From 4f59d7119c7cb5f32ca91662a74c217ea7c4ddca Mon Sep 17 00:00:00 2001 From: Zhen Lei Date: Tue, 25 Aug 2015 12:08:22 +0800 Subject: of: to support binding numa node to specified device in devicetree For now, in function device_add, the new device will be forced to inherit the numa node of its parent. But this will override the device's numa node which configured in devicetree. Signed-off-by: Zhen Lei Signed-off-by: Rob Herring --- drivers/of/device.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'drivers/of') diff --git a/drivers/of/device.c b/drivers/of/device.c index 8b91ea241b10..e5f47cec75f3 100644 --- a/drivers/of/device.c +++ b/drivers/of/device.c @@ -60,11 +60,12 @@ int of_device_add(struct platform_device *ofdev) ofdev->name = dev_name(&ofdev->dev); ofdev->id = -1; - /* device_add will assume that this device is on the same node as - * the parent. If there is no parent defined, set the node - * explicitly */ - if (!ofdev->dev.parent) - set_dev_node(&ofdev->dev, of_node_to_nid(ofdev->dev.of_node)); + /* + * If this device has not binding numa node in devicetree, that is + * of_node_to_nid returns NUMA_NO_NODE. device_add will assume that this + * device is on the same node as the parent. + */ + set_dev_node(&ofdev->dev, of_node_to_nid(ofdev->dev.of_node)); return device_add(&ofdev->dev); } -- cgit v1.2.3 From ae1add247bf8c22facacbd818142f1f66e735802 Mon Sep 17 00:00:00 2001 From: Mitchel Humpherys Date: Tue, 15 Sep 2015 18:30:36 -0700 Subject: of: Check for overlap in reserved memory regions Any overlap in the reserved memory regions (those specified in the reserved-memory DT node) is a bug. These bugs might go undetected as long as the contested region isn't used simultaneously by multiple software agents, which makes such bugs hard to debug. Fix this by printing a scary warning during boot if overlap is detected. Signed-off-by: Mitchel Humpherys Signed-off-by: Rob Herring --- drivers/of/of_reserved_mem.c | 43 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) (limited to 'drivers/of') diff --git a/drivers/of/of_reserved_mem.c b/drivers/of/of_reserved_mem.c index 726ebe792813..62f467b8ccae 100644 --- a/drivers/of/of_reserved_mem.c +++ b/drivers/of/of_reserved_mem.c @@ -1,7 +1,7 @@ /* * Device tree based initialization code for reserved memory. * - * Copyright (c) 2013, The Linux Foundation. All Rights Reserved. + * Copyright (c) 2013, 2015 The Linux Foundation. All Rights Reserved. * Copyright (c) 2013,2014 Samsung Electronics Co., Ltd. * http://www.samsung.com * Author: Marek Szyprowski @@ -20,6 +20,7 @@ #include #include #include +#include #define MAX_RESERVED_REGIONS 16 static struct reserved_mem reserved_mem[MAX_RESERVED_REGIONS]; @@ -197,12 +198,52 @@ static int __init __reserved_mem_init_node(struct reserved_mem *rmem) return -ENOENT; } +static int __init __rmem_cmp(const void *a, const void *b) +{ + const struct reserved_mem *ra = a, *rb = b; + + return ra->base - rb->base; +} + +static void __init __rmem_check_for_overlap(void) +{ + int i; + + if (reserved_mem_count < 2) + return; + + sort(reserved_mem, reserved_mem_count, sizeof(reserved_mem[0]), + __rmem_cmp, NULL); + for (i = 0; i < reserved_mem_count - 1; i++) { + struct reserved_mem *this, *next; + + this = &reserved_mem[i]; + next = &reserved_mem[i + 1]; + if (!(this->base && next->base)) + continue; + if (this->base + this->size > next->base) { + phys_addr_t this_end, next_end; + + this_end = this->base + this->size; + next_end = next->base + next->size; + WARN(1, + "Reserved memory: OVERLAP DETECTED!\n%s (%pa--%pa) overlaps with %s (%pa--%pa)\n", + this->name, &this->base, &this_end, + next->name, &next->base, &next_end); + } + } +} + /** * fdt_init_reserved_mem - allocate and init all saved reserved memory regions */ void __init fdt_init_reserved_mem(void) { int i; + + /* check for overlapping reserved regions */ + __rmem_check_for_overlap(); + for (i = 0; i < reserved_mem_count; i++) { struct reserved_mem *rmem = &reserved_mem[i]; unsigned long node = rmem->fdt_node; -- cgit v1.2.3 From 4af971064977b00a437c1ed8ead8876db4e3b58a Mon Sep 17 00:00:00 2001 From: Pavel Fedin Date: Thu, 8 Oct 2015 10:24:25 +0300 Subject: PCI: of: Add 64-bit address recognition without LPAE support If non-LPAE kernel is booted up on a machine with 64-bit PCI resources, PCI controller probe fails with: PCI host bridge /pcie@10000000 ranges: IO 0x3eff0000..0x3effffff -> 0x00000000 MEM 0x10000000..0x3efeffff -> 0x10000000 MEM 0x8000000000..0xffffffffff -> 0x8000000000 pci-host-generic 3f000000.pcie: resource collision: [mem 0x00000000-0xffffffff] conflicts with /pl011@9000000 [mem 0x09000000-0x09000fff] pci-host-generic: probe of 3f000000.pcie failed with error -16 This happens because res->start assignment in of_pci_range_to_resource() truncates the upper part of the address, because res->start is of phys_addr_t type, which is 32-bit on non-LPAE kernels. This patch adds explicit recognition of 64-bit resources, preventing from potential problems when e. g. 0x8000001234 would be converted to 0x00001234. Signed-off-by: Pavel Fedin Signed-off-by: Rob Herring --- drivers/of/address.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers/of') diff --git a/drivers/of/address.c b/drivers/of/address.c index 384574c3987c..cd53fe4a0c86 100644 --- a/drivers/of/address.c +++ b/drivers/of/address.c @@ -330,6 +330,12 @@ int of_pci_range_to_resource(struct of_pci_range *range, } res->start = port; } else { + if ((sizeof(resource_size_t) < 8) && + upper_32_bits(range->cpu_addr)) { + err = -EINVAL; + goto invalid_range; + } + res->start = range->cpu_addr; } res->end = res->start + range->size - 1; -- cgit v1.2.3 From f134f25162e7174ebe63f8aa16810192606eb826 Mon Sep 17 00:00:00 2001 From: Pavel Fedin Date: Thu, 8 Oct 2015 10:24:26 +0300 Subject: PCI: of: Ignore resources with failed translation This patch allows PCI host controller to function even if part of resources is unusable for some reason. An example is non-LPAE kernel on a machine which has some 64-bit resources. Unusable resources will be just skipped instead of a complete failure. Signed-off-by: Pavel Fedin Signed-off-by: Rob Herring --- drivers/of/of_pci.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers/of') diff --git a/drivers/of/of_pci.c b/drivers/of/of_pci.c index 5751dc5b6494..ea7c2b6dfc56 100644 --- a/drivers/of/of_pci.c +++ b/drivers/of/of_pci.c @@ -223,8 +223,10 @@ int of_pci_get_host_bridge_resources(struct device_node *dev, } err = of_pci_range_to_resource(&range, dev, res); - if (err) - goto conversion_failed; + if (err) { + kfree(res); + continue; + } if (resource_type(res) == IORESOURCE_IO) { if (!io_base) { -- cgit v1.2.3 From 6296ad9e3375c6c1ddbb371f589ba6a145bb31df Mon Sep 17 00:00:00 2001 From: Stefan Agner Date: Sat, 10 Oct 2015 01:29:30 -0700 Subject: of/fdt: fix aliases with baudrate in earlycon Many boards use an alias in the stdout-path specification along with console options after a colon (e.g. serial0:115200n8). When using earlycon, this specification currently does not work. While fdt_path_offset supports alias resolution, it does not remove the console options by itself. Use the fdt_path_offset_namelen variant and provide the length of the alias to enable aliases with console options in the stdout-path. Signed-off-by: Stefan Agner Signed-off-by: Rob Herring --- drivers/of/fdt.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers/of') diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index 6e82bc42373b..9fc356830226 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c @@ -813,8 +813,11 @@ static int __init early_init_dt_scan_chosen_serial(void) if (!p || !l) return -ENOENT; + /* Remove console options if present */ + l = strchrnul(p, ':') - p; + /* Get the node specified by stdout-path */ - offset = fdt_path_offset(fdt, p); + offset = fdt_path_offset_namelen(fdt, p, l); if (offset < 0) return -ENODEV; -- cgit v1.2.3 From 52493d446141b07c8ba28dd6a529513f8b2342bd Mon Sep 17 00:00:00 2001 From: Jonas Gorski Date: Mon, 12 Oct 2015 14:43:23 +0200 Subject: of/irq: make of_irq_find_parent static of_irq_find_parent has no users outside of of_irq.c, so it does not make sense to expose it in of_irq.h. Therefore remove the prototype and dummy implmeentation and make the function static instead. Signed-off-by: Jonas Gorski Signed-off-by: Rob Herring --- drivers/of/irq.c | 2 +- include/linux/of_irq.h | 6 ------ 2 files changed, 1 insertion(+), 7 deletions(-) (limited to 'drivers/of') diff --git a/drivers/of/irq.c b/drivers/of/irq.c index 55317fa9c9dc..0c7f4cbe3434 100644 --- a/drivers/of/irq.c +++ b/drivers/of/irq.c @@ -53,7 +53,7 @@ EXPORT_SYMBOL_GPL(irq_of_parse_and_map); * Returns a pointer to the interrupt parent node, or NULL if the interrupt * parent could not be determined. */ -struct device_node *of_irq_find_parent(struct device_node *child) +static struct device_node *of_irq_find_parent(struct device_node *child) { struct device_node *p; const __be32 *parp; diff --git a/include/linux/of_irq.h b/include/linux/of_irq.h index 0088038d5ccd..a58e2e51eeb2 100644 --- a/include/linux/of_irq.h +++ b/include/linux/of_irq.h @@ -77,7 +77,6 @@ static inline void of_msi_configure(struct device *dev, struct device_node *np) * so declare it here regardless of the CONFIG_OF_IRQ setting. */ extern unsigned int irq_of_parse_and_map(struct device_node *node, int index); -extern struct device_node *of_irq_find_parent(struct device_node *child); #else /* !CONFIG_OF */ static inline unsigned int irq_of_parse_and_map(struct device_node *dev, @@ -85,11 +84,6 @@ static inline unsigned int irq_of_parse_and_map(struct device_node *dev, { return 0; } - -static inline void *of_irq_find_parent(struct device_node *child) -{ - return NULL; -} #endif /* !CONFIG_OF */ #endif /* __OF_IRQ_H */ -- cgit v1.2.3 From 855ff2878ec5ef15f0a69a528b2ca676edfb3ee4 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Thu, 22 Oct 2015 11:02:50 +0200 Subject: of/unittest: add missing of_node_put for_each_child_of_node performs an of_node_get on each iteration, so a break out of the loop requires an of_node_put. A simplified version of the semantic patch that fixes this problem is as follows (http://coccinelle.lip6.fr): // @@ expression root,e; local idexpression child; @@ for_each_child_of_node(root, child) { ... when != of_node_put(child) when != e = child ( return child; | + of_node_put(child); ? return ...; ) ... } // Combine the puts into code at the end of the function, for conciseness. Signed-off-by: Julia Lawall Signed-off-by: Rob Herring --- drivers/of/unittest.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers/of') diff --git a/drivers/of/unittest.c b/drivers/of/unittest.c index 9f71770b6226..e16ea5717b7f 100644 --- a/drivers/of/unittest.c +++ b/drivers/of/unittest.c @@ -205,16 +205,20 @@ static int __init of_unittest_check_node_linkage(struct device_node *np) if (child->parent != np) { pr_err("Child node %s links to wrong parent %s\n", child->name, np->name); - return -EINVAL; + rc = -EINVAL; + goto put_child; } rc = of_unittest_check_node_linkage(child); if (rc < 0) - return rc; + goto put_child; count += rc; } return count + 1; +put_child: + of_node_put(child); + return rc; } static void __init of_unittest_check_tree_linkage(void) -- cgit v1.2.3 From 8363ccb917c6bd497392f5a6b716f46213d86495 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Thu, 22 Oct 2015 11:02:51 +0200 Subject: of/irq: add missing of_node_put for_each_matching_node performs an of_node_get on each iteration, so a break out of the loop requires an of_node_put. A simplified version of the semantic patch that fixes this problem is as follows (http://coccinelle.lip6.fr): // @@ local idexpression n; expression e; identifier l; @@ for_each_matching_node(n,...) { ... ( of_node_put(n); | e = n | + of_node_put(n); ? goto l; ) ... } ... l: ... when != n // Besides the issue found by the semantic patch, this code also stores the device_node value in a list, which requires an of_node_get, and then cleans up the list on exit from the function, which requires an of_node_put. Signed-off-by: Julia Lawall Signed-off-by: Rob Herring --- drivers/of/irq.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers/of') diff --git a/drivers/of/irq.c b/drivers/of/irq.c index 0c7f4cbe3434..bcc1f4b2211e 100644 --- a/drivers/of/irq.c +++ b/drivers/of/irq.c @@ -501,10 +501,12 @@ 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 (WARN_ON(!desc)) { + of_node_put(np); goto err; + } - desc->dev = np; + desc->dev = of_node_get(np); desc->interrupt_parent = of_irq_find_parent(np); if (desc->interrupt_parent == np) desc->interrupt_parent = NULL; @@ -575,6 +577,7 @@ void __init of_irq_init(const struct of_device_id *matches) err: list_for_each_entry_safe(desc, temp_desc, &intc_desc_list, list) { list_del(&desc->list); + of_node_put(desc->dev); kfree(desc); } } -- cgit v1.2.3 From 7fad948a7c22cf47ef4e3c3127cd961ff5e2d394 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Thu, 22 Oct 2015 11:02:49 +0200 Subject: of/platform: add missing of_node_put for_each_child_of_node performs an of_node_get on each iteration, so a break out of the loop requires an of_node_put. A simplified version of the semantic patch that fixes this problem is as follows (http://coccinelle.lip6.fr): // @@ local idexpression n; expression root,e; @@ for_each_child_of_node(root,n) { ... ( of_node_put(n); | e = n | + of_node_put(n); ? break; ) ... } ... when != n // Signed-off-by: Julia Lawall Signed-off-by: Rob Herring --- drivers/of/platform.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers/of') diff --git a/drivers/of/platform.c b/drivers/of/platform.c index 1001efaedcb8..af98343614d8 100644 --- a/drivers/of/platform.c +++ b/drivers/of/platform.c @@ -405,8 +405,10 @@ int of_platform_bus_probe(struct device_node *root, if (!of_match_node(matches, child)) continue; rc = of_platform_bus_create(child, matches, NULL, parent, false); - if (rc) + if (rc) { + of_node_put(child); break; + } } of_node_put(root); @@ -447,8 +449,10 @@ int of_platform_populate(struct device_node *root, for_each_child_of_node(root, child) { rc = of_platform_bus_create(child, matches, lookup, parent, true); - if (rc) + if (rc) { + of_node_put(child); break; + } } of_node_set_flag(root, OF_POPULATED_BUS); -- cgit v1.2.3 From 001cf5048e99df7ddac2716ee9958083488b6071 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Thu, 22 Oct 2015 11:02:48 +0200 Subject: of/overlay: add missing of_node_put for_each_child_of_node performs an of_node_get on each iteration, so a break out of the loop requires an of_node_put. A simplified version of the semantic patch that fixes this problem is as follows (http://coccinelle.lip6.fr): // @@ expression root,e; local idexpression child; @@ for_each_child_of_node(root, child) { ... when != of_node_put(child) when != e = child ( return child; | + of_node_put(child); ? return ...; ) ... } // Signed-off-by: Julia Lawall Signed-off-by: Rob Herring --- drivers/of/overlay.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers/of') diff --git a/drivers/of/overlay.c b/drivers/of/overlay.c index 24e025f79299..54e5af9d7377 100644 --- a/drivers/of/overlay.c +++ b/drivers/of/overlay.c @@ -149,6 +149,7 @@ static int of_overlay_apply_one(struct of_overlay *ov, pr_err("%s: Failed to apply single node @%s/%s\n", __func__, target->full_name, child->name); + of_node_put(child); return ret; } } @@ -417,8 +418,10 @@ static int overlay_subtree_check(struct device_node *tree, return 1; for_each_child_of_node(tree, child) { - if (overlay_subtree_check(child, dn)) + if (overlay_subtree_check(child, dn)) { + of_node_put(child); return 1; + } } return 0; -- cgit v1.2.3 From 3f5ceec96470050d20d7281d49985e3b1cfc3995 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 23 Oct 2015 20:47:20 +0900 Subject: of/fdt: fix error checking for earlycon address fdt_translate_address() returns OF_BAD_ADDR on error. It is defined as a u64 value, so the variable "addr" should be defined as u64 as well. Fixes: fb11ffe74c79 ("of/fdt: add FDT serial scanning for earlycon") Signed-off-by: Masahiro Yamada Signed-off-by: Rob Herring --- drivers/of/fdt.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/of') diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index 9fc356830226..196e449fc853 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c @@ -822,14 +822,15 @@ static int __init early_init_dt_scan_chosen_serial(void) return -ENODEV; while (match->compatible[0]) { - unsigned long addr; + u64 addr; + if (fdt_node_check_compatible(fdt, offset, match->compatible)) { match++; continue; } addr = fdt_translate_address(fdt, offset); - if (!addr) + if (addr == OF_BAD_ADDR) return -ENXIO; of_setup_earlycon(addr, match->data); -- cgit v1.2.3 From 1b7c501b51a8c851ff82769cbe905ef19cb70239 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Tue, 6 Oct 2015 17:57:33 -0500 Subject: of: add config option to enable building of all dtbs Enable building all dtb files when CONFIG_OF_ALL_DTBS is enabled. The dtbs are not really dependent on a platform being enabled or any other kernel config, so for testing coverage it is convenient to build all of the dtbs. In order to only build dtbs, this option can be used by creating an allno.config file containing: CONFIG_COMPILE_TEST=y CONFIG_OF=y CONFIG_OF_ALL_DTBS=y And then running: make KCONFIG_ALLCONFIG=1 allnoconfig make dtbs While building the dtbs themselves don't need a cross compiler, the scripts dependency does need one. This can be hacked around by commenting out "subdir-y += mod" in scripts/Makefile. Signed-off-by: Rob Herring Cc: Frank Rowand Cc: Grant Likely --- drivers/of/Kconfig | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'drivers/of') diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig index 59bb8556e43a..e2a48415d969 100644 --- a/drivers/of/Kconfig +++ b/drivers/of/Kconfig @@ -23,6 +23,16 @@ config OF_UNITTEST If unsure, say N here, but this option is safe to enable. +config OF_ALL_DTBS + bool "Build all Device Tree Blobs" + depends on COMPILE_TEST + select DTC + help + This option builds all possible Device Tree Blobs (DTBs) for the + current architecture. + + If unsure, say N here, but this option is safe to enable. + config OF_FLATTREE bool select DTC -- cgit v1.2.3 From 0b13ea8e2661822960b59924b02b4a0ebcf22149 Mon Sep 17 00:00:00 2001 From: Saurabh Sengar Date: Tue, 27 Oct 2015 09:12:01 +0530 Subject: drivers: of: removing assignment of 0 to static variable no need to initialise static variable with 0, hence correcting it. Signed-off-by: Saurabh Sengar 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 196e449fc853..d2430298a309 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c @@ -184,7 +184,7 @@ static void * unflatten_dt_node(const void *blob, struct property *pp, **prev_pp = NULL; const char *pathp; unsigned int l, allocl; - static int depth = 0; + static int depth; int old_depth; int offset; int has_name = 0; -- cgit v1.2.3 From 510bd068db34b946a067629679c5cc99c8b99f1e Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Wed, 28 Oct 2015 12:05:27 +0900 Subject: of: simplify arch_find_n_match_cpu_physical_id() function This commit does not change the function behavior. Signed-off-by: Masahiro Yamada Signed-off-by: Rob Herring --- drivers/of/base.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers/of') diff --git a/drivers/of/base.c b/drivers/of/base.c index 8b5a187a7682..017dd94f16ea 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -375,10 +375,7 @@ bool __weak arch_find_n_match_cpu_physical_id(struct device_node *cpun, cpu, thread)) return true; - if (__of_find_n_match_cpu_property(cpun, "reg", cpu, thread)) - return true; - - return false; + return __of_find_n_match_cpu_property(cpun, "reg", cpu, thread); } /** -- cgit v1.2.3