diff options
author | Russell King <rmk+kernel@arm.linux.org.uk> | 2014-10-12 00:53:35 +0200 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2014-10-17 17:59:07 +0200 |
commit | c5488307dd679ea3fc23fec77dbf27191c2becda (patch) | |
tree | 2a0aa3513a08208c93decc6440322dcd48401ec0 /drivers | |
parent | drm/armada: add IRQ support back (diff) | |
download | linux-c5488307dd679ea3fc23fec77dbf27191c2becda.tar.xz linux-c5488307dd679ea3fc23fec77dbf27191c2becda.zip |
drm/armada: fix page_flip refcounting leak
A refcounting leak was found of the original frame buffer attached to
the CRTC when using the page_flip ioctl, resulting in the frame buffer
never being freed.
This was not obvious initially, as if the page flip subsequently
re-attaches the original frame buffer, the refcounts will be balanced.
However, if the original frame buffer is freed, then it will be leaked.
Fix this by ensuring that we take a reference on the incoming fb, but
rely on the queued work to drop that ref count.
Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/gpu/drm/armada/armada_crtc.c | 13 |
1 files changed, 5 insertions, 8 deletions
diff --git a/drivers/gpu/drm/armada/armada_crtc.c b/drivers/gpu/drm/armada/armada_crtc.c index 9a0cc09e6653..ef6be294c07d 100644 --- a/drivers/gpu/drm/armada/armada_crtc.c +++ b/drivers/gpu/drm/armada/armada_crtc.c @@ -945,18 +945,15 @@ static int armada_drm_crtc_page_flip(struct drm_crtc *crtc, armada_reg_queue_end(work->regs, i); /* - * Hold the old framebuffer for the work - DRM appears to drop our - * reference to the old framebuffer in drm_mode_page_flip_ioctl(). + * Ensure that we hold a reference on the new framebuffer. + * This has to match the behaviour in mode_set. */ - drm_framebuffer_reference(work->old_fb); + drm_framebuffer_reference(fb); ret = armada_drm_crtc_queue_frame_work(dcrtc, work); if (ret) { - /* - * Undo our reference above; DRM does not drop the reference - * to this object on error, so that's okay. - */ - drm_framebuffer_unreference(work->old_fb); + /* Undo our reference above */ + drm_framebuffer_unreference(fb); kfree(work); return ret; } |