diff options
| author | Zhi Wang <zhiw@nvidia.com> | 2026-01-21 22:22:08 +0200 |
|---|---|---|
| committer | Danilo Krummrich <dakr@kernel.org> | 2026-01-23 21:20:11 +0100 |
| commit | 121d87b28e1d9061d3aaa156c43a627d3cb5e620 (patch) | |
| tree | c0f45e4b093d2525dea5648ddd52105ae5f4ae99 /drivers/gpu/nova-core | |
| parent | 7043698aee6b6f61415ebb49b7e95fdfb9373a77 (diff) | |
| download | linux-next-121d87b28e1d9061d3aaa156c43a627d3cb5e620.tar.gz linux-next-121d87b28e1d9061d3aaa156c43a627d3cb5e620.zip | |
rust: io: separate generic I/O helpers from MMIO implementation
The previous Io<SIZE> type combined both the generic I/O access helpers
and MMIO implementation details in a single struct. This coupling prevented
reusing the I/O helpers for other backends, such as PCI configuration
space.
Establish a clean separation between the I/O interface and concrete
backends by separating generic I/O helpers from MMIO implementation.
Introduce a new trait hierarchy to handle different access capabilities:
- IoCapable<T>: A marker trait indicating that a backend supports I/O
operations of a certain type (u8, u16, u32, or u64).
- Io trait: Defines fallible (try_read8, try_write8, etc.) and infallibile
(read8, write8, etc.) I/O methods with runtime bounds checking and
compile-time bounds checking.
- IoKnownSize trait: The marker trait for types support infallible I/O
methods.
Move the MMIO-specific logic into a dedicated Mmio<SIZE> type that
implements the Io traits. Rename IoRaw to MmioRaw and update consumers to
use the new types.
Cc: Alexandre Courbot <acourbot@nvidia.com>
Cc: Alice Ryhl <aliceryhl@google.com>
Cc: Bjorn Helgaas <helgaas@kernel.org>
Cc: Gary Guo <gary@garyguo.net>
Cc: Danilo Krummrich <dakr@kernel.org>
Cc: John Hubbard <jhubbard@nvidia.com>
Signed-off-by: Zhi Wang <zhiw@nvidia.com>
Reviewed-by: Alice Ryhl <aliceryhl@google.com>
Reviewed-by: Alexandre Courbot <acourbot@nvidia.com>
Reviewed-by: Gary Guo <gary@garyguo.net>
Link: https://patch.msgid.link/20260121202212.4438-3-zhiw@nvidia.com
[ Add #[expect(unused)] to define_{read,write}!(). - Danilo ]
Signed-off-by: Danilo Krummrich <dakr@kernel.org>
Diffstat (limited to 'drivers/gpu/nova-core')
| -rw-r--r-- | drivers/gpu/nova-core/gsp/sequencer.rs | 5 | ||||
| -rw-r--r-- | drivers/gpu/nova-core/regs/macros.rs | 90 | ||||
| -rw-r--r-- | drivers/gpu/nova-core/vbios.rs | 1 |
3 files changed, 59 insertions, 37 deletions
diff --git a/drivers/gpu/nova-core/gsp/sequencer.rs b/drivers/gpu/nova-core/gsp/sequencer.rs index 2d0369c49092..862cf7f27143 100644 --- a/drivers/gpu/nova-core/gsp/sequencer.rs +++ b/drivers/gpu/nova-core/gsp/sequencer.rs @@ -12,7 +12,10 @@ use core::{ use kernel::{ device, - io::poll::read_poll_timeout, + io::{ + poll::read_poll_timeout, + Io, // + }, prelude::*, time::{ delay::fsleep, diff --git a/drivers/gpu/nova-core/regs/macros.rs b/drivers/gpu/nova-core/regs/macros.rs index fd1a815fa57d..ed624be1f39b 100644 --- a/drivers/gpu/nova-core/regs/macros.rs +++ b/drivers/gpu/nova-core/regs/macros.rs @@ -369,16 +369,18 @@ macro_rules! register { /// Read the register from its address in `io`. #[inline(always)] - pub(crate) fn read<const SIZE: usize, T>(io: &T) -> Self where - T: ::core::ops::Deref<Target = ::kernel::io::Io<SIZE>>, + pub(crate) fn read<T, I>(io: &T) -> Self where + T: ::core::ops::Deref<Target = I>, + I: ::kernel::io::IoKnownSize + ::kernel::io::IoCapable<u32>, { Self(io.read32($offset)) } /// Write the value contained in `self` to the register address in `io`. #[inline(always)] - pub(crate) fn write<const SIZE: usize, T>(self, io: &T) where - T: ::core::ops::Deref<Target = ::kernel::io::Io<SIZE>>, + pub(crate) fn write<T, I>(self, io: &T) where + T: ::core::ops::Deref<Target = I>, + I: ::kernel::io::IoKnownSize + ::kernel::io::IoCapable<u32>, { io.write32(self.0, $offset) } @@ -386,11 +388,12 @@ macro_rules! register { /// Read the register from its address in `io` and run `f` on its value to obtain a new /// value to write back. #[inline(always)] - pub(crate) fn update<const SIZE: usize, T, F>( + pub(crate) fn update<T, I, F>( io: &T, f: F, ) where - T: ::core::ops::Deref<Target = ::kernel::io::Io<SIZE>>, + T: ::core::ops::Deref<Target = I>, + I: ::kernel::io::IoKnownSize + ::kernel::io::IoCapable<u32>, F: ::core::ops::FnOnce(Self) -> Self, { let reg = f(Self::read(io)); @@ -408,12 +411,13 @@ macro_rules! register { /// Read the register from `io`, using the base address provided by `base` and adding /// the register's offset to it. #[inline(always)] - pub(crate) fn read<const SIZE: usize, T, B>( + pub(crate) fn read<T, I, B>( io: &T, #[allow(unused_variables)] base: &B, ) -> Self where - T: ::core::ops::Deref<Target = ::kernel::io::Io<SIZE>>, + T: ::core::ops::Deref<Target = I>, + I: ::kernel::io::IoKnownSize + ::kernel::io::IoCapable<u32>, B: crate::regs::macros::RegisterBase<$base>, { const OFFSET: usize = $name::OFFSET; @@ -428,13 +432,14 @@ macro_rules! register { /// Write the value contained in `self` to `io`, using the base address provided by /// `base` and adding the register's offset to it. #[inline(always)] - pub(crate) fn write<const SIZE: usize, T, B>( + pub(crate) fn write<T, I, B>( self, io: &T, #[allow(unused_variables)] base: &B, ) where - T: ::core::ops::Deref<Target = ::kernel::io::Io<SIZE>>, + T: ::core::ops::Deref<Target = I>, + I: ::kernel::io::IoKnownSize + ::kernel::io::IoCapable<u32>, B: crate::regs::macros::RegisterBase<$base>, { const OFFSET: usize = $name::OFFSET; @@ -449,12 +454,13 @@ macro_rules! register { /// the register's offset to it, then run `f` on its value to obtain a new value to /// write back. #[inline(always)] - pub(crate) fn update<const SIZE: usize, T, B, F>( + pub(crate) fn update<T, I, B, F>( io: &T, base: &B, f: F, ) where - T: ::core::ops::Deref<Target = ::kernel::io::Io<SIZE>>, + T: ::core::ops::Deref<Target = I>, + I: ::kernel::io::IoKnownSize + ::kernel::io::IoCapable<u32>, B: crate::regs::macros::RegisterBase<$base>, F: ::core::ops::FnOnce(Self) -> Self, { @@ -474,11 +480,12 @@ macro_rules! register { /// Read the array register at index `idx` from its address in `io`. #[inline(always)] - pub(crate) fn read<const SIZE: usize, T>( + pub(crate) fn read<T, I>( io: &T, idx: usize, ) -> Self where - T: ::core::ops::Deref<Target = ::kernel::io::Io<SIZE>>, + T: ::core::ops::Deref<Target = I>, + I: ::kernel::io::IoKnownSize + ::kernel::io::IoCapable<u32>, { build_assert!(idx < Self::SIZE); @@ -490,12 +497,13 @@ macro_rules! register { /// Write the value contained in `self` to the array register with index `idx` in `io`. #[inline(always)] - pub(crate) fn write<const SIZE: usize, T>( + pub(crate) fn write<T, I>( self, io: &T, idx: usize ) where - T: ::core::ops::Deref<Target = ::kernel::io::Io<SIZE>>, + T: ::core::ops::Deref<Target = I>, + I: ::kernel::io::IoKnownSize + ::kernel::io::IoCapable<u32>, { build_assert!(idx < Self::SIZE); @@ -507,12 +515,13 @@ macro_rules! register { /// Read the array register at index `idx` in `io` and run `f` on its value to obtain a /// new value to write back. #[inline(always)] - pub(crate) fn update<const SIZE: usize, T, F>( + pub(crate) fn update<T, I, F>( io: &T, idx: usize, f: F, ) where - T: ::core::ops::Deref<Target = ::kernel::io::Io<SIZE>>, + T: ::core::ops::Deref<Target = I>, + I: ::kernel::io::IoKnownSize + ::kernel::io::IoCapable<u32>, F: ::core::ops::FnOnce(Self) -> Self, { let reg = f(Self::read(io, idx)); @@ -524,11 +533,12 @@ macro_rules! register { /// The validity of `idx` is checked at run-time, and `EINVAL` is returned is the /// access was out-of-bounds. #[inline(always)] - pub(crate) fn try_read<const SIZE: usize, T>( + pub(crate) fn try_read<T, I>( io: &T, idx: usize, ) -> ::kernel::error::Result<Self> where - T: ::core::ops::Deref<Target = ::kernel::io::Io<SIZE>>, + T: ::core::ops::Deref<Target = I>, + I: ::kernel::io::IoKnownSize + ::kernel::io::IoCapable<u32>, { if idx < Self::SIZE { Ok(Self::read(io, idx)) @@ -542,12 +552,13 @@ macro_rules! register { /// The validity of `idx` is checked at run-time, and `EINVAL` is returned is the /// access was out-of-bounds. #[inline(always)] - pub(crate) fn try_write<const SIZE: usize, T>( + pub(crate) fn try_write<T, I>( self, io: &T, idx: usize, ) -> ::kernel::error::Result where - T: ::core::ops::Deref<Target = ::kernel::io::Io<SIZE>>, + T: ::core::ops::Deref<Target = I>, + I: ::kernel::io::IoKnownSize + ::kernel::io::IoCapable<u32>, { if idx < Self::SIZE { Ok(self.write(io, idx)) @@ -562,12 +573,13 @@ macro_rules! register { /// The validity of `idx` is checked at run-time, and `EINVAL` is returned is the /// access was out-of-bounds. #[inline(always)] - pub(crate) fn try_update<const SIZE: usize, T, F>( + pub(crate) fn try_update<T, I, F>( io: &T, idx: usize, f: F, ) -> ::kernel::error::Result where - T: ::core::ops::Deref<Target = ::kernel::io::Io<SIZE>>, + T: ::core::ops::Deref<Target = I>, + I: ::kernel::io::IoKnownSize + ::kernel::io::IoCapable<u32>, F: ::core::ops::FnOnce(Self) -> Self, { if idx < Self::SIZE { @@ -593,13 +605,14 @@ macro_rules! register { /// Read the array register at index `idx` from `io`, using the base address provided /// by `base` and adding the register's offset to it. #[inline(always)] - pub(crate) fn read<const SIZE: usize, T, B>( + pub(crate) fn read<T, I, B>( io: &T, #[allow(unused_variables)] base: &B, idx: usize, ) -> Self where - T: ::core::ops::Deref<Target = ::kernel::io::Io<SIZE>>, + T: ::core::ops::Deref<Target = I>, + I: ::kernel::io::IoKnownSize + ::kernel::io::IoCapable<u32>, B: crate::regs::macros::RegisterBase<$base>, { build_assert!(idx < Self::SIZE); @@ -614,14 +627,15 @@ macro_rules! register { /// Write the value contained in `self` to `io`, using the base address provided by /// `base` and adding the offset of array register `idx` to it. #[inline(always)] - pub(crate) fn write<const SIZE: usize, T, B>( + pub(crate) fn write<T, I, B>( self, io: &T, #[allow(unused_variables)] base: &B, idx: usize ) where - T: ::core::ops::Deref<Target = ::kernel::io::Io<SIZE>>, + T: ::core::ops::Deref<Target = I>, + I: ::kernel::io::IoKnownSize + ::kernel::io::IoCapable<u32>, B: crate::regs::macros::RegisterBase<$base>, { build_assert!(idx < Self::SIZE); @@ -636,13 +650,14 @@ macro_rules! register { /// by `base` and adding the register's offset to it, then run `f` on its value to /// obtain a new value to write back. #[inline(always)] - pub(crate) fn update<const SIZE: usize, T, B, F>( + pub(crate) fn update<T, I, B, F>( io: &T, base: &B, idx: usize, f: F, ) where - T: ::core::ops::Deref<Target = ::kernel::io::Io<SIZE>>, + T: ::core::ops::Deref<Target = I>, + I: ::kernel::io::IoKnownSize + ::kernel::io::IoCapable<u32>, B: crate::regs::macros::RegisterBase<$base>, F: ::core::ops::FnOnce(Self) -> Self, { @@ -656,12 +671,13 @@ macro_rules! register { /// The validity of `idx` is checked at run-time, and `EINVAL` is returned is the /// access was out-of-bounds. #[inline(always)] - pub(crate) fn try_read<const SIZE: usize, T, B>( + pub(crate) fn try_read<T, I, B>( io: &T, base: &B, idx: usize, ) -> ::kernel::error::Result<Self> where - T: ::core::ops::Deref<Target = ::kernel::io::Io<SIZE>>, + T: ::core::ops::Deref<Target = I>, + I: ::kernel::io::IoKnownSize + ::kernel::io::IoCapable<u32>, B: crate::regs::macros::RegisterBase<$base>, { if idx < Self::SIZE { @@ -677,13 +693,14 @@ macro_rules! register { /// The validity of `idx` is checked at run-time, and `EINVAL` is returned is the /// access was out-of-bounds. #[inline(always)] - pub(crate) fn try_write<const SIZE: usize, T, B>( + pub(crate) fn try_write<T, I, B>( self, io: &T, base: &B, idx: usize, ) -> ::kernel::error::Result where - T: ::core::ops::Deref<Target = ::kernel::io::Io<SIZE>>, + T: ::core::ops::Deref<Target = I>, + I: ::kernel::io::IoKnownSize + ::kernel::io::IoCapable<u32>, B: crate::regs::macros::RegisterBase<$base>, { if idx < Self::SIZE { @@ -700,13 +717,14 @@ macro_rules! register { /// The validity of `idx` is checked at run-time, and `EINVAL` is returned is the /// access was out-of-bounds. #[inline(always)] - pub(crate) fn try_update<const SIZE: usize, T, B, F>( + pub(crate) fn try_update<T, I, B, F>( io: &T, base: &B, idx: usize, f: F, ) -> ::kernel::error::Result where - T: ::core::ops::Deref<Target = ::kernel::io::Io<SIZE>>, + T: ::core::ops::Deref<Target = I>, + I: ::kernel::io::IoKnownSize + ::kernel::io::IoCapable<u32>, B: crate::regs::macros::RegisterBase<$base>, F: ::core::ops::FnOnce(Self) -> Self, { diff --git a/drivers/gpu/nova-core/vbios.rs b/drivers/gpu/nova-core/vbios.rs index abf423560ff4..fe33b519e4d8 100644 --- a/drivers/gpu/nova-core/vbios.rs +++ b/drivers/gpu/nova-core/vbios.rs @@ -6,6 +6,7 @@ use core::convert::TryFrom; use kernel::{ device, + io::Io, prelude::*, ptr::{ Alignable, |
