diff options
author | Rafael J. Wysocki <rjw@sisk.pl> | 2012-09-24 07:31:38 -0400 |
---|---|---|
committer | Rafael J. Wysocki <rjw@sisk.pl> | 2012-09-24 07:31:38 -0400 |
commit | 057d51a1268fe4be039db8ff0791fcfcb63a4f1b (patch) | |
tree | 50b7395aa526c5be9f3ae75836b5ad364db04877 /drivers/base/power/main.c | |
parent | 071f58279f274f749c4109aef86d899766014139 (diff) | |
parent | 88d26136a256576e444db312179e17af6dd0ea87 (diff) |
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/power/main.c')
-rw-r--r-- | drivers/base/power/main.c | 31 |
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) | |||
570 | pm_callback_t callback = NULL; | 570 | pm_callback_t callback = NULL; |
571 | char *info = NULL; | 571 | char *info = NULL; |
572 | int error = 0; | 572 | int error = 0; |
573 | bool put = false; | ||
574 | 573 | ||
575 | TRACE_DEVICE(dev); | 574 | TRACE_DEVICE(dev); |
576 | TRACE_RESUME(0); | 575 | TRACE_RESUME(0); |
@@ -591,7 +590,6 @@ static int device_resume(struct device *dev, pm_message_t state, bool async) | |||
591 | goto Unlock; | 590 | goto Unlock; |
592 | 591 | ||
593 | pm_runtime_enable(dev); | 592 | pm_runtime_enable(dev); |
594 | put = true; | ||
595 | 593 | ||
596 | if (dev->pm_domain) { | 594 | if (dev->pm_domain) { |
597 | info = "power domain "; | 595 | info = "power domain "; |
@@ -646,9 +644,6 @@ static int device_resume(struct device *dev, pm_message_t state, bool async) | |||
646 | 644 | ||
647 | TRACE_RESUME(error); | 645 | TRACE_RESUME(error); |
648 | 646 | ||
649 | if (put) | ||
650 | pm_runtime_put_sync(dev); | ||
651 | |||
652 | return error; | 647 | return error; |
653 | } | 648 | } |
654 | 649 | ||
@@ -762,6 +757,8 @@ static void device_complete(struct device *dev, pm_message_t state) | |||
762 | } | 757 | } |
763 | 758 | ||
764 | device_unlock(dev); | 759 | device_unlock(dev); |
760 | |||
761 | pm_runtime_put_sync(dev); | ||
765 | } | 762 | } |
766 | 763 | ||
767 | /** | 764 | /** |
@@ -1015,7 +1012,7 @@ int dpm_suspend_end(pm_message_t state) | |||
1015 | 1012 | ||
1016 | error = dpm_suspend_noirq(state); | 1013 | error = dpm_suspend_noirq(state); |
1017 | if (error) { | 1014 | if (error) { |
1018 | dpm_resume_early(state); | 1015 | dpm_resume_early(resume_event(state)); |
1019 | return error; | 1016 | return error; |
1020 | } | 1017 | } |
1021 | 1018 | ||
@@ -1062,12 +1059,16 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async) | |||
1062 | if (async_error) | 1059 | if (async_error) |
1063 | goto Complete; | 1060 | goto Complete; |
1064 | 1061 | ||
1065 | pm_runtime_get_noresume(dev); | 1062 | /* |
1063 | * If a device configured to wake up the system from sleep states | ||
1064 | * has been suspended at run time and there's a resume request pending | ||
1065 | * for it, this is equivalent to the device signaling wakeup, so the | ||
1066 | * system suspend operation should be aborted. | ||
1067 | */ | ||
1066 | if (pm_runtime_barrier(dev) && device_may_wakeup(dev)) | 1068 | if (pm_runtime_barrier(dev) && device_may_wakeup(dev)) |
1067 | pm_wakeup_event(dev, 0); | 1069 | pm_wakeup_event(dev, 0); |
1068 | 1070 | ||
1069 | if (pm_wakeup_pending()) { | 1071 | if (pm_wakeup_pending()) { |
1070 | pm_runtime_put_sync(dev); | ||
1071 | async_error = -EBUSY; | 1072 | async_error = -EBUSY; |
1072 | goto Complete; | 1073 | goto Complete; |
1073 | } | 1074 | } |
@@ -1133,12 +1134,10 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async) | |||
1133 | Complete: | 1134 | Complete: |
1134 | complete_all(&dev->power.completion); | 1135 | complete_all(&dev->power.completion); |
1135 | 1136 | ||
1136 | if (error) { | 1137 | if (error) |
1137 | pm_runtime_put_sync(dev); | ||
1138 | async_error = error; | 1138 | async_error = error; |
1139 | } else if (dev->power.is_suspended) { | 1139 | else if (dev->power.is_suspended) |
1140 | __pm_runtime_disable(dev, false); | 1140 | __pm_runtime_disable(dev, false); |
1141 | } | ||
1142 | 1141 | ||
1143 | return error; | 1142 | return error; |
1144 | } | 1143 | } |
@@ -1234,6 +1233,14 @@ static int device_prepare(struct device *dev, pm_message_t state) | |||
1234 | if (dev->power.syscore) | 1233 | if (dev->power.syscore) |
1235 | return 0; | 1234 | return 0; |
1236 | 1235 | ||
1236 | /* | ||
1237 | * If a device's parent goes into runtime suspend at the wrong time, | ||
1238 | * it won't be possible to resume the device. To prevent this we | ||
1239 | * block runtime suspend here, during the prepare phase, and allow | ||
1240 | * it again during the complete phase. | ||
1241 | */ | ||
1242 | pm_runtime_get_noresume(dev); | ||
1243 | |||
1237 | device_lock(dev); | 1244 | device_lock(dev); |
1238 | 1245 | ||
1239 | dev->power.wakeup_path = device_may_wakeup(dev); | 1246 | dev->power.wakeup_path = device_may_wakeup(dev); |