From: Hans Verkuil <hans.verkuil@xxxxxxxxx> Add proper locking to the file operations, allowing for the removal of the V4L2_FL_LOCK_ALL_FOPS flag. Signed-off-by: Hans Verkuil <hans.verkuil@xxxxxxxxx> --- drivers/media/video/s5p-fimc/fimc-capture.c | 36 +++++++++++++++++++-------- 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/drivers/media/video/s5p-fimc/fimc-capture.c b/drivers/media/video/s5p-fimc/fimc-capture.c index 62ce539..62045dc 100644 --- a/drivers/media/video/s5p-fimc/fimc-capture.c +++ b/drivers/media/video/s5p-fimc/fimc-capture.c @@ -479,17 +479,22 @@ static int fimc_capture_set_default_format(struct fimc_dev *fimc); static int fimc_capture_open(struct file *file) { struct fimc_dev *fimc = video_drvdata(file); - int ret = v4l2_fh_open(file); + int ret; + + /* Return if the corresponding video mem2mem node is already opened. */ + if (fimc_m2m_active(fimc)) + return -EBUSY; + ret = v4l2_fh_open(file); if (ret) return ret; dbg("pid: %d, state: 0x%lx", task_pid_nr(current), fimc->state); - /* Return if the corresponding video mem2mem node is already opened. */ - if (fimc_m2m_active(fimc)) - return -EBUSY; - + if (mutex_lock_interruptible(&fimc->lock)) { + v4l2_fh_release(file); + return -ERESTARTSYS; + } set_bit(ST_CAPT_BUSY, &fimc->state); pm_runtime_get_sync(&fimc->pdev->dev); @@ -503,6 +508,7 @@ static int fimc_capture_open(struct file *file) fimc->vid_cap.refcnt--; v4l2_fh_release(file); clear_bit(ST_CAPT_BUSY, &fimc->state); + mutex_unlock(&fimc->lock); return ret; } ret = fimc_capture_ctrls_create(fimc); @@ -510,6 +516,7 @@ static int fimc_capture_open(struct file *file) if (!ret && !fimc->vid_cap.user_subdev_api) ret = fimc_capture_set_default_format(fimc); } + mutex_unlock(&fimc->lock); return ret; } @@ -519,6 +526,7 @@ static int fimc_capture_close(struct file *file) dbg("pid: %d, state: 0x%lx", task_pid_nr(current), fimc->state); + mutex_lock(&fimc->lock); if (--fimc->vid_cap.refcnt == 0) { clear_bit(ST_CAPT_BUSY, &fimc->state); fimc_stop_capture(fimc, false); @@ -532,6 +540,7 @@ static int fimc_capture_close(struct file *file) vb2_queue_release(&fimc->vid_cap.vbq); fimc_ctrls_delete(fimc->vid_cap.ctx); } + mutex_unlock(&fimc->lock); return v4l2_fh_release(file); } @@ -539,15 +548,24 @@ static unsigned int fimc_capture_poll(struct file *file, struct poll_table_struct *wait) { struct fimc_dev *fimc = video_drvdata(file); + unsigned res; - return vb2_poll(&fimc->vid_cap.vbq, file, wait); + mutex_lock(&fimc->lock); + res = vb2_poll(&fimc->vid_cap.vbq, file, wait); + mutex_unlock(&fimc->lock); + return res; } static int fimc_capture_mmap(struct file *file, struct vm_area_struct *vma) { struct fimc_dev *fimc = video_drvdata(file); + int ret; - return vb2_mmap(&fimc->vid_cap.vbq, vma); + if (mutex_lock_interruptible(&fimc->lock)) + return -ERESTARTSYS; + ret = vb2_mmap(&fimc->vid_cap.vbq, vma); + mutex_unlock(&fimc->lock); + return ret; } static const struct v4l2_file_operations fimc_capture_fops = { @@ -1590,10 +1608,6 @@ static int fimc_register_capture_device(struct fimc_dev *fimc, vfd->minor = -1; vfd->release = video_device_release; vfd->lock = &fimc->lock; - /* Locking in file operations other than ioctl should be done - by the driver, not the V4L2 core. - This driver needs auditing so that this flag can be removed. */ - set_bit(V4L2_FL_LOCK_ALL_FOPS, &vfd->flags); video_set_drvdata(vfd, fimc); vid_cap = &fimc->vid_cap; -- 1.7.10 -- To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html