[PATCH] ARM: imx: irq: fix buggy usage of irq_data irq field
Philipp Zabel
p.zabel at pengutronix.de
Mon Dec 1 09:12:21 PST 2014
Hi Marc,
Am Montag, den 01.12.2014, 16:25 +0000 schrieb Marc Zyngier:
> mach-imx directly references to the irq field in
> struct irq_data, and uses this to directly poke hardware register.
>
> But irq is the *virtual* irq number, something that has nothing
> to do with the actual HW irq (stored in the hwirq field). And once
> we put the stacked domain code in action, the whole thing explodes,
> as these two values are *very* different.
>
> Just replacing all instances of irq with hwirq fixes the issue.
I have tried this on next-20141128, but due to
struct irq_data *iomuxc_irq_data = irq_get_irq_data(32); /* now returns NULL */
in arch/arm/mach-imx/pm-imx6q.c it still explodes:
Unable to handle kernel NULL pointer dereference at virtual address 00000008
pgd = 80004000
[00000008] *pgd=00000000
Internal error: Oops: 5 [#1] SMP ARM
Modules linked in:
CPU: 0 PID: 0 Comm: swapper/0 Not tainted 3.18.0-rc6-next-20141128+ #8437
Hardware name: Freescale i.MX6 Quad/DualLite (Device Tree)
task: 808520e8 ti: 80846000 task.ti: 80846000
PC is at imx_gpc_irq_unmask+0x14/0x54
LR is at imx6q_set_lpm+0x6c/0xe0
pc : [<8001ec90>] lr : [<8001fb6c>] psr: 800001d3
sp : 80847ea0 ip : 8001ec90 fp : 80847eac
r10: 00000000 r9 : 80891c4c r8 : c0818080
r7 : 00000000 r6 : 00000000 r5 : 00000078 r4 : 80892068
r3 : c0818000 r2 : 00000079 r1 : 00000020 r0 : 00000000
Flags: Nzcv IRQs off FIQs off Mode SVC_32 ISA ARM Segment kernel
Control: 10c5387d Table: 1000404a DAC: 00000015
Process swapper/0 (pid: 0, stack limit = 0x80846240)
Stack: (0x80847ea0 to 0x80848000)
7ea0: 80847ecc 80847eb0 8001fb6c 8001ec88 80891c94 af01e080 8083f9e8 80891c94
7ec0: 80847f54 80847ed0 807dddd0 8001fb0c c0818060 00000018 00000000 80891c4c
7ee0: 00000000 80891c4c c0818024 af6644c0 c081803c c0818020 c0818060 c0818038
7f00: c0818028 c0818034 c0818048 c0818024 c081802c c0818014 8001e3dc c081801c
7f20: 80891c4c c0818000 016e3600 00000001 af6644c0 af002740 808801e4 00200200
7f40: 00100100 00000000 80847f94 80847f58 80807710 807da4bc 80880180 00000001
7f60: 00000000 00000000 00000000 00000000 808917c0 00000001 ffffffff 80820808
7f80: 8084e480 808917c0 80847fa4 80847f98 807d57b8 80807608 80847ff4 80847fa8
7fa0: 807d1bd4 807d5794 ffffffff ffffffff 807d16d0 00000000 00000000 affff9c0
7fc0: 00000000 80820808 00000000 80891a54 8084e4fc 80820804 808531c4 1000406a
7fe0: 412fc09a 00000000 00000000 80847ff8 10008074 807d1960 00000000 00000000
Backtrace:
[<8001ec7c>] (imx_gpc_irq_unmask) from [<8001fb6c>] (imx6q_set_lpm+0x6c/0xe0)
[<8001fb00>] (imx6q_set_lpm) from [<807dddd0>] (imx6q_clocks_init+0x3920/0x392c)
r7:80891c94 r6:8083f9e8 r5:af01e080 r4:80891c94
[<807da4b0>] (imx6q_clocks_init) from [<80807710>] (of_clk_init+0x114/0x1a4)
r10:00000000 r9:00100100 r8:00200200 r7:808801e4 r6:af002740 r5:af6644c0
r4:00000001
[<808075fc>] (of_clk_init) from [<807d57b8>] (time_init+0x30/0x38)
r10:808917c0 r9:8084e480 r8:80820808 r7:ffffffff r6:00000001 r5:808917c0
r4:00000000
[<807d5788>] (time_init) from [<807d1bd4>] (start_kernel+0x280/0x3dc)
[<807d1954>] (start_kernel) from [<10008074>] (0x10008074)
r10:00000000 r9:412fc09a r8:1000406a r7:808531c4 r6:80820804 r5:8084e4fc
r4:80891a54
Code: e92dd800 e24cb004 e52de004 ebffdbbb (e5903008)
---[ end trace cb88537fdc8fa200 ]---
> Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
> ---
> arch/arm/mach-imx/gpc.c | 18 +++++++++---------
> 1 file changed, 9 insertions(+), 9 deletions(-)
>
> diff --git a/arch/arm/mach-imx/gpc.c b/arch/arm/mach-imx/gpc.c
> index 82ea74e..1455829 100644
> --- a/arch/arm/mach-imx/gpc.c
> +++ b/arch/arm/mach-imx/gpc.c
> @@ -56,14 +56,14 @@ void imx_gpc_post_resume(void)
>
> static int imx_gpc_irq_set_wake(struct irq_data *d, unsigned int on)
> {
> - unsigned int idx = d->irq / 32 - 1;
> + unsigned int idx = d->hwirq / 32 - 1;
> u32 mask;
>
> /* Sanity check for SPI irq */
> - if (d->irq < 32)
> + if (d->hwirq < 32)
> return -EINVAL;
>
> - mask = 1 << d->irq % 32;
> + mask = 1 << d->hwirq % 32;
> gpc_wake_irqs[idx] = on ? gpc_wake_irqs[idx] | mask :
> gpc_wake_irqs[idx] & ~mask;
>
> @@ -97,12 +97,12 @@ void imx_gpc_irq_unmask(struct irq_data *d)
> u32 val;
>
> /* Sanity check for SPI irq */
> - if (d->irq < 32)
> + if (d->hwirq < 32)
> return;
>
> - reg = gpc_base + GPC_IMR1 + (d->irq / 32 - 1) * 4;
> + reg = gpc_base + GPC_IMR1 + (d->hwirq / 32 - 1) * 4;
> val = readl_relaxed(reg);
> - val &= ~(1 << d->irq % 32);
> + val &= ~(1 << d->hwirq % 32);
> writel_relaxed(val, reg);
> }
>
> @@ -112,12 +112,12 @@ void imx_gpc_irq_mask(struct irq_data *d)
> u32 val;
>
> /* Sanity check for SPI irq */
> - if (d->irq < 32)
> + if (d->hwirq < 32)
> return;
>
> - reg = gpc_base + GPC_IMR1 + (d->irq / 32 - 1) * 4;
> + reg = gpc_base + GPC_IMR1 + (d->hwirq / 32 - 1) * 4;
> val = readl_relaxed(reg);
> - val |= 1 << (d->irq % 32);
> + val |= 1 << (d->hwirq % 32);
> writel_relaxed(val, reg);
> }
>
More information about the linux-arm-kernel
mailing list