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