summaryrefslogtreecommitdiffstats
path: root/drivers/acpi/device_pm.c
diff options
context:
space:
mode:
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>2014-05-17 00:18:13 +0200
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2014-05-20 13:22:48 +0200
commitf25c0ae2b4c41996c1a6b609132c1788a6eea080 (patch)
tree9e8c3d59b60daeff462f0d1049b7571a62c31764 /drivers/acpi/device_pm.c
parent55cc33ceb75643d190ed215f423972e0b7ae7aeb (diff)
downloadop-kernel-dev-f25c0ae2b4c41996c1a6b609132c1788a6eea080.zip
op-kernel-dev-f25c0ae2b4c41996c1a6b609132c1788a6eea080.tar.gz
ACPI / PM: Avoid resuming devices in ACPI PM domain during system suspend
Rework the ACPI PM domain's PM callbacks to avoid resuming devices during system suspend (in order to modify their wakeup settings etc.) if that isn't necessary. Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Diffstat (limited to 'drivers/acpi/device_pm.c')
-rw-r--r--drivers/acpi/device_pm.c43
1 files changed, 36 insertions, 7 deletions
diff --git a/drivers/acpi/device_pm.c b/drivers/acpi/device_pm.c
index d047739..9e5fd9c 100644
--- a/drivers/acpi/device_pm.c
+++ b/drivers/acpi/device_pm.c
@@ -900,18 +900,46 @@ EXPORT_SYMBOL_GPL(acpi_dev_resume_early);
*/
int acpi_subsys_prepare(struct device *dev)
{
- /*
- * Devices having power.ignore_children set may still be necessary for
- * suspending their children in the next phase of device suspend.
- */
- if (dev->power.ignore_children)
- pm_runtime_resume(dev);
+ struct acpi_device *adev = ACPI_COMPANION(dev);
+ u32 sys_target;
+ int ret, state;
+
+ ret = pm_generic_prepare(dev);
+ if (ret < 0)
+ return ret;
+
+ if (!adev || !pm_runtime_suspended(dev)
+ || device_may_wakeup(dev) != !!adev->wakeup.prepare_count)
+ return 0;
+
+ sys_target = acpi_target_system_state();
+ if (sys_target == ACPI_STATE_S0)
+ return 1;
- return pm_generic_prepare(dev);
+ if (adev->power.flags.dsw_present)
+ return 0;
+
+ ret = acpi_dev_pm_get_state(dev, adev, sys_target, NULL, &state);
+ return !ret && state == adev->power.state;
}
EXPORT_SYMBOL_GPL(acpi_subsys_prepare);
/**
+ * acpi_subsys_complete - Finalize device's resume during system resume.
+ * @dev: Device to handle.
+ */
+static void acpi_subsys_complete(struct device *dev)
+{
+ /*
+ * If the device had been runtime-suspended before the system went into
+ * the sleep state it is going out of and it has never been resumed till
+ * now, resume it in case the firmware powered it up.
+ */
+ if (dev->power.direct_complete)
+ pm_request_resume(dev);
+}
+
+/**
* acpi_subsys_suspend - Run the device driver's suspend callback.
* @dev: Device to handle.
*
@@ -979,6 +1007,7 @@ static struct dev_pm_domain acpi_general_pm_domain = {
#endif
#ifdef CONFIG_PM_SLEEP
.prepare = acpi_subsys_prepare,
+ .complete = acpi_subsys_complete,
.suspend = acpi_subsys_suspend,
.suspend_late = acpi_subsys_suspend_late,
.resume_early = acpi_subsys_resume_early,
OpenPOWER on IntegriCloud