xref: /linux/drivers/gpu/drm/xe/xe_hw_error.c (revision 570f7e331f5febb30f1384817463c7e42b65ca7d)
1 // SPDX-License-Identifier: MIT
2 /*
3  * Copyright © 2025 Intel Corporation
4  */
5 
6 #include <linux/bitmap.h>
7 
8 #include "regs/xe_gsc_regs.h"
9 #include "regs/xe_hw_error_regs.h"
10 #include "regs/xe_irq_regs.h"
11 
12 #include "xe_debugfs.h"
13 #include "xe_device.h"
14 #include "xe_drm_ras.h"
15 #include "xe_hw_error.h"
16 #include "xe_mmio.h"
17 #include "xe_survivability_mode.h"
18 
19 #define GT_HW_ERROR_MAX_ERR_BITS		16
20 #define HEC_UNCORR_FW_ERR_BITS			4
21 #define XE_RAS_REG_SIZE				32
22 #define XE_SOC_NUM_IEH				2
23 
24 #define PVC_ERROR_MASK_SET(hw_err, err_bit)	((hw_err == HARDWARE_ERROR_CORRECTABLE) ? \
25 						 (PVC_COR_ERR_MASK & REG_BIT(err_bit)) : \
26 						 (PVC_FAT_ERR_MASK & REG_BIT(err_bit)))
27 
28 static const char * const error_severity[] = DRM_XE_RAS_ERROR_SEVERITY_NAMES;
29 
30 static const char * const hec_uncorrected_fw_errors[] = {
31 	"Fatal",
32 	"CSE Disabled",
33 	"FD Corruption",
34 	"Data Corruption"
35 };
36 
37 enum gt_vector_regs {
38 	ERR_STAT_GT_VECTOR0 = 0,
39 	ERR_STAT_GT_VECTOR1,
40 	ERR_STAT_GT_VECTOR2,
41 	ERR_STAT_GT_VECTOR3,
42 	ERR_STAT_GT_VECTOR4,
43 	ERR_STAT_GT_VECTOR5,
44 	ERR_STAT_GT_VECTOR6,
45 	ERR_STAT_GT_VECTOR7,
46 	ERR_STAT_GT_VECTOR_MAX
47 };
48 
49 #define PVC_GT_VECTOR_LEN(hw_err)	((hw_err == HARDWARE_ERROR_CORRECTABLE) ? \
50 					 ERR_STAT_GT_VECTOR4 : ERR_STAT_GT_VECTOR_MAX)
51 
52 static enum drm_xe_ras_error_severity hw_err_to_severity(const enum hardware_error hw_err)
53 {
54 	if (hw_err == HARDWARE_ERROR_CORRECTABLE)
55 		return DRM_XE_RAS_ERR_SEV_CORRECTABLE;
56 
57 	/* Uncorrectable errors comprise of both fatal and non-fatal errors */
58 	return DRM_XE_RAS_ERR_SEV_UNCORRECTABLE;
59 }
60 
61 static inline u32 err_src_to_id(u32 err_bit)
62 {
63 	switch (err_bit) {
64 	case XE_GT_ERROR:
65 		return DRM_XE_RAS_ERR_COMP_CORE_COMPUTE;
66 	case XE_SOC_ERROR:
67 		return DRM_XE_RAS_ERR_COMP_SOC_INTERNAL;
68 	default:
69 		return 0;
70 	}
71 }
72 
73 static const char * const pvc_master_global_err_reg[] = {
74 	[0 ... 1]	= "Undefined",
75 	[2]		= "HBM SS0: Channel0",
76 	[3]		= "HBM SS0: Channel1",
77 	[4]		= "HBM SS0: Channel2",
78 	[5]		= "HBM SS0: Channel3",
79 	[6]		= "HBM SS0: Channel4",
80 	[7]		= "HBM SS0: Channel5",
81 	[8]		= "HBM SS0: Channel6",
82 	[9]		= "HBM SS0: Channel7",
83 	[10]		= "HBM SS1: Channel0",
84 	[11]		= "HBM SS1: Channel1",
85 	[12]		= "HBM SS1: Channel2",
86 	[13]		= "HBM SS1: Channel3",
87 	[14]		= "HBM SS1: Channel4",
88 	[15]		= "HBM SS1: Channel5",
89 	[16]		= "HBM SS1: Channel6",
90 	[17]		= "HBM SS1: Channel7",
91 	[18 ... 31]	= "Undefined",
92 };
93 static_assert(ARRAY_SIZE(pvc_master_global_err_reg) == XE_RAS_REG_SIZE);
94 
95 static const char * const pvc_slave_global_err_reg[] = {
96 	[0]		= "Undefined",
97 	[1]		= "HBM SS2: Channel0",
98 	[2]		= "HBM SS2: Channel1",
99 	[3]		= "HBM SS2: Channel2",
100 	[4]		= "HBM SS2: Channel3",
101 	[5]		= "HBM SS2: Channel4",
102 	[6]		= "HBM SS2: Channel5",
103 	[7]		= "HBM SS2: Channel6",
104 	[8]		= "HBM SS2: Channel7",
105 	[9]		= "HBM SS3: Channel0",
106 	[10]		= "HBM SS3: Channel1",
107 	[11]		= "HBM SS3: Channel2",
108 	[12]		= "HBM SS3: Channel3",
109 	[13]		= "HBM SS3: Channel4",
110 	[14]		= "HBM SS3: Channel5",
111 	[15]		= "HBM SS3: Channel6",
112 	[16]		= "HBM SS3: Channel7",
113 	[17]		= "Undefined",
114 	[18]		= "ANR MDFI",
115 	[19 ... 31]	= "Undefined",
116 };
117 static_assert(ARRAY_SIZE(pvc_slave_global_err_reg) == XE_RAS_REG_SIZE);
118 
119 static const char * const pvc_slave_local_fatal_err_reg[] = {
120 	[0]		= "Local IEH: Malformed PCIe AER",
121 	[1]		= "Local IEH: Malformed PCIe ERR",
122 	[2]		= "Local IEH: UR conditions in IEH",
123 	[3]		= "Local IEH: From SERR Sources",
124 	[4 ... 19]	= "Undefined",
125 	[20]		= "Malformed MCA error packet (HBM/Punit)",
126 	[21 ... 31]	= "Undefined",
127 };
128 static_assert(ARRAY_SIZE(pvc_slave_local_fatal_err_reg) == XE_RAS_REG_SIZE);
129 
130 static const char * const pvc_master_local_fatal_err_reg[] = {
131 	[0]		= "Local IEH: Malformed IOSF PCIe AER",
132 	[1]		= "Local IEH: Malformed IOSF PCIe ERR",
133 	[2]		= "Local IEH: UR RESPONSE",
134 	[3]		= "Local IEH: From SERR SPI controller",
135 	[4]		= "Base Die MDFI T2T",
136 	[5]		= "Undefined",
137 	[6]		= "Base Die MDFI T2C",
138 	[7]		= "Undefined",
139 	[8]		= "Invalid CSC PSF Command Parity",
140 	[9]		= "Invalid CSC PSF Unexpected Completion",
141 	[10]		= "Invalid CSC PSF Unsupported Request",
142 	[11]		= "Invalid PCIe PSF Command Parity",
143 	[12]		= "PCIe PSF Unexpected Completion",
144 	[13]		= "PCIe PSF Unsupported Request",
145 	[14 ... 19]	= "Undefined",
146 	[20]		= "Malformed MCA error packet (HBM/Punit)",
147 	[21 ... 31]	= "Undefined",
148 };
149 static_assert(ARRAY_SIZE(pvc_master_local_fatal_err_reg) == XE_RAS_REG_SIZE);
150 
151 static const char * const pvc_master_local_nonfatal_err_reg[] = {
152 	[0 ... 3]	= "Undefined",
153 	[4]		= "Base Die MDFI T2T",
154 	[5]		= "Undefined",
155 	[6]		= "Base Die MDFI T2C",
156 	[7]		= "Undefined",
157 	[8]		= "Invalid CSC PSF Command Parity",
158 	[9]		= "Invalid CSC PSF Unexpected Completion",
159 	[10]		= "Invalid PCIe PSF Command Parity",
160 	[11 ... 31]	= "Undefined",
161 };
162 static_assert(ARRAY_SIZE(pvc_master_local_nonfatal_err_reg) == XE_RAS_REG_SIZE);
163 
164 #define PVC_MASTER_LOCAL_REG_INFO(hw_err)	((hw_err == HARDWARE_ERROR_FATAL) ? \
165 						 pvc_master_local_fatal_err_reg : \
166 						 pvc_master_local_nonfatal_err_reg)
167 
168 static void csc_hw_error_work(struct work_struct *work)
169 {
170 	struct xe_tile *tile = container_of(work, typeof(*tile), csc_hw_error_work);
171 	struct xe_device *xe = tile_to_xe(tile);
172 
173 	xe_survivability_mode_runtime_enable(xe);
174 }
175 
176 static void csc_hw_error_handler(struct xe_tile *tile, const enum hardware_error hw_err)
177 {
178 	const enum drm_xe_ras_error_severity severity = hw_err_to_severity(hw_err);
179 	const char *severity_str = error_severity[severity];
180 	struct xe_device *xe = tile_to_xe(tile);
181 	struct xe_mmio *mmio = &tile->mmio;
182 	u32 base, err_bit, err_src;
183 	unsigned long fw_err;
184 
185 	if (xe->info.platform != XE_BATTLEMAGE)
186 		return;
187 
188 	base = BMG_GSC_HECI1_BASE;
189 	lockdep_assert_held(&xe->irq.lock);
190 	err_src = xe_mmio_read32(mmio, HEC_UNCORR_ERR_STATUS(base));
191 	if (!err_src) {
192 		drm_err_ratelimited(&xe->drm, HW_ERR "Tile%d reported %s HEC_ERR_STATUS register blank\n",
193 				    tile->id, severity_str);
194 		return;
195 	}
196 
197 	if (err_src & UNCORR_FW_REPORTED_ERR) {
198 		fw_err = xe_mmio_read32(mmio, HEC_UNCORR_FW_ERR_DW0(base));
199 		for_each_set_bit(err_bit, &fw_err, HEC_UNCORR_FW_ERR_BITS) {
200 			drm_err_ratelimited(&xe->drm, HW_ERR
201 					    "HEC FW %s %s reported, bit[%d] is set\n",
202 					     hec_uncorrected_fw_errors[err_bit], severity_str,
203 					     err_bit);
204 
205 			schedule_work(&tile->csc_hw_error_work);
206 		}
207 	}
208 
209 	xe_mmio_write32(mmio, HEC_UNCORR_ERR_STATUS(base), err_src);
210 }
211 
212 static void log_hw_error(struct xe_tile *tile, const char *name,
213 			 const enum drm_xe_ras_error_severity severity)
214 {
215 	const char *severity_str = error_severity[severity];
216 	struct xe_device *xe = tile_to_xe(tile);
217 
218 	if (severity == DRM_XE_RAS_ERR_SEV_CORRECTABLE)
219 		drm_warn(&xe->drm, HW_ERR "%s %s detected\n", name, severity_str);
220 	else
221 		drm_err_ratelimited(&xe->drm, HW_ERR "%s %s detected\n", name, severity_str);
222 }
223 
224 static void log_gt_err(struct xe_tile *tile, const char *name, int i, u32 err,
225 		       const enum drm_xe_ras_error_severity severity)
226 {
227 	const char *severity_str = error_severity[severity];
228 	struct xe_device *xe = tile_to_xe(tile);
229 
230 	if (severity == DRM_XE_RAS_ERR_SEV_CORRECTABLE)
231 		drm_warn(&xe->drm, HW_ERR "%s %s detected, ERROR_STAT_GT_VECTOR%d:0x%08x\n",
232 			 name, severity_str, i, err);
233 	else
234 		drm_err_ratelimited(&xe->drm, HW_ERR "%s %s detected, ERROR_STAT_GT_VECTOR%d:0x%08x\n",
235 				    name, severity_str, i, err);
236 }
237 
238 static void log_soc_error(struct xe_tile *tile, const char * const *reg_info,
239 			  const enum drm_xe_ras_error_severity severity, u32 err_bit, u32 index)
240 {
241 	const char *severity_str = error_severity[severity];
242 	struct xe_device *xe = tile_to_xe(tile);
243 	struct xe_drm_ras *ras = &xe->ras;
244 	struct xe_drm_ras_counter *info = ras->info[severity];
245 	const char *name;
246 
247 	name = reg_info[err_bit];
248 
249 	if (strcmp(name, "Undefined")) {
250 		if (severity == DRM_XE_RAS_ERR_SEV_CORRECTABLE)
251 			drm_warn(&xe->drm, HW_ERR "%s SOC %s detected", name, severity_str);
252 		else
253 			drm_err_ratelimited(&xe->drm, HW_ERR "%s SOC %s detected", name, severity_str);
254 		atomic_inc(&info[index].counter);
255 	}
256 }
257 
258 static void gt_hw_error_handler(struct xe_tile *tile, const enum hardware_error hw_err,
259 				u32 error_id)
260 {
261 	const enum drm_xe_ras_error_severity severity = hw_err_to_severity(hw_err);
262 	struct xe_device *xe = tile_to_xe(tile);
263 	struct xe_drm_ras *ras = &xe->ras;
264 	struct xe_drm_ras_counter *info = ras->info[severity];
265 	struct xe_mmio *mmio = &tile->mmio;
266 	unsigned long err_stat = 0;
267 	int i;
268 
269 	if (xe->info.platform != XE_PVC)
270 		return;
271 
272 	if (hw_err == HARDWARE_ERROR_NONFATAL) {
273 		atomic_inc(&info[error_id].counter);
274 		log_hw_error(tile, info[error_id].name, severity);
275 		return;
276 	}
277 
278 	for (i = 0; i < PVC_GT_VECTOR_LEN(hw_err); i++) {
279 		u32 vector, val;
280 
281 		vector = xe_mmio_read32(mmio, ERR_STAT_GT_VECTOR_REG(hw_err, i));
282 		if (!vector)
283 			continue;
284 
285 		switch (i) {
286 		case ERR_STAT_GT_VECTOR0:
287 		case ERR_STAT_GT_VECTOR1: {
288 			u32 errbit;
289 
290 			val = hweight32(vector);
291 			atomic_add(val, &info[error_id].counter);
292 			log_gt_err(tile, "Subslice", i, vector, severity);
293 
294 			/*
295 			 * Error status register is only populated once per error.
296 			 * Read the register and clear once.
297 			 */
298 			if (err_stat)
299 				break;
300 
301 			err_stat = xe_mmio_read32(mmio, ERR_STAT_GT_REG(hw_err));
302 			for_each_set_bit(errbit, &err_stat, GT_HW_ERROR_MAX_ERR_BITS) {
303 				if (PVC_ERROR_MASK_SET(hw_err, errbit))
304 					atomic_inc(&info[error_id].counter);
305 			}
306 			if (err_stat)
307 				xe_mmio_write32(mmio, ERR_STAT_GT_REG(hw_err), err_stat);
308 			break;
309 		}
310 		case ERR_STAT_GT_VECTOR2:
311 		case ERR_STAT_GT_VECTOR3:
312 			val = hweight32(vector);
313 			atomic_add(val, &info[error_id].counter);
314 			log_gt_err(tile, "L3 BANK", i, vector, severity);
315 			break;
316 		case ERR_STAT_GT_VECTOR6:
317 			val = hweight32(vector);
318 			atomic_add(val, &info[error_id].counter);
319 			log_gt_err(tile, "TLB", i, vector, severity);
320 			break;
321 		case ERR_STAT_GT_VECTOR7:
322 			val = hweight32(vector);
323 			atomic_add(val, &info[error_id].counter);
324 			log_gt_err(tile, "L3 Fabric", i, vector, severity);
325 			break;
326 		default:
327 			log_gt_err(tile, "Undefined", i, vector, severity);
328 		}
329 
330 		xe_mmio_write32(mmio, ERR_STAT_GT_VECTOR_REG(hw_err, i), vector);
331 	}
332 }
333 
334 static void soc_slave_ieh_handler(struct xe_tile *tile, const enum hardware_error hw_err, u32 error_id)
335 {
336 	const enum drm_xe_ras_error_severity severity = hw_err_to_severity(hw_err);
337 	unsigned long slave_global_errstat, slave_local_errstat;
338 	struct xe_mmio *mmio = &tile->mmio;
339 	u32 regbit, slave;
340 
341 	slave = SOC_PVC_SLAVE_BASE;
342 	slave_global_errstat = xe_mmio_read32(mmio, SOC_GLOBAL_ERR_STAT_REG(slave, hw_err));
343 
344 	if (slave_global_errstat & SOC_IEH1_LOCAL_ERR_STATUS) {
345 		slave_local_errstat = xe_mmio_read32(mmio, SOC_LOCAL_ERR_STAT_REG(slave, hw_err));
346 
347 		if (hw_err == HARDWARE_ERROR_FATAL) {
348 			for_each_set_bit(regbit, &slave_local_errstat, XE_RAS_REG_SIZE)
349 				log_soc_error(tile, pvc_slave_local_fatal_err_reg, severity,
350 					      regbit, error_id);
351 		}
352 
353 		xe_mmio_write32(mmio, SOC_LOCAL_ERR_STAT_REG(slave, hw_err),
354 				slave_local_errstat);
355 	}
356 
357 	for_each_set_bit(regbit, &slave_global_errstat, XE_RAS_REG_SIZE)
358 		log_soc_error(tile, pvc_slave_global_err_reg, severity, regbit, error_id);
359 
360 	xe_mmio_write32(mmio, SOC_GLOBAL_ERR_STAT_REG(slave, hw_err), slave_global_errstat);
361 }
362 
363 static void soc_hw_error_handler(struct xe_tile *tile, const enum hardware_error hw_err,
364 				 u32 error_id)
365 {
366 	const enum drm_xe_ras_error_severity severity = hw_err_to_severity(hw_err);
367 	struct xe_device *xe = tile_to_xe(tile);
368 	struct xe_mmio *mmio = &tile->mmio;
369 	unsigned long master_global_errstat, master_local_errstat;
370 	u32 master, slave, regbit;
371 	int i;
372 
373 	if (xe->info.platform != XE_PVC)
374 		return;
375 
376 	master = SOC_PVC_MASTER_BASE;
377 	slave = SOC_PVC_SLAVE_BASE;
378 
379 	/* Mask error type in GSYSEVTCTL so that no new errors of the type will be reported */
380 	for (i = 0; i < XE_SOC_NUM_IEH; i++)
381 		xe_mmio_write32(mmio, SOC_GSYSEVTCTL_REG(master, slave, i), ~REG_BIT(hw_err));
382 
383 	if (hw_err == HARDWARE_ERROR_CORRECTABLE) {
384 		xe_mmio_write32(mmio, SOC_GLOBAL_ERR_STAT_REG(master, hw_err), REG_GENMASK(31, 0));
385 		xe_mmio_write32(mmio, SOC_LOCAL_ERR_STAT_REG(master, hw_err), REG_GENMASK(31, 0));
386 		xe_mmio_write32(mmio, SOC_GLOBAL_ERR_STAT_REG(slave, hw_err), REG_GENMASK(31, 0));
387 		xe_mmio_write32(mmio, SOC_LOCAL_ERR_STAT_REG(slave, hw_err), REG_GENMASK(31, 0));
388 		goto unmask_gsysevtctl;
389 	}
390 
391 	/*
392 	 * Read the master global IEH error register, if BIT(1) is set then process
393 	 * the slave IEH first. If BIT(0) in global error register is set then process
394 	 * the corresponding local error registers.
395 	 */
396 	master_global_errstat = xe_mmio_read32(mmio, SOC_GLOBAL_ERR_STAT_REG(master, hw_err));
397 	if (master_global_errstat & SOC_SLAVE_IEH)
398 		soc_slave_ieh_handler(tile, hw_err, error_id);
399 
400 	if (master_global_errstat & SOC_IEH0_LOCAL_ERR_STATUS) {
401 		master_local_errstat = xe_mmio_read32(mmio, SOC_LOCAL_ERR_STAT_REG(master, hw_err));
402 
403 		for_each_set_bit(regbit, &master_local_errstat, XE_RAS_REG_SIZE)
404 			log_soc_error(tile, PVC_MASTER_LOCAL_REG_INFO(hw_err), severity, regbit, error_id);
405 
406 		xe_mmio_write32(mmio, SOC_LOCAL_ERR_STAT_REG(master, hw_err), master_local_errstat);
407 	}
408 
409 	for_each_set_bit(regbit, &master_global_errstat, XE_RAS_REG_SIZE)
410 		log_soc_error(tile, pvc_master_global_err_reg, severity, regbit, error_id);
411 
412 	xe_mmio_write32(mmio, SOC_GLOBAL_ERR_STAT_REG(master, hw_err), master_global_errstat);
413 
414 unmask_gsysevtctl:
415 	for (i = 0; i < XE_SOC_NUM_IEH; i++)
416 		xe_mmio_write32(mmio, SOC_GSYSEVTCTL_REG(master, slave, i),
417 				(HARDWARE_ERROR_MAX << 1) + 1);
418 }
419 
420 static void hw_error_source_handler(struct xe_tile *tile, const enum hardware_error hw_err)
421 {
422 	const enum drm_xe_ras_error_severity severity = hw_err_to_severity(hw_err);
423 	const char *severity_str = error_severity[severity];
424 	struct xe_device *xe = tile_to_xe(tile);
425 	struct xe_drm_ras *ras = &xe->ras;
426 	struct xe_drm_ras_counter *info = ras->info[severity];
427 	unsigned long flags, err_src;
428 	u32 err_bit;
429 
430 	if (!IS_DGFX(xe))
431 		return;
432 
433 	/*
434 	 * Hardware errors are reported through System Controller on the platforms that
435 	 * support it, and never routed as direct IRQ to SGUnit. So we should never be
436 	 * here for those platforms.
437 	 */
438 	if (xe->info.has_sysctrl) {
439 		drm_err_ratelimited(&xe->drm, HW_ERR "Invalid error routing\n");
440 		return;
441 	}
442 
443 	spin_lock_irqsave(&xe->irq.lock, flags);
444 	err_src = xe_mmio_read32(&tile->mmio, DEV_ERR_STAT_REG(hw_err));
445 	if (!err_src) {
446 		drm_err_ratelimited(&xe->drm, HW_ERR "Tile%d reported %s DEV_ERR_STAT register blank!\n",
447 				    tile->id, severity_str);
448 		goto unlock;
449 	}
450 
451 	/*
452 	 * On encountering CSC firmware errors, the graphics device becomes unrecoverable
453 	 * so return immediately on error. The only way to recover from these errors is
454 	 * firmware flash. The device will enter Runtime Survivability mode when such
455 	 * errors are detected.
456 	 */
457 	if (err_src & REG_BIT(XE_CSC_ERROR)) {
458 		csc_hw_error_handler(tile, hw_err);
459 		goto clear_reg;
460 	}
461 
462 	if (!info)
463 		goto clear_reg;
464 
465 	for_each_set_bit(err_bit, &err_src, XE_RAS_REG_SIZE) {
466 		const char *name;
467 		u32 error_id;
468 
469 		error_id = err_src_to_id(err_bit);
470 		if (!error_id)
471 			continue;
472 
473 		name = info[error_id].name;
474 		if (!name)
475 			continue;
476 
477 		if (severity == DRM_XE_RAS_ERR_SEV_CORRECTABLE) {
478 			drm_warn(&xe->drm, HW_ERR
479 				 "TILE%d reported %s %s, bit[%d] is set\n",
480 				 tile->id, name, severity_str, err_bit);
481 		} else {
482 			drm_err_ratelimited(&xe->drm, HW_ERR
483 					    "TILE%d reported %s %s, bit[%d] is set\n",
484 					    tile->id, name, severity_str, err_bit);
485 		}
486 
487 		if (err_bit == XE_GT_ERROR)
488 			gt_hw_error_handler(tile, hw_err, error_id);
489 		if (err_bit == XE_SOC_ERROR)
490 			soc_hw_error_handler(tile, hw_err, error_id);
491 	}
492 
493 clear_reg:
494 	xe_mmio_write32(&tile->mmio, DEV_ERR_STAT_REG(hw_err), err_src);
495 unlock:
496 	spin_unlock_irqrestore(&xe->irq.lock, flags);
497 }
498 
499 /**
500  * xe_hw_error_irq_handler - irq handling for hw errors
501  * @tile: tile instance
502  * @master_ctl: value read from master interrupt register
503  *
504  * Xe platforms add three error bits to the master interrupt register to support error handling.
505  * These three bits are used to convey the class of error FATAL, NONFATAL, or CORRECTABLE.
506  * To process the interrupt, determine the source of error by reading the Device Error Source
507  * Register that corresponds to the class of error being serviced.
508  */
509 void xe_hw_error_irq_handler(struct xe_tile *tile, const u32 master_ctl)
510 {
511 	enum hardware_error hw_err;
512 
513 	if (xe_fault_csc_hw_error())
514 		schedule_work(&tile->csc_hw_error_work);
515 
516 	for (hw_err = 0; hw_err < HARDWARE_ERROR_MAX; hw_err++) {
517 		if (master_ctl & ERROR_IRQ(hw_err))
518 			hw_error_source_handler(tile, hw_err);
519 	}
520 }
521 
522 /*
523  * Process hardware errors during boot
524  */
525 static void process_hw_errors(struct xe_device *xe)
526 {
527 	struct xe_tile *tile;
528 	u32 master_ctl;
529 	u8 id;
530 
531 	for_each_tile(tile, xe, id) {
532 		master_ctl = xe_mmio_read32(&tile->mmio, GFX_MSTR_IRQ);
533 		xe_hw_error_irq_handler(tile, master_ctl);
534 		xe_mmio_write32(&tile->mmio, GFX_MSTR_IRQ, master_ctl);
535 	}
536 }
537 
538 /**
539  * xe_hw_error_init - Initialize hw errors
540  * @xe: xe device instance
541  *
542  * Initialize and check for errors that occurred during boot
543  * prior to driver load
544  */
545 void xe_hw_error_init(struct xe_device *xe)
546 {
547 	struct xe_tile *tile = xe_device_get_root_tile(xe);
548 
549 	if (!IS_DGFX(xe) || IS_SRIOV_VF(xe))
550 		return;
551 
552 	INIT_WORK(&tile->csc_hw_error_work, csc_hw_error_work);
553 
554 	process_hw_errors(xe);
555 }
556