1 // SPDX-License-Identifier: GPL-2.0 OR MIT 2 3 //! DRM device. 4 //! 5 //! C header: [`include/drm/drm_device.h`](srctree/include/drm/drm_device.h) 6 7 use crate::{ 8 alloc::allocator::Kmalloc, 9 bindings, device, 10 drm::{ 11 self, 12 driver::AllocImpl, // 13 }, 14 error::from_err_ptr, 15 prelude::*, 16 sync::aref::{ 17 ARef, 18 AlwaysRefCounted, // 19 }, 20 types::Opaque, 21 workqueue::{ 22 HasDelayedWork, 23 HasWork, 24 Work, 25 WorkItem, // 26 }, 27 }; 28 use core::{ 29 alloc::Layout, 30 mem, 31 ops::Deref, 32 ptr::{ 33 self, 34 NonNull, // 35 }, 36 }; 37 38 #[cfg(CONFIG_DRM_LEGACY)] 39 macro_rules! drm_legacy_fields { 40 ( $($field:ident: $val:expr),* $(,)? ) => { 41 bindings::drm_driver { 42 $( $field: $val ),*, 43 firstopen: None, 44 preclose: None, 45 dma_ioctl: None, 46 dma_quiescent: None, 47 context_dtor: None, 48 irq_handler: None, 49 irq_preinstall: None, 50 irq_postinstall: None, 51 irq_uninstall: None, 52 get_vblank_counter: None, 53 enable_vblank: None, 54 disable_vblank: None, 55 dev_priv_size: 0, 56 } 57 } 58 } 59 60 #[cfg(not(CONFIG_DRM_LEGACY))] 61 macro_rules! drm_legacy_fields { 62 ( $($field:ident: $val:expr),* $(,)? ) => { 63 bindings::drm_driver { 64 $( $field: $val ),* 65 } 66 } 67 } 68 69 /// A typed DRM device with a specific `drm::Driver` implementation. 70 /// 71 /// The device is always reference-counted. 72 /// 73 /// # Invariants 74 /// 75 /// `self.dev` is a valid instance of a `struct device`. 76 #[repr(C)] 77 pub struct Device<T: drm::Driver> { 78 dev: Opaque<bindings::drm_device>, 79 data: T::Data, 80 } 81 82 impl<T: drm::Driver> Device<T> { 83 const fn compute_features() -> u32 { 84 let mut features = drm::driver::FEAT_GEM; 85 86 if T::FEAT_RENDER { 87 features |= drm::driver::FEAT_RENDER; 88 } 89 90 features 91 } 92 93 const VTABLE: bindings::drm_driver = drm_legacy_fields! { 94 load: None, 95 open: Some(drm::File::<T::File>::open_callback), 96 postclose: Some(drm::File::<T::File>::postclose_callback), 97 unload: None, 98 release: Some(Self::release), 99 master_set: None, 100 master_drop: None, 101 debugfs_init: None, 102 gem_create_object: T::Object::ALLOC_OPS.gem_create_object, 103 prime_handle_to_fd: T::Object::ALLOC_OPS.prime_handle_to_fd, 104 prime_fd_to_handle: T::Object::ALLOC_OPS.prime_fd_to_handle, 105 gem_prime_import: T::Object::ALLOC_OPS.gem_prime_import, 106 gem_prime_import_sg_table: T::Object::ALLOC_OPS.gem_prime_import_sg_table, 107 dumb_create: T::Object::ALLOC_OPS.dumb_create, 108 dumb_map_offset: T::Object::ALLOC_OPS.dumb_map_offset, 109 show_fdinfo: None, 110 fbdev_probe: None, 111 112 major: T::INFO.major, 113 minor: T::INFO.minor, 114 patchlevel: T::INFO.patchlevel, 115 name: crate::str::as_char_ptr_in_const_context(T::INFO.name).cast_mut(), 116 desc: crate::str::as_char_ptr_in_const_context(T::INFO.desc).cast_mut(), 117 118 driver_features: Self::compute_features(), 119 ioctls: T::IOCTLS.as_ptr(), 120 num_ioctls: T::IOCTLS.len() as i32, 121 fops: &Self::GEM_FOPS, 122 }; 123 124 const GEM_FOPS: bindings::file_operations = drm::gem::create_fops(); 125 126 /// Create a new `drm::Device` for a `drm::Driver`. 127 pub fn new(dev: &device::Device, data: impl PinInit<T::Data, Error>) -> Result<ARef<Self>> { 128 // `__drm_dev_alloc` uses `kmalloc()` to allocate memory, hence ensure a `kmalloc()` 129 // compatible `Layout`. 130 let layout = Kmalloc::aligned_layout(Layout::new::<Self>()); 131 132 // Use a temporary vtable without a `release` callback until `data` is initialized, so 133 // init failure can release the DRM device without dropping uninitialized fields. 134 let alloc_vtable = bindings::drm_driver { 135 release: None, 136 ..Self::VTABLE 137 }; 138 139 // SAFETY: 140 // - `alloc_vtable` reference remains valid until no longer used, 141 // - `dev` is valid by its type invarants, 142 let raw_drm: *mut Self = unsafe { 143 bindings::__drm_dev_alloc( 144 dev.as_raw(), 145 &alloc_vtable, 146 layout.size(), 147 mem::offset_of!(Self, dev), 148 ) 149 } 150 .cast(); 151 let raw_drm = NonNull::new(from_err_ptr(raw_drm)?).ok_or(ENOMEM)?; 152 153 // SAFETY: `raw_drm` is a valid pointer to `Self`, given that `__drm_dev_alloc` was 154 // successful. 155 let drm_dev = unsafe { Self::into_drm_device(raw_drm) }; 156 157 // SAFETY: `raw_drm` is a valid pointer to `Self`. 158 let raw_data = unsafe { ptr::addr_of_mut!((*raw_drm.as_ptr()).data) }; 159 160 // SAFETY: 161 // - `raw_data` is a valid pointer to uninitialized memory. 162 // - `raw_data` will not move until it is dropped. 163 unsafe { data.__pinned_init(raw_data) }.inspect_err(|_| { 164 // SAFETY: `__drm_dev_alloc()` was successful, hence `drm_dev` must be valid and the 165 // refcount must be non-zero. 166 unsafe { bindings::drm_dev_put(drm_dev) }; 167 })?; 168 169 // SAFETY: `drm_dev` is still private to this function. 170 unsafe { (*drm_dev).driver = const { &Self::VTABLE } }; 171 172 // SAFETY: The reference count is one, and now we take ownership of that reference as a 173 // `drm::Device`. 174 Ok(unsafe { ARef::from_raw(raw_drm) }) 175 } 176 177 pub(crate) fn as_raw(&self) -> *mut bindings::drm_device { 178 self.dev.get() 179 } 180 181 /// # Safety 182 /// 183 /// `ptr` must be a valid pointer to a `struct device` embedded in `Self`. 184 unsafe fn from_drm_device(ptr: *const bindings::drm_device) -> *mut Self { 185 // SAFETY: By the safety requirements of this function `ptr` is a valid pointer to a 186 // `struct drm_device` embedded in `Self`. 187 unsafe { crate::container_of!(Opaque::cast_from(ptr), Self, dev) }.cast_mut() 188 } 189 190 /// # Safety 191 /// 192 /// `ptr` must be a valid pointer to `Self`. 193 unsafe fn into_drm_device(ptr: NonNull<Self>) -> *mut bindings::drm_device { 194 // SAFETY: By the safety requirements of this function, `ptr` is a valid pointer to `Self`. 195 unsafe { &raw mut (*ptr.as_ptr()).dev }.cast() 196 } 197 198 /// Not intended to be called externally, except via declare_drm_ioctls!() 199 /// 200 /// # Safety 201 /// 202 /// Callers must ensure that `ptr` is valid, non-null, and has a non-zero reference count, 203 /// i.e. it must be ensured that the reference count of the C `struct drm_device` `ptr` points 204 /// to can't drop to zero, for the duration of this function call and the entire duration when 205 /// the returned reference exists. 206 /// 207 /// Additionally, callers must ensure that the `struct device`, `ptr` is pointing to, is 208 /// embedded in `Self`. 209 #[doc(hidden)] 210 pub unsafe fn from_raw<'a>(ptr: *const bindings::drm_device) -> &'a Self { 211 // SAFETY: By the safety requirements of this function `ptr` is a valid pointer to a 212 // `struct drm_device` embedded in `Self`. 213 let ptr = unsafe { Self::from_drm_device(ptr) }; 214 215 // SAFETY: `ptr` is valid by the safety requirements of this function. 216 unsafe { &*ptr.cast() } 217 } 218 219 extern "C" fn release(ptr: *mut bindings::drm_device) { 220 // SAFETY: `ptr` is a valid pointer to a `struct drm_device` and embedded in `Self`. 221 let this = unsafe { Self::from_drm_device(ptr) }; 222 223 // SAFETY: 224 // - When `release` runs it is guaranteed that there is no further access to `this`. 225 // - `this` is valid for dropping. 226 unsafe { core::ptr::drop_in_place(this) }; 227 } 228 } 229 230 impl<T: drm::Driver> Deref for Device<T> { 231 type Target = T::Data; 232 233 fn deref(&self) -> &Self::Target { 234 &self.data 235 } 236 } 237 238 // SAFETY: DRM device objects are always reference counted and the get/put functions 239 // satisfy the requirements. 240 unsafe impl<T: drm::Driver> AlwaysRefCounted for Device<T> { 241 fn inc_ref(&self) { 242 // SAFETY: The existence of a shared reference guarantees that the refcount is non-zero. 243 unsafe { bindings::drm_dev_get(self.as_raw()) }; 244 } 245 246 unsafe fn dec_ref(obj: NonNull<Self>) { 247 // SAFETY: `obj` is a valid pointer to `Self`. 248 let drm_dev = unsafe { Self::into_drm_device(obj) }; 249 250 // SAFETY: The safety requirements guarantee that the refcount is non-zero. 251 unsafe { bindings::drm_dev_put(drm_dev) }; 252 } 253 } 254 255 impl<T: drm::Driver> AsRef<device::Device> for Device<T> { 256 fn as_ref(&self) -> &device::Device { 257 // SAFETY: `bindings::drm_device::dev` is valid as long as the DRM device itself is valid, 258 // which is guaranteed by the type invariant. 259 unsafe { device::Device::from_raw((*self.as_raw()).dev) } 260 } 261 } 262 263 // SAFETY: A `drm::Device` can be released from any thread. 264 unsafe impl<T: drm::Driver> Send for Device<T> {} 265 266 // SAFETY: A `drm::Device` can be shared among threads because all immutable methods are protected 267 // by the synchronization in `struct drm_device`. 268 unsafe impl<T: drm::Driver> Sync for Device<T> {} 269 270 impl<T, const ID: u64> WorkItem<ID> for Device<T> 271 where 272 T: drm::Driver, 273 T::Data: WorkItem<ID, Pointer = ARef<Device<T>>>, 274 T::Data: HasWork<Device<T>, ID>, 275 { 276 type Pointer = ARef<Device<T>>; 277 278 fn run(ptr: ARef<Device<T>>) { 279 T::Data::run(ptr); 280 } 281 } 282 283 // SAFETY: 284 // 285 // - `raw_get_work` and `work_container_of` return valid pointers by relying on 286 // `T::Data::raw_get_work` and `container_of`. In particular, `T::Data` is 287 // stored inline in `drm::Device`, so the `container_of` call is valid. 288 // 289 // - The two methods are true inverses of each other: given `ptr: *mut 290 // Device<T>`, `raw_get_work` will return a `*mut Work<Device<T>, ID>` through 291 // `T::Data::raw_get_work` and given a `ptr: *mut Work<Device<T>, ID>`, 292 // `work_container_of` will return a `*mut Device<T>` through `container_of`. 293 unsafe impl<T, const ID: u64> HasWork<Device<T>, ID> for Device<T> 294 where 295 T: drm::Driver, 296 T::Data: HasWork<Device<T>, ID>, 297 { 298 unsafe fn raw_get_work(ptr: *mut Self) -> *mut Work<Device<T>, ID> { 299 // SAFETY: The caller promises that `ptr` points to a valid `Device<T>`. 300 let data_ptr = unsafe { &raw mut (*ptr).data }; 301 302 // SAFETY: `data_ptr` is a valid pointer to `T::Data`. 303 unsafe { T::Data::raw_get_work(data_ptr) } 304 } 305 306 unsafe fn work_container_of(ptr: *mut Work<Device<T>, ID>) -> *mut Self { 307 // SAFETY: The caller promises that `ptr` points at a `Work` field in 308 // `T::Data`. 309 let data_ptr = unsafe { T::Data::work_container_of(ptr) }; 310 311 // SAFETY: `T::Data` is stored as the `data` field in `Device<T>`. 312 unsafe { crate::container_of!(data_ptr, Self, data) } 313 } 314 } 315 316 // SAFETY: Our `HasWork<T, ID>` implementation returns a `work_struct` that is 317 // stored in the `work` field of a `delayed_work` with the same access rules as 318 // the `work_struct` owing to the bound on `T::Data: HasDelayedWork<Device<T>, 319 // ID>`, which requires that `T::Data::raw_get_work` return a `work_struct` that 320 // is inside a `delayed_work`. 321 unsafe impl<T, const ID: u64> HasDelayedWork<Device<T>, ID> for Device<T> 322 where 323 T: drm::Driver, 324 T::Data: HasDelayedWork<Device<T>, ID>, 325 { 326 } 327