media: fix crash in viu_set_dcu
authorrongrong zhou <rongrong.zhou@amlogic.com>
Fri, 13 Apr 2018 06:46:33 +0000 (14:46 +0800)
committerYixun Lan <yixun.lan@amlogic.com>
Thu, 26 Apr 2018 10:49:39 +0000 (03:49 -0700)
PD#164288: 1. add check in viu_set_dcu.
2. do not clear cur_dispbuf in irq & unreg

Unable to handle kernel NULL pointer dereference at virtual address
 0000000c
task: ffffff800a688900 task.stack: ffffff800a670000
PC is at vsync_isr+0x2c20/0x51e0
LR is at vsync_isr+0x2c04/0x51e0
[<ffffff80098398cc>] vsync_isr+0x2c20/0x51e0
[<ffffff80091072bc>] __handle_irq_event_percpu+0x68/0x23c
[<ffffff80091074d0>] handle_irq_event_percpu+0x40/0x94
[<ffffff8009107570>] handle_irq_event+0x4c/0x7c
[<ffffff800910b66c>] handle_fasteoi_irq+0xd4/0x1a4
[<ffffff8009106268>] generic_handle_irq+0x34/0x4c
[<ffffff8009106974>] __handle_domain_irq+0x90/0xf8
[<ffffff80090815f4>] gic_handle_irq+0x5c/0xa8

Change-Id: I871bf078c25cbb92889d592ee7cb88cea62f089c
Signed-off-by: rongrong zhou <rongrong.zhou@amlogic.com>
drivers/amlogic/media/video_sink/video.c

index 8a32217..c2e6c65 100644 (file)
@@ -2594,9 +2594,14 @@ static void viu_set_dcu(struct vpp_frame_par_s *frame_par, struct vframe_s *vf)
        static const u32 vpat[MAX_VSKIP_COUNT + 1] = {
                0, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf};
        u32 u, v;
-       u32 type = vf->type, bit_mode = 0;
+       u32 type, bit_mode = 0;
        bool vf_with_el = false;
 
+       if (vf == NULL) {
+               pr_info("viu_set_dcu vf NULL, return\n");
+               return;
+       }
+       type = vf->type;
        pr_debug("set dcu for vd1 %p, type:0x%x\n", vf, type);
        if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXBB) {
                if (frame_par->nocomp)
@@ -6657,7 +6662,9 @@ static long amvideo_ioctl(struct file *file, unsigned int cmd, ulong arg)
 
        case AMSTREAM_IOC_CLEAR_VBUF:{
                        unsigned long flags;
-
+                       while (atomic_read(&video_inirq_flag) > 0 ||
+                               atomic_read(&video_unreg_flag) > 0)
+                               schedule();
                        spin_lock_irqsave(&lock, flags);
                        cur_dispbuf = NULL;
                        spin_unlock_irqrestore(&lock, flags);