PM / Sleep: Make pm_op() and pm_noirq_op() return callback pointers
authorRafael J. Wysocki <rjw@sisk.pl>
Sat, 17 Dec 2011 23:34:01 +0000 (00:34 +0100)
committerRafael J. Wysocki <rjw@sisk.pl>
Wed, 21 Dec 2011 21:00:56 +0000 (22:00 +0100)
Make the pm_op() and pm_noirq_op() functions return pointers to
appropriate callbacks instead of executing those callbacks and
returning their results.

This change is required for a subsequent modification that will
execute the corresponding driver callback if the subsystem
callback returned by either pm_op(), or pm_noirq_op() is NULL.

Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
drivers/base/power/main.c

index b570189d4f2dfc1618063851de4dcbb353818439..b5cef7e7de234ccf1fd523b377ce0cff17411c1e 100644 (file)
@@ -32,6 +32,8 @@
 #include "../base.h"
 #include "power.h"
 
+typedef int (*pm_callback_t)(struct device *);
+
 /*
  * The entries in the dpm_list list are in a depth first order, simply
  * because children are guaranteed to be discovered after parents, and
@@ -211,113 +213,70 @@ static void dpm_wait_for_children(struct device *dev, bool async)
        device_for_each_child(dev, &async, dpm_wait_fn);
 }
 
-static int dpm_run_callback(struct device *dev, int (*cb)(struct device *))
-{
-       ktime_t calltime;
-       int error;
-
-       if (!cb)
-               return 0;
-
-       calltime = initcall_debug_start(dev);
-
-       error = cb(dev);
-       suspend_report_result(cb, error);
-
-       initcall_debug_report(dev, calltime, error);
-
-       return error;
-}
-
 /**
- * pm_op - Execute the PM operation appropriate for given PM event.
- * @dev: Device to handle.
+ * pm_op - Return the PM operation appropriate for given PM event.
  * @ops: PM operations to choose from.
  * @state: PM transition of the system being carried out.
  */
-static int pm_op(struct device *dev,
-                const struct dev_pm_ops *ops,
-                pm_message_t state)
+static pm_callback_t pm_op(const struct dev_pm_ops *ops, pm_message_t state)
 {
-       int error = 0;
-
        switch (state.event) {
 #ifdef CONFIG_SUSPEND
        case PM_EVENT_SUSPEND:
-               error = dpm_run_callback(dev, ops->suspend);
-               break;
+               return ops->suspend;
        case PM_EVENT_RESUME:
-               error = dpm_run_callback(dev, ops->resume);
-               break;
+               return ops->resume;
 #endif /* CONFIG_SUSPEND */
 #ifdef CONFIG_HIBERNATE_CALLBACKS
        case PM_EVENT_FREEZE:
        case PM_EVENT_QUIESCE:
-               error = dpm_run_callback(dev, ops->freeze);
-               break;
+               return ops->freeze;
        case PM_EVENT_HIBERNATE:
-               error = dpm_run_callback(dev, ops->poweroff);
-               break;
+               return ops->poweroff;
        case PM_EVENT_THAW:
        case PM_EVENT_RECOVER:
-               error = dpm_run_callback(dev, ops->thaw);
+               return ops->thaw;
                break;
        case PM_EVENT_RESTORE:
-               error = dpm_run_callback(dev, ops->restore);
-               break;
+               return ops->restore;
 #endif /* CONFIG_HIBERNATE_CALLBACKS */
-       default:
-               error = -EINVAL;
        }
 
-       return error;
+       return NULL;
 }
 
 /**
- * pm_noirq_op - Execute the PM operation appropriate for given PM event.
- * @dev: Device to handle.
+ * pm_noirq_op - Return the PM operation appropriate for given PM event.
  * @ops: PM operations to choose from.
  * @state: PM transition of the system being carried out.
  *
  * The driver of @dev will not receive interrupts while this function is being
  * executed.
  */
