[Mesa-dev] [PATCH v2 5/6] gallium/radeon: implement set_device_reset_callback

Nicolai Hähnle nhaehnle at gmail.com
Tue Oct 4 08:11:23 UTC 2016


From: Nicolai Hähnle <nicolai.haehnle at amd.com>

Check for device reset on flush. It would be nicer if the kernel just
reported this as an error on the submit ioctl (and similarly for fences),
but this will do for now.
---
 src/gallium/drivers/r600/r600_hw_context.c    |  3 +++
 src/gallium/drivers/radeon/r600_pipe_common.c | 32 +++++++++++++++++++++++++++
 src/gallium/drivers/radeon/r600_pipe_common.h |  2 ++
 src/gallium/drivers/radeonsi/si_hw_context.c  |  3 +++
 4 files changed, 40 insertions(+)

diff --git a/src/gallium/drivers/r600/r600_hw_context.c b/src/gallium/drivers/r600/r600_hw_context.c
index dc5ad75..bc6217a 100644
--- a/src/gallium/drivers/r600/r600_hw_context.c
+++ b/src/gallium/drivers/r600/r600_hw_context.c
@@ -251,20 +251,23 @@ void r600_flush_emit(struct r600_context *rctx)
 void r600_context_gfx_flush(void *context, unsigned flags,
 			    struct pipe_fence_handle **fence)
 {
 	struct r600_context *ctx = context;
 	struct radeon_winsys_cs *cs = ctx->b.gfx.cs;
 	struct radeon_winsys *ws = ctx->b.ws;
 
 	if (!radeon_emitted(cs, ctx->b.initial_gfx_cs_size))
 		return;
 
+	if (r600_check_device_reset(&ctx->b))
+		return;
+
 	r600_preflush_suspend_features(&ctx->b);
 
 	/* flush the framebuffer cache */
 	ctx->b.flags |= R600_CONTEXT_FLUSH_AND_INV |
 		      R600_CONTEXT_FLUSH_AND_INV_CB |
 		      R600_CONTEXT_FLUSH_AND_INV_DB |
 		      R600_CONTEXT_FLUSH_AND_INV_CB_META |
 		      R600_CONTEXT_FLUSH_AND_INV_DB_META |
 		      R600_CONTEXT_WAIT_3D_IDLE |
 		      R600_CONTEXT_WAIT_CP_DMA_IDLE;
diff --git a/src/gallium/drivers/radeon/r600_pipe_common.c b/src/gallium/drivers/radeon/r600_pipe_common.c
index 95950c3..4e94e07 100644
--- a/src/gallium/drivers/radeon/r600_pipe_common.c
+++ b/src/gallium/drivers/radeon/r600_pipe_common.c
@@ -477,20 +477,50 @@ static void r600_set_debug_callback(struct pipe_context *ctx,
 				    const struct pipe_debug_callback *cb)
 {
 	struct r600_common_context *rctx = (struct r600_common_context *)ctx;
 
 	if (cb)
 		rctx->debug = *cb;
 	else
 		memset(&rctx->debug, 0, sizeof(rctx->debug));
 }
 
+static void r600_set_device_reset_callback(struct pipe_context *ctx,
+					   const struct pipe_device_reset_callback *cb)
+{
+	struct r600_common_context *rctx = (struct r600_common_context *)ctx;
+
+	if (cb)
+		rctx->device_reset_callback = *cb;
+	else
+		memset(&rctx->device_reset_callback, 0,
+		       sizeof(rctx->device_reset_callback));
+}
+
+bool r600_check_device_reset(struct r600_common_context *rctx)
+{
+	enum pipe_reset_status status;
+
+	if (!rctx->device_reset_callback.reset)
+		return false;
+
+	if (!rctx->b.get_device_reset_status)
+		return false;
+
+	status = rctx->b.get_device_reset_status(&rctx->b);
+	if (status == PIPE_NO_RESET)
+		return false;
+
+	rctx->device_reset_callback.reset(rctx->device_reset_callback.data, status);
+	return true;
+}
+
 bool r600_common_context_init(struct r600_common_context *rctx,
 			      struct r600_common_screen *rscreen,
 			      unsigned context_flags)
 {
 	slab_create(&rctx->pool_transfers,
 			 sizeof(struct r600_transfer), 64);
 
 	rctx->screen = rscreen;
 	rctx->ws = rscreen->ws;
 	rctx->family = rscreen->family;
@@ -521,20 +551,22 @@ bool r600_common_context_init(struct r600_common_context *rctx,
 	else
 		rctx->b.buffer_subdata = r600_buffer_subdata;
 
 	if (rscreen->info.drm_major == 2 && rscreen->info.drm_minor >= 43) {
 		rctx->b.get_device_reset_status = r600_get_reset_status;
 		rctx->gpu_reset_counter =
 			rctx->ws->query_value(rctx->ws,
 					      RADEON_GPU_RESET_COUNTER);
 	}
 
+	rctx->b.set_device_reset_callback = r600_set_device_reset_callback;
+
 	LIST_INITHEAD(&rctx->texture_buffers);
 
 	r600_init_context_texture_functions(rctx);
 	r600_init_viewport_functions(rctx);
 	r600_streamout_init(rctx);
 	r600_query_init(rctx);
 	cayman_init_msaa(&rctx->b);
 
 	rctx->allocator_zeroed_memory =
 		u_suballocator_create(&rctx->b, rscreen->info.gart_page_size,
diff --git a/src/gallium/drivers/radeon/r600_pipe_common.h b/src/gallium/drivers/radeon/r600_pipe_common.h
index c6669cc..d6b6664 100644
--- a/src/gallium/drivers/radeon/r600_pipe_common.h
+++ b/src/gallium/drivers/radeon/r600_pipe_common.h
@@ -613,20 +613,21 @@ struct r600_common_context {
 		int64_t				last_use_timestamp;
 		bool				query_active;
 	} dcc_stats[5];
 
 	/* The list of all texture buffer objects in this context.
 	 * This list is walked when a buffer is invalidated/reallocated and
 	 * the GPU addresses are updated. */
 	struct list_head		texture_buffers;
 
 	struct pipe_debug_callback	debug;
+	struct pipe_device_reset_callback device_reset_callback;
 
 	void				*query_result_shader;
 
 	/* Copy one resource to another using async DMA. */
 	void (*dma_copy)(struct pipe_context *ctx,
 			 struct pipe_resource *dst,
 			 unsigned dst_level,
 			 unsigned dst_x, unsigned dst_y, unsigned dst_z,
 			 struct pipe_resource *src,
 			 unsigned src_level,
@@ -726,20 +727,21 @@ void r600_screen_clear_buffer(struct r600_common_screen *rscreen, struct pipe_re
 			      enum r600_coherency coher);
 struct pipe_resource *r600_resource_create_common(struct pipe_screen *screen,
 						  const struct pipe_resource *templ);
 const char *r600_get_llvm_processor_name(enum radeon_family family);
 void r600_need_dma_space(struct r600_common_context *ctx, unsigned num_dw,
 			 struct r600_resource *dst, struct r600_resource *src);
 void r600_dma_emit_wait_idle(struct r600_common_context *rctx);
 void radeon_save_cs(struct radeon_winsys *ws, struct radeon_winsys_cs *cs,
 		    struct radeon_saved_cs *saved);
 void radeon_clear_saved_cs(struct radeon_saved_cs *saved);
+bool r600_check_device_reset(struct r600_common_context *rctx);
 
 /* r600_gpu_load.c */
 void r600_gpu_load_kill_thread(struct r600_common_screen *rscreen);
 uint64_t r600_gpu_load_begin(struct r600_common_screen *rscreen);
 unsigned r600_gpu_load_end(struct r600_common_screen *rscreen, uint64_t begin);
 
 /* r600_perfcounters.c */
 void r600_perfcounters_destroy(struct r600_common_screen *rscreen);
 
 /* r600_query.c */
diff --git a/src/gallium/drivers/radeonsi/si_hw_context.c b/src/gallium/drivers/radeonsi/si_hw_context.c
index 67e8352..7d851b8 100644
--- a/src/gallium/drivers/radeonsi/si_hw_context.c
+++ b/src/gallium/drivers/radeonsi/si_hw_context.c
@@ -96,20 +96,23 @@ void si_context_gfx_flush(void *context, unsigned flags,
 	struct si_context *ctx = context;
 	struct radeon_winsys_cs *cs = ctx->b.gfx.cs;
 	struct radeon_winsys *ws = ctx->b.ws;
 
 	if (ctx->gfx_flush_in_progress)
 		return;
 
 	if (!radeon_emitted(cs, ctx->b.initial_gfx_cs_size))
 		return;
 
+	if (r600_check_device_reset(&ctx->b))
+		return;
+
 	ctx->gfx_flush_in_progress = true;
 
 	r600_preflush_suspend_features(&ctx->b);
 
 	ctx->b.flags |= SI_CONTEXT_CS_PARTIAL_FLUSH |
 			SI_CONTEXT_PS_PARTIAL_FLUSH;
 
 	/* DRM 3.1.0 doesn't flush TC for VI correctly. */
 	if (ctx->b.chip_class == VI && ctx->b.screen->info.drm_minor <= 1)
 		ctx->b.flags |= SI_CONTEXT_INV_GLOBAL_L2 |
-- 
2.7.4



More information about the mesa-dev mailing list