PM / Sleep: Add user space interface for manipulating wakeup sources, v3
[linux-2.6.git] / drivers / base / power / runtime.c
index ee99025..5989487 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * drivers/base/power/runtime.c - Helper functions for device run-time PM
+ * drivers/base/power/runtime.c - Helper functions for device runtime PM
  *
  * Copyright (c) 2009 Rafael J. Wysocki <rjw@sisk.pl>, Novell Inc.
  * Copyright (C) 2010 Alan Stern <stern@rowland.harvard.edu>
@@ -8,7 +8,9 @@
  */
 
 #include <linux/sched.h>
+#include <linux/export.h>
 #include <linux/pm_runtime.h>
+#include <trace/events/rpm.h>
 #include "power.h"
 
 static int rpm_resume(struct device *dev, int rpmflags);
@@ -28,13 +30,10 @@ static int rpm_suspend(struct device *dev, int rpmflags);
 void update_pm_runtime_accounting(struct device *dev)
 {
        unsigned long now = jiffies;
-       int delta;
+       unsigned long delta;
 
        delta = now - dev->power.accounting_timestamp;
 
-       if (delta < 0)
-               delta = 0;
-
        dev->power.accounting_timestamp = now;
 
        if (dev->power.disable_depth > 0)
@@ -155,11 +154,36 @@ static int rpm_check_suspend_allowed(struct device *dev)
 }
 
 /**
+ * __rpm_callback - Run a given runtime PM callback for a given device.
+ * @cb: Runtime PM callback to run.
+ * @dev: Device to run the callback for.
+ */
+static int __rpm_callback(int (*cb)(struct device *), struct device *dev)
+       __releases(&dev->power.lock) __acquires(&dev->power.lock)
+{
+       int retval;
+
+       if (dev->power.irq_safe)
+               spin_unlock(&dev->power.lock);
+       else
+               spin_unlock_irq(&dev->power.lock);
+
+       retval = cb(dev);
+
+       if (dev->power.irq_safe)
+               spin_lock(&dev->power.lock);
+       else
+               spin_lock_irq(&dev->power.lock);
+
+       return retval;
+}
+
+/**
  * rpm_idle - Notify device bus type if the device can be suspended.
  * @dev: Device to notify the bus type about.
  * @rpmflags: Flag bits.
  *
- * Check if the device's run-time PM status allows it to be suspended.  If
+ * Check if the device's runtime PM status allows it to be suspended.  If
  * another idle notification has been started earlier, return immediately.  If
  * the RPM_ASYNC flag is set then queue an idle-notification request; otherwise
  * run the ->runtime_idle() callback directly.
@@ -171,6 +195,7 @@ static int rpm_idle(struct device *dev, int rpmflags)
        int (*callback)(struct device *);
        int retval;
 
+       trace_rpm_idle(dev, rpmflags);
        retval = rpm_check_suspend_allowed(dev);
        if (retval < 0)
                ;       /* Conditions are wrong. */
@@ -225,18 +250,17 @@ static int rpm_idle(struct device *dev, int rpmflags)
        else
                callback = NULL;
 
-       if (callback) {
-               spin_unlock_irq(&dev->power.lock);
+       if (!callback && dev->driver && dev->driver->pm)
+               callback = dev->driver->pm->runtime_idle;
 
-               callback(dev);
-
-               spin_lock_irq(&dev->power.lock);
-       }
+       if (callback)
+               __rpm_callback(callback, dev);
 
        dev->power.idle_notification = false;
        wake_up_all(&dev->power.wait_queue);
 
  out:
+       trace_rpm_return_int(dev, _THIS_IP_, retval);
        return retval;
 }
 
@@ -246,39 +270,36 @@ static int rpm_idle(struct device *dev, int rpmflags)
  * @dev: Device to run the callback for.
  */
 static int rpm_callback(int (*cb)(struct device *), struct device *dev)
