Expose an interface to replace the domain of an iommu group for frameworks like vfio which claims the ownership of the whole iommu group. Signed-off-by: Lu Baolu <baolu.lu@xxxxxxxxxxxxxxx> --- include/linux/iommu.h | 10 ++++++++++ drivers/iommu/iommu.c | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/include/linux/iommu.h b/include/linux/iommu.h index 408a6d2b3034..66ebce3d1e11 100644 --- a/include/linux/iommu.h +++ b/include/linux/iommu.h @@ -677,6 +677,9 @@ void iommu_device_unuse_dma_api(struct device *dev); int iommu_group_set_dma_owner(struct iommu_group *group, void *owner); void iommu_group_release_dma_owner(struct iommu_group *group); bool iommu_group_dma_owner_claimed(struct iommu_group *group); +int iommu_group_replace_domain(struct iommu_group *group, + struct iommu_domain *old, + struct iommu_domain *new); #else /* CONFIG_IOMMU_API */ @@ -1090,6 +1093,13 @@ static inline bool iommu_group_dma_owner_claimed(struct iommu_group *group) { return false; } + +static inline int +iommu_group_replace_domain(struct iommu_group *group, struct iommu_domain *old, + struct iommu_domain *new) +{ + return -ENODEV; +} #endif /* CONFIG_IOMMU_API */ /** diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index 72a95dea688e..ab8ab95969f5 100644 --- a/drivers/iommu/iommu.c +++ b/drivers/iommu/iommu.c @@ -3431,3 +3431,40 @@ bool iommu_group_dma_owner_claimed(struct iommu_group *group) return user; } EXPORT_SYMBOL_GPL(iommu_group_dma_owner_claimed); + +/** + * iommu_group_replace_domain() - Replace group's domain + * @group: The group. + * @old: The previous attached domain. NULL for none. + * @new: The new domain about to be attached. + * + * This is to support backward compatibility for vfio which manages the dma + * ownership in iommu_group level. + */ +int iommu_group_replace_domain(struct iommu_group *group, + struct iommu_domain *old, + struct iommu_domain *new) +{ + int ret = 0; + + mutex_lock(&group->mutex); + if (!group->owner || group->domain != old) { + ret = -EPERM; + goto unlock_out; + } + + if (old) + __iommu_detach_group(old, group); + + if (new) { + ret = __iommu_attach_group(new, group); + if (ret && old) + __iommu_attach_group(old, group); + } + +unlock_out: + mutex_unlock(&group->mutex); + + return ret; +} +EXPORT_SYMBOL_GPL(iommu_group_replace_domain); -- 2.25.1