aboutsummaryrefslogtreecommitdiff
path: root/drivers/media/v4l2-core/v4l2-dev.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-dev.c
parent93a9d9008d3c963d5d12c56460b5e1d93dad3ea8 (diff)
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-dev.c')
-rw-r--r--drivers/media/v4l2-core/v4l2-dev.c18
1 files changed, 16 insertions, 2 deletions
diff --git a/drivers/media/v4l2-core/v4l2-dev.c b/drivers/media/v4l2-core/v4l2-dev.c
index 69e775930fc4..feb749aaaa42 100644
--- a/drivers/media/v4l2-core/v4l2-dev.c
+++ b/drivers/media/v4l2-core/v4l2-dev.c
@@ -444,8 +444,22 @@ static int v4l2_release(struct inode *inode, struct file *filp)
struct video_device *vdev = video_devdata(filp);
int ret = 0;
- if (vdev->fops->release)
- ret = vdev->fops->release(filp);
+ /*
+ * We need to serialize the release() with queueing new requests.
+ * The release() may trigger the cancellation of a streaming
+ * operation, and that should not be mixed with queueing a new
+ * request at the same time.
+ */
+ if (vdev->fops->release) {
+ if (v4l2_device_supports_requests(vdev->v4l2_dev)) {
+ mutex_lock(&vdev->v4l2_dev->mdev->req_queue_mutex);
+ ret = vdev->fops->release(filp);
+ mutex_unlock(&vdev->v4l2_dev->mdev->req_queue_mutex);
+ } else {
+ ret = vdev->fops->release(filp);
+ }
+ }
+
if (vdev->dev_debug & V4L2_DEV_DEBUG_FOP)
dprintk("%s: release\n",
video_device_node_name(vdev));