diff options
Diffstat (limited to 'drivers/base/power/main.c')
-rw-r--r-- | drivers/base/power/main.c | 175 |
1 files changed, 93 insertions, 82 deletions
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index 83404973f97..052dc53eef3 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c @@ -423,26 +423,22 @@ static int device_resume_noirq(struct device *dev, pm_message_t state) TRACE_DEVICE(dev); TRACE_RESUME(0); - if (dev->bus && dev->bus->pm) { - pm_dev_dbg(dev, state, "EARLY "); - error = pm_noirq_op(dev, dev->bus->pm, state); - if (error) - goto End; + if (dev->pwr_domain) { + pm_dev_dbg(dev, state, "EARLY power domain "); + pm_noirq_op(dev, &dev->pwr_domain->ops, state); } if (dev->type && dev->type->pm) { pm_dev_dbg(dev, state, "EARLY type "); error = pm_noirq_op(dev, dev->type->pm, state); - if (error) - goto End; - } - - if (dev->class && dev->class->pm) { + } else if (dev->class && dev->class->pm) { pm_dev_dbg(dev, state, "EARLY class "); error = pm_noirq_op(dev, 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); } -End: TRACE_RESUME(error); return error; } @@ -518,36 +514,39 @@ static int device_resume(struct device *dev, pm_message_t state, bool async) dev->power.in_suspend = false; - if (dev->bus) { - if (dev->bus->pm) { - pm_dev_dbg(dev, state, ""); - error = pm_op(dev, dev->bus->pm, state); - } else if (dev->bus->resume) { - pm_dev_dbg(dev, state, "legacy "); - error = legacy_resume(dev, dev->bus->resume); - } - if (error) - goto End; + if (dev->pwr_domain) { + pm_dev_dbg(dev, state, "power domain "); + pm_op(dev, &dev->pwr_domain->ops, state); } - if (dev->type) { - if (dev->type->pm) { - pm_dev_dbg(dev, state, "type "); - error = pm_op(dev, dev->type->pm, state); - } - if (error) - goto End; + if (dev->type && dev->type->pm) { + pm_dev_dbg(dev, state, "type "); + error = pm_op(dev, 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); + goto End; } else if (dev->class->resume) { pm_dev_dbg(dev, state, "legacy class "); error = legacy_resume(dev, 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); + } else if (dev->bus->resume) { + pm_dev_dbg(dev, state, "legacy "); + error = legacy_resume(dev, dev->bus->resume); + } + } + End: device_unlock(dev); complete_all(&dev->power.completion); @@ -629,19 +628,23 @@ static void device_complete(struct device *dev, pm_message_t state) { device_lock(dev); - if (dev->class && dev->class->pm && dev->class->pm->complete) { - pm_dev_dbg(dev, state, "completing class "); - dev->class->pm->complete(dev); + if (dev->pwr_domain && dev->pwr_domain->ops.complete) { + pm_dev_dbg(dev, state, "completing power domain "); + dev->pwr_domain->ops.complete(dev); } - if (dev->type && dev->type->pm && dev->type->pm->complete) { + if (dev->type && dev->type->pm) { pm_dev_dbg(dev, state, "completing type "); - dev->type->pm->complete(dev); - } - - if (dev->bus && dev->bus->pm && dev->bus->pm->complete) { + if (dev->type->pm->complete) + dev->type->pm->complete(dev); + } else if (dev->class && dev->class->pm) { + pm_dev_dbg(dev, state, "completing class "); + if (dev->class->pm->complete) + dev->class->pm->complete(dev); + } else if (dev->bus && dev->bus->pm) { pm_dev_dbg(dev, state, "completing "); - dev->bus->pm->complete(dev); + if (dev->bus->pm->complete) + dev->bus->pm->complete(dev); } device_unlock(dev); @@ -669,7 +672,6 @@ static void dpm_complete(pm_message_t state) mutex_unlock(&dpm_list_mtx); device_complete(dev, state); - pm_runtime_put_sync(dev); mutex_lock(&dpm_list_mtx); put_device(dev); @@ -727,29 +729,31 @@ 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; - - if (dev->class && dev->class->pm) { - pm_dev_dbg(dev, state, "LATE class "); - error = pm_noirq_op(dev, dev->class->pm, state); - if (error) - goto End; - } + int error; if (dev->type && dev->type->pm) { pm_dev_dbg(dev, state, "LATE type "); error = pm_noirq_op(dev, dev->type->pm, state); if (error) - goto End; - } - - if (dev->bus && dev->bus->pm) { + return error; + } else if (dev->class && dev->class->pm) { + pm_dev_dbg(dev, state, "LATE class "); + error = pm_noirq_op(dev, dev->class->pm, state); + if (error) + return error; + } else if (dev->bus && dev->bus->pm) { pm_dev_dbg(dev, state, "LATE "); error = pm_noirq_op(dev, dev->bus->pm, state); + if (error) + return error; } -End: - return error; + if (dev->pwr_domain) { + pm_dev_dbg(dev, state, "LATE power domain "); + pm_noirq_op(dev, &dev->pwr_domain->ops, state); + } + + return 0; } /** @@ -836,25 +840,22 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async) goto End; } + if (dev->type && dev->type->pm) { + pm_dev_dbg(dev, state, "type "); + error = pm_op(dev, dev->type->pm, state); + goto Domain; + } + if (dev->class) { if (dev->class->pm) { pm_dev_dbg(dev, state, "class "); error = pm_op(dev, dev->class->pm, state); + goto Domain; } else if (dev->class->suspend) { pm_dev_dbg(dev, state, "legacy class "); error = legacy_suspend(dev, state, dev->class->suspend); + goto Domain; } - if (error) - goto End; - } - - if (dev->type) { - if (dev->type->pm) { - pm_dev_dbg(dev, state, "type "); - error = pm_op(dev, dev->type->pm, state); - } - if (error) - goto End; } if (dev->bus) { @@ -867,6 +868,12 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async) } } + Domain: + if (!error && dev->pwr_domain) { + pm_dev_dbg(dev, state, "power domain "); + pm_op(dev, &dev->pwr_domain->ops, state); + } + End: device_unlock(dev); complete_all(&dev->power.completion); @@ -957,27 +964,34 @@ static int device_prepare(struct device *dev, pm_message_t state) device_lock(dev); - if (dev->bus && dev->bus->pm && dev->bus->pm->prepare) { + if (dev->type && dev->type->pm) { + pm_dev_dbg(dev, state, "preparing type "); + if (dev->type->pm->prepare) + error = dev->type->pm->prepare(dev); + suspend_report_result(dev->type->pm->prepare, error); + if (error) + goto End; + } else if (dev->class && dev->class->pm) { + pm_dev_dbg(dev, state, "preparing class "); + if (dev->class->pm->prepare) + error = dev->class->pm->prepare(dev); + suspend_report_result(dev->class->pm->prepare, error); + if (error) + goto End; + } else if (dev->bus && dev->bus->pm) { pm_dev_dbg(dev, state, "preparing "); - error = dev->bus->pm->prepare(dev); + if (dev->bus->pm->prepare) + error = dev->bus->pm->prepare(dev); suspend_report_result(dev->bus->pm->prepare, error); if (error) goto End; } - if (dev->type && dev->type->pm && dev->type->pm->prepare) { - pm_dev_dbg(dev, state, "preparing type "); - error = dev->type->pm->prepare(dev); - suspend_report_result(dev->type->pm->prepare, error); - if (error) - goto End; + if (dev->pwr_domain && dev->pwr_domain->ops.prepare) { + pm_dev_dbg(dev, state, "preparing power domain "); + dev->pwr_domain->ops.prepare(dev); } - if (dev->class && dev->class->pm && dev->class->pm->prepare) { - pm_dev_dbg(dev, state, "preparing class "); - error = dev->class->pm->prepare(dev); - suspend_report_result(dev->class->pm->prepare, error); - } End: device_unlock(dev); @@ -1005,12 +1019,9 @@ static int dpm_prepare(pm_message_t state) if (pm_runtime_barrier(dev) && device_may_wakeup(dev)) pm_wakeup_event(dev, 0); - if (pm_wakeup_pending()) { - pm_runtime_put_sync(dev); - error = -EBUSY; - } else { - error = device_prepare(dev, state); - } + pm_runtime_put_sync(dev); + error = pm_wakeup_pending() ? + -EBUSY : device_prepare(dev, state); mutex_lock(&dpm_list_mtx); if (error) { |