mm: compaction: encapsulate defer reset logic
[firefly-linux-kernel-4.4.55.git] / mm / memblock.c
index de4d9c352fd64dfd8a072db1504c6b3bbd9bbf15..1c2ef2c7edabc635de699015e2984c21849e06a0 100644 (file)
@@ -21,6 +21,9 @@
 #include <linux/memblock.h>
 
 #include <asm-generic/sections.h>
+#include <linux/io.h>
+
+#include "internal.h"
 
 static struct memblock_region memblock_memory_init_regions[INIT_MEMBLOCK_REGIONS] __initdata_memblock;
 static struct memblock_region memblock_reserved_init_regions[INIT_MEMBLOCK_REGIONS] __initdata_memblock;
@@ -94,7 +97,7 @@ static long __init_memblock memblock_overlaps_region(struct memblock_type *type,
  * @end: end of candidate range, can be %MEMBLOCK_ALLOC_{ANYWHERE|ACCESSIBLE}
  * @size: size of free area to find
  * @align: alignment of free area to find
- * @nid: nid of the free area to find, %MAX_NUMNODES for any node
+ * @nid: nid of the free area to find, %NUMA_NO_NODE for any node
  *
  * Utility called from memblock_find_in_range_node(), find free area bottom-up.
  *
@@ -126,7 +129,7 @@ __memblock_find_range_bottom_up(phys_addr_t start, phys_addr_t end,
  * @end: end of candidate range, can be %MEMBLOCK_ALLOC_{ANYWHERE|ACCESSIBLE}
  * @size: size of free area to find
  * @align: alignment of free area to find
- * @nid: nid of the free area to find, %MAX_NUMNODES for any node
+ * @nid: nid of the free area to find, %NUMA_NO_NODE for any node
  *
  * Utility called from memblock_find_in_range_node(), find free area top-down.
  *
@@ -157,11 +160,11 @@ __memblock_find_range_top_down(phys_addr_t start, phys_addr_t end,
 
 /**
  * memblock_find_in_range_node - find free area in given range and node
- * @start: start of candidate range
- * @end: end of candidate range, can be %MEMBLOCK_ALLOC_{ANYWHERE|ACCESSIBLE}
  * @size: size of free area to find
  * @align: alignment of free area to find
- * @nid: nid of the free area to find, %MAX_NUMNODES for any node
+ * @start: start of candidate range
+ * @end: end of candidate range, can be %MEMBLOCK_ALLOC_{ANYWHERE|ACCESSIBLE}
+ * @nid: nid of the free area to find, %NUMA_NO_NODE for any node
  *
  * Find @size free area aligned to @align in the specified range and node.
  *
@@ -176,9 +179,9 @@ __memblock_find_range_top_down(phys_addr_t start, phys_addr_t end,
  * RETURNS:
  * Found address on success, 0 on failure.
  */
-phys_addr_t __init_memblock memblock_find_in_range_node(phys_addr_t start,
-                                       phys_addr_t end, phys_addr_t size,
-                                       phys_addr_t align, int nid)
+phys_addr_t __init_memblock memblock_find_in_range_node(phys_addr_t size,
+                                       phys_addr_t align, phys_addr_t start,
+                                       phys_addr_t end, int nid)
 {
        int ret;
        phys_addr_t kernel_end;
@@ -241,8 +244,8 @@ phys_addr_t __init_memblock memblock_find_in_range(phys_addr_t start,
                                        phys_addr_t end, phys_addr_t size,
                                        phys_addr_t align)
 {
-       return memblock_find_in_range_node(start, end, size, align,
-                                          MAX_NUMNODES);
+       return memblock_find_in_range_node(size, align, start, end,
+                                           NUMA_NO_NODE);
 }
 
 static void __init_memblock memblock_remove_region(struct memblock_type *type, unsigned long r)
@@ -754,7 +757,7 @@ int __init_memblock memblock_clear_hotplug(phys_addr_t base, phys_addr_t size)
 /**
  * __next_free_mem_range - next function for for_each_free_mem_range()
  * @idx: pointer to u64 loop variable
- * @nid: node selector, %MAX_NUMNODES for all nodes
+ * @nid: node selector, %NUMA_NO_NODE for all nodes
  * @out_start: ptr to phys_addr_t for start address of the range, can be %NULL
  * @out_end: ptr to phys_addr_t for end address of the range, can be %NULL
  * @out_nid: ptr to int for nid of the range, can be %NULL
@@ -783,13 +786,16 @@ void __init_memblock __next_free_mem_range(u64 *idx, int nid,
        int mi = *idx & 0xffffffff;
        int ri = *idx >> 32;
 
+       if (WARN_ONCE(nid == MAX_NUMNODES, "Usage of MAX_NUMNODES is deprecated. Use NUMA_NO_NODE instead\n"))
+               nid = NUMA_NO_NODE;
+
        for ( ; mi < mem->cnt; mi++) {
                struct memblock_region *m = &mem->regions[mi];
                phys_addr_t m_start = m->base;
                phys_addr_t m_end = m->base + m->size;
 
                /* only memory regions are associated with nodes, check it */
-               if (nid != MAX_NUMNODES && nid != memblock_get_region_node(m))
+               if (nid != NUMA_NO_NODE && nid != memblock_get_region_node(m))
                        continue;
 
                /* scan areas before each reservation for intersection */
@@ -830,7 +836,7 @@ void __init_memblock __next_free_mem_range(u64 *idx, int nid,
 /**
  * __next_free_mem_range_rev - next function for for_each_free_mem_range_reverse()
  * @idx: pointer to u64 loop variable
- * @nid: nid: node selector, %MAX_NUMNODES for all nodes
+ * @nid: nid: node selector, %NUMA_NO_NODE for all nodes
  * @out_start: ptr to phys_addr_t for start address of the range, can be %NULL
  * @out_end: ptr to phys_addr_t for end address of the range, can be %NULL
  * @out_nid: ptr to int for nid of the range, can be %NULL
@@ -851,6 +857,9 @@ void __init_memblock __next_free_mem_range_rev(u64 *idx, int nid,
        int mi = *idx & 0xffffffff;
        int ri = *idx >> 32;
 
+       if (WARN_ONCE(nid == MAX_NUMNODES, "Usage of MAX_NUMNODES is deprecated. Use NUMA_NO_NODE instead\n"))
+               nid = NUMA_NO_NODE;
+
        if (*idx == (u64)ULLONG_MAX) {
                mi = mem->cnt - 1;
                ri = rsv->cnt;
@@ -862,7 +871,7 @@ void __init_memblock __next_free_mem_range_rev(u64 *idx, int nid,
                phys_addr_t m_end = m->base + m->size;
 
                /* only memory regions are associated with nodes, check it */
-               if (nid != MAX_NUMNODES && nid != memblock_get_region_node(m))
+               if (nid != NUMA_NO_NODE && nid != memblock_get_region_node(m))
                        continue;
 
                /* skip hotpluggable memory regions if needed */
@@ -969,13 +978,13 @@ static phys_addr_t __init memblock_alloc_base_nid(phys_addr_t size,
 {
        phys_addr_t found;
 
-       if (WARN_ON(!align))
-               align = __alignof__(long long);
+       if (!align)
+               align = SMP_CACHE_BYTES;
 
        /* align @size to avoid excessive fragmentation on reserved array */
        size = round_up(size, align);
 
-       found = memblock_find_in_range_node(0, max_addr, size, align, nid);
+       found = memblock_find_in_range_node(size, align, 0, max_addr, nid);
        if (found && !memblock_reserve(found, size))
                return found;
 
@@ -989,7 +998,7 @@ phys_addr_t __init memblock_alloc_nid(phys_addr_t size, phys_addr_t align, int n
 
 phys_addr_t __init __memblock_alloc_base(phys_addr_t size, phys_addr_t align, phys_addr_t max_addr)
 {
-       return memblock_alloc_base_nid(size, align, max_addr, MAX_NUMNODES);
+       return memblock_alloc_base_nid(size, align, max_addr, NUMA_NO_NODE);
 }
 
 phys_addr_t __init memblock_alloc_base(phys_addr_t size, phys_addr_t align, phys_addr_t max_addr)
@@ -1019,6 +1028,207 @@ phys_addr_t __init memblock_alloc_try_nid(phys_addr_t size, phys_addr_t align, i
        return memblock_alloc_base(size, align, MEMBLOCK_ALLOC_ACCESSIBLE);
 }
 
+/**
+ * memblock_virt_alloc_internal - allocate boot memory block
+ * @size: size of memory block to be allocated in bytes
+ * @align: alignment of the region and block's size
+ * @min_addr: the lower bound of the memory region to allocate (phys address)
+ * @max_addr: the upper bound of the memory region to allocate (phys address)
+ * @nid: nid of the free area to find, %NUMA_NO_NODE for any node
+ *
+ * The @min_addr limit is dropped if it can not be satisfied and the allocation
+ * will fall back to memory below @min_addr. Also, allocation may fall back
+ * to any node in the system if the specified node can not
+ * hold the requested memory.
+ *
+ * The allocation is performed from memory region limited by
+ * memblock.current_limit if @max_addr == %BOOTMEM_ALLOC_ACCESSIBLE.
+ *
+ * The memory block is aligned on SMP_CACHE_BYTES if @align == 0.
+ *
+ * The phys address of allocated boot memory block is converted to virtual and
+ * allocated memory is reset to 0.
+ *
+ * In addition, function sets the min_count to 0 using kmemleak_alloc for
+ * allocated boot memory block, so that it is never reported as leaks.
+ *
+ * RETURNS:
+ * Virtual address of allocated memory block on success, NULL on failure.
+ */
+static void * __init memblock_virt_alloc_internal(
+                               phys_addr_t size, phys_addr_t align,
+                               phys_addr_t min_addr, phys_addr_t max_addr,
+                               int nid)
+{
+       phys_addr_t alloc;
+       void *ptr;
+
+       if (WARN_ONCE(nid == MAX_NUMNODES, "Usage of MAX_NUMNODES is deprecated. Use NUMA_NO_NODE instead\n"))
+               nid = NUMA_NO_NODE;
+
+       /*
+        * Detect any accidental use of these APIs after slab is ready, as at
+        * this moment memblock may be deinitialized already and its
+        * internal data may be destroyed (after execution of free_all_bootmem)
+        */
+       if (WARN_ON_ONCE(slab_is_available()))
+               return kzalloc_node(size, GFP_NOWAIT, nid);
+
+       if (!align)
+               align = SMP_CACHE_BYTES;
+
+       /* align @size to avoid excessive fragmentation on reserved array */
+       size = round_up(size, align);
+
+again:
+       alloc = memblock_find_in_range_node(size, align, min_addr, max_addr,
+                                           nid);
+       if (alloc)
+               goto done;
+
+       if (nid != NUMA_NO_NODE) {
+               alloc = memblock_find_in_range_node(size, align, min_addr,
+                                                   max_addr,  NUMA_NO_NODE);
+               if (alloc)
+                       goto done;
+       }
+
+       if (min_addr) {
+               min_addr = 0;
+               goto again;
+       } else {
+               goto error;
+       }
+
+done:
+       memblock_reserve(alloc, size);
+       ptr = phys_to_virt(alloc);
+       memset(ptr, 0, size);
+
+       /*
+        * The min_count is set to 0 so that bootmem allocated blocks
+        * are never reported as leaks. This is because many of these blocks
+        * are only referred via the physical address which is not
+        * looked up by kmemleak.
+        */
+       kmemleak_alloc(ptr, size, 0, 0);
+
+       return ptr;
+
+error:
+       return NULL;
+}
+
+/**
+ * memblock_virt_alloc_try_nid_nopanic - allocate boot memory block
+ * @size: size of memory block to be allocated in bytes
+ * @align: alignment of the region and block's size
+ * @min_addr: the lower bound of the memory region from where the allocation
+ *       is preferred (phys address)
+ * @max_addr: the upper bound of the memory region from where the allocation
+ *           is preferred (phys address), or %BOOTMEM_ALLOC_ACCESSIBLE to
+ *           allocate only from memory limited by memblock.current_limit value
+ * @nid: nid of the free area to find, %NUMA_NO_NODE for any node
+ *
+ * Public version of _memblock_virt_alloc_try_nid_nopanic() which provides
+ * additional debug information (including caller info), if enabled.
+ *
+ * RETURNS:
+ * Virtual address of allocated memory block on success, NULL on failure.
+ */
+void * __init memblock_virt_alloc_try_nid_nopanic(
+                               phys_addr_t size, phys_addr_t align,
+                               phys_addr_t min_addr, phys_addr_t max_addr,
+                               int nid)
+{
+       memblock_dbg("%s: %llu bytes align=0x%llx nid=%d from=0x%llx max_addr=0x%llx %pF\n",
+                    __func__, (u64)size, (u64)align, nid, (u64)min_addr,
+                    (u64)max_addr, (void *)_RET_IP_);
+       return memblock_virt_alloc_internal(size, align, min_addr,
+                                            max_addr, nid);
+}
+
+/**
+ * memblock_virt_alloc_try_nid - allocate boot memory block with panicking
+ * @size: size of memory block to be allocated in bytes
+ * @align: alignment of the region and block's size
+ * @min_addr: the lower bound of the memory region from where the allocation
+ *       is preferred (phys address)
+ * @max_addr: the upper bound of the memory region from where the allocation
+ *           is preferred (phys address), or %BOOTMEM_ALLOC_ACCESSIBLE to
+ *           allocate only from memory limited by memblock.current_limit value
+ * @nid: nid of the free area to find, %NUMA_NO_NODE for any node
+ *
+ * Public panicking version of _memblock_virt_alloc_try_nid_nopanic()
+ * which provides debug information (including caller info), if enabled,
+ * and panics if the request can not be satisfied.
+ *
+ * RETURNS:
+ * Virtual address of allocated memory block on success, NULL on failure.
+ */
+void * __init memblock_virt_alloc_try_nid(
+                       phys_addr_t size, phys_addr_t align,
+                       phys_addr_t min_addr, phys_addr_t max_addr,
+                       int nid)
+{
+       void *ptr;
+
+       memblock_dbg("%s: %llu bytes align=0x%llx nid=%d from=0x%llx max_addr=0x%llx %pF\n",
+                    __func__, (u64)size, (u64)align, nid, (u64)min_addr,
+                    (u64)max_addr, (void *)_RET_IP_);
+       ptr = memblock_virt_alloc_internal(size, align,
+                                          min_addr, max_addr, nid);
+       if (ptr)
+               return ptr;
+
+       panic("%s: Failed to allocate %llu bytes align=0x%llx nid=%d from=0x%llx max_addr=0x%llx\n",
+             __func__, (u64)size, (u64)align, nid, (u64)min_addr,
+             (u64)max_addr);
+       return NULL;
+}
+
+/**
+ * __memblock_free_early - free boot memory block
+ * @base: phys starting address of the  boot memory block
+ * @size: size of the boot memory block in bytes
+ *
+ * Free boot memory block previously allocated by memblock_virt_alloc_xx() API.
+ * The freeing memory will not be released to the buddy allocator.
+ */
+void __init __memblock_free_early(phys_addr_t base, phys_addr_t size)
+{
+       memblock_dbg("%s: [%#016llx-%#016llx] %pF\n",
+                    __func__, (u64)base, (u64)base + size - 1,
+                    (void *)_RET_IP_);
+       kmemleak_free_part(__va(base), size);
+       __memblock_remove(&memblock.reserved, base, size);
+}
+
+/*
+ * __memblock_free_late - free bootmem block pages directly to buddy allocator
+ * @addr: phys starting address of the  boot memory block
+ * @size: size of the boot memory block in bytes
+ *
+ * This is only useful when the bootmem allocator has already been torn
+ * down, but we are still initializing the system.  Pages are released directly
+ * to the buddy allocator, no bootmem metadata is updated because it is gone.
+ */
+void __init __memblock_free_late(phys_addr_t base, phys_addr_t size)
+{
+       u64 cursor, end;
+
+       memblock_dbg("%s: [%#016llx-%#016llx] %pF\n",
+                    __func__, (u64)base, (u64)base + size - 1,
+                    (void *)_RET_IP_);
+       kmemleak_free_part(__va(base), size);
+       cursor = PFN_UP(base);
+       end = PFN_DOWN(base + size);
+
+       for (; cursor < end; cursor++) {
+               __free_pages_bootmem(pfn_to_page(cursor), 0);
+               totalram_pages++;
+       }
+}
 
 /*
  * Remaining API functions