Commit 9bdbf7eb authored by Dave Airlie's avatar Dave Airlie
Browse files

Merge tag 'drm-rust-next-2026-03-30' of...

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: default avatarDave Airlie <airlied@redhat.com>

From: "Danilo Krummrich" <dakr@kernel.org>
Link: https://patch.msgid.link/DHGH4BLT03BU.ZJH5U52WE8BY@kernel.org
parents 28899037 7c50d748
Loading
Loading
Loading
Loading
+0 −76
Original line number Diff line number Diff line
@@ -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]
---------------------------

+17 −1
Original line number Diff line number Diff line
@@ -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>
+7 −0
Original line number Diff line number Diff line
@@ -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
+3 −2
Original line number Diff line number Diff line
@@ -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 @@ pub(crate) fn new(dev: &NovaDevice, size: usize) -> Result<ARef<gem::Object<Self
        }
        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.
+56 −44
Original line number Diff line number Diff line
// 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 @@ fn probe(

        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 @@ fn probe(
                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 @@ fn probe(
}

#[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 @@ fn drop(self: Pin<&mut Self>) {
};

#[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),
    }
}

Loading