diff options
author | Marek Szyprowski <m.szyprowski@samsung.com> | 2015-05-19 15:20:44 +0200 |
---|---|---|
committer | Seung-Woo Kim <sw0312.kim@samsung.com> | 2016-12-14 13:45:13 +0900 |
commit | 82e325004dd397ff781c12266d2212f72c47089c (patch) | |
tree | d9331484e58c8b5029f42c6e7e09ef6b33192299 /arch | |
parent | 2b56dc6190e196b2e065e8e4a1044955d78bda03 (diff) | |
download | linux-exynos-82e325004dd397ff781c12266d2212f72c47089c.tar.gz linux-exynos-82e325004dd397ff781c12266d2212f72c47089c.tar.bz2 linux-exynos-82e325004dd397ff781c12266d2212f72c47089c.zip |
ARM: DMA-mapping: Update to v7: add support for creating reserved mappings in iova space
Update to v7 of Marek Szyprowski's Exynos SYSMMU (IOMMU) integration
with DT and DMA-mapping subsystem.
Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
Signed-off-by: Krzysztof Kozlowski <k.kozlowski@samsung.com>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/arm/mm/dma-mapping.c | 29 |
1 files changed, 23 insertions, 6 deletions
diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c index 55add24c3b4c..c36abc603712 100644 --- a/arch/arm/mm/dma-mapping.c +++ b/arch/arm/mm/dma-mapping.c @@ -2128,7 +2128,7 @@ static int arm_iommu_init_reserved(struct device *dev, { const char *name = "iommu-reserved-mapping"; const __be32 *prop = NULL; - int len, naddr, nsize; + int ret = 0, len, naddr, nsize, regions, cells; struct device_node *node = dev->of_node; phys_addr_t phys; dma_addr_t dma; @@ -2145,18 +2145,27 @@ static int arm_iommu_init_reserved(struct device *dev, return 0; len /= sizeof(u32); + cells = 2 * naddr + nsize; + regions = len / cells; - if (len < 2 * naddr + nsize) { + if (len % cells) { dev_err(dev, "invalid length (%d cells) of %s property\n", len, name); return -EINVAL; } - phys = of_read_number(prop, naddr); - dma = of_read_number(prop + naddr, naddr); - size = of_read_number(prop + 2*naddr, nsize); + while (regions--) { + phys = of_read_number(prop, naddr); + dma = of_read_number(prop + naddr, naddr); + size = of_read_number(prop + 2*naddr, nsize); + prop += cells; - return arm_iommu_add_reserved(dev, domain, phys, dma, size); + ret = arm_iommu_add_reserved(dev, domain, phys, dma, size); + if (ret) + break; + } + + return ret; } static struct dma_map_ops *arm_get_iommu_dma_map_ops(bool coherent) @@ -2187,6 +2196,14 @@ static bool arm_setup_iommu_dma_ops(struct device *dev, u64 dma_base, u64 size, return false; } + if (arm_iommu_init_reserved(dev, mapping) != 0) { + pr_warn("Failed to initialize reserved mapping for device %s\n", + dev_name(dev)); + __arm_iommu_detach_device(dev); + arm_iommu_release_mapping(mapping); + return false; + } + if (__arm_iommu_attach_device(dev, mapping)) { pr_warn("Failed to attached device %s to IOMMU_mapping\n", dev_name(dev)); |