aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSamuel Pitoiset <samuel.pitoiset@gmail.com>2017-02-13 19:00:49 -0500
committerAlex Deucher <alexander.deucher@amd.com>2017-03-29 23:53:03 -0400
commitd6c29695e68ca911648dbe2294764dab6ef84fc7 (patch)
treeb14a6d711a6e8065e64b31599fdada9668163cee
parent75cb00dc0c9dbe5e7a971ac729384d8d05f0deb1 (diff)
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>
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h4
-rw-r--r--drivers/gpu/drm/amd/amdgpu/ci_dpm.c43
-rw-r--r--drivers/gpu/drm/amd/amdgpu/kv_dpm.c34
-rw-r--r--drivers/gpu/drm/amd/amdgpu/si_dpm.c41
4 files changed, 121 insertions, 1 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h
index 5dd9daae9eef..8c96a4caa715 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h
@@ -270,6 +270,8 @@ struct amdgpu_dpm_funcs {
270 struct amdgpu_ps *cps, 270 struct amdgpu_ps *cps,
271 struct amdgpu_ps *rps, 271 struct amdgpu_ps *rps,
272 bool *equal); 272 bool *equal);
273 int (*read_sensor)(struct amdgpu_device *adev, int idx, void *value,
274 int *size);
273 275
274 struct amd_vce_state* (*get_vce_clock_state)(struct amdgpu_device *adev, unsigned idx); 276 struct amd_vce_state* (*get_vce_clock_state)(struct amdgpu_device *adev, unsigned idx);
275 int (*reset_power_profile_state)(struct amdgpu_device *adev, 277 int (*reset_power_profile_state)(struct amdgpu_device *adev,
@@ -293,7 +295,7 @@ struct amdgpu_dpm_funcs {
293#define amdgpu_dpm_read_sensor(adev, idx, value, size) \ 295#define amdgpu_dpm_read_sensor(adev, idx, value, size) \
294 ((adev)->pp_enabled ? \ 296 ((adev)->pp_enabled ? \
295 (adev)->powerplay.pp_funcs->read_sensor(adev->powerplay.pp_handle, (idx), (value), (size)) : \ 297 (adev)->powerplay.pp_funcs->read_sensor(adev->powerplay.pp_handle, (idx), (value), (size)) : \
296 -EINVAL) 298 (adev)->pm.funcs->read_sensor((adev), (idx), (value), (size)))
297 299
298#define amdgpu_dpm_get_temperature(adev) \ 300#define amdgpu_dpm_get_temperature(adev) \
299 ((adev)->pp_enabled ? \ 301 ((adev)->pp_enabled ? \
diff --git a/drivers/gpu/drm/amd/amdgpu/ci_dpm.c b/drivers/gpu/drm/amd/amdgpu/ci_dpm.c
index 578878d1d4c0..b00e81db522d 100644
--- a/drivers/gpu/drm/amd/amdgpu/ci_dpm.c
+++ b/drivers/gpu/drm/amd/amdgpu/ci_dpm.c
@@ -6936,6 +6936,48 @@ static int ci_dpm_switch_power_profile(struct amdgpu_device *adev,
6936 return 0; 6936 return 0;
6937} 6937}
6938 6938
6939static 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
6939const struct amd_ip_funcs ci_dpm_ip_funcs = { 6981const struct amd_ip_funcs ci_dpm_ip_funcs = {
6940 .name = "ci_dpm", 6982 .name = "ci_dpm",
6941 .early_init = ci_dpm_early_init, 6983 .early_init = ci_dpm_early_init,
@@ -6982,6 +7024,7 @@ static const struct amdgpu_dpm_funcs ci_dpm_funcs = {
6982 .set_power_profile_state = ci_dpm_set_power_profile_state, 7024 .set_power_profile_state = ci_dpm_set_power_profile_state,
6983 .reset_power_profile_state = ci_dpm_reset_power_profile_state, 7025 .reset_power_profile_state = ci_dpm_reset_power_profile_state,
6984 .switch_power_profile = ci_dpm_switch_power_profile, 7026 .switch_power_profile = ci_dpm_switch_power_profile,
7027 .read_sensor = ci_dpm_read_sensor,
6985}; 7028};
6986 7029
6987static void ci_dpm_set_dpm_funcs(struct amdgpu_device *adev) 7030static void ci_dpm_set_dpm_funcs(struct amdgpu_device *adev)
diff --git a/drivers/gpu/drm/amd/amdgpu/kv_dpm.c b/drivers/gpu/drm/amd/amdgpu/kv_dpm.c
index f5a343cb0010..13f323745729 100644
--- a/drivers/gpu/drm/amd/amdgpu/kv_dpm.c
+++ b/drivers/gpu/drm/amd/amdgpu/kv_dpm.c
@@ -3260,6 +3260,39 @@ static int kv_check_state_equal(struct amdgpu_device *adev,
3260 return 0; 3260 return 0;
3261} 3261}
3262 3262
3263static 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
3263const struct amd_ip_funcs kv_dpm_ip_funcs = { 3296const struct amd_ip_funcs kv_dpm_ip_funcs = {
3264 .name = "kv_dpm", 3297 .name = "kv_dpm",
3265 .early_init = kv_dpm_early_init, 3298 .early_init = kv_dpm_early_init,
@@ -3292,6 +3325,7 @@ static const struct amdgpu_dpm_funcs kv_dpm_funcs = {
3292 .enable_bapm = &kv_dpm_enable_bapm, 3325 .enable_bapm = &kv_dpm_enable_bapm,
3293 .get_vce_clock_state = amdgpu_get_vce_clock_state, 3326 .get_vce_clock_state = amdgpu_get_vce_clock_state,
3294 .check_state_equal = kv_check_state_equal, 3327 .check_state_equal = kv_check_state_equal,
3328 .read_sensor = &kv_dpm_read_sensor,
3295}; 3329};
3296 3330
3297static void kv_dpm_set_dpm_funcs(struct amdgpu_device *adev) 3331static void kv_dpm_set_dpm_funcs(struct amdgpu_device *adev)
diff --git a/drivers/gpu/drm/amd/amdgpu/si_dpm.c b/drivers/gpu/drm/amd/amdgpu/si_dpm.c
index c5dec210d529..eb84c2a6d951 100644
--- a/drivers/gpu/drm/amd/amdgpu/si_dpm.c
+++ b/drivers/gpu/drm/amd/amdgpu/si_dpm.c
@@ -7982,6 +7982,46 @@ static int si_check_state_equal(struct amdgpu_device *adev,
7982 return 0; 7982 return 0;
7983} 7983}
7984 7984
7985static 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
7986const struct amd_ip_funcs si_dpm_ip_funcs = { 8026const struct amd_ip_funcs si_dpm_ip_funcs = {
7987 .name = "si_dpm", 8027 .name = "si_dpm",
@@ -8018,6 +8058,7 @@ static const struct amdgpu_dpm_funcs si_dpm_funcs = {
8018 .get_fan_speed_percent = &si_dpm_get_fan_speed_percent, 8058 .get_fan_speed_percent = &si_dpm_get_fan_speed_percent,
8019 .check_state_equal = &si_check_state_equal, 8059 .check_state_equal = &si_check_state_equal,
8020 .get_vce_clock_state = amdgpu_get_vce_clock_state, 8060 .get_vce_clock_state = amdgpu_get_vce_clock_state,
8061 .read_sensor = &si_dpm_read_sensor,
8021}; 8062};
8022 8063
8023static void si_dpm_set_dpm_funcs(struct amdgpu_device *adev) 8064static void si_dpm_set_dpm_funcs(struct amdgpu_device *adev)