-       __releases(&dev->power.lock) __acquires(&dev->power.lock)
 {
        int retval;
 
        if (!cb)
                return -ENOSYS;
 
-       if (dev->power.irq_safe) {
-               retval = cb(dev);
-       } else {
-               spin_unlock_irq(&dev->power.lock);
+       retval = __rpm_callback(cb, dev);
 
-               retval = cb(dev);
-
-               spin_lock_irq(&dev->power.lock);
-       }
        dev->power.runtime_error = retval;
        return retval != -EACCES ? retval : -EIO;
 }
 
 /**
- * rpm_suspend - Carry out run-time suspend of given device.
+ * rpm_suspend - Carry out runtime suspend of given device.
  * @dev: Device to suspend.
  * @rpmflags: Flag bits.
  *
- * Check if the device's run-time PM status allows it to be suspended.  If
- * another suspend has been started earlier, either return immediately or wait
- * for it to finish, depending on the RPM_NOWAIT and RPM_ASYNC flags.  Cancel a
- * pending idle notification.  If the RPM_ASYNC flag is set then queue a
- * suspend request; otherwise run the ->runtime_suspend() callback directly.
- * If a deferred resume was requested while the callback was running then carry
- * it out; otherwise send an idle notification for the device (if the suspend
- * failed) or for its parent (if the suspend succeeded).
+ * Check if the device's runtime PM status allows it to be suspended.
+ * Cancel a pending idle notification, autosuspend or suspend. If
+ * another suspend has been started earlier, either return immediately
+ * or wait for it to finish, depending on the RPM_NOWAIT and RPM_ASYNC
+ * flags. If the RPM_ASYNC flag is set then queue a suspend request;
+ * otherwise run the ->runtime_suspend() callback directly. When
+ * ->runtime_suspend succeeded, if a deferred resume was requested while
+ * the callback was running then carry it out, otherwise send an idle
+ * notification for its parent (if the suspend succeeded and both
+ * ignore_children of parent->power and irq_safe of dev->power are not set).
+ * If ->runtime_suspend failed with -EAGAIN or -EBUSY, and if the RPM_AUTO
+ * flag is set and the next autosuspend-delay expiration time is in the
+ * future, schedule another autosuspend attempt.
  *
  * This function must be called under dev->power.lock with interrupts disabled.
  */
@@ -289,7 +310,7 @@ static int rpm_suspend(struct device *dev, int rpmflags)
        struct device *parent = NULL;
        int retval;
 
-       dev_dbg(dev, "%s flags 0x%x\n", __func__, rpmflags);
+       trace_rpm_suspend(dev, rpmflags);
 
  repeat:
        retval = rpm_check_suspend_allowed(dev);
@@ -341,6 +362,15 @@ static int rpm_suspend(struct device *dev, int rpmflags)
                        goto out;
                }
 
