diff options
Diffstat (limited to 'drivers/acpi/scan.c')
-rw-r--r-- | drivers/acpi/scan.c | 261 |
1 files changed, 161 insertions, 100 deletions
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 57b053f424d1..7efe546a8c42 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c | |||
@@ -41,6 +41,7 @@ static DEFINE_MUTEX(acpi_scan_lock); | |||
41 | static LIST_HEAD(acpi_scan_handlers_list); | 41 | static LIST_HEAD(acpi_scan_handlers_list); |
42 | DEFINE_MUTEX(acpi_device_lock); | 42 | DEFINE_MUTEX(acpi_device_lock); |
43 | LIST_HEAD(acpi_wakeup_device_list); | 43 | LIST_HEAD(acpi_wakeup_device_list); |
44 | static DEFINE_MUTEX(acpi_hp_context_lock); | ||
44 | 45 | ||
45 | struct acpi_device_bus_id{ | 46 | struct acpi_device_bus_id{ |
46 | char bus_id[15]; | 47 | char bus_id[15]; |
@@ -60,6 +61,27 @@ void acpi_scan_lock_release(void) | |||
60 | } | 61 | } |
61 | EXPORT_SYMBOL_GPL(acpi_scan_lock_release); | 62 | EXPORT_SYMBOL_GPL(acpi_scan_lock_release); |
62 | 63 | ||
64 | void acpi_lock_hp_context(void) | ||
65 | { | ||
66 | mutex_lock(&acpi_hp_context_lock); | ||
67 | } | ||
68 | |||
69 | void acpi_unlock_hp_context(void) | ||
70 | { | ||
71 | mutex_unlock(&acpi_hp_context_lock); | ||
72 | } | ||
73 | |||
74 | void acpi_initialize_hp_context(struct acpi_device *adev, | ||
75 | struct acpi_hotplug_context *hp, | ||
76 | int (*notify)(struct acpi_device *, u32), | ||
77 | void (*uevent)(struct acpi_device *, u32)) | ||
78 | { | ||
79 | acpi_lock_hp_context(); | ||
80 | acpi_set_hp_context(adev, hp, notify, uevent, NULL); | ||
81 | acpi_unlock_hp_context(); | ||
82 | } | ||
83 | EXPORT_SYMBOL_GPL(acpi_initialize_hp_context); | ||
84 | |||
63 | int acpi_scan_add_handler(struct acpi_scan_handler *handler) | 85 | int acpi_scan_add_handler(struct acpi_scan_handler *handler) |
64 | { | 86 | { |
65 | if (!handler || !handler->attach) | 87 | if (!handler || !handler->attach) |
@@ -439,90 +461,75 @@ static int acpi_scan_bus_check(struct acpi_device *adev) | |||
439 | return 0; | 461 | return 0; |
440 | } | 462 | } |
441 | 463 | ||
442 | static void acpi_device_hotplug(void *data, u32 src) | 464 | static int acpi_generic_hotplug_event(struct acpi_device *adev, u32 type) |
443 | { | 465 | { |
444 | u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; | 466 | switch (type) { |
445 | struct acpi_device *adev = data; | ||
446 | int error; | ||
447 | |||
448 | lock_device_hotplug(); | ||
449 | mutex_lock(&acpi_scan_lock); | ||
450 | |||
451 | /* | ||
452 | * The device object's ACPI handle cannot become invalid as long as we | ||
453 | * are holding acpi_scan_lock, but it may have become invalid before | ||
454 | * that lock was acquired. | ||
455 | */ | ||
456 | if (adev->handle == INVALID_ACPI_HANDLE) | ||
457 | goto out; | ||
458 | |||
459 | switch (src) { | ||
460 | case ACPI_NOTIFY_BUS_CHECK: | 467 | case ACPI_NOTIFY_BUS_CHECK: |
461 | error = acpi_scan_bus_check(adev); | 468 | return acpi_scan_bus_check(adev); |
462 | break; | ||
463 | case ACPI_NOTIFY_DEVICE_CHECK: | 469 | case ACPI_NOTIFY_DEVICE_CHECK: |
464 | error = acpi_scan_device_check(adev); | 470 | return acpi_scan_device_check(adev); |
465 | break; | ||
466 | case ACPI_NOTIFY_EJECT_REQUEST: | 471 | case ACPI_NOTIFY_EJECT_REQUEST: |
467 | case ACPI_OST_EC_OSPM_EJECT: | 472 | case ACPI_OST_EC_OSPM_EJECT: |
468 | error = acpi_scan_hot_remove(adev); | 473 | if (adev->handler && !adev->handler->hotplug.enabled) { |
469 | break; | 474 | dev_info(&adev->dev, "Eject disabled\n"); |
470 | default: | 475 | return -EPERM; |
471 | error = -EINVAL; | 476 | } |
472 | break; | 477 | acpi_evaluate_ost(adev->handle, ACPI_NOTIFY_EJECT_REQUEST, |
478 | ACPI_OST_SC_EJECT_IN_PROGRESS, NULL); | ||
479 | return acpi_scan_hot_remove(adev); | ||
473 | } | 480 | } |
474 | if (!error) | 481 | return -EINVAL; |
475 | ost_code = ACPI_OST_SC_SUCCESS; | ||
476 | |||
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(); | ||
482 | } | 482 | } |
483 | 483 | ||
484 | static void acpi_hotplug_notify_cb(acpi_handle handle, u32 type, void *data) | 484 | void acpi_device_hotplug(struct acpi_device *adev, u32 src) |
485 | { | 485 | { |
486 | u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; | 486 | u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; |
487 | struct acpi_device *adev; | 487 | int error = -ENODEV; |
488 | acpi_status status; | ||
489 | 488 | ||
490 | if (acpi_bus_get_device(handle, &adev)) | 489 | lock_device_hotplug(); |
491 | goto err_out; | 490 | mutex_lock(&acpi_scan_lock); |
492 | 491 | ||
493 | switch (type) { | 492 | /* |
494 | case ACPI_NOTIFY_BUS_CHECK: | 493 | * The device object's ACPI handle cannot become invalid as long as we |
495 | acpi_handle_debug(handle, "ACPI_NOTIFY_BUS_CHECK event\n"); | 494 | * are holding acpi_scan_lock, but it might have become invalid before |
496 | break; | 495 | * that lock was acquired. |
497 | case ACPI_NOTIFY_DEVICE_CHECK: | 496 | */ |
498 | acpi_handle_debug(handle, "ACPI_NOTIFY_DEVICE_CHECK event\n"); | 497 | if (adev->handle == INVALID_ACPI_HANDLE) |
499 | break; | 498 | goto err_out; |
500 | case ACPI_NOTIFY_EJECT_REQUEST: | ||
501 | acpi_handle_debug(handle, "ACPI_NOTIFY_EJECT_REQUEST event\n"); | ||
502 | if (!adev->handler) | ||
503 | goto err_out; | ||
504 | 499 | ||
505 | if (!adev->handler->hotplug.enabled) { | 500 | if (adev->flags.is_dock_station) { |
506 | acpi_handle_err(handle, "Eject disabled\n"); | 501 | error = dock_notify(adev, src); |
502 | } else if (adev->flags.hotplug_notify) { | ||
503 | error = acpi_generic_hotplug_event(adev, src); | ||
504 | if (error == -EPERM) { | ||
507 | ost_code = ACPI_OST_SC_EJECT_NOT_SUPPORTED; | 505 | ost_code = ACPI_OST_SC_EJECT_NOT_SUPPORTED; |
508 | goto err_out; | 506 | goto err_out; |
509 | } | 507 | } |
510 | acpi_evaluate_hotplug_ost(handle, ACPI_NOTIFY_EJECT_REQUEST, | 508 | } else { |
511 | ACPI_OST_SC_EJECT_IN_PROGRESS, NULL); | 509 | int (*notify)(struct acpi_device *, u32); |
512 | break; | ||
513 | default: | ||
514 | /* non-hotplug event; possibly handled by other handler */ | ||
515 | return; | ||
516 | } | ||
517 | get_device(&adev->dev); | ||
518 | status = acpi_hotplug_execute(acpi_device_hotplug, adev, type); | ||
519 | if (ACPI_SUCCESS(status)) | ||
520 | return; | ||
521 | 510 | ||
522 | put_device(&adev->dev); | 511 | acpi_lock_hp_context(); |
512 | notify = adev->hp ? adev->hp->notify : NULL; | ||
513 | acpi_unlock_hp_context(); | ||
514 | /* | ||
515 | * There may be additional notify handlers for device objects | ||
516 | * without the .event() callback, so ignore them here. | ||
517 | */ | ||
518 | if (notify) | ||
519 | error = notify(adev, src); | ||
520 | else | ||
521 | goto out; | ||
522 | } | ||
523 | if (!error) | ||
524 | ost_code = ACPI_OST_SC_SUCCESS; | ||
523 | 525 | ||
524 | err_out: | 526 | err_out: |
525 | acpi_evaluate_hotplug_ost(handle, type, ost_code, NULL); | 527 | acpi_evaluate_ost(adev->handle, src, ost_code, NULL); |
528 | |||
529 | out: | ||
530 | acpi_bus_put_acpi_device(adev); | ||
531 | mutex_unlock(&acpi_scan_lock); | ||
532 | unlock_device_hotplug(); | ||
526 | } | 533 | } |
527 | 534 | ||
528 | static ssize_t real_power_state_show(struct device *dev, | 535 | static ssize_t real_power_state_show(struct device *dev, |
@@ -570,17 +577,14 @@ acpi_eject_store(struct device *d, struct device_attribute *attr, | |||
570 | if (ACPI_FAILURE(status) || !acpi_device->flags.ejectable) | 577 | if (ACPI_FAILURE(status) || !acpi_device->flags.ejectable) |
571 | return -ENODEV; | 578 | return -ENODEV; |
572 | 579 | ||
573 | acpi_evaluate_hotplug_ost(acpi_device->handle, ACPI_OST_EC_OSPM_EJECT, | ||
574 | ACPI_OST_SC_EJECT_IN_PROGRESS, NULL); | ||
575 | get_device(&acpi_device->dev); | 580 | get_device(&acpi_device->dev); |
576 | status = acpi_hotplug_execute(acpi_device_hotplug, acpi_device, | 581 | status = acpi_hotplug_schedule(acpi_device, ACPI_OST_EC_OSPM_EJECT); |
577 | ACPI_OST_EC_OSPM_EJECT); | ||
578 | if (ACPI_SUCCESS(status)) | 582 | if (ACPI_SUCCESS(status)) |
579 | return count; | 583 | return count; |
580 | 584 | ||
581 | put_device(&acpi_device->dev); | 585 | put_device(&acpi_device->dev); |
582 | acpi_evaluate_hotplug_ost(acpi_device->handle, ACPI_OST_EC_OSPM_EJECT, | 586 | acpi_evaluate_ost(acpi_device->handle, ACPI_OST_EC_OSPM_EJECT, |
583 | ACPI_OST_SC_NON_SPECIFIC_FAILURE, NULL); | 587 | ACPI_OST_SC_NON_SPECIFIC_FAILURE, NULL); |
584 | return status == AE_NO_MEMORY ? -ENOMEM : -EAGAIN; | 588 | return status == AE_NO_MEMORY ? -ENOMEM : -EAGAIN; |
585 | } | 589 | } |
586 | 590 | ||
@@ -1114,14 +1118,16 @@ static void acpi_scan_drop_device(acpi_handle handle, void *context) | |||
1114 | mutex_unlock(&acpi_device_del_lock); | 1118 | mutex_unlock(&acpi_device_del_lock); |
1115 | } | 1119 | } |
1116 | 1120 | ||
1117 | int acpi_bus_get_device(acpi_handle handle, struct acpi_device **device) | 1121 | static int acpi_get_device_data(acpi_handle handle, struct acpi_device **device, |
1122 | void (*callback)(void *)) | ||
1118 | { | 1123 | { |
1119 | acpi_status status; | 1124 | acpi_status status; |
1120 | 1125 | ||
1121 | if (!device) | 1126 | if (!device) |
1122 | return -EINVAL; | 1127 | return -EINVAL; |
1123 | 1128 | ||
1124 | status = acpi_get_data(handle, acpi_scan_drop_device, (void **)device); | 1129 | status = acpi_get_data_full(handle, acpi_scan_drop_device, |
1130 | (void **)device, callback); | ||
1125 | if (ACPI_FAILURE(status) || !*device) { | 1131 | if (ACPI_FAILURE(status) || !*device) { |
1126 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No context for object [%p]\n", | 1132 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No context for object [%p]\n", |
1127 | handle)); | 1133 | handle)); |
@@ -1129,8 +1135,32 @@ int acpi_bus_get_device(acpi_handle handle, struct acpi_device **device) | |||
1129 | } | 1135 | } |
1130 | return 0; | 1136 | return 0; |
1131 | } | 1137 | } |
1138 | |||
1139 | int acpi_bus_get_device(acpi_handle handle, struct acpi_device **device) | ||
1140 | { | ||
1141 | return acpi_get_device_data(handle, device, NULL); | ||
1142 | } | ||
1132 | EXPORT_SYMBOL(acpi_bus_get_device); | 1143 | EXPORT_SYMBOL(acpi_bus_get_device); |
1133 | 1144 | ||
1145 | static void get_acpi_device(void *dev) | ||
1146 | { | ||
1147 | if (dev) | ||
1148 | get_device(&((struct acpi_device *)dev)->dev); | ||
1149 | } | ||
1150 | |||
1151 | struct acpi_device *acpi_bus_get_acpi_device(acpi_handle handle) | ||
1152 | { | ||
1153 | struct acpi_device *adev = NULL; | ||
1154 | |||
1155 | acpi_get_device_data(handle, &adev, get_acpi_device); | ||
1156 | return adev; | ||
1157 | } | ||
1158 | |||
1159 | void acpi_bus_put_acpi_device(struct acpi_device *adev) | ||
1160 | { | ||
1161 | put_device(&adev->dev); | ||
1162 | } | ||
1163 | |||
1134 | int acpi_device_add(struct acpi_device *device, | 1164 | int acpi_device_add(struct acpi_device *device, |
1135 | void (*release)(struct device *)) | 1165 | void (*release)(struct device *)) |
1136 | { | 1166 | { |
@@ -1641,6 +1671,27 @@ bool acpi_bay_match(acpi_handle handle) | |||
1641 | return acpi_ata_match(phandle); | 1671 | return acpi_ata_match(phandle); |
1642 | } | 1672 | } |
1643 | 1673 | ||
1674 | bool acpi_device_is_battery(struct acpi_device *adev) | ||
1675 | { | ||
1676 | struct acpi_hardware_id *hwid; | ||
1677 | |||
1678 | list_for_each_entry(hwid, &adev->pnp.ids, list) | ||
1679 | if (!strcmp("PNP0C0A", hwid->id)) | ||
1680 | return true; | ||
1681 | |||
1682 | return false; | ||
1683 | } | ||
1684 | |||
1685 | static bool is_ejectable_bay(struct acpi_device *adev) | ||
1686 | { | ||
1687 | acpi_handle handle = adev->handle; | ||
1688 | |||
1689 | if (acpi_has_method(handle, "_EJ0") && acpi_device_is_battery(adev)) | ||
1690 | return true; | ||
1691 | |||
1692 | return acpi_bay_match(handle); | ||
1693 | } | ||
1694 | |||
1644 | /* | 1695 | /* |
1645 | * acpi_dock_match - see if an acpi object has a _DCK method | 1696 | * acpi_dock_match - see if an acpi object has a _DCK method |
1646 | */ | 1697 | */ |
@@ -1706,6 +1757,20 @@ static bool acpi_ibm_smbus_match(acpi_handle handle) | |||
1706 | return false; | 1757 | return false; |
1707 | } | 1758 | } |
1708 | 1759 | ||
1760 | static bool acpi_object_is_system_bus(acpi_handle handle) | ||
1761 | { | ||
1762 | acpi_handle tmp; | ||
1763 | |||
1764 | if (ACPI_SUCCESS(acpi_get_handle(NULL, "\\_SB", &tmp)) && | ||
1765 | tmp == handle) | ||
1766 | return true; | ||
1767 | if (ACPI_SUCCESS(acpi_get_handle(NULL, "\\_TZ", &tmp)) && | ||
1768 | tmp == handle) | ||
1769 | return true; | ||
1770 | |||
1771 | return false; | ||
1772 | } | ||
1773 | |||
1709 | static void acpi_set_pnp_ids(acpi_handle handle, struct acpi_device_pnp *pnp, | 1774 | static void acpi_set_pnp_ids(acpi_handle handle, struct acpi_device_pnp *pnp, |
1710 | int device_type) | 1775 | int device_type) |
1711 | { | 1776 | { |
@@ -1757,8 +1822,10 @@ static void acpi_set_pnp_ids(acpi_handle handle, struct acpi_device_pnp *pnp, | |||
1757 | acpi_add_id(pnp, ACPI_DOCK_HID); | 1822 | acpi_add_id(pnp, ACPI_DOCK_HID); |
1758 | else if (acpi_ibm_smbus_match(handle)) | 1823 | else if (acpi_ibm_smbus_match(handle)) |
1759 | acpi_add_id(pnp, ACPI_SMBUS_IBM_HID); | 1824 | acpi_add_id(pnp, ACPI_SMBUS_IBM_HID); |
1760 | else if (list_empty(&pnp->ids) && handle == ACPI_ROOT_OBJECT) { | 1825 | else if (list_empty(&pnp->ids) && |
1761 | acpi_add_id(pnp, ACPI_BUS_HID); /* \_SB, LNXSYBUS */ | 1826 | acpi_object_is_system_bus(handle)) { |
1827 | /* \_SB, \_TZ, LNXSYBUS */ | ||
1828 | acpi_add_id(pnp, ACPI_BUS_HID); | ||
1762 | strcpy(pnp->device_name, ACPI_BUS_DEVICE_NAME); | 1829 | strcpy(pnp->device_name, ACPI_BUS_DEVICE_NAME); |
1763 | strcpy(pnp->device_class, ACPI_BUS_CLASS); | 1830 | strcpy(pnp->device_class, ACPI_BUS_CLASS); |
1764 | } | 1831 | } |
@@ -1941,33 +2008,23 @@ void acpi_scan_hotplug_enabled(struct acpi_hotplug_profile *hotplug, bool val) | |||
1941 | mutex_unlock(&acpi_scan_lock); | 2008 | mutex_unlock(&acpi_scan_lock); |
1942 | } | 2009 | } |
1943 | 2010 | ||
1944 | static void acpi_scan_init_hotplug(acpi_handle handle, int type) | 2011 | static void acpi_scan_init_hotplug(struct acpi_device *adev) |
1945 | { | 2012 | { |
1946 | struct acpi_device_pnp pnp = {}; | ||
1947 | struct acpi_hardware_id *hwid; | 2013 | struct acpi_hardware_id *hwid; |
1948 | struct acpi_scan_handler *handler; | ||
1949 | 2014 | ||
1950 | INIT_LIST_HEAD(&pnp.ids); | 2015 | if (acpi_dock_match(adev->handle) || is_ejectable_bay(adev)) { |
1951 | acpi_set_pnp_ids(handle, &pnp, type); | 2016 | acpi_dock_add(adev); |
1952 | 2017 | return; | |
1953 | if (!pnp.type.hardware_id) | 2018 | } |
1954 | goto out; | 2019 | list_for_each_entry(hwid, &adev->pnp.ids, list) { |
2020 | struct acpi_scan_handler *handler; | ||
1955 | 2021 | ||
1956 | /* | ||
1957 | * This relies on the fact that acpi_install_notify_handler() will not | ||
1958 | * install the same notify handler routine twice for the same handle. | ||
1959 | */ | ||
1960 | list_for_each_entry(hwid, &pnp.ids, list) { | ||
1961 | handler = acpi_scan_match_handler(hwid->id, NULL); | 2022 | handler = acpi_scan_match_handler(hwid->id, NULL); |
1962 | if (handler) { | 2023 | if (handler) { |
1963 | acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY, | 2024 | adev->flags.hotplug_notify = true; |
1964 | acpi_hotplug_notify_cb, handler); | ||
1965 | break; | 2025 | break; |
1966 | } | 2026 | } |
1967 | } | 2027 | } |
1968 | |||
1969 | out: | ||
1970 | acpi_free_pnp_ids(&pnp); | ||
1971 | } | 2028 | } |
1972 | 2029 | ||
1973 | static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl_not_used, | 2030 | static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl_not_used, |
@@ -1991,12 +2048,12 @@ static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl_not_used, | |||
1991 | return AE_OK; | 2048 | return AE_OK; |
1992 | } | 2049 | } |
1993 | 2050 | ||
1994 | acpi_scan_init_hotplug(handle, type); | ||
1995 | |||
1996 | acpi_add_single_object(&device, handle, type, sta); | 2051 | acpi_add_single_object(&device, handle, type, sta); |
1997 | if (!device) | 2052 | if (!device) |
1998 | return AE_CTRL_DEPTH; | 2053 | return AE_CTRL_DEPTH; |
1999 | 2054 | ||
2055 | acpi_scan_init_hotplug(device); | ||
2056 | |||
2000 | out: | 2057 | out: |
2001 | if (!*return_value) | 2058 | if (!*return_value) |
2002 | *return_value = device; | 2059 | *return_value = device; |
@@ -2015,13 +2072,14 @@ static int acpi_scan_attach_handler(struct acpi_device *device) | |||
2015 | 2072 | ||
2016 | handler = acpi_scan_match_handler(hwid->id, &devid); | 2073 | handler = acpi_scan_match_handler(hwid->id, &devid); |
2017 | if (handler) { | 2074 | if (handler) { |
2075 | device->handler = handler; | ||
2018 | ret = handler->attach(device, devid); | 2076 | ret = handler->attach(device, devid); |
2019 | if (ret > 0) { | 2077 | if (ret > 0) |
2020 | device->handler = handler; | ||
2021 | break; | 2078 | break; |
2022 | } else if (ret < 0) { | 2079 | |
2080 | device->handler = NULL; | ||
2081 | if (ret < 0) | ||
2023 | break; | 2082 | break; |
2024 | } | ||
2025 | } | 2083 | } |
2026 | } | 2084 | } |
2027 | return ret; | 2085 | return ret; |
@@ -2030,8 +2088,12 @@ static int acpi_scan_attach_handler(struct acpi_device *device) | |||
2030 | static void acpi_bus_attach(struct acpi_device *device) | 2088 | static void acpi_bus_attach(struct acpi_device *device) |
2031 | { | 2089 | { |
2032 | struct acpi_device *child; | 2090 | struct acpi_device *child; |
2091 | acpi_handle ejd; | ||
2033 | int ret; | 2092 | int ret; |
2034 | 2093 | ||
2094 | if (ACPI_SUCCESS(acpi_bus_get_ejd(device->handle, &ejd))) | ||
2095 | register_dock_dependent_device(device, ejd); | ||
2096 | |||
2035 | acpi_bus_get_status(device); | 2097 | acpi_bus_get_status(device); |
2036 | /* Skip devices that are not present. */ | 2098 | /* Skip devices that are not present. */ |
2037 | if (!acpi_device_is_present(device)) { | 2099 | if (!acpi_device_is_present(device)) { |
@@ -2184,7 +2246,6 @@ int __init acpi_scan_init(void) | |||
2184 | acpi_cmos_rtc_init(); | 2246 | acpi_cmos_rtc_init(); |
2185 | acpi_container_init(); | 2247 | acpi_container_init(); |
2186 | acpi_memory_hotplug_init(); | 2248 | acpi_memory_hotplug_init(); |
2187 | acpi_dock_init(); | ||
2188 | 2249 | ||
2189 | mutex_lock(&acpi_scan_lock); | 2250 | mutex_lock(&acpi_scan_lock); |
2190 | /* | 2251 | /* |