Commit eec15edb authored by Zhang Rui's avatar Zhang Rui Committed by Rafael J. Wysocki

ACPI / PNP: use device ID list for PNPACPI device enumeration

ACPI can be used to enumerate PNP devices, but the code does not
handle this in the right way currently.  Namely, if an ACPI device
object
 1. Has a _CRS method,
 2. Has an identification of
    "three capital characters followed by four hex digits",
 3. Is not in the excluded IDs list,
it will be enumerated to PNP bus (that is, a PNP device object will
be create for it).  This means that, actually, the PNP bus type is
used as the default bus type for enumerating _HID devices in ACPI.

However, more and more _HID devices need to be enumerated to the
platform bus instead (that is, platform device objects need to be
created for them).  As a result, the device ID list in acpi_platform.c
is used to enforce creating platform device objects rather than PNP
device objects for matching devices.  That list has been continuously
growing recently, unfortunately, and it is pretty much guaranteed to
grow even more in the future.

To address that problem it is better to enumerate _HID devices
as platform devices by default.  To this end, change the way of
enumerating PNP devices by adding a PNP ACPI scan handler that
will use a device ID list to create PNP devices for the ACPI
device objects whose device IDs are present in that list.

The initial device ID list in the PNP ACPI scan handler contains
all of the pnp_device_id strings from all the existing PNP drivers,
so this change should be transparent to the PNP core and all of the
PNP drivers.  Still, in the future it should be possible to reduce
its size by converting PNP drivers that need not be PNP for any
technical reasons into platform drivers.
Signed-off-by: default avatarZhang Rui <rui.zhang@intel.com>
[rjw: Rewrote the changelog, modified the PNP ACPI scan handler code]
Signed-off-by: default avatarRafael J. Wysocki <rafael.j.wysocki@intel.com>
Reviewed-by: default avatarMika Westerberg <mika.westerberg@linux.intel.com>
parent aca0a4eb
...@@ -41,6 +41,7 @@ acpi-$(CONFIG_ACPI_DOCK) += dock.o ...@@ -41,6 +41,7 @@ acpi-$(CONFIG_ACPI_DOCK) += dock.o
acpi-y += pci_root.o pci_link.o pci_irq.o acpi-y += pci_root.o pci_link.o pci_irq.o
acpi-$(CONFIG_X86_INTEL_LPSS) += acpi_lpss.o acpi-$(CONFIG_X86_INTEL_LPSS) += acpi_lpss.o
acpi-y += acpi_platform.o acpi-y += acpi_platform.o
acpi-y += acpi_pnp.o
acpi-y += power.o acpi-y += power.o
acpi-y += event.o acpi-y += event.o
acpi-y += sysfs.o acpi-y += sysfs.o
......
...@@ -68,7 +68,7 @@ static int acpi_install_cmos_rtc_space_handler(struct acpi_device *adev, ...@@ -68,7 +68,7 @@ static int acpi_install_cmos_rtc_space_handler(struct acpi_device *adev,
return -ENODEV; return -ENODEV;
} }
return 0; return 1;
} }
static void acpi_remove_cmos_rtc_space_handler(struct acpi_device *adev) static void acpi_remove_cmos_rtc_space_handler(struct acpi_device *adev)
......
This diff is collapsed.
...@@ -30,6 +30,7 @@ void acpi_pci_root_init(void); ...@@ -30,6 +30,7 @@ void acpi_pci_root_init(void);
void acpi_pci_link_init(void); void acpi_pci_link_init(void);
void acpi_processor_init(void); void acpi_processor_init(void);
void acpi_platform_init(void); void acpi_platform_init(void);
void acpi_pnp_init(void);
int acpi_sysfs_init(void); int acpi_sysfs_init(void);
#ifdef CONFIG_ACPI_CONTAINER #ifdef CONFIG_ACPI_CONTAINER
void acpi_container_init(void); void acpi_container_init(void);
......
...@@ -2253,6 +2253,7 @@ int __init acpi_scan_init(void) ...@@ -2253,6 +2253,7 @@ int __init acpi_scan_init(void)
acpi_cmos_rtc_init(); acpi_cmos_rtc_init();
acpi_container_init(); acpi_container_init();
acpi_memory_hotplug_init(); acpi_memory_hotplug_init();
acpi_pnp_init();
mutex_lock(&acpi_scan_lock); mutex_lock(&acpi_scan_lock);
/* /*
......
...@@ -30,26 +30,6 @@ ...@@ -30,26 +30,6 @@
static int num; static int num;
/* We need only to blacklist devices that have already an acpi driver that
* can't use pnp layer. We don't need to blacklist device that are directly
* used by the kernel (PCI root, ...), as it is harmless and there were
* already present in pnpbios. But there is an exception for devices that
* have irqs (PIC, Timer) because we call acpi_register_gsi.
* Finally, only devices that have a CRS method need to be in this list.
*/
static struct acpi_device_id excluded_id_list[] __initdata = {
{"PNP0C09", 0}, /* EC */
{"PNP0C0F", 0}, /* Link device */
{"PNP0000", 0}, /* PIC */
{"PNP0100", 0}, /* Timer */
{"", 0},
};
static inline int __init is_exclusive_device(struct acpi_device *dev)
{
return (!acpi_match_device_ids(dev, excluded_id_list));
}
/* /*
* Compatible Device IDs * Compatible Device IDs
*/ */
...@@ -266,7 +246,7 @@ static int __init pnpacpi_add_device(struct acpi_device *device) ...@@ -266,7 +246,7 @@ static int __init pnpacpi_add_device(struct acpi_device *device)
if (!pnpid) if (!pnpid)
return 0; return 0;
if (is_exclusive_device(device) || !device->status.present) if (!device->status.present)
return 0; return 0;
dev = pnp_alloc_dev(&pnpacpi_protocol, num, pnpid); dev = pnp_alloc_dev(&pnpacpi_protocol, num, pnpid);
...@@ -326,10 +306,10 @@ static acpi_status __init pnpacpi_add_device_handler(acpi_handle handle, ...@@ -326,10 +306,10 @@ static acpi_status __init pnpacpi_add_device_handler(acpi_handle handle,
{ {
struct acpi_device *device; struct acpi_device *device;
if (!acpi_bus_get_device(handle, &device)) if (acpi_bus_get_device(handle, &device))
pnpacpi_add_device(device);
else
return AE_CTRL_DEPTH; return AE_CTRL_DEPTH;
if (acpi_is_pnp_device(device))
pnpacpi_add_device(device);
return AE_OK; return AE_OK;
} }
......
...@@ -184,6 +184,8 @@ extern int ec_transaction(u8 command, ...@@ -184,6 +184,8 @@ extern int ec_transaction(u8 command,
u8 *rdata, unsigned rdata_len); u8 *rdata, unsigned rdata_len);
extern acpi_handle ec_get_handle(void); extern acpi_handle ec_get_handle(void);
extern bool acpi_is_pnp_device(struct acpi_device *);
#if defined(CONFIG_ACPI_WMI) || defined(CONFIG_ACPI_WMI_MODULE) #if defined(CONFIG_ACPI_WMI) || defined(CONFIG_ACPI_WMI_MODULE)
typedef void (*wmi_notify_handler) (u32 value, void *context); typedef void (*wmi_notify_handler) (u32 value, void *context);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment