From 7f035f99c3f5afb3cc8b99399e18120d054495a5 Mon Sep 17 00:00:00 2001 From: Ovidiu Bunea Date: Fri, 18 Sep 2026 10:24:59 -0400 Subject: [PATCH] drm/amd/display: Add urgent watermark override for DCN42 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [why & how] Out-of-urgent bandwidth delivery to DCN is very poor under workloads. Even after asserting urgent, empirical data shows urgent return BW delays of up to 100 μs. Override the value when programming watermarks to avoid modifying mode support. Maintain the DML's calculated value as a floor. Signed-off-by: Ovidiu Bunea Signed-off-by: Fangzhi Zuo Reviewed-by: Nicholas Kazlauskas Tested-by: Dan Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 1 + .../display/dc/hubbub/dcn42/dcn42_hubbub.c | 41 +++++++++++-------- 2 files changed, 26 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index bd515c2cfce1..9b5a1846e33a 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -1314,6 +1314,7 @@ struct dc_debug_options { unsigned int auxless_alpm_lfps_t1t2_us; short auxless_alpm_lfps_t1t2_offset_us; bool disable_stutter_for_wm_program; + unsigned int urgent_watermark_override; bool enable_block_sequence_programming; uint32_t custom_psp_footer_size; bool disable_deferred_minimal_transitions; diff --git a/drivers/gpu/drm/amd/display/dc/hubbub/dcn42/dcn42_hubbub.c b/drivers/gpu/drm/amd/display/dc/hubbub/dcn42/dcn42_hubbub.c index 036276c17562..244f3f2824ed 100644 --- a/drivers/gpu/drm/amd/display/dc/hubbub/dcn42/dcn42_hubbub.c +++ b/drivers/gpu/drm/amd/display/dc/hubbub/dcn42/dcn42_hubbub.c @@ -30,15 +30,24 @@ static bool hubbub42_program_urgent_watermarks( bool safe_to_lower) { struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub); + const unsigned int urgent_floor = hubbub->ctx->dc->debug.urgent_watermark_override; + const unsigned int urgent_a = max(urgent_floor, + watermarks->dcn4x.a.urgent); + const unsigned int urgent_b = max(urgent_floor, + watermarks->dcn4x.b.urgent); + const unsigned int urgent_c = max(urgent_floor, + watermarks->dcn4x.c.urgent); + const unsigned int urgent_d = max(urgent_floor, + watermarks->dcn4x.d.urgent); bool wm_pending = false; /* Repeat for water mark set A, B, C and D. */ /* clock state A */ - if (safe_to_lower || watermarks->dcn4x.a.urgent > hubbub2->watermarks.dcn4x.a.urgent) { - hubbub2->watermarks.dcn4x.a.urgent = watermarks->dcn4x.a.urgent; + if (safe_to_lower || urgent_a > hubbub2->watermarks.dcn4x.a.urgent) { + hubbub2->watermarks.dcn4x.a.urgent = urgent_a; REG_SET(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A, 0, - DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A, watermarks->dcn4x.a.urgent); - } else if (watermarks->dcn4x.a.urgent < hubbub2->watermarks.dcn4x.a.urgent) + DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A, urgent_a); + } else if (urgent_a < hubbub2->watermarks.dcn4x.a.urgent) wm_pending = true; /* determine the transfer time for a quantity of data for a particular requestor.*/ @@ -64,11 +73,11 @@ static bool hubbub42_program_urgent_watermarks( wm_pending = true; /* clock state B */ - if (safe_to_lower || watermarks->dcn4x.b.urgent > hubbub2->watermarks.dcn4x.b.urgent) { - hubbub2->watermarks.dcn4x.b.urgent = watermarks->dcn4x.b.urgent; + if (safe_to_lower || urgent_b > hubbub2->watermarks.dcn4x.b.urgent) { + hubbub2->watermarks.dcn4x.b.urgent = urgent_b; REG_SET(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B, 0, - DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B, watermarks->dcn4x.b.urgent); - } else if (watermarks->dcn4x.b.urgent < hubbub2->watermarks.dcn4x.b.urgent) + DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B, urgent_b); + } else if (urgent_b < hubbub2->watermarks.dcn4x.b.urgent) wm_pending = true; /* determine the transfer time for a quantity of data for a particular requestor.*/ @@ -94,11 +103,11 @@ static bool hubbub42_program_urgent_watermarks( wm_pending = true; /* clock state C */ - if (safe_to_lower || watermarks->dcn4x.c.urgent > hubbub2->watermarks.dcn4x.c.urgent) { - hubbub2->watermarks.dcn4x.c.urgent = watermarks->dcn4x.c.urgent; + if (safe_to_lower || urgent_c > hubbub2->watermarks.dcn4x.c.urgent) { + hubbub2->watermarks.dcn4x.c.urgent = urgent_c; REG_SET(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C, 0, - DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C, watermarks->dcn4x.c.urgent); - } else if (watermarks->dcn4x.c.urgent < hubbub2->watermarks.dcn4x.c.urgent) + DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C, urgent_c); + } else if (urgent_c < hubbub2->watermarks.dcn4x.c.urgent) wm_pending = true; /* determine the transfer time for a quantity of data for a particular requestor.*/ @@ -124,11 +133,11 @@ static bool hubbub42_program_urgent_watermarks( wm_pending = true; /* clock state D */ - if (safe_to_lower || watermarks->dcn4x.d.urgent > hubbub2->watermarks.dcn4x.d.urgent) { - hubbub2->watermarks.dcn4x.d.urgent = watermarks->dcn4x.d.urgent; + if (safe_to_lower || urgent_d > hubbub2->watermarks.dcn4x.d.urgent) { + hubbub2->watermarks.dcn4x.d.urgent = urgent_d; REG_SET(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D, 0, - DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D, watermarks->dcn4x.d.urgent); - } else if (watermarks->dcn4x.d.urgent < hubbub2->watermarks.dcn4x.d.urgent) + DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D, urgent_d); + } else if (urgent_d < hubbub2->watermarks.dcn4x.d.urgent) wm_pending = true; /* determine the transfer time for a quantity of data for a particular requestor.*/