From: James Lin <[email protected]>

[Why]
The cursor-mode re-evaluation added to dm_crtc_get_cursor_mode() also
checks the cursor plane's own destination rectangle. The crtc_x/y/w/h
check lives in the per-plane loop, which only flags the cursor plane via
cursor_changed and does not skip it, so the check fires whenever the
cursor itself moves.

flip-vs-cursor-legacy (kms_cursor_legacy) issues a stream of legacy
cursor moves and requires each to land on the fast path within a single
vblank. With the position check, every cursor move now sets
consider_mode_change and defeats the early return, forcing the full
cursor-mode evaluation. A legacy cursor move is a cursor-only commit:
the underlying planes are not in the atomic state, so the coverage loop
(for_each_oldnew_plane_in_descending_zpos walks only planes in the
state) sees nothing covering the CRTC, evaluates entire_crtc_covered as
false, and misclassifies the cursor mode as OVERLAY on a fully-covered
screen.

That spurious NATIVE->OVERLAY transition makes should_reset_plane()
return true (lock_and_validation_needed), pulls all CRTC planes into the
commit, and - because amdgpu_dm_plane_atomic_async_check() rejects async
updates in overlay mode - permanently knocks later cursor updates off the
async fast path. Each cursor move becomes a full atomic commit with DC
global validation, serialized against the page flip, so cursor updates no
longer fit in one vblank and flip-vs-cursor-legacy fails / times out

[How]
The cursor mode is a function of the underlying planes' coverage and
properties, not of the cursor's position, so cursor movement can never
change the correct mode. Restrict the destination-rectangle check to
non-cursor planes. A move/resize of an underlying plane (the case the
original change targets, e.g. amd_cursor_overlay@non-full) still
re-evaluates the mode correctly, while pure cursor movement returns to
the fast path.

Reviewed-by: ChiaHsuan (Tom) Chung <[email protected]>
Signed-off-by: James Lin <[email protected]>
Signed-off-by: George Zhang <[email protected]>
---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 27 +++++++++++++------
 1 file changed, 19 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index d184cc4de693..2cdc297e6cab 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -6656,15 +6656,26 @@ static int dm_crtc_get_cursor_mode(struct amdgpu_device 
*adev,
                }
 
                /*
-                * A plane moving or resizing (without a scale change) changes 
how
-                * much of the CRTC it covers. This can create/remove holes 
under
-                * the cursor and thus flip the required cursor mode (native vs
-                * overlay), so the destination rect must be re-evaluated too.
+                * A non-cursor plane moving or resizing (without a scale 
change)
+                * changes how much of the CRTC it covers. This can create or
+                * remove a hole under the cursor and thus flip the required
+                * cursor mode (native vs overlay), so its destination rect must
+                * be re-evaluated too.
+                *
+                * The cursor plane itself is deliberately excluded: the cursor
+                * mode depends on the underlying planes' coverage, not on the
+                * cursor's position (see the entire_crtc_covered logic below).
+                * Triggering on cursor movement would force every legacy cursor
+                * update off its fast path, and in a cursor-only commit - where
+                * the underlying planes are not part of the state - the 
coverage
+                * loop would see no covering plane and misevaluate the mode as
+                * overlay, regressing flip-vs-cursor-legacy.
                 */
-               if (old_plane_state->crtc_x != plane_state->crtc_x ||
-                   old_plane_state->crtc_y != plane_state->crtc_y ||
-                   old_plane_state->crtc_w != plane_state->crtc_w ||
-                   old_plane_state->crtc_h != plane_state->crtc_h) {
+               if (plane->type != DRM_PLANE_TYPE_CURSOR &&
+                   (old_plane_state->crtc_x != plane_state->crtc_x ||
+                    old_plane_state->crtc_y != plane_state->crtc_y ||
+                    old_plane_state->crtc_w != plane_state->crtc_w ||
+                    old_plane_state->crtc_h != plane_state->crtc_h)) {
                        consider_mode_change = true;
                        break;
                }
-- 
2.55.0

Reply via email to