aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c')
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c63
1 files changed, 62 insertions, 1 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
index d7a957376a90..e29e7b9ca3a6 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
@@ -379,6 +379,58 @@ retry:
379 return r; 379 return r;
380} 380}
381 381
382/* Last resort, try to evict something from the current working set */
383static bool amdgpu_cs_try_evict(struct amdgpu_cs_parser *p,
384 struct amdgpu_bo_list_entry *lobj)
385{
386 uint32_t domain = lobj->robj->allowed_domains;
387 int r;
388
389 if (!p->evictable)
390 return false;
391
392 for (;&p->evictable->tv.head != &p->validated;
393 p->evictable = list_prev_entry(p->evictable, tv.head)) {
394
395 struct amdgpu_bo_list_entry *candidate = p->evictable;
396 struct amdgpu_bo *bo = candidate->robj;
397 u64 initial_bytes_moved;
398 uint32_t other;
399
400 /* If we reached our current BO we can forget it */
401 if (candidate == lobj)
402 break;
403
404 other = amdgpu_mem_type_to_domain(bo->tbo.mem.mem_type);
405
406 /* Check if this BO is in one of the domains we need space for */
407 if (!(other & domain))
408 continue;
409
410 /* Check if we can move this BO somewhere else */
411 other = bo->allowed_domains & ~domain;
412 if (!other)
413 continue;
414
415 /* Good we can try to move this BO somewhere else */
416 amdgpu_ttm_placement_from_domain(bo, other);
417 initial_bytes_moved = atomic64_read(&bo->adev->num_bytes_moved);
418 r = ttm_bo_validate(&bo->tbo, &bo->placement, true, false);
419 p->bytes_moved += atomic64_read(&bo->adev->num_bytes_moved) -
420 initial_bytes_moved;
421
422 if (unlikely(r))
423 break;
424
425 p->evictable = list_prev_entry(p->evictable, tv.head);
426 list_move(&candidate->tv.head, &p->validated);
427
428 return true;
429 }
430
431 return false;
432}
433
382int amdgpu_cs_list_validate(struct amdgpu_cs_parser *p, 434int amdgpu_cs_list_validate(struct amdgpu_cs_parser *p,
383 struct list_head *validated) 435 struct list_head *validated)
384{ 436{
@@ -403,9 +455,15 @@ int amdgpu_cs_list_validate(struct amdgpu_cs_parser *p,
403 binding_userptr = true; 455 binding_userptr = true;
404 } 456 }
405 457
406 r = amdgpu_cs_bo_validate(p, bo); 458 if (p->evictable == lobj)
459 p->evictable = NULL;
460
461 do {
462 r = amdgpu_cs_bo_validate(p, bo);
463 } while (r == -ENOMEM && amdgpu_cs_try_evict(p, lobj));
407 if (r) 464 if (r)
408 return r; 465 return r;
466
409 if (bo->shadow) { 467 if (bo->shadow) {
410 r = amdgpu_cs_bo_validate(p, bo); 468 r = amdgpu_cs_bo_validate(p, bo);
411 if (r) 469 if (r)
@@ -533,6 +591,9 @@ static int amdgpu_cs_parser_bos(struct amdgpu_cs_parser *p,
533 591
534 p->bytes_moved_threshold = amdgpu_cs_get_threshold_for_moves(p->adev); 592 p->bytes_moved_threshold = amdgpu_cs_get_threshold_for_moves(p->adev);
535 p->bytes_moved = 0; 593 p->bytes_moved = 0;
594 p->evictable = list_last_entry(&p->validated,
595 struct amdgpu_bo_list_entry,
596 tv.head);
536 597
537 r = amdgpu_cs_list_validate(p, &duplicates); 598 r = amdgpu_cs_list_validate(p, &duplicates);
538 if (r) { 599 if (r) {