aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/of/base.c
diff options
context:
space:
mode:
authorGrant Likely <grant.likely@linaro.org>2014-02-20 13:02:11 -0500
committerGrant Likely <grant.likely@linaro.org>2014-03-11 16:48:26 -0400
commit75b57ecf9d1d1e17d099ab13b8f48e6e038676be (patch)
tree1fcf03dae1722cf5c7917023a404958be2bce036 /drivers/of/base.c
parentdab2310d9d90eded48625c5382c6a60389bf8ca9 (diff)
of: Make device nodes kobjects so they show up in sysfs
Device tree nodes are already treated as objects, and we already want to expose them to userspace which is done using the /proc filesystem today. Right now the kernel has to do a lot of work to keep the /proc view in sync with the in-kernel representation. If device_nodes are switched to be kobjects then the device tree code can be a whole lot simpler. It also turns out that switching to using /sysfs from /proc results in smaller code and data size, and the userspace ABI won't change if /proc/device-tree symlinks to /sys/firmware/devicetree/base. v7: Add missing sysfs_bin_attr_init() v6: Add __of_add_property() early init fixes from Pantelis v5: Rename firmware/ofw to firmware/devicetree Fix updating property values in sysfs v4: Fixed build error on Powerpc Fixed handling of dynamic nodes on powerpc v3: Fixed handling of duplicate attribute and child node names v2: switch to using sysfs bin_attributes which solve the problem of reporting incorrect property size. Signed-off-by: Grant Likely <grant.likely@secretlab.ca> Tested-by: Sascha Hauer <s.hauer@pengutronix.de> Cc: Rob Herring <rob.herring@calxeda.com> Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org> Cc: David S. Miller <davem@davemloft.net> Cc: Nathan Fontenot <nfont@linux.vnet.ibm.com> Cc: Pantelis Antoniou <panto@antoniou-consulting.com>
Diffstat (limited to 'drivers/of/base.c')
-rw-r--r--drivers/of/base.c174
1 files changed, 166 insertions, 8 deletions
diff --git a/drivers/of/base.c b/drivers/of/base.c
index 48594f334151..3b70a468c8ab 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -23,6 +23,7 @@
23#include <linux/of.h> 23#include <linux/of.h>
24#include <linux/spinlock.h> 24#include <linux/spinlock.h>
25#include <linux/slab.h> 25#include <linux/slab.h>
26#include <linux/string.h>
26#include <linux/proc_fs.h> 27#include <linux/proc_fs.h>
27 28
28#include "of_private.h" 29#include "of_private.h"
@@ -35,6 +36,12 @@ struct device_node *of_chosen;
35struct device_node *of_aliases; 36struct device_node *of_aliases;
36static struct device_node *of_stdout; 37static struct device_node *of_stdout;
37 38
39static struct kset *of_kset;
40
41/*
42 * Used to protect the of_aliases; but also overloaded to hold off addition of
43 * nodes to sysfs
44 */
38DEFINE_MUTEX(of_aliases_mutex); 45DEFINE_MUTEX(of_aliases_mutex);
39 46
40/* use when traversing tree through the allnext, child, sibling, 47/* use when traversing tree through the allnext, child, sibling,
@@ -92,14 +99,14 @@ int __weak of_node_to_nid(struct device_node *np)
92struct device_node *of_node_get(struct device_node *node) 99struct device_node *of_node_get(struct device_node *node)
93{ 100{
94 if (node) 101 if (node)
95 kref_get(&node->kref); 102 kobject_get(&node->kobj);
96 return node; 103 return node;
97} 104}
98EXPORT_SYMBOL(of_node_get); 105EXPORT_SYMBOL(of_node_get);
99 106
100static inline struct device_node *kref_to_device_node(struct kref *kref) 107static inline struct device_node *kobj_to_device_node(struct kobject *kobj)
101{ 108{
102 return container_of(kref, struct device_node, kref); 109 return container_of(kobj, struct device_node, kobj);
103} 110}
104 111
105/** 112/**
@@ -109,16 +116,15 @@ static inline struct device_node *kref_to_device_node(struct kref *kref)
109 * In of_node_put() this function is passed to kref_put() 116 * In of_node_put() this function is passed to kref_put()
110 * as the destructor. 117 * as the destructor.
111 */ 118 */
112static void of_node_release(struct kref *kref) 119static void of_node_release(struct kobject *kobj)
113{ 120{
114 struct device_node *node = kref_to_device_node(kref); 121 struct device_node *node = kobj_to_device_node(kobj);
115 struct property *prop = node->properties; 122 struct property *prop = node->properties;
116 123
117 /* We should never be releasing nodes that haven't been detached. */ 124 /* We should never be releasing nodes that haven't been detached. */
118 if (!of_node_check_flag(node, OF_DETACHED)) { 125 if (!of_node_check_flag(node, OF_DETACHED)) {
119 pr_err("ERROR: Bad of_node_put() on %s\n", node->full_name); 126 pr_err("ERROR: Bad of_node_put() on %s\n", node->full_name);
120 dump_stack(); 127 dump_stack();
121 kref_init(&node->kref);
122 return; 128 return;
123 } 129 }
124 130
@@ -151,11 +157,140 @@ static void of_node_release(struct kref *kref)
151void of_node_put(struct device_node *node) 157void of_node_put(struct device_node *node)
152{ 158{
153 if (node) 159 if (node)
154 kref_put(&node->kref, of_node_release); 160 kobject_put(&node->kobj);
155} 161}
156EXPORT_SYMBOL(of_node_put); 162EXPORT_SYMBOL(of_node_put);
163#else
164static void of_node_release(struct kobject *kobj)
165{
166 /* Without CONFIG_OF_DYNAMIC, no nodes gets freed */
167}
157#endif /* CONFIG_OF_DYNAMIC */ 168#endif /* CONFIG_OF_DYNAMIC */
158 169
170struct kobj_type of_node_ktype = {
171 .release = of_node_release,
172};
173
174static ssize_t of_node_property_read(struct file *filp, struct kobject *kobj,
175 struct bin_attribute *bin_attr, char *buf,
176 loff_t offset, size_t count)
177{
178 struct property *pp = container_of(bin_attr, struct property, attr);
179 return memory_read_from_buffer(buf, count, &offset, pp->value, pp->length);
180}
181
182static const char *safe_name(struct kobject *kobj, const char *orig_name)
183{
184 const char *name = orig_name;
185 struct kernfs_node *kn;
186 int i = 0;
187
188 /* don't be a hero. After 16 tries give up */
189 while (i < 16 && (kn = sysfs_get_dirent(kobj->sd, name))) {
190 sysfs_put(kn);
191 if (name != orig_name)
192 kfree(name);
193 name = kasprintf(GFP_KERNEL, "%s#%i", orig_name, ++i);
194 }
195
196 if (name != orig_name)
197 pr_warn("device-tree: Duplicate name in %s, renamed to \"%s\"\n",
198 kobject_name(kobj), name);
199 return name;
200}
201
202static int __of_add_property_sysfs(struct device_node *np, struct property *pp)
203{
204 int rc;
205
206 /* Important: Don't leak passwords */
207 bool secure = strncmp(pp->name, "security-", 9) == 0;
208
209 sysfs_bin_attr_init(&pp->attr);
210 pp->attr.attr.name = safe_name(&np->kobj, pp->name);
211 pp->attr.attr.mode = secure ? S_IRUSR : S_IRUGO;
212 pp->attr.size = secure ? 0 : pp->length;
213 pp->attr.read = of_node_property_read;
214
215 rc = sysfs_create_bin_file(&np->kobj, &pp->attr);
216 WARN(rc, "error adding attribute %s to node %s\n", pp->name, np->full_name);
217 return rc;
218}
219
220static int __of_node_add(struct device_node *np)
221{
222 const char *name;
223 struct property *pp;
224 int rc;
225
226 np->kobj.kset = of_kset;
227 if (!np->parent) {
228 /* Nodes without parents are new top level trees */
229 rc = kobject_add(&np->kobj, NULL, safe_name(&of_kset->kobj, "base"));
230 } else {
231 name = safe_name(&np->parent->kobj, kbasename(np->full_name));
232 if (!name || !name[0])
233 return -EINVAL;
234
235 rc = kobject_add(&np->kobj, &np->parent->kobj, "%s", name);
236 }
237 if (rc)
238 return rc;
239
240 for_each_property_of_node(np, pp)
241 __of_add_property_sysfs(np, pp);
242
243 return 0;
244}
245
246int of_node_add(struct device_node *np)
247{
248 int rc = 0;
249 kobject_init(&np->kobj, &of_node_ktype);
250 mutex_lock(&of_aliases_mutex);
251 if (of_kset)
252 rc = __of_node_add(np);
253 mutex_unlock(&of_aliases_mutex);
254 return rc;
255}
256
257#if defined(CONFIG_OF_DYNAMIC)
258static void of_node_remove(struct device_node *np)
259{
260 struct property *pp;
261
262 for_each_property_of_node(np, pp)
263 sysfs_remove_bin_file(&np->kobj, &pp->attr);
264
265 kobject_del(&np->kobj);
266}
267#endif
268
269static int __init of_init(void)
270{
271 struct device_node *np;
272
273 /* Create the kset, and register existing nodes */
274 mutex_lock(&of_aliases_mutex);
275 of_kset = kset_create_and_add("devicetree", NULL, firmware_kobj);
276 if (!of_kset) {
277 mutex_unlock(&of_aliases_mutex);
278 return -ENOMEM;
279 }
280 for_each_of_allnodes(np)
281 __of_node_add(np);
282 mutex_unlock(&of_aliases_mutex);
283
284#if !defined(CONFIG_PROC_DEVICETREE)
285 /* Symlink to the new tree when PROC_DEVICETREE is disabled */
286 if (of_allnodes)
287 proc_symlink("device-tree", NULL, "/sys/firmware/devicetree/base");
288#endif /* CONFIG_PROC_DEVICETREE */
289
290 return 0;
291}
292core_initcall(of_init);
293
159static struct property *__of_find_property(const struct device_node *np, 294static struct property *__of_find_property(const struct device_node *np,
160 const char *name, int *lenp) 295 const char *name, int *lenp)
161{ 296{
@@ -1546,6 +1681,14 @@ int of_add_property(struct device_node *np, struct property *prop)
1546 raw_spin_lock_irqsave(&devtree_lock, flags); 1681 raw_spin_lock_irqsave(&devtree_lock, flags);
1547 rc = __of_add_property(np, prop); 1682 rc = __of_add_property(np, prop);
1548 raw_spin_unlock_irqrestore(&devtree_lock, flags); 1683 raw_spin_unlock_irqrestore(&devtree_lock, flags);
1684 if (rc)
1685 return rc;
1686
1687 /* at early boot, bail hear and defer setup to of_init() */
1688 if (!of_kset)
1689 return 0;
1690
1691 __of_add_property_sysfs(np, prop);
1549 1692
1550#ifdef CONFIG_PROC_DEVICETREE 1693#ifdef CONFIG_PROC_DEVICETREE
1551 /* try to add to proc as well if it was initialized */ 1694 /* try to add to proc as well if it was initialized */
@@ -1593,6 +1736,12 @@ int of_remove_property(struct device_node *np, struct property *prop)
1593 if (!found) 1736 if (!found)
1594 return -ENODEV; 1737 return -ENODEV;
1595 1738
1739 /* at early boot, bail hear and defer setup to of_init() */
1740 if (!of_kset)
1741 return 0;
1742
1743 sysfs_remove_bin_file(&np->kobj, &prop->attr);
1744
1596#ifdef CONFIG_PROC_DEVICETREE 1745#ifdef CONFIG_PROC_DEVICETREE
1597 /* try to remove the proc node as well */ 1746 /* try to remove the proc node as well */
1598 if (np->pde) 1747 if (np->pde)
@@ -1643,13 +1792,20 @@ int of_update_property(struct device_node *np, struct property *newprop)
1643 next = &(*next)->next; 1792 next = &(*next)->next;
1644 } 1793 }
1645 raw_spin_unlock_irqrestore(&devtree_lock, flags); 1794 raw_spin_unlock_irqrestore(&devtree_lock, flags);
1795 if (rc)
1796 return rc;
1797
1798 /* Update the sysfs attribute */
1799 if (oldprop)
1800 sysfs_remove_bin_file(&np->kobj, &oldprop->attr);
1801 __of_add_property_sysfs(np, newprop);
1646 1802
1647 if (!found) 1803 if (!found)
1648 return -ENODEV; 1804 return -ENODEV;
1649 1805
1650#ifdef CONFIG_PROC_DEVICETREE 1806#ifdef CONFIG_PROC_DEVICETREE
1651 /* try to add to proc as well if it was initialized */ 1807 /* try to add to proc as well if it was initialized */
1652 if (!rc && np->pde) 1808 if (np->pde)
1653 proc_device_tree_update_prop(np->pde, newprop, oldprop); 1809 proc_device_tree_update_prop(np->pde, newprop, oldprop);
1654#endif /* CONFIG_PROC_DEVICETREE */ 1810#endif /* CONFIG_PROC_DEVICETREE */
1655 1811
@@ -1723,6 +1879,7 @@ int of_attach_node(struct device_node *np)
1723 of_node_clear_flag(np, OF_DETACHED); 1879 of_node_clear_flag(np, OF_DETACHED);
1724 raw_spin_unlock_irqrestore(&devtree_lock, flags); 1880 raw_spin_unlock_irqrestore(&devtree_lock, flags);
1725 1881
1882 of_node_add(np);
1726 of_add_proc_dt_entry(np); 1883 of_add_proc_dt_entry(np);
1727 return 0; 1884 return 0;
1728} 1885}
@@ -1795,6 +1952,7 @@ int of_detach_node(struct device_node *np)
1795 raw_spin_unlock_irqrestore(&devtree_lock, flags); 1952 raw_spin_unlock_irqrestore(&devtree_lock, flags);
1796 1953
1797 of_remove_proc_dt_entry(np); 1954 of_remove_proc_dt_entry(np);
1955 of_node_remove(np);
1798 return rc; 1956 return rc;
1799} 1957}
1800#endif /* defined(CONFIG_OF_DYNAMIC) */ 1958#endif /* defined(CONFIG_OF_DYNAMIC) */