Skip to content

Commit

Permalink
ALSA: memalloc: Convert x86 SG-buffer handling with non-contiguous type
Browse files Browse the repository at this point in the history
We've had an x86-specific SG-buffer handling code, but now it can be
merged gracefully with the standard non-contiguous DMA pages.

After the migration, SNDRV_DMA_TYPE_DMA_SG becomes identical with
SNDRV_DMA_TYPE_NONCONTIG on x86, while others still fall back to
SNDRV_DMA_TYPE_DEV.

The remaining problem is about the SG-buffer with WC pages: the DMA
core stuff on x86 doesn't treat it well, so we still need some special
handling to manipulate the page attribute manually.  The mmap handler
for SNDRV_DMA_TYPE_DEV_SG_WC still returns -ENOENT intentionally for
the fallback to the default handler.

Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Takashi Iwai <[email protected]>
  • Loading branch information
tiwai committed Oct 18, 2021
1 parent 73325f6 commit 2d9ea39
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 213 deletions.
14 changes: 7 additions & 7 deletions include/sound/memalloc.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,6 @@ struct snd_dma_device {
#define SNDRV_DMA_TYPE_CONTINUOUS 1 /* continuous no-DMA memory */
#define SNDRV_DMA_TYPE_DEV 2 /* generic device continuous */
#define SNDRV_DMA_TYPE_DEV_WC 5 /* continuous write-combined */
#ifdef CONFIG_SND_DMA_SGBUF
#define SNDRV_DMA_TYPE_DEV_SG 3 /* generic device SG-buffer */
#define SNDRV_DMA_TYPE_DEV_WC_SG 6 /* SG write-combined */
#else
#define SNDRV_DMA_TYPE_DEV_SG SNDRV_DMA_TYPE_DEV /* no SG-buf support */
#define SNDRV_DMA_TYPE_DEV_WC_SG SNDRV_DMA_TYPE_DEV_WC
#endif
#ifdef CONFIG_GENERIC_ALLOCATOR
#define SNDRV_DMA_TYPE_DEV_IRAM 4 /* generic device iram-buffer */
#else
Expand All @@ -51,6 +44,13 @@ struct snd_dma_device {
#define SNDRV_DMA_TYPE_VMALLOC 7 /* vmalloc'ed buffer */
#define SNDRV_DMA_TYPE_NONCONTIG 8 /* non-coherent SG buffer */
#define SNDRV_DMA_TYPE_NONCOHERENT 9 /* non-coherent buffer */
#ifdef CONFIG_SND_DMA_SGBUF
#define SNDRV_DMA_TYPE_DEV_SG SNDRV_DMA_TYPE_NONCONTIG
#define SNDRV_DMA_TYPE_DEV_WC_SG 6 /* SG write-combined */
#else
#define SNDRV_DMA_TYPE_DEV_SG SNDRV_DMA_TYPE_DEV /* no SG-buf support */
#define SNDRV_DMA_TYPE_DEV_WC_SG SNDRV_DMA_TYPE_DEV_WC
#endif

/*
* info for buffer allocation
Expand Down
1 change: 0 additions & 1 deletion sound/core/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ snd-$(CONFIG_SND_JACK) += ctljack.o jack.o
snd-pcm-y := pcm.o pcm_native.o pcm_lib.o pcm_misc.o \
pcm_memory.o memalloc.o
snd-pcm-$(CONFIG_SND_PCM_TIMER) += pcm_timer.o
snd-pcm-$(CONFIG_SND_DMA_SGBUF) += sgbuf.o
snd-pcm-$(CONFIG_SND_PCM_ELD) += pcm_drm_eld.o
snd-pcm-$(CONFIG_SND_PCM_IEC958) += pcm_iec958.o

Expand Down
51 changes: 47 additions & 4 deletions sound/core/memalloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -560,6 +560,50 @@ static const struct snd_malloc_ops snd_dma_noncontig_ops = {
.get_chunk_size = snd_dma_vmalloc_get_chunk_size,
};

/* x86-specific SG-buffer with WC pages */
#ifdef CONFIG_SND_DMA_SGBUF
#define vmalloc_to_virt(v) (unsigned long)page_to_virt(vmalloc_to_page(v))

static void *snd_dma_sg_wc_alloc(struct snd_dma_buffer *dmab, size_t size)
{
void *p = snd_dma_noncontig_alloc(dmab, size);
size_t ofs;

if (!p)
return NULL;
for (ofs = 0; ofs < size; ofs += PAGE_SIZE)
set_memory_uc(vmalloc_to_virt(p + ofs), 1);
return p;
}

static void snd_dma_sg_wc_free(struct snd_dma_buffer *dmab)
{
size_t ofs;

for (ofs = 0; ofs < dmab->bytes; ofs += PAGE_SIZE)
set_memory_wb(vmalloc_to_virt(dmab->area + ofs), 1);
snd_dma_noncontig_free(dmab);
}

static int snd_dma_sg_wc_mmap(struct snd_dma_buffer *dmab,
struct vm_area_struct *area)
{
area->vm_page_prot = pgprot_writecombine(area->vm_page_prot);
/* FIXME: dma_mmap_noncontiguous() works? */
return -ENOENT; /* continue with the default mmap handler */
}

const struct snd_malloc_ops snd_dma_sg_wc_ops = {
.alloc = snd_dma_sg_wc_alloc,
.free = snd_dma_sg_wc_free,
.mmap = snd_dma_sg_wc_mmap,
.sync = snd_dma_noncontig_sync,
.get_addr = snd_dma_vmalloc_get_addr,
.get_page = snd_dma_vmalloc_get_page,
.get_chunk_size = snd_dma_vmalloc_get_chunk_size,
};
#endif /* CONFIG_SND_DMA_SGBUF */

/*
* Non-coherent pages allocator
*/
Expand Down Expand Up @@ -619,14 +663,13 @@ static const struct snd_malloc_ops *dma_ops[] = {
[SNDRV_DMA_TYPE_DEV_WC] = &snd_dma_wc_ops,
[SNDRV_DMA_TYPE_NONCONTIG] = &snd_dma_noncontig_ops,
[SNDRV_DMA_TYPE_NONCOHERENT] = &snd_dma_noncoherent_ops,
#ifdef CONFIG_SND_DMA_SGBUF
[SNDRV_DMA_TYPE_DEV_WC_SG] = &snd_dma_sg_wc_ops,
#endif
#ifdef CONFIG_GENERIC_ALLOCATOR
[SNDRV_DMA_TYPE_DEV_IRAM] = &snd_dma_iram_ops,
#endif /* CONFIG_GENERIC_ALLOCATOR */
#endif /* CONFIG_HAS_DMA */
#ifdef CONFIG_SND_DMA_SGBUF
[SNDRV_DMA_TYPE_DEV_SG] = &snd_dma_sg_ops,
[SNDRV_DMA_TYPE_DEV_WC_SG] = &snd_dma_sg_ops,
#endif
};

static const struct snd_malloc_ops *snd_dma_get_ops(struct snd_dma_buffer *dmab)
Expand Down
201 changes: 0 additions & 201 deletions sound/core/sgbuf.c

This file was deleted.

0 comments on commit 2d9ea39

Please sign in to comment.