2019-06-01 16:08:42 +08:00
|
|
|
// SPDX-License-Identifier: GPL-2.0-only
|
2005-04-17 06:20:36 +08:00
|
|
|
/*
|
|
|
|
* kernel/power/main.c - PM subsystem core functionality.
|
|
|
|
*
|
|
|
|
* Copyright (c) 2003 Patrick Mochel
|
|
|
|
* Copyright (c) 2003 Open Source Development Lab
|
|
|
|
*/
|
|
|
|
|
2011-05-27 04:00:52 +08:00
|
|
|
#include <linux/export.h>
|
2005-04-17 06:20:36 +08:00
|
|
|
#include <linux/kobject.h>
|
|
|
|
#include <linux/string.h>
|
2015-03-18 22:54:27 +08:00
|
|
|
#include <linux/pm-trace.h>
|
2009-08-19 05:38:32 +08:00
|
|
|
#include <linux/workqueue.h>
|
PM / Suspend: Add statistics debugfs file for suspend to RAM
Record S3 failure time about each reason and the latest two failed
devices' names in S3 progress.
We can check it through 'suspend_stats' entry in debugfs.
The motivation of the patch:
We are enabling power features on Medfield. Comparing with PC/notebook,
a mobile enters/exits suspend-2-ram (we call it s3 on Medfield) far
more frequently. If it can't enter suspend-2-ram in time, the power
might be used up soon.
We often find sometimes, a device suspend fails. Then, system retries
s3 over and over again. As display is off, testers and developers
don't know what happens.
Some testers and developers complain they don't know if system
tries suspend-2-ram, and what device fails to suspend. They need
such info for a quick check. The patch adds suspend_stats under
debugfs for users to check suspend to RAM statistics quickly.
If not using this patch, we have other methods to get info about
what device fails. One is to turn on CONFIG_PM_DEBUG, but users
would get too much info and testers need recompile the system.
In addition, dynamic debug is another good tool to dump debug info.
But it still doesn't match our utilization scenario closely.
1) user need write a user space parser to process the syslog output;
2) Our testing scenario is we leave the mobile for at least hours.
Then, check its status. No serial console available during the
testing. One is because console would be suspended, and the other
is serial console connecting with spi or HSU devices would consume
power. These devices are powered off at suspend-2-ram.
Signed-off-by: ShuoX Liu <shuox.liu@intel.com>
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
2011-08-11 05:01:26 +08:00
|
|
|
#include <linux/debugfs.h>
|
|
|
|
#include <linux/seq_file.h>
|
2018-07-31 16:51:32 +08:00
|
|
|
#include <linux/suspend.h>
|
2019-02-25 20:36:41 +08:00
|
|
|
#include <linux/syscalls.h>
|
2019-10-08 18:46:46 +08:00
|
|
|
#include <linux/pm_runtime.h>
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
#include "power.h"
|
|
|
|
|
2011-02-11 07:04:52 +08:00
|
|
|
#ifdef CONFIG_PM_SLEEP
|
|
|
|
|
2018-01-06 01:19:08 +08:00
|
|
|
void lock_system_sleep(void)
|
|
|
|
{
|
|
|
|
current->flags |= PF_FREEZER_SKIP;
|
2018-07-31 16:51:32 +08:00
|
|
|
mutex_lock(&system_transition_mutex);
|
2018-01-06 01:19:08 +08:00
|
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(lock_system_sleep);
|
|
|
|
|
|
|
|
void unlock_system_sleep(void)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Don't use freezer_count() because we don't want the call to
|
|
|
|
* try_to_freeze() here.
|
|
|
|
*
|
|
|
|
* Reason:
|
|
|
|
* Fundamentally, we just don't need it, because freezing condition
|
2018-07-31 16:51:32 +08:00
|
|
|
* doesn't come into effect until we release the
|
|
|
|
* system_transition_mutex lock, since the freezer always works with
|
|
|
|
* system_transition_mutex held.
|
2018-01-06 01:19:08 +08:00
|
|
|
*
|
|
|
|
* More importantly, in the case of hibernation,
|
|
|
|
* unlock_system_sleep() gets called in snapshot_read() and
|
|
|
|
* snapshot_write() when the freezing condition is still in effect.
|
|
|
|
* Which means, if we use try_to_freeze() here, it would make them
|
|
|
|
* enter the refrigerator, thus causing hibernation to lockup.
|
|
|
|
*/
|
|
|
|
current->flags &= ~PF_FREEZER_SKIP;
|
2018-07-31 16:51:32 +08:00
|
|
|
mutex_unlock(&system_transition_mutex);
|
2018-01-06 01:19:08 +08:00
|
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(unlock_system_sleep);
|
|
|
|
|
2019-02-25 20:36:41 +08:00
|
|
|
void ksys_sync_helper(void)
|
|
|
|
{
|
2019-02-25 20:36:43 +08:00
|
|
|
ktime_t start;
|
|
|
|
long elapsed_msecs;
|
|
|
|
|
|
|
|
start = ktime_get();
|
2019-02-25 20:36:41 +08:00
|
|
|
ksys_sync();
|
2019-02-25 20:36:43 +08:00
|
|
|
elapsed_msecs = ktime_to_ms(ktime_sub(ktime_get(), start));
|
|
|
|
pr_info("Filesystems sync: %ld.%03ld seconds\n",
|
|
|
|
elapsed_msecs / MSEC_PER_SEC, elapsed_msecs % MSEC_PER_SEC);
|
2019-02-25 20:36:41 +08:00
|
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(ksys_sync_helper);
|
|
|
|
|
2007-11-20 06:49:18 +08:00
|
|
|
/* Routines for PM-transition notifications */
|
|
|
|
|
|
|
|
static BLOCKING_NOTIFIER_HEAD(pm_chain_head);
|
|
|
|
|
|
|
|
int register_pm_notifier(struct notifier_block *nb)
|
|
|
|
{
|
|
|
|
return blocking_notifier_chain_register(&pm_chain_head, nb);
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(register_pm_notifier);
|
|
|
|
|
|
|
|
int unregister_pm_notifier(struct notifier_block *nb)
|
|
|
|
{
|
|
|
|
return blocking_notifier_chain_unregister(&pm_chain_head, nb);
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(unregister_pm_notifier);
|
|
|
|
|
2016-06-20 14:52:27 +08:00
|
|
|
int __pm_notifier_call_chain(unsigned long val, int nr_to_call, int *nr_calls)
|
2007-11-20 06:49:18 +08:00
|
|
|
{
|
2016-06-20 14:52:27 +08:00
|
|
|
int ret;
|
|
|
|
|
|
|
|
ret = __blocking_notifier_call_chain(&pm_chain_head, val, NULL,
|
|
|
|
nr_to_call, nr_calls);
|
2011-07-09 02:53:36 +08:00
|
|
|
|
|
|
|
return notifier_to_errno(ret);
|
2007-11-20 06:49:18 +08:00
|
|
|
}
|
2016-06-20 14:52:27 +08:00
|
|
|
int pm_notifier_call_chain(unsigned long val)
|
|
|
|
{
|
|
|
|
return __pm_notifier_call_chain(val, -1, NULL);
|
|
|
|
}
|
2007-11-20 06:49:18 +08:00
|
|
|
|
2010-01-24 05:25:15 +08:00
|
|
|
/* If set, devices may be suspended and resumed asynchronously. */
|
|
|
|
int pm_async_enabled = 1;
|
|
|
|
|
|
|
|
static ssize_t pm_async_show(struct kobject *kobj, struct kobj_attribute *attr,
|
|
|
|
char *buf)
|
|
|
|
{
|
|
|
|
return sprintf(buf, "%d\n", pm_async_enabled);
|
|
|
|
}
|
|
|
|
|
|
|
|
static ssize_t pm_async_store(struct kobject *kobj, struct kobj_attribute *attr,
|
|
|
|
const char *buf, size_t n)
|
|
|
|
{
|
|
|
|
unsigned long val;
|
|
|
|
|
2012-10-23 07:20:35 +08:00
|
|
|
if (kstrtoul(buf, 10, &val))
|
2010-01-24 05:25:15 +08:00
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
if (val > 1)
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
pm_async_enabled = val;
|
|
|
|
return n;
|
|
|
|
}
|
|
|
|
|
|
|
|
power_attr(pm_async);
|
|
|
|
|
PM / sleep: System sleep state selection interface rework
There are systems in which the platform doesn't support any special
sleep states, so suspend-to-idle (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 may be a pain in practice.
Commit 0399d4db3edf (PM / sleep: Introduce command line argument for
sleep state enumeration) attempted to address this problem by adding
a command line argument to change the meaning of the "mem" string in
/sys/power/state to make it trigger suspend-to-idle (instead of
suspend-to-RAM).
However, there also are systems in which the platform does support
special sleep states, but suspend-to-idle is the preferred one anyway
(it even may save more energy than the platform-provided sleep states
in some cases) and the above commit doesn't help in those cases.
For this reason, rework the system sleep state selection interface
again (but preserve backwards compatibiliby). Namely, add a new
sysfs file, /sys/power/mem_sleep, that will control the system
suspend mode triggered by writing "mem" to /sys/power/state (in
analogy with what /sys/power/disk does for hibernation). Make it
select suspend-to-RAM ("deep" sleep) by default (if supported) and
fall back to suspend-to-idle ("s2idle") otherwise and add a new
command line argument, mem_sleep_default, allowing that default to
be overridden if need be.
At the same time, drop the relative_sleep_states command line
argument that doesn't make sense any more.
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Tested-by: Mario Limonciello <mario.limonciello@dell.com>
2016-11-22 05:45:40 +08:00
|
|
|
#ifdef CONFIG_SUSPEND
|
|
|
|
static ssize_t mem_sleep_show(struct kobject *kobj, struct kobj_attribute *attr,
|
|
|
|
char *buf)
|
|
|
|
{
|
|
|
|
char *s = buf;
|
|
|
|
suspend_state_t i;
|
|
|
|
|
|
|
|
for (i = PM_SUSPEND_MIN; i < PM_SUSPEND_MAX; i++)
|
|
|
|
if (mem_sleep_states[i]) {
|
|
|
|
const char *label = mem_sleep_states[i];
|
|
|
|
|
|
|
|
if (mem_sleep_current == i)
|
|
|
|
s += sprintf(s, "[%s] ", label);
|
|
|
|
else
|
|
|
|
s += sprintf(s, "%s ", label);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Convert the last space to a newline if needed. */
|
|
|
|
if (s != buf)
|
|
|
|
*(s-1) = '\n';
|
|
|
|
|
|
|
|
return (s - buf);
|
|
|
|
}
|
|
|
|
|
|
|
|
static suspend_state_t decode_suspend_state(const char *buf, size_t n)
|
|
|
|
{
|
|
|
|
suspend_state_t state;
|
|
|
|
char *p;
|
|
|
|
int len;
|
|
|
|
|
|
|
|
p = memchr(buf, '\n', n);
|
|
|
|
len = p ? p - buf : n;
|
|
|
|
|
|
|
|
for (state = PM_SUSPEND_MIN; state < PM_SUSPEND_MAX; state++) {
|
|
|
|
const char *label = mem_sleep_states[state];
|
|
|
|
|
|
|
|
if (label && len == strlen(label) && !strncmp(buf, label, len))
|
|
|
|
return state;
|
|
|
|
}
|
|
|
|
|
|
|
|
return PM_SUSPEND_ON;
|
|
|
|
}
|
|
|
|
|
|
|
|
static ssize_t mem_sleep_store(struct kobject *kobj, struct kobj_attribute *attr,
|
|
|
|
const char *buf, size_t n)
|
|
|
|
{
|
|
|
|
suspend_state_t state;
|
|
|
|
int error;
|
|
|
|
|
|
|
|
error = pm_autosleep_lock();
|
|
|
|
if (error)
|
|
|
|
return error;
|
|
|
|
|
|
|
|
if (pm_autosleep_state() > PM_SUSPEND_ON) {
|
|
|
|
error = -EBUSY;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
state = decode_suspend_state(buf, n);
|
|
|
|
if (state < PM_SUSPEND_MAX && state > PM_SUSPEND_ON)
|
|
|
|
mem_sleep_current = state;
|
|
|
|
else
|
|
|
|
error = -EINVAL;
|
|
|
|
|
|
|
|
out:
|
|
|
|
pm_autosleep_unlock();
|
|
|
|
return error ? error : n;
|
|
|
|
}
|
|
|
|
|
|
|
|
power_attr(mem_sleep);
|
2020-01-16 19:53:54 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* sync_on_suspend: invoke ksys_sync_helper() before suspend.
|
|
|
|
*
|
|
|
|
* show() returns whether ksys_sync_helper() is invoked before suspend.
|
|
|
|
* store() accepts 0 or 1. 0 disables ksys_sync_helper() and 1 enables it.
|
|
|
|
*/
|
|
|
|
bool sync_on_suspend_enabled = !IS_ENABLED(CONFIG_SUSPEND_SKIP_SYNC);
|
|
|
|
|
|
|
|
static ssize_t sync_on_suspend_show(struct kobject *kobj,
|
|
|
|
struct kobj_attribute *attr, char *buf)
|
|
|
|
{
|
|
|
|
return sprintf(buf, "%d\n", sync_on_suspend_enabled);
|
|
|
|
}
|
|
|
|
|
|
|
|
static ssize_t sync_on_suspend_store(struct kobject *kobj,
|
|
|
|
struct kobj_attribute *attr,
|
|
|
|
const char *buf, size_t n)
|
|
|
|
{
|
|
|
|
unsigned long val;
|
|
|
|
|
|
|
|
if (kstrtoul(buf, 10, &val))
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
if (val > 1)
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
sync_on_suspend_enabled = !!val;
|
|
|
|
return n;
|
|
|
|
}
|
|
|
|
|
|
|
|
power_attr(sync_on_suspend);
|
PM / sleep: System sleep state selection interface rework
There are systems in which the platform doesn't support any special
sleep states, so suspend-to-idle (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 may be a pain in practice.
Commit 0399d4db3edf (PM / sleep: Introduce command line argument for
sleep state enumeration) attempted to address this problem by adding
a command line argument to change the meaning of the "mem" string in
/sys/power/state to make it trigger suspend-to-idle (instead of
suspend-to-RAM).
However, there also are systems in which the platform does support
special sleep states, but suspend-to-idle is the preferred one anyway
(it even may save more energy than the platform-provided sleep states
in some cases) and the above commit doesn't help in those cases.
For this reason, rework the system sleep state selection interface
again (but preserve backwards compatibiliby). Namely, add a new
sysfs file, /sys/power/mem_sleep, that will control the system
suspend mode triggered by writing "mem" to /sys/power/state (in
analogy with what /sys/power/disk does for hibernation). Make it
select suspend-to-RAM ("deep" sleep) by default (if supported) and
fall back to suspend-to-idle ("s2idle") otherwise and add a new
command line argument, mem_sleep_default, allowing that default to
be overridden if need be.
At the same time, drop the relative_sleep_states command line
argument that doesn't make sense any more.
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Tested-by: Mario Limonciello <mario.limonciello@dell.com>
2016-11-22 05:45:40 +08:00
|
|
|
#endif /* CONFIG_SUSPEND */
|
|
|
|
|
2017-07-21 20:44:02 +08:00
|
|
|
#ifdef CONFIG_PM_SLEEP_DEBUG
|
Suspend: Testing facility (rev. 2)
Introduce sysfs attribute /sys/power/pm_test allowing one to test the suspend
core code. Namely, writing one of the strings:
freezer
devices
platform
processors
core
to this file causes the suspend code to work in one of the test modes defined as
follows:
freezer
- test the freezing of processes
devices
- test the freezing of processes and suspending of devices
platform
- test the freezing of processes, suspending of devices and platform global
control methods(*)
processors
- test the freezing of processes, suspending of devices, platform global
control methods and the disabling of nonboot CPUs
core
- test the freezing of processes, suspending of devices, platform global
control methods, the disabling of nonboot CPUs and suspending of
platform/system devices
(*) These are ACPI global control methods on ACPI systems
Then, if a suspend is started by normal means, the suspend core will perform
its normal operations up to the point indicated by given test level. Next, it
will wait for 5 seconds and carry out the resume operations needed to transition
the system back to the fully functional state.
Writing "none" to /sys/power/pm_test turns the testing off.
When open for reading, /sys/power/pm_test contains a space-separated list of all
available tests (including "none" that represents the normal functionality) in
which the current test level is indicated by square brackets.
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Acked-by: Pavel Machek <pavel@ucw.cz>
Signed-off-by: Len Brown <len.brown@intel.com>
2007-11-20 06:41:19 +08:00
|
|
|
int pm_test_level = TEST_NONE;
|
|
|
|
|
|
|
|
static const char * const pm_tests[__TEST_AFTER_LAST] = {
|
|
|
|
[TEST_NONE] = "none",
|
|
|
|
[TEST_CORE] = "core",
|
|
|
|
[TEST_CPUS] = "processors",
|
|
|
|
[TEST_PLATFORM] = "platform",
|
|
|
|
[TEST_DEVICES] = "devices",
|
|
|
|
[TEST_FREEZER] = "freezer",
|
|
|
|
};
|
|
|
|
|
2008-01-29 07:29:06 +08:00
|
|
|
static ssize_t pm_test_show(struct kobject *kobj, struct kobj_attribute *attr,
|
|
|
|
char *buf)
|
Suspend: Testing facility (rev. 2)
Introduce sysfs attribute /sys/power/pm_test allowing one to test the suspend
core code. Namely, writing one of the strings:
freezer
devices
platform
processors
core
to this file causes the suspend code to work in one of the test modes defined as
follows:
freezer
- test the freezing of processes
devices
- test the freezing of processes and suspending of devices
platform
- test the freezing of processes, suspending of devices and platform global
control methods(*)
processors
- test the freezing of processes, suspending of devices, platform global
control methods and the disabling of nonboot CPUs
core
- test the freezing of processes, suspending of devices, platform global
control methods, the disabling of nonboot CPUs and suspending of
platform/system devices
(*) These are ACPI global control methods on ACPI systems
Then, if a suspend is started by normal means, the suspend core will perform
its normal operations up to the point indicated by given test level. Next, it
will wait for 5 seconds and carry out the resume operations needed to transition
the system back to the fully functional state.
Writing "none" to /sys/power/pm_test turns the testing off.
When open for reading, /sys/power/pm_test contains a space-separated list of all
available tests (including "none" that represents the normal functionality) in
which the current test level is indicated by square brackets.
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Acked-by: Pavel Machek <pavel@ucw.cz>
Signed-off-by: Len Brown <len.brown@intel.com>
2007-11-20 06:41:19 +08:00
|
|
|
{
|
|
|
|
char *s = buf;
|
|
|
|
int level;
|
|
|
|
|
|
|
|
for (level = TEST_FIRST; level <= TEST_MAX; level++)
|
|
|
|
if (pm_tests[level]) {
|
|
|
|
if (level == pm_test_level)
|
|
|
|
s += sprintf(s, "[%s] ", pm_tests[level]);
|
|
|
|
else
|
|
|
|
s += sprintf(s, "%s ", pm_tests[level]);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (s != buf)
|
|
|
|
/* convert the last space to a newline */
|
|
|
|
*(s-1) = '\n';
|
|
|
|
|
|
|
|
return (s - buf);
|
|
|
|
}
|
|
|
|
|
2008-01-29 07:29:06 +08:00
|
|
|
static ssize_t pm_test_store(struct kobject *kobj, struct kobj_attribute *attr,
|
|
|
|
const char *buf, size_t n)
|
Suspend: Testing facility (rev. 2)
Introduce sysfs attribute /sys/power/pm_test allowing one to test the suspend
core code. Namely, writing one of the strings:
freezer
devices
platform
processors
core
to this file causes the suspend code to work in one of the test modes defined as
follows:
freezer
- test the freezing of processes
devices
- test the freezing of processes and suspending of devices
platform
- test the freezing of processes, suspending of devices and platform global
control methods(*)
processors
- test the freezing of processes, suspending of devices, platform global
control methods and the disabling of nonboot CPUs
core
- test the freezing of processes, suspending of devices, platform global
control methods, the disabling of nonboot CPUs and suspending of
platform/system devices
(*) These are ACPI global control methods on ACPI systems
Then, if a suspend is started by normal means, the suspend core will perform
its normal operations up to the point indicated by given test level. Next, it
will wait for 5 seconds and carry out the resume operations needed to transition
the system back to the fully functional state.
Writing "none" to /sys/power/pm_test turns the testing off.
When open for reading, /sys/power/pm_test contains a space-separated list of all
available tests (including "none" that represents the normal functionality) in
which the current test level is indicated by square brackets.
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Acked-by: Pavel Machek <pavel@ucw.cz>
Signed-off-by: Len Brown <len.brown@intel.com>
2007-11-20 06:41:19 +08:00
|
|
|
{
|
|
|
|
const char * const *s;
|
|
|
|
int level;
|
|
|
|
char *p;
|
|
|
|
int len;
|
|
|
|
int error = -EINVAL;
|
|
|
|
|
|
|
|
p = memchr(buf, '\n', n);
|
|
|
|
len = p ? p - buf : n;
|
|
|
|
|
2011-12-08 05:29:54 +08:00
|
|
|
lock_system_sleep();
|
Suspend: Testing facility (rev. 2)
Introduce sysfs attribute /sys/power/pm_test allowing one to test the suspend
core code. Namely, writing one of the strings:
freezer
devices
platform
processors
core
to this file causes the suspend code to work in one of the test modes defined as
follows:
freezer
- test the freezing of processes
devices
- test the freezing of processes and suspending of devices
platform
- test the freezing of processes, suspending of devices and platform global
control methods(*)
processors
- test the freezing of processes, suspending of devices, platform global
control methods and the disabling of nonboot CPUs
core
- test the freezing of processes, suspending of devices, platform global
control methods, the disabling of nonboot CPUs and suspending of
platform/system devices
(*) These are ACPI global control methods on ACPI systems
Then, if a suspend is started by normal means, the suspend core will perform
its normal operations up to the point indicated by given test level. Next, it
will wait for 5 seconds and carry out the resume operations needed to transition
the system back to the fully functional state.
Writing "none" to /sys/power/pm_test turns the testing off.
When open for reading, /sys/power/pm_test contains a space-separated list of all
available tests (including "none" that represents the normal functionality) in
which the current test level is indicated by square brackets.
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Acked-by: Pavel Machek <pavel@ucw.cz>
Signed-off-by: Len Brown <len.brown@intel.com>
2007-11-20 06:41:19 +08:00
|
|
|
|
|
|
|
level = TEST_FIRST;
|
|
|
|
for (s = &pm_tests[level]; level <= TEST_MAX; s++, level++)
|
|
|
|
if (*s && len == strlen(*s) && !strncmp(buf, *s, len)) {
|
|
|
|
pm_test_level = level;
|
|
|
|
error = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2011-12-08 05:29:54 +08:00
|
|
|
unlock_system_sleep();
|
Suspend: Testing facility (rev. 2)
Introduce sysfs attribute /sys/power/pm_test allowing one to test the suspend
core code. Namely, writing one of the strings:
freezer
devices
platform
processors
core
to this file causes the suspend code to work in one of the test modes defined as
follows:
freezer
- test the freezing of processes
devices
- test the freezing of processes and suspending of devices
platform
- test the freezing of processes, suspending of devices and platform global
control methods(*)
processors
- test the freezing of processes, suspending of devices, platform global
control methods and the disabling of nonboot CPUs
core
- test the freezing of processes, suspending of devices, platform global
control methods, the disabling of nonboot CPUs and suspending of
platform/system devices
(*) These are ACPI global control methods on ACPI systems
Then, if a suspend is started by normal means, the suspend core will perform
its normal operations up to the point indicated by given test level. Next, it
will wait for 5 seconds and carry out the resume operations needed to transition
the system back to the fully functional state.
Writing "none" to /sys/power/pm_test turns the testing off.
When open for reading, /sys/power/pm_test contains a space-separated list of all
available tests (including "none" that represents the normal functionality) in
which the current test level is indicated by square brackets.
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Acked-by: Pavel Machek <pavel@ucw.cz>
Signed-off-by: Len Brown <len.brown@intel.com>
2007-11-20 06:41:19 +08:00
|
|
|
|
|
|
|
return error ? error : n;
|
|
|
|
}
|
|
|
|
|
|
|
|
power_attr(pm_test);
|
2017-07-21 20:44:02 +08:00
|
|
|
#endif /* CONFIG_PM_SLEEP_DEBUG */
|
Suspend: Testing facility (rev. 2)
Introduce sysfs attribute /sys/power/pm_test allowing one to test the suspend
core code. Namely, writing one of the strings:
freezer
devices
platform
processors
core
to this file causes the suspend code to work in one of the test modes defined as
follows:
freezer
- test the freezing of processes
devices
- test the freezing of processes and suspending of devices
platform
- test the freezing of processes, suspending of devices and platform global
control methods(*)
processors
- test the freezing of processes, suspending of devices, platform global
control methods and the disabling of nonboot CPUs
core
- test the freezing of processes, suspending of devices, platform global
control methods, the disabling of nonboot CPUs and suspending of
platform/system devices
(*) These are ACPI global control methods on ACPI systems
Then, if a suspend is started by normal means, the suspend core will perform
its normal operations up to the point indicated by given test level. Next, it
will wait for 5 seconds and carry out the resume operations needed to transition
the system back to the fully functional state.
Writing "none" to /sys/power/pm_test turns the testing off.
When open for reading, /sys/power/pm_test contains a space-separated list of all
available tests (including "none" that represents the normal functionality) in
which the current test level is indicated by square brackets.
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Acked-by: Pavel Machek <pavel@ucw.cz>
Signed-off-by: Len Brown <len.brown@intel.com>
2007-11-20 06:41:19 +08:00
|
|
|
|
PM / Suspend: Add statistics debugfs file for suspend to RAM
Record S3 failure time about each reason and the latest two failed
devices' names in S3 progress.
We can check it through 'suspend_stats' entry in debugfs.
The motivation of the patch:
We are enabling power features on Medfield. Comparing with PC/notebook,
a mobile enters/exits suspend-2-ram (we call it s3 on Medfield) far
more frequently. If it can't enter suspend-2-ram in time, the power
might be used up soon.
We often find sometimes, a device suspend fails. Then, system retries
s3 over and over again. As display is off, testers and developers
don't know what happens.
Some testers and developers complain they don't know if system
tries suspend-2-ram, and what device fails to suspend. They need
such info for a quick check. The patch adds suspend_stats under
debugfs for users to check suspend to RAM statistics quickly.
If not using this patch, we have other methods to get info about
what device fails. One is to turn on CONFIG_PM_DEBUG, but users
would get too much info and testers need recompile the system.
In addition, dynamic debug is another good tool to dump debug info.
But it still doesn't match our utilization scenario closely.
1) user need write a user space parser to process the syslog output;
2) Our testing scenario is we leave the mobile for at least hours.
Then, check its status. No serial console available during the
testing. One is because console would be suspended, and the other
is serial console connecting with spi or HSU devices would consume
power. These devices are powered off at suspend-2-ram.
Signed-off-by: ShuoX Liu <shuox.liu@intel.com>
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
2011-08-11 05:01:26 +08:00
|
|
|
static char *suspend_step_name(enum suspend_stat_step step)
|
|
|
|
{
|
|
|
|
switch (step) {
|
|
|
|
case SUSPEND_FREEZE:
|
|
|
|
return "freeze";
|
|
|
|
case SUSPEND_PREPARE:
|
|
|
|
return "prepare";
|
|
|
|
case SUSPEND_SUSPEND:
|
|
|
|
return "suspend";
|
|
|
|
case SUSPEND_SUSPEND_NOIRQ:
|
|
|
|
return "suspend_noirq";
|
|
|
|
case SUSPEND_RESUME_NOIRQ:
|
|
|
|
return "resume_noirq";
|
|
|
|
case SUSPEND_RESUME:
|
|
|
|
return "resume";
|
|
|
|
default:
|
|
|
|
return "";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-08-01 05:29:33 +08:00
|
|
|
#define suspend_attr(_name) \
|
|
|
|
static ssize_t _name##_show(struct kobject *kobj, \
|
|
|
|
struct kobj_attribute *attr, char *buf) \
|
|
|
|
{ \
|
|
|
|
return sprintf(buf, "%d\n", suspend_stats._name); \
|
|
|
|
} \
|
|
|
|
static struct kobj_attribute _name = __ATTR_RO(_name)
|
|
|
|
|
|
|
|
suspend_attr(success);
|
|
|
|
suspend_attr(fail);
|
|
|
|
suspend_attr(failed_freeze);
|
|
|
|
suspend_attr(failed_prepare);
|
|
|
|
suspend_attr(failed_suspend);
|
|
|
|
suspend_attr(failed_suspend_late);
|
|
|
|
suspend_attr(failed_suspend_noirq);
|
|
|
|
suspend_attr(failed_resume);
|
|
|
|
suspend_attr(failed_resume_early);
|
|
|
|
suspend_attr(failed_resume_noirq);
|
|
|
|
|
|
|
|
static ssize_t last_failed_dev_show(struct kobject *kobj,
|
|
|
|
struct kobj_attribute *attr, char *buf)
|
|
|
|
{
|
|
|
|
int index;
|
|
|
|
char *last_failed_dev = NULL;
|
|
|
|
|
|
|
|
index = suspend_stats.last_failed_dev + REC_FAILED_NUM - 1;
|
|
|
|
index %= REC_FAILED_NUM;
|
|
|
|
last_failed_dev = suspend_stats.failed_devs[index];
|
|
|
|
|
|
|
|
return sprintf(buf, "%s\n", last_failed_dev);
|
|
|
|
}
|
|
|
|
static struct kobj_attribute last_failed_dev = __ATTR_RO(last_failed_dev);
|
|
|
|
|
|
|
|
static ssize_t last_failed_errno_show(struct kobject *kobj,
|
|
|
|
struct kobj_attribute *attr, char *buf)
|
|
|
|
{
|
|
|
|
int index;
|
|
|
|
int last_failed_errno;
|
|
|
|
|
|
|
|
index = suspend_stats.last_failed_errno + REC_FAILED_NUM - 1;
|
|
|
|
index %= REC_FAILED_NUM;
|
|
|
|
last_failed_errno = suspend_stats.errno[index];
|
|
|
|
|
|
|
|
return sprintf(buf, "%d\n", last_failed_errno);
|
|
|
|
}
|
|
|
|
static struct kobj_attribute last_failed_errno = __ATTR_RO(last_failed_errno);
|
|
|
|
|
|
|
|
static ssize_t last_failed_step_show(struct kobject *kobj,
|
|
|
|
struct kobj_attribute *attr, char *buf)
|
|
|
|
{
|
|
|
|
int index;
|
|
|
|
enum suspend_stat_step step;
|
|
|
|
char *last_failed_step = NULL;
|
|
|
|
|
|
|
|
index = suspend_stats.last_failed_step + REC_FAILED_NUM - 1;
|
|
|
|
index %= REC_FAILED_NUM;
|
|
|
|
step = suspend_stats.failed_steps[index];
|
|
|
|
last_failed_step = suspend_step_name(step);
|
|
|
|
|
|
|
|
return sprintf(buf, "%s\n", last_failed_step);
|
|
|
|
}
|
|
|
|
static struct kobj_attribute last_failed_step = __ATTR_RO(last_failed_step);
|
|
|
|
|
|
|
|
static struct attribute *suspend_attrs[] = {
|
|
|
|
&success.attr,
|
|
|
|
&fail.attr,
|
|
|
|
&failed_freeze.attr,
|
|
|
|
&failed_prepare.attr,
|
|
|
|
&failed_suspend.attr,
|
|
|
|
&failed_suspend_late.attr,
|
|
|
|
&failed_suspend_noirq.attr,
|
|
|
|
&failed_resume.attr,
|
|
|
|
&failed_resume_early.attr,
|
|
|
|
&failed_resume_noirq.attr,
|
|
|
|
&last_failed_dev.attr,
|
|
|
|
&last_failed_errno.attr,
|
|
|
|
&last_failed_step.attr,
|
|
|
|
NULL,
|
|
|
|
};
|
|
|
|
|
|
|
|
static struct attribute_group suspend_attr_group = {
|
|
|
|
.name = "suspend_stats",
|
|
|
|
.attrs = suspend_attrs,
|
|
|
|
};
|
|
|
|
|
|
|
|
#ifdef CONFIG_DEBUG_FS
|
PM / Suspend: Add statistics debugfs file for suspend to RAM
Record S3 failure time about each reason and the latest two failed
devices' names in S3 progress.
We can check it through 'suspend_stats' entry in debugfs.
The motivation of the patch:
We are enabling power features on Medfield. Comparing with PC/notebook,
a mobile enters/exits suspend-2-ram (we call it s3 on Medfield) far
more frequently. If it can't enter suspend-2-ram in time, the power
might be used up soon.
We often find sometimes, a device suspend fails. Then, system retries
s3 over and over again. As display is off, testers and developers
don't know what happens.
Some testers and developers complain they don't know if system
tries suspend-2-ram, and what device fails to suspend. They need
such info for a quick check. The patch adds suspend_stats under
debugfs for users to check suspend to RAM statistics quickly.
If not using this patch, we have other methods to get info about
what device fails. One is to turn on CONFIG_PM_DEBUG, but users
would get too much info and testers need recompile the system.
In addition, dynamic debug is another good tool to dump debug info.
But it still doesn't match our utilization scenario closely.
1) user need write a user space parser to process the syslog output;
2) Our testing scenario is we leave the mobile for at least hours.
Then, check its status. No serial console available during the
testing. One is because console would be suspended, and the other
is serial console connecting with spi or HSU devices would consume
power. These devices are powered off at suspend-2-ram.
Signed-off-by: ShuoX Liu <shuox.liu@intel.com>
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
2011-08-11 05:01:26 +08:00
|
|
|
static int suspend_stats_show(struct seq_file *s, void *unused)
|
|
|
|
{
|
|
|
|
int i, index, last_dev, last_errno, last_step;
|
|
|
|
|
|
|
|
last_dev = suspend_stats.last_failed_dev + REC_FAILED_NUM - 1;
|
|
|
|
last_dev %= REC_FAILED_NUM;
|
|
|
|
last_errno = suspend_stats.last_failed_errno + REC_FAILED_NUM - 1;
|
|
|
|
last_errno %= REC_FAILED_NUM;
|
|
|
|
last_step = suspend_stats.last_failed_step + REC_FAILED_NUM - 1;
|
|
|
|
last_step %= REC_FAILED_NUM;
|
2012-01-30 03:38:29 +08:00
|
|
|
seq_printf(s, "%s: %d\n%s: %d\n%s: %d\n%s: %d\n%s: %d\n"
|
|
|
|
"%s: %d\n%s: %d\n%s: %d\n%s: %d\n%s: %d\n",
|
PM / Suspend: Add statistics debugfs file for suspend to RAM
Record S3 failure time about each reason and the latest two failed
devices' names in S3 progress.
We can check it through 'suspend_stats' entry in debugfs.
The motivation of the patch:
We are enabling power features on Medfield. Comparing with PC/notebook,
a mobile enters/exits suspend-2-ram (we call it s3 on Medfield) far
more frequently. If it can't enter suspend-2-ram in time, the power
might be used up soon.
We often find sometimes, a device suspend fails. Then, system retries
s3 over and over again. As display is off, testers and developers
don't know what happens.
Some testers and developers complain they don't know if system
tries suspend-2-ram, and what device fails to suspend. They need
such info for a quick check. The patch adds suspend_stats under
debugfs for users to check suspend to RAM statistics quickly.
If not using this patch, we have other methods to get info about
what device fails. One is to turn on CONFIG_PM_DEBUG, but users
would get too much info and testers need recompile the system.
In addition, dynamic debug is another good tool to dump debug info.
But it still doesn't match our utilization scenario closely.
1) user need write a user space parser to process the syslog output;
2) Our testing scenario is we leave the mobile for at least hours.
Then, check its status. No serial console available during the
testing. One is because console would be suspended, and the other
is serial console connecting with spi or HSU devices would consume
power. These devices are powered off at suspend-2-ram.
Signed-off-by: ShuoX Liu <shuox.liu@intel.com>
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
2011-08-11 05:01:26 +08:00
|
|
|
"success", suspend_stats.success,
|
|
|
|
"fail", suspend_stats.fail,
|
|
|
|
"failed_freeze", suspend_stats.failed_freeze,
|
|
|
|
"failed_prepare", suspend_stats.failed_prepare,
|
|
|
|
"failed_suspend", suspend_stats.failed_suspend,
|
2012-01-30 03:38:29 +08:00
|
|
|
"failed_suspend_late",
|
|
|
|
suspend_stats.failed_suspend_late,
|
PM / Suspend: Add statistics debugfs file for suspend to RAM
Record S3 failure time about each reason and the latest two failed
devices' names in S3 progress.
We can check it through 'suspend_stats' entry in debugfs.
The motivation of the patch:
We are enabling power features on Medfield. Comparing with PC/notebook,
a mobile enters/exits suspend-2-ram (we call it s3 on Medfield) far
more frequently. If it can't enter suspend-2-ram in time, the power
might be used up soon.
We often find sometimes, a device suspend fails. Then, system retries
s3 over and over again. As display is off, testers and developers
don't know what happens.
Some testers and developers complain they don't know if system
tries suspend-2-ram, and what device fails to suspend. They need
such info for a quick check. The patch adds suspend_stats under
debugfs for users to check suspend to RAM statistics quickly.
If not using this patch, we have other methods to get info about
what device fails. One is to turn on CONFIG_PM_DEBUG, but users
would get too much info and testers need recompile the system.
In addition, dynamic debug is another good tool to dump debug info.
But it still doesn't match our utilization scenario closely.
1) user need write a user space parser to process the syslog output;
2) Our testing scenario is we leave the mobile for at least hours.
Then, check its status. No serial console available during the
testing. One is because console would be suspended, and the other
is serial console connecting with spi or HSU devices would consume
power. These devices are powered off at suspend-2-ram.
Signed-off-by: ShuoX Liu <shuox.liu@intel.com>
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
2011-08-11 05:01:26 +08:00
|
|
|
"failed_suspend_noirq",
|
|
|
|
suspend_stats.failed_suspend_noirq,
|
|
|
|
"failed_resume", suspend_stats.failed_resume,
|
2012-01-30 03:38:29 +08:00
|
|
|
"failed_resume_early",
|
|
|
|
suspend_stats.failed_resume_early,
|
PM / Suspend: Add statistics debugfs file for suspend to RAM
Record S3 failure time about each reason and the latest two failed
devices' names in S3 progress.
We can check it through 'suspend_stats' entry in debugfs.
The motivation of the patch:
We are enabling power features on Medfield. Comparing with PC/notebook,
a mobile enters/exits suspend-2-ram (we call it s3 on Medfield) far
more frequently. If it can't enter suspend-2-ram in time, the power
might be used up soon.
We often find sometimes, a device suspend fails. Then, system retries
s3 over and over again. As display is off, testers and developers
don't know what happens.
Some testers and developers complain they don't know if system
tries suspend-2-ram, and what device fails to suspend. They need
such info for a quick check. The patch adds suspend_stats under
debugfs for users to check suspend to RAM statistics quickly.
If not using this patch, we have other methods to get info about
what device fails. One is to turn on CONFIG_PM_DEBUG, but users
would get too much info and testers need recompile the system.
In addition, dynamic debug is another good tool to dump debug info.
But it still doesn't match our utilization scenario closely.
1) user need write a user space parser to process the syslog output;
2) Our testing scenario is we leave the mobile for at least hours.
Then, check its status. No serial console available during the
testing. One is because console would be suspended, and the other
is serial console connecting with spi or HSU devices would consume
power. These devices are powered off at suspend-2-ram.
Signed-off-by: ShuoX Liu <shuox.liu@intel.com>
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
2011-08-11 05:01:26 +08:00
|
|
|
"failed_resume_noirq",
|
|
|
|
suspend_stats.failed_resume_noirq);
|
|
|
|
seq_printf(s, "failures:\n last_failed_dev:\t%-s\n",
|
|
|
|
suspend_stats.failed_devs[last_dev]);
|
|
|
|
for (i = 1; i < REC_FAILED_NUM; i++) {
|
|
|
|
index = last_dev + REC_FAILED_NUM - i;
|
|
|
|
index %= REC_FAILED_NUM;
|
|
|
|
seq_printf(s, "\t\t\t%-s\n",
|
|
|
|
suspend_stats.failed_devs[index]);
|
|
|
|
}
|
|
|
|
seq_printf(s, " last_failed_errno:\t%-d\n",
|
|
|
|
suspend_stats.errno[last_errno]);
|
|
|
|
for (i = 1; i < REC_FAILED_NUM; i++) {
|
|
|
|
index = last_errno + REC_FAILED_NUM - i;
|
|
|
|
index %= REC_FAILED_NUM;
|
|
|
|
seq_printf(s, "\t\t\t%-d\n",
|
|
|
|
suspend_stats.errno[index]);
|
|
|
|
}
|
|
|
|
seq_printf(s, " last_failed_step:\t%-s\n",
|
|
|
|
suspend_step_name(
|
|
|
|
suspend_stats.failed_steps[last_step]));
|
|
|
|
for (i = 1; i < REC_FAILED_NUM; i++) {
|
|
|
|
index = last_step + REC_FAILED_NUM - i;
|
|
|
|
index %= REC_FAILED_NUM;
|
|
|
|
seq_printf(s, "\t\t\t%-s\n",
|
|
|
|
suspend_step_name(
|
|
|
|
suspend_stats.failed_steps[index]));
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
2018-12-12 00:20:48 +08:00
|
|
|
DEFINE_SHOW_ATTRIBUTE(suspend_stats);
|
PM / Suspend: Add statistics debugfs file for suspend to RAM
Record S3 failure time about each reason and the latest two failed
devices' names in S3 progress.
We can check it through 'suspend_stats' entry in debugfs.
The motivation of the patch:
We are enabling power features on Medfield. Comparing with PC/notebook,
a mobile enters/exits suspend-2-ram (we call it s3 on Medfield) far
more frequently. If it can't enter suspend-2-ram in time, the power
might be used up soon.
We often find sometimes, a device suspend fails. Then, system retries
s3 over and over again. As display is off, testers and developers
don't know what happens.
Some testers and developers complain they don't know if system
tries suspend-2-ram, and what device fails to suspend. They need
such info for a quick check. The patch adds suspend_stats under
debugfs for users to check suspend to RAM statistics quickly.
If not using this patch, we have other methods to get info about
what device fails. One is to turn on CONFIG_PM_DEBUG, but users
would get too much info and testers need recompile the system.
In addition, dynamic debug is another good tool to dump debug info.
But it still doesn't match our utilization scenario closely.
1) user need write a user space parser to process the syslog output;
2) Our testing scenario is we leave the mobile for at least hours.
Then, check its status. No serial console available during the
testing. One is because console would be suspended, and the other
is serial console connecting with spi or HSU devices would consume
power. These devices are powered off at suspend-2-ram.
Signed-off-by: ShuoX Liu <shuox.liu@intel.com>
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
2011-08-11 05:01:26 +08:00
|
|
|
|
|
|
|
static int __init pm_debugfs_init(void)
|
|
|
|
{
|
|
|
|
debugfs_create_file("suspend_stats", S_IFREG | S_IRUGO,
|
2018-12-12 00:20:48 +08:00
|
|
|
NULL, NULL, &suspend_stats_fops);
|
PM / Suspend: Add statistics debugfs file for suspend to RAM
Record S3 failure time about each reason and the latest two failed
devices' names in S3 progress.
We can check it through 'suspend_stats' entry in debugfs.
The motivation of the patch:
We are enabling power features on Medfield. Comparing with PC/notebook,
a mobile enters/exits suspend-2-ram (we call it s3 on Medfield) far
more frequently. If it can't enter suspend-2-ram in time, the power
might be used up soon.
We often find sometimes, a device suspend fails. Then, system retries
s3 over and over again. As display is off, testers and developers
don't know what happens.
Some testers and developers complain they don't know if system
tries suspend-2-ram, and what device fails to suspend. They need
such info for a quick check. The patch adds suspend_stats under
debugfs for users to check suspend to RAM statistics quickly.
If not using this patch, we have other methods to get info about
what device fails. One is to turn on CONFIG_PM_DEBUG, but users
would get too much info and testers need recompile the system.
In addition, dynamic debug is another good tool to dump debug info.
But it still doesn't match our utilization scenario closely.
1) user need write a user space parser to process the syslog output;
2) Our testing scenario is we leave the mobile for at least hours.
Then, check its status. No serial console available during the
testing. One is because console would be suspended, and the other
is serial console connecting with spi or HSU devices would consume
power. These devices are powered off at suspend-2-ram.
Signed-off-by: ShuoX Liu <shuox.liu@intel.com>
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
2011-08-11 05:01:26 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
late_initcall(pm_debugfs_init);
|
|
|
|
#endif /* CONFIG_DEBUG_FS */
|
|
|
|
|
2011-08-12 04:38:12 +08:00
|
|
|
#endif /* CONFIG_PM_SLEEP */
|
|
|
|
|
2012-06-21 06:19:33 +08:00
|
|
|
#ifdef CONFIG_PM_SLEEP_DEBUG
|
|
|
|
/*
|
|
|
|
* pm_print_times: print time taken by devices to suspend and resume.
|
|
|
|
*
|
|
|
|
* show() returns whether printing of suspend and resume times is enabled.
|
|
|
|
* store() accepts 0 or 1. 0 disables printing and 1 enables it.
|
|
|
|
*/
|
|
|
|
bool pm_print_times_enabled;
|
|
|
|
|
|
|
|
static ssize_t pm_print_times_show(struct kobject *kobj,
|
|
|
|
struct kobj_attribute *attr, char *buf)
|
|
|
|
{
|
|
|
|
return sprintf(buf, "%d\n", pm_print_times_enabled);
|
|
|
|
}
|
|
|
|
|
|
|
|
static ssize_t pm_print_times_store(struct kobject *kobj,
|
|
|
|
struct kobj_attribute *attr,
|
|
|
|
const char *buf, size_t n)
|
|
|
|
{
|
|
|
|
unsigned long val;
|
|
|
|
|
|
|
|
if (kstrtoul(buf, 10, &val))
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
if (val > 1)
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
pm_print_times_enabled = !!val;
|
|
|
|
return n;
|
|
|
|
}
|
|
|
|
|
|
|
|
power_attr(pm_print_times);
|
|
|
|
|
|
|
|
static inline void pm_print_times_init(void)
|
|
|
|
{
|
|
|
|
pm_print_times_enabled = !!initcall_debug;
|
|
|
|
}
|
2015-09-16 01:32:46 +08:00
|
|
|
|
|
|
|
static ssize_t pm_wakeup_irq_show(struct kobject *kobj,
|
|
|
|
struct kobj_attribute *attr,
|
|
|
|
char *buf)
|
|
|
|
{
|
|
|
|
return pm_wakeup_irq ? sprintf(buf, "%u\n", pm_wakeup_irq) : -ENODATA;
|
|
|
|
}
|
|
|
|
|
2016-01-02 10:09:16 +08:00
|
|
|
power_attr_ro(pm_wakeup_irq);
|
2015-09-16 01:32:46 +08:00
|
|
|
|
2017-08-16 09:16:59 +08:00
|
|
|
bool pm_debug_messages_on __read_mostly;
|
2017-07-19 08:38:44 +08:00
|
|
|
|
|
|
|
static ssize_t pm_debug_messages_show(struct kobject *kobj,
|
|
|
|
struct kobj_attribute *attr, char *buf)
|
|
|
|
{
|
|
|
|
return sprintf(buf, "%d\n", pm_debug_messages_on);
|
|
|
|
}
|
|
|
|
|
|
|
|
static ssize_t pm_debug_messages_store(struct kobject *kobj,
|
|
|
|
struct kobj_attribute *attr,
|
|
|
|
const char *buf, size_t n)
|
|
|
|
{
|
|
|
|
unsigned long val;
|
|
|
|
|
|
|
|
if (kstrtoul(buf, 10, &val))
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
if (val > 1)
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
pm_debug_messages_on = !!val;
|
|
|
|
return n;
|
|
|
|
}
|
|
|
|
|
|
|
|
power_attr(pm_debug_messages);
|
|
|
|
|
|
|
|
/**
|
2017-07-23 06:03:43 +08:00
|
|
|
* __pm_pr_dbg - Print a suspend debug message to the kernel log.
|
|
|
|
* @defer: Whether or not to use printk_deferred() to print the message.
|
2017-07-19 08:38:44 +08:00
|
|
|
* @fmt: Message format.
|
|
|
|
*
|
|
|
|
* The message will be emitted if enabled through the pm_debug_messages
|
|
|
|
* sysfs attribute.
|
|
|
|
*/
|
2017-07-23 06:03:43 +08:00
|
|
|
void __pm_pr_dbg(bool defer, const char *fmt, ...)
|
2017-07-19 08:38:44 +08:00
|
|
|
{
|
|
|
|
struct va_format vaf;
|
|
|
|
va_list args;
|
|
|
|
|
|
|
|
if (!pm_debug_messages_on)
|
|
|
|
return;
|
|
|
|
|
|
|
|
va_start(args, fmt);
|
|
|
|
|
|
|
|
vaf.fmt = fmt;
|
|
|
|
vaf.va = &args;
|
|
|
|
|
2017-07-23 06:03:43 +08:00
|
|
|
if (defer)
|
|
|
|
printk_deferred(KERN_DEBUG "PM: %pV", &vaf);
|
|
|
|
else
|
|
|
|
printk(KERN_DEBUG "PM: %pV", &vaf);
|
2017-07-19 08:38:44 +08:00
|
|
|
|
|
|
|
va_end(args);
|
|
|
|
}
|
|
|
|
|
2015-05-13 21:31:12 +08:00
|
|
|
#else /* !CONFIG_PM_SLEEP_DEBUG */
|
2012-06-21 06:19:33 +08:00
|
|
|
static inline void pm_print_times_init(void) {}
|
|
|
|
#endif /* CONFIG_PM_SLEEP_DEBUG */
|
|
|
|
|
2007-11-28 03:28:26 +08:00
|
|
|
struct kobject *power_kobj;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
/**
|
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: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
2014-05-26 19:40:59 +08:00
|
|
|
* state - control system sleep states.
|
2005-04-17 06:20:36 +08:00
|
|
|
*
|
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: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
2014-05-26 19:40:59 +08:00
|
|
|
* show() returns available sleep state labels, which may be "mem", "standby",
|
2018-06-14 23:34:32 +08:00
|
|
|
* "freeze" and "disk" (hibernation).
|
|
|
|
* See Documentation/admin-guide/pm/sleep-states.rst for a description of
|
|
|
|
* what they mean.
|
2005-04-17 06:20:36 +08:00
|
|
|
*
|
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: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
2014-05-26 19:40:59 +08:00
|
|
|
* store() accepts one of those strings, translates it into the proper
|
|
|
|
* enumerated value, and initiates a suspend transition.
|
2005-04-17 06:20:36 +08:00
|
|
|
*/
|
2007-11-02 20:47:53 +08:00
|
|
|
static ssize_t state_show(struct kobject *kobj, struct kobj_attribute *attr,
|
|
|
|
char *buf)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
2007-07-30 05:27:18 +08:00
|
|
|
char *s = buf;
|
|
|
|
#ifdef CONFIG_SUSPEND
|
2014-05-26 19:40:47 +08:00
|
|
|
suspend_state_t i;
|
|
|
|
|
|
|
|
for (i = PM_SUSPEND_MIN; i < PM_SUSPEND_MAX; i++)
|
2014-07-16 04:02:11 +08:00
|
|
|
if (pm_states[i])
|
|
|
|
s += sprintf(s,"%s ", pm_states[i]);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2007-07-30 05:27:18 +08:00
|
|
|
#endif
|
2014-06-14 04:30:35 +08:00
|
|
|
if (hibernation_available())
|
|
|
|
s += sprintf(s, "disk ");
|
2007-05-09 17:33:18 +08:00
|
|
|
if (s != buf)
|
|
|
|
/* convert the last space to a newline */
|
|
|
|
*(s-1) = '\n';
|
2005-04-17 06:20:36 +08:00
|
|
|
return (s - buf);
|
|
|
|
}
|
|
|
|
|
2012-04-30 04:53:22 +08:00
|
|
|
static suspend_state_t decode_state(const char *buf, size_t n)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
2007-07-30 05:27:18 +08:00
|
|
|
#ifdef CONFIG_SUSPEND
|
2014-07-16 04:02:11 +08:00
|
|
|
suspend_state_t state;
|
2007-07-30 05:27:18 +08:00
|
|
|
#endif
|
2005-04-17 06:20:36 +08:00
|
|
|
char *p;
|
|
|
|
int len;
|
|
|
|
|
|
|
|
p = memchr(buf, '\n', n);
|
|
|
|
len = p ? p - buf : n;
|
|
|
|
|
2012-04-30 04:53:22 +08:00
|
|
|
/* Check hibernation first. */
|
2019-08-09 15:10:23 +08:00
|
|
|
if (len == 4 && str_has_prefix(buf, "disk"))
|
2012-04-30 04:53:22 +08:00
|
|
|
return PM_SUSPEND_MAX;
|
2007-05-09 17:33:18 +08:00
|
|
|
|
2007-07-30 05:27:18 +08:00
|
|
|
#ifdef CONFIG_SUSPEND
|
2014-07-16 04:02:11 +08:00
|
|
|
for (state = PM_SUSPEND_MIN; state < PM_SUSPEND_MAX; state++) {
|
|
|
|
const char *label = pm_states[state];
|
|
|
|
|
|
|
|
if (label && len == strlen(label) && !strncmp(buf, label, len))
|
|
|
|
return state;
|
|
|
|
}
|
2007-07-30 05:27:18 +08:00
|
|
|
#endif
|
|
|
|
|
2012-04-30 04:53:22 +08:00
|
|
|
return PM_SUSPEND_ON;
|
|
|
|
}
|
|
|
|
|
|
|
|
static ssize_t state_store(struct kobject *kobj, struct kobj_attribute *attr,
|
|
|
|
const char *buf, size_t n)
|
|
|
|
{
|
|
|
|
suspend_state_t state;
|
|
|
|
int error;
|
|
|
|
|
|
|
|
error = pm_autosleep_lock();
|
|
|
|
if (error)
|
|
|
|
return error;
|
|
|
|
|
|
|
|
if (pm_autosleep_state() > PM_SUSPEND_ON) {
|
|
|
|
error = -EBUSY;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
state = decode_state(buf, n);
|
PM / sleep: System sleep state selection interface rework
There are systems in which the platform doesn't support any special
sleep states, so suspend-to-idle (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 may be a pain in practice.
Commit 0399d4db3edf (PM / sleep: Introduce command line argument for
sleep state enumeration) attempted to address this problem by adding
a command line argument to change the meaning of the "mem" string in
/sys/power/state to make it trigger suspend-to-idle (instead of
suspend-to-RAM).
However, there also are systems in which the platform does support
special sleep states, but suspend-to-idle is the preferred one anyway
(it even may save more energy than the platform-provided sleep states
in some cases) and the above commit doesn't help in those cases.
For this reason, rework the system sleep state selection interface
again (but preserve backwards compatibiliby). Namely, add a new
sysfs file, /sys/power/mem_sleep, that will control the system
suspend mode triggered by writing "mem" to /sys/power/state (in
analogy with what /sys/power/disk does for hibernation). Make it
select suspend-to-RAM ("deep" sleep) by default (if supported) and
fall back to suspend-to-idle ("s2idle") otherwise and add a new
command line argument, mem_sleep_default, allowing that default to
be overridden if need be.
At the same time, drop the relative_sleep_states command line
argument that doesn't make sense any more.
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Tested-by: Mario Limonciello <mario.limonciello@dell.com>
2016-11-22 05:45:40 +08:00
|
|
|
if (state < PM_SUSPEND_MAX) {
|
|
|
|
if (state == PM_SUSPEND_MEM)
|
|
|
|
state = mem_sleep_current;
|
|
|
|
|
2012-04-30 04:53:22 +08:00
|
|
|
error = pm_suspend(state);
|
PM / sleep: System sleep state selection interface rework
There are systems in which the platform doesn't support any special
sleep states, so suspend-to-idle (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 may be a pain in practice.
Commit 0399d4db3edf (PM / sleep: Introduce command line argument for
sleep state enumeration) attempted to address this problem by adding
a command line argument to change the meaning of the "mem" string in
/sys/power/state to make it trigger suspend-to-idle (instead of
suspend-to-RAM).
However, there also are systems in which the platform does support
special sleep states, but suspend-to-idle is the preferred one anyway
(it even may save more energy than the platform-provided sleep states
in some cases) and the above commit doesn't help in those cases.
For this reason, rework the system sleep state selection interface
again (but preserve backwards compatibiliby). Namely, add a new
sysfs file, /sys/power/mem_sleep, that will control the system
suspend mode triggered by writing "mem" to /sys/power/state (in
analogy with what /sys/power/disk does for hibernation). Make it
select suspend-to-RAM ("deep" sleep) by default (if supported) and
fall back to suspend-to-idle ("s2idle") otherwise and add a new
command line argument, mem_sleep_default, allowing that default to
be overridden if need be.
At the same time, drop the relative_sleep_states command line
argument that doesn't make sense any more.
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Tested-by: Mario Limonciello <mario.limonciello@dell.com>
2016-11-22 05:45:40 +08:00
|
|
|
} else if (state == PM_SUSPEND_MAX) {
|
2012-04-30 04:53:22 +08:00
|
|
|
error = hibernate();
|
PM / sleep: System sleep state selection interface rework
There are systems in which the platform doesn't support any special
sleep states, so suspend-to-idle (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 may be a pain in practice.
Commit 0399d4db3edf (PM / sleep: Introduce command line argument for
sleep state enumeration) attempted to address this problem by adding
a command line argument to change the meaning of the "mem" string in
/sys/power/state to make it trigger suspend-to-idle (instead of
suspend-to-RAM).
However, there also are systems in which the platform does support
special sleep states, but suspend-to-idle is the preferred one anyway
(it even may save more energy than the platform-provided sleep states
in some cases) and the above commit doesn't help in those cases.
For this reason, rework the system sleep state selection interface
again (but preserve backwards compatibiliby). Namely, add a new
sysfs file, /sys/power/mem_sleep, that will control the system
suspend mode triggered by writing "mem" to /sys/power/state (in
analogy with what /sys/power/disk does for hibernation). Make it
select suspend-to-RAM ("deep" sleep) by default (if supported) and
fall back to suspend-to-idle ("s2idle") otherwise and add a new
command line argument, mem_sleep_default, allowing that default to
be overridden if need be.
At the same time, drop the relative_sleep_states command line
argument that doesn't make sense any more.
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Tested-by: Mario Limonciello <mario.limonciello@dell.com>
2016-11-22 05:45:40 +08:00
|
|
|
} else {
|
2012-04-30 04:53:22 +08:00
|
|
|
error = -EINVAL;
|
PM / sleep: System sleep state selection interface rework
There are systems in which the platform doesn't support any special
sleep states, so suspend-to-idle (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 may be a pain in practice.
Commit 0399d4db3edf (PM / sleep: Introduce command line argument for
sleep state enumeration) attempted to address this problem by adding
a command line argument to change the meaning of the "mem" string in
/sys/power/state to make it trigger suspend-to-idle (instead of
suspend-to-RAM).
However, there also are systems in which the platform does support
special sleep states, but suspend-to-idle is the preferred one anyway
(it even may save more energy than the platform-provided sleep states
in some cases) and the above commit doesn't help in those cases.
For this reason, rework the system sleep state selection interface
again (but preserve backwards compatibiliby). Namely, add a new
sysfs file, /sys/power/mem_sleep, that will control the system
suspend mode triggered by writing "mem" to /sys/power/state (in
analogy with what /sys/power/disk does for hibernation). Make it
select suspend-to-RAM ("deep" sleep) by default (if supported) and
fall back to suspend-to-idle ("s2idle") otherwise and add a new
command line argument, mem_sleep_default, allowing that default to
be overridden if need be.
At the same time, drop the relative_sleep_states command line
argument that doesn't make sense any more.
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Tested-by: Mario Limonciello <mario.limonciello@dell.com>
2016-11-22 05:45:40 +08:00
|
|
|
}
|
2012-04-30 04:53:22 +08:00
|
|
|
|
|
|
|
out:
|
|
|
|
pm_autosleep_unlock();
|
2005-04-17 06:20:36 +08:00
|
|
|
return error ? error : n;
|
|
|
|
}
|
|
|
|
|
|
|
|
power_attr(state);
|
|
|
|
|
PM: Make it possible to avoid races between wakeup and system sleep
One of the arguments during the suspend blockers discussion was that
the mainline kernel didn't contain any mechanisms making it possible
to avoid races between wakeup and system suspend.
Generally, there are two problems in that area. First, if a wakeup
event occurs exactly when /sys/power/state is being written to, it
may be delivered to user space right before the freezer kicks in, so
the user space consumer of the event may not be able to process it
before the system is suspended. Second, if a wakeup event occurs
after user space has been frozen, it is not generally guaranteed that
the ongoing transition of the system into a sleep state will be
aborted.
To address these issues introduce a new global sysfs attribute,
/sys/power/wakeup_count, associated with a running counter of wakeup
events and three helper functions, pm_stay_awake(), pm_relax(), and
pm_wakeup_event(), that may be used by kernel subsystems to control
the behavior of this attribute and to request the PM core to abort
system transitions into a sleep state already in progress.
The /sys/power/wakeup_count file may be read from or written to by
user space. Reads will always succeed (unless interrupted by a
signal) and return the current value of the wakeup events counter.
Writes, however, will only succeed if the written number is equal to
the current value of the wakeup events counter. If a write is
successful, it will cause the kernel to save the current value of the
wakeup events counter and to abort the subsequent system transition
into a sleep state if any wakeup events are reported after the write
has returned.
[The assumption is that before writing to /sys/power/state user space
will first read from /sys/power/wakeup_count. Next, user space
consumers of wakeup events will have a chance to acknowledge or
veto the upcoming system transition to a sleep state. Finally, if
the transition is allowed to proceed, /sys/power/wakeup_count will
be written to and if that succeeds, /sys/power/state will be written
to as well. Still, if any wakeup events are reported to the PM core
by kernel subsystems after that point, the transition will be
aborted.]
Additionally, put a wakeup events counter into struct dev_pm_info and
make these per-device wakeup event counters available via sysfs,
so that it's possible to check the activity of various wakeup event
sources within the kernel.
To illustrate how subsystems can use pm_wakeup_event(), make the
low-level PCI runtime PM wakeup-handling code use it.
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Acked-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Acked-by: Greg Kroah-Hartman <gregkh@suse.de>
Acked-by: markgross <markgross@thegnar.org>
Reviewed-by: Alan Stern <stern@rowland.harvard.edu>
2010-07-06 04:43:53 +08:00
|
|
|
#ifdef CONFIG_PM_SLEEP
|
|
|
|
/*
|
|
|
|
* The 'wakeup_count' attribute, along with the functions defined in
|
|
|
|
* drivers/base/power/wakeup.c, provides a means by which wakeup events can be
|
|
|
|
* handled in a non-racy way.
|
|
|
|
*
|
|
|
|
* If a wakeup event occurs when the system is in a sleep state, it simply is
|
|
|
|
* woken up. In turn, if an event that would wake the system up from a sleep
|
|
|
|
* state occurs when it is undergoing a transition to that sleep state, the
|
|
|
|
* transition should be aborted. Moreover, if such an event occurs when the
|
|
|
|
* system is in the working state, an attempt to start a transition to the
|
|
|
|
* given sleep state should fail during certain period after the detection of
|
|
|
|
* the event. Using the 'state' attribute alone is not sufficient to satisfy
|
|
|
|
* these requirements, because a wakeup event may occur exactly when 'state'
|
|
|
|
* is being written to and may be delivered to user space right before it is
|
|
|
|
* frozen, so the event will remain only partially processed until the system is
|
|
|
|
* woken up by another event. In particular, it won't cause the transition to
|
|
|
|
* a sleep state to be aborted.
|
|
|
|
*
|
|
|
|
* This difficulty may be overcome if user space uses 'wakeup_count' before
|
|
|
|
* writing to 'state'. It first should read from 'wakeup_count' and store
|
|
|
|
* the read value. Then, after carrying out its own preparations for the system
|
|
|
|
* transition to a sleep state, it should write the stored value to
|
2011-03-31 09:57:33 +08:00
|
|
|
* 'wakeup_count'. If that fails, at least one wakeup event has occurred since
|
PM: Make it possible to avoid races between wakeup and system sleep
One of the arguments during the suspend blockers discussion was that
the mainline kernel didn't contain any mechanisms making it possible
to avoid races between wakeup and system suspend.
Generally, there are two problems in that area. First, if a wakeup
event occurs exactly when /sys/power/state is being written to, it
may be delivered to user space right before the freezer kicks in, so
the user space consumer of the event may not be able to process it
before the system is suspended. Second, if a wakeup event occurs
after user space has been frozen, it is not generally guaranteed that
the ongoing transition of the system into a sleep state will be
aborted.
To address these issues introduce a new global sysfs attribute,
/sys/power/wakeup_count, associated with a running counter of wakeup
events and three helper functions, pm_stay_awake(), pm_relax(), and
pm_wakeup_event(), that may be used by kernel subsystems to control
the behavior of this attribute and to request the PM core to abort
system transitions into a sleep state already in progress.
The /sys/power/wakeup_count file may be read from or written to by
user space. Reads will always succeed (unless interrupted by a
signal) and return the current value of the wakeup events counter.
Writes, however, will only succeed if the written number is equal to
the current value of the wakeup events counter. If a write is
successful, it will cause the kernel to save the current value of the
wakeup events counter and to abort the subsequent system transition
into a sleep state if any wakeup events are reported after the write
has returned.
[The assumption is that before writing to /sys/power/state user space
will first read from /sys/power/wakeup_count. Next, user space
consumers of wakeup events will have a chance to acknowledge or
veto the upcoming system transition to a sleep state. Finally, if
the transition is allowed to proceed, /sys/power/wakeup_count will
be written to and if that succeeds, /sys/power/state will be written
to as well. Still, if any wakeup events are reported to the PM core
by kernel subsystems after that point, the transition will be
aborted.]
Additionally, put a wakeup events counter into struct dev_pm_info and
make these per-device wakeup event counters available via sysfs,
so that it's possible to check the activity of various wakeup event
sources within the kernel.
To illustrate how subsystems can use pm_wakeup_event(), make the
low-level PCI runtime PM wakeup-handling code use it.
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Acked-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Acked-by: Greg Kroah-Hartman <gregkh@suse.de>
Acked-by: markgross <markgross@thegnar.org>
Reviewed-by: Alan Stern <stern@rowland.harvard.edu>
2010-07-06 04:43:53 +08:00
|
|
|
* 'wakeup_count' was read and 'state' should not be written to. Otherwise, it
|
|
|
|
* is allowed to write to 'state', but the transition will be aborted if there
|
|
|
|
* are any wakeup events detected after 'wakeup_count' was written to.
|
|
|
|
*/
|
|
|
|
|
|
|
|
static ssize_t wakeup_count_show(struct kobject *kobj,
|
|
|
|
struct kobj_attribute *attr,
|
|
|
|
char *buf)
|
|
|
|
{
|
2010-09-23 04:09:10 +08:00
|
|
|
unsigned int val;
|
PM: Make it possible to avoid races between wakeup and system sleep
One of the arguments during the suspend blockers discussion was that
the mainline kernel didn't contain any mechanisms making it possible
to avoid races between wakeup and system suspend.
Generally, there are two problems in that area. First, if a wakeup
event occurs exactly when /sys/power/state is being written to, it
may be delivered to user space right before the freezer kicks in, so
the user space consumer of the event may not be able to process it
before the system is suspended. Second, if a wakeup event occurs
after user space has been frozen, it is not generally guaranteed that
the ongoing transition of the system into a sleep state will be
aborted.
To address these issues introduce a new global sysfs attribute,
/sys/power/wakeup_count, associated with a running counter of wakeup
events and three helper functions, pm_stay_awake(), pm_relax(), and
pm_wakeup_event(), that may be used by kernel subsystems to control
the behavior of this attribute and to request the PM core to abort
system transitions into a sleep state already in progress.
The /sys/power/wakeup_count file may be read from or written to by
user space. Reads will always succeed (unless interrupted by a
signal) and return the current value of the wakeup events counter.
Writes, however, will only succeed if the written number is equal to
the current value of the wakeup events counter. If a write is
successful, it will cause the kernel to save the current value of the
wakeup events counter and to abort the subsequent system transition
into a sleep state if any wakeup events are reported after the write
has returned.
[The assumption is that before writing to /sys/power/state user space
will first read from /sys/power/wakeup_count. Next, user space
consumers of wakeup events will have a chance to acknowledge or
veto the upcoming system transition to a sleep state. Finally, if
the transition is allowed to proceed, /sys/power/wakeup_count will
be written to and if that succeeds, /sys/power/state will be written
to as well. Still, if any wakeup events are reported to the PM core
by kernel subsystems after that point, the transition will be
aborted.]
Additionally, put a wakeup events counter into struct dev_pm_info and
make these per-device wakeup event counters available via sysfs,
so that it's possible to check the activity of various wakeup event
sources within the kernel.
To illustrate how subsystems can use pm_wakeup_event(), make the
low-level PCI runtime PM wakeup-handling code use it.
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Acked-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Acked-by: Greg Kroah-Hartman <gregkh@suse.de>
Acked-by: markgross <markgross@thegnar.org>
Reviewed-by: Alan Stern <stern@rowland.harvard.edu>
2010-07-06 04:43:53 +08:00
|
|
|
|
2012-04-30 04:53:22 +08:00
|
|
|
return pm_get_wakeup_count(&val, true) ?
|
|
|
|
sprintf(buf, "%u\n", val) : -EINTR;
|
PM: Make it possible to avoid races between wakeup and system sleep
One of the arguments during the suspend blockers discussion was that
the mainline kernel didn't contain any mechanisms making it possible
to avoid races between wakeup and system suspend.
Generally, there are two problems in that area. First, if a wakeup
event occurs exactly when /sys/power/state is being written to, it
may be delivered to user space right before the freezer kicks in, so
the user space consumer of the event may not be able to process it
before the system is suspended. Second, if a wakeup event occurs
after user space has been frozen, it is not generally guaranteed that
the ongoing transition of the system into a sleep state will be
aborted.
To address these issues introduce a new global sysfs attribute,
/sys/power/wakeup_count, associated with a running counter of wakeup
events and three helper functions, pm_stay_awake(), pm_relax(), and
pm_wakeup_event(), that may be used by kernel subsystems to control
the behavior of this attribute and to request the PM core to abort
system transitions into a sleep state already in progress.
The /sys/power/wakeup_count file may be read from or written to by
user space. Reads will always succeed (unless interrupted by a
signal) and return the current value of the wakeup events counter.
Writes, however, will only succeed if the written number is equal to
the current value of the wakeup events counter. If a write is
successful, it will cause the kernel to save the current value of the
wakeup events counter and to abort the subsequent system transition
into a sleep state if any wakeup events are reported after the write
has returned.
[The assumption is that before writing to /sys/power/state user space
will first read from /sys/power/wakeup_count. Next, user space
consumers of wakeup events will have a chance to acknowledge or
veto the upcoming system transition to a sleep state. Finally, if
the transition is allowed to proceed, /sys/power/wakeup_count will
be written to and if that succeeds, /sys/power/state will be written
to as well. Still, if any wakeup events are reported to the PM core
by kernel subsystems after that point, the transition will be
aborted.]
Additionally, put a wakeup events counter into struct dev_pm_info and
make these per-device wakeup event counters available via sysfs,
so that it's possible to check the activity of various wakeup event
sources within the kernel.
To illustrate how subsystems can use pm_wakeup_event(), make the
low-level PCI runtime PM wakeup-handling code use it.
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Acked-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Acked-by: Greg Kroah-Hartman <gregkh@suse.de>
Acked-by: markgross <markgross@thegnar.org>
Reviewed-by: Alan Stern <stern@rowland.harvard.edu>
2010-07-06 04:43:53 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static ssize_t wakeup_count_store(struct kobject *kobj,
|
|
|
|
struct kobj_attribute *attr,
|
|
|
|
const char *buf, size_t n)
|
|
|
|
{
|
2010-09-23 04:09:10 +08:00
|
|
|
unsigned int val;
|
2012-04-30 04:53:22 +08:00
|
|
|
int error;
|
|
|
|
|
|
|
|
error = pm_autosleep_lock();
|
|
|
|
if (error)
|
|
|
|
return error;
|
PM: Make it possible to avoid races between wakeup and system sleep
One of the arguments during the suspend blockers discussion was that
the mainline kernel didn't contain any mechanisms making it possible
to avoid races between wakeup and system suspend.
Generally, there are two problems in that area. First, if a wakeup
event occurs exactly when /sys/power/state is being written to, it
may be delivered to user space right before the freezer kicks in, so
the user space consumer of the event may not be able to process it
before the system is suspended. Second, if a wakeup event occurs
after user space has been frozen, it is not generally guaranteed that
the ongoing transition of the system into a sleep state will be
aborted.
To address these issues introduce a new global sysfs attribute,
/sys/power/wakeup_count, associated with a running counter of wakeup
events and three helper functions, pm_stay_awake(), pm_relax(), and
pm_wakeup_event(), that may be used by kernel subsystems to control
the behavior of this attribute and to request the PM core to abort
system transitions into a sleep state already in progress.
The /sys/power/wakeup_count file may be read from or written to by
user space. Reads will always succeed (unless interrupted by a
signal) and return the current value of the wakeup events counter.
Writes, however, will only succeed if the written number is equal to
the current value of the wakeup events counter. If a write is
successful, it will cause the kernel to save the current value of the
wakeup events counter and to abort the subsequent system transition
into a sleep state if any wakeup events are reported after the write
has returned.
[The assumption is that before writing to /sys/power/state user space
will first read from /sys/power/wakeup_count. Next, user space
consumers of wakeup events will have a chance to acknowledge or
veto the upcoming system transition to a sleep state. Finally, if
the transition is allowed to proceed, /sys/power/wakeup_count will
be written to and if that succeeds, /sys/power/state will be written
to as well. Still, if any wakeup events are reported to the PM core
by kernel subsystems after that point, the transition will be
aborted.]
Additionally, put a wakeup events counter into struct dev_pm_info and
make these per-device wakeup event counters available via sysfs,
so that it's possible to check the activity of various wakeup event
sources within the kernel.
To illustrate how subsystems can use pm_wakeup_event(), make the
low-level PCI runtime PM wakeup-handling code use it.
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Acked-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Acked-by: Greg Kroah-Hartman <gregkh@suse.de>
Acked-by: markgross <markgross@thegnar.org>
Reviewed-by: Alan Stern <stern@rowland.harvard.edu>
2010-07-06 04:43:53 +08:00
|
|
|
|
2012-04-30 04:53:22 +08:00
|
|
|
if (pm_autosleep_state() > PM_SUSPEND_ON) {
|
|
|
|
error = -EBUSY;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
error = -EINVAL;
|
2010-09-23 04:09:10 +08:00
|
|
|
if (sscanf(buf, "%u", &val) == 1) {
|
PM: Make it possible to avoid races between wakeup and system sleep
One of the arguments during the suspend blockers discussion was that
the mainline kernel didn't contain any mechanisms making it possible
to avoid races between wakeup and system suspend.
Generally, there are two problems in that area. First, if a wakeup
event occurs exactly when /sys/power/state is being written to, it
may be delivered to user space right before the freezer kicks in, so
the user space consumer of the event may not be able to process it
before the system is suspended. Second, if a wakeup event occurs
after user space has been frozen, it is not generally guaranteed that
the ongoing transition of the system into a sleep state will be
aborted.
To address these issues introduce a new global sysfs attribute,
/sys/power/wakeup_count, associated with a running counter of wakeup
events and three helper functions, pm_stay_awake(), pm_relax(), and
pm_wakeup_event(), that may be used by kernel subsystems to control
the behavior of this attribute and to request the PM core to abort
system transitions into a sleep state already in progress.
The /sys/power/wakeup_count file may be read from or written to by
user space. Reads will always succeed (unless interrupted by a
signal) and return the current value of the wakeup events counter.
Writes, however, will only succeed if the written number is equal to
the current value of the wakeup events counter. If a write is
successful, it will cause the kernel to save the current value of the
wakeup events counter and to abort the subsequent system transition
into a sleep state if any wakeup events are reported after the write
has returned.
[The assumption is that before writing to /sys/power/state user space
will first read from /sys/power/wakeup_count. Next, user space
consumers of wakeup events will have a chance to acknowledge or
veto the upcoming system transition to a sleep state. Finally, if
the transition is allowed to proceed, /sys/power/wakeup_count will
be written to and if that succeeds, /sys/power/state will be written
to as well. Still, if any wakeup events are reported to the PM core
by kernel subsystems after that point, the transition will be
aborted.]
Additionally, put a wakeup events counter into struct dev_pm_info and
make these per-device wakeup event counters available via sysfs,
so that it's possible to check the activity of various wakeup event
sources within the kernel.
To illustrate how subsystems can use pm_wakeup_event(), make the
low-level PCI runtime PM wakeup-handling code use it.
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Acked-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Acked-by: Greg Kroah-Hartman <gregkh@suse.de>
Acked-by: markgross <markgross@thegnar.org>
Reviewed-by: Alan Stern <stern@rowland.harvard.edu>
2010-07-06 04:43:53 +08:00
|
|
|
if (pm_save_wakeup_count(val))
|
2012-04-30 04:53:22 +08:00
|
|
|
error = n;
|
2013-06-13 03:55:22 +08:00
|
|
|
else
|
|
|
|
pm_print_active_wakeup_sources();
|
PM: Make it possible to avoid races between wakeup and system sleep
One of the arguments during the suspend blockers discussion was that
the mainline kernel didn't contain any mechanisms making it possible
to avoid races between wakeup and system suspend.
Generally, there are two problems in that area. First, if a wakeup
event occurs exactly when /sys/power/state is being written to, it
may be delivered to user space right before the freezer kicks in, so
the user space consumer of the event may not be able to process it
before the system is suspended. Second, if a wakeup event occurs
after user space has been frozen, it is not generally guaranteed that
the ongoing transition of the system into a sleep state will be
aborted.
To address these issues introduce a new global sysfs attribute,
/sys/power/wakeup_count, associated with a running counter of wakeup
events and three helper functions, pm_stay_awake(), pm_relax(), and
pm_wakeup_event(), that may be used by kernel subsystems to control
the behavior of this attribute and to request the PM core to abort
system transitions into a sleep state already in progress.
The /sys/power/wakeup_count file may be read from or written to by
user space. Reads will always succeed (unless interrupted by a
signal) and return the current value of the wakeup events counter.
Writes, however, will only succeed if the written number is equal to
the current value of the wakeup events counter. If a write is
successful, it will cause the kernel to save the current value of the
wakeup events counter and to abort the subsequent system transition
into a sleep state if any wakeup events are reported after the write
has returned.
[The assumption is that before writing to /sys/power/state user space
will first read from /sys/power/wakeup_count. Next, user space
consumers of wakeup events will have a chance to acknowledge or
veto the upcoming system transition to a sleep state. Finally, if
the transition is allowed to proceed, /sys/power/wakeup_count will
be written to and if that succeeds, /sys/power/state will be written
to as well. Still, if any wakeup events are reported to the PM core
by kernel subsystems after that point, the transition will be
aborted.]
Additionally, put a wakeup events counter into struct dev_pm_info and
make these per-device wakeup event counters available via sysfs,
so that it's possible to check the activity of various wakeup event
sources within the kernel.
To illustrate how subsystems can use pm_wakeup_event(), make the
low-level PCI runtime PM wakeup-handling code use it.
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Acked-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Acked-by: Greg Kroah-Hartman <gregkh@suse.de>
Acked-by: markgross <markgross@thegnar.org>
Reviewed-by: Alan Stern <stern@rowland.harvard.edu>
2010-07-06 04:43:53 +08:00
|
|
|
}
|
2012-04-30 04:53:22 +08:00
|
|
|
|
|
|
|
out:
|
|
|
|
pm_autosleep_unlock();
|
|
|
|
return error;
|
PM: Make it possible to avoid races between wakeup and system sleep
One of the arguments during the suspend blockers discussion was that
the mainline kernel didn't contain any mechanisms making it possible
to avoid races between wakeup and system suspend.
Generally, there are two problems in that area. First, if a wakeup
event occurs exactly when /sys/power/state is being written to, it
may be delivered to user space right before the freezer kicks in, so
the user space consumer of the event may not be able to process it
before the system is suspended. Second, if a wakeup event occurs
after user space has been frozen, it is not generally guaranteed that
the ongoing transition of the system into a sleep state will be
aborted.
To address these issues introduce a new global sysfs attribute,
/sys/power/wakeup_count, associated with a running counter of wakeup
events and three helper functions, pm_stay_awake(), pm_relax(), and
pm_wakeup_event(), that may be used by kernel subsystems to control
the behavior of this attribute and to request the PM core to abort
system transitions into a sleep state already in progress.
The /sys/power/wakeup_count file may be read from or written to by
user space. Reads will always succeed (unless interrupted by a
signal) and return the current value of the wakeup events counter.
Writes, however, will only succeed if the written number is equal to
the current value of the wakeup events counter. If a write is
successful, it will cause the kernel to save the current value of the
wakeup events counter and to abort the subsequent system transition
into a sleep state if any wakeup events are reported after the write
has returned.
[The assumption is that before writing to /sys/power/state user space
will first read from /sys/power/wakeup_count. Next, user space
consumers of wakeup events will have a chance to acknowledge or
veto the upcoming system transition to a sleep state. Finally, if
the transition is allowed to proceed, /sys/power/wakeup_count will
be written to and if that succeeds, /sys/power/state will be written
to as well. Still, if any wakeup events are reported to the PM core
by kernel subsystems after that point, the transition will be
aborted.]
Additionally, put a wakeup events counter into struct dev_pm_info and
make these per-device wakeup event counters available via sysfs,
so that it's possible to check the activity of various wakeup event
sources within the kernel.
To illustrate how subsystems can use pm_wakeup_event(), make the
low-level PCI runtime PM wakeup-handling code use it.
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Acked-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Acked-by: Greg Kroah-Hartman <gregkh@suse.de>
Acked-by: markgross <markgross@thegnar.org>
Reviewed-by: Alan Stern <stern@rowland.harvard.edu>
2010-07-06 04:43:53 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
power_attr(wakeup_count);
|
2012-04-30 04:53:22 +08:00
|
|
|
|
|
|
|
#ifdef CONFIG_PM_AUTOSLEEP
|
|
|
|
static ssize_t autosleep_show(struct kobject *kobj,
|
|
|
|
struct kobj_attribute *attr,
|
|
|
|
char *buf)
|
|
|
|
{
|
|
|
|
suspend_state_t state = pm_autosleep_state();
|
|
|
|
|
|
|
|
if (state == PM_SUSPEND_ON)
|
|
|
|
return sprintf(buf, "off\n");
|
|
|
|
|
|
|
|
#ifdef CONFIG_SUSPEND
|
|
|
|
if (state < PM_SUSPEND_MAX)
|
2014-07-16 04:02:11 +08:00
|
|
|
return sprintf(buf, "%s\n", pm_states[state] ?
|
|
|
|
pm_states[state] : "error");
|
2012-04-30 04:53:22 +08:00
|
|
|
#endif
|
|
|
|
#ifdef CONFIG_HIBERNATION
|
|
|
|
return sprintf(buf, "disk\n");
|
|
|
|
#else
|
|
|
|
return sprintf(buf, "error");
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
static ssize_t autosleep_store(struct kobject *kobj,
|
|
|
|
struct kobj_attribute *attr,
|
|
|
|
const char *buf, size_t n)
|
|
|
|
{
|
|
|
|
suspend_state_t state = decode_state(buf, n);
|
|
|
|
int error;
|
|
|
|
|
|
|
|
if (state == PM_SUSPEND_ON
|
2012-05-04 06:14:21 +08:00
|
|
|
&& strcmp(buf, "off") && strcmp(buf, "off\n"))
|
2012-04-30 04:53:22 +08:00
|
|
|
return -EINVAL;
|
|
|
|
|
PM / sleep: System sleep state selection interface rework
There are systems in which the platform doesn't support any special
sleep states, so suspend-to-idle (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 may be a pain in practice.
Commit 0399d4db3edf (PM / sleep: Introduce command line argument for
sleep state enumeration) attempted to address this problem by adding
a command line argument to change the meaning of the "mem" string in
/sys/power/state to make it trigger suspend-to-idle (instead of
suspend-to-RAM).
However, there also are systems in which the platform does support
special sleep states, but suspend-to-idle is the preferred one anyway
(it even may save more energy than the platform-provided sleep states
in some cases) and the above commit doesn't help in those cases.
For this reason, rework the system sleep state selection interface
again (but preserve backwards compatibiliby). Namely, add a new
sysfs file, /sys/power/mem_sleep, that will control the system
suspend mode triggered by writing "mem" to /sys/power/state (in
analogy with what /sys/power/disk does for hibernation). Make it
select suspend-to-RAM ("deep" sleep) by default (if supported) and
fall back to suspend-to-idle ("s2idle") otherwise and add a new
command line argument, mem_sleep_default, allowing that default to
be overridden if need be.
At the same time, drop the relative_sleep_states command line
argument that doesn't make sense any more.
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Tested-by: Mario Limonciello <mario.limonciello@dell.com>
2016-11-22 05:45:40 +08:00
|
|
|
if (state == PM_SUSPEND_MEM)
|
|
|
|
state = mem_sleep_current;
|
|
|
|
|
2012-04-30 04:53:22 +08:00
|
|
|
error = pm_autosleep_set_state(state);
|
|
|
|
return error ? error : n;
|
|
|
|
}
|
|
|
|
|
|
|
|
power_attr(autosleep);
|
|
|
|
#endif /* CONFIG_PM_AUTOSLEEP */
|
PM / Sleep: Add user space interface for manipulating wakeup sources, v3
Android allows user space to manipulate wakelocks using two
sysfs file located in /sys/power/, wake_lock and wake_unlock.
Writing a wakelock name and optionally a timeout to the wake_lock
file causes the wakelock whose name was written to be acquired (it
is created before is necessary), optionally with the given timeout.
Writing the name of a wakelock to wake_unlock causes that wakelock
to be released.
Implement an analogous interface for user space using wakeup sources.
Add the /sys/power/wake_lock and /sys/power/wake_unlock files
allowing user space to create, activate and deactivate wakeup
sources, such that writing a name and optionally a timeout to
wake_lock causes the wakeup source of that name to be activated,
optionally with the given timeout. If that wakeup source doesn't
exist, it will be created and then activated. Writing a name to
wake_unlock causes the wakeup source of that name, if there is one,
to be deactivated. Wakeup sources created with the help of
wake_lock that haven't been used for more than 5 minutes are garbage
collected and destroyed. Moreover, there can be only WL_NUMBER_LIMIT
wakeup sources created with the help of wake_lock present at a time.
The data type used to track wakeup sources created by user space is
called "struct wakelock" to indicate the origins of this feature.
This version of the patch includes an rbtree manipulation fix from John Stultz.
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Reviewed-by: NeilBrown <neilb@suse.de>
2012-04-30 04:53:42 +08:00
|
|
|
|
|
|
|
#ifdef CONFIG_PM_WAKELOCKS
|
|
|
|
static ssize_t wake_lock_show(struct kobject *kobj,
|
|
|
|
struct kobj_attribute *attr,
|
|
|
|
char *buf)
|
|
|
|
{
|
|
|
|
return pm_show_wakelocks(buf, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
static ssize_t wake_lock_store(struct kobject *kobj,
|
|
|
|
struct kobj_attribute *attr,
|
|
|
|
const char *buf, size_t n)
|
|
|
|
{
|
|
|
|
int error = pm_wake_lock(buf);
|
|
|
|
return error ? error : n;
|
|
|
|
}
|
|
|
|
|
|
|
|
power_attr(wake_lock);
|
|
|
|
|
|
|
|
static ssize_t wake_unlock_show(struct kobject *kobj,
|
|
|
|
struct kobj_attribute *attr,
|
|
|
|
char *buf)
|
|
|
|
{
|
|
|
|
return pm_show_wakelocks(buf, false);
|
|
|
|
}
|
|
|
|
|
|
|
|
static ssize_t wake_unlock_store(struct kobject *kobj,
|
|
|
|
struct kobj_attribute *attr,
|
|
|
|
const char *buf, size_t n)
|
|
|
|
{
|
|
|
|
int error = pm_wake_unlock(buf);
|
|
|
|
return error ? error : n;
|
|
|
|
}
|
|
|
|
|
|
|
|
power_attr(wake_unlock);
|
|
|
|
|
|
|
|
#endif /* CONFIG_PM_WAKELOCKS */
|
PM: Make it possible to avoid races between wakeup and system sleep
One of the arguments during the suspend blockers discussion was that
the mainline kernel didn't contain any mechanisms making it possible
to avoid races between wakeup and system suspend.
Generally, there are two problems in that area. First, if a wakeup
event occurs exactly when /sys/power/state is being written to, it
may be delivered to user space right before the freezer kicks in, so
the user space consumer of the event may not be able to process it
before the system is suspended. Second, if a wakeup event occurs
after user space has been frozen, it is not generally guaranteed that
the ongoing transition of the system into a sleep state will be
aborted.
To address these issues introduce a new global sysfs attribute,
/sys/power/wakeup_count, associated with a running counter of wakeup
events and three helper functions, pm_stay_awake(), pm_relax(), and
pm_wakeup_event(), that may be used by kernel subsystems to control
the behavior of this attribute and to request the PM core to abort
system transitions into a sleep state already in progress.
The /sys/power/wakeup_count file may be read from or written to by
user space. Reads will always succeed (unless interrupted by a
signal) and return the current value of the wakeup events counter.
Writes, however, will only succeed if the written number is equal to
the current value of the wakeup events counter. If a write is
successful, it will cause the kernel to save the current value of the
wakeup events counter and to abort the subsequent system transition
into a sleep state if any wakeup events are reported after the write
has returned.
[The assumption is that before writing to /sys/power/state user space
will first read from /sys/power/wakeup_count. Next, user space
consumers of wakeup events will have a chance to acknowledge or
veto the upcoming system transition to a sleep state. Finally, if
the transition is allowed to proceed, /sys/power/wakeup_count will
be written to and if that succeeds, /sys/power/state will be written
to as well. Still, if any wakeup events are reported to the PM core
by kernel subsystems after that point, the transition will be
aborted.]
Additionally, put a wakeup events counter into struct dev_pm_info and
make these per-device wakeup event counters available via sysfs,
so that it's possible to check the activity of various wakeup event
sources within the kernel.
To illustrate how subsystems can use pm_wakeup_event(), make the
low-level PCI runtime PM wakeup-handling code use it.
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Acked-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Acked-by: Greg Kroah-Hartman <gregkh@suse.de>
Acked-by: markgross <markgross@thegnar.org>
Reviewed-by: Alan Stern <stern@rowland.harvard.edu>
2010-07-06 04:43:53 +08:00
|
|
|
#endif /* CONFIG_PM_SLEEP */
|
|
|
|
|
2006-09-26 14:32:58 +08:00
|
|
|
#ifdef CONFIG_PM_TRACE
|
|
|
|
int pm_trace_enabled;
|
|
|
|
|
2007-11-02 20:47:53 +08:00
|
|
|
static ssize_t pm_trace_show(struct kobject *kobj, struct kobj_attribute *attr,
|
|
|
|
char *buf)
|
2006-09-26 14:32:58 +08:00
|
|
|
{
|
|
|
|
return sprintf(buf, "%d\n", pm_trace_enabled);
|
|
|
|
}
|
|
|
|
|
|
|
|
static ssize_t
|
2007-11-02 20:47:53 +08:00
|
|
|
pm_trace_store(struct kobject *kobj, struct kobj_attribute *attr,
|
|
|
|
const char *buf, size_t n)
|
2006-09-26 14:32:58 +08:00
|
|
|
{
|
|
|
|
int val;
|
|
|
|
|
|
|
|
if (sscanf(buf, "%d", &val) == 1) {
|
|
|
|
pm_trace_enabled = !!val;
|
2013-06-27 06:27:35 +08:00
|
|
|
if (pm_trace_enabled) {
|
|
|
|
pr_warn("PM: Enabling pm_trace changes system date and time during resume.\n"
|
|
|
|
"PM: Correct system time has to be restored manually after resume.\n");
|
|
|
|
}
|
2006-09-26 14:32:58 +08:00
|
|
|
return n;
|
|
|
|
}
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
power_attr(pm_trace);
|
2010-10-12 06:00:25 +08:00
|
|
|
|
|
|
|
static ssize_t pm_trace_dev_match_show(struct kobject *kobj,
|
|
|
|
struct kobj_attribute *attr,
|
|
|
|
char *buf)
|
|
|
|
{
|
|
|
|
return show_trace_dev_match(buf, PAGE_SIZE);
|
|
|
|
}
|
|
|
|
|
2016-01-02 10:09:16 +08:00
|
|
|
power_attr_ro(pm_trace_dev_match);
|
2010-10-12 06:00:25 +08:00
|
|
|
|
Suspend: Testing facility (rev. 2)
Introduce sysfs attribute /sys/power/pm_test allowing one to test the suspend
core code. Namely, writing one of the strings:
freezer
devices
platform
processors
core
to this file causes the suspend code to work in one of the test modes defined as
follows:
freezer
- test the freezing of processes
devices
- test the freezing of processes and suspending of devices
platform
- test the freezing of processes, suspending of devices and platform global
control methods(*)
processors
- test the freezing of processes, suspending of devices, platform global
control methods and the disabling of nonboot CPUs
core
- test the freezing of processes, suspending of devices, platform global
control methods, the disabling of nonboot CPUs and suspending of
platform/system devices
(*) These are ACPI global control methods on ACPI systems
Then, if a suspend is started by normal means, the suspend core will perform
its normal operations up to the point indicated by given test level. Next, it
will wait for 5 seconds and carry out the resume operations needed to transition
the system back to the fully functional state.
Writing "none" to /sys/power/pm_test turns the testing off.
When open for reading, /sys/power/pm_test contains a space-separated list of all
available tests (including "none" that represents the normal functionality) in
which the current test level is indicated by square brackets.
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Acked-by: Pavel Machek <pavel@ucw.cz>
Signed-off-by: Len Brown <len.brown@intel.com>
2007-11-20 06:41:19 +08:00
|
|
|
#endif /* CONFIG_PM_TRACE */
|
2006-09-26 14:32:58 +08:00
|
|
|
|
2013-02-01 16:56:03 +08:00
|
|
|
#ifdef CONFIG_FREEZER
|
|
|
|
static ssize_t pm_freeze_timeout_show(struct kobject *kobj,
|
|
|
|
struct kobj_attribute *attr, char *buf)
|
|
|
|
{
|
|
|
|
return sprintf(buf, "%u\n", freeze_timeout_msecs);
|
|
|
|
}
|
|
|
|
|
|
|
|
static ssize_t pm_freeze_timeout_store(struct kobject *kobj,
|
|
|
|
struct kobj_attribute *attr,
|
|
|
|
const char *buf, size_t n)
|
|
|
|
{
|
|
|
|
unsigned long val;
|
|
|
|
|
|
|
|
if (kstrtoul(buf, 10, &val))
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
freeze_timeout_msecs = val;
|
|
|
|
return n;
|
|
|
|
}
|
|
|
|
|
|
|
|
power_attr(pm_freeze_timeout);
|
|
|
|
|
|
|
|
#endif /* CONFIG_FREEZER*/
|
|
|
|
|
2006-09-26 14:32:58 +08:00
|
|
|
static struct attribute * g[] = {
|
|
|
|
&state_attr.attr,
|
Suspend: Testing facility (rev. 2)
Introduce sysfs attribute /sys/power/pm_test allowing one to test the suspend
core code. Namely, writing one of the strings:
freezer
devices
platform
processors
core
to this file causes the suspend code to work in one of the test modes defined as
follows:
freezer
- test the freezing of processes
devices
- test the freezing of processes and suspending of devices
platform
- test the freezing of processes, suspending of devices and platform global
control methods(*)
processors
- test the freezing of processes, suspending of devices, platform global
control methods and the disabling of nonboot CPUs
core
- test the freezing of processes, suspending of devices, platform global
control methods, the disabling of nonboot CPUs and suspending of
platform/system devices
(*) These are ACPI global control methods on ACPI systems
Then, if a suspend is started by normal means, the suspend core will perform
its normal operations up to the point indicated by given test level. Next, it
will wait for 5 seconds and carry out the resume operations needed to transition
the system back to the fully functional state.
Writing "none" to /sys/power/pm_test turns the testing off.
When open for reading, /sys/power/pm_test contains a space-separated list of all
available tests (including "none" that represents the normal functionality) in
which the current test level is indicated by square brackets.
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Acked-by: Pavel Machek <pavel@ucw.cz>
Signed-off-by: Len Brown <len.brown@intel.com>
2007-11-20 06:41:19 +08:00
|
|
|
#ifdef CONFIG_PM_TRACE
|
2006-09-26 14:32:58 +08:00
|
|
|
&pm_trace_attr.attr,
|
2010-10-12 06:00:25 +08:00
|
|
|
&pm_trace_dev_match_attr.attr,
|
Suspend: Testing facility (rev. 2)
Introduce sysfs attribute /sys/power/pm_test allowing one to test the suspend
core code. Namely, writing one of the strings:
freezer
devices
platform
processors
core
to this file causes the suspend code to work in one of the test modes defined as
follows:
freezer
- test the freezing of processes
devices
- test the freezing of processes and suspending of devices
platform
- test the freezing of processes, suspending of devices and platform global
control methods(*)
processors
- test the freezing of processes, suspending of devices, platform global
control methods and the disabling of nonboot CPUs
core
- test the freezing of processes, suspending of devices, platform global
control methods, the disabling of nonboot CPUs and suspending of
platform/system devices
(*) These are ACPI global control methods on ACPI systems
Then, if a suspend is started by normal means, the suspend core will perform
its normal operations up to the point indicated by given test level. Next, it
will wait for 5 seconds and carry out the resume operations needed to transition
the system back to the fully functional state.
Writing "none" to /sys/power/pm_test turns the testing off.
When open for reading, /sys/power/pm_test contains a space-separated list of all
available tests (including "none" that represents the normal functionality) in
which the current test level is indicated by square brackets.
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Acked-by: Pavel Machek <pavel@ucw.cz>
Signed-off-by: Len Brown <len.brown@intel.com>
2007-11-20 06:41:19 +08:00
|
|
|
#endif
|
2010-01-24 05:25:15 +08:00
|
|
|
#ifdef CONFIG_PM_SLEEP
|
|
|
|
&pm_async_attr.attr,
|
PM: Make it possible to avoid races between wakeup and system sleep
One of the arguments during the suspend blockers discussion was that
the mainline kernel didn't contain any mechanisms making it possible
to avoid races between wakeup and system suspend.
Generally, there are two problems in that area. First, if a wakeup
event occurs exactly when /sys/power/state is being written to, it
may be delivered to user space right before the freezer kicks in, so
the user space consumer of the event may not be able to process it
before the system is suspended. Second, if a wakeup event occurs
after user space has been frozen, it is not generally guaranteed that
the ongoing transition of the system into a sleep state will be
aborted.
To address these issues introduce a new global sysfs attribute,
/sys/power/wakeup_count, associated with a running counter of wakeup
events and three helper functions, pm_stay_awake(), pm_relax(), and
pm_wakeup_event(), that may be used by kernel subsystems to control
the behavior of this attribute and to request the PM core to abort
system transitions into a sleep state already in progress.
The /sys/power/wakeup_count file may be read from or written to by
user space. Reads will always succeed (unless interrupted by a
signal) and return the current value of the wakeup events counter.
Writes, however, will only succeed if the written number is equal to
the current value of the wakeup events counter. If a write is
successful, it will cause the kernel to save the current value of the
wakeup events counter and to abort the subsequent system transition
into a sleep state if any wakeup events are reported after the write
has returned.
[The assumption is that before writing to /sys/power/state user space
will first read from /sys/power/wakeup_count. Next, user space
consumers of wakeup events will have a chance to acknowledge or
veto the upcoming system transition to a sleep state. Finally, if
the transition is allowed to proceed, /sys/power/wakeup_count will
be written to and if that succeeds, /sys/power/state will be written
to as well. Still, if any wakeup events are reported to the PM core
by kernel subsystems after that point, the transition will be
aborted.]
Additionally, put a wakeup events counter into struct dev_pm_info and
make these per-device wakeup event counters available via sysfs,
so that it's possible to check the activity of various wakeup event
sources within the kernel.
To illustrate how subsystems can use pm_wakeup_event(), make the
low-level PCI runtime PM wakeup-handling code use it.
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Acked-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Acked-by: Greg Kroah-Hartman <gregkh@suse.de>
Acked-by: markgross <markgross@thegnar.org>
Reviewed-by: Alan Stern <stern@rowland.harvard.edu>
2010-07-06 04:43:53 +08:00
|
|
|
&wakeup_count_attr.attr,
|
PM / sleep: System sleep state selection interface rework
There are systems in which the platform doesn't support any special
sleep states, so suspend-to-idle (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 may be a pain in practice.
Commit 0399d4db3edf (PM / sleep: Introduce command line argument for
sleep state enumeration) attempted to address this problem by adding
a command line argument to change the meaning of the "mem" string in
/sys/power/state to make it trigger suspend-to-idle (instead of
suspend-to-RAM).
However, there also are systems in which the platform does support
special sleep states, but suspend-to-idle is the preferred one anyway
(it even may save more energy than the platform-provided sleep states
in some cases) and the above commit doesn't help in those cases.
For this reason, rework the system sleep state selection interface
again (but preserve backwards compatibiliby). Namely, add a new
sysfs file, /sys/power/mem_sleep, that will control the system
suspend mode triggered by writing "mem" to /sys/power/state (in
analogy with what /sys/power/disk does for hibernation). Make it
select suspend-to-RAM ("deep" sleep) by default (if supported) and
fall back to suspend-to-idle ("s2idle") otherwise and add a new
command line argument, mem_sleep_default, allowing that default to
be overridden if need be.
At the same time, drop the relative_sleep_states command line
argument that doesn't make sense any more.
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Tested-by: Mario Limonciello <mario.limonciello@dell.com>
2016-11-22 05:45:40 +08:00
|
|
|
#ifdef CONFIG_SUSPEND
|
|
|
|
&mem_sleep_attr.attr,
|
2020-01-16 19:53:54 +08:00
|
|
|
&sync_on_suspend_attr.attr,
|
PM / sleep: System sleep state selection interface rework
There are systems in which the platform doesn't support any special
sleep states, so suspend-to-idle (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 may be a pain in practice.
Commit 0399d4db3edf (PM / sleep: Introduce command line argument for
sleep state enumeration) attempted to address this problem by adding
a command line argument to change the meaning of the "mem" string in
/sys/power/state to make it trigger suspend-to-idle (instead of
suspend-to-RAM).
However, there also are systems in which the platform does support
special sleep states, but suspend-to-idle is the preferred one anyway
(it even may save more energy than the platform-provided sleep states
in some cases) and the above commit doesn't help in those cases.
For this reason, rework the system sleep state selection interface
again (but preserve backwards compatibiliby). Namely, add a new
sysfs file, /sys/power/mem_sleep, that will control the system
suspend mode triggered by writing "mem" to /sys/power/state (in
analogy with what /sys/power/disk does for hibernation). Make it
select suspend-to-RAM ("deep" sleep) by default (if supported) and
fall back to suspend-to-idle ("s2idle") otherwise and add a new
command line argument, mem_sleep_default, allowing that default to
be overridden if need be.
At the same time, drop the relative_sleep_states command line
argument that doesn't make sense any more.
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Tested-by: Mario Limonciello <mario.limonciello@dell.com>
2016-11-22 05:45:40 +08:00
|
|
|
#endif
|
2012-04-30 04:53:22 +08:00
|
|
|
#ifdef CONFIG_PM_AUTOSLEEP
|
|
|
|
&autosleep_attr.attr,
|
|
|
|
#endif
|
PM / Sleep: Add user space interface for manipulating wakeup sources, v3
Android allows user space to manipulate wakelocks using two
sysfs file located in /sys/power/, wake_lock and wake_unlock.
Writing a wakelock name and optionally a timeout to the wake_lock
file causes the wakelock whose name was written to be acquired (it
is created before is necessary), optionally with the given timeout.
Writing the name of a wakelock to wake_unlock causes that wakelock
to be released.
Implement an analogous interface for user space using wakeup sources.
Add the /sys/power/wake_lock and /sys/power/wake_unlock files
allowing user space to create, activate and deactivate wakeup
sources, such that writing a name and optionally a timeout to
wake_lock causes the wakeup source of that name to be activated,
optionally with the given timeout. If that wakeup source doesn't
exist, it will be created and then activated. Writing a name to
wake_unlock causes the wakeup source of that name, if there is one,
to be deactivated. Wakeup sources created with the help of
wake_lock that haven't been used for more than 5 minutes are garbage
collected and destroyed. Moreover, there can be only WL_NUMBER_LIMIT
wakeup sources created with the help of wake_lock present at a time.
The data type used to track wakeup sources created by user space is
called "struct wakelock" to indicate the origins of this feature.
This version of the patch includes an rbtree manipulation fix from John Stultz.
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Reviewed-by: NeilBrown <neilb@suse.de>
2012-04-30 04:53:42 +08:00
|
|
|
#ifdef CONFIG_PM_WAKELOCKS
|
|
|
|
&wake_lock_attr.attr,
|
|
|
|
&wake_unlock_attr.attr,
|
|
|
|
#endif
|
2012-06-21 06:19:33 +08:00
|
|
|
#ifdef CONFIG_PM_SLEEP_DEBUG
|
2017-07-21 20:44:02 +08:00
|
|
|
&pm_test_attr.attr,
|
2012-06-20 04:23:33 +08:00
|
|
|
&pm_print_times_attr.attr,
|
2015-09-16 01:32:46 +08:00
|
|
|
&pm_wakeup_irq_attr.attr,
|
2017-07-19 08:38:44 +08:00
|
|
|
&pm_debug_messages_attr.attr,
|
2010-01-24 05:25:15 +08:00
|
|
|
#endif
|
2013-02-01 16:56:03 +08:00
|
|
|
#endif
|
|
|
|
#ifdef CONFIG_FREEZER
|
|
|
|
&pm_freeze_timeout_attr.attr,
|
Suspend: Testing facility (rev. 2)
Introduce sysfs attribute /sys/power/pm_test allowing one to test the suspend
core code. Namely, writing one of the strings:
freezer
devices
platform
processors
core
to this file causes the suspend code to work in one of the test modes defined as
follows:
freezer
- test the freezing of processes
devices
- test the freezing of processes and suspending of devices
platform
- test the freezing of processes, suspending of devices and platform global
control methods(*)
processors
- test the freezing of processes, suspending of devices, platform global
control methods and the disabling of nonboot CPUs
core
- test the freezing of processes, suspending of devices, platform global
control methods, the disabling of nonboot CPUs and suspending of
platform/system devices
(*) These are ACPI global control methods on ACPI systems
Then, if a suspend is started by normal means, the suspend core will perform
its normal operations up to the point indicated by given test level. Next, it
will wait for 5 seconds and carry out the resume operations needed to transition
the system back to the fully functional state.
Writing "none" to /sys/power/pm_test turns the testing off.
When open for reading, /sys/power/pm_test contains a space-separated list of all
available tests (including "none" that represents the normal functionality) in
which the current test level is indicated by square brackets.
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Acked-by: Pavel Machek <pavel@ucw.cz>
Signed-off-by: Len Brown <len.brown@intel.com>
2007-11-20 06:41:19 +08:00
|
|
|
#endif
|
2006-09-26 14:32:58 +08:00
|
|
|
NULL,
|
|
|
|
};
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2017-06-30 12:52:14 +08:00
|
|
|
static const struct attribute_group attr_group = {
|
2005-04-17 06:20:36 +08:00
|
|
|
.attrs = g,
|
|
|
|
};
|
|
|
|
|
2019-08-01 05:29:33 +08:00
|
|
|
static const struct attribute_group *attr_groups[] = {
|
|
|
|
&attr_group,
|
|
|
|
#ifdef CONFIG_PM_SLEEP
|
|
|
|
&suspend_attr_group,
|
|
|
|
#endif
|
|
|
|
NULL,
|
|
|
|
};
|
|
|
|
|
2009-08-19 05:38:32 +08:00
|
|
|
struct workqueue_struct *pm_wq;
|
2009-12-04 03:22:21 +08:00
|
|
|
EXPORT_SYMBOL_GPL(pm_wq);
|
2009-08-19 05:38:32 +08:00
|
|
|
|
|
|
|
static int __init pm_start_workqueue(void)
|
|
|
|
{
|
2011-02-16 16:25:31 +08:00
|
|
|
pm_wq = alloc_workqueue("pm", WQ_FREEZABLE, 0);
|
2009-08-19 05:38:32 +08:00
|
|
|
|
|
|
|
return pm_wq ? 0 : -ENOMEM;
|
|
|
|
}
|
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
static int __init pm_init(void)
|
|
|
|
{
|
2009-08-19 05:38:32 +08:00
|
|
|
int error = pm_start_workqueue();
|
|
|
|
if (error)
|
|
|
|
return error;
|
2010-09-21 01:44:56 +08:00
|
|
|
hibernate_image_size_init();
|
2011-05-15 17:38:48 +08:00
|
|
|
hibernate_reserved_size_init();
|
2016-08-19 21:41:00 +08:00
|
|
|
pm_states_init();
|
2007-11-28 03:28:26 +08:00
|
|
|
power_kobj = kobject_create_and_add("power", NULL);
|
|
|
|
if (!power_kobj)
|
2007-11-02 01:39:50 +08:00
|
|
|
return -ENOMEM;
|
2019-08-01 05:29:33 +08:00
|
|
|
error = sysfs_create_groups(power_kobj, attr_groups);
|
2012-04-30 04:53:22 +08:00
|
|
|
if (error)
|
|
|
|
return error;
|
2012-06-21 06:19:33 +08:00
|
|
|
pm_print_times_init();
|
2012-04-30 04:53:22 +08:00
|
|
|
return pm_autosleep_init();
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
core_initcall(pm_init);
|