PM: Avoid compiler warning in pm_noirq_op()
[pandora-kernel.git] / drivers / base / power / main.c
index 31b5266..e6d6280 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/interrupt.h>
 #include <linux/sched.h>
 #include <linux/async.h>
+#include <linux/suspend.h>
 
 #include "../base.h"
 #include "power.h"
@@ -303,7 +304,7 @@ static int pm_noirq_op(struct device *dev,
                        pm_message_t state)
 {
        int error = 0;
-       ktime_t calltime, delta, rettime;
+       ktime_t calltime = ktime_set(0, 0), delta, rettime;
 
        if (initcall_debug) {
                pr_info("calling  %s+ @ %i, parent: %s\n",
@@ -475,20 +476,33 @@ End:
  */
 void dpm_resume_noirq(pm_message_t state)
 {
-       struct device *dev;
+       struct list_head list;
        ktime_t starttime = ktime_get();
 
+       INIT_LIST_HEAD(&list);
        mutex_lock(&dpm_list_mtx);
        transition_started = false;
-       list_for_each_entry(dev, &dpm_list, power.entry)
+       while (!list_empty(&dpm_list)) {
+               struct device *dev = to_device(dpm_list.next);
+
+               get_device(dev);
                if (dev->power.status > DPM_OFF) {
                        int error;
 
                        dev->power.status = DPM_OFF;
+                       mutex_unlock(&dpm_list_mtx);
+
                        error = device_resume_noirq(dev, state);
+
+                       mutex_lock(&dpm_list_mtx);
                        if (error)
                                pm_dev_err(dev, state, " early", error);
                }
+               if (!list_empty(&dev->power.entry))
+                       list_move_tail(&dev->power.entry, &list);
+               put_device(dev);
+       }
+       list_splice(&list, &dpm_list);
        mutex_unlock(&dpm_list_mtx);
        dpm_show_time(starttime, state, "early");
        resume_device_irqs();
@@ -789,20 +803,33 @@ End:
  */
 int dpm_suspend_noirq(pm_message_t state)
 {
-       struct device *dev;
+       struct list_head list;
        ktime_t starttime = ktime_get();
        int error = 0;
 
+       INIT_LIST_HEAD(&list);
        suspend_device_irqs();
        mutex_lock(&dpm_list_mtx);
-       list_for_each_entry_reverse(dev, &dpm_list, power.entry) {
+       while (!list_empty(&dpm_list)) {
+               struct device *dev = to_device(dpm_list.prev);
+
+               get_device(dev);
+               mutex_unlock(&dpm_list_mtx);
+
                error = device_suspend_noirq(dev, state);
+
+               mutex_lock(&dpm_list_mtx);
                if (error) {
                        pm_dev_err(dev, state, " late", error);
+                       put_device(dev);
                        break;
                }
                dev->power.status = DPM_OFF_IRQ;
+               if (!list_empty(&dev->power.entry))
+                       list_move(&dev->power.entry, &list);
+               put_device(dev);
        }
+       list_splice_tail(&list, &dpm_list);
        mutex_unlock(&dpm_list_mtx);
        if (error)
                dpm_resume_noirq(resume_event(state));
@@ -850,6 +877,11 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async)
        if (async_error)
                goto End;
 
+       if (pm_wakeup_pending()) {
+               async_error = -EBUSY;
+               goto End;
+       }
+
        if (dev->class) {
                if (dev->class->pm) {
                        pm_dev_dbg(dev, state, "class ");
@@ -1026,8 +1058,10 @@ static int dpm_prepare(pm_message_t state)
                mutex_unlock(&dpm_list_mtx);
 
                pm_runtime_get_noresume(dev);
-               if (pm_runtime_barrier(dev) && device_may_wakeup(dev)) {
-                       /* Wake-up requested during system sleep transition. */
+               if (pm_runtime_barrier(dev) && device_may_wakeup(dev))
+                       pm_wakeup_event(dev, 0);
+
+               if (pm_wakeup_pending()) {
                        pm_runtime_put_sync(dev);
                        error = -EBUSY;
                } else {
@@ -1042,8 +1076,8 @@ static int dpm_prepare(pm_message_t state)
                                error = 0;
                                continue;
                        }
-                       printk(KERN_ERR "PM: Failed to prepare device %s "
-                               "for power transition: error %d\n",
+                       printk(KERN_INFO "PM: Device %s not prepared "
+                               "for power transition: code %d\n",
                                kobject_name(&dev->kobj), error);
                        put_device(dev);
                        break;