Instead of updating NUMA distance every time we lookup a node id
from the associativity property, add helpers that can be used
during boot which does this only once. Also remove the distance
update from node id lookup helpers.

Signed-off-by: Aneesh Kumar K.V <aneesh.ku...@linux.ibm.com>
---
 arch/powerpc/mm/numa.c | 135 +++++++++++++++++++++++++++--------------
 1 file changed, 88 insertions(+), 47 deletions(-)

diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c
index 645a95e3a7ea..c481f08d565b 100644
--- a/arch/powerpc/mm/numa.c
+++ b/arch/powerpc/mm/numa.c
@@ -208,22 +208,6 @@ int __node_distance(int a, int b)
 }
 EXPORT_SYMBOL(__node_distance);
 
-static void initialize_distance_lookup_table(int nid,
-               const __be32 *associativity)
-{
-       int i;
-
-       if (affinity_form != FORM1_AFFINITY)
-               return;
-
-       for (i = 0; i < max_associativity_domain_index; i++) {
-               const __be32 *entry;
-
-               entry = &associativity[be32_to_cpu(distance_ref_points[i]) - 1];
-               distance_lookup_table[nid][i] = of_read_number(entry, 1);
-       }
-}
-
 /*
  * Returns nid in the range [0..nr_node_ids], or -1 if no useful NUMA
  * info is found.
@@ -241,15 +225,6 @@ static int associativity_to_nid(const __be32 
*associativity)
        /* POWER4 LPAR uses 0xffff as invalid node */
        if (nid == 0xffff || nid >= nr_node_ids)
                nid = NUMA_NO_NODE;
-
-       if (nid > 0 &&
-               of_read_number(associativity, 1) >= 
max_associativity_domain_index) {
-               /*
-                * Skip the length field and send start of associativity array
-                */
-               initialize_distance_lookup_table(nid, associativity + 1);
-       }
-
 out:
        return nid;
 }
