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, + ¶ms->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
