diff options
Diffstat (limited to 'drivers/gpu/drm/radeon/radeon_display.c')
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_display.c | 13 |
1 files changed, 8 insertions, 5 deletions
diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index ae247eec87c0..292f73f0ddbd 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c @@ -264,6 +264,8 @@ static void radeon_unpin_work_func(struct work_struct *__work) radeon_bo_unreserve(work->old_rbo); } else DRM_ERROR("failed to reserve buffer after flip\n"); + + drm_gem_object_unreference_unlocked(&work->old_rbo->gem_base); kfree(work); } @@ -371,6 +373,8 @@ static int radeon_crtc_page_flip(struct drm_crtc *crtc, new_radeon_fb = to_radeon_framebuffer(fb); /* schedule unpin of the old buffer */ obj = old_radeon_fb->obj; + /* take a reference to the old object */ + drm_gem_object_reference(obj); rbo = gem_to_radeon_bo(obj); work->old_rbo = rbo; INIT_WORK(&work->work, radeon_unpin_work_func); @@ -378,12 +382,9 @@ static int radeon_crtc_page_flip(struct drm_crtc *crtc, /* We borrow the event spin lock for protecting unpin_work */ spin_lock_irqsave(&dev->event_lock, flags); if (radeon_crtc->unpin_work) { - spin_unlock_irqrestore(&dev->event_lock, flags); - kfree(work); - radeon_fence_unref(&fence); - DRM_DEBUG_DRIVER("flip queue: crtc already busy\n"); - return -EBUSY; + r = -EBUSY; + goto unlock_free; } radeon_crtc->unpin_work = work; radeon_crtc->deferred_flip_completion = 0; @@ -497,6 +498,8 @@ pflip_cleanup1: pflip_cleanup: spin_lock_irqsave(&dev->event_lock, flags); radeon_crtc->unpin_work = NULL; +unlock_free: + drm_gem_object_unreference_unlocked(old_radeon_fb->obj); spin_unlock_irqrestore(&dev->event_lock, flags); radeon_fence_unref(&fence); kfree(work); |