mirror of
https://github.com/torvalds/linux.git
synced 2026-06-02 19:43:40 +02:00
rust: drm: add DRM driver registration
Implement the DRM driver `Registration`. The `Registration` structure is responsible to register and unregister a DRM driver. It makes use of the `Devres` container in order to allow the `Registration` to be owned by devres, such that it is automatically dropped (and the DRM driver unregistered) once the parent device is unbound. Signed-off-by: Asahi Lina <lina@asahilina.net> Reviewed-by: Alyssa Rosenzweig <alyssa@rosenzweig.io> Reviewed-by: Lyude Paul <lyude@redhat.com> Link: https://lore.kernel.org/r/20250410235546.43736-6-dakr@kernel.org [ Rework of drm::Registration * move VTABLE to drm::Device to prevent use-after-free bugs; VTABLE needs to be bound to the lifetime of drm::Device, not the drm::Registration * combine new() and register() to get rid of the registered boolean * remove file_operations * move struct drm_device creation to drm::Device * introduce Devres * original source archive: https://archive.is/Pl9ys - Danilo ] Signed-off-by: Danilo Krummrich <dakr@kernel.org>
This commit is contained in:
parent
1e4b8896c0
commit
0600032c54
|
|
@ -4,7 +4,15 @@
|
||||||
//!
|
//!
|
||||||
//! C header: [`include/linux/drm/drm_drv.h`](srctree/include/linux/drm/drm_drv.h)
|
//! C header: [`include/linux/drm/drm_drv.h`](srctree/include/linux/drm/drm_drv.h)
|
||||||
|
|
||||||
use crate::{bindings, drm, str::CStr};
|
use crate::{
|
||||||
|
bindings, device,
|
||||||
|
devres::Devres,
|
||||||
|
drm,
|
||||||
|
error::{to_result, Result},
|
||||||
|
prelude::*,
|
||||||
|
str::CStr,
|
||||||
|
types::ARef,
|
||||||
|
};
|
||||||
use macros::vtable;
|
use macros::vtable;
|
||||||
|
|
||||||
/// Driver use the GEM memory manager. This should be set for all modern drivers.
|
/// Driver use the GEM memory manager. This should be set for all modern drivers.
|
||||||
|
|
@ -103,3 +111,53 @@ pub trait Driver {
|
||||||
/// IOCTL list. See `kernel::drm::ioctl::declare_drm_ioctls!{}`.
|
/// IOCTL list. See `kernel::drm::ioctl::declare_drm_ioctls!{}`.
|
||||||
const IOCTLS: &'static [drm::ioctl::DrmIoctlDescriptor];
|
const IOCTLS: &'static [drm::ioctl::DrmIoctlDescriptor];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The registration type of a `drm::Device`.
|
||||||
|
///
|
||||||
|
/// Once the `Registration` structure is dropped, the device is unregistered.
|
||||||
|
pub struct Registration<T: Driver>(ARef<drm::Device<T>>);
|
||||||
|
|
||||||
|
impl<T: Driver> Registration<T> {
|
||||||
|
/// Creates a new [`Registration`] and registers it.
|
||||||
|
fn new(drm: &drm::Device<T>, flags: usize) -> Result<Self> {
|
||||||
|
// SAFETY: `drm.as_raw()` is valid by the invariants of `drm::Device`.
|
||||||
|
to_result(unsafe { bindings::drm_dev_register(drm.as_raw(), flags) })?;
|
||||||
|
|
||||||
|
Ok(Self(drm.into()))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Same as [`Registration::new`}, but transfers ownership of the [`Registration`] to
|
||||||
|
/// [`Devres`].
|
||||||
|
pub fn new_foreign_owned(
|
||||||
|
drm: &drm::Device<T>,
|
||||||
|
dev: &device::Device<device::Bound>,
|
||||||
|
flags: usize,
|
||||||
|
) -> Result {
|
||||||
|
if drm.as_ref().as_raw() != dev.as_raw() {
|
||||||
|
return Err(EINVAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
let reg = Registration::<T>::new(drm, flags)?;
|
||||||
|
Devres::new_foreign_owned(dev, reg, GFP_KERNEL)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a reference to the `Device` instance for this registration.
|
||||||
|
pub fn device(&self) -> &drm::Device<T> {
|
||||||
|
&self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SAFETY: `Registration` doesn't offer any methods or access to fields when shared between
|
||||||
|
// threads, hence it's safe to share it.
|
||||||
|
unsafe impl<T: Driver> Sync for Registration<T> {}
|
||||||
|
|
||||||
|
// SAFETY: Registration with and unregistration from the DRM subsystem can happen from any thread.
|
||||||
|
unsafe impl<T: Driver> Send for Registration<T> {}
|
||||||
|
|
||||||
|
impl<T: Driver> Drop for Registration<T> {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
// SAFETY: Safe by the invariant of `ARef<drm::Device<T>>`. The existence of this
|
||||||
|
// `Registration` also guarantees the this `drm::Device` is actually registered.
|
||||||
|
unsafe { bindings::drm_dev_unregister(self.0.as_raw()) };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@
|
||||||
pub use self::device::Device;
|
pub use self::device::Device;
|
||||||
pub use self::driver::Driver;
|
pub use self::driver::Driver;
|
||||||
pub use self::driver::DriverInfo;
|
pub use self::driver::DriverInfo;
|
||||||
|
pub use self::driver::Registration;
|
||||||
|
|
||||||
pub(crate) mod private {
|
pub(crate) mod private {
|
||||||
pub trait Sealed {}
|
pub trait Sealed {}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user