diff options
Diffstat (limited to 'kernel/power')
| -rw-r--r-- | kernel/power/snapshot.c | 54 |
1 files changed, 39 insertions, 15 deletions
diff --git a/kernel/power/snapshot.c b/kernel/power/snapshot.c index f1604d8cf489..791a61892bb5 100644 --- a/kernel/power/snapshot.c +++ b/kernel/power/snapshot.c | |||
| @@ -725,6 +725,14 @@ static void memory_bm_clear_bit(struct memory_bitmap *bm, unsigned long pfn) | |||
| 725 | clear_bit(bit, addr); | 725 | clear_bit(bit, addr); |
| 726 | } | 726 | } |
| 727 | 727 | ||
| 728 | static void memory_bm_clear_current(struct memory_bitmap *bm) | ||
| 729 | { | ||
| 730 | int bit; | ||
| 731 | |||
| 732 | bit = max(bm->cur.node_bit - 1, 0); | ||
| 733 | clear_bit(bit, bm->cur.node->data); | ||
| 734 | } | ||
| 735 | |||
| 728 | static int memory_bm_test_bit(struct memory_bitmap *bm, unsigned long pfn) | 736 | static int memory_bm_test_bit(struct memory_bitmap *bm, unsigned long pfn) |
| 729 | { | 737 | { |
| 730 | void *addr; | 738 | void *addr; |
| @@ -1333,23 +1341,39 @@ static struct memory_bitmap copy_bm; | |||
| 1333 | 1341 | ||
| 1334 | void swsusp_free(void) | 1342 | void swsusp_free(void) |
| 1335 | { | 1343 | { |
| 1336 | struct zone *zone; | 1344 | unsigned long fb_pfn, fr_pfn; |
| 1337 | unsigned long pfn, max_zone_pfn; | ||
| 1338 | 1345 | ||
| 1339 | for_each_populated_zone(zone) { | 1346 | if (!forbidden_pages_map || !free_pages_map) |
| 1340 | max_zone_pfn = zone_end_pfn(zone); | 1347 | goto out; |
| 1341 | for (pfn = zone->zone_start_pfn; pfn < max_zone_pfn; pfn++) | 1348 | |
| 1342 | if (pfn_valid(pfn)) { | 1349 | memory_bm_position_reset(forbidden_pages_map); |
| 1343 | struct page *page = pfn_to_page(pfn); | 1350 | memory_bm_position_reset(free_pages_map); |
| 1344 | 1351 | ||
| 1345 | if (swsusp_page_is_forbidden(page) && | 1352 | loop: |
| 1346 | swsusp_page_is_free(page)) { | 1353 | fr_pfn = memory_bm_next_pfn(free_pages_map); |
| 1347 | swsusp_unset_page_forbidden(page); | 1354 | fb_pfn = memory_bm_next_pfn(forbidden_pages_map); |
| 1348 | swsusp_unset_page_free(page); | 1355 | |
| 1349 | __free_page(page); | 1356 | /* |
| 1350 | } | 1357 | * Find the next bit set in both bitmaps. This is guaranteed to |
| 1351 | } | 1358 | * terminate when fb_pfn == fr_pfn == BM_END_OF_MAP. |
| 1359 | */ | ||
| 1360 | do { | ||
| 1361 | if (fb_pfn < fr_pfn) | ||
| 1362 | fb_pfn = memory_bm_next_pfn(forbidden_pages_map); | ||
| 1363 | if (fr_pfn < fb_pfn) | ||
| 1364 | fr_pfn = memory_bm_next_pfn(free_pages_map); | ||
| 1365 | } while (fb_pfn != fr_pfn); | ||
| 1366 | |||
| 1367 | if (fr_pfn != BM_END_OF_MAP && pfn_valid(fr_pfn)) { | ||
| 1368 | struct page *page = pfn_to_page(fr_pfn); | ||
| 1369 | |||
| 1370 | memory_bm_clear_current(forbidden_pages_map); | ||
| 1371 | memory_bm_clear_current(free_pages_map); | ||
| 1372 | __free_page(page); | ||
| 1373 | goto loop; | ||
| 1352 | } | 1374 | } |
| 1375 | |||
| 1376 | out: | ||
| 1353 | nr_copy_pages = 0; | 1377 | nr_copy_pages = 0; |
| 1354 | nr_meta_pages = 0; | 1378 | nr_meta_pages = 0; |
| 1355 | restore_pblist = NULL; | 1379 | restore_pblist = NULL; |
