|
Chuck Ebbert |
a9318c9 |
From 498c555f56a02ec1059bc150cde84411ba0ac010 Mon Sep 17 00:00:00 2001
|
|
|
de4207a |
From: Dave Airlie <airlied@redhat.com>
|
|
|
de4207a |
Date: Sun, 29 May 2011 17:48:32 +1000
|
|
|
de4207a |
Subject: [PATCH] drm/radeon: fix oops in ttm reserve when pageflipping (v2)
|
|
|
de4207a |
|
|
|
de4207a |
We need to take a reference to this object, pinning doesn't take a reference
|
|
|
de4207a |
so if userspace deletes the object it can disappear even if pinned.
|
|
|
de4207a |
|
|
|
de4207a |
v2: fix error paths to unreference properly also.
|
|
|
de4207a |
|
|
|
de4207a |
should fix:
|
|
|
de4207a |
https://bugzilla.kernel.org/show_bug.cgi?id=32402
|
|
|
de4207a |
and
|
|
|
de4207a |
https://bugzilla.redhat.com/show_bug.cgi?id=680651
|
|
|
de4207a |
|
|
|
de4207a |
Signed-off-by: Dave Airlie <airlied@redhat.com>
|
|
|
de4207a |
---
|
|
|
de4207a |
drivers/gpu/drm/radeon/radeon_display.c | 13 ++++++++-----
|
|
|
de4207a |
1 files changed, 8 insertions(+), 5 deletions(-)
|
|
|
de4207a |
|
|
|
de4207a |
diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c
|
|
|
de4207a |
index ae247ee..292f73f 100644
|
|
|
de4207a |
--- a/drivers/gpu/drm/radeon/radeon_display.c
|
|
|
de4207a |
+++ b/drivers/gpu/drm/radeon/radeon_display.c
|
|
|
de4207a |
@@ -264,6 +264,8 @@ static void radeon_unpin_work_func(struct work_struct *__work)
|
|
|
de4207a |
radeon_bo_unreserve(work->old_rbo);
|
|
|
de4207a |
} else
|
|
|
de4207a |
DRM_ERROR("failed to reserve buffer after flip\n");
|
|
|
de4207a |
+
|
|
|
de4207a |
+ drm_gem_object_unreference_unlocked(work->old_rbo->gobj);
|
|
|
de4207a |
kfree(work);
|
|
|
de4207a |
}
|
|
|
de4207a |
|
|
|
de4207a |
@@ -371,6 +373,8 @@ static int radeon_crtc_page_flip(struct drm_crtc *crtc,
|
|
|
de4207a |
new_radeon_fb = to_radeon_framebuffer(fb);
|
|
|
de4207a |
/* schedule unpin of the old buffer */
|
|
|
de4207a |
obj = old_radeon_fb->obj;
|
|
|
de4207a |
+ /* take a reference to the old object */
|
|
|
de4207a |
+ drm_gem_object_reference(obj);
|
|
|
de4207a |
rbo = obj->driver_private;
|
|
|
de4207a |
work->old_rbo = rbo;
|
|
|
de4207a |
INIT_WORK(&work->work, radeon_unpin_work_func);
|
|
|
de4207a |
@@ -378,12 +382,9 @@ static int radeon_crtc_page_flip(struct drm_crtc *crtc,
|
|
|
de4207a |
/* We borrow the event spin lock for protecting unpin_work */
|
|
|
de4207a |
spin_lock_irqsave(&dev->event_lock, flags);
|
|
|
de4207a |
if (radeon_crtc->unpin_work) {
|
|
|
de4207a |
- spin_unlock_irqrestore(&dev->event_lock, flags);
|
|
|
de4207a |
- kfree(work);
|
|
|
de4207a |
- radeon_fence_unref(&fence);
|
|
|
de4207a |
-
|
|
|
de4207a |
DRM_DEBUG_DRIVER("flip queue: crtc already busy\n");
|
|
|
de4207a |
- return -EBUSY;
|
|
|
de4207a |
+ r = -EBUSY;
|
|
|
de4207a |
+ goto unlock_free;
|
|
|
de4207a |
}
|
|
|
de4207a |
radeon_crtc->unpin_work = work;
|
|
|
de4207a |
radeon_crtc->deferred_flip_completion = 0;
|
|
|
de4207a |
@@ -497,6 +498,8 @@ pflip_cleanup1:
|
|
|
de4207a |
pflip_cleanup:
|
|
|
de4207a |
spin_lock_irqsave(&dev->event_lock, flags);
|
|
|
de4207a |
radeon_crtc->unpin_work = NULL;
|
|
|
de4207a |
+unlock_free:
|
|
|
de4207a |
+ drm_gem_object_unreference_unlocked(old_radeon_fb->obj);
|
|
|
de4207a |
spin_unlock_irqrestore(&dev->event_lock, flags);
|
|
|
de4207a |
radeon_fence_unref(&fence);
|
|
|
de4207a |
kfree(work);
|
|
|
de4207a |
--
|
|
|
de4207a |
1.7.4.4
|
|
|
de4207a |
|