vdin: improve robustness of vdin drvier for reentry case [1/1]
authorzhiwei.yuan <zhiwei.yuan@amlogic.com>
Fri, 30 Aug 2019 07:04:13 +0000 (15:04 +0800)
committerTao Zeng <tao.zeng@amlogic.com>
Mon, 2 Sep 2019 06:59:50 +0000 (23:59 -0700)
PD#SWPL-13492

Problem:
disable irq cnt don't equal to enable

Solution:
corrent mutex mechanism for vdin driver

Verify:
verified by t962x2_x301

Change-Id: I9d33c8297c9ed4d155233948d1d6bb7dfc6ca4a4
Signed-off-by: zhiwei.yuan <zhiwei.yuan@amlogic.com>
drivers/amlogic/media/vin/tvin/vdin/vdin_debug.c
drivers/amlogic/media/vin/tvin/vdin/vdin_drv.c

index 6e69237..916b9a0 100644 (file)
@@ -1490,8 +1490,16 @@ static ssize_t vdin_attr_store(struct device *dev,
                ret = request_irq(devp->irq, vdin_isr, IRQF_SHARED,
                                devp->irq_name, (void *)devp);
 
+               if (vdin_dbg_en)
+                       pr_info("%s vdin.%d request_irq\n", __func__,
+                               devp->index);
+
                /*disable irq until vdin is configured completely*/
                disable_irq_nosync(devp->irq);
+
+               if (vdin_dbg_en)
+                       pr_info("%s vdin.%d disable_irq_nosync\n", __func__,
+                               devp->index);
                /*init queue*/
                init_waitqueue_head(&devp->queue);
                /* remove the hardware limit to vertical [0-max]*/
@@ -1551,6 +1559,10 @@ start_chk:
                devp->flags &= (~VDIN_FLAG_DEC_STARTED);
                /* free irq */
                free_irq(devp->irq, (void *)devp);
+
+               if (vdin_dbg_en)
+                       pr_info("%s vdin.%d free_irq\n", __func__,
+                               devp->index);
                /* reset the hardware limit to vertical [0-1079]  */
                /* WRITE_VCBUS_REG(VPP_PREBLEND_VD1_V_START_END, 0x00000437); */
        } else if (!strcmp(parm[0], "v4l2stop")) {
index 5956fbb..826baa4 100644 (file)
@@ -735,6 +735,10 @@ void vdin_stop_dec(struct vdin_dev_s *devp)
 
        disable_irq_nosync(devp->irq);
 
+       if (vdin_dbg_en)
+               pr_info("%s vdin.%d disable_irq_nosync\n", __func__,
+                       devp->index);
+
        if (devp->afbce_mode == 1) {
                while (i++ < afbc_write_down_timeout) {
                        if (vdin_afbce_read_writedown_flag())
@@ -939,6 +943,10 @@ int start_tvin_service(int no, struct vdin_parm_s  *para)
                ret = request_irq(devp->irq, vdin_v4l2_isr, IRQF_SHARED,
                                devp->irq_name, (void *)devp);
 
+               if (vdin_dbg_en)
+                       pr_info("%s vdin.%d request_irq\n", __func__,
+                               devp->index);
+
                if (ret != 0) {
                        pr_info("vdin_v4l2_isr request irq error.\n");
                        return -1;
@@ -987,6 +995,10 @@ int stop_tvin_service(int no)
        if ((devp->parm.port != TVIN_PORT_VIU1) ||
                (viu_hw_irq != 0)) {
                free_irq(devp->irq, (void *)devp);
+
+               if (vdin_dbg_en)
+                       pr_info("%s vdin.%d free_irq\n", __func__,
+                               devp->index);
                devp->flags &= (~VDIN_FLAG_ISR_REQ);
        }
        end_time = jiffies_to_msecs(jiffies);
@@ -2184,20 +2196,28 @@ static int vdin_open(struct inode *inode, struct file *file)
 
        /* request irq */
        if (work_mode_simple) {
-               if (vdin_dbg_en)
-                       pr_info("vdin.%d work in simple mode.\n", devp->index);
                ret = request_irq(devp->irq, vdin_isr_simple, IRQF_SHARED,
                                devp->irq_name, (void *)devp);
-       } else {
+
                if (vdin_dbg_en)
-                       pr_info("vdin.%d work in normal mode.\n", devp->index);
+                       pr_info("%s vdin.%d simple request_irq\n", __func__,
+                               devp->index);
+       } else {
                ret = request_irq(devp->irq, vdin_isr, IRQF_SHARED,
                                devp->irq_name, (void *)devp);
+
+               if (vdin_dbg_en)
+                       pr_info("%s vdin.%d request_irq\n", __func__,
+                               devp->index);
        }
        devp->flags |= VDIN_FLAG_ISR_REQ;
        /*disable irq until vdin is configured completely*/
        disable_irq_nosync(devp->irq);
 
+       if (vdin_dbg_en)
+               pr_info("%s vdin.%d disable_irq_nosync\n", __func__,
+                       devp->index);
+
        /*init queue*/
        init_waitqueue_head(&devp->queue);
 
@@ -2243,8 +2263,13 @@ static int vdin_release(struct inode *inode, struct file *file)
        devp->flags &= (~VDIN_FLAG_SNOW_FLAG);
 
        /* free irq */
-       if (devp->flags & VDIN_FLAG_ISR_REQ)
+       if (devp->flags & VDIN_FLAG_ISR_REQ) {
                free_irq(devp->irq, (void *)devp);
+
+               if (vdin_dbg_en)
+                       pr_info("%s vdin.%d free_irq\n", __func__,
+                               devp->index);
+       }
        devp->flags &= (~VDIN_FLAG_ISR_REQ);
 
        file->private_data = NULL;
@@ -2385,9 +2410,10 @@ static long vdin_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
                        (viu_hw_irq != 0)) {
                        /*enable irq */
                        enable_irq(devp->irq);
+
                        if (vdin_dbg_en)
-                               pr_info("****[%s]enable_irq ifdef VDIN_V2****\n",
-                                               __func__);
+                               pr_info("%s START_DEC vdin.%d enable_irq\n",
+                                       __func__, devp->index);
                }
 
                devp->flags |= VDIN_FLAG_DEC_STARTED;
@@ -2408,10 +2434,12 @@ static long vdin_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
                        mutex_unlock(&devp->fe_lock);
                        break;
                }
+
                if (time_en) {
                        devp->start_time = jiffies_to_msecs(jiffies);
                        pr_info("TVIN_IOC_STOP_DEC %ums.\n", devp->start_time);
                }
+
                devp->flags |= VDIN_FLAG_DEC_STOP_ISR;
                vdin_stop_dec(devp);
                /* init flag */
@@ -2694,7 +2722,7 @@ static long vdin_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
                }
                break;
        case TVIN_IOC_GET_LATENCY_MODE:
-               mutex_unlock(&devp->fe_lock);
+               mutex_lock(&devp->fe_lock);
                if (copy_to_user(argp,
                        &(devp->prop.latency),
                        sizeof(struct tvin_latency_s))) {
@@ -2750,9 +2778,14 @@ static long vdin_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
                        pr_info("TVIN_IOC_S_VDIN_V4L2START cann't be used at vdin0\n");
                        break;
                }
-               if (devp->flags & VDIN_FLAG_ISR_REQ)
+               if (devp->flags & VDIN_FLAG_ISR_REQ) {
                        free_irq(devp->irq, (void *)devp);
 
+                       if (vdin_dbg_en)
+                               pr_info("%s vdin.%d free_irq\n", __func__,
+                                       devp->index);
+               }
+
                if (copy_from_user(&vdin_v4l2_param, argp,
                                sizeof(struct vdin_v4l2_param_s))) {
                        pr_info("vdin_v4l2_param copy fail\n");