rcu: Remove unused rcu_state externs
[linux-2.6-microblaze.git] / mm / memblock.c
index a853150..7df468c 100644 (file)
@@ -20,7 +20,6 @@
 #include <linux/kmemleak.h>
 #include <linux/seq_file.h>
 #include <linux/memblock.h>
-#include <linux/bootmem.h>
 
 #include <asm/sections.h>
 #include <linux/io.h>
  * initialization compltes.
  */
 
+#ifndef CONFIG_NEED_MULTIPLE_NODES
+struct pglist_data __refdata contig_page_data;
+EXPORT_SYMBOL(contig_page_data);
+#endif
+
+unsigned long max_low_pfn;
+unsigned long min_low_pfn;
+unsigned long max_pfn;
+unsigned long long max_possible_pfn;
+
 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;
 #ifdef CONFIG_HAVE_MEMBLOCK_PHYS_MAP
@@ -1238,8 +1247,11 @@ static phys_addr_t __init memblock_alloc_range_nid(phys_addr_t size,
 {
        phys_addr_t found;
 
-       if (!align)
+       if (!align) {
+               /* Can't use WARNs this early in boot on powerpc */
+               dump_stack();
                align = SMP_CACHE_BYTES;
+       }
 
        found = memblock_find_in_range_node(size, align, start, end, nid,
                                            flags);
@@ -1269,7 +1281,7 @@ phys_addr_t __init memblock_alloc_base_nid(phys_addr_t size,
        return memblock_alloc_range_nid(size, align, 0, max_addr, nid, flags);
 }
 
-phys_addr_t __init memblock_alloc_nid(phys_addr_t size, phys_addr_t align, int nid)
+phys_addr_t __init memblock_phys_alloc_nid(phys_addr_t size, phys_addr_t align, int nid)
 {
        enum memblock_flags flags = choose_memblock_flags();
        phys_addr_t ret;
@@ -1304,23 +1316,22 @@ phys_addr_t __init memblock_alloc_base(phys_addr_t size, phys_addr_t align, phys
        return alloc;
 }
 
-phys_addr_t __init memblock_alloc(phys_addr_t size, phys_addr_t align)
+phys_addr_t __init memblock_phys_alloc(phys_addr_t size, phys_addr_t align)
 {
        return memblock_alloc_base(size, align, MEMBLOCK_ALLOC_ACCESSIBLE);
 }
 
-phys_addr_t __init memblock_alloc_try_nid(phys_addr_t size, phys_addr_t align, int nid)
+phys_addr_t __init memblock_phys_alloc_try_nid(phys_addr_t size, phys_addr_t align, int nid)
 {
-       phys_addr_t res = memblock_alloc_nid(size, align, nid);
+       phys_addr_t res = memblock_phys_alloc_nid(size, align, nid);
 
        if (res)
                return res;
        return memblock_alloc_base(size, align, MEMBLOCK_ALLOC_ACCESSIBLE);
 }
 
-#if defined(CONFIG_NO_BOOTMEM)
 /**
- * memblock_virt_alloc_internal - allocate boot memory block
+ * memblock_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)
@@ -1333,9 +1344,7 @@ phys_addr_t __init memblock_alloc_try_nid(phys_addr_t size, phys_addr_t align, i
  * 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.
+ * memblock.current_limit if @max_addr == %MEMBLOCK_ALLOC_ACCESSIBLE.
  *
  * The phys address of allocated boot memory block is converted to virtual and
  * allocated memory is reset to 0.
@@ -1346,7 +1355,7 @@ phys_addr_t __init memblock_alloc_try_nid(phys_addr_t size, phys_addr_t align, i
  * Return:
  * Virtual address of allocated memory block on success, NULL on failure.
  */
-static void * __init memblock_virt_alloc_internal(
+static void * __init memblock_alloc_internal(
                                phys_addr_t size, phys_addr_t align,
                                phys_addr_t min_addr, phys_addr_t max_addr,
                                int nid)
@@ -1361,13 +1370,15 @@ static void * __init memblock_virt_alloc_internal(
        /*
         * 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)
+        * internal data may be destroyed (after execution of memblock_free_all)
         */
        if (WARN_ON_ONCE(slab_is_available()))
                return kzalloc_node(size, GFP_NOWAIT, nid);
 
-       if (!align)
+       if (!align) {
+               dump_stack();
                align = SMP_CACHE_BYTES;
+       }
 
        if (max_addr > memblock.current_limit)
                max_addr = memblock.current_limit;
@@ -1413,14 +1424,14 @@ done:
 }
 
 /**
- * memblock_virt_alloc_try_nid_raw - allocate boot memory block without zeroing
+ * memblock_alloc_try_nid_raw - allocate boot memory block without zeroing
  * memory and without 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
+ *           is preferred (phys address), or %MEMBLOCK_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
  *
@@ -1431,7 +1442,7 @@ done:
  * Return:
  * Virtual address of allocated memory block on success, NULL on failure.
  */
-void * __init memblock_virt_alloc_try_nid_raw(
+void * __init memblock_alloc_try_nid_raw(
                        phys_addr_t size, phys_addr_t align,
                        phys_addr_t min_addr, phys_addr_t max_addr,
                        int nid)
@@ -1442,7 +1453,7 @@ void * __init memblock_virt_alloc_try_nid_raw(
                     __func__, (u64)size, (u64)align, nid, &min_addr,
                     &max_addr, (void *)_RET_IP_);
 
-       ptr = memblock_virt_alloc_internal(size, align,
+       ptr = memblock_alloc_internal(size, align,
                                           min_addr, max_addr, nid);
        if (ptr && size > 0)
                page_init_poison(ptr, size);
@@ -1451,13 +1462,13 @@ void * __init memblock_virt_alloc_try_nid_raw(
 }
 
 /**
- * memblock_virt_alloc_try_nid_nopanic - allocate boot memory block
+ * memblock_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
+ *           is preferred (phys address), or %MEMBLOCK_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
  *
@@ -1467,7 +1478,7 @@ void * __init memblock_virt_alloc_try_nid_raw(
  * Return:
  * Virtual address of allocated memory block on success, NULL on failure.
  */
-void * __init memblock_virt_alloc_try_nid_nopanic(
+void * __init memblock_alloc_try_nid_nopanic(
                                phys_addr_t size, phys_addr_t align,
                                phys_addr_t min_addr, phys_addr_t max_addr,
                                int nid)
@@ -1478,7 +1489,7 @@ void * __init memblock_virt_alloc_try_nid_nopanic(
                     __func__, (u64)size, (u64)align, nid, &min_addr,
                     &max_addr, (void *)_RET_IP_);
 
-       ptr = memblock_virt_alloc_internal(size, align,
+       ptr = memblock_alloc_internal(size, align,
                                           min_addr, max_addr, nid);
        if (ptr)
                memset(ptr, 0, size);
@@ -1486,24 +1497,24 @@ void * __init memblock_virt_alloc_try_nid_nopanic(
 }
 
 /**
- * memblock_virt_alloc_try_nid - allocate boot memory block with panicking
+ * memblock_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
+ *           is preferred (phys address), or %MEMBLOCK_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()
+ * Public panicking version of memblock_alloc_try_nid_nopanic()
  * which provides debug information (including caller info), if enabled,
  * and panics if the request can not be satisfied.
  *
  * Return:
  * Virtual address of allocated memory block on success, NULL on failure.
  */
-void * __init memblock_virt_alloc_try_nid(
+void * __init memblock_alloc_try_nid(
                        phys_addr_t size, phys_addr_t align,
                        phys_addr_t min_addr, phys_addr_t max_addr,
                        int nid)
@@ -1513,7 +1524,7 @@ void * __init memblock_virt_alloc_try_nid(
        memblock_dbg("%s: %llu bytes align=0x%llx nid=%d from=%pa max_addr=%pa %pF\n",
                     __func__, (u64)size, (u64)align, nid, &min_addr,
                     &max_addr, (void *)_RET_IP_);
-       ptr = memblock_virt_alloc_internal(size, align,
+       ptr = memblock_alloc_internal(size, align,
                                           min_addr, max_addr, nid);
        if (ptr) {
                memset(ptr, 0, size);
@@ -1524,14 +1535,13 @@ void * __init memblock_virt_alloc_try_nid(
              __func__, (u64)size, (u64)align, nid, &min_addr, &max_addr);
        return NULL;
 }
-#endif
 
 /**
  * __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.
+ * Free boot memory block previously allocated by memblock_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)
@@ -1565,7 +1575,7 @@ void __init __memblock_free_late(phys_addr_t base, phys_addr_t size)
        end = PFN_DOWN(base + size);
 
        for (; cursor < end; cursor++) {
-               __free_pages_bootmem(pfn_to_page(cursor), cursor, 0);
+               memblock_free_pages(pfn_to_page(cursor), cursor, 0);
                totalram_pages++;
        }
 }
@@ -1879,6 +1889,100 @@ static int __init early_memblock(char *p)
 }
 early_param("memblock", early_memblock);
 
+static void __init __free_pages_memory(unsigned long start, unsigned long end)
+{
+       int order;
+
+       while (start < end) {
+               order = min(MAX_ORDER - 1UL, __ffs(start));
+
+               while (start + (1UL << order) > end)
+                       order--;
+
+               memblock_free_pages(pfn_to_page(start), start, order);
+
+               start += (1UL << order);
+       }
+}
+
+static unsigned long __init __free_memory_core(phys_addr_t start,
+                                phys_addr_t end)
+{
+       unsigned long start_pfn = PFN_UP(start);
+       unsigned long end_pfn = min_t(unsigned long,
+                                     PFN_DOWN(end), max_low_pfn);
+
+       if (start_pfn >= end_pfn)
+               return 0;
+
+       __free_pages_memory(start_pfn, end_pfn);
+
+       return end_pfn - start_pfn;
+}
+
+static unsigned long __init free_low_memory_core_early(void)
+{
+       unsigned long count = 0;
+       phys_addr_t start, end;
+       u64 i;
+
+       memblock_clear_hotplug(0, -1);
+
+       for_each_reserved_mem_region(i, &start, &end)
+               reserve_bootmem_region(start, end);
+
+       /*
+        * We need to use NUMA_NO_NODE instead of NODE_DATA(0)->node_id
+        *  because in some case like Node0 doesn't have RAM installed
+        *  low ram will be on Node1
+        */
+       for_each_free_mem_range(i, NUMA_NO_NODE, MEMBLOCK_NONE, &start, &end,
+                               NULL)
+               count += __free_memory_core(start, end);
+
+       return count;
+}
+
+static int reset_managed_pages_done __initdata;
+
+void reset_node_managed_pages(pg_data_t *pgdat)
+{
+       struct zone *z;
+
+       for (z = pgdat->node_zones; z < pgdat->node_zones + MAX_NR_ZONES; z++)
+               z->managed_pages = 0;
+}
+
+void __init reset_all_zones_managed_pages(void)
+{
+       struct pglist_data *pgdat;
+
+       if (reset_managed_pages_done)
+               return;
+
+       for_each_online_pgdat(pgdat)
+               reset_node_managed_pages(pgdat);
+
+       reset_managed_pages_done = 1;
+}
+
+/**
+ * memblock_free_all - release free pages to the buddy allocator
+ *
+ * Return: the number of pages actually released.
+ */
+unsigned long __init memblock_free_all(void)
+{
+       unsigned long pages;
+
+       reset_all_zones_managed_pages();
+
+       pages = free_low_memory_core_early();
+       totalram_pages += pages;
+
+       return pages;
+}
+
 #if defined(CONFIG_DEBUG_FS) && !defined(CONFIG_ARCH_DISCARD_MEMBLOCK)
 
 static int memblock_debug_show(struct seq_file *m, void *private)