diff options
Diffstat (limited to 'kernel/power/disk.c')
-rw-r--r-- | kernel/power/disk.c | 76 |
1 files changed, 32 insertions, 44 deletions
diff --git a/kernel/power/disk.c b/kernel/power/disk.c index 0854770b63b9..5cb080e7eebd 100644 --- a/kernel/power/disk.c +++ b/kernel/power/disk.c | |||
@@ -215,8 +215,6 @@ static int create_image(int platform_mode) | |||
215 | if (error) | 215 | if (error) |
216 | return error; | 216 | return error; |
217 | 217 | ||
218 | device_pm_lock(); | ||
219 | |||
220 | /* At this point, device_suspend() has been called, but *not* | 218 | /* At this point, device_suspend() has been called, but *not* |
221 | * device_power_down(). We *must* call device_power_down() now. | 219 | * device_power_down(). We *must* call device_power_down() now. |
222 | * Otherwise, drivers for some devices (e.g. interrupt controllers) | 220 | * Otherwise, drivers for some devices (e.g. interrupt controllers) |
@@ -227,7 +225,7 @@ static int create_image(int platform_mode) | |||
227 | if (error) { | 225 | if (error) { |
228 | printk(KERN_ERR "PM: Some devices failed to power down, " | 226 | printk(KERN_ERR "PM: Some devices failed to power down, " |
229 | "aborting hibernation\n"); | 227 | "aborting hibernation\n"); |
230 | goto Unlock; | 228 | return error; |
231 | } | 229 | } |
232 | 230 | ||
233 | error = platform_pre_snapshot(platform_mode); | 231 | error = platform_pre_snapshot(platform_mode); |
@@ -241,9 +239,9 @@ static int create_image(int platform_mode) | |||
241 | 239 | ||
242 | local_irq_disable(); | 240 | local_irq_disable(); |
243 | 241 | ||
244 | sysdev_suspend(PMSG_FREEZE); | 242 | error = sysdev_suspend(PMSG_FREEZE); |
245 | if (error) { | 243 | if (error) { |
246 | printk(KERN_ERR "PM: Some devices failed to power down, " | 244 | printk(KERN_ERR "PM: Some system devices failed to power down, " |
247 | "aborting hibernation\n"); | 245 | "aborting hibernation\n"); |
248 | goto Enable_irqs; | 246 | goto Enable_irqs; |
249 | } | 247 | } |
@@ -280,9 +278,6 @@ static int create_image(int platform_mode) | |||
280 | device_power_up(in_suspend ? | 278 | device_power_up(in_suspend ? |
281 | (error ? PMSG_RECOVER : PMSG_THAW) : PMSG_RESTORE); | 279 | (error ? PMSG_RECOVER : PMSG_THAW) : PMSG_RESTORE); |
282 | 280 | ||
283 | Unlock: | ||
284 | device_pm_unlock(); | ||
285 | |||
286 | return error; | 281 | return error; |
287 | } | 282 | } |
288 | 283 | ||
@@ -344,13 +339,11 @@ static int resume_target_kernel(bool platform_mode) | |||
344 | { | 339 | { |
345 | int error; | 340 | int error; |
346 | 341 | ||
347 | device_pm_lock(); | ||
348 | |||
349 | error = device_power_down(PMSG_QUIESCE); | 342 | error = device_power_down(PMSG_QUIESCE); |
350 | if (error) { | 343 | if (error) { |
351 | printk(KERN_ERR "PM: Some devices failed to power down, " | 344 | printk(KERN_ERR "PM: Some devices failed to power down, " |
352 | "aborting resume\n"); | 345 | "aborting resume\n"); |
353 | goto Unlock; | 346 | return error; |
354 | } | 347 | } |
355 | 348 | ||
356 | error = platform_pre_restore(platform_mode); | 349 | error = platform_pre_restore(platform_mode); |
@@ -403,9 +396,6 @@ static int resume_target_kernel(bool platform_mode) | |||
403 | 396 | ||
404 | device_power_up(PMSG_RECOVER); | 397 | device_power_up(PMSG_RECOVER); |
405 | 398 | ||
406 | Unlock: | ||
407 | device_pm_unlock(); | ||
408 | |||
409 | return error; | 399 | return error; |
410 | } | 400 | } |
411 | 401 | ||
@@ -464,11 +454,9 @@ int hibernation_platform_enter(void) | |||
464 | goto Resume_devices; | 454 | goto Resume_devices; |
465 | } | 455 | } |
466 | 456 | ||
467 | device_pm_lock(); | ||
468 | |||
469 | error = device_power_down(PMSG_HIBERNATE); | 457 | error = device_power_down(PMSG_HIBERNATE); |
470 | if (error) | 458 | if (error) |
471 | goto Unlock; | 459 | goto Resume_devices; |
472 | 460 | ||
473 | error = hibernation_ops->prepare(); | 461 | error = hibernation_ops->prepare(); |
474 | if (error) | 462 | if (error) |
@@ -493,9 +481,6 @@ int hibernation_platform_enter(void) | |||
493 | 481 | ||
494 | device_power_up(PMSG_RESTORE); | 482 | device_power_up(PMSG_RESTORE); |
495 | 483 | ||
496 | Unlock: | ||
497 | device_pm_unlock(); | ||
498 | |||
499 | Resume_devices: | 484 | Resume_devices: |
500 | entering_platform_hibernation = false; | 485 | entering_platform_hibernation = false; |
501 | device_resume(PMSG_RESTORE); | 486 | device_resume(PMSG_RESTORE); |
@@ -646,13 +631,6 @@ static int software_resume(void) | |||
646 | return 0; | 631 | return 0; |
647 | 632 | ||
648 | /* | 633 | /* |
649 | * We can't depend on SCSI devices being available after loading one of | ||
650 | * their modules if scsi_complete_async_scans() is not called and the | ||
651 | * resume device usually is a SCSI one. | ||
652 | */ | ||
653 | scsi_complete_async_scans(); | ||
654 | |||
655 | /* | ||
656 | * name_to_dev_t() below takes a sysfs buffer mutex when sysfs | 634 | * name_to_dev_t() below takes a sysfs buffer mutex when sysfs |
657 | * is configured into the kernel. Since the regular hibernate | 635 | * is configured into the kernel. Since the regular hibernate |
658 | * trigger path is via sysfs which takes a buffer mutex before | 636 | * trigger path is via sysfs which takes a buffer mutex before |
@@ -663,32 +641,42 @@ static int software_resume(void) | |||
663 | * here to avoid lockdep complaining. | 641 | * here to avoid lockdep complaining. |
664 | */ | 642 | */ |
665 | mutex_lock_nested(&pm_mutex, SINGLE_DEPTH_NESTING); | 643 | mutex_lock_nested(&pm_mutex, SINGLE_DEPTH_NESTING); |
644 | |||
645 | if (swsusp_resume_device) | ||
646 | goto Check_image; | ||
647 | |||
648 | if (!strlen(resume_file)) { | ||
649 | error = -ENOENT; | ||
650 | goto Unlock; | ||
651 | } | ||
652 | |||
653 | pr_debug("PM: Checking image partition %s\n", resume_file); | ||
654 | |||
655 | /* Check if the device is there */ | ||
656 | swsusp_resume_device = name_to_dev_t(resume_file); | ||
666 | if (!swsusp_resume_device) { | 657 | if (!swsusp_resume_device) { |
667 | if (!strlen(resume_file)) { | ||
668 | mutex_unlock(&pm_mutex); | ||
669 | return -ENOENT; | ||
670 | } | ||
671 | /* | 658 | /* |
672 | * Some device discovery might still be in progress; we need | 659 | * Some device discovery might still be in progress; we need |
673 | * to wait for this to finish. | 660 | * to wait for this to finish. |
674 | */ | 661 | */ |
675 | wait_for_device_probe(); | 662 | wait_for_device_probe(); |
663 | /* | ||
664 | * We can't depend on SCSI devices being available after loading | ||
665 | * one of their modules until scsi_complete_async_scans() is | ||
666 | * called and the resume device usually is a SCSI one. | ||
667 | */ | ||
668 | scsi_complete_async_scans(); | ||
669 | |||
676 | swsusp_resume_device = name_to_dev_t(resume_file); | 670 | swsusp_resume_device = name_to_dev_t(resume_file); |
677 | pr_debug("PM: Resume from partition %s\n", resume_file); | 671 | if (!swsusp_resume_device) { |
678 | } else { | 672 | error = -ENODEV; |
679 | pr_debug("PM: Resume from partition %d:%d\n", | 673 | goto Unlock; |
680 | MAJOR(swsusp_resume_device), | 674 | } |
681 | MINOR(swsusp_resume_device)); | ||
682 | } | 675 | } |
683 | 676 | ||
684 | if (noresume) { | 677 | Check_image: |
685 | /** | 678 | pr_debug("PM: Resume from partition %d:%d\n", |
686 | * FIXME: If noresume is specified, we need to find the | 679 | MAJOR(swsusp_resume_device), MINOR(swsusp_resume_device)); |
687 | * partition and reset it back to normal swap space. | ||
688 | */ | ||
689 | mutex_unlock(&pm_mutex); | ||
690 | return 0; | ||
691 | } | ||
692 | 680 | ||
693 | pr_debug("PM: Checking hibernation image.\n"); | 681 | pr_debug("PM: Checking hibernation image.\n"); |
694 | error = swsusp_check(); | 682 | error = swsusp_check(); |