diff mbox

[3/3] drm/amdgpu: fix lock cleanup during buffer creation

Message ID 20170214103744.4133-3-nhaehnle@gmail.com (mailing list archive)
State New, archived
Headers show

Commit Message

Nicolai Hähnle Feb. 14, 2017, 10:37 a.m. UTC
From: Nicolai Hähnle <nicolai.haehnle@amd.com>

Open-code the initial ttm_bo_validate call, so that we can properly
unlock the reservation lock when it fails. Also, properly destruct
the reservation object when the first part of TTM BO initialization
fails.

Actual deadlocks caused by the missing unlock should have been fixed
by "drm/ttm: never add BO that failed to validate to the LRU list",
superseding the flawed fix in commit 38fc4856ad98 ("drm/amdgpu: fix
a potential deadlock in amdgpu_bo_create_restricted()").

This change fixes remaining recursive locking errors that can be seen
with lock debugging enabled, and avoids the error of freeing a locked
mutex.

Fixes: 12a852219583 ("drm/amdgpu: improve AMDGPU_GEM_CREATE_VRAM_CLEARED handling (v2)")
Signed-off-by: Nicolai Hähnle <nicolai.haehnle@amd.com>
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_object.c | 32 +++++++++++++++++++++++++-----
 1 file changed, 27 insertions(+), 5 deletions(-)
diff mbox

Patch

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
index d1ef1d0..bea845f 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
@@ -399,12 +399,34 @@  int amdgpu_bo_create_restricted(struct amdgpu_device *adev,
 		locked = ww_mutex_trylock(&bo->tbo.ttm_resv.lock);
 		WARN_ON(!locked);
 	}
-	r = ttm_bo_init(&adev->mman.bdev, &bo->tbo, size, type,
-			&bo->placement, page_align, !kernel, NULL,
-			acc_size, sg, resv ? resv : &bo->tbo.ttm_resv,
-			&amdgpu_ttm_bo_destroy);
-	if (unlikely(r != 0))
+	r = ttm_bo_init_top(&adev->mman.bdev, &bo->tbo, size, type,
+			    page_align, NULL,
+			    acc_size, sg, resv ? resv : &bo->tbo.ttm_resv,
+			    &amdgpu_ttm_bo_destroy);
+	if (unlikely(r != 0)) {
+		if (!resv) {
+			ww_mutex_unlock(&bo->tbo.ttm_resv.lock);
+			reservation_object_fini(&bo->tbo.ttm_resv);
+		}
+		amdgpu_ttm_bo_destroy(&bo->tbo);
+		return r;
+	}
+
+	r = ttm_bo_validate(&bo->tbo, &bo->placement, !kernel, false);
+	if (unlikely(r != 0)) {
+		struct ttm_buffer_object *tbo = &bo->tbo;
+
+		if (!resv)
+			ww_mutex_unlock(&bo->tbo.ttm_resv.lock);
+		ttm_bo_unref(&tbo);
 		return r;
+	}
+
+	if (!(bo->tbo.mem.placement & TTM_PL_FLAG_NO_EVICT)) {
+		spin_lock(&bo->tbo.glob->lru_lock);
+		ttm_bo_add_to_lru(&bo->tbo);
+		spin_unlock(&bo->tbo.glob->lru_lock);
+	}
 
 	bo->tbo.priority = ilog2(bo->tbo.num_pages);
 	if (kernel)