Skip to content

Commit

Permalink
NVIDIA: SAUCE: iommu/arm-smmu-v3: Allow default substream bypass with…
Browse files Browse the repository at this point in the history
… a pasid support

BugLink: https://bugs.launchpad.net/bugs/2031320

When an iommu_domain is set to IOMMU_DOMAIN_IDENTITY, the driver would
skip the allocation of a CD table and set the CONFIG field of the STE
to STRTAB_STE_0_CFG_BYPASS. This works well for devices that only have
one substream, i.e. PASID disabled.

However, there could be a use case, for a pasid capable device, that
allows bypassing the translation at the default substream while still
enabling the pasid feature, which means the driver should not skip the
allocation of a CD table nor simply bypass the CONFIG field. Instead,
the S1DSS field should be set to STRTAB_STE_1_S1DSS_BYPASS and the
SHCFG field should be set to STRTAB_STE_1_SHCFG_INCOMING.

Add s1dss in struct arm_smmu_s1_cfg, to allow a configuration in the
finalise() to support this use case.

Also, according to "13.5 Summary of attribute/permission configuration
fields" in the reference manual, the SHCFG field value is irrelevant.
So, set the SHCFG field of the STE always to STRTAB_STE_1_SHCFG_INCOMING
for simplification.

Signed-off-by: Nicolin Chen <[email protected]>
Reviewed-by: Pritesh Raithatha <[email protected]>
Signed-off-by: Jamie Nguyen <[email protected]>
Tested-by: Matt Ochs <[email protected]>
Acked-by: Brad Figg <[email protected]>
Acked-by: Jacob Martin <[email protected]>
Acked-by: Noah Wager <[email protected]>
Signed-off-by: Brad Figg <[email protected]>
  • Loading branch information
nicolinc authored and jacobmartin0 committed Aug 9, 2024
1 parent 5526c7a commit d620047
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 4 deletions.
20 changes: 16 additions & 4 deletions drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
Original file line number Diff line number Diff line change
Expand Up @@ -1138,6 +1138,12 @@ static int arm_smmu_alloc_cd_tables(struct arm_smmu_master *master)

cd_table->stall_enabled = master->stall_enabled;
cd_table->s1cdmax = master->ssid_bits;

if (master->domain->domain.type == IOMMU_DOMAIN_IDENTITY)
cd_table->s1dss = STRTAB_STE_1_S1DSS_BYPASS;
else
cd_table->s1dss = STRTAB_STE_1_S1DSS_SSID0;

max_contexts = 1 << cd_table->s1cdmax;

if (!(smmu->features & ARM_SMMU_FEAT_2_LVL_CDTAB) ||
Expand Down Expand Up @@ -1341,7 +1347,8 @@ static void arm_smmu_write_strtab_ent(struct arm_smmu_master *master, u32 sid,

BUG_ON(ste_live);
dst->data[1] = cpu_to_le64(
FIELD_PREP(STRTAB_STE_1_S1DSS, STRTAB_STE_1_S1DSS_SSID0) |
FIELD_PREP(STRTAB_STE_1_S1DSS, s1_cfg->s1dss) |
FIELD_PREP(STRTAB_STE_1_SHCFG, STRTAB_STE_1_SHCFG_INCOMING) |
FIELD_PREP(STRTAB_STE_1_S1CIR, STRTAB_STE_1_S1C_CACHE_WBRA) |
FIELD_PREP(STRTAB_STE_1_S1COR, STRTAB_STE_1_S1C_CACHE_WBRA) |
FIELD_PREP(STRTAB_STE_1_S1CSH, ARM_SMMU_SH_ISH) |
Expand Down Expand Up @@ -2138,7 +2145,8 @@ static int arm_smmu_domain_finalise_s2(struct arm_smmu_domain *smmu_domain,
return 0;
}

static int arm_smmu_domain_finalise(struct iommu_domain *domain)
static int arm_smmu_domain_finalise(struct iommu_domain *domain,
struct arm_smmu_master *master)
{
int ret;
unsigned long ias, oas;
Expand All @@ -2150,7 +2158,11 @@ static int arm_smmu_domain_finalise(struct iommu_domain *domain)
struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain);
struct arm_smmu_device *smmu = smmu_domain->smmu;

if (domain->type == IOMMU_DOMAIN_IDENTITY) {
/*
* A master with a pasid capability might need a CD table, so only set
* ARM_SMMU_DOMAIN_BYPASS if IOMMU_DOMAIN_IDENTITY and non-pasid master
*/
if (domain->type == IOMMU_DOMAIN_IDENTITY && !master->ssid_bits) {
smmu_domain->stage = ARM_SMMU_DOMAIN_BYPASS;
return 0;
}
Expand Down Expand Up @@ -2402,7 +2414,7 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)

if (!smmu_domain->smmu) {
smmu_domain->smmu = smmu;
ret = arm_smmu_domain_finalise(domain);
ret = arm_smmu_domain_finalise(domain, master);
if (ret)
smmu_domain->smmu = NULL;
} else if (smmu_domain->smmu != smmu)
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 @@ -601,6 +601,7 @@ struct arm_smmu_ctx_desc_cfg {
struct arm_smmu_l1_ctx_desc *l1_desc;
unsigned int num_l1_ents;
u8 s1fmt;
u8 s1dss;
/* log2 of the maximum number of CDs supported by this table */
u8 s1cdmax;
/* Whether CD entries in this table have the stall bit set. */
Expand Down

0 comments on commit d620047

Please sign in to comment.