From deb387d4af5a4be3b656b5d69ae4d87ccee325b8 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Fri, 15 Mar 2019 10:22:47 +0100 Subject: of: property: Document that of_graph_get_endpoint_by_regs needs of_node_put The node returned by of_graph_get_endpoint_by_regs has a reference taken, and we need to put that reference back when done with the node. However, the documentation for that node doesn't mention it, so let's make sure it does. Signed-off-by: Maxime Ripard Signed-off-by: Rob Herring --- drivers/of/property.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/of') diff --git a/drivers/of/property.c b/drivers/of/property.c index 8631efa1daa1..d7fa75e31f22 100644 --- a/drivers/of/property.c +++ b/drivers/of/property.c @@ -659,7 +659,7 @@ EXPORT_SYMBOL(of_graph_get_next_endpoint); * * Return: An 'endpoint' node pointer which is identified by reg and at the same * is the child of a port node identified by port_reg. reg and port_reg are - * ignored when they are -1. + * ignored when they are -1. Use of_node_put() on the pointer when done. */ struct device_node *of_graph_get_endpoint_by_regs( const struct device_node *parent, int port_reg, int reg) -- cgit v1.2.3-59-g8ed1b From d0b8ed47e83a2253897500ea4fcae8e8198942b4 Mon Sep 17 00:00:00 2001 From: pierre Kuo Date: Tue, 19 Feb 2019 15:45:00 +0800 Subject: of: reserved_mem: fix reserve memory leak The __reserved_mem_init_node will call region specific reserved memory init codes, but once all compatibled init codes failed, the memory region will left in memory.reserved and cause leakage. Take cma reserve memory DTS for example, if user declare 1MB size, which is not align to (PAGE_SIZE << max(MAX_ORDER - 1, pageblock_order)), rmem_cma_setup will return -EINVAL. Meanwhile, rmem_dma_setup will also return -EINVAL since "reusable" property is not set. If finally there is no reserved memory init pick up this memory, kernel will left the 1MB leak in memory.reserved. This patch will remove this kind of memory from memory.reserved, only when __reserved_mem_init_node return neither 0 nor -ENOENT. Signed-off-by: pierre Kuo Signed-off-by: Rob Herring --- drivers/of/of_reserved_mem.c | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) (limited to 'drivers/of') diff --git a/drivers/of/of_reserved_mem.c b/drivers/of/of_reserved_mem.c index 6a36bc0b3d64..89e190e94af7 100644 --- a/drivers/of/of_reserved_mem.c +++ b/drivers/of/of_reserved_mem.c @@ -171,6 +171,7 @@ static int __init __reserved_mem_init_node(struct reserved_mem *rmem) { extern const struct of_device_id __reservedmem_of_table[]; const struct of_device_id *i; + int ret = -ENOENT; for (i = __reservedmem_of_table; i < &__rmem_of_table_sentinel; i++) { reservedmem_of_init_fn initfn = i->data; @@ -179,13 +180,14 @@ static int __init __reserved_mem_init_node(struct reserved_mem *rmem) if (!of_flat_dt_is_compatible(rmem->fdt_node, compat)) continue; - if (initfn(rmem) == 0) { + ret = initfn(rmem); + if (ret == 0) { pr_info("initialized node %s, compatible id %s\n", rmem->name, compat); - return 0; + break; } } - return -ENOENT; + return ret; } static int __init __rmem_cmp(const void *a, const void *b) @@ -245,7 +247,9 @@ void __init fdt_init_reserved_mem(void) int len; const __be32 *prop; int err = 0; + int nomap; + nomap = of_get_flat_dt_prop(node, "no-map", NULL) != NULL; prop = of_get_flat_dt_prop(node, "phandle", &len); if (!prop) prop = of_get_flat_dt_prop(node, "linux,phandle", &len); @@ -255,8 +259,16 @@ void __init fdt_init_reserved_mem(void) if (rmem->size == 0) err = __reserved_mem_alloc_size(node, rmem->name, &rmem->base, &rmem->size); - if (err == 0) - __reserved_mem_init_node(rmem); + if (err == 0) { + err = __reserved_mem_init_node(rmem); + if (err != 0 && err != -ENOENT) { + pr_info("node %s compatible matching fail\n", + rmem->name); + memblock_free(rmem->base, rmem->size); + if (nomap) + memblock_add(rmem->base, rmem->size); + } + } } } -- cgit v1.2.3-59-g8ed1b From 95835a8d473ee650d5fd13ff223f1cfd568b1bdd Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Mon, 1 Apr 2019 10:56:43 +0200 Subject: of: address: Retrieve a parent through a callback in __of_translate_address The __of_translate_address function is used to translate the device tree addresses to physical addresses using the various ranges property to create the offset. However, it's shared between the CPU addresses (based on the ranges property) and the DMA addresses (based on dma-ranges). Since we're going to add support for a DMA parent node that is not the DT parent node, we need to change the logic a bit to have a callback function that will retrieve the parent node we should use. Reviewed-by: Robin Murphy Signed-off-by: Maxime Ripard Signed-off-by: Rob Herring --- drivers/of/address.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'drivers/of') diff --git a/drivers/of/address.c b/drivers/of/address.c index 2270373b30ab..5359a80c4e8c 100644 --- a/drivers/of/address.c +++ b/drivers/of/address.c @@ -569,6 +569,7 @@ static int of_translate_one(struct device_node *parent, struct of_bus *bus, * relative to that node. */ static u64 __of_translate_address(struct device_node *dev, + struct device_node *(*get_parent)(const struct device_node *), const __be32 *in_addr, const char *rprop, struct device_node **host) { @@ -585,7 +586,7 @@ static u64 __of_translate_address(struct device_node *dev, *host = NULL; /* Get parent & match bus type */ - parent = of_get_parent(dev); + parent = get_parent(dev); if (parent == NULL) goto bail; bus = of_match_bus(parent); @@ -609,7 +610,7 @@ static u64 __of_translate_address(struct device_node *dev, /* Switch to parent bus */ of_node_put(dev); dev = parent; - parent = of_get_parent(dev); + parent = get_parent(dev); /* If root, we have finished */ if (parent == NULL) { @@ -665,7 +666,8 @@ u64 of_translate_address(struct device_node *dev, const __be32 *in_addr) struct device_node *host; u64 ret; - ret = __of_translate_address(dev, in_addr, "ranges", &host); + ret = __of_translate_address(dev, of_get_parent, + in_addr, "ranges", &host); if (host) { of_node_put(host); return OF_BAD_ADDR; @@ -680,7 +682,8 @@ u64 of_translate_dma_address(struct device_node *dev, const __be32 *in_addr) struct device_node *host; u64 ret; - ret = __of_translate_address(dev, in_addr, "dma-ranges", &host); + ret = __of_translate_address(dev, of_get_parent, + in_addr, "dma-ranges", &host); if (host) { of_node_put(host); @@ -736,7 +739,8 @@ static u64 of_translate_ioport(struct device_node *dev, const __be32 *in_addr, unsigned long port; struct device_node *host; - taddr = __of_translate_address(dev, in_addr, "ranges", &host); + taddr = __of_translate_address(dev, of_get_parent, + in_addr, "ranges", &host); if (host) { /* host-specific port access */ port = logic_pio_trans_hwaddr(&host->fwnode, taddr, size); -- cgit v1.2.3-59-g8ed1b From f83a6e5dea6cf71d39c6b70a07cbe99b4ef48fe1 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Mon, 1 Apr 2019 10:56:44 +0200 Subject: of: address: Add support for the parent DMA bus Some SoCs have devices that are using a separate bus from the main bus to perform DMA. These buses might have some restrictions and/or different mapping than from the CPU side, so we'd need to express those using the usual dma-ranges, but using a different DT node than the node's parent. Now that the generic interconnect bindings are available, we can model an interconnect with the reserved name "dma-mem" for those use-cases. Reviewed-by: Robin Murphy Signed-off-by: Maxime Ripard Signed-off-by: Rob Herring --- drivers/of/address.c | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) (limited to 'drivers/of') diff --git a/drivers/of/address.c b/drivers/of/address.c index 5359a80c4e8c..978427a9d5e6 100644 --- a/drivers/of/address.c +++ b/drivers/of/address.c @@ -677,12 +677,30 @@ u64 of_translate_address(struct device_node *dev, const __be32 *in_addr) } EXPORT_SYMBOL(of_translate_address); +static struct device_node *__of_get_dma_parent(const struct device_node *np) +{ + struct of_phandle_args args; + int ret, index; + + index = of_property_match_string(np, "interconnect-names", "dma-mem"); + if (index < 0) + return of_get_parent(np); + + ret = of_parse_phandle_with_args(np, "interconnects", + "#interconnect-cells", + index, &args); + if (ret < 0) + return of_get_parent(np); + + return of_node_get(args.np); +} + u64 of_translate_dma_address(struct device_node *dev, const __be32 *in_addr) { struct device_node *host; u64 ret; - ret = __of_translate_address(dev, of_get_parent, + ret = __of_translate_address(dev, __of_get_dma_parent, in_addr, "dma-ranges", &host); if (host) { @@ -912,9 +930,15 @@ int of_dma_get_range(struct device_node *np, u64 *dma_addr, u64 *paddr, u64 *siz return -EINVAL; while (1) { + struct device_node *parent; + naddr = of_n_addr_cells(node); nsize = of_n_size_cells(node); - node = of_get_next_parent(node); + + parent = __of_get_dma_parent(node); + of_node_put(node); + + node = parent; if (!node) break; -- cgit v1.2.3-59-g8ed1b From af3be70a32113787da9f15e4ce8a357ae6caa293 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Wed, 3 Apr 2019 10:56:33 -0700 Subject: of: Improve of_phandle_iterator_next() error message Understanding why of_phandle_iterator_next() returns an error can sometimes be hard to decipher based solely on the error message, a typical error example is that #foo-cells = and the phandle property used has a smaller number of cells specified, e.g.: #thermal-sensor-cells = <1>; phandle = <&scmi_sensor> instead of: phandle <&scmi_sensor 0>; Instead, make it clear what the expectations are towards debugging incorrect Device Tree faster: OF: /thermal-zones/scmi-thermal: #thermal-sensor-cells = 1, found 0 instead Signed-off-by: Florian Fainelli Signed-off-by: Rob Herring --- drivers/of/base.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/of') diff --git a/drivers/of/base.c b/drivers/of/base.c index 5226e898476e..20e0e7ee4edf 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -1350,8 +1350,9 @@ int of_phandle_iterator_next(struct of_phandle_iterator *it) * property data length */ if (it->cur + count > it->list_end) { - pr_err("%pOF: arguments longer than property\n", - it->parent); + pr_err("%pOF: %s = %d found %d\n", + it->parent, it->cells_name, + count, it->cell_count); goto err; } } -- cgit v1.2.3-59-g8ed1b From b827bcbba36d0b9447239136e2237710cca70383 Mon Sep 17 00:00:00 2001 From: xiaojiangfeng Date: Wed, 10 Apr 2019 16:29:41 +0800 Subject: of: del redundant type conversion The type of variable l in early_init_dt_scan_chosen is int, there is no need to convert to int. Signed-off-by: xiaojiangfeng Reviewed-by: Frank Rowand Signed-off-by: Rob Herring --- drivers/of/fdt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/of') diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index 4734223ab702..de893c9616a1 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c @@ -1091,7 +1091,7 @@ int __init early_init_dt_scan_chosen(unsigned long node, const char *uname, /* Retrieve command line */ p = of_get_flat_dt_prop(node, "bootargs", &l); if (p != NULL && l > 0) - strlcpy(data, p, min((int)l, COMMAND_LINE_SIZE)); + strlcpy(data, p, min(l, COMMAND_LINE_SIZE)); /* * CONFIG_CMDLINE is meant to be a default in case nothing else -- cgit v1.2.3-59-g8ed1b From 8e94fd36220cb541ab536214bd9993035251cd5c Mon Sep 17 00:00:00 2001 From: Jojo Zeng Date: Thu, 25 Apr 2019 09:45:54 +0800 Subject: of/device.c: fix the wrong comments the comments which discribed the input parameters of of_match_device(). the name is changed, so fix it. Signed-off-by: Jojo Zeng Reviewed-by: Frank Rowand Signed-off-by: Rob Herring --- drivers/of/device.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/of') diff --git a/drivers/of/device.c b/drivers/of/device.c index 3717f2a20d0d..da8158392010 100644 --- a/drivers/of/device.c +++ b/drivers/of/device.c @@ -17,7 +17,7 @@ /** * of_match_device - Tell if a struct device matches an of_device_id list - * @ids: array of of device match structures to search in + * @matches: array of of device match structures to search in * @dev: the of device structure to match against * * Used by a driver to check whether an platform_device present in the -- cgit v1.2.3-59-g8ed1b From 6f7dc9a37f2b325fc870d1e1ada6169185f8852c Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 2 May 2019 14:40:15 +0200 Subject: of: irq: Remove WARN_ON() for kzalloc() failure There is no need to print a backtrace if kzalloc() fails, as the memory allocation core already takes care of that. Signed-off-by: Geert Uytterhoeven Signed-off-by: Rob Herring --- drivers/of/irq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/of') diff --git a/drivers/of/irq.c b/drivers/of/irq.c index e1f6f392a4c0..7f84bb4903ca 100644 --- a/drivers/of/irq.c +++ b/drivers/of/irq.c @@ -500,7 +500,7 @@ void __init of_irq_init(const struct of_device_id *matches) * pointer, interrupt-parent device_node etc. */ desc = kzalloc(sizeof(*desc), GFP_KERNEL); - if (WARN_ON(!desc)) { + if (!desc) { of_node_put(np); goto err; } -- cgit v1.2.3-59-g8ed1b From 2a656cb5a4a3473c5fc6bf4fddc3560ceed53220 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 2 May 2019 14:45:35 +0200 Subject: of: unittest: Remove error printing on OOM There is no need to print a backtrace or other error message if kzalloc(), kmemdup(), or devm_kzalloc() fails, as the memory allocation core already takes care of that. Signed-off-by: Geert Uytterhoeven Signed-off-by: Rob Herring --- drivers/of/unittest.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) (limited to 'drivers/of') diff --git a/drivers/of/unittest.c b/drivers/of/unittest.c index cccde756b510..3832a5de4602 100644 --- a/drivers/of/unittest.c +++ b/drivers/of/unittest.c @@ -344,7 +344,7 @@ static void __init of_unittest_check_phandles(void) } nh = kzalloc(sizeof(*nh), GFP_KERNEL); - if (WARN_ON(!nh)) + if (!nh) return; nh->np = np; @@ -1199,12 +1199,9 @@ static int __init unittest_data_add(void) /* creating copy */ unittest_data = kmemdup(__dtb_testcases_begin, size, GFP_KERNEL); - - if (!unittest_data) { - pr_warn("%s: Failed to allocate memory for unittest_data; " - "not running tests\n", __func__); + if (!unittest_data) return -ENOMEM; - } + of_fdt_unflatten_tree(unittest_data, NULL, &unittest_data_node); if (!unittest_data_node) { pr_warn("%s: No tree to attach; not running tests\n", __func__); @@ -1845,10 +1842,8 @@ static int unittest_i2c_bus_probe(struct platform_device *pdev) dev_dbg(dev, "%s for node @%pOF\n", __func__, np); std = devm_kzalloc(dev, sizeof(*std), GFP_KERNEL); - if (!std) { - dev_err(dev, "Failed to allocate unittest i2c data\n"); + if (!std) return -ENOMEM; - } /* link them together */ std->pdev = pdev; -- cgit v1.2.3-59-g8ed1b