Re: Reap URB on disconnected device never returns

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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

[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux