From 6a526efcfbbc639cd9af5c38ac63f9d61e6e696d Mon Sep 17 00:00:00 2001 From: Ilia Mirkin Date: Thu, 4 Feb 2021 12:15:43 -0500 Subject: [PATCH] nouveau: reinstate fencing on screen destroy As it turns out, the wait is required as the driver expects for rendering to be quiesced on exit. This can trigger channel failures, which in turn trigger recovery. This can fail and destroy the whole system. Fixes: 28a781323fb ("nouveau: change fence destruction logic on screen destroy") References: https://gitlab.freedesktop.org/mesa/mesa/-/issues/4223 Signed-off-by: Ilia Mirkin Reviewed-by: Karol Herbst Part-of: (cherry picked from commit 92f12952f32ee08cd302f8591ab059ca5f167239) --- .pick_status.json | 2 +- src/gallium/drivers/nouveau/nouveau_fence.c | 18 ++++++++---------- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/.pick_status.json b/.pick_status.json index 59cbdef3ecf..c65a22f7c5a 100644 --- a/.pick_status.json +++ b/.pick_status.json @@ -1957,7 +1957,7 @@ "description": "nouveau: reinstate fencing on screen destroy", "nominated": true, "nomination_type": 1, - "resolution": 0, + "resolution": 1, "master_sha": null, "because_sha": "28a781323fba87e6e338cfecb0b6fe25a08f61a4" }, diff --git a/src/gallium/drivers/nouveau/nouveau_fence.c b/src/gallium/drivers/nouveau/nouveau_fence.c index 49f686bfbb5..b4c938fff61 100644 --- a/src/gallium/drivers/nouveau/nouveau_fence.c +++ b/src/gallium/drivers/nouveau/nouveau_fence.c @@ -111,17 +111,15 @@ nouveau_fence_del(struct nouveau_fence *fence) void nouveau_fence_cleanup(struct nouveau_screen *screen) { - struct nouveau_fence *fence, *next; - - for (fence = screen->fence.head; fence; fence = next) { - next = fence->next; - nouveau_fence_trigger_work(fence); - nouveau_fence_ref(NULL, &fence); - } - screen->fence.head = NULL; - screen->fence.tail = NULL; if (screen->fence.current) { - nouveau_fence_trigger_work(screen->fence.current); + struct nouveau_fence *current = NULL; + + /* nouveau_fence_wait will create a new current fence, so wait on the + * _current_ one, and remove both. + */ + nouveau_fence_ref(screen->fence.current, ¤t); + nouveau_fence_wait(current, NULL); + nouveau_fence_ref(NULL, ¤t); nouveau_fence_ref(NULL, &screen->fence.current); } }