diff options
author | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2017-07-20 20:12:10 -0400 |
---|---|---|
committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2017-07-24 17:53:46 -0400 |
commit | 9a3ebe3523cc8297301d5d95332536ad123856bf (patch) | |
tree | 2c99ca6d2ba28b7ed99702f0596683f0bb6c1052 | |
parent | 48059c095bafc2ba23da1b3fa26b6ba142cb854f (diff) |
PM / sleep: Check pm_wakeup_pending() in __device_suspend_noirq()
Restore the pm_wakeup_pending() check in __device_suspend_noirq()
removed by commit eed4d47efe95 (ACPI / sleep: Ignore spurious SCI
wakeups from suspend-to-idle) as that allows the function to return
earlier if there's a wakeup event pending already (so that it may
spend less time on carrying out operations that will be reversed
shortly anyway) and rework the main suspend-to-idle loop to take
that optimization into account.
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
-rw-r--r-- | drivers/base/power/main.c | 5 | ||||
-rw-r--r-- | kernel/power/suspend.c | 19 |
2 files changed, 21 insertions, 3 deletions
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index f64e5b819e5c..ea1732ed7a9d 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c | |||
@@ -1105,6 +1105,11 @@ static int __device_suspend_noirq(struct device *dev, pm_message_t state, bool a | |||
1105 | if (async_error) | 1105 | if (async_error) |
1106 | goto Complete; | 1106 | goto Complete; |
1107 | 1107 | ||
1108 | if (pm_wakeup_pending()) { | ||
1109 | async_error = -EBUSY; | ||
1110 | goto Complete; | ||
1111 | } | ||
1112 | |||
1108 | if (dev->power.syscore || dev->power.direct_complete) | 1113 | if (dev->power.syscore || dev->power.direct_complete) |
1109 | goto Complete; | 1114 | goto Complete; |
1110 | 1115 | ||
diff --git a/kernel/power/suspend.c b/kernel/power/suspend.c index 0c61713b6e5c..5cf232795318 100644 --- a/kernel/power/suspend.c +++ b/kernel/power/suspend.c | |||
@@ -108,19 +108,32 @@ static void s2idle_loop(void) | |||
108 | { | 108 | { |
109 | pm_pr_dbg("suspend-to-idle\n"); | 109 | pm_pr_dbg("suspend-to-idle\n"); |
110 | 110 | ||
111 | while (!dpm_suspend_noirq(PMSG_SUSPEND)) { | 111 | for (;;) { |
112 | int error; | ||
113 | |||
114 | dpm_noirq_begin(); | ||
115 | |||
112 | /* | 116 | /* |
113 | * Suspend-to-idle equals | 117 | * Suspend-to-idle equals |
114 | * frozen processes + suspended devices + idle processors. | 118 | * frozen processes + suspended devices + idle processors. |
115 | * Thus freeze_enter() should be called right after | 119 | * Thus freeze_enter() should be called right after |
116 | * all devices have been suspended. | 120 | * all devices have been suspended. |
117 | */ | 121 | */ |
118 | freeze_enter(); | 122 | error = dpm_noirq_suspend_devices(PMSG_SUSPEND); |
123 | if (!error) | ||
124 | freeze_enter(); | ||
125 | |||
126 | dpm_noirq_resume_devices(PMSG_RESUME); | ||
127 | if (error && (error != -EBUSY || !pm_wakeup_pending())) { | ||
128 | dpm_noirq_end(); | ||
129 | break; | ||
130 | } | ||
119 | 131 | ||
120 | if (freeze_ops && freeze_ops->wake) | 132 | if (freeze_ops && freeze_ops->wake) |
121 | freeze_ops->wake(); | 133 | freeze_ops->wake(); |
122 | 134 | ||
123 | dpm_resume_noirq(PMSG_RESUME); | 135 | dpm_noirq_end(); |
136 | |||
124 | if (freeze_ops && freeze_ops->sync) | 137 | if (freeze_ops && freeze_ops->sync) |
125 | freeze_ops->sync(); | 138 | freeze_ops->sync(); |
126 | 139 | ||