88
99use 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