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