[SeaBIOS] USB3 problems

Kevin O'Connor kevin at koconnor.net
Tue Nov 10 14:57:57 CET 2015


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 at 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 at 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:



More information about the SeaBIOS mailing list