Skip to content

Commit e1ea9d3

Browse files
yiliu1765jgunthorpe
authored andcommitted
iommu: Store either domain or handle in group->pasid_array
iommu_attach_device_pasid() only stores handle to group->pasid_array when there is a valid handle input. However, it makes the iommu_attach_device_pasid() unable to detect if the pasid has been attached or not previously. To be complete, let the iommu_attach_device_pasid() store the domain to group->pasid_array if no valid handle. The other users of the group->pasid_array should be updated to be consistent. e.g. the iommu_attach_group_handle() and iommu_replace_group_handle(). Link: https://patch.msgid.link/r/[email protected] Suggested-by: Jason Gunthorpe <[email protected]> Reviewed-by: Jason Gunthorpe <[email protected]> Reviewed-by: Nicolin Chen <[email protected]> Reviewed-by: Kevin Tian <[email protected]> Signed-off-by: Yi Liu <[email protected]> Reviewed-by: Lu Baolu <[email protected]> Signed-off-by: Jason Gunthorpe <[email protected]>
1 parent 473ec07 commit e1ea9d3

File tree

1 file changed

+31
-12
lines changed

1 file changed

+31
-12
lines changed

drivers/iommu/iommu.c

Lines changed: 31 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,9 @@ static unsigned int iommu_def_domain_type __read_mostly;
4545
static bool iommu_dma_strict __read_mostly = IS_ENABLED(CONFIG_IOMMU_DEFAULT_DMA_STRICT);
4646
static u32 iommu_cmd_line __read_mostly;
4747

48+
/* Tags used with xa_tag_pointer() in group->pasid_array */
49+
enum { IOMMU_PASID_ARRAY_DOMAIN = 0, IOMMU_PASID_ARRAY_HANDLE = 1 };
50+
4851
struct iommu_group {
4952
struct kobject kobj;
5053
struct kobject *devices_kobj;
@@ -2147,6 +2150,17 @@ struct iommu_domain *iommu_get_dma_domain(struct device *dev)
21472150
return dev->iommu_group->default_domain;
21482151
}
21492152

2153+
static void *iommu_make_pasid_array_entry(struct iommu_domain *domain,
2154+
struct iommu_attach_handle *handle)
2155+
{
2156+
if (handle) {
2157+
handle->domain = domain;
2158+
return xa_tag_pointer(handle, IOMMU_PASID_ARRAY_HANDLE);
2159+
}
2160+
2161+
return xa_tag_pointer(domain, IOMMU_PASID_ARRAY_DOMAIN);
2162+
}
2163+
21502164
static int __iommu_attach_group(struct iommu_domain *domain,
21512165
struct iommu_group *group)
21522166
{
@@ -3348,6 +3362,7 @@ int iommu_attach_device_pasid(struct iommu_domain *domain,
33483362
struct iommu_group *group = dev->iommu_group;
33493363
struct group_device *device;
33503364
const struct iommu_ops *ops;
3365+
void *entry;
33513366
int ret;
33523367

33533368
if (!group)
@@ -3371,10 +3386,9 @@ int iommu_attach_device_pasid(struct iommu_domain *domain,
33713386
}
33723387
}
33733388

3374-
if (handle)
3375-
handle->domain = domain;
3389+
entry = iommu_make_pasid_array_entry(domain, handle);
33763390

3377-
ret = xa_insert(&group->pasid_array, pasid, handle, GFP_KERNEL);
3391+
ret = xa_insert(&group->pasid_array, pasid, entry, GFP_KERNEL);
33783392
if (ret)
33793393
goto out_unlock;
33803394

@@ -3454,13 +3468,17 @@ struct iommu_attach_handle *
34543468
iommu_attach_handle_get(struct iommu_group *group, ioasid_t pasid, unsigned int type)
34553469
{
34563470
struct iommu_attach_handle *handle;
3471+
void *entry;
34573472

34583473
xa_lock(&group->pasid_array);
3459-
handle = xa_load(&group->pasid_array, pasid);
3460-
if (!handle)
3474+
entry = xa_load(&group->pasid_array, pasid);
3475+
if (!entry || xa_pointer_tag(entry) != IOMMU_PASID_ARRAY_HANDLE) {
34613476
handle = ERR_PTR(-ENOENT);
3462-
else if (type && handle->domain->type != type)
3463-
handle = ERR_PTR(-EBUSY);
3477+
} else {
3478+
handle = xa_untag_pointer(entry);
3479+
if (type && handle->domain->type != type)
3480+
handle = ERR_PTR(-EBUSY);
3481+
}
34643482
xa_unlock(&group->pasid_array);
34653483

34663484
return handle;
@@ -3483,14 +3501,15 @@ int iommu_attach_group_handle(struct iommu_domain *domain,
34833501
struct iommu_group *group,
34843502
struct iommu_attach_handle *handle)
34853503
{
3504+
void *entry;
34863505
int ret;
34873506

34883507
if (!handle)
34893508
return -EINVAL;
34903509

34913510
mutex_lock(&group->mutex);
3492-
handle->domain = domain;
3493-
ret = xa_insert(&group->pasid_array, IOMMU_NO_PASID, handle, GFP_KERNEL);
3511+
entry = iommu_make_pasid_array_entry(domain, handle);
3512+
ret = xa_insert(&group->pasid_array, IOMMU_NO_PASID, entry, GFP_KERNEL);
34943513
if (ret)
34953514
goto err_unlock;
34963515

@@ -3543,14 +3562,14 @@ int iommu_replace_group_handle(struct iommu_group *group,
35433562
struct iommu_domain *new_domain,
35443563
struct iommu_attach_handle *handle)
35453564
{
3546-
void *curr;
3565+
void *curr, *entry;
35473566
int ret;
35483567

35493568
if (!new_domain || !handle)
35503569
return -EINVAL;
35513570

35523571
mutex_lock(&group->mutex);
3553-
handle->domain = new_domain;
3572+
entry = iommu_make_pasid_array_entry(new_domain, handle);
35543573
ret = xa_reserve(&group->pasid_array, IOMMU_NO_PASID, GFP_KERNEL);
35553574
if (ret)
35563575
goto err_unlock;
@@ -3559,7 +3578,7 @@ int iommu_replace_group_handle(struct iommu_group *group,
35593578
if (ret)
35603579
goto err_release;
35613580

3562-
curr = xa_store(&group->pasid_array, IOMMU_NO_PASID, handle, GFP_KERNEL);
3581+
curr = xa_store(&group->pasid_array, IOMMU_NO_PASID, entry, GFP_KERNEL);
35633582
WARN_ON(xa_is_err(curr));
35643583

35653584
mutex_unlock(&group->mutex);

0 commit comments

Comments
 (0)