diff options
| author | Tony Luck <tony.luck@intel.com> | 2005-10-20 13:41:44 -0400 |
|---|---|---|
| committer | Tony Luck <tony.luck@intel.com> | 2005-10-20 13:41:44 -0400 |
| commit | 9cec58dc138d6fcad9f447a19c8ff69f6540e667 (patch) | |
| tree | 4fe1cca94fdba8b705c87615bee06d3346f687ce /kernel/power/swsusp.c | |
| parent | 17e5ad6c0ce5a970e2830d0de8bdd60a2f077d38 (diff) | |
| parent | ac9b9c667c2e1194e22ebe0a441ae1c37aaa9b90 (diff) | |
Update from upstream with manual merge of Yasunori Goto's
changes to swiotlb.c made in commit 281dd25cdc0d6903929b79183816d151ea626341
since this file has been moved from arch/ia64/lib/swiotlb.c to
lib/swiotlb.c
Signed-off-by: Tony Luck <tony.luck@intel.com>
Diffstat (limited to 'kernel/power/swsusp.c')
| -rw-r--r-- | kernel/power/swsusp.c | 36 |
1 files changed, 22 insertions, 14 deletions
diff --git a/kernel/power/swsusp.c b/kernel/power/swsusp.c index d967e875ee82..2d5c45676442 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) | |||
| 402 | static void data_free(void) | 402 | static 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 | */ | ||
| 866 | void swsusp_free(void) | 868 | void 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 | ||
| @@ -1089,7 +1095,7 @@ static inline void eat_page(void *page) | |||
| 1089 | *eaten_memory = c; | 1095 | *eaten_memory = c; |
| 1090 | } | 1096 | } |
| 1091 | 1097 | ||
| 1092 | static unsigned long get_usable_page(unsigned gfp_mask) | 1098 | unsigned long get_usable_page(unsigned gfp_mask) |
| 1093 | { | 1099 | { |
| 1094 | unsigned long m; | 1100 | unsigned long m; |
| 1095 | 1101 | ||
| @@ -1103,7 +1109,7 @@ static unsigned long get_usable_page(unsigned gfp_mask) | |||
| 1103 | return m; | 1109 | return m; |
| 1104 | } | 1110 | } |
| 1105 | 1111 | ||
| 1106 | static void free_eaten_memory(void) | 1112 | void free_eaten_memory(void) |
| 1107 | { | 1113 | { |
| 1108 | unsigned long m; | 1114 | unsigned long m; |
| 1109 | void **c; | 1115 | void **c; |
| @@ -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 | } |
| @@ -1474,11 +1481,12 @@ static int read_suspend_image(void) | |||
| 1474 | /* Allocate memory for the image and read the data from swap */ | 1481 | /* Allocate memory for the image and read the data from swap */ |
| 1475 | 1482 | ||
| 1476 | error = check_pagedir(pagedir_nosave); | 1483 | error = check_pagedir(pagedir_nosave); |
| 1477 | free_eaten_memory(); | 1484 | |
| 1478 | if (!error) | 1485 | if (!error) |
| 1479 | error = data_read(pagedir_nosave); | 1486 | error = data_read(pagedir_nosave); |
| 1480 | 1487 | ||
| 1481 | if (error) { /* We fail cleanly */ | 1488 | if (error) { /* We fail cleanly */ |
| 1489 | free_eaten_memory(); | ||
| 1482 | for_each_pbe (p, pagedir_nosave) | 1490 | for_each_pbe (p, pagedir_nosave) |
| 1483 | if (p->address) { | 1491 | if (p->address) { |
| 1484 | free_page(p->address); | 1492 | free_page(p->address); |
