arm_smmu_master_install_s2crs(struct arm_smmu_master_cfg *cfg, } } -static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev, - struct iommu_domain *old) +static int arm_smmu_test_dev(struct iommu_domain *domain, struct device *dev, + ioasid_t pasid, struct iommu_domain *old) { - struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain); - struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev); - struct arm_smmu_master_cfg *cfg; - struct arm_smmu_device *smmu; - int ret; + struct arm_smmu_master_cfg *cfg = dev_iommu_priv_get(dev); + struct arm_smmu_domain *smmu_domain; /* * FIXME: The arch/arm DMA API code tries to attach devices to its own @@ -1181,11 +1186,40 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev, * domains, just say no (but more politely than by dereferencing NULL). * This should be at least a WARN_ON once that's sorted. */ - cfg = dev_iommu_priv_get(dev); if (!cfg) return -ENODEV; - smmu = cfg->smmu; + if (domain == arm_smmu_ops.identity_domain || + domain == arm_smmu_ops.blocked_domain) + return 0; + + smmu_domain = to_smmu_domain(domain); + scoped_guard(mutex, &smmu_domain->init_mutex) { + /* arm_smmu_init_domain_context() will initialize it */ + if (!smmu_domain->smmu) + return 0; + /* + * Sanity check the domain. We don't support domains across + * different SMMUs. + */ + if (smmu_domain->smmu != cfg->smmu) + return -EINVAL; + if (arm_smmu_get_context_fmt(smmu_domain) == + ARM_SMMU_CTX_FMT_NONE) + return -EINVAL; + } + + return 0; +} + +static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev, + struct iommu_domain *old) +{ + struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain); + struct arm_smmu_master_cfg *cfg = dev_iommu_priv_get(dev); + struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev); + struct arm_smmu_device *smmu = cfg->smmu; + int ret; ret = arm_smmu_rpm_get(smmu); if (ret < 0) @@ -1196,15 +1230,6 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev, if (ret < 0) goto rpm_put; - /* - * Sanity check the domain. We don't support domains across - * different SMMUs. - */ - if (smmu_domain->smmu != smmu) { - ret = -EINVAL; - goto rpm_put; - } - /* Looks ok, so add the device to the domain */ arm_smmu_master_install_s2crs(cfg, S2CR_TYPE_TRANS, smmu_domain->cfg.cbndx, fwspec); @@ -1221,8 +1246,6 @@ static int arm_smmu_attach_dev_type(struct device *dev, struct arm_smmu_device *smmu; int ret; - if (!cfg) - return -ENODEV; smmu = cfg->smmu; ret = arm_smmu_rpm_get(smmu); @@ -1242,6 +1265,7 @@ static int arm_smmu_attach_dev_identity(struct iommu_domain *domain, } static const struct iommu_domain_ops arm_smmu_identity_ops = { + .test_dev = arm_smmu_test_dev, .attach_dev = arm_smmu_attach_dev_identity, }; @@ -1258,6 +1282,7 @@ static int arm_smmu_attach_dev_blocked(struct iommu_domain *domain, } static const struct iommu_domain_ops arm_smmu_blocked_ops = { + .test_dev = arm_smmu_test_dev, .attach_dev = arm_smmu_attach_dev_blocked, }; @@ -1647,6 +1672,7 @@ static const struct iommu_ops arm_smmu_ops = { .def_domain_type = arm_smmu_def_domain_type, .owner = THIS_MODULE, .default_domain_ops = &(const struct iommu_domain_ops) { + .test_dev = arm_smmu_test_dev, .attach_dev = arm_smmu_attach_dev, .map_pages = arm_smmu_map_pages, .unmap_pages = arm_smmu_unmap_pages, -- 2.43.0[PATCH v1 06/20] iommu/arm-smmu: Implement arm_smmu_test_devNicolin Chen undefined, , undefined undefined undefined undefined undefined undefined undefined undefined undefined undefined undefined undefined undefined undefined undefined undefined undefined undefined undefined undefined undefined undefined undefined undefined undefined undefined undefined undefined undefined undefined undefined undefined undefined undefined undefined undefined undefined undefined undefined undefined