@@ -17,7 +17,7 @@ use core::{
17
17
slice,
18
18
} ;
19
19
20
- use gem:: BaseObject ;
20
+ use gem:: { BaseObject , IntoGEMObject } ;
21
21
22
22
/// Trait which must be implemented by drivers using shmem-backed GEM objects.
23
23
pub trait DriverObject : gem:: BaseDriverObject < Object < Self > > {
@@ -72,6 +72,8 @@ pub struct Object<T: DriverObject> {
72
72
// The DRM core ensures the Device exists as long as its objects exist, so we don't need to
73
73
// manage the reference count here.
74
74
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 ,
75
77
#[ pin]
76
78
inner : T ,
77
79
}
@@ -98,6 +100,7 @@ unsafe extern "C" fn gem_create_object<T: DriverObject>(
98
100
// SAFETY: GEM ensures the device lives as long as its objects live
99
101
inner <- T :: new( unsafe { device:: Device :: borrow( dev) } , size) ,
100
102
dev,
103
+ parent_resv_obj: core:: ptr:: null( ) ,
101
104
} ) ;
102
105
103
106
// 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_
129
132
core:: ptr:: drop_in_place ( & mut ( * p) . inner ) ;
130
133
}
131
134
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
+
132
144
// SAFETY: This pointer has to be valid, since p is valid
133
145
unsafe {
134
146
bindings:: drm_gem_shmem_free ( & mut ( * p) . obj ) ;
@@ -231,6 +243,25 @@ impl<T: DriverObject> Object<T> {
231
243
// SAFETY: mut_shmem always returns a valid pointer
232
244
( unsafe { * self . mut_shmem ( ) } ) . set_map_wc ( map_wc) ;
233
245
}
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
+ }
234
265
}
235
266
236
267
impl < T : DriverObject > Deref for Object < T > {
0 commit comments