[PATCH 6/8] powerpc: implement dma_mmap_coherent()

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



A lazy version of dma_mmap_coherent() implementation for powerpc.
The standard mmap is used as a fallback.

Signed-off-by: Takashi Iwai <tiwai@xxxxxxx>
---
 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

--
To unsubscribe from this list: send the line "unsubscribe linux-arch" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Kernel]     [Kernel Newbies]     [x86 Platform Driver]     [Netdev]     [Linux Wireless]     [Netfilter]     [Bugtraq]     [Linux Filesystems]     [Yosemite Discussion]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Samba]     [Device Mapper]

  Powered by Linux