diff options
author | Yinghai Lu <yinghai@kernel.org> | 2010-02-10 04:20:15 -0500 |
---|---|---|
committer | H. Peter Anvin <hpa@zytor.com> | 2010-02-10 20:47:18 -0500 |
commit | 1842f90cc98625d4d9bf8f8b927f17705ceb4e9c (patch) | |
tree | 12a120d130aef8d12010d1b3732af1387bac751d /arch/x86/mm/numa_64.c | |
parent | 79c601695870ca2a9c0ba9949a97d2be78ec07b2 (diff) |
x86: Call early_res_to_bootmem one time
Simplify setup_node_mem: don't use bootmem from other node, instead
just find_e820_area in early_node_mem.
This keeps the boundary between early_res and boot mem more clear, and
lets us only call early_res_to_bootmem() one time instead of for all
nodes.
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
LKML-Reference: <1265793639-15071-12-git-send-email-yinghai@kernel.org>
Signed-off-by: H. Peter Anvin <hpa@zytor.com>
Diffstat (limited to 'arch/x86/mm/numa_64.c')
-rw-r--r-- | arch/x86/mm/numa_64.c | 62 |
1 files changed, 20 insertions, 42 deletions
diff --git a/arch/x86/mm/numa_64.c b/arch/x86/mm/numa_64.c index 83bbc70d11bb..3232148756ce 100644 --- a/arch/x86/mm/numa_64.c +++ b/arch/x86/mm/numa_64.c | |||
@@ -164,18 +164,21 @@ static void * __init early_node_mem(int nodeid, unsigned long start, | |||
164 | unsigned long align) | 164 | unsigned long align) |
165 | { | 165 | { |
166 | unsigned long mem = find_e820_area(start, end, size, align); | 166 | unsigned long mem = find_e820_area(start, end, size, align); |
167 | void *ptr; | ||
168 | 167 | ||
169 | if (mem != -1L) | 168 | if (mem != -1L) |
170 | return __va(mem); | 169 | return __va(mem); |
171 | 170 | ||
172 | ptr = __alloc_bootmem_nopanic(size, align, __pa(MAX_DMA_ADDRESS)); | 171 | |
173 | if (ptr == NULL) { | 172 | start = __pa(MAX_DMA_ADDRESS); |
174 | printk(KERN_ERR "Cannot find %lu bytes in node %d\n", | 173 | end = max_low_pfn_mapped << PAGE_SHIFT; |
174 | mem = find_e820_area(start, end, size, align); | ||
175 | if (mem != -1L) | ||
176 | return __va(mem); | ||
177 | |||
178 | printk(KERN_ERR "Cannot find %lu bytes in node %d\n", | ||
175 | size, nodeid); | 179 | size, nodeid); |
176 | return NULL; | 180 | |
177 | } | 181 | return NULL; |
178 | return ptr; | ||
179 | } | 182 | } |
180 | 183 | ||
181 | /* Initialize bootmem allocator for a node */ | 184 | /* Initialize bootmem allocator for a node */ |
@@ -211,8 +214,12 @@ setup_node_bootmem(int nodeid, unsigned long start, unsigned long end) | |||
211 | if (node_data[nodeid] == NULL) | 214 | if (node_data[nodeid] == NULL) |
212 | return; | 215 | return; |
213 | nodedata_phys = __pa(node_data[nodeid]); | 216 | nodedata_phys = __pa(node_data[nodeid]); |
217 | reserve_early(nodedata_phys, nodedata_phys + pgdat_size, "NODE_DATA"); | ||
214 | printk(KERN_INFO " NODE_DATA [%016lx - %016lx]\n", nodedata_phys, | 218 | printk(KERN_INFO " NODE_DATA [%016lx - %016lx]\n", nodedata_phys, |
215 | nodedata_phys + pgdat_size - 1); | 219 | nodedata_phys + pgdat_size - 1); |
220 | nid = phys_to_nid(nodedata_phys); | ||
221 | if (nid != nodeid) | ||
222 | printk(KERN_INFO " NODE_DATA(%d) on node %d\n", nodeid, nid); | ||
216 | 223 | ||
217 | memset(NODE_DATA(nodeid), 0, sizeof(pg_data_t)); | 224 | memset(NODE_DATA(nodeid), 0, sizeof(pg_data_t)); |
218 | NODE_DATA(nodeid)->bdata = &bootmem_node_data[nodeid]; | 225 | NODE_DATA(nodeid)->bdata = &bootmem_node_data[nodeid]; |
@@ -227,11 +234,7 @@ setup_node_bootmem(int nodeid, unsigned long start, unsigned long end) | |||
227 | * of alloc_bootmem, that could clash with reserved range | 234 | * of alloc_bootmem, that could clash with reserved range |
228 | */ | 235 | */ |
229 | bootmap_pages = bootmem_bootmap_pages(last_pfn - start_pfn); | 236 | bootmap_pages = bootmem_bootmap_pages(last_pfn - start_pfn); |
230 | nid = phys_to_nid(nodedata_phys); | 237 | bootmap_start = roundup(nodedata_phys + pgdat_size, PAGE_SIZE); |
231 | if (nid == nodeid) | ||
232 | bootmap_start = roundup(nodedata_phys + pgdat_size, PAGE_SIZE); | ||
233 | else | ||
234 | bootmap_start = roundup(start, PAGE_SIZE); | ||
235 | /* | 238 | /* |
236 | * SMP_CACHE_BYTES could be enough, but init_bootmem_node like | 239 | * SMP_CACHE_BYTES could be enough, but init_bootmem_node like |
237 | * to use that to align to PAGE_SIZE | 240 | * to use that to align to PAGE_SIZE |
@@ -239,18 +242,13 @@ setup_node_bootmem(int nodeid, unsigned long start, unsigned long end) | |||
239 | bootmap = early_node_mem(nodeid, bootmap_start, end, | 242 | bootmap = early_node_mem(nodeid, bootmap_start, end, |
240 | bootmap_pages<<PAGE_SHIFT, PAGE_SIZE); | 243 | bootmap_pages<<PAGE_SHIFT, PAGE_SIZE); |
241 | if (bootmap == NULL) { | 244 | if (bootmap == NULL) { |
242 | if (nodedata_phys < start || nodedata_phys >= end) { | 245 | free_early(nodedata_phys, nodedata_phys + pgdat_size); |
243 | /* | ||
244 | * only need to free it if it is from other node | ||
245 | * bootmem | ||
246 | */ | ||
247 | if (nid != nodeid) | ||
248 | free_bootmem(nodedata_phys, pgdat_size); | ||
249 | } | ||
250 | node_data[nodeid] = NULL; | 246 | node_data[nodeid] = NULL; |
251 | return; | 247 | return; |
252 | } | 248 | } |
253 | bootmap_start = __pa(bootmap); | 249 | bootmap_start = __pa(bootmap); |
250 | reserve_early(bootmap_start, bootmap_start+(bootmap_pages<<PAGE_SHIFT), | ||
251 | "BOOTMAP"); | ||
254 | 252 | ||
255 | bootmap_size = init_bootmem_node(NODE_DATA(nodeid), | 253 | bootmap_size = init_bootmem_node(NODE_DATA(nodeid), |
256 | bootmap_start >> PAGE_SHIFT, | 254 | bootmap_start >> PAGE_SHIFT, |
@@ -259,31 +257,11 @@ setup_node_bootmem(int nodeid, unsigned long start, unsigned long end) | |||
259 | printk(KERN_INFO " bootmap [%016lx - %016lx] pages %lx\n", | 257 | printk(KERN_INFO " bootmap [%016lx - %016lx] pages %lx\n", |
260 | bootmap_start, bootmap_start + bootmap_size - 1, | 258 | bootmap_start, bootmap_start + bootmap_size - 1, |
261 | bootmap_pages); | 259 | bootmap_pages); |
262 | |||
263 | free_bootmem_with_active_regions(nodeid, end); | ||
264 | |||
265 | /* | ||
266 | * convert early reserve to bootmem reserve earlier | ||
267 | * otherwise early_node_mem could use early reserved mem | ||
268 | * on previous node | ||
269 | */ | ||
270 | early_res_to_bootmem(start, end); | ||
271 | |||
272 | /* | ||
273 | * in some case early_node_mem could use alloc_bootmem | ||
274 | * to get range on other node, don't reserve that again | ||
275 | */ | ||
276 | if (nid != nodeid) | ||
277 | printk(KERN_INFO " NODE_DATA(%d) on node %d\n", nodeid, nid); | ||
278 | else | ||
279 | reserve_bootmem_node(NODE_DATA(nodeid), nodedata_phys, | ||
280 | pgdat_size, BOOTMEM_DEFAULT); | ||
281 | nid = phys_to_nid(bootmap_start); | 260 | nid = phys_to_nid(bootmap_start); |
282 | if (nid != nodeid) | 261 | if (nid != nodeid) |
283 | printk(KERN_INFO " bootmap(%d) on node %d\n", nodeid, nid); | 262 | printk(KERN_INFO " bootmap(%d) on node %d\n", nodeid, nid); |
284 | else | 263 | |
285 | reserve_bootmem_node(NODE_DATA(nodeid), bootmap_start, | 264 | free_bootmem_with_active_regions(nodeid, end); |
286 | bootmap_pages<<PAGE_SHIFT, BOOTMEM_DEFAULT); | ||
287 | 265 | ||
288 | node_set_online(nodeid); | 266 | node_set_online(nodeid); |
289 | } | 267 | } |