aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-09-25 10:39:29 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2014-09-25 10:39:29 -0400
commit4d3afba349efbb5d4a3e42345f1976ec2371b7f1 (patch)
tree6ad5c041da74049418f316ca843fa86a344de77e
parent005f800508eb391480f463dad3d54e5b4ec67d57 (diff)
parent9aacd602f0246f1b1f3c4684b2ab13d0772976f7 (diff)
Merge tag 'devicetree-for-linus' of git://git.secretlab.ca/git/linux
Pull devicetree bug fixes and documentation from Grant Likely: "Several bug fix commits for issues found in the v3.17 rc series. Most of these are minor in that they aren't actively dangerous, but they have been seen in the wild. The one important fix is commit 7dbe5849fb50 ("of: make sure of_alias is initialized before accessing it"), without which some powerpc platforms will fail to find stdout for the console" * tag 'devicetree-for-linus' of git://git.secretlab.ca/git/linux: of/fdt: fix memory range check of: Fix memory block alignment in early_init_dt_add_memory_arch() of: make sure of_alias is initialized before accessing it of: Documentation regarding attaching OF Selftest testdata of: Disabling OF functions that use sysfs if CONFIG_SYSFS disabled of: correct of_console_check()'s return value
-rw-r--r--Documentation/devicetree/of_selftest.txt211
-rw-r--r--drivers/of/base.c16
-rw-r--r--drivers/of/dynamic.c3
-rw-r--r--drivers/of/fdt.c14
4 files changed, 237 insertions, 7 deletions
diff --git a/Documentation/devicetree/of_selftest.txt b/Documentation/devicetree/of_selftest.txt
new file mode 100644
index 000000000000..3a2f54d07fc5
--- /dev/null
+++ b/Documentation/devicetree/of_selftest.txt
@@ -0,0 +1,211 @@
1Open Firmware Device Tree Selftest
2----------------------------------
3
4Author: Gaurav Minocha <gaurav.minocha.os@gmail.com>
5
61. Introduction
7
8This document explains how the test data required for executing OF selftest
9is attached to the live tree dynamically, independent of the machine's
10architecture.
11
12It is recommended to read the following documents before moving ahead.
13
14[1] Documentation/devicetree/usage-model.txt
15[2] http://www.devicetree.org/Device_Tree_Usage
16
17OF Selftest has been designed to test the interface (include/linux/of.h)
18provided to device driver developers to fetch the device information..etc.
19from the unflattened device tree data structure. This interface is used by
20most of the device drivers in various use cases.
21
22
232. Test-data
24
25The Device Tree Source file (drivers/of/testcase-data/testcases.dts) contains
26the test data required for executing the unit tests automated in
27drivers/of/selftests.c. Currently, following Device Tree Source Include files
28(.dtsi) are included in testcase.dts:
29
30drivers/of/testcase-data/tests-interrupts.dtsi
31drivers/of/testcase-data/tests-platform.dtsi
32drivers/of/testcase-data/tests-phandle.dtsi
33drivers/of/testcase-data/tests-match.dtsi
34
35When the kernel is build with OF_SELFTEST enabled, then the following make rule
36
37$(obj)/%.dtb: $(src)/%.dts FORCE
38 $(call if_changed_dep, dtc)
39
40is used to compile the DT source file (testcase.dts) into a binary blob
41(testcase.dtb), also referred as flattened DT.
42
43After that, using the following rule the binary blob above is wrapped as an
44assembly file (testcase.dtb.S).
45
46$(obj)/%.dtb.S: $(obj)/%.dtb
47 $(call cmd, dt_S_dtb)
48
49The assembly file is compiled into an object file (testcase.dtb.o), and is
50linked into the kernel image.
51
52
532.1. Adding the test data
54
55Un-flattened device tree structure:
56
57Un-flattened device tree consists of connected device_node(s) in form of a tree
58structure described below.
59
60// following struct members are used to construct the tree
61struct device_node {
62 ...
63 struct device_node *parent;
64 struct device_node *child;
65 struct device_node *sibling;
66 struct device_node *allnext; /* next in list of all nodes */
67 ...
68 };
69
70Figure 1, describes a generic structure of machine’s un-flattened device tree
71considering only child and sibling pointers. There exists another pointer,
72*parent, that is used to traverse the tree in the reverse direction. So, at
73a particular level the child node and all the sibling nodes will have a parent
74pointer pointing to a common node (e.g. child1, sibling2, sibling3, sibling4’s
75parent points to root node)
76
77root (‘/’)
78 |
79child1 -> sibling2 -> sibling3 -> sibling4 -> null
80 | | | |
81 | | | null
82 | | |
83 | | child31 -> sibling32 -> null
84 | | | |
85 | | null null
86 | |
87 | child21 -> sibling22 -> sibling23 -> null
88 | | | |
89 | null null null
90 |
91child11 -> sibling12 -> sibling13 -> sibling14 -> null
92 | | | |
93 | | | null
94 | | |
95 null null child131 -> null
96 |
97 null
98
99Figure 1: Generic structure of un-flattened device tree
100
101
102*allnext: it is used to link all the nodes of DT into a list. So, for the
103 above tree the list would be as follows:
104
105root->child1->child11->sibling12->sibling13->child131->sibling14->sibling2->
106child21->sibling22->sibling23->sibling3->child31->sibling32->sibling4->null
107
108Before executing OF selftest, it is required to attach the test data to
109machine's device tree (if present). So, when selftest_data_add() is called,
110at first it reads the flattened device tree data linked into the kernel image
111via the following kernel symbols:
112
113__dtb_testcases_begin - address marking the start of test data blob
114__dtb_testcases_end - address marking the end of test data blob
115
116Secondly, it calls of_fdt_unflatten_device_tree() to unflatten the flattened
117blob. And finally, if the machine’s device tree (i.e live tree) is present,
118then it attaches the unflattened test data tree to the live tree, else it
119attaches itself as a live device tree.
120
121attach_node_and_children() uses of_attach_node() to attach the nodes into the
122live tree as explained below. To explain the same, the test data tree described
123 in Figure 2 is attached to the live tree described in Figure 1.
124
125root (‘/’)
126 |
127 testcase-data
128 |
129 test-child0 -> test-sibling1 -> test-sibling2 -> test-sibling3 -> null
130 | | | |
131 test-child01 null null null
132
133
134allnext list:
135
136root->testcase-data->test-child0->test-child01->test-sibling1->test-sibling2
137->test-sibling3->null
138
139Figure 2: Example test data tree to be attached to live tree.
140
141According to the scenario above, the live tree is already present so it isn’t
142required to attach the root(‘/’) node. All other nodes are attached by calling
143of_attach_node() on each node.
144
145In the function of_attach_node(), the new node is attached as the child of the
146given parent in live tree. But, if parent already has a child then the new node
147replaces the current child and turns it into its sibling. So, when the testcase
148data node is attached to the live tree above (Figure 1), the final structure is
149 as shown in Figure 3.
150
151root (‘/’)
152 |
153testcase-data -> child1 -> sibling2 -> sibling3 -> sibling4 -> null
154 | | | | |
155 (...) | | | null
156 | | child31 -> sibling32 -> null
157 | | | |
158 | | null null
159 | |
160 | child21 -> sibling22 -> sibling23 -> null
161 | | | |
162 | null null null
163 |
164 child11 -> sibling12 -> sibling13 -> sibling14 -> null
165 | | | |
166 null null | null
167 |
168 child131 -> null
169 |
170 null
171-----------------------------------------------------------------------
172
173root (‘/’)
174 |
175testcase-data -> child1 -> sibling2 -> sibling3 -> sibling4 -> null
176 | | | | |
177 | (...) (...) (...) null
178 |
179test-sibling3 -> test-sibling2 -> test-sibling1 -> test-child0 -> null
180 | | | |
181 null null null test-child01
182
183
184Figure 3: Live device tree structure after attaching the testcase-data.
185
186
187Astute readers would have noticed that test-child0 node becomes the last
188sibling compared to the earlier structure (Figure 2). After attaching first
189test-child0 the test-sibling1 is attached that pushes the child node
190(i.e. test-child0) to become a sibling and makes itself a child node,
191 as mentioned above.
192
193If a duplicate node is found (i.e. if a node with same full_name property is
194already present in the live tree), then the node isn’t attached rather its
195properties are updated to the live tree’s node by calling the function
196update_node_properties().
197
198
1992.2. Removing the test data
200
201Once the test case execution is complete, selftest_data_remove is called in
202order to remove the device nodes attached initially (first the leaf nodes are
203detached and then moving up the parent nodes are removed, and eventually the
204whole tree). selftest_data_remove() calls detach_node_and_children() that uses
205of_detach_node() to detach the nodes from the live device tree.
206
207To detach a node, of_detach_node() first updates all_next linked list, by
208attaching the previous node’s allnext to current node’s allnext pointer. And
209then, it either updates the child pointer of given node’s parent to its
210sibling or attaches the previous sibling to the given node’s sibling, as
211appropriate. That is it :)
diff --git a/drivers/of/base.c b/drivers/of/base.c
index d8574adf0d62..293ed4b687ba 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -138,6 +138,9 @@ int __of_add_property_sysfs(struct device_node *np, struct property *pp)
138 /* Important: Don't leak passwords */ 138 /* Important: Don't leak passwords */
139 bool secure = strncmp(pp->name, "security-", 9) == 0; 139 bool secure = strncmp(pp->name, "security-", 9) == 0;
140 140
141 if (!IS_ENABLED(CONFIG_SYSFS))
142 return 0;
143
141 if (!of_kset || !of_node_is_attached(np)) 144 if (!of_kset || !of_node_is_attached(np))
142 return 0; 145 return 0;
143 146
@@ -158,6 +161,9 @@ int __of_attach_node_sysfs(struct device_node *np)
158 struct property *pp; 161 struct property *pp;
159 int rc; 162 int rc;
160 163
164 if (!IS_ENABLED(CONFIG_SYSFS))
165 return 0;
166
161 if (!of_kset) 167 if (!of_kset)
162 return 0; 168 return 0;
163 169
@@ -1713,6 +1719,9 @@ int __of_remove_property(struct device_node *np, struct property *prop)
1713 1719
1714void __of_remove_property_sysfs(struct device_node *np, struct property *prop) 1720void __of_remove_property_sysfs(struct device_node *np, struct property *prop)
1715{ 1721{
1722 if (!IS_ENABLED(CONFIG_SYSFS))
1723 return;
1724
1716 /* at early boot, bail here and defer setup to of_init() */ 1725 /* at early boot, bail here and defer setup to of_init() */
1717 if (of_kset && of_node_is_attached(np)) 1726 if (of_kset && of_node_is_attached(np))
1718 sysfs_remove_bin_file(&np->kobj, &prop->attr); 1727 sysfs_remove_bin_file(&np->kobj, &prop->attr);
@@ -1777,6 +1786,9 @@ int __of_update_property(struct device_node *np, struct property *newprop,
1777void __of_update_property_sysfs(struct device_node *np, struct property *newprop, 1786void __of_update_property_sysfs(struct device_node *np, struct property *newprop,
1778 struct property *oldprop) 1787 struct property *oldprop)
1779{ 1788{
1789 if (!IS_ENABLED(CONFIG_SYSFS))
1790 return;
1791
1780 /* At early boot, bail out and defer setup to of_init() */ 1792 /* At early boot, bail out and defer setup to of_init() */
1781 if (!of_kset) 1793 if (!of_kset)
1782 return; 1794 return;
@@ -1847,6 +1859,7 @@ void of_alias_scan(void * (*dt_alloc)(u64 size, u64 align))
1847{ 1859{
1848 struct property *pp; 1860 struct property *pp;
1849 1861
1862 of_aliases = of_find_node_by_path("/aliases");
1850 of_chosen = of_find_node_by_path("/chosen"); 1863 of_chosen = of_find_node_by_path("/chosen");
1851 if (of_chosen == NULL) 1864 if (of_chosen == NULL)
1852 of_chosen = of_find_node_by_path("/chosen@0"); 1865 of_chosen = of_find_node_by_path("/chosen@0");
@@ -1862,7 +1875,6 @@ void of_alias_scan(void * (*dt_alloc)(u64 size, u64 align))
1862 of_stdout = of_find_node_by_path(name); 1875 of_stdout = of_find_node_by_path(name);
1863 } 1876 }
1864 1877
1865 of_aliases = of_find_node_by_path("/aliases");
1866 if (!of_aliases) 1878 if (!of_aliases)
1867 return; 1879 return;
1868 1880
@@ -1986,7 +1998,7 @@ bool of_console_check(struct device_node *dn, char *name, int index)
1986{ 1998{
1987 if (!dn || dn != of_stdout || console_set_on_cmdline) 1999 if (!dn || dn != of_stdout || console_set_on_cmdline)
1988 return false; 2000 return false;
1989 return add_preferred_console(name, index, NULL); 2001 return !add_preferred_console(name, index, NULL);
1990} 2002}
1991EXPORT_SYMBOL_GPL(of_console_check); 2003EXPORT_SYMBOL_GPL(of_console_check);
1992 2004
diff --git a/drivers/of/dynamic.c b/drivers/of/dynamic.c
index 54fecc49a1fe..f297891d8529 100644
--- a/drivers/of/dynamic.c
+++ b/drivers/of/dynamic.c
@@ -45,6 +45,9 @@ void __of_detach_node_sysfs(struct device_node *np)
45{ 45{
46 struct property *pp; 46 struct property *pp;
47 47
48 if (!IS_ENABLED(CONFIG_SYSFS))
49 return;
50
48 BUG_ON(!of_node_is_initialized(np)); 51 BUG_ON(!of_node_is_initialized(np));
49 if (!of_kset) 52 if (!of_kset)
50 return; 53 return;
diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
index 79cb8313c7d8..d1ffca8b34ea 100644
--- a/drivers/of/fdt.c
+++ b/drivers/of/fdt.c
@@ -928,7 +928,11 @@ int __init early_init_dt_scan_chosen(unsigned long node, const char *uname,
928void __init __weak early_init_dt_add_memory_arch(u64 base, u64 size) 928void __init __weak early_init_dt_add_memory_arch(u64 base, u64 size)
929{ 929{
930 const u64 phys_offset = __pa(PAGE_OFFSET); 930 const u64 phys_offset = __pa(PAGE_OFFSET);
931 base &= PAGE_MASK; 931
932 if (!PAGE_ALIGNED(base)) {
933 size -= PAGE_SIZE - (base & ~PAGE_MASK);
934 base = PAGE_ALIGN(base);
935 }
932 size &= PAGE_MASK; 936 size &= PAGE_MASK;
933 937
934 if (base > MAX_PHYS_ADDR) { 938 if (base > MAX_PHYS_ADDR) {
@@ -937,10 +941,10 @@ void __init __weak early_init_dt_add_memory_arch(u64 base, u64 size)
937 return; 941 return;
938 } 942 }
939 943
940 if (base + size > MAX_PHYS_ADDR) { 944 if (base + size - 1 > MAX_PHYS_ADDR) {
941 pr_warning("Ignoring memory range 0x%lx - 0x%llx\n", 945 pr_warning("Ignoring memory range 0x%llx - 0x%llx\n",
942 ULONG_MAX, base + size); 946 ((u64)MAX_PHYS_ADDR) + 1, base + size);
943 size = MAX_PHYS_ADDR - base; 947 size = MAX_PHYS_ADDR - base + 1;
944 } 948 }
945 949
946 if (base + size < phys_offset) { 950 if (base + size < phys_offset) {