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 <zhiwei.yuan@amlogic.com>
This commit is contained in:
zhiwei.yuan
2019-08-30 15:04:13 +08:00
committed by Tao Zeng
parent 0e1da739ae
commit a1cd76a48c
2 changed files with 54 additions and 9 deletions

View 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")) {

View 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");