Patchwork ALSA fixes for non-coherent ppc32 again

login
register
mail settings
Submitter Takashi Iwai
Date July 8, 2009, 2:13 p.m.
Message ID <s5hfxd7qn49.wl%tiwai@suse.de>
Download mbox | patch
Permalink /patch/29595/
State Changes Requested
Delegated to: Benjamin Herrenschmidt
Headers show

Comments

Takashi Iwai - July 8, 2009, 2:13 p.m.
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
Gerhard Pircher - July 9, 2009, 11:22 a.m.
-------- Original-Nachricht --------
> Datum: Wed, 08 Jul 2009 16:13:10 +0200
> Von: Takashi Iwai <tiwai@suse.de>
> An: Benjamin Herrenschmidt <benh@kernel.crashing.org>
> CC: Gerhard Pircher <gerhard_pircher@gmx.net>, linuxppc-dev@ozlabs.org
> Betreff: Re: ALSA fixes for non-coherent ppc32 again

> 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?)
Okay, I cross-build it on a x86 machine and tested it on my AmigaOne with
the VIA686 onboard sound and a Soundblaster 5.1. It worked fine after I
applied the "ALSA: Fix SG-buffer DMA with non-coherent architectures"
patch.

Thanks!

Gerhard

Patch

===
From a8cb7ed04595785d902d3ad20ba2fe5ccbe31690 Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@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@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);