Commit c2d430af authored by Sylwester Nawrocki's avatar Sylwester Nawrocki Committed by Mauro Carvalho Chehab

[media] s5p-fimc: Remove V4L2_FL_LOCK_ALL_FOPS flag

This patch adds locking for open(), close(), poll() and mmap()
file operations in the driver as a follow up to the changes
done in commit 5126f259
"v4l2-dev: add flag to have the core lock all file operations".
Signed-off-by: default avatarSylwester Nawrocki <s.nawrocki@samsung.com>
Signed-off-by: default avatarKyungmin Park <kyungmin.park@samsung.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent 837c7e42
...@@ -480,48 +480,59 @@ static int fimc_capture_set_default_format(struct fimc_dev *fimc); ...@@ -480,48 +480,59 @@ static int fimc_capture_set_default_format(struct fimc_dev *fimc);
static int fimc_capture_open(struct file *file) static int fimc_capture_open(struct file *file)
{ {
struct fimc_dev *fimc = video_drvdata(file); struct fimc_dev *fimc = video_drvdata(file);
int ret; int ret = -EBUSY;
dbg("pid: %d, state: 0x%lx", task_pid_nr(current), fimc->state); dbg("pid: %d, state: 0x%lx", task_pid_nr(current), fimc->state);
if (mutex_lock_interruptible(&fimc->lock))
return -ERESTARTSYS;
if (fimc_m2m_active(fimc)) if (fimc_m2m_active(fimc))
return -EBUSY; goto unlock;
set_bit(ST_CAPT_BUSY, &fimc->state); set_bit(ST_CAPT_BUSY, &fimc->state);
ret = pm_runtime_get_sync(&fimc->pdev->dev); ret = pm_runtime_get_sync(&fimc->pdev->dev);
if (ret < 0) if (ret < 0)
return ret; goto unlock;
ret = v4l2_fh_open(file); ret = v4l2_fh_open(file);
if (ret) if (ret) {
return ret; pm_runtime_put(&fimc->pdev->dev);
goto unlock;
if (++fimc->vid_cap.refcnt != 1) }
return 0;
ret = fimc_pipeline_initialize(&fimc->pipeline, if (++fimc->vid_cap.refcnt == 1) {
ret = fimc_pipeline_initialize(&fimc->pipeline,
&fimc->vid_cap.vfd->entity, true); &fimc->vid_cap.vfd->entity, true);
if (ret < 0) {
clear_bit(ST_CAPT_BUSY, &fimc->state);
pm_runtime_put_sync(&fimc->pdev->dev);
fimc->vid_cap.refcnt--;
v4l2_fh_release(file);
return ret;
}
ret = fimc_capture_ctrls_create(fimc);
if (!ret && !fimc->vid_cap.user_subdev_api) if (!ret && !fimc->vid_cap.user_subdev_api)
ret = fimc_capture_set_default_format(fimc); ret = fimc_capture_set_default_format(fimc);
if (!ret)
ret = fimc_capture_ctrls_create(fimc);
if (ret < 0) {
clear_bit(ST_CAPT_BUSY, &fimc->state);
pm_runtime_put_sync(&fimc->pdev->dev);
fimc->vid_cap.refcnt--;
v4l2_fh_release(file);
}
}
unlock:
mutex_unlock(&fimc->lock);
return ret; return ret;
} }
static int fimc_capture_close(struct file *file) static int fimc_capture_close(struct file *file)
{ {
struct fimc_dev *fimc = video_drvdata(file); struct fimc_dev *fimc = video_drvdata(file);
int ret;
dbg("pid: %d, state: 0x%lx", task_pid_nr(current), fimc->state); dbg("pid: %d, state: 0x%lx", task_pid_nr(current), fimc->state);
if (mutex_lock_interruptible(&fimc->lock))
return -ERESTARTSYS;
if (--fimc->vid_cap.refcnt == 0) { if (--fimc->vid_cap.refcnt == 0) {
clear_bit(ST_CAPT_BUSY, &fimc->state); clear_bit(ST_CAPT_BUSY, &fimc->state);
fimc_stop_capture(fimc, false); fimc_stop_capture(fimc, false);
...@@ -535,22 +546,40 @@ static int fimc_capture_close(struct file *file) ...@@ -535,22 +546,40 @@ static int fimc_capture_close(struct file *file)
vb2_queue_release(&fimc->vid_cap.vbq); vb2_queue_release(&fimc->vid_cap.vbq);
fimc_ctrls_delete(fimc->vid_cap.ctx); fimc_ctrls_delete(fimc->vid_cap.ctx);
} }
return v4l2_fh_release(file);
ret = v4l2_fh_release(file);
mutex_unlock(&fimc->lock);
return ret;
} }
static unsigned int fimc_capture_poll(struct file *file, static unsigned int fimc_capture_poll(struct file *file,
struct poll_table_struct *wait) struct poll_table_struct *wait)
{ {
struct fimc_dev *fimc = video_drvdata(file); struct fimc_dev *fimc = video_drvdata(file);
int ret;
return vb2_poll(&fimc->vid_cap.vbq, file, wait); if (mutex_lock_interruptible(&fimc->lock))
return POLL_ERR;
ret = vb2_poll(&fimc->vid_cap.vbq, file, wait);
mutex_unlock(&fimc->lock);
return ret;
} }
static int fimc_capture_mmap(struct file *file, struct vm_area_struct *vma) static int fimc_capture_mmap(struct file *file, struct vm_area_struct *vma)
{ {
struct fimc_dev *fimc = video_drvdata(file); struct fimc_dev *fimc = video_drvdata(file);
int ret;
if (mutex_lock_interruptible(&fimc->lock))
return -ERESTARTSYS;
return vb2_mmap(&fimc->vid_cap.vbq, vma); ret = vb2_mmap(&fimc->vid_cap.vbq, vma);
mutex_unlock(&fimc->lock);
return ret;
} }
static const struct v4l2_file_operations fimc_capture_fops = { static const struct v4l2_file_operations fimc_capture_fops = {
...@@ -1589,10 +1618,7 @@ static int fimc_register_capture_device(struct fimc_dev *fimc, ...@@ -1589,10 +1618,7 @@ static int fimc_register_capture_device(struct fimc_dev *fimc,
vfd->minor = -1; vfd->minor = -1;
vfd->release = video_device_release; vfd->release = video_device_release;
vfd->lock = &fimc->lock; 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); video_set_drvdata(vfd, fimc);
vid_cap = &fimc->vid_cap; vid_cap = &fimc->vid_cap;
......
...@@ -642,21 +642,25 @@ static int fimc_m2m_open(struct file *file) ...@@ -642,21 +642,25 @@ static int fimc_m2m_open(struct file *file)
{ {
struct fimc_dev *fimc = video_drvdata(file); struct fimc_dev *fimc = video_drvdata(file);
struct fimc_ctx *ctx; struct fimc_ctx *ctx;
int ret; int ret = -EBUSY;
dbg("pid: %d, state: 0x%lx, refcnt: %d", dbg("pid: %d, state: 0x%lx, refcnt: %d",
task_pid_nr(current), fimc->state, fimc->vid_cap.refcnt); task_pid_nr(current), fimc->state, fimc->vid_cap.refcnt);
if (mutex_lock_interruptible(&fimc->lock))
return -ERESTARTSYS;
/* /*
* Return if the corresponding video capture node * Return if the corresponding video capture node
* is already opened. * is already opened.
*/ */
if (fimc->vid_cap.refcnt > 0) if (fimc->vid_cap.refcnt > 0)
return -EBUSY; goto unlock;
ctx = kzalloc(sizeof *ctx, GFP_KERNEL); ctx = kzalloc(sizeof *ctx, GFP_KERNEL);
if (!ctx) if (!ctx) {
return -ENOMEM; ret = -ENOMEM;
goto unlock;
}
v4l2_fh_init(&ctx->fh, fimc->m2m.vfd); v4l2_fh_init(&ctx->fh, fimc->m2m.vfd);
ctx->fimc_dev = fimc; ctx->fimc_dev = fimc;
...@@ -687,6 +691,8 @@ static int fimc_m2m_open(struct file *file) ...@@ -687,6 +691,8 @@ static int fimc_m2m_open(struct file *file)
if (fimc->m2m.refcnt++ == 0) if (fimc->m2m.refcnt++ == 0)
set_bit(ST_M2M_RUN, &fimc->state); set_bit(ST_M2M_RUN, &fimc->state);
mutex_unlock(&fimc->lock);
return 0; return 0;
error_c: error_c:
...@@ -695,6 +701,8 @@ static int fimc_m2m_open(struct file *file) ...@@ -695,6 +701,8 @@ static int fimc_m2m_open(struct file *file)
v4l2_fh_del(&ctx->fh); v4l2_fh_del(&ctx->fh);
v4l2_fh_exit(&ctx->fh); v4l2_fh_exit(&ctx->fh);
kfree(ctx); kfree(ctx);
unlock:
mutex_unlock(&fimc->lock);
return ret; return ret;
} }
...@@ -706,6 +714,9 @@ static int fimc_m2m_release(struct file *file) ...@@ -706,6 +714,9 @@ static int fimc_m2m_release(struct file *file)
dbg("pid: %d, state: 0x%lx, refcnt= %d", dbg("pid: %d, state: 0x%lx, refcnt= %d",
task_pid_nr(current), fimc->state, fimc->m2m.refcnt); task_pid_nr(current), fimc->state, fimc->m2m.refcnt);
if (mutex_lock_interruptible(&fimc->lock))
return -ERESTARTSYS;
v4l2_m2m_ctx_release(ctx->m2m_ctx); v4l2_m2m_ctx_release(ctx->m2m_ctx);
fimc_ctrls_delete(ctx); fimc_ctrls_delete(ctx);
v4l2_fh_del(&ctx->fh); v4l2_fh_del(&ctx->fh);
...@@ -714,6 +725,8 @@ static int fimc_m2m_release(struct file *file) ...@@ -714,6 +725,8 @@ static int fimc_m2m_release(struct file *file)
if (--fimc->m2m.refcnt <= 0) if (--fimc->m2m.refcnt <= 0)
clear_bit(ST_M2M_RUN, &fimc->state); clear_bit(ST_M2M_RUN, &fimc->state);
kfree(ctx); kfree(ctx);
mutex_unlock(&fimc->lock);
return 0; return 0;
} }
...@@ -721,16 +734,32 @@ static unsigned int fimc_m2m_poll(struct file *file, ...@@ -721,16 +734,32 @@ static unsigned int fimc_m2m_poll(struct file *file,
struct poll_table_struct *wait) struct poll_table_struct *wait)
{ {
struct fimc_ctx *ctx = fh_to_ctx(file->private_data); struct fimc_ctx *ctx = fh_to_ctx(file->private_data);
struct fimc_dev *fimc = ctx->fimc_dev;
int ret;
return v4l2_m2m_poll(file, ctx->m2m_ctx, wait); if (mutex_lock_interruptible(&fimc->lock))
return -ERESTARTSYS;
ret = v4l2_m2m_poll(file, ctx->m2m_ctx, wait);
mutex_unlock(&fimc->lock);
return ret;
} }
static int fimc_m2m_mmap(struct file *file, struct vm_area_struct *vma) static int fimc_m2m_mmap(struct file *file, struct vm_area_struct *vma)
{ {
struct fimc_ctx *ctx = fh_to_ctx(file->private_data); struct fimc_ctx *ctx = fh_to_ctx(file->private_data);
struct fimc_dev *fimc = ctx->fimc_dev;
int ret;
if (mutex_lock_interruptible(&fimc->lock))
return -ERESTARTSYS;
return v4l2_m2m_mmap(file, ctx->m2m_ctx, vma); ret = v4l2_m2m_mmap(file, ctx->m2m_ctx, vma);
mutex_unlock(&fimc->lock);
return ret;
} }
static const struct v4l2_file_operations fimc_m2m_fops = { static const struct v4l2_file_operations fimc_m2m_fops = {
...@@ -772,10 +801,6 @@ int fimc_register_m2m_device(struct fimc_dev *fimc, ...@@ -772,10 +801,6 @@ int fimc_register_m2m_device(struct fimc_dev *fimc,
vfd->minor = -1; vfd->minor = -1;
vfd->release = video_device_release; vfd->release = video_device_release;
vfd->lock = &fimc->lock; 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);
snprintf(vfd->name, sizeof(vfd->name), "fimc.%d.m2m", fimc->id); snprintf(vfd->name, sizeof(vfd->name), "fimc.%d.m2m", fimc->id);
video_set_drvdata(vfd, fimc); video_set_drvdata(vfd, fimc);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment