diff options
author | Rafael J. Wysocki <rjw@sisk.pl> | 2011-07-15 23:59:25 +0200 |
---|---|---|
committer | Rafael J. Wysocki <rjw@sisk.pl> | 2011-07-15 23:59:25 +0200 |
commit | 7ae033cc0dfce68d8e0c83aca60837cf2bf0d2e6 (patch) | |
tree | 91bb3b8ae2790c7fef06b1832a7df61ae496a77a /drivers/base/power/main.c | |
parent | ba1389d74f34c0c6e95cc135a332cd29c29d9c20 (diff) | |
parent | c8c9fda5069456eb9e0e403c19764b2e257802e1 (diff) |
Merge branch 'pm-runtime' into for-linus
* pm-runtime:
OMAP: PM: disable idle on suspend for GPIO and UART
OMAP: PM: omap_device: add API to disable idle on suspend
OMAP: PM: omap_device: add system PM methods for PM domain handling
OMAP: PM: omap_device: conditionally use PM domain runtime helpers
PM / Runtime: Add new helper function: pm_runtime_status_suspended()
PM / Runtime: Consistent utilization of deferred_resume
PM / Runtime: Prevent runtime_resume from racing with probe
PM / Runtime: Replace "run-time" with "runtime" in documentation
PM / Runtime: Improve documentation of enable, disable and barrier
PM: Limit race conditions between runtime PM and system sleep (v2)
PCI / PM: Detect early wakeup in pci_pm_prepare()
PM / Runtime: Return special error code if runtime PM is disabled
PM / Runtime: Update documentation of interactions with system sleep
Diffstat (limited to 'drivers/base/power/main.c')
-rw-r--r-- | drivers/base/power/main.c | 35 |
1 files changed, 23 insertions, 12 deletions
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index 85b591a5429..a85459126bc 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c @@ -505,6 +505,7 @@ static int legacy_resume(struct device *dev, int (*cb)(struct device *dev)) static int device_resume(struct device *dev, pm_message_t state, bool async) { int error = 0; + bool put = false; TRACE_DEVICE(dev); TRACE_RESUME(0); @@ -521,6 +522,9 @@ static int device_resume(struct device *dev, pm_message_t state, bool async) if (!dev->power.is_suspended) goto Unlock; + pm_runtime_enable(dev); + put = true; + if (dev->pm_domain) { pm_dev_dbg(dev, state, "power domain "); error = pm_op(dev, &dev->pm_domain->ops, state); @@ -563,6 +567,10 @@ static int device_resume(struct device *dev, pm_message_t state, bool async) complete_all(&dev->power.completion); TRACE_RESUME(error); + + if (put) + pm_runtime_put_sync(dev); + return error; } @@ -843,16 +851,22 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async) int error = 0; dpm_wait_for_children(dev, async); - device_lock(dev); if (async_error) - goto Unlock; + return 0; + + pm_runtime_get_noresume(dev); + if (pm_runtime_barrier(dev) && device_may_wakeup(dev)) + pm_wakeup_event(dev, 0); if (pm_wakeup_pending()) { + pm_runtime_put_sync(dev); async_error = -EBUSY; - goto Unlock; + return 0; } + device_lock(dev); + if (dev->pm_domain) { pm_dev_dbg(dev, state, "power domain "); error = pm_op(dev, &dev->pm_domain->ops, state); @@ -890,12 +904,15 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async) End: dev->power.is_suspended = !error; - Unlock: device_unlock(dev); complete_all(&dev->power.completion); - if (error) + if (error) { + pm_runtime_put_sync(dev); async_error = error; + } else if (dev->power.is_suspended) { + __pm_runtime_disable(dev, false); + } return error; } @@ -1035,13 +1052,7 @@ int dpm_prepare(pm_message_t state) get_device(dev); mutex_unlock(&dpm_list_mtx); - pm_runtime_get_noresume(dev); - if (pm_runtime_barrier(dev) && device_may_wakeup(dev)) - pm_wakeup_event(dev, 0); - - pm_runtime_put_sync(dev); - error = pm_wakeup_pending() ? - -EBUSY : device_prepare(dev, state); + error = device_prepare(dev, state); mutex_lock(&dpm_list_mtx); if (error) { |