diff options
Diffstat (limited to 'drivers/acpi/scan.c')
-rw-r--r-- | drivers/acpi/scan.c | 137 |
1 files changed, 89 insertions, 48 deletions
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index d64a5826ef35..984eaff235df 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c | |||
@@ -450,43 +450,61 @@ static int acpi_scan_bus_check(struct acpi_device *adev) | |||
450 | return 0; | 450 | return 0; |
451 | } | 451 | } |
452 | 452 | ||
453 | static int acpi_generic_hotplug_event(struct acpi_device *adev, u32 type) | ||
454 | { | ||
455 | switch (type) { | ||
456 | case ACPI_NOTIFY_BUS_CHECK: | ||
457 | return acpi_scan_bus_check(adev); | ||
458 | case ACPI_NOTIFY_DEVICE_CHECK: | ||
459 | return acpi_scan_device_check(adev); | ||
460 | case ACPI_NOTIFY_EJECT_REQUEST: | ||
461 | case ACPI_OST_EC_OSPM_EJECT: | ||
462 | return acpi_scan_hot_remove(adev); | ||
463 | } | ||
464 | return -EINVAL; | ||
465 | } | ||
466 | |||
453 | static void acpi_device_hotplug(void *data, u32 src) | 467 | static void acpi_device_hotplug(void *data, u32 src) |
454 | { | 468 | { |
455 | u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; | 469 | u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; |
456 | struct acpi_device *adev = data; | 470 | struct acpi_device *adev = data; |
457 | int error; | 471 | int error = -ENODEV; |
458 | 472 | ||
459 | lock_device_hotplug(); | 473 | lock_device_hotplug(); |
460 | mutex_lock(&acpi_scan_lock); | 474 | mutex_lock(&acpi_scan_lock); |
461 | 475 | ||
462 | /* | 476 | /* |
463 | * The device object's ACPI handle cannot become invalid as long as we | 477 | * The device object's ACPI handle cannot become invalid as long as we |
464 | * are holding acpi_scan_lock, but it may have become invalid before | 478 | * are holding acpi_scan_lock, but it might have become invalid before |
465 | * that lock was acquired. | 479 | * that lock was acquired. |
466 | */ | 480 | */ |
467 | if (adev->handle == INVALID_ACPI_HANDLE) | 481 | if (adev->handle == INVALID_ACPI_HANDLE) |
468 | goto out; | 482 | goto err_out; |
469 | 483 | ||
470 | switch (src) { | 484 | if (adev->flags.hotplug_notify) { |
471 | case ACPI_NOTIFY_BUS_CHECK: | 485 | error = acpi_generic_hotplug_event(adev, src); |
472 | error = acpi_scan_bus_check(adev); | 486 | } else { |
473 | break; | 487 | int (*event)(struct acpi_device *, u32); |
474 | case ACPI_NOTIFY_DEVICE_CHECK: | 488 | |
475 | error = acpi_scan_device_check(adev); | 489 | acpi_lock_hp_context(); |
476 | break; | 490 | event = adev->hp ? adev->hp->event : NULL; |
477 | case ACPI_NOTIFY_EJECT_REQUEST: | 491 | acpi_unlock_hp_context(); |
478 | case ACPI_OST_EC_OSPM_EJECT: | 492 | /* |
479 | error = acpi_scan_hot_remove(adev); | 493 | * There may be additional notify handlers for device objects |
480 | break; | 494 | * without the .event() callback, so ignore them here. |
481 | default: | 495 | */ |
482 | error = -EINVAL; | 496 | if (event) |
483 | break; | 497 | error = event(adev, src); |
498 | else | ||
499 | goto out; | ||
484 | } | 500 | } |
485 | if (!error) | 501 | if (!error) |
486 | ost_code = ACPI_OST_SC_SUCCESS; | 502 | ost_code = ACPI_OST_SC_SUCCESS; |
487 | 503 | ||
488 | out: | 504 | err_out: |
489 | acpi_evaluate_hotplug_ost(adev->handle, src, ost_code, NULL); | 505 | acpi_evaluate_hotplug_ost(adev->handle, src, ost_code, NULL); |
506 | |||
507 | out: | ||
490 | acpi_bus_put_acpi_device(adev); | 508 | acpi_bus_put_acpi_device(adev); |
491 | mutex_unlock(&acpi_scan_lock); | 509 | mutex_unlock(&acpi_scan_lock); |
492 | unlock_device_hotplug(); | 510 | unlock_device_hotplug(); |
@@ -494,8 +512,8 @@ static void acpi_device_hotplug(void *data, u32 src) | |||
494 | 512 | ||
495 | static void acpi_hotplug_notify_cb(acpi_handle handle, u32 type, void *data) | 513 | static void acpi_hotplug_notify_cb(acpi_handle handle, u32 type, void *data) |
496 | { | 514 | { |
497 | u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; | ||
498 | struct acpi_scan_handler *handler = data; | 515 | struct acpi_scan_handler *handler = data; |
516 | u32 ost_code = ACPI_OST_SC_SUCCESS; | ||
499 | struct acpi_device *adev; | 517 | struct acpi_device *adev; |
500 | acpi_status status; | 518 | acpi_status status; |
501 | 519 | ||
@@ -503,26 +521,49 @@ static void acpi_hotplug_notify_cb(acpi_handle handle, u32 type, void *data) | |||
503 | case ACPI_NOTIFY_BUS_CHECK: | 521 | case ACPI_NOTIFY_BUS_CHECK: |
504 | acpi_handle_debug(handle, "ACPI_NOTIFY_BUS_CHECK event\n"); | 522 | acpi_handle_debug(handle, "ACPI_NOTIFY_BUS_CHECK event\n"); |
505 | break; | 523 | break; |
524 | |||
506 | case ACPI_NOTIFY_DEVICE_CHECK: | 525 | case ACPI_NOTIFY_DEVICE_CHECK: |
507 | acpi_handle_debug(handle, "ACPI_NOTIFY_DEVICE_CHECK event\n"); | 526 | acpi_handle_debug(handle, "ACPI_NOTIFY_DEVICE_CHECK event\n"); |
508 | break; | 527 | break; |
528 | |||
509 | case ACPI_NOTIFY_EJECT_REQUEST: | 529 | case ACPI_NOTIFY_EJECT_REQUEST: |
510 | acpi_handle_debug(handle, "ACPI_NOTIFY_EJECT_REQUEST event\n"); | 530 | acpi_handle_debug(handle, "ACPI_NOTIFY_EJECT_REQUEST event\n"); |
511 | if (!handler->hotplug.enabled) { | 531 | if (handler && !handler->hotplug.enabled) { |
512 | acpi_handle_err(handle, "Eject disabled\n"); | 532 | acpi_handle_err(handle, "Eject disabled\n"); |
513 | ost_code = ACPI_OST_SC_EJECT_NOT_SUPPORTED; | 533 | ost_code = ACPI_OST_SC_EJECT_NOT_SUPPORTED; |
514 | goto err_out; | 534 | goto out; |
515 | } | 535 | } |
516 | acpi_evaluate_hotplug_ost(handle, ACPI_NOTIFY_EJECT_REQUEST, | 536 | acpi_evaluate_hotplug_ost(handle, ACPI_NOTIFY_EJECT_REQUEST, |
517 | ACPI_OST_SC_EJECT_IN_PROGRESS, NULL); | 537 | ACPI_OST_SC_EJECT_IN_PROGRESS, NULL); |
518 | break; | 538 | break; |
519 | default: | 539 | |
520 | /* non-hotplug event; possibly handled by other handler */ | 540 | case ACPI_NOTIFY_DEVICE_WAKE: |
521 | return; | 541 | return; |
542 | |||
543 | case ACPI_NOTIFY_FREQUENCY_MISMATCH: | ||
544 | acpi_handle_err(handle, "Device cannot be configured due " | ||
545 | "to a frequency mismatch\n"); | ||
546 | goto out; | ||
547 | |||
548 | case ACPI_NOTIFY_BUS_MODE_MISMATCH: | ||
549 | acpi_handle_err(handle, "Device cannot be configured due " | ||
550 | "to a bus mode mismatch\n"); | ||
551 | goto out; | ||
552 | |||
553 | case ACPI_NOTIFY_POWER_FAULT: | ||
554 | acpi_handle_err(handle, "Device has suffered a power fault\n"); | ||
555 | goto out; | ||
556 | |||
557 | default: | ||
558 | acpi_handle_warn(handle, "Unsupported event type 0x%x\n", type); | ||
559 | ost_code = ACPI_OST_SC_UNRECOGNIZED_NOTIFY; | ||
560 | goto out; | ||
522 | } | 561 | } |
562 | |||
563 | ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; | ||
523 | adev = acpi_bus_get_acpi_device(handle); | 564 | adev = acpi_bus_get_acpi_device(handle); |
524 | if (!adev) | 565 | if (!adev) |
525 | goto err_out; | 566 | goto out; |
526 | 567 | ||
527 | status = acpi_hotplug_execute(acpi_device_hotplug, adev, type); | 568 | status = acpi_hotplug_execute(acpi_device_hotplug, adev, type); |
528 | if (ACPI_SUCCESS(status)) | 569 | if (ACPI_SUCCESS(status)) |
@@ -530,10 +571,22 @@ static void acpi_hotplug_notify_cb(acpi_handle handle, u32 type, void *data) | |||
530 | 571 | ||
531 | acpi_bus_put_acpi_device(adev); | 572 | acpi_bus_put_acpi_device(adev); |
532 | 573 | ||
533 | err_out: | 574 | out: |
534 | acpi_evaluate_hotplug_ost(handle, type, ost_code, NULL); | 575 | acpi_evaluate_hotplug_ost(handle, type, ost_code, NULL); |
535 | } | 576 | } |
536 | 577 | ||
578 | void acpi_install_hotplug_notify_handler(acpi_handle handle, void *data) | ||
579 | { | ||
580 | acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY, | ||
581 | acpi_hotplug_notify_cb, data); | ||
582 | } | ||
583 | |||
584 | void acpi_remove_hotplug_notify_handler(acpi_handle handle) | ||
585 | { | ||
586 | acpi_remove_notify_handler(handle, ACPI_SYSTEM_NOTIFY, | ||
587 | acpi_hotplug_notify_cb); | ||
588 | } | ||
589 | |||
537 | static ssize_t real_power_state_show(struct device *dev, | 590 | static ssize_t real_power_state_show(struct device *dev, |
538 | struct device_attribute *attr, char *buf) | 591 | struct device_attribute *attr, char *buf) |
539 | { | 592 | { |
@@ -1976,33 +2029,21 @@ void acpi_scan_hotplug_enabled(struct acpi_hotplug_profile *hotplug, bool val) | |||
1976 | mutex_unlock(&acpi_scan_lock); | 2029 | mutex_unlock(&acpi_scan_lock); |
1977 | } | 2030 | } |
1978 | 2031 | ||
1979 | static void acpi_scan_init_hotplug(acpi_handle handle, int type) | 2032 | static void acpi_scan_init_hotplug(struct acpi_device *adev) |
1980 | { | 2033 | { |
1981 | struct acpi_device_pnp pnp = {}; | ||
1982 | struct acpi_hardware_id *hwid; | 2034 | struct acpi_hardware_id *hwid; |
1983 | struct acpi_scan_handler *handler; | ||
1984 | 2035 | ||
1985 | INIT_LIST_HEAD(&pnp.ids); | 2036 | list_for_each_entry(hwid, &adev->pnp.ids, list) { |
1986 | acpi_set_pnp_ids(handle, &pnp, type); | 2037 | struct acpi_scan_handler *handler; |
1987 | |||
1988 | if (!pnp.type.hardware_id) | ||
1989 | goto out; | ||
1990 | 2038 | ||
1991 | /* | ||
1992 | * This relies on the fact that acpi_install_notify_handler() will not | ||
1993 | * install the same notify handler routine twice for the same handle. | ||
1994 | */ | ||
1995 | list_for_each_entry(hwid, &pnp.ids, list) { | ||
1996 | handler = acpi_scan_match_handler(hwid->id, NULL); | 2039 | handler = acpi_scan_match_handler(hwid->id, NULL); |
1997 | if (handler) { | 2040 | if (!handler) |
1998 | acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY, | 2041 | continue; |
1999 | acpi_hotplug_notify_cb, handler); | ||
2000 | break; | ||
2001 | } | ||
2002 | } | ||
2003 | 2042 | ||
2004 | out: | 2043 | acpi_install_hotplug_notify_handler(adev->handle, handler); |
2005 | acpi_free_pnp_ids(&pnp); | 2044 | adev->flags.hotplug_notify = true; |
2045 | break; | ||
2046 | } | ||
2006 | } | 2047 | } |
2007 | 2048 | ||
2008 | static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl_not_used, | 2049 | static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl_not_used, |
@@ -2026,12 +2067,12 @@ static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl_not_used, | |||
2026 | return AE_OK; | 2067 | return AE_OK; |
2027 | } | 2068 | } |
2028 | 2069 | ||
2029 | acpi_scan_init_hotplug(handle, type); | ||
2030 | |||
2031 | acpi_add_single_object(&device, handle, type, sta); | 2070 | acpi_add_single_object(&device, handle, type, sta); |
2032 | if (!device) | 2071 | if (!device) |
2033 | return AE_CTRL_DEPTH; | 2072 | return AE_CTRL_DEPTH; |
2034 | 2073 | ||
2074 | acpi_scan_init_hotplug(device); | ||
2075 | |||
2035 | out: | 2076 | out: |
2036 | if (!*return_value) | 2077 | if (!*return_value) |
2037 | *return_value = device; | 2078 | *return_value = device; |