]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - drivers/mxc/ipu3/ipu_device.c
ENGR00295201 ipuv3: vdic: kernel dump when run deinterlace stress test
[karo-tx-linux.git] / drivers / mxc / ipu3 / ipu_device.c
index 8f6b957de3b0bd41f7f7ef25553a606ff55e3a04..f1f6ad16ff201fde12938f9f34e471d527b2e156 100644 (file)
@@ -286,6 +286,7 @@ struct ipu_task_entry {
        u8      task_in_list;
        u8      split_done;
        struct mutex split_lock;
+       struct mutex vdic_lock;
        wait_queue_head_t split_waitq;
 
        struct list_head node;
@@ -1697,10 +1698,12 @@ static int queue_split_task(struct ipu_task_entry *t,
        int i, j;
        struct ipu_task_entry *tsk = NULL;
        struct mutex *lock = &t->split_lock;
+       struct mutex *vdic_lock = &t->vdic_lock;
 
        dev_dbg(t->dev, "Split task 0x%p, no-0x%x, size:%d\n",
                         t, t->task_no, size);
        mutex_init(lock);
+       mutex_init(vdic_lock);
        init_waitqueue_head(&t->split_waitq);
        INIT_LIST_HEAD(&t->split_list);
        for (j = 0; j < size; j++) {
@@ -2389,11 +2392,13 @@ static void vdi_split_process(struct ipu_soc *ipu, struct ipu_task_entry *t)
        u32 line_size;
        unsigned char  *base_off;
        struct ipu_task_entry *parent = t->parent;
+       struct mutex *lock = &parent->vdic_lock;
 
        if (!parent) {
                dev_err(t->dev, "ERR[0x%x]invalid parent\n", t->task_no);
                return;
        }
+       mutex_lock(lock);
        stripe_mode = t->task_no & 0xf;
        task_no = t->task_no >> 4;
 
@@ -2410,6 +2415,7 @@ static void vdi_split_process(struct ipu_soc *ipu, struct ipu_task_entry *t)
        vdi_size = vdi_save_lines * line_size;
        if (vdi_save_lines <= 0) {
                dev_err(t->dev, "[0x%p] vdi_save_line error\n", (void *)t);
+               mutex_unlock(lock);
                return;
        }
 
@@ -2425,6 +2431,7 @@ static void vdi_split_process(struct ipu_soc *ipu, struct ipu_task_entry *t)
                if (parent->vditmpbuf[0] == NULL) {
                        dev_err(t->dev,
                                "[0x%p]Falied Alloc vditmpbuf[0]\n", (void *)t);
+                       mutex_unlock(lock);
                        return;
                }
                memset(parent->vditmpbuf[0], 0, vdi_size);
@@ -2433,6 +2440,7 @@ static void vdi_split_process(struct ipu_soc *ipu, struct ipu_task_entry *t)
                if (parent->vditmpbuf[1] == NULL) {
                        dev_err(t->dev,
                                "[0x%p]Falied Alloc vditmpbuf[1]\n", (void *)t);
+                       mutex_unlock(lock);
                        return;
                }
                memset(parent->vditmpbuf[1], 0, vdi_size);
@@ -2451,6 +2459,7 @@ static void vdi_split_process(struct ipu_soc *ipu, struct ipu_task_entry *t)
        }
        if (base_off == NULL) {
                dev_err(t->dev, "ERR[0x%p]Failed get virtual address\n", t);
+               mutex_unlock(lock);
                return;
        }
 
@@ -2573,6 +2582,7 @@ static void vdi_split_process(struct ipu_soc *ipu, struct ipu_task_entry *t)
        }
        if (!pfn_valid(t->output.paddr >> PAGE_SHIFT))
                iounmap(base_off);
+       mutex_unlock(lock);
 }
 
 static void do_task_release(struct ipu_task_entry *t, int fail)