From e5cc66dfad0a811338ef088b9b4be17cadc01dea Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Thu, 5 Sep 2019 20:02:58 +0200 Subject: [PATCH] etnaviv: Rework locking Replace the per-screen locking of flushing with per-context one and add per-context lock around command stream buffer accesses, to prevent cross-context flushing from corrupting these command stream buffers. Signed-off-by: Marek Vasut --- src/gallium/drivers/etnaviv/etnaviv_blt.c | 5 ++++- src/gallium/drivers/etnaviv/etnaviv_context.c | 16 +++++++++++----- src/gallium/drivers/etnaviv/etnaviv_context.h | 2 ++ src/gallium/drivers/etnaviv/etnaviv_resource.c | 4 ++-- src/gallium/drivers/etnaviv/etnaviv_rs.c | 5 +++++ src/gallium/drivers/etnaviv/etnaviv_screen.c | 4 ---- src/gallium/drivers/etnaviv/etnaviv_screen.h | 2 -- src/gallium/drivers/etnaviv/etnaviv_texture.c | 2 ++ src/gallium/drivers/etnaviv/etnaviv_transfer.c | 4 ++-- 9 files changed, 28 insertions(+), 16 deletions(-) diff --git a/src/gallium/drivers/etnaviv/etnaviv_blt.c b/src/gallium/drivers/etnaviv/etnaviv_blt.c index f3067a7ac2d..a90bb4609e5 100644 --- a/src/gallium/drivers/etnaviv/etnaviv_blt.c +++ b/src/gallium/drivers/etnaviv/etnaviv_blt.c @@ -324,6 +324,7 @@ etna_clear_blt(struct pipe_context *pctx, unsigned buffers, const union pipe_color_union *color, double depth, unsigned stencil) { struct etna_context *ctx = etna_context(pctx); + mtx_lock(&ctx->lock); etna_set_state(ctx->stream, VIVS_GL_FLUSH_CACHE, 0x00000c23); etna_set_state(ctx->stream, VIVS_TS_FLUSH_CACHE, VIVS_TS_FLUSH_CACHE_FLUSH); @@ -344,9 +345,9 @@ etna_clear_blt(struct pipe_context *pctx, unsigned buffers, etna_set_state(ctx->stream, VIVS_GL_FLUSH_CACHE, 0x00000c23); else etna_set_state(ctx->stream, VIVS_GL_FLUSH_CACHE, 0x00000002); + mtx_unlock(&ctx->lock); } - static bool etna_try_blt_blit(struct pipe_context *pctx, const struct pipe_blit_info *blit_info) @@ -416,6 +417,7 @@ etna_try_blt_blit(struct pipe_context *pctx, return true; } + mtx_lock(&ctx->lock); /* Kick off BLT here */ if (src == dst && src_lev->ts_compress_fmt < 0) { /* Resolve-in-place */ @@ -510,6 +512,7 @@ etna_try_blt_blit(struct pipe_context *pctx, dst->seqno++; dst_lev->ts_valid = false; + mtx_unlock(&ctx->lock); return true; } diff --git a/src/gallium/drivers/etnaviv/etnaviv_context.c b/src/gallium/drivers/etnaviv/etnaviv_context.c index 4a33b7a9229..96f96dc97e6 100644 --- a/src/gallium/drivers/etnaviv/etnaviv_context.c +++ b/src/gallium/drivers/etnaviv/etnaviv_context.c @@ -63,7 +63,7 @@ etna_context_destroy(struct pipe_context *pctx) struct etna_context *ctx = etna_context(pctx); struct etna_screen *screen = ctx->screen; - mtx_lock(&screen->lock); + mtx_lock(&ctx->lock); if (ctx->used_resources_read) { /* @@ -94,7 +94,7 @@ etna_context_destroy(struct pipe_context *pctx) _mesa_set_destroy(ctx->used_resources_write, NULL); } - mtx_unlock(&screen->lock); + mtx_unlock(&ctx->lock); if (ctx->dummy_rt) etna_bo_del(ctx->dummy_rt); @@ -118,6 +118,8 @@ etna_context_destroy(struct pipe_context *pctx) if (ctx->in_fence_fd != -1) close(ctx->in_fence_fd); + mtx_destroy(&ctx->lock); + FREE(pctx); } @@ -265,6 +267,8 @@ etna_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info) if (!etna_state_update(ctx)) return; + mtx_lock(&ctx->lock); + /* * Figure out the buffers/features we need: */ @@ -339,6 +343,7 @@ etna_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info) * draw op has caused the hang. */ etna_stall(ctx->stream, SYNC_RECIPIENT_FE, SYNC_RECIPIENT_PE); } + mtx_unlock(&ctx->lock); if (DBG_ENABLED(ETNA_DBG_FLUSH_ALL)) pctx->flush(pctx, NULL, 0); @@ -414,7 +419,7 @@ etna_flush(struct pipe_context *pctx, struct pipe_fence_handle **fence, struct etna_screen *screen = ctx->screen; int out_fence_fd = -1; - mtx_lock(&screen->lock); + mtx_lock(&ctx->lock); list_for_each_entry(struct etna_hw_query, hq, &ctx->active_hw_queries, node) etna_hw_query_suspend(hq, ctx); @@ -452,9 +457,8 @@ etna_flush(struct pipe_context *pctx, struct pipe_fence_handle **fence, } _mesa_set_clear(ctx->used_resources_write, NULL); - mtx_unlock(&screen->lock); - etna_reset_gpu_state(ctx); + mtx_unlock(&ctx->lock); } static void @@ -512,6 +516,8 @@ etna_context_create(struct pipe_screen *pscreen, void *priv, unsigned flags) if (!ctx->used_resources_write) goto fail; + mtx_init(&ctx->lock, mtx_recursive); + /* context ctxate setup */ ctx->specs = screen->specs; ctx->screen = screen; diff --git a/src/gallium/drivers/etnaviv/etnaviv_context.h b/src/gallium/drivers/etnaviv/etnaviv_context.h index 25169abd71d..42ffae24342 100644 --- a/src/gallium/drivers/etnaviv/etnaviv_context.h +++ b/src/gallium/drivers/etnaviv/etnaviv_context.h @@ -194,6 +194,8 @@ struct etna_context { /* set of resources used by currently-unsubmitted renders */ struct set *used_resources_read; struct set *used_resources_write; + + mtx_t lock; }; static inline struct etna_context * diff --git a/src/gallium/drivers/etnaviv/etnaviv_resource.c b/src/gallium/drivers/etnaviv/etnaviv_resource.c index 1d1a0587f2a..5d72e83da73 100644 --- a/src/gallium/drivers/etnaviv/etnaviv_resource.c +++ b/src/gallium/drivers/etnaviv/etnaviv_resource.c @@ -645,7 +645,7 @@ etna_resource_used(struct etna_context *ctx, struct pipe_resource *prsc, if (!prsc) return; - mtx_lock(&screen->lock); + mtx_lock(&ctx->lock); rsc = etna_resource(prsc); @@ -682,7 +682,7 @@ etna_resource_used(struct etna_context *ctx, struct pipe_resource *prsc, _mesa_set_add(rsc->pending_ctx, ctx); } - mtx_unlock(&screen->lock); + mtx_unlock(&ctx->lock); } bool diff --git a/src/gallium/drivers/etnaviv/etnaviv_rs.c b/src/gallium/drivers/etnaviv/etnaviv_rs.c index 0ac9b67f5f3..cba0f18a7a1 100644 --- a/src/gallium/drivers/etnaviv/etnaviv_rs.c +++ b/src/gallium/drivers/etnaviv/etnaviv_rs.c @@ -392,6 +392,7 @@ etna_clear_rs(struct pipe_context *pctx, unsigned buffers, const union pipe_color_union *color, double depth, unsigned stencil) { struct etna_context *ctx = etna_context(pctx); + mtx_lock(&ctx->lock); /* Flush color and depth cache before clearing anything. * This is especially important when coming from another surface, as @@ -437,6 +438,7 @@ etna_clear_rs(struct pipe_context *pctx, unsigned buffers, etna_blit_clear_zs_rs(pctx, ctx->framebuffer_s.zsbuf, buffers, depth, stencil); etna_stall(ctx->stream, SYNC_RECIPIENT_RA, SYNC_RECIPIENT_PE); + mtx_unlock(&ctx->lock); } static bool @@ -647,6 +649,8 @@ etna_try_rs_blit(struct pipe_context *pctx, width & (w_align - 1) || height & (h_align - 1)) goto manual; + mtx_lock(&ctx->lock); + /* Always flush color and depth cache together before resolving. This works * around artifacts that appear in some cases when scanning out a texture * directly after it has been rendered to, such as rendering an animated web @@ -736,6 +740,7 @@ etna_try_rs_blit(struct pipe_context *pctx, dst->seqno++; dst_lev->ts_valid = false; ctx->dirty |= ETNA_DIRTY_DERIVE_TS; + mtx_unlock(&ctx->lock); return true; diff --git a/src/gallium/drivers/etnaviv/etnaviv_screen.c b/src/gallium/drivers/etnaviv/etnaviv_screen.c index ed989dbe149..d9449cd4ec9 100644 --- a/src/gallium/drivers/etnaviv/etnaviv_screen.c +++ b/src/gallium/drivers/etnaviv/etnaviv_screen.c @@ -84,8 +84,6 @@ etna_screen_destroy(struct pipe_screen *pscreen) { struct etna_screen *screen = etna_screen(pscreen); - mtx_destroy(&screen->lock); - if (screen->perfmon) etna_perfmon_del(screen->perfmon); @@ -956,8 +954,6 @@ etna_screen_create(struct etna_device *dev, struct etna_gpu *gpu, if (screen->drm_version >= ETNA_DRM_VERSION_PERFMON) etna_pm_query_setup(screen); - mtx_init(&screen->lock, mtx_recursive); - return pscreen; fail: diff --git a/src/gallium/drivers/etnaviv/etnaviv_screen.h b/src/gallium/drivers/etnaviv/etnaviv_screen.h index 00d6989955f..e69d598c463 100644 --- a/src/gallium/drivers/etnaviv/etnaviv_screen.h +++ b/src/gallium/drivers/etnaviv/etnaviv_screen.h @@ -85,8 +85,6 @@ struct etna_screen { uint32_t drm_version; - mtx_t lock; - nir_shader_compiler_options options; }; diff --git a/src/gallium/drivers/etnaviv/etnaviv_texture.c b/src/gallium/drivers/etnaviv/etnaviv_texture.c index 748d3ff3e6f..2650192f4e0 100644 --- a/src/gallium/drivers/etnaviv/etnaviv_texture.c +++ b/src/gallium/drivers/etnaviv/etnaviv_texture.c @@ -310,7 +310,9 @@ etna_texture_barrier(struct pipe_context *pctx, unsigned flags) struct etna_context *ctx = etna_context(pctx); /* clear color and texture cache to make sure that texture unit reads * what has been written */ + mtx_lock(&ctx->lock); etna_set_state(ctx->stream, VIVS_GL_FLUSH_CACHE, VIVS_GL_FLUSH_CACHE_COLOR | VIVS_GL_FLUSH_CACHE_TEXTURE); + mtx_unlock(&ctx->lock); } uint32_t diff --git a/src/gallium/drivers/etnaviv/etnaviv_transfer.c b/src/gallium/drivers/etnaviv/etnaviv_transfer.c index b203b1aadfb..8b6466d5269 100644 --- a/src/gallium/drivers/etnaviv/etnaviv_transfer.c +++ b/src/gallium/drivers/etnaviv/etnaviv_transfer.c @@ -355,7 +355,7 @@ etna_transfer_map(struct pipe_context *pctx, struct pipe_resource *prsc, * current GPU usage (reads must wait for GPU writes, writes must have * exclusive access to the buffer). */ - mtx_lock(&screen->lock); + mtx_lock(&ctx->lock); if ((trans->rsc && (etna_resource(trans->rsc)->status & ETNA_PENDING_WRITE)) || (!trans->rsc && @@ -369,7 +369,7 @@ etna_transfer_map(struct pipe_context *pctx, struct pipe_resource *prsc, } } - mtx_unlock(&screen->lock); + mtx_unlock(&ctx->lock); if (usage & PIPE_TRANSFER_READ) prep_flags |= DRM_ETNA_PREP_READ; -- 2.30.2