Skip to content

Commit 5a2eb85

Browse files
committed
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>
1 parent 0e06b4a commit 5a2eb85

File tree

4 files changed

+100
-0
lines changed

4 files changed

+100
-0
lines changed

Documentation/ABI/testing/sysfs-devices-power

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,3 +51,29 @@ Description:
5151
drivers. Changing this attribute to "on" prevents the driver
5252
from power managing the device at run time. Doing that while
5353
the device is suspended causes it to be woken up.
54+
55+
What: /sys/devices/.../power/async
56+
Date: January 2009
57+
Contact: Rafael J. Wysocki <rjw@sisk.pl>
58+
Description:
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.

drivers/base/power/sysfs.c

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,24 @@
5454
* wakeup events internally (unless they are disabled), keeping
5555
* their hardware in low power modes whenever they're unused. This
5656
* 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.
5775
*/
5876

5977
static const char enabled[] = "enabled";
@@ -125,12 +143,43 @@ wake_store(struct device * dev, struct device_attribute *attr,
125143

126144
static DEVICE_ATTR(wakeup, 0644, wake_show, wake_store);
127145

146+
#ifdef CONFIG_PM_SLEEP_ADVANCED_DEBUG
147+
static 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+
154+
static 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+
172+
static DEVICE_ATTR(async, 0644, async_show, async_store);
173+
#endif /* CONFIG_PM_SLEEP_ADVANCED_DEBUG */
128174

129175
static struct attribute * power_attrs[] = {
130176
#ifdef CONFIG_PM_RUNTIME
131177
&dev_attr_control.attr,
132178
#endif
133179
&dev_attr_wakeup.attr,
180+
#ifdef CONFIG_PM_SLEEP_ADVANCED_DEBUG
181+
&dev_attr_async.attr,
182+
#endif
134183
NULL,
135184
};
136185
static struct attribute_group pm_attr_group = {

include/linux/device.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -478,6 +478,17 @@ static inline void device_enable_async_suspend(struct device *dev)
478478
dev->power.async_suspend = true;
479479
}
480480

481+
static 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+
487+
static inline bool device_async_suspend_enabled(struct device *dev)
488+
{
489+
return !!dev->power.async_suspend;
490+
}
491+
481492
void driver_init(void);
482493

483494
/*

kernel/power/Kconfig

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,15 @@ config PM_DEBUG
2727
code. This is helpful when debugging and reporting PM bugs, like
2828
suspend support.
2929

30+
config 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+
3039
config PM_VERBOSE
3140
bool "Verbose Power Management debugging"
3241
depends on PM_DEBUG
@@ -85,6 +94,11 @@ config PM_SLEEP
8594
depends on SUSPEND || HIBERNATION || XEN_SAVE_RESTORE
8695
default y
8796

97+
config PM_SLEEP_ADVANCED_DEBUG
98+
bool
99+
depends on PM_ADVANCED_DEBUG
100+
default n
101+
88102
config SUSPEND
89103
bool "Suspend to RAM and standby"
90104
depends on PM && ARCH_SUSPEND_POSSIBLE

0 commit comments

Comments
 (0)