Commit 0399d4db authored by Rafael J. Wysocki's avatar Rafael J. Wysocki

PM / sleep: Introduce command line argument for sleep state enumeration

On some systems the platform doesn't support neither
PM_SUSPEND_MEM nor PM_SUSPEND_STANDBY, so PM_SUSPEND_FREEZE is the
only available system sleep state.  However, some user space frameworks
only use the "mem" and (sometimes) "standby" sleep state labels, so
the users of those systems need to modify user space in order to be
able to use system suspend at all and that is not always possible.

For this reason, add a new kernel command line argument,
relative_sleep_states, allowing the users of those systems to change
the way in which the kernel assigns labels to system sleep states.
Namely, for relative_sleep_states=1, the "mem", "standby" and "freeze"
labels will enumerate the available system sleem states from the
deepest to the shallowest, respectively, so that "mem" is always
present in /sys/power/state and the other state strings may or may
not be presend depending on what is supported by the platform.

Update system sleep states documentation to reflect this change.
Signed-off-by: default avatarRafael J. Wysocki <rafael.j.wysocki@intel.com>
parent 43e8317b
...@@ -7,19 +7,30 @@ Description: ...@@ -7,19 +7,30 @@ Description:
subsystem. subsystem.
What: /sys/power/state What: /sys/power/state
Date: August 2006 Date: May 2014
Contact: Rafael J. Wysocki <rjw@rjwysocki.net> Contact: Rafael J. Wysocki <rjw@rjwysocki.net>
Description: Description:
The /sys/power/state file controls the system power state. The /sys/power/state file controls system sleep states.
Reading from this file returns what states are supported, Reading from this file returns the available sleep state
which is hard-coded to 'freeze' (Low-Power Idle), 'standby' labels, which may be "mem", "standby", "freeze" and "disk"
(Power-On Suspend), 'mem' (Suspend-to-RAM), and 'disk' (hibernation). The meanings of the first three labels depend on
(Suspend-to-Disk). the relative_sleep_states command line argument as follows:
1) relative_sleep_states = 1
"mem", "standby", "freeze" represent non-hibernation sleep
states from the deepest ("mem", always present) to the
shallowest ("freeze"). "standby" and "freeze" may or may
not be present depending on the capabilities of the
platform. "freeze" can only be present if "standby" is
present.
2) relative_sleep_states = 0 (default)
"mem" - "suspend-to-RAM", present if supported.
"standby" - "power-on suspend", present if supported.
"freeze" - "suspend-to-idle", always present.
Writing to this file one of these strings causes the system to Writing to this file one of these strings causes the system to
transition into that state. Please see the file transition into the corresponding state, if available. See
Documentation/power/states.txt for a description of each of Documentation/power/states.txt for a description of what
these states. "suspend-to-RAM", "power-on suspend" and "suspend-to-idle" mean.
What: /sys/power/disk What: /sys/power/disk
Date: September 2006 Date: September 2006
......
...@@ -2889,6 +2889,13 @@ bytes respectively. Such letter suffixes can also be entirely omitted. ...@@ -2889,6 +2889,13 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
[KNL, SMP] Set scheduler's default relax_domain_level. [KNL, SMP] Set scheduler's default relax_domain_level.
See Documentation/cgroups/cpusets.txt. See Documentation/cgroups/cpusets.txt.
relative_sleep_states=
[SUSPEND] Use sleep state labeling where the deepest
state available other than hibernation is always "mem".
Format: { "0" | "1" }
0 -- Traditional sleep state labels.
1 -- Relative sleep state labels.
reserve= [KNL,BUGS] Force the kernel to ignore some iomem area reserve= [KNL,BUGS] Force the kernel to ignore some iomem area
reservetop= [X86-32] reservetop= [X86-32]
......
System Power Management Sleep States
System Power Management States (C) 2014 Intel Corp., Rafael J. Wysocki <rafael.j.wysocki@intel.com>
The kernel supports up to four system sleep states generically, although three
of them depend on the platform support code to implement the low-level details
for each state.
The kernel supports four power management states generically, though The states are represented by strings that can be read or written to the
one is generic and the other three are dependent on platform support /sys/power/state file. Those strings may be "mem", "standby", "freeze" and
code to implement the low-level details for each state. "disk", where the last one always represents hibernation (Suspend-To-Disk) and
This file describes each state, what they are the meaning of the remaining ones depends on the relative_sleep_states command
commonly called, what ACPI state they map to, and what string to write line argument.
to /sys/power/state to enter that state
state: Freeze / Low-Power Idle For relative_sleep_states=1, the strings "mem", "standby" and "freeze" label the
available non-hibernation sleep states from the deepest to the shallowest,
respectively. In that case, "mem" is always present in /sys/power/state,
because there is at least one non-hibernation sleep state in every system. If
the given system supports two non-hibernation sleep states, "standby" is present
in /sys/power/state in addition to "mem". If the system supports three
non-hibernation sleep states, "freeze" will be present in /sys/power/state in
addition to "mem" and "standby".
For relative_sleep_states=0, which is the default, the following descriptions
apply.
state: Suspend-To-Idle
ACPI state: S0 ACPI state: S0
String: "freeze" Label: "freeze"
This state is a generic, pure software, light-weight, low-power state. This state is a generic, pure software, light-weight, system sleep state.
It allows more energy to be saved relative to idle by freezing user It allows more energy to be saved relative to runtime idle by freezing user
space and putting all I/O devices into low-power states (possibly space and putting all I/O devices into low-power states (possibly
lower-power than available at run time), such that the processors can lower-power than available at run time), such that the processors can
spend more time in their idle states. spend more time in their idle states.
This state can be used for platforms without Standby/Suspend-to-RAM
This state can be used for platforms without Power-On Suspend/Suspend-to-RAM
support, or it can be used in addition to Suspend-to-RAM (memory sleep) support, or it can be used in addition to Suspend-to-RAM (memory sleep)
to provide reduced resume latency. to provide reduced resume latency. It is always supported.
State: Standby / Power-On Suspend State: Standby / Power-On Suspend
ACPI State: S1 ACPI State: S1
String: "standby" Label: "standby"
This state offers minimal, though real, power savings, while providing This state, if supported, offers moderate, though real, power savings, while
a very low-latency transition back to a working system. No operating providing a relatively low-latency transition back to a working system. No
state is lost (the CPU retains power), so the system easily starts up operating state is lost (the CPU retains power), so the system easily starts up
again where it left off. again where it left off.
We try to put devices in a low-power state equivalent to D1, which In addition to freezing user space and putting all I/O devices into low-power
also offers low power savings, but low resume latency. Not all devices states, which is done for Suspend-To-Idle too, nonboot CPUs are taken offline
support D1, and those that don't are left on. and all low-level system functions are suspended during transitions into this
state. For this reason, it should allow more energy to be saved relative to
Suspend-To-Idle, but the resume latency will generally be greater than for that
state.
State: Suspend-to-RAM State: Suspend-to-RAM
ACPI State: S3 ACPI State: S3
String: "mem" Label: "mem"
This state offers significant power savings as everything in the This state, if supported, offers significant power savings as everything in the
system is put into a low-power state, except for memory, which is system is put into a low-power state, except for memory, which should be placed
placed in self-refresh mode to retain its contents. into the self-refresh mode to retain its contents. All of the steps carried out
when entering Power-On Suspend are also carried out during transitions to STR.
Additional operations may take place depending on the platform capabilities. In
particular, on ACPI systems the kernel passes control to the BIOS (platform
firmware) as the last step during STR transitions and that usually results in
powering down some more low-level components that aren't directly controlled by
the kernel.
System and device state is saved and kept in memory. All devices are System and device state is saved and kept in memory. All devices are suspended
suspended and put into D3. In many cases, all peripheral buses lose and put into low-power states. In many cases, all peripheral buses lose power
power when entering STR, so devices must be able to handle the when entering STR, so devices must be able to handle the transition back to the
transition back to the On state. "on" state.
For at least ACPI, STR requires some minimal boot-strapping code to For at least ACPI, STR requires some minimal boot-strapping code to resume the
resume the system from STR. This may be true on other platforms. system from it. This may be the case on other platforms too.
State: Suspend-to-disk State: Suspend-to-disk
ACPI State: S4 ACPI State: S4
String: "disk" Label: "disk"
This state offers the greatest power savings, and can be used even in This state offers the greatest power savings, and can be used even in
the absence of low-level platform support for power management. This the absence of low-level platform support for power management. This
......
...@@ -279,14 +279,14 @@ static inline void pm_print_times_init(void) {} ...@@ -279,14 +279,14 @@ static inline void pm_print_times_init(void) {}
struct kobject *power_kobj; struct kobject *power_kobj;
/** /**
* state - control system power state. * state - control system sleep states.
* *
* show() returns what states are supported, which is hard-coded to * show() returns available sleep state labels, which may be "mem", "standby",
* 'freeze' (Low-Power Idle), 'standby' (Power-On Suspend), * "freeze" and "disk" (hibernation). See Documentation/power/states.txt for a
* 'mem' (Suspend-to-RAM), and 'disk' (Suspend-to-Disk). * description of what they mean.
* *
* store() accepts one of those strings, translates it into the * store() accepts one of those strings, translates it into the proper
* proper enumerated value, and initiates a suspend transition. * enumerated value, and initiates a suspend transition.
*/ */
static ssize_t state_show(struct kobject *kobj, struct kobj_attribute *attr, static ssize_t state_show(struct kobject *kobj, struct kobj_attribute *attr,
char *buf) char *buf)
......
...@@ -78,6 +78,26 @@ static bool valid_state(suspend_state_t state) ...@@ -78,6 +78,26 @@ static bool valid_state(suspend_state_t state)
return suspend_ops && suspend_ops->valid && suspend_ops->valid(state); return suspend_ops && suspend_ops->valid && suspend_ops->valid(state);
} }
/*
* If this is set, the "mem" label always corresponds to the deepest sleep state
* available, the "standby" label corresponds to the second deepest sleep state
* available (if any), and the "freeze" label corresponds to the remaining
* available sleep state (if there is one).
*/
static bool relative_states;
static int __init sleep_states_setup(char *str)
{
relative_states = !strncmp(str, "1", 1);
if (relative_states) {
pm_states[PM_SUSPEND_MEM].state = PM_SUSPEND_FREEZE;
pm_states[PM_SUSPEND_FREEZE].state = 0;
}
return 1;
}
__setup("relative_sleep_states=", sleep_states_setup);
/** /**
* suspend_set_ops - Set the global suspend method table. * suspend_set_ops - Set the global suspend method table.
* @ops: Suspend operations to use. * @ops: Suspend operations to use.
...@@ -85,12 +105,20 @@ static bool valid_state(suspend_state_t state) ...@@ -85,12 +105,20 @@ static bool valid_state(suspend_state_t state)
void suspend_set_ops(const struct platform_suspend_ops *ops) void suspend_set_ops(const struct platform_suspend_ops *ops)
{ {
suspend_state_t i; suspend_state_t i;
int j = PM_SUSPEND_MAX - 1;
lock_system_sleep(); lock_system_sleep();
suspend_ops = ops; suspend_ops = ops;
for (i = PM_SUSPEND_STANDBY; i <= PM_SUSPEND_MEM; i++) for (i = PM_SUSPEND_MEM; i >= PM_SUSPEND_STANDBY; i--)
pm_states[i].state = valid_state(i) ? i : 0; if (valid_state(i))
pm_states[j--].state = i;
else if (!relative_states)
pm_states[j--].state = 0;
pm_states[j--].state = PM_SUSPEND_FREEZE;
while (j >= PM_SUSPEND_MIN)
pm_states[j--].state = 0;
unlock_system_sleep(); unlock_system_sleep();
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment