Subject: Re: [RFC/PATCH] powerpc/iommu: Support "hybrid" iommu/direct DMA ops for coherent_mask < dma_mask

From: Brian King <[email-masked]>
Date: Thu, 14 May 2015 16:34:55 -0500

On 05/14/2015 02:43 AM, Benjamin Herrenschmidt wrote:
> 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-masked]>

Thanks Ben. This doesn't quite work, though, since pci_set_consistent_dma_mask
ends up calling dma_supported, which returns 0 here for a 32 bit mask if
pci_set_consistent_dma_mask was already called with a 64 bit mask. I worked
around it with the hack below and saw that I was able to get 64 bit DMA
and the card showed up all the drives. We'll need a better a better fix
for upstream obviously, but I wanted to be able to check out the rest of the patch
a bit...

Thanks,

Brian

-- 
Brian King
Power Linux I/O
IBM Linux Technology Center

Signed-off-by: Brian King <[email-masked]>
---

 arch/powerpc/kernel/dma.c |   12 +++++++++++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff -puN arch/powerpc/kernel/dma.c~powerpc_iommu_hybrid_fixup arch/powerpc/kernel/dma.c
--- linux/arch/powerpc/kernel/dma.c~powerpc_iommu_hybrid_fixup	2015-05-14 10:28:38.361416590 -0500
+++ linux-bjking1/arch/powerpc/kernel/dma.c	2015-05-14 10:54:39.367292683 -0500
@@ -62,6 +62,16 @@ static int dma_direct_dma_supported(stru
 #endif
 }
 
+static int dma_direct_is_dma_supported(struct device *dev, u64 mask)
+{
+	if (!dma_direct_dma_supported(dev, mask)) {
+		if (mask < 0xfffffff)
+			return 0;
+	}
+
+	return 1;
+}
+
 void *__dma_direct_alloc_coherent(struct device *dev, size_t size,
 				  dma_addr_t *dma_handle, gfp_t flag,
 				  struct dma_attrs *attrs)
@@ -273,7 +283,7 @@ struct dma_map_ops dma_direct_ops = {
 	.mmap				= dma_direct_mmap_coherent,
 	.map_sg				= dma_direct_map_sg,
 	.unmap_sg			= dma_direct_unmap_sg,
-	.dma_supported			= dma_direct_dma_supported,
+	.dma_supported			= dma_direct_is_dma_supported,
 	.map_page			= dma_direct_map_page,
 	.unmap_page			= dma_direct_unmap_page,
 	.get_required_mask		= dma_direct_get_required_mask,
_