summaryrefslogtreecommitdiffstats
path: root/drivers/base
diff options
context:
space:
mode:
authorRafael J. Wysocki <rjw@sisk.pl>2012-09-24 13:31:38 +0200
committerRafael J. Wysocki <rjw@sisk.pl>2012-09-24 13:31:38 +0200
commit057d51a1268fe4be039db8ff0791fcfcb63a4f1b (patch)
tree50b7395aa526c5be9f3ae75836b5ad364db04877 /drivers/base
parentMerge branch 'pm-runtime' (diff)
parentPM: Prevent runtime suspend during system resume (diff)
downloadlinux-057d51a1268fe4be039db8ff0791fcfcb63a4f1b.tar.xz
linux-057d51a1268fe4be039db8ff0791fcfcb63a4f1b.zip
Merge branch 'pm-sleep'
* pm-sleep: PM: Prevent runtime suspend during system resume PM / Sleep: use resume event when call dpm_resume_early Conflicts: drivers/base/power/main.c (trivial)
Diffstat (limited to 'drivers/base')
-rw-r--r--drivers/base/power/main.c31
1 files changed, 19 insertions, 12 deletions
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c
index 57f5814c2732..008e6786ae79 100644
--- a/drivers/base/power/main.c
+++ b/drivers/base/power/main.c
@@ -570,7 +570,6 @@ static int device_resume(struct device *dev, pm_message_t state, bool async)
pm_callback_t callback = NULL;
char *info = NULL;
int error = 0;
- bool put = false;
TRACE_DEVICE(dev);
TRACE_RESUME(0);
@@ -591,7 +590,6 @@ static int device_resume(struct device *dev, pm_message_t state, bool async)
goto Unlock;
pm_runtime_enable(dev);
- put = true;
if (dev->pm_domain) {
info = "power domain ";
@@ -646,9 +644,6 @@ static int device_resume(struct device *dev, pm_message_t state, bool async)
TRACE_RESUME(error);
- if (put)
- pm_runtime_put_sync(dev);
-
return error;
}
@@ -762,6 +757,8 @@ static void device_complete(struct device *dev, pm_message_t state)
}
device_unlock(dev);
+
+ pm_runtime_put_sync(dev);
}
/**
@@ -1015,7 +1012,7 @@ int dpm_suspend_end(pm_message_t state)
error = dpm_suspend_noirq(state);
if (error) {
- dpm_resume_early(state);
+ dpm_resume_early(resume_event(state));
return error;
}
@@ -1062,12 +1059,16 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async)
if (async_error)
goto Complete;
- pm_runtime_get_noresume(dev);
+ /*
+ * If a device configured to wake up the system from sleep states
+ * has been suspended at run time and there's a resume request pending
+ * for it, this is equivalent to the device signaling wakeup, so the
+ * system suspend operation should be aborted.
+ */
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 Complete;
}
@@ -1133,12 +1134,10 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async)
Complete:
complete_all(&dev->power.completion);
- if (error) {
- pm_runtime_put_sync(dev);
+ if (error)
async_error = error;
- } else if (dev->power.is_suspended) {
+ else if (dev->power.is_suspended)
__pm_runtime_disable(dev, false);
- }
return error;
}
@@ -1234,6 +1233,14 @@ static int device_prepare(struct device *dev, pm_message_t state)
if (dev->power.syscore)
return 0;
+ /*
+ * If a device's parent goes into runtime suspend at the wrong time,
+ * it won't be possible to resume the device. To prevent this we
+ * block runtime suspend here, during the prepare phase, and allow
+ * it again during the complete phase.
+ */
+ pm_runtime_get_noresume(dev);
+
device_lock(dev);
dev->power.wakeup_path = device_may_wakeup(dev);