summaryrefslogtreecommitdiffstats
path: root/target/linux/bcm27xx/patches-6.6/950-0710-drm-vc4-Free-all-stale-dlists-if-channel-is-disabled.patch
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/bcm27xx/patches-6.6/950-0710-drm-vc4-Free-all-stale-dlists-if-channel-is-disabled.patch')
-rw-r--r--target/linux/bcm27xx/patches-6.6/950-0710-drm-vc4-Free-all-stale-dlists-if-channel-is-disabled.patch86
1 files changed, 86 insertions, 0 deletions
diff --git a/target/linux/bcm27xx/patches-6.6/950-0710-drm-vc4-Free-all-stale-dlists-if-channel-is-disabled.patch b/target/linux/bcm27xx/patches-6.6/950-0710-drm-vc4-Free-all-stale-dlists-if-channel-is-disabled.patch
new file mode 100644
index 0000000000..53f2684f3b
--- /dev/null
+++ b/target/linux/bcm27xx/patches-6.6/950-0710-drm-vc4-Free-all-stale-dlists-if-channel-is-disabled.patch
@@ -0,0 +1,86 @@
+From 9c02b7cd40a89ba1339d32a46b6694276902b81a Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.com>
+Date: Thu, 26 Oct 2023 18:23:31 +0100
+Subject: [PATCH 0710/1085] drm/vc4: Free all stale dlists if channel is
+ disabled
+
+The code handling freeing stale dlists had 2 issues:
+- it disabled the interrupt as soon as the first EOF interrupt
+ occurred, even if it didn't clear all stale allocations, thus
+ leading to stale entries
+- It didn't free stale entries from disabled channels, so eg
+ "kmstest -c 0" could leave a stale alloc on channel 1 floating
+ around.
+
+Keep the interrupt enabled whilst there are any outstanding
+allocs, and discard those on disabled channels. This second
+channel does require us to call vc4_hvs_stop_channel from
+vc4_crtc_atomic_disable so that the channel actually gets stopped.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
+---
+ drivers/gpu/drm/vc4/vc4_crtc.c | 2 ++
+ drivers/gpu/drm/vc4/vc4_hvs.c | 27 +++++++++++++++++++++++++--
+ 2 files changed, 27 insertions(+), 2 deletions(-)
+
+--- a/drivers/gpu/drm/vc4/vc4_crtc.c
++++ b/drivers/gpu/drm/vc4/vc4_crtc.c
+@@ -661,6 +661,8 @@ static void vc4_crtc_atomic_disable(stru
+
+ vc4_crtc_disable(crtc, encoder, state, old_vc4_state->assigned_channel);
+
++ vc4_hvs_atomic_disable(crtc, state);
++
+ /*
+ * Make sure we issue a vblank event after disabling the CRTC if
+ * someone was waiting it.
+--- a/drivers/gpu/drm/vc4/vc4_hvs.c
++++ b/drivers/gpu/drm/vc4/vc4_hvs.c
+@@ -697,7 +697,8 @@ static void vc4_hvs_schedule_dlist_sweep
+ if (!list_empty(&hvs->stale_dlist_entries))
+ queue_work(system_unbound_wq, &hvs->free_dlist_work);
+
+- vc4_hvs_irq_clear_eof(hvs, channel);
++ if (list_empty(&hvs->stale_dlist_entries))
++ vc4_hvs_irq_clear_eof(hvs, channel);
+
+ spin_unlock_irqrestore(&hvs->mm_lock, flags);
+ }
+@@ -712,6 +713,27 @@ static bool vc4_hvs_frcnt_lte(u8 cnt1, u
+ return (s8)((cnt1 << 2) - (cnt2 << 2)) <= 0;
+ }
+
++bool vc4_hvs_check_channel_active(struct vc4_hvs *hvs, unsigned int fifo)
++{
++ struct vc4_dev *vc4 = hvs->vc4;
++ struct drm_device *drm = &vc4->base;
++ bool enabled = false;
++ int idx;
++
++ WARN_ON_ONCE(vc4->gen > VC4_GEN_6);
++
++ if (!drm_dev_enter(drm, &idx))
++ return 0;
++
++ if (vc4->gen >= VC4_GEN_6)
++ enabled = HVS_READ(SCALER6_DISPX_CTRL0(fifo)) & SCALER6_DISPX_CTRL0_ENB;
++ else
++ enabled = HVS_READ(SCALER_DISPCTRLX(fifo)) & SCALER_DISPCTRLX_ENABLE;
++
++ drm_dev_exit(idx);
++ return enabled;
++}
++
+ /*
+ * Some atomic commits (legacy cursor updates, mostly) will not wait for
+ * the next vblank and will just return once the commit has been pushed
+@@ -746,7 +768,8 @@ static void vc4_hvs_dlist_free_work(stru
+ u8 frcnt;
+
+ frcnt = vc4_hvs_get_fifo_frame_count(hvs, cur->channel);
+- if (!vc4_hvs_frcnt_lte(cur->target_frame_count, frcnt))
++ if (vc4_hvs_check_channel_active(hvs, cur->channel) &&
++ !vc4_hvs_frcnt_lte(cur->target_frame_count, frcnt))
+ continue;
+
+ vc4_hvs_free_dlist_entry_locked(hvs, cur);