[PATCH v3] powerpc/numa: Fill distance_lookup_table for offline nodes

Srikar Dronamraju srikar at linux.vnet.ibm.com
Mon Sep 13 22:57:08 AEST 2021


Scheduler expects the number of unique node distances to be available
at boot. It iterates over all pairs of nodes and records
node_distance() for that pair, and then calculates the set of unique
distances. As per PAPR, node distances for offline nodes is not
available. However, PAPR already exposes unique possible node
distances. Fake the offline node's distance_lookup_table entries so
that all possible node distances are updated.

However this only needs to be done if the number of unique node
distances that can be computed for online nodes is less than the
number of possible unique node distances as represented by
distance_ref_points_depth. When the node is actually onlined,
distance_lookup_table will be updated with actual entries.

Cc: linuxppc-dev at lists.ozlabs.org
Cc: Nathan Lynch <nathanl at linux.ibm.com>
Cc: Michael Ellerman <mpe at ellerman.id.au>
Cc: Ingo Molnar <mingo at kernel.org>
Cc: Peter Zijlstra <peterz at infradead.org>
Cc: Valentin Schneider <valentin.schneider at arm.com>
Cc: Gautham R Shenoy <ego at linux.vnet.ibm.com>
Cc: Vincent Guittot <vincent.guittot at linaro.org>
Cc: Geetika Moolchandani <Geetika.Moolchandani1 at ibm.com>
Cc: Laurent Dufour <ldufour at linux.ibm.com>
Cc: kernel test robot <lkp at intel.com>
Signed-off-by: Srikar Dronamraju <srikar at linux.vnet.ibm.com>
---
Changelog:
v2: https://lore.kernel.org/linuxppc-dev/20210821102535.169643-4-srikar@linux.vnet.ibm.com/t/#u
- Updated changelog
- Updated variable names
- Rebased to newer branch
- tweaked the WARN if the depth is greater than sizeof(long)
- All of the above based on comments from Michael Ellerman

v1: https://lore.kernel.org/linuxppc-dev/20210701041552.112072-3-srikar@linux.vnet.ibm.com/t/#u
[ Fixed a missing prototype warning Reported-by: kernel test robot <lkp at intel.com>]

 arch/powerpc/mm/numa.c | 68 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 68 insertions(+)

diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c
index 6f14c8fb6359..5ac9f20ebbc8 100644
--- a/arch/powerpc/mm/numa.c
+++ b/arch/powerpc/mm/numa.c
@@ -1079,6 +1079,73 @@ void __init dump_numa_cpu_topology(void)
 	}
 }
 
+/*
+ * Scheduler expects unique number of node distances to be available at
+ * boot. It uses node distance to calculate this unique node distances. On
+ * POWER, node distances for offline nodes is not available. However, POWER
+ * already knows unique possible node distances. Fake the offline node's
+ * distance_lookup_table entries so that all possible node distances are
+ * updated.
+ */
+static void __init fake_update_distance_lookup_table(void)
+{
+	unsigned long distance_map;
+	int i, cur_depth, max_depth, node;
+
+	if (!numa_enabled)
+		return;
+
+	if (affinity_form != FORM1_AFFINITY)
+		return;
+
+	/*
+	 * distance_ref_points_depth lists the unique numa domains
+	 * available. However it ignore LOCAL_DISTANCE. So add +1
+	 * to get the actual number of unique distances.
+	 */
+	max_depth = distance_ref_points_depth + 1;
+
+	if (max_depth > sizeof(distance_map)) {
+		WARN(1, "Max depth %d > %ld\n", max_depth, sizeof(distance_map));
+		max_depth = sizeof(distance_map);
+	}
+
+	bitmap_zero(&distance_map, max_depth);
+	bitmap_set(&distance_map, 0, 1);
+
+	for_each_online_node(node) {
+		int nd, distance;
+
+		if (node == first_online_node)
+			continue;
+
+		nd = __node_distance(node, first_online_node);
+		for (i = 0, distance = LOCAL_DISTANCE; i < max_depth; i++, distance *= 2) {
+			if (distance == nd) {
+				bitmap_set(&distance_map, i, 1);
+				break;
+			}
+		}
+		cur_depth = bitmap_weight(&distance_map, max_depth);
+		if (cur_depth == max_depth)
+			return;
+	}
+
+	for_each_node(node) {
+		if (node_online(node))
+			continue;
+
+		i = find_first_zero_bit(&distance_map, max_depth);
+		bitmap_set(&distance_map, i, 1);
+		while (i--)
+			distance_lookup_table[node][i] = node;
+
+		cur_depth = bitmap_weight(&distance_map, max_depth);
+		if (cur_depth == max_depth)
+			return;
+	}
+}
+
 /* Initialize NODE_DATA for a node on the local memory */
 static void __init setup_node_data(int nid, u64 start_pfn, u64 end_pfn)
 {
@@ -1201,6 +1268,7 @@ void __init mem_topology_setup(void)
 		 */
 		numa_setup_cpu(cpu);
 	}
+	fake_update_distance_lookup_table();
 }
 
 void __init initmem_init(void)
-- 
2.27.0



More information about the Linuxppc-dev mailing list