Commit e300180f authored by Michel Dänzer's avatar Michel Dänzer Committed by Alex Deucher

drm/ttm: Don't evict BOs outside of the requested placement range

The radeon driver uses placement range restrictions for several reasons,
in particular to make sure BOs in VRAM can be accessed by the CPU, e.g.
during a page fault.

Without this change, TTM could evict other BOs while trying to satisfy
the requested placement, even if the evicted BOs were outside of the
requested placement range. Doing so didn't free up any space in the
requested placement range, so the (potentially high) eviction cost was
incurred for no benefit.

Nominating for stable because radeon driver changes in 3.17 made this
much more noticeable than before.

Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=84662
Cc: stable@vger.kernel.org
Signed-off-by: default avatarMichel Dänzer <michel.daenzer@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 9ace2ef7
...@@ -709,6 +709,7 @@ static int ttm_bo_evict(struct ttm_buffer_object *bo, bool interruptible, ...@@ -709,6 +709,7 @@ static int ttm_bo_evict(struct ttm_buffer_object *bo, bool interruptible,
static int ttm_mem_evict_first(struct ttm_bo_device *bdev, static int ttm_mem_evict_first(struct ttm_bo_device *bdev,
uint32_t mem_type, uint32_t mem_type,
const struct ttm_place *place,
bool interruptible, bool interruptible,
bool no_wait_gpu) bool no_wait_gpu)
{ {
...@@ -720,9 +721,22 @@ static int ttm_mem_evict_first(struct ttm_bo_device *bdev, ...@@ -720,9 +721,22 @@ static int ttm_mem_evict_first(struct ttm_bo_device *bdev,
spin_lock(&glob->lru_lock); spin_lock(&glob->lru_lock);
list_for_each_entry(bo, &man->lru, lru) { list_for_each_entry(bo, &man->lru, lru) {
ret = __ttm_bo_reserve(bo, false, true, false, NULL); ret = __ttm_bo_reserve(bo, false, true, false, NULL);
if (!ret) if (!ret) {
if (place && (place->fpfn || place->lpfn)) {
/* Don't evict this BO if it's outside of the
* requested placement range
*/
if (place->fpfn >= (bo->mem.start + bo->mem.size) ||
(place->lpfn && place->lpfn <= bo->mem.start)) {
__ttm_bo_unreserve(bo);
ret = -EBUSY;
continue;
}
}
break; break;
} }
}
if (ret) { if (ret) {
spin_unlock(&glob->lru_lock); spin_unlock(&glob->lru_lock);
...@@ -782,7 +796,7 @@ static int ttm_bo_mem_force_space(struct ttm_buffer_object *bo, ...@@ -782,7 +796,7 @@ static int ttm_bo_mem_force_space(struct ttm_buffer_object *bo,
return ret; return ret;
if (mem->mm_node) if (mem->mm_node)
break; break;
ret = ttm_mem_evict_first(bdev, mem_type, ret = ttm_mem_evict_first(bdev, mem_type, place,
interruptible, no_wait_gpu); interruptible, no_wait_gpu);
if (unlikely(ret != 0)) if (unlikely(ret != 0))
return ret; return ret;
...@@ -1233,7 +1247,7 @@ static int ttm_bo_force_list_clean(struct ttm_bo_device *bdev, ...@@ -1233,7 +1247,7 @@ static int ttm_bo_force_list_clean(struct ttm_bo_device *bdev,
spin_lock(&glob->lru_lock); spin_lock(&glob->lru_lock);
while (!list_empty(&man->lru)) { while (!list_empty(&man->lru)) {
spin_unlock(&glob->lru_lock); spin_unlock(&glob->lru_lock);
ret = ttm_mem_evict_first(bdev, mem_type, false, false); ret = ttm_mem_evict_first(bdev, mem_type, NULL, false, false);
if (ret) { if (ret) {
if (allow_errors) { if (allow_errors) {
return ret; return ret;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment