aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/v4l2-core/v4l2-ioctl.c
diff options
context:
space:
mode:
authorHans Verkuil <hans.verkuil@cisco.com>2018-05-21 04:54:34 -0400
committerMauro Carvalho Chehab <mchehab+samsung@kernel.org>2018-08-31 11:07:51 -0400
commitcc6eddcd37ce6be403b5820ffd84cb84b33b653f (patch)
treeeb462214042304f56bbea9cb34127618b051b5d4 /drivers/media/v4l2-core/v4l2-ioctl.c
parentmedia: v4l2-device.h: add v4l2_device_supports_requests() helper (diff)
downloadlinux-dev-cc6eddcd37ce6be403b5820ffd84cb84b33b653f.tar.xz
linux-dev-cc6eddcd37ce6be403b5820ffd84cb84b33b653f.zip
media: v4l2-dev: lock req_queue_mutex
We need to serialize streamon/off with queueing new requests. These ioctls may trigger the cancellation of a streaming operation, and that should not be mixed with queuing a new request at the same time. Finally close() needs this lock since that too can trigger the cancellation of a streaming operation. We take the req_queue_mutex here before any other locks since it is a very high-level lock. Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com> Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com> Reviewed-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org> Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
Diffstat (limited to 'drivers/media/v4l2-core/v4l2-ioctl.c')
-rw-r--r--drivers/media/v4l2-core/v4l2-ioctl.c22
1 files changed, 21 insertions, 1 deletions
diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c
index 54afc9c7ee6e..ea475d833dd6 100644
--- a/drivers/media/v4l2-core/v4l2-ioctl.c
+++ b/drivers/media/v4l2-core/v4l2-ioctl.c
@@ -2780,6 +2780,7 @@ static long __video_do_ioctl(struct file *file,
unsigned int cmd, void *arg)
{
struct video_device *vfd = video_devdata(file);
+ struct mutex *req_queue_lock = NULL;
struct mutex *lock; /* ioctl serialization mutex */
const struct v4l2_ioctl_ops *ops = vfd->ioctl_ops;
bool write_only = false;
@@ -2799,10 +2800,27 @@ static long __video_do_ioctl(struct file *file,
if (test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags))
vfh = file->private_data;
+ /*
+ * We need to serialize streamon/off with queueing new requests.
+ * These ioctls may trigger the cancellation of a streaming
+ * operation, and that should not be mixed with queueing a new
+ * request at the same time.
+ */
+ if (v4l2_device_supports_requests(vfd->v4l2_dev) &&
+ (cmd == VIDIOC_STREAMON || cmd == VIDIOC_STREAMOFF)) {
+ req_queue_lock = &vfd->v4l2_dev->mdev->req_queue_mutex;
+
+ if (mutex_lock_interruptible(req_queue_lock))
+ return -ERESTARTSYS;
+ }
+
lock = v4l2_ioctl_get_lock(vfd, vfh, cmd, arg);
- if (lock && mutex_lock_interruptible(lock))
+ if (lock && mutex_lock_interruptible(lock)) {
+ if (req_queue_lock)
+ mutex_unlock(req_queue_lock);
return -ERESTARTSYS;
+ }
if (!video_is_registered(vfd)) {
ret = -ENODEV;
@@ -2861,6 +2879,8 @@ done:
unlock:
if (lock)
mutex_unlock(lock);
+ if (req_queue_lock)
+ mutex_unlock(req_queue_lock);
return ret;
}