53f2684f3be612fe62d399590e3c176a699e5bfe
[openwrt/staging/blocktrron.git] /
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
5 disabled
6
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
13 around.
14
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.
19
20 Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
21 ---
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(-)
25
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
29
30 vc4_crtc_disable(crtc, encoder, state, old_vc4_state->assigned_channel);
31
32 + vc4_hvs_atomic_disable(crtc, state);
33 +
34 /*
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);
42
43 - vc4_hvs_irq_clear_eof(hvs, channel);
44 + if (list_empty(&hvs->stale_dlist_entries))
45 + vc4_hvs_irq_clear_eof(hvs, channel);
46
47 spin_unlock_irqrestore(&hvs->mm_lock, flags);
48 }
49 @@ -712,6 +713,27 @@ static bool vc4_hvs_frcnt_lte(u8 cnt1, u
50 return (s8)((cnt1 << 2) - (cnt2 << 2)) <= 0;
51 }
52
53 +bool vc4_hvs_check_channel_active(struct vc4_hvs *hvs, unsigned int fifo)
54 +{
55 + struct vc4_dev *vc4 = hvs->vc4;
56 + struct drm_device *drm = &vc4->base;
57 + bool enabled = false;
58 + int idx;
59 +
60 + WARN_ON_ONCE(vc4->gen > VC4_GEN_6);
61 +
62 + if (!drm_dev_enter(drm, &idx))
63 + return 0;
64 +
65 + if (vc4->gen >= VC4_GEN_6)
66 + enabled = HVS_READ(SCALER6_DISPX_CTRL0(fifo)) & SCALER6_DISPX_CTRL0_ENB;
67 + else
68 + enabled = HVS_READ(SCALER_DISPCTRLX(fifo)) & SCALER_DISPCTRLX_ENABLE;
69 +
70 + drm_dev_exit(idx);
71 + return enabled;
72 +}
73 +
74 /*
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
78 u8 frcnt;
79
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))
84 continue;
85
86 vc4_hvs_free_dlist_entry_locked(hvs, cur);