static void r600_flush_dma_ring(void *ctx, unsigned flags,
				struct pipe_fence_handle **fence)
{
	struct r600_common_context *rctx = (struct r600_common_context *)ctx;
	struct radeon_winsys_cs *cs = rctx->dma.cs;
	struct radeon_saved_cs saved;
	bool check_vm =
		(rctx->screen->debug_flags & DBG_CHECK_VM) &&
		rctx->check_vm_faults;

	if (!radeon_emitted(cs, 0)) {
		if (fence)
			rctx->ws->fence_reference(fence, rctx->last_sdma_fence);
		return;
	}

	if (check_vm)
		radeon_save_cs(rctx->ws, cs, &saved, true);

	rctx->ws->cs_flush(cs, flags, &rctx->last_sdma_fence);
	if (fence)
		rctx->ws->fence_reference(fence, rctx->last_sdma_fence);

	if (check_vm) {
		/* Use conservative timeout 800ms, after which we won't wait any
		 * longer and assume the GPU is hung.
		 */
		rctx->ws->fence_wait(rctx->ws, rctx->last_sdma_fence, 800*1000*1000);

		rctx->check_vm_faults(rctx, &saved, RING_DMA);
		radeon_clear_saved_cs(&saved);
	}
}
示例#2
0
void r600_context_gfx_flush(void *context, unsigned flags,
			    struct pipe_fence_handle **fence)
{
	struct r600_context *ctx = context;
	struct radeon_cmdbuf *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;

	r600_flush_emit(ctx);

	if (ctx->trace_buf)
		eg_trace_emit(ctx);
	/* old kernels and userspace don't set SX_MISC, so we must reset it to 0 here */
	if (ctx->b.chip_class == R600) {
		radeon_set_context_reg(cs, R_028350_SX_MISC, 0);
	}

	if (ctx->is_debug) {
		/* Save the IB for debug contexts. */
		radeon_clear_saved_cs(&ctx->last_gfx);
		radeon_save_cs(ws, cs, &ctx->last_gfx, true);
		r600_resource_reference(&ctx->last_trace_buf, ctx->trace_buf);
		r600_resource_reference(&ctx->trace_buf, NULL);
	}
	/* Flush the CS. */
	ws->cs_flush(cs, flags, &ctx->b.last_gfx_fence);
	if (fence)
		ws->fence_reference(fence, ctx->b.last_gfx_fence);
	ctx->b.num_gfx_cs_flushes++;

	if (ctx->is_debug) {
		if (!ws->fence_wait(ws, ctx->b.last_gfx_fence, 10000000)) {
			const char *fname = getenv("R600_TRACE");
			if (!fname)
				exit(-1);
			FILE *fl = fopen(fname, "w+");
			if (fl) {
				eg_dump_debug_state(&ctx->b.b, fl, 0);
				fclose(fl);
			} else
				perror(fname);
			exit(-1);
		}
	}
	r600_begin_new_cs(ctx);
}