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_entry_sr *entries; 58 }; 59 60 struct rtp_test_case { 61 const char *name; 62 unsigned long expected_active; 63 const struct xe_rtp_entry *entries; 64 }; 65 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 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 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 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 283 static const struct rtp_to_sr_test_case rtp_to_sr_cases[] = { 284 { 285 .name = "coalesce-same-reg", 286 .expected_reg = REGULAR_REG1, 287 .expected_set_bits = REG_BIT(0) | REG_BIT(1), 288 .expected_clr_bits = REG_BIT(0) | REG_BIT(1), 289 .expected_active = BIT(0) | BIT(1), 290 .expected_count_sr_entries = 1, 291 /* Different bits on the same register: create a single entry */ 292 .entries = (const struct xe_rtp_entry_sr[]) { 293 { XE_RTP_NAME("basic-1"), 294 XE_RTP_RULES(FUNC(match_yes)), 295 XE_RTP_ACTIONS(SET(REGULAR_REG1, REG_BIT(0))) 296 }, 297 { XE_RTP_NAME("basic-2"), 298 XE_RTP_RULES(FUNC(match_yes)), 299 XE_RTP_ACTIONS(SET(REGULAR_REG1, REG_BIT(1))) 300 }, 301 {} 302 }, 303 }, 304 { 305 .name = "no-match-no-add", 306 .expected_reg = REGULAR_REG1, 307 .expected_set_bits = REG_BIT(0), 308 .expected_clr_bits = REG_BIT(0), 309 .expected_active = BIT(0), 310 .expected_count_sr_entries = 1, 311 /* Don't coalesce second entry since rules don't match */ 312 .entries = (const struct xe_rtp_entry_sr[]) { 313 { XE_RTP_NAME("basic-1"), 314 XE_RTP_RULES(FUNC(match_yes)), 315 XE_RTP_ACTIONS(SET(REGULAR_REG1, REG_BIT(0))) 316 }, 317 { XE_RTP_NAME("basic-2"), 318 XE_RTP_RULES(FUNC(match_no)), 319 XE_RTP_ACTIONS(SET(REGULAR_REG1, REG_BIT(1))) 320 }, 321 {} 322 }, 323 }, 324 { 325 .name = "two-regs-two-entries", 326 .expected_reg = REGULAR_REG1, 327 .expected_set_bits = REG_BIT(0), 328 .expected_clr_bits = REG_BIT(0), 329 .expected_active = BIT(0) | BIT(1), 330 .expected_count_sr_entries = 2, 331 /* Same bits on different registers are not coalesced */ 332 .entries = (const struct xe_rtp_entry_sr[]) { 333 { XE_RTP_NAME("basic-1"), 334 XE_RTP_RULES(FUNC(match_yes)), 335 XE_RTP_ACTIONS(SET(REGULAR_REG1, REG_BIT(0))) 336 }, 337 { XE_RTP_NAME("basic-2"), 338 XE_RTP_RULES(FUNC(match_yes)), 339 XE_RTP_ACTIONS(SET(REGULAR_REG2, REG_BIT(0))) 340 }, 341 {} 342 }, 343 }, 344 { 345 .name = "clr-one-set-other", 346 .expected_reg = REGULAR_REG1, 347 .expected_set_bits = REG_BIT(0), 348 .expected_clr_bits = REG_BIT(1) | REG_BIT(0), 349 .expected_active = BIT(0) | BIT(1), 350 .expected_count_sr_entries = 1, 351 /* Check clr vs set actions on different bits */ 352 .entries = (const struct xe_rtp_entry_sr[]) { 353 { XE_RTP_NAME("basic-1"), 354 XE_RTP_RULES(FUNC(match_yes)), 355 XE_RTP_ACTIONS(SET(REGULAR_REG1, REG_BIT(0))) 356 }, 357 { XE_RTP_NAME("basic-2"), 358 XE_RTP_RULES(FUNC(match_yes)), 359 XE_RTP_ACTIONS(CLR(REGULAR_REG1, REG_BIT(1))) 360 }, 361 {} 362 }, 363 }, 364 { 365 #define TEMP_MASK REG_GENMASK(10, 8) 366 #define TEMP_FIELD REG_FIELD_PREP(TEMP_MASK, 2) 367 .name = "set-field", 368 .expected_reg = REGULAR_REG1, 369 .expected_set_bits = TEMP_FIELD, 370 .expected_clr_bits = TEMP_MASK, 371 .expected_active = BIT(0), 372 .expected_count_sr_entries = 1, 373 /* Check FIELD_SET works */ 374 .entries = (const struct xe_rtp_entry_sr[]) { 375 { XE_RTP_NAME("basic-1"), 376 XE_RTP_RULES(FUNC(match_yes)), 377 XE_RTP_ACTIONS(FIELD_SET(REGULAR_REG1, 378 TEMP_MASK, TEMP_FIELD)) 379 }, 380 {} 381 }, 382 #undef TEMP_MASK 383 #undef TEMP_FIELD 384 }, 385 { 386 .name = "conflict-duplicate", 387 .expected_reg = REGULAR_REG1, 388 .expected_set_bits = REG_BIT(0), 389 .expected_clr_bits = REG_BIT(0), 390 .expected_active = BIT(0) | BIT(1), 391 .expected_count_sr_entries = 1, 392 .expected_sr_errors = 1, 393 .entries = (const struct xe_rtp_entry_sr[]) { 394 { XE_RTP_NAME("basic-1"), 395 XE_RTP_RULES(FUNC(match_yes)), 396 XE_RTP_ACTIONS(SET(REGULAR_REG1, REG_BIT(0))) 397 }, 398 /* drop: setting same values twice */ 399 { XE_RTP_NAME("basic-2"), 400 XE_RTP_RULES(FUNC(match_yes)), 401 XE_RTP_ACTIONS(SET(REGULAR_REG1, REG_BIT(0))) 402 }, 403 {} 404 }, 405 }, 406 { 407 .name = "conflict-not-disjoint", 408 .expected_reg = REGULAR_REG1, 409 .expected_set_bits = REG_BIT(0), 410 .expected_clr_bits = REG_BIT(0), 411 .expected_active = BIT(0) | BIT(1), 412 .expected_count_sr_entries = 1, 413 .expected_sr_errors = 1, 414 .entries = (const struct xe_rtp_entry_sr[]) { 415 { XE_RTP_NAME("basic-1"), 416 XE_RTP_RULES(FUNC(match_yes)), 417 XE_RTP_ACTIONS(SET(REGULAR_REG1, REG_BIT(0))) 418 }, 419 /* drop: bits are not disjoint with previous entries */ 420 { XE_RTP_NAME("basic-2"), 421 XE_RTP_RULES(FUNC(match_yes)), 422 XE_RTP_ACTIONS(CLR(REGULAR_REG1, REG_GENMASK(1, 0))) 423 }, 424 {} 425 }, 426 }, 427 { 428 .name = "conflict-reg-type", 429 .expected_reg = REGULAR_REG1, 430 .expected_set_bits = REG_BIT(0), 431 .expected_clr_bits = REG_BIT(0), 432 .expected_active = BIT(0) | BIT(1) | BIT(2), 433 .expected_count_sr_entries = 1, 434 .expected_sr_errors = 2, 435 .entries = (const struct xe_rtp_entry_sr[]) { 436 { XE_RTP_NAME("basic-1"), 437 XE_RTP_RULES(FUNC(match_yes)), 438 XE_RTP_ACTIONS(SET(REGULAR_REG1, REG_BIT(0))) 439 }, 440 /* drop: regular vs MCR */ 441 { XE_RTP_NAME("basic-2"), 442 XE_RTP_RULES(FUNC(match_yes)), 443 XE_RTP_ACTIONS(SET(MCR_REG1, REG_BIT(1))) 444 }, 445 /* drop: regular vs masked */ 446 { XE_RTP_NAME("basic-3"), 447 XE_RTP_RULES(FUNC(match_yes)), 448 XE_RTP_ACTIONS(SET(MASKED_REG1, REG_BIT(0))) 449 }, 450 {} 451 }, 452 }, 453 { 454 .name = "bad-mcr-reg-forced-to-regular", 455 .expected_reg = REGULAR_REG4, 456 .expected_set_bits = REG_BIT(0), 457 .expected_clr_bits = REG_BIT(0), 458 .expected_active = BIT(0), 459 .expected_count_sr_entries = 1, 460 .expected_sr_errors = 1, 461 .entries = (const struct xe_rtp_entry_sr[]) { 462 { XE_RTP_NAME("bad-mcr-regular-reg"), 463 XE_RTP_RULES(FUNC(match_yes)), 464 XE_RTP_ACTIONS(SET(BAD_MCR_REG4, REG_BIT(0))) 465 }, 466 {} 467 }, 468 }, 469 { 470 .name = "bad-regular-reg-forced-to-mcr", 471 .expected_reg = MCR_REG5, 472 .expected_set_bits = REG_BIT(0), 473 .expected_clr_bits = REG_BIT(0), 474 .expected_active = BIT(0), 475 .expected_count_sr_entries = 1, 476 .expected_sr_errors = 1, 477 .entries = (const struct xe_rtp_entry_sr[]) { 478 { XE_RTP_NAME("bad-regular-reg"), 479 XE_RTP_RULES(FUNC(match_yes)), 480 XE_RTP_ACTIONS(SET(BAD_REGULAR_REG5, REG_BIT(0))) 481 }, 482 {} 483 }, 484 }, 485 }; 486 487 static void xe_rtp_process_to_sr_tests(struct kunit *test) 488 { 489 const struct rtp_to_sr_test_case *param = test->param_value; 490 struct xe_device *xe = test->priv; 491 struct xe_gt *gt = xe_device_get_root_tile(xe)->primary_gt; 492 struct xe_reg_sr *reg_sr = >->reg_sr; 493 const struct xe_reg_sr_entry *sre, *sr_entry = NULL; 494 struct xe_rtp_process_ctx ctx = XE_RTP_PROCESS_CTX_INITIALIZER(gt); 495 unsigned long idx, count_sr_entries = 0, count_rtp_entries = 0, active = 0; 496 497 xe_reg_sr_init(reg_sr, "xe_rtp_to_sr_tests", xe); 498 499 while (param->entries[count_rtp_entries].rules) 500 count_rtp_entries++; 501 502 xe_rtp_process_ctx_enable_active_tracking(&ctx, &active, count_rtp_entries); 503 xe_rtp_process_to_sr(&ctx, param->entries, count_rtp_entries, 504 reg_sr, false); 505 506 xa_for_each(®_sr->xa, idx, sre) { 507 if (idx == param->expected_reg.addr) 508 sr_entry = sre; 509 510 count_sr_entries++; 511 } 512 513 KUNIT_EXPECT_EQ(test, active, param->expected_active); 514 515 KUNIT_EXPECT_EQ(test, count_sr_entries, param->expected_count_sr_entries); 516 if (count_sr_entries) { 517 KUNIT_EXPECT_EQ(test, sr_entry->clr_bits, param->expected_clr_bits); 518 KUNIT_EXPECT_EQ(test, sr_entry->set_bits, param->expected_set_bits); 519 KUNIT_EXPECT_EQ(test, sr_entry->reg.raw, param->expected_reg.raw); 520 } else { 521 KUNIT_EXPECT_NULL(test, sr_entry); 522 } 523 524 KUNIT_EXPECT_EQ(test, reg_sr->errors, param->expected_sr_errors); 525 } 526 527 /* 528 * Entries below follow the logic used with xe_wa_oob.rules: 529 * 1) Entries with empty name are OR'ed: all entries marked active since the 530 * last entry with a name 531 * 2) There are no action associated with rules 532 */ 533 static const struct rtp_test_case rtp_cases[] = { 534 { 535 .name = "active1", 536 .expected_active = BIT(0), 537 .entries = (const struct xe_rtp_entry[]) { 538 { XE_RTP_NAME("r1"), 539 XE_RTP_RULES(FUNC(match_yes)), 540 }, 541 {} 542 }, 543 }, 544 { 545 .name = "active2", 546 .expected_active = BIT(0) | BIT(1), 547 .entries = (const struct xe_rtp_entry[]) { 548 { XE_RTP_NAME("r1"), 549 XE_RTP_RULES(FUNC(match_yes)), 550 }, 551 { XE_RTP_NAME("r2"), 552 XE_RTP_RULES(FUNC(match_yes)), 553 }, 554 {} 555 }, 556 }, 557 { 558 .name = "active-inactive", 559 .expected_active = BIT(0), 560 .entries = (const struct xe_rtp_entry[]) { 561 { XE_RTP_NAME("r1"), 562 XE_RTP_RULES(FUNC(match_yes)), 563 }, 564 { XE_RTP_NAME("r2"), 565 XE_RTP_RULES(FUNC(match_no)), 566 }, 567 {} 568 }, 569 }, 570 { 571 .name = "inactive-active", 572 .expected_active = BIT(1), 573 .entries = (const struct xe_rtp_entry[]) { 574 { XE_RTP_NAME("r1"), 575 XE_RTP_RULES(FUNC(match_no)), 576 }, 577 { XE_RTP_NAME("r2"), 578 XE_RTP_RULES(FUNC(match_yes)), 579 }, 580 {} 581 }, 582 }, 583 { 584 .name = "inactive-active-inactive", 585 .expected_active = BIT(1), 586 .entries = (const struct xe_rtp_entry[]) { 587 { XE_RTP_NAME("r1"), 588 XE_RTP_RULES(FUNC(match_no)), 589 }, 590 { XE_RTP_NAME("r2"), 591 XE_RTP_RULES(FUNC(match_yes)), 592 }, 593 { XE_RTP_NAME("r3"), 594 XE_RTP_RULES(FUNC(match_no)), 595 }, 596 {} 597 }, 598 }, 599 { 600 .name = "inactive-inactive-inactive", 601 .expected_active = 0, 602 .entries = (const struct xe_rtp_entry[]) { 603 { XE_RTP_NAME("r1"), 604 XE_RTP_RULES(FUNC(match_no)), 605 }, 606 { XE_RTP_NAME("r2"), 607 XE_RTP_RULES(FUNC(match_no)), 608 }, 609 { XE_RTP_NAME("r3"), 610 XE_RTP_RULES(FUNC(match_no)), 611 }, 612 {} 613 }, 614 }, 615 }; 616 617 static void xe_rtp_process_tests(struct kunit *test) 618 { 619 const struct rtp_test_case *param = test->param_value; 620 struct xe_device *xe = test->priv; 621 struct xe_gt *gt = xe_device_get_root_tile(xe)->primary_gt; 622 struct xe_rtp_process_ctx ctx = XE_RTP_PROCESS_CTX_INITIALIZER(gt); 623 unsigned long count_rtp_entries = 0, active = 0; 624 625 while (param->entries[count_rtp_entries].rules) 626 count_rtp_entries++; 627 628 xe_rtp_process_ctx_enable_active_tracking(&ctx, &active, count_rtp_entries); 629 xe_rtp_process(&ctx, param->entries); 630 631 KUNIT_EXPECT_EQ(test, active, param->expected_active); 632 } 633 634 static void rtp_rules_desc(const struct rtp_rules_test_case *t, char *desc) 635 { 636 strscpy(desc, t->name, KUNIT_PARAM_DESC_SIZE); 637 } 638 639 KUNIT_ARRAY_PARAM(rtp_rules, rtp_rules_cases, rtp_rules_desc); 640 641 static void rtp_to_sr_desc(const struct rtp_to_sr_test_case *t, char *desc) 642 { 643 strscpy(desc, t->name, KUNIT_PARAM_DESC_SIZE); 644 } 645 646 KUNIT_ARRAY_PARAM(rtp_to_sr, rtp_to_sr_cases, rtp_to_sr_desc); 647 648 static void rtp_desc(const struct rtp_test_case *t, char *desc) 649 { 650 strscpy(desc, t->name, KUNIT_PARAM_DESC_SIZE); 651 } 652 653 KUNIT_ARRAY_PARAM(rtp, rtp_cases, rtp_desc); 654 655 static int xe_rtp_test_init(struct kunit *test) 656 { 657 struct xe_device *xe; 658 struct device *dev; 659 int ret; 660 661 dev = drm_kunit_helper_alloc_device(test); 662 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dev); 663 664 xe = xe_kunit_helper_alloc_xe_device(test, dev); 665 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, xe); 666 667 /* Initialize an empty device */ 668 test->priv = NULL; 669 ret = xe_pci_fake_device_init(xe); 670 KUNIT_ASSERT_EQ(test, ret, 0); 671 672 xe->drm.dev = dev; 673 test->priv = xe; 674 675 kunit_activate_static_stub(test, xe_gt_mcr_check_reg, fake_xe_gt_mcr_check_reg); 676 677 return 0; 678 } 679 680 static void xe_rtp_test_exit(struct kunit *test) 681 { 682 struct xe_device *xe = test->priv; 683 684 drm_kunit_helper_free_device(test, xe->drm.dev); 685 } 686 687 static struct kunit_case xe_rtp_tests[] = { 688 KUNIT_CASE_PARAM(xe_rtp_rules_tests, rtp_rules_gen_params), 689 KUNIT_CASE_PARAM(xe_rtp_process_to_sr_tests, rtp_to_sr_gen_params), 690 KUNIT_CASE_PARAM(xe_rtp_process_tests, rtp_gen_params), 691 {} 692 }; 693 694 static struct kunit_suite xe_rtp_test_suite = { 695 .name = "xe_rtp", 696 .init = xe_rtp_test_init, 697 .exit = xe_rtp_test_exit, 698 .test_cases = xe_rtp_tests, 699 }; 700 701 kunit_test_suite(xe_rtp_test_suite); 702