[PATCH 02/23] v4l2-dev: make it possible to skip locking for non ioctl fops

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Just like with some ioctls some drivers may want to prevent the core from
taking the V4L2 core lock on other fops.

Signed-off-by: Hans de Goede <hdegoede@xxxxxxxxxx>
---
 Documentation/video4linux/v4l2-framework.txt |    7 ++--
 drivers/media/video/v4l2-dev.c               |   45 ++++++++++++++------------
 include/media/v4l2-dev.h                     |    4 +++
 3 files changed, 34 insertions(+), 22 deletions(-)

diff --git a/Documentation/video4linux/v4l2-framework.txt b/Documentation/video4linux/v4l2-framework.txt
index 4b9b407..c2e6591 100644
--- a/Documentation/video4linux/v4l2-framework.txt
+++ b/Documentation/video4linux/v4l2-framework.txt
@@ -621,8 +621,11 @@ v4l2_file_operations and locking
 
 You can set a pointer to a mutex_lock in struct video_device. Usually this
 will be either a top-level mutex or a mutex per device node. By default this
-lock will be used for each file operation and ioctl, but you can disable
-locking for selected ioctls by calling:
+lock will be used for each file operation and ioctl, you can disable this
+for all non ioctl operations by setting the V4L2_FL_DONT_USE_LOCK flag, e.g.:
+	set_bit(V4L2_FL_DONT_USE_LOCK, &vdev->flags);
+
+For ioctls you can disable locking for selected ioctls by calling:
 
 	void v4l2_dont_use_lock(struct video_device *vdev, unsigned int cmd);
 
diff --git a/drivers/media/video/v4l2-dev.c b/drivers/media/video/v4l2-dev.c
index a51a061..eb20f0b 100644
--- a/drivers/media/video/v4l2-dev.c
+++ b/drivers/media/video/v4l2-dev.c
@@ -274,12 +274,12 @@ static ssize_t v4l2_read(struct file *filp, char __user *buf,
 
 	if (!vdev->fops->read)
 		return -EINVAL;
-	if (vdev->lock && mutex_lock_interruptible(vdev->lock))
+	if (vdev->fops_lock && mutex_lock_interruptible(vdev->fops_lock))
 		return -ERESTARTSYS;
 	if (video_is_registered(vdev))
 		ret = vdev->fops->read(filp, buf, sz, off);
-	if (vdev->lock)
-		mutex_unlock(vdev->lock);
+	if (vdev->fops_lock)
+		mutex_unlock(vdev->fops_lock);
 	return ret;
 }
 
@@ -291,12 +291,12 @@ static ssize_t v4l2_write(struct file *filp, const char __user *buf,
 
 	if (!vdev->fops->write)
 		return -EINVAL;
-	if (vdev->lock && mutex_lock_interruptible(vdev->lock))
+	if (vdev->fops_lock && mutex_lock_interruptible(vdev->fops_lock))
 		return -ERESTARTSYS;
 	if (video_is_registered(vdev))
 		ret = vdev->fops->write(filp, buf, sz, off);
-	if (vdev->lock)
-		mutex_unlock(vdev->lock);
+	if (vdev->fops_lock)
+		mutex_unlock(vdev->fops_lock);
 	return ret;
 }
 
@@ -307,12 +307,12 @@ static unsigned int v4l2_poll(struct file *filp, struct poll_table_struct *poll)
 
 	if (!vdev->fops->poll)
 		return DEFAULT_POLLMASK;
-	if (vdev->lock)
-		mutex_lock(vdev->lock);
+	if (vdev->fops_lock)
+		mutex_lock(vdev->fops_lock);
 	if (video_is_registered(vdev))
 		ret = vdev->fops->poll(filp, poll);
-	if (vdev->lock)
-		mutex_unlock(vdev->lock);
+	if (vdev->fops_lock)
+		mutex_unlock(vdev->fops_lock);
 	return ret;
 }
 
