From: TungYu Lu tungyu.lu@amd.com
[ Upstream commit 33bc89949b4366dff2dca30bc61ba1c0cbcd2ab2 ]
[Why] The minimum value of the dst_y_prefetch_equ was not correct in prefetch calculation whice causes OPTC underflow.
[How] Add the min operation of dst_y_prefetch_equ in prefetch calculation for legacy DML.
Reviewed-by: Nicholas Kazlauskas nicholas.kazlauskas@amd.com Signed-off-by: TungYu Lu tungyu.lu@amd.com Signed-off-by: Zaeem Mohamed zaeem.mohamed@amd.com Tested-by: Mark Broadworth mark.broadworth@amd.com Signed-off-by: Alex Deucher alexander.deucher@amd.com Signed-off-by: Sasha Levin sashal@kernel.org ---
**YES** ## Analysis This commit should be backported to stable kernel trees. Here's my detailed analysis: ### **Bug Description and Impact** The commit fixes a critical hardware register overflow issue in AMD display's prefetch calculation that causes OPTC (Output Pipe and Timing Control) underflow. OPTC underflow is a serious display issue that can cause: - Screen corruption or artifacts - Display timing problems - Potential system instability during display operations ### **Code Change Analysis** The fix adds a single line in three DCN (Display Core Next) versions (30, 31, 314): ```c dst_y_prefetch_equ = dml_min(dst_y_prefetch_equ, 63.75); // limit to the reg limit of U6.2 for DST_Y_PREFETCH ``` This change: 1. **Prevents register overflow**: The DST_Y_PREFETCH register is limited to 8 bits with U6.2 format, meaning maximum value is 63.75 2. **Applies early in calculation**: The limit is applied to `dst_y_prefetch_equ` before it's used in subsequent calculations 3. **Matches existing pattern**: DCN21 already has this exact fix (commit 9857bb9457fe5 from 2021), establishing this as a known, proven solution ### **Why This Should Be Backported** 1. **Important Bug Fix**: Fixes a hardware register overflow that causes visible display issues affecting end users 2. **Minimal Risk**: - Single line addition in each file - No architectural changes - Simply enforces hardware register limits that should have been there - Proven safe (already in DCN21 for 3+ years) 3. **Contained Scope**: Only affects AMD display prefetch calculations in legacy DML (Display Mode Library) versions 4. **Clear User Impact**: OPTC underflow causes noticeable display problems that users would report 5. **Follows Stable Criteria**: - Small, obvious fix - Addresses hardware limitation - Low regression risk - Similar to reference commits marked "YES" for backporting ### **Comparison with Similar Commits** Looking at the provided examples: - **Similar Commit #1** (YES): Also fixes prefetch calculation with min operation and has `Cc: stable@vger.kernel.org` - **Similar Commit #2** (YES): Fixes prefetch calculation loop variables and explicitly tagged for stable backport - **Similar Commit #4** (NO): Same type of DST_Y_PREFETCH guard fix but wasn't tagged for stable The pattern shows that prefetch calculation fixes that prevent register overflow and have clear user impact are good backport candidates. ### **Hardware Context** This affects DCN 3.0, 3.1, and 3.14 hardware generations. The fact that DCN 2.1 already had this fix suggests this was a systematic issue across multiple hardware generations that needed addressing. The fix is essential for proper display functionality and represents a critical hardware constraint that must be enforced to prevent register overflow and subsequent display corruption.
drivers/gpu/drm/amd/display/dc/dml/dcn30/display_mode_vba_30.c | 1 + drivers/gpu/drm/amd/display/dc/dml/dcn31/display_mode_vba_31.c | 1 + drivers/gpu/drm/amd/display/dc/dml/dcn314/display_mode_vba_314.c | 1 + 3 files changed, 3 insertions(+)
diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_mode_vba_30.c b/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_mode_vba_30.c index 72ffa1abebaa1..d799ae7a9048d 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_mode_vba_30.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_mode_vba_30.c @@ -1002,6 +1002,7 @@ static bool CalculatePrefetchSchedule(
dst_y_prefetch_equ = VStartup - (Tsetup + dml_max(TWait + TCalc, *Tdmdl)) / LineTime - (*DSTYAfterScaler + *DSTXAfterScaler / myPipe->HTotal); + dst_y_prefetch_equ = dml_min(dst_y_prefetch_equ, 63.75); // limit to the reg limit of U6.2 for DST_Y_PREFETCH
Lsw_oto = dml_max(PrefetchSourceLinesY, PrefetchSourceLinesC); Tsw_oto = Lsw_oto * LineTime; diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn31/display_mode_vba_31.c b/drivers/gpu/drm/amd/display/dc/dml/dcn31/display_mode_vba_31.c index adea459e7d363..338a295c464dc 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn31/display_mode_vba_31.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn31/display_mode_vba_31.c @@ -1105,6 +1105,7 @@ static bool CalculatePrefetchSchedule( Tr0_oto_lines = dml_ceil(4.0 * Tr0_oto / LineTime, 1) / 4.0; dst_y_prefetch_oto = Tvm_oto_lines + 2 * Tr0_oto_lines + Lsw_oto; dst_y_prefetch_equ = VStartup - (*TSetup + dml_max(TWait + TCalc, *Tdmdl)) / LineTime - (*DSTYAfterScaler + *DSTXAfterScaler / myPipe->HTotal); + dst_y_prefetch_equ = dml_min(dst_y_prefetch_equ, 63.75); // limit to the reg limit of U6.2 for DST_Y_PREFETCH dst_y_prefetch_equ = dml_floor(4.0 * (dst_y_prefetch_equ + 0.125), 1) / 4.0; Tpre_rounded = dst_y_prefetch_equ * LineTime;
diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn314/display_mode_vba_314.c b/drivers/gpu/drm/amd/display/dc/dml/dcn314/display_mode_vba_314.c index a94aa0f21a7f4..06cb11bc60905 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn314/display_mode_vba_314.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn314/display_mode_vba_314.c @@ -1126,6 +1126,7 @@ static bool CalculatePrefetchSchedule( Tr0_oto_lines = dml_ceil(4.0 * Tr0_oto / LineTime, 1) / 4.0; dst_y_prefetch_oto = Tvm_oto_lines + 2 * Tr0_oto_lines + Lsw_oto; dst_y_prefetch_equ = VStartup - (*TSetup + dml_max(TWait + TCalc, *Tdmdl)) / LineTime - (*DSTYAfterScaler + *DSTXAfterScaler / myPipe->HTotal); + dst_y_prefetch_equ = dml_min(dst_y_prefetch_equ, 63.75); // limit to the reg limit of U6.2 for DST_Y_PREFETCH dst_y_prefetch_equ = dml_floor(4.0 * (dst_y_prefetch_equ + 0.125), 1) / 4.0; Tpre_rounded = dst_y_prefetch_equ * LineTime;