diff options
Diffstat (limited to 'common/recipes-kernel/linux/linux-yocto-4.19.8/2039-drm-ttm-fix-busy-memory-to-fail-other-user-v10.patch')
-rw-r--r-- | common/recipes-kernel/linux/linux-yocto-4.19.8/2039-drm-ttm-fix-busy-memory-to-fail-other-user-v10.patch | 173 |
1 files changed, 173 insertions, 0 deletions
diff --git a/common/recipes-kernel/linux/linux-yocto-4.19.8/2039-drm-ttm-fix-busy-memory-to-fail-other-user-v10.patch b/common/recipes-kernel/linux/linux-yocto-4.19.8/2039-drm-ttm-fix-busy-memory-to-fail-other-user-v10.patch new file mode 100644 index 00000000..5a620a2e --- /dev/null +++ b/common/recipes-kernel/linux/linux-yocto-4.19.8/2039-drm-ttm-fix-busy-memory-to-fail-other-user-v10.patch @@ -0,0 +1,173 @@ +From 0d738510e75bcf8974def92502d4a557c80d33fc Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Christian=20K=C3=B6nig?= <christian.koenig@amd.com> +Date: Wed, 22 May 2019 09:51:47 +0200 +Subject: [PATCH 2039/2940] drm/ttm: fix busy memory to fail other user v10 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +BOs on the LRU might be blocked during command submission +and cause OOM situations. + +Avoid this by blocking for the first busy BO not locked by +the same ticket as the BO we are searching space for. + +v10: completely start over with the patch since we didn't + handled a whole bunch of corner cases. + +Change-Id: I65309984703ef5acc83ef0bfa7c35ad24150fe9d +Signed-off-by: Christian König <christian.koenig@amd.com> +Reviewed-by: Chunming Zhou <david1.zhou@amd.com> +Tested-by: Pierre-Eric Pelloux-Prayer <pierre-eric.pelloux-prayer@amd.com> +Signed-off-by: Chaudhary Amit Kumar <Chaudharyamit.Kumar@amd.com> +--- + drivers/gpu/drm/ttm/ttm_bo.c | 77 +++++++++++++++++++++++++++++++----- + 1 file changed, 67 insertions(+), 10 deletions(-) + +diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c +index 0afa619c49ab..40b4b1bcd258 100644 +--- a/drivers/gpu/drm/ttm/ttm_bo.c ++++ b/drivers/gpu/drm/ttm/ttm_bo.c +@@ -779,7 +779,7 @@ EXPORT_SYMBOL(ttm_bo_eviction_valuable); + * b. Otherwise, trylock it. + */ + static bool ttm_bo_evict_swapout_allowable(struct ttm_buffer_object *bo, +- struct ttm_operation_ctx *ctx, bool *locked) ++ struct ttm_operation_ctx *ctx, bool *locked, bool *busy) + { + bool ret = false; + +@@ -789,22 +789,64 @@ static bool ttm_bo_evict_swapout_allowable(struct ttm_buffer_object *bo, + if (ctx->flags & TTM_OPT_FLAG_ALLOW_RES_EVICT + || !list_empty(&bo->ddestroy)) + ret = true; ++ *locked = false; ++ if (busy) ++ *busy = false; + } else { +- *locked = reservation_object_trylock(bo->resv); +- ret = *locked; ++ ret = reservation_object_trylock(bo->resv); ++ *locked = ret; ++ if (busy) ++ *busy = !ret; + } + + return ret; + } + ++/** ++ * ttm_mem_evict_wait_busy - wait for a busy BO to become available ++ * ++ * @busy_bo: BO which couldn't be locked with trylock ++ * @ctx: operation context ++ * @ticket: acquire ticket ++ * ++ * Try to lock a busy buffer object to avoid failing eviction. ++ */ ++static int ttm_mem_evict_wait_busy(struct ttm_buffer_object *busy_bo, ++ struct ttm_operation_ctx *ctx, ++ struct ww_acquire_ctx *ticket) ++{ ++ int r; ++ ++ if (!busy_bo || !ticket) ++ return -EBUSY; ++ ++ if (ctx->interruptible) ++ r = reservation_object_lock_interruptible(busy_bo->resv, ++ ticket); ++ else ++ r = reservation_object_lock(busy_bo->resv, ticket); ++ ++ /* ++ * TODO: It would be better to keep the BO locked until allocation is at ++ * least tried one more time, but that would mean a much larger rework ++ * of TTM. ++ */ ++ if (!r) ++ reservation_object_unlock(busy_bo->resv); ++ ++ return r == -EDEADLK ? -EAGAIN : r; ++} ++ ++ + static int ttm_mem_evict_first(struct ttm_bo_device *bdev, + uint32_t mem_type, + const struct ttm_place *place, +- struct ttm_operation_ctx *ctx) ++ struct ttm_operation_ctx *ctx, ++ struct ww_acquire_ctx *ticket) + { ++ struct ttm_buffer_object *bo = NULL, *busy_bo = NULL; + struct ttm_bo_global *glob = bdev->glob; + struct ttm_mem_type_manager *man = &bdev->man[mem_type]; +- struct ttm_buffer_object *bo = NULL; + bool locked = false; + unsigned i; + int ret; +@@ -812,8 +854,15 @@ static int ttm_mem_evict_first(struct ttm_bo_device *bdev, + spin_lock(&glob->lru_lock); + for (i = 0; i < TTM_MAX_BO_PRIORITY; ++i) { + list_for_each_entry(bo, &man->lru[i], lru) { +- if (!ttm_bo_evict_swapout_allowable(bo, ctx, &locked)) ++ bool busy; ++ ++ if (!ttm_bo_evict_swapout_allowable(bo, ctx, &locked, ++ &busy)) { ++ if (busy && !busy_bo && ++ bo->resv->lock.ctx != ticket) ++ busy_bo = bo; + continue; ++ } + + if (place && !bdev->driver->eviction_valuable(bo, + place)) { +@@ -832,8 +881,13 @@ static int ttm_mem_evict_first(struct ttm_bo_device *bdev, + } + + if (!bo) { ++ if (busy_bo) ++ ttm_bo_get(busy_bo); + spin_unlock(&glob->lru_lock); +- return -EBUSY; ++ ret = ttm_mem_evict_wait_busy(busy_bo, ctx, ticket); ++ if (busy_bo) ++ ttm_bo_put(busy_bo); ++ return ret; + } + + kref_get(&bo->list_kref); +@@ -917,7 +971,8 @@ static int ttm_bo_mem_force_space(struct ttm_buffer_object *bo, + return ret; + if (mem->mm_node) + break; +- ret = ttm_mem_evict_first(bdev, mem->mem_type, place, ctx); ++ ret = ttm_mem_evict_first(bdev, mem->mem_type, place, ctx, ++ bo->resv->lock.ctx); + if (unlikely(ret != 0)) + return ret; + } while (1); +@@ -1416,7 +1471,8 @@ static int ttm_bo_force_list_clean(struct ttm_bo_device *bdev, + for (i = 0; i < TTM_MAX_BO_PRIORITY; ++i) { + while (!list_empty(&man->lru[i])) { + spin_unlock(&glob->lru_lock); +- ret = ttm_mem_evict_first(bdev, mem_type, NULL, &ctx); ++ ret = ttm_mem_evict_first(bdev, mem_type, NULL, &ctx, ++ NULL); + if (ret) + return ret; + spin_lock(&glob->lru_lock); +@@ -1771,7 +1827,8 @@ int ttm_bo_swapout(struct ttm_bo_global *glob, struct ttm_operation_ctx *ctx) + spin_lock(&glob->lru_lock); + for (i = 0; i < TTM_MAX_BO_PRIORITY; ++i) { + list_for_each_entry(bo, &glob->swap_lru[i], swap) { +- if (ttm_bo_evict_swapout_allowable(bo, ctx, &locked)) { ++ if (ttm_bo_evict_swapout_allowable(bo, ctx, &locked, ++ NULL)) { + ret = 0; + break; + } +-- +2.17.1 + |