diff options
Diffstat (limited to 'arch/x86_64')
-rw-r--r-- | arch/x86_64/mm/numa.c | 41 | ||||
-rw-r--r-- | arch/x86_64/mm/srat.c | 6 |
2 files changed, 38 insertions, 9 deletions
diff --git a/arch/x86_64/mm/numa.c b/arch/x86_64/mm/numa.c index 779132af29a7..cc02573a3271 100644 --- a/arch/x86_64/mm/numa.c +++ b/arch/x86_64/mm/numa.c | |||
@@ -100,11 +100,30 @@ int early_pfn_to_nid(unsigned long pfn) | |||
100 | } | 100 | } |
101 | #endif | 101 | #endif |
102 | 102 | ||
103 | static void * __init | ||
104 | early_node_mem(int nodeid, unsigned long start, unsigned long end, | ||
105 | unsigned long size) | ||
106 | { | ||
107 | unsigned long mem = find_e820_area(start, end, size); | ||
108 | void *ptr; | ||
109 | if (mem != -1L) | ||
110 | return __va(mem); | ||
111 | ptr = __alloc_bootmem_nopanic(size, | ||
112 | SMP_CACHE_BYTES, __pa(MAX_DMA_ADDRESS)); | ||
113 | if (ptr == 0) { | ||
114 | printk(KERN_ERR "Cannot find %lu bytes in node %d\n", | ||
115 | size, nodeid); | ||
116 | return NULL; | ||
117 | } | ||
118 | return ptr; | ||
119 | } | ||
120 | |||
103 | /* Initialize bootmem allocator for a node */ | 121 | /* Initialize bootmem allocator for a node */ |
104 | void __init setup_node_bootmem(int nodeid, unsigned long start, unsigned long end) | 122 | void __init setup_node_bootmem(int nodeid, unsigned long start, unsigned long end) |
105 | { | 123 | { |
106 | unsigned long start_pfn, end_pfn, bootmap_pages, bootmap_size, bootmap_start; | 124 | unsigned long start_pfn, end_pfn, bootmap_pages, bootmap_size, bootmap_start; |
107 | unsigned long nodedata_phys; | 125 | unsigned long nodedata_phys; |
126 | void *bootmap; | ||
108 | const int pgdat_size = round_up(sizeof(pg_data_t), PAGE_SIZE); | 127 | const int pgdat_size = round_up(sizeof(pg_data_t), PAGE_SIZE); |
109 | 128 | ||
110 | start = round_up(start, ZONE_ALIGN); | 129 | start = round_up(start, ZONE_ALIGN); |
@@ -114,13 +133,11 @@ void __init setup_node_bootmem(int nodeid, unsigned long start, unsigned long en | |||
114 | start_pfn = start >> PAGE_SHIFT; | 133 | start_pfn = start >> PAGE_SHIFT; |
115 | end_pfn = end >> PAGE_SHIFT; | 134 | end_pfn = end >> PAGE_SHIFT; |
116 | 135 | ||
117 | nodedata_phys = find_e820_area(start, end, pgdat_size); | 136 | node_data[nodeid] = early_node_mem(nodeid, start, end, pgdat_size); |
118 | if (nodedata_phys == -1L) | 137 | if (node_data[nodeid] == NULL) |
119 | panic("Cannot find memory pgdat in node %d\n", nodeid); | 138 | return; |
120 | 139 | nodedata_phys = __pa(node_data[nodeid]); | |
121 | Dprintk("nodedata_phys %lx\n", nodedata_phys); | ||
122 | 140 | ||
123 | node_data[nodeid] = phys_to_virt(nodedata_phys); | ||
124 | memset(NODE_DATA(nodeid), 0, sizeof(pg_data_t)); | 141 | memset(NODE_DATA(nodeid), 0, sizeof(pg_data_t)); |
125 | NODE_DATA(nodeid)->bdata = &plat_node_bdata[nodeid]; | 142 | NODE_DATA(nodeid)->bdata = &plat_node_bdata[nodeid]; |
126 | NODE_DATA(nodeid)->node_start_pfn = start_pfn; | 143 | NODE_DATA(nodeid)->node_start_pfn = start_pfn; |
@@ -129,9 +146,15 @@ void __init setup_node_bootmem(int nodeid, unsigned long start, unsigned long en | |||
129 | /* Find a place for the bootmem map */ | 146 | /* Find a place for the bootmem map */ |
130 | bootmap_pages = bootmem_bootmap_pages(end_pfn - start_pfn); | 147 | bootmap_pages = bootmem_bootmap_pages(end_pfn - start_pfn); |
131 | bootmap_start = round_up(nodedata_phys + pgdat_size, PAGE_SIZE); | 148 | bootmap_start = round_up(nodedata_phys + pgdat_size, PAGE_SIZE); |
132 | bootmap_start = find_e820_area(bootmap_start, end, bootmap_pages<<PAGE_SHIFT); | 149 | bootmap = early_node_mem(nodeid, bootmap_start, end, |
133 | if (bootmap_start == -1L) | 150 | bootmap_pages<<PAGE_SHIFT); |
134 | panic("Not enough continuous space for bootmap on node %d", nodeid); | 151 | if (bootmap == NULL) { |
152 | if (nodedata_phys < start || nodedata_phys >= end) | ||
153 | free_bootmem((unsigned long)node_data[nodeid],pgdat_size); | ||
154 | node_data[nodeid] = NULL; | ||
155 | return; | ||
156 | } | ||
157 | bootmap_start = __pa(bootmap); | ||
135 | Dprintk("bootmap start %lu pages %lu\n", bootmap_start, bootmap_pages); | 158 | Dprintk("bootmap start %lu pages %lu\n", bootmap_start, bootmap_pages); |
136 | 159 | ||
137 | bootmap_size = init_bootmem_node(NODE_DATA(nodeid), | 160 | bootmap_size = init_bootmem_node(NODE_DATA(nodeid), |
diff --git a/arch/x86_64/mm/srat.c b/arch/x86_64/mm/srat.c index 443875eb15a2..15ae9fcd65a7 100644 --- a/arch/x86_64/mm/srat.c +++ b/arch/x86_64/mm/srat.c | |||
@@ -415,6 +415,12 @@ int __init acpi_scan_nodes(unsigned long start, unsigned long end) | |||
415 | /* Finally register nodes */ | 415 | /* Finally register nodes */ |
416 | for_each_node_mask(i, nodes_parsed) | 416 | for_each_node_mask(i, nodes_parsed) |
417 | setup_node_bootmem(i, nodes[i].start, nodes[i].end); | 417 | setup_node_bootmem(i, nodes[i].start, nodes[i].end); |
418 | /* Try again in case setup_node_bootmem missed one due | ||
419 | to missing bootmem */ | ||
420 | for_each_node_mask(i, nodes_parsed) | ||
421 | if (!node_online(i)) | ||
422 | setup_node_bootmem(i, nodes[i].start, nodes[i].end); | ||
423 | |||
418 | for (i = 0; i < NR_CPUS; i++) { | 424 | for (i = 0; i < NR_CPUS; i++) { |
419 | if (cpu_to_node[i] == NUMA_NO_NODE) | 425 | if (cpu_to_node[i] == NUMA_NO_NODE) |
420 | continue; | 426 | continue; |