aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/of/base.c96
-rw-r--r--drivers/of/dynamic.c12
-rw-r--r--drivers/of/of_private.h10
-rw-r--r--include/linux/of.h2
4 files changed, 69 insertions, 51 deletions
diff --git a/drivers/of/base.c b/drivers/of/base.c
index b403f9d98461..ad4929cbd876 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -37,10 +37,13 @@ struct device_node *of_chosen;
37struct device_node *of_aliases; 37struct device_node *of_aliases;
38static struct device_node *of_stdout; 38static struct device_node *of_stdout;
39 39
40static struct kset *of_kset; 40struct kset *of_kset;
41 41
42/* 42/*
43 * Used to protect the of_aliases, to hold off addition of nodes to sysfs 43 * Used to protect the of_aliases, to hold off addition of nodes to sysfs.
44 * This mutex must be held whenever modifications are being made to the
45 * device tree. The of_{attach,detach}_node() and
46 * of_{add,remove,update}_property() helpers make sure this happens.
44 */ 47 */
45DEFINE_MUTEX(of_mutex); 48DEFINE_MUTEX(of_mutex);
46 49
@@ -127,13 +130,16 @@ static const char *safe_name(struct kobject *kobj, const char *orig_name)
127 return name; 130 return name;
128} 131}
129 132
130static int __of_add_property_sysfs(struct device_node *np, struct property *pp) 133int __of_add_property_sysfs(struct device_node *np, struct property *pp)
131{ 134{
132 int rc; 135 int rc;
133 136
134 /* Important: Don't leak passwords */ 137 /* Important: Don't leak passwords */
135 bool secure = strncmp(pp->name, "security-", 9) == 0; 138 bool secure = strncmp(pp->name, "security-", 9) == 0;
136 139
140 if (!of_kset || !of_node_is_attached(np))
141 return 0;
142
137 sysfs_bin_attr_init(&pp->attr); 143 sysfs_bin_attr_init(&pp->attr);
138 pp->attr.attr.name = safe_name(&np->kobj, pp->name); 144 pp->attr.attr.name = safe_name(&np->kobj, pp->name);
139 pp->attr.attr.mode = secure ? S_IRUSR : S_IRUGO; 145 pp->attr.attr.mode = secure ? S_IRUSR : S_IRUGO;
@@ -145,12 +151,15 @@ static int __of_add_property_sysfs(struct device_node *np, struct property *pp)
145 return rc; 151 return rc;
146} 152}
147 153
148static int __of_node_add(struct device_node *np) 154int __of_attach_node_sysfs(struct device_node *np)
149{ 155{
150 const char *name; 156 const char *name;
151 struct property *pp; 157 struct property *pp;
152 int rc; 158 int rc;
153 159
160 if (!of_kset)
161 return 0;
162
154 np->kobj.kset = of_kset; 163 np->kobj.kset = of_kset;
155 if (!np->parent) { 164 if (!np->parent) {
156 /* Nodes without parents are new top level trees */ 165 /* Nodes without parents are new top level trees */
@@ -172,26 +181,6 @@ static int __of_node_add(struct device_node *np)
172 return 0; 181 return 0;
173} 182}
174 183
175int of_node_add(struct device_node *np)
176{
177 int rc = 0;
178
179 BUG_ON(!of_node_is_initialized(np));
180
181 /*
182 * Grab the mutex here so that in a race condition between of_init() and
183 * of_node_add(), node addition will still be consistent.
184 */
185 mutex_lock(&of_mutex);
186 if (of_kset)
187 rc = __of_node_add(np);
188 else
189 /* This scenario may be perfectly valid, but report it anyway */
190 pr_info("of_node_add(%s) before of_init()\n", np->full_name);
191 mutex_unlock(&of_mutex);
192 return rc;
193}
194
195static int __init of_init(void) 184static int __init of_init(void)
196{ 185{
197 struct device_node *np; 186 struct device_node *np;
@@ -204,7 +193,7 @@ static int __init of_init(void)
204 return -ENOMEM; 193 return -ENOMEM;
205 } 194 }
206 for_each_of_allnodes(np) 195 for_each_of_allnodes(np)
207 __of_node_add(np); 196 __of_attach_node_sysfs(np);
208 mutex_unlock(&of_mutex); 197 mutex_unlock(&of_mutex);
209 198
210 /* Symlink in /proc as required by userspace ABI */ 199 /* Symlink in /proc as required by userspace ABI */
@@ -1689,15 +1678,17 @@ int of_add_property(struct device_node *np, struct property *prop)
1689 if (rc) 1678 if (rc)
1690 return rc; 1679 return rc;
1691 1680
1681 mutex_lock(&of_mutex);
1682
1692 raw_spin_lock_irqsave(&devtree_lock, flags); 1683 raw_spin_lock_irqsave(&devtree_lock, flags);
1693 rc = __of_add_property(np, prop); 1684 rc = __of_add_property(np, prop);
1694 raw_spin_unlock_irqrestore(&devtree_lock, flags); 1685 raw_spin_unlock_irqrestore(&devtree_lock, flags);
1695 if (rc)
1696 return rc;
1697 1686
1698 if (of_node_is_attached(np)) 1687 if (!rc)
1699 __of_add_property_sysfs(np, prop); 1688 __of_add_property_sysfs(np, prop);
1700 1689
1690 mutex_unlock(&of_mutex);
1691
1701 return rc; 1692 return rc;
1702} 1693}
1703 1694
@@ -1720,6 +1711,13 @@ int __of_remove_property(struct device_node *np, struct property *prop)
1720 return 0; 1711 return 0;
1721} 1712}
1722 1713
1714void __of_remove_property_sysfs(struct device_node *np, struct property *prop)
1715{
1716 /* at early boot, bail here and defer setup to of_init() */
1717 if (of_kset && of_node_is_attached(np))
1718 sysfs_remove_bin_file(&np->kobj, &prop->attr);
1719}
1720
1723/** 1721/**
1724 * of_remove_property - Remove a property from a node. 1722 * of_remove_property - Remove a property from a node.
1725 * 1723 *
@@ -1737,20 +1735,18 @@ int of_remove_property(struct device_node *np, struct property *prop)
1737 if (rc) 1735 if (rc)
1738 return rc; 1736 return rc;
1739 1737
1738 mutex_lock(&of_mutex);
1739
1740 raw_spin_lock_irqsave(&devtree_lock, flags); 1740 raw_spin_lock_irqsave(&devtree_lock, flags);
1741 rc = __of_remove_property(np, prop); 1741 rc = __of_remove_property(np, prop);
1742 raw_spin_unlock_irqrestore(&devtree_lock, flags); 1742 raw_spin_unlock_irqrestore(&devtree_lock, flags);
1743 1743
1744 if (rc) 1744 if (!rc)
1745 return rc; 1745 __of_remove_property_sysfs(np, prop);
1746
1747 /* at early boot, bail hear and defer setup to of_init() */
1748 if (!of_kset)
1749 return 0;
1750 1746
1751 sysfs_remove_bin_file(&np->kobj, &prop->attr); 1747 mutex_unlock(&of_mutex);
1752 1748
1753 return 0; 1749 return rc;
1754} 1750}
1755 1751
1756int __of_update_property(struct device_node *np, struct property *newprop, 1752int __of_update_property(struct device_node *np, struct property *newprop,
@@ -1779,6 +1775,18 @@ int __of_update_property(struct device_node *np, struct property *newprop,
1779 return 0; 1775 return 0;
1780} 1776}
1781 1777
1778void __of_update_property_sysfs(struct device_node *np, struct property *newprop,
1779 struct property *oldprop)
1780{
1781 /* At early boot, bail out and defer setup to of_init() */
1782 if (!of_kset)
1783 return;
1784
1785 if (oldprop)
1786 sysfs_remove_bin_file(&np->kobj, &oldprop->attr);
1787 __of_add_property_sysfs(np, newprop);
1788}
1789
1782/* 1790/*
1783 * of_update_property - Update a property in a node, if the property does 1791 * of_update_property - Update a property in a node, if the property does
1784 * not exist, add it. 1792 * not exist, add it.
@@ -1801,22 +1809,18 @@ int of_update_property(struct device_node *np, struct property *newprop)
1801 if (rc) 1809 if (rc)
1802 return rc; 1810 return rc;
1803 1811
1812 mutex_lock(&of_mutex);
1813
1804 raw_spin_lock_irqsave(&devtree_lock, flags); 1814 raw_spin_lock_irqsave(&devtree_lock, flags);
1805 rc = __of_update_property(np, newprop, &oldprop); 1815 rc = __of_update_property(np, newprop, &oldprop);
1806 raw_spin_unlock_irqrestore(&devtree_lock, flags); 1816 raw_spin_unlock_irqrestore(&devtree_lock, flags);
1807 if (rc)
1808 return rc;
1809 1817
1810 /* At early boot, bail out and defer setup to of_init() */ 1818 if (!rc)
1811 if (!of_kset) 1819 __of_update_property_sysfs(np, newprop, oldprop);
1812 return 0;
1813 1820
1814 /* Update the sysfs attribute */ 1821 mutex_unlock(&of_mutex);
1815 if (oldprop)
1816 sysfs_remove_bin_file(&np->kobj, &oldprop->attr);
1817 __of_add_property_sysfs(np, newprop);
1818 1822
1819 return 0; 1823 return rc;
1820} 1824}
1821 1825
1822static void of_alias_add(struct alias_prop *ap, struct device_node *np, 1826static void of_alias_add(struct alias_prop *ap, struct device_node *np,
diff --git a/drivers/of/dynamic.c b/drivers/of/dynamic.c
index 75fcc66fcefd..c875787fa394 100644
--- a/drivers/of/dynamic.c
+++ b/drivers/of/dynamic.c
@@ -41,11 +41,13 @@ void of_node_put(struct device_node *node)
41} 41}
42EXPORT_SYMBOL(of_node_put); 42EXPORT_SYMBOL(of_node_put);
43 43
44static void of_node_remove(struct device_node *np) 44void __of_detach_node_sysfs(struct device_node *np)
45{ 45{
46 struct property *pp; 46 struct property *pp;
47 47
48 BUG_ON(!of_node_is_initialized(np)); 48 BUG_ON(!of_node_is_initialized(np));
49 if (!of_kset)
50 return;
49 51
50 /* only remove properties if on sysfs */ 52 /* only remove properties if on sysfs */
51 if (of_node_is_attached(np)) { 53 if (of_node_is_attached(np)) {
@@ -115,11 +117,13 @@ int of_attach_node(struct device_node *np)
115 if (rc) 117 if (rc)
116 return rc; 118 return rc;
117 119
120 mutex_lock(&of_mutex);
118 raw_spin_lock_irqsave(&devtree_lock, flags); 121 raw_spin_lock_irqsave(&devtree_lock, flags);
119 __of_attach_node(np); 122 __of_attach_node(np);
120 raw_spin_unlock_irqrestore(&devtree_lock, flags); 123 raw_spin_unlock_irqrestore(&devtree_lock, flags);
121 124
122 of_node_add(np); 125 __of_attach_node_sysfs(np);
126 mutex_unlock(&of_mutex);
123 return 0; 127 return 0;
124} 128}
125 129
@@ -174,11 +178,13 @@ int of_detach_node(struct device_node *np)
174 if (rc) 178 if (rc)
175 return rc; 179 return rc;
176 180
181 mutex_lock(&of_mutex);
177 raw_spin_lock_irqsave(&devtree_lock, flags); 182 raw_spin_lock_irqsave(&devtree_lock, flags);
178 __of_detach_node(np); 183 __of_detach_node(np);
179 raw_spin_unlock_irqrestore(&devtree_lock, flags); 184 raw_spin_unlock_irqrestore(&devtree_lock, flags);
180 185
181 of_node_remove(np); 186 __of_detach_node_sysfs(np);
187 mutex_unlock(&of_mutex);
182 return rc; 188 return rc;
183} 189}
184 190
diff --git a/drivers/of/of_private.h b/drivers/of/of_private.h
index 0f6089722af9..0d99ba8caeed 100644
--- a/drivers/of/of_private.h
+++ b/drivers/of/of_private.h
@@ -33,6 +33,8 @@ struct alias_prop {
33 33
34extern struct mutex of_mutex; 34extern struct mutex of_mutex;
35extern struct list_head aliases_lookup; 35extern struct list_head aliases_lookup;
36extern struct kset *of_kset;
37
36 38
37static inline struct device_node *kobj_to_device_node(struct kobject *kobj) 39static inline struct device_node *kobj_to_device_node(struct kobject *kobj)
38{ 40{
@@ -62,11 +64,19 @@ struct property *__of_prop_dup(const struct property *prop, gfp_t allocflags);
62struct device_node *__of_node_alloc(const char *full_name, gfp_t allocflags); 64struct device_node *__of_node_alloc(const char *full_name, gfp_t allocflags);
63 65
64extern int __of_add_property(struct device_node *np, struct property *prop); 66extern int __of_add_property(struct device_node *np, struct property *prop);
67extern int __of_add_property_sysfs(struct device_node *np,
68 struct property *prop);
65extern int __of_remove_property(struct device_node *np, struct property *prop); 69extern int __of_remove_property(struct device_node *np, struct property *prop);
70extern void __of_remove_property_sysfs(struct device_node *np,
71 struct property *prop);
66extern int __of_update_property(struct device_node *np, 72extern int __of_update_property(struct device_node *np,
67 struct property *newprop, struct property **oldprop); 73 struct property *newprop, struct property **oldprop);
74extern void __of_update_property_sysfs(struct device_node *np,
75 struct property *newprop, struct property *oldprop);
68 76
69extern void __of_attach_node(struct device_node *np); 77extern void __of_attach_node(struct device_node *np);
78extern int __of_attach_node_sysfs(struct device_node *np);
70extern void __of_detach_node(struct device_node *np); 79extern void __of_detach_node(struct device_node *np);
80extern void __of_detach_node_sysfs(struct device_node *np);
71 81
72#endif /* _LINUX_OF_PRIVATE_H */ 82#endif /* _LINUX_OF_PRIVATE_H */
diff --git a/include/linux/of.h b/include/linux/of.h
index abf829a1f150..705fa12fca7f 100644
--- a/include/linux/of.h
+++ b/include/linux/of.h
@@ -74,8 +74,6 @@ struct of_phandle_args {
74 uint32_t args[MAX_PHANDLE_ARGS]; 74 uint32_t args[MAX_PHANDLE_ARGS];
75}; 75};
76 76
77extern int of_node_add(struct device_node *node);
78
79/* initialize a node */ 77/* initialize a node */
80extern struct kobj_type of_node_ktype; 78extern struct kobj_type of_node_ktype;
81static inline void of_node_init(struct device_node *node) 79static inline void of_node_init(struct device_node *node)