]> git.neil.brown.name Git - history.git/commitdiff
[PATCH] swsusp: 64-bit compatibility
authorPavel Machek <pavel@ucw.cz>
Thu, 5 Dec 2002 14:09:22 +0000 (06:09 -0800)
committerLinus Torvalds <torvalds@home.transmeta.com>
Thu, 5 Dec 2002 14:09:22 +0000 (06:09 -0800)
This makes swsusp 64bit compatible, and makes it work in case of two
mirrors of physical memory (x86-64 works like that). It also contains
few accumulated cleanups.

kernel/suspend.c

index 838efbc167872097cc0bf86963006f3f615387ea..0dcb6d6b8e790061e5d16a947b8fffef9af18f21 100644 (file)
@@ -80,9 +80,9 @@ unsigned char software_suspend_enabled = 0;
 #endif
 
 #define TIMEOUT        (6 * HZ)                        /* Timeout for stopping processes */
-#define ADDRESS(x) ((unsigned long) phys_to_virt(((x) << PAGE_SHIFT)))
-
-extern int C_A_D;
+#define __ADDRESS(x)  ((unsigned long) phys_to_virt(x))
+#define ADDRESS(x) __ADDRESS((x) << PAGE_SHIFT)
+#define ADDRESS2(x) __ADDRESS(__pa(x))         /* Needed for x86-64 where some pages are in memory twice */
 
 /* References to section boundaries */
 extern char _text, _etext, _edata, __bss_start, _end;
@@ -145,10 +145,10 @@ static const char name_resume[] = "Resume Machine: ";
 /*
  * Debug
  */
-#undef DEBUG_DEFAULT
+#define        DEBUG_DEFAULT
 #undef DEBUG_PROCESS
 #undef DEBUG_SLOW
-#define TEST_SWSUSP 1          /* Set to 1 to reboot instead of halt machine after suspension */
+#define TEST_SWSUSP 0          /* Set to 1 to reboot instead of halt machine after suspension */
 
 #ifdef DEBUG_DEFAULT
 # define PRINTK(f, a...)       printk(f, ## a)
@@ -235,6 +235,7 @@ int freeze_processes(void)
        } while(todo);
        
        printk( "|\n" );
+       BUG_ON(in_atomic());
        return 0;
 }
 
@@ -322,20 +323,20 @@ static void mark_swapfiles(swp_entry_t prev, int mode)
        rw_swap_page_sync(READ, entry, page);
 
        if (mode == MARK_SWAP_RESUME) {
-               if (!memcmp("SUSP1R",cur->swh.magic.magic,6))
+               if (!memcmp("S1",cur->swh.magic.magic,2))
                        memcpy(cur->swh.magic.magic,"SWAP-SPACE",10);
-               else if (!memcmp("SUSP2R",cur->swh.magic.magic,6))
+               else if (!memcmp("S2",cur->swh.magic.magic,2))
                        memcpy(cur->swh.magic.magic,"SWAPSPACE2",10);
                else printk("%sUnable to find suspended-data signature (%.10s - misspelled?\n", 
                        name_resume, cur->swh.magic.magic);
        } else {
                if ((!memcmp("SWAP-SPACE",cur->swh.magic.magic,10)))
-                       memcpy(cur->swh.magic.magic,"SUSP1R....",10);
+                       memcpy(cur->swh.magic.magic,"S1SUSP....",10);
                else if ((!memcmp("SWAPSPACE2",cur->swh.magic.magic,10)))
-                       memcpy(cur->swh.magic.magic,"SUSP2R....",10);
+                       memcpy(cur->swh.magic.magic,"S2SUSP....",10);
                else panic("\nSwapspace is not swapspace (%.10s)\n", cur->swh.magic.magic);
                cur->link.next = prev; /* prev is the first/last swap page of the resume area */
-               /* link.next lies *no more* in last 4 bytes of magic */
+               /* link.next lies *no more* in last 4/8 bytes of magic */
        }
        rw_swap_page_sync(WRITE, entry, page);
        __free_page(page);
@@ -489,7 +490,6 @@ static int count_and_copy_data_pages(struct pbe *pagedir_p)
                        if (PageNosave(page))
                                continue;
 
