aboutsummaryrefslogtreecommitdiffstats
path: root/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/4133-drm-amd-powerplay-bug-fix-for-pcie-parameters-overri.patch
diff options
context:
space:
mode:
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.patch273
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
+