[media] au0828: fix disconnect sequence
The driver crashed when the device was disconnected while an application still had a device node open. Fixed by using the release() callback of struct v4l2_device. Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com> Reviewed-by: Devin Heitmueller <dheitmueller@kernellabs.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
This commit is contained in:
parent
dc6d2a2f66
commit
823beb7e22
@ -125,6 +125,26 @@ static int recv_control_msg(struct au0828_dev *dev, u16 request, u32 value,
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void au0828_usb_release(struct au0828_dev *dev)
|
||||||
|
{
|
||||||
|
/* I2C */
|
||||||
|
au0828_i2c_unregister(dev);
|
||||||
|
|
||||||
|
kfree(dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_VIDEO_AU0828_V4L2
|
||||||
|
static void au0828_usb_v4l2_release(struct v4l2_device *v4l2_dev)
|
||||||
|
{
|
||||||
|
struct au0828_dev *dev =
|
||||||
|
container_of(v4l2_dev, struct au0828_dev, v4l2_dev);
|
||||||
|
|
||||||
|
v4l2_ctrl_handler_free(&dev->v4l2_ctrl_hdl);
|
||||||
|
v4l2_device_unregister(&dev->v4l2_dev);
|
||||||
|
au0828_usb_release(dev);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static void au0828_usb_disconnect(struct usb_interface *interface)
|
static void au0828_usb_disconnect(struct usb_interface *interface)
|
||||||
{
|
{
|
||||||
struct au0828_dev *dev = usb_get_intfdata(interface);
|
struct au0828_dev *dev = usb_get_intfdata(interface);
|
||||||
@ -134,27 +154,19 @@ static void au0828_usb_disconnect(struct usb_interface *interface)
|
|||||||
/* Digital TV */
|
/* Digital TV */
|
||||||
au0828_dvb_unregister(dev);
|
au0828_dvb_unregister(dev);
|
||||||
|
|
||||||
#ifdef CONFIG_VIDEO_AU0828_V4L2
|
|
||||||
if (AUVI_INPUT(0).type != AU0828_VMUX_UNDEFINED)
|
|
||||||
au0828_analog_unregister(dev);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* I2C */
|
|
||||||
au0828_i2c_unregister(dev);
|
|
||||||
|
|
||||||
#ifdef CONFIG_VIDEO_AU0828_V4L2
|
|
||||||
v4l2_ctrl_handler_free(&dev->v4l2_ctrl_hdl);
|
|
||||||
v4l2_device_unregister(&dev->v4l2_dev);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
usb_set_intfdata(interface, NULL);
|
usb_set_intfdata(interface, NULL);
|
||||||
|
|
||||||
mutex_lock(&dev->mutex);
|
mutex_lock(&dev->mutex);
|
||||||
dev->usbdev = NULL;
|
dev->usbdev = NULL;
|
||||||
mutex_unlock(&dev->mutex);
|
mutex_unlock(&dev->mutex);
|
||||||
|
#ifdef CONFIG_VIDEO_AU0828_V4L2
|
||||||
kfree(dev);
|
if (AUVI_INPUT(0).type != AU0828_VMUX_UNDEFINED) {
|
||||||
|
au0828_analog_unregister(dev);
|
||||||
|
v4l2_device_disconnect(&dev->v4l2_dev);
|
||||||
|
v4l2_device_put(&dev->v4l2_dev);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
au0828_usb_release(dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int au0828_usb_probe(struct usb_interface *interface,
|
static int au0828_usb_probe(struct usb_interface *interface,
|
||||||
@ -203,6 +215,8 @@ static int au0828_usb_probe(struct usb_interface *interface,
|
|||||||
dev->boardnr = id->driver_info;
|
dev->boardnr = id->driver_info;
|
||||||
|
|
||||||
#ifdef CONFIG_VIDEO_AU0828_V4L2
|
#ifdef CONFIG_VIDEO_AU0828_V4L2
|
||||||
|
dev->v4l2_dev.release = au0828_usb_v4l2_release;
|
||||||
|
|
||||||
/* Create the v4l2_device */
|
/* Create the v4l2_device */
|
||||||
retval = v4l2_device_register(&interface->dev, &dev->v4l2_dev);
|
retval = v4l2_device_register(&interface->dev, &dev->v4l2_dev);
|
||||||
if (retval) {
|
if (retval) {
|
||||||
|
@ -1063,14 +1063,7 @@ static int au0828_v4l2_close(struct file *filp)
|
|||||||
res_free(fh, AU0828_RESOURCE_VBI);
|
res_free(fh, AU0828_RESOURCE_VBI);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dev->users == 1) {
|
if (dev->users == 1 && video_is_registered(video_devdata(filp))) {
|
||||||
if (dev->dev_state & DEV_DISCONNECTED) {
|
|
||||||
au0828_analog_unregister(dev);
|
|
||||||
kfree(fh);
|
|
||||||
kfree(dev);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
au0828_analog_stream_disable(dev);
|
au0828_analog_stream_disable(dev);
|
||||||
|
|
||||||
au0828_uninit_isoc(dev);
|
au0828_uninit_isoc(dev);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user