drivers/gpu/drm/amd/amdgpu/umc_v8_7.c

Source file repositories/reference/linux-study-clean/drivers/gpu/drm/amd/amdgpu/umc_v8_7.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/amd/amdgpu/umc_v8_7.c
Extension
.c
Size
15069 bytes
Lines
447
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

REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, UECC) == 1) {

		err_addr = ras->umc_ecc.ecc[eccinfo_table_idx].mca_umc_addr;
		err_addr = REG_GET_FIELD(err_addr, MCA_UMC_UMC0_MCUMC_ADDRT0, ErrorAddr);

		umc_v8_7_convert_error_address(adev, err_data, err_addr,
						ch_inst, umc_inst);
	}
}

static void umc_v8_7_ecc_info_query_ras_error_address(struct amdgpu_device *adev,
					void *ras_error_status)
{
	struct ras_err_data *err_data = (struct ras_err_data *)ras_error_status;

	uint32_t umc_inst        = 0;
	uint32_t ch_inst         = 0;

	/* TODO: driver needs to toggle DF Cstate to ensure
	 * safe access of UMC resgisters. Will add the protection
	 * when firmware interface is ready
	 */
	LOOP_UMC_INST_AND_CH(umc_inst, ch_inst) {
		umc_v8_7_ecc_info_query_error_address(adev,
						err_data,
						ch_inst,
						umc_inst);
	}
}

static void umc_v8_7_clear_error_count_per_channel(struct amdgpu_device *adev,
					uint32_t umc_reg_offset)
{
	uint32_t ecc_err_cnt_addr;
	uint32_t ecc_err_cnt_sel, ecc_err_cnt_sel_addr;

	ecc_err_cnt_sel_addr =
		SOC15_REG_OFFSET(UMC, 0, mmUMCCH0_0_GeccErrCntSel);
	ecc_err_cnt_addr =
		SOC15_REG_OFFSET(UMC, 0, mmUMCCH0_0_GeccErrCnt);

	/* select the lower chip */
	ecc_err_cnt_sel = RREG32_PCIE((ecc_err_cnt_sel_addr +
					umc_reg_offset) * 4);
	ecc_err_cnt_sel = REG_SET_FIELD(ecc_err_cnt_sel,
					UMCCH0_0_GeccErrCntSel,
					GeccErrCntCsSel, 0);
	WREG32_PCIE((ecc_err_cnt_sel_addr + umc_reg_offset) * 4,
			ecc_err_cnt_sel);

	/* clear lower chip error count */
	WREG32_PCIE((ecc_err_cnt_addr + umc_reg_offset) * 4,
			UMC_V8_7_CE_CNT_INIT);

	/* select the higher chip */
	ecc_err_cnt_sel = RREG32_PCIE((ecc_err_cnt_sel_addr +
					umc_reg_offset) * 4);
	ecc_err_cnt_sel = REG_SET_FIELD(ecc_err_cnt_sel,
					UMCCH0_0_GeccErrCntSel,
					GeccErrCntCsSel, 1);
	WREG32_PCIE((ecc_err_cnt_sel_addr + umc_reg_offset) * 4,
			ecc_err_cnt_sel);

	/* clear higher chip error count */
	WREG32_PCIE((ecc_err_cnt_addr + umc_reg_offset) * 4,
			UMC_V8_7_CE_CNT_INIT);
}

static void umc_v8_7_clear_error_count(struct amdgpu_device *adev)
{
	uint32_t umc_inst        = 0;
	uint32_t ch_inst         = 0;
	uint32_t umc_reg_offset  = 0;

	LOOP_UMC_INST_AND_CH(umc_inst, ch_inst) {
		umc_reg_offset = get_umc_v8_7_reg_offset(adev,
						umc_inst,
						ch_inst);

		umc_v8_7_clear_error_count_per_channel(adev,
						umc_reg_offset);
	}
}

static void umc_v8_7_query_correctable_error_count(struct amdgpu_device *adev,
						   uint32_t umc_reg_offset,
						   unsigned long *error_count)
{
	uint32_t ecc_err_cnt_sel, ecc_err_cnt_sel_addr;
	uint32_t ecc_err_cnt, ecc_err_cnt_addr;

Annotation

Implementation Notes