diff options
-rw-r--r-- | drivers/of/base.c | 35 | ||||
-rw-r--r-- | drivers/of/fdt.c | 3 | ||||
-rw-r--r-- | drivers/of/pdt.c | 3 | ||||
-rw-r--r-- | include/linux/of.h | 19 |
4 files changed, 47 insertions, 13 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) | |||
246 | int of_node_add(struct device_node *np) | 246 | int 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 | } |
diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index 96ad1ab7f9d6..70ccc36513e7 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c | |||
@@ -202,6 +202,7 @@ static void * unflatten_dt_node(struct boot_param_header *blob, | |||
202 | __alignof__(struct device_node)); | 202 | __alignof__(struct device_node)); |
203 | if (allnextpp) { | 203 | if (allnextpp) { |
204 | char *fn; | 204 | char *fn; |
205 | of_node_init(np); | ||
205 | np->full_name = fn = ((char *)np) + sizeof(*np); | 206 | np->full_name = fn = ((char *)np) + sizeof(*np); |
206 | if (new_format) { | 207 | if (new_format) { |
207 | /* rebuild full path for new format */ | 208 | /* rebuild full path for new format */ |
@@ -326,8 +327,6 @@ static void * unflatten_dt_node(struct boot_param_header *blob, | |||
326 | np->name = "<NULL>"; | 327 | np->name = "<NULL>"; |
327 | if (!np->type) | 328 | if (!np->type) |
328 | np->type = "<NULL>"; | 329 | np->type = "<NULL>"; |
329 | |||
330 | of_node_add(np); | ||
331 | } | 330 | } |
332 | while (tag == OF_DT_BEGIN_NODE || tag == OF_DT_NOP) { | 331 | while (tag == OF_DT_BEGIN_NODE || tag == OF_DT_NOP) { |
333 | if (tag == OF_DT_NOP) | 332 | if (tag == OF_DT_NOP) |
diff --git a/drivers/of/pdt.c b/drivers/of/pdt.c index e64fa3d3da5f..36b4035881b0 100644 --- a/drivers/of/pdt.c +++ b/drivers/of/pdt.c | |||
@@ -176,6 +176,7 @@ static struct device_node * __init of_pdt_create_node(phandle node, | |||
176 | return NULL; | 176 | return NULL; |
177 | 177 | ||
178 | dp = prom_early_alloc(sizeof(*dp)); | 178 | dp = prom_early_alloc(sizeof(*dp)); |
179 | of_node_init(dp); | ||
179 | of_pdt_incr_unique_id(dp); | 180 | of_pdt_incr_unique_id(dp); |
180 | dp->parent = parent; | 181 | dp->parent = parent; |
181 | 182 | ||
@@ -213,7 +214,6 @@ static struct device_node * __init of_pdt_build_tree(struct device_node *parent, | |||
213 | *nextp = &dp->allnext; | 214 | *nextp = &dp->allnext; |
214 | 215 | ||
215 | dp->full_name = of_pdt_build_full_name(dp); | 216 | dp->full_name = of_pdt_build_full_name(dp); |
216 | of_node_add(dp); | ||
217 | 217 | ||
218 | dp->child = of_pdt_build_tree(dp, | 218 | dp->child = of_pdt_build_tree(dp, |
219 | of_pdt_prom_ops->getchild(node), nextp); | 219 | of_pdt_prom_ops->getchild(node), nextp); |
@@ -244,7 +244,6 @@ void __init of_pdt_build_devicetree(phandle root_node, struct of_pdt_ops *ops) | |||
244 | of_allnodes->path_component_name = ""; | 244 | of_allnodes->path_component_name = ""; |
245 | #endif | 245 | #endif |
246 | of_allnodes->full_name = "/"; | 246 | of_allnodes->full_name = "/"; |
247 | of_node_add(of_allnodes); | ||
248 | 247 | ||
249 | nextp = &of_allnodes->allnext; | 248 | nextp = &of_allnodes->allnext; |
250 | of_allnodes->child = of_pdt_build_tree(of_allnodes, | 249 | of_allnodes->child = of_pdt_build_tree(of_allnodes, |
diff --git a/include/linux/of.h b/include/linux/of.h index 257994a420f3..a8b9dad90c64 100644 --- a/include/linux/of.h +++ b/include/linux/of.h | |||
@@ -76,6 +76,25 @@ struct of_phandle_args { | |||
76 | 76 | ||
77 | extern int of_node_add(struct device_node *node); | 77 | extern int of_node_add(struct device_node *node); |
78 | 78 | ||
79 | /* initialize a node */ | ||
80 | extern struct kobj_type of_node_ktype; | ||
81 | static inline void of_node_init(struct device_node *node) | ||
82 | { | ||
83 | kobject_init(&node->kobj, &of_node_ktype); | ||
84 | } | ||
85 | |||
86 | /* true when node is initialized */ | ||
87 | static inline int of_node_is_initialized(struct device_node *node) | ||
88 | { | ||
89 | return node && node->kobj.state_initialized; | ||
90 | } | ||
91 | |||
92 | /* true when node is attached (i.e. present on sysfs) */ | ||
93 | static inline int of_node_is_attached(struct device_node *node) | ||
94 | { | ||
95 | return node && node->kobj.state_in_sysfs; | ||
96 | } | ||
97 | |||
79 | #ifdef CONFIG_OF_DYNAMIC | 98 | #ifdef CONFIG_OF_DYNAMIC |
80 | extern struct device_node *of_node_get(struct device_node *node); | 99 | extern struct device_node *of_node_get(struct device_node *node); |
81 | extern void of_node_put(struct device_node *node); | 100 | extern void of_node_put(struct device_node *node); |