diff options
Diffstat (limited to 'drivers/of/dynamic.c')
-rw-r--r-- | drivers/of/dynamic.c | 40 |
1 files changed, 29 insertions, 11 deletions
diff --git a/drivers/of/dynamic.c b/drivers/of/dynamic.c index af1b1ecd6a3d..661ad2f5c00c 100644 --- a/drivers/of/dynamic.c +++ b/drivers/of/dynamic.c @@ -272,15 +272,16 @@ struct property *__of_prop_dup(const struct property *prop, gfp_t allocflags) } /** - * __of_node_alloc() - Create an empty device node dynamically. - * @full_name: Full name of the new device node + * __of_node_dup() - Duplicate or create an empty device node dynamically. + * @fmt: Format string (plus vargs) for new full name of the device node * - * Create an empty device tree node, 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 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. */ -struct device_node *__of_node_alloc(const char *fmt, ...) +struct device_node *__of_node_dup(const struct device_node *np, const char *fmt, ...) { va_list vargs; struct device_node *node; @@ -291,17 +292,34 @@ struct device_node *__of_node_alloc(const char *fmt, ...) va_start(vargs, fmt); node->full_name = kvasprintf(GFP_KERNEL, fmt, vargs); va_end(vargs); - if (!node->full_name) - goto err_free; + if (!node->full_name) { + kfree(node); + return NULL; + } of_node_set_flag(node, OF_DYNAMIC); of_node_set_flag(node, OF_DETACHED); of_node_init(node); + /* Iterate over and duplicate all properties */ + if (np) { + struct property *pp, *new_pp; + for_each_property_of_node(np, pp) { + new_pp = __of_prop_dup(pp, GFP_KERNEL); + if (!new_pp) + goto err_prop; + if (__of_add_property(node, new_pp)) { + kfree(new_pp->name); + kfree(new_pp->value); + kfree(new_pp); + goto err_prop; + } + } + } return node; - err_free: - kfree(node); + err_prop: + of_node_put(node); /* Frees the node and properties */ return NULL; } |