[PATCH 5/5] drm/xe/configfs: Add interface to wa_bb commands

Lucas De Marchi lucas.demarchi at intel.com
Fri May 23 18:54:39 UTC 2025


During validation it's useful to ensure additional commands are executed
on every context switch. Add the interface to configfs to allow commands
to be inserted in the WA batch buffer.

Signed-off-by: Lucas De Marchi <lucas.demarchi at intel.com>
---
 drivers/gpu/drm/xe/xe_configfs.c | 178 +++++++++++++++++++++++++++++++++++++--
 1 file changed, 172 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/xe/xe_configfs.c b/drivers/gpu/drm/xe/xe_configfs.c
index d73fe5a6666cb..c1604160ec67c 100644
--- a/drivers/gpu/drm/xe/xe_configfs.c
+++ b/drivers/gpu/drm/xe/xe_configfs.c
@@ -4,6 +4,7 @@
  */
 
 #include <linux/bitops.h>
+#include <linux/ctype.h>
 #include <linux/configfs.h>
 #include <linux/find.h>
 #include <linux/init.h>
@@ -78,12 +79,20 @@
  *	rmdir /sys/kernel/config/xe/0000:03:00.0/
  */
 
+/* Similar to struct xe_bb, but not tied to HW (yet) */
+struct wa_bb {
+	u32 *cs;
+	u32 len; /* in dwords */
+};
+
 struct xe_config_device {
 	struct config_group group;
 
 	bool survivability_mode;
 	u64 engine_allowed;
 
+	struct wa_bb wa_bb[XE_ENGINE_CLASS_MAX];
+
 	/* protects attributes */
 	struct mutex lock;
 };
