[AMD Official Use Only - General]

The series is:

Reviewed-by: Tao Zhou <[email protected]>

> -----Original Message-----
> From: Chai, Thomas <[email protected]>
> Sent: Wednesday, July 13, 2022 11:25 AM
> To: [email protected]
> Cc: Chai, Thomas <[email protected]>; Zhang, Hawking
> <[email protected]>; Zhou1, Tao <[email protected]>;
> Clements, John <[email protected]>; Li, Candice
> <[email protected]>; Chai, Thomas <[email protected]>; Deucher,
> Alexander <[email protected]>; Zhou1, Tao
> <[email protected]>
> 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 <[email protected]>
> Reviewed-by: Alexander Deucher <[email protected]>
> Reviewed-by: Hawking Zhang <[email protected]>
> Reviewed-by: Tao Zhou <[email protected]>
> ---
>  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

Reply via email to