diff options
Diffstat (limited to 'kernel/power')
| -rw-r--r-- | kernel/power/disk.c | 45 | ||||
| -rw-r--r-- | kernel/power/main.c | 24 | ||||
| -rw-r--r-- | kernel/power/swap.c | 2 | ||||
| -rw-r--r-- | kernel/power/user.c | 9 |
4 files changed, 54 insertions, 26 deletions
diff --git a/kernel/power/disk.c b/kernel/power/disk.c index 5f21ab2bbcdf..e71ca9cd81b2 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" |
| @@ -655,32 +656,42 @@ static int software_resume(void) | |||
| 655 | * here to avoid lockdep complaining. | 656 | * here to avoid lockdep complaining. |
| 656 | */ | 657 | */ |
| 657 | mutex_lock_nested(&pm_mutex, SINGLE_DEPTH_NESTING); | 658 | mutex_lock_nested(&pm_mutex, SINGLE_DEPTH_NESTING); |
| 659 | |||
| 660 | if (swsusp_resume_device) | ||
| 661 | goto Check_image; | ||
| 662 | |||
| 663 | if (!strlen(resume_file)) { | ||
| 664 | error = -ENOENT; | ||
| 665 | goto Unlock; | ||
| 666 | } | ||
| 667 | |||
| 668 | pr_debug("PM: Checking image partition %s\n", resume_file); | ||
| 669 | |||
| 670 | /* Check if the device is there */ | ||
| 671 | swsusp_resume_device = name_to_dev_t(resume_file); | ||
| 658 | if (!swsusp_resume_device) { | 672 | if (!swsusp_resume_device) { |
| 659 | if (!strlen(resume_file)) { | ||
| 660 | mutex_unlock(&pm_mutex); | ||
| 661 | return -ENOENT; | ||
| 662 | } | ||
| 663 | /* | 673 | /* |
| 664 | * Some device discovery might still be in progress; we need | 674 | * Some device discovery might still be in progress; we need |
| 665 | * to wait for this to finish. | 675 | * to wait for this to finish. |
| 666 | */ | 676 | */ |
| 667 | wait_for_device_probe(); | 677 | wait_for_device_probe(); |
| 678 | /* | ||
| 679 | * We can't depend on SCSI devices being available after loading | ||
| 680 | * one of their modules until scsi_complete_async_scans() is | ||
| 681 | * called and the resume device usually is a SCSI one. | ||
| 682 | */ | ||
| 683 | scsi_complete_async_scans(); | ||
| 684 | |||
| 668 | swsusp_resume_device = name_to_dev_t(resume_file); | 685 | swsusp_resume_device = name_to_dev_t(resume_file); |
| 669 | pr_debug("PM: Resume from partition %s\n", resume_file); | 686 | if (!swsusp_resume_device) { |
| 670 | } else { | 687 | error = -ENODEV; |
| 671 | pr_debug("PM: Resume from partition %d:%d\n", | 688 | goto Unlock; |
| 672 | MAJOR(swsusp_resume_device), | 689 | } |
| 673 | MINOR(swsusp_resume_device)); | ||
| 674 | } | 690 | } |
| 675 | 691 | ||
| 676 | if (noresume) { | 692 | Check_image: |
| 677 | /** | 693 | pr_debug("PM: Resume from partition %d:%d\n", |
| 678 | * FIXME: If noresume is specified, we need to find the | 694 | 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 | 695 | ||
| 685 | pr_debug("PM: Checking hibernation image.\n"); | 696 | pr_debug("PM: Checking hibernation image.\n"); |
| 686 | error = swsusp_check(); | 697 | error = swsusp_check(); |
diff --git a/kernel/power/main.c b/kernel/power/main.c index f172f41858bb..f99ed6a75eac 100644 --- a/kernel/power/main.c +++ b/kernel/power/main.c | |||
| @@ -291,20 +291,26 @@ static int suspend_enter(suspend_state_t state) | |||
| 291 | 291 | ||
| 292 | device_pm_lock(); | 292 | device_pm_lock(); |
| 293 | 293 | ||
| 294 | if (suspend_ops->prepare) { | ||
| 295 | error = suspend_ops->prepare(); | ||
| 296 | if (error) | ||
| 297 | goto Done; | ||
| 298 | } | ||
| 299 | |||
| 294 | error = device_power_down(PMSG_SUSPEND); | 300 | error = device_power_down(PMSG_SUSPEND); |
| 295 | if (error) { | 301 | if (error) { |
| 296 | printk(KERN_ERR "PM: Some devices failed to power down\n"); | 302 | printk(KERN_ERR "PM: Some devices failed to power down\n"); |
| 297 | goto Done; | 303 | goto Platfrom_finish; |
| 298 | } | 304 | } |
| 299 | 305 | ||
| 300 | if (suspend_ops->prepare) { | 306 | if (suspend_ops->prepare_late) { |
| 301 | error = suspend_ops->prepare(); | 307 | error = suspend_ops->prepare_late(); |
| 302 | if (error) | 308 | if (error) |
| 303 | goto Power_up_devices; | 309 | goto Power_up_devices; |
| 304 | } | 310 | } |
| 305 | 311 | ||
| 306 | if (suspend_test(TEST_PLATFORM)) | 312 | if (suspend_test(TEST_PLATFORM)) |
| 307 | goto Platfrom_finish; | 313 | goto Platform_wake; |
| 308 | 314 | ||
| 309 | error = disable_nonboot_cpus(); | 315 | error = disable_nonboot_cpus(); |
| 310 | if (error || suspend_test(TEST_CPUS)) | 316 | if (error || suspend_test(TEST_CPUS)) |
| @@ -326,13 +332,17 @@ static int suspend_enter(suspend_state_t state) | |||
| 326 | Enable_cpus: | 332 | Enable_cpus: |
| 327 | enable_nonboot_cpus(); | 333 | enable_nonboot_cpus(); |
| 328 | 334 | ||
| 329 | Platfrom_finish: | 335 | Platform_wake: |
| 330 | if (suspend_ops->finish) | 336 | if (suspend_ops->wake) |
| 331 | suspend_ops->finish(); | 337 | suspend_ops->wake(); |
| 332 | 338 | ||
| 333 | Power_up_devices: | 339 | Power_up_devices: |
| 334 | device_power_up(PMSG_RESUME); | 340 | device_power_up(PMSG_RESUME); |
| 335 | 341 | ||
| 342 | Platfrom_finish: | ||
| 343 | if (suspend_ops->finish) | ||
| 344 | suspend_ops->finish(); | ||
| 345 | |||
| 336 | Done: | 346 | Done: |
| 337 | device_pm_unlock(); | 347 | device_pm_unlock(); |
| 338 | 348 | ||
diff --git a/kernel/power/swap.c b/kernel/power/swap.c index 505f319e489c..8ba052c86d48 100644 --- a/kernel/power/swap.c +++ b/kernel/power/swap.c | |||
| @@ -64,8 +64,6 @@ static int submit(int rw, pgoff_t page_off, struct page *page, | |||
| 64 | struct bio *bio; | 64 | struct bio *bio; |
| 65 | 65 | ||
| 66 | bio = bio_alloc(__GFP_WAIT | __GFP_HIGH, 1); | 66 | bio = bio_alloc(__GFP_WAIT | __GFP_HIGH, 1); |
| 67 | if (!bio) | ||
| 68 | return -ENOMEM; | ||
| 69 | bio->bi_sector = page_off * (PAGE_SIZE >> 9); | 67 | bio->bi_sector = page_off * (PAGE_SIZE >> 9); |
| 70 | bio->bi_bdev = resume_bdev; | 68 | bio->bi_bdev = resume_bdev; |
| 71 | bio->bi_end_io = end_swap_bio_read; | 69 | bio->bi_end_io = end_swap_bio_read; |
diff --git a/kernel/power/user.c b/kernel/power/user.c index 6c85359364f2..ed97375daae9 100644 --- a/kernel/power/user.c +++ b/kernel/power/user.c | |||
| @@ -24,6 +24,7 @@ | |||
| 24 | #include <linux/cpu.h> | 24 | #include <linux/cpu.h> |
| 25 | #include <linux/freezer.h> | 25 | #include <linux/freezer.h> |
| 26 | #include <linux/smp_lock.h> | 26 | #include <linux/smp_lock.h> |
| 27 | #include <scsi/scsi_scan.h> | ||
| 27 | 28 | ||
| 28 | #include <asm/uaccess.h> | 29 | #include <asm/uaccess.h> |
| 29 | 30 | ||
| @@ -92,6 +93,7 @@ static int snapshot_open(struct inode *inode, struct file *filp) | |||
| 92 | filp->private_data = data; | 93 | filp->private_data = data; |
| 93 | memset(&data->handle, 0, sizeof(struct snapshot_handle)); | 94 | memset(&data->handle, 0, sizeof(struct snapshot_handle)); |
| 94 | if ((filp->f_flags & O_ACCMODE) == O_RDONLY) { | 95 | if ((filp->f_flags & O_ACCMODE) == O_RDONLY) { |
| 96 | /* Hibernating. The image device should be accessible. */ | ||
| 95 | data->swap = swsusp_resume_device ? | 97 | data->swap = swsusp_resume_device ? |
| 96 | swap_type_of(swsusp_resume_device, 0, NULL) : -1; | 98 | swap_type_of(swsusp_resume_device, 0, NULL) : -1; |
| 97 | data->mode = O_RDONLY; | 99 | data->mode = O_RDONLY; |
| @@ -99,6 +101,13 @@ static int snapshot_open(struct inode *inode, struct file *filp) | |||
| 99 | if (error) | 101 | if (error) |
| 100 | pm_notifier_call_chain(PM_POST_HIBERNATION); | 102 | pm_notifier_call_chain(PM_POST_HIBERNATION); |
| 101 | } else { | 103 | } else { |
| 104 | /* | ||
| 105 | * Resuming. We may need to wait for the image device to | ||
| 106 | * appear. | ||
| 107 | */ | ||
| 108 | wait_for_device_probe(); | ||
| 109 | scsi_complete_async_scans(); | ||
| 110 | |||
| 102 | data->swap = -1; | 111 | data->swap = -1; |
| 103 | data->mode = O_WRONLY; | 112 | data->mode = O_WRONLY; |
| 104 | error = pm_notifier_call_chain(PM_RESTORE_PREPARE); | 113 | error = pm_notifier_call_chain(PM_RESTORE_PREPARE); |
