diff options
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/kexec.c | 7 | ||||
| -rw-r--r-- | kernel/power/console.c | 6 | ||||
| -rw-r--r-- | kernel/power/disk.c | 22 | ||||
| -rw-r--r-- | kernel/power/main.c | 8 | ||||
| -rw-r--r-- | kernel/power/user.c | 8 | ||||
| -rw-r--r-- | kernel/printk.c | 15 |
6 files changed, 54 insertions, 12 deletions
diff --git a/kernel/kexec.c b/kernel/kexec.c index 795e7b67a228..c7fd6692939d 100644 --- a/kernel/kexec.c +++ b/kernel/kexec.c | |||
| @@ -1465,6 +1465,11 @@ int kernel_kexec(void) | |||
| 1465 | error = device_power_down(PMSG_FREEZE); | 1465 | error = device_power_down(PMSG_FREEZE); |
| 1466 | if (error) | 1466 | if (error) |
| 1467 | goto Enable_irqs; | 1467 | goto Enable_irqs; |
| 1468 | |||
| 1469 | /* Suspend system devices */ | ||
| 1470 | error = sysdev_suspend(PMSG_FREEZE); | ||
| 1471 | if (error) | ||
| 1472 | goto Power_up_devices; | ||
| 1468 | } else | 1473 | } else |
| 1469 | #endif | 1474 | #endif |
| 1470 | { | 1475 | { |
| @@ -1477,6 +1482,8 @@ int kernel_kexec(void) | |||
| 1477 | 1482 | ||
| 1478 | #ifdef CONFIG_KEXEC_JUMP | 1483 | #ifdef CONFIG_KEXEC_JUMP |
| 1479 | if (kexec_image->preserve_context) { | 1484 | if (kexec_image->preserve_context) { |
| 1485 | sysdev_resume(); | ||
| 1486 | Power_up_devices: | ||
| 1480 | device_power_up(PMSG_RESTORE); | 1487 | device_power_up(PMSG_RESTORE); |
| 1481 | Enable_irqs: | 1488 | Enable_irqs: |
| 1482 | local_irq_enable(); | 1489 | local_irq_enable(); |
diff --git a/kernel/power/console.c b/kernel/power/console.c index b8628be2a465..a3961b205de7 100644 --- a/kernel/power/console.c +++ b/kernel/power/console.c | |||
| @@ -78,6 +78,12 @@ void pm_restore_console(void) | |||
| 78 | } | 78 | } |
| 79 | set_console(orig_fgconsole); | 79 | set_console(orig_fgconsole); |
| 80 | release_console_sem(); | 80 | release_console_sem(); |
| 81 | |||
| 82 | if (vt_waitactive(orig_fgconsole)) { | ||
| 83 | pr_debug("Resume: Can't switch VCs."); | ||
| 84 | return; | ||
| 85 | } | ||
| 86 | |||
| 81 | kmsg_redirect = orig_kmsg; | 87 | kmsg_redirect = orig_kmsg; |
| 82 | } | 88 | } |
| 83 | #endif | 89 | #endif |
diff --git a/kernel/power/disk.c b/kernel/power/disk.c index 432ee575c9ee..4a4a206b1979 100644 --- a/kernel/power/disk.c +++ b/kernel/power/disk.c | |||
| @@ -227,6 +227,12 @@ static int create_image(int platform_mode) | |||
| 227 | "aborting hibernation\n"); | 227 | "aborting hibernation\n"); |
| 228 | goto Enable_irqs; | 228 | goto Enable_irqs; |
| 229 | } | 229 | } |
| 230 | sysdev_suspend(PMSG_FREEZE); | ||
| 231 | if (error) { | ||
| 232 | printk(KERN_ERR "PM: Some devices failed to power down, " | ||
| 233 | "aborting hibernation\n"); | ||
| 234 | goto Power_up_devices; | ||
| 235 | } | ||
| 230 | 236 | ||
| 231 | if (hibernation_test(TEST_CORE)) | 237 | if (hibernation_test(TEST_CORE)) |
| 232 | goto Power_up; | 238 | goto Power_up; |
| @@ -242,9 +248,11 @@ static int create_image(int platform_mode) | |||
| 242 | if (!in_suspend) | 248 | if (!in_suspend) |
| 243 | platform_leave(platform_mode); | 249 | platform_leave(platform_mode); |
| 244 | Power_up: | 250 | Power_up: |
| 251 | sysdev_resume(); | ||
| 245 | /* NOTE: device_power_up() is just a resume() for devices | 252 | /* NOTE: device_power_up() is just a resume() for devices |
| 246 | * that suspended with irqs off ... no overall powerup. | 253 | * that suspended with irqs off ... no overall powerup. |
| 247 | */ | 254 | */ |
| 255 | Power_up_devices: | ||
| 248 | device_power_up(in_suspend ? | 256 | device_power_up(in_suspend ? |
| 249 | (error ? PMSG_RECOVER : PMSG_THAW) : PMSG_RESTORE); | 257 | (error ? PMSG_RECOVER : PMSG_THAW) : PMSG_RESTORE); |
| 250 | Enable_irqs: | 258 | Enable_irqs: |
| @@ -335,6 +343,7 @@ static int resume_target_kernel(void) | |||
| 335 | "aborting resume\n"); | 343 | "aborting resume\n"); |
| 336 | goto Enable_irqs; | 344 | goto Enable_irqs; |
| 337 | } | 345 | } |
| 346 | sysdev_suspend(PMSG_QUIESCE); | ||
| 338 | /* We'll ignore saved state, but this gets preempt count (etc) right */ | 347 | /* We'll ignore saved state, but this gets preempt count (etc) right */ |
| 339 | save_processor_state(); | 348 | save_processor_state(); |
| 340 | error = restore_highmem(); | 349 | error = restore_highmem(); |
| @@ -357,6 +366,7 @@ static int resume_target_kernel(void) | |||
| 357 | swsusp_free(); | 366 | swsusp_free(); |
| 358 | restore_processor_state(); | 367 | restore_processor_state(); |
| 359 | touch_softlockup_watchdog(); | 368 | touch_softlockup_watchdog(); |
| 369 | sysdev_resume(); | ||
| 360 | device_power_up(PMSG_RECOVER); | 370 | device_power_up(PMSG_RECOVER); |
| 361 | Enable_irqs: | 371 | Enable_irqs: |
| 362 | local_irq_enable(); | 372 | local_irq_enable(); |
| @@ -440,6 +450,7 @@ int hibernation_platform_enter(void) | |||
| 440 | local_irq_disable(); | 450 | local_irq_disable(); |
| 441 | error = device_power_down(PMSG_HIBERNATE); | 451 | error = device_power_down(PMSG_HIBERNATE); |
| 442 | if (!error) { | 452 | if (!error) { |
| 453 | sysdev_suspend(PMSG_HIBERNATE); | ||
| 443 | hibernation_ops->enter(); | 454 | hibernation_ops->enter(); |
| 444 | /* We should never get here */ | 455 | /* We should never get here */ |
| 445 | while (1); | 456 | while (1); |
| @@ -595,6 +606,12 @@ static int software_resume(void) | |||
| 595 | unsigned int flags; | 606 | unsigned int flags; |
| 596 | 607 | ||
| 597 | /* | 608 | /* |
| 609 | * If the user said "noresume".. bail out early. | ||
| 610 | */ | ||
| 611 | if (noresume) | ||
| 612 | return 0; | ||
| 613 | |||
| 614 | /* | ||
| 598 | * name_to_dev_t() below takes a sysfs buffer mutex when sysfs | 615 | * name_to_dev_t() below takes a sysfs buffer mutex when sysfs |
| 599 | * is configured into the kernel. Since the regular hibernate | 616 | * is configured into the kernel. Since the regular hibernate |
| 600 | * trigger path is via sysfs which takes a buffer mutex before | 617 | * trigger path is via sysfs which takes a buffer mutex before |
| @@ -610,6 +627,11 @@ static int software_resume(void) | |||
| 610 | mutex_unlock(&pm_mutex); | 627 | mutex_unlock(&pm_mutex); |
| 611 | return -ENOENT; | 628 | return -ENOENT; |
| 612 | } | 629 | } |
| 630 | /* | ||
| 631 | * Some device discovery might still be in progress; we need | ||
| 632 | * to wait for this to finish. | ||
| 633 | */ | ||
| 634 | wait_for_device_probe(); | ||
| 613 | swsusp_resume_device = name_to_dev_t(resume_file); | 635 | swsusp_resume_device = name_to_dev_t(resume_file); |
| 614 | pr_debug("PM: Resume from partition %s\n", resume_file); | 636 | pr_debug("PM: Resume from partition %s\n", resume_file); |
| 615 | } else { | 637 | } else { |
diff --git a/kernel/power/main.c b/kernel/power/main.c index b4d219016b6c..c9632f841f64 100644 --- a/kernel/power/main.c +++ b/kernel/power/main.c | |||
| @@ -298,8 +298,12 @@ static int suspend_enter(suspend_state_t state) | |||
| 298 | goto Done; | 298 | goto Done; |
| 299 | } | 299 | } |
| 300 | 300 | ||
| 301 | if (!suspend_test(TEST_CORE)) | 301 | error = sysdev_suspend(PMSG_SUSPEND); |
| 302 | error = suspend_ops->enter(state); | 302 | if (!error) { |
| 303 | if (!suspend_test(TEST_CORE)) | ||
| 304 | error = suspend_ops->enter(state); | ||
| 305 | sysdev_resume(); | ||
| 306 | } | ||
| 303 | 307 | ||
| 304 | device_power_up(PMSG_RESUME); | 308 | device_power_up(PMSG_RESUME); |
| 305 | Done: | 309 | Done: |
diff --git a/kernel/power/user.c b/kernel/power/user.c index 005b93d839ba..6c85359364f2 100644 --- a/kernel/power/user.c +++ b/kernel/power/user.c | |||
| @@ -95,15 +95,15 @@ static int snapshot_open(struct inode *inode, struct file *filp) | |||
| 95 | data->swap = swsusp_resume_device ? | 95 | data->swap = swsusp_resume_device ? |
| 96 | swap_type_of(swsusp_resume_device, 0, NULL) : -1; | 96 | swap_type_of(swsusp_resume_device, 0, NULL) : -1; |
| 97 | data->mode = O_RDONLY; | 97 | data->mode = O_RDONLY; |
| 98 | error = pm_notifier_call_chain(PM_RESTORE_PREPARE); | 98 | error = pm_notifier_call_chain(PM_HIBERNATION_PREPARE); |
| 99 | if (error) | 99 | if (error) |
| 100 | pm_notifier_call_chain(PM_POST_RESTORE); | 100 | pm_notifier_call_chain(PM_POST_HIBERNATION); |
| 101 | } else { | 101 | } else { |
| 102 | data->swap = -1; | 102 | data->swap = -1; |
| 103 | data->mode = O_WRONLY; | 103 | data->mode = O_WRONLY; |
| 104 | error = pm_notifier_call_chain(PM_HIBERNATION_PREPARE); | 104 | error = pm_notifier_call_chain(PM_RESTORE_PREPARE); |
| 105 | if (error) | 105 | if (error) |
| 106 | pm_notifier_call_chain(PM_POST_HIBERNATION); | 106 | pm_notifier_call_chain(PM_POST_RESTORE); |
| 107 | } | 107 | } |
| 108 | if (error) | 108 | if (error) |
| 109 | atomic_inc(&snapshot_device_available); | 109 | atomic_inc(&snapshot_device_available); |
diff --git a/kernel/printk.c b/kernel/printk.c index 69188f226a93..e3602d0755b0 100644 --- a/kernel/printk.c +++ b/kernel/printk.c | |||
| @@ -73,7 +73,6 @@ EXPORT_SYMBOL(oops_in_progress); | |||
| 73 | * driver system. | 73 | * driver system. |
| 74 | */ | 74 | */ |
| 75 | static DECLARE_MUTEX(console_sem); | 75 | static DECLARE_MUTEX(console_sem); |
| 76 | static DECLARE_MUTEX(secondary_console_sem); | ||
| 77 | struct console *console_drivers; | 76 | struct console *console_drivers; |
| 78 | EXPORT_SYMBOL_GPL(console_drivers); | 77 | EXPORT_SYMBOL_GPL(console_drivers); |
| 79 | 78 | ||
| @@ -891,12 +890,14 @@ void suspend_console(void) | |||
| 891 | printk("Suspending console(s) (use no_console_suspend to debug)\n"); | 890 | printk("Suspending console(s) (use no_console_suspend to debug)\n"); |
| 892 | acquire_console_sem(); | 891 | acquire_console_sem(); |
| 893 | console_suspended = 1; | 892 | console_suspended = 1; |
| 893 | up(&console_sem); | ||
| 894 | } | 894 | } |
| 895 | 895 | ||
| 896 | void resume_console(void) | 896 | void resume_console(void) |
| 897 | { | 897 | { |
| 898 | if (!console_suspend_enabled) | 898 | if (!console_suspend_enabled) |
| 899 | return; | 899 | return; |
| 900 | down(&console_sem); | ||
| 900 | console_suspended = 0; | 901 | console_suspended = 0; |
| 901 | release_console_sem(); | 902 | release_console_sem(); |
| 902 | } | 903 | } |
| @@ -912,11 +913,9 @@ void resume_console(void) | |||
| 912 | void acquire_console_sem(void) | 913 | void acquire_console_sem(void) |
| 913 | { | 914 | { |
| 914 | BUG_ON(in_interrupt()); | 915 | BUG_ON(in_interrupt()); |
| 915 | if (console_suspended) { | ||
| 916 | down(&secondary_console_sem); | ||
| 917 | return; | ||
| 918 | } | ||
| 919 | down(&console_sem); | 916 | down(&console_sem); |
| 917 | if (console_suspended) | ||
| 918 | return; | ||
| 920 | console_locked = 1; | 919 | console_locked = 1; |
| 921 | console_may_schedule = 1; | 920 | console_may_schedule = 1; |
| 922 | } | 921 | } |
| @@ -926,6 +925,10 @@ int try_acquire_console_sem(void) | |||
| 926 | { | 925 | { |
| 927 | if (down_trylock(&console_sem)) | 926 | if (down_trylock(&console_sem)) |
| 928 | return -1; | 927 | return -1; |
| 928 | if (console_suspended) { | ||
| 929 | up(&console_sem); | ||
| 930 | return -1; | ||
| 931 | } | ||
| 929 | console_locked = 1; | 932 | console_locked = 1; |
| 930 | console_may_schedule = 0; | 933 | console_may_schedule = 0; |
| 931 | return 0; | 934 | return 0; |
| @@ -979,7 +982,7 @@ void release_console_sem(void) | |||
| 979 | unsigned wake_klogd = 0; | 982 | unsigned wake_klogd = 0; |
| 980 | 983 | ||
| 981 | if (console_suspended) { | 984 | if (console_suspended) { |
| 982 | up(&secondary_console_sem); | 985 | up(&console_sem); |
| 983 | return; | 986 | return; |
| 984 | } | 987 | } |
| 985 | 988 | ||
