PM / core: Add helpers for subsystem callback selection
[sfrench/cifs-2.6.git] / drivers / base / power / main.c
index 6e8cc5de93fd28754497ac82f309d522e699673b..3c5fdf155c91b1ea40576fd54e445944915aed20 100644 (file)
@@ -551,6 +551,35 @@ bool dev_pm_may_skip_resume(struct device *dev)
        return !dev->power.must_resume && pm_transition.event != PM_EVENT_RESTORE;
 }
 
+static pm_callback_t dpm_subsys_resume_noirq_cb(struct device *dev,
+                                               pm_message_t state,
+                                               const char **info_p)
+{
+       pm_callback_t callback;
+       const char *info;
+
+       if (dev->pm_domain) {
+               info = "noirq power domain ";
+               callback = pm_noirq_op(&dev->pm_domain->ops, state);
+       } else if (dev->type && dev->type->pm) {
+               info = "noirq type ";
+               callback = pm_noirq_op(dev->type->pm, state);
+       } else if (dev->class && dev->class->pm) {
+               info = "noirq class ";
+               callback = pm_noirq_op(dev->class->pm, state);
+       } else if (dev->bus && dev->bus->pm) {
+               info = "noirq bus ";
+               callback = pm_noirq_op(dev->bus->pm, state);
+       } else {
+               return NULL;
+       }
+
+       if (info_p)
+               *info_p = info;
+
+       return callback;
+}
+
 /**
  * device_resume_noirq - Execute a "noirq resume" callback for given device.
  * @dev: Device to handle.
@@ -562,8 +591,8 @@ bool dev_pm_may_skip_resume(struct device *dev)
  */
 static int device_resume_noirq(struct device *dev, pm_message_t state, bool async)
 {
-       pm_callback_t callback = NULL;
-       const char *info = NULL;
+       pm_callback_t callback;
+       const char *info;
        int error = 0;
 
        TRACE_DEVICE(dev);
@@ -577,19 +606,7 @@ static int device_resume_noirq(struct device *dev, pm_message_t state, bool asyn
 
        dpm_wait_for_superior(dev, async);
 
-       if (dev->pm_domain) {
-               info = "noirq power domain ";
-               callback = pm_noirq_op(&dev->pm_domain->ops, state);
-       } else if (dev->type && dev->type->pm) {
-               info = "noirq type ";
-               callback = pm_noirq_op(dev->type->pm, state);
-       } else if (dev->class && dev->class->pm) {
-               info = "noirq class ";
-               callback = pm_noirq_op(dev->class->pm, state);
-       } else if (dev->bus && dev->bus->pm) {
-               info = "noirq bus ";
-               callback = pm_noirq_op(dev->bus->pm, state);
-       }
+       callback = dpm_subsys_resume_noirq_cb(dev, state, &info);
 
        if (!callback && dev->driver && dev->driver->pm) {
                info = "noirq driver ";
@@ -704,6 +721,35 @@ void dpm_resume_noirq(pm_message_t state)
        dpm_noirq_end();
 }
 
+static pm_callback_t dpm_subsys_resume_early_cb(struct device *dev,
+                                               pm_message_t state,
+                                               const char **info_p)
+{
+       pm_callback_t callback;
+       const char *info;
+
+       if (dev->pm_domain) {
+               info = "early power domain ";
+               callback = pm_late_early_op(&dev->pm_domain->ops, state);
+       } else if (dev->type && dev->type->pm) {
+               info = "early type ";
+               callback = pm_late_early_op(dev->type->pm, state);
+       } else if (dev->class && dev->class->pm) {
+               info = "early class ";
+               callback = pm_late_early_op(dev->class->pm, state);
+       } else if (dev->bus && dev->bus->pm) {
+               info = "early bus ";
+               callback = pm_late_early_op(dev->bus->pm, state);
+       } else {
+               return NULL;
+       }
+
+       if (info_p)
+               *info_p = info;
+
+       return callback;
+}
+
 /**
  * device_resume_early - Execute an "early resume" callback for given device.
  * @dev: Device to handle.
@@ -714,8 +760,8 @@ void dpm_resume_noirq(pm_message_t state)
  */
 static int device_resume_early(struct device *dev, pm_message_t state, bool async)
 {
-       pm_callback_t callback = NULL;
-       const char *info = NULL;
+       pm_callback_t callback;
+       const char *info;
        int error = 0;
 
        TRACE_DEVICE(dev);
@@ -729,19 +775,7 @@ static int device_resume_early(struct device *dev, pm_message_t state, bool asyn
 
        dpm_wait_for_superior(dev, async);
 
-       if (dev->pm_domain) {
-               info = "early power domain ";
-               callback = pm_late_early_op(&dev->pm_domain->ops, state);
-       } else if (dev->type && dev->type->pm) {
-               info = "early type ";
-               callback = pm_late_early_op(dev->type->pm, state);
-       } else if (dev->class && dev->class->pm) {
-               info = "early class ";
-               callback = pm_late_early_op(dev->class->pm, state);
-       } else if (dev->bus && dev->bus->pm) {
-               info = "early bus ";
-               callback = pm_late_early_op(dev->bus->pm, state);
-       }
+       callback = dpm_subsys_resume_early_cb(dev, state, &info);
 
        if (!callback && dev->driver && dev->driver->pm) {
                info = "early driver ";
@@ -1128,6 +1162,35 @@ static void dpm_superior_set_must_resume(struct device *dev)
        device_links_read_unlock(idx);
 }
 
+static pm_callback_t dpm_subsys_suspend_noirq_cb(struct device *dev,
+                                                pm_message_t state,
+                                                const char **info_p)
+{
+       pm_callback_t callback;
+       const char *info;
+
+       if (dev->pm_domain) {
+               info = "noirq power domain ";
+               callback = pm_noirq_op(&dev->pm_domain->ops, state);
+       } else if (dev->type && dev->type->pm) {
+               info = "noirq type ";
+               callback = pm_noirq_op(dev->type->pm, state);
+       } else if (dev->class && dev->class->pm) {
+               info = "noirq class ";
+               callback = pm_noirq_op(dev->class->pm, state);
+       } else if (dev->bus && dev->bus->pm) {
+               info = "noirq bus ";
+               callback = pm_noirq_op(dev->bus->pm, state);
+       } else {
+               return NULL;
+       }
+
+       if (info_p)
+               *info_p = info;
+
+       return callback;
+}
+
 /**
  * __device_suspend_noirq - Execute a "noirq suspend" callback for given device.
  * @dev: Device to handle.
@@ -1139,8 +1202,8 @@ static void dpm_superior_set_must_resume(struct device *dev)
  */
 static int __device_suspend_noirq(struct device *dev, pm_message_t state, bool async)
 {
-       pm_callback_t callback = NULL;
-       const char *info = NULL;
+       pm_callback_t callback;
+       const char *info;
        int error = 0;
 
        TRACE_DEVICE(dev);
@@ -1159,19 +1222,7 @@ static int __device_suspend_noirq(struct device *dev, pm_message_t state, bool a
        if (dev->power.syscore || dev->power.direct_complete)
                goto Complete;
 
-       if (dev->pm_domain) {
-               info = "noirq power domain ";
-               callback = pm_noirq_op(&dev->pm_domain->ops, state);
-       } else if (dev->type && dev->type->pm) {
-               info = "noirq type ";
-               callback = pm_noirq_op(dev->type->pm, state);
-       } else if (dev->class && dev->class->pm) {
-               info = "noirq class ";
-               callback = pm_noirq_op(dev->class->pm, state);
-       } else if (dev->bus && dev->bus->pm) {
-               info = "noirq bus ";
-               callback = pm_noirq_op(dev->bus->pm, state);
-       }
+       callback = dpm_subsys_suspend_noirq_cb(dev, state, &info);
 
        if (!callback && dev->driver && dev->driver->pm) {
                info = "noirq driver ";
@@ -1306,6 +1357,35 @@ int dpm_suspend_noirq(pm_message_t state)
        return ret;
 }
 
+static pm_callback_t dpm_subsys_suspend_late_cb(struct device *dev,
+                                               pm_message_t state,
+                                               const char **info_p)
+{
+       pm_callback_t callback;
+       const char *info;
+
+       if (dev->pm_domain) {
+               info = "late power domain ";
+               callback = pm_late_early_op(&dev->pm_domain->ops, state);
+       } else if (dev->type && dev->type->pm) {
+               info = "late type ";
+               callback = pm_late_early_op(dev->type->pm, state);
+       } else if (dev->class && dev->class->pm) {
+               info = "late class ";
+               callback = pm_late_early_op(dev->class->pm, state);
+       } else if (dev->bus && dev->bus->pm) {
+               info = "late bus ";
+               callback = pm_late_early_op(dev->bus->pm, state);
+       } else {
+               return NULL;
+       }
+
+       if (info_p)
+               *info_p = info;
+
+       return callback;
+}
+
 /**
  * __device_suspend_late - Execute a "late suspend" callback for given device.
  * @dev: Device to handle.
@@ -1316,8 +1396,8 @@ int dpm_suspend_noirq(pm_message_t state)
  */
 static int __device_suspend_late(struct device *dev, pm_message_t state, bool async)
 {
-       pm_callback_t callback = NULL;
-       const char *info = NULL;
+       pm_callback_t callback;
+       const char *info;
        int error = 0;
 
        TRACE_DEVICE(dev);
@@ -1338,19 +1418,7 @@ static int __device_suspend_late(struct device *dev, pm_message_t state, bool as
        if (dev->power.syscore || dev->power.direct_complete)
                goto Complete;
 
-       if (dev->pm_domain) {
-               info = "late power domain ";
-               callback = pm_late_early_op(&dev->pm_domain->ops, state);
-       } else if (dev->type && dev->type->pm) {
-               info = "late type ";
-               callback = pm_late_early_op(dev->type->pm, state);
-       } else if (dev->class && dev->class->pm) {
-               info = "late class ";
-               callback = pm_late_early_op(dev->class->pm, state);
-       } else if (dev->bus && dev->bus->pm) {
-               info = "late bus ";
-               callback = pm_late_early_op(dev->bus->pm, state);
-       }
+       callback = dpm_subsys_suspend_late_cb(dev, state, &info);
 
        if (!callback && dev->driver && dev->driver->pm) {
                info = "late driver ";