diff options
Diffstat (limited to 'drivers/of')
-rw-r--r-- | drivers/of/address.c | 6 | ||||
-rw-r--r-- | drivers/of/device.c | 11 | ||||
-rw-r--r-- | drivers/of/fdt.c | 5 | ||||
-rw-r--r-- | drivers/of/irq.c | 2 | ||||
-rw-r--r-- | drivers/of/of_pci.c | 6 | ||||
-rw-r--r-- | drivers/of/of_reserved_mem.c | 43 |
6 files changed, 63 insertions, 10 deletions
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; 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); } 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; 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/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) { 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 <m.szyprowski@samsung.com> @@ -20,6 +20,7 @@ #include <linux/mm.h> #include <linux/sizes.h> #include <linux/of_reserved_mem.h> +#include <linux/sort.h> #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; |