diff options
Diffstat (limited to 'mm')
-rw-r--r-- | mm/Kconfig | 9 | ||||
-rw-r--r-- | mm/sparse.c | 38 |
2 files changed, 41 insertions, 6 deletions
diff --git a/mm/Kconfig b/mm/Kconfig index cd379936cac6..fc644c5c065d 100644 --- a/mm/Kconfig +++ b/mm/Kconfig | |||
@@ -89,3 +89,12 @@ config NEED_MULTIPLE_NODES | |||
89 | config HAVE_MEMORY_PRESENT | 89 | config HAVE_MEMORY_PRESENT |
90 | def_bool y | 90 | def_bool y |
91 | depends on ARCH_HAVE_MEMORY_PRESENT || SPARSEMEM | 91 | depends on ARCH_HAVE_MEMORY_PRESENT || SPARSEMEM |
92 | |||
93 | # | ||
94 | # Architectecture platforms which require a two level mem_section in SPARSEMEM | ||
95 | # must select this option. This is usually for architecture platforms with | ||
96 | # an extremely sparse physical address space. | ||
97 | # | ||
98 | config ARCH_SPARSEMEM_EXTREME | ||
99 | def_bool n | ||
100 | depends on SPARSEMEM && 64BIT | ||
diff --git a/mm/sparse.c b/mm/sparse.c index b54e304df4a7..b2b456bf0a5d 100644 --- a/mm/sparse.c +++ b/mm/sparse.c | |||
@@ -13,7 +13,26 @@ | |||
13 | * | 13 | * |
14 | * 1) mem_section - memory sections, mem_map's for valid memory | 14 | * 1) mem_section - memory sections, mem_map's for valid memory |
15 | */ | 15 | */ |
16 | struct mem_section mem_section[NR_MEM_SECTIONS]; | 16 | #ifdef CONFIG_ARCH_SPARSEMEM_EXTREME |
17 | struct mem_section *mem_section[NR_SECTION_ROOTS] | ||
18 | ____cacheline_maxaligned_in_smp; | ||
19 | |||
20 | static void sparse_index_init(unsigned long section, int nid) | ||
21 | { | ||
22 | unsigned long root = SECTION_TO_ROOT(section); | ||
23 | |||
24 | if (mem_section[root]) | ||
25 | return; | ||
26 | mem_section[root] = alloc_bootmem_node(NODE_DATA(nid), PAGE_SIZE); | ||
27 | if (mem_section[root]) | ||
28 | memset(mem_section[root], 0, PAGE_SIZE); | ||
29 | else | ||
30 | panic("memory_present: NO MEMORY\n"); | ||
31 | } | ||
32 | #else | ||
33 | struct mem_section mem_section[NR_MEM_SECTIONS] | ||
34 | ____cacheline_maxaligned_in_smp; | ||
35 | #endif | ||
17 | EXPORT_SYMBOL(mem_section); | 36 | EXPORT_SYMBOL(mem_section); |
18 | 37 | ||
19 | /* Record a memory area against a node. */ | 38 | /* Record a memory area against a node. */ |
@@ -24,8 +43,13 @@ void memory_present(int nid, unsigned long start, unsigned long end) | |||
24 | start &= PAGE_SECTION_MASK; | 43 | start &= PAGE_SECTION_MASK; |
25 | for (pfn = start; pfn < end; pfn += PAGES_PER_SECTION) { | 44 | for (pfn = start; pfn < end; pfn += PAGES_PER_SECTION) { |
26 | unsigned long section = pfn_to_section_nr(pfn); | 45 | unsigned long section = pfn_to_section_nr(pfn); |
27 | if (!mem_section[section].section_mem_map) | 46 | struct mem_section *ms; |
28 | mem_section[section].section_mem_map = SECTION_MARKED_PRESENT; | 47 | |
48 | sparse_index_init(section, nid); | ||
49 | |||
50 | ms = __nr_to_section(section); | ||
51 | if (!ms->section_mem_map) | ||
52 | ms->section_mem_map = SECTION_MARKED_PRESENT; | ||
29 | } | 53 | } |
30 | } | 54 | } |
31 | 55 | ||
@@ -85,6 +109,7 @@ static struct page *sparse_early_mem_map_alloc(unsigned long pnum) | |||
85 | { | 109 | { |
86 | struct page *map; | 110 | struct page *map; |
87 | int nid = early_pfn_to_nid(section_nr_to_pfn(pnum)); | 111 | int nid = early_pfn_to_nid(section_nr_to_pfn(pnum)); |
112 | struct mem_section *ms = __nr_to_section(pnum); | ||
88 | 113 | ||
89 | map = alloc_remap(nid, sizeof(struct page) * PAGES_PER_SECTION); | 114 | map = alloc_remap(nid, sizeof(struct page) * PAGES_PER_SECTION); |
90 | if (map) | 115 | if (map) |
@@ -96,7 +121,7 @@ static struct page *sparse_early_mem_map_alloc(unsigned long pnum) | |||
96 | return map; | 121 | return map; |
97 | 122 | ||
98 | printk(KERN_WARNING "%s: allocation failed\n", __FUNCTION__); | 123 | printk(KERN_WARNING "%s: allocation failed\n", __FUNCTION__); |
99 | mem_section[pnum].section_mem_map = 0; | 124 | ms->section_mem_map = 0; |
100 | return NULL; | 125 | return NULL; |
101 | } | 126 | } |
102 | 127 | ||
@@ -114,8 +139,9 @@ void sparse_init(void) | |||
114 | continue; | 139 | continue; |
115 | 140 | ||
116 | map = sparse_early_mem_map_alloc(pnum); | 141 | map = sparse_early_mem_map_alloc(pnum); |
117 | if (map) | 142 | if (!map) |
118 | sparse_init_one_section(&mem_section[pnum], pnum, map); | 143 | continue; |
144 | sparse_init_one_section(__nr_to_section(pnum), pnum, map); | ||
119 | } | 145 | } |
120 | } | 146 | } |
121 | 147 | ||