From bdde708ebfde4a8c1d3829578d3f6481a343533a Mon Sep 17 00:00:00 2001 From: Robby Cai Date: Thu, 15 Aug 2013 20:18:15 +0800 Subject: ENGR00275459 mx6sl: csi/v4l: fix kernel dump when do repeated streamon/streamoff When do stream on/off in pair repeatedly without close the v4l device, the kernel dump happens: Unable to handle kernel paging request at virtual address 00200200 pgd = c0004000 [00200200] *pgd=00000000 Internal error: Oops: 805 [#1] PREEMPT Modules linked in: CPU: 0 Not tainted (3.0.35-06027-gbbea887-dirty #21) PC is at camera_callback+0x15c/0x1c8 LR is at 0x200200 pc : [] lr : [<00200200>] psr: 20000193 sp : c0b0fed0 ip : 00200200 fp : daf1102c r10: daf11034 r9 : 00100100 r8 : daf11098 r7 : daf11100 r6 : daf11034 r5 : daf11000 r4 : c0b0e000 r3 : 00000000 r2 : 00000001 r1 : 00000001 r0 : daf114b8 Flags: nzCv IRQs off FIQs on Mode SVC_32 ISA ARM Segment kernel Control: 10c53c7d Table: 8cc8c059 DAC: 00000015 ... Process swapper (pid: 0, stack limit = 0xc0b0e2e8) Stack: (0xc0b0fed0 to 0xc0b10000) fec0: c0374674 822a4000 daf11000 c0b87eb4 fee0: 00000000 00000027 c0b73904 c0b305e0 00000001 c0374090 da2bbbe0 c0b0e000 ff00: 00000000 c00acc58 00000000 c0098058 00989680 c0b305e0 c0b0e000 00000000 ff20: 00000002 00000001 c0b0e000 00000000 00000000 c00acdf8 00000000 c0b0e000 ff40: 9e4e7881 c0b305e0 c0b0e000 c00aee44 c00aed9c c0b43c6c 00000027 c00ac634 ff60: 00000270 c004257c ffffffff f2a00100 00000027 c00417cc 20000000 00000006 ff80: f40c4000 00000000 c0b0e000 c0b6a924 c0b1876c c0b18764 80004059 412fc09a ffa0: 00000000 00000000 c0063a40 c0b0ffc0 c004f758 c0042690 80000013 ffffffff ffc0: c004266c c004294c c0b1013c 00000000 c10960c0 c00088ec c0008334 00000000 ffe0: 00000000 c00337d4 10c53c7d c0b10060 c00337d0 80008040 00000000 00000000 [] (camera_callback+0x15c/0x1c8) from [] (csi_irq_handler+ 0x7c/0x160) [] (csi_irq_handler+0x7c/0x160) from [] ( handle_irq_event_percpu+0x50/0x19c) [] (handle_irq_event_percpu+0x50/0x19c) from [] ( handle_irq_event+0x54/0x84) [] (handle_irq_event+0x54/0x84) from [] (handle_fasteoi_irq +0xa8/0x160) [] (handle_fasteoi_irq+0xa8/0x160) from [] ( generic_handle_irq+0x2c/0x40) [] (generic_handle_irq+0x2c/0x40) from [] (handle_IRQ +0x30/0x84) [] (handle_IRQ+0x30/0x84) from [] (__irq_svc+0x4c/0xa8) [] (__irq_svc+0x4c/0xa8) from [] (default_idle+0x24/0x28) [] (default_idle+0x24/0x28) from [] (cpu_idle+0x8c/0xc0) [] (cpu_idle+0x8c/0xc0) from [] (start_kernel+0x294/0x2e4) [] (start_kernel+0x294/0x2e4) from [<80008040>] (0x80008040) Code: e88c4200 e595c030 e5858030 e8881800 (e58c8000) ---[ end trace 224150c26d2bd5f7 ]--- The root cause is cam->enc_counter is not re-initialized to 0 when calls STREAMOFF ioctl, and then in DQBUF ioctl wait_event_interruptible_timeout() sees the condition is true and access cam->done_q queue which has no strict check and could be empty. This patch adds the re-initialization and the sanity check. Also, add the pointer check for memcpy because the destination may be NULL on UERSPTR mode. Signed-off-by: Robby Cai --- drivers/media/video/mxc/capture/csi_v4l2_capture.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/video/mxc/capture/csi_v4l2_capture.c b/drivers/media/video/mxc/capture/csi_v4l2_capture.c index adc77d3b64a1..68dda9b98490 100644 --- a/drivers/media/video/mxc/capture/csi_v4l2_capture.c +++ b/drivers/media/video/mxc/capture/csi_v4l2_capture.c @@ -484,6 +484,7 @@ static void csi_free_frames(cam_data *cam) for (i = 0; i < FRAME_NUM; i++) cam->frame[i].buffer.flags = V4L2_BUF_FLAG_MAPPED; + cam->enc_counter = 0; INIT_LIST_HEAD(&cam->ready_q); INIT_LIST_HEAD(&cam->working_q); INIT_LIST_HEAD(&cam->done_q); @@ -1025,6 +1026,12 @@ static int csi_v4l_dqueue(cam_data *cam, struct v4l2_buffer *buf) spin_lock_irqsave(&cam->dqueue_int_lock, lock_flags); + if (list_empty(&cam->done_q)) { + spin_unlock_irqrestore(&cam->dqueue_int_lock, lock_flags); + up(&cam->busy_lock); + return -EINVAL; + } + cam->enc_counter--; frame = list_entry(cam->done_q.next, struct mxc_v4l_frame, queue); @@ -1065,7 +1072,8 @@ static int csi_v4l_dqueue(cam_data *cam, struct v4l2_buffer *buf) return retval; } pxp_complete_update(cam); - memcpy(cam->frame[buf->index].vaddress, + if (cam->frame[buf->index].vaddress) + memcpy(cam->frame[buf->index].vaddress, cam->frame[req_buf_number].vaddress, cam->v2f.fmt.pix.sizeimage); } -- cgit v1.2.3