--- a/sys/dev/drm/radeon/evergreen_dma.c +++ b/sys/dev/drm/radeon/evergreen_dma.c @@ -118,6 +118,16 @@ 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, 0xfffff); r = radeon_ring_lock(rdev, ring, num_loops * 5 + 11); @@ -127,8 +137,13 @@ 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); + } for (i = 0; i < num_loops; i++) { cur_size_in_dw = size_in_dw;