|
@@ -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) {
|