1 From 9c02b7cd40a89ba1339d32a46b6694276902b81a 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 0710/1085] drm/vc4: Free all stale dlists if channel is
7 The code handling freeing stale dlists had 2 issues:
8 - it disabled the interrupt as soon as the first EOF interrupt
9 occurred, even if it didn't clear all stale allocations, thus
10 leading to stale entries
11 - It didn't free stale entries from disabled channels, so eg
12 "kmstest -c 0" could leave a stale alloc on channel 1 floating
15 Keep the interrupt enabled whilst there are any outstanding
16 allocs, and discard those on disabled channels. This second
17 channel does require us to call vc4_hvs_stop_channel from
18 vc4_crtc_atomic_disable so that the channel actually gets stopped.
20 Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
22 drivers/gpu/drm/vc4/vc4_crtc.c | 2 ++
23 drivers/gpu/drm/vc4/vc4_hvs.c | 27 +++++++++++++++++++++++++--
24 2 files changed, 27 insertions(+), 2 deletions(-)
26 --- a/drivers/gpu/drm/vc4/vc4_crtc.c
27 +++ b/drivers/gpu/drm/vc4/vc4_crtc.c
28 @@ -661,6 +661,8 @@ static void vc4_crtc_atomic_disable(stru
30 vc4_crtc_disable(crtc, encoder, state, old_vc4_state->assigned_channel);
32 + vc4_hvs_atomic_disable(crtc, state);
35 * Make sure we issue a vblank event after disabling the CRTC if
36 * someone was waiting it.
37 --- a/drivers/gpu/drm/vc4/vc4_hvs.c
38 +++ b/drivers/gpu/drm/vc4/vc4_hvs.c
39 @@ -697,7 +697,8 @@ static void vc4_hvs_schedule_dlist_sweep
40 if (!list_empty(&hvs->stale_dlist_entries))
41 queue_work(system_unbound_wq, &hvs->free_dlist_work);
43 - vc4_hvs_irq_clear_eof(hvs, channel);
44 + if (list_empty(&hvs->stale_dlist_entries))
45 + vc4_hvs_irq_clear_eof(hvs, channel);
47 spin_unlock_irqrestore(&hvs->mm_lock, flags);
49 @@ -712,6 +713,27 @@ static bool vc4_hvs_frcnt_lte(u8 cnt1, u
50 return (s8)((cnt1 << 2) - (cnt2 << 2)) <= 0;
53 +bool vc4_hvs_check_channel_active(struct vc4_hvs *hvs, unsigned int fifo)
55 + struct vc4_dev *vc4 = hvs->vc4;
56 + struct drm_device *drm = &vc4->base;
57 + bool enabled = false;
60 + WARN_ON_ONCE(vc4->gen > VC4_GEN_6);
62 + if (!drm_dev_enter(drm, &idx))
65 + if (vc4->gen >= VC4_GEN_6)
66 + enabled = HVS_READ(SCALER6_DISPX_CTRL0(fifo)) & SCALER6_DISPX_CTRL0_ENB;
68 + enabled = HVS_READ(SCALER_DISPCTRLX(fifo)) & SCALER_DISPCTRLX_ENABLE;
75 * Some atomic commits (legacy cursor updates, mostly) will not wait for
76 * the next vblank and will just return once the commit has been pushed
77 @@ -746,7 +768,8 @@ static void vc4_hvs_dlist_free_work(stru
80 frcnt = vc4_hvs_get_fifo_frame_count(hvs, cur->channel);
81 - if (!vc4_hvs_frcnt_lte(cur->target_frame_count, frcnt))
82 + if (vc4_hvs_check_channel_active(hvs, cur->channel) &&
83 + !vc4_hvs_frcnt_lte(cur->target_frame_count, frcnt))
86 vc4_hvs_free_dlist_entry_locked(hvs, cur);