
From: Todd Poynor <tpoynor@mvista.com>

(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 (refusing to suspend it again).

(2) Move devices from the active list to the off list only when
    suspending all devices as part of a system suspend, not for runtime
    suspend.  This matches the resume code, which only moves devices from
    off to active during system resume, such that runtime resume currently
    doesn't move the suspended device back to the active list.  (This also
    avoids reordering the device list for runtime suspends; the list is in
    order of registration and suspend/resume works best that way --
    granted, more sweeping improvements in how device dependencies are
    accounted for in the suspend/resume order are also needed someday.)

Runtime device suspend/resume is in some cases used frequently on
battery-powered embedded devices, to save additional power and to handle
device power state interactions with overall system power state on certain
platforms.

Signed-off-by:  Andrew Morton <akpm@osdl.org>
---

 25-akpm/drivers/base/power/runtime.c |    5 ++++-
 25-akpm/drivers/base/power/suspend.c |   23 ++++++++++-------------
 2 files changed, 14 insertions(+), 14 deletions(-)

diff -puN drivers/base/power/runtime.c~device-runtime-suspend-resume-fixes drivers/base/power/runtime.c
--- 25/drivers/base/power/runtime.c~device-runtime-suspend-resume-fixes	Wed May 26 15:56:59 2004
+++ 25-akpm/drivers/base/power/runtime.c	Wed May 26 15:56:59 2004
@@ -14,7 +14,10 @@ static void runtime_resume(struct device
 {
 	if (!dev->power.power_state)
 		return;
-	resume_device(dev);
+	if (! resume_device(dev))
+		dev->power.power_state = 0;
+
+	return;
 }
 
 
diff -puN drivers/base/power/suspend.c~device-runtime-suspend-resume-fixes drivers/base/power/suspend.c
--- 25/drivers/base/power/suspend.c~device-runtime-suspend-resume-fixes	Wed May 26 15:56:59 2004
+++ 25-akpm/drivers/base/power/suspend.c	Wed May 26 15:56:59 2004
@@ -42,13 +42,6 @@ int suspend_device(struct device * dev, 
 	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 @@ int device_suspend(u32 state)
 	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);
_
