Skip to content

Commit 5d9ff4b

Browse files
asahilinajannau
authored andcommitted
rust: drm: gem: shmem: Add share_dma_resv() function
Allow a GEM object to share another object's DMA reservation, for use with drm_gpuvm. To keep memory safety, we hold a reference to the GEM object owning the resv, and drop it when the child object is freed. Signed-off-by: Asahi Lina <[email protected]>
1 parent 09d225e commit 5d9ff4b

File tree

1 file changed

+32
-1
lines changed

1 file changed

+32
-1
lines changed

rust/kernel/drm/gem/shmem.rs

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -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.
2323
pub 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

236267
impl<T: DriverObject> Deref for Object<T> {

0 commit comments

Comments
 (0)