]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
drm/amd/powerplay: fix navi10 system intermittent reboot issue V2
authorEvan Quan <evan.quan@amd.com>
Thu, 30 Jan 2020 08:46:38 +0000 (16:46 +0800)
committerAlex Deucher <alexander.deucher@amd.com>
Tue, 4 Feb 2020 15:37:08 +0000 (10:37 -0500)
This workaround is needed only for Navi10 12 Gbps SKUs.

V2: added SMU firmware version guard

Signed-off-by: Evan Quan <evan.quan@amd.com>
Reviewed-by: Feifei Xu <Feifei.Xu@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Cc: stable@vger.kernel.org
drivers/gpu/drm/amd/powerplay/amdgpu_smu.c
drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h
drivers/gpu/drm/amd/powerplay/inc/smu_types.h
drivers/gpu/drm/amd/powerplay/inc/smu_v11_0_ppsmc.h
drivers/gpu/drm/amd/powerplay/navi10_ppt.c
drivers/gpu/drm/amd/powerplay/smu_internal.h

index 99469479e2770b1660ba720f94db4e40a4a41146..99ad4ddbe12f01c89e36460eac27cc194f66bd72 100644 (file)
@@ -21,6 +21,7 @@
  */
 
 #include <linux/firmware.h>
+#include <linux/pci.h>
 
 #include "pp_debug.h"
 #include "amdgpu.h"
@@ -1137,6 +1138,23 @@ static int smu_smc_table_hw_init(struct smu_context *smu,
                ret = smu_system_features_control(smu, true);
                if (ret)
                        return ret;
+
+               if (adev->asic_type == CHIP_NAVI10) {
+                       if ((adev->pdev->device == 0x731f && (adev->pdev->revision == 0xc2 ||
+                                                             adev->pdev->revision == 0xc3 ||
+                                                             adev->pdev->revision == 0xca ||
+                                                             adev->pdev->revision == 0xcb)) ||
+                           (adev->pdev->device == 0x66af && (adev->pdev->revision == 0xf3 ||
+                                                             adev->pdev->revision == 0xf4 ||
+                                                             adev->pdev->revision == 0xf5 ||
+                                                             adev->pdev->revision == 0xf6))) {
+                               ret = smu_disable_umc_cdr_12gbps_workaround(smu);
+                               if (ret) {
+                                       pr_err("Workaround failed to disable UMC CDR feature on 12Gbps SKU!\n");
+                                       return ret;
+                               }
+                       }
+               }
        }
        if (adev->asic_type != CHIP_ARCTURUS) {
                ret = smu_notify_display_change(smu);
index b0591a8dda411507f041c2cc02e3040565040eb9..3237eb1ff7082148508139d057fcb41a08333dfb 100644 (file)
@@ -565,6 +565,7 @@ struct pptable_funcs {
        int (*set_soft_freq_limited_range)(struct smu_context *smu, enum smu_clk_type clk_type, uint32_t min, uint32_t max);
        int (*override_pcie_parameters)(struct smu_context *smu);
        uint32_t (*get_pptable_power_limit)(struct smu_context *smu);
+       int (*disable_umc_cdr_12gbps_workaround)(struct smu_context *smu);
 };
 
 int smu_load_microcode(struct smu_context *smu);
index d8c9b7f91fcc2825459eabc99ed7388ee9fa00b1..a5b4df1467130f47432ee6e3a15f503b3f9d2fc7 100644 (file)
        __SMU_DUMMY_MAP(SetSoftMinJpeg),              \
        __SMU_DUMMY_MAP(SetHardMinFclkByFreq),        \
        __SMU_DUMMY_MAP(DFCstateControl), \
+       __SMU_DUMMY_MAP(DAL_DISABLE_DUMMY_PSTATE_CHANGE), \
+       __SMU_DUMMY_MAP(DAL_ENABLE_DUMMY_PSTATE_CHANGE), \
 
 #undef __SMU_DUMMY_MAP
 #define __SMU_DUMMY_MAP(type)  SMU_MSG_##type
index 373861ddccd0eaa3d74667c78030242b8eaa5c2f..406bfd187ce864f08de97c1ddb34fab2e0852f2d 100644 (file)
 #define PPSMC_MSG_GetVoltageByDpmOverdrive       0x45
 #define PPSMC_MSG_BacoAudioD3PME                 0x48
 
-#define PPSMC_Message_Count                      0x49
+#define PPSMC_MSG_DALDisableDummyPstateChange    0x49
+#define PPSMC_MSG_DALEnableDummyPstateChange     0x4A
+
+#define PPSMC_Message_Count                      0x4B
 
 typedef uint32_t PPSMC_Result;
 typedef uint32_t PPSMC_Msg;
index f1b27fc20c19f0824950225c70b32721fb66859b..e59cd2c74dc9a1873f81723270e188cd90107fe5 100644 (file)
@@ -119,6 +119,8 @@ static struct smu_11_0_cmn2aisc_mapping navi10_message_map[SMU_MSG_MAX_COUNT] =
        MSG_MAP(PowerDownJpeg,          PPSMC_MSG_PowerDownJpeg),
        MSG_MAP(BacoAudioD3PME,         PPSMC_MSG_BacoAudioD3PME),
        MSG_MAP(ArmD3,                  PPSMC_MSG_ArmD3),
+       MSG_MAP(DAL_DISABLE_DUMMY_PSTATE_CHANGE,PPSMC_MSG_DALDisableDummyPstateChange),
+       MSG_MAP(DAL_ENABLE_DUMMY_PSTATE_CHANGE, PPSMC_MSG_DALEnableDummyPstateChange),
 };
 
 static struct smu_11_0_cmn2aisc_mapping navi10_clk_map[SMU_CLK_COUNT] = {
@@ -2093,6 +2095,61 @@ static int navi10_run_btc(struct smu_context *smu)
        return ret;
 }
 
