On Thu, 5 Mar 2009, Martin Poupe wrote: > Hello, > I have found folowing bug in linux kernel (see also in > http://bugzilla.kernel.org/show_bug.cgi?id=12817): > > Distribution:Slackware 12.2 > Kernel: 2.6.27.7 > Problem Description and steps to reproduce: > 1. Submit urb to read from interrupt (or bulk) endpoint from USB device > 2. call ioctl to reap this urb (USBDEVS_REAPURB), there are no other requests pending for this device (fd) > 3. the thread is blocked in the kernel (which is OK) > 4. disconnect the USB device > 5. the thread is blocked in the kernel for ever (!) > 6. try to discard urb (USBDEVS_DISCARDURB)from another thread, this fails > (probably because the fd is no longer valid), but this doesn't unblock the > first thread (!) > I am attaching simple test program (modified testlibusb.c from libusb-0.1.12 to demonstrate this). > To compile: gcc -o test test.c -lusb > To run: ./test <VID> <PID>, where VID and PID are hex numbers (e.g. ./test 1234 90ab) > You need to find some USB hardware, which is NOT drive by dedicated driver (so you cannot test this by USB mouse or flash drive, > because as early as submit urb fails by error EBUSY ) Here is a patch which should fix the problem. The patch was written for 2.6.29 but I think it will apply okay to 2.6.27. Alan Stern Index: usb-2.6/drivers/usb/core/devio.c =================================================================== --- usb-2.6.orig/drivers/usb/core/devio.c +++ usb-2.6/drivers/usb/core/devio.c @@ -359,11 +359,6 @@ static void destroy_async(struct dev_sta spin_lock_irqsave(&ps->lock, flags); } spin_unlock_irqrestore(&ps->lock, flags); - as = async_getcompleted(ps); - while (as) { - free_async(as); - as = async_getcompleted(ps); - } } static void destroy_async_on_interface(struct dev_state *ps, @@ -644,6 +639,7 @@ static int usbdev_release(struct inode * struct dev_state *ps = file->private_data; struct usb_device *dev = ps->dev; unsigned int ifnum; + struct async *as; usb_lock_device(dev); @@ -662,6 +658,12 @@ static int usbdev_release(struct inode * usb_unlock_device(dev); usb_put_dev(dev); put_pid(ps->disc_pid); + + as = async_getcompleted(ps); + while (as) { + free_async(as); + as = async_getcompleted(ps); + } kfree(ps); return 0; } -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html