aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>2014-05-16 18:18:13 -0400
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2014-05-20 07:22:48 -0400
commitf25c0ae2b4c41996c1a6b609132c1788a6eea080 (patch)
tree9e8c3d59b60daeff462f0d1049b7571a62c31764
parent55cc33ceb75643d190ed215f423972e0b7ae7aeb (diff)
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>
-rw-r--r--drivers/acpi/device_pm.c43
-rw-r--r--drivers/acpi/scan.c4
-rw-r--r--include/acpi/acpi_bus.h3
3 files changed, 42 insertions, 8 deletions
diff --git a/drivers/acpi/device_pm.c b/drivers/acpi/device_pm.c
index d047739f3380..9e5fd9c440b7 100644
--- a/drivers/acpi/device_pm.c
+++ b/drivers/acpi/device_pm.c
@@ -900,18 +900,46 @@ EXPORT_SYMBOL_GPL(acpi_dev_resume_early);
900 */ 900 */
901int acpi_subsys_prepare(struct device *dev) 901int acpi_subsys_prepare(struct device *dev)
902{ 902{
903 /* 903 struct acpi_device *adev = ACPI_COMPANION(dev);
904 * Devices having power.ignore_children set may still be necessary for 904 u32 sys_target;
905 * suspending their children in the next phase of device suspend. 905 int ret, state;
906 */ 906
907 if (dev->power.ignore_children) 907 ret = pm_generic_prepare(dev);
908 pm_runtime_resume(dev); 908 if (ret < 0)
909 return ret;
910
911 if (!adev || !pm_runtime_suspended(dev)
912 || device_may_wakeup(dev) != !!adev->wakeup.prepare_count)
913 return 0;
914
915 sys_target = acpi_target_system_state();
916 if (sys_target == ACPI_STATE_S0)
917 return 1;
909 918
910 return pm_generic_prepare(dev); 919 if (adev->power.flags.dsw_present)
920 return 0;
921
922 ret = acpi_dev_pm_get_state(dev, adev, sys_target, NULL, &state);
923 return !ret && state == adev->power.state;
911} 924}
912EXPORT_SYMBOL_GPL(acpi_subsys_prepare); 925EXPORT_SYMBOL_GPL(acpi_subsys_prepare);
913 926
914/** 927/**
928 * acpi_subsys_complete - Finalize device's resume during system resume.
929 * @dev: Device to handle.
930 */
931static void acpi_subsys_complete(struct device *dev)
932{
933 /*
934 * If the device had been runtime-suspended before the system went into
935 * the sleep state it is going out of and it has never been resumed till
936 * now, resume it in case the firmware powered it up.
937 */
938 if (dev->power.direct_complete)
939 pm_request_resume(dev);
940}
941
942/**
915 * acpi_subsys_suspend - Run the device driver's suspend callback. 943 * acpi_subsys_suspend - Run the device driver's suspend callback.
916 * @dev: Device to handle. 944 * @dev: Device to handle.
917 * 945 *
@@ -979,6 +1007,7 @@ static struct dev_pm_domain acpi_general_pm_domain = {
979#endif 1007#endif
980#ifdef CONFIG_PM_SLEEP 1008#ifdef CONFIG_PM_SLEEP
981 .prepare = acpi_subsys_prepare, 1009 .prepare = acpi_subsys_prepare,
1010 .complete = acpi_subsys_complete,
982 .suspend = acpi_subsys_suspend, 1011 .suspend = acpi_subsys_suspend,
983 .suspend_late = acpi_subsys_suspend_late, 1012 .suspend_late = acpi_subsys_suspend_late,
984 .resume_early = acpi_subsys_resume_early, 1013 .resume_early = acpi_subsys_resume_early,
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index 7efe546a8c42..df6e4c924b35 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -1551,9 +1551,13 @@ static void acpi_bus_get_power_flags(struct acpi_device *device)
1551 */ 1551 */
1552 if (acpi_has_method(device->handle, "_PSC")) 1552 if (acpi_has_method(device->handle, "_PSC"))
1553 device->power.flags.explicit_get = 1; 1553 device->power.flags.explicit_get = 1;
1554
1554 if (acpi_has_method(device->handle, "_IRC")) 1555 if (acpi_has_method(device->handle, "_IRC"))
1555 device->power.flags.inrush_current = 1; 1556 device->power.flags.inrush_current = 1;
1556 1557
1558 if (acpi_has_method(device->handle, "_DSW"))
1559 device->power.flags.dsw_present = 1;
1560
1557 /* 1561 /*
1558 * Enumerate supported power management states 1562 * Enumerate supported power management states
1559 */ 1563 */
diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h
index 84a2e29a2314..7417a16c8d86 100644
--- a/include/acpi/acpi_bus.h
+++ b/include/acpi/acpi_bus.h
@@ -261,7 +261,8 @@ struct acpi_device_power_flags {
261 u32 inrush_current:1; /* Serialize Dx->D0 */ 261 u32 inrush_current:1; /* Serialize Dx->D0 */
262 u32 power_removed:1; /* Optimize Dx->D0 */ 262 u32 power_removed:1; /* Optimize Dx->D0 */
263 u32 ignore_parent:1; /* Power is independent of parent power state */ 263 u32 ignore_parent:1; /* Power is independent of parent power state */
264 u32 reserved:27; 264 u32 dsw_present:1; /* _DSW present? */
265 u32 reserved:26;
265}; 266};
266 267
267struct acpi_device_power_state { 268struct acpi_device_power_state {