* [PATCH 1/8] lib/igt_drm_netlink: Introduce DRM RAS Generic Netlink interface
2026-07-29 12:19 [PATCH 0/8] Xe3P GPU Error Injection Test Suite with DRM RAS Netlink Support Ravi Kishore Koppuravuri
@ 2026-07-29 12:19 ` Ravi Kishore Koppuravuri
2026-08-06 23:45 ` Harish Chegondi
2026-07-29 12:19 ` [PATCH 2/8] lib/igt_drm_netlink: add get_error_counter support Ravi Kishore Koppuravuri
` (6 subsequent siblings)
7 siblings, 1 reply; 13+ messages in thread
From: Ravi Kishore Koppuravuri @ 2026-07-29 12:19 UTC (permalink / raw)
To: igt-dev
Cc: riana.tauro, anshuman.gupta, mallesh.koujalagi, raag.jadav,
Ravi Kishore Koppuravuri
Introduce DRM RAS Generic Netlink interface as a library
Signed-off-by: Ravi Kishore Koppuravuri <ravi.kishore.koppuravuri@intel.com>
---
include/drm-uapi/drm_ras.h | 50 +++++++++++++++++++++++++++++++
lib/igt_drm_netlink.c | 60 ++++++++++++++++++++++++++++++++++++++
lib/igt_drm_netlink.h | 25 ++++++++++++++++
lib/meson.build | 9 ++++++
4 files changed, 144 insertions(+)
create mode 100644 include/drm-uapi/drm_ras.h
create mode 100644 lib/igt_drm_netlink.c
create mode 100644 lib/igt_drm_netlink.h
diff --git a/include/drm-uapi/drm_ras.h b/include/drm-uapi/drm_ras.h
new file mode 100644
index 000000000..218a3ee86
--- /dev/null
+++ b/include/drm-uapi/drm_ras.h
@@ -0,0 +1,50 @@
+/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */
+/* Do not edit directly, auto-generated from: */
+/* Documentation/netlink/specs/drm_ras.yaml */
+/* YNL-GEN uapi header */
+/* To regenerate run: tools/net/ynl/ynl-regen.sh */
+
+#ifndef _UAPI_LINUX_DRM_RAS_H
+#define _UAPI_LINUX_DRM_RAS_H
+
+#define DRM_RAS_FAMILY_NAME "drm-ras"
+#define DRM_RAS_FAMILY_VERSION 1
+
+/*
+ * Type of the node. Currently, only error-counter nodes are supported, which
+ * expose reliability counters for a hardware/software component.
+ */
+enum drm_ras_node_type {
+ DRM_RAS_NODE_TYPE_ERROR_COUNTER = 1,
+};
+
+enum {
+ DRM_RAS_A_NODE_ATTRS_NODE_ID = 1,
+ DRM_RAS_A_NODE_ATTRS_DEVICE_NAME,
+ DRM_RAS_A_NODE_ATTRS_NODE_NAME,
+ DRM_RAS_A_NODE_ATTRS_NODE_TYPE,
+
+ __DRM_RAS_A_NODE_ATTRS_MAX,
+ DRM_RAS_A_NODE_ATTRS_MAX = (__DRM_RAS_A_NODE_ATTRS_MAX - 1)
+};
+
+enum {
+ DRM_RAS_A_ERROR_COUNTER_ATTRS_NODE_ID = 1,
+ DRM_RAS_A_ERROR_COUNTER_ATTRS_ERROR_ID,
+ DRM_RAS_A_ERROR_COUNTER_ATTRS_ERROR_NAME,
+ DRM_RAS_A_ERROR_COUNTER_ATTRS_ERROR_VALUE,
+
+ __DRM_RAS_A_ERROR_COUNTER_ATTRS_MAX,
+ DRM_RAS_A_ERROR_COUNTER_ATTRS_MAX = (__DRM_RAS_A_ERROR_COUNTER_ATTRS_MAX - 1)
+};
+
+enum {
+ DRM_RAS_CMD_LIST_NODES = 1,
+ DRM_RAS_CMD_GET_ERROR_COUNTER,
+ DRM_RAS_CMD_CLEAR_ERROR_COUNTER,
+
+ __DRM_RAS_CMD_MAX,
+ DRM_RAS_CMD_MAX = (__DRM_RAS_CMD_MAX - 1)
+};
+
+#endif /* _UAPI_LINUX_DRM_RAS_H */
diff --git a/lib/igt_drm_netlink.c b/lib/igt_drm_netlink.c
new file mode 100644
index 000000000..1c07bb2db
--- /dev/null
+++ b/lib/igt_drm_netlink.c
@@ -0,0 +1,60 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2026 Intel Corporation
+ */
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <netlink/errno.h>
+#include <netlink/genl/ctrl.h>
+#include <netlink/genl/genl.h>
+#include <netlink/netlink.h>
+
+#include "igt_core.h"
+#include "igt_drm_netlink.h"
+
+void cleanup_nl_socket(struct app_context *ctx)
+{
+ if (!ctx || !ctx->sock)
+ return;
+
+ nl_close(ctx->sock);
+ nl_socket_free(ctx->sock);
+ ctx->sock = NULL;
+ ctx->family_id = -1;
+
+ igt_debug("Cleaned up netlink socket.\n");
+}
+
+int init_nl_socket(struct app_context *ctx)
+{
+ ctx->sock = nl_socket_alloc();
+ if (!ctx->sock)
+ return -1;
+
+ igt_debug("Socket allocation successful. Connecting to Generic Netlink...\n");
+ if (genl_connect(ctx->sock) < 0) {
+ cleanup_nl_socket(ctx);
+ return -1;
+ }
+
+ igt_debug("Resolving Generic Netlink family '%s'...\n", DRM_RAS_FAMILY_NAME);
+ ctx->family_id = genl_ctrl_resolve(ctx->sock, DRM_RAS_FAMILY_NAME);
+ if (ctx->family_id < 0) {
+ fprintf(stderr,
+ "Failed to resolve Generic Netlink family '%s': %s. "
+ "This may mean the running kernel does not expose DRM RAS support.\n",
+ DRM_RAS_FAMILY_NAME,
+ nl_geterror(ctx->family_id));
+ cleanup_nl_socket(ctx);
+ return -1;
+ }
+
+ igt_debug("Resolved Generic Netlink family '%s' with id %d.\n",
+ DRM_RAS_FAMILY_NAME, ctx->family_id);
+ return 0;
+}
diff --git a/lib/igt_drm_netlink.h b/lib/igt_drm_netlink.h
new file mode 100644
index 000000000..c20d5452b
--- /dev/null
+++ b/lib/igt_drm_netlink.h
@@ -0,0 +1,25 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright © 2026 Intel Corporation
+ */
+
+#ifndef IGT_DRM_NETLINK_H
+#define IGT_DRM_NETLINK_H
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#include <netlink/netlink.h>
+
+#include <drm-uapi/drm_ras.h>
+
+struct app_context {
+ struct nl_sock *sock;
+ int family_id;
+};
+
+void cleanup_nl_socket(struct app_context *ctx);
+int init_nl_socket(struct app_context *ctx);
+
+#endif /* IGT_DRM_NETLINK_H */
+
diff --git a/lib/meson.build b/lib/meson.build
index 4af346b43..79674e032 100644
--- a/lib/meson.build
+++ b/lib/meson.build
@@ -27,6 +27,7 @@ lib_sources = [
'igt_device_scan.c',
'igt_drm_clients.h',
'igt_drm_fdinfo.c',
+ 'igt_drm_netlink.c',
'igt_fs.c',
'igt_aux.c',
'igt_dp.c',
@@ -141,6 +142,13 @@ lib_sources = [
'vendor/uwildmat/uwildmat.c',
]
+libnl = declare_dependency(dependencies : [
+ dependency('libnl-3.0', required : true),
+ dependency('libnl-genl-3.0', required : true),
+ dependency('libnl-cli-3.0', required : true),
+ dependency('libnl-utils', required : false),
+])
+
lib_deps = [
cairo,
glib,
@@ -148,6 +156,7 @@ lib_deps = [
libdrm,
libdw,
libkmod,
+ libnl,
libpci,
libudev,
math,
--
2.34.1
^ permalink raw reply related [flat|nested] 13+ messages in thread* Re: [PATCH 1/8] lib/igt_drm_netlink: Introduce DRM RAS Generic Netlink interface
2026-07-29 12:19 ` [PATCH 1/8] lib/igt_drm_netlink: Introduce DRM RAS Generic Netlink interface Ravi Kishore Koppuravuri
@ 2026-08-06 23:45 ` Harish Chegondi
0 siblings, 0 replies; 13+ messages in thread
From: Harish Chegondi @ 2026-08-06 23:45 UTC (permalink / raw)
To: Ravi Kishore Koppuravuri
Cc: igt-dev, riana.tauro, anshuman.gupta, mallesh.koujalagi,
raag.jadav
On Wed, Jul 29, 2026 at 05:49:52PM +0530, Ravi Kishore Koppuravuri wrote:
> Introduce DRM RAS Generic Netlink interface as a library
>
> Signed-off-by: Ravi Kishore Koppuravuri <ravi.kishore.koppuravuri@intel.com>
> ---
> include/drm-uapi/drm_ras.h | 50 +++++++++++++++++++++++++++++++
> lib/igt_drm_netlink.c | 60 ++++++++++++++++++++++++++++++++++++++
> lib/igt_drm_netlink.h | 25 ++++++++++++++++
> lib/meson.build | 9 ++++++
> 4 files changed, 144 insertions(+)
> create mode 100644 include/drm-uapi/drm_ras.h
> create mode 100644 lib/igt_drm_netlink.c
> create mode 100644 lib/igt_drm_netlink.h
>
> diff --git a/include/drm-uapi/drm_ras.h b/include/drm-uapi/drm_ras.h
> new file mode 100644
> index 000000000..218a3ee86
> --- /dev/null
> +++ b/include/drm-uapi/drm_ras.h
> @@ -0,0 +1,50 @@
> +/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */
> +/* Do not edit directly, auto-generated from: */
> +/* Documentation/netlink/specs/drm_ras.yaml */
> +/* YNL-GEN uapi header */
> +/* To regenerate run: tools/net/ynl/ynl-regen.sh */
> +
> +#ifndef _UAPI_LINUX_DRM_RAS_H
> +#define _UAPI_LINUX_DRM_RAS_H
> +
> +#define DRM_RAS_FAMILY_NAME "drm-ras"
> +#define DRM_RAS_FAMILY_VERSION 1
> +
> +/*
> + * Type of the node. Currently, only error-counter nodes are supported, which
> + * expose reliability counters for a hardware/software component.
> + */
> +enum drm_ras_node_type {
> + DRM_RAS_NODE_TYPE_ERROR_COUNTER = 1,
> +};
> +
> +enum {
> + DRM_RAS_A_NODE_ATTRS_NODE_ID = 1,
> + DRM_RAS_A_NODE_ATTRS_DEVICE_NAME,
> + DRM_RAS_A_NODE_ATTRS_NODE_NAME,
> + DRM_RAS_A_NODE_ATTRS_NODE_TYPE,
> +
> + __DRM_RAS_A_NODE_ATTRS_MAX,
> + DRM_RAS_A_NODE_ATTRS_MAX = (__DRM_RAS_A_NODE_ATTRS_MAX - 1)
> +};
The above enums doesn't seem to be used anywhere in this patch series?
> +
> +enum {
> + DRM_RAS_A_ERROR_COUNTER_ATTRS_NODE_ID = 1,
> + DRM_RAS_A_ERROR_COUNTER_ATTRS_ERROR_ID,
> + DRM_RAS_A_ERROR_COUNTER_ATTRS_ERROR_NAME,
> + DRM_RAS_A_ERROR_COUNTER_ATTRS_ERROR_VALUE,
> +
> + __DRM_RAS_A_ERROR_COUNTER_ATTRS_MAX,
> + DRM_RAS_A_ERROR_COUNTER_ATTRS_MAX = (__DRM_RAS_A_ERROR_COUNTER_ATTRS_MAX - 1)
> +};
Is this header file auto generated? I wonder why the above enums have an
"A" after RAS but not the below enums? I think it would be a good idea
to have consistency in enum names.
> +
> +enum {
> + DRM_RAS_CMD_LIST_NODES = 1,
> + DRM_RAS_CMD_GET_ERROR_COUNTER,
> + DRM_RAS_CMD_CLEAR_ERROR_COUNTER,
> +
> + __DRM_RAS_CMD_MAX,
> + DRM_RAS_CMD_MAX = (__DRM_RAS_CMD_MAX - 1)
> +};
> +
> +#endif /* _UAPI_LINUX_DRM_RAS_H */
> diff --git a/lib/igt_drm_netlink.c b/lib/igt_drm_netlink.c
> new file mode 100644
> index 000000000..1c07bb2db
> --- /dev/null
> +++ b/lib/igt_drm_netlink.c
> @@ -0,0 +1,60 @@
> +// SPDX-License-Identifier: MIT
> +/*
> + * Copyright © 2026 Intel Corporation
> + */
> +
> +#include <stdbool.h>
> +#include <stdint.h>
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <string.h>
> +
> +#include <netlink/errno.h>
> +#include <netlink/genl/ctrl.h>
> +#include <netlink/genl/genl.h>
> +#include <netlink/netlink.h>
> +
> +#include "igt_core.h"
> +#include "igt_drm_netlink.h"
> +
> +void cleanup_nl_socket(struct app_context *ctx)
> +{
> + if (!ctx || !ctx->sock)
> + return;
> +
> + nl_close(ctx->sock);
> + nl_socket_free(ctx->sock);
> + ctx->sock = NULL;
> + ctx->family_id = -1;
> +
> + igt_debug("Cleaned up netlink socket.\n");
> +}
> +
> +int init_nl_socket(struct app_context *ctx)
> +{
> + ctx->sock = nl_socket_alloc();
> + if (!ctx->sock)
> + return -1;
> +
> + igt_debug("Socket allocation successful. Connecting to Generic Netlink...\n");
> + if (genl_connect(ctx->sock) < 0) {
> + cleanup_nl_socket(ctx);
> + return -1;
> + }
> +
> + igt_debug("Resolving Generic Netlink family '%s'...\n", DRM_RAS_FAMILY_NAME);
> + ctx->family_id = genl_ctrl_resolve(ctx->sock, DRM_RAS_FAMILY_NAME);
> + if (ctx->family_id < 0) {
> + fprintf(stderr,
> + "Failed to resolve Generic Netlink family '%s': %s. "
> + "This may mean the running kernel does not expose DRM RAS support.\n",
> + DRM_RAS_FAMILY_NAME,
> + nl_geterror(ctx->family_id));
> + cleanup_nl_socket(ctx);
> + return -1;
> + }
> +
> + igt_debug("Resolved Generic Netlink family '%s' with id %d.\n",
> + DRM_RAS_FAMILY_NAME, ctx->family_id);
> + return 0;
> +}
> diff --git a/lib/igt_drm_netlink.h b/lib/igt_drm_netlink.h
> new file mode 100644
> index 000000000..c20d5452b
> --- /dev/null
> +++ b/lib/igt_drm_netlink.h
> @@ -0,0 +1,25 @@
> +/* SPDX-License-Identifier: MIT */
> +/*
> + * Copyright © 2026 Intel Corporation
> + */
> +
> +#ifndef IGT_DRM_NETLINK_H
> +#define IGT_DRM_NETLINK_H
> +
> +#include <stdbool.h>
> +#include <stdint.h>
> +
> +#include <netlink/netlink.h>
> +
> +#include <drm-uapi/drm_ras.h>
> +
> +struct app_context {
> + struct nl_sock *sock;
> + int family_id;
> +};
> +
> +void cleanup_nl_socket(struct app_context *ctx);
> +int init_nl_socket(struct app_context *ctx);
> +
> +#endif /* IGT_DRM_NETLINK_H */
> +
> diff --git a/lib/meson.build b/lib/meson.build
> index 4af346b43..79674e032 100644
> --- a/lib/meson.build
> +++ b/lib/meson.build
> @@ -27,6 +27,7 @@ lib_sources = [
> 'igt_device_scan.c',
> 'igt_drm_clients.h',
> 'igt_drm_fdinfo.c',
> + 'igt_drm_netlink.c',
> 'igt_fs.c',
> 'igt_aux.c',
> 'igt_dp.c',
> @@ -141,6 +142,13 @@ lib_sources = [
> 'vendor/uwildmat/uwildmat.c',
> ]
>
> +libnl = declare_dependency(dependencies : [
> + dependency('libnl-3.0', required : true),
> + dependency('libnl-genl-3.0', required : true),
> + dependency('libnl-cli-3.0', required : true),
> + dependency('libnl-utils', required : false),
> +])
> +
> lib_deps = [
> cairo,
> glib,
> @@ -148,6 +156,7 @@ lib_deps = [
> libdrm,
> libdw,
> libkmod,
> + libnl,
> libpci,
> libudev,
> math,
> --
> 2.34.1
>
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 2/8] lib/igt_drm_netlink: add get_error_counter support
2026-07-29 12:19 [PATCH 0/8] Xe3P GPU Error Injection Test Suite with DRM RAS Netlink Support Ravi Kishore Koppuravuri
2026-07-29 12:19 ` [PATCH 1/8] lib/igt_drm_netlink: Introduce DRM RAS Generic Netlink interface Ravi Kishore Koppuravuri
@ 2026-07-29 12:19 ` Ravi Kishore Koppuravuri
2026-07-29 12:19 ` [PATCH 3/8] lib/igt_drm_netlink: add get_error_threshold command support Ravi Kishore Koppuravuri
` (5 subsequent siblings)
7 siblings, 0 replies; 13+ messages in thread
From: Ravi Kishore Koppuravuri @ 2026-07-29 12:19 UTC (permalink / raw)
To: igt-dev
Cc: riana.tauro, anshuman.gupta, mallesh.koujalagi, raag.jadav,
Ravi Kishore Koppuravuri
Add netlink request/response handling for DRM_RAS_CMD_GET_ERROR_COUNTER.
Signed-off-by: Ravi Kishore Koppuravuri <ravi.kishore.koppuravuri@intel.com>
---
lib/igt_drm_netlink.c | 179 +++++++++++++++++++++++++++++++++++++++++-
lib/igt_drm_netlink.h | 11 +++
2 files changed, 188 insertions(+), 2 deletions(-)
diff --git a/lib/igt_drm_netlink.c b/lib/igt_drm_netlink.c
index 1c07bb2db..4d543275d 100644
--- a/lib/igt_drm_netlink.c
+++ b/lib/igt_drm_netlink.c
@@ -5,6 +5,7 @@
#include <stdbool.h>
#include <stdint.h>
+#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -17,6 +18,146 @@
#include "igt_core.h"
#include "igt_drm_netlink.h"
+static int ras_command_cb(struct nl_msg *msg, void *arg)
+{
+ struct app_context *ctx = arg;
+ struct nlmsghdr *nlh;
+ struct genlmsghdr *gnlh;
+ int ret;
+
+ nlh = nlmsg_hdr(msg);
+ gnlh = nlmsg_data(nlh);
+
+ switch (gnlh->cmd) {
+ case DRM_RAS_CMD_GET_ERROR_COUNTER: {
+ struct nlattr *attrs[DRM_RAS_A_ERROR_COUNTER_ATTRS_MAX + 1];
+
+ ret = genlmsg_parse(nlh, 0, attrs,
+ DRM_RAS_A_ERROR_COUNTER_ATTRS_MAX, NULL);
+ if (ret < 0)
+ return NL_SKIP;
+
+ if (!attrs[DRM_RAS_A_ERROR_COUNTER_ATTRS_ERROR_VALUE])
+ return NL_SKIP;
+
+ ctx->error_value = nla_get_u32(attrs[DRM_RAS_A_ERROR_COUNTER_ATTRS_ERROR_VALUE]);
+ break;
+ }
+ default:
+ return NL_SKIP;
+ }
+
+ return NL_OK;
+}
+
+static int send_and_recv_nl_msg(struct app_context *ctx,
+ struct nl_cb *cb,
+ struct nl_msg *msg)
+{
+ int ret;
+
+ ret = nl_send_auto(ctx->sock, msg);
+ nlmsg_free(msg);
+ if (ret < 0) {
+ nl_cb_put(cb);
+ return ret;
+ }
+
+ ret = nl_recvmsgs(ctx->sock, cb);
+ nl_cb_put(cb);
+
+ return ret;
+}
+
+static int send_command(struct app_context *ctx, uint8_t cmd)
+{
+ struct nl_cb *cb;
+ struct nl_msg *msg;
+ void *msg_head;
+ int ret;
+
+ msg = nlmsg_alloc();
+ if (!msg)
+ return -ENOMEM;
+
+ msg_head = genlmsg_put(msg,
+ NL_AUTO_PORT,
+ NL_AUTO_SEQ,
+ ctx->family_id,
+ 0,
+ NLM_F_REQUEST | NLM_F_ACK,
+ cmd,
+ DRM_RAS_FAMILY_VERSION);
+ if (!msg_head) {
+ nlmsg_free(msg);
+ return -ENOMEM;
+ }
+
+ switch (cmd) {
+ case DRM_RAS_CMD_GET_ERROR_COUNTER:
+ ret = nla_put_u32(msg,
+ DRM_RAS_A_ERROR_COUNTER_ATTRS_NODE_ID,
+ ctx->node_id);
+ if (ret < 0) {
+ nlmsg_free(msg);
+ return ret;
+ }
+
+ ret = nla_put_u32(msg,
+ DRM_RAS_A_ERROR_COUNTER_ATTRS_ERROR_ID,
+ ctx->error_id);
+ if (ret < 0) {
+ nlmsg_free(msg);
+ return ret;
+ }
+ break;
+ default:
+ nlmsg_free(msg);
+ return -EOPNOTSUPP;
+ }
+
+ cb = nl_cb_alloc(NL_CB_DEFAULT);
+ if (!cb) {
+ nlmsg_free(msg);
+ return -ENOMEM;
+ }
+
+ ret = nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, ras_command_cb, ctx);
+ if (ret < 0) {
+ nl_cb_put(cb);
+ nlmsg_free(msg);
+ return ret;
+ }
+
+ return send_and_recv_nl_msg(ctx, cb, msg);
+}
+
+int init_app_context(struct app_context *ctx)
+{
+ if (!ctx)
+ return -EINVAL;
+
+ ctx->sock = NULL;
+ ctx->node_id = UINT32_MAX;
+ ctx->error_id = UINT32_MAX;
+ ctx->error_value = 0;
+ ctx->family_id = -1;
+
+ return 0;
+}
+
+void cleanup_app_context(struct app_context *ctx)
+{
+ if (!ctx)
+ return;
+
+ ctx->sock = NULL;
+ ctx->node_id = UINT32_MAX;
+ ctx->error_id = UINT32_MAX;
+ ctx->error_value = 0;
+ ctx->family_id = -1;
+}
+
void cleanup_nl_socket(struct app_context *ctx)
{
if (!ctx || !ctx->sock)
@@ -24,14 +165,20 @@ void cleanup_nl_socket(struct app_context *ctx)
nl_close(ctx->sock);
nl_socket_free(ctx->sock);
- ctx->sock = NULL;
- ctx->family_id = -1;
+
+ cleanup_app_context(ctx);
igt_debug("Cleaned up netlink socket.\n");
}
int init_nl_socket(struct app_context *ctx)
{
+ int ret;
+
+ ret = init_app_context(ctx);
+ if (ret < 0)
+ return ret;
+
ctx->sock = nl_socket_alloc();
if (!ctx->sock)
return -1;
@@ -58,3 +205,31 @@ int init_nl_socket(struct app_context *ctx)
DRM_RAS_FAMILY_NAME, ctx->family_id);
return 0;
}
+
+int get_error_counter(struct app_context *ctx)
+{
+ int ret;
+
+ if (!ctx || !ctx->sock || ctx->family_id < 0)
+ return -EINVAL;
+
+ if (ctx->node_id == UINT32_MAX ||
+ ctx->error_id == UINT32_MAX ||
+ ctx->error_id == 0) {
+ igt_warn("Invalid node_id (%u) or error_id (%u) provided. "
+ "node_id should be >= 0 and error_id should be >= 1.\n",
+ ctx->node_id, ctx->error_id);
+ return -EINVAL;
+ }
+
+ ctx->error_value = 0;
+
+ ret = send_command(ctx, DRM_RAS_CMD_GET_ERROR_COUNTER);
+ if (ret < 0)
+ return ret;
+
+ igt_debug("Retrieved error counter: node_id=%u error_id=%u value=%u\n",
+ ctx->node_id, ctx->error_id, ctx->error_value);
+
+ return 0;
+}
diff --git a/lib/igt_drm_netlink.h b/lib/igt_drm_netlink.h
index c20d5452b..e539bc030 100644
--- a/lib/igt_drm_netlink.h
+++ b/lib/igt_drm_netlink.h
@@ -9,17 +9,28 @@
#include <stdbool.h>
#include <stdint.h>
+#include <linux/genetlink.h>
+
+#include <netlink/attr.h>
+#include <netlink/handlers.h>
+#include <netlink/msg.h>
#include <netlink/netlink.h>
#include <drm-uapi/drm_ras.h>
struct app_context {
struct nl_sock *sock;
+ uint32_t node_id;
+ uint32_t error_id;
+ uint32_t error_value;
int family_id;
};
+int init_app_context(struct app_context *ctx);
+void cleanup_app_context(struct app_context *ctx);
void cleanup_nl_socket(struct app_context *ctx);
int init_nl_socket(struct app_context *ctx);
+int get_error_counter(struct app_context *ctx);
#endif /* IGT_DRM_NETLINK_H */
--
2.34.1
^ permalink raw reply related [flat|nested] 13+ messages in thread* [PATCH 3/8] lib/igt_drm_netlink: add get_error_threshold command support
2026-07-29 12:19 [PATCH 0/8] Xe3P GPU Error Injection Test Suite with DRM RAS Netlink Support Ravi Kishore Koppuravuri
2026-07-29 12:19 ` [PATCH 1/8] lib/igt_drm_netlink: Introduce DRM RAS Generic Netlink interface Ravi Kishore Koppuravuri
2026-07-29 12:19 ` [PATCH 2/8] lib/igt_drm_netlink: add get_error_counter support Ravi Kishore Koppuravuri
@ 2026-07-29 12:19 ` Ravi Kishore Koppuravuri
2026-08-07 23:14 ` Harish Chegondi
2026-07-29 12:19 ` [PATCH 4/8] lib/igt_drm_netlink: add set_error_threshold " Ravi Kishore Koppuravuri
` (4 subsequent siblings)
7 siblings, 1 reply; 13+ messages in thread
From: Ravi Kishore Koppuravuri @ 2026-07-29 12:19 UTC (permalink / raw)
To: igt-dev
Cc: riana.tauro, anshuman.gupta, mallesh.koujalagi, raag.jadav,
Ravi Kishore Koppuravuri
Add support for GET_ERROR_THRESHOLD to fetch the current value of error
threshold
Signed-off-by: Ravi Kishore Koppuravuri <ravi.kishore.koppuravuri@intel.com>
---
include/drm-uapi/drm_ras.h | 18 +++++++++++++
lib/igt_drm_netlink.c | 53 +++++++++++++++++++++++++++++++++++---
lib/igt_drm_netlink.h | 2 ++
3 files changed, 70 insertions(+), 3 deletions(-)
diff --git a/include/drm-uapi/drm_ras.h b/include/drm-uapi/drm_ras.h
index 218a3ee86..60611833b 100644
--- a/include/drm-uapi/drm_ras.h
+++ b/include/drm-uapi/drm_ras.h
@@ -33,18 +33,36 @@ enum {
DRM_RAS_A_ERROR_COUNTER_ATTRS_ERROR_ID,
DRM_RAS_A_ERROR_COUNTER_ATTRS_ERROR_NAME,
DRM_RAS_A_ERROR_COUNTER_ATTRS_ERROR_VALUE,
+ DRM_RAS_A_ERROR_COUNTER_ATTRS_ERROR_THRESHOLD,
__DRM_RAS_A_ERROR_COUNTER_ATTRS_MAX,
DRM_RAS_A_ERROR_COUNTER_ATTRS_MAX = (__DRM_RAS_A_ERROR_COUNTER_ATTRS_MAX - 1)
};
+enum {
+ DRM_RAS_A_ERROR_EVENT_ATTRS_DEVICE_NAME = 1,
+ DRM_RAS_A_ERROR_EVENT_ATTRS_NODE_ID,
+ DRM_RAS_A_ERROR_EVENT_ATTRS_NODE_NAME,
+ DRM_RAS_A_ERROR_EVENT_ATTRS_ERROR_ID,
+ DRM_RAS_A_ERROR_EVENT_ATTRS_ERROR_NAME,
+ DRM_RAS_A_ERROR_EVENT_ATTRS_ERROR_VALUE,
+
+ __DRM_RAS_A_ERROR_EVENT_ATTRS_MAX,
+ DRM_RAS_A_ERROR_EVENT_ATTRS_MAX = (__DRM_RAS_A_ERROR_EVENT_ATTRS_MAX - 1)
+};
+
enum {
DRM_RAS_CMD_LIST_NODES = 1,
DRM_RAS_CMD_GET_ERROR_COUNTER,
DRM_RAS_CMD_CLEAR_ERROR_COUNTER,
+ DRM_RAS_CMD_GET_ERROR_THRESHOLD,
+ DRM_RAS_CMD_SET_ERROR_THRESHOLD,
+ DRM_RAS_CMD_ERROR_EVENT,
__DRM_RAS_CMD_MAX,
DRM_RAS_CMD_MAX = (__DRM_RAS_CMD_MAX - 1)
};
+#define DRM_RAS_MCGRP_ERROR_NOTIFY "error-notify"
+
#endif /* _UAPI_LINUX_DRM_RAS_H */
diff --git a/lib/igt_drm_netlink.c b/lib/igt_drm_netlink.c
index 4d543275d..036660a6a 100644
--- a/lib/igt_drm_netlink.c
+++ b/lib/igt_drm_netlink.c
@@ -43,6 +43,21 @@ static int ras_command_cb(struct nl_msg *msg, void *arg)
ctx->error_value = nla_get_u32(attrs[DRM_RAS_A_ERROR_COUNTER_ATTRS_ERROR_VALUE]);
break;
}
+ case DRM_RAS_CMD_GET_ERROR_THRESHOLD: {
+ struct nlattr *attrs[DRM_RAS_A_ERROR_COUNTER_ATTRS_MAX + 1];
+
+ ret = genlmsg_parse(nlh, 0, attrs,
+ DRM_RAS_A_ERROR_COUNTER_ATTRS_MAX, NULL);
+ if (ret < 0)
+ return NL_SKIP;
+
+ if (!attrs[DRM_RAS_A_ERROR_COUNTER_ATTRS_ERROR_THRESHOLD])
+ return NL_SKIP;
+
+ ctx->error_threshold =
+ nla_get_u32(attrs[DRM_RAS_A_ERROR_COUNTER_ATTRS_ERROR_THRESHOLD]);
+ break;
+ }
default:
return NL_SKIP;
}
@@ -94,6 +109,7 @@ static int send_command(struct app_context *ctx, uint8_t cmd)
}
switch (cmd) {
+ case DRM_RAS_CMD_GET_ERROR_THRESHOLD:
case DRM_RAS_CMD_GET_ERROR_COUNTER:
ret = nla_put_u32(msg,
DRM_RAS_A_ERROR_COUNTER_ATTRS_NODE_ID,
@@ -141,6 +157,7 @@ int init_app_context(struct app_context *ctx)
ctx->node_id = UINT32_MAX;
ctx->error_id = UINT32_MAX;
ctx->error_value = 0;
+ ctx->error_threshold = 0;
ctx->family_id = -1;
return 0;
@@ -155,6 +172,7 @@ void cleanup_app_context(struct app_context *ctx)
ctx->node_id = UINT32_MAX;
ctx->error_id = UINT32_MAX;
ctx->error_value = 0;
+ ctx->error_threshold = 0;
ctx->family_id = -1;
}
@@ -206,10 +224,8 @@ int init_nl_socket(struct app_context *ctx)
return 0;
}
-int get_error_counter(struct app_context *ctx)
+static int validate_inputs(struct app_context *ctx, uint8_t cmd)
{
- int ret;
-
if (!ctx || !ctx->sock || ctx->family_id < 0)
return -EINVAL;
@@ -222,6 +238,17 @@ int get_error_counter(struct app_context *ctx)
return -EINVAL;
}
+ return 0;
+}
+
+int get_error_counter(struct app_context *ctx)
+{
+ int ret;
+
+ ret = validate_inputs(ctx, DRM_RAS_CMD_GET_ERROR_COUNTER);
+ if (ret < 0)
+ return ret;
+
ctx->error_value = 0;
ret = send_command(ctx, DRM_RAS_CMD_GET_ERROR_COUNTER);
@@ -233,3 +260,23 @@ int get_error_counter(struct app_context *ctx)
return 0;
}
+
+int get_error_threshold(struct app_context *ctx)
+{
+ int ret;
+
+ ret = validate_inputs(ctx, DRM_RAS_CMD_GET_ERROR_THRESHOLD);
+ if (ret < 0)
+ return ret;
+
+ ctx->error_threshold = 0;
+
+ ret = send_command(ctx, DRM_RAS_CMD_GET_ERROR_THRESHOLD);
+ if (ret < 0)
+ return ret;
+
+ igt_debug("Retrieved error threshold: node_id=%u error_id=%u threshold=%u\n",
+ ctx->node_id, ctx->error_id, ctx->error_threshold);
+
+ return 0;
+}
diff --git a/lib/igt_drm_netlink.h b/lib/igt_drm_netlink.h
index e539bc030..fae9b0e06 100644
--- a/lib/igt_drm_netlink.h
+++ b/lib/igt_drm_netlink.h
@@ -23,6 +23,7 @@ struct app_context {
uint32_t node_id;
uint32_t error_id;
uint32_t error_value;
+ uint32_t error_threshold;
int family_id;
};
@@ -31,6 +32,7 @@ void cleanup_app_context(struct app_context *ctx);
void cleanup_nl_socket(struct app_context *ctx);
int init_nl_socket(struct app_context *ctx);
int get_error_counter(struct app_context *ctx);
+int get_error_threshold(struct app_context *ctx);
#endif /* IGT_DRM_NETLINK_H */
--
2.34.1
^ permalink raw reply related [flat|nested] 13+ messages in thread* Re: [PATCH 3/8] lib/igt_drm_netlink: add get_error_threshold command support
2026-07-29 12:19 ` [PATCH 3/8] lib/igt_drm_netlink: add get_error_threshold command support Ravi Kishore Koppuravuri
@ 2026-08-07 23:14 ` Harish Chegondi
0 siblings, 0 replies; 13+ messages in thread
From: Harish Chegondi @ 2026-08-07 23:14 UTC (permalink / raw)
To: Ravi Kishore Koppuravuri
Cc: igt-dev, riana.tauro, anshuman.gupta, mallesh.koujalagi,
raag.jadav
On Wed, Jul 29, 2026 at 05:49:54PM +0530, Ravi Kishore Koppuravuri wrote:
> Add support for GET_ERROR_THRESHOLD to fetch the current value of error
> threshold
>
> Signed-off-by: Ravi Kishore Koppuravuri <ravi.kishore.koppuravuri@intel.com>
> ---
> include/drm-uapi/drm_ras.h | 18 +++++++++++++
> lib/igt_drm_netlink.c | 53 +++++++++++++++++++++++++++++++++++---
> lib/igt_drm_netlink.h | 2 ++
> 3 files changed, 70 insertions(+), 3 deletions(-)
>
> diff --git a/include/drm-uapi/drm_ras.h b/include/drm-uapi/drm_ras.h
> index 218a3ee86..60611833b 100644
> --- a/include/drm-uapi/drm_ras.h
> +++ b/include/drm-uapi/drm_ras.h
> @@ -33,18 +33,36 @@ enum {
> DRM_RAS_A_ERROR_COUNTER_ATTRS_ERROR_ID,
> DRM_RAS_A_ERROR_COUNTER_ATTRS_ERROR_NAME,
> DRM_RAS_A_ERROR_COUNTER_ATTRS_ERROR_VALUE,
> + DRM_RAS_A_ERROR_COUNTER_ATTRS_ERROR_THRESHOLD,
>
> __DRM_RAS_A_ERROR_COUNTER_ATTRS_MAX,
> DRM_RAS_A_ERROR_COUNTER_ATTRS_MAX = (__DRM_RAS_A_ERROR_COUNTER_ATTRS_MAX - 1)
> };
>
> +enum {
> + DRM_RAS_A_ERROR_EVENT_ATTRS_DEVICE_NAME = 1,
> + DRM_RAS_A_ERROR_EVENT_ATTRS_NODE_ID,
> + DRM_RAS_A_ERROR_EVENT_ATTRS_NODE_NAME,
> + DRM_RAS_A_ERROR_EVENT_ATTRS_ERROR_ID,
> + DRM_RAS_A_ERROR_EVENT_ATTRS_ERROR_NAME,
> + DRM_RAS_A_ERROR_EVENT_ATTRS_ERROR_VALUE,
> +
> + __DRM_RAS_A_ERROR_EVENT_ATTRS_MAX,
> + DRM_RAS_A_ERROR_EVENT_ATTRS_MAX = (__DRM_RAS_A_ERROR_EVENT_ATTRS_MAX - 1)
The above enums are not used anywhere in this patch?
> +};
> +
> enum {
> DRM_RAS_CMD_LIST_NODES = 1,
> DRM_RAS_CMD_GET_ERROR_COUNTER,
> DRM_RAS_CMD_CLEAR_ERROR_COUNTER,
> + DRM_RAS_CMD_GET_ERROR_THRESHOLD,
> + DRM_RAS_CMD_SET_ERROR_THRESHOLD,
> + DRM_RAS_CMD_ERROR_EVENT,
DRM_RAS_CMD_SET_ERROR_THRESHOLD and DRM_RAS_CMD_ERROR_EVENT are not
used in this patch?
>
> __DRM_RAS_CMD_MAX,
> DRM_RAS_CMD_MAX = (__DRM_RAS_CMD_MAX - 1)
> };
>
> +#define DRM_RAS_MCGRP_ERROR_NOTIFY "error-notify"
Same here. DRM_RAS_MCGRP_ERROR_NOTIFY not used in this patch?
> +
> #endif /* _UAPI_LINUX_DRM_RAS_H */
> diff --git a/lib/igt_drm_netlink.c b/lib/igt_drm_netlink.c
> index 4d543275d..036660a6a 100644
> --- a/lib/igt_drm_netlink.c
> +++ b/lib/igt_drm_netlink.c
> @@ -43,6 +43,21 @@ static int ras_command_cb(struct nl_msg *msg, void *arg)
> ctx->error_value = nla_get_u32(attrs[DRM_RAS_A_ERROR_COUNTER_ATTRS_ERROR_VALUE]);
> break;
> }
> + case DRM_RAS_CMD_GET_ERROR_THRESHOLD: {
> + struct nlattr *attrs[DRM_RAS_A_ERROR_COUNTER_ATTRS_MAX + 1];
> +
> + ret = genlmsg_parse(nlh, 0, attrs,
> + DRM_RAS_A_ERROR_COUNTER_ATTRS_MAX, NULL);
> + if (ret < 0)
> + return NL_SKIP;
> +
> + if (!attrs[DRM_RAS_A_ERROR_COUNTER_ATTRS_ERROR_THRESHOLD])
> + return NL_SKIP;
> +
> + ctx->error_threshold =
> + nla_get_u32(attrs[DRM_RAS_A_ERROR_COUNTER_ATTRS_ERROR_THRESHOLD]);
> + break;
> + }
> default:
> return NL_SKIP;
> }
> @@ -94,6 +109,7 @@ static int send_command(struct app_context *ctx, uint8_t cmd)
> }
>
> switch (cmd) {
> + case DRM_RAS_CMD_GET_ERROR_THRESHOLD:
> case DRM_RAS_CMD_GET_ERROR_COUNTER:
> ret = nla_put_u32(msg,
> DRM_RAS_A_ERROR_COUNTER_ATTRS_NODE_ID,
> @@ -141,6 +157,7 @@ int init_app_context(struct app_context *ctx)
> ctx->node_id = UINT32_MAX;
> ctx->error_id = UINT32_MAX;
> ctx->error_value = 0;
> + ctx->error_threshold = 0;
> ctx->family_id = -1;
>
> return 0;
> @@ -155,6 +172,7 @@ void cleanup_app_context(struct app_context *ctx)
> ctx->node_id = UINT32_MAX;
> ctx->error_id = UINT32_MAX;
> ctx->error_value = 0;
> + ctx->error_threshold = 0;
> ctx->family_id = -1;
> }
>
> @@ -206,10 +224,8 @@ int init_nl_socket(struct app_context *ctx)
> return 0;
> }
>
> -int get_error_counter(struct app_context *ctx)
> +static int validate_inputs(struct app_context *ctx, uint8_t cmd)
> {
> - int ret;
> -
> if (!ctx || !ctx->sock || ctx->family_id < 0)
> return -EINVAL;
>
> @@ -222,6 +238,17 @@ int get_error_counter(struct app_context *ctx)
> return -EINVAL;
> }
>
> + return 0;
> +}
> +
> +int get_error_counter(struct app_context *ctx)
> +{
> + int ret;
> +
> + ret = validate_inputs(ctx, DRM_RAS_CMD_GET_ERROR_COUNTER);
> + if (ret < 0)
> + return ret;
> +
> ctx->error_value = 0;
>
> ret = send_command(ctx, DRM_RAS_CMD_GET_ERROR_COUNTER);
> @@ -233,3 +260,23 @@ int get_error_counter(struct app_context *ctx)
>
> return 0;
> }
> +
> +int get_error_threshold(struct app_context *ctx)
> +{
> + int ret;
> +
> + ret = validate_inputs(ctx, DRM_RAS_CMD_GET_ERROR_THRESHOLD);
> + if (ret < 0)
> + return ret;
> +
> + ctx->error_threshold = 0;
> +
> + ret = send_command(ctx, DRM_RAS_CMD_GET_ERROR_THRESHOLD);
> + if (ret < 0)
> + return ret;
> +
> + igt_debug("Retrieved error threshold: node_id=%u error_id=%u threshold=%u\n",
> + ctx->node_id, ctx->error_id, ctx->error_threshold);
> +
> + return 0;
> +}
> diff --git a/lib/igt_drm_netlink.h b/lib/igt_drm_netlink.h
> index e539bc030..fae9b0e06 100644
> --- a/lib/igt_drm_netlink.h
> +++ b/lib/igt_drm_netlink.h
> @@ -23,6 +23,7 @@ struct app_context {
> uint32_t node_id;
> uint32_t error_id;
> uint32_t error_value;
> + uint32_t error_threshold;
> int family_id;
> };
>
> @@ -31,6 +32,7 @@ void cleanup_app_context(struct app_context *ctx);
> void cleanup_nl_socket(struct app_context *ctx);
> int init_nl_socket(struct app_context *ctx);
> int get_error_counter(struct app_context *ctx);
> +int get_error_threshold(struct app_context *ctx);
>
> #endif /* IGT_DRM_NETLINK_H */
>
> --
> 2.34.1
>
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 4/8] lib/igt_drm_netlink: add set_error_threshold command support
2026-07-29 12:19 [PATCH 0/8] Xe3P GPU Error Injection Test Suite with DRM RAS Netlink Support Ravi Kishore Koppuravuri
` (2 preceding siblings ...)
2026-07-29 12:19 ` [PATCH 3/8] lib/igt_drm_netlink: add get_error_threshold command support Ravi Kishore Koppuravuri
@ 2026-07-29 12:19 ` Ravi Kishore Koppuravuri
2026-08-07 23:21 ` Harish Chegondi
2026-07-29 12:19 ` [PATCH 5/8] tests/intel/xe_err_injection: Add GT UC Unicast GAM Walker Command Parity Error Injection Ravi Kishore Koppuravuri
` (3 subsequent siblings)
7 siblings, 1 reply; 13+ messages in thread
From: Ravi Kishore Koppuravuri @ 2026-07-29 12:19 UTC (permalink / raw)
To: igt-dev
Cc: riana.tauro, anshuman.gupta, mallesh.koujalagi, raag.jadav,
Ravi Kishore Koppuravuri
Add support for SET_ERROR_THRESHOLD to set the custom error threshold
value
Signed-off-by: Ravi Kishore Koppuravuri <ravi.kishore.koppuravuri@intel.com>
---
lib/igt_drm_netlink.c | 39 +++++++++++++++++++++++++++++++++++++++
lib/igt_drm_netlink.h | 1 +
2 files changed, 40 insertions(+)
diff --git a/lib/igt_drm_netlink.c b/lib/igt_drm_netlink.c
index 036660a6a..4738090af 100644
--- a/lib/igt_drm_netlink.c
+++ b/lib/igt_drm_netlink.c
@@ -29,6 +29,8 @@ static int ras_command_cb(struct nl_msg *msg, void *arg)
gnlh = nlmsg_data(nlh);
switch (gnlh->cmd) {
+ case DRM_RAS_CMD_SET_ERROR_THRESHOLD:
+ break;
case DRM_RAS_CMD_GET_ERROR_COUNTER: {
struct nlattr *attrs[DRM_RAS_A_ERROR_COUNTER_ATTRS_MAX + 1];
@@ -109,6 +111,7 @@ static int send_command(struct app_context *ctx, uint8_t cmd)
}
switch (cmd) {
+ case DRM_RAS_CMD_SET_ERROR_THRESHOLD:
case DRM_RAS_CMD_GET_ERROR_THRESHOLD:
case DRM_RAS_CMD_GET_ERROR_COUNTER:
ret = nla_put_u32(msg,
@@ -126,6 +129,16 @@ static int send_command(struct app_context *ctx, uint8_t cmd)
nlmsg_free(msg);
return ret;
}
+
+ if (cmd == DRM_RAS_CMD_SET_ERROR_THRESHOLD) {
+ ret = nla_put_u32(msg,
+ DRM_RAS_A_ERROR_COUNTER_ATTRS_ERROR_THRESHOLD,
+ ctx->error_threshold);
+ if (ret < 0) {
+ nlmsg_free(msg);
+ return ret;
+ }
+ }
break;
default:
nlmsg_free(msg);
@@ -238,6 +251,14 @@ static int validate_inputs(struct app_context *ctx, uint8_t cmd)
return -EINVAL;
}
+ if (cmd == DRM_RAS_CMD_SET_ERROR_THRESHOLD &&
+ (ctx->error_threshold < 1 || ctx->error_threshold > 16)) {
+ igt_warn("Invalid error_threshold (%u) provided. "
+ "error_threshold should be >= 1 and <= 16.\n",
+ ctx->error_threshold);
+ return -EINVAL;
+ }
+
return 0;
}
@@ -280,3 +301,21 @@ int get_error_threshold(struct app_context *ctx)
return 0;
}
+
+int set_error_threshold(struct app_context *ctx)
+{
+ int ret;
+
+ ret = validate_inputs(ctx, DRM_RAS_CMD_SET_ERROR_THRESHOLD);
+ if (ret < 0)
+ return ret;
+
+ ret = send_command(ctx, DRM_RAS_CMD_SET_ERROR_THRESHOLD);
+ if (ret < 0)
+ return ret;
+
+ igt_debug("Set error threshold: node_id=%u error_id=%u threshold=%u\n",
+ ctx->node_id, ctx->error_id, ctx->error_threshold);
+
+ return 0;
+}
diff --git a/lib/igt_drm_netlink.h b/lib/igt_drm_netlink.h
index fae9b0e06..c44486ffa 100644
--- a/lib/igt_drm_netlink.h
+++ b/lib/igt_drm_netlink.h
@@ -33,6 +33,7 @@ void cleanup_nl_socket(struct app_context *ctx);
int init_nl_socket(struct app_context *ctx);
int get_error_counter(struct app_context *ctx);
int get_error_threshold(struct app_context *ctx);
+int set_error_threshold(struct app_context *ctx);
#endif /* IGT_DRM_NETLINK_H */
--
2.34.1
^ permalink raw reply related [flat|nested] 13+ messages in thread* Re: [PATCH 4/8] lib/igt_drm_netlink: add set_error_threshold command support
2026-07-29 12:19 ` [PATCH 4/8] lib/igt_drm_netlink: add set_error_threshold " Ravi Kishore Koppuravuri
@ 2026-08-07 23:21 ` Harish Chegondi
0 siblings, 0 replies; 13+ messages in thread
From: Harish Chegondi @ 2026-08-07 23:21 UTC (permalink / raw)
To: Ravi Kishore Koppuravuri
Cc: igt-dev, riana.tauro, anshuman.gupta, mallesh.koujalagi,
raag.jadav
On Wed, Jul 29, 2026 at 05:49:55PM +0530, Ravi Kishore Koppuravuri wrote:
> Add support for SET_ERROR_THRESHOLD to set the custom error threshold
> value
>
> Signed-off-by: Ravi Kishore Koppuravuri <ravi.kishore.koppuravuri@intel.com>
> ---
> lib/igt_drm_netlink.c | 39 +++++++++++++++++++++++++++++++++++++++
> lib/igt_drm_netlink.h | 1 +
> 2 files changed, 40 insertions(+)
>
> diff --git a/lib/igt_drm_netlink.c b/lib/igt_drm_netlink.c
> index 036660a6a..4738090af 100644
> --- a/lib/igt_drm_netlink.c
> +++ b/lib/igt_drm_netlink.c
> @@ -29,6 +29,8 @@ static int ras_command_cb(struct nl_msg *msg, void *arg)
> gnlh = nlmsg_data(nlh);
>
> switch (gnlh->cmd) {
> + case DRM_RAS_CMD_SET_ERROR_THRESHOLD:
The definition of DRM_RAS_CMD_SET_ERROR_THRESHOLD needs to be added in
this patch instead of the previous patch.
> + break;
> case DRM_RAS_CMD_GET_ERROR_COUNTER: {
> struct nlattr *attrs[DRM_RAS_A_ERROR_COUNTER_ATTRS_MAX + 1];
>
> @@ -109,6 +111,7 @@ static int send_command(struct app_context *ctx, uint8_t cmd)
> }
>
> switch (cmd) {
> + case DRM_RAS_CMD_SET_ERROR_THRESHOLD:
> case DRM_RAS_CMD_GET_ERROR_THRESHOLD:
> case DRM_RAS_CMD_GET_ERROR_COUNTER:
> ret = nla_put_u32(msg,
> @@ -126,6 +129,16 @@ static int send_command(struct app_context *ctx, uint8_t cmd)
> nlmsg_free(msg);
> return ret;
> }
> +
> + if (cmd == DRM_RAS_CMD_SET_ERROR_THRESHOLD) {
> + ret = nla_put_u32(msg,
> + DRM_RAS_A_ERROR_COUNTER_ATTRS_ERROR_THRESHOLD,
> + ctx->error_threshold);
> + if (ret < 0) {
> + nlmsg_free(msg);
> + return ret;
> + }
> + }
> break;
> default:
> nlmsg_free(msg);
> @@ -238,6 +251,14 @@ static int validate_inputs(struct app_context *ctx, uint8_t cmd)
> return -EINVAL;
> }
>
> + if (cmd == DRM_RAS_CMD_SET_ERROR_THRESHOLD &&
> + (ctx->error_threshold < 1 || ctx->error_threshold > 16)) {
> + igt_warn("Invalid error_threshold (%u) provided. "
> + "error_threshold should be >= 1 and <= 16.\n",
> + ctx->error_threshold);
> + return -EINVAL;
> + }
> +
> return 0;
> }
>
> @@ -280,3 +301,21 @@ int get_error_threshold(struct app_context *ctx)
>
> return 0;
> }
> +
> +int set_error_threshold(struct app_context *ctx)
> +{
> + int ret;
> +
> + ret = validate_inputs(ctx, DRM_RAS_CMD_SET_ERROR_THRESHOLD);
> + if (ret < 0)
> + return ret;
> +
> + ret = send_command(ctx, DRM_RAS_CMD_SET_ERROR_THRESHOLD);
> + if (ret < 0)
> + return ret;
> +
> + igt_debug("Set error threshold: node_id=%u error_id=%u threshold=%u\n",
> + ctx->node_id, ctx->error_id, ctx->error_threshold);
> +
> + return 0;
> +}
> diff --git a/lib/igt_drm_netlink.h b/lib/igt_drm_netlink.h
> index fae9b0e06..c44486ffa 100644
> --- a/lib/igt_drm_netlink.h
> +++ b/lib/igt_drm_netlink.h
> @@ -33,6 +33,7 @@ void cleanup_nl_socket(struct app_context *ctx);
> int init_nl_socket(struct app_context *ctx);
> int get_error_counter(struct app_context *ctx);
> int get_error_threshold(struct app_context *ctx);
> +int set_error_threshold(struct app_context *ctx);
>
> #endif /* IGT_DRM_NETLINK_H */
>
> --
> 2.34.1
>
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 5/8] tests/intel/xe_err_injection: Add GT UC Unicast GAM Walker Command Parity Error Injection
2026-07-29 12:19 [PATCH 0/8] Xe3P GPU Error Injection Test Suite with DRM RAS Netlink Support Ravi Kishore Koppuravuri
` (3 preceding siblings ...)
2026-07-29 12:19 ` [PATCH 4/8] lib/igt_drm_netlink: add set_error_threshold " Ravi Kishore Koppuravuri
@ 2026-07-29 12:19 ` Ravi Kishore Koppuravuri
2026-07-29 12:19 ` [PATCH 6/8] lib/igt_drm_netlink: add event notify subscription and event wait support Ravi Kishore Koppuravuri
` (2 subsequent siblings)
7 siblings, 0 replies; 13+ messages in thread
From: Ravi Kishore Koppuravuri @ 2026-07-29 12:19 UTC (permalink / raw)
To: igt-dev
Cc: riana.tauro, anshuman.gupta, mallesh.koujalagi, raag.jadav,
Ravi Kishore Koppuravuri
MMIO based GT Uncorrectable Unicast GAM Walker command parity error
injection to verify the Xe driver error handling and recovery flows with
the help of DRM Netlink API suite
Signed-off-by: Ravi Kishore Koppuravuri <ravi.kishore.koppuravuri@intel.com>
---
tests/intel/xe_err_injection.c | 313 +++++++++++++++++++++++++++++++++
tests/intel/xe_err_injection.h | 18 ++
tests/meson.build | 1 +
3 files changed, 332 insertions(+)
create mode 100644 tests/intel/xe_err_injection.c
create mode 100644 tests/intel/xe_err_injection.h
diff --git a/tests/intel/xe_err_injection.c b/tests/intel/xe_err_injection.c
new file mode 100644
index 000000000..afbaf0646
--- /dev/null
+++ b/tests/intel/xe_err_injection.c
@@ -0,0 +1,313 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2026 Intel Corporation
+ */
+
+/**
+ * TEST: MMIO based Error Injection
+ * Category: RAS
+ * Mega feature: Telemetry
+ * Sub-category: Driver
+ * Test category: Error Injection
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include "igt.h"
+#include "lib/igt_drm_netlink.h"
+#include "lib/intel_reg.h"
+#include "lib/intel_compute.h"
+
+#include "xe_drm.h"
+#include "xe/xe_ioctl.h"
+#include "xe/xe_mmio.h"
+#include "xe/xe_query.h"
+#include "xe_err_injection.h"
+
+enum {
+ RECOVERY_SUCCESS = 1,
+ RECOVERY_FAILED = 2,
+ RECOVERY_TIMEOUT = 3,
+};
+
+static void run_xe_compute_on_all_engines(int fd, bool state)
+{
+ struct drm_xe_engine_class_instance *hwe;
+
+ if (state == POST_ARMING_INJECTION_WL)
+ igt_info("Running compute-square on all engines post injection\n");
+ else if (state == POST_RECOVERY_WL)
+ igt_info("Running compute-square on all engines post recovery\n");
+
+ xe_for_each_engine(fd, hwe) {
+ if (hwe->engine_class != DRM_XE_ENGINE_CLASS_COMPUTE)
+ continue;
+
+ igt_require_f(xe_run_intel_compute_kernel_on_engine(fd, hwe, NULL,
+ EXECENV_PREF_SYSTEM),
+ "GPU does not support "
+ "compute on engine\n");
+ }
+}
+
+static void write_reg(struct xe_mmio *mmio, uint32_t reg, uint32_t value)
+{
+ xe_mmio_write32(mmio, reg, value);
+}
+
+static void modify_reg_bit(struct xe_mmio *mmio, uint32_t reg_addr,
+ uint32_t bit_mask, bool set)
+{
+ uint32_t regval;
+
+ regval = xe_mmio_read32(mmio, reg_addr);
+ if (set)
+ regval |= bit_mask;
+ else
+ regval &= ~bit_mask;
+
+ xe_mmio_write32(mmio, reg_addr, regval);
+}
+
+static int acquire_forcewake(int fd)
+{
+ int fw_handle;
+
+ fw_handle = igt_debugfs_open(fd, "forcewake_all", O_RDONLY);
+ igt_assert_lte(0, fw_handle);
+ return fw_handle;
+}
+
+static void release_forcewake(int fw_handle)
+{
+ if (fw_handle >= 0)
+ close(fw_handle);
+}
+
+static uint32_t get_counter(uint32_t node_id, uint32_t error_id)
+{
+ struct app_context ctx;
+ int ret;
+ uint32_t error_value = UINT32_MAX;
+
+ ret = init_nl_socket(&ctx);
+ if (ret < 0) {
+ igt_warn("Failed to initialize netlink socket for error command (ret=%d)\n", ret);
+ return error_value;
+ }
+
+ ctx.node_id = node_id;
+ ctx.error_id = error_id;
+
+ ret = get_error_counter(&ctx);
+ if (ret < 0) {
+ igt_warn("get_error_counter failed from error command path (ret=%d)\n", ret);
+ } else {
+ error_value = ctx.error_value;
+ igt_info("get_error_counter: node_id=%u error_id=%u value=%u\n",
+ ctx.node_id, ctx.error_id, ctx.error_value);
+ }
+
+ cleanup_nl_socket(&ctx);
+
+ return error_value;
+}
+
+static int check_dmesg_for_recovery(const char *marker, int elapsed_secs)
+{
+ char *buff = NULL;
+ size_t buff_size = 0;
+ ssize_t line_len;
+ FILE *fp;
+ const char *success = "AER: device recovery successful";
+ const char *failed = "AER: device recovery failed";
+ bool marker_seen = false;
+
+ fp = popen("dmesg", "r");
+ if (!fp) {
+ igt_warn("Unable to open dmesg to check recovery status\n");
+ return -1;
+ }
+
+ while ((line_len = getline(&buff, &buff_size, fp)) != -1) {
+ (void)line_len;
+ if (!marker_seen) {
+ if (strstr(buff, marker))
+ marker_seen = true;
+ continue;
+ }
+
+ if (strstr(buff, success)) {
+ igt_info("Found \"%s\" in dmesg after %d secs\n", success, elapsed_secs);
+ free(buff);
+ pclose(fp);
+ return RECOVERY_SUCCESS;
+ }
+ if (strstr(buff, failed)) {
+ igt_info("Found \"%s\" in dmesg after %d secs\n", failed, elapsed_secs);
+ free(buff);
+ pclose(fp);
+ return RECOVERY_FAILED;
+ }
+ }
+
+ free(buff);
+ pclose(fp);
+ return RECOVERY_TIMEOUT;
+}
+
+static int check_err_recovery(void)
+{
+ time_t start_time = time(NULL);
+ time_t timeout = 5 * 60;
+ int time_interval = 30;
+ time_t elapsed_time;
+ int status;
+ char marker[128];
+
+ snprintf(marker, sizeof(marker),
+ "IGT xe_err_injection recovery marker pid=%d start=%lld",
+ getpid(), (long long)start_time);
+ igt_kmsg(KMSG_INFO "%s\n", marker);
+
+ while (1) {
+ elapsed_time = time(NULL) - start_time;
+ status = check_dmesg_for_recovery(marker, elapsed_time);
+ if (status < 0) {
+ igt_warn("Failed to query dmesg for recovery status\n");
+ return RECOVERY_FAILED;
+ }
+ if (status == RECOVERY_SUCCESS || status == RECOVERY_FAILED)
+ return status;
+
+ if (elapsed_time >= timeout) {
+ igt_warn("Timed out while waiting for error recovery\n");
+ return RECOVERY_TIMEOUT;
+ }
+
+ sleep(time_interval);
+ }
+}
+
+static void print_aer_recovery_status(void)
+{
+ int recovery_ret;
+
+ recovery_ret = check_err_recovery();
+ igt_assert_f(recovery_ret != RECOVERY_TIMEOUT,
+ "AER error recovery timed out\n");
+ igt_assert_f(recovery_ret != RECOVERY_FAILED,
+ "AER device recovery failed\n");
+ if (recovery_ret == RECOVERY_SUCCESS)
+ igt_info("AER device recovery successful\n");
+}
+
+static void log_status(bool val, const char *err_name)
+{
+ if (val)
+ igt_info("Injection status SET: %s\n", err_name);
+ else
+ igt_info("Injection status NOT SET: %s\n", err_name);
+}
+
+static bool gt_uc_wkr_parity_recovered;
+
+/**
+ * SUBTEST: GT-UC-unicast-wkr-cmd-parity-err
+ * Description: GT Uncorrectable Unicast Walker Command parity error injection
+ * Functionality: error injection
+ */
+static void wkr_cmd_parity_err_injection(struct xe_mmio *mmio, int fd)
+{
+ int fw_handle;
+ uint32_t error_counter_before_inj;
+ uint32_t error_counter_after_inj;
+ uint32_t node_id = 1;
+ uint32_t error_id = 1;
+
+ fw_handle = acquire_forcewake(fd);
+
+ error_counter_before_inj = get_counter(node_id, error_id);
+
+ /* Arm the injection sequence. */
+ write_reg(mmio, MC_PKT_CTRL_MGSR_3D_ADDRESS, 0x0);
+ modify_reg_bit(mmio,
+ WKR_FABRIC_ERR_INJ_GAMWALK_3D_ADDRESS,
+ WKR_FABRIC_ERR_INJ_GAMWALK_3D_VALUE,
+ true);
+ modify_reg_bit(mmio,
+ MC_PKT_CTRL_MGSR_3D_ADDRESS,
+ MC_PKT_CTRL_MGSR_3D_VALUE,
+ true);
+ igt_info("Injected GT Uncorrectable Unicast Walker Cmd parity error\n");
+
+ run_xe_compute_on_all_engines(fd, POST_ARMING_INJECTION_WL);
+
+ release_forcewake(fw_handle);
+ print_aer_recovery_status();
+ error_counter_after_inj = get_counter(node_id, error_id);
+
+ igt_assert_f(error_counter_before_inj != UINT32_MAX &&
+ error_counter_after_inj != UINT32_MAX,
+ "Failed to fetch valid error counters: before=%u after=%u\n",
+ error_counter_before_inj, error_counter_after_inj);
+
+ igt_info("error counter: before injection=%u after injection=%u\n",
+ error_counter_before_inj, error_counter_after_inj);
+
+ igt_assert_f(error_counter_after_inj > error_counter_before_inj,
+ "GT Uncorrectable Unicast Walker Cmd parity error injection "
+ "failed: before injection=%u after injection=%u\n",
+ error_counter_before_inj, error_counter_after_inj);
+ igt_info("GT Uncorrectable Unicast Walker Cmd parity error injection successful\n");
+ gt_uc_wkr_parity_recovered = true;
+}
+
+static void inject_error(const char *injection, struct xe_mmio *mmio, int fd)
+{
+ igt_info("Starting Error Injection test: %s\n", injection);
+ if (strcmp(injection, "GT-UC-unicast-wkr-cmd-parity-err") == 0)
+ wkr_cmd_parity_err_injection(mmio, fd);
+ else
+ igt_info("Invalid Error Injection specified\n");
+}
+
+/**
+ * SUBTEST: GT-UC-unicast-wkr-cmd-parity-err-post-recovery-wl
+ * Description: Run a post-recovery Xe workload after parity error injection.
+ * Functionality: workload validation
+ */
+
+int igt_main()
+{
+ int fd;
+ struct xe_mmio mmio;
+
+ igt_fixture() {
+ fd = drm_open_driver(DRIVER_XE);
+ igt_require(igt_debugfs_exists(fd, "forcewake_all", O_RDONLY));
+ xe_mmio_access_init(fd, &mmio);
+ igt_require(xe_mmio_is_initialized(&mmio));
+ }
+
+ igt_describe("Inject GT uncorrectable unicast worker command parity error.");
+ igt_subtest("GT-UC-unicast-wkr-cmd-parity-err")
+ inject_error("GT-UC-unicast-wkr-cmd-parity-err", &mmio, fd);
+
+ igt_describe("Run post-recovery workload after GT parity error injection test.");
+ igt_subtest("GT-UC-unicast-wkr-cmd-parity-err-post-recovery-wl") {
+ igt_require_f(gt_uc_wkr_parity_recovered,
+ "Run GT-UC-unicast-wkr-cmd-parity-err first\n");
+ run_xe_compute_on_all_engines(fd, POST_RECOVERY_WL);
+ }
+
+ igt_fixture() {
+ xe_mmio_access_fini(&mmio);
+ drm_close_driver(fd);
+ }
+}
diff --git a/tests/intel/xe_err_injection.h b/tests/intel/xe_err_injection.h
new file mode 100644
index 000000000..d7efc2fd2
--- /dev/null
+++ b/tests/intel/xe_err_injection.h
@@ -0,0 +1,18 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright © 2026 Intel Corporation
+ */
+
+#ifndef XE_ERR_INJECTION_H
+#define XE_ERR_INJECTION_H
+
+/* GT Uncorrectable unicast worker command parity error injection */
+#define MC_PKT_CTRL_MGSR_3D_ADDRESS 0x00FD4
+#define MC_PKT_CTRL_MGSR_3D_VALUE 0x80000000
+#define WKR_FABRIC_ERR_INJ_GAMWALK_3D_ADDRESS 0xF310
+#define WKR_FABRIC_ERR_INJ_GAMWALK_3D_VALUE 0x1
+
+#define POST_RECOVERY_WL 1
+#define POST_ARMING_INJECTION_WL 0
+
+#endif /* XE_ERR_INJECTION_H */
diff --git a/tests/meson.build b/tests/meson.build
index a62f447df..0f090dcee 100644
--- a/tests/meson.build
+++ b/tests/meson.build
@@ -292,6 +292,7 @@ intel_xe_progs = [
'xe_debugfs',
'xe_dma_buf_sync',
'xe_drm_fdinfo',
+ 'xe_err_injection',
'xe_eu_stall',
'xe_evict',
'xe_evict_ccs',
--
2.34.1
^ permalink raw reply related [flat|nested] 13+ messages in thread* [PATCH 6/8] lib/igt_drm_netlink: add event notify subscription and event wait support
2026-07-29 12:19 [PATCH 0/8] Xe3P GPU Error Injection Test Suite with DRM RAS Netlink Support Ravi Kishore Koppuravuri
` (4 preceding siblings ...)
2026-07-29 12:19 ` [PATCH 5/8] tests/intel/xe_err_injection: Add GT UC Unicast GAM Walker Command Parity Error Injection Ravi Kishore Koppuravuri
@ 2026-07-29 12:19 ` Ravi Kishore Koppuravuri
2026-07-29 12:19 ` [PATCH 7/8] tests/intel/xe_err_injection: Add tests for L2 bank Corr err threshold scenarios Ravi Kishore Koppuravuri
2026-07-29 12:19 ` [PATCH 8/8] tests/intel/xe_err_injection: add CRI GPU requirement check Ravi Kishore Koppuravuri
7 siblings, 0 replies; 13+ messages in thread
From: Ravi Kishore Koppuravuri @ 2026-07-29 12:19 UTC (permalink / raw)
To: igt-dev
Cc: riana.tauro, anshuman.gupta, mallesh.koujalagi, raag.jadav,
Ravi Kishore Koppuravuri
Added event notification support with subscribe for an error-notify event and
wait for the event notification functionalities.
Signed-off-by: Ravi Kishore Koppuravuri <ravi.kishore.koppuravuri@intel.com>
---
lib/igt_drm_netlink.c | 108 ++++++++++++++++++++++++++++++++++++++++++
lib/igt_drm_netlink.h | 6 +++
2 files changed, 114 insertions(+)
diff --git a/lib/igt_drm_netlink.c b/lib/igt_drm_netlink.c
index 4738090af..b72fb343d 100644
--- a/lib/igt_drm_netlink.c
+++ b/lib/igt_drm_netlink.c
@@ -6,6 +6,7 @@
#include <stdbool.h>
#include <stdint.h>
#include <errno.h>
+#include <poll.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -31,6 +32,26 @@ static int ras_command_cb(struct nl_msg *msg, void *arg)
switch (gnlh->cmd) {
case DRM_RAS_CMD_SET_ERROR_THRESHOLD:
break;
+ case DRM_RAS_CMD_ERROR_EVENT: {
+ struct nlattr *attrs[DRM_RAS_A_ERROR_EVENT_ATTRS_MAX + 1];
+
+ ret = genlmsg_parse(nlh, 0, attrs,
+ DRM_RAS_A_ERROR_EVENT_ATTRS_MAX, NULL);
+ if (ret < 0)
+ return NL_SKIP;
+
+ if (!attrs[DRM_RAS_A_ERROR_EVENT_ATTRS_NODE_ID] ||
+ !attrs[DRM_RAS_A_ERROR_EVENT_ATTRS_ERROR_ID] ||
+ !attrs[DRM_RAS_A_ERROR_EVENT_ATTRS_ERROR_VALUE])
+ return NL_SKIP;
+
+ ctx->event_node_id = nla_get_u32(attrs[DRM_RAS_A_ERROR_EVENT_ATTRS_NODE_ID]);
+ ctx->event_error_id = nla_get_u32(attrs[DRM_RAS_A_ERROR_EVENT_ATTRS_ERROR_ID]);
+ ctx->event_error_value =
+ nla_get_u32(attrs[DRM_RAS_A_ERROR_EVENT_ATTRS_ERROR_VALUE]);
+ ctx->event_received = true;
+ break;
+ }
case DRM_RAS_CMD_GET_ERROR_COUNTER: {
struct nlattr *attrs[DRM_RAS_A_ERROR_COUNTER_ATTRS_MAX + 1];
@@ -171,6 +192,10 @@ int init_app_context(struct app_context *ctx)
ctx->error_id = UINT32_MAX;
ctx->error_value = 0;
ctx->error_threshold = 0;
+ ctx->event_node_id = UINT32_MAX;
+ ctx->event_error_id = UINT32_MAX;
+ ctx->event_error_value = 0;
+ ctx->event_received = false;
ctx->family_id = -1;
return 0;
@@ -186,6 +211,10 @@ void cleanup_app_context(struct app_context *ctx)
ctx->error_id = UINT32_MAX;
ctx->error_value = 0;
ctx->error_threshold = 0;
+ ctx->event_node_id = UINT32_MAX;
+ ctx->event_error_id = UINT32_MAX;
+ ctx->event_error_value = 0;
+ ctx->event_received = false;
ctx->family_id = -1;
}
@@ -319,3 +348,82 @@ int set_error_threshold(struct app_context *ctx)
return 0;
}
+
+int subscribe_error_notify(struct app_context *ctx, const char *notify_group_name)
+{
+ int grp_id;
+ int ret;
+
+ if (!ctx || !ctx->sock || ctx->family_id < 0 ||
+ !notify_group_name || notify_group_name[0] == '\0')
+ return -EINVAL;
+
+ grp_id = genl_ctrl_resolve_grp(ctx->sock,
+ DRM_RAS_FAMILY_NAME,
+ notify_group_name);
+ if (grp_id < 0)
+ return grp_id;
+
+ ret = nl_socket_add_membership(ctx->sock, grp_id);
+ if (ret < 0)
+ return ret;
+
+ igt_debug("Subscribed to DRM RAS multicast group '%s' (id=%d).\n",
+ notify_group_name, grp_id);
+
+ return 0;
+}
+
+int wait_for_error_notify_event(struct app_context *ctx, int timeout_ms)
+{
+ struct nl_cb *cb;
+ struct pollfd pfd;
+ int ret;
+
+ if (!ctx || !ctx->sock || ctx->family_id < 0)
+ return -EINVAL;
+
+ if (timeout_ms < -1)
+ return -EINVAL;
+
+ cb = nl_cb_alloc(NL_CB_DEFAULT);
+ if (!cb)
+ return -ENOMEM;
+
+ ret = nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, ras_command_cb, ctx);
+ if (ret < 0) {
+ nl_cb_put(cb);
+ return ret;
+ }
+
+ ctx->event_received = false;
+
+ pfd.fd = nl_socket_get_fd(ctx->sock);
+ pfd.events = POLLIN;
+ pfd.revents = 0;
+
+ ret = poll(&pfd, 1, timeout_ms);
+ if (ret == 0) {
+ nl_cb_put(cb);
+ return -ETIMEDOUT;
+ }
+
+ if (ret < 0) {
+ ret = -errno;
+ nl_cb_put(cb);
+ return ret;
+ }
+
+ ret = nl_recvmsgs(ctx->sock, cb);
+ nl_cb_put(cb);
+ if (ret < 0)
+ return ret;
+
+ if (!ctx->event_received)
+ return -ENOMSG;
+
+ igt_debug("Received error-notify event: node_id=%u error_id=%u value=%u\n",
+ ctx->event_node_id, ctx->event_error_id, ctx->event_error_value);
+
+ return 0;
+}
diff --git a/lib/igt_drm_netlink.h b/lib/igt_drm_netlink.h
index c44486ffa..b04221a23 100644
--- a/lib/igt_drm_netlink.h
+++ b/lib/igt_drm_netlink.h
@@ -24,6 +24,10 @@ struct app_context {
uint32_t error_id;
uint32_t error_value;
uint32_t error_threshold;
+ uint32_t event_node_id;
+ uint32_t event_error_id;
+ uint32_t event_error_value;
+ bool event_received;
int family_id;
};
@@ -34,6 +38,8 @@ int init_nl_socket(struct app_context *ctx);
int get_error_counter(struct app_context *ctx);
int get_error_threshold(struct app_context *ctx);
int set_error_threshold(struct app_context *ctx);
+int subscribe_error_notify(struct app_context *ctx, const char *notify_group_name);
+int wait_for_error_notify_event(struct app_context *ctx, int timeout_ms);
#endif /* IGT_DRM_NETLINK_H */
--
2.34.1
^ permalink raw reply related [flat|nested] 13+ messages in thread* [PATCH 7/8] tests/intel/xe_err_injection: Add tests for L2 bank Corr err threshold scenarios
2026-07-29 12:19 [PATCH 0/8] Xe3P GPU Error Injection Test Suite with DRM RAS Netlink Support Ravi Kishore Koppuravuri
` (5 preceding siblings ...)
2026-07-29 12:19 ` [PATCH 6/8] lib/igt_drm_netlink: add event notify subscription and event wait support Ravi Kishore Koppuravuri
@ 2026-07-29 12:19 ` Ravi Kishore Koppuravuri
2026-07-29 12:19 ` [PATCH 8/8] tests/intel/xe_err_injection: add CRI GPU requirement check Ravi Kishore Koppuravuri
7 siblings, 0 replies; 13+ messages in thread
From: Ravi Kishore Koppuravuri @ 2026-07-29 12:19 UTC (permalink / raw)
To: igt-dev
Cc: riana.tauro, anshuman.gupta, mallesh.koujalagi, raag.jadav,
Ravi Kishore Koppuravuri
Introduced L2 bank correctable error threshold subtests:
- single correctable error
- Correctable error with threshold set to 1
- 16 Correctable error injections with threshold set to 0xF
Add DRM RAS netlink error-notify event subscription to verify
correctable error detection across all the above subtests.
Signed-off-by: Ravi Kishore Koppuravuri <ravi.kishore.koppuravuri@intel.com>
---
tests/intel/xe_err_injection.c | 252 +++++++++++++++++++++++++++++++++
tests/intel/xe_err_injection.h | 10 ++
2 files changed, 262 insertions(+)
diff --git a/tests/intel/xe_err_injection.c b/tests/intel/xe_err_injection.c
index afbaf0646..0303f4a56 100644
--- a/tests/intel/xe_err_injection.c
+++ b/tests/intel/xe_err_injection.c
@@ -35,6 +35,14 @@ enum {
RECOVERY_TIMEOUT = 3,
};
+time_t event_timeout = 10 * 1000; /* 10 seconds */
+
+/* Cleanup helper for injection test functions */
+#define CLEANUP_ON_ERROR(ctx, fw_handle) do { \
+ cleanup_nl_socket(&ctx); \
+ release_forcewake(fw_handle); \
+} while (0)
+
static void run_xe_compute_on_all_engines(int fd, bool state)
{
struct drm_xe_engine_class_instance *hwe;
@@ -268,6 +276,238 @@ static void wkr_cmd_parity_err_injection(struct xe_mmio *mmio, int fd)
gt_uc_wkr_parity_recovered = true;
}
+/* Inject a GT correctable error */
+static void l2_bank_corr_err_injection(struct xe_mmio *mmio, int fd)
+{
+ /* Arm the Injection */
+ write_reg(mmio, L2_BANK_ERR_INJ, L2_BANK_DATA_1BIT_ERR_INJ_CONFIG);
+ igt_info("Armed L2 Bank Correctable Error Injection\n");
+}
+
+/**
+ * SUBTEST: l2-bank-corr-err-threshold-1
+ * Description: Inject single bit error injection in SSA data array when this bit is written
+ * (this bit is a self clearing bit, event will be generated once written) - Correctable Error
+ * Functionality: error injection
+ */
+static void l2_bank_corr_err_injection_with_threshold_1(struct xe_mmio *mmio, int fd)
+{
+ int fw_handle;
+ int ret;
+ uint32_t current_threshold = UINT32_MAX;
+ struct app_context ctx;
+
+ fw_handle = acquire_forcewake(fd);
+
+ ret = init_nl_socket(&ctx);
+ if (ret < 0) {
+ release_forcewake(fw_handle);
+ igt_assert_f(false, "Failed to initialize netlink socket (ret=%d)\n", ret);
+ }
+
+ /* Subscribe to error-notify */
+ ret = subscribe_error_notify(&ctx, DRM_RAS_MCGRP_ERROR_NOTIFY);
+ if (ret < 0) {
+ CLEANUP_ON_ERROR(ctx, fw_handle);
+ igt_assert_f(false, "Failed to subscribe to error-notify (ret=%d)\n", ret);
+ }
+
+ /* get current GT Correctable error threshold */
+ ctx.node_id = 0;
+ ctx.error_id = 1;
+ ret = get_error_threshold(&ctx);
+ if (ret < 0) {
+ CLEANUP_ON_ERROR(ctx, fw_handle);
+ igt_assert_f(false, "Failed to query GT correctable error threshold before injection\n");
+ }
+ current_threshold = ctx.error_threshold;
+ igt_info("Current GT Correctable error threshold: %u\n", current_threshold);
+
+ /* Set GT Correctable error threshold to 1 */
+ ctx.error_threshold = 1;
+ ret = set_error_threshold(&ctx);
+ if (ret < 0) {
+ CLEANUP_ON_ERROR(ctx, fw_handle);
+ igt_assert_f(false, "Failed to set GT correctable error threshold before injection\n");
+ }
+
+ /* Inject a GT correctable error */
+ l2_bank_corr_err_injection(mmio, fd);
+
+ ret = wait_for_error_notify_event(&ctx, event_timeout); /* wait for 10 secs */
+ if (ret == 0 && ctx.event_error_value == 1) {
+ log_status(true, "L2 Bank Correctable Error with threshold 1");
+ } else {
+ log_status(false, "L2 Bank Correctable Error with threshold 1");
+ /* restore threshold before failing */
+ ctx.error_threshold = current_threshold;
+ set_error_threshold(&ctx);
+ CLEANUP_ON_ERROR(ctx, fw_handle);
+ igt_assert_f(false, "Did not receive expected RAS event or error_value after injection\n");
+ }
+
+ /* restore GT Correctable error threshold to original value */
+ ctx.error_threshold = current_threshold;
+ ret = set_error_threshold(&ctx);
+ if (ret < 0) {
+ CLEANUP_ON_ERROR(ctx, fw_handle);
+ igt_assert_f(false, "Failed to restore GT correctable error threshold after injection\n");
+ }
+
+ CLEANUP_ON_ERROR(ctx, fw_handle);
+}
+
+/**
+ * SUBTEST: l2-bank-corr-err-16-times
+ * Description: Inject single bit error injection in SSA data array when this bit is written
+ * (this bit is a self clearing bit, event will be generated once written) - Correctable Error
+ * Functionality: error injection
+ */
+static void l2_bank_corr_err_injection_16_times(struct xe_mmio *mmio, int fd)
+{
+ int fw_handle;
+ uint32_t current_threshold = UINT32_MAX;
+ uint32_t gt_corr_counter_before = 0, gt_corr_counter_current = 0;
+ int ret;
+ struct app_context ctx;
+
+ fw_handle = acquire_forcewake(fd);
+
+ ret = init_nl_socket(&ctx);
+ if (ret < 0) {
+ release_forcewake(fw_handle);
+ igt_assert_f(false, "Failed to initialize netlink socket (ret=%d)\n", ret);
+ }
+
+ ret = subscribe_error_notify(&ctx, DRM_RAS_MCGRP_ERROR_NOTIFY);
+ if (ret < 0) {
+ CLEANUP_ON_ERROR(ctx, fw_handle);
+ igt_assert_f(false, "Failed to subscribe to error-notify (ret=%d)\n", ret);
+ }
+
+ /* Query error counter before injection */
+ ctx.node_id = 0;
+ ctx.error_id = 1;
+ ret = get_error_counter(&ctx);
+ if (ret < 0) {
+ CLEANUP_ON_ERROR(ctx, fw_handle);
+ igt_assert_f(false,
+ "Failed to query GT correctable error counter before injection\n");
+ }
+ gt_corr_counter_before = ctx.error_value;
+
+ /* get current GT Correctable error threshold */
+ ret = get_error_threshold(&ctx);
+ if (ret < 0) {
+ CLEANUP_ON_ERROR(ctx, fw_handle);
+ igt_assert_f(false,
+ "Failed to query GT correctable error threshold before injection\n");
+ }
+ current_threshold = ctx.error_threshold;
+ igt_info("Current GT Correctable error threshold: %u\n", current_threshold);
+
+ for (int i = 0; i < 16; i++) {
+ igt_info("****** Injection iteration: %d ***********\n", i + 1);
+ /* Inject a GT correctable error */
+ l2_bank_corr_err_injection(mmio, fd);
+
+ /* Query error counter after injection */
+ ret = get_error_counter(&ctx);
+ if (ret < 0) {
+ CLEANUP_ON_ERROR(ctx, fw_handle);
+ igt_assert_f(false,
+ "Failed to query GT correctable error counter:iteration %d\n",
+ i + 1);
+ }
+ gt_corr_counter_current = ctx.error_value;
+ igt_info("GT Correctable error counter incremented by : %u "
+ "since before initial injection\n",
+ gt_corr_counter_current - gt_corr_counter_before);
+ }
+
+ /* Confirm whether error counter incremented by 16 after 16 injections */
+ if ((gt_corr_counter_current - gt_corr_counter_before) == 16) {
+ log_status(true, "L2 Bank Correctable Error Injection 16 times");
+ } else {
+ log_status(false, "L2 Bank Correctable Error Injection 16 times");
+ CLEANUP_ON_ERROR(ctx, fw_handle);
+ igt_assert_f(false,
+ "GT Correctable error counter didn't increment "
+ "by 16 after 16 injections\n");
+ }
+
+ ret = wait_for_error_notify_event(&ctx, event_timeout);
+ if (ret == 0 && ctx.event_error_value == 1) {
+ log_status(true, "L2 Bank Correctable Error Injection 16 times");
+ } else {
+ log_status(false, "L2 Bank Correctable Error Injection 16 times");
+ CLEANUP_ON_ERROR(ctx, fw_handle);
+ igt_assert_f(false, "Did not receive expected MSI event or "
+ "error_value after injection\n");
+ }
+
+ CLEANUP_ON_ERROR(ctx, fw_handle);
+}
+
+/**
+ * SUBTEST: l2-bank-single-corr-err
+ * Description: Inject single bit error injection in SSA data array when this bit is written
+ * (this bit is a self clearing bit, event will be generated once written) - Correctable Error
+ * Functionality: error injection
+ */
+static void l2_bank_single_corr_err_injection(struct xe_mmio *mmio, int fd)
+{
+ int fw_handle;
+ int ret;
+ uint32_t gt_corr_counter_before = 0, gt_corr_counter_after = 0;
+ struct app_context ctx;
+
+ fw_handle = acquire_forcewake(fd);
+
+ ret = init_nl_socket(&ctx);
+ if (ret < 0) {
+ release_forcewake(fw_handle);
+ igt_assert_f(false, "Failed to initialize netlink socket (ret=%d)\n", ret);
+ }
+
+ /* Query error counter before injection */
+ ctx.node_id = 0;
+ ctx.error_id = 1;
+ ret = get_error_counter(&ctx);
+ if (ret < 0) {
+ CLEANUP_ON_ERROR(ctx, fw_handle);
+ igt_assert_f(false,
+ "Failed to query GT correctable error counter before injection\n");
+ }
+ gt_corr_counter_before = ctx.error_value;
+ igt_info("GT Correctable error counter before injection: %u\n", gt_corr_counter_before);
+
+ /* Inject a GT correctable error */
+ l2_bank_corr_err_injection(mmio, fd);
+
+ /* Query error counter after injection */
+ ret = get_error_counter(&ctx);
+ if (ret < 0) {
+ CLEANUP_ON_ERROR(ctx, fw_handle);
+ igt_assert_f(false,
+ "Failed to query GT correctable error counter after injection\n");
+ }
+ gt_corr_counter_after = ctx.error_value;
+ igt_info("GT Correctable error counter after injection: %u\n", gt_corr_counter_after);
+
+ if (gt_corr_counter_after > gt_corr_counter_before) {
+ igt_info("GT Correctable error counter incremented by %u after injection\n",
+ gt_corr_counter_after - gt_corr_counter_before);
+ log_status(true, "L2 Bank Correctable Error");
+ } else {
+ CLEANUP_ON_ERROR(ctx, fw_handle);
+ igt_assert_f(false,
+ "L2 Bank (GT) Correctable Error Injection count not incremented\n");
+ }
+
+ CLEANUP_ON_ERROR(ctx, fw_handle);
+}
+
static void inject_error(const char *injection, struct xe_mmio *mmio, int fd)
{
igt_info("Starting Error Injection test: %s\n", injection);
@@ -306,6 +546,18 @@ int igt_main()
run_xe_compute_on_all_engines(fd, POST_RECOVERY_WL);
}
+ igt_describe("Inject GT correctable error and validate error-notify event with threshold set to 1.");
+ igt_subtest("l2-bank-corr-err-threshold-1")
+ l2_bank_corr_err_injection_with_threshold_1(&mmio, fd);
+
+ igt_describe("Inject GT correctable error 16 times and validate counter/event behavior.");
+ igt_subtest("l2-bank-corr-err-16-times")
+ l2_bank_corr_err_injection_16_times(&mmio, fd);
+
+ igt_describe("Inject a single GT correctable error and validate counter increment.");
+ igt_subtest("l2-bank-single-corr-err")
+ l2_bank_single_corr_err_injection(&mmio, fd);
+
igt_fixture() {
xe_mmio_access_fini(&mmio);
drm_close_driver(fd);
diff --git a/tests/intel/xe_err_injection.h b/tests/intel/xe_err_injection.h
index d7efc2fd2..1a9ea2f2e 100644
--- a/tests/intel/xe_err_injection.h
+++ b/tests/intel/xe_err_injection.h
@@ -15,4 +15,14 @@
#define POST_RECOVERY_WL 1
#define POST_ARMING_INJECTION_WL 0
+/* L2 Bank (LBCFLOCKMSGREG) error injection */
+#define L2_BANK_ERR_INJ 0xB1B4
+#define DATA_1BIT_ERR_INJ_REQ (1 << 3)
+#define FUSA_TEST_MODE_ERR_INJ_REQ (1 << 2)
+#define MASK_BIT_FOR_DATA_1BIT_ERR_INJ_REQ (1 << 19)
+#define MASK_BIT_FOR_FUSA_TEST_MODE_ERR_INJ_REQ (1 << 18)
+#define L2_BANK_DATA_1BIT_ERR_INJ_CONFIG \
+ (DATA_1BIT_ERR_INJ_REQ | FUSA_TEST_MODE_ERR_INJ_REQ | \
+ MASK_BIT_FOR_DATA_1BIT_ERR_INJ_REQ | MASK_BIT_FOR_FUSA_TEST_MODE_ERR_INJ_REQ)
+
#endif /* XE_ERR_INJECTION_H */
--
2.34.1
^ permalink raw reply related [flat|nested] 13+ messages in thread* [PATCH 8/8] tests/intel/xe_err_injection: add CRI GPU requirement check
2026-07-29 12:19 [PATCH 0/8] Xe3P GPU Error Injection Test Suite with DRM RAS Netlink Support Ravi Kishore Koppuravuri
` (6 preceding siblings ...)
2026-07-29 12:19 ` [PATCH 7/8] tests/intel/xe_err_injection: Add tests for L2 bank Corr err threshold scenarios Ravi Kishore Koppuravuri
@ 2026-07-29 12:19 ` Ravi Kishore Koppuravuri
2026-08-07 0:06 ` Harish Chegondi
7 siblings, 1 reply; 13+ messages in thread
From: Ravi Kishore Koppuravuri @ 2026-07-29 12:19 UTC (permalink / raw)
To: igt-dev
Cc: riana.tauro, anshuman.gupta, mallesh.koujalagi, raag.jadav,
Ravi Kishore Koppuravuri
Add support to verify the CRI GPU and skips test gracefully
on non-cri platforms
Signed-off-by: Ravi Kishore Koppuravuri <ravi.kishore.koppuravuri@intel.com>
---
tests/intel/xe_err_injection.c | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/tests/intel/xe_err_injection.c b/tests/intel/xe_err_injection.c
index 0303f4a56..4df4589b3 100644
--- a/tests/intel/xe_err_injection.c
+++ b/tests/intel/xe_err_injection.c
@@ -20,6 +20,7 @@
#include "igt.h"
#include "lib/igt_drm_netlink.h"
+#include "lib/intel_chipset.h"
#include "lib/intel_reg.h"
#include "lib/intel_compute.h"
@@ -508,6 +509,14 @@ static void l2_bank_single_corr_err_injection(struct xe_mmio *mmio, int fd)
CLEANUP_ON_ERROR(ctx, fw_handle);
}
+static void igt_require_cri(int fd)
+{
+ uint16_t dev_id = xe_dev_id(fd);
+
+ igt_require_f(IS_CRESCENTISLAND(dev_id),
+ "This test requires CRI GPU, but found device ID 0x%04x\n", dev_id);
+}
+
static void inject_error(const char *injection, struct xe_mmio *mmio, int fd)
{
igt_info("Starting Error Injection test: %s\n", injection);
@@ -531,6 +540,11 @@ int igt_main()
igt_fixture() {
fd = drm_open_driver(DRIVER_XE);
igt_require(igt_debugfs_exists(fd, "forcewake_all", O_RDONLY));
+ igt_require_cri(fd);
+ /*
+ * TODO: Add firmware query for error injection support.
+ * Should check: EOM (End of Manufacturing) status and error injection jumper state.
+ */
xe_mmio_access_init(fd, &mmio);
igt_require(xe_mmio_is_initialized(&mmio));
}
--
2.34.1
^ permalink raw reply related [flat|nested] 13+ messages in thread* Re: [PATCH 8/8] tests/intel/xe_err_injection: add CRI GPU requirement check
2026-07-29 12:19 ` [PATCH 8/8] tests/intel/xe_err_injection: add CRI GPU requirement check Ravi Kishore Koppuravuri
@ 2026-08-07 0:06 ` Harish Chegondi
0 siblings, 0 replies; 13+ messages in thread
From: Harish Chegondi @ 2026-08-07 0:06 UTC (permalink / raw)
To: Ravi Kishore Koppuravuri
Cc: igt-dev, riana.tauro, anshuman.gupta, mallesh.koujalagi,
raag.jadav
On Wed, Jul 29, 2026 at 05:49:59PM +0530, Ravi Kishore Koppuravuri wrote:
> Add support to verify the CRI GPU and skips test gracefully
> on non-cri platforms
>
> Signed-off-by: Ravi Kishore Koppuravuri <ravi.kishore.koppuravuri@intel.com>
> ---
> tests/intel/xe_err_injection.c | 14 ++++++++++++++
> 1 file changed, 14 insertions(+)
>
> diff --git a/tests/intel/xe_err_injection.c b/tests/intel/xe_err_injection.c
> index 0303f4a56..4df4589b3 100644
> --- a/tests/intel/xe_err_injection.c
> +++ b/tests/intel/xe_err_injection.c
> @@ -20,6 +20,7 @@
>
> #include "igt.h"
> #include "lib/igt_drm_netlink.h"
> +#include "lib/intel_chipset.h"
> #include "lib/intel_reg.h"
> #include "lib/intel_compute.h"
>
> @@ -508,6 +509,14 @@ static void l2_bank_single_corr_err_injection(struct xe_mmio *mmio, int fd)
> CLEANUP_ON_ERROR(ctx, fw_handle);
> }
>
> +static void igt_require_cri(int fd)
> +{
> + uint16_t dev_id = xe_dev_id(fd);
> +
> + igt_require_f(IS_CRESCENTISLAND(dev_id),
> + "This test requires CRI GPU, but found device ID 0x%04x\n", dev_id);
> +}
> +
> static void inject_error(const char *injection, struct xe_mmio *mmio, int fd)
> {
> igt_info("Starting Error Injection test: %s\n", injection);
> @@ -531,6 +540,11 @@ int igt_main()
> igt_fixture() {
> fd = drm_open_driver(DRIVER_XE);
> igt_require(igt_debugfs_exists(fd, "forcewake_all", O_RDONLY));
> + igt_require_cri(fd);
Instead of a separate function, you can just use the igt_require_f(IS_CRESCENTISLAND(dev_id),..) here
> + /*
> + * TODO: Add firmware query for error injection support.
> + * Should check: EOM (End of Manufacturing) status and error injection jumper state.
> + */
> xe_mmio_access_init(fd, &mmio);
> igt_require(xe_mmio_is_initialized(&mmio));
> }
> --
> 2.34.1
>
I think this patch should be merged into the patch 5/8:
Add GT UC Unicast GAM Walker Command Parity Error Injection
Since, these error injection tests are run only on CRI as of now, this
patch can be squashed into 5/8
^ permalink raw reply [flat|nested] 13+ messages in thread