Each device is put into its own protection domain (if possible). For configuration with one or just a view masters per SMMU that is easy to achieve.
In case of many devices per SMMU (e.g. MMU-500 with it's distributed translation support) isolation of each device might not be possible -- depending on number of available SMR groups and/or context banks. Derive dma_base and size from (coherent_)dma_mask of device Signed-off-by: Andreas Herrmann <andreas.herrm...@calxeda.com> --- drivers/iommu/arm-smmu.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index 0dfd255..3eb2259 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -46,6 +46,7 @@ #include <linux/amba/bus.h> #include <asm/pgalloc.h> +#include <asm/dma-iommu.h> /* Maximum number of stream IDs assigned to a single device */ #define MAX_MASTER_STREAMIDS 8 @@ -1768,6 +1769,64 @@ static int arm_smmu_device_cfg_probe(struct arm_smmu_device *smmu) return 0; } +extern struct platform_device *of_find_device_by_node(struct device_node *np); + +static int arm_smmu_isolate_devices(void) +{ + struct dma_iommu_mapping *mapping; + struct arm_smmu_device *smmu; + struct rb_node *rbn; + struct arm_smmu_master *master; + struct platform_device *pdev; + struct device *dev; + void __iomem *gr0_base; + u32 cr0; + int ret = 0; + size_t size; + + list_for_each_entry(smmu, &arm_smmu_devices, list) { + rbn = rb_first(&smmu->masters); + while (rbn) { + master = container_of(rbn, struct arm_smmu_master, node); + pdev = of_find_device_by_node(master->of_node); + if (!pdev) + break; + dev = &pdev->dev; + + size = (size_t) dev->coherent_dma_mask; + size = size ? : (unsigned long) dev->dma_mask; + if (!size) { + dev_warn(dev, "(coherent_)dma_mask not set\n"); + continue; + } + + mapping = arm_iommu_create_mapping(&platform_bus_type, + 0, size, 0); + if (IS_ERR(mapping)) { + ret = PTR_ERR(mapping); + dev_info(dev, "arm_iommu_create_mapping failed\n"); + goto out; + } + + ret = arm_iommu_attach_device(dev, mapping); + if (ret < 0) { + dev_info(dev, "arm_iommu_attach_device failed\n"); + arm_iommu_release_mapping(mapping); + } + rbn = rb_next(rbn); + } + + gr0_base = ARM_SMMU_GR0(smmu); + cr0 = readl_relaxed(gr0_base + ARM_SMMU_GR0_sCR0); + cr0 |= sCR0_USFCFG; + writel(cr0, gr0_base + ARM_SMMU_GR0_sCR0); + } + +out: + return ret; +} + + static int arm_smmu_device_dt_probe(struct platform_device *pdev) { struct resource *res; -- 1.7.9.5 _______________________________________________ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu