Messages in this thread Patch in this message | | | From | Lu Baolu <> | Subject | [PATCH v2 3/6] iommu: Same critical region for device release and removal | Date | Fri, 17 Feb 2023 17:47:33 +0800 |
| |
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 some 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.
Signed-off-by: Lu Baolu <baolu.lu@linux.intel.com> --- drivers/iommu/iommu.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-)
diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index 6247883991e2..093692308b80 100644 --- a/drivers/iommu/iommu.c +++ b/drivers/iommu/iommu.c @@ -101,6 +101,10 @@ static int iommu_create_device_direct_mappings(struct iommu_group *group, static struct iommu_group *iommu_group_get_for_dev(struct device *dev); static ssize_t iommu_group_store_type(struct iommu_group *group, const char *buf, size_t count); +static struct group_device * +__iommu_group_remove_device(struct iommu_group *group, struct device *dev); +static void __iommu_group_release_device(struct iommu_group *group, + struct group_device *grp_dev); #define IOMMU_GROUP_ATTR(_name, _mode, _show, _store) \ struct iommu_group_attribute iommu_group_attr_##_name = \ @@ -466,18 +470,25 @@ int iommu_probe_device(struct device *dev) void iommu_release_device(struct device *dev) { + struct iommu_group *group = dev->iommu_group; + struct group_device *device; const struct iommu_ops *ops; - if (!dev->iommu) + if (!dev->iommu || !group) return; iommu_device_unlink(dev->iommu->iommu_dev, dev); + mutex_lock(&group->mutex); ops = dev_iommu_ops(dev); if (ops->release_device) ops->release_device(dev); + device = __iommu_group_remove_device(group, dev); + mutex_unlock(&group->mutex); + + if (device) + __iommu_group_release_device(group, device); - iommu_group_remove_device(dev); module_put(ops->owner); dev_iommu_free(dev); } -- 2.34.1
| |