On Sun, Sep 19, 2021 at 02:38:41PM +0800, Liu Yi L wrote: > From: Lu Baolu > > These two helpers could be used when 1) the iommu group is singleton, > or 2) the upper layer has put the iommu group into the secure state by > calling iommu_device_init_user_dma(). > > As we want the iommufd design to be a device-centric model, we want to > remove any group knowledge in iommufd. Given that we already have > iommu_at[de]tach_device() interface, we could extend it for iommufd > simply by doing below: > > - first device in a group does group attach; > - last device in a group does group detach. > > as long as the group has been put into the secure context. > > The commit <426a273834eae> ("iommu: Limit iommu_attach/detach_device to > device with their own group") deliberately restricts the two interfaces > to single-device group. To avoid the conflict with existing usages, we > keep this policy and put the new extension only when the group has been > marked for user_dma. I still kind of hate this interface because it means an operation that appears to be explicitly on a single device has an implicit effect on other devices. > Signed-off-by: Lu Baolu > --- > drivers/iommu/iommu.c | 25 +++++++++++++++++++++---- > 1 file changed, 21 insertions(+), 4 deletions(-) > > diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c > index bffd84e978fb..b6178997aef1 100644 > --- a/drivers/iommu/iommu.c > +++ b/drivers/iommu/iommu.c > @@ -47,6 +47,7 @@ struct iommu_group { > struct list_head entry; > unsigned long user_dma_owner_id; > refcount_t owner_cnt; > + refcount_t attach_cnt; > }; > > struct group_device { > @@ -1994,7 +1995,7 @@ static int __iommu_attach_device(struct iommu_domain *domain, > int iommu_attach_device(struct iommu_domain *domain, struct device *dev) > { > struct iommu_group *group; > - int ret; > + int ret = 0; > > group = iommu_group_get(dev); > if (!group) > @@ -2005,11 +2006,23 @@ int iommu_attach_device(struct iommu_domain *domain, struct device *dev) > * change while we are attaching > */ > mutex_lock(&group->mutex); > - ret = -EINVAL; > - if (iommu_group_device_count(group) != 1) > + if (group->user_dma_owner_id) { > + if (group->domain) { > + if (group->domain != domain) > + ret = -EBUSY; > + else > + refcount_inc(&group->attach_cnt); > + > + goto out_unlock; > + } > + } else if (iommu_group_device_count(group) != 1) { With this condition in the else, how can you ever attach the first device of a multi-device group? > + ret = -EINVAL; > goto out_unlock; > + } > > ret = __iommu_attach_group(domain, group); > + if (!ret && group->user_dma_owner_id) > + refcount_set(&group->attach_cnt, 1); > > out_unlock: > mutex_unlock(&group->mutex); > @@ -2261,7 +2274,10 @@ void iommu_detach_device(struct iommu_domain *domain, struct device *dev) > return; > > mutex_lock(&group->mutex); > - if (iommu_group_device_count(group) != 1) { > + if (group->user_dma_owner_id) { > + if (!refcount_dec_and_test(&group->attach_cnt)) > + goto out_unlock; > + } else if (iommu_group_device_count(group) != 1) { Shouldn't this path (detach a thing that's not attached), be a no-op regardless of whether it's a singleton group or not? Why does one deserve a warning and one not? > WARN_ON(1); > goto out_unlock; > } > @@ -3368,6 +3384,7 @@ static int iommu_group_init_user_dma(struct iommu_group *group, > > group->user_dma_owner_id = owner; > refcount_set(&group->owner_cnt, 1); > + refcount_set(&group->attach_cnt, 0); > > /* default domain is unsafe for user-initiated dma */ > if (group->domain == group->default_domain) -- David Gibson | I'll have my music baroque, and my code david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_ | _way_ _around_! http://www.ozlabs.org/~dgibson