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
This commit is contained in:
parent
512660cd1f
commit
dc72c52a42
@ -90,6 +90,59 @@ static const struct rtp_test_case cases[] = {
|
||||
{}
|
||||
},
|
||||
},
|
||||
{
|
||||
.name = "match-or",
|
||||
.expected_reg = REGULAR_REG1,
|
||||
.expected_set_bits = REG_BIT(0) | REG_BIT(1) | REG_BIT(2),
|
||||
.expected_clr_bits = REG_BIT(0) | REG_BIT(1) | REG_BIT(2),
|
||||
.expected_count = 1,
|
||||
.entries = (const struct xe_rtp_entry_sr[]) {
|
||||
{ XE_RTP_NAME("first"),
|
||||
XE_RTP_RULES(FUNC(match_yes), OR, FUNC(match_no)),
|
||||
XE_RTP_ACTIONS(SET(REGULAR_REG1, REG_BIT(0)))
|
||||
},
|
||||
{ XE_RTP_NAME("middle"),
|
||||
XE_RTP_RULES(FUNC(match_no), FUNC(match_no), OR,
|
||||
FUNC(match_yes), OR,
|
||||
FUNC(match_no)),
|
||||
XE_RTP_ACTIONS(SET(REGULAR_REG1, REG_BIT(1)))
|
||||
},
|
||||
{ XE_RTP_NAME("last"),
|
||||
XE_RTP_RULES(FUNC(match_no), OR, FUNC(match_yes)),
|
||||
XE_RTP_ACTIONS(SET(REGULAR_REG1, REG_BIT(2)))
|
||||
},
|
||||
{ XE_RTP_NAME("no-match"),
|
||||
XE_RTP_RULES(FUNC(match_no), OR, FUNC(match_no)),
|
||||
XE_RTP_ACTIONS(SET(REGULAR_REG1, REG_BIT(3)))
|
||||
},
|
||||
{}
|
||||
},
|
||||
},
|
||||
{
|
||||
.name = "match-or-xfail",
|
||||
.expected_reg = REGULAR_REG1,
|
||||
.expected_count = 0,
|
||||
.entries = (const struct xe_rtp_entry_sr[]) {
|
||||
{ XE_RTP_NAME("leading-or"),
|
||||
XE_RTP_RULES(OR, FUNC(match_yes)),
|
||||
XE_RTP_ACTIONS(SET(REGULAR_REG1, REG_BIT(0)))
|
||||
},
|
||||
{ XE_RTP_NAME("trailing-or"),
|
||||
/*
|
||||
* First condition is match_no, otherwise the failure
|
||||
* wouldn't really trigger as RTP stops processing as
|
||||
* soon as it has a matching set of rules
|
||||
*/
|
||||
XE_RTP_RULES(FUNC(match_no), OR),
|
||||
XE_RTP_ACTIONS(SET(REGULAR_REG1, REG_BIT(1)))
|
||||
},
|
||||
{ XE_RTP_NAME("no-or-or-yes"),
|
||||
XE_RTP_RULES(FUNC(match_no), OR, OR, FUNC(match_yes)),
|
||||
XE_RTP_ACTIONS(SET(REGULAR_REG1, REG_BIT(2)))
|
||||
},
|
||||
{}
|
||||
},
|
||||
},
|
||||
{
|
||||
.name = "no-match-no-add-multiple-rules",
|
||||
.expected_reg = REGULAR_REG1,
|
||||
|
@ -35,11 +35,18 @@ static bool rule_matches(const struct xe_device *xe,
|
||||
unsigned int n_rules)
|
||||
{
|
||||
const struct xe_rtp_rule *r;
|
||||
unsigned int i;
|
||||
unsigned int i, rcount = 0;
|
||||
bool match;
|
||||
|
||||
for (r = rules, i = 0; i < n_rules; r = &rules[++i]) {
|
||||
switch (r->match_type) {
|
||||
case XE_RTP_MATCH_OR:
|
||||
/*
|
||||
* This is only reached if a complete set of
|
||||
* rules passed or none were evaluated. For both cases,
|
||||
* shortcut the other rules and return the proper value.
|
||||
*/
|
||||
goto done;
|
||||
case XE_RTP_MATCH_PLATFORM:
|
||||
match = xe->info.platform == r->platform;
|
||||
break;
|
||||
@ -102,10 +109,27 @@ static bool rule_matches(const struct xe_device *xe,
|
||||
match = false;
|
||||
}
|
||||
|
||||
if (!match)
|
||||
return false;
|
||||
if (!match) {
|
||||
/*
|
||||
* Advance rules until we find XE_RTP_MATCH_OR to check
|
||||
* if there's another set of conditions to check
|
||||
*/
|
||||
while (i < n_rules && rules[++i].match_type != XE_RTP_MATCH_OR)
|
||||
;
|
||||
|
||||
if (i >= n_rules)
|
||||
return false;
|
||||
|
||||
rcount = 0;
|
||||
} else {
|
||||
rcount++;
|
||||
}
|
||||
}
|
||||
|
||||
done:
|
||||
if (drm_WARN_ON(&xe->drm, !rcount))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -179,6 +179,27 @@ struct xe_reg_sr;
|
||||
#define XE_RTP_RULE_IS_DISCRETE \
|
||||
{ .match_type = XE_RTP_MATCH_DISCRETE }
|
||||
|
||||
/**
|
||||
* XE_RTP_RULE_OR - Create an OR condition for rtp rules
|
||||
*
|
||||
* RTP rules are AND'ed when evaluated and all of them need to match.
|
||||
* XE_RTP_RULE_OR allows to create set of rules where any of them matching is
|
||||
* sufficient for the action to trigger. Example:
|
||||
*
|
||||
* .. code-block:: c
|
||||
*
|
||||
* const struct xe_rtp_entry_sr entries[] = {
|
||||
* ...
|
||||
* { XE_RTP_NAME("test-entry"),
|
||||
* XE_RTP_RULES(PLATFORM(DG2), OR, PLATFORM(TIGERLAKE)),
|
||||
* ...
|
||||
* },
|
||||
* ...
|
||||
* };
|
||||
*/
|
||||
#define XE_RTP_RULE_OR \
|
||||
{ .match_type = XE_RTP_MATCH_OR }
|
||||
|
||||
/**
|
||||
* XE_RTP_ACTION_WR - Helper to write a value to the register, overriding all
|
||||
* the bits
|
||||
|
@ -51,6 +51,7 @@ enum {
|
||||
XE_RTP_MATCH_ENGINE_CLASS,
|
||||
XE_RTP_MATCH_NOT_ENGINE_CLASS,
|
||||
XE_RTP_MATCH_FUNC,
|
||||
XE_RTP_MATCH_OR,
|
||||
};
|
||||
|
||||
/** struct xe_rtp_rule - match rule for processing entry */
|
||||
|
Loading…
x
Reference in New Issue
Block a user