[PATCH 2/3] ALSA: Fix mapping of DMA buffers
From: Takashi Iwai <hidden>
Date: 2008-06-18 10:41:50
Subsystem:
sound, the rest · Maintainers:
Jaroslav Kysela, Takashi Iwai, Linus Torvalds
The DMA buffers allocated via dma_alloc_coherent() aren't easily mmappable for many architectures. This is a quick fix for some known archs that don't work properly with the current code. Signed-off-by: Takashi Iwai <redacted> --- sound/core/Kconfig | 7 +++++++ sound/core/pcm_native.c | 42 ++++++++++++++++++++++++++++-------------- 2 files changed, 35 insertions(+), 14 deletions(-)
diff --git a/sound/core/Kconfig b/sound/core/Kconfig
index 335d45e..8e4e644 100644
--- a/sound/core/Kconfig
+++ b/sound/core/Kconfig@@ -174,3 +174,10 @@ config SND_PCM_XRUN_DEBUG config SND_VMASTER bool + +config SND_COHERENT_DMA + def_bool y + depends on !PPC32 || !NOT_COHERENT_CACHE + depends on !ARM + depends on !MIPS + depends on !PARISC
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index 61f5d42..e21ad2f 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c@@ -3124,6 +3124,12 @@ static struct vm_operations_struct snd_pcm_vm_ops_data = { .open = snd_pcm_mmap_data_open, .close = snd_pcm_mmap_data_close, +}; + +static struct vm_operations_struct snd_pcm_vm_ops_data_fault = +{ + .open = snd_pcm_mmap_data_open, + .close = snd_pcm_mmap_data_close, .fault = snd_pcm_mmap_data_fault, };
@@ -3133,10 +3139,21 @@ static struct vm_operations_struct snd_pcm_vm_ops_data = static int snd_pcm_default_mmap(struct snd_pcm_substream *substream, struct vm_area_struct *area) { - area->vm_ops = &snd_pcm_vm_ops_data; - area->vm_private_data = substream; area->vm_flags |= VM_RESERVED; - atomic_inc(&substream->mmap_count); +#ifndef CONFIG_SND_COHERENT_DMA + if (!substream->ops->page) { + switch (substream->dma_buffer.dev.type) { + case SNDRV_DMA_TYPE_DEV: + return dma_mmap_coherent(substream->dma_buffer.dev.dev, + area, + substream->runtime->dma_area, + substream->runtime->dma_addr, + area->vm_end - area->vm_start); + } + } +#endif /* !CONFIG_SND_COHERNT_DMA */ + /* mmap with fault handler */ + area->vm_ops = &snd_pcm_vm_ops_data_fault; return 0; }
@@ -3144,12 +3161,6 @@ static int snd_pcm_default_mmap(struct snd_pcm_substream *substream, * mmap the DMA buffer on I/O memory area */ #if SNDRV_PCM_INFO_MMAP_IOMEM -static struct vm_operations_struct snd_pcm_vm_ops_data_mmio = -{ - .open = snd_pcm_mmap_data_open, - .close = snd_pcm_mmap_data_close, -}; - int snd_pcm_lib_mmap_iomem(struct snd_pcm_substream *substream, struct vm_area_struct *area) {
@@ -3159,8 +3170,6 @@ int snd_pcm_lib_mmap_iomem(struct snd_pcm_substream *substream, #ifdef pgprot_noncached area->vm_page_prot = pgprot_noncached(area->vm_page_prot); #endif - area->vm_ops = &snd_pcm_vm_ops_data_mmio; - area->vm_private_data = substream; area->vm_flags |= VM_IO; size = area->vm_end - area->vm_start; offset = area->vm_pgoff << PAGE_SHIFT;
@@ -3168,7 +3177,6 @@ int snd_pcm_lib_mmap_iomem(struct snd_pcm_substream *substream, (substream->runtime->dma_addr + offset) >> PAGE_SHIFT, size, area->vm_page_prot)) return -EAGAIN; - atomic_inc(&substream->mmap_count); return 0; }
@@ -3185,6 +3193,7 @@ int snd_pcm_mmap_data(struct snd_pcm_substream *substream, struct file *file, long size; unsigned long offset; size_t dma_bytes; + int err; if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { if (!(area->vm_flags & (VM_WRITE|VM_READ)))
@@ -3210,10 +3219,15 @@ int snd_pcm_mmap_data(struct snd_pcm_substream *substream, struct file *file, if (offset > dma_bytes - size) return -EINVAL; + area->vm_ops = &snd_pcm_vm_ops_data; + area->vm_private_data = substream; if (substream->ops->mmap) - return substream->ops->mmap(substream, area); + err = substream->ops->mmap(substream, area); else - return snd_pcm_default_mmap(substream, area); + err = snd_pcm_default_mmap(substream, area); + if (!err) + atomic_inc(&substream->mmap_count); + return err; } EXPORT_SYMBOL(snd_pcm_mmap_data);
--
1.5.4.5