-static int pm_noirq_op(struct device *dev,
-                       const struct dev_pm_ops *ops,
-                       pm_message_t state)
+static pm_callback_t pm_noirq_op(const struct dev_pm_ops *ops, pm_message_t state)
 {
-       int error = 0;
-
        switch (state.event) {
 #ifdef CONFIG_SUSPEND
        case PM_EVENT_SUSPEND:
-               error = dpm_run_callback(dev, ops->suspend_noirq);
-               break;
+               return ops->suspend_noirq;
        case PM_EVENT_RESUME:
-               error = dpm_run_callback(dev, ops->resume_noirq);
-               break;
+               return ops->resume_noirq;
 #endif /* CONFIG_SUSPEND */
 #ifdef CONFIG_HIBERNATE_CALLBACKS
        case PM_EVENT_FREEZE:
        case PM_EVENT_QUIESCE:
-               error = dpm_run_callback(dev, ops->freeze_noirq);
-               break;
+               return ops->freeze_noirq;
        case PM_EVENT_HIBERNATE:
-               error = dpm_run_callback(dev, ops->poweroff_noirq);
-               break;
+               return ops->poweroff_noirq;
        case PM_EVENT_THAW:
        case PM_EVENT_RECOVER:
-               error = dpm_run_callback(dev, ops->thaw_noirq);
-               break;
+               return ops->thaw_noirq;
        case PM_EVENT_RESTORE:
-               error = dpm_run_callback(dev, ops->restore_noirq);
-               break;
+               return ops->restore_noirq;
 #endif /* CONFIG_HIBERNATE_CALLBACKS */
-       default:
-               error = -EINVAL;
        }
 
-       return error;
+       return NULL;
 }
 
 static char *pm_verb(int event)
@@ -375,6 +334,26 @@ static void dpm_show_time(ktime_t starttime, pm_message_t state, char *info)
                usecs / USEC_PER_MSEC, usecs % USEC_PER_MSEC);
 }
 
+static int dpm_run_callback(pm_callback_t cb, struct device *dev,
+                           pm_message_t state, char *info)
+{
+       ktime_t calltime;
+       int error;
+
+       if (!cb)
+               return 0;
+
+       calltime = initcall_debug_start(dev);
+
+       pm_dev_dbg(dev, state, info);
+       error = cb(dev);
+       suspend_report_result(cb, error);
+
+       initcall_debug_report(dev, calltime, error);
+
+       return error;
+}
+
 /*------------------------- Resume routines -------------------------*/
 
 /**
@@ -387,25 +366,29 @@ static void dpm_show_time(ktime_t starttime, pm_message_t state, char *info)
  */
 static int device_resume_noirq(struct device *dev, pm_message_t state)
 {
+       pm_callback_t callback = NULL;
+       char *info = NULL;
        int error = 0;
 
        TRACE_DEVICE(dev);
        TRACE_RESUME(0);
 
        if (dev->pm_domain) {
-               pm_dev_dbg(dev, state, "EARLY power domain ");
-               error = pm_noirq_op(dev, &dev->pm_domain->ops, state);
+               info = "EARLY power domain ";
+               callback = pm_noirq_op(&dev->pm_domain->ops, state);
        } else if (dev->type && dev->type->pm) {
-               pm_dev_dbg(dev, state, "EARLY type ");
-               error = pm_noirq_op(dev, dev->type->pm, state);
+               info = "EARLY type ";
+               callback = pm_noirq_op(dev->type->pm, state);
        } else if (dev->class && dev->class->pm) {
-               pm_dev_dbg(dev, state, "EARLY class ");
-               error = pm_noirq_op(dev, dev->class->pm, state);
+               info = "EARLY class ";
+               callback = pm_noirq_op(dev->class->pm, state);
        } else if (dev->bus && dev->bus->pm) {
-               pm_dev_dbg(dev, state, "EARLY ");
-               error = pm_noirq_op(dev, dev->bus->pm, state);
+               info = "EARLY ";
+               callback = pm_noirq_op(dev->bus->pm, state);
        }
 
+       error = dpm_run_callback(callback, dev, state, info);
+
        TRACE_RESUME(error);
        return error;
 }
