diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/acpi/dock.c | 25 | ||||
-rw-r--r-- | drivers/acpi/internal.h | 6 | ||||
-rw-r--r-- | drivers/acpi/osl.c | 96 | ||||
-rw-r--r-- | drivers/acpi/pci_root.c | 51 | ||||
-rw-r--r-- | drivers/acpi/scan.c | 176 | ||||
-rw-r--r-- | drivers/pci/hotplug/acpiphp_glue.c | 18 |
6 files changed, 144 insertions, 228 deletions
diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c index ca86c1ce7c8a..dcd73ccb514c 100644 --- a/drivers/acpi/dock.c +++ b/drivers/acpi/dock.c | |||
@@ -669,39 +669,20 @@ static void dock_notify(struct dock_station *ds, u32 event) | |||
669 | } | 669 | } |
670 | } | 670 | } |
671 | 671 | ||
672 | struct dock_data { | 672 | static void acpi_dock_deferred_cb(void *data, u32 event) |
673 | struct dock_station *ds; | ||
674 | u32 event; | ||
675 | }; | ||
676 | |||
677 | static void acpi_dock_deferred_cb(void *context) | ||
678 | { | 673 | { |
679 | struct dock_data *data = context; | ||
680 | |||
681 | acpi_scan_lock_acquire(); | 674 | acpi_scan_lock_acquire(); |
682 | dock_notify(data->ds, data->event); | 675 | dock_notify(data, event); |
683 | acpi_scan_lock_release(); | 676 | acpi_scan_lock_release(); |
684 | kfree(data); | ||
685 | } | 677 | } |
686 | 678 | ||
687 | static void dock_notify_handler(acpi_handle handle, u32 event, void *data) | 679 | static void dock_notify_handler(acpi_handle handle, u32 event, void *data) |
688 | { | 680 | { |
689 | struct dock_data *dd; | ||
690 | |||
691 | if (event != ACPI_NOTIFY_BUS_CHECK && event != ACPI_NOTIFY_DEVICE_CHECK | 681 | if (event != ACPI_NOTIFY_BUS_CHECK && event != ACPI_NOTIFY_DEVICE_CHECK |
692 | && event != ACPI_NOTIFY_EJECT_REQUEST) | 682 | && event != ACPI_NOTIFY_EJECT_REQUEST) |
693 | return; | 683 | return; |
694 | 684 | ||
695 | dd = kmalloc(sizeof(*dd), GFP_KERNEL); | 685 | acpi_hotplug_execute(acpi_dock_deferred_cb, data, event); |
696 | if (dd) { | ||
697 | acpi_status status; | ||
698 | |||
699 | dd->ds = data; | ||
700 | dd->event = event; | ||
701 | status = acpi_os_hotplug_execute(acpi_dock_deferred_cb, dd); | ||
702 | if (ACPI_FAILURE(status)) | ||
703 | kfree(dd); | ||
704 | } | ||
705 | } | 686 | } |
706 | 687 | ||
707 | /** | 688 | /** |
diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index e9304dc7ebfa..a29739c0ba79 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h | |||
@@ -26,11 +26,6 @@ | |||
26 | acpi_status acpi_os_initialize1(void); | 26 | acpi_status acpi_os_initialize1(void); |
27 | int init_acpi_device_notify(void); | 27 | int init_acpi_device_notify(void); |
28 | int acpi_scan_init(void); | 28 | int acpi_scan_init(void); |
29 | #ifdef CONFIG_ACPI_PCI_SLOT | ||
30 | void acpi_pci_slot_init(void); | ||
31 | #else | ||
32 | static inline void acpi_pci_slot_init(void) { } | ||
33 | #endif | ||
34 | void acpi_pci_root_init(void); | 29 | void acpi_pci_root_init(void); |
35 | void acpi_pci_link_init(void); | 30 | void acpi_pci_link_init(void); |
36 | void acpi_pci_root_hp_init(void); | 31 | void acpi_pci_root_hp_init(void); |
@@ -92,6 +87,7 @@ void acpi_device_add_finalize(struct acpi_device *device); | |||
92 | void acpi_free_pnp_ids(struct acpi_device_pnp *pnp); | 87 | void acpi_free_pnp_ids(struct acpi_device_pnp *pnp); |
93 | int acpi_bind_one(struct device *dev, acpi_handle handle); | 88 | int acpi_bind_one(struct device *dev, acpi_handle handle); |
94 | int acpi_unbind_one(struct device *dev); | 89 | int acpi_unbind_one(struct device *dev); |
90 | void acpi_bus_device_eject(void *data, u32 ost_src); | ||
95 | 91 | ||
96 | /* -------------------------------------------------------------------------- | 92 | /* -------------------------------------------------------------------------- |
97 | Power Resource | 93 | Power Resource |
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); | ||
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index d3874f425653..417876bce854 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c | |||
@@ -39,6 +39,8 @@ | |||
39 | #include <acpi/acpi_drivers.h> | 39 | #include <acpi/acpi_drivers.h> |
40 | #include <acpi/apei.h> | 40 | #include <acpi/apei.h> |
41 | 41 | ||
42 | #include "internal.h" | ||
43 | |||
42 | #define PREFIX "ACPI: " | 44 | #define PREFIX "ACPI: " |
43 | 45 | ||
44 | #define _COMPONENT ACPI_PCI_COMPONENT | 46 | #define _COMPONENT ACPI_PCI_COMPONENT |
@@ -590,39 +592,10 @@ static void handle_root_bridge_insertion(acpi_handle handle) | |||
590 | acpi_handle_err(handle, "cannot add bridge to acpi list\n"); | 592 | acpi_handle_err(handle, "cannot add bridge to acpi list\n"); |
591 | } | 593 | } |
592 | 594 | ||
593 | static void handle_root_bridge_removal(struct acpi_device *device) | 595 | static void hotplug_event_root(void *data, u32 type) |
594 | { | ||
595 | acpi_status status; | ||
596 | struct acpi_eject_event *ej_event; | ||
597 | |||
598 | ej_event = kmalloc(sizeof(*ej_event), GFP_KERNEL); | ||
599 | if (!ej_event) { | ||
600 | /* Inform firmware the hot-remove operation has error */ | ||
601 | (void) acpi_evaluate_hotplug_ost(device->handle, | ||
602 | ACPI_NOTIFY_EJECT_REQUEST, | ||
603 | ACPI_OST_SC_NON_SPECIFIC_FAILURE, | ||
604 | NULL); | ||
605 | return; | ||
606 | } | ||
607 | |||
608 | ej_event->device = device; | ||
609 | ej_event->event = ACPI_NOTIFY_EJECT_REQUEST; | ||
610 | |||
611 | status = acpi_os_hotplug_execute(acpi_bus_hot_remove_device, ej_event); | ||
612 | if (ACPI_FAILURE(status)) | ||
613 | kfree(ej_event); | ||
614 | } | ||
615 | |||
616 | static void _handle_hotplug_event_root(struct work_struct *work) | ||
617 | { | 596 | { |
597 | acpi_handle handle = data; | ||
618 | struct acpi_pci_root *root; | 598 | struct acpi_pci_root *root; |
619 | struct acpi_hp_work *hp_work; | ||
620 | acpi_handle handle; | ||
621 | u32 type; | ||
622 | |||
623 | hp_work = container_of(work, struct acpi_hp_work, work); | ||
624 | handle = hp_work->handle; | ||
625 | type = hp_work->type; | ||
626 | 599 | ||
627 | acpi_scan_lock_acquire(); | 600 | acpi_scan_lock_acquire(); |
628 | 601 | ||
@@ -652,9 +625,15 @@ static void _handle_hotplug_event_root(struct work_struct *work) | |||
652 | /* request device eject */ | 625 | /* request device eject */ |
653 | acpi_handle_printk(KERN_DEBUG, handle, | 626 | acpi_handle_printk(KERN_DEBUG, handle, |
654 | "Device eject notify on %s\n", __func__); | 627 | "Device eject notify on %s\n", __func__); |
655 | if (root) | 628 | if (!root) |
656 | handle_root_bridge_removal(root->device); | 629 | break; |
657 | break; | 630 | |
631 | get_device(&root->device->dev); | ||
632 | |||
633 | acpi_scan_lock_release(); | ||
634 | |||
635 | acpi_bus_device_eject(root->device, ACPI_NOTIFY_EJECT_REQUEST); | ||
636 | return; | ||
658 | default: | 637 | default: |
659 | acpi_handle_warn(handle, | 638 | acpi_handle_warn(handle, |
660 | "notify_handler: unknown event type 0x%x\n", | 639 | "notify_handler: unknown event type 0x%x\n", |
@@ -663,14 +642,12 @@ static void _handle_hotplug_event_root(struct work_struct *work) | |||
663 | } | 642 | } |
664 | 643 | ||
665 | acpi_scan_lock_release(); | 644 | acpi_scan_lock_release(); |
666 | kfree(hp_work); /* allocated in handle_hotplug_event_bridge */ | ||
667 | } | 645 | } |
668 | 646 | ||
669 | static void handle_hotplug_event_root(acpi_handle handle, u32 type, | 647 | static void handle_hotplug_event_root(acpi_handle handle, u32 type, |
670 | void *context) | 648 | void *context) |
671 | { | 649 | { |
672 | alloc_acpi_hp_work(handle, type, context, | 650 | acpi_hotplug_execute(hotplug_event_root, handle, type); |
673 | _handle_hotplug_event_root); | ||
674 | } | 651 | } |
675 | 652 | ||
676 | static acpi_status __init | 653 | static acpi_status __init |
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index fee8a297c7d9..55f9dedbbf9f 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c | |||
@@ -125,8 +125,8 @@ acpi_device_modalias_show(struct device *dev, struct device_attribute *attr, cha | |||
125 | } | 125 | } |
126 | static DEVICE_ATTR(modalias, 0444, acpi_device_modalias_show, NULL); | 126 | static DEVICE_ATTR(modalias, 0444, acpi_device_modalias_show, NULL); |
127 | 127 | ||
128 | static acpi_status acpi_bus_offline_companions(acpi_handle handle, u32 lvl, | 128 | static acpi_status acpi_bus_offline(acpi_handle handle, u32 lvl, void *data, |
129 | void *data, void **ret_p) | 129 | void **ret_p) |
130 | { | 130 | { |
131 | struct acpi_device *device = NULL; | 131 | struct acpi_device *device = NULL; |
132 | struct acpi_device_physical_node *pn; | 132 | struct acpi_device_physical_node *pn; |
@@ -136,6 +136,11 @@ static acpi_status acpi_bus_offline_companions(acpi_handle handle, u32 lvl, | |||
136 | if (acpi_bus_get_device(handle, &device)) | 136 | if (acpi_bus_get_device(handle, &device)) |
137 | return AE_OK; | 137 | return AE_OK; |
138 | 138 | ||
139 | if (device->handler && !device->handler->hotplug.enabled) { | ||
140 | *ret_p = &device->dev; | ||
141 | return AE_SUPPORT; | ||
142 | } | ||
143 | |||
139 | mutex_lock(&device->physical_node_lock); | 144 | mutex_lock(&device->physical_node_lock); |
140 | 145 | ||
141 | list_for_each_entry(pn, &device->physical_node_list, node) { | 146 | list_for_each_entry(pn, &device->physical_node_list, node) { |
@@ -168,8 +173,8 @@ static acpi_status acpi_bus_offline_companions(acpi_handle handle, u32 lvl, | |||
168 | return status; | 173 | return status; |
169 | } | 174 | } |
170 | 175 | ||
171 | static acpi_status acpi_bus_online_companions(acpi_handle handle, u32 lvl, | 176 | static acpi_status acpi_bus_online(acpi_handle handle, u32 lvl, void *data, |
172 | void *data, void **ret_p) | 177 | void **ret_p) |
173 | { | 178 | { |
174 | struct acpi_device *device = NULL; | 179 | struct acpi_device *device = NULL; |
175 | struct acpi_device_physical_node *pn; | 180 | struct acpi_device_physical_node *pn; |
@@ -214,26 +219,32 @@ static int acpi_scan_hot_remove(struct acpi_device *device) | |||
214 | * If the first pass is successful, the second one isn't needed, though. | 219 | * If the first pass is successful, the second one isn't needed, though. |
215 | */ | 220 | */ |
216 | errdev = NULL; | 221 | errdev = NULL; |
217 | acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, | 222 | status = acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, |
218 | NULL, acpi_bus_offline_companions, | 223 | NULL, acpi_bus_offline, (void *)false, |
219 | (void *)false, (void **)&errdev); | 224 | (void **)&errdev); |
220 | acpi_bus_offline_companions(handle, 0, (void *)false, (void **)&errdev); | 225 | if (status == AE_SUPPORT) { |
226 | dev_warn(errdev, "Offline disabled.\n"); | ||
227 | acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, | ||
228 | acpi_bus_online, NULL, NULL, NULL); | ||
229 | put_device(&device->dev); | ||
230 | return -EPERM; | ||
231 | } | ||
232 | acpi_bus_offline(handle, 0, (void *)false, (void **)&errdev); | ||
221 | if (errdev) { | 233 | if (errdev) { |
222 | errdev = NULL; | 234 | errdev = NULL; |
223 | acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, | 235 | acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, |
224 | NULL, acpi_bus_offline_companions, | 236 | NULL, acpi_bus_offline, (void *)true, |
225 | (void *)true , (void **)&errdev); | 237 | (void **)&errdev); |
226 | if (!errdev || acpi_force_hot_remove) | 238 | if (!errdev || acpi_force_hot_remove) |
227 | acpi_bus_offline_companions(handle, 0, (void *)true, | 239 | acpi_bus_offline(handle, 0, (void *)true, |
228 | (void **)&errdev); | 240 | (void **)&errdev); |
229 | 241 | ||
230 | if (errdev && !acpi_force_hot_remove) { | 242 | if (errdev && !acpi_force_hot_remove) { |
231 | dev_warn(errdev, "Offline failed.\n"); | 243 | dev_warn(errdev, "Offline failed.\n"); |
232 | acpi_bus_online_companions(handle, 0, NULL, NULL); | 244 | acpi_bus_online(handle, 0, NULL, NULL); |
233 | acpi_walk_namespace(ACPI_TYPE_ANY, handle, | 245 | acpi_walk_namespace(ACPI_TYPE_ANY, handle, |
234 | ACPI_UINT32_MAX, | 246 | ACPI_UINT32_MAX, acpi_bus_online, |
235 | acpi_bus_online_companions, NULL, | 247 | NULL, NULL, NULL); |
236 | NULL, NULL); | ||
237 | put_device(&device->dev); | 248 | put_device(&device->dev); |
238 | return -EBUSY; | 249 | return -EBUSY; |
239 | } | 250 | } |
@@ -274,10 +285,10 @@ static int acpi_scan_hot_remove(struct acpi_device *device) | |||
274 | return 0; | 285 | return 0; |
275 | } | 286 | } |
276 | 287 | ||
277 | static void acpi_bus_device_eject(void *context) | 288 | void acpi_bus_device_eject(void *data, u32 ost_src) |
278 | { | 289 | { |
279 | acpi_handle handle = context; | 290 | struct acpi_device *device = data; |
280 | struct acpi_device *device = NULL; | 291 | acpi_handle handle = device->handle; |
281 | struct acpi_scan_handler *handler; | 292 | struct acpi_scan_handler *handler; |
282 | u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; | 293 | u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; |
283 | int error; | 294 | int error; |
@@ -285,38 +296,41 @@ static void acpi_bus_device_eject(void *context) | |||
285 | lock_device_hotplug(); | 296 | lock_device_hotplug(); |
286 | mutex_lock(&acpi_scan_lock); | 297 | mutex_lock(&acpi_scan_lock); |
287 | 298 | ||
288 | acpi_bus_get_device(handle, &device); | ||
289 | if (!device) | ||
290 | goto err_out; | ||
291 | |||
292 | handler = device->handler; | 299 | handler = device->handler; |
293 | if (!handler || !handler->hotplug.enabled) { | 300 | if (!handler || !handler->hotplug.enabled) { |
294 | ost_code = ACPI_OST_SC_EJECT_NOT_SUPPORTED; | 301 | put_device(&device->dev); |
295 | goto err_out; | 302 | goto err_support; |
296 | } | 303 | } |
297 | acpi_evaluate_hotplug_ost(handle, ACPI_NOTIFY_EJECT_REQUEST, | 304 | |
298 | ACPI_OST_SC_EJECT_IN_PROGRESS, NULL); | 305 | if (ost_src == ACPI_NOTIFY_EJECT_REQUEST) |
306 | acpi_evaluate_hotplug_ost(handle, ACPI_NOTIFY_EJECT_REQUEST, | ||
307 | ACPI_OST_SC_EJECT_IN_PROGRESS, NULL); | ||
308 | |||
299 | if (handler->hotplug.mode == AHM_CONTAINER) | 309 | if (handler->hotplug.mode == AHM_CONTAINER) |
300 | kobject_uevent(&device->dev.kobj, KOBJ_OFFLINE); | 310 | kobject_uevent(&device->dev.kobj, KOBJ_OFFLINE); |
301 | 311 | ||
302 | get_device(&device->dev); | ||
303 | error = acpi_scan_hot_remove(device); | 312 | error = acpi_scan_hot_remove(device); |
304 | if (error) | 313 | if (error == -EPERM) { |
314 | goto err_support; | ||
315 | } else if (error) { | ||
305 | goto err_out; | 316 | goto err_out; |
317 | } | ||
306 | 318 | ||
307 | out: | 319 | out: |
308 | mutex_unlock(&acpi_scan_lock); | 320 | mutex_unlock(&acpi_scan_lock); |
309 | unlock_device_hotplug(); | 321 | unlock_device_hotplug(); |
310 | return; | 322 | return; |
311 | 323 | ||
324 | err_support: | ||
325 | ost_code = ACPI_OST_SC_EJECT_NOT_SUPPORTED; | ||
312 | err_out: | 326 | err_out: |
313 | acpi_evaluate_hotplug_ost(handle, ACPI_NOTIFY_EJECT_REQUEST, ost_code, | 327 | acpi_evaluate_hotplug_ost(handle, ost_src, ost_code, NULL); |
314 | NULL); | ||
315 | goto out; | 328 | goto out; |
316 | } | 329 | } |
317 | 330 | ||
318 | static void acpi_scan_bus_device_check(acpi_handle handle, u32 ost_source) | 331 | static void acpi_scan_bus_device_check(void *data, u32 ost_source) |
319 | { | 332 | { |
333 | acpi_handle handle = data; | ||
320 | struct acpi_device *device = NULL; | 334 | struct acpi_device *device = NULL; |
321 | u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; | 335 | u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; |
322 | int error; | 336 | int error; |
@@ -331,8 +345,6 @@ static void acpi_scan_bus_device_check(acpi_handle handle, u32 ost_source) | |||
331 | goto out; | 345 | goto out; |
332 | } | 346 | } |
333 | } | 347 | } |
334 | acpi_evaluate_hotplug_ost(handle, ost_source, | ||
335 | ACPI_OST_SC_INSERT_IN_PROGRESS, NULL); | ||
336 | error = acpi_bus_scan(handle); | 348 | error = acpi_bus_scan(handle); |
337 | if (error) { | 349 | if (error) { |
338 | acpi_handle_warn(handle, "Namespace scan failure\n"); | 350 | acpi_handle_warn(handle, "Namespace scan failure\n"); |
@@ -353,18 +365,6 @@ static void acpi_scan_bus_device_check(acpi_handle handle, u32 ost_source) | |||
353 | unlock_device_hotplug(); | 365 | unlock_device_hotplug(); |
354 | } | 366 | } |
355 | 367 | ||
356 | static void acpi_scan_bus_check(void *context) | ||
357 | { | ||
358 | acpi_scan_bus_device_check((acpi_handle)context, | ||
359 | ACPI_NOTIFY_BUS_CHECK); | ||
360 | } | ||
361 | |||
362 | static void acpi_scan_device_check(void *context) | ||
363 | { | ||
364 | acpi_scan_bus_device_check((acpi_handle)context, | ||
365 | ACPI_NOTIFY_DEVICE_CHECK); | ||
366 | } | ||
367 | |||
368 | static void acpi_hotplug_unsupported(acpi_handle handle, u32 type) | 368 | static void acpi_hotplug_unsupported(acpi_handle handle, u32 type) |
369 | { | 369 | { |
370 | u32 ost_status; | 370 | u32 ost_status; |
@@ -395,8 +395,8 @@ static void acpi_hotplug_unsupported(acpi_handle handle, u32 type) | |||
395 | 395 | ||
396 | static void acpi_hotplug_notify_cb(acpi_handle handle, u32 type, void *data) | 396 | static void acpi_hotplug_notify_cb(acpi_handle handle, u32 type, void *data) |
397 | { | 397 | { |
398 | acpi_osd_exec_callback callback; | ||
399 | struct acpi_scan_handler *handler = data; | 398 | struct acpi_scan_handler *handler = data; |
399 | struct acpi_device *adev; | ||
400 | acpi_status status; | 400 | acpi_status status; |
401 | 401 | ||
402 | if (!handler->hotplug.enabled) | 402 | if (!handler->hotplug.enabled) |
@@ -405,56 +405,35 @@ static void acpi_hotplug_notify_cb(acpi_handle handle, u32 type, void *data) | |||
405 | switch (type) { | 405 | switch (type) { |
406 | case ACPI_NOTIFY_BUS_CHECK: | 406 | case ACPI_NOTIFY_BUS_CHECK: |
407 | acpi_handle_debug(handle, "ACPI_NOTIFY_BUS_CHECK event\n"); | 407 | acpi_handle_debug(handle, "ACPI_NOTIFY_BUS_CHECK event\n"); |
408 | callback = acpi_scan_bus_check; | ||
409 | break; | 408 | break; |
410 | case ACPI_NOTIFY_DEVICE_CHECK: | 409 | case ACPI_NOTIFY_DEVICE_CHECK: |
411 | acpi_handle_debug(handle, "ACPI_NOTIFY_DEVICE_CHECK event\n"); | 410 | acpi_handle_debug(handle, "ACPI_NOTIFY_DEVICE_CHECK event\n"); |
412 | callback = acpi_scan_device_check; | ||
413 | break; | 411 | break; |
414 | case ACPI_NOTIFY_EJECT_REQUEST: | 412 | case ACPI_NOTIFY_EJECT_REQUEST: |
415 | acpi_handle_debug(handle, "ACPI_NOTIFY_EJECT_REQUEST event\n"); | 413 | acpi_handle_debug(handle, "ACPI_NOTIFY_EJECT_REQUEST event\n"); |
416 | callback = acpi_bus_device_eject; | 414 | status = acpi_bus_get_device(handle, &adev); |
417 | break; | 415 | if (ACPI_FAILURE(status)) |
416 | goto err_out; | ||
417 | |||
418 | get_device(&adev->dev); | ||
419 | status = acpi_hotplug_execute(acpi_bus_device_eject, adev, type); | ||
420 | if (ACPI_SUCCESS(status)) | ||
421 | return; | ||
422 | |||
423 | put_device(&adev->dev); | ||
424 | goto err_out; | ||
418 | default: | 425 | default: |
419 | /* non-hotplug event; possibly handled by other handler */ | 426 | /* non-hotplug event; possibly handled by other handler */ |
420 | return; | 427 | return; |
421 | } | 428 | } |
422 | status = acpi_os_hotplug_execute(callback, handle); | 429 | status = acpi_hotplug_execute(acpi_scan_bus_device_check, handle, type); |
423 | if (ACPI_FAILURE(status)) | 430 | if (ACPI_SUCCESS(status)) |
424 | acpi_evaluate_hotplug_ost(handle, type, | 431 | return; |
425 | ACPI_OST_SC_NON_SPECIFIC_FAILURE, | ||
426 | NULL); | ||
427 | } | ||
428 | |||
429 | /** | ||
430 | * acpi_bus_hot_remove_device: hot-remove a device and its children | ||
431 | * @context: struct acpi_eject_event pointer (freed in this func) | ||
432 | * | ||
433 | * Hot-remove a device and its children. This function frees up the | ||
434 | * memory space passed by arg context, so that the caller may call | ||
435 | * this function asynchronously through acpi_os_hotplug_execute(). | ||
436 | */ | ||
437 | void acpi_bus_hot_remove_device(void *context) | ||
438 | { | ||
439 | struct acpi_eject_event *ej_event = context; | ||
440 | struct acpi_device *device = ej_event->device; | ||
441 | acpi_handle handle = device->handle; | ||
442 | int error; | ||
443 | |||
444 | lock_device_hotplug(); | ||
445 | mutex_lock(&acpi_scan_lock); | ||
446 | |||
447 | error = acpi_scan_hot_remove(device); | ||
448 | if (error && handle) | ||
449 | acpi_evaluate_hotplug_ost(handle, ej_event->event, | ||
450 | ACPI_OST_SC_NON_SPECIFIC_FAILURE, | ||
451 | NULL); | ||
452 | 432 | ||
453 | mutex_unlock(&acpi_scan_lock); | 433 | err_out: |
454 | unlock_device_hotplug(); | 434 | acpi_evaluate_hotplug_ost(handle, type, |
455 | kfree(context); | 435 | ACPI_OST_SC_NON_SPECIFIC_FAILURE, NULL); |
456 | } | 436 | } |
457 | EXPORT_SYMBOL(acpi_bus_hot_remove_device); | ||
458 | 437 | ||
459 | static ssize_t real_power_state_show(struct device *dev, | 438 | static ssize_t real_power_state_show(struct device *dev, |
460 | struct device_attribute *attr, char *buf) | 439 | struct device_attribute *attr, char *buf) |
@@ -487,10 +466,8 @@ acpi_eject_store(struct device *d, struct device_attribute *attr, | |||
487 | const char *buf, size_t count) | 466 | const char *buf, size_t count) |
488 | { | 467 | { |
489 | struct acpi_device *acpi_device = to_acpi_device(d); | 468 | struct acpi_device *acpi_device = to_acpi_device(d); |
490 | struct acpi_eject_event *ej_event; | ||
491 | acpi_object_type not_used; | 469 | acpi_object_type not_used; |
492 | acpi_status status; | 470 | acpi_status status; |
493 | int ret; | ||
494 | 471 | ||
495 | if (!count || buf[0] != '1') | 472 | if (!count || buf[0] != '1') |
496 | return -EINVAL; | 473 | return -EINVAL; |
@@ -503,28 +480,18 @@ acpi_eject_store(struct device *d, struct device_attribute *attr, | |||
503 | if (ACPI_FAILURE(status) || !acpi_device->flags.ejectable) | 480 | if (ACPI_FAILURE(status) || !acpi_device->flags.ejectable) |
504 | return -ENODEV; | 481 | return -ENODEV; |
505 | 482 | ||
506 | ej_event = kmalloc(sizeof(*ej_event), GFP_KERNEL); | ||
507 | if (!ej_event) { | ||
508 | ret = -ENOMEM; | ||
509 | goto err_out; | ||
510 | } | ||
511 | acpi_evaluate_hotplug_ost(acpi_device->handle, ACPI_OST_EC_OSPM_EJECT, | 483 | acpi_evaluate_hotplug_ost(acpi_device->handle, ACPI_OST_EC_OSPM_EJECT, |
512 | ACPI_OST_SC_EJECT_IN_PROGRESS, NULL); | 484 | ACPI_OST_SC_EJECT_IN_PROGRESS, NULL); |
513 | ej_event->device = acpi_device; | ||
514 | ej_event->event = ACPI_OST_EC_OSPM_EJECT; | ||
515 | get_device(&acpi_device->dev); | 485 | get_device(&acpi_device->dev); |
516 | status = acpi_os_hotplug_execute(acpi_bus_hot_remove_device, ej_event); | 486 | status = acpi_hotplug_execute(acpi_bus_device_eject, acpi_device, |
487 | ACPI_OST_EC_OSPM_EJECT); | ||
517 | if (ACPI_SUCCESS(status)) | 488 | if (ACPI_SUCCESS(status)) |
518 | return count; | 489 | return count; |
519 | 490 | ||
520 | put_device(&acpi_device->dev); | 491 | put_device(&acpi_device->dev); |
521 | kfree(ej_event); | ||
522 | ret = status == AE_NO_MEMORY ? -ENOMEM : -EAGAIN; | ||
523 | |||
524 | err_out: | ||
525 | acpi_evaluate_hotplug_ost(acpi_device->handle, ACPI_OST_EC_OSPM_EJECT, | 492 | acpi_evaluate_hotplug_ost(acpi_device->handle, ACPI_OST_EC_OSPM_EJECT, |
526 | ACPI_OST_SC_NON_SPECIFIC_FAILURE, NULL); | 493 | ACPI_OST_SC_NON_SPECIFIC_FAILURE, NULL); |
527 | return ret; | 494 | return status == AE_NO_MEMORY ? -ENOMEM : -EAGAIN; |
528 | } | 495 | } |
529 | 496 | ||
530 | static DEVICE_ATTR(eject, 0200, NULL, acpi_eject_store); | 497 | static DEVICE_ATTR(eject, 0200, NULL, acpi_eject_store); |
@@ -1676,7 +1643,6 @@ void acpi_init_device_object(struct acpi_device *device, acpi_handle handle, | |||
1676 | 1643 | ||
1677 | void acpi_device_add_finalize(struct acpi_device *device) | 1644 | void acpi_device_add_finalize(struct acpi_device *device) |
1678 | { | 1645 | { |
1679 | device->flags.match_driver = true; | ||
1680 | dev_set_uevent_suppress(&device->dev, false); | 1646 | dev_set_uevent_suppress(&device->dev, false); |
1681 | kobject_uevent(&device->dev.kobj, KOBJ_ADD); | 1647 | kobject_uevent(&device->dev.kobj, KOBJ_ADD); |
1682 | } | 1648 | } |
@@ -1915,8 +1881,12 @@ static acpi_status acpi_bus_device_attach(acpi_handle handle, u32 lvl_not_used, | |||
1915 | return AE_OK; | 1881 | return AE_OK; |
1916 | 1882 | ||
1917 | ret = acpi_scan_attach_handler(device); | 1883 | ret = acpi_scan_attach_handler(device); |
1918 | if (ret) | 1884 | if (ret < 0) |
1919 | return ret > 0 ? AE_OK : AE_CTRL_DEPTH; | 1885 | return AE_CTRL_DEPTH; |
1886 | |||
1887 | device->flags.match_driver = true; | ||
1888 | if (ret > 0) | ||
1889 | return AE_OK; | ||
1920 | 1890 | ||
1921 | ret = device_attach(&device->dev); | 1891 | ret = device_attach(&device->dev); |
1922 | return ret >= 0 ? AE_OK : AE_CTRL_DEPTH; | 1892 | return ret >= 0 ? AE_OK : AE_CTRL_DEPTH; |
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index be12fbfcae10..e98018b43e2a 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 | ||
878 | static void hotplug_event_work(struct work_struct *work) | 878 | static 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 | } |