Skip to content

Commit 80de0b4

Browse files
committed
rust: drm: gpuvm: Switch to DRM_GPUVM_IMMEDIATE_MODE
DRM_GPUVM_IMMEDIATE_MODE allows for deferred gpuva unlink and gpuvm bo release. Signed-off-by: Janne Grunau <j@jannau.net>
1 parent 5d6788d commit 80de0b4

2 files changed

Lines changed: 102 additions & 4 deletions

File tree

rust/helpers/drm_gpuvm.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,11 @@ struct drm_gpuvm_bo *rust_helper_drm_gpuvm_bo_get(struct drm_gpuvm_bo *vm_bo)
2525
return drm_gpuvm_bo_get(vm_bo);
2626
}
2727

28+
bool rust_helper_drm_gpuvm_immediate_mode(struct drm_gpuvm *gpuvm)
29+
{
30+
return drm_gpuvm_immediate_mode(gpuvm);
31+
}
32+
2833
bool rust_helper_drm_gpuvm_is_extobj(struct drm_gpuvm *gpuvm, struct drm_gem_object *obj)
2934
{
3035
return drm_gpuvm_is_extobj(gpuvm, obj);

rust/kernel/drm/gpuvm.rs

Lines changed: 97 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,13 @@
88

99
use crate::{
1010
bindings, drm,
11-
drm::device,
11+
drm::{
12+
device,
13+
gem::{
14+
BaseObject,
15+
IntoGEMObject, //
16+
},
17+
},
1218
error::{
1319
code::{EINVAL, ENOMEM},
1420
from_result, to_result, Error, Result,
@@ -177,7 +183,9 @@ impl<T: DriverGpuVm> OpMap<T> {
177183
return Err(Pin::new_unchecked(KBox::from_raw(p)));
178184
};
179185
// SAFETY: This takes a new reference to the gpuvmbo.
186+
gpuvmbo.lock_gpuva();
180187
bindings::drm_gpuva_link(&mut p.gpuva, &gpuvmbo.bo as *const _ as *mut _);
188+
gpuvmbo.unlock_gpuva();
181189
}
182190
Ok(())
183191
}
@@ -194,6 +202,12 @@ impl<T: DriverGpuVm> OpUnMap<T> {
194202
Some(unsafe { &*p })
195203
}
196204
pub fn unmap_and_unlink_va(&mut self) -> Option<Pin<KBox<GpuVa<T>>>> {
205+
self.do_unmap_and_unlink_va(false)
206+
}
207+
pub fn unmap_and_unlink_va_defer(&mut self) -> Option<Pin<KBox<GpuVa<T>>>> {
208+
self.do_unmap_and_unlink_va(true)
209+
}
210+
fn do_unmap_and_unlink_va(&mut self, defer: bool) -> Option<Pin<KBox<GpuVa<T>>>> {
197211
if self.0.va.is_null() {
198212
return None;
199213
}
@@ -203,7 +217,11 @@ impl<T: DriverGpuVm> OpUnMap<T> {
203217
// SAFETY: The GpuVa object reference is valid per the op_unmap contract
204218
unsafe {
205219
bindings::drm_gpuva_unmap(&mut self.0);
206-
bindings::drm_gpuva_unlink(self.0.va);
220+
if defer {
221+
bindings::drm_gpuva_unlink_defer(self.0.va);
222+
} else {
223+
bindings::drm_gpuva_unlink(self.0.va);
224+
}
207225
}
208226

209227
// Unlinking/unmapping relinquishes ownership of the GpuVa object,
@@ -287,6 +305,20 @@ impl<T: DriverGpuVm> GpuVmBo<T> {
287305
pub fn inner(&self) -> &T::GpuVmBo {
288306
&self.inner
289307
}
308+
/// Lock the GpuVmBo's gem boject gpuva lock
309+
pub fn lock_gpuva(&self) {
310+
unsafe {
311+
let lock = &raw mut (*self.bo.obj).gpuva.lock;
312+
bindings::mutex_lock(lock);
313+
}
314+
}
315+
/// Unlock the GpuVmBo's gem boject gpuva lock
316+
pub fn unlock_gpuva(&self) {
317+
unsafe {
318+
let lock = &raw mut (*self.bo.obj).gpuva.lock;
319+
bindings::mutex_unlock(lock);
320+
}
321+
}
290322
}
291323

292324
// SAFETY: DRM GpuVmBo objects are always reference counted and the get/put functions
@@ -414,7 +446,7 @@ pub(super) unsafe extern "C" fn step_remap_callback<T: DriverGpuVm>(
414446

415447
// SAFETY: We incremented the refcount above, and the Rust reference we took is
416448
// no longer in scope.
417-
unsafe { bindings::drm_gpuvm_bo_put(p_vm_bo) };
449+
unsafe { bindings::drm_gpuvm_bo_put_deferred(p_vm_bo) };
418450

419451
res
420452
}
@@ -461,6 +493,7 @@ impl<T: DriverGpuVm> GpuVm<T> {
461493

462494
pub fn new<E>(
463495
name: &'static CStr,
496+
flags: bindings::drm_gpuvm_flags,
464497
dev: &device::Device<T::Driver>,
465498
r_obj: ARef<<<T::Driver as drm::Driver>::Object as BaseDriverObject>::Object>,
466499
range: Range<u64>,
@@ -480,7 +513,7 @@ impl<T: DriverGpuVm> GpuVm<T> {
480513
bindings::drm_gpuvm_init(
481514
Opaque::cast_into(slot),
482515
name.as_char_ptr(),
483-
0,
516+
flags,
484517
dev.as_raw(),
485518
r_obj.as_raw() as *const _ as *mut _,
486519
range.start,
@@ -560,6 +593,66 @@ impl<T: DriverGpuVm> GpuVm<T> {
560593
// SAFETY: This is safe to call as long as the arguments are valid pointers.
561594
unsafe { bindings::drm_gpuvm_is_extobj(self.gpuvm() as *mut _, gem) }
562595
}
596+
597+
pub fn bo_deferred_cleanup(&self) {
598+
unsafe { bindings::drm_gpuvm_bo_deferred_cleanup(self.gpuvm() as *mut _) }
599+
}
600+
601+
pub fn find_bo(& self,
602+
obj: &Object<T>
603+
) -> Option<ARef<GpuVmBo<T>>> {
604+
obj.lock_gpuva();
605+
// SAFETY: drm_gem_object.gpuva.lock was just locked.
606+
let p = unsafe {
607+
bindings::drm_gpuvm_bo_find(
608+
self.gpuvm() as *mut _,
609+
obj.as_raw() as *const _ as *mut _,
610+
)
611+
};
612+
obj.unlock_gpuva();
613+
if p.is_null() {
614+
None
615+
} else {
616+
// SAFETY: All the drm_gpuvm_bo objects in this GpuVm are always allocated by us as GpuVmBo<T>.
617+
let p = unsafe { crate::container_of!(p, GpuVmBo<T>, bo) as *mut GpuVmBo<T> };
618+
// SAFETY: We checked for NULL above, and the types ensure that
619+
// this object was created by vm_bo_alloc_callback<T>.
620+
Some(unsafe { ARef::from_raw(NonNull::new_unchecked(p)) })
621+
}
622+
}
623+
624+
pub fn obtain_bo(& self,
625+
obj: &Object<T>) -> Result<ARef<GpuVmBo<T>>> {
626+
obj.lock_gpuva();
627+
// SAFETY: drm_gem_object.gpuva.lock was just locked.
628+
let p = unsafe {
629+
bindings::drm_gpuvm_bo_obtain(
630+
self.gpuvm() as *mut _,
631+
obj.as_raw() as *const _ as *mut _,
632+
)
633+
};
634+
obj.unlock_gpuva();
635+
if p.is_null() {
636+
Err(ENOMEM)
637+
} else {
638+
// SAFETY: Container invariant is guaranteed for GpuVmBo objects for this GpuVm.
639+
let p = unsafe { crate::container_of!(p, GpuVmBo<T>, bo) as *mut GpuVmBo<T> };
640+
// SAFETY: We checked for NULL above, and the types ensure that
641+
// this object was created by vm_bo_alloc_callback<T>.
642+
Ok(unsafe { ARef::from_raw(NonNull::new_unchecked(p)) })
643+
}
644+
}
645+
646+
pub fn bo_unmap(& self, ctx: &mut T::StepContext, bo: &GpuVmBo<T>) -> Result {
647+
let mut ctx = StepContext {
648+
ctx,
649+
gpuvm: self,
650+
};
651+
// SAFETY: LockedGpuVm implies the right locks are held.
652+
to_result(unsafe {
653+
bindings::drm_gpuvm_bo_unmap(&bo.bo as *const _ as *mut _, &mut ctx as *mut _ as *mut _)
654+
})
655+
}
563656
}
564657

565658
// SAFETY: DRM GpuVm objects are always reference counted and the get/put functions

0 commit comments

Comments
 (0)