From: Wenjing Liu <[email protected]>

[Why]
The hubbub perfmon peak-bandwidth path used a monolithic function
combining counter configuration and enable in one call, and wrote results
into a caller-supplied struct outside the dc_state model. A BLS-driven
approach builds the measurement from stateless primitives, gates it to OTG
frame boundaries, and stores results in dc_state.

[How]
- Rename the peak-BW vtable members from "unbounded_bandwidth" to
  "out_of_order_bandwidth" and split them into arm and start operations.
- Add the full set of perfmon BLS primitives - param structs, union
  members, enum entries, executors, and hwss_add_* builders - for reset,
  arm, every start_measuring_* and every get_* operation.
- Add dc_probe_status (valid, type, result union) plus probe_status[] to
  dc_state.
- Replace the measure_memory_qos hook with program_perfmon(dc, context),
  which writes results into probe_status[].
- dc_get_qos_info no longer calls the removed hook.

Reviewed-by: Dominik Kaszewski <[email protected]>
Signed-off-by: Wenjing Liu <[email protected]>
Signed-off-by: Wayne Lin <[email protected]>
---
 drivers/gpu/drm/amd/display/dc/core/dc.c      |  17 +-
 .../drm/amd/display/dc/core/dc_hw_sequencer.c | 337 ++++++++++++++++++
 .../gpu/drm/amd/display/dc/core/dc_state.c    |   1 +
 .../drm/amd/display/dc/hwss/hw_sequencer.h    | 191 +++++++++-
 .../gpu/drm/amd/display/dc/inc/core_types.h   |  27 ++
 .../gpu/drm/amd/display/dc/inc/hw/dchubbub.h  |  12 +-
 6 files changed, 562 insertions(+), 23 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c 
