xref: /linux/rust/kernel/drm/driver.rs (revision 638eeda8abaa3e6afe6bd5758ef8045a7f33b9a0)
107c90160SAsahi Lina // SPDX-License-Identifier: GPL-2.0 OR MIT
207c90160SAsahi Lina 
307c90160SAsahi Lina //! DRM driver core.
407c90160SAsahi Lina //!
5c2783c7cSMiguel Ojeda //! C header: [`include/drm/drm_drv.h`](srctree/include/drm/drm_drv.h)
607c90160SAsahi Lina 
70600032cSAsahi Lina use crate::{
846ae8fd7SDanilo Krummrich     bindings, device, devres, drm,
90600032cSAsahi Lina     error::{to_result, Result},
100600032cSAsahi Lina     prelude::*,
11f1f2a22bSShankari Anand     sync::aref::ARef,
120600032cSAsahi Lina };
1307c90160SAsahi Lina use macros::vtable;
1407c90160SAsahi Lina 
1507c90160SAsahi Lina /// Driver use the GEM memory manager. This should be set for all modern drivers.
1607c90160SAsahi Lina pub(crate) const FEAT_GEM: u32 = bindings::drm_driver_feature_DRIVER_GEM;
1707c90160SAsahi Lina 
1807c90160SAsahi Lina /// Information data for a DRM Driver.
1907c90160SAsahi Lina pub struct DriverInfo {
2007c90160SAsahi Lina     /// Driver major version.
2107c90160SAsahi Lina     pub major: i32,
2207c90160SAsahi Lina     /// Driver minor version.
2307c90160SAsahi Lina     pub minor: i32,
2407c90160SAsahi Lina     /// Driver patchlevel version.
2507c90160SAsahi Lina     pub patchlevel: i32,
2607c90160SAsahi Lina     /// Driver name.
2707c90160SAsahi Lina     pub name: &'static CStr,
2807c90160SAsahi Lina     /// Driver description.
2907c90160SAsahi Lina     pub desc: &'static CStr,
3007c90160SAsahi Lina }
3107c90160SAsahi Lina 
3207c90160SAsahi Lina /// Internal memory management operation set, normally created by memory managers (e.g. GEM).
3307c90160SAsahi Lina pub struct AllocOps {
3407c90160SAsahi Lina     pub(crate) gem_create_object: Option<
3507c90160SAsahi Lina         unsafe extern "C" fn(
3607c90160SAsahi Lina             dev: *mut bindings::drm_device,
3707c90160SAsahi Lina             size: usize,
3807c90160SAsahi Lina         ) -> *mut bindings::drm_gem_object,
3907c90160SAsahi Lina     >,
4007c90160SAsahi Lina     pub(crate) prime_handle_to_fd: Option<
4107c90160SAsahi Lina         unsafe extern "C" fn(
4207c90160SAsahi Lina             dev: *mut bindings::drm_device,
4307c90160SAsahi Lina             file_priv: *mut bindings::drm_file,
4407c90160SAsahi Lina             handle: u32,
4507c90160SAsahi Lina             flags: u32,
4607c90160SAsahi Lina             prime_fd: *mut core::ffi::c_int,
4707c90160SAsahi Lina         ) -> core::ffi::c_int,
4807c90160SAsahi Lina     >,
4907c90160SAsahi Lina     pub(crate) prime_fd_to_handle: Option<
5007c90160SAsahi Lina         unsafe extern "C" fn(
5107c90160SAsahi Lina             dev: *mut bindings::drm_device,
5207c90160SAsahi Lina             file_priv: *mut bindings::drm_file,
5307c90160SAsahi Lina             prime_fd: core::ffi::c_int,
5407c90160SAsahi Lina             handle: *mut u32,
5507c90160SAsahi Lina         ) -> core::ffi::c_int,
5607c90160SAsahi Lina     >,
5707c90160SAsahi Lina     pub(crate) gem_prime_import: Option<
5807c90160SAsahi Lina         unsafe extern "C" fn(
5907c90160SAsahi Lina             dev: *mut bindings::drm_device,
6007c90160SAsahi Lina             dma_buf: *mut bindings::dma_buf,
6107c90160SAsahi Lina         ) -> *mut bindings::drm_gem_object,
6207c90160SAsahi Lina     >,
6307c90160SAsahi Lina     pub(crate) gem_prime_import_sg_table: Option<
6407c90160SAsahi Lina         unsafe extern "C" fn(
6507c90160SAsahi Lina             dev: *mut bindings::drm_device,
6607c90160SAsahi Lina             attach: *mut bindings::dma_buf_attachment,
6707c90160SAsahi Lina             sgt: *mut bindings::sg_table,
6807c90160SAsahi Lina         ) -> *mut bindings::drm_gem_object,
6907c90160SAsahi Lina     >,
7007c90160SAsahi Lina     pub(crate) dumb_create: Option<
7107c90160SAsahi Lina         unsafe extern "C" fn(
7207c90160SAsahi Lina             file_priv: *mut bindings::drm_file,
7307c90160SAsahi Lina             dev: *mut bindings::drm_device,
7407c90160SAsahi Lina             args: *mut bindings::drm_mode_create_dumb,
7507c90160SAsahi Lina         ) -> core::ffi::c_int,
7607c90160SAsahi Lina     >,
7707c90160SAsahi Lina     pub(crate) dumb_map_offset: Option<
7807c90160SAsahi Lina         unsafe extern "C" fn(
7907c90160SAsahi Lina             file_priv: *mut bindings::drm_file,
8007c90160SAsahi Lina             dev: *mut bindings::drm_device,
8107c90160SAsahi Lina             handle: u32,
8207c90160SAsahi Lina             offset: *mut u64,
8307c90160SAsahi Lina         ) -> core::ffi::c_int,
8407c90160SAsahi Lina     >,
8507c90160SAsahi Lina }
8607c90160SAsahi Lina 
8707c90160SAsahi Lina /// Trait for memory manager implementations. Implemented internally.
88c284d3e4SAsahi Lina pub trait AllocImpl: super::private::Sealed + drm::gem::IntoGEMObject {
896ea42e91SLyude Paul     /// The [`Driver`] implementation for this [`AllocImpl`].
906ea42e91SLyude Paul     type Driver: drm::Driver;
916ea42e91SLyude Paul 
9207c90160SAsahi Lina     /// The C callback operations for this memory manager.
9307c90160SAsahi Lina     const ALLOC_OPS: AllocOps;
9407c90160SAsahi Lina }
9507c90160SAsahi Lina 
9607c90160SAsahi Lina /// The DRM `Driver` trait.
9707c90160SAsahi Lina ///
9807c90160SAsahi Lina /// This trait must be implemented by drivers in order to create a `struct drm_device` and `struct
9907c90160SAsahi Lina /// drm_driver` to be registered in the DRM subsystem.
10007c90160SAsahi Lina #[vtable]
10107c90160SAsahi Lina pub trait Driver {
10207c90160SAsahi Lina     /// Context data associated with the DRM driver
10307c90160SAsahi Lina     type Data: Sync + Send;
10407c90160SAsahi Lina 
10507c90160SAsahi Lina     /// The type used to manage memory for this driver.
10607c90160SAsahi Lina     type Object: AllocImpl;
10707c90160SAsahi Lina 
108a98a73beSAsahi Lina     /// The type used to represent a DRM File (client)
109a98a73beSAsahi Lina     type File: drm::file::DriverFile;
110a98a73beSAsahi Lina 
11107c90160SAsahi Lina     /// Driver metadata
11207c90160SAsahi Lina     const INFO: DriverInfo;
11307c90160SAsahi Lina 
11407c90160SAsahi Lina     /// IOCTL list. See `kernel::drm::ioctl::declare_drm_ioctls!{}`.
11507c90160SAsahi Lina     const IOCTLS: &'static [drm::ioctl::DrmIoctlDescriptor];
11607c90160SAsahi Lina }
1170600032cSAsahi Lina 
1180600032cSAsahi Lina /// The registration type of a `drm::Device`.
1190600032cSAsahi Lina ///
1200600032cSAsahi Lina /// Once the `Registration` structure is dropped, the device is unregistered.
1210600032cSAsahi Lina pub struct Registration<T: Driver>(ARef<drm::Device<T>>);
1220600032cSAsahi Lina 
1230600032cSAsahi Lina impl<T: Driver> Registration<T> {
1240600032cSAsahi Lina     fn new(drm: &drm::Device<T>, flags: usize) -> Result<Self> {
1250600032cSAsahi Lina         // SAFETY: `drm.as_raw()` is valid by the invariants of `drm::Device`.
1260600032cSAsahi Lina         to_result(unsafe { bindings::drm_dev_register(drm.as_raw(), flags) })?;
1270600032cSAsahi Lina 
1280600032cSAsahi Lina         Ok(Self(drm.into()))
1290600032cSAsahi Lina     }
1300600032cSAsahi Lina 
131*638eeda8SLyude Paul     /// Registers a new [`Device`](drm::Device) with userspace.
132*638eeda8SLyude Paul     ///
133*638eeda8SLyude Paul     /// Ownership of the [`Registration`] object is passed to [`devres::register`].
1340600032cSAsahi Lina     pub fn new_foreign_owned(
1350600032cSAsahi Lina         drm: &drm::Device<T>,
1360600032cSAsahi Lina         dev: &device::Device<device::Bound>,
1370600032cSAsahi Lina         flags: usize,
13846ae8fd7SDanilo Krummrich     ) -> Result
13946ae8fd7SDanilo Krummrich     where
14046ae8fd7SDanilo Krummrich         T: 'static,
14146ae8fd7SDanilo Krummrich     {
1420600032cSAsahi Lina         if drm.as_ref().as_raw() != dev.as_raw() {
1430600032cSAsahi Lina             return Err(EINVAL);
1440600032cSAsahi Lina         }
1450600032cSAsahi Lina 
1460600032cSAsahi Lina         let reg = Registration::<T>::new(drm, flags)?;
14746ae8fd7SDanilo Krummrich 
14846ae8fd7SDanilo Krummrich         devres::register(dev, reg, GFP_KERNEL)
1490600032cSAsahi Lina     }
1500600032cSAsahi Lina 
1510600032cSAsahi Lina     /// Returns a reference to the `Device` instance for this registration.
1520600032cSAsahi Lina     pub fn device(&self) -> &drm::Device<T> {
1530600032cSAsahi Lina         &self.0
1540600032cSAsahi Lina     }
1550600032cSAsahi Lina }
1560600032cSAsahi Lina 
1570600032cSAsahi Lina // SAFETY: `Registration` doesn't offer any methods or access to fields when shared between
1580600032cSAsahi Lina // threads, hence it's safe to share it.
1590600032cSAsahi Lina unsafe impl<T: Driver> Sync for Registration<T> {}
1600600032cSAsahi Lina 
1610600032cSAsahi Lina // SAFETY: Registration with and unregistration from the DRM subsystem can happen from any thread.
1620600032cSAsahi Lina unsafe impl<T: Driver> Send for Registration<T> {}
1630600032cSAsahi Lina 
1640600032cSAsahi Lina impl<T: Driver> Drop for Registration<T> {
1650600032cSAsahi Lina     fn drop(&mut self) {
1660600032cSAsahi Lina         // SAFETY: Safe by the invariant of `ARef<drm::Device<T>>`. The existence of this
1670600032cSAsahi Lina         // `Registration` also guarantees the this `drm::Device` is actually registered.
1680600032cSAsahi Lina         unsafe { bindings::drm_dev_unregister(self.0.as_raw()) };
1690600032cSAsahi Lina     }
1700600032cSAsahi Lina }
171