1use crate::{
13 container_of,
14 drm::{
15 driver,
16 gem,
17 private::Sealed,
18 Device,
19 DeviceContext,
20 Registered, },
22 error::to_result,
23 prelude::*,
24 sync::aref::ARef,
25 types::Opaque, };
27use core::{
28 marker::PhantomData,
29 ops::{
30 Deref,
31 DerefMut, },
33 ptr::NonNull, };
35use gem::{
36 BaseObjectPrivate,
37 DriverObject,
38 IntoGEMObject, };
40
41#[derive(Default)]
46pub struct ObjectConfig<'a, T: DriverObject, C: DeviceContext = Registered> {
47 pub map_wc: bool,
49
50 pub parent_resv_obj: Option<&'a Object<T, C>>,
54}
55
56#[repr(C)]
64#[pin_data]
65pub struct Object<T: DriverObject, C: DeviceContext = Registered> {
66 #[pin]
67 obj: Opaque<bindings::drm_gem_shmem_object>,
68 parent_resv_obj: Option<ARef<Object<T, C>>>,
70 #[pin]
71 inner: T,
72 _ctx: PhantomData<C>,
73}
74
75super::impl_aref_for_gem_obj! {
76 impl<T, C> for Object<T, C>
77 where
78 T: DriverObject,
79 C: DeviceContext
80}
81
82unsafe impl<T: DriverObject, C: DeviceContext> Send for Object<T, C> {}
84
85unsafe impl<T: DriverObject, C: DeviceContext> Sync for Object<T, C> {}
87
88impl<T: DriverObject, C: DeviceContext> Object<T, C> {
89 const VTABLE: bindings::drm_gem_object_funcs = bindings::drm_gem_object_funcs {
91 free: Some(Self::free_callback),
92 open: Some(super::open_callback::<T>),
93 close: Some(super::close_callback::<T>),
94 print_info: Some(bindings::drm_gem_shmem_object_print_info),
95 export: None,
96 pin: Some(bindings::drm_gem_shmem_object_pin),
97 unpin: Some(bindings::drm_gem_shmem_object_unpin),
98 get_sg_table: Some(bindings::drm_gem_shmem_object_get_sg_table),
99 vmap: Some(bindings::drm_gem_shmem_object_vmap),
100 vunmap: Some(bindings::drm_gem_shmem_object_vunmap),
101 mmap: Some(bindings::drm_gem_shmem_object_mmap),
102 status: None,
103 rss: None,
104 #[allow(unused_unsafe, reason = "Safe since Rust 1.82.0")]
105 vm_ops: unsafe { &raw const bindings::drm_gem_shmem_vm_ops },
107 evict: None,
108 };
109
110 fn as_raw_shmem(&self) -> *mut bindings::drm_gem_shmem_object {
112 self.obj.get()
113 }
114
115 pub fn new(
119 dev: &Device<T::Driver, C>,
120 size: usize,
121 config: ObjectConfig<'_, T, C>,
122 args: T::Args,
123 ) -> Result<ARef<Self>> {
124 let new: Pin<KBox<Self>> = KBox::try_pin_init(
125 try_pin_init!(Self {
126 obj <- Opaque::init_zeroed(),
127 parent_resv_obj: config.parent_resv_obj.map(|p| p.into()),
128 inner <- T::new(dev, size, args),
129 _ctx: PhantomData::<C>,
130 }),
131 GFP_KERNEL,
132 )?;
133
134 unsafe { (*new.as_raw()).funcs = &Self::VTABLE };
136
137 to_result(unsafe { bindings::drm_gem_shmem_init(dev.as_raw(), new.as_raw_shmem(), size) })?;
139
140 let new = KBox::into_raw(unsafe { Pin::into_inner_unchecked(new) });
142
143 let obj = unsafe { ARef::from_raw(NonNull::new_unchecked(new)) };
145
146 if let Some(parent_resv) = config.parent_resv_obj {
148 unsafe { (*obj.obj.get()).base.resv = parent_resv.raw_dma_resv() };
151 }
152
153 let shmem = unsafe { &mut *obj.as_raw_shmem() };
156 shmem.set_map_wc(config.map_wc);
157
158 Ok(obj)
159 }
160
161 pub fn dev(&self) -> &Device<T::Driver, C> {
163 unsafe { Device::from_raw((*self.as_raw()).dev) }
165 }
166
167 extern "C" fn free_callback(obj: *mut bindings::drm_gem_object) {
168 let this = unsafe { container_of!(obj, bindings::drm_gem_shmem_object, base) };
173
174 unsafe { bindings::drm_gem_shmem_release(this) };
178
179 let this = unsafe { container_of!(Opaque::cast_from(this), Self, obj) }.cast_mut();
184
185 let _ = unsafe { KBox::from_raw(this) };
187 }
188}
189
190impl<T: DriverObject, C: DeviceContext> Deref for Object<T, C> {
191 type Target = T;
192
193 fn deref(&self) -> &Self::Target {
194 &self.inner
195 }
196}
197
198impl<T: DriverObject, C: DeviceContext> DerefMut for Object<T, C> {
199 fn deref_mut(&mut self) -> &mut Self::Target {
200 &mut self.inner
201 }
202}
203
204impl<T: DriverObject, C: DeviceContext> Sealed for Object<T, C> {}
205
206impl<T: DriverObject, C: DeviceContext> gem::IntoGEMObject for Object<T, C> {
207 fn as_raw(&self) -> *mut bindings::drm_gem_object {
208 unsafe { &raw mut (*self.obj.get()).base }
212 }
213
214 unsafe fn from_raw<'a>(obj: *mut bindings::drm_gem_object) -> &'a Self {
215 unsafe {
218 let obj = Opaque::cast_from(container_of!(obj, bindings::drm_gem_shmem_object, base));
219
220 &*container_of!(obj, Self, obj)
221 }
222 }
223}
224
225impl<T: DriverObject, C: DeviceContext> driver::AllocImpl for Object<T, C> {
226 type Driver = T::Driver;
227
228 const ALLOC_OPS: driver::AllocOps = driver::AllocOps {
229 gem_create_object: None,
230 prime_handle_to_fd: None,
231 prime_fd_to_handle: None,
232 gem_prime_import: None,
233 gem_prime_import_sg_table: Some(bindings::drm_gem_shmem_prime_import_sg_table),
234 dumb_create: Some(bindings::drm_gem_shmem_dumb_create),
235 dumb_map_offset: None,
236 };
237}