diff options
author | Takashi Iwai <tiwai@suse.de> | 2019-11-05 09:01:37 +0100 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2019-11-06 15:43:33 +0100 |
commit | 7e8edae39fd1f880f098612c991cf6d0f646c20d (patch) | |
tree | fce448380f7e5f00ee63a87614612e6bbc8b9899 /sound/core/pcm_native.c | |
parent | 1fe7f397cfe229494a88c6496b53ba532d4d4a42 (diff) | |
download | linux-7e8edae39fd1f880f098612c991cf6d0f646c20d.tar.bz2 |
ALSA: pcm: Handle special page mapping in the default mmap handler
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>
Diffstat (limited to 'sound/core/pcm_native.c')
-rw-r--r-- | sound/core/pcm_native.c | 14 |
1 files changed, 13 insertions, 1 deletions
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index c3a139436ac2..998c63192ae4 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -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); + } } /* |