diff options
Diffstat (limited to 'kernel/power/disk.c')
-rw-r--r-- | kernel/power/disk.c | 74 |
1 files changed, 35 insertions, 39 deletions
diff --git a/kernel/power/disk.c b/kernel/power/disk.c index f3db382c2b2d..5cb080e7eebd 100644 --- a/kernel/power/disk.c +++ b/kernel/power/disk.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <linux/console.h> | 22 | #include <linux/console.h> |
23 | #include <linux/cpu.h> | 23 | #include <linux/cpu.h> |
24 | #include <linux/freezer.h> | 24 | #include <linux/freezer.h> |
25 | #include <scsi/scsi_scan.h> | ||
25 | #include <asm/suspend.h> | 26 | #include <asm/suspend.h> |
26 | 27 | ||
27 | #include "power.h" | 28 | #include "power.h" |
@@ -214,8 +215,6 @@ static int create_image(int platform_mode) | |||
214 | if (error) | 215 | if (error) |
215 | return error; | 216 | return error; |
216 | 217 | ||
217 | device_pm_lock(); | ||
218 | |||
219 | /* At this point, device_suspend() has been called, but *not* | 218 | /* At this point, device_suspend() has been called, but *not* |
220 | * device_power_down(). We *must* call device_power_down() now. | 219 | * device_power_down(). We *must* call device_power_down() now. |
221 | * Otherwise, drivers for some devices (e.g. interrupt controllers) | 220 | * Otherwise, drivers for some devices (e.g. interrupt controllers) |
@@ -226,7 +225,7 @@ static int create_image(int platform_mode) | |||
226 | if (error) { | 225 | if (error) { |
227 | printk(KERN_ERR "PM: Some devices failed to power down, " | 226 | printk(KERN_ERR "PM: Some devices failed to power down, " |
228 | "aborting hibernation\n"); | 227 | "aborting hibernation\n"); |
229 | goto Unlock; | 228 | return error; |
230 | } | 229 | } |
231 | 230 | ||
232 | error = platform_pre_snapshot(platform_mode); | 231 | error = platform_pre_snapshot(platform_mode); |
@@ -240,9 +239,9 @@ static int create_image(int platform_mode) | |||
240 | 239 | ||
241 | local_irq_disable(); | 240 | local_irq_disable(); |
242 | 241 | ||
243 | sysdev_suspend(PMSG_FREEZE); | 242 | error = sysdev_suspend(PMSG_FREEZE); |
244 | if (error) { | 243 | if (error) { |
245 | printk(KERN_ERR "PM: Some devices failed to power down, " | 244 | printk(KERN_ERR "PM: Some system devices failed to power down, " |
246 | "aborting hibernation\n"); | 245 | "aborting hibernation\n"); |
247 | goto Enable_irqs; | 246 | goto Enable_irqs; |
248 | } | 247 | } |
@@ -279,9 +278,6 @@ static int create_image(int platform_mode) | |||
279 | device_power_up(in_suspend ? | 278 | device_power_up(in_suspend ? |
280 | (error ? PMSG_RECOVER : PMSG_THAW) : PMSG_RESTORE); | 279 | (error ? PMSG_RECOVER : PMSG_THAW) : PMSG_RESTORE); |
281 | 280 | ||
282 | Unlock: | ||
283 | device_pm_unlock(); | ||
284 | |||
285 | return error; | 281 | return error; |
286 | } | 282 | } |
287 | 283 | ||
@@ -289,7 +285,7 @@ static int create_image(int platform_mode) | |||
289 | * hibernation_snapshot - quiesce devices and create the hibernation | 285 | * hibernation_snapshot - quiesce devices and create the hibernation |
290 | * snapshot image. | 286 | * snapshot image. |
291 | * @platform_mode - if set, use the platform driver, if available, to | 287 | * @platform_mode - if set, use the platform driver, if available, to |
292 | * prepare the platform frimware for the power transition. | 288 | * prepare the platform firmware for the power transition. |
293 | * | 289 | * |
294 | * Must be called with pm_mutex held | 290 | * Must be called with pm_mutex held |
295 | */ | 291 | */ |
@@ -343,13 +339,11 @@ static int resume_target_kernel(bool platform_mode) | |||
343 | { | 339 | { |
344 | int error; | 340 | int error; |
345 | 341 | ||
346 | device_pm_lock(); | ||
347 | |||
348 | error = device_power_down(PMSG_QUIESCE); | 342 | error = device_power_down(PMSG_QUIESCE); |
349 | if (error) { | 343 | if (error) { |
350 | printk(KERN_ERR "PM: Some devices failed to power down, " | 344 | printk(KERN_ERR "PM: Some devices failed to power down, " |
351 | "aborting resume\n"); | 345 | "aborting resume\n"); |
352 | goto Unlock; | 346 | return error; |
353 | } | 347 | } |
354 | 348 | ||
355 | error = platform_pre_restore(platform_mode); | 349 | error = platform_pre_restore(platform_mode); |
@@ -402,9 +396,6 @@ static int resume_target_kernel(bool platform_mode) | |||
402 | 396 | ||
403 | device_power_up(PMSG_RECOVER); | 397 | device_power_up(PMSG_RECOVER); |
404 | 398 | ||
405 | Unlock: | ||
406 | device_pm_unlock(); | ||
407 | |||
408 | return error; | 399 | return error; |
409 | } | 400 | } |
410 | 401 | ||
@@ -412,7 +403,7 @@ static int resume_target_kernel(bool platform_mode) | |||
412 | * hibernation_restore - quiesce devices and restore the hibernation | 403 | * hibernation_restore - quiesce devices and restore the hibernation |
413 | * snapshot image. If successful, control returns in hibernation_snaphot() | 404 | * snapshot image. If successful, control returns in hibernation_snaphot() |
414 | * @platform_mode - if set, use the platform driver, if available, to | 405 | * @platform_mode - if set, use the platform driver, if available, to |
415 | * prepare the platform frimware for the transition. | 406 | * prepare the platform firmware for the transition. |
416 | * | 407 | * |
417 | * Must be called with pm_mutex held | 408 | * Must be called with pm_mutex held |
418 | */ | 409 | */ |
@@ -463,11 +454,9 @@ int hibernation_platform_enter(void) | |||
463 | goto Resume_devices; | 454 | goto Resume_devices; |
464 | } | 455 | } |
465 | 456 | ||
466 | device_pm_lock(); | ||
467 | |||
468 | error = device_power_down(PMSG_HIBERNATE); | 457 | error = device_power_down(PMSG_HIBERNATE); |
469 | if (error) | 458 | if (error) |
470 | goto Unlock; | 459 | goto Resume_devices; |
471 | 460 | ||
472 | error = hibernation_ops->prepare(); | 461 | error = hibernation_ops->prepare(); |
473 | if (error) | 462 | if (error) |
@@ -492,9 +481,6 @@ int hibernation_platform_enter(void) | |||
492 | 481 | ||
493 | device_power_up(PMSG_RESTORE); | 482 | device_power_up(PMSG_RESTORE); |
494 | 483 | ||
495 | Unlock: | ||
496 | device_pm_unlock(); | ||
497 | |||
498 | Resume_devices: | 484 | Resume_devices: |
499 | entering_platform_hibernation = false; | 485 | entering_platform_hibernation = false; |
500 | device_resume(PMSG_RESTORE); | 486 | device_resume(PMSG_RESTORE); |
@@ -655,32 +641,42 @@ static int software_resume(void) | |||
655 | * here to avoid lockdep complaining. | 641 | * here to avoid lockdep complaining. |
656 | */ | 642 | */ |
657 | 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); | ||
658 | if (!swsusp_resume_device) { | 657 | if (!swsusp_resume_device) { |
659 | if (!strlen(resume_file)) { | ||
660 | mutex_unlock(&pm_mutex); | ||
661 | return -ENOENT; | ||
662 | } | ||
663 | /* | 658 | /* |
664 | * Some device discovery might still be in progress; we need | 659 | * Some device discovery might still be in progress; we need |
665 | * to wait for this to finish. | 660 | * to wait for this to finish. |
666 | */ | 661 | */ |
667 | 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 | |||
668 | swsusp_resume_device = name_to_dev_t(resume_file); | 670 | swsusp_resume_device = name_to_dev_t(resume_file); |
669 | pr_debug("PM: Resume from partition %s\n", resume_file); | 671 | if (!swsusp_resume_device) { |
670 | } else { | 672 | error = -ENODEV; |
671 | pr_debug("PM: Resume from partition %d:%d\n", | 673 | goto Unlock; |
672 | MAJOR(swsusp_resume_device), | 674 | } |
673 | MINOR(swsusp_resume_device)); | ||
674 | } | 675 | } |
675 | 676 | ||
676 | if (noresume) { | 677 | Check_image: |
677 | /** | 678 | pr_debug("PM: Resume from partition %d:%d\n", |
678 | * FIXME: If noresume is specified, we need to find the | 679 | MAJOR(swsusp_resume_device), MINOR(swsusp_resume_device)); |
679 | * partition and reset it back to normal swap space. | ||
680 | */ | ||
681 | mutex_unlock(&pm_mutex); | ||
682 | return 0; | ||
683 | } | ||
684 | 680 | ||
685 | pr_debug("PM: Checking hibernation image.\n"); | 681 | pr_debug("PM: Checking hibernation image.\n"); |
686 | error = swsusp_check(); | 682 | error = swsusp_check(); |