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