[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