On Tue, 2026-10-27 at 15:49 -0700, Matthew Brost wrote:
> Drivers walking a manager's LRU with
> ttm_bo_lru_for_each_reserved_guarded()
> may decide that the rest of the current priority isn't worth walking,
> for example when the priority is roughly age ordered and the walk hit
> a BO that is still too hot to evict. Today the only option is to stop
> the walk altogether, which also gives up on the remaining priorities.
> 
> Add ttm_resource_manager_next_priority() to move a resource cursor to
> the start of the next priority, and ttm_bo_lru_cursor_skip_priority()
> to make the next ttm_bo_lru_cursor_next() use it.
> 
> While at it, stop incrementing the cursor priority past the last
> valid
> priority once the iteration is done.
> 
> Assisted-by: LLM
> Signed-off-by: Matthew Brost <[email protected]>

Reviewed-by: Thomas Hellström <[email protected]>

> ---
>  drivers/gpu/drm/ttm/ttm_bo_util.c  |  3 +++
>  drivers/gpu/drm/ttm/ttm_resource.c | 35 ++++++++++++++++++++++++++--
> --
>  include/drm/ttm/ttm_bo.h           | 19 ++++++++++++++++
>  include/drm/ttm/ttm_resource.h     |  2 ++
>  4 files changed, 55 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/gpu/drm/ttm/ttm_bo_util.c
> b/drivers/gpu/drm/ttm/ttm_bo_util.c
> index f9458a4d5a09..d626f014e61f 100644
> --- a/drivers/gpu/drm/ttm/ttm_bo_util.c
> +++ b/drivers/gpu/drm/ttm/ttm_bo_util.c
> @@ -997,6 +997,9 @@ __ttm_bo_lru_cursor_next(struct ttm_bo_lru_cursor
> *curs)
>               if (first) {
>                       res = ttm_resource_manager_first(&curs-
> >res_curs);
>                       first = false;
> +             } else if (curs->skip_priority) {
> +                     res =
> ttm_resource_manager_next_priority(&curs->res_curs);
> +                     curs->skip_priority = false;
>               } else {
>                       res = ttm_resource_manager_next(&curs-
> >res_curs);
>               }
> diff --git a/drivers/gpu/drm/ttm/ttm_resource.c
> b/drivers/gpu/drm/ttm/ttm_resource.c
> index 4e6d3d658d85..e631507d7aa1 100644
> --- a/drivers/gpu/drm/ttm/ttm_resource.c
> +++ b/drivers/gpu/drm/ttm/ttm_resource.c
> @@ -674,6 +674,17 @@ ttm_resource_cursor_check_bulk(struct
> ttm_resource_cursor *cursor,
>       }
>  }
>  
> +static bool ttm_resource_cursor_next_priority(struct
> ttm_resource_cursor *cursor)
> +{
> +     if (cursor->priority + 1 >= TTM_MAX_BO_PRIORITY)
> +             return false;
> +
> +     list_move(&cursor->hitch.link, &cursor->man->lru[++cursor-
> >priority]);
> +     ttm_resource_cursor_clear_bulk(cursor);
> +
> +     return true;
> +}
> +
>  /**
>   * ttm_resource_manager_first() - Start iterating over the resources
>   * of a resource manager
> @@ -723,16 +734,32 @@ ttm_resource_manager_next(struct
> ttm_resource_cursor *cursor)
>                       }
>               }
>  
> -             if (++cursor->priority >= TTM_MAX_BO_PRIORITY)
> +             if (!ttm_resource_cursor_next_priority(cursor))
>                       break;
> -
> -             list_move(&cursor->hitch.link, &man->lru[cursor-
> >priority]);
> -             ttm_resource_cursor_clear_bulk(cursor);
>       }
>  
>       return NULL;
>  }
>  
> +/**
> + * ttm_resource_manager_next_priority() - Skip the rest of the
> current
> + * priority and continue iterating at the next one
> + * @cursor: cursor to record the position
> + *
> + * Return: the first resource of the next non-empty priority, or
> NULL if
> + * there is none.
> + */
> +struct ttm_resource *
> +ttm_resource_manager_next_priority(struct ttm_resource_cursor
> *cursor)
> +{
> +     lockdep_assert_held(&cursor->man->bdev->lru_lock);
> +
> +     if (!ttm_resource_cursor_next_priority(cursor))
> +             return NULL;
> +
> +     return ttm_resource_manager_next(cursor);
> +}
> +
>  /**
>   * ttm_lru_first_res_or_null() - Return the first resource on an lru
> list
>   * @head: The list head of the lru list.
> diff --git a/include/drm/ttm/ttm_bo.h b/include/drm/ttm/ttm_bo.h
> index 32791c4db2a9..2fc517dbf03d 100644
> --- a/include/drm/ttm/ttm_bo.h
> +++ b/include/drm/ttm/ttm_bo.h
> @@ -507,10 +507,29 @@ struct ttm_bo_lru_cursor {
>        * unlock before the next iteration or after loop exit.
>        */
>       bool needs_unlock;
> +     /**
> +      * @skip_priority: Continue at the next LRU priority on the
> next
> +      * iteration. See ttm_bo_lru_cursor_skip_priority().
> +      */
> +     bool skip_priority;
>       /** @arg: Pointer to common BO LRU walk arguments. */
>       struct ttm_lru_walk_arg *arg;
>  };
>  
> +/**
> + * ttm_bo_lru_cursor_skip_priority() - Skip the rest of the current
> priority
> + * @curs: The cursor.
> + *
> + * Make the next ttm_bo_lru_cursor_next() skip the remaining buffer
> objects
> + * of the current LRU priority and continue at the next priority,
> for
> + * example when the caller decides the rest of the priority isn't
> worth
> + * walking.
> + */
> +static inline void ttm_bo_lru_cursor_skip_priority(struct
> ttm_bo_lru_cursor *curs)
> +{
> +     curs->skip_priority = true;
> +}
> +
>  void ttm_bo_lru_cursor_fini(struct ttm_bo_lru_cursor *curs);
>  
>  struct ttm_bo_lru_cursor *
> diff --git a/include/drm/ttm/ttm_resource.h
> b/include/drm/ttm/ttm_resource.h
> index 714c533622c2..8cd70d1e5481 100644
> --- a/include/drm/ttm/ttm_resource.h
> +++ b/include/drm/ttm/ttm_resource.h
> @@ -499,6 +499,8 @@ struct ttm_resource *
>  ttm_resource_manager_first(struct ttm_resource_cursor *cursor);
>  struct ttm_resource *
>  ttm_resource_manager_next(struct ttm_resource_cursor *cursor);
> +struct ttm_resource *
> +ttm_resource_manager_next_priority(struct ttm_resource_cursor
> *cursor);
>  
>  struct ttm_resource *
>  ttm_lru_first_res_or_null(struct list_head *head);

Reply via email to