1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * Copyright © 2023 Intel Corporation
4 */
5
6 #include <linux/string.h>
7 #include <linux/xarray.h>
8
9 #include <drm/drm_drv.h>
10 #include <drm/drm_kunit_helpers.h>
11
12 #include <kunit/static_stub.h>
13 #include <kunit/test.h>
14
15 #include "regs/xe_gt_regs.h"
16 #include "regs/xe_reg_defs.h"
17 #include "xe_device.h"
18 #include "xe_device_types.h"
19 #include "xe_gt_mcr.h"
20 #include "xe_kunit_helpers.h"
21 #include "xe_pci_test.h"
22 #include "xe_reg_sr.h"
23 #include "xe_rtp.h"
24 #include "xe_rtp_test.h"
25
26 #define REGULAR_REG1 XE_REG(1)
27 #define REGULAR_REG2 XE_REG(2)
28 #define REGULAR_REG3 XE_REG(3)
29 #define REGULAR_REG4 XE_REG(4)
30 #define BAD_REGULAR_REG5 XE_REG(5)
31 #define MCR_REG1 XE_REG_MCR(1)
32 #define MCR_REG2 XE_REG_MCR(2)
33 #define MCR_REG3 XE_REG_MCR(3)
34 #define BAD_MCR_REG4 XE_REG_MCR(4)
35 #define MCR_REG5 XE_REG_MCR(5)
36 #define MASKED_REG1 XE_REG(1, XE_REG_OPTION_MASKED)
37
38 #undef XE_REG_MCR
39 #define XE_REG_MCR(...) XE_REG(__VA_ARGS__, .mcr = 1)
40
41 struct rtp_rules_test_case {
42 const char *name;
43 bool expected_match;
44 int expected_err;
45 const struct xe_rtp_rule *rules;
46 u8 n_rules;
47 };
48
49 struct rtp_to_sr_test_case {
50 const char *name;
51 struct xe_reg expected_reg;
52 u32 expected_set_bits;
53 u32 expected_clr_bits;
54 unsigned long expected_count_sr_entries;
55 unsigned int expected_sr_errors;
56 unsigned long expected_active;
57 const struct xe_rtp_table_sr table;
58 };
59
60 struct rtp_test_case {
61 const char *name;
62 unsigned long expected_active;
63 const struct xe_rtp_table table;
64 };
65
fake_xe_gt_mcr_check_reg(struct xe_gt * gt,struct xe_reg reg)66 static bool fake_xe_gt_mcr_check_reg(struct xe_gt *gt, struct xe_reg reg)
67 {
68 /*
69 * All supported platforms in this imaginary setup will always have REG4
70 * as a non-MCR register and REG5 as MCR, meaning that BAD_MCR_REG4 and
71 * BAD_REGULAR_REG5 represent programming errors to be captured by our
72 * tests.
73 */
74 if (reg.raw == BAD_REGULAR_REG5.raw)
75 return true;
76
77 if (reg.raw == BAD_MCR_REG4.raw)
78 return false;
79
80 return reg.mcr;
81 }
82
match_yes(const struct xe_device * xe,const struct xe_gt * gt,const struct xe_hw_engine * hwe)83 static bool match_yes(const struct xe_device *xe, const struct xe_gt *gt,
84 const struct xe_hw_engine *hwe)
85 {
86 return true;
87 }
88
match_no(const struct xe_device * xe,const struct xe_gt * gt,const struct xe_hw_engine * hwe)89 static bool match_no(const struct xe_device *xe, const struct xe_gt *gt,
90 const struct xe_hw_engine *hwe)
91 {
92 return false;
93 }
94
95 static const struct rtp_rules_test_case rtp_rules_cases[] = {
96 /*
97 * Single rules.
98 *
99 * TODO: Include other types of rules as well: GRAPHICS_VERSION(),
100 * MEDIA_VERSION(), etc.
101 */
102 {
103 .name = "no",
104 .expected_match = false,
105 XE_RTP_RULES(FUNC(match_no)),
106 },
107 {
108 .name = "yes",
109 .expected_match = true,
110 XE_RTP_RULES(FUNC(match_yes)),
111 },
112
113 /* Conjunctions with 2 operands. */
114 {
115 .name = "no-and-no",
116 .expected_match = false,
117 XE_RTP_RULES(FUNC(match_no), FUNC(match_no)),
118 },
119 {
120 .name = "no-and-yes",
121 .expected_match = false,
122 XE_RTP_RULES(FUNC(match_no), FUNC(match_yes)),
123 },
124 {
125 .name = "yes-and-no",
126 .expected_match = false,
127 XE_RTP_RULES(FUNC(match_yes), FUNC(match_no)),
128 },
129 {
130 .name = "yes-and-yes",
131 .expected_match = true,
132 XE_RTP_RULES(FUNC(match_yes), FUNC(match_yes)),
133 },
134
135 /* Disjunctions with 2 operands. */
136 {
137 .name = "no-or-no",
138 .expected_match = false,
139 XE_RTP_RULES(FUNC(match_no), OR, FUNC(match_no)),
140 },
141 {
142 .name = "no-or-yes",
143 .expected_match = true,
144 XE_RTP_RULES(FUNC(match_no), OR, FUNC(match_yes)),
145 },
146 {
147 .name = "yes-or-no",
148 .expected_match = true,
149 XE_RTP_RULES(FUNC(match_yes), OR, FUNC(match_no)),
150 },
151 {
152 .name = "yes-or-yes",
153 .expected_match = true,
154 XE_RTP_RULES(FUNC(match_yes), OR, FUNC(match_yes)),
155 },
156
157 /* Conjunction and disjunctions. */
158 {
159 .name = "no-yes-or-yes-no",
160 .expected_match = false,
161 XE_RTP_RULES(FUNC(match_no), FUNC(match_yes), OR,
162 FUNC(match_yes), FUNC(match_no)),
163 },
164 {
165 .name = "no-yes-or-yes-yes",
166 .expected_match = true,
167 XE_RTP_RULES(FUNC(match_no), FUNC(match_yes), OR,
168 FUNC(match_yes), FUNC(match_yes)),
169 },
170 {
171 .name = "yes-yes-or-no-yes",
172 .expected_match = true,
173 XE_RTP_RULES(FUNC(match_yes), FUNC(match_yes), OR,
174 FUNC(match_no), FUNC(match_yes)),
175 },
176 {
177 .name = "yes-yes-or-yes-yes",
178 .expected_match = true,
179 XE_RTP_RULES(FUNC(match_yes), FUNC(match_yes), OR,
180 FUNC(match_yes), FUNC(match_yes)),
181 },
182 {
183 .name = "no-no-or-yes-or-no",
184 .expected_match = true,
185 XE_RTP_RULES(FUNC(match_no), FUNC(match_no), OR,
186 FUNC(match_yes), OR,
187 FUNC(match_no)),
188 },
189
190 /* Syntax errors. */
191 {
192 .name = "or",
193 .expected_match = false,
194 .expected_err = -EINVAL,
195 XE_RTP_RULES(OR),
196 },
197 {
198 .name = "or-yes",
199 .expected_match = true,
200 .expected_err = -EINVAL,
201 XE_RTP_RULES(OR, FUNC(match_yes)),
202 },
203 {
204 .name = "or-no",
205 .expected_match = false,
206 .expected_err = -EINVAL,
207 XE_RTP_RULES(OR, FUNC(match_no)),
208 },
209 {
210 .name = "yes-or",
211 .expected_match = true,
212 .expected_err = -EINVAL,
213 XE_RTP_RULES(FUNC(match_yes), OR),
214 },
215 {
216 .name = "no-or",
217 .expected_match = false,
218 .expected_err = -EINVAL,
219 XE_RTP_RULES(FUNC(match_no), OR),
220 },
221 {
222 .name = "no-or-or-yes",
223 .expected_match = true,
224 .expected_err = -EINVAL,
225 XE_RTP_RULES(FUNC(match_no), OR, OR, FUNC(match_yes)),
226 },
227 {
228 .name = "yes-or-or-no",
229 .expected_match = true,
230 .expected_err = -EINVAL,
231 XE_RTP_RULES(FUNC(match_yes), OR, OR, FUNC(match_no)),
232 },
233 {
234 .name = "no-or-or-no",
235 .expected_match = false,
236 .expected_err = -EINVAL,
237 XE_RTP_RULES(FUNC(match_no), OR, OR, FUNC(match_no)),
238 },
239
240 /* No match because hwe is NULL. */
241 {
242 .name = "missing-context-engine-class",
243 .expected_match = false,
244 XE_RTP_RULES(ENGINE_CLASS(RENDER)),
245 },
246
247 /*
248 * Missing context (hwe==NULL) does not cause parsing to stop, hence we
249 * expect a match.
250 */
251 {
252 .name = "missing-context-engine-class-or-yes",
253 .expected_match = true,
254 XE_RTP_RULES(ENGINE_CLASS(RENDER), OR, FUNC(match_yes)),
255 },
256
257 /*
258 * Missing context (hwe==NULL) does not cause parsing to stop, hence we
259 * expect a syntax error.
260 */
261 {
262 .name = "missing-context-engine-class-or-or-yes",
263 .expected_match = true,
264 .expected_err = -EINVAL,
265 XE_RTP_RULES(ENGINE_CLASS(RENDER), OR, OR, FUNC(match_yes)),
266 },
267 };
268
xe_rtp_rules_tests(struct kunit * test)269 static void xe_rtp_rules_tests(struct kunit *test)
270 {
271 const struct rtp_rules_test_case *param = test->param_value;
272 struct xe_device *xe = test->priv;
273 struct xe_gt *gt = xe_device_get_root_tile(xe)->primary_gt;
274 int err;
275 bool match;
276
277 match = xe_rtp_rule_matches(xe, gt, NULL, param->rules, param->n_rules, &err);
278
279 KUNIT_EXPECT_EQ(test, match, param->expected_match);
280 KUNIT_EXPECT_EQ(test, err, param->expected_err);
281 }
282
bits_2_3_set(struct xe_gt * gt,struct xe_hw_engine * hwe)283 static u32 bits_2_3_set(struct xe_gt *gt, struct xe_hw_engine *hwe)
284 {
285 return REG_BIT(2) | REG_BIT(3);
286 }
287
288 static const struct rtp_to_sr_test_case rtp_to_sr_cases[] = {
289 {
290 .name = "coalesce-same-reg",
291 .expected_reg = REGULAR_REG1,
292 .expected_set_bits = REG_BIT(0) | REG_BIT(1),
293 .expected_clr_bits = REG_BIT(0) | REG_BIT(1),
294 .expected_active = BIT(0) | BIT(1),
295 .expected_count_sr_entries = 1,
296 /* Different bits on the same register: create a single entry */
297 .table = XE_RTP_TABLE_SR(
298 { XE_RTP_NAME("basic-1"),
299 XE_RTP_RULES(FUNC(match_yes)),
300 XE_RTP_ACTIONS(SET(REGULAR_REG1, REG_BIT(0)))
301 },
302 { XE_RTP_NAME("basic-2"),
303 XE_RTP_RULES(FUNC(match_yes)),
304 XE_RTP_ACTIONS(SET(REGULAR_REG1, REG_BIT(1)))
305 },
306 ),
307 },
308 {
309 .name = "coalesce-same-reg-literal-and-func",
310 .expected_reg = REGULAR_REG1,
311 .expected_set_bits = REG_BIT(0) | REG_BIT(1) | REG_BIT(2) | REG_BIT(3),
312 .expected_clr_bits = REG_BIT(0) | REG_BIT(1) | REG_BIT(2) | REG_BIT(3),
313 .expected_active = BIT(0) | BIT(1),
314 .expected_count_sr_entries = 1,
315 /* Different bits on the same register: create a single entry */
316 .table = XE_RTP_TABLE_SR(
317 { XE_RTP_NAME("basic-1"),
318 XE_RTP_RULES(FUNC(match_yes)),
319 XE_RTP_ACTIONS(FIELD_SET(REGULAR_REG1,
320 REG_BIT(0) | REG_BIT(1),
321 REG_BIT(0) | REG_BIT(1)))
322 },
323 { XE_RTP_NAME("basic-2"),
324 XE_RTP_RULES(FUNC(match_yes)),
325 XE_RTP_ACTIONS(FIELD_SET_FUNC(REGULAR_REG1,
326 REG_BIT(2) | REG_BIT(3),
327 bits_2_3_set))
328 },
329 ),
330 },
331 {
332 .name = "no-match-no-add",
333 .expected_reg = REGULAR_REG1,
334 .expected_set_bits = REG_BIT(0),
335 .expected_clr_bits = REG_BIT(0),
336 .expected_active = BIT(0),
337 .expected_count_sr_entries = 1,
338 /* Don't coalesce second entry since rules don't match */
339 .table = XE_RTP_TABLE_SR(
340 { XE_RTP_NAME("basic-1"),
341 XE_RTP_RULES(FUNC(match_yes)),
342 XE_RTP_ACTIONS(SET(REGULAR_REG1, REG_BIT(0)))
343 },
344 { XE_RTP_NAME("basic-2"),
345 XE_RTP_RULES(FUNC(match_no)),
346 XE_RTP_ACTIONS(SET(REGULAR_REG1, REG_BIT(1)))
347 },
348 ),
349 },
350 {
351 .name = "two-regs-two-entries",
352 .expected_reg = REGULAR_REG1,
353 .expected_set_bits = REG_BIT(0),
354 .expected_clr_bits = REG_BIT(0),
355 .expected_active = BIT(0) | BIT(1),
356 .expected_count_sr_entries = 2,
357 /* Same bits on different registers are not coalesced */
358 .table = XE_RTP_TABLE_SR(
359 { XE_RTP_NAME("basic-1"),
360 XE_RTP_RULES(FUNC(match_yes)),
361 XE_RTP_ACTIONS(SET(REGULAR_REG1, REG_BIT(0)))
362 },
363 { XE_RTP_NAME("basic-2"),
364 XE_RTP_RULES(FUNC(match_yes)),
365 XE_RTP_ACTIONS(SET(REGULAR_REG2, REG_BIT(0)))
366 },
367 ),
368 },
369 {
370 .name = "clr-one-set-other",
371 .expected_reg = REGULAR_REG1,
372 .expected_set_bits = REG_BIT(0),
373 .expected_clr_bits = REG_BIT(1) | REG_BIT(0),
374 .expected_active = BIT(0) | BIT(1),
375 .expected_count_sr_entries = 1,
376 /* Check clr vs set actions on different bits */
377 .table = XE_RTP_TABLE_SR(
378 { XE_RTP_NAME("basic-1"),
379 XE_RTP_RULES(FUNC(match_yes)),
380 XE_RTP_ACTIONS(SET(REGULAR_REG1, REG_BIT(0)))
381 },
382 { XE_RTP_NAME("basic-2"),
383 XE_RTP_RULES(FUNC(match_yes)),
384 XE_RTP_ACTIONS(CLR(REGULAR_REG1, REG_BIT(1)))
385 },
386 ),
387 },
388 {
389 #define TEMP_MASK REG_GENMASK(10, 8)
390 #define TEMP_FIELD REG_FIELD_PREP(TEMP_MASK, 2)
391 .name = "set-field",
392 .expected_reg = REGULAR_REG1,
393 .expected_set_bits = TEMP_FIELD,
394 .expected_clr_bits = TEMP_MASK,
395 .expected_active = BIT(0),
396 .expected_count_sr_entries = 1,
397 /* Check FIELD_SET works */
398 .table = XE_RTP_TABLE_SR(
399 { XE_RTP_NAME("basic-1"),
400 XE_RTP_RULES(FUNC(match_yes)),
401 XE_RTP_ACTIONS(FIELD_SET(REGULAR_REG1,
402 TEMP_MASK, TEMP_FIELD))
403 },
404 ),
405 #undef TEMP_MASK
406 #undef TEMP_FIELD
407 },
408 {
409 .name = "conflict-duplicate",
410 .expected_reg = REGULAR_REG1,
411 .expected_set_bits = REG_BIT(0),
412 .expected_clr_bits = REG_BIT(0),
413 .expected_active = BIT(0) | BIT(1),
414 .expected_count_sr_entries = 1,
415 .expected_sr_errors = 1,
416 .table = XE_RTP_TABLE_SR(
417 { XE_RTP_NAME("basic-1"),
418 XE_RTP_RULES(FUNC(match_yes)),
419 XE_RTP_ACTIONS(SET(REGULAR_REG1, REG_BIT(0)))
420 },
421 /* drop: setting same values twice */
422 { XE_RTP_NAME("basic-2"),
423 XE_RTP_RULES(FUNC(match_yes)),
424 XE_RTP_ACTIONS(SET(REGULAR_REG1, REG_BIT(0)))
425 },
426 ),
427 },
428 {
429 .name = "conflict-not-disjoint",
430 .expected_reg = REGULAR_REG1,
431 .expected_set_bits = REG_BIT(0),
432 .expected_clr_bits = REG_BIT(0),
433 .expected_active = BIT(0) | BIT(1),
434 .expected_count_sr_entries = 1,
435 .expected_sr_errors = 1,
436 .table = XE_RTP_TABLE_SR(
437 { XE_RTP_NAME("basic-1"),
438 XE_RTP_RULES(FUNC(match_yes)),
439 XE_RTP_ACTIONS(SET(REGULAR_REG1, REG_BIT(0)))
440 },
441 /* drop: bits are not disjoint with previous entries */
442 { XE_RTP_NAME("basic-2"),
443 XE_RTP_RULES(FUNC(match_yes)),
444 XE_RTP_ACTIONS(CLR(REGULAR_REG1, REG_GENMASK(1, 0)))
445 },
446 ),
447 },
448 {
449 .name = "conflict-not-disjoint-literal-and-func",
450 .expected_reg = REGULAR_REG1,
451 .expected_set_bits = REG_BIT(1) | REG_BIT(2),
452 .expected_clr_bits = REG_BIT(1) | REG_BIT(2),
453 .expected_active = BIT(0) | BIT(1),
454 .expected_count_sr_entries = 1,
455 .expected_sr_errors = 1,
456 .table = XE_RTP_TABLE_SR(
457 { XE_RTP_NAME("basic-1"),
458 XE_RTP_RULES(FUNC(match_yes)),
459 XE_RTP_ACTIONS(FIELD_SET(REGULAR_REG1,
460 REG_BIT(1) | REG_BIT(2),
461 REG_BIT(1) | REG_BIT(2)))
462 },
463 /* drop: bits are not disjoint with previous entries */
464 { XE_RTP_NAME("basic-2"),
465 XE_RTP_RULES(FUNC(match_yes)),
466 XE_RTP_ACTIONS(FIELD_SET_FUNC(REGULAR_REG1,
467 REG_BIT(2) | REG_BIT(3),
468 bits_2_3_set))
469 },
470 ),
471 },
472 {
473 .name = "conflict-reg-type",
474 .expected_reg = REGULAR_REG1,
475 .expected_set_bits = REG_BIT(0),
476 .expected_clr_bits = REG_BIT(0),
477 .expected_active = BIT(0) | BIT(1) | BIT(2),
478 .expected_count_sr_entries = 1,
479 .expected_sr_errors = 2,
480 .table = XE_RTP_TABLE_SR(
481 { XE_RTP_NAME("basic-1"),
482 XE_RTP_RULES(FUNC(match_yes)),
483 XE_RTP_ACTIONS(SET(REGULAR_REG1, REG_BIT(0)))
484 },
485 /* drop: regular vs MCR */
486 { XE_RTP_NAME("basic-2"),
487 XE_RTP_RULES(FUNC(match_yes)),
488 XE_RTP_ACTIONS(SET(MCR_REG1, REG_BIT(1)))
489 },
490 /* drop: regular vs masked */
491 { XE_RTP_NAME("basic-3"),
492 XE_RTP_RULES(FUNC(match_yes)),
493 XE_RTP_ACTIONS(SET(MASKED_REG1, REG_BIT(0)))
494 },
495 ),
496 },
497 {
498 .name = "bad-mcr-reg-forced-to-regular",
499 .expected_reg = REGULAR_REG4,
500 .expected_set_bits = REG_BIT(0),
501 .expected_clr_bits = REG_BIT(0),
502 .expected_active = BIT(0),
503 .expected_count_sr_entries = 1,
504 .expected_sr_errors = 1,
505 .table = XE_RTP_TABLE_SR(
506 { XE_RTP_NAME("bad-mcr-regular-reg"),
507 XE_RTP_RULES(FUNC(match_yes)),
508 XE_RTP_ACTIONS(SET(BAD_MCR_REG4, REG_BIT(0)))
509 },
510 ),
511 },
512 {
513 .name = "bad-regular-reg-forced-to-mcr",
514 .expected_reg = MCR_REG5,
515 .expected_set_bits = REG_BIT(0),
516 .expected_clr_bits = REG_BIT(0),
517 .expected_active = BIT(0),
518 .expected_count_sr_entries = 1,
519 .expected_sr_errors = 1,
520 .table = XE_RTP_TABLE_SR(
521 { XE_RTP_NAME("bad-regular-reg"),
522 XE_RTP_RULES(FUNC(match_yes)),
523 XE_RTP_ACTIONS(SET(BAD_REGULAR_REG5, REG_BIT(0)))
524 },
525 ),
526 },
527 };
528
xe_rtp_process_to_sr_tests(struct kunit * test)529 static void xe_rtp_process_to_sr_tests(struct kunit *test)
530 {
531 const struct rtp_to_sr_test_case *param = test->param_value;
532 struct xe_device *xe = test->priv;
533 struct xe_gt *gt = xe_device_get_root_tile(xe)->primary_gt;
534 struct xe_reg_sr *reg_sr = >->reg_sr;
535 const struct xe_reg_sr_entry *sre, *sr_entry = NULL;
536 struct xe_rtp_process_ctx ctx = XE_RTP_PROCESS_CTX_INITIALIZER(gt);
537 unsigned long idx, count_sr_entries = 0, active = 0;
538
539 xe_reg_sr_init(reg_sr, "xe_rtp_to_sr_tests", xe);
540
541 xe_rtp_process_ctx_enable_active_tracking(&ctx, &active, param->table.n_entries);
542 xe_rtp_process_to_sr(&ctx, ¶m->table, reg_sr, false);
543
544 xa_for_each(®_sr->xa, idx, sre) {
545 if (idx == param->expected_reg.addr)
546 sr_entry = sre;
547
548 count_sr_entries++;
549 }
550
551 KUNIT_EXPECT_EQ(test, active, param->expected_active);
552
553 KUNIT_EXPECT_EQ(test, count_sr_entries, param->expected_count_sr_entries);
554 if (count_sr_entries) {
555 KUNIT_EXPECT_EQ(test, sr_entry->clr_bits, param->expected_clr_bits);
556 KUNIT_EXPECT_EQ(test, sr_entry->set_bits, param->expected_set_bits);
557 KUNIT_EXPECT_EQ(test, sr_entry->reg.raw, param->expected_reg.raw);
558 } else {
559 KUNIT_EXPECT_NULL(test, sr_entry);
560 }
561
562 KUNIT_EXPECT_EQ(test, reg_sr->errors, param->expected_sr_errors);
563 }
564
565 /*
566 * Entries below follow the logic used with xe_wa_oob.rules:
567 * 1) Entries with empty name are OR'ed: all entries marked active since the
568 * last entry with a name
569 * 2) There are no action associated with rules
570 */
571 static const struct rtp_test_case rtp_cases[] = {
572 {
573 .name = "active1",
574 .expected_active = BIT(0),
575 .table = XE_RTP_TABLE(
576 { XE_RTP_NAME("r1"),
577 XE_RTP_RULES(FUNC(match_yes)),
578 },
579 ),
580 },
581 {
582 .name = "active2",
583 .expected_active = BIT(0) | BIT(1),
584 .table = XE_RTP_TABLE(
585 { XE_RTP_NAME("r1"),
586 XE_RTP_RULES(FUNC(match_yes)),
587 },
588 { XE_RTP_NAME("r2"),
589 XE_RTP_RULES(FUNC(match_yes)),
590 },
591 ),
592 },
593 {
594 .name = "active-inactive",
595 .expected_active = BIT(0),
596 .table = XE_RTP_TABLE(
597 { XE_RTP_NAME("r1"),
598 XE_RTP_RULES(FUNC(match_yes)),
599 },
600 { XE_RTP_NAME("r2"),
601 XE_RTP_RULES(FUNC(match_no)),
602 },
603 ),
604 },
605 {
606 .name = "inactive-active",
607 .expected_active = BIT(1),
608 .table = XE_RTP_TABLE(
609 { XE_RTP_NAME("r1"),
610 XE_RTP_RULES(FUNC(match_no)),
611 },
612 { XE_RTP_NAME("r2"),
613 XE_RTP_RULES(FUNC(match_yes)),
614 },
615 ),
616 },
617 {
618 .name = "inactive-active-inactive",
619 .expected_active = BIT(1),
620 .table = XE_RTP_TABLE(
621 { XE_RTP_NAME("r1"),
622 XE_RTP_RULES(FUNC(match_no)),
623 },
624 { XE_RTP_NAME("r2"),
625 XE_RTP_RULES(FUNC(match_yes)),
626 },
627 { XE_RTP_NAME("r3"),
628 XE_RTP_RULES(FUNC(match_no)),
629 },
630 ),
631 },
632 {
633 .name = "inactive-inactive-inactive",
634 .expected_active = 0,
635 .table = XE_RTP_TABLE(
636 { XE_RTP_NAME("r1"),
637 XE_RTP_RULES(FUNC(match_no)),
638 },
639 { XE_RTP_NAME("r2"),
640 XE_RTP_RULES(FUNC(match_no)),
641 },
642 { XE_RTP_NAME("r3"),
643 XE_RTP_RULES(FUNC(match_no)),
644 },
645 ),
646 },
647 };
648
xe_rtp_process_tests(struct kunit * test)649 static void xe_rtp_process_tests(struct kunit *test)
650 {
651 const struct rtp_test_case *param = test->param_value;
652 struct xe_device *xe = test->priv;
653 struct xe_gt *gt = xe_device_get_root_tile(xe)->primary_gt;
654 struct xe_rtp_process_ctx ctx = XE_RTP_PROCESS_CTX_INITIALIZER(gt);
655 unsigned long active = 0;
656
657 xe_rtp_process_ctx_enable_active_tracking(&ctx, &active, param->table.n_entries);
658 xe_rtp_process(&ctx, ¶m->table);
659
660 KUNIT_EXPECT_EQ(test, active, param->expected_active);
661 }
662
rtp_rules_desc(const struct rtp_rules_test_case * t,char * desc)663 static void rtp_rules_desc(const struct rtp_rules_test_case *t, char *desc)
664 {
665 strscpy(desc, t->name, KUNIT_PARAM_DESC_SIZE);
666 }
667
668 KUNIT_ARRAY_PARAM(rtp_rules, rtp_rules_cases, rtp_rules_desc);
669
rtp_to_sr_desc(const struct rtp_to_sr_test_case * t,char * desc)670 static void rtp_to_sr_desc(const struct rtp_to_sr_test_case *t, char *desc)
671 {
672 strscpy(desc, t->name, KUNIT_PARAM_DESC_SIZE);
673 }
674
675 KUNIT_ARRAY_PARAM(rtp_to_sr, rtp_to_sr_cases, rtp_to_sr_desc);
676
rtp_desc(const struct rtp_test_case * t,char * desc)677 static void rtp_desc(const struct rtp_test_case *t, char *desc)
678 {
679 strscpy(desc, t->name, KUNIT_PARAM_DESC_SIZE);
680 }
681
682 KUNIT_ARRAY_PARAM(rtp, rtp_cases, rtp_desc);
683
xe_rtp_test_init(struct kunit * test)684 static int xe_rtp_test_init(struct kunit *test)
685 {
686 struct xe_device *xe;
687 struct device *dev;
688 int ret;
689
690 dev = drm_kunit_helper_alloc_device(test);
691 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dev);
692
693 xe = xe_kunit_helper_alloc_xe_device(test, dev);
694 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, xe);
695
696 /* Initialize an empty device */
697 test->priv = NULL;
698 ret = xe_pci_fake_device_init(xe);
699 KUNIT_ASSERT_EQ(test, ret, 0);
700
701 xe->drm.dev = dev;
702 test->priv = xe;
703
704 kunit_activate_static_stub(test, xe_gt_mcr_check_reg, fake_xe_gt_mcr_check_reg);
705
706 return 0;
707 }
708
xe_rtp_test_exit(struct kunit * test)709 static void xe_rtp_test_exit(struct kunit *test)
710 {
711 struct xe_device *xe = test->priv;
712
713 drm_kunit_helper_free_device(test, xe->drm.dev);
714 }
715
716 static struct kunit_case xe_rtp_tests[] = {
717 KUNIT_CASE_PARAM(xe_rtp_rules_tests, rtp_rules_gen_params),
718 KUNIT_CASE_PARAM(xe_rtp_process_to_sr_tests, rtp_to_sr_gen_params),
719 KUNIT_CASE_PARAM(xe_rtp_process_tests, rtp_gen_params),
720 {}
721 };
722
723 static struct kunit_suite xe_rtp_test_suite = {
724 .name = "xe_rtp",
725 .init = xe_rtp_test_init,
726 .exit = xe_rtp_test_exit,
727 .test_cases = xe_rtp_tests,
728 };
729
730 kunit_test_suite(xe_rtp_test_suite);
731