Re: [PATCH v2 03/16] rust: io: support register projections

"Alexandre Courbot" <[email protected]>
Newsgroups dev.linux.lists.driver-core,dev.linux.lists.nova-gpu,org.freedesktop.lists.dri-devel,org.kernel.vger.linux-kernel,org.kernel.vger.linux-pci,org.kernel.vger.rust-for-linux
Message-ID <[email protected]>
On Thu Aug 6, 2026 at 1:35 AM JST, Gary Guo wrote:
> `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 preferrably used instead.
>
> Signed-off-by: Gary Guo <[email protected]>
> ---
>  rust/kernel/io.rs | 58 ++++++++++++++++++++++++++++++++++++++++++++-----------
>  1 file changed, 47 insertions(+), 11 deletions(-)
>
> diff --git a/rust/kernel/io.rs b/rust/kernel/io.rs
> index 71c6180ed745..ae18890866b6 100644
> --- a/rust/kernel/io.rs
> +++ b/rust/kernel/io.rs
> @@ -295,7 +295,7 @@ fn transmute_neo<Src: IntoBytes, Dst: FromBytes>(val: Src) -> Dst {
>  ///
>  /// The layout of the type and the underlying primitive must match; this is enforced via const
>  /// assertions when I/O methods are used, as the type system cannot represent this.
> -/// [`IoRepr::from_repr`] and [`IoRepr::into_expr`] can be overridden for conversions, however it
> +/// [`IoRepr::from_repr`] and [`IoRepr::into_repr`] can be overridden for conversions, however it

This typo was introduced in patch 2, let's fix it there.

>  /// should be noted that they are only invoked on value read/write operations and are not invoked
>  /// on byte operations such as [`Io::copy_read`].
>  ///
> @@ -970,8 +970,7 @@ fn try_read<T, L>(self, location: L) -> Result<T>
>          L: IoLoc<Self::Target, T>,
>          Self::Backend: IoCapable<<T as IoRepr>::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.
> @@ -1004,8 +1003,7 @@ fn try_write<T, L>(self, location: L, value: T) -> Result
>          L: IoLoc<Self::Target, T>,
>          Self::Backend: IoCapable<<T as IoRepr>::Repr>,
>      {
> -        let view = io_view::<Self, T>(self, location.offset())?;
> -        view.write_val(value);
> +        io_write!(self, try: location, value);
>          Ok(())
>      }
>  
> @@ -1084,7 +1082,7 @@ fn try_update<T, L, F>(self, location: L, f: F) -> Result
>          Self::Backend: IoCapable<<T as IoRepr>::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(())
>      }
> @@ -1117,8 +1115,7 @@ fn read<T, L>(self, location: L) -> T
>          L: IoLoc<Self::Target, T>,
>          Self::Backend: IoCapable<<T as IoRepr>::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.
> @@ -1149,8 +1146,7 @@ fn write<T, L>(self, location: L, value: T)
>          L: IoLoc<Self::Target, T>,
>          Self::Backend: IoCapable<<T as IoRepr>::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.
> @@ -1227,7 +1223,7 @@ fn update<T, L, F>(self, location: L, f: F)
>          Self::Backend: IoCapable<<T as IoRepr>::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()));
>      }
>  }
> @@ -1772,6 +1768,25 @@ pub unsafe fn project_view<U: ?Sized + KnownSize>(
>          // SAFETY: Per safety requirement.
>          unsafe { T::Backend::project_view::<T::Target, _>(self.0, ptr) }
>      }
> +
> +    #[inline(always)]
> +    pub fn try_project_loc<U, L>(

nit: missing documentation

> +        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>

ditto.
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.