drm/amd/pm: correct the power limits reporting on OOB supported
authorEvan Quan <evan.quan@amd.com>
Wed, 19 May 2021 04:22:04 +0000 (12:22 +0800)
committerAlex Deucher <alexander.deucher@amd.com>
Fri, 11 Jun 2021 20:03:09 +0000 (16:03 -0400)
As OOB(out-of-band) interface may be used to update the power limits.
Thus to make sure the power limits reporting of our driver always
reflects the correct values, the internal cache must be aligned
carefully.

V2: add support for out-of-band of other ASICs
    align cached current power limit with OOB imposed

Signed-off-by: Evan Quan <evan.quan@amd.com>
Reviewed-By: Harish Kasiviswanathan <Harish.Kasiviswanathan@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h
drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c
drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c
drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c
drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c
drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c
drivers/gpu/drm/amd/pm/swsmu/smu_internal.h

index 0c06c2f..6559912 100644 (file)
@@ -765,7 +765,10 @@ struct pptable_funcs {
        /**
         * @get_power_limit: Get the device's power limits.
         */
-       int (*get_power_limit)(struct smu_context *smu);
+       int (*get_power_limit)(struct smu_context *smu,
+                              uint32_t *current_power_limit,
+                              uint32_t *default_power_limit,
+                              uint32_t *max_power_limit);
 
        /**
         * @get_ppt_limit: Get the device's ppt limits.
index a6029a8..cb375f1 100644 (file)
@@ -688,7 +688,10 @@ static int smu_late_init(void *handle)
                return ret;
        }
 
-       ret = smu_get_asic_power_limits(smu);
+       ret = smu_get_asic_power_limits(smu,
+                                       &smu->current_power_limit,
+                                       &smu->default_power_limit,
+                                       &smu->max_power_limit);
        if (ret) {
                dev_err(adev->dev, "Failed to get asic power limits!\n");
                return ret;
@@ -2238,6 +2241,15 @@ int smu_get_power_limit(void *handle,
        } else {
                switch (limit_level) {
                case SMU_PPT_LIMIT_CURRENT:
+                       if ((smu->adev->asic_type == CHIP_ALDEBARAN) ||
+                            (smu->adev->asic_type == CHIP_SIENNA_CICHLID) ||
+                            (smu->adev->asic_type == CHIP_NAVY_FLOUNDER) ||
+                            (smu->adev->asic_type == CHIP_DIMGREY_CAVEFISH) ||
+                            (smu->adev->asic_type == CHIP_BEIGE_GOBY))
+                               ret = smu_get_asic_power_limits(smu,
+                                                               &smu->current_power_limit,
+                                                               NULL,
+                                                               NULL);
                        *limit = smu->current_power_limit;
                        break;
                case SMU_PPT_LIMIT_DEFAULT:
index 51ab5cb..094df6f 100644 (file)
@@ -1194,7 +1194,10 @@ static int arcturus_get_fan_parameters(struct smu_context *smu)
        return 0;
 }
 
-static int arcturus_get_power_limit(struct smu_context *smu)
+static int arcturus_get_power_limit(struct smu_context *smu,
+                                   uint32_t *current_power_limit,
+                                   uint32_t *default_power_limit,
+                                   uint32_t *max_power_limit)
 {
        struct smu_11_0_powerplay_table *powerplay_table =
                (struct smu_11_0_powerplay_table *)smu->smu_table.power_play_table;
@@ -1210,17 +1213,24 @@ static int arcturus_get_power_limit(struct smu_context *smu)
                power_limit =
                        pptable->SocketPowerLimitAc[PPT_THROTTLER_PPT0];
        }
-       smu->current_power_limit = smu->default_power_limit = power_limit;
 
-       if (smu->od_enabled) {
-               od_percent = le32_to_cpu(powerplay_table->overdrive_table.max[SMU_11_0_ODSETTING_POWERPERCENTAGE]);
+       if (current_power_limit)
+               *current_power_limit = power_limit;
+       if (default_power_limit)
+               *default_power_limit = power_limit;
 
-               dev_dbg(smu->adev->dev, "ODSETTING_POWERPERCENTAGE: %d (default: %d)\n", od_percent, power_limit);
+       if (max_power_limit) {
+               if (smu->od_enabled) {
+                       od_percent = le32_to_cpu(powerplay_table->overdrive_table.max[SMU_11_0_ODSETTING_POWERPERCENTAGE]);
 
-               power_limit *= (100 + od_percent);
-               power_limit /= 100;
+                       dev_dbg(smu->adev->dev, "ODSETTING_POWERPERCENTAGE: %d (default: %d)\n", od_percent, power_limit);
+
+                       power_limit *= (100 + od_percent);
+                       power_limit /= 100;
+               }
+
+               *max_power_limit = power_limit;
        }
-       smu->max_power_limit = power_limit;
 
        return 0;
 }
index 5a967db..0e67517 100644 (file)
@@ -2136,7 +2136,10 @@ static int navi10_display_disable_memory_clock_switch(struct smu_context *smu,
        return ret;
 }
 
-static int navi10_get_power_limit(struct smu_context *smu)
+static int navi10_get_power_limit(struct smu_context *smu,
+                                 uint32_t *current_power_limit,
+                                 uint32_t *default_power_limit,
+                                 uint32_t *max_power_limit)
 {
        struct smu_11_0_powerplay_table *powerplay_table =
                (struct smu_11_0_powerplay_table *)smu->smu_table.power_play_table;
@@ -2153,18 +2156,25 @@ static int navi10_get_power_limit(struct smu_context *smu)
                power_limit =
                        pptable->SocketPowerLimitAc[PPT_THROTTLER_PPT0];
        }
-       smu->current_power_limit = smu->default_power_limit = power_limit;
 
-       if (smu->od_enabled &&
-           navi10_od_feature_is_supported(od_settings, SMU_11_0_ODCAP_POWER_LIMIT)) {
-               od_percent = le32_to_cpu(powerplay_table->overdrive_table.max[SMU_11_0_ODSETTING_POWERPERCENTAGE]);
+       if (current_power_limit)
+               *current_power_limit = power_limit;
+       if (default_power_limit)
+               *default_power_limit = power_limit;
 
-               dev_dbg(smu->adev->dev, "ODSETTING_POWERPERCENTAGE: %d (default: %d)\n", od_percent, power_limit);
+       if (max_power_limit) {
+               if (smu->od_enabled &&
+                   navi10_od_feature_is_supported(od_settings, SMU_11_0_ODCAP_POWER_LIMIT)) {
+                       od_percent = le32_to_cpu(powerplay_table->overdrive_table.max[SMU_11_0_ODSETTING_POWERPERCENTAGE]);
 
-               power_limit *= (100 + od_percent);
-               power_limit /= 100;
+                       dev_dbg(smu->adev->dev, "ODSETTING_POWERPERCENTAGE: %d (default: %d)\n", od_percent, power_limit);
+
+                       power_limit *= (100 + od_percent);
+                       power_limit /= 100;
+               }
+
+               *max_power_limit = power_limit;
        }
-       smu->max_power_limit = power_limit;
 
        return 0;
 }
index 848efc2..c751f71 100644 (file)
@@ -1791,7 +1791,10 @@ static int sienna_cichlid_display_disable_memory_clock_switch(struct smu_context
        return ret;
 }
 
-static int sienna_cichlid_get_power_limit(struct smu_context *smu)
+static int sienna_cichlid_get_power_limit(struct smu_context *smu,
+                                         uint32_t *current_power_limit,
+                                         uint32_t *default_power_limit,
+                                         uint32_t *max_power_limit)
 {
        struct smu_11_0_7_powerplay_table *powerplay_table =
                (struct smu_11_0_7_powerplay_table *)smu->smu_table.power_play_table;
@@ -1804,17 +1807,23 @@ static int sienna_cichlid_get_power_limit(struct smu_context *smu)
                power_limit =
                        table_member[PPT_THROTTLER_PPT0];
        }
-       smu->current_power_limit = smu->default_power_limit = power_limit;
 
-       if (smu->od_enabled) {
-               od_percent = le32_to_cpu(powerplay_table->overdrive_table.max[SMU_11_0_7_ODSETTING_POWERPERCENTAGE]);
+       if (current_power_limit)
+               *current_power_limit = power_limit;
+       if (default_power_limit)
+               *default_power_limit = power_limit;
 
-               dev_dbg(smu->adev->dev, "ODSETTING_POWERPERCENTAGE: %d (default: %d)\n", od_percent, power_limit);
+       if (max_power_limit) {
+               if (smu->od_enabled) {
+                       od_percent = le32_to_cpu(powerplay_table->overdrive_table.max[SMU_11_0_7_ODSETTING_POWERPERCENTAGE]);
 
-               power_limit *= (100 + od_percent);
-               power_limit /= 100;
+                       dev_dbg(smu->adev->dev, "ODSETTING_POWERPERCENTAGE: %d (default: %d)\n", od_percent, power_limit);
+
+                       power_limit *= (100 + od_percent);
+                       power_limit /= 100;
+               }
+               *max_power_limit = power_limit;
        }
-       smu->max_power_limit = power_limit;
 
        return 0;
 }
index 3a7d2f5..18681dc 100644 (file)
@@ -2071,7 +2071,10 @@ static int vangogh_mode2_reset(struct smu_context *smu)
        return vangogh_mode_reset(smu, SMU_RESET_MODE_2);
 }
 
-static int vangogh_get_power_limit(struct smu_context *smu)
+static int vangogh_get_power_limit(struct smu_context *smu,
+                                  uint32_t *current_power_limit,
+                                  uint32_t *default_power_limit,
+                                  uint32_t *max_power_limit)
 {
        struct smu_11_5_power_context *power_context =
                                                                smu->smu_power.power_context;
@@ -2087,8 +2090,12 @@ static int vangogh_get_power_limit(struct smu_context *smu)
                return ret;
        }
        /* convert from milliwatt to watt */
-       smu->current_power_limit = smu->default_power_limit = ppt_limit / 1000;
-       smu->max_power_limit = 29;
+       if (current_power_limit)
+               *current_power_limit = ppt_limit / 1000;
+       if (default_power_limit)
+               *default_power_limit = ppt_limit / 1000;
+       if (max_power_limit)
+               *max_power_limit = 29;
 
        ret = smu_cmn_send_smc_msg(smu, SMU_MSG_GetFastPPTLimit, &ppt_limit);
        if (ret) {
index 0a53909..64a4126 100644 (file)
@@ -1146,7 +1146,10 @@ static int aldebaran_read_sensor(struct smu_context *smu,
        return ret;
 }
 
-static int aldebaran_get_power_limit(struct smu_context *smu)
+static int aldebaran_get_power_limit(struct smu_context *smu,
+                                    uint32_t *current_power_limit,
+                                    uint32_t *default_power_limit,
+                                    uint32_t *max_power_limit)
 {
        PPTable_t *pptable = smu->smu_table.driver_pptable;
        uint32_t power_limit = 0;
@@ -1166,9 +1169,15 @@ static int aldebaran_get_power_limit(struct smu_context *smu)
                power_limit = pptable->PptLimit;
        }
 
-       smu->current_power_limit = smu->default_power_limit = power_limit;
-       if (pptable)
-               smu->max_power_limit = pptable->PptLimit;
+       if (current_power_limit)
+               *current_power_limit = power_limit;
+       if (default_power_limit)
+               *default_power_limit = power_limit;
+
+       if (max_power_limit) {
+               if (pptable)
+                       *max_power_limit = pptable->PptLimit;
+       }
 
        return 0;
 }
index b6d2f2e..59f9cff 100644 (file)
@@ -82,7 +82,7 @@
 #define smu_i2c_fini(smu, control)                                     smu_ppt_funcs(i2c_fini, 0, smu, control)
 #define smu_get_unique_id(smu)                                         smu_ppt_funcs(get_unique_id, 0, smu)
 #define smu_log_thermal_throttling(smu)                                        smu_ppt_funcs(log_thermal_throttling_event, 0, smu)
-#define smu_get_asic_power_limits(smu)                                 smu_ppt_funcs(get_power_limit, 0, smu)
+#define smu_get_asic_power_limits(smu, current, default, max)          smu_ppt_funcs(get_power_limit, 0, smu, current, default, max)
 #define smu_get_pp_feature_mask(smu, buf)                              smu_ppt_funcs(get_pp_feature_mask, 0, smu, buf)
 #define smu_set_pp_feature_mask(smu, new_mask)                         smu_ppt_funcs(set_pp_feature_mask, 0, smu, new_mask)
 #define smu_gfx_ulv_control(smu, enablement)                           smu_ppt_funcs(gfx_ulv_control, 0, smu, enablement)