Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider: - [High] drm/i915: atomic KMS violation and i9xx hardware quirk trigger in cursor update - [Medium] drm/i915: missing CURPOS reprogram during i845 cursor shape change --
commit 80d531685d42e74f0f8ac2b8f9867c83e1f1a6b8 Author: George Karagounis <[email protected]> Date: Sat Sep 19 17:39:14 2026 +0000 drm/i915/display: Split i845 and i9xx cursor updates into arm/noarm There was a problem with the i845 and i9xx cursor update functions they handled both position updates and control/base/size updates in a single armed sequence. This prevented the cursor position from being updated asynchronously, which can make the cursor feel laggy To fix this i split the updates into two phases 1. noarm Calculates and writes the CURPOS register immediately. 2. arm Calculates and writes CURCNTR, CURBASE, and CURSIZE to latch the control and memory updates at vblank > diff --git a/drivers/gpu/drm/i915/display/intel_cursor.c > b/drivers/gpu/drm/i915/display/intel_cursor.c > index 4afd275de86ea..bcf00b78a71b7 100644 > --- a/drivers/gpu/drm/i915/display/intel_cursor.c > +++ b/drivers/gpu/drm/i915/display/intel_cursor.c > @@ -271,14 +271,27 @@ static int i845_check_cursor(struct intel_crtc_state > *crtc_state, > return 0; > } > > -/* TODO: split into noarm+arm pair */ > +static void i845_cursor_update_noarm(struct intel_dsb *dsb, > + struct intel_plane *plane, > + const struct intel_crtc_state *crtc_state, > + const struct intel_plane_state > *plane_state) > +{ > + struct intel_display *display = to_intel_display(plane); > + u32 pos = 0; > + > + if (plane_state && plane_state->uapi.visible) > + pos = intel_cursor_position(crtc_state, plane_state, false); > + > + intel_de_write_fw(display, CURPOS(display, PIPE_A), pos); > +} > + [Severity: High] Does writing CURPOS in the noarm phase break atomic KMS synchronization? Writing self-arming registers in the noarm phase can cause visible tearing when updating the cursor position and image simultaneously. [ ... ] > static void i845_cursor_update_arm(struct intel_dsb *dsb, > struct intel_plane *plane, > const struct intel_crtc_state *crtc_state, > const struct intel_plane_state *plane_state) > { > struct intel_display *display = to_intel_display(plane); > - u32 cntl = 0, base = 0, pos = 0, size = 0; > + u32 cntl = 0, base = 0, size = 0; [ ... ] > /* On these chipsets we can only modify the base/size/stride > * whilst the cursor is disabled. > */ > if (plane->cursor.base != base || > plane->cursor.size != size || > plane->cursor.cntl != cntl) { > intel_de_write_fw(display, CURCNTR(display, PIPE_A), 0); > intel_de_write_fw(display, CURBASE(display, PIPE_A), base); > intel_de_write_fw(display, CURSIZE(display, PIPE_A), size); > - intel_de_write_fw(display, CURPOS(display, PIPE_A), pos); > intel_de_write_fw(display, CURCNTR(display, PIPE_A), cntl); [Severity: Medium] Can the hardware lose the cursor position here? The CURPOS write was removed from this atomic disabled-update sequence. Updating the cursor base, size, or control on an i845 platform triggers a temporary disable/enable cycle, and omitting the CURPOS reprogramming while the cursor is temporarily disabled might cause the position to be lost. [ ... ] > +static void i9xx_cursor_update_noarm(struct intel_dsb *dsb, > + struct intel_plane *plane, > + const struct intel_crtc_state *crtc_state, > + const struct intel_plane_state > *plane_state) > +{ > + struct intel_display *display = to_intel_display(plane); > + enum pipe pipe = plane->pipe; > + u32 pos = 0; > + > + if (plane_state && plane_state->uapi.visible) > + pos = intel_cursor_position(crtc_state, plane_state, false); > + > + intel_de_write_dsb(display, dsb, CURPOS(display, pipe), pos); > +} [Severity: High] Does prematurely writing CURPOS trigger the i9xx self-arming quirk? Because CURCNTR has not yet been written in the arm phase, writing CURPOS here causes it to arm itself prematurely. It gets canceled later by writes to CURCNTR during the arm phase, resulting in dropped cursor position updates. [ ... ] > static void i9xx_cursor_update_arm(struct intel_dsb *dsb, > struct intel_plane *plane, > const struct intel_crtc_state *crtc_state, > const struct intel_plane_state *plane_state) > { [ ... ] > /* > * On some platforms writing CURCNTR first will also > * cause CURPOS to be armed by the CURBASE write. > * Without the CURCNTR write the CURPOS write would > * arm itself. Thus we always update CURCNTR before > * CURPOS. > * > * On other platforms CURPOS always requires the > * CURBASE write to arm the update. Additionally > * a write to any of the cursor register will cancel > * an already armed cursor update. Thus leaving out > * the CURBASE write after CURPOS could lead to a > * cursor that doesn't appear to move, or even change > * shape. Thus we always write CURBASE. [Severity: High] Does the new update sequence violate the documented hardware quirk? The hardware quirk documentation warns against the exact sequence introduced by this patch. Since the commit message explicitly states the intent to make cursor position updates asynchronous, this appears to be a violation of the atomic KMS design. -- Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=1
