* [RFC PATCH 1/7] drm/xe: Add error Signature IDs for RAS logging
2026-07-02 11:14 [RFC PATCH 0/7] Add CPER logging support for CRI Badal Nilawar
@ 2026-07-02 11:14 ` Badal Nilawar
2026-07-02 11:14 ` [RFC PATCH 2/7] drm/xe/xe_ras: Add support to retrieve info queue data for CRI Badal Nilawar
` (5 subsequent siblings)
6 siblings, 0 replies; 11+ messages in thread
From: Badal Nilawar @ 2026-07-02 11:14 UTC (permalink / raw)
To: intel-xe
Cc: anshuman.gupta, rodrigo.vivi, daniele.ceraolospurio, raag.jadav,
riana.tauro, mallesh.koujalagi, aravind.iddamsetty
From: Mallesh Koujalagi <mallesh.koujalagi@intel.com>
Every GPU fault needs a stable numeric label so monitoring tools can
identify what went wrong without parsing log text. Add xe_sig_ids.h
which defines those labels, called SIG_IDs.
Signed-off-by: Mallesh Koujalagi <mallesh.koujalagi@intel.com>
---
drivers/gpu/drm/xe/xe_sig_ids.h | 29 +++++++++++++++++++++++++++++
1 file changed, 29 insertions(+)
create mode 100644 drivers/gpu/drm/xe/xe_sig_ids.h
diff --git a/drivers/gpu/drm/xe/xe_sig_ids.h b/drivers/gpu/drm/xe/xe_sig_ids.h
new file mode 100644
index 000000000000..7badd0d7ad72
--- /dev/null
+++ b/drivers/gpu/drm/xe/xe_sig_ids.h
@@ -0,0 +1,29 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright © 2026 Intel Corporation
+ */
+
+#ifndef _XE_SIG_IDS_H_
+#define _XE_SIG_IDS_H_
+
+/*
+ * Driver SIG_IDs
+ */
+#define XE_SIG_PROBE 1 /* FATAL: probe failed */
+#define XE_SIG_WEDGED 2 /* FATAL: device wedged */
+#define XE_SIG_SURVIVABILITY 3 /* FATAL: survivability mode */
+#define XE_SIG_FW 4 /* RECOVERABLE: GuC/HuC/UC/GSC/CSC/PCODE */
+#define XE_SIG_GT_TDR 5 /* RECOVERABLE: engine hang / reset */
+#define XE_SIG_MEM_FAULT 6 /* RECOVERABLE: VM bind, page fault, GTT */
+#define XE_SIG_IO_BUS 7 /* RECOVERABLE: runtime PCIe/IOMMU/MMIO */
+
+/*
+ * HW SIG_IDs
+ */
+#define XE_SIG_HW_DEVICE_MEMORY 8 /* Device memory errors (e.g. ECC) */
+#define XE_SIG_HW_CORE_COMPUTE 9 /* Compute/shader core errors */
+#define XE_SIG_HW_PCIE 10 /* PCIe interface errors */
+#define XE_SIG_HW_FABRIC 11 /* On-package fabric errors */
+#define XE_SIG_HW_SOC_INTERNAL 12 /* SoC-internal errors */
+
+#endif /* _XE_SIG_IDS_H_ */
--
2.54.0
^ permalink raw reply related [flat|nested] 11+ messages in thread* [RFC PATCH 2/7] drm/xe/xe_ras: Add support to retrieve info queue data for CRI
2026-07-02 11:14 [RFC PATCH 0/7] Add CPER logging support for CRI Badal Nilawar
2026-07-02 11:14 ` [RFC PATCH 1/7] drm/xe: Add error Signature IDs for RAS logging Badal Nilawar
@ 2026-07-02 11:14 ` Badal Nilawar
2026-07-07 12:29 ` Mallesh, Koujalagi
2026-07-02 11:14 ` [RFC PATCH 3/7] drm/xe/xe_ras: Refactor get_counter() to return response structure Badal Nilawar
` (4 subsequent siblings)
6 siblings, 1 reply; 11+ messages in thread
From: Badal Nilawar @ 2026-07-02 11:14 UTC (permalink / raw)
To: intel-xe
Cc: anshuman.gupta, rodrigo.vivi, daniele.ceraolospurio, raag.jadav,
riana.tauro, mallesh.koujalagi, aravind.iddamsetty
Add support to retrieve info queue data. It can be retrieved when
has_info_queue=1 and RAS_INFO_QUEUE_FLAG_MORE_DATA is set in
response of XE_SYSCTRL_CMD_GET_COUNTER.
Signed-off-by: Badal Nilawar <badal.nilawar@intel.com>
Assisted-by: Copilot:claude-sonnet-4.6
---
drivers/gpu/drm/xe/xe_ras.c | 34 ++++++
drivers/gpu/drm/xe/xe_ras_types.h | 112 +++++++++++++++++-
drivers/gpu/drm/xe/xe_sysctrl_mailbox_types.h | 2 +
3 files changed, 147 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/xe/xe_ras.c b/drivers/gpu/drm/xe/xe_ras.c
index 44f4e1a3455b..85b0202467f6 100644
--- a/drivers/gpu/drm/xe/xe_ras.c
+++ b/drivers/gpu/drm/xe/xe_ras.c
@@ -270,6 +270,40 @@ int xe_ras_clear_counter(struct xe_device *xe, u8 severity, u8 component)
return 0;
}
+static int get_info_queue_data(struct xe_device *xe,
+ const struct xe_ras_get_info_queue_data_request *req,
+ struct xe_ras_get_info_queue_data_response *out)
+{
+ struct xe_ras_get_info_queue_data_response response = {0};
+ struct xe_sysctrl_mailbox_command command = {0};
+ size_t rlen;
+ int ret;
+
+ xe_sysctrl_create_command(&command, XE_SYSCTRL_GROUP_GFSP,
+ XE_SYSCTRL_CMD_GET_INFO_QUEUE_DATA,
+ (void *)req, sizeof(*req), &response, sizeof(response));
+
+ ret = xe_sysctrl_send_command(&xe->sc, &command, &rlen);
+ if (ret) {
+ xe_err(xe, "sysctrl: failed to get info queue data %d\n", ret);
+ return ret;
+ }
+
+ if (rlen != sizeof(response)) {
+ xe_err(xe, "sysctrl: unexpected get info queue data response length %zu (expected %zu)\n",
+ rlen, sizeof(response));
+ return -EIO;
+ }
+
+ xe_dbg(xe, "[RAS]: info queue data: status=%u chunk_size=%u flags=0x%x\n",
+ response.operation_status,
+ response.queue_response.queue_header.chunk_size,
+ response.queue_response.queue_header.flags);
+
+ *out = response;
+ return 0;
+}
+
/**
* xe_ras_init - Initialize Xe RAS
* @xe: xe device instance
diff --git a/drivers/gpu/drm/xe/xe_ras_types.h b/drivers/gpu/drm/xe/xe_ras_types.h
index 6688e11f57a8..fc496888b3f8 100644
--- a/drivers/gpu/drm/xe/xe_ras_types.h
+++ b/drivers/gpu/drm/xe/xe_ras_types.h
@@ -9,6 +9,12 @@
#include <linux/types.h>
#define XE_RAS_NUM_COUNTERS 16
+#define XE_RAS_INFO_QUEUE_MAX_CHUNK_SIZE 200
+#define XE_RAS_INFO_QUEUE_MAX_TOTAL_SIZE 5120
+#define XE_RAS_INFO_QUEUE_FLAG_AVAILABLE 0x01
+#define XE_RAS_INFO_QUEUE_FLAG_MORE_DATA 0x02
+#define XE_RAS_INFO_QUEUE_FLAG_OVERFLOW 0x04
+#define XE_RAS_INFO_QUEUE_FLAG_COMPRESSED 0x08
/**
* struct xe_ras_error_common - Error fields that are common across all products
@@ -71,7 +77,64 @@ struct xe_ras_threshold_crossed {
} __packed;
/**
- * struct xe_ras_get_counter_request - Request structure for get counter
+ * struct xe_ras_info_queue_header - Metadata for large info queue data transfers
+ *
+ * Provides chunk metadata for commands that support extended info queue
+ * functionality. Used when the total data exceeds a single mailbox response.
+ */
+struct xe_ras_info_queue_header {
+ /** @total_size: Total size of the complete info queue data in bytes */
+ u32 total_size;
+ /** @chunk_offset: Offset of this chunk within the total data in bytes */
+ u32 chunk_offset;
+ /** @chunk_size: Size of the data in this chunk in bytes */
+ u32 chunk_size;
+ /** @sequence_number: Sequence number for this chunk, starts at 0 */
+ u32 sequence_number;
+ /** @flags: Info queue control flags (RAS_INFO_QUEUE_FLAG_*) */
+ u32 flags:8;
+ /** @compression_type: Compression algorithm used; 0 = none */
+ u32 compression_type:4;
+ /** @num_headers: Number of detailed counter headers at start of queue_data */
+ u32 num_headers:5;
+ /** @reserved: Reserved for future use */
+ u32 reserved:15;
+ /** @checksum: CRC32 checksum of this chunk data */
+ u32 checksum;
+} __packed;
+
+/**
+ * struct xe_ras_info_queue_request - Request for a specific chunk of info queue data
+ *
+ * Allows the driver to request continuation of large info queue transfers
+ * by specifying an offset and size within the full data set.
+ */
+struct xe_ras_info_queue_request {
+ /** @requested_offset: Byte offset of the requested data chunk */
+ u32 requested_offset;
+ /** @requested_size: Maximum size of the requested chunk in bytes */
+ u32 requested_size;
+ /** @session_id: Session ID to correlate multi-chunk transfers */
+ struct xe_ras_error_class session_id;
+ /** @reserved: Reserved for future use */
+ u32 reserved;
+} __packed;
+
+/**
+ * struct xe_ras_info_queue_response - Generic response for commands with info queues
+ *
+ * Standard response format for any command that returns an info queue
+ * payload. May be embedded in a command-specific response structure.
+ */
+struct xe_ras_info_queue_response {
+ /** @queue_header: Info queue metadata for this chunk */
+ struct xe_ras_info_queue_header queue_header;
+ /** @queue_data: Info queue data for this chunk */
+ u8 queue_data[XE_RAS_INFO_QUEUE_MAX_CHUNK_SIZE];
+} __packed;
+
+/**
+ * struct xe_ras_get_counter_request - Request for get error counter
*/
struct xe_ras_get_counter_request {
/** @counter: Error counter to be queried */
@@ -121,4 +184,51 @@ struct xe_ras_clear_counter_response {
/** @reserved1: Reserved for future use */
u32 reserved1[3];
} __packed;
+
+/**
+ * struct xe_ras_info_queue_dynamic_counter_hdr - Aggregate counter header entry
+ *
+ * When a session requests aggregate counter data, one header per matching
+ * dynamic counter class is prepended to the queue data. The @counter field
+ * indicates how many subsequent error log entries belong to this class.
+ */
+struct xe_ras_info_queue_dynamic_counter_hdr {
+ /** @error_class: Error class associated with this counter group */
+ struct xe_ras_error_class error_class;
+ /** @counter: Number of error log entries that follow for this class */
+ u32 counter;
+} __packed;
+
+/**
+ * struct xe_ras_error_log - Single error log entry following dynamic counter headers
+ */
+struct xe_ras_error_log {
+ /** @timestamp: Timestamp when the error was recorded */
+ u64 timestamp;
+ /** @error_details: Error-specific details */
+ u32 error_details[16];
+} __packed;
+
+/**
+ * struct xe_ras_get_info_queue_data_request - Request for RAS_CMD_GET_INFO_QUEUE_DATA
+ */
+struct xe_ras_get_info_queue_data_request {
+ /** @queue_request: Info queue request parameters */
+ struct xe_ras_info_queue_request queue_request;
+ /** @source_command: Original command that generated the info queue */
+ u32 source_command;
+ /** @source_context: Context from original command, if applicable */
+ struct xe_ras_error_class source_context;
+} __packed;
+
+/**
+ * struct xe_ras_get_info_queue_data_response - Response for RAS_CMD_GET_INFO_QUEUE_DATA
+ */
+struct xe_ras_get_info_queue_data_response {
+ /** @operation_status: Status of the retrieval operation */
+ u32 operation_status;
+ /** @queue_response: Info queue data chunk */
+ struct xe_ras_info_queue_response queue_response;
+} __packed;
+
#endif
diff --git a/drivers/gpu/drm/xe/xe_sysctrl_mailbox_types.h b/drivers/gpu/drm/xe/xe_sysctrl_mailbox_types.h
index 6e3753554510..538d93352655 100644
--- a/drivers/gpu/drm/xe/xe_sysctrl_mailbox_types.h
+++ b/drivers/gpu/drm/xe/xe_sysctrl_mailbox_types.h
@@ -25,11 +25,13 @@ enum xe_sysctrl_group {
* @XE_SYSCTRL_CMD_GET_COUNTER: Get error counter value
* @XE_SYSCTRL_CMD_CLEAR_COUNTER: Clear error counter value
* @XE_SYSCTRL_CMD_GET_PENDING_EVENT: Retrieve pending event
+ * @XE_SYSCTRL_CMD_GET_INFO_QUEUE_DATA: Retrieve a chunk of info queue data
*/
enum xe_sysctrl_gfsp_cmd {
XE_SYSCTRL_CMD_GET_COUNTER = 0x03,
XE_SYSCTRL_CMD_CLEAR_COUNTER = 0x04,
XE_SYSCTRL_CMD_GET_PENDING_EVENT = 0x07,
+ XE_SYSCTRL_CMD_GET_INFO_QUEUE_DATA = 0x0D,
};
/**
--
2.54.0
^ permalink raw reply related [flat|nested] 11+ messages in thread* Re: [RFC PATCH 2/7] drm/xe/xe_ras: Add support to retrieve info queue data for CRI
2026-07-02 11:14 ` [RFC PATCH 2/7] drm/xe/xe_ras: Add support to retrieve info queue data for CRI Badal Nilawar
@ 2026-07-07 12:29 ` Mallesh, Koujalagi
0 siblings, 0 replies; 11+ messages in thread
From: Mallesh, Koujalagi @ 2026-07-07 12:29 UTC (permalink / raw)
To: Badal Nilawar, intel-xe
Cc: anshuman.gupta, rodrigo.vivi, daniele.ceraolospurio, raag.jadav,
riana.tauro, aravind.iddamsetty
[-- Attachment #1: Type: text/plain, Size: 8580 bytes --]
On 02-07-2026 04:44 pm, Badal Nilawar wrote:
> Add support to retrieve info queue data. It can be retrieved when
> has_info_queue=1 and RAS_INFO_QUEUE_FLAG_MORE_DATA is set in
> response of XE_SYSCTRL_CMD_GET_COUNTER.
>
nit: Please change commit message, we haven't checked has_info_queue=1
>
> Signed-off-by: Badal Nilawar<badal.nilawar@intel.com>
> Assisted-by: Copilot:claude-sonnet-4.6
> ---
> drivers/gpu/drm/xe/xe_ras.c | 34 ++++++
> drivers/gpu/drm/xe/xe_ras_types.h | 112 +++++++++++++++++-
> drivers/gpu/drm/xe/xe_sysctrl_mailbox_types.h | 2 +
> 3 files changed, 147 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/xe/xe_ras.c b/drivers/gpu/drm/xe/xe_ras.c
> index 44f4e1a3455b..85b0202467f6 100644
> --- a/drivers/gpu/drm/xe/xe_ras.c
> +++ b/drivers/gpu/drm/xe/xe_ras.c
> @@ -270,6 +270,40 @@ int xe_ras_clear_counter(struct xe_device *xe, u8 severity, u8 component)
> return 0;
> }
>
> +static int get_info_queue_data(struct xe_device *xe,
> + const struct xe_ras_get_info_queue_data_request *req,
> + struct xe_ras_get_info_queue_data_response *out)
> +{
Why we need info queue data? When we are going to use info queue data?
> + struct xe_ras_get_info_queue_data_response response = {0};
> + struct xe_sysctrl_mailbox_command command = {0};
> + size_t rlen;
> + int ret;
> +
> + xe_sysctrl_create_command(&command, XE_SYSCTRL_GROUP_GFSP,
> + XE_SYSCTRL_CMD_GET_INFO_QUEUE_DATA,
> + (void *)req, sizeof(*req), &response, sizeof(response));
> +
> + ret = xe_sysctrl_send_command(&xe->sc, &command, &rlen);
> + if (ret) {
> + xe_err(xe, "sysctrl: failed to get info queue data %d\n", ret);
> + return ret;
> + }
> +
> + if (rlen != sizeof(response)) {
> + xe_err(xe, "sysctrl: unexpected get info queue data response length %zu (expected %zu)\n",
> + rlen, sizeof(response));
> + return -EIO;
> + }
> +
> + xe_dbg(xe, "[RAS]: info queue data: status=%u chunk_size=%u flags=0x%x\n",
> + response.operation_status,
> + response.queue_response.queue_header.chunk_size,
> + response.queue_response.queue_header.flags);
> +
What happen when system control send corrupt data?
> + *out = response;
> + return 0;
> +}
> +
> /**
> * xe_ras_init - Initialize Xe RAS
> * @xe: xe device instance
> diff --git a/drivers/gpu/drm/xe/xe_ras_types.h b/drivers/gpu/drm/xe/xe_ras_types.h
> index 6688e11f57a8..fc496888b3f8 100644
> --- a/drivers/gpu/drm/xe/xe_ras_types.h
> +++ b/drivers/gpu/drm/xe/xe_ras_types.h
> @@ -9,6 +9,12 @@
> #include <linux/types.h>
>
> #define XE_RAS_NUM_COUNTERS 16
> +#define XE_RAS_INFO_QUEUE_MAX_CHUNK_SIZE 200
> +#define XE_RAS_INFO_QUEUE_MAX_TOTAL_SIZE 5120
> +#define XE_RAS_INFO_QUEUE_FLAG_AVAILABLE 0x01
> +#define XE_RAS_INFO_QUEUE_FLAG_MORE_DATA 0x02
> +#define XE_RAS_INFO_QUEUE_FLAG_OVERFLOW 0x04
> +#define XE_RAS_INFO_QUEUE_FLAG_COMPRESSED 0x08
>
What is use of XE_RAS_INFO_QUEUE_FLAG_COMPRESSED? When we are using it?
Thanks,
-/Mallesh
> /**
> * struct xe_ras_error_common - Error fields that are common across all products
> @@ -71,7 +77,64 @@ struct xe_ras_threshold_crossed {
> } __packed;
>
> /**
> - * struct xe_ras_get_counter_request - Request structure for get counter
> + * struct xe_ras_info_queue_header - Metadata for large info queue data transfers
> + *
> + * Provides chunk metadata for commands that support extended info queue
> + * functionality. Used when the total data exceeds a single mailbox response.
> + */
> +struct xe_ras_info_queue_header {
> + /** @total_size: Total size of the complete info queue data in bytes */
> + u32 total_size;
> + /** @chunk_offset: Offset of this chunk within the total data in bytes */
> + u32 chunk_offset;
> + /** @chunk_size: Size of the data in this chunk in bytes */
> + u32 chunk_size;
> + /** @sequence_number: Sequence number for this chunk, starts at 0 */
> + u32 sequence_number;
> + /** @flags: Info queue control flags (RAS_INFO_QUEUE_FLAG_*) */
> + u32 flags:8;
> + /** @compression_type: Compression algorithm used; 0 = none */
> + u32 compression_type:4;
> + /** @num_headers: Number of detailed counter headers at start of queue_data */
> + u32 num_headers:5;
> + /** @reserved: Reserved for future use */
> + u32 reserved:15;
> + /** @checksum: CRC32 checksum of this chunk data */
> + u32 checksum;
> +} __packed;
> +
> +/**
> + * struct xe_ras_info_queue_request - Request for a specific chunk of info queue data
> + *
> + * Allows the driver to request continuation of large info queue transfers
> + * by specifying an offset and size within the full data set.
> + */
> +struct xe_ras_info_queue_request {
> + /** @requested_offset: Byte offset of the requested data chunk */
> + u32 requested_offset;
> + /** @requested_size: Maximum size of the requested chunk in bytes */
> + u32 requested_size;
> + /** @session_id: Session ID to correlate multi-chunk transfers */
> + struct xe_ras_error_class session_id;
> + /** @reserved: Reserved for future use */
> + u32 reserved;
> +} __packed;
> +
> +/**
> + * struct xe_ras_info_queue_response - Generic response for commands with info queues
> + *
> + * Standard response format for any command that returns an info queue
> + * payload. May be embedded in a command-specific response structure.
> + */
> +struct xe_ras_info_queue_response {
> + /** @queue_header: Info queue metadata for this chunk */
> + struct xe_ras_info_queue_header queue_header;
> + /** @queue_data: Info queue data for this chunk */
> + u8 queue_data[XE_RAS_INFO_QUEUE_MAX_CHUNK_SIZE];
> +} __packed;
> +
> +/**
> + * struct xe_ras_get_counter_request - Request for get error counter
> */
> struct xe_ras_get_counter_request {
> /** @counter: Error counter to be queried */
> @@ -121,4 +184,51 @@ struct xe_ras_clear_counter_response {
> /** @reserved1: Reserved for future use */
> u32 reserved1[3];
> } __packed;
> +
> +/**
> + * struct xe_ras_info_queue_dynamic_counter_hdr - Aggregate counter header entry
> + *
> + * When a session requests aggregate counter data, one header per matching
> + * dynamic counter class is prepended to the queue data. The @counter field
> + * indicates how many subsequent error log entries belong to this class.
> + */
> +struct xe_ras_info_queue_dynamic_counter_hdr {
> + /** @error_class: Error class associated with this counter group */
> + struct xe_ras_error_class error_class;
> + /** @counter: Number of error log entries that follow for this class */
> + u32 counter;
> +} __packed;
> +
> +/**
> + * struct xe_ras_error_log - Single error log entry following dynamic counter headers
> + */
> +struct xe_ras_error_log {
> + /** @timestamp: Timestamp when the error was recorded */
> + u64 timestamp;
> + /** @error_details: Error-specific details */
> + u32 error_details[16];
> +} __packed;
> +
> +/**
> + * struct xe_ras_get_info_queue_data_request - Request for RAS_CMD_GET_INFO_QUEUE_DATA
> + */
> +struct xe_ras_get_info_queue_data_request {
> + /** @queue_request: Info queue request parameters */
> + struct xe_ras_info_queue_request queue_request;
> + /** @source_command: Original command that generated the info queue */
> + u32 source_command;
> + /** @source_context: Context from original command, if applicable */
> + struct xe_ras_error_class source_context;
> +} __packed;
> +
> +/**
> + * struct xe_ras_get_info_queue_data_response - Response for RAS_CMD_GET_INFO_QUEUE_DATA
> + */
> +struct xe_ras_get_info_queue_data_response {
> + /** @operation_status: Status of the retrieval operation */
> + u32 operation_status;
> + /** @queue_response: Info queue data chunk */
> + struct xe_ras_info_queue_response queue_response;
> +} __packed;
> +
> #endif
> diff --git a/drivers/gpu/drm/xe/xe_sysctrl_mailbox_types.h b/drivers/gpu/drm/xe/xe_sysctrl_mailbox_types.h
> index 6e3753554510..538d93352655 100644
> --- a/drivers/gpu/drm/xe/xe_sysctrl_mailbox_types.h
> +++ b/drivers/gpu/drm/xe/xe_sysctrl_mailbox_types.h
> @@ -25,11 +25,13 @@ enum xe_sysctrl_group {
> * @XE_SYSCTRL_CMD_GET_COUNTER: Get error counter value
> * @XE_SYSCTRL_CMD_CLEAR_COUNTER: Clear error counter value
> * @XE_SYSCTRL_CMD_GET_PENDING_EVENT: Retrieve pending event
> + * @XE_SYSCTRL_CMD_GET_INFO_QUEUE_DATA: Retrieve a chunk of info queue data
> */
> enum xe_sysctrl_gfsp_cmd {
> XE_SYSCTRL_CMD_GET_COUNTER = 0x03,
> XE_SYSCTRL_CMD_CLEAR_COUNTER = 0x04,
> XE_SYSCTRL_CMD_GET_PENDING_EVENT = 0x07,
> + XE_SYSCTRL_CMD_GET_INFO_QUEUE_DATA = 0x0D,
> };
>
> /**
[-- Attachment #2: Type: text/html, Size: 9404 bytes --]
^ permalink raw reply [flat|nested] 11+ messages in thread
* [RFC PATCH 3/7] drm/xe/xe_ras: Refactor get_counter() to return response structure
2026-07-02 11:14 [RFC PATCH 0/7] Add CPER logging support for CRI Badal Nilawar
2026-07-02 11:14 ` [RFC PATCH 1/7] drm/xe: Add error Signature IDs for RAS logging Badal Nilawar
2026-07-02 11:14 ` [RFC PATCH 2/7] drm/xe/xe_ras: Add support to retrieve info queue data for CRI Badal Nilawar
@ 2026-07-02 11:14 ` Badal Nilawar
2026-07-03 7:41 ` Tauro, Riana
2026-07-07 12:53 ` Mallesh, Koujalagi
2026-07-02 11:14 ` [RFC PATCH 4/7] drm/xe/cper: Add CPER structures and trace event Badal Nilawar
` (3 subsequent siblings)
6 siblings, 2 replies; 11+ messages in thread
From: Badal Nilawar @ 2026-07-02 11:14 UTC (permalink / raw)
To: intel-xe
Cc: anshuman.gupta, rodrigo.vivi, daniele.ceraolospurio, raag.jadav,
riana.tauro, mallesh.koujalagi, aravind.iddamsetty
Return the complete response structure from get_counter() instead of
only the counter value. This allows callers to access additional
response fields, such as has_info_queue for CPER record building.
Signed-off-by: Badal Nilawar <badal.nilawar@intel.com>
Assisted-by: Copilot:claude-sonnet-4.6
---
drivers/gpu/drm/xe/xe_ras.c | 23 +++++++++++++++--------
drivers/gpu/drm/xe/xe_ras_types.h | 10 ++++++++--
2 files changed, 23 insertions(+), 10 deletions(-)
diff --git a/drivers/gpu/drm/xe/xe_ras.c b/drivers/gpu/drm/xe/xe_ras.c
index 85b0202467f6..e594d4d3a23f 100644
--- a/drivers/gpu/drm/xe/xe_ras.c
+++ b/drivers/gpu/drm/xe/xe_ras.c
@@ -157,12 +157,12 @@ void xe_ras_counter_threshold_crossed(struct xe_device *xe,
}
}
-static int get_counter(struct xe_device *xe, struct xe_ras_error_class *counter, u32 *value)
+static int get_counter(struct xe_device *xe, const struct xe_ras_error_class *counter,
+ struct xe_ras_get_counter_response *out)
{
struct xe_ras_get_counter_response response = {0};
struct xe_ras_get_counter_request request = {0};
struct xe_sysctrl_mailbox_command command = {0};
- struct xe_ras_error_common *common;
size_t rlen;
int ret;
@@ -183,12 +183,11 @@ static int get_counter(struct xe_device *xe, struct xe_ras_error_class *counter,
return -EIO;
}
- common = &response.counter.common;
- *value = response.value;
-
- xe_dbg(xe, "[RAS]: get counter %u for %s %s\n", *value, comp_to_str(common->component),
- sev_to_str(common->severity));
+ xe_dbg(xe, "[RAS]: get counter value %u for %s %s\n", response.value,
+ comp_to_str(response.counter.common.component),
+ sev_to_str(response.counter.common.severity));
+ *out = response;
return 0;
}
@@ -207,12 +206,20 @@ static int get_counter(struct xe_device *xe, struct xe_ras_error_class *counter,
int xe_ras_get_counter(struct xe_device *xe, u8 severity, u8 component, u32 *value)
{
struct xe_ras_error_class counter = {0};
+ struct xe_ras_get_counter_response response;
+ int ret;
counter.common.severity = drm_to_xe_ras_severity(severity);
counter.common.component = drm_to_xe_ras_component(component);
guard(xe_pm_runtime)(xe);
- return get_counter(xe, &counter, value);
+
+ ret = get_counter(xe, &counter, &response);
+ if (ret)
+ return ret;
+
+ *value = response.counter_value;
+ return 0;
}
/**
diff --git a/drivers/gpu/drm/xe/xe_ras_types.h b/drivers/gpu/drm/xe/xe_ras_types.h
index fc496888b3f8..befdaf297103 100644
--- a/drivers/gpu/drm/xe/xe_ras_types.h
+++ b/drivers/gpu/drm/xe/xe_ras_types.h
@@ -155,8 +155,14 @@ struct xe_ras_get_counter_response {
u64 timestamp;
/** @threshold: Threshold value for the counter */
u32 threshold;
- /** @reserved: Reserved */
- u32 reserved[57];
+ /** @reserved: Reserved for future use */
+ u32 reserved:9;
+ /** @has_info_queue: Set if info queue is available */
+ u32 has_info_queue:1;
+ /** @reserved1: Reserved for future use */
+ u32 reserved1:22;
+ /** @info_queue: Initial info queue data (first chunk) if available */
+ struct xe_ras_info_queue_response info_queue;
} __packed;
/**
--
2.54.0
^ permalink raw reply related [flat|nested] 11+ messages in thread* Re: [RFC PATCH 3/7] drm/xe/xe_ras: Refactor get_counter() to return response structure
2026-07-02 11:14 ` [RFC PATCH 3/7] drm/xe/xe_ras: Refactor get_counter() to return response structure Badal Nilawar
@ 2026-07-03 7:41 ` Tauro, Riana
2026-07-07 12:53 ` Mallesh, Koujalagi
1 sibling, 0 replies; 11+ messages in thread
From: Tauro, Riana @ 2026-07-03 7:41 UTC (permalink / raw)
To: Badal Nilawar, intel-xe
Cc: anshuman.gupta, rodrigo.vivi, daniele.ceraolospurio, raag.jadav,
mallesh.koujalagi, aravind.iddamsetty
On 02-07-2026 16:44, Badal Nilawar wrote:
> Return the complete response structure from get_counter() instead of
> only the counter value. This allows callers to access additional
> response fields, such as has_info_queue for CPER record building.
>
> Signed-off-by: Badal Nilawar <badal.nilawar@intel.com>
> Assisted-by: Copilot:claude-sonnet-4.6
> ---
> drivers/gpu/drm/xe/xe_ras.c | 23 +++++++++++++++--------
> drivers/gpu/drm/xe/xe_ras_types.h | 10 ++++++++--
> 2 files changed, 23 insertions(+), 10 deletions(-)
>
> diff --git a/drivers/gpu/drm/xe/xe_ras.c b/drivers/gpu/drm/xe/xe_ras.c
> index 85b0202467f6..e594d4d3a23f 100644
> --- a/drivers/gpu/drm/xe/xe_ras.c
> +++ b/drivers/gpu/drm/xe/xe_ras.c
> @@ -157,12 +157,12 @@ void xe_ras_counter_threshold_crossed(struct xe_device *xe,
> }
> }
>
> -static int get_counter(struct xe_device *xe, struct xe_ras_error_class *counter, u32 *value)
> +static int get_counter(struct xe_device *xe, const struct xe_ras_error_class *counter,
> + struct xe_ras_get_counter_response *out)
> {
> struct xe_ras_get_counter_response response = {0};
> struct xe_ras_get_counter_request request = {0};
> struct xe_sysctrl_mailbox_command command = {0};
> - struct xe_ras_error_common *common;
> size_t rlen;
> int ret;
>
> @@ -183,12 +183,11 @@ static int get_counter(struct xe_device *xe, struct xe_ras_error_class *counter,
> return -EIO;
> }
>
> - common = &response.counter.common;
> - *value = response.value;
> -
> - xe_dbg(xe, "[RAS]: get counter %u for %s %s\n", *value, comp_to_str(common->component),
> - sev_to_str(common->severity));
> + xe_dbg(xe, "[RAS]: get counter value %u for %s %s\n", response.value,
> + comp_to_str(response.counter.common.component),
> + sev_to_str(response.counter.common.severity));
Why the unnecessary change?
>
> + *out = response;
> return 0;
> }
>
> @@ -207,12 +206,20 @@ static int get_counter(struct xe_device *xe, struct xe_ras_error_class *counter,
> int xe_ras_get_counter(struct xe_device *xe, u8 severity, u8 component, u32 *value)
> {
> struct xe_ras_error_class counter = {0};
> + struct xe_ras_get_counter_response response;
> + int ret;
>
> counter.common.severity = drm_to_xe_ras_severity(severity);
> counter.common.component = drm_to_xe_ras_component(component);
>
> guard(xe_pm_runtime)(xe);
> - return get_counter(xe, &counter, value);
> +
> + ret = get_counter(xe, &counter, &response);
> + if (ret)
> + return ret;
> +
> + *value = response.counter_value;
Does this compile? I don't see a counter_value in response
Thanks
Riana
> + return 0;
> }
>
> /**
> diff --git a/drivers/gpu/drm/xe/xe_ras_types.h b/drivers/gpu/drm/xe/xe_ras_types.h
> index fc496888b3f8..befdaf297103 100644
> --- a/drivers/gpu/drm/xe/xe_ras_types.h
> +++ b/drivers/gpu/drm/xe/xe_ras_types.h
> @@ -155,8 +155,14 @@ struct xe_ras_get_counter_response {
> u64 timestamp;
> /** @threshold: Threshold value for the counter */
> u32 threshold;
> - /** @reserved: Reserved */
> - u32 reserved[57];
> + /** @reserved: Reserved for future use */
> + u32 reserved:9;
> + /** @has_info_queue: Set if info queue is available */
> + u32 has_info_queue:1;
> + /** @reserved1: Reserved for future use */
> + u32 reserved1:22;
> + /** @info_queue: Initial info queue data (first chunk) if available */
> + struct xe_ras_info_queue_response info_queue;
> } __packed;
>
> /**
^ permalink raw reply [flat|nested] 11+ messages in thread* Re: [RFC PATCH 3/7] drm/xe/xe_ras: Refactor get_counter() to return response structure
2026-07-02 11:14 ` [RFC PATCH 3/7] drm/xe/xe_ras: Refactor get_counter() to return response structure Badal Nilawar
2026-07-03 7:41 ` Tauro, Riana
@ 2026-07-07 12:53 ` Mallesh, Koujalagi
1 sibling, 0 replies; 11+ messages in thread
From: Mallesh, Koujalagi @ 2026-07-07 12:53 UTC (permalink / raw)
To: Badal Nilawar, intel-xe
Cc: anshuman.gupta, rodrigo.vivi, daniele.ceraolospurio, raag.jadav,
riana.tauro, aravind.iddamsetty
On 02-07-2026 04:44 pm, Badal Nilawar wrote:
> Return the complete response structure from get_counter() instead of
> only the counter value. This allows callers to access additional
> response fields, such as has_info_queue for CPER record building.
>
> Signed-off-by: Badal Nilawar <badal.nilawar@intel.com>
> Assisted-by: Copilot:claude-sonnet-4.6
> ---
> drivers/gpu/drm/xe/xe_ras.c | 23 +++++++++++++++--------
> drivers/gpu/drm/xe/xe_ras_types.h | 10 ++++++++--
> 2 files changed, 23 insertions(+), 10 deletions(-)
>
> diff --git a/drivers/gpu/drm/xe/xe_ras.c b/drivers/gpu/drm/xe/xe_ras.c
> index 85b0202467f6..e594d4d3a23f 100644
> --- a/drivers/gpu/drm/xe/xe_ras.c
> +++ b/drivers/gpu/drm/xe/xe_ras.c
> @@ -157,12 +157,12 @@ void xe_ras_counter_threshold_crossed(struct xe_device *xe,
> }
> }
>
> -static int get_counter(struct xe_device *xe, struct xe_ras_error_class *counter, u32 *value)
> +static int get_counter(struct xe_device *xe, const struct xe_ras_error_class *counter,
> + struct xe_ras_get_counter_response *out)
> {
> struct xe_ras_get_counter_response response = {0};
response is not required, we can directly use "out".
> struct xe_ras_get_counter_request request = {0};
> struct xe_sysctrl_mailbox_command command = {0};
> - struct xe_ras_error_common *common;
> size_t rlen;
> int ret;
>
> @@ -183,12 +183,11 @@ static int get_counter(struct xe_device *xe, struct xe_ras_error_class *counter,
> return -EIO;
> }
>
> - common = &response.counter.common;
> - *value = response.value;
> -
> - xe_dbg(xe, "[RAS]: get counter %u for %s %s\n", *value, comp_to_str(common->component),
> - sev_to_str(common->severity));
> + xe_dbg(xe, "[RAS]: get counter value %u for %s %s\n", response.value,
> + comp_to_str(response.counter.common.component),
> + sev_to_str(response.counter.common.severity));
>
> + *out = response;
> return 0;
> }
>
> @@ -207,12 +206,20 @@ static int get_counter(struct xe_device *xe, struct xe_ras_error_class *counter,
> int xe_ras_get_counter(struct xe_device *xe, u8 severity, u8 component, u32 *value)
> {
> struct xe_ras_error_class counter = {0};
> + struct xe_ras_get_counter_response response;
Safe to initialized response = {0}.
> + int ret;
>
> counter.common.severity = drm_to_xe_ras_severity(severity);
> counter.common.component = drm_to_xe_ras_component(component);
>
> guard(xe_pm_runtime)(xe);
> - return get_counter(xe, &counter, value);
> +
> + ret = get_counter(xe, &counter, &response);
> + if (ret)
> + return ret;
> +
> + *value = response.counter_value;
counter_value is not member of response. should get compilation error.
Thanks,
-/Mallesh
> + return 0;
> }
>
> /**
> diff --git a/drivers/gpu/drm/xe/xe_ras_types.h b/drivers/gpu/drm/xe/xe_ras_types.h
> index fc496888b3f8..befdaf297103 100644
> --- a/drivers/gpu/drm/xe/xe_ras_types.h
> +++ b/drivers/gpu/drm/xe/xe_ras_types.h
> @@ -155,8 +155,14 @@ struct xe_ras_get_counter_response {
> u64 timestamp;
> /** @threshold: Threshold value for the counter */
> u32 threshold;
> - /** @reserved: Reserved */
> - u32 reserved[57];
> + /** @reserved: Reserved for future use */
> + u32 reserved:9;
> + /** @has_info_queue: Set if info queue is available */
> + u32 has_info_queue:1;
> + /** @reserved1: Reserved for future use */
> + u32 reserved1:22;
> + /** @info_queue: Initial info queue data (first chunk) if available */
> + struct xe_ras_info_queue_response info_queue;
> } __packed;
>
> /**
^ permalink raw reply [flat|nested] 11+ messages in thread
* [RFC PATCH 4/7] drm/xe/cper: Add CPER structures and trace event
2026-07-02 11:14 [RFC PATCH 0/7] Add CPER logging support for CRI Badal Nilawar
` (2 preceding siblings ...)
2026-07-02 11:14 ` [RFC PATCH 3/7] drm/xe/xe_ras: Refactor get_counter() to return response structure Badal Nilawar
@ 2026-07-02 11:14 ` Badal Nilawar
2026-07-02 11:14 ` [RFC PATCH 5/7] drm/xe/cper: APIs to prepare and log CPER record Badal Nilawar
` (2 subsequent siblings)
6 siblings, 0 replies; 11+ messages in thread
From: Badal Nilawar @ 2026-07-02 11:14 UTC (permalink / raw)
To: intel-xe
Cc: anshuman.gupta, rodrigo.vivi, daniele.ceraolospurio, raag.jadav,
riana.tauro, mallesh.koujalagi, aravind.iddamsetty
Define packed data structures and Intel-specific GUID macros needed
to build Intel GPU CPER (Common Platform Error Record) non-standard
records.
Add xe_error_cper trace event to log the assembled CPER record bytes.
Signed-off-by: Badal Nilawar <badal.nilawar@intel.com>
Assisted-by: Copilot:claude-sonnet-4.6
---
drivers/gpu/drm/xe/Makefile | 1 +
drivers/gpu/drm/xe/xe_cper_types.h | 186 +++++++++++++++++++++++++++++
drivers/gpu/drm/xe/xe_trace_cper.c | 9 ++
drivers/gpu/drm/xe/xe_trace_cper.h | 65 ++++++++++
4 files changed, 261 insertions(+)
create mode 100644 drivers/gpu/drm/xe/xe_cper_types.h
create mode 100644 drivers/gpu/drm/xe/xe_trace_cper.c
create mode 100644 drivers/gpu/drm/xe/xe_trace_cper.h
diff --git a/drivers/gpu/drm/xe/Makefile b/drivers/gpu/drm/xe/Makefile
index e5a04253e73b..01e6711cce1c 100644
--- a/drivers/gpu/drm/xe/Makefile
+++ b/drivers/gpu/drm/xe/Makefile
@@ -134,6 +134,7 @@ xe-y += xe_bb.o \
xe_tlb_inval_job.o \
xe_trace.o \
xe_trace_bo.o \
+ xe_trace_cper.o \
xe_trace_guc.o \
xe_trace_lrc.o \
xe_ttm_stolen_mgr.o \
diff --git a/drivers/gpu/drm/xe/xe_cper_types.h b/drivers/gpu/drm/xe/xe_cper_types.h
new file mode 100644
index 000000000000..82167ea4eb16
--- /dev/null
+++ b/drivers/gpu/drm/xe/xe_cper_types.h
@@ -0,0 +1,186 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright © 2026 Intel Corporation
+ */
+
+#ifndef _XE_CPER_TYPES_H_
+#define _XE_CPER_TYPES_H_
+
+#include <linux/cper.h>
+#include <linux/types.h>
+#include <linux/uuid.h>
+
+/* Intel CPER GUID Namespace — RFC 9562 UUIDv5 (SHA-1 name-based)
+ *
+ * All values below are generated deterministically by the shell script
+ * in the [Generation Script] section. Re-run that script to verify.
+ * Do NOT hand-edit the byte values.
+ */
+
+/* Creator IDs */
+#define INTEL_CPER_CREATOR_XEKMD \
+ GUID_INIT(0x9a42070f, 0xdf9d, 0x555e, \
+ 0xba, 0x02, 0x7c, 0xbc, 0x86, 0x3d, 0x37, 0x1c)
+
+#define INTEL_CPER_CREATOR_AMC \
+ GUID_INIT(0x215803da, 0xfc7a, 0x5925, \
+ 0xb7, 0x8b, 0x1f, 0xc1, 0x19, 0x61, 0x58, 0xd1)
+
+/* Notification Types */
+#define INTEL_CPER_NOTIFY_GPU_ERROR \
+ GUID_INIT(0x4ae12aef, 0x8745, 0x5fc7, \
+ 0xb9, 0x96, 0x71, 0xee, 0xbb, 0x51, 0xf2, 0x23)
+
+#define INTEL_CPER_NOTIFY_DRV_ERROR \
+ GUID_INIT(0xcef7e934, 0x51e7, 0x535f, \
+ 0xa6, 0x78, 0x5a, 0x4c, 0xcc, 0xb6, 0x96, 0x09)
+
+/* Section Types */
+#define INTEL_CPER_SECTION_ACCEL_GENERIC \
+ GUID_INIT(0xea9d8f84, 0x4258, 0x5227, \
+ 0x80, 0x28, 0xb9, 0xb1, 0x3e, 0x6d, 0x58, 0xb0)
+
+#pragma pack(push, 1)
+
+/**
+ * struct xe_cper_sec_intel_err_hdr - Intel-specific CPER error section header
+ *
+ * Fixed-size header for the Intel GPU error section of a CPER record.
+ * All multi-byte fields are little-endian; the structure is packed.
+ */
+struct xe_cper_sec_intel_err_hdr {
+ /** @error_class: Error classification (type, component, location, cause) */
+ union {
+ struct {
+ /** @error_class.error_type: RAS error severity */
+ u8 error_type;
+ /** @error_class.error_component: IP block that raised the error */
+ u8 error_component;
+ /** @error_class.tile: Tile number */
+ u8 tile;
+ /** @error_class.instance: Instance within the tile */
+ u32 instance;
+ /** @error_class.cause: Error cause code */
+ u32 cause;
+ /** @error_class.reserved: Reserved, must be zero */
+ u8 reserved;
+ } error_class;
+ /** @class: Raw byte view of the error class */
+ u8 class[12];
+ };
+ /** @first_timestamp: Timestamp of the first occurrence of this error class */
+ u64 first_timestamp;
+ /** @sig_id: Aggregated error class SIG ID; set to U32_MAX if unknown */
+ u32 sig_id;
+ /** @error_count: Number of times this error has been observed */
+ u32 error_count;
+ /** @valid_bits: Bitmask indicating which header fields are populated */
+ union {
+ struct {
+ /** @valid_bits.location: @error_class field is valid */
+ u16 location : 1;
+ /** @valid_bits.first_timestamp: @first_timestamp field is valid */
+ u16 first_timestamp : 1;
+ /** @valid_bits.sig_id: @sig_id field is valid */
+ u16 sig_id : 1;
+ /** @valid_bits.pci_bdf: @pci_bdf field is valid */
+ u16 pci_bdf : 1;
+ /** @valid_bits.drv_version: @drv_version field is valid */
+ u16 drv_version : 1;
+ /** @valid_bits.fw_id: @fw_id field is valid */
+ u16 fw_id : 1;
+ /** @valid_bits.reserved: Reserved, must be zero */
+ u16 reserved : 10;
+ } valid_bits;
+ /** @validation_bits: Raw u16 view of all valid bits */
+ u16 validation_bits;
+ };
+ /** @pci_bdf: PCI location string, format "DDDD:bb:dd.f" */
+ char pci_bdf[16];
+ /** @drv_version: Driver source version string (THIS_MODULE->srcversion) */
+ char drv_version[25];
+ /** @fw_id: Firmware version string (GFSP+PCODE+CSC+GUC or MNG+NUC+RAS+GUC) */
+ char fw_id[256];
+ /** @reserved: Reserved for future use, must be zero */
+ u8 reserved[5];
+};
+
+/**
+ * struct xe_cper_sec_intel_error_info - Variable-length Intel GPU error payload
+ *
+ * Appended after &xe_cper_sec_intel_err_hdr when detailed per-event data
+ * is available. The @event_queue flexible array holds @event_queue_count
+ * packed &xe_intel_priv_event_entry records.
+ */
+struct xe_cper_sec_intel_error_info {
+ /** @error_class: Error classification (mirrors the header error_class) */
+ union {
+ struct {
+ u8 error_type;
+ u8 error_component;
+ u8 tile;
+ u32 instance;
+ u32 cause;
+ u8 reserved;
+ } error_class;
+ /** @class: Raw byte view of the error class */
+ u8 class[12];
+ };
+ /** @error_count: Total number of errors recorded */
+ u32 error_count;
+ /** @event_queue_length: Total byte size of the @event_queue array */
+ u32 event_queue_length;
+ /** @event_queue_count: Number of entries in @event_queue */
+ u32 event_queue_count;
+ /** @event_queue: Packed array of &xe_intel_priv_event_entry records */
+ u8 event_queue[];
+};
+
+/**
+ * struct xe_intel_priv_event_entry - Single error event in the event queue
+ *
+ * Each entry is variable-length; @entry_length gives the byte size of
+ * @metadata only (not including @entry_length or @timestamp).
+ */
+struct xe_intel_priv_event_entry {
+ /** @entry_length: Byte length of the @metadata payload */
+ u32 entry_length;
+ /** @timestamp: Hardware timestamp of this event */
+ u64 timestamp;
+ /** @metadata: Event-specific payload bytes */
+ u8 metadata[];
+};
+
+/**
+ * struct xe_cper_nonstd_record - Fixed-size portion of an Intel GPU CPER record
+ *
+ * Contains the standard CPER record header, section descriptor, and the
+ * Intel error section header. A &xe_cper_sec_intel_error_info payload
+ * (with its flexible @event_queue array) is appended dynamically.
+ */
+struct xe_cper_nonstd_record {
+ /** @record_hdr: Standard CPER record header (UEFI Appendix N.2.1) */
+ struct cper_record_header record_hdr;
+ /** @section_desc: CPER section descriptor */
+ struct cper_section_descriptor section_desc;
+ /** @intel_hdr: Intel-specific error section header */
+ struct xe_cper_sec_intel_err_hdr intel_hdr;
+};
+
+#pragma pack(pop)
+
+/**
+ * struct xe_platform_id_entry - Mapping from PCI device ID to CPER platform GUID
+ *
+ * Used to resolve the platform_id field in a CPER section descriptor.
+ * GUIDs are UUIDv5 (RFC 9562, SHA-1) derived from the Intel CPER namespace
+ * with name string "platform/8086:<dev_id_hex_lower>".
+ */
+struct xe_platform_id_entry {
+ /** @device_id: PCI device ID */
+ u16 device_id;
+ /** @platform_id: Corresponding UUIDv5 platform GUID */
+ guid_t platform_id;
+};
+
+#endif
diff --git a/drivers/gpu/drm/xe/xe_trace_cper.c b/drivers/gpu/drm/xe/xe_trace_cper.c
new file mode 100644
index 000000000000..caea8783ab7c
--- /dev/null
+++ b/drivers/gpu/drm/xe/xe_trace_cper.c
@@ -0,0 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright © 2026 Intel Corporation
+ */
+
+#ifndef __CHECKER__
+#define CREATE_TRACE_POINTS
+#include "xe_trace_cper.h"
+#endif
diff --git a/drivers/gpu/drm/xe/xe_trace_cper.h b/drivers/gpu/drm/xe/xe_trace_cper.h
new file mode 100644
index 000000000000..45af86467616
--- /dev/null
+++ b/drivers/gpu/drm/xe/xe_trace_cper.h
@@ -0,0 +1,65 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright © 2026 Intel Corporation
+ */
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM xe
+
+#if !defined(_XE_TRACE_CPER_H_) || defined(TRACE_HEADER_MULTI_READ)
+#define _XE_TRACE_CPER_H_
+
+#include <linux/tracepoint.h>
+#include <linux/types.h>
+
+#include "xe_cper_types.h"
+#include "xe_device_types.h"
+
+#define __dev_name_xe(xe) dev_name((xe)->drm.dev)
+
+TRACE_EVENT(xe_error_cper,
+ TP_PROTO(struct xe_device *xe,
+ const guid_t *platform_id, const guid_t *fru_id,
+ const u8 severity,
+ const struct xe_cper_sec_intel_err_hdr *ihdr,
+ u32 cper_len, const u8 *cper),
+ TP_ARGS(xe, platform_id, fru_id, severity, ihdr, cper_len, cper),
+
+ TP_STRUCT__entry(
+ __string(dev, __dev_name_xe(xe))
+ __array(char, platform_id, UUID_SIZE)
+ __array(char, fru_id, UUID_SIZE)
+ __field(u8, sev)
+ __array(u8, ihdr_raw, sizeof(struct xe_cper_sec_intel_err_hdr))
+ __field(u32, cper_len)
+ __dynamic_array(u8, cper, cper_len)
+ ),
+
+ TP_fast_assign(
+ __assign_str(dev);
+ __entry->sev = severity;
+ memcpy(__entry->platform_id, platform_id, UUID_SIZE);
+ memcpy(__entry->fru_id, fru_id, UUID_SIZE);
+ memcpy(__entry->ihdr_raw, ihdr,
+ sizeof(struct xe_cper_sec_intel_err_hdr));
+ __entry->cper_len = cper_len;
+ memcpy(__get_dynamic_array(cper), cper, cper_len);
+ ),
+
+ TP_printk("dev=%s severity=%d platform_id=%pU fru_id=%pU "
+ "intel_err_hdr_raw=%s cper_len=%u cper_raw=%s",
+ __get_str(dev), __entry->sev,
+ __entry->platform_id, __entry->fru_id,
+ __print_hex(__entry->ihdr_raw, sizeof(struct xe_cper_sec_intel_err_hdr)),
+ __entry->cper_len,
+ __print_hex(__get_dynamic_array(cper), __entry->cper_len))
+);
+
+#endif
+
+/* This part must be outside protection */
+#undef TRACE_INCLUDE_PATH
+#undef TRACE_INCLUDE_FILE
+#define TRACE_INCLUDE_PATH ../../drivers/gpu/drm/xe
+#define TRACE_INCLUDE_FILE xe_trace_cper
+#include <trace/define_trace.h>
--
2.54.0
^ permalink raw reply related [flat|nested] 11+ messages in thread* [RFC PATCH 5/7] drm/xe/cper: APIs to prepare and log CPER record
2026-07-02 11:14 [RFC PATCH 0/7] Add CPER logging support for CRI Badal Nilawar
` (3 preceding siblings ...)
2026-07-02 11:14 ` [RFC PATCH 4/7] drm/xe/cper: Add CPER structures and trace event Badal Nilawar
@ 2026-07-02 11:14 ` Badal Nilawar
2026-07-02 11:14 ` [RFC PATCH 6/7] drm/xe/cper: Prepare Intel CPER error info from info queue Badal Nilawar
2026-07-02 11:14 ` [RFC PATCH 7/7] drm/xe/cper: Log CPER record for correctable errors Badal Nilawar
6 siblings, 0 replies; 11+ messages in thread
From: Badal Nilawar @ 2026-07-02 11:14 UTC (permalink / raw)
To: intel-xe
Cc: anshuman.gupta, rodrigo.vivi, daniele.ceraolospurio, raag.jadav,
riana.tauro, mallesh.koujalagi, aravind.iddamsetty
Add APIs to initialize Intel-specific CPER metadata, build a
non-standard CPER record, and emit it via the xe_error_cper tracepoint.
Signed-off-by: Badal Nilawar <badal.nilawar@intel.com>
Assisted-by: Copilot:claude-sonnet-4.6
---
drivers/gpu/drm/xe/Makefile | 1 +
drivers/gpu/drm/xe/xe_cper.c | 215 +++++++++++++++++++++++++++++++++++
drivers/gpu/drm/xe/xe_cper.h | 30 +++++
3 files changed, 246 insertions(+)
create mode 100644 drivers/gpu/drm/xe/xe_cper.c
create mode 100644 drivers/gpu/drm/xe/xe_cper.h
diff --git a/drivers/gpu/drm/xe/Makefile b/drivers/gpu/drm/xe/Makefile
index 01e6711cce1c..37600de21a35 100644
--- a/drivers/gpu/drm/xe/Makefile
+++ b/drivers/gpu/drm/xe/Makefile
@@ -35,6 +35,7 @@ $(obj)/generated/%_device_wa_oob.c $(obj)/generated/%_device_wa_oob.h: $(obj)/xe
xe-y += xe_bb.o \
xe_bo.o \
xe_bo_evict.o \
+ xe_cper.o \
xe_dep_scheduler.o \
xe_devcoredump.o \
xe_device.o \
diff --git a/drivers/gpu/drm/xe/xe_cper.c b/drivers/gpu/drm/xe/xe_cper.c
new file mode 100644
index 000000000000..b46190601d98
--- /dev/null
+++ b/drivers/gpu/drm/xe/xe_cper.c
@@ -0,0 +1,215 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2026 Intel Corporation
+ */
+
+#include <linux/cper.h>
+#include <linux/ktime.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+
+#include <drm/drm_print.h>
+
+#include "xe_cper.h"
+#include "xe_cper_types.h"
+#include "xe_device_types.h"
+#include "xe_ras_types.h"
+#include "xe_trace_cper.h"
+
+static const struct xe_platform_id_entry xe_platform_ids[] = {
+ /* 0x674C platform/8086:674c */
+ { 0x674C, GUID_INIT(0x9046afe5, 0x9041, 0x5124,
+ 0x86, 0x14, 0x92, 0x55, 0x0d, 0x9e, 0x9d, 0xa6) },
+};
+
+/**
+ * fill_pci_bdf - populate pci_bdf in the Intel section header
+ * @xe: xe device instance
+ * @ihdr: Intel section header to update
+ *
+ * Writes the PCI domain:bus:device.function string into @ihdr->pci_bdf and
+ * sets the corresponding valid bit.
+ */
+static void fill_pci_bdf(struct xe_device *xe,
+ struct xe_cper_sec_intel_err_hdr *ihdr)
+{
+ struct pci_dev *pdev = to_pci_dev(xe->drm.dev);
+
+ snprintf(ihdr->pci_bdf, sizeof(ihdr->pci_bdf), "%04x:%02x:%02x.%x",
+ pci_domain_nr(pdev->bus), pdev->bus->number,
+ PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn));
+ ihdr->valid_bits.pci_bdf = 1;
+}
+
+/**
+ * fill_drv_version - populate drv_version in the Intel section header
+ * @ihdr: Intel section header to update
+ *
+ * Copies the module's srcversion string into @ihdr->drv_version and sets the
+ * corresponding valid bit.
+ */
+static void fill_drv_version(struct xe_cper_sec_intel_err_hdr *ihdr)
+{
+ if (!THIS_MODULE->srcversion)
+ return;
+
+ strscpy(ihdr->drv_version, THIS_MODULE->srcversion,
+ sizeof(ihdr->drv_version));
+ ihdr->valid_bits.drv_version = 1;
+}
+
+/**
+ * lookup_platform_id - find the UUIDv5 platform_id for a PCI device ID
+ * @pdev: PCI device whose device ID is used as the lookup key
+ *
+ * Searches xe_platform_ids[] for an entry matching @pdev->device.
+ *
+ * Returns a pointer to the matching guid_t, or %NULL if not found.
+ */
+static const guid_t *lookup_platform_id(const struct pci_dev *pdev)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(xe_platform_ids); i++)
+ if (xe_platform_ids[i].device_id == pdev->device)
+ return &xe_platform_ids[i].platform_id;
+ return NULL;
+}
+
+static void fill_fw_id(struct xe_device *xe,
+ struct xe_cper_sec_intel_err_hdr *ihdr)
+{
+ /* TODO: populate ihdr->fw_id from firmware version queries */
+}
+
+/**
+ * xe_cper_init_intel_err_hdr - Populate an Intel CPER section header
+ * @xe: xe device instance
+ * @location: 12-byte error classification blob (cast from the source
+ * error class struct); pass %NULL if not applicable
+ * @first_timestamp: timestamp of the first occurrence; pass 0 if not available
+ * @sig_id: signal identifier for the error; pass %U32_MAX if not applicable
+ * @error_count: number of times this error has occurred
+ * @ihdr: Intel section header to populate
+ *
+ * Fills in @ihdr with the provided error metadata and sets the corresponding
+ * valid bits.
+ */
+void xe_cper_init_intel_err_hdr(struct xe_device *xe,
+ const u8 location[12],
+ u64 first_timestamp,
+ u32 sig_id,
+ u64 error_count,
+ struct xe_cper_sec_intel_err_hdr *ihdr)
+{
+ if (location) {
+ memcpy(&ihdr->error_class, location, sizeof(ihdr->error_class));
+ ihdr->valid_bits.location = 1;
+ }
+
+ if (first_timestamp) {
+ ihdr->first_timestamp = first_timestamp;
+ ihdr->valid_bits.first_timestamp = 1;
+ }
+
+ if (sig_id != U32_MAX) {
+ ihdr->sig_id = sig_id;
+ ihdr->valid_bits.sig_id = 1;
+ }
+
+ ihdr->error_count = error_count;
+
+ fill_pci_bdf(xe, ihdr);
+ fill_drv_version(ihdr);
+ fill_fw_id(xe, ihdr);
+}
+
+/**
+ * xe_cper_record_emit - Build and emit a CPER record for an Intel GPU error
+ * @xe: xe device instance
+ * @fru_id: GUID identifying the field-replaceable unit
+ * @severity: CPER error severity (CPER_SEV_*)
+ * @ihdr: Intel-specific section header, fully populated by
+ * xe_cper_init_intel_err_hdr()
+ * @einfo: optional xe_cper_sec_intel_error_info payload; may be %NULL
+ * @einfo_size: byte size of @einfo, including any event_queue data
+ *
+ * The platform_id is resolved automatically from xe_platform_ids[] using
+ * the PCI device ID. If no entry matches, the field is left zeroed and
+ * the record is still emitted.
+ */
+void xe_cper_record_emit(struct xe_device *xe,
+ const guid_t *fru_id,
+ u8 severity,
+ guid_t notification_type,
+ struct xe_cper_sec_intel_err_hdr *ihdr,
+ const void *einfo,
+ u32 einfo_size)
+{
+ struct pci_dev *pdev = to_pci_dev(xe->drm.dev);
+ const guid_t *platform_id = lookup_platform_id(pdev);
+ u32 total_len = sizeof(struct xe_cper_nonstd_record) + einfo_size;
+ struct cper_section_descriptor *sdesc;
+ struct cper_record_header *rhdr;
+ struct xe_cper_nonstd_record *rec;
+
+ rec = kzalloc(total_len, GFP_KERNEL);
+ if (!rec) {
+ drm_err(&xe->drm, "CPER: failed to allocate record buffer\n");
+ return;
+ }
+
+ rhdr = &rec->record_hdr;
+ sdesc = &rec->section_desc;
+
+ /* Assemble the CPER record header (UEFI Appendix N.2.1) */
+ memcpy(rhdr->signature, CPER_SIG_RECORD, CPER_SIG_SIZE);
+ rhdr->revision = CPER_RECORD_REV;
+ rhdr->signature_end = CPER_SIG_END;
+ rhdr->section_count = 1;
+ rhdr->error_severity = severity;
+ rhdr->validation_bits = CPER_VALID_TIMESTAMP;
+ rhdr->record_length = total_len;
+ rhdr->timestamp = ktime_get_real_ns();
+ if (platform_id) {
+ rhdr->platform_id = *platform_id;
+ rhdr->validation_bits |= CPER_VALID_PLATFORM_ID;
+ }
+ rhdr->creator_id = INTEL_CPER_CREATOR_XEKMD;
+ rhdr->notification_type = notification_type;
+ rhdr->record_id = cper_next_record_id();
+ rhdr->flags = 0;
+
+ /* Assemble the section descriptor (UEFI Appendix N.2.2) */
+ sdesc->section_offset = sizeof(struct cper_record_header) +
+ sizeof(struct cper_section_descriptor);
+ sdesc->section_length = sizeof(struct xe_cper_sec_intel_err_hdr) +
+ einfo_size;
+ sdesc->revision = CPER_RECORD_REV;
+ /* Set validation_bits using CPER_SEC_VALID_FRU_ID / CPER_SEC_VALID_FRU_TEXT
+ * when the corresponding fields are populated.
+ */
+ sdesc->validation_bits = 0;
+ sdesc->reserved = 0;
+ sdesc->flags = 0;
+ sdesc->section_type = INTEL_CPER_SECTION_ACCEL_GENERIC;
+ if (fru_id && !guid_is_null(fru_id)) {
+ sdesc->fru_id = *fru_id;
+ sdesc->validation_bits |= CPER_SEC_VALID_FRU_ID;
+ }
+ sdesc->section_severity = severity;
+
+ /* Copy the Intel-specific section header (updated with BDF/version) */
+ rec->intel_hdr = *ihdr;
+
+ /* Append optional variable-length error info */
+ if (einfo && einfo_size)
+ memcpy((u8 *)rec + sizeof(*rec), einfo, einfo_size);
+
+ trace_xe_error_cper(xe, platform_id, fru_id, severity,
+ &rec->intel_hdr, total_len, (u8 *)rec);
+
+ kfree(rec);
+}
diff --git a/drivers/gpu/drm/xe/xe_cper.h b/drivers/gpu/drm/xe/xe_cper.h
new file mode 100644
index 000000000000..7027e3f1be60
--- /dev/null
+++ b/drivers/gpu/drm/xe/xe_cper.h
@@ -0,0 +1,30 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright © 2026 Intel Corporation
+ */
+
+#ifndef _XE_CPER_H_
+#define _XE_CPER_H_
+
+#include <linux/types.h>
+#include <linux/uuid.h>
+
+struct xe_cper_sec_intel_err_hdr;
+struct xe_device;
+
+void xe_cper_record_emit(struct xe_device *xe,
+ const guid_t *fru_id,
+ u8 severity,
+ guid_t notification_type,
+ struct xe_cper_sec_intel_err_hdr *ihdr,
+ const void *einfo,
+ u32 einfo_size);
+
+void xe_cper_init_intel_err_hdr(struct xe_device *xe,
+ const u8 location[12],
+ u64 first_timestamp,
+ u32 sig_id,
+ u64 error_count,
+ struct xe_cper_sec_intel_err_hdr *ihdr);
+
+#endif /* _XE_CPER_H_ */
--
2.54.0
^ permalink raw reply related [flat|nested] 11+ messages in thread* [RFC PATCH 6/7] drm/xe/cper: Prepare Intel CPER error info from info queue
2026-07-02 11:14 [RFC PATCH 0/7] Add CPER logging support for CRI Badal Nilawar
` (4 preceding siblings ...)
2026-07-02 11:14 ` [RFC PATCH 5/7] drm/xe/cper: APIs to prepare and log CPER record Badal Nilawar
@ 2026-07-02 11:14 ` Badal Nilawar
2026-07-02 11:14 ` [RFC PATCH 7/7] drm/xe/cper: Log CPER record for correctable errors Badal Nilawar
6 siblings, 0 replies; 11+ messages in thread
From: Badal Nilawar @ 2026-07-02 11:14 UTC (permalink / raw)
To: intel-xe
Cc: anshuman.gupta, rodrigo.vivi, daniele.ceraolospurio, raag.jadav,
riana.tauro, mallesh.koujalagi, aravind.iddamsetty
Add prepare_cper_error_info() to xe_ras.c which assembles the raw info
queue data embedded in a GET_COUNTER response (and any subsequent chunks
fetched via GET_INFO_QUEUE_DATA) into a xe_cper_sec_intel_error_info
that can be passed directly to cper logging function.
Signed-off-by: Badal Nilawar <badal.nilawar@intel.com>
Assisted-by: Copilot:claude-sonnet-4.6
---
drivers/gpu/drm/xe/xe_ras.c | 142 +++++++++++++++++++++++++++++++++++-
1 file changed, 141 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/xe/xe_ras.c b/drivers/gpu/drm/xe/xe_ras.c
index e594d4d3a23f..8579cde6a4bf 100644
--- a/drivers/gpu/drm/xe/xe_ras.c
+++ b/drivers/gpu/drm/xe/xe_ras.c
@@ -3,6 +3,8 @@
* Copyright © 2026 Intel Corporation
*/
+#include "xe_cper.h"
+#include "xe_cper_types.h"
#include "xe_device.h"
#include "xe_drm_ras.h"
#include "xe_pm.h"
@@ -218,7 +220,7 @@ int xe_ras_get_counter(struct xe_device *xe, u8 severity, u8 component, u32 *val
if (ret)
return ret;
- *value = response.counter_value;
+ *value = response.value;
return 0;
}
@@ -311,6 +313,144 @@ static int get_info_queue_data(struct xe_device *xe,
return 0;
}
+/**
+ * prepare_cper_error_info - Assemble info queue chunks and convert to CPER einfo
+ * @xe: xe device instance
+ * @counter_resp: counter response containing the first embedded chunk
+ * @error_class: RAS error class used to populate the einfo error_class fields
+ * @einfo_size_out: output size of the allocated einfo buffer
+ *
+ * Assembles the complete raw info queue data from the first chunk already
+ * embedded in @counter_resp and any additional chunks fetched via
+ * GET_INFO_QUEUE_DATA. The raw data layout is:
+ *
+ * [xe_ras_info_queue_dynamic_counter_hdr * num_headers]
+ * [xe_ras_error_log * N]
+ *
+ * Each xe_ras_error_log is translated into an xe_intel_priv_event_entry and
+ * appended to the returned xe_cper_sec_intel_error_info.event_queue[].
+ *
+ * Returns: allocated einfo on success (caller must kfree()), NULL on failure.
+ */
+static struct xe_cper_sec_intel_error_info *
+prepare_cper_error_info(struct xe_device *xe,
+ const struct xe_ras_get_counter_response *counter_resp,
+ const struct xe_ras_error_class *error_class,
+ u32 *einfo_size_out)
+{
+ const struct xe_ras_info_queue_header *first_qhdr =
+ &counter_resp->info_queue.queue_header;
+ struct xe_ras_get_info_queue_data_request iq_req = {0};
+ struct xe_ras_get_info_queue_data_response iq_response = {0};
+ struct xe_cper_sec_intel_error_info *einfo;
+ struct xe_intel_priv_event_entry *entry;
+ const struct xe_ras_error_log *logs;
+ u32 entry_size, einfo_size;
+ u32 num_logs;
+ u32 raw_total, iq_offset = 0;
+ u8 *raw_buf;
+ u32 i;
+
+ raw_buf = kzalloc(XE_RAS_INFO_QUEUE_MAX_TOTAL_SIZE, GFP_KERNEL);
+ if (!raw_buf)
+ return NULL;
+
+ /* Copy first chunk already embedded in the counter response */
+ if (first_qhdr->chunk_size &&
+ first_qhdr->chunk_offset + first_qhdr->chunk_size <=
+ XE_RAS_INFO_QUEUE_MAX_TOTAL_SIZE) {
+ memcpy(raw_buf + first_qhdr->chunk_offset,
+ counter_resp->info_queue.queue_data,
+ first_qhdr->chunk_size);
+ iq_offset = first_qhdr->chunk_size;
+ }
+
+ /* Fetch any remaining chunks */
+ if (first_qhdr->flags & XE_RAS_INFO_QUEUE_FLAG_MORE_DATA) {
+ iq_req.source_command = XE_SYSCTRL_CMD_GET_COUNTER;
+ iq_req.source_context = counter_resp->counter;
+ iq_req.queue_request.requested_size = XE_RAS_INFO_QUEUE_MAX_CHUNK_SIZE;
+ iq_req.queue_request.session_id = counter_resp->counter;
+
+ do {
+ struct xe_ras_info_queue_header *qhdr;
+ u32 end;
+
+ iq_req.queue_request.requested_offset = iq_offset;
+
+ if (get_info_queue_data(xe, &iq_req, &iq_response))
+ break;
+
+ qhdr = &iq_response.queue_response.queue_header;
+ end = qhdr->chunk_offset + qhdr->chunk_size;
+
+ if (end > XE_RAS_INFO_QUEUE_MAX_TOTAL_SIZE) {
+ xe_warn(xe, "[RAS]: CPER: info queue chunk out of bounds (offset=%u size=%u)\n",
+ qhdr->chunk_offset, qhdr->chunk_size);
+ break;
+ }
+
+ memcpy(raw_buf + qhdr->chunk_offset,
+ iq_response.queue_response.queue_data,
+ qhdr->chunk_size);
+
+ if (!qhdr->chunk_size)
+ break;
+
+ iq_offset += qhdr->chunk_size;
+ } while (iq_response.queue_response.queue_header.flags &
+ XE_RAS_INFO_QUEUE_FLAG_MORE_DATA);
+ }
+
+ raw_total = first_qhdr->total_size
+ ? min(first_qhdr->total_size, XE_RAS_INFO_QUEUE_MAX_TOTAL_SIZE)
+ : iq_offset;
+
+ num_logs = raw_total / sizeof(struct xe_ras_error_log);
+ if (!num_logs) {
+ kfree(raw_buf);
+ return NULL;
+ }
+
+ /*
+ * Each xe_intel_priv_event_entry holds:
+ * entry_length (u32) + timestamp (u64) + metadata[] (error_details)
+ */
+ entry_size = offsetof(struct xe_intel_priv_event_entry, metadata) +
+ sizeof_field(struct xe_ras_error_log, error_details);
+ einfo_size = sizeof(*einfo) + num_logs * entry_size;
+
+ einfo = kzalloc(einfo_size, GFP_KERNEL);
+ if (!einfo) {
+ kfree(raw_buf);
+ return NULL;
+ }
+
+ einfo->error_count = counter_resp->value;
+ einfo->event_queue_length = num_logs * entry_size;
+ einfo->event_queue_count = num_logs;
+ einfo->error_class.error_type = error_class->common.severity;
+ einfo->error_class.error_component = error_class->common.component;
+ einfo->error_class.tile = error_class->product.unit.tile;
+ einfo->error_class.instance = error_class->product.unit.instance;
+ einfo->error_class.cause = error_class->product.cause.cause;
+
+ logs = (const struct xe_ras_error_log *)raw_buf;
+ entry = (struct xe_intel_priv_event_entry *)einfo->event_queue;
+
+ for (i = 0; i < num_logs; i++) {
+ entry->entry_length = sizeof_field(struct xe_ras_error_log, error_details);
+ entry->timestamp = logs[i].timestamp;
+ memcpy(entry->metadata, logs[i].error_details,
+ sizeof(logs[i].error_details));
+ entry = (struct xe_intel_priv_event_entry *)((u8 *)entry + entry_size);
+ }
+
+ kfree(raw_buf);
+ *einfo_size_out = einfo_size;
+ return einfo;
+}
+
/**
* xe_ras_init - Initialize Xe RAS
* @xe: xe device instance
--
2.54.0
^ permalink raw reply related [flat|nested] 11+ messages in thread* [RFC PATCH 7/7] drm/xe/cper: Log CPER record for correctable errors
2026-07-02 11:14 [RFC PATCH 0/7] Add CPER logging support for CRI Badal Nilawar
` (5 preceding siblings ...)
2026-07-02 11:14 ` [RFC PATCH 6/7] drm/xe/cper: Prepare Intel CPER error info from info queue Badal Nilawar
@ 2026-07-02 11:14 ` Badal Nilawar
6 siblings, 0 replies; 11+ messages in thread
From: Badal Nilawar @ 2026-07-02 11:14 UTC (permalink / raw)
To: intel-xe
Cc: anshuman.gupta, rodrigo.vivi, daniele.ceraolospurio, raag.jadav,
riana.tauro, mallesh.koujalagi, aravind.iddamsetty
In xe_ras_counter_threshold_crossed(), emit a CPER record for each
correctable error reported via the counter threshold crossed event.
Signed-off-by: Badal Nilawar <badal.nilawar@intel.com>
Assisted-by: Copilot:claude-sonnet-4.6
---
drivers/gpu/drm/xe/xe_ras.c | 75 +++++++++++++++++++++++++++++++++++++
1 file changed, 75 insertions(+)
diff --git a/drivers/gpu/drm/xe/xe_ras.c b/drivers/gpu/drm/xe/xe_ras.c
index 8579cde6a4bf..53f192a2e97f 100644
--- a/drivers/gpu/drm/xe/xe_ras.c
+++ b/drivers/gpu/drm/xe/xe_ras.c
@@ -11,6 +11,7 @@
#include "xe_printk.h"
#include "xe_ras.h"
#include "xe_ras_types.h"
+#include "xe_sig_ids.h"
#include "xe_sysctrl.h"
#include "xe_sysctrl_event_types.h"
#include "xe_sysctrl_mailbox.h"
@@ -67,6 +68,10 @@ static const char *const xe_ras_components[] = {
};
static_assert(ARRAY_SIZE(xe_ras_components) == XE_RAS_COMP_MAX);
+static void emit_hw_error_cper(struct xe_device *xe,
+ const struct xe_ras_error_class *error_class,
+ u64 timestamp, u32 sig_id, u8 severity);
+
static u8 drm_to_xe_ras_severity(u8 severity)
{
switch (severity) {
@@ -133,6 +138,38 @@ static inline const char *comp_to_str(u8 component)
return xe_ras_components[component];
}
+static u32 ras_comp_to_hw_sigid(u8 component)
+{
+ switch (component) {
+ case XE_RAS_COMP_DEVICE_MEMORY:
+ return XE_SIG_HW_DEVICE_MEMORY;
+ case XE_RAS_COMP_CORE_COMPUTE:
+ return XE_SIG_HW_CORE_COMPUTE;
+ case XE_RAS_COMP_PCIE:
+ return XE_SIG_HW_PCIE;
+ case XE_RAS_COMP_FABRIC:
+ return XE_SIG_HW_FABRIC;
+ case XE_RAS_COMP_SOC_INTERNAL:
+ return XE_SIG_HW_SOC_INTERNAL;
+ default:
+ return U32_MAX;
+ }
+}
+
+static u8 ras_sev_to_cper_sev(u8 ras_sev)
+{
+ switch (ras_sev) {
+ case XE_RAS_SEV_CORRECTABLE:
+ return CPER_SEV_CORRECTED;
+ case XE_RAS_SEV_UNCORRECTABLE:
+ return CPER_SEV_RECOVERABLE;
+ case XE_RAS_SEV_INFORMATIONAL:
+ return CPER_SEV_INFORMATIONAL;
+ default:
+ return CPER_SEV_RECOVERABLE;
+ }
+}
+
void xe_ras_counter_threshold_crossed(struct xe_device *xe,
struct xe_sysctrl_event_response *response)
{
@@ -154,6 +191,9 @@ void xe_ras_counter_threshold_crossed(struct xe_device *xe,
severity = errors[id].common.severity;
component = errors[id].common.component;
+ /* Emit a CPER record for this error */
+ emit_hw_error_cper(xe, &errors[id], 0, ras_comp_to_hw_sigid(component), severity);
+
xe_warn(xe, "[RAS]: %s %s detected\n",
comp_to_str(component), sev_to_str(severity));
}
@@ -451,6 +491,41 @@ prepare_cper_error_info(struct xe_device *xe,
return einfo;
}
+static void emit_hw_error_cper(struct xe_device *xe,
+ const struct xe_ras_error_class *error_class,
+ u64 timestamp, u32 sig_id, u8 severity)
+{
+ struct xe_ras_get_counter_response counter_response = {};
+ struct xe_cper_sec_intel_err_hdr ihdr = {};
+ struct xe_cper_sec_intel_error_info *einfo = NULL;
+ u32 einfo_size = 0;
+
+ if (get_counter(xe, error_class, &counter_response)) {
+ xe_err(xe, "[RAS]: CPER: failed to get counter, skipping record\n");
+ return;
+ }
+
+ xe_cper_init_intel_err_hdr(xe,
+ (const u8 *)error_class,
+ timestamp,
+ sig_id,
+ counter_response.value,
+ &ihdr);
+
+ if (counter_response.has_info_queue) {
+ einfo = prepare_cper_error_info(xe, &counter_response,
+ error_class, &einfo_size);
+ if (!einfo)
+ xe_err(xe, "[RAS]: CPER: failed to build einfo from info queue\n");
+ }
+
+ xe_cper_record_emit(xe, &guid_null,
+ ras_sev_to_cper_sev(severity),
+ INTEL_CPER_NOTIFY_GPU_ERROR,
+ &ihdr, einfo, einfo_size);
+ kfree(einfo);
+}
+
/**
* xe_ras_init - Initialize Xe RAS
* @xe: xe device instance
--
2.54.0
^ permalink raw reply related [flat|nested] 11+ messages in thread