Michal Suchanek 91c0ea
From 8ddc6448ec5a5ef50eaa581a7dec0e12a02850ff Mon Sep 17 00:00:00 2001
Michal Suchanek 91c0ea
From: "Aneesh Kumar K.V" <aneesh.kumar@linux.ibm.com>
Michal Suchanek 91c0ea
Date: Thu, 12 Aug 2021 18:52:21 +0530
Michal Suchanek 91c0ea
Subject: [PATCH] powerpc/pseries: Consolidate different NUMA distance update
Michal Suchanek 91c0ea
 code paths
Michal Suchanek 91c0ea
Michal Suchanek 91c0ea
References: bsc#1209999 ltc#202140 bsc#1142685 ltc#179509 FATE#327775 git-fixes
Michal Suchanek 91c0ea
Patch-mainline: v5.15-rc1
Michal Suchanek 91c0ea
Git-commit: 8ddc6448ec5a5ef50eaa581a7dec0e12a02850ff
Michal Suchanek 91c0ea
Michal Suchanek 91c0ea
The associativity details of the newly added resourced are collected from
Michal Suchanek 91c0ea
the hypervisor via "ibm,configure-connector" rtas call. Update the numa
Michal Suchanek 91c0ea
distance details of the newly added numa node after the above call.
Michal Suchanek 91c0ea
Michal Suchanek 91c0ea
Instead of updating NUMA distance every time we lookup a node id
Michal Suchanek 91c0ea
from the associativity property, add helpers that can be used
Michal Suchanek 91c0ea
during boot which does this only once. Also remove the distance
Michal Suchanek 91c0ea
update from node id lookup helpers.
Michal Suchanek 91c0ea
Michal Suchanek 91c0ea
Currently, we duplicate parsing code for ibm,associativity and
Michal Suchanek 91c0ea
ibm,associativity-lookup-arrays in the kernel. The associativity array provided
Michal Suchanek 91c0ea
by these device tree properties are very similar and hence can use
Michal Suchanek 91c0ea
a helper to parse the node id and numa distance details.
Michal Suchanek 91c0ea
Michal Suchanek 91c0ea
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.ibm.com>
Michal Suchanek 91c0ea
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Michal Suchanek 91c0ea
Link: https://lore.kernel.org/r/20210812132223.225214-4-aneesh.kumar@linux.ibm.com
Michal Suchanek 91c0ea
Acked-by: Michal Suchanek <msuchanek@suse.de>
Michal Suchanek 91c0ea
---
Michal Suchanek 91c0ea
 arch/powerpc/include/asm/topology.h           |   2 +
Michal Suchanek 91c0ea
 arch/powerpc/mm/numa.c                        | 212 +++++++++++++-----
Michal Suchanek 91c0ea
 arch/powerpc/platforms/pseries/hotplug-cpu.c  |   2 +
Michal Suchanek 91c0ea
 .../platforms/pseries/hotplug-memory.c        |   2 +
Michal Suchanek 91c0ea
 4 files changed, 161 insertions(+), 57 deletions(-)
Michal Suchanek 91c0ea
Michal Suchanek 91c0ea
diff --git a/arch/powerpc/include/asm/topology.h b/arch/powerpc/include/asm/topology.h
Michal Suchanek 91c0ea
index e4db64c0e184..a6425a70c37b 100644
Michal Suchanek 91c0ea
--- a/arch/powerpc/include/asm/topology.h
Michal Suchanek 91c0ea
+++ b/arch/powerpc/include/asm/topology.h
Michal Suchanek 91c0ea
@@ -64,6 +64,7 @@ static inline int early_cpu_to_node(int cpu)
Michal Suchanek 91c0ea
 }
Michal Suchanek 91c0ea
 
Michal Suchanek 91c0ea
 int of_drconf_to_nid_single(struct drmem_lmb *lmb);
Michal Suchanek 91c0ea
+void update_numa_distance(struct device_node *node);
Michal Suchanek 91c0ea
 
Michal Suchanek 91c0ea
 #else
Michal Suchanek 91c0ea
 
Michal Suchanek 91c0ea
@@ -93,6 +94,7 @@ static inline int of_drconf_to_nid_single(struct drmem_lmb *lmb)
Michal Suchanek 91c0ea
 	return first_online_node;
