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)