diff options
| author | Dave Airlie <airlied@redhat.com> | 2026-04-01 07:20:59 +1000 |
|---|---|---|
| committer | Dave Airlie <airlied@redhat.com> | 2026-04-01 07:32:05 +1000 |
| commit | 9bdbf7eb25b3121ef19533df4fb70f2c39fc0d6a (patch) | |
| tree | 488e7fbc6301e76c49d975d98ae5b3bfff2ff200 | |
| parent | 28899037b85e77490f202fa9361c3c2780be3ec2 (diff) | |
| parent | 7c50d748b4a635bc39802ea3f6b120e66b1b9067 (diff) | |
Merge tag 'drm-rust-next-2026-03-30' of https://gitlab.freedesktop.org/drm/rust/kernel into drm-next
DRM Rust changes for v7.1-rc1
- DMA:
- Rework the DMA coherent API: introduce Coherent<T> as a generalized
container for arbitrary types, replacing the slice-only
CoherentAllocation<T>. Add CoherentBox for memory initialization
before exposing a buffer to hardware (converting to Coherent when
ready), and CoherentHandle for allocations without kernel mapping.
- Add Coherent::init() / init_with_attrs() for one-shot initialization
via pin-init, and from-slice constructors for both Coherent and
CoherentBox
- Add uaccess write_dma() for copying from DMA buffers to userspace
and BinaryWriter support for Coherent<T>
- DRM:
- Add GPU buddy allocator abstraction
- Add DRM shmem GEM helper abstraction
- Allow drm::Device to dispatch work and delayed work items to driver
private data
- Add impl_aref_for_gem_obj!() macro to reduce GEM refcount
boilerplate, and introduce DriverObject::Args for constructor
context
- Add dma_resv_lock helper and raw_dma_resv() accessor on GEM objects
- Clean up imports across the DRM module
- I/O:
- Merged via a signed tag from the driver-core tree: register!() macro
and I/O infrastructure improvements (IoCapable refactor, RelaxedMmio
wrapper, IoLoc trait, generic accessors, write_reg /
LocatedRegister)
- Nova (Core):
- Fix and harden the GSP command queue: correct write pointer
advancing, empty slot handling, and ring buffer indexing; add mutex
locking and make Cmdq a pinned type; distinguish wait vs no-wait
commands
- Add support for large RPCs via continuation records, splitting
oversized commands across multiple queue slots
- Simplify GSP sequencer and message handling code: remove unused
trait and Display impls, derive Debug and Zeroable where applicable,
warn on unconsumed message data
- Refactor Falcon firmware handling: create DMA objects lazily, add
PIO upload support, and use the Generic Bootloader to boot FWSEC on
Turing
- Convert all register definitions (PMC, PBUS, PFB, GC6, FUSE, PDISP,
Falcon) to the kernel register!() macro; add bounded_enum macro to
define enums usable as register fields
- Migrate all DMA usage to the new Coherent, CoherentBox, and
CoherentHandle APIs
- Harden firmware parsing with checked arithmetic throughout FWSEC,
Booter, RISC-V parsing paths
- Add debugfs support for reading GSP-RM log buffers; replace
module_pci_driver!() with explicit module init to support
module-level debugfs setup
- Fix auxiliary device registration for multi-GPU systems
- Various cleanups: import style, firmware parsing refactoring,
framebuffer size logging
- Rust:
- Add interop::list module providing a C linked list interface
- Extend num::Bounded with shift operations, into_bool(), and const
get() to support register bitfield manipulation
- Enable the generic_arg_infer Rust feature and add EMSGSIZE error
code
- Tyr:
- Adopt vertical import style per kernel Rust guidelines
- Clarify driver/device type names and use DRM device type alias
consistently across the driver
- Fix GPU model/version decoding in GpuInfo
- Workqueue:
- Add ARef<T> support for work and delayed work
Signed-off-by: Dave Airlie <airlied@redhat.com>
From: "Danilo Krummrich" <dakr@kernel.org>
Link: https://patch.msgid.link/DHGH4BLT03BU.ZJH5U52WE8BY@kernel.org
74 files changed, 7125 insertions, 3058 deletions
diff --git a/Documentation/gpu/nova/core/todo.rst b/Documentation/gpu/nova/core/todo.rst index d1964eb645e2..d5130b2b08fb 100644 --- a/Documentation/gpu/nova/core/todo.rst +++ b/Documentation/gpu/nova/core/todo.rst @@ -51,82 +51,6 @@ There also have been considerations of ToPrimitive [2]. | Link: https://lore.kernel.org/all/cover.1750689857.git.y.j3ms.n@gmail.com/ [1] | Link: https://rust-for-linux.zulipchat.com/#narrow/channel/288089-General/topic/Implement.20.60FromPrimitive.60.20trait.20.2B.20derive.20macro.20for.20nova-core/with/541971854 [2] -Generic register abstraction [REGA] ------------------------------------ - -Work out how register constants and structures can be automatically generated -through generalized macros. - -Example: - -.. code-block:: rust - - register!(BOOT0, 0x0, u32, pci::Bar<SIZE>, Fields [ - MINOR_REVISION(3:0, RO), - MAJOR_REVISION(7:4, RO), - REVISION(7:0, RO), // Virtual register combining major and minor rev. - ]) - -This could expand to something like: - -.. code-block:: rust - - const BOOT0_OFFSET: usize = 0x00000000; - const BOOT0_MINOR_REVISION_SHIFT: u8 = 0; - const BOOT0_MINOR_REVISION_MASK: u32 = 0x0000000f; - const BOOT0_MAJOR_REVISION_SHIFT: u8 = 4; - const BOOT0_MAJOR_REVISION_MASK: u32 = 0x000000f0; - const BOOT0_REVISION_SHIFT: u8 = BOOT0_MINOR_REVISION_SHIFT; - const BOOT0_REVISION_MASK: u32 = BOOT0_MINOR_REVISION_MASK | BOOT0_MAJOR_REVISION_MASK; - - struct Boot0(u32); - - impl Boot0 { - #[inline] - fn read(bar: &RevocableGuard<'_, pci::Bar<SIZE>>) -> Self { - Self(bar.readl(BOOT0_OFFSET)) - } - - #[inline] - fn minor_revision(&self) -> u32 { - (self.0 & BOOT0_MINOR_REVISION_MASK) >> BOOT0_MINOR_REVISION_SHIFT - } - - #[inline] - fn major_revision(&self) -> u32 { - (self.0 & BOOT0_MAJOR_REVISION_MASK) >> BOOT0_MAJOR_REVISION_SHIFT - } - - #[inline] - fn revision(&self) -> u32 { - (self.0 & BOOT0_REVISION_MASK) >> BOOT0_REVISION_SHIFT - } - } - -Usage: - -.. code-block:: rust - - let bar = bar.try_access().ok_or(ENXIO)?; - - let boot0 = Boot0::read(&bar); - pr_info!("Revision: {}\n", boot0.revision()); - -A work-in-progress implementation currently resides in -`drivers/gpu/nova-core/regs/macros.rs` and is used in nova-core. It would be -nice to improve it (possibly using proc macros) and move it to the `kernel` -crate so it can be used by other components as well. - -Features desired before this happens: - -* Make I/O optional I/O (for field values that are not registers), -* Support other sizes than `u32`, -* Allow visibility control for registers and individual fields, -* Use Rust slice syntax to express fields ranges. - -| Complexity: Advanced -| Contact: Alexandre Courbot - Numerical operations [NUMM] --------------------------- diff --git a/MAINTAINERS b/MAINTAINERS index ae8a01f30ff4..608a5c69df4f 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -7534,6 +7534,7 @@ F: include/linux/*fence.h F: include/linux/dma-buf.h F: include/linux/dma-buf/ F: include/linux/dma-resv.h +F: rust/helpers/dma-resv.c K: \bdma_(?:buf|fence|resv)\b DMA GENERIC OFFLOAD ENGINE SUBSYSTEM @@ -8513,7 +8514,10 @@ T: git https://gitlab.freedesktop.org/drm/rust/kernel.git F: drivers/gpu/drm/nova/ F: drivers/gpu/drm/tyr/ F: drivers/gpu/nova-core/ +F: rust/helpers/gpu.c F: rust/kernel/drm/ +F: rust/kernel/gpu.rs +F: rust/kernel/gpu/ DRM DRIVERS FOR ALLWINNER A10 M: Chen-Yu Tsai <wens@kernel.org> @@ -8931,7 +8935,7 @@ F: include/drm/ttm/ GPU BUDDY ALLOCATOR M: Matthew Auld <matthew.auld@intel.com> M: Arun Pravin <arunpravin.paneerselvam@amd.com> -R: Christian Koenig <christian.koenig@amd.com> +R: Joel Fernandes <joelagnelf@nvidia.com> L: dri-devel@lists.freedesktop.org S: Maintained T: git https://gitlab.freedesktop.org/drm/misc/kernel.git @@ -8940,6 +8944,9 @@ F: drivers/gpu/drm/drm_buddy.c F: drivers/gpu/tests/gpu_buddy_test.c F: include/drm/drm_buddy.h F: include/linux/gpu_buddy.h +F: rust/helpers/gpu.c +F: rust/kernel/gpu.rs +F: rust/kernel/gpu/ DRM AUTOMATED TESTING M: Helen Koike <helen.fornazier@gmail.com> @@ -23208,6 +23215,15 @@ T: git https://github.com/Rust-for-Linux/linux.git alloc-next F: rust/kernel/alloc.rs F: rust/kernel/alloc/ +RUST [INTEROP] +M: Joel Fernandes <joelagnelf@nvidia.com> +M: Alexandre Courbot <acourbot@nvidia.com> +L: rust-for-linux@vger.kernel.org +S: Maintained +T: git https://github.com/Rust-for-Linux/linux.git interop-next +F: rust/kernel/interop.rs +F: rust/kernel/interop/ + RUST [NUM] M: Alexandre Courbot <acourbot@nvidia.com> R: Yury Norov <yury.norov@gmail.com> diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig index 5386248e75b6..8f5a8d3012e4 100644 --- a/drivers/gpu/drm/Kconfig +++ b/drivers/gpu/drm/Kconfig @@ -268,6 +268,13 @@ config DRM_GEM_SHMEM_HELPER help Choose this if you need the GEM shmem helper functions +config RUST_DRM_GEM_SHMEM_HELPER + bool + depends on DRM && MMU + select DRM_GEM_SHMEM_HELPER + help + Choose this if you need the GEM shmem helper functions In Rust + config DRM_SUBALLOC_HELPER tristate depends on DRM diff --git a/drivers/gpu/drm/nova/gem.rs b/drivers/gpu/drm/nova/gem.rs index 6ccfa5da5761..e073e174e257 100644 --- a/drivers/gpu/drm/nova/gem.rs +++ b/drivers/gpu/drm/nova/gem.rs @@ -19,8 +19,9 @@ pub(crate) struct NovaObject {} impl gem::DriverObject for NovaObject { type Driver = NovaDriver; + type Args = (); - fn new(_dev: &NovaDevice, _size: usize) -> impl PinInit<Self, Error> { + fn new(_dev: &NovaDevice, _size: usize, _args: Self::Args) -> impl PinInit<Self, Error> { try_pin_init!(NovaObject {}) } } @@ -33,7 +34,7 @@ impl NovaObject { } let aligned_size = page::page_align(size).ok_or(EINVAL)?; - gem::Object::new(dev, aligned_size) + gem::Object::new(dev, aligned_size, ()) } /// Look up a GEM object handle for a `File` and return an `ObjectRef` for it. diff --git a/drivers/gpu/drm/tyr/driver.rs b/drivers/gpu/drm/tyr/driver.rs index beeffe36b6cb..611434641580 100644 --- a/drivers/gpu/drm/tyr/driver.rs +++ b/drivers/gpu/drm/tyr/driver.rs @@ -1,44 +1,56 @@ // SPDX-License-Identifier: GPL-2.0 or MIT -use kernel::clk::Clk; -use kernel::clk::OptionalClk; -use kernel::device::Bound; -use kernel::device::Core; -use kernel::device::Device; -use kernel::devres::Devres; -use kernel::drm; -use kernel::drm::ioctl; -use kernel::io::poll; -use kernel::new_mutex; -use kernel::of; -use kernel::platform; -use kernel::prelude::*; -use kernel::regulator; -use kernel::regulator::Regulator; -use kernel::sizes::SZ_2M; -use kernel::sync::aref::ARef; -use kernel::sync::Arc; -use kernel::sync::Mutex; -use kernel::time; - -use crate::file::File; -use crate::gem::TyrObject; -use crate::gpu; -use crate::gpu::GpuInfo; -use crate::regs; +use kernel::{ + clk::{ + Clk, + OptionalClk, // + }, + device::{ + Bound, + Core, + Device, // + }, + devres::Devres, + drm, + drm::ioctl, + io::poll, + new_mutex, + of, + platform, + prelude::*, + regulator, + regulator::Regulator, + sizes::SZ_2M, + sync::{ + aref::ARef, + Arc, + Mutex, // + }, + time, // +}; + +use crate::{ + file::TyrDrmFileData, + gem::TyrObject, + gpu, + gpu::GpuInfo, + regs, // +}; pub(crate) type IoMem = kernel::io::mem::IoMem<SZ_2M>; +pub(crate) struct TyrDrmDriver; + /// Convenience type alias for the DRM device type for this driver. -pub(crate) type TyrDevice = drm::Device<TyrDriver>; +pub(crate) type TyrDrmDevice = drm::Device<TyrDrmDriver>; #[pin_data(PinnedDrop)] -pub(crate) struct TyrDriver { - _device: ARef<TyrDevice>, +pub(crate) struct TyrPlatformDriverData { + _device: ARef<TyrDrmDevice>, } #[pin_data(PinnedDrop)] -pub(crate) struct TyrData { +pub(crate) struct TyrDrmDeviceData { pub(crate) pdev: ARef<platform::Device>, #[pin] @@ -61,9 +73,9 @@ pub(crate) struct TyrData { // that it will be removed in a future patch. // // SAFETY: This will be removed in a future patch. -unsafe impl Send for TyrData {} +unsafe impl Send for TyrDrmDeviceData {} // SAFETY: This will be removed in a future patch. -unsafe impl Sync for TyrData {} +unsafe impl Sync for TyrDrmDeviceData {} fn issue_soft_reset(dev: &Device<Bound>, iomem: &Devres<IoMem>) -> Result { regs::GPU_CMD.write(dev, iomem, regs::GPU_CMD_SOFT_RESET)?; @@ -82,14 +94,14 @@ fn issue_soft_reset(dev: &Device<Bound>, iomem: &Devres<IoMem>) -> Result { kernel::of_device_table!( OF_TABLE, MODULE_OF_TABLE, - <TyrDriver as platform::Driver>::IdInfo, + <TyrPlatformDriverData as platform::Driver>::IdInfo, [ (of::DeviceId::new(c"rockchip,rk3588-mali"), ()), (of::DeviceId::new(c"arm,mali-valhall-csf"), ()) ] ); -impl platform::Driver for TyrDriver { +impl platform::Driver for TyrPlatformDriverData { type IdInfo = (); const OF_ID_TABLE: Option<of::IdTable<Self::IdInfo>> = Some(&OF_TABLE); @@ -119,7 +131,7 @@ impl platform::Driver for TyrDriver { let platform: ARef<platform::Device> = pdev.into(); - let data = try_pin_init!(TyrData { + let data = try_pin_init!(TyrDrmDeviceData { pdev: platform.clone(), clks <- new_mutex!(Clocks { core: core_clk, @@ -133,10 +145,10 @@ impl platform::Driver for TyrDriver { gpu_info, }); - let tdev: ARef<TyrDevice> = drm::Device::new(pdev.as_ref(), data)?; - drm::driver::Registration::new_foreign_owned(&tdev, pdev.as_ref(), 0)?; + let ddev: ARef<TyrDrmDevice> = drm::Device::new(pdev.as_ref(), data)?; + drm::driver::Registration::new_foreign_owned(&ddev, pdev.as_ref(), 0)?; - let driver = TyrDriver { _device: tdev }; + let driver = TyrPlatformDriverData { _device: ddev }; // We need this to be dev_info!() because dev_dbg!() does not work at // all in Rust for now, and we need to see whether probe succeeded. @@ -146,12 +158,12 @@ impl platform::Driver for TyrDriver { } #[pinned_drop] -impl PinnedDrop for TyrDriver { +impl PinnedDrop for TyrPlatformDriverData { fn drop(self: Pin<&mut Self>) {} } #[pinned_drop] -impl PinnedDrop for TyrData { +impl PinnedDrop for TyrDrmDeviceData { fn drop(self: Pin<&mut Self>) { // TODO: the type-state pattern for Clks will fix this. let clks = self.clks.lock(); @@ -172,15 +184,15 @@ const INFO: drm::DriverInfo = drm::DriverInfo { }; #[vtable] -impl drm::Driver for TyrDriver { - type Data = TyrData; - type File = File; +impl drm::Driver for TyrDrmDriver { + type Data = TyrDrmDeviceData; + type File = TyrDrmFileData; type Object = drm::gem::Object<TyrObject>; const INFO: drm::DriverInfo = INFO; kernel::declare_drm_ioctls! { - (PANTHOR_DEV_QUERY, drm_panthor_dev_query, ioctl::RENDER_ALLOW, File::dev_query), + (PANTHOR_DEV_QUERY, drm_panthor_dev_query, ioctl::RENDER_ALLOW, TyrDrmFileData::dev_query), } } diff --git a/drivers/gpu/drm/tyr/file.rs b/drivers/gpu/drm/tyr/file.rs index 0ef432947b73..31411da203c5 100644 --- a/drivers/gpu/drm/tyr/file.rs +++ b/drivers/gpu/drm/tyr/file.rs @@ -1,37 +1,41 @@ // SPDX-License-Identifier: GPL-2.0 or MIT -use kernel::drm; -use kernel::prelude::*; -use kernel::uaccess::UserSlice; -use kernel::uapi; - -use crate::driver::TyrDevice; -use crate::TyrDriver; +use kernel::{ + drm, + prelude::*, + uaccess::UserSlice, + uapi, // +}; + +use crate::driver::{ + TyrDrmDevice, + TyrDrmDriver, // +}; #[pin_data] -pub(crate) struct File {} +pub(crate) struct TyrDrmFileData {} /// Convenience type alias for our DRM `File` type -pub(crate) type DrmFile = drm::file::File<File>; +pub(crate) type TyrDrmFile = drm::file::File<TyrDrmFileData>; -impl drm::file::DriverFile for File { - type Driver = TyrDriver; +impl drm::file::DriverFile for TyrDrmFileData { + type Driver = TyrDrmDriver; fn open(_dev: &drm::Device<Self::Driver>) -> Result<Pin<KBox<Self>>> { KBox::try_pin_init(try_pin_init!(Self {}), GFP_KERNEL) } } -impl File { +impl TyrDrmFileData { pub(crate) fn dev_query( - tdev: &TyrDevice, + ddev: &TyrDrmDevice, devquery: &mut uapi::drm_panthor_dev_query, - _file: &DrmFile, + _file: &TyrDrmFile, ) -> Result<u32> { if devquery.pointer == 0 { match devquery.type_ { uapi::drm_panthor_dev_query_type_DRM_PANTHOR_DEV_QUERY_GPU_INFO => { - devquery.size = core::mem::size_of_val(&tdev.gpu_info) as u32; + devquery.size = core::mem::size_of_val(&ddev.gpu_info) as u32; Ok(0) } _ => Err(EINVAL), @@ -45,7 +49,7 @@ impl File { ) .writer(); - writer.write(&tdev.gpu_info)?; + writer.write(&ddev.gpu |
