A couple of fixes for theoretical races discovered during the lockdep discussions with Maarten Lankhorst
The ttm_mem_evict_first function could theoretically drop the lru lock without retrying if a reservation from off the LRU list ended up waiting. However, since currently there are no users that could cause a wait in that situation so this is not suitable for stable
Signed-off-by: Thomas Hellstrom thellstrom@vmware.com --- drivers/gpu/drm/ttm/ttm_bo.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index 402ab69..d42631c 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -817,11 +817,11 @@ retry: goto retry; }
- ret = ttm_bo_reserve_locked(bo, false, no_wait_reserve, false, 0); + ret = ttm_bo_reserve_locked(bo, false, true, false, 0);
if (unlikely(ret == -EBUSY)) { spin_unlock(&glob->lru_lock); - if (likely(!no_wait_gpu)) + if (likely(!no_wait_reserve)) ret = ttm_bo_wait_unreserved(bo, interruptible);
kref_put(&bo->list_kref, ttm_bo_release_list);
In theory, that function could release the lru lock between checking for bo on ddestroy list and a successful reserve if the bo was already reserved, and the function was called with waiting reserves allowed. However, all current reservers of a bo on the ddestroy list would atomically take the bo off the list after a successful reserve so this race should not have been hit, so no need to backport for stable.
This patch also fixes a case found by Maarten Lankhorst where ttm_mem_evict_first called with no_wait_gpu would incorrectly spin waiting for bo idle if trying to evict a busy buffer that also sits on the ddestroy list.
Signed-off-by: Thomas Hellstrom thellstrom@vmware.com --- drivers/gpu/drm/ttm/ttm_bo.c | 22 +++++++++++++--------- 1 files changed, 13 insertions(+), 9 deletions(-)
diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index d42631c..043cd33 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -580,6 +580,7 @@ retry: if (unlikely(ret != 0)) return ret;
+retry_reserve: spin_lock(&glob->lru_lock);
if (unlikely(list_empty(&bo->ddestroy))) { @@ -587,14 +588,20 @@ retry: return 0; }
- ret = ttm_bo_reserve_locked(bo, interruptible, - no_wait_reserve, false, 0); + ret = ttm_bo_reserve_locked(bo, false, true, false, 0);
- if (unlikely(ret != 0)) { + if (unlikely(ret == -EBUSY)) { spin_unlock(&glob->lru_lock); - return ret; + if (likely(!no_wait_reserve)) + ret = ttm_bo_wait_unreserved(bo, interruptible); + if (unlikely(ret != 0)) + return ret; + + goto retry_reserve; }
+ BUG_ON(ret != 0); + /** * We can re-check for sync object without taking * the bo::lock since setting the sync object requires @@ -810,11 +817,8 @@ retry: ret = ttm_bo_cleanup_refs(bo, interruptible, no_wait_reserve, no_wait_gpu); kref_put(&bo->list_kref, ttm_bo_release_list); - - if (likely(ret == 0 || ret == -ERESTARTSYS)) - return ret; - - goto retry; + + return ret; }
ret = ttm_bo_reserve_locked(bo, false, true, false, 0);
On Mon, Oct 22, 2012 at 02:51:24PM +0200, Thomas Hellstrom wrote:
A couple of fixes for theoretical races discovered during the lockdep discussions with Maarten Lankhorst
For the serie Reviewed-by: Jerome Glisse jglisse@redhat.com
dri-devel@lists.freedesktop.org