drm/amd/pp: Expose set/get_power_limit for DGPU
authorRex Zhu <Rex.Zhu@amd.com>
Mon, 29 Jan 2018 10:04:18 +0000 (18:04 +0800)
committerAlex Deucher <alexander.deucher@amd.com>
Mon, 19 Feb 2018 19:19:44 +0000 (14:19 -0500)
User can change power limit between
[0, 1] * max power limit.

Set power limit to 0, restore to max power limit.

Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Rex Zhu <Rex.Zhu@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/include/kgd_pp_interface.h
drivers/gpu/drm/amd/powerplay/amd_powerplay.c
drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c
drivers/gpu/drm/amd/powerplay/hwmgr/smu7_powertune.c
drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c
drivers/gpu/drm/amd/powerplay/hwmgr/vega10_powertune.c
drivers/gpu/drm/amd/powerplay/inc/hwmgr.h

index 4f69fe8ca3715977ba0d1a1ad4ed2bd1af9fcc42..22c2fa30731fab40a5aa4bfae891852948926025 100644 (file)
@@ -283,6 +283,8 @@ struct amd_pm_funcs {
                                        uint32_t mc_addr_low,
                                        uint32_t mc_addr_hi,
                                        uint32_t size);
+       int (*set_power_limit)(void *handle, uint32_t n);
+       int (*get_power_limit)(void *handle, uint32_t *limit, bool default_limit);
 /* export to DC */
        u32 (*get_sclk)(void *handle, bool low);
        u32 (*get_mclk)(void *handle, bool low);
index 7c4b88aa7abbce47a89be266211316d5ad9c29fe..376ed2dd52c7e66d5f4d736d80dd602d4be021f7 100644 (file)
@@ -1237,6 +1237,65 @@ static int pp_dpm_notify_smu_memory_info(void *handle,
        return ret;
 }
 
