Fedora kernel-2.6.17-1.2142_FC4 patched with stable patch-2.6.17.4-vs2.0.2-rc26.diff
[linux-2.6.git] / arch / i386 / kernel / srat.c
index 8c0bd56..52b3ed5 100644 (file)
@@ -28,7 +28,9 @@
 #include <linux/bootmem.h>
 #include <linux/mmzone.h>
 #include <linux/acpi.h>
+#include <linux/nodemask.h>
 #include <asm/srat.h>
+#include <asm/topology.h>
 
 /*
  * proximity macros and definitions
@@ -57,8 +59,6 @@ static int num_memory_chunks;         /* total number of memory chunks */
 static int zholes_size_init;
 static unsigned long zholes_size[MAX_NUMNODES * MAX_NR_ZONES];
 
-extern unsigned long node_start_pfn[], node_end_pfn[];
-
 extern void * boot_ioremap(unsigned long, unsigned long);
 
 /* Identify CPU proximity domains */
@@ -137,8 +137,8 @@ static void __init parse_memory_affinity_structure (char *sratp)
                 "enabled and removable" : "enabled" ) );
 }
 
-#if MAX_NR_ZONES != 3
-#error "MAX_NR_ZONES != 3, chunk_to_zone requires review"
+#if MAX_NR_ZONES != 4
+#error "MAX_NR_ZONES != 4, chunk_to_zone requires review"
 #endif
 /* Take a chunk of pages from page frame cstart to cend and count the number
  * of pages in each zone, returned via zones[].
@@ -181,21 +181,43 @@ static __init void chunk_to_zones(unsigned long cstart, unsigned long cend,
        }
 }
 
-static void __init initialize_physnode_map(void)
+/*
+ * The SRAT table always lists ascending addresses, so can always
+ * assume that the first "start" address that you see is the real
+ * start of the node, and that the current "end" address is after
+ * the previous one.
+ */
+static __init void node_read_chunk(int nid, struct node_memory_chunk_s *memory_chunk)
 {
-       int i;
-       unsigned long pfn;
-       struct node_memory_chunk_s *nmcp;
-
-       /* Run the list of memory chunks and fill in the phymap. */
-       nmcp = node_memory_chunk;
-       for (i = num_memory_chunks; --i >= 0; nmcp++) {
-               for (pfn = nmcp->start_pfn; pfn <= nmcp->end_pfn;
-                                               pfn += PAGES_PER_ELEMENT)
-               {
-                       physnode_map[pfn / PAGES_PER_ELEMENT] = (int)nmcp->nid;
-               }
+       /*
+        * Only add present memory as told by the e820.
+        * There is no guarantee from the SRAT that the memory it
+        * enumerates is present at boot time because it represents
+        * *possible* memory hotplug areas the same as normal RAM.
+        */
+       if (memory_chunk->start_pfn >= max_pfn) {
+               printk (KERN_INFO "Ignoring SRAT pfns: 0x%08lx -> %08lx\n",
+                       memory_chunk->start_pfn, memory_chunk->end_pfn);
+               return;
        }
+       if (memory_chunk->nid != nid)
+               return;
+
+       if (!node_has_online_mem(nid))
+               node_start_pfn[nid] = memory_chunk->start_pfn;
+
+       if (node_start_pfn[nid] > memory_chunk->start_pfn)
+               node_start_pfn[nid] = memory_chunk->start_pfn;
+
+       if (node_end_pfn[nid] < memory_chunk->end_pfn)
+               node_end_pfn[nid] = memory_chunk->end_pfn;
+}
+
+static u8 pxm_to_nid_map[MAX_PXM_DOMAINS];/* _PXM to logical node ID map */
+
+int pxm_to_node(int pxm)
+{
+       return pxm_to_nid_map[pxm];
 }
 
 /* Parse the ACPI Static Resource Affinity Table */
@@ -203,7 +225,6 @@ static int __init acpi20_parse_srat(struct acpi_table_srat *sratp)
 {
        u8 *start, *end, *p;
        int i, j, nid;
-       u8 pxm_to_nid_map[MAX_PXM_DOMAINS];/* _PXM to logical node ID map */
        u8 nid_to_pxm_map[MAX_NUMNODES];/* logical node ID to _PXM map */
 
        start = (u8 *)(&(sratp->reserved) + 1); /* skip header */
@@ -248,57 +269,48 @@ static int __init acpi20_parse_srat(struct acpi_table_srat *sratp)
         * a set of sequential node IDs starting at zero.  (ACPI doesn't seem
         * to specify the range of _PXM values.)
         */
-       numnodes = 0;           /* init total nodes in system */
+       /*
+        * MCD - we no longer HAVE to number nodes sequentially.  PXM domain
+        * numbers could go as high as 256, and MAX_NUMNODES for i386 is typically
+        * 32, so we will continue numbering them in this manner until MAX_NUMNODES
+        * approaches MAX_PXM_DOMAINS for i386.
+        */
+       nodes_clear(node_online_map);
        for (i = 0; i < MAX_PXM_DOMAINS; i++) {
                if (BMAP_TEST(pxm_bitmap, i)) {
-                       pxm_to_nid_map[i] = numnodes;
-                       nid_to_pxm_map[numnodes] = i;
-                       node_set_online(numnodes);
-                       ++numnodes;
+                       nid = num_online_nodes();
+                       pxm_to_nid_map[i] = nid;
+                       nid_to_pxm_map[nid] = i;
+                       node_set_online(nid);
                }
        }
-
-       if (numnodes == 0)
-               BUG();
+       BUG_ON(num_online_nodes() == 0);
 
        /* set cnode id in memory chunk structure */
        for (i = 0; i < num_memory_chunks; i++)
                node_memory_chunk[i].nid = pxm_to_nid_map[node_memory_chunk[i].pxm];
 
-       initialize_physnode_map();
-       
        printk("pxm bitmap: ");
        for (i = 0; i < sizeof(pxm_bitmap); i++) {
                printk("%02X ", pxm_bitmap[i]);
        }
        printk("\n");
-       printk("Number of logical nodes in system = %d\n", numnodes);
+       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 (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",
-                      j, node_memory_chunk[j].nid,
-                      node_memory_chunk[j].start_pfn,
-                      node_memory_chunk[j].end_pfn);
+                      j, chunk->nid, chunk->start_pfn, chunk->end_pfn);
+               node_read_chunk(chunk->nid, chunk);
        }
  
