Message ID | s5hfxd7qn49.wl%tiwai@suse.de (mailing list archive) |
---|---|
State | Changes Requested |
Delegated to: | Benjamin Herrenschmidt |
Headers | show |
-------- 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
=== 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);