Move sanity and compatibility tests from the attach_dev callbacks to the new test_dev callback functions. The IOMMU core makes sure an attach_dev call must be invoked after a successful test_dev call.
Following the test_dev guideline, replace dev_err with dev_dbg. Signed-off-by: Nicolin Chen <[email protected]> --- drivers/iommu/arm/arm-smmu/qcom_iommu.c | 46 ++++++++++++++++++------- 1 file changed, 34 insertions(+), 12 deletions(-) diff --git a/drivers/iommu/arm/arm-smmu/qcom_iommu.c b/drivers/iommu/arm/arm-smmu/qcom_iommu.c index 9222a4a48bb33..53b1c279563ba 100644 --- a/drivers/iommu/arm/arm-smmu/qcom_iommu.c +++ b/drivers/iommu/arm/arm-smmu/qcom_iommu.c @@ -359,18 +359,36 @@ static void qcom_iommu_domain_free(struct iommu_domain *domain) kfree(qcom_domain); } -static int qcom_iommu_attach_dev(struct iommu_domain *domain, - struct device *dev, struct iommu_domain *old) +static int qcom_iommu_domain_test_dev(struct iommu_domain *domain, + struct device *dev, ioasid_t pasid, + struct iommu_domain *old) { struct qcom_iommu_dev *qcom_iommu = dev_iommu_priv_get(dev); struct qcom_iommu_domain *qcom_domain = to_qcom_iommu_domain(domain); - int ret; if (!qcom_iommu) { - dev_err(dev, "cannot attach to IOMMU, is it on the same bus?\n"); + dev_dbg(dev, "cannot attach to IOMMU, is it on the same bus?\n"); return -ENXIO; } + scoped_guard(mutex, &qcom_domain->init_mutex) { + /* + * Sanity check the domain. We don't support domains across + * different IOMMUs. + */ + if (qcom_domain->iommu && qcom_domain->iommu != qcom_iommu) + return -EINVAL; + } + + return 0; +} + +static int qcom_iommu_attach_dev(struct iommu_domain *domain, + struct device *dev, struct iommu_domain *old) +{ + struct qcom_iommu_dev *qcom_iommu = dev_iommu_priv_get(dev); + int ret; + /* Ensure that the domain is finalized */ pm_runtime_get_sync(qcom_iommu->dev); ret = qcom_iommu_init_domain(domain, qcom_iommu, dev); @@ -378,13 +396,17 @@ static int qcom_iommu_attach_dev(struct iommu_domain *domain, if (ret < 0) return ret; - /* - * Sanity check the domain. We don't support domains across - * different IOMMUs. - */ - if (qcom_domain->iommu != qcom_iommu) - return -EINVAL; + return 0; +} +static int qcom_iommu_identity_test(struct iommu_domain *identity_domain, + struct device *dev, ioasid_t pasid, + struct iommu_domain *old) +{ + if (old == identity_domain || !old) + return 0; + if (WARN_ON(!to_qcom_iommu_domain(old)->iommu)) + return -EINVAL; return 0; } @@ -401,8 +423,6 @@ static int qcom_iommu_identity_attach(struct iommu_domain *identity_domain, return 0; qcom_domain = to_qcom_iommu_domain(old); - if (WARN_ON(!qcom_domain->iommu)) - return -EINVAL; pm_runtime_get_sync(qcom_iommu->dev); for (i = 0; i < fwspec->num_ids; i++) { @@ -418,6 +438,7 @@ static int qcom_iommu_identity_attach(struct iommu_domain *identity_domain, } static struct iommu_domain_ops qcom_iommu_identity_ops = { + .test_dev = qcom_iommu_identity_test, .attach_dev = qcom_iommu_identity_attach, }; @@ -599,6 +620,7 @@ static const struct iommu_ops qcom_iommu_ops = { .device_group = generic_device_group, .of_xlate = qcom_iommu_of_xlate, .default_domain_ops = &(const struct iommu_domain_ops) { + .test_dev = qcom_iommu_domain_test_dev, .attach_dev = qcom_iommu_attach_dev, .map_pages = qcom_iommu_map, .unmap_pages = qcom_iommu_unmap, -- 2.43.0

