Skip to content

Commit

Permalink
iommu/arm-smmu-v3: Consolidate clearing a CD table entry
Browse files Browse the repository at this point in the history
A cleared entry is all 0's. Make arm_smmu_clear_cd() do this sequence.

If we are clearing an entry and for some reason it is not already
allocated in the CD table then something has gone wrong.

Remove case (5) from arm_smmu_write_ctx_desc().

Tested-by: Nicolin Chen <nicolinc@nvidia.com>
Tested-by: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com>
Reviewed-by: Michael Shavit <mshavit@google.com>
Reviewed-by: Nicolin Chen <nicolinc@nvidia.com>
Reviewed-by: Moritz Fischer <moritzf@google.com>
Reviewed-by: Mostafa Saleh <smostafa@google.com>
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
Link: https://lore.kernel.org/r/4-v9-5040dc602008+177d7-smmuv3_newapi_p2_jgg@nvidia.com
Signed-off-by: Will Deacon <will@kernel.org>
  • Loading branch information
Jason Gunthorpe authored and Will Deacon committed May 1, 2024
1 parent e9d1e4f commit af8f0b8
Show file tree
Hide file tree
Showing 3 changed files with 18 additions and 11 deletions.
2 changes: 1 addition & 1 deletion drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c
Original file line number Diff line number Diff line change
Expand Up @@ -569,7 +569,7 @@ void arm_smmu_sva_remove_dev_pasid(struct iommu_domain *domain,

mutex_lock(&sva_lock);

arm_smmu_write_ctx_desc(master, id, NULL);
arm_smmu_clear_cd(master, id);

list_for_each_entry(t, &master->bonds, list) {
if (t->mm == mm) {
Expand Down
26 changes: 16 additions & 10 deletions drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
Original file line number Diff line number Diff line change
Expand Up @@ -1310,6 +1310,19 @@ void arm_smmu_make_s1_cd(struct arm_smmu_cd *target,
target->data[3] = cpu_to_le64(cd->mair);
}

void arm_smmu_clear_cd(struct arm_smmu_master *master, ioasid_t ssid)
{
struct arm_smmu_cd target = {};
struct arm_smmu_cd *cdptr;

if (!master->cd_table.cdtab)
return;
cdptr = arm_smmu_get_cd_ptr(master, ssid);
if (WARN_ON(!cdptr))
return;
arm_smmu_write_cd_entry(master, ssid, cdptr, &target);
}

int arm_smmu_write_ctx_desc(struct arm_smmu_master *master, int ssid,
struct arm_smmu_ctx_desc *cd)
{
Expand All @@ -1320,7 +1333,6 @@ int arm_smmu_write_ctx_desc(struct arm_smmu_master *master, int ssid,
* (2) Install a secondary CD, for SID+SSID traffic.
* (4) Quiesce the context without clearing the valid bit. Disable
* translation, and ignore any translation fault.
* (5) Remove a secondary CD.
*/
u64 val;
struct arm_smmu_cd target;
Expand All @@ -1339,10 +1351,7 @@ int arm_smmu_write_ctx_desc(struct arm_smmu_master *master, int ssid,
target = *cd_table_entry;
val = le64_to_cpu(cdptr->data[0]);

if (!cd) { /* (5) */
memset(cdptr, 0, sizeof(*cdptr));
val = 0;
} else if (cd == &quiet_cd) { /* (4) */
if (cd == &quiet_cd) { /* (4) */
val &= ~(CTXDESC_CD_0_TCR_T0SZ | CTXDESC_CD_0_TCR_TG0 |
CTXDESC_CD_0_TCR_IRGN0 | CTXDESC_CD_0_TCR_ORGN0 |
CTXDESC_CD_0_TCR_SH0);
Expand Down Expand Up @@ -2674,9 +2683,7 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)
case ARM_SMMU_DOMAIN_S2:
arm_smmu_make_s2_domain_ste(&target, master, smmu_domain);
arm_smmu_install_ste_for_dev(master, &target);
if (master->cd_table.cdtab)
arm_smmu_write_ctx_desc(master, IOMMU_NO_PASID,
NULL);
arm_smmu_clear_cd(master, IOMMU_NO_PASID);
break;
}

Expand Down Expand Up @@ -2724,8 +2731,7 @@ static int arm_smmu_attach_dev_ste(struct device *dev,
* arm_smmu_domain->devices to avoid races updating the same context
* descriptor from arm_smmu_share_asid().
*/
if (master->cd_table.cdtab)
arm_smmu_write_ctx_desc(master, IOMMU_NO_PASID, NULL);
arm_smmu_clear_cd(master, IOMMU_NO_PASID);
return 0;
}

Expand Down
1 change: 1 addition & 0 deletions drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
Original file line number Diff line number Diff line change
Expand Up @@ -751,6 +751,7 @@ extern struct xarray arm_smmu_asid_xa;
extern struct mutex arm_smmu_asid_lock;
extern struct arm_smmu_ctx_desc quiet_cd;

void arm_smmu_clear_cd(struct arm_smmu_master *master, ioasid_t ssid);
struct arm_smmu_cd *arm_smmu_get_cd_ptr(struct arm_smmu_master *master,
u32 ssid);
void arm_smmu_make_s1_cd(struct arm_smmu_cd *target,
Expand Down

0 comments on commit af8f0b8

Please sign in to comment.