1use crate::{
13 container_of,
14 drm::{
15 device,
16 driver,
17 gem,
18 private::Sealed, },
20 error::to_result,
21 prelude::*,
22 sync::aref::ARef,
23 types::Opaque, };
25use core::{
26 ops::{
27 Deref,
28 DerefMut, },
30 ptr::NonNull,
31};
32use gem::{
33 BaseObjectPrivate,
34 DriverObject,
35 IntoGEMObject, };
37
38#[derive(Default)]
43pub struct ObjectConfig<'a, T: DriverObject> {
44 pub map_wc: bool,
46
47 pub parent_resv_obj: Option<&'a Object<T>>,
51}
52
53#[repr(C)]
60#[pin_data]
61pub struct Object<T: DriverObject> {
62 #[pin]
63 obj: Opaque<bindings::drm_gem_shmem_object>,
64 parent_resv_obj: Option<ARef<Object<T>>>,
66 #[pin]
67 inner: T,
68}
69
70super::impl_aref_for_gem_obj!(impl<T> for Object<T> where T: DriverObject);
71
72unsafe impl<T: DriverObject> Send for Object<T> {}
74
75unsafe impl<T: DriverObject> Sync for Object<T> {}
77
78impl<T: DriverObject> Object<T> {
79 const VTABLE: bindings::drm_gem_object_funcs = bindings::drm_gem_object_funcs {
81 free: Some(Self::free_callback),
82 open: Some(super::open_callback::<T>),
83 close: Some(super::close_callback::<T>),
84 print_info: Some(bindings::drm_gem_shmem_object_print_info),
85 export: None,
86 pin: Some(bindings::drm_gem_shmem_object_pin),
87 unpin: Some(bindings::drm_gem_shmem_object_unpin),
88 get_sg_table: Some(bindings::drm_gem_shmem_object_get_sg_table),
89 vmap: Some(bindings::drm_gem_shmem_object_vmap),
90 vunmap: Some(bindings::drm_gem_shmem_object_vunmap),
91 mmap: Some(bindings::drm_gem_shmem_object_mmap),
92 status: None,
93 rss: None,
94 #[allow(unused_unsafe, reason = "Safe since Rust 1.82.0")]
95 vm_ops: unsafe { &raw const bindings::drm_gem_shmem_vm_ops },
97 evict: None,
98 };
99
100 fn as_raw_shmem(&self) -> *mut bindings::drm_gem_shmem_object {
102 self.obj.get()
103 }
104
105 pub fn new(
109 dev: &device::Device<T::Driver>,
110 size: usize,
111 config: ObjectConfig<'_, T>,
112 args: T::Args,
113 ) -> Result<ARef<Self>> {
114 let new: Pin<KBox<Self>> = KBox::try_pin_init(
115 try_pin_init!(Self {
116 obj <- Opaque::init_zeroed(),
117 parent_resv_obj: config.parent_resv_obj.map(|p| p.into()),
118 inner <- T::new(dev, size, args),
119 }),
120 GFP_KERNEL,
121 )?;
122
123 unsafe { (*new.as_raw()).funcs = &Self::VTABLE };
125
126 to_result(unsafe { bindings::drm_gem_shmem_init(dev.as_raw(), new.as_raw_shmem(), size) })?;
128
129 let new = KBox::into_raw(unsafe { Pin::into_inner_unchecked(new) });
131
132 let obj = unsafe { ARef::from_raw(NonNull::new_unchecked(new)) };
134
135 if let Some(parent_resv) = config.parent_resv_obj {
137 unsafe { (*obj.obj.get()).base.resv = parent_resv.raw_dma_resv() };
140 }
141
142 let shmem = unsafe { &mut *obj.as_raw_shmem() };
145 shmem.set_map_wc(config.map_wc);
146
147 Ok(obj)
148 }
149
150 pub fn dev(&self) -> &device::Device<T::Driver> {
152 unsafe { device::Device::from_raw((*self.as_raw()).dev) }
154 }
155
156 extern "C" fn free_callback(obj: *mut bindings::drm_gem_object) {
157 let this = unsafe { container_of!(obj, bindings::drm_gem_shmem_object, base) };
162
163 unsafe { bindings::drm_gem_shmem_release(this) };
167
168 let this = unsafe { container_of!(Opaque::cast_from(this), Self, obj) }.cast_mut();
173
174 let _ = unsafe { KBox::from_raw(this) };
176 }
177}
178
179impl<T: DriverObject> Deref for Object<T> {
180 type Target = T;
181
182 fn deref(&self) -> &Self::Target {
183 &self.inner
184 }
185}
186
187impl<T: DriverObject> DerefMut for Object<T> {
188 fn deref_mut(&mut self) -> &mut Self::Target {
189 &mut self.inner
190 }
191}
192
193impl<T: DriverObject> Sealed for Object<T> {}
194
195impl<T: DriverObject> gem::IntoGEMObject for Object<T> {
196 fn as_raw(&self) -> *mut bindings::drm_gem_object {
197 unsafe { &raw mut (*self.obj.get()).base }
201 }
202
203 unsafe fn from_raw<'a>(obj: *mut bindings::drm_gem_object) -> &'a Object<T> {
204 unsafe {
207 let obj = Opaque::cast_from(container_of!(obj, bindings::drm_gem_shmem_object, base));
208
209 &*container_of!(obj, Object<T>, obj)
210 }
211 }
212}
213
214impl<T: DriverObject> driver::AllocImpl for Object<T> {
215 type Driver = T::Driver;
216
217 const ALLOC_OPS: driver::AllocOps = driver::AllocOps {
218 gem_create_object: None,
219 prime_handle_to_fd: None,
220 prime_fd_to_handle: None,
221 gem_prime_import: None,
222 gem_prime_import_sg_table: Some(bindings::drm_gem_shmem_prime_import_sg_table),
223 dumb_create: Some(bindings::drm_gem_shmem_dumb_create),
224 dumb_map_offset: None,
225 };
226}