[media] v4l2-dev: make it possible to skip locking for selected ioctls

Using the V4L2 core lock is a very robust method that is usually very good
at doing the right thing. But some drivers, particularly USB drivers, may
want to prevent the core from taking the lock for specific ioctls, particularly
buffer queuing ioctls.

The reason is that certain commands like S_CTRL can take a long time to process
over USB and all the time the core has the lock, preventing VIDIOC_DQBUF from
proceeding, even though a frame may be ready in the queue.

This introduces unwanted latency.

Since the buffer queuing commands often have their own internal lock it is
often not necessary to take the core lock. Drivers can now say that they don't
want the core to take the lock for specific ioctls.

As it is a specific opt-out it makes it clear to the reviewer that those
ioctls will need more care when reviewing.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Acked-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
diff --git a/drivers/media/video/v4l2-dev.c b/drivers/media/video/v4l2-dev.c
index 70bec54..e4a9ed6 100644
--- a/drivers/media/video/v4l2-dev.c
+++ b/drivers/media/video/v4l2-dev.c
@@ -322,11 +322,19 @@
 	int ret = -ENODEV;
 
 	if (vdev->fops->unlocked_ioctl) {
-		if (vdev->lock && mutex_lock_interruptible(vdev->lock))
-			return -ERESTARTSYS;
+		bool locked = false;
+
+		if (vdev->lock) {
+			/* always lock unless the cmd is marked as "don't use lock" */
+			locked = !v4l2_is_known_ioctl(cmd) ||
+				 !test_bit(_IOC_NR(cmd), vdev->dont_use_lock);
+
+			if (locked && mutex_lock_interruptible(vdev->lock))
+				return -ERESTARTSYS;
+		}
 		if (video_is_registered(vdev))
 			ret = vdev->fops->unlocked_ioctl(filp, cmd, arg);
-		if (vdev->lock)
+		if (locked)
 			mutex_unlock(vdev->lock);
 	} else if (vdev->fops->ioctl) {
 		/* This code path is a replacement for the BKL. It is a major