Skip to content

Commit 3e7f57d

Browse files
LuBaoluwilldeacon
authored andcommitted
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 <[email protected]> Reviewed-by: Jason Gunthorpe <[email protected]> Reviewed-by: Kevin Tian <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Will Deacon <[email protected]>
1 parent 1467821 commit 3e7f57d

File tree

4 files changed

+54
-12
lines changed

4 files changed

+54
-12
lines changed

drivers/iommu/iommu-priv.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,4 +28,7 @@ void iommu_device_unregister_bus(struct iommu_device *iommu,
2828
const struct bus_type *bus,
2929
struct notifier_block *nb);
3030

31+
struct iommu_attach_handle *iommu_attach_handle_get(struct iommu_group *group,
32+
ioasid_t pasid,
33+
unsigned int type);
3134
#endif /* __LINUX_IOMMU_PRIV_H */

drivers/iommu/iommu-sva.c

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@ static struct iommu_mm_data *iommu_alloc_mm_data(struct mm_struct *mm, struct de
4141
}
4242
iommu_mm->pasid = pasid;
4343
INIT_LIST_HEAD(&iommu_mm->sva_domains);
44-
INIT_LIST_HEAD(&iommu_mm->sva_handles);
4544
/*
4645
* Make sure the write to mm->iommu_mm is not reordered in front of
4746
* 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
6968
*/
7069
struct iommu_sva *iommu_sva_bind_device(struct device *dev, struct mm_struct *mm)
7170
{
71+
struct iommu_group *group = dev->iommu_group;
72+
struct iommu_attach_handle *attach_handle;
7273
struct iommu_mm_data *iommu_mm;
7374
struct iommu_domain *domain;
7475
struct iommu_sva *handle;
7576
int ret;
7677

78+
if (!group)
79+
return ERR_PTR(-ENODEV);
80+
7781
mutex_lock(&iommu_sva_lock);
7882

7983
/* Allocate mm->pasid if necessary. */
@@ -83,12 +87,22 @@ struct iommu_sva *iommu_sva_bind_device(struct device *dev, struct mm_struct *mm
8387
goto out_unlock;
8488
}
8589

86-
list_for_each_entry(handle, &mm->iommu_mm->sva_handles, handle_item) {
87-
if (handle->dev == dev) {
88-
refcount_inc(&handle->users);
89-
mutex_unlock(&iommu_sva_lock);
90-
return handle;
90+
/* A bond already exists, just take a reference`. */
91+
attach_handle = iommu_attach_handle_get(group, iommu_mm->pasid, IOMMU_DOMAIN_SVA);
92+
if (!IS_ERR(attach_handle)) {
93+
handle = container_of(attach_handle, struct iommu_sva, handle);
94+
if (attach_handle->domain->mm != mm) {
95+
ret = -EBUSY;
96+
goto out_unlock;
9197
}
98+
refcount_inc(&handle->users);
99+
mutex_unlock(&iommu_sva_lock);
100+
return handle;
101+
}
102+
103+
if (PTR_ERR(attach_handle) != -ENOENT) {
104+
ret = PTR_ERR(attach_handle);
105+
goto out_unlock;
92106
}
93107

94108
handle = kzalloc(sizeof(*handle), GFP_KERNEL);
@@ -99,7 +113,6 @@ struct iommu_sva *iommu_sva_bind_device(struct device *dev, struct mm_struct *mm
99113

100114
/* Search for an existing domain. */
101115
list_for_each_entry(domain, &mm->iommu_mm->sva_domains, next) {
102-
handle->handle.domain = domain;
103116
ret = iommu_attach_device_pasid(domain, dev, iommu_mm->pasid,
104117
&handle->handle);
105118
if (!ret) {
@@ -115,7 +128,6 @@ struct iommu_sva *iommu_sva_bind_device(struct device *dev, struct mm_struct *mm
115128
goto out_free_handle;
116129
}
117130

118-
handle->handle.domain = domain;
119131
ret = iommu_attach_device_pasid(domain, dev, iommu_mm->pasid,
120132
&handle->handle);
121133
if (ret)
@@ -125,7 +137,6 @@ struct iommu_sva *iommu_sva_bind_device(struct device *dev, struct mm_struct *mm
125137

126138
out:
127139
refcount_set(&handle->users, 1);
128-
list_add(&handle->handle_item, &mm->iommu_mm->sva_handles);
129140
mutex_unlock(&iommu_sva_lock);
130141
handle->dev = dev;
131142
return handle;
@@ -159,7 +170,6 @@ void iommu_sva_unbind_device(struct iommu_sva *handle)
159170
mutex_unlock(&iommu_sva_lock);
160171
return;
161172
}
162-
list_del(&handle->handle_item);
163173

164174
iommu_detach_device_pasid(domain, dev, iommu_mm->pasid);
165175
if (--domain->users == 0) {

drivers/iommu/iommu.c

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3486,3 +3486,34 @@ void iommu_free_global_pasid(ioasid_t pasid)
34863486
ida_free(&iommu_global_pasid_ida, pasid);
34873487
}
34883488
EXPORT_SYMBOL_GPL(iommu_free_global_pasid);
3489+
3490+
/**
3491+
* iommu_attach_handle_get - Return the attach handle
3492+
* @group: the iommu group that domain was attached to
3493+
* @pasid: the pasid within the group
3494+
* @type: matched domain type, 0 for any match
3495+
*
3496+
* Return handle or ERR_PTR(-ENOENT) on none, ERR_PTR(-EBUSY) on mismatch.
3497+
*
3498+
* Return the attach handle to the caller. The life cycle of an iommu attach
3499+
* handle is from the time when the domain is attached to the time when the
3500+
* domain is detached. Callers are required to synchronize the call of
3501+
* iommu_attach_handle_get() with domain attachment and detachment. The attach
3502+
* handle can only be used during its life cycle.
3503+
*/
3504+
struct iommu_attach_handle *
3505+
iommu_attach_handle_get(struct iommu_group *group, ioasid_t pasid, unsigned int type)
3506+
{
3507+
struct iommu_attach_handle *handle;
3508+
3509+
xa_lock(&group->pasid_array);
3510+
handle = xa_load(&group->pasid_array, pasid);
3511+
if (!handle)
3512+
handle = ERR_PTR(-ENOENT);
3513+
else if (type && handle->domain->type != type)
3514+
handle = ERR_PTR(-EBUSY);
3515+
xa_unlock(&group->pasid_array);
3516+
3517+
return handle;
3518+
}
3519+
EXPORT_SYMBOL_NS_GPL(iommu_attach_handle_get, IOMMUFD_INTERNAL);

include/linux/iommu.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1005,14 +1005,12 @@ struct iommu_attach_handle {
10051005
struct iommu_sva {
10061006
struct iommu_attach_handle handle;
10071007
struct device *dev;
1008-
struct list_head handle_item;
10091008
refcount_t users;
10101009
};
10111010

10121011
struct iommu_mm_data {
10131012
u32 pasid;
10141013
struct list_head sva_domains;
1015-
struct list_head sva_handles;
10161014
};
10171015

10181016
int iommu_fwspec_init(struct device *dev, struct fwnode_handle *iommu_fwnode,

0 commit comments

Comments
 (0)