Hello Alan,
I tried your patch with my kernel (2.6.27.7) and it works !
I have tried also the latest kernel (2.6.29-rc7-git1), but this kernel
has also the problem.
Can you estimate when this patch will be applied to the mainline?
Martin Poupe
Alan Stern wrote:
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