diff options
Diffstat (limited to 'kernel/power/hibernate.c')
-rw-r--r-- | kernel/power/hibernate.c | 59 |
1 files changed, 24 insertions, 35 deletions
diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c index 6d6d28870335..e09dfbfeecee 100644 --- a/kernel/power/hibernate.c +++ b/kernel/power/hibernate.c | |||
@@ -16,7 +16,6 @@ | |||
16 | #include <linux/string.h> | 16 | #include <linux/string.h> |
17 | #include <linux/device.h> | 17 | #include <linux/device.h> |
18 | #include <linux/async.h> | 18 | #include <linux/async.h> |
19 | #include <linux/kmod.h> | ||
20 | #include <linux/delay.h> | 19 | #include <linux/delay.h> |
21 | #include <linux/fs.h> | 20 | #include <linux/fs.h> |
22 | #include <linux/mount.h> | 21 | #include <linux/mount.h> |
@@ -245,8 +244,8 @@ void swsusp_show_speed(struct timeval *start, struct timeval *stop, | |||
245 | * create_image - Create a hibernation image. | 244 | * create_image - Create a hibernation image. |
246 | * @platform_mode: Whether or not to use the platform driver. | 245 | * @platform_mode: Whether or not to use the platform driver. |
247 | * | 246 | * |
248 | * Execute device drivers' .freeze_noirq() callbacks, create a hibernation image | 247 | * Execute device drivers' "late" and "noirq" freeze callbacks, create a |
249 | * and execute the drivers' .thaw_noirq() callbacks. | 248 | * hibernation image and run the drivers' "noirq" and "early" thaw callbacks. |
250 | * | 249 | * |
251 | * Control reappears in this routine after the subsequent restore. | 250 | * Control reappears in this routine after the subsequent restore. |
252 | */ | 251 | */ |
@@ -254,7 +253,7 @@ static int create_image(int platform_mode) | |||
254 | { | 253 | { |
255 | int error; | 254 | int error; |
256 | 255 | ||
257 | error = dpm_suspend_noirq(PMSG_FREEZE); | 256 | error = dpm_suspend_end(PMSG_FREEZE); |
258 | if (error) { | 257 | if (error) { |
259 | printk(KERN_ERR "PM: Some devices failed to power down, " | 258 | printk(KERN_ERR "PM: Some devices failed to power down, " |
260 | "aborting hibernation\n"); | 259 | "aborting hibernation\n"); |
@@ -306,7 +305,7 @@ static int create_image(int platform_mode) | |||
306 | Platform_finish: | 305 | Platform_finish: |
307 | platform_finish(platform_mode); | 306 | platform_finish(platform_mode); |
308 | 307 | ||
309 | dpm_resume_noirq(in_suspend ? | 308 | dpm_resume_start(in_suspend ? |
310 | (error ? PMSG_RECOVER : PMSG_THAW) : PMSG_RESTORE); | 309 | (error ? PMSG_RECOVER : PMSG_THAW) : PMSG_RESTORE); |
311 | 310 | ||
312 | return error; | 311 | return error; |
@@ -343,13 +342,13 @@ int hibernation_snapshot(int platform_mode) | |||
343 | * successful freezer test. | 342 | * successful freezer test. |
344 | */ | 343 | */ |
345 | freezer_test_done = true; | 344 | freezer_test_done = true; |
346 | goto Cleanup; | 345 | goto Thaw; |
347 | } | 346 | } |
348 | 347 | ||
349 | error = dpm_prepare(PMSG_FREEZE); | 348 | error = dpm_prepare(PMSG_FREEZE); |
350 | if (error) { | 349 | if (error) { |
351 | dpm_complete(PMSG_RECOVER); | 350 | dpm_complete(PMSG_RECOVER); |
352 | goto Cleanup; | 351 | goto Thaw; |
353 | } | 352 | } |
354 | 353 | ||
355 | suspend_console(); | 354 | suspend_console(); |
@@ -385,6 +384,8 @@ int hibernation_snapshot(int platform_mode) | |||
385 | platform_end(platform_mode); | 384 | platform_end(platform_mode); |
386 | return error; | 385 | return error; |
387 | 386 | ||
387 | Thaw: | ||
388 | thaw_kernel_threads(); | ||
388 | Cleanup: | 389 | Cleanup: |
389 | swsusp_free(); | 390 | swsusp_free(); |
390 | goto Close; | 391 | goto Close; |
@@ -394,16 +395,16 @@ int hibernation_snapshot(int platform_mode) | |||
394 | * resume_target_kernel - Restore system state from a hibernation image. | 395 | * resume_target_kernel - Restore system state from a hibernation image. |
395 | * @platform_mode: Whether or not to use the platform driver. | 396 | * @platform_mode: Whether or not to use the platform driver. |
396 | * | 397 | * |
397 | * Execute device drivers' .freeze_noirq() callbacks, restore the contents of | 398 | * Execute device drivers' "noirq" and "late" freeze callbacks, restore the |
398 | * highmem that have not been restored yet from the image and run the low-level | 399 | * contents of highmem that have not been restored yet from the image and run |
399 | * code that will restore the remaining contents of memory and switch to the | 400 | * the low-level code that will restore the remaining contents of memory and |
400 | * just restored target kernel. | 401 | * switch to the just restored target kernel. |
401 | */ | 402 | */ |
402 | static int resume_target_kernel(bool platform_mode) | 403 | static int resume_target_kernel(bool platform_mode) |
403 | { | 404 | { |
404 | int error; | 405 | int error; |
405 | 406 | ||
406 | error = dpm_suspend_noirq(PMSG_QUIESCE); | 407 | error = dpm_suspend_end(PMSG_QUIESCE); |
407 | if (error) { | 408 | if (error) { |
408 | printk(KERN_ERR "PM: Some devices failed to power down, " | 409 | printk(KERN_ERR "PM: Some devices failed to power down, " |
409 | "aborting resume\n"); | 410 | "aborting resume\n"); |
@@ -460,7 +461,7 @@ static int resume_target_kernel(bool platform_mode) | |||
460 | Cleanup: | 461 | Cleanup: |
461 | platform_restore_cleanup(platform_mode); | 462 | platform_restore_cleanup(platform_mode); |
462 | 463 | ||
463 | dpm_resume_noirq(PMSG_RECOVER); | 464 | dpm_resume_start(PMSG_RECOVER); |
464 | 465 | ||
465 | return error; | 466 | return error; |
466 | } | 467 | } |
@@ -518,7 +519,7 @@ int hibernation_platform_enter(void) | |||
518 | goto Resume_devices; | 519 | goto Resume_devices; |
519 | } | 520 | } |
520 | 521 | ||
521 | error = dpm_suspend_noirq(PMSG_HIBERNATE); | 522 | error = dpm_suspend_end(PMSG_HIBERNATE); |
522 | if (error) | 523 | if (error) |
523 | goto Resume_devices; | 524 | goto Resume_devices; |
524 | 525 | ||
@@ -549,7 +550,7 @@ int hibernation_platform_enter(void) | |||
549 | Platform_finish: | 550 | Platform_finish: |
550 | hibernation_ops->finish(); | 551 | hibernation_ops->finish(); |
551 | 552 | ||
552 | dpm_resume_noirq(PMSG_RESTORE); | 553 | dpm_resume_start(PMSG_RESTORE); |
553 | 554 | ||
554 | Resume_devices: | 555 | Resume_devices: |
555 | entering_platform_hibernation = false; | 556 | entering_platform_hibernation = false; |
@@ -609,10 +610,6 @@ int hibernate(void) | |||
609 | if (error) | 610 | if (error) |
610 | goto Exit; | 611 | goto Exit; |
611 | 612 | ||
612 | error = usermodehelper_disable(); | ||
613 | if (error) | ||
614 | goto Exit; | ||
615 | |||
616 | /* Allocate memory management structures */ | 613 | /* Allocate memory management structures */ |
617 | error = create_basic_memory_bitmaps(); | 614 | error = create_basic_memory_bitmaps(); |
618 | if (error) | 615 | if (error) |
@@ -624,15 +621,11 @@ int hibernate(void) | |||
624 | 621 | ||
625 | error = freeze_processes(); | 622 | error = freeze_processes(); |
626 | if (error) | 623 | if (error) |
627 | goto Finish; | 624 | goto Free_bitmaps; |
628 | 625 | ||
629 | error = hibernation_snapshot(hibernation_mode == HIBERNATION_PLATFORM); | 626 | error = hibernation_snapshot(hibernation_mode == HIBERNATION_PLATFORM); |
630 | if (error) | 627 | if (error || freezer_test_done) |
631 | goto Thaw; | ||
632 | if (freezer_test_done) { | ||
633 | freezer_test_done = false; | ||
634 | goto Thaw; | 628 | goto Thaw; |
635 | } | ||
636 | 629 | ||
637 | if (in_suspend) { | 630 | if (in_suspend) { |
638 | unsigned int flags = 0; | 631 | unsigned int flags = 0; |
@@ -657,9 +650,12 @@ int hibernate(void) | |||
657 | 650 | ||
658 | Thaw: | 651 | Thaw: |
659 | thaw_processes(); | 652 | thaw_processes(); |
660 | Finish: | 653 | |
654 | /* Don't bother checking whether freezer_test_done is true */ | ||
655 | freezer_test_done = false; | ||
656 | |||
657 | Free_bitmaps: | ||
661 | free_basic_memory_bitmaps(); | 658 | free_basic_memory_bitmaps(); |
662 | usermodehelper_enable(); | ||
663 | Exit: | 659 | Exit: |
664 | pm_notifier_call_chain(PM_POST_HIBERNATION); | 660 | pm_notifier_call_chain(PM_POST_HIBERNATION); |
665 | pm_restore_console(); | 661 | pm_restore_console(); |
@@ -774,15 +770,9 @@ static int software_resume(void) | |||
774 | if (error) | 770 | if (error) |
775 | goto close_finish; | 771 | goto close_finish; |
776 | 772 | ||
777 | error = usermodehelper_disable(); | ||
778 | if (error) | ||
779 | goto close_finish; | ||
780 | |||
781 | error = create_basic_memory_bitmaps(); | 773 | error = create_basic_memory_bitmaps(); |
782 | if (error) { | 774 | if (error) |
783 | usermodehelper_enable(); | ||
784 | goto close_finish; | 775 | goto close_finish; |
785 | } | ||
786 | 776 | ||
787 | pr_debug("PM: Preparing processes for restore.\n"); | 777 | pr_debug("PM: Preparing processes for restore.\n"); |
788 | error = freeze_processes(); | 778 | error = freeze_processes(); |
@@ -803,7 +793,6 @@ static int software_resume(void) | |||
803 | thaw_processes(); | 793 | thaw_processes(); |
804 | Done: | 794 | Done: |
805 | free_basic_memory_bitmaps(); | 795 | free_basic_memory_bitmaps(); |
806 | usermodehelper_enable(); | ||
807 | Finish: | 796 | Finish: |
808 | pm_notifier_call_chain(PM_POST_RESTORE); | 797 | pm_notifier_call_chain(PM_POST_RESTORE); |
809 | pm_restore_console(); | 798 | pm_restore_console(); |