All of lore.kernel.org
 help / color / mirror / Atom feed
* [bug report] drm/ttm, drm_xe, Implement ttm_lru_walk_for_evict() using the guarded LRU iteration
@ 2025-06-29  3:51 Dan Carpenter
  2025-07-21 14:35 ` Thomas Hellström
  0 siblings, 1 reply; 4+ messages in thread
From: Dan Carpenter @ 2025-06-29  3:51 UTC (permalink / raw)
  To: Thomas Hellström; +Cc: dri-devel

Hello Thomas Hellström,

Commit bb8aa27eff6f ("drm/ttm, drm_xe, Implement
ttm_lru_walk_for_evict() using the guarded LRU iteration") from Jun
23, 2025 (linux-next), leads to the following (unpublished) Smatch
static checker warning:

	drivers/gpu/drm/ttm/ttm_bo_util.c:991 __ttm_bo_lru_cursor_next()
	warn: duplicate check 'res' (previous on line 952)

drivers/gpu/drm/ttm/ttm_bo_util.c
   931  __ttm_bo_lru_cursor_next(struct ttm_bo_lru_cursor *curs)
   932  {
   933          spinlock_t *lru_lock = &curs->res_curs.man->bdev->lru_lock;
   934          struct ttm_resource *res = NULL;
   935          struct ttm_buffer_object *bo;
   936          struct ttm_lru_walk_arg *arg = curs->arg;
   937          bool first = !curs->bo;
   938  
   939          ttm_bo_lru_cursor_cleanup_bo(curs);
   940  
   941          spin_lock(lru_lock);
   942          for (;;) {
   943                  int mem_type, ret = 0;
   944                  bool bo_locked = false;
   945  
   946                  if (first) {
   947                          res = ttm_resource_manager_first(&curs->res_curs);
   948                          first = false;
   949                  } else {
   950                          res = ttm_resource_manager_next(&curs->res_curs);
   951                  }
   952                  if (!res)
   953                          break;

This is the only break statement

   954  
   955                  bo = res->bo;
   956                  if (ttm_lru_walk_trylock(curs, bo))
   957                          bo_locked = true;
   958                  else if (!arg->ticket || arg->ctx->no_wait_gpu || arg->trylock_only)
   959                          continue;
   960  
   961                  if (!ttm_bo_get_unless_zero(bo)) {
   962                          if (curs->needs_unlock)
   963                                  dma_resv_unlock(bo->base.resv);
   964                          continue;
   965                  }
   966  
   967                  mem_type = res->mem_type;
   968                  spin_unlock(lru_lock);
   969                  if (!bo_locked)
   970                          ret = ttm_lru_walk_ticketlock(curs, bo);
   971  
   972                  /*
   973                   * Note that in between the release of the lru lock and the
   974                   * ticketlock, the bo may have switched resource,
   975                   * and also memory type, since the resource may have been
   976                   * freed and allocated again with a different memory type.
   977                   * In that case, just skip it.
   978                   */
   979                  curs->bo = bo;
   980                  if (!ret && bo->resource && bo->resource->mem_type == mem_type)
   981                          return bo;
   982  
   983                  ttm_bo_lru_cursor_cleanup_bo(curs);
   984                  if (ret && ret != -EALREADY)
   985                          return ERR_PTR(ret);
   986  
   987                  spin_lock(lru_lock);
   988          }
   989  
   990          spin_unlock(lru_lock);
   991          return res ? bo : NULL;

So we know res is NULL and we could just change this to "return NULL;"

   992  }

regards,
dan carpenter

^ permalink raw reply	[flat|nested] 4+ messages in thread

* [bug report] drm/ttm, drm_xe, Implement ttm_lru_walk_for_evict() using the guarded LRU iteration
@ 2025-07-01 17:49 Dan Carpenter
  2025-07-21 14:10 ` Thomas Hellström
  0 siblings, 1 reply; 4+ messages in thread
From: Dan Carpenter @ 2025-07-01 17:49 UTC (permalink / raw)
  To: Thomas Hellström; +Cc: dri-devel

Hello Thomas Hellström,

