[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