@@ -17,7 +17,7 @@ use core::{
1717 slice,
1818} ;
1919
20- use gem:: BaseObject ;
20+ use gem:: { BaseObject , IntoGEMObject } ;
2121
2222/// Trait which must be implemented by drivers using shmem-backed GEM objects.
2323pub trait DriverObject : gem:: BaseDriverObject < Object < Self > > {
@@ -72,6 +72,8 @@ pub struct Object<T: DriverObject> {
7272 // The DRM core ensures the Device exists as long as its objects exist, so we don't need to
7373 // manage the reference count here.
7474 dev : * const bindings:: drm_device ,
75+ // Parent object that owns this object's DMA reservation object
76+ parent_resv_obj : * const bindings:: drm_gem_object ,
7577 #[ pin]
7678 inner : T ,
7779}
@@ -98,6 +100,7 @@ unsafe extern "C" fn gem_create_object<T: DriverObject>(
98100 // SAFETY: GEM ensures the device lives as long as its objects live
99101 inner <- T :: new( unsafe { device:: Device :: borrow( dev) } , size) ,
100102 dev,
103+ parent_resv_obj: core:: ptr:: null( ) ,
101104 } ) ;
102105
103106 // SAFETY: p is a valid pointer to an uninitialized Object<T>.
@@ -129,6 +132,15 @@ unsafe extern "C" fn free_callback<T: DriverObject>(obj: *mut bindings::drm_gem_
129132 core:: ptr:: drop_in_place ( & mut ( * p) . inner ) ;
130133 }
131134
135+ // SAFETY: parent_resv_obj is either NULL or a valid reference to the
136+ // GEM object owning the DMA reservation for this object, which we drop
137+ // here.
138+ unsafe {
139+ if !( * p) . parent_resv_obj . is_null ( ) {
140+ bindings:: drm_gem_object_put ( ( * p) . parent_resv_obj as * const _ as * mut _ ) ;
141+ }
142+ }
143+
132144 // SAFETY: This pointer has to be valid, since p is valid
133145 unsafe {
134146 bindings:: drm_gem_shmem_free ( & mut ( * p) . obj ) ;
@@ -231,6 +243,25 @@ impl<T: DriverObject> Object<T> {
231243 // SAFETY: mut_shmem always returns a valid pointer
232244 ( unsafe { * self . mut_shmem ( ) } ) . set_map_wc ( map_wc) ;
233245 }
246+
247+ /// Share the dma_resv object from another GEM object.
248+ ///
249+ /// Should be called before the object is used/shared. Can only be called once.
250+ pub fn share_dma_resv ( & mut self , from_object : & impl IntoGEMObject ) -> Result {
251+ let from_obj = from_object. gem_obj ( ) ;
252+ if !self . parent_resv_obj . is_null ( ) {
253+ Err ( EBUSY )
254+ } else {
255+ // SAFETY: from_obj is a valid object pointer per the trait Invariant.
256+ unsafe {
257+ bindings:: drm_gem_object_get ( from_obj as * const _ as * mut _ ) ;
258+ }
259+ self . parent_resv_obj = from_obj;
260+ let gem = self . mut_gem_obj ( ) ;
261+ gem. resv = from_obj. resv ;
262+ Ok ( ( ) )
263+ }
264+ }
234265}
235266
236267impl < T : DriverObject > Deref for Object < T > {
0 commit comments