drm/amdgpu: dump RAS EEPROM table via debugfs

When the RAS core manages the EEPROM, the eeprom_control is never
initialized (amdgpu_ras_init_badpage_info() returns early), so reading
ras/ras_eeprom_table in debugfs printed only a zeroed header and no
records, even though bad-page records exist in the RAS core EEPROM.

Source the table header and records from the RAS core EEPROM
(ras_core->ras_eeprom) in that case, reusing the existing output layout
so the debugfs node keeps the same format. Skip the dump when the
firmware manages the EEPROM, since the records are not stored in the
I2C-backed table then.

Signed-off-by: Xiang Liu <xiang.liu@amd.com>
Reviewed-by: Tao Zhou <tao.zhou1@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
Xiang Liu 2026-06-17 16:51:18 +08:00 committed by Alex Deucher
parent 991fd2cb90
commit 5c64e5c768

View File

@ -1398,6 +1398,86 @@ static ssize_t amdgpu_ras_debugfs_table_read(struct file *f, char __user *buf,
return res < 0 ? res : orig_size - size;
}
static ssize_t
amdgpu_ras_debugfs_table_read_uniras(struct amdgpu_device *adev,
char __user *buf,
size_t size, loff_t *pos)
{
struct amdgpu_ras_mgr *ras_mgr = amdgpu_ras_mgr_get_context(adev);
struct ras_core_context *ras_core = ras_mgr ? ras_mgr->ras_core : NULL;
struct eeprom_umc_record *records = NULL;
struct ras_eeprom_control *control;
size_t bufsz, len = 0;
u32 num_recs;
char *kbuf;
ssize_t res;
int i;
if (!ras_core)
return 0;
/* pmfw manages eeprom data by itself */
if (ras_fw_eeprom_supported(ras_core))
return 0;
control = &ras_core->ras_eeprom;
num_recs = ras_eeprom_get_record_count(ras_core);
bufsz = strlen(tbl_hdr_str) + tbl_hdr_fmt_size +
strlen(rec_hdr_str) + (size_t)rec_hdr_fmt_size * num_recs + 1;
kbuf = kvmalloc(bufsz, GFP_KERNEL);
if (!kbuf)
return -ENOMEM;
if (num_recs) {
records = kvcalloc(num_recs, sizeof(*records), GFP_KERNEL);
if (!records) {
res = -ENOMEM;
goto out;
}
res = ras_eeprom_read(ras_core, records, num_recs);
if (res)
goto out;
}
len += scnprintf(kbuf + len, bufsz - len, "%s", tbl_hdr_str);
len += scnprintf(kbuf + len, bufsz - len, tbl_hdr_fmt,
control->tbl_hdr.header,
control->tbl_hdr.version,
control->tbl_hdr.first_rec_offset,
control->tbl_hdr.tbl_size,
control->tbl_hdr.checksum);
len += scnprintf(kbuf + len, bufsz - len, "%s", rec_hdr_str);
for (i = 0; i < num_recs; i++) {
u32 ai = RAS_RI_TO_AI(control, i);
int et = records[i].err_type;
const char *ets = (et >= 0 && et < AMDGPU_RAS_EEPROM_ERR_COUNT) ?
record_err_type_str[et] : "na";
len += scnprintf(kbuf + len, bufsz - len, rec_hdr_fmt,
i,
RAS_INDEX_TO_OFFSET(control, ai),
ets,
records[i].bank,
records[i].ts,
records[i].offset,
records[i].mem_channel,
records[i].mcumc_id,
records[i].retired_row_pfn);
}
res = simple_read_from_buffer(buf, size, pos, kbuf, len);
out:
kvfree(records);
kvfree(kbuf);
return res;
}
static ssize_t
amdgpu_ras_debugfs_eeprom_table_read(struct file *f, char __user *buf,
size_t size, loff_t *pos)
@ -1411,6 +1491,10 @@ amdgpu_ras_debugfs_eeprom_table_read(struct file *f, char __user *buf,
if (!size)
return size;
if (amdgpu_uniras_enabled(adev))
return amdgpu_ras_debugfs_table_read_uniras(adev, buf,
size, pos);
if (!ras || !control) {
res = snprintf(data, sizeof(data), "Not supported\n");
if (*pos >= res)