path: root/payloads
diff options
authorSourabh Banerjee <sbanerje@codeaurora.org>2014-09-24 16:14:45 +0530
committerPatrick Georgi <pgeorgi@google.com>2015-03-23 18:41:18 +0100
commite73335ce8ec518035df525142e5e9f4b92ccd143 (patch)
tree262825f3f380358e53497bd72205db990c1cad4d /payloads
parent654cf9c2d812dbb614e37db41b22f186553ced81 (diff)
libpayload: usb: xhci: set ENT flag in last Normal TRB
If a TD is comprised of one or more Normal TRBs and terminated with an Event Data TRB, then the transition to the Idle state (and associated Stream state save) could occur after all the data for the TD has been moved (e.g. after Transfer Event TRBs have been executed), but before the Event Data TRB is executed. Under these conditions, the execution of the Event Data TRB is necessary to complete the TD, otherwise it does not occur until the next time the Stream is scheduled. This could lead to the lock up. The Evaluate Next TRB(ENT) flag provides a means of forcing the execution of a terminating Event Data TRB. Setting ENT flag in last Normal TRB makes the xHC to evaluate the Even Data TRB. BUG=chrome-os-partner:29375 TEST=Verified kernel boot-up on storm from previously failing USB stick. USB stick model: Sandisk Ultra USB 3.0 Pen Drive 32 GB Strontium Jet USB 3.0 Pen Drive 32 GB Change-Id: I092e2109c55c2274239c493cb67b47d730304ed2 Signed-off-by: Patrick Georgi <pgeorgi@chromium.org> Original-Commit-Id: 7eefb3b2858c841165ae839d349d2a0be50fbcc8 Original-Change-Id: I4e123577ec5a5996d87d2fc52cb6cf5c571c9fae Original-Signed-off-by: Sourabh Banerjee <sbanerje@codeaurora.org> Original-Reviewed-on: https://chromium-review.googlesource.com/220123 Original-Reviewed-by: Julius Werner <jwerner@chromium.org> Original-Commit-Queue: Vadim Bendebury <vbendeb@chromium.org> Original-Tested-by: Vadim Bendebury <vbendeb@chromium.org> Reviewed-on: http://review.coreboot.org/8736 Tested-by: build bot (Jenkins) Reviewed-by: Patrick Georgi <pgeorgi@google.com>
Diffstat (limited to 'payloads')
2 files changed, 11 insertions, 0 deletions
diff --git a/payloads/libpayload/drivers/usb/xhci.c b/payloads/libpayload/drivers/usb/xhci.c
index 33009bc63..7adb304a2 100644
--- a/payloads/libpayload/drivers/usb/xhci.c
+++ b/payloads/libpayload/drivers/usb/xhci.c
@@ -551,6 +551,14 @@ xhci_enqueue_td(transfer_ring_t *const tr, const int ep, const size_t mps,
} else {
+ /*
+ * This is a workaround for Synopsys DWC3. If the ENT flag is
+ * not set for the Normal and Data Stage TRBs. We get Event TRB
+ * with length 0x20d from the controller when we enqueue a TRB
+ * for the IN endpoint with length 0x200.
+ */
+ if (!length)
+ TRB_SET(ENT, trb, 1);
diff --git a/payloads/libpayload/drivers/usb/xhci_private.h b/payloads/libpayload/drivers/usb/xhci_private.h
index 43800d8d4..3861858b4 100644
--- a/payloads/libpayload/drivers/usb/xhci_private.h
+++ b/payloads/libpayload/drivers/usb/xhci_private.h
@@ -93,6 +93,9 @@ enum { TRB_DIR_OUT = 0, TRB_DIR_IN = 1 };
#define TRB_TC_FIELD control /* TC - Toggle Cycle */
#define TRB_TC_START 1
#define TRB_TC_LEN 1
+#define TRB_ENT_FIELD control /* ENT - Evaluate Next TRB */
+#define TRB_ENT_START 1
+#define TRB_ENT_LEN 1
#define TRB_ISP_FIELD control /* ISP - Interrupt-on Short Packet */
#define TRB_ISP_START 2
#define TRB_ISP_LEN 1