aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'kernel')
-rw-r--r--kernel/power/disk.c109
1 files changed, 61 insertions, 48 deletions
diff --git a/kernel/power/disk.c b/kernel/power/disk.c
index 320bb0949bdf..e886d1332a10 100644
--- a/kernel/power/disk.c
+++ b/kernel/power/disk.c
@@ -228,13 +228,22 @@ static int create_image(int platform_mode)
228 goto Unlock; 228 goto Unlock;
229 } 229 }
230 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
231 local_irq_disable(); 240 local_irq_disable();
232 241
233 sysdev_suspend(PMSG_FREEZE); 242 sysdev_suspend(PMSG_FREEZE);
234 if (error) { 243 if (error) {
235 printk(KERN_ERR "PM: Some devices failed to power down, " 244 printk(KERN_ERR "PM: Some devices failed to power down, "
236 "aborting hibernation\n"); 245 "aborting hibernation\n");
237 goto Power_up_devices; 246 goto Enable_irqs;
238 } 247 }
239 248
240 if (hibernation_test(TEST_CORE)) 249 if (hibernation_test(TEST_CORE))
@@ -250,15 +259,22 @@ static int create_image(int platform_mode)
250 restore_processor_state(); 259 restore_processor_state();
251 if (!in_suspend) 260 if (!in_suspend)
252 platform_leave(platform_mode); 261 platform_leave(platform_mode);
262
253 Power_up: 263 Power_up:
254 sysdev_resume(); 264 sysdev_resume();
255 /* NOTE: device_power_up() is just a resume() for devices 265 /* NOTE: device_power_up() is just a resume() for devices
256 * that suspended with irqs off ... no overall powerup. 266 * that suspended with irqs off ... no overall powerup.
257 */ 267 */
258 268
259 Power_up_devices: 269 Enable_irqs:
260 local_irq_enable(); 270 local_irq_enable();
261 271
272 Enable_cpus:
273 enable_nonboot_cpus();
274
275 Platform_finish:
276 platform_finish(platform_mode);
277
262 device_power_up(in_suspend ? 278 device_power_up(in_suspend ?
263 (error ? PMSG_RECOVER : PMSG_THAW) : PMSG_RESTORE); 279 (error ? PMSG_RECOVER : PMSG_THAW) : PMSG_RESTORE);
264 280
@@ -298,25 +314,9 @@ int hibernation_snapshot(int platform_mode)
298 if (hibernation_test(TEST_DEVICES)) 314 if (hibernation_test(TEST_DEVICES))
299 goto Recover_platform; 315 goto Recover_platform;
300 316
301 error = platform_pre_snapshot(platform_mode); 317 error = create_image(platform_mode);
302 if (error || hibernation_test(TEST_PLATFORM)) 318 /* Control returns here after successful restore */
303 goto Finish;
304
305 error = disable_nonboot_cpus();
306 if (!error) {
307 if (hibernation_test(TEST_CPUS))
308 goto Enable_cpus;
309
310 if (hibernation_testmode(HIBERNATION_TEST))
311 goto Enable_cpus;
312 319
313 error = create_image(platform_mode);
314 /* Control returns here after successful restore */
315 }
316 Enable_cpus:
317 enable_nonboot_cpus();
318 Finish:
319 platform_finish(platform_mode);
320 Resume_devices: 320 Resume_devices:
321 device_resume(in_suspend ? 321 device_resume(in_suspend ?
322 (error ? PMSG_RECOVER : PMSG_THAW) : PMSG_RESTORE); 322 (error ? PMSG_RECOVER : PMSG_THAW) : PMSG_RESTORE);
@@ -338,7 +338,7 @@ int hibernation_snapshot(int platform_mode)
338 * kernel. 338 * kernel.
339 */ 339 */
340 340
341static int resume_target_kernel(void) 341static int resume_target_kernel(bool platform_mode)
342{ 342{
343 int error; 343 int error;
344 344
@@ -351,9 +351,20 @@ static int resume_target_kernel(void)
351 goto Unlock; 351 goto Unlock;
352 } 352 }
353 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
354 local_irq_disable(); 362 local_irq_disable();
355 363
356 sysdev_suspend(PMSG_QUIESCE); 364 error = sysdev_suspend(PMSG_QUIESCE);
365 if (error)
366 goto Enable_irqs;
367
357 /* 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 */
358 save_processor_state(); 369 save_processor_state();
359 error = restore_highmem(); 370 error = restore_highmem();
@@ -379,8 +390,15 @@ static int resume_target_kernel(void)
379 390
380 sysdev_resume(); 391 sysdev_resume();
381 392
393 Enable_irqs:
382 local_irq_enable(); 394 local_irq_enable();
383 395
396 Enable_cpus:
397 enable_nonboot_cpus();
398
399 Cleanup:
400 platform_restore_cleanup(platform_mode);
401
384 device_power_up(PMSG_RECOVER); 402 device_power_up(PMSG_RECOVER);
385 403
386 Unlock: 404 Unlock:
@@ -405,19 +423,10 @@ int hibernation_restore(int platform_mode)
405 pm_prepare_console(); 423 pm_prepare_console();
406 suspend_console(); 424 suspend_console();
407 error = device_suspend(PMSG_QUIESCE); 425 error = device_suspend(PMSG_QUIESCE);
408 if (error)
409 goto Finish;
410
411 error = platform_pre_restore(platform_mode);
412 if (!error) { 426 if (!error) {
413 error = disable_nonboot_cpus(); 427 error = resume_target_kernel(platform_mode);
414 if (!error) 428 device_resume(PMSG_RECOVER);
415 error = resume_target_kernel();
416 enable_nonboot_cpus();
417 } 429 }
418 platform_restore_cleanup(platform_mode);
419 device_resume(PMSG_RECOVER);
420 Finish:
421 resume_console(); 430 resume_console();
422 pm_restore_console(); 431 pm_restore_console();
423 return error; 432 return error;
@@ -453,34 +462,38 @@ int hibernation_platform_enter(void)
453 goto Resume_devices; 462 goto Resume_devices;
454 } 463 }
455 464
465 device_pm_lock();
466
467 error = device_power_down(PMSG_HIBERNATE);
468 if (error)
469 goto Unlock;
470
456 error = hibernation_ops->prepare(); 471 error = hibernation_ops->prepare();
457 if (error) 472 if (error)
458 goto Resume_devices; 473 goto Platofrm_finish;
459 474
460 error = disable_nonboot_cpus(); 475 error = disable_nonboot_cpus();
461 if (error) 476 if (error)
462 goto Finish; 477 goto Platofrm_finish;
463
464 device_pm_lock();
465
466 error = device_power_down(PMSG_HIBERNATE);
467 if (!error) {
468 local_irq_disable();
469 sysdev_suspend(PMSG_HIBERNATE);
470 hibernation_ops->enter();
471 /* We should never get here */
472 while (1);
473 }
474 478
475 device_pm_unlock(); 479 local_irq_disable();
480 sysdev_suspend(PMSG_HIBERNATE);
481 hibernation_ops->enter();
482 /* We should never get here */
483 while (1);
476 484
477 /* 485 /*
478 * 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
479 * the system is going to be halted anyway. 487 * the system is going to be halted anyway.
480 */ 488 */
481 Finish: 489 Platofrm_finish:
482 hibernation_ops->finish(); 490 hibernation_ops->finish();
483 491
492 device_power_up(PMSG_RESTORE);
493
494 Unlock:
495 device_pm_unlock();
496
484 Resume_devices: 497 Resume_devices:
485 entering_platform_hibernation = false; 498 entering_platform_hibernation = false;
486 device_resume(PMSG_RESTORE); 499 device_resume(PMSG_RESTORE);