@@ -455,6 +438,8 @@ EXPORT_SYMBOL_GPL(dpm_resume_noirq);
  */
 static int device_resume(struct device *dev, pm_message_t state, bool async)
 {
+       pm_callback_t callback = NULL;
+       char *info = NULL;
        int error = 0;
        bool put = false;
 
@@ -477,40 +462,41 @@ static int device_resume(struct device *dev, pm_message_t state, bool async)
        put = true;
 
        if (dev->pm_domain) {
-               pm_dev_dbg(dev, state, "power domain ");
-               error = pm_op(dev, &dev->pm_domain->ops, state);
+               info = "power domain ";
+               callback = pm_op(&dev->pm_domain->ops, state);
                goto End;
        }
 
        if (dev->type && dev->type->pm) {
-               pm_dev_dbg(dev, state, "type ");
-               error = pm_op(dev, dev->type->pm, state);
+               info = "type ";
+               callback = pm_op(dev->type->pm, state);
                goto End;
        }
 
        if (dev->class) {
                if (dev->class->pm) {
-                       pm_dev_dbg(dev, state, "class ");
-                       error = pm_op(dev, dev->class->pm, state);
+                       info = "class ";
+                       callback = pm_op(dev->class->pm, state);
                        goto End;
                } else if (dev->class->resume) {
-                       pm_dev_dbg(dev, state, "legacy class ");
-                       error = dpm_run_callback(dev, dev->class->resume);
+                       info = "legacy class ";
+                       callback = dev->class->resume;
                        goto End;
                }
        }
 
        if (dev->bus) {
                if (dev->bus->pm) {
-                       pm_dev_dbg(dev, state, "");
-                       error = pm_op(dev, dev->bus->pm, state);
+                       info = "";
+                       callback = pm_op(dev->bus->pm, state);
                } else if (dev->bus->resume) {
-                       pm_dev_dbg(dev, state, "legacy ");
-                       error = dpm_run_callback(dev, dev->bus->resume);
+                       info = "legacy ";
+                       callback = dev->bus->resume;
                }
        }
 
  End:
+       error = dpm_run_callback(callback, dev, state, info);
        dev->power.is_suspended = false;
 
  Unlock:
@@ -705,23 +691,24 @@ static pm_message_t resume_event(pm_message_t sleep_state)
  */
 static int device_suspend_noirq(struct device *dev, pm_message_t state)
 {
-       int error = 0;
+       pm_callback_t callback = NULL;
+       char *info = NULL;
 
        if (dev->pm_domain) {
-               pm_dev_dbg(dev, state, "LATE power domain ");
-               error = pm_noirq_op(dev, &dev->pm_domain->ops, state);
+               info = "LATE power domain ";
+               callback = pm_noirq_op(&dev->pm_domain->ops, state);
        } else if (dev->type && dev->type->pm) {
-               pm_dev_dbg(dev, state, "LATE type ");
-               error = pm_noirq_op(dev, dev->type->pm, state);
+               info = "LATE type ";
+               callback = pm_noirq_op(dev->type->pm, state);
        } else if (dev->class && dev->class->pm) {
-               pm_dev_dbg(dev, state, "LATE class ");
-               error = pm_noirq_op(dev, dev->class->pm, state);
+               info = "LATE class ";
+               callback = pm_noirq_op(dev->class->pm, state);
        } else if (dev->bus && dev->bus->pm) {
-               pm_dev_dbg(dev, state, "LATE ");
-               error = pm_noirq_op(dev, dev->bus->pm, state);
+               info = "LATE ";
+               callback = pm_noirq_op(dev->bus->pm, state);
        }
 
-       return error;
+       return dpm_run_callback(callback, dev, state, info);
 }
 
 /**
@@ -798,6 +785,8 @@ static int legacy_suspend(struct device *dev, pm_message_t state,
  */
 static int __device_suspend(struct device *dev, pm_message_t state, bool async)
 {
+       pm_callback_t callback = NULL;
+       char *info = NULL;
        int error = 0;
 
        dpm_wait_for_children(dev, async);
@@ -818,22 +807,22 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async)
        device_lock(dev);
 
        if (dev->pm_domain) {
-               pm_dev_dbg(dev, state, "power domain ");
-               error = pm_op(dev, &dev->pm_domain->ops, state);
-               goto End;
+               info = "power domain ";
+               callback = pm_op(&dev->pm_domain->ops, state);
+               goto Run;
        }
 
        if (dev->type && dev->type->pm) {
-               pm_dev_dbg(dev, state, "type ");
-               error = pm_op(dev, dev->type->pm, state);
-               goto End;
+               info = "type ";
+               callback = pm_op(dev->type->pm, state);
+               goto Run;
        }
 
        if (dev->class) {
                if (dev->class->pm) {
-                       pm_dev_dbg(dev, state, "class ");
-                       error = pm_op(dev, dev->class->pm, state);
-                       goto End;
+                       info = "class ";
+                       callback = pm_op(dev->class->pm, state);
+                       goto Run;
                } else if (dev->class->suspend) {
                        pm_dev_dbg(dev, state, "legacy class ");
                        error = legacy_suspend(dev, state, dev->class->suspend);
@@ -843,14 +832,18 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async)
 
        if (dev->bus) {
                if (dev->bus->pm) {
-                       pm_dev_dbg(dev, state, "");
-                       error = pm_op(dev, dev->bus->pm, state);
+                       info = "";
+                       callback = pm_op(dev->bus->pm, state);
                } else if (dev->bus->suspend) {
                        pm_dev_dbg(dev, state, "legacy ");
                        error = legacy_suspend(dev, state, dev->bus->suspend);
+                       goto End;
                }
        }
 
+ Run:
+       error = dpm_run_callback(callback, dev, state, info);
+
  End:
        if (!error) {
                dev->power.is_suspended = true;