drm/xe/xe_ras: Add support to get error counter value

Add request/response structures and helper functions to query system
controller to get error counter value.

Reviewed-by: Raag Jadav <raag.jadav@intel.com>
Link: https://patch.msgid.link/20260618060633.2790109-10-riana.tauro@intel.com
Signed-off-by: Riana Tauro <riana.tauro@intel.com>
This commit is contained in:
Riana Tauro 2026-06-18 11:36:36 +05:30
parent cdeb5e248d
commit fe48a86980
6 changed files with 153 additions and 0 deletions

View File

@ -4,11 +4,14 @@
*/
#include "xe_device.h"
#include "xe_pm.h"
#include "xe_printk.h"
#include "xe_ras.h"
#include "xe_ras_types.h"
#include "xe_sysctrl.h"
#include "xe_sysctrl_event_types.h"
#include "xe_sysctrl_mailbox.h"
#include "xe_sysctrl_mailbox_types.h"
/* Severity of detected errors */
enum xe_ras_severity {
@ -50,6 +53,36 @@ static const char *const xe_ras_components[] = {
};
static_assert(ARRAY_SIZE(xe_ras_components) == XE_RAS_COMP_MAX);
static u8 drm_to_xe_ras_severity(u8 severity)
{
switch (severity) {
case DRM_XE_RAS_ERR_SEV_CORRECTABLE:
return XE_RAS_SEV_CORRECTABLE;
case DRM_XE_RAS_ERR_SEV_UNCORRECTABLE:
return XE_RAS_SEV_UNCORRECTABLE;
default:
return XE_RAS_SEV_NOT_SUPPORTED;
}
}
static u8 drm_to_xe_ras_component(u8 component)
{
switch (component) {
case DRM_XE_RAS_ERR_COMP_CORE_COMPUTE:
return XE_RAS_COMP_CORE_COMPUTE;
case DRM_XE_RAS_ERR_COMP_SOC_INTERNAL:
return XE_RAS_COMP_SOC_INTERNAL;
case DRM_XE_RAS_ERR_COMP_DEVICE_MEMORY:
return XE_RAS_COMP_DEVICE_MEMORY;
case DRM_XE_RAS_ERR_COMP_PCIE:
return XE_RAS_COMP_PCIE;
case DRM_XE_RAS_ERR_COMP_FABRIC:
return XE_RAS_COMP_FABRIC;
default:
return XE_RAS_COMP_NOT_SUPPORTED;
}
}
static inline const char *sev_to_str(u8 severity)
{
if (severity >= XE_RAS_SEV_MAX)
@ -91,3 +124,61 @@ void xe_ras_counter_threshold_crossed(struct xe_device *xe,
comp_to_str(component), sev_to_str(severity));
}
}
static int get_counter(struct xe_device *xe, struct xe_ras_error_class *counter, u32 *value)
{
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;
request.counter = *counter;
xe_sysctrl_create_command(&command, XE_SYSCTRL_GROUP_GFSP, XE_SYSCTRL_CMD_GET_COUNTER,
&request, sizeof(request), &response, sizeof(response));
ret = xe_sysctrl_send_command(&xe->sc, &command, &rlen);
if (ret) {
xe_err(xe, "sysctrl: failed to get counter %d\n", ret);
return ret;
}
if (rlen != sizeof(response)) {
xe_err(xe, "sysctrl: unexpected get counter response length %zu (expected %zu)\n",
rlen, sizeof(response));
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));
return 0;
}
/**
* xe_ras_get_counter() - Get error counter value
* @xe: Xe device instance
* @severity: Error severity to be queried (&enum drm_xe_ras_error_severity)
* @component: Error component to be queried (&enum drm_xe_ras_error_component)
* @value: Counter value
*
* This function retrieves the value of a specific error counter based on
* the error severity and component.
*
* Return: 0 on success, negative error code on failure.
*/
int xe_ras_get_counter(struct xe_device *xe, u8 severity, u8 component, u32 *value)
{
struct xe_ras_error_class counter = {0};
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);
}

