[PATCH] x86-64: Support dualcore and 8 socket systems in k8 fallback node parsing
[pandora-kernel.git] / arch / x86_64 / kernel / setup.c
index 0aa5262..df55a63 100644 (file)
  * Machine setup..
  */
 
-struct cpuinfo_x86 boot_cpu_data;
+struct cpuinfo_x86 boot_cpu_data __read_mostly;
 
 unsigned long mmu_cr4_features;
 
 int acpi_disabled;
 EXPORT_SYMBOL(acpi_disabled);
-#ifdef CONFIG_ACPI_BOOT
+#ifdef CONFIG_ACPI
 extern int __initdata acpi_ht;
 extern acpi_interrupt_flags    acpi_sci_flags;
 int __initdata acpi_force = 0;
@@ -294,7 +294,7 @@ static __init void parse_cmdline_early (char ** cmdline_p)
                        maxcpus = simple_strtoul(from + 8, NULL, 0);
                }
 #endif
-#ifdef CONFIG_ACPI_BOOT
+#ifdef CONFIG_ACPI
                /* "acpi=off" disables both ACPI table parsing and interpreter init */
                if (!memcmp(from, "acpi=off", 8))
                        disable_acpi();
@@ -566,7 +566,7 @@ void __init setup_arch(char **cmdline_p)
 
        init_memory_mapping(0, (end_pfn_map << PAGE_SHIFT));
 
-#ifdef CONFIG_ACPI_BOOT
+#ifdef CONFIG_ACPI
        /*
         * Initialize the ACPI boot-time table parser (gets the RSDP and SDT).
         * Call this early for SRAT node setup.
@@ -645,20 +645,20 @@ void __init setup_arch(char **cmdline_p)
                }
        }
 #endif
-
-       sparse_init();
-
 #ifdef CONFIG_KEXEC
        if (crashk_res.start != crashk_res.end) {
                reserve_bootmem(crashk_res.start,
                        crashk_res.end - crashk_res.start + 1);
        }
 #endif
+
+       sparse_init();
+
        paging_init();
 
        check_ioapic();
 
-#ifdef CONFIG_ACPI_BOOT
+#ifdef CONFIG_ACPI
        /*
         * Read APIC and some other early information from ACPI tables.
         */
@@ -755,6 +755,24 @@ static void __cpuinit display_cacheinfo(struct cpuinfo_x86 *c)
        }
 }
 
+#ifdef CONFIG_NUMA
+static int nearby_node(int apicid)
+{
+       int i;
+       for (i = apicid - 1; i >= 0; i--) {
+               int node = apicid_to_node[i];
+               if (node != NUMA_NO_NODE && node_online(node))
+                       return node;
+       }
+       for (i = apicid + 1; i < MAX_LOCAL_APIC; i++) {
+               int node = apicid_to_node[i];
+               if (node != NUMA_NO_NODE && node_online(node))
+                       return node;
+       }
+       return first_node(node_online_map); /* Shouldn't happen */
+}
+#endif
+
 /*
  * On a AMD dual core setup the lower bits of the APIC id distingush the cores.
  * Assumes number of cores is a power of two.
@@ -763,8 +781,11 @@ static void __init amd_detect_cmp(struct cpuinfo_x86 *c)
 {
 #ifdef CONFIG_SMP
        int cpu = smp_processor_id();
-       int node = 0;
        unsigned bits;
+#ifdef CONFIG_NUMA
+       int node = 0;
+       unsigned apicid = phys_proc_id[cpu];
+#endif
 
        bits = 0;
        while ((1 << bits) < c->x86_num_cores)
@@ -776,20 +797,32 @@ static void __init amd_detect_cmp(struct cpuinfo_x86 *c)
        phys_proc_id[cpu] >>= bits;
 
 #ifdef CONFIG_NUMA
-       /* When an ACPI SRAT table is available use the mappings from SRAT
-          instead. */
-       if (acpi_numa <= 0) {
-               node = phys_proc_id[cpu];
-               if (!node_online(node))
-                       node = first_node(node_online_map);
-               cpu_to_node[cpu] = node;
-       } else {
-               node = cpu_to_node[cpu];
-       }
+       node = phys_proc_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.  */
+               int ht_nodeid = apicid - (phys_proc_id[0] << bits);
+               if (ht_nodeid >= 0 &&
+                   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);
+       }
+       cpu_to_node[cpu] = node;
+
+       printk(KERN_INFO "CPU %d(%d) -> Node %d -> Core %d\n",
+                       cpu, c->x86_num_cores, node, cpu_core_id[cpu]);
 #endif
-
-       printk(KERN_INFO "CPU %d(%d) -> Node %d -> Core %d\n",
-                       cpu, c->x86_num_cores, node, cpu_core_id[cpu]);
 #endif
 }
 
@@ -929,7 +962,7 @@ static void __cpuinit init_intel(struct cpuinfo_x86 *c)
        c->x86_num_cores = intel_num_cpu_cores(c);
 }
 
-void __cpuinit get_cpu_vendor(struct cpuinfo_x86 *c)
+static void __cpuinit get_cpu_vendor(struct cpuinfo_x86 *c)
 {
        char *v = c->x86_vendor_id;