[SeaBIOS] How to boot USB 3.0 devices with SeaBIOS

Kevin O'Connor kevin at koconnor.net
Tue Oct 3 18:15:10 CEST 2017


On Sun, Oct 01, 2017 at 04:25:05AM +0200, diffusae wrote:
> Hello!
> 
> On 01.10.2017 02:07, Kevin O'Connor wrote:
> 
> > That's an unusual failure.  Can you recompile seabios with the debug
> > level set to 5, reproduce, and forward the log?  Then also provide a
> > log with a boot when the USB 3 drive is not plugged in.  Finally,
> > please provide the output from "lsusb -t" and "lsusb".
> 
> To reproduce I've disconnected all other USB devices.
> With the drive plugged in, there is no USB 3 hub after boot.
> If there is no drive plugged in, than the timeout warning goes away:
> 
> |bfeab000| WARNING - Timeout at xhci_event_wait:735!

It looks like you're having the same USB2/USB3 device detection issue
that has popped up in the past.  For example, see:

https://mail.coreboot.org/pipermail/seabios/2015-December/010121.html

Interestingly, though, in your case the USB2 instance of the device
persists past reset, but not past set_address.  Worse, it appears the
controller hangs when set_address is sent to the USB2 instance.

Can you recompile SeaBIOS with the patch below applied?  I don't have
a good way to test this, but I'm hopeful it will help detect the USB2
disconnect and avoid the controller hang.

-Kevin


diff --git a/src/hw/usb-xhci.c b/src/hw/usb-xhci.c
index 50b3b86..a4cdd4e 100644
--- a/src/hw/usb-xhci.c
+++ b/src/hw/usb-xhci.c
@@ -779,29 +779,39 @@ static void xhci_trb_queue(struct xhci_ring *ring,
             trb->status & 0xffff);
 }
 
-static int xhci_cmd_submit(struct usb_xhci_s *xhci,
-                           struct xhci_trb *cmd)
+static int xhci_cmd_submit(struct usb_xhci_s *xhci, u32 command, u32 slotid
+                           , struct xhci_inctx *inctx)
 {
-    int rc;
+    if (inctx) {
+        struct xhci_slotctx *slot = (void*)&inctx[1 << xhci->context64];
+        u32 port = ((slot->ctx[1] >> 16) & 0xff) - 1;
+        u32 portsc = readl(&xhci->pr[port].portsc);
+        if (!(portsc & XHCI_PORTSC_CCS)) {
+            // Device no longer connected?!
+            xhci_print_port_state(1, __func__, port, portsc);
+            return -1;
+        }
+    }
+
+    struct xhci_trb cmd = {
+        .ptr_low  = (u32)inctx,
+        .ptr_high = 0,
+        .status   = 0,
+        .control  = (slotid << 24) | (command << 10),
+    };
 
     mutex_lock(&xhci->cmds->lock);
-    xhci_trb_queue(xhci->cmds, cmd);
+    xhci_trb_queue(xhci->cmds, &cmd);
     xhci_doorbell(xhci, 0, 0);
-    rc = xhci_event_wait(xhci, xhci->cmds, 1000);
+    int rc = xhci_event_wait(xhci, xhci->cmds, 1000);
     mutex_unlock(&xhci->cmds->lock);
     return rc;
 }
 
 static int xhci_cmd_enable_slot(struct usb_xhci_s *xhci)
 {
-    struct xhci_trb cmd = {
-        .ptr_low  = 0,
-        .ptr_high = 0,
-        .status   = 0,
-        .control  = (CR_ENABLE_SLOT << 10)
-    };
     dprintf(3, "%s:\n", __func__);
-    int cc = xhci_cmd_submit(xhci, &cmd);
+    int cc = xhci_cmd_submit(xhci, CR_ENABLE_SLOT, 0, NULL);
     if (cc != CC_SUCCESS)
         return -1;
     return (xhci->cmds->evt.control >> 24) & 0xff;
@@ -809,55 +819,31 @@ static int xhci_cmd_enable_slot(struct usb_xhci_s *xhci)
 
 static int xhci_cmd_disable_slot(struct usb_xhci_s *xhci, u32 slotid)
 {
-    struct xhci_trb cmd = {
-        .ptr_low  = 0,
-        .ptr_high = 0,
-        .status   = 0,
-        .control  = (slotid << 24) | (CR_DISABLE_SLOT << 10)
-    };
     dprintf(3, "%s: slotid %d\n", __func__, slotid);
-    return xhci_cmd_submit(xhci, &cmd);
+    return xhci_cmd_submit(xhci, CR_DISABLE_SLOT, slotid, NULL);
 }
 
 static int xhci_cmd_address_device(struct usb_xhci_s *xhci, u32 slotid
                                    , struct xhci_inctx *inctx)
 {
-    struct xhci_trb cmd = {
-        .ptr_low  = (u32)inctx,
-        .ptr_high = 0,
-        .status   = 0,
-        .control  = (slotid << 24) | (CR_ADDRESS_DEVICE << 10)
-    };
     dprintf(3, "%s: slotid %d\n", __func__, slotid);
-    return xhci_cmd_submit(xhci, &cmd);
+    return xhci_cmd_submit(xhci, CR_ADDRESS_DEVICE, slotid, inctx);
 }
 
 static int xhci_cmd_configure_endpoint(struct usb_xhci_s *xhci, u32 slotid
                                        , struct xhci_inctx *inctx)
 {
-    struct xhci_trb cmd = {
-        .ptr_low  = (u32)inctx,
-        .ptr_high = 0,
-        .status   = 0,
-        .control  = (slotid << 24) | (CR_CONFIGURE_ENDPOINT << 10)
-    };
     dprintf(3, "%s: slotid %d, add 0x%x, del 0x%x\n", __func__,
             slotid, inctx->add, inctx->del);
-    return xhci_cmd_submit(xhci, &cmd);
+    return xhci_cmd_submit(xhci, CR_CONFIGURE_ENDPOINT, slotid, inctx);
 }
 
 static int xhci_cmd_evaluate_context(struct usb_xhci_s *xhci, u32 slotid
                                      , struct xhci_inctx *inctx)
 {
-    struct xhci_trb cmd = {
-        .ptr_low  = (u32)inctx,
-        .ptr_high = 0,
-        .status   = 0,
-        .control  = (slotid << 24) | (CR_EVALUATE_CONTEXT << 10)
-    };
     dprintf(3, "%s: slotid %d, add 0x%x, del 0x%x\n", __func__,
             slotid, inctx->add, inctx->del);
-    return xhci_cmd_submit(xhci, &cmd);
+    return xhci_cmd_submit(xhci, CR_EVALUATE_CONTEXT, slotid, inctx);
 }
 
 static struct xhci_inctx *



More information about the SeaBIOS mailing list