memblock: rename __free_pages_bootmem to memblock_free_pages
[linux-2.6-block.git] / mm / nobootmem.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  *  bootmem - A boot-time physical memory allocator and configurator
4  *
5  *  Copyright (C) 1999 Ingo Molnar
6  *                1999 Kanoj Sarcar, SGI
7  *                2008 Johannes Weiner
8  *
9  * Access to this subsystem has to be serialized externally (which is true
10  * for the boot process anyway).
11  */
12 #include <linux/init.h>
13 #include <linux/pfn.h>
14 #include <linux/slab.h>
15 #include <linux/export.h>
16 #include <linux/kmemleak.h>
17 #include <linux/range.h>
18 #include <linux/memblock.h>
19 #include <linux/bootmem.h>
20
21 #include <asm/bug.h>
22 #include <asm/io.h>
23
24 #include "internal.h"
25
26 #ifndef CONFIG_NEED_MULTIPLE_NODES
27 struct pglist_data __refdata contig_page_data;
28 EXPORT_SYMBOL(contig_page_data);
29 #endif
30
31 unsigned long max_low_pfn;
32 unsigned long min_low_pfn;
33 unsigned long max_pfn;
34 unsigned long long max_possible_pfn;
35
36 static void __init __free_pages_memory(unsigned long start, unsigned long end)
37 {
38         int order;
39
40         while (start < end) {
41                 order = min(MAX_ORDER - 1UL, __ffs(start));
42
43                 while (start + (1UL << order) > end)
44                         order--;
45
46                 memblock_free_pages(pfn_to_page(start), start, order);
47
48                 start += (1UL << order);
49         }
50 }
51
52 static unsigned long __init __free_memory_core(phys_addr_t start,
53                                  phys_addr_t end)
54 {
55         unsigned long start_pfn = PFN_UP(start);
56         unsigned long end_pfn = min_t(unsigned long,
57                                       PFN_DOWN(end), max_low_pfn);
58
59         if (start_pfn >= end_pfn)
60                 return 0;
61
62         __free_pages_memory(start_pfn, end_pfn);
63
64         return end_pfn - start_pfn;
65 }
66
67 static unsigned long __init free_low_memory_core_early(void)
68 {
69         unsigned long count = 0;
70         phys_addr_t start, end;
71         u64 i;
72
73         memblock_clear_hotplug(0, -1);
74
75         for_each_reserved_mem_region(i, &start, &end)
76                 reserve_bootmem_region(start, end);
77
78         /*
79          * We need to use NUMA_NO_NODE instead of NODE_DATA(0)->node_id
80          *  because in some case like Node0 doesn't have RAM installed
81          *  low ram will be on Node1
82          */
83         for_each_free_mem_range(i, NUMA_NO_NODE, MEMBLOCK_NONE, &start, &end,
84                                 NULL)
85                 count += __free_memory_core(start, end);
86
87         return count;
88 }
89
90 static int reset_managed_pages_done __initdata;
91
92 void reset_node_managed_pages(pg_data_t *pgdat)
93 {
94         struct zone *z;
95
96         for (z = pgdat->node_zones; z < pgdat->node_zones + MAX_NR_ZONES; z++)
97                 z->managed_pages = 0;
98 }
99
100 void __init reset_all_zones_managed_pages(void)
101 {
102         struct pglist_data *pgdat;
103
104         if (reset_managed_pages_done)
105                 return;
106
107         for_each_online_pgdat(pgdat)
108                 reset_node_managed_pages(pgdat);
109
110         reset_managed_pages_done = 1;
111 }
112
113 /**
114  * memblock_free_all - release free pages to the buddy allocator
115  *
116  * Return: the number of pages actually released.
117  */
118 unsigned long __init memblock_free_all(void)
119 {
120         unsigned long pages;
121
122         reset_all_zones_managed_pages();
123
124         pages = free_low_memory_core_early();
125         totalram_pages += pages;
126
127         return pages;
128 }