aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/bcm27xx/patches-5.15/950-0753-drm-vc4-Fix-out-of-order-frames-during-asynchronous-.patch
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/bcm27xx/patches-5.15/950-0753-drm-vc4-Fix-out-of-order-frames-during-asynchronous-.patch')
-rw-r--r--target/linux/bcm27xx/patches-5.15/950-0753-drm-vc4-Fix-out-of-order-frames-during-asynchronous-.patch97
1 files changed, 97 insertions, 0 deletions
diff --git a/target/linux/bcm27xx/patches-5.15/950-0753-drm-vc4-Fix-out-of-order-frames-during-asynchronous-.patch b/target/linux/bcm27xx/patches-5.15/950-0753-drm-vc4-Fix-out-of-order-frames-during-asynchronous-.patch
new file mode 100644
index 0000000000..a5505849e6
--- /dev/null
+++ b/target/linux/bcm27xx/patches-5.15/950-0753-drm-vc4-Fix-out-of-order-frames-during-asynchronous-.patch
@@ -0,0 +1,97 @@
+From a0bc59127231cbea506651c362d4836a0ff5591f Mon Sep 17 00:00:00 2001
+From: Maxime Ripard <maxime@cerno.tech>
+Date: Wed, 8 Sep 2021 21:12:26 +0200
+Subject: [PATCH] drm/vc4: Fix out of order frames during asynchronous
+ page flips
+
+When doing an asynchronous page flip (PAGE_FLIP ioctl with the
+DRM_MODE_PAGE_FLIP_ASYNC flag set), the current code waits for the
+possible GPU buffer being rendered through a call to
+vc4_queue_seqno_cb().
+
+On the BCM2835-37, the GPU driver is part of the vc4 driver and that
+function is defined in vc4_gem.c to wait for the buffer to be rendered,
+and once it's done, call a callback.
+
+However, on the BCM2711 used on the RaspberryPi4, the GPU driver is
+separate (v3d) and that function won't do anything. This was working
+because we were going into a path, due to uninitialized variables, that
+was always scheduling the callback.
+
+However, we were never actually waiting for the buffer to be rendered
+which was resulting in frames being displayed out of order.
+
+The generic API to signal those kind of completion in the kernel are the
+DMA fences, and fortunately the v3d drivers supports them and signal
+when its job is done. That API also provides an equivalent function that
+allows to have a callback being executed when the fence is signalled as
+done.
+
+Let's change our driver a bit to rely on the previous function for the
+older SoCs, and on DMA fences for the BCM2711.
+
+Signed-off-by: Maxime Ripard <maxime@cerno.tech>
+---
+ drivers/gpu/drm/vc4/vc4_crtc.c | 37 ++++++++++++++++++++++++++++++++--
+ 1 file changed, 35 insertions(+), 2 deletions(-)
+
+--- a/drivers/gpu/drm/vc4/vc4_crtc.c
++++ b/drivers/gpu/drm/vc4/vc4_crtc.c
+@@ -813,6 +813,7 @@ struct vc4_async_flip_state {
+ struct drm_pending_vblank_event *event;
+
+ struct vc4_seqno_cb cb;
++ struct dma_fence_cb fence_cb;
+ };
+
+ /* Called when the V3D execution for the BO being flipped to is done, so that
+@@ -858,6 +859,39 @@ vc4_async_page_flip_complete(struct vc4_
+ kfree(flip_state);
+ }
+
++static void vc4_async_page_flip_fence_complete(struct dma_fence *fence,
++ struct dma_fence_cb *cb)
++{
++ struct vc4_async_flip_state *flip_state =
++ container_of(cb, struct vc4_async_flip_state, fence_cb);
++
++ vc4_async_page_flip_complete(&flip_state->cb);
++ dma_fence_put(fence);
++}
++
++static int vc4_async_set_fence_cb(struct drm_device *dev,
++ struct vc4_async_flip_state *flip_state)
++{
++ struct drm_framebuffer *fb = flip_state->fb;
++ struct drm_gem_cma_object *cma_bo = drm_fb_cma_get_gem_obj(fb, 0);
++ struct vc4_dev *vc4 = to_vc4_dev(dev);
++ struct dma_fence *fence;
++
++ if (!vc4->hvs->hvs5) {
++ struct vc4_bo *bo = to_vc4_bo(&cma_bo->base);
++
++ return vc4_queue_seqno_cb(dev, &flip_state->cb, bo->seqno,
++ vc4_async_page_flip_complete);
++ }
++
++ fence = dma_fence_get(dma_resv_excl_fence(cma_bo->base.resv));
++ if (dma_fence_add_callback(fence, &flip_state->fence_cb,
++ vc4_async_page_flip_fence_complete))
++ vc4_async_page_flip_fence_complete(fence, &flip_state->fence_cb);
++
++ return 0;
++}
++
+ /* Implements async (non-vblank-synced) page flips.
+ *
+ * The page flip ioctl needs to return immediately, so we grab the
+@@ -918,8 +952,7 @@ static int vc4_async_page_flip(struct dr
+ */
+ drm_atomic_set_fb_for_plane(plane->state, fb);
+
+- vc4_queue_seqno_cb(dev, &flip_state->cb, bo->seqno,
+- vc4_async_page_flip_complete);
++ vc4_async_set_fence_cb(dev, flip_state);
+
+ /* Driver takes ownership of state on successful async commit. */
+ return 0;