aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHans de Goede <hdegoede@redhat.com>2010-12-30 11:11:21 -0500
committerMauro Carvalho Chehab <mchehab@redhat.com>2011-01-19 08:44:53 -0500
commit4e770f7602fb2285f3106f98109d0685618ddc22 (patch)
tree0ee5912a6514a3889f8f5b08cbe1e9cb1ae2cf5f
parent82f4b5b67e795fe03952b278873712e4562304d2 (diff)
[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>
-rw-r--r--drivers/media/video/gspca/gspca.c15
1 files changed, 9 insertions, 6 deletions
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,
1630 1630
1631 if (buf_type != V4L2_BUF_TYPE_VIDEO_CAPTURE) 1631 if (buf_type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1632 return -EINVAL; 1632 return -EINVAL;
1633 if (!gspca_dev->streaming) 1633
1634 return 0;
1635 if (mutex_lock_interruptible(&gspca_dev->queue_lock)) 1634 if (mutex_lock_interruptible(&gspca_dev->queue_lock))
1636 return -ERESTARTSYS; 1635 return -ERESTARTSYS;
1637 1636
1637 if (!gspca_dev->streaming) {
1638 ret = 0;
1639 goto out;
1640 }
1641
1638 /* check the capture file */ 1642 /* check the capture file */
1639 if (gspca_dev->capt_file != file) { 1643 if (gspca_dev->capt_file != file) {
1640 ret = -EBUSY; 1644 ret = -EBUSY;
@@ -2341,12 +2345,11 @@ void gspca_disconnect(struct usb_interface *intf)
2341 PDEBUG(D_PROBE, "%s disconnect", 2345 PDEBUG(D_PROBE, "%s disconnect",
2342 video_device_node_name(&gspca_dev->vdev)); 2346 video_device_node_name(&gspca_dev->vdev));
2343 mutex_lock(&gspca_dev->usb_lock); 2347 mutex_lock(&gspca_dev->usb_lock);
2348
2344 gspca_dev->present = 0; 2349 gspca_dev->present = 0;
2350 wake_up_interruptible(&gspca_dev->wq);
2345 2351
2346 if (gspca_dev->streaming) { 2352 destroy_urbs(gspca_dev);
2347 destroy_urbs(gspca_dev);
2348 wake_up_interruptible(&gspca_dev->wq);
2349 }
2350 2353
2351#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) 2354#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
2352 gspca_input_destroy_urb(gspca_dev); 2355 gspca_input_destroy_urb(gspca_dev);