[PATCH] convert i386 Summit subarch to use SRAT info for apicid_to_node calls
authorkeith mannthey <kmannth@us.ibm.com>
Fri, 29 Sep 2006 08:58:46 +0000 (01:58 -0700)
committerLinus Torvalds <torvalds@g5.osdl.org>
Fri, 29 Sep 2006 16:18:03 +0000 (09:18 -0700)
Convert the i386 summit subarch apicid_to_node to use node information
provided by the SRAT.  It was discussed a little on LKML a few weeks ago
and was seen as an acceptable fix.  The current way of obtaining the nodeid

 static inline int apicid_to_node(int logical_apicid)
 {
   return logical_apicid >> 5;
 }

is just not correct for all summit systems/bios.  Assuming the apicid
matches the Linux node number require a leap of faith that the bios mapped
out the apicids a set way.  Modern summit HW (IBM x460) does not layout its
bios in the manner for various reasons and is unable to boot i386 numa.

The best way to get the correct apicid to node information is from the SRAT
table during boot.  It lays out what apicid belongs to what node.  I use
this information to create a table for use at run time.

Signed-off-by: Keith Mannthey <kmannth@us.ibm.com>
Cc: Andi Kleen <ak@suse.de>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
arch/i386/kernel/smpboot.c
arch/i386/kernel/srat.c
include/asm-i386/mach-summit/mach_apic.h
include/asm-i386/smp.h

index 020d873b7d2130584e84906186703c8cd6079498..82b26d5ce476554bd3eb6158cda3d664a6974224 100644 (file)
@@ -102,6 +102,8 @@ u8 x86_cpu_to_apicid[NR_CPUS] __read_mostly =
                        { [0 ... NR_CPUS-1] = 0xff };
 EXPORT_SYMBOL(x86_cpu_to_apicid);
 
+u8 apicid_2_node[MAX_APICID];
+
 /*
  * Trampoline 80x86 program as an array.
  */
@@ -645,7 +647,7 @@ static void map_cpu_to_logical_apicid(void)
 {
        int cpu = smp_processor_id();
        int apicid = logical_smp_processor_id();
-       int node = apicid_to_node(apicid);
+       int node = apicid_to_node(hard_smp_processor_id());
 
        if (!node_online(node))
                node = first_online_node;
@@ -954,6 +956,7 @@ static int __devinit do_boot_cpu(int apicid, int cpu)
 
        irq_ctx_init(cpu);
 
+       x86_cpu_to_apicid[cpu] = apicid;
        /*
         * This grunge runs the startup process for
         * the targeted processor.
index 32413122c4c2650f1114db0f10bb1d8e12c116b8..f7e735c077c35df71c4ae0c2262113f3ea7a92e4 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/nodemask.h>
 #include <asm/srat.h>
 #include <asm/topology.h>
+#include <asm/smp.h>
 
 /*
  * proximity macros and definitions
@@ -54,6 +55,7 @@ struct node_memory_chunk_s {
 static struct node_memory_chunk_s node_memory_chunk[MAXCHUNKS];
 
 static int num_memory_chunks;          /* total number of memory chunks */
+static u8 __initdata apicid_to_pxm[MAX_APICID];
 
 extern void * boot_ioremap(unsigned long, unsigned long);
 
@@ -69,6 +71,8 @@ static void __init parse_cpu_affinity_structure(char *p)
        /* mark this node as "seen" in node bitmap */
        BMAP_SET(pxm_bitmap, cpu_affinity->proximity_domain);
 
+       apicid_to_pxm[cpu_affinity->apic_id] = cpu_affinity->proximity_domain;
+
        printk("CPU 0x%02X in proximity domain 0x%02X\n",
                cpu_affinity->apic_id, cpu_affinity->proximity_domain);
 }
@@ -235,6 +239,9 @@ static int __init acpi20_parse_srat(struct acpi_table_srat *sratp)
        printk("Number of logical nodes in system = %d\n", num_online_nodes());
        printk("Number of memory chunks in system = %d\n", num_memory_chunks);
 
+       for (i = 0; i < MAX_APICID; i++)
+               apicid_2_node[i] = pxm_to_node(apicid_to_pxm[i]);
+
        for (j = 0; j < num_memory_chunks; j++){
                struct node_memory_chunk_s * chunk = &node_memory_chunk[j];
                printk("chunk %d nid %d start_pfn %08lx end_pfn %08lx\n",
index a81b0596159508618a3e2b2bfc11ea5b9d62fe47..254a0fe01c6a3f46b5983afc9336b11a61a3d81d 100644 (file)
@@ -88,7 +88,7 @@ static inline void clustered_apic_check(void)
 
 static inline int apicid_to_node(int logical_apicid)
 {
-       return logical_apicid >> 5;          /* 2 clusterids per CEC */
+       return apicid_2_node[logical_apicid];
 }
 
 /* Mapping from cpu number to logical apicid */
index 32ac8c91d5c5ccb2e8856ee2a6943d59609d090e..915c26a31b79a6f0a855ae06920810761978abe8 100644 (file)
@@ -46,6 +46,8 @@ extern u8 x86_cpu_to_apicid[];
 
 #define cpu_physical_id(cpu)   x86_cpu_to_apicid[cpu]
 
+extern u8 apicid_2_node[];
+
 #ifdef CONFIG_HOTPLUG_CPU
 extern void cpu_exit_clear(void);
 extern void cpu_uninit(void);