summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/of/dynamic.c21
-rw-r--r--drivers/of/of_private.h3
-rw-r--r--drivers/of/overlay.c18
-rw-r--r--drivers/of/unittest.c6
4 files changed, 30 insertions, 18 deletions
diff --git a/drivers/of/dynamic.c b/drivers/of/dynamic.c
index 7bb33d22b4e2..f4f8ed9b5454 100644
--- a/drivers/of/dynamic.c
+++ b/drivers/of/dynamic.c
@@ -383,25 +383,24 @@ struct property *__of_prop_dup(const struct property *prop, gfp_t allocflags)
/**
* __of_node_dup() - Duplicate or create an empty device node dynamically.
- * @fmt: Format string (plus vargs) for new full name of the device node
+ * @np: if not NULL, contains properties to be duplicated in new node
+ * @full_name: string value to be duplicated into new node's full_name field
*
- * Create an device tree node, either by duplicating an empty node or by allocating
- * an empty one suitable for further modification. The node data are
- * dynamically allocated and all the node flags have the OF_DYNAMIC &
- * OF_DETACHED bits set. Returns the newly allocated node or NULL on out of
- * memory error.
+ * Create a device tree node, optionally duplicating the properties of
+ * another node. The node data are dynamically allocated and all the node
+ * flags have the OF_DYNAMIC & OF_DETACHED bits set.
+ *
+ * Returns the newly allocated node or NULL on out of memory error.
*/
-struct device_node *__of_node_dup(const struct device_node *np, const char *fmt, ...)
+struct device_node *__of_node_dup(const struct device_node *np,
+ const char *full_name)
{
- va_list vargs;
struct device_node *node;
node = kzalloc(sizeof(*node), GFP_KERNEL);
if (!node)
return NULL;
- va_start(vargs, fmt);
- node->full_name = kvasprintf(GFP_KERNEL, fmt, vargs);
- va_end(vargs);
+ node->full_name = kstrdup(full_name, GFP_KERNEL);
if (!node->full_name) {
kfree(node);
return NULL;
diff --git a/drivers/of/of_private.h b/drivers/of/of_private.h
index 0c609e7d0334..26bb31beb03e 100644
--- a/drivers/of/of_private.h
+++ b/drivers/of/of_private.h
@@ -104,7 +104,8 @@ extern void *__unflatten_device_tree(const void *blob,
* own the devtree lock or work on detached trees only.
*/
struct property *__of_prop_dup(const struct property *prop, gfp_t allocflags);
-__printf(2, 3) struct device_node *__of_node_dup(const struct device_node *np, const char *fmt, ...);
+struct device_node *__of_node_dup(const struct device_node *np,
+ const char *full_name);
struct device_node *__of_find_node_by_path(struct device_node *parent,
const char *path);
diff --git a/drivers/of/overlay.c b/drivers/of/overlay.c
index b930e05d1215..30d91f907026 100644
--- a/drivers/of/overlay.c
+++ b/drivers/of/overlay.c
@@ -312,7 +312,20 @@ static int add_changeset_property(struct overlay_changeset *ovcs,
* If @node has child nodes, add the children recursively via
* build_changeset_next_level().
*
- * NOTE: Multiple mods of created nodes not supported.
+ * NOTE_1: A live devicetree created from a flattened device tree (FDT) will
+ * not contain the full path in node->full_name. Thus an overlay
+ * created from an FDT also will not contain the full path in
+ * node->full_name. However, a live devicetree created from Open
+ * Firmware may have the full path in node->full_name.
+ *
+ * add_changeset_node() follows the FDT convention and does not include
+ * the full path in node->full_name. Even though it expects the overlay
+ * to not contain the full path, it uses kbasename() to remove the
+ * full path should it exist. It also uses kbasename() in comparisons
+ * to nodes in the live devicetree so that it can apply an overlay to
+ * a live devicetree created from Open Firmware.
+ *
+ * NOTE_2: Multiple mods of created nodes not supported.
* If more than one fragment contains a node that does not already exist
* in the live tree, then for each fragment of_changeset_attach_node()
* will add a changeset entry to add the node. When the changeset is
@@ -339,8 +352,7 @@ static int add_changeset_node(struct overlay_changeset *ovcs,
break;
if (!tchild) {
- tchild = __of_node_dup(node, "%pOF/%s",
- target_node, node_kbasename);
+ tchild = __of_node_dup(node, node_kbasename);
if (!tchild)
return -ENOMEM;
diff --git a/drivers/of/unittest.c b/drivers/of/unittest.c
index a17195fcaeda..62c8a8b8af2d 100644
--- a/drivers/of/unittest.c
+++ b/drivers/of/unittest.c
@@ -692,13 +692,13 @@ static void __init of_unittest_changeset(void)
struct device_node *n1, *n2, *n21, *nchangeset, *nremove, *parent, *np;
struct of_changeset chgset;
- n1 = __of_node_dup(NULL, "/testcase-data/changeset/n1");
+ n1 = __of_node_dup(NULL, "n1");
unittest(n1, "testcase setup failure\n");
- n2 = __of_node_dup(NULL, "/testcase-data/changeset/n2");
+ n2 = __of_node_dup(NULL, "n2");
unittest(n2, "testcase setup failure\n");
- n21 = __of_node_dup(NULL, "%s/%s", "/testcase-data/changeset/n2", "n21");
+ n21 = __of_node_dup(NULL, "n21");
unittest(n21, "testcase setup failure %p\n", n21);
nchangeset = of_find_node_by_path("/testcase-data/changeset");