From a1cd76a48cfd2fb365a4d4a73328f3f5ee207e7a Mon Sep 17 00:00:00 2001 From: "zhiwei.yuan" Date: Fri, 30 Aug 2019 15:04:13 +0800 Subject: [PATCH] vdin: improve robustness of vdin drvier for reentry case [1/1] 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 --- drivers/amlogic/media/vin/tvin/vdin/vdin_debug.c | 12 ++++++ drivers/amlogic/media/vin/tvin/vdin/vdin_drv.c | 51 +++++++++++++++++++----- 2 files changed, 54 insertions(+), 9 deletions(-) diff --git a/drivers/amlogic/media/vin/tvin/vdin/vdin_debug.c b/drivers/amlogic/media/vin/tvin/vdin/vdin_debug.c index 6e69237..916b9a0 100644 --- a/drivers/amlogic/media/vin/tvin/vdin/vdin_debug.c +++ b/drivers/amlogic/media/vin/tvin/vdin/vdin_debug.c @@ -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")) { diff --git a/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.c b/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.c index 5956fbb..826baa4 100644 --- a/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.c +++ b/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.c @@ -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"); -- 2.7.4