PM / Sleep: Add user space interface for manipulating wakeup sources, v3
[linux-2.6.git] / drivers / base / power / runtime.c
index c56efd7..5989487 100644 (file)
@@ -403,6 +403,12 @@ static int rpm_suspend(struct device *dev, int rpmflags)
                goto out;
        }
 
+       if (__dev_pm_qos_read_value(dev) < 0) {
+               /* Negative PM QoS constraint means "never suspend". */
+               retval = -EPERM;
+               goto out;
+       }
+
        __update_runtime_status(dev, RPM_SUSPENDING);
 
        if (dev->pm_domain)
@@ -420,27 +426,9 @@ static int rpm_suspend(struct device *dev, int rpmflags)
                callback = dev->driver->pm->runtime_suspend;
 
        retval = rpm_callback(callback, dev);
-       if (retval) {
-               __update_runtime_status(dev, RPM_ACTIVE);
-               dev->power.deferred_resume = false;
-               if (retval == -EAGAIN || retval == -EBUSY) {
-                       dev->power.runtime_error = 0;
+       if (retval)
+               goto fail;
 
-                       /*
-                        * If the callback routine failed an autosuspend, and
-                        * if the last_busy time has been updated so that there
-                        * is a new autosuspend expiration time, automatically
-                        * reschedule another autosuspend.
-                        */
-                       if ((rpmflags & RPM_AUTO) &&
-                           pm_runtime_autosuspend_expiration(dev) != 0)
-                               goto repeat;
-               } else {
-                       pm_runtime_cancel_pending(dev);
-               }
-               wake_up_all(&dev->power.wait_queue);
-               goto out;
-       }
  no_callback:
        __update_runtime_status(dev, RPM_SUSPENDED);
        pm_runtime_deactivate_timer(dev);
@@ -472,6 +460,28 @@ static int rpm_suspend(struct device *dev, int rpmflags)
        trace_rpm_return_int(dev, _THIS_IP_, retval);
 
        return retval;
+
+ fail:
+       __update_runtime_status(dev, RPM_ACTIVE);
+       dev->power.deferred_resume = false;
+       wake_up_all(&dev->power.wait_queue);
+
+       if (retval == -EAGAIN || retval == -EBUSY) {
+               dev->power.runtime_error = 0;
+
+               /*
+                * If the callback routine failed an autosuspend, and
+                * if the last_busy time has been updated so that there
+                * is a new autosuspend expiration time, automatically
+                * reschedule another autosuspend.
+                */
+               if ((rpmflags & RPM_AUTO) &&
+                   pm_runtime_autosuspend_expiration(dev) != 0)
+                       goto repeat;
+       } else {
+               pm_runtime_cancel_pending(dev);
+       }
+       goto out;
 }
 
 /**