b/drivers/gpu/drm/amd/display/dc/core/dc.c
index 3fa577a02df1..a3665c49a381 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc.c
@@ -8125,24 +8125,13 @@ void dc_log_preos_dmcub_info(const struct dc *dc)
 bool dc_get_qos_info(struct dc *dc, struct dc_qos_info *info)
 {
        const struct dc_clocks *clk = &dc->current_state->bw_ctx.bw.dcn.clk;
-       struct dc_measured_memory_qos measured = {};
        struct dc_requested_memory_qos requested = {};
 
        memset(info, 0, sizeof(*info));
 
-       // Check if measurement function is available
-       if (!dc->hwss.measure_memory_qos) {
-               return false;
-       }
-
-       dc->hwss.measure_memory_qos(dc, &measured);
-
-       info->actual_peak_bw_in_mbps    = measured.peak_bw_mbps;
-       info->actual_avg_bw_in_mbps     = measured.avg_bw_mbps;
-       info->actual_min_latency_in_ns  = measured.min_latency_ns;
-       info->actual_max_latency_in_ns  = measured.max_latency_ns;
-       info->actual_avg_latency_in_ns  = measured.avg_latency_ns;
-       info->dcn_bandwidth_ub_in_mbps  = (uint32_t)(clk->fclk_khz / 1000 * 64);
+       /* TODO: remove the actual_* fields from struct dc_qos_info once all 
callers
+        * read measured QoS from dc_state probe_status instead of this struct. 
*/
+       info->dcn_bandwidth_ub_in_mbps = (uint32_t)(clk->fclk_khz / 1000 * 64);
 
        if (dc->clk_mgr && dc->clk_mgr->funcs->get_requested_memory_qos) {
                dc->clk_mgr->funcs->get_requested_memory_qos(dc->clk_mgr, 
&requested);
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c 
b/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c
index 6002175420a0..07ec00e11f2d 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c
@@ -1495,6 +1495,48 @@ void hwss_execute_sequence(struct dc *dc,
                case HUBBUB_SOFT_RESET:
                        hwss_hubbub_soft_reset(params);
                        break;
+               case HUBBUB_PERFMON_RESET:
+                       hwss_hubbub_perfmon_reset(params);
+                       break;
+               case HUBBUB_PERFMON_ARM_OUT_OF_ORDER_BW:
+                       hwss_hubbub_perfmon_arm_out_of_order_bw(params);
+                       break;
+               case HUBBUB_PERFMON_START_OUT_OF_ORDER_BW:
+                       hwss_hubbub_perfmon_start_out_of_order_bw(params);
+                       break;
+               case HUBBUB_PERFMON_START_IN_ORDER_BW:
+                       hwss_hubbub_perfmon_start_in_order_bw(params);
+                       break;
+               case HUBBUB_PERFMON_START_MEMORY_LATENCIES:
+                       hwss_hubbub_perfmon_start_memory_latencies(params);
+                       break;
+               case HUBBUB_PERFMON_START_URGENT_ASSERTION_COUNT:
+                       
hwss_hubbub_perfmon_start_urgent_assertion_count(params);
+                       break;
+               case HUBBUB_PERFMON_START_URGENT_RAMP_LATENCY:
+                       hwss_hubbub_perfmon_start_urgent_ramp_latency(params);
+                       break;
+               case HUBBUB_PERFMON_START_PREFETCH_DATA_SIZE:
+                       hwss_hubbub_perfmon_start_prefetch_data_size(params);
+                       break;
+               case HUBBUB_PERFMON_GET_OUT_OF_ORDER_BW:
+                       hwss_hubbub_perfmon_get_out_of_order_bw(params);
+                       break;
+               case HUBBUB_PERFMON_GET_IN_ORDER_BW:
+                       hwss_hubbub_perfmon_get_in_order_bw(params);
+                       break;
+               case HUBBUB_PERFMON_GET_MEMORY_LATENCIES:
+                       hwss_hubbub_perfmon_get_memory_latencies(params);
+                       break;
+               case HUBBUB_PERFMON_GET_URGENT_ASSERTION_COUNT:
+                       hwss_hubbub_perfmon_get_urgent_assertion_count(params);
+                       break;
+               case HUBBUB_PERFMON_GET_PREFETCH_DATA_SIZE:
+                       hwss_hubbub_perfmon_get_prefetch_data_size(params);
+                       break;
+               case HUBBUB_PERFMON_GET_URGENT_RAMP_LATENCY:
+                       hwss_hubbub_perfmon_get_urgent_ramp_latency(params);
+                       break;
                case HUBP_CLK_CNTL:
                        hwss_hubp_clk_cntl(params);
                        break;
@@ -3251,6 +3293,139 @@ void hwss_hubbub_soft_reset(union block_sequence_params 
*params)
                params->hubbub_soft_reset_params.hubbub_soft_reset(hubbub, 
reset);
 }
 
+void hwss_hubbub_perfmon_reset(union block_sequence_params *params)
+{
+       struct hubbub *hubbub = params->hubbub_perfmon_reset_params.hubbub;
+
+       if (hubbub && hubbub->funcs->perfmon.reset)
+               hubbub->funcs->perfmon.reset(hubbub);
+}
+
+void hwss_hubbub_perfmon_arm_out_of_order_bw(union block_sequence_params 
*params)
+{
+       struct hubbub *hubbub = 
params->hubbub_perfmon_arm_out_of_order_bw_params.hubbub;
+
+       if (hubbub && 
hubbub->funcs->perfmon.arm_measuring_out_of_order_bandwidth)
+               
hubbub->funcs->perfmon.arm_measuring_out_of_order_bandwidth(hubbub);
+}
+
+void hwss_hubbub_perfmon_start_out_of_order_bw(union block_sequence_params 
*params)
+{
+       struct hubbub *hubbub = 
params->hubbub_perfmon_start_out_of_order_bw_params.hubbub;
+
+       if (hubbub && 
hubbub->funcs->perfmon.start_measuring_out_of_order_bandwidth)
+               
hubbub->funcs->perfmon.start_measuring_out_of_order_bandwidth(hubbub);
+}
+
+void hwss_hubbub_perfmon_start_in_order_bw(union block_sequence_params *params)
+{
+       struct hubbub *hubbub = 
params->hubbub_perfmon_start_in_order_bw_params.hubbub;
+
+       if (hubbub && hubbub->funcs->perfmon.start_measuring_in_order_bandwidth)
+               
hubbub->funcs->perfmon.start_measuring_in_order_bandwidth(hubbub);
+}
+
+void hwss_hubbub_perfmon_start_memory_latencies(union block_sequence_params 
*params)
+{
+       struct hubbub *hubbub = 
params->hubbub_perfmon_start_memory_latencies_params.hubbub;
+
+       if (hubbub && hubbub->funcs->perfmon.start_measuring_memory_latencies)
+               hubbub->funcs->perfmon.start_measuring_memory_latencies(hubbub);
+}
+
+void hwss_hubbub_perfmon_start_urgent_assertion_count(union 
block_sequence_params *params)
+{
+       struct hubbub *hubbub = 
params->hubbub_perfmon_start_urgent_assertion_count_params.hubbub;
+
+       if (hubbub && 
hubbub->funcs->perfmon.start_measuring_urgent_assertion_count)
+               
hubbub->funcs->perfmon.start_measuring_urgent_assertion_count(hubbub);
+}
+
+void hwss_hubbub_perfmon_start_urgent_ramp_latency(union block_sequence_params 
*params)
+{
+       struct hubbub *hubbub = 
params->hubbub_perfmon_start_urgent_ramp_latency_params.hubbub;
+
+       if (hubbub && 
hubbub->funcs->perfmon.start_measuring_urgent_ramp_latency)
+               hubbub->funcs->perfmon.start_measuring_urgent_ramp_latency(
+                               hubbub,
+                               
&params->hubbub_perfmon_start_urgent_ramp_latency_params.latency_params);
+}
+
+void hwss_hubbub_perfmon_start_prefetch_data_size(union block_sequence_params 
*params)
+{
+       struct hubbub *hubbub = 
params->hubbub_perfmon_start_prefetch_data_size_params.hubbub;
+
+       if (hubbub && hubbub->funcs->perfmon.start_measuring_prefetch_data_size)
+               
hubbub->funcs->perfmon.start_measuring_prefetch_data_size(hubbub);
+}
+
+void hwss_hubbub_perfmon_get_out_of_order_bw(union block_sequence_params 
*params)
+{
+       struct hubbub *hubbub = 
params->hubbub_perfmon_get_out_of_order_bw_params.hubbub;
+       uint32_t refclk_mhz  = 
params->hubbub_perfmon_get_out_of_order_bw_params.refclk_mhz;
+       uint32_t *mbps       = 
params->hubbub_perfmon_get_out_of_order_bw_params.bandwidth_mbps;
+       uint32_t *duration   = 
params->hubbub_perfmon_get_out_of_order_bw_params.duration_ns;
+
+       if (hubbub && hubbub->funcs->perfmon.get_out_of_order_bandwidth_mbps && 
mbps)
+               *mbps = hubbub->funcs->perfmon.get_out_of_order_bandwidth_mbps(
+                               hubbub, refclk_mhz, duration);
+}
+
+void hwss_hubbub_perfmon_get_in_order_bw(union block_sequence_params *params)
+{
+       struct hubbub *hubbub     = 
params->hubbub_perfmon_get_in_order_bw_params.hubbub;
+       uint32_t refclk_mhz       = 
params->hubbub_perfmon_get_in_order_bw_params.refclk_mhz;
+       uint32_t min_duration_ns  = 
params->hubbub_perfmon_get_in_order_bw_params.min_duration_ns;
+       uint32_t *mbps            = 
params->hubbub_perfmon_get_in_order_bw_params.bandwidth_mbps;
+       uint32_t *duration        = 
params->hubbub_perfmon_get_in_order_bw_params.duration_ns;
+
+       if (hubbub && hubbub->funcs->perfmon.get_in_order_bandwidth_mbps && 
mbps)
+               *mbps = hubbub->funcs->perfmon.get_in_order_bandwidth_mbps(
+                               hubbub, refclk_mhz, min_duration_ns, duration);
+}
+
+void hwss_hubbub_perfmon_get_memory_latencies(union block_sequence_params 
*params)
+{
+       struct hubbub *hubbub = 
params->hubbub_perfmon_get_memory_latencies_params.hubbub;
+       uint32_t refclk_mhz  = 
params->hubbub_perfmon_get_memory_latencies_params.refclk_mhz;
+       struct hubbub_system_latencies *result = 
params->hubbub_perfmon_get_memory_latencies_params.result;
+
+       if (hubbub && hubbub->funcs->perfmon.get_memory_latencies_ns && result)
+               hubbub->funcs->perfmon.get_memory_latencies_ns(
+                               hubbub, refclk_mhz, &result->min_latency_ns, 
&result->max_latency_ns, &result->avg_latency_ns);
+}
+
+void hwss_hubbub_perfmon_get_urgent_assertion_count(union 
block_sequence_params *params)
+{
+       struct hubbub *hubbub   = 
params->hubbub_perfmon_get_urgent_assertion_count_params.hubbub;
+       uint32_t refclk_mhz    = 
params->hubbub_perfmon_get_urgent_assertion_count_params.refclk_mhz;
+       uint32_t *count         = 
params->hubbub_perfmon_get_urgent_assertion_count_params.assertion_count;
+
+       if (hubbub && hubbub->funcs->perfmon.get_urgent_assertion_count)
+               hubbub->funcs->perfmon.get_urgent_assertion_count(
+                               hubbub, refclk_mhz, count, NULL, NULL);
+}
+
+void hwss_hubbub_perfmon_get_prefetch_data_size(union block_sequence_params 
*params)
+{
+       struct hubbub *hubbub     = 
params->hubbub_perfmon_get_prefetch_data_size_params.hubbub;
+       uint32_t *prefetch_size   = 
params->hubbub_perfmon_get_prefetch_data_size_params.prefetch_data_size;
+
+       if (hubbub && hubbub->funcs->perfmon.get_prefetch_data_size && 
prefetch_size)
+               *prefetch_size = 
hubbub->funcs->perfmon.get_prefetch_data_size(hubbub);
+}
+
+void hwss_hubbub_perfmon_get_urgent_ramp_latency(union block_sequence_params 
*params)
+{
+       struct hubbub *hubbub = 
params->hubbub_perfmon_get_urgent_ramp_latency_params.hubbub;
+       uint32_t refclk_mhz  = 
params->hubbub_perfmon_get_urgent_ramp_latency_params.refclk_mhz;
+       uint32_t *latency_ns = 
params->hubbub_perfmon_get_urgent_ramp_latency_params.latency_ns;
+
+       if (hubbub && hubbub->funcs->perfmon.get_urgent_ramp_latency_ns && 
latency_ns)
+               *latency_ns = hubbub->funcs->perfmon.get_urgent_ramp_latency_ns(
+                               hubbub, refclk_mhz);
+}
+
 void hwss_hubp_clk_cntl(union block_sequence_params *params)
 {
        struct hubp *hubp = params->hubp_clk_cntl_params.hubp;
@@ -4422,6 +4597,168 @@ void hwss_add_hubbub_soft_reset(struct 
block_sequence_state *seq_state,
        }
 }
 
+void hwss_add_hubbub_perfmon_reset(struct block_sequence_state *seq_state,
+               struct hubbub *hubbub)
+{
+       if (*seq_state->num_steps < MAX_HWSS_BLOCK_SEQUENCE_SIZE) {
+               seq_state->steps[*seq_state->num_steps].func = 
HUBBUB_PERFMON_RESET;
+               
seq_state->steps[*seq_state->num_steps].params.hubbub_perfmon_reset_params.hubbub
 = hubbub;
+               (*seq_state->num_steps)++;
+       }
+}
+
+void hwss_add_hubbub_perfmon_arm_out_of_order_bw(struct block_sequence_state 
*seq_state,
+               struct hubbub *hubbub)
+{
+       if (*seq_state->num_steps < MAX_HWSS_BLOCK_SEQUENCE_SIZE) {
+               seq_state->steps[*seq_state->num_steps].func = 
HUBBUB_PERFMON_ARM_OUT_OF_ORDER_BW;
+               
seq_state->steps[*seq_state->num_steps].params.hubbub_perfmon_arm_out_of_order_bw_params.hubbub
 = hubbub;
+               (*seq_state->num_steps)++;
+       }
+}
+
+void hwss_add_hubbub_perfmon_start_out_of_order_bw(struct block_sequence_state 
*seq_state,
+               struct hubbub *hubbub)
+{
+       if (*seq_state->num_steps < MAX_HWSS_BLOCK_SEQUENCE_SIZE) {
+               seq_state->steps[*seq_state->num_steps].func = 
HUBBUB_PERFMON_START_OUT_OF_ORDER_BW;
+               
seq_state->steps[*seq_state->num_steps].params.hubbub_perfmon_start_out_of_order_bw_params.hubbub
 = hubbub;
+               (*seq_state->num_steps)++;
+       }
+}
+
+void hwss_add_hubbub_perfmon_start_in_order_bw(struct block_sequence_state 
*seq_state,
+               struct hubbub *hubbub)
+{
+       if (*seq_state->num_steps < MAX_HWSS_BLOCK_SEQUENCE_SIZE) {
+               seq_state->steps[*seq_state->num_steps].func = 
HUBBUB_PERFMON_START_IN_ORDER_BW;
+               
seq_state->steps[*seq_state->num_steps].params.hubbub_perfmon_start_in_order_bw_params.hubbub
 = hubbub;
+               (*seq_state->num_steps)++;
+       }
+}
+
+void hwss_add_hubbub_perfmon_start_memory_latencies(struct 
block_sequence_state *seq_state,
+               struct hubbub *hubbub)
+{
+       if (*seq_state->num_steps < MAX_HWSS_BLOCK_SEQUENCE_SIZE) {
+               seq_state->steps[*seq_state->num_steps].func = 
HUBBUB_PERFMON_START_MEMORY_LATENCIES;
+               
seq_state->steps[*seq_state->num_steps].params.hubbub_perfmon_start_memory_latencies_params.hubbub
 = hubbub;
+               (*seq_state->num_steps)++;
+       }
+}
+
+void hwss_add_hubbub_perfmon_start_urgent_assertion_count(struct 
block_sequence_state *seq_state,
+               struct hubbub *hubbub)
+{
+       if (*seq_state->num_steps < MAX_HWSS_BLOCK_SEQUENCE_SIZE) {
+               seq_state->steps[*seq_state->num_steps].func = 
HUBBUB_PERFMON_START_URGENT_ASSERTION_COUNT;
+               
seq_state->steps[*seq_state->num_steps].params.hubbub_perfmon_start_urgent_assertion_count_params.hubbub
 = hubbub;
+               (*seq_state->num_steps)++;
+       }
+}
+
+void hwss_add_hubbub_perfmon_start_urgent_ramp_latency(struct 
block_sequence_state *seq_state,
+               struct hubbub *hubbub,
+               const struct hubbub_urgent_latency_params *latency_params)
+{
+       if (*seq_state->num_steps < MAX_HWSS_BLOCK_SEQUENCE_SIZE) {
+               seq_state->steps[*seq_state->num_steps].func = 
HUBBUB_PERFMON_START_URGENT_RAMP_LATENCY;
+               
seq_state->steps[*seq_state->num_steps].params.hubbub_perfmon_start_urgent_ramp_latency_params.hubbub
 = hubbub;
+               
seq_state->steps[*seq_state->num_steps].params.hubbub_perfmon_start_urgent_ramp_latency_params.latency_params
 =
+                               *latency_params;
+               (*seq_state->num_steps)++;
+       }
+}
+
+void hwss_add_hubbub_perfmon_start_prefetch_data_size(struct 
block_sequence_state *seq_state,
+               struct hubbub *hubbub)
+{
+       if (*seq_state->num_steps < MAX_HWSS_BLOCK_SEQUENCE_SIZE) {
+               seq_state->steps[*seq_state->num_steps].func = 
HUBBUB_PERFMON_START_PREFETCH_DATA_SIZE;
+               
seq_state->steps[*seq_state->num_steps].params.hubbub_perfmon_start_prefetch_data_size_params.hubbub
 = hubbub;
+               (*seq_state->num_steps)++;
+       }
+}
+
+void hwss_add_hubbub_perfmon_get_out_of_order_bw(struct block_sequence_state 
*seq_state,
+               struct hubbub *hubbub, uint32_t refclk_mhz,
+               uint32_t *bandwidth_mbps, uint32_t *duration_ns)
+{
+       if (*seq_state->num_steps < MAX_HWSS_BLOCK_SEQUENCE_SIZE) {
+               seq_state->steps[*seq_state->num_steps].func = 
HUBBUB_PERFMON_GET_OUT_OF_ORDER_BW;
+               
seq_state->steps[*seq_state->num_steps].params.hubbub_perfmon_get_out_of_order_bw_params.hubbub
 = hubbub;
+               
seq_state->steps[*seq_state->num_steps].params.hubbub_perfmon_get_out_of_order_bw_params.refclk_mhz
 = refclk_mhz;
+               
seq_state->steps[*seq_state->num_steps].params.hubbub_perfmon_get_out_of_order_bw_params.bandwidth_mbps
 = bandwidth_mbps;
+               
seq_state->steps[*seq_state->num_steps].params.hubbub_perfmon_get_out_of_order_bw_params.duration_ns
 = duration_ns;
+               (*seq_state->num_steps)++;
+       }
+}
+
+void hwss_add_hubbub_perfmon_get_in_order_bw(struct block_sequence_state 
*seq_state,
+               struct hubbub *hubbub, uint32_t refclk_mhz, uint32_t 
min_duration_ns,
+               uint32_t *bandwidth_mbps, uint32_t *duration_ns)
+{
+       if (*seq_state->num_steps < MAX_HWSS_BLOCK_SEQUENCE_SIZE) {
+               seq_state->steps[*seq_state->num_steps].func = 
HUBBUB_PERFMON_GET_IN_ORDER_BW;
+               
seq_state->steps[*seq_state->num_steps].params.hubbub_perfmon_get_in_order_bw_params.hubbub
 = hubbub;
+               
seq_state->steps[*seq_state->num_steps].params.hubbub_perfmon_get_in_order_bw_params.refclk_mhz
 = refclk_mhz;
+               
seq_state->steps[*seq_state->num_steps].params.hubbub_perfmon_get_in_order_bw_params.min_duration_ns
 = min_duration_ns;
+               
seq_state->steps[*seq_state->num_steps].params.hubbub_perfmon_get_in_order_bw_params.bandwidth_mbps
 = bandwidth_mbps;
+               
seq_state->steps[*seq_state->num_steps].params.hubbub_perfmon_get_in_order_bw_params.duration_ns
 = duration_ns;
+               (*seq_state->num_steps)++;
+       }
+}
+
+void hwss_add_hubbub_perfmon_get_memory_latencies(struct block_sequence_state 
*seq_state,
+               struct hubbub *hubbub, uint32_t refclk_mhz,
+               struct hubbub_system_latencies *result)
+{
+       if (*seq_state->num_steps < MAX_HWSS_BLOCK_SEQUENCE_SIZE) {
+               seq_state->steps[*seq_state->num_steps].func = 
HUBBUB_PERFMON_GET_MEMORY_LATENCIES;
+               
seq_state->steps[*seq_state->num_steps].params.hubbub_perfmon_get_memory_latencies_params.hubbub
 = hubbub;
+               
seq_state->steps[*seq_state->num_steps].params.hubbub_perfmon_get_memory_latencies_params.refclk_mhz
 = refclk_mhz;
+               
seq_state->steps[*seq_state->num_steps].params.hubbub_perfmon_get_memory_latencies_params.result
 = result;
+               (*seq_state->num_steps)++;
+       }
+}
+
+void hwss_add_hubbub_perfmon_get_urgent_assertion_count(struct 
block_sequence_state *seq_state,
+               struct hubbub *hubbub, uint32_t refclk_mhz,
+               uint32_t *assertion_count)
+{
+       if (*seq_state->num_steps < MAX_HWSS_BLOCK_SEQUENCE_SIZE) {
+               seq_state->steps[*seq_state->num_steps].func = 
HUBBUB_PERFMON_GET_URGENT_ASSERTION_COUNT;
+               
seq_state->steps[*seq_state->num_steps].params.hubbub_perfmon_get_urgent_assertion_count_params.hubbub
 = hubbub;
+               
seq_state->steps[*seq_state->num_steps].params.hubbub_perfmon_get_urgent_assertion_count_params.refclk_mhz
 = refclk_mhz;
+               
seq_state->steps[*seq_state->num_steps].params.hubbub_perfmon_get_urgent_assertion_count_params.assertion_count
 = assertion_count;
+               (*seq_state->num_steps)++;
+       }
+}
+
+void hwss_add_hubbub_perfmon_get_prefetch_data_size(struct 
block_sequence_state *seq_state,
+               struct hubbub *hubbub, uint32_t *prefetch_data_size)
+{
+       if (*seq_state->num_steps < MAX_HWSS_BLOCK_SEQUENCE_SIZE) {
+               seq_state->steps[*seq_state->num_steps].func = 
HUBBUB_PERFMON_GET_PREFETCH_DATA_SIZE;
+               
seq_state->steps[*seq_state->num_steps].params.hubbub_perfmon_get_prefetch_data_size_params.hubbub
 = hubbub;
+               
seq_state->steps[*seq_state->num_steps].params.hubbub_perfmon_get_prefetch_data_size_params.prefetch_data_size
 = prefetch_data_size;
+               (*seq_state->num_steps)++;
+       }
+}
+
+void hwss_add_hubbub_perfmon_get_urgent_ramp_latency(struct 
block_sequence_state *seq_state,
+               struct hubbub *hubbub, uint32_t refclk_mhz,
+               uint32_t *latency_ns)
+{
+       if (*seq_state->num_steps < MAX_HWSS_BLOCK_SEQUENCE_SIZE) {
+               seq_state->steps[*seq_state->num_steps].func = 
HUBBUB_PERFMON_GET_URGENT_RAMP_LATENCY;
+               
seq_state->steps[*seq_state->num_steps].params.hubbub_perfmon_get_urgent_ramp_latency_params.hubbub
 = hubbub;
+               
seq_state->steps[*seq_state->num_steps].params.hubbub_perfmon_get_urgent_ramp_latency_params.refclk_mhz
 = refclk_mhz;
+               
seq_state->steps[*seq_state->num_steps].params.hubbub_perfmon_get_urgent_ramp_latency_params.latency_ns
 = latency_ns;
+               (*seq_state->num_steps)++;
+       }
+}
+
 void hwss_add_hubp_clk_cntl(struct block_sequence_state *seq_state,
                struct hubp *hubp,
                bool enable)
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_state.c 
b/drivers/gpu/drm/amd/display/dc/core/dc_state.c
index 03cb40e94d58..a62a435054c6 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_state.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_state.c
@@ -362,6 +362,7 @@ void dc_state_destruct(struct dc_state *state)
        state->phantom_plane_count = 0;
 
        memset(state->probes, 0, sizeof(state->probes));
+       memset(state->probe_status, 0, sizeof(state->probe_status));
        state->probe_count = 0;
 
        state->stream_mask = 0;
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h 
b/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h
index e8bf96a7d63a..6754da1e6ee2 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h
+++ b/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h
@@ -32,6 +32,7 @@
 #include "inc/hw/link_encoder.h"
 #include "inc/core_status.h"
 #include "inc/hw/hw_shared.h"
+#include "inc/hw/dchubbub.h"
 #include "dsc/dsc.h"
 #include "link_service_types.h"
 
@@ -53,7 +54,6 @@ struct drr_params;
 struct dc_underflow_debug_data;
 struct dsc_optc_config;
 struct vm_system_aperture_param;
-struct dc_measured_memory_qos;
 struct stream_encoder;
 struct hpo_dp_stream_encoder;
 struct hpo_frl_stream_encoder;
@@ -580,6 +580,77 @@ struct hubbub_soft_reset_params {
        bool reset;
 };
 
+struct hubbub_perfmon_reset_params {
+       struct hubbub *hubbub;
+};
+
+struct hubbub_perfmon_arm_out_of_order_bw_params {
+       struct hubbub *hubbub;
+};
+
+struct hubbub_perfmon_start_out_of_order_bw_params {
+       struct hubbub *hubbub;
+};
+
+struct hubbub_perfmon_start_in_order_bw_params {
+       struct hubbub *hubbub;
+};
+
+struct hubbub_perfmon_start_memory_latencies_params {
+       struct hubbub *hubbub;
+};
+
+struct hubbub_perfmon_start_urgent_assertion_count_params {
+       struct hubbub *hubbub;
+};
+
+struct hubbub_perfmon_start_urgent_ramp_latency_params {
+       struct hubbub *hubbub;
+       struct hubbub_urgent_latency_params latency_params;
+};
+
+struct hubbub_perfmon_start_prefetch_data_size_params {
+       struct hubbub *hubbub;
+};
+
+struct hubbub_perfmon_get_out_of_order_bw_params {
+       struct hubbub *hubbub;
+       uint32_t       refclk_mhz;
+       uint32_t      *bandwidth_mbps;
+       uint32_t      *duration_ns;
+};
+
+struct hubbub_perfmon_get_in_order_bw_params {
+       struct hubbub *hubbub;
+       uint32_t       refclk_mhz;
+       uint32_t       min_duration_ns;
+       uint32_t      *bandwidth_mbps;
+       uint32_t      *duration_ns;
+};
+
+struct hubbub_perfmon_get_memory_latencies_params {
+       struct hubbub                        *hubbub;
+       uint32_t                              refclk_mhz;
+       struct hubbub_system_latencies       *result;
+};
+
+struct hubbub_perfmon_get_urgent_assertion_count_params {
+       struct hubbub *hubbub;
+       uint32_t       refclk_mhz;
+       uint32_t      *assertion_count;
+};
+
+struct hubbub_perfmon_get_prefetch_data_size_params {
+       struct hubbub *hubbub;
+       uint32_t      *prefetch_data_size;
+};
+
+struct hubbub_perfmon_get_urgent_ramp_latency_params {
+       struct hubbub *hubbub;
+       uint32_t       refclk_mhz;
+       uint32_t      *latency_ns;
+};
+
 struct hubp_clk_cntl_params {
        struct hubp *hubp;
        bool enable;
@@ -1031,6 +1102,20 @@ union block_sequence_params {
        struct hubp_set_blank_en_params hubp_set_blank_en_params;
        struct hubp_disable_control_params hubp_disable_control_params;
        struct hubbub_soft_reset_params hubbub_soft_reset_params;
+       struct hubbub_perfmon_reset_params hubbub_perfmon_reset_params;
+       struct hubbub_perfmon_arm_out_of_order_bw_params 
hubbub_perfmon_arm_out_of_order_bw_params;
+       struct hubbub_perfmon_start_out_of_order_bw_params 
hubbub_perfmon_start_out_of_order_bw_params;
+       struct hubbub_perfmon_start_in_order_bw_params 
hubbub_perfmon_start_in_order_bw_params;
+       struct hubbub_perfmon_start_memory_latencies_params 
hubbub_perfmon_start_memory_latencies_params;
+       struct hubbub_perfmon_start_urgent_assertion_count_params 
hubbub_perfmon_start_urgent_assertion_count_params;
+       struct hubbub_perfmon_start_urgent_ramp_latency_params 
hubbub_perfmon_start_urgent_ramp_latency_params;
+       struct hubbub_perfmon_start_prefetch_data_size_params 
hubbub_perfmon_start_prefetch_data_size_params;
+       struct hubbub_perfmon_get_out_of_order_bw_params 
hubbub_perfmon_get_out_of_order_bw_params;
+       struct hubbub_perfmon_get_in_order_bw_params 
hubbub_perfmon_get_in_order_bw_params;
+       struct hubbub_perfmon_get_memory_latencies_params 
hubbub_perfmon_get_memory_latencies_params;
+       struct hubbub_perfmon_get_urgent_assertion_count_params 
hubbub_perfmon_get_urgent_assertion_count_params;
+       struct hubbub_perfmon_get_prefetch_data_size_params 
hubbub_perfmon_get_prefetch_data_size_params;
+       struct hubbub_perfmon_get_urgent_ramp_latency_params 
hubbub_perfmon_get_urgent_ramp_latency_params;
        struct hubp_clk_cntl_params hubp_clk_cntl_params;
        struct hubp_init_params hubp_init_params;
        struct hubp_set_vm_system_aperture_settings_params 
hubp_set_vm_system_aperture_settings_params;
@@ -1258,6 +1343,20 @@ enum block_sequence_func {
        HUBBUB_PROGRAM_WATERMARKS,
        HUBBUB_PROGRAM_ARBITER,
        HUBBUB_PROGRAM_COMPBUF_SEGMENTS,
+       HUBBUB_PERFMON_RESET,
+       HUBBUB_PERFMON_ARM_OUT_OF_ORDER_BW,
+       HUBBUB_PERFMON_START_OUT_OF_ORDER_BW,
+       HUBBUB_PERFMON_START_IN_ORDER_BW,
+       HUBBUB_PERFMON_START_MEMORY_LATENCIES,
+       HUBBUB_PERFMON_START_URGENT_ASSERTION_COUNT,
+       HUBBUB_PERFMON_START_URGENT_RAMP_LATENCY,
+       HUBBUB_PERFMON_START_PREFETCH_DATA_SIZE,
+       HUBBUB_PERFMON_GET_OUT_OF_ORDER_BW,
+       HUBBUB_PERFMON_GET_IN_ORDER_BW,
+       HUBBUB_PERFMON_GET_MEMORY_LATENCIES,
+       HUBBUB_PERFMON_GET_URGENT_ASSERTION_COUNT,
+       HUBBUB_PERFMON_GET_PREFETCH_DATA_SIZE,
+       HUBBUB_PERFMON_GET_URGENT_RAMP_LATENCY,
        /* This must be the last value in this enum, add new ones above */
        HWSS_BLOCK_SEQUENCE_FUNC_COUNT
 };
@@ -1591,14 +1690,16 @@ struct hw_sequencer_funcs {
                        struct dc_underflow_debug_data *out_data);
 
        /**
-        * measure_memory_qos - Measure memory QoS metrics
-        * @dc: DC structure
-        * @qos: Pointer to dc_measured_memory_qos struct to populate with 
measured values
+        * program_perfmon - Program/transition perfmon probes for a commit.
+        * @dc:      DC structure
+        * @context: target state; probes, probe_count, and probe_status are
+        *           read from and written to this object
         *
-        * Populates the provided dc_measured_memory_qos struct with peak 
bandwidth, average bandwidth,
-        * max latency, min latency, and average latency from hardware 
performance counters.
+        * Invoked during the execute phase of dc_update_state. The hook 
resolves
+        * each probe's transition by diffing @context against dc->current_state
+        * and latches MEASURED results into @context->probe_status.
         */
-       void (*measure_memory_qos)(struct dc *dc, struct dc_measured_memory_qos 
*qos);
+       void (*program_perfmon)(struct dc *dc, struct dc_state *context);
 
 };
 
@@ -1875,6 +1976,34 @@ void hwss_hubp_disable_control(union 
block_sequence_params *params);
 
 void hwss_hubbub_soft_reset(union block_sequence_params *params);
 
+void hwss_hubbub_perfmon_reset(union block_sequence_params *params);
+
+void hwss_hubbub_perfmon_arm_out_of_order_bw(union block_sequence_params 
*params);
+
+void hwss_hubbub_perfmon_start_out_of_order_bw(union block_sequence_params 
*params);
+
+void hwss_hubbub_perfmon_start_in_order_bw(union block_sequence_params 
*params);
+
+void hwss_hubbub_perfmon_start_memory_latencies(union block_sequence_params 
*params);
+
+void hwss_hubbub_perfmon_start_urgent_assertion_count(union 
block_sequence_params *params);
+
+void hwss_hubbub_perfmon_start_urgent_ramp_latency(union block_sequence_params 
*params);
+
+void hwss_hubbub_perfmon_start_prefetch_data_size(union block_sequence_params 
*params);
+
+void hwss_hubbub_perfmon_get_out_of_order_bw(union block_sequence_params 
*params);
+
+void hwss_hubbub_perfmon_get_in_order_bw(union block_sequence_params *params);
+
+void hwss_hubbub_perfmon_get_memory_latencies(union block_sequence_params 
*params);
+
+void hwss_hubbub_perfmon_get_urgent_assertion_count(union 
block_sequence_params *params);
+
+void hwss_hubbub_perfmon_get_prefetch_data_size(union block_sequence_params 
*params);
+
+void hwss_hubbub_perfmon_get_urgent_ramp_latency(union block_sequence_params 
*params);
+
 void hwss_hubp_clk_cntl(union block_sequence_params *params);
 
 void hwss_hubp_init(union block_sequence_params *params);
@@ -2213,6 +2342,54 @@ void hwss_add_hubbub_soft_reset(struct 
block_sequence_state *seq_state,
                void (*hubbub_soft_reset)(struct hubbub *hubbub, bool reset),
                bool reset);
 
+void hwss_add_hubbub_perfmon_reset(struct block_sequence_state *seq_state,
+               struct hubbub *hubbub);
+
+void hwss_add_hubbub_perfmon_arm_out_of_order_bw(struct block_sequence_state 
*seq_state,
+               struct hubbub *hubbub);
+
+void hwss_add_hubbub_perfmon_start_out_of_order_bw(struct block_sequence_state 
*seq_state,
+               struct hubbub *hubbub);
+
+void hwss_add_hubbub_perfmon_start_in_order_bw(struct block_sequence_state 
*seq_state,
+               struct hubbub *hubbub);
+
+void hwss_add_hubbub_perfmon_start_memory_latencies(struct 
block_sequence_state *seq_state,
+               struct hubbub *hubbub);
+
+void hwss_add_hubbub_perfmon_start_urgent_assertion_count(struct 
block_sequence_state *seq_state,
+               struct hubbub *hubbub);
+
+void hwss_add_hubbub_perfmon_start_urgent_ramp_latency(struct 
block_sequence_state *seq_state,
+               struct hubbub *hubbub,
+               const struct hubbub_urgent_latency_params *latency_params);
+
+void hwss_add_hubbub_perfmon_start_prefetch_data_size(struct 
block_sequence_state *seq_state,
+               struct hubbub *hubbub);
+
+void hwss_add_hubbub_perfmon_get_out_of_order_bw(struct block_sequence_state 
*seq_state,
+               struct hubbub *hubbub, uint32_t refclk_mhz,
+               uint32_t *bandwidth_mbps, uint32_t *duration_ns);
+
+void hwss_add_hubbub_perfmon_get_in_order_bw(struct block_sequence_state 
*seq_state,
+               struct hubbub *hubbub, uint32_t refclk_mhz, uint32_t 
min_duration_ns,
+               uint32_t *bandwidth_mbps, uint32_t *duration_ns);
+
+void hwss_add_hubbub_perfmon_get_memory_latencies(struct block_sequence_state 
*seq_state,
+               struct hubbub *hubbub, uint32_t refclk_mhz,
+               struct hubbub_system_latencies *result);
+
+void hwss_add_hubbub_perfmon_get_urgent_assertion_count(struct 
block_sequence_state *seq_state,
+               struct hubbub *hubbub, uint32_t refclk_mhz,
+               uint32_t *assertion_count);
+
+void hwss_add_hubbub_perfmon_get_prefetch_data_size(struct 
block_sequence_state *seq_state,
+               struct hubbub *hubbub, uint32_t *prefetch_data_size);
+
+void hwss_add_hubbub_perfmon_get_urgent_ramp_latency(struct 
block_sequence_state *seq_state,
+               struct hubbub *hubbub, uint32_t refclk_mhz,
+               uint32_t *latency_ns);
+
 void hwss_add_hubp_clk_cntl(struct block_sequence_state *seq_state,
                struct hubp *hubp,
                bool enable);
diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h 
b/drivers/gpu/drm/amd/display/dc/inc/core_types.h
index c42626101cd7..ac3e9eaa569c 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h
@@ -33,6 +33,7 @@
 #include "dc_bios_types.h"
 #include "mem_input.h"
 #include "hubp.h"
+#include "hw/dchubbub.h"
 #include "mpc.h"
 #include "dwb.h"
 #include "hw/dio.h"
@@ -609,6 +610,27 @@ struct dc_dmub_cmd {
        enum dm_dmub_wait_type wait_type;
 };
 
+/**
+ * struct dc_probe_status - DC-internal latched perfmon results for a probe.
+ * @valid: true if a measurement was latched this commit.
+ * @type: type of the probe that produced this result.
+ * @u.bandwidth_mbps:         peak BW in Mbps (DC_PROBE_PEAK_MEM_BW).
+ * @u.latency:                min/max/avg memory latency in ns 
(DC_PROBE_MEM_LATENCY),
+ *                            stored as struct hubbub_system_latencies.
+ * @u.urgent_assertion_count: number of urgent assertion events 
(DC_PROBE_URGENT_ASSERTION_COUNT).
+ * @u.prefetch_data_size:     total prefetch data in bytes 
(DC_PROBE_PREFETCH_DATA_SIZE).
+ */
+struct dc_probe_status {
+       bool                       valid;
+       enum dc_probe_type         type;
+       union {
+               uint32_t bandwidth_mbps;
+               struct hubbub_system_latencies latency;
+               uint32_t urgent_assertion_count;
+               uint32_t prefetch_data_size;
+       } u;
+};
+
 /**
  * struct dc_state - The full description of a state requested by users
  */
@@ -652,6 +674,11 @@ struct dc_state {
         */
        struct dc_probe_state probes[MAX_PROBES];
 
+       /**
+        * @probe_status: Committed absolute set of probe results.
+        */
+       struct dc_probe_status probe_status[MAX_PROBES];
+
        /**
         * @probe_count: Number of valid entries in @probes.
         */
diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/dchubbub.h 
b/drivers/gpu/drm/amd/display/dc/inc/hw/dchubbub.h
index 4307362749f0..fd742b320128 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/hw/dchubbub.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/hw/dchubbub.h
@@ -158,6 +158,12 @@ struct hubbub_urgent_latency_params {
        uint32_t bw_factor_x1000;
 };
 
+struct hubbub;
+struct dchub_init_data;
+struct dc_dcc_surface_param;
+struct dc_surface_dcc_cap;
+union dcn_watermark_set;
+struct dml2_display_arb_regs;
 struct hubbub_funcs {
        void (*update_dchub)(
                        struct hubbub *hubbub,
@@ -274,9 +280,11 @@ struct hubbub_funcs {
                                const struct hubbub_urgent_latency_params 
*params);
                uint32_t (*get_urgent_ramp_latency_ns)(struct hubbub *hubbub,
                                uint32_t refclk_mhz);
-               void (*start_measuring_unbounded_bandwidth)(
+               void (*arm_measuring_out_of_order_bandwidth)(
                                struct hubbub *hubbub);
-               uint32_t (*get_unbounded_bandwidth_mbps)(struct hubbub *hubbub,
+               void (*start_measuring_out_of_order_bandwidth)(
+                               struct hubbub *hubbub);
+               uint32_t (*get_out_of_order_bandwidth_mbps)(struct hubbub 
*hubbub,
                                uint32_t refclk_mhz, uint32_t *duration_ns);
                void (*start_measuring_in_order_bandwidth)(
                                struct hubbub *hubbub);
-- 
2.43.0

Reply via email to