diff --git a/sys/dev/drm/radeon/rv770_dma.c b/sys/dev/drm/radeon/rv770_dma.c index acff6e09..16c2616c 100644 --- a/sys/dev/drm/radeon/rv770_dma.c +++ b/sys/dev/drm/radeon/rv770_dma.c @@ -56,7 +56,17 @@ struct radeon_fence *rv770_copy_dma(struct radeon_device *rdev, size_in_dw = (num_gpu_pages << RADEON_GPU_PAGE_SHIFT) / 4; num_loops = DIV_ROUND_UP(size_in_dw, 0xFFFF); - r = radeon_ring_lock(rdev, ring, num_loops * 5 + 8); + /* Reserve space for everything radeon_sync_rings() may emit on THIS + * ring (up to RADEON_NUM_SYNCS semaphore waits, 3 dwords each on the + * r6xx/r7xx DMA ring) plus the 5-dword fence emit. The old "+8" + * covered exactly one semaphore wait; with two pending cross-ring + * fences (GFX + UVD) the over-emission wrote 16 dwords past the + * reserved window (radeon_ring_write() only DRM_ERRORs and writes + * anyway, radeon.h:2710-2716), overwriting un-executed ring commands + * when the ring is tight. Mirrors the IB-path accounting + * (radeon_ib.c reserves 64 + RADEON_NUM_SYNCS * 8, radeon_ib.c:135). + */ + r = radeon_ring_lock(rdev, ring, num_loops * 5 + 8 + RADEON_NUM_SYNCS * 3); if (r) { DRM_ERROR("radeon: moving bo (%d).\n", r); radeon_sync_free(rdev, &sync, NULL);