drm/amd/powerplay: support runtime ppfeatures setting on Navi10

Submitted by Deucher, Alexander on June 25, 2019, 12:53 p.m.

Details

Message ID BN6PR12MB18093BD5BC99A1282AC75E25F7E30@BN6PR12MB1809.namprd12.prod.outlook.com
State New
Headers show
Series "drm/amd/powerplay: support runtime ppfeatures setting on Navi10" ( rev: 2 ) in AMD X.Org drivers

Not browsing as part of any series.

Commit Message

Deucher, Alexander June 25, 2019, 12:53 p.m.
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>

Patch hide | download patch | download mbox

diff --git a/drivers/gpu/drm/amd/powerplay/navi10_ppt.c b/drivers/gpu/drm/amd/powerplay/navi10_ppt.c
index ac4b3fc97a8d..3d61372db551 100644
--- a/drivers/gpu/drm/amd/powerplay/navi10_ppt.c
+++ b/drivers/gpu/drm/amd/powerplay/navi10_ppt.c
@@ -1275,6 +1275,169 @@  static int navi10_get_uclk_dpm_states(struct smu_context *smu, uint32_t *clocks_
         return 0;
 }

+static int navi10_get_ppfeature_status(struct smu_context *smu,
+                                      char *buf)
+{
+       static const char *ppfeature_name[] = {
+                               "DPM_PREFETCHER",
+                               "DPM_GFXCLK",
+                               "DPM_GFX_PACE",
+                               "DPM_UCLK",
+                               "DPM_SOCCLK",
+                               "DPM_MP0CLK",
+                               "DPM_LINK",
+                               "DPM_DCEFCLK",
+                               "MEM_VDDCI_SCALING",
+                               "MEM_MVDD_SCALING",
+                               "DS_GFXCLK",
+                               "DS_SOCCLK",
+                               "DS_LCLK",
+                               "DS_DCEFCLK",
+                               "DS_UCLK",
+                               "GFX_ULV",
+                               "FW_DSTATE",
+                               "GFXOFF",
+                               "BACO",
+                               "VCN_PG",
+                               "JPEG_PG",
+                               "USB_PG",
+                               "RSMU_SMN_CG",
+                               "PPT",
+                               "TDC",
+                               "GFX_EDC",
+                               "APCC_PLUS",
+                               "GTHR",
+                               "ACDC",
+                               "VR0HOT",
+                               "VR1HOT",
+                               "FW_CTF",
+                               "FAN_CONTROL",
+                               "THERMAL",
+                               "GFX_DCS",
+                               "RM",
+                               "LED_DISPLAY",
+                               "GFX_SS",
+                               "OUT_OF_BAND_MONITOR",
+                               "TEMP_DEPENDENT_VMIN",
+                               "MMHUB_PG",
+                               "ATHUB_PG"};
+       static const char *output_title[] = {
+                               "FEATURES",
+                               "BITMASK",
+                               "ENABLEMENT"};
+       uint64_t features_enabled;
+       uint32_t feature_mask[2];
+       int i;
+       int ret = 0;
+       int size = 0;
+
+       ret = smu_feature_get_enabled_mask(smu, feature_mask, 2);
+       PP_ASSERT_WITH_CODE(!ret,
+                       "[GetPPfeatureStatus] Failed to get enabled smc features!",
+                       return ret);
+       features_enabled = (uint64_t)feature_mask[0] |
+                          (uint64_t)feature_mask[1] << 32;
+
+       size += sprintf(buf + size, "Current ppfeatures: 0x%016llx\n", features_enabled);
+       size += sprintf(buf + size, "%-19s %-22s %s\n",
+                               output_title[0],
+                               output_title[1],
+                               output_title[2]);
+       for (i = 0; i < (sizeof(ppfeature_name) / sizeof(ppfeature_name[0])); i++) {
+               size += sprintf(buf + size, "%-19s 0x%016llx %6s\n",
+                                       ppfeature_name[i],
+                                       1ULL << i,
+                                       (features_enabled & (1ULL << i)) ? "Y" : "N");
+       }
+
+       return size;
+}
+
+static int navi10_enable_smc_features(struct smu_context *smu,
+                                     bool enabled,
+                                     uint64_t feature_masks)
+{
+       struct smu_feature *feature = &smu->smu_feature;
+       uint32_t feature_low, feature_high;
+       uint32_t feature_mask[2];
+       int ret = 0;
+
+       feature_low = (uint32_t)(feature_masks & 0xFFFFFFFF);
+       feature_high = (uint32_t)((feature_masks & 0xFFFFFFFF00000000ULL) >> 32);
+
+       if (enabled) {
+               ret = smu_send_smc_msg_with_param(smu, SMU_MSG_EnableSmuFeaturesLow,
+                                                 feature_low);
+               if (ret)
+                       return ret;
+               ret = smu_send_smc_msg_with_param(smu, SMU_MSG_EnableSmuFeaturesHigh,
+                                                 feature_high);
+               if (ret)
+                       return ret;
+       } else {
+               ret = smu_send_smc_msg_with_param(smu, SMU_MSG_DisableSmuFeaturesLow,
+                                                 feature_low);
+               if (ret)
+                       return ret;
+               ret = smu_send_smc_msg_with_param(smu, SMU_MSG_DisableSmuFeaturesHigh,
+                                                 feature_high);
+               if (ret)
+                       return ret;
+       }
+
+       ret = smu_feature_get_enabled_mask(smu, feature_mask, 2);
+       if (ret)
+               return ret;
+
+       mutex_lock(&feature->mutex);
+       bitmap_copy(feature->enabled, (unsigned long *)&feature_mask,
+                   feature->feature_num);
+       mutex_unlock(&feature->mutex);
+
+       return 0;
+}
+
+static int navi10_set_ppfeature_status(struct smu_context *smu,
+                                      uint64_t new_ppfeature_masks)
+{
+       uint64_t features_enabled;
+       uint32_t feature_mask[2];
+       uint64_t features_to_enable;
+       uint64_t features_to_disable;
+       int ret = 0;
+
+       ret = smu_feature_get_enabled_mask(smu, feature_mask, 2);
+       PP_ASSERT_WITH_CODE(!ret,
+                       "[SetPPfeatureStatus] Failed to get enabled smc features!",
+                       return ret);
+       features_enabled = (uint64_t)feature_mask[0] |
+                          (uint64_t)feature_mask[1] << 32;
+
+       features_to_disable =
+               features_enabled & ~new_ppfeature_masks;
+       features_to_enable =
+               ~features_enabled & new_ppfeature_masks;
+
+       pr_debug("features_to_disable 0x%llx\n", features_to_disable);
+       pr_debug("features_to_enable 0x%llx\n", features_to_enable);
+
+       if (features_to_disable) {
+               ret = navi10_enable_smc_features(smu, false, features_to_disable);
+               PP_ASSERT_WITH_CODE(!ret,
+                               "[SetPPfeatureStatus] Failed to disable smc features!",
+                               return ret);
+       }
+
+       if (features_to_enable) {
+               ret = navi10_enable_smc_features(smu, true, features_to_enable);
+               PP_ASSERT_WITH_CODE(!ret,
+                               "[SetPPfeatureStatus] Failed to enable smc features!",
+                               return ret);
+       }
+
+       return 0;
+}
+
 static const struct pptable_funcs navi10_ppt_funcs = {
         .tables_init = navi10_tables_init,
         .alloc_dpm_context = navi10_allocate_dpm_context,
@@ -1308,6 +1471,8 @@  static const struct pptable_funcs navi10_ppt_funcs = {
         .set_watermarks_table = navi10_set_watermarks_table,
         .read_sensor = navi10_read_sensor,
         .get_uclk_dpm_states = navi10_get_uclk_dpm_states,
+       .get_ppfeature_status = navi10_get_ppfeature_status,
+       .set_ppfeature_status = navi10_set_ppfeature_status,
 };

 void navi10_set_ppt_funcs(struct smu_context *smu)