]> www.infradead.org Git - users/hch/configfs.git/commitdiff
drm/xe/rtp: Allow to OR rules
authorLucas De Marchi <lucas.demarchi@intel.com>
Tue, 18 Jun 2024 05:00:42 +0000 (22:00 -0700)
committerMatt Roper <matthew.d.roper@intel.com>
Tue, 18 Jun 2024 19:03:28 +0000 (12:03 -0700)
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
drivers/gpu/drm/xe/tests/xe_rtp_test.c
drivers/gpu/drm/xe/xe_rtp.c
drivers/gpu/drm/xe/xe_rtp.h
drivers/gpu/drm/xe/xe_rtp_types.h

index 474a0b222ce164c61dc947800a8d4d8538001e05..f217445c246a80b1539fb4bd11b58cbe224d4273 100644 (file)
@@ -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,
index eff1c9c2f5ccc89819a43135a757e06eda55b495..dc315b8aae071c8837a44c62c4c9d667f2dacbfc 100644 (file)
@@ -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;
 }
 
index 904c5156a7b1bb202fbaede5f4913a37f3c93501..bd5b5ba0fb313003e5c6f99baa7765444314b993 100644 (file)
@@ -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
index 637acc7626a4da6c649e0090b73ade99b3373300..10150bc22ccd358e3be0d6548eb6df7a22eb40fe 100644 (file)
@@ -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 */