From: Badal Nilawar <badal.nilawar@intel.com>
To: intel-xe@lists.freedesktop.org
Cc: anshuman.gupta@intel.com, rodrigo.vivi@intel.com,
daniele.ceraolospurio@intel.com, raag.jadav@intel.com,
riana.tauro@intel.com, mallesh.koujalagi@intel.com,
aravind.iddamsetty@intel.com, michal.wajdeczko@intel.com,
himal.prasad.ghimiray@intel.com, arvind.yadav@intel.com
Subject: [PATCH v2 05/11] drm/xe/cper: Prepare Intel CPER error info from info queue
Date: Tue, 25 Aug 2026 23:29:22 +0530 [thread overview]
Message-ID: <20260825175916.1103841-18-badal.nilawar@intel.com> (raw)
In-Reply-To: <20260825175916.1103841-13-badal.nilawar@intel.com>
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 | 278 ++++++++++++++++++++++++++++++++++++
1 file changed, 278 insertions(+)
diff --git a/drivers/gpu/drm/xe/xe_ras.c b/drivers/gpu/drm/xe/xe_ras.c
index e913235e9cce..27c78800b5d2 100644
--- a/drivers/gpu/drm/xe/xe_ras.c
+++ b/drivers/gpu/drm/xe/xe_ras.c
@@ -3,8 +3,11 @@
* Copyright © 2026 Intel Corporation
*/
+#include "xe_cper.h"
+#include "xe_cper_types.h"
#include "xe_debugfs.h"
#include "xe_device.h"
+#include "xe_device_types.h"
#include "xe_drm_ras.h"
#include "xe_log.h"
#include "xe_pm.h"
@@ -471,6 +474,281 @@ static int get_counter(struct xe_device *xe, struct xe_ras_error_class *counter,
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_cper_einfo_entry - One CPER error-info buffer with its byte size
+ * @hdr: dynamic-counter header carrying the per-entry error_class and counter
+ * value; used by the caller to build a dedicated xe_cper_sec_intel_err_hdr
+ * for each CPER record
+ * @einfo: allocated error-info payload (caller must kfree)
+ * @einfo_size: byte size of @einfo including any event_queue data
+ * @timestamp: timestamp of first occurrence of dynamic-counter
+ */
+struct xe_cper_einfo_entry {
+ struct xe_ras_info_queue_dynamic_counter_hdr hdr;
+ struct xe_cper_sec_intel_error_info *einfo;
+ u32 einfo_size;
+ u64 timestamp;
+};
+
+/**
+ * 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. Two use cases are supported based on num_headers in
+ * the info queue header:
+ *
+ * Detail error counter (num_headers == 0)::
+ *
+ * [xe_ras_error_log * N]
+ *
+ * Returns one xe_cper_einfo_entry covering all N logs.
+ *
+ * Aggregate error counter (num_headers > 0)::
+ *
+ * [xe_ras_info_queue_dynamic_counter_hdr * num_headers]
+ * [xe_ras_error_log * N]
+ *
+ * Returns one xe_cper_einfo_entry per header. Each header's @counter field
+ * gives the number of consecutive xe_ras_error_log entries belonging to it
+ * and its @error_class is used to populate the entry's einfo->error_class.
+ *
+ * Returns: allocated xe_cper_einfo_entry array on success (caller must kfree
+ * each entry's einfo then kfree the array), NULL on failure.
+ * @count_out is set to the number of entries in the array.
+ */
+static struct xe_cper_einfo_entry *
+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 *count_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_einfo_entry *einfo_arr;
+ u32 num_headers, headers_size;
+ u32 raw_total, iq_offset = 0;
+ u32 entry_size;
+ 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_headers = first_qhdr->num_headers;
+ headers_size = num_headers * sizeof(struct xe_ras_info_queue_dynamic_counter_hdr);
+
+ if (headers_size > raw_total) {
+ xe_warn(xe, "[RAS]: CPER: aggregate headers size (%u) exceeds raw total (%u)\n",
+ headers_size, raw_total);
+ kfree(raw_buf);
+ return NULL;
+ }
+
+ /*
+ * entry_size is constant for every xe_intel_priv_event_entry:
+ * 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);
+
+ if (num_headers == 0) {
+ /* Detail case: single einfo covering all log entries */
+ u32 num_logs = raw_total / sizeof(struct xe_ras_error_log);
+ struct xe_cper_sec_intel_error_info *einfo;
+ struct xe_intel_priv_event_entry *entry;
+ const struct xe_ras_error_log *logs;
+ u32 einfo_size;
+
+ if (!num_logs) {
+ kfree(raw_buf);
+ return NULL;
+ }
+
+ einfo_arr = kzalloc(sizeof(*einfo_arr), GFP_KERNEL);
+ if (!einfo_arr) {
+ kfree(raw_buf);
+ return NULL;
+ }
+
+ einfo_size = sizeof(*einfo) + num_logs * entry_size;
+ einfo = kzalloc(einfo_size, GFP_KERNEL);
+ if (!einfo) {
+ kfree(einfo_arr);
+ 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);
+ }
+
+ einfo_arr[0].hdr.error_class = *error_class;
+ einfo_arr[0].hdr.counter = counter_resp->value;
+ einfo_arr[0].einfo = einfo;
+ einfo_arr[0].einfo_size = einfo_size;
+ einfo_arr[0].timestamp = logs[0].timestamp;
+ *count_out = 1;
+
+ } else {
+ /* Aggregate case: one einfo per dynamic-counter header */
+ const struct xe_ras_info_queue_dynamic_counter_hdr *hdrs =
+ (const struct xe_ras_info_queue_dynamic_counter_hdr *)raw_buf;
+ const struct xe_ras_error_log *all_logs =
+ (const struct xe_ras_error_log *)(raw_buf + headers_size);
+ u32 avail_logs = (raw_total - headers_size) / sizeof(struct xe_ras_error_log);
+ u32 log_offset = 0;
+
+ einfo_arr = kzalloc_objs(*einfo_arr, num_headers, GFP_KERNEL);
+ if (!einfo_arr) {
+ kfree(raw_buf);
+ return NULL;
+ }
+
+ for (i = 0; i < num_headers; i++) {
+ u32 num_logs = min_t(u32, hdrs[i].counter, XE_RAS_NUM_COUNTERS);
+ struct xe_cper_sec_intel_error_info *einfo;
+ struct xe_intel_priv_event_entry *entry;
+ u32 einfo_size;
+ u32 j;
+
+ if (log_offset + num_logs > avail_logs) {
+ xe_warn(xe, "[RAS]: CPER: header[%u] claims %u logs but only %u remain\n",
+ i, num_logs, avail_logs - log_offset);
+ break;
+ }
+
+ if (!num_logs) {
+ log_offset += num_logs;
+ continue;
+ }
+
+ einfo_size = sizeof(*einfo) + num_logs * entry_size;
+ einfo = kzalloc(einfo_size, GFP_KERNEL);
+ if (!einfo) {
+ u32 k;
+
+ for (k = 0; k < i; k++)
+ kfree(einfo_arr[k].einfo);
+ kfree(einfo_arr);
+ kfree(raw_buf);
+ return NULL;
+ }
+
+ einfo->error_count = num_logs;
+ einfo->event_queue_length = num_logs * entry_size;
+ einfo->event_queue_count = num_logs;
+ einfo->error_class.error_type = hdrs[i].error_class.common.severity;
+ einfo->error_class.tile = hdrs[i].error_class.product.unit.tile;
+ einfo->error_class.instance = hdrs[i].error_class.product.unit.instance;
+ einfo->error_class.cause = hdrs[i].error_class.product.cause.cause;
+ einfo->error_class.error_component = hdrs[i].error_class.common.component;
+
+ entry = (struct xe_intel_priv_event_entry *)einfo->event_queue;
+ for (j = 0; j < num_logs; j++) {
+ const struct xe_ras_error_log *log = &all_logs[log_offset + j];
+
+ entry->entry_length = sizeof_field(struct xe_ras_error_log, error_details);
+ entry->timestamp = log->timestamp;
+ memcpy(entry->metadata, log->error_details,
+ sizeof(log->error_details));
+ entry = (struct xe_intel_priv_event_entry *)((u8 *)entry + entry_size);
+
+ if (j == 0)
+ einfo_arr[i].timestamp = log->timestamp;
+ }
+
+ einfo_arr[i].hdr = hdrs[i];
+ einfo_arr[i].einfo = einfo;
+ einfo_arr[i].einfo_size = einfo_size;
+ log_offset += num_logs;
+ }
+
+ *count_out = i;
+ }
+
+ kfree(raw_buf);
+ return einfo_arr;
+}
+
/**
* xe_ras_process_errors() - Process and contain hardware errors
* @xe: xe device instance
--
2.54.0
next prev parent reply other threads:[~2026-08-25 17:42 UTC|newest]
Thread overview: 35+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-25 17:59 [PATCH v2 00/11] Add CPER logging support for CRI Badal Nilawar
2026-08-25 17:59 ` [PATCH v2 01/11] drm/xe/xe_ras: Add support to retrieve info queue data " Badal Nilawar
2026-08-25 17:53 ` sashiko-bot
2026-08-26 0:54 ` Rodrigo Vivi
2026-08-25 20:48 ` Michal Wajdeczko
2026-08-25 17:59 ` [PATCH v2 02/11] drm/xe/xe_ras: Refactor get_counter() to return response structure Badal Nilawar
2026-08-25 17:59 ` [PATCH v2 03/11] drm/xe/cper: Add CPER structures and trace event Badal Nilawar
2026-08-25 17:51 ` sashiko-bot
2026-08-28 15:23 ` Rodrigo Vivi
2026-08-25 17:59 ` [PATCH v2 04/11] drm/xe/cper: APIs to prepare and log CPER record Badal Nilawar
2026-08-25 18:02 ` sashiko-bot
2026-08-26 0:59 ` Rodrigo Vivi
2026-08-25 17:59 ` Badal Nilawar [this message]
2026-08-25 17:54 ` [PATCH v2 05/11] drm/xe/cper: Prepare Intel CPER error info from info queue sashiko-bot
2026-08-25 17:59 ` [PATCH v2 06/11] drm/xe/cper: Log CPER records for aggregate counter retrival Badal Nilawar
2026-08-25 17:55 ` sashiko-bot
2026-08-26 1:01 ` Rodrigo Vivi
2026-08-25 17:59 ` [PATCH v2 07/11] drm/xe/cper: Allow hardware error CPER reporting from xe_log Badal Nilawar
2026-08-25 17:54 ` sashiko-bot
2026-08-27 21:27 ` Michal Wajdeczko
2026-08-25 17:59 ` [PATCH v2 08/11] drm/xe/ras: Report device memory errors using SIGID Badal Nilawar
2026-08-25 17:58 ` sashiko-bot
2026-08-27 20:25 ` Michal Wajdeczko
2026-08-25 17:59 ` [PATCH v2 09/11] drm/xe/ras: Report core compute " Badal Nilawar
2026-08-25 17:55 ` sashiko-bot
2026-08-25 17:59 ` [PATCH v2 10/11] drm/xe/ras: Report soc internal " Badal Nilawar
2026-08-28 15:20 ` Rodrigo Vivi
2026-08-25 17:59 ` [PATCH v2 11/11] drm/xe/ras: Report correctable " Badal Nilawar
2026-08-25 18:03 ` sashiko-bot
2026-08-25 18:29 ` ✗ CI.checkpatch: warning for Add CPER logging support for CRI (rev2) Patchwork
2026-08-25 18:31 ` ✓ CI.KUnit: success " Patchwork
2026-08-25 19:25 ` ✓ Xe.CI.BAT: " Patchwork
2026-08-25 22:06 ` ✗ Xe.CI.FULL: failure " Patchwork
2026-08-26 19:50 ` [PATCH v2 00/11] Add CPER logging support for CRI Matt Roper
2026-08-27 20:12 ` Rodrigo Vivi
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260825175916.1103841-18-badal.nilawar@intel.com \
--to=badal.nilawar@intel.com \
--cc=anshuman.gupta@intel.com \
--cc=aravind.iddamsetty@intel.com \
--cc=arvind.yadav@intel.com \
--cc=daniele.ceraolospurio@intel.com \
--cc=himal.prasad.ghimiray@intel.com \
--cc=intel-xe@lists.freedesktop.org \
--cc=mallesh.koujalagi@intel.com \
--cc=michal.wajdeczko@intel.com \
--cc=raag.jadav@intel.com \
--cc=riana.tauro@intel.com \
--cc=rodrigo.vivi@intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.