+static int navi10_dummy_pstate_control(struct smu_context *smu, bool enable)
+{
+       int result = 0;
+
+       if (!enable)
+               result = smu_send_smc_msg(smu, SMU_MSG_DAL_DISABLE_DUMMY_PSTATE_CHANGE);
+       else
+               result = smu_send_smc_msg(smu, SMU_MSG_DAL_ENABLE_DUMMY_PSTATE_CHANGE);
+
+       return result;
+}
+
+static int navi10_disable_umc_cdr_12gbps_workaround(struct smu_context *smu)
+{
+       uint32_t uclk_count, uclk_min, uclk_max;
+       uint32_t smu_version;
+       int ret = 0;
+
+       ret = smu_get_smc_version(smu, NULL, &smu_version);
+       if (ret)
+               return ret;
+
+       /* This workaround is available only for 42.50 or later SMC firmwares */
+       if (smu_version < 0x2A3200)
+               return 0;
+
+       ret = smu_get_dpm_level_count(smu, SMU_UCLK, &uclk_count);
+       if (ret)
+               return ret;
+
+       ret = smu_get_dpm_freq_by_index(smu, SMU_UCLK, (uint16_t)0, &uclk_min);
+       if (ret)
+               return ret;
+
+       ret = smu_get_dpm_freq_by_index(smu, SMU_UCLK, (uint16_t)(uclk_count - 1), &uclk_max);
+       if (ret)
+               return ret;
+
+       /* Force UCLK out of the highest DPM */
+       ret = smu_set_hard_freq_range(smu, SMU_UCLK, 0, uclk_min);
+       if (ret)
+               return ret;
+
+       /* Revert the UCLK Hardmax */
+       ret = smu_set_hard_freq_range(smu, SMU_UCLK, 0, uclk_max);
+       if (ret)
+               return ret;
+
+       /*
+        * In this case, SMU already disabled dummy pstate during enablement
+        * of UCLK DPM, we have to re-enabled it.
+        * */
+       return navi10_dummy_pstate_control(smu, true);
+}
+
 static const struct pptable_funcs navi10_ppt_funcs = {
        .tables_init = navi10_tables_init,
        .alloc_dpm_context = navi10_allocate_dpm_context,
@@ -2187,6 +2244,7 @@ static const struct pptable_funcs navi10_ppt_funcs = {
        .od_edit_dpm_table = navi10_od_edit_dpm_table,
        .get_pptable_power_limit = navi10_get_pptable_power_limit,
        .run_btc = navi10_run_btc,
+       .disable_umc_cdr_12gbps_workaround = navi10_disable_umc_cdr_12gbps_workaround,
 };
 
 void navi10_set_ppt_funcs(struct smu_context *smu)
index 783319ec8bf9c05159babcb39f89d38292c9a225..7bd200ffcda8b873fcd2a76d23440abca4ae0b49 100644 (file)
@@ -207,4 +207,7 @@ int smu_send_smc_msg(struct smu_context *smu, enum smu_message_type msg);
 #define smu_update_pcie_parameters(smu, pcie_gen_cap, pcie_width_cap) \
                ((smu)->ppt_funcs->update_pcie_parameters ? (smu)->ppt_funcs->update_pcie_parameters((smu), (pcie_gen_cap), (pcie_width_cap)) : 0)
 
+#define smu_disable_umc_cdr_12gbps_workaround(smu) \
+       ((smu)->ppt_funcs->disable_umc_cdr_12gbps_workaround ? (smu)->ppt_funcs->disable_umc_cdr_12gbps_workaround((smu)) : 0)
+
 #endif