PM / core: Add helpers for subsystem callback selection
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>
Sat, 9 Dec 2017 23:58:18 +0000 (00:58 +0100)
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>
Tue, 2 Jan 2018 23:29:48 +0000 (00:29 +0100)
Add helper routines to find and return a suitable subsystem callback
during the "noirq" phases of system suspend/resume (or analogous)
transitions as well as during the "late" phase of system suspend and
the "early" phase of system resume (or analogous) transitions.

The helpers will be called from additional sites going forward.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Reviewed-by: Ulf Hansson <ulf.hansson@linaro.org>
Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>
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 ";