summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c')
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c368
1 files changed, 119 insertions, 249 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c
index b265b4d9053f..baa8cc3646d5 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c
@@ -124,8 +124,6 @@
RAS_TABLE_V2_1_INFO_SIZE) \
/ RAS_TABLE_RECORD_SIZE)
-#define RAS_SMU_MESSAGE_TIMEOUT_MS 1000 /* 1s */
-
/* Given a zero-based index of an EEPROM RAS record, yields the EEPROM
* offset off of RAS_TABLE_START. That is, this is something you can
* add to control->i2c_address, and then tell I2C layer to read
@@ -159,6 +157,9 @@
static bool __is_ras_eeprom_supported(struct amdgpu_device *adev)
{
+ if (amdgpu_sriov_vf(adev))
+ return false;
+
switch (amdgpu_ip_version(adev, MP1_HWIP, 0)) {
case IP_VERSION(11, 0, 2): /* VEGA20 and ARCTURUS */
case IP_VERSION(11, 0, 7): /* Sienna cichlid */
@@ -449,57 +450,46 @@ int amdgpu_ras_eeprom_reset_table(struct amdgpu_ras_eeprom_control *control)
struct amdgpu_ras_eeprom_table_header *hdr = &control->tbl_hdr;
struct amdgpu_ras_eeprom_table_ras_info *rai = &control->tbl_rai;
struct amdgpu_ras *con = amdgpu_ras_get_context(adev);
- u32 erase_res = 0;
u8 csum;
int res;
mutex_lock(&control->ras_tbl_mutex);
- if (!amdgpu_ras_smu_eeprom_supported(adev)) {
- hdr->header = RAS_TABLE_HDR_VAL;
- amdgpu_ras_set_eeprom_table_version(control);
-
- if (hdr->version >= RAS_TABLE_VER_V2_1) {
- hdr->first_rec_offset = RAS_RECORD_START_V2_1;
- hdr->tbl_size = RAS_TABLE_HEADER_SIZE +
- RAS_TABLE_V2_1_INFO_SIZE;
- rai->rma_status = GPU_HEALTH_USABLE;
-
- control->ras_record_offset = RAS_RECORD_START_V2_1;
- control->ras_max_record_count = RAS_MAX_RECORD_COUNT_V2_1;
- /**
- * GPU health represented as a percentage.
- * 0 means worst health, 100 means fully health.
- */
- rai->health_percent = 100;
- /* ecc_page_threshold = 0 means disable bad page retirement */
- rai->ecc_page_threshold = con->bad_page_cnt_threshold;
- } else {
- hdr->first_rec_offset = RAS_RECORD_START;
- hdr->tbl_size = RAS_TABLE_HEADER_SIZE;
+ hdr->header = RAS_TABLE_HDR_VAL;
+ amdgpu_ras_set_eeprom_table_version(control);
- control->ras_record_offset = RAS_RECORD_START;
- control->ras_max_record_count = RAS_MAX_RECORD_COUNT;
- }
+ if (hdr->version >= RAS_TABLE_VER_V2_1) {
+ hdr->first_rec_offset = RAS_RECORD_START_V2_1;
+ hdr->tbl_size = RAS_TABLE_HEADER_SIZE +
+ RAS_TABLE_V2_1_INFO_SIZE;
+ rai->rma_status = GPU_HEALTH_USABLE;
- csum = __calc_hdr_byte_sum(control);
- if (hdr->version >= RAS_TABLE_VER_V2_1)
- csum += __calc_ras_info_byte_sum(control);
- csum = -csum;
- hdr->checksum = csum;
- res = __write_table_header(control);
- if (!res && hdr->version > RAS_TABLE_VER_V1)
- res = __write_table_ras_info(control);
+ control->ras_record_offset = RAS_RECORD_START_V2_1;
+ control->ras_max_record_count = RAS_MAX_RECORD_COUNT_V2_1;
+ /**
+ * GPU health represented as a percentage.
+ * 0 means worst health, 100 means fully health.
+ */
+ rai->health_percent = 100;
+ /* ecc_page_threshold = 0 means disable bad page retirement */
+ rai->ecc_page_threshold = con->bad_page_cnt_threshold;
} else {
- res = amdgpu_ras_smu_erase_ras_table(adev, &erase_res);
- if (res || erase_res) {
- dev_warn(adev->dev, "RAS EEPROM reset failed, res:%d result:%d",
- res, erase_res);
- if (!res)
- res = -EIO;
- }
+ hdr->first_rec_offset = RAS_RECORD_START;
+ hdr->tbl_size = RAS_TABLE_HEADER_SIZE;
+
+ control->ras_record_offset = RAS_RECORD_START;
+ control->ras_max_record_count = RAS_MAX_RECORD_COUNT;
}
+ csum = __calc_hdr_byte_sum(control);
+ if (hdr->version >= RAS_TABLE_VER_V2_1)
+ csum += __calc_ras_info_byte_sum(control);
+ csum = -csum;
+ hdr->checksum = csum;
+ res = __write_table_header(control);
+ if (!res && hdr->version > RAS_TABLE_VER_V1)
+ res = __write_table_ras_info(control);
+
control->ras_num_recs = 0;
control->ras_num_bad_pages = 0;
control->ras_num_mca_recs = 0;
@@ -662,7 +652,6 @@ amdgpu_ras_eeprom_append_table(struct amdgpu_ras_eeprom_control *control,
const u32 num)
{
struct amdgpu_ras *con = amdgpu_ras_get_context(to_amdgpu_device(control));
- struct amdgpu_device *adev = to_amdgpu_device(control);
u32 a, b, i;
u8 *buf, *pp;
int res;
@@ -767,10 +756,7 @@ amdgpu_ras_eeprom_append_table(struct amdgpu_ras_eeprom_control *control,
% control->ras_max_record_count;
/*old asics only save pa to eeprom like before*/
- if (IP_VERSION_MAJ(amdgpu_ip_version(adev, UMC_HWIP, 0)) < 12)
- control->ras_num_pa_recs += num;
- else
- control->ras_num_mca_recs += num;
+ control->ras_num_pa_recs += num;
control->ras_num_bad_pages = con->bad_page_num;
Out:
@@ -879,71 +865,6 @@ Out:
return res;
}
-int amdgpu_ras_eeprom_update_record_num(struct amdgpu_ras_eeprom_control *control)
-{
- struct amdgpu_device *adev = to_amdgpu_device(control);
- int ret, retry = 20;
-
- if (!amdgpu_ras_smu_eeprom_supported(adev))
- return 0;
-
- control->ras_num_recs_old = control->ras_num_recs;
-
- do {
- /* 1000ms timeout is long enough, smu_get_badpage_count won't
- * return -EBUSY before timeout.
- */
- ret = amdgpu_ras_smu_get_badpage_count(adev,
- &(control->ras_num_recs), RAS_SMU_MESSAGE_TIMEOUT_MS);
- if (!ret &&
- (control->ras_num_recs_old == control->ras_num_recs)) {
- /* record number update in PMFW needs some time,
- * smu_get_badpage_count may return immediately without
- * count update, sleep for a while and retry again.
- */
- msleep(50);
- retry--;
- } else {
- break;
- }
- } while (retry);
-
- /* no update of record number is not a real failure,
- * don't print warning here
- */
- if (!ret && (control->ras_num_recs_old == control->ras_num_recs))
- ret = -EINVAL;
-
- return ret;
-}
-
-static int amdgpu_ras_smu_eeprom_append(struct amdgpu_ras_eeprom_control *control)
-{
- struct amdgpu_device *adev = to_amdgpu_device(control);
- struct amdgpu_ras *con = amdgpu_ras_get_context(adev);
-
- if (!amdgpu_ras_smu_eeprom_supported(adev) || !con)
- return 0;
-
- control->ras_num_bad_pages = con->bad_page_num;
-
- if (amdgpu_bad_page_threshold != 0 &&
- control->ras_num_bad_pages > con->bad_page_cnt_threshold) {
- dev_warn(adev->dev,
- "Saved bad pages %d reaches threshold value %d\n",
- control->ras_num_bad_pages, con->bad_page_cnt_threshold);
-
- if (adev->cper.enabled && amdgpu_cper_generate_bp_threshold_record(adev))
- dev_warn(adev->dev, "fail to generate bad page threshold cper records\n");
-
- if ((amdgpu_bad_page_threshold != -1) &&
- (amdgpu_bad_page_threshold != -2))
- con->is_rma = true;
- }
-
- return 0;
-}
-
/**
* amdgpu_ras_eeprom_append -- append records to the EEPROM RAS table
* @control: pointer to control structure
@@ -968,9 +889,6 @@ int amdgpu_ras_eeprom_append(struct amdgpu_ras_eeprom_control *control,
if (!__is_ras_eeprom_supported(adev))
return 0;
- if (amdgpu_ras_smu_eeprom_supported(adev))
- return amdgpu_ras_smu_eeprom_append(control);
-
if (num == 0) {
dev_err(adev->dev, "will not append 0 records\n");
return -EINVAL;
@@ -1046,52 +964,6 @@ static int __amdgpu_ras_eeprom_read(struct amdgpu_ras_eeprom_control *control,
return res;
}
-int amdgpu_ras_eeprom_read_idx(struct amdgpu_ras_eeprom_control *control,
- struct eeprom_table_record *record, u32 rec_idx,
- const u32 num)
-{
- struct amdgpu_device *adev = to_amdgpu_device(control);
- uint64_t ts, end_idx;
- int i, ret;
- u64 mca, ipid;
- u32 cu, mem_channel, mcumc_id;
-
- if (!amdgpu_ras_smu_eeprom_supported(adev))
- return 0;
-
- if (!adev->umc.ras || !adev->umc.ras->mca_ipid_parse)
- return -EOPNOTSUPP;
-
- end_idx = rec_idx + num;
- for (i = rec_idx; i < end_idx; i++) {
- ret = amdgpu_ras_smu_get_badpage_mca_addr(adev, i, &mca);
- if (ret)
- return ret;
-
- ret = amdgpu_ras_smu_get_badpage_ipid(adev, i, &ipid);
- if (ret)
- return ret;
-
- ret = amdgpu_ras_smu_get_timestamp(adev, i, &ts);
- if (ret)
- return ret;
-
- record[i - rec_idx].address = mca;
- /* retired_page (pa) is unused now */
- record[i - rec_idx].retired_page = 0x1ULL;
- record[i - rec_idx].ts = ts;
- record[i - rec_idx].err_type = AMDGPU_RAS_EEPROM_ERR_NON_RECOVERABLE;
-
- adev->umc.ras->mca_ipid_parse(adev, ipid,
- &cu, &mem_channel, &mcumc_id, NULL);
- record[i - rec_idx].cu = (u8)cu;
- record[i - rec_idx].mem_channel = (u8)mem_channel;
- record[i - rec_idx].mcumc_id = (u8)mcumc_id;
- }
-
- return 0;
-}
-
/**
* amdgpu_ras_eeprom_read -- read EEPROM
* @control: pointer to control structure
@@ -1113,9 +985,6 @@ int amdgpu_ras_eeprom_read(struct amdgpu_ras_eeprom_control *control,
u8 *buf, *pp;
u32 g0, g1;
- if (amdgpu_ras_smu_eeprom_supported(adev))
- return amdgpu_ras_eeprom_read_idx(control, record, 0, num);
-
if (!__is_ras_eeprom_supported(adev))
return 0;
@@ -1396,6 +1265,86 @@ Out:
}
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)
{
@@ -1408,6 +1357,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)
@@ -1521,42 +1474,6 @@ Out:
return res == RAS_TABLE_V2_1_INFO_SIZE ? 0 : res;
}
-static int amdgpu_ras_smu_eeprom_init(struct amdgpu_ras_eeprom_control *control)
-{
- struct amdgpu_device *adev = to_amdgpu_device(control);
- struct amdgpu_ras_eeprom_table_header *hdr = &control->tbl_hdr;
- struct amdgpu_ras *ras = amdgpu_ras_get_context(adev);
- uint64_t local_time;
- int res;
-
- ras->is_rma = false;
-
- if (!__is_ras_eeprom_supported(adev))
- return 0;
- mutex_init(&control->ras_tbl_mutex);
-
- res = amdgpu_ras_smu_get_table_version(adev, &(hdr->version));
- if (res)
- return res;
-
- res = amdgpu_ras_smu_get_badpage_count(adev,
- &(control->ras_num_recs), 100);
- if (res)
- return res;
-
- local_time = (uint64_t)ktime_get_real_seconds();
- res = amdgpu_ras_smu_set_timestamp(adev, local_time);
- if (res)
- return res;
-
- control->ras_max_record_count = 4000;
-
- control->ras_num_mca_recs = 0;
- control->ras_num_pa_recs = 0;
-
- return 0;
-}
-
int amdgpu_ras_eeprom_init(struct amdgpu_ras_eeprom_control *control)
{
struct amdgpu_device *adev = to_amdgpu_device(control);
@@ -1567,9 +1484,6 @@ int amdgpu_ras_eeprom_init(struct amdgpu_ras_eeprom_control *control)
uint32_t vram_type = adev->gmc.vram_type;
int res;
- if (amdgpu_ras_smu_eeprom_supported(adev))
- return amdgpu_ras_smu_eeprom_init(control);
-
ras->is_rma = false;
if (!__is_ras_eeprom_supported(adev))
@@ -1663,47 +1577,6 @@ int amdgpu_ras_eeprom_init(struct amdgpu_ras_eeprom_control *control)
return 0;
}
-static int amdgpu_ras_smu_eeprom_check(struct amdgpu_ras_eeprom_control *control)
-{
- struct amdgpu_device *adev = to_amdgpu_device(control);
- struct amdgpu_ras *ras = amdgpu_ras_get_context(adev);
-
- if (!__is_ras_eeprom_supported(adev))
- return 0;
-
- control->ras_num_bad_pages = ras->bad_page_num;
-
- if ((ras->bad_page_cnt_threshold < control->ras_num_bad_pages) &&
- amdgpu_bad_page_threshold != 0) {
- dev_warn(adev->dev,
- "RAS records:%d exceed threshold:%d\n",
- control->ras_num_bad_pages, ras->bad_page_cnt_threshold);
- if ((amdgpu_bad_page_threshold == -1) ||
- (amdgpu_bad_page_threshold == -2)) {
- dev_warn(adev->dev,
- "Please consult AMD Service Action Guide (SAG) for appropriate service procedures\n");
- } else {
- ras->is_rma = true;
- dev_warn(adev->dev,
- "User defined threshold is set, runtime service will be halt when threshold is reached\n");
- }
-
- return 0;
- }
-
- dev_dbg(adev->dev,
- "Found existing EEPROM table with %d records",
- control->ras_num_bad_pages);
-
- /* Warn if we are at 90% of the threshold or above
- */
- if (10 * control->ras_num_bad_pages >= 9 * ras->bad_page_cnt_threshold)
- dev_warn(adev->dev, "RAS records:%u exceeds 90%% of threshold:%d",
- control->ras_num_bad_pages,
- ras->bad_page_cnt_threshold);
- return 0;
-}
-
int amdgpu_ras_eeprom_check(struct amdgpu_ras_eeprom_control *control)
{
struct amdgpu_device *adev = to_amdgpu_device(control);
@@ -1711,9 +1584,6 @@ int amdgpu_ras_eeprom_check(struct amdgpu_ras_eeprom_control *control)
struct amdgpu_ras *ras = amdgpu_ras_get_context(adev);
int res = 0;
- if (amdgpu_ras_smu_eeprom_supported(adev))
- return amdgpu_ras_smu_eeprom_check(control);
-
if (!__is_ras_eeprom_supported(adev))
return 0;
@@ -1973,7 +1843,7 @@ void amdgpu_ras_check_bad_page_status(struct amdgpu_device *adev)
struct amdgpu_ras *ras = amdgpu_ras_get_context(adev);
struct amdgpu_ras_eeprom_control *control = ras ? &ras->eeprom_control : NULL;
- if (!control || amdgpu_bad_page_threshold == 0)
+ if (!__is_ras_eeprom_supported(adev) || !control || amdgpu_bad_page_threshold == 0)
return;
if (control->ras_num_bad_pages > ras->bad_page_cnt_threshold) {