From: Evan Quan <evan.q...@amd.com>

The power limit retrieval should be done per asic. Since we may
need to lookup in the pptable and that's really asic specific.

Signed-off-by: Evan Quan <evan.q...@amd.com>
Reviewed-by: Kenneth Feng <kenneth.f...@amd.com>
Signed-off-by: Alex Deucher <alexander.deuc...@amd.com>
---
 drivers/gpu/drm/amd/powerplay/amdgpu_smu.c    |  2 +-
 drivers/gpu/drm/amd/powerplay/arcturus_ppt.c  | 51 +++++++++++++++++
 .../gpu/drm/amd/powerplay/inc/amdgpu_smu.h    |  4 +-
 drivers/gpu/drm/amd/powerplay/navi10_ppt.c    | 51 +++++++++++++++++
 drivers/gpu/drm/amd/powerplay/smu_v11_0.c     | 55 ++++---------------
 5 files changed, 116 insertions(+), 47 deletions(-)

diff --git a/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c 
b/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c
index 3f615d4624c7..330cc3258e61 100644
--- a/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c
+++ b/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c
@@ -1136,7 +1136,7 @@ static int smu_smc_table_hw_init(struct smu_context *smu,
                if (ret)
                        return ret;
 
-               ret = smu_get_power_limit(smu, &smu->default_power_limit, 
false);
+               ret = smu_get_power_limit(smu, &smu->default_power_limit, true);
                if (ret)
                        return ret;
        }
diff --git a/drivers/gpu/drm/amd/powerplay/arcturus_ppt.c 
b/drivers/gpu/drm/amd/powerplay/arcturus_ppt.c
index c67a9914ce7b..9360f5a25b69 100644
--- a/drivers/gpu/drm/amd/powerplay/arcturus_ppt.c
+++ b/drivers/gpu/drm/amd/powerplay/arcturus_ppt.c
@@ -1323,6 +1323,56 @@ arcturus_get_profiling_clk_mask(struct smu_context *smu,
        return 0;
 }
 
