summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorMarek Szyprowski <m.szyprowski@samsung.com>2015-05-19 15:20:44 +0200
committerSeung-Woo Kim <sw0312.kim@samsung.com>2016-12-14 13:45:13 +0900
commit82e325004dd397ff781c12266d2212f72c47089c (patch)
treed9331484e58c8b5029f42c6e7e09ef6b33192299 /arch
parent2b56dc6190e196b2e065e8e4a1044955d78bda03 (diff)
downloadlinux-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.c29
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));