aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/cpu/amd.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/kernel/cpu/amd.c')
-rw-r--r--arch/x86/kernel/cpu/amd.c51
1 files changed, 32 insertions, 19 deletions
diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c
index 58f1b012e1c..3ecece0217e 100644
--- a/arch/x86/kernel/cpu/amd.c
+++ b/arch/x86/kernel/cpu/amd.c
@@ -233,18 +233,22 @@ static void __cpuinit init_amd_k7(struct cpuinfo_x86 *c)
233} 233}
234#endif 234#endif
235 235
236#if defined(CONFIG_NUMA) && defined(CONFIG_X86_64) 236#ifdef CONFIG_NUMA
237/*
238 * To workaround broken NUMA config. Read the comment in
239 * srat_detect_node().
240 */
237static int __cpuinit nearby_node(int apicid) 241static int __cpuinit nearby_node(int apicid)
238{ 242{
239 int i, node; 243 int i, node;
240 244
241 for (i = apicid - 1; i >= 0; i--) { 245 for (i = apicid - 1; i >= 0; i--) {
242 node = apicid_to_node[i]; 246 node = __apicid_to_node[i];
243 if (node != NUMA_NO_NODE && node_online(node)) 247 if (node != NUMA_NO_NODE && node_online(node))
244 return node; 248 return node;
245 } 249 }
246 for (i = apicid + 1; i < MAX_LOCAL_APIC; i++) { 250 for (i = apicid + 1; i < MAX_LOCAL_APIC; i++) {
247 node = apicid_to_node[i]; 251 node = __apicid_to_node[i];
248 if (node != NUMA_NO_NODE && node_online(node)) 252 if (node != NUMA_NO_NODE && node_online(node))
249 return node; 253 return node;
250 } 254 }
@@ -338,31 +342,40 @@ EXPORT_SYMBOL_GPL(amd_get_nb_id);
338 342
339static void __cpuinit srat_detect_node(struct cpuinfo_x86 *c) 343static void __cpuinit srat_detect_node(struct cpuinfo_x86 *c)
340{ 344{
341#if defined(CONFIG_NUMA) && defined(CONFIG_X86_64) 345#ifdef CONFIG_NUMA
342 int cpu = smp_processor_id(); 346 int cpu = smp_processor_id();
343 int node; 347 int node;
344 unsigned apicid = c->apicid; 348 unsigned apicid = c->apicid;
345 349
346 node = per_cpu(cpu_llc_id, cpu); 350 node = numa_cpu_node(cpu);
351 if (node == NUMA_NO_NODE)
352 node = per_cpu(cpu_llc_id, cpu);
347 353
348 if (apicid_to_node[apicid] != NUMA_NO_NODE)
349 node = apicid_to_node[apicid];
350 if (!node_online(node)) { 354 if (!node_online(node)) {
351 /* Two possibilities here: 355 /*
352 - The CPU is missing memory and no node was created. 356 * Two possibilities here:
353 In that case try picking one from a nearby CPU 357 *
354 - The APIC IDs differ from the HyperTransport node IDs 358 * - The CPU is missing memory and no node was created. In
355 which the K8 northbridge parsing fills in. 359 * that case try picking one from a nearby CPU.
356 Assume they are all increased by a constant offset, 360 *
357 but in the same order as the HT nodeids. 361 * - The APIC IDs differ from the HyperTransport node IDs
358 If that doesn't result in a usable node fall back to the 362 * which the K8 northbridge parsing fills in. Assume
359 path for the previous case. */ 363 * they are all increased by a constant offset, but in
360 364 * the same order as the HT nodeids. If that doesn't
365 * result in a usable node fall back to the path for the
366 * previous case.
367 *
368 * This workaround operates directly on the mapping between
369 * APIC ID and NUMA node, assuming certain relationship
370 * between APIC ID, HT node ID and NUMA topology. As going
371 * through CPU mapping may alter the outcome, directly
372 * access __apicid_to_node[].
373 */
361 int ht_nodeid = c->initial_apicid; 374 int ht_nodeid = c->initial_apicid;
362 375
363 if (ht_nodeid >= 0 && 376 if (ht_nodeid >= 0 &&
364 apicid_to_node[ht_nodeid] != NUMA_NO_NODE) 377 __apicid_to_node[ht_nodeid] != NUMA_NO_NODE)
365 node = apicid_to_node[ht_nodeid]; 378 node = __apicid_to_node[ht_nodeid];
366 /* Pick a nearby node */ 379 /* Pick a nearby node */
367 if (!node_online(node)) 380 if (!node_online(node))
368 node = nearby_node(apicid); 381 node = nearby_node(apicid);