⬢ DragonFlyBSD Kernel Audit
DF-5170 / fix.diff
← back to finding ↓ download raw
--- 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;