XE_RAS_COMP_MAX
};
+/* RAS response status codes */
+enum xe_ras_response_status {
+ XE_RAS_STATUS_SUCCESS = 0,
+ XE_RAS_STATUS_INVALID_PARAM,
+ XE_RAS_STATUS_OP_NOT_SUPPORTED,
+ XE_RAS_STATUS_TIMEOUT,
+ XE_RAS_STATUS_HARDWARE_FAILURE,
+ XE_RAS_STATUS_INSUFFICIENT_RESOURCES,
+ XE_RAS_STATUS_MAX
+};
+
static const char *const xe_ras_severities[] = {
[XE_RAS_SEV_NOT_SUPPORTED] = "Not Supported",
[XE_RAS_SEV_CORRECTABLE] = "Correctable Error",
}
}
+static int ras_status_to_errno(u32 status)
+{
+ switch (status) {
+ case XE_RAS_STATUS_SUCCESS:
+ return 0;
+ case XE_RAS_STATUS_INVALID_PARAM:
+ return -EINVAL;
+ case XE_RAS_STATUS_OP_NOT_SUPPORTED:
+ return -EOPNOTSUPP;
+ case XE_RAS_STATUS_TIMEOUT:
+ return -ETIMEDOUT;
+ case XE_RAS_STATUS_HARDWARE_FAILURE:
+ return -EIO;
+ case XE_RAS_STATUS_INSUFFICIENT_RESOURCES:
+ return -ENOSPC;
+ default:
+ return -EPROTO;
+ }
+}
+
static inline const char *sev_to_str(u8 severity)
{
if (severity >= XE_RAS_SEV_MAX)
guard(xe_pm_runtime)(xe);
return get_counter(xe, &counter, value);
}
+
+/**
+ * xe_ras_clear_counter() - Clear error counter value
+ * @xe: Xe device instance
+ * @severity: Error severity to be cleared (&enum drm_xe_ras_error_severity)
+ * @component: Error component to be cleared (&enum drm_xe_ras_error_component)
+ *
+ * This function clears 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_clear_counter(struct xe_device *xe, u8 severity, u8 component)
+{
+ struct xe_ras_clear_counter_response response = {0};
+ struct xe_ras_clear_counter_request request = {0};
+ struct xe_sysctrl_mailbox_command command = {0};
+ struct xe_ras_error_class *counter;
+ size_t rlen;
+ 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_CLEAR_COUNTER,
+ &request, sizeof(request), &response, sizeof(response));
+
+ guard(xe_pm_runtime)(xe);
+ ret = xe_sysctrl_send_command(&xe->sc, &command, &rlen);
+ if (ret) {
+ xe_err(xe, "sysctrl: failed to clear counter %d\n", ret);
+ return ret;
+ }
+
+ if (rlen != sizeof(response)) {
+ xe_err(xe, "sysctrl: unexpected clear counter response length %zu (expected %zu)\n",
+ rlen, sizeof(response));
+ return -EIO;
+ }
+
+ ret = ras_status_to_errno(response.status);
+ if (ret) {
+ xe_err(xe, "sysctrl: clear counter command failed with status %#x\n",
+ response.status);
+ return ret;
+ }
+
+ counter = &response.counter;
+
+ xe_dbg(xe, "[RAS]: clear counter for %s %s\n", comp_to_str(counter->common.component),
+ sev_to_str(counter->common.severity));
+
+ return 0;
+}
u32 reserved[57];
} __packed;
+/**
+ * struct xe_ras_clear_counter_request - Request structure for clear counter
+ */
+struct xe_ras_clear_counter_request {
+ /** @counter: Counter class to be cleared */
+ struct xe_ras_error_class counter;
+ /** @reserved: Reserved for future use */
+ u32 reserved;
+} __packed;
+
+/**
+ * struct xe_ras_clear_counter_response - Response structure for clear counter
+ */
+struct xe_ras_clear_counter_response {
+ /** @counter: Counter class that was cleared */
+ struct xe_ras_error_class counter;
+ /** @reserved: Reserved */
+ u32 reserved;
+ /** @timestamp: Timestamp when the counter was cleared */
+ u64 timestamp;
+ /** @status: Status of the clear operation */
+ u32 status;
+ /** @reserved1: Reserved for future use */
+ u32 reserved1[3];
+} __packed;
#endif