+static int pp_set_power_limit(void *handle, uint32_t limit)
+{
+       struct pp_hwmgr *hwmgr;
+       struct pp_instance *pp_handle = (struct pp_instance *)handle;
+       int ret = 0;
+
+       ret = pp_check(pp_handle);
+
+       if (ret)
+               return ret;
+
+       hwmgr = pp_handle->hwmgr;
+
+       if (hwmgr->hwmgr_func->set_power_limit == NULL) {
+               pr_info("%s was not implemented.\n", __func__);
+               return -EINVAL;
+       }
+
+       if (limit == 0)
+               limit = hwmgr->default_power_limit;
+
+       if (limit > hwmgr->default_power_limit)
+               return -EINVAL;
+
+       mutex_lock(&pp_handle->pp_lock);
+       hwmgr->hwmgr_func->set_power_limit(hwmgr, limit);
+       hwmgr->power_limit = limit;
+       mutex_unlock(&pp_handle->pp_lock);
+       return ret;
+}
+
+static int pp_get_power_limit(void *handle, uint32_t *limit, bool default_limit)
+{
+       struct pp_hwmgr *hwmgr;
+       struct pp_instance *pp_handle = (struct pp_instance *)handle;
+       int ret = 0;
+
+       ret = pp_check(pp_handle);
+
+       if (ret)
+               return ret;
+
+       if (limit == NULL)
+               return -EINVAL;
+
+       hwmgr = pp_handle->hwmgr;
+
+       mutex_lock(&pp_handle->pp_lock);
+
+       if (default_limit)
+               *limit = hwmgr->default_power_limit;
+       else
+               *limit = hwmgr->power_limit;
+
+       mutex_unlock(&pp_handle->pp_lock);
+
+       return ret;
+}
+
 static int pp_display_configuration_change(void *handle,
        const struct amd_pp_display_configuration *display_config)
 {
@@ -1530,6 +1589,8 @@ const struct amd_pm_funcs pp_dpm_funcs = {
        .get_power_profile_mode = pp_get_power_profile_mode,
        .set_power_profile_mode = pp_set_power_profile_mode,
        .odn_edit_dpm_table = pp_odn_edit_dpm_table,
+       .set_power_limit = pp_set_power_limit,
+       .get_power_limit = pp_get_power_limit,
 /* export to DC */
        .get_sclk = pp_dpm_get_sclk,
        .get_mclk = pp_dpm_get_mclk,
index c59cb9499e06057628d2e2cdb011d899772accf2..937971361b65bff562d49ae508723c169b7a71ec 100644 (file)
@@ -4987,6 +4987,7 @@ static const struct pp_hwmgr_func smu7_hwmgr_funcs = {
        .get_max_high_clocks = smu7_get_max_high_clocks,
        .get_thermal_temperature_range = smu7_get_thermal_temperature_range,
        .odn_edit_dpm_table = smu7_odn_edit_dpm_table,
+       .set_power_limit = smu7_set_power_limit,
 };
 
 uint8_t smu7_get_sleep_divider_id_from_clock(uint32_t clock,
index 85ca16abb626f954a3b17edaa584616a8b93e727..a93829dfd73018a3f82c79e02c79a0cd5267bd0c 100644 (file)
@@ -857,6 +857,8 @@ int smu7_set_power_limit(struct pp_hwmgr *hwmgr, uint32_t n)
 {
        struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
 
+       n = (n & 0xff) << 8;
+
        if (data->power_containment_features &
                        POWERCONTAINMENT_FEATURE_PkgPwrLimit)
                return smum_send_msg_to_smc_with_parameter(hwmgr,
@@ -903,12 +905,12 @@ int smu7_enable_power_containment(struct pp_hwmgr *hwmgr)
                        PP_ASSERT_WITH_CODE((0 == smc_result),
                                        "Failed to enable PkgPwrTracking in SMC.", result = -1;);
                        if (0 == smc_result) {
-                               uint32_t default_limit =
-                                       (uint32_t)(cac_table->usMaximumPowerDeliveryLimit * 256);
+                               hwmgr->default_power_limit = hwmgr->power_limit =
+                                               cac_table->usMaximumPowerDeliveryLimit;
                                data->power_containment_features |=
                                                POWERCONTAINMENT_FEATURE_PkgPwrLimit;
 
-                               if (smu7_set_power_limit(hwmgr, default_limit))
+                               if (smu7_set_power_limit(hwmgr, hwmgr->power_limit))
                                        pr_err("Failed to set Default Power Limit in SMC!");
                        }
                }
index 341fba5f71714a7c41fa5957eff5c79f4495a63b..d0c8ba0096fe767b94ef3a023354856f981dbfac 100644 (file)
@@ -5155,6 +5155,7 @@ static const struct pp_hwmgr_func vega10_hwmgr_funcs = {
        .start_thermal_controller = vega10_start_thermal_controller,
        .get_power_profile_mode = vega10_get_power_profile_mode,
        .set_power_profile_mode = vega10_set_power_profile_mode,
+       .set_power_limit = vega10_set_power_limit,
 };
 
 int vega10_hwmgr_init(struct pp_hwmgr *hwmgr)
index 598a194737a99e0e4190ece6cea4a541d4557c8c..981c9e5431daf01c873ba0e1cc5a808951263185 100644 (file)
@@ -1357,10 +1357,11 @@ int vega10_enable_power_containment(struct pp_hwmgr *hwmgr)
        struct phm_ppt_v2_information *table_info =
                        (struct phm_ppt_v2_information *)(hwmgr->pptable);
        struct phm_tdp_table *tdp_table = table_info->tdp_table;
-       uint32_t default_pwr_limit =
-                       (uint32_t)(tdp_table->usMaximumPowerDeliveryLimit);
        int result = 0;
 
+       hwmgr->default_power_limit = hwmgr->power_limit =
+                       (uint32_t)(tdp_table->usMaximumPowerDeliveryLimit);
+
        if (PP_CAP(PHM_PlatformCaps_PowerContainment)) {
                if (data->smu_features[GNLD_PPT].supported)
                        PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr,
@@ -1374,7 +1375,7 @@ int vega10_enable_power_containment(struct pp_hwmgr *hwmgr)
                                        "Attempt to enable PPT feature Failed!",
                                        data->smu_features[GNLD_TDC].supported = false);
 
-               result = vega10_set_power_limit(hwmgr, default_pwr_limit);
+               result = vega10_set_power_limit(hwmgr, hwmgr->power_limit);
                PP_ASSERT_WITH_CODE(!result,
                                "Failed to set Default Power Limit in SMC!",
                                return result);
index 4d96439dd98917e35e59c90d61d374f5eb03f357..c0f9cea083394b305fcaaf0abaebd6a765e10e76 100644 (file)
@@ -347,6 +347,7 @@ struct pp_hwmgr_func {
        int (*odn_edit_dpm_table)(struct pp_hwmgr *hwmgr,
                                        enum PP_OD_DPM_TABLE_COMMAND type,
                                        long *input, uint32_t size);
+       int (*set_power_limit)(struct pp_hwmgr *hwmgr, uint32_t n);
        int (*set_mmhub_powergating_by_smu)(struct pp_hwmgr *hwmgr);
 };
 
@@ -759,6 +760,8 @@ struct pp_hwmgr {
        uint32_t pstate_sclk;
        uint32_t pstate_mclk;
        bool od_enabled;
+       uint32_t power_limit;
+       uint32_t default_power_limit;
 };
 
 struct cgs_irq_src_funcs {