aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/power/swsusp.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/power/swsusp.c')
-rw-r--r--kernel/power/swsusp.c29
1 files changed, 18 insertions, 11 deletions
diff --git a/kernel/power/swsusp.c b/kernel/power/swsusp.c
index d967e875ee82..acf79ac1cb6d 100644
--- a/kernel/power/swsusp.c
+++ b/kernel/power/swsusp.c
@@ -363,7 +363,7 @@ static void lock_swapdevices(void)
363} 363}
364 364
365/** 365/**
366 * write_swap_page - Write one page to a fresh swap location. 366 * write_page - Write one page to a fresh swap location.
367 * @addr: Address we're writing. 367 * @addr: Address we're writing.
368 * @loc: Place to store the entry we used. 368 * @loc: Place to store the entry we used.
369 * 369 *
@@ -402,15 +402,14 @@ static int write_page(unsigned long addr, swp_entry_t * loc)
402static void data_free(void) 402static void data_free(void)
403{ 403{
404 swp_entry_t entry; 404 swp_entry_t entry;
405 int i; 405 struct pbe * p;
406 406
407 for (i = 0; i < nr_copy_pages; i++) { 407 for_each_pbe(p, pagedir_nosave) {
408 entry = (pagedir_nosave + i)->swap_address; 408 entry = p->swap_address;
409 if (entry.val) 409 if (entry.val)
410 swap_free(entry); 410 swap_free(entry);
411 else 411 else
412 break; 412 break;
413 (pagedir_nosave + i)->swap_address = (swp_entry_t){0};
414 } 413 }
415} 414}
416 415
@@ -863,6 +862,9 @@ static int alloc_image_pages(void)
863 return 0; 862 return 0;
864} 863}
865 864
865/* Free pages we allocated for suspend. Suspend pages are alocated
866 * before atomic copy, so we need to free them after resume.
867 */
866void swsusp_free(void) 868void swsusp_free(void)
867{ 869{
868 BUG_ON(PageNosave(virt_to_page(pagedir_save))); 870 BUG_ON(PageNosave(virt_to_page(pagedir_save)));
@@ -918,6 +920,7 @@ static int swsusp_alloc(void)
918 920
919 pagedir_nosave = NULL; 921 pagedir_nosave = NULL;
920 nr_copy_pages = calc_nr(nr_copy_pages); 922 nr_copy_pages = calc_nr(nr_copy_pages);
923 nr_copy_pages_check = nr_copy_pages;
921 924
922 pr_debug("suspend: (pages needed: %d + %d free: %d)\n", 925 pr_debug("suspend: (pages needed: %d + %d free: %d)\n",
923 nr_copy_pages, PAGES_FOR_IO, nr_free_pages()); 926 nr_copy_pages, PAGES_FOR_IO, nr_free_pages());
@@ -928,6 +931,10 @@ static int swsusp_alloc(void)
928 if (!enough_swap()) 931 if (!enough_swap())
929 return -ENOSPC; 932 return -ENOSPC;
930 933
934 if (MAX_PBES < nr_copy_pages / PBES_PER_PAGE +
935 !!(nr_copy_pages % PBES_PER_PAGE))
936 return -ENOSPC;
937
931 if (!(pagedir_save = alloc_pagedir(nr_copy_pages))) { 938 if (!(pagedir_save = alloc_pagedir(nr_copy_pages))) {
932 printk(KERN_ERR "suspend: Allocating pagedir failed.\n"); 939 printk(KERN_ERR "suspend: Allocating pagedir failed.\n");
933 return -ENOMEM; 940 return -ENOMEM;
@@ -940,7 +947,6 @@ static int swsusp_alloc(void)
940 return error; 947 return error;
941 } 948 }
942 949
943 nr_copy_pages_check = nr_copy_pages;
944 return 0; 950 return 0;
945} 951}
946 952
@@ -1213,8 +1219,9 @@ static struct pbe * swsusp_pagedir_relocate(struct pbe *pblist)
1213 free_pagedir(pblist); 1219 free_pagedir(pblist);
1214 free_eaten_memory(); 1220 free_eaten_memory();
1215 pblist = NULL; 1221 pblist = NULL;
1216 } 1222 /* Is this even worth handling? It should never ever happen, and we
1217 else 1223 have just lost user's state, anyway... */
1224 } else
1218 printk("swsusp: Relocated %d pages\n", rel); 1225 printk("swsusp: Relocated %d pages\n", rel);
1219 1226
1220 return pblist; 1227 return pblist;
@@ -1434,9 +1441,9 @@ static int read_pagedir(struct pbe *pblist)
1434 } 1441 }
1435 1442
1436 if (error) 1443 if (error)
1437 free_page((unsigned long)pblist); 1444 free_pagedir(pblist);
1438 1445 else
1439 BUG_ON(i != swsusp_info.pagedir_pages); 1446 BUG_ON(i != swsusp_info.pagedir_pages);
1440 1447
1441 return error; 1448 return error;
1442} 1449}