Commit 662bfa61 authored by Christian König's avatar Christian König Committed by Alex Deucher

drm/amdgpu: prevent command submission failures under memory pressure v2

As last resort try to evict BOs from the current working set into other
memory domains. This effectively prevents command submission failures when
VM page tables have been swapped out.

v2: fix typos
Signed-off-by: default avatarChristian König <christian.koenig@amd.com>
Reviewed-by: default avatarAlex Deucher <alexander.deucher@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 1abdc3d7
...@@ -1225,6 +1225,7 @@ struct amdgpu_cs_parser { ...@@ -1225,6 +1225,7 @@ struct amdgpu_cs_parser {
struct fence *fence; struct fence *fence;
uint64_t bytes_moved_threshold; uint64_t bytes_moved_threshold;
uint64_t bytes_moved; uint64_t bytes_moved;
struct amdgpu_bo_list_entry *evictable;
/* user fence */ /* user fence */
struct amdgpu_bo_list_entry uf_entry; struct amdgpu_bo_list_entry uf_entry;
......
...@@ -379,6 +379,58 @@ static int amdgpu_cs_bo_validate(struct amdgpu_cs_parser *p, ...@@ -379,6 +379,58 @@ static int amdgpu_cs_bo_validate(struct amdgpu_cs_parser *p,
return r; return r;
} }
/* Last resort, try to evict something from the current working set */
static bool amdgpu_cs_try_evict(struct amdgpu_cs_parser *p,
struct amdgpu_bo_list_entry *lobj)
{
uint32_t domain = lobj->robj->allowed_domains;
int r;
if (!p->evictable)
return false;
for (;&p->evictable->tv.head != &p->validated;
p->evictable = list_prev_entry(p->evictable, tv.head)) {
struct amdgpu_bo_list_entry *candidate = p->evictable;
struct amdgpu_bo *bo = candidate->robj;
u64 initial_bytes_moved;
uint32_t other;
/* If we reached our current BO we can forget it */
if (candidate == lobj)
break;
other = amdgpu_mem_type_to_domain(bo->tbo.mem.mem_type);
/* Check if this BO is in one of the domains we need space for */
if (!(other & domain))
continue;
/* Check if we can move this BO somewhere else */
other = bo->allowed_domains & ~domain;
if (!other)
continue;
/* Good we can try to move this BO somewhere else */
amdgpu_ttm_placement_from_domain(bo, other);
initial_bytes_moved = atomic64_read(&bo->adev->num_bytes_moved);
r = ttm_bo_validate(&bo->tbo, &bo->placement, true, false);
p->bytes_moved += atomic64_read(&bo->adev->num_bytes_moved) -
initial_bytes_moved;
if (unlikely(r))
break;
p->evictable = list_prev_entry(p->evictable, tv.head);
list_move(&candidate->tv.head, &p->validated);
return true;
}
return false;
}
int amdgpu_cs_list_validate(struct amdgpu_cs_parser *p, int amdgpu_cs_list_validate(struct amdgpu_cs_parser *p,
struct list_head *validated) struct list_head *validated)
{ {
...@@ -403,9 +455,15 @@ int amdgpu_cs_list_validate(struct amdgpu_cs_parser *p, ...@@ -403,9 +455,15 @@ int amdgpu_cs_list_validate(struct amdgpu_cs_parser *p,
binding_userptr = true; binding_userptr = true;
} }
r = amdgpu_cs_bo_validate(p, bo); if (p->evictable == lobj)
p->evictable = NULL;
do {
r = amdgpu_cs_bo_validate(p, bo);
} while (r == -ENOMEM && amdgpu_cs_try_evict(p, lobj));
if (r) if (r)
return r; return r;
if (bo->shadow) { if (bo->shadow) {
r = amdgpu_cs_bo_validate(p, bo); r = amdgpu_cs_bo_validate(p, bo);
if (r) if (r)
...@@ -533,6 +591,9 @@ static int amdgpu_cs_parser_bos(struct amdgpu_cs_parser *p, ...@@ -533,6 +591,9 @@ static int amdgpu_cs_parser_bos(struct amdgpu_cs_parser *p,
p->bytes_moved_threshold = amdgpu_cs_get_threshold_for_moves(p->adev); p->bytes_moved_threshold = amdgpu_cs_get_threshold_for_moves(p->adev);
p->bytes_moved = 0; p->bytes_moved = 0;
p->evictable = list_last_entry(&p->validated,
struct amdgpu_bo_list_entry,
tv.head);
r = amdgpu_cs_list_validate(p, &duplicates); r = amdgpu_cs_list_validate(p, &duplicates);
if (r) { if (r) {
......
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