aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/vc4/vc4_crtc.c46
1 files changed, 45 insertions, 1 deletions
diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
index bf4667481935..c61dff594195 100644
--- a/drivers/gpu/drm/vc4/vc4_crtc.c
+++ b/drivers/gpu/drm/vc4/vc4_crtc.c
@@ -760,6 +760,7 @@ static irqreturn_t vc4_crtc_irq_handler(int irq, void *data)
760struct vc4_async_flip_state { 760struct vc4_async_flip_state {
761 struct drm_crtc *crtc; 761 struct drm_crtc *crtc;
762 struct drm_framebuffer *fb; 762 struct drm_framebuffer *fb;
763 struct drm_framebuffer *old_fb;
763 struct drm_pending_vblank_event *event; 764 struct drm_pending_vblank_event *event;
764 765
765 struct vc4_seqno_cb cb; 766 struct vc4_seqno_cb cb;
@@ -789,6 +790,23 @@ vc4_async_page_flip_complete(struct vc4_seqno_cb *cb)
789 790
790 drm_crtc_vblank_put(crtc); 791 drm_crtc_vblank_put(crtc);
791 drm_framebuffer_put(flip_state->fb); 792 drm_framebuffer_put(flip_state->fb);
793
794 /* Decrement the BO usecnt in order to keep the inc/dec calls balanced
795 * when the planes are updated through the async update path.
796 * FIXME: we should move to generic async-page-flip when it's
797 * available, so that we can get rid of this hand-made cleanup_fb()
798 * logic.
799 */
800 if (flip_state->old_fb) {
801 struct drm_gem_cma_object *cma_bo;
802 struct vc4_bo *bo;
803
804 cma_bo = drm_fb_cma_get_gem_obj(flip_state->old_fb, 0);
805 bo = to_vc4_bo(&cma_bo->base);
806 vc4_bo_dec_usecnt(bo);
807 drm_framebuffer_put(flip_state->old_fb);
808 }
809
792 kfree(flip_state); 810 kfree(flip_state);
793 811
794 up(&vc4->async_modeset); 812 up(&vc4->async_modeset);
@@ -813,9 +831,22 @@ static int vc4_async_page_flip(struct drm_crtc *crtc,
813 struct drm_gem_cma_object *cma_bo = drm_fb_cma_get_gem_obj(fb, 0); 831 struct drm_gem_cma_object *cma_bo = drm_fb_cma_get_gem_obj(fb, 0);
814 struct vc4_bo *bo = to_vc4_bo(&cma_bo->base); 832 struct vc4_bo *bo = to_vc4_bo(&cma_bo->base);
815 833
834 /* Increment the BO usecnt here, so that we never end up with an
835 * unbalanced number of vc4_bo_{dec,inc}_usecnt() calls when the
836 * plane is later updated through the non-async path.
837 * FIXME: we should move to generic async-page-flip when it's
838 * available, so that we can get rid of this hand-made prepare_fb()
839 * logic.
840 */
841 ret = vc4_bo_inc_usecnt(bo);
842 if (ret)
843 return ret;
844
816 flip_state = kzalloc(sizeof(*flip_state), GFP_KERNEL); 845 flip_state = kzalloc(sizeof(*flip_state), GFP_KERNEL);
817 if (!flip_state) 846 if (!flip_state) {
847 vc4_bo_dec_usecnt(bo);
818 return -ENOMEM; 848 return -ENOMEM;
849 }
819 850
820 drm_framebuffer_get(fb); 851 drm_framebuffer_get(fb);
821 flip_state->fb = fb; 852 flip_state->fb = fb;
@@ -826,10 +857,23 @@ static int vc4_async_page_flip(struct drm_crtc *crtc,
826 ret = down_interruptible(&vc4->async_modeset); 857 ret = down_interruptible(&vc4->async_modeset);
827 if (ret) { 858 if (ret) {
828 drm_framebuffer_put(fb); 859 drm_framebuffer_put(fb);
860 vc4_bo_dec_usecnt(bo);
829 kfree(flip_state); 861 kfree(flip_state);
830 return ret; 862 return ret;
831 } 863 }
832 864
865 /* Save the current FB before it's replaced by the new one in
866 * drm_atomic_set_fb_for_plane(). We'll need the old FB in
867 * vc4_async_page_flip_complete() to decrement the BO usecnt and keep
868 * it consistent.
869 * FIXME: we should move to generic async-page-flip when it's
870 * available, so that we can get rid of this hand-made cleanup_fb()
871 * logic.
872 */
873 flip_state->old_fb = plane->state->fb;
874 if (flip_state->old_fb)
875 drm_framebuffer_get(flip_state->old_fb);
876
833 WARN_ON(drm_crtc_vblank_get(crtc) != 0); 877 WARN_ON(drm_crtc_vblank_get(crtc) != 0);
834 878
835 /* Immediately update the plane's legacy fb pointer, so that later 879 /* Immediately update the plane's legacy fb pointer, so that later