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,31 @@ MODULE_LICENSE("GPL"); MODULE_VERSION(USBVISION_VERSION_STRING); MODULE_ALIAS(DRIVER_ALIAS); +#include +#include + +extern void ASlist(struct kernfs_node *parent); +static int ASflag; + +static int usbvision_check(struct usb_usbvision *usbvision, char *msg) +{ + struct kernfs_node *kn; + + if (!video_is_registered(&usbvision->rdev)) { + dev_info(&usbvision->rdev.dev, "AS 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, "AS Power ok: %s\n", msg); + } else { + dev_err(&usbvision->rdev.dev, "AS Power gone: %s\n", msg); + return 1; + } + } + return 0; +} + /*****************************************************************************/ /* SYSFS Code - Copied from the stv680.c usb module. */ @@ -314,6 +339,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 +406,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 +421,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 +484,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 +1107,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 +1144,28 @@ 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_check(usbvision, "radio close 3"); usbvision_audio_off(usbvision); usbvision->radio = 0; usbvision->user--; + r = usbvision->remove_pending; + usbvision_check(usbvision, "radio close 4"); 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,6 +1282,8 @@ static void usbvision_unregister_video(s if (video_is_registered(&usbvision->rdev)) { PDEBUG(DBG_PROBE, "unregister %s [v4l2]", video_device_node_name(&usbvision->rdev)); + if (usbvision_check(usbvision, "unregister_video")) + ASlist(usbvision->rdev.dev.kobj.sd); video_unregister_device(&usbvision->rdev); } @@ -1283,6 +1331,10 @@ static int usbvision_register_video(stru usbvision->nr, video_device_node_name(&usbvision->rdev)); } /* all done */ + if (!ASflag) { + ASflag = 1; + ASlist(usbvision->rdev.dev.kobj.sd); + } return 0; err_exit: @@ -1551,6 +1603,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 +1620,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/fs/kernfs/dir.c =================================================================== --- usb-devel.orig/fs/kernfs/dir.c +++ usb-devel/fs/kernfs/dir.c @@ -25,6 +25,31 @@ static DEFINE_SPINLOCK(kernfs_idr_lock); #define rb_to_kn(X) rb_entry((X), struct kernfs_node, rb) +static void ASlist2(struct rb_node *node, int level) +{ + struct kernfs_node *kn = rb_to_kn(node); + + if (node->rb_left) + ASlist2(node->rb_left, level + 1); + printk(KERN_INFO "%d %u: %s\n", level, kn->hash, kn->name); + if (node->rb_right) + ASlist2(node->rb_right, level + 1); +} + +void ASlist(struct kernfs_node *parent) +{ + struct rb_node *node; + + mutex_lock(&kernfs_mutex); + node = parent->dir.children.rb_node; + printk(KERN_INFO "Listing for %s (%px, root node %px)\n", + parent->name, parent, node); + if (node) + ASlist2(node, 0); + mutex_unlock(&kernfs_mutex); +} +EXPORT_SYMBOL_GPL(ASlist); + static bool kernfs_active(struct kernfs_node *kn) { lockdep_assert_held(&kernfs_mutex);