]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - kernel/power/snapshot.c
[TCP]: Uninline tcp_is_cwnd_limited
[linux-2.6-omap-h63xx.git] / kernel / power / snapshot.c
index b7039772b05ca04a3d0fd67dfde40c31e9539f20..78039b477d2bd7bbae3ab893763111475ea932a6 100644 (file)
@@ -607,7 +607,8 @@ static LIST_HEAD(nosave_regions);
  */
 
 void __init
-register_nosave_region(unsigned long start_pfn, unsigned long end_pfn)
+__register_nosave_region(unsigned long start_pfn, unsigned long end_pfn,
+                        int use_kmalloc)
 {
        struct nosave_region *region;
 
@@ -623,8 +624,13 @@ register_nosave_region(unsigned long start_pfn, unsigned long end_pfn)
                        goto Report;
                }
        }
-       /* This allocation cannot fail */
-       region = alloc_bootmem_low(sizeof(struct nosave_region));
+       if (use_kmalloc) {
+               /* during init, this shouldn't fail */
+               region = kmalloc(sizeof(struct nosave_region), GFP_KERNEL);
+               BUG_ON(!region);
+       } else
+               /* This allocation cannot fail */
+               region = alloc_bootmem_low(sizeof(struct nosave_region));
        region->start_pfn = start_pfn;
        region->end_pfn = end_pfn;
        list_add_tail(&region->list, &nosave_regions);
@@ -703,7 +709,8 @@ static void mark_nosave_pages(struct memory_bitmap *bm)
                                region->end_pfn << PAGE_SHIFT);
 
                for (pfn = region->start_pfn; pfn < region->end_pfn; pfn++)
-                       memory_bm_set_bit(bm, pfn);
+                       if (pfn_valid(pfn))
+                               memory_bm_set_bit(bm, pfn);
        }
 }
 
@@ -998,11 +1005,12 @@ copy_data_pages(struct memory_bitmap *copy_bm, struct memory_bitmap *orig_bm)
        }
        memory_bm_position_reset(orig_bm);
        memory_bm_position_reset(copy_bm);
-       do {
+       for(;;) {
                pfn = memory_bm_next_pfn(orig_bm);
-               if (likely(pfn != BM_END_OF_MAP))
-                       copy_data_page(memory_bm_next_pfn(copy_bm), pfn);
-       } while (pfn != BM_END_OF_MAP);
+               if (unlikely(pfn == BM_END_OF_MAP))
+                       break;
+               copy_data_page(memory_bm_next_pfn(copy_bm), pfn);
+       }
 }
 
 /* Total number of image pages */
@@ -1227,22 +1235,44 @@ asmlinkage int swsusp_save(void)
        nr_copy_pages = nr_pages;
        nr_meta_pages = DIV_ROUND_UP(nr_pages * sizeof(long), PAGE_SIZE);
 
-       printk("swsusp: critical section/: done (%d pages copied)\n", nr_pages);
+       printk("swsusp: critical section: done (%d pages copied)\n", nr_pages);
 
        return 0;
 }
 
-static void init_header(struct swsusp_info *info)
+#ifndef CONFIG_ARCH_HIBERNATION_HEADER
+static int init_header_complete(struct swsusp_info *info)
 {
-       memset(info, 0, sizeof(struct swsusp_info));
+       memcpy(&info->uts, init_utsname(), sizeof(struct new_utsname));
        info->version_code = LINUX_VERSION_CODE;
+       return 0;
+}
+
+static char *check_image_kernel(struct swsusp_info *info)
+{
+       if (info->version_code != LINUX_VERSION_CODE)
+               return "kernel version";
+       if (strcmp(info->uts.sysname,init_utsname()->sysname))
+               return "system type";
+       if (strcmp(info->uts.release,init_utsname()->release))
+               return "kernel release";
+       if (strcmp(info->uts.version,init_utsname()->version))
+               return "version";
+       if (strcmp(info->uts.machine,init_utsname()->machine))
+               return "machine";
+       return NULL;
+}
+#endif /* CONFIG_ARCH_HIBERNATION_HEADER */
+
+static int init_header(struct swsusp_info *info)
+{
+       memset(info, 0, sizeof(struct swsusp_info));
        info->num_physpages = num_physpages;
-       memcpy(&info->uts, init_utsname(), sizeof(struct new_utsname));
-       info->cpus = num_online_cpus();
        info->image_pages = nr_copy_pages;
        info->pages = nr_copy_pages + nr_meta_pages + 1;
        info->size = info->pages;
        info->size <<= PAGE_SHIFT;
+       return init_header_complete(info);
 }
 
 /**
@@ -1296,7 +1326,11 @@ int snapshot_read_next(struct snapshot_handle *handle, size_t count)
                        return -ENOMEM;
        }
        if (!handle->offset) {
-               init_header((struct swsusp_info *)buffer);
+               int error;
+
+               error = init_header((struct swsusp_info *)buffer);
+               if (error)
+                       return error;
                handle->buffer = buffer;
                memory_bm_position_reset(&orig_bm);
                memory_bm_position_reset(&copy_bm);
@@ -1387,22 +1421,13 @@ duplicate_memory_bitmap(struct memory_bitmap *dst, struct memory_bitmap *src)
        }
 }
 
-static inline int check_header(struct swsusp_info *info)
+static int check_header(struct swsusp_info *info)
 {
-       char *reason = NULL;
+       char *reason;
 
-       if (info->version_code != LINUX_VERSION_CODE)
-               reason = "kernel version";
-       if (info->num_physpages != num_physpages)
+       reason = check_image_kernel(info);
+       if (!reason && info->num_physpages != num_physpages)
                reason = "memory size";
-       if (strcmp(info->uts.sysname,init_utsname()->sysname))
-               reason = "system type";
-       if (strcmp(info->uts.release,init_utsname()->release))
-               reason = "kernel release";
-       if (strcmp(info->uts.version,init_utsname()->version))
-               reason = "version";
-       if (strcmp(info->uts.machine,init_utsname()->machine))
-               reason = "machine";
        if (reason) {
                printk(KERN_ERR "swsusp: Resume mismatch: %s\n", reason);
                return -EPERM;