#define MAX_PHYS_MEMORY                (1UL << IA64_MAX_PHYS_BITS)     /* Max physical address supported */
 
-lboard_t *root_lboard[MAX_COMPACT_NODES];
-
 extern void bte_init_node(nodepda_t *, cnodeid_t);
 
 extern void sn_timer_init(void);
 EXPORT_SYMBOL(sn_region_size);
 int sn_prom_type;      /* 0=hardware, 1=medusa/realprom, 2=medusa/fakeprom */
 
-short physical_node_map[MAX_PHYSNODE_ID];
+short physical_node_map[MAX_NUMALINK_NODES];
 static unsigned long sn_prom_features[MAX_PROM_FEATURE_SETS];
 
 EXPORT_SYMBOL(physical_node_map);
 
-int numionodes;
+int num_cnodes;
 
 static void sn_init_pdas(char **);
-static void scan_for_ionodes(void);
+static void build_cnode_tables(void);
 
 static nodepda_t *nodepdaindr[MAX_COMPACT_NODES];
 
 char drive_info[4 * 16];
 #endif
 
-/*
- * Get nasid of current cpu early in boot before nodepda is initialized
- */
-static int
-boot_get_nasid(void)
-{
-       int nasid;
-
-       if (ia64_sn_get_sapic_info(get_sapicid(), &nasid, NULL, NULL))
-               BUG();
-       return nasid;
-}
-
 /*
  * This routine can only be used during init, since
  * smp_boot_data is an init data structure.
 }
 
 extern int platform_intr_list[];
-extern nasid_t master_nasid;
 static int __initdata shub_1_1_found = 0;
 
 /*
 void __init sn_setup(char **cmdline_p)
 {
        long status, ticks_per_sec, drift;
-       int pxm;
        u32 version = sn_sal_rev();
        extern void sn_cpu_init(void);
 
 
        MAX_DMA_ADDRESS = PAGE_OFFSET + MAX_PHYS_MEMORY;
 
-       memset(physical_node_map, -1, sizeof(physical_node_map));
-       for (pxm = 0; pxm < MAX_PXM_DOMAINS; pxm++)
-               if (pxm_to_nid_map[pxm] != -1)
-                       physical_node_map[pxm_to_nasid(pxm)] =
-                           pxm_to_nid_map[pxm];
+       /*
+        * Build the tables for managing cnodes.
+        */
+       build_cnode_tables();
 
        /*
         * Old PROMs do not provide an ACPI FADT. Disable legacy keyboard
 
        printk("SGI SAL version %x.%02x\n", version >> 8, version & 0x00FF);
 
-       master_nasid = boot_get_nasid();
-
        status =
            ia64_sal_freq_base(SAL_FREQ_BASE_REALTIME_CLOCK, &ticks_per_sec,
                               &drift);
 {
        cnodeid_t cnode;
 
-       memset(sn_cnodeid_to_nasid, -1,
-                       sizeof(__ia64_per_cpu_var(__sn_cnodeid_to_nasid)));
-       for_each_online_node(cnode)
-               sn_cnodeid_to_nasid[cnode] =
-                               pxm_to_nasid(nid_to_pxm_map[cnode]);
-
-       numionodes = num_online_nodes();
-       scan_for_ionodes();
-
        /*
         * Allocate & initalize the nodepda for each node.
         */
        /*
         * Allocate & initialize nodepda for TIOs.  For now, put them on node 0.
         */
