MLK-11527 ARM: imx: gpcv2: using irq number wrongly
authorPeter Chen <peter.chen@freescale.com>
Wed, 9 Sep 2015 04:58:47 +0000 (12:58 +0800)
committerNitin Garg <nitin.garg@nxp.com>
Mon, 19 Mar 2018 19:48:32 +0000 (14:48 -0500)
We should use hwirq instead of logic number at gpc driver, otherwise,
it may override other global memory due to write out of boundary
for array, eg: below oops may kernel at imx7d sdb board during suspend/
resume test:

INFO: rcu_preempt detected stalls on CPUs/tasks:
1: (2 GPs behind) idle=b25/140000000000000/0 softirq=1951/1957 fqs=0
(detected by 0, t=2102 jiffies, g=847, c=846, q=4)
Task dump for CPU 1:
swapper/1       R running   6088     0      1 0x00000000
[<8089f4e4>] (__schedule) from [<8089f908>] (schedule+0x4c/0xa4)
[<8089f908>] (schedule) from [<80011514>] (arch_cpu_idle_dead+0x18/0x1c)
[<80011514>] (arch_cpu_idle_dead) from [<8006e3d8>] (cpu_startup_entry+0x2e0/0x450)
[<8006e3d8>] (cpu_startup_entry) from [<80017200>] (secondary_start_kernel+0x13c/0x15c)
[<80017200>] (secondary_start_kernel) from [<800095ac>] (__enable_mmu+0x0/0x14)
rcu_preempt kthread starved for 2102 jiffies!
NMI watchdog: BUG: soft lockup - CPU#0 stuck for 22s! [rtcwakeup.out:735]
Modules linked in: evbug
CPU: 0 PID: 735 Comm: rtcwakeup.out Tainted: G        W       4.1.4-00701-g32bb3ba-dirty #370
Hardware name: Freescale i.MX7 Dual (Device Tree)
task: a8920a00 ti: a99bc000 task.ti: a99bc000
PC is at _raw_spin_lock+0x4c/0x60
LR is at get_parent_ip+0x14/0x30
pc : [<808a2e74>]    lr : [<8005c080>]    psr: 80000013
sp : a99bdcd8  ip : a99bdca8  fp : a99bdcec
r10: 80d4455c  r9 : 00008070  r8 : 00000010
r7 : 00000000  r6 : 00000000  r5 : 00000001  r4 : 80e09934
r3 : 00000001  r2 : 00000000  r1 : 00000000  r0 : 00000000
Flags: Nzcv  IRQs on  FIQs on  Mode SVC_32  ISA ARM  Segment user
Control: 10c5387d  Table: a9f0006a  DAC: 00000015
CPU: 0 PID: 735 Comm: rtcwakeup.out Tainted: G        W       4.1.4-00701-g32bb3ba-dirty #370
Hardware name: Freescale i.MX7 Dual (Device Tree)
[<80019258>] (unwind_backtrace) from [<80014948>] (show_stack+0x20/0x24)
[<80014948>] (show_stack) from [<8089b490>] (dump_stack+0x8c/0xcc)
[<8089b490>] (dump_stack) from [<80011714>] (show_regs+0x1c/0x20)
[<80011714>] (show_regs) from [<800af83c>] (watchdog_timer_fn+0x290/0x2fc)
[<800af83c>] (watchdog_timer_fn) from [<8008c0a8>] (__run_hrtimer+0x90/0x294)
[<8008c0a8>] (__run_hrtimer) from [<8008cd94>] (hrtimer_interrupt+0x11c/0x2ac)
[<8008cd94>] (hrtimer_interrupt) from [<80618a4c>] (arch_timer_handler_phys+0x40/0x48)
[<80618a4c>] (arch_timer_handler_phys) from [<8007ca24>] (handle_percpu_devid_irq+0xac/0x1d0)
[<8007ca24>] (handle_percpu_devid_irq) from [<80078334>] (generic_handle_irq+0x3c/0x4c)
[<80078334>] (generic_handle_irq) from [<80078660>] (__handle_domain_irq+0x8c/0xfc)
[<80078660>] (__handle_domain_irq) from [<800094e4>] (gic_handle_irq+0x34/0x6c)
[<800094e4>] (gic_handle_irq) from [<80015500>] (__irq_svc+0x40/0x74)
Exception stack(0xa99bdc90 to 0xa99bdcd8)
dc80:                                     00000000 00000000 00000000 00000001
dca0: 80e09934 00000001 00000000 00000000 00000010 00008070 80d4455c a99bdcec
dcc0: a99bdca8 a99bdcd8 8005c080 808a2e74 80000013 ffffffff
[<80015500>] (__irq_svc) from [<808a2e74>] (_raw_spin_lock+0x4c/0x60)
[<808a2e74>] (_raw_spin_lock) from [<8002ac14>] (imx_enable_cpu+0x34/0xc8)
[<8002ac14>] (imx_enable_cpu) from [<8002b548>] (imx_cpu_kill+0x60/0x94)
[<8002b548>] (imx_cpu_kill) from [<80017090>] (__cpu_die+0x60/0x94)
[<80017090>] (__cpu_die) from [<808959bc>] (_cpu_down+0x1e4/0x2fc)
[<808959bc>] (_cpu_down) from [<80036f7c>] (disable_nonboot_cpus+0xd0/0x264)
[<80036f7c>] (disable_nonboot_cpus) from [<80073984>] (suspend_devices_and_enter+0x344/0x910)
[<80073984>] (suspend_devices_and_enter) from [<8007433c>] (pm_suspend+0x3ec/0x6e4)
[<8007433c>] (pm_suspend) from [<80072754>] (state_store+0x7c/0xcc)
[<80072754>] (state_store) from [<803455e4>] (kobj_attr_store+0x1c/0x28)
[<803455e4>] (kobj_attr_store) from [<8019f670>] (sysfs_kf_write+0x54/0x58)
[<8019f670>] (sysfs_kf_write) from [<8019ea40>] (kernfs_fop_write+0xc8/0x1ac)
[<8019ea40>] (kernfs_fop_write) from [<8013285c>] (__vfs_write+0x34/0xe8)
[<8013285c>] (__vfs_write) from [<801330cc>] (vfs_write+0xa0/0x174)
[<801330cc>] (vfs_write) from [<80133970>] (SyS_write+0x54/0xb0)
[<80133970>] (SyS_write) from [<800108c0>] (ret_fast_syscall+0x0/0x3c)

