[Intel-xe] [PATCH 6/7] drm/xe: Add support for OOB workarounds
Lucas De Marchi
lucas.demarchi at intel.com
Thu May 4 07:32:49 UTC 2023
There are WAs that, due to their nature, cannot be applied from
a central place like xe_wa.c. Those are peppered around the rest of the
code, as needed. This gives them a new name: "out-of-band workarounds".
These workarounds then have their names and rules grouped in a special
ELF section that the driver can loop through on initialization to report
the active workarounds.
Currently this only supports checks for the xe device info, not
supporting gt/engine checks. Those can be added later, with the downside
of not being able to be reported on driver probe.
Signed-off-by: Lucas De Marchi <lucas.demarchi at intel.com>
---
drivers/gpu/drm/xe/Makefile | 2 ++
drivers/gpu/drm/xe/xe.lds | 8 ++++++++
drivers/gpu/drm/xe/xe_device.c | 4 ++++
drivers/gpu/drm/xe/xe_rtp.c | 22 ++++++++++++++++++++++
drivers/gpu/drm/xe/xe_rtp.h | 22 ++++++++++++++++++++++
drivers/gpu/drm/xe/xe_rtp_types.h | 12 ++++++++++++
drivers/gpu/drm/xe/xe_wa.c | 25 +++++++++++++++++++++++--
drivers/gpu/drm/xe/xe_wa.h | 19 +++++++++++++++++++
8 files changed, 112 insertions(+), 2 deletions(-)
create mode 100644 drivers/gpu/drm/xe/xe.lds
diff --git a/drivers/gpu/drm/xe/Makefile b/drivers/gpu/drm/xe/Makefile
index 84ad0e949044..7c54fd998371 100644
--- a/drivers/gpu/drm/xe/Makefile
+++ b/drivers/gpu/drm/xe/Makefile
@@ -208,6 +208,8 @@ ifeq ($(CONFIG_DRM_FBDEV_EMULATION),y)
xe-$(CONFIG_DRM_XE_DISPLAY) += i915-display/intel_fbdev.o
endif
+LDFLAGS_xe.o := -T $(srctree)/$(src)/xe.lds
+
obj-$(CONFIG_DRM_XE) += xe.o
obj-$(CONFIG_DRM_XE_KUNIT_TEST) += tests/
diff --git a/drivers/gpu/drm/xe/xe.lds b/drivers/gpu/drm/xe/xe.lds
new file mode 100644
index 000000000000..fa84ecbc3cd6
--- /dev/null
+++ b/drivers/gpu/drm/xe/xe.lds
@@ -0,0 +1,8 @@
+SECTIONS
+{
+ .rodata.__xe_wa_oob ALIGN(8) : {
+ __start___xe_wa_oob = .;
+ *(__xe_wa_oob)
+ __stop___xe_wa_oob = .;
+ }
+}
diff --git a/drivers/gpu/drm/xe/xe_device.c b/drivers/gpu/drm/xe/xe_device.c
index 45d6e5ff47fd..a07f56c9a2eb 100644
--- a/drivers/gpu/drm/xe/xe_device.c
+++ b/drivers/gpu/drm/xe/xe_device.c
@@ -31,6 +31,7 @@
#include "xe_ttm_sys_mgr.h"
#include "xe_vm.h"
#include "xe_vm_madvise.h"
+#include "xe_wa.h"
#include "xe_wait_user_fence.h"
static int xe_file_open(struct drm_device *dev, struct drm_file *file)
@@ -237,6 +238,7 @@ static void xe_device_sanitize(struct drm_device *drm, void *arg)
int xe_device_probe(struct xe_device *xe)
{
+ struct drm_printer p = drm_debug_printer("xe: ");
struct xe_gt *gt;
int err;
u8 id;
@@ -291,6 +293,8 @@ int xe_device_probe(struct xe_device *xe)
/* Allocate and map stolen after potential VRAM resize */
xe_ttm_stolen_mgr_init(xe);
+ xe_wa_dump(xe, &p);
+
/*
* Now that GT is initialized (TTM in particular),
* we can try to init display, and inherit the initial fb.
diff --git a/drivers/gpu/drm/xe/xe_rtp.c b/drivers/gpu/drm/xe/xe_rtp.c
index 88eaea597cf7..62d12dd23bc5 100644
--- a/drivers/gpu/drm/xe/xe_rtp.c
+++ b/drivers/gpu/drm/xe/xe_rtp.c
@@ -69,12 +69,21 @@ static bool rule_matches(const struct xe_device *xe,
match = xe->info.is_dgfx;
break;
case XE_RTP_MATCH_ENGINE_CLASS:
+ if (drm_WARN_ON(&xe->drm, !hwe))
+ return false;
+
match = hwe->class == r->engine_class;
break;
case XE_RTP_MATCH_NOT_ENGINE_CLASS:
+ if (drm_WARN_ON(&xe->drm, !hwe))
+ return false;
+
match = hwe->class != r->engine_class;
break;
case XE_RTP_MATCH_FUNC:
+ if (drm_WARN_ON(&xe->drm, !gt))
+ return false;
+
match = r->match_func(gt, hwe);
break;
default:
@@ -158,6 +167,19 @@ void xe_rtp_process(const struct xe_rtp_entry *entries, struct xe_reg_sr *sr,
}
EXPORT_SYMBOL_IF_KUNIT(xe_rtp_process);
+
+bool xe_rtp_match_entry_oob(struct xe_device *xe,
+ const struct xe_rtp_entry_oob *oob_entry)
+{
+ const struct xe_rtp_entry entry = {
+ .name = oob_entry->name,
+ .n_rules = oob_entry->n_rules,
+ .rules = oob_entry->rules,
+ };
+
+ return rule_matches(xe, NULL, NULL, &entry);
+}
+
bool xe_rtp_match_even_instance(const struct xe_gt *gt,
const struct xe_hw_engine *hwe)
{
diff --git a/drivers/gpu/drm/xe/xe_rtp.h b/drivers/gpu/drm/xe/xe_rtp.h
index 8bc946694bfc..2fa14b5d51d7 100644
--- a/drivers/gpu/drm/xe/xe_rtp.h
+++ b/drivers/gpu/drm/xe/xe_rtp.h
@@ -6,6 +6,7 @@
#ifndef _XE_RTP_
#define _XE_RTP_
+#include <linux/compiler.h>
#include <linux/types.h>
#include <linux/xarray.h>
@@ -20,6 +21,7 @@
* Register table poke infrastructure
*/
+struct xe_device;
struct xe_hw_engine;
struct xe_gt;
struct xe_reg_sr;
@@ -361,6 +363,26 @@ struct xe_reg_sr;
void xe_rtp_process(const struct xe_rtp_entry *entries, struct xe_reg_sr *sr,
struct xe_gt *gt, struct xe_hw_engine *hwe);
+
+#define __XE_RTP_ENTRY_OOB(uniq__, section__, name__, ...) ({ \
+ static const struct xe_rtp_rule __PASTE(rule_, uniq__)[] = { \
+ XE_RTP_PASTE_FOREACH(RULE_, COMMA, (__VA_ARGS__)) \
+ }; \
+ static const struct xe_rtp_entry_oob __PASTE(entry__, uniq__) \
+ __used __aligned(sizeof(void *)) __section(section__) = { \
+ .name = name__, \
+ .n_rules = _XE_COUNT_ARGS(__VA_ARGS__), \
+ .rules = __PASTE(rule_, uniq__), \
+ }; \
+ &__PASTE(entry__, uniq__); \
+})
+
+#define XE_RTP_ENTRY_OOB(section__, name__, ...) \
+ __XE_RTP_ENTRY_OOB(__UNIQUE_ID(xe_rtp), section__, name__, __VA_ARGS__)
+
+bool xe_rtp_match_entry_oob(struct xe_device *xe,
+ const struct xe_rtp_entry_oob *entry);
+
/* 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 12df8a9e9c45..a70d697c87f4 100644
--- a/drivers/gpu/drm/xe/xe_rtp_types.h
+++ b/drivers/gpu/drm/xe/xe_rtp_types.h
@@ -95,4 +95,16 @@ struct xe_rtp_entry {
u8 flags;
};
+/**
+ * struct xe_rtp_entry_oob - Entry in an out-of-band rtp table
+ *
+ * Like struct xe_rtp_entry, but there is no action associated with it, since it
+ * only serves to match the rules
+ */
+struct xe_rtp_entry_oob {
+ const char *name;
+ const struct xe_rtp_rule *rules;
+ u8 n_rules;
+};
+
#endif
diff --git a/drivers/gpu/drm/xe/xe_wa.c b/drivers/gpu/drm/xe/xe_wa.c
index b0bb2f4438f4..f8d780fff6bb 100644
--- a/drivers/gpu/drm/xe/xe_wa.c
+++ b/drivers/gpu/drm/xe/xe_wa.c
@@ -72,8 +72,8 @@
* engine registers are restored in a context restore sequence. This is
* currently not used in the driver.
*
- * - Other: There are WAs that, due to their nature, cannot be applied from a
- * central place. Those are peppered around the rest of the code, as needed.
+ * - Other/OOB: There are WAs that, due to their nature, cannot be applied from
+ * a central place. Those are peppered around the rest of the code, as needed.
* Workarounds related to the display IP are the main example.
*
* .. [1] Technically, some registers are powercontext saved & restored, so they
@@ -90,6 +90,9 @@
#undef XE_REG_MCR
#define XE_REG_MCR(...) XE_REG(__VA_ARGS__, .mcr = 1)
+extern const struct xe_rtp_entry_oob __start___xe_wa_oob[];
+extern const struct xe_rtp_entry_oob __stop___xe_wa_oob[];
+
__diag_push();
__diag_ignore_all("-Woverride-init", "Allow field overrides in table");
@@ -608,3 +611,21 @@ void xe_wa_process_lrc(struct xe_hw_engine *hwe)
{
xe_rtp_process(lrc_was, &hwe->reg_lrc, hwe->gt, hwe);
}
+
+/**
+ * xe_wa_dump - dump all active workarounds known by the driver
+ * @xe: xe device
+ * @p: DRM printer
+ */
+void xe_wa_dump(struct xe_device *xe, struct drm_printer *p)
+{
+ const struct xe_rtp_entry_oob *entry_oob;
+
+ drm_printf(p, "OOB Workarounds\n");
+ for (entry_oob = __start___xe_wa_oob;
+ entry_oob < __stop___xe_wa_oob;
+ entry_oob++) {
+ if (xe_rtp_match_entry_oob(xe, entry_oob))
+ drm_printf(p, "\t%s\n", entry_oob->name);
+ }
+}
diff --git a/drivers/gpu/drm/xe/xe_wa.h b/drivers/gpu/drm/xe/xe_wa.h
index cd2307d58795..53d377c45f71 100644
--- a/drivers/gpu/drm/xe/xe_wa.h
+++ b/drivers/gpu/drm/xe/xe_wa.h
@@ -6,6 +6,9 @@
#ifndef _XE_WA_
#define _XE_WA_
+#include "xe_rtp.h"
+
+struct drm_printer;
struct xe_gt;
struct xe_hw_engine;
@@ -15,4 +18,20 @@ void xe_wa_process_lrc(struct xe_hw_engine *hwe);
void xe_reg_whitelist_process_engine(struct xe_hw_engine *hwe);
+void xe_wa_dump(struct xe_device *xe, struct drm_printer *p);
+
+/**
+ * XE_WA - Out-of-band workarounds, that don't fit the lifecycle any
+ * other more specific type
+ * @xe: xe device instance
+ * @name: Workaround name
+ * @...: xe_rtp_rule array by using XE_RTP_RULES()
+ */
+#define XE_WA(xe__, name__, ...) ({ \
+ const struct xe_rtp_entry_oob *entry__ = XE_RTP_ENTRY_OOB("__xe_wa_oob",\
+ name__, \
+ __VA_ARGS__); \
+ xe_rtp_match_entry_oob(xe__, entry__); \
+})
+
#endif
--
2.40.1
More information about the Intel-xe
mailing list