diff options
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-.patch | 97 |
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; |