powerpc/pseries: Dynamic add entires to associativity lookup array
authorNathan Fontenot <nfont@linux.vnet.ibm.com>
Mon, 20 Jun 2016 14:01:38 +0000 (09:01 -0500)
committerMichael Ellerman <mpe@ellerman.id.au>
Fri, 15 Jul 2016 10:18:26 +0000 (20:18 +1000)
Dynamically add entries to the associativity lookup array

The ibm,associativity-lookup-arrays property may only contain
associativity arrays for LMBs present at boot time. When hotplug
adding a LMB its associativity array may not be in the associativity
lookup array, this patch adds the ability to add new entries to the
associativity lookup array.

Signed-off-by: Nathan Fontenot <nfont@linux.vnet.ibm.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
arch/powerpc/platforms/pseries/hotplug-memory.c

index 3dbc82b..08e51f6 100644 (file)
@@ -191,14 +191,74 @@ static int dlpar_update_device_tree_lmb(struct of_drconf_cell *lmb)
        return 0;
 }
 
+static u32 find_aa_index(struct device_node *dr_node,
+                        struct property *ala_prop, const u32 *lmb_assoc)
+{
+       u32 *assoc_arrays;
+       u32 aa_index;
+       int aa_arrays, aa_array_entries, aa_array_sz;
+       int i, index;
+
+       /*
+        * The ibm,associativity-lookup-arrays property is defined to be
+        * a 32-bit value specifying the number of associativity arrays
+        * followed by a 32-bitvalue specifying the number of entries per
+        * array, followed by the associativity arrays.
+        */
+       assoc_arrays = ala_prop->value;
+
+       aa_arrays = be32_to_cpu(assoc_arrays[0]);
+       aa_array_entries = be32_to_cpu(assoc_arrays[1]);
+       aa_array_sz = aa_array_entries * sizeof(u32);
+
+       aa_index = -1;
+       for (i = 0; i < aa_arrays; i++) {
+               index = (i * aa_array_entries) + 2;
+
+               if (memcmp(&assoc_arrays[index], &lmb_assoc[1], aa_array_sz))
+                       continue;
+
+               aa_index = i;
+               break;
+       }
+
+       if (aa_index == -1) {
+               struct property *new_prop;
+               u32 new_prop_size;
+
+               new_prop_size = ala_prop->length + aa_array_sz;
+               new_prop = dlpar_clone_property(ala_prop, new_prop_size);
+               if (!new_prop)
+                       return -1;
+
+               assoc_arrays = new_prop->value;
+
+               /* increment the number of entries in the lookup array */
+               assoc_arrays[0] = cpu_to_be32(aa_arrays + 1);
+
+               /* copy the new associativity into the lookup array */
+               index = aa_arrays * aa_array_entries + 2;
+               memcpy(&assoc_arrays[index], &lmb_assoc[1], aa_array_sz);
+
+               of_update_property(dr_node, new_prop);
+
+               /*
+                * The associativity lookup array index for this lmb is
+                * number of entries - 1 since we added its associativity
+                * to the end of the lookup array.
+                */
+               aa_index = be32_to_cpu(assoc_arrays[0]) - 1;
+       }
+
+       return aa_index;
+}
+
 static u32 lookup_lmb_associativity_index(struct of_drconf_cell *lmb)
 {
        struct device_node *parent, *lmb_node, *dr_node;
+       struct property *ala_prop;
        const u32 *lmb_assoc;
-       const u32 *assoc_arrays;
        u32 aa_index;
-       int aa_arrays, aa_array_entries, aa_array_sz;
-       int i;
 
        parent = of_find_node_by_path("/");
        if (!parent)
@@ -222,34 +282,15 @@ static u32 lookup_lmb_associativity_index(struct of_drconf_cell *lmb)
                return -ENODEV;
        }
 
-       assoc_arrays = of_get_property(dr_node,
-                                      "ibm,associativity-lookup-arrays",
-                                      NULL);
-       of_node_put(dr_node);
-       if (!assoc_arrays) {
+       ala_prop = of_find_property(dr_node, "ibm,associativity-lookup-arrays",
+                                   NULL);
+       if (!ala_prop) {
+               of_node_put(dr_node);
                dlpar_free_cc_nodes(lmb_node);
                return -ENODEV;
        }
 
-       /* The ibm,associativity-lookup-arrays property is defined to be
-        * a 32-bit value specifying the number of associativity arrays
-        * followed by a 32-bitvalue specifying the number of entries per
-        * array, followed by the associativity arrays.
-        */
-       aa_arrays = be32_to_cpu(assoc_arrays[0]);
-       aa_array_entries = be32_to_cpu(assoc_arrays[1]);
-       aa_array_sz = aa_array_entries * sizeof(u32);
-
-       aa_index = -1;
-       for (i = 0; i < aa_arrays; i++) {
-               int indx = (i * aa_array_entries) + 2;
-
-               if (memcmp(&assoc_arrays[indx], &lmb_assoc[1], aa_array_sz))
-                       continue;
-
-               aa_index = i;
-               break;
-       }
+       aa_index = find_aa_index(dr_node, ala_prop, lmb_assoc);
 
        dlpar_free_cc_nodes(lmb_node);
        return aa_index;