summaryrefslogtreecommitdiff
path: root/sys/dev/usb/xhci.c
diff options
context:
space:
mode:
authorMartin Pieuchot <mpi@cvs.openbsd.org>2015-01-04 20:10:09 +0000
committerMartin Pieuchot <mpi@cvs.openbsd.org>2015-01-04 20:10:09 +0000
commit65bdaaec414a989cb901662735f4f3cf63f4307a (patch)
tree80af32c23700999eb4a0a6e75c447af2c1a17a05 /sys/dev/usb/xhci.c
parent16e2702891d485c2c4472ba32134a360f16e77ef (diff)
Only set the status of a completed xfer just before giving it back to
the stack. This will allow stricter checks when aborting transfers. While here update a comment about short transfer and multi-TRB TD since bulk transfers can also use a chain now.
Diffstat (limited to 'sys/dev/usb/xhci.c')
-rw-r--r--sys/dev/usb/xhci.c25
1 files changed, 12 insertions, 13 deletions
diff --git a/sys/dev/usb/xhci.c b/sys/dev/usb/xhci.c
index 7f50578a4e7..b2f4a3c473e 100644
--- a/sys/dev/usb/xhci.c
+++ b/sys/dev/usb/xhci.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: xhci.c,v 1.50 2015/01/02 18:06:25 mpi Exp $ */
+/* $OpenBSD: xhci.c,v 1.51 2015/01/04 20:10:08 mpi Exp $ */
/*
* Copyright (c) 2014 Martin Pieuchot
@@ -744,29 +744,28 @@ xhci_event_xfer(struct xhci_softc *sc, uint64_t paddr, uint32_t status,
switch (code) {
case XHCI_CODE_SUCCESS:
/*
- * This might be the ``Event Status TRB'' of a control
- * request for which the ``Event Data TRB'' triggered
- * a Short Transfer condition, see below.
+ * This might be the last TRB of a TD that ended up
+ * with a Short Transfer condition, see below.
*/
- if (xfer->actlen)
- break;
+ if (xfer->actlen == 0)
+ xfer->actlen = xfer->length - remain;
- /* FALLTHROUGH */
+ xfer->status = USBD_NORMAL_COMPLETION;
+ break;
case XHCI_CODE_SHORT_XFER:
xfer->actlen = xfer->length - remain;
- xfer->status = USBD_NORMAL_COMPLETION;
/*
* If this is not the last TRB of a transfer, we should
- * not assume the USB packet is finished. In the case
- * of a Sort Transfer condition we should theoretically
- * clear the IOC flags on the ``Event Status TRB'' but
- * the HC might have already processed it since before
- * we start processing the softinterrupt.
+ * theoretically clear the IOC at the end of the chain
+ * but the HC might have already processed it before we
+ * had a change to schedule the softinterrupt.
*/
xx = (struct xhci_xfer *)xfer;
if (xx->index != trb_idx)
return;
+
+ xfer->status = USBD_NORMAL_COMPLETION;
break;
case XHCI_CODE_TXERR:
case XHCI_CODE_SPLITERR: