OSDN Git Service

drm/amd/powerplay: make power limit retrieval as asic specific
authorEvan Quan <evan.quan@amd.com>
Wed, 31 Jul 2019 03:52:37 +0000 (22:52 -0500)
committerAlex Deucher <alexander.deucher@amd.com>
Wed, 31 Jul 2019 04:48:35 +0000 (23:48 -0500)
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.quan@amd.com>
Reviewed-by: Kenneth Feng <kenneth.feng@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/powerplay/amdgpu_smu.c
drivers/gpu/drm/amd/powerplay/arcturus_ppt.c
drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h
drivers/gpu/drm/amd/powerplay/navi10_ppt.c
drivers/gpu/drm/amd/powerplay/smu_v11_0.c

index b1e0e2a..13b2c8a 100644 (file)
@@ -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;
        }
index c67a991..9360f5a 100644 (file)
@@ -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)
index 76edb2c..1ecd73c 100644 (file)
@@ -450,6 +450,7 @@ struct pptable_funcs {
        int (*set_performance_level)(struct smu_context *smu, enum amd_dpm_forced_level level);
        int (*display_disable_memory_clock_switch)(struct smu_context *smu, bool disable_memory_clock_switch);
        void (*dump_pptable)(struct smu_context *smu);
+       int (*get_power_limit)(struct smu_context *smu, uint32_t *limit, bool asic_default);
 };
 
 struct smu_funcs
@@ -482,7 +483,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);
@@ -611,7 +611,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) \
index 5ae19ae..106352a 100644 (file)
@@ -1509,6 +1509,56 @@ static int navi10_display_disable_memory_clock_switch(struct smu_context *smu,
        return ret;
 }
 
+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,
@@ -1546,6 +1596,7 @@ static const struct pptable_funcs navi10_ppt_funcs = {
        .set_performance_level = navi10_set_performance_level,
        .get_thermal_temperature_range = navi10_get_thermal_temperature_range,
        .display_disable_memory_clock_switch = navi10_display_disable_memory_clock_switch,
+       .get_power_limit = navi10_get_power_limit,
 };
 
 void navi10_set_ppt_funcs(struct smu_context *smu)
index 89f4c9e..35669e8 100644 (file)
@@ -1015,64 +1015,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,
@@ -1753,7 +1721,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,