diff options
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c')
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 63 |
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 */ | ||
383 | static 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 | |||
382 | int amdgpu_cs_list_validate(struct amdgpu_cs_parser *p, | 434 | int 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) { |