Signed-off-by: Peter Chen <peter.chen@freescale.com>
arch/arm/mach-imx/gpcv2.c

index 69b8394..b1d666c 100644 (file)
@@ -116,6 +116,8 @@ static int imx_gpcv2_irq_set_wake(struct irq_data *d, unsigned int on)
        unsigned long flags;
        u32 mask;
 
+       BUG_ON(idx >= IMR_NUM);
+
        mask = 1 << d->hwirq % 32;
        spin_lock_irqsave(&gpcv2_lock, flags);
        gpcv2_wake_irqs[idx] = on ? gpcv2_wake_irqs[idx] | mask :
@@ -432,11 +434,14 @@ static void imx_gpcv2_mf_mix_off(void)
 
 int imx_gpcv2_mf_power_on(unsigned int irq, unsigned int on)
 {
-       unsigned int idx = irq / 32 - 1;
+       struct irq_desc *desc = irq_to_desc(irq);
+       unsigned long hwirq = desc->irq_data.hwirq;
+       unsigned int idx = hwirq / 32;
        unsigned long flags;
-       u32 mask;
+       u32 mask = 1 << (hwirq % 32);
+
+       BUG_ON(idx >= IMR_NUM);
 
-       mask = 1 << (irq % 32);
        spin_lock_irqsave(&gpcv2_lock, flags);
        gpcv2_mf_request_on[idx] = on ? gpcv2_mf_request_on[idx] | mask :
                                  gpcv2_mf_request_on[idx] & ~mask;