diff options
-rw-r--r-- | drivers/acpi/acpi_memhotplug.c | 56 | ||||
-rw-r--r-- | drivers/acpi/container.c | 12 | ||||
-rw-r--r-- | drivers/acpi/dock.c | 19 | ||||
-rw-r--r-- | drivers/acpi/processor_driver.c | 24 | ||||
-rw-r--r-- | drivers/acpi/scan.c | 69 | ||||
-rw-r--r-- | drivers/pci/hotplug/acpiphp_glue.c | 6 | ||||
-rw-r--r-- | drivers/pci/hotplug/sgi_hotplug.c | 5 | ||||
-rw-r--r-- | include/acpi/acpi_bus.h | 3 |
8 files changed, 139 insertions, 55 deletions
diff --git a/drivers/acpi/acpi_memhotplug.c b/drivers/acpi/acpi_memhotplug.c index 94c823b25138..034d3e72aa92 100644 --- a/drivers/acpi/acpi_memhotplug.c +++ b/drivers/acpi/acpi_memhotplug.c | |||
@@ -153,14 +153,16 @@ acpi_memory_get_device_resources(struct acpi_memory_device *mem_device) | |||
153 | return 0; | 153 | return 0; |
154 | } | 154 | } |
155 | 155 | ||
156 | static int | 156 | static int acpi_memory_get_device(acpi_handle handle, |
157 | acpi_memory_get_device(acpi_handle handle, | 157 | struct acpi_memory_device **mem_device) |
158 | struct acpi_memory_device **mem_device) | ||
159 | { | 158 | { |
160 | struct acpi_device *device = NULL; | 159 | struct acpi_device *device = NULL; |
161 | int result; | 160 | int result = 0; |
162 | 161 | ||
163 | if (!acpi_bus_get_device(handle, &device) && device) | 162 | acpi_scan_lock_acquire(); |
163 | |||
164 | acpi_bus_get_device(handle, &device); | ||
165 | if (device) | ||
164 | goto end; | 166 | goto end; |
165 | 167 | ||
166 | /* | 168 | /* |
@@ -169,23 +171,28 @@ acpi_memory_get_device(acpi_handle handle, | |||
169 | */ | 171 | */ |
170 | result = acpi_bus_scan(handle); | 172 | result = acpi_bus_scan(handle); |
171 | if (result) { | 173 | if (result) { |
172 | acpi_handle_warn(handle, "Cannot add acpi bus\n"); | 174 | acpi_handle_warn(handle, "ACPI namespace scan failed\n"); |
173 | return -EINVAL; | 175 | result = -EINVAL; |
176 | goto out; | ||
174 | } | 177 | } |
175 | result = acpi_bus_get_device(handle, &device); | 178 | result = acpi_bus_get_device(handle, &device); |
176 | if (result) { | 179 | if (result) { |
177 | acpi_handle_warn(handle, "Missing device object\n"); | 180 | acpi_handle_warn(handle, "Missing device object\n"); |
178 | return -EINVAL; | 181 | result = -EINVAL; |
182 | goto out; | ||
179 | } | 183 | } |
180 | 184 | ||
181 | end: | 185 | end: |
182 | *mem_device = acpi_driver_data(device); | 186 | *mem_device = acpi_driver_data(device); |
183 | if (!(*mem_device)) { | 187 | if (!(*mem_device)) { |
184 | dev_err(&device->dev, "driver data not found\n"); | 188 | dev_err(&device->dev, "driver data not found\n"); |
185 | return -ENODEV; | 189 | result = -ENODEV; |
190 | goto out; | ||
186 | } | 191 | } |
187 | 192 | ||
188 | return 0; | 193 | out: |
194 | acpi_scan_lock_release(); | ||
195 | return result; | ||
189 | } | 196 | } |
190 | 197 | ||
191 | static int acpi_memory_check_device(struct acpi_memory_device *mem_device) | 198 | static int acpi_memory_check_device(struct acpi_memory_device *mem_device) |
@@ -305,6 +312,7 @@ static void acpi_memory_device_notify(acpi_handle handle, u32 event, void *data) | |||
305 | struct acpi_device *device; | 312 | struct acpi_device *device; |
306 | struct acpi_eject_event *ej_event = NULL; | 313 | struct acpi_eject_event *ej_event = NULL; |
307 | u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; /* default */ | 314 | u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; /* default */ |
315 | acpi_status status; | ||
308 | 316 | ||
309 | switch (event) { | 317 | switch (event) { |
310 | case ACPI_NOTIFY_BUS_CHECK: | 318 | case ACPI_NOTIFY_BUS_CHECK: |
@@ -327,29 +335,40 @@ static void acpi_memory_device_notify(acpi_handle handle, u32 event, void *data) | |||
327 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | 335 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, |
328 | "\nReceived EJECT REQUEST notification for device\n")); | 336 | "\nReceived EJECT REQUEST notification for device\n")); |
329 | 337 | ||
338 | status = AE_ERROR; | ||
339 | acpi_scan_lock_acquire(); | ||
340 | |||
330 | if (acpi_bus_get_device(handle, &device)) { | 341 | if (acpi_bus_get_device(handle, &device)) { |
331 | acpi_handle_err(handle, "Device doesn't exist\n"); | 342 | acpi_handle_err(handle, "Device doesn't exist\n"); |
332 | break; | 343 | goto unlock; |
333 | } | 344 | } |
334 | mem_device = acpi_driver_data(device); | 345 | mem_device = acpi_driver_data(device); |
335 | if (!mem_device) { | 346 | if (!mem_device) { |
336 | acpi_handle_err(handle, "Driver Data is NULL\n"); | 347 | acpi_handle_err(handle, "Driver Data is NULL\n"); |
337 | break; | 348 | goto unlock; |
338 | } | 349 | } |
339 | 350 | ||
340 | ej_event = kmalloc(sizeof(*ej_event), GFP_KERNEL); | 351 | ej_event = kmalloc(sizeof(*ej_event), GFP_KERNEL); |
341 | if (!ej_event) { | 352 | if (!ej_event) { |
342 | pr_err(PREFIX "No memory, dropping EJECT\n"); | 353 | pr_err(PREFIX "No memory, dropping EJECT\n"); |
343 | break; | 354 | goto unlock; |
344 | } | 355 | } |
345 | 356 | ||
357 | get_device(&device->dev); | ||
346 | ej_event->device = device; | 358 | ej_event->device = device; |
347 | ej_event->event = ACPI_NOTIFY_EJECT_REQUEST; | 359 | ej_event->event = ACPI_NOTIFY_EJECT_REQUEST; |
348 | acpi_os_hotplug_execute(acpi_bus_hot_remove_device, | 360 | /* The eject is carried out asynchronously. */ |
349 | (void *)ej_event); | 361 | status = acpi_os_hotplug_execute(acpi_bus_hot_remove_device, |
362 | ej_event); | ||
363 | if (ACPI_FAILURE(status)) { | ||
364 | put_device(&device->dev); | ||
365 | kfree(ej_event); | ||
366 | } | ||
350 | 367 | ||
351 | /* eject is performed asynchronously */ | 368 | unlock: |
352 | return; | 369 | acpi_scan_lock_release(); |
370 | if (ACPI_SUCCESS(status)) | ||
371 | return; | ||
353 | default: | 372 | default: |
354 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | 373 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, |
355 | "Unsupported event [0x%x]\n", event)); | 374 | "Unsupported event [0x%x]\n", event)); |
@@ -360,7 +379,6 @@ static void acpi_memory_device_notify(acpi_handle handle, u32 event, void *data) | |||
360 | 379 | ||
361 | /* Inform firmware that the hotplug operation has completed */ | 380 | /* Inform firmware that the hotplug operation has completed */ |
362 | (void) acpi_evaluate_hotplug_ost(handle, event, ost_code, NULL); | 381 | (void) acpi_evaluate_hotplug_ost(handle, event, ost_code, NULL); |
363 | return; | ||
364 | } | 382 | } |
365 | 383 | ||
366 | static void acpi_memory_device_free(struct acpi_memory_device *mem_device) | 384 | static void acpi_memory_device_free(struct acpi_memory_device *mem_device) |
diff --git a/drivers/acpi/container.c b/drivers/acpi/container.c index 4cc2937cc022..5523ba7d764d 100644 --- a/drivers/acpi/container.c +++ b/drivers/acpi/container.c | |||
@@ -88,6 +88,8 @@ static void container_notify_cb(acpi_handle handle, u32 type, void *context) | |||
88 | acpi_status status; | 88 | acpi_status status; |
89 | u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; /* default */ | 89 | u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; /* default */ |
90 | 90 | ||
91 | acpi_scan_lock_acquire(); | ||
92 | |||
91 | switch (type) { | 93 | switch (type) { |
92 | case ACPI_NOTIFY_BUS_CHECK: | 94 | case ACPI_NOTIFY_BUS_CHECK: |
93 | /* Fall through */ | 95 | /* Fall through */ |
@@ -103,7 +105,7 @@ static void container_notify_cb(acpi_handle handle, u32 type, void *context) | |||
103 | /* device exist and this is a remove request */ | 105 | /* device exist and this is a remove request */ |
104 | device->flags.eject_pending = 1; | 106 | device->flags.eject_pending = 1; |
105 | kobject_uevent(&device->dev.kobj, KOBJ_OFFLINE); | 107 | kobject_uevent(&device->dev.kobj, KOBJ_OFFLINE); |
106 | return; | 108 | goto out; |
107 | } | 109 | } |
108 | break; | 110 | break; |
109 | } | 111 | } |
@@ -130,18 +132,20 @@ static void container_notify_cb(acpi_handle handle, u32 type, void *context) | |||
130 | if (!acpi_bus_get_device(handle, &device) && device) { | 132 | if (!acpi_bus_get_device(handle, &device) && device) { |
131 | device->flags.eject_pending = 1; | 133 | device->flags.eject_pending = 1; |
132 | kobject_uevent(&device->dev.kobj, KOBJ_OFFLINE); | 134 | kobject_uevent(&device->dev.kobj, KOBJ_OFFLINE); |
133 | return; | 135 | goto out; |
134 | } | 136 | } |
135 | break; | 137 | break; |
136 | 138 | ||
137 | default: | 139 | default: |
138 | /* non-hotplug event; possibly handled by other handler */ | 140 | /* non-hotplug event; possibly handled by other handler */ |
139 | return; | 141 | goto out; |
140 | } | 142 | } |
141 | 143 | ||
142 | /* Inform firmware that the hotplug operation has completed */ | 144 | /* Inform firmware that the hotplug operation has completed */ |
143 | (void) acpi_evaluate_hotplug_ost(handle, type, ost_code, NULL); | 145 | (void) acpi_evaluate_hotplug_ost(handle, type, ost_code, NULL); |
144 | return; | 146 | |
147 | out: | ||
148 | acpi_scan_lock_release(); | ||
145 | } | 149 | } |
146 | 150 | ||
147 | static bool is_container(acpi_handle handle) | 151 | static bool is_container(acpi_handle handle) |
diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c index 68d720af71ed..4fdea381ef21 100644 --- a/drivers/acpi/dock.c +++ b/drivers/acpi/dock.c | |||
@@ -744,7 +744,9 @@ static void acpi_dock_deferred_cb(void *context) | |||
744 | { | 744 | { |
745 | struct dock_data *data = context; | 745 | struct dock_data *data = context; |
746 | 746 | ||
747 | acpi_scan_lock_acquire(); | ||
747 | dock_notify(data->handle, data->event, data->ds); | 748 | dock_notify(data->handle, data->event, data->ds); |
749 | acpi_scan_lock_release(); | ||
748 | kfree(data); | 750 | kfree(data); |
749 | } | 751 | } |
750 | 752 | ||
@@ -757,20 +759,31 @@ static int acpi_dock_notifier_call(struct notifier_block *this, | |||
757 | if (event != ACPI_NOTIFY_BUS_CHECK && event != ACPI_NOTIFY_DEVICE_CHECK | 759 | if (event != ACPI_NOTIFY_BUS_CHECK && event != ACPI_NOTIFY_DEVICE_CHECK |
758 | && event != ACPI_NOTIFY_EJECT_REQUEST) | 760 | && event != ACPI_NOTIFY_EJECT_REQUEST) |
759 | return 0; | 761 | return 0; |
762 | |||
763 | acpi_scan_lock_acquire(); | ||
764 | |||
760 | list_for_each_entry(dock_station, &dock_stations, sibling) { | 765 | list_for_each_entry(dock_station, &dock_stations, sibling) { |
761 | if (dock_station->handle == handle) { | 766 | if (dock_station->handle == handle) { |
762 | struct dock_data *dd; | 767 | struct dock_data *dd; |
768 | acpi_status status; | ||
763 | 769 | ||
764 | dd = kmalloc(sizeof(*dd), GFP_KERNEL); | 770 | dd = kmalloc(sizeof(*dd), GFP_KERNEL); |
765 | if (!dd) | 771 | if (!dd) |
766 | return 0; | 772 | break; |
773 | |||
767 | dd->handle = handle; | 774 | dd->handle = handle; |
768 | dd->event = event; | 775 | dd->event = event; |
769 | dd->ds = dock_station; | 776 | dd->ds = dock_station; |
770 | acpi_os_hotplug_execute(acpi_dock_deferred_cb, dd); | 777 | status = acpi_os_hotplug_execute(acpi_dock_deferred_cb, |
771 | return 0 ; | 778 | dd); |
779 | if (ACPI_FAILURE(status)) | ||
780 | kfree(dd); | ||
781 | |||
782 | break; | ||
772 | } | 783 | } |
773 | } | 784 | } |
785 | |||
786 | acpi_scan_lock_release(); | ||
774 | return 0; | 787 | return 0; |
775 | } | 788 | } |
776 | 789 | ||
diff --git a/drivers/acpi/processor_driver.c b/drivers/acpi/processor_driver.c index c5d2fd85dbe0..cbf1f122666b 100644 --- a/drivers/acpi/processor_driver.c +++ b/drivers/acpi/processor_driver.c | |||
@@ -683,8 +683,11 @@ static void acpi_processor_hotplug_notify(acpi_handle handle, | |||
683 | struct acpi_device *device = NULL; | 683 | struct acpi_device *device = NULL; |
684 | struct acpi_eject_event *ej_event = NULL; | 684 | struct acpi_eject_event *ej_event = NULL; |
685 | u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; /* default */ | 685 | u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; /* default */ |
686 | acpi_status status; | ||
686 | int result; | 687 | int result; |
687 | 688 | ||
689 | acpi_scan_lock_acquire(); | ||
690 | |||
688 | switch (event) { | 691 | switch (event) { |
689 | case ACPI_NOTIFY_BUS_CHECK: | 692 | case ACPI_NOTIFY_BUS_CHECK: |
690 | case ACPI_NOTIFY_DEVICE_CHECK: | 693 | case ACPI_NOTIFY_DEVICE_CHECK: |
@@ -733,25 +736,32 @@ static void acpi_processor_hotplug_notify(acpi_handle handle, | |||
733 | break; | 736 | break; |
734 | } | 737 | } |
735 | 738 | ||
739 | get_device(&device->dev); | ||
736 | ej_event->device = device; | 740 | ej_event->device = device; |
737 | ej_event->event = ACPI_NOTIFY_EJECT_REQUEST; | 741 | ej_event->event = ACPI_NOTIFY_EJECT_REQUEST; |
738 | acpi_os_hotplug_execute(acpi_bus_hot_remove_device, | 742 | /* The eject is carried out asynchronously. */ |
739 | (void *)ej_event); | 743 | status = acpi_os_hotplug_execute(acpi_bus_hot_remove_device, |
740 | 744 | ej_event); | |
741 | /* eject is performed asynchronously */ | 745 | if (ACPI_FAILURE(status)) { |
742 | return; | 746 | put_device(&device->dev); |
747 | kfree(ej_event); | ||
748 | break; | ||
749 | } | ||
750 | goto out; | ||
743 | 751 | ||
744 | default: | 752 | default: |
745 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | 753 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, |
746 | "Unsupported event [0x%x]\n", event)); | 754 | "Unsupported event [0x%x]\n", event)); |
747 | 755 | ||
748 | /* non-hotplug event; possibly handled by other handler */ | 756 | /* non-hotplug event; possibly handled by other handler */ |
749 | return; | 757 | goto out; |
750 | } | 758 | } |
751 | 759 | ||
752 | /* Inform firmware that the hotplug operation has completed */ | 760 | /* Inform firmware that the hotplug operation has completed */ |
753 | (void) acpi_evaluate_hotplug_ost(handle, event, ost_code, NULL); | 761 | (void) acpi_evaluate_hotplug_ost(handle, event, ost_code, NULL); |
754 | return; | 762 | |
763 | out: | ||
764 | acpi_scan_lock_release(); | ||
755 | } | 765 | } |
756 | 766 | ||
757 | static acpi_status is_processor_device(acpi_handle handle) | 767 | static acpi_status is_processor_device(acpi_handle handle) |
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index c7676ee8eca4..d16a94ef0baf 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c | |||
@@ -42,6 +42,18 @@ struct acpi_device_bus_id{ | |||
42 | struct list_head node; | 42 | struct list_head node; |
43 | }; | 43 | }; |
44 | 44 | ||
45 | void acpi_scan_lock_acquire(void) | ||
46 | { | ||
47 | mutex_lock(&acpi_scan_lock); | ||
48 | } | ||
49 | EXPORT_SYMBOL_GPL(acpi_scan_lock_acquire); | ||
50 | |||
51 | void acpi_scan_lock_release(void) | ||
52 | { | ||
53 | mutex_unlock(&acpi_scan_lock); | ||
54 | } | ||
55 | EXPORT_SYMBOL_GPL(acpi_scan_lock_release); | ||
56 | |||
45 | int acpi_scan_add_handler(struct acpi_scan_handler *handler) | 57 | int acpi_scan_add_handler(struct acpi_scan_handler *handler) |
46 | { | 58 | { |
47 | if (!handler || !handler->attach) | 59 | if (!handler || !handler->attach) |
@@ -95,8 +107,6 @@ acpi_device_modalias_show(struct device *dev, struct device_attribute *attr, cha | |||
95 | } | 107 | } |
96 | static DEVICE_ATTR(modalias, 0444, acpi_device_modalias_show, NULL); | 108 | static DEVICE_ATTR(modalias, 0444, acpi_device_modalias_show, NULL); |
97 | 109 | ||
98 | static void __acpi_bus_trim(struct acpi_device *start); | ||
99 | |||
100 | /** | 110 | /** |
101 | * acpi_bus_hot_remove_device: hot-remove a device and its children | 111 | * acpi_bus_hot_remove_device: hot-remove a device and its children |
102 | * @context: struct acpi_eject_event pointer (freed in this func) | 112 | * @context: struct acpi_eject_event pointer (freed in this func) |
@@ -107,7 +117,7 @@ static void __acpi_bus_trim(struct acpi_device *start); | |||
107 | */ | 117 | */ |
108 | void acpi_bus_hot_remove_device(void *context) | 118 | void acpi_bus_hot_remove_device(void *context) |
109 | { | 119 | { |
110 | struct acpi_eject_event *ej_event = (struct acpi_eject_event *) context; | 120 | struct acpi_eject_event *ej_event = context; |
111 | struct acpi_device *device = ej_event->device; | 121 | struct acpi_device *device = ej_event->device; |
112 | acpi_handle handle = device->handle; | 122 | acpi_handle handle = device->handle; |
113 | acpi_handle temp; | 123 | acpi_handle temp; |
@@ -118,11 +128,19 @@ void acpi_bus_hot_remove_device(void *context) | |||
118 | 128 | ||
119 | mutex_lock(&acpi_scan_lock); | 129 | mutex_lock(&acpi_scan_lock); |
120 | 130 | ||
131 | /* If there is no handle, the device node has been unregistered. */ | ||
132 | if (!device->handle) { | ||
133 | dev_dbg(&device->dev, "ACPI handle missing\n"); | ||
134 | put_device(&device->dev); | ||
135 | goto out; | ||
136 | } | ||
137 | |||
121 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | 138 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, |
122 | "Hot-removing device %s...\n", dev_name(&device->dev))); | 139 | "Hot-removing device %s...\n", dev_name(&device->dev))); |
123 | 140 | ||
124 | __acpi_bus_trim(device); | 141 | acpi_bus_trim(device); |
125 | /* Device node has been released. */ | 142 | /* Device node has been unregistered. */ |
143 | put_device(&device->dev); | ||
126 | device = NULL; | 144 | device = NULL; |
127 | 145 | ||
128 | if (ACPI_SUCCESS(acpi_get_handle(handle, "_LCK", &temp))) { | 146 | if (ACPI_SUCCESS(acpi_get_handle(handle, "_LCK", &temp))) { |
@@ -151,6 +169,7 @@ void acpi_bus_hot_remove_device(void *context) | |||
151 | ost_code, NULL); | 169 | ost_code, NULL); |
152 | } | 170 | } |
153 | 171 | ||
172 | out: | ||
154 | mutex_unlock(&acpi_scan_lock); | 173 | mutex_unlock(&acpi_scan_lock); |
155 | kfree(context); | 174 | kfree(context); |
156 | return; | 175 | return; |
@@ -212,6 +231,7 @@ acpi_eject_store(struct device *d, struct device_attribute *attr, | |||
212 | goto err; | 231 | goto err; |
213 | } | 232 | } |
214 | 233 | ||
234 | get_device(&acpi_device->dev); | ||
215 | ej_event->device = acpi_device; | 235 | ej_event->device = acpi_device; |
216 | if (acpi_device->flags.eject_pending) { | 236 | if (acpi_device->flags.eject_pending) { |
217 | /* event originated from ACPI eject notification */ | 237 | /* event originated from ACPI eject notification */ |
@@ -224,7 +244,11 @@ acpi_eject_store(struct device *d, struct device_attribute *attr, | |||
224 | ej_event->event, ACPI_OST_SC_EJECT_IN_PROGRESS, NULL); | 244 | ej_event->event, ACPI_OST_SC_EJECT_IN_PROGRESS, NULL); |
225 | } | 245 | } |
226 | 246 | ||
227 | acpi_os_hotplug_execute(acpi_bus_hot_remove_device, (void *)ej_event); | 247 | status = acpi_os_hotplug_execute(acpi_bus_hot_remove_device, ej_event); |
248 | if (ACPI_FAILURE(status)) { | ||
249 | put_device(&acpi_device->dev); | ||
250 | kfree(ej_event); | ||
251 | } | ||
228 | err: | 252 | err: |
229 | return ret; | 253 | return ret; |
230 | } | 254 | } |
@@ -779,6 +803,7 @@ static void acpi_device_unregister(struct acpi_device *device) | |||
779 | * no more references. | 803 | * no more references. |
780 | */ | 804 | */ |
781 | acpi_device_set_power(device, ACPI_STATE_D3_COLD); | 805 | acpi_device_set_power(device, ACPI_STATE_D3_COLD); |
806 | device->handle = NULL; | ||
782 | put_device(&device->dev); | 807 | put_device(&device->dev); |
783 | } | 808 | } |
784 | 809 | ||
@@ -1623,14 +1648,14 @@ static acpi_status acpi_bus_device_attach(acpi_handle handle, u32 lvl_not_used, | |||
1623 | * there has been a real error. There just have been no suitable ACPI objects | 1648 | * there has been a real error. There just have been no suitable ACPI objects |
1624 | * in the table trunk from which the kernel could create a device and add an | 1649 | * in the table trunk from which the kernel could create a device and add an |
1625 | * appropriate driver. | 1650 | * appropriate driver. |
1651 | * | ||
1652 | * Must be called under acpi_scan_lock. | ||
1626 | */ | 1653 | */ |
1627 | int acpi_bus_scan(acpi_handle handle) | 1654 | int acpi_bus_scan(acpi_handle handle) |
1628 | { | 1655 | { |
1629 | void *device = NULL; | 1656 | void *device = NULL; |
1630 | int error = 0; | 1657 | int error = 0; |
1631 | 1658 | ||
1632 | mutex_lock(&acpi_scan_lock); | ||
1633 | |||
1634 | if (ACPI_SUCCESS(acpi_bus_check_add(handle, 0, NULL, &device))) | 1659 | if (ACPI_SUCCESS(acpi_bus_check_add(handle, 0, NULL, &device))) |
1635 | acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, | 1660 | acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, |
1636 | acpi_bus_check_add, NULL, NULL, &device); | 1661 | acpi_bus_check_add, NULL, NULL, &device); |
@@ -1641,7 +1666,6 @@ int acpi_bus_scan(acpi_handle handle) | |||
1641 | acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, | 1666 | acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, |
1642 | acpi_bus_device_attach, NULL, NULL, NULL); | 1667 | acpi_bus_device_attach, NULL, NULL, NULL); |
1643 | 1668 | ||
1644 | mutex_unlock(&acpi_scan_lock); | ||
1645 | return error; | 1669 | return error; |
1646 | } | 1670 | } |
1647 | EXPORT_SYMBOL(acpi_bus_scan); | 1671 | EXPORT_SYMBOL(acpi_bus_scan); |
@@ -1678,7 +1702,13 @@ static acpi_status acpi_bus_remove(acpi_handle handle, u32 lvl_not_used, | |||
1678 | return AE_OK; | 1702 | return AE_OK; |
1679 | } | 1703 | } |
1680 | 1704 | ||
1681 | static void __acpi_bus_trim(struct acpi_device *start) | 1705 | /** |
1706 | * acpi_bus_trim - Remove ACPI device node and all of its descendants | ||
1707 | * @start: Root of the ACPI device nodes subtree to remove. | ||
1708 | * | ||
1709 | * Must be called under acpi_scan_lock. | ||
1710 | */ | ||
1711 | void acpi_bus_trim(struct acpi_device *start) | ||
1682 | { | 1712 | { |
1683 | /* | 1713 | /* |
1684 | * Execute acpi_bus_device_detach() as a post-order callback to detach | 1714 | * Execute acpi_bus_device_detach() as a post-order callback to detach |
@@ -1695,13 +1725,6 @@ static void __acpi_bus_trim(struct acpi_device *start) | |||
1695 | acpi_bus_remove, NULL, NULL); | 1725 | acpi_bus_remove, NULL, NULL); |
1696 | acpi_bus_remove(start->handle, 0, NULL, NULL); | 1726 | acpi_bus_remove(start->handle, 0, NULL, NULL); |
1697 | } | 1727 | } |
1698 | |||
1699 | void acpi_bus_trim(struct acpi_device *start) | ||
1700 | { | ||
1701 | mutex_lock(&acpi_scan_lock); | ||
1702 | __acpi_bus_trim(start); | ||
1703 | mutex_unlock(&acpi_scan_lock); | ||
1704 | } | ||
1705 | EXPORT_SYMBOL_GPL(acpi_bus_trim); | 1728 | EXPORT_SYMBOL_GPL(acpi_bus_trim); |
1706 | 1729 | ||
1707 | static int acpi_bus_scan_fixed(void) | 1730 | static int acpi_bus_scan_fixed(void) |
@@ -1758,23 +1781,27 @@ int __init acpi_scan_init(void) | |||
1758 | acpi_csrt_init(); | 1781 | acpi_csrt_init(); |
1759 | acpi_container_init(); | 1782 | acpi_container_init(); |
1760 | 1783 | ||
1784 | mutex_lock(&acpi_scan_lock); | ||
1761 | /* | 1785 | /* |
1762 | * Enumerate devices in the ACPI namespace. | 1786 | * Enumerate devices in the ACPI namespace. |
1763 | */ | 1787 | */ |
1764 | result = acpi_bus_scan(ACPI_ROOT_OBJECT); | 1788 | result = acpi_bus_scan(ACPI_ROOT_OBJECT); |
1765 | if (result) | 1789 | if (result) |
1766 | return result; | 1790 | goto out; |
1767 | 1791 | ||
1768 | result = acpi_bus_get_device(ACPI_ROOT_OBJECT, &acpi_root); | 1792 | result = acpi_bus_get_device(ACPI_ROOT_OBJECT, &acpi_root); |
1769 | if (result) | 1793 | if (result) |
1770 | return result; | 1794 | goto out; |
1771 | 1795 | ||
1772 | result = acpi_bus_scan_fixed(); | 1796 | result = acpi_bus_scan_fixed(); |
1773 | if (result) { | 1797 | if (result) { |
1774 | acpi_device_unregister(acpi_root); | 1798 | acpi_device_unregister(acpi_root); |
1775 | return result; | 1799 | goto out; |
1776 | } | 1800 | } |
1777 | 1801 | ||
1778 | acpi_update_all_gpes(); | 1802 | acpi_update_all_gpes(); |
1779 | return 0; | 1803 | |
1804 | out: | ||
1805 | mutex_unlock(&acpi_scan_lock); | ||
1806 | return result; | ||
1780 | } | 1807 | } |
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index d1a6f4a25da8..a951c22921d1 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c | |||
@@ -1218,6 +1218,8 @@ static void _handle_hotplug_event_bridge(struct work_struct *work) | |||
1218 | handle = hp_work->handle; | 1218 | handle = hp_work->handle; |
1219 | type = hp_work->type; | 1219 | type = hp_work->type; |
1220 | 1220 | ||
1221 | acpi_scan_lock_acquire(); | ||
1222 | |||
1221 | if (acpi_bus_get_device(handle, &device)) { | 1223 | if (acpi_bus_get_device(handle, &device)) { |
1222 | /* This bridge must have just been physically inserted */ | 1224 | /* This bridge must have just been physically inserted */ |
1223 | handle_bridge_insertion(handle, type); | 1225 | handle_bridge_insertion(handle, type); |
@@ -1295,6 +1297,7 @@ static void _handle_hotplug_event_bridge(struct work_struct *work) | |||
1295 | } | 1297 | } |
1296 | 1298 | ||
1297 | out: | 1299 | out: |
1300 | acpi_scan_lock_release(); | ||
1298 | kfree(hp_work); /* allocated in handle_hotplug_event_bridge */ | 1301 | kfree(hp_work); /* allocated in handle_hotplug_event_bridge */ |
1299 | } | 1302 | } |
1300 | 1303 | ||
@@ -1341,6 +1344,8 @@ static void _handle_hotplug_event_func(struct work_struct *work) | |||
1341 | 1344 | ||
1342 | func = (struct acpiphp_func *)context; | 1345 | func = (struct acpiphp_func *)context; |
1343 | 1346 | ||
1347 | acpi_scan_lock_acquire(); | ||
1348 | |||
1344 | switch (type) { | 1349 | switch (type) { |
1345 | case ACPI_NOTIFY_BUS_CHECK: | 1350 | case ACPI_NOTIFY_BUS_CHECK: |
1346 | /* bus re-enumerate */ | 1351 | /* bus re-enumerate */ |
@@ -1371,6 +1376,7 @@ static void _handle_hotplug_event_func(struct work_struct *work) | |||
1371 | break; | 1376 | break; |
1372 | } | 1377 | } |
1373 | 1378 | ||
1379 | acpi_scan_lock_release(); | ||
1374 | kfree(hp_work); /* allocated in handle_hotplug_event_func */ | 1380 | kfree(hp_work); /* allocated in handle_hotplug_event_func */ |
1375 | } | 1381 | } |
1376 | 1382 | ||
diff --git a/drivers/pci/hotplug/sgi_hotplug.c b/drivers/pci/hotplug/sgi_hotplug.c index ae606b3e991e..574421bc2fa6 100644 --- a/drivers/pci/hotplug/sgi_hotplug.c +++ b/drivers/pci/hotplug/sgi_hotplug.c | |||
@@ -425,6 +425,7 @@ static int enable_slot(struct hotplug_slot *bss_hotplug_slot) | |||
425 | pdevice = NULL; | 425 | pdevice = NULL; |
426 | } | 426 | } |
427 | 427 | ||
428 | acpi_scan_lock_acquire(); | ||
428 | /* | 429 | /* |
429 | * Walk the rootbus node's immediate children looking for | 430 | * Walk the rootbus node's immediate children looking for |
430 | * the slot's device node(s). There can be more than | 431 | * the slot's device node(s). There can be more than |
@@ -458,6 +459,7 @@ static int enable_slot(struct hotplug_slot *bss_hotplug_slot) | |||
458 | } | 459 | } |
459 | } | 460 | } |
460 | } | 461 | } |
462 | acpi_scan_lock_release(); | ||
461 | } | 463 | } |
462 | 464 | ||
463 | /* Call the driver for the new device */ | 465 | /* Call the driver for the new device */ |
@@ -508,6 +510,7 @@ static int disable_slot(struct hotplug_slot *bss_hotplug_slot) | |||
508 | /* Get the rootbus node pointer */ | 510 | /* Get the rootbus node pointer */ |
509 | phandle = PCI_CONTROLLER(slot->pci_bus)->acpi_handle; | 511 | phandle = PCI_CONTROLLER(slot->pci_bus)->acpi_handle; |
510 | 512 | ||
513 | acpi_scan_lock_acquire(); | ||
511 | /* | 514 | /* |
512 | * Walk the rootbus node's immediate children looking for | 515 | * Walk the rootbus node's immediate children looking for |
513 | * the slot's device node(s). There can be more than | 516 | * the slot's device node(s). There can be more than |
@@ -538,7 +541,7 @@ static int disable_slot(struct hotplug_slot *bss_hotplug_slot) | |||
538 | acpi_bus_trim(device); | 541 | acpi_bus_trim(device); |
539 | } | 542 | } |
540 | } | 543 | } |
541 | 544 | acpi_scan_lock_release(); | |
542 | } | 545 | } |
543 | 546 | ||
544 | /* Free the SN resources assigned to the Linux device.*/ | 547 | /* Free the SN resources assigned to the Linux device.*/ |
diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index 41850cb21730..227ba7dc293d 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h | |||
@@ -395,6 +395,9 @@ int acpi_bus_receive_event(struct acpi_bus_event *event); | |||
395 | static inline int acpi_bus_generate_proc_event(struct acpi_device *device, u8 type, int data) | 395 | static inline int acpi_bus_generate_proc_event(struct acpi_device *device, u8 type, int data) |
396 | { return 0; } | 396 | { return 0; } |
397 | #endif | 397 | #endif |
398 | |||
399 | void acpi_scan_lock_acquire(void); | ||
400 | void acpi_scan_lock_release(void); | ||
398 | int acpi_scan_add_handler(struct acpi_scan_handler *handler); | 401 | int acpi_scan_add_handler(struct acpi_scan_handler *handler); |
399 | int acpi_bus_register_driver(struct acpi_driver *driver); | 402 | int acpi_bus_register_driver(struct acpi_driver *driver); |
400 | void acpi_bus_unregister_driver(struct acpi_driver *driver); | 403 | void acpi_bus_unregister_driver(struct acpi_driver *driver); |