xref: /linux/drivers/gpu/drm/xe/xe_ras.c (revision 570f7e331f5febb30f1384817463c7e42b65ca7d)
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_survivability_mode.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 #define CORE_COMPUTE_UNCORR_TYPE	GENMASK(26, 25)
18 /*
19  * Uncorrectable error type for core compute errors.
20  * 0 - Correctable Error
21  * 1 - Local Uncorrectable Error
22  * 2 - Global Uncorrectable Error
23  * 3 - Informational Error
24  */
25 #define  GLOBAL_UNCORR_ERROR		2
26 
27 /* Severity of detected errors  */
28 enum xe_ras_severity {
29 	XE_RAS_SEV_NOT_SUPPORTED = 0,
30 	XE_RAS_SEV_CORRECTABLE,
31 	XE_RAS_SEV_UNCORRECTABLE,
32 	XE_RAS_SEV_INFORMATIONAL,
33 	XE_RAS_SEV_MAX
34 };
35 
36 /* Major IP blocks/components where errors can originate */
37 enum xe_ras_component {
38 	XE_RAS_COMP_NOT_SUPPORTED = 0,
39 	XE_RAS_COMP_DEVICE_MEMORY,
40 	XE_RAS_COMP_CORE_COMPUTE,
41 	XE_RAS_COMP_RESERVED,
42 	XE_RAS_COMP_PCIE,
43 	XE_RAS_COMP_FABRIC,
44 	XE_RAS_COMP_SOC_INTERNAL,
45 	XE_RAS_COMP_MAX
46 };
47 
48 /* RAS response status codes */
49 enum xe_ras_response_status {
50 	XE_RAS_STATUS_SUCCESS = 0,
51 	XE_RAS_STATUS_INVALID_PARAM,
52 	XE_RAS_STATUS_OP_NOT_SUPPORTED,
53 	XE_RAS_STATUS_TIMEOUT,
54 	XE_RAS_STATUS_HARDWARE_FAILURE,
55 	XE_RAS_STATUS_INSUFFICIENT_RESOURCES,
56 	XE_RAS_STATUS_MAX
57 };
58 
59 /* GPU health values */
60 enum xe_ras_health {
61 	XE_RAS_HEALTH_OK = 0,
62 	XE_RAS_HEALTH_WARNING,
63 	XE_RAS_HEALTH_CRITICAL,
64 	XE_RAS_HEALTH_MAX
65 };
66 
67 static const char *const xe_ras_severities[] = {
68 	[XE_RAS_SEV_NOT_SUPPORTED]		= "Not Supported",
69 	[XE_RAS_SEV_CORRECTABLE]		= "Correctable Error",
70 	[XE_RAS_SEV_UNCORRECTABLE]		= "Uncorrectable Error",
71 	[XE_RAS_SEV_INFORMATIONAL]		= "Informational Error",
72 };
73 static_assert(ARRAY_SIZE(xe_ras_severities) == XE_RAS_SEV_MAX);
74 
75 static const char *const xe_ras_components[] = {
76 	[XE_RAS_COMP_NOT_SUPPORTED]		= "Not Supported",
77 	[XE_RAS_COMP_DEVICE_MEMORY]		= "Device Memory",
78 	[XE_RAS_COMP_CORE_COMPUTE]		= "Core Compute",
79 	[XE_RAS_COMP_RESERVED]			= "Reserved",
80 	[XE_RAS_COMP_PCIE]			= "PCIe",
81 	[XE_RAS_COMP_FABRIC]			= "Fabric",
82 	[XE_RAS_COMP_SOC_INTERNAL]		= "SoC Internal",
83 };
84 static_assert(ARRAY_SIZE(xe_ras_components) == XE_RAS_COMP_MAX);
85 
86 static const char * const gpu_health_states[] = {
87 	[XE_RAS_HEALTH_OK]		= "ok",
88 	[XE_RAS_HEALTH_WARNING]		= "warning",
89 	[XE_RAS_HEALTH_CRITICAL]	= "critical",
90 };
91 static_assert(ARRAY_SIZE(gpu_health_states) == XE_RAS_HEALTH_MAX);
92 
93 static u8 drm_to_xe_ras_severity(u8 severity)
94 {
95 	switch (severity) {
96 	case DRM_XE_RAS_ERR_SEV_CORRECTABLE:
97 		return XE_RAS_SEV_CORRECTABLE;
98 	case DRM_XE_RAS_ERR_SEV_UNCORRECTABLE:
99 		return XE_RAS_SEV_UNCORRECTABLE;
100 	default:
101 		return XE_RAS_SEV_NOT_SUPPORTED;
102 	}
103 }
104 
105 static u8 drm_to_xe_ras_component(u8 component)
106 {
107 	switch (component) {
108 	case DRM_XE_RAS_ERR_COMP_CORE_COMPUTE:
109 		return XE_RAS_COMP_CORE_COMPUTE;
110 	case DRM_XE_RAS_ERR_COMP_SOC_INTERNAL:
111 		return XE_RAS_COMP_SOC_INTERNAL;
112 	case DRM_XE_RAS_ERR_COMP_DEVICE_MEMORY:
113 		return XE_RAS_COMP_DEVICE_MEMORY;
114 	case DRM_XE_RAS_ERR_COMP_PCIE:
115 		return XE_RAS_COMP_PCIE;
116 	case DRM_XE_RAS_ERR_COMP_FABRIC:
117 		return XE_RAS_COMP_FABRIC;
118 	default:
119 		return XE_RAS_COMP_NOT_SUPPORTED;
120 	}
121 }
122 
123 static int ras_status_to_errno(u32 status)
124 {
125 	switch (status) {
126 	case XE_RAS_STATUS_SUCCESS:
127 		return 0;
128 	case XE_RAS_STATUS_INVALID_PARAM:
129 		return -EINVAL;
130 	case XE_RAS_STATUS_OP_NOT_SUPPORTED:
131 		return -EOPNOTSUPP;
132 	case XE_RAS_STATUS_TIMEOUT:
133 		return -ETIMEDOUT;
134 	case XE_RAS_STATUS_HARDWARE_FAILURE:
135 		return -EIO;
136 	case XE_RAS_STATUS_INSUFFICIENT_RESOURCES:
137 		return -ENOSPC;
138 	default:
139 		return -EPROTO;
140 	}
141 }
142 
143 static inline const char *sev_to_str(u8 severity)
144 {
145 	if (severity >= XE_RAS_SEV_MAX)
146 		severity = XE_RAS_SEV_NOT_SUPPORTED;
147 
148 	return xe_ras_severities[severity];
149 }
150 
151 static inline const char *comp_to_str(u8 component)
152 {
153 	if (component >= XE_RAS_COMP_MAX)
154 		component = XE_RAS_COMP_NOT_SUPPORTED;
155 
156 	return xe_ras_components[component];
157 }
158 
159 static struct pci_dev *find_usp_dev(struct pci_dev *pdev)
160 {
161 	struct pci_dev *vsp;
162 
163 	/*
164 	 * Device Hierarchy:
165 	 *
166 	 * Upstream Switch Port (USP) --> Virtual Switch Port (VSP) --> SGunit (GPU endpoint)
167 	 */
168 	vsp = pci_upstream_bridge(pdev);
169 	if (!vsp)
170 		return NULL;
171 
172 	return pci_upstream_bridge(vsp);
173 }
174 
175 static void ras_usp_aer_init(struct xe_device *xe)
176 {
177 	struct pci_dev *pdev = to_pci_dev(xe->drm.dev);
178 	struct pci_dev *usp;
179 	u16 aer_cap;
180 	u32 status;
181 
182 	usp = find_usp_dev(pdev);
183 	if (!usp)
184 		return;
185 
186 	aer_cap = pci_find_ext_capability(usp, PCI_EXT_CAP_ID_ERR);
187 	if (!aer_cap) {
188 		dev_warn(&usp->dev, "AER capability unavailable\n");
189 		return;
190 	}
191 
192 	/*
193 	 * Clear any stale Uncorrectable Internal Error Status event in Uncorrectable Error
194 	 * Status Register.
195 	 */
196 	pci_read_config_dword(usp, aer_cap + PCI_ERR_UNCOR_STATUS, &status);
197 	if (status & PCI_ERR_UNC_INTN)
198 		pci_write_config_dword(usp, aer_cap + PCI_ERR_UNCOR_STATUS, PCI_ERR_UNC_INTN);
199 
200 	/*
201 	 * All errors are steered to USP which is a PCIe AER Compliant device.
202 	 * Downgrade all the errors to non-fatal to prevent PCIe bus driver
203 	 * from triggering a Secondary Bus Reset (SBR). This allows error
204 	 * detection, containment and recovery in the driver.
205 	 *
206 	 * The Uncorrectable Error Severity Register has the 'Uncorrectable
207 	 * Internal Error Severity' set to fatal by default. Set this to
208 	 * non-fatal and unmask the error.
209 	 */
210 
211 	/* Downgrade Uncorrectable Internal Error to non-fatal */
212 	pci_clear_and_set_config_dword(usp, aer_cap + PCI_ERR_UNCOR_SEVER, PCI_ERR_UNC_INTN, 0);
213 
214 	/* Unmask Uncorrectable Internal Error */
215 	pci_clear_and_set_config_dword(usp, aer_cap + PCI_ERR_UNCOR_MASK, PCI_ERR_UNC_INTN, 0);
216 
217 	pci_save_state(usp);
218 	dev_dbg(&usp->dev, "Uncorrectable Internal Errors downgraded and unmasked\n");
219 }
220 
221 static u8 handle_core_compute_errors(struct xe_ras_error_array *arr)
222 {
223 	struct xe_ras_compute_error *error_info = (void *)arr->details;
224 	u8 uncorr_type;
225 
226 	uncorr_type = FIELD_GET(CORE_COMPUTE_UNCORR_TYPE, error_info->log_header);
227 
228 	/* Request a reset if error is global */
229 	if (uncorr_type == GLOBAL_UNCORR_ERROR)
230 		return XE_RAS_RECOVERY_ACTION_RESET;
231 
232 	/*
233 	 * No action needed for other errors.
234 	 * Local errors are recovered using an engine reset by GuC.
235 	 */
236 	return XE_RAS_RECOVERY_ACTION_RECOVERED;
237 }
238 
239 static u8 handle_soc_internal_errors(struct xe_device *xe, struct xe_ras_error_array *arr)
240 {
241 	struct xe_ras_soc_error *info = (void *)arr->details;
242 	struct xe_ras_soc_error_source *source = &info->source;
243 	struct xe_ras_error_class *counter = &arr->counter;
244 
245 	if (source->csc) {
246 		struct xe_ras_csc_error *csc_error = (void *)info->details;
247 
248 		/*
249 		 * CSC uncorrectable errors are classified as hardware errors and firmware errors.
250 		 * CSC firmware errors are critical errors that can be recovered only by firmware
251 		 * update via SPI driver. On a CSC firmware error, PCODE enables FDO mode and sets
252 		 * the bit in the capability register. On receiving this error, the driver enables
253 		 * runtime survivability mode which notifies userspace that a firmware update
254 		 * is required.
255 		 */
256 		if (csc_error->hec_fw_error) {
257 			xe_err(xe, "[RAS]: CSC %s detected: 0x%x\n",
258 			       sev_to_str(counter->common.severity),
259 			       csc_error->hec_fw_error);
260 			xe_survivability_mode_runtime_enable(xe);
261 			return XE_RAS_RECOVERY_ACTION_DISCONNECT;
262 		}
263 	} else if (source->ieh) {
264 		struct xe_ras_ieh_error *ieh_error = (void *)info->details;
265 
266 		if (ieh_error->global_error_status & XE_RAS_SOC_IEH_PUNIT) {
267 			xe_err(xe, "[RAS]: PUNIT %s detected: 0x%x\n",
268 			       sev_to_str(counter->common.severity),
269 			       ieh_error->global_error_status);
270 			/* TODO: Add PUNIT error handling */
271 			return XE_RAS_RECOVERY_ACTION_DISCONNECT;
272 		}
273 	}
274 
275 	/* For other SoC internal errors, request a reset as recovery mechanism */
276 	return XE_RAS_RECOVERY_ACTION_RESET;
277 }
278 
279 static u8 handle_device_memory_errors(struct xe_device *xe, struct xe_ras_error_array *arr)
280 {
281 	struct xe_ras_memory_error *info = (void *)arr->details;
282 
283 	/*
284 	 * For memory errors, the recovery action depends on the error category
285 	 *
286 	 * TODO: Double-bit ECC errors: Page offlining
287 	 * Poison and data parity errors: Log only
288 	 * For any other memory errors, request a reset as recovery mechanism
289 	 */
290 	switch (info->category) {
291 	case XE_RAS_MEMORY_POISON:
292 		xe_info(xe, "[RAS]: Poison error detected\n");
293 		break;
294 	case XE_RAS_MEMORY_DATA_PARITY:
295 		xe_info(xe, "[RAS]: Data parity error detected\n");
296 		break;
297 	case XE_RAS_MEMORY_DB_ECC:
298 		xe_info(xe, "[RAS]: Double-bit ECC error detected at sw address 0x%llx\n",
299 			info->sw_address);
300 		/* TODO: Add page offlining for Double-bit ECC error */
301 		fallthrough;
302 	default:
303 		return XE_RAS_RECOVERY_ACTION_RESET;
304 	}
305 
306 	return XE_RAS_RECOVERY_ACTION_RECOVERED;
307 }
308 
309 void xe_ras_counter_threshold_crossed(struct xe_device *xe,
310 				      struct xe_sysctrl_event_response *response)
311 {
312 	struct xe_ras_threshold_crossed *pending = (void *)&response->data;
313 	struct xe_ras_error_class *errors = pending->counters;
314 	u32 id, ncounters = pending->ncounters;
315 
316 	BUILD_BUG_ON(sizeof(response->data) < sizeof(*pending));
317 	xe_device_assert_mem_access(xe);
318 
319 	if (!ncounters || ncounters > XE_RAS_NUM_COUNTERS)
320 		xe_err(xe, "sysctrl: unexpected counter threshold crossed %u\n", ncounters);
321 	else
322 		xe_warn(xe, "[RAS]: counter threshold crossed, %u new errors\n", ncounters);
323 
324 	for (id = 0; id < ncounters && id < XE_RAS_NUM_COUNTERS; id++) {
325 		u8 severity, component;
326 
327 		severity = errors[id].common.severity;
328 		component = errors[id].common.component;
329 
330 		xe_warn(xe, "[RAS]: %s %s detected\n",
331 			comp_to_str(component), sev_to_str(severity));
332 	}
333 }
334 
335 static int get_counter(struct xe_device *xe, struct xe_ras_error_class *counter, u32 *value)
336 {
337 	struct xe_ras_get_counter_response response = {0};
338 	struct xe_ras_get_counter_request request = {0};
339 	struct xe_sysctrl_mailbox_command command = {0};
340 	struct xe_ras_error_common *common;
341 	size_t rlen;
342 	int ret;
343 
344 	request.counter = *counter;
345 
346 	xe_sysctrl_create_command(&command, XE_SYSCTRL_GROUP_GFSP, XE_SYSCTRL_CMD_GET_COUNTER,
347 				  &request, sizeof(request), &response, sizeof(response));
348 
349 	ret = xe_sysctrl_send_command(&xe->sc, &command, &rlen);
350 	if (ret) {
351 		xe_err(xe, "sysctrl: failed to get counter %d\n", ret);
352 		return ret;
353 	}
354 
355 	if (rlen != sizeof(response)) {
356 		xe_err(xe, "sysctrl: unexpected get counter response length %zu (expected %zu)\n",
357 		       rlen, sizeof(response));
358 		return -EIO;
359 	}
360 
361 	common = &response.counter.common;
362 	*value = response.value;
363 
364 	xe_dbg(xe, "[RAS]: get counter %u for %s %s\n", *value, comp_to_str(common->component),
365 	       sev_to_str(common->severity));
366 
367 	return 0;
368 }
369 
370 /**
371  * xe_ras_process_errors() - Process and contain hardware errors
372  * @xe: xe device instance
373  *
374  * Get error details from system controller and return recovery
375  * method.
376  *
377  * Returns: recovery action to be taken
378  */
379 enum xe_ras_recovery_action xe_ras_process_errors(struct xe_device *xe)
380 {
381 	struct xe_sysctrl_mailbox_command command = {0};
382 	enum xe_ras_recovery_action final_action;
383 	u32 remaining = XE_SYSCTRL_FLOOD_LIMIT;
384 	struct xe_ras_get_soc_error response;
385 	size_t rlen;
386 	int ret;
387 
388 	if (!xe->info.has_sysctrl)
389 		return XE_RAS_RECOVERY_ACTION_RESET;
390 
391 	/* Default action */
392 	final_action = XE_RAS_RECOVERY_ACTION_RECOVERED;
393 
394 	xe_sysctrl_create_command(&command, XE_SYSCTRL_GROUP_GFSP, XE_SYSCTRL_CMD_GET_SOC_ERROR,
395 				  NULL, 0, &response, sizeof(response));
396 
397 	do {
398 		memset(&response, 0, sizeof(response));
399 
400 		ret = xe_sysctrl_send_command(&xe->sc, &command, &rlen);
401 		if (ret) {
402 			xe_err(xe, "sysctrl: failed to get soc error %d\n", ret);
403 			goto err;
404 		}
405 
406 		if (rlen != sizeof(response)) {
407 			xe_err(xe, "sysctrl: unexpected get soc error response length %zu (expected %zu)\n",
408 			       rlen, sizeof(response));
409 			goto err;
410 		}
411 
412 		/* Report if number of errors exceeds the maximum errors supported */
413 		if (response.num_errors > XE_RAS_NUM_ERROR_ARR)
414 			xe_err(xe, "sysctrl: number of errors received %d out of bound (%d)\n",
415 			       response.num_errors, XE_RAS_NUM_ERROR_ARR);
416 
417 		for (int i = 0; i < response.num_errors && i < XE_RAS_NUM_ERROR_ARR; i++) {
418 			struct xe_ras_error_array *arr = &response.arr[i];
419 			enum xe_ras_recovery_action action;
420 			u8 component, severity;
421 
422 			component = arr->counter.common.component;
423 			severity = arr->counter.common.severity;
424 
425 			xe_info(xe, "[RAS]: %s %s detected\n", comp_to_str(component),
426 				sev_to_str(severity));
427 
428 			switch (component) {
429 			case XE_RAS_COMP_CORE_COMPUTE:
430 				action = handle_core_compute_errors(arr);
431 				break;
432 			case XE_RAS_COMP_SOC_INTERNAL:
433 				action = handle_soc_internal_errors(xe, arr);
434 				break;
435 			case XE_RAS_COMP_DEVICE_MEMORY:
436 				action = handle_device_memory_errors(xe, arr);
437 				break;
438 			default:
439 				/* For any other component, reset */
440 				action = XE_RAS_RECOVERY_ACTION_RESET;
441 				break;
442 			}
443 
444 			/* Process and log all errors and then trigger highest recovery action */
445 			if (action > final_action)
446 				final_action = action;
447 		}
448 
449 		/* Treat flooding as a system controller error */
450 		if (!--remaining) {
451 			xe_err(xe, "[RAS]: sysctrl: get soc error response flooding\n");
452 			goto err;
453 		}
454 
455 	} while (response.additional_errors);
456 
457 	return final_action;
458 
459 err:
460 	return XE_RAS_RECOVERY_ACTION_RESET;
461 }
462 
463 /**
464  * xe_ras_get_counter() - Get error counter value
465  * @xe: Xe device instance
466  * @severity: Error severity to be queried (&enum drm_xe_ras_error_severity)
467  * @component: Error component to be queried (&enum drm_xe_ras_error_component)
468  * @value: Counter value
469  *
470  * This function retrieves the value of a specific error counter based on
471  * the error severity and component.
472  *
473  * Return: 0 on success, negative error code on failure.
474  */
475 int xe_ras_get_counter(struct xe_device *xe, u8 severity, u8 component, u32 *value)
476 {
477 	struct xe_ras_error_class counter = {0};
478 
479 	counter.common.severity = drm_to_xe_ras_severity(severity);
480 	counter.common.component = drm_to_xe_ras_component(component);
481 
482 	guard(xe_pm_runtime)(xe);
483 	return get_counter(xe, &counter, value);
484 }
485 
486 /**
487  * xe_ras_clear_counter() - Clear error counter value
488  * @xe: Xe device instance
489  * @severity: Error severity to be cleared (&enum drm_xe_ras_error_severity)
490  * @component: Error component to be cleared (&enum drm_xe_ras_error_component)
491  *
492  * This function clears the value of a specific error counter based on
493  * the error severity and component.
494  *
495  * Return: 0 on success, negative error code on failure.
496  */
497 int xe_ras_clear_counter(struct xe_device *xe, u8 severity, u8 component)
498 {
499 	struct xe_ras_clear_counter_response response = {0};
500 	struct xe_ras_clear_counter_request request = {0};
501 	struct xe_sysctrl_mailbox_command command = {0};
502 	struct xe_ras_error_class *counter;
503 	size_t rlen;
504 	int ret;
505 
506 	counter = &request.counter;
507 	counter->common.severity = drm_to_xe_ras_severity(severity);
508 	counter->common.component = drm_to_xe_ras_component(component);
509 
510 	xe_sysctrl_create_command(&command, XE_SYSCTRL_GROUP_GFSP, XE_SYSCTRL_CMD_CLEAR_COUNTER,
511 				  &request, sizeof(request), &response, sizeof(response));
512 
513 	guard(xe_pm_runtime)(xe);
514 	ret = xe_sysctrl_send_command(&xe->sc, &command, &rlen);
515 	if (ret) {
516 		xe_err(xe, "sysctrl: failed to clear counter %d\n", ret);
517 		return ret;
518 	}
519 
520 	if (rlen != sizeof(response)) {
521 		xe_err(xe, "sysctrl: unexpected clear counter response length %zu (expected %zu)\n",
522 		       rlen, sizeof(response));
523 		return -EIO;
524 	}
525 
526 	ret = ras_status_to_errno(response.status);
527 	if (ret) {
528 		xe_err(xe, "sysctrl: clear counter command failed with status %#x\n",
529 		       response.status);
530 		return ret;
531 	}
532 
533 	counter = &response.counter;
534 
535 	xe_dbg(xe, "[RAS]: clear counter for %s %s\n", comp_to_str(counter->common.component),
536 	       sev_to_str(counter->common.severity));
537 
538 	return 0;
539 }
540 
541 static ssize_t gpu_health_show(struct device *dev, struct device_attribute *attr, char *buf)
542 {
543 	struct xe_ras_get_health_response response = {0};
544 	struct xe_sysctrl_mailbox_command command = {0};
545 	struct xe_ras_get_health_request request = {0};
546 	struct xe_device *xe = kdev_to_xe_device(dev);
547 	const char *health;
548 	size_t rlen;
549 	int ret;
550 
551 	xe_sysctrl_create_command(&command, XE_SYSCTRL_GROUP_GFSP, XE_SYSCTRL_CMD_GET_HEALTH,
552 				  &request, sizeof(request), &response, sizeof(response));
553 	guard(xe_pm_runtime)(xe);
554 	ret = xe_sysctrl_send_command(&xe->sc, &command, &rlen);
555 	if (ret) {
556 		xe_err(xe, "sysctrl: failed to get health %d\n", ret);
557 		return ret;
558 	}
559 
560 	if (rlen != sizeof(response)) {
561 		xe_err(xe, "sysctrl: unexpected get health response length %zu (expected %zu)\n",
562 		       rlen, sizeof(response));
563 		return -EIO;
564 	}
565 	if (response.health >= XE_RAS_HEALTH_MAX) {
566 		xe_err(xe, "sysctrl: invalid health state %u\n",
567 		       response.health);
568 		return -EIO;
569 	}
570 
571 	health = gpu_health_states[response.health];
572 
573 	xe_dbg(xe, "[RAS]: get health: %s\n", health);
574 
575 	return sysfs_emit(buf, "%s\n", health);
576 }
577 
578 static ssize_t gpu_health_store(struct device *dev, struct device_attribute *attr,
579 				const char *buf, size_t count)
580 {
581 	struct xe_ras_set_health_response response = {0};
582 	struct xe_sysctrl_mailbox_command command = {0};
583 	struct xe_ras_set_health_request request = {0};
584 	struct xe_device *xe = kdev_to_xe_device(dev);
585 	const char *health;
586 	size_t rlen;
587 	int state;
588 	int ret;
589 
590 	state = sysfs_match_string(gpu_health_states, buf);
591 	if (state < 0)
592 		return -EINVAL;
593 
594 	request.health = state;
595 
596 	xe_sysctrl_create_command(&command, XE_SYSCTRL_GROUP_GFSP, XE_SYSCTRL_CMD_SET_HEALTH,
597 				  &request, sizeof(request), &response, sizeof(response));
598 	guard(xe_pm_runtime)(xe);
599 	ret = xe_sysctrl_send_command(&xe->sc, &command, &rlen);
600 	if (ret) {
601 		xe_err(xe, "sysctrl: failed to set health %d\n", ret);
602 		return ret;
603 	}
604 
605 	if (rlen != sizeof(response)) {
606 		xe_err(xe, "sysctrl: unexpected set health response length %zu (expected %zu)\n",
607 		       rlen, sizeof(response));
608 		return -EIO;
609 	}
610 
611 	ret = ras_status_to_errno(response.status);
612 	if (ret) {
613 		xe_err(xe, "sysctrl: set health command failed with status %#x\n",
614 		       response.status);
615 		return ret;
616 	}
617 
618 	if (response.health >= XE_RAS_HEALTH_MAX) {
619 		xe_err(xe, "sysctrl: invalid health state %u\n",
620 		       response.health);
621 		return -EIO;
622 	}
623 
624 	health = gpu_health_states[response.health];
625 
626 	xe_dbg(xe, "[RAS]: set health: %s\n", health);
627 
628 	return count;
629 }
630 static DEVICE_ATTR_RW(gpu_health);
631 
632 static struct attribute *gpu_health_attrs[] = {
633 	&dev_attr_gpu_health.attr,
634 	NULL
635 };
636 
637 /**
638  * DOC: GPU Health Indicator
639  *
640  * On Intel Xe platforms that support the gpu health indicator interface,
641  * the driver exposes this sysfs attribute for in-band access to the gpu
642  * health state::
643  *
644  *     /sys/bus/pci/devices/<device>/gpu_health
645  *
646  * Reading the attribute is available to all users and returns a single
647  * line containing the current gpu health state, whereas writing is
648  * restricted to administrative users and updates the state to one of the
649  * valid values.
650  *
651  * Management tools and administrators use this interface to query the
652  * current gpu health state (e.g. for telemetry/monitoring) and to
653  * update it - for example, to mark the gpu as ``warning`` or ``critical``
654  * after diagnostics, or reset it back to ``ok`` once remediated.
655  *
656  * The valid values for the gpu health state are:
657  *
658  * - ``ok``
659  *     The gpu is healthy and operating within normal parameters.
660  *
661  * - ``warning``
662  *     The gpu is experiencing minor issues but remains operational.
663  *
664  * - ``critical``
665  *     The gpu is in a critical state and may not be operational.
666  *
667  * See Documentation/ABI/testing/sysfs-driver-intel-xe-ras for the ABI
668  * specification.
669  */
670 static const struct attribute_group gpu_health_group = {
671 	.attrs = gpu_health_attrs,
672 };
673 
674 /**
675  * xe_ras_init - Initialize Xe RAS
676  * @xe: xe device instance
677  *
678  * Initialize Xe RAS
679  */
680 void xe_ras_init(struct xe_device *xe)
681 {
682 	int ret;
683 
684 	xe_drm_ras_init(xe);
685 
686 	if (!xe->info.has_sysctrl)
687 		return;
688 
689 	if (IS_ENABLED(CONFIG_PCIEAER))
690 		ras_usp_aer_init(xe);
691 
692 	ret = devm_device_add_group(xe->drm.dev, &gpu_health_group);
693 	if (ret)
694 		xe_err(xe, "Failed to create GPU health sysfs, err=%d\n", ret);
695 }
696