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;
 }
 {
        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
 
 {
        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);
        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 rc;
 }
 
                return NULL;
 
        dp = prom_early_alloc(sizeof(*dp));
+       of_node_init(dp);
        of_pdt_incr_unique_id(dp);
        dp->parent = parent;
 
                *nextp = &dp->allnext;
 
                dp->full_name = of_pdt_build_full_name(dp);
-               of_node_add(dp);
 
                dp->child = of_pdt_build_tree(dp,
                                of_pdt_prom_ops->getchild(node), nextp);
        of_allnodes->path_component_name = "";
 #endif
        of_allnodes->full_name = "/";
-       of_node_add(of_allnodes);
 
        nextp = &of_allnodes->allnext;
        of_allnodes->child = of_pdt_build_tree(of_allnodes,
 
 
 extern int of_node_add(struct device_node *node);
 
+/* initialize a node */
+extern struct kobj_type of_node_ktype;
+static inline void of_node_init(struct device_node *node)
+{
+       kobject_init(&node->kobj, &of_node_ktype);
+}
+
+/* true when node is initialized */
+static inline int of_node_is_initialized(struct device_node *node)
+{
+       return node && node->kobj.state_initialized;
+}
+
+/* true when node is attached (i.e. present on sysfs) */
+static inline int of_node_is_attached(struct device_node *node)
+{
+       return node && node->kobj.state_in_sysfs;
+}
+
 #ifdef CONFIG_OF_DYNAMIC
 extern struct device_node *of_node_get(struct device_node *node);
 extern void of_node_put(struct device_node *node);