aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci
diff options
context:
space:
mode:
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>2013-11-06 19:45:40 -0500
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2013-11-07 13:28:48 -0500
commit7b98118aaa5d75644c48f41fc5d0cc181e478383 (patch)
tree9ab1e04ce0ee5ce816d744e50db1a3e2ba607575 /drivers/pci
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/pci')
-rw-r--r--drivers/pci/hotplug/acpiphp_glue.c18
1 files changed, 7 insertions, 11 deletions
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c
index 0b7d23b4ad95..5246ba297470 100644
--- a/drivers/pci/hotplug/acpiphp_glue.c
+++ b/drivers/pci/hotplug/acpiphp_glue.c
@@ -875,21 +875,17 @@ static void hotplug_event(acpi_handle handle, u32 type, void *data)
875 put_bridge(bridge); 875 put_bridge(bridge);
876} 876}
877 877
878static void hotplug_event_work(struct work_struct *work) 878static void hotplug_event_work(void *data, u32 type)
879{ 879{
880 struct acpiphp_context *context; 880 struct acpiphp_context *context = data;
881 struct acpi_hp_work *hp_work; 881 acpi_handle handle = context->handle;
882 882
883 hp_work = container_of(work, struct acpi_hp_work, work);
884 context = hp_work->context;
885 acpi_scan_lock_acquire(); 883 acpi_scan_lock_acquire();
886 884
887 hotplug_event(hp_work->handle, hp_work->type, context); 885 hotplug_event(handle, type, context);
888 886
889 acpi_scan_lock_release(); 887 acpi_scan_lock_release();
890 acpi_evaluate_hotplug_ost(hp_work->handle, hp_work->type, 888 acpi_evaluate_hotplug_ost(handle, type, ACPI_OST_SC_SUCCESS, NULL);
891 ACPI_OST_SC_SUCCESS, NULL);
892 kfree(hp_work); /* allocated in handle_hotplug_event() */
893 put_bridge(context->func.parent); 889 put_bridge(context->func.parent);
894} 890}
895 891
@@ -940,10 +936,10 @@ static void handle_hotplug_event(acpi_handle handle, u32 type, void *data)
940 936
941 mutex_lock(&acpiphp_context_lock); 937 mutex_lock(&acpiphp_context_lock);
942 context = acpiphp_get_context(handle); 938 context = acpiphp_get_context(handle);
943 if (context) { 939 if (context && !WARN_ON(context->handle != handle)) {
944 get_bridge(context->func.parent); 940 get_bridge(context->func.parent);
945 acpiphp_put_context(context); 941 acpiphp_put_context(context);
946 alloc_acpi_hp_work(handle, type, context, hotplug_event_work); 942 acpi_hotplug_execute(hotplug_event_work, context, type);
947 mutex_unlock(&acpiphp_context_lock); 943 mutex_unlock(&acpiphp_context_lock);
948 return; 944 return;
949 } 945 }