[3/4] drm/nouveau: Fix ordering between TTM and GEM release

Submitted by Thierry Reding on Sept. 16, 2019, 2:19 p.m.

Details

Message ID 20190916141926.8594-4-thierry.reding@gmail.com
State New
Headers show
Series "drm/nouveau: Miscellaneous fixes" ( rev: 1 ) in Nouveau

Not browsing as part of any series.

Commit Message

Thierry Reding Sept. 16, 2019, 2:19 p.m.
From: Thierry Reding <treding@nvidia.com>

When the last reference to a TTM BO is dropped, ttm_bo_release() will
acquire the DMA reservation object's wound/wait mutex while trying to
clean up (ttm_bo_cleanup_refs_or_queue() via ttm_bo_release()). It is
therefore essential that drm_gem_object_release() be called after the
TTM BO has been uninitialized, otherwise drm_gem_object_release() has
already destroyed the wound/wait mutex (via dma_resv_fini()).

Signed-off-by: Thierry Reding <treding@nvidia.com>
---
 drivers/gpu/drm/nouveau/nouveau_bo.c  | 10 ++++++++--
 drivers/gpu/drm/nouveau/nouveau_gem.c |  4 ----
 2 files changed, 8 insertions(+), 6 deletions(-)

Patch hide | download patch | download mbox

diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c
index e7803dca32c5..f8015e0318d7 100644
--- a/drivers/gpu/drm/nouveau/nouveau_bo.c
+++ b/drivers/gpu/drm/nouveau/nouveau_bo.c
@@ -136,10 +136,16 @@  nouveau_bo_del_ttm(struct ttm_buffer_object *bo)
 	struct drm_device *dev = drm->dev;
 	struct nouveau_bo *nvbo = nouveau_bo(bo);
 
-	if (unlikely(nvbo->bo.base.filp))
-		DRM_ERROR("bo %p still attached to GEM object\n", bo);
 	WARN_ON(nvbo->pin_refcnt > 0);
 	nv10_bo_put_tile_region(dev, nvbo->tile, NULL);
+
+	/*
+	 * If nouveau_bo_new() allocated this buffer, the GEM object was never
+	 * initialized, so don't attempt to release it.
+	 */
+	if (bo->base.dev)
+		drm_gem_object_release(&bo->base);
+
 	kfree(nvbo);
 }
 
diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c
index 1bdffd714456..1324c19f4e5c 100644
--- a/drivers/gpu/drm/nouveau/nouveau_gem.c
+++ b/drivers/gpu/drm/nouveau/nouveau_gem.c
@@ -51,10 +51,6 @@  nouveau_gem_object_del(struct drm_gem_object *gem)
 	if (gem->import_attach)
 		drm_prime_gem_destroy(gem, nvbo->bo.sg);
 
-	drm_gem_object_release(gem);
-
-	/* reset filp so nouveau_bo_del_ttm() can test for it */
-	gem->filp = NULL;
 	ttm_bo_put(&nvbo->bo);
 
 	pm_runtime_mark_last_busy(dev);