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

Samuel Pitoiset samuel.pitoiset at gmail.com
Tue Feb 14 00:13:49 UTC 2017



On 02/14/2017 12:46 AM, Tom St Denis wrote:
> On 02/13/2017 06:40 PM, Samuel Pitoiset wrote:
>>
>>
>> On 02/14/2017 12:17 AM, Tom St Denis wrote:
>>> Hi Samuel,
>>
>> Hi Tom,
>>
>>
>>>
>>> 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.
>>
>> You mean removing the sanity check (for powerplay boards)? I can do that
>> in a follow-up patch yes.
>
> As long as the path to or the pointer for read_sensor is not null.
>
> It's been a while since I looked at the pm code but I wonder if a sanity
> check is still required even if you use the macro to read the sensor.

Ah yeah, not the function I was thinking of but should be pretty simple 
I think.

>
> Tom
>
>
>>
>>>
>>> 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)
>>>>
>>>
>>> _______________________________________________
>>> amd-gfx mailing list
>>> amd-gfx at lists.freedesktop.org
>>> https://lists.freedesktop.org/mailman/listinfo/amd-gfx
>


More information about the amd-gfx mailing list