Skip to content

Commit d2e053d

Browse files
jgunthorpewilldeacon
authored andcommitted
iommu/arm-smmu-v3: Put writing the context descriptor in the right order
Get closer to the IOMMU API ideal that changes between domains can be hitless. The ordering for the CD table entry is not entirely clean from this perspective. When switching away from a STE with a CD table programmed in it we should write the new STE first, then clear any old data in the CD entry. If we are programming a CD table for the first time to a STE then the CD entry should be programmed before the STE is loaded. If we are replacing a CD table entry when the STE already points at the CD entry then we just need to do the make/break sequence. Lift this code out of arm_smmu_detach_dev() so it can all be sequenced properly. The only other caller is arm_smmu_release_device() and it is going to free the cdtable anyhow, so it doesn't matter what is in it. Reviewed-by: Michael Shavit <[email protected]> Reviewed-by: Nicolin Chen <[email protected]> Reviewed-by: Mostafa Saleh <[email protected]> Tested-by: Shameer Kolothum <[email protected]> Tested-by: Nicolin Chen <[email protected]> Tested-by: Moritz Fischer <[email protected]> Signed-off-by: Jason Gunthorpe <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Will Deacon <[email protected]>
1 parent 8c73c32 commit d2e053d

File tree

1 file changed

+20
-9
lines changed

1 file changed

+20
-9
lines changed

drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2522,14 +2522,6 @@ static void arm_smmu_detach_dev(struct arm_smmu_master *master)
25222522

25232523
master->domain = NULL;
25242524
master->ats_enabled = false;
2525-
/*
2526-
* Clearing the CD entry isn't strictly required to detach the domain
2527-
* since the table is uninstalled anyway, but it helps avoid confusion
2528-
* in the call to arm_smmu_write_ctx_desc on the next attach (which
2529-
* expects the entry to be empty).
2530-
*/
2531-
if (smmu_domain->stage == ARM_SMMU_DOMAIN_S1 && master->cd_table.cdtab)
2532-
arm_smmu_write_ctx_desc(master, IOMMU_NO_PASID, NULL);
25332525
}
25342526

25352527
static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)
@@ -2606,6 +2598,17 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)
26062598
master->domain = NULL;
26072599
goto out_list_del;
26082600
}
2601+
} else {
2602+
/*
2603+
* arm_smmu_write_ctx_desc() relies on the entry being
2604+
* invalid to work, clear any existing entry.
2605+
*/
2606+
ret = arm_smmu_write_ctx_desc(master, IOMMU_NO_PASID,
2607+
NULL);
2608+
if (ret) {
2609+
master->domain = NULL;
2610+
goto out_list_del;
2611+
}
26092612
}
26102613

26112614
ret = arm_smmu_write_ctx_desc(master, IOMMU_NO_PASID, &smmu_domain->cd);
@@ -2615,15 +2618,23 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)
26152618
}
26162619

26172620
arm_smmu_make_cdtable_ste(&target, master);
2621+
arm_smmu_install_ste_for_dev(master, &target);
26182622
break;
26192623
case ARM_SMMU_DOMAIN_S2:
26202624
arm_smmu_make_s2_domain_ste(&target, master, smmu_domain);
2625+
arm_smmu_install_ste_for_dev(master, &target);
2626+
if (master->cd_table.cdtab)
2627+
arm_smmu_write_ctx_desc(master, IOMMU_NO_PASID,
2628+
NULL);
26212629
break;
26222630
case ARM_SMMU_DOMAIN_BYPASS:
26232631
arm_smmu_make_bypass_ste(&target);
2632+
arm_smmu_install_ste_for_dev(master, &target);
2633+
if (master->cd_table.cdtab)
2634+
arm_smmu_write_ctx_desc(master, IOMMU_NO_PASID,
2635+
NULL);
26242636
break;
26252637
}
2626-
arm_smmu_install_ste_for_dev(master, &target);
26272638

26282639
arm_smmu_enable_ats(master);
26292640
goto out_unlock;

0 commit comments

Comments
 (0)