4242#include <linux/file.h>
4343#include <linux/module.h>
4444#include <linux/atomic.h>
45+ #include <linux/cgroup_dmem.h>
4546#include <linux/dma-resv.h>
4647
4748#include "ttm_module.h"
@@ -499,6 +500,13 @@ struct ttm_bo_evict_walk {
499500 struct ttm_resource * * res ;
500501 /** @evicted: Number of successful evictions. */
501502 unsigned long evicted ;
503+
504+ /** @limit_pool: Which pool limit we should test against */
505+ struct dmem_cgroup_pool_state * limit_pool ;
506+ /** @try_low: Whether we should attempt to evict BO's with low watermark threshold */
507+ bool try_low ;
508+ /** @hit_low: If we cannot evict a bo when @try_low is false (first pass) */
509+ bool hit_low ;
502510};
503511
504512static s64 ttm_bo_evict_cb (struct ttm_lru_walk * walk , struct ttm_buffer_object * bo )
@@ -507,6 +515,10 @@ static s64 ttm_bo_evict_cb(struct ttm_lru_walk *walk, struct ttm_buffer_object *
507515 container_of (walk , typeof (* evict_walk ), walk );
508516 s64 lret ;
509517
518+ if (!dmem_cgroup_state_evict_valuable (evict_walk -> limit_pool , bo -> resource -> css ,
519+ evict_walk -> try_low , & evict_walk -> hit_low ))
520+ return 0 ;
521+
510522 if (bo -> pin_count || !bo -> bdev -> funcs -> eviction_valuable (bo , evict_walk -> place ))
511523 return 0 ;
512524
@@ -524,7 +536,7 @@ static s64 ttm_bo_evict_cb(struct ttm_lru_walk *walk, struct ttm_buffer_object *
524536 evict_walk -> evicted ++ ;
525537 if (evict_walk -> res )
526538 lret = ttm_resource_alloc (evict_walk -> evictor , evict_walk -> place ,
527- evict_walk -> res );
539+ evict_walk -> res , NULL );
528540 if (lret == 0 )
529541 return 1 ;
530542out :
@@ -545,7 +557,8 @@ static int ttm_bo_evict_alloc(struct ttm_device *bdev,
545557 struct ttm_buffer_object * evictor ,
546558 struct ttm_operation_ctx * ctx ,
547559 struct ww_acquire_ctx * ticket ,
548- struct ttm_resource * * res )
560+ struct ttm_resource * * res ,
561+ struct dmem_cgroup_pool_state * limit_pool )
549562{
550563 struct ttm_bo_evict_walk evict_walk = {
551564 .walk = {
@@ -556,22 +569,39 @@ static int ttm_bo_evict_alloc(struct ttm_device *bdev,
556569 .place = place ,
557570 .evictor = evictor ,
558571 .res = res ,
572+ .limit_pool = limit_pool ,
559573 };
560574 s64 lret ;
561575
562576 evict_walk .walk .trylock_only = true;
563577 lret = ttm_lru_walk_for_evict (& evict_walk .walk , bdev , man , 1 );
578+
579+ /* One more attempt if we hit low limit? */
580+ if (!lret && evict_walk .hit_low ) {
581+ evict_walk .try_low = true;
582+ lret = ttm_lru_walk_for_evict (& evict_walk .walk , bdev , man , 1 );
583+ }
564584 if (lret || !ticket )
565585 goto out ;
566586
587+ /* Reset low limit */
588+ evict_walk .try_low = evict_walk .hit_low = false;
567589 /* If ticket-locking, repeat while making progress. */
568590 evict_walk .walk .trylock_only = false;
591+
592+ retry :
569593 do {
570594 /* The walk may clear the evict_walk.walk.ticket field */
571595 evict_walk .walk .ticket = ticket ;
572596 evict_walk .evicted = 0 ;
573597 lret = ttm_lru_walk_for_evict (& evict_walk .walk , bdev , man , 1 );
574598 } while (!lret && evict_walk .evicted );
599+
600+ /* We hit the low limit? Try once more */
601+ if (!lret && evict_walk .hit_low && !evict_walk .try_low ) {
602+ evict_walk .try_low = true;
603+ goto retry ;
604+ }
575605out :
576606 if (lret < 0 )
577607 return lret ;
@@ -689,6 +719,7 @@ static int ttm_bo_alloc_resource(struct ttm_buffer_object *bo,
689719
690720 for (i = 0 ; i < placement -> num_placement ; ++ i ) {
691721 const struct ttm_place * place = & placement -> placement [i ];
722+ struct dmem_cgroup_pool_state * limit_pool = NULL ;
692723 struct ttm_resource_manager * man ;
693724 bool may_evict ;
694725
@@ -701,15 +732,20 @@ static int ttm_bo_alloc_resource(struct ttm_buffer_object *bo,
701732 continue ;
702733
703734 may_evict = (force_space && place -> mem_type != TTM_PL_SYSTEM );
704- ret = ttm_resource_alloc (bo , place , res );
735+ ret = ttm_resource_alloc (bo , place , res , force_space ? & limit_pool : NULL );
705736 if (ret ) {
706- if (ret != - ENOSPC )
737+ if (ret != - ENOSPC && ret != - EAGAIN ) {
738+ dmem_cgroup_pool_state_put (limit_pool );
707739 return ret ;
708- if (!may_evict )
740+ }
741+ if (!may_evict ) {
742+ dmem_cgroup_pool_state_put (limit_pool );
709743 continue ;
744+ }
710745
711746 ret = ttm_bo_evict_alloc (bdev , man , place , bo , ctx ,
712- ticket , res );
747+ ticket , res , limit_pool );
748+ dmem_cgroup_pool_state_put (limit_pool );
713749 if (ret == - EBUSY )
714750 continue ;
715751 if (ret )
@@ -1056,6 +1092,8 @@ struct ttm_bo_swapout_walk {
10561092 struct ttm_lru_walk walk ;
10571093 /** @gfp_flags: The gfp flags to use for ttm_tt_swapout() */
10581094 gfp_t gfp_flags ;
1095+
1096+ bool hit_low , evict_low ;
10591097};
10601098
10611099static s64
@@ -1106,7 +1144,7 @@ ttm_bo_swapout_cb(struct ttm_lru_walk *walk, struct ttm_buffer_object *bo)
11061144
11071145 memset (& hop , 0 , sizeof (hop ));
11081146 place .mem_type = TTM_PL_SYSTEM ;
1109- ret = ttm_resource_alloc (bo , & place , & evict_mem );
1147+ ret = ttm_resource_alloc (bo , & place , & evict_mem , NULL );
11101148 if (ret )
11111149 goto out ;
11121150
0 commit comments