diff options
Diffstat (limited to 'drivers/acpi/scan.c')
-rw-r--r-- | drivers/acpi/scan.c | 623 |
1 files changed, 388 insertions, 235 deletions
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index fd39459926b1..57b053f424d1 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c | |||
@@ -12,13 +12,12 @@ | |||
12 | #include <linux/dmi.h> | 12 | #include <linux/dmi.h> |
13 | #include <linux/nls.h> | 13 | #include <linux/nls.h> |
14 | 14 | ||
15 | #include <acpi/acpi_drivers.h> | 15 | #include <asm/pgtable.h> |
16 | 16 | ||
17 | #include "internal.h" | 17 | #include "internal.h" |
18 | 18 | ||
19 | #define _COMPONENT ACPI_BUS_COMPONENT | 19 | #define _COMPONENT ACPI_BUS_COMPONENT |
20 | ACPI_MODULE_NAME("scan"); | 20 | ACPI_MODULE_NAME("scan"); |
21 | #define STRUCT_TO_INT(s) (*((int*)&s)) | ||
22 | extern struct acpi_device *acpi_root; | 21 | extern struct acpi_device *acpi_root; |
23 | 22 | ||
24 | #define ACPI_BUS_CLASS "system_bus" | 23 | #define ACPI_BUS_CLASS "system_bus" |
@@ -27,6 +26,8 @@ extern struct acpi_device *acpi_root; | |||
27 | 26 | ||
28 | #define ACPI_IS_ROOT_DEVICE(device) (!(device)->parent) | 27 | #define ACPI_IS_ROOT_DEVICE(device) (!(device)->parent) |
29 | 28 | ||
29 | #define INVALID_ACPI_HANDLE ((acpi_handle)empty_zero_page) | ||
30 | |||
30 | /* | 31 | /* |
31 | * If set, devices will be hot-removed even if they cannot be put offline | 32 | * If set, devices will be hot-removed even if they cannot be put offline |
32 | * gracefully (from the kernel's standpoint). | 33 | * gracefully (from the kernel's standpoint). |
@@ -85,6 +86,9 @@ int acpi_scan_add_handler_with_hotplug(struct acpi_scan_handler *handler, | |||
85 | * Creates hid/cid(s) string needed for modalias and uevent | 86 | * Creates hid/cid(s) string needed for modalias and uevent |
86 | * e.g. on a device with hid:IBM0001 and cid:ACPI0001 you get: | 87 | * e.g. on a device with hid:IBM0001 and cid:ACPI0001 you get: |
87 | * char *modalias: "acpi:IBM0001:ACPI0001" | 88 | * char *modalias: "acpi:IBM0001:ACPI0001" |
89 | * Return: 0: no _HID and no _CID | ||
90 | * -EINVAL: output error | ||
91 | * -ENOMEM: output is truncated | ||
88 | */ | 92 | */ |
89 | static int create_modalias(struct acpi_device *acpi_dev, char *modalias, | 93 | static int create_modalias(struct acpi_device *acpi_dev, char *modalias, |
90 | int size) | 94 | int size) |
@@ -101,8 +105,10 @@ static int create_modalias(struct acpi_device *acpi_dev, char *modalias, | |||
101 | 105 | ||
102 | list_for_each_entry(id, &acpi_dev->pnp.ids, list) { | 106 | list_for_each_entry(id, &acpi_dev->pnp.ids, list) { |
103 | count = snprintf(&modalias[len], size, "%s:", id->id); | 107 | count = snprintf(&modalias[len], size, "%s:", id->id); |
104 | if (count < 0 || count >= size) | 108 | if (count < 0) |
105 | return -EINVAL; | 109 | return EINVAL; |
110 | if (count >= size) | ||
111 | return -ENOMEM; | ||
106 | len += count; | 112 | len += count; |
107 | size -= count; | 113 | size -= count; |
108 | } | 114 | } |
@@ -111,20 +117,96 @@ static int create_modalias(struct acpi_device *acpi_dev, char *modalias, | |||
111 | return len; | 117 | return len; |
112 | } | 118 | } |
113 | 119 | ||
120 | /* | ||
121 | * Creates uevent modalias field for ACPI enumerated devices. | ||
122 | * Because the other buses does not support ACPI HIDs & CIDs. | ||
123 | * e.g. for a device with hid:IBM0001 and cid:ACPI0001 you get: | ||
124 | * "acpi:IBM0001:ACPI0001" | ||
125 | */ | ||
126 | int acpi_device_uevent_modalias(struct device *dev, struct kobj_uevent_env *env) | ||
127 | { | ||
128 | struct acpi_device *acpi_dev; | ||
129 | int len; | ||
130 | |||
131 | acpi_dev = ACPI_COMPANION(dev); | ||
132 | if (!acpi_dev) | ||
133 | return -ENODEV; | ||
134 | |||
135 | /* Fall back to bus specific way of modalias exporting */ | ||
136 | if (list_empty(&acpi_dev->pnp.ids)) | ||
137 | return -ENODEV; | ||
138 | |||
139 | if (add_uevent_var(env, "MODALIAS=")) | ||
140 | return -ENOMEM; | ||
141 | len = create_modalias(acpi_dev, &env->buf[env->buflen - 1], | ||
142 | sizeof(env->buf) - env->buflen); | ||
143 | if (len <= 0) | ||
144 | return len; | ||
145 | env->buflen += len; | ||
146 | return 0; | ||
147 | } | ||
148 | EXPORT_SYMBOL_GPL(acpi_device_uevent_modalias); | ||
149 | |||
150 | /* | ||
151 | * Creates modalias sysfs attribute for ACPI enumerated devices. | ||
152 | * Because the other buses does not support ACPI HIDs & CIDs. | ||
153 | * e.g. for a device with hid:IBM0001 and cid:ACPI0001 you get: | ||
154 | * "acpi:IBM0001:ACPI0001" | ||
155 | */ | ||
156 | int acpi_device_modalias(struct device *dev, char *buf, int size) | ||
157 | { | ||
158 | struct acpi_device *acpi_dev; | ||
159 | int len; | ||
160 | |||
161 | acpi_dev = ACPI_COMPANION(dev); | ||
162 | if (!acpi_dev) | ||
163 | return -ENODEV; | ||
164 | |||
165 | /* Fall back to bus specific way of modalias exporting */ | ||
166 | if (list_empty(&acpi_dev->pnp.ids)) | ||
167 | return -ENODEV; | ||
168 | |||
169 | len = create_modalias(acpi_dev, buf, size -1); | ||
170 | if (len <= 0) | ||
171 | return len; | ||
172 | buf[len++] = '\n'; | ||
173 | return len; | ||
174 | } | ||
175 | EXPORT_SYMBOL_GPL(acpi_device_modalias); | ||
176 | |||
114 | static ssize_t | 177 | static ssize_t |
115 | acpi_device_modalias_show(struct device *dev, struct device_attribute *attr, char *buf) { | 178 | acpi_device_modalias_show(struct device *dev, struct device_attribute *attr, char *buf) { |
116 | struct acpi_device *acpi_dev = to_acpi_device(dev); | 179 | struct acpi_device *acpi_dev = to_acpi_device(dev); |
117 | int len; | 180 | int len; |
118 | 181 | ||
119 | /* Device has no HID and no CID or string is >1024 */ | ||
120 | len = create_modalias(acpi_dev, buf, 1024); | 182 | len = create_modalias(acpi_dev, buf, 1024); |
121 | if (len <= 0) | 183 | if (len <= 0) |
122 | return 0; | 184 | return len; |
123 | buf[len++] = '\n'; | 185 | buf[len++] = '\n'; |
124 | return len; | 186 | return len; |
125 | } | 187 | } |
126 | static DEVICE_ATTR(modalias, 0444, acpi_device_modalias_show, NULL); | 188 | static DEVICE_ATTR(modalias, 0444, acpi_device_modalias_show, NULL); |
127 | 189 | ||
190 | bool acpi_scan_is_offline(struct acpi_device *adev, bool uevent) | ||
191 | { | ||
192 | struct acpi_device_physical_node *pn; | ||
193 | bool offline = true; | ||
194 | |||
195 | mutex_lock(&adev->physical_node_lock); | ||
196 | |||
197 | list_for_each_entry(pn, &adev->physical_node_list, node) | ||
198 | if (device_supports_offline(pn->dev) && !pn->dev->offline) { | ||
199 | if (uevent) | ||
200 | kobject_uevent(&pn->dev->kobj, KOBJ_CHANGE); | ||
201 | |||
202 | offline = false; | ||
203 | break; | ||
204 | } | ||
205 | |||
206 | mutex_unlock(&adev->physical_node_lock); | ||
207 | return offline; | ||
208 | } | ||
209 | |||
128 | static acpi_status acpi_bus_offline(acpi_handle handle, u32 lvl, void *data, | 210 | static acpi_status acpi_bus_offline(acpi_handle handle, u32 lvl, void *data, |
129 | void **ret_p) | 211 | void **ret_p) |
130 | { | 212 | { |
@@ -195,19 +277,11 @@ static acpi_status acpi_bus_online(acpi_handle handle, u32 lvl, void *data, | |||
195 | return AE_OK; | 277 | return AE_OK; |
196 | } | 278 | } |
197 | 279 | ||
198 | static int acpi_scan_hot_remove(struct acpi_device *device) | 280 | static int acpi_scan_try_to_offline(struct acpi_device *device) |
199 | { | 281 | { |
200 | acpi_handle handle = device->handle; | 282 | acpi_handle handle = device->handle; |
201 | struct device *errdev; | 283 | struct device *errdev = NULL; |
202 | acpi_status status; | 284 | acpi_status status; |
203 | unsigned long long sta; | ||
204 | |||
205 | /* If there is no handle, the device node has been unregistered. */ | ||
206 | if (!handle) { | ||
207 | dev_dbg(&device->dev, "ACPI handle missing\n"); | ||
208 | put_device(&device->dev); | ||
209 | return -EINVAL; | ||
210 | } | ||
211 | 285 | ||
212 | /* | 286 | /* |
213 | * Carry out two passes here and ignore errors in the first pass, | 287 | * Carry out two passes here and ignore errors in the first pass, |
@@ -218,7 +292,6 @@ static int acpi_scan_hot_remove(struct acpi_device *device) | |||
218 | * | 292 | * |
219 | * If the first pass is successful, the second one isn't needed, though. | 293 | * If the first pass is successful, the second one isn't needed, though. |
220 | */ | 294 | */ |
221 | errdev = NULL; | ||
222 | status = acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, | 295 | status = acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, |
223 | NULL, acpi_bus_offline, (void *)false, | 296 | NULL, acpi_bus_offline, (void *)false, |
224 | (void **)&errdev); | 297 | (void **)&errdev); |
@@ -226,7 +299,6 @@ static int acpi_scan_hot_remove(struct acpi_device *device) | |||
226 | dev_warn(errdev, "Offline disabled.\n"); | 299 | dev_warn(errdev, "Offline disabled.\n"); |
227 | acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, | 300 | acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, |
228 | acpi_bus_online, NULL, NULL, NULL); | 301 | acpi_bus_online, NULL, NULL, NULL); |
229 | put_device(&device->dev); | ||
230 | return -EPERM; | 302 | return -EPERM; |
231 | } | 303 | } |
232 | acpi_bus_offline(handle, 0, (void *)false, (void **)&errdev); | 304 | acpi_bus_offline(handle, 0, (void *)false, (void **)&errdev); |
@@ -245,20 +317,32 @@ static int acpi_scan_hot_remove(struct acpi_device *device) | |||
245 | acpi_walk_namespace(ACPI_TYPE_ANY, handle, | 317 | acpi_walk_namespace(ACPI_TYPE_ANY, handle, |
246 | ACPI_UINT32_MAX, acpi_bus_online, | 318 | ACPI_UINT32_MAX, acpi_bus_online, |
247 | NULL, NULL, NULL); | 319 | NULL, NULL, NULL); |
248 | put_device(&device->dev); | ||
249 | return -EBUSY; | 320 | return -EBUSY; |
250 | } | 321 | } |
251 | } | 322 | } |
323 | return 0; | ||
324 | } | ||
325 | |||
326 | static int acpi_scan_hot_remove(struct acpi_device *device) | ||
327 | { | ||
328 | acpi_handle handle = device->handle; | ||
329 | unsigned long long sta; | ||
330 | acpi_status status; | ||
331 | |||
332 | if (device->handler->hotplug.demand_offline && !acpi_force_hot_remove) { | ||
333 | if (!acpi_scan_is_offline(device, true)) | ||
334 | return -EBUSY; | ||
335 | } else { | ||
336 | int error = acpi_scan_try_to_offline(device); | ||
337 | if (error) | ||
338 | return error; | ||
339 | } | ||
252 | 340 | ||
253 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | 341 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, |
254 | "Hot-removing device %s...\n", dev_name(&device->dev))); | 342 | "Hot-removing device %s...\n", dev_name(&device->dev))); |
255 | 343 | ||
256 | acpi_bus_trim(device); | 344 | acpi_bus_trim(device); |
257 | 345 | ||
258 | /* Device node has been unregistered. */ | ||
259 | put_device(&device->dev); | ||
260 | device = NULL; | ||
261 | |||
262 | acpi_evaluate_lck(handle, 0); | 346 | acpi_evaluate_lck(handle, 0); |
263 | /* | 347 | /* |
264 | * TBD: _EJD support. | 348 | * TBD: _EJD support. |
@@ -285,115 +369,126 @@ static int acpi_scan_hot_remove(struct acpi_device *device) | |||
285 | return 0; | 369 | return 0; |
286 | } | 370 | } |
287 | 371 | ||
288 | void acpi_bus_device_eject(void *data, u32 ost_src) | 372 | static int acpi_scan_device_not_present(struct acpi_device *adev) |
289 | { | 373 | { |
290 | struct acpi_device *device = data; | 374 | if (!acpi_device_enumerated(adev)) { |
291 | acpi_handle handle = device->handle; | 375 | dev_warn(&adev->dev, "Still not present\n"); |
292 | u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; | 376 | return -EALREADY; |
293 | int error; | 377 | } |
378 | acpi_bus_trim(adev); | ||
379 | return 0; | ||
380 | } | ||
294 | 381 | ||
295 | lock_device_hotplug(); | 382 | static int acpi_scan_device_check(struct acpi_device *adev) |
296 | mutex_lock(&acpi_scan_lock); | 383 | { |
384 | int error; | ||
297 | 385 | ||
298 | if (ost_src == ACPI_NOTIFY_EJECT_REQUEST) | 386 | acpi_bus_get_status(adev); |
299 | acpi_evaluate_hotplug_ost(handle, ACPI_NOTIFY_EJECT_REQUEST, | 387 | if (adev->status.present || adev->status.functional) { |
300 | ACPI_OST_SC_EJECT_IN_PROGRESS, NULL); | 388 | /* |
389 | * This function is only called for device objects for which | ||
390 | * matching scan handlers exist. The only situation in which | ||
391 | * the scan handler is not attached to this device object yet | ||
392 | * is when the device has just appeared (either it wasn't | ||
393 | * present at all before or it was removed and then added | ||
394 | * again). | ||
395 | */ | ||
396 | if (adev->handler) { | ||
397 | dev_warn(&adev->dev, "Already enumerated\n"); | ||
398 | return -EALREADY; | ||
399 | } | ||
400 | error = acpi_bus_scan(adev->handle); | ||
401 | if (error) { | ||
402 | dev_warn(&adev->dev, "Namespace scan failure\n"); | ||
403 | return error; | ||
404 | } | ||
405 | if (!adev->handler) { | ||
406 | dev_warn(&adev->dev, "Enumeration failure\n"); | ||
407 | error = -ENODEV; | ||
408 | } | ||
409 | } else { | ||
410 | error = acpi_scan_device_not_present(adev); | ||
411 | } | ||
412 | return error; | ||
413 | } | ||
301 | 414 | ||
302 | if (device->handler && device->handler->hotplug.mode == AHM_CONTAINER) | 415 | static int acpi_scan_bus_check(struct acpi_device *adev) |
303 | kobject_uevent(&device->dev.kobj, KOBJ_OFFLINE); | 416 | { |
417 | struct acpi_scan_handler *handler = adev->handler; | ||
418 | struct acpi_device *child; | ||
419 | int error; | ||
304 | 420 | ||
305 | error = acpi_scan_hot_remove(device); | 421 | acpi_bus_get_status(adev); |
306 | if (error == -EPERM) { | 422 | if (!(adev->status.present || adev->status.functional)) { |
307 | goto err_support; | 423 | acpi_scan_device_not_present(adev); |
308 | } else if (error) { | 424 | return 0; |
309 | goto err_out; | ||
310 | } | 425 | } |
426 | if (handler && handler->hotplug.scan_dependent) | ||
427 | return handler->hotplug.scan_dependent(adev); | ||
311 | 428 | ||
312 | out: | 429 | error = acpi_bus_scan(adev->handle); |
313 | mutex_unlock(&acpi_scan_lock); | 430 | if (error) { |
314 | unlock_device_hotplug(); | 431 | dev_warn(&adev->dev, "Namespace scan failure\n"); |
315 | return; | 432 | return error; |
316 | 433 | } | |
317 | err_support: | 434 | list_for_each_entry(child, &adev->children, node) { |
318 | ost_code = ACPI_OST_SC_EJECT_NOT_SUPPORTED; | 435 | error = acpi_scan_bus_check(child); |
319 | err_out: | 436 | if (error) |
320 | acpi_evaluate_hotplug_ost(handle, ost_src, ost_code, NULL); | 437 | return error; |
321 | goto out; | 438 | } |
439 | return 0; | ||
322 | } | 440 | } |
323 | 441 | ||
324 | static void acpi_scan_bus_device_check(void *data, u32 ost_source) | 442 | static void acpi_device_hotplug(void *data, u32 src) |
325 | { | 443 | { |
326 | acpi_handle handle = data; | ||
327 | struct acpi_device *device = NULL; | ||
328 | u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; | 444 | u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; |
445 | struct acpi_device *adev = data; | ||
329 | int error; | 446 | int error; |
330 | 447 | ||
331 | lock_device_hotplug(); | 448 | lock_device_hotplug(); |
332 | mutex_lock(&acpi_scan_lock); | 449 | mutex_lock(&acpi_scan_lock); |
333 | 450 | ||
334 | if (ost_source != ACPI_NOTIFY_BUS_CHECK) { | 451 | /* |
335 | acpi_bus_get_device(handle, &device); | 452 | * The device object's ACPI handle cannot become invalid as long as we |
336 | if (device) { | 453 | * are holding acpi_scan_lock, but it may have become invalid before |
337 | dev_warn(&device->dev, "Attempt to re-insert\n"); | 454 | * that lock was acquired. |
338 | goto out; | 455 | */ |
339 | } | 456 | if (adev->handle == INVALID_ACPI_HANDLE) |
340 | } | ||
341 | error = acpi_bus_scan(handle); | ||
342 | if (error) { | ||
343 | acpi_handle_warn(handle, "Namespace scan failure\n"); | ||
344 | goto out; | ||
345 | } | ||
346 | error = acpi_bus_get_device(handle, &device); | ||
347 | if (error) { | ||
348 | acpi_handle_warn(handle, "Missing device node object\n"); | ||
349 | goto out; | 457 | goto out; |
350 | } | ||
351 | ost_code = ACPI_OST_SC_SUCCESS; | ||
352 | if (device->handler && device->handler->hotplug.mode == AHM_CONTAINER) | ||
353 | kobject_uevent(&device->dev.kobj, KOBJ_ONLINE); | ||
354 | 458 | ||
355 | out: | 459 | switch (src) { |
356 | acpi_evaluate_hotplug_ost(handle, ost_source, ost_code, NULL); | ||
357 | mutex_unlock(&acpi_scan_lock); | ||
358 | unlock_device_hotplug(); | ||
359 | } | ||
360 | |||
361 | static void acpi_hotplug_unsupported(acpi_handle handle, u32 type) | ||
362 | { | ||
363 | u32 ost_status; | ||
364 | |||
365 | switch (type) { | ||
366 | case ACPI_NOTIFY_BUS_CHECK: | 460 | case ACPI_NOTIFY_BUS_CHECK: |
367 | acpi_handle_debug(handle, | 461 | error = acpi_scan_bus_check(adev); |
368 | "ACPI_NOTIFY_BUS_CHECK event: unsupported\n"); | ||
369 | ost_status = ACPI_OST_SC_INSERT_NOT_SUPPORTED; | ||
370 | break; | 462 | break; |
371 | case ACPI_NOTIFY_DEVICE_CHECK: | 463 | case ACPI_NOTIFY_DEVICE_CHECK: |
372 | acpi_handle_debug(handle, | 464 | error = acpi_scan_device_check(adev); |
373 | "ACPI_NOTIFY_DEVICE_CHECK event: unsupported\n"); | ||
374 | ost_status = ACPI_OST_SC_INSERT_NOT_SUPPORTED; | ||
375 | break; | 465 | break; |
376 | case ACPI_NOTIFY_EJECT_REQUEST: | 466 | case ACPI_NOTIFY_EJECT_REQUEST: |
377 | acpi_handle_debug(handle, | 467 | case ACPI_OST_EC_OSPM_EJECT: |
378 | "ACPI_NOTIFY_EJECT_REQUEST event: unsupported\n"); | 468 | error = acpi_scan_hot_remove(adev); |
379 | ost_status = ACPI_OST_SC_EJECT_NOT_SUPPORTED; | ||
380 | break; | 469 | break; |
381 | default: | 470 | default: |
382 | /* non-hotplug event; possibly handled by other handler */ | 471 | error = -EINVAL; |
383 | return; | 472 | break; |
384 | } | 473 | } |
474 | if (!error) | ||
475 | ost_code = ACPI_OST_SC_SUCCESS; | ||
385 | 476 | ||
386 | acpi_evaluate_hotplug_ost(handle, type, ost_status, NULL); | 477 | out: |
478 | acpi_evaluate_hotplug_ost(adev->handle, src, ost_code, NULL); | ||
479 | put_device(&adev->dev); | ||
480 | mutex_unlock(&acpi_scan_lock); | ||
481 | unlock_device_hotplug(); | ||
387 | } | 482 | } |
388 | 483 | ||
389 | static void acpi_hotplug_notify_cb(acpi_handle handle, u32 type, void *data) | 484 | static void acpi_hotplug_notify_cb(acpi_handle handle, u32 type, void *data) |
390 | { | 485 | { |
391 | struct acpi_scan_handler *handler = data; | 486 | u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; |
392 | struct acpi_device *adev; | 487 | struct acpi_device *adev; |
393 | acpi_status status; | 488 | acpi_status status; |
394 | 489 | ||
395 | if (!handler->hotplug.enabled) | 490 | if (acpi_bus_get_device(handle, &adev)) |
396 | return acpi_hotplug_unsupported(handle, type); | 491 | goto err_out; |
397 | 492 | ||
398 | switch (type) { | 493 | switch (type) { |
399 | case ACPI_NOTIFY_BUS_CHECK: | 494 | case ACPI_NOTIFY_BUS_CHECK: |
@@ -404,27 +499,30 @@ static void acpi_hotplug_notify_cb(acpi_handle handle, u32 type, void *data) | |||
404 | break; | 499 | break; |
405 | case ACPI_NOTIFY_EJECT_REQUEST: | 500 | case ACPI_NOTIFY_EJECT_REQUEST: |
406 | acpi_handle_debug(handle, "ACPI_NOTIFY_EJECT_REQUEST event\n"); | 501 | acpi_handle_debug(handle, "ACPI_NOTIFY_EJECT_REQUEST event\n"); |
407 | if (acpi_bus_get_device(handle, &adev)) | 502 | if (!adev->handler) |
408 | goto err_out; | 503 | goto err_out; |
409 | 504 | ||
410 | get_device(&adev->dev); | 505 | if (!adev->handler->hotplug.enabled) { |
411 | status = acpi_hotplug_execute(acpi_bus_device_eject, adev, type); | 506 | acpi_handle_err(handle, "Eject disabled\n"); |
412 | if (ACPI_SUCCESS(status)) | 507 | ost_code = ACPI_OST_SC_EJECT_NOT_SUPPORTED; |
413 | return; | 508 | goto err_out; |
414 | 509 | } | |
415 | put_device(&adev->dev); | 510 | acpi_evaluate_hotplug_ost(handle, ACPI_NOTIFY_EJECT_REQUEST, |
416 | goto err_out; | 511 | ACPI_OST_SC_EJECT_IN_PROGRESS, NULL); |
512 | break; | ||
417 | default: | 513 | default: |
418 | /* non-hotplug event; possibly handled by other handler */ | 514 | /* non-hotplug event; possibly handled by other handler */ |
419 | return; | 515 | return; |
420 | } | 516 | } |
421 | status = acpi_hotplug_execute(acpi_scan_bus_device_check, handle, type); | 517 | get_device(&adev->dev); |
518 | status = acpi_hotplug_execute(acpi_device_hotplug, adev, type); | ||
422 | if (ACPI_SUCCESS(status)) | 519 | if (ACPI_SUCCESS(status)) |
423 | return; | 520 | return; |
424 | 521 | ||
522 | put_device(&adev->dev); | ||
523 | |||
425 | err_out: | 524 | err_out: |
426 | acpi_evaluate_hotplug_ost(handle, type, | 525 | acpi_evaluate_hotplug_ost(handle, type, ost_code, NULL); |
427 | ACPI_OST_SC_NON_SPECIFIC_FAILURE, NULL); | ||
428 | } | 526 | } |
429 | 527 | ||
430 | static ssize_t real_power_state_show(struct device *dev, | 528 | static ssize_t real_power_state_show(struct device *dev, |
@@ -475,7 +573,7 @@ acpi_eject_store(struct device *d, struct device_attribute *attr, | |||
475 | acpi_evaluate_hotplug_ost(acpi_device->handle, ACPI_OST_EC_OSPM_EJECT, | 573 | acpi_evaluate_hotplug_ost(acpi_device->handle, ACPI_OST_EC_OSPM_EJECT, |
476 | ACPI_OST_SC_EJECT_IN_PROGRESS, NULL); | 574 | ACPI_OST_SC_EJECT_IN_PROGRESS, NULL); |
477 | get_device(&acpi_device->dev); | 575 | get_device(&acpi_device->dev); |
478 | status = acpi_hotplug_execute(acpi_bus_device_eject, acpi_device, | 576 | status = acpi_hotplug_execute(acpi_device_hotplug, acpi_device, |
479 | ACPI_OST_EC_OSPM_EJECT); | 577 | ACPI_OST_EC_OSPM_EJECT); |
480 | if (ACPI_SUCCESS(status)) | 578 | if (ACPI_SUCCESS(status)) |
481 | return count; | 579 | return count; |
@@ -567,6 +665,20 @@ acpi_device_sun_show(struct device *dev, struct device_attribute *attr, | |||
567 | } | 665 | } |
568 | static DEVICE_ATTR(sun, 0444, acpi_device_sun_show, NULL); | 666 | static DEVICE_ATTR(sun, 0444, acpi_device_sun_show, NULL); |
569 | 667 | ||
668 | static ssize_t status_show(struct device *dev, struct device_attribute *attr, | ||
669 | char *buf) { | ||
670 | struct acpi_device *acpi_dev = to_acpi_device(dev); | ||
671 | acpi_status status; | ||
672 | unsigned long long sta; | ||
673 | |||
674 | status = acpi_evaluate_integer(acpi_dev->handle, "_STA", NULL, &sta); | ||
675 | if (ACPI_FAILURE(status)) | ||
676 | return -ENODEV; | ||
677 | |||
678 | return sprintf(buf, "%llu\n", sta); | ||
679 | } | ||
680 | static DEVICE_ATTR_RO(status); | ||
681 | |||
570 | static int acpi_device_setup_files(struct acpi_device *dev) | 682 | static int acpi_device_setup_files(struct acpi_device *dev) |
571 | { | 683 | { |
572 | struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; | 684 | struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; |
@@ -622,6 +734,12 @@ static int acpi_device_setup_files(struct acpi_device *dev) | |||
622 | dev->pnp.sun = (unsigned long)-1; | 734 | dev->pnp.sun = (unsigned long)-1; |
623 | } | 735 | } |
624 | 736 | ||
737 | if (acpi_has_method(dev->handle, "_STA")) { | ||
738 | result = device_create_file(&dev->dev, &dev_attr_status); | ||
739 | if (result) | ||
740 | goto end; | ||
741 | } | ||
742 | |||
625 | /* | 743 | /* |
626 | * If device has _EJ0, 'eject' file is created that is used to trigger | 744 | * If device has _EJ0, 'eject' file is created that is used to trigger |
627 | * hot-removal function from userland. | 745 | * hot-removal function from userland. |
@@ -677,6 +795,8 @@ static void acpi_device_remove_files(struct acpi_device *dev) | |||
677 | device_remove_file(&dev->dev, &dev_attr_adr); | 795 | device_remove_file(&dev->dev, &dev_attr_adr); |
678 | device_remove_file(&dev->dev, &dev_attr_modalias); | 796 | device_remove_file(&dev->dev, &dev_attr_modalias); |
679 | device_remove_file(&dev->dev, &dev_attr_hid); | 797 | device_remove_file(&dev->dev, &dev_attr_hid); |
798 | if (acpi_has_method(dev->handle, "_STA")) | ||
799 | device_remove_file(&dev->dev, &dev_attr_status); | ||
680 | if (dev->handle) | 800 | if (dev->handle) |
681 | device_remove_file(&dev->dev, &dev_attr_path); | 801 | device_remove_file(&dev->dev, &dev_attr_path); |
682 | } | 802 | } |
@@ -782,8 +902,8 @@ static int acpi_device_uevent(struct device *dev, struct kobj_uevent_env *env) | |||
782 | return -ENOMEM; | 902 | return -ENOMEM; |
783 | len = create_modalias(acpi_dev, &env->buf[env->buflen - 1], | 903 | len = create_modalias(acpi_dev, &env->buf[env->buflen - 1], |
784 | sizeof(env->buf) - env->buflen); | 904 | sizeof(env->buf) - env->buflen); |
785 | if (len >= (sizeof(env->buf) - env->buflen)) | 905 | if (len <= 0) |
786 | return -ENOMEM; | 906 | return len; |
787 | env->buflen += len; | 907 | env->buflen += len; |
788 | return 0; | 908 | return 0; |
789 | } | 909 | } |
@@ -907,9 +1027,91 @@ struct bus_type acpi_bus_type = { | |||
907 | .uevent = acpi_device_uevent, | 1027 | .uevent = acpi_device_uevent, |
908 | }; | 1028 | }; |
909 | 1029 | ||
910 | static void acpi_bus_data_handler(acpi_handle handle, void *context) | 1030 | static void acpi_device_del(struct acpi_device *device) |
1031 | { | ||
1032 | mutex_lock(&acpi_device_lock); | ||
1033 | if (device->parent) | ||
1034 | list_del(&device->node); | ||
1035 | |||
1036 | list_del(&device->wakeup_list); | ||
1037 | mutex_unlock(&acpi_device_lock); | ||
1038 | |||
1039 | acpi_power_add_remove_device(device, false); | ||
1040 | acpi_device_remove_files(device); | ||
1041 | if (device->remove) | ||
1042 | device->remove(device); | ||
1043 | |||
1044 | device_del(&device->dev); | ||
1045 | } | ||
1046 | |||
1047 | static LIST_HEAD(acpi_device_del_list); | ||
1048 | static DEFINE_MUTEX(acpi_device_del_lock); | ||
1049 | |||
1050 | static void acpi_device_del_work_fn(struct work_struct *work_not_used) | ||
1051 | { | ||
1052 | for (;;) { | ||
1053 | struct acpi_device *adev; | ||
1054 | |||
1055 | mutex_lock(&acpi_device_del_lock); | ||
1056 | |||
1057 | if (list_empty(&acpi_device_del_list)) { | ||
1058 | mutex_unlock(&acpi_device_del_lock); | ||
1059 | break; | ||
1060 | } | ||
1061 | adev = list_first_entry(&acpi_device_del_list, | ||
1062 | struct acpi_device, del_list); | ||
1063 | list_del(&adev->del_list); | ||
1064 | |||
1065 | mutex_unlock(&acpi_device_del_lock); | ||
1066 | |||
1067 | acpi_device_del(adev); | ||
1068 | /* | ||
1069 | * Drop references to all power resources that might have been | ||
1070 | * used by the device. | ||
1071 | */ | ||
1072 | acpi_power_transition(adev, ACPI_STATE_D3_COLD); | ||
1073 | put_device(&adev->dev); | ||
1074 | } | ||
1075 | } | ||
1076 | |||
1077 | /** | ||
1078 | * acpi_scan_drop_device - Drop an ACPI device object. | ||
1079 | * @handle: Handle of an ACPI namespace node, not used. | ||
1080 | * @context: Address of the ACPI device object to drop. | ||
1081 | * | ||
1082 | * This is invoked by acpi_ns_delete_node() during the removal of the ACPI | ||
1083 | * namespace node the device object pointed to by @context is attached to. | ||
1084 | * | ||
1085 | * The unregistration is carried out asynchronously to avoid running | ||
1086 | * acpi_device_del() under the ACPICA's namespace mutex and the list is used to | ||
1087 | * ensure the correct ordering (the device objects must be unregistered in the | ||
1088 | * same order in which the corresponding namespace nodes are deleted). | ||
1089 | */ | ||
1090 | static void acpi_scan_drop_device(acpi_handle handle, void *context) | ||
911 | { | 1091 | { |
912 | /* Intentionally empty. */ | 1092 | static DECLARE_WORK(work, acpi_device_del_work_fn); |
1093 | struct acpi_device *adev = context; | ||
1094 | |||
1095 | mutex_lock(&acpi_device_del_lock); | ||
1096 | |||
1097 | /* | ||
1098 | * Use the ACPI hotplug workqueue which is ordered, so this work item | ||
1099 | * won't run after any hotplug work items submitted subsequently. That | ||
1100 | * prevents attempts to register device objects identical to those being | ||
1101 | * deleted from happening concurrently (such attempts result from | ||
1102 | * hotplug events handled via the ACPI hotplug workqueue). It also will | ||
1103 | * run after all of the work items submitted previosuly, which helps | ||
1104 | * those work items to ensure that they are not accessing stale device | ||
1105 | * objects. | ||
1106 | */ | ||
1107 | if (list_empty(&acpi_device_del_list)) | ||
1108 | acpi_queue_hotplug_work(&work); | ||
1109 | |||
1110 | list_add_tail(&adev->del_list, &acpi_device_del_list); | ||
1111 | /* Make acpi_ns_validate_handle() return NULL for this handle. */ | ||
1112 | adev->handle = INVALID_ACPI_HANDLE; | ||
1113 | |||
1114 | mutex_unlock(&acpi_device_del_lock); | ||
913 | } | 1115 | } |
914 | 1116 | ||
915 | int acpi_bus_get_device(acpi_handle handle, struct acpi_device **device) | 1117 | int acpi_bus_get_device(acpi_handle handle, struct acpi_device **device) |
@@ -919,7 +1121,7 @@ int acpi_bus_get_device(acpi_handle handle, struct acpi_device **device) | |||
919 | if (!device) | 1121 | if (!device) |
920 | return -EINVAL; | 1122 | return -EINVAL; |
921 | 1123 | ||
922 | status = acpi_get_data(handle, acpi_bus_data_handler, (void **)device); | 1124 | status = acpi_get_data(handle, acpi_scan_drop_device, (void **)device); |
923 | if (ACPI_FAILURE(status) || !*device) { | 1125 | if (ACPI_FAILURE(status) || !*device) { |
924 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No context for object [%p]\n", | 1126 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No context for object [%p]\n", |
925 | handle)); | 1127 | handle)); |
@@ -939,7 +1141,7 @@ int acpi_device_add(struct acpi_device *device, | |||
939 | if (device->handle) { | 1141 | if (device->handle) { |
940 | acpi_status status; | 1142 | acpi_status status; |
941 | 1143 | ||
942 | status = acpi_attach_data(device->handle, acpi_bus_data_handler, | 1144 | status = acpi_attach_data(device->handle, acpi_scan_drop_device, |
943 | device); | 1145 | device); |
944 | if (ACPI_FAILURE(status)) { | 1146 | if (ACPI_FAILURE(status)) { |
945 | acpi_handle_err(device->handle, | 1147 | acpi_handle_err(device->handle, |
@@ -957,6 +1159,7 @@ int acpi_device_add(struct acpi_device *device, | |||
957 | INIT_LIST_HEAD(&device->node); | 1159 | INIT_LIST_HEAD(&device->node); |
958 | INIT_LIST_HEAD(&device->wakeup_list); | 1160 | INIT_LIST_HEAD(&device->wakeup_list); |
959 | INIT_LIST_HEAD(&device->physical_node_list); | 1161 | INIT_LIST_HEAD(&device->physical_node_list); |
1162 | INIT_LIST_HEAD(&device->del_list); | ||
960 | mutex_init(&device->physical_node_lock); | 1163 | mutex_init(&device->physical_node_lock); |
961 | 1164 | ||
962 | new_bus_id = kzalloc(sizeof(struct acpi_device_bus_id), GFP_KERNEL); | 1165 | new_bus_id = kzalloc(sizeof(struct acpi_device_bus_id), GFP_KERNEL); |
@@ -1020,37 +1223,10 @@ int acpi_device_add(struct acpi_device *device, | |||
1020 | mutex_unlock(&acpi_device_lock); | 1223 | mutex_unlock(&acpi_device_lock); |
1021 | 1224 | ||
1022 | err_detach: | 1225 | err_detach: |
1023 | acpi_detach_data(device->handle, acpi_bus_data_handler); | 1226 | acpi_detach_data(device->handle, acpi_scan_drop_device); |
1024 | return result; | 1227 | return result; |
1025 | } | 1228 | } |
1026 | 1229 | ||
1027 | static void acpi_device_unregister(struct acpi_device *device) | ||
1028 | { | ||
1029 | mutex_lock(&acpi_device_lock); | ||
1030 | if (device->parent) | ||
1031 | list_del(&device->node); | ||
1032 | |||
1033 | list_del(&device->wakeup_list); | ||
1034 | mutex_unlock(&acpi_device_lock); | ||
1035 | |||
1036 | acpi_detach_data(device->handle, acpi_bus_data_handler); | ||
1037 | |||
1038 | acpi_power_add_remove_device(device, false); | ||
1039 | acpi_device_remove_files(device); | ||
1040 | if (device->remove) | ||
1041 | device->remove(device); | ||
1042 | |||
1043 | device_del(&device->dev); | ||
1044 | /* | ||
1045 | * Transition the device to D3cold to drop the reference counts of all | ||
1046 | * power resources the device depends on and turn off the ones that have | ||
1047 | * no more references. | ||
1048 | */ | ||
1049 | acpi_device_set_power(device, ACPI_STATE_D3_COLD); | ||
1050 | device->handle = NULL; | ||
1051 | put_device(&device->dev); | ||
1052 | } | ||
1053 | |||
1054 | /* -------------------------------------------------------------------------- | 1230 | /* -------------------------------------------------------------------------- |
1055 | Driver Management | 1231 | Driver Management |
1056 | -------------------------------------------------------------------------- */ | 1232 | -------------------------------------------------------------------------- */ |
@@ -1624,11 +1800,13 @@ void acpi_init_device_object(struct acpi_device *device, acpi_handle handle, | |||
1624 | device->device_type = type; | 1800 | device->device_type = type; |
1625 | device->handle = handle; | 1801 | device->handle = handle; |
1626 | device->parent = acpi_bus_get_parent(handle); | 1802 | device->parent = acpi_bus_get_parent(handle); |
1627 | STRUCT_TO_INT(device->status) = sta; | 1803 | acpi_set_device_status(device, sta); |
1628 | acpi_device_get_busid(device); | 1804 | acpi_device_get_busid(device); |
1629 | acpi_set_pnp_ids(handle, &device->pnp, type); | 1805 | acpi_set_pnp_ids(handle, &device->pnp, type); |
1630 | acpi_bus_get_flags(device); | 1806 | acpi_bus_get_flags(device); |
1631 | device->flags.match_driver = false; | 1807 | device->flags.match_driver = false; |
1808 | device->flags.initialized = true; | ||
1809 | device->flags.visited = false; | ||
1632 | device_initialize(&device->dev); | 1810 | device_initialize(&device->dev); |
1633 | dev_set_uevent_suppress(&device->dev, true); | 1811 | dev_set_uevent_suppress(&device->dev, true); |
1634 | } | 1812 | } |
@@ -1713,6 +1891,15 @@ static int acpi_bus_type_and_status(acpi_handle handle, int *type, | |||
1713 | return 0; | 1891 | return 0; |
1714 | } | 1892 | } |
1715 | 1893 | ||
1894 | bool acpi_device_is_present(struct acpi_device *adev) | ||
1895 | { | ||
1896 | if (adev->status.present || adev->status.functional) | ||
1897 | return true; | ||
1898 | |||
1899 | adev->flags.initialized = false; | ||
1900 | return false; | ||
1901 | } | ||
1902 | |||
1716 | static bool acpi_scan_handler_matching(struct acpi_scan_handler *handler, | 1903 | static bool acpi_scan_handler_matching(struct acpi_scan_handler *handler, |
1717 | char *idstr, | 1904 | char *idstr, |
1718 | const struct acpi_device_id **matchid) | 1905 | const struct acpi_device_id **matchid) |
@@ -1772,7 +1959,7 @@ static void acpi_scan_init_hotplug(acpi_handle handle, int type) | |||
1772 | */ | 1959 | */ |
1773 | list_for_each_entry(hwid, &pnp.ids, list) { | 1960 | list_for_each_entry(hwid, &pnp.ids, list) { |
1774 | handler = acpi_scan_match_handler(hwid->id, NULL); | 1961 | handler = acpi_scan_match_handler(hwid->id, NULL); |
1775 | if (handler && !handler->hotplug.ignore) { | 1962 | if (handler) { |
1776 | acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY, | 1963 | acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY, |
1777 | acpi_hotplug_notify_cb, handler); | 1964 | acpi_hotplug_notify_cb, handler); |
1778 | break; | 1965 | break; |
@@ -1806,18 +1993,6 @@ static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl_not_used, | |||
1806 | 1993 | ||
1807 | acpi_scan_init_hotplug(handle, type); | 1994 | acpi_scan_init_hotplug(handle, type); |
1808 | 1995 | ||
1809 | if (!(sta & ACPI_STA_DEVICE_PRESENT) && | ||
1810 | !(sta & ACPI_STA_DEVICE_FUNCTIONING)) { | ||
1811 | struct acpi_device_wakeup wakeup; | ||
1812 | |||
1813 | if (acpi_has_method(handle, "_PRW")) { | ||
1814 | acpi_bus_extract_wakeup_device_power_package(handle, | ||
1815 | &wakeup); | ||
1816 | acpi_power_resources_list_free(&wakeup.resources); | ||
1817 | } | ||
1818 | return AE_CTRL_DEPTH; | ||
1819 | } | ||
1820 | |||
1821 | acpi_add_single_object(&device, handle, type, sta); | 1996 | acpi_add_single_object(&device, handle, type, sta); |
1822 | if (!device) | 1997 | if (!device) |
1823 | return AE_CTRL_DEPTH; | 1998 | return AE_CTRL_DEPTH; |
@@ -1852,36 +2027,40 @@ static int acpi_scan_attach_handler(struct acpi_device *device) | |||
1852 | return ret; | 2027 | return ret; |
1853 | } | 2028 | } |
1854 | 2029 | ||
1855 | static acpi_status acpi_bus_device_attach(acpi_handle handle, u32 lvl_not_used, | 2030 | static void acpi_bus_attach(struct acpi_device *device) |
1856 | void *not_used, void **ret_not_used) | ||
1857 | { | 2031 | { |
1858 | struct acpi_device *device; | 2032 | struct acpi_device *child; |
1859 | unsigned long long sta_not_used; | ||
1860 | int ret; | 2033 | int ret; |
1861 | 2034 | ||
1862 | /* | 2035 | acpi_bus_get_status(device); |
1863 | * Ignore errors ignored by acpi_bus_check_add() to avoid terminating | 2036 | /* Skip devices that are not present. */ |
1864 | * namespace walks prematurely. | 2037 | if (!acpi_device_is_present(device)) { |
1865 | */ | 2038 | device->flags.visited = false; |
1866 | if (acpi_bus_type_and_status(handle, &ret, &sta_not_used)) | 2039 | return; |
1867 | return AE_OK; | 2040 | } |
1868 | |||
1869 | if (acpi_bus_get_device(handle, &device)) | ||
1870 | return AE_CTRL_DEPTH; | ||
1871 | |||
1872 | if (device->handler) | 2041 | if (device->handler) |
1873 | return AE_OK; | 2042 | goto ok; |
1874 | 2043 | ||
2044 | if (!device->flags.initialized) { | ||
2045 | acpi_bus_update_power(device, NULL); | ||
2046 | device->flags.initialized = true; | ||
2047 | } | ||
2048 | device->flags.visited = false; | ||
1875 | ret = acpi_scan_attach_handler(device); | 2049 | ret = acpi_scan_attach_handler(device); |
1876 | if (ret < 0) | 2050 | if (ret < 0) |
1877 | return AE_CTRL_DEPTH; | 2051 | return; |
1878 | 2052 | ||
1879 | device->flags.match_driver = true; | 2053 | device->flags.match_driver = true; |
1880 | if (ret > 0) | 2054 | if (!ret) { |
1881 | return AE_OK; | 2055 | ret = device_attach(&device->dev); |
2056 | if (ret < 0) | ||
2057 | return; | ||
2058 | } | ||
2059 | device->flags.visited = true; | ||
1882 | 2060 | ||
1883 | ret = device_attach(&device->dev); | 2061 | ok: |
1884 | return ret >= 0 ? AE_OK : AE_CTRL_DEPTH; | 2062 | list_for_each_entry(child, &device->children, node) |
2063 | acpi_bus_attach(child); | ||
1885 | } | 2064 | } |
1886 | 2065 | ||
1887 | /** | 2066 | /** |
@@ -1901,75 +2080,49 @@ static acpi_status acpi_bus_device_attach(acpi_handle handle, u32 lvl_not_used, | |||
1901 | int acpi_bus_scan(acpi_handle handle) | 2080 | int acpi_bus_scan(acpi_handle handle) |
1902 | { | 2081 | { |
1903 | void *device = NULL; | 2082 | void *device = NULL; |
1904 | int error = 0; | ||
1905 | 2083 | ||
1906 | if (ACPI_SUCCESS(acpi_bus_check_add(handle, 0, NULL, &device))) | 2084 | if (ACPI_SUCCESS(acpi_bus_check_add(handle, 0, NULL, &device))) |
1907 | acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, | 2085 | acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, |
1908 | acpi_bus_check_add, NULL, NULL, &device); | 2086 | acpi_bus_check_add, NULL, NULL, &device); |
1909 | 2087 | ||
1910 | if (!device) | 2088 | if (device) { |
1911 | error = -ENODEV; | 2089 | acpi_bus_attach(device); |
1912 | else if (ACPI_SUCCESS(acpi_bus_device_attach(handle, 0, NULL, NULL))) | 2090 | return 0; |
1913 | acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, | ||
1914 | acpi_bus_device_attach, NULL, NULL, NULL); | ||
1915 | |||
1916 | return error; | ||
1917 | } | ||
1918 | EXPORT_SYMBOL(acpi_bus_scan); | ||
1919 | |||
1920 | static acpi_status acpi_bus_device_detach(acpi_handle handle, u32 lvl_not_used, | ||
1921 | void *not_used, void **ret_not_used) | ||
1922 | { | ||
1923 | struct acpi_device *device = NULL; | ||
1924 | |||
1925 | if (!acpi_bus_get_device(handle, &device)) { | ||
1926 | struct acpi_scan_handler *dev_handler = device->handler; | ||
1927 | |||
1928 | if (dev_handler) { | ||
1929 | if (dev_handler->detach) | ||
1930 | dev_handler->detach(device); | ||
1931 | |||
1932 | device->handler = NULL; | ||
1933 | } else { | ||
1934 | device_release_driver(&device->dev); | ||
1935 | } | ||
1936 | } | 2091 | } |
1937 | return AE_OK; | 2092 | return -ENODEV; |
1938 | } | ||
1939 | |||
1940 | static acpi_status acpi_bus_remove(acpi_handle handle, u32 lvl_not_used, | ||
1941 | void *not_used, void **ret_not_used) | ||
1942 | { | ||
1943 | struct acpi_device *device = NULL; | ||
1944 | |||
1945 | if (!acpi_bus_get_device(handle, &device)) | ||
1946 | acpi_device_unregister(device); | ||
1947 | |||
1948 | return AE_OK; | ||
1949 | } | 2093 | } |
2094 | EXPORT_SYMBOL(acpi_bus_scan); | ||
1950 | 2095 | ||
1951 | /** | 2096 | /** |
1952 | * acpi_bus_trim - Remove ACPI device node and all of its descendants | 2097 | * acpi_bus_trim - Detach scan handlers and drivers from ACPI device objects. |
1953 | * @start: Root of the ACPI device nodes subtree to remove. | 2098 | * @adev: Root of the ACPI namespace scope to walk. |
1954 | * | 2099 | * |
1955 | * Must be called under acpi_scan_lock. | 2100 | * Must be called under acpi_scan_lock. |
1956 | */ | 2101 | */ |
1957 | void acpi_bus_trim(struct acpi_device *start) | 2102 | void acpi_bus_trim(struct acpi_device *adev) |
1958 | { | 2103 | { |
2104 | struct acpi_scan_handler *handler = adev->handler; | ||
2105 | struct acpi_device *child; | ||
2106 | |||
2107 | list_for_each_entry_reverse(child, &adev->children, node) | ||
2108 | acpi_bus_trim(child); | ||
2109 | |||
2110 | adev->flags.match_driver = false; | ||
2111 | if (handler) { | ||
2112 | if (handler->detach) | ||
2113 | handler->detach(adev); | ||
2114 | |||
2115 | adev->handler = NULL; | ||
2116 | } else { | ||
2117 | device_release_driver(&adev->dev); | ||
2118 | } | ||
1959 | /* | 2119 | /* |
1960 | * Execute acpi_bus_device_detach() as a post-order callback to detach | 2120 | * Most likely, the device is going away, so put it into D3cold before |
1961 | * all ACPI drivers from the device nodes being removed. | 2121 | * that. |
1962 | */ | ||
1963 | acpi_walk_namespace(ACPI_TYPE_ANY, start->handle, ACPI_UINT32_MAX, NULL, | ||
1964 | acpi_bus_device_detach, NULL, NULL); | ||
1965 | acpi_bus_device_detach(start->handle, 0, NULL, NULL); | ||
1966 | /* | ||
1967 | * Execute acpi_bus_remove() as a post-order callback to remove device | ||
1968 | * nodes in the given namespace scope. | ||
1969 | */ | 2122 | */ |
1970 | acpi_walk_namespace(ACPI_TYPE_ANY, start->handle, ACPI_UINT32_MAX, NULL, | 2123 | acpi_device_set_power(adev, ACPI_STATE_D3_COLD); |
1971 | acpi_bus_remove, NULL, NULL); | 2124 | adev->flags.initialized = false; |
1972 | acpi_bus_remove(start->handle, 0, NULL, NULL); | 2125 | adev->flags.visited = false; |
1973 | } | 2126 | } |
1974 | EXPORT_SYMBOL_GPL(acpi_bus_trim); | 2127 | EXPORT_SYMBOL_GPL(acpi_bus_trim); |
1975 | 2128 | ||
@@ -2047,14 +2200,14 @@ int __init acpi_scan_init(void) | |||
2047 | 2200 | ||
2048 | result = acpi_bus_scan_fixed(); | 2201 | result = acpi_bus_scan_fixed(); |
2049 | if (result) { | 2202 | if (result) { |
2050 | acpi_device_unregister(acpi_root); | 2203 | acpi_detach_data(acpi_root->handle, acpi_scan_drop_device); |
2204 | acpi_device_del(acpi_root); | ||
2205 | put_device(&acpi_root->dev); | ||
2051 | goto out; | 2206 | goto out; |
2052 | } | 2207 | } |
2053 | 2208 | ||
2054 | acpi_update_all_gpes(); | 2209 | acpi_update_all_gpes(); |
2055 | 2210 | ||
2056 | acpi_pci_root_hp_init(); | ||
2057 | |||
2058 | out: | 2211 | out: |
2059 | mutex_unlock(&acpi_scan_lock); | 2212 | mutex_unlock(&acpi_scan_lock); |
2060 | return result; | 2213 | return result; |