From fa3f1348e49feeac511dbe5b22bbddc47f56ba81 Mon Sep 17 00:00:00 2001 From: Marek Olšák Date: Wed, 16 Feb 2011 22:23:23 +0100 Subject: r300g: fix a race between CS and SET_TILING ioctls --- src/gallium/winsys/radeon/drm/radeon_drm_bo.c | 13 +++++++++++++ src/gallium/winsys/radeon/drm/radeon_drm_cs.c | 12 ++++++------ src/gallium/winsys/radeon/drm/radeon_drm_cs.h | 2 ++ 3 files changed, 21 insertions(+), 6 deletions(-) (limited to 'src/gallium/winsys/radeon/drm') diff --git a/src/gallium/winsys/radeon/drm/radeon_drm_bo.c b/src/gallium/winsys/radeon/drm/radeon_drm_bo.c index afb8131acbe..3094337a3cd 100644 --- a/src/gallium/winsys/radeon/drm/radeon_drm_bo.c +++ b/src/gallium/winsys/radeon/drm/radeon_drm_bo.c @@ -394,13 +394,26 @@ static void radeon_bo_get_tiling(struct r300_winsys_bo *_buf, } static void radeon_bo_set_tiling(struct r300_winsys_bo *_buf, + struct r300_winsys_cs *rcs, enum r300_buffer_tiling microtiled, enum r300_buffer_tiling macrotiled, uint32_t pitch) { struct radeon_bo *bo = get_radeon_bo(pb_buffer(_buf)); + struct radeon_drm_cs *cs = radeon_drm_cs(rcs); struct drm_radeon_gem_set_tiling args = {}; + /* Tiling determines how DRM treats the buffer data. + * We must flush CS when changing it if the buffer is referenced. */ + if (cs && radeon_bo_is_referenced_by_cs(cs, bo)) { + radeon_drm_cs_flush(rcs); + radeon_drm_cs_sync_flush(rcs); + } + + while (p_atomic_read(&bo->num_active_ioctls)) { + sched_yield(); + } + if (microtiled == R300_BUFFER_TILED) args.tiling_flags |= RADEON_BO_FLAGS_MICRO_TILE; else if (microtiled == R300_BUFFER_SQUARETILED) diff --git a/src/gallium/winsys/radeon/drm/radeon_drm_cs.c b/src/gallium/winsys/radeon/drm/radeon_drm_cs.c index b4f5c9f6a88..8f6f4a1f35a 100644 --- a/src/gallium/winsys/radeon/drm/radeon_drm_cs.c +++ b/src/gallium/winsys/radeon/drm/radeon_drm_cs.c @@ -330,7 +330,7 @@ static void radeon_drm_cs_write_reloc(struct r300_winsys_cs *rcs, OUT_CS(&cs->base, index * RELOC_DWORDS); } -static PIPE_THREAD_ROUTINE(radeon_drm_cs_emit_async, param) +static PIPE_THREAD_ROUTINE(radeon_drm_cs_emit_ioctl, param) { struct radeon_cs_context *csc = (struct radeon_cs_context*)param; unsigned i; @@ -355,7 +355,7 @@ static PIPE_THREAD_ROUTINE(radeon_drm_cs_emit_async, param) return NULL; } -static void radeon_drm_cs_sync_flush(struct r300_winsys_cs *rcs) +void radeon_drm_cs_sync_flush(struct r300_winsys_cs *rcs) { struct radeon_drm_cs *cs = radeon_drm_cs(rcs); @@ -368,7 +368,7 @@ static void radeon_drm_cs_sync_flush(struct r300_winsys_cs *rcs) DEBUG_GET_ONCE_BOOL_OPTION(thread, "RADEON_THREAD", TRUE) -static void radeon_drm_cs_emit(struct r300_winsys_cs *rcs) +void radeon_drm_cs_flush(struct r300_winsys_cs *rcs) { struct radeon_drm_cs *cs = radeon_drm_cs(rcs); struct radeon_cs_context *tmp; @@ -385,10 +385,10 @@ static void radeon_drm_cs_emit(struct r300_winsys_cs *rcs) p_atomic_inc(&cs->csc->relocs_bo[i]->num_active_ioctls); if (debug_get_option_thread()) { - cs->thread = pipe_thread_create(radeon_drm_cs_emit_async, cs->csc); + cs->thread = pipe_thread_create(radeon_drm_cs_emit_ioctl, cs->csc); assert(cs->thread); } else { - radeon_drm_cs_emit_async(cs->csc); + radeon_drm_cs_emit_ioctl(cs->csc); } } @@ -440,7 +440,7 @@ void radeon_drm_cs_init_functions(struct radeon_drm_winsys *ws) ws->base.cs_add_reloc = radeon_drm_cs_add_reloc; ws->base.cs_validate = radeon_drm_cs_validate; ws->base.cs_write_reloc = radeon_drm_cs_write_reloc; - ws->base.cs_flush = radeon_drm_cs_emit; + ws->base.cs_flush = radeon_drm_cs_flush; ws->base.cs_sync_flush = radeon_drm_cs_sync_flush; ws->base.cs_set_flush = radeon_drm_cs_set_flush; ws->base.cs_is_buffer_referenced = radeon_bo_is_referenced; diff --git a/src/gallium/winsys/radeon/drm/radeon_drm_cs.h b/src/gallium/winsys/radeon/drm/radeon_drm_cs.h index 486fd237fc9..4cc97f37e09 100644 --- a/src/gallium/winsys/radeon/drm/radeon_drm_cs.h +++ b/src/gallium/winsys/radeon/drm/radeon_drm_cs.h @@ -96,6 +96,8 @@ static INLINE boolean radeon_bo_is_referenced_by_any_cs(struct radeon_bo *bo) return bo->num_cs_references; } +void radeon_drm_cs_flush(struct r300_winsys_cs *rcs); +void radeon_drm_cs_sync_flush(struct r300_winsys_cs *rcs); void radeon_drm_cs_init_functions(struct radeon_drm_winsys *ws); #endif -- cgit v1.2.3