From 418370ff2231b7db5abf59b8faec911e6fc44d96 Mon Sep 17 00:00:00 2001 From: Danny Lin Date: Wed, 3 Jun 2020 22:49:00 -0700 Subject: of: reserved_mem: Fix typo in the too-many-regions message Minor fix for a missing preposition in the error message that appears when there are too many reserved memory regions for the allocated array to store. Signed-off-by: Danny Lin Link: https://lore.kernel.org/r/20200604054900.200317-1-danny@kdrag0n.dev Signed-off-by: Rob Herring --- drivers/of/of_reserved_mem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/of') diff --git a/drivers/of/of_reserved_mem.c b/drivers/of/of_reserved_mem.c index 6877080c8af9..98972881fc59 100644 --- a/drivers/of/of_reserved_mem.c +++ b/drivers/of/of_reserved_mem.c @@ -54,7 +54,7 @@ void __init fdt_reserved_mem_save_node(unsigned long node, const char *uname, struct reserved_mem *rmem = &reserved_mem[reserved_mem_count]; if (reserved_mem_count == ARRAY_SIZE(reserved_mem)) { - pr_err("not enough space all defined regions.\n"); + pr_err("not enough space for all defined regions.\n"); return; } -- cgit v1.2.3 From bb278b149df9baceac8deea0f95d73c47b3effa8 Mon Sep 17 00:00:00 2001 From: Saravana Kannan Date: Tue, 9 Jun 2020 18:19:34 -0700 Subject: of: property: Improve cycle detection when one of the devices is never added Consider this example where -> means LHS device is a consumer of RHS device and indentation represents "child of" of the previous device. Device A -> Device C Device B -> Device A Device C Without this commit: 1. Device A is added. 2. Device A is added to waiting for supplier list (Device C) 3. Device B is added 4. Device B is linked as a consumer to Device A 5. Device A doesn't probe because it's waiting for Device C to be added. 6. Device B doesn't probe because Device A hasn't probed. 7. Device C will never be added because it's parent hasn't probed. So, Device A, B and C will be in a probe/add deadlock. This commit detects this scenario and stops trying to create a device link between Device A and Device C since doing so would create the following cycle: Device A -> Devic C -(parent)-> Device B -> Device A. With this commit: 1. Device A is added. 3. Device B is added 4. Device B is linked as a consumer to Device A 5. Device A probes. 6. Device B probes because Device A has probed. 7. Device C is added and probed. Signed-off-by: Saravana Kannan Link: https://lore.kernel.org/r/20200610011934.49795-3-saravanak@google.com Signed-off-by: Rob Herring --- drivers/of/property.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 56 insertions(+), 6 deletions(-) (limited to 'drivers/of') diff --git a/drivers/of/property.c b/drivers/of/property.c index 1f2086f4e7ce..6a5760f0d6cd 100644 --- a/drivers/of/property.c +++ b/drivers/of/property.c @@ -1014,6 +1014,30 @@ static bool of_is_ancestor_of(struct device_node *test_ancestor, return false; } +/** + * of_get_next_parent_dev - Add device link to supplier from supplier phandle + * @np: device tree node + * + * Given a device tree node (@np), this function finds its closest ancestor + * device tree node that has a corresponding struct device. + * + * The caller of this function is expected to call put_device() on the returned + * device when they are done. + */ +static struct device *of_get_next_parent_dev(struct device_node *np) +{ + struct device *dev = NULL; + + of_node_get(np); + do { + np = of_get_next_parent(np); + if (np) + dev = get_dev_from_fwnode(&np->fwnode); + } while (np && !dev); + of_node_put(np); + return dev; +} + /** * of_link_to_phandle - Add device link to supplier from supplier phandle * @dev: consumer device @@ -1035,10 +1059,9 @@ static bool of_is_ancestor_of(struct device_node *test_ancestor, static int of_link_to_phandle(struct device *dev, struct device_node *sup_np, u32 dl_flags) { - struct device *sup_dev; + struct device *sup_dev, *sup_par_dev; int ret = 0; struct device_node *tmp_np = sup_np; - int is_populated; of_node_get(sup_np); /* @@ -1075,16 +1098,43 @@ static int of_link_to_phandle(struct device *dev, struct device_node *sup_np, return -EINVAL; } sup_dev = get_dev_from_fwnode(&sup_np->fwnode); - is_populated = of_node_check_flag(sup_np, OF_POPULATED); - of_node_put(sup_np); - if (!sup_dev && is_populated) { + if (!sup_dev && of_node_check_flag(sup_np, OF_POPULATED)) { /* Early device without struct device. */ dev_dbg(dev, "Not linking to %pOFP - No struct device\n", sup_np); + of_node_put(sup_np); return -ENODEV; } else if (!sup_dev) { - return -EAGAIN; + /* + * DL_FLAG_SYNC_STATE_ONLY doesn't block probing and supports + * cycles. So cycle detection isn't necessary and shouldn't be + * done. + */ + if (dl_flags & DL_FLAG_SYNC_STATE_ONLY) { + of_node_put(sup_np); + return -EAGAIN; + } + + sup_par_dev = of_get_next_parent_dev(sup_np); + + if (sup_par_dev && device_is_dependent(dev, sup_par_dev)) { + /* Cyclic dependency detected, don't try to link */ + dev_dbg(dev, "Not linking to %pOFP - cycle detected\n", + sup_np); + ret = -EINVAL; + } else { + /* + * Can't check for cycles or no cycles. So let's try + * again later. + */ + ret = -EAGAIN; + } + + of_node_put(sup_np); + put_device(sup_par_dev); + return ret; } + of_node_put(sup_np); if (!device_link_add(dev, sup_dev, dl_flags)) ret = -EINVAL; put_device(sup_dev); -- cgit v1.2.3 From 1094d5db26c21e85cd84c97e28d5ba502603da38 Mon Sep 17 00:00:00 2001 From: Wenchao Hao Date: Thu, 2 Jul 2020 00:24:44 +0800 Subject: of/address: Fix variable name in comment of of_iomap The first variable name of of_iomap is np while previous comment write device here. Signed-off-by: Wenchao Hao Link: https://lore.kernel.org/r/20200701162444.9494-1-haowenchao22@gmail.com Signed-off-by: Rob Herring --- drivers/of/address.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/of') diff --git a/drivers/of/address.c b/drivers/of/address.c index 8eea3f6e29a4..381dc9be7b22 100644 --- a/drivers/of/address.c +++ b/drivers/of/address.c @@ -864,7 +864,7 @@ EXPORT_SYMBOL_GPL(of_address_to_resource); /** * of_iomap - Maps the memory mapped IO for a given device_node - * @device: the device whose io range will be mapped + * @np: the device whose io range will be mapped * @index: index of the io range * * Returns a pointer to the mapped memory -- cgit v1.2.3 From 53e6a671f70abc2c30fa94ae33c0f1c2fe24985e Mon Sep 17 00:00:00 2001 From: Saravana Kannan Date: Fri, 24 Jul 2020 16:44:14 -0700 Subject: of: property: Add device link support for multiple DT bindings Add support for creating device links out of the following DT bindings: - interrupts-extended - nvmem-cells - phys - wakeup-parent Signed-off-by: Saravana Kannan Link: https://lore.kernel.org/r/20200724234415.1651639-1-saravanak@google.com Signed-off-by: Rob Herring --- drivers/of/property.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'drivers/of') diff --git a/drivers/of/property.c b/drivers/of/property.c index 6a5760f0d6cd..b06edeb1f88b 100644 --- a/drivers/of/property.c +++ b/drivers/of/property.c @@ -1269,6 +1269,11 @@ DEFINE_SIMPLE_PROP(dmas, "dmas", "#dma-cells") DEFINE_SIMPLE_PROP(power_domains, "power-domains", "#power-domain-cells") DEFINE_SIMPLE_PROP(hwlocks, "hwlocks", "#hwlock-cells") DEFINE_SIMPLE_PROP(extcon, "extcon", NULL) +DEFINE_SIMPLE_PROP(interrupts_extended, "interrupts-extended", + "#interrupt-cells") +DEFINE_SIMPLE_PROP(nvmem_cells, "nvmem-cells", NULL) +DEFINE_SIMPLE_PROP(phys, "phys", "#phy-cells") +DEFINE_SIMPLE_PROP(wakeup_parent, "wakeup-parent", NULL) DEFINE_SUFFIX_PROP(regulators, "-supply", NULL) DEFINE_SUFFIX_PROP(gpio, "-gpio", "#gpio-cells") DEFINE_SUFFIX_PROP(gpios, "-gpios", "#gpio-cells") @@ -1294,6 +1299,10 @@ static const struct supplier_bindings of_supplier_bindings[] = { { .parse_prop = parse_power_domains, }, { .parse_prop = parse_hwlocks, }, { .parse_prop = parse_extcon, }, + { .parse_prop = parse_interrupts_extended, }, + { .parse_prop = parse_nvmem_cells, }, + { .parse_prop = parse_phys, }, + { .parse_prop = parse_wakeup_parent, }, { .parse_prop = parse_regulators, }, { .parse_prop = parse_gpio, }, { .parse_prop = parse_gpios, }, -- cgit v1.2.3 From fb820b494acb70e3a20e50935118239c7e5c94dd Mon Sep 17 00:00:00 2001 From: Saravana Kannan Date: Fri, 24 Jul 2020 16:44:15 -0700 Subject: of: property: Add device link support for pinctrl-0 through pinctrl-8 Add support for pinctrl-0 through pinctrl-8 explicitly instead of trying to add support for pinctrl-%d properties. Of all the pinctrl-* properties in dts files (20322), only 47% (9531) are pinctrl-%d properties. Of all the pinctrl-%d properties, 99.5% (9486) are made up of pinctrl-[0-2]. 'pinctrl-8' is the current maximum found in dts files. Trying to parse all pinctrl-* properties and checking for pinctrl-%d is unnecessarily complicated. So, just add support for pinctrl-[0-8] for now. In the unlikely event we ever exceed pinctrl-8, we can come back and improve this. Signed-off-by: Saravana Kannan Link: https://lore.kernel.org/r/20200724234415.1651639-2-saravanak@google.com Signed-off-by: Rob Herring --- drivers/of/property.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'drivers/of') diff --git a/drivers/of/property.c b/drivers/of/property.c index b06edeb1f88b..d40d923ffeaf 100644 --- a/drivers/of/property.c +++ b/drivers/of/property.c @@ -1274,6 +1274,15 @@ DEFINE_SIMPLE_PROP(interrupts_extended, "interrupts-extended", DEFINE_SIMPLE_PROP(nvmem_cells, "nvmem-cells", NULL) DEFINE_SIMPLE_PROP(phys, "phys", "#phy-cells") DEFINE_SIMPLE_PROP(wakeup_parent, "wakeup-parent", NULL) +DEFINE_SIMPLE_PROP(pinctrl0, "pinctrl-0", NULL) +DEFINE_SIMPLE_PROP(pinctrl1, "pinctrl-1", NULL) +DEFINE_SIMPLE_PROP(pinctrl2, "pinctrl-2", NULL) +DEFINE_SIMPLE_PROP(pinctrl3, "pinctrl-3", NULL) +DEFINE_SIMPLE_PROP(pinctrl4, "pinctrl-4", NULL) +DEFINE_SIMPLE_PROP(pinctrl5, "pinctrl-5", NULL) +DEFINE_SIMPLE_PROP(pinctrl6, "pinctrl-6", NULL) +DEFINE_SIMPLE_PROP(pinctrl7, "pinctrl-7", NULL) +DEFINE_SIMPLE_PROP(pinctrl8, "pinctrl-8", NULL) DEFINE_SUFFIX_PROP(regulators, "-supply", NULL) DEFINE_SUFFIX_PROP(gpio, "-gpio", "#gpio-cells") DEFINE_SUFFIX_PROP(gpios, "-gpios", "#gpio-cells") @@ -1303,6 +1312,15 @@ static const struct supplier_bindings of_supplier_bindings[] = { { .parse_prop = parse_nvmem_cells, }, { .parse_prop = parse_phys, }, { .parse_prop = parse_wakeup_parent, }, + { .parse_prop = parse_pinctrl0, }, + { .parse_prop = parse_pinctrl1, }, + { .parse_prop = parse_pinctrl2, }, + { .parse_prop = parse_pinctrl3, }, + { .parse_prop = parse_pinctrl4, }, + { .parse_prop = parse_pinctrl5, }, + { .parse_prop = parse_pinctrl6, }, + { .parse_prop = parse_pinctrl7, }, + { .parse_prop = parse_pinctrl8, }, { .parse_prop = parse_regulators, }, { .parse_prop = parse_gpio, }, { .parse_prop = parse_gpios, }, -- cgit v1.2.3 From bda2127827e9dd2781ae095cda0b8e5bf685c458 Mon Sep 17 00:00:00 2001 From: Nicolas Saenz Julienne Date: Mon, 3 Aug 2020 16:25:47 +0200 Subject: of: unittest: Use bigger address cells to catch parser regressions Getting address and size cells for dma-ranges/ranges parsing is tricky and shouldn't rely on the node's count_cells() method. The function starts looking for cells on the parent node, as its supposed to work with device nodes, which doesn't work when input with bus nodes, as generally done when parsing ranges. Add test to catch regressions on that specific quirk as developers will be tempted to edit it out in favor of the default method. Signed-off-by: Nicolas Saenz Julienne Link: https://lore.kernel.org/r/9200970a917a9cabdc5b17483b5a8725111eb9d0.camel@suse.de Signed-off-by: Rob Herring --- drivers/of/unittest-data/tests-address.dtsi | 10 +++++----- drivers/of/unittest.c | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/of') diff --git a/drivers/of/unittest-data/tests-address.dtsi b/drivers/of/unittest-data/tests-address.dtsi index 3fe5d3987beb..6604a52bf6cb 100644 --- a/drivers/of/unittest-data/tests-address.dtsi +++ b/drivers/of/unittest-data/tests-address.dtsi @@ -23,13 +23,13 @@ }; bus@80000000 { - #address-cells = <1>; - #size-cells = <1>; - ranges = <0x0 0x80000000 0x100000>; - dma-ranges = <0x10000000 0x0 0x40000000>; + #address-cells = <2>; + #size-cells = <2>; + ranges = <0x0 0x0 0x80000000 0x0 0x100000>; + dma-ranges = <0x1 0x0 0x0 0x20 0x0>; device@1000 { - reg = <0x1000 0x1000>; + reg = <0x0 0x1000 0x0 0x1000>; }; }; diff --git a/drivers/of/unittest.c b/drivers/of/unittest.c index 398de04fd19c..9b7e84bdc7d4 100644 --- a/drivers/of/unittest.c +++ b/drivers/of/unittest.c @@ -900,7 +900,7 @@ static void __init of_unittest_parse_dma_ranges(void) of_unittest_dma_ranges_one("/testcase-data/address-tests/device@70000000", 0x0, 0x20000000, 0x40000000); of_unittest_dma_ranges_one("/testcase-data/address-tests/bus@80000000/device@1000", - 0x10000000, 0x20000000, 0x40000000); + 0x100000000, 0x20000000, 0x2000000000); of_unittest_dma_ranges_one("/testcase-data/address-tests/pci@90000000", 0x80000000, 0x20000000, 0x10000000); } -- cgit v1.2.3 From 6f1188b4ac7577c29a4883d5618fa2231396fe9d Mon Sep 17 00:00:00 2001 From: Yue Hu Date: Thu, 30 Jul 2020 17:23:53 +0800 Subject: of: reserved-memory: remove duplicated call to of_get_flat_dt_prop() for no-map node Just use nomap instead of the second call to of_get_flat_dt_prop(). And change nomap as a bool type due to != NULL operator. Also, correct comment about node of 'align' -> 'alignment'. Signed-off-by: Yue Hu Link: https://lore.kernel.org/r/20200730092353.15644-1-zbestahu@gmail.com Signed-off-by: Rob Herring --- drivers/of/of_reserved_mem.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/of') diff --git a/drivers/of/of_reserved_mem.c b/drivers/of/of_reserved_mem.c index 98972881fc59..46b9371c8a33 100644 --- a/drivers/of/of_reserved_mem.c +++ b/drivers/of/of_reserved_mem.c @@ -69,7 +69,7 @@ void __init fdt_reserved_mem_save_node(unsigned long node, const char *uname, /** * __reserved_mem_alloc_size() - allocate reserved memory described by - * 'size', 'align' and 'alloc-ranges' properties. + * 'size', 'alignment' and 'alloc-ranges' properties. */ static int __init __reserved_mem_alloc_size(unsigned long node, const char *uname, phys_addr_t *res_base, phys_addr_t *res_size) @@ -79,7 +79,7 @@ static int __init __reserved_mem_alloc_size(unsigned long node, phys_addr_t base = 0, align = 0, size; int len; const __be32 *prop; - int nomap; + bool nomap; int ret; prop = of_get_flat_dt_prop(node, "size", &len); @@ -92,8 +92,6 @@ static int __init __reserved_mem_alloc_size(unsigned long node, } size = dt_mem_next_cell(dt_root_size_cells, &prop); - nomap = of_get_flat_dt_prop(node, "no-map", NULL) != NULL; - prop = of_get_flat_dt_prop(node, "alignment", &len); if (prop) { if (len != dt_root_addr_cells * sizeof(__be32)) { @@ -104,11 +102,13 @@ static int __init __reserved_mem_alloc_size(unsigned long node, align = dt_mem_next_cell(dt_root_addr_cells, &prop); } + nomap = of_get_flat_dt_prop(node, "no-map", NULL) != NULL; + /* Need adjust the alignment to satisfy the CMA requirement */ if (IS_ENABLED(CONFIG_CMA) && of_flat_dt_is_compatible(node, "shared-dma-pool") && of_get_flat_dt_prop(node, "reusable", NULL) - && !of_get_flat_dt_prop(node, "no-map", NULL)) { + && !nomap) { unsigned long order = max_t(unsigned long, MAX_ORDER - 1, pageblock_order); @@ -247,7 +247,7 @@ void __init fdt_init_reserved_mem(void) int len; const __be32 *prop; int err = 0; - int nomap; + bool nomap; nomap = of_get_flat_dt_prop(node, "no-map", NULL) != NULL; prop = of_get_flat_dt_prop(node, "phandle", &len); -- cgit v1.2.3