From 0642f95c4ef2137082cc1310fbb9708d43e89e1e Mon Sep 17 00:00:00 2001 From: Karol Herbst Date: Tue, 9 Feb 2021 20:32:15 +0100 Subject: [PATCH] nouveau/fence: make the fence struct part of the fence API This makes it easier to implement proper locking of the fence struct as we can redesign some of the functions to take the list object instead of fence objects. Signed-off-by: Karol Herbst Reviewed-by: M Henning Part-of: --- src/gallium/drivers/nouveau/nouveau_fence.c | 68 ++++++++++--------- src/gallium/drivers/nouveau/nouveau_fence.h | 12 +++- src/gallium/drivers/nouveau/nouveau_screen.h | 12 +--- .../drivers/nouveau/nv30/nv30_screen.c | 2 +- .../drivers/nouveau/nv50/nv50_screen.c | 2 +- .../drivers/nouveau/nvc0/nvc0_screen.c | 2 +- 6 files changed, 54 insertions(+), 44 deletions(-) diff --git a/src/gallium/drivers/nouveau/nouveau_fence.c b/src/gallium/drivers/nouveau/nouveau_fence.c index a0789739fa3..e3ea148b17d 100644 --- a/src/gallium/drivers/nouveau/nouveau_fence.c +++ b/src/gallium/drivers/nouveau/nouveau_fence.c @@ -59,6 +59,7 @@ void nouveau_fence_emit(struct nouveau_fence *fence) { struct nouveau_screen *screen = fence->screen; + struct nouveau_fence_list *fence_list = &screen->fence; assert(fence->state != NOUVEAU_FENCE_STATE_EMITTING); if (fence->state >= NOUVEAU_FENCE_STATE_EMITTED) @@ -69,14 +70,14 @@ nouveau_fence_emit(struct nouveau_fence *fence) ++fence->ref; - if (screen->fence.tail) - screen->fence.tail->next = fence; + if (fence_list->tail) + fence_list->tail->next = fence; else - screen->fence.head = fence; + fence_list->head = fence; - screen->fence.tail = fence; + fence_list->tail = fence; - screen->fence.emit(&screen->base, &fence->sequence); + fence_list->emit(&screen->base, &fence->sequence); assert(fence->state == NOUVEAU_FENCE_STATE_EMITTING); fence->state = NOUVEAU_FENCE_STATE_EMITTED; @@ -86,19 +87,19 @@ void nouveau_fence_del(struct nouveau_fence *fence) { struct nouveau_fence *it; - struct nouveau_screen *screen = fence->screen; + struct nouveau_fence_list *fence_list = &fence->screen->fence; if (fence->state == NOUVEAU_FENCE_STATE_EMITTED || fence->state == NOUVEAU_FENCE_STATE_FLUSHED) { - if (fence == screen->fence.head) { - screen->fence.head = fence->next; - if (!screen->fence.head) - screen->fence.tail = NULL; + if (fence == fence_list->head) { + fence_list->head = fence->next; + if (!fence_list->head) + fence_list->tail = NULL; } else { - for (it = screen->fence.head; it && it->next != fence; it = it->next); + for (it = fence_list->head; it && it->next != fence; it = it->next); it->next = fence->next; - if (screen->fence.tail == fence) - screen->fence.tail = it; + if (fence_list->tail == fence) + fence_list->tail = it; } } @@ -111,18 +112,18 @@ nouveau_fence_del(struct nouveau_fence *fence) } void -nouveau_fence_cleanup(struct nouveau_screen *screen) +nouveau_fence_cleanup(struct nouveau_fence_list *fence_list) { - if (screen->fence.current) { + if (fence_list->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_ref(fence_list->current, ¤t); nouveau_fence_wait(current, NULL); nouveau_fence_ref(NULL, ¤t); - nouveau_fence_ref(NULL, &screen->fence.current); + nouveau_fence_ref(NULL, &fence_list->current); } } @@ -131,7 +132,8 @@ nouveau_fence_update(struct nouveau_screen *screen, bool flushed) { struct nouveau_fence *fence; struct nouveau_fence *next = NULL; - u32 sequence = screen->fence.update(&screen->base); + struct nouveau_fence_list *fence_list = &screen->fence; + u32 sequence = fence_list->update(&screen->base); /* If running under drm-shim, let all fences be signalled so things run to * completion (avoids a hang at the end of shader-db). @@ -139,11 +141,11 @@ nouveau_fence_update(struct nouveau_screen *screen, bool flushed) if (unlikely(screen->disable_fences)) sequence = screen->fence.sequence; - if (screen->fence.sequence_ack == sequence) + if (fence_list->sequence_ack == sequence) return; - screen->fence.sequence_ack = sequence; + fence_list->sequence_ack = sequence; - for (fence = screen->fence.head; fence; fence = next) { + for (fence = fence_list->head; fence; fence = next) { next = fence->next; sequence = fence->sequence; @@ -152,12 +154,12 @@ nouveau_fence_update(struct nouveau_screen *screen, bool flushed) nouveau_fence_trigger_work(fence); nouveau_fence_ref(NULL, &fence); - if (sequence == screen->fence.sequence_ack) + if (sequence == fence_list->sequence_ack) break; } - screen->fence.head = next; + fence_list->head = next; if (!next) - screen->fence.tail = NULL; + fence_list->tail = NULL; if (flushed) { for (fence = next; fence; fence = fence->next) @@ -186,6 +188,7 @@ static bool nouveau_fence_kick(struct nouveau_fence *fence) { struct nouveau_screen *screen = fence->screen; + struct nouveau_fence_list *fence_list = &screen->fence; /* wtf, someone is waiting on a fence in flush_notify handler? */ assert(fence->state != NOUVEAU_FENCE_STATE_EMITTING); @@ -199,7 +202,7 @@ nouveau_fence_kick(struct nouveau_fence *fence) if (nouveau_pushbuf_kick(screen->pushbuf, screen->pushbuf->channel)) return false; - if (fence == screen->fence.current) + if (fence == fence_list->current) nouveau_fence_next(screen); nouveau_fence_update(screen, false); @@ -211,6 +214,7 @@ bool nouveau_fence_wait(struct nouveau_fence *fence, struct util_debug_callback *debug) { struct nouveau_screen *screen = fence->screen; + struct nouveau_fence_list *fence_list = &screen->fence; uint32_t spins = 0; int64_t start = 0; @@ -241,7 +245,7 @@ nouveau_fence_wait(struct nouveau_fence *fence, struct util_debug_callback *debu debug_printf("Wait on fence %u (ack = %u, next = %u) timed out !\n", fence->sequence, - screen->fence.sequence_ack, screen->fence.sequence); + fence_list->sequence_ack, fence_list->sequence); return false; } @@ -249,16 +253,18 @@ nouveau_fence_wait(struct nouveau_fence *fence, struct util_debug_callback *debu void nouveau_fence_next(struct nouveau_screen *screen) { - if (screen->fence.current->state < NOUVEAU_FENCE_STATE_EMITTING) { - if (screen->fence.current->ref > 1) - nouveau_fence_emit(screen->fence.current); + struct nouveau_fence_list *fence_list = &screen->fence; + + if (fence_list->current->state < NOUVEAU_FENCE_STATE_EMITTING) { + if (fence_list->current->ref > 1) + nouveau_fence_emit(fence_list->current); else return; } - nouveau_fence_ref(NULL, &screen->fence.current); + nouveau_fence_ref(NULL, &fence_list->current); - nouveau_fence_new(screen, &screen->fence.current); + nouveau_fence_new(screen, &fence_list->current); } void diff --git a/src/gallium/drivers/nouveau/nouveau_fence.h b/src/gallium/drivers/nouveau/nouveau_fence.h index 129939f0167..a9b21624543 100644 --- a/src/gallium/drivers/nouveau/nouveau_fence.h +++ b/src/gallium/drivers/nouveau/nouveau_fence.h @@ -29,11 +29,21 @@ struct nouveau_fence { struct list_head work; }; +struct nouveau_fence_list { + struct nouveau_fence *head; + struct nouveau_fence *tail; + struct nouveau_fence *current; + uint32_t sequence; + uint32_t sequence_ack; + void (*emit)(struct pipe_screen *, uint32_t *sequence); + uint32_t (*update)(struct pipe_screen *); +}; + void nouveau_fence_emit(struct nouveau_fence *); void nouveau_fence_del(struct nouveau_fence *); bool nouveau_fence_new(struct nouveau_screen *, struct nouveau_fence **); -void nouveau_fence_cleanup(struct nouveau_screen *); +void nouveau_fence_cleanup(struct nouveau_fence_list *); bool nouveau_fence_work(struct nouveau_fence *, void (*)(void *), void *); void nouveau_fence_update(struct nouveau_screen *, bool flushed); void nouveau_fence_next(struct nouveau_screen *); diff --git a/src/gallium/drivers/nouveau/nouveau_screen.h b/src/gallium/drivers/nouveau/nouveau_screen.h index 470e1336785..100e9b207b2 100644 --- a/src/gallium/drivers/nouveau/nouveau_screen.h +++ b/src/gallium/drivers/nouveau/nouveau_screen.h @@ -6,6 +6,8 @@ #include "util/u_atomic.h" #include "util/u_memory.h" +#include "nouveau_fence.h" + #ifndef NDEBUG # define NOUVEAU_ENABLE_DRIVER_STATISTICS #endif @@ -44,15 +46,7 @@ struct nouveau_screen { uint16_t class_3d; - struct { - struct nouveau_fence *head; - struct nouveau_fence *tail; - struct nouveau_fence *current; - u32 sequence; - u32 sequence_ack; - void (*emit)(struct pipe_screen *, u32 *sequence); - u32 (*update)(struct pipe_screen *); - } fence; + struct nouveau_fence_list fence; struct nouveau_mman *mm_VRAM; struct nouveau_mman *mm_GART; diff --git a/src/gallium/drivers/nouveau/nv30/nv30_screen.c b/src/gallium/drivers/nouveau/nv30/nv30_screen.c index 0ec79fb8c43..fd87f19a6c7 100644 --- a/src/gallium/drivers/nouveau/nv30/nv30_screen.c +++ b/src/gallium/drivers/nouveau/nv30/nv30_screen.c @@ -549,7 +549,7 @@ nv30_screen_destroy(struct pipe_screen *pscreen) if (!nouveau_drm_screen_unref(&screen->base)) return; - nouveau_fence_cleanup(&screen->base); + nouveau_fence_cleanup(&screen->base.fence); nouveau_bo_ref(NULL, &screen->notify); diff --git a/src/gallium/drivers/nouveau/nv50/nv50_screen.c b/src/gallium/drivers/nouveau/nv50/nv50_screen.c index 38a105c54f2..11a5975ba76 100644 --- a/src/gallium/drivers/nouveau/nv50/nv50_screen.c +++ b/src/gallium/drivers/nouveau/nv50/nv50_screen.c @@ -624,7 +624,7 @@ nv50_screen_destroy(struct pipe_screen *pscreen) if (!nouveau_drm_screen_unref(&screen->base)) return; - nouveau_fence_cleanup(&screen->base); + nouveau_fence_cleanup(&screen->base.fence); if (screen->base.pushbuf) screen->base.pushbuf->user_priv = NULL; diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_screen.c b/src/gallium/drivers/nouveau/nvc0/nvc0_screen.c index e12519ceb3a..056166b04de 100644 --- a/src/gallium/drivers/nouveau/nvc0/nvc0_screen.c +++ b/src/gallium/drivers/nouveau/nvc0/nvc0_screen.c @@ -715,7 +715,7 @@ nvc0_screen_destroy(struct pipe_screen *pscreen) if (!nouveau_drm_screen_unref(&screen->base)) return; - nouveau_fence_cleanup(&screen->base); + nouveau_fence_cleanup(&screen->base.fence); if (screen->base.pushbuf) screen->base.pushbuf->user_priv = NULL;