Blame view
drivers/acpi/numa.c
8.29 KB
1da177e4c Linux-2.6.12-rc2 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
/* * acpi_numa.c - ACPI NUMA support * * Copyright (C) 2002 Takayoshi Kochi <t-kochi@bq.jp.nec.com> * * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * */ #include <linux/module.h> |
1da177e4c Linux-2.6.12-rc2 |
26 27 28 29 30 |
#include <linux/init.h> #include <linux/kernel.h> #include <linux/types.h> #include <linux/errno.h> #include <linux/acpi.h> |
b552a8c56 ACPI: remove NID_... |
31 |
#include <linux/numa.h> |
1da177e4c Linux-2.6.12-rc2 |
32 |
#include <acpi/acpi_bus.h> |
1da177e4c Linux-2.6.12-rc2 |
33 |
|
a192a9580 ACPI: Move defini... |
34 |
#define PREFIX "ACPI: " |
1da177e4c Linux-2.6.12-rc2 |
35 36 |
#define ACPI_NUMA 0x80000000 #define _COMPONENT ACPI_NUMA |
f52fd66d2 ACPI: clean up AC... |
37 |
ACPI_MODULE_NAME("numa"); |
1da177e4c Linux-2.6.12-rc2 |
38 |
|
762834e8b [PATCH] Unify pxm... |
39 |
static nodemask_t nodes_found_map = NODE_MASK_NONE; |
762834e8b [PATCH] Unify pxm... |
40 41 |
/* maps to convert between proximity domain and logical node ID */ |
ffada8913 ACPI: fix modpost... |
42 |
static int pxm_to_node_map[MAX_PXM_DOMAINS] |
b552a8c56 ACPI: remove NID_... |
43 |
= { [0 ... MAX_PXM_DOMAINS - 1] = NUMA_NO_NODE }; |
ffada8913 ACPI: fix modpost... |
44 |
static int node_to_pxm_map[MAX_NUMNODES] |
b552a8c56 ACPI: remove NID_... |
45 |
= { [0 ... MAX_NUMNODES - 1] = PXM_INVAL }; |
762834e8b [PATCH] Unify pxm... |
46 |
|
f363d16fb acpi: fix potenti... |
47 |
int pxm_to_node(int pxm) |
762834e8b [PATCH] Unify pxm... |
48 49 |
{ if (pxm < 0) |
b552a8c56 ACPI: remove NID_... |
50 |
return NUMA_NO_NODE; |
762834e8b [PATCH] Unify pxm... |
51 52 |
return pxm_to_node_map[pxm]; } |
f363d16fb acpi: fix potenti... |
53 |
int node_to_pxm(int node) |
762834e8b [PATCH] Unify pxm... |
54 55 56 57 58 |
{ if (node < 0) return PXM_INVAL; return node_to_pxm_map[node]; } |
3484d7981 x86_64: fake pxm-... |
59 60 |
void __acpi_map_pxm_to_node(int pxm, int node) { |
0f9b75ef3 ACPI: NUMA: map p... |
61 62 63 64 |
if (pxm_to_node_map[pxm] == NUMA_NO_NODE || node < pxm_to_node_map[pxm]) pxm_to_node_map[pxm] = node; if (node_to_pxm_map[node] == PXM_INVAL || pxm < node_to_pxm_map[node]) node_to_pxm_map[node] = pxm; |
3484d7981 x86_64: fake pxm-... |
65 |
} |
8ff6f48d9 ACPI: Section mis... |
66 |
int acpi_map_pxm_to_node(int pxm) |
762834e8b [PATCH] Unify pxm... |
67 68 |
{ int node = pxm_to_node_map[pxm]; |
b552a8c56 ACPI: remove NID_... |
69 |
if (node < 0) { |
762834e8b [PATCH] Unify pxm... |
70 |
if (nodes_weight(nodes_found_map) >= MAX_NUMNODES) |
b552a8c56 ACPI: remove NID_... |
71 |
return NUMA_NO_NODE; |
762834e8b [PATCH] Unify pxm... |
72 |
node = first_unset_node(nodes_found_map); |
3484d7981 x86_64: fake pxm-... |
73 |
__acpi_map_pxm_to_node(pxm, node); |
762834e8b [PATCH] Unify pxm... |
74 75 76 77 78 |
node_set(node, nodes_found_map); } return node; } |
ae2c6dcf9 x86_64: various c... |
79 80 |
static void __init acpi_table_print_srat_entry(struct acpi_subtable_header *header) |
1da177e4c Linux-2.6.12-rc2 |
81 |
{ |
4be44fcd3 [ACPI] Lindent al... |
82 |
ACPI_FUNCTION_NAME("acpi_table_print_srat_entry"); |
1da177e4c Linux-2.6.12-rc2 |
83 84 85 86 87 |
if (!header) return; switch (header->type) { |
15a58ed12 ACPICA: Remove du... |
88 |
case ACPI_SRAT_TYPE_CPU_AFFINITY: |
1da177e4c Linux-2.6.12-rc2 |
89 |
#ifdef ACPI_DEBUG_OUTPUT |
4be44fcd3 [ACPI] Lindent al... |
90 |
{ |
15a58ed12 ACPICA: Remove du... |
91 92 |
struct acpi_srat_cpu_affinity *p = (struct acpi_srat_cpu_affinity *)header; |
4be44fcd3 [ACPI] Lindent al... |
93 94 95 |
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "SRAT Processor (id[0x%02x] eid[0x%02x]) in proximity domain %d %s ", |
15a58ed12 ACPICA: Remove du... |
96 97 98 99 |
p->apic_id, p->local_sapic_eid, p->proximity_domain_lo, (p->flags & ACPI_SRAT_CPU_ENABLED)? "enabled" : "disabled")); |
4be44fcd3 [ACPI] Lindent al... |
100 101 |
} #endif /* ACPI_DEBUG_OUTPUT */ |
1da177e4c Linux-2.6.12-rc2 |
102 |
break; |
15a58ed12 ACPICA: Remove du... |
103 |
case ACPI_SRAT_TYPE_MEMORY_AFFINITY: |
1da177e4c Linux-2.6.12-rc2 |
104 |
#ifdef ACPI_DEBUG_OUTPUT |
4be44fcd3 [ACPI] Lindent al... |
105 |
{ |
15a58ed12 ACPICA: Remove du... |
106 107 |
struct acpi_srat_mem_affinity *p = (struct acpi_srat_mem_affinity *)header; |
4be44fcd3 [ACPI] Lindent al... |
108 |
ACPI_DEBUG_PRINT((ACPI_DB_INFO, |
19d0cfe9d ACPICA: Update DM... |
109 110 |
"SRAT Memory (0x%lx length 0x%lx) in proximity domain %d %s%s ", |
15a58ed12 ACPICA: Remove du... |
111 112 |
(unsigned long)p->base_address, (unsigned long)p->length, |
19d0cfe9d ACPICA: Update DM... |
113 |
p->proximity_domain, |
15a58ed12 ACPICA: Remove du... |
114 115 116 117 |
(p->flags & ACPI_SRAT_MEM_ENABLED)? "enabled" : "disabled", (p->flags & ACPI_SRAT_MEM_HOT_PLUGGABLE)? " hot-pluggable" : "")); |
4be44fcd3 [ACPI] Lindent al... |
118 119 |
} #endif /* ACPI_DEBUG_OUTPUT */ |
1da177e4c Linux-2.6.12-rc2 |
120 |
break; |
7237d3de7 x86, ACPI: add su... |
121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 |
case ACPI_SRAT_TYPE_X2APIC_CPU_AFFINITY: #ifdef ACPI_DEBUG_OUTPUT { struct acpi_srat_x2apic_cpu_affinity *p = (struct acpi_srat_x2apic_cpu_affinity *)header; ACPI_DEBUG_PRINT((ACPI_DB_INFO, "SRAT Processor (x2apicid[0x%08x]) in" " proximity domain %d %s ", p->apic_id, p->proximity_domain, (p->flags & ACPI_SRAT_CPU_ENABLED) ? "enabled" : "disabled")); } #endif /* ACPI_DEBUG_OUTPUT */ break; |
1da177e4c Linux-2.6.12-rc2 |
137 |
default: |
4be44fcd3 [ACPI] Lindent al... |
138 139 140 141 |
printk(KERN_WARNING PREFIX "Found unsupported SRAT entry (type = 0x%x) ", header->type); |
1da177e4c Linux-2.6.12-rc2 |
142 143 144 |
break; } } |
39b8931b5 ACPI: handle inva... |
145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 |
/* * A lot of BIOS fill in 10 (= no distance) everywhere. This messes * up the NUMA heuristics which wants the local node to have a smaller * distance than the others. * Do some quick checks here and only use the SLIT if it passes. */ static __init int slit_valid(struct acpi_table_slit *slit) { int i, j; int d = slit->locality_count; for (i = 0; i < d; i++) { for (j = 0; j < d; j++) { u8 val = slit->entry[d*i + j]; if (i == j) { if (val != LOCAL_DISTANCE) return 0; } else if (val <= LOCAL_DISTANCE) return 0; } } return 1; } |
15a58ed12 ACPICA: Remove du... |
167 |
static int __init acpi_parse_slit(struct acpi_table_header *table) |
1da177e4c Linux-2.6.12-rc2 |
168 |
{ |
4be44fcd3 [ACPI] Lindent al... |
169 |
struct acpi_table_slit *slit; |
1da177e4c Linux-2.6.12-rc2 |
170 |
|
15a58ed12 ACPICA: Remove du... |
171 |
if (!table) |
1da177e4c Linux-2.6.12-rc2 |
172 |
return -EINVAL; |
15a58ed12 ACPICA: Remove du... |
173 |
slit = (struct acpi_table_slit *)table; |
1da177e4c Linux-2.6.12-rc2 |
174 |
|
39b8931b5 ACPI: handle inva... |
175 176 177 178 179 |
if (!slit_valid(slit)) { printk(KERN_INFO "ACPI: SLIT table looks invalid. Not used. "); return -EINVAL; } |
1da177e4c Linux-2.6.12-rc2 |
180 181 182 183 |
acpi_numa_slit_init(slit); return 0; } |
7237d3de7 x86, ACPI: add su... |
184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 |
void __init __attribute__ ((weak)) acpi_numa_x2apic_affinity_init(struct acpi_srat_x2apic_cpu_affinity *pa) { printk(KERN_WARNING PREFIX "Found unsupported x2apic [0x%08x] SRAT entry ", pa->apic_id); return; } static int __init acpi_parse_x2apic_affinity(struct acpi_subtable_header *header, const unsigned long end) { struct acpi_srat_x2apic_cpu_affinity *processor_affinity; processor_affinity = (struct acpi_srat_x2apic_cpu_affinity *)header; if (!processor_affinity) return -EINVAL; acpi_table_print_srat_entry(header); /* let architecture-dependent part to do it */ acpi_numa_x2apic_affinity_init(processor_affinity); return 0; } |
1da177e4c Linux-2.6.12-rc2 |
211 |
static int __init |
7237d3de7 x86, ACPI: add su... |
212 |
acpi_parse_processor_affinity(struct acpi_subtable_header *header, |
4be44fcd3 [ACPI] Lindent al... |
213 |
const unsigned long end) |
1da177e4c Linux-2.6.12-rc2 |
214 |
{ |
15a58ed12 ACPICA: Remove du... |
215 |
struct acpi_srat_cpu_affinity *processor_affinity; |
1da177e4c Linux-2.6.12-rc2 |
216 |
|
15a58ed12 ACPICA: Remove du... |
217 |
processor_affinity = (struct acpi_srat_cpu_affinity *)header; |
1da177e4c Linux-2.6.12-rc2 |
218 219 220 221 222 223 224 225 226 227 |
if (!processor_affinity) return -EINVAL; acpi_table_print_srat_entry(header); /* let architecture-dependent part to do it */ acpi_numa_processor_affinity_init(processor_affinity); return 0; } |
1da177e4c Linux-2.6.12-rc2 |
228 |
static int __init |
15a58ed12 ACPICA: Remove du... |
229 |
acpi_parse_memory_affinity(struct acpi_subtable_header * header, |
4be44fcd3 [ACPI] Lindent al... |
230 |
const unsigned long end) |
1da177e4c Linux-2.6.12-rc2 |
231 |
{ |
15a58ed12 ACPICA: Remove du... |
232 |
struct acpi_srat_mem_affinity *memory_affinity; |
1da177e4c Linux-2.6.12-rc2 |
233 |
|
15a58ed12 ACPICA: Remove du... |
234 |
memory_affinity = (struct acpi_srat_mem_affinity *)header; |
1da177e4c Linux-2.6.12-rc2 |
235 236 237 238 239 240 241 242 243 244 |
if (!memory_affinity) return -EINVAL; acpi_table_print_srat_entry(header); /* let architecture-dependent part to do it */ acpi_numa_memory_affinity_init(memory_affinity); return 0; } |
15a58ed12 ACPICA: Remove du... |
245 |
static int __init acpi_parse_srat(struct acpi_table_header *table) |
1da177e4c Linux-2.6.12-rc2 |
246 |
{ |
15a58ed12 ACPICA: Remove du... |
247 |
if (!table) |
1da177e4c Linux-2.6.12-rc2 |
248 |
return -EINVAL; |
cfa806f05 gcc-4.6: ACPI: fi... |
249 |
/* Real work done in acpi_table_parse_srat below. */ |
1da177e4c Linux-2.6.12-rc2 |
250 251 252 |
return 0; } |
ae2c6dcf9 x86_64: various c... |
253 |
static int __init |
15a58ed12 ACPICA: Remove du... |
254 |
acpi_table_parse_srat(enum acpi_srat_type id, |
5a8765a84 ACPI: acpi_madt_e... |
255 |
acpi_table_entry_handler handler, unsigned int max_entries) |
1da177e4c Linux-2.6.12-rc2 |
256 |
{ |
6eb87fed5 ACPI: acpi_table_... |
257 |
return acpi_table_parse_entries(ACPI_SIG_SRAT, |
4be44fcd3 [ACPI] Lindent al... |
258 259 |
sizeof(struct acpi_table_srat), id, handler, max_entries); |
1da177e4c Linux-2.6.12-rc2 |
260 |
} |
4be44fcd3 [ACPI] Lindent al... |
261 |
int __init acpi_numa_init(void) |
1da177e4c Linux-2.6.12-rc2 |
262 |
{ |
940fed2e7 x86-64, NUMA: Uni... |
263 |
int cnt = 0; |
d3bd05882 x86, acpi: Parse ... |
264 |
|
d3bd05882 x86, acpi: Parse ... |
265 266 267 268 269 |
/* * Should not limit number with cpu num that is from NR_CPUS or nr_cpus= * SRAT cpu entries could have different order with that in MADT. * So go over all cpu entries in SRAT to get apicid to node mapping. */ |
8716273ca x86: Export srat ... |
270 |
|
1da177e4c Linux-2.6.12-rc2 |
271 |
/* SRAT: Static Resource Affinity Table */ |
7f8f97c3c ACPI: acpi_table_... |
272 |
if (!acpi_table_parse(ACPI_SIG_SRAT, acpi_parse_srat)) { |
7237d3de7 x86, ACPI: add su... |
273 |
acpi_table_parse_srat(ACPI_SRAT_TYPE_X2APIC_CPU_AFFINITY, |
9378b63cc x86, ia64, acpi: ... |
274 |
acpi_parse_x2apic_affinity, 0); |
ae2c6dcf9 x86_64: various c... |
275 |
acpi_table_parse_srat(ACPI_SRAT_TYPE_CPU_AFFINITY, |
9378b63cc x86, ia64, acpi: ... |
276 |
acpi_parse_processor_affinity, 0); |
940fed2e7 x86-64, NUMA: Uni... |
277 |
cnt = acpi_table_parse_srat(ACPI_SRAT_TYPE_MEMORY_AFFINITY, |
8716273ca x86: Export srat ... |
278 279 |
acpi_parse_memory_affinity, NR_NODE_MEMBLKS); |
1da177e4c Linux-2.6.12-rc2 |
280 281 282 |
} /* SLIT: System Locality Information Table */ |
7f8f97c3c ACPI: acpi_table_... |
283 |
acpi_table_parse(ACPI_SIG_SLIT, acpi_parse_slit); |
1da177e4c Linux-2.6.12-rc2 |
284 285 |
acpi_numa_arch_fixup(); |
940fed2e7 x86-64, NUMA: Uni... |
286 287 288 289 |
if (cnt <= 0) return cnt ?: -ENOENT; return 0; |
1da177e4c Linux-2.6.12-rc2 |
290 |
} |
7e81ab9d3 Fix unnecesary me... |
291 |
int acpi_get_pxm(acpi_handle h) |
1da177e4c Linux-2.6.12-rc2 |
292 |
{ |
27663c585 ACPI: Change acpi... |
293 |
unsigned long long pxm; |
1da177e4c Linux-2.6.12-rc2 |
294 295 296 297 298 299 300 301 |
acpi_status status; acpi_handle handle; acpi_handle phandle = h; do { handle = phandle; status = acpi_evaluate_integer(handle, "_PXM", NULL, &pxm); if (ACPI_SUCCESS(status)) |
50dd09697 ACPI: Remove unne... |
302 |
return pxm; |
1da177e4c Linux-2.6.12-rc2 |
303 |
status = acpi_get_parent(handle, &phandle); |
4be44fcd3 [ACPI] Lindent al... |
304 |
} while (ACPI_SUCCESS(status)); |
1da177e4c Linux-2.6.12-rc2 |
305 306 |
return -1; } |
1e3590e2e [PATCH] pgdat all... |
307 |
|
7e81ab9d3 Fix unnecesary me... |
308 |
int acpi_get_node(acpi_handle *handle) |
1e3590e2e [PATCH] pgdat all... |
309 310 |
{ int pxm, node = -1; |
1e3590e2e [PATCH] pgdat all... |
311 |
pxm = acpi_get_pxm(handle); |
27ce34198 acpi: check for p... |
312 |
if (pxm >= 0 && pxm < MAX_PXM_DOMAINS) |
1e3590e2e [PATCH] pgdat all... |
313 |
node = acpi_map_pxm_to_node(pxm); |
635227ee8 ACPI: remove func... |
314 |
return node; |
1e3590e2e [PATCH] pgdat all... |
315 316 |
} EXPORT_SYMBOL(acpi_get_node); |