Commit eb238732 authored by Hans de Goede's avatar Hans de Goede Committed by Mauro Carvalho Chehab

[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: default avatarHans de Goede <hdegoede@redhat.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent a2d887c5
......@@ -595,16 +595,12 @@ static int gspca_set_alt0(struct gspca_dev *gspca_dev)
static void gspca_stream_off(struct gspca_dev *gspca_dev)
{
gspca_dev->streaming = 0;
if (gspca_dev->present) {
if (gspca_dev->sd_desc->stopN)
gspca_dev->sd_desc->stopN(gspca_dev);
destroy_urbs(gspca_dev);
gspca_input_destroy_urb(gspca_dev);
gspca_set_alt0(gspca_dev);
gspca_input_create_urb(gspca_dev);
}
/* always call stop0 to free the subdriver's resources */
if (gspca_dev->sd_desc->stopN)
gspca_dev->sd_desc->stopN(gspca_dev);
destroy_urbs(gspca_dev);
gspca_input_destroy_urb(gspca_dev);
gspca_set_alt0(gspca_dev);
gspca_input_create_urb(gspca_dev);
if (gspca_dev->sd_desc->stop0)
gspca_dev->sd_desc->stop0(gspca_dev);
PDEBUG(D_STREAM, "stream off OK");
......@@ -2369,7 +2365,6 @@ void gspca_disconnect(struct usb_interface *intf)
usb_set_intfdata(intf, NULL);
gspca_dev->dev = NULL;
gspca_dev->present = 0;
wake_up_interruptible(&gspca_dev->wq);
destroy_urbs(gspca_dev);
#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
......@@ -2380,6 +2375,11 @@ void gspca_disconnect(struct usb_interface *intf)
input_unregister_device(input_dev);
}
#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);
video_unregister_device(&gspca_dev->vdev);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment