diff mbox series

[1/2] ALSA: memalloc: Use DMA API for x86 WC page allocations, too

Message ID 20240801064808.31205-1-tiwai@suse.de (mailing list archive)
State New, archived
Headers show
Series [1/2] ALSA: memalloc: Use DMA API for x86 WC page allocations, too | expand

Commit Message

Takashi Iwai Aug. 1, 2024, 6:48 a.m. UTC
The memalloc helper used a house-made code for allocation of WC pages
on x86, since the standard DMA API doesn't cover it well.  Meanwhile,
the manually allocated pages won't work together with IOMMU, resulting
in faults, so we should switch to the DMA API in that case, instead.

This patch tries to switch back to DMA API for WC pages on x86, but
with some additional tweaks that are missing.

Link: https://bugzilla.kernel.org/show_bug.cgi?id=219087
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/core/memalloc.c | 35 +++++++++++++++++------------------
 1 file changed, 17 insertions(+), 18 deletions(-)
diff mbox series

Patch

diff --git a/sound/core/memalloc.c b/sound/core/memalloc.c
index f901504b5afc..428652fda926 100644
--- a/sound/core/memalloc.c
+++ b/sound/core/memalloc.c
@@ -492,40 +492,39 @@  static const struct snd_malloc_ops snd_dma_dev_ops = {
  */
 /* x86-specific allocations */
 #ifdef CONFIG_SND_DMA_SGBUF
-static void *snd_dma_wc_alloc(struct snd_dma_buffer *dmab, size_t size)
-{
-	return do_alloc_pages(dmab->dev.dev, size, &dmab->addr, true);
-}
-
-static void snd_dma_wc_free(struct snd_dma_buffer *dmab)
-{
-	do_free_pages(dmab->area, dmab->bytes, true);
-}
-
-static int snd_dma_wc_mmap(struct snd_dma_buffer *dmab,
-			   struct vm_area_struct *area)
-{
-	area->vm_page_prot = pgprot_writecombine(area->vm_page_prot);
-	return snd_dma_continuous_mmap(dmab, area);
-}
+#define x86_fallback(dmab)	(!get_dma_ops(dmab->dev.dev))
 #else
+#define x86_fallback(dmab)	false
+#endif
+
 static void *snd_dma_wc_alloc(struct snd_dma_buffer *dmab, size_t size)
 {
+	if (x86_fallback(dmab))
+		return do_alloc_pages(dmab->dev.dev, size, &dmab->addr, true);
 	return dma_alloc_wc(dmab->dev.dev, size, &dmab->addr, DEFAULT_GFP);
 }
 
 static void snd_dma_wc_free(struct snd_dma_buffer *dmab)
 {
+	if (x86_fallback(dmab)) {
+		do_free_pages(dmab->area, dmab->bytes, true);
+		return;
+	}
 	dma_free_wc(dmab->dev.dev, dmab->bytes, dmab->area, dmab->addr);
 }
 
 static int snd_dma_wc_mmap(struct snd_dma_buffer *dmab,
 			   struct vm_area_struct *area)
 {
+#ifdef CONFIG_SND_DMA_SGBUF
+	if (x86_fallback(dmab)) {
+		area->vm_page_prot = pgprot_writecombine(area->vm_page_prot);
+		return snd_dma_continuous_mmap(dmab, area);
+	}
+#endif
 	return dma_mmap_wc(dmab->dev.dev, area,
 			   dmab->area, dmab->addr, dmab->bytes);
 }
-#endif /* CONFIG_SND_DMA_SGBUF */
 
 static const struct snd_malloc_ops snd_dma_wc_ops = {
 	.alloc = snd_dma_wc_alloc,
@@ -548,7 +547,7 @@  static void *snd_dma_noncontig_alloc(struct snd_dma_buffer *dmab, size_t size)
 	sgt = dma_alloc_noncontiguous(dmab->dev.dev, size, dmab->dev.dir,
 				      DEFAULT_GFP, 0);
 #ifdef CONFIG_SND_DMA_SGBUF
-	if (!sgt && !get_dma_ops(dmab->dev.dev))
+	if (!sgt && x86_fallback(dmab))
 		return snd_dma_sg_fallback_alloc(dmab, size);
 #endif
 	if (!sgt)