diff options
| author | Grant Likely <grant.likely@secretlab.ca> | 2010-01-29 05:04:33 -0700 | 
|---|---|---|
| committer | Grant Likely <grant.likely@secretlab.ca> | 2010-02-09 08:32:42 -0700 | 
| commit | fcdeb7fedf89f4bbc2e11959794968080cd8426e (patch) | |
| tree | b549ce78d381f6185d10395afdea9ce8f741fd40 /drivers/of/base.c | |
| parent | 580537140568caddbc8a727d4c2f238d38707f68 (diff) | |
| download | olio-linux-3.10-fcdeb7fedf89f4bbc2e11959794968080cd8426e.tar.xz olio-linux-3.10-fcdeb7fedf89f4bbc2e11959794968080cd8426e.zip  | |
of: merge of_attach_node() & of_detach_node()
Merge common code between PowerPC and Microblaze
Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
Tested-by: Wolfram Sang <w.sang@pengutronix.de>
Acked-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'drivers/of/base.c')
| -rw-r--r-- | drivers/of/base.c | 71 | 
1 files changed, 71 insertions, 0 deletions
diff --git a/drivers/of/base.c b/drivers/of/base.c index cf89ee6253f..2ce58be314a 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -870,3 +870,74 @@ int prom_update_property(struct device_node *np,  	return 0;  } + +#if defined(CONFIG_OF_DYNAMIC) +/* + * Support for dynamic device trees. + * + * On some platforms, the device tree can be manipulated at runtime. + * The routines in this section support adding, removing and changing + * device tree nodes. + */ + +/** + * of_attach_node - Plug a device node into the tree and global list. + */ +void of_attach_node(struct device_node *np) +{ +	unsigned long flags; + +	write_lock_irqsave(&devtree_lock, flags); +	np->sibling = np->parent->child; +	np->allnext = allnodes; +	np->parent->child = np; +	allnodes = np; +	write_unlock_irqrestore(&devtree_lock, flags); +} + +/** + * 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. + */ +void of_detach_node(struct device_node *np) +{ +	struct device_node *parent; +	unsigned long flags; + +	write_lock_irqsave(&devtree_lock, flags); + +	parent = np->parent; +	if (!parent) +		goto out_unlock; + +	if (allnodes == np) +		allnodes = np->allnext; +	else { +		struct device_node *prev; +		for (prev = allnodes; +		     prev->allnext != np; +		     prev = prev->allnext) +			; +		prev->allnext = np->allnext; +	} + +	if (parent->child == np) +		parent->child = np->sibling; +	else { +		struct device_node *prevsib; +		for (prevsib = np->parent->child; +		     prevsib->sibling != np; +		     prevsib = prevsib->sibling) +			; +		prevsib->sibling = np->sibling; +	} + +	of_node_set_flag(np, OF_DETACHED); + +out_unlock: +	write_unlock_irqrestore(&devtree_lock, flags); +} +#endif /* defined(CONFIG_OF_DYNAMIC) */ +  |