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

drm/xe/rtp: Allow to OR rules

Some workarounds started to depend on different set of conditions where
the action should be applied if any of them match. See e.g.
commit 24d0d98af1c3 ("drm/xe/xe2lpm: Fixup Wa_14020756599"). Add
XE_RTP_MATCH_OR that allows to implement a logical OR for the rules.
Normal precedence applies:

r1, r2, OR, r3

means

(r1 AND r2) OR r3

The check is shortcut as soon as a set of conditions match.

v2: Do not match on empty number of rules-other-than-OR evaluated

Reviewed-by: Matt Roper <matthew.d.roper@intel.com>
Signed-off-by: Lucas De Marchi <lucas.demarchi@intel.com>
Signed-off-by: Matt Roper <matthew.d.roper@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20240618050044.324454-4-lucas.demarchi@intel.com

authored by

Lucas De Marchi and committed by
Matt Roper
dc72c52a 512660cd

+102 -3
+53
drivers/gpu/drm/xe/tests/xe_rtp_test.c
··· 91 91 }, 92 92 }, 93 93 { 94 + .name = "match-or", 95 + .expected_reg = REGULAR_REG1, 96 + .expected_set_bits = REG_BIT(0) | REG_BIT(1) | REG_BIT(2), 97 + .expected_clr_bits = REG_BIT(0) | REG_BIT(1) | REG_BIT(2), 98 + .expected_count = 1, 99 + .entries = (const struct xe_rtp_entry_sr[]) { 100 + { XE_RTP_NAME("first"), 101 + XE_RTP_RULES(FUNC(match_yes), OR, FUNC(match_no)), 102 + XE_RTP_ACTIONS(SET(REGULAR_REG1, REG_BIT(0))) 103 + }, 104 + { XE_RTP_NAME("middle"), 105 + XE_RTP_RULES(FUNC(match_no), FUNC(match_no), OR, 106 + FUNC(match_yes), OR, 107 + FUNC(match_no)), 108 + XE_RTP_ACTIONS(SET(REGULAR_REG1, REG_BIT(1))) 109 + }, 110 + { XE_RTP_NAME("last"), 111 + XE_RTP_RULES(FUNC(match_no), OR, FUNC(match_yes)), 112 + XE_RTP_ACTIONS(SET(REGULAR_REG1, REG_BIT(2))) 113 + }, 114 + { XE_RTP_NAME("no-match"), 115 + XE_RTP_RULES(FUNC(match_no), OR, FUNC(match_no)), 116 + XE_RTP_ACTIONS(SET(REGULAR_REG1, REG_BIT(3))) 117 + }, 118 + {} 119 + }, 120 + }, 121 + { 122 + .name = "match-or-xfail", 123 + .expected_reg = REGULAR_REG1, 124 + .expected_count = 0, 125 + .entries = (const struct xe_rtp_entry_sr[]) { 126 + { XE_RTP_NAME("leading-or"), 127 + XE_RTP_RULES(OR, FUNC(match_yes)), 128 + XE_RTP_ACTIONS(SET(REGULAR_REG1, REG_BIT(0))) 129 + }, 130 + { XE_RTP_NAME("trailing-or"), 131 + /* 132 + * First condition is match_no, otherwise the failure 133 + * wouldn't really trigger as RTP stops processing as 134 + * soon as it has a matching set of rules 135 + */ 136 + XE_RTP_RULES(FUNC(match_no), OR), 137 + XE_RTP_ACTIONS(SET(REGULAR_REG1, REG_BIT(1))) 138 + }, 139 + { XE_RTP_NAME("no-or-or-yes"), 140 + XE_RTP_RULES(FUNC(match_no), OR, OR, FUNC(match_yes)), 141 + XE_RTP_ACTIONS(SET(REGULAR_REG1, REG_BIT(2))) 142 + }, 143 + {} 144 + }, 145 + }, 146 + { 94 147 .name = "no-match-no-add-multiple-rules", 95 148 .expected_reg = REGULAR_REG1, 96 149 .expected_set_bits = REG_BIT(0),
+27 -3
drivers/gpu/drm/xe/xe_rtp.c
··· 35 35 unsigned int n_rules) 36 36 { 37 37 const struct xe_rtp_rule *r; 38 - unsigned int i; 38 + unsigned int i, rcount = 0; 39 39 bool match; 40 40 41 41 for (r = rules, i = 0; i < n_rules; r = &rules[++i]) { 42 42 switch (r->match_type) { 43 + case XE_RTP_MATCH_OR: 44 + /* 45 + * This is only reached if a complete set of 46 + * rules passed or none were evaluated. For both cases, 47 + * shortcut the other rules and return the proper value. 48 + */ 49 + goto done; 43 50 case XE_RTP_MATCH_PLATFORM: 44 51 match = xe->info.platform == r->platform; 45 52 break; ··· 109 102 match = false; 110 103 } 111 104 112 - if (!match) 113 - return false; 105 + if (!match) { 106 + /* 107 + * Advance rules until we find XE_RTP_MATCH_OR to check 108 + * if there's another set of conditions to check 109 + */ 110 + while (i < n_rules && rules[++i].match_type != XE_RTP_MATCH_OR) 111 + ; 112 + 113 + if (i >= n_rules) 114 + return false; 115 + 116 + rcount = 0; 117 + } else { 118 + rcount++; 119 + } 114 120 } 121 + 122 + done: 123 + if (drm_WARN_ON(&xe->drm, !rcount)) 124 + return false; 115 125 116 126 return true; 117 127 }
+21
drivers/gpu/drm/xe/xe_rtp.h
··· 180 180 { .match_type = XE_RTP_MATCH_DISCRETE } 181 181 182 182 /** 183 + * XE_RTP_RULE_OR - Create an OR condition for rtp rules 184 + * 185 + * RTP rules are AND'ed when evaluated and all of them need to match. 186 + * XE_RTP_RULE_OR allows to create set of rules where any of them matching is 187 + * sufficient for the action to trigger. Example: 188 + * 189 + * .. code-block:: c 190 + * 191 + * const struct xe_rtp_entry_sr entries[] = { 192 + * ... 193 + * { XE_RTP_NAME("test-entry"), 194 + * XE_RTP_RULES(PLATFORM(DG2), OR, PLATFORM(TIGERLAKE)), 195 + * ... 196 + * }, 197 + * ... 198 + * }; 199 + */ 200 + #define XE_RTP_RULE_OR \ 201 + { .match_type = XE_RTP_MATCH_OR } 202 + 203 + /** 183 204 * XE_RTP_ACTION_WR - Helper to write a value to the register, overriding all 184 205 * the bits 185 206 * @reg_: Register
+1
drivers/gpu/drm/xe/xe_rtp_types.h
··· 51 51 XE_RTP_MATCH_ENGINE_CLASS, 52 52 XE_RTP_MATCH_NOT_ENGINE_CLASS, 53 53 XE_RTP_MATCH_FUNC, 54 + XE_RTP_MATCH_OR, 54 55 }; 55 56 56 57 /** struct xe_rtp_rule - match rule for processing entry */