+static int arcturus_get_power_limit(struct smu_context *smu,
+                                    uint32_t *limit,
+                                    bool asic_default)
+{
+       PPTable_t *pptable = smu->smu_table.driver_pptable;
+       uint32_t asic_default_power_limit;
+       int ret = 0;
+       int power_src;
+
+       if (!smu->default_power_limit ||
+           !smu->power_limit) {
+               if (smu_feature_is_enabled(smu, SMU_FEATURE_PPT_BIT)) {
+                       power_src = smu_power_get_index(smu, 
SMU_POWER_SOURCE_AC);
+                       if (power_src < 0)
+                               return -EINVAL;
+
+                       ret = smu_send_smc_msg_with_param(smu, 
SMU_MSG_GetPptLimit,
+                               power_src << 16);
+                       if (ret) {
+                               pr_err("[%s] get PPT limit failed!", __func__);
+                               return ret;
+                       }
+                       smu_read_smc_arg(smu, &asic_default_power_limit);
+               } else {
+                       /* the last hope to figure out the ppt limit */
+                       if (!pptable) {
+                               pr_err("Cannot get PPT limit due to pptable 
missing!");
+                               return -EINVAL;
+                       }
+                       asic_default_power_limit =
+                               pptable->SocketPowerLimitAc[PPT_THROTTLER_PPT0];
+               }
+
+               if (smu->od_enabled) {
+                       asic_default_power_limit *= (100 + 
smu->smu_table.TDPODLimit);
+                       asic_default_power_limit /= 100;
+               }
+
+               smu->default_power_limit = asic_default_power_limit;
+               smu->power_limit = asic_default_power_limit;
+       }
+
+       if (asic_default)
+               *limit = smu->default_power_limit;
+       else
+               *limit = smu->power_limit;
+
+       return 0;
+}
+
 static void arcturus_dump_pptable(struct smu_context *smu)
 {
        struct smu_table_context *table_context = &smu->smu_table;
@@ -1788,6 +1838,7 @@ static const struct pptable_funcs arcturus_ppt_funcs = {
        .get_profiling_clk_mask = arcturus_get_profiling_clk_mask,
        /* debug (internal used) */
        .dump_pptable = arcturus_dump_pptable,
+       .get_power_limit = arcturus_get_power_limit,
 };
 
 void arcturus_set_ppt_funcs(struct smu_context *smu)
diff --git a/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h 
b/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h
index 519aeac706a5..093e70fe684d 100644
--- a/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h
+++ b/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h
@@ -447,6 +447,7 @@ struct pptable_funcs {
        int (*set_default_od_settings)(struct smu_context *smu, bool 
initialize);
        int (*set_performance_level)(struct smu_context *smu, enum 
amd_dpm_forced_level level);
        void (*dump_pptable)(struct smu_context *smu);
+       int (*get_power_limit)(struct smu_context *smu, uint32_t *limit, bool 
asic_default);
 };
 
 struct smu_funcs
@@ -479,7 +480,6 @@ struct smu_funcs
        int (*set_allowed_mask)(struct smu_context *smu);
        int (*get_enabled_mask)(struct smu_context *smu, uint32_t 
*feature_mask, uint32_t num);
        int (*notify_display_change)(struct smu_context *smu);
-       int (*get_power_limit)(struct smu_context *smu, uint32_t *limit, bool 
def);
        int (*set_power_limit)(struct smu_context *smu, uint32_t n);
        int (*get_current_clk_freq)(struct smu_context *smu, enum smu_clk_type 
clk_id, uint32_t *value);
        int (*init_max_sustainable_clocks)(struct smu_context *smu);
@@ -608,7 +608,7 @@ struct smu_funcs
 #define smu_set_default_od8_settings(smu) \
        ((smu)->ppt_funcs->set_default_od8_settings ? 
(smu)->ppt_funcs->set_default_od8_settings((smu)) : 0)
 #define smu_get_power_limit(smu, limit, def) \
-       ((smu)->funcs->get_power_limit ? (smu)->funcs->get_power_limit((smu), 
(limit), (def)) : 0)
+       ((smu)->ppt_funcs->get_power_limit ? 
(smu)->ppt_funcs->get_power_limit((smu), (limit), (def)) : 0)
 #define smu_set_power_limit(smu, limit) \
        ((smu)->funcs->set_power_limit ? (smu)->funcs->set_power_limit((smu), 
(limit)) : 0)
 #define smu_get_current_clk_freq(smu, clk_id, value) \
diff --git a/drivers/gpu/drm/amd/powerplay/navi10_ppt.c 
b/drivers/gpu/drm/amd/powerplay/navi10_ppt.c
index 01d534c8442e..efcedeb8d883 100644
--- a/drivers/gpu/drm/amd/powerplay/navi10_ppt.c
+++ b/drivers/gpu/drm/amd/powerplay/navi10_ppt.c
@@ -1484,6 +1484,56 @@ static int navi10_get_thermal_temperature_range(struct 
smu_context *smu,
        return 0;
 }
 
+static int navi10_get_power_limit(struct smu_context *smu,
+                                    uint32_t *limit,
+                                    bool asic_default)
+{
+       PPTable_t *pptable = smu->smu_table.driver_pptable;
+       uint32_t asic_default_power_limit;
+       int ret = 0;
+       int power_src;
+
+       if (!smu->default_power_limit ||
+           !smu->power_limit) {
+               if (smu_feature_is_enabled(smu, SMU_FEATURE_PPT_BIT)) {
+                       power_src = smu_power_get_index(smu, 
SMU_POWER_SOURCE_AC);
+                       if (power_src < 0)
+                               return -EINVAL;
+
+                       ret = smu_send_smc_msg_with_param(smu, 
SMU_MSG_GetPptLimit,
+                               power_src << 16);
+                       if (ret) {
+                               pr_err("[%s] get PPT limit failed!", __func__);
+                               return ret;
+                       }
+                       smu_read_smc_arg(smu, &asic_default_power_limit);
+               } else {
+                       /* the last hope to figure out the ppt limit */
+                       if (!pptable) {
+                               pr_err("Cannot get PPT limit due to pptable 
missing!");
+                               return -EINVAL;
+                       }
+                       asic_default_power_limit =
+                               pptable->SocketPowerLimitAc[PPT_THROTTLER_PPT0];
+               }
+
+               if (smu->od_enabled) {
+                       asic_default_power_limit *= (100 + 
smu->smu_table.TDPODLimit);
+                       asic_default_power_limit /= 100;
+               }
+
+               smu->default_power_limit = asic_default_power_limit;
+               smu->power_limit = asic_default_power_limit;
+       }
+
+       if (asic_default)
+               *limit = smu->default_power_limit;
+       else
+               *limit = smu->power_limit;
+
+       return 0;
+}
+
 static const struct pptable_funcs navi10_ppt_funcs = {
        .tables_init = navi10_tables_init,
        .alloc_dpm_context = navi10_allocate_dpm_context,
@@ -1520,6 +1570,7 @@ static const struct pptable_funcs navi10_ppt_funcs = {
        .get_uclk_dpm_states = navi10_get_uclk_dpm_states,
        .set_performance_level = navi10_set_performance_level,
        .get_thermal_temperature_range = navi10_get_thermal_temperature_range,
+       .get_power_limit = navi10_get_power_limit,
 };
 
 void navi10_set_ppt_funcs(struct smu_context *smu)
diff --git a/drivers/gpu/drm/amd/powerplay/smu_v11_0.c 
b/drivers/gpu/drm/amd/powerplay/smu_v11_0.c
index caf02ea4a481..7f03ca401d97 100644
--- a/drivers/gpu/drm/amd/powerplay/smu_v11_0.c
+++ b/drivers/gpu/drm/amd/powerplay/smu_v11_0.c
@@ -1012,64 +1012,32 @@ static int smu_v11_0_init_max_sustainable_clocks(struct 
smu_context *smu)
        return 0;
 }
 
-static int smu_v11_0_get_power_limit(struct smu_context *smu,
-                                    uint32_t *limit,
-                                    bool get_default)
+static int smu_v11_0_set_power_limit(struct smu_context *smu, uint32_t n)
 {
        int ret = 0;
-       int power_src;
 
-       power_src = smu_power_get_index(smu, SMU_POWER_SOURCE_AC);
-       if (power_src < 0)
+       if (n > smu->default_power_limit) {
+               pr_err("New power limit is over the max allowed %d\n",
+                               smu->default_power_limit);
                return -EINVAL;
-
-       if (get_default) {
-               mutex_lock(&smu->mutex);
-               *limit = smu->default_power_limit;
-               if (smu->od_enabled) {
-                       *limit *= (100 + smu->smu_table.TDPODLimit);
-                       *limit /= 100;
-               }
-               mutex_unlock(&smu->mutex);
-       } else {
-               ret = smu_send_smc_msg_with_param(smu, SMU_MSG_GetPptLimit,
-                       power_src << 16);
-               if (ret) {
-                       pr_err("[%s] get PPT limit failed!", __func__);
-                       return ret;
-               }
-               smu_read_smc_arg(smu, limit);
-               smu->power_limit = *limit;
        }
 
-       return ret;
-}
-
-static int smu_v11_0_set_power_limit(struct smu_context *smu, uint32_t n)
-{
-       uint32_t max_power_limit;
-       int ret = 0;
-
        if (n == 0)
                n = smu->default_power_limit;
 
-       max_power_limit = smu->default_power_limit;
-
-       if (smu->od_enabled) {
-               max_power_limit *= (100 + smu->smu_table.TDPODLimit);
-               max_power_limit /= 100;
+       if (!smu_feature_is_enabled(smu, SMU_FEATURE_PPT_BIT)) {
+               pr_err("Setting new power limit is not supported!\n");
+               return -EOPNOTSUPP;
        }
-       if (n > max_power_limit)
-               return -EINVAL;
 
-       if (smu_feature_is_enabled(smu, SMU_FEATURE_PPT_BIT))
-               ret = smu_send_smc_msg_with_param(smu, SMU_MSG_SetPptLimit, n);
+       ret = smu_send_smc_msg_with_param(smu, SMU_MSG_SetPptLimit, n);
        if (ret) {
-               pr_err("[%s] Set power limit Failed!", __func__);
+               pr_err("[%s] Set power limit Failed!\n", __func__);
                return ret;
        }
+       smu->power_limit = n;
 
-       return ret;
+       return 0;
 }
 
 static int smu_v11_0_get_current_clk_freq(struct smu_context *smu,
@@ -1742,7 +1710,6 @@ static const struct smu_funcs smu_v11_0_funcs = {
        .get_enabled_mask = smu_v11_0_get_enabled_mask,
        .system_features_control = smu_v11_0_system_features_control,
        .notify_display_change = smu_v11_0_notify_display_change,
-       .get_power_limit = smu_v11_0_get_power_limit,
        .set_power_limit = smu_v11_0_set_power_limit,
        .get_current_clk_freq = smu_v11_0_get_current_clk_freq,
        .init_max_sustainable_clocks = smu_v11_0_init_max_sustainable_clocks,
-- 
2.20.1

_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

Reply via email to