aboutsummaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
authorMadhavan Srinivasan <maddy@linux.vnet.ibm.com>2017-06-22 17:45:18 +0530
committerStewart Smith <stewart@linux.vnet.ibm.com>2017-06-27 15:31:52 +1000
commit41444879ebb26a7242ec6a0ccb484279dff43977 (patch)
tree144b593eedb38e7c19edd77c6cafdb5d3b9b8b36 /core
parent3ae55cca0ea3609bd90f2208b492cda37abb1cfe (diff)
downloadskiboot-41444879ebb26a7242ec6a0ccb484279dff43977.zip
skiboot-41444879ebb26a7242ec6a0ccb484279dff43977.tar.gz
skiboot-41444879ebb26a7242ec6a0ccb484279dff43977.tar.bz2
dt: Add phandle fixup helpers
When there is a new device tree that needs to be added to the main dt of the opal (ex, IMC catalog dtb loaded from pnor partition), we need to check for the phandle values in the new incoming device tree before attaching it. Reason is that, incoming device tree could already have phandle values initialized for its nodes. Now, if we attach this new device tree to the main opal DT, we could potentially hit phandle duplicate error (since the phandles value usually start with 1). To avoid this, a new helper function dt_adjust_subtree_phandle() is added to scan the incoming device tree and update node "phandle" accordingly based on the opal "last_phandle" value. Add to this, helper function also supports updates of "properties" with in a node which may refer the "phandle" value in the incoming device tree. Helper function will also fix the "properties" field accordingly. Acked-by: Michael Neuling <mikey@neuling.org> Signed-off-by: Madhavan Srinivasan <maddy@linux.vnet.ibm.com> Signed-off-by: Stewart Smith <stewart@linux.vnet.ibm.com>
Diffstat (limited to 'core')
-rw-r--r--core/device.c38
-rw-r--r--core/test/run-device.c35
2 files changed, 71 insertions, 2 deletions
diff --git a/core/device.c b/core/device.c
index df0f4e9..fc1db56 100644
--- a/core/device.c
+++ b/core/device.c
@@ -1069,3 +1069,41 @@ bool dt_node_is_enabled(struct dt_node *node)
return p->len > 1 && p->prop[0] == 'o' && p->prop[1] == 'k';
}
+
+/*
+ * Function to fixup the phandle in the subtree.
+ */
+void dt_adjust_subtree_phandle(struct dt_node *dev,
+ const char** (get_properties_to_fix)(struct dt_node *n))
+{
+ struct dt_node *node;
+ struct dt_property *prop;
+ u32 phandle, max_phandle = 0, import_phandle = new_phandle();
+ const char **name;
+
+ dt_for_each_node(dev, node) {
+ const char **props_to_update;
+ node->phandle += import_phandle;
+
+ /*
+ * calculate max_phandle(new_tree), needed to update
+ * last_phandle.
+ */
+ if (node->phandle >= max_phandle)
+ max_phandle = node->phandle;
+
+ props_to_update = get_properties_to_fix(node);
+ if (!props_to_update)
+ continue;
+ for (name = props_to_update; *name != NULL; name++) {
+ prop = __dt_find_property(node, *name);
+ if (!prop)
+ continue;
+ phandle = dt_prop_get_u32(node, *name);
+ phandle += import_phandle;
+ memcpy((char *)&prop->prop, &phandle, prop->len);
+ }
+ }
+
+ set_last_phandle(max_phandle);
+}
diff --git a/core/test/run-device.c b/core/test/run-device.c
index 5939afc..1a4cb1e 100644
--- a/core/test/run-device.c
+++ b/core/test/run-device.c
@@ -33,6 +33,8 @@ static inline bool fake_is_rodata(const void *p)
#include "../device.c"
#include <assert.h>
#include "../../test/dt_common.c"
+const char *prop_to_fix[] = {"something", NULL};
+const char **props_to_fix(struct dt_node *node);
static void check_path(const struct dt_node *node, const char * expected_path)
{
@@ -87,18 +89,29 @@ static bool is_sorted(const struct dt_node *root)
return true;
}
+/*handler for phandle fixup test */
+const char **props_to_fix(struct dt_node *node)
+{
+ const struct dt_property *prop;
+
+ prop = dt_find_property(node, "something");
+ if (prop)
+ return prop_to_fix;
+
+ return NULL;
+}
int main(void)
{
struct dt_node *root, *c1, *c2, *gc1, *gc2, *gc3, *ggc1, *ggc2;
struct dt_node *addrs, *addr1, *addr2;
- struct dt_node *i;
+ struct dt_node *i, *subtree, *ev1, *ut1, *ut2;
const struct dt_property *p;
struct dt_property *p2;
unsigned int n;
char *s;
size_t sz;
- u32 phandle;
+ u32 phandle, ev1_ph, new_prop_ph;
root = dt_new_root("");
assert(!list_top(&root->properties, struct dt_property, list));
@@ -412,6 +425,24 @@ int main(void)
dt_free(root);
+ /* phandle fixup test */
+ subtree = dt_new_root("subtree");
+ ev1 = dt_new(subtree, "ev@1");
+ ev1_ph = ev1->phandle;
+ dt_new(ev1,"a@1");
+ dt_new(ev1,"a@2");
+ dt_new(ev1,"a@3");
+ ut1 = dt_new(subtree, "ut@1");
+ dt_add_property(ut1, "something", (const void *)&ev1->phandle, 4);
+ ut2 = dt_new(subtree, "ut@2");
+ dt_add_property(ut2, "something", (const void *)&ev1->phandle, 4);
+
+ dt_adjust_subtree_phandle(subtree, props_to_fix);
+ assert(!(ev1->phandle == ev1_ph));
+ new_prop_ph = dt_prop_get_u32(ut1, "something");
+ assert(!(new_prop_ph == ev1_ph));
+ new_prop_ph = dt_prop_get_u32(ut2, "something");
+ assert(!(new_prop_ph == ev1_ph));
return 0;
}