Commit bb8aa27eff6f ("drm/ttm, drm_xe, Implement
ttm_lru_walk_for_evict() using the guarded LRU iteration") from Jun
23, 2025 (linux-next), leads to the following Smatch static checker
warning:

	drivers/gpu/drm/ttm/ttm_bo_util.c:899 ttm_lru_walk_for_evict()
	warn: 'bo' isn't an ERR_PTR

drivers/gpu/drm/ttm/ttm_bo_util.c
   883  s64 ttm_lru_walk_for_evict(struct ttm_lru_walk *walk, struct ttm_device *bdev,
   884                             struct ttm_resource_manager *man, s64 target)
   885  {
   886          struct ttm_bo_lru_cursor cursor;
   887          struct ttm_buffer_object *bo;
   888          s64 progress = 0;
   889          s64 lret;
   890  
   891          ttm_bo_lru_for_each_reserved_guarded(&cursor, man, &walk->arg, bo) {
   892                  lret = walk->ops->process_bo(walk, bo);
   893                  if (lret == -EBUSY || lret == -EALREADY)
   894                          lret = 0;
   895                  progress = (lret < 0) ? lret : progress + lret;
   896                  if (progress < 0 || progress >= target)
   897                          break;
   898          }
   899          if (IS_ERR(bo))
   900                  return PTR_ERR(bo);

The ttm_bo_lru_for_each_reserved_guarded() macro checks for IS_ERR_OR_NULL()
but it can only be NULL.  These things are a bit frustrating to me because
when a function returns both error pointers and NULL then ideally there is a
reason for that and it should be documented.  "This function returns error
pointers if there is an error (kmalloc failed etc) or NULL if the object is
not found".

https://staticthinking.wordpress.com/2022/08/01/mixing-error-pointers-and-null/

   901  
   902          return progress;

It's strange to me that we returns progress values which are greater than the
target value.

   903  }

regards,
dan carpenter

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [bug report] drm/ttm, drm_xe, Implement ttm_lru_walk_for_evict() using the guarded LRU iteration
  2025-07-01 17:49 [bug report] drm/ttm, drm_xe, Implement ttm_lru_walk_for_evict() using the guarded LRU iteration Dan Carpenter
@ 2025-07-21 14:10 ` Thomas Hellström
  0 siblings, 0 replies; 4+ messages in thread
From: Thomas Hellström @ 2025-07-21 14:10 UTC (permalink / raw)
  To: Dan Carpenter; +Cc: dri-devel

Hi!

On Tue, 2025-07-01 at 12:49 -0500, Dan Carpenter wrote:
> Hello Thomas Hellström,
> 
> Commit bb8aa27eff6f ("drm/ttm, drm_xe, Implement
> ttm_lru_walk_for_evict() using the guarded LRU iteration") from Jun
> 23, 2025 (linux-next), leads to the following Smatch static checker
> warning:
> 
> 	drivers/gpu/drm/ttm/ttm_bo_util.c:899
> ttm_lru_walk_for_evict()
> 	warn: 'bo' isn't an ERR_PTR
> 
> drivers/gpu/drm/ttm/ttm_bo_util.c
>    883  s64 ttm_lru_walk_for_evict(struct ttm_lru_walk *walk, struct
> ttm_device *bdev,
>    884                             struct ttm_resource_manager *man,
> s64 target)
>    885  {
>    886          struct ttm_bo_lru_cursor cursor;
>    887          struct ttm_buffer_object *bo;
>    888          s64 progress = 0;
>    889          s64 lret;
>    890  
>    891          ttm_bo_lru_for_each_reserved_guarded(&cursor, man,
> &walk->arg, bo) {
>    892                  lret = walk->ops->process_bo(walk, bo);
>    893                  if (lret == -EBUSY || lret == -EALREADY)
>    894                          lret = 0;
>    895                  progress = (lret < 0) ? lret : progress +
> lret;
>    896                  if (progress < 0 || progress >= target)
>    897                          break;
>    898          }
>    899          if (IS_ERR(bo))
>    900                  return PTR_ERR(bo);
> 
> The ttm_bo_lru_for_each_reserved_guarded() macro checks for
> IS_ERR_OR_NULL()
> but it can only be NULL.

That's not correct.

>   These things are a bit frustrating to me because
> when a function returns both error pointers and NULL then ideally
> there is a
> reason for that and it should be documented.  "This function returns
> error
> pointers if there is an error (kmalloc failed etc) or NULL if the
> object is
> not found".

The error pointer is documented under the
ttm_bo_lru_for_each_reserved_guarded() macro. But it is true that I've
forgotten to update the doc for ttm_bo_lru_cursor_first() and
ttm_bo_lru_cursor_next() to reflect that they may return an error
pointer or NULL. I will put together a patch for that.

> 
> https://staticthinking.wordpress.com/2022/08/01/mixing-error-pointers-and-null/
> 
>    901  
>    902          return progress;
> 
> It's strange to me that we returns progress values which are greater
> than the
> target value.

This is also documented in the ttm_lru_walk_for_evict() kerneldoc. In
short a typical intended use-case is that we're requested to evict
@target pages, but since we evict a buffer object at a time (multiple
pages) the total may exceed @progress.

In any case it looks like the ttm_lru_walk_for_evict() function may go
away with upcoming patches from Christian.

Thanks,
Thomas
 

> 
>    903  }
> 
> regards,
> dan carpenter


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [bug report] drm/ttm, drm_xe, Implement ttm_lru_walk_for_evict() using the guarded LRU iteration
  2025-06-29  3:51 Dan Carpenter
@ 2025-07-21 14:35 ` Thomas Hellström
  0 siblings, 0 replies; 4+ messages in thread
From: Thomas Hellström @ 2025-07-21 14:35 UTC (permalink / raw)
  To: Dan Carpenter; +Cc: dri-devel

On Sat, 2025-06-28 at 22:51 -0500, Dan Carpenter wrote:
> Hello Thomas Hellström,
> 
> Commit bb8aa27eff6f ("drm/ttm, drm_xe, Implement
> ttm_lru_walk_for_evict() using the guarded LRU iteration") from Jun
> 23, 2025 (linux-next), leads to the following (unpublished) Smatch
> static checker warning:
> 
> 	drivers/gpu/drm/ttm/ttm_bo_util.c:991
> __ttm_bo_lru_cursor_next()
> 	warn: duplicate check 'res' (previous on line 952)
> 
> drivers/gpu/drm/ttm/ttm_bo_util.c
>    931  __ttm_bo_lru_cursor_next(struct ttm_bo_lru_cursor *curs)
>    932  {
>    933          spinlock_t *lru_lock = &curs->res_curs.man->bdev-
> >lru_lock;
>    934          struct ttm_resource *res = NULL;
>    935          struct ttm_buffer_object *bo;
>    936          struct ttm_lru_walk_arg *arg = curs->arg;
>    937          bool first = !curs->bo;
>    938  
>    939          ttm_bo_lru_cursor_cleanup_bo(curs);
>    940  
>    941          spin_lock(lru_lock);
>    942          for (;;) {
>    943                  int mem_type, ret = 0;
>    944                  bool bo_locked = false;
>    945  
>    946                  if (first) {
>    947                          res =
> ttm_resource_manager_first(&curs->res_curs);
>    948                          first = false;
>    949                  } else {
>    950                          res =
> ttm_resource_manager_next(&curs->res_curs);
>    951                  }
>    952                  if (!res)
>    953                          break;
> 
> This is the only break statement
> 
>    954  
>    955                  bo = res->bo;
>    956                  if (ttm_lru_walk_trylock(curs, bo))
>    957                          bo_locked = true;
>    958                  else if (!arg->ticket || arg->ctx-
> >no_wait_gpu || arg->trylock_only)
>    959                          continue;
>    960  
>    961                  if (!ttm_bo_get_unless_zero(bo)) {
>    962                          if (curs->needs_unlock)
>    963                                  dma_resv_unlock(bo-
> >base.resv);
>    964                          continue;
>    965                  }
>    966  
>    967                  mem_type = res->mem_type;
>    968                  spin_unlock(lru_lock);
>    969                  if (!bo_locked)
>    970                          ret = ttm_lru_walk_ticketlock(curs,
> bo);
>    971  
>    972                  /*
>    973                   * Note that in between the release of the
> lru lock and the
>    974                   * ticketlock, the bo may have switched
> resource,
>    975                   * and also memory type, since the resource
> may have been
>    976                   * freed and allocated again with a different
> memory type.
>    977                   * In that case, just skip it.
>    978                   */
>    979                  curs->bo = bo;
>    980                  if (!ret && bo->resource && bo->resource-
> >mem_type == mem_type)
>    981                          return bo;
>    982  
>    983                  ttm_bo_lru_cursor_cleanup_bo(curs);
>    984                  if (ret && ret != -EALREADY)
>    985                          return ERR_PTR(ret);
>    986  
>    987                  spin_lock(lru_lock);
>    988          }
>    989  
>    990          spin_unlock(lru_lock);
>    991          return res ? bo : NULL;
> 
> So we know res is NULL and we could just change this to "return
> NULL;"

Right.
Thanks for the report. Will put together a patch.

Thanks,
Thomas


> 
>    992  }
> 
> regards,
> dan carpenter


^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2025-07-21 14:35 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-07-01 17:49 [bug report] drm/ttm, drm_xe, Implement ttm_lru_walk_for_evict() using the guarded LRU iteration Dan Carpenter
2025-07-21 14:10 ` Thomas Hellström
  -- strict thread matches above, loose matches on Subject: below --
2025-06-29  3:51 Dan Carpenter
2025-07-21 14:35 ` Thomas Hellström

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.