diff options
Diffstat (limited to 'drivers/acpi/osl.c')
-rw-r--r-- | drivers/acpi/osl.c | 96 |
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 | ||
1112 | static acpi_status __acpi_os_execute(acpi_execute_type type, | 1108 | acpi_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 | } |
1165 | EXPORT_SYMBOL(acpi_os_execute); | ||
1178 | 1166 | ||
1179 | acpi_status acpi_os_execute(acpi_execute_type type, | 1167 | void 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 | } |
1184 | EXPORT_SYMBOL(acpi_os_execute); | ||
1185 | 1172 | ||
1186 | acpi_status acpi_os_hotplug_execute(acpi_osd_exec_callback function, | 1173 | struct acpi_hp_work { |
1187 | void *context) | 1174 | struct work_struct work; |
1175 | acpi_hp_callback func; | ||
1176 | void *data; | ||
1177 | u32 src; | ||
1178 | }; | ||
1179 | |||
1180 | static 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 | } |
1191 | EXPORT_SYMBOL(acpi_os_hotplug_execute); | ||
1192 | 1188 | ||
1193 | void acpi_os_wait_events_complete(void) | 1189 | acpi_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 | ||
1199 | EXPORT_SYMBOL(acpi_os_wait_events_complete); | ||
1200 | 1218 | ||
1201 | acpi_status | 1219 | acpi_status |
1202 | acpi_os_create_semaphore(u32 max_units, u32 initial_units, acpi_handle * handle) | 1220 | acpi_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 | |||
1850 | void 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 | } | ||
1869 | EXPORT_SYMBOL_GPL(alloc_acpi_hp_work); | ||