diff options
Diffstat (limited to 'drivers/acpi')
-rw-r--r-- | drivers/acpi/bus.c | 29 | ||||
-rw-r--r-- | drivers/acpi/device_pm.c | 8 | ||||
-rw-r--r-- | drivers/acpi/internal.h | 2 | ||||
-rw-r--r-- | drivers/acpi/power.c | 15 | ||||
-rw-r--r-- | drivers/acpi/scan.c | 1 |
5 files changed, 48 insertions, 7 deletions
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index 7a3ad929f095..a23903c8bea9 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -486,6 +486,35 @@ static void acpi_device_remove_notify_handler(struct acpi_device *device) Device Matching -------------------------------------------------------------------------- */ +/** + * acpi_device_is_first_physical_node - Is given dev first physical node + * @adev: ACPI companion device + * @dev: Physical device to check + * + * Function checks if given @dev is the first physical devices attached to + * the ACPI companion device. This distinction is needed in some cases + * where the same companion device is shared between many physical devices. + * + * Note that the caller have to provide valid @adev pointer. + */ +bool acpi_device_is_first_physical_node(struct acpi_device *adev, + const struct device *dev) +{ + bool ret = false; + + mutex_lock(&adev->physical_node_lock); + if (!list_empty(&adev->physical_node_list)) { + const struct acpi_device_physical_node *node; + + node = list_first_entry(&adev->physical_node_list, + struct acpi_device_physical_node, node); + ret = node->dev == dev; + } + mutex_unlock(&adev->physical_node_lock); + + return ret; +} + /* * acpi_companion_match() - Can we match via ACPI companion device * @dev: Device in question diff --git a/drivers/acpi/device_pm.c b/drivers/acpi/device_pm.c index 717afcdb5f4a..08dc3ec7e892 100644 --- a/drivers/acpi/device_pm.c +++ b/drivers/acpi/device_pm.c @@ -1123,6 +1123,14 @@ int acpi_dev_pm_attach(struct device *dev, bool power_on) if (dev->pm_domain) return -EEXIST; + /* + * Only attach the power domain to the first device if the + * companion is shared by multiple. This is to prevent doing power + * management twice. + */ + if (!acpi_device_is_first_physical_node(adev, dev)) + return -EBUSY; + acpi_add_pm_notifier(adev, dev, acpi_pm_notify_work_func); dev->pm_domain = &acpi_general_pm_domain; if (power_on) { diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index c529454532dc..df7f7aff327b 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h @@ -99,6 +99,8 @@ void acpi_device_add_finalize(struct acpi_device *device); void acpi_free_pnp_ids(struct acpi_device_pnp *pnp); bool acpi_device_is_present(struct acpi_device *adev); bool acpi_device_is_battery(struct acpi_device *adev); +bool acpi_device_is_first_physical_node(struct acpi_device *adev, + const struct device *dev); /* -------------------------------------------------------------------------- Device Matching and Notification diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c index 93eac53b5110..ce68ae68840d 100644 --- a/drivers/acpi/power.c +++ b/drivers/acpi/power.c @@ -1,8 +1,10 @@ /* - * acpi_power.c - ACPI Bus Power Management ($Revision: 39 $) + * drivers/acpi/power.c - ACPI Power Resources management. * - * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com> - * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com> + * Copyright (C) 2001 - 2015 Intel Corp. + * Author: Andy Grover <andrew.grover@intel.com> + * Author: Paul Diefenbaugh <paul.s.diefenbaugh@intel.com> + * Author: Rafael J. Wysocki <rafael.j.wysocki@intel.com> * * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * @@ -27,10 +29,11 @@ * ACPI power-managed devices may be controlled in two ways: * 1. via "Device Specific (D-State) Control" * 2. via "Power Resource Control". - * This module is used to manage devices relying on Power Resource Control. + * The code below deals with ACPI Power Resources control. * - * An ACPI "power resource object" describes a software controllable power - * plane, clock plane, or other resource used by a power managed device. + * An ACPI "power resource object" represents a software controllable power + * plane, clock plane, or other resource depended on by a device. + * * A device may rely on multiple power resources, and a power resource * may be shared by multiple devices. */ diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 2fe5a37c385c..01136b879038 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -115,7 +115,6 @@ int acpi_scan_add_handler_with_hotplug(struct acpi_scan_handler *handler, return 0; } - bool acpi_scan_is_offline(struct acpi_device *adev, bool uevent) { struct acpi_device_physical_node *pn; |