Hi Samuel, It would be helpful to modify amdgpu_debugfs_sensor_read() to support dpm based sensors as well. This will let me add it to umr. If you can swing that in here that would be helpful if not I can submit my own patch when this lands. Cheers, Tom On 02/13/2017 05:01 PM, Samuel Pitoiset wrote: > Currently, only the GPU temperature, the shader clock and > eventually the memory clock are implemented. The main goal > is to expose this info to the userspace like Radeon. > > Signed-off-by: Samuel Pitoiset <samuel.pitoiset at gmail.com> > --- > drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h | 4 +++- > drivers/gpu/drm/amd/amdgpu/ci_dpm.c | 26 +++++++++++++++++++++ > drivers/gpu/drm/amd/amdgpu/kv_dpm.c | 34 +++++++++++++++++++++++++++ > drivers/gpu/drm/amd/amdgpu/si_dpm.c | 41 +++++++++++++++++++++++++++++++++ > 4 files changed, 104 insertions(+), 1 deletion(-) > > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h > index 98698dcf15c7..f1876808ff58 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 { > struct amdgpu_ps *cps, > struct amdgpu_ps *rps, > bool *equal); > + int (*read_sensor)(struct amdgpu_device *adev, int idx, void *value, > + int *size); > > struct amd_vce_state* (*get_vce_clock_state)(struct amdgpu_device *adev, unsigned idx); > int (*reset_power_profile_state)(struct amdgpu_device *adev, > @@ -293,7 +295,7 @@ struct amdgpu_dpm_funcs { > #define amdgpu_dpm_read_sensor(adev, idx, value, size) \ > ((adev)->pp_enabled ? \ > (adev)->powerplay.pp_funcs->read_sensor(adev->powerplay.pp_handle, (idx), (value), (size)) : \ > - -EINVAL) > + (adev)->pm.funcs->read_sensor((adev), (idx), (value), (size))) > > #define amdgpu_dpm_get_temperature(adev) \ > ((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..e3a06d6d9e99 100644 > --- a/drivers/gpu/drm/amd/amdgpu/ci_dpm.c > +++ b/drivers/gpu/drm/amd/amdgpu/ci_dpm.c > @@ -6936,6 +6936,31 @@ static int ci_dpm_switch_power_profile(struct amdgpu_device *adev, > return 0; > } > > +static int ci_dpm_read_sensor(struct amdgpu_device *adev, int idx, > + void *value, int *size) > +{ > + /* size must be at least 4 bytes for all sensors */ > + if (*size < 4) > + return -EINVAL; > + > + switch (idx) { > + case AMDGPU_PP_SENSOR_GFX_SCLK: > + *((uint32_t *)value) = ci_get_average_sclk_freq(adev); > + *size = 4; > + return 0; > + case AMDGPU_PP_SENSOR_GFX_MCLK: > + *((uint32_t *)value) = ci_get_average_mclk_freq(adev); > + *size = 4; > + return 0; > + case AMDGPU_PP_SENSOR_GPU_TEMP: > + *((uint32_t *)value) = ci_dpm_get_temp(adev); > + *size = 4; > + return 0; > + default: > + return -EINVAL; > + } > +} > + > const struct amd_ip_funcs ci_dpm_ip_funcs = { > .name = "ci_dpm", > .early_init = ci_dpm_early_init, > @@ -6982,6 +7007,7 @@ static const struct amdgpu_dpm_funcs ci_dpm_funcs = { > .set_power_profile_state = ci_dpm_set_power_profile_state, > .reset_power_profile_state = ci_dpm_reset_power_profile_state, > .switch_power_profile = ci_dpm_switch_power_profile, > + .read_sensor = ci_dpm_read_sensor, > }; > > static 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, > return 0; > } > > +static int kv_dpm_read_sensor(struct amdgpu_device *adev, int idx, > + void *value, int *size) > +{ > + struct kv_power_info *pi = kv_get_pi(adev); > + uint32_t sclk; > + u32 pl_index = > + (RREG32_SMC(ixTARGET_AND_CURRENT_PROFILE_INDEX) & > + TARGET_AND_CURRENT_PROFILE_INDEX__CURR_SCLK_INDEX_MASK) >> > + TARGET_AND_CURRENT_PROFILE_INDEX__CURR_SCLK_INDEX__SHIFT; > + > + /* size must be at least 4 bytes for all sensors */ > + if (*size < 4) > + return -EINVAL; > + > + switch (idx) { > + case AMDGPU_PP_SENSOR_GFX_SCLK: > + if (pl_index < SMU__NUM_SCLK_DPM_STATE) { > + sclk = be32_to_cpu( > + pi->graphics_level[pl_index].SclkFrequency); > + *((uint32_t *)value) = sclk; > + *size = 4; > + return 0; > + } > + return -EINVAL; > + case AMDGPU_PP_SENSOR_GPU_TEMP: > + *((uint32_t *)value) = kv_dpm_get_temp(adev); > + *size = 4; > + return 0; > + default: > + return -EINVAL; > + } > +} > + > const struct amd_ip_funcs kv_dpm_ip_funcs = { > .name = "kv_dpm", > .early_init = kv_dpm_early_init, > @@ -3292,6 +3325,7 @@ static const struct amdgpu_dpm_funcs kv_dpm_funcs = { > .enable_bapm = &kv_dpm_enable_bapm, > .get_vce_clock_state = amdgpu_get_vce_clock_state, > .check_state_equal = kv_check_state_equal, > + .read_sensor = &kv_dpm_read_sensor, > }; > > static 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 f55e45b52fbc..ded6b9b7153e 100644 > --- a/drivers/gpu/drm/amd/amdgpu/si_dpm.c > +++ b/drivers/gpu/drm/amd/amdgpu/si_dpm.c > @@ -7972,6 +7972,46 @@ static int si_check_state_equal(struct amdgpu_device *adev, > return 0; > } > > +static int si_dpm_read_sensor(struct amdgpu_device *adev, int idx, > + void *value, int *size) > +{ > + struct evergreen_power_info *eg_pi = evergreen_get_pi(adev); > + struct amdgpu_ps *rps = &eg_pi->current_rps; > + struct si_ps *ps = si_get_ps(rps); > + uint32_t sclk, mclk; > + u32 pl_index = > + (RREG32(TARGET_AND_CURRENT_PROFILE_INDEX) & CURRENT_STATE_INDEX_MASK) >> > + CURRENT_STATE_INDEX_SHIFT; > + > + /* size must be at least 4 bytes for all sensors */ > + if (*size < 4) > + return -EINVAL; > + > + switch (idx) { > + case AMDGPU_PP_SENSOR_GFX_SCLK: > + if (pl_index < ps->performance_level_count) { > + sclk = ps->performance_levels[pl_index].sclk; > + *((uint32_t *)value) = sclk; > + *size = 4; > + return 0; > + } > + return -EINVAL; > + case AMDGPU_PP_SENSOR_GFX_MCLK: > + if (pl_index < ps->performance_level_count) { > + mclk = ps->performance_levels[pl_index].mclk; > + *((uint32_t *)value) = mclk; > + *size = 4; > + return 0; > + } > + return -EINVAL; > + case AMDGPU_PP_SENSOR_GPU_TEMP: > + *((uint32_t *)value) = si_dpm_get_temp(adev); > + *size = 4; > + return 0; > + default: > + return -EINVAL; > + } > +} > > const struct amd_ip_funcs si_dpm_ip_funcs = { > .name = "si_dpm", > @@ -8008,6 +8048,7 @@ static const struct amdgpu_dpm_funcs si_dpm_funcs = { > .get_fan_speed_percent = &si_dpm_get_fan_speed_percent, > .check_state_equal = &si_check_state_equal, > .get_vce_clock_state = amdgpu_get_vce_clock_state, > + .read_sensor = &si_dpm_read_sensor, > }; > > static void si_dpm_set_dpm_funcs(struct amdgpu_device *adev) >