diff options
Diffstat (limited to 'kernel/power/hibernate.c')
-rw-r--r-- | kernel/power/hibernate.c | 49 |
1 files changed, 30 insertions, 19 deletions
diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c index 37170d4dd9a6..df88d55dc436 100644 --- a/kernel/power/hibernate.c +++ b/kernel/power/hibernate.c | |||
@@ -35,7 +35,7 @@ | |||
35 | static int nocompress; | 35 | static int nocompress; |
36 | static int noresume; | 36 | static int noresume; |
37 | static int resume_wait; | 37 | static int resume_wait; |
38 | static int resume_delay; | 38 | static unsigned int resume_delay; |
39 | static char resume_file[256] = CONFIG_PM_STD_PARTITION; | 39 | static char resume_file[256] = CONFIG_PM_STD_PARTITION; |
40 | dev_t swsusp_resume_device; | 40 | dev_t swsusp_resume_device; |
41 | sector_t swsusp_resume_block; | 41 | sector_t swsusp_resume_block; |
@@ -228,19 +228,23 @@ static void platform_recover(int platform_mode) | |||
228 | void swsusp_show_speed(struct timeval *start, struct timeval *stop, | 228 | void swsusp_show_speed(struct timeval *start, struct timeval *stop, |
229 | unsigned nr_pages, char *msg) | 229 | unsigned nr_pages, char *msg) |
230 | { | 230 | { |
231 | s64 elapsed_centisecs64; | 231 | u64 elapsed_centisecs64; |
232 | int centisecs; | 232 | unsigned int centisecs; |
233 | int k; | 233 | unsigned int k; |
234 | int kps; | 234 | unsigned int kps; |
235 | 235 | ||
236 | elapsed_centisecs64 = timeval_to_ns(stop) - timeval_to_ns(start); | 236 | elapsed_centisecs64 = timeval_to_ns(stop) - timeval_to_ns(start); |
237 | /* | ||
238 | * If "(s64)elapsed_centisecs64 < 0", it will print long elapsed time, | ||
239 | * it is obvious enough for what went wrong. | ||
240 | */ | ||
237 | do_div(elapsed_centisecs64, NSEC_PER_SEC / 100); | 241 | do_div(elapsed_centisecs64, NSEC_PER_SEC / 100); |
238 | centisecs = elapsed_centisecs64; | 242 | centisecs = elapsed_centisecs64; |
239 | if (centisecs == 0) | 243 | if (centisecs == 0) |
240 | centisecs = 1; /* avoid div-by-zero */ | 244 | centisecs = 1; /* avoid div-by-zero */ |
241 | k = nr_pages * (PAGE_SIZE / 1024); | 245 | k = nr_pages * (PAGE_SIZE / 1024); |
242 | kps = (k * 100) / centisecs; | 246 | kps = (k * 100) / centisecs; |
243 | printk(KERN_INFO "PM: %s %d kbytes in %d.%02d seconds (%d.%02d MB/s)\n", | 247 | printk(KERN_INFO "PM: %s %u kbytes in %u.%02u seconds (%u.%02u MB/s)\n", |
244 | msg, k, | 248 | msg, k, |
245 | centisecs / 100, centisecs % 100, | 249 | centisecs / 100, centisecs % 100, |
246 | kps / 1000, (kps % 1000) / 10); | 250 | kps / 1000, (kps % 1000) / 10); |
@@ -595,7 +599,8 @@ static void power_down(void) | |||
595 | case HIBERNATION_PLATFORM: | 599 | case HIBERNATION_PLATFORM: |
596 | hibernation_platform_enter(); | 600 | hibernation_platform_enter(); |
597 | case HIBERNATION_SHUTDOWN: | 601 | case HIBERNATION_SHUTDOWN: |
598 | kernel_power_off(); | 602 | if (pm_power_off) |
603 | kernel_power_off(); | ||
599 | break; | 604 | break; |
600 | #ifdef CONFIG_SUSPEND | 605 | #ifdef CONFIG_SUSPEND |
601 | case HIBERNATION_SUSPEND: | 606 | case HIBERNATION_SUSPEND: |
@@ -623,7 +628,8 @@ static void power_down(void) | |||
623 | * corruption after resume. | 628 | * corruption after resume. |
624 | */ | 629 | */ |
625 | printk(KERN_CRIT "PM: Please power down manually\n"); | 630 | printk(KERN_CRIT "PM: Please power down manually\n"); |
626 | while(1); | 631 | while (1) |
632 | cpu_relax(); | ||
627 | } | 633 | } |
628 | 634 | ||
629 | /** | 635 | /** |
@@ -973,16 +979,20 @@ static ssize_t resume_show(struct kobject *kobj, struct kobj_attribute *attr, | |||
973 | static ssize_t resume_store(struct kobject *kobj, struct kobj_attribute *attr, | 979 | static ssize_t resume_store(struct kobject *kobj, struct kobj_attribute *attr, |
974 | const char *buf, size_t n) | 980 | const char *buf, size_t n) |
975 | { | 981 | { |
976 | unsigned int maj, min; | ||
977 | dev_t res; | 982 | dev_t res; |
978 | int ret = -EINVAL; | 983 | int len = n; |
984 | char *name; | ||
979 | 985 | ||
980 | if (sscanf(buf, "%u:%u", &maj, &min) != 2) | 986 | if (len && buf[len-1] == '\n') |
981 | goto out; | 987 | len--; |
988 | name = kstrndup(buf, len, GFP_KERNEL); | ||
989 | if (!name) | ||
990 | return -ENOMEM; | ||
982 | 991 | ||
983 | res = MKDEV(maj,min); | 992 | res = name_to_dev_t(name); |
984 | if (maj != MAJOR(res) || min != MINOR(res)) | 993 | kfree(name); |
985 | goto out; | 994 | if (!res) |
995 | return -EINVAL; | ||
986 | 996 | ||
987 | lock_system_sleep(); | 997 | lock_system_sleep(); |
988 | swsusp_resume_device = res; | 998 | swsusp_resume_device = res; |
@@ -990,9 +1000,7 @@ static ssize_t resume_store(struct kobject *kobj, struct kobj_attribute *attr, | |||
990 | printk(KERN_INFO "PM: Starting manual resume from disk\n"); | 1000 | printk(KERN_INFO "PM: Starting manual resume from disk\n"); |
991 | noresume = 0; | 1001 | noresume = 0; |
992 | software_resume(); | 1002 | software_resume(); |
993 | ret = n; | 1003 | return n; |
994 | out: | ||
995 | return ret; | ||
996 | } | 1004 | } |
997 | 1005 | ||
998 | power_attr(resume); | 1006 | power_attr(resume); |
@@ -1107,7 +1115,10 @@ static int __init resumewait_setup(char *str) | |||
1107 | 1115 | ||
1108 | static int __init resumedelay_setup(char *str) | 1116 | static int __init resumedelay_setup(char *str) |
1109 | { | 1117 | { |
1110 | resume_delay = simple_strtoul(str, NULL, 0); | 1118 | int rc = kstrtouint(str, 0, &resume_delay); |
1119 | |||
1120 | if (rc) | ||
1121 | return rc; | ||
1111 | return 1; | 1122 | return 1; |
1112 | } | 1123 | } |
1113 | 1124 | ||