Commit dc72c52a authored by Lucas De Marchi's avatar Lucas De Marchi Committed by Matt Roper
Browse files

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 24d0d98a ("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: default avatarMatt Roper <matthew.d.roper@intel.com>
Signed-off-by: default avatarLucas De Marchi <lucas.demarchi@intel.com>
Signed-off-by: default avatarMatt Roper <matthew.d.roper@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20240618050044.324454-4-lucas.demarchi@intel.com
parent 512660cd
Loading
Loading
Loading
Loading
+53 −0
Original line number Diff line number Diff line
@@ -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,
+27 −3
Original line number Diff line number Diff line
@@ -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)
		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;
}

+21 −0
Original line number Diff line number Diff line
@@ -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
+1 −0
Original line number Diff line number Diff line
@@ -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 */