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 @@ -131,6 +131,25 @@ MODULE_LICENSE("GPL"); MODULE_VERSION(USBVISION_VERSION_STRING); MODULE_ALIAS(DRIVER_ALIAS); +#include +#include + +static void usbvision_check(struct usb_usbvision *usbvision, char *msg) +{ + struct kernfs_node *kn; + + if (!video_is_registered(&usbvision->rdev)) { + dev_info(&usbvision->rdev.dev, "Not registered: %s\n", msg); + } else { + kn = kernfs_find_and_get(usbvision->rdev.dev.kobj.sd, "power"); + if (kn) { + kernfs_put(kn); + dev_info(&usbvision->rdev.dev, "Power ok: %s\n", msg); + } else { + dev_err(&usbvision->rdev.dev, "Power gone: %s\n", msg); + } + } +} /*****************************************************************************/ /* SYSFS Code - Copied from the stv680.c usb module. */ @@ -314,6 +333,11 @@ static int usbvision_v4l2_open(struct fi if (mutex_lock_interruptible(&usbvision->v4l2_lock)) return -ERESTARTSYS; + usbvision_check(usbvision, "v4l2 open"); + if (usbvision->remove_pending) { + err_code = -ENODEV; + goto unlock; + } if (usbvision->user) { err_code = -EBUSY; } else { @@ -363,6 +387,7 @@ unlock: mutex_unlock(&usbvision->v4l2_lock); PDEBUG(DBG_IO, "success"); + pr_info("v4l2 open -> %d\n", err_code); return err_code; } @@ -377,10 +402,13 @@ unlock: static int usbvision_v4l2_close(struct file *file) { struct usb_usbvision *usbvision = video_drvdata(file); + int r; PDEBUG(DBG_IO, "close"); + usbvision_check(usbvision, "v4l2 close 1"); mutex_lock(&usbvision->v4l2_lock); + usbvision_check(usbvision, "v4l2 close 2"); usbvision_audio_off(usbvision); usbvision_restart_isoc(usbvision); usbvision_stop_isoc(usbvision); @@ -389,11 +417,13 @@ static int usbvision_v4l2_close(struct f usbvision_frames_free(usbvision); usbvision_empty_framequeues(usbvision); usbvision_scratch_free(usbvision); + usbvision_check(usbvision, "v4l2 close 3"); 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 +483,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 +1106,12 @@ static int usbvision_radio_open(struct f if (mutex_lock_interruptible(&usbvision->v4l2_lock)) return -ERESTARTSYS; + + usbvision_check(usbvision, "radio open"); + if (usbvision->remove_pending) { + err_code = -ENODEV; + goto out; + } err_code = v4l2_fh_open(file); if (err_code) goto out; @@ -1098,6 +1137,7 @@ static int usbvision_radio_open(struct f } out: mutex_unlock(&usbvision->v4l2_lock); + pr_info("radio open -> %d\n", err_code); return err_code; } @@ -1105,21 +1145,27 @@ out: static int usbvision_radio_close(struct file *file) { struct usb_usbvision *usbvision = video_drvdata(file); + int r; PDEBUG(DBG_IO, ""); + usbvision_check(usbvision, "radio close 1"); mutex_lock(&usbvision->v4l2_lock); + usbvision_check(usbvision, "radio close 2"); /* 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_check(usbvision, "radio close 3"); 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); @@ -1233,10 +1279,13 @@ static void usbvision_vdev_init(struct u static void usbvision_unregister_video(struct usb_usbvision *usbvision) { /* Radio Device: */ + usbvision_check(usbvision, "unregister video"); 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: */ @@ -1283,6 +1332,7 @@ static int usbvision_register_video(stru usbvision->nr, video_device_node_name(&usbvision->rdev)); } /* all done */ + usbvision_check(usbvision, "register video"); return 0; err_exit: @@ -1346,6 +1396,7 @@ static void usbvision_release(struct usb { PDEBUG(DBG_PROBE, ""); + usbvision_check(usbvision, "release"); usbvision->initialized = 0; usbvision_remove_sysfs(&usbvision->vdev); @@ -1551,6 +1602,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, ""); @@ -1560,6 +1612,7 @@ static void usbvision_disconnect(struct } mutex_lock(&usbvision->v4l2_lock); + usbvision_check(usbvision, "disconnect 1"); /* At this time we ask to cancel outstanding URBs */ usbvision_stop_isoc(usbvision); @@ -1567,13 +1620,15 @@ 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 */ + usbvision_check(usbvision, "disconnect 2"); 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);