ALSA fixes for non-coherent ppc32 again
Takashi Iwai
tiwai at suse.de
Thu Jul 9 00:13:10 EST 2009
At Wed, 08 Jul 2009 13:01:50 +1000,
Benjamin Herrenschmidt wrote:
>
> On Mon, 2009-06-22 at 08:34 +1000, Benjamin Herrenschmidt wrote:
> > On Sun, 2009-06-21 at 20:18 +0200, Gerhard Pircher wrote:
> > > Hi,
> > >
> > > Takashi Iwai posted patches to make ALSA work on non-coherent PPC32
> > > systems (almost exactly) a year ago. See here:
> > > http://www.nabble.com/-PATCH-0-3--ALSA-fixes-for-non-coherent-ppc32-to17980027.html#a17980027
> > >
> > > As far as I can see these patches never went upstream. Where there any
> > > objections or did we just forget about them? It would be cool, if the
> > > patches could be merged now, as at least two platforms need this bugfix
> > > (namely Sam440 and AmigaOne).
> >
> > I definitely forgot about those... But I'm fine with what Takashi did
> > for now, I can always make the powerpc helper for dma_mmap_coherent()
> > smarter later on if necessary.
>
> BTW. Can you guys send a "final" patch for adding mmap_coherent to
> powerpc ? Please make so that the dma_mmap_coherent() function doesn't
> explose if dma_ops->mmap_coherent is NULL though (either fail gracefully
> or fallback to some standard mmap).
The attached is the revised patch. It falls backs to the standard
mmap.
The whole patch series are found in test/dma-fix branch of sound git
tree below:
git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6.git test/dma-fix
I had no time to play cross-build yet, so it'd be helpful if someone
can test it...
(BTW, any good minimal gcc and binutils package for kernel builds for
PPC32?)
> Note that we probably need to add the virtual address too. IE. On
> platforms with an iommu, we cannot easily go back from the dma_addr_t to
> the memory address, it's easier to do that from the virtual address in
> fact.
Yes, the virtual address is passed as well. Which parameter to be
used is just a matter of arch-specific implementation.
thanks,
Takashi
===
From a8cb7ed04595785d902d3ad20ba2fe5ccbe31690 Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai at suse.de>
Date: Wed, 8 Jul 2009 11:35:56 +0200
Subject: [PATCH] powerpc: implement dma_mmap_coherent()
A lazy version of dma_mmap_coherent() implementation for powerpc.
The standard mmap is used as a fallback.
Signed-off-by: Takashi Iwai <tiwai at suse.de>
---
arch/powerpc/include/asm/dma-mapping.h | 22 ++++++++++++++++++++++
arch/powerpc/kernel/dma.c | 21 +++++++++++++++++++++
2 files changed, 43 insertions(+), 0 deletions(-)
diff --git a/arch/powerpc/include/asm/dma-mapping.h b/arch/powerpc/include/asm/dma-mapping.h
index b44aaab..030a4b1 100644
--- a/arch/powerpc/include/asm/dma-mapping.h
+++ b/arch/powerpc/include/asm/dma-mapping.h
@@ -105,6 +105,10 @@ struct dma_mapping_ops {
struct scatterlist *sg, int nelems,
enum dma_data_direction direction);
#endif
+ int (*mmap_coherent)(struct device *hwdev,
+ struct vm_area_struct *vma,
+ void *cpu_addr, dma_addr_t dma_handle,
+ size_t size);
};
/*
@@ -415,6 +419,24 @@ static inline void dma_sync_single_range_for_device(struct device *dev,
}
#endif
+#define ARCH_HAS_DMA_MMAP_COHERENT
+static inline int dma_mmap_coherent(struct device *dev,
+ struct vm_area_struct *vma,
+ void *cpu_addr, dma_addr_t dma_handle,
+ size_t size)
+{
+ struct dma_mapping_ops *dma_ops = get_dma_ops(dev);
+
+ BUG_ON(!dma_ops);
+
+ if (dma_ops->mmap_coherent)
+ return dma_ops->mmap_coherent(dev, vma, cpu_addr, dma_handle,
+ size);
+ else
+ return dma_direct_ops.mmap_coherent(dev, vma, cpu_addr,
+ dma_handle, size);
+}
+
static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
{
#ifdef CONFIG_PPC64
diff --git a/arch/powerpc/kernel/dma.c b/arch/powerpc/kernel/dma.c
index 20a60d6..d11db99 100644
--- a/arch/powerpc/kernel/dma.c
+++ b/arch/powerpc/kernel/dma.c
@@ -140,6 +140,26 @@ static inline void dma_direct_sync_single_range(struct device *dev,
}
#endif
+static int dma_direct_mmap_coherent(struct device *dev,
+ struct vm_area_struct *vma,
+ void *cpu_addr, dma_addr_t dma_handle,
+ size_t size)
+{
+ unsigned long pfn;
+#ifdef CONFIG_NOT_COHERENT_CACHE
+ dma_handle -= get_dma_direct_offset(dev);
+ /* assume dma_handle set via pfn_to_phys() in
+ * mm/dma-noncoherent.c
+ */
+ pfn = dma_handle >> PAGE_SHIFT;
+#else
+ pfn = page_to_pfn(virt_to_page(cpu_addr));
+#endif
+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+ return remap_pfn_range(vma, vma->vm_start, pfn + vma->vm_pgoff,
+ size, vma->vm_page_prot);
+}
+
struct dma_mapping_ops dma_direct_ops = {
.alloc_coherent = dma_direct_alloc_coherent,
.free_coherent = dma_direct_free_coherent,
@@ -154,5 +174,6 @@ struct dma_mapping_ops dma_direct_ops = {
.sync_sg_for_cpu = dma_direct_sync_sg,
.sync_sg_for_device = dma_direct_sync_sg,
#endif
+ .mmap_coherent = dma_direct_mmap_coherent,
};
EXPORT_SYMBOL(dma_direct_ops);
--
1.6.3.2
More information about the Linuxppc-dev
mailing list