-
                        if ((chunk_size=is_head_of_free_region(page))!=0) {
                                pfn += chunk_size - 1;
                                continue;
@@ -500,10 +500,9 @@ static int count_and_copy_data_pages(struct pbe *pagedir_p)
                        /*
                         * Just copy whole code segment. Hopefully it is not that big.
                         */
-                       if (ADDRESS(pfn) >= (unsigned long)
-                               &__nosave_begin && ADDRESS(pfn) < 
-                               (unsigned long)&__nosave_end) {
-                               PRINTK("[nosave %x]", ADDRESS(pfn));
+                       if ((ADDRESS(pfn) >= (unsigned long) ADDRESS2(&__nosave_begin)) && 
+                           (ADDRESS(pfn) <  (unsigned long) ADDRESS2(&__nosave_end))) {
+                               PRINTK("[nosave %lx]", ADDRESS(pfn));
                                continue;
                        }
                        /* Hmm, perhaps copying all reserved pages is not too healthy as they may contain 
@@ -513,7 +512,7 @@ static int count_and_copy_data_pages(struct pbe *pagedir_p)
                nr_copy_pages++;
                if (pagedir_p) {
                        pagedir_p->orig_address = ADDRESS(pfn);
-                       copy_page(pagedir_p->address, pagedir_p->orig_address);
+                       copy_page((void *) pagedir_p->address, (void *) pagedir_p->orig_address);
                        pagedir_p++;
                }
        }
@@ -549,7 +548,7 @@ static suspend_pagedir_t *create_suspend_pagedir(int nr_copy_pages)
 
        pagedir_order = get_bitmask_order(SUSPEND_PD_PAGES(nr_copy_pages));
 
-       p = pagedir = (suspend_pagedir_t *)__get_free_pages(GFP_ATOMIC, pagedir_order);
+       p = pagedir = (suspend_pagedir_t *)__get_free_pages(GFP_ATOMIC | __GFP_COLD, pagedir_order);
        if(!pagedir)
                return NULL;
 
@@ -558,11 +557,12 @@ static suspend_pagedir_t *create_suspend_pagedir(int nr_copy_pages)
                SetPageNosave(page++);
                
        while(nr_copy_pages--) {
-               p->address = get_zeroed_page(GFP_ATOMIC);
+               p->address = get_zeroed_page(GFP_ATOMIC | __GFP_COLD);
                if(!p->address) {
                        free_suspend_pagedir((unsigned long) pagedir);
                        return NULL;
                }
+               printk(".");
                SetPageNosave(virt_to_page(p->address));
                p->orig_address = 0;
                p++;
@@ -623,7 +623,7 @@ static int prepare_suspend_processes(void)
 static void free_some_memory(void)
 {
        printk("Freeing memory: ");
-       while (try_to_free_pages(&contig_page_data.node_zones[ZONE_HIGHMEM], GFP_KSWAPD, 0))
+       while (shrink_all_memory(10000))
                printk(".");
        printk("|\n");
 }
@@ -676,7 +676,7 @@ static void drivers_resume(int flags)
        }
 }
 
-static int suspend_save_image(void)
+static int suspend_prepare_image(void)
 {
        struct sysinfo i;
        unsigned int nr_needed_pages = 0;
@@ -725,9 +725,15 @@ static int suspend_save_image(void)
         *
         * Following line enforces not writing to disk until we choose.
         */
-       drivers_unsuspend();
-       spin_unlock_irq(&suspend_pagedir_lock);
+
        printk( "critical section/: done (%d pages copied)\n", nr_copy_pages );
+       spin_unlock_irq(&suspend_pagedir_lock);
+       return 0;
+}
+
+static void suspend_save_image(void)
+{
+       drivers_unsuspend();
 
        lock_swapdevices();
        write_suspend_image();
@@ -738,11 +744,11 @@ static int suspend_save_image(void)
         * filesystem clean: it is not. (And it does not matter, if we resume
         * correctly, we'll mark system clean, anyway.)
         */
-       return 0;
 }
 
-void suspend_power_down(void)
+static void suspend_power_down(void)
 {
+       extern int C_A_D;
        C_A_D = 0;
        printk(KERN_EMERG "%s%s Trying to power down.\n", name_suspend, TEST_SWSUSP ? "Disable TEST_SWSUSP. NOT ": "");
 #ifdef CONFIG_VT
@@ -788,8 +794,8 @@ void do_magic_resume_2(void)
 
        PRINTK( "Freeing prev allocated pagedir\n" );
        free_suspend_pagedir((unsigned long) pagedir_save);
-       drivers_resume(RESUME_ALL_PHASES);
        spin_unlock_irq(&suspend_pagedir_lock);
+       drivers_resume(RESUME_ALL_PHASES);
 
        PRINTK( "Fixing swap signatures... " );
        mark_swapfiles(((swp_entry_t) {0}), MARK_SWAP_RESUME);
@@ -804,14 +810,17 @@ void do_magic_suspend_1(void)
 {
        mb();
        barrier();
+       BUG_ON(in_atomic());
        spin_lock_irq(&suspend_pagedir_lock);
 }
 
 void do_magic_suspend_2(void)
 {
        read_swapfiles();
-       if (!suspend_save_image())
+       if (!suspend_prepare_image()) { /* suspend_save_image realeses suspend_pagedir_lock */
+               suspend_save_image();
                suspend_power_down();   /* FIXME: if suspend_power_down is commented out, console is lost after few suspends ?! */
+       }
 
        printk(KERN_EMERG "%sSuspend failed, trying to recover...\n", name_suspend);
        MDELAY(1000); /* So user can wait and report us messages if armageddon comes :-) */
@@ -827,7 +836,7 @@ void do_magic_suspend_2(void)
        PRINTK(KERN_WARNING "%sLeaving do_magic_suspend_2...\n", name_suspend); 
 }
 
-void do_software_suspend(void)
+static void do_software_suspend(void)
 {
        arch_prepare_suspend();
        if (prepare_suspend_console())
@@ -1069,9 +1078,9 @@ static int __read_suspend_image(struct block_device *bdev, union diskpage *cur,
 
        PREPARENEXT; /* We have to read next position before we overwrite it */
 
-       if (!memcmp("SUSP1R",cur->swh.magic.magic,6))
+       if (!memcmp("S1",cur->swh.magic.magic,2))
                memcpy(cur->swh.magic.magic,"SWAP-SPACE",10);
-       else if (!memcmp("SUSP2R",cur->swh.magic.magic,6))
+       else if (!memcmp("S2",cur->swh.magic.magic,2))
                memcpy(cur->swh.magic.magic,"SWAPSPACE2",10);
        else {
                panic("%sUnable to find suspended-data signature (%.10s - misspelled?\n",