powerpc/iommu: Support "hybrid" iommu/direct DMA ops for coherent_mask < dma_mask
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.
Signed-off-by Benjamin Herrenschmidt <[email protected]>
---
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
@@ -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
@@ -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
@@ -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
@@ -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