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 <ti...@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 <ti...@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 _______________________________________________ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev