Skip to content

Commit

Permalink
drm/ttm: cope with reserved buffers on swap list in ttm_bo_swapout, v2
Browse files Browse the repository at this point in the history
Replace the while loop with a simple for each loop, and only run the
delayed destroy cleanup if we can reserve the buffer first.

No race occurs, since lru lock is never dropped any more. An empty list
and a list full of unreservable buffers both cause -EBUSY to be returned,
which is identical to the previous situation.

Signed-off-by: Maarten Lankhorst <maarten.lankhorst@canonical.com>
Reviewed-by: Thomas Hellstrom <thellstrom@vmware.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
  • Loading branch information
Maarten Lankhorst authored and Dave Airlie committed Dec 10, 2012
1 parent 85b144f commit 2b7b3ad
Showing 1 changed file with 14 additions and 30 deletions.
44 changes: 14 additions & 30 deletions drivers/gpu/drm/ttm/ttm_bo.c
Original file line number Diff line number Diff line change
Expand Up @@ -1813,41 +1813,25 @@ static int ttm_bo_swapout(struct ttm_mem_shrink *shrink)
uint32_t swap_placement = (TTM_PL_FLAG_CACHED | TTM_PL_FLAG_SYSTEM);

spin_lock(&glob->lru_lock);
while (ret == -EBUSY) {
if (unlikely(list_empty(&glob->swap_lru))) {
spin_unlock(&glob->lru_lock);
return -EBUSY;
}

bo = list_first_entry(&glob->swap_lru,
struct ttm_buffer_object, swap);
kref_get(&bo->list_kref);

if (!list_empty(&bo->ddestroy)) {
ttm_bo_reserve_locked(bo, false, false, false, 0);
ttm_bo_cleanup_refs_and_unlock(bo, false, false);
list_for_each_entry(bo, &glob->swap_lru, swap) {
ret = ttm_bo_reserve_locked(bo, false, true, false, 0);
if (!ret)
break;
}

kref_put(&bo->list_kref, ttm_bo_release_list);
spin_lock(&glob->lru_lock);
continue;
}
if (ret) {
spin_unlock(&glob->lru_lock);
return ret;
}

/**
* Reserve buffer. Since we unlock while sleeping, we need
* to re-check that nobody removed us from the swap-list while
* we slept.
*/
kref_get(&bo->list_kref);

ret = ttm_bo_reserve_locked(bo, false, true, false, 0);
if (unlikely(ret == -EBUSY)) {
spin_unlock(&glob->lru_lock);
ttm_bo_wait_unreserved(bo, false);
kref_put(&bo->list_kref, ttm_bo_release_list);
spin_lock(&glob->lru_lock);
}
if (!list_empty(&bo->ddestroy)) {
ret = ttm_bo_cleanup_refs_and_unlock(bo, false, false);
kref_put(&bo->list_kref, ttm_bo_release_list);
return ret;
}

BUG_ON(ret != 0);
put_count = ttm_bo_del_from_lru(bo);
spin_unlock(&glob->lru_lock);

Expand Down

0 comments on commit 2b7b3ad

Please sign in to comment.