DF-4414 / fix.diff
diff --git a/sys/dev/drm/radeon/radeon_vm.c b/sys/dev/drm/radeon/radeon_vm.c --- a/sys/dev/drm/radeon/radeon_vm.c +++ b/sys/dev/drm/radeon/radeon_vm.c @@ -1250,13 +1250,27 @@ void radeon_vm_fini(struct radeon_device *rdev, struct radeon_vm *vm) while (vm->va.rb_node) { bo_va = container_of((void *)vm->va.rb_node, struct radeon_bo_va, it); #endif - r = radeon_bo_reserve(bo_va->bo, false); + /* + * DFly interval-tree mock-up: the loop repeats the same + * node until interval_tree_remove() succeeds, so the + * reserve MUST make progress. Use an uninterruptible + * reserve (block until the holder releases instead of + * returning -ERESTARTSYS to a signalled exiting thread, + * which used to spin here forever), and bail out (leak + * the bo_va, matching upstream's single-pass behaviour) + * rather than livelock if it still fails. + */ + r = radeon_bo_reserve(bo_va->bo, true); if (!r) { interval_tree_remove(&bo_va->it, &vm->va); list_del_init(&bo_va->bo_list); radeon_bo_unreserve(bo_va->bo); radeon_fence_unref(&bo_va->last_pt_update); kfree(bo_va); + } else { + dev_err(rdev->dev, + "leaking bo_va in radeon_vm_fini (%d)\n", r); + break; } } |