mirror of
https://github.com/torvalds/linux.git
synced 2026-09-23 13:14:02 +02:00
rust: io: move Io methods to extension trait
`Io` trait now has a single required method with many more provided methods. Provided methods may want to rely on their implementations to not be arbitrarily overridden by implementers for correctness or soundness. A good example is the `size` method, it may be relied by unsafe code and thus must be consistent with the metadata obtained from `as_ptr`. Thus, create a new trait to host `size` method, extract existing provided methods to the new trait, and provide a blanket implementation. This pattern is used extensively in userspace Rust libraries e.g. `tokio` where `AsyncRead` has minimum methods and `AsyncReadExt` is what users mostly interact with. To avoid changing all user imports, the base trait is renamed to `IoBase` and the newly added trait takes the existing `Io` name. Reviewed-by: Alexandre Courbot <acourbot@nvidia.com> Suggested-by: Danilo Krummrich <dakr@kernel.org> Signed-off-by: Gary Guo <gary@garyguo.net> Reviewed-by: Daniel Almeida <daniel.almeida@collabora.com> Link: https://patch.msgid.link/20260706-io_projection-v6-12-72cd5d055d54@garyguo.net [ Add comment explaining the purpose of the Io blanket implementation. - Danilo ] Signed-off-by: Danilo Krummrich <dakr@kernel.org>
This commit is contained in:
parent
bed01ca9e9
commit
9b36c13cbd
|
|
@ -68,6 +68,7 @@ struct Inner<T> {
|
|||
/// devres::Devres,
|
||||
/// io::{
|
||||
/// Io,
|
||||
/// IoBase,
|
||||
/// Mmio,
|
||||
/// MmioRaw,
|
||||
/// MmioBackend,
|
||||
|
|
@ -105,7 +106,7 @@ struct Inner<T> {
|
|||
/// }
|
||||
/// }
|
||||
///
|
||||
/// impl<'a, const SIZE: usize> Io<'a> for &'a IoMem<SIZE> {
|
||||
/// impl<'a, const SIZE: usize> IoBase<'a> for &'a IoMem<SIZE> {
|
||||
/// type Backend = MmioBackend;
|
||||
/// type Target = Region<SIZE>;
|
||||
///
|
||||
|
|
|
|||
|
|
@ -224,7 +224,7 @@ fn io_view<'a, IO: Io<'a>, U>(
|
|||
/// operation.
|
||||
pub trait IoBackend {
|
||||
/// View type for this I/O backend.
|
||||
type View<'a, T: ?Sized + KnownSize>: Io<'a, Backend = Self, Target = T>;
|
||||
type View<'a, T: ?Sized + KnownSize>: IoBase<'a, Backend = Self, Target = T>;
|
||||
|
||||
/// Convert a `view` to a raw pointer for projection.
|
||||
///
|
||||
|
|
@ -310,15 +310,12 @@ fn offset(self) -> usize {
|
|||
/// Types implementing this trait (e.g. MMIO BARs or PCI config regions)
|
||||
/// can perform I/O operations on regions of memory.
|
||||
///
|
||||
/// The [`Io`] trait provides:
|
||||
/// - Method to convert into [`IoBackend::View`].
|
||||
/// - Helper methods for offset validation and address calculation
|
||||
/// - Fallible (runtime checked) accessors for different data widths
|
||||
///
|
||||
/// Which I/O methods are available depends on the associated [`IoBackend`] implementation.
|
||||
/// This trait defines which backend shall be used for I/O operations and provides a method to
|
||||
/// convert into [`IoBackend::View`]. Users should use the [`Io`] trait which provides the actual
|
||||
/// methods to perform I/O operations.
|
||||
///
|
||||
/// This should be implemented on cheaply copyable handles, such as references or view types.
|
||||
pub trait Io<'a>: Copy {
|
||||
pub trait IoBase<'a>: Copy {
|
||||
/// Type that defines all I/O operations.
|
||||
type Backend: IoBackend;
|
||||
|
||||
|
|
@ -327,6 +324,21 @@ pub trait Io<'a>: Copy {
|
|||
|
||||
/// Return a view that covers the full region.
|
||||
fn as_view(self) -> <Self::Backend as IoBackend>::View<'a, Self::Target>;
|
||||
}
|
||||
|
||||
/// Extension trait to provide I/O operation methods to types that implement [`IoBase`].
|
||||
///
|
||||
/// This trait provides:
|
||||
/// - Helper methods for offset validation and address calculation
|
||||
/// - Fallible (runtime checked) accessors for different data widths
|
||||
///
|
||||
/// Which I/O methods are available depends on the associated [`IoBackend`] implementation.
|
||||
pub trait Io<'a>: IoBase<'a> {
|
||||
/// Returns the size of this I/O region.
|
||||
#[inline]
|
||||
fn size(self) -> usize {
|
||||
KnownSize::size(Self::Backend::as_ptr(self.as_view()))
|
||||
}
|
||||
|
||||
/// Fallible 8-bit read with runtime bounds check.
|
||||
#[inline(always)]
|
||||
|
|
@ -780,6 +792,10 @@ fn update<T, L, F>(self, location: L, f: F)
|
|||
}
|
||||
}
|
||||
|
||||
// Blanket implementation ensures that provided methods cannot be arbitrarily overridden by
|
||||
// implementers, which is relied upon for correctness and soundness.
|
||||
impl<'a, T: IoBase<'a>> Io<'a> for T {}
|
||||
|
||||
/// A view of memory-mapped I/O region.
|
||||
///
|
||||
/// # Invariant
|
||||
|
|
@ -820,7 +836,7 @@ unsafe impl<T: ?Sized + Sync> Send for Mmio<'_, T> {}
|
|||
// SAFETY: `Mmio<'_, T>` is conceptually `&T` but in I/O memory.
|
||||
unsafe impl<T: ?Sized + Sync> Sync for Mmio<'_, T> {}
|
||||
|
||||
impl<'a, T: ?Sized + KnownSize> Io<'a> for Mmio<'a, T> {
|
||||
impl<'a, T: ?Sized + KnownSize> IoBase<'a> for Mmio<'a, T> {
|
||||
type Backend = MmioBackend;
|
||||
type Target = T;
|
||||
|
||||
|
|
@ -921,7 +937,7 @@ unsafe fn project_view<'a, T: ?Sized + KnownSize, U: ?Sized + KnownSize>(
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, T: ?Sized + KnownSize> Io<'a> for RelaxedMmio<'a, T> {
|
||||
impl<'a, T: ?Sized + KnownSize> IoBase<'a> for RelaxedMmio<'a, T> {
|
||||
type Backend = RelaxedMmioBackend;
|
||||
type Target = T;
|
||||
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@
|
|||
Region,
|
||||
Resource, //
|
||||
},
|
||||
Io,
|
||||
IoBase,
|
||||
Mmio,
|
||||
MmioBackend,
|
||||
MmioRaw, //
|
||||
|
|
@ -210,7 +210,7 @@ pub fn into_devres(self) -> Result<Devres<ExclusiveIoMem<'static, SIZE>>> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, const SIZE: usize> Io<'a> for &'a ExclusiveIoMem<'_, SIZE> {
|
||||
impl<'a, const SIZE: usize> IoBase<'a> for &'a ExclusiveIoMem<'_, SIZE> {
|
||||
type Backend = MmioBackend;
|
||||
type Target = super::Region<SIZE>;
|
||||
|
||||
|
|
@ -292,7 +292,7 @@ fn drop(&mut self) {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, const SIZE: usize> Io<'a> for &'a IoMem<'_, SIZE> {
|
||||
impl<'a, const SIZE: usize> IoBase<'a> for &'a IoMem<'_, SIZE> {
|
||||
type Backend = MmioBackend;
|
||||
type Target = super::Region<SIZE>;
|
||||
|
||||
|
|
|
|||
|
|
@ -8,8 +8,8 @@
|
|||
device,
|
||||
devres::Devres,
|
||||
io::{
|
||||
Io,
|
||||
IoBackend,
|
||||
IoBase,
|
||||
IoCapable,
|
||||
Mmio,
|
||||
MmioBackend,
|
||||
|
|
@ -144,7 +144,7 @@ fn io_write(view: ConfigSpace<'_, $ty>, value: $ty) {
|
|||
impl_config_space_io_capable!(u16, pci_read_config_word, pci_write_config_word);
|
||||
impl_config_space_io_capable!(u32, pci_read_config_dword, pci_write_config_dword);
|
||||
|
||||
impl<'a, T: ?Sized + KnownSize> Io<'a> for ConfigSpace<'a, T> {
|
||||
impl<'a, T: ?Sized + KnownSize> IoBase<'a> for ConfigSpace<'a, T> {
|
||||
type Backend = ConfigSpaceBackend;
|
||||
type Target = T;
|
||||
|
||||
|
|
@ -267,7 +267,7 @@ fn drop(&mut self) {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, const SIZE: usize> Io<'a> for &'a Bar<'_, SIZE> {
|
||||
impl<'a, const SIZE: usize> IoBase<'a> for &'a Bar<'_, SIZE> {
|
||||
type Backend = MmioBackend;
|
||||
type Target = crate::io::Region<SIZE>;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user