summaryrefslogtreecommitdiffstats
path: root/drivers/acpi/scan.c
diff options
context:
space:
mode:
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>2013-11-07 01:45:40 +0100
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2013-11-07 19:28:48 +0100
commit7b98118aaa5d75644c48f41fc5d0cc181e478383 (patch)
tree9ab1e04ce0ee5ce816d744e50db1a3e2ba607575 /drivers/acpi/scan.c
parent176a88d79d6b5aebabaff16734e8b3107efcaaad (diff)
ACPI / hotplug: Consolidate deferred execution of ACPI hotplug routines
There are two different interfaces for queuing up work items on the ACPI hotplug workqueue, alloc_acpi_hp_work() used by PCI and PCI host bridge hotplug code and acpi_os_hotplug_execute() used by the common ACPI hotplug code and docking stations. They both are somewhat cumbersome to use and work slightly differently. The users of alloc_acpi_hp_work() have to submit a work function that will extract the necessary data items from a struct acpi_hp_work object allocated by alloc_acpi_hp_work() and then will free that object, while it would be more straightforward to simply use a work function with one more argument and let the interface take care of the execution details. The users of acpi_os_hotplug_execute() also have to deal with the fact that it takes only one argument in addition to the work function pointer, although acpi_os_execute_deferred() actually takes care of the allocation and freeing of memory, so it would have been able to pass more arguments to the work function if it hadn't been constrained by the connection with acpi_os_execute(). Moreover, while alloc_acpi_hp_work() makes GFP_KERNEL memory allocations, which is correct, because hotplug work items are always queued up from process context, acpi_os_hotplug_execute() uses GFP_ATOMIC, as that is needed by acpi_os_execute(). Also, acpi_os_execute_deferred() queued up by it waits for the ACPI event workqueues to flush before executing the work function, whereas alloc_acpi_hp_work() can't do anything similar. That leads to somewhat arbitrary differences in behavior between various ACPI hotplug code paths and has to be straightened up. For this reason, replace both alloc_acpi_hp_work() and acpi_os_hotplug_execute() with a single interface, acpi_hotplug_execute(), combining their behavior and being more friendly to its users than any of the two. Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Tested-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Diffstat (limited to 'drivers/acpi/scan.c')
-rw-r--r--drivers/acpi/scan.c43
1 files changed, 8 insertions, 35 deletions
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index 5cd7f8c5666a..276cde70a514 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -285,8 +285,9 @@ static int acpi_scan_hot_remove(struct acpi_device *device)
return 0;
}
-void acpi_bus_device_eject(struct acpi_device *device, u32 ost_src)
+void acpi_bus_device_eject(void *data, u32 ost_src)
{
+ struct acpi_device *device = data;
acpi_handle handle = device->handle;
struct acpi_scan_handler *handler;
u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE;
@@ -327,8 +328,9 @@ void acpi_bus_device_eject(struct acpi_device *device, u32 ost_src)
goto out;
}
-static void acpi_scan_bus_device_check(acpi_handle handle, u32 ost_source)
+static void acpi_scan_bus_device_check(void *data, u32 ost_source)
{
+ acpi_handle handle = data;
struct acpi_device *device = NULL;
u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE;
int error;
@@ -363,18 +365,6 @@ static void acpi_scan_bus_device_check(acpi_handle handle, u32 ost_source)
unlock_device_hotplug();
}
-static void acpi_scan_bus_check(void *context)
-{
- acpi_scan_bus_device_check((acpi_handle)context,
- ACPI_NOTIFY_BUS_CHECK);
-}
-
-static void acpi_scan_device_check(void *context)
-{
- acpi_scan_bus_device_check((acpi_handle)context,
- ACPI_NOTIFY_DEVICE_CHECK);
-}
-
static void acpi_hotplug_unsupported(acpi_handle handle, u32 type)
{
u32 ost_status;
@@ -403,18 +393,8 @@ static void acpi_hotplug_unsupported(acpi_handle handle, u32 type)
acpi_evaluate_hotplug_ost(handle, type, ost_status, NULL);
}
-/**
- * acpi_bus_hot_remove_device: Hot-remove a device and its children.
- * @context: Address of the ACPI device object to hot-remove.
- */
-static void acpi_bus_hot_remove_device(void *context)
-{
- acpi_bus_device_eject(context, ACPI_NOTIFY_EJECT_REQUEST);
-}
-
static void acpi_hotplug_notify_cb(acpi_handle handle, u32 type, void *data)
{
- acpi_osd_exec_callback callback;
struct acpi_scan_handler *handler = data;
struct acpi_device *adev;
acpi_status status;
@@ -425,11 +405,9 @@ static void acpi_hotplug_notify_cb(acpi_handle handle, u32 type, void *data)
switch (type) {
case ACPI_NOTIFY_BUS_CHECK:
acpi_handle_debug(handle, "ACPI_NOTIFY_BUS_CHECK event\n");
- callback = acpi_scan_bus_check;
break;
case ACPI_NOTIFY_DEVICE_CHECK:
acpi_handle_debug(handle, "ACPI_NOTIFY_DEVICE_CHECK event\n");
- callback = acpi_scan_device_check;
break;
case ACPI_NOTIFY_EJECT_REQUEST:
acpi_handle_debug(handle, "ACPI_NOTIFY_EJECT_REQUEST event\n");
@@ -438,8 +416,7 @@ static void acpi_hotplug_notify_cb(acpi_handle handle, u32 type, void *data)
goto err_out;
get_device(&adev->dev);
- callback = acpi_bus_hot_remove_device;
- status = acpi_os_hotplug_execute(callback, adev);
+ status = acpi_hotplug_execute(acpi_bus_device_eject, adev, type);
if (ACPI_SUCCESS(status))
return;
@@ -449,7 +426,7 @@ static void acpi_hotplug_notify_cb(acpi_handle handle, u32 type, void *data)
/* non-hotplug event; possibly handled by other handler */
return;
}
- status = acpi_os_hotplug_execute(callback, handle);
+ status = acpi_hotplug_execute(acpi_scan_bus_device_check, handle, type);
if (ACPI_SUCCESS(status))
return;
@@ -484,11 +461,6 @@ static ssize_t power_state_show(struct device *dev,
static DEVICE_ATTR(power_state, 0444, power_state_show, NULL);
-static void acpi_eject_store_work(void *context)
-{
- acpi_bus_device_eject(context, ACPI_OST_EC_OSPM_EJECT);
-}
-
static ssize_t
acpi_eject_store(struct device *d, struct device_attribute *attr,
const char *buf, size_t count)
@@ -511,7 +483,8 @@ acpi_eject_store(struct device *d, struct device_attribute *attr,
acpi_evaluate_hotplug_ost(acpi_device->handle, ACPI_OST_EC_OSPM_EJECT,
ACPI_OST_SC_EJECT_IN_PROGRESS, NULL);
get_device(&acpi_device->dev);
- status = acpi_os_hotplug_execute(acpi_eject_store_work, acpi_device);
+ status = acpi_hotplug_execute(acpi_bus_device_eject, acpi_device,
+ ACPI_OST_EC_OSPM_EJECT);
if (ACPI_SUCCESS(status))
return count;