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.