diff options
author | Pantelis Antoniou <pantelis.antoniou@konsulko.com> | 2014-07-04 19:58:47 +0300 |
---|---|---|
committer | Grant Likely <grant.likely@linaro.org> | 2014-07-16 08:16:17 -0600 |
commit | 698433963b98d6de7b102c242805c99fda4fa1fb (patch) | |
tree | 05a223f160742f6659e47cd5accc245934c941ef /drivers/of/dynamic.c | |
parent | 6afc0dc381573559251de9a8259404f49e6aed14 (diff) |
OF: Utility helper functions for dynamic nodes
Introduce helper functions for working with the live DT tree,
all of them related to dynamically adding/removing nodes and
properties.
__of_prop_dup() copies a property dynamically
__of_node_alloc() creates an empty node
Bug fix about prop->len == 0 by Ionut Nicu <ioan.nicu.ext@nsn.com>
Signed-off-by: Pantelis Antoniou <pantelis.antoniou@konsulko.com>
[glikely: Added unittest for of_copy_property and dropped fine-grained allocations]
[glikely: removed name, type and phandle arguments from __of_node_alloc]
Signed-off-by: Grant Likely <grant.likely@linaro.org>
Diffstat (limited to 'drivers/of/dynamic.c')
-rw-r--r-- | drivers/of/dynamic.c | 77 |
1 files changed, 77 insertions, 0 deletions
diff --git a/drivers/of/dynamic.c b/drivers/of/dynamic.c index 125994330437..e0c4c6e25980 100644 --- a/drivers/of/dynamic.c +++ b/drivers/of/dynamic.c @@ -214,3 +214,80 @@ void of_node_release(struct kobject *kobj) kfree(node->data); kfree(node); } + +/** + * __of_prop_dup - Copy a property dynamically. + * @prop: Property to copy + * @allocflags: Allocation flags (typically pass GFP_KERNEL) + * + * Copy a property by dynamically allocating the memory of both the + * property stucture and the property name & contents. The property's + * flags have the OF_DYNAMIC bit set so that we can differentiate between + * dynamically allocated properties and not. + * Returns the newly allocated property or NULL on out of memory error. + */ +struct property *__of_prop_dup(const struct property *prop, gfp_t allocflags) +{ + struct property *new; + + new = kzalloc(sizeof(*new), allocflags); + if (!new) + return NULL; + + /* + * NOTE: There is no check for zero length value. + * In case of a boolean property This will allocate a value + * of zero bytes. We do this to work around the use + * of of_get_property() calls on boolean values. + */ + new->name = kstrdup(prop->name, allocflags); + new->value = kmemdup(prop->value, prop->length, allocflags); + new->length = prop->length; + if (!new->name || !new->value) + goto err_free; + + /* mark the property as dynamic */ + of_property_set_flag(new, OF_DYNAMIC); + + return new; + + err_free: + kfree(new->name); + kfree(new->value); + kfree(new); + return NULL; +} + +/** + * __of_node_alloc() - Create an empty device node dynamically. + * @full_name: Full name of the new device node + * @allocflags: Allocation flags (typically pass GFP_KERNEL) + * + * 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. + */ +struct device_node *__of_node_alloc(const char *full_name, gfp_t allocflags) +{ + struct device_node *node; + + node = kzalloc(sizeof(*node), allocflags); + if (!node) + return NULL; + + node->full_name = kstrdup(full_name, allocflags); + of_node_set_flag(node, OF_DYNAMIC); + of_node_set_flag(node, OF_DETACHED); + if (!node->full_name) + goto err_free; + + of_node_init(node); + + return node; + + err_free: + kfree(node->full_name); + kfree(node); + return NULL; +} |