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>
(cherry picked from commit 0829f6d1f69e4f2fae4062987ae6531a9af1a2e3)
Signed-off-by: Mark Brown <broonie@kernel.org>
diff --git a/drivers/of/base.c b/drivers/of/base.c
index f12feae..fa0a29a 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -238,10 +238,19 @@
int of_node_add(struct device_node *np)
{
int rc = 0;
- kobject_init(&np->kobj, &of_node_ktype);
+
+ BUG_ON(!of_node_is_initialized(np));
+
+ /*
+ * Grab the mutex here so that in a race condition between of_init() and
+ * of_node_add(), node addition will still be consistent.
+ */
mutex_lock(&of_aliases_mutex);
if (of_kset)
rc = __of_node_add(np);
+ else
+ /* This scenario may be perfectly valid, but report it anyway */
+ pr_info("of_node_add(%s) before of_init()\n", np->full_name);
mutex_unlock(&of_aliases_mutex);
return rc;
}
@@ -251,10 +260,17 @@
{
struct property *pp;
- for_each_property_of_node(np, pp)
- sysfs_remove_bin_file(&np->kobj, &pp->attr);
+ BUG_ON(!of_node_is_initialized(np));
- kobject_del(&np->kobj);
+ /* only remove properties if on sysfs */
+ if (of_node_is_attached(np)) {
+ for_each_property_of_node(np, pp)
+ sysfs_remove_bin_file(&np->kobj, &pp->attr);
+ kobject_del(&np->kobj);
+ }
+
+ /* finally remove the kobj_init ref */
+ of_node_put(np);
}
#endif
@@ -1501,6 +1517,10 @@
{
struct of_prop_reconfig pr;
+ /* only call notifiers if the node is attached */
+ if (!of_node_is_attached(np))
+ return 0;
+
pr.dn = np;
pr.prop = prop;
return of_reconfig_notify(action, &pr);
@@ -1542,11 +1562,8 @@
if (rc)
return rc;
- /* at early boot, bail hear and defer setup to of_init() */
- if (!of_kset)
- return 0;
-
- __of_add_property_sysfs(np, prop);
+ if (of_node_is_attached(np))
+ __of_add_property_sysfs(np, prop);
return 0;
}