From a8bf7527a2e17ccf1366e67f6ac728327ca34c40 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Mon, 26 Aug 2013 11:22:45 -0500 Subject: of: create unflatten_and_copy_device_tree Several architectures using DT support built-in dtb's in the init section. These platforms need to copy the dtb from init since the strings are referenced after unflattening. Every arch has their own copying routine which do the same thing. Create a common function, unflatten_and_copy_device_tree, to copy the dtb when unflattening the dtb. Signed-off-by: Rob Herring Acked-by: Grant Likely --- drivers/of/fdt.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'drivers/of') diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index 229dd9d69e18..51776166d2b0 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c @@ -802,6 +802,30 @@ void __init unflatten_device_tree(void) of_alias_scan(early_init_dt_alloc_memory_arch); } +/** + * unflatten_and_copy_device_tree - copy and create tree of device_nodes from flat blob + * + * Copies and unflattens the device-tree passed by the firmware, creating the + * tree of struct device_node. It also fills the "name" and "type" + * pointers of the nodes so the normal device-tree walking functions + * can be used. This should only be used when the FDT memory has not been + * reserved such is the case when the FDT is built-in to the kernel init + * section. If the FDT memory is reserved already then unflatten_device_tree + * should be used instead. + */ +void __init unflatten_and_copy_device_tree(void) +{ + int size = __be32_to_cpu(initial_boot_params->totalsize); + void *dt = early_init_dt_alloc_memory_arch(size, + __alignof__(struct boot_param_header)); + + if (dt) { + memcpy(dt, initial_boot_params, size); + initial_boot_params = dt; + } + unflatten_device_tree(); +} + #endif /* CONFIG_OF_EARLY_FLATTREE */ /* Feed entire flattened device tree into the random pool */ -- cgit v1.2.1 From 0288ffcbfdf9b8656e7320c24caa1e4c1d498287 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Mon, 26 Aug 2013 09:47:40 -0500 Subject: of: Introduce common early_init_dt_scan Most architectures scan the all the same items early in the FDT and none are really architecture specific. Create a common early_init_dt_scan to unify the early scan of root, memory, and chosen nodes in the flattened DT. Signed-off-by: Rob Herring Acked-by: Grant Likely --- drivers/of/fdt.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) (limited to 'drivers/of') diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index 51776166d2b0..bfbfda543768 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c @@ -785,6 +785,32 @@ void * __init __weak early_init_dt_alloc_memory_arch(u64 size, u64 align) } #endif +bool __init early_init_dt_scan(void *params) +{ + if (!params) + return false; + + /* Setup flat device-tree pointer */ + initial_boot_params = params; + + /* check device tree validity */ + if (be32_to_cpu(initial_boot_params->magic) != OF_DT_HEADER) { + initial_boot_params = NULL; + return false; + } + + /* Retrieve various information from the /chosen node */ + of_scan_flat_dt(early_init_dt_scan_chosen, boot_command_line); + + /* Initialize {size,address}-cells info */ + of_scan_flat_dt(early_init_dt_scan_root, NULL); + + /* Setup memory, calling early_init_dt_add_memory_arch */ + of_scan_flat_dt(early_init_dt_scan_memory, NULL); + + return true; +} + /** * unflatten_device_tree - create tree of device_nodes from flat blob * -- cgit v1.2.1 From 068f6310b965d67d57f89ebf4c539e5933754366 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Tue, 24 Sep 2013 22:20:01 -0500 Subject: of: create default early_init_dt_add_memory_arch Create a weak version of early_init_dt_add_memory_arch which uses memblock. This will unify all architectures except ones with custom memory bank structs. Signed-off-by: Rob Herring Acked-by: Catalin Marinas Cc: Will Deacon Cc: Michal Simek Cc: Jonas Bonn Acked-by: Grant Likely Cc: linux-arm-kernel@lists.infradead.org Cc: microblaze-uclinux@itee.uq.edu.au Cc: linux@lists.openrisc.net Cc: devicetree@vger.kernel.org --- drivers/of/fdt.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'drivers/of') diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index bfbfda543768..5bc55b6e2b41 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c @@ -775,6 +775,25 @@ int __init early_init_dt_scan_chosen(unsigned long node, const char *uname, } #ifdef CONFIG_HAVE_MEMBLOCK +void __init __weak early_init_dt_add_memory_arch(u64 base, u64 size) +{ + const u64 phys_offset = __pa(PAGE_OFFSET); + base &= PAGE_MASK; + size &= PAGE_MASK; + if (base + size < phys_offset) { + pr_warning("Ignoring memory block 0x%llx - 0x%llx\n", + base, base + size); + return; + } + if (base < phys_offset) { + pr_warning("Ignoring memory range 0x%llx - 0x%llx\n", + base, phys_offset); + size -= phys_offset - base; + base = phys_offset; + } + memblock_add(base, size); +} + /* * called from unflatten_device_tree() to bootstrap devicetree itself * Architectures can override this definition if memblock isn't used -- cgit v1.2.1 From 29eb45a9ab4839a1e9cef2bcf369b918c9c4fcad Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Fri, 30 Aug 2013 17:06:53 -0500 Subject: of: remove early_init_dt_setup_initrd_arch All arches do essentially the same thing now for early_init_dt_setup_initrd_arch, so it can now be removed. Signed-off-by: Rob Herring Acked-by: Vineet Gupta Cc: Russell King Cc: Mark Salter Cc: Aurelien Jacquiot Cc: James Hogan Cc: Michal Simek Cc: Ralf Baechle Cc: Jonas Bonn Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Cc: Thomas Gleixner Cc: Ingo Molnar Cc: "H. Peter Anvin" Cc: x86@kernel.org Cc: Chris Zankel Cc: Max Filippov Acked-by: Grant Likely --- drivers/of/fdt.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'drivers/of') diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index 5bc55b6e2b41..5f4cc88cd89e 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c @@ -624,7 +624,7 @@ int __init of_scan_flat_dt_by_path(const char *path, * early_init_dt_check_for_initrd - Decode initrd location from flat tree * @node: reference to node containing initrd location ('chosen') */ -void __init early_init_dt_check_for_initrd(unsigned long node) +static void __init early_init_dt_check_for_initrd(unsigned long node) { u64 start, end; unsigned long len; @@ -642,12 +642,15 @@ void __init early_init_dt_check_for_initrd(unsigned long node) return; end = of_read_number(prop, len/4); - early_init_dt_setup_initrd_arch(start, end); + initrd_start = (unsigned long)__va(start); + initrd_end = (unsigned long)__va(end); + initrd_below_start_ok = 1; + pr_debug("initrd_start=0x%llx initrd_end=0x%llx\n", (unsigned long long)start, (unsigned long long)end); } #else -inline void early_init_dt_check_for_initrd(unsigned long node) +static inline void early_init_dt_check_for_initrd(unsigned long node) { } #endif /* CONFIG_BLK_DEV_INITRD */ -- cgit v1.2.1 From 6a903a2551ef778d60ce4341722d611144251398 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Tue, 27 Aug 2013 21:41:56 -0500 Subject: of: introduce common FDT machine related functions Introduce common of_flat_dt_match_machine and of_flat_dt_get_machine_name functions to unify architectures' handling of machine level model and compatible properties. Several architectures match the root compatible string with an arch specific list of machine descriptors duplicating the same search algorithm. Create a common implementation with a simple architecture specific hook to iterate over each machine's match table. Signed-off-by: Rob Herring Acked-by: Grant Likely --- drivers/of/fdt.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) (limited to 'drivers/of') diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index 5f4cc88cd89e..5c479104fc67 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c @@ -619,6 +619,66 @@ int __init of_scan_flat_dt_by_path(const char *path, return ret; } +const char * __init of_flat_dt_get_machine_name(void) +{ + const char *name; + unsigned long dt_root = of_get_flat_dt_root(); + + name = of_get_flat_dt_prop(dt_root, "model", NULL); + if (!name) + name = of_get_flat_dt_prop(dt_root, "compatible", NULL); + return name; +} + +/** + * of_flat_dt_match_machine - Iterate match tables to find matching machine. + * + * @default_match: A machine specific ptr to return in case of no match. + * @get_next_compat: callback function to return next compatible match table. + * + * Iterate through machine match tables to find the best match for the machine + * compatible string in the FDT. + */ +const void * __init of_flat_dt_match_machine(const void *default_match, + const void * (*get_next_compat)(const char * const**)) +{ + const void *data = NULL; + const void *best_data = default_match; + const char *const *compat; + unsigned long dt_root; + unsigned int best_score = ~1, score = 0; + + dt_root = of_get_flat_dt_root(); + while ((data = get_next_compat(&compat))) { + score = of_flat_dt_match(dt_root, compat); + if (score > 0 && score < best_score) { + best_data = data; + best_score = score; + } + } + if (!best_data) { + const char *prop; + long size; + + pr_err("\n unrecognized device tree list:\n[ "); + + prop = of_get_flat_dt_prop(dt_root, "compatible", &size); + if (prop) { + while (size > 0) { + printk("'%s' ", prop); + size -= strlen(prop) + 1; + prop += strlen(prop) + 1; + } + } + printk("]\n\n"); + return NULL; + } + + pr_info("Machine model: %s\n", of_flat_dt_get_machine_name()); + + return best_data; +} + #ifdef CONFIG_BLK_DEV_INITRD /** * early_init_dt_check_for_initrd - Decode initrd location from flat tree -- cgit v1.2.1 From 9cae09c5a9940b9e02474be0639f0b49bd592a33 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Mon, 9 Sep 2013 18:13:46 -0500 Subject: of: remove unnecessary prom.h includes Remove unnecessary prom.h includes in preparation to make prom.h optional. Signed-off-by: Rob Herring Acked-by: Grant Likely --- drivers/of/of_pci_irq.c | 1 - drivers/of/pdt.c | 1 - 2 files changed, 2 deletions(-) (limited to 'drivers/of') diff --git a/drivers/of/of_pci_irq.c b/drivers/of/of_pci_irq.c index 677053813211..d86076431af6 100644 --- a/drivers/of/of_pci_irq.c +++ b/drivers/of/of_pci_irq.c @@ -2,7 +2,6 @@ #include #include #include -#include /** * of_irq_map_pci - Resolve the interrupt for a PCI device diff --git a/drivers/of/pdt.c b/drivers/of/pdt.c index 4ec19cbee57f..7b666736c168 100644 --- a/drivers/of/pdt.c +++ b/drivers/of/pdt.c @@ -22,7 +22,6 @@ #include #include #include -#include static struct of_pdt_ops *of_pdt_prom_ops __initdata; -- cgit v1.2.1 From 25ff79443cbfa924b8df1d4a8a0fbff83816938a Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Sat, 7 Sep 2013 14:07:11 -0500 Subject: of: implement pci_address_to_pio as weak function Implement pci_address_to_pio as weak function to remove the dependency on asm/prom.h. This is in preparation to make prom.h optional. Signed-off-by: Rob Herring Acked-by: Grant Likely Cc: Michal Simek Cc: Ralf Baechle Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Cc: Thomas Gleixner Cc: Ingo Molnar Cc: "H. Peter Anvin" Cc: x86@kernel.org Cc: Grant Likely --- drivers/of/address.c | 8 ++++++++ drivers/of/of_pci.c | 1 - 2 files changed, 8 insertions(+), 1 deletion(-) (limited to 'drivers/of') diff --git a/drivers/of/address.c b/drivers/of/address.c index b55c21890760..556a7fb6ead3 100644 --- a/drivers/of/address.c +++ b/drivers/of/address.c @@ -626,6 +626,14 @@ const __be32 *of_get_address(struct device_node *dev, int index, u64 *size, } EXPORT_SYMBOL(of_get_address); +unsigned long __weak pci_address_to_pio(phys_addr_t address) +{ + if (address > IO_SPACE_LIMIT) + return (unsigned long)-1; + + return (unsigned long) address; +} + static int __of_address_to_resource(struct device_node *dev, const __be32 *addrp, u64 size, unsigned int flags, const char *name, struct resource *r) diff --git a/drivers/of/of_pci.c b/drivers/of/of_pci.c index e5ca00893c0c..848199633798 100644 --- a/drivers/of/of_pci.c +++ b/drivers/of/of_pci.c @@ -2,7 +2,6 @@ #include #include #include -#include static inline int __of_pci_pci_compare(struct device_node *node, unsigned int data) -- cgit v1.2.1 From 0c3f061c195ceb891067b6de9e4ecc347c4dea31 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Tue, 17 Sep 2013 10:42:50 -0500 Subject: of: implement of_node_to_nid as a weak function Implement of_node_to_nid as weak function to remove the dependency on asm/prom.h. This is in preparation to make prom.h optional. Signed-off-by: Rob Herring Acked-by: Grant Likely --- drivers/of/base.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers/of') diff --git a/drivers/of/base.c b/drivers/of/base.c index 865d3f66c86b..ced4c06d79b3 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -74,6 +74,13 @@ int of_n_size_cells(struct device_node *np) } EXPORT_SYMBOL(of_n_size_cells); +#ifdef CONFIG_NUMA +int __weak of_node_to_nid(struct device_node *np) +{ + return numa_node_id(); +} +#endif + #if defined(CONFIG_OF_DYNAMIC) /** * of_node_get - Increment refcount of a node -- cgit v1.2.1 From d1cb9d1af0bc11b7450a6032f43935c746609418 Mon Sep 17 00:00:00 2001 From: David Miller Date: Thu, 3 Oct 2013 17:24:51 -0400 Subject: of: Make cpu node handling more portable. Use for_each_node_by_type() to iterate all cpu nodes in the system. Provide and overridable function arch_find_n_match_cpu_physical_id, which sees if the given device node matches 'cpu' and if so sets '*thread' when non-NULL to the cpu thread number within the core. The default implementation behaves the same as the existing code. Add a sparc64 implementation. Signed-off-by: David S. Miller Tested-by: Sudeep KarkadaNagesha Signed-off-by: Grant Likely --- drivers/of/base.c | 45 ++++++++++++++++++++++++++++----------------- 1 file changed, 28 insertions(+), 17 deletions(-) (limited to 'drivers/of') diff --git a/drivers/of/base.c b/drivers/of/base.c index 7d4c70f859e3..e4c99453adf1 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -280,6 +280,31 @@ static bool __of_find_n_match_cpu_property(struct device_node *cpun, return false; } +/* + * arch_find_n_match_cpu_physical_id - See if the given device node is + * for the cpu corresponding to logical cpu 'cpu'. Return true if so, + * else false. If 'thread' is non-NULL, the local thread number within the + * core is returned in it. + */ +bool __weak arch_find_n_match_cpu_physical_id(struct device_node *cpun, + int cpu, unsigned int *thread) +{ + /* Check for non-standard "ibm,ppc-interrupt-server#s" property + * for thread ids on PowerPC. If it doesn't exist fallback to + * standard "reg" property. + */ + if (IS_ENABLED(CONFIG_PPC) && + __of_find_n_match_cpu_property(cpun, + "ibm,ppc-interrupt-server#s", + cpu, thread)) + return true; + + if (__of_find_n_match_cpu_property(cpun, "reg", cpu, thread)) + return true; + + return false; +} + /** * of_get_cpu_node - Get device node associated with the given logical CPU * @@ -300,24 +325,10 @@ static bool __of_find_n_match_cpu_property(struct device_node *cpun, */ struct device_node *of_get_cpu_node(int cpu, unsigned int *thread) { - struct device_node *cpun, *cpus; - - cpus = of_find_node_by_path("/cpus"); - if (!cpus) - return NULL; + struct device_node *cpun; - for_each_child_of_node(cpus, cpun) { - if (of_node_cmp(cpun->type, "cpu")) - continue; - /* Check for non-standard "ibm,ppc-interrupt-server#s" property - * for thread ids on PowerPC. If it doesn't exist fallback to - * standard "reg" property. - */ - if (IS_ENABLED(CONFIG_PPC) && - __of_find_n_match_cpu_property(cpun, - "ibm,ppc-interrupt-server#s", cpu, thread)) - return cpun; - if (__of_find_n_match_cpu_property(cpun, "reg", cpu, thread)) + for_each_node_by_type(cpun, "cpu") { + if (arch_find_n_match_cpu_physical_id(cpun, cpu, thread)) return cpun; } return NULL; -- cgit v1.2.1 From f3cea45a77c8ebdb7efad100e576eb6cb401bf25 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Fri, 4 Oct 2013 17:24:26 +0100 Subject: of: Fix iteration bug over CPU reg properties The size of each hwid in a cpu nodes 'reg' property is defined by the parents #address-cells property in the normal way. The cpu parsing code has a bug where it will overrun the end of the property if address-cells is greater than one. This commit fixes the problem by adjusting the array size by the number of address cells. It also makes sure address-cells isn't zero for that would cause an infinite loop. v2: bail if #address-cells is zero instead of forcing to OF_ROOT_NODE_ADDR_CELLS_DEFAULT. Forcing it will cause the reg property to be parsed incorrectly. Signed-off-by: Grant Likely Cc: Rob Herring Cc: Benjamin Herrenschmidt --- drivers/of/base.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/of') diff --git a/drivers/of/base.c b/drivers/of/base.c index e4c99453adf1..3ae106d89791 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -265,9 +265,9 @@ static bool __of_find_n_match_cpu_property(struct device_node *cpun, ac = of_n_addr_cells(cpun); cell = of_get_property(cpun, prop_name, &prop_len); - if (!cell) + if (!cell || !ac) return false; - prop_len /= sizeof(*cell); + prop_len /= sizeof(*cell) * ac; for (tid = 0; tid < prop_len; tid++) { hwid = of_read_number(cell, ac); if (arch_match_cpu_phys_id(cpu, hwid)) { -- cgit v1.2.1 From 8804827b305dbc1c6e24f2b36f1df4a9856b80e8 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Thu, 19 Sep 2013 11:01:52 -0500 Subject: of: Fix dereferencing node name in debug output to be safe Several locations in the of_address and of_irq code dereference the full_name parameter from a device_node pointer without checking if the pointer is valid. This patch switches to use of_node_full_name() which always checks the pointer. Signed-off-by: Grant Likely --- drivers/of/address.c | 6 +++--- drivers/of/irq.c | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers/of') diff --git a/drivers/of/address.c b/drivers/of/address.c index b55c21890760..71180b91bfbe 100644 --- a/drivers/of/address.c +++ b/drivers/of/address.c @@ -489,7 +489,7 @@ static u64 __of_translate_address(struct device_node *dev, int na, ns, pna, pns; u64 result = OF_BAD_ADDR; - pr_debug("OF: ** translation for device %s **\n", dev->full_name); + pr_debug("OF: ** translation for device %s **\n", of_node_full_name(dev)); /* Increase refcount at current level */ of_node_get(dev); @@ -504,13 +504,13 @@ static u64 __of_translate_address(struct device_node *dev, bus->count_cells(dev, &na, &ns); if (!OF_CHECK_COUNTS(na, ns)) { printk(KERN_ERR "prom_parse: Bad cell count for %s\n", - dev->full_name); + of_node_full_name(dev)); goto bail; } memcpy(addr, in_addr, na * 4); pr_debug("OF: bus is %s (na=%d, ns=%d) on %s\n", - bus->name, na, ns, parent->full_name); + bus->name, na, ns, of_node_full_name(parent)); of_dump_addr("OF: translating address:", addr, na); /* Translate */ diff --git a/drivers/of/irq.c b/drivers/of/irq.c index 1752988d6aa8..f5fa5d84aa06 100644 --- a/drivers/of/irq.c +++ b/drivers/of/irq.c @@ -102,7 +102,7 @@ int of_irq_map_raw(struct device_node *parent, const __be32 *intspec, int imaplen, match, i; pr_debug("of_irq_map_raw: par=%s,intspec=[0x%08x 0x%08x...],ointsize=%d\n", - parent->full_name, be32_to_cpup(intspec), + of_node_full_name(parent), be32_to_cpup(intspec), be32_to_cpup(intspec + 1), ointsize); ipar = of_node_get(parent); @@ -126,7 +126,7 @@ int of_irq_map_raw(struct device_node *parent, const __be32 *intspec, goto fail; } - pr_debug("of_irq_map_raw: ipar=%s, size=%d\n", ipar->full_name, intsize); + pr_debug("of_irq_map_raw: ipar=%s, size=%d\n", of_node_full_name(ipar), intsize); if (ointsize != intsize) return -EINVAL; @@ -287,7 +287,7 @@ int of_irq_map_one(struct device_node *device, int index, struct of_irq *out_irq u32 intsize, intlen; int res = -EINVAL; - pr_debug("of_irq_map_one: dev=%s, index=%d\n", device->full_name, index); + pr_debug("of_irq_map_one: dev=%s, index=%d\n", of_node_full_name(device), index); /* OldWorld mac stuff is "special", handle out of line */ if (of_irq_workarounds & OF_IMAP_OLDWORLD_MAC) @@ -355,7 +355,7 @@ int of_irq_to_resource(struct device_node *dev, int index, struct resource *r) r->start = r->end = irq; r->flags = IORESOURCE_IRQ; - r->name = name ? name : dev->full_name; + r->name = name ? name : of_node_full_name(dev); } return irq; -- cgit v1.2.1 From 4a43d686fe336cc0e955c4400ba4d3fcff788786 Mon Sep 17 00:00:00 2001 From: Tomasz Figa Date: Sat, 28 Sep 2013 19:52:51 +0200 Subject: of/irq: Pass trigger type in IRQ resource flags Some drivers might rely on availability of trigger flags in IRQ resource, for example to configure the hardware for particular interrupt type. However current code creating IRQ resources from data in device tree does not configure trigger flags in resulting resources. This patch tries to solve the problem, based on the fact that irq_of_parse_and_map() configures the trigger based on DT interrupt specifier and IRQD_TRIGGER_* flags are consistent with IORESOURCE_IRQ_*, and we can get correct trigger flags by calling irqd_get_trigger_type() after mapping the interrupt. Signed-off-by: Tomasz Figa [grant.likely: Merged the two assignments to r->flags] Signed-off-by: Grant Likely --- 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 f5fa5d84aa06..90068f914911 100644 --- a/drivers/of/irq.c +++ b/drivers/of/irq.c @@ -354,7 +354,7 @@ int of_irq_to_resource(struct device_node *dev, int index, struct resource *r) &name); r->start = r->end = irq; - r->flags = IORESOURCE_IRQ; + r->flags = IORESOURCE_IRQ | irqd_get_trigger_type(irq_get_irq_data(irq)); r->name = name ? name : of_node_full_name(dev); } -- cgit v1.2.1 From 0c02c8007ea5554d028f99fd3e29fc201fdeeab3 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Thu, 19 Sep 2013 11:22:36 -0500 Subject: of/irq: Rename of_irq_map_* functions to of_irq_parse_* The OF irq handling code has been overloading the term 'map' to refer to both parsing the data in the device tree and mapping it to the internal linux irq system. This is probably because the device tree does have the concept of an 'interrupt-map' function for translating interrupt references from one node to another, but 'map' is still confusing when the primary purpose of some of the functions are to parse the DT data. This patch renames all the of_irq_map_* functions to of_irq_parse_* which makes it clear that there is a difference between the parsing phase and the mapping phase. Kernel code can make use of just the parsing or just the mapping support as needed by the subsystem. The patch was generated mechanically with a handful of sed commands. Signed-off-by: Grant Likely Acked-by: Michal Simek Acked-by: Tony Lindgren Cc: Ralf Baechle Cc: Benjamin Herrenschmidt --- drivers/of/address.c | 4 ++-- drivers/of/irq.c | 28 ++++++++++++++-------------- drivers/of/of_pci_irq.c | 10 +++++----- 3 files changed, 21 insertions(+), 21 deletions(-) (limited to 'drivers/of') diff --git a/drivers/of/address.c b/drivers/of/address.c index 71180b91bfbe..994f293baebf 100644 --- a/drivers/of/address.c +++ b/drivers/of/address.c @@ -532,12 +532,12 @@ static u64 __of_translate_address(struct device_node *dev, pbus->count_cells(dev, &pna, &pns); if (!OF_CHECK_COUNTS(pna, pns)) { printk(KERN_ERR "prom_parse: Bad cell count for %s\n", - dev->full_name); + of_node_full_name(dev)); break; } pr_debug("OF: parent bus is %s (na=%d, ns=%d) on %s\n", - pbus->name, pna, pns, parent->full_name); + pbus->name, pna, pns, of_node_full_name(parent)); /* Apply bus translation */ if (of_translate_one(dev, bus, pbus, addr, na, ns, pna, rprop)) diff --git a/drivers/of/irq.c b/drivers/of/irq.c index 90068f914911..410aa2415f42 100644 --- a/drivers/of/irq.c +++ b/drivers/of/irq.c @@ -31,14 +31,14 @@ * @dev: Device node of the device whose interrupt is to be mapped * @index: Index of the interrupt to map * - * This function is a wrapper that chains of_irq_map_one() and + * This function is a wrapper that chains of_irq_parse_one() and * irq_create_of_mapping() to make things easier to callers */ unsigned int irq_of_parse_and_map(struct device_node *dev, int index) { struct of_irq oirq; - if (of_irq_map_one(dev, index, &oirq)) + if (of_irq_parse_one(dev, index, &oirq)) return 0; return irq_create_of_mapping(oirq.controller, oirq.specifier, @@ -79,7 +79,7 @@ struct device_node *of_irq_find_parent(struct device_node *child) } /** - * of_irq_map_raw - Low level interrupt tree parsing + * of_irq_parse_raw - Low level interrupt tree parsing * @parent: the device interrupt parent * @intspec: interrupt specifier ("interrupts" property of the device) * @ointsize: size of the passed in interrupt specifier @@ -93,7 +93,7 @@ struct device_node *of_irq_find_parent(struct device_node *child) * properties, for example when resolving PCI interrupts when no device * node exist for the parent. */ -int of_irq_map_raw(struct device_node *parent, const __be32 *intspec, +int of_irq_parse_raw(struct device_node *parent, const __be32 *intspec, u32 ointsize, const __be32 *addr, struct of_irq *out_irq) { struct device_node *ipar, *tnode, *old = NULL, *newpar = NULL; @@ -101,7 +101,7 @@ int of_irq_map_raw(struct device_node *parent, const __be32 *intspec, u32 intsize = 1, addrsize, newintsize = 0, newaddrsize = 0; int imaplen, match, i; - pr_debug("of_irq_map_raw: par=%s,intspec=[0x%08x 0x%08x...],ointsize=%d\n", + pr_debug("of_irq_parse_raw: par=%s,intspec=[0x%08x 0x%08x...],ointsize=%d\n", of_node_full_name(parent), be32_to_cpup(intspec), be32_to_cpup(intspec + 1), ointsize); @@ -126,7 +126,7 @@ int of_irq_map_raw(struct device_node *parent, const __be32 *intspec, goto fail; } - pr_debug("of_irq_map_raw: ipar=%s, size=%d\n", of_node_full_name(ipar), intsize); + pr_debug("of_irq_parse_raw: ipar=%s, size=%d\n", of_node_full_name(ipar), intsize); if (ointsize != intsize) return -EINVAL; @@ -269,29 +269,29 @@ int of_irq_map_raw(struct device_node *parent, const __be32 *intspec, return -EINVAL; } -EXPORT_SYMBOL_GPL(of_irq_map_raw); +EXPORT_SYMBOL_GPL(of_irq_parse_raw); /** - * of_irq_map_one - Resolve an interrupt for a device + * of_irq_parse_one - Resolve an interrupt for a device * @device: the device whose interrupt is to be resolved * @index: index of the interrupt to resolve * @out_irq: structure of_irq filled by this function * * This function resolves an interrupt, walking the tree, for a given - * device-tree node. It's the high level pendant to of_irq_map_raw(). + * device-tree node. It's the high level pendant to of_irq_parse_raw(). */ -int of_irq_map_one(struct device_node *device, int index, struct of_irq *out_irq) +int of_irq_parse_one(struct device_node *device, int index, struct of_irq *out_irq) { struct device_node *p; const __be32 *intspec, *tmp, *addr; u32 intsize, intlen; int res = -EINVAL; - pr_debug("of_irq_map_one: dev=%s, index=%d\n", of_node_full_name(device), index); + pr_debug("of_irq_parse_one: dev=%s, index=%d\n", of_node_full_name(device), index); /* OldWorld mac stuff is "special", handle out of line */ if (of_irq_workarounds & OF_IMAP_OLDWORLD_MAC) - return of_irq_map_oldworld(device, index, out_irq); + return of_irq_parse_oldworld(device, index, out_irq); /* Get the interrupts property */ intspec = of_get_property(device, "interrupts", &intlen); @@ -322,13 +322,13 @@ int of_irq_map_one(struct device_node *device, int index, struct of_irq *out_irq goto out; /* Get new specifier and map it */ - res = of_irq_map_raw(p, intspec + index * intsize, intsize, + res = of_irq_parse_raw(p, intspec + index * intsize, intsize, addr, out_irq); out: of_node_put(p); return res; } -EXPORT_SYMBOL_GPL(of_irq_map_one); +EXPORT_SYMBOL_GPL(of_irq_parse_one); /** * of_irq_to_resource - Decode a node's IRQ and return it as a resource diff --git a/drivers/of/of_pci_irq.c b/drivers/of/of_pci_irq.c index 677053813211..dceec1048dab 100644 --- a/drivers/of/of_pci_irq.c +++ b/drivers/of/of_pci_irq.c @@ -5,7 +5,7 @@ #include /** - * of_irq_map_pci - Resolve the interrupt for a PCI device + * of_irq_parse_pci - Resolve the interrupt for a PCI device * @pdev: the device whose interrupt is to be resolved * @out_irq: structure of_irq filled by this function * @@ -15,7 +15,7 @@ * PCI tree until an device-node is found, at which point it will finish * resolving using the OF tree walking. */ -int of_irq_map_pci(const struct pci_dev *pdev, struct of_irq *out_irq) +int of_irq_parse_pci(const struct pci_dev *pdev, struct of_irq *out_irq) { struct device_node *dn, *ppnode; struct pci_dev *ppdev; @@ -30,7 +30,7 @@ int of_irq_map_pci(const struct pci_dev *pdev, struct of_irq *out_irq) */ dn = pci_device_to_OF_node(pdev); if (dn) { - rc = of_irq_map_one(dn, 0, out_irq); + rc = of_irq_parse_one(dn, 0, out_irq); if (!rc) return rc; } @@ -88,6 +88,6 @@ int of_irq_map_pci(const struct pci_dev *pdev, struct of_irq *out_irq) lspec_be = cpu_to_be32(lspec); laddr[0] = cpu_to_be32((pdev->bus->number << 16) | (pdev->devfn << 8)); laddr[1] = laddr[2] = cpu_to_be32(0); - return of_irq_map_raw(ppnode, &lspec_be, 1, laddr, out_irq); + return of_irq_parse_raw(ppnode, &lspec_be, 1, laddr, out_irq); } -EXPORT_SYMBOL_GPL(of_irq_map_pci); +EXPORT_SYMBOL_GPL(of_irq_parse_pci); -- cgit v1.2.1 From 530210c7814e83564c7ca7bca8192515042c0b63 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Sun, 15 Sep 2013 16:39:11 +0100 Subject: of/irq: Replace of_irq with of_phandle_args struct of_irq and struct of_phandle_args are exactly the same structure. This patch makes the kernel use of_phandle_args everywhere. This in itself isn't a big deal, but it makes some follow-on patches simpler. Signed-off-by: Grant Likely Acked-by: Michal Simek Acked-by: Tony Lindgren Cc: Russell King Cc: Ralf Baechle Cc: Benjamin Herrenschmidt --- drivers/of/irq.c | 15 +++++++-------- drivers/of/of_pci_irq.c | 2 +- 2 files changed, 8 insertions(+), 9 deletions(-) (limited to 'drivers/of') diff --git a/drivers/of/irq.c b/drivers/of/irq.c index 410aa2415f42..a7db38a63403 100644 --- a/drivers/of/irq.c +++ b/drivers/of/irq.c @@ -36,13 +36,12 @@ */ unsigned int irq_of_parse_and_map(struct device_node *dev, int index) { - struct of_irq oirq; + struct of_phandle_args oirq; if (of_irq_parse_one(dev, index, &oirq)) return 0; - return irq_create_of_mapping(oirq.controller, oirq.specifier, - oirq.size); + return irq_create_of_mapping(oirq.np, oirq.args, oirq.args_count); } EXPORT_SYMBOL_GPL(irq_of_parse_and_map); @@ -94,7 +93,7 @@ struct device_node *of_irq_find_parent(struct device_node *child) * node exist for the parent. */ int of_irq_parse_raw(struct device_node *parent, const __be32 *intspec, - u32 ointsize, const __be32 *addr, struct of_irq *out_irq) + u32 ointsize, const __be32 *addr, struct of_phandle_args *out_irq) { struct device_node *ipar, *tnode, *old = NULL, *newpar = NULL; const __be32 *tmp, *imap, *imask; @@ -156,10 +155,10 @@ int of_irq_parse_raw(struct device_node *parent, const __be32 *intspec, NULL) { pr_debug(" -> got it !\n"); for (i = 0; i < intsize; i++) - out_irq->specifier[i] = + out_irq->args[i] = of_read_number(intspec +i, 1); - out_irq->size = intsize; - out_irq->controller = ipar; + out_irq->args_count = intsize; + out_irq->np = ipar; of_node_put(old); return 0; } @@ -280,7 +279,7 @@ EXPORT_SYMBOL_GPL(of_irq_parse_raw); * This function resolves an interrupt, walking the tree, for a given * device-tree node. It's the high level pendant to of_irq_parse_raw(). */ -int of_irq_parse_one(struct device_node *device, int index, struct of_irq *out_irq) +int of_irq_parse_one(struct device_node *device, int index, struct of_phandle_args *out_irq) { struct device_node *p; const __be32 *intspec, *tmp, *addr; diff --git a/drivers/of/of_pci_irq.c b/drivers/of/of_pci_irq.c index dceec1048dab..ee3293d4b66b 100644 --- a/drivers/of/of_pci_irq.c +++ b/drivers/of/of_pci_irq.c @@ -15,7 +15,7 @@ * PCI tree until an device-node is found, at which point it will finish * resolving using the OF tree walking. */ -int of_irq_parse_pci(const struct pci_dev *pdev, struct of_irq *out_irq) +int of_irq_parse_pci(const struct pci_dev *pdev, struct of_phandle_args *out_irq) { struct device_node *dn, *ppnode; struct pci_dev *ppdev; -- cgit v1.2.1 From e6d30ab1e7d1281784672c0fc2ffa385cfb7279e Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Sun, 15 Sep 2013 16:55:53 +0100 Subject: of/irq: simplify args to irq_create_of_mapping All the callers of irq_create_of_mapping() pass the contents of a struct of_phandle_args structure to the function. Since all the callers already have an of_phandle_args pointer, why not pass it directly to irq_create_of_mapping()? Signed-off-by: Grant Likely Acked-by: Michal Simek Acked-by: Tony Lindgren Cc: Thomas Gleixner Cc: Russell King Cc: Ralf Baechle Cc: Benjamin Herrenschmidt --- 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 a7db38a63403..84184c44e8db 100644 --- a/drivers/of/irq.c +++ b/drivers/of/irq.c @@ -41,7 +41,7 @@ unsigned int irq_of_parse_and_map(struct device_node *dev, int index) if (of_irq_parse_one(dev, index, &oirq)) return 0; - return irq_create_of_mapping(oirq.np, oirq.args, oirq.args_count); + return irq_create_of_mapping(&oirq); } EXPORT_SYMBOL_GPL(irq_of_parse_and_map); -- cgit v1.2.1 From 2361613206e66ce59cc0e08efa8d98ec15b84ed1 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Sun, 15 Sep 2013 22:32:39 +0100 Subject: of/irq: Refactor interrupt-map parsing All the users of of_irq_parse_raw pass in a raw interrupt specifier from the device tree and expect it to be returned (possibly modified) in an of_phandle_args structure. However, the primary function of of_irq_parse_raw() is to check for translations due to the presence of one or more interrupt-map properties. The actual placing of the data into an of_phandle_args structure is trivial. If it is refactored to accept an of_phandle_args structure directly, then it becomes possible to consume of_phandle_args from other sources. This is important for an upcoming patch that allows a device to be connected to more than one interrupt parent. It also simplifies the code a bit. The biggest complication with this patch is that the old version works on the interrupt specifiers in __be32 form, but the of_phandle_args structure is intended to carry it in the cpu-native version. A bit of churn was required to make this work. In the end it results in tighter code, so the churn is worth it. Signed-off-by: Grant Likely Acked-by: Tony Lindgren Cc: Benjamin Herrenschmidt --- drivers/of/irq.c | 108 +++++++++++++++++++++++++----------------------- drivers/of/of_pci_irq.c | 7 +++- 2 files changed, 62 insertions(+), 53 deletions(-) (limited to 'drivers/of') diff --git a/drivers/of/irq.c b/drivers/of/irq.c index 84184c44e8db..0ed5ed4a5f9b 100644 --- a/drivers/of/irq.c +++ b/drivers/of/irq.c @@ -80,31 +80,32 @@ struct device_node *of_irq_find_parent(struct device_node *child) /** * of_irq_parse_raw - Low level interrupt tree parsing * @parent: the device interrupt parent - * @intspec: interrupt specifier ("interrupts" property of the device) - * @ointsize: size of the passed in interrupt specifier - * @addr: address specifier (start of "reg" property of the device) - * @out_irq: structure of_irq filled by this function + * @addr: address specifier (start of "reg" property of the device) in be32 format + * @out_irq: structure of_irq updated by this function * * Returns 0 on success and a negative number on error * * This function is a low-level interrupt tree walking function. It * can be used to do a partial walk with synthetized reg and interrupts * properties, for example when resolving PCI interrupts when no device - * node exist for the parent. + * node exist for the parent. It takes an interrupt specifier structure as + * input, walks the tree looking for any interrupt-map properties, translates + * the specifier for each map, and then returns the translated map. */ -int of_irq_parse_raw(struct device_node *parent, const __be32 *intspec, - u32 ointsize, const __be32 *addr, struct of_phandle_args *out_irq) +int of_irq_parse_raw(const __be32 *addr, struct of_phandle_args *out_irq) { struct device_node *ipar, *tnode, *old = NULL, *newpar = NULL; - const __be32 *tmp, *imap, *imask; + __be32 initial_match_array[8]; + const __be32 *match_array = initial_match_array; + const __be32 *tmp, *imap, *imask, dummy_imask[] = { ~0, ~0, ~0, ~0, ~0 }; u32 intsize = 1, addrsize, newintsize = 0, newaddrsize = 0; int imaplen, match, i; pr_debug("of_irq_parse_raw: par=%s,intspec=[0x%08x 0x%08x...],ointsize=%d\n", - of_node_full_name(parent), be32_to_cpup(intspec), - be32_to_cpup(intspec + 1), ointsize); + of_node_full_name(out_irq->np), out_irq->args[0], out_irq->args[1], + out_irq->args_count); - ipar = of_node_get(parent); + ipar = of_node_get(out_irq->np); /* First get the #interrupt-cells property of the current cursor * that tells us how to interpret the passed-in intspec. If there @@ -127,7 +128,7 @@ int of_irq_parse_raw(struct device_node *parent, const __be32 *intspec, pr_debug("of_irq_parse_raw: ipar=%s, size=%d\n", of_node_full_name(ipar), intsize); - if (ointsize != intsize) + if (out_irq->args_count != intsize) return -EINVAL; /* Look for this #address-cells. We have to implement the old linux @@ -146,6 +147,21 @@ int of_irq_parse_raw(struct device_node *parent, const __be32 *intspec, pr_debug(" -> addrsize=%d\n", addrsize); + /* If we were passed no "reg" property and we attempt to parse + * an interrupt-map, then #address-cells must be 0. + * Fail if it's not. + */ + if (addr == NULL && addrsize != 0) { + pr_debug(" -> no reg passed in when needed !\n"); + return -EINVAL; + } + + /* Precalculate the match array - this simplifies match loop */ + for (i = 0; i < addrsize; i++) + initial_match_array[i] = addr[i]; + for (i = 0; i < intsize; i++) + initial_match_array[addrsize + i] = cpu_to_be32(out_irq->args[i]); + /* Now start the actual "proper" walk of the interrupt tree */ while (ipar != NULL) { /* Now check if cursor is an interrupt-controller and if it is @@ -154,11 +170,6 @@ int of_irq_parse_raw(struct device_node *parent, const __be32 *intspec, if (of_get_property(ipar, "interrupt-controller", NULL) != NULL) { pr_debug(" -> got it !\n"); - for (i = 0; i < intsize; i++) - out_irq->args[i] = - of_read_number(intspec +i, 1); - out_irq->args_count = intsize; - out_irq->np = ipar; of_node_put(old); return 0; } @@ -175,34 +186,16 @@ int of_irq_parse_raw(struct device_node *parent, const __be32 *intspec, /* Look for a mask */ imask = of_get_property(ipar, "interrupt-map-mask", NULL); - - /* If we were passed no "reg" property and we attempt to parse - * an interrupt-map, then #address-cells must be 0. - * Fail if it's not. - */ - if (addr == NULL && addrsize != 0) { - pr_debug(" -> no reg passed in when needed !\n"); - goto fail; - } + if (!imask) + imask = dummy_imask; /* Parse interrupt-map */ match = 0; while (imaplen > (addrsize + intsize + 1) && !match) { /* Compare specifiers */ match = 1; - for (i = 0; i < addrsize && match; ++i) { - __be32 mask = imask ? imask[i] - : cpu_to_be32(0xffffffffu); - match = ((addr[i] ^ imap[i]) & mask) == 0; - } - for (; i < (addrsize + intsize) && match; ++i) { - __be32 mask = imask ? imask[i] - : cpu_to_be32(0xffffffffu); - match = - ((intspec[i-addrsize] ^ imap[i]) & mask) == 0; - } - imap += addrsize + intsize; - imaplen -= addrsize + intsize; + for (i = 0; i < (addrsize + intsize); i++, imaplen--) + match = !((match_array[i] ^ *imap++) & imask[i]); pr_debug(" -> match=%d (imaplen=%d)\n", match, imaplen); @@ -247,12 +240,18 @@ int of_irq_parse_raw(struct device_node *parent, const __be32 *intspec, if (!match) goto fail; - of_node_put(old); - old = of_node_get(newpar); + /* + * Successfully parsed an interrrupt-map translation; copy new + * interrupt specifier into the out_irq structure + */ + of_node_put(out_irq->np); + out_irq->np = of_node_get(newpar); + + match_array = imap - newaddrsize - newintsize; + for (i = 0; i < newintsize; i++) + out_irq->args[i] = be32_to_cpup(imap - newintsize + i); + out_irq->args_count = intsize = newintsize; addrsize = newaddrsize; - intsize = newintsize; - intspec = imap - intsize; - addr = intspec - addrsize; skiplevel: /* Iterate again with new parent */ @@ -263,7 +262,7 @@ int of_irq_parse_raw(struct device_node *parent, const __be32 *intspec, } fail: of_node_put(ipar); - of_node_put(old); + of_node_put(out_irq->np); of_node_put(newpar); return -EINVAL; @@ -276,15 +275,16 @@ EXPORT_SYMBOL_GPL(of_irq_parse_raw); * @index: index of the interrupt to resolve * @out_irq: structure of_irq filled by this function * - * This function resolves an interrupt, walking the tree, for a given - * device-tree node. It's the high level pendant to of_irq_parse_raw(). + * This function resolves an interrupt for a node by walking the interrupt tree, + * finding which interrupt controller node it is attached to, and returning the + * interrupt specifier that can be used to retrieve a Linux IRQ number. */ int of_irq_parse_one(struct device_node *device, int index, struct of_phandle_args *out_irq) { struct device_node *p; const __be32 *intspec, *tmp, *addr; u32 intsize, intlen; - int res = -EINVAL; + int i, res = -EINVAL; pr_debug("of_irq_parse_one: dev=%s, index=%d\n", of_node_full_name(device), index); @@ -320,9 +320,15 @@ int of_irq_parse_one(struct device_node *device, int index, struct of_phandle_ar if ((index + 1) * intsize > intlen) goto out; - /* Get new specifier and map it */ - res = of_irq_parse_raw(p, intspec + index * intsize, intsize, - addr, out_irq); + /* Copy intspec into irq structure */ + intspec += index * intsize; + out_irq->np = p; + out_irq->args_count = intsize; + for (i = 0; i < intsize; i++) + out_irq->args[i] = be32_to_cpup(intspec++); + + /* Check if there are any interrupt-map translations to process */ + res = of_irq_parse_raw(addr, out_irq); out: of_node_put(p); return res; diff --git a/drivers/of/of_pci_irq.c b/drivers/of/of_pci_irq.c index ee3293d4b66b..303afebc247a 100644 --- a/drivers/of/of_pci_irq.c +++ b/drivers/of/of_pci_irq.c @@ -85,9 +85,12 @@ int of_irq_parse_pci(const struct pci_dev *pdev, struct of_phandle_args *out_irq pdev = ppdev; } + out_irq->np = ppnode; + out_irq->args_count = 1; + out_irq->args[0] = lspec; lspec_be = cpu_to_be32(lspec); laddr[0] = cpu_to_be32((pdev->bus->number << 16) | (pdev->devfn << 8)); - laddr[1] = laddr[2] = cpu_to_be32(0); - return of_irq_parse_raw(ppnode, &lspec_be, 1, laddr, out_irq); + laddr[1] = laddr[2] = cpu_to_be32(0); + return of_irq_parse_raw(laddr, out_irq); } EXPORT_SYMBOL_GPL(of_irq_parse_pci); -- cgit v1.2.1 From 624cfca534f9b1ffb1326617b4e973a3d5ecff4a Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Fri, 11 Oct 2013 22:05:10 +0100 Subject: of: Add helper for printing an of_phandle_args structure It is sometimes useful for debug to get the contents of an of_phandle_args structure out into the kernel log. Signed-off-by: Grant Likely --- drivers/of/base.c | 9 +++++++++ drivers/of/irq.c | 6 +++--- 2 files changed, 12 insertions(+), 3 deletions(-) (limited to 'drivers/of') diff --git a/drivers/of/base.c b/drivers/of/base.c index 3ae106d89791..021db96245e7 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -1185,6 +1185,15 @@ int of_property_count_strings(struct device_node *np, const char *propname) } EXPORT_SYMBOL_GPL(of_property_count_strings); +void of_print_phandle_args(const char *msg, const struct of_phandle_args *args) +{ + int i; + printk("%s %s", msg, of_node_full_name(args->np)); + for (i = 0; i < args->args_count; i++) + printk(i ? ",%08x" : ":%08x", args->args[i]); + printk("\n"); +} + static int __of_parse_phandle_with_args(const struct device_node *np, const char *list_name, const char *cells_name, diff --git a/drivers/of/irq.c b/drivers/of/irq.c index 0ed5ed4a5f9b..ddea945ec29e 100644 --- a/drivers/of/irq.c +++ b/drivers/of/irq.c @@ -101,9 +101,9 @@ int of_irq_parse_raw(const __be32 *addr, struct of_phandle_args *out_irq) u32 intsize = 1, addrsize, newintsize = 0, newaddrsize = 0; int imaplen, match, i; - pr_debug("of_irq_parse_raw: par=%s,intspec=[0x%08x 0x%08x...],ointsize=%d\n", - of_node_full_name(out_irq->np), out_irq->args[0], out_irq->args[1], - out_irq->args_count); +#ifdef DEBUG + of_print_phandle_args("of_irq_parse_raw: ", out_irq); +#endif ipar = of_node_get(out_irq->np); -- cgit v1.2.1 From a9f10ca76d784023fc45f01f025b54e9960f4ec1 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Fri, 11 Oct 2013 22:04:23 +0100 Subject: of: Add testcases for interrupt parsing This patch extends the DT selftest code with some test cases for the interrupt parsing functions. Signed-off-by: Grant Likely --- drivers/of/selftest.c | 91 +++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 85 insertions(+), 6 deletions(-) (limited to 'drivers/of') diff --git a/drivers/of/selftest.c b/drivers/of/selftest.c index 0eb5c38b4e07..9c80f0b7556b 100644 --- a/drivers/of/selftest.c +++ b/drivers/of/selftest.c @@ -9,18 +9,24 @@ #include #include #include +#include #include #include #include #include -static bool selftest_passed = true; +static struct selftest_results { + int passed; + int failed; +} selftest_results; + #define selftest(result, fmt, ...) { \ if (!(result)) { \ - pr_err("FAIL %s:%i " fmt, __FILE__, __LINE__, ##__VA_ARGS__); \ - selftest_passed = false; \ + selftest_results.failed++; \ + pr_err("FAIL %s():%i " fmt, __func__, __LINE__, ##__VA_ARGS__); \ } else { \ - pr_info("pass %s:%i\n", __FILE__, __LINE__); \ + selftest_results.passed++; \ + pr_debug("pass %s():%i\n", __func__, __LINE__); \ } \ } @@ -131,7 +137,6 @@ static void __init of_selftest_property_match_string(void) struct device_node *np; int rc; - pr_info("start\n"); np = of_find_node_by_path("/testcase-data/phandle-tests/consumer-a"); if (!np) { pr_err("No testcase data in device tree\n"); @@ -154,6 +159,78 @@ static void __init of_selftest_property_match_string(void) selftest(rc == -EILSEQ, "unterminated string; rc=%i", rc); } +static void __init of_selftest_parse_interrupts(void) +{ + struct device_node *np; + struct of_phandle_args args; + int i, rc; + + np = of_find_node_by_path("/testcase-data/interrupts/interrupts0"); + if (!np) { + pr_err("missing testcase data\n"); + return; + } + + for (i = 0; i < 4; i++) { + bool passed = true; + args.args_count = 0; + rc = of_irq_parse_one(np, i, &args); + + passed &= !rc; + passed &= (args.args_count == 1); + passed &= (args.args[0] == (i + 1)); + + selftest(passed, "index %i - data error on node %s rc=%i\n", + i, args.np->full_name, rc); + } + of_node_put(np); + + np = of_find_node_by_path("/testcase-data/interrupts/interrupts1"); + if (!np) { + pr_err("missing testcase data\n"); + return; + } + + for (i = 0; i < 4; i++) { + bool passed = true; + args.args_count = 0; + rc = of_irq_parse_one(np, i, &args); + + /* Test the values from tests-phandle.dtsi */ + switch (i) { + case 0: + passed &= !rc; + passed &= (args.args_count == 1); + passed &= (args.args[0] == 9); + break; + case 1: + passed &= !rc; + passed &= (args.args_count == 3); + passed &= (args.args[0] == 10); + passed &= (args.args[1] == 11); + passed &= (args.args[2] == 12); + break; + case 2: + passed &= !rc; + passed &= (args.args_count == 2); + passed &= (args.args[0] == 13); + passed &= (args.args[1] == 14); + break; + case 3: + passed &= !rc; + passed &= (args.args_count == 2); + passed &= (args.args[0] == 15); + passed &= (args.args[1] == 16); + break; + default: + passed = false; + } + selftest(passed, "index %i - data error on node %s rc=%i\n", + i, args.np->full_name, rc); + } + of_node_put(np); +} + static int __init of_selftest(void) { struct device_node *np; @@ -168,7 +245,9 @@ static int __init of_selftest(void) pr_info("start of selftest - you will see error messages\n"); of_selftest_parse_phandle_with_args(); of_selftest_property_match_string(); - pr_info("end of selftest - %s\n", selftest_passed ? "PASS" : "FAIL"); + of_selftest_parse_interrupts(); + pr_info("end of selftest - %i passed, %i failed\n", + selftest_results.passed, selftest_results.failed); return 0; } late_initcall(of_selftest); -- cgit v1.2.1 From 3da5278727a895d49a601f67fd49dffa0b80f9a5 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Wed, 18 Sep 2013 15:24:43 +0200 Subject: of/irq: Rework of_irq_count() The of_irq_to_resource() helper that is used to implement of_irq_count() tries to resolve interrupts and in fact creates a mapping for resolved interrupts. That's pretty heavy lifting for something that claims to just return the number of interrupts requested by a given device node. Instead, use the more lightweight of_irq_map_one(), which, despite the name, doesn't create an actual mapping. Perhaps a better name would be of_irq_translate_one(). Signed-off-by: Thierry Reding Acked-by: Rob Herring [grant.likely: fixup s/of_irq_map_one/of_irq_parse_one/] Signed-off-by: Grant Likely --- drivers/of/irq.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/of') diff --git a/drivers/of/irq.c b/drivers/of/irq.c index ddea945ec29e..7c4ff122785f 100644 --- a/drivers/of/irq.c +++ b/drivers/of/irq.c @@ -373,9 +373,10 @@ EXPORT_SYMBOL_GPL(of_irq_to_resource); */ int of_irq_count(struct device_node *dev) { + struct of_phandle_args irq; int nr = 0; - while (of_irq_to_resource(dev, nr, NULL)) + while (of_irq_parse_one(dev, nr, &irq) == 0) nr++; return nr; -- cgit v1.2.1 From 16b84e5a505c790538e534ad8dfda9c288691e40 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Thu, 19 Sep 2013 16:44:55 -0500 Subject: of/irq: Create of_irq_parse_and_map_pci() to consolidate arch code. Several architectures open code effectively the same code block for finding and mapping PCI irqs. This patch consolidates it down to a single function. Signed-off-by: Grant Likely Acked-by: Michal Simek Cc: Russell King Cc: Ralf Baechle Cc: Benjamin Herrenschmidt --- drivers/of/of_pci_irq.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) (limited to 'drivers/of') diff --git a/drivers/of/of_pci_irq.c b/drivers/of/of_pci_irq.c index 303afebc247a..8e92acd8253f 100644 --- a/drivers/of/of_pci_irq.c +++ b/drivers/of/of_pci_irq.c @@ -94,3 +94,28 @@ int of_irq_parse_pci(const struct pci_dev *pdev, struct of_phandle_args *out_irq return of_irq_parse_raw(laddr, out_irq); } EXPORT_SYMBOL_GPL(of_irq_parse_pci); + +/** + * of_irq_parse_and_map_pci() - Decode a PCI irq from the device tree and map to a virq + * @dev: The pci device needing an irq + * @slot: PCI slot number; passed when used as map_irq callback. Unused + * @pin: PCI irq pin number; passed when used as map_irq callback. Unused + * + * @slot and @pin are unused, but included in the function so that this + * function can be used directly as the map_irq callback to pci_fixup_irqs(). + */ +int of_irq_parse_and_map_pci(const struct pci_dev *dev, u8 slot, u8 pin) +{ + struct of_phandle_args oirq; + int ret; + + ret = of_irq_parse_pci(dev, &oirq); + if (ret) { + dev_err(&dev->dev, "of_irq_parse_pci() failed with rc=%d\n", ret); + return 0; /* Proper return code 0 == NO_IRQ */ + } + + return irq_create_of_mapping(&oirq); +} +EXPORT_SYMBOL_GPL(of_irq_parse_and_map_pci); + -- cgit v1.2.1 From 79d9701559a9f3e9b2021fbd292f5e70ad75f686 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Thu, 19 Sep 2013 16:47:37 -0500 Subject: of/irq: create interrupts-extended property The standard interrupts property in device tree can only handle interrupts coming from a single interrupt parent. If a device is wired to multiple interrupt controllers, then it needs to be attached to a node with an interrupt-map property to demux the interrupt specifiers which is confusing. It would be a lot easier if there was a form of the interrupts property that allows for a separate interrupt phandle for each interrupt specifier. This patch does exactly that by creating a new interrupts-extended property which reuses the phandle+arguments pattern used by GPIOs and other core bindings. Signed-off-by: Grant Likely Acked-by: Tony Lindgren Acked-by: Kumar Gala [grant.likely: removed versatile platform hunks into separate patch] Cc: Rob Herring --- drivers/of/irq.c | 16 ++++++++---- drivers/of/selftest.c | 70 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 81 insertions(+), 5 deletions(-) (limited to 'drivers/of') diff --git a/drivers/of/irq.c b/drivers/of/irq.c index 7c4ff122785f..8cc62b4a7988 100644 --- a/drivers/of/irq.c +++ b/drivers/of/irq.c @@ -292,17 +292,23 @@ int of_irq_parse_one(struct device_node *device, int index, struct of_phandle_ar if (of_irq_workarounds & OF_IMAP_OLDWORLD_MAC) return of_irq_parse_oldworld(device, index, out_irq); + /* Get the reg property (if any) */ + addr = of_get_property(device, "reg", NULL); + /* Get the interrupts property */ intspec = of_get_property(device, "interrupts", &intlen); - if (intspec == NULL) - return -EINVAL; + if (intspec == NULL) { + /* Try the new-style interrupts-extended */ + res = of_parse_phandle_with_args(device, "interrupts-extended", + "#interrupt-cells", index, out_irq); + if (res) + return -EINVAL; + return of_irq_parse_raw(addr, out_irq); + } intlen /= sizeof(*intspec); pr_debug(" intspec=%d intlen=%d\n", be32_to_cpup(intspec), intlen); - /* Get the reg property (if any) */ - addr = of_get_property(device, "reg", NULL); - /* Look for the interrupt parent. */ p = of_irq_find_parent(device); if (p == NULL) diff --git a/drivers/of/selftest.c b/drivers/of/selftest.c index 9c80f0b7556b..e21012bde639 100644 --- a/drivers/of/selftest.c +++ b/drivers/of/selftest.c @@ -231,6 +231,75 @@ static void __init of_selftest_parse_interrupts(void) of_node_put(np); } +static void __init of_selftest_parse_interrupts_extended(void) +{ + struct device_node *np; + struct of_phandle_args args; + int i, rc; + + np = of_find_node_by_path("/testcase-data/interrupts/interrupts-extended0"); + if (!np) { + pr_err("missing testcase data\n"); + return; + } + + for (i = 0; i < 7; i++) { + bool passed = true; + rc = of_irq_parse_one(np, i, &args); + + /* Test the values from tests-phandle.dtsi */ + switch (i) { + case 0: + passed &= !rc; + passed &= (args.args_count == 1); + passed &= (args.args[0] == 1); + break; + case 1: + passed &= !rc; + passed &= (args.args_count == 3); + passed &= (args.args[0] == 2); + passed &= (args.args[1] == 3); + passed &= (args.args[2] == 4); + break; + case 2: + passed &= !rc; + passed &= (args.args_count == 2); + passed &= (args.args[0] == 5); + passed &= (args.args[1] == 6); + break; + case 3: + passed &= !rc; + passed &= (args.args_count == 1); + passed &= (args.args[0] == 9); + break; + case 4: + passed &= !rc; + passed &= (args.args_count == 3); + passed &= (args.args[0] == 10); + passed &= (args.args[1] == 11); + passed &= (args.args[2] == 12); + break; + case 5: + passed &= !rc; + passed &= (args.args_count == 2); + passed &= (args.args[0] == 13); + passed &= (args.args[1] == 14); + break; + case 6: + passed &= !rc; + passed &= (args.args_count == 1); + passed &= (args.args[0] == 15); + break; + default: + passed = false; + } + + selftest(passed, "index %i - data error on node %s rc=%i\n", + i, args.np->full_name, rc); + } + of_node_put(np); +} + static int __init of_selftest(void) { struct device_node *np; @@ -246,6 +315,7 @@ static int __init of_selftest(void) of_selftest_parse_phandle_with_args(); of_selftest_property_match_string(); of_selftest_parse_interrupts(); + of_selftest_parse_interrupts_extended(); pr_info("end of selftest - %i passed, %i failed\n", selftest_results.passed, selftest_results.failed); return 0; -- cgit v1.2.1 From 0589342c27944e50ebd7a54f5215002b6598b748 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Tue, 29 Oct 2013 23:36:46 -0500 Subject: of: set dma_mask to point to coherent_dma_mask Platform devices created by DT code don't initialize dma_mask pointer to anything. Set it to coherent_dma_mask by default if the architecture code has not set it. Signed-off-by: Rob Herring --- drivers/of/platform.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/of') diff --git a/drivers/of/platform.c b/drivers/of/platform.c index 9b439ac63d8e..c005495fa382 100644 --- a/drivers/of/platform.c +++ b/drivers/of/platform.c @@ -216,6 +216,8 @@ static struct platform_device *of_platform_device_create_pdata( dev->archdata.dma_mask = 0xffffffffUL; #endif dev->dev.coherent_dma_mask = DMA_BIT_MASK(32); + if (!dev->dev.dma_mask) + dev->dev.dma_mask = &dev->dev.coherent_dma_mask; dev->dev.bus = &platform_bus_type; dev->dev.platform_data = platform_data; -- cgit v1.2.1 From 78119fd1068cc068f6112a57a5f6de0e5b20245a Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Fri, 1 Nov 2013 10:50:50 -0700 Subject: of/irq: Fix bug in interrupt parsing refactor. Commit 2361613206e6, "of/irq: Refactor interrupt-map parsing" introduced a bug. The irq parsing will fail for some nodes that don't have a reg property. It is fixed by deferring the check for reg until it is actually needed. Also adjust the testcase data to catch the bug. Signed-off-by: Grant Likely Tested-by: Stephen Warren Tested-by: Ming Lei Tested-by: Stephen Warren Cc: Rob Herring --- drivers/of/irq.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'drivers/of') diff --git a/drivers/of/irq.c b/drivers/of/irq.c index 8cc62b4a7988..52dba6a01423 100644 --- a/drivers/of/irq.c +++ b/drivers/of/irq.c @@ -147,18 +147,9 @@ int of_irq_parse_raw(const __be32 *addr, struct of_phandle_args *out_irq) pr_debug(" -> addrsize=%d\n", addrsize); - /* If we were passed no "reg" property and we attempt to parse - * an interrupt-map, then #address-cells must be 0. - * Fail if it's not. - */ - if (addr == NULL && addrsize != 0) { - pr_debug(" -> no reg passed in when needed !\n"); - return -EINVAL; - } - /* Precalculate the match array - this simplifies match loop */ for (i = 0; i < addrsize; i++) - initial_match_array[i] = addr[i]; + initial_match_array[i] = addr ? addr[i] : 0; for (i = 0; i < intsize; i++) initial_match_array[addrsize + i] = cpu_to_be32(out_irq->args[i]); @@ -174,6 +165,15 @@ int of_irq_parse_raw(const __be32 *addr, struct of_phandle_args *out_irq) return 0; } + /* + * interrupt-map parsing does not work without a reg + * property when #address-cells != 0 + */ + if (addrsize && !addr) { + pr_debug(" -> no reg passed in when needed !\n"); + goto fail; + } + /* Now look for an interrupt-map */ imap = of_get_property(ipar, "interrupt-map", &imaplen); /* No interrupt map, check for an interrupt parent */ -- cgit v1.2.1 From 355e62f5ad12b005c862838156262eb2df2f8dff Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Sat, 2 Nov 2013 00:11:02 -0700 Subject: of/irq: Fix potential buffer overflow Commit 2361613206e6, "of/irq: Refactor interrupt-map parsing" introduced a potential buffer overflow bug because it doesn't do sufficient range checking on the input data. This patch adds the appropriate checking and buffer size adjustments. If the bounds are out of range then warn loudly. MAX_PHANDLE_ARGS should be sufficient. If it is not then the value can be increased. Signed-off-by: Grant Likely Cc: Rob Herring --- drivers/of/irq.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'drivers/of') diff --git a/drivers/of/irq.c b/drivers/of/irq.c index 52dba6a01423..d385bb824772 100644 --- a/drivers/of/irq.c +++ b/drivers/of/irq.c @@ -95,9 +95,9 @@ struct device_node *of_irq_find_parent(struct device_node *child) int of_irq_parse_raw(const __be32 *addr, struct of_phandle_args *out_irq) { struct device_node *ipar, *tnode, *old = NULL, *newpar = NULL; - __be32 initial_match_array[8]; + __be32 initial_match_array[MAX_PHANDLE_ARGS]; const __be32 *match_array = initial_match_array; - const __be32 *tmp, *imap, *imask, dummy_imask[] = { ~0, ~0, ~0, ~0, ~0 }; + const __be32 *tmp, *imap, *imask, dummy_imask[] = { [0 ... MAX_PHANDLE_ARGS] = ~0 }; u32 intsize = 1, addrsize, newintsize = 0, newaddrsize = 0; int imaplen, match, i; @@ -147,6 +147,10 @@ int of_irq_parse_raw(const __be32 *addr, struct of_phandle_args *out_irq) pr_debug(" -> addrsize=%d\n", addrsize); + /* Range check so that the temporary buffer doesn't overflow */ + if (WARN_ON(addrsize + intsize > MAX_PHANDLE_ARGS)) + goto fail; + /* Precalculate the match array - this simplifies match loop */ for (i = 0; i < addrsize; i++) initial_match_array[i] = addr ? addr[i] : 0; @@ -229,6 +233,8 @@ int of_irq_parse_raw(const __be32 *addr, struct of_phandle_args *out_irq) newintsize, newaddrsize); /* Check for malformed properties */ + if (WARN_ON(newaddrsize + newintsize > MAX_PHANDLE_ARGS)) + goto fail; if (imaplen < (newaddrsize + newintsize)) goto fail; -- cgit v1.2.1 From 74dac2ed699cbe1dee0e4e7891619d53a5f2632f Mon Sep 17 00:00:00 2001 From: Tomasz Figa Date: Tue, 5 Nov 2013 16:21:18 +0100 Subject: of: irq: Fix interrupt-map entry matching This patch fixes interrupt-map entry matching code to properly match all specifier cells with interrupt map entries. Signed-off-by: Tomasz Figa Tested-by: Sachin Kamat 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 d385bb824772..786b0b47fae4 100644 --- a/drivers/of/irq.c +++ b/drivers/of/irq.c @@ -199,7 +199,7 @@ int of_irq_parse_raw(const __be32 *addr, struct of_phandle_args *out_irq) /* Compare specifiers */ match = 1; for (i = 0; i < (addrsize + intsize); i++, imaplen--) - match = !((match_array[i] ^ *imap++) & imask[i]); + match &= !((match_array[i] ^ *imap++) & imask[i]); pr_debug(" -> match=%d (imaplen=%d)\n", match, imaplen); -- cgit v1.2.1 From f5ae18ece391c3bbf03bb1edc5fdcf23dc8b7e54 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Thu, 7 Nov 2013 11:54:27 -0600 Subject: dt: disable self-tests for !OF_IRQ Fix OF selftest compile on sparc which does not enable OF_IRQ. drivers/of/selftest.c:177: undefined reference to `of_irq_parse_one' drivers/of/selftest.c:197: undefined reference to `of_irq_parse_one' drivers/of/selftest.c:248: undefined reference to `of_irq_parse_one' Signed-off-by: Rob Herring Acked-by: Grant Likely --- drivers/of/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/of') diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig index 9d2009a9004d..9b28f8b0c3c2 100644 --- a/drivers/of/Kconfig +++ b/drivers/of/Kconfig @@ -17,6 +17,7 @@ config PROC_DEVICETREE config OF_SELFTEST bool "Device Tree Runtime self tests" + depends on OF_IRQ help This option builds in test cases for the device tree infrastructure that are executed one at boot time, and the results dumped to the -- cgit v1.2.1