Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ARM: 9119/1: amba: Properly handle device probe without IRQ domain

of_amba_device_create() uses irq_of_parse_and_map() to translate
a DT interrupt specification into a Linux virtual interrupt number.

But it doesn't properly handle the case where the interrupt controller
is not yet available, eg, when pl011 interrupt is connected to MBIGEN
interrupt controller, because the mbigen initialization is too late,
which will lead to no IRQ due to no IRQ domain found, log is shown below,
"irq: no irq domain found for uart0 !"

use of_irq_get() to return -EPROBE_DEFER as above, and in the function
amba_device_try_add()/amba_device_add(), it will properly handle in such
case, also return 0 in other fail cases to be consistent as before.

Cc: Rob Herring <robh+dt@kernel.org>
Cc: Frank Rowand <frowand.list@gmail.com>
Reported-by: Ruizhe Lin <linruizhe@huawei.com>
Reviewed-by: Rob Herring <robh@kernel.org>
Signed-off-by: Kefeng Wang <wangkefeng.wang@huawei.com>
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>

authored by

Wang Kefeng and committed by
Russell King (Oracle)
854f695c eb4f7569

+28 -5
+27
drivers/amba/bus.c
··· 19 19 #include <linux/clk/clk-conf.h> 20 20 #include <linux/platform_device.h> 21 21 #include <linux/reset.h> 22 + #include <linux/of_irq.h> 22 23 23 24 #include <asm/irq.h> 24 25 ··· 372 371 kfree(d); 373 372 } 374 373 374 + static int of_amba_device_decode_irq(struct amba_device *dev) 375 + { 376 + struct device_node *node = dev->dev.of_node; 377 + int i, irq = 0; 378 + 379 + if (IS_ENABLED(CONFIG_OF_IRQ) && node) { 380 + /* Decode the IRQs and address ranges */ 381 + for (i = 0; i < AMBA_NR_IRQS; i++) { 382 + irq = of_irq_get(node, i); 383 + if (irq < 0) { 384 + if (irq == -EPROBE_DEFER) 385 + return irq; 386 + irq = 0; 387 + } 388 + 389 + dev->irq[i] = irq; 390 + } 391 + } 392 + 393 + return 0; 394 + } 395 + 375 396 static int amba_device_try_add(struct amba_device *dev, struct resource *parent) 376 397 { 377 398 u32 size; 378 399 void __iomem *tmp; 379 400 int i, ret; 401 + 402 + ret = of_amba_device_decode_irq(dev); 403 + if (ret) 404 + goto err_out; 380 405 381 406 ret = request_resource(parent, &dev->res); 382 407 if (ret)
+1 -5
drivers/of/platform.c
··· 222 222 { 223 223 struct amba_device *dev; 224 224 const void *prop; 225 - int i, ret; 225 + int ret; 226 226 227 227 pr_debug("Creating amba device %pOF\n", node); 228 228 ··· 252 252 prop = of_get_property(node, "arm,primecell-periphid", NULL); 253 253 if (prop) 254 254 dev->periphid = of_read_ulong(prop, 1); 255 - 256 - /* Decode the IRQs and address ranges */ 257 - for (i = 0; i < AMBA_NR_IRQS; i++) 258 - dev->irq[i] = irq_of_parse_and_map(node, i); 259 255 260 256 ret = of_address_to_resource(node, 0, &dev->res); 261 257 if (ret) {