]> git.ipfire.org Git - thirdparty/kernel/stable.git/blobdiff - mm/cma.c
mm/cma.c: fix crash on CMA allocation if bitmap allocation fails
[thirdparty/kernel/stable.git] / mm / cma.c
index ea506eb18cd6b2cff00606a6c1e1387b48099ffa..5ae4452656cdf44c186dba301d240e0eff2bf87a 100644 (file)
--- a/mm/cma.c
+++ b/mm/cma.c
@@ -54,7 +54,7 @@ unsigned long cma_get_size(const struct cma *cma)
 }
 
 static unsigned long cma_bitmap_aligned_mask(const struct cma *cma,
-                                            int align_order)
+                                            unsigned int align_order)
 {
        if (align_order <= cma->order_per_bit)
                return 0;
@@ -62,17 +62,14 @@ static unsigned long cma_bitmap_aligned_mask(const struct cma *cma,
 }
 
 /*
- * Find a PFN aligned to the specified order and return an offset represented in
- * order_per_bits.
+ * Find the offset of the base PFN from the specified align_order.
+ * The value returned is represented in order_per_bits.
  */
 static unsigned long cma_bitmap_aligned_offset(const struct cma *cma,
-                                              int align_order)
+                                              unsigned int align_order)
 {
-       if (align_order <= cma->order_per_bit)
-               return 0;
-
-       return (ALIGN(cma->base_pfn, (1UL << align_order))
-               - cma->base_pfn) >> cma->order_per_bit;
+       return (cma->base_pfn & ((1UL << align_order) - 1))
+               >> cma->order_per_bit;
 }
 
 static unsigned long cma_bitmap_pages_to_bits(const struct cma *cma,
@@ -103,8 +100,10 @@ static int __init cma_activate_area(struct cma *cma)
 
        cma->bitmap = kzalloc(bitmap_size, GFP_KERNEL);
 
-       if (!cma->bitmap)
+       if (!cma->bitmap) {
+               cma->count = 0;
                return -ENOMEM;
+       }
 
        WARN_ON_ONCE(!pfn_valid(pfn));
        zone = page_zone(pfn_to_page(pfn));
@@ -183,7 +182,8 @@ int __init cma_init_reserved_mem(phys_addr_t base, phys_addr_t size,
                return -EINVAL;
 
        /* ensure minimal alignment required by mm core */
-       alignment = PAGE_SIZE << max(MAX_ORDER - 1, pageblock_order);
+       alignment = PAGE_SIZE <<
+                       max_t(unsigned long, MAX_ORDER - 1, pageblock_order);
 
        /* alignment should be aligned with order_per_bit */
        if (!IS_ALIGNED(alignment >> PAGE_SHIFT, 1 << order_per_bit))
@@ -266,8 +266,8 @@ int __init cma_declare_contiguous(phys_addr_t base,
         * migratetype page by page allocator's buddy algorithm. In the case,
         * you couldn't get a contiguous memory, which is not what we want.
         */
-       alignment = max(alignment,
-               (phys_addr_t)PAGE_SIZE << max(MAX_ORDER - 1, pageblock_order));
+       alignment = max(alignment,  (phys_addr_t)PAGE_SIZE <<
+                         max_t(unsigned long, MAX_ORDER - 1, pageblock_order));
        base = ALIGN(base, alignment);
        size = ALIGN(size, alignment);
        limit &= ~(alignment - 1);
@@ -341,12 +341,14 @@ int __init cma_declare_contiguous(phys_addr_t base,
 
        ret = cma_init_reserved_mem(base, size, order_per_bit, res_cma);
        if (ret)
-               goto err;
+               goto free_mem;
 
        pr_info("Reserved %ld MiB at %pa\n", (unsigned long)size / SZ_1M,
                &base);
        return 0;
 
+free_mem:
+       memblock_free(base, size);
 err:
        pr_err("Failed to reserve %ld MiB\n", (unsigned long)size / SZ_1M);
        return ret;