Merge branch 'x86-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[firefly-linux-kernel-4.4.55.git] / kernel / power / snapshot.c
index 4fc5c32422b39db0e509ea35e675b3852db895eb..f1604d8cf489a2e0cc689ab82ce6c3adfb82f693 100644 (file)
@@ -725,14 +725,6 @@ static void memory_bm_clear_bit(struct memory_bitmap *bm, unsigned long pfn)
        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;
@@ -954,6 +946,25 @@ static void mark_nosave_pages(struct memory_bitmap *bm)
        }
 }
 
+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
@@ -1322,35 +1333,23 @@ static struct memory_bitmap copy_bm;
 
 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;
@@ -2015,7 +2014,7 @@ static int mark_unsafe_pages(struct memory_bitmap *bm)
        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;