aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>2013-02-13 08:36:47 -0500
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2013-02-13 08:36:47 -0500
commit3757b94802fb65d8f696597a74053cf21738da0b (patch)
tree78a3a00dbd82fab5e30a46699f83a3e492604e86
parent64fd7401c5e4cf7c64452ecd9b700a55a5ebea50 (diff)
ACPI / hotplug: Fix concurrency issues and memory leaks
This changeset is aimed at fixing a few different but related problems in the ACPI hotplug infrastructure. First of all, since notify handlers may be run in parallel with acpi_bus_scan(), acpi_bus_trim() and acpi_bus_hot_remove_device() and some of them are installed for ACPI handles that have no struct acpi_device objects attached (i.e. before those objects are created), those notify handlers have to take acpi_scan_lock to prevent races from taking place (e.g. a struct acpi_device is found to be present for the given ACPI handle, but right after that it is removed by acpi_bus_trim() running in parallel to the given notify handler). Moreover, since some of them call acpi_bus_scan() and acpi_bus_trim(), this leads to the conclusion that acpi_scan_lock should be acquired by the callers of these two funtions rather by these functions themselves. For these reasons, make all notify handlers that can handle device addition and eject events take acpi_scan_lock and remove the acpi_scan_lock locking from acpi_bus_scan() and acpi_bus_trim(). Accordingly, update all of their users to make sure that they are always called under acpi_scan_lock. Furthermore, since eject operations are carried out asynchronously with respect to the notify events that trigger them, with the help of acpi_bus_hot_remove_device(), even if notify handlers take the ACPI scan lock, it still is possible that, for example, acpi_bus_trim() will run between acpi_bus_hot_remove_device() and the notify handler that scheduled its execution and that acpi_bus_trim() will remove the device node passed to acpi_bus_hot_remove_device() for ejection. In that case, the struct acpi_device object obtained by acpi_bus_hot_remove_device() will be invalid and not-so-funny things will ensue. To protect agaist that, make the users of acpi_bus_hot_remove_device() run get_device() on ACPI device node objects that are about to be passed to it and make acpi_bus_hot_remove_device() run put_device() on them and check if their ACPI handles are not NULL (make acpi_device_unregister() clear the device nodes' ACPI handles for that check to work). Finally, observe that acpi_os_hotplug_execute() actually can fail, in which case its caller ought to free memory allocated for the context object to prevent leaks from happening. It also needs to run put_device() on the device node that it ran get_device() on previously in that case. Modify the code accordingly. Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Acked-by: Yinghai Lu <yinghai@kernel.org>
-rw-r--r--drivers/acpi/acpi_memhotplug.c56
-rw-r--r--drivers/acpi/container.c12
-rw-r--r--drivers/acpi/dock.c19
-rw-r--r--drivers/acpi/processor_driver.c24
-rw-r--r--drivers/acpi/scan.c69
-rw-r--r--drivers/pci/hotplug/acpiphp_glue.c6
-rw-r--r--drivers/pci/hotplug/sgi_hotplug.c5
-rw-r--r--include/acpi/acpi_bus.h3
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
156static int 156static int acpi_memory_get_device(acpi_handle handle,
157acpi_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
191static int acpi_memory_check_device(struct acpi_memory_device *mem_device) 198static 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
366static void acpi_memory_device_free(struct acpi_memory_device *mem_device) 384static 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
147static bool is_container(acpi_handle handle) 151static 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
757static acpi_status is_processor_device(acpi_handle handle) 767static 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
45void acpi_scan_lock_acquire(void)
46{
47 mutex_lock(&acpi_scan_lock);
48}
49EXPORT_SYMBOL_GPL(acpi_scan_lock_acquire);
50
51void acpi_scan_lock_release(void)
52{
53 mutex_unlock(&acpi_scan_lock);
54}
55EXPORT_SYMBOL_GPL(acpi_scan_lock_release);
56
45int acpi_scan_add_handler(struct acpi_scan_handler *handler) 57int 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}
96static DEVICE_ATTR(modalias, 0444, acpi_device_modalias_show, NULL); 108static DEVICE_ATTR(modalias, 0444, acpi_device_modalias_show, NULL);
97 109
98static 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 */
108void acpi_bus_hot_remove_device(void *context) 118void 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 }
228err: 252err:
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 */
1627int acpi_bus_scan(acpi_handle handle) 1654int 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}
1647EXPORT_SYMBOL(acpi_bus_scan); 1671EXPORT_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
1681static 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 */
1711void 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
1699void 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}
1705EXPORT_SYMBOL_GPL(acpi_bus_trim); 1728EXPORT_SYMBOL_GPL(acpi_bus_trim);
1706 1729
1707static int acpi_bus_scan_fixed(void) 1730static 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
1297out: 1299out:
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);
395static inline int acpi_bus_generate_proc_event(struct acpi_device *device, u8 type, int data) 395static 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
399void acpi_scan_lock_acquire(void);
400void acpi_scan_lock_release(void);
398int acpi_scan_add_handler(struct acpi_scan_handler *handler); 401int acpi_scan_add_handler(struct acpi_scan_handler *handler);
399int acpi_bus_register_driver(struct acpi_driver *driver); 402int acpi_bus_register_driver(struct acpi_driver *driver);
400void acpi_bus_unregister_driver(struct acpi_driver *driver); 403void acpi_bus_unregister_driver(struct acpi_driver *driver);