Michal Suchanek 91c0ea
 }
Michal Suchanek 91c0ea
 
Michal Suchanek 91c0ea
+static inline void update_numa_distance(struct device_node *node) {}
Michal Suchanek 91c0ea
 #endif /* CONFIG_NUMA */
Michal Suchanek 91c0ea
 
Michal Suchanek 91c0ea
 #if defined(CONFIG_NUMA) && defined(CONFIG_PPC_SPLPAR)
Michal Suchanek 91c0ea
diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c
Michal Suchanek 91c0ea
index 0bad11b3e929..3cda37c52f26 100644
Michal Suchanek 91c0ea
--- a/arch/powerpc/mm/numa.c
Michal Suchanek 91c0ea
+++ b/arch/powerpc/mm/numa.c
Michal Suchanek 91c0ea
@@ -208,50 +208,35 @@ int __node_distance(int a, int b)
Michal Suchanek 91c0ea
 }
Michal Suchanek 91c0ea
 EXPORT_SYMBOL(__node_distance);
Michal Suchanek 91c0ea
 
Michal Suchanek 91c0ea
-static void initialize_distance_lookup_table(int nid,
Michal Suchanek 91c0ea
-		const __be32 *associativity)
Michal Suchanek 91c0ea
+static int __associativity_to_nid(const __be32 *associativity,
Michal Suchanek 91c0ea
+				  int max_array_sz)
Michal Suchanek 91c0ea
 {
Michal Suchanek 91c0ea
-	int i;
Michal Suchanek 91c0ea
+	int nid;
Michal Suchanek 91c0ea
+	/*
Michal Suchanek 91c0ea
+	 * primary_domain_index is 1 based array index.
Michal Suchanek 91c0ea
+	 */
Michal Suchanek 91c0ea
+	int index = primary_domain_index  - 1;
Michal Suchanek 91c0ea
 
Michal Suchanek 91c0ea
-	if (affinity_form != FORM1_AFFINITY)
Michal Suchanek 91c0ea
-		return;
Michal Suchanek 91c0ea
+	if (!numa_enabled || index >= max_array_sz)
Michal Suchanek 91c0ea
+		return NUMA_NO_NODE;
Michal Suchanek 91c0ea
 
Michal Suchanek 91c0ea
-	for (i = 0; i < distance_ref_points_depth; i++) {
Michal Suchanek 91c0ea
-		const __be32 *entry;
Michal Suchanek 91c0ea
+	nid = of_read_number(&associativity[index], 1);
Michal Suchanek 91c0ea
 
Michal Suchanek 91c0ea
-		entry = &associativity[be32_to_cpu(distance_ref_points[i]) - 1];
Michal Suchanek 91c0ea
-		distance_lookup_table[nid][i] = of_read_number(entry, 1);
Michal Suchanek 91c0ea
-	}
Michal Suchanek 91c0ea
+	/* POWER4 LPAR uses 0xffff as invalid node */
Michal Suchanek 91c0ea
+	if (nid == 0xffff || nid >= nr_node_ids)
Michal Suchanek 91c0ea
+		nid = NUMA_NO_NODE;
Michal Suchanek 91c0ea
+	return nid;
Michal Suchanek 91c0ea
 }
Michal Suchanek 91c0ea
-
Michal Suchanek 91c0ea
 /*
Michal Suchanek 91c0ea
  * Returns nid in the range [0..nr_node_ids], or -1 if no useful NUMA
Michal Suchanek 91c0ea
  * info is found.
Michal Suchanek 91c0ea
  */
Michal Suchanek 91c0ea
 static int associativity_to_nid(const __be32 *associativity)
