On Tue, Sep 06, 2022 at 08:44:54PM +0800, Lu Baolu wrote: > +/** > + * iommu_sva_bind_device() - Bind a process address space to a device > + * @dev: the device > + * @mm: the mm to bind, caller must hold a reference to mm_users > + * > + * Create a bond between device and address space, allowing the device to access > + * the mm using the returned PASID. If a bond already exists between @device and > + * @mm, it is returned and an additional reference is taken. Caller must call > + * iommu_sva_unbind_device() to release each reference. This isn't true anymore. How about storing handle in the domain? (Maybe also drop my Reviewed-by tags since this has changed significantly, I tend to ignore patches that have them) Thanks, Jean > + * > + * iommu_dev_enable_feature(dev, IOMMU_DEV_FEAT_SVA) must be called first, to > + * initialize the required SVA features. > + * > + * On error, returns an ERR_PTR value. > + */ > +struct iommu_sva *iommu_sva_bind_device(struct device *dev, struct mm_struct *mm) > +{ > + struct iommu_domain *domain; > + struct iommu_sva *handle; > + ioasid_t max_pasids; > + int ret; > + > + max_pasids = dev->iommu->max_pasids; > + if (!max_pasids) > + return ERR_PTR(-EOPNOTSUPP); > + > + /* Allocate mm->pasid if necessary. */ > + ret = iommu_sva_alloc_pasid(mm, 1, max_pasids - 1); > + if (ret) > + return ERR_PTR(ret); > + > + handle = kzalloc(sizeof(*handle), GFP_KERNEL); > + if (!handle) > + return ERR_PTR(-ENOMEM); > + > + mutex_lock(&iommu_sva_lock); > + /* Search for an existing domain. */ > + domain = iommu_get_domain_for_dev_pasid(dev, mm->pasid, > + IOMMU_DOMAIN_SVA); > + if (IS_ERR(domain)) { > + ret = PTR_ERR(domain); > + goto out_unlock; > + } > + > + if (domain) { > + domain->users++; > + goto out; > + } > + > + /* Allocate a new domain and set it on device pasid. */ > + domain = iommu_sva_domain_alloc(dev, mm); > + if (!domain) { > + ret = -ENOMEM; > + goto out_unlock; > + } > + > + ret = iommu_attach_device_pasid(domain, dev, mm->pasid); > + if (ret) > + goto out_free_domain; > + domain->users = 1; > +out: > + mutex_unlock(&iommu_sva_lock); > + handle->dev = dev; > + handle->domain = domain; > + > + return handle; > + > +out_free_domain: > + iommu_domain_free(domain); > +out_unlock: > + mutex_unlock(&iommu_sva_lock); > + kfree(handle); > + > + return ERR_PTR(ret); > +} > +EXPORT_SYMBOL_GPL(iommu_sva_bind_device);