xref: /linux/drivers/gpu/drm/amd/ras/core/aca.c (revision 67f8bc848ee31831336bd478e57d2f993551902e)
1 // SPDX-License-Identifier: MIT
2 /*
3  * Copyright 2025 Advanced Micro Devices, Inc.
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a
6  * copy of this software and associated documentation files (the "Software"),
7  * to deal in the Software without restriction, including without limitation
8  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9  * and/or sell copies of the Software, and to permit persons to whom the
10  * Software is furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be included in
13  * all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
19  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
20  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
21  * OTHER DEALINGS IN THE SOFTWARE.
22  *
23  */
24 #include "ras.h"
25 #include "aca.h"
26 #include "aca_v1_0.h"
27 #include "ras_mp1_v13_0.h"
28 
29 #define ACA_MARK_FATAL_FLAG    0x100
30 #define ACA_MARK_UE_READ_FLAG  0x1
31 
32 #define blk_name(block_id) ras_core_get_ras_block_name(block_id)
33 
34 static struct aca_regs_dump {
35 	const char *name;
36 	int reg_idx;
37 } aca_regs[] = {
38 	{"CONTROL",		ACA_REG_IDX__CTL},
39 	{"STATUS",		ACA_REG_IDX__STATUS},
40 	{"ADDR",		ACA_REG_IDX__ADDR},
41 	{"MISC",		ACA_REG_IDX__MISC0},
42 	{"CONFIG",		ACA_REG_IDX__CONFG},
43 	{"IPID",		ACA_REG_IDX__IPID},
44 	{"SYND",		ACA_REG_IDX__SYND},
45 	{"DESTAT",		ACA_REG_IDX__DESTAT},
46 	{"DEADDR",		ACA_REG_IDX__DEADDR},
47 	{"CONTROL_MASK",	ACA_REG_IDX__CTL_MASK},
48 };
49 
50 
51 static void aca_report_ecc_info(struct ras_core_context *ras_core,
52 				u64 seq_no, u32 blk, u32 skt, u32 aid,
53 				struct aca_aid_ecc *aid_ecc,
54 				struct aca_bank_ecc *new_ecc)
55 {
56 	struct aca_ecc_count ecc_count = {0};
57 
58 	ecc_count.new_ue_count = new_ecc->ue_count;
59 	ecc_count.new_de_count = new_ecc->de_count;
60 	ecc_count.new_ce_count = new_ecc->ce_count;
61 	if (blk == RAS_BLOCK_ID__GFX) {
62 		struct aca_ecc_count *xcd_ecc;
63 		int xcd_id;
64 
65 		for (xcd_id = 0; xcd_id < aid_ecc->xcd.xcd_num; xcd_id++) {
66 			xcd_ecc = &aid_ecc->xcd.xcd[xcd_id].ecc_err;
67 			ecc_count.total_ue_count += xcd_ecc->total_ue_count;
68 			ecc_count.total_de_count += xcd_ecc->total_de_count;
69 			ecc_count.total_ce_count += xcd_ecc->total_ce_count;
70 		}
71 	} else {
72 		ecc_count.total_ue_count = aid_ecc->ecc_err.total_ue_count;
73 		ecc_count.total_de_count = aid_ecc->ecc_err.total_de_count;
74 		ecc_count.total_ce_count = aid_ecc->ecc_err.total_ce_count;
75 	}
76 
77 	if (ecc_count.new_ue_count) {
78 		RAS_DEV_INFO(ras_core->dev,
79 		"{%llu} socket: %d, die: %d, %u new uncorrectable hardware errors detected in %s block\n",
80 			seq_no, skt, aid, ecc_count.new_ue_count, blk_name(blk));
81 		RAS_DEV_INFO(ras_core->dev,
82 		"{%llu} socket: %d, die: %d, %u uncorrectable hardware errors detected in total in %s block\n",
83 			seq_no, skt, aid, ecc_count.total_ue_count, blk_name(blk));
84 	}
85 
86 	if (ecc_count.new_de_count && blk == RAS_BLOCK_ID__UMC) {
87 		RAS_DEV_INFO(ras_core->dev,
88 		"{%llu} socket: %d, die: %d, %u new deferred hardware errors detected in %s block\n",
89 			seq_no, skt, aid, ecc_count.new_de_count,
90 			blk_name(blk));
91 		RAS_DEV_INFO(ras_core->dev,
92 		"{%llu} socket: %d, die: %d, %u deferred hardware errors detected in total in %s block\n",
93 			seq_no, skt, aid, ecc_count.total_de_count,
94 			blk_name(blk));
95 	}
96 
97 	if (ecc_count.new_ce_count) {
98 		if (ras_core_is_ce_log_disabled(ras_core))
99 			return;
100 		RAS_DEV_INFO(ras_core->dev,
101 		"{%llu} socket: %d, die: %d, %u new correctable hardware errors detected in %s block\n",
102 			seq_no, skt, aid, ecc_count.new_ce_count, blk_name(blk));
103 		RAS_DEV_INFO(ras_core->dev,
104 		"{%llu} socket: %d, die: %d, %u correctable hardware errors detected in total in %s block\n",
105 			seq_no, skt, aid, ecc_count.total_ce_count, blk_name(blk));
106 	}
107 }
108 
109 static void aca_bank_log(struct ras_core_context *ras_core,
110 			 int idx, int total, struct aca_bank_reg *bank,
111 			 struct aca_bank_ecc *bank_ecc)
112 {
113 	int i;
114 
115 	if (ras_core_is_ce_log_disabled(ras_core) &&
116 	   bank->ecc_type == RAS_ERR_TYPE__CE &&
117 	   !bank_ecc->de_count)
118 		return;
119 
120 	RAS_DEV_INFO(ras_core->dev,
121 		"{%llu}" RAS_HW_ERR "Accelerator Check Architecture events logged\n",
122 		bank->seq_no);
123 	/* plus 1 for output format, e.g: ACA[08/08]: xxxx */
124 	for (i = 0; i < ARRAY_SIZE(aca_regs); i++)
125 		RAS_DEV_INFO(ras_core->dev,
126 			"{%llu}" RAS_HW_ERR "ACA[%02d/%02d].%s=0x%016llx\n",
127 			bank->seq_no, idx + 1, total,
128 			aca_regs[i].name, bank->regs[aca_regs[i].reg_idx]);
129 }
130 
131 static void aca_log_bank_data(struct ras_core_context *ras_core,
132 			struct aca_bank_reg *bank, struct aca_bank_ecc *bank_ecc,
133 			struct ras_log_batch_tag *batch)
134 {
135 	if (bank_ecc->ue_count)
136 		ras_log_ring_add_log_event(ras_core, RAS_LOG_EVENT_UE, bank->regs, batch);
137 	else if (bank_ecc->de_count)
138 		ras_log_ring_add_log_event(ras_core, RAS_LOG_EVENT_DE, bank->regs, batch);
139 	else
140 		ras_log_ring_add_log_event(ras_core, RAS_LOG_EVENT_CE, bank->regs, batch);
141 }
142 
143 static int aca_get_bank_count(struct ras_core_context *ras_core,
144 			      enum ras_err_type type, u32 *count)
145 {
146 	return ras_mp1_get_bank_count(ras_core, type, count);
147 }
148 
149 static bool aca_match_bank(struct aca_block *aca_blk, struct aca_bank_reg *bank)
150 {
151 	const struct aca_bank_hw_ops *bank_ops;
152 
153 	if (!aca_blk->blk_info)
154 		return false;
155 
156 	bank_ops = &aca_blk->blk_info->bank_ops;
157 	if (!bank_ops->bank_match)
158 		return false;
159 
160 	return bank_ops->bank_match(aca_blk, bank);
161 }
162 
163 static int aca_parse_bank(struct ras_core_context *ras_core,
164 			  struct aca_block *aca_blk,
165 			  struct aca_bank_reg *bank,
166 			  struct aca_bank_ecc *ecc)
167 {
168 	const struct aca_bank_hw_ops *bank_ops = &aca_blk->blk_info->bank_ops;
169 
170 	if (!bank_ops || !bank_ops->bank_parse)
171 		return -RAS_CORE_NOT_SUPPORTED;
172 
173 	return bank_ops->bank_parse(ras_core, aca_blk, bank, ecc);
174 }
175 
176 static int aca_check_block_ecc_info(struct ras_core_context *ras_core,
177 			struct aca_block *aca_blk, struct aca_ecc_info *info)
178 {
179 	if (info->socket_id >= aca_blk->ecc.socket_num_per_hive) {
180 		RAS_DEV_ERR(ras_core->dev,
181 			"Socket id (%d) is out of config! max:%u\n",
182 			info->socket_id, aca_blk->ecc.socket_num_per_hive);
183 		return -ENODATA;
184 	}
185 
186 	if (info->die_id >= aca_blk->ecc.socket[info->socket_id].aid_num) {
187 		RAS_DEV_ERR(ras_core->dev,
188 			"Die id (%d) is out of config! max:%u\n",
189 			info->die_id, aca_blk->ecc.socket[info->socket_id].aid_num);
190 		return -ENODATA;
191 	}
192 
193 	if ((aca_blk->blk_info->ras_block_id == RAS_BLOCK_ID__GFX) &&
194 	    (info->xcd_id >=
195 		 aca_blk->ecc.socket[info->socket_id].aid[info->die_id].xcd.xcd_num)) {
196 		RAS_DEV_ERR(ras_core->dev,
197 			"Xcd id (%d) is out of config! max:%u\n",
198 			info->xcd_id,
199 			aca_blk->ecc.socket[info->socket_id].aid[info->die_id].xcd.xcd_num);
200 		return -ENODATA;
201 	}
202 
203 	return 0;
204 }
205 
206 static int aca_log_bad_bank(struct ras_core_context *ras_core,
207 				 struct aca_block *aca_blk, struct aca_bank_reg *bank,
208 				 struct aca_bank_ecc *bank_ecc)
209 {
210 	struct aca_ecc_info *info;
211 	struct aca_ecc_count *ecc_err;
212 	struct aca_aid_ecc *aid_ecc;
213 	int ret;
214 
215 	info = &bank_ecc->bank_info;
216 
217 	ret = aca_check_block_ecc_info(ras_core, aca_blk, info);
218 	if (ret)
219 		return ret;
220 
221 	mutex_lock(&ras_core->ras_aca.aca_lock);
222 	aid_ecc = &aca_blk->ecc.socket[info->socket_id].aid[info->die_id];
223 	if (aca_blk->blk_info->ras_block_id == RAS_BLOCK_ID__GFX)
224 		ecc_err = &aid_ecc->xcd.xcd[info->xcd_id].ecc_err;
225 	else
226 		ecc_err = &aid_ecc->ecc_err;
227 
228 	ecc_err->new_ce_count += bank_ecc->ce_count;
229 	ecc_err->total_ce_count += bank_ecc->ce_count;
230 	ecc_err->new_ue_count += bank_ecc->ue_count;
231 	ecc_err->total_ue_count += bank_ecc->ue_count;
232 	ecc_err->new_de_count += bank_ecc->de_count;
233 	ecc_err->total_de_count += bank_ecc->de_count;
234 	mutex_unlock(&ras_core->ras_aca.aca_lock);
235 
236 	if ((aca_blk->blk_info->ras_block_id == RAS_BLOCK_ID__UMC) &&
237 	    bank_ecc->de_count) {
238 		struct ras_bank_ecc  ras_ecc = {0};
239 
240 		if (ras_fw_eeprom_supported(ras_core)) {
241 			ret = ras_fw_eeprom_update_record(ras_core, &ras_ecc);
242 			if (!ret) {
243 				ras_ecc.nps = ras_core_get_curr_nps_mode(ras_core);
244 				ras_ecc.status = bank_ecc->bank_info.status;
245 				ras_ecc.seq_no = bank->seq_no;
246 			}
247 		} else {
248 			ras_ecc.nps = ras_core_get_curr_nps_mode(ras_core);
249 			ras_ecc.addr = bank_ecc->bank_info.addr;
250 			ras_ecc.ipid = bank_ecc->bank_info.ipid;
251 			ras_ecc.status = bank_ecc->bank_info.status;
252 			ras_ecc.seq_no = bank->seq_no;
253 		}
254 
255 		if (!ret) {
256 			if (ras_core_gpu_in_reset(ras_core))
257 				ras_umc_log_bad_bank_pending(ras_core, &ras_ecc);
258 			else
259 				ras_umc_log_bad_bank(ras_core, &ras_ecc);
260 		}
261 	}
262 
263 	aca_report_ecc_info(ras_core,
264 		bank->seq_no, aca_blk->blk_info->ras_block_id, info->socket_id, info->die_id,
265 		&aca_blk->ecc.socket[info->socket_id].aid[info->die_id], bank_ecc);
266 
267 	return 0;
268 }
269 
270 static struct aca_block *aca_get_bank_aca_block(struct ras_core_context *ras_core,
271 				struct aca_bank_reg *bank)
272 {
273 	int i = 0;
274 
275 	for (i = 0; i < RAS_BLOCK_ID__LAST; i++)
276 		if (aca_match_bank(&ras_core->ras_aca.aca_blk[i], bank))
277 			return &ras_core->ras_aca.aca_blk[i];
278 
279 	return NULL;
280 }
281 
282 static int aca_dump_bank(struct ras_core_context *ras_core, u32 ecc_type,
283 			 int idx, void *data)
284 {
285 	struct aca_bank_reg *bank = (struct aca_bank_reg *)data;
286 	int i, ret, reg_cnt;
287 
288 	reg_cnt = min_t(int, 16, ARRAY_SIZE(bank->regs));
289 	for (i = 0; i < reg_cnt; i++) {
290 		ret = ras_mp1_dump_bank(ras_core, ecc_type, idx, i, &bank->regs[i]);
291 		if (ret)
292 			return ret;
293 	}
294 
295 	return 0;
296 }
297 
298 static uint64_t aca_get_bank_seqno(struct ras_core_context *ras_core,
299 				enum ras_err_type err_type, struct aca_block *aca_blk,
300 				struct aca_bank_ecc *bank_ecc)
301 {
302 	uint64_t seq_no = 0;
303 
304 	if (bank_ecc->de_count) {
305 		if (aca_blk->blk_info->ras_block_id == RAS_BLOCK_ID__UMC)
306 			seq_no = ras_core_get_seqno(ras_core, RAS_SEQNO_TYPE_DE, true);
307 		else
308 			seq_no = ras_core_get_seqno(ras_core,
309 					RAS_SEQNO_TYPE_POISON_CONSUMPTION, true);
310 	} else if (bank_ecc->ue_count) {
311 		seq_no = ras_core_get_seqno(ras_core, RAS_SEQNO_TYPE_UE, true);
312 	} else {
313 		seq_no = ras_core_get_seqno(ras_core, RAS_SEQNO_TYPE_CE, true);
314 	}
315 
316 	return seq_no;
317 }
318 
319 static bool aca_dup_update_ue_in_fatal(struct ras_core_context *ras_core,
320 				u32 ecc_type)
321 {
322 	struct ras_aca *aca = &ras_core->ras_aca;
323 
324 	if (ecc_type != RAS_ERR_TYPE__UE)
325 		return false;
326 
327 	if (aca->ue_updated_mark & ACA_MARK_FATAL_FLAG) {
328 		if (aca->ue_updated_mark & ACA_MARK_UE_READ_FLAG)
329 			return true;
330 
331 		aca->ue_updated_mark |= ACA_MARK_UE_READ_FLAG;
332 	}
333 
334 	return false;
335 }
336 
337 void ras_aca_mark_fatal_flag(struct ras_core_context *ras_core)
338 {
339 	struct ras_aca *aca = &ras_core->ras_aca;
340 
341 	if (!aca)
342 		return;
343 
344 	aca->ue_updated_mark |= ACA_MARK_FATAL_FLAG;
345 }
346 
347 void ras_aca_clear_fatal_flag(struct ras_core_context *ras_core)
348 {
349 	struct ras_aca *aca = &ras_core->ras_aca;
350 
351 	if (!aca)
352 		return;
353 
354 	if ((aca->ue_updated_mark & ACA_MARK_FATAL_FLAG) &&
355 		(aca->ue_updated_mark & ACA_MARK_UE_READ_FLAG))
356 		aca->ue_updated_mark = 0;
357 }
358 
359 static int aca_banks_update(struct ras_core_context *ras_core,
360 			u32 ecc_type, void *data)
361 {
362 	struct aca_bank_reg bank;
363 	struct aca_block *aca_blk;
364 	struct aca_bank_ecc bank_ecc;
365 	struct ras_log_batch_tag *batch_tag = NULL;
366 	u32 count = 0;
367 	int ret = 0;
368 	int i;
369 
370 	mutex_lock(&ras_core->ras_aca.bank_op_lock);
371 
372 	if (aca_dup_update_ue_in_fatal(ras_core, ecc_type))
373 		goto out;
374 
375 	ret = aca_get_bank_count(ras_core, ecc_type, &count);
376 	if (ret)
377 		goto out;
378 
379 	if (!count)
380 		goto out;
381 
382 	batch_tag = ras_log_ring_create_batch_tag(ras_core);
383 	for (i = 0; i < count; i++) {
384 		memset(&bank, 0, sizeof(bank));
385 		ret = aca_dump_bank(ras_core, ecc_type, i, &bank);
386 		if (ret)
387 			break;
388 
389 		bank.ecc_type = ecc_type;
390 
391 		memset(&bank_ecc, 0, sizeof(bank_ecc));
392 		aca_blk = aca_get_bank_aca_block(ras_core, &bank);
393 		if (aca_blk)
394 			ret = aca_parse_bank(ras_core, aca_blk, &bank, &bank_ecc);
395 
396 		bank.seq_no = aca_get_bank_seqno(ras_core, ecc_type, aca_blk, &bank_ecc);
397 
398 		aca_log_bank_data(ras_core, &bank, &bank_ecc, batch_tag);
399 		aca_bank_log(ras_core, i, count, &bank, &bank_ecc);
400 
401 		if (!ret && aca_blk)
402 			ret = aca_log_bad_bank(ras_core, aca_blk, &bank, &bank_ecc);
403 
404 		if (ret)
405 			break;
406 	}
407 	ras_log_ring_destroy_batch_tag(ras_core, batch_tag);
408 
409 out:
410 	mutex_unlock(&ras_core->ras_aca.bank_op_lock);
411 	return ret;
412 }
413 
414 int ras_aca_update_ecc(struct ras_core_context *ras_core, u32 type, void *data)
415 {
416 	/* Update aca bank to aca source error_cache first */
417 	return aca_banks_update(ras_core, type, data);
418 }
419 
420 static struct aca_block *ras_aca_get_block_handle(struct ras_core_context *ras_core, uint32_t blk)
421 {
422 	return &ras_core->ras_aca.aca_blk[blk];
423 }
424 
425 static int ras_aca_clear_block_ecc_count(struct ras_core_context *ras_core, u32 blk)
426 {
427 	struct aca_block *aca_blk;
428 	struct aca_aid_ecc  *aid_ecc;
429 	int skt, aid, xcd;
430 
431 	mutex_lock(&ras_core->ras_aca.aca_lock);
432 	aca_blk = ras_aca_get_block_handle(ras_core, blk);
433 	for (skt = 0; skt < aca_blk->ecc.socket_num_per_hive; skt++) {
434 		for (aid = 0; aid < aca_blk->ecc.socket[skt].aid_num; aid++) {
435 			aid_ecc = &aca_blk->ecc.socket[skt].aid[aid];
436 			if (blk == RAS_BLOCK_ID__GFX) {
437 				for (xcd = 0; xcd < aid_ecc->xcd.xcd_num; xcd++)
438 					memset(&aid_ecc->xcd.xcd[xcd],
439 						0, sizeof(struct aca_xcd_ecc));
440 			} else {
441 				memset(&aid_ecc->ecc_err, 0, sizeof(aid_ecc->ecc_err));
442 			}
443 		}
444 	}
445 	mutex_unlock(&ras_core->ras_aca.aca_lock);
446 
447 	return 0;
448 }
449 
450 int ras_aca_clear_all_blocks_ecc_count(struct ras_core_context *ras_core)
451 {
452 	enum ras_block_id blk;
453 	int ret;
454 
455 	for (blk = RAS_BLOCK_ID__UMC; blk < RAS_BLOCK_ID__LAST; blk++) {
456 		ret = ras_aca_clear_block_ecc_count(ras_core, blk);
457 		if (ret)
458 			break;
459 	}
460 
461 	return ret;
462 }
463 
464 int ras_aca_clear_block_new_ecc_count(struct ras_core_context *ras_core, u32 blk)
465 {
466 	struct aca_block *aca_blk;
467 	int skt, aid, xcd;
468 	struct aca_ecc_count *ecc_err;
469 	struct aca_aid_ecc  *aid_ecc;
470 
471 	mutex_lock(&ras_core->ras_aca.aca_lock);
472 	aca_blk = ras_aca_get_block_handle(ras_core, blk);
473 	for (skt = 0; skt < aca_blk->ecc.socket_num_per_hive; skt++) {
474 		for (aid = 0; aid < aca_blk->ecc.socket[skt].aid_num; aid++) {
475 			aid_ecc = &aca_blk->ecc.socket[skt].aid[aid];
476 			if (blk == RAS_BLOCK_ID__GFX) {
477 				for (xcd = 0; xcd < aid_ecc->xcd.xcd_num; xcd++) {
478 					ecc_err = &aid_ecc->xcd.xcd[xcd].ecc_err;
479 					ecc_err->new_ce_count = 0;
480 					ecc_err->new_ue_count = 0;
481 					ecc_err->new_de_count = 0;
482 				}
483 			} else {
484 				ecc_err = &aid_ecc->ecc_err;
485 				ecc_err->new_ce_count = 0;
486 				ecc_err->new_ue_count = 0;
487 				ecc_err->new_de_count = 0;
488 			}
489 		}
490 	}
491 	mutex_unlock(&ras_core->ras_aca.aca_lock);
492 
493 	return 0;
494 }
495 
496 static int ras_aca_get_block_each_aid_ecc_count(struct ras_core_context *ras_core,
497 						u32 blk, u32 skt, u32 aid, u32 xcd,
498 						struct aca_ecc_count *ecc_count)
499 {
500 	struct aca_block *aca_blk;
501 	struct aca_ecc_count *ecc_err;
502 
503 	aca_blk = ras_aca_get_block_handle(ras_core, blk);
504 	if (blk == RAS_BLOCK_ID__GFX)
505 		ecc_err = &aca_blk->ecc.socket[skt].aid[aid].xcd.xcd[xcd].ecc_err;
506 	else
507 		ecc_err = &aca_blk->ecc.socket[skt].aid[aid].ecc_err;
508 
509 	ecc_count->new_ce_count = ecc_err->new_ce_count;
510 	ecc_count->total_ce_count = ecc_err->total_ce_count;
511 	ecc_count->new_ue_count = ecc_err->new_ue_count;
512 	ecc_count->total_ue_count = ecc_err->total_ue_count;
513 	ecc_count->new_de_count = ecc_err->new_de_count;
514 	ecc_count->total_de_count = ecc_err->total_de_count;
515 
516 	return 0;
517 }
518 
519 static inline void _add_ecc_count(struct aca_ecc_count *des, struct aca_ecc_count *src)
520 {
521 	des->new_ce_count += src->new_ce_count;
522 	des->total_ce_count += src->total_ce_count;
523 	des->new_ue_count += src->new_ue_count;
524 	des->total_ue_count += src->total_ue_count;
525 	des->new_de_count += src->new_de_count;
526 	des->total_de_count += src->total_de_count;
527 }
528 
529 static const struct ras_aca_ip_func *aca_get_ip_func(
530 				struct ras_core_context *ras_core, uint32_t ip_version)
531 {
532 	switch (ip_version) {
533 	case IP_VERSION(1, 0, 0):
534 		return &ras_aca_func_v1_0;
535 	default:
536 		RAS_DEV_ERR(ras_core->dev,
537 			"ACA ip version(0x%x) is not supported!\n", ip_version);
538 		break;
539 	}
540 
541 	return NULL;
542 }
543 
544 int ras_aca_get_block_ecc_count(struct ras_core_context *ras_core,
545 				u32 blk, void *data)
546 {
547 	struct ras_ecc_count *err_data = (struct ras_ecc_count *)data;
548 	struct aca_block *aca_blk;
549 	int skt, aid, xcd;
550 	struct aca_ecc_count ecc_xcd;
551 	struct aca_ecc_count ecc_aid;
552 	struct aca_ecc_count ecc;
553 
554 	if (blk >= RAS_BLOCK_ID__LAST)
555 		return -EINVAL;
556 
557 	if (!err_data)
558 		return -EINVAL;
559 
560 	aca_blk = ras_aca_get_block_handle(ras_core, blk);
561 	memset(&ecc, 0, sizeof(ecc));
562 
563 	mutex_lock(&ras_core->ras_aca.aca_lock);
564 	if (blk == RAS_BLOCK_ID__GFX) {
565 		for (skt = 0; skt < aca_blk->ecc.socket_num_per_hive; skt++) {
566 			for (aid = 0; aid < aca_blk->ecc.socket[skt].aid_num; aid++) {
567 				memset(&ecc_aid, 0, sizeof(ecc_aid));
568 				for (xcd = 0;
569 				     xcd < aca_blk->ecc.socket[skt].aid[aid].xcd.xcd_num;
570 				     xcd++) {
571 					memset(&ecc_xcd, 0, sizeof(ecc_xcd));
572 					if (ras_aca_get_block_each_aid_ecc_count(ras_core,
573 							blk, skt, aid, xcd, &ecc_xcd))
574 						continue;
575 					_add_ecc_count(&ecc_aid, &ecc_xcd);
576 				}
577 				_add_ecc_count(&ecc, &ecc_aid);
578 			}
579 		}
580 	} else {
581 		for (skt = 0; skt < aca_blk->ecc.socket_num_per_hive; skt++) {
582 			for (aid = 0; aid < aca_blk->ecc.socket[skt].aid_num; aid++) {
583 				memset(&ecc_aid, 0, sizeof(ecc_aid));
584 				if (ras_aca_get_block_each_aid_ecc_count(ras_core,
585 						blk, skt, aid, 0, &ecc_aid))
586 					continue;
587 				_add_ecc_count(&ecc, &ecc_aid);
588 			}
589 		}
590 	}
591 
592 	err_data->new_ce_count = ecc.new_ce_count;
593 	err_data->total_ce_count = ecc.total_ce_count;
594 	err_data->new_ue_count = ecc.new_ue_count;
595 	err_data->total_ue_count = ecc.total_ue_count;
596 	err_data->new_de_count = ecc.new_de_count;
597 	err_data->total_de_count = ecc.total_de_count;
598 	mutex_unlock(&ras_core->ras_aca.aca_lock);
599 
600 	return 0;
601 }
602 
603 int ras_aca_sw_init(struct ras_core_context *ras_core)
604 {
605 	struct ras_aca *ras_aca = &ras_core->ras_aca;
606 	struct ras_aca_config *aca_cfg = &ras_core->config->aca_cfg;
607 	struct aca_block *aca_blk;
608 	uint32_t socket_num_per_hive;
609 	uint32_t aid_num_per_socket;
610 	uint32_t xcd_num_per_aid;
611 	int blk, skt, aid;
612 
613 	socket_num_per_hive = aca_cfg->socket_num_per_hive;
614 	aid_num_per_socket = aca_cfg->aid_num_per_socket;
615 	xcd_num_per_aid = aca_cfg->xcd_num_per_aid;
616 
617 	if (!xcd_num_per_aid || !aid_num_per_socket ||
618 		(socket_num_per_hive > MAX_SOCKET_NUM_PER_HIVE) ||
619 	    (aid_num_per_socket > MAX_AID_NUM_PER_SOCKET) ||
620 	    (xcd_num_per_aid > MAX_XCD_NUM_PER_AID)) {
621 		RAS_DEV_ERR(ras_core->dev, "Invalid ACA system configuration: %d, %d, %d\n",
622 			socket_num_per_hive, aid_num_per_socket, xcd_num_per_aid);
623 		return -EINVAL;
624 	}
625 
626 	memset(ras_aca, 0, sizeof(*ras_aca));
627 
628 	for (blk = 0; blk < RAS_BLOCK_ID__LAST; blk++) {
629 		aca_blk = &ras_aca->aca_blk[blk];
630 		aca_blk->ecc.socket_num_per_hive = socket_num_per_hive;
631 		for (skt = 0; skt < aca_blk->ecc.socket_num_per_hive; skt++) {
632 			aca_blk->ecc.socket[skt].aid_num = aid_num_per_socket;
633 			if (blk == RAS_BLOCK_ID__GFX) {
634 				for (aid = 0; aid < aca_blk->ecc.socket[skt].aid_num; aid++)
635 					aca_blk->ecc.socket[skt].aid[aid].xcd.xcd_num =
636 								xcd_num_per_aid;
637 			}
638 		}
639 	}
640 
641 	mutex_init(&ras_aca->aca_lock);
642 	mutex_init(&ras_aca->bank_op_lock);
643 
644 	return 0;
645 }
646 
647 int ras_aca_sw_fini(struct ras_core_context *ras_core)
648 {
649 	struct ras_aca *ras_aca = &ras_core->ras_aca;
650 
651 	mutex_destroy(&ras_aca->aca_lock);
652 	mutex_destroy(&ras_aca->bank_op_lock);
653 
654 	return 0;
655 }
656 
657 int ras_aca_hw_init(struct ras_core_context *ras_core)
658 {
659 	struct ras_aca *ras_aca = &ras_core->ras_aca;
660 	struct aca_block *aca_blk;
661 	const struct ras_aca_ip_func *ip_func;
662 	int i;
663 
664 	ras_aca->aca_ip_version = ras_core->config->aca_ip_version;
665 	ip_func = aca_get_ip_func(ras_core, ras_aca->aca_ip_version);
666 	if (!ip_func)
667 		return -EINVAL;
668 
669 	for (i = 0; i < ip_func->block_num; i++) {
670 		aca_blk = &ras_aca->aca_blk[ip_func->block_info[i]->ras_block_id];
671 		aca_blk->blk_info = ip_func->block_info[i];
672 	}
673 
674 	ras_aca->ue_updated_mark = 0;
675 
676 	return 0;
677 }
678 
679 int ras_aca_hw_fini(struct ras_core_context *ras_core)
680 {
681 	struct ras_aca *ras_aca = &ras_core->ras_aca;
682 
683 	ras_aca->ue_updated_mark = 0;
684 
685 	return 0;
686 }
687