@@ -144,6 +144,14 @@ static void arm_smmu_v3_test_ste_expect_transition(
144
144
KUNIT_EXPECT_MEMEQ (test , target -> data , cur_copy .data , sizeof (cur_copy ));
145
145
}
146
146
147
+ static void arm_smmu_v3_test_ste_expect_non_hitless_transition (
148
+ struct kunit * test , const struct arm_smmu_ste * cur ,
149
+ const struct arm_smmu_ste * target , unsigned int num_syncs_expected )
150
+ {
151
+ arm_smmu_v3_test_ste_expect_transition (test , cur , target ,
152
+ num_syncs_expected , false);
153
+ }
154
+
147
155
static void arm_smmu_v3_test_ste_expect_hitless_transition (
148
156
struct kunit * test , const struct arm_smmu_ste * cur ,
149
157
const struct arm_smmu_ste * target , unsigned int num_syncs_expected )
@@ -155,6 +163,7 @@ static void arm_smmu_v3_test_ste_expect_hitless_transition(
155
163
static const dma_addr_t fake_cdtab_dma_addr = 0xF0F0F0F0F0F0 ;
156
164
157
165
static void arm_smmu_test_make_cdtable_ste (struct arm_smmu_ste * ste ,
166
+ unsigned int s1dss ,
158
167
const dma_addr_t dma_addr )
159
168
{
160
169
struct arm_smmu_master master = {
@@ -164,7 +173,7 @@ static void arm_smmu_test_make_cdtable_ste(struct arm_smmu_ste *ste,
164
173
.smmu = & smmu ,
165
174
};
166
175
167
- arm_smmu_make_cdtable_ste (ste , & master , true, STRTAB_STE_1_S1DSS_SSID0 );
176
+ arm_smmu_make_cdtable_ste (ste , & master , true, s1dss );
168
177
}
169
178
170
179
static void arm_smmu_v3_write_ste_test_bypass_to_abort (struct kunit * test )
@@ -194,7 +203,8 @@ static void arm_smmu_v3_write_ste_test_cdtable_to_abort(struct kunit *test)
194
203
{
195
204
struct arm_smmu_ste ste ;
196
205
197
- arm_smmu_test_make_cdtable_ste (& ste , fake_cdtab_dma_addr );
206
+ arm_smmu_test_make_cdtable_ste (& ste , STRTAB_STE_1_S1DSS_SSID0 ,
207
+ fake_cdtab_dma_addr );
198
208
arm_smmu_v3_test_ste_expect_hitless_transition (test , & ste , & abort_ste ,
199
209
NUM_EXPECTED_SYNCS (2 ));
200
210
}
@@ -203,7 +213,8 @@ static void arm_smmu_v3_write_ste_test_abort_to_cdtable(struct kunit *test)
203
213
{
204
214
struct arm_smmu_ste ste ;
205
215
206
- arm_smmu_test_make_cdtable_ste (& ste , fake_cdtab_dma_addr );
216
+ arm_smmu_test_make_cdtable_ste (& ste , STRTAB_STE_1_S1DSS_SSID0 ,
217
+ fake_cdtab_dma_addr );
207
218
arm_smmu_v3_test_ste_expect_hitless_transition (test , & abort_ste , & ste ,
208
219
NUM_EXPECTED_SYNCS (2 ));
209
220
}
@@ -212,7 +223,8 @@ static void arm_smmu_v3_write_ste_test_cdtable_to_bypass(struct kunit *test)
212
223
{
213
224
struct arm_smmu_ste ste ;
214
225
215
- arm_smmu_test_make_cdtable_ste (& ste , fake_cdtab_dma_addr );
226
+ arm_smmu_test_make_cdtable_ste (& ste , STRTAB_STE_1_S1DSS_SSID0 ,
227
+ fake_cdtab_dma_addr );
216
228
arm_smmu_v3_test_ste_expect_hitless_transition (test , & ste , & bypass_ste ,
217
229
NUM_EXPECTED_SYNCS (3 ));
218
230
}
@@ -221,11 +233,54 @@ static void arm_smmu_v3_write_ste_test_bypass_to_cdtable(struct kunit *test)
221
233
{
222
234
struct arm_smmu_ste ste ;
223
235
224
- arm_smmu_test_make_cdtable_ste (& ste , fake_cdtab_dma_addr );
236
+ arm_smmu_test_make_cdtable_ste (& ste , STRTAB_STE_1_S1DSS_SSID0 ,
237
+ fake_cdtab_dma_addr );
225
238
arm_smmu_v3_test_ste_expect_hitless_transition (test , & bypass_ste , & ste ,
226
239
NUM_EXPECTED_SYNCS (3 ));
227
240
}
228
241
242
+ static void arm_smmu_v3_write_ste_test_cdtable_s1dss_change (struct kunit * test )
243
+ {
244
+ struct arm_smmu_ste ste ;
245
+ struct arm_smmu_ste s1dss_bypass ;
246
+
247
+ arm_smmu_test_make_cdtable_ste (& ste , STRTAB_STE_1_S1DSS_SSID0 ,
248
+ fake_cdtab_dma_addr );
249
+ arm_smmu_test_make_cdtable_ste (& s1dss_bypass , STRTAB_STE_1_S1DSS_BYPASS ,
250
+ fake_cdtab_dma_addr );
251
+
252
+ /*
253
+ * Flipping s1dss on a CD table STE only involves changes to the second
254
+ * qword of an STE and can be done in a single write.
255
+ */
256
+ arm_smmu_v3_test_ste_expect_hitless_transition (
257
+ test , & ste , & s1dss_bypass , NUM_EXPECTED_SYNCS (1 ));
258
+ arm_smmu_v3_test_ste_expect_hitless_transition (
259
+ test , & s1dss_bypass , & ste , NUM_EXPECTED_SYNCS (1 ));
260
+ }
261
+
262
+ static void
263
+ arm_smmu_v3_write_ste_test_s1dssbypass_to_stebypass (struct kunit * test )
264
+ {
265
+ struct arm_smmu_ste s1dss_bypass ;
266
+
267
+ arm_smmu_test_make_cdtable_ste (& s1dss_bypass , STRTAB_STE_1_S1DSS_BYPASS ,
268
+ fake_cdtab_dma_addr );
269
+ arm_smmu_v3_test_ste_expect_hitless_transition (
270
+ test , & s1dss_bypass , & bypass_ste , NUM_EXPECTED_SYNCS (2 ));
271
+ }
272
+
273
+ static void
274
+ arm_smmu_v3_write_ste_test_stebypass_to_s1dssbypass (struct kunit * test )
275
+ {
276
+ struct arm_smmu_ste s1dss_bypass ;
277
+
278
+ arm_smmu_test_make_cdtable_ste (& s1dss_bypass , STRTAB_STE_1_S1DSS_BYPASS ,
279
+ fake_cdtab_dma_addr );
280
+ arm_smmu_v3_test_ste_expect_hitless_transition (
281
+ test , & bypass_ste , & s1dss_bypass , NUM_EXPECTED_SYNCS (2 ));
282
+ }
283
+
229
284
static void arm_smmu_test_make_s2_ste (struct arm_smmu_ste * ste ,
230
285
bool ats_enabled )
231
286
{
@@ -285,6 +340,48 @@ static void arm_smmu_v3_write_ste_test_bypass_to_s2(struct kunit *test)
285
340
NUM_EXPECTED_SYNCS (2 ));
286
341
}
287
342
343
+ static void arm_smmu_v3_write_ste_test_s1_to_s2 (struct kunit * test )
344
+ {
345
+ struct arm_smmu_ste s1_ste ;
346
+ struct arm_smmu_ste s2_ste ;
347
+
348
+ arm_smmu_test_make_cdtable_ste (& s1_ste , STRTAB_STE_1_S1DSS_SSID0 ,
349
+ fake_cdtab_dma_addr );
350
+ arm_smmu_test_make_s2_ste (& s2_ste , true);
351
+ arm_smmu_v3_test_ste_expect_hitless_transition (test , & s1_ste , & s2_ste ,
352
+ NUM_EXPECTED_SYNCS (3 ));
353
+ }
354
+
355
+ static void arm_smmu_v3_write_ste_test_s2_to_s1 (struct kunit * test )
356
+ {
357
+ struct arm_smmu_ste s1_ste ;
358
+ struct arm_smmu_ste s2_ste ;
359
+
360
+ arm_smmu_test_make_cdtable_ste (& s1_ste , STRTAB_STE_1_S1DSS_SSID0 ,
361
+ fake_cdtab_dma_addr );
362
+ arm_smmu_test_make_s2_ste (& s2_ste , true);
363
+ arm_smmu_v3_test_ste_expect_hitless_transition (test , & s2_ste , & s1_ste ,
364
+ NUM_EXPECTED_SYNCS (3 ));
365
+ }
366
+
367
+ static void arm_smmu_v3_write_ste_test_non_hitless (struct kunit * test )
368
+ {
369
+ struct arm_smmu_ste ste ;
370
+ struct arm_smmu_ste ste_2 ;
371
+
372
+ /*
373
+ * Although no flow resembles this in practice, one way to force an STE
374
+ * update to be non-hitless is to change its CD table pointer as well as
375
+ * s1 dss field in the same update.
376
+ */
377
+ arm_smmu_test_make_cdtable_ste (& ste , STRTAB_STE_1_S1DSS_SSID0 ,
378
+ fake_cdtab_dma_addr );
379
+ arm_smmu_test_make_cdtable_ste (& ste_2 , STRTAB_STE_1_S1DSS_BYPASS ,
380
+ 0x4B4B4b4B4B );
381
+ arm_smmu_v3_test_ste_expect_non_hitless_transition (
382
+ test , & ste , & ste_2 , NUM_EXPECTED_SYNCS (3 ));
383
+ }
384
+
288
385
static void arm_smmu_v3_test_cd_expect_transition (
289
386
struct kunit * test , const struct arm_smmu_cd * cur ,
290
387
const struct arm_smmu_cd * target , unsigned int num_syncs_expected ,
@@ -438,10 +535,16 @@ static struct kunit_case arm_smmu_v3_test_cases[] = {
438
535
KUNIT_CASE (arm_smmu_v3_write_ste_test_abort_to_cdtable ),
439
536
KUNIT_CASE (arm_smmu_v3_write_ste_test_cdtable_to_bypass ),
440
537
KUNIT_CASE (arm_smmu_v3_write_ste_test_bypass_to_cdtable ),
538
+ KUNIT_CASE (arm_smmu_v3_write_ste_test_cdtable_s1dss_change ),
539
+ KUNIT_CASE (arm_smmu_v3_write_ste_test_s1dssbypass_to_stebypass ),
540
+ KUNIT_CASE (arm_smmu_v3_write_ste_test_stebypass_to_s1dssbypass ),
441
541
KUNIT_CASE (arm_smmu_v3_write_ste_test_s2_to_abort ),
442
542
KUNIT_CASE (arm_smmu_v3_write_ste_test_abort_to_s2 ),
443
543
KUNIT_CASE (arm_smmu_v3_write_ste_test_s2_to_bypass ),
444
544
KUNIT_CASE (arm_smmu_v3_write_ste_test_bypass_to_s2 ),
545
+ KUNIT_CASE (arm_smmu_v3_write_ste_test_s1_to_s2 ),
546
+ KUNIT_CASE (arm_smmu_v3_write_ste_test_s2_to_s1 ),
547
+ KUNIT_CASE (arm_smmu_v3_write_ste_test_non_hitless ),
445
548
KUNIT_CASE (arm_smmu_v3_write_cd_test_s1_clear ),
446
549
KUNIT_CASE (arm_smmu_v3_write_cd_test_s1_change_asid ),
447
550
KUNIT_CASE (arm_smmu_v3_write_cd_test_sva_clear ),
0 commit comments