MLK-15064-2 ARM64: DMA: limit the dma mask to be 32bit
authorRichard Zhu <hongxing.zhu@nxp.com>
Tue, 14 May 2019 08:28:15 +0000 (16:28 +0800)
committerRichard Zhu <hongxing.zhu@nxp.com>
Wed, 15 May 2019 06:17:11 +0000 (14:17 +0800)
Limit the dma mask to be 32bit, because that
the imx8 doesn't have the 64bit dma capapbility
although it is 64bit soc.

Signed-off-by: Richard Zhu <hongxing.zhu@nxp.com>
Reviewed-by: Frank Li <frank.li@nxp.com>
arch/arm64/mm/dma-mapping.c

index c389f2b..9f0452a 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/vmalloc.h>
 #include <linux/swiotlb.h>
 #include <linux/pci.h>
+#include <linux/of.h>
 
 #include <asm/cacheflush.h>
 
@@ -328,7 +329,19 @@ static int __swiotlb_dma_mapping_error(struct device *hwdev, dma_addr_t addr)
        return 0;
 }
 
-static const struct dma_map_ops arm64_swiotlb_dma_ops = {
+static int __swiotlb_dma_supported_quirk(struct device *hwdev, u64 mask)
+{
+       if (mask > DMA_BIT_MASK(32)) {
+               pr_err("Can't support > 32 bit dma.\n");
+               return 0;
+       }
+
+       if (swiotlb)
+               return swiotlb_dma_supported(hwdev, mask);
+       return 1;
+}
+
+static struct dma_map_ops arm64_swiotlb_dma_ops = {
        .alloc = __dma_alloc,
        .free = __dma_free,
        .mmap = __swiotlb_mmap,
@@ -807,7 +820,7 @@ static void __iommu_unmap_sg_attrs(struct device *dev,
        iommu_dma_unmap_sg(dev, sgl, nelems, dir, attrs);
 }
 
-static const struct dma_map_ops iommu_dma_ops = {
+static struct dma_map_ops iommu_dma_ops = {
        .alloc = __iommu_alloc_attrs,
        .free = __iommu_free_attrs,
        .mmap = __iommu_mmap_attrs,
@@ -867,6 +880,15 @@ void arch_teardown_dma_ops(struct device *dev)
        dev->dma_ops = NULL;
 }
 
+static int iommu_dma_supported_quirk(struct device *dev, u64 mask)
+{
+       if (mask > DMA_BIT_MASK(32)) {
+               pr_err("Can't support > 32 bit dma.\n");
+               return 0;
+       }
+
+       return 1;
+}
 #else
 
 static void __iommu_setup_dma_ops(struct device *dev, u64 dma_base, u64 size,
@@ -875,9 +897,16 @@ static void __iommu_setup_dma_ops(struct device *dev, u64 dma_base, u64 size,
 
 #endif  /* CONFIG_IOMMU_DMA */
 
+/*
+ * Some 64bit SoCs only support up to 32bit dma capability.
+ * Do quirk set here.
+ */
 void arch_setup_dma_ops(struct device *dev, u64 dma_base, u64 size,
                        const struct iommu_ops *iommu, bool coherent)
 {
+       u32 mask32;
+       struct device_node *np;
+
        if (!dev->dma_ops)
                dev->dma_ops = &arm64_swiotlb_dma_ops;
 
@@ -890,4 +919,16 @@ void arch_setup_dma_ops(struct device *dev, u64 dma_base, u64 size,
                dev->dma_ops = xen_dma_ops;
        }
 #endif
+
+       np = of_find_compatible_node(NULL, NULL, "dma-capability");
+       if (np == NULL)
+               return;
+       if (of_property_read_u32(np, "only-dma-mask32", &mask32))
+               mask32 = 0;
+       if (mask32) {
+               arm64_swiotlb_dma_ops.dma_supported = __swiotlb_dma_supported_quirk;
+#ifdef CONFIG_IOMMU_DMA
+               iommu_dma_ops.dma_supported = iommu_dma_supported_quirk;
+#endif
+       }
 }