Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/amdgpu: implement read_sensor() for pre-powerplay chips

Add the GPU temperature, the shader clock and eventually the
memory clock (as well as the GPU load on CI). The main goal is
to expose this info to the userspace like Radeon.

v2: - add AMDGPU_PP_SENSOR_GPU_LOAD on CI
- update the commit description

Signed-off-by: Samuel Pitoiset <samuel.pitoiset@gmail.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>

authored by

Samuel Pitoiset and committed by
Alex Deucher
d6c29695 75cb00dc

+121 -1
+3 -1
drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h
··· 270 270 struct amdgpu_ps *cps, 271 271 struct amdgpu_ps *rps, 272 272 bool *equal); 273 + int (*read_sensor)(struct amdgpu_device *adev, int idx, void *value, 274 + int *size); 273 275 274 276 struct amd_vce_state* (*get_vce_clock_state)(struct amdgpu_device *adev, unsigned idx); 275 277 int (*reset_power_profile_state)(struct amdgpu_device *adev, ··· 295 293 #define amdgpu_dpm_read_sensor(adev, idx, value, size) \ 296 294 ((adev)->pp_enabled ? \ 297 295 (adev)->powerplay.pp_funcs->read_sensor(adev->powerplay.pp_handle, (idx), (value), (size)) : \ 298 - -EINVAL) 296 + (adev)->pm.funcs->read_sensor((adev), (idx), (value), (size))) 299 297 300 298 #define amdgpu_dpm_get_temperature(adev) \ 301 299 ((adev)->pp_enabled ? \
+43
drivers/gpu/drm/amd/amdgpu/ci_dpm.c
··· 6936 6936 return 0; 6937 6937 } 6938 6938 6939 + static int ci_dpm_read_sensor(struct amdgpu_device *adev, int idx, 6940 + void *value, int *size) 6941 + { 6942 + u32 activity_percent = 50; 6943 + int ret; 6944 + 6945 + /* size must be at least 4 bytes for all sensors */ 6946 + if (*size < 4) 6947 + return -EINVAL; 6948 + 6949 + switch (idx) { 6950 + case AMDGPU_PP_SENSOR_GFX_SCLK: 6951 + *((uint32_t *)value) = ci_get_average_sclk_freq(adev); 6952 + *size = 4; 6953 + return 0; 6954 + case AMDGPU_PP_SENSOR_GFX_MCLK: 6955 + *((uint32_t *)value) = ci_get_average_mclk_freq(adev); 6956 + *size = 4; 6957 + return 0; 6958 + case AMDGPU_PP_SENSOR_GPU_TEMP: 6959 + *((uint32_t *)value) = ci_dpm_get_temp(adev); 6960 + *size = 4; 6961 + return 0; 6962 + case AMDGPU_PP_SENSOR_GPU_LOAD: 6963 + ret = ci_read_smc_soft_register(adev, 6964 + offsetof(SMU7_SoftRegisters, 6965 + AverageGraphicsA), 6966 + &activity_percent); 6967 + if (ret == 0) { 6968 + activity_percent += 0x80; 6969 + activity_percent >>= 8; 6970 + activity_percent = 6971 + activity_percent > 100 ? 100 : activity_percent; 6972 + } 6973 + *((uint32_t *)value) = activity_percent; 6974 + *size = 4; 6975 + return 0; 6976 + default: 6977 + return -EINVAL; 6978 + } 6979 + } 6980 + 6939 6981 const struct amd_ip_funcs ci_dpm_ip_funcs = { 6940 6982 .name = "ci_dpm", 6941 6983 .early_init = ci_dpm_early_init, ··· 7024 6982 .set_power_profile_state = ci_dpm_set_power_profile_state, 7025 6983 .reset_power_profile_state = ci_dpm_reset_power_profile_state, 7026 6984 .switch_power_profile = ci_dpm_switch_power_profile, 6985 + .read_sensor = ci_dpm_read_sensor, 7027 6986 }; 7028 6987 7029 6988 static void ci_dpm_set_dpm_funcs(struct amdgpu_device *adev)
+34
drivers/gpu/drm/amd/amdgpu/kv_dpm.c
··· 3260 3260 return 0; 3261 3261 } 3262 3262 3263 + static int kv_dpm_read_sensor(struct amdgpu_device *adev, int idx, 3264 + void *value, int *size) 3265 + { 3266 + struct kv_power_info *pi = kv_get_pi(adev); 3267 + uint32_t sclk; 3268 + u32 pl_index = 3269 + (RREG32_SMC(ixTARGET_AND_CURRENT_PROFILE_INDEX) & 3270 + TARGET_AND_CURRENT_PROFILE_INDEX__CURR_SCLK_INDEX_MASK) >> 3271 + TARGET_AND_CURRENT_PROFILE_INDEX__CURR_SCLK_INDEX__SHIFT; 3272 + 3273 + /* size must be at least 4 bytes for all sensors */ 3274 + if (*size < 4) 3275 + return -EINVAL; 3276 + 3277 + switch (idx) { 3278 + case AMDGPU_PP_SENSOR_GFX_SCLK: 3279 + if (pl_index < SMU__NUM_SCLK_DPM_STATE) { 3280 + sclk = be32_to_cpu( 3281 + pi->graphics_level[pl_index].SclkFrequency); 3282 + *((uint32_t *)value) = sclk; 3283 + *size = 4; 3284 + return 0; 3285 + } 3286 + return -EINVAL; 3287 + case AMDGPU_PP_SENSOR_GPU_TEMP: 3288 + *((uint32_t *)value) = kv_dpm_get_temp(adev); 3289 + *size = 4; 3290 + return 0; 3291 + default: 3292 + return -EINVAL; 3293 + } 3294 + } 3295 + 3263 3296 const struct amd_ip_funcs kv_dpm_ip_funcs = { 3264 3297 .name = "kv_dpm", 3265 3298 .early_init = kv_dpm_early_init, ··· 3325 3292 .enable_bapm = &kv_dpm_enable_bapm, 3326 3293 .get_vce_clock_state = amdgpu_get_vce_clock_state, 3327 3294 .check_state_equal = kv_check_state_equal, 3295 + .read_sensor = &kv_dpm_read_sensor, 3328 3296 }; 3329 3297 3330 3298 static void kv_dpm_set_dpm_funcs(struct amdgpu_device *adev)
+41
drivers/gpu/drm/amd/amdgpu/si_dpm.c
··· 7982 7982 return 0; 7983 7983 } 7984 7984 7985 + static int si_dpm_read_sensor(struct amdgpu_device *adev, int idx, 7986 + void *value, int *size) 7987 + { 7988 + struct evergreen_power_info *eg_pi = evergreen_get_pi(adev); 7989 + struct amdgpu_ps *rps = &eg_pi->current_rps; 7990 + struct si_ps *ps = si_get_ps(rps); 7991 + uint32_t sclk, mclk; 7992 + u32 pl_index = 7993 + (RREG32(TARGET_AND_CURRENT_PROFILE_INDEX) & CURRENT_STATE_INDEX_MASK) >> 7994 + CURRENT_STATE_INDEX_SHIFT; 7995 + 7996 + /* size must be at least 4 bytes for all sensors */ 7997 + if (*size < 4) 7998 + return -EINVAL; 7999 + 8000 + switch (idx) { 8001 + case AMDGPU_PP_SENSOR_GFX_SCLK: 8002 + if (pl_index < ps->performance_level_count) { 8003 + sclk = ps->performance_levels[pl_index].sclk; 8004 + *((uint32_t *)value) = sclk; 8005 + *size = 4; 8006 + return 0; 8007 + } 8008 + return -EINVAL; 8009 + case AMDGPU_PP_SENSOR_GFX_MCLK: 8010 + if (pl_index < ps->performance_level_count) { 8011 + mclk = ps->performance_levels[pl_index].mclk; 8012 + *((uint32_t *)value) = mclk; 8013 + *size = 4; 8014 + return 0; 8015 + } 8016 + return -EINVAL; 8017 + case AMDGPU_PP_SENSOR_GPU_TEMP: 8018 + *((uint32_t *)value) = si_dpm_get_temp(adev); 8019 + *size = 4; 8020 + return 0; 8021 + default: 8022 + return -EINVAL; 8023 + } 8024 + } 7985 8025 7986 8026 const struct amd_ip_funcs si_dpm_ip_funcs = { 7987 8027 .name = "si_dpm", ··· 8058 8018 .get_fan_speed_percent = &si_dpm_get_fan_speed_percent, 8059 8019 .check_state_equal = &si_check_state_equal, 8060 8020 .get_vce_clock_state = amdgpu_get_vce_clock_state, 8021 + .read_sensor = &si_dpm_read_sensor, 8061 8022 }; 8062 8023 8063 8024 static void si_dpm_set_dpm_funcs(struct amdgpu_device *adev)