summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristopher Pascoe <pascoe@cvs.openbsd.org>2006-08-22 01:53:43 +0000
committerChristopher Pascoe <pascoe@cvs.openbsd.org>2006-08-22 01:53:43 +0000
commit3cd6f7cf29a1da4dfa0e5d065f3dc9132c6261f3 (patch)
tree58eb5b42c98ca2322fa34705838dadf3f2409eb0
parent05d967276b6b43a3f9d9d15b208097b25cbe9a20 (diff)
Deactivate the QTDs when removing a queue head to prevent the host
controller from reactivating it. Slight variation on what is suggested in the EHCI spec to work around problems with VIA controllers. ok dlg@
-rw-r--r--sys/dev/usb/ehci.c25
1 files changed, 20 insertions, 5 deletions
diff --git a/sys/dev/usb/ehci.c b/sys/dev/usb/ehci.c
index 7a0364e53fd..8f63d6d9a7a 100644
--- a/sys/dev/usb/ehci.c
+++ b/sys/dev/usb/ehci.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ehci.c,v 1.66 2006/08/22 01:34:08 pascoe Exp $ */
+/* $OpenBSD: ehci.c,v 1.67 2006/08/22 01:53:42 pascoe Exp $ */
/* $NetBSD: ehci.c,v 1.66 2004/06/30 03:11:56 mycroft Exp $ */
/*
@@ -2462,7 +2462,7 @@ ehci_abort_xfer(usbd_xfer_handle xfer, usbd_status status)
}
/*
- * Step 1: Make interrupt routine and hardware ignore xfer.
+ * Step 1: Make interrupt routine and timeouts ignore xfer.
*/
s = splusb();
exfer->ehci_xfer_flags |= EHCI_XFER_ABORTING;
@@ -2481,7 +2481,21 @@ ehci_abort_xfer(usbd_xfer_handle xfer, usbd_status status)
ehci_rem_qh(sc, sqh, psqh);
/*
- * Step 3: make sure the soft interrupt routine
+ * Step 3: Deactivate all of the qTDs that we will be removing,
+ * otherwise the queue head may go active again. The EHCI spec
+ * suggests we should perform the deactivation before removing the
+ * queue head from the schedule, however the VT6202 (at least) only
+ * behaves correctly when we deactivate them afterwards.
+ */
+ for (sqtd = exfer->sqtdstart; ; sqtd = sqtd->nextqtd) {
+ sqtd->qtd.qtd_status = htole32(EHCI_QTD_HALTED);
+ if (sqtd == exfer->sqtdend)
+ break;
+ }
+ ehci_sync_hc(sc);
+
+ /*
+ * Step 4: make sure the soft interrupt routine
* has run. This should remove any completed items off the queue.
* The hardware has no reference to completed items (TDs).
* It's safe to remove them at any time.
@@ -2498,7 +2512,7 @@ ehci_abort_xfer(usbd_xfer_handle xfer, usbd_status status)
#endif /* USB_USE_SOFTINTR */
/*
- * Step 4: Remove any vestiges of the xfer from the hardware.
+ * Step 5: Remove any vestiges of the xfer from the hardware.
* The complication here is that the hardware may have executed
* into or even beyond the xfer we're trying to abort.
* So as we're scanning the TDs of this xfer we check if
@@ -2577,8 +2591,9 @@ ehci_abort_xfer(usbd_xfer_handle xfer, usbd_status status)
}
}
ehci_add_qh(sqh, psqh);
+
/*
- * Step 4: Execute callback.
+ * Step 6: Execute callback.
*/
#ifdef DIAGNOSTIC
exfer->isdone = 1;