View File

@ -6,10 +6,13 @@
#ifndef _XE_RAS_H_
#define _XE_RAS_H_
#include <linux/types.h>
struct xe_device;
struct xe_sysctrl_event_response;
void xe_ras_counter_threshold_crossed(struct xe_device *xe,
struct xe_sysctrl_event_response *response);
int xe_ras_get_counter(struct xe_device *xe, u8 severity, u8 component, u32 *value);
#endif

View File

@ -70,4 +70,30 @@ struct xe_ras_threshold_crossed {
struct xe_ras_error_class counters[XE_RAS_NUM_COUNTERS];
} __packed;
/**
* struct xe_ras_get_counter_request - Request structure for get counter
*/
struct xe_ras_get_counter_request {
/** @counter: Error counter to be queried */
struct xe_ras_error_class counter;
/** @reserved: Reserved for future use */
u32 reserved;
} __packed;
/**
* struct xe_ras_get_counter_response - Response structure for get counter
*/
struct xe_ras_get_counter_response {
/** @counter: Error counter that was queried */
struct xe_ras_error_class counter;
/** @value: Current counter value */
u32 value;
/** @timestamp: Timestamp when counter was last updated */
u64 timestamp;
/** @threshold: Threshold value for the counter */
u32 threshold;
/** @reserved: Reserved */
u32 reserved[57];
} __packed;
#endif

View File

@ -293,6 +293,34 @@ static int sysctrl_send_command(struct xe_sysctrl *sc,
return 0;
}
/**
* xe_sysctrl_create_command() - Create system controller command
* @command: Sysctrl command structure
* @group_id: Command group ID
* @cmd_id: Command ID
* @request: Pointer to request buffer (can be NULL)
* @request_len: Size of request buffer
* @response: Pointer to response buffer
* @response_len: Size of response buffer
*
* Helper function to create sysctrl command to be sent via %xe_sysctrl_send_command()
*/
void xe_sysctrl_create_command(struct xe_sysctrl_mailbox_command *command, u8 group_id, u8 cmd_id,
void *request, size_t request_len, void *response,
size_t response_len)
{
struct xe_sysctrl_app_msg_hdr header = {0};
header.data = FIELD_PREP(APP_HDR_GROUP_ID_MASK, group_id) |
FIELD_PREP(APP_HDR_COMMAND_MASK, cmd_id);
command->header = header;
command->data_in = request;
command->data_in_len = request_len;
command->data_out = response;
command->data_out_len = response_len;
}
/**
* xe_sysctrl_mailbox_init - Initialize System Controller mailbox interface
* @sc: System controller structure

View File

@ -23,6 +23,9 @@ struct xe_sysctrl_mailbox_command;
#define XE_SYSCTRL_APP_HDR_VERSION(hdr) \
FIELD_GET(APP_HDR_VERSION_MASK, (hdr)->data)
void xe_sysctrl_create_command(struct xe_sysctrl_mailbox_command *command, u8 group_id, u8 cmd_id,
void *request, size_t request_len, void *response,
size_t response_len);
void xe_sysctrl_mailbox_init(struct xe_sysctrl *sc);
int xe_sysctrl_send_command(struct xe_sysctrl *sc,
struct xe_sysctrl_mailbox_command *cmd,

View File

@ -22,9 +22,11 @@ enum xe_sysctrl_group {
/**
* enum xe_sysctrl_gfsp_cmd - Commands supported by GFSP group
*
* @XE_SYSCTRL_CMD_GET_COUNTER: Get error counter value
* @XE_SYSCTRL_CMD_GET_PENDING_EVENT: Retrieve pending event
*/
enum xe_sysctrl_gfsp_cmd {
XE_SYSCTRL_CMD_GET_COUNTER = 0x03,
XE_SYSCTRL_CMD_GET_PENDING_EVENT = 0x07,
};