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