1 From 8b7078d1bbd8bb548cc97d5214adb828e9f0037c Mon Sep 17 00:00:00 2001
2 From: Dave Stevenson <dave.stevenson@raspberrypi.com>
3 Date: Thu, 26 Oct 2023 18:23:31 +0100
4 Subject: [PATCH] drm/vc4: Free all stale dlists if channel is disabled
6 The code handling freeing stale dlists had 2 issues:
7 - it disabled the interrupt as soon as the first EOF interrupt
8 occurred, even if it didn't clear all stale allocations, thus
9 leading to stale entries
10 - It didn't free stale entries from disabled channels, so eg
11 "kmstest -c 0" could leave a stale alloc on channel 1 floating
14 Keep the interrupt enabled whilst there are any outstanding
15 allocs, and discard those on disabled channels. This second
16 channel does require us to call vc4_hvs_stop_channel from
17 vc4_crtc_atomic_disable so that the channel actually gets stopped.
19 Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
21 drivers/gpu/drm/vc4/vc4_crtc.c | 2 ++
22 drivers/gpu/drm/vc4/vc4_hvs.c | 27 +++++++++++++++++++++++++--
23 2 files changed, 27 insertions(+), 2 deletions(-)
25 --- a/drivers/gpu/drm/vc4/vc4_crtc.c
26 +++ b/drivers/gpu/drm/vc4/vc4_crtc.c
27 @@ -660,6 +660,8 @@ static void vc4_crtc_atomic_disable(stru
29 vc4_crtc_disable(crtc, encoder, state, old_vc4_state->assigned_channel);
31 + vc4_hvs_atomic_disable(crtc, state);
34 * Make sure we issue a vblank event after disabling the CRTC if
35 * someone was waiting it.
36 --- a/drivers/gpu/drm/vc4/vc4_hvs.c
37 +++ b/drivers/gpu/drm/vc4/vc4_hvs.c
38 @@ -697,7 +697,8 @@ static void vc4_hvs_schedule_dlist_sweep
39 if (!list_empty(&hvs->stale_dlist_entries))
40 queue_work(system_unbound_wq, &hvs->free_dlist_work);
42 - vc4_hvs_irq_clear_eof(hvs, channel);
43 + if (list_empty(&hvs->stale_dlist_entries))
44 + vc4_hvs_irq_clear_eof(hvs, channel);
46 spin_unlock_irqrestore(&hvs->mm_lock, flags);
48 @@ -712,6 +713,27 @@ static bool vc4_hvs_frcnt_lte(u8 cnt1, u
49 return (s8)((cnt1 << 2) - (cnt2 << 2)) <= 0;
52 +bool vc4_hvs_check_channel_active(struct vc4_hvs *hvs, unsigned int fifo)
54 + struct vc4_dev *vc4 = hvs->vc4;
55 + struct drm_device *drm = &vc4->base;
56 + bool enabled = false;
59 + WARN_ON_ONCE(vc4->gen > VC4_GEN_6);
61 + if (!drm_dev_enter(drm, &idx))
64 + if (vc4->gen >= VC4_GEN_6)
65 + enabled = HVS_READ(SCALER6_DISPX_CTRL0(fifo)) & SCALER6_DISPX_CTRL0_ENB;
67 + enabled = HVS_READ(SCALER_DISPCTRLX(fifo)) & SCALER_DISPCTRLX_ENABLE;
74 * Some atomic commits (legacy cursor updates, mostly) will not wait for
75 * the next vblank and will just return once the commit has been pushed
76 @@ -746,7 +768,8 @@ static void vc4_hvs_dlist_free_work(stru
79 frcnt = vc4_hvs_get_fifo_frame_count(hvs, cur->channel);
80 - if (!vc4_hvs_frcnt_lte(cur->target_frame_count, frcnt))
81 + if (vc4_hvs_check_channel_active(hvs, cur->channel) &&
82 + !vc4_hvs_frcnt_lte(cur->target_frame_count, frcnt))
85 vc4_hvs_free_dlist_entry_locked(hvs, cur);