diff options
Diffstat (limited to 'meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/4133-drm-amd-powerplay-bug-fix-for-pcie-parameters-overri.patch')
-rw-r--r-- | meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/4133-drm-amd-powerplay-bug-fix-for-pcie-parameters-overri.patch | 273 |
1 files changed, 273 insertions, 0 deletions
diff --git a/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/4133-drm-amd-powerplay-bug-fix-for-pcie-parameters-overri.patch b/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/4133-drm-amd-powerplay-bug-fix-for-pcie-parameters-overri.patch new file mode 100644 index 00000000..1907ed9b --- /dev/null +++ b/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/4133-drm-amd-powerplay-bug-fix-for-pcie-parameters-overri.patch @@ -0,0 +1,273 @@ +From 0d3a43711fc55bba4355010ec4c165bafad46c69 Mon Sep 17 00:00:00 2001 +From: Kenneth Feng <kenneth.feng@amd.com> +Date: Fri, 11 Oct 2019 17:51:34 +0800 +Subject: [PATCH 4133/4736] drm/amd/powerplay: bug fix for pcie parameters + override + +Bug fix for pcie paramerers override on swsmu. +Below is a scenario to have this problem. +pptable definition on pcie dpm: +0 -> pcie gen speed:1, pcie lanes: *16 +1 -> pcie gen speed:4, pcie lanes: *16 +Then if we have a system only have the capbility: +pcie gen speed: 3, pcie lanes: *8, +we will override dpm 1 to pcie gen speed 3, pcie lanes *8. +But the code skips the dpm 0 configuration. +So the real pcie dpm parameters are: +0 -> pcie gen speed:1, pcie lanes: *16 +1 -> pcie gen speed:3, pcie lanes: *8 +Then the wrong pcie lanes will be toggled. + +Signed-off-by: Kenneth Feng <kenneth.feng@amd.com> +Reviewed-by: Alex Deucher <alexander.deucher@amd.com> +Reviewed-by: Evan Quan <evan.quan@amd.com> +--- + drivers/gpu/drm/amd/powerplay/amdgpu_smu.c | 44 ------------------- + .../gpu/drm/amd/powerplay/inc/amdgpu_smu.h | 8 ++++ + drivers/gpu/drm/amd/powerplay/navi10_ppt.c | 23 ++++++++++ + drivers/gpu/drm/amd/powerplay/smu_v11_0.c | 44 +++++++++++++++++++ + drivers/gpu/drm/amd/powerplay/vega20_ppt.c | 23 ++++++++++ + 5 files changed, 98 insertions(+), 44 deletions(-) + +diff --git a/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c b/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c +index a37a1b1d8abd..26cacc899dfe 100644 +--- a/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c ++++ b/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c +@@ -945,50 +945,6 @@ static int smu_fini_fb_allocations(struct smu_context *smu) + return 0; + } + +-static int smu_override_pcie_parameters(struct smu_context *smu) +-{ +- struct amdgpu_device *adev = smu->adev; +- uint32_t pcie_gen = 0, pcie_width = 0, smu_pcie_arg; +- int ret; +- +- if (adev->flags & AMD_IS_APU) +- return 0; +- +- if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN4) +- pcie_gen = 3; +- else if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3) +- pcie_gen = 2; +- else if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN2) +- pcie_gen = 1; +- else if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN1) +- pcie_gen = 0; +- +- /* Bit 31:16: LCLK DPM level. 0 is DPM0, and 1 is DPM1 +- * Bit 15:8: PCIE GEN, 0 to 3 corresponds to GEN1 to GEN4 +- * Bit 7:0: PCIE lane width, 1 to 7 corresponds is x1 to x32 +- */ +- if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X16) +- pcie_width = 6; +- else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X12) +- pcie_width = 5; +- else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X8) +- pcie_width = 4; +- else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X4) +- pcie_width = 3; +- else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X2) +- pcie_width = 2; +- else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X1) +- pcie_width = 1; +- +- smu_pcie_arg = (1 << 16) | (pcie_gen << 8) | pcie_width; +- ret = smu_send_smc_msg_with_param(smu, +- SMU_MSG_OverridePcieParameters, +- smu_pcie_arg); +- if (ret) +- pr_err("[%s] Attempt to override pcie params failed!\n", __func__); +- return ret; +-} +- + static int smu_smc_table_hw_init(struct smu_context *smu, + bool initialize) + { +diff --git a/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h b/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h +index 401affdee49d..cdb845f5f23e 100644 +--- a/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h ++++ b/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h +@@ -469,6 +469,7 @@ struct pptable_funcs { + int (*get_dpm_clk_limited)(struct smu_context *smu, enum smu_clk_type clk_type, + uint32_t dpm_level, uint32_t *freq); + int (*set_df_cstate)(struct smu_context *smu, enum pp_df_cstate state); ++ int (*update_pcie_parameters)(struct smu_context *smu, uint32_t pcie_gen_cap, uint32_t pcie_width_cap); + }; + + struct smu_funcs +@@ -551,6 +552,7 @@ struct smu_funcs + int (*mode2_reset)(struct smu_context *smu); + int (*get_dpm_ultimate_freq)(struct smu_context *smu, enum smu_clk_type clk_type, uint32_t *min, uint32_t *max); + 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); + }; + + #define smu_init_microcode(smu) \ +@@ -783,6 +785,12 @@ struct smu_funcs + #define smu_set_soft_freq_limited_range(smu, clk_type, min, max) \ + ((smu)->funcs->set_soft_freq_limited_range ? (smu)->funcs->set_soft_freq_limited_range((smu), (clk_type), (min), (max)) : -EINVAL) + ++#define smu_override_pcie_parameters(smu) \ ++ ((smu)->funcs->override_pcie_parameters ? (smu)->funcs->override_pcie_parameters((smu)) : 0) ++ ++#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) ++ + extern int smu_get_atom_data_table(struct smu_context *smu, uint32_t table, + uint16_t *size, uint8_t *frev, uint8_t *crev, + uint8_t **addr); +diff --git a/drivers/gpu/drm/amd/powerplay/navi10_ppt.c b/drivers/gpu/drm/amd/powerplay/navi10_ppt.c +index e8e5c889cc95..b88aae9bb242 100644 +--- a/drivers/gpu/drm/amd/powerplay/navi10_ppt.c ++++ b/drivers/gpu/drm/amd/powerplay/navi10_ppt.c +@@ -1628,6 +1628,28 @@ static int navi10_get_power_limit(struct smu_context *smu, + return 0; + } + ++static int navi10_update_pcie_parameters(struct smu_context *smu, ++ uint32_t pcie_gen_cap, ++ uint32_t pcie_width_cap) ++{ ++ PPTable_t *pptable = smu->smu_table.driver_pptable; ++ int ret, i; ++ uint32_t smu_pcie_arg; ++ ++ for (i = 0; i < NUM_LINK_LEVELS; i++) { ++ smu_pcie_arg = (i << 16) | ++ ((pptable->PcieGenSpeed[i] <= pcie_gen_cap) ? (pptable->PcieGenSpeed[i] << 8) : ++ (pcie_gen_cap << 8)) | ((pptable->PcieLaneCount[i] <= pcie_width_cap) ? ++ pptable->PcieLaneCount[i] : pcie_width_cap); ++ ret = smu_send_smc_msg_with_param(smu, ++ SMU_MSG_OverridePcieParameters, ++ smu_pcie_arg); ++ } ++ ++ return ret; ++} ++ ++ + static const struct pptable_funcs navi10_ppt_funcs = { + .tables_init = navi10_tables_init, + .alloc_dpm_context = navi10_allocate_dpm_context, +@@ -1666,6 +1688,7 @@ static const struct pptable_funcs navi10_ppt_funcs = { + .get_thermal_temperature_range = navi10_get_thermal_temperature_range, + .display_disable_memory_clock_switch = navi10_display_disable_memory_clock_switch, + .get_power_limit = navi10_get_power_limit, ++ .update_pcie_parameters = navi10_update_pcie_parameters, + }; + + void navi10_set_ppt_funcs(struct smu_context *smu) +diff --git a/drivers/gpu/drm/amd/powerplay/smu_v11_0.c b/drivers/gpu/drm/amd/powerplay/smu_v11_0.c +index 9883f0a4471a..df1f2b99fed7 100644 +--- a/drivers/gpu/drm/amd/powerplay/smu_v11_0.c ++++ b/drivers/gpu/drm/amd/powerplay/smu_v11_0.c +@@ -32,6 +32,7 @@ + #include "vega20_ppt.h" + #include "arcturus_ppt.h" + #include "navi10_ppt.h" ++#include "amd_pcie.h" + + #include "asic_reg/thm/thm_11_0_2_offset.h" + #include "asic_reg/thm/thm_11_0_2_sh_mask.h" +@@ -1791,6 +1792,48 @@ static int smu_v11_0_set_soft_freq_limited_range(struct smu_context *smu, enum s + return ret; + } + ++static int smu_v11_0_override_pcie_parameters(struct smu_context *smu) ++{ ++ struct amdgpu_device *adev = smu->adev; ++ uint32_t pcie_gen = 0, pcie_width = 0; ++ int ret; ++ ++ if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN4) ++ pcie_gen = 3; ++ else if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3) ++ pcie_gen = 2; ++ else if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN2) ++ pcie_gen = 1; ++ else if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN1) ++ pcie_gen = 0; ++ ++ /* Bit 31:16: LCLK DPM level. 0 is DPM0, and 1 is DPM1 ++ * Bit 15:8: PCIE GEN, 0 to 3 corresponds to GEN1 to GEN4 ++ * Bit 7:0: PCIE lane width, 1 to 7 corresponds is x1 to x32 ++ */ ++ if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X16) ++ pcie_width = 6; ++ else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X12) ++ pcie_width = 5; ++ else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X8) ++ pcie_width = 4; ++ else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X4) ++ pcie_width = 3; ++ else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X2) ++ pcie_width = 2; ++ else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X1) ++ pcie_width = 1; ++ ++ ret = smu_update_pcie_parameters(smu, pcie_gen, pcie_width); ++ ++ if (ret) ++ pr_err("[%s] Attempt to override pcie params failed!\n", __func__); ++ ++ return ret; ++ ++} ++ ++ + static const struct smu_funcs smu_v11_0_funcs = { + .init_microcode = smu_v11_0_init_microcode, + .load_microcode = smu_v11_0_load_microcode, +@@ -1843,6 +1886,7 @@ static const struct smu_funcs smu_v11_0_funcs = { + .baco_reset = smu_v11_0_baco_reset, + .get_dpm_ultimate_freq = smu_v11_0_get_dpm_ultimate_freq, + .set_soft_freq_limited_range = smu_v11_0_set_soft_freq_limited_range, ++ .override_pcie_parameters = smu_v11_0_override_pcie_parameters, + }; + + void smu_v11_0_set_smu_funcs(struct smu_context *smu) +diff --git a/drivers/gpu/drm/amd/powerplay/vega20_ppt.c b/drivers/gpu/drm/amd/powerplay/vega20_ppt.c +index 1050566cb69a..a76ffd58404e 100644 +--- a/drivers/gpu/drm/amd/powerplay/vega20_ppt.c ++++ b/drivers/gpu/drm/amd/powerplay/vega20_ppt.c +@@ -3157,6 +3157,28 @@ static int vega20_set_df_cstate(struct smu_context *smu, + return smu_send_smc_msg_with_param(smu, SMU_MSG_DFCstateControl, state); + } + ++static int vega20_update_pcie_parameters(struct smu_context *smu, ++ uint32_t pcie_gen_cap, ++ uint32_t pcie_width_cap) ++{ ++ PPTable_t *pptable = smu->smu_table.driver_pptable; ++ int ret, i; ++ uint32_t smu_pcie_arg; ++ ++ for (i = 0; i < NUM_LINK_LEVELS; i++) { ++ smu_pcie_arg = (i << 16) | ++ ((pptable->PcieGenSpeed[i] <= pcie_gen_cap) ? (pptable->PcieGenSpeed[i] << 8) : ++ (pcie_gen_cap << 8)) | ((pptable->PcieLaneCount[i] <= pcie_width_cap) ? ++ pptable->PcieLaneCount[i] : pcie_width_cap); ++ ret = smu_send_smc_msg_with_param(smu, ++ SMU_MSG_OverridePcieParameters, ++ smu_pcie_arg); ++ } ++ ++ return ret; ++} ++ ++ + static const struct pptable_funcs vega20_ppt_funcs = { + .tables_init = vega20_tables_init, + .alloc_dpm_context = vega20_allocate_dpm_context, +@@ -3201,6 +3223,7 @@ static const struct pptable_funcs vega20_ppt_funcs = { + .set_watermarks_table = vega20_set_watermarks_table, + .get_thermal_temperature_range = vega20_get_thermal_temperature_range, + .set_df_cstate = vega20_set_df_cstate, ++ .update_pcie_parameters = vega20_update_pcie_parameters + }; + + void vega20_set_ppt_funcs(struct smu_context *smu) +-- +2.17.1 + |