V4L/DVB (6056): ivtv: move serialization to the fileops level

Serialization is now done on the open/close/ioctl level and also when the
read/write/poll start an encoder/decoder stream.

Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
diff --git a/drivers/media/video/ivtv/ivtv-ioctl.c b/drivers/media/video/ivtv/ivtv-ioctl.c
index 2c0f272..2061d82 100644
--- a/drivers/media/video/ivtv/ivtv-ioctl.c
+++ b/drivers/media/video/ivtv/ivtv-ioctl.c
@@ -1446,11 +1446,15 @@
 				return 0;
 			if (nonblocking)
 				return -EAGAIN;
-			/* wait for event */
+			/* Wait for event. Note that serialize_lock is locked,
+			   so to allow other processes to access the driver while
+			   we are waiting unlock first and later lock again. */
+			mutex_unlock(&itv->serialize_lock);
 			prepare_to_wait(&itv->event_waitq, &wait, TASK_INTERRUPTIBLE);
 			if ((itv->i_flags & (IVTV_F_I_EV_DEC_STOPPED|IVTV_F_I_EV_VSYNC)) == 0)
 				schedule();
 			finish_wait(&itv->event_waitq, &wait);
+			mutex_lock(&itv->serialize_lock);
 			if (signal_pending(current)) {
 				/* return if a signal was received */
 				IVTV_DEBUG_INFO("User stopped wait for event\n");
@@ -1580,12 +1584,9 @@
 	return 0;
 }
 
-int ivtv_v4l2_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
-		    unsigned long arg)
+static int ivtv_serialized_ioctl(struct ivtv *itv, struct inode *inode, struct file *filp,
+		unsigned int cmd, unsigned long arg)
 {
-	struct ivtv_open_id *id = (struct ivtv_open_id *)filp->private_data;
-	struct ivtv *itv = id->itv;
-
 	/* Filter dvb ioctls that cannot be handled by video_usercopy */
 	switch (cmd) {
 	case VIDEO_SELECT_SOURCE:
@@ -1620,3 +1621,16 @@
 	}
 	return video_usercopy(inode, filp, cmd, arg, ivtv_v4l2_do_ioctl);
 }
+
+int ivtv_v4l2_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
+		    unsigned long arg)
+{
+	struct ivtv_open_id *id = (struct ivtv_open_id *)filp->private_data;
+	struct ivtv *itv = id->itv;
+	int res;
+
+	mutex_lock(&itv->serialize_lock);
+	res = ivtv_serialized_ioctl(itv, inode, filp, cmd, arg);
+	mutex_unlock(&itv->serialize_lock);
+	return res;
+}