Re: [patch] suspend/resume debugging: device filter

From: Ingo Molnar
Date: Sat May 05 2007 - 05:24:56 EST



* Greg KH <gregkh@xxxxxxx> wrote:

> Here's a (compile tested only) patch that does this on a per-device
> basis, which is smaller, and should work just as well as your patch.
>
> It creates a new file in the power/ directory for every device called
> "can_suspend". Write a '0' to it to prevent that device from being
> suspended.
>
> Does this work for you?

yeah, i was able to use this too to debug suspend/resume problems. But
i've added the check to the resume path too - for example sw-suspend
does a resume of devices during its suspend cycle, cutting off much of
the netconsole output.

which makes the can_suspend flag mis-named - perhaps rename it to
exclude_pm ?

updated patch below, against v2.6.21. Could we get this into v2.6.22
please? It's a real time-saver.

Ingo

---
drivers/base/power/resume.c | 6 ++++++
drivers/base/power/suspend.c | 2 +-
drivers/base/power/sysfs.c | 30 ++++++++++++++++++++++++++++++
include/linux/device.h | 1 +
4 files changed, 38 insertions(+), 1 deletion(-)

Index: linux/drivers/base/power/resume.c
===================================================================
--- linux.orig/drivers/base/power/resume.c
+++ linux/drivers/base/power/resume.c
@@ -24,6 +24,9 @@ int resume_device(struct device * dev)
{
int error = 0;

+ if (dev->no_suspend)
+ return 0;
+
TRACE_DEVICE(dev);
TRACE_RESUME(0);
down(&dev->sem);
@@ -52,6 +55,9 @@ static int resume_device_early(struct de
{
int error = 0;

+ if (dev->no_suspend)
+ return 0;
+
TRACE_DEVICE(dev);
TRACE_RESUME(0);
if (dev->bus && dev->bus->resume_early) {
Index: linux/drivers/base/power/suspend.c
===================================================================
--- linux.orig/drivers/base/power/suspend.c
+++ linux/drivers/base/power/suspend.c
@@ -78,7 +78,7 @@ int suspend_device(struct device * dev,
suspend_report_result(dev->class->suspend, error);
}

- if (!error && dev->bus && dev->bus->suspend && !dev->power.power_state.event) {
+ if (!error && !dev->no_suspend && dev->bus && dev->bus->suspend && !dev->power.power_state.event) {
dev_dbg(dev, "%s%s\n",
suspend_verb(state.event),
((state.event == PM_EVENT_SUSPEND)
Index: linux/drivers/base/power/sysfs.c
===================================================================
--- linux.orig/drivers/base/power/sysfs.c
+++ linux/drivers/base/power/sysfs.c
@@ -141,12 +141,42 @@ wake_store(struct device * dev, struct d

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

+static ssize_t can_suspend_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "%s\n", dev->no_suspend ? "no" : "yes");
+}
+
+static ssize_t can_suspend_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t n)
+{
+ if (!n)
+ return -EINVAL;
+
+ switch (buf[0]) {
+ case 'y':
+ case 'Y':
+ case '1':
+ dev->no_suspend = 0;
+ break;
+ case 'n':
+ case 'N':
+ case '0':
+ dev->no_suspend = 1;
+ break;
+ }
+
+ return n;
+}
+static DEVICE_ATTR(can_suspend, 0644, can_suspend_show, can_suspend_store);

static struct attribute * power_attrs[] = {
#ifdef CONFIG_PM_SYSFS_DEPRECATED
&dev_attr_state.attr,
#endif
&dev_attr_wakeup.attr,
+ &dev_attr_can_suspend.attr,
NULL,
};
static struct attribute_group pm_attr_group = {
Index: linux/include/linux/device.h
===================================================================
--- linux.orig/include/linux/device.h
+++ linux/include/linux/device.h
@@ -402,6 +402,7 @@ struct device {
char bus_id[BUS_ID_SIZE]; /* position on parent bus */
struct device_type *type;
unsigned is_registered:1;
+ unsigned no_suspend:1;
struct device_attribute uevent_attr;
struct device_attribute *devt_attr;

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/