ALSA: pcm: Handle special page mapping in the default mmap handler
authorTakashi Iwai <tiwai@suse.de>
Tue, 5 Nov 2019 08:01:37 +0000 (09:01 +0100)
committerTakashi Iwai <tiwai@suse.de>
Wed, 6 Nov 2019 14:43:33 +0000 (15:43 +0100)
When a driver needs to deal with a special buffer like a SG or a
vmalloc buffer, it has to set up the PCM page ops explicitly for the
corresponding helper function.  This is rather error-prone and many
people forgot or incorrectly used it.

For simplifying the call patterns and avoiding such a potential bug,
this patch enhances the PCM default mmap handler to check the
(pre-)allocated buffer type and handles the page gracefully depending
on the buffer type.  If the PCM page ops is given, the ops is still
used in a higher priority.  The new code path is only for the default
(NULL page ops) case.

Link: https://lore.kernel.org/r/20191105080138.1260-4-tiwai@suse.de
Signed-off-by: Takashi Iwai <tiwai@suse.de>
sound/core/pcm_native.c

index c3a139436ac269ada2402cbeec9552339b0e2633..998c63192ae4b8b906987c04574518e298abd02d 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/pm_qos.h>
 #include <linux/io.h>
 #include <linux/dma-mapping.h>
+#include <linux/vmalloc.h>
 #include <sound/core.h>
 #include <sound/control.h>
 #include <sound/info.h>
@@ -3335,7 +3336,18 @@ static inline struct page *
 snd_pcm_default_page_ops(struct snd_pcm_substream *substream, unsigned long ofs)
 {
        void *vaddr = substream->runtime->dma_area + ofs;
-       return virt_to_page(vaddr);
+
+       switch (substream->dma_buffer.dev.type) {
+#ifdef CONFIG_SND_DMA_SGBUF
+       case SNDRV_DMA_TYPE_DEV_SG:
+       case SNDRV_DMA_TYPE_DEV_UC_SG:
+               return snd_pcm_sgbuf_ops_page(substream, ofs);
+#endif /* CONFIG_SND_DMA_SGBUF */
+       case SNDRV_DMA_TYPE_VMALLOC:
+               return vmalloc_to_page(vaddr);
+       default:
+               return virt_to_page(vaddr);
+       }
 }
 
 /*