[media] pwc: Allow multiple opens

Allow multiple opens of the /dev/video node so that control panel apps
can be open to-gether with streaming apps.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
diff --git a/drivers/media/video/pwc/pwc-if.c b/drivers/media/video/pwc/pwc-if.c
index b591b72..a6b5fde 100644
--- a/drivers/media/video/pwc/pwc-if.c
+++ b/drivers/media/video/pwc/pwc-if.c
@@ -678,12 +678,6 @@
 	if (!pdev->udev)
 		return -ENODEV;
 
-	if (pdev->vopen) {
-		PWC_DEBUG_OPEN("I'm busy, someone is using the device.\n");
-		return -EBUSY;
-	}
-
-	pdev->vopen++;
 	file->private_data = vdev;
 	PWC_DEBUG_OPEN("<< video_open() returns 0.\n");
 	return 0;
@@ -718,10 +712,12 @@
 	PWC_DEBUG_OPEN(">> video_close called(vdev = 0x%p).\n", vdev);
 
 	pdev = video_get_drvdata(vdev);
-	vb2_queue_release(&pdev->vb_queue);
-	pdev->vopen--;
+	if (pdev->capt_file == file) {
+		vb2_queue_release(&pdev->vb_queue);
+		pdev->capt_file = NULL;
+	}
 
-	PWC_DEBUG_OPEN("<< video_close() vopen=%d\n", pdev->vopen);
+	PWC_DEBUG_OPEN("<< video_close()\n");
 	return 0;
 }
 
@@ -734,6 +730,12 @@
 	if (!pdev->udev)
 		return -ENODEV;
 
+	if (pdev->capt_file != NULL &&
+	    pdev->capt_file != file)
+		return -EBUSY;
+
+	pdev->capt_file = file;
+
 	return vb2_read(&pdev->vb_queue, buf, count, ppos,
 			file->f_flags & O_NONBLOCK);
 }
@@ -754,6 +756,9 @@
 	struct video_device *vdev = file->private_data;
 	struct pwc_device *pdev = video_get_drvdata(vdev);
 
+	if (pdev->capt_file != file)
+		return -EBUSY;
+
 	return vb2_mmap(&pdev->vb_queue, vma);
 }
 
diff --git a/drivers/media/video/pwc/pwc-v4l.c b/drivers/media/video/pwc/pwc-v4l.c
index 8bd0a68..834055b 100644
--- a/drivers/media/video/pwc/pwc-v4l.c
+++ b/drivers/media/video/pwc/pwc-v4l.c
@@ -284,13 +284,21 @@
 }
 
 /* ioctl(VIDIOC_SET_FMT) */
-static int pwc_vidioc_set_fmt(struct pwc_device *pdev, struct v4l2_format *f)
+
+static int pwc_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f)
 {
+	struct pwc_device *pdev = video_drvdata(file);
 	int ret, fps, snapshot, compression, pixelformat;
 
 	if (!pdev->udev)
 		return -ENODEV;
 
+	if (pdev->capt_file != NULL &&
+	    pdev->capt_file != file)
+		return -EBUSY;
+
+	pdev->capt_file = file;
+
 	ret = pwc_vidioc_try_fmt(pdev, f);
 	if (ret<0)
 		return ret;
@@ -678,18 +686,17 @@
 	return pwc_vidioc_try_fmt(pdev, f);
 }
 
-static int pwc_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f)
-{
-	struct pwc_device *pdev = video_drvdata(file);
-
-	return pwc_vidioc_set_fmt(pdev, f);
-}
-
 static int pwc_reqbufs(struct file *file, void *fh,
 		       struct v4l2_requestbuffers *rb)
 {
 	struct pwc_device *pdev = video_drvdata(file);
 
+	if (pdev->capt_file != NULL &&
+	    pdev->capt_file != file)
+		return -EBUSY;
+
+	pdev->capt_file = file;
+
 	return vb2_reqbufs(&pdev->vb_queue, rb);
 }
 
@@ -707,6 +714,9 @@
 	if (!pdev->udev)
 		return -ENODEV;
 
+	if (pdev->capt_file != file)
+		return -EBUSY;
+
 	return vb2_qbuf(&pdev->vb_queue, buf);
 }
 
@@ -717,6 +727,9 @@
 	if (!pdev->udev)
 		return -ENODEV;
 
+	if (pdev->capt_file != file)
+		return -EBUSY;
+
 	return vb2_dqbuf(&pdev->vb_queue, buf, file->f_flags & O_NONBLOCK);
 }
 
@@ -727,6 +740,9 @@
 	if (!pdev->udev)
 		return -ENODEV;
 
+	if (pdev->capt_file != file)
+		return -EBUSY;
+
 	return vb2_streamon(&pdev->vb_queue, i);
 }
 
@@ -737,6 +753,9 @@
 	if (!pdev->udev)
 		return -ENODEV;
 
+	if (pdev->capt_file != file)
+		return -EBUSY;
+
 	return vb2_streamoff(&pdev->vb_queue, i);
 }
 
diff --git a/drivers/media/video/pwc/pwc.h b/drivers/media/video/pwc/pwc.h
index 8d82c6a..d65cd14 100644
--- a/drivers/media/video/pwc/pwc.h
+++ b/drivers/media/video/pwc/pwc.h
@@ -160,7 +160,7 @@
 	char serial[30];	/* serial number (string) */
 
 	/*** Video data ***/
-	int vopen;		/* flag */
+	struct file *capt_file;	/* file doing video capture */
 	int vendpoint;		/* video isoc endpoint */
 	int vcinterface;	/* video control interface */
 	int valternate;		/* alternate interface needed */