[SeaBIOS] [PATCH 1/4] xhci: Update the times for usb command timeouts.

Kevin O'Connor kevin at koconnor.net
Sat Jun 14 20:08:50 CEST 2014


The xhci controller had a hardcoded 1 second timeout for both bulk and
control transfers.  The 1 second bulk timeout is too small for some
real devices.

Increase both times to 5.1 seconds - according to the USB spec, the
maximum time a command should take is 5 seconds.  However, have the
set_address command only wait for 150ms (spec says set_address should
take no more than 50ms).

Introduce usb_xfer_time() to calculate maximum command time.

Signed-off-by: Kevin O'Connor <kevin at koconnor.net>
---
 src/hw/usb-xhci.c |  4 ++--
 src/hw/usb.c      | 13 +++++++++++++
 src/hw/usb.h      |  5 +++++
 3 files changed, 20 insertions(+), 2 deletions(-)

diff --git a/src/hw/usb-xhci.c b/src/hw/usb-xhci.c
index ca1fe25..e3052a5 100644
--- a/src/hw/usb-xhci.c
+++ b/src/hw/usb-xhci.c
@@ -1042,7 +1042,7 @@ xhci_control(struct usb_pipe *p, int dir, const void *cmd, int cmdsize
         xhci_xfer_data(pipe, dir, data, datalen);
     xhci_xfer_status(pipe, dir, datalen);
 
-    int cc = xhci_event_wait(xhci, &pipe->reqs, 1000);
+    int cc = xhci_event_wait(xhci, &pipe->reqs, usb_xfer_time(p, datalen));
     if (cc != CC_SUCCESS) {
         dprintf(1, "%s: control xfer failed (cc %d)\n", __func__, cc);
         return -1;
@@ -1062,7 +1062,7 @@ xhci_send_bulk(struct usb_pipe *p, int dir, void *data, int datalen)
         GET_LOWFLAT(pipe->pipe.cntl), struct usb_xhci_s, usb);
 
     xhci_xfer_normal(pipe, data, datalen);
-    int cc = xhci_event_wait(xhci, &pipe->reqs, 1000);
+    int cc = xhci_event_wait(xhci, &pipe->reqs, usb_xfer_time(p, datalen));
     if (cc != CC_SUCCESS) {
         dprintf(1, "%s: bulk xfer failed (cc %d)\n", __func__, cc);
         return -1;
diff --git a/src/hw/usb.c b/src/hw/usb.c
index 7b8a9f5..46b46be 100644
--- a/src/hw/usb.c
+++ b/src/hw/usb.c
@@ -187,6 +187,19 @@ usb_getFrameExp(struct usbdevice_s *usbdev
     return (period <= 4) ? 0 : period - 4;
 }
 
+// Maximum time (in ms) a data transfer should take
+int
+usb_xfer_time(struct usb_pipe *pipe, int datalen)
+{
+    // Use the maximum command time (5 seconds), except for
+    // set_address commands where we don't want to stall the boot if
+    // the device doesn't actually exist.  Add 100ms to account for
+    // any controller delays.
+    if (!pipe->devaddr)
+        return USB_TIME_STATUS + 100;
+    return USB_TIME_COMMAND + 100;
+}
+
 // Find the first endpoing of a given type in an interface description.
 struct usb_endpoint_descriptor *
 findEndPointDesc(struct usbdevice_s *usbdev, int type, int dir)
diff --git a/src/hw/usb.h b/src/hw/usb.h
index 6196296..3a663ce 100644
--- a/src/hw/usb.h
+++ b/src/hw/usb.h
@@ -84,6 +84,10 @@ struct usbhub_op_s {
 #define USB_TIME_DRSTR  50
 #define USB_TIME_RSTRCY 10
 
+#define USB_TIME_STATUS  50
+#define USB_TIME_DATAIN  500
+#define USB_TIME_COMMAND 5000
+
 #define USB_TIME_SETADDR_RECOVERY 2
 
 #define USB_PID_OUT                     0xe1
@@ -237,6 +241,7 @@ void usb_desc2pipe(struct usb_pipe *pipe, struct usbdevice_s *usbdev
                    , struct usb_endpoint_descriptor *epdesc);
 int usb_getFrameExp(struct usbdevice_s *usbdev
                     , struct usb_endpoint_descriptor *epdesc);
+int usb_xfer_time(struct usb_pipe *pipe, int datalen);
 struct usb_endpoint_descriptor *findEndPointDesc(struct usbdevice_s *usbdev
                                                  , int type, int dir);
 void usb_enumerate(struct usbhub_s *hub);
-- 
1.9.3




More information about the SeaBIOS mailing list