aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'kernel')
-rw-r--r--kernel/power/power.h1
-rw-r--r--kernel/power/swsusp.c190
2 files changed, 65 insertions, 126 deletions
diff --git a/kernel/power/power.h b/kernel/power/power.h
index 273a5b1d70..7e8492fd14 100644
--- a/kernel/power/power.h
+++ b/kernel/power/power.h
@@ -16,7 +16,6 @@ struct swsusp_info {
16 int cpus; 16 int cpus;
17 unsigned long image_pages; 17 unsigned long image_pages;
18 unsigned long pages; 18 unsigned long pages;
19 swp_entry_t start;
20} __attribute__((aligned(PAGE_SIZE))); 19} __attribute__((aligned(PAGE_SIZE)));
21 20
22 21
diff --git a/kernel/power/swsusp.c b/kernel/power/swsusp.c
index 0479c9be7d..55a18d26ab 100644
--- a/kernel/power/swsusp.c
+++ b/kernel/power/swsusp.c
@@ -93,7 +93,7 @@ extern char resume_file[];
93 93
94static struct swsusp_header { 94static struct swsusp_header {
95 char reserved[PAGE_SIZE - 20 - sizeof(swp_entry_t)]; 95 char reserved[PAGE_SIZE - 20 - sizeof(swp_entry_t)];
96 swp_entry_t swsusp_info; 96 swp_entry_t image;
97 char orig_sig[10]; 97 char orig_sig[10];
98 char sig[10]; 98 char sig[10];
99} __attribute__((packed, aligned(PAGE_SIZE))) swsusp_header; 99} __attribute__((packed, aligned(PAGE_SIZE))) swsusp_header;
@@ -106,7 +106,7 @@ static struct swsusp_info swsusp_info;
106 106
107static unsigned short root_swap = 0xffff; 107static unsigned short root_swap = 0xffff;
108 108
109static int mark_swapfiles(swp_entry_t prev) 109static int mark_swapfiles(swp_entry_t start)
110{ 110{
111 int error; 111 int error;
112 112
@@ -117,7 +117,7 @@ static int mark_swapfiles(swp_entry_t prev)
117 !memcmp("SWAPSPACE2",swsusp_header.sig, 10)) { 117 !memcmp("SWAPSPACE2",swsusp_header.sig, 10)) {
118 memcpy(swsusp_header.orig_sig,swsusp_header.sig, 10); 118 memcpy(swsusp_header.orig_sig,swsusp_header.sig, 10);
119 memcpy(swsusp_header.sig,SWSUSP_SIG, 10); 119 memcpy(swsusp_header.sig,SWSUSP_SIG, 10);
120 swsusp_header.swsusp_info = prev; 120 swsusp_header.image = start;
121 error = rw_swap_page_sync(WRITE, 121 error = rw_swap_page_sync(WRITE,
122 swp_entry(root_swap, 0), 122 swp_entry(root_swap, 0),
123 virt_to_page((unsigned long) 123 virt_to_page((unsigned long)
@@ -423,22 +423,7 @@ static void init_header(unsigned int nr_pages)
423 swsusp_info.cpus = num_online_cpus(); 423 swsusp_info.cpus = num_online_cpus();
424 swsusp_info.image_pages = nr_pages; 424 swsusp_info.image_pages = nr_pages;
425 swsusp_info.pages = nr_pages + 425 swsusp_info.pages = nr_pages +
426 ((nr_pages * sizeof(long) + PAGE_SIZE - 1) >> PAGE_SHIFT); 426 ((nr_pages * sizeof(long) + PAGE_SIZE - 1) >> PAGE_SHIFT) + 1;
427}
428
429static int close_swap(void)
430{
431 swp_entry_t entry;
432 int error;
433
434 dump_info();
435 error = write_page((unsigned long)&swsusp_info, &entry);
436 if (!error) {
437 printk( "S" );
438 error = mark_swapfiles(entry);
439 printk( "|\n" );
440 }
441 return error;
442} 427}
443 428
444/** 429/**
@@ -522,6 +507,7 @@ int swsusp_write(struct pbe *pblist, unsigned int nr_pages)
522{ 507{
523 struct swap_map_page *swap_map; 508 struct swap_map_page *swap_map;
524 struct swap_map_handle handle; 509 struct swap_map_handle handle;
510 swp_entry_t start;
525 int error; 511 int error;
526 512
527 if ((error = swsusp_swap_check())) { 513 if ((error = swsusp_swap_check())) {
@@ -539,18 +525,23 @@ int swsusp_write(struct pbe *pblist, unsigned int nr_pages)
539 return -ENOMEM; 525 return -ENOMEM;
540 init_swap_map_handle(&handle, swap_map); 526 init_swap_map_handle(&handle, swap_map);
541 527
542 error = save_image_metadata(pblist, &handle); 528 error = swap_map_write_page(&handle, (unsigned long)&swsusp_info);
529 if (!error)
530 error = save_image_metadata(pblist, &handle);
543 if (!error) 531 if (!error)
544 error = save_image_data(pblist, &handle, nr_pages); 532 error = save_image_data(pblist, &handle, nr_pages);
545 if (error) 533 if (error)
546 goto Free_image_entries; 534 goto Free_image_entries;
547 535
548 swap_map = reverse_swap_map(swap_map); 536 swap_map = reverse_swap_map(swap_map);
549 error = save_swap_map(swap_map, &swsusp_info.start); 537 error = save_swap_map(swap_map, &start);
550 if (error) 538 if (error)
551 goto Free_map_entries; 539 goto Free_map_entries;
552 540
553 error = close_swap(); 541 dump_info();
542 printk( "S" );
543 error = mark_swapfiles(start);
544 printk( "|\n" );
554 if (error) 545 if (error)
555 goto Free_map_entries; 546 goto Free_map_entries;
556 547
@@ -840,70 +831,28 @@ static inline int swap_map_read_page(struct swap_map_handle *handle, void *buf)
840 return error; 831 return error;
841} 832}
842 833
843/* 834static int check_header(void)
844 * Sanity check if this image makes sense with this kernel/swap context
845 * I really don't think that it's foolproof but more than nothing..
846 */
847
848static const char *sanity_check(void)
849{ 835{
836 char *reason = NULL;
837
850 dump_info(); 838 dump_info();
851 if (swsusp_info.version_code != LINUX_VERSION_CODE) 839 if (swsusp_info.version_code != LINUX_VERSION_CODE)
852 return "kernel version"; 840 reason = "kernel version";
853 if (swsusp_info.num_physpages != num_physpages) 841 if (swsusp_info.num_physpages != num_physpages)
854 return "memory size"; 842 reason = "memory size";
855 if (strcmp(swsusp_info.uts.sysname,system_utsname.sysname)) 843 if (strcmp(swsusp_info.uts.sysname,system_utsname.sysname))
856 return "system type"; 844 reason = "system type";
857 if (strcmp(swsusp_info.uts.release,system_utsname.release)) 845 if (strcmp(swsusp_info.uts.release,system_utsname.release))
858 return "kernel release"; 846 reason = "kernel release";
859 if (strcmp(swsusp_info.uts.version,system_utsname.version)) 847 if (strcmp(swsusp_info.uts.version,system_utsname.version))
860 return "version"; 848 reason = "version";
861 if (strcmp(swsusp_info.uts.machine,system_utsname.machine)) 849 if (strcmp(swsusp_info.uts.machine,system_utsname.machine))
862 return "machine"; 850 reason = "machine";
863#if 0 851 if (reason) {
864 /* We can't use number of online CPUs when we use hotplug to remove them ;-))) */ 852 printk(KERN_ERR "swsusp: Resume mismatch: %s\n", reason);
865 if (swsusp_info.cpus != num_possible_cpus())
866 return "number of cpus";
867#endif
868 return NULL;
869}
870
871static int check_header(void)
872{
873 const char *reason = NULL;
874 int error;
875
876 if ((error = bio_read_page(swp_offset(swsusp_header.swsusp_info), &swsusp_info)))
877 return error;
878
879 /* Is this same machine? */
880 if ((reason = sanity_check())) {
881 printk(KERN_ERR "swsusp: Resume mismatch: %s\n",reason);
882 return -EPERM; 853 return -EPERM;
883 } 854 }
884 return error; 855 return 0;
885}
886
887static int check_sig(void)
888{
889 int error;
890
891 memset(&swsusp_header, 0, sizeof(swsusp_header));
892 if ((error = bio_read_page(0, &swsusp_header)))
893 return error;
894 if (!memcmp(SWSUSP_SIG, swsusp_header.sig, 10)) {
895 memcpy(swsusp_header.sig, swsusp_header.orig_sig, 10);
896
897 /*
898 * Reset swap signature now.
899 */
900 error = bio_write_page(0, &swsusp_header);
901 } else {
902 return -EINVAL;
903 }
904 if (!error)
905 pr_debug("swsusp: Signature found, resuming\n");
906 return error;
907} 856}
908 857
909/** 858/**
@@ -989,33 +938,29 @@ static int load_image_metadata(struct pbe *pblist, struct swap_map_handle *handl
989 return error; 938 return error;
990} 939}
991 940
992static int check_suspend_image(void) 941int swsusp_read(struct pbe **pblist_ptr)
993{
994 int error = 0;
995
996 if ((error = check_sig()))
997 return error;
998
999 if ((error = check_header()))
1000 return error;
1001
1002 return 0;
1003}
1004