Skip to content

Commit 74145ca

Browse files
pixelclusterptr1337
authored andcommitted
drm/ttm: Be more aggressive when allocating below protection limit
When the cgroup's memory usage is below the low/min limit and allocation fails, try evicting some unprotected buffers to make space. Otherwise, application buffers may be forced to go into GTT even though usage is below the corresponding low/min limit, if other applications filled VRAM with their allocations first. Signed-off-by: Natalie Vock <natalie.vock@gmx.de>
1 parent 68ca27e commit 74145ca

1 file changed

Lines changed: 48 additions & 3 deletions

File tree

drivers/gpu/drm/ttm/ttm_bo.c

Lines changed: 48 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -496,6 +496,10 @@ struct ttm_bo_alloc_state {
496496
struct dmem_cgroup_pool_state *limit_pool;
497497
/** @in_evict: Whether we are currently evicting buffers */
498498
bool in_evict;
499+
/** @may_try_low: If only unprotected BOs, i.e. BOs whose cgroup
500+
* is exceeding its dmem low/min protection, should be considered for eviction
501+
*/
502+
bool may_try_low;
499503
};
500504

501505
/**
@@ -545,6 +549,42 @@ static int ttm_bo_alloc_at_place(struct ttm_buffer_object *bo,
545549
}
546550
}
547551

552+
/*
553+
* cgroup protection plays a special role in eviction.
554+
* Conceptually, protection of memory via the dmem cgroup controller
555+
* entitles the protected cgroup to use a certain amount of memory.
556+
* There are two types of protection - the 'low' limit is a
557+
* "best-effort" protection, whereas the 'min' limit provides a hard
558+
* guarantee that memory within the cgroup's allowance will not be
559+
* evicted under any circumstance.
560+
*
561+
* To faithfully model this concept in TTM, we also need to take cgroup
562+
* protection into account when allocating. When allocation in one
563+
* place fails, TTM will default to trying other places first before
564+
* evicting.
565+
* If the allocation is covered by dmem cgroup protection, however,
566+
* this prevents the allocation from using the memory it is "entitled"
567+
* to. To make sure unprotected allocations cannot push new protected
568+
* allocations out of places they are "entitled" to use, we should
569+
* evict buffers not covered by any cgroup protection, if this
570+
* allocation is covered by cgroup protection.
571+
*
572+
* Buffers covered by 'min' protection are a special case - the 'min'
573+
* limit is a stronger guarantee than 'low', and thus buffers protected
574+
* by 'low' but not 'min' should also be considered for eviction.
575+
* Buffers protected by 'min' will never be considered for eviction
576+
* anyway, so the regular eviction path should be triggered here.
577+
* Buffers protected by 'low' but not 'min' will take a special
578+
* eviction path that only evicts buffers covered by neither 'low' or
579+
* 'min' protections.
580+
*/
581+
if (!alloc_state->in_evict) {
582+
may_evict |= dmem_cgroup_below_min(NULL, alloc_state->charge_pool);
583+
alloc_state->may_try_low = may_evict;
584+
585+
may_evict |= dmem_cgroup_below_low(NULL, alloc_state->charge_pool);
586+
}
587+
548588
ret = ttm_resource_alloc(bo, place, res, alloc_state->charge_pool);
549589
if (ret) {
550590
if (ret == -ENOSPC && may_evict)
@@ -657,8 +697,12 @@ static int ttm_bo_evict_alloc(struct ttm_device *bdev,
657697
evict_walk.walk.arg.trylock_only = true;
658698
lret = ttm_lru_walk_for_evict(&evict_walk.walk, bdev, man, 1);
659699

660-
/* One more attempt if we hit low limit? */
661-
if (!lret && evict_walk.hit_low) {
700+
/* If we failed to find enough BOs to evict, but we skipped over
701+
* some BOs because they were covered by dmem low protection, retry
702+
* evicting these protected BOs too, except if we're told not to
703+
* consider protected BOs at all.
704+
*/
705+
if (!lret && evict_walk.hit_low && state->may_try_low) {
662706
evict_walk.try_low = true;
663707
lret = ttm_lru_walk_for_evict(&evict_walk.walk, bdev, man, 1);
664708
}
@@ -679,7 +723,8 @@ static int ttm_bo_evict_alloc(struct ttm_device *bdev,
679723
} while (!lret && evict_walk.evicted);
680724

681725
/* We hit the low limit? Try once more */
682-
if (!lret && evict_walk.hit_low && !evict_walk.try_low) {
726+
if (!lret && evict_walk.hit_low && !evict_walk.try_low &&
727+
state->may_try_low) {
683728
evict_walk.try_low = true;
684729
goto retry;
685730
}

0 commit comments

Comments
 (0)