Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2b7b3ad2 authored by Maarten Lankhorst's avatar Maarten Lankhorst Committed by Dave Airlie
Browse files

drm/ttm: cope with reserved buffers on swap list in ttm_bo_swapout, v2



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: default avatarMaarten Lankhorst <maarten.lankhorst@canonical.com>
Reviewed-by: default avatarThomas Hellstrom <thellstrom@vmware.com>
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
parent 85b144f8
Loading
Loading
Loading
Loading
+14 −30
Original line number Diff line number Diff line
@@ -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))) {
	list_for_each_entry(bo, &glob->swap_lru, swap) {
		ret = ttm_bo_reserve_locked(bo, false, true, false, 0);
		if (!ret)
			break;
	}

	if (ret) {
		spin_unlock(&glob->lru_lock);
			return -EBUSY;
		return ret;
	}

		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);

			kref_put(&bo->list_kref, ttm_bo_release_list);
			spin_lock(&glob->lru_lock);
			continue;
		}

		/**
		 * Reserve buffer. Since we unlock while sleeping, we need
		 * to re-check that nobody removed us from the swap-list while
		 * we slept.
		 */

		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);
		ret = ttm_bo_cleanup_refs_and_unlock(bo, false, false);
		kref_put(&bo->list_kref, ttm_bo_release_list);
			spin_lock(&glob->lru_lock);
		}
		return ret;
	}

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