Merge to Fedora kernel-2.6.7-1.441
[linux-2.6.git] / kernel / power / swsusp.c
index 752f6cd..ff8fdbc 100644 (file)
@@ -503,6 +503,9 @@ static int count_and_copy_zone(struct zone *zone, struct pbe **pagedir_p)
                if (!pbe)
                        continue;
                pbe->orig_address = (long) page_address(page);
+               /* Copy page is dangerous: it likes to mess with
+                  preempt count on specific cpus. Wrong preempt count is then copied,
+                  oops. */
                copy_page((void *)pbe->address, (void *)pbe->orig_address);
                pbe++;
        }
@@ -860,19 +863,6 @@ int software_suspend(void)
 
 /* More restore stuff */
 
-/* FIXME: Why not memcpy(to, from, 1<<pagedir_order*PAGE_SIZE)? */
-static void copy_pagedir(suspend_pagedir_t *to, suspend_pagedir_t *from)
-{
-       int i;
-       char *topointer=(char *)to, *frompointer=(char *)from;
-
-       for(i=0; i < 1 << pagedir_order; i++) {
-               copy_page(topointer, frompointer);
-               topointer += PAGE_SIZE;
-               frompointer += PAGE_SIZE;
-       }
-}
-
 #define does_collide(addr) does_collide_order(pagedir_nosave, addr, 0)
 
 /*
@@ -920,11 +910,12 @@ static int relocate_pagedir(void)
         * We have to avoid recursion (not to overflow kernel stack),
         * and that's why code looks pretty cryptic 
         */
-       suspend_pagedir_t *new_pagedir, *old_pagedir = pagedir_nosave;
+       suspend_pagedir_t *old_pagedir = pagedir_nosave;
        void **eaten_memory = NULL;
        void **c = eaten_memory, *m, *f;
+       int ret = 0;
 
-       printk("Relocating pagedir");
+       printk("Relocating pagedir ");
 
        if(!does_collide_order(old_pagedir, (unsigned long)old_pagedir, pagedir_order)) {
                printk("not necessary\n");
@@ -932,7 +923,6 @@ static int relocate_pagedir(void)
        }
 
        while ((m = (void *) __get_free_pages(GFP_ATOMIC, pagedir_order))) {
-               memset(m, 0, PAGE_SIZE);
                if (!does_collide_order(old_pagedir, (unsigned long)m, pagedir_order))
                        break;
                eaten_memory = m;
@@ -941,22 +931,23 @@ static int relocate_pagedir(void)
                c = eaten_memory;
        }
 
-       if (!m)
-               return -ENOMEM;
-
-       pagedir_nosave = new_pagedir = m;
-       copy_pagedir(new_pagedir, old_pagedir);
+       if (!m) {
+               printk("out of memory\n");
+               ret = -ENOMEM;
+       } else {
+               pagedir_nosave =
+                       memcpy(m, old_pagedir, PAGE_SIZE << pagedir_order);
+       }
 
        c = eaten_memory;
-       while(c) {
+       while (c) {
                printk(":");
-               f = *c;
+               f = c;
                c = *c;
-               if (f)
-                       free_pages((unsigned long)f, pagedir_order);
+               free_pages((unsigned long)f, pagedir_order);
        }
        printk("|\n");
-       return 0;
+       return ret;
 }
 
 /*