summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorhselasky <hselasky@FreeBSD.org>2013-10-25 10:20:19 +0000
committerhselasky <hselasky@FreeBSD.org>2013-10-25 10:20:19 +0000
commit04fdff3ee16d842d845250e78d7bc7bb7347a839 (patch)
tree1b134fd463cba56305a8e5ec317d4d7a08e750f1
parent43cd197a0d5467cc3116e8b4d4190d5b88e73e61 (diff)
downloadFreeBSD-src-04fdff3ee16d842d845250e78d7bc7bb7347a839.zip
FreeBSD-src-04fdff3ee16d842d845250e78d7bc7bb7347a839.tar.gz
MFC r256750:
Improve XHCI stability. When a command timeout happens, the command should be aborted else the command queue can stop. Refer to section "4.6.1.2" of the XHCI specification. Approved by: re (glebius)
-rw-r--r--sys/dev/usb/controller/xhci.c19
1 files changed, 19 insertions, 0 deletions
diff --git a/sys/dev/usb/controller/xhci.c b/sys/dev/usb/controller/xhci.c
index 0f8470e..5892825 100644
--- a/sys/dev/usb/controller/xhci.c
+++ b/sys/dev/usb/controller/xhci.c
@@ -1144,6 +1144,25 @@ xhci_do_command(struct xhci_softc *sc, struct xhci_trb *trb,
}
if (err != 0) {
DPRINTFN(0, "Command timeout!\n");
+
+ /*
+ * Try to abort the last command as per section
+ * 4.6.1.2 "Aborting a Command" of the XHCI
+ * specification:
+ */
+ temp = XREAD4(sc, oper, XHCI_CRCR_LO);
+ XWRITE4(sc, oper, XHCI_CRCR_LO, temp | XHCI_CRCR_LO_CA);
+
+ /* wait for abort event, if any */
+ err = cv_timedwait(&sc->sc_cmd_cv, &sc->sc_bus.bus_mtx, hz / 16);
+
+ if (err != 0 && xhci_interrupt_poll(sc) != 0) {
+ DPRINTF("Command was completed when polling\n");
+ err = 0;
+ }
+ if (err != 0) {
+ DPRINTF("Command abort timeout!\n");
+ }
err = USB_ERR_TIMEOUT;
trb->dwTrb2 = 0;
trb->dwTrb3 = 0;
OpenPOWER on IntegriCloud