summaryrefslogtreecommitdiff
path: root/rust/kernel/drm
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2026-10-13 17:59:46 +1000
committerDave Airlie <airlied@redhat.com>2026-10-13 18:01:37 +1000
commita56b45995b1e6b9ee671485b1fe68b0c7f754a67 (patch)
treea6f83d97cf7acca6eed91b794435e1966b827ab6 /rust/kernel/drm
parent22739ca2a80c9c2bbeace4075249efdc950d3ac1 (diff)
parentd511064b2e732b7152a542d589d07a4814c1b674 (diff)
Merge tag 'drm-rust-next-2026-10-11' of https://gitlab.freedesktop.org/drm/rust/kernel into drm-next
DRM Rust changes for v7.4-rc1 - Cross-subsystem: - I/O (shared from driver-core tree via signed tag rust-io-7.4-rc1): - Reimplement register!() as a procedural macro, require matching base types for register access, and replace relative registers with typed I/O projections. Convert Nova, Tyr and the PCI sample - Add AsRepr/AsReprMut conversions for I/O on compatible wrapper types and transmute helpers with deferred size checks - DMA (shared from driver-core tree via signed tag rust-dma-7.4-rc1): - Tie Coherent, CoherentBox and CoherentHandle to the device's bound lifetime, and allow scoped debugfs files backed by non-'static data - Allow auxiliary registration-data closures to return covariant sub-fields and add UserSliceWriter::write_truncated() - Implement Send and Sync for MapleTree - Add PCI resource_flags() and IORESOURCE_MEM_64, and convert PCI IRQ flags to impl_flags!() - Add I/O view cast() with compile-time size and alignment checks - DRM: - Add Rust dma_fence abstractions with separate producer (DriverFence) and consumer (Fence) types, per-context sequencing, signal callbacks and preallocation. Additional backend operations remain follow-up work. - Initialize DRM registrations and their data in place, removing a separate allocation - Drop the unused flags argument from drm::Registration::new() - Nova: - UAPI and Cross Module API: - Add NovaCoreApi and a lifetime-bound handle for auxiliary child drivers, carried in nova-drm registration data - Expose a render node and extensible INFO ioctl reporting GPU architecture, opaque chip ID, usable VRAM and VRAM BAR sizes, full and short GPU names, and GID, with size discovery and truncation to the userspace buffer size - Move BAR-size queries into GPU info, removing GETPARAM and changing the UAPI - PRAMIN access: - Add typed CPU access to VRAM through the movable 1 MiB BAR0 PRAMIN window, with per-architecture support from Turing through Blackwell - Add GpuMm centralized memory manager, VramAddress type, aperture documentation and optional probe-time self-tests under CONFIG_NOVA_CORE_SELFTESTS - GPU virtual memory and BAR1: - Add VRAM buddy allocation, TLB flushing, MMU v2/v3 page-table types with trait-based generics (PteOps, PdeOps, DualPdeOps, MmuConfig) and a generic walker - Add maple-tree virtual address tracking and multi-page mapping, separating allocation from mapping execution - Add CPU access to mapped VRAM through BAR1 and memory-management self-tests; handle 64-bit BAR0 when locating BAR1 - GPU interrupts and GSP events: - Add GIN (GPU Interrupt and Notification) interrupt-tree support with MSI-X, MSI fallback and per-architecture rearming - Drain GSP events between commands via a threaded SWGEN0 handler - Report OS errors, robust-channel notifications and unknown messages without aborting command waits; hold the queue lock and use one deadline per wait - Disable GSP event interrupts on persistent falcon faults or drain errors - Add a delivery/rearm self-test, interrupt-tree KUnit coverage and interrupt-controller documentation - GSP messaging fixes: - Queue setup RPCs before GSP-RM boot - Correct DMA barriers in both queue directions - Firmware and transport: - Extract a reusable radix3 buffer mapper; zero-pad page-table levels to whole pages to prevent booter reads of stale padding - Correct GSP-FMC naming and boot-flow documentation - Set MCTP header version 1 for FSP messages and retain the command queue's BAR0 reference - Resource handling: - Replace unnecessary BarUser reference counting with in-place ownership and borrowed access; consolidate probe initialization - Declare an unlimited DMA maximum segment size - Tyr: - Use bitfield!() for firmware section flags and memory attributes that do not describe registers - Zero unsupported and newly added GPU-info fields, and limit the doorbell array to 17 entries to fit the mapped register region Signed-off-by: Dave Airlie <airlied@redhat.com> From: "Danilo Krummrich" <dakr@kernel.org> Link: https://patch.msgid.link/DM371PN4TBJT.3LY1B0EYWSI4@kernel.org
Diffstat (limited to 'rust/kernel/drm')
-rw-r--r--rust/kernel/drm/driver.rs77
1 files changed, 44 insertions, 33 deletions
diff --git a/rust/kernel/drm/driver.rs b/rust/kernel/drm/driver.rs
index 74f6ed690d8b..f6db91e81e79 100644
--- a/rust/kernel/drm/driver.rs
+++ b/rust/kernel/drm/driver.rs
@@ -12,7 +12,10 @@ use crate::{
prelude::*,
sync::aref::ARef, //
};
-use core::ptr::NonNull;
+use core::{
+ marker::PhantomPinned,
+ ptr::NonNull, //
+};
/// Driver use the GEM memory manager. This should be set for all modern drivers.
pub(crate) const FEAT_GEM: u32 = bindings::drm_driver_feature_DRIVER_GEM;
@@ -143,9 +146,15 @@ pub trait Driver {
/// The registration type of a `drm::Device`.
///
/// Once the `Registration` structure is dropped, the device is unregistered.
+#[pin_data(PinnedDrop)]
pub struct Registration<'a, T: Driver> {
drm: ARef<drm::Device<T>>,
- _reg_data: Pin<KBox<T::RegistrationData<'a>>>,
+ #[pin]
+ data: T::RegistrationData<'a>,
+ /// Even if `T::RegistrationData` is `Unpin`, the registration must not be moved because a
+ /// pointer to `data` is stored in the DRM device.
+ #[pin]
+ _pin: PhantomPinned,
}
impl<'a, T: Driver> Registration<'a, T> {
@@ -159,39 +168,40 @@ impl<'a, T: Driver> Registration<'a, T> {
pub unsafe fn new<E>(
dev: &'a device::Device<device::Bound>,
drm: drm::UnregisteredDevice<T>,
- reg_data: impl PinInit<T::RegistrationData<'a>, E>,
- flags: usize,
- ) -> Result<Self>
+ data: impl PinInit<T::RegistrationData<'a>, E>,
+ ) -> impl PinInit<Self, Error>
where
Error: From<E>,
{
- let parent = drm.as_ref();
- if parent.as_ref().as_raw() != dev.as_raw() {
- return Err(EINVAL);
- }
-
- let reg_data: Pin<KBox<T::RegistrationData<'a>>> = KBox::pin_init(reg_data, GFP_KERNEL)?;
-
- // Store the registration data pointer in the device before registration, so that it is
- // visible once ioctls can be called.
- let ptr: NonNull<T::RegistrationData<'static>> =
- NonNull::from(Pin::get_ref(reg_data.as_ref())).cast();
-
- // SAFETY: No concurrent access; the device is not yet registered.
- unsafe { *drm.registration_data.get() = ptr };
-
- // SAFETY: `drm` is a valid, initialized but not yet registered DRM device.
- let ret = unsafe { bindings::drm_dev_register(drm.as_raw(), flags) };
- if let Err(e) = to_result(ret) {
- // SAFETY: `drm_dev_register()` synchronizes SRCU on failure, so no concurrent
- // access to `registration_data` is possible at this point.
- unsafe { *drm.registration_data.get() = NonNull::dangling() };
- return Err(e);
- }
-
- Ok(Self {
+ try_pin_init!(Self {
+ _: {
+ let parent = drm.as_ref();
+ if parent.as_ref().as_raw() != dev.as_raw() {
+ return Err(EINVAL);
+ }
+ },
+
+ data <- data,
drm: (&*drm).into(),
- _reg_data: reg_data,
+ _pin: PhantomPinned,
+
+ _: {
+ // Store the registration data pointer in the device before registration, so
+ // that it is visible once ioctls can be called.
+ let ptr: NonNull<T::RegistrationData<'static>> =
+ NonNull::from(data.as_ref().get_ref()).cast();
+
+ // SAFETY: No concurrent access; the device is not yet registered.
+ unsafe { *drm.registration_data.get() = ptr };
+
+ // SAFETY: `drm` is a valid, initialized but not yet registered DRM device.
+ let ret = unsafe { bindings::drm_dev_register(drm.as_raw(), 0) };
+ to_result(ret).inspect_err(|_| {
+ // SAFETY: `drm_dev_register()` synchronizes SRCU on failure, so no
+ // concurrent access to `registration_data` is possible at this point.
+ unsafe { *drm.registration_data.get() = NonNull::dangling() };
+ })?;
+ },
})
}
@@ -208,8 +218,9 @@ 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) {
+#[pinned_drop]
+impl<T: Driver> PinnedDrop for Registration<'_, T> {
+ fn drop(self: Pin<&mut Self>) {
// Use `drm_dev_unplug` rather than `drm_dev_unregister` to ensure that existing
// `drm_dev_enter()` critical sections complete before unregistration proceeds. This
// is required for the safety of `RegistrationGuard`, which relies on the SRCU barrier in