|
@@ -234,17 +234,21 @@ static void __cpuinit init_amd_k7(struct cpuinfo_x86 *c)
|
|
|
#endif
|
|
|
|
|
|
#if defined(CONFIG_NUMA) && defined(CONFIG_X86_64)
|
|
|
+/*
|
|
|
+ * To workaround broken NUMA config. Read the comment in
|
|
|
+ * srat_detect_node().
|
|
|
+ */
|
|
|
static int __cpuinit nearby_node(int apicid)
|
|
|
{
|
|
|
int i, node;
|
|
|
|
|
|
for (i = apicid - 1; i >= 0; i--) {
|
|
|
- node = apicid_to_node[i];
|
|
|
+ node = __apicid_to_node[i];
|
|
|
if (node != NUMA_NO_NODE && node_online(node))
|
|
|
return node;
|
|
|
}
|
|
|
for (i = apicid + 1; i < MAX_LOCAL_APIC; i++) {
|
|
|
- node = apicid_to_node[i];
|
|
|
+ node = __apicid_to_node[i];
|
|
|
if (node != NUMA_NO_NODE && node_online(node))
|
|
|
return node;
|
|
|
}
|
|
@@ -339,26 +343,35 @@ static void __cpuinit srat_detect_node(struct cpuinfo_x86 *c)
|
|
|
int node;
|
|
|
unsigned apicid = c->apicid;
|
|
|
|
|
|
- node = per_cpu(cpu_llc_id, cpu);
|
|
|
+ node = numa_cpu_node(cpu);
|
|
|
+ if (node == NUMA_NO_NODE)
|
|
|
+ node = per_cpu(cpu_llc_id, cpu);
|
|
|
|
|
|
- if (apicid_to_node[apicid] != NUMA_NO_NODE)
|
|
|
- node = apicid_to_node[apicid];
|
|
|
if (!node_online(node)) {
|
|
|
- /* Two possibilities here:
|
|
|
- - The CPU is missing memory and no node was created.
|
|
|
- In that case try picking one from a nearby CPU
|
|
|
- - The APIC IDs differ from the HyperTransport node IDs
|
|
|
- which the K8 northbridge parsing fills in.
|
|
|
- Assume they are all increased by a constant offset,
|
|
|
- but in the same order as the HT nodeids.
|
|
|
- If that doesn't result in a usable node fall back to the
|
|
|
- path for the previous case. */
|
|
|
-
|
|
|
+ /*
|
|
|
+ * Two possibilities here:
|
|
|
+ *
|
|
|
+ * - The CPU is missing memory and no node was created. In
|
|
|
+ * that case try picking one from a nearby CPU.
|
|
|
+ *
|
|
|
+ * - The APIC IDs differ from the HyperTransport node IDs
|
|
|
+ * which the K8 northbridge parsing fills in. Assume
|
|
|
+ * they are all increased by a constant offset, but in
|
|
|
+ * the same order as the HT nodeids. If that doesn't
|
|
|
+ * result in a usable node fall back to the path for the
|
|
|
+ * previous case.
|
|
|
+ *
|
|
|
+ * This workaround operates directly on the mapping between
|
|
|
+ * APIC ID and NUMA node, assuming certain relationship
|
|
|
+ * between APIC ID, HT node ID and NUMA topology. As going
|
|
|
+ * through CPU mapping may alter the outcome, directly
|
|
|
+ * access __apicid_to_node[].
|
|
|
+ */
|
|
|
int ht_nodeid = c->initial_apicid;
|
|
|
|
|
|
if (ht_nodeid >= 0 &&
|
|
|
- apicid_to_node[ht_nodeid] != NUMA_NO_NODE)
|
|
|
- node = apicid_to_node[ht_nodeid];
|
|
|
+ __apicid_to_node[ht_nodeid] != NUMA_NO_NODE)
|
|
|
+ node = __apicid_to_node[ht_nodeid];
|
|
|
/* Pick a nearby node */
|
|
|
if (!node_online(node))
|
|
|
node = nearby_node(apicid);
|