Out of broad need for these macros in Rust, move them out. Several folks have shown interest (Nova, Tyr GPU drivers).
bitfield moved into bits modules - defines bitfields in Rust structs similar to C. register moved into io module - defines hardware registers and accessors. [Added F: record to MAINTAINERS file entry as suggested by Yury.] Reviewed-by: Elle Rhumsaa <[email protected]> Signed-off-by: Joel Fernandes <[email protected]> --- MAINTAINERS | 1 + drivers/gpu/nova-core/falcon.rs | 2 +- drivers/gpu/nova-core/falcon/gsp.rs | 3 +- drivers/gpu/nova-core/falcon/sec2.rs | 2 +- drivers/gpu/nova-core/nova_core.rs | 3 -- drivers/gpu/nova-core/regs.rs | 6 +-- rust/kernel/bits.rs | 2 + .../kernel/bits}/bitfield.rs | 27 ++++++----- rust/kernel/io.rs | 1 + .../macros.rs => rust/kernel/io/register.rs | 46 ++++++++++--------- 10 files changed, 50 insertions(+), 43 deletions(-) rename {drivers/gpu/nova-core => rust/kernel/bits}/bitfield.rs (91%) rename drivers/gpu/nova-core/regs/macros.rs => rust/kernel/io/register.rs (93%) diff --git a/MAINTAINERS b/MAINTAINERS index b97760467f09..ca9132fa4055 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4313,6 +4313,7 @@ F: include/asm-generic/bitops.h F: include/linux/bitops.h F: lib/test_bitops.c F: tools/*/bitops* +F: rust/kernel/bits* BLINKM RGB LED DRIVER M: Jan-Simon Moeller <[email protected]> diff --git a/drivers/gpu/nova-core/falcon.rs b/drivers/gpu/nova-core/falcon.rs index 938f25b556a8..55f03f435138 100644 --- a/drivers/gpu/nova-core/falcon.rs +++ b/drivers/gpu/nova-core/falcon.rs @@ -6,6 +6,7 @@ use hal::FalconHal; use kernel::device; use kernel::dma::DmaAddress; +use kernel::io::register::RegisterBase; use kernel::prelude::*; use kernel::sync::aref::ARef; use kernel::time::Delta; @@ -14,7 +15,6 @@ use crate::driver::Bar0; use crate::gpu::Chipset; use crate::regs; -use crate::regs::macros::RegisterBase; use crate::util; pub(crate) mod gsp; diff --git a/drivers/gpu/nova-core/falcon/gsp.rs b/drivers/gpu/nova-core/falcon/gsp.rs index c9ab375fd8a1..04920a619246 100644 --- a/drivers/gpu/nova-core/falcon/gsp.rs +++ b/drivers/gpu/nova-core/falcon/gsp.rs @@ -1,12 +1,13 @@ // SPDX-License-Identifier: GPL-2.0 +use kernel::io::register::RegisterBase; use kernel::prelude::*; use kernel::time::Delta; use crate::{ driver::Bar0, falcon::{Falcon, FalconEngine, PFalcon2Base, PFalconBase}, - regs::{self, macros::RegisterBase}, + regs, util::wait_on, }; diff --git a/drivers/gpu/nova-core/falcon/sec2.rs b/drivers/gpu/nova-core/falcon/sec2.rs index 815786c8480d..81717868a8a8 100644 --- a/drivers/gpu/nova-core/falcon/sec2.rs +++ b/drivers/gpu/nova-core/falcon/sec2.rs @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 use crate::falcon::{FalconEngine, PFalcon2Base, PFalconBase}; -use crate::regs::macros::RegisterBase; +use kernel::io::register::RegisterBase; /// Type specifying the `Sec2` falcon engine. Cannot be instantiated. pub(crate) struct Sec2(()); diff --git a/drivers/gpu/nova-core/nova_core.rs b/drivers/gpu/nova-core/nova_core.rs index eaba6ad22f7a..4dbc7e5daae3 100644 --- a/drivers/gpu/nova-core/nova_core.rs +++ b/drivers/gpu/nova-core/nova_core.rs @@ -2,9 +2,6 @@ //! Nova Core GPU Driver -#[macro_use] -mod bitfield; - mod dma; mod driver; mod falcon; diff --git a/drivers/gpu/nova-core/regs.rs b/drivers/gpu/nova-core/regs.rs index c214f8056d6e..07533eb6f64e 100644 --- a/drivers/gpu/nova-core/regs.rs +++ b/drivers/gpu/nova-core/regs.rs @@ -4,15 +4,13 @@ // but are mapped to types. #![allow(non_camel_case_types)] -#[macro_use] -pub(crate) mod macros; - use crate::falcon::{ DmaTrfCmdSize, FalconCoreRev, FalconCoreRevSubversion, FalconFbifMemType, FalconFbifTarget, FalconModSelAlgo, FalconSecurityModel, PFalcon2Base, PFalconBase, PeregrineCoreSelect, }; use crate::gpu::{Architecture, Chipset}; use kernel::prelude::*; +use kernel::register; // PMC @@ -352,6 +350,7 @@ pub(crate) fn mem_scrubbing_done(self) -> bool { pub(crate) mod gm107 { // FUSE + use kernel::register; register!(NV_FUSE_STATUS_OPT_DISPLAY @ 0x00021c04 { 0:0 display_disabled as bool; @@ -360,6 +359,7 @@ pub(crate) mod gm107 { pub(crate) mod ga100 { // FUSE + use kernel::register; register!(NV_FUSE_STATUS_OPT_DISPLAY @ 0x00820c04 { 0:0 display_disabled as bool; diff --git a/rust/kernel/bits.rs b/rust/kernel/bits.rs index 553d50265883..590a77d99ad7 100644 --- a/rust/kernel/bits.rs +++ b/rust/kernel/bits.rs @@ -201,3 +201,5 @@ pub const fn [<genmask_ $ty>](range: RangeInclusive<u32>) -> $ty { /// assert_eq!(genmask_u8(0..=7), u8::MAX); /// ``` ); + +pub mod bitfield; diff --git a/drivers/gpu/nova-core/bitfield.rs b/rust/kernel/bits/bitfield.rs similarity index 91% rename from drivers/gpu/nova-core/bitfield.rs rename to rust/kernel/bits/bitfield.rs index 39354e60360c..0837fefc270f 100644 --- a/drivers/gpu/nova-core/bitfield.rs +++ b/rust/kernel/bits/bitfield.rs @@ -78,10 +78,13 @@ //! - `as <type> ?=> <try_into_type>` calls `<try_into_type>`'s `TryFrom::<<type>>` implementation //! and returns the result. This is useful with fields for which not all values are valid. //! + +/// bitfield macro definition +#[macro_export] macro_rules! bitfield { // Main entry point - defines the bitfield struct with fields ($vis:vis struct $name:ident : $storage:ty $(, $comment:literal)? { $($fields:tt)* }) => { - bitfield!(@core $vis $name $storage $(, $comment)? { $($fields)* }); + ::kernel::bitfield!(@core $vis $name $storage $(, $comment)? { $($fields)* }); }; // All rules below are helpers. @@ -116,7 +119,7 @@ fn from(val: $storage) -> Self { } } - bitfield!(@fields_dispatcher $vis $name $storage { $($fields)* }); + ::kernel::bitfield!(@fields_dispatcher $vis $name $storage { $($fields)* }); }; // Captures the fields and passes them to all the implementers that require field information. @@ -132,7 +135,7 @@ fn from(val: $storage) -> Self { )* } ) => { - bitfield!(@field_accessors $vis $name $storage { + ::kernel::bitfield!(@field_accessors $vis $name $storage { $( $hi:$lo $field as $type $(?=> $try_into_type)? @@ -141,8 +144,8 @@ fn from(val: $storage) -> Self { ; )* }); - bitfield!(@debug $name { $($field;)* }); - bitfield!(@default $name { $($field;)* }); + ::kernel::bitfield!(@debug $name { $($field;)* }); + ::kernel::bitfield!(@default $name { $($field;)* }); }; // Defines all the field getter/setter methods for `$name`. @@ -157,7 +160,7 @@ fn from(val: $storage) -> Self { } ) => { $( - bitfield!(@check_field_bounds $hi:$lo $field as $type); + ::kernel::bitfield!(@check_field_bounds $hi:$lo $field as $type); )* #[allow(dead_code)] @@ -169,7 +172,7 @@ impl $name { } $( - bitfield!(@field_accessor $vis $name $storage, $hi:$lo $field as $type + ::kernel::bitfield!(@field_accessor $vis $name $storage, $hi:$lo $field as $type $(?=> $try_into_type)? $(=> $into_type)? $(, $comment)? @@ -206,7 +209,7 @@ impl $name { @field_accessor $vis:vis $name:ident $storage:ty, $hi:tt:$lo:tt $field:ident as bool => $into_type:ty $(, $comment:literal)?; ) => { - bitfield!( + ::kernel::bitfield!( @leaf_accessor $vis $name $storage, $hi:$lo $field { |f| <$into_type>::from(if f != 0 { true } else { false }) } $into_type => $into_type $(, $comment)?; @@ -217,7 +220,7 @@ impl $name { ( @field_accessor $vis:vis $name:ident $storage:ty, $hi:tt:$lo:tt $field:ident as bool $(, $comment:literal)?; ) => { - bitfield!(@field_accessor $vis $name $storage, $hi:$lo $field as bool => bool $(, $comment)?;); + ::kernel::bitfield!(@field_accessor $vis $name $storage, $hi:$lo $field as bool => bool $(, $comment)?;); }; // Catches the `?=>` syntax for non-boolean fields. @@ -225,7 +228,7 @@ impl $name { @field_accessor $vis:vis $name:ident $storage:ty, $hi:tt:$lo:tt $field:ident as $type:tt ?=> $try_into_type:ty $(, $comment:literal)?; ) => { - bitfield!(@leaf_accessor $vis $name $storage, $hi:$lo $field + ::kernel::bitfield!(@leaf_accessor $vis $name $storage, $hi:$lo $field { |f| <$try_into_type>::try_from(f as $type) } $try_into_type => ::core::result::Result< $try_into_type, @@ -239,7 +242,7 @@ impl $name { @field_accessor $vis:vis $name:ident $storage:ty, $hi:tt:$lo:tt $field:ident as $type:tt => $into_type:ty $(, $comment:literal)?; ) => { - bitfield!(@leaf_accessor $vis $name $storage, $hi:$lo $field + ::kernel::bitfield!(@leaf_accessor $vis $name $storage, $hi:$lo $field { |f| <$into_type>::from(f as $type) } $into_type => $into_type $(, $comment)?;); }; @@ -248,7 +251,7 @@ impl $name { @field_accessor $vis:vis $name:ident $storage:ty, $hi:tt:$lo:tt $field:ident as $type:tt $(, $comment:literal)?; ) => { - bitfield!(@field_accessor $vis $name $storage, $hi:$lo $field as $type => $type $(, $comment)?;); + ::kernel::bitfield!(@field_accessor $vis $name $storage, $hi:$lo $field as $type => $type $(, $comment)?;); }; // Generates the accessor methods for a single field. diff --git a/rust/kernel/io.rs b/rust/kernel/io.rs index 03b467722b86..a79b603604b1 100644 --- a/rust/kernel/io.rs +++ b/rust/kernel/io.rs @@ -8,6 +8,7 @@ use crate::{bindings, build_assert, ffi::c_void}; pub mod mem; +pub mod register; pub mod resource; pub use resource::Resource; diff --git a/drivers/gpu/nova-core/regs/macros.rs b/rust/kernel/io/register.rs similarity index 93% rename from drivers/gpu/nova-core/regs/macros.rs rename to rust/kernel/io/register.rs index 6a4f3271beb3..088a8590db92 100644 --- a/drivers/gpu/nova-core/regs/macros.rs +++ b/rust/kernel/io/register.rs @@ -17,7 +17,8 @@ /// The `T` generic argument is used to distinguish which base to use, in case a type provides /// several bases. It is given to the `register!` macro to restrict the use of the register to /// implementors of this particular variant. -pub(crate) trait RegisterBase<T> { +pub trait RegisterBase<T> { + /// The base address for the register. const BASE: usize; } @@ -273,28 +274,29 @@ pub(crate) trait RegisterBase<T> { /// # Ok(()) /// # } /// ``` +#[macro_export] macro_rules! register { // Creates a register at a fixed offset of the MMIO space. ($name:ident @ $offset:literal $(, $comment:literal)? { $($fields:tt)* } ) => { - bitfield!(pub(crate) struct $name: u32 $(, $comment)? { $($fields)* } ); + ::kernel::bitfield!(pub(crate) struct $name: u32 $(, $comment)? { $($fields)* } ); register!(@io_fixed $name @ $offset); }; // Creates an alias register of fixed offset register `alias` with its own fields. ($name:ident => $alias:ident $(, $comment:literal)? { $($fields:tt)* } ) => { - bitfield!(pub(crate) struct $name: u32 $(, $comment)? { $($fields)* } ); + ::kernel::bitfield!(pub(crate) struct $name: u32 $(, $comment)? { $($fields)* } ); register!(@io_fixed $name @ $alias::OFFSET); }; // Creates a register at a relative offset from a base address provider. ($name:ident @ $base:ty [ $offset:literal ] $(, $comment:literal)? { $($fields:tt)* } ) => { - bitfield!(pub(crate) struct $name: u32 $(, $comment)? { $($fields)* } ); + ::kernel::bitfield!(pub(crate) struct $name: u32 $(, $comment)? { $($fields)* } ); register!(@io_relative $name @ $base [ $offset ]); }; // Creates an alias register of relative offset register `alias` with its own fields. ($name:ident => $base:ty [ $alias:ident ] $(, $comment:literal)? { $($fields:tt)* }) => { - bitfield!(pub(crate) struct $name: u32 $(, $comment)? { $($fields)* } ); + ::kernel::bitfield!(pub(crate) struct $name: u32 $(, $comment)? { $($fields)* } ); register!(@io_relative $name @ $base [ $alias::OFFSET ]); }; @@ -305,7 +307,7 @@ macro_rules! register { } ) => { static_assert!(::core::mem::size_of::<u32>() <= $stride); - bitfield!(pub(crate) struct $name: u32 $(, $comment)? { $($fields)* } ); + ::kernel::bitfield!(pub(crate) struct $name: u32 $(, $comment)? { $($fields)* } ); register!(@io_array $name @ $offset [ $size ; $stride ]); }; @@ -326,7 +328,7 @@ macro_rules! register { $(, $comment:literal)? { $($fields:tt)* } ) => { static_assert!(::core::mem::size_of::<u32>() <= $stride); - bitfield!(pub(crate) struct $name: u32 $(, $comment)? { $($fields)* } ); + ::kernel::bitfield!(pub(crate) struct $name: u32 $(, $comment)? { $($fields)* } ); register!(@io_relative_array $name @ $base [ $offset [ $size ; $stride ] ]); }; @@ -348,7 +350,7 @@ macro_rules! register { } ) => { static_assert!($idx < $alias::SIZE); - bitfield!(pub(crate) struct $name: u32 $(, $comment)? { $($fields)* } ); + ::kernel::bitfield!(pub(crate) struct $name: u32 $(, $comment)? { $($fields)* } ); register!(@io_relative $name @ $base [ $alias::OFFSET + $idx * $alias::STRIDE ] ); }; @@ -357,7 +359,7 @@ macro_rules! register { // to avoid it being interpreted in place of the relative register array alias rule. ($name:ident => $alias:ident [ $idx:expr ] $(, $comment:literal)? { $($fields:tt)* }) => { static_assert!($idx < $alias::SIZE); - bitfield!(pub(crate) struct $name: u32 $(, $comment)? { $($fields)* } ); + ::kernel::bitfield!(pub(crate) struct $name: u32 $(, $comment)? { $($fields)* } ); register!(@io_fixed $name @ $alias::OFFSET + $idx * $alias::STRIDE ); }; @@ -414,12 +416,12 @@ pub(crate) fn read<const SIZE: usize, T, B>( base: &B, ) -> Self where T: ::core::ops::Deref<Target = ::kernel::io::Io<SIZE>>, - B: crate::regs::macros::RegisterBase<$base>, + B: ::kernel::io::register::RegisterBase<$base>, { const OFFSET: usize = $name::OFFSET; let value = io.read32( - <B as crate::regs::macros::RegisterBase<$base>>::BASE + OFFSET + <B as ::kernel::io::register::RegisterBase<$base>>::BASE + OFFSET ); Self(value) @@ -435,13 +437,13 @@ pub(crate) fn write<const SIZE: usize, T, B>( base: &B, ) where T: ::core::ops::Deref<Target = ::kernel::io::Io<SIZE>>, - B: crate::regs::macros::RegisterBase<$base>, + B: ::kernel::io::register::RegisterBase<$base>, { const OFFSET: usize = $name::OFFSET; io.write32( self.0, - <B as crate::regs::macros::RegisterBase<$base>>::BASE + OFFSET + <B as ::kernel::io::register::RegisterBase<$base>>::BASE + OFFSET ); } @@ -455,7 +457,7 @@ pub(crate) fn alter<const SIZE: usize, T, B, F>( f: F, ) where T: ::core::ops::Deref<Target = ::kernel::io::Io<SIZE>>, - B: crate::regs::macros::RegisterBase<$base>, + B: ::kernel::io::register::RegisterBase<$base>, F: ::core::ops::FnOnce(Self) -> Self, { let reg = f(Self::read(io, base)); @@ -600,11 +602,11 @@ pub(crate) fn read<const SIZE: usize, T, B>( idx: usize, ) -> Self where T: ::core::ops::Deref<Target = ::kernel::io::Io<SIZE>>, - B: crate::regs::macros::RegisterBase<$base>, + B: ::kernel::io::register::RegisterBase<$base>, { build_assert!(idx < Self::SIZE); - let offset = <B as crate::regs::macros::RegisterBase<$base>>::BASE + + let offset = <B as ::kernel::io::register::RegisterBase<$base>>::BASE + Self::OFFSET + (idx * Self::STRIDE); let value = io.read32(offset); @@ -622,11 +624,11 @@ pub(crate) fn write<const SIZE: usize, T, B>( idx: usize ) where T: ::core::ops::Deref<Target = ::kernel::io::Io<SIZE>>, - B: crate::regs::macros::RegisterBase<$base>, + B: ::kernel::io::register::RegisterBase<$base>, { build_assert!(idx < Self::SIZE); - let offset = <B as crate::regs::macros::RegisterBase<$base>>::BASE + + let offset = <B as ::kernel::io::register::RegisterBase<$base>>::BASE + Self::OFFSET + (idx * Self::STRIDE); io.write32(self.0, offset); @@ -643,7 +645,7 @@ pub(crate) fn alter<const SIZE: usize, T, B, F>( f: F, ) where T: ::core::ops::Deref<Target = ::kernel::io::Io<SIZE>>, - B: crate::regs::macros::RegisterBase<$base>, + B: ::kernel::io::register::RegisterBase<$base>, F: ::core::ops::FnOnce(Self) -> Self, { let reg = f(Self::read(io, base, idx)); @@ -662,7 +664,7 @@ pub(crate) fn try_read<const SIZE: usize, T, B>( idx: usize, ) -> ::kernel::error::Result<Self> where T: ::core::ops::Deref<Target = ::kernel::io::Io<SIZE>>, - B: crate::regs::macros::RegisterBase<$base>, + B: ::kernel::io::register::RegisterBase<$base>, { if idx < Self::SIZE { Ok(Self::read(io, base, idx)) @@ -684,7 +686,7 @@ pub(crate) fn try_write<const SIZE: usize, T, B>( idx: usize, ) -> ::kernel::error::Result where T: ::core::ops::Deref<Target = ::kernel::io::Io<SIZE>>, - B: crate::regs::macros::RegisterBase<$base>, + B: ::kernel::io::register::RegisterBase<$base>, { if idx < Self::SIZE { Ok(self.write(io, base, idx)) @@ -707,7 +709,7 @@ pub(crate) fn try_alter<const SIZE: usize, T, B, F>( f: F, ) -> ::kernel::error::Result where T: ::core::ops::Deref<Target = ::kernel::io::Io<SIZE>>, - B: crate::regs::macros::RegisterBase<$base>, + B: ::kernel::io::register::RegisterBase<$base>, F: ::core::ops::FnOnce(Self) -> Self, { if idx < Self::SIZE { -- 2.34.1
