Skip to content

Commit f188056

Browse files
jgunthorpejoergroedel
authored andcommitted
iommu: Avoid locking/unlocking for iommu_probe_device()
Remove the race where a hotplug of a device into an existing group will have the device installed in the group->devices, but not yet attached to the group's current domain. Move the group attachment logic from iommu_probe_device() and put it under the same mutex that updates the group->devices list so everything is atomic under the lock. We retain the two step setup of the default domain for the bus_iommu_probe() case solely so that we have a more complete view of the group when creating the default domain for boot time devices. This is not generally necessary with the current code structure but seems to be supporting some odd corner cases like alias RID's and IOMMU_RESV_DIRECT or driver bugs returning different default_domain types for the same group. During bus_iommu_probe() the group will have a device list but both group->default_domain and group->domain will be NULL. Reviewed-by: Lu Baolu <[email protected]> Reviewed-by: Kevin Tian <[email protected]> Signed-off-by: Jason Gunthorpe <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Joerg Roedel <[email protected]>
1 parent fa08280 commit f188056

File tree

1 file changed

+35
-43
lines changed

1 file changed

+35
-43
lines changed

drivers/iommu/iommu.c

Lines changed: 35 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,8 @@ static ssize_t iommu_group_store_type(struct iommu_group *group,
131131
const char *buf, size_t count);
132132
static struct group_device *iommu_group_alloc_device(struct iommu_group *group,
133133
struct device *dev);
134+
static void __iommu_group_free_device(struct iommu_group *group,
135+
struct group_device *grp_dev);
134136

135137
#define IOMMU_GROUP_ATTR(_name, _mode, _show, _store) \
136138
struct iommu_group_attribute iommu_group_attr_##_name = \
@@ -469,14 +471,39 @@ static int __iommu_probe_device(struct device *dev, struct list_head *group_list
469471
goto err_put_group;
470472
}
471473

474+
/*
475+
* The gdev must be in the list before calling
476+
* iommu_setup_default_domain()
477+
*/
472478
list_add_tail(&gdev->list, &group->devices);
473-
if (group_list && !group->default_domain && list_empty(&group->entry))
474-
list_add_tail(&group->entry, group_list);
479+
WARN_ON(group->default_domain && !group->domain);
480+
if (group->default_domain)
481+
iommu_create_device_direct_mappings(group->default_domain, dev);
482+
if (group->domain) {
483+
ret = __iommu_device_set_domain(group, dev, group->domain, 0);
484+
if (ret)
485+
goto err_remove_gdev;
486+
} else if (!group->default_domain && !group_list) {
487+
ret = iommu_setup_default_domain(group, 0);
488+
if (ret)
489+
goto err_remove_gdev;
490+
} else if (!group->default_domain) {
491+
/*
492+
* With a group_list argument we defer the default_domain setup
493+
* to the caller by providing a de-duplicated list of groups
494+
* that need further setup.
495+
*/
496+
if (list_empty(&group->entry))
497+
list_add_tail(&group->entry, group_list);
498+
}
475499
mutex_unlock(&group->mutex);
476500
mutex_unlock(&iommu_probe_device_lock);
477501

478502
return 0;
479503

504+
err_remove_gdev:
505+
list_del(&gdev->list);
506+
__iommu_group_free_device(group, gdev);
480507
err_put_group:
481508
iommu_deinit_device(dev);
482509
mutex_unlock(&group->mutex);
@@ -490,52 +517,17 @@ static int __iommu_probe_device(struct device *dev, struct list_head *group_list
490517
int iommu_probe_device(struct device *dev)
491518
{
492519
const struct iommu_ops *ops;
493-
struct iommu_group *group;
494520
int ret;
495521

496522
ret = __iommu_probe_device(dev, NULL);
497523
if (ret)
498-
goto err_out;
499-
500-
group = iommu_group_get(dev);
501-
if (!group) {
502-
ret = -ENODEV;
503-
goto err_release;
504-
}
505-
506-
mutex_lock(&group->mutex);
507-
508-
if (group->default_domain)
509-
iommu_create_device_direct_mappings(group->default_domain, dev);
510-
511-
if (group->domain) {
512-
ret = __iommu_device_set_domain(group, dev, group->domain, 0);
513-
if (ret)
514-
goto err_unlock;
515-
} else if (!group->default_domain) {
516-
ret = iommu_setup_default_domain(group, 0);
517-
if (ret)
518-
goto err_unlock;
519-
}
520-
521-
mutex_unlock(&group->mutex);
522-
iommu_group_put(group);
524+
return ret;
523525

524526
ops = dev_iommu_ops(dev);
525527
if (ops->probe_finalize)
526528
ops->probe_finalize(dev);
527529

528530
return 0;
529-
530-
err_unlock:
531-
mutex_unlock(&group->mutex);
532-
iommu_group_put(group);
533-
err_release:
534-
iommu_release_device(dev);
535-
536-
err_out:
537-
return ret;
538-
539531
}
540532

541533
static void __iommu_group_free_device(struct iommu_group *group,
@@ -1815,11 +1807,6 @@ int bus_iommu_probe(const struct bus_type *bus)
18151807
LIST_HEAD(group_list);
18161808
int ret;
18171809

1818-
/*
1819-
* This code-path does not allocate the default domain when
1820-
* creating the iommu group, so do it after the groups are
1821-
* created.
1822-
*/
18231810
ret = bus_for_each_dev(bus, NULL, &group_list, probe_iommu_group);
18241811
if (ret)
18251812
return ret;
@@ -1832,6 +1819,11 @@ int bus_iommu_probe(const struct bus_type *bus)
18321819
/* Remove item from the list */
18331820
list_del_init(&group->entry);
18341821

1822+
/*
1823+
* We go to the trouble of deferred default domain creation so
1824+
* that the cross-group default domain type and the setup of the
1825+
* IOMMU_RESV_DIRECT will work correctly in non-hotpug scenarios.
1826+
*/
18351827
ret = iommu_setup_default_domain(group, 0);
18361828
if (ret) {
18371829
mutex_unlock(&group->mutex);

0 commit comments

Comments
 (0)