Currently, `Io` is implemented on owned I/O objects (e.g. `Bar`). This is going to change with I/O projections, as then `Io` need to work both for owned objects and views of them. Views are themselves reference-like (however they obviously cannot be references, because they belong to a different address space).
To faciliate the change, change `Io` to be implemented on reference types for the owned I/O objects, and make methods take `self` instead of `&self`. When I/O views are implemented, we can then naturally implement `Io` for these objects. Signed-off-by: Gary Guo <[email protected]> --- rust/kernel/io.rs | 80 +++++++++++++++++++++++++-------------------------- rust/kernel/pci/io.rs | 12 ++++---- 2 files changed, 46 insertions(+), 46 deletions(-) diff --git a/rust/kernel/io.rs b/rust/kernel/io.rs index 5a657bb3da09..d57df2a072a0 100644 --- a/rust/kernel/io.rs +++ b/rust/kernel/io.rs @@ -226,7 +226,7 @@ pub trait IoCapable<T> { /// /// - The range `[address..address + size_of::<T>()]` must be within the bounds of `Self`. /// - `address` must be aligned. - unsafe fn io_read(&self, address: usize) -> T; + unsafe fn io_read(self, address: usize) -> T; /// Performs an I/O write of `value` at `address`. /// @@ -234,7 +234,7 @@ pub trait IoCapable<T> { /// /// - The range `[address..address + size_of::<T>()]` must be within the bounds of `Self`. /// - `address` must be aligned. - unsafe fn io_write(&self, value: T, address: usize); + unsafe fn io_write(self, value: T, address: usize); } /// Describes a given I/O location: its offset, width, and type to convert the raw value from and @@ -301,21 +301,21 @@ fn offset(self) -> usize { /// /// For MMIO regions, all widths (u8, u16, u32, and u64 on 64-bit systems) are typically /// supported. For PCI configuration space, u8, u16, and u32 are supported but u64 is not. -pub trait Io { +pub trait Io: Copy { /// Type of this I/O region. For untyped regions, [`Region`] can be used. type Target: ?Sized + KnownSize; /// Returns the base address of this mapping. - fn addr(&self) -> usize; + fn addr(self) -> usize; /// Returns the maximum size of this mapping. - fn maxsize(&self) -> usize; + fn maxsize(self) -> usize; /// Returns the absolute I/O address for a given `offset`, /// performing compile-time bound checks. // Always inline to optimize out error path of `build_assert`. #[inline(always)] - fn io_addr_assert<U>(&self, offset: usize) -> usize { + fn io_addr_assert<U>(self, offset: usize) -> usize { // We cannot check alignment with `offset_valid` using `self.addr()`. So set 0 for it and // ensure alignment by checking that the alignment of `U` is smaller or equal to the // alignment of `Self::Target`. @@ -328,7 +328,7 @@ fn io_addr_assert<U>(&self, offset: usize) -> usize { /// Returns the absolute I/O address for a given `offset`, /// performing runtime bound checks. #[inline] - fn io_addr<U>(&self, offset: usize) -> Result<usize> { + fn io_addr<U>(self, offset: usize) -> Result<usize> { if !offset_valid::<U>(self.addr(), offset, self.maxsize()) { return Err(EINVAL); } @@ -340,7 +340,7 @@ fn io_addr<U>(&self, offset: usize) -> Result<usize> { /// Fallible 8-bit read with runtime bounds check. #[inline(always)] - fn try_read8(&self, offset: usize) -> Result<u8> + fn try_read8(self, offset: usize) -> Result<u8> where usize: IoLoc<Self::Target, u8, IoType = u8>, Self: IoCapable<u8>, @@ -350,7 +350,7 @@ fn try_read8(&self, offset: usize) -> Result<u8> /// Fallible 16-bit read with runtime bounds check. #[inline(always)] - fn try_read16(&self, offset: usize) -> Result<u16> + fn try_read16(self, offset: usize) -> Result<u16> where usize: IoLoc<Self::Target, u16, IoType = u16>, Self: IoCapable<u16>, @@ -360,7 +360,7 @@ fn try_read16(&self, offset: usize) -> Result<u16> /// Fallible 32-bit read with runtime bounds check. #[inline(always)] - fn try_read32(&self, offset: usize) -> Result<u32> + fn try_read32(self, offset: usize) -> Result<u32> where usize: IoLoc<Self::Target, u32, IoType = u32>, Self: IoCapable<u32>, @@ -370,7 +370,7 @@ fn try_read32(&self, offset: usize) -> Result<u32> /// Fallible 64-bit read with runtime bounds check. #[inline(always)] - fn try_read64(&self, offset: usize) -> Result<u64> + fn try_read64(self, offset: usize) -> Result<u64> where usize: IoLoc<Self::Target, u64, IoType = u64>, Self: IoCapable<u64>, @@ -380,7 +380,7 @@ fn try_read64(&self, offset: usize) -> Result<u64> /// Fallible 8-bit write with runtime bounds check. #[inline(always)] - fn try_write8(&self, value: u8, offset: usize) -> Result + fn try_write8(self, value: u8, offset: usize) -> Result where usize: IoLoc<Self::Target, u8, IoType = u8>, Self: IoCapable<u8>, @@ -390,7 +390,7 @@ fn try_write8(&self, value: u8, offset: usize) -> Result /// Fallible 16-bit write with runtime bounds check. #[inline(always)] - fn try_write16(&self, value: u16, offset: usize) -> Result + fn try_write16(self, value: u16, offset: usize) -> Result where usize: IoLoc<Self::Target, u16, IoType = u16>, Self: IoCapable<u16>, @@ -400,7 +400,7 @@ fn try_write16(&self, value: u16, offset: usize) -> Result /// Fallible 32-bit write with runtime bounds check. #[inline(always)] - fn try_write32(&self, value: u32, offset: usize) -> Result + fn try_write32(self, value: u32, offset: usize) -> Result where usize: IoLoc<Self::Target, u32, IoType = u32>, Self: IoCapable<u32>, @@ -410,7 +410,7 @@ fn try_write32(&self, value: u32, offset: usize) -> Result /// Fallible 64-bit write with runtime bounds check. #[inline(always)] - fn try_write64(&self, value: u64, offset: usize) -> Result + fn try_write64(self, value: u64, offset: usize) -> Result where usize: IoLoc<Self::Target, u64, IoType = u64>, Self: IoCapable<u64>, @@ -420,7 +420,7 @@ fn try_write64(&self, value: u64, offset: usize) -> Result /// Infallible 8-bit read with compile-time bounds check. #[inline(always)] - fn read8(&self, offset: usize) -> u8 + fn read8(self, offset: usize) -> u8 where usize: IoLoc<Self::Target, u8, IoType = u8>, Self: IoCapable<u8>, @@ -430,7 +430,7 @@ fn read8(&self, offset: usize) -> u8 /// Infallible 16-bit read with compile-time bounds check. #[inline(always)] - fn read16(&self, offset: usize) -> u16 + fn read16(self, offset: usize) -> u16 where usize: IoLoc<Self::Target, u16, IoType = u16>, Self: IoCapable<u16>, @@ -440,7 +440,7 @@ fn read16(&self, offset: usize) -> u16 /// Infallible 32-bit read with compile-time bounds check. #[inline(always)] - fn read32(&self, offset: usize) -> u32 + fn read32(self, offset: usize) -> u32 where usize: IoLoc<Self::Target, u32, IoType = u32>, Self: IoCapable<u32>, @@ -450,7 +450,7 @@ fn read32(&self, offset: usize) -> u32 /// Infallible 64-bit read with compile-time bounds check. #[inline(always)] - fn read64(&self, offset: usize) -> u64 + fn read64(self, offset: usize) -> u64 where usize: IoLoc<Self::Target, u64, IoType = u64>, Self: IoCapable<u64>, @@ -460,7 +460,7 @@ fn read64(&self, offset: usize) -> u64 /// Infallible 8-bit write with compile-time bounds check. #[inline(always)] - fn write8(&self, value: u8, offset: usize) + fn write8(self, value: u8, offset: usize) where usize: IoLoc<Self::Target, u8, IoType = u8>, Self: IoCapable<u8>, @@ -470,7 +470,7 @@ fn write8(&self, value: u8, offset: usize) /// Infallible 16-bit write with compile-time bounds check. #[inline(always)] - fn write16(&self, value: u16, offset: usize) + fn write16(self, value: u16, offset: usize) where usize: IoLoc<Self::Target, u16, IoType = u16>, Self: IoCapable<u16>, @@ -480,7 +480,7 @@ fn write16(&self, value: u16, offset: usize) /// Infallible 32-bit write with compile-time bounds check. #[inline(always)] - fn write32(&self, value: u32, offset: usize) + fn write32(self, value: u32, offset: usize) where usize: IoLoc<Self::Target, u32, IoType = u32>, Self: IoCapable<u32>, @@ -490,7 +490,7 @@ fn write32(&self, value: u32, offset: usize) /// Infallible 64-bit write with compile-time bounds check. #[inline(always)] - fn write64(&self, value: u64, offset: usize) + fn write64(self, value: u64, offset: usize) where usize: IoLoc<Self::Target, u64, IoType = u64>, Self: IoCapable<u64>, @@ -521,7 +521,7 @@ fn write64(&self, value: u64, offset: usize) /// } /// ``` #[inline(always)] - fn try_read<T, L>(&self, location: L) -> Result<T> + fn try_read<T, L>(self, location: L) -> Result<T> where L: IoLoc<Self::Target, T>, Self: IoCapable<L::IoType>, @@ -555,7 +555,7 @@ fn try_read<T, L>(&self, location: L) -> Result<T> /// } /// ``` #[inline(always)] - fn try_write<T, L>(&self, location: L, value: T) -> Result + fn try_write<T, L>(self, location: L, value: T) -> Result where L: IoLoc<Self::Target, T>, Self: IoCapable<L::IoType>, @@ -601,7 +601,7 @@ fn try_write<T, L>(&self, location: L, value: T) -> Result /// } /// ``` #[inline(always)] - fn try_write_reg<T, L, V>(&self, value: V) -> Result + fn try_write_reg<T, L, V>(self, value: V) -> Result where L: IoLoc<Self::Target, T>, V: LocatedRegister<Self::Target, Location = L, Value = T>, @@ -634,7 +634,7 @@ fn try_write_reg<T, L, V>(&self, value: V) -> Result /// } /// ``` #[inline(always)] - fn try_update<T, L, F>(&self, location: L, f: F) -> Result + fn try_update<T, L, F>(self, location: L, f: F) -> Result where L: IoLoc<Self::Target, T>, Self: IoCapable<L::IoType>, @@ -673,7 +673,7 @@ fn try_update<T, L, F>(&self, location: L, f: F) -> Result /// } /// ``` #[inline(always)] - fn read<T, L>(&self, location: L) -> T + fn read<T, L>(self, location: L) -> T where L: IoLoc<Self::Target, T>, Self: IoCapable<L::IoType>, @@ -705,7 +705,7 @@ fn read<T, L>(&self, location: L) -> T /// } /// ``` #[inline(always)] - fn write<T, L>(&self, location: L, value: T) + fn write<T, L>(self, location: L, value: T) where L: IoLoc<Self::Target, T>, Self: IoCapable<L::IoType>, @@ -748,7 +748,7 @@ fn write<T, L>(&self, location: L, value: T) /// } /// ``` #[inline(always)] - fn write_reg<T, L, V>(&self, value: V) + fn write_reg<T, L, V>(self, value: V) where L: IoLoc<Self::Target, T>, V: LocatedRegister<Self::Target, Location = L, Value = T>, @@ -781,7 +781,7 @@ fn write_reg<T, L, V>(&self, value: V) /// } /// ``` #[inline(always)] - fn update<T, L, F>(&self, location: L, f: F) + fn update<T, L, F>(self, location: L, f: F) where L: IoLoc<Self::Target, T>, Self: IoCapable<L::IoType>, @@ -802,13 +802,13 @@ fn update<T, L, F>(&self, location: L, f: F) macro_rules! impl_mmio_io_capable { ($mmio:ident, $(#[$attr:meta])* $ty:ty, $read_fn:ident, $write_fn:ident) => { $(#[$attr])* - impl<const SIZE: usize> IoCapable<$ty> for $mmio<SIZE> { - unsafe fn io_read(&self, address: usize) -> $ty { + impl<const SIZE: usize> IoCapable<$ty> for &$mmio<SIZE> { + unsafe fn io_read(self, address: usize) -> $ty { // SAFETY: By the trait invariant `address` is a valid address for MMIO operations. unsafe { bindings::$read_fn(address as *const c_void) } } - unsafe fn io_write(&self, value: $ty, address: usize) { + unsafe fn io_write(self, value: $ty, address: usize) { // SAFETY: By the trait invariant `address` is a valid address for MMIO operations. unsafe { bindings::$write_fn(value, address as *mut c_void) } } @@ -829,18 +829,18 @@ unsafe fn io_write(&self, value: $ty, address: usize) { writeq ); -impl<const SIZE: usize> Io for Mmio<SIZE> { +impl<'a, const SIZE: usize> Io for &'a Mmio<SIZE> { type Target = Region<SIZE>; /// Returns the base address of this mapping. #[inline] - fn addr(&self) -> usize { + fn addr(self) -> usize { self.0.addr() } /// Returns the maximum size of this mapping. #[inline] - fn maxsize(&self) -> usize { + fn maxsize(self) -> usize { self.0.maxsize() } } @@ -867,16 +867,16 @@ pub unsafe fn from_raw(raw: &MmioRaw<SIZE>) -> &Self { #[repr(transparent)] pub struct RelaxedMmio<const SIZE: usize = 0>(Mmio<SIZE>); -impl<const SIZE: usize> Io for RelaxedMmio<SIZE> { +impl<'a, const SIZE: usize> Io for &'a RelaxedMmio<SIZE> { type Target = Region<SIZE>; #[inline] - fn addr(&self) -> usize { + fn addr(self) -> usize { self.0.addr() } #[inline] - fn maxsize(&self) -> usize { + fn maxsize(self) -> usize { self.0.maxsize() } } diff --git a/rust/kernel/pci/io.rs b/rust/kernel/pci/io.rs index b4996aa059d8..505305cd9b86 100644 --- a/rust/kernel/pci/io.rs +++ b/rust/kernel/pci/io.rs @@ -79,8 +79,8 @@ pub struct ConfigSpace<'a, S: ?Sized + ConfigSpaceKind = Extended> { /// Implements [`IoCapable`] on [`ConfigSpace`] for `$ty` using `$read_fn` and `$write_fn`. macro_rules! impl_config_space_io_capable { ($ty:ty, $read_fn:ident, $write_fn:ident) => { - impl<'a, S: ?Sized + ConfigSpaceKind> IoCapable<$ty> for ConfigSpace<'a, S> { - unsafe fn io_read(&self, address: usize) -> $ty { + impl<'a, S: ?Sized + ConfigSpaceKind> IoCapable<$ty> for &ConfigSpace<'a, S> { + unsafe fn io_read(self, address: usize) -> $ty { let mut val: $ty = 0; // Return value from C function is ignored in infallible accessors. @@ -94,7 +94,7 @@ unsafe fn io_read(&self, address: usize) -> $ty { val } - unsafe fn io_write(&self, value: $ty, address: usize) { + unsafe fn io_write(self, value: $ty, address: usize) { // Return value from C function is ignored in infallible accessors. let _ret = // SAFETY: By the type invariant `self.pdev` is a valid address. @@ -112,18 +112,18 @@ unsafe fn io_write(&self, value: $ty, address: usize) { 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, S: ?Sized + ConfigSpaceKind> Io for ConfigSpace<'a, S> { +impl<'a, S: ?Sized + ConfigSpaceKind> Io for &ConfigSpace<'a, S> { type Target = S; /// Returns the base address of the I/O region. It is always 0 for configuration space. #[inline] - fn addr(&self) -> usize { + fn addr(self) -> usize { 0 } /// Returns the maximum size of the configuration space. #[inline] - fn maxsize(&self) -> usize { + fn maxsize(self) -> usize { self.pdev.cfg_size().into_raw() } } -- 2.54.0
