mirror of https://gitee.com/openkylin/linux.git
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> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
parent
bcccee89f4
commit
372120f0a5
|
@ -945,50 +945,6 @@ static int smu_fini_fb_allocations(struct smu_context *smu)
|
||||||
return 0;
|
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,
|
static int smu_smc_table_hw_init(struct smu_context *smu,
|
||||||
bool initialize)
|
bool initialize)
|
||||||
{
|
{
|
||||||
|
|
|
@ -469,6 +469,7 @@ struct pptable_funcs {
|
||||||
int (*get_dpm_clk_limited)(struct smu_context *smu, enum smu_clk_type clk_type,
|
int (*get_dpm_clk_limited)(struct smu_context *smu, enum smu_clk_type clk_type,
|
||||||
uint32_t dpm_level, uint32_t *freq);
|
uint32_t dpm_level, uint32_t *freq);
|
||||||
int (*set_df_cstate)(struct smu_context *smu, enum pp_df_cstate state);
|
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
|
struct smu_funcs
|
||||||
|
@ -551,6 +552,7 @@ struct smu_funcs
|
||||||
int (*mode2_reset)(struct smu_context *smu);
|
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 (*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 (*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) \
|
#define smu_init_microcode(smu) \
|
||||||
|
@ -783,6 +785,12 @@ struct smu_funcs
|
||||||
#define smu_set_soft_freq_limited_range(smu, clk_type, min, max) \
|
#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)
|
((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,
|
extern int smu_get_atom_data_table(struct smu_context *smu, uint32_t table,
|
||||||
uint16_t *size, uint8_t *frev, uint8_t *crev,
|
uint16_t *size, uint8_t *frev, uint8_t *crev,
|
||||||
uint8_t **addr);
|
uint8_t **addr);
|
||||||
|
|
|
@ -1629,6 +1629,28 @@ static int navi10_get_power_limit(struct smu_context *smu,
|
||||||
return 0;
|
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 = {
|
static const struct pptable_funcs navi10_ppt_funcs = {
|
||||||
.tables_init = navi10_tables_init,
|
.tables_init = navi10_tables_init,
|
||||||
.alloc_dpm_context = navi10_allocate_dpm_context,
|
.alloc_dpm_context = navi10_allocate_dpm_context,
|
||||||
|
@ -1667,6 +1689,7 @@ static const struct pptable_funcs navi10_ppt_funcs = {
|
||||||
.get_thermal_temperature_range = navi10_get_thermal_temperature_range,
|
.get_thermal_temperature_range = navi10_get_thermal_temperature_range,
|
||||||
.display_disable_memory_clock_switch = navi10_display_disable_memory_clock_switch,
|
.display_disable_memory_clock_switch = navi10_display_disable_memory_clock_switch,
|
||||||
.get_power_limit = navi10_get_power_limit,
|
.get_power_limit = navi10_get_power_limit,
|
||||||
|
.update_pcie_parameters = navi10_update_pcie_parameters,
|
||||||
};
|
};
|
||||||
|
|
||||||
void navi10_set_ppt_funcs(struct smu_context *smu)
|
void navi10_set_ppt_funcs(struct smu_context *smu)
|
||||||
|
|
|
@ -35,6 +35,7 @@
|
||||||
#include "vega20_ppt.h"
|
#include "vega20_ppt.h"
|
||||||
#include "arcturus_ppt.h"
|
#include "arcturus_ppt.h"
|
||||||
#include "navi10_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_offset.h"
|
||||||
#include "asic_reg/thm/thm_11_0_2_sh_mask.h"
|
#include "asic_reg/thm/thm_11_0_2_sh_mask.h"
|
||||||
|
@ -1792,6 +1793,48 @@ static int smu_v11_0_set_soft_freq_limited_range(struct smu_context *smu, enum s
|
||||||
return ret;
|
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 = {
|
static const struct smu_funcs smu_v11_0_funcs = {
|
||||||
.init_microcode = smu_v11_0_init_microcode,
|
.init_microcode = smu_v11_0_init_microcode,
|
||||||
.load_microcode = smu_v11_0_load_microcode,
|
.load_microcode = smu_v11_0_load_microcode,
|
||||||
|
@ -1844,6 +1887,7 @@ static const struct smu_funcs smu_v11_0_funcs = {
|
||||||
.baco_reset = smu_v11_0_baco_reset,
|
.baco_reset = smu_v11_0_baco_reset,
|
||||||
.get_dpm_ultimate_freq = smu_v11_0_get_dpm_ultimate_freq,
|
.get_dpm_ultimate_freq = smu_v11_0_get_dpm_ultimate_freq,
|
||||||
.set_soft_freq_limited_range = smu_v11_0_set_soft_freq_limited_range,
|
.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)
|
void smu_v11_0_set_smu_funcs(struct smu_context *smu)
|
||||||
|
|
|
@ -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);
|
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 = {
|
static const struct pptable_funcs vega20_ppt_funcs = {
|
||||||
.tables_init = vega20_tables_init,
|
.tables_init = vega20_tables_init,
|
||||||
.alloc_dpm_context = vega20_allocate_dpm_context,
|
.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,
|
.set_watermarks_table = vega20_set_watermarks_table,
|
||||||
.get_thermal_temperature_range = vega20_get_thermal_temperature_range,
|
.get_thermal_temperature_range = vega20_get_thermal_temperature_range,
|
||||||
.set_df_cstate = vega20_set_df_cstate,
|
.set_df_cstate = vega20_set_df_cstate,
|
||||||
|
.update_pcie_parameters = vega20_update_pcie_parameters
|
||||||
};
|
};
|
||||||
|
|
||||||
void vega20_set_ppt_funcs(struct smu_context *smu)
|
void vega20_set_ppt_funcs(struct smu_context *smu)
|
||||||
|
|
Loading…
Reference in New Issue