PM / sleep / ACPI: Use the ACPI_FADT_LOW_POWER_S0 flag
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>
Thu, 17 Nov 2016 02:28:53 +0000 (03:28 +0100)
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>
Mon, 21 Nov 2016 21:48:10 +0000 (22:48 +0100)
Modify the ACPI system sleep support setup code to select
suspend-to-idle as the default system sleep state if the
ACPI_FADT_LOW_POWER_S0 flag is set in the FADT and the
default sleep state was not selected from the kernel command
line.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Tested-by: Mario Limonciello <mario.limonciello@dell.com>
Documentation/power/states.txt
drivers/acpi/sleep.c
include/linux/suspend.h
kernel/power/suspend.c

index 008ecb588317bc1d354bb5f50513605d6154237c..8a39ce45d8a01c298ec3b62b878e2623cba5a958 100644 (file)
@@ -35,7 +35,9 @@ only one way to cause the system to go into the Suspend-To-RAM state (write
 The default suspend mode (ie. the one to be used without writing anything into
 /sys/power/mem_sleep) is either "deep" (if Suspend-To-RAM is supported) or
 "s2idle", but it can be overridden by the value of the "mem_sleep_default"
-parameter in the kernel command line.
+parameter in the kernel command line.  On some ACPI-based systems, depending on
+the information in the FADT, the default may be "s2idle" even if Suspend-To-RAM
+is supported.
 
 The properties of all of the sleep states are described below.
 
index deb0ff78eba8705b56292d1acf2e206541ee8bf8..ce1855fd584b190cdb6feede2e918fe4cbb0628a 100644 (file)
@@ -691,6 +691,14 @@ static void acpi_sleep_suspend_setup(void)
                if (acpi_sleep_state_supported(i))
                        sleep_states[i] = 1;
 
+       /*
+        * Use suspend-to-idle by default if ACPI_FADT_LOW_POWER_S0 is set and
+        * the default suspend mode was not selected from the command line.
+        */
+       if (acpi_gbl_FADT.flags & ACPI_FADT_LOW_POWER_S0 &&
+           mem_sleep_default > PM_SUSPEND_MEM)
+               mem_sleep_default = PM_SUSPEND_FREEZE;
+
        suspend_set_ops(old_suspend_ordering ?
                &acpi_suspend_ops_old : &acpi_suspend_ops);
        freeze_set_ops(&acpi_freeze_ops);
index d9718378a8bee0b327d08c2e80a6fd3b5490b967..0c729c3c85499a1e51f79ac7252d60d548787fb4 100644 (file)
@@ -194,6 +194,8 @@ struct platform_freeze_ops {
 };
 
 #ifdef CONFIG_SUSPEND
+extern suspend_state_t mem_sleep_default;
+
 /**
  * suspend_set_ops - set platform dependent suspend operations
  * @ops: The new suspend operations to set.
index 15e6baef5c73f90b6817c0b1c4e871ea40e30318..f67ceb7768b82ac4e183b22042f1f0784011262b 100644 (file)
@@ -46,7 +46,7 @@ static const char * const mem_sleep_labels[] = {
 const char *mem_sleep_states[PM_SUSPEND_MAX];
 
 suspend_state_t mem_sleep_current = PM_SUSPEND_FREEZE;
-static suspend_state_t mem_sleep_default = PM_SUSPEND_MEM;
+suspend_state_t mem_sleep_default = PM_SUSPEND_MAX;
 
 unsigned int pm_suspend_global_flags;
 EXPORT_SYMBOL_GPL(pm_suspend_global_flags);
@@ -168,7 +168,7 @@ void suspend_set_ops(const struct platform_suspend_ops *ops)
        }
        if (valid_state(PM_SUSPEND_MEM)) {
                mem_sleep_states[PM_SUSPEND_MEM] = mem_sleep_labels[PM_SUSPEND_MEM];
-               if (mem_sleep_default == PM_SUSPEND_MEM)
+               if (mem_sleep_default >= PM_SUSPEND_MEM)
                        mem_sleep_current = PM_SUSPEND_MEM;
        }