Index: usb-devel/drivers/media/usb/usbvision/usbvision-video.c =================================================================== --- usb-devel.orig/drivers/media/usb/usbvision/usbvision-video.c +++ usb-devel/drivers/media/usb/usbvision/usbvision-video.c @@ -314,6 +314,10 @@ static int usbvision_v4l2_open(struct fi if (mutex_lock_interruptible(&usbvision->v4l2_lock)) return -ERESTARTSYS; + if (usbvision->remove_pending) { + err_code = -ENODEV; + goto unlock; + } if (usbvision->user) { err_code = -EBUSY; } else { @@ -377,6 +381,7 @@ unlock: static int usbvision_v4l2_close(struct file *file) { struct usb_usbvision *usbvision = video_drvdata(file); + int r; PDEBUG(DBG_IO, "close"); @@ -391,9 +396,10 @@ static int usbvision_v4l2_close(struct f usbvision_scratch_free(usbvision); usbvision->user--; + r = usbvision->remove_pending; mutex_unlock(&usbvision->v4l2_lock); - if (usbvision->remove_pending) { + if (r) { printk(KERN_INFO "%s: Final disconnect\n", __func__); usbvision_release(usbvision); return 0; @@ -453,6 +459,9 @@ static int vidioc_querycap(struct file * { struct usb_usbvision *usbvision = video_drvdata(file); + if (!usbvision->dev) + return -ENODEV; + strscpy(vc->driver, "USBVision", sizeof(vc->driver)); strscpy(vc->card, usbvision_device_data[usbvision->dev_model].model_string, @@ -1073,6 +1082,11 @@ static int usbvision_radio_open(struct f if (mutex_lock_interruptible(&usbvision->v4l2_lock)) return -ERESTARTSYS; + + if (usbvision->remove_pending) { + err_code = -ENODEV; + goto out; + } err_code = v4l2_fh_open(file); if (err_code) goto out; @@ -1105,21 +1119,24 @@ out: static int usbvision_radio_close(struct file *file) { struct usb_usbvision *usbvision = video_drvdata(file); + int r; PDEBUG(DBG_IO, ""); mutex_lock(&usbvision->v4l2_lock); /* Set packet size to 0 */ usbvision->iface_alt = 0; - usb_set_interface(usbvision->dev, usbvision->iface, + if (usbvision->dev) + usb_set_interface(usbvision->dev, usbvision->iface, usbvision->iface_alt); usbvision_audio_off(usbvision); usbvision->radio = 0; usbvision->user--; + r = usbvision->remove_pending; mutex_unlock(&usbvision->v4l2_lock); - if (usbvision->remove_pending) { + if (r) { printk(KERN_INFO "%s: Final disconnect\n", __func__); v4l2_fh_release(file); usbvision_release(usbvision); @@ -1236,14 +1253,18 @@ static void usbvision_unregister_video(s if (video_is_registered(&usbvision->rdev)) { PDEBUG(DBG_PROBE, "unregister %s [v4l2]", video_device_node_name(&usbvision->rdev)); + dev_info(&usbvision->rdev.dev, "Unregister\n"); video_unregister_device(&usbvision->rdev); + printk(KERN_INFO "Unregister done\n"); } /* Video Device: */ if (video_is_registered(&usbvision->vdev)) { PDEBUG(DBG_PROBE, "unregister %s [v4l2]", video_device_node_name(&usbvision->vdev)); + dev_info(&usbvision->vdev.dev, "Unregister\n"); video_unregister_device(&usbvision->vdev); + printk(KERN_INFO "Unregister done\n"); } } @@ -1355,6 +1376,7 @@ static void usbvision_release(struct usb usb_free_urb(usbvision->ctrl_urb); v4l2_ctrl_handler_free(&usbvision->hdl); + dev_info(&usbvision->dev->dev, "usbvision_release -> v4l2_device_unregister\n"); v4l2_device_unregister(&usbvision->v4l2_dev); kfree(usbvision); @@ -1551,6 +1573,7 @@ err_usb: static void usbvision_disconnect(struct usb_interface *intf) { struct usb_usbvision *usbvision = to_usbvision(usb_get_intfdata(intf)); + int u; PDEBUG(DBG_PROBE, ""); @@ -1567,13 +1590,14 @@ static void usbvision_disconnect(struct v4l2_device_disconnect(&usbvision->v4l2_dev); usbvision_i2c_unregister(usbvision); usbvision->remove_pending = 1; /* Now all ISO data will be ignored */ + u = usbvision->user; usb_put_dev(usbvision->dev); usbvision->dev = NULL; /* USB device is no more */ mutex_unlock(&usbvision->v4l2_lock); - if (usbvision->user) { + if (u) { printk(KERN_INFO "%s: In use, disconnect pending\n", __func__); wake_up_interruptible(&usbvision->wait_frame); Index: usb-devel/drivers/media/v4l2-core/v4l2-dev.c =================================================================== --- usb-devel.orig/drivers/media/v4l2-core/v4l2-dev.c +++ usb-devel/drivers/media/v4l2-core/v4l2-dev.c @@ -1048,6 +1048,7 @@ void video_unregister_device(struct vide */ clear_bit(V4L2_FL_REGISTERED, &vdev->flags); mutex_unlock(&videodev_lock); + dump_stack(); device_unregister(&vdev->dev); } EXPORT_SYMBOL(video_unregister_device);