mirror of
https://github.com/torvalds/linux.git
synced 2024-11-26 22:21:42 +00:00
iommu: Remove sva handle list
The struct sva_iommu represents an association between an SVA domain and a PASID of a device. It's stored in the iommu group's pasid array and also tracked by a list in the per-mm data structure. Removes duplicate tracking of sva_iommu by eliminating the list. Signed-off-by: Lu Baolu <baolu.lu@linux.intel.com> Reviewed-by: Jason Gunthorpe <jgg@nvidia.com> Reviewed-by: Kevin Tian <kevin.tian@intel.com> Link: https://lore.kernel.org/r/20240702063444.105814-3-baolu.lu@linux.intel.com Signed-off-by: Will Deacon <will@kernel.org>
This commit is contained in:
parent
14678219cf
commit
3e7f57d1ef
@ -28,4 +28,7 @@ void iommu_device_unregister_bus(struct iommu_device *iommu,
|
||||
const struct bus_type *bus,
|
||||
struct notifier_block *nb);
|
||||
|
||||
struct iommu_attach_handle *iommu_attach_handle_get(struct iommu_group *group,
|
||||
ioasid_t pasid,
|
||||
unsigned int type);
|
||||
#endif /* __LINUX_IOMMU_PRIV_H */
|
||||
|
@ -41,7 +41,6 @@ static struct iommu_mm_data *iommu_alloc_mm_data(struct mm_struct *mm, struct de
|
||||
}
|
||||
iommu_mm->pasid = pasid;
|
||||
INIT_LIST_HEAD(&iommu_mm->sva_domains);
|
||||
INIT_LIST_HEAD(&iommu_mm->sva_handles);
|
||||
/*
|
||||
* Make sure the write to mm->iommu_mm is not reordered in front of
|
||||
* initialization to iommu_mm fields. If it does, readers may see a
|
||||
@ -69,11 +68,16 @@ static struct iommu_mm_data *iommu_alloc_mm_data(struct mm_struct *mm, struct de
|
||||
*/
|
||||
struct iommu_sva *iommu_sva_bind_device(struct device *dev, struct mm_struct *mm)
|
||||
{
|
||||
struct iommu_group *group = dev->iommu_group;
|
||||
struct iommu_attach_handle *attach_handle;
|
||||
struct iommu_mm_data *iommu_mm;
|
||||
struct iommu_domain *domain;
|
||||
struct iommu_sva *handle;
|
||||
int ret;
|
||||
|
||||
if (!group)
|
||||
return ERR_PTR(-ENODEV);
|
||||
|
||||
mutex_lock(&iommu_sva_lock);
|
||||
|
||||
/* Allocate mm->pasid if necessary. */
|
||||
@ -83,12 +87,22 @@ struct iommu_sva *iommu_sva_bind_device(struct device *dev, struct mm_struct *mm
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
list_for_each_entry(handle, &mm->iommu_mm->sva_handles, handle_item) {
|
||||
if (handle->dev == dev) {
|
||||
refcount_inc(&handle->users);
|
||||
mutex_unlock(&iommu_sva_lock);
|
||||
return handle;
|
||||
/* A bond already exists, just take a reference`. */
|
||||
attach_handle = iommu_attach_handle_get(group, iommu_mm->pasid, IOMMU_DOMAIN_SVA);
|
||||
if (!IS_ERR(attach_handle)) {
|
||||
handle = container_of(attach_handle, struct iommu_sva, handle);
|
||||
if (attach_handle->domain->mm != mm) {
|
||||
ret = -EBUSY;
|
||||
goto out_unlock;
|
||||
}
|
||||
refcount_inc(&handle->users);
|
||||
mutex_unlock(&iommu_sva_lock);
|
||||
return handle;
|
||||
}
|
||||
|
||||
if (PTR_ERR(attach_handle) != -ENOENT) {
|
||||
ret = PTR_ERR(attach_handle);
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
handle = kzalloc(sizeof(*handle), GFP_KERNEL);
|
||||
@ -99,7 +113,6 @@ struct iommu_sva *iommu_sva_bind_device(struct device *dev, struct mm_struct *mm
|
||||
|
||||
/* Search for an existing domain. */
|
||||
list_for_each_entry(domain, &mm->iommu_mm->sva_domains, next) {
|
||||
handle->handle.domain = domain;
|
||||
ret = iommu_attach_device_pasid(domain, dev, iommu_mm->pasid,
|
||||
&handle->handle);
|
||||
if (!ret) {
|
||||
@ -115,7 +128,6 @@ struct iommu_sva *iommu_sva_bind_device(struct device *dev, struct mm_struct *mm
|
||||
goto out_free_handle;
|
||||
}
|
||||
|
||||
handle->handle.domain = domain;
|
||||
ret = iommu_attach_device_pasid(domain, dev, iommu_mm->pasid,
|
||||
&handle->handle);
|
||||
if (ret)
|
||||
@ -125,7 +137,6 @@ struct iommu_sva *iommu_sva_bind_device(struct device *dev, struct mm_struct *mm
|
||||
|
||||
out:
|
||||
refcount_set(&handle->users, 1);
|
||||
list_add(&handle->handle_item, &mm->iommu_mm->sva_handles);
|
||||
mutex_unlock(&iommu_sva_lock);
|
||||
handle->dev = dev;
|
||||
return handle;
|
||||
@ -159,7 +170,6 @@ void iommu_sva_unbind_device(struct iommu_sva *handle)
|
||||
mutex_unlock(&iommu_sva_lock);
|
||||
return;
|
||||
}
|
||||
list_del(&handle->handle_item);
|
||||
|
||||
iommu_detach_device_pasid(domain, dev, iommu_mm->pasid);
|
||||
if (--domain->users == 0) {
|
||||
|
@ -3486,3 +3486,34 @@ void iommu_free_global_pasid(ioasid_t pasid)
|
||||
ida_free(&iommu_global_pasid_ida, pasid);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(iommu_free_global_pasid);
|
||||
|
||||
/**
|
||||
* iommu_attach_handle_get - Return the attach handle
|
||||
* @group: the iommu group that domain was attached to
|
||||
* @pasid: the pasid within the group
|
||||
* @type: matched domain type, 0 for any match
|
||||
*
|
||||
* Return handle or ERR_PTR(-ENOENT) on none, ERR_PTR(-EBUSY) on mismatch.
|
||||
*
|
||||
* Return the attach handle to the caller. The life cycle of an iommu attach
|
||||
* handle is from the time when the domain is attached to the time when the
|
||||
* domain is detached. Callers are required to synchronize the call of
|
||||
* iommu_attach_handle_get() with domain attachment and detachment. The attach
|
||||
* handle can only be used during its life cycle.
|
||||
*/
|
||||
struct iommu_attach_handle *
|
||||
iommu_attach_handle_get(struct iommu_group *group, ioasid_t pasid, unsigned int type)
|
||||
{
|
||||
struct iommu_attach_handle *handle;
|
||||
|
||||
xa_lock(&group->pasid_array);
|
||||
handle = xa_load(&group->pasid_array, pasid);
|
||||
if (!handle)
|
||||
handle = ERR_PTR(-ENOENT);
|
||||
else if (type && handle->domain->type != type)
|
||||
handle = ERR_PTR(-EBUSY);
|
||||
xa_unlock(&group->pasid_array);
|
||||
|
||||
return handle;
|
||||
}
|
||||
EXPORT_SYMBOL_NS_GPL(iommu_attach_handle_get, IOMMUFD_INTERNAL);
|
||||
|
@ -1005,14 +1005,12 @@ struct iommu_attach_handle {
|
||||
struct iommu_sva {
|
||||
struct iommu_attach_handle handle;
|
||||
struct device *dev;
|
||||
struct list_head handle_item;
|
||||
refcount_t users;
|
||||
};
|
||||
|
||||
struct iommu_mm_data {
|
||||
u32 pasid;
|
||||
struct list_head sva_domains;
|
||||
struct list_head sva_handles;
|
||||
};
|
||||
|
||||
int iommu_fwspec_init(struct device *dev, struct fwnode_handle *iommu_fwnode,
|
||||
|
Loading…
Reference in New Issue
Block a user