Skip to contentSkip to conversation

powerpc/iommu: Support "hybrid" iommu/direct DMA ops for coherent_mask < dma_mask

PATCH In review Benjamin Herrenschmidt 1 participant 1 message Jun 22, 2015 PowerPC

lore
Share & tools
lore
#0 lore raw

PATCH 3/3 powerpc/iommu: Support "hybrid" iommu/direct DMA ops for coherent_mask < dma_mask

This patch adds the ability to the DMA direct ops to fallback to the IOMMU ops for coherent alloc/free if the coherent mask of the device isn't suitable for accessing the direct DMA space and the device also happens to have an active IOMMU table.

---

v2: Implement a custom dma_set_coherent_mask() to work around the fact that dma_supported() will fail otherwise.

v3: Add missing symbol export

v4: Split and rebase

---
 arch/powerpc/Kconfig                   |   4 ++
 arch/powerpc/include/asm/dma-mapping.h |  10 +--
 arch/powerpc/kernel/dma-iommu.c        |   2 +-
 arch/powerpc/kernel/dma-swiotlb.c      |   4 +-
 arch/powerpc/kernel/dma.c              | 111 +++++++++++++++++++++++++++------
 5 files changed, 105 insertions(+), 26 deletions(-)
arch/powerpc/Kconfig +4 -0
index 22b0940..cd46474 100644
@@ -82,6 +82,9 @@ config GENERIC_HWEIGHT
 	bool
 	default y
 
+config ARCH_HAS_DMA_SET_COHERENT_MASK
+        bool
+
 config PPC
 	bool
 	default y
@@ -152,6 +155,7 @@ config PPC
 	select DCACHE_WORD_ACCESS if PPC64 && CPU_LITTLE_ENDIAN
 	select NO_BOOTMEM
 	select HAVE_GENERIC_RCU_GUP
+	select ARCH_HAS_DMA_SET_COHERENT_MASK
 
 config GENERIC_CSUM
 	def_bool CPU_LITTLE_ENDIAN
arch/powerpc/include/asm/dma-mapping.h +5 -5
index 35b9965..2e12366 100644
@@ -21,12 +21,12 @@
 #define DMA_ERROR_CODE		(~(dma_addr_t)0x0)
 
 /* Some dma direct funcs must be visible for use in other dma_ops */
-extern void *dma_direct_alloc_coherent(struct device *dev, size_t size,
-				       dma_addr_t *dma_handle, gfp_t flag,
+extern void *__dma_direct_alloc_coherent(struct device *dev, size_t size,
+					 dma_addr_t *dma_handle, gfp_t flag,
+					 struct dma_attrs *attrs);
+extern void __dma_direct_free_coherent(struct device *dev, size_t size,
+				       void *vaddr, dma_addr_t dma_handle,
 				       struct dma_attrs *attrs);
-extern void dma_direct_free_coherent(struct device *dev, size_t size,
-				     void *vaddr, dma_addr_t dma_handle,
-				     struct dma_attrs *attrs);
 extern int dma_direct_mmap_coherent(struct device *dev,
 				    struct vm_area_struct *vma,
 				    void *cpu_addr, dma_addr_t handle,
arch/powerpc/kernel/dma-iommu.c +1 -1
index 4c68bfe..41a7d9d 100644
@@ -73,7 +73,7 @@ static void dma_iommu_unmap_sg(struct device *dev, struct scatterlist *sglist,
 }
 
 /* We support DMA to/from any memory page via the iommu */
-static int dma_iommu_dma_supported(struct device *dev, u64 mask)
+int dma_iommu_dma_supported(struct device *dev, u64 mask)
 {
 	struct iommu_table *tbl = get_iommu_table_base(dev);
 
arch/powerpc/kernel/dma-swiotlb.c +2 -2
index 7359797..81b81cd 100644
@@ -47,8 +47,8 @@ static u64 swiotlb_powerpc_get_required(struct device *dev)
  * for everything else.
  */
 struct dma_map_ops swiotlb_dma_ops = {
-	.alloc = dma_direct_alloc_coherent,
-	.free = dma_direct_free_coherent,
+	.alloc = __dma_direct_alloc_coherent,
+	.free = __dma_direct_free_coherent,
 	.mmap = dma_direct_mmap_coherent,
 	.map_sg = swiotlb_map_sg_attrs,
 	.unmap_sg = swiotlb_unmap_sg_attrs,
arch/powerpc/kernel/dma.c +93 -18

147 lines not on this page · raw message