On Wed, Feb 11, 2026 at 04:48:52PM -0800, Khaled Almahallawy wrote:
> The driver automatically allocates a Y-plane (4A/5A) when userspace
> configures an NV12 surface. The allocation loop doesn't check if a
> candidate plane is already configured by userspace in the same atomic
> commit, causing conflict as observed in this i915_display_info:
> 
>   [PLANE:124:plane 4A]: type=OVL
>       uapi: [FB:566] AB24 little-endian (0x34324241),0x0,1920x1280, 
> visible=visible
>       planar: Linked to [PLANE:34:plane 1A] as a Y plane
>       hw: [FB:564] NV12 little-endian (0x3231564e),0x0,1920x1080, visible=yes
> 
> Plane 4A's uapi state shows userspace's AB24 framebuffer, but the hw
> state shows it was reprogrammed with the NV12 Y-plane.
> 
> Example triggered by experiment with IGT test to commit NV12 + multiple
> AB24 planes:
> 
>   === Testing with NV12 primary + 3 ABGR8888 overlays ===
>     Plane 0 (Primary): NV12 1920x1080 at (0, 0)
>     Plane 1 (Overlay 0): ABGR8888 1920x1280 (fullscreen) at (0, 0)
>     Plane 2 (Overlay 1): ABGR8888 1920x1280 (fullscreen) at (0, 0)
>     Plane 3 (Overlay 2): ABGR8888 1920x1280 (fullscreen) at (0, 0)
>     TEST_ONLY passed, committing...
>     Atomic commit SUCCEEDED
> 
> The bug triggers a kernel WARNING in unlink_nv12_plane():
>   WARNING: drivers/gpu/drm/i915/display/intel_plane.c:1521
>   drm_WARN_ON(plane_state->uapi.visible)
>

I think the actual bug is that we unlink the nv12 planes after
plane_atomic_check(). unlink_nv12_plane() will then clobber
some things in the crtc state that was set up by 
plane_atomic_check().

So we perhaps want something like this:

diff --git a/drivers/gpu/drm/i915/display/intel_plane.c 
b/drivers/gpu/drm/i915/display/intel_plane.c
index 3dc2ed52147f..98d0255b8b18 100644
--- a/drivers/gpu/drm/i915/display/intel_plane.c
+++ b/drivers/gpu/drm/i915/display/intel_plane.c
@@ -441,6 +441,8 @@ void intel_plane_set_invisible(struct intel_crtc_state 
*crtc_state,
 {
        struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
 
+       unlink_nv12_plane(crtc_state, plane_state);
+
        crtc_state->active_planes &= ~BIT(plane->id);
        crtc_state->scaled_planes &= ~BIT(plane->id);
        crtc_state->nv12_planes &= ~BIT(plane->id);
@@ -1513,6 +1515,9 @@ static void unlink_nv12_plane(struct intel_crtc_state 
*crtc_state,
        struct intel_display *display = to_intel_display(plane_state);
        struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
 
+       if (!plane_state->planar_linked_plane)
+               return;
+
        plane_state->planar_linked_plane = NULL;
 
        if (!plane_state->is_y_plane)
@@ -1550,8 +1555,7 @@ static int icl_check_nv12_planes(struct 
intel_atomic_state *state,
                if (plane->pipe != crtc->pipe)
                        continue;
 
-               if (plane_state->planar_linked_plane)
-                       unlink_nv12_plane(crtc_state, plane_state);
+               unlink_nv12_plane(crtc_state, plane_state);
        }
 
        if (!crtc_state->nv12_planes)

With that we could perhaps even drop the second unlink_nv12_plane()
call, but haven't really thought through the details...

> Fix by checking uapi.fb before allocating a Y-plane. If set, userspace
> configured this plane, so skip to the next candidate. This enables
> graceful fallback (4A busy -> try 5A) rather than the current
> behavior that steals planes from userspace.

I do have a patch in some branch that changes the Y plane
selection to use 'enabled_planes' instead of 'active_planes'
which is equivalent to this. It is perhaps the slightly more
logical approach but it could result some specific usage
scenarios losing NV12 scanout capability. IIRC I also had
some unsolved issue with that approach, which is why I never
even sent out the patch.

> IGT test and kernel fix generated with assistance from Claude Sonnet 4.5
> through an iterative process. The following is a summary of the prompts
> used:
> 
> IGT test generation prompt:
> Need an IGT test to:
> 1. Reproduce the NV12 + multiple AB24 plane allocation conflict
> 2. Work across different GPU vendors (not Intel-specific)
> 3. Discover hardware limits through iteration (not hardcoded)
> 4. Test atomic commit behavior with mixed formats
> 5. Validate driver properly rejects invalid configurations
> 6. Help debug plane allocation issues (interactive inspection)
> 
> Kernel fix debug process:
> 1. Explained NV12 UV->Y plane linking mechanism (link_nv12_planes)
> 2. Traced Y-plane selection algorithm and hardware constraints
> 3. Analyzed i915_display_info output showing uapi vs hw state mismatch
> 4. Triggered kernel WARNING in unlink_nv12_plane() confirming the bug
> 5. Traced kernel logs through atomic commit sequence
> 6. Identified root cause: Y-plane allocation checks uapi.crtc, but that's
>    set later during plane validation. uapi.fb is set earlier during state
>    setup, making it the correct indicator of userspace configuration
> 7. Evaluated uapi.fb vs uapi.visible for detection timing
> 8. Initially suggested rejecting commit with -EINVAL, but decided graceful
>    fallback with continue is better - allows trying alternate Y-planes
>    (4A busy -> 5A) instead of failing entire atomic commit
> 9. Validated fix prevents plane stealing while allowing alternate Y-plane
> 
> Cc: Uma Shankar <[email protected]>
> Cc: Jani Nikula <[email protected]>
> Cc: Ville Syrjala <[email protected]>
> Signed-off-by: Khaled Almahallawy <[email protected]>
> ---
>  drivers/gpu/drm/i915/display/intel_plane.c | 4 ++++
>  1 file changed, 4 insertions(+)
> 
> diff --git a/drivers/gpu/drm/i915/display/intel_plane.c 
> b/drivers/gpu/drm/i915/display/intel_plane.c
> index 3dc2ed52147f..57d1a9cd226e 100644
> --- a/drivers/gpu/drm/i915/display/intel_plane.c
> +++ b/drivers/gpu/drm/i915/display/intel_plane.c
> @@ -1578,6 +1578,10 @@ static int icl_check_nv12_planes(struct 
> intel_atomic_state *state,
>                       if (IS_ERR(y_plane_state))
>                               return PTR_ERR(y_plane_state);
>  
> +                     /* Reject if this Y-plane is being configured by 
> userspace */
> +                     if (y_plane_state->uapi.fb)
> +                             continue;
> +
>                       break;
>               }
>  
> -- 
> 2.43.0

-- 
Ville Syrjälä
Intel

Reply via email to