diff options
Diffstat (limited to 'drivers')
24 files changed, 2213 insertions, 459 deletions
diff --git a/drivers/base/platform.c b/drivers/base/platform.c index b2afc29403f9..233ececd15a3 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c | |||
@@ -1006,6 +1006,7 @@ int __init platform_bus_init(void) | |||
1006 | error = bus_register(&platform_bus_type); | 1006 | error = bus_register(&platform_bus_type); |
1007 | if (error) | 1007 | if (error) |
1008 | device_unregister(&platform_bus); | 1008 | device_unregister(&platform_bus); |
1009 | of_platform_register_reconfig_notifier(); | ||
1009 | return error; | 1010 | return error; |
1010 | } | 1011 | } |
1011 | 1012 | ||
diff --git a/drivers/crypto/nx/nx-842.c b/drivers/crypto/nx/nx-842.c index 061407d59520..887196e9b50c 100644 --- a/drivers/crypto/nx/nx-842.c +++ b/drivers/crypto/nx/nx-842.c | |||
@@ -1009,9 +1009,9 @@ error_out: | |||
1009 | * notifier_to_errno() to decode this value | 1009 | * notifier_to_errno() to decode this value |
1010 | */ | 1010 | */ |
1011 | static int nx842_OF_notifier(struct notifier_block *np, unsigned long action, | 1011 | static int nx842_OF_notifier(struct notifier_block *np, unsigned long action, |
1012 | void *update) | 1012 | void *data) |
1013 | { | 1013 | { |
1014 | struct of_prop_reconfig *upd = update; | 1014 | struct of_reconfig_data *upd = data; |
1015 | struct nx842_devdata *local_devdata; | 1015 | struct nx842_devdata *local_devdata; |
1016 | struct device_node *node = NULL; | 1016 | struct device_node *node = NULL; |
1017 | 1017 | ||
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index 68aeb8eedae0..229a89e84b0f 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c | |||
@@ -49,6 +49,7 @@ | |||
49 | #include <linux/acpi.h> | 49 | #include <linux/acpi.h> |
50 | #include <linux/jump_label.h> | 50 | #include <linux/jump_label.h> |
51 | #include <asm/uaccess.h> | 51 | #include <asm/uaccess.h> |
52 | #include <linux/err.h> | ||
52 | 53 | ||
53 | #include "i2c-core.h" | 54 | #include "i2c-core.h" |
54 | 55 | ||
@@ -1369,63 +1370,69 @@ static void i2c_scan_static_board_info(struct i2c_adapter *adapter) | |||
1369 | /* OF support code */ | 1370 | /* OF support code */ |
1370 | 1371 | ||
1371 | #if IS_ENABLED(CONFIG_OF) | 1372 | #if IS_ENABLED(CONFIG_OF) |
1372 | static void of_i2c_register_devices(struct i2c_adapter *adap) | 1373 | static struct i2c_client *of_i2c_register_device(struct i2c_adapter *adap, |
1374 | struct device_node *node) | ||
1373 | { | 1375 | { |
1374 | void *result; | 1376 | struct i2c_client *result; |
1375 | struct device_node *node; | 1377 | struct i2c_board_info info = {}; |
1378 | struct dev_archdata dev_ad = {}; | ||
1379 | const __be32 *addr; | ||
1380 | int len; | ||
1376 | 1381 | ||
1377 | /* Only register child devices if the adapter has a node pointer set */ | 1382 | dev_dbg(&adap->dev, "of_i2c: register %s\n", node->full_name); |
1378 | if (!adap->dev.of_node) | ||
1379 | return; | ||
1380 | 1383 | ||
1381 | dev_dbg(&adap->dev, "of_i2c: walking child nodes\n"); | 1384 | if (of_modalias_node(node, info.type, sizeof(info.type)) < 0) { |
1385 | dev_err(&adap->dev, "of_i2c: modalias failure on %s\n", | ||
1386 | node->full_name); | ||
1387 | return ERR_PTR(-EINVAL); | ||
1388 | } | ||
1382 | 1389 | ||
1383 | for_each_available_child_of_node(adap->dev.of_node, node) { | 1390 | addr = of_get_property(node, "reg", &len); |
1384 | struct i2c_board_info info = {}; | 1391 | if (!addr || (len < sizeof(int))) { |
1385 | struct dev_archdata dev_ad = {}; | 1392 | dev_err(&adap->dev, "of_i2c: invalid reg on %s\n", |
1386 | const __be32 *addr; | 1393 | node->full_name); |
1387 | int len; | 1394 | return ERR_PTR(-EINVAL); |
1395 | } | ||
1388 | 1396 | ||
1389 | dev_dbg(&adap->dev, "of_i2c: register %s\n", node->full_name); | 1397 | info.addr = be32_to_cpup(addr); |
1398 | if (info.addr > (1 << 10) - 1) { | ||
1399 | dev_err(&adap->dev, "of_i2c: invalid addr=%x on %s\n", | ||
1400 | info.addr, node->full_name); | ||
1401 | return ERR_PTR(-EINVAL); | ||
1402 | } | ||
1390 | 1403 | ||
1391 | if (of_modalias_node(node, info.type, sizeof(info.type)) < 0) { | 1404 | info.irq = irq_of_parse_and_map(node, 0); |
1392 | dev_err(&adap->dev, "of_i2c: modalias failure on %s\n", | 1405 | info.of_node = of_node_get(node); |
1393 | node->full_name); | 1406 | info.archdata = &dev_ad; |
1394 | continue; | ||
1395 | } | ||
1396 | 1407 | ||
1397 | addr = of_get_property(node, "reg", &len); | 1408 | if (of_get_property(node, "wakeup-source", NULL)) |
1398 | if (!addr || (len < sizeof(int))) { | 1409 | info.flags |= I2C_CLIENT_WAKE; |
1399 | dev_err(&adap->dev, "of_i2c: invalid reg on %s\n", | ||
1400 | node->full_name); | ||
1401 | continue; | ||
1402 | } | ||
1403 | 1410 | ||
1404 | info.addr = be32_to_cpup(addr); | 1411 | request_module("%s%s", I2C_MODULE_PREFIX, info.type); |
1405 | if (info.addr > (1 << 10) - 1) { | 1412 | |
1406 | dev_err(&adap->dev, "of_i2c: invalid addr=%x on %s\n", | 1413 | result = i2c_new_device(adap, &info); |
1407 | info.addr, node->full_name); | 1414 | if (result == NULL) { |
1408 | continue; | 1415 | dev_err(&adap->dev, "of_i2c: Failure registering %s\n", |
1409 | } | 1416 | node->full_name); |
1417 | of_node_put(node); | ||
1418 | irq_dispose_mapping(info.irq); | ||
1419 | return ERR_PTR(-EINVAL); | ||
1420 | } | ||
1421 | return result; | ||
1422 | } | ||
1410 | 1423 | ||
1411 | info.irq = irq_of_parse_and_map(node, 0); | 1424 | static void of_i2c_register_devices(struct i2c_adapter *adap) |
1412 | info.of_node = of_node_get(node); | 1425 | { |
1413 | info.archdata = &dev_ad; | 1426 | struct device_node *node; |
1414 | 1427 | ||
1415 | if (of_get_property(node, "wakeup-source", NULL)) | 1428 | /* Only register child devices if the adapter has a node pointer set */ |
1416 | info.flags |= I2C_CLIENT_WAKE; | 1429 | if (!adap->dev.of_node) |
1430 | return; | ||
1417 | 1431 | ||
1418 | request_module("%s%s", I2C_MODULE_PREFIX, info.type); | 1432 | dev_dbg(&adap->dev, "of_i2c: walking child nodes\n"); |
1419 | 1433 | ||
1420 | result = i2c_new_device(adap, &info); | 1434 | for_each_available_child_of_node(adap->dev.of_node, node) |
1421 | if (result == NULL) { | 1435 | of_i2c_register_device(adap, node); |
1422 | dev_err(&adap->dev, "of_i2c: Failure registering %s\n", | ||
1423 | node->full_name); | ||
1424 | of_node_put(node); | ||
1425 | irq_dispose_mapping(info.irq); | ||
1426 | continue; | ||
1427 | } | ||
1428 | } | ||
1429 | } | 1436 | } |
1430 | 1437 | ||
1431 | static int of_dev_node_match(struct device *dev, void *data) | 1438 | static int of_dev_node_match(struct device *dev, void *data) |
@@ -1945,6 +1952,52 @@ void i2c_clients_command(struct i2c_adapter *adap, unsigned int cmd, void *arg) | |||
1945 | } | 1952 | } |
1946 | EXPORT_SYMBOL(i2c_clients_command); | 1953 | EXPORT_SYMBOL(i2c_clients_command); |
1947 | 1954 | ||
1955 | #if IS_ENABLED(CONFIG_OF_DYNAMIC) | ||
1956 | static int of_i2c_notify(struct notifier_block *nb, unsigned long action, | ||
1957 | void *arg) | ||
1958 | { | ||
1959 | struct of_reconfig_data *rd = arg; | ||
1960 | struct i2c_adapter *adap; | ||
1961 | struct i2c_client *client; | ||
1962 | |||
1963 | switch (of_reconfig_get_state_change(action, rd)) { | ||
1964 | case OF_RECONFIG_CHANGE_ADD: | ||
1965 | adap = of_find_i2c_adapter_by_node(rd->dn->parent); | ||
1966 | if (adap == NULL) | ||
1967 | return NOTIFY_OK; /* not for us */ | ||
1968 | |||
1969 | client = of_i2c_register_device(adap, rd->dn); | ||
1970 | put_device(&adap->dev); | ||
1971 | |||
1972 | if (IS_ERR(client)) { | ||
1973 | pr_err("%s: failed to create for '%s'\n", | ||
1974 | __func__, rd->dn->full_name); | ||
1975 | return notifier_from_errno(PTR_ERR(client)); | ||
1976 | } | ||
1977 | break; | ||
1978 | case OF_RECONFIG_CHANGE_REMOVE: | ||
1979 | /* find our device by node */ | ||
1980 | client = of_find_i2c_device_by_node(rd->dn); | ||
1981 | if (client == NULL) | ||
1982 | return NOTIFY_OK; /* no? not meant for us */ | ||
1983 | |||
1984 | /* unregister takes one ref away */ | ||
1985 | i2c_unregister_device(client); | ||
1986 | |||
1987 | /* and put the reference of the find */ | ||
1988 | put_device(&client->dev); | ||
1989 | break; | ||
1990 | } | ||
1991 | |||
1992 | return NOTIFY_OK; | ||
1993 | } | ||
1994 | static struct notifier_block i2c_of_notifier = { | ||
1995 | .notifier_call = of_i2c_notify, | ||
1996 | }; | ||
1997 | #else | ||
1998 | extern struct notifier_block i2c_of_notifier; | ||
1999 | #endif /* CONFIG_OF_DYNAMIC */ | ||
2000 | |||
1948 | static int __init i2c_init(void) | 2001 | static int __init i2c_init(void) |
1949 | { | 2002 | { |
1950 | int retval; | 2003 | int retval; |
@@ -1962,6 +2015,10 @@ static int __init i2c_init(void) | |||
1962 | retval = i2c_add_driver(&dummy_driver); | 2015 | retval = i2c_add_driver(&dummy_driver); |
1963 | if (retval) | 2016 | if (retval) |
1964 | goto class_err; | 2017 | goto class_err; |
2018 | |||
2019 | if (IS_ENABLED(CONFIG_OF_DYNAMIC)) | ||
2020 | WARN_ON(of_reconfig_notifier_register(&i2c_of_notifier)); | ||
2021 | |||
1965 | return 0; | 2022 | return 0; |
1966 | 2023 | ||
1967 | class_err: | 2024 | class_err: |
@@ -1975,6 +2032,8 @@ bus_err: | |||
1975 | 2032 | ||
1976 | static void __exit i2c_exit(void) | 2033 | static void __exit i2c_exit(void) |
1977 | { | 2034 | { |
2035 | if (IS_ENABLED(CONFIG_OF_DYNAMIC)) | ||
2036 | WARN_ON(of_reconfig_notifier_unregister(&i2c_of_notifier)); | ||
1978 | i2c_del_driver(&dummy_driver); | 2037 | i2c_del_driver(&dummy_driver); |
1979 | #ifdef CONFIG_I2C_COMPAT | 2038 | #ifdef CONFIG_I2C_COMPAT |
1980 | class_compat_unregister(i2c_adapter_compat_class); | 2039 | class_compat_unregister(i2c_adapter_compat_class); |
diff --git a/drivers/mfd/vexpress-sysreg.c b/drivers/mfd/vexpress-sysreg.c index 9e21e4fc9599..8f43ab8fd2d6 100644 --- a/drivers/mfd/vexpress-sysreg.c +++ b/drivers/mfd/vexpress-sysreg.c | |||
@@ -223,7 +223,7 @@ static int vexpress_sysreg_probe(struct platform_device *pdev) | |||
223 | vexpress_config_set_master(vexpress_sysreg_get_master()); | 223 | vexpress_config_set_master(vexpress_sysreg_get_master()); |
224 | 224 | ||
225 | /* Confirm board type against DT property, if available */ | 225 | /* Confirm board type against DT property, if available */ |
226 | if (of_property_read_u32(of_allnodes, "arm,hbi", &dt_hbi) == 0) { | 226 | if (of_property_read_u32(of_root, "arm,hbi", &dt_hbi) == 0) { |
227 | u32 id = vexpress_get_procid(VEXPRESS_SITE_MASTER); | 227 | u32 id = vexpress_get_procid(VEXPRESS_SITE_MASTER); |
228 | u32 hbi = (id >> SYS_PROCIDx_HBI_SHIFT) & SYS_HBI_MASK; | 228 | u32 hbi = (id >> SYS_PROCIDx_HBI_SHIFT) & SYS_HBI_MASK; |
229 | 229 | ||
diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig index 1a13f5b722c5..b5e0c873d4e1 100644 --- a/drivers/of/Kconfig +++ b/drivers/of/Kconfig | |||
@@ -7,8 +7,8 @@ config OF | |||
7 | menu "Device Tree and Open Firmware support" | 7 | menu "Device Tree and Open Firmware support" |
8 | depends on OF | 8 | depends on OF |
9 | 9 | ||
10 | config OF_SELFTEST | 10 | config OF_UNITTEST |
11 | bool "Device Tree Runtime self tests" | 11 | bool "Device Tree runtime unit tests" |
12 | depends on OF_IRQ && OF_EARLY_FLATTREE | 12 | depends on OF_IRQ && OF_EARLY_FLATTREE |
13 | select OF_DYNAMIC | 13 | select OF_DYNAMIC |
14 | select OF_RESOLVE | 14 | select OF_RESOLVE |
@@ -23,6 +23,7 @@ config OF_FLATTREE | |||
23 | bool | 23 | bool |
24 | select DTC | 24 | select DTC |
25 | select LIBFDT | 25 | select LIBFDT |
26 | select CRC32 | ||
26 | 27 | ||
27 | config OF_EARLY_FLATTREE | 28 | config OF_EARLY_FLATTREE |
28 | bool | 29 | bool |
@@ -83,4 +84,10 @@ config OF_RESERVED_MEM | |||
83 | config OF_RESOLVE | 84 | config OF_RESOLVE |
84 | bool | 85 | bool |
85 | 86 | ||
87 | config OF_OVERLAY | ||
88 | bool | ||
89 | depends on OF | ||
90 | select OF_DYNAMIC | ||
91 | select OF_RESOLVE | ||
92 | |||
86 | endmenu # OF | 93 | endmenu # OF |
diff --git a/drivers/of/Makefile b/drivers/of/Makefile index ca9209ce50cd..7563f36c71db 100644 --- a/drivers/of/Makefile +++ b/drivers/of/Makefile | |||
@@ -6,14 +6,15 @@ obj-$(CONFIG_OF_PROMTREE) += pdt.o | |||
6 | obj-$(CONFIG_OF_ADDRESS) += address.o | 6 | obj-$(CONFIG_OF_ADDRESS) += address.o |
7 | obj-$(CONFIG_OF_IRQ) += irq.o | 7 | obj-$(CONFIG_OF_IRQ) += irq.o |
8 | obj-$(CONFIG_OF_NET) += of_net.o | 8 | obj-$(CONFIG_OF_NET) += of_net.o |
9 | obj-$(CONFIG_OF_SELFTEST) += of_selftest.o | 9 | obj-$(CONFIG_OF_UNITTEST) += of_unittest.o |
10 | of_selftest-objs := selftest.o testcase-data/testcases.dtb.o | 10 | of_unittest-objs := unittest.o unittest-data/testcases.dtb.o |
11 | obj-$(CONFIG_OF_MDIO) += of_mdio.o | 11 | obj-$(CONFIG_OF_MDIO) += of_mdio.o |
12 | obj-$(CONFIG_OF_PCI) += of_pci.o | 12 | obj-$(CONFIG_OF_PCI) += of_pci.o |
13 | obj-$(CONFIG_OF_PCI_IRQ) += of_pci_irq.o | 13 | obj-$(CONFIG_OF_PCI_IRQ) += of_pci_irq.o |
14 | obj-$(CONFIG_OF_MTD) += of_mtd.o | 14 | obj-$(CONFIG_OF_MTD) += of_mtd.o |
15 | obj-$(CONFIG_OF_RESERVED_MEM) += of_reserved_mem.o | 15 | obj-$(CONFIG_OF_RESERVED_MEM) += of_reserved_mem.o |
16 | obj-$(CONFIG_OF_RESOLVE) += resolver.o | 16 | obj-$(CONFIG_OF_RESOLVE) += resolver.o |
17 | obj-$(CONFIG_OF_OVERLAY) += overlay.o | ||
17 | 18 | ||
18 | CFLAGS_fdt.o = -I$(src)/../../scripts/dtc/libfdt | 19 | CFLAGS_fdt.o = -I$(src)/../../scripts/dtc/libfdt |
19 | CFLAGS_fdt_address.o = -I$(src)/../../scripts/dtc/libfdt | 20 | CFLAGS_fdt_address.o = -I$(src)/../../scripts/dtc/libfdt |
diff --git a/drivers/of/address.c b/drivers/of/address.c index 06af494184d6..ad2906919d45 100644 --- a/drivers/of/address.c +++ b/drivers/of/address.c | |||
@@ -491,7 +491,7 @@ static int of_translate_one(struct device_node *parent, struct of_bus *bus, | |||
491 | */ | 491 | */ |
492 | ranges = of_get_property(parent, rprop, &rlen); | 492 | ranges = of_get_property(parent, rprop, &rlen); |
493 | if (ranges == NULL && !of_empty_ranges_quirk()) { | 493 | if (ranges == NULL && !of_empty_ranges_quirk()) { |
494 | pr_err("OF: no ranges; cannot translate\n"); | 494 | pr_debug("OF: no ranges; cannot translate\n"); |
495 | return 1; | 495 | return 1; |
496 | } | 496 | } |
497 | if (ranges == NULL || rlen == 0) { | 497 | if (ranges == NULL || rlen == 0) { |
@@ -884,7 +884,7 @@ EXPORT_SYMBOL(of_iomap); | |||
884 | * return PTR_ERR(base); | 884 | * return PTR_ERR(base); |
885 | */ | 885 | */ |
886 | void __iomem *of_io_request_and_map(struct device_node *np, int index, | 886 | void __iomem *of_io_request_and_map(struct device_node *np, int index, |
887 | char *name) | 887 | const char *name) |
888 | { | 888 | { |
889 | struct resource res; | 889 | struct resource res; |
890 | void __iomem *mem; | 890 | void __iomem *mem; |
diff --git a/drivers/of/base.c b/drivers/of/base.c index 4c2ccde42427..36536b6a8834 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c | |||
@@ -32,11 +32,12 @@ | |||
32 | 32 | ||
33 | LIST_HEAD(aliases_lookup); | 33 | LIST_HEAD(aliases_lookup); |
34 | 34 | ||
35 | struct device_node *of_allnodes; | 35 | struct device_node *of_root; |
36 | EXPORT_SYMBOL(of_allnodes); | 36 | EXPORT_SYMBOL(of_root); |
37 | struct device_node *of_chosen; | 37 | struct device_node *of_chosen; |
38 | struct device_node *of_aliases; | 38 | struct device_node *of_aliases; |
39 | struct device_node *of_stdout; | 39 | struct device_node *of_stdout; |
40 | static const char *of_stdout_options; | ||
40 | 41 | ||
41 | struct kset *of_kset; | 42 | struct kset *of_kset; |
42 | 43 | ||
@@ -48,7 +49,7 @@ struct kset *of_kset; | |||
48 | */ | 49 | */ |
49 | DEFINE_MUTEX(of_mutex); | 50 | DEFINE_MUTEX(of_mutex); |
50 | 51 | ||
51 | /* use when traversing tree through the allnext, child, sibling, | 52 | /* use when traversing tree through the child, sibling, |
52 | * or parent members of struct device_node. | 53 | * or parent members of struct device_node. |
53 | */ | 54 | */ |
54 | DEFINE_RAW_SPINLOCK(devtree_lock); | 55 | DEFINE_RAW_SPINLOCK(devtree_lock); |
@@ -204,7 +205,7 @@ static int __init of_init(void) | |||
204 | mutex_unlock(&of_mutex); | 205 | mutex_unlock(&of_mutex); |
205 | 206 | ||
206 | /* Symlink in /proc as required by userspace ABI */ | 207 | /* Symlink in /proc as required by userspace ABI */ |
207 | if (of_allnodes) | 208 | if (of_root) |
208 | proc_symlink("device-tree", NULL, "/sys/firmware/devicetree/base"); | 209 | proc_symlink("device-tree", NULL, "/sys/firmware/devicetree/base"); |
209 | 210 | ||
210 | return 0; | 211 | return 0; |
@@ -245,6 +246,23 @@ struct property *of_find_property(const struct device_node *np, | |||
245 | } | 246 | } |
246 | EXPORT_SYMBOL(of_find_property); | 247 | EXPORT_SYMBOL(of_find_property); |
247 | 248 | ||
249 | struct device_node *__of_find_all_nodes(struct device_node *prev) | ||
250 | { | ||
251 | struct device_node *np; | ||
252 | if (!prev) { | ||
253 | np = of_root; | ||
254 | } else if (prev->child) { | ||
255 | np = prev->child; | ||
256 | } else { | ||
257 | /* Walk back up looking for a sibling, or the end of the structure */ | ||
258 | np = prev; | ||
259 | while (np->parent && !np->sibling) | ||
260 | np = np->parent; | ||
261 | np = np->sibling; /* Might be null at the end of the tree */ | ||
262 | } | ||
263 | return np; | ||
264 | } | ||
265 | |||
248 | /** | 266 | /** |
249 | * of_find_all_nodes - Get next node in global list | 267 | * of_find_all_nodes - Get next node in global list |
250 | * @prev: Previous node or NULL to start iteration | 268 | * @prev: Previous node or NULL to start iteration |
@@ -259,10 +277,8 @@ struct device_node *of_find_all_nodes(struct device_node *prev) | |||
259 | unsigned long flags; | 277 | unsigned long flags; |
260 | 278 | ||
261 | raw_spin_lock_irqsave(&devtree_lock, flags); | 279 | raw_spin_lock_irqsave(&devtree_lock, flags); |
262 | np = prev ? prev->allnext : of_allnodes; | 280 | np = __of_find_all_nodes(prev); |
263 | for (; np != NULL; np = np->allnext) | 281 | of_node_get(np); |
264 | if (of_node_get(np)) | ||
265 | break; | ||
266 | of_node_put(prev); | 282 | of_node_put(prev); |
267 | raw_spin_unlock_irqrestore(&devtree_lock, flags); | 283 | raw_spin_unlock_irqrestore(&devtree_lock, flags); |
268 | return np; | 284 | return np; |
@@ -485,7 +501,7 @@ EXPORT_SYMBOL(of_device_is_compatible); | |||
485 | * of_machine_is_compatible - Test root of device tree for a given compatible value | 501 | * of_machine_is_compatible - Test root of device tree for a given compatible value |
486 | * @compat: compatible string to look for in root node's compatible property. | 502 | * @compat: compatible string to look for in root node's compatible property. |
487 | * | 503 | * |
488 | * Returns true if the root node has the given value in its | 504 | * Returns a positive integer if the root node has the given value in its |
489 | * compatible property. | 505 | * compatible property. |
490 | */ | 506 | */ |
491 | int of_machine_is_compatible(const char *compat) | 507 | int of_machine_is_compatible(const char *compat) |
@@ -507,27 +523,27 @@ EXPORT_SYMBOL(of_machine_is_compatible); | |||
507 | * | 523 | * |
508 | * @device: Node to check for availability, with locks already held | 524 | * @device: Node to check for availability, with locks already held |
509 | * | 525 | * |
510 | * Returns 1 if the status property is absent or set to "okay" or "ok", | 526 | * Returns true if the status property is absent or set to "okay" or "ok", |
511 | * 0 otherwise | 527 | * false otherwise |
512 | */ | 528 | */ |
513 | static int __of_device_is_available(const struct device_node *device) | 529 | static bool __of_device_is_available(const struct device_node *device) |
514 | { | 530 | { |
515 | const char *status; | 531 | const char *status; |
516 | int statlen; | 532 | int statlen; |
517 | 533 | ||
518 | if (!device) | 534 | if (!device) |
519 | return 0; | 535 | return false; |
520 | 536 | ||
521 | status = __of_get_property(device, "status", &statlen); | 537 | status = __of_get_property(device, "status", &statlen); |
522 | if (status == NULL) | 538 | if (status == NULL) |
523 | return 1; | 539 | return true; |
524 | 540 | ||
525 | if (statlen > 0) { | 541 | if (statlen > 0) { |
526 | if (!strcmp(status, "okay") || !strcmp(status, "ok")) | 542 | if (!strcmp(status, "okay") || !strcmp(status, "ok")) |
527 | return 1; | 543 | return true; |
528 | } | 544 | } |
529 | 545 | ||
530 | return 0; | 546 | return false; |
531 | } | 547 | } |
532 | 548 | ||
533 | /** | 549 | /** |
@@ -535,13 +551,13 @@ static int __of_device_is_available(const struct device_node *device) | |||
535 | * | 551 | * |
536 | * @device: Node to check for availability | 552 | * @device: Node to check for availability |
537 | * | 553 | * |
538 | * Returns 1 if the status property is absent or set to "okay" or "ok", | 554 | * Returns true if the status property is absent or set to "okay" or "ok", |
539 | * 0 otherwise | 555 | * false otherwise |
540 | */ | 556 | */ |
541 | int of_device_is_available(const struct device_node *device) | 557 | bool of_device_is_available(const struct device_node *device) |
542 | { | 558 | { |
543 | unsigned long flags; | 559 | unsigned long flags; |
544 | int res; | 560 | bool res; |
545 | 561 | ||
546 | raw_spin_lock_irqsave(&devtree_lock, flags); | 562 | raw_spin_lock_irqsave(&devtree_lock, flags); |
547 | res = __of_device_is_available(device); | 563 | res = __of_device_is_available(device); |
@@ -577,9 +593,9 @@ EXPORT_SYMBOL(of_get_parent); | |||
577 | * of_get_next_parent - Iterate to a node's parent | 593 | * of_get_next_parent - Iterate to a node's parent |
578 | * @node: Node to get parent of | 594 | * @node: Node to get parent of |
579 | * | 595 | * |
580 | * This is like of_get_parent() except that it drops the | 596 | * This is like of_get_parent() except that it drops the |
581 | * refcount on the passed node, making it suitable for iterating | 597 | * refcount on the passed node, making it suitable for iterating |
582 | * through a node's parents. | 598 | * through a node's parents. |
583 | * | 599 | * |
584 | * Returns a node pointer with refcount incremented, use | 600 | * Returns a node pointer with refcount incremented, use |
585 | * of_node_put() on it when done. | 601 | * of_node_put() on it when done. |
@@ -699,10 +715,15 @@ static struct device_node *__of_find_node_by_path(struct device_node *parent, | |||
699 | { | 715 | { |
700 | struct device_node *child; | 716 | struct device_node *child; |
701 | int len = strchrnul(path, '/') - path; | 717 | int len = strchrnul(path, '/') - path; |
718 | int term; | ||
702 | 719 | ||
703 | if (!len) | 720 | if (!len) |
704 | return NULL; | 721 | return NULL; |
705 | 722 | ||
723 | term = strchrnul(path, ':') - path; | ||
724 | if (term < len) | ||
725 | len = term; | ||
726 | |||
706 | __for_each_child_of_node(parent, child) { | 727 | __for_each_child_of_node(parent, child) { |
707 | const char *name = strrchr(child->full_name, '/'); | 728 | const char *name = strrchr(child->full_name, '/'); |
708 | if (WARN(!name, "malformed device_node %s\n", child->full_name)) | 729 | if (WARN(!name, "malformed device_node %s\n", child->full_name)) |
@@ -715,11 +736,14 @@ static struct device_node *__of_find_node_by_path(struct device_node *parent, | |||
715 | } | 736 | } |
716 | 737 | ||
717 | /** | 738 | /** |
718 | * of_find_node_by_path - Find a node matching a full OF path | 739 | * of_find_node_opts_by_path - Find a node matching a full OF path |
719 | * @path: Either the full path to match, or if the path does not | 740 | * @path: Either the full path to match, or if the path does not |
720 | * start with '/', the name of a property of the /aliases | 741 | * start with '/', the name of a property of the /aliases |
721 | * node (an alias). In the case of an alias, the node | 742 | * node (an alias). In the case of an alias, the node |
722 | * matching the alias' value will be returned. | 743 | * matching the alias' value will be returned. |
744 | * @opts: Address of a pointer into which to store the start of | ||
745 | * an options string appended to the end of the path with | ||
746 | * a ':' separator. | ||
723 | * | 747 | * |
724 | * Valid paths: | 748 | * Valid paths: |
725 | * /foo/bar Full path | 749 | * /foo/bar Full path |
@@ -729,19 +753,23 @@ static struct device_node *__of_find_node_by_path(struct device_node *parent, | |||
729 | * Returns a node pointer with refcount incremented, use | 753 | * Returns a node pointer with refcount incremented, use |
730 | * of_node_put() on it when done. | 754 | * of_node_put() on it when done. |
731 | */ | 755 | */ |
732 | struct device_node *of_find_node_by_path(const char *path) | 756 | struct device_node *of_find_node_opts_by_path(const char *path, const char **opts) |
733 | { | 757 | { |
734 | struct device_node *np = NULL; | 758 | struct device_node *np = NULL; |
735 | struct property *pp; | 759 | struct property *pp; |
736 | unsigned long flags; | 760 | unsigned long flags; |
761 | const char *separator = strchr(path, ':'); | ||
762 | |||
763 | if (opts) | ||
764 | *opts = separator ? separator + 1 : NULL; | ||
737 | 765 | ||
738 | if (strcmp(path, "/") == 0) | 766 | if (strcmp(path, "/") == 0) |
739 | return of_node_get(of_allnodes); | 767 | return of_node_get(of_root); |
740 | 768 | ||
741 | /* The path could begin with an alias */ | 769 | /* The path could begin with an alias */ |
742 | if (*path != '/') { | 770 | if (*path != '/') { |
743 | char *p = strchrnul(path, '/'); | 771 | char *p = strchrnul(path, '/'); |
744 | int len = p - path; | 772 | int len = separator ? separator - path : p - path; |
745 | 773 | ||
746 | /* of_aliases must not be NULL */ | 774 | /* of_aliases must not be NULL */ |
747 | if (!of_aliases) | 775 | if (!of_aliases) |
@@ -761,7 +789,7 @@ struct device_node *of_find_node_by_path(const char *path) | |||
761 | /* Step down the tree matching path components */ | 789 | /* Step down the tree matching path components */ |
762 | raw_spin_lock_irqsave(&devtree_lock, flags); | 790 | raw_spin_lock_irqsave(&devtree_lock, flags); |
763 | if (!np) | 791 | if (!np) |
764 | np = of_node_get(of_allnodes); | 792 | np = of_node_get(of_root); |
765 | while (np && *path == '/') { | 793 | while (np && *path == '/') { |
766 | path++; /* Increment past '/' delimiter */ | 794 | path++; /* Increment past '/' delimiter */ |
767 | np = __of_find_node_by_path(np, path); | 795 | np = __of_find_node_by_path(np, path); |
@@ -770,7 +798,7 @@ struct device_node *of_find_node_by_path(const char *path) | |||
770 | raw_spin_unlock_irqrestore(&devtree_lock, flags); | 798 | raw_spin_unlock_irqrestore(&devtree_lock, flags); |
771 | return np; | 799 | return np; |
772 | } | 800 | } |
773 | EXPORT_SYMBOL(of_find_node_by_path); | 801 | EXPORT_SYMBOL(of_find_node_opts_by_path); |
774 | 802 | ||
775 | /** | 803 | /** |
776 | * of_find_node_by_name - Find a node by its "name" property | 804 | * of_find_node_by_name - Find a node by its "name" property |
@@ -790,8 +818,7 @@ struct device_node *of_find_node_by_name(struct device_node *from, | |||
790 | unsigned long flags; | 818 | unsigned long flags; |
791 | 819 | ||
792 | raw_spin_lock_irqsave(&devtree_lock, flags); | 820 | raw_spin_lock_irqsave(&devtree_lock, flags); |
793 | np = from ? from->allnext : of_allnodes; | 821 | for_each_of_allnodes_from(from, np) |
794 | for (; np; np = np->allnext) | ||
795 | if (np->name && (of_node_cmp(np->name, name) == 0) | 822 | if (np->name && (of_node_cmp(np->name, name) == 0) |
796 | && of_node_get(np)) | 823 | && of_node_get(np)) |
797 | break; | 824 | break; |
@@ -820,8 +847,7 @@ struct device_node *of_find_node_by_type(struct device_node *from, | |||
820 | unsigned long flags; | 847 | unsigned long flags; |
821 | 848 | ||
822 | raw_spin_lock_irqsave(&devtree_lock, flags); | 849 | raw_spin_lock_irqsave(&devtree_lock, flags); |
823 | np = from ? from->allnext : of_allnodes; | 850 | for_each_of_allnodes_from(from, np) |
824 | for (; np; np = np->allnext) | ||
825 | if (np->type && (of_node_cmp(np->type, type) == 0) | 851 | if (np->type && (of_node_cmp(np->type, type) == 0) |
826 | && of_node_get(np)) | 852 | && of_node_get(np)) |
827 | break; | 853 | break; |
@@ -852,12 +878,10 @@ struct device_node *of_find_compatible_node(struct device_node *from, | |||
852 | unsigned long flags; | 878 | unsigned long flags; |
853 | 879 | ||
854 | raw_spin_lock_irqsave(&devtree_lock, flags); | 880 | raw_spin_lock_irqsave(&devtree_lock, flags); |
855 | np = from ? from->allnext : of_allnodes; | 881 | for_each_of_allnodes_from(from, np) |
856 | for (; np; np = np->allnext) { | ||
857 | if (__of_device_is_compatible(np, compatible, type, NULL) && | 882 | if (__of_device_is_compatible(np, compatible, type, NULL) && |
858 | of_node_get(np)) | 883 | of_node_get(np)) |
859 | break; | 884 | break; |
860 | } | ||
861 | of_node_put(from); | 885 | of_node_put(from); |
862 | raw_spin_unlock_irqrestore(&devtree_lock, flags); | 886 | raw_spin_unlock_irqrestore(&devtree_lock, flags); |
863 | return np; | 887 | return np; |
@@ -884,8 +908,7 @@ struct device_node *of_find_node_with_property(struct device_node *from, | |||
884 | unsigned long flags; | 908 | unsigned long flags; |
885 | 909 | ||
886 | raw_spin_lock_irqsave(&devtree_lock, flags); | 910 | raw_spin_lock_irqsave(&devtree_lock, flags); |
887 | np = from ? from->allnext : of_allnodes; | 911 | for_each_of_allnodes_from(from, np) { |
888 | for (; np; np = np->allnext) { | ||
889 | for (pp = np->properties; pp; pp = pp->next) { | 912 | for (pp = np->properties; pp; pp = pp->next) { |
890 | if (of_prop_cmp(pp->name, prop_name) == 0) { | 913 | if (of_prop_cmp(pp->name, prop_name) == 0) { |
891 | of_node_get(np); | 914 | of_node_get(np); |
@@ -923,7 +946,7 @@ const struct of_device_id *__of_match_node(const struct of_device_id *matches, | |||
923 | } | 946 | } |
924 | 947 | ||
925 | /** | 948 | /** |
926 | * of_match_node - Tell if an device_node has a matching of_match structure | 949 | * of_match_node - Tell if a device_node has a matching of_match structure |
927 | * @matches: array of of device match structures to search in | 950 | * @matches: array of of device match structures to search in |
928 | * @node: the of device structure to match against | 951 | * @node: the of device structure to match against |
929 | * | 952 | * |
@@ -967,8 +990,7 @@ struct device_node *of_find_matching_node_and_match(struct device_node *from, | |||
967 | *match = NULL; | 990 | *match = NULL; |
968 | 991 | ||
969 | raw_spin_lock_irqsave(&devtree_lock, flags); | 992 | raw_spin_lock_irqsave(&devtree_lock, flags); |
970 | np = from ? from->allnext : of_allnodes; | 993 | for_each_of_allnodes_from(from, np) { |
971 | for (; np; np = np->allnext) { | ||
972 | m = __of_match_node(matches, np); | 994 | m = __of_match_node(matches, np); |
973 | if (m && of_node_get(np)) { | 995 | if (m && of_node_get(np)) { |
974 | if (match) | 996 | if (match) |
@@ -1025,7 +1047,7 @@ struct device_node *of_find_node_by_phandle(phandle handle) | |||
1025 | return NULL; | 1047 | return NULL; |
1026 | 1048 | ||
1027 | raw_spin_lock_irqsave(&devtree_lock, flags); | 1049 | raw_spin_lock_irqsave(&devtree_lock, flags); |
1028 | for (np = of_allnodes; np; np = np->allnext) | 1050 | for_each_of_allnodes(np) |
1029 | if (np->phandle == handle) | 1051 | if (np->phandle == handle) |
1030 | break; | 1052 | break; |
1031 | of_node_get(np); | 1053 | of_node_get(np); |
@@ -1350,7 +1372,7 @@ int of_property_match_string(struct device_node *np, const char *propname, | |||
1350 | EXPORT_SYMBOL_GPL(of_property_match_string); | 1372 | EXPORT_SYMBOL_GPL(of_property_match_string); |
1351 | 1373 | ||
1352 | /** | 1374 | /** |
1353 | * of_property_read_string_util() - Utility helper for parsing string properties | 1375 | * of_property_read_string_helper() - Utility helper for parsing string properties |
1354 | * @np: device node from which the property value is to be read. | 1376 | * @np: device node from which the property value is to be read. |
1355 | * @propname: name of the property to be searched. | 1377 | * @propname: name of the property to be searched. |
1356 | * @out_strs: output array of string pointers. | 1378 | * @out_strs: output array of string pointers. |
@@ -1549,21 +1571,21 @@ EXPORT_SYMBOL(of_parse_phandle); | |||
1549 | * Returns 0 on success and fills out_args, on error returns appropriate | 1571 | * Returns 0 on success and fills out_args, on error returns appropriate |
1550 | * errno value. | 1572 | * errno value. |
1551 | * | 1573 | * |
1552 | * Caller is responsible to call of_node_put() on the returned out_args->node | 1574 | * Caller is responsible to call of_node_put() on the returned out_args->np |
1553 | * pointer. | 1575 | * pointer. |
1554 | * | 1576 | * |
1555 | * Example: | 1577 | * Example: |
1556 | * | 1578 | * |
1557 | * phandle1: node1 { | 1579 | * phandle1: node1 { |
1558 | * #list-cells = <2>; | 1580 | * #list-cells = <2>; |
1559 | * } | 1581 | * } |
1560 | * | 1582 | * |
1561 | * phandle2: node2 { | 1583 | * phandle2: node2 { |
1562 | * #list-cells = <1>; | 1584 | * #list-cells = <1>; |
1563 | * } | 1585 | * } |
1564 | * | 1586 | * |
1565 | * node3 { | 1587 | * node3 { |
1566 | * list = <&phandle1 1 2 &phandle2 3>; | 1588 | * list = <&phandle1 1 2 &phandle2 3>; |
1567 | * } | 1589 | * } |
1568 | * | 1590 | * |
1569 | * To get a device_node of the `node2' node you may call this: | 1591 | * To get a device_node of the `node2' node you may call this: |
@@ -1592,7 +1614,7 @@ EXPORT_SYMBOL(of_parse_phandle_with_args); | |||
1592 | * Returns 0 on success and fills out_args, on error returns appropriate | 1614 | * Returns 0 on success and fills out_args, on error returns appropriate |
1593 | * errno value. | 1615 | * errno value. |
1594 | * | 1616 | * |
1595 | * Caller is responsible to call of_node_put() on the returned out_args->node | 1617 | * Caller is responsible to call of_node_put() on the returned out_args->np |
1596 | * pointer. | 1618 | * pointer. |
1597 | * | 1619 | * |
1598 | * Example: | 1620 | * Example: |
@@ -1604,7 +1626,7 @@ EXPORT_SYMBOL(of_parse_phandle_with_args); | |||
1604 | * } | 1626 | * } |
1605 | * | 1627 | * |
1606 | * node3 { | 1628 | * node3 { |
1607 | * list = <&phandle1 0 2 &phandle2 2 3>; | 1629 | * list = <&phandle1 0 2 &phandle2 2 3>; |
1608 | * } | 1630 | * } |
1609 | * | 1631 | * |
1610 | * To get a device_node of the `node2' node you may call this: | 1632 | * To get a device_node of the `node2' node you may call this: |
@@ -1838,14 +1860,14 @@ static void of_alias_add(struct alias_prop *ap, struct device_node *np, | |||
1838 | } | 1860 | } |
1839 | 1861 | ||
1840 | /** | 1862 | /** |
1841 | * of_alias_scan - Scan all properties of 'aliases' node | 1863 | * of_alias_scan - Scan all properties of the 'aliases' node |
1842 | * | 1864 | * |
1843 | * The function scans all the properties of 'aliases' node and populate | 1865 | * The function scans all the properties of the 'aliases' node and populates |
1844 | * the the global lookup table with the properties. It returns the | 1866 | * the global lookup table with the properties. It returns the |
1845 | * number of alias_prop found, or error code in error case. | 1867 | * number of alias properties found, or an error code in case of failure. |
1846 | * | 1868 | * |
1847 | * @dt_alloc: An allocator that provides a virtual address to memory | 1869 | * @dt_alloc: An allocator that provides a virtual address to memory |
1848 | * for the resulting tree | 1870 | * for storing the resulting tree |
1849 | */ | 1871 | */ |
1850 | void of_alias_scan(void * (*dt_alloc)(u64 size, u64 align)) | 1872 | void of_alias_scan(void * (*dt_alloc)(u64 size, u64 align)) |
1851 | { | 1873 | { |
@@ -1864,7 +1886,7 @@ void of_alias_scan(void * (*dt_alloc)(u64 size, u64 align)) | |||
1864 | if (IS_ENABLED(CONFIG_PPC) && !name) | 1886 | if (IS_ENABLED(CONFIG_PPC) && !name) |
1865 | name = of_get_property(of_aliases, "stdout", NULL); | 1887 | name = of_get_property(of_aliases, "stdout", NULL); |
1866 | if (name) | 1888 | if (name) |
1867 | of_stdout = of_find_node_by_path(name); | 1889 | of_stdout = of_find_node_opts_by_path(name, &of_stdout_options); |
1868 | } | 1890 | } |
1869 | 1891 | ||
1870 | if (!of_aliases) | 1892 | if (!of_aliases) |
@@ -1990,7 +2012,8 @@ bool of_console_check(struct device_node *dn, char *name, int index) | |||
1990 | { | 2012 | { |
1991 | if (!dn || dn != of_stdout || console_set_on_cmdline) | 2013 | if (!dn || dn != of_stdout || console_set_on_cmdline) |
1992 | return false; | 2014 | return false; |
1993 | return !add_preferred_console(name, index, NULL); | 2015 | return !add_preferred_console(name, index, |
2016 | kstrdup(of_stdout_options, GFP_KERNEL)); | ||
1994 | } | 2017 | } |
1995 | EXPORT_SYMBOL_GPL(of_console_check); | 2018 | EXPORT_SYMBOL_GPL(of_console_check); |
1996 | 2019 | ||
diff --git a/drivers/of/dynamic.c b/drivers/of/dynamic.c index d4994177dec2..3351ef408125 100644 --- a/drivers/of/dynamic.c +++ b/drivers/of/dynamic.c | |||
@@ -77,18 +77,132 @@ int of_reconfig_notifier_unregister(struct notifier_block *nb) | |||
77 | } | 77 | } |
78 | EXPORT_SYMBOL_GPL(of_reconfig_notifier_unregister); | 78 | EXPORT_SYMBOL_GPL(of_reconfig_notifier_unregister); |
79 | 79 | ||
80 | int of_reconfig_notify(unsigned long action, void *p) | 80 | #ifdef DEBUG |
81 | const char *action_names[] = { | ||
82 | [OF_RECONFIG_ATTACH_NODE] = "ATTACH_NODE", | ||
83 | [OF_RECONFIG_DETACH_NODE] = "DETACH_NODE", | ||
84 | [OF_RECONFIG_ADD_PROPERTY] = "ADD_PROPERTY", | ||
85 | [OF_RECONFIG_REMOVE_PROPERTY] = "REMOVE_PROPERTY", | ||
86 | [OF_RECONFIG_UPDATE_PROPERTY] = "UPDATE_PROPERTY", | ||
87 | }; | ||
88 | #endif | ||
89 | |||
90 | int of_reconfig_notify(unsigned long action, struct of_reconfig_data *p) | ||
81 | { | 91 | { |
82 | int rc; | 92 | int rc; |
93 | #ifdef DEBUG | ||
94 | struct of_reconfig_data *pr = p; | ||
95 | |||
96 | switch (action) { | ||
97 | case OF_RECONFIG_ATTACH_NODE: | ||
98 | case OF_RECONFIG_DETACH_NODE: | ||
99 | pr_debug("of/notify %-15s %s\n", action_names[action], | ||
100 | pr->dn->full_name); | ||
101 | break; | ||
102 | case OF_RECONFIG_ADD_PROPERTY: | ||
103 | case OF_RECONFIG_REMOVE_PROPERTY: | ||
104 | case OF_RECONFIG_UPDATE_PROPERTY: | ||
105 | pr_debug("of/notify %-15s %s:%s\n", action_names[action], | ||
106 | pr->dn->full_name, pr->prop->name); | ||
107 | break; | ||
83 | 108 | ||
109 | } | ||
110 | #endif | ||
84 | rc = blocking_notifier_call_chain(&of_reconfig_chain, action, p); | 111 | rc = blocking_notifier_call_chain(&of_reconfig_chain, action, p); |
85 | return notifier_to_errno(rc); | 112 | return notifier_to_errno(rc); |
86 | } | 113 | } |
87 | 114 | ||
115 | /* | ||
116 | * of_reconfig_get_state_change() - Returns new state of device | ||
117 | * @action - action of the of notifier | ||
118 | * @arg - argument of the of notifier | ||
119 | * | ||
120 | * Returns the new state of a device based on the notifier used. | ||
121 | * Returns 0 on device going from enabled to disabled, 1 on device | ||
122 | * going from disabled to enabled and -1 on no change. | ||
123 | */ | ||
124 | int of_reconfig_get_state_change(unsigned long action, struct of_reconfig_data *pr) | ||
125 | { | ||
126 | struct property *prop, *old_prop = NULL; | ||
127 | int is_status, status_state, old_status_state, prev_state, new_state; | ||
128 | |||
129 | /* figure out if a device should be created or destroyed */ | ||
130 | switch (action) { | ||
131 | case OF_RECONFIG_ATTACH_NODE: | ||
132 | case OF_RECONFIG_DETACH_NODE: | ||
133 | prop = of_find_property(pr->dn, "status", NULL); | ||
134 | break; | ||
135 | case OF_RECONFIG_ADD_PROPERTY: | ||
136 | case OF_RECONFIG_REMOVE_PROPERTY: | ||
137 | prop = pr->prop; | ||
138 | break; | ||
139 | case OF_RECONFIG_UPDATE_PROPERTY: | ||
140 | prop = pr->prop; | ||
141 | old_prop = pr->old_prop; | ||
142 | break; | ||
143 | default: | ||
144 | return OF_RECONFIG_NO_CHANGE; | ||
145 | } | ||
146 | |||
147 | is_status = 0; | ||
148 | status_state = -1; | ||
149 | old_status_state = -1; | ||
150 | prev_state = -1; | ||
151 | new_state = -1; | ||
152 | |||
153 | if (prop && !strcmp(prop->name, "status")) { | ||
154 | is_status = 1; | ||
155 | status_state = !strcmp(prop->value, "okay") || | ||
156 | !strcmp(prop->value, "ok"); | ||
157 | if (old_prop) | ||
158 | old_status_state = !strcmp(old_prop->value, "okay") || | ||
159 | !strcmp(old_prop->value, "ok"); | ||
160 | } | ||
161 | |||
162 | switch (action) { | ||
163 | case OF_RECONFIG_ATTACH_NODE: | ||
164 | prev_state = 0; | ||
165 | /* -1 & 0 status either missing or okay */ | ||
166 | new_state = status_state != 0; | ||
167 | break; | ||
168 | case OF_RECONFIG_DETACH_NODE: | ||
169 | /* -1 & 0 status either missing or okay */ | ||
170 | prev_state = status_state != 0; | ||
171 | new_state = 0; | ||
172 | break; | ||
173 | case OF_RECONFIG_ADD_PROPERTY: | ||
174 | if (is_status) { | ||
175 | /* no status property -> enabled (legacy) */ | ||
176 | prev_state = 1; | ||
177 | new_state = status_state; | ||
178 | } | ||
179 | break; | ||
180 | case OF_RECONFIG_REMOVE_PROPERTY: | ||
181 | if (is_status) { | ||
182 | prev_state = status_state; | ||
183 | /* no status property -> enabled (legacy) */ | ||
184 | new_state = 1; | ||
185 | } | ||
186 | break; | ||
187 | case OF_RECONFIG_UPDATE_PROPERTY: | ||
188 | if (is_status) { | ||
189 | prev_state = old_status_state != 0; | ||
190 | new_state = status_state != 0; | ||
191 | } | ||
192 | break; | ||
193 | } | ||
194 | |||
195 | if (prev_state == new_state) | ||
196 | return OF_RECONFIG_NO_CHANGE; | ||
197 | |||
198 | return new_state ? OF_RECONFIG_CHANGE_ADD : OF_RECONFIG_CHANGE_REMOVE; | ||
199 | } | ||
200 | EXPORT_SYMBOL_GPL(of_reconfig_get_state_change); | ||
201 | |||
88 | int of_property_notify(int action, struct device_node *np, | 202 | int of_property_notify(int action, struct device_node *np, |
89 | struct property *prop, struct property *oldprop) | 203 | struct property *prop, struct property *oldprop) |
90 | { | 204 | { |
91 | struct of_prop_reconfig pr; | 205 | struct of_reconfig_data pr; |
92 | 206 | ||
93 | /* only call notifiers if the node is attached */ | 207 | /* only call notifiers if the node is attached */ |
94 | if (!of_node_is_attached(np)) | 208 | if (!of_node_is_attached(np)) |
@@ -117,8 +231,6 @@ void __of_attach_node(struct device_node *np) | |||
117 | 231 | ||
118 | np->child = NULL; | 232 | np->child = NULL; |
119 | np->sibling = np->parent->child; | 233 | np->sibling = np->parent->child; |
120 | np->allnext = np->parent->allnext; | ||
121 | np->parent->allnext = np; | ||
122 | np->parent->child = np; | 234 | np->parent->child = np; |
123 | of_node_clear_flag(np, OF_DETACHED); | 235 | of_node_clear_flag(np, OF_DETACHED); |
124 | } | 236 | } |
@@ -128,8 +240,12 @@ void __of_attach_node(struct device_node *np) | |||
128 | */ | 240 | */ |
129 | int of_attach_node(struct device_node *np) | 241 | int of_attach_node(struct device_node *np) |
130 | { | 242 | { |
243 | struct of_reconfig_data rd; | ||
131 | unsigned long flags; | 244 | unsigned long flags; |
132 | 245 | ||
246 | memset(&rd, 0, sizeof(rd)); | ||
247 | rd.dn = np; | ||
248 | |||
133 | mutex_lock(&of_mutex); | 249 | mutex_lock(&of_mutex); |
134 | raw_spin_lock_irqsave(&devtree_lock, flags); | 250 | raw_spin_lock_irqsave(&devtree_lock, flags); |
135 | __of_attach_node(np); | 251 | __of_attach_node(np); |
@@ -138,7 +254,7 @@ int of_attach_node(struct device_node *np) | |||
138 | __of_attach_node_sysfs(np); | 254 | __of_attach_node_sysfs(np); |
139 | mutex_unlock(&of_mutex); | 255 | mutex_unlock(&of_mutex); |
140 | 256 | ||
141 | of_reconfig_notify(OF_RECONFIG_ATTACH_NODE, np); | 257 | of_reconfig_notify(OF_RECONFIG_ATTACH_NODE, &rd); |
142 | 258 | ||
143 | return 0; | 259 | return 0; |
144 | } | 260 | } |
@@ -154,17 +270,6 @@ void __of_detach_node(struct device_node *np) | |||
154 | if (WARN_ON(!parent)) | 270 | if (WARN_ON(!parent)) |
155 | return; | 271 | return; |
156 | 272 | ||
157 | if (of_allnodes == np) | ||
158 | of_allnodes = np->allnext; | ||
159 | else { | ||
160 | struct device_node *prev; | ||
161 | for (prev = of_allnodes; | ||
162 | prev->allnext != np; | ||
163 | prev = prev->allnext) | ||
164 | ; | ||
165 | prev->allnext = np->allnext; | ||
166 | } | ||
167 | |||
168 | if (parent->child == np) | 273 | if (parent->child == np) |
169 | parent->child = np->sibling; | 274 | parent->child = np->sibling; |
170 | else { | 275 | else { |
@@ -187,9 +292,13 @@ void __of_detach_node(struct device_node *np) | |||
187 | */ | 292 | */ |
188 | int of_detach_node(struct device_node *np) | 293 | int of_detach_node(struct device_node *np) |
189 | { | 294 | { |
295 | struct of_reconfig_data rd; | ||
190 | unsigned long flags; | 296 | unsigned long flags; |
191 | int rc = 0; | 297 | int rc = 0; |
192 | 298 | ||
299 | memset(&rd, 0, sizeof(rd)); | ||
300 | rd.dn = np; | ||
301 | |||
193 | mutex_lock(&of_mutex); | 302 | mutex_lock(&of_mutex); |
194 | raw_spin_lock_irqsave(&devtree_lock, flags); | 303 | raw_spin_lock_irqsave(&devtree_lock, flags); |
195 | __of_detach_node(np); | 304 | __of_detach_node(np); |
@@ -198,7 +307,7 @@ int of_detach_node(struct device_node *np) | |||
198 | __of_detach_node_sysfs(np); | 307 | __of_detach_node_sysfs(np); |
199 | mutex_unlock(&of_mutex); | 308 | mutex_unlock(&of_mutex); |
200 | 309 | ||
201 | of_reconfig_notify(OF_RECONFIG_DETACH_NODE, np); | 310 | of_reconfig_notify(OF_RECONFIG_DETACH_NODE, &rd); |
202 | 311 | ||
203 | return rc; | 312 | return rc; |
204 | } | 313 | } |
@@ -285,36 +394,54 @@ struct property *__of_prop_dup(const struct property *prop, gfp_t allocflags) | |||
285 | } | 394 | } |
286 | 395 | ||
287 | /** | 396 | /** |
288 | * __of_node_alloc() - Create an empty device node dynamically. | 397 | * __of_node_dup() - Duplicate or create an empty device node dynamically. |
289 | * @full_name: Full name of the new device node | 398 | * @fmt: Format string (plus vargs) for new full name of the device node |
290 | * @allocflags: Allocation flags (typically pass GFP_KERNEL) | ||
291 | * | 399 | * |
292 | * Create an empty device tree node, suitable for further modification. | 400 | * Create an device tree node, either by duplicating an empty node or by allocating |
293 | * The node data are dynamically allocated and all the node flags | 401 | * an empty one suitable for further modification. The node data are |
294 | * have the OF_DYNAMIC & OF_DETACHED bits set. | 402 | * dynamically allocated and all the node flags have the OF_DYNAMIC & |
295 | * Returns the newly allocated node or NULL on out of memory error. | 403 | * OF_DETACHED bits set. Returns the newly allocated node or NULL on out of |
404 | * memory error. | ||
296 | */ | 405 | */ |
297 | struct device_node *__of_node_alloc(const char *full_name, gfp_t allocflags) | 406 | struct device_node *__of_node_dup(const struct device_node *np, const char *fmt, ...) |
298 | { | 407 | { |
408 | va_list vargs; | ||
299 | struct device_node *node; | 409 | struct device_node *node; |
300 | 410 | ||
301 | node = kzalloc(sizeof(*node), allocflags); | 411 | node = kzalloc(sizeof(*node), GFP_KERNEL); |
302 | if (!node) | 412 | if (!node) |
303 | return NULL; | 413 | return NULL; |
414 | va_start(vargs, fmt); | ||
415 | node->full_name = kvasprintf(GFP_KERNEL, fmt, vargs); | ||
416 | va_end(vargs); | ||
417 | if (!node->full_name) { | ||
418 | kfree(node); | ||
419 | return NULL; | ||
420 | } | ||
304 | 421 | ||
305 | node->full_name = kstrdup(full_name, allocflags); | ||
306 | of_node_set_flag(node, OF_DYNAMIC); | 422 | of_node_set_flag(node, OF_DYNAMIC); |
307 | of_node_set_flag(node, OF_DETACHED); | 423 | of_node_set_flag(node, OF_DETACHED); |
308 | if (!node->full_name) | ||
309 | goto err_free; | ||
310 | |||
311 | of_node_init(node); | 424 | of_node_init(node); |
312 | 425 | ||
426 | /* Iterate over and duplicate all properties */ | ||
427 | if (np) { | ||
428 | struct property *pp, *new_pp; | ||
429 | for_each_property_of_node(np, pp) { | ||
430 | new_pp = __of_prop_dup(pp, GFP_KERNEL); | ||
431 | if (!new_pp) | ||
432 | goto err_prop; | ||
433 | if (__of_add_property(node, new_pp)) { | ||
434 | kfree(new_pp->name); | ||
435 | kfree(new_pp->value); | ||
436 | kfree(new_pp); | ||
437 | goto err_prop; | ||
438 | } | ||
439 | } | ||
440 | } | ||
313 | return node; | 441 | return node; |
314 | 442 | ||
315 | err_free: | 443 | err_prop: |
316 | kfree(node->full_name); | 444 | of_node_put(node); /* Frees the node and properties */ |
317 | kfree(node); | ||
318 | return NULL; | 445 | return NULL; |
319 | } | 446 | } |
320 | 447 | ||
@@ -330,27 +457,15 @@ static void __of_changeset_entry_dump(struct of_changeset_entry *ce) | |||
330 | { | 457 | { |
331 | switch (ce->action) { | 458 | switch (ce->action) { |
332 | case OF_RECONFIG_ADD_PROPERTY: | 459 | case OF_RECONFIG_ADD_PROPERTY: |
333 | pr_debug("%p: %s %s/%s\n", | ||
334 | ce, "ADD_PROPERTY ", ce->np->full_name, | ||
335 | ce->prop->name); | ||
336 | break; | ||
337 | case OF_RECONFIG_REMOVE_PROPERTY: | 460 | case OF_RECONFIG_REMOVE_PROPERTY: |
338 | pr_debug("%p: %s %s/%s\n", | ||
339 | ce, "REMOVE_PROPERTY", ce->np->full_name, | ||
340 | ce->prop->name); | ||
341 | break; | ||
342 | case OF_RECONFIG_UPDATE_PROPERTY: | 461 | case OF_RECONFIG_UPDATE_PROPERTY: |
343 | pr_debug("%p: %s %s/%s\n", | 462 | pr_debug("of/cset<%p> %-15s %s/%s\n", ce, action_names[ce->action], |
344 | ce, "UPDATE_PROPERTY", ce->np->full_name, | 463 | ce->np->full_name, ce->prop->name); |
345 | ce->prop->name); | ||
346 | break; | 464 | break; |
347 | case OF_RECONFIG_ATTACH_NODE: | 465 | case OF_RECONFIG_ATTACH_NODE: |
348 | pr_debug("%p: %s %s\n", | ||
349 | ce, "ATTACH_NODE ", ce->np->full_name); | ||
350 | break; | ||
351 | case OF_RECONFIG_DETACH_NODE: | 466 | case OF_RECONFIG_DETACH_NODE: |
352 | pr_debug("%p: %s %s\n", | 467 | pr_debug("of/cset<%p> %-15s %s\n", ce, action_names[ce->action], |
353 | ce, "DETACH_NODE ", ce->np->full_name); | 468 | ce->np->full_name); |
354 | break; | 469 | break; |
355 | } | 470 | } |
356 | } | 471 | } |
@@ -388,6 +503,7 @@ static void __of_changeset_entry_invert(struct of_changeset_entry *ce, | |||
388 | 503 | ||
389 | static void __of_changeset_entry_notify(struct of_changeset_entry *ce, bool revert) | 504 | static void __of_changeset_entry_notify(struct of_changeset_entry *ce, bool revert) |
390 | { | 505 | { |
506 | struct of_reconfig_data rd; | ||
391 | struct of_changeset_entry ce_inverted; | 507 | struct of_changeset_entry ce_inverted; |
392 | int ret; | 508 | int ret; |
393 | 509 | ||
@@ -399,7 +515,9 @@ static void __of_changeset_entry_notify(struct of_changeset_entry *ce, bool reve | |||
399 | switch (ce->action) { | 515 | switch (ce->action) { |
400 | case OF_RECONFIG_ATTACH_NODE: | 516 | case OF_RECONFIG_ATTACH_NODE: |
401 | case OF_RECONFIG_DETACH_NODE: | 517 | case OF_RECONFIG_DETACH_NODE: |
402 | ret = of_reconfig_notify(ce->action, ce->np); | 518 | memset(&rd, 0, sizeof(rd)); |
519 | rd.dn = ce->np; | ||
520 | ret = of_reconfig_notify(ce->action, &rd); | ||
403 | break; | 521 | break; |
404 | case OF_RECONFIG_ADD_PROPERTY: | 522 | case OF_RECONFIG_ADD_PROPERTY: |
405 | case OF_RECONFIG_REMOVE_PROPERTY: | 523 | case OF_RECONFIG_REMOVE_PROPERTY: |
diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index d134710de96d..510074226d57 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c | |||
@@ -9,6 +9,7 @@ | |||
9 | * version 2 as published by the Free Software Foundation. | 9 | * version 2 as published by the Free Software Foundation. |
10 | */ | 10 | */ |
11 | 11 | ||
12 | #include <linux/crc32.h> | ||
12 | #include <linux/kernel.h> | 13 | #include <linux/kernel.h> |
13 | #include <linux/initrd.h> | 14 | #include <linux/initrd.h> |
14 | #include <linux/memblock.h> | 15 | #include <linux/memblock.h> |
@@ -22,6 +23,7 @@ | |||
22 | #include <linux/libfdt.h> | 23 | #include <linux/libfdt.h> |
23 | #include <linux/debugfs.h> | 24 | #include <linux/debugfs.h> |
24 | #include <linux/serial_core.h> | 25 | #include <linux/serial_core.h> |
26 | #include <linux/sysfs.h> | ||
25 | 27 | ||
26 | #include <asm/setup.h> /* for COMMAND_LINE_SIZE */ | 28 | #include <asm/setup.h> /* for COMMAND_LINE_SIZE */ |
27 | #include <asm/page.h> | 29 | #include <asm/page.h> |
@@ -145,15 +147,15 @@ static void *unflatten_dt_alloc(void **mem, unsigned long size, | |||
145 | * @mem: Memory chunk to use for allocating device nodes and properties | 147 | * @mem: Memory chunk to use for allocating device nodes and properties |
146 | * @p: pointer to node in flat tree | 148 | * @p: pointer to node in flat tree |
147 | * @dad: Parent struct device_node | 149 | * @dad: Parent struct device_node |
148 | * @allnextpp: pointer to ->allnext from last allocated device_node | ||
149 | * @fpsize: Size of the node path up at the current depth. | 150 | * @fpsize: Size of the node path up at the current depth. |
150 | */ | 151 | */ |
151 | static void * unflatten_dt_node(void *blob, | 152 | static void * unflatten_dt_node(void *blob, |
152 | void *mem, | 153 | void *mem, |
153 | int *poffset, | 154 | int *poffset, |
154 | struct device_node *dad, | 155 | struct device_node *dad, |
155 | struct device_node ***allnextpp, | 156 | struct device_node **nodepp, |
156 | unsigned long fpsize) | 157 | unsigned long fpsize, |
158 | bool dryrun) | ||
157 | { | 159 | { |
158 | const __be32 *p; | 160 | const __be32 *p; |
159 | struct device_node *np; | 161 | struct device_node *np; |
@@ -200,7 +202,7 @@ static void * unflatten_dt_node(void *blob, | |||
200 | 202 | ||
201 | np = unflatten_dt_alloc(&mem, sizeof(struct device_node) + allocl, | 203 | np = unflatten_dt_alloc(&mem, sizeof(struct device_node) + allocl, |
202 | __alignof__(struct device_node)); | 204 | __alignof__(struct device_node)); |
203 | if (allnextpp) { | 205 | if (!dryrun) { |
204 | char *fn; | 206 | char *fn; |
205 | of_node_init(np); | 207 | of_node_init(np); |
206 | np->full_name = fn = ((char *)np) + sizeof(*np); | 208 | np->full_name = fn = ((char *)np) + sizeof(*np); |
@@ -222,16 +224,10 @@ static void * unflatten_dt_node(void *blob, | |||
222 | memcpy(fn, pathp, l); | 224 | memcpy(fn, pathp, l); |
223 | 225 | ||
224 | prev_pp = &np->properties; | 226 | prev_pp = &np->properties; |
225 | **allnextpp = np; | ||
226 | *allnextpp = &np->allnext; | ||
227 | if (dad != NULL) { | 227 | if (dad != NULL) { |
228 | np->parent = dad; | 228 | np->parent = dad; |
229 | /* we temporarily use the next field as `last_child'*/ | 229 | np->sibling = dad->child; |
230 | if (dad->next == NULL) | 230 | dad->child = np; |
231 | dad->child = np; | ||
232 | else | ||
233 | dad->next->sibling = np; | ||
234 | dad->next = np; | ||
235 | } | 231 | } |
236 | } | 232 | } |
237 | /* process properties */ | 233 | /* process properties */ |
@@ -254,7 +250,7 @@ static void * unflatten_dt_node(void *blob, | |||
254 | has_name = 1; | 250 | has_name = 1; |
255 | pp = unflatten_dt_alloc(&mem, sizeof(struct property), | 251 | pp = unflatten_dt_alloc(&mem, sizeof(struct property), |
256 | __alignof__(struct property)); | 252 | __alignof__(struct property)); |
257 | if (allnextpp) { | 253 | if (!dryrun) { |
258 | /* We accept flattened tree phandles either in | 254 | /* We accept flattened tree phandles either in |
259 | * ePAPR-style "phandle" properties, or the | 255 | * ePAPR-style "phandle" properties, or the |
260 | * legacy "linux,phandle" properties. If both | 256 | * legacy "linux,phandle" properties. If both |
@@ -296,7 +292,7 @@ static void * unflatten_dt_node(void *blob, | |||
296 | sz = (pa - ps) + 1; | 292 | sz = (pa - ps) + 1; |
297 | pp = unflatten_dt_alloc(&mem, sizeof(struct property) + sz, | 293 | pp = unflatten_dt_alloc(&mem, sizeof(struct property) + sz, |
298 | __alignof__(struct property)); | 294 | __alignof__(struct property)); |
299 | if (allnextpp) { | 295 | if (!dryrun) { |
300 | pp->name = "name"; | 296 | pp->name = "name"; |
301 | pp->length = sz; | 297 | pp->length = sz; |
302 | pp->value = pp + 1; | 298 | pp->value = pp + 1; |
@@ -308,7 +304,7 @@ static void * unflatten_dt_node(void *blob, | |||
308 | (char *)pp->value); | 304 | (char *)pp->value); |
309 | } | 305 | } |
310 | } | 306 | } |
311 | if (allnextpp) { | 307 | if (!dryrun) { |
312 | *prev_pp = NULL; | 308 | *prev_pp = NULL; |
313 | np->name = of_get_property(np, "name", NULL); | 309 | np->name = of_get_property(np, "name", NULL); |
314 | np->type = of_get_property(np, "device_type", NULL); | 310 | np->type = of_get_property(np, "device_type", NULL); |
@@ -324,12 +320,30 @@ static void * unflatten_dt_node(void *blob, | |||
324 | if (depth < 0) | 320 | if (depth < 0) |
325 | depth = 0; | 321 | depth = 0; |
326 | while (*poffset > 0 && depth > old_depth) | 322 | while (*poffset > 0 && depth > old_depth) |
327 | mem = unflatten_dt_node(blob, mem, poffset, np, allnextpp, | 323 | mem = unflatten_dt_node(blob, mem, poffset, np, NULL, |
328 | fpsize); | 324 | fpsize, dryrun); |
329 | 325 | ||
330 | if (*poffset < 0 && *poffset != -FDT_ERR_NOTFOUND) | 326 | if (*poffset < 0 && *poffset != -FDT_ERR_NOTFOUND) |
331 | pr_err("unflatten: error %d processing FDT\n", *poffset); | 327 | pr_err("unflatten: error %d processing FDT\n", *poffset); |
332 | 328 | ||
329 | /* | ||
330 | * Reverse the child list. Some drivers assumes node order matches .dts | ||
331 | * node order | ||
332 | */ | ||
333 | if (!dryrun && np->child) { | ||
334 | struct device_node *child = np->child; | ||
335 | np->child = NULL; | ||
336 | while (child) { | ||
337 | struct device_node *next = child->sibling; | ||
338 | child->sibling = np->child; | ||
339 | np->child = child; | ||
340 | child = next; | ||
341 | } | ||
342 | } | ||
343 | |||
344 | if (nodepp) | ||
345 | *nodepp = np; | ||
346 | |||
333 | return mem; | 347 | return mem; |
334 | } | 348 | } |
335 | 349 | ||
@@ -352,7 +366,6 @@ static void __unflatten_device_tree(void *blob, | |||
352 | unsigned long size; | 366 | unsigned long size; |
353 | int start; | 367 | int start; |
354 | void *mem; | 368 | void *mem; |
355 | struct device_node **allnextp = mynodes; | ||
356 | 369 | ||
357 | pr_debug(" -> unflatten_device_tree()\n"); | 370 | pr_debug(" -> unflatten_device_tree()\n"); |
358 | 371 | ||
@@ -373,7 +386,7 @@ static void __unflatten_device_tree(void *blob, | |||
373 | 386 | ||
374 | /* First pass, scan for size */ | 387 | /* First pass, scan for size */ |
375 | start = 0; | 388 | start = 0; |
376 | size = (unsigned long)unflatten_dt_node(blob, NULL, &start, NULL, NULL, 0); | 389 | size = (unsigned long)unflatten_dt_node(blob, NULL, &start, NULL, NULL, 0, true); |
377 | size = ALIGN(size, 4); | 390 | size = ALIGN(size, 4); |
378 | 391 | ||
379 | pr_debug(" size is %lx, allocating...\n", size); | 392 | pr_debug(" size is %lx, allocating...\n", size); |
@@ -388,11 +401,10 @@ static void __unflatten_device_tree(void *blob, | |||
388 | 401 | ||
389 | /* Second pass, do actual unflattening */ | 402 | /* Second pass, do actual unflattening */ |
390 | start = 0; | 403 | start = 0; |
391 | unflatten_dt_node(blob, mem, &start, NULL, &allnextp, 0); | 404 | unflatten_dt_node(blob, mem, &start, NULL, mynodes, 0, false); |
392 | if (be32_to_cpup(mem + size) != 0xdeadbeef) | 405 | if (be32_to_cpup(mem + size) != 0xdeadbeef) |
393 | pr_warning("End of tree marker overwritten: %08x\n", | 406 | pr_warning("End of tree marker overwritten: %08x\n", |
394 | be32_to_cpup(mem + size)); | 407 | be32_to_cpup(mem + size)); |
395 | *allnextp = NULL; | ||
396 | 408 | ||
397 | pr_debug(" <- unflatten_device_tree()\n"); | 409 | pr_debug(" <- unflatten_device_tree()\n"); |
398 | } | 410 | } |
@@ -425,6 +437,8 @@ void *initial_boot_params; | |||
425 | 437 | ||
426 | #ifdef CONFIG_OF_EARLY_FLATTREE | 438 | #ifdef CONFIG_OF_EARLY_FLATTREE |
427 | 439 | ||
440 | static u32 of_fdt_crc32; | ||
441 | |||
428 | /** | 442 | /** |
429 | * res_mem_reserve_reg() - reserve all memory described in 'reg' property | 443 | * res_mem_reserve_reg() - reserve all memory described in 'reg' property |
430 | */ | 444 | */ |
@@ -930,6 +944,11 @@ void __init __weak early_init_dt_add_memory_arch(u64 base, u64 size) | |||
930 | const u64 phys_offset = __pa(PAGE_OFFSET); | 944 | const u64 phys_offset = __pa(PAGE_OFFSET); |
931 | 945 | ||
932 | if (!PAGE_ALIGNED(base)) { | 946 | if (!PAGE_ALIGNED(base)) { |
947 | if (size < PAGE_SIZE - (base & ~PAGE_MASK)) { | ||
948 | pr_warn("Ignoring memory block 0x%llx - 0x%llx\n", | ||
949 | base, base + size); | ||
950 | return; | ||
951 | } | ||
933 | size -= PAGE_SIZE - (base & ~PAGE_MASK); | 952 | size -= PAGE_SIZE - (base & ~PAGE_MASK); |
934 | base = PAGE_ALIGN(base); | 953 | base = PAGE_ALIGN(base); |
935 | } | 954 | } |
@@ -992,15 +1011,14 @@ bool __init early_init_dt_verify(void *params) | |||
992 | if (!params) | 1011 | if (!params) |
993 | return false; | 1012 | return false; |
994 | 1013 | ||
995 | /* Setup flat device-tree pointer */ | ||
996 | initial_boot_params = params; | ||
997 | |||
998 | /* check device tree validity */ | 1014 | /* check device tree validity */ |
999 | if (fdt_check_header(params)) { | 1015 | if (fdt_check_header(params)) |
1000 | initial_boot_params = NULL; | ||
1001 | return false; | 1016 | return false; |
1002 | } | ||
1003 | 1017 | ||
1018 | /* Setup flat device-tree pointer */ | ||
1019 | initial_boot_params = params; | ||
1020 | of_fdt_crc32 = crc32_be(~0, initial_boot_params, | ||
1021 | fdt_totalsize(initial_boot_params)); | ||
1004 | return true; | 1022 | return true; |
1005 | } | 1023 | } |
1006 | 1024 | ||
@@ -1039,7 +1057,7 @@ bool __init early_init_dt_scan(void *params) | |||
1039 | */ | 1057 | */ |
1040 | void __init unflatten_device_tree(void) | 1058 | void __init unflatten_device_tree(void) |
1041 | { | 1059 | { |
1042 | __unflatten_device_tree(initial_boot_params, &of_allnodes, | 1060 | __unflatten_device_tree(initial_boot_params, &of_root, |
1043 | early_init_dt_alloc_memory_arch); | 1061 | early_init_dt_alloc_memory_arch); |
1044 | 1062 | ||
1045 | /* Get pointer to "/chosen" and "/aliases" nodes for use everywhere */ | 1063 | /* Get pointer to "/chosen" and "/aliases" nodes for use everywhere */ |
@@ -1078,27 +1096,32 @@ void __init unflatten_and_copy_device_tree(void) | |||
1078 | unflatten_device_tree(); | 1096 | unflatten_device_tree(); |
1079 | } | 1097 | } |
1080 | 1098 | ||
1081 | #if defined(CONFIG_DEBUG_FS) && defined(DEBUG) | 1099 | #ifdef CONFIG_SYSFS |
1082 | static struct debugfs_blob_wrapper flat_dt_blob; | 1100 | static ssize_t of_fdt_raw_read(struct file *filp, struct kobject *kobj, |
1083 | 1101 | struct bin_attribute *bin_attr, | |
1084 | static int __init of_flat_dt_debugfs_export_fdt(void) | 1102 | char *buf, loff_t off, size_t count) |
1085 | { | 1103 | { |
1086 | struct dentry *d = debugfs_create_dir("device-tree", NULL); | 1104 | memcpy(buf, initial_boot_params + off, count); |
1087 | 1105 | return count; | |
1088 | if (!d) | 1106 | } |
1089 | return -ENOENT; | ||
1090 | 1107 | ||
1091 | flat_dt_blob.data = initial_boot_params; | 1108 | static int __init of_fdt_raw_init(void) |
1092 | flat_dt_blob.size = fdt_totalsize(initial_boot_params); | 1109 | { |
1110 | static struct bin_attribute of_fdt_raw_attr = | ||
1111 | __BIN_ATTR(fdt, S_IRUSR, of_fdt_raw_read, NULL, 0); | ||
1093 | 1112 | ||
1094 | d = debugfs_create_blob("flat-device-tree", S_IFREG | S_IRUSR, | 1113 | if (!initial_boot_params) |
1095 | d, &flat_dt_blob); | 1114 | return 0; |
1096 | if (!d) | ||
1097 | return -ENOENT; | ||
1098 | 1115 | ||
1099 | return 0; | 1116 | if (of_fdt_crc32 != crc32_be(~0, initial_boot_params, |
1117 | fdt_totalsize(initial_boot_params))) { | ||
1118 | pr_warn("fdt: not creating '/sys/firmware/fdt': CRC check failed\n"); | ||
1119 | return 0; | ||
1120 | } | ||
1121 | of_fdt_raw_attr.size = fdt_totalsize(initial_boot_params); | ||
1122 | return sysfs_create_bin_file(firmware_kobj, &of_fdt_raw_attr); | ||
1100 | } | 1123 | } |
1101 | module_init(of_flat_dt_debugfs_export_fdt); | 1124 | late_initcall(of_fdt_raw_init); |
1102 | #endif | 1125 | #endif |
1103 | 1126 | ||
1104 | #endif /* CONFIG_OF_EARLY_FLATTREE */ | 1127 | #endif /* CONFIG_OF_EARLY_FLATTREE */ |
diff --git a/drivers/of/of_private.h b/drivers/of/of_private.h index 858e0a5d9a11..8e882e706cd8 100644 --- a/drivers/of/of_private.h +++ b/drivers/of/of_private.h | |||
@@ -61,7 +61,7 @@ static inline int of_property_notify(int action, struct device_node *np, | |||
61 | * own the devtree lock or work on detached trees only. | 61 | * own the devtree lock or work on detached trees only. |
62 | */ | 62 | */ |
63 | struct property *__of_prop_dup(const struct property *prop, gfp_t allocflags); | 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); | 64 | __printf(2, 3) struct device_node *__of_node_dup(const struct device_node *np, const char *fmt, ...); |
65 | 65 | ||
66 | extern const void *__of_get_property(const struct device_node *np, | 66 | extern const void *__of_get_property(const struct device_node *np, |
67 | const char *name, int *lenp); | 67 | const char *name, int *lenp); |
diff --git a/drivers/of/overlay.c b/drivers/of/overlay.c new file mode 100644 index 000000000000..ea63fbd228ed --- /dev/null +++ b/drivers/of/overlay.c | |||
@@ -0,0 +1,562 @@ | |||
1 | /* | ||
2 | * Functions for working with device tree overlays | ||
3 | * | ||
4 | * Copyright (C) 2012 Pantelis Antoniou <panto@antoniou-consulting.com> | ||
5 | * Copyright (C) 2012 Texas Instruments Inc. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or | ||
8 | * modify it under the terms of the GNU General Public License | ||
9 | * version 2 as published by the Free Software Foundation. | ||
10 | */ | ||
11 | #undef DEBUG | ||
12 | #include <linux/kernel.h> | ||
13 | #include <linux/module.h> | ||
14 | #include <linux/of.h> | ||
15 | #include <linux/of_device.h> | ||
16 | #include <linux/string.h> | ||
17 | #include <linux/ctype.h> | ||
18 | #include <linux/errno.h> | ||
19 | #include <linux/string.h> | ||
20 | #include <linux/slab.h> | ||
21 | #include <linux/err.h> | ||
22 | |||
23 | #include "of_private.h" | ||
24 | |||
25 | /** | ||
26 | * struct of_overlay_info - Holds a single overlay info | ||
27 | * @target: target of the overlay operation | ||
28 | * @overlay: pointer to the overlay contents node | ||
29 | * | ||
30 | * Holds a single overlay state, including all the overlay logs & | ||
31 | * records. | ||
32 | */ | ||
33 | struct of_overlay_info { | ||
34 | struct device_node *target; | ||
35 | struct device_node *overlay; | ||
36 | }; | ||
37 | |||
38 | /** | ||
39 | * struct of_overlay - Holds a complete overlay transaction | ||
40 | * @node: List on which we are located | ||
41 | * @count: Count of ovinfo structures | ||
42 | * @ovinfo_tab: Overlay info table (count sized) | ||
43 | * @cset: Changeset to be used | ||
44 | * | ||
45 | * Holds a complete overlay transaction | ||
46 | */ | ||
47 | struct of_overlay { | ||
48 | int id; | ||
49 | struct list_head node; | ||
50 | int count; | ||
51 | struct of_overlay_info *ovinfo_tab; | ||
52 | struct of_changeset cset; | ||
53 | }; | ||
54 | |||
55 | static int of_overlay_apply_one(struct of_overlay *ov, | ||
56 | struct device_node *target, const struct device_node *overlay); | ||
57 | |||
58 | static int of_overlay_apply_single_property(struct of_overlay *ov, | ||
59 | struct device_node *target, struct property *prop) | ||
60 | { | ||
61 | struct property *propn, *tprop; | ||
62 | |||
63 | /* NOTE: Multiple changes of single properties not supported */ | ||
64 | tprop = of_find_property(target, prop->name, NULL); | ||
65 | |||
66 | /* special properties are not meant to be updated (silent NOP) */ | ||
67 | if (of_prop_cmp(prop->name, "name") == 0 || | ||
68 | of_prop_cmp(prop->name, "phandle") == 0 || | ||
69 | of_prop_cmp(prop->name, "linux,phandle") == 0) | ||
70 | return 0; | ||
71 | |||
72 | propn = __of_prop_dup(prop, GFP_KERNEL); | ||
73 | if (propn == NULL) | ||
74 | return -ENOMEM; | ||
75 | |||
76 | /* not found? add */ | ||
77 | if (tprop == NULL) | ||
78 | return of_changeset_add_property(&ov->cset, target, propn); | ||
79 | |||
80 | /* found? update */ | ||
81 | return of_changeset_update_property(&ov->cset, target, propn); | ||
82 | } | ||
83 | |||
84 | static int of_overlay_apply_single_device_node(struct of_overlay *ov, | ||
85 | struct device_node *target, struct device_node *child) | ||
86 | { | ||
87 | const char *cname; | ||
88 | struct device_node *tchild, *grandchild; | ||
89 | int ret = 0; | ||
90 | |||
91 | cname = kbasename(child->full_name); | ||
92 | if (cname == NULL) | ||
93 | return -ENOMEM; | ||
94 | |||
95 | /* NOTE: Multiple mods of created nodes not supported */ | ||
96 | tchild = of_get_child_by_name(target, cname); | ||
97 | if (tchild != NULL) { | ||
98 | /* apply overlay recursively */ | ||
99 | ret = of_overlay_apply_one(ov, tchild, child); | ||
100 | of_node_put(tchild); | ||
101 | } else { | ||
102 | /* create empty tree as a target */ | ||
103 | tchild = __of_node_dup(child, "%s/%s", target->full_name, cname); | ||
104 | if (!tchild) | ||
105 | return -ENOMEM; | ||
106 | |||
107 | /* point to parent */ | ||
108 | tchild->parent = target; | ||
109 | |||
110 | ret = of_changeset_attach_node(&ov->cset, tchild); | ||
111 | if (ret) | ||
112 | return ret; | ||
113 | |||
114 | ret = of_overlay_apply_one(ov, tchild, child); | ||
115 | if (ret) | ||
116 | return ret; | ||
117 | |||
118 | /* The properties are already copied, now do the child nodes */ | ||
119 | for_each_child_of_node(child, grandchild) { | ||
120 | ret = of_overlay_apply_single_device_node(ov, tchild, grandchild); | ||
121 | if (ret) { | ||
122 | pr_err("%s: Failed to apply single node @%s/%s\n", | ||
123 | __func__, tchild->full_name, | ||
124 | grandchild->name); | ||
125 | return ret; | ||
126 | } | ||
127 | } | ||
128 | } | ||
129 | |||
130 | return ret; | ||
131 | } | ||
132 | |||
133 | /* | ||
134 | * Apply a single overlay node recursively. | ||
135 | * | ||
136 | * Note that the in case of an error the target node is left | ||
137 | * in a inconsistent state. Error recovery should be performed | ||
138 | * by using the changeset. | ||
139 | */ | ||
140 | static int of_overlay_apply_one(struct of_overlay *ov, | ||
141 | struct device_node *target, const struct device_node *overlay) | ||
142 | { | ||
143 | struct device_node *child; | ||
144 | struct property *prop; | ||
145 | int ret; | ||
146 | |||
147 | for_each_property_of_node(overlay, prop) { | ||
148 | ret = of_overlay_apply_single_property(ov, target, prop); | ||
149 | if (ret) { | ||
150 | pr_err("%s: Failed to apply prop @%s/%s\n", | ||
151 | __func__, target->full_name, prop->name); | ||
152 | return ret; | ||
153 | } | ||
154 | } | ||
155 | |||
156 | for_each_child_of_node(overlay, child) { | ||
157 | ret = of_overlay_apply_single_device_node(ov, target, child); | ||
158 | if (ret != 0) { | ||
159 | pr_err("%s: Failed to apply single node @%s/%s\n", | ||
160 | __func__, target->full_name, | ||
161 | child->name); | ||
162 | return ret; | ||
163 | } | ||
164 | } | ||
165 | |||
166 | return 0; | ||
167 | } | ||
168 | |||
169 | /** | ||
170 | * of_overlay_apply() - Apply @count overlays pointed at by @ovinfo_tab | ||
171 | * @ov: Overlay to apply | ||
172 | * | ||
173 | * Applies the overlays given, while handling all error conditions | ||
174 | * appropriately. Either the operation succeeds, or if it fails the | ||
175 | * live tree is reverted to the state before the attempt. | ||
176 | * Returns 0, or an error if the overlay attempt failed. | ||
177 | */ | ||
178 | static int of_overlay_apply(struct of_overlay *ov) | ||
179 | { | ||
180 | int i, err; | ||
181 | |||
182 | /* first we apply the overlays atomically */ | ||
183 | for (i = 0; i < ov->count; i++) { | ||
184 | struct of_overlay_info *ovinfo = &ov->ovinfo_tab[i]; | ||
185 | |||
186 | err = of_overlay_apply_one(ov, ovinfo->target, ovinfo->overlay); | ||
187 | if (err != 0) { | ||
188 | pr_err("%s: overlay failed '%s'\n", | ||
189 | __func__, ovinfo->target->full_name); | ||
190 | return err; | ||
191 | } | ||
192 | } | ||
193 | |||
194 | return 0; | ||
195 | } | ||
196 | |||
197 | /* | ||
198 | * Find the target node using a number of different strategies | ||
199 | * in order of preference | ||
200 | * | ||
201 | * "target" property containing the phandle of the target | ||
202 | * "target-path" property containing the path of the target | ||
203 | */ | ||
204 | static struct device_node *find_target_node(struct device_node *info_node) | ||
205 | { | ||
206 | const char *path; | ||
207 | u32 val; | ||
208 | int ret; | ||
209 | |||
210 | /* first try to go by using the target as a phandle */ | ||
211 | ret = of_property_read_u32(info_node, "target", &val); | ||
212 | if (ret == 0) | ||
213 | return of_find_node_by_phandle(val); | ||
214 | |||
215 | /* now try to locate by path */ | ||
216 | ret = of_property_read_string(info_node, "target-path", &path); | ||
217 | if (ret == 0) | ||
218 | return of_find_node_by_path(path); | ||
219 | |||
220 | pr_err("%s: Failed to find target for node %p (%s)\n", __func__, | ||
221 | info_node, info_node->name); | ||
222 | |||
223 | return NULL; | ||
224 | } | ||
225 | |||
226 | /** | ||
227 | * of_fill_overlay_info() - Fill an overlay info structure | ||
228 | * @ov Overlay to fill | ||
229 | * @info_node: Device node containing the overlay | ||
230 | * @ovinfo: Pointer to the overlay info structure to fill | ||
231 | * | ||
232 | * Fills an overlay info structure with the overlay information | ||
233 | * from a device node. This device node must have a target property | ||
234 | * which contains a phandle of the overlay target node, and an | ||
235 | * __overlay__ child node which has the overlay contents. | ||
236 | * Both ovinfo->target & ovinfo->overlay have their references taken. | ||
237 | * | ||
238 | * Returns 0 on success, or a negative error value. | ||
239 | */ | ||
240 | static int of_fill_overlay_info(struct of_overlay *ov, | ||
241 | struct device_node *info_node, struct of_overlay_info *ovinfo) | ||
242 | { | ||
243 | ovinfo->overlay = of_get_child_by_name(info_node, "__overlay__"); | ||
244 | if (ovinfo->overlay == NULL) | ||
245 | goto err_fail; | ||
246 | |||
247 | ovinfo->target = find_target_node(info_node); | ||
248 | if (ovinfo->target == NULL) | ||
249 | goto err_fail; | ||
250 | |||
251 | return 0; | ||
252 | |||
253 | err_fail: | ||
254 | of_node_put(ovinfo->target); | ||
255 | of_node_put(ovinfo->overlay); | ||
256 | |||
257 | memset(ovinfo, 0, sizeof(*ovinfo)); | ||
258 | return -EINVAL; | ||
259 | } | ||
260 | |||
261 | /** | ||
262 | * of_build_overlay_info() - Build an overlay info array | ||
263 | * @ov Overlay to build | ||
264 | * @tree: Device node containing all the overlays | ||
265 | * | ||
266 | * Helper function that given a tree containing overlay information, | ||
267 | * allocates and builds an overlay info array containing it, ready | ||
268 | * for use using of_overlay_apply. | ||
269 | * | ||
270 | * Returns 0 on success with the @cntp @ovinfop pointers valid, | ||
271 | * while on error a negative error value is returned. | ||
272 | */ | ||
273 | static int of_build_overlay_info(struct of_overlay *ov, | ||
274 | struct device_node *tree) | ||
275 | { | ||
276 | struct device_node *node; | ||
277 | struct of_overlay_info *ovinfo; | ||
278 | int cnt, err; | ||
279 | |||
280 | /* worst case; every child is a node */ | ||
281 | cnt = 0; | ||
282 | for_each_child_of_node(tree, node) | ||
283 | cnt++; | ||
284 | |||
285 | ovinfo = kcalloc(cnt, sizeof(*ovinfo), GFP_KERNEL); | ||
286 | if (ovinfo == NULL) | ||
287 | return -ENOMEM; | ||
288 | |||
289 | cnt = 0; | ||
290 | for_each_child_of_node(tree, node) { | ||
291 | memset(&ovinfo[cnt], 0, sizeof(*ovinfo)); | ||
292 | err = of_fill_overlay_info(ov, node, &ovinfo[cnt]); | ||
293 | if (err == 0) | ||
294 | cnt++; | ||
295 | } | ||
296 | |||
297 | /* if nothing filled, return error */ | ||
298 | if (cnt == 0) { | ||
299 | kfree(ovinfo); | ||
300 | return -ENODEV; | ||
301 | } | ||
302 | |||
303 | ov->count = cnt; | ||
304 | ov->ovinfo_tab = ovinfo; | ||
305 | |||
306 | return 0; | ||
307 | } | ||
308 | |||
309 | /** | ||
310 | * of_free_overlay_info() - Free an overlay info array | ||
311 | * @ov Overlay to free the overlay info from | ||
312 | * @ovinfo_tab: Array of overlay_info's to free | ||
313 | * | ||
314 | * Releases the memory of a previously allocated ovinfo array | ||
315 | * by of_build_overlay_info. | ||
316 | * Returns 0, or an error if the arguments are bogus. | ||
317 | */ | ||
318 | static int of_free_overlay_info(struct of_overlay *ov) | ||
319 | { | ||
320 | struct of_overlay_info *ovinfo; | ||
321 | int i; | ||
322 | |||
323 | /* do it in reverse */ | ||
324 | for (i = ov->count - 1; i >= 0; i--) { | ||
325 | ovinfo = &ov->ovinfo_tab[i]; | ||
326 | |||
327 | of_node_put(ovinfo->target); | ||
328 | of_node_put(ovinfo->overlay); | ||
329 | } | ||
330 | kfree(ov->ovinfo_tab); | ||
331 | |||
332 | return 0; | ||
333 | } | ||
334 | |||
335 | static LIST_HEAD(ov_list); | ||
336 | static DEFINE_IDR(ov_idr); | ||
337 | |||
338 | /** | ||
339 | * of_overlay_create() - Create and apply an overlay | ||
340 | * @tree: Device node containing all the overlays | ||
341 | * | ||
342 | * Creates and applies an overlay while also keeping track | ||
343 | * of the overlay in a list. This list can be used to prevent | ||
344 | * illegal overlay removals. | ||
345 | * | ||
346 | * Returns the id of the created overlay, or an negative error number | ||
347 | */ | ||
348 | int of_overlay_create(struct device_node *tree) | ||
349 | { | ||
350 | struct of_overlay *ov; | ||
351 | int err, id; | ||
352 | |||
353 | /* allocate the overlay structure */ | ||
354 | ov = kzalloc(sizeof(*ov), GFP_KERNEL); | ||
355 | if (ov == NULL) | ||
356 | return -ENOMEM; | ||
357 | ov->id = -1; | ||
358 | |||
359 | INIT_LIST_HEAD(&ov->node); | ||
360 | |||
361 | of_changeset_init(&ov->cset); | ||
362 | |||
363 | mutex_lock(&of_mutex); | ||
364 | |||
365 | id = idr_alloc(&ov_idr, ov, 0, 0, GFP_KERNEL); | ||
366 | if (id < 0) { | ||
367 | pr_err("%s: idr_alloc() failed for tree@%s\n", | ||
368 | __func__, tree->full_name); | ||
369 | err = id; | ||
370 | goto err_destroy_trans; | ||
371 | } | ||
372 | ov->id = id; | ||
373 | |||
374 | /* build the overlay info structures */ | ||
375 | err = of_build_overlay_info(ov, tree); | ||
376 | if (err) { | ||
377 | pr_err("%s: of_build_overlay_info() failed for tree@%s\n", | ||
378 | __func__, tree->full_name); | ||
379 | goto err_free_idr; | ||
380 | } | ||
381 | |||
382 | /* apply the overlay */ | ||
383 | err = of_overlay_apply(ov); | ||
384 | if (err) { | ||
385 | pr_err("%s: of_overlay_apply() failed for tree@%s\n", | ||
386 | __func__, tree->full_name); | ||
387 | goto err_abort_trans; | ||
388 | } | ||
389 | |||
390 | /* apply the changeset */ | ||
391 | err = of_changeset_apply(&ov->cset); | ||
392 | if (err) { | ||
393 | pr_err("%s: of_changeset_apply() failed for tree@%s\n", | ||
394 | __func__, tree->full_name); | ||
395 | goto err_revert_overlay; | ||
396 | } | ||
397 | |||
398 | /* add to the tail of the overlay list */ | ||
399 | list_add_tail(&ov->node, &ov_list); | ||
400 | |||
401 | mutex_unlock(&of_mutex); | ||
402 | |||
403 | return id; | ||
404 | |||
405 | err_revert_overlay: | ||
406 | err_abort_trans: | ||
407 | of_free_overlay_info(ov); | ||
408 | err_free_idr: | ||
409 | idr_remove(&ov_idr, ov->id); | ||
410 | err_destroy_trans: | ||
411 | of_changeset_destroy(&ov->cset); | ||
412 | kfree(ov); | ||
413 | mutex_unlock(&of_mutex); | ||
414 | |||
415 | return err; | ||
416 | } | ||
417 | EXPORT_SYMBOL_GPL(of_overlay_create); | ||
418 | |||
419 | /* check whether the given node, lies under the given tree */ | ||
420 | static int overlay_subtree_check(struct device_node *tree, | ||
421 | struct device_node *dn) | ||
422 | { | ||
423 | struct device_node *child; | ||
424 | |||
425 | /* match? */ | ||
426 | if (tree == dn) | ||
427 | return 1; | ||
428 | |||
429 | for_each_child_of_node(tree, child) { | ||
430 | if (overlay_subtree_check(child, dn)) | ||
431 | return 1; | ||
432 | } | ||
433 | |||
434 | return 0; | ||
435 | } | ||
436 | |||
437 | /* check whether this overlay is the topmost */ | ||
438 | static int overlay_is_topmost(struct of_overlay *ov, struct device_node *dn) | ||
439 | { | ||
440 | struct of_overlay *ovt; | ||
441 | struct of_changeset_entry *ce; | ||
442 | |||
443 | list_for_each_entry_reverse(ovt, &ov_list, node) { | ||
444 | /* if we hit ourselves, we're done */ | ||
445 | if (ovt == ov) | ||
446 | break; | ||
447 | |||
448 | /* check against each subtree affected by this overlay */ | ||
449 | list_for_each_entry(ce, &ovt->cset.entries, node) { | ||
450 | if (overlay_subtree_check(ce->np, dn)) { | ||
451 | pr_err("%s: #%d clashes #%d @%s\n", | ||
452 | __func__, ov->id, ovt->id, | ||
453 | dn->full_name); | ||
454 | return 0; | ||
455 | } | ||
456 | } | ||
457 | } | ||
458 | |||
459 | /* overlay is topmost */ | ||
460 | return 1; | ||
461 | } | ||
462 | |||
463 | /* | ||
464 | * We can safely remove the overlay only if it's the top-most one. | ||
465 | * Newly applied overlays are inserted at the tail of the overlay list, | ||
466 | * so a top most overlay is the one that is closest to the tail. | ||
467 | * | ||
468 | * The topmost check is done by exploiting this property. For each | ||
469 | * affected device node in the log list we check if this overlay is | ||
470 | * the one closest to the tail. If another overlay has affected this | ||
471 | * device node and is closest to the tail, then removal is not permited. | ||
472 | */ | ||
473 | static int overlay_removal_is_ok(struct of_overlay *ov) | ||
474 | { | ||
475 | struct of_changeset_entry *ce; | ||
476 | |||
477 | list_for_each_entry(ce, &ov->cset.entries, node) { | ||
478 | if (!overlay_is_topmost(ov, ce->np)) { | ||
479 | pr_err("%s: overlay #%d is not topmost\n", | ||
480 | __func__, ov->id); | ||
481 | return 0; | ||
482 | } | ||
483 | } | ||
484 | |||
485 | return 1; | ||
486 | } | ||
487 | |||
488 | /** | ||
489 | * of_overlay_destroy() - Removes an overlay | ||
490 | * @id: Overlay id number returned by a previous call to of_overlay_create | ||
491 | * | ||
492 | * Removes an overlay if it is permissible. | ||
493 | * | ||
494 | * Returns 0 on success, or an negative error number | ||
495 | */ | ||
496 | int of_overlay_destroy(int id) | ||
497 | { | ||
498 | struct of_overlay *ov; | ||
499 | int err; | ||
500 | |||
501 | mutex_lock(&of_mutex); | ||
502 | |||
503 | ov = idr_find(&ov_idr, id); | ||
504 | if (ov == NULL) { | ||
505 | err = -ENODEV; | ||
506 | pr_err("%s: Could not find overlay #%d\n", | ||
507 | __func__, id); | ||
508 | goto out; | ||
509 | } | ||
510 | |||
511 | /* check whether the overlay is safe to remove */ | ||
512 | if (!overlay_removal_is_ok(ov)) { | ||
513 | err = -EBUSY; | ||
514 | pr_err("%s: removal check failed for overlay #%d\n", | ||
515 | __func__, id); | ||
516 | goto out; | ||
517 | } | ||
518 | |||
519 | |||
520 | list_del(&ov->node); | ||
521 | of_changeset_revert(&ov->cset); | ||
522 | of_free_overlay_info(ov); | ||
523 | idr_remove(&ov_idr, id); | ||
524 | of_changeset_destroy(&ov->cset); | ||
525 | kfree(ov); | ||
526 | |||
527 | err = 0; | ||
528 | |||
529 | out: | ||
530 | mutex_unlock(&of_mutex); | ||
531 | |||
532 | return err; | ||
533 | } | ||
534 | EXPORT_SYMBOL_GPL(of_overlay_destroy); | ||
535 | |||
536 | /** | ||
537 | * of_overlay_destroy_all() - Removes all overlays from the system | ||
538 | * | ||
539 | * Removes all overlays from the system in the correct order. | ||
540 | * | ||
541 | * Returns 0 on success, or an negative error number | ||
542 | */ | ||
543 | int of_overlay_destroy_all(void) | ||
544 | { | ||
545 | struct of_overlay *ov, *ovn; | ||
546 | |||
547 | mutex_lock(&of_mutex); | ||
548 | |||
549 | /* the tail of list is guaranteed to be safe to remove */ | ||
550 | list_for_each_entry_safe_reverse(ov, ovn, &ov_list, node) { | ||
551 | list_del(&ov->node); | ||
552 | of_changeset_revert(&ov->cset); | ||
553 | of_free_overlay_info(ov); | ||
554 | idr_remove(&ov_idr, ov->id); | ||
555 | kfree(ov); | ||
556 | } | ||
557 | |||
558 | mutex_unlock(&of_mutex); | ||
559 | |||
560 | return 0; | ||
561 | } | ||
562 | EXPORT_SYMBOL_GPL(of_overlay_destroy_all); | ||
diff --git a/drivers/of/pdt.c b/drivers/of/pdt.c index 36b4035881b0..d2acae825af9 100644 --- a/drivers/of/pdt.c +++ b/drivers/of/pdt.c | |||
@@ -25,8 +25,7 @@ | |||
25 | 25 | ||
26 | static struct of_pdt_ops *of_pdt_prom_ops __initdata; | 26 | static struct of_pdt_ops *of_pdt_prom_ops __initdata; |
27 | 27 | ||
28 | void __initdata (*of_pdt_build_more)(struct device_node *dp, | 28 | void __initdata (*of_pdt_build_more)(struct device_node *dp); |
29 | struct device_node ***nextp); | ||
30 | 29 | ||
31 | #if defined(CONFIG_SPARC) | 30 | #if defined(CONFIG_SPARC) |
32 | unsigned int of_pdt_unique_id __initdata; | 31 | unsigned int of_pdt_unique_id __initdata; |
@@ -192,8 +191,7 @@ static struct device_node * __init of_pdt_create_node(phandle node, | |||
192 | } | 191 | } |
193 | 192 | ||
194 | static struct device_node * __init of_pdt_build_tree(struct device_node *parent, | 193 | static struct device_node * __init of_pdt_build_tree(struct device_node *parent, |
195 | phandle node, | 194 | phandle node) |
196 | struct device_node ***nextp) | ||
197 | { | 195 | { |
198 | struct device_node *ret = NULL, *prev_sibling = NULL; | 196 | struct device_node *ret = NULL, *prev_sibling = NULL; |
199 | struct device_node *dp; | 197 | struct device_node *dp; |
@@ -210,16 +208,12 @@ static struct device_node * __init of_pdt_build_tree(struct device_node *parent, | |||
210 | ret = dp; | 208 | ret = dp; |
211 | prev_sibling = dp; | 209 | prev_sibling = dp; |
212 | 210 | ||
213 | *(*nextp) = dp; | ||
214 | *nextp = &dp->allnext; | ||
215 | |||
216 | dp->full_name = of_pdt_build_full_name(dp); | 211 | dp->full_name = of_pdt_build_full_name(dp); |
217 | 212 | ||
218 | dp->child = of_pdt_build_tree(dp, | 213 | dp->child = of_pdt_build_tree(dp, of_pdt_prom_ops->getchild(node)); |
219 | of_pdt_prom_ops->getchild(node), nextp); | ||
220 | 214 | ||
221 | if (of_pdt_build_more) | 215 | if (of_pdt_build_more) |
222 | of_pdt_build_more(dp, nextp); | 216 | of_pdt_build_more(dp); |
223 | 217 | ||
224 | node = of_pdt_prom_ops->getsibling(node); | 218 | node = of_pdt_prom_ops->getsibling(node); |
225 | } | 219 | } |
@@ -234,20 +228,17 @@ static void * __init kernel_tree_alloc(u64 size, u64 align) | |||
234 | 228 | ||
235 | void __init of_pdt_build_devicetree(phandle root_node, struct of_pdt_ops *ops) | 229 | void __init of_pdt_build_devicetree(phandle root_node, struct of_pdt_ops *ops) |
236 | { | 230 | { |
237 | struct device_node **nextp; | ||
238 | |||
239 | BUG_ON(!ops); | 231 | BUG_ON(!ops); |
240 | of_pdt_prom_ops = ops; | 232 | of_pdt_prom_ops = ops; |
241 | 233 | ||
242 | of_allnodes = of_pdt_create_node(root_node, NULL); | 234 | of_root = of_pdt_create_node(root_node, NULL); |
243 | #if defined(CONFIG_SPARC) | 235 | #if defined(CONFIG_SPARC) |
244 | of_allnodes->path_component_name = ""; | 236 | of_root->path_component_name = ""; |
245 | #endif | 237 | #endif |
246 | of_allnodes->full_name = "/"; | 238 | of_root->full_name = "/"; |
247 | 239 | ||
248 | nextp = &of_allnodes->allnext; | 240 | of_root->child = of_pdt_build_tree(of_root, |
249 | of_allnodes->child = of_pdt_build_tree(of_allnodes, | 241 | of_pdt_prom_ops->getchild(of_root->phandle)); |
250 | of_pdt_prom_ops->getchild(of_allnodes->phandle), &nextp); | ||
251 | 242 | ||
252 | /* Get pointer to "/chosen" and "/aliases" nodes for use everywhere */ | 243 | /* Get pointer to "/chosen" and "/aliases" nodes for use everywhere */ |
253 | of_alias_scan(kernel_tree_alloc); | 244 | of_alias_scan(kernel_tree_alloc); |
diff --git a/drivers/of/platform.c b/drivers/of/platform.c index 3b64d0bf5bba..cd87a36495be 100644 --- a/drivers/of/platform.c +++ b/drivers/of/platform.c | |||
@@ -138,7 +138,7 @@ struct platform_device *of_device_alloc(struct device_node *np, | |||
138 | } | 138 | } |
139 | 139 | ||
140 | dev->dev.of_node = of_node_get(np); | 140 | dev->dev.of_node = of_node_get(np); |
141 | dev->dev.parent = parent; | 141 | dev->dev.parent = parent ? : &platform_bus; |
142 | 142 | ||
143 | if (bus_id) | 143 | if (bus_id) |
144 | dev_set_name(&dev->dev, "%s", bus_id); | 144 | dev_set_name(&dev->dev, "%s", bus_id); |
@@ -291,7 +291,7 @@ static struct amba_device *of_amba_device_create(struct device_node *node, | |||
291 | 291 | ||
292 | /* setup generic device info */ | 292 | /* setup generic device info */ |
293 | dev->dev.of_node = of_node_get(node); | 293 | dev->dev.of_node = of_node_get(node); |
294 | dev->dev.parent = parent; | 294 | dev->dev.parent = parent ? : &platform_bus; |
295 | dev->dev.platform_data = platform_data; | 295 | dev->dev.platform_data = platform_data; |
296 | if (bus_id) | 296 | if (bus_id) |
297 | dev_set_name(&dev->dev, "%s", bus_id); | 297 | dev_set_name(&dev->dev, "%s", bus_id); |
@@ -500,6 +500,7 @@ int of_platform_populate(struct device_node *root, | |||
500 | if (rc) | 500 | if (rc) |
501 | break; | 501 | break; |
502 | } | 502 | } |
503 | of_node_set_flag(root, OF_POPULATED_BUS); | ||
503 | 504 | ||
504 | of_node_put(root); | 505 | of_node_put(root); |
505 | return rc; | 506 | return rc; |
@@ -542,8 +543,66 @@ static int of_platform_device_destroy(struct device *dev, void *data) | |||
542 | */ | 543 | */ |
543 | void of_platform_depopulate(struct device *parent) | 544 | void of_platform_depopulate(struct device *parent) |
544 | { | 545 | { |
545 | device_for_each_child(parent, NULL, of_platform_device_destroy); | 546 | if (parent->of_node && of_node_check_flag(parent->of_node, OF_POPULATED_BUS)) { |
547 | device_for_each_child(parent, NULL, of_platform_device_destroy); | ||
548 | of_node_clear_flag(parent->of_node, OF_POPULATED_BUS); | ||
549 | } | ||
546 | } | 550 | } |
547 | EXPORT_SYMBOL_GPL(of_platform_depopulate); | 551 | EXPORT_SYMBOL_GPL(of_platform_depopulate); |
548 | 552 | ||
553 | #ifdef CONFIG_OF_DYNAMIC | ||
554 | static int of_platform_notify(struct notifier_block *nb, | ||
555 | unsigned long action, void *arg) | ||
556 | { | ||
557 | struct of_reconfig_data *rd = arg; | ||
558 | struct platform_device *pdev_parent, *pdev; | ||
559 | bool children_left; | ||
560 | |||
561 | switch (of_reconfig_get_state_change(action, rd)) { | ||
562 | case OF_RECONFIG_CHANGE_ADD: | ||
563 | /* verify that the parent is a bus */ | ||
564 | if (!of_node_check_flag(rd->dn->parent, OF_POPULATED_BUS)) | ||
565 | return NOTIFY_OK; /* not for us */ | ||
566 | |||
567 | /* pdev_parent may be NULL when no bus platform device */ | ||
568 | pdev_parent = of_find_device_by_node(rd->dn->parent); | ||
569 | pdev = of_platform_device_create(rd->dn, NULL, | ||
570 | pdev_parent ? &pdev_parent->dev : NULL); | ||
571 | of_dev_put(pdev_parent); | ||
572 | |||
573 | if (pdev == NULL) { | ||
574 | pr_err("%s: failed to create for '%s'\n", | ||
575 | __func__, rd->dn->full_name); | ||
576 | /* of_platform_device_create tosses the error code */ | ||
577 | return notifier_from_errno(-EINVAL); | ||
578 | } | ||
579 | break; | ||
580 | |||
581 | case OF_RECONFIG_CHANGE_REMOVE: | ||
582 | /* find our device by node */ | ||
583 | pdev = of_find_device_by_node(rd->dn); | ||
584 | if (pdev == NULL) | ||
585 | return NOTIFY_OK; /* no? not meant for us */ | ||
586 | |||
587 | /* unregister takes one ref away */ | ||
588 | of_platform_device_destroy(&pdev->dev, &children_left); | ||
589 | |||
590 | /* and put the reference of the find */ | ||
591 | of_dev_put(pdev); | ||
592 | break; | ||
593 | } | ||
594 | |||
595 | return NOTIFY_OK; | ||
596 | } | ||
597 | |||
598 | static struct notifier_block platform_of_notifier = { | ||
599 | .notifier_call = of_platform_notify, | ||
600 | }; | ||
601 | |||
602 | void of_platform_register_reconfig_notifier(void) | ||
603 | { | ||
604 | WARN_ON(of_reconfig_notifier_register(&platform_of_notifier)); | ||
605 | } | ||
606 | #endif /* CONFIG_OF_DYNAMIC */ | ||
607 | |||
549 | #endif /* CONFIG_OF_ADDRESS */ | 608 | #endif /* CONFIG_OF_ADDRESS */ |
diff --git a/drivers/of/resolver.c b/drivers/of/resolver.c index aed7959f800d..640eb4cb46e3 100644 --- a/drivers/of/resolver.c +++ b/drivers/of/resolver.c | |||
@@ -111,7 +111,8 @@ static void __of_adjust_tree_phandles(struct device_node *node, | |||
111 | __of_adjust_tree_phandles(child, phandle_delta); | 111 | __of_adjust_tree_phandles(child, phandle_delta); |
112 | } | 112 | } |
113 | 113 | ||
114 | static int __of_adjust_phandle_ref(struct device_node *node, struct property *rprop, int value, bool is_delta) | 114 | static int __of_adjust_phandle_ref(struct device_node *node, |
115 | struct property *rprop, int value) | ||
115 | { | 116 | { |
116 | phandle phandle; | 117 | phandle phandle; |
117 | struct device_node *refnode; | 118 | struct device_node *refnode; |
@@ -181,7 +182,7 @@ static int __of_adjust_phandle_ref(struct device_node *node, struct property *rp | |||
181 | goto err_fail; | 182 | goto err_fail; |
182 | } | 183 | } |
183 | 184 | ||
184 | phandle = is_delta ? be32_to_cpup(sprop->value + offset) + value : value; | 185 | phandle = value; |
185 | *(__be32 *)(sprop->value + offset) = cpu_to_be32(phandle); | 186 | *(__be32 *)(sprop->value + offset) = cpu_to_be32(phandle); |
186 | } | 187 | } |
187 | 188 | ||
@@ -190,36 +191,97 @@ err_fail: | |||
190 | return err; | 191 | return err; |
191 | } | 192 | } |
192 | 193 | ||
194 | /* compare nodes taking into account that 'name' strips out the @ part */ | ||
195 | static int __of_node_name_cmp(const struct device_node *dn1, | ||
196 | const struct device_node *dn2) | ||
197 | { | ||
198 | const char *n1 = strrchr(dn1->full_name, '/') ? : "/"; | ||
199 | const char *n2 = strrchr(dn2->full_name, '/') ? : "/"; | ||
200 | |||
201 | return of_node_cmp(n1, n2); | ||
202 | } | ||
203 | |||
193 | /* | 204 | /* |
194 | * Adjust the local phandle references by the given phandle delta. | 205 | * Adjust the local phandle references by the given phandle delta. |
195 | * Assumes the existances of a __local_fixups__ node at the root | 206 | * Assumes the existances of a __local_fixups__ node at the root. |
196 | * of the tree. Does not take any devtree locks so make sure you | 207 | * Assumes that __of_verify_tree_phandle_references has been called. |
197 | * call this on a tree which is at the detached state. | 208 | * Does not take any devtree locks so make sure you call this on a tree |
209 | * which is at the detached state. | ||
198 | */ | 210 | */ |
199 | static int __of_adjust_tree_phandle_references(struct device_node *node, | 211 | static int __of_adjust_tree_phandle_references(struct device_node *node, |
200 | int phandle_delta) | 212 | struct device_node *target, int phandle_delta) |
201 | { | 213 | { |
202 | struct device_node *child; | 214 | struct device_node *child, *childtarget; |
203 | struct property *rprop; | 215 | struct property *rprop, *sprop; |
204 | int err; | 216 | int err, i, count; |
205 | 217 | unsigned int off; | |
206 | /* locate the symbols & fixups nodes on resolve */ | 218 | phandle phandle; |
207 | for_each_child_of_node(node, child) | ||
208 | if (of_node_cmp(child->name, "__local_fixups__") == 0) | ||
209 | break; | ||
210 | 219 | ||
211 | /* no local fixups */ | 220 | if (node == NULL) |
212 | if (!child) | ||
213 | return 0; | 221 | return 0; |
214 | 222 | ||
215 | /* find the local fixups property */ | 223 | for_each_property_of_node(node, rprop) { |
216 | for_each_property_of_node(child, rprop) { | 224 | |
217 | /* skip properties added automatically */ | 225 | /* skip properties added automatically */ |
218 | if (of_prop_cmp(rprop->name, "name") == 0) | 226 | if (of_prop_cmp(rprop->name, "name") == 0 || |
227 | of_prop_cmp(rprop->name, "phandle") == 0 || | ||
228 | of_prop_cmp(rprop->name, "linux,phandle") == 0) | ||
219 | continue; | 229 | continue; |
220 | 230 | ||
221 | err = __of_adjust_phandle_ref(node, rprop, phandle_delta, true); | 231 | if ((rprop->length % 4) != 0 || rprop->length == 0) { |
222 | if (err) | 232 | pr_err("%s: Illegal property (size) '%s' @%s\n", |
233 | __func__, rprop->name, node->full_name); | ||
234 | return -EINVAL; | ||
235 | } | ||
236 | count = rprop->length / sizeof(__be32); | ||
237 | |||
238 | /* now find the target property */ | ||
239 | for_each_property_of_node(target, sprop) { | ||
240 | if (of_prop_cmp(sprop->name, rprop->name) == 0) | ||
241 | break; | ||
242 | } | ||
243 | |||
244 | if (sprop == NULL) { | ||
245 | pr_err("%s: Could not find target property '%s' @%s\n", | ||
246 | __func__, rprop->name, node->full_name); | ||
247 | return -EINVAL; | ||
248 | } | ||
249 | |||
250 | for (i = 0; i < count; i++) { | ||
251 | off = be32_to_cpu(((__be32 *)rprop->value)[i]); | ||
252 | /* make sure the offset doesn't overstep (even wrap) */ | ||
253 | if (off >= sprop->length || | ||
254 | (off + 4) > sprop->length) { | ||
255 | pr_err("%s: Illegal property '%s' @%s\n", | ||
256 | __func__, rprop->name, | ||
257 | node->full_name); | ||
258 | return -EINVAL; | ||
259 | } | ||
260 | |||
261 | if (phandle_delta) { | ||
262 | /* adjust */ | ||
263 | phandle = be32_to_cpu(*(__be32 *)(sprop->value + off)); | ||
264 | phandle += phandle_delta; | ||
265 | *(__be32 *)(sprop->value + off) = cpu_to_be32(phandle); | ||
266 | } | ||
267 | } | ||
268 | } | ||
269 | |||
270 | for_each_child_of_node(node, child) { | ||
271 | |||
272 | for_each_child_of_node(target, childtarget) | ||
273 | if (__of_node_name_cmp(child, childtarget) == 0) | ||
274 | break; | ||
275 | |||
276 | if (!childtarget) { | ||
277 | pr_err("%s: Could not find target child '%s' @%s\n", | ||
278 | __func__, child->name, node->full_name); | ||
279 | return -EINVAL; | ||
280 | } | ||
281 | |||
282 | err = __of_adjust_tree_phandle_references(child, childtarget, | ||
283 | phandle_delta); | ||
284 | if (err != 0) | ||
223 | return err; | 285 | return err; |
224 | } | 286 | } |
225 | 287 | ||
@@ -241,7 +303,7 @@ static int __of_adjust_tree_phandle_references(struct device_node *node, | |||
241 | */ | 303 | */ |
242 | int of_resolve_phandles(struct device_node *resolve) | 304 | int of_resolve_phandles(struct device_node *resolve) |
243 | { | 305 | { |
244 | struct device_node *child, *refnode; | 306 | struct device_node *child, *childroot, *refnode; |
245 | struct device_node *root_sym, *resolve_sym, *resolve_fix; | 307 | struct device_node *root_sym, *resolve_sym, *resolve_fix; |
246 | struct property *rprop; | 308 | struct property *rprop; |
247 | const char *refpath; | 309 | const char *refpath; |
@@ -255,9 +317,23 @@ int of_resolve_phandles(struct device_node *resolve) | |||
255 | /* first we need to adjust the phandles */ | 317 | /* first we need to adjust the phandles */ |
256 | phandle_delta = of_get_tree_max_phandle() + 1; | 318 | phandle_delta = of_get_tree_max_phandle() + 1; |
257 | __of_adjust_tree_phandles(resolve, phandle_delta); | 319 | __of_adjust_tree_phandles(resolve, phandle_delta); |
258 | err = __of_adjust_tree_phandle_references(resolve, phandle_delta); | 320 | |
259 | if (err != 0) | 321 | /* locate the local fixups */ |
260 | return err; | 322 | childroot = NULL; |
323 | for_each_child_of_node(resolve, childroot) | ||
324 | if (of_node_cmp(childroot->name, "__local_fixups__") == 0) | ||
325 | break; | ||
326 | |||
327 | if (childroot != NULL) { | ||
328 | /* resolve root is guaranteed to be the '/' */ | ||
329 | err = __of_adjust_tree_phandle_references(childroot, | ||
330 | resolve, 0); | ||
331 | if (err != 0) | ||
332 | return err; | ||
333 | |||
334 | BUG_ON(__of_adjust_tree_phandle_references(childroot, | ||
335 | resolve, phandle_delta)); | ||
336 | } | ||
261 | 337 | ||
262 | root_sym = NULL; | 338 | root_sym = NULL; |
263 | resolve_sym = NULL; | 339 | resolve_sym = NULL; |
@@ -322,7 +398,7 @@ int of_resolve_phandles(struct device_node *resolve) | |||
322 | pr_debug("%s: %s phandle is 0x%08x\n", | 398 | pr_debug("%s: %s phandle is 0x%08x\n", |
323 | __func__, rprop->name, phandle); | 399 | __func__, rprop->name, phandle); |
324 | 400 | ||
325 | err = __of_adjust_phandle_ref(resolve, rprop, phandle, false); | 401 | err = __of_adjust_phandle_ref(resolve, rprop, phandle); |
326 | if (err) | 402 | if (err) |
327 | break; | 403 | break; |
328 | } | 404 | } |
diff --git a/drivers/of/testcase-data/testcases.dts b/drivers/of/testcase-data/testcases.dts deleted file mode 100644 index 6994e15c24bf..000000000000 --- a/drivers/of/testcase-data/testcases.dts +++ /dev/null | |||
@@ -1,50 +0,0 @@ | |||
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" | ||
16 | |||
17 | /* | ||
18 | * phandle fixup data - generated by dtc patches that aren't upstream. | ||
19 | * This data must be regenerated whenever phandle references are modified in | ||
20 | * the testdata tree. | ||
21 | * | ||
22 | * The format of this data may be subject to change. For the time being consider | ||
23 | * this a kernel-internal data format. | ||
24 | */ | ||
25 | / { __local_fixups__ { | ||
26 | fixup = "/testcase-data/testcase-device2:interrupt-parent:0", | ||
27 | "/testcase-data/testcase-device1:interrupt-parent:0", | ||
28 | "/testcase-data/interrupts/interrupts-extended0:interrupts-extended:60", | ||
29 | "/testcase-data/interrupts/interrupts-extended0:interrupts-extended:52", | ||
30 | "/testcase-data/interrupts/interrupts-extended0:interrupts-extended:44", | ||
31 | "/testcase-data/interrupts/interrupts-extended0:interrupts-extended:36", | ||
32 | "/testcase-data/interrupts/interrupts-extended0:interrupts-extended:24", | ||
33 | "/testcase-data/interrupts/interrupts-extended0:interrupts-extended:8", | ||
34 | "/testcase-data/interrupts/interrupts-extended0:interrupts-extended:0", | ||
35 | "/testcase-data/interrupts/interrupts1:interrupt-parent:0", | ||
36 | "/testcase-data/interrupts/interrupts0:interrupt-parent:0", | ||
37 | "/testcase-data/interrupts/intmap1:interrupt-map:12", | ||
38 | "/testcase-data/interrupts/intmap0:interrupt-map:52", | ||
39 | "/testcase-data/interrupts/intmap0:interrupt-map:36", | ||
40 | "/testcase-data/interrupts/intmap0:interrupt-map:16", | ||
41 | "/testcase-data/interrupts/intmap0:interrupt-map:4", | ||
42 | "/testcase-data/phandle-tests/consumer-a:phandle-list-bad-args:12", | ||
43 | "/testcase-data/phandle-tests/consumer-a:phandle-list-bad-args:0", | ||
44 | "/testcase-data/phandle-tests/consumer-a:phandle-list:56", | ||
45 | "/testcase-data/phandle-tests/consumer-a:phandle-list:52", | ||
46 | "/testcase-data/phandle-tests/consumer-a:phandle-list:40", | ||
47 | "/testcase-data/phandle-tests/consumer-a:phandle-list:24", | ||
48 | "/testcase-data/phandle-tests/consumer-a:phandle-list:8", | ||
49 | "/testcase-data/phandle-tests/consumer-a:phandle-list:0"; | ||
50 | }; }; | ||
diff --git a/drivers/of/unittest-data/testcases.dts b/drivers/of/unittest-data/testcases.dts new file mode 100644 index 000000000000..12f7c3d649c8 --- /dev/null +++ b/drivers/of/unittest-data/testcases.dts | |||
@@ -0,0 +1,79 @@ | |||
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" | ||
16 | #include "tests-overlay.dtsi" | ||
17 | |||
18 | /* | ||
19 | * phandle fixup data - generated by dtc patches that aren't upstream. | ||
20 | * This data must be regenerated whenever phandle references are modified in | ||
21 | * the testdata tree. | ||
22 | * | ||
23 | * The format of this data may be subject to change. For the time being consider | ||
24 | * this a kernel-internal data format. | ||
25 | */ | ||
26 | / { __local_fixups__ { | ||
27 | testcase-data { | ||
28 | phandle-tests { | ||
29 | consumer-a { | ||
30 | phandle-list = <0x00000000 0x00000008 | ||
31 | 0x00000018 0x00000028 | ||
32 | 0x00000034 0x00000038>; | ||
33 | phandle-list-bad-args = <0x00000000 0x0000000c>; | ||
34 | }; | ||
35 | }; | ||
36 | interrupts { | ||
37 | intmap0 { | ||
38 | interrupt-map = <0x00000004 0x00000010 | ||
39 | 0x00000024 0x00000034>; | ||
40 | }; | ||
41 | intmap1 { | ||
42 | interrupt-map = <0x0000000c>; | ||
43 | }; | ||
44 | interrupts0 { | ||
45 | interrupt-parent = <0x00000000>; | ||
46 | }; | ||
47 | interrupts1 { | ||
48 | interrupt-parent = <0x00000000>; | ||
49 | }; | ||
50 | interrupts-extended0 { | ||
51 | interrupts-extended = <0x00000000 0x00000008 | ||
52 | 0x00000018 0x00000024 | ||
53 | 0x0000002c 0x00000034 | ||
54 | 0x0000003c>; | ||
55 | }; | ||
56 | }; | ||
57 | testcase-device1 { | ||
58 | interrupt-parent = <0x00000000>; | ||
59 | }; | ||
60 | testcase-device2 { | ||
61 | interrupt-parent = <0x00000000>; | ||
62 | }; | ||
63 | overlay2 { | ||
64 | fragment@0 { | ||
65 | target = <0x00000000>; | ||
66 | }; | ||
67 | }; | ||
68 | overlay3 { | ||
69 | fragment@0 { | ||
70 | target = <0x00000000>; | ||
71 | }; | ||
72 | }; | ||
73 | overlay4 { | ||
74 | fragment@0 { | ||
75 | target = <0x00000000>; | ||
76 | }; | ||
77 | }; | ||
78 | }; | ||
79 | }; }; | ||
diff --git a/drivers/of/testcase-data/tests-interrupts.dtsi b/drivers/of/unittest-data/tests-interrupts.dtsi index da4695f60351..da4695f60351 100644 --- a/drivers/of/testcase-data/tests-interrupts.dtsi +++ b/drivers/of/unittest-data/tests-interrupts.dtsi | |||
diff --git a/drivers/of/testcase-data/tests-match.dtsi b/drivers/of/unittest-data/tests-match.dtsi index c9e541129534..c9e541129534 100644 --- a/drivers/of/testcase-data/tests-match.dtsi +++ b/drivers/of/unittest-data/tests-match.dtsi | |||
diff --git a/drivers/of/unittest-data/tests-overlay.dtsi b/drivers/of/unittest-data/tests-overlay.dtsi new file mode 100644 index 000000000000..75976da22b2e --- /dev/null +++ b/drivers/of/unittest-data/tests-overlay.dtsi | |||
@@ -0,0 +1,180 @@ | |||
1 | |||
2 | / { | ||
3 | testcase-data { | ||
4 | overlay-node { | ||
5 | |||
6 | /* test bus */ | ||
7 | selftestbus: test-bus { | ||
8 | compatible = "simple-bus"; | ||
9 | #address-cells = <1>; | ||
10 | #size-cells = <0>; | ||
11 | |||
12 | selftest100: test-selftest100 { | ||
13 | compatible = "selftest"; | ||
14 | status = "okay"; | ||
15 | reg = <100>; | ||
16 | }; | ||
17 | |||
18 | selftest101: test-selftest101 { | ||
19 | compatible = "selftest"; | ||
20 | status = "disabled"; | ||
21 | reg = <101>; | ||
22 | }; | ||
23 | |||
24 | selftest0: test-selftest0 { | ||
25 | compatible = "selftest"; | ||
26 | status = "disabled"; | ||
27 | reg = <0>; | ||
28 | }; | ||
29 | |||
30 | selftest1: test-selftest1 { | ||
31 | compatible = "selftest"; | ||
32 | status = "okay"; | ||
33 | reg = <1>; | ||
34 | }; | ||
35 | |||
36 | selftest2: test-selftest2 { | ||
37 | compatible = "selftest"; | ||
38 | status = "disabled"; | ||
39 | reg = <2>; | ||
40 | }; | ||
41 | |||
42 | selftest3: test-selftest3 { | ||
43 | compatible = "selftest"; | ||
44 | status = "okay"; | ||
45 | reg = <3>; | ||
46 | }; | ||
47 | |||
48 | selftest5: test-selftest5 { | ||
49 | compatible = "selftest"; | ||
50 | status = "disabled"; | ||
51 | reg = <5>; | ||
52 | }; | ||
53 | |||
54 | selftest6: test-selftest6 { | ||
55 | compatible = "selftest"; | ||
56 | status = "disabled"; | ||
57 | reg = <6>; | ||
58 | }; | ||
59 | |||
60 | selftest7: test-selftest7 { | ||
61 | compatible = "selftest"; | ||
62 | status = "disabled"; | ||
63 | reg = <7>; | ||
64 | }; | ||
65 | |||
66 | selftest8: test-selftest8 { | ||
67 | compatible = "selftest"; | ||
68 | status = "disabled"; | ||
69 | reg = <8>; | ||
70 | }; | ||
71 | }; | ||
72 | }; | ||
73 | |||
74 | /* test enable using absolute target path */ | ||
75 | overlay0 { | ||
76 | fragment@0 { | ||
77 | target-path = "/testcase-data/overlay-node/test-bus/test-selftest0"; | ||
78 | __overlay__ { | ||
79 | status = "okay"; | ||
80 | }; | ||
81 | }; | ||
82 | }; | ||
83 | |||
84 | /* test disable using absolute target path */ | ||
85 | overlay1 { | ||
86 | fragment@0 { | ||
87 | target-path = "/testcase-data/overlay-node/test-bus/test-selftest1"; | ||
88 | __overlay__ { | ||
89 | status = "disabled"; | ||
90 | }; | ||
91 | }; | ||
92 | }; | ||
93 | |||
94 | /* test enable using label */ | ||
95 | overlay2 { | ||
96 | fragment@0 { | ||
97 | target = <&selftest2>; | ||
98 | __overlay__ { | ||
99 | status = "okay"; | ||
100 | }; | ||
101 | }; | ||
102 | }; | ||
103 | |||
104 | /* test disable using label */ | ||
105 | overlay3 { | ||
106 | fragment@0 { | ||
107 | target = <&selftest3>; | ||
108 | __overlay__ { | ||
109 | status = "disabled"; | ||
110 | }; | ||
111 | }; | ||
112 | }; | ||
113 | |||
114 | /* test insertion of a full node */ | ||
115 | overlay4 { | ||
116 | fragment@0 { | ||
117 | target = <&selftestbus>; | ||
118 | __overlay__ { | ||
119 | |||
120 | /* suppress DTC warning */ | ||
121 | #address-cells = <1>; | ||
122 | #size-cells = <0>; | ||
123 | |||
124 | test-selftest4 { | ||
125 | compatible = "selftest"; | ||
126 | status = "okay"; | ||
127 | reg = <4>; | ||
128 | }; | ||
129 | }; | ||
130 | }; | ||
131 | }; | ||
132 | |||
133 | /* test overlay apply revert */ | ||
134 | overlay5 { | ||
135 | fragment@0 { | ||
136 | target-path = "/testcase-data/overlay-node/test-bus/test-selftest5"; | ||
137 | __overlay__ { | ||
138 | status = "okay"; | ||
139 | }; | ||
140 | }; | ||
141 | }; | ||
142 | |||
143 | /* test overlays application and removal in sequence */ | ||
144 | overlay6 { | ||
145 | fragment@0 { | ||
146 | target-path = "/testcase-data/overlay-node/test-bus/test-selftest6"; | ||
147 | __overlay__ { | ||
148 | status = "okay"; | ||
149 | }; | ||
150 | }; | ||
151 | }; | ||
152 | overlay7 { | ||
153 | fragment@0 { | ||
154 | target-path = "/testcase-data/overlay-node/test-bus/test-selftest7"; | ||
155 | __overlay__ { | ||
156 | status = "okay"; | ||
157 | }; | ||
158 | }; | ||
159 | }; | ||
160 | |||
161 | /* test overlays application and removal in bad sequence */ | ||
162 | overlay8 { | ||
163 | fragment@0 { | ||
164 | target-path = "/testcase-data/overlay-node/test-bus/test-selftest8"; | ||
165 | __overlay__ { | ||
166 | status = "okay"; | ||
167 | }; | ||
168 | }; | ||
169 | }; | ||
170 | overlay9 { | ||
171 | fragment@0 { | ||
172 | target-path = "/testcase-data/overlay-node/test-bus/test-selftest8"; | ||
173 | __overlay__ { | ||
174 | property-foo = "bar"; | ||
175 | }; | ||
176 | }; | ||
177 | }; | ||
178 | |||
179 | }; | ||
180 | }; | ||
diff --git a/drivers/of/testcase-data/tests-phandle.dtsi b/drivers/of/unittest-data/tests-phandle.dtsi index 5b1527e8a7fb..5b1527e8a7fb 100644 --- a/drivers/of/testcase-data/tests-phandle.dtsi +++ b/drivers/of/unittest-data/tests-phandle.dtsi | |||
diff --git a/drivers/of/testcase-data/tests-platform.dtsi b/drivers/of/unittest-data/tests-platform.dtsi index eb20eeb2b062..eb20eeb2b062 100644 --- a/drivers/of/testcase-data/tests-platform.dtsi +++ b/drivers/of/unittest-data/tests-platform.dtsi | |||
diff --git a/drivers/of/selftest.c b/drivers/of/unittest.c index e2d79afa9dc6..844838e11ef1 100644 --- a/drivers/of/selftest.c +++ b/drivers/of/unittest.c | |||
@@ -17,6 +17,8 @@ | |||
17 | #include <linux/mutex.h> | 17 | #include <linux/mutex.h> |
18 | #include <linux/slab.h> | 18 | #include <linux/slab.h> |
19 | #include <linux/device.h> | 19 | #include <linux/device.h> |
20 | #include <linux/platform_device.h> | ||
21 | #include <linux/of_platform.h> | ||
20 | 22 | ||
21 | #include "of_private.h" | 23 | #include "of_private.h" |
22 | 24 | ||
@@ -30,19 +32,22 @@ static struct device_node *nodes[NO_OF_NODES]; | |||
30 | static int last_node_index; | 32 | static int last_node_index; |
31 | static bool selftest_live_tree; | 33 | static bool selftest_live_tree; |
32 | 34 | ||
33 | #define selftest(result, fmt, ...) { \ | 35 | #define selftest(result, fmt, ...) ({ \ |
34 | if (!(result)) { \ | 36 | bool failed = !(result); \ |
37 | if (failed) { \ | ||
35 | selftest_results.failed++; \ | 38 | selftest_results.failed++; \ |
36 | pr_err("FAIL %s():%i " fmt, __func__, __LINE__, ##__VA_ARGS__); \ | 39 | pr_err("FAIL %s():%i " fmt, __func__, __LINE__, ##__VA_ARGS__); \ |
37 | } else { \ | 40 | } else { \ |
38 | selftest_results.passed++; \ | 41 | selftest_results.passed++; \ |
39 | pr_debug("pass %s():%i\n", __func__, __LINE__); \ | 42 | pr_debug("pass %s():%i\n", __func__, __LINE__); \ |
40 | } \ | 43 | } \ |
41 | } | 44 | failed; \ |
45 | }) | ||
42 | 46 | ||
43 | static void __init of_selftest_find_node_by_name(void) | 47 | static void __init of_selftest_find_node_by_name(void) |
44 | { | 48 | { |
45 | struct device_node *np; | 49 | struct device_node *np; |
50 | const char *options; | ||
46 | 51 | ||
47 | np = of_find_node_by_path("/testcase-data"); | 52 | np = of_find_node_by_path("/testcase-data"); |
48 | selftest(np && !strcmp("/testcase-data", np->full_name), | 53 | selftest(np && !strcmp("/testcase-data", np->full_name), |
@@ -83,6 +88,35 @@ static void __init of_selftest_find_node_by_name(void) | |||
83 | np = of_find_node_by_path("testcase-alias/missing-path"); | 88 | np = of_find_node_by_path("testcase-alias/missing-path"); |
84 | selftest(!np, "non-existent alias with relative path returned node %s\n", np->full_name); | 89 | selftest(!np, "non-existent alias with relative path returned node %s\n", np->full_name); |
85 | of_node_put(np); | 90 | of_node_put(np); |
91 | |||
92 | np = of_find_node_opts_by_path("/testcase-data:testoption", &options); | ||
93 | selftest(np && !strcmp("testoption", options), | ||
94 | "option path test failed\n"); | ||
95 | of_node_put(np); | ||
96 | |||
97 | np = of_find_node_opts_by_path("/testcase-data:testoption", NULL); | ||
98 | selftest(np, "NULL option path test failed\n"); | ||
99 | of_node_put(np); | ||
100 | |||
101 | np = of_find_node_opts_by_path("testcase-alias:testaliasoption", | ||
102 | &options); | ||
103 | selftest(np && !strcmp("testaliasoption", options), | ||
104 | "option alias path test failed\n"); | ||
105 | of_node_put(np); | ||
106 | |||
107 | np = of_find_node_opts_by_path("testcase-alias:testaliasoption", NULL); | ||
108 | selftest(np, "NULL option alias path test failed\n"); | ||
109 | of_node_put(np); | ||
110 | |||
111 | options = "testoption"; | ||
112 | np = of_find_node_opts_by_path("testcase-alias", &options); | ||
113 | selftest(np && !options, "option clearing test failed\n"); | ||
114 | of_node_put(np); | ||
115 | |||
116 | options = "testoption"; | ||
117 | np = of_find_node_opts_by_path("/", &options); | ||
118 | selftest(np && !options, "option clearing root node test failed\n"); | ||
119 | of_node_put(np); | ||
86 | } | 120 | } |
87 | 121 | ||
88 | static void __init of_selftest_dynamic(void) | 122 | static void __init of_selftest_dynamic(void) |
@@ -148,7 +182,7 @@ static void __init of_selftest_dynamic(void) | |||
148 | 182 | ||
149 | static int __init of_selftest_check_node_linkage(struct device_node *np) | 183 | static int __init of_selftest_check_node_linkage(struct device_node *np) |
150 | { | 184 | { |
151 | struct device_node *child, *allnext_index = np; | 185 | struct device_node *child; |
152 | int count = 0, rc; | 186 | int count = 0, rc; |
153 | 187 | ||
154 | for_each_child_of_node(np, child) { | 188 | for_each_child_of_node(np, child) { |
@@ -158,14 +192,6 @@ static int __init of_selftest_check_node_linkage(struct device_node *np) | |||
158 | return -EINVAL; | 192 | return -EINVAL; |
159 | } | 193 | } |
160 | 194 | ||
161 | while (allnext_index && allnext_index != child) | ||
162 | allnext_index = allnext_index->allnext; | ||
163 | if (allnext_index != child) { | ||
164 | pr_err("Node %s is ordered differently in sibling and allnode lists\n", | ||
165 | child->name); | ||
166 | return -EINVAL; | ||
167 | } | ||
168 | |||
169 | rc = of_selftest_check_node_linkage(child); | 195 | rc = of_selftest_check_node_linkage(child); |
170 | if (rc < 0) | 196 | if (rc < 0) |
171 | return rc; | 197 | return rc; |
@@ -180,12 +206,12 @@ static void __init of_selftest_check_tree_linkage(void) | |||
180 | struct device_node *np; | 206 | struct device_node *np; |
181 | int allnode_count = 0, child_count; | 207 | int allnode_count = 0, child_count; |
182 | 208 | ||
183 | if (!of_allnodes) | 209 | if (!of_root) |
184 | return; | 210 | return; |
185 | 211 | ||
186 | for_each_of_allnodes(np) | 212 | for_each_of_allnodes(np) |
187 | allnode_count++; | 213 | allnode_count++; |
188 | child_count = of_selftest_check_node_linkage(of_allnodes); | 214 | child_count = of_selftest_check_node_linkage(of_root); |
189 | 215 | ||
190 | selftest(child_count > 0, "Device node data structure is corrupted\n"); | 216 | selftest(child_count > 0, "Device node data structure is corrupted\n"); |
191 | selftest(child_count == allnode_count, "allnodes list size (%i) doesn't match" | 217 | selftest(child_count == allnode_count, "allnodes list size (%i) doesn't match" |
@@ -451,15 +477,15 @@ static void __init of_selftest_changeset(void) | |||
451 | struct property *ppadd, padd = { .name = "prop-add", .length = 0, .value = "" }; | 477 | struct property *ppadd, padd = { .name = "prop-add", .length = 0, .value = "" }; |
452 | struct property *ppupdate, pupdate = { .name = "prop-update", .length = 5, .value = "abcd" }; | 478 | struct property *ppupdate, pupdate = { .name = "prop-update", .length = 5, .value = "abcd" }; |
453 | struct property *ppremove; | 479 | struct property *ppremove; |
454 | struct device_node *n1, *n2, *n21, *nremove, *parent; | 480 | struct device_node *n1, *n2, *n21, *nremove, *parent, *np; |
455 | struct of_changeset chgset; | 481 | struct of_changeset chgset; |
456 | 482 | ||
457 | of_changeset_init(&chgset); | 483 | of_changeset_init(&chgset); |
458 | n1 = __of_node_alloc("/testcase-data/changeset/n1", GFP_KERNEL); | 484 | n1 = __of_node_dup(NULL, "/testcase-data/changeset/n1"); |
459 | selftest(n1, "testcase setup failure\n"); | 485 | selftest(n1, "testcase setup failure\n"); |
460 | n2 = __of_node_alloc("/testcase-data/changeset/n2", GFP_KERNEL); | 486 | n2 = __of_node_dup(NULL, "/testcase-data/changeset/n2"); |
461 | selftest(n2, "testcase setup failure\n"); | 487 | selftest(n2, "testcase setup failure\n"); |
462 | n21 = __of_node_alloc("/testcase-data/changeset/n2/n21", GFP_KERNEL); | 488 | n21 = __of_node_dup(NULL, "%s/%s", "/testcase-data/changeset/n2", "n21"); |
463 | selftest(n21, "testcase setup failure %p\n", n21); | 489 | selftest(n21, "testcase setup failure %p\n", n21); |
464 | nremove = of_find_node_by_path("/testcase-data/changeset/node-remove"); | 490 | nremove = of_find_node_by_path("/testcase-data/changeset/node-remove"); |
465 | selftest(nremove, "testcase setup failure\n"); | 491 | selftest(nremove, "testcase setup failure\n"); |
@@ -487,6 +513,11 @@ static void __init of_selftest_changeset(void) | |||
487 | selftest(!of_changeset_apply(&chgset), "apply failed\n"); | 513 | selftest(!of_changeset_apply(&chgset), "apply failed\n"); |
488 | mutex_unlock(&of_mutex); | 514 | mutex_unlock(&of_mutex); |
489 | 515 | ||
516 | /* Make sure node names are constructed correctly */ | ||
517 | selftest((np = of_find_node_by_path("/testcase-data/changeset/n2/n21")), | ||
518 | "'%s' not added\n", n21->full_name); | ||
519 | of_node_put(np); | ||
520 | |||
490 | mutex_lock(&of_mutex); | 521 | mutex_lock(&of_mutex); |
491 | selftest(!of_changeset_revert(&chgset), "revert failed\n"); | 522 | selftest(!of_changeset_revert(&chgset), "revert failed\n"); |
492 | mutex_unlock(&of_mutex); | 523 | mutex_unlock(&of_mutex); |
@@ -702,10 +733,13 @@ static void __init of_selftest_match_node(void) | |||
702 | } | 733 | } |
703 | } | 734 | } |
704 | 735 | ||
736 | struct device test_bus = { | ||
737 | .init_name = "unittest-bus", | ||
738 | }; | ||
705 | static void __init of_selftest_platform_populate(void) | 739 | static void __init of_selftest_platform_populate(void) |
706 | { | 740 | { |
707 | int irq; | 741 | int irq, rc; |
708 | struct device_node *np, *child; | 742 | struct device_node *np, *child, *grandchild; |
709 | struct platform_device *pdev; | 743 | struct platform_device *pdev; |
710 | struct of_device_id match[] = { | 744 | struct of_device_id match[] = { |
711 | { .compatible = "test-device", }, | 745 | { .compatible = "test-device", }, |
@@ -730,20 +764,32 @@ static void __init of_selftest_platform_populate(void) | |||
730 | irq = platform_get_irq(pdev, 0); | 764 | irq = platform_get_irq(pdev, 0); |
731 | selftest(irq < 0 && irq != -EPROBE_DEFER, "device parsing error failed - %d\n", irq); | 765 | selftest(irq < 0 && irq != -EPROBE_DEFER, "device parsing error failed - %d\n", irq); |
732 | 766 | ||
733 | np = of_find_node_by_path("/testcase-data/platform-tests"); | 767 | if (selftest(np = of_find_node_by_path("/testcase-data/platform-tests"), |
734 | if (!np) { | 768 | "No testcase data in device tree\n")); |
735 | pr_err("No testcase data in device tree\n"); | 769 | return; |
770 | |||
771 | if (selftest(!(rc = device_register(&test_bus)), | ||
772 | "testbus registration failed; rc=%i\n", rc)); | ||
736 | return; | 773 | return; |
737 | } | ||
738 | 774 | ||
739 | for_each_child_of_node(np, child) { | 775 | for_each_child_of_node(np, child) { |
740 | struct device_node *grandchild; | 776 | of_platform_populate(child, match, NULL, &test_bus); |
741 | of_platform_populate(child, match, NULL, NULL); | ||
742 | for_each_child_of_node(child, grandchild) | 777 | for_each_child_of_node(child, grandchild) |
743 | selftest(of_find_device_by_node(grandchild), | 778 | selftest(of_find_device_by_node(grandchild), |
744 | "Could not create device for node '%s'\n", | 779 | "Could not create device for node '%s'\n", |
745 | grandchild->name); | 780 | grandchild->name); |
746 | } | 781 | } |
782 | |||
783 | of_platform_depopulate(&test_bus); | ||
784 | for_each_child_of_node(np, child) { | ||
785 | for_each_child_of_node(child, grandchild) | ||
786 | selftest(!of_find_device_by_node(grandchild), | ||
787 | "device didn't get destroyed '%s'\n", | ||
788 | grandchild->name); | ||
789 | } | ||
790 | |||
791 | device_unregister(&test_bus); | ||
792 | of_node_put(np); | ||
747 | } | 793 | } |
748 | 794 | ||
749 | /** | 795 | /** |
@@ -775,33 +821,29 @@ static void update_node_properties(struct device_node *np, | |||
775 | */ | 821 | */ |
776 | static int attach_node_and_children(struct device_node *np) | 822 | static int attach_node_and_children(struct device_node *np) |
777 | { | 823 | { |
778 | struct device_node *next, *root = np, *dup; | 824 | struct device_node *next, *dup, *child; |
779 | 825 | ||
780 | /* skip root node */ | 826 | dup = of_find_node_by_path(np->full_name); |
781 | np = np->child; | 827 | if (dup) { |
782 | /* storing a copy in temporary node */ | 828 | update_node_properties(np, dup); |
783 | dup = np; | 829 | return 0; |
830 | } | ||
784 | 831 | ||
785 | while (dup) { | 832 | /* Children of the root need to be remembered for removal */ |
833 | if (np->parent == of_root) { | ||
786 | if (WARN_ON(last_node_index >= NO_OF_NODES)) | 834 | if (WARN_ON(last_node_index >= NO_OF_NODES)) |
787 | return -EINVAL; | 835 | return -EINVAL; |
788 | nodes[last_node_index++] = dup; | 836 | nodes[last_node_index++] = np; |
789 | dup = dup->sibling; | ||
790 | } | 837 | } |
791 | dup = NULL; | ||
792 | 838 | ||
793 | while (np) { | 839 | child = np->child; |
794 | next = np->allnext; | 840 | np->child = NULL; |
795 | dup = of_find_node_by_path(np->full_name); | 841 | np->sibling = NULL; |
796 | if (dup) | 842 | of_attach_node(np); |
797 | update_node_properties(np, dup); | 843 | while (child) { |
798 | else { | 844 | next = child->sibling; |
799 | np->child = NULL; | 845 | attach_node_and_children(child); |
800 | if (np->parent == root) | 846 | child = next; |
801 | np->parent = of_allnodes; | ||
802 | of_attach_node(np); | ||
803 | } | ||
804 | np = next; | ||
805 | } | 847 | } |
806 | 848 | ||
807 | return 0; | 849 | return 0; |
@@ -846,10 +888,10 @@ static int __init selftest_data_add(void) | |||
846 | return -EINVAL; | 888 | return -EINVAL; |
847 | } | 889 | } |
848 | 890 | ||
849 | if (!of_allnodes) { | 891 | if (!of_root) { |
850 | /* enabling flag for removing nodes */ | 892 | /* enabling flag for removing nodes */ |
851 | selftest_live_tree = true; | 893 | selftest_live_tree = true; |
852 | of_allnodes = selftest_data_node; | 894 | of_root = selftest_data_node; |
853 | 895 | ||
854 | for_each_of_allnodes(np) | 896 | for_each_of_allnodes(np) |
855 | __of_attach_node_sysfs(np); | 897 | __of_attach_node_sysfs(np); |
@@ -859,7 +901,14 @@ static int __init selftest_data_add(void) | |||
859 | } | 901 | } |
860 | 902 | ||
861 | /* attach the sub-tree to live tree */ | 903 | /* attach the sub-tree to live tree */ |
862 | return attach_node_and_children(selftest_data_node); | 904 | np = selftest_data_node->child; |
905 | while (np) { | ||
906 | struct device_node *next = np->sibling; | ||
907 | np->parent = of_root; | ||
908 | attach_node_and_children(np); | ||
909 | np = next; | ||
910 | } | ||
911 | return 0; | ||
863 | } | 912 | } |
864 | 913 | ||
865 | /** | 914 | /** |
@@ -889,10 +938,10 @@ static void selftest_data_remove(void) | |||
889 | of_node_put(of_chosen); | 938 | of_node_put(of_chosen); |
890 | of_aliases = NULL; | 939 | of_aliases = NULL; |
891 | of_chosen = NULL; | 940 | of_chosen = NULL; |
892 | for_each_child_of_node(of_allnodes, np) | 941 | for_each_child_of_node(of_root, np) |
893 | detach_node_and_children(np); | 942 | detach_node_and_children(np); |
894 | __of_detach_node_sysfs(of_allnodes); | 943 | __of_detach_node_sysfs(of_root); |
895 | of_allnodes = NULL; | 944 | of_root = NULL; |
896 | return; | 945 | return; |
897 | } | 946 | } |
898 | 947 | ||
@@ -915,6 +964,483 @@ static void selftest_data_remove(void) | |||
915 | } | 964 | } |
916 | } | 965 | } |
917 | 966 | ||
967 | #ifdef CONFIG_OF_OVERLAY | ||
968 | |||
969 | static int selftest_probe(struct platform_device *pdev) | ||
970 | { | ||
971 | struct device *dev = &pdev->dev; | ||
972 | struct device_node *np = dev->of_node; | ||
973 | |||
974 | if (np == NULL) { | ||
975 | dev_err(dev, "No OF data for device\n"); | ||
976 | return -EINVAL; | ||
977 | |||
978 | } | ||
979 | |||
980 | dev_dbg(dev, "%s for node @%s\n", __func__, np->full_name); | ||
981 | return 0; | ||
982 | } | ||
983 | |||
984 | static int selftest_remove(struct platform_device *pdev) | ||
985 | { | ||
986 | struct device *dev = &pdev->dev; | ||
987 | struct device_node *np = dev->of_node; | ||
988 | |||
989 | dev_dbg(dev, "%s for node @%s\n", __func__, np->full_name); | ||
990 | return 0; | ||
991 | } | ||
992 | |||
993 | static struct of_device_id selftest_match[] = { | ||
994 | { .compatible = "selftest", }, | ||
995 | {}, | ||
996 | }; | ||
997 | |||
998 | static struct platform_driver selftest_driver = { | ||
999 | .probe = selftest_probe, | ||
1000 | .remove = selftest_remove, | ||
1001 | .driver = { | ||
1002 | .name = "selftest", | ||
1003 | .owner = THIS_MODULE, | ||
1004 | .of_match_table = of_match_ptr(selftest_match), | ||
1005 | }, | ||
1006 | }; | ||
1007 | |||
1008 | /* get the platform device instantiated at the path */ | ||
1009 | static struct platform_device *of_path_to_platform_device(const char *path) | ||
1010 | { | ||
1011 | struct device_node *np; | ||
1012 | struct platform_device *pdev; | ||
1013 | |||
1014 | np = of_find_node_by_path(path); | ||
1015 | if (np == NULL) | ||
1016 | return NULL; | ||
1017 | |||
1018 | pdev = of_find_device_by_node(np); | ||
1019 | of_node_put(np); | ||
1020 | |||
1021 | return pdev; | ||
1022 | } | ||
1023 | |||
1024 | /* find out if a platform device exists at that path */ | ||
1025 | static int of_path_platform_device_exists(const char *path) | ||
1026 | { | ||
1027 | struct platform_device *pdev; | ||
1028 | |||
1029 | pdev = of_path_to_platform_device(path); | ||
1030 | platform_device_put(pdev); | ||
1031 | return pdev != NULL; | ||
1032 | } | ||
1033 | |||
1034 | static const char *selftest_path(int nr) | ||
1035 | { | ||
1036 | static char buf[256]; | ||
1037 | |||
1038 | snprintf(buf, sizeof(buf) - 1, | ||
1039 | "/testcase-data/overlay-node/test-bus/test-selftest%d", nr); | ||
1040 | buf[sizeof(buf) - 1] = '\0'; | ||
1041 | |||
1042 | return buf; | ||
1043 | } | ||
1044 | |||
1045 | static const char *overlay_path(int nr) | ||
1046 | { | ||
1047 | static char buf[256]; | ||
1048 | |||
1049 | snprintf(buf, sizeof(buf) - 1, | ||
1050 | "/testcase-data/overlay%d", nr); | ||
1051 | buf[sizeof(buf) - 1] = '\0'; | ||
1052 | |||
1053 | return buf; | ||
1054 | } | ||
1055 | |||
1056 | static const char *bus_path = "/testcase-data/overlay-node/test-bus"; | ||
1057 | |||
1058 | static int of_selftest_apply_overlay(int selftest_nr, int overlay_nr, | ||
1059 | int *overlay_id) | ||
1060 | { | ||
1061 | struct device_node *np = NULL; | ||
1062 | int ret, id = -1; | ||
1063 | |||
1064 | np = of_find_node_by_path(overlay_path(overlay_nr)); | ||
1065 | if (np == NULL) { | ||
1066 | selftest(0, "could not find overlay node @\"%s\"\n", | ||
1067 | overlay_path(overlay_nr)); | ||
1068 | ret = -EINVAL; | ||
1069 | goto out; | ||
1070 | } | ||
1071 | |||
1072 | ret = of_overlay_create(np); | ||
1073 | if (ret < 0) { | ||
1074 | selftest(0, "could not create overlay from \"%s\"\n", | ||
1075 | overlay_path(overlay_nr)); | ||
1076 | goto out; | ||
1077 | } | ||
1078 | id = ret; | ||
1079 | |||
1080 | ret = 0; | ||
1081 | |||
1082 | out: | ||
1083 | of_node_put(np); | ||
1084 | |||
1085 | if (overlay_id) | ||
1086 | *overlay_id = id; | ||
1087 | |||
1088 | return ret; | ||
1089 | } | ||
1090 | |||
1091 | /* apply an overlay while checking before and after states */ | ||
1092 | static int of_selftest_apply_overlay_check(int overlay_nr, int selftest_nr, | ||
1093 | int before, int after) | ||
1094 | { | ||
1095 | int ret; | ||
1096 | |||
1097 | /* selftest device must not be in before state */ | ||
1098 | if (of_path_platform_device_exists(selftest_path(selftest_nr)) | ||
1099 | != before) { | ||
1100 | selftest(0, "overlay @\"%s\" with device @\"%s\" %s\n", | ||
1101 | overlay_path(overlay_nr), | ||
1102 | selftest_path(selftest_nr), | ||
1103 | !before ? "enabled" : "disabled"); | ||
1104 | return -EINVAL; | ||
1105 | } | ||
1106 | |||
1107 | ret = of_selftest_apply_overlay(overlay_nr, selftest_nr, NULL); | ||
1108 | if (ret != 0) { | ||
1109 | /* of_selftest_apply_overlay already called selftest() */ | ||
1110 | return ret; | ||
1111 | } | ||
1112 | |||
1113 | /* selftest device must be to set to after state */ | ||
1114 | if (of_path_platform_device_exists(selftest_path(selftest_nr)) | ||
1115 | != after) { | ||
1116 | selftest(0, "overlay @\"%s\" failed to create @\"%s\" %s\n", | ||
1117 | overlay_path(overlay_nr), | ||
1118 | selftest_path(selftest_nr), | ||
1119 | !after ? "enabled" : "disabled"); | ||
1120 | return -EINVAL; | ||
1121 | } | ||
1122 | |||
1123 | return 0; | ||
1124 | } | ||
1125 | |||
1126 | /* apply an overlay and then revert it while checking before, after states */ | ||
1127 | static int of_selftest_apply_revert_overlay_check(int overlay_nr, | ||
1128 | int selftest_nr, int before, int after) | ||
1129 | { | ||
1130 | int ret, ov_id; | ||
1131 | |||
1132 | /* selftest device must be in before state */ | ||
1133 | if (of_path_platform_device_exists(selftest_path(selftest_nr)) | ||
1134 | != before) { | ||
1135 | selftest(0, "overlay @\"%s\" with device @\"%s\" %s\n", | ||
1136 | overlay_path(overlay_nr), | ||
1137 | selftest_path(selftest_nr), | ||
1138 | !before ? "enabled" : "disabled"); | ||
1139 | return -EINVAL; | ||
1140 | } | ||
1141 | |||
1142 | /* apply the overlay */ | ||
1143 | ret = of_selftest_apply_overlay(overlay_nr, selftest_nr, &ov_id); | ||
1144 | if (ret != 0) { | ||
1145 | /* of_selftest_apply_overlay already called selftest() */ | ||
1146 | return ret; | ||
1147 | } | ||
1148 | |||
1149 | /* selftest device must be in after state */ | ||
1150 | if (of_path_platform_device_exists(selftest_path(selftest_nr)) | ||
1151 | != after) { | ||
1152 | selftest(0, "overlay @\"%s\" failed to create @\"%s\" %s\n", | ||
1153 | overlay_path(overlay_nr), | ||
1154 | selftest_path(selftest_nr), | ||
1155 | !after ? "enabled" : "disabled"); | ||
1156 | return -EINVAL; | ||
1157 | } | ||
1158 | |||
1159 | ret = of_overlay_destroy(ov_id); | ||
1160 | if (ret != 0) { | ||
1161 | selftest(0, "overlay @\"%s\" failed to be destroyed @\"%s\"\n", | ||
1162 | overlay_path(overlay_nr), | ||
1163 | selftest_path(selftest_nr)); | ||
1164 | return ret; | ||
1165 | } | ||
1166 | |||
1167 | /* selftest device must be again in before state */ | ||
1168 | if (of_path_platform_device_exists(selftest_path(selftest_nr)) | ||
1169 | != before) { | ||
1170 | selftest(0, "overlay @\"%s\" with device @\"%s\" %s\n", | ||
1171 | overlay_path(overlay_nr), | ||
1172 | selftest_path(selftest_nr), | ||
1173 | !before ? "enabled" : "disabled"); | ||
1174 | return -EINVAL; | ||
1175 | } | ||
1176 | |||
1177 | return 0; | ||
1178 | } | ||
1179 | |||
1180 | /* test activation of device */ | ||
1181 | static void of_selftest_overlay_0(void) | ||
1182 | { | ||
1183 | int ret; | ||
1184 | |||
1185 | /* device should enable */ | ||
1186 | ret = of_selftest_apply_overlay_check(0, 0, 0, 1); | ||
1187 | if (ret != 0) | ||
1188 | return; | ||
1189 | |||
1190 | selftest(1, "overlay test %d passed\n", 0); | ||
1191 | } | ||
1192 | |||
1193 | /* test deactivation of device */ | ||
1194 | static void of_selftest_overlay_1(void) | ||
1195 | { | ||
1196 | int ret; | ||
1197 | |||
1198 | /* device should disable */ | ||
1199 | ret = of_selftest_apply_overlay_check(1, 1, 1, 0); | ||
1200 | if (ret != 0) | ||
1201 | return; | ||
1202 | |||
1203 | selftest(1, "overlay test %d passed\n", 1); | ||
1204 | } | ||
1205 | |||
1206 | /* test activation of device */ | ||
1207 | static void of_selftest_overlay_2(void) | ||
1208 | { | ||
1209 | int ret; | ||
1210 | |||
1211 | /* device should enable */ | ||
1212 | ret = of_selftest_apply_overlay_check(2, 2, 0, 1); | ||
1213 | if (ret != 0) | ||
1214 | return; | ||
1215 | |||
1216 | selftest(1, "overlay test %d passed\n", 2); | ||
1217 | } | ||
1218 | |||
1219 | /* test deactivation of device */ | ||
1220 | static void of_selftest_overlay_3(void) | ||
1221 | { | ||
1222 | int ret; | ||
1223 | |||
1224 | /* device should disable */ | ||
1225 | ret = of_selftest_apply_overlay_check(3, 3, 1, 0); | ||
1226 | if (ret != 0) | ||
1227 | return; | ||
1228 | |||
1229 | selftest(1, "overlay test %d passed\n", 3); | ||
1230 | } | ||
1231 | |||
1232 | /* test activation of a full device node */ | ||
1233 | static void of_selftest_overlay_4(void) | ||
1234 | { | ||
1235 | int ret; | ||
1236 | |||
1237 | /* device should disable */ | ||
1238 | ret = of_selftest_apply_overlay_check(4, 4, 0, 1); | ||
1239 | if (ret != 0) | ||
1240 | return; | ||
1241 | |||
1242 | selftest(1, "overlay test %d passed\n", 4); | ||
1243 | } | ||
1244 | |||
1245 | /* test overlay apply/revert sequence */ | ||
1246 | static void of_selftest_overlay_5(void) | ||
1247 | { | ||
1248 | int ret; | ||
1249 | |||
1250 | /* device should disable */ | ||
1251 | ret = of_selftest_apply_revert_overlay_check(5, 5, 0, 1); | ||
1252 | if (ret != 0) | ||
1253 | return; | ||
1254 | |||
1255 | selftest(1, "overlay test %d passed\n", 5); | ||
1256 | } | ||
1257 | |||
1258 | /* test overlay application in sequence */ | ||
1259 | static void of_selftest_overlay_6(void) | ||
1260 | { | ||
1261 | struct device_node *np; | ||
1262 | int ret, i, ov_id[2]; | ||
1263 | int overlay_nr = 6, selftest_nr = 6; | ||
1264 | int before = 0, after = 1; | ||
1265 | |||
1266 | /* selftest device must be in before state */ | ||
1267 | for (i = 0; i < 2; i++) { | ||
1268 | if (of_path_platform_device_exists( | ||
1269 | selftest_path(selftest_nr + i)) | ||
1270 | != before) { | ||
1271 | selftest(0, "overlay @\"%s\" with device @\"%s\" %s\n", | ||
1272 | overlay_path(overlay_nr + i), | ||
1273 | selftest_path(selftest_nr + i), | ||
1274 | !before ? "enabled" : "disabled"); | ||
1275 | return; | ||
1276 | } | ||
1277 | } | ||
1278 | |||
1279 | /* apply the overlays */ | ||
1280 | for (i = 0; i < 2; i++) { | ||
1281 | |||
1282 | np = of_find_node_by_path(overlay_path(overlay_nr + i)); | ||
1283 | if (np == NULL) { | ||
1284 | selftest(0, "could not find overlay node @\"%s\"\n", | ||
1285 | overlay_path(overlay_nr + i)); | ||
1286 | return; | ||
1287 | } | ||
1288 | |||
1289 | ret = of_overlay_create(np); | ||
1290 | if (ret < 0) { | ||
1291 | selftest(0, "could not create overlay from \"%s\"\n", | ||
1292 | overlay_path(overlay_nr + i)); | ||
1293 | return; | ||
1294 | } | ||
1295 | ov_id[i] = ret; | ||
1296 | } | ||
1297 | |||
1298 | for (i = 0; i < 2; i++) { | ||
1299 | /* selftest device must be in after state */ | ||
1300 | if (of_path_platform_device_exists( | ||
1301 | selftest_path(selftest_nr + i)) | ||
1302 | != after) { | ||
1303 | selftest(0, "overlay @\"%s\" failed @\"%s\" %s\n", | ||
1304 | overlay_path(overlay_nr + i), | ||
1305 | selftest_path(selftest_nr + i), | ||
1306 | !after ? "enabled" : "disabled"); | ||
1307 | return; | ||
1308 | } | ||
1309 | } | ||
1310 | |||
1311 | for (i = 1; i >= 0; i--) { | ||
1312 | ret = of_overlay_destroy(ov_id[i]); | ||
1313 | if (ret != 0) { | ||
1314 | selftest(0, "overlay @\"%s\" failed destroy @\"%s\"\n", | ||
1315 | overlay_path(overlay_nr + i), | ||
1316 | selftest_path(selftest_nr + i)); | ||
1317 | return; | ||
1318 | } | ||
1319 | } | ||
1320 | |||
1321 | for (i = 0; i < 2; i++) { | ||
1322 | /* selftest device must be again in before state */ | ||
1323 | if (of_path_platform_device_exists( | ||
1324 | selftest_path(selftest_nr + i)) | ||
1325 | != before) { | ||
1326 | selftest(0, "overlay @\"%s\" with device @\"%s\" %s\n", | ||
1327 | overlay_path(overlay_nr + i), | ||
1328 | selftest_path(selftest_nr + i), | ||
1329 | !before ? "enabled" : "disabled"); | ||
1330 | return; | ||
1331 | } | ||
1332 | } | ||
1333 | |||
1334 | selftest(1, "overlay test %d passed\n", 6); | ||
1335 | } | ||
1336 | |||
1337 | /* test overlay application in sequence */ | ||
1338 | static void of_selftest_overlay_8(void) | ||
1339 | { | ||
1340 | struct device_node *np; | ||
1341 | int ret, i, ov_id[2]; | ||
1342 | int overlay_nr = 8, selftest_nr = 8; | ||
1343 | |||
1344 | /* we don't care about device state in this test */ | ||
1345 | |||
1346 | /* apply the overlays */ | ||
1347 | for (i = 0; i < 2; i++) { | ||
1348 | |||
1349 | np = of_find_node_by_path(overlay_path(overlay_nr + i)); | ||
1350 | if (np == NULL) { | ||
1351 | selftest(0, "could not find overlay node @\"%s\"\n", | ||
1352 | overlay_path(overlay_nr + i)); | ||
1353 | return; | ||
1354 | } | ||
1355 | |||
1356 | ret = of_overlay_create(np); | ||
1357 | if (ret < 0) { | ||
1358 | selftest(0, "could not create overlay from \"%s\"\n", | ||
1359 | overlay_path(overlay_nr + i)); | ||
1360 | return; | ||
1361 | } | ||
1362 | ov_id[i] = ret; | ||
1363 | } | ||
1364 | |||
1365 | /* now try to remove first overlay (it should fail) */ | ||
1366 | ret = of_overlay_destroy(ov_id[0]); | ||
1367 | if (ret == 0) { | ||
1368 | selftest(0, "overlay @\"%s\" was destroyed @\"%s\"\n", | ||
1369 | overlay_path(overlay_nr + 0), | ||
1370 | selftest_path(selftest_nr)); | ||
1371 | return; | ||
1372 | } | ||
1373 | |||
1374 | /* removing them in order should work */ | ||
1375 | for (i = 1; i >= 0; i--) { | ||
1376 | ret = of_overlay_destroy(ov_id[i]); | ||
1377 | if (ret != 0) { | ||
1378 | selftest(0, "overlay @\"%s\" not destroyed @\"%s\"\n", | ||
1379 | overlay_path(overlay_nr + i), | ||
1380 | selftest_path(selftest_nr)); | ||
1381 | return; | ||
1382 | } | ||
1383 | } | ||
1384 | |||
1385 | selftest(1, "overlay test %d passed\n", 8); | ||
1386 | } | ||
1387 | |||
1388 | static void __init of_selftest_overlay(void) | ||
1389 | { | ||
1390 | struct device_node *bus_np = NULL; | ||
1391 | int ret; | ||
1392 | |||
1393 | ret = platform_driver_register(&selftest_driver); | ||
1394 | if (ret != 0) { | ||
1395 | selftest(0, "could not register selftest driver\n"); | ||
1396 | goto out; | ||
1397 | } | ||
1398 | |||
1399 | bus_np = of_find_node_by_path(bus_path); | ||
1400 | if (bus_np == NULL) { | ||
1401 | selftest(0, "could not find bus_path \"%s\"\n", bus_path); | ||
1402 | goto out; | ||
1403 | } | ||
1404 | |||
1405 | ret = of_platform_populate(bus_np, of_default_bus_match_table, | ||
1406 | NULL, NULL); | ||
1407 | if (ret != 0) { | ||
1408 | selftest(0, "could not populate bus @ \"%s\"\n", bus_path); | ||
1409 | goto out; | ||
1410 | } | ||
1411 | |||
1412 | if (!of_path_platform_device_exists(selftest_path(100))) { | ||
1413 | selftest(0, "could not find selftest0 @ \"%s\"\n", | ||
1414 | selftest_path(100)); | ||
1415 | goto out; | ||
1416 | } | ||
1417 | |||
1418 | if (of_path_platform_device_exists(selftest_path(101))) { | ||
1419 | selftest(0, "selftest1 @ \"%s\" should not exist\n", | ||
1420 | selftest_path(101)); | ||
1421 | goto out; | ||
1422 | } | ||
1423 | |||
1424 | selftest(1, "basic infrastructure of overlays passed"); | ||
1425 | |||
1426 | /* tests in sequence */ | ||
1427 | of_selftest_overlay_0(); | ||
1428 | of_selftest_overlay_1(); | ||
1429 | of_selftest_overlay_2(); | ||
1430 | of_selftest_overlay_3(); | ||
1431 | of_selftest_overlay_4(); | ||
1432 | of_selftest_overlay_5(); | ||
1433 | of_selftest_overlay_6(); | ||
1434 | of_selftest_overlay_8(); | ||
1435 | |||
1436 | out: | ||
1437 | of_node_put(bus_np); | ||
1438 | } | ||
1439 | |||
1440 | #else | ||
1441 | static inline void __init of_selftest_overlay(void) { } | ||
1442 | #endif | ||
1443 | |||
918 | static int __init of_selftest(void) | 1444 | static int __init of_selftest(void) |
919 | { | 1445 | { |
920 | struct device_node *np; | 1446 | struct device_node *np; |
@@ -947,6 +1473,7 @@ static int __init of_selftest(void) | |||
947 | of_selftest_parse_interrupts_extended(); | 1473 | of_selftest_parse_interrupts_extended(); |
948 | of_selftest_match_node(); | 1474 | of_selftest_match_node(); |
949 | of_selftest_platform_populate(); | 1475 | of_selftest_platform_populate(); |
1476 | of_selftest_overlay(); | ||
950 | 1477 | ||
951 | /* removing selftest data from live tree */ | 1478 | /* removing selftest data from live tree */ |
952 | selftest_data_remove(); | 1479 | selftest_data_remove(); |
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index da7e6225b8f6..66a70e9bc743 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c | |||
@@ -1220,6 +1220,121 @@ err_init_queue: | |||
1220 | /*-------------------------------------------------------------------------*/ | 1220 | /*-------------------------------------------------------------------------*/ |
1221 | 1221 | ||
1222 | #if defined(CONFIG_OF) | 1222 | #if defined(CONFIG_OF) |
1223 | static struct spi_device * | ||
1224 | of_register_spi_device(struct spi_master *master, struct device_node *nc) | ||
1225 | { | ||
1226 | struct spi_device *spi; | ||
1227 | int rc; | ||
1228 | u32 value; | ||
1229 | |||
1230 | /* Alloc an spi_device */ | ||
1231 | spi = spi_alloc_device(master); | ||
1232 | if (!spi) { | ||
1233 | dev_err(&master->dev, "spi_device alloc error for %s\n", | ||
1234 | nc->full_name); | ||
1235 | rc = -ENOMEM; | ||
1236 | goto err_out; | ||
1237 | } | ||
1238 | |||
1239 | /* Select device driver */ | ||
1240 | rc = of_modalias_node(nc, spi->modalias, | ||
1241 | sizeof(spi->modalias)); | ||
1242 | if (rc < 0) { | ||
1243 | dev_err(&master->dev, "cannot find modalias for %s\n", | ||
1244 | nc->full_name); | ||
1245 | goto err_out; | ||
1246 | } | ||
1247 | |||
1248 | /* Device address */ | ||
1249 | rc = of_property_read_u32(nc, "reg", &value); | ||
1250 | if (rc) { | ||
1251 | dev_err(&master->dev, "%s has no valid 'reg' property (%d)\n", | ||
1252 | nc->full_name, rc); | ||
1253 | goto err_out; | ||
1254 | } | ||
1255 | spi->chip_select = value; | ||
1256 | |||
1257 | /* Mode (clock phase/polarity/etc.) */ | ||
1258 | if (of_find_property(nc, "spi-cpha", NULL)) | ||
1259 | spi->mode |= SPI_CPHA; | ||
1260 | if (of_find_property(nc, "spi-cpol", NULL)) | ||
1261 | spi->mode |= SPI_CPOL; | ||
1262 | if (of_find_property(nc, "spi-cs-high", NULL)) | ||
1263 | spi->mode |= SPI_CS_HIGH; | ||
1264 | if (of_find_property(nc, "spi-3wire", NULL)) | ||
1265 | spi->mode |= SPI_3WIRE; | ||
1266 | if (of_find_property(nc, "spi-lsb-first", NULL)) | ||
1267 | spi->mode |= SPI_LSB_FIRST; | ||
1268 | |||
1269 | /* Device DUAL/QUAD mode */ | ||
1270 | if (!of_property_read_u32(nc, "spi-tx-bus-width", &value)) { | ||
1271 | switch (value) { | ||
1272 | case 1: | ||
1273 | break; | ||
1274 | case 2: | ||
1275 | spi->mode |= SPI_TX_DUAL; | ||
1276 | break; | ||
1277 | case 4: | ||
1278 | spi->mode |= SPI_TX_QUAD; | ||
1279 | break; | ||
1280 | default: | ||
1281 | dev_warn(&master->dev, | ||
1282 | "spi-tx-bus-width %d not supported\n", | ||
1283 | value); | ||
1284 | break; | ||
1285 | } | ||
1286 | } | ||
1287 | |||
1288 | if (!of_property_read_u32(nc, "spi-rx-bus-width", &value)) { | ||
1289 | switch (value) { | ||
1290 | case 1: | ||
1291 | break; | ||
1292 | case 2: | ||
1293 | spi->mode |= SPI_RX_DUAL; | ||
1294 | break; | ||
1295 | case 4: | ||
1296 | spi->mode |= SPI_RX_QUAD; | ||
1297 | break; | ||
1298 | default: | ||
1299 | dev_warn(&master->dev, | ||
1300 | "spi-rx-bus-width %d not supported\n", | ||
1301 | value); | ||
1302 | break; | ||
1303 | } | ||
1304 | } | ||
1305 | |||
1306 | /* Device speed */ | ||
1307 | rc = of_property_read_u32(nc, "spi-max-frequency", &value); | ||
1308 | if (rc) { | ||
1309 | dev_err(&master->dev, "%s has no valid 'spi-max-frequency' property (%d)\n", | ||
1310 | nc->full_name, rc); | ||
1311 | goto err_out; | ||
1312 | } | ||
1313 | spi->max_speed_hz = value; | ||
1314 | |||
1315 | /* IRQ */ | ||
1316 | spi->irq = irq_of_parse_and_map(nc, 0); | ||
1317 | |||
1318 | /* Store a pointer to the node in the device structure */ | ||
1319 | of_node_get(nc); | ||
1320 | spi->dev.of_node = nc; | ||
1321 | |||
1322 | /* Register the new device */ | ||
1323 | request_module("%s%s", SPI_MODULE_PREFIX, spi->modalias); | ||
1324 | rc = spi_add_device(spi); | ||
1325 | if (rc) { | ||
1326 | dev_err(&master->dev, "spi_device register error %s\n", | ||
1327 | nc->full_name); | ||
1328 | goto err_out; | ||
1329 | } | ||
1330 | |||
1331 | return spi; | ||
1332 | |||
1333 | err_out: | ||
1334 | spi_dev_put(spi); | ||
1335 | return ERR_PTR(rc); | ||
1336 | } | ||
1337 | |||
1223 | /** | 1338 | /** |
1224 | * of_register_spi_devices() - Register child devices onto the SPI bus | 1339 | * of_register_spi_devices() - Register child devices onto the SPI bus |
1225 | * @master: Pointer to spi_master device | 1340 | * @master: Pointer to spi_master device |
@@ -1231,116 +1346,15 @@ static void of_register_spi_devices(struct spi_master *master) | |||
1231 | { | 1346 | { |
1232 | struct spi_device *spi; | 1347 | struct spi_device *spi; |
1233 | struct device_node *nc; | 1348 | struct device_node *nc; |
1234 | int rc; | ||
1235 | u32 value; | ||
1236 | 1349 | ||
1237 | if (!master->dev.of_node) | 1350 | if (!master->dev.of_node) |
1238 | return; | 1351 | return; |
1239 | 1352 | ||
1240 | for_each_available_child_of_node(master->dev.of_node, nc) { | 1353 | for_each_available_child_of_node(master->dev.of_node, nc) { |
1241 | /* Alloc an spi_device */ | 1354 | spi = of_register_spi_device(master, nc); |
1242 | spi = spi_alloc_device(master); | 1355 | if (IS_ERR(spi)) |
1243 | if (!spi) { | 1356 | dev_warn(&master->dev, "Failed to create SPI device for %s\n", |
1244 | dev_err(&master->dev, "spi_device alloc error for %s\n", | ||
1245 | nc->full_name); | 1357 | nc->full_name); |
1246 | spi_dev_put(spi); | ||
1247 | continue; | ||
1248 | } | ||
1249 | |||
1250 | /* Select device driver */ | ||
1251 | if (of_modalias_node(nc, spi->modalias, | ||
1252 | sizeof(spi->modalias)) < 0) { | ||
1253 | dev_err(&master->dev, "cannot find modalias for %s\n", | ||
1254 | nc->full_name); | ||
1255 | spi_dev_put(spi); | ||
1256 | continue; | ||
1257 | } | ||
1258 | |||
1259 | /* Device address */ | ||
1260 | rc = of_property_read_u32(nc, "reg", &value); | ||
1261 | if (rc) { | ||
1262 | dev_err(&master->dev, "%s has no valid 'reg' property (%d)\n", | ||
1263 | nc->full_name, rc); | ||
1264 | spi_dev_put(spi); | ||
1265 | continue; | ||
1266 | } | ||
1267 | spi->chip_select = value; | ||
1268 | |||
1269 | /* Mode (clock phase/polarity/etc.) */ | ||
1270 | if (of_find_property(nc, "spi-cpha", NULL)) | ||
1271 | spi->mode |= SPI_CPHA; | ||
1272 | if (of_find_property(nc, "spi-cpol", NULL)) | ||
1273 | spi->mode |= SPI_CPOL; | ||
1274 | if (of_find_property(nc, "spi-cs-high", NULL)) | ||
1275 | spi->mode |= SPI_CS_HIGH; | ||
1276 | if (of_find_property(nc, "spi-3wire", NULL)) | ||
1277 | spi->mode |= SPI_3WIRE; | ||
1278 | if (of_find_property(nc, "spi-lsb-first", NULL)) | ||
1279 | spi->mode |= SPI_LSB_FIRST; | ||
1280 | |||
1281 | /* Device DUAL/QUAD mode */ | ||
1282 | if (!of_property_read_u32(nc, "spi-tx-bus-width", &value)) { | ||
1283 | switch (value) { | ||
1284 | case 1: | ||
1285 | break; | ||
1286 | case 2: | ||
1287 | spi->mode |= SPI_TX_DUAL; | ||
1288 | break; | ||
1289 | case 4: | ||
1290 | spi->mode |= SPI_TX_QUAD; | ||
1291 | break; | ||
1292 | default: | ||
1293 | dev_warn(&master->dev, | ||
1294 | "spi-tx-bus-width %d not supported\n", | ||
1295 | value); | ||
1296 | break; | ||
1297 | } | ||
1298 | } | ||
1299 | |||
1300 | if (!of_property_read_u32(nc, "spi-rx-bus-width", &value)) { | ||
1301 | switch (value) { | ||
1302 | case 1: | ||
1303 | break; | ||
1304 | case 2: | ||
1305 | spi->mode |= SPI_RX_DUAL; | ||
1306 | break; | ||
1307 | case 4: | ||
1308 | spi->mode |= SPI_RX_QUAD; | ||
1309 | break; | ||
1310 | default: | ||
1311 | dev_warn(&master->dev, | ||
1312 | "spi-rx-bus-width %d not supported\n", | ||
1313 | value); | ||
1314 | break; | ||
1315 | } | ||
1316 | } | ||
1317 | |||
1318 | /* Device speed */ | ||
1319 | rc = of_property_read_u32(nc, "spi-max-frequency", &value); | ||
1320 | if (rc) { | ||
1321 | dev_err(&master->dev, "%s has no valid 'spi-max-frequency' property (%d)\n", | ||
1322 | nc->full_name, rc); | ||
1323 | spi_dev_put(spi); | ||
1324 | continue; | ||
1325 | } | ||
1326 | spi->max_speed_hz = value; | ||
1327 | |||
1328 | /* IRQ */ | ||
1329 | spi->irq = irq_of_parse_and_map(nc, 0); | ||
1330 | |||
1331 | /* Store a pointer to the node in the device structure */ | ||
1332 | of_node_get(nc); | ||
1333 | spi->dev.of_node = nc; | ||
1334 | |||
1335 | /* Register the new device */ | ||
1336 | request_module("%s%s", SPI_MODULE_PREFIX, spi->modalias); | ||
1337 | rc = spi_add_device(spi); | ||
1338 | if (rc) { | ||
1339 | dev_err(&master->dev, "spi_device register error %s\n", | ||
1340 | nc->full_name); | ||
1341 | spi_dev_put(spi); | ||
1342 | } | ||
1343 | |||
1344 | } | 1358 | } |
1345 | } | 1359 | } |
1346 | #else | 1360 | #else |
@@ -2303,6 +2317,86 @@ EXPORT_SYMBOL_GPL(spi_write_then_read); | |||
2303 | 2317 | ||
2304 | /*-------------------------------------------------------------------------*/ | 2318 | /*-------------------------------------------------------------------------*/ |
2305 | 2319 | ||
2320 | #if IS_ENABLED(CONFIG_OF_DYNAMIC) | ||
2321 | static int __spi_of_device_match(struct device *dev, void *data) | ||
2322 | { | ||
2323 | return dev->of_node == data; | ||
2324 | } | ||
2325 | |||
2326 | /* must call put_device() when done with returned spi_device device */ | ||
2327 | static struct spi_device *of_find_spi_device_by_node(struct device_node *node) | ||
2328 | { | ||
2329 | struct device *dev = bus_find_device(&spi_bus_type, NULL, node, | ||
2330 | __spi_of_device_match); | ||
2331 | return dev ? to_spi_device(dev) : NULL; | ||
2332 | } | ||
2333 | |||
2334 | static int __spi_of_master_match(struct device *dev, const void *data) | ||
2335 | { | ||
2336 | return dev->of_node == data; | ||
2337 | } | ||
2338 | |||
2339 | /* the spi masters are not using spi_bus, so we find it with another way */ | ||
2340 | static struct spi_master *of_find_spi_master_by_node(struct device_node *node) | ||
2341 | { | ||
2342 | struct device *dev; | ||
2343 | |||
2344 | dev = class_find_device(&spi_master_class, NULL, node, | ||
2345 | __spi_of_master_match); | ||
2346 | if (!dev) | ||
2347 | return NULL; | ||
2348 | |||
2349 | /* reference got in class_find_device */ | ||
2350 | return container_of(dev, struct spi_master, dev); | ||
2351 | } | ||
2352 | |||
2353 | static int of_spi_notify(struct notifier_block *nb, unsigned long action, | ||
2354 | void *arg) | ||
2355 | { | ||
2356 | struct of_reconfig_data *rd = arg; | ||
2357 | struct spi_master *master; | ||
2358 | struct spi_device *spi; | ||
2359 | |||
2360 | switch (of_reconfig_get_state_change(action, arg)) { | ||
2361 | case OF_RECONFIG_CHANGE_ADD: | ||
2362 | master = of_find_spi_master_by_node(rd->dn->parent); | ||
2363 | if (master == NULL) | ||
2364 | return NOTIFY_OK; /* not for us */ | ||
2365 | |||
2366 | spi = of_register_spi_device(master, rd->dn); | ||
2367 | put_device(&master->dev); | ||
2368 | |||
2369 | if (IS_ERR(spi)) { | ||
2370 | pr_err("%s: failed to create for '%s'\n", | ||
2371 | __func__, rd->dn->full_name); | ||
2372 | return notifier_from_errno(PTR_ERR(spi)); | ||
2373 | } | ||
2374 | break; | ||
2375 | |||
2376 | case OF_RECONFIG_CHANGE_REMOVE: | ||
2377 | /* find our device by node */ | ||
2378 | spi = of_find_spi_device_by_node(rd->dn); | ||
2379 | if (spi == NULL) | ||
2380 | return NOTIFY_OK; /* no? not meant for us */ | ||
2381 | |||
2382 | /* unregister takes one ref away */ | ||
2383 | spi_unregister_device(spi); | ||
2384 | |||
2385 | /* and put the reference of the find */ | ||
2386 | put_device(&spi->dev); | ||
2387 | break; | ||
2388 | } | ||
2389 | |||
2390 | return NOTIFY_OK; | ||
2391 | } | ||
2392 | |||
2393 | static struct notifier_block spi_of_notifier = { | ||
2394 | .notifier_call = of_spi_notify, | ||
2395 | }; | ||
2396 | #else /* IS_ENABLED(CONFIG_OF_DYNAMIC) */ | ||
2397 | extern struct notifier_block spi_of_notifier; | ||
2398 | #endif /* IS_ENABLED(CONFIG_OF_DYNAMIC) */ | ||
2399 | |||
2306 | static int __init spi_init(void) | 2400 | static int __init spi_init(void) |
2307 | { | 2401 | { |
2308 | int status; | 2402 | int status; |
@@ -2320,6 +2414,10 @@ static int __init spi_init(void) | |||
2320 | status = class_register(&spi_master_class); | 2414 | status = class_register(&spi_master_class); |
2321 | if (status < 0) | 2415 | if (status < 0) |
2322 | goto err2; | 2416 | goto err2; |
2417 | |||
2418 | if (IS_ENABLED(CONFIG_OF_DYNAMIC)) | ||
2419 | WARN_ON(of_reconfig_notifier_register(&spi_of_notifier)); | ||
2420 | |||
2323 | return 0; | 2421 | return 0; |
2324 | 2422 | ||
2325 | err2: | 2423 | err2: |