Skip to content

Commit 9ec36ca

Browse files
robherringglikely
authored andcommitted
of/irq: do irq resolution in platform_get_irq
Currently we get the following kind of errors if we try to use interrupt phandles to irqchips that have not yet initialized: irq: no irq domain found for /ocp/pinmux@48002030 ! ------------[ cut here ]------------ WARNING: CPU: 0 PID: 1 at drivers/of/platform.c:171 of_device_alloc+0x144/0x184() Modules linked in: CPU: 0 PID: 1 Comm: swapper/0 Not tainted 3.12.0-00038-g42a9708 #1012 (show_stack+0x14/0x1c) (dump_stack+0x6c/0xa0) (warn_slowpath_common+0x64/0x84) (warn_slowpath_null+0x1c/0x24) (of_device_alloc+0x144/0x184) (of_platform_device_create_pdata+0x44/0x9c) (of_platform_bus_create+0xd0/0x170) (of_platform_bus_create+0x12c/0x170) (of_platform_populate+0x60/0x98) This is because we're wrongly trying to populate resources that are not yet available. It's perfectly valid to create irqchips dynamically, so let's fix up the issue by resolving the interrupt resources when platform_get_irq is called. And then we also need to accept the fact that some irqdomains do not exist that early on, and only get initialized later on. So we can make the current WARN_ON into just into a pr_debug(). We still attempt to populate irq resources when we create the devices. This allows current drivers which don't use platform_get_irq to continue to function. Once all drivers are fixed, this code can be removed. Suggested-by: Russell King <[email protected]> Signed-off-by: Rob Herring <[email protected]> Signed-off-by: Tony Lindgren <[email protected]> Tested-by: Tony Lindgren <[email protected]> Cc: [email protected] # v3.10+ Signed-off-by: Grant Likely <[email protected]>
1 parent 82c0f58 commit 9ec36ca

File tree

4 files changed

+40
-2
lines changed

4 files changed

+40
-2
lines changed

drivers/base/platform.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include <linux/string.h>
1414
#include <linux/platform_device.h>
1515
#include <linux/of_device.h>
16+
#include <linux/of_irq.h>
1617
#include <linux/module.h>
1718
#include <linux/init.h>
1819
#include <linux/dma-mapping.h>
@@ -87,7 +88,11 @@ int platform_get_irq(struct platform_device *dev, unsigned int num)
8788
return -ENXIO;
8889
return dev->archdata.irqs[num];
8990
#else
90-
struct resource *r = platform_get_resource(dev, IORESOURCE_IRQ, num);
91+
struct resource *r;
92+
if (IS_ENABLED(CONFIG_OF_IRQ) && dev->dev.of_node)
93+
return of_irq_get(dev->dev.of_node, num);
94+
95+
r = platform_get_resource(dev, IORESOURCE_IRQ, num);
9196

9297
return r ? r->start : -ENXIO;
9398
#endif

drivers/of/irq.c

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -379,6 +379,32 @@ int of_irq_to_resource(struct device_node *dev, int index, struct resource *r)
379379
}
380380
EXPORT_SYMBOL_GPL(of_irq_to_resource);
381381

382+
/**
383+
* of_irq_get - Decode a node's IRQ and return it as a Linux irq number
384+
* @dev: pointer to device tree node
385+
* @index: zero-based index of the irq
386+
*
387+
* Returns Linux irq number on success, or -EPROBE_DEFER if the irq domain
388+
* is not yet created.
389+
*
390+
*/
391+
int of_irq_get(struct device_node *dev, int index)
392+
{
393+
int rc;
394+
struct of_phandle_args oirq;
395+
struct irq_domain *domain;
396+
397+
rc = of_irq_parse_one(dev, index, &oirq);
398+
if (rc)
399+
return rc;
400+
401+
domain = irq_find_host(oirq.np);
402+
if (!domain)
403+
return -EPROBE_DEFER;
404+
405+
return irq_create_of_mapping(&oirq);
406+
}
407+
382408
/**
383409
* of_irq_count - Count the number of IRQs a node uses
384410
* @dev: pointer to device tree node

drivers/of/platform.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,9 @@ struct platform_device *of_device_alloc(struct device_node *np,
168168
rc = of_address_to_resource(np, i, res);
169169
WARN_ON(rc);
170170
}
171-
WARN_ON(of_irq_to_resource_table(np, res, num_irq) != num_irq);
171+
if (of_irq_to_resource_table(np, res, num_irq) != num_irq)
172+
pr_debug("not all legacy IRQ resources mapped for %s\n",
173+
np->name);
172174
}
173175

174176
dev->dev.of_node = of_node_get(np);

include/linux/of_irq.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,11 +44,16 @@ extern void of_irq_init(const struct of_device_id *matches);
4444

4545
#ifdef CONFIG_OF_IRQ
4646
extern int of_irq_count(struct device_node *dev);
47+
extern int of_irq_get(struct device_node *dev, int index);
4748
#else
4849
static inline int of_irq_count(struct device_node *dev)
4950
{
5051
return 0;
5152
}
53+
static inline int of_irq_get(struct device_node *dev, int index)
54+
{
55+
return 0;
56+
}
5257
#endif
5358

5459
#if defined(CONFIG_OF)

0 commit comments

Comments
 (0)