aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/ABI/testing/sysfs-firmware-ofw28
-rw-r--r--arch/powerpc/platforms/pseries/dlpar.c2
-rw-r--r--arch/powerpc/platforms/pseries/reconfig.c2
-rw-r--r--arch/powerpc/sysdev/msi_bitmap.c2
-rw-r--r--drivers/of/Kconfig8
-rw-r--r--drivers/of/base.c231
-rw-r--r--drivers/of/fdt.c2
-rw-r--r--drivers/of/pdt.c3
-rw-r--r--drivers/of/selftest.c62
-rw-r--r--drivers/of/testcase-data/tests-phandle.dtsi3
-rw-r--r--fs/proc/Makefile1
-rw-r--r--fs/proc/internal.h7
-rw-r--r--fs/proc/proc_devtree.c241
-rw-r--r--fs/proc/root.c3
-rw-r--r--include/linux/of.h39
15 files changed, 300 insertions, 334 deletions
diff --git a/Documentation/ABI/testing/sysfs-firmware-ofw b/Documentation/ABI/testing/sysfs-firmware-ofw
new file mode 100644
index 000000000000..f562b188e71d
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-firmware-ofw
@@ -0,0 +1,28 @@
1What: /sys/firmware/devicetree/*
2Date: November 2013
3Contact: Grant Likely <grant.likely@linaro.org>
4Description:
5 When using OpenFirmware or a Flattened Device Tree to enumerate
6 hardware, the device tree structure will be exposed in this
7 directory.
8
9 It is possible for multiple device-tree directories to exist.
10 Some device drivers use a separate detached device tree which
11 have no attachment to the system tree and will appear in a
12 different subdirectory under /sys/firmware/devicetree.
13
14 Userspace must not use the /sys/firmware/devicetree/base
15 path directly, but instead should follow /proc/device-tree
16 symlink. It is possible that the absolute path will change
17 in the future, but the symlink is the stable ABI.
18
19 The /proc/device-tree symlink replaces the devicetree /proc
20 filesystem support, and has largely the same semantics and
21 should be compatible with existing userspace.
22
23 The contents of /sys/firmware/devicetree/ is a
24 hierarchy of directories, one per device tree node. The
25 directory name is the resolved path component name (node
26 name plus address). Properties are represented as files
27 in the directory. The contents of each file is the exact
28 binary data from the device tree.
diff --git a/arch/powerpc/platforms/pseries/dlpar.c b/arch/powerpc/platforms/pseries/dlpar.c
index a8fe5aa3d34f..022b38e6a80b 100644
--- a/arch/powerpc/platforms/pseries/dlpar.c
+++ b/arch/powerpc/platforms/pseries/dlpar.c
@@ -11,7 +11,6 @@
11 */ 11 */
12 12
13#include <linux/kernel.h> 13#include <linux/kernel.h>
14#include <linux/kref.h>
15#include <linux/notifier.h> 14#include <linux/notifier.h>
16#include <linux/spinlock.h> 15#include <linux/spinlock.h>
17#include <linux/cpu.h> 16#include <linux/cpu.h>
@@ -87,7 +86,6 @@ static struct device_node *dlpar_parse_cc_node(struct cc_workarea *ccwa,
87 } 86 }
88 87
89 of_node_set_flag(dn, OF_DYNAMIC); 88 of_node_set_flag(dn, OF_DYNAMIC);
90 kref_init(&dn->kref);
91 89
92 return dn; 90 return dn;
93} 91}
diff --git a/arch/powerpc/platforms/pseries/reconfig.c b/arch/powerpc/platforms/pseries/reconfig.c
index f93cdf55628c..0435bb65d0aa 100644
--- a/arch/powerpc/platforms/pseries/reconfig.c
+++ b/arch/powerpc/platforms/pseries/reconfig.c
@@ -12,7 +12,6 @@
12 */ 12 */
13 13
14#include <linux/kernel.h> 14#include <linux/kernel.h>
15#include <linux/kref.h>
16#include <linux/notifier.h> 15#include <linux/notifier.h>
17#include <linux/proc_fs.h> 16#include <linux/proc_fs.h>
18#include <linux/slab.h> 17#include <linux/slab.h>
@@ -70,7 +69,6 @@ static int pSeries_reconfig_add_node(const char *path, struct property *proplist
70 69
71 np->properties = proplist; 70 np->properties = proplist;
72 of_node_set_flag(np, OF_DYNAMIC); 71 of_node_set_flag(np, OF_DYNAMIC);
73 kref_init(&np->kref);
74 72
75 np->parent = derive_parent(path); 73 np->parent = derive_parent(path);
76 if (IS_ERR(np->parent)) { 74 if (IS_ERR(np->parent)) {
diff --git a/arch/powerpc/sysdev/msi_bitmap.c b/arch/powerpc/sysdev/msi_bitmap.c
index 0968b66b4cf9..8ba60424be95 100644
--- a/arch/powerpc/sysdev/msi_bitmap.c
+++ b/arch/powerpc/sysdev/msi_bitmap.c
@@ -202,7 +202,7 @@ void __init test_of_node(void)
202 202
203 /* There should really be a struct device_node allocator */ 203 /* There should really be a struct device_node allocator */
204 memset(&of_node, 0, sizeof(of_node)); 204 memset(&of_node, 0, sizeof(of_node));
205 kref_init(&of_node.kref); 205 kref_init(&of_node.kobj.kref);
206 of_node.full_name = node_name; 206 of_node.full_name = node_name;
207 207
208 check(0 == msi_bitmap_alloc(&bmp, size, &of_node)); 208 check(0 == msi_bitmap_alloc(&bmp, size, &of_node));
diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig
index c144b8f990ff..889005fa4d04 100644
--- a/drivers/of/Kconfig
+++ b/drivers/of/Kconfig
@@ -7,14 +7,6 @@ config OF
7menu "Device Tree and Open Firmware support" 7menu "Device Tree and Open Firmware support"
8 depends on OF 8 depends on OF
9 9
10config PROC_DEVICETREE
11 bool "Support for device tree in /proc"
12 depends on PROC_FS && !SPARC
13 help
14 This option adds a device-tree directory under /proc which contains
15 an image of the device tree that the kernel copies from Open
16 Firmware or other boot firmware. If unsure, say Y here.
17
18config OF_SELFTEST 10config OF_SELFTEST
19 bool "Device Tree Runtime self tests" 11 bool "Device Tree Runtime self tests"
20 depends on OF_IRQ 12 depends on OF_IRQ
diff --git a/drivers/of/base.c b/drivers/of/base.c
index 48594f334151..418a4ff9d97c 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,154 @@ 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
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 */
256 mutex_lock(&of_aliases_mutex);
257 if (of_kset)
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);
262 mutex_unlock(&of_aliases_mutex);
263 return rc;
264}
265
266#if defined(CONFIG_OF_DYNAMIC)
267static void of_node_remove(struct device_node *np)
268{
269 struct property *pp;
270
271 BUG_ON(!of_node_is_initialized(np));
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 }
279
280 /* finally remove the kobj_init ref */
281 of_node_put(np);
282}
283#endif
284
285static int __init of_init(void)
286{
287 struct device_node *np;
288
289 /* Create the kset, and register existing nodes */
290 mutex_lock(&of_aliases_mutex);
291 of_kset = kset_create_and_add("devicetree", NULL, firmware_kobj);
292 if (!of_kset) {
293 mutex_unlock(&of_aliases_mutex);
294 return -ENOMEM;
295 }
296 for_each_of_allnodes(np)
297 __of_node_add(np);
298 mutex_unlock(&of_aliases_mutex);
299
300 /* Symlink in /proc as required by userspace ABI */
301 if (of_allnodes)
302 proc_symlink("device-tree", NULL, "/sys/firmware/devicetree/base");
303
304 return 0;
305}
306core_initcall(of_init);
307
159static struct property *__of_find_property(const struct device_node *np, 308static struct property *__of_find_property(const struct device_node *np,
160 const char *name, int *lenp) 309 const char *name, int *lenp)
161{ 310{
@@ -1498,6 +1647,10 @@ static int of_property_notify(int action, struct device_node *np,
1498{ 1647{
1499 struct of_prop_reconfig pr; 1648 struct of_prop_reconfig pr;
1500 1649
1650 /* only call notifiers if the node is attached */
1651 if (!of_node_is_attached(np))
1652 return 0;
1653
1501 pr.dn = np; 1654 pr.dn = np;
1502 pr.prop = prop; 1655 pr.prop = prop;
1503 return of_reconfig_notify(action, &pr); 1656 return of_reconfig_notify(action, &pr);
@@ -1546,12 +1699,11 @@ int of_add_property(struct device_node *np, struct property *prop)
1546 raw_spin_lock_irqsave(&devtree_lock, flags); 1699 raw_spin_lock_irqsave(&devtree_lock, flags);
1547 rc = __of_add_property(np, prop); 1700 rc = __of_add_property(np, prop);
1548 raw_spin_unlock_irqrestore(&devtree_lock, flags); 1701 raw_spin_unlock_irqrestore(&devtree_lock, flags);
1702 if (rc)
1703 return rc;
1549 1704
1550#ifdef CONFIG_PROC_DEVICETREE 1705 if (of_node_is_attached(np))
1551 /* try to add to proc as well if it was initialized */ 1706 __of_add_property_sysfs(np, prop);
1552 if (!rc && np->pde)
1553 proc_device_tree_add_prop(np->pde, prop);
1554#endif /* CONFIG_PROC_DEVICETREE */
1555 1707
1556 return rc; 1708 return rc;
1557} 1709}
@@ -1593,11 +1745,11 @@ int of_remove_property(struct device_node *np, struct property *prop)
1593 if (!found) 1745 if (!found)
1594 return -ENODEV; 1746 return -ENODEV;
1595 1747
1596#ifdef CONFIG_PROC_DEVICETREE 1748 /* at early boot, bail hear and defer setup to of_init() */
1597 /* try to remove the proc node as well */ 1749 if (!of_kset)
1598 if (np->pde) 1750 return 0;
1599 proc_device_tree_remove_prop(np->pde, prop); 1751
1600#endif /* CONFIG_PROC_DEVICETREE */ 1752 sysfs_remove_bin_file(&np->kobj, &prop->attr);
1601 1753
1602 return 0; 1754 return 0;
1603} 1755}
@@ -1643,16 +1795,17 @@ int of_update_property(struct device_node *np, struct property *newprop)
1643 next = &(*next)->next; 1795 next = &(*next)->next;
1644 } 1796 }
1645 raw_spin_unlock_irqrestore(&devtree_lock, flags); 1797 raw_spin_unlock_irqrestore(&devtree_lock, flags);
1798 if (rc)
1799 return rc;
1800
1801 /* Update the sysfs attribute */
1802 if (oldprop)
1803 sysfs_remove_bin_file(&np->kobj, &oldprop->attr);
1804 __of_add_property_sysfs(np, newprop);
1646 1805
1647 if (!found) 1806 if (!found)
1648 return -ENODEV; 1807 return -ENODEV;
1649 1808
1650#ifdef CONFIG_PROC_DEVICETREE
1651 /* try to add to proc as well if it was initialized */
1652 if (!rc && np->pde)
1653 proc_device_tree_update_prop(np->pde, newprop, oldprop);
1654#endif /* CONFIG_PROC_DEVICETREE */
1655
1656 return 0; 1809 return 0;
1657} 1810}
1658 1811
@@ -1687,22 +1840,6 @@ int of_reconfig_notify(unsigned long action, void *p)
1687 return notifier_to_errno(rc); 1840 return notifier_to_errno(rc);
1688} 1841}
1689 1842
1690#ifdef CONFIG_PROC_DEVICETREE
1691static void of_add_proc_dt_entry(struct device_node *dn)
1692{
1693 struct proc_dir_entry *ent;
1694
1695 ent = proc_mkdir(strrchr(dn->full_name, '/') + 1, dn->parent->pde);
1696 if (ent)
1697 proc_device_tree_add_node(dn, ent);
1698}
1699#else
1700static void of_add_proc_dt_entry(struct device_node *dn)
1701{
1702 return;
1703}
1704#endif
1705
1706/** 1843/**
1707 * of_attach_node - Plug a device node into the tree and global list. 1844 * of_attach_node - Plug a device node into the tree and global list.
1708 */ 1845 */
@@ -1723,22 +1860,10 @@ int of_attach_node(struct device_node *np)
1723 of_node_clear_flag(np, OF_DETACHED); 1860 of_node_clear_flag(np, OF_DETACHED);
1724 raw_spin_unlock_irqrestore(&devtree_lock, flags); 1861 raw_spin_unlock_irqrestore(&devtree_lock, flags);
1725 1862
1726 of_add_proc_dt_entry(np); 1863 of_node_add(np);
1727 return 0; 1864 return 0;
1728} 1865}
1729 1866
1730#ifdef CONFIG_PROC_DEVICETREE
1731static void of_remove_proc_dt_entry(struct device_node *dn)
1732{
1733 proc_remove(dn->pde);
1734}
1735#else
1736static void of_remove_proc_dt_entry(struct device_node *dn)
1737{
1738 return;
1739}
1740#endif
1741
1742/** 1867/**
1743 * of_detach_node - "Unplug" a node from the device tree. 1868 * of_detach_node - "Unplug" a node from the device tree.
1744 * 1869 *
@@ -1794,7 +1919,7 @@ int of_detach_node(struct device_node *np)
1794 of_node_set_flag(np, OF_DETACHED); 1919 of_node_set_flag(np, OF_DETACHED);
1795 raw_spin_unlock_irqrestore(&devtree_lock, flags); 1920 raw_spin_unlock_irqrestore(&devtree_lock, flags);
1796 1921
1797 of_remove_proc_dt_entry(np); 1922 of_node_remove(np);
1798 return rc; 1923 return rc;
1799} 1924}
1800#endif /* defined(CONFIG_OF_DYNAMIC) */ 1925#endif /* defined(CONFIG_OF_DYNAMIC) */
diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
index 501bc83f8cdf..fa16a912a927 100644
--- a/drivers/of/fdt.c
+++ b/drivers/of/fdt.c
@@ -204,6 +204,7 @@ static void * unflatten_dt_node(struct boot_param_header *blob,
204 __alignof__(struct device_node)); 204 __alignof__(struct device_node));
205 if (allnextpp) { 205 if (allnextpp) {
206 char *fn; 206 char *fn;
207 of_node_init(np);
207 np->full_name = fn = ((char *)np) + sizeof(*np); 208 np->full_name = fn = ((char *)np) + sizeof(*np);
208 if (new_format) { 209 if (new_format) {
209 /* rebuild full path for new format */ 210 /* rebuild full path for new format */
@@ -234,7 +235,6 @@ static void * unflatten_dt_node(struct boot_param_header *blob,
234 dad->next->sibling = np; 235 dad->next->sibling = np;
235 dad->next = np; 236 dad->next = np;
236 } 237 }
237 kref_init(&np->kref);
238 } 238 }
239 /* process properties */ 239 /* process properties */
240 while (1) { 240 while (1) {
diff --git a/drivers/of/pdt.c b/drivers/of/pdt.c
index 7b666736c168..36b4035881b0 100644
--- a/drivers/of/pdt.c
+++ b/drivers/of/pdt.c
@@ -176,11 +176,10 @@ 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
182 kref_init(&dp->kref);
183
184 dp->name = of_pdt_get_one_property(node, "name"); 183 dp->name = of_pdt_get_one_property(node, "name");
185 dp->type = of_pdt_get_one_property(node, "device_type"); 184 dp->type = of_pdt_get_one_property(node, "device_type");
186 dp->phandle = node; 185 dp->phandle = node;
diff --git a/drivers/of/selftest.c b/drivers/of/selftest.c
index 6643d1920985..ae4450070503 100644
--- a/drivers/of/selftest.c
+++ b/drivers/of/selftest.c
@@ -30,6 +30,67 @@ static struct selftest_results {
30 } \ 30 } \
31} 31}
32 32
33static void __init of_selftest_dynamic(void)
34{
35 struct device_node *np;
36 struct property *prop;
37
38 np = of_find_node_by_path("/testcase-data");
39 if (!np) {
40 pr_err("missing testcase data\n");
41 return;
42 }
43
44 /* Array of 4 properties for the purpose of testing */
45 prop = kzalloc(sizeof(*prop) * 4, GFP_KERNEL);
46 if (!prop) {
47 selftest(0, "kzalloc() failed\n");
48 return;
49 }
50
51 /* Add a new property - should pass*/
52 prop->name = "new-property";
53 prop->value = "new-property-data";
54 prop->length = strlen(prop->value);
55 selftest(of_add_property(np, prop) == 0, "Adding a new property failed\n");
56
57 /* Try to add an existing property - should fail */
58 prop++;
59 prop->name = "new-property";
60 prop->value = "new-property-data-should-fail";
61 prop->length = strlen(prop->value);
62 selftest(of_add_property(np, prop) != 0,
63 "Adding an existing property should have failed\n");
64
65 /* Try to modify an existing property - should pass */
66 prop->value = "modify-property-data-should-pass";
67 prop->length = strlen(prop->value);
68 selftest(of_update_property(np, prop) == 0,
69 "Updating an existing property should have passed\n");
70
71 /* Try to modify non-existent property - should pass*/
72 prop++;
73 prop->name = "modify-property";
74 prop->value = "modify-missing-property-data-should-pass";
75 prop->length = strlen(prop->value);
76 selftest(of_update_property(np, prop) == 0,
77 "Updating a missing property should have passed\n");
78
79 /* Remove property - should pass */
80 selftest(of_remove_property(np, prop) == 0,
81 "Removing a property should have passed\n");
82
83 /* Adding very large property - should pass */
84 prop++;
85 prop->name = "large-property-PAGE_SIZEx8";
86 prop->length = PAGE_SIZE * 8;
87 prop->value = kzalloc(prop->length, GFP_KERNEL);
88 selftest(prop->value != NULL, "Unable to allocate large buffer\n");
89 if (prop->value)
90 selftest(of_add_property(np, prop) == 0,
91 "Adding a large property should have passed\n");
92}
93
33static void __init of_selftest_parse_phandle_with_args(void) 94static void __init of_selftest_parse_phandle_with_args(void)
34{ 95{
35 struct device_node *np; 96 struct device_node *np;
@@ -378,6 +439,7 @@ static int __init of_selftest(void)
378 of_node_put(np); 439 of_node_put(np);
379 440
380 pr_info("start of selftest - you will see error messages\n"); 441 pr_info("start of selftest - you will see error messages\n");
442 of_selftest_dynamic();
381 of_selftest_parse_phandle_with_args(); 443 of_selftest_parse_phandle_with_args();
382 of_selftest_property_match_string(); 444 of_selftest_property_match_string();
383 of_selftest_parse_interrupts(); 445 of_selftest_parse_interrupts();
diff --git a/drivers/of/testcase-data/tests-phandle.dtsi b/drivers/of/testcase-data/tests-phandle.dtsi
index 0007d3cd7dc2..788a4c24b8f5 100644
--- a/drivers/of/testcase-data/tests-phandle.dtsi
+++ b/drivers/of/testcase-data/tests-phandle.dtsi
@@ -1,6 +1,9 @@
1 1
2/ { 2/ {
3 testcase-data { 3 testcase-data {
4 security-password = "password";
5 duplicate-name = "duplicate";
6 duplicate-name { };
4 phandle-tests { 7 phandle-tests {
5 provider0: provider0 { 8 provider0: provider0 {
6 #phandle-cells = <0>; 9 #phandle-cells = <0>;
diff --git a/fs/proc/Makefile b/fs/proc/Makefile
index ab30716584f5..239493ec718e 100644
--- a/fs/proc/Makefile
+++ b/fs/proc/Makefile
@@ -27,6 +27,5 @@ proc-$(CONFIG_PROC_SYSCTL) += proc_sysctl.o
27proc-$(CONFIG_NET) += proc_net.o 27proc-$(CONFIG_NET) += proc_net.o
28proc-$(CONFIG_PROC_KCORE) += kcore.o 28proc-$(CONFIG_PROC_KCORE) += kcore.o
29proc-$(CONFIG_PROC_VMCORE) += vmcore.o 29proc-$(CONFIG_PROC_VMCORE) += vmcore.o
30proc-$(CONFIG_PROC_DEVICETREE) += proc_devtree.o
31proc-$(CONFIG_PRINTK) += kmsg.o 30proc-$(CONFIG_PRINTK) += kmsg.o
32proc-$(CONFIG_PROC_PAGE_MONITOR) += page.o 31proc-$(CONFIG_PROC_PAGE_MONITOR) += page.o
diff --git a/fs/proc/internal.h b/fs/proc/internal.h
index 651d09a11dde..3ab6d14e71c5 100644
--- a/fs/proc/internal.h
+++ b/fs/proc/internal.h
@@ -211,13 +211,6 @@ extern int proc_fill_super(struct super_block *);
211extern void proc_entry_rundown(struct proc_dir_entry *); 211extern void proc_entry_rundown(struct proc_dir_entry *);
212 212
213/* 213/*
214 * proc_devtree.c
215 */
216#ifdef CONFIG_PROC_DEVICETREE
217extern void proc_device_tree_init(void);
218#endif
219
220/*
221 * proc_namespaces.c 214 * proc_namespaces.c
222 */ 215 */
223extern const struct inode_operations proc_ns_dir_inode_operations; 216extern const struct inode_operations proc_ns_dir_inode_operations;
diff --git a/fs/proc/proc_devtree.c b/fs/proc/proc_devtree.c
deleted file mode 100644
index c82dd5147845..000000000000
--- a/fs/proc/proc_devtree.c
+++ /dev/null
@@ -1,241 +0,0 @@
1/*
2 * proc_devtree.c - handles /proc/device-tree
3 *
4 * Copyright 1997 Paul Mackerras
5 */
6#include <linux/errno.h>
7#include <linux/init.h>
8#include <linux/time.h>
9#include <linux/proc_fs.h>
10#include <linux/seq_file.h>
11#include <linux/printk.h>
12#include <linux/stat.h>
13#include <linux/string.h>
14#include <linux/of.h>
15#include <linux/export.h>
16#include <linux/slab.h>
17#include <asm/uaccess.h>
18#include "internal.h"
19
20static inline void set_node_proc_entry(struct device_node *np,
21 struct proc_dir_entry *de)
22{
23 np->pde = de;
24}
25
26static struct proc_dir_entry *proc_device_tree;
27
28/*
29 * Supply data on a read from /proc/device-tree/node/property.
30 */
31static int property_proc_show(struct seq_file *m, void *v)
32{
33 struct property *pp = m->private;
34
35 seq_write(m, pp->value, pp->length);
36 return 0;
37}
38
39static int property_proc_open(struct inode *inode, struct file *file)
40{
41 return single_open(file, property_proc_show, __PDE_DATA(inode));
42}
43
44static const struct file_operations property_proc_fops = {
45 .owner = THIS_MODULE,
46 .open = property_proc_open,
47 .read = seq_read,
48 .llseek = seq_lseek,
49 .release = single_release,
50};
51
52/*
53 * For a node with a name like "gc@10", we make symlinks called "gc"
54 * and "@10" to it.
55 */
56
57/*
58 * Add a property to a node
59 */
60static struct proc_dir_entry *
61__proc_device_tree_add_prop(struct proc_dir_entry *de, struct property *pp,
62 const char *name)
63{
64 struct proc_dir_entry *ent;
65
66 /*
67 * Unfortunately proc_register puts each new entry
68 * at the beginning of the list. So we rearrange them.
69 */
70 ent = proc_create_data(name,
71 strncmp(name, "security-", 9) ? S_IRUGO : S_IRUSR,
72 de, &property_proc_fops, pp);
73 if (ent == NULL)
74 return NULL;
75
76 if (!strncmp(name, "security-", 9))
77 proc_set_size(ent, 0); /* don't leak number of password chars */
78 else
79 proc_set_size(ent, pp->length);
80
81 return ent;
82}
83
84
85void proc_device_tree_add_prop(struct proc_dir_entry *pde, struct property *prop)
86{
87 __proc_device_tree_add_prop(pde, prop, prop->name);
88}
89
90void proc_device_tree_remove_prop(struct proc_dir_entry *pde,
91 struct property *prop)
92{
93 remove_proc_entry(prop->name, pde);
94}
95
96void proc_device_tree_update_prop(struct proc_dir_entry *pde,
97 struct property *newprop,
98 struct property *oldprop)
99{
100 struct proc_dir_entry *ent;
101
102 if (!oldprop) {
103 proc_device_tree_add_prop(pde, newprop);
104 return;
105 }
106
107 for (ent = pde->subdir; ent != NULL; ent = ent->next)
108 if (ent->data == oldprop)
109 break;
110 if (ent == NULL) {
111 pr_warn("device-tree: property \"%s\" does not exist\n",
112 oldprop->name);
113 } else {
114 ent->data = newprop;
115 ent->size = newprop->length;
116 }
117}
118
119/*
120 * Various dodgy firmware might give us nodes and/or properties with
121 * conflicting names. That's generally ok, except for exporting via /proc,
122 * so munge names here to ensure they're unique.
123 */
124
125static int duplicate_name(struct proc_dir_entry *de, const char *name)
126{
127 struct proc_dir_entry *ent;
128 int found = 0;
129
130 spin_lock(&proc_subdir_lock);
131
132 for (ent = de->subdir; ent != NULL; ent = ent->next) {
133 if (strcmp(ent->name, name) == 0) {
134 found = 1;
135 break;
136 }
137 }
138
139 spin_unlock(&proc_subdir_lock);
140
141 return found;
142}
143
144static const char *fixup_name(struct device_node *np, struct proc_dir_entry *de,
145 const char *name)
146{
147 char *fixed_name;
148 int fixup_len = strlen(name) + 2 + 1; /* name + #x + \0 */
149 int i = 1, size;
150
151realloc:
152 fixed_name = kmalloc(fixup_len, GFP_KERNEL);
153 if (fixed_name == NULL) {
154 pr_err("device-tree: Out of memory trying to fixup "
155 "name \"%s\"\n", name);
156 return name;
157 }
158
159retry:
160 size = snprintf(fixed_name, fixup_len, "%s#%d", name, i);
161 size++; /* account for NULL */
162
163 if (size > fixup_len) {
164 /* We ran out of space, free and reallocate. */
165 kfree(fixed_name);
166 fixup_len = size;
167 goto realloc;
168 }
169
170 if (duplicate_name(de, fixed_name)) {
171 /* Multiple duplicates. Retry with a different offset. */
172 i++;
173 goto retry;
174 }
175
176 pr_warn("device-tree: Duplicate name in %s, renamed to \"%s\"\n",
177 np->full_name, fixed_name);
178
179 return fixed_name;
180}
181
182/*
183 * Process a node, adding entries for its children and its properties.
184 */
185void proc_device_tree_add_node(struct device_node *np,
186 struct proc_dir_entry *de)
187{
188 struct property *pp;
189 struct proc_dir_entry *ent;
190 struct device_node *child;
191 const char *p;
192
193 set_node_proc_entry(np, de);
194 for (child = NULL; (child = of_get_next_child(np, child));) {
195 /* Use everything after the last slash, or the full name */
196 p = kbasename(child->full_name);
197
198 if (duplicate_name(de, p))
199 p = fixup_name(np, de, p);
200
201 ent = proc_mkdir(p, de);
202 if (ent == NULL)
203 break;
204 proc_device_tree_add_node(child, ent);
205 }
206 of_node_put(child);
207
208 for (pp = np->properties; pp != NULL; pp = pp->next) {
209 p = pp->name;
210
211 if (strchr(p, '/'))
212 continue;
213
214 if (duplicate_name(de, p))
215 p = fixup_name(np, de, p);
216
217 ent = __proc_device_tree_add_prop(de, pp, p);
218 if (ent == NULL)
219 break;
220 }
221}
222
223/*
224 * Called on initialization to set up the /proc/device-tree subtree
225 */
226void __init proc_device_tree_init(void)
227{
228 struct device_node *root;
229
230 proc_device_tree = proc_mkdir("device-tree", NULL);
231 if (proc_device_tree == NULL)
232 return;
233 root = of_find_node_by_path("/");
234 if (root == NULL) {
235 remove_proc_entry("device-tree", NULL);
236 pr_debug("/proc/device-tree: can't find root\n");
237 return;
238 }
239 proc_device_tree_add_node(root, proc_device_tree);
240 of_node_put(root);
241}
diff --git a/fs/proc/root.c b/fs/proc/root.c
index 87dbcbef7fe4..7bbeb5257af1 100644
--- a/fs/proc/root.c
+++ b/fs/proc/root.c
@@ -183,9 +183,6 @@ void __init proc_root_init(void)
183 proc_mkdir("openprom", NULL); 183 proc_mkdir("openprom", NULL);
184#endif 184#endif
185 proc_tty_init(); 185 proc_tty_init();
186#ifdef CONFIG_PROC_DEVICETREE
187 proc_device_tree_init();
188#endif
189 proc_mkdir("bus", NULL); 186 proc_mkdir("bus", NULL);
190 proc_sys_init(); 187 proc_sys_init();
191} 188}
diff --git a/include/linux/of.h b/include/linux/of.h
index b3d0f6d86e3b..a8b9dad90c64 100644
--- a/include/linux/of.h
+++ b/include/linux/of.h
@@ -18,7 +18,7 @@
18#include <linux/types.h> 18#include <linux/types.h>
19#include <linux/bitops.h> 19#include <linux/bitops.h>
20#include <linux/errno.h> 20#include <linux/errno.h>
21#include <linux/kref.h> 21#include <linux/kobject.h>
22#include <linux/mod_devicetable.h> 22#include <linux/mod_devicetable.h>
23#include <linux/spinlock.h> 23#include <linux/spinlock.h>
24#include <linux/topology.h> 24#include <linux/topology.h>
@@ -37,6 +37,7 @@ struct property {
37 struct property *next; 37 struct property *next;
38 unsigned long _flags; 38 unsigned long _flags;
39 unsigned int unique_id; 39 unsigned int unique_id;
40 struct bin_attribute attr;
40}; 41};
41 42
42#if defined(CONFIG_SPARC) 43#if defined(CONFIG_SPARC)
@@ -56,8 +57,7 @@ struct device_node {
56 struct device_node *sibling; 57 struct device_node *sibling;
57 struct device_node *next; /* next device of same type */ 58 struct device_node *next; /* next device of same type */
58 struct device_node *allnext; /* next in list of all nodes */ 59 struct device_node *allnext; /* next in list of all nodes */
59 struct proc_dir_entry *pde; /* this node's proc directory */ 60 struct kobject kobj;
60 struct kref kref;
61 unsigned long _flags; 61 unsigned long _flags;
62 void *data; 62 void *data;
63#if defined(CONFIG_SPARC) 63#if defined(CONFIG_SPARC)
@@ -74,6 +74,27 @@ 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 */
80extern struct kobj_type of_node_ktype;
81static 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 */
87static 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) */
93static inline int of_node_is_attached(struct device_node *node)
94{
95 return node && node->kobj.state_in_sysfs;
96}
97
77#ifdef CONFIG_OF_DYNAMIC 98#ifdef CONFIG_OF_DYNAMIC
78extern struct device_node *of_node_get(struct device_node *node); 99extern struct device_node *of_node_get(struct device_node *node);
79extern void of_node_put(struct device_node *node); 100extern void of_node_put(struct device_node *node);
@@ -187,6 +208,8 @@ static inline const char *of_node_full_name(const struct device_node *np)
187 return np ? np->full_name : "<no-node>"; 208 return np ? np->full_name : "<no-node>";
188} 209}
189 210
211#define for_each_of_allnodes(dn) \
212 for (dn = of_allnodes; dn; dn = dn->allnext)
190extern struct device_node *of_find_node_by_name(struct device_node *from, 213extern struct device_node *of_find_node_by_name(struct device_node *from,
191 const char *name); 214 const char *name);
192extern struct device_node *of_find_node_by_type(struct device_node *from, 215extern struct device_node *of_find_node_by_type(struct device_node *from,
@@ -653,14 +676,4 @@ static inline int of_get_available_child_count(const struct device_node *np)
653 return num; 676 return num;
654} 677}
655 678
656#if defined(CONFIG_PROC_FS) && defined(CONFIG_PROC_DEVICETREE)
657extern void proc_device_tree_add_node(struct device_node *, struct proc_dir_entry *);
658extern void proc_device_tree_add_prop(struct proc_dir_entry *pde, struct property *prop);
659extern void proc_device_tree_remove_prop(struct proc_dir_entry *pde,
660 struct property *prop);
661extern void proc_device_tree_update_prop(struct proc_dir_entry *pde,
662 struct property *newprop,
663 struct property *oldprop);
664#endif
665
666#endif /* _LINUX_OF_H */ 679#endif /* _LINUX_OF_H */