summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--kernel/power/suspend.c120
1 files changed, 77 insertions, 43 deletions
diff --git a/kernel/power/suspend.c b/kernel/power/suspend.c
index 83f5b3e70d95..9a071bea80eb 100644
--- a/kernel/power/suspend.c
+++ b/kernel/power/suspend.c
@@ -36,12 +36,6 @@ const char *pm_states[PM_SUSPEND_MAX];
36 36
37static const struct platform_suspend_ops *suspend_ops; 37static const struct platform_suspend_ops *suspend_ops;
38static const struct platform_freeze_ops *freeze_ops; 38static const struct platform_freeze_ops *freeze_ops;
39
40static bool need_suspend_ops(suspend_state_t state)
41{
42 return state > PM_SUSPEND_FREEZE;
43}
44
45static DECLARE_WAIT_QUEUE_HEAD(suspend_freeze_wait_head); 39static DECLARE_WAIT_QUEUE_HEAD(suspend_freeze_wait_head);
46static bool suspend_freeze_wake; 40static bool suspend_freeze_wake;
47 41
@@ -139,6 +133,65 @@ int suspend_valid_only_mem(suspend_state_t state)
139} 133}
140EXPORT_SYMBOL_GPL(suspend_valid_only_mem); 134EXPORT_SYMBOL_GPL(suspend_valid_only_mem);
141 135
136static bool sleep_state_supported(suspend_state_t state)
137{
138 return state == PM_SUSPEND_FREEZE || (suspend_ops && suspend_ops->enter);
139}
140
141static int platform_suspend_prepare(suspend_state_t state)
142{
143 return state != PM_SUSPEND_FREEZE && suspend_ops->prepare ?
144 suspend_ops->prepare() : 0;
145}
146
147static int platform_suspend_prepare_late(suspend_state_t state)
148{
149 return state != PM_SUSPEND_FREEZE && suspend_ops->prepare_late ?
150 suspend_ops->prepare_late() : 0;
151}
152
153static void platform_suspend_wake(suspend_state_t state)
154{
155 if (state != PM_SUSPEND_FREEZE && suspend_ops->wake)
156 suspend_ops->wake();
157}
158
159static void platform_suspend_finish(suspend_state_t state)
160{
161 if (state != PM_SUSPEND_FREEZE && suspend_ops->finish)
162 suspend_ops->finish();
163}
164
165static int platform_suspend_begin(suspend_state_t state)
166{
167 if (state == PM_SUSPEND_FREEZE && freeze_ops && freeze_ops->begin)
168 return freeze_ops->begin();
169 else if (suspend_ops->begin)
170 return suspend_ops->begin(state);
171 else
172 return 0;
173}
174
175static void platform_suspend_end(suspend_state_t state)
176{
177 if (state == PM_SUSPEND_FREEZE && freeze_ops && freeze_ops->end)
178 freeze_ops->end();
179 else if (suspend_ops->end)
180 suspend_ops->end();
181}
182
183static void platform_suspend_recover(suspend_state_t state)
184{
185 if (state != PM_SUSPEND_FREEZE && suspend_ops->recover)
186 suspend_ops->recover();
187}
188
189static bool platform_suspend_again(suspend_state_t state)
190{
191 return state != PM_SUSPEND_FREEZE && suspend_ops->suspend_again ?
192 suspend_ops->suspend_again() : false;
193}
194
142static int suspend_test(int level) 195static int suspend_test(int level)
143{ 196{
144#ifdef CONFIG_PM_DEBUG 197#ifdef CONFIG_PM_DEBUG
@@ -162,7 +215,7 @@ static int suspend_prepare(suspend_state_t state)
162{ 215{
163 int error; 216 int error;
164 217
165 if (need_suspend_ops(state) && (!suspend_ops || !suspend_ops->enter)) 218 if (!sleep_state_supported(state))
166 return -EPERM; 219 return -EPERM;
167 220
168 pm_prepare_console(); 221 pm_prepare_console();
@@ -208,23 +261,18 @@ static int suspend_enter(suspend_state_t state, bool *wakeup)
208{ 261{
209 int error; 262 int error;
210 263
211 if (need_suspend_ops(state) && suspend_ops->prepare) { 264 error = platform_suspend_prepare(state);
212 error = suspend_ops->prepare(); 265 if (error)
213 if (error) 266 goto Platform_finish;
214 goto Platform_finish;
215 }
216 267
217 error = dpm_suspend_end(PMSG_SUSPEND); 268 error = dpm_suspend_end(PMSG_SUSPEND);
218 if (error) { 269 if (error) {
219 printk(KERN_ERR "PM: Some devices failed to power down\n"); 270 printk(KERN_ERR "PM: Some devices failed to power down\n");
220 goto Platform_finish; 271 goto Platform_finish;
221 } 272 }
222 273 error = platform_suspend_prepare_late(state);
223 if (need_suspend_ops(state) && suspend_ops->prepare_late) { 274 if (error)
224 error = suspend_ops->prepare_late(); 275 goto Platform_wake;
225 if (error)
226 goto Platform_wake;
227 }
228 276
229 if (suspend_test(TEST_PLATFORM)) 277 if (suspend_test(TEST_PLATFORM))
230 goto Platform_wake; 278 goto Platform_wake;
@@ -272,15 +320,11 @@ static int suspend_enter(suspend_state_t state, bool *wakeup)
272 ftrace_start(); 320 ftrace_start();
273 321
274 Platform_wake: 322 Platform_wake:
275 if (need_suspend_ops(state) && suspend_ops->wake) 323 platform_suspend_wake(state);
276 suspend_ops->wake();
277
278 dpm_resume_start(PMSG_RESUME); 324 dpm_resume_start(PMSG_RESUME);
279 325
280 Platform_finish: 326 Platform_finish:
281 if (need_suspend_ops(state) && suspend_ops->finish) 327 platform_suspend_finish(state);
282 suspend_ops->finish();
283
284 return error; 328 return error;
285} 329}
286 330
@@ -293,18 +337,13 @@ int suspend_devices_and_enter(suspend_state_t state)
293 int error; 337 int error;
294 bool wakeup = false; 338 bool wakeup = false;
295 339
296 if (need_suspend_ops(state) && !suspend_ops) 340 if (!sleep_state_supported(state))
297 return -ENOSYS; 341 return -ENOSYS;
298 342
299 if (need_suspend_ops(state) && suspend_ops->begin) { 343 error = platform_suspend_begin(state);
300 error = suspend_ops->begin(state); 344 if (error)
301 if (error) 345 goto Close;
302 goto Close; 346
303 } else if (state == PM_SUSPEND_FREEZE && freeze_ops && freeze_ops->begin) {
304 error = freeze_ops->begin();
305 if (error)
306 goto Close;
307 }
308 suspend_console(); 347 suspend_console();
309 suspend_test_start(); 348 suspend_test_start();
310 error = dpm_suspend_start(PMSG_SUSPEND); 349 error = dpm_suspend_start(PMSG_SUSPEND);
@@ -318,25 +357,20 @@ int suspend_devices_and_enter(suspend_state_t state)
318 357
319 do { 358 do {
320 error = suspend_enter(state, &wakeup); 359 error = suspend_enter(state, &wakeup);
321 } while (!error && !wakeup && need_suspend_ops(state) 360 } while (!error && !wakeup && platform_suspend_again(state));
322 && suspend_ops->suspend_again && suspend_ops->suspend_again());
323 361
324 Resume_devices: 362 Resume_devices:
325 suspend_test_start(); 363 suspend_test_start();
326 dpm_resume_end(PMSG_RESUME); 364 dpm_resume_end(PMSG_RESUME);
327 suspend_test_finish("resume devices"); 365 suspend_test_finish("resume devices");
328 resume_console(); 366 resume_console();
329 Close:
330 if (need_suspend_ops(state) && suspend_ops->end)
331 suspend_ops->end();
332 else if (state == PM_SUSPEND_FREEZE && freeze_ops && freeze_ops->end)
333 freeze_ops->end();
334 367
368 Close:
369 platform_suspend_end(state);
335 return error; 370 return error;
336 371
337 Recover_platform: 372 Recover_platform:
338 if (need_suspend_ops(state) && suspend_ops->recover) 373 platform_suspend_recover(state);
339 suspend_ops->recover();
340 goto Resume_devices; 374 goto Resume_devices;
341} 375}
342 376