@@ -291,10 +266,13 @@ static void __initialize_form1_numa_distance(const __be32 
*associativity)
 {
        int i, nid;
 
+       if (affinity_form != FORM1_AFFINITY)
+               return;
+
        if (of_read_number(associativity, 1) >= primary_domain_index) {
                nid = of_read_number(&associativity[primary_domain_index], 1);
 
-               for (i = 0; i < max_domain_index; i++) {
+               for (i = 0; i < max_associativity_domain_index; i++) {
                        const __be32 *entry;
 
                        entry = 
&associativity[be32_to_cpu(distance_ref_points[i])];
@@ -474,6 +452,48 @@ static int of_get_assoc_arrays(struct assoc_arrays *aa)
        return 0;
 }
 
+static int get_nid_and_numa_distance(struct drmem_lmb *lmb)
+{
+       struct assoc_arrays aa = { .arrays = NULL };
+       int default_nid = NUMA_NO_NODE;
+       int nid = default_nid;
+       int rc, index;
+
+       if ((primary_domain_index < 0) || !numa_enabled)
+               return default_nid;
+
+       rc = of_get_assoc_arrays(&aa);
+       if (rc)
+               return default_nid;
+
+       if (primary_domain_index <= aa.array_sz &&
+           !(lmb->flags & DRCONF_MEM_AI_INVALID) && lmb->aa_index < 
aa.n_arrays) {
+               index = lmb->aa_index * aa.array_sz + primary_domain_index - 1;
+               nid = of_read_number(&aa.arrays[index], 1);
+
+               if (nid == 0xffff || nid >= nr_node_ids)
+                       nid = default_nid;
+               if (nid > 0 && affinity_form == FORM1_AFFINITY) {
+                       int i;
+                       const __be32 *associativity;
+
+                       index = lmb->aa_index * aa.array_sz;
+                       associativity = &aa.arrays[index];
+                       /*
+                        * lookup array associativity entries have different 
format
+                        * There is no length of the array as the first element.
+                        */
+                       for (i = 0; i < max_associativity_domain_index; i++) {
+                               const __be32 *entry;
+
+                               entry = 
&associativity[be32_to_cpu(distance_ref_points[i]) - 1];
+                               distance_lookup_table[nid][i] = 
of_read_number(entry, 1);
+                       }
+               }
+       }
+       return nid;
+}
+
 /*
  * This is like of_node_to_nid_single() for memory represented in the
  * ibm,dynamic-reconfiguration-memory node.
@@ -499,21 +519,14 @@ int of_drconf_to_nid_single(struct drmem_lmb *lmb)
 
                if (nid == 0xffff || nid >= nr_node_ids)
                        nid = default_nid;
-
-               if (nid > 0) {
-                       index = lmb->aa_index * aa.array_sz;
-                       initialize_distance_lookup_table(nid,
-                                                       &aa.arrays[index]);
-               }
        }
-
        return nid;
 }
 
 #ifdef CONFIG_PPC_SPLPAR
-static int vphn_get_nid(long lcpu)
+
+static int __vphn_get_associativity(long lcpu, __be32 *associativity)
 {
-       __be32 associativity[VPHN_ASSOC_BUFSIZE] = {0};
        long rc, hwid;
 
        /*
@@ -533,10 +546,22 @@ static int vphn_get_nid(long lcpu)
 
                rc = hcall_vphn(hwid, VPHN_FLAG_VCPU, associativity);
                if (rc == H_SUCCESS)
-                       return associativity_to_nid(associativity);
+                       return 0;
        }
 
+       return -1;
+}
+
+static int vphn_get_nid(long lcpu)
+{
+       __be32 associativity[VPHN_ASSOC_BUFSIZE] = {0};
+
+
+       if (!__vphn_get_associativity(lcpu, associativity))
+               return associativity_to_nid(associativity);
+
        return NUMA_NO_NODE;
+
 }
 #else
 static int vphn_get_nid(long unused)
@@ -733,7 +758,7 @@ static int __init numa_setup_drmem_lmb(struct drmem_lmb 
*lmb,
                        size = read_n_cells(n_mem_size_cells, usm);
                }
 
-               nid = of_drconf_to_nid_single(lmb);
+               nid = get_nid_and_numa_distance(lmb);
                fake_numa_create_new_node(((base + size) >> PAGE_SHIFT),
                                          &nid);
                node_set_online(nid);
@@ -750,6 +775,7 @@ static int __init parse_numa_properties(void)
        struct device_node *memory;
        int default_nid = 0;
        unsigned long i;
+       const __be32 *associativity;
 
        if (numa_enabled == 0) {
                printk(KERN_WARNING "NUMA disabled by user\n");
@@ -775,18 +801,30 @@ static int __init parse_numa_properties(void)
         * each node to be onlined must have NODE_DATA etc backing it.
         */
        for_each_present_cpu(i) {
+               __be32 vphn_assoc[VPHN_ASSOC_BUFSIZE];
                struct device_node *cpu;
-               int nid = vphn_get_nid(i);
+               int nid = NUMA_NO_NODE;
 
-               /*
-                * Don't fall back to default_nid yet -- we will plug
-                * cpus into nodes once the memory scan has discovered
-                * the topology.
-                */
-               if (nid == NUMA_NO_NODE) {
+               memset(vphn_assoc, 0, VPHN_ASSOC_BUFSIZE * sizeof(__be32));
+
+               if (__vphn_get_associativity(i, vphn_assoc) == 0) {
+                       nid = associativity_to_nid(vphn_assoc);
+                       __initialize_form1_numa_distance(vphn_assoc);
+               } else {
+
+                       /*
+                        * Don't fall back to default_nid yet -- we will plug
+                        * cpus into nodes once the memory scan has discovered
+                        * the topology.
+                        */
                        cpu = of_get_cpu_node(i, NULL);
                        BUG_ON(!cpu);
-                       nid = of_node_to_nid_single(cpu);
+
+                       associativity = of_get_associativity(cpu);
+                       if (associativity) {
+                               nid = associativity_to_nid(associativity);
+                               __initialize_form1_numa_distance(associativity);
+                       }
                        of_node_put(cpu);
                }
 
@@ -822,8 +860,11 @@ static int __init parse_numa_properties(void)
                 * have associativity properties.  If none, then
                 * everything goes to default_nid.
                 */
-               nid = of_node_to_nid_single(memory);
-               if (nid < 0)
+               associativity = of_get_associativity(memory);
+               if (associativity) {
+                       nid = associativity_to_nid(associativity);
+                       __initialize_form1_numa_distance(associativity);
+               } else
                        nid = default_nid;
 
                fake_numa_create_new_node(((start + size) >> PAGE_SHIFT), &nid);
-- 
2.31.1

Reply via email to