Am Tue, May 18, 2021 at 07:42:07AM +0200 schrieb Alexandre Ratchov: > On Mon, May 17, 2021 at 10:19:59PM +0200, Patrick Wildt wrote: > > The thing though is that I thought xhci(4) was already calling syncmem > > on that buffer. I mean, it's happening in xhci_device_isoc_start(), > > isn't it? It's doing > > > > usb_syncmem(&xfer->dmabuf, 0, xfer->length, > > usbd_xfer_isread(xfer) ? > > BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE); > > > > and unless the usbd_xfer_isread() is wrong, it should be passing > > PREWRITE as well. > > > > AFAICS, the usb_syncmem() call in xhci_device_isoc_start() is > correct. The problem is that it's called too early, before the data to > transfer is stored to memory. > > Indeed, xhci_device_isoc_start() doesn't start the transfer, it just > queues xfer's frames descriptors on the HC ring; each descriptor is a > pointer to 1 ms of audio data that's initialiy zero-filled by > uaudio(4). The HC sends on the wire a single frame every millisecond > from its ring. After frames are queued, userland can start filling the > data pointed by the frame descriptors, so that when the HC dequeues > them, the data is ready. If userland misses the deadline (fills the > memory after frame is sent), the HC sends the initial frame content > (zeros, i.e. silencs), playback "stutters". > > This is equivalent to how PCI audio hardware works.
Ah, I see, that makes sense. > > Unless xfer->length is different than xfer->size? But then the whole > > isoc code in xhci(4) would be wrong, since it relies on xfer->length. > > > > Oh, maybe that's it. The isoc code mostly works on xfer->frlengths[], > > and maybe xfer->length is not what we need to use there. > > > > Maybe we need to sync each individual frame with the corresponding > > frlength? > > The easier is to sync just after userland stops touching the memory > block; FWIW, a block contains multiple frames (10 with default sndiod > settings). >