Commit 42c46be2 authored by Gangliang Xie's avatar Gangliang Xie Committed by Alex Deucher
Browse files

drm/amd/ras: add read func for pmfw eeprom



add read func for pmfw eeprom, and adapt address converting
for bad pages loaded from pmfw eeprom

v2: change label 'Out' to 'out'

Signed-off-by: default avatarTao Zhou <tao.zhou1@amd.com>
Signed-off-by: default avatarGangliang Xie <ganglxie@amd.com>
Reviewed-by: default avatarTao Zhou <tao.zhou1@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 3972f41b
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -241,6 +241,7 @@ struct ras_bank_ecc {
	uint64_t status;
	uint64_t ipid;
	uint64_t addr;
	uint64_t ts;
};

struct ras_bank_ecc_node {
+4 −1
Original line number Diff line number Diff line
@@ -241,6 +241,9 @@ static int ras_core_eeprom_recovery(struct ras_core_context *ras_core)
	int count;
	int ret;

	if (ras_fw_eeprom_supported(ras_core))
		count = ras_fw_eeprom_get_record_count(ras_core);
	else
		count = ras_eeprom_get_record_count(ras_core);
	if (!count)
		return 0;
+70 −0
Original line number Diff line number Diff line
@@ -259,3 +259,73 @@ int ras_fw_eeprom_append(struct ras_core_context *ras_core,
	mutex_unlock(&control->ras_tbl_mutex);
	return 0;
}

int ras_fw_eeprom_read_idx(struct ras_core_context *ras_core,
			 struct eeprom_umc_record *record_umc,
			 struct ras_bank_ecc *ras_ecc,
			 u32 rec_idx, const u32 num)
{
	struct ras_fw_eeprom_control *control = &ras_core->ras_fw_eeprom;
	int i, ret, end_idx;
	u64 mca, ipid, ts;

	if (!ras_core->ras_umc.ip_func ||
	    !ras_core->ras_umc.ip_func->mca_ipid_parse)
		return -EOPNOTSUPP;

	mutex_lock(&control->ras_tbl_mutex);

	end_idx = rec_idx + num;
	for (i = rec_idx; i < end_idx; i++) {
		ret = ras_fw_get_badpage_mca_addr(ras_core, i, &mca);
		if (ret)
			goto out;

		ret = ras_fw_get_badpage_ipid(ras_core, i, &ipid);
		if (ret)
			goto out;

		ret = ras_fw_get_timestamp(ras_core, i, &ts);
		if (ret)
			goto out;

		if (record_umc) {
			record_umc[i - rec_idx].address = mca;
			/* retired_page (pa) is unused now */
			record_umc[i - rec_idx].retired_row_pfn = 0x1ULL;
			record_umc[i - rec_idx].ts = ts;
			record_umc[i - rec_idx].err_type = RAS_EEPROM_ERR_NON_RECOVERABLE;

			ras_core->ras_umc.ip_func->mca_ipid_parse(ras_core, ipid,
				(uint32_t *)&(record_umc[i - rec_idx].cu),
				(uint32_t *)&(record_umc[i - rec_idx].mem_channel),
				(uint32_t *)&(record_umc[i - rec_idx].mcumc_id), NULL);

			/* update bad channel bitmap */
			if ((record_umc[i - rec_idx].mem_channel < BITS_PER_TYPE(control->bad_channel_bitmap)) &&
				!(control->bad_channel_bitmap & (1 << record_umc[i - rec_idx].mem_channel))) {
				control->bad_channel_bitmap |= 1 << record_umc[i - rec_idx].mem_channel;
				control->update_channel_flag = true;
			}
		}

		if (ras_ecc) {
			ras_ecc[i - rec_idx].addr = mca;
			ras_ecc[i - rec_idx].ipid = ipid;
			ras_ecc[i - rec_idx].ts = ts;
		}

	}

out:
	mutex_unlock(&control->ras_tbl_mutex);
	return ret;
}

uint32_t ras_fw_eeprom_get_record_count(struct ras_core_context *ras_core)
{
	if (!ras_core)
		return 0;

	return ras_core->ras_fw_eeprom.ras_num_recs;
}
+5 −0
Original line number Diff line number Diff line
@@ -70,5 +70,10 @@ int ras_fw_eeprom_reset_table(struct ras_core_context *ras_core);
bool ras_fw_eeprom_check_safety_watermark(struct ras_core_context *ras_core);
int ras_fw_eeprom_append(struct ras_core_context *ras_core,
			   struct eeprom_umc_record *record, const u32 num);
int ras_fw_eeprom_read_idx(struct ras_core_context *ras_core,
			 struct eeprom_umc_record *record_umc,
			 struct ras_bank_ecc *ras_ecc,
			 u32 rec_idx, const u32 num);
uint32_t ras_fw_eeprom_get_record_count(struct ras_core_context *ras_core);

#endif
+20 −7
Original line number Diff line number Diff line
@@ -448,16 +448,26 @@ int ras_umc_load_bad_pages(struct ras_core_context *ras_core)
	uint32_t ras_num_recs;
	int ret;

	ras_num_recs = ras_eeprom_get_record_count(ras_core);
	if (ras_fw_eeprom_supported(ras_core)) {
		ras_num_recs = ras_fw_eeprom_get_record_count(ras_core);
		/* no bad page record, skip eeprom access */
		if (!ras_num_recs ||
		    ras_core->ras_fw_eeprom.record_threshold_config == DISABLE_RETIRE_PAGE)
			return 0;
	} else {
		ras_num_recs = ras_eeprom_get_record_count(ras_core);
		if (!ras_num_recs ||
		    ras_core->ras_eeprom.record_threshold_config == DISABLE_RETIRE_PAGE)
			return 0;
	}

	bps = kzalloc_objs(*bps, ras_num_recs);
	if (!bps)
		return -ENOMEM;

	if (ras_fw_eeprom_supported(ras_core))
		ret = ras_fw_eeprom_read_idx(ras_core, bps, 0, 0, ras_num_recs);
	else
		ret = ras_eeprom_read(ras_core, bps, ras_num_recs);
	if (ret) {
		RAS_DEV_ERR(ras_core->dev, "Failed to load EEPROM table records!");
@@ -486,6 +496,9 @@ static int ras_umc_save_bad_pages(struct ras_core_context *ras_core)
	if (!data->bps)
		return 0;

	if (ras_fw_eeprom_supported(ras_core))
		eeprom_record_num = ras_fw_eeprom_get_record_count(ras_core);
	else
		eeprom_record_num = ras_eeprom_get_record_count(ras_core);
	mutex_lock(&ras_umc->umc_lock);
	save_count = data->count - eeprom_record_num;
Loading