On Mon, Nov 09, 2015 at 08:49:12AM -0500, Kevin O'Connor wrote:
On Wed, Nov 04, 2015 at 03:30:52PM +0000, Wim Vervoorn wrote:
Hello,
I am running into issues when using USB3 sticks in a system (on an XHCI controller).
When I am using a single USB3 stick it gets detected properly. When I am using 2 USB3 sticks only one is detected. When using one USB3 and a USB2 stick it depends on the slots. In one case both are detected in the other case only the USB2 stick.
I was first blaming this on the XHCI controller initialization but I have now reproduced this same issue on two completely different systems. One base on AMD Steppe Eagle and the other on an Intel Braswell.
Does this sound familiar? Has anyone run into this before. (I am using two ADAT CI03 sticks)
To summarize some off-list exchange of debug logs, it looks like this issue can be worked around by both applying the "msleep(20)" patch and by increasing USB_TIME_SIGATT to 500.
I think making a new config file (eg, "etc/usb-time-sigatt") to allow USB_TIME_SIGATT to be configured without patching the code would make sense. I'll send a patch.
I don't have a good solution for the msleep() issue right now.
Can you try reverting the msleep and sigatt changes and only apply the patch below?
-Kevin
commit d331c611e5572270419406e1e0057cd17e502edd Author: Kevin O'Connor kevin@koconnor.net Date: Tue Nov 10 08:50:52 2015 -0500
xhci: Check for device disconnects during USB2 reset polling
Some XHCI controllers register super-speed devices on high-speed ports and then disconnect them when the super-speed detection completes. Make sure to recognize these disconnect events during the reset process.
Signed-off-by: Kevin O'Connor kevin@koconnor.net
diff --git a/src/hw/usb-xhci.c b/src/hw/usb-xhci.c index 173dff1..945b462 100644 --- a/src/hw/usb-xhci.c +++ b/src/hw/usb-xhci.c @@ -351,6 +351,9 @@ xhci_hub_reset(struct usbhub_s *hub, u32 port) struct usb_xhci_s *xhci = container_of(hub->cntl, struct usb_xhci_s, usb); u32 portsc = readl(&xhci->pr[port].portsc); int rc; + if (!(portsc & XHCI_PORTSC_CCS)) + // Device no longer connected?! + return -1;
switch (xhci_get_field(portsc, XHCI_PORTSC_PLS)) { case PLS_U0: @@ -360,11 +363,22 @@ xhci_hub_reset(struct usbhub_s *hub, u32 port) case PLS_POLLING: // A USB2 port - perform device reset and wait for completion xhci_print_port_state(3, __func__, port, portsc); - portsc |= XHCI_PORTSC_PR; - writel(&xhci->pr[port].portsc, portsc); - if (wait_bit(&xhci->pr[port].portsc, XHCI_PORTSC_PED, XHCI_PORTSC_PED, 100) != 0) - return -1; - portsc = readl(&xhci->pr[port].portsc); + writel(&xhci->pr[port].portsc, portsc | XHCI_PORTSC_PR); + u32 end = timer_calc(100); + for (;;) { + portsc = readl(&xhci->pr[port].portsc); + if (!(portsc & XHCI_PORTSC_CCS)) + // Device disconnected during reset + return -1; + if (portsc & XHCI_PORTSC_PED) + // Reset complete + break; + if (timer_check(end)) { + warn_timeout(); + return -1; + } + yield(); + } rc = speed_from_xhci[xhci_get_field(portsc, XHCI_PORTSC_SPEED)]; break; default: