diff options
| -rw-r--r-- | drivers/acpi/dock.c | 25 | ||||
| -rw-r--r-- | drivers/acpi/internal.h | 2 | ||||
| -rw-r--r-- | drivers/acpi/osl.c | 96 | ||||
| -rw-r--r-- | drivers/acpi/pci_root.c | 14 | ||||
| -rw-r--r-- | drivers/acpi/scan.c | 43 | ||||
| -rw-r--r-- | drivers/pci/hotplug/acpiphp_glue.c | 18 | ||||
| -rw-r--r-- | include/acpi/acpi_bus.h | 12 | ||||
| -rw-r--r-- | include/acpi/acpiosxf.h | 3 |
8 files changed, 71 insertions, 142 deletions
diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c index 05ea4be01a83..eab7d1145bfa 100644 --- a/drivers/acpi/dock.c +++ b/drivers/acpi/dock.c | |||
| @@ -671,39 +671,20 @@ static void dock_notify(struct dock_station *ds, u32 event) | |||
| 671 | } | 671 | } |
| 672 | } | 672 | } |
| 673 | 673 | ||
| 674 | struct dock_data { | 674 | static void acpi_dock_deferred_cb(void *data, u32 event) |
| 675 | struct dock_station *ds; | ||
| 676 | u32 event; | ||
| 677 | }; | ||
| 678 | |||
| 679 | static void acpi_dock_deferred_cb(void *context) | ||
| 680 | { | 675 | { |
| 681 | struct dock_data *data = context; | ||
| 682 | |||
| 683 | acpi_scan_lock_acquire(); | 676 | acpi_scan_lock_acquire(); |
| 684 | dock_notify(data->ds, data->event); | 677 | dock_notify(data, event); |
| 685 | acpi_scan_lock_release(); | 678 | acpi_scan_lock_release(); |
| 686 | kfree(data); | ||
| 687 | } | 679 | } |
| 688 | 680 | ||
| 689 | static void dock_notify_handler(acpi_handle handle, u32 event, void *data) | 681 | static void dock_notify_handler(acpi_handle handle, u32 event, void *data) |
| 690 | { | 682 | { |
| 691 | struct dock_data *dd; | ||
| 692 | |||
| 693 | if (event != ACPI_NOTIFY_BUS_CHECK && event != ACPI_NOTIFY_DEVICE_CHECK | 683 | if (event != ACPI_NOTIFY_BUS_CHECK && event != ACPI_NOTIFY_DEVICE_CHECK |
| 694 | && event != ACPI_NOTIFY_EJECT_REQUEST) | 684 | && event != ACPI_NOTIFY_EJECT_REQUEST) |
| 695 | return; | 685 | return; |
| 696 | 686 | ||
| 697 | dd = kmalloc(sizeof(*dd), GFP_KERNEL); | 687 | acpi_hotplug_execute(acpi_dock_deferred_cb, data, event); |
| 698 | if (dd) { | ||
| 699 | acpi_status status; | ||
| 700 | |||
| 701 | dd->ds = data; | ||
| 702 | dd->event = event; | ||
| 703 | status = acpi_os_hotplug_execute(acpi_dock_deferred_cb, dd); | ||
| 704 | if (ACPI_FAILURE(status)) | ||
| 705 | kfree(dd); | ||
| 706 | } | ||
| 707 | } | 688 | } |
| 708 | 689 | ||
| 709 | /** | 690 | /** |
diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index 80cd1a10c4c3..c6db680c826c 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h | |||
| @@ -87,7 +87,7 @@ void acpi_device_add_finalize(struct acpi_device *device); | |||
| 87 | void acpi_free_pnp_ids(struct acpi_device_pnp *pnp); | 87 | void acpi_free_pnp_ids(struct acpi_device_pnp *pnp); |
| 88 | int acpi_bind_one(struct device *dev, acpi_handle handle); | 88 | int acpi_bind_one(struct device *dev, acpi_handle handle); |
| 89 | int acpi_unbind_one(struct device *dev); | 89 | int acpi_unbind_one(struct device *dev); |
| 90 | void acpi_bus_device_eject(struct acpi_device *device, u32 ost_src); | 90 | void acpi_bus_device_eject(void *data, u32 ost_src); |
| 91 | 91 | ||
| 92 | /* -------------------------------------------------------------------------- | 92 | /* -------------------------------------------------------------------------- |
| 93 | Power Resource | 93 | Power Resource |
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index e5f416c7f66e..cfc3e260a688 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 |
| @@ -1067,9 +1066,6 @@ static void acpi_os_execute_deferred(struct work_struct *work) | |||
| 1067 | { | 1066 | { |
| 1068 | struct acpi_os_dpc *dpc = container_of(work, struct acpi_os_dpc, work); | 1067 | struct acpi_os_dpc *dpc = container_of(work, struct acpi_os_dpc, work); |
| 1069 | 1068 | ||
| 1070 | if (dpc->wait) | ||
| 1071 | acpi_os_wait_events_complete(); | ||
| 1072 | |||
| 1073 | dpc->function(dpc->context); | 1069 | dpc->function(dpc->context); |
| 1074 | kfree(dpc); | 1070 | kfree(dpc); |
| 1075 | } | 1071 | } |
| @@ -1089,8 +1085,8 @@ static void acpi_os_execute_deferred(struct work_struct *work) | |||
| 1089 | * | 1085 | * |
| 1090 | ******************************************************************************/ | 1086 | ******************************************************************************/ |
| 1091 | 1087 | ||
| 1092 | static acpi_status __acpi_os_execute(acpi_execute_type type, | 1088 | acpi_status acpi_os_execute(acpi_execute_type type, |
| 1093 | acpi_osd_exec_callback function, void *context, int hp) | 1089 | acpi_osd_exec_callback function, void *context) |
| 1094 | { | 1090 | { |
| 1095 | acpi_status status = AE_OK; | 1091 | acpi_status status = AE_OK; |
| 1096 | struct acpi_os_dpc *dpc; | 1092 | struct acpi_os_dpc *dpc; |
| @@ -1117,20 +1113,11 @@ static acpi_status __acpi_os_execute(acpi_execute_type type, | |||
| 1117 | dpc->context = context; | 1113 | dpc->context = context; |
| 1118 | 1114 | ||
| 1119 | /* | 1115 | /* |
| 1120 | * We can't run hotplug code in keventd_wq/kacpid_wq/kacpid_notify_wq | ||
| 1121 | * because the hotplug code may call driver .remove() functions, | ||
| 1122 | * which invoke flush_scheduled_work/acpi_os_wait_events_complete | ||
| 1123 | * to flush these workqueues. | ||
| 1124 | * | ||
| 1125 | * To prevent lockdep from complaining unnecessarily, make sure that | 1116 | * To prevent lockdep from complaining unnecessarily, make sure that |
| 1126 | * there is a different static lockdep key for each workqueue by using | 1117 | * there is a different static lockdep key for each workqueue by using |
| 1127 | * INIT_WORK() for each of them separately. | 1118 | * INIT_WORK() for each of them separately. |
| 1128 | */ | 1119 | */ |
| 1129 | if (hp) { | 1120 | if (type == OSL_NOTIFY_HANDLER) { |
| 1130 | queue = kacpi_hotplug_wq; | ||
| 1131 | dpc->wait = 1; | ||
| 1132 | INIT_WORK(&dpc->work, acpi_os_execute_deferred); | ||
| 1133 | } else if (type == OSL_NOTIFY_HANDLER) { | ||
| 1134 | queue = kacpi_notify_wq; | 1121 | queue = kacpi_notify_wq; |
| 1135 | INIT_WORK(&dpc->work, acpi_os_execute_deferred); | 1122 | INIT_WORK(&dpc->work, acpi_os_execute_deferred); |
| 1136 | } else { | 1123 | } else { |
| @@ -1155,28 +1142,59 @@ static acpi_status __acpi_os_execute(acpi_execute_type type, | |||
| 1155 | } | 1142 | } |
| 1156 | return status; | 1143 | return status; |
| 1157 | } | 1144 | } |
| 1145 | EXPORT_SYMBOL(acpi_os_execute); | ||
| 1158 | 1146 | ||
| 1159 | acpi_status acpi_os_execute(acpi_execute_type type, | 1147 | void acpi_os_wait_events_complete(void) |
| 1160 | acpi_osd_exec_callback function, void *context) | ||
| 1161 | { | 1148 | { |
| 1162 | return __acpi_os_execute(type, function, context, 0); | 1149 | flush_workqueue(kacpid_wq); |
| 1150 | flush_workqueue(kacpi_notify_wq); | ||
| 1163 | } | 1151 | } |
| 1164 | EXPORT_SYMBOL(acpi_os_execute); | ||
| 1165 | 1152 | ||
| 1166 | acpi_status acpi_os_hotplug_execute(acpi_osd_exec_callback function, | 1153 | struct acpi_hp_work { |
| 1167 | void *context) | 1154 | struct work_struct work; |
| 1155 | acpi_hp_callback func; | ||
| 1156 | void *data; | ||
| 1157 | u32 src; | ||
| 1158 | }; | ||
| 1159 | |||
| 1160 | static void acpi_hotplug_work_fn(struct work_struct *work) | ||
| 1168 | { | 1161 | { |
| 1169 | return __acpi_os_execute(0, function, context, 1); | 1162 | struct acpi_hp_work *hpw = container_of(work, struct acpi_hp_work, work); |
| 1163 | |||
| 1164 | acpi_os_wait_events_complete(); | ||
| 1165 | hpw->func(hpw->data, hpw->src); | ||
| 1166 | kfree(hpw); | ||
| 1170 | } | 1167 | } |
| 1171 | EXPORT_SYMBOL(acpi_os_hotplug_execute); | ||
| 1172 | 1168 | ||
| 1173 | void acpi_os_wait_events_complete(void) | 1169 | acpi_status acpi_hotplug_execute(acpi_hp_callback func, void *data, u32 src) |
| 1174 | { | 1170 | { |
| 1175 | flush_workqueue(kacpid_wq); | 1171 | struct acpi_hp_work *hpw; |
| 1176 | flush_workqueue(kacpi_notify_wq); | 1172 | |
| 1173 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, | ||
| 1174 | "Scheduling function [%p(%p, %u)] for deferred execution.\n", | ||
| 1175 | func, data, src)); | ||
| 1176 | |||
| 1177 | hpw = kmalloc(sizeof(*hpw), GFP_KERNEL); | ||
| 1178 | if (!hpw) | ||
| 1179 | return AE_NO_MEMORY; | ||
| 1180 | |||
| 1181 | INIT_WORK(&hpw->work, acpi_hotplug_work_fn); | ||
| 1182 | hpw->func = func; | ||
| 1183 | hpw->data = data; | ||
| 1184 | hpw->src = src; | ||
| 1185 | /* | ||
| 1186 | * We can't run hotplug code in kacpid_wq/kacpid_notify_wq etc., because | ||
| 1187 | * the hotplug code may call driver .remove() functions, which may | ||
| 1188 | * invoke flush_scheduled_work()/acpi_os_wait_events_complete() to flush | ||
| 1189 | * these workqueues. | ||
| 1190 | */ | ||
| 1191 | if (!queue_work(kacpi_hotplug_wq, &hpw->work)) { | ||
