[PATCH v2] drm/amd/powerplay: bug fix for pcie parameters override
Alex Deucher
alexdeucher at gmail.com
Sat Oct 12 02:06:06 UTC 2019
On Fri, Oct 11, 2019 at 6:34 AM Kenneth Feng <kenneth.feng at amd.com> wrote:
>
> 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 at amd.com>
Reviewed-by: Alex Deucher <alexander.deucher at amd.com>
> ---
> drivers/gpu/drm/amd/powerplay/amdgpu_smu.c | 44 --------------------------
> drivers/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 | 25 ++++++++++++++-
> 5 files changed, 99 insertions(+), 45 deletions(-)
>
> diff --git a/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c b/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c
> index c9266ea..de54da2 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 ccf711c..809de0d 100644
> --- a/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h
> +++ b/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h
> @@ -468,6 +468,7 @@ struct pptable_funcs {
> int (*get_power_limit)(struct smu_context *smu, uint32_t *limit, bool asic_default);
> int (*get_dpm_clk_limited)(struct smu_context *smu, enum smu_clk_type clk_type,
> uint32_t dpm_level, uint32_t *freq);
> + int (*update_pcie_parameters)(struct smu_context *smu, uint32_t pcie_gen_cap, uint32_t pcie_width_cap);
> };
>
> struct smu_funcs
> @@ -550,6 +551,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) \
> @@ -782,6 +784,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 a583cf8..a2f33cf 100644
> --- a/drivers/gpu/drm/amd/powerplay/navi10_ppt.c
> +++ b/drivers/gpu/drm/amd/powerplay/navi10_ppt.c
> @@ -1592,6 +1592,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,
> @@ -1630,6 +1652,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 c9e90d5..a812ae5 100644
> --- a/drivers/gpu/drm/amd/powerplay/smu_v11_0.c
> +++ b/drivers/gpu/drm/amd/powerplay/smu_v11_0.c
> @@ -35,6 +35,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"
> @@ -1792,6 +1793,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,
> @@ -1844,6 +1887,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 f655ebd..adca84a 100644
> --- a/drivers/gpu/drm/amd/powerplay/vega20_ppt.c
> +++ b/drivers/gpu/drm/amd/powerplay/vega20_ppt.c
> @@ -3135,6 +3135,28 @@ static int vega20_get_thermal_temperature_range(struct smu_context *smu,
> return 0;
> }
>
> +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,
> @@ -3177,7 +3199,8 @@ static const struct pptable_funcs vega20_ppt_funcs = {
> .get_fan_speed_percent = vega20_get_fan_speed_percent,
> .get_fan_speed_rpm = vega20_get_fan_speed_rpm,
> .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,
> + .update_pcie_parameters = vega20_update_pcie_parameters
> };
>
> void vega20_set_ppt_funcs(struct smu_context *smu)
> --
> 2.7.4
>
> _______________________________________________
> amd-gfx mailing list
> amd-gfx at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/amd-gfx
More information about the amd-gfx
mailing list