x86/platform/UV: Fold blade info into per node hub info structs
[cascardo/linux.git] / arch / x86 / kernel / apic / x2apic_uv_x.c
index 35c9610..afe1b03 100644 (file)
@@ -238,21 +238,14 @@ EXPORT_SYMBOL_GPL(__uv_hub_info_list);
 DEFINE_PER_CPU(struct uv_cpu_info_s, __uv_cpu_info);
 EXPORT_PER_CPU_SYMBOL_GPL(__uv_cpu_info);
 
-struct uv_blade_info *uv_blade_info;
-EXPORT_SYMBOL_GPL(uv_blade_info);
-
-short *uv_node_to_blade;
-EXPORT_SYMBOL_GPL(uv_node_to_blade);
-
-short *uv_cpu_to_blade;
-EXPORT_SYMBOL_GPL(uv_cpu_to_blade);
-
 short uv_possible_blades;
 EXPORT_SYMBOL_GPL(uv_possible_blades);
 
 unsigned long sn_rtc_cycles_per_second;
 EXPORT_SYMBOL(sn_rtc_cycles_per_second);
 
+static __initdata unsigned short *_node_to_pnode;
+
 extern int uv_hub_info_version(void)
 {
        return UV_HUB_INFO_VERSION;
@@ -385,7 +378,6 @@ static unsigned long set_apic_id(unsigned int id)
 
 static unsigned int uv_read_apic_id(void)
 {
-
        return x2apic_get_apic_id(apic_read(APIC_ID));
 }
 
@@ -460,19 +452,6 @@ static void set_x2apic_extra_bits(int pnode)
        __this_cpu_write(x2apic_extra_bits, pnode << uvh_apicid.s.pnode_shift);
 }
 
-/*
- * Called on boot cpu.
- */
-static __init int boot_pnode_to_blade(int pnode)
-{
-       int blade;
-
-       for (blade = 0; blade < uv_num_possible_blades(); blade++)
-               if (pnode == uv_blade_info[blade].pnode)
-                       return blade;
-       BUG();
-}
-
 #define        UVH_RH_GAM_ALIAS210_REDIRECT_CONFIG_LENGTH      3
 #define DEST_SHIFT UVH_RH_GAM_ALIAS210_REDIRECT_CONFIG_0_MMR_DEST_BASE_SHFT
 
