aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRafael J. Wysocki <rjw@sisk.pl>2010-01-23 16:25:23 -0500
committerRafael J. Wysocki <rjw@sisk.pl>2010-02-26 14:39:10 -0500
commit5a2eb8585f3b38e01e30aacaa8b985a1520a993d (patch)
tree471b33cc48cf48ed491e8b3f2934bfb3fa9e81e1
parent0e06b4a891c6a108412fe24b4500f499da2cf8a1 (diff)
PM: Add facility for advanced testing of async suspend/resume
Add configuration switch CONFIG_PM_ADVANCED_DEBUG for compiling in extra PM debugging/testing code allowing one to access some PM-related attributes of devices from the user space via sysfs. If CONFIG_PM_ADVANCED_DEBUG is set, add sysfs attribute power/async for every device allowing the user space to access the device's power.async_suspend flag and modify it, if desired. Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
-rw-r--r--Documentation/ABI/testing/sysfs-devices-power26
-rw-r--r--drivers/base/power/sysfs.c49
-rw-r--r--include/linux/device.h11
-rw-r--r--kernel/power/Kconfig14
4 files changed, 100 insertions, 0 deletions
diff --git a/Documentation/ABI/testing/sysfs-devices-power b/Documentation/ABI/testing/sysfs-devices-power
index 431bfd7e65c7..6123c523bfd7 100644
--- a/Documentation/ABI/testing/sysfs-devices-power
+++ b/Documentation/ABI/testing/sysfs-devices-power
@@ -51,3 +51,29 @@ Description:
51 drivers. Changing this attribute to "on" prevents the driver 51 drivers. Changing this attribute to "on" prevents the driver
52 from power managing the device at run time. Doing that while 52 from power managing the device at run time. Doing that while
53 the device is suspended causes it to be woken up. 53 the device is suspended causes it to be woken up.
54
55What: /sys/devices/.../power/async
56Date: January 2009
57Contact: Rafael J. Wysocki <rjw@sisk.pl>
58Description:
59 The /sys/devices/.../async attribute allows the user space to
60 enable or diasble the device's suspend and resume callbacks to
61 be executed asynchronously (ie. in separate threads, in parallel
62 with the main suspend/resume thread) during system-wide power
63 transitions (eg. suspend to RAM, hibernation).
64
65 All devices have one of the following two values for the
66 power/async file:
67
68 + "enabled\n" to permit the asynchronous suspend/resume;
69 + "disabled\n" to forbid it;
70
71 The value of this attribute may be changed by writing either
72 "enabled", or "disabled" to it.
73
74 It generally is unsafe to permit the asynchronous suspend/resume
75 of a device unless it is certain that all of the PM dependencies
76 of the device are known to the PM core. However, for some
77 devices this attribute is set to "enabled" by bus type code or
78 device drivers and in that cases it should be safe to leave the
79 default value.
diff --git a/drivers/base/power/sysfs.c b/drivers/base/power/sysfs.c
index c011ff15632c..86fd9373447e 100644
--- a/drivers/base/power/sysfs.c
+++ b/drivers/base/power/sysfs.c
@@ -54,6 +54,24 @@
54 * wakeup events internally (unless they are disabled), keeping 54 * wakeup events internally (unless they are disabled), keeping
55 * their hardware in low power modes whenever they're unused. This 55 * their hardware in low power modes whenever they're unused. This
56 * saves runtime power, without requiring system-wide sleep states. 56 * saves runtime power, without requiring system-wide sleep states.
57 *
58 * async - Report/change current async suspend setting for the device
59 *
60 * Asynchronous suspend and resume of the device during system-wide power
61 * state transitions can be enabled by writing "enabled" to this file.
62 * Analogously, if "disabled" is written to this file, the device will be
63 * suspended and resumed synchronously.
64 *
65 * All devices have one of the following two values for power/async:
66 *
67 * + "enabled\n" to permit the asynchronous suspend/resume of the device;
68 * + "disabled\n" to forbid it;
69 *
70 * NOTE: It generally is unsafe to permit the asynchronous suspend/resume
71 * of a device unless it is certain that all of the PM dependencies of the
72 * device are known to the PM core. However, for some devices this
73 * attribute is set to "enabled" by bus type code or device drivers and in
74 * that cases it should be safe to leave the default value.
57 */ 75 */
58 76
59static const char enabled[] = "enabled"; 77static const char enabled[] = "enabled";
@@ -125,12 +143,43 @@ wake_store(struct device * dev, struct device_attribute *attr,
125 143
126static DEVICE_ATTR(wakeup, 0644, wake_show, wake_store); 144static DEVICE_ATTR(wakeup, 0644, wake_show, wake_store);
127 145
146#ifdef CONFIG_PM_SLEEP_ADVANCED_DEBUG
147static ssize_t async_show(struct device *dev, struct device_attribute *attr,
148 char *buf)
149{
150 return sprintf(buf, "%s\n",
151 device_async_suspend_enabled(dev) ? enabled : disabled);
152}
153
154static ssize_t async_store(struct device *dev, struct device_attribute *attr,
155 const char *buf, size_t n)
156{
157 char *cp;
158 int len = n;
159
160 cp = memchr(buf, '\n', n);
161 if (cp)
162 len = cp - buf;
163 if (len == sizeof enabled - 1 && strncmp(buf, enabled, len) == 0)
164 device_enable_async_suspend(dev);
165 else if (len == sizeof disabled - 1 && strncmp(buf, disabled, len) == 0)
166 device_disable_async_suspend(dev);
167 else
168 return -EINVAL;
169 return n;
170}
171
172static DEVICE_ATTR(async, 0644, async_show, async_store);
173#endif /* CONFIG_PM_SLEEP_ADVANCED_DEBUG */
128 174
129static struct attribute * power_attrs[] = { 175static struct attribute * power_attrs[] = {
130#ifdef CONFIG_PM_RUNTIME 176#ifdef CONFIG_PM_RUNTIME
131 &dev_attr_control.attr, 177 &dev_attr_control.attr,
132#endif 178#endif
133 &dev_attr_wakeup.attr, 179 &dev_attr_wakeup.attr,
180#ifdef CONFIG_PM_SLEEP_ADVANCED_DEBUG
181 &dev_attr_async.attr,
182#endif
134 NULL, 183 NULL,
135}; 184};
136static struct attribute_group pm_attr_group = { 185static struct attribute_group pm_attr_group = {
diff --git a/include/linux/device.h b/include/linux/device.h
index 70adc5f3f50a..b30527db3ac0 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -478,6 +478,17 @@ static inline void device_enable_async_suspend(struct device *dev)
478 dev->power.async_suspend = true; 478 dev->power.async_suspend = true;
479} 479}
480 480
481static inline void device_disable_async_suspend(struct device *dev)
482{
483 if (dev->power.status == DPM_ON)
484 dev->power.async_suspend = false;
485}
486
487static inline bool device_async_suspend_enabled(struct device *dev)
488{
489 return !!dev->power.async_suspend;
490}
491
481void driver_init(void); 492void driver_init(void);
482 493
483/* 494/*
diff --git a/kernel/power/Kconfig b/kernel/power/Kconfig
index 4c9cffcf69c7..5c36ea9d55d2 100644
--- a/kernel/power/Kconfig
+++ b/kernel/power/Kconfig
@@ -27,6 +27,15 @@ config PM_DEBUG
27 code. This is helpful when debugging and reporting PM bugs, like 27 code. This is helpful when debugging and reporting PM bugs, like
28 suspend support. 28 suspend support.
29 29
30config PM_ADVANCED_DEBUG
31 bool "Extra PM attributes in sysfs for low-level debugging/testing"
32 depends on PM_DEBUG
33 default n
34 ---help---
35 Add extra sysfs attributes allowing one to access some Power Management
36 fields of device objects from user space. If you are not a kernel
37 developer interested in debugging/testing Power Management, say "no".
38
30config PM_VERBOSE 39config PM_VERBOSE
31 bool "Verbose Power Management debugging" 40 bool "Verbose Power Management debugging"
32 depends on PM_DEBUG 41 depends on PM_DEBUG
@@ -85,6 +94,11 @@ config PM_SLEEP
85 depends on SUSPEND || HIBERNATION || XEN_SAVE_RESTORE 94 depends on SUSPEND || HIBERNATION || XEN_SAVE_RESTORE
86 default y 95 default y
87 96
97config PM_SLEEP_ADVANCED_DEBUG
98 bool
99 depends on PM_ADVANCED_DEBUG
100 default n
101
88config SUSPEND 102config SUSPEND
89 bool "Suspend to RAM and standby" 103 bool "Suspend to RAM and standby"
90 depends on PM && ARCH_SUSPEND_POSSIBLE 104 depends on PM && ARCH_SUSPEND_POSSIBLE