drivers/gpu/drm/amd/ras/rascore/ras_eeprom_fw.c

Source file repositories/reference/linux-study-clean/drivers/gpu/drm/amd/ras/rascore/ras_eeprom_fw.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/amd/ras/rascore/ras_eeprom_fw.c
Extension
.c
Size
14685 bytes
Lines
523
Domain
Driver Families
Bucket
drivers/gpu
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

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,
				&cu, &mem_channel, &mcumc_id, NULL);
			record_umc[i - rec_idx].cu = (u8)cu;
			record_umc[i - rec_idx].mem_channel = (u8)mem_channel;
			record_umc[i - rec_idx].mcumc_id = (u8)mcumc_id;

			/* 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;
}

int ras_fw_eeprom_update_record(struct ras_core_context *ras_core,
				struct ras_bank_ecc *ras_ecc)
{
	struct ras_fw_eeprom_control *control = &ras_core->ras_fw_eeprom;
	int ret, retry = 20;
	u32 recs_num_new = control->ras_num_recs;

	do {
		/* 1000ms timeout is long enough, smu_get_badpage_count won't
		 * return -EBUSY before timeout.
		 */
		ret = ras_fw_get_badpage_count(ras_core,
			&recs_num_new, RAS_SMU_MESSAGE_TIMEOUT_MS);
		if (!ret &&
		    (recs_num_new == 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);

	if (ret)
		return ret;

	if (recs_num_new > control->ras_num_recs)
		ret = ras_fw_eeprom_read_idx(ras_core, 0,
					ras_ecc, control->ras_num_recs, 1);
	else
		ret = -EINVAL;

	return ret;
}

static int __check_ras_fw_table_status(struct ras_core_context *ras_core)
{
	struct ras_fw_eeprom_control *control = &ras_core->ras_fw_eeprom;
	uint64_t local_time;
	int res;

	mutex_init(&control->ras_tbl_mutex);

	res = ras_fw_get_table_version(ras_core, &(control->version));
	if (res)

Annotation

Implementation Notes