*/
#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 {
};
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)
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);
+}
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
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