1
2
3
4
5
6
7
8
9
10
11
12#include <linux/suspend.h>
13#include <linux/syscalls.h>
14#include <linux/reboot.h>
15#include <linux/string.h>
16#include <linux/device.h>
17#include <linux/kmod.h>
18#include <linux/delay.h>
19#include <linux/fs.h>
20#include <linux/mount.h>
21#include <linux/pm.h>
22#include <linux/console.h>
23#include <linux/cpu.h>
24#include <linux/freezer.h>
25#include <scsi/scsi_scan.h>
26#include <asm/suspend.h>
27
28#include "power.h"
29
30
31static int noresume = 0;
32static char resume_file[256] = CONFIG_PM_STD_PARTITION;
33dev_t swsusp_resume_device;
34sector_t swsusp_resume_block;
35
36enum {
37 HIBERNATION_INVALID,
38 HIBERNATION_PLATFORM,
39 HIBERNATION_TEST,
40 HIBERNATION_TESTPROC,
41 HIBERNATION_SHUTDOWN,
42 HIBERNATION_REBOOT,
43
44 __HIBERNATION_AFTER_LAST
45};
46#define HIBERNATION_MAX (__HIBERNATION_AFTER_LAST-1)
47#define HIBERNATION_FIRST (HIBERNATION_INVALID + 1)
48
49static int hibernation_mode = HIBERNATION_SHUTDOWN;
50
51static struct platform_hibernation_ops *hibernation_ops;
52
53
54
55
56
57
58void hibernation_set_ops(struct platform_hibernation_ops *ops)
59{
60 if (ops && !(ops->begin && ops->end && ops->pre_snapshot
61 && ops->prepare && ops->finish && ops->enter && ops->pre_restore
62 && ops->restore_cleanup)) {
63 WARN_ON(1);
64 return;
65 }
66 mutex_lock(&pm_mutex);
67 hibernation_ops = ops;
68 if (ops)
69 hibernation_mode = HIBERNATION_PLATFORM;
70 else if (hibernation_mode == HIBERNATION_PLATFORM)
71 hibernation_mode = HIBERNATION_SHUTDOWN;
72
73 mutex_unlock(&pm_mutex);
74}
75
76static bool entering_platform_hibernation;
77
78bool system_entering_hibernation(void)
79{
80 return entering_platform_hibernation;
81}
82EXPORT_SYMBOL(system_entering_hibernation);
83
84#ifdef CONFIG_PM_DEBUG
85static void hibernation_debug_sleep(void)
86{
87 printk(KERN_INFO "hibernation debug: Waiting for 5 seconds.\n");
88 mdelay(5000);
89}
90
91static int hibernation_testmode(int mode)
92{
93 if (hibernation_mode == mode) {
94 hibernation_debug_sleep();
95 return 1;
96 }
97 return 0;
98}
99
100static int hibernation_test(int level)
101{
102 if (pm_test_level == level) {
103 hibernation_debug_sleep();
104 return 1;
105 }
106 return 0;
107}
108#else
109static int hibernation_testmode(int mode) { return 0; }
110static int hibernation_test(int level) { return 0; }
111#endif
112
113
114
115
116
117
118static int platform_begin(int platform_mode)
119{
120 return (platform_mode && hibernation_ops) ?
121 hibernation_ops->begin() : 0;
122}
123
124
125
126
127
128
129static void platform_end(int platform_mode)
130{
131 if (platform_mode && hibernation_ops)
132 hibernation_ops->end();
133}
134
135
136
137
138
139
140static int platform_pre_snapshot(int platform_mode)
141{
142 return (platform_mode && hibernation_ops) ?
143 hibernation_ops->pre_snapshot() : 0;
144}
145
146
147
148
149
150
151static void platform_leave(int platform_mode)
152{
153 if (platform_mode && hibernation_ops)
154 hibernation_ops->leave();
155}
156
157
158
159
160
161
162static void platform_finish(int platform_mode)
163{
164 if (platform_mode && hibernation_ops)
165 hibernation_ops->finish();
166}
167
168
169
170
171
172
173
174static int platform_pre_restore(int platform_mode)
175{
176 return (platform_mode && hibernation_ops) ?
177 hibernation_ops->pre_restore() : 0;
178}
179
180
181
182
183
184
185
186
187static void platform_restore_cleanup(int platform_mode)
188{
189 if (platform_mode && hibernation_ops)
190 hibernation_ops->restore_cleanup();
191}
192
193
194
195
196
197
198static void platform_recover(int platform_mode)
199{
200 if (platform_mode && hibernation_ops && hibernation_ops->recover)
201 hibernation_ops->recover();
202}
203
204
205
206
207
208
209
210static int create_image(int platform_mode)
211{
212 int error;
213
214 error = arch_prepare_suspend();
215 if (error)
216 return error;
217
218
219
220
221
222
223
224 error = dpm_suspend_noirq(PMSG_FREEZE);
225 if (error) {
226 printk(KERN_ERR "PM: Some devices failed to power down, "
227 "aborting hibernation\n");
228 return error;
229 }
230
231 error = platform_pre_snapshot(platform_mode);
232 if (error || hibernation_test(TEST_PLATFORM))
233 goto Platform_finish;
234
235 error = disable_nonboot_cpus();
236 if (error || hibernation_test(TEST_CPUS)
237 || hibernation_testmode(HIBERNATION_TEST))
238 goto Enable_cpus;
239
240 local_irq_disable();
241
242 error = sysdev_suspend(PMSG_FREEZE);
243 if (error) {
244 printk(KERN_ERR "PM: Some system devices failed to power down, "
245 "aborting hibernation\n");
246 goto Enable_irqs;
247 }
248
249 if (hibernation_test(TEST_CORE))
250 goto Power_up;
251
252 in_suspend = 1;
253 save_processor_state();
254 error = swsusp_arch_suspend();
255 if (error)
256 printk(KERN_ERR "PM: Error %d creating hibernation image\n",
257 error);
258
259 restore_processor_state();
260 if (!in_suspend)
261 platform_leave(platform_mode);
262
263 Power_up:
264 sysdev_resume();
265
266
267
268
269 Enable_irqs:
270 local_irq_enable();
271
272 Enable_cpus:
273 enable_nonboot_cpus();
274
275 Platform_finish:
276 platform_finish(platform_mode);
277
278 dpm_resume_noirq(in_suspend ?
279 (error ? PMSG_RECOVER : PMSG_THAW) : PMSG_RESTORE);
280
281 return error;
282}
283
284
285
286
287
288
289
290
291
292
293int hibernation_snapshot(int platform_mode)
294{
295 int error;
296
297 error = platform_begin(platform_mode);
298 if (error)
299 return error;
300
301
302 error = hibernate_preallocate_memory();
303 if (error)
304 goto Close;
305
306 suspend_console();
307 error = dpm_suspend_start(PMSG_FREEZE);
308 if (error)
309 goto Recover_platform;
310
311 if (hibernation_test(TEST_DEVICES))
312 goto Recover_platform;
313
314 error = create_image(platform_mode);
315
316
317 Resume_devices:
318
319 if (error || !in_suspend)
320 swsusp_free();
321
322 dpm_resume_end(in_suspend ?
323 (error ? PMSG_RECOVER : PMSG_THAW) : PMSG_RESTORE);
324 resume_console();
325 Close:
326 platform_end(platform_mode);
327 return error;
328
329 Recover_platform:
330 platform_recover(platform_mode);
331 goto Resume_devices;
332}
333
334
335
336
337
338
339
340
341
342static int resume_target_kernel(bool platform_mode)
343{
344 int error;
345
346 error = dpm_suspend_noirq(PMSG_QUIESCE);
347 if (error) {
348 printk(KERN_ERR "PM: Some devices failed to power down, "
349 "aborting resume\n");
350 return error;
351 }
352
353 error = platform_pre_restore(platform_mode);
354 if (error)
355 goto Cleanup;
356
357 error = disable_nonboot_cpus();
358 if (error)
359 goto Enable_cpus;
360
361 local_irq_disable();
362
363 error = sysdev_suspend(PMSG_QUIESCE);
364 if (error)
365 goto Enable_irqs;
366
367
368 save_processor_state();
369 error = restore_highmem();
370 if (!error) {
371 error = swsusp_arch_resume();
372
373
374
375
376
377 BUG_ON(!error);
378
379 restore_highmem();
380 }
381
382
383
384
385
386 swsusp_free();
387 restore_processor_state();
388 touch_softlockup_watchdog();
389
390 sysdev_resume();
391
392 Enable_irqs:
393 local_irq_enable();
394
395 Enable_cpus:
396 enable_nonboot_cpus();
397
398 Cleanup:
399 platform_restore_cleanup(platform_mode);
400
401 dpm_resume_noirq(PMSG_RECOVER);
402
403 return error;
404}
405
406
407
408
409
410
411
412
413
414
415int hibernation_restore(int platform_mode)
416{
417 int error;
418
419 pm_prepare_console();
420 suspend_console();
421 error = dpm_suspend_start(PMSG_QUIESCE);
422 if (!error) {
423 error = resume_target_kernel(platform_mode);
424 dpm_resume_end(PMSG_RECOVER);
425 }
426 resume_console();
427 pm_restore_console();
428 return error;
429}
430
431
432
433
434
435
436int hibernation_platform_enter(void)
437{
438 int error;
439
440 if (!hibernation_ops)
441 return -ENOSYS;
442
443
444
445
446
447
448 error = hibernation_ops->begin();
449 if (error)
450 goto Close;
451
452 entering_platform_hibernation = true;
453 suspend_console();
454 error = dpm_suspend_start(PMSG_HIBERNATE);
455 if (error) {
456 if (hibernation_ops->recover)
457 hibernation_ops->recover();
458 goto Resume_devices;
459 }
460
461 error = dpm_suspend_noirq(PMSG_HIBERNATE);
462 if (error)
463 goto Resume_devices;
464
465 error = hibernation_ops->prepare();
466 if (error)
467 goto Platform_finish;
468
469 error = disable_nonboot_cpus();
470 if (error)
471 goto Platform_finish;
472
473 local_irq_disable();
474 sysdev_suspend(PMSG_HIBERNATE);
475 hibernation_ops->enter();
476
477 while (1);
478
479
480
481
482
483 Platform_finish:
484 hibernation_ops->finish();
485
486 dpm_suspend_noirq(PMSG_RESTORE);
487
488 Resume_devices:
489 entering_platform_hibernation = false;
490 dpm_resume_end(PMSG_RESTORE);
491 resume_console();
492
493 Close:
494 hibernation_ops->end();
495
496 return error;
497}
498
499
500
501
502
503
504
505
506static void power_down(void)
507{
508 switch (hibernation_mode) {
509 case HIBERNATION_TEST:
510 case HIBERNATION_TESTPROC:
511 break;
512 case HIBERNATION_REBOOT:
513 kernel_restart(NULL);
514 break;
515 case HIBERNATION_PLATFORM:
516 hibernation_platform_enter();
517 case HIBERNATION_SHUTDOWN:
518 kernel_power_off();
519 break;
520 }
521 kernel_halt();
522
523
524
525
526 printk(KERN_CRIT "PM: Please power down manually\n");
527 while(1);
528}
529
530static int prepare_processes(void)
531{
532 int error = 0;
533
534 if (freeze_processes()) {
535 error = -EBUSY;
536 thaw_processes();
537 }
538 return error;
539}
540
541
542
543
544
545int hibernate(void)
546{
547 int error;
548
549 mutex_lock(&pm_mutex);
550
551 if (!atomic_add_unless(&snapshot_device_available, -1, 0)) {
552 error = -EBUSY;
553 goto Unlock;
554 }
555
556 pm_prepare_console();
557 error = pm_notifier_call_chain(PM_HIBERNATION_PREPARE);
558 if (error)
559 goto Exit;
560
561 error = usermodehelper_disable();
562 if (error)
563 goto Exit;
564
565
566 error = create_basic_memory_bitmaps();
567 if (error)
568 goto Exit;
569
570 printk(KERN_INFO "PM: Syncing filesystems ... ");
571 sys_sync();
572 printk("done.\n");
573
574 error = prepare_processes();
575 if (error)
576 goto Finish;
577
578 if (hibernation_test(TEST_FREEZER))
579 goto Thaw;
580
581 if (hibernation_testmode(HIBERNATION_TESTPROC))
582 goto Thaw;
583
584 error = hibernation_snapshot(hibernation_mode == HIBERNATION_PLATFORM);
585 if (error)
586 goto Thaw;
587
588 if (in_suspend) {
589 unsigned int flags = 0;
590
591 if (hibernation_mode == HIBERNATION_PLATFORM)
592 flags |= SF_PLATFORM_MODE;
593 pr_debug("PM: writing image.\n");
594 error = swsusp_write(flags);
595 swsusp_free();
596 if (!error)
597 power_down();
598 } else {
599 pr_debug("PM: Image restored successfully.\n");
600 }
601
602 Thaw:
603 thaw_processes();
604 Finish:
605 free_basic_memory_bitmaps();
606 usermodehelper_enable();
607 Exit:
608 pm_notifier_call_chain(PM_POST_HIBERNATION);
609 pm_restore_console();
610 atomic_inc(&snapshot_device_available);
611 Unlock:
612 mutex_unlock(&pm_mutex);
613 return error;
614}
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629static int software_resume(void)
630{
631 int error;
632 unsigned int flags;
633
634
635
636
637 if (noresume)
638 return 0;
639
640
641
642
643
644
645
646
647
648
649
650 mutex_lock_nested(&pm_mutex, SINGLE_DEPTH_NESTING);
651
652 if (swsusp_resume_device)
653 goto Check_image;
654
655 if (!strlen(resume_file)) {
656 error = -ENOENT;
657 goto Unlock;
658 }
659
660 pr_debug("PM: Checking image partition %s\n", resume_file);
661
662
663 swsusp_resume_device = name_to_dev_t(resume_file);
664 if (!swsusp_resume_device) {
665
666
667
668
669 wait_for_device_probe();
670
671
672
673
674
675 scsi_complete_async_scans();
676
677 swsusp_resume_device = name_to_dev_t(resume_file);
678 if (!swsusp_resume_device) {
679 error = -ENODEV;
680 goto Unlock;
681 }
682 }
683
684 Check_image:
685 pr_debug("PM: Resume from partition %d:%d\n",
686 MAJOR(swsusp_resume_device), MINOR(swsusp_resume_device));
687
688 pr_debug("PM: Checking hibernation image.\n");
689 error = swsusp_check();
690 if (error)
691 goto Unlock;
692
693
694 if (!atomic_add_unless(&snapshot_device_available, -1, 0)) {
695 error = -EBUSY;
696 swsusp_close(FMODE_READ);
697 goto Unlock;
698 }
699
700 pm_prepare_console();
701 error = pm_notifier_call_chain(PM_RESTORE_PREPARE);
702 if (error)
703 goto close_finish;
704
705 error = usermodehelper_disable();
706 if (error)
707 goto close_finish;
708
709 error = create_basic_memory_bitmaps();
710 if (error)
711 goto close_finish;
712
713 pr_debug("PM: Preparing processes for restore.\n");
714 error = prepare_processes();
715 if (error) {
716 swsusp_close(FMODE_READ);
717 goto Done;
718 }
719
720 pr_debug("PM: Reading hibernation image.\n");
721
722 error = swsusp_read(&flags);
723 swsusp_close(FMODE_READ);
724 if (!error)
725 hibernation_restore(flags & SF_PLATFORM_MODE);
726
727 printk(KERN_ERR "PM: Restore failed, recovering.\n");
728 swsusp_free();
729 thaw_processes();
730 Done:
731 free_basic_memory_bitmaps();
732 usermodehelper_enable();
733 Finish:
734 pm_notifier_call_chain(PM_POST_RESTORE);
735 pm_restore_console();
736 atomic_inc(&snapshot_device_available);
737
738 Unlock:
739 mutex_unlock(&pm_mutex);
740 pr_debug("PM: Resume from disk failed.\n");
741 return error;
742close_finish:
743 swsusp_close(FMODE_READ);
744 goto Finish;
745}
746
747late_initcall(software_resume);
748
749
750static const char * const hibernation_modes[] = {
751 [HIBERNATION_PLATFORM] = "platform",
752 [HIBERNATION_SHUTDOWN] = "shutdown",
753 [HIBERNATION_REBOOT] = "reboot",
754 [HIBERNATION_TEST] = "test",
755 [HIBERNATION_TESTPROC] = "testproc",
756};
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784static ssize_t disk_show(struct kobject *kobj, struct kobj_attribute *attr,
785 char *buf)
786{
787 int i;
788 char *start = buf;
789
790 for (i = HIBERNATION_FIRST; i <= HIBERNATION_MAX; i++) {
791 if (!hibernation_modes[i])
792 continue;
793 switch (i) {
794 case HIBERNATION_SHUTDOWN:
795 case HIBERNATION_REBOOT:
796 case HIBERNATION_TEST:
797 case HIBERNATION_TESTPROC:
798 break;
799 case HIBERNATION_PLATFORM:
800 if (hibernation_ops)
801 break;
802
803 continue;
804 }
805 if (i == hibernation_mode)
806 buf += sprintf(buf, "[%s] ", hibernation_modes[i]);
807 else
808 buf += sprintf(buf, "%s ", hibernation_modes[i]);
809 }
810 buf += sprintf(buf, "\n");
811 return buf-start;
812}
813
814
815static ssize_t disk_store(struct kobject *kobj, struct kobj_attribute *attr,
816 const char *buf, size_t n)
817{
818 int error = 0;
819 int i;
820 int len;
821 char *p;
822 int mode = HIBERNATION_INVALID;
823
824 p = memchr(buf, '\n', n);
825 len = p ? p - buf : n;
826
827 mutex_lock(&pm_mutex);
828 for (i = HIBERNATION_FIRST; i <= HIBERNATION_MAX; i++) {
829 if (len == strlen(hibernation_modes[i])
830 && !strncmp(buf, hibernation_modes[i], len)) {
831 mode = i;
832 break;
833 }
834 }
835 if (mode != HIBERNATION_INVALID) {
836 switch (mode) {
837 case HIBERNATION_SHUTDOWN:
838 case HIBERNATION_REBOOT:
839 case HIBERNATION_TEST:
840 case HIBERNATION_TESTPROC:
841 hibernation_mode = mode;
842 break;
843 case HIBERNATION_PLATFORM:
844 if (hibernation_ops)
845 hibernation_mode = mode;
846 else
847 error = -EINVAL;
848 }
849 } else
850 error = -EINVAL;
851
852 if (!error)
853 pr_debug("PM: Hibernation mode set to '%s'\n",
854 hibernation_modes[mode]);
855 mutex_unlock(&pm_mutex);
856 return error ? error : n;
857}
858
859power_attr(disk);
860
861static ssize_t resume_show(struct kobject *kobj, struct kobj_attribute *attr,
862 char *buf)
863{
864 return sprintf(buf,"%d:%d\n", MAJOR(swsusp_resume_device),
865 MINOR(swsusp_resume_device));
866}
867
868static ssize_t resume_store(struct kobject *kobj, struct kobj_attribute *attr,
869 const char *buf, size_t n)
870{
871 unsigned int maj, min;
872 dev_t res;
873 int ret = -EINVAL;
874
875 if (sscanf(buf, "%u:%u", &maj, &min) != 2)
876 goto out;
877
878 res = MKDEV(maj,min);
879 if (maj != MAJOR(res) || min != MINOR(res))
880 goto out;
881
882 mutex_lock(&pm_mutex);
883 swsusp_resume_device = res;
884 mutex_unlock(&pm_mutex);
885 printk(KERN_INFO "PM: Starting manual resume from disk\n");
886 noresume = 0;
887 software_resume();
888 ret = n;
889 out:
890 return ret;
891}
892
893power_attr(resume);
894
895static ssize_t image_size_show(struct kobject *kobj, struct kobj_attribute *attr,
896 char *buf)
897{
898 return sprintf(buf, "%lu\n", image_size);
899}
900
901static ssize_t image_size_store(struct kobject *kobj, struct kobj_attribute *attr,
902 const char *buf, size_t n)
903{
904 unsigned long size;
905
906 if (sscanf(buf, "%lu", &size) == 1) {
907 image_size = size;
908 return n;
909 }
910
911 return -EINVAL;
912}
913
914power_attr(image_size);
915
916static struct attribute * g[] = {
917 &disk_attr.attr,
918 &resume_attr.attr,
919 &image_size_attr.attr,
920 NULL,
921};
922
923
924static struct attribute_group attr_group = {
925 .attrs = g,
926};
927
928
929static int __init pm_disk_init(void)
930{
931 return sysfs_create_group(power_kobj, &attr_group);
932}
933
934core_initcall(pm_disk_init);
935
936
937static int __init resume_setup(char *str)
938{
939 if (noresume)
940 return 1;
941
942 strncpy( resume_file, str, 255 );
943 return 1;
944}
945
946static int __init resume_offset_setup(char *str)
947{
948 unsigned long long offset;
949
950 if (noresume)
951 return 1;
952
953 if (sscanf(str, "%llu", &offset) == 1)
954 swsusp_resume_block = offset;
955
956 return 1;
957}
958
959static int __init noresume_setup(char *str)
960{
961 noresume = 1;
962 return 1;
963}
964
965__setup("noresume", noresume_setup);
966__setup("resume_offset=", resume_offset_setup);
967__setup("resume=", resume_setup);
968