Merge tag 'drm-misc-fixes-2018-05-02' of git://anongit.freedesktop.org/drm/drm-misc...
authorDave Airlie <airlied@redhat.com>
Thu, 3 May 2018 01:58:39 +0000 (11:58 +1000)
committerDave Airlie <airlied@redhat.com>
Thu, 3 May 2018 01:58:39 +0000 (11:58 +1000)
vc4: Fix bo refcounts during async commits (Boris)
vga-dac: Fix edid memory leak (Sean)

Cc: Boris Brezillon <boris.brezillon@bootlin.com>
Cc: Sean Paul <seanpaul@chromium.org>
* tag 'drm-misc-fixes-2018-05-02' of git://anongit.freedesktop.org/drm/drm-misc:
  drm/bridge: vga-dac: Fix edid memory leak
  drm/vc4: Make sure vc4_bo_{inc,dec}_usecnt() calls are balanced

drivers/gpu/drm/bridge/dumb-vga-dac.c
drivers/gpu/drm/vc4/vc4_crtc.c

index 498d5948d1a8099066fc62d5305ffe64c3c84ca0..9837c8d69e6918f0418158054db605b55e082cb8 100644 (file)
@@ -56,7 +56,9 @@ static int dumb_vga_get_modes(struct drm_connector *connector)
        }
 
        drm_mode_connector_update_edid_property(connector, edid);
-       return drm_add_edid_modes(connector, edid);
+       ret = drm_add_edid_modes(connector, edid);
+       kfree(edid);
+       return ret;
 
 fallback:
        /*
index bf4667481935281526def8786619cd0a537c76f7..c61dff594195afe5b4a05d37bb3bd7c6b188b007 100644 (file)
@@ -760,6 +760,7 @@ static irqreturn_t vc4_crtc_irq_handler(int irq, void *data)
 struct vc4_async_flip_state {
        struct drm_crtc *crtc;
        struct drm_framebuffer *fb;
+       struct drm_framebuffer *old_fb;
        struct drm_pending_vblank_event *event;
 
        struct vc4_seqno_cb cb;
@@ -789,6 +790,23 @@ vc4_async_page_flip_complete(struct vc4_seqno_cb *cb)
 
        drm_crtc_vblank_put(crtc);
        drm_framebuffer_put(flip_state->fb);
+
+       /* Decrement the BO usecnt in order to keep the inc/dec calls balanced
+        * when the planes are updated through the async update path.
+        * FIXME: we should move to generic async-page-flip when it's
+        * available, so that we can get rid of this hand-made cleanup_fb()
+        * logic.
+        */
+       if (flip_state->old_fb) {
+               struct drm_gem_cma_object *cma_bo;
+               struct vc4_bo *bo;
+
+               cma_bo = drm_fb_cma_get_gem_obj(flip_state->old_fb, 0);
+               bo = to_vc4_bo(&cma_bo->base);
+               vc4_bo_dec_usecnt(bo);
+               drm_framebuffer_put(flip_state->old_fb);
+       }
+
        kfree(flip_state);
 
        up(&vc4->async_modeset);
@@ -813,9 +831,22 @@ static int vc4_async_page_flip(struct drm_crtc *crtc,
        struct drm_gem_cma_object *cma_bo = drm_fb_cma_get_gem_obj(fb, 0);
        struct vc4_bo *bo = to_vc4_bo(&cma_bo->base);
 
+       /* Increment the BO usecnt here, so that we never end up with an
+        * unbalanced number of vc4_bo_{dec,inc}_usecnt() calls when the
+        * plane is later updated through the non-async path.
+        * FIXME: we should move to generic async-page-flip when it's
+        * available, so that we can get rid of this hand-made prepare_fb()
+        * logic.
+        */
+       ret = vc4_bo_inc_usecnt(bo);
+       if (ret)
+               return ret;
+
        flip_state = kzalloc(sizeof(*flip_state), GFP_KERNEL);
-       if (!flip_state)
+       if (!flip_state) {
+               vc4_bo_dec_usecnt(bo);
                return -ENOMEM;
+       }
 
        drm_framebuffer_get(fb);
        flip_state->fb = fb;
@@ -826,10 +857,23 @@ static int vc4_async_page_flip(struct drm_crtc *crtc,
        ret = down_interruptible(&vc4->async_modeset);
        if (ret) {
                drm_framebuffer_put(fb);
+               vc4_bo_dec_usecnt(bo);
                kfree(flip_state);
                return ret;
        }
 
+       /* Save the current FB before it's replaced by the new one in
+        * drm_atomic_set_fb_for_plane(). We'll need the old FB in
+        * vc4_async_page_flip_complete() to decrement the BO usecnt and keep
+        * it consistent.
+        * FIXME: we should move to generic async-page-flip when it's
+        * available, so that we can get rid of this hand-made cleanup_fb()
+        * logic.
+        */
+       flip_state->old_fb = plane->state->fb;
+       if (flip_state->old_fb)
+               drm_framebuffer_get(flip_state->old_fb);
+
        WARN_ON(drm_crtc_vblank_get(crtc) != 0);
 
        /* Immediately update the plane's legacy fb pointer, so that later