diff options
author | Richard Zhu <hongxing.zhu@nxp.com> | 2016-09-19 16:39:44 +0800 |
---|---|---|
committer | Jason Liu <jason.hui.liu@nxp.com> | 2019-02-12 10:26:57 +0800 |
commit | 9e7f775e8a800c966b945da5ae407888232ae051 (patch) | |
tree | 4824698462db1208ead257daffcbb80d002ebed6 /arch | |
parent | d5b25b71c142449af7f4d18acac68a32f0dd5268 (diff) |
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 <hongxing.zhu@nxp.com>
Reviewed-by: Frank Li <frank.li@nxp.com>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/arm64/mm/dma-mapping.c | 45 |
1 files changed, 43 insertions, 2 deletions
diff --git a/arch/arm64/mm/dma-mapping.c b/arch/arm64/mm/dma-mapping.c index 358aa8cb1cc0..7015d3ed55c7 100644 --- a/arch/arm64/mm/dma-mapping.c +++ b/arch/arm64/mm/dma-mapping.c @@ -29,6 +29,7 @@ #include <linux/vmalloc.h> #include <linux/swiotlb.h> #include <linux/pci.h> +#include <linux/of.h> #include <asm/cacheflush.h> @@ -373,7 +374,23 @@ static int __swiotlb_dma_mapping_error(struct device *hwdev, dma_addr_t addr) return 0; } -static const struct dma_map_ops swiotlb_dma_ops = { +/* + * Some 64bit SoCs only support up to 32bit dma capability. + * Do quirk set here. + */ +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 swiotlb_dma_ops = { .alloc = __dma_alloc, .free = __dma_free, .mmap = __swiotlb_mmap, @@ -857,7 +874,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, @@ -917,6 +934,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, @@ -928,6 +954,9 @@ static void __iommu_setup_dma_ops(struct device *dev, u64 dma_base, u64 size, 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 = &swiotlb_dma_ops; @@ -940,4 +969,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) { + swiotlb_dma_ops.dma_supported = __swiotlb_dma_supported_quirk; +#ifdef CONFIG_IOMMU_DMA + iommu_dma_ops.dma_supported = iommu_dma_supported_quirk; +#endif + } } |