drm/amd/pm: add aca smu backend support for smu v13.0.6
authorYang Wang <kevinyang.wang@amd.com>
Tue, 14 Nov 2023 11:43:34 +0000 (19:43 +0800)
committerAlex Deucher <alexander.deucher@amd.com>
Mon, 15 Jan 2024 23:35:36 +0000 (18:35 -0500)
add aca smu backend support for smu v13.0.6.

Signed-off-by: Yang Wang <kevinyang.wang@amd.com>
Reviewed-by: Hawking Zhang <Hawking.Zhang@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c

index a28649f210933c03721c71e4e1fedb6935d00130..c813b3c7940af494e473b81d68788a5345cf4a17 100644 (file)
@@ -45,6 +45,7 @@
 #include <linux/pci.h>
 #include "amdgpu_ras.h"
 #include "amdgpu_mca.h"
+#include "amdgpu_aca.h"
 #include "smu_cmn.h"
 #include "mp/mp_13_0_6_offset.h"
 #include "mp/mp_13_0_6_sh_mask.h"
@@ -2858,6 +2859,143 @@ static const struct amdgpu_mca_smu_funcs smu_v13_0_6_mca_smu_funcs = {
        .mca_get_valid_mca_count = mca_smu_get_valid_mca_count,
 };
 
+static int aca_smu_set_debug_mode(struct amdgpu_device *adev, bool enable)
+{
+       struct smu_context *smu = adev->powerplay.pp_handle;
+
+       return smu_v13_0_6_mca_set_debug_mode(smu, enable);
+}
+
+static int smu_v13_0_6_get_valid_aca_count(struct smu_context *smu, enum aca_error_type type, u32 *count)
+{
+       uint32_t msg;
+       int ret;
+
+       if (!count)
+               return -EINVAL;
+
+       switch (type) {
+       case ACA_ERROR_TYPE_UE:
+               msg = SMU_MSG_QueryValidMcaCount;
+               break;
+       case ACA_ERROR_TYPE_CE:
+               msg = SMU_MSG_QueryValidMcaCeCount;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       ret = smu_cmn_send_smc_msg(smu, msg, count);
+       if (ret) {
+               *count = 0;
+               return ret;
+       }
+
+       return 0;
+}
+
+static int aca_smu_get_valid_aca_count(struct amdgpu_device *adev,
+                                      enum aca_error_type type, u32 *count)
+{
+       struct smu_context *smu = adev->powerplay.pp_handle;
+       int ret;
+
+       switch (type) {
+       case ACA_ERROR_TYPE_UE:
+       case ACA_ERROR_TYPE_CE:
+               ret = smu_v13_0_6_get_valid_aca_count(smu, type, count);
+               break;
+       default:
+               ret = -EINVAL;
+               break;
+       }
+
+       return ret;
+}
+
+static int __smu_v13_0_6_aca_bank_dump(struct smu_context *smu, enum aca_error_type type,
+                                      int idx, int offset, u32 *val)
+{
+       uint32_t msg, param;
+
+       switch (type) {
+       case ACA_ERROR_TYPE_UE:
+               msg = SMU_MSG_McaBankDumpDW;
+               break;
+       case ACA_ERROR_TYPE_CE:
+               msg = SMU_MSG_McaBankCeDumpDW;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       param = ((idx & 0xffff) << 16) | (offset & 0xfffc);
+
+       return smu_cmn_send_smc_msg_with_param(smu, msg, param, (uint32_t *)val);
+}
+
+static int smu_v13_0_6_aca_bank_dump(struct smu_context *smu, enum aca_error_type type,
+                                    int idx, int offset, u32 *val, int count)
+{
+       int ret, i;
+
+       if (!val)
+               return -EINVAL;
+
+       for (i = 0; i < count; i++) {
+               ret = __smu_v13_0_6_aca_bank_dump(smu, type, idx, offset + (i << 2), &val[i]);
+               if (ret)
+                       return ret;
+       }
+
+       return 0;
+}
+
+static int aca_bank_read_reg(struct amdgpu_device *adev, enum aca_error_type type,
+                            int idx, int reg_idx, u64 *val)
+{
+       struct smu_context *smu = adev->powerplay.pp_handle;
+       u32 data[2] = {0, 0};
+       int ret;
+
+       if (!val || reg_idx >= ACA_REG_IDX_COUNT)
+               return -EINVAL;
+
+       ret = smu_v13_0_6_aca_bank_dump(smu, type, idx, reg_idx * 8, data, ARRAY_SIZE(data));
+       if (ret)
+               return ret;
+
+       *val = (u64)data[1] << 32 | data[0];
+
+       dev_dbg(adev->dev, "mca read bank reg: type:%s, index: %d, reg_idx: %d, val: 0x%016llx\n",
+               type == ACA_ERROR_TYPE_UE ? "UE" : "CE", idx, reg_idx, *val);
+
+       return 0;
+}
+
+static int aca_smu_get_valid_aca_bank(struct amdgpu_device *adev,
+                                     enum aca_error_type type, int idx, struct aca_bank *bank)
+{
+       int i, ret, count;
+
+       count = min_t(int, 16, ARRAY_SIZE(bank->regs));
+       for (i = 0; i < count; i++) {
+               ret = aca_bank_read_reg(adev, type, idx, i, &bank->regs[i]);
+               if (ret)
+                       return ret;
+       }
+
+       return 0;
+}
+
+static const struct aca_smu_funcs smu_v13_0_6_aca_smu_funcs = {
+       .max_ue_bank_count = 12,
+       .max_ce_bank_count = 12,
+       .set_debug_mode = aca_smu_set_debug_mode,
+       .get_valid_aca_count = aca_smu_get_valid_aca_count,
+       .get_valid_aca_bank = aca_smu_get_valid_aca_bank,
+};
+
 static int smu_v13_0_6_select_xgmi_plpd_policy(struct smu_context *smu,
                                               enum pp_xgmi_plpd_mode mode)
 {
@@ -2970,4 +3108,5 @@ void smu_v13_0_6_set_ppt_funcs(struct smu_context *smu)
        smu->smc_driver_if_version = SMU13_0_6_DRIVER_IF_VERSION;
        smu_v13_0_set_smu_mailbox_registers(smu);
        amdgpu_mca_smu_init_funcs(smu->adev, &smu_v13_0_6_mca_smu_funcs);
+       amdgpu_aca_set_smu_funcs(smu->adev, &smu_v13_0_6_aca_smu_funcs);
 }