• Takashi Iwai's avatar
    ALSA: memalloc: Support for non-contiguous page allocation · a25684a9
    Takashi Iwai authored
    This patch adds the support for allocation of non-contiguous DMA pages
    in the common memalloc helper.  It's another SG-buffer type, but
    unlike the existing one, this is directional and requires the explicit
    sync / invalidation of dirty pages on non-coherent architectures.
    
    For this enhancement, the following points are changed:
    - snd_dma_device stores the DMA direction.
    - snd_dma_device stores need_sync flag indicating whether the explicit
      sync is required or not.
    - A new variant of helper functions, snd_dma_alloc_dir_pages() and
      *_all() are introduced; the old snd_dma_alloc_pages() and *_all()
      kept as just wrappers with DMA_BIDIRECTIONAL.
    - A new helper snd_dma_buffer_sync() is introduced; this gets called
      in the appropriate places.
    - A new allocation type, SNDRV_DMA_TYPE_NONCONTIG, is introduced.
    
    When the driver allocates pages with this new type, and it may require
    the SNDRV_PCM_INFO_EXPLICIT_SYNC flag set to the PCM hardware.info for
    taking the full control of PCM applptr and hwptr changes (that implies
    disabling the mmap of control/status data).  When the buffer
    allocation is managed by snd_pcm_set_managed_buffer(), this flag is
    automatically set depending on the result of dma_need_sync()
    internally.  Otherwise, if the buffer is managed manually, the driver
    has to set the flag explicitly, too.
    
    The explicit sync between CPU and device for non-coherent memory is
    performed at the points before and after read/write transfer as well
    as the applptr/hwptr syncptr ioctl.  In the case of mmap mode,
    user-space is supposed to call the syncptr ioctl with the hwptr flag
    to update and fetch the status at first; this corresponds to CPU-sync.
    Then user-space advances the applptr via syncptr ioctl again with
    applptr flag, and this corresponds to the device sync with flushing.
    
    Other than the DMA direction and the explicit sync, the usage of this
    new buffer type is almost equivalent with the existing
    SNDRV_DMA_TYPE_DEV_SG; you can get the page and the address via
    snd_sgbuf_get_page() and snd_sgbuf_get_addr(), also calculate the
    continuous pages via snd_sgbuf_get_chunk_size().
    
    For those SG-page handling, the non-contig type shares the same ops
    with the vmalloc handler.  As we do always vmap the SG pages at first,
    the actual address can be deduced from the vmapped address easily
    without iterating the SG-list.
    
    Link: https://lore.kernel.org/r/20211017074859.24112-2-tiwai@suse.deSigned-off-by: default avatarTakashi Iwai <tiwai@suse.de>
    a25684a9
pcm_native.c 112 KB