diff options
Diffstat (limited to 'drivers/base/power/runtime.c')
-rw-r--r-- | drivers/base/power/runtime.c | 76 |
1 files changed, 32 insertions, 44 deletions
diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c index 67c7938e430b..5070c4fe8542 100644 --- a/drivers/base/power/runtime.c +++ b/drivers/base/power/runtime.c @@ -13,43 +13,38 @@ #include <trace/events/rpm.h> #include "power.h" -#define RPM_GET_CALLBACK(dev, cb) \ -({ \ - int (*__rpm_cb)(struct device *__d); \ - \ - if (dev->pm_domain) \ - __rpm_cb = dev->pm_domain->ops.cb; \ - else if (dev->type && dev->type->pm) \ - __rpm_cb = dev->type->pm->cb; \ - else if (dev->class && dev->class->pm) \ - __rpm_cb = dev->class->pm->cb; \ - else if (dev->bus && dev->bus->pm) \ - __rpm_cb = dev->bus->pm->cb; \ - else \ - __rpm_cb = NULL; \ - \ - if (!__rpm_cb && dev->driver && dev->driver->pm) \ - __rpm_cb = dev->driver->pm->cb; \ - \ - __rpm_cb; \ -}) - -static int (*rpm_get_suspend_cb(struct device *dev))(struct device *) -{ - return RPM_GET_CALLBACK(dev, runtime_suspend); -} +typedef int (*pm_callback_t)(struct device *); -static int (*rpm_get_resume_cb(struct device *dev))(struct device *) +static pm_callback_t __rpm_get_callback(struct device *dev, size_t cb_offset) { - return RPM_GET_CALLBACK(dev, runtime_resume); -} + pm_callback_t cb; + const struct dev_pm_ops *ops; + + if (dev->pm_domain) + ops = &dev->pm_domain->ops; + else if (dev->type && dev->type->pm) + ops = dev->type->pm; + else if (dev->class && dev->class->pm) + ops = dev->class->pm; + else if (dev->bus && dev->bus->pm) + ops = dev->bus->pm; + else + ops = NULL; -#ifdef CONFIG_PM_RUNTIME -static int (*rpm_get_idle_cb(struct device *dev))(struct device *) -{ - return RPM_GET_CALLBACK(dev, runtime_idle); + if (ops) + cb = *(pm_callback_t *)((void *)ops + cb_offset); + else + cb = NULL; + + if (!cb && dev->driver && dev->driver->pm) + cb = *(pm_callback_t *)((void *)dev->driver->pm + cb_offset); + + return cb; } +#define RPM_GET_CALLBACK(dev, callback) \ + __rpm_get_callback(dev, offsetof(struct dev_pm_ops, callback)) + static int rpm_resume(struct device *dev, int rpmflags); static int rpm_suspend(struct device *dev, int rpmflags); @@ -347,7 +342,7 @@ static int rpm_idle(struct device *dev, int rpmflags) dev->power.idle_notification = true; - callback = rpm_get_idle_cb(dev); + callback = RPM_GET_CALLBACK(dev, runtime_idle); if (callback) retval = __rpm_callback(callback, dev); @@ -517,7 +512,7 @@ static int rpm_suspend(struct device *dev, int rpmflags) __update_runtime_status(dev, RPM_SUSPENDING); - callback = rpm_get_suspend_cb(dev); + callback = RPM_GET_CALLBACK(dev, runtime_suspend); retval = rpm_callback(callback, dev); if (retval) @@ -737,7 +732,7 @@ static int rpm_resume(struct device *dev, int rpmflags) __update_runtime_status(dev, RPM_RESUMING); - callback = rpm_get_resume_cb(dev); + callback = RPM_GET_CALLBACK(dev, runtime_resume); retval = rpm_callback(callback, dev); if (retval) { @@ -1402,7 +1397,6 @@ void pm_runtime_remove(struct device *dev) if (dev->power.irq_safe && dev->parent) pm_runtime_put(dev->parent); } -#endif /** * pm_runtime_force_suspend - Force a device into suspend state if needed. @@ -1422,16 +1416,10 @@ int pm_runtime_force_suspend(struct device *dev) int ret = 0; pm_runtime_disable(dev); - - /* - * Note that pm_runtime_status_suspended() returns false while - * !CONFIG_PM_RUNTIME, which means the device will be put into low - * power state. - */ if (pm_runtime_status_suspended(dev)) return 0; - callback = rpm_get_suspend_cb(dev); + callback = RPM_GET_CALLBACK(dev, runtime_suspend); if (!callback) { ret = -ENOSYS; @@ -1467,7 +1455,7 @@ int pm_runtime_force_resume(struct device *dev) int (*callback)(struct device *); int ret = 0; - callback = rpm_get_resume_cb(dev); + callback = RPM_GET_CALLBACK(dev, runtime_resume); if (!callback) { ret = -ENOSYS; |