@@ -91,15 +100,16 @@ struct xe_config_device {
 struct engine_info {
 	const char *cls;
 	u64 mask;
+	enum xe_engine_class engine_class;
 };
 
 static const struct engine_info engine_info[] = {
-	{ .cls = "rcs", .mask = XE_HW_ENGINE_RCS_MASK },
-	{ .cls = "bcs", .mask = XE_HW_ENGINE_BCS_MASK },
-	{ .cls = "vcs", .mask = XE_HW_ENGINE_VCS_MASK },
-	{ .cls = "vecs", .mask = XE_HW_ENGINE_VECS_MASK },
-	{ .cls = "ccs", .mask = XE_HW_ENGINE_CCS_MASK },
-	{ .cls = "gsccs", .mask = XE_HW_ENGINE_GSCCS_MASK },
+	{ .cls = "rcs", .mask = XE_HW_ENGINE_RCS_MASK, XE_ENGINE_CLASS_RENDER },
+	{ .cls = "bcs", .mask = XE_HW_ENGINE_BCS_MASK, XE_ENGINE_CLASS_COPY },
+	{ .cls = "vcs", .mask = XE_HW_ENGINE_VCS_MASK, XE_ENGINE_CLASS_VIDEO_DECODE },
+	{ .cls = "vecs", .mask = XE_HW_ENGINE_VECS_MASK, XE_ENGINE_CLASS_VIDEO_ENHANCE },
+	{ .cls = "ccs", .mask = XE_HW_ENGINE_CCS_MASK, XE_ENGINE_CLASS_COMPUTE },
+	{ .cls = "gsccs", .mask = XE_HW_ENGINE_GSCCS_MASK, XE_ENGINE_CLASS_OTHER },
 };
 
 static struct xe_config_device *to_xe_config_device(struct config_item *item)
@@ -214,12 +224,166 @@ static ssize_t engine_allowed_store(struct config_item *item, const char *page,
 	return len;
 }
 
+static ssize_t wa_bb_show(struct config_item *item, char *page)
+{
+	struct xe_config_device *dev = to_xe_config_device(item);
+	ssize_t len;
+	char *p = page;
+
+	guard(mutex)(&dev->lock);
+
+	for (size_t i = 0; i < ARRAY_SIZE(engine_info); i++) {
+		enum xe_engine_class ec = engine_info[i].engine_class;
+
+		if (!dev->wa_bb[ec].len)
+			continue;
+
+		len = sprintf(p, "%s:", engine_info[i].cls);
+		p += len;
+
+		for (size_t j = 0; j < dev->wa_bb[ec].len; j++) {
+			len = sprintf(p, " %08x", dev->wa_bb[ec].cs[j]);
+			p += len;
+		}
+
+		*p++ = '\n';
+	}
+
+	return p - page;
+}
+
+static bool lookup_engine_class(const char *name, size_t namelen,
+				enum xe_engine_class *engine_class)
+{
+	size_t i;
+
+	for (i = 0; i < ARRAY_SIZE(engine_info); i++) {
+		size_t clslen = strlen(engine_info[i].cls);
+
+		if (clslen == namelen &&
+		    !memcmp(engine_info[i].cls, name, namelen)) {
+			*engine_class = engine_info[i].engine_class;
+			return true;
+		}
+	}
+
+	return false;
+}
+
+/*
+ * Parse lines with the format
+ *
+ *	<engine-class> <u32> <u32...>
+ *
+ * and optionally save them in @wa_bb[i].cs is non-NULL.
+ *
+ * Return the number of dwords parsed.
+ */
+static ssize_t parse_wa_bb_lines(const char *lines, size_t len,
+				 struct wa_bb wa_bb[static XE_ENGINE_CLASS_MAX])
+{
+	const char *p;
+	ssize_t ret = 0;
+
+	for (p = lines; p - lines < len;) {
+		enum xe_engine_class ec;
+		size_t namelen;
+		u32 val;
+
+		while (isspace(*p))
+			p++;
+
+		if (*p == '\n') {
+			p++;
+			continue;
+		}
+
+		if (!*p)
+			break;
+
+		namelen = strcspn(p, " \t\n");
+		if (!p[namelen] || p[namelen] == '\n' ||
+		    !lookup_engine_class(p, namelen, &ec))
+			return -EINVAL;
+
+		for (p += namelen; p - lines < len && *p != '\n';) {
+			u8 numlen = 0;
+			u32 wa_bb_len;
+			char numstr[9];
+
+			while (isspace(*p))
+				p++;
+
+			while (isxdigit(*p)) {
+				if (numlen == sizeof(numstr) - 1)
+					return -EINVAL;
+				numstr[numlen++] = *p;
+				p++;
+			}
+
+			numstr[numlen] = '\0';
+			if (kstrtou32(numstr, 16, &val))
+				return -EINVAL;
+
+			wa_bb_len = wa_bb[ec].len;
+			if (wa_bb[ec].cs)
+				wa_bb[ec].cs[wa_bb_len] = val;
+
+			wa_bb[ec].len++;
+			ret++;
+		}
+	}
+
+	return ret;
+}
+
+static ssize_t wa_bb_store(struct config_item *item, const char *page,
+			   size_t len)
+{
+	struct xe_config_device *dev = to_xe_config_device(item);
+	struct wa_bb wa_bb[XE_ENGINE_CLASS_MAX] = { };
+	ssize_t count, class;
+	u32 *tmp;
+
+	/* 1. Count dwords - wa_bb[i].cs is NULL for all classes */
+	count = parse_wa_bb_lines(page, len, wa_bb);
+	if (count < 0)
+		return count;
+
+	guard(mutex)(&dev->lock);
+
+	/*
+	 * 2. Allocate a u32 array and set the pointers to the right positions
+	 * according to the length of each class' wa_bb
+	 */
+	tmp = krealloc(dev->wa_bb[0].cs, count * sizeof(u32), GFP_KERNEL);
+	if (!tmp)
+		return -ENOMEM;
+
+	for (class = 0, count = 0; class < XE_ENGINE_CLASS_MAX; ++class) {
+		wa_bb[class].cs = tmp + count;
+		count += wa_bb[class].len;
+		wa_bb[class].len = 0;
+	}
+
+	/* 3. Parse wa_bb lines again, this time saving the values */
+	count = parse_wa_bb_lines(page, len, wa_bb);
+	if (count < 0)
+		return count;
+
+	memcpy(dev->wa_bb, wa_bb, sizeof(wa_bb));
+
+	return len;
+}
+
 CONFIGFS_ATTR(, survivability_mode);
 CONFIGFS_ATTR(, engine_allowed);
+CONFIGFS_ATTR(, wa_bb);
 
 static struct configfs_attribute *xe_config_device_attrs[] = {
 	&attr_survivability_mode,
 	&attr_engine_allowed,
+	&attr_wa_bb,
 	NULL,
 };
 
@@ -228,6 +392,8 @@ static void xe_config_device_release(struct config_item *item)
 	struct xe_config_device *dev = to_xe_config_device(item);
 
 	mutex_destroy(&dev->lock);
+
+	kfree(dev->wa_bb[0].cs);
 	kfree(dev);
 }
 

-- 
2.49.0



More information about the Intel-xe mailing list