[PATCH v2 5/8] iommu/arm-smmu-v3: Precompute the invalidation commands
Jason Gunthorpe
jgg at nvidia.com
Thu Jul 9 05:07:44 PDT 2026
On Tue, Jul 07, 2026 at 01:31:53PM -0700, Nicolin Chen wrote:
> > + tlbi->range.data0 =
> > + FIELD_PREP(CMDQ_TLBI_0_NUM,
> > + DIV_ROUND_UP_ULL(num_tg, 1ULL << scale) - 1) |
> > + FIELD_PREP(CMDQ_TLBI_0_SCALE, scale);
> > + tlbi->range.data1 = FIELD_PREP(CMDQ_TLBI_1_LEAF, tlbi->leaf_only) |
> > + FIELD_PREP(CMDQ_TLBI_1_TTL, ttl) |
> > + FIELD_PREP(CMDQ_TLBI_1_TG, tg_enc) |
> > + (cur_tg << tg_lg2);
>
> Could this be slightly cleaner:
>
> unsigned int num = 0, scale = 0;
> ...
> if (num_tg == 1) {
> if (!ttl)
> ttl = 3;
> goto build;
I'm not keen on gotos outside error unwind, but how about
+ tlbi->range.data1 =
+ FIELD_PREP(CMDQ_TLBI_1_LEAF, !tlbi->table_levels_bitmap) |
+ FIELD_PREP(CMDQ_TLBI_1_TG, tg_enc) | (cur_tg << tg_lg2);
+
/*
* SMMUv3 H.a Section 4.4.1.1: TG!=0, NUM==0, SCALE==0, TTL==0 is
* Reserved and causes CERROR_ILL. Single page uses NUM=0, SCALE=0 with
@@ -2472,11 +2476,7 @@ static void arm_smmu_tlbi_calc_range(struct arm_smmu_tlbi *tlbi,
if (WARN_ON(!ttl))
ttl = 3;
tlbi->range.data0 = 0;
- tlbi->range.data1 = FIELD_PREP(CMDQ_TLBI_1_LEAF,
- !tlbi->table_levels_bitmap) |
- FIELD_PREP(CMDQ_TLBI_1_TTL, ttl) |
- FIELD_PREP(CMDQ_TLBI_1_TG, tg_enc) |
- (cur_tg << tg_lg2);
+ tlbi->range.data1 |= FIELD_PREP(CMDQ_TLBI_1_TTL, ttl);
return;
}
@@ -2513,11 +2513,7 @@ static void arm_smmu_tlbi_calc_range(struct arm_smmu_tlbi *tlbi,
FIELD_PREP(CMDQ_TLBI_0_NUM,
DIV_ROUND_UP_ULL(num_tg, 1ULL << scale) - 1) |
FIELD_PREP(CMDQ_TLBI_0_SCALE, scale);
- tlbi->range.data1 =
- FIELD_PREP(CMDQ_TLBI_1_LEAF, !tlbi->table_levels_bitmap) |
- FIELD_PREP(CMDQ_TLBI_1_TTL, ttl) |
- FIELD_PREP(CMDQ_TLBI_1_TG, tg_enc) |
- (cur_tg << tg_lg2);
+ tlbi->range.data1 |= FIELD_PREP(CMDQ_TLBI_1_TTL, ttl);
}
Which removes most of the duplication
> > + if (invs->has_range_inv) {
> > + if (!tlbi.range.use_full_inv)
> > + arm_smmu_tlbi_calc_range(&tlbi);
> > + } else {
> > + tlbi.range.use_full_inv = true;
>
> I am a bit unsure about this line since invs has no RIL entry.
>
> Is it set for a defensive reason?
Yes, it should never matter but since the has_range_inv and per-smmu
tests are disjoint I included it defensively. I will replace it with a
comment.
Jason
More information about the linux-arm-kernel
mailing list