At the moment just handle BUS_NOTIFY_BIND_DRIVER to conditionally isolate all master devices for an SMMU.
Depending on DT information each device is put into its own protection domain (if possible). For configuration with one or just a few 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. Default is that device isolation is contolled per SMMU with SMMU node property "arm,smmu-isolate-devices" in a DT. If this property is set for an SMMU node, device isolation is performed. W/o device isolation the driver detects SMMUs but no translation is configured (transactions just bypass translation process). Note that for device isolation dma_base and size are fixed as 0 and SZ_128M at the moment. Signed-off-by: Andreas Herrmann <andreas.herrm...@calxeda.com> --- drivers/iommu/arm-smmu.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index 0ad204e..3ba17ac 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> /* Driver options */ #define ARM_SMMU_OPT_ISOLATE_DEVICES (1 << 0) @@ -1976,6 +1977,48 @@ static int arm_smmu_device_remove(struct platform_device *pdev) return 0; } +static int arm_smmu_device_notifier(struct notifier_block *nb, + unsigned long action, void *data) +{ + struct device *dev = data; + struct dma_iommu_mapping *mapping; + struct arm_smmu_device *smmu; + int ret; + + switch (action) { + case BUS_NOTIFY_BIND_DRIVER: + + arm_smmu_add_device(dev); + smmu = dev->archdata.iommu; + if (!smmu || !(smmu->options & ARM_SMMU_OPT_ISOLATE_DEVICES)) + break; + + mapping = arm_iommu_create_mapping(&platform_bus_type, + 0, SZ_128M, 0); + if (IS_ERR(mapping)) { + ret = PTR_ERR(mapping); + dev_info(dev, "arm_iommu_create_mapping failed\n"); + break; + } + + ret = arm_iommu_attach_device(dev, mapping); + if (ret < 0) { + dev_info(dev, "arm_iommu_attach_device failed\n"); + arm_iommu_release_mapping(mapping); + } + + break; + default: + break; + } + + return 0; +} + +static struct notifier_block device_nb = { + .notifier_call = arm_smmu_device_notifier, +}; + #ifdef CONFIG_OF static struct of_device_id arm_smmu_of_match[] = { { .compatible = "arm,smmu-v1", }, @@ -2012,6 +2055,8 @@ static int __init arm_smmu_init(void) if (!iommu_present(&amba_bustype)) bus_set_iommu(&amba_bustype, &arm_smmu_ops); + bus_register_notifier(&platform_bus_type, &device_nb); + return 0; } -- 1.7.9.5 _______________________________________________ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu