--- a/sys/dev/drm/radeon/r600_dma.c +++ b/sys/dev/drm/radeon/r600_dma.c @@ -454,12 +454,22 @@ struct radeon_fence *r600_copy_dma(struct radeon_device *rdev, radeon_sync_create(&sync); + /* Sync with the resv before taking the ring lock: the waits inside + * radeon_sync_resv() may sleep and must not hold rdev->ring_lock. + */ + r = radeon_sync_resv(rdev, &sync, resv, false); + if (r) { + DRM_ERROR("radeon: syncing before moving bo (%d).\n", r); + radeon_sync_free(rdev, &sync, NULL); + return ERR_PTR(r); + } + size_in_dw = (num_gpu_pages << RADEON_GPU_PAGE_SHIFT) / 4; num_loops = DIV_ROUND_UP(size_in_dw, 0xFFFE); r = radeon_ring_lock(rdev, ring, num_loops * 4 + 8); if (r) { DRM_ERROR("radeon: moving bo (%d).\n", r); radeon_sync_free(rdev, &sync, NULL); return ERR_PTR(r); } - radeon_sync_resv(rdev, &sync, resv, false); - radeon_sync_rings(rdev, &sync, ring->idx); + r = radeon_sync_rings(rdev, &sync, ring->idx); + if (r) { + DRM_ERROR("radeon: failed to sync rings while moving bo (%d).\n", r); + radeon_ring_unlock_undo(rdev, ring); + radeon_sync_free(rdev, &sync, NULL); + return ERR_PTR(r); + }