[PATCH] drm/amd/pm: Fix that RPM cannot be obtained for specific GPU
huangyizhi
huangyizhi at hnu.edu.cn
Tue Sep 28 00:49:41 UTC 2021
The current mechanism for obtaining RPM is to read tach_period from
the register, and then calculate the RPM together with the frequency.
But we found that on specific GPUs, such as RX 550 and RX 560D,
tach_period always reads as 0 and smu7_fan_ctrl_get_fan_speed_rpm
will returns -EINVAL.
To solve this problem, when reading tach_period as 0, we try
to estimate the current RPM using the percentage of current pwm, the
maximum and minimum RPM.
Signed-off-by: huangyizhi <huangyizhi at hnu.edu.cn>
---
.../drm/amd/pm/powerplay/hwmgr/smu7_thermal.c | 28 ++++++++++++++++---
1 file changed, 24 insertions(+), 4 deletions(-)
diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_thermal.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_thermal.c
index a6c3610db23e..307dd87d6882 100644
--- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_thermal.c
+++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_thermal.c
@@ -81,6 +81,11 @@ int smu7_fan_ctrl_get_fan_speed_rpm(struct pp_hwmgr *hwmgr, uint32_t *speed)
{
uint32_t tach_period;
uint32_t crystal_clock_freq;
+ uint32_t duty100;
+ uint32_t duty;
+ uint32_t speed_percent;
+ uint64_t tmp64;
+
if (hwmgr->thermal_controller.fanInfo.bNoFan ||
!hwmgr->thermal_controller.fanInfo.ucTachometerPulsesPerRevolution)
@@ -89,13 +94,28 @@ int smu7_fan_ctrl_get_fan_speed_rpm(struct pp_hwmgr *hwmgr, uint32_t *speed)
tach_period = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
CG_TACH_STATUS, TACH_PERIOD);
- if (tach_period == 0)
- return -EINVAL;
+ if (tach_period == 0) {
- crystal_clock_freq = amdgpu_asic_get_xclk((struct amdgpu_device *)hwmgr->adev);
+ duty100 = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
+ CG_FDO_CTRL1, FMAX_DUTY100);
+ duty = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
+ CG_THERMAL_STATUS, FDO_PWM_DUTY);
- *speed = 60 * crystal_clock_freq * 10000 / tach_period;
+ if (duty100 == 0)
+ return -EINVAL;
+ tmp64 = (uint64_t)duty * 100;
+ do_div(tmp64, duty100);
+ speed_percent = MIN((uint32_t)tmp64, 100);
+
+ *speed = speed_percent * (hwmgr->thermal_controller.fanInfo.ulMaxRPM
+ - hwmgr->thermal_controller.fanInfo.ulMinRPM) / 100;
+ } else {
+
+ crystal_clock_freq = amdgpu_asic_get_xclk((struct amdgpu_device *)hwmgr->adev);
+
+ *speed = 60 * crystal_clock_freq * 10000 / tach_period;
+ }
return 0;
}
--
2.30.0
More information about the amd-gfx
mailing list