Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/xe: Migrate OOB WAs to OR rules

Now that rtp has OR rules, it's not needed to extend it to process OOB
WAs. Previously if an entry had no name, it was considered as "a set of
rules OR'ed with the last named entry".

Instead of generating new entries, add OR rules. The syntax for
xe_wa_oob.rules remains the same, with xe_gen_wa_oob generating the
slightly different table. Object sizes delta are negligible, but having
just one logic makes it easier to maintain:

add/remove: 0/0 grow/shrink: 1/2 up/down: 160/-269 (-109)
Function old new delta
__compound_literal 6104 6264 +160
xe_wa_dump 1839 1810 -29
oob_was 816 576 -240
Total: Before=17257, After=17148, chg -0.63%

Reviewed-by: Gustavo Sousa <gustavo.sousa@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20240727015907.899192-9-lucas.demarchi@intel.com
Signed-off-by: Lucas De Marchi <lucas.demarchi@intel.com>

+37 -49
+15 -19
drivers/gpu/drm/xe/tests/xe_rtp_test.c
··· 401 401 }, 402 402 { 403 403 .name = "inactive-1st_or_active-inactive", 404 - .expected_active = BIT(1) | BIT(2) | BIT(3), 404 + .expected_active = BIT(1), 405 405 .entries = (const struct xe_rtp_entry[]) { 406 406 { XE_RTP_NAME("r1"), 407 407 XE_RTP_RULES(FUNC(match_no)), 408 408 }, 409 409 { XE_RTP_NAME("r2_or_conditions"), 410 - XE_RTP_RULES(FUNC(match_yes)), 411 - }, 412 - { XE_RTP_RULES(FUNC(match_no)) }, 413 - { XE_RTP_RULES(FUNC(match_no)) }, 410 + XE_RTP_RULES(FUNC(match_yes), OR, 411 + FUNC(match_no), OR, 412 + FUNC(match_no)) }, 414 413 { XE_RTP_NAME("r3"), 415 414 XE_RTP_RULES(FUNC(match_no)), 416 415 }, ··· 418 419 }, 419 420 { 420 421 .name = "inactive-2nd_or_active-inactive", 421 - .expected_active = BIT(1) | BIT(2) | BIT(3), 422 + .expected_active = BIT(1), 422 423 .entries = (const struct xe_rtp_entry[]) { 423 424 { XE_RTP_NAME("r1"), 424 425 XE_RTP_RULES(FUNC(match_no)), 425 426 }, 426 427 { XE_RTP_NAME("r2_or_conditions"), 427 - XE_RTP_RULES(FUNC(match_no)), 428 - }, 429 - { XE_RTP_RULES(FUNC(match_yes)) }, 430 - { XE_RTP_RULES(FUNC(match_no)) }, 428 + XE_RTP_RULES(FUNC(match_no), OR, 429 + FUNC(match_yes), OR, 430 + FUNC(match_no)) }, 431 431 { XE_RTP_NAME("r3"), 432 432 XE_RTP_RULES(FUNC(match_no)), 433 433 }, ··· 435 437 }, 436 438 { 437 439 .name = "inactive-last_or_active-inactive", 438 - .expected_active = BIT(1) | BIT(2) | BIT(3), 440 + .expected_active = BIT(1), 439 441 .entries = (const struct xe_rtp_entry[]) { 440 442 { XE_RTP_NAME("r1"), 441 443 XE_RTP_RULES(FUNC(match_no)), 442 444 }, 443 445 { XE_RTP_NAME("r2_or_conditions"), 444 - XE_RTP_RULES(FUNC(match_no)), 445 - }, 446 - { XE_RTP_RULES(FUNC(match_no)) }, 447 - { XE_RTP_RULES(FUNC(match_yes)) }, 446 + XE_RTP_RULES(FUNC(match_no), OR, 447 + FUNC(match_no), OR, 448 + FUNC(match_yes)) }, 448 449 { XE_RTP_NAME("r3"), 449 450 XE_RTP_RULES(FUNC(match_no)), 450 451 }, ··· 458 461 XE_RTP_RULES(FUNC(match_no)), 459 462 }, 460 463 { XE_RTP_NAME("r2_or_conditions"), 461 - XE_RTP_RULES(FUNC(match_no)), 462 - }, 463 - { XE_RTP_RULES(FUNC(match_no)) }, 464 - { XE_RTP_RULES(FUNC(match_no)) }, 464 + XE_RTP_RULES(FUNC(match_no), OR, 465 + FUNC(match_no), OR, 466 + FUNC(match_no)) }, 465 467 { XE_RTP_NAME("r3"), 466 468 XE_RTP_RULES(FUNC(match_no)), 467 469 },
+12 -4
drivers/gpu/drm/xe/xe_gen_wa_oob.c
··· 97 97 98 98 if (name) { 99 99 fprintf(cheader, "\tXE_WA_OOB_%s = %u,\n", name, idx); 100 - fprintf(csource, "{ XE_RTP_NAME(\"%s\"), XE_RTP_RULES(%s) },\n", 100 + 101 + /* Close previous entry before starting a new one */ 102 + if (idx) 103 + fprintf(csource, ") },\n"); 104 + 105 + fprintf(csource, "{ XE_RTP_NAME(\"%s\"),\n XE_RTP_RULES(%s", 101 106 name, rules); 107 + idx++; 102 108 } else { 103 - fprintf(csource, "{ XE_RTP_NAME(NULL), XE_RTP_RULES(%s) },\n", 104 - rules); 109 + fprintf(csource, ", OR,\n\t%s", rules); 105 110 } 106 111 107 - idx++; 108 112 lineno++; 109 113 if (!is_continuation) 110 114 prev_name = name; 111 115 } 116 + 117 + /* Close last entry */ 118 + if (idx) 119 + fprintf(csource, ") },\n"); 112 120 113 121 fprintf(cheader, "\t_XE_WA_OOB_COUNT = %u\n", idx); 114 122
+10 -26
drivers/gpu/drm/xe/xe_rtp.c
··· 221 221 222 222 static void rtp_mark_active(struct xe_device *xe, 223 223 struct xe_rtp_process_ctx *ctx, 224 - unsigned int first, unsigned int n_entries) 224 + unsigned int idx) 225 225 { 226 226 if (!ctx->active_entries) 227 227 return; 228 228 229 - if (drm_WARN_ON(&xe->drm, first + n_entries > ctx->n_entries)) 229 + if (drm_WARN_ON(&xe->drm, idx >= ctx->n_entries)) 230 230 return; 231 231 232 - bitmap_set(ctx->active_entries, first, n_entries); 232 + bitmap_set(ctx->active_entries, idx, 1); 233 233 } 234 234 235 235 /** ··· 274 274 } 275 275 276 276 if (match) 277 - rtp_mark_active(xe, ctx, entry - entries, 1); 277 + rtp_mark_active(xe, ctx, entry - entries); 278 278 } 279 279 } 280 280 EXPORT_SYMBOL_IF_KUNIT(xe_rtp_process_to_sr); ··· 285 285 * @entries: Table with RTP definitions 286 286 * 287 287 * Walk the table pointed by @entries (with an empty sentinel), executing the 288 - * rules. A few differences from xe_rtp_process_to_sr(): 289 - * 290 - * 1. There is no action associated with each entry since this uses 291 - * struct xe_rtp_entry. Its main use is for marking active workarounds via 292 - * xe_rtp_process_ctx_enable_active_tracking(). 293 - * 2. There is support for OR operations by having entries with no name. 288 + * rules. One difference from xe_rtp_process_to_sr(): there is no action 289 + * associated with each entry since this uses struct xe_rtp_entry. Its main use 290 + * is for marking active workarounds via 291 + * xe_rtp_process_ctx_enable_active_tracking(). 294 292 */ 295 293 void xe_rtp_process(struct xe_rtp_process_ctx *ctx, 296 294 const struct xe_rtp_entry *entries) 297 295 { 298 - const struct xe_rtp_entry *entry, *first_entry; 296 + const struct xe_rtp_entry *entry; 299 297 struct xe_hw_engine *hwe; 300 298 struct xe_gt *gt; 301 299 struct xe_device *xe; 302 300 303 301 rtp_get_context(ctx, &hwe, &gt, &xe); 304 302 305 - first_entry = entries; 306 - if (drm_WARN_ON(&xe->drm, !first_entry->name)) 307 - return; 308 - 309 303 for (entry = entries; entry && entry->rules; entry++) { 310 - if (entry->name) 311 - first_entry = entry; 312 - 313 304 if (!rule_matches(xe, gt, hwe, entry->rules, entry->n_rules)) 314 305 continue; 315 306 316 - /* Fast-forward entry, eliminating the OR'ed entries */ 317 - for (entry++; entry && entry->rules; entry++) 318 - if (entry->name) 319 - break; 320 - entry--; 321 - 322 - rtp_mark_active(xe, ctx, first_entry - entries, 323 - entry - first_entry + 1); 307 + rtp_mark_active(xe, ctx, entry - entries); 324 308 } 325 309 } 326 310 EXPORT_SYMBOL_IF_KUNIT(xe_rtp_process);