summaryrefslogtreecommitdiff
path: root/drivers/acpi/scan.c
diff options
context:
space:
mode:
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>2014-02-16 04:51:01 +0400
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2014-02-16 04:51:01 +0400
commit1e2380cd144f6a9619f72f80ad9a93268f63b8dc (patch)
tree03f661af52c942b0d1c7523c1bd05af59b610671 /drivers/acpi/scan.c
parentd6a40224a30687f6e0471c4476e3a1a9adc28a96 (diff)
downloadlinux-1e2380cd144f6a9619f72f80ad9a93268f63b8dc.tar.xz
ACPI / dock: Dispatch dock notifications from the global notify handler
The ACPI dock station code carries out an extra namespace scan before the main one in order to find and register all of the dock device objects. Then, it registers a notify handler for each of them for handling dock events. However, dock device objects need not be scanned for upfront. They very well can be enumerated and registered during the first phase of the main namespace scan, before attaching scan handlers and ACPI drivers to ACPI device objects. Then, the dependent devices can be added to the in the second phase. That makes it possible to drop the extra namespace scan, so do it. Moreover, it is not necessary to register notify handlers for all of the dock stations' namespace nodes, becuase notifications may be dispatched from the global notify handler for them. Do that and drop two functions used for dock notify handling, acpi_dock_deferred_cb() and dock_notify_handler(), that aren't necessary any more. Finally, some dock station objects have _HID objects matching the ACPI container scan handler which causes it to claim those objects and try to handle their hotplug, but that is not a good idea, because those objects have their own special hotplug handling anyway. For this reason, the hotplug_notify flag should not be set for ACPI device objects representing dock stations and the container scan handler should be made ignore those objects, so make that happen. Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Diffstat (limited to 'drivers/acpi/scan.c')
-rw-r--r--drivers/acpi/scan.c36
1 files changed, 34 insertions, 2 deletions
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index 8bb48bfab1df..ec12d970d78d 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -487,7 +487,9 @@ void acpi_device_hotplug(void *data, u32 src)
if (adev->handle == INVALID_ACPI_HANDLE)
goto err_out;
- if (adev->flags.hotplug_notify) {
+ if (adev->flags.is_dock_station) {
+ error = dock_notify(adev, src);
+ } else if (adev->flags.hotplug_notify) {
error = acpi_generic_hotplug_event(adev, src);
if (error == -EPERM) {
ost_code = ACPI_OST_SC_EJECT_NOT_SUPPORTED;
@@ -1660,6 +1662,29 @@ bool acpi_bay_match(acpi_handle handle)
return acpi_ata_match(phandle);
}
+bool acpi_device_is_battery(acpi_handle handle)
+{
+ struct acpi_device_info *info;
+ bool ret = false;
+
+ if (!ACPI_SUCCESS(acpi_get_object_info(handle, &info)))
+ return false;
+
+ if (info->valid & ACPI_VALID_HID)
+ ret = !strcmp("PNP0C0A", info->hardware_id.string);
+
+ kfree(info);
+ return ret;
+}
+
+static bool is_ejectable_bay(acpi_handle handle)
+{
+ if (acpi_has_method(handle, "_EJ0") && acpi_device_is_battery(handle))
+ return true;
+
+ return acpi_bay_match(handle);
+}
+
/*
* acpi_dock_match - see if an acpi object has a _DCK method
*/
@@ -1964,6 +1989,10 @@ static void acpi_scan_init_hotplug(struct acpi_device *adev)
{
struct acpi_hardware_id *hwid;
+ if (acpi_dock_match(adev->handle) || is_ejectable_bay(adev->handle)) {
+ acpi_dock_add(adev);
+ return;
+ }
list_for_each_entry(hwid, &adev->pnp.ids, list) {
struct acpi_scan_handler *handler;
@@ -2035,8 +2064,12 @@ static int acpi_scan_attach_handler(struct acpi_device *device)
static void acpi_bus_attach(struct acpi_device *device)
{
struct acpi_device *child;
+ acpi_handle ejd;
int ret;
+ if (ACPI_SUCCESS(acpi_bus_get_ejd(device->handle, &ejd)))
+ register_dock_dependent_device(device, ejd);
+
acpi_bus_get_status(device);
/* Skip devices that are not present. */
if (!acpi_device_is_present(device)) {
@@ -2189,7 +2222,6 @@ int __init acpi_scan_init(void)
acpi_cmos_rtc_init();
acpi_container_init();
acpi_memory_hotplug_init();
- acpi_dock_init();
mutex_lock(&acpi_scan_lock);
/*