summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJulius Werner <jwerner@chromium.org>2013-09-26 15:13:44 -0700
committerMarc Jones <marc.jones@se-eng.com>2014-08-31 23:49:54 +0200
commit49ba28339087cb1057fbb12071a0981013a88e55 (patch)
tree210e34c10995e3fa557ff6df6fbe92cb2e682d45
parent6eb83f4bf0c6ac88594449f42d606cbb4887615c (diff)
downloadcoreboot-49ba28339087cb1057fbb12071a0981013a88e55.tar.xz
libpayload: xhci: Ensure to reset dequeue pointer on stopped endpoints
This patch fixes a bug in the XHCI stack that occurs when a multi-TRB TD times out before the last TRB is processed. The driver will correctly issue a Stop Endpoint command in that case, but the xHC will still preserve the transfer state and just pick up right after that on the next doorbell ring. It will then process the leftover TRBs from the old TD the next time a transfer is issued. (cf. XHCI 4.6.9) We fix this by changing the existing xhci_reset_endpoint() calls in transfer functions to not only trigger on Halted (2) and Error (4), but also on Stopped (3). That function will not actually issue a Reset Endpoint command in this case, but it will nuke the whole transfer ring and issue a Set TR Dequeue Pointer command, which is sufficient (though slightly overkill) to solve our problem. Change-Id: I3abbe30ff9d4911a8af1f792324e018d427019e8 Signed-off-by: Julius Werner <jwerner@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/170833 Reviewed-by: Ronald Minnich <rminnich@chromium.org> Reviewed-by: Kees Cook <keescook@chromium.org> (cherry picked from commit f12424af0e29ac12963e8e5a7970fadcc0bb6cee) Signed-off-by: Isaac Christensen <isaac.christensen@se-eng.com> Reviewed-on: http://review.coreboot.org/6787 Reviewed-by: Stefan Reinauer <stefan.reinauer@coreboot.org> Tested-by: build bot (Jenkins)
-rw-r--r--payloads/libpayload/drivers/usb/xhci.c8
1 files changed, 4 insertions, 4 deletions
diff --git a/payloads/libpayload/drivers/usb/xhci.c b/payloads/libpayload/drivers/usb/xhci.c
index 4ab2fe3c34..5b30d0cf54 100644
--- a/payloads/libpayload/drivers/usb/xhci.c
+++ b/payloads/libpayload/drivers/usb/xhci.c
@@ -599,9 +599,9 @@ xhci_control(usbdev_t *const dev, const direction_t dir,
return -1;
}
- /* Reset endpoint if it's halted */
+ /* Reset endpoint if it's not running */
const unsigned ep_state = EC_GET(STATE, epctx);
- if (ep_state == 2 || ep_state == 4) {
+ if (ep_state > 1) {
if (xhci_reset_endpoint(dev, NULL, 0))
return -1;
}
@@ -710,9 +710,9 @@ xhci_bulk(endpoint_t *const ep, const int size, u8 *const src,
memcpy(data, src, size);
}
- /* Reset endpoint if it's halted */
+ /* Reset endpoint if it's not running */
const unsigned ep_state = EC_GET(STATE, epctx);
- if (ep_state == 2 || ep_state == 4) {
+ if (ep_state > 1) {
if (xhci_reset_endpoint(ep->dev, ep, 0))
return -1;
}