xref: /linux/drivers/gpu/drm/xe/xe_ras.c (revision 81aa6f190aa0e9ff752fcd0a9eda676458e23133)
1 // SPDX-License-Identifier: MIT
2 /*
3  * Copyright © 2026 Intel Corporation
4  */
5 
6 #include "xe_device.h"
7 #include "xe_drm_ras.h"
8 #include "xe_pm.h"
9 #include "xe_printk.h"
10 #include "xe_ras.h"
11 #include "xe_ras_types.h"
12 #include "xe_sysctrl.h"
13 #include "xe_sysctrl_event_types.h"
14 #include "xe_sysctrl_mailbox.h"
15 #include "xe_sysctrl_mailbox_types.h"
16 
17 /* Severity of detected errors  */
18 enum xe_ras_severity {
19 	XE_RAS_SEV_NOT_SUPPORTED = 0,
20 	XE_RAS_SEV_CORRECTABLE,
21 	XE_RAS_SEV_UNCORRECTABLE,
22 	XE_RAS_SEV_INFORMATIONAL,
23 	XE_RAS_SEV_MAX
24 };
25 
26 /* Major IP blocks/components where errors can originate */
27 enum xe_ras_component {
28 	XE_RAS_COMP_NOT_SUPPORTED = 0,
29 	XE_RAS_COMP_DEVICE_MEMORY,
30 	XE_RAS_COMP_CORE_COMPUTE,
31 	XE_RAS_COMP_RESERVED,
32 	XE_RAS_COMP_PCIE,
33 	XE_RAS_COMP_FABRIC,
34 	XE_RAS_COMP_SOC_INTERNAL,
35 	XE_RAS_COMP_MAX
36 };
37 
38 /* RAS response status codes */
39 enum xe_ras_response_status {
40 	XE_RAS_STATUS_SUCCESS = 0,
41 	XE_RAS_STATUS_INVALID_PARAM,
42 	XE_RAS_STATUS_OP_NOT_SUPPORTED,
43 	XE_RAS_STATUS_TIMEOUT,
44 	XE_RAS_STATUS_HARDWARE_FAILURE,
45 	XE_RAS_STATUS_INSUFFICIENT_RESOURCES,
46 	XE_RAS_STATUS_MAX
47 };
48 
49 static const char *const xe_ras_severities[] = {
50 	[XE_RAS_SEV_NOT_SUPPORTED]		= "Not Supported",
51 	[XE_RAS_SEV_CORRECTABLE]		= "Correctable Error",
52 	[XE_RAS_SEV_UNCORRECTABLE]		= "Uncorrectable Error",
53 	[XE_RAS_SEV_INFORMATIONAL]		= "Informational Error",
54 };
55 static_assert(ARRAY_SIZE(xe_ras_severities) == XE_RAS_SEV_MAX);
56 
57 static const char *const xe_ras_components[] = {
58 	[XE_RAS_COMP_NOT_SUPPORTED]		= "Not Supported",
59 	[XE_RAS_COMP_DEVICE_MEMORY]		= "Device Memory",
60 	[XE_RAS_COMP_CORE_COMPUTE]		= "Core Compute",
61 	[XE_RAS_COMP_RESERVED]			= "Reserved",
62 	[XE_RAS_COMP_PCIE]			= "PCIe",
63 	[XE_RAS_COMP_FABRIC]			= "Fabric",
64 	[XE_RAS_COMP_SOC_INTERNAL]		= "SoC Internal",
65 };
66 static_assert(ARRAY_SIZE(xe_ras_components) == XE_RAS_COMP_MAX);
67 
68 static u8 drm_to_xe_ras_severity(u8 severity)
69 {
70 	switch (severity) {
71 	case DRM_XE_RAS_ERR_SEV_CORRECTABLE:
72 		return XE_RAS_SEV_CORRECTABLE;
73 	case DRM_XE_RAS_ERR_SEV_UNCORRECTABLE:
74 		return XE_RAS_SEV_UNCORRECTABLE;
75 	default:
76 		return XE_RAS_SEV_NOT_SUPPORTED;
77 	}
78 }
79 
80 static u8 drm_to_xe_ras_component(u8 component)
81 {
82 	switch (component) {
83 	case DRM_XE_RAS_ERR_COMP_CORE_COMPUTE:
84 		return XE_RAS_COMP_CORE_COMPUTE;
85 	case DRM_XE_RAS_ERR_COMP_SOC_INTERNAL:
86 		return XE_RAS_COMP_SOC_INTERNAL;
87 	case DRM_XE_RAS_ERR_COMP_DEVICE_MEMORY:
88 		return XE_RAS_COMP_DEVICE_MEMORY;
89 	case DRM_XE_RAS_ERR_COMP_PCIE:
90 		return XE_RAS_COMP_PCIE;
91 	case DRM_XE_RAS_ERR_COMP_FABRIC:
92 		return XE_RAS_COMP_FABRIC;
93 	default:
94 		return XE_RAS_COMP_NOT_SUPPORTED;
95 	}
96 }
97 
98 static int ras_status_to_errno(u32 status)
99 {
100 	switch (status) {
101 	case XE_RAS_STATUS_SUCCESS:
102 		return 0;
103 	case XE_RAS_STATUS_INVALID_PARAM:
104 		return -EINVAL;
105 	case XE_RAS_STATUS_OP_NOT_SUPPORTED:
106 		return -EOPNOTSUPP;
107 	case XE_RAS_STATUS_TIMEOUT:
108 		return -ETIMEDOUT;
109 	case XE_RAS_STATUS_HARDWARE_FAILURE:
110 		return -EIO;
111 	case XE_RAS_STATUS_INSUFFICIENT_RESOURCES:
112 		return -ENOSPC;
113 	default:
114 		return -EPROTO;
115 	}
116 }
117 
118 static inline const char *sev_to_str(u8 severity)
119 {
120 	if (severity >= XE_RAS_SEV_MAX)
121 		severity = XE_RAS_SEV_NOT_SUPPORTED;
122 
123 	return xe_ras_severities[severity];
124 }
125 
126 static inline const char *comp_to_str(u8 component)
127 {
128 	if (component >= XE_RAS_COMP_MAX)
129 		component = XE_RAS_COMP_NOT_SUPPORTED;
130 
131 	return xe_ras_components[component];
132 }
133 
134 static struct pci_dev *find_usp_dev(struct pci_dev *pdev)
135 {
136 	struct pci_dev *vsp;
137 
138 	/*
139 	 * Device Hierarchy:
140 	 *
141 	 * Upstream Switch Port (USP) --> Virtual Switch Port (VSP) --> SGunit (GPU endpoint)
142 	 */
143 	vsp = pci_upstream_bridge(pdev);
144 	if (!vsp)
145 		return NULL;
146 
147 	return pci_upstream_bridge(vsp);
148 }
149 
150 static void ras_usp_aer_init(struct xe_device *xe)
151 {
152 	struct pci_dev *pdev = to_pci_dev(xe->drm.dev);
153 	struct pci_dev *usp;
154 	u16 aer_cap;
155 	u32 status;
156 
157 	usp = find_usp_dev(pdev);
158 	if (!usp)
159 		return;
160 
161 	aer_cap = pci_find_ext_capability(usp, PCI_EXT_CAP_ID_ERR);
162 	if (!aer_cap) {
163 		dev_warn(&usp->dev, "AER capability unavailable\n");
164 		return;
165 	}
166 
167 	/*
168 	 * Clear any stale Uncorrectable Internal Error Status event in Uncorrectable Error
169 	 * Status Register.
170 	 */
171 	pci_read_config_dword(usp, aer_cap + PCI_ERR_UNCOR_STATUS, &status);
172 	if (status & PCI_ERR_UNC_INTN)
173 		pci_write_config_dword(usp, aer_cap + PCI_ERR_UNCOR_STATUS, PCI_ERR_UNC_INTN);
174 
175 	/*
176 	 * All errors are steered to USP which is a PCIe AER Compliant device.
177 	 * Downgrade all the errors to non-fatal to prevent PCIe bus driver
178 	 * from triggering a Secondary Bus Reset (SBR). This allows error
179 	 * detection, containment and recovery in the driver.
180 	 *
181 	 * The Uncorrectable Error Severity Register has the 'Uncorrectable
182 	 * Internal Error Severity' set to fatal by default. Set this to
183 	 * non-fatal and unmask the error.
184 	 */
185 
186 	/* Downgrade Uncorrectable Internal Error to non-fatal */
187 	pci_clear_and_set_config_dword(usp, aer_cap + PCI_ERR_UNCOR_SEVER, PCI_ERR_UNC_INTN, 0);
188 
189 	/* Unmask Uncorrectable Internal Error */
190 	pci_clear_and_set_config_dword(usp, aer_cap + PCI_ERR_UNCOR_MASK, PCI_ERR_UNC_INTN, 0);
191 
192 	pci_save_state(usp);
193 	dev_dbg(&usp->dev, "Uncorrectable Internal Errors downgraded and unmasked\n");
194 }
195 
196 void xe_ras_counter_threshold_crossed(struct xe_device *xe,
197 				      struct xe_sysctrl_event_response *response)
198 {
199 	struct xe_ras_threshold_crossed *pending = (void *)&response->data;
200 	struct xe_ras_error_class *errors = pending->counters;
201 	u32 id, ncounters = pending->ncounters;
202 
203 	BUILD_BUG_ON(sizeof(response->data) < sizeof(*pending));
204 	xe_device_assert_mem_access(xe);
205 
206 	if (!ncounters || ncounters > XE_RAS_NUM_COUNTERS)
207 		xe_err(xe, "sysctrl: unexpected counter threshold crossed %u\n", ncounters);
208 	else
209 		xe_warn(xe, "[RAS]: counter threshold crossed, %u new errors\n", ncounters);
210 
211 	for (id = 0; id < ncounters && id < XE_RAS_NUM_COUNTERS; id++) {
212 		u8 severity, component;
213 
214 		severity = errors[id].common.severity;
215 		component = errors[id].common.component;
216 
217 		xe_warn(xe, "[RAS]: %s %s detected\n",
218 			comp_to_str(component), sev_to_str(severity));
219 	}
220 }
221 
222 static int get_counter(struct xe_device *xe, struct xe_ras_error_class *counter, u32 *value)
223 {
224 	struct xe_ras_get_counter_response response = {0};
225 	struct xe_ras_get_counter_request request = {0};
226 	struct xe_sysctrl_mailbox_command command = {0};
227 	struct xe_ras_error_common *common;
228 	size_t rlen;
229 	int ret;
230 
231 	request.counter = *counter;
232 
233 	xe_sysctrl_create_command(&command, XE_SYSCTRL_GROUP_GFSP, XE_SYSCTRL_CMD_GET_COUNTER,
234 				  &request, sizeof(request), &response, sizeof(response));
235 
236 	ret = xe_sysctrl_send_command(&xe->sc, &command, &rlen);
237 	if (ret) {
238 		xe_err(xe, "sysctrl: failed to get counter %d\n", ret);
239 		return ret;
240 	}
241 
242 	if (rlen != sizeof(response)) {
243 		xe_err(xe, "sysctrl: unexpected get counter response length %zu (expected %zu)\n",
244 		       rlen, sizeof(response));
245 		return -EIO;
246 	}
247 
248 	common = &response.counter.common;
249 	*value = response.value;
250 
251 	xe_dbg(xe, "[RAS]: get counter %u for %s %s\n", *value, comp_to_str(common->component),
252 	       sev_to_str(common->severity));
253 
254 	return 0;
255 }
256 
257 /**
258  * xe_ras_get_counter() - Get error counter value
259  * @xe: Xe device instance
260  * @severity: Error severity to be queried (&enum drm_xe_ras_error_severity)
261  * @component: Error component to be queried (&enum drm_xe_ras_error_component)
262  * @value: Counter value
263  *
264  * This function retrieves the value of a specific error counter based on
265  * the error severity and component.
266  *
267  * Return: 0 on success, negative error code on failure.
268  */
269 int xe_ras_get_counter(struct xe_device *xe, u8 severity, u8 component, u32 *value)
270 {
271 	struct xe_ras_error_class counter = {0};
272 
273 	counter.common.severity = drm_to_xe_ras_severity(severity);
274 	counter.common.component = drm_to_xe_ras_component(component);
275 
276 	guard(xe_pm_runtime)(xe);
277 	return get_counter(xe, &counter, value);
278 }
279 
280 /**
281  * xe_ras_clear_counter() - Clear error counter value
282  * @xe: Xe device instance
283  * @severity: Error severity to be cleared (&enum drm_xe_ras_error_severity)
284  * @component: Error component to be cleared (&enum drm_xe_ras_error_component)
285  *
286  * This function clears the value of a specific error counter based on
287  * the error severity and component.
288  *
289  * Return: 0 on success, negative error code on failure.
290  */
291 int xe_ras_clear_counter(struct xe_device *xe, u8 severity, u8 component)
292 {
293 	struct xe_ras_clear_counter_response response = {0};
294 	struct xe_ras_clear_counter_request request = {0};
295 	struct xe_sysctrl_mailbox_command command = {0};
296 	struct xe_ras_error_class *counter;
297 	size_t rlen;
298 	int ret;
299 
300 	counter = &request.counter;
301 	counter->common.severity = drm_to_xe_ras_severity(severity);
302 	counter->common.component = drm_to_xe_ras_component(component);
303 
304 	xe_sysctrl_create_command(&command, XE_SYSCTRL_GROUP_GFSP, XE_SYSCTRL_CMD_CLEAR_COUNTER,
305 				  &request, sizeof(request), &response, sizeof(response));
306 
307 	guard(xe_pm_runtime)(xe);
308 	ret = xe_sysctrl_send_command(&xe->sc, &command, &rlen);
309 	if (ret) {
310 		xe_err(xe, "sysctrl: failed to clear counter %d\n", ret);
311 		return ret;
312 	}
313 
314 	if (rlen != sizeof(response)) {
315 		xe_err(xe, "sysctrl: unexpected clear counter response length %zu (expected %zu)\n",
316 		       rlen, sizeof(response));
317 		return -EIO;
318 	}
319 
320 	ret = ras_status_to_errno(response.status);
321 	if (ret) {
322 		xe_err(xe, "sysctrl: clear counter command failed with status %#x\n",
323 		       response.status);
324 		return ret;
325 	}
326 
327 	counter = &response.counter;
328 
329 	xe_dbg(xe, "[RAS]: clear counter for %s %s\n", comp_to_str(counter->common.component),
330 	       sev_to_str(counter->common.severity));
331 
332 	return 0;
333 }
334 
335 /**
336  * xe_ras_init - Initialize Xe RAS
337  * @xe: xe device instance
338  *
339  * Initialize Xe RAS
340  */
341 void xe_ras_init(struct xe_device *xe)
342 {
343 	if (!xe->info.has_drm_ras)
344 		return;
345 
346 	xe_drm_ras_init(xe);
347 
348 	if (!xe->info.has_sysctrl)
349 		return;
350 
351 	if (IS_ENABLED(CONFIG_PCIEAER))
352 		ras_usp_aer_init(xe);
353 }
354