13 #include <linux/export.h>
16 #include <linux/reboot.h>
17 #include <linux/string.h>
18 #include <linux/device.h>
29 #include <linux/ctype.h>
35 static int nocompress;
37 static int resume_wait;
38 static int resume_delay;
39 static char resume_file[256] = CONFIG_PM_STD_PARTITION;
55 #define HIBERNATION_MAX (__HIBERNATION_AFTER_LAST-1)
56 #define HIBERNATION_FIRST (HIBERNATION_INVALID + 1)
77 hibernation_ops = ops;
83 unlock_system_sleep();
86 static bool entering_platform_hibernation;
90 return entering_platform_hibernation;
94 #ifdef CONFIG_PM_DEBUG
95 static void hibernation_debug_sleep(
void)
101 static int hibernation_test(
int level)
103 if (pm_test_level == level) {
104 hibernation_debug_sleep();
110 static int hibernation_test(
int level) {
return 0; }
117 static int platform_begin(
int platform_mode)
119 return (platform_mode && hibernation_ops) ?
120 hibernation_ops->
begin() : 0;
127 static void platform_end(
int platform_mode)
129 if (platform_mode && hibernation_ops)
130 hibernation_ops->
end();
141 static int platform_pre_snapshot(
int platform_mode)
143 return (platform_mode && hibernation_ops) ?
156 static void platform_leave(
int platform_mode)
158 if (platform_mode && hibernation_ops)
159 hibernation_ops->
leave();
171 static void platform_finish(
int platform_mode)
173 if (platform_mode && hibernation_ops)
174 hibernation_ops->
finish();
187 static int platform_pre_restore(
int platform_mode)
189 return (platform_mode && hibernation_ops) ?
204 static void platform_restore_cleanup(
int platform_mode)
206 if (platform_mode && hibernation_ops)
214 static void platform_recover(
int platform_mode)
216 if (platform_mode && hibernation_ops && hibernation_ops->
recover)
228 unsigned nr_pages,
char *
msg)
230 s64 elapsed_centisecs64;
235 elapsed_centisecs64 = timeval_to_ns(stop) - timeval_to_ns(start);
237 centisecs = elapsed_centisecs64;
241 kps = (k * 100) / centisecs;
242 printk(
KERN_INFO "PM: %s %d kbytes in %d.%02d seconds (%d.%02d MB/s)\n",
244 centisecs / 100, centisecs % 100,
245 kps / 1000, (kps % 1000) / 10);
257 static int create_image(
int platform_mode)
264 "aborting hibernation\n");
268 error = platform_pre_snapshot(platform_mode);
270 goto Platform_finish;
272 error = disable_nonboot_cpus();
273 if (error || hibernation_test(
TEST_CPUS))
278 error = syscore_suspend();
281 "aborting hibernation\n");
297 events_check_enabled =
false;
298 platform_leave(platform_mode);
308 enable_nonboot_cpus();
311 platform_finish(platform_mode);
330 error = platform_begin(platform_mode);
366 platform_recover(platform_mode);
368 error = create_image(platform_mode);
391 platform_end(platform_mode);
410 static int resume_target_kernel(
bool platform_mode)
417 "aborting resume\n");
421 error = platform_pre_restore(platform_mode);
425 error = disable_nonboot_cpus();
431 error = syscore_suspend();
436 error = restore_highmem();
466 enable_nonboot_cpus();
469 platform_restore_cleanup(platform_mode);
493 error = resume_target_kernel(platform_mode);
510 if (!hibernation_ops)
518 error = hibernation_ops->
begin();
522 entering_platform_hibernation =
true;
536 error = hibernation_ops->
prepare();
538 goto Platform_finish;
540 error = disable_nonboot_cpus();
542 goto Platform_finish;
551 hibernation_ops->
enter();
558 enable_nonboot_cpus();
561 hibernation_ops->
finish();
566 entering_platform_hibernation =
false;
572 hibernation_ops->
end();
586 #ifdef CONFIG_SUSPEND
590 switch (hibernation_mode) {
599 #ifdef CONFIG_SUSPEND
600 case HIBERNATION_SUSPEND:
612 error = swsusp_unmark();
665 unsigned int flags = 0;
682 pr_debug(
"PM: Image restored successfully.\n");
698 unlock_system_sleep();
718 static int software_resume(
void)
744 if (!
strlen(resume_file)) {
749 pr_debug(
"PM: Checking hibernation image partition %s\n", resume_file);
754 ssleep(resume_delay);
764 if (
isdigit(resume_file[0]) && resume_wait) {
791 pr_debug(
"PM: Hibernation image partition %d:%d present\n",
794 pr_debug(
"PM: Looking for hibernation image.\n");
815 pr_debug(
"PM: Preparing processes for restore.\n");
822 pr_debug(
"PM: Loading hibernation image.\n");
829 printk(
KERN_ERR "PM: Failed to load hibernation image, recovering.\n");
841 pr_debug(
"PM: Hibernation image not present or could not be loaded.\n");
851 static const char *
const hibernation_modes[] = {
855 #ifdef CONFIG_SUSPEND
856 [HIBERNATION_SUSPEND] =
"suspend",
893 if (!hibernation_modes[i])
898 #ifdef CONFIG_SUSPEND
899 case HIBERNATION_SUSPEND:
908 if (i == hibernation_mode)
909 buf +=
sprintf(buf,
"[%s] ", hibernation_modes[i]);
911 buf +=
sprintf(buf,
"%s ", hibernation_modes[i]);
918 const char *buf,
size_t n)
927 len = p ? p - buf :
n;
931 if (len ==
strlen(hibernation_modes[i])
932 && !
strncmp(buf, hibernation_modes[i], len)) {
941 #ifdef CONFIG_SUSPEND
942 case HIBERNATION_SUSPEND:
944 hibernation_mode =
mode;
948 hibernation_mode =
mode;
956 pr_debug(
"PM: Hibernation mode set to '%s'\n",
957 hibernation_modes[mode]);
958 unlock_system_sleep();
959 return error ? error :
n;
972 const char *buf,
size_t n)
978 if (
sscanf(buf,
"%u:%u", &maj, &min) != 2)
981 res =
MKDEV(maj,min);
987 unlock_system_sleep();
1005 const char *buf,
size_t n)
1009 if (
sscanf(buf,
"%lu", &size) == 1) {
1027 const char *buf,
size_t n)
1031 if (
sscanf(buf,
"%lu", &size) == 1) {
1044 &image_size_attr.attr,
1045 &reserved_size_attr.attr,
1055 static int __init pm_disk_init(
void)
1063 static int __init resume_setup(
char *
str)
1068 strncpy( resume_file, str, 255 );
1072 static int __init resume_offset_setup(
char *str)
1074 unsigned long long offset;
1079 if (
sscanf(str,
"%llu", &offset) == 1)
1085 static int __init hibernate_setup(
char *str)
1087 if (!
strncmp(str,
"noresume", 8))
1089 else if (!
strncmp(str,
"nocompress", 10))
1094 static int __init noresume_setup(
char *str)
1100 static int __init resumewait_setup(
char *str)
1106 static int __init resumedelay_setup(
char *str)
1112 __setup(
"noresume", noresume_setup);
1113 __setup(
"resume_offset=", resume_offset_setup);
1114 __setup(
"resume=", resume_setup);
1115 __setup(
"hibernate=", hibernate_setup);
1116 __setup(
"resumewait", resumewait_setup);
1117 __setup(
"resumedelay=", resumedelay_setup);