Re: usb_kill_urb deadlock with multiple hubs in series (2.6.29)

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

 



On 22/11/09 02:20, Alan Stern wrote:
> On Sat, 21 Nov 2009, Alan Stern wrote:
> 
>> > They are, and they all pretend to be self-powered, but it shouldn't
>> > cause a deadlock situation. I couldn't resolve it even by unplugging
>> > all devices from that host controller.
>> 
>> Tracking down the deadlock will require more information.  A kernel log
>> with CONFIG_USB_DEBUG certainly, and a usbmon trace if you can get it.
> 
> Sorry, I forgot that you had included a detailed log in the original
> bug description.  It shows that khubd is waiting for a spinlock.  Most
> likely some other process is holding that lock but isn't included in
> your listing.  ksuspend_usbd is a potential suspect, along with 
> anything else accessing a USB device.
> 
> Also, why was lsusb running at the time of the deadlock?

I ran lsusb after the deadlock occurred, but before getting a list of
waiting tasks.

21 19:37:36 [58320.379525] temperhum     D 000034e2     0  2212   2210
would have 3 USB devices open, but two of them are on other controllers
and the devices are accessed serially. There are another 3 more USB
devices; I didn't check all of them but at least one was still working
properly. The other two would not have been actively in use.

If it happens again I'll get a stack trace of all tasks. Aren't they
stuck in the following call inside usb_kill_urb()?
  wait_event(usb_kill_urb_queue, atomic_read(&urb->use_count) == 0);

Before that, it calls usb_hcd_unlink_urb(), but the return value is
ignored?

One possible path is:
  usb_hcd_unlink_urb()
    unlink1() // use_count > 0
      usb_rh_urb_dequeue()
	usb_hcd_check_unlink_urb()

which could return non-zero stopping usb_hcd_unlink_urb() from calling
usb_hcd_giveback_urb() and then the use_count isn't decremented. It
looks like the hardware would then be responsible for causing
usb_hcd_giveback_urb() to run, unless usb_hcd_poll_rh_status() runs.

This code in usb_hcd_check_unlink_urb() does not match its comment:
   /* Any status except -EINPROGRESS means something already started to
    * unlink this URB from the hardware.  So there's no more work to do.
    */
   if (urb->unlinked)
      return -EBUSY;
   urb->unlinked = status;
"Any status except -EINPROGRESS" but it doesn't check what the value of
urb->unlinked is, so it could be -EINPROGRESS.

I can try connecting multiple hub devices which won't stay stable again,
but not on the same hardware (although it'll still be an OHCI HCD).

-- 
Simon Arlott
--
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