Index: sys/dev/usb/xhci.c =================================================================== RCS file: /cvsroot/src/sys/dev/usb/xhci.c,v retrieving revision 1.188 diff -p -u -r1.188 xhci.c --- sys/dev/usb/xhci.c 30 Jan 2025 10:51:39 -0000 1.188 +++ sys/dev/usb/xhci.c 2 Aug 2025 20:33:40 -0000 @@ -129,9 +129,10 @@ fail: struct xhci_pipe { struct usbd_pipe xp_pipe; struct usb_task xp_async_task; - int16_t xp_isoc_next; /* next frame */ + int16_t xp_isoc_next; /* next micro frame */ uint8_t xp_maxb; /* max burst */ uint8_t xp_mult; + uint8_t xp_ival; }; #define XHCI_COMMAND_RING_TRBS 256 @@ -1566,6 +1567,19 @@ xhci_init(struct xhci_softc *sc) sizeof(uint64_t) * sc->sc_maxspbuf, BUS_DMASYNC_PREWRITE); } + sc->sc_isthresh = XHCI_HCS2_IST(hcs2); + aprint_debug_dev(sc->sc_dev, "sc_isthresh %d\n", sc->sc_isthresh); + + /* + * xHI 5.3.4 + * If bit[3] is 0, IST is number of microframes in bit[2:0] + * If bit[3] is 1, IST is number of frames in bit[2:0] + */ + if (sc->sc_isthresh & 0x8) { + sc->sc_isthresh = (sc->sc_isthresh & 0x7) * + USB_UFRAMES_PER_FRAME; + } + config = xhci_op_read_4(sc, XHCI_CONFIG); config &= ~0xFF; config |= sc->sc_maxslots & 0xFF; @@ -2330,7 +2344,8 @@ xhci_pipe_restart_async_task(void *cooki */ KASSERT(xfer->ux_status != USBD_NOT_STARTED); if (xfer->ux_status == USBD_IN_PROGRESS) { - (*pipe->up_methods->upm_start)(xfer); + if (pipe->up_methods->upm_start != NULL) + (*pipe->up_methods->upm_start)(xfer); } else { DPRINTF("pipe restart race xfer=%#jx status=%jd", (uintptr_t)xfer, xfer->ux_status, 0, 0); @@ -3983,6 +3998,7 @@ xhci_setup_maxburst(struct usbd_pipe *pi break; } + xpipe->xp_ival = ival; xpipe->xp_maxb = maxb + 1; xpipe->xp_mult = mult + 1; @@ -4604,20 +4620,23 @@ xhci_device_isoc_enter(struct usbd_xfer usb_syncmem(dma, 0, xfer->ux_length, isread ? BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE); - ival = xfer->ux_pipe->up_endpoint->ue_edesc->bInterval; - if (ival >= 1 && ival <= 16) - ival = 1 << (ival - 1); + ival = xpipe->xp_ival; + if (ival >= 0 && ival <= 15) + ival = 1 << ival; else ival = 1; /* fake something up */ + const unsigned mfmask = XHCI_MFINDEX_GET(~(uint32_t)0); + if (xpipe->xp_isoc_next == -1) { uint32_t mfindex = xhci_rt_read_4(sc, XHCI_MFINDEX); DPRINTF("mfindex %jx", (uintmax_t)mfindex, 0, 0, 0); - mfindex = XHCI_MFINDEX_GET(mfindex + 1); - mfindex /= USB_UFRAMES_PER_FRAME; - mfindex += 7; /* 7 frames is max possible IST */ - xpipe->xp_isoc_next = roundup2(mfindex, ival); + mfindex = XHCI_MFINDEX_GET(mfindex); + + /* Start Frame = MFINDEX + IST + 1 */ + mfindex += sc->sc_isthresh + 1; + xpipe->xp_isoc_next = roundup2(mfindex, ival) & mfmask; } offs = 0; @@ -4627,6 +4646,8 @@ xhci_device_isoc_enter(struct usbd_xfer const unsigned tbc = howmany(tdpc, maxb) - 1; const unsigned tlbpc1 = tdpc % maxb; const unsigned tlbpc = tlbpc1 ? tlbpc1 - 1 : maxb - 1; + const unsigned frid = xpipe->xp_isoc_next / + USB_UFRAMES_PER_FRAME; KASSERTMSG(len <= 0x10000, "len %d", len); parameter = DMAADDR(dma, offs); @@ -4639,10 +4660,10 @@ xhci_device_isoc_enter(struct usbd_xfer XHCI_TRB_3_TLBPC_SET(tlbpc) | XHCI_TRB_3_IOC_BIT; if (XHCI_HCC_CFC(sc->sc_hcc)) { - control |= XHCI_TRB_3_FRID_SET(xpipe->xp_isoc_next); + control |= XHCI_TRB_3_FRID_SET(frid); #if 0 } else if (xpipe->xp_isoc_next == -1) { - control |= XHCI_TRB_3_FRID_SET(xpipe->xp_isoc_next); + control |= XHCI_TRB_3_FRID_SET(frid); #endif } else { control |= XHCI_TRB_3_ISO_SIA_BIT; @@ -4653,7 +4674,7 @@ xhci_device_isoc_enter(struct usbd_xfer #endif xhci_xfer_put_trb(xx, i, parameter, status, control); - xpipe->xp_isoc_next += ival; + xpipe->xp_isoc_next = (xpipe->xp_isoc_next + ival) & mfmask; offs += len; } Index: sys/dev/usb/xhcivar.h =================================================================== RCS file: /cvsroot/src/sys/dev/usb/xhcivar.h,v retrieving revision 1.25 diff -p -u -r1.25 xhcivar.h --- sys/dev/usb/xhcivar.h 30 Jan 2025 00:42:47 -0000 1.25 +++ sys/dev/usb/xhcivar.h 2 Aug 2025 20:33:40 -0000 @@ -107,6 +107,7 @@ struct xhci_softc { int sc_maxslots; int sc_maxintrs; int sc_maxspbuf; + int sc_isthresh; /* value in frames */ /* * Port routing and root hub - xHCI 4.19.7