From: Wenjing Liu <[email protected]>

[Why]
Keep the display QoS model and firmware table consistent when test
overrides are enabled.

[How]
Serialize the overridden QoS values into a dedicated transfer buffer
and send the table after clock initialization.

Signed-off-by: Wenjing Liu <[email protected]>
Signed-off-by: Fangzhi Zuo <[email protected]>
Reviewed-by: Alvin Lee <[email protected]>
---
 .../display/dc/clk_mgr/dcn60/dcn60_clk_mgr.c  | 125 ++++++++++++++++--
 .../amd/display/dc/inc/hw/clk_mgr_internal.h  |   9 ++
 2 files changed, 123 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn60/dcn60_clk_mgr.c 
b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn60/dcn60_clk_mgr.c
index d6db6168c3da..00d96232a013 100644
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn60/dcn60_clk_mgr.c
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn60/dcn60_clk_mgr.c
@@ -120,6 +120,9 @@ static const struct clk_mgr_mask clk_mgr_mask_dcn60 = {
 #define TO_DCN60_CLK_MGR(clk_mgr)\
        container_of(clk_mgr, struct dcn60_clk_mgr, base)
 
+/* Temporary UTM override used to unblock DCN6 testing. */
+static bool dcn60_should_apply_temp_utm_override = true;
+
 static bool dcn60_is_ppclk_dpm_enabled(struct clk_mgr_internal *clk_mgr, 
PPCLK_e clk)
 {
        bool ppclk_dpm_enabled = false;
@@ -627,6 +630,74 @@ static void dcn60_override_clk_table(struct 
clk_limit_table *clk_table)
        (void)clk_table;
 }
 
+/**
+ * dcn60_copy_utm_qos_model_to_soc_table - Convert a UTM QoS model to the PMFW 
table format.
+ * @dchub: overridden DCN6 UTM QoS model
+ * @utm_table: GPU-visible PMFW UTM table to populate
+ */
+static void dcn60_copy_utm_qos_model_to_soc_table(
+               const struct utm_qos_model_dchub_v3 *dchub,
+               SocUtmTable_t *utm_table)
+{
+       unsigned int load_level_count = dchub->load_level_count;
+       unsigned int sop_count = dchub->sop_count;
+       unsigned int ll, sop;
+
+       if (load_level_count > UTM_QOS_MODEL_V3_MAX_LOAD_LEVEL_COUNT)
+               load_level_count = UTM_QOS_MODEL_V3_MAX_LOAD_LEVEL_COUNT;
+
+       if (sop_count > UTM_QOS_MODEL_V3_MAX_SOP_COUNT)
+               sop_count = UTM_QOS_MODEL_V3_MAX_SOP_COUNT;
+
+       memset(utm_table, 0, sizeof(*utm_table));
+       utm_table->Header.LoadLevelCount = load_level_count;
+       utm_table->Header.SopCount = sop_count;
+
+       for (ll = 0; ll < load_level_count; ll++) {
+               for (sop = 0; sop < sop_count; sop++) {
+                       const struct utm_qos_model_dchub_v3_sop_entry *src =
+                                       &dchub->sops[ll][sop];
+                       SocUtmSopEntry_t *dst = &utm_table->Sops[ll][sop];
+
+                       dst->UrgentRampPs = src->urgent_ramp_ps;
+                       dst->TripPs = src->t_trip_ps;
+                       dst->MetaTripToMemPs = src->meta_trip_to_mem_ps;
+                       dst->MaxReqLatencyUrgPs = src->max_req_latency_urg_ps;
+                       dst->AvgReqLatencyUrgPs = src->avg_req_latency_urg_ps;
+                       dst->MaxReqLatencyNonUrgPs = 
src->max_req_latency_non_urg_ps;
+                       dst->AvgReqLatencyNonUrgPs = 
src->avg_req_latency_non_urg_ps;
+                       dst->DfResponseTimePs = src->df_response_time_ps;
+                       dst->UrgentBandwidthKBps = src->urgent_bandwidth_KBps;
+                       dst->NominalBandwidthKBps = src->nominal_bandwidth_KBps;
+                       dst->LsdmaBandwidthKBps = src->lsdma_bandwidth_KBps;
+               }
+       }
+}
+
+/**
+ * dcn60_override_utm_qos_model - Override the UTM QoS model.
+ * @bw_params: clock manager bandwidth parameters
+ */
+static void dcn60_override_utm_qos_model(struct clk_bw_params *bw_params)
+{
+       struct utm_qos_model *qos_model;
+       struct utm_qos_model_dchub_v3 *dchub;
+
+       if (!bw_params->utm_qos_model
+                       || bw_params->utm_qos_model->version != 
utm_qos_model_version_v3
+                       || !bw_params->utm_qos_model->dchub_v3)
+               return;
+
+       qos_model = (struct utm_qos_model *)bw_params->utm_qos_model;
+       dchub = (struct utm_qos_model_dchub_v3 *)qos_model->dchub_v3;
+
+       dcn6_test_initialize_utm_qos_model_v3(qos_model, dchub);
+
+       // Override for lsdma here is redundant with the above call, but this 
may need to outlive
+       // the test_initialize call for debug purposes so keep it here for now.
+       dcn6_test_override_lsdma_bandwidth_v3(dchub);
+}
+
 static void dcn60_override_bw_params(struct clk_mgr_internal *clk_mgr,
                struct clk_bw_params *bw_params)
 {
@@ -654,17 +725,8 @@ static void dcn60_override_bw_params(struct 
clk_mgr_internal *clk_mgr,
 
        bw_params->dc_mode_softmax_memclk = bw_params->dc_mode_limit.memclk_mhz;
 
-       /* Override as needed - temporary for debug only. */
-       if (bw_params->utm_qos_model && bw_params->utm_qos_model->dchub_v3) {
-               dcn6_test_initialize_utm_qos_model_v3(
-                               (struct utm_qos_model 
*)bw_params->utm_qos_model,
-                               (struct utm_qos_model_dchub_v3 
*)bw_params->utm_qos_model->dchub_v3);
-
-               // Override for lsdma here is redundant with the above call, 
but this may need to outlive
-               // the test_initialize call for debug purposes so keep it here 
for now.
-               dcn6_test_override_lsdma_bandwidth_v3(
-                               (struct utm_qos_model_dchub_v3 
*)bw_params->utm_qos_model->dchub_v3);
-       }
+       if (dcn60_should_apply_temp_utm_override)
+               dcn60_override_utm_qos_model(bw_params);
 }
 
 /**
@@ -922,6 +984,32 @@ static void dcn60_clock_read_ss_info(struct 
clk_mgr_internal *clk_mgr)
        }
 }
 
+/**
+ * dcn60_update_smu_utm_table - Send the current UTM QoS model to SMU.
+ * @clk_mgr: clock manager instance
+ *
+ * Return: true if SMU accepted the UTM table, false otherwise
+ */
+static bool dcn60_update_smu_utm_table(struct clk_mgr_internal *clk_mgr)
+{
+       const struct utm_qos_model *qos_model = 
clk_mgr->base.bw_params->utm_qos_model;
+       const struct utm_qos_model_dchub_v3 *dchub;
+       SocUtmTable_t *utm_table;
+
+       if (!qos_model
+                       || qos_model->version != utm_qos_model_version_v3
+                       || !qos_model->dchub_v3
+                       || !clk_mgr->utm_override_table)
+               return false;
+
+       dchub = qos_model->dchub_v3;
+       utm_table = (SocUtmTable_t *)clk_mgr->utm_override_table;
+
+       dcn60_copy_utm_qos_model_to_soc_table(dchub, utm_table);
+       return dcn60_smu_set_soc_utm_table(clk_mgr,
+                       clk_mgr->utm_override_table_addr);
+}
+
 void dcn60_init_clocks(struct clk_mgr *clk_mgr_base)
 {
        struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base);
@@ -947,6 +1035,11 @@ void dcn60_init_clocks(struct clk_mgr *clk_mgr_base)
        if (clk_mgr->dpm_present)
                clk_mgr_base->ctx->dc->res_pool->funcs->update_bw_bounding_box(
                                clk_mgr_base->ctx->dc, clk_mgr_base->bw_params);
+
+       if (clk_mgr->dpm_present
+                       && dcn60_should_apply_temp_utm_override
+                       && !dcn60_update_smu_utm_table(clk_mgr))
+               DC_LOG_ERROR("Failed to transfer UTM override table to SMU.\n");
 }
 
 
@@ -1751,6 +1844,12 @@ struct clk_mgr_internal *dcn60_clk_mgr_construct(
        if (!clk_mgr->dal_init_table)
                goto fail;
 
+       clk_mgr->utm_override_table = 
dm_helpers_allocate_gpu_mem(clk_mgr->base.ctx,
+                       DC_MEM_ALLOC_TYPE_GART, sizeof(SocUtmTable_t),
+                       &clk_mgr->utm_override_table_addr);
+       if (!clk_mgr->utm_override_table)
+               goto fail;
+
        return &clk_mgr60->base;
 
 fail:
@@ -1764,6 +1863,10 @@ void dcn60_clk_mgr_destroy(struct clk_mgr_internal 
*clk_mgr)
 {
        kfree(clk_mgr->base.bw_params);
 
+       if (clk_mgr->utm_override_table)
+               dm_helpers_free_gpu_mem(clk_mgr->base.ctx, 
DC_MEM_ALLOC_TYPE_GART,
+                               clk_mgr->utm_override_table);
+
        if (clk_mgr->dal_init_table)
                dm_helpers_free_gpu_mem(clk_mgr->base.ctx, 
DC_MEM_ALLOC_TYPE_GART,
                                (void *)clk_mgr->dal_init_table);
diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr_internal.h 
b/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr_internal.h
index d735eb1e7f43..68fd92258e8c 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr_internal.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr_internal.h
@@ -541,6 +541,15 @@ struct clk_mgr_internal {
        const void *dal_init_table;
        long long dal_init_table_addr;
 
+       /**
+        * @utm_override_table:
+        *
+        * GPU-accessible DRAM buffer for the UTM table transferred to SMU via
+        * DALSMC_MSG_TransferTableDram2Smu(TABLE_SOC_UTM).
+        */
+       void *utm_override_table;
+       long long utm_override_table_addr;
+
        bool dpm_present;
        bool pme_trigger_pending;
 };
-- 
2.53.0

Reply via email to