Skip to content

Commit 66cb4d0

Browse files
committed
rust: drm/gpuvm: Pass vm_bo explicitly to step_remap()
We cannot drop ARef<GpuVmBo<T>> references within the step_*() calls, since the destructore takes the object lock but that is already locked here. Instead of providing a method that the callback can use to obtain a reference (which, when dropped, would deadlock), grab a reference ourselves and pass it explicitly into the callback as a &ref. Thus, we can drop it without locking again. Signed-off-by: Asahi Lina <lina@asahilina.net>
1 parent f2a88f6 commit 66cb4d0

1 file changed

Lines changed: 22 additions & 15 deletions

File tree

rust/kernel/drm/gpuvm.rs

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ pub trait DriverGpuVm: Sized {
4646
fn step_remap(
4747
self: &mut UpdatingGpuVm<'_, Self>,
4848
op: &mut OpReMap<Self>,
49+
vm_bo: &GpuVmBo<Self>,
4950
ctx: &mut Self::StepContext,
5051
) -> Result;
5152
}
@@ -198,17 +199,6 @@ impl<T: DriverGpuVm> GpuVa<T> {
198199
pub fn range(&self) -> u64 {
199200
self.gpuva.va.range
200201
}
201-
pub fn vm_bo(&self) -> ARef<GpuVmBo<T>> {
202-
// SAFETY: Container invariant is guaranteed for ops structs created for our types.
203-
let p =
204-
unsafe { crate::container_of!(self.gpuva.vm_bo, GpuVmBo<T>, bo) as *mut GpuVmBo<T> };
205-
206-
// SAFETY: We incref and wrap in an ARef, so the reference count is consistent
207-
unsafe {
208-
bindings::drm_gpuvm_bo_get(self.gpuva.vm_bo);
209-
ARef::from_raw(NonNull::new_unchecked(p))
210-
}
211-
}
212202
pub fn offset(&self) -> u64 {
213203
self.gpuva.gem.offset
214204
}
@@ -340,10 +330,27 @@ pub(super) unsafe extern "C" fn step_remap_callback<T: DriverGpuVm>(
340330
// guaranteed to outlive this function.
341331
let ctx = unsafe { &mut *(_priv as *mut StepContext<'_, T>) };
342332

343-
from_result(|| {
344-
UpdatingGpuVm(ctx.gpuvm).step_remap(remap, ctx.ctx)?;
345-
Ok(0)
346-
})
333+
let p_vm_bo = remap.unmap().va().unwrap().gpuva.vm_bo;
334+
335+
let res = {
336+
// SAFETY: vm_bo pointer must be valid and non-null by the step_remap invariants.
337+
// Since we grab a ref, this reference's lifetime is until the decref.
338+
let vm_bo_ref = unsafe {
339+
bindings::drm_gpuvm_bo_get(p_vm_bo);
340+
&*(crate::container_of!(p_vm_bo, GpuVmBo<T>, bo) as *mut GpuVmBo<T>)
341+
};
342+
343+
from_result(|| {
344+
UpdatingGpuVm(ctx.gpuvm).step_remap(remap, vm_bo_ref, ctx.ctx)?;
345+
Ok(0)
346+
})
347+
};
348+
349+
// SAFETY: We incremented the refcount above, and the Rust reference we took is
350+
// no longer in scope.
351+
unsafe { bindings::drm_gpuvm_bo_put(p_vm_bo) };
352+
353+
res
347354
}
348355
pub(super) unsafe extern "C" fn step_unmap_callback<T: DriverGpuVm>(
349356
op: *mut bindings::drm_gpuva_op,

0 commit comments

Comments
 (0)