diff options
author | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2013-08-30 08:14:25 -0400 |
---|---|---|
committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2013-08-30 08:14:25 -0400 |
commit | 7bc583d102d6f89c3dc4b502caec6ba03c9d318f (patch) | |
tree | 550e6333f2205f006849984b52408ed796bcd0c5 /drivers/acpi/scan.c | |
parent | da48afb26b40ebb5d6b0e84793e0662859c7ea20 (diff) | |
parent | f943db40c29f3c82a56956e9ca36f21d6d855db9 (diff) |
Merge branch 'acpi-hotplug'
* acpi-hotplug:
ACPI / hotplug: Remove containers synchronously
driver core / ACPI: Avoid device hot remove locking issues
Diffstat (limited to 'drivers/acpi/scan.c')
-rw-r--r-- | drivers/acpi/scan.c | 49 |
1 files changed, 15 insertions, 34 deletions
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index e76365136ba3..61d090b6ce25 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c | |||
@@ -287,6 +287,7 @@ static void acpi_bus_device_eject(void *context) | |||
287 | struct acpi_device *device = NULL; | 287 | struct acpi_device *device = NULL; |
288 | struct acpi_scan_handler *handler; | 288 | struct acpi_scan_handler *handler; |
289 | u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; | 289 | u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; |
290 | int error; | ||
290 | 291 | ||
291 | mutex_lock(&acpi_scan_lock); | 292 | mutex_lock(&acpi_scan_lock); |
292 | 293 | ||
@@ -301,17 +302,13 @@ static void acpi_bus_device_eject(void *context) | |||
301 | } | 302 | } |
302 | acpi_evaluate_hotplug_ost(handle, ACPI_NOTIFY_EJECT_REQUEST, | 303 | acpi_evaluate_hotplug_ost(handle, ACPI_NOTIFY_EJECT_REQUEST, |
303 | ACPI_OST_SC_EJECT_IN_PROGRESS, NULL); | 304 | ACPI_OST_SC_EJECT_IN_PROGRESS, NULL); |
304 | if (handler->hotplug.mode == AHM_CONTAINER) { | 305 | if (handler->hotplug.mode == AHM_CONTAINER) |
305 | device->flags.eject_pending = true; | ||
306 | kobject_uevent(&device->dev.kobj, KOBJ_OFFLINE); | 306 | kobject_uevent(&device->dev.kobj, KOBJ_OFFLINE); |
307 | } else { | ||
308 | int error; | ||
309 | 307 | ||
310 | get_device(&device->dev); | 308 | get_device(&device->dev); |
311 | error = acpi_scan_hot_remove(device); | 309 | error = acpi_scan_hot_remove(device); |
312 | if (error) | 310 | if (error) |
313 | goto err_out; | 311 | goto err_out; |
314 | } | ||
315 | 312 | ||
316 | out: | 313 | out: |
317 | mutex_unlock(&acpi_scan_lock); | 314 | mutex_unlock(&acpi_scan_lock); |
@@ -496,7 +493,6 @@ acpi_eject_store(struct device *d, struct device_attribute *attr, | |||
496 | struct acpi_eject_event *ej_event; | 493 | struct acpi_eject_event *ej_event; |
497 | acpi_object_type not_used; | 494 | acpi_object_type not_used; |
498 | acpi_status status; | 495 | acpi_status status; |
499 | u32 ost_source; | ||
500 | int ret; | 496 | int ret; |
501 | 497 | ||
502 | if (!count || buf[0] != '1') | 498 | if (!count || buf[0] != '1') |
@@ -510,43 +506,28 @@ acpi_eject_store(struct device *d, struct device_attribute *attr, | |||
510 | if (ACPI_FAILURE(status) || !acpi_device->flags.ejectable) | 506 | if (ACPI_FAILURE(status) || !acpi_device->flags.ejectable) |
511 | return -ENODEV; | 507 | return -ENODEV; |
512 | 508 | ||
513 | mutex_lock(&acpi_scan_lock); | ||
514 | |||
515 | if (acpi_device->flags.eject_pending) { | ||
516 | /* ACPI eject notification event. */ | ||
517 | ost_source = ACPI_NOTIFY_EJECT_REQUEST; | ||
518 | acpi_device->flags.eject_pending = 0; | ||
519 | } else { | ||
520 | /* Eject initiated by user space. */ | ||
521 | ost_source = ACPI_OST_EC_OSPM_EJECT; | ||
522 | } | ||
523 | ej_event = kmalloc(sizeof(*ej_event), GFP_KERNEL); | 509 | ej_event = kmalloc(sizeof(*ej_event), GFP_KERNEL); |
524 | if (!ej_event) { | 510 | if (!ej_event) { |
525 | ret = -ENOMEM; | 511 | ret = -ENOMEM; |
526 | goto err_out; | 512 | goto err_out; |
527 | } | 513 | } |
528 | acpi_evaluate_hotplug_ost(acpi_device->handle, ost_source, | 514 | acpi_evaluate_hotplug_ost(acpi_device->handle, ACPI_OST_EC_OSPM_EJECT, |
529 | ACPI_OST_SC_EJECT_IN_PROGRESS, NULL); | 515 | ACPI_OST_SC_EJECT_IN_PROGRESS, NULL); |
530 | ej_event->device = acpi_device; | 516 | ej_event->device = acpi_device; |
531 | ej_event->event = ost_source; | 517 | ej_event->event = ACPI_OST_EC_OSPM_EJECT; |
532 | get_device(&acpi_device->dev); | 518 | get_device(&acpi_device->dev); |
533 | status = acpi_os_hotplug_execute(acpi_bus_hot_remove_device, ej_event); | 519 | status = acpi_os_hotplug_execute(acpi_bus_hot_remove_device, ej_event); |
534 | if (ACPI_FAILURE(status)) { | 520 | if (ACPI_SUCCESS(status)) |
535 | put_device(&acpi_device->dev); | 521 | return count; |
536 | kfree(ej_event); | ||
537 | ret = status == AE_NO_MEMORY ? -ENOMEM : -EAGAIN; | ||
538 | goto err_out; | ||
539 | } | ||
540 | ret = count; | ||
541 | 522 | ||
542 | out: | 523 | put_device(&acpi_device->dev); |
543 | mutex_unlock(&acpi_scan_lock); | 524 | kfree(ej_event); |
544 | return ret; | 525 | ret = status == AE_NO_MEMORY ? -ENOMEM : -EAGAIN; |
545 | 526 | ||
546 | err_out: | 527 | err_out: |
547 | acpi_evaluate_hotplug_ost(acpi_device->handle, ost_source, | 528 | acpi_evaluate_hotplug_ost(acpi_device->handle, ACPI_OST_EC_OSPM_EJECT, |
548 | ACPI_OST_SC_NON_SPECIFIC_FAILURE, NULL); | 529 | ACPI_OST_SC_NON_SPECIFIC_FAILURE, NULL); |
549 | goto out; | 530 | return ret; |
550 | } | 531 | } |
551 | 532 | ||
552 | static DEVICE_ATTR(eject, 0200, NULL, acpi_eject_store); | 533 | static DEVICE_ATTR(eject, 0200, NULL, acpi_eject_store); |