summaryrefslogtreecommitdiff
path: root/drivers/iommu
diff options
context:
space:
mode:
authorJason Gunthorpe <jgg@nvidia.com>2023-05-11 01:42:10 -0300
committerJoerg Roedel <jroedel@suse.de>2023-05-23 08:15:56 +0200
commit8b4eb75ee50e6f4606f88debf44aeb47937057d4 (patch)
tree0e133af0c686dda30121f539ef34668e94d9d4af /drivers/iommu
parentdfddd54dc77c4519ee3c94e7462b1c035c69a031 (diff)
iommu: Consolidate the code to calculate the target default domain type
Put all the code to calculate the default domain type into one function. Make the function able to handle the iommu_change_dev_def_domain() by taking in the target domain type and erroring out if the target type isn't reachable. This makes it really clear that specifying a 0 type during iommu_change_dev_def_domain() will have the same outcome as the normal probe path. Remove the obfuscating use of __iommu_group_for_each_dev() and related struct __group_domain_type. Reviewed-by: Lu Baolu <baolu.lu@linux.intel.com> Reviewed-by: Kevin Tian <kevin.tian@intel.com> Tested-by: Heiko Stuebner <heiko@sntech.de> Tested-by: Niklas Schnelle <schnelle@linux.ibm.com> Signed-off-by: Jason Gunthorpe <jgg@nvidia.com> Link: https://lore.kernel.org/r/12-v5-1b99ae392328+44574-iommu_err_unwind_jgg@nvidia.com Signed-off-by: Joerg Roedel <jroedel@suse.de>
Diffstat (limited to 'drivers/iommu')
-rw-r--r--drivers/iommu/iommu.c88
1 files changed, 35 insertions, 53 deletions
diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index 2041e3e028de..9e661cbd3d42 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -1758,50 +1758,43 @@ static int iommu_bus_notifier(struct notifier_block *nb,
return 0;
}
-struct __group_domain_type {
- struct device *dev;
- unsigned int type;
-};
-
-static int probe_get_default_domain_type(struct device *dev, void *data)
+/* A target_type of 0 will select the best domain type and cannot fail */
+static int iommu_get_default_domain_type(struct iommu_group *group,
+ int target_type)
{
- struct __group_domain_type *gtype = data;
- unsigned int type = iommu_get_def_domain_type(dev);
+ int best_type = target_type;
+ struct group_device *gdev;
+ struct device *last_dev;
- if (type) {
- if (gtype->type && gtype->type != type) {
- dev_warn(dev, "Device needs domain type %s, but device %s in the same iommu group requires type %s - using default\n",
- iommu_domain_type_str(type),
- dev_name(gtype->dev),
- iommu_domain_type_str(gtype->type));
- gtype->type = 0;
- }
+ lockdep_assert_held(&group->mutex);
- if (!gtype->dev) {
- gtype->dev = dev;
- gtype->type = type;
+ for_each_group_device(group, gdev) {
+ unsigned int type = iommu_get_def_domain_type(gdev->dev);
+
+ if (best_type && type && best_type != type) {
+ if (target_type) {
+ dev_err_ratelimited(
+ gdev->dev,
+ "Device cannot be in %s domain\n",
+ iommu_domain_type_str(target_type));
+ return -1;
+ }
+
+ dev_warn(
+ gdev->dev,
+ "Device needs domain type %s, but device %s in the same iommu group requires type %s - using default\n",
+ iommu_domain_type_str(type), dev_name(last_dev),
+ iommu_domain_type_str(best_type));
+ return iommu_def_domain_type;
}
+ if (!best_type)
+ best_type = type;
+ last_dev = gdev->dev;
}
- return 0;
-}
-
-static void probe_alloc_default_domain(const struct bus_type *bus,
- struct iommu_group *group)
-{
- struct __group_domain_type gtype;
-
- memset(&gtype, 0, sizeof(gtype));
-
- /* Ask for default domain requirements of all devices in the group */
- __iommu_group_for_each_dev(group, &gtype,
- probe_get_default_domain_type);
-
- if (!gtype.type)
- gtype.type = iommu_def_domain_type;
-
- iommu_group_alloc_default_domain(bus, group, gtype.type);
-
+ if (!best_type)
+ return iommu_def_domain_type;
+ return best_type;
}
static int iommu_group_do_probe_finalize(struct device *dev, void *data)
@@ -1857,7 +1850,8 @@ int bus_iommu_probe(const struct bus_type *bus)
list_del_init(&group->entry);
/* Try to allocate default domain */
- probe_alloc_default_domain(bus, group);
+ iommu_group_alloc_default_domain(
+ bus, group, iommu_get_default_domain_type(group, 0));
if (!group->default_domain) {
mutex_unlock(&group->mutex);
@@ -2882,27 +2876,15 @@ EXPORT_SYMBOL_GPL(iommu_dev_disable_feature);
static int iommu_change_dev_def_domain(struct iommu_group *group,
struct device *dev, int type)
{
- struct __group_domain_type gtype = {NULL, 0};
struct iommu_domain *prev_dom;
int ret;
lockdep_assert_held(&group->mutex);
prev_dom = group->default_domain;
- __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 = gtype.type ? : iommu_def_domain_type;
- } else if (gtype.type && type != gtype.type) {
- dev_err_ratelimited(dev, "Device cannot be in %s domain\n",
- iommu_domain_type_str(type));
+ type = iommu_get_default_domain_type(group, type);
+ if (type < 0)
return -EINVAL;
- }
/*
* Switch to a new domain only if the requested domain type is different