[Bug 257082] Sound with Scarlett Solo 3rd intermittently cuts off for very short periods of milliseconds.
Date: Sun, 11 Jul 2021 15:57:24 UTC
https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=257082 --- Comment #16 from Hodong <hodong@nimfsoft.com> --- (In reply to Hans Petter Selasky from comment #14) I applied your patch to FreeBSD-13 and I'm listening to music and still having the same problem. An error occurred in xhci.c when applying your patch, so I applied it manually. Perhaps only the line number is different. diff --git a/sys/dev/usb/controller/xhci.c b/sys/dev/usb/controller/xhci.c index 10e37c97c..690091fce 100644 --- a/sys/dev/usb/controller/xhci.c +++ b/sys/dev/usb/controller/xhci.c @@ -133,8 +133,8 @@ struct xhci_std_temp { uint32_t offset; uint32_t max_packet_size; uint32_t average; + uint32_t isoc_frame; uint16_t isoc_delta; - uint16_t isoc_frame; uint8_t shortpkt; uint8_t multishort; uint8_t last_frame; @@ -644,6 +644,9 @@ xhci_init(struct xhci_softc *sc, device_t self, uint8_t dma32) DPRINTF("HCS2=0x%08x\n", temp); + /* get isochronous scheduling threshold */ + sc->sc_ist = XHCI_HCS2_IST(temp); + /* get number of scratchpads */ sc->sc_noscratch = XHCI_HCS2_SPB_MAX(temp); @@ -2075,58 +2078,57 @@ xhci_setup_generic_chain(struct usb_xfer *xfer) x = XREAD4(temp.sc, runt, XHCI_MFINDEX); - DPRINTF("MFINDEX=0x%08x\n", x); + DPRINTF("MFINDEX=0x%08x IST=0x%x\n", x, temp.sc->sc_ist); switch (usbd_get_speed(xfer->xroot->udev)) { case USB_SPEED_FULL: shift = 3; temp.isoc_delta = 8; /* 1ms */ - x += temp.isoc_delta - 1; - x &= ~(temp.isoc_delta - 1); break; default: shift = usbd_xfer_get_fps_shift(xfer); temp.isoc_delta = 1U << shift; - x += temp.isoc_delta - 1; - x &= ~(temp.isoc_delta - 1); - /* simple frame load balancing */ - x += xfer->endpoint->usb_uframe; break; } - y = XHCI_MFINDEX_GET(x - xfer->endpoint->isoc_next); + /* Compute isochronous scheduling threshold. */ + if (temp.sc->sc_ist & 8) + y = (temp.sc->sc_ist & 7) << 3; + else + y = (temp.sc->sc_ist & 7); - if ((xfer->endpoint->is_synced == 0) || - (y < (xfer->nframes << shift)) || - (XHCI_MFINDEX_GET(-y) >= (128 * 8))) { + /* Range check the IST. */ + if (y < 8) { + y = 0; + } else if (y > 15) { + DPRINTFN(3, "IST(%d) is too big!\n", temp.sc->sc_ist); /* - * If there is data underflow or the pipe - * queue is empty we schedule the transfer a - * few frames ahead of the current frame - * position. Else two isochronous transfers - * might overlap. + * The USB stack minimum isochronous transfer + * size is typically 2x2 ms of payload. If the + * IST makes is above 15 microframes, we have + * an effective scheduling delay of more than + * or equal to 2 milliseconds, which is too + * much. */ - xfer->endpoint->isoc_next = XHCI_MFINDEX_GET(x + (3 * 8)); - xfer->endpoint->is_synced = 1; - temp.do_isoc_sync = 1; - - DPRINTFN(3, "start next=%d\n", xfer->endpoint->isoc_next); + } else { + /* + * Subtract one millisecond, because the + * generic code adds that to the latency. + */ + y -= 8; } - /* compute isochronous completion time */ - - y = XHCI_MFINDEX_GET(xfer->endpoint->isoc_next - (x & ~7)); + if (usbd_xfer_get_isochronous_start_frame( + xfer, x, y, 8, XHCI_MFINDEX_GET(-1), &temp.isoc_frame)) { + /* Start isochronous transfer at specified time. */ + temp.do_isoc_sync = 1; - xfer->isoc_time_complete = - usb_isoc_time_expand(&temp.sc->sc_bus, x / 8) + - (y / 8) + (((xfer->nframes << shift) + 7) / 8); + DPRINTFN(3, "start next=%d\n", temp.isoc_frame); + } x = 0; - temp.isoc_frame = xfer->endpoint->isoc_next; temp.trb_type = XHCI_TRB_TYPE_ISOCH; - xfer->endpoint->isoc_next += xfer->nframes << shift; - } else if (xfer->flags_int.control_xfr) { /* check if we should prepend a setup message */ @@ -3063,15 +3065,7 @@ xhci_device_done(struct usb_xfer *xfer, usb_error_t error) static void xhci_device_generic_open(struct usb_xfer *xfer) { - if (xfer->flags_int.isochronous_xfr) { - switch (xfer->xroot->udev->speed) { - case USB_SPEED_FULL: - break; - default: - usb_hs_bandwidth_alloc(xfer); - break; - } - } + DPRINTF("\n"); } static void @@ -3080,16 +3074,6 @@ xhci_device_generic_close(struct usb_xfer *xfer) DPRINTF("\n"); xhci_device_done(xfer, USB_ERR_CANCELLED); - - if (xfer->flags_int.isochronous_xfr) { - switch (xfer->xroot->udev->speed) { - case USB_SPEED_FULL: - break; - default: - usb_hs_bandwidth_free(xfer); - break; - } - } } static void ------------------------- Before installing the kernel, I gave the following commands: cd /boot git init git add . git commit -m initial So I can see that the kernel is properly installed. ----------------------------------------------- /boot % git status On branch master Changes not staged for commit: (use "git add/rm <file>..." to update what will be committed) (use "git restore <file>..." to discard changes in working directory) modified: entropy deleted: kernel.old/.freebsd-update modified: kernel/ehci.ko modified: kernel/kernel modified: kernel/ohci.ko modified: kernel/uhci.ko modified: kernel/usb.ko modified: kernel/xhci.ko Untracked files: (use "git add <file>..." to include in what will be committed) kernel.old/if_igb.ko kernel.old/if_ixlv.ko no changes added to commit (use "git add" and/or "git commit -a") ----------------------------------------------- The xhci.c of FreeBSD-13 and FreeBSD-14-CURRENT is different. So when I have time later, I'll install FreeBSD-14-CURRENT and listen to music with Scarlett Solo. Thank you so much. -- You are receiving this mail because: You are the assignee for the bug.