Commit 5a2eb858 authored by Rafael J. Wysocki's avatar Rafael J. Wysocki

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: default avatarRafael J. Wysocki <rjw@sisk.pl>
parent 0e06b4a8
...@@ -51,3 +51,29 @@ Description: ...@@ -51,3 +51,29 @@ Description:
drivers. Changing this attribute to "on" prevents the driver drivers. Changing this attribute to "on" prevents the driver
from power managing the device at run time. Doing that while from power managing the device at run time. Doing that while
the device is suspended causes it to be woken up. the device is suspended causes it to be woken up.
What: /sys/devices/.../power/async
Date: January 2009
Contact: Rafael J. Wysocki <rjw@sisk.pl>
Description:
The /sys/devices/.../async attribute allows the user space to
enable or diasble the device's suspend and resume callbacks to
be executed asynchronously (ie. in separate threads, in parallel
with the main suspend/resume thread) during system-wide power
transitions (eg. suspend to RAM, hibernation).
All devices have one of the following two values for the
power/async file:
+ "enabled\n" to permit the asynchronous suspend/resume;
+ "disabled\n" to forbid it;
The value of this attribute may be changed by writing either
"enabled", or "disabled" to it.
It generally is unsafe to permit the asynchronous suspend/resume
of a device unless it is certain that all of the PM dependencies
of the device are known to the PM core. However, for some
devices this attribute is set to "enabled" by bus type code or
device drivers and in that cases it should be safe to leave the
default value.
...@@ -54,6 +54,24 @@ ...@@ -54,6 +54,24 @@
* wakeup events internally (unless they are disabled), keeping * wakeup events internally (unless they are disabled), keeping
* their hardware in low power modes whenever they're unused. This * their hardware in low power modes whenever they're unused. This
* saves runtime power, without requiring system-wide sleep states. * saves runtime power, without requiring system-wide sleep states.
*
* async - Report/change current async suspend setting for the device
*
* Asynchronous suspend and resume of the device during system-wide power
* state transitions can be enabled by writing "enabled" to this file.
* Analogously, if "disabled" is written to this file, the device will be
* suspended and resumed synchronously.
*
* All devices have one of the following two values for power/async:
*
* + "enabled\n" to permit the asynchronous suspend/resume of the device;
* + "disabled\n" to forbid it;
*
* NOTE: It generally is unsafe to permit the asynchronous suspend/resume
* of a device unless it is certain that all of the PM dependencies of the
* device are known to the PM core. However, for some devices this
* attribute is set to "enabled" by bus type code or device drivers and in
* that cases it should be safe to leave the default value.
*/ */
static const char enabled[] = "enabled"; static const char enabled[] = "enabled";
...@@ -125,12 +143,43 @@ wake_store(struct device * dev, struct device_attribute *attr, ...@@ -125,12 +143,43 @@ wake_store(struct device * dev, struct device_attribute *attr,
static DEVICE_ATTR(wakeup, 0644, wake_show, wake_store); static DEVICE_ATTR(wakeup, 0644, wake_show, wake_store);
#ifdef CONFIG_PM_SLEEP_ADVANCED_DEBUG
static ssize_t async_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
return sprintf(buf, "%s\n",
device_async_suspend_enabled(dev) ? enabled : disabled);
}
static ssize_t async_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t n)
{
char *cp;
int len = n;
cp = memchr(buf, '\n', n);
if (cp)
len = cp - buf;
if (len == sizeof enabled - 1 && strncmp(buf, enabled, len) == 0)
device_enable_async_suspend(dev);
else if (len == sizeof disabled - 1 && strncmp(buf, disabled, len) == 0)
device_disable_async_suspend(dev);
else
return -EINVAL;
return n;
}
static DEVICE_ATTR(async, 0644, async_show, async_store);
#endif /* CONFIG_PM_SLEEP_ADVANCED_DEBUG */
static struct attribute * power_attrs[] = { static struct attribute * power_attrs[] = {
#ifdef CONFIG_PM_RUNTIME #ifdef CONFIG_PM_RUNTIME
&dev_attr_control.attr, &dev_attr_control.attr,
#endif #endif
&dev_attr_wakeup.attr, &dev_attr_wakeup.attr,
#ifdef CONFIG_PM_SLEEP_ADVANCED_DEBUG
&dev_attr_async.attr,
#endif
NULL, NULL,
}; };
static struct attribute_group pm_attr_group = { static struct attribute_group pm_attr_group = {
......
...@@ -478,6 +478,17 @@ static inline void device_enable_async_suspend(struct device *dev) ...@@ -478,6 +478,17 @@ static inline void device_enable_async_suspend(struct device *dev)
dev->power.async_suspend = true; dev->power.async_suspend = true;
} }
static inline void device_disable_async_suspend(struct device *dev)
{
if (dev->power.status == DPM_ON)
dev->power.async_suspend = false;
}
static inline bool device_async_suspend_enabled(struct device *dev)
{
return !!dev->power.async_suspend;
}
void driver_init(void); void driver_init(void);
/* /*
......
...@@ -27,6 +27,15 @@ config PM_DEBUG ...@@ -27,6 +27,15 @@ config PM_DEBUG
code. This is helpful when debugging and reporting PM bugs, like code. This is helpful when debugging and reporting PM bugs, like
suspend support. suspend support.
config PM_ADVANCED_DEBUG
bool "Extra PM attributes in sysfs for low-level debugging/testing"
depends on PM_DEBUG
default n
---help---
Add extra sysfs attributes allowing one to access some Power Management
fields of device objects from user space. If you are not a kernel
developer interested in debugging/testing Power Management, say "no".
config PM_VERBOSE config PM_VERBOSE
bool "Verbose Power Management debugging" bool "Verbose Power Management debugging"
depends on PM_DEBUG depends on PM_DEBUG
...@@ -85,6 +94,11 @@ config PM_SLEEP ...@@ -85,6 +94,11 @@ config PM_SLEEP
depends on SUSPEND || HIBERNATION || XEN_SAVE_RESTORE depends on SUSPEND || HIBERNATION || XEN_SAVE_RESTORE
default y default y
config PM_SLEEP_ADVANCED_DEBUG
bool
depends on PM_ADVANCED_DEBUG
default n
config SUSPEND config SUSPEND
bool "Suspend to RAM and standby" bool "Suspend to RAM and standby"
depends on PM && ARCH_SUSPEND_POSSIBLE depends on PM && ARCH_SUSPEND_POSSIBLE
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment