From 6b5eab54691956b27669ce726cbd8ef2d8ec1e50 Mon Sep 17 00:00:00 2001 From: Chris Bainbridge Date: Wed, 22 Apr 2015 00:25:36 +0100 Subject: ACPI / EC: fix NULL pointer dereference in acpi_ec_remove_query_handler() Use list_for_each_entry_safe for iterating because handler may be freed in the loop. BUG: unable to handle kernel NULL pointer dereference at 000000000000002c IP: [] acpi_ec_put_query_handler+0x7/0x1a Call Trace: acpi_ec_remove_query_handler+0x87/0x97 acpi_smbus_hc_remove+0x2a/0x44 [sbshc] acpi_device_remove+0x7b/0x9a __device_release_driver+0x7e/0x110 driver_detach+0xb0/0xc0 bus_remove_driver+0x54/0xe0 driver_unregister+0x2b/0x60 acpi_bus_unregister_driver+0x10/0x12 acpi_smb_hc_driver_exit+0x10/0x12 [sbshc] SyS_delete_module+0x1b8/0x210 system_call_fastpath+0x12/0x6a Signed-off-by: Chris Bainbridge Signed-off-by: Rafael J. Wysocki --- drivers/acpi/ec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index 220d6406c9e9..5e8fed448850 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -861,7 +861,7 @@ void acpi_ec_remove_query_handler(struct acpi_ec *ec, u8 query_bit) } } mutex_unlock(&ec->mutex); - list_for_each_entry(handler, &free_list, node) + list_for_each_entry_safe(handler, tmp, &free_list, node) acpi_ec_put_query_handler(handler); } EXPORT_SYMBOL_GPL(acpi_ec_remove_query_handler); -- cgit v1.2.3 From 4c533c801d1c9b5c38458a0e7516e0cf50643782 Mon Sep 17 00:00:00 2001 From: Rafael J. Wysocki Date: Sat, 18 Apr 2015 01:25:46 +0200 Subject: ACPI / scan: Annotate physical_node_lock in acpi_scan_is_offline() acpi_scan_is_offline() may be called under the physical_node_lock lock of the given device object's parent, so prevent lockdep from complaining about that by annotating that instance with SINGLE_DEPTH_NESTING. Fixes: caa73ea158de (ACPI / hotplug / driver core: Handle containers in a special way) Reported-and-tested-by: Xie XiuQi Reviewed-by: Toshi Kani Cc: 3.14+ # 3.14+ Signed-off-by: Rafael J. Wysocki --- drivers/acpi/scan.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 69bc0d888c01..8d40467d37f9 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -375,7 +375,11 @@ bool acpi_scan_is_offline(struct acpi_device *adev, bool uevent) struct acpi_device_physical_node *pn; bool offline = true; - mutex_lock(&adev->physical_node_lock); + /* + * acpi_container_offline() calls this for all of the container's + * children under the container's physical_node_lock lock. + */ + mutex_lock_nested(&adev->physical_node_lock, SINGLE_DEPTH_NESTING); list_for_each_entry(pn, &adev->physical_node_list, node) if (device_supports_offline(pn->dev) && !pn->dev->offline) { -- cgit v1.2.3 From 7d284352f9cbc032f2294024b1a6b5c06765c246 Mon Sep 17 00:00:00 2001 From: Rafael J. Wysocki Date: Fri, 24 Apr 2015 02:18:01 +0200 Subject: ACPI / scan: Add a scan handler for PRP0001 If the special PRP0001 device ID is present in the given device's list of ACPI/PNP IDs and the device has a valid "compatible" property in the _DSD, it should be enumerated using the default mechanism, unless some scan handlers match the IDs preceding PRP0001 in the device's list of ACPI/PNP IDs. In addition to that, no scan handlers matching the IDs following PRP0001 in that list should be attached to the device. To make that happen, define a scan handler that will match PRP0001 and trigger the default enumeration for the matching devices if the "compatible" property is present for them. Since that requires the check for platform_id and device->handler to be removed from acpi_default_enumeration(), move the fallback invocation of acpi_default_enumeration() to acpi_bus_attach() (after it's checked if there's a matching ACPI driver for the device), which is a better place to call it, and do the platform_id check in there too (device->handler is guaranteed to be unset at the point where the function is looking for a matching ACPI driver). Signed-off-by: Rafael J. Wysocki Acked-by: Darren Hart --- drivers/acpi/scan.c | 33 ++++++++++++++++++++++++++++----- 1 file changed, 28 insertions(+), 5 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 8d40467d37f9..03141aa4ea95 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -2392,9 +2392,6 @@ static void acpi_default_enumeration(struct acpi_device *device) struct list_head resource_list; bool is_spi_i2c_slave = false; - if (!device->pnp.type.platform_id || device->handler) - return; - /* * Do not enemerate SPI/I2C slaves as they will be enuerated by their * respective parents. @@ -2407,6 +2404,29 @@ static void acpi_default_enumeration(struct acpi_device *device) acpi_create_platform_device(device); } +static const struct acpi_device_id generic_device_ids[] = { + {"PRP0001", }, + {"", }, +}; + +static int acpi_generic_device_attach(struct acpi_device *adev, + const struct acpi_device_id *not_used) +{ + /* + * Since PRP0001 is the only ID handled here, the test below can be + * unconditional. + */ + if (adev->data.of_compatible) + acpi_default_enumeration(adev); + + return 1; +} + +static struct acpi_scan_handler generic_device_handler = { + .ids = generic_device_ids, + .attach = acpi_generic_device_attach, +}; + static int acpi_scan_attach_handler(struct acpi_device *device) { struct acpi_hardware_id *hwid; @@ -2432,8 +2452,6 @@ static int acpi_scan_attach_handler(struct acpi_device *device) break; } } - if (!ret) - acpi_default_enumeration(device); return ret; } @@ -2475,6 +2493,9 @@ static void acpi_bus_attach(struct acpi_device *device) ret = device_attach(&device->dev); if (ret < 0) return; + + if (!ret && device->pnp.type.platform_id) + acpi_default_enumeration(device); } device->flags.visited = true; @@ -2633,6 +2654,8 @@ int __init acpi_scan_init(void) acpi_pnp_init(); acpi_int340x_thermal_init(); + acpi_scan_add_handler(&generic_device_handler); + mutex_lock(&acpi_scan_lock); /* * Enumerate devices in the ACPI namespace. -- cgit v1.2.3