@@ -399,12 +399,12 @@ static int v4l2_mmap(struct file *filp, struct vm_area_struct *vm)
 
 	if (!vdev->fops->mmap)
 		return ret;
-	if (vdev->lock && mutex_lock_interruptible(vdev->lock))
+	if (vdev->fops_lock && mutex_lock_interruptible(vdev->fops_lock))
 		return -ERESTARTSYS;
 	if (video_is_registered(vdev))
 		ret = vdev->fops->mmap(filp, vm);
-	if (vdev->lock)
-		mutex_unlock(vdev->lock);
+	if (vdev->fops_lock)
+		mutex_unlock(vdev->fops_lock);
 	return ret;
 }
 
@@ -426,7 +426,8 @@ static int v4l2_open(struct inode *inode, struct file *filp)
 	video_get(vdev);
 	mutex_unlock(&videodev_lock);
 	if (vdev->fops->open) {
-		if (vdev->lock && mutex_lock_interruptible(vdev->lock)) {
+		if (vdev->fops_lock &&
+				mutex_lock_interruptible(vdev->fops_lock)) {
 			ret = -ERESTARTSYS;
 			goto err;
 		}
@@ -434,8 +435,8 @@ static int v4l2_open(struct inode *inode, struct file *filp)
 			ret = vdev->fops->open(filp);
 		else
 			ret = -ENODEV;
-		if (vdev->lock)
-			mutex_unlock(vdev->lock);
+		if (vdev->fops_lock)
+			mutex_unlock(vdev->fops_lock);
 	}
 
 err:
@@ -452,11 +453,11 @@ static int v4l2_release(struct inode *inode, struct file *filp)
 	int ret = 0;
 
 	if (vdev->fops->release) {
-		if (vdev->lock)
-			mutex_lock(vdev->lock);
+		if (vdev->fops_lock)
+			mutex_lock(vdev->fops_lock);
 		vdev->fops->release(filp);
-		if (vdev->lock)
-			mutex_unlock(vdev->lock);
+		if (vdev->fops_lock)
+			mutex_unlock(vdev->fops_lock);
 	}
 	/* decrease the refcount unconditionally since the release()
 	   return value is ignored. */
@@ -601,6 +602,10 @@ int __video_register_device(struct video_device *vdev, int type, int nr,
 		if (vdev->prio == NULL)
 			vdev->prio = &vdev->v4l2_dev->prio;
 	}
+	if (test_bit(V4L2_FL_DONT_USE_LOCK, &vdev->flags))
+		vdev->fops_lock = NULL;
+	else
+		vdev->fops_lock = vdev->lock;
 
 	/* Part 2: find a free minor, device node number and device index. */
 #ifdef CONFIG_VIDEO_FIXED_MINOR_RANGES
diff --git a/include/media/v4l2-dev.h b/include/media/v4l2-dev.h
index 0da84dc..fa80124 100644
--- a/include/media/v4l2-dev.h
+++ b/include/media/v4l2-dev.h
@@ -39,6 +39,9 @@ struct v4l2_ctrl_handler;
 #define V4L2_FL_USES_V4L2_FH	(1)
 /* Use the prio field of v4l2_fh for core priority checking */
 #define V4L2_FL_USE_FH_PRIO	(2)
+/* Don't take the lock for all fops, except ioctl. For ioctls the lock can be
+   disabled on a per ioctl basis by calling v4l2_dont_use_lock. */
+#define V4L2_FL_DONT_USE_LOCK	(3)
 
 /* Priority helper functions */
 
@@ -130,6 +133,7 @@ struct video_device
 	/* serialization lock */
 	DECLARE_BITMAP(dont_use_lock, BASE_VIDIOC_PRIVATE);
 	struct mutex *lock;
+	struct mutex *fops_lock;	/* Internal v4l2-vdev usage only */
 };
 
 #define media_entity_to_video_device(__e) \
-- 
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


[Index of Archives]     [Linux Input]     [Video for Linux]     [Gstreamer Embedded]     [Mplayer Users]     [Linux USB Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]
  Powered by Linux