Allow asynchronous page flips on planes that either lack a framebuffer or retain the same framebuffer, as long as no plane properties are modified.
This avoids unnecessary failures in async flip paths when the update is effectively a no-op, improving compatibility with some compositors. Closes: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/13834 Signed-off-by: Naveen Kumar <naveen1.ku...@intel.com> --- drivers/gpu/drm/i915/display/intel_display.c | 18 +++++++++------ drivers/gpu/drm/i915/display/intel_plane.c | 24 ++++++++++++++++++++ 2 files changed, 35 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 456fc4b04cda..e0eb0de62ff4 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -5970,18 +5970,21 @@ static int intel_async_flip_check_uapi(struct intel_atomic_state *state, * this(vlv/chv and icl+) should be added when async flip is * enabled in the atomic IOCTL path. */ - if (!plane->async_flip) { + if (!plane->async_flip && new_plane_state->uapi.fb) { drm_dbg_kms(display->drm, "[PLANE:%d:%s] async flip not supported\n", plane->base.base.id, plane->base.name); return -EINVAL; } - if (!old_plane_state->uapi.fb || !new_plane_state->uapi.fb) { - drm_dbg_kms(display->drm, - "[PLANE:%d:%s] no old or new framebuffer\n", - plane->base.base.id, plane->base.name); - return -EINVAL; + if (plane->base.type != DRM_PLANE_TYPE_CURSOR && + plane->base.type != DRM_PLANE_TYPE_OVERLAY) { + if (!old_plane_state->uapi.fb || !new_plane_state->uapi.fb) { + drm_dbg_kms(display->drm, + "[PLANE:%d:%s] no old or new framebuffer\n", + plane->base.base.id, plane->base.name); + return -EINVAL; + } } } @@ -6034,7 +6037,8 @@ static int intel_async_flip_check_hw(struct intel_atomic_state *state, struct in * an async flip. We should never get this far otherwise. */ if (drm_WARN_ON(display->drm, - new_crtc_state->do_async_flip && !plane->async_flip)) + new_crtc_state->do_async_flip && !plane->async_flip && + new_plane_state->hw.fb)) return -EINVAL; /* diff --git a/drivers/gpu/drm/i915/display/intel_plane.c b/drivers/gpu/drm/i915/display/intel_plane.c index 36fb07471deb..434be91b57df 100644 --- a/drivers/gpu/drm/i915/display/intel_plane.c +++ b/drivers/gpu/drm/i915/display/intel_plane.c @@ -1425,9 +1425,33 @@ static int intel_get_scanout_buffer(struct drm_plane *plane, return 0; } +static int +intel_plane_atomic_async_check(struct drm_plane *plane, + struct drm_atomic_state *_state, bool flip) +{ + struct intel_atomic_state *state = to_intel_atomic_state(_state); + struct intel_plane *intel_plane; + const struct intel_plane_state *old_plane_state; + struct intel_plane_state *new_plane_state; + int i; + + for_each_oldnew_intel_plane_in_state(state, intel_plane, old_plane_state, + new_plane_state, i) { + if (intel_plane->id != to_intel_plane(plane)->id) + continue; + + /* no old or new framebuffer */ + if (flip && !old_plane_state->uapi.fb && !new_plane_state->uapi.fb) + return 0; + } + + return -EINVAL; +} + static const struct drm_plane_helper_funcs intel_plane_helper_funcs = { .prepare_fb = intel_prepare_plane_fb, .cleanup_fb = intel_cleanup_plane_fb, + .atomic_async_check = intel_plane_atomic_async_check, }; static const struct drm_plane_helper_funcs intel_primary_plane_helper_funcs = { -- 2.48.1