#include "regs/xe_sysctrl_regs.h"
#include "xe_device.h"
#include "xe_mmio.h"
+#include "xe_pm.h"
#include "xe_soc_remapper.h"
#include "xe_sysctrl.h"
#include "xe_sysctrl_mailbox.h"
static void xe_sysctrl_work(struct work_struct *work)
{
+ struct xe_sysctrl *sc = container_of(work, struct xe_sysctrl, work);
+ struct xe_device *xe = sc_to_xe(sc);
+
+ guard(xe_pm_runtime)(xe);
+ xe_sysctrl_event(sc);
}
/**
if (ret)
return ret;
+ ret = devm_mutex_init(xe->drm.dev, &sc->event_lock);
+ if (ret)
+ return ret;
+
xe->soc_remapper.set_sysctrl_region(xe, SYSCTRL_MAILBOX_INDEX);
xe_sysctrl_mailbox_init(sc);
INIT_WORK(&sc->work, xe_sysctrl_work);
--- /dev/null
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2026 Intel Corporation
+ */
+
+#include "xe_device.h"
+#include "xe_irq.h"
+#include "xe_printk.h"
+#include "xe_sysctrl.h"
+#include "xe_sysctrl_event_types.h"
+#include "xe_sysctrl_mailbox.h"
+#include "xe_sysctrl_mailbox_types.h"
+
+static void get_pending_event(struct xe_sysctrl *sc, struct xe_sysctrl_mailbox_command *command)
+{
+ struct xe_sysctrl_event_response *response = command->data_out;
+ struct xe_device *xe = sc_to_xe(sc);
+ u32 count = XE_SYSCTRL_EVENT_FLOOD;
+ size_t len;
+ int ret;
+
+ do {
+ memset(response, 0, sizeof(*response));
+
+ ret = xe_sysctrl_send_command(sc, command, &len);
+ if (ret) {
+ xe_err(xe, "sysctrl: failed to get pending event %d\n", ret);
+ return;
+ }
+
+ if (len != sizeof(*response)) {
+ xe_err(xe, "sysctrl: unexpected event response length %zu (expected %zu)\n",
+ len, sizeof(*response));
+ return;
+ }
+
+ if (response->event == XE_SYSCTRL_EVENT_THRESHOLD_CROSSED)
+ xe_warn(xe, "[RAS]: counter threshold crossed\n");
+ else
+ xe_warn(xe, "sysctrl: unexpected event %#x\n", response->event);
+
+ if (!--count) {
+ xe_err(xe, "sysctrl: event flooding\n");
+ return;
+ }
+
+ xe_dbg(xe, "sysctrl: %u events pending\n", response->count);
+ } while (response->count);
+}
+
+static void event_request_prepare(struct xe_device *xe, struct xe_sysctrl_app_msg_hdr *header,
+ struct xe_sysctrl_event_request *request)
+{
+ struct pci_dev *pdev = to_pci_dev(xe->drm.dev);
+
+ header->data = REG_FIELD_PREP(APP_HDR_GROUP_ID_MASK, XE_SYSCTRL_GROUP_GFSP) |
+ REG_FIELD_PREP(APP_HDR_COMMAND_MASK, XE_SYSCTRL_CMD_GET_PENDING_EVENT);
+
+ request->vector = xe_device_has_msix(xe) ? XE_IRQ_DEFAULT_MSIX : 0;
+ request->fn = PCI_FUNC(pdev->devfn);
+}
+
+/**
+ * xe_sysctrl_event() - Handler for System Controller events
+ * @sc: System Controller instance
+ *
+ * Handle events generated by System Controller.
+ */
+void xe_sysctrl_event(struct xe_sysctrl *sc)
+{
+ struct xe_sysctrl_mailbox_command command = {};
+ struct xe_sysctrl_event_response response = {};
+ struct xe_sysctrl_event_request request = {};
+ struct xe_sysctrl_app_msg_hdr header = {};
+
+ xe_device_assert_mem_access(sc_to_xe(sc));
+ event_request_prepare(sc_to_xe(sc), &header, &request);
+
+ command.header = header;
+ command.data_in = &request;
+ command.data_in_len = sizeof(request);
+ command.data_out = &response;
+ command.data_out_len = sizeof(response);
+
+ guard(mutex)(&sc->event_lock);
+ get_pending_event(sc, &command);
+}
--- /dev/null
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright © 2026 Intel Corporation
+ */
+
+#ifndef _XE_SYSCTRL_EVENT_TYPES_H_
+#define _XE_SYSCTRL_EVENT_TYPES_H_
+
+#include <linux/types.h>
+
+#define XE_SYSCTRL_EVENT_DATA_LEN 59
+
+/* Modify as needed */
+#define XE_SYSCTRL_EVENT_FLOOD 16
+
+/**
+ * enum xe_sysctrl_event - Events reported by System Controller
+ *
+ * @XE_SYSCTRL_EVENT_THRESHOLD_CROSSED: Error counter threshold crossed
+ */
+enum xe_sysctrl_event {
+ XE_SYSCTRL_EVENT_THRESHOLD_CROSSED = 0x01,
+};
+
+/**
+ * struct xe_sysctrl_event_request - Request structure for pending event
+ */
+struct xe_sysctrl_event_request {
+ /** @vector: MSI-X vector that was triggered */
+ u32 vector;
+ /** @fn: Function index (0-7) of PCIe device */
+ u32 fn:8;
+ /** @reserved: Reserved for future use */
+ u32 reserved:24;
+ /** @reserved1: Reserved for future use */
+ u32 reserved1[2];
+} __packed;
+
+/**
+ * struct xe_sysctrl_event_response - Response structure for pending event
+ */
+struct xe_sysctrl_event_response {
+ /** @count: Pending event count after this response */
+ u32 count;
+ /** @event: Pending event type */
+ u32 event;
+ /** @timestamp: Timestamp of most recent event */
+ u64 timestamp;
+ /** @extended: Event has extended payload */
+ u32 extended:1;
+ /** @reserved: Reserved for future use */
+ u32 reserved:31;
+ /** @data: Generic event data */
+ u32 data[XE_SYSCTRL_EVENT_DATA_LEN];
+} __packed;
+
+#endif /* _XE_SYSCTRL_EVENT_TYPES_H_ */