summaryrefslogtreecommitdiffstats
path: root/drivers/acpi
diff options
context:
space:
mode:
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>2015-09-01 03:38:43 +0200
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2015-09-01 03:38:43 +0200
commitef5f5de069bd9081a7ddf6998269b58fc65e27ef (patch)
tree21d53507543248f81725cbc486625f77562f935d /drivers/acpi
parent73990fc810bf84c5338d9596f8af8d70fe90ac72 (diff)
parente91a398c31cef2d51786642e372c503cd43fba90 (diff)
downloadlinux-ef5f5de069bd9081a7ddf6998269b58fc65e27ef.tar.bz2
Merge branch 'acpi-pm'
* acpi-pm: ACPI / bus: Move duplicate code to a separate new function mfd: Add support for Intel Sunrisepoint LPSS devices dmaengine: add a driver for Intel integrated DMA 64-bit mfd: make mfd_remove_devices() iterate in reverse order driver core: implement device_for_each_child_reverse() klist: implement klist_prev() Driver core: wakeup the parent device before trying probe ACPI / PM: Attach ACPI power domain only once PM / QoS: Make it possible to expose device latency tolerance to userspace ACPI / PM: Update the copyright notice and description of power.c
Diffstat (limited to 'drivers/acpi')
-rw-r--r--drivers/acpi/bus.c54
-rw-r--r--drivers/acpi/device_pm.c8
-rw-r--r--drivers/acpi/internal.h2
-rw-r--r--drivers/acpi/power.c15
-rw-r--r--drivers/acpi/scan.c1
5 files changed, 57 insertions, 23 deletions
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
index 54a2e66ce236..46506e7687cd 100644
--- a/drivers/acpi/bus.c
+++ b/drivers/acpi/bus.c
@@ -482,6 +482,43 @@ static void acpi_device_remove_notify_handler(struct acpi_device *device)
Device Matching
-------------------------------------------------------------------------- */
+static struct acpi_device *acpi_primary_dev_companion(struct acpi_device *adev,
+ const struct device *dev)
+{
+ struct mutex *physical_node_lock = &adev->physical_node_lock;
+
+ mutex_lock(physical_node_lock);
+ if (list_empty(&adev->physical_node_list)) {
+ adev = NULL;
+ } else {
+ const struct acpi_device_physical_node *node;
+
+ node = list_first_entry(&adev->physical_node_list,
+ struct acpi_device_physical_node, node);
+ if (node->dev != dev)
+ adev = NULL;
+ }
+ mutex_unlock(physical_node_lock);
+ return adev;
+}
+
+/**
+ * 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)
+{
+ return !!acpi_primary_dev_companion(adev, dev);
+}
+
/*
* acpi_companion_match() - Can we match via ACPI companion device
* @dev: Device in question
@@ -506,7 +543,6 @@ static void acpi_device_remove_notify_handler(struct acpi_device *device)
struct acpi_device *acpi_companion_match(const struct device *dev)
{
struct acpi_device *adev;
- struct mutex *physical_node_lock;
adev = ACPI_COMPANION(dev);
if (!adev)
@@ -515,21 +551,7 @@ struct acpi_device *acpi_companion_match(const struct device *dev)
if (list_empty(&adev->pnp.ids))
return NULL;
- physical_node_lock = &adev->physical_node_lock;
- mutex_lock(physical_node_lock);
- if (list_empty(&adev->physical_node_list)) {
- adev = NULL;
- } else {
- const struct acpi_device_physical_node *node;
-
- node = list_first_entry(&adev->physical_node_list,
- struct acpi_device_physical_node, node);
- if (node->dev != dev)
- adev = NULL;
- }
- mutex_unlock(physical_node_lock);
-
- return adev;
+ return acpi_primary_dev_companion(adev, dev);
}
/**
diff --git a/drivers/acpi/device_pm.c b/drivers/acpi/device_pm.c
index da0867899d10..4806b7f856c4 100644
--- a/drivers/acpi/device_pm.c
+++ b/drivers/acpi/device_pm.c
@@ -1119,6 +1119,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 2c195cd5ab1b..9e426210c2a8 100644
--- a/drivers/acpi/internal.h
+++ b/drivers/acpi/internal.h
@@ -96,6 +96,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 45b47f2c9f03..fcd4ce6f78d5 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>
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
@@ -23,10 +25,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;