-       /*calculate node_start_pfn/node_end_pfn arrays*/
-       for (nid = 0; nid < numnodes; nid++) {
-               int been_here_before = 0;
-
-               for (j = 0; j < num_memory_chunks; j++){
-                       if (node_memory_chunk[j].nid == nid) {
-                               if (been_here_before == 0) {
-                                       node_start_pfn[nid] = node_memory_chunk[j].start_pfn;
-                                       node_end_pfn[nid] = node_memory_chunk[j].end_pfn;
-                                       been_here_before = 1;
-                               } else { /* We've found another chunk of memory for the node */
-                                       if (node_start_pfn[nid] < node_memory_chunk[j].start_pfn) {
-                                               node_end_pfn[nid] = node_memory_chunk[j].end_pfn;
-                                       }
-                               }
-                       }
-               }
+       for_each_online_node(nid) {
+               unsigned long start = node_start_pfn[nid];
+               unsigned long end = node_end_pfn[nid];
+
+               memory_present(nid, start, end);
+               node_remap_size[nid] = node_memmap_size_bytes(nid, start, end);
        }
        return 1;
 out_fail:
@@ -315,7 +327,12 @@ int __init get_memcfg_from_srat(void)
        int tables = 0;
        int i = 0;
 
-       acpi_find_root_pointer(ACPI_PHYSICAL_ADDRESSING, rsdp_address);
+       if (ACPI_FAILURE(acpi_find_root_pointer(ACPI_PHYSICAL_ADDRESSING,
+                                               rsdp_address))) {
+               printk("%s: System description tables not found\n",
+                      __FUNCTION__);
+               goto out_err;
+       }
 
        if (rsdp_address->pointer_type == ACPI_PHYSICAL_POINTER) {
                printk("%s: assigning address to rsdp\n", __FUNCTION__);
@@ -415,7 +432,7 @@ static void __init get_zholes_init(void)
        int first;
        unsigned long end = 0;
 
-       for (nid = 0; nid < numnodes; nid++) {
+       for_each_online_node(nid) {
                first = 1;
                for (c = 0; c < num_memory_chunks; c++){
                        if (node_memory_chunk[c].nid == nid) {
@@ -443,8 +460,8 @@ unsigned long * __init get_zholes_size(int nid)
                zholes_size_init++;
                get_zholes_init();
        }
-       if((nid >= numnodes) | (nid >= MAX_NUMNODES))
-               printk("%s: nid = %d is invalid. numnodes = %d",
-                      __FUNCTION__, nid, numnodes);
+       if (nid >= MAX_NUMNODES || !node_online(nid))
+               printk("%s: nid = %d is invalid/offline. num_online_nodes = %d",
+                      __FUNCTION__, nid, num_online_nodes());
        return &zholes_size[nid * MAX_NR_ZONES];
 }