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