aboutsummaryrefslogtreecommitdiff
path: root/drivers/of/base.c
diff options
context:
space:
mode:
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 f12feaee4051..fa0a29ac28c4 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -238,10 +238,19 @@ static int __of_node_add(struct device_node *np)
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 @@ static void of_node_remove(struct device_node *np)
{
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));
+
+ /* 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);
+ }
- kobject_del(&np->kobj);
+ /* finally remove the kobj_init ref */
+ of_node_put(np);
}
#endif
@@ -1501,6 +1517,10 @@ static int of_property_notify(int action, struct device_node *np,
{
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 @@ int of_add_property(struct device_node *np, struct property *prop)
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;
}