[PATCH 1/2] drm/amdgpu: implement read_sensor() for pre-powerplay chips

Tom St Denis tom.stdenis at amd.com
Mon Feb 13 23:17:24 UTC 2017


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)
>



More information about the amd-gfx mailing list