diff options
author | Pantelis Antoniou <pantelis.antoniou@konsulko.com> | 2014-07-04 19:58:46 +0300 |
---|---|---|
committer | Grant Likely <grant.likely@linaro.org> | 2014-07-16 08:16:52 -0600 |
commit | d8c50088417ebf61ad8b132caad20d10f7736034 (patch) | |
tree | 40f3105ec3c03601e22301f36d207362e6d1226e /drivers/of/dynamic.c | |
parent | 698433963b98d6de7b102c242805c99fda4fa1fb (diff) | |
download | linux-d8c50088417ebf61ad8b132caad20d10f7736034.tar.gz |
of: Create unlocked versions of node and property add/remove functions
The DT overlay code will need to manipulate nodes and properties while
already holding the devicetree lock, or on nodes that are not yet
attached to the tree, but the current helper functions don't allow that.
Extract the core behaviour from the accessors and create the following
unlocked variants.
The unlocked variants require either the lock to already be held or for
the nodes to be detached from the tree. Changes to live nodes will not
get updated in sysfs, so the caller must arrange for housekeeping to
take place after dropping the lock.
The new functions are: __of_add_property(), __of_remove_property(),
__of_update_property(), __of_attach_node() and __of_detach_node().
Signed-off-by: Pantelis Antoniou <pantelis.antoniou@konsulko.com>
[Remove unnecessary diff hunks and rewrite commit text]
Signed-off-by: Grant Likely <grant.likely@linaro.org>
Diffstat (limited to 'drivers/of/dynamic.c')
-rw-r--r-- | drivers/of/dynamic.c | 63 |
1 files changed, 34 insertions, 29 deletions
diff --git a/drivers/of/dynamic.c b/drivers/of/dynamic.c index e0c4c6e25980..75fcc66fcefd 100644 --- a/drivers/of/dynamic.c +++ b/drivers/of/dynamic.c @@ -94,6 +94,15 @@ int of_property_notify(int action, struct device_node *np, return of_reconfig_notify(action, &pr); } +void __of_attach_node(struct device_node *np) +{ + np->sibling = np->parent->child; + np->allnext = np->parent->allnext; + np->parent->allnext = np; + np->parent->child = np; + of_node_clear_flag(np, OF_DETACHED); +} + /** * of_attach_node() - Plug a device node into the tree and global list. */ @@ -107,46 +116,23 @@ int of_attach_node(struct device_node *np) return rc; raw_spin_lock_irqsave(&devtree_lock, flags); - np->sibling = np->parent->child; - np->allnext = np->parent->allnext; - np->parent->allnext = np; - np->parent->child = np; - of_node_clear_flag(np, OF_DETACHED); + __of_attach_node(np); raw_spin_unlock_irqrestore(&devtree_lock, flags); of_node_add(np); return 0; } -/** - * of_detach_node() - "Unplug" a node from the device tree. - * - * The caller must hold a reference to the node. The memory associated with - * the node is not freed until its refcount goes to zero. - */ -int of_detach_node(struct device_node *np) +void __of_detach_node(struct device_node *np) { struct device_node *parent; - unsigned long flags; - int rc = 0; - - rc = of_reconfig_notify(OF_RECONFIG_DETACH_NODE, np); - if (rc) - return rc; - raw_spin_lock_irqsave(&devtree_lock, flags); - - if (of_node_check_flag(np, OF_DETACHED)) { - /* someone already detached it */ - raw_spin_unlock_irqrestore(&devtree_lock, flags); - return rc; - } + if (WARN_ON(of_node_check_flag(np, OF_DETACHED))) + return; parent = np->parent; - if (!parent) { - raw_spin_unlock_irqrestore(&devtree_lock, flags); - return rc; - } + if (WARN_ON(!parent)) + return; if (of_allnodes == np) of_allnodes = np->allnext; @@ -171,6 +157,25 @@ int of_detach_node(struct device_node *np) } of_node_set_flag(np, OF_DETACHED); +} + +/** + * of_detach_node() - "Unplug" a node from the device tree. + * + * The caller must hold a reference to the node. The memory associated with + * the node is not freed until its refcount goes to zero. + */ +int of_detach_node(struct device_node *np) +{ + unsigned long flags; + int rc = 0; + + rc = of_reconfig_notify(OF_RECONFIG_DETACH_NODE, np); + if (rc) + return rc; + + raw_spin_lock_irqsave(&devtree_lock, flags); + __of_detach_node(np); raw_spin_unlock_irqrestore(&devtree_lock, flags); of_node_remove(np); |