summaryrefslogtreecommitdiffstats
path: root/drivers/acpi/osl.c
diff options
context:
space:
mode:
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>2013-11-07 13:31:15 -0500
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2013-11-07 13:31:15 -0500
commit63ff4d0765a4e30afa659edbf09006987fc62499 (patch)
treefb9f64c4510ea08e076c715c87dd61b3d79f99d6 /drivers/acpi/osl.c
parent679d9980f9914136f6e488d976eb412de156c542 (diff)
parent7b98118aaa5d75644c48f41fc5d0cc181e478383 (diff)
Merge branch 'acpi-hotplug'
* acpi-hotplug: ACPI / hotplug: Consolidate deferred execution of ACPI hotplug routines ACPI / hotplug: Do not execute "insert in progress" _OST ACPI / hotplug: Carry out PCI root eject directly ACPI / hotplug: Merge device hot-removal routines ACPI / hotplug: Make acpi_bus_hot_remove_device() internal ACPI / hotplug: Simplify device ejection routines ACPI / hotplug: Fix handle_root_bridge_removal() ACPI / hotplug: Refuse to hot-remove all objects with disabled hotplug ACPI / scan: Start matching drivers after trying scan handlers ACPI: Remove acpi_pci_slot_init() headers from internal.h Conflicts: include/acpi/acpiosxf.h (with the 'acpica' branch)
Diffstat (limited to 'drivers/acpi/osl.c')
-rw-r--r--drivers/acpi/osl.c96
1 files changed, 46 insertions, 50 deletions
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
index a0c09adf7e7d..54a20ff4b864 100644
--- a/drivers/acpi/osl.c
+++ b/drivers/acpi/osl.c
@@ -61,7 +61,6 @@ struct acpi_os_dpc {
61 acpi_osd_exec_callback function; 61 acpi_osd_exec_callback function;
62 void *context; 62 void *context;
63 struct work_struct work; 63 struct work_struct work;
64 int wait;
65}; 64};
66 65
67#ifdef CONFIG_ACPI_CUSTOM_DSDT 66#ifdef CONFIG_ACPI_CUSTOM_DSDT
@@ -1087,9 +1086,6 @@ static void acpi_os_execute_deferred(struct work_struct *work)
1087{ 1086{
1088 struct acpi_os_dpc *dpc = container_of(work, struct acpi_os_dpc, work); 1087 struct acpi_os_dpc *dpc = container_of(work, struct acpi_os_dpc, work);
1089 1088
1090 if (dpc->wait)
1091 acpi_os_wait_events_complete();
1092
1093 dpc->function(dpc->context); 1089 dpc->function(dpc->context);
1094 kfree(dpc); 1090 kfree(dpc);
1095} 1091}
@@ -1109,8 +1105,8 @@ static void acpi_os_execute_deferred(struct work_struct *work)
1109 * 1105 *
1110 ******************************************************************************/ 1106 ******************************************************************************/
1111 1107
1112static acpi_status __acpi_os_execute(acpi_execute_type type, 1108acpi_status acpi_os_execute(acpi_execute_type type,
1113 acpi_osd_exec_callback function, void *context, int hp) 1109 acpi_osd_exec_callback function, void *context)
1114{ 1110{
1115 acpi_status status = AE_OK; 1111 acpi_status status = AE_OK;
1116 struct acpi_os_dpc *dpc; 1112 struct acpi_os_dpc *dpc;
@@ -1137,20 +1133,11 @@ static acpi_status __acpi_os_execute(acpi_execute_type type,
1137 dpc->context = context; 1133 dpc->context = context;
1138 1134
1139 /* 1135 /*
1140 * We can't run hotplug code in keventd_wq/kacpid_wq/kacpid_notify_wq
1141 * because the hotplug code may call driver .remove() functions,
1142 * which invoke flush_scheduled_work/acpi_os_wait_events_complete
1143 * to flush these workqueues.
1144 *
1145 * To prevent lockdep from complaining unnecessarily, make sure that 1136 * To prevent lockdep from complaining unnecessarily, make sure that
1146 * there is a different static lockdep key for each workqueue by using 1137 * there is a different static lockdep key for each workqueue by using
1147 * INIT_WORK() for each of them separately. 1138 * INIT_WORK() for each of them separately.
1148 */ 1139 */
1149 if (hp) { 1140 if (type == OSL_NOTIFY_HANDLER) {
1150 queue = kacpi_hotplug_wq;
1151 dpc->wait = 1;
1152 INIT_WORK(&dpc->work, acpi_os_execute_deferred);
1153 } else if (type == OSL_NOTIFY_HANDLER) {
1154 queue = kacpi_notify_wq; 1141 queue = kacpi_notify_wq;
1155 INIT_WORK(&dpc->work, acpi_os_execute_deferred); 1142 INIT_WORK(&dpc->work, acpi_os_execute_deferred);
1156 } else { 1143 } else {
@@ -1175,28 +1162,59 @@ static acpi_status __acpi_os_execute(acpi_execute_type type,
1175 } 1162 }
1176 return status; 1163 return status;
1177} 1164}
1165EXPORT_SYMBOL(acpi_os_execute);
1178 1166
1179acpi_status acpi_os_execute(acpi_execute_type type, 1167void acpi_os_wait_events_complete(void)
1180 acpi_osd_exec_callback function, void *context)
1181{ 1168{
1182 return __acpi_os_execute(type, function, context, 0); 1169 flush_workqueue(kacpid_wq);
1170 flush_workqueue(kacpi_notify_wq);
1183} 1171}
1184EXPORT_SYMBOL(acpi_os_execute);
1185 1172
1186acpi_status acpi_os_hotplug_execute(acpi_osd_exec_callback function, 1173struct acpi_hp_work {
1187 void *context) 1174 struct work_struct work;
1175 acpi_hp_callback func;
1176 void *data;
1177 u32 src;
1178};
1179
1180static void acpi_hotplug_work_fn(struct work_struct *work)
1188{ 1181{
1189 return __acpi_os_execute(0, function, context, 1); 1182 struct acpi_hp_work *hpw = container_of(work, struct acpi_hp_work, work);
1183
1184 acpi_os_wait_events_complete();
1185 hpw->func(hpw->data, hpw->src);
1186 kfree(hpw);
1190} 1187}
1191EXPORT_SYMBOL(acpi_os_hotplug_execute);
1192 1188
1193void acpi_os_wait_events_complete(void) 1189acpi_status acpi_hotplug_execute(acpi_hp_callback func, void *data, u32 src)
1194{ 1190{
1195 flush_workqueue(kacpid_wq); 1191 struct acpi_hp_work *hpw;
1196 flush_workqueue(kacpi_notify_wq); 1192
1193 ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
1194 "Scheduling function [%p(%p, %u)] for deferred execution.\n",
1195 func, data, src));
1196
1197 hpw = kmalloc(sizeof(*hpw), GFP_KERNEL);
1198 if (!hpw)
1199 return AE_NO_MEMORY;
1200
1201 INIT_WORK(&hpw->work, acpi_hotplug_work_fn);
1202 hpw->func = func;
1203 hpw->data = data;
1204 hpw->src = src;
1205 /*
1206 * We can't run hotplug code in kacpid_wq/kacpid_notify_wq etc., because
1207 * the hotplug code may call driver .remove() functions, which may
1208 * invoke flush_scheduled_work()/acpi_os_wait_events_complete() to flush
1209 * these workqueues.
1210 */
1211 if (!queue_work(kacpi_hotplug_wq, &hpw->work)) {
1212 kfree(hpw);
1213 return AE_ERROR;
1214 }
1215 return AE_OK;
1197} 1216}
1198 1217
1199EXPORT_SYMBOL(acpi_os_wait_events_complete);
1200 1218
1201acpi_status 1219acpi_status
1202acpi_os_create_semaphore(u32 max_units, u32 initial_units, acpi_handle * handle) 1220acpi_os_create_semaphore(u32 max_units, u32 initial_units, acpi_handle * handle)
@@ -1845,25 +1863,3 @@ void acpi_os_set_prepare_extended_sleep(int (*func)(u8 sleep_state,
1845{ 1863{
1846 __acpi_os_prepare_extended_sleep = func; 1864 __acpi_os_prepare_extended_sleep = func;
1847} 1865}
1848
1849
1850void alloc_acpi_hp_work(acpi_handle handle, u32 type, void *context,
1851 void (*func)(struct work_struct *work))
1852{
1853 struct acpi_hp_work *hp_work;
1854 int ret;
1855
1856 hp_work = kmalloc(sizeof(*hp_work), GFP_KERNEL);
1857 if (!hp_work)
1858 return;
1859
1860 hp_work->handle = handle;
1861 hp_work->type = type;
1862 hp_work->context = context;
1863
1864 INIT_WORK(&hp_work->work, func);
1865 ret = queue_work(kacpi_hotplug_wq, &hp_work->work);
1866 if (!ret)
1867 kfree(hp_work);
1868}
1869EXPORT_SYMBOL_GPL(alloc_acpi_hp_work);