[PATCH] drm/amd/powerplay: change smu_read_sensor sequence in smu

Wang, Kevin(Yang) Kevin1.Wang at amd.com
Fri Jul 19 17:03:28 UTC 2019


The read sensor function is not same as other one, this function should be handle many different sensor type,  I don’t want to handle all sensor type in asic file, because some sensor is very simple, only should be send a message to smc, and  some sensor should be parse Table with firmware.

Eg: get gfx clk,
Only need send message to get value.
Because the message already mapped on each asic, so this sensor should be handled in smu_v11.c.

Eg: get gpu load,
this sensor should be get value from firmware table, so should must be handled in xxx_ppt.c

Eg: get pstate clock,
It is full software sensor, so it is handled in amdgpu_smu.c

In this patch, the smu only want to public one api of smu_read_sensor, and the other sensor macro is helper in smu internally.

I want to reduce duplicate code in smu, it will be let bring up new asic easy.

Thanks

> On Jul 20, 2019, at 12:14 AM, Alex Deucher <alexdeucher at gmail.com> wrote:
> 
>> On Fri, Jul 19, 2019 at 12:01 PM Wang, Kevin(Yang) <Kevin1.Wang at amd.com> wrote:
>> 
>> 
>> ________________________________
>> From: Alex Deucher <alexdeucher at gmail.com>
>> Sent: Friday, July 19, 2019 11:17 PM
>> To: Wang, Kevin(Yang) <Kevin1.Wang at amd.com>
>> Cc: amd-gfx at lists.freedesktop.org <amd-gfx at lists.freedesktop.org>; Huang, Ray <Ray.Huang at amd.com>; Feng, Kenneth <Kenneth.Feng at amd.com>
>> Subject: Re: [PATCH] drm/amd/powerplay: change smu_read_sensor sequence in smu
>> 
>>> On Fri, Jul 19, 2019 at 7:23 AM Wang, Kevin(Yang) <Kevin1.Wang at amd.com> wrote:
>>> 
>>> each asic maybe has different read sensor method.
>>> so change read sensor sequence in smu.
>>> 
>>> read sensor sequence:
>>> asic sensor --> smc sensor (smu 11...) --> default_sensor (common)
>> 
>> I think this makes sense.  That said, the current swSMU callback
>> structures are really confusing.  I think we should switch to a single
>> set of per asic callbacks and then add common helpers.  Then for asics
>> where it makes sense we can just use the helper as the callback for
>> all relevant asics.  If they need something asic specific, use the
>> asic specific function.  That should avoid the current mix of
>> callbacks and make it clearer what code gets used when.
>> 
>> Alex
>> 
>> [kevin]:
>> 
>> thanks review, in current code, the read sensor related function is not very clear, so i want to refine them.
>> but I'm not sure which way to write good code logic.
>> 
>> way 1:
>> 
>> provide a puiblic function named smu_read_sensor as public smu api for other kenel module, like this patch.
>> this function will try to get value from asic or smu ip level or common, call them in turn according to the rules.
>> 
>> way 2:
>> 
>> define a maco named smu_read_sensor as public api, implement it in xxx_ppt.c file,
>> if can't handle sensor type in xxx_ppt.c, then call helper in smu_v11_0.c,  then call amdgpu_smu.c helper.
>> 
>> in this way, it means we must implement this callback function in xxx_ppt.c.
>> if need to support new asic, we should add some dulicated code in xxx_ppt.c, if not the smu_read_sensor api is not work well.
>> in smu module, use many macros as module public api, it is impossible to tell at what level these macros implement specific code logic.
>> so i want to refine them.
>> 
>> do you think which way is good for this case?
> 
> I personally prefer way 2.  With way 1, the common functions would
> just be a wrapper around the asic specific callbacks.  The older
> powerplay code worked that way.  If there is something common that
> needs to be done for all asics, I think that would make sense, but I
> don't know that we have any cases like that.  If we do end up needing
> something like that, we can always revisit this.
> 
> I was thinking something like the following:
> 
> struct smu_asic_funcs {
>    int (*get_current_clock_freq)();
>    int (*get_fan_speed_rpm)();
>    ...
> }
> 
> Then for cases where two asics use the same SMU interface, you can
> create a common function.  So for vega20, it might look like:
> 
> static const struct smu_asic_funcs vega20_smu_asic_funcs =
> {
>    .get_current_clock_freq = smu_v11_0_get_current_clock_freq,
>    .get_fan_speed_rpm = vega20_get_fan_speed_rpm,
>    ...
> };
> 
> and navi10 would look like:
> 
> static const struct smu_asic_funcs navi10_smu_asic_funcs =
> {
>    .get_current_clock_freq = smu_v11_0_get_current_clock_freq,
>    .get_fan_speed_rpm = navi10_get_fan_speed_rpm,
>    ...
> };
> 
> Alex
> 
> 
>> thanks.
>> 
>>> 
>>> Signed-off-by: Kevin Wang <kevin1.wang at amd.com>
>>> ---
>>> drivers/gpu/drm/amd/powerplay/amdgpu_smu.c    | 26 +++++++++++++++++--
>>> .../gpu/drm/amd/powerplay/inc/amdgpu_smu.h    |  9 ++++---
>>> drivers/gpu/drm/amd/powerplay/navi10_ppt.c    |  3 +++
>>> drivers/gpu/drm/amd/powerplay/smu_v11_0.c | 10 +++----
>>> drivers/gpu/drm/amd/powerplay/vega20_ppt.c    |  3 +++
>>> 5 files changed, 40 insertions(+), 11 deletions(-)
>>> 
>>> diff --git a/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c b/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c
>>> index 05b91bc5054c..85269f86cae2 100644
>>> --- a/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c
>>> +++ b/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c
>>> @@ -284,11 +284,14 @@ int smu_get_power_num_states(struct smu_context *smu,
>>>        return 0;
>>> }
>>> 
>>> -int smu_common_read_sensor(struct smu_context *smu, enum amd_pp_sensors sensor,
>>> -                          void *data, uint32_t *size)
>>> +int smu_default_read_sensor(struct smu_context *smu, enum amd_pp_sensors sensor,
>>> +                           void *data, uint32_t *size)
>>> {
>>>        int ret = 0;
>>> 
>>> +       if (!data || !size)
>>> +               return -EINVAL;
>>> +
>>>        switch (sensor) {
>>>        case AMDGPU_PP_SENSOR_STABLE_PSTATE_SCLK:
>>>                *((uint32_t *)data) = smu->pstate_sclk;
>>> @@ -321,6 +324,25 @@ int smu_common_read_sensor(struct smu_context *smu, enum amd_pp_sensors sensor,
>>>        return ret;
>>> }
>>> 
>>> +int smu_read_sensor(struct smu_context *smu, enum amd_pp_sensors sensor,
>>> +                   void *data, uint32_t *size)
>>> +{
>>> +       int ret = 0;
>>> +
>>> +       if (!data || !size)
>>> +               return -EINVAL;
>>> +
>>> +       /* handle sensor sequence: asic --> ip level -->  default */
>>> +       ret = smu_asic_read_sensor(smu, sensor, data, size);
>>> +       if (ret) {
>>> +               ret = smu_smc_read_sensor(smu, sensor, data, size);
>>> +               if (ret)
>>> +                       ret = smu_default_read_sensor(smu, sensor, data, size);
>>> +       }
>>> +
>>> +       return ret;
>>> +}
>>> +
>>> int smu_update_table(struct smu_context *smu, enum smu_table_id table_index, int argument,
>>>                     void *table_data, bool drv2smu)
>>> {
>>> diff --git a/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h b/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h
>>> index 34093ddca105..462bae8d62aa 100644
>>> --- a/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h
>>> +++ b/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h
>>> @@ -820,10 +820,10 @@ struct smu_funcs
>>>        ((smu)->ppt_funcs->set_thermal_fan_table ? (smu)->ppt_funcs->set_thermal_fan_table((smu)) : 0)
>>> #define smu_start_thermal_control(smu) \
>>>        ((smu)->funcs->start_thermal_control? (smu)->funcs->start_thermal_control((smu)) : 0)
>>> -#define smu_read_sensor(smu, sensor, data, size) \
>>> -       ((smu)->funcs->read_sensor? (smu)->funcs->read_sensor((smu), (sensor), (data), (size)) : 0)
>>> +#define smu_smc_read_sensor(smu, sensor, data, size) \
>>> +       ((smu)->funcs->read_sensor? (smu)->funcs->read_sensor((smu), (sensor), (data), (size)) : -EINVAL)
>>> #define smu_asic_read_sensor(smu, sensor, data, size) \
>>> -       ((smu)->ppt_funcs->read_sensor? (smu)->ppt_funcs->read_sensor((smu), (sensor), (data), (size)) : 0)
>>> +       ((smu)->ppt_funcs->read_sensor? (smu)->ppt_funcs->read_sensor((smu), (sensor), (data), (size)) : -EINVAL)
>>> #define smu_get_power_profile_mode(smu, buf) \
>>>        ((smu)->ppt_funcs->get_power_profile_mode ? (smu)->ppt_funcs->get_power_profile_mode((smu), buf) : 0)
>>> #define smu_set_power_profile_mode(smu, param, param_size) \
>>> @@ -989,5 +989,6 @@ enum amd_dpm_forced_level smu_get_performance_level(struct smu_context *smu);
>>> int smu_force_performance_level(struct smu_context *smu, enum amd_dpm_forced_level level);
>>> int smu_set_display_count(struct smu_context *smu, uint32_t count);
>>> bool smu_clk_dpm_is_enabled(struct smu_context *smu, enum smu_clk_type clk_type);
>>> -
>>> +int smu_read_sensor(struct smu_context *smu, enum amd_pp_sensors sensor,
>>> +                   void *data, uint32_t *size);
>>> #endif
>>> diff --git a/drivers/gpu/drm/amd/powerplay/navi10_ppt.c b/drivers/gpu/drm/amd/powerplay/navi10_ppt.c
>>> index 46e2913e4af4..0a53695785b6 100644
>>> --- a/drivers/gpu/drm/amd/powerplay/navi10_ppt.c
>>> +++ b/drivers/gpu/drm/amd/powerplay/navi10_ppt.c
>>> @@ -1365,6 +1365,9 @@ static int navi10_read_sensor(struct smu_context *smu,
>>>        struct smu_table_context *table_context = &smu->smu_table;
>>>        PPTable_t *pptable = table_context->driver_pptable;
>>> 
>>> +       if (!data || !size)
>>> +               return -EINVAL;
>>> +
>>>        switch (sensor) {
>>>        case AMDGPU_PP_SENSOR_MAX_FAN_RPM:
>>>                *(uint32_t *)data = pptable->FanMaximumRpm;
>>> diff --git a/drivers/gpu/drm/amd/powerplay/smu_v11_0.c b/drivers/gpu/drm/amd/powerplay/smu_v11_0.c
>>> index 76bc157525d0..2679b6ff6ca3 100644
>>> --- a/drivers/gpu/drm/amd/powerplay/smu_v11_0.c
>>> +++ b/drivers/gpu/drm/amd/powerplay/smu_v11_0.c
>>> @@ -1267,6 +1267,10 @@ static int smu_v11_0_read_sensor(struct smu_context *smu,
>>>                                 void *data, uint32_t *size)
>>> {
>>>        int ret = 0;
>>> +
>>> +       if (!data || !size)
>>> +               return -EINVAL;
>>> +
>>>        switch (sensor) {
>>>        case AMDGPU_PP_SENSOR_GFX_MCLK:
>>>                ret = smu_get_current_clk_freq(smu, SMU_UCLK, (uint32_t *)data);
>>> @@ -1285,14 +1289,10 @@ static int smu_v11_0_read_sensor(struct smu_context *smu,
>>>                *size = 4;
>>>                break;
>>>        default:
>>> -               ret = smu_common_read_sensor(smu, sensor, data, size);
>>> +               ret = -EINVAL;
>>>                break;
>>>        }
>>> 
>>> -       /* try get sensor data by asic */
>>> -       if (ret)
>>> -               ret = smu_asic_read_sensor(smu, sensor, data, size);
>>> -
>>>        if (ret)
>>>                *size = 0;
>>> 
>>> diff --git a/drivers/gpu/drm/amd/powerplay/vega20_ppt.c b/drivers/gpu/drm/amd/powerplay/vega20_ppt.c
>>> index bcd0efaf7bbd..b44ec7c670c5 100644
>>> --- a/drivers/gpu/drm/amd/powerplay/vega20_ppt.c
>>> +++ b/drivers/gpu/drm/amd/powerplay/vega20_ppt.c
>>> @@ -3146,6 +3146,9 @@ static int vega20_read_sensor(struct smu_context *smu,
>>>        struct smu_table_context *table_context = &smu->smu_table;
>>>        PPTable_t *pptable = table_context->driver_pptable;
>>> 
>>> +       if (!data || !size)
>>> +               return -EINVAL;
>>> +
>>>        switch (sensor) {
>>>        case AMDGPU_PP_SENSOR_MAX_FAN_RPM:
>>>                *(uint32_t *)data = pptable->FanMaximumRpm;
>>> --
>>> 2.22.0
>>> 
>>> _______________________________________________
>>> 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