> -----Original Message-----
> From: Intel-xe <intel-xe-boun...@lists.freedesktop.org> On Behalf Of Maarten
> Lankhorst
> Sent: Wednesday, May 22, 2024 11:04 AM
> To: intel-gfx@lists.freedesktop.org
> Cc: intel...@lists.freedesktop.org; Maarten Lankhorst
> <maarten.lankho...@linux.intel.com>
> Subject: [v6 3/3] drm/i915: Use the same vblank worker for atomic unpin
>
> In case of legacy cursor update, the cursor VMA needs to be unpinned only
> after
> vblank. This exceeds the lifetime of the whole atomic commit.
>
> Any trick I attempted to keep the atomic commit alive didn't work, as
> drm_atomic_helper_setup_commit() force throttles on any old commit that
> wasn't cleaned up.
>
> The only option remaining is to remove the plane from the atomic commit, and
> use the same path as the legacy cursor update to clean the state after vblank.
>
> Changes since previous version:
> - Call the memset for plane state immediately when scheduling vblank,
> this prevents a use-after-free in cursor cleanup.
Have checked and followed the changes along with testing the same with
Chaitanya. This looks good now.
Reviewed-by: Uma Shankar <uma.shan...@intel.com>
> Signed-off-by: Maarten Lankhorst <maarten.lankho...@linux.intel.com>
> ---
> .../gpu/drm/i915/display/intel_atomic_plane.c | 13 +++++++-
> .../gpu/drm/i915/display/intel_atomic_plane.h | 2 ++
> drivers/gpu/drm/i915/display/intel_crtc.c | 31 +++++++++++++++++++
> drivers/gpu/drm/i915/display/intel_cursor.c | 2 +-
> drivers/gpu/drm/i915/display/intel_cursor.h | 3 ++
> 5 files changed, 49 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/display/intel_atomic_plane.c
> b/drivers/gpu/drm/i915/display/intel_atomic_plane.c
> index 27224ecdc94c..a06c676c9bb3 100644
> --- a/drivers/gpu/drm/i915/display/intel_atomic_plane.c
> +++ b/drivers/gpu/drm/i915/display/intel_atomic_plane.c
> @@ -42,6 +42,7 @@
> #include "i915_reg.h"
> #include "intel_atomic_plane.h"
> #include "intel_cdclk.h"
> +#include "intel_cursor.h"
> #include "intel_display_rps.h"
> #include "intel_display_trace.h"
> #include "intel_display_types.h"
> @@ -1188,7 +1189,6 @@ intel_cleanup_plane_fb(struct drm_plane *plane,
>
> intel_display_rps_mark_interactive(dev_priv, state, false);
>
> - /* Should only be called after a successful intel_prepare_plane_fb()! */
> intel_plane_unpin_fb(old_plane_state);
> }
>
> @@ -1201,3 +1201,14 @@ void intel_plane_helper_add(struct intel_plane
> *plane) {
> drm_plane_helper_add(&plane->base, &intel_plane_helper_funcs); }
> +
> +void intel_plane_init_cursor_vblank_work(struct intel_plane_state
> *old_plane_state,
> + struct intel_plane_state
> *new_plane_state) {
> + if (!old_plane_state->ggtt_vma ||
> + old_plane_state->ggtt_vma == new_plane_state->ggtt_vma)
> + return;
> +
> + drm_vblank_work_init(&old_plane_state->unpin_work, old_plane_state-
> >uapi.crtc,
> + intel_cursor_unpin_work);
> +}
> diff --git a/drivers/gpu/drm/i915/display/intel_atomic_plane.h
> b/drivers/gpu/drm/i915/display/intel_atomic_plane.h
> index e7a0699f17c8..4c2031fc3504 100644
> --- a/drivers/gpu/drm/i915/display/intel_atomic_plane.h
> +++ b/drivers/gpu/drm/i915/display/intel_atomic_plane.h
> @@ -67,5 +67,7 @@ void intel_plane_set_invisible(struct intel_crtc_state
> *crtc_state,
> struct intel_plane_state *plane_state); void
> intel_plane_helper_add(struct intel_plane *plane); bool
> intel_plane_needs_physical(struct intel_plane *plane);
> +void intel_plane_init_cursor_vblank_work(struct intel_plane_state
> *old_plane_state,
> + struct intel_plane_state
> *new_plane_state);
>
> #endif /* __INTEL_ATOMIC_PLANE_H__ */
> diff --git a/drivers/gpu/drm/i915/display/intel_crtc.c
> b/drivers/gpu/drm/i915/display/intel_crtc.c
> index 339010384b86..283106558b2a 100644
> --- a/drivers/gpu/drm/i915/display/intel_crtc.c
> +++ b/drivers/gpu/drm/i915/display/intel_crtc.c
> @@ -499,6 +499,19 @@ void intel_pipe_update_start(struct intel_atomic_state
> *state,
> if (intel_crtc_needs_vblank_work(new_crtc_state))
> intel_crtc_vblank_work_init(new_crtc_state);
>
> + if (state->base.legacy_cursor_update) {
> + struct intel_plane *plane;
> + struct intel_plane_state *old_plane_state, *new_plane_state;
> + int i;
> +
> + for_each_oldnew_intel_plane_in_state(state, plane,
> old_plane_state,
> + new_plane_state, i) {
> + if (old_plane_state->uapi.crtc == &crtc->base)
> +
> intel_plane_init_cursor_vblank_work(old_plane_state,
> +
> new_plane_state);
> + }
> + }
> +
> intel_vblank_evade_init(old_crtc_state, new_crtc_state, &evade);
>
> if (drm_WARN_ON(&dev_priv->drm, drm_crtc_vblank_get(&crtc-
> >base)))
> @@ -615,6 +628,24 @@ void intel_pipe_update_end(struct intel_atomic_state
> *state,
> new_crtc_state->uapi.event = NULL;
> }
>
> + if (state->base.legacy_cursor_update) {
> + struct intel_plane *plane;
> + struct intel_plane_state *old_plane_state;
> + int i;
> +
> + for_each_old_intel_plane_in_state(state, plane,
> old_plane_state, i) {
> + if (old_plane_state->uapi.crtc == &crtc->base &&
> + old_plane_state->unpin_work.vblank) {
> + drm_vblank_work_schedule(&old_plane_state-
> >unpin_work,
> +
> drm_crtc_accurate_vblank_count(&crtc->base) + 1,
> + false);
> +
> + /* Remove plane from atomic state,
> cleanup/free is done from vblank worker. */
> + memset(&state->base.planes[i], 0, sizeof(state-
> >base.planes[i]));
> + }
> + }
> + }
> +
> /*
> * Send VRR Push to terminate Vblank. If we are already in vblank
> * this has to be done _after_ sampling the frame counter, as diff --git
> a/drivers/gpu/drm/i915/display/intel_cursor.c
> b/drivers/gpu/drm/i915/display/intel_cursor.c
> index 36e2dcbe3614..a6dcc4d95ff2 100644
> --- a/drivers/gpu/drm/i915/display/intel_cursor.c
> +++ b/drivers/gpu/drm/i915/display/intel_cursor.c
> @@ -710,7 +710,7 @@ static bool intel_cursor_format_mod_supported(struct
> drm_plane *_plane,
> return format == DRM_FORMAT_ARGB8888;
> }
>
> -static void intel_cursor_unpin_work(struct kthread_work *base)
> +void intel_cursor_unpin_work(struct kthread_work *base)
> {
> struct drm_vblank_work *work = to_drm_vblank_work(base);
> struct intel_plane_state *plane_state = diff --git
> a/drivers/gpu/drm/i915/display/intel_cursor.h
> b/drivers/gpu/drm/i915/display/intel_cursor.h
> index ce333bf4c2d5..e2d9ec710a86 100644
> --- a/drivers/gpu/drm/i915/display/intel_cursor.h
> +++ b/drivers/gpu/drm/i915/display/intel_cursor.h
> @@ -9,9 +9,12 @@
> enum pipe;
> struct drm_i915_private;
> struct intel_plane;
> +struct kthread_work;
>
> struct intel_plane *
> intel_cursor_plane_create(struct drm_i915_private *dev_priv,
> enum pipe pipe);
>
> +void intel_cursor_unpin_work(struct kthread_work *base);
> +
> #endif
> --
> 2.43.0