diff options
| author | Gary Guo <gary@garyguo.net> | 2026-09-01 17:50:29 +0100 |
|---|---|---|
| committer | Danilo Krummrich <dakr@kernel.org> | 2026-09-06 13:39:48 +0200 |
| commit | 2a750c56179b416f3501c2644f787265ad7a6785 (patch) | |
| tree | 546e335d92c1d8382857be0c2f6097ea0bf7d849 /rust | |
| parent | ff067ace5fbeada7e629d4aaccfa1d04da3eeebc (diff) | |
| download | linux-next-2a750c56179b416f3501c2644f787265ad7a6785.tar.gz linux-next-2a750c56179b416f3501c2644f787265ad7a6785.zip | |
rust: io: support register projections
`IoLoc`s themselves just describe a projection from a region to a
concrete register. Thus, support it in `io_project` macro too. Also,
update methods that operate on `IoLoc` to use I/O projection.
Documentation of `io_project!` is not expanded yet as the example works
better when `register!` type can specify base type. `io_read!` and
`io_write!` gains the ability to operate on registers as corollary of
the capability of `io_project!`. Examples are not added because `read`
and `write` is still preferably used instead.
Reviewed-by: Alexandre Courbot <acourbot@nvidia.com>
Signed-off-by: Gary Guo <gary@garyguo.net>
Tested-by: Alexandre Courbot <acourbot@nvidia.com>
Link: https://patch.msgid.link/20260901-typed_register-v4-5-5552b1d59525@garyguo.net
Signed-off-by: Danilo Krummrich <dakr@kernel.org>
Diffstat (limited to 'rust')
| -rw-r--r-- | rust/kernel/io.rs | 56 |
1 files changed, 46 insertions, 10 deletions
diff --git a/rust/kernel/io.rs b/rust/kernel/io.rs index 18c71bd765b2..8df268969566 100644 --- a/rust/kernel/io.rs +++ b/rust/kernel/io.rs @@ -857,8 +857,7 @@ pub trait Io<'a>: IoBase<'a> { L: IoLoc<Self::Target, T>, Self::Backend: IoCapable<<T as AsRepr>::Repr>, { - let view = io_view::<Self, T>(self, location.offset())?; - Ok(view.read_val()) + Ok(io_read!(self, try: location)) } /// Generic fallible write with runtime bounds check. @@ -891,8 +890,7 @@ pub trait Io<'a>: IoBase<'a> { L: IoLoc<Self::Target, T>, Self::Backend: IoCapable<<T as AsRepr>::Repr>, { - let view = io_view::<Self, T>(self, location.offset())?; - view.write_val(value); + io_write!(self, try: location, value); Ok(()) } @@ -971,7 +969,7 @@ pub trait Io<'a>: IoBase<'a> { Self::Backend: IoCapable<<T as AsRepr>::Repr>, F: FnOnce(T) -> T, { - let view = io_view::<Self, T>(self, location.offset())?; + let view = io_project!(self, try: location); view.write_val(f(view.read_val())); Ok(()) } @@ -1004,8 +1002,7 @@ pub trait Io<'a>: IoBase<'a> { L: IoLoc<Self::Target, T>, Self::Backend: IoCapable<<T as AsRepr>::Repr>, { - let view = io_view_assert::<Self, T>(self, location.offset()); - view.read_val() + io_read!(self, build: location) } /// Generic infallible write with compile-time bounds check. @@ -1036,8 +1033,7 @@ pub trait Io<'a>: IoBase<'a> { L: IoLoc<Self::Target, T>, Self::Backend: IoCapable<<T as AsRepr>::Repr>, { - let view = io_view_assert::<Self, T>(self, location.offset()); - view.write_val(value) + io_write!(self, build: location, value); } /// Generic infallible write of a fully-located register value. @@ -1114,7 +1110,7 @@ pub trait Io<'a>: IoBase<'a> { Self::Backend: IoCapable<<T as AsRepr>::Repr>, F: FnOnce(T) -> T, { - let view = io_view_assert::<Self, T>(self, location.offset()); + let view = io_project!(self, build: location); view.write_val(f(view.read_val())); } } @@ -1659,6 +1655,25 @@ where // SAFETY: Per safety requirement. unsafe { T::Backend::project_view::<T::Target, _>(self.0, ptr) } } + + #[inline(always)] + pub fn try_project_loc<U, L>( + self, + location: L, + ) -> Result<<T::Backend as IoBackend>::View<'a, U>> + where + L: IoLoc<T::Target, U>, + { + io_view::<_, U>(self.0, location.offset()) + } + + #[inline(always)] + pub fn project_loc<U, L>(self, location: L) -> <T::Backend as IoBackend>::View<'a, U> + where + L: IoLoc<T::Target, U>, + { + io_view_assert::<_, U>(self.0, location.offset()) + } } /// Project an I/O type to a subview of it. @@ -1686,6 +1701,21 @@ where #[macro_export] #[doc(hidden)] macro_rules! io_project { + // Register projection + ($io:expr, try: $ioloc:expr) => {{ + #[allow(unused)] + use $crate::io::IoBase as _; + let view = $crate::io::ProjectHelper($io.as_view()); + view.try_project_loc($ioloc)? + }}; + ($io:expr, build: $ioloc:expr) => {{ + #[allow(unused)] + use $crate::io::IoBase as _; + let view = $crate::io::ProjectHelper($io.as_view()); + view.project_loc($ioloc) + }}; + + // Field or index projection ($io:expr, $($proj:tt)*) => {{ #[allow(unused)] use $crate::io::IoBase as _; @@ -1756,6 +1786,12 @@ macro_rules! io_write { (@parse [$io:expr] [$($proj:tt)*] [[$flavor:ident: $index:expr] $($rest:tt)*]) => { $crate::io_write!(@parse [$io] [$($proj)* [$flavor: $index]] [$($rest)*]) }; + (@parse [$io:expr] [] [try: $ioloc:expr, $($rest:tt)*]) => { + $crate::io_write!(@parse [$io] [try: $ioloc] [, $($rest)*]) + }; + (@parse [$io:expr] [] [build: $ioloc:expr, $($rest:tt)*]) => { + $crate::io_write!(@parse [$io] [build: $ioloc] [, $($rest)*]) + }; ($io:expr, $($rest:tt)*) => { $crate::io_write!(@parse [$io] [] [$($rest)*]) }; |
