From c5488307dd679ea3fc23fec77dbf27191c2becda Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 11 Oct 2014 23:53:35 +0100 Subject: 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 Signed-off-by: Russell King --- drivers/gpu/drm/armada/armada_crtc.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) (limited to 'drivers/gpu/drm/armada/armada_crtc.c') 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; } -- cgit v1.2.2 From 178e561f514fca4863c06a4af3501172e5627eb1 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 11 Oct 2014 23:57:04 +0100 Subject: drm/armada: convert to use vblank_on/off calls A future commit changes the way various vblank calls behave, which causes drivers to break. Converting to use the drm_crtc_vblank_on/off calls avoids this breakage. Signed-off-by: Russell King --- drivers/gpu/drm/armada/armada_crtc.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers/gpu/drm/armada/armada_crtc.c') diff --git a/drivers/gpu/drm/armada/armada_crtc.c b/drivers/gpu/drm/armada/armada_crtc.c index ef6be294c07d..e4a1490b42c2 100644 --- a/drivers/gpu/drm/armada/armada_crtc.c +++ b/drivers/gpu/drm/armada/armada_crtc.c @@ -260,7 +260,7 @@ static void armada_drm_vblank_off(struct armada_crtc *dcrtc) * Tell the DRM core that vblank IRQs aren't going to happen for * a while. This cleans up any pending vblank events for us. */ - drm_vblank_off(dev, dcrtc->num); + drm_crtc_vblank_off(&dcrtc->crtc); /* Handle any pending flip event. */ spin_lock_irq(&dev->event_lock); @@ -289,6 +289,8 @@ static void armada_drm_crtc_dpms(struct drm_crtc *crtc, int dpms) armada_drm_crtc_update(dcrtc); if (dpms_blanked(dpms)) armada_drm_vblank_off(dcrtc); + else + drm_crtc_vblank_on(&dcrtc->crtc); } } @@ -526,7 +528,7 @@ static int armada_drm_crtc_mode_set(struct drm_crtc *crtc, /* Wait for pending flips to complete */ wait_event(dcrtc->frame_wait, !dcrtc->frame_work); - drm_vblank_pre_modeset(crtc->dev, dcrtc->num); + drm_crtc_vblank_off(crtc); crtc->mode = *adj; @@ -617,7 +619,7 @@ static int armada_drm_crtc_mode_set(struct drm_crtc *crtc, armada_drm_crtc_update(dcrtc); - drm_vblank_post_modeset(crtc->dev, dcrtc->num); + drm_crtc_vblank_on(crtc); armada_drm_crtc_finish_fb(dcrtc, old_fb, dpms_blanked(dcrtc->dpms)); return 0; -- cgit v1.2.2