Michal Suchanek 91c0ea
 {
Michal Suchanek 91c0ea
-	int nid = NUMA_NO_NODE;
Michal Suchanek 91c0ea
-
Michal Suchanek 91c0ea
-	if (!numa_enabled)
Michal Suchanek 91c0ea
-		goto out;
Michal Suchanek 91c0ea
-
Michal Suchanek 91c0ea
-	if (of_read_number(associativity, 1) >= primary_domain_index)
Michal Suchanek 91c0ea
-		nid = of_read_number(&associativity[primary_domain_index], 1);
Michal Suchanek 91c0ea
-
Michal Suchanek 91c0ea
-	/* POWER4 LPAR uses 0xffff as invalid node */
Michal Suchanek 91c0ea
-	if (nid == 0xffff || nid >= nr_node_ids)
Michal Suchanek 91c0ea
-		nid = NUMA_NO_NODE;
Michal Suchanek 91c0ea
-
Michal Suchanek 91c0ea
-	if (nid > 0 &&
Michal Suchanek 91c0ea
-		of_read_number(associativity, 1) >= distance_ref_points_depth) {
Michal Suchanek 91c0ea
-		/*
Michal Suchanek 91c0ea
-		 * Skip the length field and send start of associativity array
Michal Suchanek 91c0ea
-		 */
Michal Suchanek 91c0ea
-		initialize_distance_lookup_table(nid, associativity + 1);
Michal Suchanek 91c0ea
-	}
Michal Suchanek 91c0ea
+	int array_sz = of_read_number(associativity, 1);
Michal Suchanek 91c0ea
 
Michal Suchanek 91c0ea
-out:
Michal Suchanek 91c0ea
-	return nid;
Michal Suchanek 91c0ea
+	/* Skip the first element in the associativity array */
Michal Suchanek 91c0ea
+	return __associativity_to_nid((associativity + 1), array_sz);
Michal Suchanek 91c0ea
 }
Michal Suchanek 91c0ea
 
Michal Suchanek 91c0ea
 /* Returns the nid associated with the given device tree node,
Michal Suchanek 91c0ea
@@ -287,6 +272,60 @@ int of_node_to_nid(struct device_node *device)
Michal Suchanek 91c0ea
 }
Michal Suchanek 91c0ea
 EXPORT_SYMBOL(of_node_to_nid);
Michal Suchanek 91c0ea
 
Michal Suchanek 91c0ea
+static void __initialize_form1_numa_distance(const __be32 *associativity,
Michal Suchanek 91c0ea
+					     int max_array_sz)
Michal Suchanek 91c0ea
+{
Michal Suchanek 91c0ea
+	int i, nid;
Michal Suchanek 91c0ea
+
Michal Suchanek 91c0ea
+	if (affinity_form != FORM1_AFFINITY)
Michal Suchanek 91c0ea
+		return;
Michal Suchanek 91c0ea
+
Michal Suchanek 91c0ea
+	nid = __associativity_to_nid(associativity, max_array_sz);
Michal Suchanek 91c0ea
+	if (nid != NUMA_NO_NODE) {
Michal Suchanek 91c0ea
+		for (i = 0; i < distance_ref_points_depth; i++) {
Michal Suchanek 91c0ea
+			const __be32 *entry;
Michal Suchanek 91c0ea
+			int index = be32_to_cpu(distance_ref_points[i]) - 1;
Michal Suchanek 91c0ea
+
Michal Suchanek 91c0ea
+			/*
Michal Suchanek 91c0ea
+			 * broken hierarchy, return with broken distance table
Michal Suchanek 91c0ea
+			 */
Michal Suchanek 91c0ea
+			if (WARN(index >= max_array_sz, "Broken ibm,associativity property"))
Michal Suchanek 91c0ea
+				return;
Michal Suchanek 91c0ea
+
Michal Suchanek 91c0ea
+			entry = &associativity[index];
Michal Suchanek 91c0ea
+			distance_lookup_table[nid][i] = of_read_number(entry, 1);
Michal Suchanek 91c0ea
+		}
Michal Suchanek 91c0ea
+	}
Michal Suchanek 91c0ea
+}
Michal Suchanek 91c0ea
+
Michal Suchanek 91c0ea
+static void initialize_form1_numa_distance(const __be32 *associativity)
Michal Suchanek 91c0ea
+{
Michal Suchanek 91c0ea
+	int array_sz;
Michal Suchanek 91c0ea
+
Michal Suchanek 91c0ea
+	array_sz = of_read_number(associativity, 1);
Michal Suchanek 91c0ea
+	/* Skip the first element in the associativity array */
Michal Suchanek 91c0ea
+	__initialize_form1_numa_distance(associativity + 1, array_sz);
Michal Suchanek 91c0ea
+}
Michal Suchanek 91c0ea
+
Michal Suchanek 91c0ea
+/*
Michal Suchanek 91c0ea
+ * Used to update distance information w.r.t newly added node.
Michal Suchanek 91c0ea
+ */
Michal Suchanek 91c0ea
+void update_numa_distance(struct device_node *node)
Michal Suchanek 91c0ea
+{
Michal Suchanek 91c0ea
+	if (affinity_form == FORM0_AFFINITY)
Michal Suchanek 91c0ea
+		return;
Michal Suchanek 91c0ea
+	else if (affinity_form == FORM1_AFFINITY) {
Michal Suchanek 91c0ea
+		const __be32 *associativity;
Michal Suchanek 91c0ea
+
Michal Suchanek 91c0ea
+		associativity = of_get_associativity(node);
Michal Suchanek 91c0ea
+		if (!associativity)
Michal Suchanek 91c0ea
+			return;
Michal Suchanek 91c0ea
+
Michal Suchanek 91c0ea
+		initialize_form1_numa_distance(associativity);
Michal Suchanek 91c0ea
+		return;
Michal Suchanek 91c0ea
+	}
Michal Suchanek 91c0ea
+}
Michal Suchanek 91c0ea
+
Michal Suchanek 91c0ea
 static int __init find_primary_domain_index(void)
