aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDimitri Sivanich <sivanich@sgi.com>2016-04-29 17:54:23 -0400
committerIngo Molnar <mingo@kernel.org>2016-05-04 02:48:51 -0400
commitf68376fc9e6dc15a08e16f08c95e503f19ad8e34 (patch)
tree732f918304910575e730eb7d5d5a6451ff9f3d53
parent40bfb8eedf1e7fa0535c685ff1000c05bcf7a637 (diff)
x86/platform/UV: Fix incorrect nodes and pnodes for cpuless and memoryless nodes
This patch fixes the problem of incorrect nodes and pnodes being returned when referring to nodes that either have no cpus (AKA "headless") or no memory. Tested-by: John Estabrook <estabrook@sgi.com> Tested-by: Gary Kroening <gfk@sgi.com> Tested-by: Nathan Zimmer <nzimmer@sgi.com> Signed-off-by: Dimitri Sivanich <sivanich@sgi.com> Signed-off-by: Mike Travis <travis@sgi.com> Cc: Andrew Banman <abanman@sgi.com> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Andy Lutomirski <luto@amacapital.net> Cc: Borislav Petkov <bp@alien8.de> Cc: Brian Gerst <brgerst@gmail.com> Cc: Denys Vlasenko <dvlasenk@redhat.com> Cc: H. Peter Anvin <hpa@zytor.com> Cc: Len Brown <len.brown@intel.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Russ Anderson <rja@sgi.com> Cc: Thomas Gleixner <tglx@linutronix.de> Link: http://lkml.kernel.org/r/20160429215406.192644884@asylum.americas.sgi.com Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r--arch/x86/kernel/apic/x2apic_uv_x.c58
1 files changed, 28 insertions, 30 deletions
diff --git a/arch/x86/kernel/apic/x2apic_uv_x.c b/arch/x86/kernel/apic/x2apic_uv_x.c
index 65a40d4a95fe..aa6de8bad360 100644
--- a/arch/x86/kernel/apic/x2apic_uv_x.c
+++ b/arch/x86/kernel/apic/x2apic_uv_x.c
@@ -1232,8 +1232,7 @@ static void __init decode_uv_systab(void)
1232 */ 1232 */
1233static __init void boot_init_possible_blades(struct uv_hub_info_s *hub_info) 1233static __init void boot_init_possible_blades(struct uv_hub_info_s *hub_info)
1234{ 1234{
1235 size_t bytes; 1235 int i, uv_pb = 0;
1236 int blade, i, j, uv_pb = 0, num_nodes = num_possible_nodes();
1237 1236
1238 pr_info("UV: NODE_PRESENT_DEPTH = %d\n", UVH_NODE_PRESENT_TABLE_DEPTH); 1237 pr_info("UV: NODE_PRESENT_DEPTH = %d\n", UVH_NODE_PRESENT_TABLE_DEPTH);
1239 for (i = 0; i < UVH_NODE_PRESENT_TABLE_DEPTH; i++) { 1238 for (i = 0; i < UVH_NODE_PRESENT_TABLE_DEPTH; i++) {
@@ -1247,28 +1246,6 @@ static __init void boot_init_possible_blades(struct uv_hub_info_s *hub_info)
1247 } 1246 }
1248 if (uv_possible_blades != uv_pb) 1247 if (uv_possible_blades != uv_pb)
1249 uv_possible_blades = uv_pb; 1248 uv_possible_blades = uv_pb;
1250
1251 bytes = num_nodes * sizeof(_node_to_pnode[0]);
1252 _node_to_pnode = kmalloc(bytes, GFP_KERNEL);
1253 BUG_ON(!_node_to_pnode);
1254
1255 for (blade = 0, i = 0; i < UVH_NODE_PRESENT_TABLE_DEPTH; i++) {
1256 unsigned short pnode;
1257 unsigned long present =
1258 uv_read_local_mmr(UVH_NODE_PRESENT_TABLE + i * 8);
1259
1260 for (j = 0; j < 64; j++) {
1261 if (!test_bit(j, &present))
1262 continue;
1263 pnode = (i * 64 + j) & hub_info->pnode_mask;
1264 _node_to_pnode[blade++] = pnode;
1265 }
1266 if (blade > num_nodes) {
1267 pr_err("UV: blade count(%d) exceeds node count(%d)!\n",
1268 blade, num_nodes);
1269 BUG();
1270 }
1271 }
1272} 1249}
1273 1250
1274static void __init build_socket_tables(void) 1251static void __init build_socket_tables(void)
@@ -1449,7 +1426,6 @@ void __init uv_system_init(void)
1449 bytes = sizeof(struct uv_hub_info_s); 1426 bytes = sizeof(struct uv_hub_info_s);
1450 for_each_node(nodeid) { 1427 for_each_node(nodeid) {
1451 struct uv_hub_info_s *new_hub; 1428 struct uv_hub_info_s *new_hub;
1452 unsigned short pnode;
1453 1429
1454 if (__uv_hub_info_list[nodeid]) { 1430 if (__uv_hub_info_list[nodeid]) {
1455 pr_err("UV: Node %d UV HUB already initialized!?\n", 1431 pr_err("UV: Node %d UV HUB already initialized!?\n",
@@ -1467,10 +1443,11 @@ void __init uv_system_init(void)
1467 BUG_ON(!new_hub); 1443 BUG_ON(!new_hub);
1468 *new_hub = hub_info; 1444 *new_hub = hub_info;
1469 1445
1470 pnode = _node_to_pnode[nodeid]; 1446 /* Use information from GAM table if available */
1471 min_pnode = min(pnode, min_pnode); 1447 if (_node_to_pnode)
1472 max_pnode = max(pnode, max_pnode); 1448 new_hub->pnode = _node_to_pnode[nodeid];
1473 new_hub->pnode = pnode; 1449 else /* Fill in during cpu loop */
1450 new_hub->pnode = 0xffff;
1474 new_hub->numa_blade_id = uv_node_to_blade_id(nodeid); 1451 new_hub->numa_blade_id = uv_node_to_blade_id(nodeid);
1475 new_hub->memory_nid = -1; 1452 new_hub->memory_nid = -1;
1476 new_hub->nr_possible_cpus = 0; 1453 new_hub->nr_possible_cpus = 0;
@@ -1480,18 +1457,39 @@ void __init uv_system_init(void)
1480 /* Initialize per cpu info */ 1457 /* Initialize per cpu info */
1481 for_each_possible_cpu(cpu) { 1458 for_each_possible_cpu(cpu) {
1482 int apicid = per_cpu(x86_cpu_to_apicid, cpu); 1459 int apicid = per_cpu(x86_cpu_to_apicid, cpu);
1460 int numa_node_id;
1461 unsigned short pnode;
1483 1462
1484 nodeid = cpu_to_node(cpu); 1463 nodeid = cpu_to_node(cpu);
1464 numa_node_id = numa_cpu_node(cpu);
1465 pnode = uv_apicid_to_pnode(apicid);
1466
1485 uv_cpu_info_per(cpu)->p_uv_hub_info = uv_hub_info_list(nodeid); 1467 uv_cpu_info_per(cpu)->p_uv_hub_info = uv_hub_info_list(nodeid);
1486 uv_cpu_info_per(cpu)->blade_cpu_id = 1468 uv_cpu_info_per(cpu)->blade_cpu_id =
1487 uv_cpu_hub_info(cpu)->nr_possible_cpus++; 1469 uv_cpu_hub_info(cpu)->nr_possible_cpus++;
1488 if (uv_cpu_hub_info(cpu)->memory_nid == -1) 1470 if (uv_cpu_hub_info(cpu)->memory_nid == -1)
1489 uv_cpu_hub_info(cpu)->memory_nid = cpu_to_node(cpu); 1471 uv_cpu_hub_info(cpu)->memory_nid = cpu_to_node(cpu);
1472 if (nodeid != numa_node_id && /* init memoryless node */
1473 uv_hub_info_list(numa_node_id)->pnode == 0xffff)
1474 uv_hub_info_list(numa_node_id)->pnode = pnode;
1475 else if (uv_cpu_hub_info(cpu)->pnode == 0xffff)
1476 uv_cpu_hub_info(cpu)->pnode = pnode;
1490 uv_cpu_scir_info(cpu)->offset = uv_scir_offset(apicid); 1477 uv_cpu_scir_info(cpu)->offset = uv_scir_offset(apicid);
1491 } 1478 }
1492 1479
1493 /* Display per node info */
1494 for_each_node(nodeid) { 1480 for_each_node(nodeid) {
1481 unsigned short pnode = uv_hub_info_list(nodeid)->pnode;
1482
1483 /* Add pnode info for pre-GAM list nodes without cpus */
1484 if (pnode == 0xffff) {
1485 unsigned long paddr;
1486
1487 paddr = node_start_pfn(nodeid) << PAGE_SHIFT;
1488 pnode = uv_gpa_to_pnode(uv_soc_phys_ram_to_gpa(paddr));
1489 uv_hub_info_list(nodeid)->pnode = pnode;
1490 }
1491 min_pnode = min(pnode, min_pnode);
1492 max_pnode = max(pnode, max_pnode);
1495 pr_info("UV: UVHUB node:%2d pn:%02x nrcpus:%d\n", 1493 pr_info("UV: UVHUB node:%2d pn:%02x nrcpus:%d\n",
1496 nodeid, 1494 nodeid,
1497 uv_hub_info_list(nodeid)->pnode, 1495 uv_hub_info_list(nodeid)->pnode,