[PATCH 4/4] iommu: Cleanup iommu_change_dev_def_domain()

From: Lu Baolu
Date: Mon Feb 13 2023 - 02:58:40 EST


As the singleton group limitation has been removed, cleanup the code
in iommu_change_dev_def_domain() accordingly.

Signed-off-by: Lu Baolu <baolu.lu@xxxxxxxxxxxxxxx>
---
drivers/iommu/iommu.c | 41 ++++++++++-------------------------------
1 file changed, 10 insertions(+), 31 deletions(-)

diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index 1e69def20a67..67b978403a05 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -2783,7 +2783,7 @@ int iommu_dev_disable_feature(struct device *dev, enum iommu_dev_features feat)
EXPORT_SYMBOL_GPL(iommu_dev_disable_feature);

/*
- * Changes the default domain of an iommu group that has *only* one device
+ * Changes the default domain of an iommu group
*
* @group: The group for which the default domain should be changed
* @type: The type of the new default domain that gets associated with the group
@@ -2797,33 +2797,14 @@ EXPORT_SYMBOL_GPL(iommu_dev_disable_feature);
*/
static int iommu_change_dev_def_domain(struct iommu_group *group, int type)
{
+ struct __group_domain_type gtype = {NULL, 0};
struct iommu_domain *prev_dom;
struct group_device *grp_dev;
- int ret, dev_def_dom;
struct device *dev;
+ int ret;

mutex_lock(&group->mutex);

- /*
- * iommu group wasn't locked while acquiring device lock in
- * iommu_group_store_type(). So, make sure that the device count hasn't
- * changed while acquiring device lock.
- *
- * Changing default domain of an iommu group with two or more devices
- * isn't supported because there could be a potential deadlock. Consider
- * the following scenario. T1 is trying to acquire device locks of all
- * the devices in the group and before it could acquire all of them,
- * there could be another thread T2 (from different sub-system and use
- * case) that has already acquired some of the device locks and might be
- * waiting for T1 to release other device locks.
- */
- if (iommu_group_device_count(group) != 1) {
- pr_err_ratelimited("Cannot change default domain: Group has more than one device\n");
- ret = -EINVAL;
- goto out;
- }
-
- /* Since group has only one device */
grp_dev = list_first_entry(&group->devices, struct group_device, list);
dev = grp_dev->dev;

@@ -2833,15 +2814,16 @@ static int iommu_change_dev_def_domain(struct iommu_group *group, int type)
goto out;
}

- dev_def_dom = iommu_get_def_domain_type(dev);
+ __iommu_group_for_each_dev(group, &gtype,
+ probe_get_default_domain_type);
if (!type) {
/*
* If the user hasn't requested any specific type of domain and
* if the device supports both the domains, then default to the
* domain the device was booted with
*/
- type = dev_def_dom ? : iommu_def_domain_type;
- } else if (dev_def_dom && type != dev_def_dom) {
+ type = gtype.type ? : iommu_def_domain_type;
+ } else if (gtype.type && type != gtype.type) {
pr_err_ratelimited("Device cannot be in %s domain\n",
iommu_domain_type_str(type));
ret = -EINVAL;
@@ -2870,16 +2852,14 @@ static int iommu_change_dev_def_domain(struct iommu_group *group, int type)
if (ret)
goto out;

- ret = iommu_create_device_direct_mappings(group, dev);
+ ret = iommu_group_create_direct_mappings(group);
if (ret)
goto free_new_domain;

- ret = __iommu_attach_device(group->default_domain, dev);
+ ret = __iommu_attach_group(group->default_domain, group);
if (ret)
goto free_new_domain;

- group->domain = group->default_domain;
-
/*
* Release the mutex here because ops->probe_finalize() call-back of
* some vendor IOMMU drivers calls arm_iommu_attach_device() which
@@ -2889,7 +2869,7 @@ static int iommu_change_dev_def_domain(struct iommu_group *group, int type)
mutex_unlock(&group->mutex);

/* Make sure dma_ops is appropriatley set */
- iommu_group_do_probe_finalize(dev, group->default_domain);
+ __iommu_group_dma_finalize(group);
iommu_domain_free(prev_dom);
return 0;

@@ -2897,7 +2877,6 @@ static int iommu_change_dev_def_domain(struct iommu_group *group, int type)
iommu_domain_free(group->default_domain);
group->default_domain = prev_dom;
group->domain = prev_dom;
-
out:
mutex_unlock(&group->mutex);

--
2.34.1