drm/amd/powerplay: maximize code sharing around power limit
authorEvan Quan <evan.quan@amd.com>
Mon, 8 Jun 2020 08:29:41 +0000 (16:29 +0800)
committerAlex Deucher <alexander.deucher@amd.com>
Wed, 1 Jul 2020 05:59:18 +0000 (01:59 -0400)
Also cache the current and max power limits.

Signed-off-by: Evan Quan <evan.quan@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/powerplay/arcturus_ppt.c
drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h
drivers/gpu/drm/amd/powerplay/inc/smu_v11_0.h
drivers/gpu/drm/amd/powerplay/navi10_ppt.c
drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c
drivers/gpu/drm/amd/powerplay/smu_v11_0.c

index 0704a9c..2c78271 100644 (file)
@@ -1413,40 +1413,33 @@ static int arcturus_get_power_limit(struct smu_context *smu,
                                     uint32_t *limit,
                                     bool cap)
 {
+       struct smu_11_0_powerplay_table *powerplay_table =
+               (struct smu_11_0_powerplay_table *)smu->smu_table.power_play_table;
        PPTable_t *pptable = smu->smu_table.driver_pptable;
-       uint32_t asic_default_power_limit = 0;
-       int ret = 0;
-       int power_src;
-
-       if (!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;
+       uint32_t power_limit, od_percent;
 
-                       ret = smu_send_smc_msg_with_param(smu, SMU_MSG_GetPptLimit,
-                               power_src << 16, &asic_default_power_limit);
-                       if (ret) {
-                               dev_err(smu->adev->dev, "[%s] get PPT limit failed!", __func__);
-                               return ret;
-                       }
-               } else {
-                       /* the last hope to figure out the ppt limit */
-                       if (!pptable) {
-                               dev_err(smu->adev->dev, "Cannot get PPT limit due to pptable missing!");
-                               return -EINVAL;
-                       }
-                       asic_default_power_limit =
-                               pptable->SocketPowerLimitAc[PPT_THROTTLER_PPT0];
+       if (smu_v11_0_get_current_power_limit(smu, &power_limit)) {
+               /* the last hope to figure out the ppt limit */
+               if (!pptable) {
+                       dev_err(smu->adev->dev, "Cannot get PPT limit due to pptable missing!");
+                       return -EINVAL;
                }
+               power_limit =
+                       pptable->SocketPowerLimitAc[PPT_THROTTLER_PPT0];
+       }
+       smu->current_power_limit = power_limit;
+
+       if (smu->od_enabled) {
+               od_percent = le32_to_cpu(powerplay_table->overdrive_table.max[SMU_11_0_ODSETTING_POWERPERCENTAGE]);
+
+               dev_dbg(smu->adev->dev, "ODSETTING_POWERPERCENTAGE: %d (default: %d)\n", od_percent, power_limit);
 
-               smu->power_limit = asic_default_power_limit;
+               power_limit *= (100 + od_percent);
+               power_limit /= 100;
        }
+       smu->max_power_limit = power_limit;
 
-       if (cap)
-               *limit = smu_get_max_power_limit(smu);
-       else
-               *limit = smu->power_limit;
+       *limit = (cap ? smu->max_power_limit : smu->current_power_limit);
 
        return 0;
 }
index 9276320..574a793 100644 (file)
@@ -382,6 +382,8 @@ struct smu_context
        bool od_enabled;
        uint32_t power_limit;
        uint32_t default_power_limit;
+       uint32_t current_power_limit;
+       uint32_t max_power_limit;
 
        /* soft pptable */
        uint32_t ppt_offset_bytes;
index 9da2f26..2e9939b 100644 (file)
@@ -196,6 +196,9 @@ int smu_v11_0_get_enabled_mask(struct smu_context *smu,
 
 int smu_v11_0_notify_display_change(struct smu_context *smu);
 
+int smu_v11_0_get_current_power_limit(struct smu_context *smu,
+                                     uint32_t *power_limit);
+
 int smu_v11_0_set_power_limit(struct smu_context *smu, uint32_t n);
 
 int smu_v11_0_get_current_clk_freq(struct smu_context *smu,
index e63498e..b867f94 100644 (file)
@@ -1923,43 +1923,36 @@ static uint32_t navi10_get_pptable_power_limit(struct smu_context *smu)
 }
 
 static int navi10_get_power_limit(struct smu_context *smu,
-                                    uint32_t *limit,
-                                    bool cap)
+                                 uint32_t *limit,
+                                 bool cap)
 {
+       struct smu_11_0_powerplay_table *powerplay_table =
+               (struct smu_11_0_powerplay_table *)smu->smu_table.power_play_table;
        PPTable_t *pptable = smu->smu_table.driver_pptable;
-       uint32_t asic_default_power_limit = 0;
-       int ret = 0;
-       int power_src;
-
-       if (!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;
+       uint32_t power_limit, od_percent;
 
-                       ret = smu_send_smc_msg_with_param(smu, SMU_MSG_GetPptLimit,
-                               power_src << 16, &asic_default_power_limit);
-                       if (ret) {
-                               dev_err(smu->adev->dev, "[%s] get PPT limit failed!", __func__);
-                               return ret;
-                       }
-               } else {
-                       /* the last hope to figure out the ppt limit */
-                       if (!pptable) {
-                               dev_err(smu->adev->dev, "Cannot get PPT limit due to pptable missing!");
-                               return -EINVAL;
-                       }
-                       asic_default_power_limit =
-                               pptable->SocketPowerLimitAc[PPT_THROTTLER_PPT0];
+       if (smu_v11_0_get_current_power_limit(smu, &power_limit)) {
+               /* the last hope to figure out the ppt limit */
+               if (!pptable) {
+                       dev_err(smu->adev->dev, "Cannot get PPT limit due to pptable missing!");
+                       return -EINVAL;
                }
+               power_limit =
+                       pptable->SocketPowerLimitAc[PPT_THROTTLER_PPT0];
+       }
+       smu->current_power_limit = power_limit;
 
-               smu->power_limit = asic_default_power_limit;
+       if (smu->od_enabled) {
+               od_percent = le32_to_cpu(powerplay_table->overdrive_table.max[SMU_11_0_ODSETTING_POWERPERCENTAGE]);
+
+               dev_dbg(smu->adev->dev, "ODSETTING_POWERPERCENTAGE: %d (default: %d)\n", od_percent, power_limit);
+
+               power_limit *= (100 + od_percent);
+               power_limit /= 100;
        }
+       smu->max_power_limit = power_limit;
 
-       if (cap)
-               *limit = smu_get_max_power_limit(smu);
-       else
-               *limit = smu->power_limit;
+       *limit = (cap ? smu->max_power_limit : smu->current_power_limit);
 
        return 0;
 }
index b836752..c427e23 100644 (file)
@@ -1747,40 +1747,33 @@ static int sienna_cichlid_get_power_limit(struct smu_context *smu,
                                     uint32_t *limit,
                                     bool cap)
 {
+       struct smu_11_0_7_powerplay_table *powerplay_table =
+               (struct smu_11_0_7_powerplay_table *)smu->smu_table.power_play_table;
        PPTable_t *pptable = smu->smu_table.driver_pptable;
-       uint32_t asic_default_power_limit = 0;
-       int ret = 0;
-       int power_src;
-
-       if (!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, &asic_default_power_limit);
-                       if (ret) {
-                               dev_err(smu->adev->dev, "[%s] get PPT limit failed!", __func__);
-                               return ret;
-                       }
-               } else {
-                       /* the last hope to figure out the ppt limit */
-                       if (!pptable) {
-                               dev_err(smu->adev->dev, "Cannot get PPT limit due to pptable missing!");
-                               return -EINVAL;
-                       }
-                       asic_default_power_limit =
-                               pptable->SocketPowerLimitAc[PPT_THROTTLER_PPT0];
+       uint32_t power_limit, od_percent;
+
+       if (smu_v11_0_get_current_power_limit(smu, &power_limit)) {
+               /* the last hope to figure out the ppt limit */
+               if (!pptable) {
+                       dev_err(smu->adev->dev, "Cannot get PPT limit due to pptable missing!");
+                       return -EINVAL;
                }
+               power_limit =
+                       pptable->SocketPowerLimitAc[PPT_THROTTLER_PPT0];
+       }
+       smu->current_power_limit = power_limit;
+
+       if (smu->od_enabled) {
+               od_percent = le32_to_cpu(powerplay_table->overdrive_table.max[SMU_11_0_7_ODSETTING_POWERPERCENTAGE]);
+
+               dev_dbg(smu->adev->dev, "ODSETTING_POWERPERCENTAGE: %d (default: %d)\n", od_percent, power_limit);
 
-               smu->power_limit = asic_default_power_limit;
+               power_limit *= (100 + od_percent);
+               power_limit /= 100;
        }
+       smu->max_power_limit = power_limit;
 
-       if (cap)
-               *limit = smu_get_max_power_limit(smu);
-       else
-               *limit = smu->power_limit;
+       *limit = (cap ? smu->max_power_limit : smu->current_power_limit);
 
        return 0;
 }
index 9421b4b..53491c5 100644 (file)
@@ -1056,6 +1056,29 @@ int smu_v11_0_init_max_sustainable_clocks(struct smu_context *smu)
        return 0;
 }
 
+int smu_v11_0_get_current_power_limit(struct smu_context *smu,
+                                     uint32_t *power_limit)
+{
+       int power_src;
+       int ret = 0;
+
+       if (!smu_feature_is_enabled(smu, SMU_FEATURE_PPT_BIT))
+               return -EINVAL;
+
+       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,
+                                         power_limit);
+       if (ret)
+               dev_err(smu->adev->dev, "[%s] get PPT limit failed!", __func__);
+
+       return ret;
+}
+
 int smu_v11_0_set_power_limit(struct smu_context *smu, uint32_t n)
 {
        int ret = 0;