diff --git a/drivers/media/usb/em28xx/em28xx-video.c b/drivers/media/usb/em28xx/em28xx-video.c index c418add65bb5..3b8766d00897 100644 --- a/drivers/media/usb/em28xx/em28xx-video.c +++ b/drivers/media/usb/em28xx/em28xx-video.c @@ -2305,9 +2305,14 @@ static void em28xx_free_v4l2(struct v4l2_device *v4l2_dev) container_of(v4l2_dev, struct em28xx_v4l2, v4l2_dev); struct em28xx *dev = v4l2->dev; + mutex_lock(&dev->lock); + v4l2_ctrl_handler_free(&v4l2->ctrl_handler); v4l2_device_unregister(v4l2_dev); dev->v4l2 = NULL; + + mutex_unlock(&dev->lock); + kfree(v4l2); kref_put(&dev->ref, em28xx_free_device); } @@ -2388,25 +2393,24 @@ static int em28xx_v4l2_open(struct file *filp) */ static int em28xx_v4l2_fini(struct em28xx *dev) { - struct em28xx_v4l2 *v4l2 = dev->v4l2; + struct em28xx_v4l2 *v4l2; - if (dev->is_audio_only) { - /* Shouldn't initialize IR for this interface */ - return 0; - } + mutex_lock(&dev->lock); - if (!dev->has_video) { - /* This device does not support the v4l2 extension */ + if (dev->is_audio_only || /* Shouldn't initialize IR for this interface */ + !dev->has_video) { /* This device does not support the v4l2 extension */ + mutex_unlock(&dev->lock); return 0; } - if (!v4l2) + v4l2 = dev->v4l2; + if (!v4l2) { + mutex_unlock(&dev->lock); return 0; + } dev_info(&dev->intf->dev, "Closing video extension\n"); - mutex_lock(&dev->lock); - v4l2_device_disconnect(&v4l2->v4l2_dev); em28xx_uninit_usb_xfer(dev, EM28XX_ANALOG_MODE); @@ -2992,13 +2996,19 @@ static int em28xx_v4l2_init(struct em28xx *dev) goto unregister_dev; } + v4l2->vb_vbiq.lock = &v4l2->vb_vbi_queue_lock; + ret = em28xx_vb2_setup(dev); + if (ret) { + dev_err(&dev->intf->dev, "unable to setup device queues, error %d\n", ret); + goto unregister_dev; + } + /* Allocate and fill vbi video_device struct */ if (em28xx_vbi_supported(dev) == 1) { em28xx_vdev_init(dev, &v4l2->vbi_dev, &em28xx_video_template, "vbi"); v4l2->vbi_dev.queue = &v4l2->vb_vbiq; - v4l2->vbi_dev.queue->lock = &v4l2->vb_vbi_queue_lock; v4l2->vbi_dev.device_caps = V4L2_CAP_STREAMING | V4L2_CAP_READWRITE | V4L2_CAP_VBI_CAPTURE; if ((v4l2->vdev.device_caps & V4L2_CAP_TUNER) == 0) @@ -3068,9 +3078,6 @@ static int em28xx_v4l2_init(struct em28xx *dev) /* Save some power by putting tuner to sleep */ v4l2_device_call_all(&v4l2->v4l2_dev, 0, tuner, standby); - /* initialize videobuf2 stuff */ - em28xx_vb2_setup(dev); - dev_info(&dev->intf->dev, "V4L2 extension successfully initialized\n");