Hi,

I found another issue with the calculation of the actual length on short
xfers.  On e.g. bulk transfers with multiple TRBs the first short TRB
will give us a short event.  We will then calculate the actual length
and return.  So far this is good.

The last TRB in the TD is marked as IOC (Interrupt On Complete) and will
give us an additional event.  One one of my machine this is not a succ-
ess event, but also a short event.

In that case we would set xfer->actlen again, overwriting the actual
result.  It would sum all TRBs apart from the last one which will result
in a bigger and bogus number.

What we need to do is to make sure it's only set once, and that's when
we get a short event for the first time.  This is essentially the same
check that we have in the success event.

ok?

Patrick

diff --git a/sys/dev/usb/xhci.c b/sys/dev/usb/xhci.c
index 064235b2841..eea7be1e5e3 100644
--- a/sys/dev/usb/xhci.c
+++ b/sys/dev/usb/xhci.c
@@ -856,8 +856,9 @@ xhci_event_xfer_generic(struct xhci_softc *sc, struct 
usbd_xfer *xfer,
                /*
                 * Use values from the transfer TRB instead of the status TRB.
                 */
-               xfer->actlen = xhci_xfer_length_generic(xx, xp, trb_idx) -
-                   remain;
+               if (xfer->actlen == 0)
+                       xfer->actlen =
+                           xhci_xfer_length_generic(xx, xp, trb_idx) - remain;
                /*
                 * If this is not the last TRB of a transfer, we should
                 * theoretically clear the IOC at the end of the chain

Reply via email to