+               if (dev->power.irq_safe) {
+                       spin_unlock(&dev->power.lock);
+
+                       cpu_relax();
+
+                       spin_lock(&dev->power.lock);
+                       goto repeat;
+               }
+
                /* Wait for the other suspend running in parallel with us. */
                for (;;) {
                        prepare_to_wait(&dev->power.wait_queue, &wait,
@@ -373,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)
@@ -386,23 +422,20 @@ static int rpm_suspend(struct device *dev, int rpmflags)
        else
                callback = NULL;
 
+       if (!callback && dev->driver && dev->driver->pm)
+               callback = dev->driver->pm->runtime_suspend;
+
        retval = rpm_callback(callback, dev);
-       if (retval) {
-               __update_runtime_status(dev, RPM_ACTIVE);
-               dev->power.deferred_resume = 0;
-               if (retval == -EAGAIN || retval == -EBUSY)
-                       dev->power.runtime_error = 0;
-               else
-                       pm_runtime_cancel_pending(dev);
-       } else {
+       if (retval)
+               goto fail;
+
  no_callback:
-               __update_runtime_status(dev, RPM_SUSPENDED);
-               pm_runtime_deactivate_timer(dev);
+       __update_runtime_status(dev, RPM_SUSPENDED);
+       pm_runtime_deactivate_timer(dev);
 
-               if (dev->parent) {
-                       parent = dev->parent;
-                       atomic_add_unless(&parent->power.child_count, -1, 0);
-               }
+       if (dev->parent) {
+               parent = dev->parent;
+               atomic_add_unless(&parent->power.child_count, -1, 0);
        }
        wake_up_all(&dev->power.wait_queue);
 
@@ -424,17 +457,39 @@ static int rpm_suspend(struct device *dev, int rpmflags)
        }
 
  out:
-       dev_dbg(dev, "%s returns %d\n", __func__, retval);
+       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;
 }
 
 /**
- * rpm_resume - Carry out run-time resume of given device.
+ * rpm_resume - Carry out runtime resume of given device.
  * @dev: Device to resume.
  * @rpmflags: Flag bits.
  *
- * Check if the device's run-time PM status allows it to be resumed.  Cancel
+ * Check if the device's runtime PM status allows it to be resumed.  Cancel
  * any scheduled or pending requests.  If another resume has been started
  * earlier, either return immediately or wait for it to finish, depending on the
  * RPM_NOWAIT and RPM_ASYNC flags.  Similarly, if there's a suspend running in
@@ -453,7 +508,7 @@ static int rpm_resume(struct device *dev, int rpmflags)
        struct device *parent = NULL;
        int retval = 0;
 
-       dev_dbg(dev, "%s flags 0x%x\n", __func__, rpmflags);
+       trace_rpm_resume(dev, rpmflags);
 
  repeat:
        if (dev->power.runtime_error)
@@ -490,6 +545,15 @@ static int rpm_resume(struct device *dev, int rpmflags)
                        goto out;
                }
 
+               if (dev->power.irq_safe) {
+                       spin_unlock(&dev->power.lock);
+
+                       cpu_relax();
+
+                       spin_lock(&dev->power.lock);
+                       goto repeat;
+               }
+
                /* Wait for the operation carried out in parallel with us. */
                for (;;) {
                        prepare_to_wait(&dev->power.wait_queue, &wait,
@@ -551,7 +615,7 @@ static int rpm_resume(struct device *dev, int rpmflags)
 
                spin_lock(&parent->power.lock);
                /*
-                * We can resume if the parent's run-time PM is disabled or it
+                * We can resume if the parent's runtime PM is disabled or it
                 * is set to ignore children.
                 */
                if (!parent->power.disable_depth
@@ -585,6 +649,9 @@ static int rpm_resume(struct device *dev, int rpmflags)
        else
                callback = NULL;
 
+       if (!callback && dev->driver && dev->driver->pm)
+               callback = dev->driver->pm->runtime_resume;
+
        retval = rpm_callback(callback, dev);
        if (retval) {
                __update_runtime_status(dev, RPM_SUSPENDED);
@@ -609,17 +676,17 @@ static int rpm_resume(struct device *dev, int rpmflags)
                spin_lock_irq(&dev->power.lock);
        }
 
-       dev_dbg(dev, "%s returns %d\n", __func__, retval);
+       trace_rpm_return_int(dev, _THIS_IP_, retval);
 
        return retval;
 }
 
 /**
- * pm_runtime_work - Universal run-time PM work function.
+ * pm_runtime_work - Universal runtime PM work function.
  * @work: Work structure used for scheduling the execution of this function.
  *
  * Use @work to get the device object the work is to be done for, determine what
- * is to be done and execute the appropriate run-time PM function.
+ * is to be done and execute the appropriate runtime PM function.
  */
 static void pm_runtime_work(struct work_struct *work)
 {
@@ -718,7 +785,7 @@ int pm_schedule_suspend(struct device *dev, unsigned int delay)
 EXPORT_SYMBOL_GPL(pm_schedule_suspend);
 
 /**
- * __pm_runtime_idle - Entry point for run-time idle operations.
+ * __pm_runtime_idle - Entry point for runtime idle operations.
  * @dev: Device to send idle notification for.
  * @rpmflags: Flag bits.
  *
@@ -726,13 +793,16 @@ EXPORT_SYMBOL_GPL(pm_schedule_suspend);
  * return immediately if it is larger than zero.  Then carry out an idle
  * notification, either synchronous or asynchronous.
  *
- * This routine may be called in atomic context if the RPM_ASYNC flag is set.
+ * This routine may be called in atomic context if the RPM_ASYNC flag is set,
+ * or if pm_runtime_irq_safe() has been called.
  */
 int __pm_runtime_idle(struct device *dev, int rpmflags)
 {
        unsigned long flags;
        int retval;
 
+       might_sleep_if(!(rpmflags & RPM_ASYNC) && !dev->power.irq_safe);
+
        if (rpmflags & RPM_GET_PUT) {
                if (!atomic_dec_and_test(&dev->power.usage_count))
                        return 0;
@@ -747,7 +817,7 @@ int __pm_runtime_idle(struct device *dev, int rpmflags)
 EXPORT_SYMBOL_GPL(__pm_runtime_idle);
 
 /**
- * __pm_runtime_suspend - Entry point for run-time put/suspend operations.
+ * __pm_runtime_suspend - Entry point for runtime put/suspend operations.
  * @dev: Device to suspend.
  * @rpmflags: Flag bits.
  *
@@ -755,13 +825,16 @@ EXPORT_SYMBOL_GPL(__pm_runtime_idle);
  * return immediately if it is larger than zero.  Then carry out a suspend,
  * either synchronous or asynchronous.
  *
- * This routine may be called in atomic context if the RPM_ASYNC flag is set.
+ * This routine may be called in atomic context if the RPM_ASYNC flag is set,
+ * or if pm_runtime_irq_safe() has been called.
  */
 int __pm_runtime_suspend(struct device *dev, int rpmflags)
 {
        unsigned long flags;
        int retval;
 
+       might_sleep_if(!(rpmflags & RPM_ASYNC) && !dev->power.irq_safe);
+
        if (rpmflags & RPM_GET_PUT) {
                if (!atomic_dec_and_test(&dev->power.usage_count))
                        return 0;
@@ -776,20 +849,23 @@ int __pm_runtime_suspend(struct device *dev, int rpmflags)
 EXPORT_SYMBOL_GPL(__pm_runtime_suspend);
 
 /**
- * __pm_runtime_resume - Entry point for run-time resume operations.
+ * __pm_runtime_resume - Entry point for runtime resume operations.
  * @dev: Device to resume.
  * @rpmflags: Flag bits.
  *
  * If the RPM_GET_PUT flag is set, increment the device's usage count.  Then
  * carry out a resume, either synchronous or asynchronous.
  *
- * This routine may be called in atomic context if the RPM_ASYNC flag is set.
+ * This routine may be called in atomic context if the RPM_ASYNC flag is set,
+ * or if pm_runtime_irq_safe() has been called.
  */
 int __pm_runtime_resume(struct device *dev, int rpmflags)
 {
        unsigned long flags;
        int retval;
 
+       might_sleep_if(!(rpmflags & RPM_ASYNC) && !dev->power.irq_safe);
+
        if (rpmflags & RPM_GET_PUT)
                atomic_inc(&dev->power.usage_count);
 
@@ -802,11 +878,11 @@ int __pm_runtime_resume(struct device *dev, int rpmflags)
 EXPORT_SYMBOL_GPL(__pm_runtime_resume);
 
 /**
- * __pm_runtime_set_status - Set run-time PM status of a device.
+ * __pm_runtime_set_status - Set runtime PM status of a device.
  * @dev: Device to handle.
- * @status: New run-time PM status of the device.
+ * @status: New runtime PM status of the device.
  *
- * If run-time PM of the device is disabled or its power.runtime_error field is
+ * If runtime PM of the device is disabled or its power.runtime_error field is
  * different from zero, the status may be changed either to RPM_ACTIVE, or to
  * RPM_SUSPENDED, as long as that reflects the actual state of the device.
  * However, if the device has a parent and the parent is not active, and the
@@ -852,7 +928,7 @@ int __pm_runtime_set_status(struct device *dev, unsigned int status)
 
                /*
                 * It is invalid to put an active child under a parent that is
-                * not active, has run-time PM enabled and the
+                * not active, has runtime PM enabled and the
                 * 'power.ignore_children' flag unset.
                 */
                if (!parent->power.disable_depth
@@ -886,7 +962,7 @@ EXPORT_SYMBOL_GPL(__pm_runtime_set_status);
  * @dev: Device to handle.
  *
  * Flush all pending requests for the device from pm_wq and wait for all
- * run-time PM operations involving the device in progress to complete.
+ * runtime PM operations involving the device in progress to complete.
  *
  * Should be called under dev->power.lock with interrupts disabled.
  */
@@ -934,7 +1010,7 @@ static void __pm_runtime_barrier(struct device *dev)
  * Prevent the device from being suspended by incrementing its usage counter and
  * if there's a pending resume request for the device, wake the device up.
  * Next, make sure that all pending requests for the device have been flushed
- * from pm_wq and wait for all run-time PM operations involving the device in
+ * from pm_wq and wait for all runtime PM operations involving the device in
  * progress to complete.
  *
  * Return value:
@@ -964,18 +1040,18 @@ int pm_runtime_barrier(struct device *dev)
 EXPORT_SYMBOL_GPL(pm_runtime_barrier);
 
 /**
- * __pm_runtime_disable - Disable run-time PM of a device.
+ * __pm_runtime_disable - Disable runtime PM of a device.
  * @dev: Device to handle.
  * @check_resume: If set, check if there's a resume request for the device.
  *
  * Increment power.disable_depth for the device and if was zero previously,
- * cancel all pending run-time PM requests for the device and wait for all
+ * cancel all pending runtime PM requests for the device and wait for all
  * operations in progress to complete.  The device can be either active or
- * suspended after its run-time PM has been disabled.
+ * suspended after its runtime PM has been disabled.
  *
  * If @check_resume is set and there's a resume request pending when
  * __pm_runtime_disable() is called and power.disable_depth is zero, the
- * function will wake up the device before disabling its run-time PM.
+ * function will wake up the device before disabling its runtime PM.
  */
 void __pm_runtime_disable(struct device *dev, bool check_resume)
 {
@@ -988,7 +1064,7 @@ void __pm_runtime_disable(struct device *dev, bool check_resume)
 
        /*
         * Wake up the device if there's a resume request pending, because that
-        * means there probably is some I/O to process and disabling run-time PM
+        * means there probably is some I/O to process and disabling runtime PM
         * shouldn't prevent the device from processing the I/O.
         */
        if (check_resume && dev->power.request_pending
@@ -1013,7 +1089,7 @@ void __pm_runtime_disable(struct device *dev, bool check_resume)
 EXPORT_SYMBOL_GPL(__pm_runtime_disable);
 
 /**
- * pm_runtime_enable - Enable run-time PM of a device.
+ * pm_runtime_enable - Enable runtime PM of a device.
  * @dev: Device to handle.
  */
 void pm_runtime_enable(struct device *dev)
@@ -1032,7 +1108,7 @@ void pm_runtime_enable(struct device *dev)
 EXPORT_SYMBOL_GPL(pm_runtime_enable);
 
 /**
- * pm_runtime_forbid - Block run-time PM of a device.
+ * pm_runtime_forbid - Block runtime PM of a device.
  * @dev: Device to handle.
  *
  * Increase the device's usage count and clear its power.runtime_auto flag,
@@ -1055,7 +1131,7 @@ void pm_runtime_forbid(struct device *dev)
 EXPORT_SYMBOL_GPL(pm_runtime_forbid);
 
 /**
- * pm_runtime_allow - Unblock run-time PM of a device.
+ * pm_runtime_allow - Unblock runtime PM of a device.
  * @dev: Device to handle.
  *
  * Decrease the device's usage count and set its power.runtime_auto flag.
@@ -1076,12 +1152,12 @@ void pm_runtime_allow(struct device *dev)
 EXPORT_SYMBOL_GPL(pm_runtime_allow);
 
 /**
- * pm_runtime_no_callbacks - Ignore run-time PM callbacks for a device.
+ * pm_runtime_no_callbacks - Ignore runtime PM callbacks for a device.
  * @dev: Device to handle.
  *
  * Set the power.no_callbacks flag, which tells the PM core that this
- * device is power-managed through its parent and has no run-time PM
- * callbacks of its own.  The run-time sysfs attributes will be removed.
+ * device is power-managed through its parent and has no runtime PM
+ * callbacks of its own.  The runtime sysfs attributes will be removed.
  */
 void pm_runtime_no_callbacks(struct device *dev)
 {
@@ -1157,8 +1233,8 @@ static void update_autosuspend(struct device *dev, int old_delay, int old_use)
  * @delay: Value of the new delay in milliseconds.
  *
  * Set the device's power.autosuspend_delay value.  If it changes to negative
- * and the power.use_autosuspend flag is set, prevent run-time suspends.  If it
- * changes the other way, allow run-time suspends.
+ * and the power.use_autosuspend flag is set, prevent runtime suspends.  If it
+ * changes the other way, allow runtime suspends.
  */
 void pm_runtime_set_autosuspend_delay(struct device *dev, int delay)
 {
@@ -1178,7 +1254,7 @@ EXPORT_SYMBOL_GPL(pm_runtime_set_autosuspend_delay);
  * @dev: Device to handle.
  * @use: New value for use_autosuspend.
  *
- * Set the device's power.use_autosuspend flag, and allow or prevent run-time
+ * Set the device's power.use_autosuspend flag, and allow or prevent runtime
  * suspends as needed.
  */
 void __pm_runtime_use_autosuspend(struct device *dev, bool use)
@@ -1195,7 +1271,7 @@ void __pm_runtime_use_autosuspend(struct device *dev, bool use)
 EXPORT_SYMBOL_GPL(__pm_runtime_use_autosuspend);
 
 /**
- * pm_runtime_init - Initialize run-time PM fields in given device object.
+ * pm_runtime_init - Initialize runtime PM fields in given device object.
  * @dev: Device object to initialize.
  */
 void pm_runtime_init(struct device *dev)