88
99use crate :: {
1010 bindings, drm,
11- drm:: device,
11+ drm:: { device, gem :: BaseObject } ,
1212 error:: {
1313 code:: { EINVAL , ENOMEM } ,
1414 from_result, to_result, Error , Result ,
@@ -177,7 +177,9 @@ impl<T: DriverGpuVm> OpMap<T> {
177177 return Err ( Pin :: new_unchecked ( KBox :: from_raw ( p) ) ) ;
178178 } ;
179179 // SAFETY: This takes a new reference to the gpuvmbo.
180+ gpuvmbo. lock_gpuva ( ) ;
180181 bindings:: drm_gpuva_link ( & mut p. gpuva , & gpuvmbo. bo as * const _ as * mut _ ) ;
182+ gpuvmbo. unlock_gpuva ( ) ;
181183 }
182184 Ok ( ( ) )
183185 }
@@ -194,6 +196,12 @@ impl<T: DriverGpuVm> OpUnMap<T> {
194196 Some ( unsafe { & * p } )
195197 }
196198 pub fn unmap_and_unlink_va ( & mut self ) -> Option < Pin < KBox < GpuVa < T > > > > {
199+ self . do_unmap_and_unlink_va ( false )
200+ }
201+ pub fn unmap_and_unlink_va_defer ( & mut self ) -> Option < Pin < KBox < GpuVa < T > > > > {
202+ self . do_unmap_and_unlink_va ( true )
203+ }
204+ fn do_unmap_and_unlink_va ( & mut self , defer : bool ) -> Option < Pin < KBox < GpuVa < T > > > > {
197205 if self . 0 . va . is_null ( ) {
198206 return None ;
199207 }
@@ -203,7 +211,11 @@ impl<T: DriverGpuVm> OpUnMap<T> {
203211 // SAFETY: The GpuVa object reference is valid per the op_unmap contract
204212 unsafe {
205213 bindings:: drm_gpuva_unmap ( & mut self . 0 ) ;
206- bindings:: drm_gpuva_unlink ( self . 0 . va ) ;
214+ if defer {
215+ bindings:: drm_gpuva_unlink_defer ( self . 0 . va ) ;
216+ } else {
217+ bindings:: drm_gpuva_unlink ( self . 0 . va ) ;
218+ }
207219 }
208220
209221 // Unlinking/unmapping relinquishes ownership of the GpuVa object,
@@ -287,6 +299,20 @@ impl<T: DriverGpuVm> GpuVmBo<T> {
287299 pub fn inner ( & self ) -> & T :: GpuVmBo {
288300 & self . inner
289301 }
302+ /// Lock the GpuVmBo's gem boject gpuva lock
303+ pub fn lock_gpuva ( & self ) {
304+ unsafe {
305+ let lock = & raw mut ( * self . bo . obj ) . gpuva . lock ;
306+ bindings:: mutex_lock ( lock) ;
307+ }
308+ }
309+ /// Unlock the GpuVmBo's gem boject gpuva lock
310+ pub fn unlock_gpuva ( & self ) {
311+ unsafe {
312+ let lock = & raw mut ( * self . bo . obj ) . gpuva . lock ;
313+ bindings:: mutex_unlock ( lock) ;
314+ }
315+ }
290316}
291317
292318// SAFETY: DRM GpuVmBo objects are always reference counted and the get/put functions
@@ -302,10 +328,9 @@ unsafe impl<T: DriverGpuVm> AlwaysRefCounted for GpuVmBo<T> {
302328 // The drm_gpuvm_put function satisfies the requirements for dec_ref().
303329 // (We do not support custom locks yet.)
304330 unsafe {
305- let resv = ( * obj. as_mut ( ) . bo . obj ) . resv ;
306- bindings:: dma_resv_lock ( resv, core:: ptr:: null_mut ( ) ) ;
331+ obj. as_mut ( ) . lock_gpuva ( ) ;
307332 bindings:: drm_gpuvm_bo_put ( & mut obj. as_mut ( ) . bo ) ;
308- bindings :: dma_resv_unlock ( resv ) ;
333+ obj . as_mut ( ) . unlock_gpuva ( ) ;
309334 }
310335 }
311336}
@@ -414,7 +439,7 @@ pub(super) unsafe extern "C" fn step_remap_callback<T: DriverGpuVm>(
414439
415440 // SAFETY: We incremented the refcount above, and the Rust reference we took is
416441 // no longer in scope.
417- unsafe { bindings:: drm_gpuvm_bo_put ( p_vm_bo) } ;
442+ unsafe { bindings:: drm_gpuvm_bo_put_deferred ( p_vm_bo) } ;
418443
419444 res
420445}
@@ -461,6 +486,7 @@ impl<T: DriverGpuVm> GpuVm<T> {
461486
462487 pub fn new < E > (
463488 name : & ' static CStr ,
489+ flags : bindings:: drm_gpuvm_flags ,
464490 dev : & device:: Device < T :: Driver > ,
465491 r_obj : ARef < <<T :: Driver as drm:: Driver >:: Object as BaseDriverObject >:: Object > ,
466492 range : Range < u64 > ,
@@ -480,7 +506,7 @@ impl<T: DriverGpuVm> GpuVm<T> {
480506 bindings:: drm_gpuvm_init(
481507 Opaque :: cast_into( slot) ,
482508 name. as_char_ptr( ) ,
483- 0 ,
509+ flags ,
484510 dev. as_raw( ) ,
485511 r_obj. as_raw( ) as * const _ as * mut _,
486512 range. start,
@@ -560,6 +586,66 @@ impl<T: DriverGpuVm> GpuVm<T> {
560586 // SAFETY: This is safe to call as long as the arguments are valid pointers.
561587 unsafe { bindings:: drm_gpuvm_is_extobj ( self . gpuvm ( ) as * mut _ , gem) }
562588 }
589+
590+ pub fn bo_deferred_cleanup ( & self ) {
591+ unsafe { bindings:: drm_gpuvm_bo_deferred_cleanup ( self . gpuvm ( ) as * mut _ ) }
592+ }
593+
594+ pub fn find_bo ( & self ,
595+ obj : & <<T :: Driver as drm:: Driver >:: Object as BaseDriverObject >:: Object
596+ ) -> Option < ARef < GpuVmBo < T > > > {
597+ obj. lock_gpuva ( ) ;
598+ // SAFETY: drm_gem_object.gpuva.lock was just locked.
599+ let p = unsafe {
600+ bindings:: drm_gpuvm_bo_find (
601+ self . gpuvm ( ) as * mut _ ,
602+ obj. as_raw ( ) as * const _ as * mut _ ,
603+ )
604+ } ;
605+ obj. unlock_gpuva ( ) ;
606+ if p. is_null ( ) {
607+ None
608+ } else {
609+ // SAFETY: All the drm_gpuvm_bo objects in this GpuVm are always allocated by us as GpuVmBo<T>.
610+ let p = unsafe { crate :: container_of!( p, GpuVmBo <T >, bo) as * mut GpuVmBo < T > } ;
611+ // SAFETY: We checked for NULL above, and the types ensure that
612+ // this object was created by vm_bo_alloc_callback<T>.
613+ Some ( unsafe { ARef :: from_raw ( NonNull :: new_unchecked ( p) ) } )
614+ }
615+ }
616+
617+ pub fn obtain_bo ( & self ,
618+ obj : & <<T :: Driver as drm:: Driver >:: Object as BaseDriverObject >:: Object ) -> Result < ARef < GpuVmBo < T > > > {
619+ obj. lock_gpuva ( ) ;
620+ // SAFETY: drm_gem_object.gpuva.lock was just locked.
621+ let p = unsafe {
622+ bindings:: drm_gpuvm_bo_obtain (
623+ self . gpuvm ( ) as * mut _ ,
624+ obj. as_raw ( ) as * const _ as * mut _ ,
625+ )
626+ } ;
627+ obj. unlock_gpuva ( ) ;
628+ if p. is_null ( ) {
629+ Err ( ENOMEM )
630+ } else {
631+ // SAFETY: Container invariant is guaranteed for GpuVmBo objects for this GpuVm.
632+ let p = unsafe { crate :: container_of!( p, GpuVmBo <T >, bo) as * mut GpuVmBo < T > } ;
633+ // SAFETY: We checked for NULL above, and the types ensure that
634+ // this object was created by vm_bo_alloc_callback<T>.
635+ Ok ( unsafe { ARef :: from_raw ( NonNull :: new_unchecked ( p) ) } )
636+ }
637+ }
638+
639+ pub fn bo_unmap ( & self , ctx : & mut T :: StepContext , bo : & GpuVmBo < T > ) -> Result {
640+ let mut ctx = StepContext {
641+ ctx,
642+ gpuvm : self ,
643+ } ;
644+ // SAFETY: LockedGpuVm implies the right locks are held.
645+ to_result ( unsafe {
646+ bindings:: drm_gpuvm_bo_unmap ( & bo. bo as * const _ as * mut _ , & mut ctx as * mut _ as * mut _ )
647+ } )
648+ }
563649}
564650
565651// SAFETY: DRM GpuVm objects are always reference counted and the get/put functions
0 commit comments