aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/power/disk.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/power/disk.c')
-rw-r--r--kernel/power/disk.c138
1 files changed, 85 insertions, 53 deletions
diff --git a/kernel/power/disk.c b/kernel/power/disk.c
index 4a4a206b1979..e886d1332a10 100644
--- a/kernel/power/disk.c
+++ b/kernel/power/disk.c
@@ -214,7 +214,7 @@ static int create_image(int platform_mode)
214 return error; 214 return error;
215 215
216 device_pm_lock(); 216 device_pm_lock();
217 local_irq_disable(); 217
218 /* At this point, device_suspend() has been called, but *not* 218 /* At this point, device_suspend() has been called, but *not*
219 * device_power_down(). We *must* call device_power_down() now. 219 * device_power_down(). We *must* call device_power_down() now.
220 * Otherwise, drivers for some devices (e.g. interrupt controllers) 220 * Otherwise, drivers for some devices (e.g. interrupt controllers)
@@ -225,13 +225,25 @@ static int create_image(int platform_mode)
225 if (error) { 225 if (error) {
226 printk(KERN_ERR "PM: Some devices failed to power down, " 226 printk(KERN_ERR "PM: Some devices failed to power down, "
227 "aborting hibernation\n"); 227 "aborting hibernation\n");
228 goto Enable_irqs; 228 goto Unlock;
229 } 229 }
230
231 error = platform_pre_snapshot(platform_mode);
232 if (error || hibernation_test(TEST_PLATFORM))
233 goto Platform_finish;
234
235 error = disable_nonboot_cpus();
236 if (error || hibernation_test(TEST_CPUS)
237 || hibernation_testmode(HIBERNATION_TEST))
238 goto Enable_cpus;
239
240 local_irq_disable();
241
230 sysdev_suspend(PMSG_FREEZE); 242 sysdev_suspend(PMSG_FREEZE);
231 if (error) { 243 if (error) {
232 printk(KERN_ERR "PM: Some devices failed to power down, " 244 printk(KERN_ERR "PM: Some devices failed to power down, "
233 "aborting hibernation\n"); 245 "aborting hibernation\n");
234 goto Power_up_devices; 246 goto Enable_irqs;
235 } 247 }
236 248
237 if (hibernation_test(TEST_CORE)) 249 if (hibernation_test(TEST_CORE))
@@ -247,17 +259,28 @@ static int create_image(int platform_mode)
247 restore_processor_state(); 259 restore_processor_state();
248 if (!in_suspend) 260 if (!in_suspend)
249 platform_leave(platform_mode); 261 platform_leave(platform_mode);
262
250 Power_up: 263 Power_up:
251 sysdev_resume(); 264 sysdev_resume();
252 /* NOTE: device_power_up() is just a resume() for devices 265 /* NOTE: device_power_up() is just a resume() for devices
253 * that suspended with irqs off ... no overall powerup. 266 * that suspended with irqs off ... no overall powerup.
254 */ 267 */
255 Power_up_devices: 268
256 device_power_up(in_suspend ?
257 (error ? PMSG_RECOVER : PMSG_THAW) : PMSG_RESTORE);
258 Enable_irqs: 269 Enable_irqs:
259 local_irq_enable(); 270 local_irq_enable();
271
272 Enable_cpus:
273 enable_nonboot_cpus();
274
275 Platform_finish:
276 platform_finish(platform_mode);
277
278 device_power_up(in_suspend ?
279 (error ? PMSG_RECOVER : PMSG_THAW) : PMSG_RESTORE);
280
281 Unlock:
260 device_pm_unlock(); 282 device_pm_unlock();
283
261 return error; 284 return error;
262} 285}
263 286
@@ -291,25 +314,9 @@ int hibernation_snapshot(int platform_mode)
291 if (hibernation_test(TEST_DEVICES)) 314 if (hibernation_test(TEST_DEVICES))
292 goto Recover_platform; 315 goto Recover_platform;
293 316
294 error = platform_pre_snapshot(platform_mode); 317 error = create_image(platform_mode);
295 if (error || hibernation_test(TEST_PLATFORM)) 318 /* Control returns here after successful restore */
296 goto Finish;
297
298 error = disable_nonboot_cpus();
299 if (!error) {
300 if (hibernation_test(TEST_CPUS))
301 goto Enable_cpus;
302
303 if (hibernation_testmode(HIBERNATION_TEST))
304 goto Enable_cpus;
305 319
306 error = create_image(platform_mode);
307 /* Control returns here after successful restore */
308 }
309 Enable_cpus:
310 enable_nonboot_cpus();
311 Finish:
312 platform_finish(platform_mode);
313 Resume_devices: 320 Resume_devices:
314 device_resume(in_suspend ? 321 device_resume(in_suspend ?
315 (error ? PMSG_RECOVER : PMSG_THAW) : PMSG_RESTORE); 322 (error ? PMSG_RECOVER : PMSG_THAW) : PMSG_RESTORE);
@@ -331,19 +338,33 @@ int hibernation_snapshot(int platform_mode)
331 * kernel. 338 * kernel.
332 */ 339 */
333 340
334static int resume_target_kernel(void) 341static int resume_target_kernel(bool platform_mode)
335{ 342{
336 int error; 343 int error;
337 344
338 device_pm_lock(); 345 device_pm_lock();
339 local_irq_disable(); 346
340 error = device_power_down(PMSG_QUIESCE); 347 error = device_power_down(PMSG_QUIESCE);
341 if (error) { 348 if (error) {
342 printk(KERN_ERR "PM: Some devices failed to power down, " 349 printk(KERN_ERR "PM: Some devices failed to power down, "
343 "aborting resume\n"); 350 "aborting resume\n");
344 goto Enable_irqs; 351 goto Unlock;
345 } 352 }
346 sysdev_suspend(PMSG_QUIESCE); 353
354 error = platform_pre_restore(platform_mode);
355 if (error)
356 goto Cleanup;
357
358 error = disable_nonboot_cpus();
359 if (error)
360 goto Enable_cpus;
361
362 local_irq_disable();
363
364 error = sysdev_suspend(PMSG_QUIESCE);
365 if (error)
366 goto Enable_irqs;
367
347 /* We'll ignore saved state, but this gets preempt count (etc) right */ 368 /* We'll ignore saved state, but this gets preempt count (etc) right */
348 save_processor_state(); 369 save_processor_state();
349 error = restore_highmem(); 370 error = restore_highmem();
@@ -366,11 +387,23 @@ static int resume_target_kernel(void)
366 swsusp_free(); 387 swsusp_free();
367 restore_processor_state(); 388 restore_processor_state();
368 touch_softlockup_watchdog(); 389 touch_softlockup_watchdog();
390
369 sysdev_resume(); 391 sysdev_resume();
370 device_power_up(PMSG_RECOVER); 392
371 Enable_irqs: 393 Enable_irqs:
372 local_irq_enable(); 394 local_irq_enable();
395
396 Enable_cpus:
397 enable_nonboot_cpus();
398
399 Cleanup:
400 platform_restore_cleanup(platform_mode);
401
402 device_power_up(PMSG_RECOVER);
403
404 Unlock:
373 device_pm_unlock(); 405 device_pm_unlock();
406
374 return error; 407 return error;
375} 408}
376 409
@@ -390,19 +423,10 @@ int hibernation_restore(int platform_mode)
390 pm_prepare_console(); 423 pm_prepare_console();
391 suspend_console(); 424 suspend_console();
392 error = device_suspend(PMSG_QUIESCE); 425 error = device_suspend(PMSG_QUIESCE);
393 if (error)
394 goto Finish;
395
396 error = platform_pre_restore(platform_mode);
397 if (!error) { 426 if (!error) {
398 error = disable_nonboot_cpus(); 427 error = resume_target_kernel(platform_mode);
399 if (!error) 428 device_resume(PMSG_RECOVER);
400 error = resume_target_kernel();
401 enable_nonboot_cpus();
402 } 429 }
403 platform_restore_cleanup(platform_mode);
404 device_resume(PMSG_RECOVER);
405 Finish:
406 resume_console(); 430 resume_console();
407 pm_restore_console(); 431 pm_restore_console();
408 return error; 432 return error;
@@ -438,38 +462,46 @@ int hibernation_platform_enter(void)
438 goto Resume_devices; 462 goto Resume_devices;
439 } 463 }
440 464
465 device_pm_lock();
466
467 error = device_power_down(PMSG_HIBERNATE);
468 if (error)
469 goto Unlock;
470
441 error = hibernation_ops->prepare(); 471 error = hibernation_ops->prepare();
442 if (error) 472 if (error)
443 goto Resume_devices; 473 goto Platofrm_finish;
444 474
445 error = disable_nonboot_cpus(); 475 error = disable_nonboot_cpus();
446 if (error) 476 if (error)
447 goto Finish; 477 goto Platofrm_finish;
448 478
449 device_pm_lock();
450 local_irq_disable(); 479 local_irq_disable();
451 error = device_power_down(PMSG_HIBERNATE); 480 sysdev_suspend(PMSG_HIBERNATE);
452 if (!error) { 481 hibernation_ops->enter();
453 sysdev_suspend(PMSG_HIBERNATE); 482 /* We should never get here */
454 hibernation_ops->enter(); 483 while (1);
455 /* We should never get here */
456 while (1);
457 }
458 local_irq_enable();
459 device_pm_unlock();
460 484
461 /* 485 /*
462 * We don't need to reenable the nonboot CPUs or resume consoles, since 486 * We don't need to reenable the nonboot CPUs or resume consoles, since
463 * the system is going to be halted anyway. 487 * the system is going to be halted anyway.
464 */ 488 */
465 Finish: 489 Platofrm_finish:
466 hibernation_ops->finish(); 490 hibernation_ops->finish();
491
492 device_power_up(PMSG_RESTORE);
493
494 Unlock:
495 device_pm_unlock();
496
467 Resume_devices: 497 Resume_devices:
468 entering_platform_hibernation = false; 498 entering_platform_hibernation = false;
469 device_resume(PMSG_RESTORE); 499 device_resume(PMSG_RESTORE);
470 resume_console(); 500 resume_console();
501
471 Close: 502 Close:
472 hibernation_ops->end(); 503 hibernation_ops->end();
504
473 return error; 505 return error;
474} 506}
475 507