diff options
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c')
| -rw-r--r-- | drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c | 71 | 
1 files changed, 71 insertions, 0 deletions
| diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c b/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c index 1bf672966a62..3e1de8c8b372 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c @@ -31,6 +31,7 @@  #include "soc15d.h"  #include "vcn_v2_0.h"  #include "mmsch_v1_0.h" +#include "vcn_v2_5.h"  #include "vcn/vcn_2_5_offset.h"  #include "vcn/vcn_2_5_sh_mask.h" @@ -59,6 +60,7 @@ static int vcn_v2_5_set_powergating_state(void *handle,  static int vcn_v2_5_pause_dpg_mode(struct amdgpu_device *adev,  				int inst_idx, struct dpg_pause_state *new_state);  static int vcn_v2_5_sriov_start(struct amdgpu_device *adev); +static void vcn_v2_5_set_ras_funcs(struct amdgpu_device *adev);  static int amdgpu_ih_clientid_vcns[] = {  	SOC15_IH_CLIENTID_VCN, @@ -100,6 +102,7 @@ static int vcn_v2_5_early_init(void *handle)  	vcn_v2_5_set_dec_ring_funcs(adev);  	vcn_v2_5_set_enc_ring_funcs(adev);  	vcn_v2_5_set_irq_funcs(adev); +	vcn_v2_5_set_ras_funcs(adev);  	return 0;  } @@ -1932,3 +1935,71 @@ const struct amdgpu_ip_block_version vcn_v2_6_ip_block =  		.rev = 0,  		.funcs = &vcn_v2_6_ip_funcs,  }; + +static uint32_t vcn_v2_6_query_poison_by_instance(struct amdgpu_device *adev, +			uint32_t instance, uint32_t sub_block) +{ +	uint32_t poison_stat = 0, reg_value = 0; + +	switch (sub_block) { +	case AMDGPU_VCN_V2_6_VCPU_VCODEC: +		reg_value = RREG32_SOC15(VCN, instance, mmUVD_RAS_VCPU_VCODEC_STATUS); +		poison_stat = REG_GET_FIELD(reg_value, UVD_RAS_VCPU_VCODEC_STATUS, POISONED_PF); +		break; +	default: +		break; +	}; + +	if (poison_stat) +		dev_info(adev->dev, "Poison detected in VCN%d, sub_block%d\n", +			instance, sub_block); + +	return poison_stat; +} + +static bool vcn_v2_6_query_poison_status(struct amdgpu_device *adev) +{ +	uint32_t inst, sub; +	uint32_t poison_stat = 0; + +	for (inst = 0; inst < adev->vcn.num_vcn_inst; inst++) +		for (sub = 0; sub < AMDGPU_VCN_V2_6_MAX_SUB_BLOCK; sub++) +			poison_stat += +			vcn_v2_6_query_poison_by_instance(adev, inst, sub); + +	return !!poison_stat; +} + +const struct amdgpu_ras_block_hw_ops vcn_v2_6_ras_hw_ops = { +	.query_poison_status = vcn_v2_6_query_poison_status, +}; + +static struct amdgpu_vcn_ras vcn_v2_6_ras = { +	.ras_block = { +		.hw_ops = &vcn_v2_6_ras_hw_ops, +	}, +}; + +static void vcn_v2_5_set_ras_funcs(struct amdgpu_device *adev) +{ +	switch (adev->ip_versions[VCN_HWIP][0]) { +	case IP_VERSION(2, 6, 0): +		adev->vcn.ras = &vcn_v2_6_ras; +		break; +	default: +		break; +	} + +	if (adev->vcn.ras) { +		amdgpu_ras_register_ras_block(adev, &adev->vcn.ras->ras_block); + +		strcpy(adev->vcn.ras->ras_block.ras_comm.name, "vcn"); +		adev->vcn.ras->ras_block.ras_comm.block = AMDGPU_RAS_BLOCK__VCN; +		adev->vcn.ras->ras_block.ras_comm.type = AMDGPU_RAS_ERROR__POISON; +		adev->vcn.ras_if = &adev->vcn.ras->ras_block.ras_comm; + +		/* If don't define special ras_late_init function, use default ras_late_init */ +		if (!adev->vcn.ras->ras_block.ras_late_init) +			adev->vcn.ras->ras_block.ras_late_init = amdgpu_ras_block_late_init; +	} +} | 
