1 /* 2 * Copyright 2019 Advanced Micro Devices, Inc. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included in 12 * all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 * OTHER DEALINGS IN THE SOFTWARE. 21 * 22 */ 23 24 #include "amdgpu_ras_eeprom.h" 25 #include "amdgpu.h" 26 #include "amdgpu_ras.h" 27 #include <linux/bits.h> 28 #include "atom.h" 29 #include "amdgpu_atomfirmware.h" 30 31 #define EEPROM_I2C_TARGET_ADDR_VEGA20 0xA0 32 #define EEPROM_I2C_TARGET_ADDR_ARCTURUS 0xA8 33 #define EEPROM_I2C_TARGET_ADDR_ARCTURUS_D342 0xA0 34 #define EEPROM_I2C_TARGET_ADDR_SIENNA_CICHLID 0xA0 35 #define EEPROM_I2C_TARGET_ADDR_ALDEBARAN 0xA0 36 37 /* 38 * The 2 macros bellow represent the actual size in bytes that 39 * those entities occupy in the EEPROM memory. 40 * EEPROM_TABLE_RECORD_SIZE is different than sizeof(eeprom_table_record) which 41 * uses uint64 to store 6b fields such as retired_page. 42 */ 43 #define EEPROM_TABLE_HEADER_SIZE 20 44 #define EEPROM_TABLE_RECORD_SIZE 24 45 46 #define EEPROM_ADDRESS_SIZE 0x2 47 48 /* Table hdr is 'AMDR' */ 49 #define EEPROM_TABLE_HDR_VAL 0x414d4452 50 #define EEPROM_TABLE_VER 0x00010000 51 52 /* Bad GPU tag ‘BADG’ */ 53 #define EEPROM_TABLE_HDR_BAD 0x42414447 54 55 /* Assume 2 Mbit size */ 56 #define EEPROM_SIZE_BYTES 256000 57 #define EEPROM_PAGE__SIZE_BYTES 256 58 #define EEPROM_HDR_START 0 59 #define EEPROM_RECORD_START (EEPROM_HDR_START + EEPROM_TABLE_HEADER_SIZE) 60 #define EEPROM_MAX_RECORD_NUM ((EEPROM_SIZE_BYTES - EEPROM_TABLE_HEADER_SIZE) / EEPROM_TABLE_RECORD_SIZE) 61 #define EEPROM_ADDR_MSB_MASK GENMASK(17, 8) 62 63 #define to_amdgpu_device(x) (container_of(x, struct amdgpu_ras, eeprom_control))->adev 64 65 static bool __is_ras_eeprom_supported(struct amdgpu_device *adev) 66 { 67 if ((adev->asic_type == CHIP_VEGA20) || 68 (adev->asic_type == CHIP_ARCTURUS) || 69 (adev->asic_type == CHIP_SIENNA_CICHLID) || 70 (adev->asic_type == CHIP_ALDEBARAN)) 71 return true; 72 73 return false; 74 } 75 76 static bool __get_eeprom_i2c_addr_arct(struct amdgpu_device *adev, 77 uint16_t *i2c_addr) 78 { 79 struct atom_context *atom_ctx = adev->mode_info.atom_context; 80 81 if (!i2c_addr || !atom_ctx) 82 return false; 83 84 if (strnstr(atom_ctx->vbios_version, 85 "D342", 86 sizeof(atom_ctx->vbios_version))) 87 *i2c_addr = EEPROM_I2C_TARGET_ADDR_ARCTURUS_D342; 88 else 89 *i2c_addr = EEPROM_I2C_TARGET_ADDR_ARCTURUS; 90 91 return true; 92 } 93 94 static bool __get_eeprom_i2c_addr(struct amdgpu_device *adev, 95 uint16_t *i2c_addr) 96 { 97 if (!i2c_addr) 98 return false; 99 100 if (amdgpu_atomfirmware_ras_rom_addr(adev, (uint8_t*)i2c_addr)) 101 return true; 102 103 switch (adev->asic_type) { 104 case CHIP_VEGA20: 105 *i2c_addr = EEPROM_I2C_TARGET_ADDR_VEGA20; 106 break; 107 108 case CHIP_ARCTURUS: 109 return __get_eeprom_i2c_addr_arct(adev, i2c_addr); 110 111 case CHIP_SIENNA_CICHLID: 112 *i2c_addr = EEPROM_I2C_TARGET_ADDR_SIENNA_CICHLID; 113 break; 114 115 case CHIP_ALDEBARAN: 116 *i2c_addr = EEPROM_I2C_TARGET_ADDR_ALDEBARAN; 117 break; 118 119 default: 120 return false; 121 } 122 123 return true; 124 } 125 126 static void __encode_table_header_to_buff(struct amdgpu_ras_eeprom_table_header *hdr, 127 unsigned char *buff) 128 { 129 uint32_t *pp = (uint32_t *) buff; 130 131 pp[0] = cpu_to_le32(hdr->header); 132 pp[1] = cpu_to_le32(hdr->version); 133 pp[2] = cpu_to_le32(hdr->first_rec_offset); 134 pp[3] = cpu_to_le32(hdr->tbl_size); 135 pp[4] = cpu_to_le32(hdr->checksum); 136 } 137 138 static void __decode_table_header_from_buff(struct amdgpu_ras_eeprom_table_header *hdr, 139 unsigned char *buff) 140 { 141 uint32_t *pp = (uint32_t *)buff; 142 143 hdr->header = le32_to_cpu(pp[0]); 144 hdr->version = le32_to_cpu(pp[1]); 145 hdr->first_rec_offset = le32_to_cpu(pp[2]); 146 hdr->tbl_size = le32_to_cpu(pp[3]); 147 hdr->checksum = le32_to_cpu(pp[4]); 148 } 149 150 static int __update_table_header(struct amdgpu_ras_eeprom_control *control, 151 unsigned char *buff) 152 { 153 int ret = 0; 154 struct amdgpu_device *adev = to_amdgpu_device(control); 155 struct i2c_msg msg = { 156 .addr = 0, 157 .flags = 0, 158 .len = EEPROM_ADDRESS_SIZE + EEPROM_TABLE_HEADER_SIZE, 159 .buf = buff, 160 }; 161 162 163 *(uint16_t *)buff = EEPROM_HDR_START; 164 __encode_table_header_to_buff(&control->tbl_hdr, buff + EEPROM_ADDRESS_SIZE); 165 166 msg.addr = control->i2c_address; 167 168 /* i2c may be unstable in gpu reset */ 169 down_read(&adev->reset_sem); 170 ret = i2c_transfer(&adev->pm.smu_i2c, &msg, 1); 171 up_read(&adev->reset_sem); 172 173 if (ret < 1) 174 DRM_ERROR("Failed to write EEPROM table header, ret:%d", ret); 175 176 return ret; 177 } 178 179 static uint32_t __calc_hdr_byte_sum(struct amdgpu_ras_eeprom_control *control) 180 { 181 int i; 182 uint32_t tbl_sum = 0; 183 184 /* Header checksum, skip checksum field in the calculation */ 185 for (i = 0; i < sizeof(control->tbl_hdr) - sizeof(control->tbl_hdr.checksum); i++) 186 tbl_sum += *(((unsigned char *)&control->tbl_hdr) + i); 187 188 return tbl_sum; 189 } 190 191 static uint32_t __calc_recs_byte_sum(struct eeprom_table_record *records, 192 int num) 193 { 194 int i, j; 195 uint32_t tbl_sum = 0; 196 197 /* Records checksum */ 198 for (i = 0; i < num; i++) { 199 struct eeprom_table_record *record = &records[i]; 200 201 for (j = 0; j < sizeof(*record); j++) { 202 tbl_sum += *(((unsigned char *)record) + j); 203 } 204 } 205 206 return tbl_sum; 207 } 208 209 static inline uint32_t __calc_tbl_byte_sum(struct amdgpu_ras_eeprom_control *control, 210 struct eeprom_table_record *records, int num) 211 { 212 return __calc_hdr_byte_sum(control) + __calc_recs_byte_sum(records, num); 213 } 214 215 /* Checksum = 256 -((sum of all table entries) mod 256) */ 216 static void __update_tbl_checksum(struct amdgpu_ras_eeprom_control *control, 217 struct eeprom_table_record *records, int num, 218 uint32_t old_hdr_byte_sum) 219 { 220 /* 221 * This will update the table sum with new records. 222 * 223 * TODO: What happens when the EEPROM table is to be wrapped around 224 * and old records from start will get overridden. 225 */ 226 227 /* need to recalculate updated header byte sum */ 228 control->tbl_byte_sum -= old_hdr_byte_sum; 229 control->tbl_byte_sum += __calc_tbl_byte_sum(control, records, num); 230 231 control->tbl_hdr.checksum = 256 - (control->tbl_byte_sum % 256); 232 } 233 234 /* table sum mod 256 + checksum must equals 256 */ 235 static bool __validate_tbl_checksum(struct amdgpu_ras_eeprom_control *control, 236 struct eeprom_table_record *records, int num) 237 { 238 control->tbl_byte_sum = __calc_tbl_byte_sum(control, records, num); 239 240 if (control->tbl_hdr.checksum + (control->tbl_byte_sum % 256) != 256) { 241 DRM_WARN("Checksum mismatch, checksum: %u ", control->tbl_hdr.checksum); 242 return false; 243 } 244 245 return true; 246 } 247 248 static int amdgpu_ras_eeprom_correct_header_tag( 249 struct amdgpu_ras_eeprom_control *control, 250 uint32_t header) 251 { 252 unsigned char buff[EEPROM_ADDRESS_SIZE + EEPROM_TABLE_HEADER_SIZE]; 253 struct amdgpu_ras_eeprom_table_header *hdr = &control->tbl_hdr; 254 int ret = 0; 255 256 memset(buff, 0, EEPROM_ADDRESS_SIZE + EEPROM_TABLE_HEADER_SIZE); 257 258 mutex_lock(&control->tbl_mutex); 259 hdr->header = header; 260 ret = __update_table_header(control, buff); 261 mutex_unlock(&control->tbl_mutex); 262 263 return ret; 264 } 265 266 int amdgpu_ras_eeprom_reset_table(struct amdgpu_ras_eeprom_control *control) 267 { 268 unsigned char buff[EEPROM_ADDRESS_SIZE + EEPROM_TABLE_HEADER_SIZE] = { 0 }; 269 struct amdgpu_ras_eeprom_table_header *hdr = &control->tbl_hdr; 270 int ret = 0; 271 272 mutex_lock(&control->tbl_mutex); 273 274 hdr->header = EEPROM_TABLE_HDR_VAL; 275 hdr->version = EEPROM_TABLE_VER; 276 hdr->first_rec_offset = EEPROM_RECORD_START; 277 hdr->tbl_size = EEPROM_TABLE_HEADER_SIZE; 278 279 control->tbl_byte_sum = 0; 280 __update_tbl_checksum(control, NULL, 0, 0); 281 control->next_addr = EEPROM_RECORD_START; 282 283 ret = __update_table_header(control, buff); 284 285 mutex_unlock(&control->tbl_mutex); 286 287 return ret; 288 289 } 290 291 int amdgpu_ras_eeprom_init(struct amdgpu_ras_eeprom_control *control, 292 bool *exceed_err_limit) 293 { 294 int ret = 0; 295 struct amdgpu_device *adev = to_amdgpu_device(control); 296 unsigned char buff[EEPROM_ADDRESS_SIZE + EEPROM_TABLE_HEADER_SIZE] = { 0 }; 297 struct amdgpu_ras_eeprom_table_header *hdr = &control->tbl_hdr; 298 struct amdgpu_ras *ras = amdgpu_ras_get_context(adev); 299 struct i2c_msg msg = { 300 .addr = 0, 301 .flags = I2C_M_RD, 302 .len = EEPROM_ADDRESS_SIZE + EEPROM_TABLE_HEADER_SIZE, 303 .buf = buff, 304 }; 305 306 *exceed_err_limit = false; 307 308 if (!__is_ras_eeprom_supported(adev)) 309 return 0; 310 311 /* Verify i2c adapter is initialized */ 312 if (!adev->pm.smu_i2c.algo) 313 return -ENOENT; 314 315 if (!__get_eeprom_i2c_addr(adev, &control->i2c_address)) 316 return -EINVAL; 317 318 mutex_init(&control->tbl_mutex); 319 320 msg.addr = control->i2c_address; 321 /* Read/Create table header from EEPROM address 0 */ 322 ret = i2c_transfer(&adev->pm.smu_i2c, &msg, 1); 323 if (ret < 1) { 324 DRM_ERROR("Failed to read EEPROM table header, ret:%d", ret); 325 return ret; 326 } 327 328 __decode_table_header_from_buff(hdr, &buff[2]); 329 330 if (hdr->header == EEPROM_TABLE_HDR_VAL) { 331 control->num_recs = (hdr->tbl_size - EEPROM_TABLE_HEADER_SIZE) / 332 EEPROM_TABLE_RECORD_SIZE; 333 control->tbl_byte_sum = __calc_hdr_byte_sum(control); 334 control->next_addr = EEPROM_RECORD_START; 335 336 DRM_DEBUG_DRIVER("Found existing EEPROM table with %d records", 337 control->num_recs); 338 339 } else if ((hdr->header == EEPROM_TABLE_HDR_BAD) && 340 (amdgpu_bad_page_threshold != 0)) { 341 if (ras->bad_page_cnt_threshold > control->num_recs) { 342 dev_info(adev->dev, "Using one valid bigger bad page " 343 "threshold and correcting eeprom header tag.\n"); 344 ret = amdgpu_ras_eeprom_correct_header_tag(control, 345 EEPROM_TABLE_HDR_VAL); 346 } else { 347 *exceed_err_limit = true; 348 dev_err(adev->dev, "Exceeding the bad_page_threshold parameter, " 349 "disabling the GPU.\n"); 350 } 351 } else { 352 DRM_INFO("Creating new EEPROM table"); 353 354 ret = amdgpu_ras_eeprom_reset_table(control); 355 } 356 357 return ret == 1 ? 0 : -EIO; 358 } 359 360 static void __encode_table_record_to_buff(struct amdgpu_ras_eeprom_control *control, 361 struct eeprom_table_record *record, 362 unsigned char *buff) 363 { 364 __le64 tmp = 0; 365 int i = 0; 366 367 /* Next are all record fields according to EEPROM page spec in LE foramt */ 368 buff[i++] = record->err_type; 369 370 buff[i++] = record->bank; 371 372 tmp = cpu_to_le64(record->ts); 373 memcpy(buff + i, &tmp, 8); 374 i += 8; 375 376 tmp = cpu_to_le64((record->offset & 0xffffffffffff)); 377 memcpy(buff + i, &tmp, 6); 378 i += 6; 379 380 buff[i++] = record->mem_channel; 381 buff[i++] = record->mcumc_id; 382 383 tmp = cpu_to_le64((record->retired_page & 0xffffffffffff)); 384 memcpy(buff + i, &tmp, 6); 385 } 386 387 static void __decode_table_record_from_buff(struct amdgpu_ras_eeprom_control *control, 388 struct eeprom_table_record *record, 389 unsigned char *buff) 390 { 391 __le64 tmp = 0; 392 int i = 0; 393 394 /* Next are all record fields according to EEPROM page spec in LE foramt */ 395 record->err_type = buff[i++]; 396 397 record->bank = buff[i++]; 398 399 memcpy(&tmp, buff + i, 8); 400 record->ts = le64_to_cpu(tmp); 401 i += 8; 402 403 memcpy(&tmp, buff + i, 6); 404 record->offset = (le64_to_cpu(tmp) & 0xffffffffffff); 405 i += 6; 406 407 record->mem_channel = buff[i++]; 408 record->mcumc_id = buff[i++]; 409 410 memcpy(&tmp, buff + i, 6); 411 record->retired_page = (le64_to_cpu(tmp) & 0xffffffffffff); 412 } 413 414 /* 415 * When reaching end of EEPROM memory jump back to 0 record address 416 * When next record access will go beyond EEPROM page boundary modify bits A17/A8 417 * in I2C selector to go to next page 418 */ 419 static uint32_t __correct_eeprom_dest_address(uint32_t curr_address) 420 { 421 uint32_t next_address = curr_address + EEPROM_TABLE_RECORD_SIZE; 422 423 /* When all EEPROM memory used jump back to 0 address */ 424 if (next_address > EEPROM_SIZE_BYTES) { 425 DRM_INFO("Reached end of EEPROM memory, jumping to 0 " 426 "and overriding old record"); 427 return EEPROM_RECORD_START; 428 } 429 430 /* 431 * To check if we overflow page boundary compare next address with 432 * current and see if bits 17/8 of the EEPROM address will change 433 * If they do start from the next 256b page 434 * 435 * https://www.st.com/resource/en/datasheet/m24m02-dr.pdf sec. 5.1.2 436 */ 437 if ((curr_address & EEPROM_ADDR_MSB_MASK) != (next_address & EEPROM_ADDR_MSB_MASK)) { 438 DRM_DEBUG_DRIVER("Reached end of EEPROM memory page, jumping to next: %lx", 439 (next_address & EEPROM_ADDR_MSB_MASK)); 440 441 return (next_address & EEPROM_ADDR_MSB_MASK); 442 } 443 444 return curr_address; 445 } 446 447 bool amdgpu_ras_eeprom_check_err_threshold(struct amdgpu_device *adev) 448 { 449 struct amdgpu_ras *con = amdgpu_ras_get_context(adev); 450 451 if (!__is_ras_eeprom_supported(adev)) 452 return false; 453 454 /* skip check eeprom table for VEGA20 Gaming */ 455 if (!con) 456 return false; 457 else 458 if (!(con->features & BIT(AMDGPU_RAS_BLOCK__UMC))) 459 return false; 460 461 if (con->eeprom_control.tbl_hdr.header == EEPROM_TABLE_HDR_BAD) { 462 dev_warn(adev->dev, "This GPU is in BAD status."); 463 dev_warn(adev->dev, "Please retire it or setting one bigger " 464 "threshold value when reloading driver.\n"); 465 return true; 466 } 467 468 return false; 469 } 470 471 int amdgpu_ras_eeprom_process_recods(struct amdgpu_ras_eeprom_control *control, 472 struct eeprom_table_record *records, 473 bool write, 474 int num) 475 { 476 int i, ret = 0; 477 struct i2c_msg *msgs, *msg; 478 unsigned char *buffs, *buff; 479 struct eeprom_table_record *record; 480 struct amdgpu_device *adev = to_amdgpu_device(control); 481 struct amdgpu_ras *ras = amdgpu_ras_get_context(adev); 482 483 if (!__is_ras_eeprom_supported(adev)) 484 return 0; 485 486 buffs = kcalloc(num, EEPROM_ADDRESS_SIZE + EEPROM_TABLE_RECORD_SIZE, 487 GFP_KERNEL); 488 if (!buffs) 489 return -ENOMEM; 490 491 mutex_lock(&control->tbl_mutex); 492 493 msgs = kcalloc(num, sizeof(*msgs), GFP_KERNEL); 494 if (!msgs) { 495 ret = -ENOMEM; 496 goto free_buff; 497 } 498 499 /* 500 * If saved bad pages number exceeds the bad page threshold for 501 * the whole VRAM, update table header to mark the BAD GPU tag 502 * and schedule one ras recovery after eeprom write is done, 503 * this can avoid the missing for latest records. 504 * 505 * This new header will be picked up and checked in the bootup 506 * by ras recovery, which may break bootup process to notify 507 * user this GPU is in bad state and to retire such GPU for 508 * further check. 509 */ 510 if (write && (amdgpu_bad_page_threshold != 0) && 511 ((control->num_recs + num) >= ras->bad_page_cnt_threshold)) { 512 dev_warn(adev->dev, 513 "Saved bad pages(%d) reaches threshold value(%d).\n", 514 control->num_recs + num, ras->bad_page_cnt_threshold); 515 control->tbl_hdr.header = EEPROM_TABLE_HDR_BAD; 516 } 517 518 /* In case of overflow just start from beginning to not lose newest records */ 519 if (write && (control->next_addr + EEPROM_TABLE_RECORD_SIZE * num > EEPROM_SIZE_BYTES)) 520 control->next_addr = EEPROM_RECORD_START; 521 522 /* 523 * TODO Currently makes EEPROM writes for each record, this creates 524 * internal fragmentation. Optimized the code to do full page write of 525 * 256b 526 */ 527 for (i = 0; i < num; i++) { 528 buff = &buffs[i * (EEPROM_ADDRESS_SIZE + EEPROM_TABLE_RECORD_SIZE)]; 529 record = &records[i]; 530 msg = &msgs[i]; 531 532 control->next_addr = __correct_eeprom_dest_address(control->next_addr); 533 534 /* 535 * Update bits 16,17 of EEPROM address in I2C address by setting them 536 * to bits 1,2 of Device address byte 537 */ 538 msg->addr = control->i2c_address | 539 ((control->next_addr & EEPROM_ADDR_MSB_MASK) >> 15); 540 msg->flags = write ? 0 : I2C_M_RD; 541 msg->len = EEPROM_ADDRESS_SIZE + EEPROM_TABLE_RECORD_SIZE; 542 msg->buf = buff; 543 544 /* Insert the EEPROM dest addess, bits 0-15 */ 545 buff[0] = ((control->next_addr >> 8) & 0xff); 546 buff[1] = (control->next_addr & 0xff); 547 548 /* EEPROM table content is stored in LE format */ 549 if (write) 550 __encode_table_record_to_buff(control, record, buff + EEPROM_ADDRESS_SIZE); 551 552 /* 553 * The destination EEPROM address might need to be corrected to account 554 * for page or entire memory wrapping 555 */ 556 control->next_addr += EEPROM_TABLE_RECORD_SIZE; 557 } 558 559 /* i2c may be unstable in gpu reset */ 560 down_read(&adev->reset_sem); 561 ret = i2c_transfer(&adev->pm.smu_i2c, msgs, num); 562 up_read(&adev->reset_sem); 563 564 if (ret < 1) { 565 DRM_ERROR("Failed to process EEPROM table records, ret:%d", ret); 566 567 /* TODO Restore prev next EEPROM address ? */ 568 goto free_msgs; 569 } 570 571 572 if (!write) { 573 for (i = 0; i < num; i++) { 574 buff = &buffs[i*(EEPROM_ADDRESS_SIZE + EEPROM_TABLE_RECORD_SIZE)]; 575 record = &records[i]; 576 577 __decode_table_record_from_buff(control, record, buff + EEPROM_ADDRESS_SIZE); 578 } 579 } 580 581 if (write) { 582 uint32_t old_hdr_byte_sum = __calc_hdr_byte_sum(control); 583 584 /* 585 * Update table header with size and CRC and account for table 586 * wrap around where the assumption is that we treat it as empty 587 * table 588 * 589 * TODO - Check the assumption is correct 590 */ 591 control->num_recs += num; 592 control->num_recs %= EEPROM_MAX_RECORD_NUM; 593 control->tbl_hdr.tbl_size += EEPROM_TABLE_RECORD_SIZE * num; 594 if (control->tbl_hdr.tbl_size > EEPROM_SIZE_BYTES) 595 control->tbl_hdr.tbl_size = EEPROM_TABLE_HEADER_SIZE + 596 control->num_recs * EEPROM_TABLE_RECORD_SIZE; 597 598 __update_tbl_checksum(control, records, num, old_hdr_byte_sum); 599 600 __update_table_header(control, buffs); 601 } else if (!__validate_tbl_checksum(control, records, num)) { 602 DRM_WARN("EEPROM Table checksum mismatch!"); 603 /* TODO Uncomment when EEPROM read/write is relliable */ 604 /* ret = -EIO; */ 605 } 606 607 free_msgs: 608 kfree(msgs); 609 610 free_buff: 611 kfree(buffs); 612 613 mutex_unlock(&control->tbl_mutex); 614 615 return ret == num ? 0 : -EIO; 616 } 617 618 inline uint32_t amdgpu_ras_eeprom_get_record_max_length(void) 619 { 620 return EEPROM_MAX_RECORD_NUM; 621 } 622 623 /* Used for testing if bugs encountered */ 624 #if 0 625 void amdgpu_ras_eeprom_test(struct amdgpu_ras_eeprom_control *control) 626 { 627 int i; 628 struct eeprom_table_record *recs = kcalloc(1, sizeof(*recs), GFP_KERNEL); 629 630 if (!recs) 631 return; 632 633 for (i = 0; i < 1 ; i++) { 634 recs[i].address = 0xdeadbeef; 635 recs[i].retired_page = i; 636 } 637 638 if (!amdgpu_ras_eeprom_process_recods(control, recs, true, 1)) { 639 640 memset(recs, 0, sizeof(*recs) * 1); 641 642 control->next_addr = EEPROM_RECORD_START; 643 644 if (!amdgpu_ras_eeprom_process_recods(control, recs, false, 1)) { 645 for (i = 0; i < 1; i++) 646 DRM_INFO("rec.address :0x%llx, rec.retired_page :%llu", 647 recs[i].address, recs[i].retired_page); 648 } else 649 DRM_ERROR("Failed in reading from table"); 650 651 } else 652 DRM_ERROR("Failed in writing to table"); 653 } 654 #endif 655