clear_bit(bit, addr);
}
-static void memory_bm_clear_current(struct memory_bitmap *bm)
-{
- int bit;
-
- bit = max(bm->cur.node_bit - 1, 0);
- clear_bit(bit, bm->cur.node->data);
-}
-
static int memory_bm_test_bit(struct memory_bitmap *bm, unsigned long pfn)
{
void *addr;
}
}
+static bool is_nosave_page(unsigned long pfn)
+{
+ struct nosave_region *region;
+
+ list_for_each_entry(region, &nosave_regions, list) {
+ if (pfn >= region->start_pfn && pfn < region->end_pfn) {
+ pr_err("PM: %#010llx in e820 nosave region: "
+ "[mem %#010llx-%#010llx]\n",
+ (unsigned long long) pfn << PAGE_SHIFT,
+ (unsigned long long) region->start_pfn << PAGE_SHIFT,
+ ((unsigned long long) region->end_pfn << PAGE_SHIFT)
+ - 1);
+ return true;
+ }
+ }
+
+ return false;
+}
+
/**
* create_basic_memory_bitmaps - create bitmaps needed for marking page
* frames that should not be saved and free page frames. The pointers
void swsusp_free(void)
{
- unsigned long fb_pfn, fr_pfn;
-
- memory_bm_position_reset(forbidden_pages_map);
- memory_bm_position_reset(free_pages_map);
-
-loop:
- fr_pfn = memory_bm_next_pfn(free_pages_map);
- fb_pfn = memory_bm_next_pfn(forbidden_pages_map);
-
- /*
- * Find the next bit set in both bitmaps. This is guaranteed to
- * terminate when fb_pfn == fr_pfn == BM_END_OF_MAP.
- */
- do {
- if (fb_pfn < fr_pfn)
- fb_pfn = memory_bm_next_pfn(forbidden_pages_map);
- if (fr_pfn < fb_pfn)
- fr_pfn = memory_bm_next_pfn(free_pages_map);
- } while (fb_pfn != fr_pfn);
-
- if (fr_pfn != BM_END_OF_MAP && pfn_valid(fr_pfn)) {
- struct page *page = pfn_to_page(fr_pfn);
+ struct zone *zone;
+ unsigned long pfn, max_zone_pfn;
- memory_bm_clear_current(forbidden_pages_map);
- memory_bm_clear_current(free_pages_map);
- __free_page(page);
- goto loop;
+ for_each_populated_zone(zone) {
+ max_zone_pfn = zone_end_pfn(zone);
+ for (pfn = zone->zone_start_pfn; pfn < max_zone_pfn; pfn++)
+ if (pfn_valid(pfn)) {
+ struct page *page = pfn_to_page(pfn);
+
+ if (swsusp_page_is_forbidden(page) &&
+ swsusp_page_is_free(page)) {
+ swsusp_unset_page_forbidden(page);
+ swsusp_unset_page_free(page);
+ __free_page(page);
+ }
+ }
}
-
nr_copy_pages = 0;
nr_meta_pages = 0;
restore_pblist = NULL;
do {
pfn = memory_bm_next_pfn(bm);
if (likely(pfn != BM_END_OF_MAP)) {
- if (likely(pfn_valid(pfn)))
+ if (likely(pfn_valid(pfn)) && !is_nosave_page(pfn))
swsusp_set_page_free(pfn_to_page(pfn));
else
return -EFAULT;