[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>
This commit is contained in:
parent
a2d887c5fe
commit
eb238732a5
|
@ -595,16 +595,12 @@ static int gspca_set_alt0(struct gspca_dev *gspca_dev)
|
||||||
static void gspca_stream_off(struct gspca_dev *gspca_dev)
|
static void gspca_stream_off(struct gspca_dev *gspca_dev)
|
||||||
{
|
{
|
||||||
gspca_dev->streaming = 0;
|
gspca_dev->streaming = 0;
|
||||||
if (gspca_dev->present) {
|
|
||||||
if (gspca_dev->sd_desc->stopN)
|
if (gspca_dev->sd_desc->stopN)
|
||||||
gspca_dev->sd_desc->stopN(gspca_dev);
|
gspca_dev->sd_desc->stopN(gspca_dev);
|
||||||
destroy_urbs(gspca_dev);
|
destroy_urbs(gspca_dev);
|
||||||
gspca_input_destroy_urb(gspca_dev);
|
gspca_input_destroy_urb(gspca_dev);
|
||||||
gspca_set_alt0(gspca_dev);
|
gspca_set_alt0(gspca_dev);
|
||||||
gspca_input_create_urb(gspca_dev);
|
gspca_input_create_urb(gspca_dev);
|
||||||
}
|
|
||||||
|
|
||||||
/* always call stop0 to free the subdriver's resources */
|
|
||||||
if (gspca_dev->sd_desc->stop0)
|
if (gspca_dev->sd_desc->stop0)
|
||||||
gspca_dev->sd_desc->stop0(gspca_dev);
|
gspca_dev->sd_desc->stop0(gspca_dev);
|
||||||
PDEBUG(D_STREAM, "stream off OK");
|
PDEBUG(D_STREAM, "stream off OK");
|
||||||
|
@ -2369,7 +2365,6 @@ void gspca_disconnect(struct usb_interface *intf)
|
||||||
usb_set_intfdata(intf, NULL);
|
usb_set_intfdata(intf, NULL);
|
||||||
gspca_dev->dev = NULL;
|
gspca_dev->dev = NULL;
|
||||||
gspca_dev->present = 0;
|
gspca_dev->present = 0;
|
||||||
wake_up_interruptible(&gspca_dev->wq);
|
|
||||||
destroy_urbs(gspca_dev);
|
destroy_urbs(gspca_dev);
|
||||||
|
|
||||||
#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
|
#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
|
||||||
|
@ -2380,6 +2375,11 @@ void gspca_disconnect(struct usb_interface *intf)
|
||||||
input_unregister_device(input_dev);
|
input_unregister_device(input_dev);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
/* Free subdriver's streaming resources / stop sd workqueue(s) */
|
||||||
|
if (gspca_dev->sd_desc->stop0 && gspca_dev->streaming)
|
||||||
|
gspca_dev->sd_desc->stop0(gspca_dev);
|
||||||
|
gspca_dev->streaming = 0;
|
||||||
|
wake_up_interruptible(&gspca_dev->wq);
|
||||||
|
|
||||||
v4l2_device_disconnect(&gspca_dev->v4l2_dev);
|
v4l2_device_disconnect(&gspca_dev->v4l2_dev);
|
||||||
video_unregister_device(&gspca_dev->vdev);
|
video_unregister_device(&gspca_dev->vdev);
|
||||||
|
|
Loading…
Reference in New Issue