[PATCH 4/7] drm/amd/pm: correct the fan speed RPM retrieving

Lazar, Lijo lijo.lazar at amd.com
Wed Jul 7 09:05:43 UTC 2021



On 7/7/2021 7:26 AM, Evan Quan wrote:
> The relationship "PWM = RPM / smu->fan_max_rpm" between fan speed
> PWM and RPM is not true for SMU11 ASICs. So, we need a new way to
> retrieving the fan speed RPM.
> 
> Change-Id: Ife4298c8b7ec93ef023a7da27d59654e0444e044
> Signed-off-by: Evan Quan <evan.quan at amd.com>
> ---
>   .../include/asic_reg/thm/thm_11_0_2_offset.h  |  3 ++
>   drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h       |  5 ++++
>   drivers/gpu/drm/amd/pm/inc/smu_v11_0.h        |  3 ++
>   drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c     |  7 ++---
>   .../gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c | 24 ++++++++++++++++
>   .../gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c   | 24 ++++++++++++++++
>   .../amd/pm/swsmu/smu11/sienna_cichlid_ppt.c   | 21 ++++++++++++++
>   .../gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c    | 28 +++++++++++++++++++
>   8 files changed, 110 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/gpu/drm/amd/include/asic_reg/thm/thm_11_0_2_offset.h b/drivers/gpu/drm/amd/include/asic_reg/thm/thm_11_0_2_offset.h
> index eca96abef445..8474f419caa5 100644
> --- a/drivers/gpu/drm/amd/include/asic_reg/thm/thm_11_0_2_offset.h
> +++ b/drivers/gpu/drm/amd/include/asic_reg/thm/thm_11_0_2_offset.h
> @@ -38,6 +38,9 @@
>   #define mmCG_TACH_CTRL                                                                                 0x006a
>   #define mmCG_TACH_CTRL_BASE_IDX                                                                        0
>   
> +#define mmCG_TACH_STATUS                                                                               0x006b
> +#define mmCG_TACH_STATUS_BASE_IDX                                                                      0
> +
>   #define mmTHM_THERMAL_INT_ENA                                                                          0x000a
>   #define mmTHM_THERMAL_INT_ENA_BASE_IDX                                                                 0
>   #define mmTHM_THERMAL_INT_CTRL                                                                         0x000b
> diff --git a/drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h b/drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h
> index fa585f0be530..db5123fc6042 100644
> --- a/drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h
> +++ b/drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h
> @@ -726,6 +726,11 @@ struct pptable_funcs {
>   	 */
>   	int (*get_fan_speed_percent)(struct smu_context *smu, uint32_t *speed);
>   
> +	/**
> +	 * @get_fan_speed_rpm: Get the current fan speed in rpm.
> +	 */
> +	int (*get_fan_speed_rpm)(struct smu_context *smu, uint32_t *speed);
> +
>   	/**
>   	 * @set_watermarks_table: Configure and upload the watermarks tables to
>   	 *                        the SMU.
> diff --git a/drivers/gpu/drm/amd/pm/inc/smu_v11_0.h b/drivers/gpu/drm/amd/pm/inc/smu_v11_0.h
> index 8e0f8e9a1665..05c8fc8fc3f9 100644
> --- a/drivers/gpu/drm/amd/pm/inc/smu_v11_0.h
> +++ b/drivers/gpu/drm/amd/pm/inc/smu_v11_0.h
> @@ -229,6 +229,9 @@ int smu_v11_0_set_fan_speed_rpm(struct smu_context *smu,
>   int smu_v11_0_get_fan_speed_percent(struct smu_context *smu,
>   				    uint32_t *speed);
>   
> +int smu_v11_0_get_fan_speed_rpm(struct smu_context *smu,
> +				uint32_t *speed);
> +
>   int smu_v11_0_set_xgmi_pstate(struct smu_context *smu,
>   				     uint32_t pstate);
>   
> diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
> index 9a25443988e3..54fb3d7d23ee 100644
> --- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
> +++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
> @@ -2614,17 +2614,14 @@ static int smu_get_fan_speed_rpm(void *handle, uint32_t *speed)
>   {
>   	struct smu_context *smu = handle;
>   	int ret = 0;
> -	u32 percent;
>   
>   	if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled)
>   		return -EOPNOTSUPP;
>   
>   	mutex_lock(&smu->mutex);
>   
> -	if (smu->ppt_funcs->get_fan_speed_percent) {
> -		ret = smu->ppt_funcs->get_fan_speed_percent(smu, &percent);
> -		*speed = percent * smu->fan_max_rpm / 100;
> -	}
> +	if (smu->ppt_funcs->get_fan_speed_rpm)
> +		ret = smu->ppt_funcs->get_fan_speed_rpm(smu, speed);
>   
>   	mutex_unlock(&smu->mutex);
>   
> diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c
> index 4a6544b8e05e..e3303c8dcaca 100644
> --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c
> +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c
> @@ -1162,6 +1162,29 @@ static int arcturus_read_sensor(struct smu_context *smu,
>   	return ret;
>   }
>   
> +static int arcturus_get_fan_speed_rpm(struct smu_context *smu,
> +				      uint32_t *speed)
> +{
> +	int ret = 0;
> +
> +	if (!speed)
> +		return -EINVAL;
> +
> +	switch (smu_v11_0_get_fan_control_mode(smu)) {
> +	case AMD_FAN_CTRL_AUTO:
> +		ret = arcturus_get_smu_metrics_data(smu,
> +						    METRICS_CURR_FANSPEED,
> +						    speed);
> +		break;
> +	default:
> +		ret = smu_v11_0_get_fan_speed_rpm(smu,
> +						  speed);
> +		break;
> +	}
> +
> +	return ret;
> +}
> +
>   static int arcturus_get_fan_parameters(struct smu_context *smu)
>   {
>   	PPTable_t *pptable = smu->smu_table.driver_pptable;
> @@ -2246,6 +2269,7 @@ static const struct pptable_funcs arcturus_ppt_funcs = {
>   	.force_clk_levels = arcturus_force_clk_levels,
>   	.read_sensor = arcturus_read_sensor,
>   	.get_fan_speed_percent = smu_v11_0_get_fan_speed_percent,
> +	.get_fan_speed_rpm = arcturus_get_fan_speed_rpm,
>   	.get_power_profile_mode = arcturus_get_power_profile_mode,
>   	.set_power_profile_mode = arcturus_set_power_profile_mode,
>   	.set_performance_level = arcturus_set_performance_level,
> diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c
> index 2ddf35788672..7dce5ea7c1a0 100644
> --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c
> +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c
> @@ -1668,6 +1668,29 @@ static bool navi10_is_dpm_running(struct smu_context *smu)
>   	return !!(feature_enabled & SMC_DPM_FEATURE);
>   }
>   
> +static int navi10_get_fan_speed_rpm(struct smu_context *smu,
> +				    uint32_t *speed)
> +{
> +	int ret = 0;
> +
> +	if (!speed)
> +		return -EINVAL;
> +
> +	switch (smu_v11_0_get_fan_control_mode(smu)) {
> +	case AMD_FAN_CTRL_AUTO:
> +		ret = navi10_get_smu_metrics_data(smu,
> +						  METRICS_CURR_FANSPEED,
> +						  speed);
> +		break;
> +	default:
> +		ret = smu_v11_0_get_fan_speed_rpm(smu,
> +						  speed);
> +		break;
> +	}
> +
> +	return ret;
> +}
> +
>   static int navi10_get_fan_parameters(struct smu_context *smu)
>   {
>   	PPTable_t *pptable = smu->smu_table.driver_pptable;
> @@ -3182,6 +3205,7 @@ static const struct pptable_funcs navi10_ppt_funcs = {
>   	.notify_smc_display_config = navi10_notify_smc_display_config,
>   	.is_dpm_running = navi10_is_dpm_running,
>   	.get_fan_speed_percent = smu_v11_0_get_fan_speed_percent,
> +	.get_fan_speed_rpm = navi10_get_fan_speed_rpm,
>   	.get_power_profile_mode = navi10_get_power_profile_mode,
>   	.set_power_profile_mode = navi10_set_power_profile_mode,
>   	.set_watermarks_table = navi10_set_watermarks_table,
> diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c
> index e7686ce6744b..2f93dc4b5968 100644
> --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c
> +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c
> @@ -1355,6 +1355,26 @@ static bool sienna_cichlid_is_dpm_running(struct smu_context *smu)
>   	return !!(feature_enabled & SMC_DPM_FEATURE);
>   }
>   
> +static int sienna_cichlid_get_fan_speed_rpm(struct smu_context *smu,
> +					    uint32_t *speed)
> +{
> +	int ret = 0;
> +
> +	if (!speed)
> +		return -EINVAL;
> +
> +	/*
> +	 * For Sienna_Cichlid and later, the fan speed(rpm) reported
> +	 * by pmfw is always trustable(even when the fan control feature
> +	 * disabled or 0 RPM kicked in).
> +	 */
> +	ret = sienna_cichlid_get_smu_metrics_data(smu,
> +						  METRICS_CURR_FANSPEED,
> +						  speed);
> +
> +	return ret;
> +}
> +
>   static int sienna_cichlid_get_fan_parameters(struct smu_context *smu)
>   {
>   	uint16_t *table_member;
> @@ -3820,6 +3840,7 @@ static const struct pptable_funcs sienna_cichlid_ppt_funcs = {
>   	.notify_smc_display_config = sienna_cichlid_notify_smc_display_config,
>   	.is_dpm_running = sienna_cichlid_is_dpm_running,
>   	.get_fan_speed_percent = smu_v11_0_get_fan_speed_percent,
> +	.get_fan_speed_rpm = sienna_cichlid_get_fan_speed_rpm,
>   	.get_power_profile_mode = sienna_cichlid_get_power_profile_mode,
>   	.set_power_profile_mode = sienna_cichlid_set_power_profile_mode,
>   	.set_watermarks_table = sienna_cichlid_set_watermarks_table,
> diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c
> index c49683b07076..0cdf55a0dba2 100644
> --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c
> +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c
> @@ -1284,6 +1284,34 @@ int smu_v11_0_get_fan_speed_percent(struct smu_context *smu,
>   	return 0;
>   }
>   
> +int smu_v11_0_get_fan_speed_rpm(struct smu_context *smu,
> +				uint32_t *speed)
> +{
> +	struct amdgpu_device *adev = smu->adev;
> +	uint32_t tach_status, crystal_clock_freq;
> +	uint64_t tmp64;
> +
> +	/*
> +	 * For pre Sienna Cichlid ASICs, the 0 RPM may be not correctly
> +	 * detected via register retrieving. To workaround this, we will
> +	 * report the fan speed as 0 RPM if user just requested such.
> +	 */
> +	if ((smu->user_dpm_profile.custom_fan_speed & SMU_CUSTOM_FAN_SPEED_RPM)
> +	     && !smu->user_dpm_profile.fan_speed_rpm) {
> +		*speed = 0;
> +		return 0;
> +	}
> +
> +	crystal_clock_freq = amdgpu_asic_get_xclk(adev) / 4;

Same frequency comment - no need to related to ASIC refclk, define and 
use fan control crystal clock.

Thanks,
Lijo

> +	tmp64 = (uint64_t)crystal_clock_freq * 60 * 10000;
> +
> +	tach_status = RREG32_SOC15(THM, 0, mmCG_TACH_STATUS);
> +	do_div(tmp64, tach_status);
> +	*speed = (uint32_t)tmp64;
> +
> +	return 0;
> +}
> +
>   int
>   smu_v11_0_set_fan_control_mode(struct smu_context *smu,
>   			       uint32_t mode)
> 


More information about the amd-gfx mailing list