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.c74
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();