On Sat, Feb 29, 2020 at 12:06:17PM -0700, Allen Smith wrote:
> umass0: using SCSI over Bulk-Only
> scsibus0 at umass0: 2 targets, initiator 0
> sd0 at scsibus0 targ 1 lun 0: <Samsung, Flash Drive, 1100> removable
> serial.090c1000418120001168
> panic: _dmamap_sync: ran off map!

This is caused by wrong endianess. The diff below fixes the byte
swapping of trb_flags and trb_status in xhci(4). Tested with umass only,
isochronous transfer mode is untested.

OK?

Index: dev/usb/xhci.c
===================================================================
RCS file: src/sys/dev/usb/xhci.c,v
retrieving revision 1.112
diff -u -p -r1.112 xhci.c
--- dev/usb/xhci.c      22 Feb 2020 14:01:35 -0000      1.112
+++ dev/usb/xhci.c      1 Mar 2020 11:20:47 -0000
@@ -821,9 +821,10 @@ xhci_xfer_length_generic(struct xhci_xfe
            ((xx->index + xp->ring.ntrb) - xx->ntrb) % (xp->ring.ntrb - 1);
 
        while (1) {
-               type = xp->ring.trbs[trb0_idx].trb_flags & XHCI_TRB_TYPE_MASK;
+               type = letoh32(xp->ring.trbs[trb0_idx].trb_flags) &
+                   XHCI_TRB_TYPE_MASK;
                if (type == XHCI_TRB_TYPE_NORMAL || type == XHCI_TRB_TYPE_DATA)
-                       len += le32toh(XHCI_TRB_LEN(
+                       len += XHCI_TRB_LEN(letoh32(
                            xp->ring.trbs[trb0_idx].trb_status));
                if (trb0_idx == trb_idx)
                        break;
@@ -930,8 +931,8 @@ xhci_event_xfer_isoc(struct usbd_xfer *x
 
        /* Find the according frame index for this TRB. */
        while (trb0_idx != trb_idx) {
-               if ((xp->ring.trbs[trb0_idx].trb_flags & XHCI_TRB_TYPE_MASK) ==
-                   XHCI_TRB_TYPE_ISOCH)
+               if ((letoh32(xp->ring.trbs[trb0_idx].trb_flags) &
+                   XHCI_TRB_TYPE_MASK) == XHCI_TRB_TYPE_ISOCH)
                        frame_idx++;
                if (trb0_idx++ == (xp->ring.ntrb - 1))
                        trb0_idx = 0;
@@ -942,7 +943,7 @@ xhci_event_xfer_isoc(struct usbd_xfer *x
         * check if the first TRB needs accounting since it might not have
         * raised an interrupt in case of full data received.
         */
-       if ((xp->ring.trbs[trb_idx].trb_flags & XHCI_TRB_TYPE_MASK) ==
+       if ((letoh32(xp->ring.trbs[trb_idx].trb_flags) & XHCI_TRB_TYPE_MASK) ==
            XHCI_TRB_TYPE_NORMAL) {
                frame_idx--;
                if (trb_idx == 0)
@@ -950,13 +951,13 @@ xhci_event_xfer_isoc(struct usbd_xfer *x
                else
                        trb0_idx = trb_idx - 1;
                if (xfer->frlengths[frame_idx] == 0) {
-                       xfer->frlengths[frame_idx] =
-                           XHCI_TRB_LEN(xp->ring.trbs[trb0_idx].trb_status);
+                       xfer->frlengths[frame_idx] = XHCI_TRB_LEN(letoh32(
+                           xp->ring.trbs[trb0_idx].trb_status));
                }
        }
 
        xfer->frlengths[frame_idx] +=
-           XHCI_TRB_LEN(xp->ring.trbs[trb_idx].trb_status) - remain;
+           XHCI_TRB_LEN(letoh32(xp->ring.trbs[trb_idx].trb_status)) - remain;
        xfer->actlen += xfer->frlengths[frame_idx];
 
        if (xx->index != trb_idx)

Reply via email to