OSDN Git Service

net: Fix skb->csum update in inet_proto_csum_replace16().
[sagit-ice-cold/kernel_xiaomi_msm8998.git] / mm / cma.c
index ea506eb..65c7aa4 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,14 @@ 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));
+       if (fixed && base & (alignment - 1)) {
+               ret = -EINVAL;
+               pr_err("Region at %pa must be aligned to %pa bytes\n",
+                       &base, &alignment);
+               goto err;
+       }
        base = ALIGN(base, alignment);
        size = ALIGN(size, alignment);
        limit &= ~(alignment - 1);
@@ -298,6 +304,13 @@ int __init cma_declare_contiguous(phys_addr_t base,
        if (limit == 0 || limit > memblock_end)
                limit = memblock_end;
 
+       if (base + size > limit) {
+               ret = -EINVAL;
+               pr_err("Size (%pa) of region at %pa exceeds limit (%pa)\n",
+                       &size, &base, &limit);
+               goto err;
+       }
+
        /* Reserve memory */
        if (fixed) {
                if (memblock_is_region_reserved(base, size) ||
@@ -341,12 +354,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;