aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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 {