* FAILED: patch "[PATCH] drm/xe/rtp: Maintain OA whitelists separately" failed to apply to 6.18-stable tree
@ 2026-07-29 10:58 gregkh
2026-08-01 3:03 ` [PATCH 6.18.y 1/6] drm/xe/lrc: Refactor out engine id to hwe conversion Sasha Levin
0 siblings, 1 reply; 7+ messages in thread
From: gregkh @ 2026-07-29 10:58 UTC (permalink / raw)
To: ashutosh.dixit, thomas.hellstrom, umesh.nerlige.ramappa; +Cc: stable
The patch below does not apply to the 6.18-stable tree.
If someone wants it applied there, or to any other stable or longterm
tree, then please email the backport, including the original git commit
id to <stable@vger.kernel.org>.
To reproduce the conflict and resubmit, you may use the following commands:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-6.18.y
git checkout FETCH_HEAD
git cherry-pick -x 31e2437561621b4867c08efc890bf629d017df03
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<stable@vger.kernel.org>' --in-reply-to '2026072913-snap-snuff-32d6@gregkh' --subject-prefix 'PATCH 6.18.y' 'HEAD^..'
Possible dependencies:
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 31e2437561621b4867c08efc890bf629d017df03 Mon Sep 17 00:00:00 2001
From: Ashutosh Dixit <ashutosh.dixit@intel.com>
Date: Mon, 15 Jun 2026 15:42:20 -0700
Subject: [PATCH] drm/xe/rtp: Maintain OA whitelists separately
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
OA registers are dynamically whitelisted (and again dewhitelisted) on OA
stream open/close. Maintaining OA whitelists separately from non-OA
register whitlists simplifies this management of OA register
whitelisting/dewhitelisting.
Fixes: 828a8eaf37c3 ("drm/xe/oa: Add MMIO trigger support")
Cc: stable@vger.kernel.org # v6.12+
Signed-off-by: Ashutosh Dixit <ashutosh.dixit@intel.com>
Reviewed-by: Umesh Nerlige Ramappa <umesh.nerlige.ramappa@intel.com>
Link: https://patch.msgid.link/20260615224227.34880-3-ashutosh.dixit@intel.com
(cherry picked from commit c478244a9e2d14b3f1f92e8bd293919e554622a5)
Signed-off-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>
diff --git a/drivers/gpu/drm/xe/xe_gt_debugfs.c b/drivers/gpu/drm/xe/xe_gt_debugfs.c
index f45306308cd6..c38bcacb27e4 100644
--- a/drivers/gpu/drm/xe/xe_gt_debugfs.c
+++ b/drivers/gpu/drm/xe/xe_gt_debugfs.c
@@ -149,8 +149,10 @@ static int register_save_restore(struct xe_gt *gt, struct drm_printer *p)
drm_printf(p, "\n");
drm_printf(p, "Whitelist\n");
- for_each_hw_engine(hwe, gt, id)
+ for_each_hw_engine(hwe, gt, id) {
xe_reg_whitelist_dump(&hwe->reg_whitelist, p);
+ xe_reg_whitelist_dump(&hwe->oa_whitelist, p);
+ }
return 0;
}
diff --git a/drivers/gpu/drm/xe/xe_hw_engine.c b/drivers/gpu/drm/xe/xe_hw_engine.c
index 98265293f2dc..55632ac4dfe7 100644
--- a/drivers/gpu/drm/xe/xe_hw_engine.c
+++ b/drivers/gpu/drm/xe/xe_hw_engine.c
@@ -572,6 +572,8 @@ static void hw_engine_init_early(struct xe_gt *gt, struct xe_hw_engine *hwe,
hw_engine_setup_default_state(hwe);
xe_reg_sr_init(&hwe->reg_whitelist, hwe->name, gt_to_xe(gt));
+ xe_reg_sr_init(&hwe->oa_whitelist, hwe->name, gt_to_xe(gt));
+ xe_reg_sr_init(&hwe->oa_sr, hwe->name, gt_to_xe(gt));
xe_reg_whitelist_process_engine(hwe);
}
diff --git a/drivers/gpu/drm/xe/xe_hw_engine_types.h b/drivers/gpu/drm/xe/xe_hw_engine_types.h
index 2cf898e682f5..84c097da9b6f 100644
--- a/drivers/gpu/drm/xe/xe_hw_engine_types.h
+++ b/drivers/gpu/drm/xe/xe_hw_engine_types.h
@@ -130,6 +130,14 @@ struct xe_hw_engine {
* @reg_whitelist: table with registers to be whitelisted
*/
struct xe_reg_sr reg_whitelist;
+ /**
+ * @oa_whitelist: oa registers to be whitelisted
+ */
+ struct xe_reg_sr oa_whitelist;
+ /**
+ * @oa_sr: oa nonpriv whitelist registers, changed on oa stream open/close
+ */
+ struct xe_reg_sr oa_sr;
/**
* @reg_lrc: LRC workaround registers
*/
diff --git a/drivers/gpu/drm/xe/xe_reg_whitelist.c b/drivers/gpu/drm/xe/xe_reg_whitelist.c
index 2d8ddb57412c..6d642c2f6fd7 100644
--- a/drivers/gpu/drm/xe/xe_reg_whitelist.c
+++ b/drivers/gpu/drm/xe/xe_reg_whitelist.c
@@ -103,6 +103,9 @@ static const struct xe_rtp_table_sr register_whitelist = XE_RTP_TABLE_SR(
WHITELIST(VFLSKPD,
RING_FORCE_TO_NONPRIV_ACCESS_RW))
},
+);
+
+static const struct xe_rtp_table_sr oa_whitelist = XE_RTP_TABLE_SR(
#define WHITELIST_DENY(r, f) WHITELIST(r, (f) | RING_FORCE_TO_NONPRIV_DENY)
@@ -206,6 +209,8 @@ void xe_reg_whitelist_process_engine(struct xe_hw_engine *hwe)
xe_rtp_process_to_sr(&ctx, ®ister_whitelist, &hwe->reg_whitelist, false);
whitelist_apply_to_hwe(hwe);
+
+ xe_rtp_process_to_sr(&ctx, &oa_whitelist, &hwe->oa_whitelist, false);
}
/**
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 6.18.y 1/6] drm/xe/lrc: Refactor out engine id to hwe conversion
2026-07-29 10:58 FAILED: patch "[PATCH] drm/xe/rtp: Maintain OA whitelists separately" failed to apply to 6.18-stable tree gregkh
@ 2026-08-01 3:03 ` Sasha Levin
2026-08-01 3:03 ` [PATCH 6.18.y 2/6] drm/xe/mcr: Extract reg_in_steering_type_ranges() Sasha Levin
` (4 more replies)
0 siblings, 5 replies; 7+ messages in thread
From: Sasha Levin @ 2026-08-01 3:03 UTC (permalink / raw)
To: stable; +Cc: Umesh Nerlige Ramappa, Niranjana Vishwanathapura, Sasha Levin
From: Umesh Nerlige Ramappa <umesh.nerlige.ramappa@intel.com>
[ Upstream commit e3a9c46fc3a29b8d7f62a7bd73bf20975037dc82 ]
We need to define more helpers that read engine ID specific register, so
move that logic outside of get_ctx_timestamp().
Signed-off-by: Umesh Nerlige Ramappa <umesh.nerlige.ramappa@intel.com>
Reviewed-by: Niranjana Vishwanathapura <niranjana.vishwanathapura@intel.com>
Link: https://patch.msgid.link/20260507162016.3888309-20-umesh.nerlige.ramappa@intel.com
Stable-dep-of: 31e243756162 ("drm/xe/rtp: Maintain OA whitelists separately")
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/gpu/drm/xe/xe_lrc.c | 20 +++++++++++++++-----
1 file changed, 15 insertions(+), 5 deletions(-)
diff --git a/drivers/gpu/drm/xe/xe_lrc.c b/drivers/gpu/drm/xe/xe_lrc.c
index 9f29dbe890f6..17f31b032216 100644
--- a/drivers/gpu/drm/xe/xe_lrc.c
+++ b/drivers/gpu/drm/xe/xe_lrc.c
@@ -2324,17 +2324,27 @@ void xe_lrc_snapshot_free(struct xe_lrc_snapshot *snapshot)
kfree(snapshot);
}
-static int get_ctx_timestamp(struct xe_lrc *lrc, u32 engine_id, u64 *reg_ctx_ts)
+static struct xe_hw_engine *engine_id_to_hwe(struct xe_gt *gt, u32 engine_id)
{
u16 class = REG_FIELD_GET(ENGINE_CLASS_ID, engine_id);
u16 instance = REG_FIELD_GET(ENGINE_INSTANCE_ID, engine_id);
+ struct xe_hw_engine *hwe = xe_gt_hw_engine(gt, class, instance, false);
+
+ if (xe_gt_WARN_ONCE(gt, !hwe || xe_hw_engine_is_reserved(hwe),
+ "Unexpected engine class:instance %d:%d for utilization\n",
+ class, instance))
+ return NULL;
+
+ return hwe;
+}
+
+static int get_ctx_timestamp(struct xe_lrc *lrc, u32 engine_id, u64 *reg_ctx_ts)
+{
struct xe_hw_engine *hwe;
u64 val;
- hwe = xe_gt_hw_engine(lrc->gt, class, instance, false);
- if (xe_gt_WARN_ONCE(lrc->gt, !hwe || xe_hw_engine_is_reserved(hwe),
- "Unexpected engine class:instance %d:%d for context utilization\n",
- class, instance))
+ hwe = engine_id_to_hwe(lrc->gt, engine_id);
+ if (!hwe)
return -1;
if (lrc_to_xe(lrc)->info.has_64bit_timestamp)
--
2.53.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 6.18.y 2/6] drm/xe/mcr: Extract reg_in_steering_type_ranges()
2026-08-01 3:03 ` [PATCH 6.18.y 1/6] drm/xe/lrc: Refactor out engine id to hwe conversion Sasha Levin
@ 2026-08-01 3:03 ` Sasha Levin
2026-08-01 3:03 ` [PATCH 6.18.y 3/6] drm/xe/reg_sr: Do sanity check for MCR vs non-MCR Sasha Levin
` (3 subsequent siblings)
4 siblings, 0 replies; 7+ messages in thread
From: Sasha Levin @ 2026-08-01 3:03 UTC (permalink / raw)
To: stable; +Cc: Gustavo Sousa, Matt Roper, Sasha Levin
From: Gustavo Sousa <gustavo.sousa@intel.com>
[ Upstream commit cdf8489533f4dd9639fd0c266dd2ec8f7a543e34 ]
The logic to check if a register falls within one of the ranges for a
steering type is already duplicated in
xe_gt_mcr_get_nonterminated_steering(). We will also want to use that
same logic in another upcoming function. Let's factor out that logic
and put it into a function named reg_in_steering_type_ranges().
Reviewed-by: Matt Roper <matthew.d.roper@intel.com>
Link: https://patch.msgid.link/20260514-rtp-mcr-check-v3-6-30dd47855fee@intel.com
Signed-off-by: Gustavo Sousa <gustavo.sousa@intel.com>
Stable-dep-of: 31e243756162 ("drm/xe/rtp: Maintain OA whitelists separately")
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/gpu/drm/xe/xe_gt_mcr.c | 43 +++++++++++++++++++---------------
1 file changed, 24 insertions(+), 19 deletions(-)
diff --git a/drivers/gpu/drm/xe/xe_gt_mcr.c b/drivers/gpu/drm/xe/xe_gt_mcr.c
index 8fb1cae91724..c7164604846f 100644
--- a/drivers/gpu/drm/xe/xe_gt_mcr.c
+++ b/drivers/gpu/drm/xe/xe_gt_mcr.c
@@ -542,6 +542,20 @@ void xe_gt_mcr_set_implicit_defaults(struct xe_gt *gt)
}
}
+static bool reg_in_steering_type_ranges(struct xe_gt *gt,
+ struct xe_reg reg,
+ int type)
+{
+ if (!gt->steering[type].ranges)
+ return false;
+
+ for (int i = 0; gt->steering[type].ranges[i].end > 0; i++)
+ if (xe_mmio_in_range(>->mmio, >->steering[type].ranges[i], reg))
+ return true;
+
+ return false;
+}
+
/*
* xe_gt_mcr_get_nonterminated_steering - find group/instance values that
* will steer a register to a non-terminated instance
@@ -563,30 +577,21 @@ bool xe_gt_mcr_get_nonterminated_steering(struct xe_gt *gt,
u8 *group, u8 *instance)
{
const struct xe_reg reg = to_xe_reg(reg_mcr);
- const struct xe_mmio_range *implicit_ranges;
for (int type = 0; type < IMPLICIT_STEERING; type++) {
- if (!gt->steering[type].ranges)
- continue;
-
- for (int i = 0; gt->steering[type].ranges[i].end > 0; i++) {
- if (xe_mmio_in_range(>->mmio, >->steering[type].ranges[i], reg)) {
- drm_WARN(>_to_xe(gt)->drm, !gt->steering[type].initialized,
- "Uninitialized usage of MCR register %s/%#x\n",
- xe_steering_types[type].name, reg.addr);
-
- *group = gt->steering[type].group_target;
- *instance = gt->steering[type].instance_target;
- return true;
- }
+ if (reg_in_steering_type_ranges(gt, reg, type)) {
+ drm_WARN(>_to_xe(gt)->drm, !gt->steering[type].initialized,
+ "Uninitialized usage of MCR register %s/%#x\n",
+ xe_steering_types[type].name, reg.addr);
+
+ *group = gt->steering[type].group_target;
+ *instance = gt->steering[type].instance_target;
+ return true;
}
}
- implicit_ranges = gt->steering[IMPLICIT_STEERING].ranges;
- if (implicit_ranges)
- for (int i = 0; implicit_ranges[i].end > 0; i++)
- if (xe_mmio_in_range(>->mmio, &implicit_ranges[i], reg))
- return false;
+ if (reg_in_steering_type_ranges(gt, reg, IMPLICIT_STEERING))
+ return false;
/*
* Not found in a steering table and not a register with implicit
--
2.53.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 6.18.y 3/6] drm/xe/reg_sr: Do sanity check for MCR vs non-MCR
2026-08-01 3:03 ` [PATCH 6.18.y 1/6] drm/xe/lrc: Refactor out engine id to hwe conversion Sasha Levin
2026-08-01 3:03 ` [PATCH 6.18.y 2/6] drm/xe/mcr: Extract reg_in_steering_type_ranges() Sasha Levin
@ 2026-08-01 3:03 ` Sasha Levin
2026-08-01 3:03 ` [PATCH 6.18.y 4/6] drm/xe/rtp: Drop rule matching cases from rtp_to_sr_cases and rtp_cases Sasha Levin
` (2 subsequent siblings)
4 siblings, 0 replies; 7+ messages in thread
From: Sasha Levin @ 2026-08-01 3:03 UTC (permalink / raw)
To: stable; +Cc: Gustavo Sousa, Matt Roper, Sasha Levin
From: Gustavo Sousa <gustavo.sousa@intel.com>
[ Upstream commit 058da4a2b164e477b02ca0562f01a9eb9e621cdd ]
The type struct xe_reg_mcr exists to ensure that the correct API is used
when handling MCR registers. However, for the register save/restore
functionality, the RTP processing always cast the register to a struct
xe_reg and then apply_one_mmio() selects the MMIO API based on the "mcr"
field of the register instance.
This allows the developer to commit mistakes like passing a MCR register
for an RTP action for a GT where the respective register is not MCR; and
vice-versa.
To capture such scenarios, do a sanity check in xe_reg_sr_add() that,
upon an inconsistency:
- "fixes" the register type by favoring what we have in our MCR range
tables instead of what the developer selected for the save/restore
entry;
- raises a notice-level message to inform about the inconsistency.
Note: As a collateral of this change, we need to include MCR
initialization in xe_wa_test.c, otherwise a bunch of test cases end up
failing because xe_gt_mcr_check_reg() will always return false, meaning
that will incorrectly say that a MCR register is not MCR.
v2:
- Downgrade messages to notice level so as not to block CI execution
when inconsistencies are found. (Matt)
- Add missing EXPORT_SYMBOL_IF_KUNIT() calls. (Gustavo)
Reviewed-by: Matt Roper <matthew.d.roper@intel.com>
Link: https://patch.msgid.link/20260514-rtp-mcr-check-v3-7-30dd47855fee@intel.com
Signed-off-by: Gustavo Sousa <gustavo.sousa@intel.com>
Stable-dep-of: 31e243756162 ("drm/xe/rtp: Maintain OA whitelists separately")
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/gpu/drm/xe/tests/xe_rtp_test.c | 71 +++++++++++++++++++++++---
drivers/gpu/drm/xe/tests/xe_wa_test.c | 12 ++++-
drivers/gpu/drm/xe/xe_gt.c | 3 ++
drivers/gpu/drm/xe/xe_gt_mcr.c | 24 +++++++++
drivers/gpu/drm/xe/xe_gt_mcr.h | 1 +
drivers/gpu/drm/xe/xe_reg_sr.c | 36 +++++++++++++
6 files changed, 139 insertions(+), 8 deletions(-)
diff --git a/drivers/gpu/drm/xe/tests/xe_rtp_test.c b/drivers/gpu/drm/xe/tests/xe_rtp_test.c
index b0254b014fe4..8d4bd18a3161 100644
--- a/drivers/gpu/drm/xe/tests/xe_rtp_test.c
+++ b/drivers/gpu/drm/xe/tests/xe_rtp_test.c
@@ -9,24 +9,30 @@
#include <drm/drm_drv.h>
#include <drm/drm_kunit_helpers.h>
+#include <kunit/static_stub.h>
#include <kunit/test.h>
#include "regs/xe_gt_regs.h"
#include "regs/xe_reg_defs.h"
#include "xe_device.h"
#include "xe_device_types.h"
+#include "xe_gt_mcr.h"
#include "xe_kunit_helpers.h"
#include "xe_pci_test.h"
#include "xe_reg_sr.h"
#include "xe_rtp.h"
-#define REGULAR_REG1 XE_REG(1)
-#define REGULAR_REG2 XE_REG(2)
-#define REGULAR_REG3 XE_REG(3)
-#define MCR_REG1 XE_REG_MCR(1)
-#define MCR_REG2 XE_REG_MCR(2)
-#define MCR_REG3 XE_REG_MCR(3)
-#define MASKED_REG1 XE_REG(1, XE_REG_OPTION_MASKED)
+#define REGULAR_REG1 XE_REG(1)
+#define REGULAR_REG2 XE_REG(2)
+#define REGULAR_REG3 XE_REG(3)
+#define REGULAR_REG4 XE_REG(4)
+#define BAD_REGULAR_REG5 XE_REG(5)
+#define MCR_REG1 XE_REG_MCR(1)
+#define MCR_REG2 XE_REG_MCR(2)
+#define MCR_REG3 XE_REG_MCR(3)
+#define BAD_MCR_REG4 XE_REG_MCR(4)
+#define MCR_REG5 XE_REG_MCR(5)
+#define MASKED_REG1 XE_REG(1, XE_REG_OPTION_MASKED)
#undef XE_REG_MCR
#define XE_REG_MCR(...) XE_REG(__VA_ARGS__, .mcr = 1)
@@ -48,6 +54,23 @@ struct rtp_test_case {
const struct xe_rtp_entry *entries;
};
+static bool fake_xe_gt_mcr_check_reg(struct xe_gt *gt, struct xe_reg reg)
+{
+ /*
+ * All supported platforms in this imaginary setup will always have REG4
+ * as a non-MCR register and REG5 as MCR, meaning that BAD_MCR_REG4 and
+ * BAD_REGULAR_REG5 represent programming errors to be captured by our
+ * tests.
+ */
+ if (reg.raw == BAD_REGULAR_REG5.raw)
+ return true;
+
+ if (reg.raw == BAD_MCR_REG4.raw)
+ return false;
+
+ return reg.mcr;
+}
+
static bool match_yes(const struct xe_gt *gt, const struct xe_hw_engine *hwe)
{
return true;
@@ -302,6 +325,38 @@ static const struct rtp_to_sr_test_case rtp_to_sr_cases[] = {
{}
},
},
+ {
+ .name = "bad-mcr-reg-forced-to-regular",
+ .expected_reg = REGULAR_REG4,
+ .expected_set_bits = REG_BIT(0),
+ .expected_clr_bits = REG_BIT(0),
+ .expected_active = BIT(0),
+ .expected_count_sr_entries = 1,
+ .expected_sr_errors = 1,
+ .entries = (const struct xe_rtp_entry_sr[]) {
+ { XE_RTP_NAME("bad-mcr-regular-reg"),
+ XE_RTP_RULES(FUNC(match_yes)),
+ XE_RTP_ACTIONS(SET(BAD_MCR_REG4, REG_BIT(0)))
+ },
+ {}
+ },
+ },
+ {
+ .name = "bad-regular-reg-forced-to-mcr",
+ .expected_reg = MCR_REG5,
+ .expected_set_bits = REG_BIT(0),
+ .expected_clr_bits = REG_BIT(0),
+ .expected_active = BIT(0),
+ .expected_count_sr_entries = 1,
+ .expected_sr_errors = 1,
+ .entries = (const struct xe_rtp_entry_sr[]) {
+ { XE_RTP_NAME("bad-regular-reg"),
+ XE_RTP_RULES(FUNC(match_yes)),
+ XE_RTP_ACTIONS(SET(BAD_REGULAR_REG5, REG_BIT(0)))
+ },
+ {}
+ },
+ },
};
static void xe_rtp_process_to_sr_tests(struct kunit *test)
@@ -520,6 +575,8 @@ static int xe_rtp_test_init(struct kunit *test)
xe->drm.dev = dev;
test->priv = xe;
+ kunit_activate_static_stub(test, xe_gt_mcr_check_reg, fake_xe_gt_mcr_check_reg);
+
return 0;
}
diff --git a/drivers/gpu/drm/xe/tests/xe_wa_test.c b/drivers/gpu/drm/xe/tests/xe_wa_test.c
index 49d191043dfa..bb2c78a01bce 100644
--- a/drivers/gpu/drm/xe/tests/xe_wa_test.c
+++ b/drivers/gpu/drm/xe/tests/xe_wa_test.c
@@ -9,6 +9,8 @@
#include <kunit/test.h>
#include "xe_device.h"
+#include "xe_gt.h"
+#include "xe_gt_mcr.h"
#include "xe_kunit_helpers.h"
#include "xe_pci_test.h"
#include "xe_reg_sr.h"
@@ -19,8 +21,10 @@ static int xe_wa_test_init(struct kunit *test)
{
const struct xe_pci_fake_data *param = test->param_value;
struct xe_pci_fake_data data = *param;
- struct xe_device *xe;
struct device *dev;
+ struct xe_device *xe;
+ struct xe_gt *gt;
+ int id;
int ret;
dev = drm_kunit_helper_alloc_device(test);
@@ -33,6 +37,12 @@ static int xe_wa_test_init(struct kunit *test)
ret = xe_pci_fake_device_init(xe);
KUNIT_ASSERT_EQ(test, ret, 0);
+ /* Needed for sanitize_mcr(). */
+ for_each_gt(gt, xe, id) {
+ xe_gt_mcr_init_early(gt);
+ xe_gt_mmio_init(gt);
+ }
+
if (!param->graphics_verx100)
xe->info.step = param->step;
diff --git a/drivers/gpu/drm/xe/xe_gt.c b/drivers/gpu/drm/xe/xe_gt.c
index 109933529847..e9e1c531ce04 100644
--- a/drivers/gpu/drm/xe/xe_gt.c
+++ b/drivers/gpu/drm/xe/xe_gt.c
@@ -7,6 +7,8 @@
#include <linux/minmax.h>
+#include <kunit/visibility.h>
+
#include <drm/drm_managed.h>
#include <uapi/drm/xe_drm.h>
@@ -727,6 +729,7 @@ void xe_gt_mmio_init(struct xe_gt *gt)
if (IS_SRIOV_VF(xe))
gt->mmio.sriov_vf_gt = gt;
}
+EXPORT_SYMBOL_IF_KUNIT(xe_gt_mmio_init);
void xe_gt_record_user_engines(struct xe_gt *gt)
{
diff --git a/drivers/gpu/drm/xe/xe_gt_mcr.c b/drivers/gpu/drm/xe/xe_gt_mcr.c
index c7164604846f..2a70abc25b36 100644
--- a/drivers/gpu/drm/xe/xe_gt_mcr.c
+++ b/drivers/gpu/drm/xe/xe_gt_mcr.c
@@ -3,6 +3,9 @@
* Copyright © 2022 Intel Corporation
*/
+#include <kunit/static_stub.h>
+#include <kunit/visibility.h>
+
#include "xe_gt_mcr.h"
#include "regs/xe_gt_regs.h"
@@ -492,6 +495,7 @@ void xe_gt_mcr_init_early(struct xe_gt *gt)
/* Mark instance 0 as initialized, we need this early for VRAM and CCS probe. */
gt->steering[INSTANCE0].initialized = true;
}
+EXPORT_SYMBOL_IF_KUNIT(xe_gt_mcr_init_early);
/**
* xe_gt_mcr_init - Normal initialization of the MCR support
@@ -556,6 +560,26 @@ static bool reg_in_steering_type_ranges(struct xe_gt *gt,
return false;
}
+/*
+ * xe_gt_mcr_check_reg - check if a register is recognized by this GT as MCR
+ * @gt: GT structure
+ * @reg: The register to check
+ *
+ * Returns true if the register offset falls within one of the MMIO ranges
+ * classified as MCR for the GT.
+ */
+bool xe_gt_mcr_check_reg(struct xe_gt *gt, struct xe_reg reg)
+{
+ KUNIT_STATIC_STUB_REDIRECT(xe_gt_mcr_check_reg, gt, reg);
+
+ for (int type = 0; type <= IMPLICIT_STEERING; type++)
+ if (reg_in_steering_type_ranges(gt, reg, type))
+ return true;
+
+ return false;
+}
+EXPORT_SYMBOL_IF_KUNIT(xe_gt_mcr_check_reg);
+
/*
* xe_gt_mcr_get_nonterminated_steering - find group/instance values that
* will steer a register to a non-terminated instance
diff --git a/drivers/gpu/drm/xe/xe_gt_mcr.h b/drivers/gpu/drm/xe/xe_gt_mcr.h
index 283a1c9770e2..d6b50b52b1d5 100644
--- a/drivers/gpu/drm/xe/xe_gt_mcr.h
+++ b/drivers/gpu/drm/xe/xe_gt_mcr.h
@@ -26,6 +26,7 @@ void xe_gt_mcr_unicast_write(struct xe_gt *gt, struct xe_reg_mcr mcr_reg,
void xe_gt_mcr_multicast_write(struct xe_gt *gt, struct xe_reg_mcr mcr_reg,
u32 value);
+bool xe_gt_mcr_check_reg(struct xe_gt *gt, struct xe_reg reg);
bool xe_gt_mcr_get_nonterminated_steering(struct xe_gt *gt,
struct xe_reg_mcr reg_mcr,
u8 *group, u8 *instance);
diff --git a/drivers/gpu/drm/xe/xe_reg_sr.c b/drivers/gpu/drm/xe/xe_reg_sr.c
index 6b9edc7ca411..c146abcaf24e 100644
--- a/drivers/gpu/drm/xe/xe_reg_sr.c
+++ b/drivers/gpu/drm/xe/xe_reg_sr.c
@@ -71,14 +71,49 @@ static void reg_sr_inc_error(struct xe_reg_sr *sr)
#endif
}
+static struct xe_reg sanitize_mcr(struct xe_reg_sr *sr,
+ const struct xe_reg_sr_entry *e,
+ struct xe_gt *gt)
+{
+ struct xe_reg reg = e->reg;
+ bool is_mcr;
+
+ /*
+ * We need the gt structure to check MCR ranges.
+ */
+ if (!gt)
+ return reg;
+
+ is_mcr = xe_gt_mcr_check_reg(gt, reg);
+
+ if (is_mcr && !reg.mcr) {
+ reg.mcr = 1;
+ xe_gt_notice(gt, "xe_reg_sr_entry using non-MCR register for address 0x%x, forcing MCR\n",
+ reg.addr);
+ reg_sr_inc_error(sr);
+ }
+
+ if (!is_mcr && reg.mcr) {
+ reg.mcr = 0;
+ xe_gt_notice(gt, "xe_reg_sr_entry using MCR register for address 0x%x, forcing non-MCR\n",
+ reg.addr);
+ reg_sr_inc_error(sr);
+ }
+
+ return reg;
+}
+
int xe_reg_sr_add(struct xe_reg_sr *sr,
const struct xe_reg_sr_entry *e,
struct xe_gt *gt)
{
unsigned long idx = e->reg.addr;
struct xe_reg_sr_entry *pentry = xa_load(&sr->xa, idx);
+ struct xe_reg reg;
int ret;
+ reg = sanitize_mcr(sr, e, gt);
+
if (pentry) {
if (!compatible_entries(pentry, e)) {
ret = -EINVAL;
@@ -99,6 +134,7 @@ int xe_reg_sr_add(struct xe_reg_sr *sr,
}
*pentry = *e;
+ pentry->reg = reg;
ret = xa_err(xa_store(&sr->xa, idx, pentry, GFP_KERNEL));
if (ret)
goto fail_free;
--
2.53.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 6.18.y 4/6] drm/xe/rtp: Drop rule matching cases from rtp_to_sr_cases and rtp_cases
2026-08-01 3:03 ` [PATCH 6.18.y 1/6] drm/xe/lrc: Refactor out engine id to hwe conversion Sasha Levin
2026-08-01 3:03 ` [PATCH 6.18.y 2/6] drm/xe/mcr: Extract reg_in_steering_type_ranges() Sasha Levin
2026-08-01 3:03 ` [PATCH 6.18.y 3/6] drm/xe/reg_sr: Do sanity check for MCR vs non-MCR Sasha Levin
@ 2026-08-01 3:03 ` Sasha Levin
2026-08-01 3:03 ` [PATCH 6.18.y 5/6] drm/xe/rtp: Add struct types for RTP tables Sasha Levin
2026-08-01 3:03 ` [PATCH 6.18.y 6/6] drm/xe/rtp: Maintain OA whitelists separately Sasha Levin
4 siblings, 0 replies; 7+ messages in thread
From: Sasha Levin @ 2026-08-01 3:03 UTC (permalink / raw)
To: stable; +Cc: Gustavo Sousa, Matt Roper, Sasha Levin
From: Gustavo Sousa <gustavo.sousa@intel.com>
[ Upstream commit ff7746336b2325087aa7958d40f327bcc50185f8 ]
The kunit test cases for the RTP framework are currently separated into
three groups:
(1) rtp_rules_cases:
Those to verify rule matching logic.
(2) rtp_to_sr_cases:
Those to verify generation of save/restore tables from RTP tables.
(3) rtp_cases
Those to verify processing of RTP tables without save/restore action
associated, which are used for OOB workarounds.
Today we have some cases in (2) and (3) that are actually meant to
verify rule matching logic. Now that we have (1), let's cleanup (2)
and (3) so that they become focused on their main objectives.
Reviewed-by: Matt Roper <matthew.d.roper@intel.com>
Link: https://patch.msgid.link/20260522-rtp-rule-parser-v3-2-0c51039899f4@intel.com
Signed-off-by: Gustavo Sousa <gustavo.sousa@intel.com>
Stable-dep-of: 31e243756162 ("drm/xe/rtp: Maintain OA whitelists separately")
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/gpu/drm/xe/tests/xe_rtp_test.c | 122 ++-----------------------
1 file changed, 6 insertions(+), 116 deletions(-)
diff --git a/drivers/gpu/drm/xe/tests/xe_rtp_test.c b/drivers/gpu/drm/xe/tests/xe_rtp_test.c
index 8d4bd18a3161..61b75ca0db66 100644
--- a/drivers/gpu/drm/xe/tests/xe_rtp_test.c
+++ b/drivers/gpu/drm/xe/tests/xe_rtp_test.c
@@ -122,80 +122,6 @@ static const struct rtp_to_sr_test_case rtp_to_sr_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_active = BIT(0) | BIT(1) | BIT(2),
- .expected_count_sr_entries = 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_sr_entries = 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,
- .expected_set_bits = REG_BIT(0),
- .expected_clr_bits = REG_BIT(0),
- .expected_active = BIT(0),
- .expected_count_sr_entries = 1,
- /* Don't coalesce second entry due to one of the rules */
- .entries = (const struct xe_rtp_entry_sr[]) {
- { XE_RTP_NAME("basic-1"),
- XE_RTP_RULES(FUNC(match_yes)),
- XE_RTP_ACTIONS(SET(REGULAR_REG1, REG_BIT(0)))
- },
- { XE_RTP_NAME("basic-2"),
- XE_RTP_RULES(FUNC(match_yes), FUNC(match_no)),
- XE_RTP_ACTIONS(SET(REGULAR_REG1, REG_BIT(1)))
- },
- {}
- },
- },
{
.name = "two-regs-two-entries",
.expected_reg = REGULAR_REG1,
@@ -455,33 +381,15 @@ static const struct rtp_test_case rtp_cases[] = {
},
},
{
- .name = "inactive-1st_or_active-inactive",
+ .name = "inactive-active-inactive",
.expected_active = BIT(1),
.entries = (const struct xe_rtp_entry[]) {
{ XE_RTP_NAME("r1"),
XE_RTP_RULES(FUNC(match_no)),
},
- { XE_RTP_NAME("r2_or_conditions"),
- XE_RTP_RULES(FUNC(match_yes), OR,
- FUNC(match_no), OR,
- FUNC(match_no)) },
- { XE_RTP_NAME("r3"),
- XE_RTP_RULES(FUNC(match_no)),
- },
- {}
- },
- },
- {
- .name = "inactive-2nd_or_active-inactive",
- .expected_active = BIT(1),
- .entries = (const struct xe_rtp_entry[]) {
- { XE_RTP_NAME("r1"),
- XE_RTP_RULES(FUNC(match_no)),
+ { XE_RTP_NAME("r2"),
+ XE_RTP_RULES(FUNC(match_yes)),
},
- { XE_RTP_NAME("r2_or_conditions"),
- XE_RTP_RULES(FUNC(match_no), OR,
- FUNC(match_yes), OR,
- FUNC(match_no)) },
{ XE_RTP_NAME("r3"),
XE_RTP_RULES(FUNC(match_no)),
},
@@ -489,33 +397,15 @@ static const struct rtp_test_case rtp_cases[] = {
},
},
{
- .name = "inactive-last_or_active-inactive",
- .expected_active = BIT(1),
+ .name = "inactive-inactive-inactive",
+ .expected_active = 0,
.entries = (const struct xe_rtp_entry[]) {
{ XE_RTP_NAME("r1"),
XE_RTP_RULES(FUNC(match_no)),
},
- { XE_RTP_NAME("r2_or_conditions"),
- XE_RTP_RULES(FUNC(match_no), OR,
- FUNC(match_no), OR,
- FUNC(match_yes)) },
- { XE_RTP_NAME("r3"),
- XE_RTP_RULES(FUNC(match_no)),
- },
- {}
- },
- },
- {
- .name = "inactive-no_or_active-inactive",
- .expected_active = 0,
- .entries = (const struct xe_rtp_entry[]) {
- { XE_RTP_NAME("r1"),
+ { XE_RTP_NAME("r2"),
XE_RTP_RULES(FUNC(match_no)),
},
- { XE_RTP_NAME("r2_or_conditions"),
- XE_RTP_RULES(FUNC(match_no), OR,
- FUNC(match_no), OR,
- FUNC(match_no)) },
{ XE_RTP_NAME("r3"),
XE_RTP_RULES(FUNC(match_no)),
},
--
2.53.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 6.18.y 5/6] drm/xe/rtp: Add struct types for RTP tables
2026-08-01 3:03 ` [PATCH 6.18.y 1/6] drm/xe/lrc: Refactor out engine id to hwe conversion Sasha Levin
` (2 preceding siblings ...)
2026-08-01 3:03 ` [PATCH 6.18.y 4/6] drm/xe/rtp: Drop rule matching cases from rtp_to_sr_cases and rtp_cases Sasha Levin
@ 2026-08-01 3:03 ` Sasha Levin
2026-08-01 3:03 ` [PATCH 6.18.y 6/6] drm/xe/rtp: Maintain OA whitelists separately Sasha Levin
4 siblings, 0 replies; 7+ messages in thread
From: Sasha Levin @ 2026-08-01 3:03 UTC (permalink / raw)
To: stable
Cc: Gustavo Sousa, Matt Roper, Violet Monti, Thomas Hellström,
Sasha Levin
From: Gustavo Sousa <gustavo.sousa@intel.com>
[ Upstream commit e23fafb8594ea886ee03e005cc32dfda24f417cf ]
We currently have a mixture of styles for our RTP tables with respect of
how we define the number of entries:
* xe_rtp_process_to_sr() expects to receive the number of entries as
arguments;
* xe_rtp_process() expects the array to have a sentinel at the end of
the array;
* in xe_rtp_test.c, even though xe_rtp_process_to_sr() does not
require a sentinel value, we need to rely on that technique to be
able to count xe_rtp_entry_sr entries because simply using
ARRAY_SIZE() is not possible.
The style used by xe_rtp_process_to_sr() makes it hard to share the
tables with other compilation units (e.g. kunit tests), since the number
of entries is calculated with ARRAY_SIZE(), which is done at compile
time.
Since we use the size of the tables to create some bitmasks, using a
sentinel style doesn't seem great either.
A way to reconcile things into a single style is to have a struct type
that would hold the entries array and the number of entries. Since we
have xe_rtp_entry and xe_rtp_entry_sr, we would have one type for each.
The advantage of the proposed approach is that now we have a nice way to
share the tables directly to kunit tests with information about their
size.
v6:
- Removed sentinels that are not needed
v5:
- Removed added code from conflict resolution issues
v4:
- Removed conflicts with main branch
v3:
- No changes
v2:
- Add compatibility with new xe_rtp_table_sr format for
"bad-mcr-reg-forced-to-regular" and
"bad-regular-reg-forced-to-mcr"
Fixes: 828a8eaf37c3 ("drm/xe/oa: Add MMIO trigger support")
Cc: stable@vger.kernel.org # v6.12+
Reviewed-by: Matt Roper <matthew.d.roper@intel.com>
Signed-off-by: Gustavo Sousa <gustavo.sousa@intel.com>
Signed-off-by: Violet Monti <violet.monti@intel.com>
Link: https://patch.msgid.link/20260601200947.2032784-7-violet.monti@intel.com
Signed-off-by: Matt Roper <matthew.d.roper@intel.com>
(cherry picked from commit 5ff004fdc7377905f2fe5264b8829d35e14608b8)
Signed-off-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>
Stable-dep-of: 31e243756162 ("drm/xe/rtp: Maintain OA whitelists separately")
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/gpu/drm/xe/tests/xe_rtp_test.c | 102 ++++++++++---------------
drivers/gpu/drm/xe/xe_hw_engine.c | 12 +--
drivers/gpu/drm/xe/xe_reg_whitelist.c | 7 +-
drivers/gpu/drm/xe/xe_rtp.c | 45 ++++++-----
drivers/gpu/drm/xe/xe_rtp.h | 17 ++++-
drivers/gpu/drm/xe/xe_rtp_types.h | 10 +++
drivers/gpu/drm/xe/xe_tuning.c | 43 +++++------
drivers/gpu/drm/xe/xe_wa.c | 86 +++++++++++----------
8 files changed, 167 insertions(+), 155 deletions(-)
diff --git a/drivers/gpu/drm/xe/tests/xe_rtp_test.c b/drivers/gpu/drm/xe/tests/xe_rtp_test.c
index 61b75ca0db66..d6a7e51901bb 100644
--- a/drivers/gpu/drm/xe/tests/xe_rtp_test.c
+++ b/drivers/gpu/drm/xe/tests/xe_rtp_test.c
@@ -45,13 +45,13 @@ struct rtp_to_sr_test_case {
unsigned long expected_count_sr_entries;
unsigned int expected_sr_errors;
unsigned long expected_active;
- const struct xe_rtp_entry_sr *entries;
+ const struct xe_rtp_table_sr table;
};
struct rtp_test_case {
const char *name;
unsigned long expected_active;
- const struct xe_rtp_entry *entries;
+ const struct xe_rtp_table table;
};
static bool fake_xe_gt_mcr_check_reg(struct xe_gt *gt, struct xe_reg reg)
@@ -90,7 +90,7 @@ static const struct rtp_to_sr_test_case rtp_to_sr_cases[] = {
.expected_active = BIT(0) | BIT(1),
.expected_count_sr_entries = 1,
/* Different bits on the same register: create a single entry */
- .entries = (const struct xe_rtp_entry_sr[]) {
+ .table = XE_RTP_TABLE_SR(
{ XE_RTP_NAME("basic-1"),
XE_RTP_RULES(FUNC(match_yes)),
XE_RTP_ACTIONS(SET(REGULAR_REG1, REG_BIT(0)))
@@ -99,8 +99,7 @@ static const struct rtp_to_sr_test_case rtp_to_sr_cases[] = {
XE_RTP_RULES(FUNC(match_yes)),
XE_RTP_ACTIONS(SET(REGULAR_REG1, REG_BIT(1)))
},
- {}
- },
+ ),
},
{
.name = "no-match-no-add",
@@ -110,7 +109,7 @@ static const struct rtp_to_sr_test_case rtp_to_sr_cases[] = {
.expected_active = BIT(0),
.expected_count_sr_entries = 1,
/* Don't coalesce second entry since rules don't match */
- .entries = (const struct xe_rtp_entry_sr[]) {
+ .table = XE_RTP_TABLE_SR(
{ XE_RTP_NAME("basic-1"),
XE_RTP_RULES(FUNC(match_yes)),
XE_RTP_ACTIONS(SET(REGULAR_REG1, REG_BIT(0)))
@@ -119,8 +118,7 @@ static const struct rtp_to_sr_test_case rtp_to_sr_cases[] = {
XE_RTP_RULES(FUNC(match_no)),
XE_RTP_ACTIONS(SET(REGULAR_REG1, REG_BIT(1)))
},
- {}
- },
+ ),
},
{
.name = "two-regs-two-entries",
@@ -130,7 +128,7 @@ static const struct rtp_to_sr_test_case rtp_to_sr_cases[] = {
.expected_active = BIT(0) | BIT(1),
.expected_count_sr_entries = 2,
/* Same bits on different registers are not coalesced */
- .entries = (const struct xe_rtp_entry_sr[]) {
+ .table = XE_RTP_TABLE_SR(
{ XE_RTP_NAME("basic-1"),
XE_RTP_RULES(FUNC(match_yes)),
XE_RTP_ACTIONS(SET(REGULAR_REG1, REG_BIT(0)))
@@ -139,8 +137,7 @@ static const struct rtp_to_sr_test_case rtp_to_sr_cases[] = {
XE_RTP_RULES(FUNC(match_yes)),
XE_RTP_ACTIONS(SET(REGULAR_REG2, REG_BIT(0)))
},
- {}
- },
+ ),
},
{
.name = "clr-one-set-other",
@@ -150,7 +147,7 @@ static const struct rtp_to_sr_test_case rtp_to_sr_cases[] = {
.expected_active = BIT(0) | BIT(1),
.expected_count_sr_entries = 1,
/* Check clr vs set actions on different bits */
- .entries = (const struct xe_rtp_entry_sr[]) {
+ .table = XE_RTP_TABLE_SR(
{ XE_RTP_NAME("basic-1"),
XE_RTP_RULES(FUNC(match_yes)),
XE_RTP_ACTIONS(SET(REGULAR_REG1, REG_BIT(0)))
@@ -159,8 +156,7 @@ static const struct rtp_to_sr_test_case rtp_to_sr_cases[] = {
XE_RTP_RULES(FUNC(match_yes)),
XE_RTP_ACTIONS(CLR(REGULAR_REG1, REG_BIT(1)))
},
- {}
- },
+ ),
},
{
#define TEMP_MASK REG_GENMASK(10, 8)
@@ -172,14 +168,13 @@ static const struct rtp_to_sr_test_case rtp_to_sr_cases[] = {
.expected_active = BIT(0),
.expected_count_sr_entries = 1,
/* Check FIELD_SET works */
- .entries = (const struct xe_rtp_entry_sr[]) {
+ .table = XE_RTP_TABLE_SR(
{ XE_RTP_NAME("basic-1"),
XE_RTP_RULES(FUNC(match_yes)),
XE_RTP_ACTIONS(FIELD_SET(REGULAR_REG1,
TEMP_MASK, TEMP_FIELD))
},
- {}
- },
+ ),
#undef TEMP_MASK
#undef TEMP_FIELD
},
@@ -191,7 +186,7 @@ static const struct rtp_to_sr_test_case rtp_to_sr_cases[] = {
.expected_active = BIT(0) | BIT(1),
.expected_count_sr_entries = 1,
.expected_sr_errors = 1,
- .entries = (const struct xe_rtp_entry_sr[]) {
+ .table = XE_RTP_TABLE_SR(
{ XE_RTP_NAME("basic-1"),
XE_RTP_RULES(FUNC(match_yes)),
XE_RTP_ACTIONS(SET(REGULAR_REG1, REG_BIT(0)))
@@ -201,8 +196,7 @@ static const struct rtp_to_sr_test_case rtp_to_sr_cases[] = {
XE_RTP_RULES(FUNC(match_yes)),
XE_RTP_ACTIONS(SET(REGULAR_REG1, REG_BIT(0)))
},
- {}
- },
+ ),
},
{
.name = "conflict-not-disjoint",
@@ -212,7 +206,7 @@ static const struct rtp_to_sr_test_case rtp_to_sr_cases[] = {
.expected_active = BIT(0) | BIT(1),
.expected_count_sr_entries = 1,
.expected_sr_errors = 1,
- .entries = (const struct xe_rtp_entry_sr[]) {
+ .table = XE_RTP_TABLE_SR(
{ XE_RTP_NAME("basic-1"),
XE_RTP_RULES(FUNC(match_yes)),
XE_RTP_ACTIONS(SET(REGULAR_REG1, REG_BIT(0)))
@@ -222,8 +216,7 @@ static const struct rtp_to_sr_test_case rtp_to_sr_cases[] = {
XE_RTP_RULES(FUNC(match_yes)),
XE_RTP_ACTIONS(CLR(REGULAR_REG1, REG_GENMASK(1, 0)))
},
- {}
- },
+ ),
},
{
.name = "conflict-reg-type",
@@ -233,7 +226,7 @@ static const struct rtp_to_sr_test_case rtp_to_sr_cases[] = {
.expected_active = BIT(0) | BIT(1) | BIT(2),
.expected_count_sr_entries = 1,
.expected_sr_errors = 2,
- .entries = (const struct xe_rtp_entry_sr[]) {
+ .table = XE_RTP_TABLE_SR(
{ XE_RTP_NAME("basic-1"),
XE_RTP_RULES(FUNC(match_yes)),
XE_RTP_ACTIONS(SET(REGULAR_REG1, REG_BIT(0)))
@@ -248,8 +241,7 @@ static const struct rtp_to_sr_test_case rtp_to_sr_cases[] = {
XE_RTP_RULES(FUNC(match_yes)),
XE_RTP_ACTIONS(SET(MASKED_REG1, REG_BIT(0)))
},
- {}
- },
+ ),
},
{
.name = "bad-mcr-reg-forced-to-regular",
@@ -259,13 +251,12 @@ static const struct rtp_to_sr_test_case rtp_to_sr_cases[] = {
.expected_active = BIT(0),
.expected_count_sr_entries = 1,
.expected_sr_errors = 1,
- .entries = (const struct xe_rtp_entry_sr[]) {
+ .table = XE_RTP_TABLE_SR(
{ XE_RTP_NAME("bad-mcr-regular-reg"),
XE_RTP_RULES(FUNC(match_yes)),
XE_RTP_ACTIONS(SET(BAD_MCR_REG4, REG_BIT(0)))
},
- {}
- },
+ ),
},
{
.name = "bad-regular-reg-forced-to-mcr",
@@ -275,13 +266,12 @@ static const struct rtp_to_sr_test_case rtp_to_sr_cases[] = {
.expected_active = BIT(0),
.expected_count_sr_entries = 1,
.expected_sr_errors = 1,
- .entries = (const struct xe_rtp_entry_sr[]) {
+ .table = XE_RTP_TABLE_SR(
{ XE_RTP_NAME("bad-regular-reg"),
XE_RTP_RULES(FUNC(match_yes)),
XE_RTP_ACTIONS(SET(BAD_REGULAR_REG5, REG_BIT(0)))
},
- {}
- },
+ ),
},
};
@@ -293,15 +283,12 @@ static void xe_rtp_process_to_sr_tests(struct kunit *test)
struct xe_reg_sr *reg_sr = >->reg_sr;
const struct xe_reg_sr_entry *sre, *sr_entry = NULL;
struct xe_rtp_process_ctx ctx = XE_RTP_PROCESS_CTX_INITIALIZER(gt);
- unsigned long idx, count_sr_entries = 0, count_rtp_entries = 0, active = 0;
+ unsigned long idx, count_sr_entries = 0, active = 0;
xe_reg_sr_init(reg_sr, "xe_rtp_to_sr_tests", xe);
- while (param->entries[count_rtp_entries].rules)
- count_rtp_entries++;
-
- xe_rtp_process_ctx_enable_active_tracking(&ctx, &active, count_rtp_entries);
- xe_rtp_process_to_sr(&ctx, param->entries, count_rtp_entries, reg_sr);
+ xe_rtp_process_ctx_enable_active_tracking(&ctx, &active, param->table.n_entries);
+ xe_rtp_process_to_sr(&ctx, ¶m->table, reg_sr, false);
xa_for_each(®_sr->xa, idx, sre) {
if (idx == param->expected_reg.addr)
@@ -334,56 +321,52 @@ static const struct rtp_test_case rtp_cases[] = {
{
.name = "active1",
.expected_active = BIT(0),
- .entries = (const struct xe_rtp_entry[]) {
+ .table = XE_RTP_TABLE(
{ XE_RTP_NAME("r1"),
XE_RTP_RULES(FUNC(match_yes)),
},
- {}
- },
+ ),
},
{
.name = "active2",
.expected_active = BIT(0) | BIT(1),
- .entries = (const struct xe_rtp_entry[]) {
+ .table = XE_RTP_TABLE(
{ XE_RTP_NAME("r1"),
XE_RTP_RULES(FUNC(match_yes)),
},
{ XE_RTP_NAME("r2"),
XE_RTP_RULES(FUNC(match_yes)),
},
- {}
- },
+ ),
},
{
.name = "active-inactive",
.expected_active = BIT(0),
- .entries = (const struct xe_rtp_entry[]) {
+ .table = XE_RTP_TABLE(
{ XE_RTP_NAME("r1"),
XE_RTP_RULES(FUNC(match_yes)),
},
{ XE_RTP_NAME("r2"),
XE_RTP_RULES(FUNC(match_no)),
},
- {}
- },
+ ),
},
{
.name = "inactive-active",
.expected_active = BIT(1),
- .entries = (const struct xe_rtp_entry[]) {
+ .table = XE_RTP_TABLE(
{ XE_RTP_NAME("r1"),
XE_RTP_RULES(FUNC(match_no)),
},
{ XE_RTP_NAME("r2"),
XE_RTP_RULES(FUNC(match_yes)),
},
- {}
- },
+ ),
},
{
.name = "inactive-active-inactive",
.expected_active = BIT(1),
- .entries = (const struct xe_rtp_entry[]) {
+ .table = XE_RTP_TABLE(
{ XE_RTP_NAME("r1"),
XE_RTP_RULES(FUNC(match_no)),
},
@@ -393,13 +376,12 @@ static const struct rtp_test_case rtp_cases[] = {
{ XE_RTP_NAME("r3"),
XE_RTP_RULES(FUNC(match_no)),
},
- {}
- },
+ ),
},
{
.name = "inactive-inactive-inactive",
.expected_active = 0,
- .entries = (const struct xe_rtp_entry[]) {
+ .table = XE_RTP_TABLE(
{ XE_RTP_NAME("r1"),
XE_RTP_RULES(FUNC(match_no)),
},
@@ -409,8 +391,7 @@ static const struct rtp_test_case rtp_cases[] = {
{ XE_RTP_NAME("r3"),
XE_RTP_RULES(FUNC(match_no)),
},
- {}
- },
+ ),
},
};
@@ -420,13 +401,10 @@ static void xe_rtp_process_tests(struct kunit *test)
struct xe_device *xe = test->priv;
struct xe_gt *gt = xe_device_get_root_tile(xe)->primary_gt;
struct xe_rtp_process_ctx ctx = XE_RTP_PROCESS_CTX_INITIALIZER(gt);
- unsigned long count_rtp_entries = 0, active = 0;
-
- while (param->entries[count_rtp_entries].rules)
- count_rtp_entries++;
+ unsigned long active = 0;
- xe_rtp_process_ctx_enable_active_tracking(&ctx, &active, count_rtp_entries);
- xe_rtp_process(&ctx, param->entries);
+ xe_rtp_process_ctx_enable_active_tracking(&ctx, &active, param->table.n_entries);
+ xe_rtp_process(&ctx, ¶m->table);
KUNIT_EXPECT_EQ(test, active, param->expected_active);
}
diff --git a/drivers/gpu/drm/xe/xe_hw_engine.c b/drivers/gpu/drm/xe/xe_hw_engine.c
index d88770370eeb..e5241bf3024c 100644
--- a/drivers/gpu/drm/xe/xe_hw_engine.c
+++ b/drivers/gpu/drm/xe/xe_hw_engine.c
@@ -375,7 +375,7 @@ xe_hw_engine_setup_default_lrc_state(struct xe_hw_engine *hwe)
u32 blit_cctl_val = REG_FIELD_PREP(BLIT_CCTL_DST_MOCS_MASK, mocs_write_idx) |
REG_FIELD_PREP(BLIT_CCTL_SRC_MOCS_MASK, mocs_read_idx);
struct xe_rtp_process_ctx ctx = XE_RTP_PROCESS_CTX_INITIALIZER(hwe);
- const struct xe_rtp_entry_sr lrc_setup[] = {
+ const struct xe_rtp_table_sr lrc_setup = XE_RTP_TABLE_SR(
/*
* Some blitter commands do not have a field for MOCS, those
* commands will use MOCS index pointed by BLIT_CCTL.
@@ -398,9 +398,9 @@ xe_hw_engine_setup_default_lrc_state(struct xe_hw_engine *hwe)
PREEMPT_GPGPU_THREAD_GROUP_LEVEL)),
XE_RTP_ENTRY_FLAG(FOREACH_ENGINE)
},
- };
+ );
- xe_rtp_process_to_sr(&ctx, lrc_setup, ARRAY_SIZE(lrc_setup), &hwe->reg_lrc);
+ xe_rtp_process_to_sr(&ctx, &lrc_setup, &hwe->reg_lrc, true);
}
static void
@@ -425,7 +425,7 @@ hw_engine_setup_default_state(struct xe_hw_engine *hwe)
u32 ring_cmd_cctl_val = REG_FIELD_PREP(CMD_CCTL_WRITE_OVERRIDE_MASK, mocs_write_idx) |
REG_FIELD_PREP(CMD_CCTL_READ_OVERRIDE_MASK, mocs_read_idx);
struct xe_rtp_process_ctx ctx = XE_RTP_PROCESS_CTX_INITIALIZER(hwe);
- const struct xe_rtp_entry_sr engine_entries[] = {
+ const struct xe_rtp_table_sr engine_sr = XE_RTP_TABLE_SR(
{ XE_RTP_NAME("RING_CMD_CCTL_default_MOCS"),
XE_RTP_RULES(GRAPHICS_VERSION_RANGE(1200, XE_RTP_END_VERSION_UNDEFINED)),
XE_RTP_ACTIONS(FIELD_SET(RING_CMD_CCTL(0),
@@ -462,9 +462,9 @@ hw_engine_setup_default_state(struct xe_hw_engine *hwe)
XE_RTP_ACTIONS(FIELD_SET(RCU_MODE, RCU_MODE_FIXED_SLICE_CCS_MODE,
RCU_MODE_FIXED_SLICE_CCS_MODE))
},
- };
+ );
- xe_rtp_process_to_sr(&ctx, engine_entries, ARRAY_SIZE(engine_entries), &hwe->reg_sr);
+ xe_rtp_process_to_sr(&ctx, &engine_sr, &hwe->reg_sr, false);
}
static const struct engine_info *find_engine_info(enum xe_engine_class class, int instance)
diff --git a/drivers/gpu/drm/xe/xe_reg_whitelist.c b/drivers/gpu/drm/xe/xe_reg_whitelist.c
index 21763dc51150..7c37d20b0970 100644
--- a/drivers/gpu/drm/xe/xe_reg_whitelist.c
+++ b/drivers/gpu/drm/xe/xe_reg_whitelist.c
@@ -25,7 +25,7 @@ static bool match_not_render(const struct xe_gt *gt,
return hwe->class != XE_ENGINE_CLASS_RENDER;
}
-static const struct xe_rtp_entry_sr register_whitelist[] = {
+static const struct xe_rtp_table_sr register_whitelist = XE_RTP_TABLE_SR(
{ XE_RTP_NAME("WaAllowPMDepthAndInvocationCountAccessFromUMD, 1408556865"),
XE_RTP_RULES(GRAPHICS_VERSION_RANGE(1200, 1210), ENGINE_CLASS(RENDER)),
XE_RTP_ACTIONS(WHITELIST(PS_INVOCATION_COUNT,
@@ -88,7 +88,7 @@ static const struct xe_rtp_entry_sr register_whitelist[] = {
RING_FORCE_TO_NONPRIV_ACCESS_RD |
RING_FORCE_TO_NONPRIV_RANGE_4))
},
-};
+);
static void whitelist_apply_to_hwe(struct xe_hw_engine *hwe)
{
@@ -136,8 +136,7 @@ void xe_reg_whitelist_process_engine(struct xe_hw_engine *hwe)
{
struct xe_rtp_process_ctx ctx = XE_RTP_PROCESS_CTX_INITIALIZER(hwe);
- xe_rtp_process_to_sr(&ctx, register_whitelist, ARRAY_SIZE(register_whitelist),
- &hwe->reg_whitelist);
+ xe_rtp_process_to_sr(&ctx, ®ister_whitelist, &hwe->reg_whitelist, false);
whitelist_apply_to_hwe(hwe);
}
diff --git a/drivers/gpu/drm/xe/xe_rtp.c b/drivers/gpu/drm/xe/xe_rtp.c
index b5f430d59f80..bb71f839832d 100644
--- a/drivers/gpu/drm/xe/xe_rtp.c
+++ b/drivers/gpu/drm/xe/xe_rtp.c
@@ -269,31 +269,35 @@ static void rtp_mark_active(struct xe_device *xe,
* xe_rtp_process_to_sr - Process all rtp @entries, adding the matching ones to
* the save-restore argument.
* @ctx: The context for processing the table, with one of device, gt or hwe
- * @entries: Table with RTP definitions
- * @n_entries: Number of entries to process, usually ARRAY_SIZE(entries)
+ * @table: Table with RTP definitions
* @sr: Save-restore struct where matching rules execute the action. This can be
* viewed as the "coalesced view" of multiple the tables. The bits for each
* register set are expected not to collide with previously added entries
+ * @process_in_vf: Whether this RTP table should get processed for SR-IOV VF
+ * devices. Should generally only be 'true' for LRC tables.
*
- * Walk the table pointed by @entries (with an empty sentinel) and add all
- * entries with matching rules to @sr. If @hwe is not NULL, its mmio_base is
- * used to calculate the right register offset
+ * Walk the table pointed by @table and add all entries with matching rules to
+ * @sr. If @hwe is not NULL, its mmio_base is used to calculate the right
+ * register offset
*/
void xe_rtp_process_to_sr(struct xe_rtp_process_ctx *ctx,
- const struct xe_rtp_entry_sr *entries,
- size_t n_entries,
- struct xe_reg_sr *sr)
+ const struct xe_rtp_table_sr *table,
+ struct xe_reg_sr *sr,
+ bool process_in_vf)
{
- const struct xe_rtp_entry_sr *entry;
struct xe_hw_engine *hwe = NULL;
struct xe_gt *gt = NULL;
struct xe_device *xe = NULL;
rtp_get_context(ctx, &hwe, >, &xe);
- xe_assert(xe, entries);
+ if (!process_in_vf && IS_SRIOV_VF(xe))
+ return;
+
+ xe_assert(xe, table->entries);
- for (entry = entries; entry - entries < n_entries; entry++) {
+ for (size_t i = 0; i < table->n_entries; i++) {
+ const struct xe_rtp_entry_sr *entry = &table->entries[i];
bool match = false;
if (entry->flags & XE_RTP_ENTRY_FLAG_FOREACH_ENGINE) {
@@ -308,37 +312,40 @@ void xe_rtp_process_to_sr(struct xe_rtp_process_ctx *ctx,
}
if (match)
- rtp_mark_active(xe, ctx, entry - entries);
+ rtp_mark_active(xe, ctx, i);
}
}
EXPORT_SYMBOL_IF_KUNIT(xe_rtp_process_to_sr);
/**
- * xe_rtp_process - Process all rtp @entries, without running any action
+ * xe_rtp_process - Process all entries in rtp @table, without running any action
* @ctx: The context for processing the table, with one of device, gt or hwe
- * @entries: Table with RTP definitions
+ * @table: Table with RTP definitions
*
- * Walk the table pointed by @entries (with an empty sentinel), executing the
+ * Walk the table pointed by @table, executing the
* rules. One difference from xe_rtp_process_to_sr(): there is no action
* associated with each entry since this uses struct xe_rtp_entry. Its main use
* is for marking active workarounds via
* xe_rtp_process_ctx_enable_active_tracking().
*/
void xe_rtp_process(struct xe_rtp_process_ctx *ctx,
- const struct xe_rtp_entry *entries)
+ const struct xe_rtp_table *table)
{
- const struct xe_rtp_entry *entry;
struct xe_hw_engine *hwe;
struct xe_gt *gt;
struct xe_device *xe;
rtp_get_context(ctx, &hwe, >, &xe);
- for (entry = entries; entry && entry->rules; entry++) {
+ xe_assert(xe, table->entries);
+
+ for (size_t i = 0; i < table->n_entries; i++) {
+ const struct xe_rtp_entry *entry = &table->entries[i];
+
if (!rule_matches(xe, gt, hwe, entry->rules, entry->n_rules))
continue;
- rtp_mark_active(xe, ctx, entry - entries);
+ rtp_mark_active(xe, ctx, i);
}
}
EXPORT_SYMBOL_IF_KUNIT(xe_rtp_process);
diff --git a/drivers/gpu/drm/xe/xe_rtp.h b/drivers/gpu/drm/xe/xe_rtp.h
index ac12ddf6cde6..086b96417770 100644
--- a/drivers/gpu/drm/xe/xe_rtp.h
+++ b/drivers/gpu/drm/xe/xe_rtp.h
@@ -420,6 +420,16 @@ struct xe_reg_sr;
XE_RTP_PASTE_FOREACH(ACTION_, COMMA, (__VA_ARGS__)) \
}
+#define XE_RTP_TABLE_SR(...) { \
+ .entries = (const struct xe_rtp_entry_sr[]){__VA_ARGS__}, \
+ .n_entries = ARRAY_SIZE(((const struct xe_rtp_entry_sr[]){__VA_ARGS__})), \
+}
+
+#define XE_RTP_TABLE(...) { \
+ .entries = (const struct xe_rtp_entry[]){__VA_ARGS__}, \
+ .n_entries = ARRAY_SIZE(((const struct xe_rtp_entry[]){__VA_ARGS__})), \
+}
+
#define XE_RTP_PROCESS_CTX_INITIALIZER(arg__) _Generic((arg__), \
struct xe_hw_engine * : (struct xe_rtp_process_ctx){ { (void *)(arg__) }, XE_RTP_PROCESS_TYPE_ENGINE }, \
struct xe_gt * : (struct xe_rtp_process_ctx){ { (void *)(arg__) }, XE_RTP_PROCESS_TYPE_GT }, \
@@ -430,11 +440,12 @@ void xe_rtp_process_ctx_enable_active_tracking(struct xe_rtp_process_ctx *ctx,
size_t n_entries);
void xe_rtp_process_to_sr(struct xe_rtp_process_ctx *ctx,
- const struct xe_rtp_entry_sr *entries,
- size_t n_entries, struct xe_reg_sr *sr);
+ const struct xe_rtp_table_sr *table,
+ struct xe_reg_sr *sr,
+ bool process_in_vf);
void xe_rtp_process(struct xe_rtp_process_ctx *ctx,
- const struct xe_rtp_entry *entries);
+ const struct xe_rtp_table *table);
/* Match functions to be used with XE_RTP_MATCH_FUNC */
diff --git a/drivers/gpu/drm/xe/xe_rtp_types.h b/drivers/gpu/drm/xe/xe_rtp_types.h
index f4cf30e298cf..fbf108b9bb7e 100644
--- a/drivers/gpu/drm/xe/xe_rtp_types.h
+++ b/drivers/gpu/drm/xe/xe_rtp_types.h
@@ -109,6 +109,16 @@ struct xe_rtp_entry {
u8 n_rules;
};
+struct xe_rtp_table_sr {
+ const struct xe_rtp_entry_sr *entries;
+ size_t n_entries;
+};
+
+struct xe_rtp_table {
+ const struct xe_rtp_entry *entries;
+ size_t n_entries;
+};
+
enum xe_rtp_process_type {
XE_RTP_PROCESS_TYPE_DEVICE,
XE_RTP_PROCESS_TYPE_GT,
diff --git a/drivers/gpu/drm/xe/xe_tuning.c b/drivers/gpu/drm/xe/xe_tuning.c
index a524170a04d0..90e01b51dd36 100644
--- a/drivers/gpu/drm/xe/xe_tuning.c
+++ b/drivers/gpu/drm/xe/xe_tuning.c
@@ -17,7 +17,7 @@
#undef XE_REG_MCR
#define XE_REG_MCR(...) XE_REG(__VA_ARGS__, .mcr = 1)
-static const struct xe_rtp_entry_sr gt_tunings[] = {
+static const struct xe_rtp_table_sr gt_tunings = XE_RTP_TABLE_SR(
{ XE_RTP_NAME("Tuning: Blend Fill Caching Optimization Disable"),
XE_RTP_RULES(PLATFORM(DG2)),
XE_RTP_ACTIONS(SET(XEHP_L3SCQREG7, BLEND_FILL_CACHING_OPT_DIS))
@@ -85,9 +85,9 @@ static const struct xe_rtp_entry_sr gt_tunings[] = {
XE_RTP_RULES(MEDIA_VERSION(2000)),
XE_RTP_ACTIONS(SET(XE2LPM_SCRATCH3_LBCF, RWFLUSHALLEN))
},
-};
+);
-static const struct xe_rtp_entry_sr engine_tunings[] = {
+static const struct xe_rtp_table_sr engine_tunings = XE_RTP_TABLE_SR(
{ XE_RTP_NAME("Tuning: L3 Hashing Mask"),
XE_RTP_RULES(GRAPHICS_VERSION_RANGE(1200, 1210),
FUNC(xe_rtp_match_first_render_or_compute)),
@@ -103,9 +103,9 @@ static const struct xe_rtp_entry_sr engine_tunings[] = {
FUNC(xe_rtp_match_first_render_or_compute)),
XE_RTP_ACTIONS(SET(RT_CTRL, DIS_NULL_QUERY))
},
-};
+);
-static const struct xe_rtp_entry_sr lrc_tunings[] = {
+static const struct xe_rtp_table_sr lrc_tunings = XE_RTP_TABLE_SR(
/* DG2 */
{ XE_RTP_NAME("Tuning: L3 cache"),
@@ -140,7 +140,7 @@ static const struct xe_rtp_entry_sr lrc_tunings[] = {
XE_RTP_ACTIONS(FIELD_SET(FF_MODE, VS_HIT_MAX_VALUE_MASK,
REG_FIELD_PREP(VS_HIT_MAX_VALUE_MASK, 0x3f)))
},
-};
+);
/**
* xe_tuning_init - initialize gt with tunings bookkeeping
@@ -154,9 +154,9 @@ int xe_tuning_init(struct xe_gt *gt)
size_t n_lrc, n_engine, n_gt, total;
unsigned long *p;
- n_gt = BITS_TO_LONGS(ARRAY_SIZE(gt_tunings));
- n_engine = BITS_TO_LONGS(ARRAY_SIZE(engine_tunings));
- n_lrc = BITS_TO_LONGS(ARRAY_SIZE(lrc_tunings));
+ n_gt = BITS_TO_LONGS(gt_tunings.n_entries);
+ n_engine = BITS_TO_LONGS(engine_tunings.n_entries);
+ n_lrc = BITS_TO_LONGS(lrc_tunings.n_entries);
total = n_gt + n_engine + n_lrc;
p = drmm_kzalloc(&xe->drm, sizeof(*p) * total, GFP_KERNEL);
@@ -179,8 +179,8 @@ void xe_tuning_process_gt(struct xe_gt *gt)
xe_rtp_process_ctx_enable_active_tracking(&ctx,
gt->tuning_active.gt,
- ARRAY_SIZE(gt_tunings));
- xe_rtp_process_to_sr(&ctx, gt_tunings, ARRAY_SIZE(gt_tunings), >->reg_sr);
+ gt_tunings.n_entries);
+ xe_rtp_process_to_sr(&ctx, >_tunings, >->reg_sr, false);
}
EXPORT_SYMBOL_IF_KUNIT(xe_tuning_process_gt);
@@ -190,9 +190,8 @@ void xe_tuning_process_engine(struct xe_hw_engine *hwe)
xe_rtp_process_ctx_enable_active_tracking(&ctx,
hwe->gt->tuning_active.engine,
- ARRAY_SIZE(engine_tunings));
- xe_rtp_process_to_sr(&ctx, engine_tunings, ARRAY_SIZE(engine_tunings),
- &hwe->reg_sr);
+ engine_tunings.n_entries);
+ xe_rtp_process_to_sr(&ctx, &engine_tunings, &hwe->reg_sr, false);
}
EXPORT_SYMBOL_IF_KUNIT(xe_tuning_process_engine);
@@ -210,8 +209,8 @@ void xe_tuning_process_lrc(struct xe_hw_engine *hwe)
xe_rtp_process_ctx_enable_active_tracking(&ctx,
hwe->gt->tuning_active.lrc,
- ARRAY_SIZE(lrc_tunings));
- xe_rtp_process_to_sr(&ctx, lrc_tunings, ARRAY_SIZE(lrc_tunings), &hwe->reg_lrc);
+ lrc_tunings.n_entries);
+ xe_rtp_process_to_sr(&ctx, &lrc_tunings, &hwe->reg_lrc, true);
}
void xe_tuning_dump(struct xe_gt *gt, struct drm_printer *p)
@@ -219,14 +218,14 @@ void xe_tuning_dump(struct xe_gt *gt, struct drm_printer *p)
size_t idx;
drm_printf(p, "GT Tunings\n");
- for_each_set_bit(idx, gt->tuning_active.gt, ARRAY_SIZE(gt_tunings))
- drm_printf_indent(p, 1, "%s\n", gt_tunings[idx].name);
+ for_each_set_bit(idx, gt->tuning_active.gt, gt_tunings.n_entries)
+ drm_printf_indent(p, 1, "%s\n", gt_tunings.entries[idx].name);
drm_printf(p, "\nEngine Tunings\n");
- for_each_set_bit(idx, gt->tuning_active.engine, ARRAY_SIZE(engine_tunings))
- drm_printf_indent(p, 1, "%s\n", engine_tunings[idx].name);
+ for_each_set_bit(idx, gt->tuning_active.engine, engine_tunings.n_entries)
+ drm_printf_indent(p, 1, "%s\n", engine_tunings.entries[idx].name);
drm_printf(p, "\nLRC Tunings\n");
- for_each_set_bit(idx, gt->tuning_active.lrc, ARRAY_SIZE(lrc_tunings))
- drm_printf_indent(p, 1, "%s\n", lrc_tunings[idx].name);
+ for_each_set_bit(idx, gt->tuning_active.lrc, lrc_tunings.n_entries)
+ drm_printf_indent(p, 1, "%s\n", lrc_tunings.entries[idx].name);
}
diff --git a/drivers/gpu/drm/xe/xe_wa.c b/drivers/gpu/drm/xe/xe_wa.c
index 51c5985830b1..20e51816695f 100644
--- a/drivers/gpu/drm/xe/xe_wa.c
+++ b/drivers/gpu/drm/xe/xe_wa.c
@@ -119,7 +119,7 @@
__diag_push();
__diag_ignore_all("-Woverride-init", "Allow field overrides in table");
-static const struct xe_rtp_entry_sr gt_was[] = {
+static const struct xe_rtp_table_sr gt_was = XE_RTP_TABLE_SR(
{ XE_RTP_NAME("14011060649"),
XE_RTP_RULES(MEDIA_VERSION_RANGE(1200, 1255),
ENGINE_CLASS(VIDEO_DECODE),
@@ -322,9 +322,9 @@ static const struct xe_rtp_entry_sr gt_was[] = {
XE_RTP_RULES(GRAPHICS_VERSION_RANGE(3000, 3005)),
XE_RTP_ACTIONS(SET(GUC_INTR_CHICKEN, DISABLE_SIGNALING_ENGINES))
},
-};
+);
-static const struct xe_rtp_entry_sr engine_was[] = {
+static const struct xe_rtp_table_sr engine_was = XE_RTP_TABLE_SR(
{ XE_RTP_NAME("22010931296, 18011464164, 14010919138"),
XE_RTP_RULES(GRAPHICS_VERSION(1200), ENGINE_CLASS(RENDER)),
XE_RTP_ACTIONS(SET(FF_THREAD_MODE(RENDER_RING_BASE),
@@ -696,9 +696,9 @@ static const struct xe_rtp_entry_sr engine_was[] = {
FUNC(xe_rtp_match_gt_has_discontiguous_dss_groups)),
XE_RTP_ACTIONS(SET(TDL_CHICKEN, EUSTALL_PERF_SAMPLING_DISABLE))
},
-};
+);
-static const struct xe_rtp_entry_sr lrc_was[] = {
+static const struct xe_rtp_table_sr lrc_was = XE_RTP_TABLE_SR(
{ XE_RTP_NAME("16011163337"),
XE_RTP_RULES(GRAPHICS_VERSION_RANGE(1200, 1210), ENGINE_CLASS(RENDER)),
/* read verification is ignored due to 1608008084. */
@@ -924,21 +924,29 @@ static const struct xe_rtp_entry_sr lrc_was[] = {
ENGINE_CLASS(RENDER)),
XE_RTP_ACTIONS(SET(CHICKEN_RASTER_1, DIS_CLIP_NEGATIVE_BOUNDING_BOX))
},
-};
+);
-static __maybe_unused const struct xe_rtp_entry oob_was[] = {
+static const struct xe_rtp_entry oob_was_entries[] = {
#include <generated/xe_wa_oob.c>
- {}
};
-static_assert(ARRAY_SIZE(oob_was) - 1 == _XE_WA_OOB_COUNT);
+static_assert(ARRAY_SIZE(oob_was_entries) == _XE_WA_OOB_COUNT);
-static __maybe_unused const struct xe_rtp_entry device_oob_was[] = {
+static __maybe_unused const struct xe_rtp_table oob_was = {
+ .entries = oob_was_entries,
+ .n_entries = ARRAY_SIZE(oob_was_entries),
+};
+
+static const struct xe_rtp_entry device_oob_was_entries[] = {
#include <generated/xe_device_wa_oob.c>
- {}
};
-static_assert(ARRAY_SIZE(device_oob_was) - 1 == _XE_DEVICE_WA_OOB_COUNT);
+static_assert(ARRAY_SIZE(device_oob_was_entries) == _XE_DEVICE_WA_OOB_COUNT);
+
+static __maybe_unused const struct xe_rtp_table device_oob_was = {
+ .entries = device_oob_was_entries,
+ .n_entries = ARRAY_SIZE(device_oob_was_entries),
+};
__diag_pop();
@@ -954,10 +962,10 @@ void xe_wa_process_device_oob(struct xe_device *xe)
{
struct xe_rtp_process_ctx ctx = XE_RTP_PROCESS_CTX_INITIALIZER(xe);
- xe_rtp_process_ctx_enable_active_tracking(&ctx, xe->wa_active.oob, ARRAY_SIZE(device_oob_was));
+ xe_rtp_process_ctx_enable_active_tracking(&ctx, xe->wa_active.oob, device_oob_was.n_entries);
xe->wa_active.oob_initialized = true;
- xe_rtp_process(&ctx, device_oob_was);
+ xe_rtp_process(&ctx, &device_oob_was);
}
/**
@@ -972,9 +980,9 @@ void xe_wa_process_gt_oob(struct xe_gt *gt)
struct xe_rtp_process_ctx ctx = XE_RTP_PROCESS_CTX_INITIALIZER(gt);
xe_rtp_process_ctx_enable_active_tracking(&ctx, gt->wa_active.oob,
- ARRAY_SIZE(oob_was));
+ oob_was.n_entries);
gt->wa_active.oob_initialized = true;
- xe_rtp_process(&ctx, oob_was);
+ xe_rtp_process(&ctx, &oob_was);
}
/**
@@ -989,8 +997,8 @@ void xe_wa_process_gt(struct xe_gt *gt)
struct xe_rtp_process_ctx ctx = XE_RTP_PROCESS_CTX_INITIALIZER(gt);
xe_rtp_process_ctx_enable_active_tracking(&ctx, gt->wa_active.gt,
- ARRAY_SIZE(gt_was));
- xe_rtp_process_to_sr(&ctx, gt_was, ARRAY_SIZE(gt_was), >->reg_sr);
+ gt_was.n_entries);
+ xe_rtp_process_to_sr(&ctx, >_was, >->reg_sr, false);
}
EXPORT_SYMBOL_IF_KUNIT(xe_wa_process_gt);
@@ -1007,8 +1015,8 @@ void xe_wa_process_engine(struct xe_hw_engine *hwe)
struct xe_rtp_process_ctx ctx = XE_RTP_PROCESS_CTX_INITIALIZER(hwe);
xe_rtp_process_ctx_enable_active_tracking(&ctx, hwe->gt->wa_active.engine,
- ARRAY_SIZE(engine_was));
- xe_rtp_process_to_sr(&ctx, engine_was, ARRAY_SIZE(engine_was), &hwe->reg_sr);
+ engine_was.n_entries);
+ xe_rtp_process_to_sr(&ctx, &engine_was, &hwe->reg_sr, false);
}
/**
@@ -1024,8 +1032,8 @@ void xe_wa_process_lrc(struct xe_hw_engine *hwe)
struct xe_rtp_process_ctx ctx = XE_RTP_PROCESS_CTX_INITIALIZER(hwe);
xe_rtp_process_ctx_enable_active_tracking(&ctx, hwe->gt->wa_active.lrc,
- ARRAY_SIZE(lrc_was));
- xe_rtp_process_to_sr(&ctx, lrc_was, ARRAY_SIZE(lrc_was), &hwe->reg_lrc);
+ lrc_was.n_entries);
+ xe_rtp_process_to_sr(&ctx, &lrc_was, &hwe->reg_lrc, true);
}
/**
@@ -1039,7 +1047,7 @@ int xe_wa_device_init(struct xe_device *xe)
unsigned long *p;
p = drmm_kzalloc(&xe->drm,
- sizeof(*p) * BITS_TO_LONGS(ARRAY_SIZE(device_oob_was)),
+ sizeof(*p) * BITS_TO_LONGS(device_oob_was.n_entries),
GFP_KERNEL);
if (!p)
@@ -1062,10 +1070,10 @@ int xe_wa_gt_init(struct xe_gt *gt)
size_t n_oob, n_lrc, n_engine, n_gt, total;
unsigned long *p;
- n_gt = BITS_TO_LONGS(ARRAY_SIZE(gt_was));
- n_engine = BITS_TO_LONGS(ARRAY_SIZE(engine_was));
- n_lrc = BITS_TO_LONGS(ARRAY_SIZE(lrc_was));
- n_oob = BITS_TO_LONGS(ARRAY_SIZE(oob_was));
+ n_gt = BITS_TO_LONGS(gt_was.n_entries);
+ n_engine = BITS_TO_LONGS(engine_was.n_entries);
+ n_lrc = BITS_TO_LONGS(lrc_was.n_entries);
+ n_oob = BITS_TO_LONGS(oob_was.n_entries);
total = n_gt + n_engine + n_lrc + n_oob;
p = drmm_kzalloc(&xe->drm, sizeof(*p) * total, GFP_KERNEL);
@@ -1089,9 +1097,9 @@ void xe_wa_device_dump(struct xe_device *xe, struct drm_printer *p)
size_t idx;
drm_printf(p, "Device OOB Workarounds\n");
- for_each_set_bit(idx, xe->wa_active.oob, ARRAY_SIZE(device_oob_was))
- if (device_oob_was[idx].name)
- drm_printf_indent(p, 1, "%s\n", device_oob_was[idx].name);
+ for_each_set_bit(idx, xe->wa_active.oob, device_oob_was.n_entries)
+ if (device_oob_was.entries[idx].name)
+ drm_printf_indent(p, 1, "%s\n", device_oob_was.entries[idx].name);
}
void xe_wa_dump(struct xe_gt *gt, struct drm_printer *p)
@@ -1099,21 +1107,21 @@ void xe_wa_dump(struct xe_gt *gt, struct drm_printer *p)
size_t idx;
drm_printf(p, "GT Workarounds\n");
- for_each_set_bit(idx, gt->wa_active.gt, ARRAY_SIZE(gt_was))
- drm_printf_indent(p, 1, "%s\n", gt_was[idx].name);
+ for_each_set_bit(idx, gt->wa_active.gt, gt_was.n_entries)
+ drm_printf_indent(p, 1, "%s\n", gt_was.entries[idx].name);
drm_printf(p, "\nEngine Workarounds\n");
- for_each_set_bit(idx, gt->wa_active.engine, ARRAY_SIZE(engine_was))
- drm_printf_indent(p, 1, "%s\n", engine_was[idx].name);
+ for_each_set_bit(idx, gt->wa_active.engine, engine_was.n_entries)
+ drm_printf_indent(p, 1, "%s\n", engine_was.entries[idx].name);
drm_printf(p, "\nLRC Workarounds\n");
- for_each_set_bit(idx, gt->wa_active.lrc, ARRAY_SIZE(lrc_was))
- drm_printf_indent(p, 1, "%s\n", lrc_was[idx].name);
+ for_each_set_bit(idx, gt->wa_active.lrc, lrc_was.n_entries)
+ drm_printf_indent(p, 1, "%s\n", lrc_was.entries[idx].name);
drm_printf(p, "\nOOB Workarounds\n");
- for_each_set_bit(idx, gt->wa_active.oob, ARRAY_SIZE(oob_was))
- if (oob_was[idx].name)
- drm_printf_indent(p, 1, "%s\n", oob_was[idx].name);
+ for_each_set_bit(idx, gt->wa_active.oob, oob_was.n_entries)
+ if (oob_was.entries[idx].name)
+ drm_printf_indent(p, 1, "%s\n", oob_was.entries[idx].name);
}
/*
--
2.53.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 6.18.y 6/6] drm/xe/rtp: Maintain OA whitelists separately
2026-08-01 3:03 ` [PATCH 6.18.y 1/6] drm/xe/lrc: Refactor out engine id to hwe conversion Sasha Levin
` (3 preceding siblings ...)
2026-08-01 3:03 ` [PATCH 6.18.y 5/6] drm/xe/rtp: Add struct types for RTP tables Sasha Levin
@ 2026-08-01 3:03 ` Sasha Levin
4 siblings, 0 replies; 7+ messages in thread
From: Sasha Levin @ 2026-08-01 3:03 UTC (permalink / raw)
To: stable
Cc: Ashutosh Dixit, Umesh Nerlige Ramappa, Thomas Hellström,
Sasha Levin
From: Ashutosh Dixit <ashutosh.dixit@intel.com>
[ Upstream commit 31e2437561621b4867c08efc890bf629d017df03 ]
OA registers are dynamically whitelisted (and again dewhitelisted) on OA
stream open/close. Maintaining OA whitelists separately from non-OA
register whitlists simplifies this management of OA register
whitelisting/dewhitelisting.
Fixes: 828a8eaf37c3 ("drm/xe/oa: Add MMIO trigger support")
Cc: stable@vger.kernel.org # v6.12+
Signed-off-by: Ashutosh Dixit <ashutosh.dixit@intel.com>
Reviewed-by: Umesh Nerlige Ramappa <umesh.nerlige.ramappa@intel.com>
Link: https://patch.msgid.link/20260615224227.34880-3-ashutosh.dixit@intel.com
(cherry picked from commit c478244a9e2d14b3f1f92e8bd293919e554622a5)
Signed-off-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/gpu/drm/xe/xe_gt_debugfs.c | 4 +++-
drivers/gpu/drm/xe/xe_hw_engine.c | 2 ++
drivers/gpu/drm/xe/xe_hw_engine_types.h | 8 ++++++++
drivers/gpu/drm/xe/xe_reg_whitelist.c | 5 +++++
4 files changed, 18 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/xe/xe_gt_debugfs.c b/drivers/gpu/drm/xe/xe_gt_debugfs.c
index f253e2df4907..1a4d8d4f44b4 100644
--- a/drivers/gpu/drm/xe/xe_gt_debugfs.c
+++ b/drivers/gpu/drm/xe/xe_gt_debugfs.c
@@ -174,8 +174,10 @@ static int register_save_restore(struct xe_gt *gt, struct drm_printer *p)
drm_printf(p, "\n");
drm_printf(p, "Whitelist\n");
- for_each_hw_engine(hwe, gt, id)
+ for_each_hw_engine(hwe, gt, id) {
xe_reg_whitelist_dump(&hwe->reg_whitelist, p);
+ xe_reg_whitelist_dump(&hwe->oa_whitelist, p);
+ }
xe_pm_runtime_put(gt_to_xe(gt));
diff --git a/drivers/gpu/drm/xe/xe_hw_engine.c b/drivers/gpu/drm/xe/xe_hw_engine.c
index e5241bf3024c..f097b5555f4e 100644
--- a/drivers/gpu/drm/xe/xe_hw_engine.c
+++ b/drivers/gpu/drm/xe/xe_hw_engine.c
@@ -565,6 +565,8 @@ static void hw_engine_init_early(struct xe_gt *gt, struct xe_hw_engine *hwe,
hw_engine_setup_default_state(hwe);
xe_reg_sr_init(&hwe->reg_whitelist, hwe->name, gt_to_xe(gt));
+ xe_reg_sr_init(&hwe->oa_whitelist, hwe->name, gt_to_xe(gt));
+ xe_reg_sr_init(&hwe->oa_sr, hwe->name, gt_to_xe(gt));
xe_reg_whitelist_process_engine(hwe);
}
diff --git a/drivers/gpu/drm/xe/xe_hw_engine_types.h b/drivers/gpu/drm/xe/xe_hw_engine_types.h
index e4191a7a2c31..04ca7545d22c 100644
--- a/drivers/gpu/drm/xe/xe_hw_engine_types.h
+++ b/drivers/gpu/drm/xe/xe_hw_engine_types.h
@@ -128,6 +128,14 @@ struct xe_hw_engine {
* @reg_whitelist: table with registers to be whitelisted
*/
struct xe_reg_sr reg_whitelist;
+ /**
+ * @oa_whitelist: oa registers to be whitelisted
+ */
+ struct xe_reg_sr oa_whitelist;
+ /**
+ * @oa_sr: oa nonpriv whitelist registers, changed on oa stream open/close
+ */
+ struct xe_reg_sr oa_sr;
/**
* @reg_lrc: LRC workaround registers
*/
diff --git a/drivers/gpu/drm/xe/xe_reg_whitelist.c b/drivers/gpu/drm/xe/xe_reg_whitelist.c
index 7c37d20b0970..66503a53410b 100644
--- a/drivers/gpu/drm/xe/xe_reg_whitelist.c
+++ b/drivers/gpu/drm/xe/xe_reg_whitelist.c
@@ -66,6 +66,9 @@ static const struct xe_rtp_table_sr register_whitelist = XE_RTP_TABLE_SR(
ENGINE_CLASS(RENDER)),
XE_RTP_ACTIONS(WHITELIST(CSBE_DEBUG_STATUS(RENDER_RING_BASE), 0))
},
+);
+
+static const struct xe_rtp_table_sr oa_whitelist = XE_RTP_TABLE_SR(
{ XE_RTP_NAME("oa_reg_render"),
XE_RTP_RULES(GRAPHICS_VERSION_RANGE(1200, XE_RTP_END_VERSION_UNDEFINED),
ENGINE_CLASS(RENDER)),
@@ -138,6 +141,8 @@ void xe_reg_whitelist_process_engine(struct xe_hw_engine *hwe)
xe_rtp_process_to_sr(&ctx, ®ister_whitelist, &hwe->reg_whitelist, false);
whitelist_apply_to_hwe(hwe);
+
+ xe_rtp_process_to_sr(&ctx, &oa_whitelist, &hwe->oa_whitelist, false);
}
/**
--
2.53.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
end of thread, other threads:[~2026-08-01 3:03 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-29 10:58 FAILED: patch "[PATCH] drm/xe/rtp: Maintain OA whitelists separately" failed to apply to 6.18-stable tree gregkh
2026-08-01 3:03 ` [PATCH 6.18.y 1/6] drm/xe/lrc: Refactor out engine id to hwe conversion Sasha Levin
2026-08-01 3:03 ` [PATCH 6.18.y 2/6] drm/xe/mcr: Extract reg_in_steering_type_ranges() Sasha Levin
2026-08-01 3:03 ` [PATCH 6.18.y 3/6] drm/xe/reg_sr: Do sanity check for MCR vs non-MCR Sasha Levin
2026-08-01 3:03 ` [PATCH 6.18.y 4/6] drm/xe/rtp: Drop rule matching cases from rtp_to_sr_cases and rtp_cases Sasha Levin
2026-08-01 3:03 ` [PATCH 6.18.y 5/6] drm/xe/rtp: Add struct types for RTP tables Sasha Levin
2026-08-01 3:03 ` [PATCH 6.18.y 6/6] drm/xe/rtp: Maintain OA whitelists separately Sasha Levin
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.