spin_unlock_irqrestore(&cma->lock, flags);
 }
 
+/*
+ * Check if a CMA area contains no ranges that intersect with
+ * multiple zones. Store the result in the flags in case
+ * this gets called more than once.
+ */
+bool cma_validate_zones(struct cma *cma)
+{
+       int r;
+       unsigned long base_pfn;
+       struct cma_memrange *cmr;
+       bool valid_bit_set;
+
+       /*
+        * If already validated, return result of previous check.
+        * Either the valid or invalid bit will be set if this
+        * check has already been done. If neither is set, the
+        * check has not been performed yet.
+        */
+       valid_bit_set = test_bit(CMA_ZONES_VALID, &cma->flags);
+       if (valid_bit_set || test_bit(CMA_ZONES_INVALID, &cma->flags))
+               return valid_bit_set;
+
+       for (r = 0; r < cma->nranges; r++) {
+               cmr = &cma->ranges[r];
+               base_pfn = cmr->base_pfn;
+
+               /*
+                * alloc_contig_range() requires the pfn range specified
+                * to be in the same zone. Simplify by forcing the entire
+                * CMA resv range to be in the same zone.
+                */
+               WARN_ON_ONCE(!pfn_valid(base_pfn));
+               if (pfn_range_intersects_zones(cma->nid, base_pfn, cmr->count)) {
+                       set_bit(CMA_ZONES_INVALID, &cma->flags);
+                       return false;
+               }
+       }
+
+       set_bit(CMA_ZONES_VALID, &cma->flags);
+
+       return true;
+}
+
 static void __init cma_activate_area(struct cma *cma)
 {
        unsigned long pfn, base_pfn;
                        goto cleanup;
        }
 
+       if (!cma_validate_zones(cma))
+               goto cleanup;
+
        for (r = 0; r < cma->nranges; r++) {
                cmr = &cma->ranges[r];
                base_pfn = cmr->base_pfn;
-
-               /*
-                * alloc_contig_range() requires the pfn range specified
-                * to be in the same zone. Simplify by forcing the entire
-                * CMA resv range to be in the same zone.
-                */
-               WARN_ON_ONCE(!pfn_valid(base_pfn));
-               if (pfn_range_intersects_zones(cma->nid, base_pfn, cmr->count))
-                       goto cleanup;
-
                for (pfn = base_pfn; pfn < base_pfn + cmr->count;
                     pfn += pageblock_nr_pages)
                        init_cma_reserved_pageblock(pfn_to_page(pfn));
                bitmap_free(cma->ranges[r].bitmap);
 
        /* Expose all pages to the buddy, they are useless for CMA. */
-       if (!cma->reserve_pages_on_error) {
+       if (!test_bit(CMA_RESERVE_PAGES_ON_ERROR, &cma->flags)) {
                for (r = 0; r < allocrange; r++) {
                        cmr = &cma->ranges[r];
                        for (pfn = cmr->base_pfn;
 
 void __init cma_reserve_pages_on_error(struct cma *cma)
 {
-       cma->reserve_pages_on_error = true;
+       set_bit(CMA_RESERVE_PAGES_ON_ERROR, &cma->flags);
 }
 
 static int __init cma_new_area(const char *name, phys_addr_t size,