aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/of/base.c
diff options
context:
space:
mode:
authorPantelis Antoniou <panto@antoniou-consulting.com>2013-12-13 13:08:59 -0500
committerGrant Likely <grant.likely@linaro.org>2014-03-19 10:58:40 -0400
commit0829f6d1f69e4f2fae4062987ae6531a9af1a2e3 (patch)
tree4081a4bee4a9e193b4de690735b5a3782d100eac /drivers/of/base.c
parent8357041a69b368991d1b04d9f1d297f8d71e1314 (diff)
of: device_node kobject lifecycle fixes
After the move to having device nodes be proper kobjects the lifecycle of the node needs to be controlled better. At first convert of_add_node() in the unflattened functions to of_init_node() which initializes the kobject so that of_node_get/put work correctly even before of_init is called. Afterwards introduce of_node_is_initialized & of_node_is_attached that query the underlying kobject about the state (attached means kobj is visible in sysfs) Using that make sure the lifecycle of the tree is correct at all times. Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com> [grant.likely: moved of_node_init() calls, fixed up locking, and dropped __of_populate() hunks] Signed-off-by: Grant Likely <grant.likely@linaro.org>
Diffstat (limited to 'drivers/of/base.c')
-rw-r--r--drivers/of/base.c35
1 files changed, 26 insertions, 9 deletions
diff --git a/drivers/of/base.c b/drivers/of/base.c
index ed3e70b84957..418a4ff9d97c 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -246,10 +246,19 @@ static int __of_node_add(struct device_node *np)
246int of_node_add(struct device_node *np) 246int of_node_add(struct device_node *np)
247{ 247{
248 int rc = 0; 248 int rc = 0;
249 kobject_init(&np->kobj, &of_node_ktype); 249
250 BUG_ON(!of_node_is_initialized(np));
251
252 /*
253 * Grab the mutex here so that in a race condition between of_init() and
254 * of_node_add(), node addition will still be consistent.
255 */
250 mutex_lock(&of_aliases_mutex); 256 mutex_lock(&of_aliases_mutex);
251 if (of_kset) 257 if (of_kset)
252 rc = __of_node_add(np); 258 rc = __of_node_add(np);
259 else
260 /* This scenario may be perfectly valid, but report it anyway */
261 pr_info("of_node_add(%s) before of_init()\n", np->full_name);
253 mutex_unlock(&of_aliases_mutex); 262 mutex_unlock(&of_aliases_mutex);
254 return rc; 263 return rc;
255} 264}
@@ -259,10 +268,17 @@ static void of_node_remove(struct device_node *np)
259{ 268{
260 struct property *pp; 269 struct property *pp;
261 270
262 for_each_property_of_node(np, pp) 271 BUG_ON(!of_node_is_initialized(np));
263 sysfs_remove_bin_file(&np->kobj, &pp->attr); 272
273 /* only remove properties if on sysfs */
274 if (of_node_is_attached(np)) {
275 for_each_property_of_node(np, pp)
276 sysfs_remove_bin_file(&np->kobj, &pp->attr);
277 kobject_del(&np->kobj);
278 }
264 279
265 kobject_del(&np->kobj); 280 /* finally remove the kobj_init ref */
281 of_node_put(np);
266} 282}
267#endif 283#endif
268 284
@@ -1631,6 +1647,10 @@ static int of_property_notify(int action, struct device_node *np,
1631{ 1647{
1632 struct of_prop_reconfig pr; 1648 struct of_prop_reconfig pr;
1633 1649
1650 /* only call notifiers if the node is attached */
1651 if (!of_node_is_attached(np))
1652 return 0;
1653
1634 pr.dn = np; 1654 pr.dn = np;
1635 pr.prop = prop; 1655 pr.prop = prop;
1636 return of_reconfig_notify(action, &pr); 1656 return of_reconfig_notify(action, &pr);
@@ -1682,11 +1702,8 @@ int of_add_property(struct device_node *np, struct property *prop)
1682 if (rc) 1702 if (rc)
1683 return rc; 1703 return rc;
1684 1704
1685 /* at early boot, bail hear and defer setup to of_init() */ 1705 if (of_node_is_attached(np))
1686 if (!of_kset) 1706 __of_add_property_sysfs(np, prop);
1687 return 0;
1688
1689 __of_add_property_sysfs(np, prop);
1690 1707
1691 return rc; 1708 return rc;
1692} 1709}