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 <[email protected]> Signed-off-by: Natalie Vock <[email protected]> --- 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
