diff options
author | Hans de Goede <hdegoede@redhat.com> | 2012-05-07 05:25:30 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2012-05-14 08:32:18 -0400 |
commit | eb238732a52b100bdf4a766a50e11e6fd9bd1d83 (patch) | |
tree | 4a21370c4c3827c9e1d06bcb1384ab08a355dab9 /drivers/media/video/gspca | |
parent | a2d887c5fea33f341fd0d2a1487150473cf69014 (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.c | 22 |
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) | |||
595 | static void gspca_stream_off(struct gspca_dev *gspca_dev) | 595 | static 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); |