From: Hans de Goede <hdegoede@redhat.com>
Date: Thu, 30 Dec 2010 16:11:21 +0000 (-0300)
Subject: [media] gspca_main: Locking fixes 1
X-Git-Tag: firefly_0821_release~7613^2~2613^2~86
X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=4e770f7602fb2285f3106f98109d0685618ddc22;p=firefly-linux-kernel-4.4.55.git

[media] gspca_main: Locking fixes 1

The gspca_dev->streaming boolean is protected against multiple access
through gspca_dev->queue_lock everywhere except for 2 places. This patch
fixes this by bringing it under the lock in vidioc_streamoff. And by
removing the check for gspca_dev->streaming in gspca_disconnect,
the destroy_urbs call may be called multiple times (and is protected
by the usb_lock) and calling wake_up_interruptible can also always be done
safely.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Acked-by: Jean-Francois Moine <moinejf@free.fr>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
---

diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c
index 442970073e8a..74626b6a9eb4 100644
--- a/drivers/media/video/gspca/gspca.c
+++ b/drivers/media/video/gspca/gspca.c
@@ -1630,11 +1630,15 @@ static int vidioc_streamoff(struct file *file, void *priv,
 
 	if (buf_type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
 		return -EINVAL;
-	if (!gspca_dev->streaming)
-		return 0;
+
 	if (mutex_lock_interruptible(&gspca_dev->queue_lock))
 		return -ERESTARTSYS;
 
+	if (!gspca_dev->streaming) {
+		ret = 0;
+		goto out;
+	}
+
 	/* check the capture file */
 	if (gspca_dev->capt_file != file) {
 		ret = -EBUSY;
@@ -2341,12 +2345,11 @@ void gspca_disconnect(struct usb_interface *intf)
 	PDEBUG(D_PROBE, "%s disconnect",
 		video_device_node_name(&gspca_dev->vdev));
 	mutex_lock(&gspca_dev->usb_lock);
+
 	gspca_dev->present = 0;
+	wake_up_interruptible(&gspca_dev->wq);
 
-	if (gspca_dev->streaming) {
-		destroy_urbs(gspca_dev);
-		wake_up_interruptible(&gspca_dev->wq);
-	}
+	destroy_urbs(gspca_dev);
 
 #if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
 	gspca_input_destroy_urb(gspca_dev);