aboutsummaryrefslogtreecommitdiffstats
path: root/mm/sparse.c
diff options
context:
space:
mode:
Diffstat (limited to 'mm/sparse.c')
-rw-r--r--mm/sparse.c75
1 files changed, 69 insertions, 6 deletions
diff --git a/mm/sparse.c b/mm/sparse.c
index b54e304df4a7..347249a4917a 100644
--- a/mm/sparse.c
+++ b/mm/sparse.c
@@ -6,6 +6,7 @@
6#include <linux/mmzone.h> 6#include <linux/mmzone.h>
7#include <linux/bootmem.h> 7#include <linux/bootmem.h>
8#include <linux/module.h> 8#include <linux/module.h>
9#include <linux/spinlock.h>
9#include <asm/dma.h> 10#include <asm/dma.h>
10 11
11/* 12/*
@@ -13,9 +14,64 @@
13 * 14 *
14 * 1) mem_section - memory sections, mem_map's for valid memory 15 * 1) mem_section - memory sections, mem_map's for valid memory
15 */ 16 */
16struct mem_section mem_section[NR_MEM_SECTIONS]; 17#ifdef CONFIG_SPARSEMEM_EXTREME
18struct mem_section *mem_section[NR_SECTION_ROOTS]
19 ____cacheline_maxaligned_in_smp;
20#else
21struct mem_section mem_section[NR_SECTION_ROOTS][SECTIONS_PER_ROOT]
22 ____cacheline_maxaligned_in_smp;
23#endif
17EXPORT_SYMBOL(mem_section); 24EXPORT_SYMBOL(mem_section);
18 25
26#ifdef CONFIG_SPARSEMEM_EXTREME
27static struct mem_section *sparse_index_alloc(int nid)
28{
29 struct mem_section *section = NULL;
30 unsigned long array_size = SECTIONS_PER_ROOT *
31 sizeof(struct mem_section);
32
33 section = alloc_bootmem_node(NODE_DATA(nid), array_size);
34
35 if (section)
36 memset(section, 0, array_size);
37
38 return section;
39}
40
41static int sparse_index_init(unsigned long section_nr, int nid)
42{
43 static spinlock_t index_init_lock = SPIN_LOCK_UNLOCKED;
44 unsigned long root = SECTION_NR_TO_ROOT(section_nr);
45 struct mem_section *section;
46 int ret = 0;
47
48 if (mem_section[root])
49 return -EEXIST;
50
51 section = sparse_index_alloc(nid);
52 /*
53 * This lock keeps two different sections from
54 * reallocating for the same index
55 */
56 spin_lock(&index_init_lock);
57
58 if (mem_section[root]) {
59 ret = -EEXIST;
60 goto out;
61 }
62
63 mem_section[root] = section;
64out:
65 spin_unlock(&index_init_lock);
66 return ret;
67}
68#else /* !SPARSEMEM_EXTREME */
69static inline int sparse_index_init(unsigned long section_nr, int nid)
70{
71 return 0;
72}
73#endif
74
19/* Record a memory area against a node. */ 75/* Record a memory area against a node. */
20void memory_present(int nid, unsigned long start, unsigned long end) 76void memory_present(int nid, unsigned long start, unsigned long end)
21{ 77{
@@ -24,8 +80,13 @@ void memory_present(int nid, unsigned long start, unsigned long end)
24 start &= PAGE_SECTION_MASK; 80 start &= PAGE_SECTION_MASK;
25 for (pfn = start; pfn < end; pfn += PAGES_PER_SECTION) { 81 for (pfn = start; pfn < end; pfn += PAGES_PER_SECTION) {
26 unsigned long section = pfn_to_section_nr(pfn); 82 unsigned long section = pfn_to_section_nr(pfn);
27 if (!mem_section[section].section_mem_map) 83 struct mem_section *ms;
28 mem_section[section].section_mem_map = SECTION_MARKED_PRESENT; 84
85 sparse_index_init(section, nid);
86
87 ms = __nr_to_section(section);
88 if (!ms->section_mem_map)
89 ms->section_mem_map = SECTION_MARKED_PRESENT;
29 } 90 }
30} 91}
31 92
@@ -85,6 +146,7 @@ static struct page *sparse_early_mem_map_alloc(unsigned long pnum)
85{ 146{
86 struct page *map; 147 struct page *map;
87 int nid = early_pfn_to_nid(section_nr_to_pfn(pnum)); 148 int nid = early_pfn_to_nid(section_nr_to_pfn(pnum));
149 struct mem_section *ms = __nr_to_section(pnum);
88 150
89 map = alloc_remap(nid, sizeof(struct page) * PAGES_PER_SECTION); 151 map = alloc_remap(nid, sizeof(struct page) * PAGES_PER_SECTION);
90 if (map) 152 if (map)
@@ -96,7 +158,7 @@ static struct page *sparse_early_mem_map_alloc(unsigned long pnum)
96 return map; 158 return map;
97 159
98 printk(KERN_WARNING "%s: allocation failed\n", __FUNCTION__); 160 printk(KERN_WARNING "%s: allocation failed\n", __FUNCTION__);
99 mem_section[pnum].section_mem_map = 0; 161 ms->section_mem_map = 0;
100 return NULL; 162 return NULL;
101} 163}
102 164
@@ -114,8 +176,9 @@ void sparse_init(void)
114 continue; 176 continue;
115 177
116 map = sparse_early_mem_map_alloc(pnum); 178 map = sparse_early_mem_map_alloc(pnum);
117 if (map) 179 if (!map)
118 sparse_init_one_section(&mem_section[pnum], pnum, map); 180 continue;
181 sparse_init_one_section(__nr_to_section(pnum), pnum, map);
119 } 182 }
120} 183}
121 184