[alsa-devel] [PATCH 0/5] PCM mmap (temporary) fixes for non-coherent architectures
Hi,
this is a patchset to fix Oopses from ALSA PCM core with mmap on MIPS and PPC non-coherent architectures. This contains also a clean-up for ARM mmap.
In this patch series, I don't try to port dma_mmap_coherent() to these architectures yet, but just put ugly ifdefs in the ALSA core side. Understand that this is a first step forward to a more cleaner solution, and the purpose right now is just to fix up long-standing Oops. I'll try to push dma_mmap_coherent() patches for the next kernel once again after this gets merged.
Since the changes are minimal, I'd like to put them in ASAP for 2.6.33. Please review and give feedbacks if any problem is found.
Thanks,
Takashi
Use dma_mmap_coherent() for mmapping the buffers allocated via dma_alloc_coherent() if available. Currently, only ARM has this function, so we do temporarily have an ifdef pcm_native.c. This should be handled better globally in future.
Signed-off-by: Takashi Iwai tiwai@suse.de --- sound/core/pcm_native.c | 49 +++++++++++++++++++++++++++++++--------------- 1 files changed, 33 insertions(+), 16 deletions(-)
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index ab73edf..f067c5b 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -26,6 +26,7 @@ #include <linux/time.h> #include <linux/pm_qos_params.h> #include <linux/uio.h> +#include <linux/dma-mapping.h> #include <sound/core.h> #include <sound/control.h> #include <sound/info.h> @@ -3094,23 +3095,42 @@ static int snd_pcm_mmap_data_fault(struct vm_area_struct *area, return 0; }
-static const struct vm_operations_struct snd_pcm_vm_ops_data = -{ +static const struct vm_operations_struct snd_pcm_vm_ops_data = { + .open = snd_pcm_mmap_data_open, + .close = snd_pcm_mmap_data_close, +}; + +static const 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, };
+#ifndef ARCH_HAS_DMA_MMAP_COHERENT +/* This should be defined / handled globally! */ +#ifdef CONFIG_ARM +#define ARCH_HAS_DMA_MMAP_COHERENT +#endif +#endif + /* * mmap the DMA buffer on RAM */ 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); +#ifdef ARCH_HAS_DMA_MMAP_COHERENT + if (!substream->ops->page && + substream->dma_buffer.dev.type == 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 /* ARCH_HAS_DMA_MMAP_COHERENT */ + /* mmap with fault handler */ + area->vm_ops = &snd_pcm_vm_ops_data_fault; return 0; }
@@ -3118,12 +3138,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 const 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) { @@ -3133,8 +3147,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; @@ -3142,7 +3154,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; }
@@ -3159,6 +3170,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))) @@ -3183,10 +3195,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);
Add a helper (inline) function as the default page ops. Any hacks wrt the page address conversion will be applied in this function.
Signed-off-by: Takashi Iwai tiwai@suse.de --- sound/core/pcm_native.c | 20 ++++++++++++-------- 1 files changed, 12 insertions(+), 8 deletions(-)
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index f067c5b..c906be2 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -3062,6 +3062,13 @@ static int snd_pcm_mmap_control(struct snd_pcm_substream *substream, struct file } #endif /* coherent mmap */
+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); +} + /* * fault callback for mmapping a RAM page */ @@ -3072,7 +3079,6 @@ static int snd_pcm_mmap_data_fault(struct vm_area_struct *area, struct snd_pcm_runtime *runtime; unsigned long offset; struct page * page; - void *vaddr; size_t dma_bytes; if (substream == NULL) @@ -3082,14 +3088,12 @@ static int snd_pcm_mmap_data_fault(struct vm_area_struct *area, dma_bytes = PAGE_ALIGN(runtime->dma_bytes); if (offset > dma_bytes - PAGE_SIZE) return VM_FAULT_SIGBUS; - if (substream->ops->page) { + if (substream->ops->page) page = substream->ops->page(substream, offset); - if (!page) - return VM_FAULT_SIGBUS; - } else { - vaddr = runtime->dma_area + offset; - page = virt_to_page(vaddr); - } + else + page = snd_pcm_default_page_ops(substream, offset); + if (!page) + return VM_FAULT_SIGBUS; get_page(page); vmf->page = page; return 0;
The non-coherent MIPS arch doesn't give the correct address by a simple virt_to_page() for pages allocated via dma_alloc_coherent().
Original patch by Wu Zhangjin wuzj@lemote.com. A proper check of the buffer allocation type was added to avoid the wrong conversion.
Note that this doesn't fix perfectly: the pages should be marked with proper pgprot value. This will be done in a future implementation like the conversion to dma_mmap_coherent().
Signed-off-by: Takashi Iwai tiwai@suse.de --- sound/core/pcm_native.c | 4 ++++ 1 files changed, 4 insertions(+), 0 deletions(-)
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index c906be2..e48c5f6 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -3066,6 +3066,10 @@ static inline struct page * snd_pcm_default_page_ops(struct snd_pcm_substream *substream, unsigned long ofs) { void *vaddr = substream->runtime->dma_area + ofs; +#if defined(CONFIG_MIPS) && defined(CONFIG_DMA_NONCOHERENT) + if (substream->dma_buffer.dev.type == SNDRV_DMA_TYPE_DEV) + return virt_to_page(CAC_ADDR(vaddr)); +#endif return virt_to_page(vaddr); }
The non-cohernet PPC arch doesn't give the correct address by a simple virt_to_page() for pages allocated via dma_alloc_coherent(). This patch adds a hack to fix the conversion similarly like MIPS.
Note that this doesn't fix perfectly: the pages should be marked with proper pgprot value. This will be done in a future implementation like the conversion to dma_mmap_coherent().
Signed-off-by: Takashi Iwai tiwai@suse.de --- sound/core/pcm_native.c | 10 ++++++++++ 1 files changed, 10 insertions(+), 0 deletions(-)
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index e48c5f6..76eb763 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -3070,6 +3070,16 @@ snd_pcm_default_page_ops(struct snd_pcm_substream *substream, unsigned long ofs) if (substream->dma_buffer.dev.type == SNDRV_DMA_TYPE_DEV) return virt_to_page(CAC_ADDR(vaddr)); #endif +#if defined(CONFIG_PPC32) && defined(CONFIG_NOT_COHERENT_CACHE) + if (substream->dma_buffer.dev.type == SNDRV_DMA_TYPE_DEV) { + dma_addr_t addr = substream->runtime->dma_addr + ofs; + addr -= get_dma_offset(substream->dma_buffer.dev.dev); + /* assume dma_handle set via pfn_to_phys() in + * mm/dma-noncoherent.c + */ + return pfn_to_page(dma_handle >> PAGE_SHIFT); + } +#endif return virt_to_page(vaddr); }
The call of dma_mmap_coherent() is done in the PCM core now.
Signed-off-by: Takashi Iwai tiwai@suse.de --- sound/arm/Makefile | 2 +- sound/arm/aaci.c | 16 +++------- sound/arm/devdma.c | 80 ---------------------------------------------------- sound/arm/devdma.h | 3 -- 4 files changed, 6 insertions(+), 95 deletions(-) delete mode 100644 sound/arm/devdma.c delete mode 100644 sound/arm/devdma.h
diff --git a/sound/arm/Makefile b/sound/arm/Makefile index 5a549ed..8c0c851 100644 --- a/sound/arm/Makefile +++ b/sound/arm/Makefile @@ -3,7 +3,7 @@ #
obj-$(CONFIG_SND_ARMAACI) += snd-aaci.o -snd-aaci-objs := aaci.o devdma.o +snd-aaci-objs := aaci.o
obj-$(CONFIG_SND_PXA2XX_PCM) += snd-pxa2xx-pcm.o snd-pxa2xx-pcm-objs := pxa2xx-pcm.o diff --git a/sound/arm/aaci.c b/sound/arm/aaci.c index 1f0f821..e593728 100644 --- a/sound/arm/aaci.c +++ b/sound/arm/aaci.c @@ -30,7 +30,6 @@ #include <sound/pcm_params.h>
#include "aaci.h" -#include "devdma.h"
#define DRIVER_NAME "aaci-pl041"
@@ -492,7 +491,7 @@ static int aaci_pcm_hw_free(struct snd_pcm_substream *substream) /* * Clear out the DMA and any allocated buffers. */ - devdma_hw_free(NULL, substream); + snd_pcm_lib_free_pages(substream);
return 0; } @@ -505,8 +504,8 @@ static int aaci_pcm_hw_params(struct snd_pcm_substream *substream,
aaci_pcm_hw_free(substream);
- err = devdma_hw_alloc(NULL, substream, - params_buffer_bytes(params)); + err = snd_pcm_lib_malloc_pages(substream, + params_buffer_bytes(params)); if (err < 0) goto out;
@@ -551,11 +550,6 @@ static snd_pcm_uframes_t aaci_pcm_pointer(struct snd_pcm_substream *substream) return bytes_to_frames(runtime, bytes); }
-static int aaci_pcm_mmap(struct snd_pcm_substream *substream, struct vm_area_struct *vma) -{ - return devdma_mmap(NULL, substream, vma); -} -
/* * Playback specific ALSA stuff @@ -722,7 +716,6 @@ static struct snd_pcm_ops aaci_playback_ops = { .prepare = aaci_pcm_prepare, .trigger = aaci_pcm_playback_trigger, .pointer = aaci_pcm_pointer, - .mmap = aaci_pcm_mmap, };
static int aaci_pcm_capture_hw_params(struct snd_pcm_substream *substream, @@ -850,7 +843,6 @@ static struct snd_pcm_ops aaci_capture_ops = { .prepare = aaci_pcm_capture_prepare, .trigger = aaci_pcm_capture_trigger, .pointer = aaci_pcm_pointer, - .mmap = aaci_pcm_mmap, };
/* @@ -1040,6 +1032,8 @@ static int __devinit aaci_init_pcm(struct aaci *aaci)
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &aaci_playback_ops); snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &aaci_capture_ops); + snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, + NULL, 0, 64 * 104); }
return ret; diff --git a/sound/arm/devdma.c b/sound/arm/devdma.c deleted file mode 100644 index 9d1e666..0000000 --- a/sound/arm/devdma.c +++ /dev/null @@ -1,80 +0,0 @@ -/* - * linux/sound/arm/devdma.c - * - * Copyright (C) 2003-2004 Russell King, All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * ARM DMA shim for ALSA. - */ -#include <linux/device.h> -#include <linux/dma-mapping.h> - -#include <sound/core.h> -#include <sound/pcm.h> - -#include "devdma.h" - -void devdma_hw_free(struct device *dev, struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_dma_buffer *buf = runtime->dma_buffer_p; - - if (runtime->dma_area == NULL) - return; - - if (buf != &substream->dma_buffer) { - dma_free_coherent(buf->dev.dev, buf->bytes, buf->area, buf->addr); - kfree(runtime->dma_buffer_p); - } - - snd_pcm_set_runtime_buffer(substream, NULL); -} - -int devdma_hw_alloc(struct device *dev, struct snd_pcm_substream *substream, size_t size) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_dma_buffer *buf = runtime->dma_buffer_p; - int ret = 0; - - if (buf) { - if (buf->bytes >= size) - goto out; - devdma_hw_free(dev, substream); - } - - if (substream->dma_buffer.area != NULL && substream->dma_buffer.bytes >= size) { - buf = &substream->dma_buffer; - } else { - buf = kmalloc(sizeof(struct snd_dma_buffer), GFP_KERNEL); - if (!buf) - goto nomem; - - buf->dev.type = SNDRV_DMA_TYPE_DEV; - buf->dev.dev = dev; - buf->area = dma_alloc_coherent(dev, size, &buf->addr, GFP_KERNEL); - buf->bytes = size; - buf->private_data = NULL; - - if (!buf->area) - goto free; - } - snd_pcm_set_runtime_buffer(substream, buf); - ret = 1; - out: - runtime->dma_bytes = size; - return ret; - - free: - kfree(buf); - nomem: - return -ENOMEM; -} - -int devdma_mmap(struct device *dev, struct snd_pcm_substream *substream, struct vm_area_struct *vma) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - return dma_mmap_coherent(dev, vma, runtime->dma_area, runtime->dma_addr, runtime->dma_bytes); -} diff --git a/sound/arm/devdma.h b/sound/arm/devdma.h deleted file mode 100644 index d025329..0000000 --- a/sound/arm/devdma.h +++ /dev/null @@ -1,3 +0,0 @@ -void devdma_hw_free(struct device *dev, struct snd_pcm_substream *substream); -int devdma_hw_alloc(struct device *dev, struct snd_pcm_substream *substream, size_t size); -int devdma_mmap(struct device *dev, struct snd_pcm_substream *substream, struct vm_area_struct *vma);
Sorry, a typo was in this patch. The fixed version is below.
FYI, the patchset is found in sound git tree topic/pcm-dma-fix branch: git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6.git topic/pcm-dma-fix
thanks,
Takashi
From bc01f9e365d3afc041ab2c296107728c56410f8f Mon Sep 17 00:00:00 2001 From: Takashi Iwai tiwai@suse.de Date: Thu, 26 Nov 2009 15:04:24 +0100 Subject: [PATCH] ALSA: pcm - fix page conversion on non-coherent PPC arch
The non-cohernet PPC arch doesn't give the correct address by a simple virt_to_page() for pages allocated via dma_alloc_coherent(). This patch adds a hack to fix the conversion similarly like MIPS.
Note that this doesn't fix perfectly: the pages should be marked with proper pgprot value. This will be done in a future implementation like the conversion to dma_mmap_coherent().
Signed-off-by: Takashi Iwai tiwai@suse.de --- sound/core/pcm_native.c | 10 ++++++++++ 1 files changed, 10 insertions(+), 0 deletions(-)
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index e48c5f6..29ab46a 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -3070,6 +3070,16 @@ snd_pcm_default_page_ops(struct snd_pcm_substream *substream, unsigned long ofs) if (substream->dma_buffer.dev.type == SNDRV_DMA_TYPE_DEV) return virt_to_page(CAC_ADDR(vaddr)); #endif +#if defined(CONFIG_PPC32) && defined(CONFIG_NOT_COHERENT_CACHE) + if (substream->dma_buffer.dev.type == SNDRV_DMA_TYPE_DEV) { + dma_addr_t addr = substream->runtime->dma_addr + ofs; + addr -= get_dma_offset(substream->dma_buffer.dev.dev); + /* assume dma_handle set via pfn_to_phys() in + * mm/dma-noncoherent.c + */ + return pfn_to_page(addr >> PAGE_SHIFT); + } +#endif return virt_to_page(vaddr); }
On Thu, 2009-11-26 at 17:56 +0100, Takashi Iwai wrote:
Sorry, a typo was in this patch. The fixed version is below.
FYI, the patchset is found in sound git tree topic/pcm-dma-fix branch: git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6.git topic/pcm-dma-fix
Ah, I didn't notice the typo :-) Ack still.
Cheers, Ben.
thanks,
Takashi
From bc01f9e365d3afc041ab2c296107728c56410f8f Mon Sep 17 00:00:00 2001 From: Takashi Iwai tiwai@suse.de Date: Thu, 26 Nov 2009 15:04:24 +0100 Subject: [PATCH] ALSA: pcm - fix page conversion on non-coherent PPC arch
The non-cohernet PPC arch doesn't give the correct address by a simple virt_to_page() for pages allocated via dma_alloc_coherent(). This patch adds a hack to fix the conversion similarly like MIPS.
Note that this doesn't fix perfectly: the pages should be marked with proper pgprot value. This will be done in a future implementation like the conversion to dma_mmap_coherent().
Signed-off-by: Takashi Iwai tiwai@suse.de
sound/core/pcm_native.c | 10 ++++++++++ 1 files changed, 10 insertions(+), 0 deletions(-)
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index e48c5f6..29ab46a 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -3070,6 +3070,16 @@ snd_pcm_default_page_ops(struct snd_pcm_substream *substream, unsigned long ofs) if (substream->dma_buffer.dev.type == SNDRV_DMA_TYPE_DEV) return virt_to_page(CAC_ADDR(vaddr)); #endif +#if defined(CONFIG_PPC32) && defined(CONFIG_NOT_COHERENT_CACHE)
- if (substream->dma_buffer.dev.type == SNDRV_DMA_TYPE_DEV) {
dma_addr_t addr = substream->runtime->dma_addr + ofs;
addr -= get_dma_offset(substream->dma_buffer.dev.dev);
/* assume dma_handle set via pfn_to_phys() in
* mm/dma-noncoherent.c
*/
return pfn_to_page(addr >> PAGE_SHIFT);
- }
+#endif return virt_to_page(vaddr); }
On Thu, 2009-11-26 at 16:13 +0100, Takashi Iwai wrote:
The non-cohernet PPC arch doesn't give the correct address by a simple virt_to_page() for pages allocated via dma_alloc_coherent(). This patch adds a hack to fix the conversion similarly like MIPS.
Note that this doesn't fix perfectly: the pages should be marked with proper pgprot value. This will be done in a future implementation like the conversion to dma_mmap_coherent().
Signed-off-by: Takashi Iwai tiwai@suse.de
This will not work with swiotlb, but then, I don't think we have -yet- to deal with a platform that does both swiotlb and isn't DMA coherent :-)
Of course, the conversion to dma_mmap_coherent will makes things better though we really will want to push that function into the dma ops.
So it's hackish but for now its an
Acked-by: Benjamin Herrenschmidt benh@kernel.crashing.org
Cheers, Ben.
sound/core/pcm_native.c | 10 ++++++++++ 1 files changed, 10 insertions(+), 0 deletions(-)
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index e48c5f6..76eb763 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -3070,6 +3070,16 @@ snd_pcm_default_page_ops(struct snd_pcm_substream *substream, unsigned long ofs) if (substream->dma_buffer.dev.type == SNDRV_DMA_TYPE_DEV) return virt_to_page(CAC_ADDR(vaddr)); #endif +#if defined(CONFIG_PPC32) && defined(CONFIG_NOT_COHERENT_CACHE)
- if (substream->dma_buffer.dev.type == SNDRV_DMA_TYPE_DEV) {
dma_addr_t addr = substream->runtime->dma_addr + ofs;
addr -= get_dma_offset(substream->dma_buffer.dev.dev);
/* assume dma_handle set via pfn_to_phys() in
* mm/dma-noncoherent.c
*/
return pfn_to_page(dma_handle >> PAGE_SHIFT);
- }
+#endif return virt_to_page(vaddr); }
At Fri, 27 Nov 2009 07:51:44 +1100, Benjamin Herrenschmidt wrote:
On Thu, 2009-11-26 at 16:13 +0100, Takashi Iwai wrote:
The non-cohernet PPC arch doesn't give the correct address by a simple virt_to_page() for pages allocated via dma_alloc_coherent(). This patch adds a hack to fix the conversion similarly like MIPS.
Note that this doesn't fix perfectly: the pages should be marked with proper pgprot value. This will be done in a future implementation like the conversion to dma_mmap_coherent().
Signed-off-by: Takashi Iwai tiwai@suse.de
This will not work with swiotlb, but then, I don't think we have -yet- to deal with a platform that does both swiotlb and isn't DMA coherent :-)
Of course, the conversion to dma_mmap_coherent will makes things better though we really will want to push that function into the dma ops.
So it's hackish but for now its an
Acked-by: Benjamin Herrenschmidt benh@kernel.crashing.org
Thanks, I added your ack to the GIT commit.
Takashi
On Thu, 2009-11-26 at 16:13 +0100, Takashi Iwai wrote:
The non-coherent MIPS arch doesn't give the correct address by a simple virt_to_page() for pages allocated via dma_alloc_coherent().
Original patch by Wu Zhangjin wuzj@lemote.com. A proper check of the buffer allocation type was added to avoid the wrong conversion.
Note that this doesn't fix perfectly: the pages should be marked with proper pgprot value. This will be done in a future implementation like the conversion to dma_mmap_coherent().
Signed-off-by: Takashi Iwai tiwai@suse.de
sound/core/pcm_native.c | 4 ++++ 1 files changed, 4 insertions(+), 0 deletions(-)
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index c906be2..e48c5f6 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -3066,6 +3066,10 @@ static inline struct page * snd_pcm_default_page_ops(struct snd_pcm_substream *substream, unsigned long ofs) { void *vaddr = substream->runtime->dma_area + ofs; +#if defined(CONFIG_MIPS) && defined(CONFIG_DMA_NONCOHERENT)
- if (substream->dma_buffer.dev.type == SNDRV_DMA_TYPE_DEV)
return virt_to_page(CAC_ADDR(vaddr));
+#endif return virt_to_page(vaddr); }
Works well on Loongson family machines, thanks!
Regards, Wu Zhangjin
At Fri, 27 Nov 2009 11:52:58 +0800, Wu Zhangjin wrote:
On Thu, 2009-11-26 at 16:13 +0100, Takashi Iwai wrote:
The non-coherent MIPS arch doesn't give the correct address by a simple virt_to_page() for pages allocated via dma_alloc_coherent().
Original patch by Wu Zhangjin wuzj@lemote.com. A proper check of the buffer allocation type was added to avoid the wrong conversion.
Note that this doesn't fix perfectly: the pages should be marked with proper pgprot value. This will be done in a future implementation like the conversion to dma_mmap_coherent().
Signed-off-by: Takashi Iwai tiwai@suse.de
sound/core/pcm_native.c | 4 ++++ 1 files changed, 4 insertions(+), 0 deletions(-)
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index c906be2..e48c5f6 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -3066,6 +3066,10 @@ static inline struct page * snd_pcm_default_page_ops(struct snd_pcm_substream *substream, unsigned long ofs) { void *vaddr = substream->runtime->dma_area + ofs; +#if defined(CONFIG_MIPS) && defined(CONFIG_DMA_NONCOHERENT)
- if (substream->dma_buffer.dev.type == SNDRV_DMA_TYPE_DEV)
return virt_to_page(CAC_ADDR(vaddr));
+#endif return virt_to_page(vaddr); }
Works well on Loongson family machines, thanks!
Thanks for checking!
Takashi
On Thu, Nov 26, 2009 at 04:13:06PM +0100, Takashi Iwai wrote:
The non-coherent MIPS arch doesn't give the correct address by a simple virt_to_page() for pages allocated via dma_alloc_coherent().
Original patch by Wu Zhangjin wuzj@lemote.com. A proper check of the buffer allocation type was added to avoid the wrong conversion.
The origins of this patch go back far further. The oldest patch I could find which is a superset of this was written by Atsushi Nemoto and various incarnations of it have been sumitted to and reject by me a number of times through the years.
Note that this doesn't fix perfectly: the pages should be marked with proper pgprot value. This will be done in a future implementation like the conversion to dma_mmap_coherent().
Signed-off-by: Takashi Iwai tiwai@suse.de
So while this is ugly I don't think this patch will actually make the the situation worse for any MIPS platform. So with both eyes closed:
Acked-by: Ralf Baechle ralf@linux-mips.org
Ralf
At Fri, 27 Nov 2009 08:46:35 +0000, Ralf Baechle wrote:
On Thu, Nov 26, 2009 at 04:13:06PM +0100, Takashi Iwai wrote:
The non-coherent MIPS arch doesn't give the correct address by a simple virt_to_page() for pages allocated via dma_alloc_coherent().
Original patch by Wu Zhangjin wuzj@lemote.com. A proper check of the buffer allocation type was added to avoid the wrong conversion.
The origins of this patch go back far further. The oldest patch I could find which is a superset of this was written by Atsushi Nemoto and various incarnations of it have been sumitted to and reject by me a number of times through the years.
Note that this doesn't fix perfectly: the pages should be marked with proper pgprot value. This will be done in a future implementation like the conversion to dma_mmap_coherent().
Signed-off-by: Takashi Iwai tiwai@suse.de
So while this is ugly I don't think this patch will actually make the the situation worse for any MIPS platform. So with both eyes closed:
Acked-by: Ralf Baechle ralf@linux-mips.org
I added your ack with the comment about the origins to the GIT commit now.
Thanks for closing your eyes ;) Hopefully this hack can be removed again shortly...
Takashi
participants (4)
-
Benjamin Herrenschmidt
-
Ralf Baechle
-
Takashi Iwai
-
Wu Zhangjin