drm/xe/ras: Add support for error threshold

System controller allows getting/setting per counter threshold for
correctable errors, which it uses to raise error events to the driver.
Get/set it using the respective mailbox command.

Signed-off-by: Raag Jadav <raag.jadav@intel.com>
Reviewed-by: Riana Tauro <riana.tauro@intel.com>
Link: https://patch.msgid.link/20260818135304.497098-4-raag.jadav@intel.com
Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
This commit is contained in:
Raag Jadav 2026-08-18 19:22:07 +05:30 committed by Rodrigo Vivi
parent b2207d4c4e
commit 5a2b1a5fb4
No known key found for this signature in database
GPG Key ID: FA625F640EEB13CA
4 changed files with 167 additions and 0 deletions

View File

@ -661,6 +661,117 @@ int xe_ras_clear_counter(struct xe_device *xe, u8 severity, u8 component)
return 0;
}
/**
* xe_ras_get_threshold() - Get error counter threshold
* @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)
* @threshold: Counter threshold
*
* This function retrieves the error threshold of a specific counter based on
* severity and component.
*
* Return: 0 on success, negative error code on failure.
*/
int xe_ras_get_threshold(struct xe_device *xe, u8 severity, u8 component, u32 *threshold)
{
struct xe_ras_get_threshold_response response = {};
struct xe_ras_get_threshold_request request = {};
struct xe_sysctrl_mailbox_command command = {};
struct xe_ras_error_class *counter;
size_t len;
int ret;
counter = &request.counter;
counter->common.severity = drm_to_xe_ras_severity(severity);
counter->common.component = drm_to_xe_ras_component(component);
xe_sysctrl_create_command(&command, XE_SYSCTRL_GROUP_GFSP, XE_SYSCTRL_CMD_GET_THRESHOLD,
&request, sizeof(request), &response, sizeof(response));
guard(xe_pm_runtime)(xe);
ret = xe_sysctrl_send_command(&xe->sc, &command, &len);
if (ret) {
xe_err(xe, "sysctrl: failed to get threshold %d\n", ret);
return ret;
}
if (len != sizeof(response)) {
xe_err(xe, "sysctrl: unexpected get threshold response length %zu (expected %zu)\n",
len, sizeof(response));
return -EIO;
}
if (!ras_counter_is_valid(xe, &response.counter))
return -EBADMSG;
counter = &response.counter;
*threshold = response.threshold;
xe_dbg(xe, "[RAS]: get threshold %u for %s %s\n", *threshold,
comp_to_str(counter->common.component), sev_to_str(counter->common.severity));
return 0;
}
/**
* xe_ras_set_threshold() - Set error counter threshold
* @xe: Xe device instance
* @severity: Error severity to be set (&enum drm_xe_ras_error_severity)
* @component: Error component to be set (&enum drm_xe_ras_error_component)
* @threshold: Counter threshold
*
* This function sets the error threshold of a specific counter based on
* severity and component.
*
* Return: 0 on success, negative error code on failure.
*/
int xe_ras_set_threshold(struct xe_device *xe, u8 severity, u8 component, u32 threshold)
{
struct xe_ras_set_threshold_response response = {};
struct xe_ras_set_threshold_request request = {};
struct xe_sysctrl_mailbox_command command = {};
struct xe_ras_error_class *counter;
size_t len;
int ret;
counter = &request.counter;
counter->common.severity = drm_to_xe_ras_severity(severity);
counter->common.component = drm_to_xe_ras_component(component);
request.threshold = threshold;
xe_sysctrl_create_command(&command, XE_SYSCTRL_GROUP_GFSP, XE_SYSCTRL_CMD_SET_THRESHOLD,
&request, sizeof(request), &response, sizeof(response));
guard(xe_pm_runtime)(xe);
ret = xe_sysctrl_send_command(&xe->sc, &command, &len);
if (ret) {
xe_err(xe, "sysctrl: failed to set threshold %d\n", ret);
return ret;
}
if (len != sizeof(response)) {
xe_err(xe, "sysctrl: unexpected set threshold response length %zu (expected %zu)\n",
len, sizeof(response));
return -EIO;
}
ret = ras_status_to_errno(response.status);
if (ret) {
xe_err(xe, "sysctrl: set threshold command failed with status %#x\n",
response.status);
return ret;
}
counter = &response.counter;
if (!ras_counter_is_valid(xe, counter))
return -EBADMSG;
xe_dbg(xe, "[RAS]: set threshold %u for %s %s\n", response.threshold,
comp_to_str(counter->common.component), sev_to_str(counter->common.severity));
return 0;
}
static ssize_t gpu_health_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct xe_ras_get_health_response response = {0};

