Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+26 −0
Original line number Diff line number Diff line
@@ -51,3 +51,29 @@ Description:
		drivers.  Changing this attribute to "on" prevents the driver
		from power managing the device at run time.  Doing that while
		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.
+49 −0
Original line number Diff line number Diff line
@@ -54,6 +54,24 @@
 *	wakeup events internally (unless they are disabled), keeping
 *	their hardware in low power modes whenever they're unused.  This
 *	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";
@@ -125,12 +143,43 @@ wake_store(struct device * dev, struct device_attribute *attr,

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[] = {
#ifdef CONFIG_PM_RUNTIME
	&dev_attr_control.attr,
#endif
	&dev_attr_wakeup.attr,
#ifdef CONFIG_PM_SLEEP_ADVANCED_DEBUG
	&dev_attr_async.attr,
#endif
	NULL,
};
static struct attribute_group pm_attr_group = {
+11 −0
Original line number Diff line number Diff line
@@ -478,6 +478,17 @@ static inline void device_enable_async_suspend(struct device *dev)
		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);

/*
+14 −0
Original line number Diff line number Diff line
@@ -27,6 +27,15 @@ config PM_DEBUG
	code. This is helpful when debugging and reporting PM bugs, like
	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
	bool "Verbose Power Management debugging"
	depends on PM_DEBUG
@@ -85,6 +94,11 @@ config PM_SLEEP
	depends on SUSPEND || HIBERNATION || XEN_SAVE_RESTORE
	default y

config PM_SLEEP_ADVANCED_DEBUG
	bool
	depends on PM_ADVANCED_DEBUG
	default n

config SUSPEND
	bool "Suspend to RAM and standby"
	depends on PM && ARCH_SUSPEND_POSSIBLE