[PATCH v2 09/10] drm/ttm: support using drm_exec during eviction v4
From: Natalie Vock
Date: Mon Jul 06 2026 - 07:06:54 EST
Allow specifying a drm_exec object in TTMs operation context which is
used to lock objects during eviction.
This allows to handle deadlocks much more gracefully and with that
avoid returning -ENOMEM on heavily contended domains.
v2: rebased on top of Thomas work
v3: rebased again
v4: rebased, fixed locks of already-reserved buffers being dropped
Signed-off-by: Christian König <christian.koenig@xxxxxxx>
Signed-off-by: Natalie Vock <nat@xxxxxxxxxxxxxxxx>
---
drivers/gpu/drm/ttm/ttm_bo_util.c | 30 ++++++++++++++++++++++--------
include/drm/ttm/ttm_bo.h | 5 +++++
2 files changed, 27 insertions(+), 8 deletions(-)
diff --git a/drivers/gpu/drm/ttm/ttm_bo_util.c b/drivers/gpu/drm/ttm/ttm_bo_util.c
index a53b25e8c2967..96699532817c2 100644
--- a/drivers/gpu/drm/ttm/ttm_bo_util.c
+++ b/drivers/gpu/drm/ttm/ttm_bo_util.c
@@ -38,6 +38,7 @@
#include <drm/ttm/ttm_tt.h>
#include <drm/drm_cache.h>
+#include <drm/drm_exec.h>
#include "ttm_bo_internal.h"
@@ -837,6 +838,8 @@ static bool ttm_lru_walk_trylock(struct ttm_bo_lru_cursor *curs,
struct ttm_operation_ctx *ctx = curs->arg->ctx;
curs->needs_unlock = false;
+ if (ctx->exec)
+ return false;
if (dma_resv_trylock(bo->base.resv)) {
curs->needs_unlock = true;
@@ -857,7 +860,9 @@ static int ttm_lru_walk_ticketlock(struct ttm_bo_lru_cursor *curs,
struct ttm_lru_walk_arg *arg = curs->arg;
int ret;
- if (arg->ctx->interruptible)
+ if (arg->ctx->exec)
+ ret = drm_exec_lock_obj_report_dup(arg->ctx->exec, &bo->base);
+ else if (arg->ctx->interruptible)
ret = dma_resv_lock_interruptible(bo->base.resv, arg->ticket);
else
ret = dma_resv_lock(bo->base.resv, arg->ticket);
@@ -871,7 +876,11 @@ static int ttm_lru_walk_ticketlock(struct ttm_bo_lru_cursor *curs,
* trylocking for this walk.
*/
arg->ticket = NULL;
- } else if (ret == -EDEADLK) {
+
+ } else if (arg->ctx->exec && arg->ctx->allow_res_evict &&
+ ret == -EALREADY) {
+ ret = 0;
+ } else if (!arg->ctx->exec && ret == -EDEADLK) {
/* Caller needs to exit the ww transaction. */
ret = -ENOSPC;
}
@@ -937,12 +946,17 @@ static void ttm_bo_lru_cursor_cleanup_bo(struct ttm_bo_lru_cursor *curs)
{
struct ttm_buffer_object *bo = curs->bo;
- if (bo) {
- if (curs->needs_unlock)
+ if (!bo)
+ return;
+
+ if (curs->needs_unlock) {
+ if (curs->arg->ctx->exec)
+ drm_exec_unlock_obj(curs->arg->ctx->exec, &bo->base);
+ else
dma_resv_unlock(bo->base.resv);
- ttm_bo_put(bo);
- curs->bo = NULL;
}
+ ttm_bo_put(bo);
+ curs->bo = NULL;
}
/**
@@ -1016,8 +1030,8 @@ __ttm_bo_lru_cursor_next(struct ttm_bo_lru_cursor *curs)
if (ttm_lru_walk_trylock(curs, bo)) {
bo_locked = true;
- } else if (!arg->ticket || arg->ctx->no_wait_gpu ||
- arg->trylock_only) {
+ } else if ((!arg->ticket || arg->ctx->no_wait_gpu ||
+ arg->trylock_only) && !arg->ctx->exec) {
spin_unlock(lru_lock);
ttm_bo_put(bo);
spin_lock(lru_lock);
diff --git a/include/drm/ttm/ttm_bo.h b/include/drm/ttm/ttm_bo.h
index a4060e44d23d0..156444b5e85d8 100644
--- a/include/drm/ttm/ttm_bo.h
+++ b/include/drm/ttm/ttm_bo.h
@@ -187,6 +187,11 @@ struct ttm_operation_ctx {
* @bytes_moved: Statistics on how many bytes have been moved.
*/
uint64_t bytes_moved;
+ /**
+ * @exec: optional drm_exec object to use for locking BOs and
+ * tracking which are locked.
+ */
+ struct drm_exec *exec;
};
/**
--
2.55.0