Skip to content

Commit bb857c5

Browse files
jgunthorpewilldeacon
authored andcommitted
iommu/arm-smmu-v3: Make domain_alloc_paging_flags() directly determine the S1/S2
The selection of S1/S2 is a bit indirect today, make domain_alloc_paging_flags() directly decode the flags and select the correct S1/S2 type. Directly reject flag combinations the HW doesn't support when processing the flags. Fix missing rejection of some flag combinations that are not supported today (ie NEST_PARENT | DIRTY_TRACKING) by using a switch statement to list out exactly the combinations that are currently supported. Move the determination of the stage out of arm_smmu_domain_finalise() and into both callers. As today the default stage is S1 if supported in HW. This makes arm_smmu_domain_alloc_paging_flags() self contained and no longer calling arm_smmu_domain_alloc_paging(). Signed-off-by: Jason Gunthorpe <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Will Deacon <[email protected]>
1 parent 48e7b8e commit bb857c5

File tree

1 file changed

+30
-12
lines changed

1 file changed

+30
-12
lines changed

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

Lines changed: 30 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2481,6 +2481,11 @@ static struct iommu_domain *arm_smmu_domain_alloc_paging(struct device *dev)
24812481
if (IS_ERR(smmu_domain))
24822482
return ERR_CAST(smmu_domain);
24832483

2484+
if (master->smmu->features & ARM_SMMU_FEAT_TRANS_S1)
2485+
smmu_domain->stage = ARM_SMMU_DOMAIN_S1;
2486+
else
2487+
smmu_domain->stage = ARM_SMMU_DOMAIN_S2;
2488+
24842489
ret = arm_smmu_domain_finalise(smmu_domain, master->smmu, 0);
24852490
if (ret) {
24862491
kfree(smmu_domain);
@@ -2554,12 +2559,6 @@ static int arm_smmu_domain_finalise(struct arm_smmu_domain *smmu_domain,
25542559
struct arm_smmu_domain *smmu_domain);
25552560
bool enable_dirty = flags & IOMMU_HWPT_ALLOC_DIRTY_TRACKING;
25562561

2557-
/* Restrict the stage to what we can actually support */
2558-
if (!(smmu->features & ARM_SMMU_FEAT_TRANS_S1))
2559-
smmu_domain->stage = ARM_SMMU_DOMAIN_S2;
2560-
if (!(smmu->features & ARM_SMMU_FEAT_TRANS_S2))
2561-
smmu_domain->stage = ARM_SMMU_DOMAIN_S1;
2562-
25632562
pgtbl_cfg = (struct io_pgtable_cfg) {
25642563
.pgsize_bitmap = smmu->pgsize_bitmap,
25652564
.coherent_walk = smmu->features & ARM_SMMU_FEAT_COHERENCY,
@@ -3231,6 +3230,7 @@ arm_smmu_domain_alloc_paging_flags(struct device *dev, u32 flags,
32313230
const struct iommu_user_data *user_data)
32323231
{
32333232
struct arm_smmu_master *master = dev_iommu_priv_get(dev);
3233+
struct arm_smmu_device *smmu = master->smmu;
32343234
const u32 PAGING_FLAGS = IOMMU_HWPT_ALLOC_DIRTY_TRACKING |
32353235
IOMMU_HWPT_ALLOC_PASID |
32363236
IOMMU_HWPT_ALLOC_NEST_PARENT;
@@ -3242,25 +3242,43 @@ arm_smmu_domain_alloc_paging_flags(struct device *dev, u32 flags,
32423242
if (user_data)
32433243
return ERR_PTR(-EOPNOTSUPP);
32443244

3245-
if (flags & IOMMU_HWPT_ALLOC_PASID)
3246-
return arm_smmu_domain_alloc_paging(dev);
3247-
32483245
smmu_domain = arm_smmu_domain_alloc();
32493246
if (IS_ERR(smmu_domain))
32503247
return ERR_CAST(smmu_domain);
32513248

3252-
if (flags & IOMMU_HWPT_ALLOC_NEST_PARENT) {
3253-
if (!(master->smmu->features & ARM_SMMU_FEAT_NESTING)) {
3249+
switch (flags) {
3250+
case 0:
3251+
/* Prefer S1 if available */
3252+
if (smmu->features & ARM_SMMU_FEAT_TRANS_S1)
3253+
smmu_domain->stage = ARM_SMMU_DOMAIN_S1;
3254+
else
3255+
smmu_domain->stage = ARM_SMMU_DOMAIN_S2;
3256+
break;
3257+
case IOMMU_HWPT_ALLOC_NEST_PARENT:
3258+
if (!(smmu->features & ARM_SMMU_FEAT_NESTING)) {
32543259
ret = -EOPNOTSUPP;
32553260
goto err_free;
32563261
}
32573262
smmu_domain->stage = ARM_SMMU_DOMAIN_S2;
32583263
smmu_domain->nest_parent = true;
3264+
break;
3265+
case IOMMU_HWPT_ALLOC_DIRTY_TRACKING:
3266+
case IOMMU_HWPT_ALLOC_DIRTY_TRACKING | IOMMU_HWPT_ALLOC_PASID:
3267+
case IOMMU_HWPT_ALLOC_PASID:
3268+
if (!(smmu->features & ARM_SMMU_FEAT_TRANS_S1)) {
3269+
ret = -EOPNOTSUPP;
3270+
goto err_free;
3271+
}
3272+
smmu_domain->stage = ARM_SMMU_DOMAIN_S1;
3273+
break;
3274+
default:
3275+
ret = -EOPNOTSUPP;
3276+
goto err_free;
32593277
}
32603278

32613279
smmu_domain->domain.type = IOMMU_DOMAIN_UNMANAGED;
32623280
smmu_domain->domain.ops = arm_smmu_ops.default_domain_ops;
3263-
ret = arm_smmu_domain_finalise(smmu_domain, master->smmu, flags);
3281+
ret = arm_smmu_domain_finalise(smmu_domain, smmu, flags);
32643282
if (ret)
32653283
goto err_free;
32663284
return &smmu_domain->domain;

0 commit comments

Comments
 (0)