From: Richard Zhu Date: Tue, 14 May 2019 08:28:15 +0000 (+0800) Subject: MLK-15064-2 ARM64: DMA: limit the dma mask to be 32bit X-Git-Tag: rel_imx_4.19.35_1.1.0~523 X-Git-Url: https://git.somdevices.com/?a=commitdiff_plain;h=1953b8289b51b1ebc42e8511a6b7b12de7142c1e;p=linux.git MLK-15064-2 ARM64: DMA: limit the dma mask to be 32bit 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 Reviewed-by: Frank Li --- diff --git a/arch/arm64/mm/dma-mapping.c b/arch/arm64/mm/dma-mapping.c index c389f2bef938..9f0452ad2029 100644 --- a/arch/arm64/mm/dma-mapping.c +++ b/arch/arm64/mm/dma-mapping.c @@ -29,6 +29,7 @@ #include #include #include +#include #include @@ -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 + } }