Michal Suchanek 91c0ea
 {
Michal Suchanek 91c0ea
 	int index;
Michal Suchanek 91c0ea
@@ -433,6 +472,38 @@ static int of_get_assoc_arrays(struct assoc_arrays *aa)
Michal Suchanek 91c0ea
 	return 0;
Michal Suchanek 91c0ea
 }
Michal Suchanek 91c0ea
 
Michal Suchanek 91c0ea
+static int get_nid_and_numa_distance(struct drmem_lmb *lmb)
Michal Suchanek 91c0ea
+{
Michal Suchanek 91c0ea
+	struct assoc_arrays aa = { .arrays = NULL };
Michal Suchanek 91c0ea
+	int default_nid = NUMA_NO_NODE;
Michal Suchanek 91c0ea
+	int nid = default_nid;
Michal Suchanek 91c0ea
+	int rc, index;
Michal Suchanek 91c0ea
+
Michal Suchanek 91c0ea
+	if ((primary_domain_index < 0) || !numa_enabled)
Michal Suchanek 91c0ea
+		return default_nid;
Michal Suchanek 91c0ea
+
Michal Suchanek 91c0ea
+	rc = of_get_assoc_arrays(&aa);
Michal Suchanek 91c0ea
+	if (rc)
Michal Suchanek 91c0ea
+		return default_nid;
Michal Suchanek 91c0ea
+
Michal Suchanek 91c0ea
+	if (primary_domain_index <= aa.array_sz &&
Michal Suchanek 91c0ea
+	    !(lmb->flags & DRCONF_MEM_AI_INVALID) && lmb->aa_index < aa.n_arrays) {
Michal Suchanek 91c0ea
+		const __be32 *associativity;
Michal Suchanek 91c0ea
+
Michal Suchanek 91c0ea
+		index = lmb->aa_index * aa.array_sz;
Michal Suchanek 91c0ea
+		associativity = &aa.arrays[index];
Michal Suchanek 91c0ea
+		nid = __associativity_to_nid(associativity, aa.array_sz);
Michal Suchanek 91c0ea
+		if (nid > 0 && affinity_form == FORM1_AFFINITY) {
Michal Suchanek 91c0ea
+			/*
Michal Suchanek 91c0ea
+			 * lookup array associativity entries have
Michal Suchanek 91c0ea
+			 * no length of the array as the first element.
Michal Suchanek 91c0ea
+			 */
Michal Suchanek 91c0ea
+			__initialize_form1_numa_distance(associativity, aa.array_sz);
Michal Suchanek 91c0ea
+		}
Michal Suchanek 91c0ea
+	}
Michal Suchanek 91c0ea
+	return nid;
Michal Suchanek 91c0ea
+}
Michal Suchanek 91c0ea
+
Michal Suchanek 91c0ea
 /*
Michal Suchanek 91c0ea
  * This is like of_node_to_nid_single() for memory represented in the
Michal Suchanek 91c0ea
  * ibm,dynamic-reconfiguration-memory node.
Michal Suchanek 91c0ea
@@ -453,26 +524,19 @@ int of_drconf_to_nid_single(struct drmem_lmb *lmb)
Michal Suchanek 91c0ea
 
Michal Suchanek 91c0ea
 	if (primary_domain_index <= aa.array_sz &&
Michal Suchanek 91c0ea
 	    !(lmb->flags & DRCONF_MEM_AI_INVALID) && lmb->aa_index < aa.n_arrays) {
Michal Suchanek 91c0ea
-		index = lmb->aa_index * aa.array_sz + primary_domain_index - 1;
Michal Suchanek 91c0ea
-		nid = of_read_number(&aa.arrays[index], 1);
Michal Suchanek 91c0ea
-
Michal Suchanek 91c0ea
-		if (nid == 0xffff || nid >= nr_node_ids)
Michal Suchanek 91c0ea
-			nid = default_nid;
Michal Suchanek 91c0ea
+		const __be32 *associativity;
Michal Suchanek 91c0ea
 
Michal Suchanek 91c0ea
-		if (nid > 0) {
Michal Suchanek 91c0ea
-			index = lmb->aa_index * aa.array_sz;
Michal Suchanek 91c0ea
-			initialize_distance_lookup_table(nid,
Michal Suchanek 91c0ea
-							&aa.arrays[index]);
Michal Suchanek 91c0ea
-		}
Michal Suchanek 91c0ea
+		index = lmb->aa_index * aa.array_sz;
Michal Suchanek 91c0ea
+		associativity = &aa.arrays[index];
Michal Suchanek 91c0ea
+		nid = __associativity_to_nid(associativity, aa.array_sz);
Michal Suchanek 91c0ea
 	}
Michal Suchanek 91c0ea
-
Michal Suchanek 91c0ea
 	return nid;
Michal Suchanek 91c0ea
 }
Michal Suchanek 91c0ea
 
Michal Suchanek 91c0ea
 #ifdef CONFIG_PPC_SPLPAR
Michal Suchanek 91c0ea
-static int vphn_get_nid(long lcpu)
Michal Suchanek 91c0ea
+
Michal Suchanek 91c0ea
+static int __vphn_get_associativity(long lcpu, __be32 *associativity)
Michal Suchanek 91c0ea
 {
Michal Suchanek 91c0ea
-	__be32 associativity[VPHN_ASSOC_BUFSIZE] = {0};
Michal Suchanek 91c0ea
 	long rc, hwid;
Michal Suchanek 91c0ea
 
Michal Suchanek 91c0ea
 	/*
Michal Suchanek 91c0ea
@@ -492,12 +556,30 @@ static int vphn_get_nid(long lcpu)
Michal Suchanek 91c0ea
 
Michal Suchanek 91c0ea
 		rc = hcall_vphn(hwid, VPHN_FLAG_VCPU, associativity);
Michal Suchanek 91c0ea
 		if (rc == H_SUCCESS)
Michal Suchanek 91c0ea
-			return associativity_to_nid(associativity);
Michal Suchanek 91c0ea
+			return 0;
Michal Suchanek 91c0ea
 	}
Michal Suchanek 91c0ea
 
Michal Suchanek 91c0ea
+	return -1;
Michal Suchanek 91c0ea
+}
Michal Suchanek 91c0ea
+
Michal Suchanek 91c0ea
+static int vphn_get_nid(long lcpu)
Michal Suchanek 91c0ea
+{
Michal Suchanek 91c0ea
+	__be32 associativity[VPHN_ASSOC_BUFSIZE] = {0};
Michal Suchanek 91c0ea
+
Michal Suchanek 91c0ea
+
Michal Suchanek 91c0ea
+	if (!__vphn_get_associativity(lcpu, associativity))
Michal Suchanek 91c0ea
+		return associativity_to_nid(associativity);
Michal Suchanek 91c0ea
+
Michal Suchanek 91c0ea
 	return NUMA_NO_NODE;
Michal Suchanek 91c0ea
+
Michal Suchanek 91c0ea
 }
Michal Suchanek 91c0ea
 #else
Michal Suchanek 91c0ea
+
Michal Suchanek 91c0ea
+static int __vphn_get_associativity(long lcpu, __be32 *associativity)
Michal Suchanek 91c0ea
+{
Michal Suchanek 91c0ea
+	return -1;
Michal Suchanek 91c0ea
+}
Michal Suchanek 91c0ea
+
Michal Suchanek 91c0ea
 static int vphn_get_nid(long unused)
Michal Suchanek 91c0ea
 {
Michal Suchanek 91c0ea
 	return NUMA_NO_NODE;
Michal Suchanek 91c0ea
@@ -692,7 +774,7 @@ static int __init numa_setup_drmem_lmb(struct drmem_lmb *lmb,
Michal Suchanek 91c0ea
 			size = read_n_cells(n_mem_size_cells, usm);
Michal Suchanek 91c0ea
 		}
Michal Suchanek 91c0ea
 
Michal Suchanek 91c0ea
-		nid = of_drconf_to_nid_single(lmb);
Michal Suchanek 91c0ea
+		nid = get_nid_and_numa_distance(lmb);
Michal Suchanek 91c0ea
 		fake_numa_create_new_node(((base + size) >> PAGE_SHIFT),
Michal Suchanek 91c0ea
 					  &nid;;
Michal Suchanek 91c0ea
 		node_set_online(nid);
Michal Suchanek 91c0ea
@@ -709,6 +791,7 @@ static int __init parse_numa_properties(void)
Michal Suchanek 91c0ea
 	struct device_node *memory;
Michal Suchanek 91c0ea
 	int default_nid = 0;
Michal Suchanek 91c0ea
 	unsigned long i;
Michal Suchanek 91c0ea
+	const __be32 *associativity;
Michal Suchanek 91c0ea
 
Michal Suchanek 91c0ea
 	if (numa_enabled == 0) {
Michal Suchanek 91c0ea
 		printk(KERN_WARNING "NUMA disabled by user\n");
Michal Suchanek 91c0ea
@@ -734,18 +817,30 @@ static int __init parse_numa_properties(void)
Michal Suchanek 91c0ea
 	 * each node to be onlined must have NODE_DATA etc backing it.
Michal Suchanek 91c0ea
 	 */
