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).
> 

Reply via email to