From: Shaohua Li Architecture special saveable memory might not be aligned to PAGE_SIZE. We should just save part of a page in the unaligned case. We changed swsusp_add_arch_pages to accept an 'address' instead of a 'pfn'. Signed-off-by: Shaohua Li Cc: Pavel Machek Cc: "Rafael J. Wysocki" Cc: Nigel Cunningham Signed-off-by: Andrew Morton --- kernel/power/snapshot.c | 34 ++++++++++++++++++++++------------ 1 files changed, 22 insertions(+), 12 deletions(-) diff -puN kernel/power/snapshot.c~swsusp-add-architecture-special-saveable-pages-fix kernel/power/snapshot.c --- devel/kernel/power/snapshot.c~swsusp-add-architecture-special-saveable-pages-fix 2006-04-20 01:09:15.000000000 -0700 +++ devel-akpm/kernel/power/snapshot.c 2006-04-20 01:09:15.000000000 -0700 @@ -40,8 +40,9 @@ static unsigned int nr_meta_pages; static unsigned long *buffer; struct arch_saveable_page { - unsigned long pfn; - void *data; + unsigned long start; + unsigned long end; + char *data; struct arch_saveable_page *next; }; static struct arch_saveable_page *arch_pages; @@ -50,13 +51,16 @@ int swsusp_add_arch_pages(unsigned long { struct arch_saveable_page *tmp; - while (start <= end) { + while (start < end) { tmp = kzalloc(sizeof(struct arch_saveable_page), GFP_KERNEL); if (!tmp) return -ENOMEM; - tmp->pfn = start; + tmp->start = start; + tmp->end = ((start >> PAGE_SHIFT) + 1) << PAGE_SHIFT; + if (tmp->end > end) + tmp->end = end; tmp->next = arch_pages; - start++; + start = tmp->end; arch_pages = tmp; } return 0; @@ -75,17 +79,20 @@ static unsigned int count_arch_pages(voi static int save_arch_mem(void) { - void *kaddr; + char *kaddr; struct arch_saveable_page *tmp = arch_pages; + int offset; pr_debug("swsusp: Saving arch specific memory"); while (tmp) { - tmp->data = (void *)__get_free_page(GFP_ATOMIC); + tmp->data = (char *)__get_free_page(GFP_ATOMIC); if (!tmp->data) return -ENOMEM; + offset = tmp->start - (tmp->start & PAGE_MASK); /* arch pages might haven't a 'struct page' */ - kaddr = kmap_atomic_pfn(tmp->pfn, KM_USER0); - memcpy(tmp->data, kaddr, PAGE_SIZE); + kaddr = kmap_atomic_pfn(tmp->start >> PAGE_SHIFT, KM_USER0); + memcpy(tmp->data + offset, kaddr + offset, + tmp->end - tmp->start); kunmap_atomic(kaddr, KM_USER0); tmp = tmp->next; @@ -95,14 +102,17 @@ static int save_arch_mem(void) static int restore_arch_mem(void) { - void *kaddr; + char *kaddr; struct arch_saveable_page *tmp = arch_pages; + int offset; while (tmp) { if (!tmp->data) continue; - kaddr = kmap_atomic_pfn(tmp->pfn, KM_USER0); - memcpy(kaddr, tmp->data, PAGE_SIZE); + offset = tmp->start - (tmp->start & PAGE_MASK); + kaddr = kmap_atomic_pfn(tmp->start >> PAGE_SHIFT, KM_USER0); + memcpy(kaddr + offset, tmp->data + offset, + tmp->end - tmp->start); kunmap_atomic(kaddr, KM_USER0); free_page((long)tmp->data); tmp->data = NULL; _