diff options
author | Hans de Goede <hdegoede@redhat.com> | 2010-12-30 11:11:21 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2011-01-19 08:44:53 -0500 |
commit | 4e770f7602fb2285f3106f98109d0685618ddc22 (patch) | |
tree | 0ee5912a6514a3889f8f5b08cbe1e9cb1ae2cf5f | |
parent | 82f4b5b67e795fe03952b278873712e4562304d2 (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.c | 15 |
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); |