aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Hellstrom <thellstrom@vmware.com>2009-12-02 12:33:46 -0500
committerDave Airlie <airlied@redhat.com>2009-12-16 00:34:40 -0500
commit9c51ba1db37cab780f38b2210913959f22d7b830 (patch)
tree78136ca9c2fc00cd0550703fe07ae7ada55c11b9
parentaaa207369436d04bb85382ddbb688a5b9461fd21 (diff)
drm/ttm: Fix potential ttm_mem_evict_first races.
1) The function was previously called with a potentially empty LRU list which would have lead to an OOPS or servere corruption. 2) In rare cases, after reservation has succeeded, another process may already have evicted it or even pinned it. We must revalidate the buffer status after releasing the lru lock. Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com> Signed-off-by: Dave Airlie <airlied@redhat.com>
-rw-r--r--drivers/gpu/drm/ttm/ttm_bo.c36
1 files changed, 31 insertions, 5 deletions
diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c
index 7927fe99d017..826240d4d675 100644
--- a/drivers/gpu/drm/ttm/ttm_bo.c
+++ b/drivers/gpu/drm/ttm/ttm_bo.c
@@ -685,19 +685,45 @@ static int ttm_mem_evict_first(struct ttm_bo_device *bdev,
685 struct ttm_buffer_object *bo; 685 struct ttm_buffer_object *bo;
686 int ret, put_count = 0; 686 int ret, put_count = 0;
687 687
688retry:
688 spin_lock(&glob->lru_lock); 689 spin_lock(&glob->lru_lock);
690 if (list_empty(&man->lru)) {
691 spin_unlock(&glob->lru_lock);
692 return -EBUSY;
693 }
694
689 bo = list_first_entry(&man->lru, struct ttm_buffer_object, lru); 695 bo = list_first_entry(&man->lru, struct ttm_buffer_object, lru);
690 kref_get(&bo->list_kref); 696 kref_get(&bo->list_kref);
691 ret = ttm_bo_reserve_locked(bo, interruptible, no_wait, false, 0); 697
692 if (likely(ret == 0)) 698 ret = ttm_bo_reserve_locked(bo, false, true, false, 0);
693 put_count = ttm_bo_del_from_lru(bo); 699
700 if (unlikely(ret == -EBUSY)) {
701 spin_unlock(&glob->lru_lock);
702 if (likely(!no_wait))
703 ret = ttm_bo_wait_unreserved(bo, interruptible);
704
705 kref_put(&bo->list_kref, ttm_bo_release_list);
706
707 /**
708 * We *need* to retry after releasing the lru lock.
709 */
710
711 if (unlikely(ret != 0))
712 return ret;
713 goto retry;
714 }
715
716 put_count = ttm_bo_del_from_lru(bo);
694 spin_unlock(&glob->lru_lock); 717 spin_unlock(&glob->lru_lock);
695 if (unlikely(ret != 0)) 718
696 return ret; 719 BUG_ON(ret != 0);
720
697 while (put_count--) 721 while (put_count--)
698 kref_put(&bo->list_kref, ttm_bo_ref_bug); 722 kref_put(&bo->list_kref, ttm_bo_ref_bug);
723
699 ret = ttm_bo_evict(bo, interruptible, no_wait); 724 ret = ttm_bo_evict(bo, interruptible, no_wait);
700 ttm_bo_unreserve(bo); 725 ttm_bo_unreserve(bo);
726
701 kref_put(&bo->list_kref, ttm_bo_release_list); 727 kref_put(&bo->list_kref, ttm_bo_release_list);
702 return ret; 728 return ret;
703} 729}