diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-08-14 11:53:39 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-08-14 11:53:39 -0400 |
commit | ae36e95cf81c98b111b84317adeb358aaffa80e2 (patch) | |
tree | 87ef144d3392cca199448117a737c657b7c4663a /drivers/of | |
parent | cc8a44c671fd3a2c792e9e1f59ea1df52697cc8b (diff) | |
parent | 663d3f7c2e5e1b018a4c53277ccfde40329d98ca (diff) |
Merge tag 'devicetree-for-linus' of git://git.secretlab.ca/git/linux
Pull device tree updates from Grant Likely:
"The branch contains the following device tree changes the v3.17 merge
window:
Group changes to the device tree. In preparation for adding device
tree overlay support, OF_DYNAMIC is reworked so that a set of device
tree changes can be prepared and applied to the tree all at once.
OF_RECONFIG notifiers see the most significant change here so that
users always get a consistent view of the tree. Notifiers generation
is moved from before a change to after it, and notifiers for a group
of changes are emitted after the entire block of changes have been
applied
Automatic console selection from DT. Console drivers can now use
of_console_check() to see if the device node is specified as a console
device. If so then it gets added as a preferred console. UART
devices get this support automatically when uart_add_one_port() is
called.
DT unit tests no longer depend on pre-loaded data in the device tree.
Data is loaded dynamically at the start of unit tests, and then
unloaded again when the tests have completed.
Also contains a few bugfixes for reserved regions and early memory
setup"
* tag 'devicetree-for-linus' of git://git.secretlab.ca/git/linux: (21 commits)
of: Fixing OF Selftest build error
drivers: of: add automated assignment of reserved regions to client devices
of: Use proper types for checking memory overflow
of: typo fix in __of_prop_dup()
Adding selftest testdata dynamically into live tree
of: Add todo tasklist for Devicetree
of: Transactional DT support.
of: Reorder device tree changes and notifiers
of: Move dynamic node fixups out of powerpc and into common code
of: Make sure attached nodes don't carry along extra children
of: Make devicetree sysfs update functions consistent.
of: Create unlocked versions of node and property add/remove functions
OF: Utility helper functions for dynamic nodes
of: Move CONFIG_OF_DYNAMIC code into a separate file
of: rename of_aliases_mutex to just of_mutex
of/platform: Fix of_platform_device_destroy iteration of devices
of: Migrate of_find_node_by_name() users to for_each_node_by_name()
tty: Update hypervisor tty drivers to use core stdout parsing code.
arm/versatile: Add the uart as the stdout device.
of: Enable console on serial ports specified by /chosen/stdout-path
...
Diffstat (limited to 'drivers/of')
-rw-r--r-- | drivers/of/Kconfig | 3 | ||||
-rw-r--r-- | drivers/of/Makefile | 4 | ||||
-rw-r--r-- | drivers/of/base.c | 451 | ||||
-rw-r--r-- | drivers/of/device.c | 4 | ||||
-rw-r--r-- | drivers/of/dynamic.c | 660 | ||||
-rw-r--r-- | drivers/of/fdt.c | 22 | ||||
-rw-r--r-- | drivers/of/of_private.h | 59 | ||||
-rw-r--r-- | drivers/of/of_reserved_mem.c | 70 | ||||
-rw-r--r-- | drivers/of/platform.c | 32 | ||||
-rw-r--r-- | drivers/of/selftest.c | 235 | ||||
-rw-r--r-- | drivers/of/testcase-data/testcases.dts | 15 | ||||
-rw-r--r-- | drivers/of/testcase-data/testcases.dtsi | 4 |
12 files changed, 1188 insertions, 371 deletions
diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig index 2dcb0541012d..5160c4eb73c2 100644 --- a/drivers/of/Kconfig +++ b/drivers/of/Kconfig | |||
@@ -9,7 +9,8 @@ menu "Device Tree and Open Firmware support" | |||
9 | 9 | ||
10 | config OF_SELFTEST | 10 | config OF_SELFTEST |
11 | bool "Device Tree Runtime self tests" | 11 | bool "Device Tree Runtime self tests" |
12 | depends on OF_IRQ | 12 | depends on OF_IRQ && OF_EARLY_FLATTREE |
13 | select OF_DYNAMIC | ||
13 | help | 14 | help |
14 | This option builds in test cases for the device tree infrastructure | 15 | This option builds in test cases for the device tree infrastructure |
15 | that are executed once at boot time, and the results dumped to the | 16 | that are executed once at boot time, and the results dumped to the |
diff --git a/drivers/of/Makefile b/drivers/of/Makefile index 099b1fb00af4..2b6a7b129d10 100644 --- a/drivers/of/Makefile +++ b/drivers/of/Makefile | |||
@@ -1,11 +1,13 @@ | |||
1 | obj-y = base.o device.o platform.o | 1 | obj-y = base.o device.o platform.o |
2 | obj-$(CONFIG_OF_DYNAMIC) += dynamic.o | ||
2 | obj-$(CONFIG_OF_FLATTREE) += fdt.o | 3 | obj-$(CONFIG_OF_FLATTREE) += fdt.o |
3 | obj-$(CONFIG_OF_EARLY_FLATTREE) += fdt_address.o | 4 | obj-$(CONFIG_OF_EARLY_FLATTREE) += fdt_address.o |
4 | obj-$(CONFIG_OF_PROMTREE) += pdt.o | 5 | obj-$(CONFIG_OF_PROMTREE) += pdt.o |
5 | obj-$(CONFIG_OF_ADDRESS) += address.o | 6 | obj-$(CONFIG_OF_ADDRESS) += address.o |
6 | obj-$(CONFIG_OF_IRQ) += irq.o | 7 | obj-$(CONFIG_OF_IRQ) += irq.o |
7 | obj-$(CONFIG_OF_NET) += of_net.o | 8 | obj-$(CONFIG_OF_NET) += of_net.o |
8 | obj-$(CONFIG_OF_SELFTEST) += selftest.o | 9 | obj-$(CONFIG_OF_SELFTEST) += of_selftest.o |
10 | of_selftest-objs := selftest.o testcase-data/testcases.dtb.o | ||
9 | obj-$(CONFIG_OF_MDIO) += of_mdio.o | 11 | obj-$(CONFIG_OF_MDIO) += of_mdio.o |
10 | obj-$(CONFIG_OF_PCI) += of_pci.o | 12 | obj-$(CONFIG_OF_PCI) += of_pci.o |
11 | obj-$(CONFIG_OF_PCI_IRQ) += of_pci_irq.o | 13 | obj-$(CONFIG_OF_PCI_IRQ) += of_pci_irq.o |
diff --git a/drivers/of/base.c b/drivers/of/base.c index b9864806e9b8..d8574adf0d62 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c | |||
@@ -17,6 +17,7 @@ | |||
17 | * as published by the Free Software Foundation; either version | 17 | * as published by the Free Software Foundation; either version |
18 | * 2 of the License, or (at your option) any later version. | 18 | * 2 of the License, or (at your option) any later version. |
19 | */ | 19 | */ |
20 | #include <linux/console.h> | ||
20 | #include <linux/ctype.h> | 21 | #include <linux/ctype.h> |
21 | #include <linux/cpu.h> | 22 | #include <linux/cpu.h> |
22 | #include <linux/module.h> | 23 | #include <linux/module.h> |
@@ -35,15 +36,17 @@ struct device_node *of_allnodes; | |||
35 | EXPORT_SYMBOL(of_allnodes); | 36 | EXPORT_SYMBOL(of_allnodes); |
36 | struct device_node *of_chosen; | 37 | struct device_node *of_chosen; |
37 | struct device_node *of_aliases; | 38 | struct device_node *of_aliases; |
38 | static struct device_node *of_stdout; | 39 | struct device_node *of_stdout; |
39 | 40 | ||
40 | static struct kset *of_kset; | 41 | struct kset *of_kset; |
41 | 42 | ||
42 | /* | 43 | /* |
43 | * Used to protect the of_aliases; but also overloaded to hold off addition of | 44 | * Used to protect the of_aliases, to hold off addition of nodes to sysfs. |
44 | * nodes to sysfs | 45 | * This mutex must be held whenever modifications are being made to the |
46 | * device tree. The of_{attach,detach}_node() and | ||
47 | * of_{add,remove,update}_property() helpers make sure this happens. | ||
45 | */ | 48 | */ |
46 | DEFINE_MUTEX(of_aliases_mutex); | 49 | DEFINE_MUTEX(of_mutex); |
47 | 50 | ||
48 | /* use when traversing tree through the allnext, child, sibling, | 51 | /* use when traversing tree through the allnext, child, sibling, |
49 | * or parent members of struct device_node. | 52 | * or parent members of struct device_node. |
@@ -89,79 +92,7 @@ int __weak of_node_to_nid(struct device_node *np) | |||
89 | } | 92 | } |
90 | #endif | 93 | #endif |
91 | 94 | ||
92 | #if defined(CONFIG_OF_DYNAMIC) | 95 | #ifndef CONFIG_OF_DYNAMIC |
93 | /** | ||
94 | * of_node_get - Increment refcount of a node | ||
95 | * @node: Node to inc refcount, NULL is supported to | ||
96 | * simplify writing of callers | ||
97 | * | ||
98 | * Returns node. | ||
99 | */ | ||
100 | struct device_node *of_node_get(struct device_node *node) | ||
101 | { | ||
102 | if (node) | ||
103 | kobject_get(&node->kobj); | ||
104 | return node; | ||
105 | } | ||
106 | EXPORT_SYMBOL(of_node_get); | ||
107 | |||
108 | static inline struct device_node *kobj_to_device_node(struct kobject *kobj) | ||
109 | { | ||
110 | return container_of(kobj, struct device_node, kobj); | ||
111 | } | ||
112 | |||
113 | /** | ||
114 | * of_node_release - release a dynamically allocated node | ||
115 | * @kref: kref element of the node to be released | ||
116 | * | ||
117 | * In of_node_put() this function is passed to kref_put() | ||
118 | * as the destructor. | ||
119 | */ | ||
120 | static void of_node_release(struct kobject *kobj) | ||
121 | { | ||
122 | struct device_node *node = kobj_to_device_node(kobj); | ||
123 | struct property *prop = node->properties; | ||
124 | |||
125 | /* We should never be releasing nodes that haven't been detached. */ | ||
126 | if (!of_node_check_flag(node, OF_DETACHED)) { | ||
127 | pr_err("ERROR: Bad of_node_put() on %s\n", node->full_name); | ||
128 | dump_stack(); | ||
129 | return; | ||
130 | } | ||
131 | |||
132 | if (!of_node_check_flag(node, OF_DYNAMIC)) | ||
133 | return; | ||
134 | |||
135 | while (prop) { | ||
136 | struct property *next = prop->next; | ||
137 | kfree(prop->name); | ||
138 | kfree(prop->value); | ||
139 | kfree(prop); | ||
140 | prop = next; | ||
141 | |||
142 | if (!prop) { | ||
143 | prop = node->deadprops; | ||
144 | node->deadprops = NULL; | ||
145 | } | ||
146 | } | ||
147 | kfree(node->full_name); | ||
148 | kfree(node->data); | ||
149 | kfree(node); | ||
150 | } | ||
151 | |||
152 | /** | ||
153 | * of_node_put - Decrement refcount of a node | ||
154 | * @node: Node to dec refcount, NULL is supported to | ||
155 | * simplify writing of callers | ||
156 | * | ||
157 | */ | ||
158 | void of_node_put(struct device_node *node) | ||
159 | { | ||
160 | if (node) | ||
161 | kobject_put(&node->kobj); | ||
162 | } | ||
163 | EXPORT_SYMBOL(of_node_put); | ||
164 | #else | ||
165 | static void of_node_release(struct kobject *kobj) | 96 | static void of_node_release(struct kobject *kobj) |
166 | { | 97 | { |
167 | /* Without CONFIG_OF_DYNAMIC, no nodes gets freed */ | 98 | /* Without CONFIG_OF_DYNAMIC, no nodes gets freed */ |
@@ -200,13 +131,16 @@ static const char *safe_name(struct kobject *kobj, const char *orig_name) | |||
200 | return name; | 131 | return name; |
201 | } | 132 | } |
202 | 133 | ||
203 | static int __of_add_property_sysfs(struct device_node *np, struct property *pp) | 134 | int __of_add_property_sysfs(struct device_node *np, struct property *pp) |
204 | { | 135 | { |
205 | int rc; | 136 | int rc; |
206 | 137 | ||
207 | /* Important: Don't leak passwords */ | 138 | /* Important: Don't leak passwords */ |
208 | bool secure = strncmp(pp->name, "security-", 9) == 0; | 139 | bool secure = strncmp(pp->name, "security-", 9) == 0; |
209 | 140 | ||
141 | if (!of_kset || !of_node_is_attached(np)) | ||
142 | return 0; | ||
143 | |||
210 | sysfs_bin_attr_init(&pp->attr); | 144 | sysfs_bin_attr_init(&pp->attr); |
211 | pp->attr.attr.name = safe_name(&np->kobj, pp->name); | 145 | pp->attr.attr.name = safe_name(&np->kobj, pp->name); |
212 | pp->attr.attr.mode = secure ? S_IRUSR : S_IRUGO; | 146 | pp->attr.attr.mode = secure ? S_IRUSR : S_IRUGO; |
@@ -218,12 +152,15 @@ static int __of_add_property_sysfs(struct device_node *np, struct property *pp) | |||
218 | return rc; | 152 | return rc; |
219 | } | 153 | } |
220 | 154 | ||
221 | static int __of_node_add(struct device_node *np) | 155 | int __of_attach_node_sysfs(struct device_node *np) |
222 | { | 156 | { |
223 | const char *name; | 157 | const char *name; |
224 | struct property *pp; | 158 | struct property *pp; |
225 | int rc; | 159 | int rc; |
226 | 160 | ||
161 | if (!of_kset) | ||
162 | return 0; | ||
163 | |||
227 | np->kobj.kset = of_kset; | 164 | np->kobj.kset = of_kset; |
228 | if (!np->parent) { | 165 | if (!np->parent) { |
229 | /* Nodes without parents are new top level trees */ | 166 | /* Nodes without parents are new top level trees */ |
@@ -245,59 +182,20 @@ static int __of_node_add(struct device_node *np) | |||
245 | return 0; | 182 | return 0; |
246 | } | 183 | } |
247 | 184 | ||
248 | int of_node_add(struct device_node *np) | ||
249 | { | ||
250 | int rc = 0; | ||
251 | |||
252 | BUG_ON(!of_node_is_initialized(np)); | ||
253 | |||
254 | /* | ||
255 | * Grab the mutex here so that in a race condition between of_init() and | ||
256 | * of_node_add(), node addition will still be consistent. | ||
257 | */ | ||
258 | mutex_lock(&of_aliases_mutex); | ||
259 | if (of_kset) | ||
260 | rc = __of_node_add(np); | ||
261 | else | ||
262 | /* This scenario may be perfectly valid, but report it anyway */ | ||
263 | pr_info("of_node_add(%s) before of_init()\n", np->full_name); | ||
264 | mutex_unlock(&of_aliases_mutex); | ||
265 | return rc; | ||
266 | } | ||
267 | |||
268 | #if defined(CONFIG_OF_DYNAMIC) | ||
269 | static void of_node_remove(struct device_node *np) | ||
270 | { | ||
271 | struct property *pp; | ||
272 | |||
273 | BUG_ON(!of_node_is_initialized(np)); | ||
274 | |||
275 | /* only remove properties if on sysfs */ | ||
276 | if (of_node_is_attached(np)) { | ||
277 | for_each_property_of_node(np, pp) | ||
278 | sysfs_remove_bin_file(&np->kobj, &pp->attr); | ||
279 | kobject_del(&np->kobj); | ||
280 | } | ||
281 | |||
282 | /* finally remove the kobj_init ref */ | ||
283 | of_node_put(np); | ||
284 | } | ||
285 | #endif | ||
286 | |||
287 | static int __init of_init(void) | 185 | static int __init of_init(void) |
288 | { | 186 | { |
289 | struct device_node *np; | 187 | struct device_node *np; |
290 | 188 | ||
291 | /* Create the kset, and register existing nodes */ | 189 | /* Create the kset, and register existing nodes */ |
292 | mutex_lock(&of_aliases_mutex); | 190 | mutex_lock(&of_mutex); |
293 | of_kset = kset_create_and_add("devicetree", NULL, firmware_kobj); | 191 | of_kset = kset_create_and_add("devicetree", NULL, firmware_kobj); |
294 | if (!of_kset) { | 192 | if (!of_kset) { |
295 | mutex_unlock(&of_aliases_mutex); | 193 | mutex_unlock(&of_mutex); |
296 | return -ENOMEM; | 194 | return -ENOMEM; |
297 | } | 195 | } |
298 | for_each_of_allnodes(np) | 196 | for_each_of_allnodes(np) |
299 | __of_node_add(np); | 197 | __of_attach_node_sysfs(np); |
300 | mutex_unlock(&of_aliases_mutex); | 198 | mutex_unlock(&of_mutex); |
301 | 199 | ||
302 | /* Symlink in /proc as required by userspace ABI */ | 200 | /* Symlink in /proc as required by userspace ABI */ |
303 | if (of_allnodes) | 201 | if (of_allnodes) |
@@ -369,8 +267,8 @@ EXPORT_SYMBOL(of_find_all_nodes); | |||
369 | * Find a property with a given name for a given node | 267 | * Find a property with a given name for a given node |
370 | * and return the value. | 268 | * and return the value. |
371 | */ | 269 | */ |
372 | static const void *__of_get_property(const struct device_node *np, | 270 | const void *__of_get_property(const struct device_node *np, |
373 | const char *name, int *lenp) | 271 | const char *name, int *lenp) |
374 | { | 272 | { |
375 | struct property *pp = __of_find_property(np, name, lenp); | 273 | struct property *pp = __of_find_property(np, name, lenp); |
376 | 274 | ||
@@ -1748,32 +1646,10 @@ int of_count_phandle_with_args(const struct device_node *np, const char *list_na | |||
1748 | } | 1646 | } |
1749 | EXPORT_SYMBOL(of_count_phandle_with_args); | 1647 | EXPORT_SYMBOL(of_count_phandle_with_args); |
1750 | 1648 | ||
1751 | #if defined(CONFIG_OF_DYNAMIC) | ||
1752 | static int of_property_notify(int action, struct device_node *np, | ||
1753 | struct property *prop) | ||
1754 | { | ||
1755 | struct of_prop_reconfig pr; | ||
1756 | |||
1757 | /* only call notifiers if the node is attached */ | ||
1758 | if (!of_node_is_attached(np)) | ||
1759 | return 0; | ||
1760 | |||
1761 | pr.dn = np; | ||
1762 | pr.prop = prop; | ||
1763 | return of_reconfig_notify(action, &pr); | ||
1764 | } | ||
1765 | #else | ||
1766 | static int of_property_notify(int action, struct device_node *np, | ||
1767 | struct property *prop) | ||
1768 | { | ||
1769 | return 0; | ||
1770 | } | ||
1771 | #endif | ||
1772 | |||
1773 | /** | 1649 | /** |
1774 | * __of_add_property - Add a property to a node without lock operations | 1650 | * __of_add_property - Add a property to a node without lock operations |
1775 | */ | 1651 | */ |
1776 | static int __of_add_property(struct device_node *np, struct property *prop) | 1652 | int __of_add_property(struct device_node *np, struct property *prop) |
1777 | { | 1653 | { |
1778 | struct property **next; | 1654 | struct property **next; |
1779 | 1655 | ||
@@ -1799,22 +1675,49 @@ int of_add_property(struct device_node *np, struct property *prop) | |||
1799 | unsigned long flags; | 1675 | unsigned long flags; |
1800 | int rc; | 1676 | int rc; |
1801 | 1677 | ||
1802 | rc = of_property_notify(OF_RECONFIG_ADD_PROPERTY, np, prop); | 1678 | mutex_lock(&of_mutex); |
1803 | if (rc) | ||
1804 | return rc; | ||
1805 | 1679 | ||
1806 | raw_spin_lock_irqsave(&devtree_lock, flags); | 1680 | raw_spin_lock_irqsave(&devtree_lock, flags); |
1807 | rc = __of_add_property(np, prop); | 1681 | rc = __of_add_property(np, prop); |
1808 | raw_spin_unlock_irqrestore(&devtree_lock, flags); | 1682 | raw_spin_unlock_irqrestore(&devtree_lock, flags); |
1809 | if (rc) | ||
1810 | return rc; | ||
1811 | 1683 | ||
1812 | if (of_node_is_attached(np)) | 1684 | if (!rc) |
1813 | __of_add_property_sysfs(np, prop); | 1685 | __of_add_property_sysfs(np, prop); |
1814 | 1686 | ||
1687 | mutex_unlock(&of_mutex); | ||
1688 | |||
1689 | if (!rc) | ||
1690 | of_property_notify(OF_RECONFIG_ADD_PROPERTY, np, prop, NULL); | ||
1691 | |||
1815 | return rc; | 1692 | return rc; |
1816 | } | 1693 | } |
1817 | 1694 | ||
1695 | int __of_remove_property(struct device_node *np, struct property *prop) | ||
1696 | { | ||
1697 | struct property **next; | ||
1698 | |||
1699 | for (next = &np->properties; *next; next = &(*next)->next) { | ||
1700 | if (*next == prop) | ||
1701 | break; | ||
1702 | } | ||
1703 | if (*next == NULL) | ||
1704 | return -ENODEV; | ||
1705 | |||
1706 | /* found the node */ | ||
1707 | *next = prop->next; | ||
1708 | prop->next = np->deadprops; | ||
1709 | np->deadprops = prop; | ||
1710 | |||
1711 | return 0; | ||
1712 | } | ||
1713 | |||
1714 | void __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 | |||
1818 | /** | 1721 | /** |
1819 | * of_remove_property - Remove a property from a node. | 1722 | * of_remove_property - Remove a property from a node. |
1820 | * | 1723 | * |
@@ -1825,211 +1728,98 @@ int of_add_property(struct device_node *np, struct property *prop) | |||
1825 | */ | 1728 | */ |
1826 | int of_remove_property(struct device_node *np, struct property *prop) | 1729 | int of_remove_property(struct device_node *np, struct property *prop) |
1827 | { | 1730 | { |
1828 | struct property **next; | ||
1829 | unsigned long flags; | 1731 | unsigned long flags; |
1830 | int found = 0; | ||
1831 | int rc; | 1732 | int rc; |
1832 | 1733 | ||
1833 | rc = of_property_notify(OF_RECONFIG_REMOVE_PROPERTY, np, prop); | 1734 | mutex_lock(&of_mutex); |
1834 | if (rc) | ||
1835 | return rc; | ||
1836 | 1735 | ||
1837 | raw_spin_lock_irqsave(&devtree_lock, flags); | 1736 | raw_spin_lock_irqsave(&devtree_lock, flags); |
1838 | next = &np->properties; | 1737 | rc = __of_remove_property(np, prop); |
1839 | while (*next) { | ||
1840 | if (*next == prop) { | ||
1841 | /* found the node */ | ||
1842 | *next = prop->next; | ||
1843 | prop->next = np->deadprops; | ||
1844 | np->deadprops = prop; | ||
1845 | found = 1; | ||
1846 | break; | ||
1847 | } | ||
1848 | next = &(*next)->next; | ||
1849 | } | ||
1850 | raw_spin_unlock_irqrestore(&devtree_lock, flags); | 1738 | raw_spin_unlock_irqrestore(&devtree_lock, flags); |
1851 | 1739 | ||
1852 | if (!found) | 1740 | if (!rc) |
1853 | return -ENODEV; | 1741 | __of_remove_property_sysfs(np, prop); |
1854 | 1742 | ||
1855 | /* at early boot, bail hear and defer setup to of_init() */ | 1743 | mutex_unlock(&of_mutex); |
1856 | if (!of_kset) | ||
1857 | return 0; | ||
1858 | 1744 | ||
1859 | sysfs_remove_bin_file(&np->kobj, &prop->attr); | 1745 | if (!rc) |
1746 | of_property_notify(OF_RECONFIG_REMOVE_PROPERTY, np, prop, NULL); | ||
1860 | 1747 | ||
1861 | return 0; | 1748 | return rc; |
1862 | } | 1749 | } |
1863 | 1750 | ||
1864 | /* | 1751 | int __of_update_property(struct device_node *np, struct property *newprop, |
1865 | * of_update_property - Update a property in a node, if the property does | 1752 | struct property **oldpropp) |
1866 | * not exist, add it. | ||
1867 | * | ||
1868 | * Note that we don't actually remove it, since we have given out | ||
1869 | * who-knows-how-many pointers to the data using get-property. | ||
1870 | * Instead we just move the property to the "dead properties" list, | ||
1871 | * and add the new property to the property list | ||
1872 | */ | ||
1873 | int of_update_property(struct device_node *np, struct property *newprop) | ||
1874 | { | 1753 | { |
1875 | struct property **next, *oldprop; | 1754 | struct property **next, *oldprop; |
1876 | unsigned long flags; | ||
1877 | int rc; | ||
1878 | |||
1879 | rc = of_property_notify(OF_RECONFIG_UPDATE_PROPERTY, np, newprop); | ||
1880 | if (rc) | ||
1881 | return rc; | ||
1882 | 1755 | ||
1883 | if (!newprop->name) | 1756 | for (next = &np->properties; *next; next = &(*next)->next) { |
1884 | return -EINVAL; | 1757 | if (of_prop_cmp((*next)->name, newprop->name) == 0) |
1758 | break; | ||
1759 | } | ||
1760 | *oldpropp = oldprop = *next; | ||
1885 | 1761 | ||
1886 | raw_spin_lock_irqsave(&devtree_lock, flags); | 1762 | if (oldprop) { |
1887 | next = &np->properties; | ||
1888 | oldprop = __of_find_property(np, newprop->name, NULL); | ||
1889 | if (!oldprop) { | ||
1890 | /* add the new node */ | ||
1891 | rc = __of_add_property(np, newprop); | ||
1892 | } else while (*next) { | ||
1893 | /* replace the node */ | 1763 | /* replace the node */ |
1894 | if (*next == oldprop) { | 1764 | newprop->next = oldprop->next; |
1895 | newprop->next = oldprop->next; | 1765 | *next = newprop; |
1896 | *next = newprop; | 1766 | oldprop->next = np->deadprops; |
1897 | oldprop->next = np->deadprops; | 1767 | np->deadprops = oldprop; |
1898 | np->deadprops = oldprop; | 1768 | } else { |
1899 | break; | 1769 | /* new node */ |
1900 | } | 1770 | newprop->next = NULL; |
1901 | next = &(*next)->next; | 1771 | *next = newprop; |
1902 | } | 1772 | } |
1903 | raw_spin_unlock_irqrestore(&devtree_lock, flags); | ||
1904 | if (rc) | ||
1905 | return rc; | ||
1906 | 1773 | ||
1774 | return 0; | ||
1775 | } | ||
1776 | |||
1777 | void __of_update_property_sysfs(struct device_node *np, struct property *newprop, | ||
1778 | struct property *oldprop) | ||
1779 | { | ||
1907 | /* At early boot, bail out and defer setup to of_init() */ | 1780 | /* At early boot, bail out and defer setup to of_init() */ |
1908 | if (!of_kset) | 1781 | if (!of_kset) |
1909 | return 0; | 1782 | return; |
1910 | 1783 | ||
1911 | /* Update the sysfs attribute */ | ||
1912 | if (oldprop) | 1784 | if (oldprop) |
1913 | sysfs_remove_bin_file(&np->kobj, &oldprop->attr); | 1785 | sysfs_remove_bin_file(&np->kobj, &oldprop->attr); |
1914 | __of_add_property_sysfs(np, newprop); | 1786 | __of_add_property_sysfs(np, newprop); |
1915 | |||
1916 | return 0; | ||
1917 | } | 1787 | } |
1918 | 1788 | ||
1919 | #if defined(CONFIG_OF_DYNAMIC) | ||
1920 | /* | 1789 | /* |
1921 | * Support for dynamic device trees. | 1790 | * of_update_property - Update a property in a node, if the property does |
1791 | * not exist, add it. | ||
1922 | * | 1792 | * |
1923 | * On some platforms, the device tree can be manipulated at runtime. | 1793 | * Note that we don't actually remove it, since we have given out |
1924 | * The routines in this section support adding, removing and changing | 1794 | * who-knows-how-many pointers to the data using get-property. |
1925 | * device tree nodes. | 1795 | * Instead we just move the property to the "dead properties" list, |
1926 | */ | 1796 | * and add the new property to the property list |
1927 | |||
1928 | static BLOCKING_NOTIFIER_HEAD(of_reconfig_chain); | ||
1929 | |||
1930 | int of_reconfig_notifier_register(struct notifier_block *nb) | ||
1931 | { | ||
1932 | return blocking_notifier_chain_register(&of_reconfig_chain, nb); | ||
1933 | } | ||
1934 | EXPORT_SYMBOL_GPL(of_reconfig_notifier_register); | ||
1935 | |||
1936 | int of_reconfig_notifier_unregister(struct notifier_block *nb) | ||
1937 | { | ||
1938 | return blocking_notifier_chain_unregister(&of_reconfig_chain, nb); | ||
1939 | } | ||
1940 | EXPORT_SYMBOL_GPL(of_reconfig_notifier_unregister); | ||
1941 | |||
1942 | int of_reconfig_notify(unsigned long action, void *p) | ||
1943 | { | ||
1944 | int rc; | ||
1945 | |||
1946 | rc = blocking_notifier_call_chain(&of_reconfig_chain, action, p); | ||
1947 | return notifier_to_errno(rc); | ||
1948 | } | ||
1949 | |||
1950 | /** | ||
1951 | * of_attach_node - Plug a device node into the tree and global list. | ||
1952 | */ | 1797 | */ |
1953 | int of_attach_node(struct device_node *np) | 1798 | int of_update_property(struct device_node *np, struct property *newprop) |
1954 | { | 1799 | { |
1800 | struct property *oldprop; | ||
1955 | unsigned long flags; | 1801 | unsigned long flags; |
1956 | int rc; | 1802 | int rc; |
1957 | 1803 | ||
1958 | rc = of_reconfig_notify(OF_RECONFIG_ATTACH_NODE, np); | 1804 | if (!newprop->name) |
1959 | if (rc) | 1805 | return -EINVAL; |
1960 | return rc; | ||
1961 | |||
1962 | raw_spin_lock_irqsave(&devtree_lock, flags); | ||
1963 | np->sibling = np->parent->child; | ||
1964 | np->allnext = np->parent->allnext; | ||
1965 | np->parent->allnext = np; | ||
1966 | np->parent->child = np; | ||
1967 | of_node_clear_flag(np, OF_DETACHED); | ||
1968 | raw_spin_unlock_irqrestore(&devtree_lock, flags); | ||
1969 | |||
1970 | of_node_add(np); | ||
1971 | return 0; | ||
1972 | } | ||
1973 | |||
1974 | /** | ||
1975 | * of_detach_node - "Unplug" a node from the device tree. | ||
1976 | * | ||
1977 | * The caller must hold a reference to the node. The memory associated with | ||
1978 | * the node is not freed until its refcount goes to zero. | ||
1979 | */ | ||
1980 | int of_detach_node(struct device_node *np) | ||
1981 | { | ||
1982 | struct device_node *parent; | ||
1983 | unsigned long flags; | ||
1984 | int rc = 0; | ||
1985 | 1806 | ||
1986 | rc = of_reconfig_notify(OF_RECONFIG_DETACH_NODE, np); | 1807 | mutex_lock(&of_mutex); |
1987 | if (rc) | ||
1988 | return rc; | ||
1989 | 1808 | ||
1990 | raw_spin_lock_irqsave(&devtree_lock, flags); | 1809 | raw_spin_lock_irqsave(&devtree_lock, flags); |
1810 | rc = __of_update_property(np, newprop, &oldprop); | ||
1811 | raw_spin_unlock_irqrestore(&devtree_lock, flags); | ||
1991 | 1812 | ||
1992 | if (of_node_check_flag(np, OF_DETACHED)) { | 1813 | if (!rc) |
1993 | /* someone already detached it */ | 1814 | __of_update_property_sysfs(np, newprop, oldprop); |
1994 | raw_spin_unlock_irqrestore(&devtree_lock, flags); | ||
1995 | return rc; | ||
1996 | } | ||
1997 | |||
1998 | parent = np->parent; | ||
1999 | if (!parent) { | ||
2000 | raw_spin_unlock_irqrestore(&devtree_lock, flags); | ||
2001 | return rc; | ||
2002 | } | ||
2003 | 1815 | ||
2004 | if (of_allnodes == np) | 1816 | mutex_unlock(&of_mutex); |
2005 | of_allnodes = np->allnext; | ||
2006 | else { | ||
2007 | struct device_node *prev; | ||
2008 | for (prev = of_allnodes; | ||
2009 | prev->allnext != np; | ||
2010 | prev = prev->allnext) | ||
2011 | ; | ||
2012 | prev->allnext = np->allnext; | ||
2013 | } | ||
2014 | 1817 | ||
2015 | if (parent->child == np) | 1818 | if (!rc) |
2016 | parent->child = np->sibling; | 1819 | of_property_notify(OF_RECONFIG_UPDATE_PROPERTY, np, newprop, oldprop); |
2017 | else { | ||
2018 | struct device_node *prevsib; | ||
2019 | for (prevsib = np->parent->child; | ||
2020 | prevsib->sibling != np; | ||
2021 | prevsib = prevsib->sibling) | ||
2022 | ; | ||
2023 | prevsib->sibling = np->sibling; | ||
2024 | } | ||
2025 | |||
2026 | of_node_set_flag(np, OF_DETACHED); | ||
2027 | raw_spin_unlock_irqrestore(&devtree_lock, flags); | ||
2028 | 1820 | ||
2029 | of_node_remove(np); | ||
2030 | return rc; | 1821 | return rc; |
2031 | } | 1822 | } |
2032 | #endif /* defined(CONFIG_OF_DYNAMIC) */ | ||
2033 | 1823 | ||
2034 | static void of_alias_add(struct alias_prop *ap, struct device_node *np, | 1824 | static void of_alias_add(struct alias_prop *ap, struct device_node *np, |
2035 | int id, const char *stem, int stem_len) | 1825 | int id, const char *stem, int stem_len) |
@@ -2062,9 +1852,12 @@ void of_alias_scan(void * (*dt_alloc)(u64 size, u64 align)) | |||
2062 | of_chosen = of_find_node_by_path("/chosen@0"); | 1852 | of_chosen = of_find_node_by_path("/chosen@0"); |
2063 | 1853 | ||
2064 | if (of_chosen) { | 1854 | if (of_chosen) { |
1855 | /* linux,stdout-path and /aliases/stdout are for legacy compatibility */ | ||
2065 | const char *name = of_get_property(of_chosen, "stdout-path", NULL); | 1856 | const char *name = of_get_property(of_chosen, "stdout-path", NULL); |
2066 | if (!name) | 1857 | if (!name) |
2067 | name = of_get_property(of_chosen, "linux,stdout-path", NULL); | 1858 | name = of_get_property(of_chosen, "linux,stdout-path", NULL); |
1859 | if (IS_ENABLED(CONFIG_PPC) && !name) | ||
1860 | name = of_get_property(of_aliases, "stdout", NULL); | ||
2068 | if (name) | 1861 | if (name) |
2069 | of_stdout = of_find_node_by_path(name); | 1862 | of_stdout = of_find_node_by_path(name); |
2070 | } | 1863 | } |
@@ -2122,7 +1915,7 @@ int of_alias_get_id(struct device_node *np, const char *stem) | |||
2122 | struct alias_prop *app; | 1915 | struct alias_prop *app; |
2123 | int id = -ENODEV; | 1916 | int id = -ENODEV; |
2124 | 1917 | ||
2125 | mutex_lock(&of_aliases_mutex); | 1918 | mutex_lock(&of_mutex); |
2126 | list_for_each_entry(app, &aliases_lookup, link) { | 1919 | list_for_each_entry(app, &aliases_lookup, link) { |
2127 | if (strcmp(app->stem, stem) != 0) | 1920 | if (strcmp(app->stem, stem) != 0) |
2128 | continue; | 1921 | continue; |
@@ -2132,7 +1925,7 @@ int of_alias_get_id(struct device_node *np, const char *stem) | |||
2132 | break; | 1925 | break; |
2133 | } | 1926 | } |
2134 | } | 1927 | } |
2135 | mutex_unlock(&of_aliases_mutex); | 1928 | mutex_unlock(&of_mutex); |
2136 | 1929 | ||
2137 | return id; | 1930 | return id; |
2138 | } | 1931 | } |
@@ -2180,20 +1973,22 @@ const char *of_prop_next_string(struct property *prop, const char *cur) | |||
2180 | EXPORT_SYMBOL_GPL(of_prop_next_string); | 1973 | EXPORT_SYMBOL_GPL(of_prop_next_string); |
2181 | 1974 | ||
2182 | /** | 1975 | /** |
2183 | * of_device_is_stdout_path - check if a device node matches the | 1976 | * of_console_check() - Test and setup console for DT setup |
2184 | * linux,stdout-path property | 1977 | * @dn - Pointer to device node |
2185 | * | 1978 | * @name - Name to use for preferred console without index. ex. "ttyS" |
2186 | * Check if this device node matches the linux,stdout-path property | 1979 | * @index - Index to use for preferred console. |
2187 | * in the chosen node. return true if yes, false otherwise. | 1980 | * |
1981 | * Check if the given device node matches the stdout-path property in the | ||
1982 | * /chosen node. If it does then register it as the preferred console and return | ||
1983 | * TRUE. Otherwise return FALSE. | ||
2188 | */ | 1984 | */ |
2189 | int of_device_is_stdout_path(struct device_node *dn) | 1985 | bool of_console_check(struct device_node *dn, char *name, int index) |
2190 | { | 1986 | { |
2191 | if (!of_stdout) | 1987 | if (!dn || dn != of_stdout || console_set_on_cmdline) |
2192 | return false; | 1988 | return false; |
2193 | 1989 | return add_preferred_console(name, index, NULL); | |
2194 | return of_stdout == dn; | ||
2195 | } | 1990 | } |
2196 | EXPORT_SYMBOL_GPL(of_device_is_stdout_path); | 1991 | EXPORT_SYMBOL_GPL(of_console_check); |
2197 | 1992 | ||
2198 | /** | 1993 | /** |
2199 | * of_find_next_cache_node - Find a node's subsidiary cache | 1994 | * of_find_next_cache_node - Find a node's subsidiary cache |
diff --git a/drivers/of/device.c b/drivers/of/device.c index dafb9736ab9b..46d6c75c1404 100644 --- a/drivers/of/device.c +++ b/drivers/of/device.c | |||
@@ -160,7 +160,7 @@ void of_device_uevent(struct device *dev, struct kobj_uevent_env *env) | |||
160 | add_uevent_var(env, "OF_COMPATIBLE_N=%d", seen); | 160 | add_uevent_var(env, "OF_COMPATIBLE_N=%d", seen); |
161 | 161 | ||
162 | seen = 0; | 162 | seen = 0; |
163 | mutex_lock(&of_aliases_mutex); | 163 | mutex_lock(&of_mutex); |
164 | list_for_each_entry(app, &aliases_lookup, link) { | 164 | list_for_each_entry(app, &aliases_lookup, link) { |
165 | if (dev->of_node == app->np) { | 165 | if (dev->of_node == app->np) { |
166 | add_uevent_var(env, "OF_ALIAS_%d=%s", seen, | 166 | add_uevent_var(env, "OF_ALIAS_%d=%s", seen, |
@@ -168,7 +168,7 @@ void of_device_uevent(struct device *dev, struct kobj_uevent_env *env) | |||
168 | seen++; | 168 | seen++; |
169 | } | 169 | } |
170 | } | 170 | } |
171 | mutex_unlock(&of_aliases_mutex); | 171 | mutex_unlock(&of_mutex); |
172 | } | 172 | } |
173 | 173 | ||
174 | int of_device_uevent_modalias(struct device *dev, struct kobj_uevent_env *env) | 174 | int of_device_uevent_modalias(struct device *dev, struct kobj_uevent_env *env) |
diff --git a/drivers/of/dynamic.c b/drivers/of/dynamic.c new file mode 100644 index 000000000000..54fecc49a1fe --- /dev/null +++ b/drivers/of/dynamic.c | |||
@@ -0,0 +1,660 @@ | |||
1 | /* | ||
2 | * Support for dynamic device trees. | ||
3 | * | ||
4 | * On some platforms, the device tree can be manipulated at runtime. | ||
5 | * The routines in this section support adding, removing and changing | ||
6 | * device tree nodes. | ||
7 | */ | ||
8 | |||
9 | #include <linux/of.h> | ||
10 | #include <linux/spinlock.h> | ||
11 | #include <linux/slab.h> | ||
12 | #include <linux/string.h> | ||
13 | #include <linux/proc_fs.h> | ||
14 | |||
15 | #include "of_private.h" | ||
16 | |||
17 | /** | ||
18 | * of_node_get() - Increment refcount of a node | ||
19 | * @node: Node to inc refcount, NULL is supported to simplify writing of | ||
20 | * callers | ||
21 | * | ||
22 | * Returns node. | ||
23 | */ | ||
24 | struct device_node *of_node_get(struct device_node *node) | ||
25 | { | ||
26 | if (node) | ||
27 | kobject_get(&node->kobj); | ||
28 | return node; | ||
29 | } | ||
30 | EXPORT_SYMBOL(of_node_get); | ||
31 | |||
32 | /** | ||
33 | * of_node_put() - Decrement refcount of a node | ||
34 | * @node: Node to dec refcount, NULL is supported to simplify writing of | ||
35 | * callers | ||
36 | */ | ||
37 | void of_node_put(struct device_node *node) | ||
38 | { | ||
39 | if (node) | ||
40 | kobject_put(&node->kobj); | ||
41 | } | ||
42 | EXPORT_SYMBOL(of_node_put); | ||
43 | |||
44 | void __of_detach_node_sysfs(struct device_node *np) | ||
45 | { | ||
46 | struct property *pp; | ||
47 | |||
48 | BUG_ON(!of_node_is_initialized(np)); | ||
49 | if (!of_kset) | ||
50 | return; | ||
51 | |||
52 | /* only remove properties if on sysfs */ | ||
53 | if (of_node_is_attached(np)) { | ||
54 | for_each_property_of_node(np, pp) | ||
55 | sysfs_remove_bin_file(&np->kobj, &pp->attr); | ||
56 | kobject_del(&np->kobj); | ||
57 | } | ||
58 | |||
59 | /* finally remove the kobj_init ref */ | ||
60 | of_node_put(np); | ||
61 | } | ||
62 | |||
63 | static BLOCKING_NOTIFIER_HEAD(of_reconfig_chain); | ||
64 | |||
65 | int of_reconfig_notifier_register(struct notifier_block *nb) | ||
66 | { | ||
67 | return blocking_notifier_chain_register(&of_reconfig_chain, nb); | ||
68 | } | ||
69 | EXPORT_SYMBOL_GPL(of_reconfig_notifier_register); | ||
70 | |||
71 | int of_reconfig_notifier_unregister(struct notifier_block *nb) | ||
72 | { | ||
73 | return blocking_notifier_chain_unregister(&of_reconfig_chain, nb); | ||
74 | } | ||
75 | EXPORT_SYMBOL_GPL(of_reconfig_notifier_unregister); | ||
76 | |||
77 | int of_reconfig_notify(unsigned long action, void *p) | ||
78 | { | ||
79 | int rc; | ||
80 | |||
81 | rc = blocking_notifier_call_chain(&of_reconfig_chain, action, p); | ||
82 | return notifier_to_errno(rc); | ||
83 | } | ||
84 | |||
85 | int of_property_notify(int action, struct device_node *np, | ||
86 | struct property *prop, struct property *oldprop) | ||
87 | { | ||
88 | struct of_prop_reconfig pr; | ||
89 | |||
90 | /* only call notifiers if the node is attached */ | ||
91 | if (!of_node_is_attached(np)) | ||
92 | return 0; | ||
93 | |||
94 | pr.dn = np; | ||
95 | pr.prop = prop; | ||
96 | pr.old_prop = oldprop; | ||
97 | return of_reconfig_notify(action, &pr); | ||
98 | } | ||
99 | |||
100 | void __of_attach_node(struct device_node *np) | ||
101 | { | ||
102 | const __be32 *phandle; | ||
103 | int sz; | ||
104 | |||
105 | np->name = __of_get_property(np, "name", NULL) ? : "<NULL>"; | ||
106 | np->type = __of_get_property(np, "device_type", NULL) ? : "<NULL>"; | ||
107 | |||
108 | phandle = __of_get_property(np, "phandle", &sz); | ||
109 | if (!phandle) | ||
110 | phandle = __of_get_property(np, "linux,phandle", &sz); | ||
111 | if (IS_ENABLED(PPC_PSERIES) && !phandle) | ||
112 | phandle = __of_get_property(np, "ibm,phandle", &sz); | ||
113 | np->phandle = (phandle && (sz >= 4)) ? be32_to_cpup(phandle) : 0; | ||
114 | |||
115 | np->child = NULL; | ||
116 | np->sibling = np->parent->child; | ||
117 | np->allnext = np->parent->allnext; | ||
118 | np->parent->allnext = np; | ||
119 | np->parent->child = np; | ||
120 | of_node_clear_flag(np, OF_DETACHED); | ||
121 | } | ||
122 | |||
123 | /** | ||
124 | * of_attach_node() - Plug a device node into the tree and global list. | ||
125 | */ | ||
126 | int of_attach_node(struct device_node *np) | ||
127 | { | ||
128 | unsigned long flags; | ||
129 | |||
130 | mutex_lock(&of_mutex); | ||
131 | raw_spin_lock_irqsave(&devtree_lock, flags); | ||
132 | __of_attach_node(np); | ||
133 | raw_spin_unlock_irqrestore(&devtree_lock, flags); | ||
134 | |||
135 | __of_attach_node_sysfs(np); | ||
136 | mutex_unlock(&of_mutex); | ||
137 | |||
138 | of_reconfig_notify(OF_RECONFIG_ATTACH_NODE, np); | ||
139 | |||
140 | return 0; | ||
141 | } | ||
142 | |||
143 | void __of_detach_node(struct device_node *np) | ||
144 | { | ||
145 | struct device_node *parent; | ||
146 | |||
147 | if (WARN_ON(of_node_check_flag(np, OF_DETACHED))) | ||
148 | return; | ||
149 | |||
150 | parent = np->parent; | ||
151 | if (WARN_ON(!parent)) | ||
152 | return; | ||
153 | |||
154 | if (of_allnodes == np) | ||
155 | of_allnodes = np->allnext; | ||
156 | else { | ||
157 | struct device_node *prev; | ||
158 | for (prev = of_allnodes; | ||
159 | prev->allnext != np; | ||
160 | prev = prev->allnext) | ||
161 | ; | ||
162 | prev->allnext = np->allnext; | ||
163 | } | ||
164 | |||
165 | if (parent->child == np) | ||
166 | parent->child = np->sibling; | ||
167 | else { | ||
168 | struct device_node *prevsib; | ||
169 | for (prevsib = np->parent->child; | ||
170 | prevsib->sibling != np; | ||
171 | prevsib = prevsib->sibling) | ||
172 | ; | ||
173 | prevsib->sibling = np->sibling; | ||
174 | } | ||
175 | |||
176 | of_node_set_flag(np, OF_DETACHED); | ||
177 | } | ||
178 | |||
179 | /** | ||
180 | * of_detach_node() - "Unplug" a node from the device tree. | ||
181 | * | ||
182 | * The caller must hold a reference to the node. The memory associated with | ||
183 | * the node is not freed until its refcount goes to zero. | ||
184 | */ | ||
185 | int of_detach_node(struct device_node *np) | ||
186 | { | ||
187 | unsigned long flags; | ||
188 | int rc = 0; | ||
189 | |||
190 | mutex_lock(&of_mutex); | ||
191 | raw_spin_lock_irqsave(&devtree_lock, flags); | ||
192 | __of_detach_node(np); | ||
193 | raw_spin_unlock_irqrestore(&devtree_lock, flags); | ||
194 | |||
195 | __of_detach_node_sysfs(np); | ||
196 | mutex_unlock(&of_mutex); | ||
197 | |||
198 | of_reconfig_notify(OF_RECONFIG_DETACH_NODE, np); | ||
199 | |||
200 | return rc; | ||
201 | } | ||
202 | |||
203 | /** | ||
204 | * of_node_release() - release a dynamically allocated node | ||
205 | * @kref: kref element of the node to be released | ||
206 | * | ||
207 | * In of_node_put() this function is passed to kref_put() as the destructor. | ||
208 | */ | ||
209 | void of_node_release(struct kobject *kobj) | ||
210 | { | ||
211 | struct device_node *node = kobj_to_device_node(kobj); | ||
212 | struct property *prop = node->properties; | ||
213 | |||
214 | /* We should never be releasing nodes that haven't been detached. */ | ||
215 | if (!of_node_check_flag(node, OF_DETACHED)) { | ||
216 | pr_err("ERROR: Bad of_node_put() on %s\n", node->full_name); | ||
217 | dump_stack(); | ||
218 | return; | ||
219 | } | ||
220 | |||
221 | if (!of_node_check_flag(node, OF_DYNAMIC)) | ||
222 | return; | ||
223 | |||
224 | while (prop) { | ||
225 | struct property *next = prop->next; | ||
226 | kfree(prop->name); | ||
227 | kfree(prop->value); | ||
228 | kfree(prop); | ||
229 | prop = next; | ||
230 | |||
231 | if (!prop) { | ||
232 | prop = node->deadprops; | ||
233 | node->deadprops = NULL; | ||
234 | } | ||
235 | } | ||
236 | kfree(node->full_name); | ||
237 | kfree(node->data); | ||
238 | kfree(node); | ||
239 | } | ||
240 | |||
241 | /** | ||
242 | * __of_prop_dup - Copy a property dynamically. | ||
243 | * @prop: Property to copy | ||
244 | * @allocflags: Allocation flags (typically pass GFP_KERNEL) | ||
245 | * | ||
246 | * Copy a property by dynamically allocating the memory of both the | ||
247 | * property stucture and the property name & contents. The property's | ||
248 | * flags have the OF_DYNAMIC bit set so that we can differentiate between | ||
249 | * dynamically allocated properties and not. | ||
250 | * Returns the newly allocated property or NULL on out of memory error. | ||
251 | */ | ||
252 | struct property *__of_prop_dup(const struct property *prop, gfp_t allocflags) | ||
253 | { | ||
254 | struct property *new; | ||
255 | |||
256 | new = kzalloc(sizeof(*new), allocflags); | ||
257 | if (!new) | ||
258 | return NULL; | ||
259 | |||
260 | /* | ||
261 | * NOTE: There is no check for zero length value. | ||
262 | * In case of a boolean property, this will allocate a value | ||
263 | * of zero bytes. We do this to work around the use | ||
264 | * of of_get_property() calls on boolean values. | ||
265 | */ | ||
266 | new->name = kstrdup(prop->name, allocflags); | ||
267 | new->value = kmemdup(prop->value, prop->length, allocflags); | ||
268 | new->length = prop->length; | ||
269 | if (!new->name || !new->value) | ||
270 | goto err_free; | ||
271 | |||
272 | /* mark the property as dynamic */ | ||
273 | of_property_set_flag(new, OF_DYNAMIC); | ||
274 | |||
275 | return new; | ||
276 | |||
277 | err_free: | ||
278 | kfree(new->name); | ||
279 | kfree(new->value); | ||
280 | kfree(new); | ||
281 | return NULL; | ||
282 | } | ||
283 | |||
284 | /** | ||
285 | * __of_node_alloc() - Create an empty device node dynamically. | ||
286 | * @full_name: Full name of the new device node | ||
287 | * @allocflags: Allocation flags (typically pass GFP_KERNEL) | ||
288 | * | ||
289 | * Create an empty device tree node, suitable for further modification. | ||
290 | * The node data are dynamically allocated and all the node flags | ||
291 | * have the OF_DYNAMIC & OF_DETACHED bits set. | ||
292 | * Returns the newly allocated node or NULL on out of memory error. | ||
293 | */ | ||
294 | struct device_node *__of_node_alloc(const char *full_name, gfp_t allocflags) | ||
295 | { | ||
296 | struct device_node *node; | ||
297 | |||
298 | node = kzalloc(sizeof(*node), allocflags); | ||
299 | if (!node) | ||
300 | return NULL; | ||
301 | |||
302 | node->full_name = kstrdup(full_name, allocflags); | ||
303 | of_node_set_flag(node, OF_DYNAMIC); | ||
304 | of_node_set_flag(node, OF_DETACHED); | ||
305 | if (!node->full_name) | ||
306 | goto err_free; | ||
307 | |||
308 | of_node_init(node); | ||
309 | |||
310 | return node; | ||
311 | |||
312 | err_free: | ||
313 | kfree(node->full_name); | ||
314 | kfree(node); | ||
315 | return NULL; | ||
316 | } | ||
317 | |||
318 | static void __of_changeset_entry_destroy(struct of_changeset_entry *ce) | ||
319 | { | ||
320 | of_node_put(ce->np); | ||
321 | list_del(&ce->node); | ||
322 | kfree(ce); | ||
323 | } | ||
324 | |||
325 | #ifdef DEBUG | ||
326 | static void __of_changeset_entry_dump(struct of_changeset_entry *ce) | ||
327 | { | ||
328 | switch (ce->action) { | ||
329 | case OF_RECONFIG_ADD_PROPERTY: | ||
330 | pr_debug("%p: %s %s/%s\n", | ||
331 | ce, "ADD_PROPERTY ", ce->np->full_name, | ||
332 | ce->prop->name); | ||
333 | break; | ||
334 | case OF_RECONFIG_REMOVE_PROPERTY: | ||
335 | pr_debug("%p: %s %s/%s\n", | ||
336 | ce, "REMOVE_PROPERTY", ce->np->full_name, | ||
337 | ce->prop->name); | ||
338 | break; | ||
339 | case OF_RECONFIG_UPDATE_PROPERTY: | ||
340 | pr_debug("%p: %s %s/%s\n", | ||
341 | ce, "UPDATE_PROPERTY", ce->np->full_name, | ||
342 | ce->prop->name); | ||
343 | break; | ||
344 | case OF_RECONFIG_ATTACH_NODE: | ||
345 | pr_debug("%p: %s %s\n", | ||
346 | ce, "ATTACH_NODE ", ce->np->full_name); | ||
347 | break; | ||
348 | case OF_RECONFIG_DETACH_NODE: | ||
349 | pr_debug("%p: %s %s\n", | ||
350 | ce, "DETACH_NODE ", ce->np->full_name); | ||
351 | break; | ||
352 | } | ||
353 | } | ||
354 | #else | ||
355 | static inline void __of_changeset_entry_dump(struct of_changeset_entry *ce) | ||
356 | { | ||
357 | /* empty */ | ||
358 | } | ||
359 | #endif | ||
360 | |||
361 | static void __of_changeset_entry_invert(struct of_changeset_entry *ce, | ||
362 | struct of_changeset_entry *rce) | ||
363 | { | ||
364 | memcpy(rce, ce, sizeof(*rce)); | ||
365 | |||
366 | switch (ce->action) { | ||
367 | case OF_RECONFIG_ATTACH_NODE: | ||
368 | rce->action = OF_RECONFIG_DETACH_NODE; | ||
369 | break; | ||
370 | case OF_RECONFIG_DETACH_NODE: | ||
371 | rce->action = OF_RECONFIG_ATTACH_NODE; | ||
372 | break; | ||
373 | case OF_RECONFIG_ADD_PROPERTY: | ||
374 | rce->action = OF_RECONFIG_REMOVE_PROPERTY; | ||
375 | break; | ||
376 | case OF_RECONFIG_REMOVE_PROPERTY: | ||
377 | rce->action = OF_RECONFIG_ADD_PROPERTY; | ||
378 | break; | ||
379 | case OF_RECONFIG_UPDATE_PROPERTY: | ||
380 | rce->old_prop = ce->prop; | ||
381 | rce->prop = ce->old_prop; | ||
382 | break; | ||
383 | } | ||
384 | } | ||
385 | |||
386 | static void __of_changeset_entry_notify(struct of_changeset_entry *ce, bool revert) | ||
387 | { | ||
388 | struct of_changeset_entry ce_inverted; | ||
389 | int ret; | ||
390 | |||
391 | if (revert) { | ||
392 | __of_changeset_entry_invert(ce, &ce_inverted); | ||
393 | ce = &ce_inverted; | ||
394 | } | ||
395 | |||
396 | switch (ce->action) { | ||
397 | case OF_RECONFIG_ATTACH_NODE: | ||
398 | case OF_RECONFIG_DETACH_NODE: | ||
399 | ret = of_reconfig_notify(ce->action, ce->np); | ||
400 | break; | ||
401 | case OF_RECONFIG_ADD_PROPERTY: | ||
402 | case OF_RECONFIG_REMOVE_PROPERTY: | ||
403 | case OF_RECONFIG_UPDATE_PROPERTY: | ||
404 | ret = of_property_notify(ce->action, ce->np, ce->prop, ce->old_prop); | ||
405 | break; | ||
406 | default: | ||
407 | pr_err("%s: invalid devicetree changeset action: %i\n", __func__, | ||
408 | (int)ce->action); | ||
409 | return; | ||
410 | } | ||
411 | |||
412 | if (ret) | ||
413 | pr_err("%s: notifier error @%s\n", __func__, ce->np->full_name); | ||
414 | } | ||
415 | |||
416 | static int __of_changeset_entry_apply(struct of_changeset_entry *ce) | ||
417 | { | ||
418 | struct property *old_prop, **propp; | ||
419 | unsigned long flags; | ||
420 | int ret = 0; | ||
421 | |||
422 | __of_changeset_entry_dump(ce); | ||
423 | |||
424 | raw_spin_lock_irqsave(&devtree_lock, flags); | ||
425 | switch (ce->action) { | ||
426 | case OF_RECONFIG_ATTACH_NODE: | ||
427 | __of_attach_node(ce->np); | ||
428 | break; | ||
429 | case OF_RECONFIG_DETACH_NODE: | ||
430 | __of_detach_node(ce->np); | ||
431 | break; | ||
432 | case OF_RECONFIG_ADD_PROPERTY: | ||
433 | /* If the property is in deadprops then it must be removed */ | ||
434 | for (propp = &ce->np->deadprops; *propp; propp = &(*propp)->next) { | ||
435 | if (*propp == ce->prop) { | ||
436 | *propp = ce->prop->next; | ||
437 | ce->prop->next = NULL; | ||
438 | break; | ||
439 | } | ||
440 | } | ||
441 | |||
442 | ret = __of_add_property(ce->np, ce->prop); | ||
443 | if (ret) { | ||
444 | pr_err("%s: add_property failed @%s/%s\n", | ||
445 | __func__, ce->np->full_name, | ||
446 | ce->prop->name); | ||
447 | break; | ||
448 | } | ||
449 | break; | ||
450 | case OF_RECONFIG_REMOVE_PROPERTY: | ||
451 | ret = __of_remove_property(ce->np, ce->prop); | ||
452 | if (ret) { | ||
453 | pr_err("%s: remove_property failed @%s/%s\n", | ||
454 | __func__, ce->np->full_name, | ||
455 | ce->prop->name); | ||
456 | break; | ||
457 | } | ||
458 | break; | ||
459 | |||
460 | case OF_RECONFIG_UPDATE_PROPERTY: | ||
461 | /* If the property is in deadprops then it must be removed */ | ||
462 | for (propp = &ce->np->deadprops; *propp; propp = &(*propp)->next) { | ||
463 | if (*propp == ce->prop) { | ||
464 | *propp = ce->prop->next; | ||
465 | ce->prop->next = NULL; | ||
466 | break; | ||
467 | } | ||
468 | } | ||
469 | |||
470 | ret = __of_update_property(ce->np, ce->prop, &old_prop); | ||
471 | if (ret) { | ||
472 | pr_err("%s: update_property failed @%s/%s\n", | ||
473 | __func__, ce->np->full_name, | ||
474 | ce->prop->name); | ||
475 | break; | ||
476 | } | ||
477 | break; | ||
478 | default: | ||
479 | ret = -EINVAL; | ||
480 | } | ||
481 | raw_spin_unlock_irqrestore(&devtree_lock, flags); | ||
482 | |||
483 | if (ret) | ||
484 | return ret; | ||
485 | |||
486 | switch (ce->action) { | ||
487 | case OF_RECONFIG_ATTACH_NODE: | ||
488 | __of_attach_node_sysfs(ce->np); | ||
489 | break; | ||
490 | case OF_RECONFIG_DETACH_NODE: | ||
491 | __of_detach_node_sysfs(ce->np); | ||
492 | break; | ||
493 | case OF_RECONFIG_ADD_PROPERTY: | ||
494 | /* ignore duplicate names */ | ||
495 | __of_add_property_sysfs(ce->np, ce->prop); | ||
496 | break; | ||
497 | case OF_RECONFIG_REMOVE_PROPERTY: | ||
498 | __of_remove_property_sysfs(ce->np, ce->prop); | ||
499 | break; | ||
500 | case OF_RECONFIG_UPDATE_PROPERTY: | ||
501 | __of_update_property_sysfs(ce->np, ce->prop, ce->old_prop); | ||
502 | break; | ||
503 | } | ||
504 | |||
505 | return 0; | ||
506 | } | ||
507 | |||
508 | static inline int __of_changeset_entry_revert(struct of_changeset_entry *ce) | ||
509 | { | ||
510 | struct of_changeset_entry ce_inverted; | ||
511 | |||
512 | __of_changeset_entry_invert(ce, &ce_inverted); | ||
513 | return __of_changeset_entry_apply(&ce_inverted); | ||
514 | } | ||
515 | |||
516 | /** | ||
517 | * of_changeset_init - Initialize a changeset for use | ||
518 | * | ||
519 | * @ocs: changeset pointer | ||
520 | * | ||
521 | * Initialize a changeset structure | ||
522 | */ | ||
523 | void of_changeset_init(struct of_changeset *ocs) | ||
524 | { | ||
525 | memset(ocs, 0, sizeof(*ocs)); | ||
526 | INIT_LIST_HEAD(&ocs->entries); | ||
527 | } | ||
528 | |||
529 | /** | ||
530 | * of_changeset_destroy - Destroy a changeset | ||
531 | * | ||
532 | * @ocs: changeset pointer | ||
533 | * | ||
534 | * Destroys a changeset. Note that if a changeset is applied, | ||
535 | * its changes to the tree cannot be reverted. | ||
536 | */ | ||
537 | void of_changeset_destroy(struct of_changeset *ocs) | ||
538 | { | ||
539 | struct of_changeset_entry *ce, *cen; | ||
540 | |||
541 | list_for_each_entry_safe_reverse(ce, cen, &ocs->entries, node) | ||
542 | __of_changeset_entry_destroy(ce); | ||
543 | } | ||
544 | |||
545 | /** | ||
546 | * of_changeset_apply - Applies a changeset | ||
547 | * | ||
548 | * @ocs: changeset pointer | ||
549 | * | ||
550 | * Applies a changeset to the live tree. | ||
551 | * Any side-effects of live tree state changes are applied here on | ||
552 | * sucess, like creation/destruction of devices and side-effects | ||
553 | * like creation of sysfs properties and directories. | ||
554 | * Returns 0 on success, a negative error value in case of an error. | ||
555 | * On error the partially applied effects are reverted. | ||
556 | */ | ||
557 | int of_changeset_apply(struct of_changeset *ocs) | ||
558 | { | ||
559 | struct of_changeset_entry *ce; | ||
560 | int ret; | ||
561 | |||
562 | /* perform the rest of the work */ | ||
563 | pr_debug("of_changeset: applying...\n"); | ||
564 | list_for_each_entry(ce, &ocs->entries, node) { | ||
565 | ret = __of_changeset_entry_apply(ce); | ||
566 | if (ret) { | ||
567 | pr_err("%s: Error applying changeset (%d)\n", __func__, ret); | ||
568 | list_for_each_entry_continue_reverse(ce, &ocs->entries, node) | ||
569 | __of_changeset_entry_revert(ce); | ||
570 | return ret; | ||
571 | } | ||
572 | } | ||
573 | pr_debug("of_changeset: applied, emitting notifiers.\n"); | ||
574 | |||
575 | /* drop the global lock while emitting notifiers */ | ||
576 | mutex_unlock(&of_mutex); | ||
577 | list_for_each_entry(ce, &ocs->entries, node) | ||
578 | __of_changeset_entry_notify(ce, 0); | ||
579 | mutex_lock(&of_mutex); | ||
580 | pr_debug("of_changeset: notifiers sent.\n"); | ||
581 | |||
582 | return 0; | ||
583 | } | ||
584 | |||
585 | /** | ||
586 | * of_changeset_revert - Reverts an applied changeset | ||
587 | * | ||
588 | * @ocs: changeset pointer | ||
589 | * | ||
590 | * Reverts a changeset returning the state of the tree to what it | ||
591 | * was before the application. | ||
592 | * Any side-effects like creation/destruction of devices and | ||
593 | * removal of sysfs properties and directories are applied. | ||
594 | * Returns 0 on success, a negative error value in case of an error. | ||
595 | */ | ||
596 | int of_changeset_revert(struct of_changeset *ocs) | ||
597 | { | ||
598 | struct of_changeset_entry *ce; | ||
599 | int ret; | ||
600 | |||
601 | pr_debug("of_changeset: reverting...\n"); | ||
602 | list_for_each_entry_reverse(ce, &ocs->entries, node) { | ||
603 | ret = __of_changeset_entry_revert(ce); | ||
604 | if (ret) { | ||
605 | pr_err("%s: Error reverting changeset (%d)\n", __func__, ret); | ||
606 | list_for_each_entry_continue(ce, &ocs->entries, node) | ||
607 | __of_changeset_entry_apply(ce); | ||
608 | return ret; | ||
609 | } | ||
610 | } | ||
611 | pr_debug("of_changeset: reverted, emitting notifiers.\n"); | ||
612 | |||
613 | /* drop the global lock while emitting notifiers */ | ||
614 | mutex_unlock(&of_mutex); | ||
615 | list_for_each_entry_reverse(ce, &ocs->entries, node) | ||
616 | __of_changeset_entry_notify(ce, 1); | ||
617 | mutex_lock(&of_mutex); | ||
618 | pr_debug("of_changeset: notifiers sent.\n"); | ||
619 | |||
620 | return 0; | ||
621 | } | ||
622 | |||
623 | /** | ||
624 | * of_changeset_action - Perform a changeset action | ||
625 | * | ||
626 | * @ocs: changeset pointer | ||
627 | * @action: action to perform | ||
628 | * @np: Pointer to device node | ||
629 | * @prop: Pointer to property | ||
630 | * | ||
631 | * On action being one of: | ||
632 | * + OF_RECONFIG_ATTACH_NODE | ||
633 | * + OF_RECONFIG_DETACH_NODE, | ||
634 | * + OF_RECONFIG_ADD_PROPERTY | ||
635 | * + OF_RECONFIG_REMOVE_PROPERTY, | ||
636 | * + OF_RECONFIG_UPDATE_PROPERTY | ||
637 | * Returns 0 on success, a negative error value in case of an error. | ||
638 | */ | ||
639 | int of_changeset_action(struct of_changeset *ocs, unsigned long action, | ||
640 | struct device_node *np, struct property *prop) | ||
641 | { | ||
642 | struct of_changeset_entry *ce; | ||
643 | |||
644 | ce = kzalloc(sizeof(*ce), GFP_KERNEL); | ||
645 | if (!ce) { | ||
646 | pr_err("%s: Failed to allocate\n", __func__); | ||
647 | return -ENOMEM; | ||
648 | } | ||
649 | /* get a reference to the node */ | ||
650 | ce->action = action; | ||
651 | ce->np = of_node_get(np); | ||
652 | ce->prop = prop; | ||
653 | |||
654 | if (action == OF_RECONFIG_UPDATE_PROPERTY && prop) | ||
655 | ce->old_prop = of_find_property(np, prop->name, NULL); | ||
656 | |||
657 | /* add it to the list */ | ||
658 | list_add_tail(&ce->node, &ocs->entries); | ||
659 | return 0; | ||
660 | } | ||
diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index 9aa012e6ea0a..f46a24ffa3fe 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c | |||
@@ -923,24 +923,24 @@ int __init early_init_dt_scan_chosen(unsigned long node, const char *uname, | |||
923 | } | 923 | } |
924 | 924 | ||
925 | #ifdef CONFIG_HAVE_MEMBLOCK | 925 | #ifdef CONFIG_HAVE_MEMBLOCK |
926 | #define MAX_PHYS_ADDR ((phys_addr_t)~0) | ||
927 | |||
926 | void __init __weak early_init_dt_add_memory_arch(u64 base, u64 size) | 928 | void __init __weak early_init_dt_add_memory_arch(u64 base, u64 size) |
927 | { | 929 | { |
928 | const u64 phys_offset = __pa(PAGE_OFFSET); | 930 | const u64 phys_offset = __pa(PAGE_OFFSET); |
929 | base &= PAGE_MASK; | 931 | base &= PAGE_MASK; |
930 | size &= PAGE_MASK; | 932 | size &= PAGE_MASK; |
931 | 933 | ||
932 | if (sizeof(phys_addr_t) < sizeof(u64)) { | 934 | if (base > MAX_PHYS_ADDR) { |
933 | if (base > ULONG_MAX) { | 935 | pr_warning("Ignoring memory block 0x%llx - 0x%llx\n", |
934 | pr_warning("Ignoring memory block 0x%llx - 0x%llx\n", | 936 | base, base + size); |
935 | base, base + size); | 937 | return; |
936 | return; | 938 | } |
937 | } | ||
938 | 939 | ||
939 | if (base + size > ULONG_MAX) { | 940 | if (base + size > MAX_PHYS_ADDR) { |
940 | pr_warning("Ignoring memory range 0x%lx - 0x%llx\n", | 941 | pr_warning("Ignoring memory range 0x%lx - 0x%llx\n", |
941 | ULONG_MAX, base + size); | 942 | ULONG_MAX, base + size); |
942 | size = ULONG_MAX - base; | 943 | size = MAX_PHYS_ADDR - base; |
943 | } | ||
944 | } | 944 | } |
945 | 945 | ||
946 | if (base + size < phys_offset) { | 946 | if (base + size < phys_offset) { |
diff --git a/drivers/of/of_private.h b/drivers/of/of_private.h index ff350c8fa7ac..858e0a5d9a11 100644 --- a/drivers/of/of_private.h +++ b/drivers/of/of_private.h | |||
@@ -31,6 +31,63 @@ struct alias_prop { | |||
31 | char stem[0]; | 31 | char stem[0]; |
32 | }; | 32 | }; |
33 | 33 | ||
34 | extern struct mutex of_aliases_mutex; | 34 | extern struct mutex of_mutex; |
35 | extern struct list_head aliases_lookup; | 35 | extern struct list_head aliases_lookup; |
36 | extern struct kset *of_kset; | ||
37 | |||
38 | |||
39 | static inline struct device_node *kobj_to_device_node(struct kobject *kobj) | ||
40 | { | ||
41 | return container_of(kobj, struct device_node, kobj); | ||
42 | } | ||
43 | |||
44 | #if defined(CONFIG_OF_DYNAMIC) | ||
45 | extern int of_property_notify(int action, struct device_node *np, | ||
46 | struct property *prop, struct property *old_prop); | ||
47 | extern void of_node_release(struct kobject *kobj); | ||
48 | #else /* CONFIG_OF_DYNAMIC */ | ||
49 | static inline int of_property_notify(int action, struct device_node *np, | ||
50 | struct property *prop, struct property *old_prop) | ||
51 | { | ||
52 | return 0; | ||
53 | } | ||
54 | #endif /* CONFIG_OF_DYNAMIC */ | ||
55 | |||
56 | /** | ||
57 | * General utilities for working with live trees. | ||
58 | * | ||
59 | * All functions with two leading underscores operate | ||
60 | * without taking node references, so you either have to | ||
61 | * own the devtree lock or work on detached trees only. | ||
62 | */ | ||
63 | struct property *__of_prop_dup(const struct property *prop, gfp_t allocflags); | ||
64 | struct device_node *__of_node_alloc(const char *full_name, gfp_t allocflags); | ||
65 | |||
66 | extern const void *__of_get_property(const struct device_node *np, | ||
67 | const char *name, int *lenp); | ||
68 | extern int __of_add_property(struct device_node *np, struct property *prop); | ||
69 | extern int __of_add_property_sysfs(struct device_node *np, | ||
70 | struct property *prop); | ||
71 | extern int __of_remove_property(struct device_node *np, struct property *prop); | ||
72 | extern void __of_remove_property_sysfs(struct device_node *np, | ||
73 | struct property *prop); | ||
74 | extern int __of_update_property(struct device_node *np, | ||
75 | struct property *newprop, struct property **oldprop); | ||
76 | extern void __of_update_property_sysfs(struct device_node *np, | ||
77 | struct property *newprop, struct property *oldprop); | ||
78 | |||
79 | extern void __of_attach_node(struct device_node *np); | ||
80 | extern int __of_attach_node_sysfs(struct device_node *np); | ||
81 | extern void __of_detach_node(struct device_node *np); | ||
82 | extern void __of_detach_node_sysfs(struct device_node *np); | ||
83 | |||
84 | /* iterators for transactions, used for overlays */ | ||
85 | /* forward iterator */ | ||
86 | #define for_each_transaction_entry(_oft, _te) \ | ||
87 | list_for_each_entry(_te, &(_oft)->te_list, node) | ||
88 | |||
89 | /* reverse iterator */ | ||
90 | #define for_each_transaction_entry_reverse(_oft, _te) \ | ||
91 | list_for_each_entry_reverse(_te, &(_oft)->te_list, node) | ||
92 | |||
36 | #endif /* _LINUX_OF_PRIVATE_H */ | 93 | #endif /* _LINUX_OF_PRIVATE_H */ |
diff --git a/drivers/of/of_reserved_mem.c b/drivers/of/of_reserved_mem.c index 632aae861375..59fb12e84e6b 100644 --- a/drivers/of/of_reserved_mem.c +++ b/drivers/of/of_reserved_mem.c | |||
@@ -206,8 +206,16 @@ void __init fdt_init_reserved_mem(void) | |||
206 | for (i = 0; i < reserved_mem_count; i++) { | 206 | for (i = 0; i < reserved_mem_count; i++) { |
207 | struct reserved_mem *rmem = &reserved_mem[i]; | 207 | struct reserved_mem *rmem = &reserved_mem[i]; |
208 | unsigned long node = rmem->fdt_node; | 208 | unsigned long node = rmem->fdt_node; |
209 | int len; | ||
210 | const __be32 *prop; | ||
209 | int err = 0; | 211 | int err = 0; |
210 | 212 | ||
213 | prop = of_get_flat_dt_prop(node, "phandle", &len); | ||
214 | if (!prop) | ||
215 | prop = of_get_flat_dt_prop(node, "linux,phandle", &len); | ||
216 | if (prop) | ||
217 | rmem->phandle = of_read_number(prop, len/4); | ||
218 | |||
211 | if (rmem->size == 0) | 219 | if (rmem->size == 0) |
212 | err = __reserved_mem_alloc_size(node, rmem->name, | 220 | err = __reserved_mem_alloc_size(node, rmem->name, |
213 | &rmem->base, &rmem->size); | 221 | &rmem->base, &rmem->size); |
@@ -215,3 +223,65 @@ void __init fdt_init_reserved_mem(void) | |||
215 | __reserved_mem_init_node(rmem); | 223 | __reserved_mem_init_node(rmem); |
216 | } | 224 | } |
217 | } | 225 | } |
226 | |||
227 | static inline struct reserved_mem *__find_rmem(struct device_node *node) | ||
228 | { | ||
229 | unsigned int i; | ||
230 | |||
231 | if (!node->phandle) | ||
232 | return NULL; | ||
233 | |||
234 | for (i = 0; i < reserved_mem_count; i++) | ||
235 | if (reserved_mem[i].phandle == node->phandle) | ||
236 | return &reserved_mem[i]; | ||
237 | return NULL; | ||
238 | } | ||
239 | |||
240 | /** | ||
241 | * of_reserved_mem_device_init() - assign reserved memory region to given device | ||
242 | * | ||
243 | * This function assign memory region pointed by "memory-region" device tree | ||
244 | * property to the given device. | ||
245 | */ | ||
246 | void of_reserved_mem_device_init(struct device *dev) | ||
247 | { | ||
248 | struct reserved_mem *rmem; | ||
249 | struct device_node *np; | ||
250 | |||
251 | np = of_parse_phandle(dev->of_node, "memory-region", 0); | ||
252 | if (!np) | ||
253 | return; | ||
254 | |||
255 | rmem = __find_rmem(np); | ||
256 | of_node_put(np); | ||
257 | |||
258 | if (!rmem || !rmem->ops || !rmem->ops->device_init) | ||
259 | return; | ||
260 | |||
261 | rmem->ops->device_init(rmem, dev); | ||
262 | dev_info(dev, "assigned reserved memory node %s\n", rmem->name); | ||
263 | } | ||
264 | |||
265 | /** | ||
266 | * of_reserved_mem_device_release() - release reserved memory device structures | ||
267 | * | ||
268 | * This function releases structures allocated for memory region handling for | ||
269 | * the given device. | ||
270 | */ | ||
271 | void of_reserved_mem_device_release(struct device *dev) | ||
272 | { | ||
273 | struct reserved_mem *rmem; | ||
274 | struct device_node *np; | ||
275 | |||
276 | np = of_parse_phandle(dev->of_node, "memory-region", 0); | ||
277 | if (!np) | ||
278 | return; | ||
279 | |||
280 | rmem = __find_rmem(np); | ||
281 | of_node_put(np); | ||
282 | |||
283 | if (!rmem || !rmem->ops || !rmem->ops->device_release) | ||
284 | return; | ||
285 | |||
286 | rmem->ops->device_release(rmem, dev); | ||
287 | } | ||
diff --git a/drivers/of/platform.c b/drivers/of/platform.c index 500436f9be7f..0197725e033a 100644 --- a/drivers/of/platform.c +++ b/drivers/of/platform.c | |||
@@ -422,6 +422,7 @@ static int of_platform_bus_create(struct device_node *bus, | |||
422 | break; | 422 | break; |
423 | } | 423 | } |
424 | } | 424 | } |
425 | of_node_set_flag(bus, OF_POPULATED_BUS); | ||
425 | return rc; | 426 | return rc; |
426 | } | 427 | } |
427 | 428 | ||
@@ -508,19 +509,13 @@ EXPORT_SYMBOL_GPL(of_platform_populate); | |||
508 | 509 | ||
509 | static int of_platform_device_destroy(struct device *dev, void *data) | 510 | static int of_platform_device_destroy(struct device *dev, void *data) |
510 | { | 511 | { |
511 | bool *children_left = data; | ||
512 | |||
513 | /* Do not touch devices not populated from the device tree */ | 512 | /* Do not touch devices not populated from the device tree */ |
514 | if (!dev->of_node || !of_node_check_flag(dev->of_node, OF_POPULATED)) { | 513 | if (!dev->of_node || !of_node_check_flag(dev->of_node, OF_POPULATED)) |
515 | *children_left = true; | ||
516 | return 0; | 514 | return 0; |
517 | } | ||
518 | 515 | ||
519 | /* Recurse, but don't touch this device if it has any children left */ | 516 | /* Recurse for any nodes that were treated as busses */ |
520 | if (of_platform_depopulate(dev) != 0) { | 517 | if (of_node_check_flag(dev->of_node, OF_POPULATED_BUS)) |
521 | *children_left = true; | 518 | device_for_each_child(dev, NULL, of_platform_device_destroy); |
522 | return 0; | ||
523 | } | ||
524 | 519 | ||
525 | if (dev->bus == &platform_bus_type) | 520 | if (dev->bus == &platform_bus_type) |
526 | platform_device_unregister(to_platform_device(dev)); | 521 | platform_device_unregister(to_platform_device(dev)); |
@@ -528,19 +523,15 @@ static int of_platform_device_destroy(struct device *dev, void *data) | |||
528 | else if (dev->bus == &amba_bustype) | 523 | else if (dev->bus == &amba_bustype) |
529 | amba_device_unregister(to_amba_device(dev)); | 524 | amba_device_unregister(to_amba_device(dev)); |
530 | #endif | 525 | #endif |
531 | else { | ||
532 | *children_left = true; | ||
533 | return 0; | ||
534 | } | ||
535 | 526 | ||
536 | of_node_clear_flag(dev->of_node, OF_POPULATED); | 527 | of_node_clear_flag(dev->of_node, OF_POPULATED); |
537 | 528 | of_node_clear_flag(dev->of_node, OF_POPULATED_BUS); | |
538 | return 0; | 529 | return 0; |
539 | } | 530 | } |
540 | 531 | ||
541 | /** | 532 | /** |
542 | * of_platform_depopulate() - Remove devices populated from device tree | 533 | * of_platform_depopulate() - Remove devices populated from device tree |
543 | * @parent: device which childred will be removed | 534 | * @parent: device which children will be removed |
544 | * | 535 | * |
545 | * Complementary to of_platform_populate(), this function removes children | 536 | * Complementary to of_platform_populate(), this function removes children |
546 | * of the given device (and, recurrently, their children) that have been | 537 | * of the given device (and, recurrently, their children) that have been |
@@ -550,14 +541,9 @@ static int of_platform_device_destroy(struct device *dev, void *data) | |||
550 | * Returns 0 when all children devices have been removed or | 541 | * Returns 0 when all children devices have been removed or |
551 | * -EBUSY when some children remained. | 542 | * -EBUSY when some children remained. |
552 | */ | 543 | */ |
553 | int of_platform_depopulate(struct device *parent) | 544 | void of_platform_depopulate(struct device *parent) |
554 | { | 545 | { |
555 | bool children_left = false; | 546 | device_for_each_child(parent, NULL, of_platform_device_destroy); |
556 | |||
557 | device_for_each_child(parent, &children_left, | ||
558 | of_platform_device_destroy); | ||
559 | |||
560 | return children_left ? -EBUSY : 0; | ||
561 | } | 547 | } |
562 | EXPORT_SYMBOL_GPL(of_platform_depopulate); | 548 | EXPORT_SYMBOL_GPL(of_platform_depopulate); |
563 | 549 | ||
diff --git a/drivers/of/selftest.c b/drivers/of/selftest.c index 077314eebb95..d41002667833 100644 --- a/drivers/of/selftest.c +++ b/drivers/of/selftest.c | |||
@@ -9,6 +9,7 @@ | |||
9 | #include <linux/errno.h> | 9 | #include <linux/errno.h> |
10 | #include <linux/module.h> | 10 | #include <linux/module.h> |
11 | #include <linux/of.h> | 11 | #include <linux/of.h> |
12 | #include <linux/of_fdt.h> | ||
12 | #include <linux/of_irq.h> | 13 | #include <linux/of_irq.h> |
13 | #include <linux/of_platform.h> | 14 | #include <linux/of_platform.h> |
14 | #include <linux/list.h> | 15 | #include <linux/list.h> |
@@ -16,11 +17,17 @@ | |||
16 | #include <linux/slab.h> | 17 | #include <linux/slab.h> |
17 | #include <linux/device.h> | 18 | #include <linux/device.h> |
18 | 19 | ||
20 | #include "of_private.h" | ||
21 | |||
19 | static struct selftest_results { | 22 | static struct selftest_results { |
20 | int passed; | 23 | int passed; |
21 | int failed; | 24 | int failed; |
22 | } selftest_results; | 25 | } selftest_results; |
23 | 26 | ||
27 | #define NO_OF_NODES 2 | ||
28 | static struct device_node *nodes[NO_OF_NODES]; | ||
29 | static int last_node_index; | ||
30 | |||
24 | #define selftest(result, fmt, ...) { \ | 31 | #define selftest(result, fmt, ...) { \ |
25 | if (!(result)) { \ | 32 | if (!(result)) { \ |
26 | selftest_results.failed++; \ | 33 | selftest_results.failed++; \ |
@@ -266,6 +273,81 @@ static void __init of_selftest_property_match_string(void) | |||
266 | selftest(rc == -EILSEQ, "unterminated string; rc=%i", rc); | 273 | selftest(rc == -EILSEQ, "unterminated string; rc=%i", rc); |
267 | } | 274 | } |
268 | 275 | ||
276 | #define propcmp(p1, p2) (((p1)->length == (p2)->length) && \ | ||
277 | (p1)->value && (p2)->value && \ | ||
278 | !memcmp((p1)->value, (p2)->value, (p1)->length) && \ | ||
279 | !strcmp((p1)->name, (p2)->name)) | ||
280 | static void __init of_selftest_property_copy(void) | ||
281 | { | ||
282 | #ifdef CONFIG_OF_DYNAMIC | ||
283 | struct property p1 = { .name = "p1", .length = 0, .value = "" }; | ||
284 | struct property p2 = { .name = "p2", .length = 5, .value = "abcd" }; | ||
285 | struct property *new; | ||
286 | |||
287 | new = __of_prop_dup(&p1, GFP_KERNEL); | ||
288 | selftest(new && propcmp(&p1, new), "empty property didn't copy correctly\n"); | ||
289 | kfree(new->value); | ||
290 | kfree(new->name); | ||
291 | kfree(new); | ||
292 | |||
293 | new = __of_prop_dup(&p2, GFP_KERNEL); | ||
294 | selftest(new && propcmp(&p2, new), "non-empty property didn't copy correctly\n"); | ||
295 | kfree(new->value); | ||
296 | kfree(new->name); | ||
297 | kfree(new); | ||
298 | #endif | ||
299 | } | ||
300 | |||
301 | static void __init of_selftest_changeset(void) | ||
302 | { | ||
303 | #ifdef CONFIG_OF_DYNAMIC | ||
304 | struct property *ppadd, padd = { .name = "prop-add", .length = 0, .value = "" }; | ||
305 | struct property *ppupdate, pupdate = { .name = "prop-update", .length = 5, .value = "abcd" }; | ||
306 | struct property *ppremove; | ||
307 | struct device_node *n1, *n2, *n21, *nremove, *parent; | ||
308 | struct of_changeset chgset; | ||
309 | |||
310 | of_changeset_init(&chgset); | ||
311 | n1 = __of_node_alloc("/testcase-data/changeset/n1", GFP_KERNEL); | ||
312 | selftest(n1, "testcase setup failure\n"); | ||
313 | n2 = __of_node_alloc("/testcase-data/changeset/n2", GFP_KERNEL); | ||
314 | selftest(n2, "testcase setup failure\n"); | ||
315 | n21 = __of_node_alloc("/testcase-data/changeset/n2/n21", GFP_KERNEL); | ||
316 | selftest(n21, "testcase setup failure %p\n", n21); | ||
317 | nremove = of_find_node_by_path("/testcase-data/changeset/node-remove"); | ||
318 | selftest(nremove, "testcase setup failure\n"); | ||
319 | ppadd = __of_prop_dup(&padd, GFP_KERNEL); | ||
320 | selftest(ppadd, "testcase setup failure\n"); | ||
321 | ppupdate = __of_prop_dup(&pupdate, GFP_KERNEL); | ||
322 | selftest(ppupdate, "testcase setup failure\n"); | ||
323 | parent = nremove->parent; | ||
324 | n1->parent = parent; | ||
325 | n2->parent = parent; | ||
326 | n21->parent = n2; | ||
327 | n2->child = n21; | ||
328 | ppremove = of_find_property(parent, "prop-remove", NULL); | ||
329 | selftest(ppremove, "failed to find removal prop"); | ||
330 | |||
331 | of_changeset_init(&chgset); | ||
332 | selftest(!of_changeset_attach_node(&chgset, n1), "fail attach n1\n"); | ||
333 | selftest(!of_changeset_attach_node(&chgset, n2), "fail attach n2\n"); | ||
334 | selftest(!of_changeset_detach_node(&chgset, nremove), "fail remove node\n"); | ||
335 | selftest(!of_changeset_attach_node(&chgset, n21), "fail attach n21\n"); | ||
336 | selftest(!of_changeset_add_property(&chgset, parent, ppadd), "fail add prop\n"); | ||
337 | selftest(!of_changeset_update_property(&chgset, parent, ppupdate), "fail update prop\n"); | ||
338 | selftest(!of_changeset_remove_property(&chgset, parent, ppremove), "fail remove prop\n"); | ||
339 | mutex_lock(&of_mutex); | ||
340 | selftest(!of_changeset_apply(&chgset), "apply failed\n"); | ||
341 | mutex_unlock(&of_mutex); | ||
342 | |||
343 | mutex_lock(&of_mutex); | ||
344 | selftest(!of_changeset_revert(&chgset), "revert failed\n"); | ||
345 | mutex_unlock(&of_mutex); | ||
346 | |||
347 | of_changeset_destroy(&chgset); | ||
348 | #endif | ||
349 | } | ||
350 | |||
269 | static void __init of_selftest_parse_interrupts(void) | 351 | static void __init of_selftest_parse_interrupts(void) |
270 | { | 352 | { |
271 | struct device_node *np; | 353 | struct device_node *np; |
@@ -517,9 +599,156 @@ static void __init of_selftest_platform_populate(void) | |||
517 | } | 599 | } |
518 | } | 600 | } |
519 | 601 | ||
602 | /** | ||
603 | * update_node_properties - adds the properties | ||
604 | * of np into dup node (present in live tree) and | ||
605 | * updates parent of children of np to dup. | ||
606 | * | ||
607 | * @np: node already present in live tree | ||
608 | * @dup: node present in live tree to be updated | ||
609 | */ | ||
610 | static void update_node_properties(struct device_node *np, | ||
611 | struct device_node *dup) | ||
612 | { | ||
613 | struct property *prop; | ||
614 | struct device_node *child; | ||
615 | |||
616 | for_each_property_of_node(np, prop) | ||
617 | of_add_property(dup, prop); | ||
618 | |||
619 | for_each_child_of_node(np, child) | ||
620 | child->parent = dup; | ||
621 | } | ||
622 | |||
623 | /** | ||
624 | * attach_node_and_children - attaches nodes | ||
625 | * and its children to live tree | ||
626 | * | ||
627 | * @np: Node to attach to live tree | ||
628 | */ | ||
629 | static int attach_node_and_children(struct device_node *np) | ||
630 | { | ||
631 | struct device_node *next, *root = np, *dup; | ||
632 | |||
633 | if (!np) { | ||
634 | pr_warn("%s: No tree to attach; not running tests\n", | ||
635 | __func__); | ||
636 | return -ENODATA; | ||
637 | } | ||
638 | |||
639 | |||
640 | /* skip root node */ | ||
641 | np = np->child; | ||
642 | /* storing a copy in temporary node */ | ||
643 | dup = np; | ||
644 | |||
645 | while (dup) { | ||
646 | nodes[last_node_index++] = dup; | ||
647 | dup = dup->sibling; | ||
648 | } | ||
649 | dup = NULL; | ||
650 | |||
651 | while (np) { | ||
652 | next = np->allnext; | ||
653 | dup = of_find_node_by_path(np->full_name); | ||
654 | if (dup) | ||
655 | update_node_properties(np, dup); | ||
656 | else { | ||
657 | np->child = NULL; | ||
658 | if (np->parent == root) | ||
659 | np->parent = of_allnodes; | ||
660 | of_attach_node(np); | ||
661 | } | ||
662 | np = next; | ||
663 | } | ||
664 | |||
665 | return 0; | ||
666 | } | ||
667 | |||
668 | /** | ||
669 | * selftest_data_add - Reads, copies data from | ||
670 | * linked tree and attaches it to the live tree | ||
671 | */ | ||
672 | static int __init selftest_data_add(void) | ||
673 | { | ||
674 | void *selftest_data; | ||
675 | struct device_node *selftest_data_node; | ||
676 | extern uint8_t __dtb_testcases_begin[]; | ||
677 | extern uint8_t __dtb_testcases_end[]; | ||
678 | const int size = __dtb_testcases_end - __dtb_testcases_begin; | ||
679 | |||
680 | if (!size || !of_allnodes) { | ||
681 | pr_warn("%s: No testcase data to attach; not running tests\n", | ||
682 | __func__); | ||
683 | return -ENODATA; | ||
684 | } | ||
685 | |||
686 | /* creating copy */ | ||
687 | selftest_data = kmemdup(__dtb_testcases_begin, size, GFP_KERNEL); | ||
688 | |||
689 | if (!selftest_data) { | ||
690 | pr_warn("%s: Failed to allocate memory for selftest_data; " | ||
691 | "not running tests\n", __func__); | ||
692 | return -ENOMEM; | ||
693 | } | ||
694 | of_fdt_unflatten_tree(selftest_data, &selftest_data_node); | ||
695 | |||
696 | /* attach the sub-tree to live tree */ | ||
697 | return attach_node_and_children(selftest_data_node); | ||
698 | } | ||
699 | |||
700 | /** | ||
701 | * detach_node_and_children - detaches node | ||
702 | * and its children from live tree | ||
703 | * | ||
704 | * @np: Node to detach from live tree | ||
705 | */ | ||
706 | static void detach_node_and_children(struct device_node *np) | ||
707 | { | ||
708 | while (np->child) | ||
709 | detach_node_and_children(np->child); | ||
710 | |||
711 | while (np->sibling) | ||
712 | detach_node_and_children(np->sibling); | ||
713 | |||
714 | of_detach_node(np); | ||
715 | } | ||
716 | |||
717 | /** | ||
718 | * selftest_data_remove - removes the selftest data | ||
719 | * nodes from the live tree | ||
720 | */ | ||
721 | static void selftest_data_remove(void) | ||
722 | { | ||
723 | struct device_node *np; | ||
724 | struct property *prop; | ||
725 | |||
726 | while (last_node_index >= 0) { | ||
727 | if (nodes[last_node_index]) { | ||
728 | np = of_find_node_by_path(nodes[last_node_index]->full_name); | ||
729 | if (strcmp(np->full_name, "/aliases") != 0) { | ||
730 | detach_node_and_children(np->child); | ||
731 | of_detach_node(np); | ||
732 | } else { | ||
733 | for_each_property_of_node(np, prop) { | ||
734 | if (strcmp(prop->name, "testcase-alias") == 0) | ||
735 | of_remove_property(np, prop); | ||
736 | } | ||
737 | } | ||
738 | } | ||
739 | last_node_index--; | ||
740 | } | ||
741 | } | ||
742 | |||
520 | static int __init of_selftest(void) | 743 | static int __init of_selftest(void) |
521 | { | 744 | { |
522 | struct device_node *np; | 745 | struct device_node *np; |
746 | int res; | ||
747 | |||
748 | /* adding data for selftest */ | ||
749 | res = selftest_data_add(); | ||
750 | if (res) | ||
751 | return res; | ||
523 | 752 | ||
524 | np = of_find_node_by_path("/testcase-data/phandle-tests/consumer-a"); | 753 | np = of_find_node_by_path("/testcase-data/phandle-tests/consumer-a"); |
525 | if (!np) { | 754 | if (!np) { |
@@ -533,12 +762,18 @@ static int __init of_selftest(void) | |||
533 | of_selftest_dynamic(); | 762 | of_selftest_dynamic(); |
534 | of_selftest_parse_phandle_with_args(); | 763 | of_selftest_parse_phandle_with_args(); |
535 | of_selftest_property_match_string(); | 764 | of_selftest_property_match_string(); |
765 | of_selftest_property_copy(); | ||
766 | of_selftest_changeset(); | ||
536 | of_selftest_parse_interrupts(); | 767 | of_selftest_parse_interrupts(); |
537 | of_selftest_parse_interrupts_extended(); | 768 | of_selftest_parse_interrupts_extended(); |
538 | of_selftest_match_node(); | 769 | of_selftest_match_node(); |
539 | of_selftest_platform_populate(); | 770 | of_selftest_platform_populate(); |
540 | pr_info("end of selftest - %i passed, %i failed\n", | 771 | pr_info("end of selftest - %i passed, %i failed\n", |
541 | selftest_results.passed, selftest_results.failed); | 772 | selftest_results.passed, selftest_results.failed); |
773 | |||
774 | /* removing selftest data from live tree */ | ||
775 | selftest_data_remove(); | ||
776 | |||
542 | return 0; | 777 | return 0; |
543 | } | 778 | } |
544 | late_initcall(of_selftest); | 779 | late_initcall(of_selftest); |
diff --git a/drivers/of/testcase-data/testcases.dts b/drivers/of/testcase-data/testcases.dts new file mode 100644 index 000000000000..219ef9324e9c --- /dev/null +++ b/drivers/of/testcase-data/testcases.dts | |||
@@ -0,0 +1,15 @@ | |||
1 | /dts-v1/; | ||
2 | / { | ||
3 | testcase-data { | ||
4 | changeset { | ||
5 | prop-update = "hello"; | ||
6 | prop-remove = "world"; | ||
7 | node-remove { | ||
8 | }; | ||
9 | }; | ||
10 | }; | ||
11 | }; | ||
12 | #include "tests-phandle.dtsi" | ||
13 | #include "tests-interrupts.dtsi" | ||
14 | #include "tests-match.dtsi" | ||
15 | #include "tests-platform.dtsi" | ||
diff --git a/drivers/of/testcase-data/testcases.dtsi b/drivers/of/testcase-data/testcases.dtsi deleted file mode 100644 index 6d8d980ac858..000000000000 --- a/drivers/of/testcase-data/testcases.dtsi +++ /dev/null | |||
@@ -1,4 +0,0 @@ | |||
1 | #include "tests-phandle.dtsi" | ||
2 | #include "tests-interrupts.dtsi" | ||
3 | #include "tests-match.dtsi" | ||
4 | #include "tests-platform.dtsi" | ||