@@ -889,10 +868,10 @@ int uv_set_vga_state(struct pci_dev *pdev, bool decode,
 void uv_cpu_init(void)
 {
        /* CPU 0 initialization will be done via uv_system_init. */
-       if (!uv_blade_info)
+       if (smp_processor_id() == 0)
                return;
 
-       uv_blade_info[uv_numa_blade_id()].nr_online_cpus++;
+       uv_hub_info->nr_online_cpus++;
 
        if (get_uv_system_type() == UV_NON_UNIQUE_APIC)
                set_x2apic_extra_bits(uv_hub_info->pnode);
@@ -976,11 +955,57 @@ void __init uv_init_hub_info(struct uv_hub_info_s *hub_info)
 
 }
 
+/*
+ * Setup physical blade translations from UVH_NODE_PRESENT_TABLE
+ * .. NB: UVH_NODE_PRESENT_TABLE is going away,
+ * .. being replaced by GAM Range Table
+ */
+static __init void boot_init_possible_blades(struct uv_hub_info_s *hub_info)
+{
+       size_t bytes;
+       int blade, i, j, uv_pb = 0, num_nodes = num_possible_nodes();
+
+       pr_info("UV: NODE_PRESENT_DEPTH = %d\n", UVH_NODE_PRESENT_TABLE_DEPTH);
+       for (i = 0; i < UVH_NODE_PRESENT_TABLE_DEPTH; i++) {
+               unsigned long np;
+
+               np = uv_read_local_mmr(UVH_NODE_PRESENT_TABLE + i * 8);
+               if (np)
+                       pr_info("UV: NODE_PRESENT(%d) = 0x%016lx\n", i, np);
+
+               uv_pb += hweight64(np);
+       }
+       if (uv_possible_blades != uv_pb)
+               uv_possible_blades = uv_pb;
+
+       bytes = num_nodes * sizeof(_node_to_pnode[0]);
+       _node_to_pnode = kmalloc(bytes, GFP_KERNEL);
+       BUG_ON(!_node_to_pnode);
+
+       for (blade = 0, i = 0; i < UVH_NODE_PRESENT_TABLE_DEPTH; i++) {
+               unsigned short pnode;
+               unsigned long present =
+                       uv_read_local_mmr(UVH_NODE_PRESENT_TABLE + i * 8);
+
+               for (j = 0; j < 64; j++) {
+                       if (!test_bit(j, &present))
+                               continue;
+                       pnode = (i * 64 + j) & hub_info->pnode_mask;
+                       _node_to_pnode[blade++] = pnode;
+               }
+               if (blade > num_nodes) {
+                       pr_err("UV: blade count(%d) exceeds node count(%d)!\n",
+                               blade, num_nodes);
+                       BUG();
+               }
+       }
+}
+
 void __init uv_system_init(void)
 {
        struct uv_hub_info_s hub_info = {0};
-       int bytes, nid, cpu, pnode, blade, i, j;
-       int min_pnode = 999999, max_pnode = -1;
+       int bytes, cpu, nodeid;
+       unsigned short min_pnode = 9999, max_pnode = 0;
        char *hub = is_uv4_hub() ? "UV400" :
                    is_uv3_hub() ? "UV300" :
                    is_uv2_hub() ? "UV2000/3000" :
@@ -997,16 +1022,9 @@ void __init uv_system_init(void)
                map_low_mmrs();
 
        uv_init_hub_info(&hub_info);
-
-       pr_info("UV: NODE_PRESENT_DEPTH = %d\n", UVH_NODE_PRESENT_TABLE_DEPTH);
-       for (i = 0; i < UVH_NODE_PRESENT_TABLE_DEPTH; i++) {
-               unsigned long np;
-
-               np = uv_read_local_mmr(UVH_NODE_PRESENT_TABLE + i * 8);
-               if (np)
-                       pr_info("UV: NODE_PRESENT(%d) = 0x%016lx\n", i, np);
-               uv_possible_blades += hweight64(np);
-       }
+       uv_possible_blades = num_possible_nodes();
+       if (!_node_to_pnode)
+               boot_init_possible_blades(&hub_info);
 
        /* uv_num_possible_blades() is really the hub count */
        pr_info("UV: Found %d hubs, %d nodes, %d cpus\n",
@@ -1014,97 +1032,69 @@ void __init uv_system_init(void)
                        num_possible_nodes(),
                        num_possible_cpus());
 
-       bytes = sizeof(struct uv_blade_info) * uv_num_possible_blades();
-       uv_blade_info = kzalloc(bytes, GFP_KERNEL);
-       BUG_ON(!uv_blade_info);
-
-       for (blade = 0; blade < uv_num_possible_blades(); blade++)
-               uv_blade_info[blade].memory_nid = -1;
-
-
-       bytes = sizeof(uv_node_to_blade[0]) * num_possible_nodes();
-       uv_node_to_blade = kmalloc(bytes, GFP_KERNEL);
-       BUG_ON(!uv_node_to_blade);
-       memset(uv_node_to_blade, 255, bytes);
-
-       bytes = sizeof(uv_cpu_to_blade[0]) * num_possible_cpus();
-       uv_cpu_to_blade = kmalloc(bytes, GFP_KERNEL);
-       BUG_ON(!uv_cpu_to_blade);
-       memset(uv_cpu_to_blade, 255, bytes);
-
-       bytes = sizeof(void *) * uv_num_possible_blades();
-       __uv_hub_info_list = kzalloc(bytes, GFP_KERNEL);
-       BUG_ON(!__uv_hub_info_list);
-
-       blade = 0;
-       for (i = 0; i < UVH_NODE_PRESENT_TABLE_DEPTH; i++) {
-               unsigned long present =
-                       uv_read_local_mmr(UVH_NODE_PRESENT_TABLE + i * 8);
-               for (j = 0; j < 64; j++) {
-                       if (!test_bit(j, &present))
-                               continue;
-                       pnode = (i * 64 + j) & hub_info.pnode_mask;
-                       uv_blade_info[blade].pnode = pnode;
-                       uv_blade_info[blade].nr_possible_cpus = 0;
-                       uv_blade_info[blade].nr_online_cpus = 0;
-                       min_pnode = min(pnode, min_pnode);
-                       max_pnode = max(pnode, max_pnode);
-                       blade++;
-               }
-       }
-
        uv_bios_init();
        uv_bios_get_sn_info(0, &uv_type, &sn_partition_id, &sn_coherency_id,
                            &sn_region_size, &system_serial_number);
        hub_info.coherency_domain_number = sn_coherency_id;
        uv_rtc_init();
 
-       for_each_present_cpu(cpu) {
-               struct uv_hub_info_s *new_hub = NULL;
-               int apicid = per_cpu(x86_cpu_to_apicid, cpu);
-               int nodeid = cpu_to_node(cpu);
+       bytes = sizeof(void *) * uv_num_possible_blades();
+       __uv_hub_info_list = kzalloc(bytes, GFP_KERNEL);
+       BUG_ON(!__uv_hub_info_list);
 
-               /* Allocate new per hub info list */
-               if (uv_hub_info_list(nodeid) == NULL) {
-                       if (cpu == 0)
-                               __uv_hub_info_list[0] = &uv_hub_info_node0;
-                       else
-                               __uv_hub_info_list[nodeid] =
-                                       kzalloc_node(bytes, GFP_KERNEL, nodeid);
-
-                       new_hub = uv_hub_info_list(nodeid);
-                       BUG_ON(!new_hub);
-                       *new_hub = hub_info;
-                       blade = boot_pnode_to_blade(new_hub->pnode);
-                       new_hub->pnode = uv_apicid_to_pnode(apicid);
-                       new_hub->numa_blade_id = blade;
+       bytes = sizeof(struct uv_hub_info_s);
+       for_each_node(nodeid) {
+               struct uv_hub_info_s *new_hub;
+               unsigned short pnode;
+
+               if (__uv_hub_info_list[nodeid]) {
+                       pr_err("UV: Node %d UV HUB already initialized!?\n",
+                               nodeid);
+                       BUG();
                }
 
-               /* Any node on the blade, else will contain -1. */
-               uv_blade_info[blade].memory_nid = nodeid;
+               /* Allocate new per hub info list */
+               new_hub = (nodeid == 0) ?
+                       &uv_hub_info_node0 :
+                       kzalloc_node(bytes, GFP_KERNEL, nodeid);
+               BUG_ON(!new_hub);
+               __uv_hub_info_list[nodeid] = new_hub;
+               new_hub = uv_hub_info_list(nodeid);
+               BUG_ON(!new_hub);
+               *new_hub = hub_info;
+
+               pnode = _node_to_pnode[nodeid];
+               min_pnode = min(pnode, min_pnode);
+               max_pnode = max(pnode, max_pnode);
+               new_hub->pnode = pnode;
+               new_hub->numa_blade_id = uv_node_to_blade_id(nodeid);
+               new_hub->memory_nid = -1;
+               new_hub->nr_possible_cpus = 0;
+               new_hub->nr_online_cpus = 0;
+       }
 
-               uv_node_to_blade[nodeid] = blade;
-               uv_cpu_to_blade[cpu] = blade;
+       /* Initialize per cpu info */
+       for_each_possible_cpu(cpu) {
+               int apicid = per_cpu(x86_cpu_to_apicid, cpu);
 
-               /* Initialize per cpu info list */
+               nodeid = cpu_to_node(cpu);
                uv_cpu_info_per(cpu)->p_uv_hub_info = uv_hub_info_list(nodeid);
-               uv_cpu_info_per(cpu)->scir.offset = uv_scir_offset(apicid);
                uv_cpu_info_per(cpu)->blade_cpu_id =
-                       uv_blade_info[blade].nr_possible_cpus++;
+                       uv_cpu_hub_info(cpu)->nr_possible_cpus++;
+               if (uv_cpu_hub_info(cpu)->memory_nid == -1)
+                       uv_cpu_hub_info(cpu)->memory_nid = cpu_to_node(cpu);
+               uv_cpu_scir_info(cpu)->offset = uv_scir_offset(apicid);
        }
 
-       /* Add blade/pnode info for nodes without cpus */
-       for_each_online_node(nid) {
-               unsigned long paddr;
-
-               if (uv_node_to_blade[nid] >= 0)
-                       continue;
-               paddr = node_start_pfn(nid) << PAGE_SHIFT;
-               pnode = uv_gpa_to_pnode(uv_soc_phys_ram_to_gpa(paddr));
-               blade = boot_pnode_to_blade(pnode);
-               uv_node_to_blade[nid] = blade;
+       /* Display per node info */
+       for_each_node(nodeid) {
+               pr_info("UV: UVHUB node:%2d pn:%02x nrcpus:%d\n",
+                       nodeid,
+                       uv_hub_info_list(nodeid)->pnode,
+                       uv_hub_info_list(nodeid)->nr_possible_cpus);
        }
 
+       pr_info("UV: min_pnode:%02x max_pnode:%02x\n", min_pnode, max_pnode);
        map_gru_high(max_pnode);
        map_mmr_high(max_pnode);
        map_mmioh_high(min_pnode, max_pnode);