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
|
|
|
|
*
|
|
|
|
* This file is released under the GPLv2
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
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>
|
2006-09-26 14:32:58 +08:00
|
|
|
#include <linux/resume-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>
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
#include "power.h"
|
|
|
|
|
2006-12-07 12:34:35 +08:00
|
|
|
DEFINE_MUTEX(pm_mutex);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2011-02-11 07:04:52 +08:00
|
|
|
#ifdef CONFIG_PM_SLEEP
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
int pm_notifier_call_chain(unsigned long val)
|
|
|
|
{
|
2011-07-09 02:53:36 +08:00
|
|
|
int ret = blocking_notifier_call_chain(&pm_chain_head, val, NULL);
|
|
|
|
|
|
|
|
return notifier_to_errno(ret);
|
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;
|
|
|
|
|
|
|
|
if (strict_strtoul(buf, 10, &val))
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
if (val > 1)
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
pm_async_enabled = val;
|
|
|
|
return n;
|
|
|
|
}
|
|
|
|
|
|
|
|
power_attr(pm_async);
|
|
|
|
|
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_DEBUG
|
|
|
|
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;
|
|
|
|
|
|
|
|
mutex_lock(&pm_mutex);
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
mutex_unlock(&pm_mutex);
|
|
|
|
|
|
|
|
return error ? error : n;
|
|
|
|
}
|
|
|
|
|
|
|
|
power_attr(pm_test);
|
2009-01-17 07:10:45 +08:00
|
|
|
#endif /* CONFIG_PM_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
|
|
|
#ifdef CONFIG_DEBUG_FS
|
|
|
|
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 "";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
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",
|
|
|
|
"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,
|
|
|
|
"failed_suspend_noirq",
|
|
|
|
suspend_stats.failed_suspend_noirq,
|
|
|
|
"failed_resume", suspend_stats.failed_resume,
|
|
|
|
"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;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int suspend_stats_open(struct inode *inode, struct file *file)
|
|
|
|
{
|
|
|
|
return single_open(file, suspend_stats_show, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
static const struct file_operations suspend_stats_operations = {
|
|
|
|
.open = suspend_stats_open,
|
|
|
|
.read = seq_read,
|
|
|
|
.llseek = seq_lseek,
|
|
|
|
.release = single_release,
|
|
|
|
};
|
|
|
|
|
|
|
|
static int __init pm_debugfs_init(void)
|
|
|
|
{
|
|
|
|
debugfs_create_file("suspend_stats", S_IFREG | S_IRUGO,
|
|
|
|
NULL, NULL, &suspend_stats_operations);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
late_initcall(pm_debugfs_init);
|
|
|
|
#endif /* CONFIG_DEBUG_FS */
|
|
|
|
|
2011-08-12 04:38:12 +08:00
|
|
|
#endif /* CONFIG_PM_SLEEP */
|
|
|
|
|
2007-11-28 03:28:26 +08:00
|
|
|
struct kobject *power_kobj;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* state - control system power state.
|
|
|
|
*
|
|
|
|
* show() returns what states are supported, which is hard-coded to
|
|
|
|
* 'standby' (Power-On Suspend), 'mem' (Suspend-to-RAM), and
|
|
|
|
* 'disk' (Suspend-to-Disk).
|
|
|
|
*
|
|
|
|
* store() accepts one of those strings, translates it into the
|
|
|
|
* proper enumerated value, and initiates a suspend transition.
|
|
|
|
*/
|
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
|
2005-04-17 06:20:36 +08:00
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < PM_SUSPEND_MAX; i++) {
|
2005-11-30 11:34:37 +08:00
|
|
|
if (pm_states[i] && valid_state(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
|
2007-07-30 05:24:36 +08:00
|
|
|
#ifdef CONFIG_HIBERNATION
|
2007-05-09 17:33:18 +08:00
|
|
|
s += sprintf(s, "%s\n", "disk");
|
|
|
|
#else
|
|
|
|
if (s != buf)
|
|
|
|
/* convert the last space to a newline */
|
|
|
|
*(s-1) = '\n';
|
|
|
|
#endif
|
2005-04-17 06:20:36 +08:00
|
|
|
return (s - buf);
|
|
|
|
}
|
|
|
|
|
2007-11-02 20:47:53 +08:00
|
|
|
static ssize_t state_store(struct kobject *kobj, struct kobj_attribute *attr,
|
|
|
|
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
|
2005-04-17 06:20:36 +08:00
|
|
|
suspend_state_t state = PM_SUSPEND_STANDBY;
|
2006-06-25 20:47:56 +08:00
|
|
|
const char * const *s;
|
2007-07-30 05:27:18 +08:00
|
|
|
#endif
|
2005-04-17 06:20:36 +08:00
|
|
|
char *p;
|
|
|
|
int len;
|
2007-07-30 05:27:18 +08:00
|
|
|
int error = -EINVAL;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
p = memchr(buf, '\n', n);
|
|
|
|
len = p ? p - buf : n;
|
|
|
|
|
2007-05-09 17:33:18 +08:00
|
|
|
/* First, check if we are requested to hibernate */
|
2007-05-17 13:11:19 +08:00
|
|
|
if (len == 4 && !strncmp(buf, "disk", len)) {
|
2007-05-09 17:33:18 +08:00
|
|
|
error = hibernate();
|
2007-07-30 05:27:18 +08:00
|
|
|
goto Exit;
|
2007-05-09 17:33:18 +08:00
|
|
|
}
|
|
|
|
|
2007-07-30 05:27:18 +08:00
|
|
|
#ifdef CONFIG_SUSPEND
|
2005-04-17 06:20:36 +08:00
|
|
|
for (s = &pm_states[state]; state < PM_SUSPEND_MAX; s++, state++) {
|
2007-05-17 13:11:19 +08:00
|
|
|
if (*s && len == strlen(*s) && !strncmp(buf, *s, len))
|
2005-04-17 06:20:36 +08:00
|
|
|
break;
|
|
|
|
}
|
2011-11-19 21:37:57 +08:00
|
|
|
if (state < PM_SUSPEND_MAX && *s) {
|
2005-04-17 06:20:36 +08:00
|
|
|
error = enter_state(state);
|
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
|
|
|
if (error) {
|
|
|
|
suspend_stats.fail++;
|
|
|
|
dpm_save_failed_errno(error);
|
|
|
|
} else
|
|
|
|
suspend_stats.success++;
|
2011-11-19 21:37:57 +08:00
|
|
|
}
|
2007-07-30 05:27:18 +08:00
|
|
|
#endif
|
|
|
|
|
|
|
|
Exit:
|
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
|
|
|
|
2010-09-23 04:09:10 +08:00
|
|
|
return pm_get_wakeup_count(&val) ? 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;
|
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
|
|
|
|
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))
|
|
|
|
return n;
|
|
|
|
}
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
power_attr(wakeup_count);
|
|
|
|
#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;
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
|
|
|
static ssize_t
|
|
|
|
pm_trace_dev_match_store(struct kobject *kobj, struct kobj_attribute *attr,
|
|
|
|
const char *buf, size_t n)
|
|
|
|
{
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
power_attr(pm_trace_dev_match);
|
|
|
|
|
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
|
|
|
|
|
|
|
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,
|
2010-01-24 05:25:15 +08:00
|
|
|
#ifdef CONFIG_PM_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_test_attr.attr,
|
2010-01-24 05:25:15 +08:00
|
|
|
#endif
|
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
|
|
|
|
|
|
|
static struct attribute_group attr_group = {
|
|
|
|
.attrs = g,
|
|
|
|
};
|
|
|
|
|
2009-08-19 05:38:32 +08:00
|
|
|
#ifdef CONFIG_PM_RUNTIME
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
static inline int pm_start_workqueue(void) { return 0; }
|
|
|
|
#endif
|
|
|
|
|
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();
|
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;
|
2007-11-28 03:28:26 +08:00
|
|
|
return sysfs_create_group(power_kobj, &attr_group);
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
core_initcall(pm_init);
|