Skip to content

Commit dba9ca9

Browse files
LuBaolujoergroedel
authored andcommitted
iommu: Same critical region for device release and removal
In a non-driver context, it is crucial to ensure the consistency of a device's iommu ops. Otherwise, it may result in a situation where a device is released but it's iommu ops are still used. Put the ops->release_device and __iommu_group_remove_device() in a same group->mutext critical region, so that, as long as group->mutex is held and the device is in its group's device list, its iommu ops are always consistent. Add check of group ownership if the released device is the last one. Signed-off-by: Jason Gunthorpe <jgg@nvidia.com> Signed-off-by: Lu Baolu <baolu.lu@linux.intel.com> Reviewed-by: Jason Gunthorpe <jgg@nvidia.com> Link: https://lore.kernel.org/r/20230322064956.263419-4-baolu.lu@linux.intel.com Signed-off-by: Joerg Roedel <jroedel@suse.de>
1 parent 293f256 commit dba9ca9

1 file changed

Lines changed: 28 additions & 2 deletions

File tree

drivers/iommu/iommu.c

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -495,18 +495,44 @@ static void __iommu_group_release_device(struct iommu_group *group,
495495

496496
void iommu_release_device(struct device *dev)
497497
{
498+
struct iommu_group *group = dev->iommu_group;
499+
struct group_device *device;
498500
const struct iommu_ops *ops;
499501

500-
if (!dev->iommu)
502+
if (!dev->iommu || !group)
501503
return;
502504

503505
iommu_device_unlink(dev->iommu->iommu_dev, dev);
504506

507+
mutex_lock(&group->mutex);
508+
device = __iommu_group_remove_device(group, dev);
509+
510+
/*
511+
* If the group has become empty then ownership must have been released,
512+
* and the current domain must be set back to NULL or the default
513+
* domain.
514+
*/
515+
if (list_empty(&group->devices))
516+
WARN_ON(group->owner_cnt ||
517+
group->domain != group->default_domain);
518+
519+
/*
520+
* release_device() must stop using any attached domain on the device.
521+
* If there are still other devices in the group they are not effected
522+
* by this callback.
523+
*
524+
* The IOMMU driver must set the device to either an identity or
525+
* blocking translation and stop using any domain pointer, as it is
526+
* going to be freed.
527+
*/
505528
ops = dev_iommu_ops(dev);
506529
if (ops->release_device)
507530
ops->release_device(dev);
531+
mutex_unlock(&group->mutex);
532+
533+
if (device)
534+
__iommu_group_release_device(group, device);
508535

509-
iommu_group_remove_device(dev);
510536
module_put(ops->owner);
511537
dev_iommu_free(dev);
512538
}

0 commit comments

Comments
 (0)