drm/amd/pm: bug fix for pcie dpm
Currently the pcie dpm has two problems. 1. Only the high dpm level speed/width can be overrided if the requested values are out of the pcie capability. 2. The high dpm level is always overrided though sometimes it's not necesarry. Signed-off-by: Kenneth Feng <kenneth.feng@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> Cc: stable@vger.kernel.org
This commit is contained in:
parent
521f04f9e3
commit
50ceb1fe7a
|
@ -1505,6 +1505,48 @@ static int vega10_populate_single_lclk_level(struct pp_hwmgr *hwmgr,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int vega10_override_pcie_parameters(struct pp_hwmgr *hwmgr)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)(hwmgr->adev);
|
||||
struct vega10_hwmgr *data =
|
||||
(struct vega10_hwmgr *)(hwmgr->backend);
|
||||
uint32_t pcie_gen = 0, pcie_width = 0;
|
||||
PPTable_t *pp_table = &(data->smc_state_table.pp_table);
|
||||
int i;
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
for (i = 0; i < NUM_LINK_LEVELS; i++) {
|
||||
if (pp_table->PcieGenSpeed[i] > pcie_gen)
|
||||
pp_table->PcieGenSpeed[i] = pcie_gen;
|
||||
|
||||
if (pp_table->PcieLaneCount[i] > pcie_width)
|
||||
pp_table->PcieLaneCount[i] = pcie_width;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int vega10_populate_smc_link_levels(struct pp_hwmgr *hwmgr)
|
||||
{
|
||||
int result = -1;
|
||||
|
@ -2556,6 +2598,11 @@ static int vega10_init_smc_table(struct pp_hwmgr *hwmgr)
|
|||
"Failed to initialize Link Level!",
|
||||
return result);
|
||||
|
||||
result = vega10_override_pcie_parameters(hwmgr);
|
||||
PP_ASSERT_WITH_CODE(!result,
|
||||
"Failed to override pcie parameters!",
|
||||
return result);
|
||||
|
||||
result = vega10_populate_all_graphic_levels(hwmgr);
|
||||
PP_ASSERT_WITH_CODE(!result,
|
||||
"Failed to initialize Graphics Level!",
|
||||
|
@ -2922,6 +2969,7 @@ static int vega10_start_dpm(struct pp_hwmgr *hwmgr, uint32_t bitmap)
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int vega10_enable_disable_PCC_limit_feature(struct pp_hwmgr *hwmgr, bool enable)
|
||||
{
|
||||
struct vega10_hwmgr *data = hwmgr->backend;
|
||||
|
|
|
@ -481,6 +481,67 @@ static void vega12_init_dpm_state(struct vega12_dpm_state *dpm_state)
|
|||
dpm_state->hard_max_level = 0xffff;
|
||||
}
|
||||
|
||||
static int vega12_override_pcie_parameters(struct pp_hwmgr *hwmgr)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)(hwmgr->adev);
|
||||
struct vega12_hwmgr *data =
|
||||
(struct vega12_hwmgr *)(hwmgr->backend);
|
||||
uint32_t pcie_gen = 0, pcie_width = 0, smu_pcie_arg, pcie_gen_arg, pcie_width_arg;
|
||||
PPTable_t *pp_table = &(data->smc_state_table.pp_table);
|
||||
int i;
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
/* 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
|
||||
*/
|
||||
for (i = 0; i < NUM_LINK_LEVELS; i++) {
|
||||
pcie_gen_arg = (pp_table->PcieGenSpeed[i] > pcie_gen) ? pcie_gen :
|
||||
pp_table->PcieGenSpeed[i];
|
||||
pcie_width_arg = (pp_table->PcieLaneCount[i] > pcie_width) ? pcie_width :
|
||||
pp_table->PcieLaneCount[i];
|
||||
|
||||
if (pcie_gen_arg != pp_table->PcieGenSpeed[i] || pcie_width_arg !=
|
||||
pp_table->PcieLaneCount[i]) {
|
||||
smu_pcie_arg = (i << 16) | (pcie_gen_arg << 8) | pcie_width_arg;
|
||||
ret = smum_send_msg_to_smc_with_parameter(hwmgr,
|
||||
PPSMC_MSG_OverridePcieParameters, smu_pcie_arg,
|
||||
NULL);
|
||||
PP_ASSERT_WITH_CODE(!ret,
|
||||
"[OverridePcieParameters] Attempt to override pcie params failed!",
|
||||
return ret);
|
||||
}
|
||||
|
||||
/* update the pptable */
|
||||
pp_table->PcieGenSpeed[i] = pcie_gen_arg;
|
||||
pp_table->PcieLaneCount[i] = pcie_width_arg;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int vega12_get_number_of_dpm_level(struct pp_hwmgr *hwmgr,
|
||||
PPCLK_e clk_id, uint32_t *num_of_levels)
|
||||
{
|
||||
|
@ -968,6 +1029,11 @@ static int vega12_enable_dpm_tasks(struct pp_hwmgr *hwmgr)
|
|||
"Failed to enable all smu features!",
|
||||
return result);
|
||||
|
||||
result = vega12_override_pcie_parameters(hwmgr);
|
||||
PP_ASSERT_WITH_CODE(!result,
|
||||
"[EnableDPMTasks] Failed to override pcie parameters!",
|
||||
return result);
|
||||
|
||||
tmp_result = vega12_power_control_set_level(hwmgr);
|
||||
PP_ASSERT_WITH_CODE(!tmp_result,
|
||||
"Failed to power control set level!",
|
||||
|
|
|
@ -831,7 +831,9 @@ static int vega20_override_pcie_parameters(struct pp_hwmgr *hwmgr)
|
|||
struct amdgpu_device *adev = (struct amdgpu_device *)(hwmgr->adev);
|
||||
struct vega20_hwmgr *data =
|
||||
(struct vega20_hwmgr *)(hwmgr->backend);
|
||||
uint32_t pcie_gen = 0, pcie_width = 0, smu_pcie_arg;
|
||||
uint32_t pcie_gen = 0, pcie_width = 0, smu_pcie_arg, pcie_gen_arg, pcie_width_arg;
|
||||
PPTable_t *pp_table = &(data->smc_state_table.pp_table);
|
||||
int i;
|
||||
int ret;
|
||||
|
||||
if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN4)
|
||||
|
@ -860,17 +862,27 @@ static int vega20_override_pcie_parameters(struct pp_hwmgr *hwmgr)
|
|||
* 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
|
||||
*/
|
||||
smu_pcie_arg = (1 << 16) | (pcie_gen << 8) | pcie_width;
|
||||
ret = smum_send_msg_to_smc_with_parameter(hwmgr,
|
||||
PPSMC_MSG_OverridePcieParameters, smu_pcie_arg,
|
||||
NULL);
|
||||
PP_ASSERT_WITH_CODE(!ret,
|
||||
"[OverridePcieParameters] Attempt to override pcie params failed!",
|
||||
return ret);
|
||||
for (i = 0; i < NUM_LINK_LEVELS; i++) {
|
||||
pcie_gen_arg = (pp_table->PcieGenSpeed[i] > pcie_gen) ? pcie_gen :
|
||||
pp_table->PcieGenSpeed[i];
|
||||
pcie_width_arg = (pp_table->PcieLaneCount[i] > pcie_width) ? pcie_width :
|
||||
pp_table->PcieLaneCount[i];
|
||||
|
||||
data->pcie_parameters_override = true;
|
||||
data->pcie_gen_level1 = pcie_gen;
|
||||
data->pcie_width_level1 = pcie_width;
|
||||
if (pcie_gen_arg != pp_table->PcieGenSpeed[i] || pcie_width_arg !=
|
||||
pp_table->PcieLaneCount[i]) {
|
||||
smu_pcie_arg = (i << 16) | (pcie_gen_arg << 8) | pcie_width_arg;
|
||||
ret = smum_send_msg_to_smc_with_parameter(hwmgr,
|
||||
PPSMC_MSG_OverridePcieParameters, smu_pcie_arg,
|
||||
NULL);
|
||||
PP_ASSERT_WITH_CODE(!ret,
|
||||
"[OverridePcieParameters] Attempt to override pcie params failed!",
|
||||
return ret);
|
||||
}
|
||||
|
||||
/* update the pptable */
|
||||
pp_table->PcieGenSpeed[i] = pcie_gen_arg;
|
||||
pp_table->PcieLaneCount[i] = pcie_width_arg;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -3319,9 +3331,7 @@ static int vega20_print_clock_levels(struct pp_hwmgr *hwmgr,
|
|||
data->od8_settings.od8_settings_array;
|
||||
OverDriveTable_t *od_table =
|
||||
&(data->smc_state_table.overdrive_table);
|
||||
struct phm_ppt_v3_information *pptable_information =
|
||||
(struct phm_ppt_v3_information *)hwmgr->pptable;
|
||||
PPTable_t *pptable = (PPTable_t *)pptable_information->smc_pptable;
|
||||
PPTable_t *pptable = &(data->smc_state_table.pp_table);
|
||||
struct pp_clock_levels_with_latency clocks;
|
||||
struct vega20_single_dpm_table *fclk_dpm_table =
|
||||
&(data->dpm_table.fclk_table);
|
||||
|
@ -3420,13 +3430,9 @@ static int vega20_print_clock_levels(struct pp_hwmgr *hwmgr,
|
|||
current_lane_width =
|
||||
vega20_get_current_pcie_link_width_level(hwmgr);
|
||||
for (i = 0; i < NUM_LINK_LEVELS; i++) {
|
||||
if (i == 1 && data->pcie_parameters_override) {
|
||||
gen_speed = data->pcie_gen_level1;
|
||||
lane_width = data->pcie_width_level1;
|
||||
} else {
|
||||
gen_speed = pptable->PcieGenSpeed[i];
|
||||
lane_width = pptable->PcieLaneCount[i];
|
||||
}
|
||||
gen_speed = pptable->PcieGenSpeed[i];
|
||||
lane_width = pptable->PcieLaneCount[i];
|
||||
|
||||
size += sprintf(buf + size, "%d: %s %s %dMhz %s\n", i,
|
||||
(gen_speed == 0) ? "2.5GT/s," :
|
||||
(gen_speed == 1) ? "5.0GT/s," :
|
||||
|
|
Loading…
Reference in New Issue