Merge tag 'amd-drm-next-6.9-2024-02-19' of https://gitlab.freedesktop.org/agd5f/linux...
[sfrench/cifs-2.6.git] / drivers / gpu / drm / amd / pm / swsmu / smu13 / smu_v13_0_6_ppt.c
index 1b96158b63bf468e0394cf364650f549598c3725..45a84fd5dc0448cae08a9dc4a78548d73be7322f 100644 (file)
@@ -172,6 +172,7 @@ static const struct cmn2asic_msg_mapping smu_v13_0_6_message_map[SMU_MSG_MAX_COU
        MSG_MAP(McaBankDumpDW,                       PPSMC_MSG_McaBankDumpDW,                   0),
        MSG_MAP(McaBankCeDumpDW,                     PPSMC_MSG_McaBankCeDumpDW,                 0),
        MSG_MAP(SelectPLPDMode,                      PPSMC_MSG_SelectPLPDMode,                  0),
+       MSG_MAP(RmaDueToBadPageThreshold,            PPSMC_MSG_RmaDueToBadPageThreshold,        0),
 };
 
 // clang-format on
@@ -1578,6 +1579,8 @@ static int smu_v13_0_6_set_performance_level(struct smu_context *smu,
        struct smu_13_0_dpm_context *dpm_context = smu_dpm->dpm_context;
        struct smu_13_0_dpm_table *gfx_table =
                &dpm_context->dpm_tables.gfx_table;
+       struct smu_13_0_dpm_table *uclk_table =
+               &dpm_context->dpm_tables.uclk_table;
        struct smu_umd_pstate_table *pstate_table = &smu->pstate_table;
        int ret;
 
@@ -1593,17 +1596,27 @@ static int smu_v13_0_6_set_performance_level(struct smu_context *smu,
                return 0;
 
        case AMD_DPM_FORCED_LEVEL_AUTO:
-               if ((gfx_table->min == pstate_table->gfxclk_pstate.curr.min) &&
-                   (gfx_table->max == pstate_table->gfxclk_pstate.curr.max))
-                       return 0;
+               if ((gfx_table->min != pstate_table->gfxclk_pstate.curr.min) ||
+                   (gfx_table->max != pstate_table->gfxclk_pstate.curr.max)) {
+                       ret = smu_v13_0_6_set_gfx_soft_freq_limited_range(
+                               smu, gfx_table->min, gfx_table->max);
+                       if (ret)
+                               return ret;
 
-               ret = smu_v13_0_6_set_gfx_soft_freq_limited_range(
-                       smu, gfx_table->min, gfx_table->max);
-               if (ret)
-                       return ret;
+                       pstate_table->gfxclk_pstate.curr.min = gfx_table->min;
+                       pstate_table->gfxclk_pstate.curr.max = gfx_table->max;
+               }
+
+               if (uclk_table->max != pstate_table->uclk_pstate.curr.max) {
+                       /* Min UCLK is not expected to be changed */
+                       ret = smu_v13_0_set_soft_freq_limited_range(
+                               smu, SMU_UCLK, 0, uclk_table->max);
+                       if (ret)
+                               return ret;
+                       pstate_table->uclk_pstate.curr.max = uclk_table->max;
+               }
+               pstate_table->uclk_pstate.custom.max = 0;
 
-               pstate_table->gfxclk_pstate.curr.min = gfx_table->min;
-               pstate_table->gfxclk_pstate.curr.max = gfx_table->max;
                return 0;
        case AMD_DPM_FORCED_LEVEL_MANUAL:
                return 0;
@@ -1626,7 +1639,8 @@ static int smu_v13_0_6_set_soft_freq_limited_range(struct smu_context *smu,
        uint32_t max_clk;
        int ret = 0;
 
-       if (clk_type != SMU_GFXCLK && clk_type != SMU_SCLK)
+       if (clk_type != SMU_GFXCLK && clk_type != SMU_SCLK &&
+           clk_type != SMU_UCLK)
                return -EINVAL;
 
        if ((smu_dpm->dpm_level != AMD_DPM_FORCED_LEVEL_MANUAL) &&
@@ -1636,18 +1650,31 @@ static int smu_v13_0_6_set_soft_freq_limited_range(struct smu_context *smu,
        if (smu_dpm->dpm_level == AMD_DPM_FORCED_LEVEL_MANUAL) {
                if (min >= max) {
                        dev_err(smu->adev->dev,
-                               "Minimum GFX clk should be less than the maximum allowed clock\n");
+                               "Minimum clk should be less than the maximum allowed clock\n");
                        return -EINVAL;
                }
 
-               if ((min == pstate_table->gfxclk_pstate.curr.min) &&
-                   (max == pstate_table->gfxclk_pstate.curr.max))
-                       return 0;
+               if (clk_type == SMU_GFXCLK) {
+                       if ((min == pstate_table->gfxclk_pstate.curr.min) &&
+                           (max == pstate_table->gfxclk_pstate.curr.max))
+                               return 0;
 
-               ret = smu_v13_0_6_set_gfx_soft_freq_limited_range(smu, min, max);
-               if (!ret) {
-                       pstate_table->gfxclk_pstate.curr.min = min;
-                       pstate_table->gfxclk_pstate.curr.max = max;
+                       ret = smu_v13_0_6_set_gfx_soft_freq_limited_range(
+                               smu, min, max);
+                       if (!ret) {
+                               pstate_table->gfxclk_pstate.curr.min = min;
+                               pstate_table->gfxclk_pstate.curr.max = max;
+                       }
+               }
+
+               if (clk_type == SMU_UCLK) {
+                       if (max == pstate_table->uclk_pstate.curr.max)
+                               return 0;
+                       /* Only max clock limiting is allowed for UCLK */
+                       ret = smu_v13_0_set_soft_freq_limited_range(
+                               smu, SMU_UCLK, 0, max);
+                       if (!ret)
+                               pstate_table->uclk_pstate.curr.max = max;
                }
 
                return ret;
@@ -1740,6 +1767,40 @@ static int smu_v13_0_6_usr_edit_dpm_table(struct smu_context *smu,
                        return -EINVAL;
                }
                break;
+       case PP_OD_EDIT_MCLK_VDDC_TABLE:
+               if (size != 2) {
+                       dev_err(smu->adev->dev,
+                               "Input parameter number not correct\n");
+                       return -EINVAL;
+               }
+
+               if (!smu_cmn_feature_is_enabled(smu,
+                                               SMU_FEATURE_DPM_UCLK_BIT)) {
+                       dev_warn(smu->adev->dev,
+                                "UCLK_LIMITS setting not supported!\n");
+                       return -EOPNOTSUPP;
+               }
+
+               if (input[0] == 0) {
+                       dev_info(smu->adev->dev,
+                                "Setting min UCLK level is not supported");
+                       return -EINVAL;
+               } else if (input[0] == 1) {
+                       if (input[1] > dpm_context->dpm_tables.uclk_table.max) {
+                               dev_warn(
+                                       smu->adev->dev,
+                                       "Maximum UCLK (%ld) MHz specified is greater than the maximum allowed (%d) MHz\n",
+                                       input[1],
+                                       dpm_context->dpm_tables.uclk_table.max);
+                               pstate_table->uclk_pstate.custom.max =
+                                       pstate_table->uclk_pstate.curr.max;
+                               return -EINVAL;
+                       }
+
+                       pstate_table->uclk_pstate.custom.max = input[1];
+               }
+               break;
+
        case PP_OD_RESTORE_DEFAULT_TABLE:
                if (size != 0) {
                        dev_err(smu->adev->dev,
@@ -1750,8 +1811,19 @@ static int smu_v13_0_6_usr_edit_dpm_table(struct smu_context *smu,
                        min_clk = dpm_context->dpm_tables.gfx_table.min;
                        max_clk = dpm_context->dpm_tables.gfx_table.max;
 
-                       return smu_v13_0_6_set_soft_freq_limited_range(
+                       ret = smu_v13_0_6_set_soft_freq_limited_range(
                                smu, SMU_GFXCLK, min_clk, max_clk);
+
+                       if (ret)
+                               return ret;
+
+                       min_clk = dpm_context->dpm_tables.uclk_table.min;
+                       max_clk = dpm_context->dpm_tables.uclk_table.max;
+                       ret = smu_v13_0_6_set_soft_freq_limited_range(
+                               smu, SMU_UCLK, min_clk, max_clk);
+                       if (ret)
+                               return ret;
+                       pstate_table->uclk_pstate.custom.max = 0;
                }
                break;
        case PP_OD_COMMIT_DPM_TABLE:
@@ -1771,8 +1843,19 @@ static int smu_v13_0_6_usr_edit_dpm_table(struct smu_context *smu,
                        min_clk = pstate_table->gfxclk_pstate.custom.min;
                        max_clk = pstate_table->gfxclk_pstate.custom.max;
 
-                       return smu_v13_0_6_set_soft_freq_limited_range(
+                       ret = smu_v13_0_6_set_soft_freq_limited_range(
                                smu, SMU_GFXCLK, min_clk, max_clk);
+
+                       if (ret)
+                               return ret;
+
+                       if (!pstate_table->uclk_pstate.custom.max)
+                               return 0;
+
+                       min_clk = pstate_table->uclk_pstate.curr.min;
+                       max_clk = pstate_table->uclk_pstate.custom.max;
+                       return smu_v13_0_6_set_soft_freq_limited_range(
+                               smu, SMU_UCLK, min_clk, max_clk);
                }
                break;
        default:
@@ -2380,6 +2463,24 @@ static int smu_v13_0_6_smu_send_hbm_bad_page_num(struct smu_context *smu,
        return ret;
 }
 
+static int smu_v13_0_6_send_rma_reason(struct smu_context *smu)
+{
+       struct amdgpu_device *adev = smu->adev;
+       int ret;
+
+       /* NOTE: the message is only valid on dGPU with pmfw 85.90.0 and above */
+       if ((adev->flags & AMD_IS_APU) || smu->smc_fw_version < 0x00555a00)
+               return 0;
+
+       ret = smu_cmn_send_smc_msg(smu, SMU_MSG_RmaDueToBadPageThreshold, NULL);
+       if (ret)
+               dev_err(smu->adev->dev,
+                       "[%s] failed to send BadPageThreshold event to SMU\n",
+                       __func__);
+
+       return ret;
+}
+
 static int mca_smu_set_debug_mode(struct amdgpu_device *adev, bool enable)
 {
        struct smu_context *smu = adev->powerplay.pp_handle;
@@ -3094,6 +3195,7 @@ static const struct pptable_funcs smu_v13_0_6_ppt_funcs = {
        .i2c_init = smu_v13_0_6_i2c_control_init,
        .i2c_fini = smu_v13_0_6_i2c_control_fini,
        .send_hbm_bad_pages_num = smu_v13_0_6_smu_send_hbm_bad_page_num,
+       .send_rma_reason = smu_v13_0_6_send_rma_reason,
 };
 
 void smu_v13_0_6_set_ppt_funcs(struct smu_context *smu)