aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/gspca
diff options
context:
space:
mode:
authorHans de Goede <hdegoede@redhat.com>2012-05-07 05:25:30 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2012-05-14 08:32:18 -0400
commiteb238732a52b100bdf4a766a50e11e6fd9bd1d83 (patch)
tree4a21370c4c3827c9e1d06bcb1384ab08a355dab9 /drivers/media/video/gspca
parenta2d887c5fea33f341fd0d2a1487150473cf69014 (diff)
[media] gspca: Call sd_stop0 on disconnect
This is necessary to ensure that worker-threads accessing the device are stopped before our disconnect handler returns. This causes a problem with stream_off calling sd_stop0 a second time when the device handle is closed. This is fixed by setting gscpa_dev->streaming to 0 on disconnect. Note that now stream_off will never be called on a disconnected device, and the present check can thus be removed from stream_off. Signed-off-by: Hans de Goede <hdegoede@redhat.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/gspca')
-rw-r--r--drivers/media/video/gspca/gspca.c22
1 files changed, 11 insertions, 11 deletions
diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c
index 8b97f777ddf4..b7cb9977f778 100644
--- a/drivers/media/video/gspca/gspca.c
+++ b/drivers/media/video/gspca/gspca.c
@@ -595,16 +595,12 @@ static int gspca_set_alt0(struct gspca_dev *gspca_dev)
595static void gspca_stream_off(struct gspca_dev *gspca_dev) 595static void gspca_stream_off(struct gspca_dev *gspca_dev)
596{ 596{
597 gspca_dev->streaming = 0; 597 gspca_dev->streaming = 0;
598 if (gspca_dev->present) { 598 if (gspca_dev->sd_desc->stopN)
599 if (gspca_dev->sd_desc->stopN) 599 gspca_dev->sd_desc->stopN(gspca_dev);
600 gspca_dev->sd_desc->stopN(gspca_dev); 600 destroy_urbs(gspca_dev);
601 destroy_urbs(gspca_dev); 601 gspca_input_destroy_urb(gspca_dev);
602 gspca_input_destroy_urb(gspca_dev); 602 gspca_set_alt0(gspca_dev);
603 gspca_set_alt0(gspca_dev); 603 gspca_input_create_urb(gspca_dev);
604 gspca_input_create_urb(gspca_dev);
605 }
606
607 /* always call stop0 to free the subdriver's resources */
608 if (gspca_dev->sd_desc->stop0) 604 if (gspca_dev->sd_desc->stop0)
609 gspca_dev->sd_desc->stop0(gspca_dev); 605 gspca_dev->sd_desc->stop0(gspca_dev);
610 PDEBUG(D_STREAM, "stream off OK"); 606 PDEBUG(D_STREAM, "stream off OK");
@@ -2369,7 +2365,6 @@ void gspca_disconnect(struct usb_interface *intf)
2369 usb_set_intfdata(intf, NULL); 2365 usb_set_intfdata(intf, NULL);
2370 gspca_dev->dev = NULL; 2366 gspca_dev->dev = NULL;
2371 gspca_dev->present = 0; 2367 gspca_dev->present = 0;
2372 wake_up_interruptible(&gspca_dev->wq);
2373 destroy_urbs(gspca_dev); 2368 destroy_urbs(gspca_dev);
2374 2369
2375#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) 2370#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
@@ -2380,6 +2375,11 @@ void gspca_disconnect(struct usb_interface *intf)
2380 input_unregister_device(input_dev); 2375 input_unregister_device(input_dev);
2381 } 2376 }
2382#endif 2377#endif
2378 /* Free subdriver's streaming resources / stop sd workqueue(s) */
2379 if (gspca_dev->sd_desc->stop0 && gspca_dev->streaming)
2380 gspca_dev->sd_desc->stop0(gspca_dev);
2381 gspca_dev->streaming = 0;
2382 wake_up_interruptible(&gspca_dev->wq);
2383 2383
2384 v4l2_device_disconnect(&gspca_dev->v4l2_dev); 2384 v4l2_device_disconnect(&gspca_dev->v4l2_dev);
2385 video_unregister_device(&gspca_dev->vdev); 2385 video_unregister_device(&gspca_dev->vdev);