]> git.karo-electronics.de Git - karo-tx-linux.git/commit
ENGR00225520 SDMA:fix kernel dump occasionally during I2C stress test
authorNicolin Chen <b42378@freescale.com>
Tue, 16 Oct 2012 08:20:03 +0000 (16:20 +0800)
committerLothar Waßmann <LW@KARO-electronics.de>
Fri, 24 May 2013 06:35:35 +0000 (08:35 +0200)
commit5178423ff133f537472029aacb7194facc4cedd3
tree55060a86900c68b4f16f0f699ee222a62e42168a
parentab1bba69a9951398428a7a94e35d7f4cf909e5c4
ENGR00225520 SDMA:fix kernel dump occasionally during I2C stress test

 Stress test with I2C devices occasionally caused kernel dump and panic:
==========================dump=start==========================
v4l_capture_testapp    0  TINFO  :
  Color space conversion YUV420->RGB565X success!
v4l_capture_testapp    0  TINFO  :
  Color space conversion YUV420->RGB565X success!
clean up environment...VPU interrupt received.

Unable to handle kernel paging request at virtual address ffdf401a
pgd = ba2a4000
[ffdf401a] *pgd=4fe1a811, *pte=00000000, *ppte=00000000
Internal error: Oops: 7 [#1] PREEMPT SMP
Modules linked in: mxc_v4l2_capture ipu_still ipu_bg_overlay_sdc
 ipu_prp_enc ipu_fg_overlay_sdc ipu_csi_enc ov5642_camera
  camera_sensor_clock [last unloaded: ipu_csi_enc]
CPU: 0    Not tainted  (3.0.35-2039-g267e004 #1)
PC is at sdma_int_handler+0x144/0x1a4
LR is at sdma_int_handler+0x70/0x1a4
pc : [<802663f4>]    lr : [<80266320>]    psr: 60000193
sp : ba3e7ca8  ip : bfee2100  fp : 00000001
r10: 80a67200  r9 : 80acbcf0  r8 : 00000003
r7 : 00000001  r6 : 00000001  r5 : 00000002  r4 : bfee20e0
r3 : ffdf4000  r2 : 00010104  r1 : ffdf4018  r0 : bfee2104
Flags: nZCv  IRQs off  FIQs on  Mode SVC_32  ISA ARM  Segment user
Control: 10c53c7d  Table: 4a2a404a  DAC: 00000015
Process mxc_vpu_test.ou (pid: 3277, stack limit = 0xba3e62f0)
Stack: (0xba3e7ca8 to 0xba3e8000)
7ca0:                   80038f40 bfee2000 002977e3 bf9cda80
 80a6724c 00000000
7cc0: 00000000 00000022 80acbcf0 80a67200 00000001 800a5cb8
 0000f08f 00000000
[<802663f4>] (sdma_int_handler+0x144/0x1a4)
 from [<800a5cb8>] (handle_irq_event_percpu+0x50/0x180)
[<800a5cb8>] (handle_irq_event_percpu+0x50/0x180)
 from [<800a5e24>] (handle_irq_event+0x3c/0x5c)
[<800a5e24>] (handle_irq_event+0x3c/0x5c)
 from [<800a81a8>] (handle_fasteoi_irq+0xbc/0x154)
[<800a81a8>] (handle_fasteoi_irq+0xbc/0x154)
 from [<800a5620>] (generic_handle_irq+0x28/0x3c)
[<800a5620>] (generic_handle_irq+0x28/0x3c)
 from [<80040830>] (handle_IRQ+0x4c/0xac)
[<80040830>] (handle_IRQ+0x4c/0xac)
 from [<8003f9cc>] (__irq_svc+0x4c/0xe8)
[<8003f9cc>] (__irq_svc+0x4c/0xe8)
 from [<800764f4>] (__do_softirq+0x4c/0x140)
[<800764f4>] (__do_softirq+0x4c/0x140)
 from [<80076a90>] (irq_exit+0x94/0x9c)
[<80076a90>] (irq_exit+0x94/0x9c)
 from [<8003a1b4>] (do_local_timer+0x70/0x90)
[<8003a1b4>] (do_local_timer+0x70/0x90)
 from [<8003f9cc>] (__irq_svc+0x4c/0xe8)
Exception stack(0xba3e7de8 to 0xba3e7e30)
[<8003f9cc>] (__irq_svc+0x4c/0xe8)
 from [<80071a88>] (vprintk+0x328/0x4a8)
[<80071a88>] (vprintk+0x328/0x4a8)
 from [<804ddb28>] (printk+0x1c/0x2c)
[<804ddb28>] (printk+0x1c/0x2c)
 from [<80390de0>] (vpu_ioctl+0x2cc/0x864)
[<80390de0>] (vpu_ioctl+0x2cc/0x864)
 from [<800fc314>] (do_vfs_ioctl+0x80/0x54c)
[<800fc314>] (do_vfs_ioctl+0x80/0x54c)
 from [<800fc818>] (sys_ioctl+0x38/0x5c)
[<800fc818>] (sys_ioctl+0x38/0x5c)
 from [<8003ff80>] (ret_fast_syscall+0x0/0x30)
Code: e594101c e5943038 e0811081 e0831101 (e5d13002)
---[ end trace 82daf36a5a07d470 ]---
Kernel panic - not syncing: Fatal exception in interrupt
Rebooting in 60 seconds..
==========================dump=end==========================
 This kernel dump only happened after one period of stress-test's done.

 From the dump info above, we just located the issue happened in SDMA driver.
 Regularly, it'd not be any problem when sdma_int_handler()'s called. But after
tracing, we found that in those occasional times, the last one irq of a channel
hadn't been responded while sdma_free_chan_resources() was already done.
 sdma_free_chan_resources() should be called in the end of the procedure. Any
irq wouldn't occur after its resources're freed.
 But considering about stress test, the test scripts uses "kill" cmd to close
aplay, which means pcm_free() might be called before last buffer's transmission
was finished. Plus, many modules're working in the same time during the test.
So CPU0, the only core can handle irq, would be busy with irq-handlings, while
the other CPU cores(i.e. CPU1~3) might be idle and deal with free() much faster
than CPU0's irq-handling. Then kernel panic.

 Since we know, in some extreme circumstances, the irq would not be handled in
time, we can manually handle the irq ONLY IF we could still detect one irq to
the channel in the beginning of free(), right before its resources's gonna be
freed.
 This Patch added checking code in the beginning of sdma_free_chan_resources()
to detect when the channel's gonna be freed if there's still one irq pended.
If so, just handle the irq manually before we free it.
 Again, considering about sdma_int_handler() might be running at the same time,
and if it already cleared the value of reg but hadn't handled the irq yet, also
added code to pend free() until irq to the channel was handled.

Signed-off-by: Nicolin Chen <b42378@freescale.com>
drivers/dma/imx-sdma.c