| From 096e02f7be910b6d1ec893e8247e6a84a67a9752 Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Tue, 7 Sep 2021 12:08:32 +0800 |
| Subject: drm/ttm: Fix a deadlock if the target BO is not idle during swap |
| MIME-Version: 1.0 |
| Content-Type: text/plain; charset=UTF-8 |
| Content-Transfer-Encoding: 8bit |
| |
| From: xinhui pan <xinhui.pan@amd.com> |
| |
| [ Upstream commit 70982eef4d7eebb47a3b1ef25ec1bc742f3a21cf ] |
| |
| The ret value might be -EBUSY, caller will think lru lock is still |
| locked but actually NOT. So return -ENOSPC instead. Otherwise we hit |
| list corruption. |
| |
| ttm_bo_cleanup_refs might fail too if BO is not idle. If we return 0, |
| caller(ttm_tt_populate -> ttm_global_swapout ->ttm_device_swapout) will |
| be stuck as we actually did not free any BO memory. This usually happens |
| when the fence is not signaled for a long time. |
| |
| Signed-off-by: xinhui pan <xinhui.pan@amd.com> |
| Reviewed-by: Christian König <christian.koenig@amd.com> |
| Fixes: ebd59851c796 ("drm/ttm: move swapout logic around v3") |
| Link: https://patchwork.freedesktop.org/patch/msgid/20210907040832.1107747-1-xinhui.pan@amd.com |
| Signed-off-by: Christian König <christian.koenig@amd.com> |
| Signed-off-by: Dave Airlie <airlied@redhat.com> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| drivers/gpu/drm/ttm/ttm_bo.c | 6 +++--- |
| 1 file changed, 3 insertions(+), 3 deletions(-) |
| |
| diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c |
| index 32202385073a..b47a5053eb85 100644 |
| --- a/drivers/gpu/drm/ttm/ttm_bo.c |
| +++ b/drivers/gpu/drm/ttm/ttm_bo.c |
| @@ -1157,9 +1157,9 @@ int ttm_bo_swapout(struct ttm_buffer_object *bo, struct ttm_operation_ctx *ctx, |
| } |
| |
| if (bo->deleted) { |
| - ttm_bo_cleanup_refs(bo, false, false, locked); |
| + ret = ttm_bo_cleanup_refs(bo, false, false, locked); |
| ttm_bo_put(bo); |
| - return 0; |
| + return ret == -EBUSY ? -ENOSPC : ret; |
| } |
| |
| ttm_bo_del_from_lru(bo); |
| @@ -1213,7 +1213,7 @@ out: |
| if (locked) |
| dma_resv_unlock(bo->base.resv); |
| ttm_bo_put(bo); |
| - return ret; |
| + return ret == -EBUSY ? -ENOSPC : ret; |
| } |
| |
| void ttm_bo_tt_destroy(struct ttm_buffer_object *bo) |
| -- |
| 2.33.0 |
| |