Skip to content

Commit a441c0a

Browse files
committed
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. Signed-off-by: Maarten Lankhorst <[email protected]> Reviewed-by: Uma Shankar <[email protected]> Link: https://patchwork.freedesktop.org/patch/msgid/[email protected]
1 parent bb8624d commit a441c0a

File tree

5 files changed

+49
-2
lines changed

5 files changed

+49
-2
lines changed

drivers/gpu/drm/i915/display/intel_atomic_plane.c

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
#include "i9xx_plane_regs.h"
4444
#include "intel_atomic_plane.h"
4545
#include "intel_cdclk.h"
46+
#include "intel_cursor.h"
4647
#include "intel_display_rps.h"
4748
#include "intel_display_trace.h"
4849
#include "intel_display_types.h"
@@ -1201,7 +1202,6 @@ intel_cleanup_plane_fb(struct drm_plane *plane,
12011202

12021203
intel_display_rps_mark_interactive(dev_priv, state, false);
12031204

1204-
/* Should only be called after a successful intel_prepare_plane_fb()! */
12051205
intel_plane_unpin_fb(old_plane_state);
12061206
}
12071207

@@ -1214,3 +1214,14 @@ void intel_plane_helper_add(struct intel_plane *plane)
12141214
{
12151215
drm_plane_helper_add(&plane->base, &intel_plane_helper_funcs);
12161216
}
1217+
1218+
void intel_plane_init_cursor_vblank_work(struct intel_plane_state *old_plane_state,
1219+
struct intel_plane_state *new_plane_state)
1220+
{
1221+
if (!old_plane_state->ggtt_vma ||
1222+
old_plane_state->ggtt_vma == new_plane_state->ggtt_vma)
1223+
return;
1224+
1225+
drm_vblank_work_init(&old_plane_state->unpin_work, old_plane_state->uapi.crtc,
1226+
intel_cursor_unpin_work);
1227+
}

drivers/gpu/drm/i915/display/intel_atomic_plane.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,5 +71,7 @@ void intel_plane_set_invisible(struct intel_crtc_state *crtc_state,
7171
struct intel_plane_state *plane_state);
7272
void intel_plane_helper_add(struct intel_plane *plane);
7373
bool intel_plane_needs_physical(struct intel_plane *plane);
74+
void intel_plane_init_cursor_vblank_work(struct intel_plane_state *old_plane_state,
75+
struct intel_plane_state *new_plane_state);
7476

7577
#endif /* __INTEL_ATOMIC_PLANE_H__ */

drivers/gpu/drm/i915/display/intel_crtc.c

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -496,6 +496,19 @@ void intel_pipe_update_start(struct intel_atomic_state *state,
496496
if (intel_crtc_needs_vblank_work(new_crtc_state))
497497
intel_crtc_vblank_work_init(new_crtc_state);
498498

499+
if (state->base.legacy_cursor_update) {
500+
struct intel_plane *plane;
501+
struct intel_plane_state *old_plane_state, *new_plane_state;
502+
int i;
503+
504+
for_each_oldnew_intel_plane_in_state(state, plane, old_plane_state,
505+
new_plane_state, i) {
506+
if (old_plane_state->uapi.crtc == &crtc->base)
507+
intel_plane_init_cursor_vblank_work(old_plane_state,
508+
new_plane_state);
509+
}
510+
}
511+
499512
intel_vblank_evade_init(old_crtc_state, new_crtc_state, &evade);
500513

501514
if (drm_WARN_ON(&dev_priv->drm, drm_crtc_vblank_get(&crtc->base)))
@@ -621,6 +634,24 @@ void intel_pipe_update_end(struct intel_atomic_state *state,
621634
intel_crtc_arm_vblank_event(new_crtc_state);
622635
}
623636

637+
if (state->base.legacy_cursor_update) {
638+
struct intel_plane *plane;
639+
struct intel_plane_state *old_plane_state;
640+
int i;
641+
642+
for_each_old_intel_plane_in_state(state, plane, old_plane_state, i) {
643+
if (old_plane_state->uapi.crtc == &crtc->base &&
644+
old_plane_state->unpin_work.vblank) {
645+
drm_vblank_work_schedule(&old_plane_state->unpin_work,
646+
drm_crtc_accurate_vblank_count(&crtc->base) + 1,
647+
false);
648+
649+
/* Remove plane from atomic state, cleanup/free is done from vblank worker. */
650+
memset(&state->base.planes[i], 0, sizeof(state->base.planes[i]));
651+
}
652+
}
653+
}
654+
624655
/*
625656
* Send VRR Push to terminate Vblank. If we are already in vblank
626657
* this has to be done _after_ sampling the frame counter, as

drivers/gpu/drm/i915/display/intel_cursor.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -761,7 +761,7 @@ static bool intel_cursor_format_mod_supported(struct drm_plane *_plane,
761761
return format == DRM_FORMAT_ARGB8888;
762762
}
763763

764-
static void intel_cursor_unpin_work(struct kthread_work *base)
764+
void intel_cursor_unpin_work(struct kthread_work *base)
765765
{
766766
struct drm_vblank_work *work = to_drm_vblank_work(base);
767767
struct intel_plane_state *plane_state =

drivers/gpu/drm/i915/display/intel_cursor.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,12 @@
99
enum pipe;
1010
struct drm_i915_private;
1111
struct intel_plane;
12+
struct kthread_work;
1213

1314
struct intel_plane *
1415
intel_cursor_plane_create(struct drm_i915_private *dev_priv,
1516
enum pipe pipe);
1617

18+
void intel_cursor_unpin_work(struct kthread_work *base);
19+
1720
#endif

0 commit comments

Comments
 (0)