View File

@ -16,6 +16,8 @@ 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);
int xe_ras_clear_counter(struct xe_device *xe, u8 severity, u8 component);
int xe_ras_get_threshold(struct xe_device *xe, u8 severity, u8 component, u32 *threshold);
int xe_ras_set_threshold(struct xe_device *xe, u8 severity, u8 component, u32 threshold);
void xe_ras_init(struct xe_device *xe);
enum xe_ras_recovery_action xe_ras_process_errors(struct xe_device *xe);

View File

@ -147,6 +147,56 @@ struct xe_ras_clear_counter_response {
u32 reserved1[3];
} __packed;
/**
* struct xe_ras_get_threshold_request - Request structure for get threshold
*/
struct xe_ras_get_threshold_request {
/** @counter: Counter to get threshold for */
struct xe_ras_error_class counter;
/** @reserved: Reserved for future use */
u32 reserved;
} __packed;
/**
* struct xe_ras_get_threshold_response - Response structure for get threshold
*/
struct xe_ras_get_threshold_response {
/** @counter: Counter ID */
struct xe_ras_error_class counter;
/** @threshold: Current threshold of the counter */
u32 threshold;
/** @reserved: Reserved for future use */
u32 reserved[4];
} __packed;
/**
* struct xe_ras_set_threshold_request - Request structure for set threshold
*/
struct xe_ras_set_threshold_request {
/** @counter: Counter to set threshold for */
struct xe_ras_error_class counter;
/** @threshold: Threshold to be set */
u32 threshold;
/** @reserved: Reserved for future use */
u32 reserved;
} __packed;
/**
* struct xe_ras_set_threshold_response - Response structure for set threshold
*/
struct xe_ras_set_threshold_response {
/** @counter: Counter ID */
struct xe_ras_error_class counter;
/** @reserved: Reserved */
u32 reserved;
/** @threshold: Updated threshold */
u32 threshold;
/** @status: Operation status */
u32 status;
/** @reserved1: Reserved for future use */
u32 reserved1[2];
} __packed;
/**
* struct xe_ras_error_array - Details of the error types
*/

View File

@ -25,6 +25,8 @@ enum xe_sysctrl_group {
* @XE_SYSCTRL_CMD_GET_SOC_ERROR: Retrieve basic error information
* @XE_SYSCTRL_CMD_GET_COUNTER: Get error counter value
* @XE_SYSCTRL_CMD_CLEAR_COUNTER: Clear error counter value
* @XE_SYSCTRL_CMD_GET_THRESHOLD: Retrieve error threshold
* @XE_SYSCTRL_CMD_SET_THRESHOLD: Set error threshold
* @XE_SYSCTRL_CMD_GET_PENDING_EVENT: Retrieve pending event
* @XE_SYSCTRL_CMD_GET_HEALTH: Retrieve gpu health
* @XE_SYSCTRL_CMD_SET_HEALTH: Set gpu health
@ -33,6 +35,8 @@ enum xe_sysctrl_gfsp_cmd {
XE_SYSCTRL_CMD_GET_SOC_ERROR = 0x01,
XE_SYSCTRL_CMD_GET_COUNTER = 0x03,
XE_SYSCTRL_CMD_CLEAR_COUNTER = 0x04,
XE_SYSCTRL_CMD_GET_THRESHOLD = 0x05,
XE_SYSCTRL_CMD_SET_THRESHOLD = 0x06,
XE_SYSCTRL_CMD_GET_PENDING_EVENT = 0x07,
XE_SYSCTRL_CMD_GET_HEALTH = 0x0B,
XE_SYSCTRL_CMD_SET_HEALTH = 0x0C,