Michal Suchanek 91c0ea
 	for_each_present_cpu(i) {
Michal Suchanek 91c0ea
+		__be32 vphn_assoc[VPHN_ASSOC_BUFSIZE];
Michal Suchanek 91c0ea
 		struct device_node *cpu;
Michal Suchanek 91c0ea
-		int nid = vphn_get_nid(i);
Michal Suchanek 91c0ea
+		int nid = NUMA_NO_NODE;
Michal Suchanek 91c0ea
 
Michal Suchanek 91c0ea
-		/*
Michal Suchanek 91c0ea
-		 * Don't fall back to default_nid yet -- we will plug
Michal Suchanek 91c0ea
-		 * cpus into nodes once the memory scan has discovered
Michal Suchanek 91c0ea
-		 * the topology.
Michal Suchanek 91c0ea
-		 */
Michal Suchanek 91c0ea
-		if (nid == NUMA_NO_NODE) {
Michal Suchanek 91c0ea
+		memset(vphn_assoc, 0, VPHN_ASSOC_BUFSIZE * sizeof(__be32));
Michal Suchanek 91c0ea
+
Michal Suchanek 91c0ea
+		if (__vphn_get_associativity(i, vphn_assoc) == 0) {
Michal Suchanek 91c0ea
+			nid = associativity_to_nid(vphn_assoc);
Michal Suchanek 91c0ea
+			initialize_form1_numa_distance(vphn_assoc);
Michal Suchanek 91c0ea
+		} else {
Michal Suchanek 91c0ea
+
Michal Suchanek 91c0ea
+			/*
Michal Suchanek 91c0ea
+			 * Don't fall back to default_nid yet -- we will plug
Michal Suchanek 91c0ea
+			 * cpus into nodes once the memory scan has discovered
Michal Suchanek 91c0ea
+			 * the topology.
Michal Suchanek 91c0ea
+			 */
Michal Suchanek 91c0ea
 			cpu = of_get_cpu_node(i, NULL);
Michal Suchanek 91c0ea
 			BUG_ON(!cpu);
Michal Suchanek 91c0ea
-			nid = of_node_to_nid_single(cpu);
Michal Suchanek 91c0ea
+
Michal Suchanek 91c0ea
+			associativity = of_get_associativity(cpu);
Michal Suchanek 91c0ea
+			if (associativity) {
Michal Suchanek 91c0ea
+				nid = associativity_to_nid(associativity);
Michal Suchanek 91c0ea
+				initialize_form1_numa_distance(associativity);
Michal Suchanek 91c0ea
+			}
Michal Suchanek 91c0ea
 			of_node_put(cpu);
Michal Suchanek 91c0ea
 		}
Michal Suchanek 91c0ea
 
Michal Suchanek 91c0ea
@@ -781,8 +876,11 @@ static int __init parse_numa_properties(void)
Michal Suchanek 91c0ea
 		 * have associativity properties.  If none, then
Michal Suchanek 91c0ea
 		 * everything goes to default_nid.
Michal Suchanek 91c0ea
 		 */
Michal Suchanek 91c0ea
-		nid = of_node_to_nid_single(memory);
Michal Suchanek 91c0ea
-		if (nid < 0)
Michal Suchanek 91c0ea
+		associativity = of_get_associativity(memory);
Michal Suchanek 91c0ea
+		if (associativity) {
Michal Suchanek 91c0ea
+			nid = associativity_to_nid(associativity);
Michal Suchanek 91c0ea
+			initialize_form1_numa_distance(associativity);
Michal Suchanek 91c0ea
+		} else
Michal Suchanek 91c0ea
 			nid = default_nid;
Michal Suchanek 91c0ea
 
Michal Suchanek 91c0ea
 		fake_numa_create_new_node(((start + size) >> PAGE_SHIFT), &nid;;
Michal Suchanek 91c0ea
diff --git a/arch/powerpc/platforms/pseries/hotplug-cpu.c b/arch/powerpc/platforms/pseries/hotplug-cpu.c
Michal Suchanek 91c0ea
index e1f224320102..1ef40ef699a6 100644
Michal Suchanek 91c0ea
--- a/arch/powerpc/platforms/pseries/hotplug-cpu.c
Michal Suchanek 91c0ea
+++ b/arch/powerpc/platforms/pseries/hotplug-cpu.c
Michal Suchanek 91c0ea
@@ -580,6 +580,8 @@ static ssize_t dlpar_cpu_add(u32 drc_index)
Michal Suchanek 91c0ea
 		return saved_rc;
Michal Suchanek 91c0ea
 	}
Michal Suchanek 91c0ea
 
Michal Suchanek 91c0ea
+	update_numa_distance(dn);
Michal Suchanek 91c0ea
+
Michal Suchanek 91c0ea
 	rc = dlpar_online_cpu(dn);
Michal Suchanek 91c0ea
 	if (rc) {
Michal Suchanek 91c0ea
 		saved_rc = rc;
Michal Suchanek 91c0ea
diff --git a/arch/powerpc/platforms/pseries/hotplug-memory.c b/arch/powerpc/platforms/pseries/hotplug-memory.c
Michal Suchanek 91c0ea
index 0beb3ca2b549..14fccd7b9c99 100644
Michal Suchanek 91c0ea
--- a/arch/powerpc/platforms/pseries/hotplug-memory.c
Michal Suchanek 91c0ea
+++ b/arch/powerpc/platforms/pseries/hotplug-memory.c
Michal Suchanek 91c0ea
@@ -180,6 +180,8 @@ static int update_lmb_associativity_index(struct drmem_lmb *lmb)
Michal Suchanek 91c0ea
 		return -ENODEV;
Michal Suchanek 91c0ea
 	}
Michal Suchanek 91c0ea
 
Michal Suchanek 91c0ea
+	update_numa_distance(lmb_node);
Michal Suchanek 91c0ea
+
Michal Suchanek 91c0ea
 	dr_node = of_find_node_by_path("/ibm,dynamic-reconfiguration-memory");
Michal Suchanek 91c0ea
 	if (!dr_node) {
Michal Suchanek 91c0ea
 		dlpar_free_cc_nodes(lmb_node);
Michal Suchanek 91c0ea
-- 
Michal Suchanek 91c0ea
2.40.0
Michal Suchanek 91c0ea