|
@@ -28,20 +28,19 @@
|
|
|
* Find a node with the give full name by recursively following any of
|
|
|
* the child node links.
|
|
|
*/
|
|
|
-static struct device_node *__of_find_node_by_full_name(struct device_node *node,
|
|
|
+static struct device_node *find_node_by_full_name(struct device_node *node,
|
|
|
const char *full_name)
|
|
|
{
|
|
|
struct device_node *child, *found;
|
|
|
|
|
|
- if (node == NULL)
|
|
|
+ if (!node)
|
|
|
return NULL;
|
|
|
|
|
|
- /* check */
|
|
|
- if (of_node_cmp(node->full_name, full_name) == 0)
|
|
|
+ if (!of_node_cmp(node->full_name, full_name))
|
|
|
return of_node_get(node);
|
|
|
|
|
|
for_each_child_of_node(node, child) {
|
|
|
- found = __of_find_node_by_full_name(child, full_name);
|
|
|
+ found = find_node_by_full_name(child, full_name);
|
|
|
if (found != NULL) {
|
|
|
of_node_put(child);
|
|
|
return found;
|
|
@@ -51,16 +50,12 @@ static struct device_node *__of_find_node_by_full_name(struct device_node *node,
|
|
|
return NULL;
|
|
|
}
|
|
|
|
|
|
-/*
|
|
|
- * Find live tree's maximum phandle value.
|
|
|
- */
|
|
|
-static phandle of_get_tree_max_phandle(void)
|
|
|
+static phandle live_tree_max_phandle(void)
|
|
|
{
|
|
|
struct device_node *node;
|
|
|
phandle phandle;
|
|
|
unsigned long flags;
|
|
|
|
|
|
- /* now search recursively */
|
|
|
raw_spin_lock_irqsave(&devtree_lock, flags);
|
|
|
phandle = 0;
|
|
|
for_each_of_allnodes(node) {
|
|
@@ -73,131 +68,102 @@ static phandle of_get_tree_max_phandle(void)
|
|
|
return phandle;
|
|
|
}
|
|
|
|
|
|
-/*
|
|
|
- * Adjust a subtree's phandle values by a given delta.
|
|
|
- * Makes sure not to just adjust the device node's phandle value,
|
|
|
- * but modify the phandle properties values as well.
|
|
|
- */
|
|
|
-static void __of_adjust_tree_phandles(struct device_node *node,
|
|
|
+static void adjust_overlay_phandles(struct device_node *overlay,
|
|
|
int phandle_delta)
|
|
|
{
|
|
|
struct device_node *child;
|
|
|
struct property *prop;
|
|
|
phandle phandle;
|
|
|
|
|
|
- /* first adjust the node's phandle direct value */
|
|
|
- if (node->phandle != 0 && node->phandle != OF_PHANDLE_ILLEGAL)
|
|
|
- node->phandle += phandle_delta;
|
|
|
+ /* adjust node's phandle in node */
|
|
|
+ if (overlay->phandle != 0 && overlay->phandle != OF_PHANDLE_ILLEGAL)
|
|
|
+ overlay->phandle += phandle_delta;
|
|
|
|
|
|
- /* now adjust phandle & linux,phandle values */
|
|
|
- for_each_property_of_node(node, prop) {
|
|
|
+ /* copy adjusted phandle into *phandle properties */
|
|
|
+ for_each_property_of_node(overlay, prop) {
|
|
|
|
|
|
- /* only look for these two */
|
|
|
- if (of_prop_cmp(prop->name, "phandle") != 0 &&
|
|
|
- of_prop_cmp(prop->name, "linux,phandle") != 0)
|
|
|
+ if (of_prop_cmp(prop->name, "phandle") &&
|
|
|
+ of_prop_cmp(prop->name, "linux,phandle"))
|
|
|
continue;
|
|
|
|
|
|
- /* must be big enough */
|
|
|
if (prop->length < 4)
|
|
|
continue;
|
|
|
|
|
|
- /* read phandle value */
|
|
|
phandle = be32_to_cpup(prop->value);
|
|
|
- if (phandle == OF_PHANDLE_ILLEGAL) /* unresolved */
|
|
|
+ if (phandle == OF_PHANDLE_ILLEGAL)
|
|
|
continue;
|
|
|
|
|
|
- /* adjust */
|
|
|
- *(uint32_t *)prop->value = cpu_to_be32(node->phandle);
|
|
|
+ *(uint32_t *)prop->value = cpu_to_be32(overlay->phandle);
|
|
|
}
|
|
|
|
|
|
- /* now do the children recursively */
|
|
|
- for_each_child_of_node(node, child)
|
|
|
- __of_adjust_tree_phandles(child, phandle_delta);
|
|
|
+ for_each_child_of_node(overlay, child)
|
|
|
+ adjust_overlay_phandles(child, phandle_delta);
|
|
|
}
|
|
|
|
|
|
-static int __of_adjust_phandle_ref(struct device_node *node,
|
|
|
- struct property *rprop, int value)
|
|
|
+static int update_usages_of_a_phandle_reference(struct device_node *overlay,
|
|
|
+ struct property *prop_fixup, phandle phandle)
|
|
|
{
|
|
|
- phandle phandle;
|
|
|
struct device_node *refnode;
|
|
|
- struct property *sprop;
|
|
|
- char *propval, *propcur, *propend, *nodestr, *propstr, *s;
|
|
|
- int offset, propcurlen;
|
|
|
+ struct property *prop;
|
|
|
+ char *value, *cur, *end, *node_path, *prop_name, *s;
|
|
|
+ int offset, len;
|
|
|
int err = 0;
|
|
|
|
|
|
- /* make a copy */
|
|
|
- propval = kmalloc(rprop->length, GFP_KERNEL);
|
|
|
- if (!propval) {
|
|
|
- pr_err("%s: Could not copy value of '%s'\n",
|
|
|
- __func__, rprop->name);
|
|
|
+ value = kmalloc(prop_fixup->length, GFP_KERNEL);
|
|
|
+ if (!value)
|
|
|
return -ENOMEM;
|
|
|
- }
|
|
|
- memcpy(propval, rprop->value, rprop->length);
|
|
|
+ memcpy(value, prop_fixup->value, prop_fixup->length);
|
|
|
|
|
|
- propend = propval + rprop->length;
|
|
|
- for (propcur = propval; propcur < propend; propcur += propcurlen + 1) {
|
|
|
- propcurlen = strlen(propcur);
|
|
|
+ /* prop_fixup contains a list of tuples of path:property_name:offset */
|
|
|
+ end = value + prop_fixup->length;
|
|
|
+ for (cur = value; cur < end; cur += len + 1) {
|
|
|
+ len = strlen(cur);
|
|
|
|
|
|
- nodestr = propcur;
|
|
|
- s = strchr(propcur, ':');
|
|
|
+ node_path = cur;
|
|
|
+ s = strchr(cur, ':');
|
|
|
if (!s) {
|
|
|
- pr_err("%s: Illegal symbol entry '%s' (1)\n",
|
|
|
- __func__, propcur);
|
|
|
err = -EINVAL;
|
|
|
goto err_fail;
|
|
|
}
|
|
|
*s++ = '\0';
|
|
|
|
|
|
- propstr = s;
|
|
|
+ prop_name = s;
|
|
|
s = strchr(s, ':');
|
|
|
if (!s) {
|
|
|
- pr_err("%s: Illegal symbol entry '%s' (2)\n",
|
|
|
- __func__, (char *)rprop->value);
|
|
|
err = -EINVAL;
|
|
|
goto err_fail;
|
|
|
}
|
|
|
-
|
|
|
*s++ = '\0';
|
|
|
+
|
|
|
err = kstrtoint(s, 10, &offset);
|
|
|
- if (err != 0) {
|
|
|
- pr_err("%s: Could get offset '%s'\n",
|
|
|
- __func__, (char *)rprop->value);
|
|
|
+ if (err)
|
|
|
goto err_fail;
|
|
|
- }
|
|
|
|
|
|
- /* look into the resolve node for the full path */
|
|
|
- refnode = __of_find_node_by_full_name(node, nodestr);
|
|
|
- if (!refnode) {
|
|
|
- pr_warn("%s: Could not find refnode '%s'\n",
|
|
|
- __func__, (char *)rprop->value);
|
|
|
+ refnode = find_node_by_full_name(overlay, node_path);
|
|
|
+ if (!refnode)
|
|
|
continue;
|
|
|
- }
|
|
|
|
|
|
- /* now find the property */
|
|
|
- for_each_property_of_node(refnode, sprop) {
|
|
|
- if (of_prop_cmp(sprop->name, propstr) == 0)
|
|
|
+ for_each_property_of_node(refnode, prop) {
|
|
|
+ if (!of_prop_cmp(prop->name, prop_name))
|
|
|
break;
|
|
|
}
|
|
|
of_node_put(refnode);
|
|
|
|
|
|
- if (!sprop) {
|
|
|
- pr_err("%s: Could not find property '%s'\n",
|
|
|
- __func__, (char *)rprop->value);
|
|
|
+ if (!prop) {
|
|
|
err = -ENOENT;
|
|
|
goto err_fail;
|
|
|
}
|
|
|
|
|
|
- phandle = value;
|
|
|
- *(__be32 *)(sprop->value + offset) = cpu_to_be32(phandle);
|
|
|
+ *(__be32 *)(prop->value + offset) = cpu_to_be32(phandle);
|
|
|
}
|
|
|
|
|
|
err_fail:
|
|
|
- kfree(propval);
|
|
|
+ kfree(value);
|
|
|
return err;
|
|
|
}
|
|
|
|
|
|
/* compare nodes taking into account that 'name' strips out the @ part */
|
|
|
-static int __of_node_name_cmp(const struct device_node *dn1,
|
|
|
+static int node_name_cmp(const struct device_node *dn1,
|
|
|
const struct device_node *dn2)
|
|
|
{
|
|
|
const char *n1 = strrchr(dn1->full_name, '/') ? : "/";
|
|
@@ -208,85 +174,77 @@ static int __of_node_name_cmp(const struct device_node *dn1,
|
|
|
|
|
|
/*
|
|
|
* Adjust the local phandle references by the given phandle delta.
|
|
|
- * Assumes the existances of a __local_fixups__ node at the root.
|
|
|
- * Assumes that __of_verify_tree_phandle_references has been called.
|
|
|
- * Does not take any devtree locks so make sure you call this on a tree
|
|
|
- * which is at the detached state.
|
|
|
+ *
|
|
|
+ * Subtree @local_fixups, which is overlay node __local_fixups__,
|
|
|
+ * mirrors the fragment node structure at the root of the overlay.
|
|
|
+ *
|
|
|
+ * For each property in the fragments that contains a phandle reference,
|
|
|
+ * @local_fixups has a property of the same name that contains a list
|
|
|
+ * of offsets of the phandle reference(s) within the respective property
|
|
|
+ * value(s). The values at these offsets will be fixed up.
|
|
|
*/
|
|
|
-static int __of_adjust_tree_phandle_references(struct device_node *node,
|
|
|
- struct device_node *target, int phandle_delta)
|
|
|
+static int adjust_local_phandle_references(struct device_node *local_fixups,
|
|
|
+ struct device_node *overlay, int phandle_delta)
|
|
|
{
|
|
|
- struct device_node *child, *childtarget;
|
|
|
- struct property *rprop, *sprop;
|
|
|
+ struct device_node *child, *overlay_child;
|
|
|
+ struct property *prop_fix, *prop;
|
|
|
int err, i, count;
|
|
|
unsigned int off;
|
|
|
phandle phandle;
|
|
|
|
|
|
- if (node == NULL)
|
|
|
+ if (!local_fixups)
|
|
|
return 0;
|
|
|
|
|
|
- for_each_property_of_node(node, rprop) {
|
|
|
+ for_each_property_of_node(local_fixups, prop_fix) {
|
|
|
|
|
|
/* skip properties added automatically */
|
|
|
- if (of_prop_cmp(rprop->name, "name") == 0 ||
|
|
|
- of_prop_cmp(rprop->name, "phandle") == 0 ||
|
|
|
- of_prop_cmp(rprop->name, "linux,phandle") == 0)
|
|
|
+ if (!of_prop_cmp(prop_fix->name, "name") ||
|
|
|
+ !of_prop_cmp(prop_fix->name, "phandle") ||
|
|
|
+ !of_prop_cmp(prop_fix->name, "linux,phandle"))
|
|
|
continue;
|
|
|
|
|
|
- if ((rprop->length % 4) != 0 || rprop->length == 0) {
|
|
|
- pr_err("%s: Illegal property (size) '%s' @%s\n",
|
|
|
- __func__, rprop->name, node->full_name);
|
|
|
+ if ((prop_fix->length % 4) != 0 || prop_fix->length == 0)
|
|
|
return -EINVAL;
|
|
|
- }
|
|
|
- count = rprop->length / sizeof(__be32);
|
|
|
+ count = prop_fix->length / sizeof(__be32);
|
|
|
|
|
|
- /* now find the target property */
|
|
|
- for_each_property_of_node(target, sprop) {
|
|
|
- if (of_prop_cmp(sprop->name, rprop->name) == 0)
|
|
|
+ for_each_property_of_node(overlay, prop) {
|
|
|
+ if (!of_prop_cmp(prop->name, prop_fix->name))
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
- if (sprop == NULL) {
|
|
|
- pr_err("%s: Could not find target property '%s' @%s\n",
|
|
|
- __func__, rprop->name, node->full_name);
|
|
|
+ if (!prop)
|
|
|
return -EINVAL;
|
|
|
- }
|
|
|
|
|
|
for (i = 0; i < count; i++) {
|
|
|
- off = be32_to_cpu(((__be32 *)rprop->value)[i]);
|
|
|
- /* make sure the offset doesn't overstep (even wrap) */
|
|
|
- if (off >= sprop->length ||
|
|
|
- (off + 4) > sprop->length) {
|
|
|
- pr_err("%s: Illegal property '%s' @%s\n",
|
|
|
- __func__, rprop->name,
|
|
|
- node->full_name);
|
|
|
+ off = be32_to_cpu(((__be32 *)prop_fix->value)[i]);
|
|
|
+ if ((off + 4) > prop->length)
|
|
|
return -EINVAL;
|
|
|
- }
|
|
|
-
|
|
|
- if (phandle_delta) {
|
|
|
- /* adjust */
|
|
|
- phandle = be32_to_cpu(*(__be32 *)(sprop->value + off));
|
|
|
- phandle += phandle_delta;
|
|
|
- *(__be32 *)(sprop->value + off) = cpu_to_be32(phandle);
|
|
|
- }
|
|
|
+
|
|
|
+ phandle = be32_to_cpu(*(__be32 *)(prop->value + off));
|
|
|
+ phandle += phandle_delta;
|
|
|
+ *(__be32 *)(prop->value + off) = cpu_to_be32(phandle);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- for_each_child_of_node(node, child) {
|
|
|
-
|
|
|
- for_each_child_of_node(target, childtarget)
|
|
|
- if (__of_node_name_cmp(child, childtarget) == 0)
|
|
|
+ /*
|
|
|
+ * These nested loops recurse down two subtrees in parallel, where the
|
|
|
+ * node names in the two subtrees match.
|
|
|
+ *
|
|
|
+ * The roots of the subtrees are the overlay's __local_fixups__ node
|
|
|
+ * and the overlay's root node.
|
|
|
+ */
|
|
|
+ for_each_child_of_node(local_fixups, child) {
|
|
|
+
|
|
|
+ for_each_child_of_node(overlay, overlay_child)
|
|
|
+ if (!node_name_cmp(child, overlay_child))
|
|
|
break;
|
|
|
|
|
|
- if (!childtarget) {
|
|
|
- pr_err("%s: Could not find target child '%s' @%s\n",
|
|
|
- __func__, child->name, node->full_name);
|
|
|
+ if (!overlay_child)
|
|
|
return -EINVAL;
|
|
|
- }
|
|
|
|
|
|
- err = __of_adjust_tree_phandle_references(child, childtarget,
|
|
|
+ err = adjust_local_phandle_references(child, overlay_child,
|
|
|
phandle_delta);
|
|
|
- if (err != 0)
|
|
|
+ if (err)
|
|
|
return err;
|
|
|
}
|
|
|
|
|
@@ -294,111 +252,103 @@ static int __of_adjust_tree_phandle_references(struct device_node *node,
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * of_resolve - Resolve the given node against the live tree.
|
|
|
+ * of_resolve_phandles - Relocate and resolve overlay against live tree
|
|
|
*
|
|
|
- * @resolve: Node to resolve
|
|
|
+ * @overlay: Pointer to devicetree overlay to relocate and resolve
|
|
|
*
|
|
|
- * Perform dynamic Device Tree resolution against the live tree
|
|
|
- * to the given node to resolve. This depends on the live tree
|
|
|
- * having a __symbols__ node, and the resolve node the __fixups__ &
|
|
|
- * __local_fixups__ nodes (if needed).
|
|
|
- * The result of the operation is a resolve node that it's contents
|
|
|
- * are fit to be inserted or operate upon the live tree.
|
|
|
- * Returns 0 on success or a negative error value on error.
|
|
|
+ * Modify (relocate) values of local phandles in @overlay to a range that
|
|
|
+ * does not conflict with the live expanded devicetree. Update references
|
|
|
+ * to the local phandles in @overlay. Update (resolve) phandle references
|
|
|
+ * in @overlay that refer to the live expanded devicetree.
|
|
|
+ *
|
|
|
+ * Phandle values in the live tree are in the range of
|
|
|
+ * 1 .. live_tree_max_phandle(). The range of phandle values in the overlay
|
|
|
+ * also begin with at 1. Adjust the phandle values in the overlay to begin
|
|
|
+ * at live_tree_max_phandle() + 1. Update references to the phandles to
|
|
|
+ * the adjusted phandle values.
|
|
|
+ *
|
|
|
+ * The name of each property in the "__fixups__" node in the overlay matches
|
|
|
+ * the name of a symbol (a label) in the live tree. The values of each
|
|
|
+ * property in the "__fixups__" node is a list of the property values in the
|
|
|
+ * overlay that need to be updated to contain the phandle reference
|
|
|
+ * corresponding to that symbol in the live tree. Update the references in
|
|
|
+ * the overlay with the phandle values in the live tree.
|
|
|
+ *
|
|
|
+ * @overlay must be detached.
|
|
|
+ *
|
|
|
+ * Resolving and applying @overlay to the live expanded devicetree must be
|
|
|
+ * protected by a mechanism to ensure that multiple overlays are processed
|
|
|
+ * in a single threaded manner so that multiple overlays will not relocate
|
|
|
+ * phandles to overlapping ranges. The mechanism to enforce this is not
|
|
|
+ * yet implemented.
|
|
|
+ *
|
|
|
+ * Return: %0 on success or a negative error value on error.
|
|
|
*/
|
|
|
-int of_resolve_phandles(struct device_node *resolve)
|
|
|
+int of_resolve_phandles(struct device_node *overlay)
|
|
|
{
|
|
|
- struct device_node *child, *childroot, *refnode;
|
|
|
- struct device_node *root_sym, *resolve_sym, *resolve_fix;
|
|
|
- struct property *rprop;
|
|
|
+ struct device_node *child, *local_fixups, *refnode;
|
|
|
+ struct device_node *tree_symbols, *overlay_fixups;
|
|
|
+ struct property *prop;
|
|
|
const char *refpath;
|
|
|
phandle phandle, phandle_delta;
|
|
|
int err;
|
|
|
|
|
|
- if (!resolve)
|
|
|
- pr_err("%s: null node\n", __func__);
|
|
|
- if (resolve && !of_node_check_flag(resolve, OF_DETACHED))
|
|
|
- pr_err("%s: node %s not detached\n", __func__,
|
|
|
- resolve->full_name);
|
|
|
- /* the resolve node must exist, and be detached */
|
|
|
- if (!resolve || !of_node_check_flag(resolve, OF_DETACHED))
|
|
|
- return -EINVAL;
|
|
|
-
|
|
|
- /* first we need to adjust the phandles */
|
|
|
- phandle_delta = of_get_tree_max_phandle() + 1;
|
|
|
- __of_adjust_tree_phandles(resolve, phandle_delta);
|
|
|
-
|
|
|
- /* locate the local fixups */
|
|
|
- childroot = NULL;
|
|
|
- for_each_child_of_node(resolve, childroot)
|
|
|
- if (of_node_cmp(childroot->name, "__local_fixups__") == 0)
|
|
|
- break;
|
|
|
-
|
|
|
- if (childroot != NULL) {
|
|
|
- /* resolve root is guaranteed to be the '/' */
|
|
|
- err = __of_adjust_tree_phandle_references(childroot,
|
|
|
- resolve, 0);
|
|
|
- if (err != 0)
|
|
|
- return err;
|
|
|
+ tree_symbols = NULL;
|
|
|
|
|
|
- BUG_ON(__of_adjust_tree_phandle_references(childroot,
|
|
|
- resolve, phandle_delta));
|
|
|
+ if (!overlay) {
|
|
|
+ pr_err("null overlay\n");
|
|
|
+ err = -EINVAL;
|
|
|
+ goto out;
|
|
|
+ }
|
|
|
+ if (!of_node_check_flag(overlay, OF_DETACHED)) {
|
|
|
+ pr_err("overlay not detached\n");
|
|
|
+ err = -EINVAL;
|
|
|
+ goto out;
|
|
|
}
|
|
|
|
|
|
- root_sym = NULL;
|
|
|
- resolve_sym = NULL;
|
|
|
- resolve_fix = NULL;
|
|
|
-
|
|
|
- /* this may fail (if no fixups are required) */
|
|
|
- root_sym = of_find_node_by_path("/__symbols__");
|
|
|
+ phandle_delta = live_tree_max_phandle() + 1;
|
|
|
+ adjust_overlay_phandles(overlay, phandle_delta);
|
|
|
|
|
|
- /* locate the symbols & fixups nodes on resolve */
|
|
|
- for_each_child_of_node(resolve, child) {
|
|
|
+ for_each_child_of_node(overlay, local_fixups)
|
|
|
+ if (!of_node_cmp(local_fixups->name, "__local_fixups__"))
|
|
|
+ break;
|
|
|
|
|
|
- if (!resolve_sym &&
|
|
|
- of_node_cmp(child->name, "__symbols__") == 0)
|
|
|
- resolve_sym = child;
|
|
|
+ err = adjust_local_phandle_references(local_fixups, overlay, phandle_delta);
|
|
|
+ if (err)
|
|
|
+ goto out;
|
|
|
|
|
|
- if (!resolve_fix &&
|
|
|
- of_node_cmp(child->name, "__fixups__") == 0)
|
|
|
- resolve_fix = child;
|
|
|
+ overlay_fixups = NULL;
|
|
|
|
|
|
- /* both found, don't bother anymore */
|
|
|
- if (resolve_sym && resolve_fix)
|
|
|
- break;
|
|
|
+ for_each_child_of_node(overlay, child) {
|
|
|
+ if (!of_node_cmp(child->name, "__fixups__"))
|
|
|
+ overlay_fixups = child;
|
|
|
}
|
|
|
|
|
|
- /* we do allow for the case where no fixups are needed */
|
|
|
- if (!resolve_fix) {
|
|
|
- err = 0; /* no error */
|
|
|
+ if (!overlay_fixups) {
|
|
|
+ err = 0;
|
|
|
goto out;
|
|
|
}
|
|
|
|
|
|
- /* we need to fixup, but no root symbols... */
|
|
|
- if (!root_sym) {
|
|
|
- pr_err("%s: no symbols in root of device tree.\n", __func__);
|
|
|
+ tree_symbols = of_find_node_by_path("/__symbols__");
|
|
|
+ if (!tree_symbols) {
|
|
|
+ pr_err("no symbols in root of device tree.\n");
|
|
|
err = -EINVAL;
|
|
|
goto out;
|
|
|
}
|
|
|
|
|
|
- for_each_property_of_node(resolve_fix, rprop) {
|
|
|
+ for_each_property_of_node(overlay_fixups, prop) {
|
|
|
|
|
|
/* skip properties added automatically */
|
|
|
- if (of_prop_cmp(rprop->name, "name") == 0)
|
|
|
+ if (!of_prop_cmp(prop->name, "name"))
|
|
|
continue;
|
|
|
|
|
|
- err = of_property_read_string(root_sym,
|
|
|
- rprop->name, &refpath);
|
|
|
- if (err != 0) {
|
|
|
- pr_err("%s: Could not find symbol '%s'\n",
|
|
|
- __func__, rprop->name);
|
|
|
+ err = of_property_read_string(tree_symbols,
|
|
|
+ prop->name, &refpath);
|
|
|
+ if (err)
|
|
|
goto out;
|
|
|
- }
|
|
|
|
|
|
refnode = of_find_node_by_path(refpath);
|
|
|
if (!refnode) {
|
|
|
- pr_err("%s: Could not find node by path '%s'\n",
|
|
|
- __func__, refpath);
|
|
|
err = -ENOENT;
|
|
|
goto out;
|
|
|
}
|
|
@@ -406,17 +356,15 @@ int of_resolve_phandles(struct device_node *resolve)
|
|
|
phandle = refnode->phandle;
|
|
|
of_node_put(refnode);
|
|
|
|
|
|
- pr_debug("%s: %s phandle is 0x%08x\n",
|
|
|
- __func__, rprop->name, phandle);
|
|
|
-
|
|
|
- err = __of_adjust_phandle_ref(resolve, rprop, phandle);
|
|
|
+ err = update_usages_of_a_phandle_reference(overlay, prop, phandle);
|
|
|
if (err)
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
out:
|
|
|
- /* NULL is handled by of_node_put as NOP */
|
|
|
- of_node_put(root_sym);
|
|
|
+ if (err)
|
|
|
+ pr_err("overlay phandle fixup failed: %d\n", err);
|
|
|
+ of_node_put(tree_symbols);
|
|
|
|
|
|
return err;
|
|
|
}
|