2004-04-02 22:29:08

by Todd Poynor

[permalink] [raw]
Subject: [PATCH] Device suspend/resume fixes

In case some changes to device handling during suspend/resume are
welcome:

(1) Set device power state at runtime resume (as is done for runtime
suspend) so that a later suspend does not think the device is still
suspended.

(2) Move devices from active to off list only when suspending all
devices, not for runtime suspend, to match resume handling, and to
avoid reordering the device list (which is in order of registration
and suspend/resume works best that way).

(3) Flush signals between resume handlers in case a resume function
causes, for example, an ECHILD from modprobe or hotplug, so
interruptible APIs for the next handler aren't affected.


--- linux-2.6.4-orig/drivers/base/power/suspend.c 2004-03-11 14:57:55.000000000 -0800
+++ linux-2.6.4-pm/drivers/base/power/suspend.c 2004-04-02 14:07:31.188415120 -0800
@@ -42,13 +42,6 @@
if (dev->bus && dev->bus->suspend)
error = dev->bus->suspend(dev,state);

- if (!error) {
- list_del(&dev->power.entry);
- list_add(&dev->power.entry,&dpm_off);
- } else if (error == -EAGAIN) {
- list_del(&dev->power.entry);
- list_add(&dev->power.entry,&dpm_off_irq);
- }
return error;
}

@@ -81,12 +74,16 @@
while(!list_empty(&dpm_active)) {
struct list_head * entry = dpm_active.prev;
struct device * dev = to_device(entry);
- if ((error = suspend_device(dev,state))) {
- if (error != -EAGAIN)
- goto Error;
- else
- error = 0;
- }
+ error = suspend_device(dev,state);
+
+ if (!error) {
+ list_del(&dev->power.entry);
+ list_add(&dev->power.entry,&dpm_off);
+ } else if (error == -EAGAIN) {
+ list_del(&dev->power.entry);
+ list_add(&dev->power.entry,&dpm_off_irq);
+ } else
+ goto Error;
}
Done:
up(&dpm_sem);
--- linux-2.6.4-orig/drivers/base/power/resume.c 2004-03-11 14:57:55.000000000 -0800
+++ linux-2.6.4-pm/drivers/base/power/resume.c 2004-04-02 14:07:29.425683096 -0800
@@ -37,6 +37,7 @@
list_del_init(entry);
resume_device(dev);
list_add_tail(entry,&dpm_active);
+ flush_signals(current);
}
}

--- linux-2.6.4-orig/drivers/base/power/runtime.c 2004-03-11 15:02:22.000000000 -0800
+++ linux-2.6.4-pm/drivers/base/power/runtime.c 2004-04-02 14:23:31.400440704 -0800
@@ -12,9 +12,14 @@

static void runtime_resume(struct device * dev)
{
+ int error;
+
if (!dev->power.power_state)
return;
- resume_device(dev);
+ if (!(error = resume_device(dev)))
+ dev->power.power_state = 0;
+
+ return error;
}


--
Todd Poynor
MontaVista Software


2004-04-02 22:58:49

by Patrick Mochel

[permalink] [raw]
Subject: Re: [PATCH] Device suspend/resume fixes


> (3) Flush signals between resume handlers in case a resume function
> causes, for example, an ECHILD from modprobe or hotplug, so
> interruptible APIs for the next handler aren't affected.

Are there really cases in which you see this as an issue?


Pat

2004-04-02 23:14:15

by Todd Poynor

[permalink] [raw]
Subject: Re: [PATCH] Device suspend/resume fixes

Patrick Mochel wrote:
>>(3) Flush signals between resume handlers in case a resume function
>>causes, for example, an ECHILD from modprobe or hotplug, so
>>interruptible APIs for the next handler aren't affected.
>
>
> Are there really cases in which you see this as an issue?

Ugh, I meant SIGCHILD, not ECHILD. We have seen this in the past on a
2.4 backport, although perhaps in a different environment than is
normally used (this was on a PowerPC embedded platform that powers off
the I/O ring during suspend). For certain hotpluggable devices such as
USB we've found it best to completely de-init and re-init the controller
and re-sense plugged cards at suspend/resume time, which is when we saw
troublesome signals (I2C setup then "timed out" before the controller
was ready because a SIGCHILD was waiting). I admit I don't know that
much about the hotplug handlers, maybe I just didn't have things setup
properly. So if this seems bizarre then I'll withdraw it and try things
again later when I have such hardware running in 2.6. Thanks,

--
Todd Poynor
MontaVista Software