Skip to content

Commit

Permalink
drm/amd/pm: bug fix for pcie dpm
Browse files Browse the repository at this point in the history
commit 50ceb1f upstream.

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
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
Kenneth Feng authored and gregkh committed Mar 17, 2021
1 parent 6b99002 commit 96b097e
Show file tree
Hide file tree
Showing 3 changed files with 141 additions and 21 deletions.
48 changes: 48 additions & 0 deletions drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_hwmgr.c
Expand Up @@ -1506,6 +1506,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;
Expand Down Expand Up @@ -2557,6 +2599,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!",
Expand Down Expand Up @@ -2923,6 +2970,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;
Expand Down
66 changes: 66 additions & 0 deletions drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_hwmgr.c
Expand Up @@ -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)
{
Expand Down Expand Up @@ -969,6 +1030,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!",
Expand Down
48 changes: 27 additions & 21 deletions drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_hwmgr.c
Expand Up @@ -832,7 +832,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)
Expand Down Expand Up @@ -861,17 +863,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];

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);
}

data->pcie_parameters_override = true;
data->pcie_gen_level1 = pcie_gen;
data->pcie_width_level1 = pcie_width;
/* update the pptable */
pp_table->PcieGenSpeed[i] = pcie_gen_arg;
pp_table->PcieLaneCount[i] = pcie_width_arg;
}

return 0;
}
Expand Down Expand Up @@ -3320,9 +3332,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);
Expand Down Expand Up @@ -3421,13 +3431,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," :
Expand Down

0 comments on commit 96b097e

Please sign in to comment.