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.c32
1 files changed, 32 insertions, 0 deletions
diff --git a/kernel/power/disk.c b/kernel/power/disk.c
index 45e8541ab7e3..4a4a206b1979 100644
--- a/kernel/power/disk.c
+++ b/kernel/power/disk.c
@@ -71,6 +71,14 @@ void hibernation_set_ops(struct platform_hibernation_ops *ops)
71 mutex_unlock(&pm_mutex); 71 mutex_unlock(&pm_mutex);
72} 72}
73 73
74static bool entering_platform_hibernation;
75
76bool system_entering_hibernation(void)
77{
78 return entering_platform_hibernation;
79}
80EXPORT_SYMBOL(system_entering_hibernation);
81
74#ifdef CONFIG_PM_DEBUG 82#ifdef CONFIG_PM_DEBUG
75static void hibernation_debug_sleep(void) 83static void hibernation_debug_sleep(void)
76{ 84{
@@ -219,6 +227,12 @@ static int create_image(int platform_mode)
219 "aborting hibernation\n"); 227 "aborting hibernation\n");
220 goto Enable_irqs; 228 goto Enable_irqs;
221 } 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 }
222 236
223 if (hibernation_test(TEST_CORE)) 237 if (hibernation_test(TEST_CORE))
224 goto Power_up; 238 goto Power_up;
@@ -234,9 +248,11 @@ static int create_image(int platform_mode)
234 if (!in_suspend) 248 if (!in_suspend)
235 platform_leave(platform_mode); 249 platform_leave(platform_mode);
236 Power_up: 250 Power_up:
251 sysdev_resume();
237 /* NOTE: device_power_up() is just a resume() for devices 252 /* NOTE: device_power_up() is just a resume() for devices
238 * that suspended with irqs off ... no overall powerup. 253 * that suspended with irqs off ... no overall powerup.
239 */ 254 */
255 Power_up_devices:
240 device_power_up(in_suspend ? 256 device_power_up(in_suspend ?
241 (error ? PMSG_RECOVER : PMSG_THAW) : PMSG_RESTORE); 257 (error ? PMSG_RECOVER : PMSG_THAW) : PMSG_RESTORE);
242 Enable_irqs: 258 Enable_irqs:
@@ -327,6 +343,7 @@ static int resume_target_kernel(void)
327 "aborting resume\n"); 343 "aborting resume\n");
328 goto Enable_irqs; 344 goto Enable_irqs;
329 } 345 }
346 sysdev_suspend(PMSG_QUIESCE);
330 /* 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 */
331 save_processor_state(); 348 save_processor_state();
332 error = restore_highmem(); 349 error = restore_highmem();
@@ -349,6 +366,7 @@ static int resume_target_kernel(void)
349 swsusp_free(); 366 swsusp_free();
350 restore_processor_state(); 367 restore_processor_state();
351 touch_softlockup_watchdog(); 368 touch_softlockup_watchdog();
369 sysdev_resume();
352 device_power_up(PMSG_RECOVER); 370 device_power_up(PMSG_RECOVER);
353 Enable_irqs: 371 Enable_irqs:
354 local_irq_enable(); 372 local_irq_enable();
@@ -411,6 +429,7 @@ int hibernation_platform_enter(void)
411 if (error) 429 if (error)
412 goto Close; 430 goto Close;
413 431
432 entering_platform_hibernation = true;
414 suspend_console(); 433 suspend_console();
415 error = device_suspend(PMSG_HIBERNATE); 434 error = device_suspend(PMSG_HIBERNATE);
416 if (error) { 435 if (error) {
@@ -431,6 +450,7 @@ int hibernation_platform_enter(void)
431 local_irq_disable(); 450 local_irq_disable();
432 error = device_power_down(PMSG_HIBERNATE); 451 error = device_power_down(PMSG_HIBERNATE);
433 if (!error) { 452 if (!error) {
453 sysdev_suspend(PMSG_HIBERNATE);
434 hibernation_ops->enter(); 454 hibernation_ops->enter();
435 /* We should never get here */ 455 /* We should never get here */
436 while (1); 456 while (1);
@@ -445,6 +465,7 @@ int hibernation_platform_enter(void)
445 Finish: 465 Finish:
446 hibernation_ops->finish(); 466 hibernation_ops->finish();
447 Resume_devices: 467 Resume_devices:
468 entering_platform_hibernation = false;
448 device_resume(PMSG_RESTORE); 469 device_resume(PMSG_RESTORE);
449 resume_console(); 470 resume_console();
450 Close: 471 Close:
@@ -585,6 +606,12 @@ static int software_resume(void)
585 unsigned int flags; 606 unsigned int flags;
586 607
587 /* 608 /*
609 * If the user said "noresume".. bail out early.
610 */
611 if (noresume)
612 return 0;
613
614 /*
588 * 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
589 * is configured into the kernel. Since the regular hibernate 616 * is configured into the kernel. Since the regular hibernate
590 * trigger path is via sysfs which takes a buffer mutex before 617 * trigger path is via sysfs which takes a buffer mutex before
@@ -600,6 +627,11 @@ static int software_resume(void)
600 mutex_unlock(&pm_mutex); 627 mutex_unlock(&pm_mutex);
601 return -ENOENT; 628 return -ENOENT;
602 } 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();
603 swsusp_resume_device = name_to_dev_t(resume_file); 635 swsusp_resume_device = name_to_dev_t(resume_file);
604 pr_debug("PM: Resume from partition %s\n", resume_file); 636 pr_debug("PM: Resume from partition %s\n", resume_file);
605 } else { 637 } else {