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