-       for (cnode = num_online_nodes(); cnode < numionodes; cnode++) {
+       for (cnode = num_online_nodes(); cnode < num_cnodes; cnode++) {
                nodepdaindr[cnode] =
                    alloc_bootmem_node(NODE_DATA(0), sizeof(nodepda_t));
                memset(nodepdaindr[cnode], 0, sizeof(nodepda_t));
        /*
         * Now copy the array of nodepda pointers to each nodepda.
         */
-       for (cnode = 0; cnode < numionodes; cnode++)
+       for (cnode = 0; cnode < num_cnodes; cnode++)
                memcpy(nodepdaindr[cnode]->pernode_pdaindr, nodepdaindr,
                       sizeof(nodepdaindr));
 
         * Initialize the per node hubdev.  This includes IO Nodes and
         * headless/memless nodes.
         */
-       for (cnode = 0; cnode < numionodes; cnode++) {
+       for (cnode = 0; cnode < num_cnodes; cnode++) {
                hubdev_init_node(nodepdaindr[cnode], cnode);
        }
 }
 }
 
 /*
- * Scan klconfig for ionodes.  Add the nasids to the
- * physical_node_map and the pda and increment numionodes.
+ * Build tables for converting between NASIDs and cnodes.
  */
+static inline int __init board_needs_cnode(int type)
+{
+       return (type == KLTYPE_SNIA || type == KLTYPE_TIO);
+}
 
-static void __init scan_for_ionodes(void)
+void __init build_cnode_tables(void)
 {
-       int nasid = 0;
+       int nasid;
+       int node;
        lboard_t *brd;
 
-       /* fakeprom does not support klgraph */
-       if (IS_RUNNING_ON_FAKE_PROM())
-               return;
-
-       /* Setup ionodes with memory */
-       for (nasid = 0; nasid < MAX_PHYSNODE_ID; nasid += 2) {
-               char *klgraph_header;
-               cnodeid_t cnodeid;
-
-               if (physical_node_map[nasid] == -1)
-                       continue;
+       memset(physical_node_map, -1, sizeof(physical_node_map));
+       memset(sn_cnodeid_to_nasid, -1,
+                       sizeof(__ia64_per_cpu_var(__sn_cnodeid_to_nasid)));
 
-               cnodeid = -1;
-               klgraph_header = __va(ia64_sn_get_klconfig_addr(nasid));
-               if (!klgraph_header) {
-                       BUG();  /* All nodes must have klconfig tables! */
-               }
-               cnodeid = nasid_to_cnodeid(nasid);
-               root_lboard[cnodeid] = (lboard_t *)
-                   NODE_OFFSET_TO_LBOARD((nasid),
-                                         ((kl_config_hdr_t
-                                           *) (klgraph_header))->
-                                         ch_board_info);
+       /*
+        * First populate the tables with C/M bricks. This ensures that
+        * cnode == node for all C & M bricks.
+        */
+       for_each_online_node(node) {
+               nasid = pxm_to_nasid(nid_to_pxm_map[node]);
+               sn_cnodeid_to_nasid[node] = nasid;
+               physical_node_map[nasid] = node;
        }
 
-       /* Scan headless/memless IO Nodes. */
-       for (nasid = 0; nasid < MAX_PHYSNODE_ID; nasid += 2) {
-               /* if there's no nasid, don't try to read the klconfig on the node */
-               if (physical_node_map[nasid] == -1)
-                       continue;
-               brd = find_lboard_any((lboard_t *)
-                                     root_lboard[nasid_to_cnodeid(nasid)],
-                                     KLTYPE_SNIA);
-               if (brd) {
-                       brd = KLCF_NEXT_ANY(brd);       /* Skip this node's lboard */
-                       if (!brd)
-                               continue;
-               }
-
-               brd = find_lboard_any(brd, KLTYPE_SNIA);
+       /*
+        * num_cnodes is total number of C/M/TIO bricks. Because of the 256 node
+        * limit on the number of nodes, we can't use the generic node numbers 
+        * for this. Note that num_cnodes is incremented below as TIOs or
+        * headless/memoryless nodes are discovered.
+        */
+       num_cnodes = num_online_nodes();
 
-               while (brd) {
-                       sn_cnodeid_to_nasid[numionodes] = brd->brd_nasid;
-                       physical_node_map[brd->brd_nasid] = numionodes;
-                       root_lboard[numionodes] = brd;
-                       numionodes++;
-                       brd = KLCF_NEXT_ANY(brd);
-                       if (!brd)
-                               break;
-
-                       brd = find_lboard_any(brd, KLTYPE_SNIA);
-               }
-       }
+       /* fakeprom does not support klgraph */
+       if (IS_RUNNING_ON_FAKE_PROM())
+               return;
 
-       /* Scan for TIO nodes. */
-       for (nasid = 0; nasid < MAX_PHYSNODE_ID; nasid += 2) {
-               /* if there's no nasid, don't try to read the klconfig on the node */
-               if (physical_node_map[nasid] == -1)
-                       continue;
-               brd = find_lboard_any((lboard_t *)
-                                     root_lboard[nasid_to_cnodeid(nasid)],
-                                     KLTYPE_TIO);
+       /* Find TIOs & headless/memoryless nodes and add them to the tables */
+       for_each_online_node(node) {
+               kl_config_hdr_t *klgraph_header;
+               nasid = cnodeid_to_nasid(node);
+               if ((klgraph_header = ia64_sn_get_klconfig_addr(nasid)) == NULL)
+                       BUG();
+               brd = NODE_OFFSET_TO_LBOARD(nasid, klgraph_header->ch_board_info);
                while (brd) {
-                       sn_cnodeid_to_nasid[numionodes] = brd->brd_nasid;
-                       physical_node_map[brd->brd_nasid] = numionodes;
-                       root_lboard[numionodes] = brd;
-                       numionodes++;
-                       brd = KLCF_NEXT_ANY(brd);
-                       if (!brd)
-                               break;
-
-                       brd = find_lboard_any(brd, KLTYPE_TIO);
+                       if (board_needs_cnode(brd->brd_type) && physical_node_map[brd->brd_nasid] < 0) {
+                               sn_cnodeid_to_nasid[num_cnodes] = brd->brd_nasid;
+                               physical_node_map[brd->brd_nasid] = num_cnodes++;
+                       }
+                       brd = find_lboard_next(brd);
                }
        }
 }
 
 #include <asm/sn/types.h>
 #include <asm/sn/sn_cpuid.h>
 
+/*
+ * This is the maximum number of NUMALINK nodes that can be part of a single
+ * SSI kernel. This number includes C-brick, M-bricks, and TIOs. Nodes in
+ * remote partitions are NOT included in this number.
+ * The number of compact nodes cannot exceed size of a coherency domain.
+ * The purpose of this define is to specify a node count that includes
+ * all C/M/TIO nodes in an SSI system.
+ *
+ * SGI system can currently support up to 256 C/M nodes plus additional TIO nodes.
+ *
+ *     Note: ACPI20 has an architectural limit of 256 nodes. When we upgrade
+ *     to ACPI3.0, this limit will be removed. The notion of "compact nodes"
+ *     should be deleted and TIOs should be included in MAX_NUMNODES.
+ */
+#define MAX_COMPACT_NODES      512
+
+/*
+ * Maximum number of nodes in all partitions and in all coherency domains.
+ * This is the total number of nodes accessible in the numalink fabric. It
+ * includes all C & M bricks, plus all TIOs.
+ *
+ * This value is also the value of the maximum number of NASIDs in the numalink
+ * fabric.
+ */
+#define MAX_NUMALINK_NODES     2048
+
 /*
  * The following defines attributes of the HUB chip. These attributes are
  * frequently referenced. They are kept in the per-cpu data areas of each cpu.
 #define enable_shub_wars_1_1() (sn_hub_info->shub_1_1_found)
 
 
-/*
- * This is the maximum number of nodes that can be part of a kernel.
- * Effectively, it's the maximum number of compact node ids (cnodeid_t).
- * This is not necessarily the same as MAX_NASIDS.
- */
-#define MAX_COMPACT_NODES      2048
-#define CPUS_PER_NODE          4
-
-
 /*
  * Compact node ID to nasid mappings kept in the per-cpu data areas of each
  * cpu.
 #define sn_cnodeid_to_nasid    (&__get_cpu_var(__sn_cnodeid_to_nasid[0]))
 
 
-
 extern u8 sn_partition_id;
 extern u8 sn_system_size;
 extern u8 sn_sharing_domain_size;
 
        klconf_off_t    brd_next_same;    /* Next BOARD with same nasid */
 } lboard_t;
 
-#define KLCF_NUM_COMPS(_brd)   ((_brd)->brd_numcompts)
-#define NODE_OFFSET_TO_KLINFO(n,off)    ((klinfo_t*) TO_NODE_CAC(n,off))
-#define KLCF_NEXT(_brd)         \
-        ((_brd)->brd_next_same ?     \
-         (NODE_OFFSET_TO_LBOARD((_brd)->brd_next_same_host, (_brd)->brd_next_same)): NULL)
-#define KLCF_NEXT_ANY(_brd)         \
-        ((_brd)->brd_next_any ?     \
-         (NODE_OFFSET_TO_LBOARD(NASID_GET(_brd), (_brd)->brd_next_any)): NULL)
-#define KLCF_COMP(_brd, _ndx)   \
-                ((((_brd)->brd_compts[(_ndx)]) == 0) ? 0 : \
-                       (NODE_OFFSET_TO_KLINFO(NASID_GET(_brd), (_brd)->brd_compts[(_ndx)])))
-
-
 /*
  * Generic info structure. This stores common info about a 
  * component.
 } klinfo_t ;
 
 
-static inline lboard_t *find_lboard_any(lboard_t * start, unsigned char brd_type)
+static inline lboard_t *find_lboard_next(lboard_t * brd)
 {
-        /* Search all boards stored on this node. */
-
-        while (start) {
-                if (start->brd_type == brd_type)
-                        return start;
-                start = KLCF_NEXT_ANY(start);
-        }
-        /* Didn't find it. */
-        return (lboard_t *) NULL;
+       if (brd && brd->brd_next_any)
+               return NODE_OFFSET_TO_LBOARD(NASID_GET(brd), brd->brd_next_any);
+        return NULL;
 }
 
-
-/* external declarations of Linux kernel functions. */
-
-extern lboard_t *root_lboard[];
-extern klinfo_t *find_component(lboard_t *brd, klinfo_t *kli, unsigned char type);
-extern klinfo_t *find_first_component(lboard_t *brd, unsigned char type);
-
 #endif /* _ASM_IA64_SN_KLCONFIG_H */