[PATCH 2/2] drm/amdgpu: add umc ras functions for umc v8_10_0

Zhou1, Tao Tao.Zhou1 at amd.com
Wed Jul 13 04:03:22 UTC 2022


[AMD Official Use Only - General]

The series is:

Reviewed-by: Tao Zhou <tao.zhou1 at amd.com>

> -----Original Message-----
> From: Chai, Thomas <YiPeng.Chai at amd.com>
> Sent: Wednesday, July 13, 2022 11:25 AM
> To: amd-gfx at lists.freedesktop.org
> Cc: Chai, Thomas <YiPeng.Chai at amd.com>; Zhang, Hawking
> <Hawking.Zhang at amd.com>; Zhou1, Tao <Tao.Zhou1 at amd.com>;
> Clements, John <John.Clements at amd.com>; Li, Candice
> <Candice.Li at amd.com>; Chai, Thomas <YiPeng.Chai at amd.com>; Deucher,
> Alexander <Alexander.Deucher at amd.com>; Zhou1, Tao
> <Tao.Zhou1 at amd.com>
> Subject: [PATCH 2/2] drm/amdgpu: add umc ras functions for umc v8_10_0
> 
> 1. Support query umc ras error counter.
> 2. Support ras umc ue error address remapping.
> 
> v2:
>   Use adev->gmc.num_umc to replace hardcoded definitions.
> 
> Signed-off-by: YiPeng Chai <YiPeng.Chai at amd.com>
> Reviewed-by: Alexander Deucher <Alexander.Deucher at amd.com>
> Reviewed-by: Hawking Zhang <Hawking.Zhang at amd.com>
> Reviewed-by: Tao Zhou <tao.zhou1 at amd.com>
> ---
>  drivers/gpu/drm/amd/amdgpu/Makefile     |   2 +-
>  drivers/gpu/drm/amd/amdgpu/amdgpu_umc.h |  10 +
> drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c  |  27 +-
> drivers/gpu/drm/amd/amdgpu/umc_v8_10.c  | 357
> ++++++++++++++++++++++++  drivers/gpu/drm/amd/amdgpu/umc_v8_10.h
> |  70 +++++
>  5 files changed, 464 insertions(+), 2 deletions(-)  create mode 100644
> drivers/gpu/drm/amd/amdgpu/umc_v8_10.c
>  create mode 100644 drivers/gpu/drm/amd/amdgpu/umc_v8_10.h
> 
> diff --git a/drivers/gpu/drm/amd/amdgpu/Makefile
> b/drivers/gpu/drm/amd/amdgpu/Makefile
> index a87e42c2c8dc..c7d0cd15b5ef 100644
> --- a/drivers/gpu/drm/amd/amdgpu/Makefile
> +++ b/drivers/gpu/drm/amd/amdgpu/Makefile
> @@ -93,7 +93,7 @@ amdgpu-y += \
> 
>  # add UMC block
>  amdgpu-y += \
> -	umc_v6_0.o umc_v6_1.o umc_v6_7.o umc_v8_7.o
> +	umc_v6_0.o umc_v6_1.o umc_v6_7.o umc_v8_7.o umc_v8_10.o
> 
>  # add IH block
>  amdgpu-y += \
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.h
> b/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.h
> index 2ec6698aa1fe..3629d8f292ef 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.h
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.h
> @@ -41,6 +41,12 @@
>  #define LOOP_UMC_CH_INST(ch_inst) for ((ch_inst) = 0; (ch_inst) < adev-
> >umc.channel_inst_num; (ch_inst)++)  #define
> LOOP_UMC_INST_AND_CH(umc_inst, ch_inst) LOOP_UMC_INST((umc_inst))
> LOOP_UMC_CH_INST((ch_inst))
> 
> +#define LOOP_UMC_NODE_INST(node_inst) \
> +		for ((node_inst) = 0; (node_inst) < adev-
> >umc.node_inst_num;
> +(node_inst)++)
> +
> +#define LOOP_UMC_EACH_NODE_INST_AND_CH(node_inst, umc_inst,
> ch_inst) \
> +		LOOP_UMC_NODE_INST((node_inst))
> LOOP_UMC_INST_AND_CH((umc_inst),
> +(ch_inst))
> +
>  struct amdgpu_umc_ras {
>  	struct amdgpu_ras_block_object ras_block;
>  	void (*err_cnt_init)(struct amdgpu_device *adev); @@ -62,6 +68,10
> @@ struct amdgpu_umc {
>  	uint32_t channel_inst_num;
>  	/* number of umc instance with memory map register access */
>  	uint32_t umc_inst_num;
> +
> +	/*number of umc node instance with memory map register access*/
> +	uint32_t node_inst_num;
> +
>  	/* UMC regiser per channel offset */
>  	uint32_t channel_offs;
>  	/* channel index table of interleaved memory */ diff --git
> a/drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c
> b/drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c
> index edbdc0b934ea..503e40a90319 100644
> --- a/drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c
> +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c
> @@ -25,7 +25,7 @@
>  #include "amdgpu.h"
>  #include "amdgpu_atomfirmware.h"
>  #include "gmc_v11_0.h"
> -#include "umc_v8_7.h"
> +#include "umc_v8_10.h"
>  #include "athub/athub_3_0_0_sh_mask.h"
>  #include "athub/athub_3_0_0_offset.h"
>  #include "oss/osssys_6_0_0_offset.h"
> @@ -537,11 +537,36 @@ static void gmc_v11_0_set_umc_funcs(struct
> amdgpu_device *adev)  {
>  	switch (adev->ip_versions[UMC_HWIP][0]) {
>  	case IP_VERSION(8, 10, 0):
> +		adev->umc.channel_inst_num =
> UMC_V8_10_CHANNEL_INSTANCE_NUM;
> +		adev->umc.umc_inst_num =
> UMC_V8_10_UMC_INSTANCE_NUM;
> +		adev->umc.node_inst_num = adev->gmc.num_umc;
> +		adev->umc.max_ras_err_cnt_per_query =
> UMC_V8_10_TOTAL_CHANNEL_NUM(adev);
> +		adev->umc.channel_offs =
> UMC_V8_10_PER_CHANNEL_OFFSET;
> +		adev->umc.channel_idx_tbl =
> &umc_v8_10_channel_idx_tbl[0][0][0];
> +		adev->umc.ras = &umc_v8_10_ras;
> +		break;
>  	case IP_VERSION(8, 11, 0):
>  		break;
>  	default:
>  		break;
>  	}
> +
> +	if (adev->umc.ras) {
> +		amdgpu_ras_register_ras_block(adev, &adev->umc.ras-
> >ras_block);
> +
> +		strcpy(adev->umc.ras->ras_block.ras_comm.name, "umc");
> +		adev->umc.ras->ras_block.ras_comm.block =
> AMDGPU_RAS_BLOCK__UMC;
> +		adev->umc.ras->ras_block.ras_comm.type =
> AMDGPU_RAS_ERROR__MULTI_UNCORRECTABLE;
> +		adev->umc.ras_if = &adev->umc.ras->ras_block.ras_comm;
> +
> +		/* If don't define special ras_late_init function, use default
> ras_late_init */
> +		if (!adev->umc.ras->ras_block.ras_late_init)
> +			adev->umc.ras->ras_block.ras_late_init =
> amdgpu_umc_ras_late_init;
> +
> +		/* If not define special ras_cb function, use default ras_cb
> */
> +		if (!adev->umc.ras->ras_block.ras_cb)
> +			adev->umc.ras->ras_block.ras_cb =
> amdgpu_umc_process_ras_data_cb;
> +	}
>  }
> 
> 
> diff --git a/drivers/gpu/drm/amd/amdgpu/umc_v8_10.c
> b/drivers/gpu/drm/amd/amdgpu/umc_v8_10.c
> new file mode 100644
> index 000000000000..36a2053f2e8b
> --- /dev/null
> +++ b/drivers/gpu/drm/amd/amdgpu/umc_v8_10.c
> @@ -0,0 +1,357 @@
> +/*
> + * Copyright 2022 Advanced Micro Devices, Inc.
> + *
> + * Permission is hereby granted, free of charge, to any person
> +obtaining a
> + * copy of this software and associated documentation files (the
> +"Software"),
> + * to deal in the Software without restriction, including without
> +limitation
> + * the rights to use, copy, modify, merge, publish, distribute,
> +sublicense,
> + * and/or sell copies of the Software, and to permit persons to whom
> +the
> + * Software is furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice shall be
> +included in
> + * all copies or substantial portions of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
> +EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
> +MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO
> EVENT
> +SHALL
> + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM,
> +DAMAGES OR
> + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
> +OTHERWISE,
> + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
> THE USE
> +OR
> + * OTHER DEALINGS IN THE SOFTWARE.
> + *
> + */
> +#include "umc_v8_10.h"
> +#include "amdgpu_ras.h"
> +#include "amdgpu_umc.h"
> +#include "amdgpu.h"
> +#include "umc/umc_8_10_0_offset.h"
> +#include "umc/umc_8_10_0_sh_mask.h"
> +
> +#define UMC_8_NODE_DIST   0x800000
> +#define UMC_8_INST_DIST   0x4000
> +
> +struct channelnum_map_colbit {
> +	uint32_t channel_num;
> +	uint32_t col_bit;
> +};
> +
> +const struct channelnum_map_colbit
> umc_v8_10_channelnum_map_colbit_table[] = {
> +	{24, 13},
> +	{20, 13},
> +	{16, 12},
> +	{14, 12},
> +	{12, 12},
> +	{10, 12},
> +	{6,  11},
> +};
> +
> +const uint32_t
> +	umc_v8_10_channel_idx_tbl[]
> +				[UMC_V8_10_UMC_INSTANCE_NUM]
> +				[UMC_V8_10_CHANNEL_INSTANCE_NUM] = {
> +	   {{16, 18}, {17, 19}},
> +	   {{15, 11}, {3,   7}},
> +	   {{1,   5}, {13,  9}},
> +	   {{23, 21}, {22, 20}},
> +	   {{0,   4}, {12,  8}},
> +	   {{14, 10}, {2,   6}}
> +	};
> +
> +static inline uint32_t get_umc_v8_10_reg_offset(struct amdgpu_device
> *adev,
> +					    uint32_t node_inst,
> +					    uint32_t umc_inst,
> +					    uint32_t ch_inst)
> +{
> +	return adev->umc.channel_offs * ch_inst + UMC_8_INST_DIST *
> umc_inst +
> +		UMC_8_NODE_DIST * node_inst;
> +}
> +
> +static void umc_v8_10_clear_error_count_per_channel(struct
> amdgpu_device *adev,
> +					uint32_t umc_reg_offset)
> +{
> +	uint32_t ecc_err_cnt_addr;
> +
> +	ecc_err_cnt_addr =
> +		SOC15_REG_OFFSET(UMC, 0, regUMCCH0_0_GeccErrCnt);
> +
> +	/* clear error count */
> +	WREG32_PCIE((ecc_err_cnt_addr + umc_reg_offset) * 4,
> +			UMC_V8_10_CE_CNT_INIT);
> +}
> +
> +static void umc_v8_10_clear_error_count(struct amdgpu_device *adev) {
> +	uint32_t node_inst       = 0;
> +	uint32_t umc_inst        = 0;
> +	uint32_t ch_inst         = 0;
> +	uint32_t umc_reg_offset  = 0;
> +
> +	LOOP_UMC_EACH_NODE_INST_AND_CH(node_inst, umc_inst,
> ch_inst) {
> +		umc_reg_offset = get_umc_v8_10_reg_offset(adev,
> +						node_inst,
> +						umc_inst,
> +						ch_inst);
> +
> +		umc_v8_10_clear_error_count_per_channel(adev,
> +						umc_reg_offset);
> +	}
> +}
> +
> +static void umc_v8_10_query_correctable_error_count(struct
> amdgpu_device *adev,
> +						   uint32_t umc_reg_offset,
> +						   unsigned long *error_count)
> +{
> +	uint32_t ecc_err_cnt, ecc_err_cnt_addr;
> +	uint64_t mc_umc_status;
> +	uint32_t mc_umc_status_addr;
> +
> +	/* UMC 8_10 registers */
> +	ecc_err_cnt_addr =
> +		SOC15_REG_OFFSET(UMC, 0, regUMCCH0_0_GeccErrCnt);
> +	mc_umc_status_addr =
> +		SOC15_REG_OFFSET(UMC, 0,
> regMCA_UMC_UMC0_MCUMC_STATUST0);
> +
> +	ecc_err_cnt = RREG32_PCIE((ecc_err_cnt_addr + umc_reg_offset) *
> 4);
> +	*error_count +=
> +		(REG_GET_FIELD(ecc_err_cnt, UMCCH0_0_GeccErrCnt,
> GeccErrCnt) -
> +		 UMC_V8_10_CE_CNT_INIT);
> +
> +	/* Check for SRAM correctable error, MCUMC_STATUS is a 64 bit
> register */
> +	mc_umc_status = RREG64_PCIE((mc_umc_status_addr +
> umc_reg_offset) * 4);
> +	if (REG_GET_FIELD(mc_umc_status,
> MCA_UMC_UMC0_MCUMC_STATUST0, Val) == 1 &&
> +	    REG_GET_FIELD(mc_umc_status,
> MCA_UMC_UMC0_MCUMC_STATUST0, CECC) == 1)
> +		*error_count += 1;
> +}
> +
> +static void umc_v8_10_query_uncorrectable_error_count(struct
> amdgpu_device *adev,
> +						      uint32_t umc_reg_offset,
> +						      unsigned long
> *error_count) {
> +	uint64_t mc_umc_status;
> +	uint32_t mc_umc_status_addr;
> +
> +	mc_umc_status_addr = SOC15_REG_OFFSET(UMC, 0,
> +regMCA_UMC_UMC0_MCUMC_STATUST0);
> +
> +	/* Check the MCUMC_STATUS. */
> +	mc_umc_status = RREG64_PCIE((mc_umc_status_addr +
> umc_reg_offset) * 4);
> +	if ((REG_GET_FIELD(mc_umc_status,
> MCA_UMC_UMC0_MCUMC_STATUST0, Val) == 1) &&
> +	    (REG_GET_FIELD(mc_umc_status,
> MCA_UMC_UMC0_MCUMC_STATUST0, Deferred) == 1 ||
> +	    REG_GET_FIELD(mc_umc_status,
> MCA_UMC_UMC0_MCUMC_STATUST0, UECC) == 1 ||
> +	    REG_GET_FIELD(mc_umc_status,
> MCA_UMC_UMC0_MCUMC_STATUST0, PCC) == 1 ||
> +	    REG_GET_FIELD(mc_umc_status,
> MCA_UMC_UMC0_MCUMC_STATUST0, UC) == 1 ||
> +	    REG_GET_FIELD(mc_umc_status,
> MCA_UMC_UMC0_MCUMC_STATUST0, TCC) == 1))
> +		*error_count += 1;
> +}
> +
> +static void umc_v8_10_query_ras_error_count(struct amdgpu_device
> *adev,
> +					   void *ras_error_status)
> +{
> +	struct ras_err_data *err_data = (struct ras_err_data
> +*)ras_error_status;
> +
> +	uint32_t node_inst       = 0;
> +	uint32_t umc_inst        = 0;
> +	uint32_t ch_inst         = 0;
> +	uint32_t umc_reg_offset  = 0;
> +
> +	LOOP_UMC_EACH_NODE_INST_AND_CH(node_inst, umc_inst,
> ch_inst) {
> +		umc_reg_offset = get_umc_v8_10_reg_offset(adev,
> +						node_inst,
> +						umc_inst,
> +						ch_inst);
> +
> +		umc_v8_10_query_correctable_error_count(adev,
> +						umc_reg_offset,
> +						&(err_data->ce_count));
> +		umc_v8_10_query_uncorrectable_error_count(adev,
> +						umc_reg_offset,
> +						&(err_data->ue_count));
> +	}
> +
> +	umc_v8_10_clear_error_count(adev);
> +}
> +
> +static uint32_t umc_v8_10_get_col_bit(uint32_t channel_num) {
> +	uint32_t t = 0;
> +
> +	for (t = 0; t <
> ARRAY_SIZE(umc_v8_10_channelnum_map_colbit_table); t++)
> +		if (channel_num ==
> umc_v8_10_channelnum_map_colbit_table[t].channel_num)
> +			return
> umc_v8_10_channelnum_map_colbit_table[t].col_bit;
> +
> +	/* Failed to get col_bit. */
> +	return U32_MAX;
> +}
> +
> +/*
> + * Mapping normal address to soc physical address in swizzle mode.
> + */
> +static int umc_v8_10_swizzle_mode_na_to_pa(struct amdgpu_device
> *adev,
> +					uint32_t channel_idx,
> +					uint64_t na, uint64_t *soc_pa)
> +{
> +	uint32_t channel_num = UMC_V8_10_TOTAL_CHANNEL_NUM(adev);
> +	uint32_t col_bit = umc_v8_10_get_col_bit(channel_num);
> +	uint64_t tmp_addr;
> +
> +	if (col_bit == U32_MAX)
> +		return -1;
> +
> +	tmp_addr = SWIZZLE_MODE_TMP_ADDR(na, channel_num,
> channel_idx);
> +	*soc_pa = SWIZZLE_MODE_ADDR_HI(tmp_addr, col_bit) |
> +		SWIZZLE_MODE_ADDR_MID(na, col_bit) |
> +		SWIZZLE_MODE_ADDR_LOW(tmp_addr, col_bit) |
> +		SWIZZLE_MODE_ADDR_LSB(na);
> +
> +	return 0;
> +}
> +
> +static void umc_v8_10_query_error_address(struct amdgpu_device *adev,
> +					 struct ras_err_data *err_data,
> +					 uint32_t umc_reg_offset,
> +					 uint32_t node_inst,
> +					 uint32_t ch_inst,
> +					 uint32_t umc_inst)
> +{
> +	uint64_t mc_umc_status_addr;
> +	uint64_t mc_umc_status, err_addr;
> +	uint32_t channel_index;
> +
> +	mc_umc_status_addr =
> +		SOC15_REG_OFFSET(UMC, 0,
> regMCA_UMC_UMC0_MCUMC_STATUST0);
> +	mc_umc_status = RREG64_PCIE((mc_umc_status_addr +
> umc_reg_offset) *
> +4);
> +
> +	if (mc_umc_status == 0)
> +		return;
> +
> +	if (!err_data->err_addr) {
> +		/* clear umc status */
> +		WREG64_PCIE((mc_umc_status_addr + umc_reg_offset) * 4,
> 0x0ULL);
> +		return;
> +	}
> +
> +	channel_index =
> +		adev->umc.channel_idx_tbl[node_inst * adev-
> >umc.umc_inst_num *
> +					adev->umc.channel_inst_num +
> +					umc_inst * adev-
> >umc.channel_inst_num +
> +					ch_inst];
> +
> +	/* calculate error address if ue/ce error is detected */
> +	if (REG_GET_FIELD(mc_umc_status,
> MCA_UMC_UMC0_MCUMC_STATUST0, Val) == 1 &&
> +	    REG_GET_FIELD(mc_umc_status,
> MCA_UMC_UMC0_MCUMC_STATUST0, AddrV) == 1 &&
> +	    (REG_GET_FIELD(mc_umc_status,
> MCA_UMC_UMC0_MCUMC_STATUST0, UECC) == 1 ||
> +	     REG_GET_FIELD(mc_umc_status,
> MCA_UMC_UMC0_MCUMC_STATUST0, CECC) == 1)) {
> +		uint32_t addr_lsb;
> +		uint64_t mc_umc_addrt0;
> +
> +		mc_umc_addrt0 = SOC15_REG_OFFSET(UMC, 0,
> regMCA_UMC_UMC0_MCUMC_ADDRT0);
> +		err_addr = RREG64_PCIE((mc_umc_addrt0 + umc_reg_offset)
> * 4);
> +		err_addr = REG_GET_FIELD(err_addr,
> MCA_UMC_UMC0_MCUMC_ADDRT0,
> +ErrorAddr);
> +
> +		/* the lowest lsb bits should be ignored */
> +		addr_lsb = REG_GET_FIELD(mc_umc_status,
> MCA_UMC_UMC0_MCUMC_STATUST0,
> +AddrLsb);
> +
> +		err_addr &= ~((0x1ULL << addr_lsb) - 1);
> +
> +		/* we only save ue error information currently, ce is skipped
> */
> +		if (REG_GET_FIELD(mc_umc_status,
> MCA_UMC_UMC0_MCUMC_STATUST0, UECC) == 1) {
> +			uint64_t na_err_addr_base = err_addr & ~(0x3ULL
> << UMC_V8_10_NA_C5_BIT);
> +			uint64_t na_err_addr, retired_page_addr;
> +			uint32_t col = 0;
> +			int ret = 0;
> +
> +			/* loop for all possibilities of [C6 C5] in normal
> address. */
> +			for (col = 0; col <
> UMC_V8_10_NA_COL_2BITS_POWER_OF_2_NUM; col++) {
> +				na_err_addr = na_err_addr_base | (col <<
> UMC_V8_10_NA_C5_BIT);
> +
> +				/* Mapping normal error address to retired
> soc physical address. */
> +				ret =
> umc_v8_10_swizzle_mode_na_to_pa(adev, channel_index,
> +								na_err_addr,
> &retired_page_addr);
> +				if (ret) {
> +					dev_err(adev->dev, "Failed to map
> pa from umc na.\n");
> +					break;
> +				}
> +				dev_info(adev->dev, "Error Address(PA):
> 0x%llx\n",
> +					retired_page_addr);
> +				amdgpu_umc_fill_error_record(err_data,
> na_err_addr,
> +						retired_page_addr,
> channel_index, umc_inst);
> +			}
> +		}
> +	}
> +
> +	/* clear umc status */
> +	WREG64_PCIE((mc_umc_status_addr + umc_reg_offset) * 4,
> 0x0ULL); }
> +
> +static void umc_v8_10_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 node_inst       = 0;
> +	uint32_t umc_inst        = 0;
> +	uint32_t ch_inst         = 0;
> +	uint32_t umc_reg_offset  = 0;
> +
> +	LOOP_UMC_EACH_NODE_INST_AND_CH(node_inst, umc_inst,
> ch_inst) {
> +		umc_reg_offset = get_umc_v8_10_reg_offset(adev,
> +						node_inst,
> +						umc_inst,
> +						ch_inst);
> +
> +		umc_v8_10_query_error_address(adev,
> +					err_data,
> +					umc_reg_offset,
> +					node_inst,
> +					ch_inst,
> +					umc_inst);
> +	}
> +}
> +
> +static void umc_v8_10_err_cnt_init_per_channel(struct amdgpu_device
> *adev,
> +					      uint32_t umc_reg_offset)
> +{
> +	uint32_t ecc_err_cnt_sel, ecc_err_cnt_sel_addr;
> +	uint32_t ecc_err_cnt_addr;
> +
> +	ecc_err_cnt_sel_addr =
> +		SOC15_REG_OFFSET(UMC, 0, regUMCCH0_0_GeccErrCntSel);
> +	ecc_err_cnt_addr =
> +		SOC15_REG_OFFSET(UMC, 0, regUMCCH0_0_GeccErrCnt);
> +
> +	ecc_err_cnt_sel = RREG32_PCIE((ecc_err_cnt_sel_addr +
> umc_reg_offset)
> +* 4);
> +
> +	/* set ce error interrupt type to APIC based interrupt */
> +	ecc_err_cnt_sel = REG_SET_FIELD(ecc_err_cnt_sel,
> UMCCH0_0_GeccErrCntSel,
> +					GeccErrInt, 0x1);
> +	WREG32_PCIE((ecc_err_cnt_sel_addr + umc_reg_offset) * 4,
> ecc_err_cnt_sel);
> +	/* set error count to initial value */
> +	WREG32_PCIE((ecc_err_cnt_addr + umc_reg_offset) * 4,
> +UMC_V8_10_CE_CNT_INIT); }
> +
> +static void umc_v8_10_err_cnt_init(struct amdgpu_device *adev) {
> +	uint32_t node_inst       = 0;
> +	uint32_t umc_inst        = 0;
> +	uint32_t ch_inst         = 0;
> +	uint32_t umc_reg_offset  = 0;
> +
> +	LOOP_UMC_EACH_NODE_INST_AND_CH(node_inst, umc_inst,
> ch_inst) {
> +		umc_reg_offset = get_umc_v8_10_reg_offset(adev,
> +						node_inst,
> +						umc_inst,
> +						ch_inst);
> +
> +		umc_v8_10_err_cnt_init_per_channel(adev, umc_reg_offset);
> +	}
> +}
> +
> +const struct amdgpu_ras_block_hw_ops umc_v8_10_ras_hw_ops = {
> +	.query_ras_error_count = umc_v8_10_query_ras_error_count,
> +	.query_ras_error_address = umc_v8_10_query_ras_error_address,
> +};
> +
> +struct amdgpu_umc_ras umc_v8_10_ras = {
> +	.ras_block = {
> +		.hw_ops = &umc_v8_10_ras_hw_ops,
> +	},
> +	.err_cnt_init = umc_v8_10_err_cnt_init, };
> diff --git a/drivers/gpu/drm/amd/amdgpu/umc_v8_10.h
> b/drivers/gpu/drm/amd/amdgpu/umc_v8_10.h
> new file mode 100644
> index 000000000000..849ede88e111
> --- /dev/null
> +++ b/drivers/gpu/drm/amd/amdgpu/umc_v8_10.h
> @@ -0,0 +1,70 @@
> +/*
> + * Copyright 2022 Advanced Micro Devices, Inc.
> + *
> + * Permission is hereby granted, free of charge, to any person
> +obtaining a
> + * copy of this software and associated documentation files (the
> +"Software"),
> + * to deal in the Software without restriction, including without
> +limitation
> + * the rights to use, copy, modify, merge, publish, distribute,
> +sublicense,
> + * and/or sell copies of the Software, and to permit persons to whom
> +the
> + * Software is furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice shall be
> +included in
> + * all copies or substantial portions of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
> +EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
> +MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO
> EVENT
> +SHALL
> + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM,
> +DAMAGES OR
> + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
> +OTHERWISE,
> + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
> THE USE
> +OR
> + * OTHER DEALINGS IN THE SOFTWARE.
> + *
> + */
> +#ifndef __UMC_V8_10_H__
> +#define __UMC_V8_10_H__
> +
> +#include "soc15_common.h"
> +#include "amdgpu.h"
> +
> +/* number of umc channel instance with memory map register access */
> +#define UMC_V8_10_CHANNEL_INSTANCE_NUM		2
> +/* number of umc instance with memory map register access */
> +#define UMC_V8_10_UMC_INSTANCE_NUM		2
> +
> +/* Total channel instances for all umc nodes */ #define
> +UMC_V8_10_TOTAL_CHANNEL_NUM(adev) \
> +	(UMC_V8_10_CHANNEL_INSTANCE_NUM *
> UMC_V8_10_UMC_INSTANCE_NUM *
> +(adev)->umc.node_inst_num)
> +
> +/* UMC regiser per channel offset */
> +#define UMC_V8_10_PER_CHANNEL_OFFSET	0x400
> +
> +/* EccErrCnt max value */
> +#define UMC_V8_10_CE_CNT_MAX		0xffff
> +/* umc ce interrupt threshold */
> +#define UUMC_V8_10_CE_INT_THRESHOLD	0xffff
> +/* umc ce count initial value */
> +#define UMC_V8_10_CE_CNT_INIT	(UMC_V8_10_CE_CNT_MAX -
> UUMC_V8_10_CE_INT_THRESHOLD)
> +
> +#define UMC_V8_10_NA_COL_2BITS_POWER_OF_2_NUM	 4
> +
> +/* The C5 bit in NA  address */
> +#define UMC_V8_10_NA_C5_BIT	14
> +
> +/* Map to swizzle mode address */
> +#define SWIZZLE_MODE_TMP_ADDR(na, ch_num, ch_idx) \
> +		((((na) >> 10) * (ch_num) + (ch_idx)) << 10) #define
> +SWIZZLE_MODE_ADDR_HI(addr, col_bit)  \
> +		(((addr) >> ((col_bit) + 2)) << ((col_bit) + 2)) #define
> +SWIZZLE_MODE_ADDR_MID(na, col_bit) ((((na) >> 8) & 0x3) << (col_bit))
> +#define SWIZZLE_MODE_ADDR_LOW(addr, col_bit) \
> +		((((addr) >> 10) & ((0x1ULL << (col_bit - 8)) - 1)) << 8) #define
> +SWIZZLE_MODE_ADDR_LSB(na) ((na) & 0xFF)
> +
> +extern struct amdgpu_umc_ras umc_v8_10_ras; extern const uint32_t
> +	umc_v8_10_channel_idx_tbl[]
> +				[UMC_V8_10_UMC_INSTANCE_NUM]
> +				[UMC_V8_10_CHANNEL_INSTANCE_NUM];
> +
> +#endif
> +
> --
> 2.25.1


More information about the amd-gfx mailing list