`IoCopyable` provides both `copy_from_io` and `copy_to_io`, so a backend that supports copies supports them in both directions, and all four copy methods of `Io` require both.
Thus, as done for `IoCapable` in the previous patch, replace `IoCopyable` with an `IoCopyReadable` trait holding `copy_from_io` and `copy_read`, and an `IoCopyWritable` trait holding `copy_to_io` and `copy_write`, and implement both for every backend that implemented `IoCopyable`. `copy_read` and `copy_to_slice`, which read from I/O memory, now require `IoCopyReadable`, and `copy_write` and `copy_from_slice`, which write to it, require `IoCopyWritable`. No functional change intended. Signed-off-by: Daniel Almeida <[email protected]> --- rust/kernel/dma.rs | 17 +++++++----- rust/kernel/io.rs | 77 ++++++++++++++++++++++++++++++------------------------ 2 files changed, 53 insertions(+), 41 deletions(-) diff --git a/rust/kernel/dma.rs b/rust/kernel/dma.rs index 7216a78d38c9..c57026368ab8 100644 --- a/rust/kernel/dma.rs +++ b/rust/kernel/dma.rs @@ -17,7 +17,8 @@ io::{ IoBackend, IoBase, - IoCopyable, + IoCopyReadable, + IoCopyWritable, IoReadable, IoWritable, SysMem, @@ -1201,7 +1202,7 @@ fn io_write<'a>(view: Self::View<'a, T>, value: T) { } } -impl IoCopyable for CoherentIoBackend { +impl IoCopyReadable for CoherentIoBackend { #[inline] unsafe fn copy_from_io(view: Self::View<'_, [u8]>, buffer: *mut u8) { // SAFETY: Per safety requirement. @@ -1209,14 +1210,16 @@ unsafe fn copy_from_io(view: Self::View<'_, [u8]>, buffer: *mut u8) { } #[inline] - unsafe fn copy_to_io(view: Self::View<'_, [u8]>, buffer: *const u8) { - // SAFETY: Per safety requirement. - unsafe { SysMemBackend::copy_to_io(view.cpu_addr, buffer) } + fn copy_read<T: zerocopy::FromBytes>(view: Self::View<'_, T>) -> T { + SysMemBackend::copy_read(view.cpu_addr) } +} +impl IoCopyWritable for CoherentIoBackend { #[inline] - fn copy_read<T: zerocopy::FromBytes>(view: Self::View<'_, T>) -> T { - SysMemBackend::copy_read(view.cpu_addr) + unsafe fn copy_to_io(view: Self::View<'_, [u8]>, buffer: *const u8) { + // SAFETY: Per safety requirement. + unsafe { SysMemBackend::copy_to_io(view.cpu_addr, buffer) } } #[inline] diff --git a/rust/kernel/io.rs b/rust/kernel/io.rs index fd5dd5f6bda4..ae60099fd4c3 100644 --- a/rust/kernel/io.rs +++ b/rust/kernel/io.rs @@ -298,8 +298,8 @@ pub trait IoWritable<T>: IoBackend { fn io_write<'a>(view: Self::View<'a, T>, value: T); } -/// Trait indicating that an I/O backend supports memory copy operations. -pub trait IoCopyable: IoBackend { +/// Trait indicating that an I/O backend supports memory copy operations from I/O. +pub trait IoCopyReadable: IoBackend { /// Copy contents of `view` to `buffer`. /// /// # Safety @@ -308,14 +308,6 @@ pub trait IoCopyable: IoBackend { /// - `buffer` should not overlap with `view`. unsafe fn copy_from_io(view: Self::View<'_, [u8]>, buffer: *mut u8); - /// Copy contents from `buffer` to `view`. - /// - /// # Safety - /// - /// - `buffer` is valid for volatile read for `view.size()` bytes. - /// - `buffer` should not overlap with `view`. - unsafe fn copy_to_io(view: Self::View<'_, [u8]>, buffer: *const u8); - /// Copy from `view` and return the value. #[inline] fn copy_read<T: FromBytes>(view: Self::View<'_, T>) -> T { @@ -337,6 +329,17 @@ fn copy_read<T: FromBytes>(view: Self::View<'_, T>) -> T { // SAFETY: `T: FromBytes` guarantee that all bit patterns are valid. unsafe { buf.assume_init() } } +} + +/// Trait indicating that an I/O backend supports memory copy operations to I/O. +pub trait IoCopyWritable: IoBackend { + /// Copy contents from `buffer` to `view`. + /// + /// # Safety + /// + /// - `buffer` is valid for volatile read for `view.size()` bytes. + /// - `buffer` should not overlap with `view`. + unsafe fn copy_to_io(view: Self::View<'_, [u8]>, buffer: *const u8); /// Copy `value` to `view`. /// @@ -602,7 +605,7 @@ fn write_val(self, value: Self::Target) #[inline] fn copy_read(self) -> Self::Target where - Self::Backend: IoCopyable, + Self::Backend: IoCopyReadable, Self::Target: Sized + FromBytes, { Self::Backend::copy_read(self.as_view()) @@ -629,7 +632,7 @@ fn copy_read(self) -> Self::Target #[inline] fn copy_write(self, value: Self::Target) where - Self::Backend: IoCopyable, + Self::Backend: IoCopyWritable, Self::Target: Sized + IntoBytes, { Self::Backend::copy_write(self.as_view(), value); @@ -654,7 +657,7 @@ fn copy_write(self, value: Self::Target) #[inline] fn copy_from_slice(self, data: &[u8]) where - Self::Backend: IoCopyable, + Self::Backend: IoCopyWritable, Self: Io<'a, Target = [u8]>, { assert_eq!(self.len(), data.len()); @@ -685,7 +688,7 @@ fn copy_from_slice(self, data: &[u8]) #[inline] fn copy_to_slice(self, data: &mut [u8]) where - Self::Backend: IoCopyable, + Self::Backend: IoCopyReadable, Self: Io<'a, Target = [u8]>, { assert_eq!(self.len(), data.len()); @@ -1275,7 +1278,7 @@ fn io_write(view: <$backend as IoBackend>::View<'_, $ty>, value: $ty) { #[cfg(CONFIG_64BIT)] impl_mmio_io_capable!(MmioBackend, u64, readq, writeq); -impl IoCopyable for MmioBackend { +impl IoCopyReadable for MmioBackend { #[inline] unsafe fn copy_from_io(view: Self::View<'_, [u8]>, buffer: *mut u8) { // SAFETY: @@ -1285,7 +1288,9 @@ unsafe fn copy_from_io(view: Self::View<'_, [u8]>, buffer: *mut u8) { bindings::memcpy_fromio(buffer.cast(), view.ptr.cast(), view.size()); } } +} +impl IoCopyWritable for MmioBackend { #[inline] unsafe fn copy_to_io(view: Self::View<'_, [u8]>, buffer: *const u8) { // SAFETY: @@ -1442,7 +1447,7 @@ fn io_write(view: SysMem<'_, $ty>, value: $ty) { #[cfg(CONFIG_64BIT)] impl_sysmem_io_capable!(u64); -impl IoCopyable for SysMemBackend { +impl IoCopyReadable for SysMemBackend { #[inline] unsafe fn copy_from_io(view: Self::View<'_, [u8]>, buffer: *mut u8) { // Use `bindings::memcpy` instead of `copy_nonoverlapping` for volatile. @@ -1452,15 +1457,6 @@ unsafe fn copy_from_io(view: Self::View<'_, [u8]>, buffer: *mut u8) { unsafe { bindings::memcpy(buffer.cast(), view.ptr.cast(), view.ptr.len()) }; } - #[inline] - unsafe fn copy_to_io(view: Self::View<'_, [u8]>, buffer: *const u8) { - // Use `bindings::memcpy` instead of `copy_nonoverlapping` for volatile. - // SAFETY: - // - `view.ptr` is in CPU address space and valid for write. - // - `buffer` is valid for read for `view.size()` bytes which is equal to `view.ptr.len()`. - unsafe { bindings::memcpy(view.ptr.cast(), buffer.cast(), view.ptr.len()) }; - } - #[inline] fn copy_read<T: FromBytes>(view: Self::View<'_, T>) -> T { // SAFETY: @@ -1471,6 +1467,17 @@ fn copy_read<T: FromBytes>(view: Self::View<'_, T>) -> T { // - `T: FromBytes` so all bit patterns are valid. unsafe { view.ptr.read_volatile() } } +} + +impl IoCopyWritable for SysMemBackend { + #[inline] + unsafe fn copy_to_io(view: Self::View<'_, [u8]>, buffer: *const u8) { + // Use `bindings::memcpy` instead of `copy_nonoverlapping` for volatile. + // SAFETY: + // - `view.ptr` is in CPU address space and valid for write. + // - `buffer` is valid for read for `view.size()` bytes which is equal to `view.ptr.len()`. + unsafe { bindings::memcpy(view.ptr.cast(), buffer.cast(), view.ptr.len()) }; + } #[inline] fn copy_write<T: IntoBytes>(view: Self::View<'_, T>, value: T) { @@ -1640,7 +1647,7 @@ fn io_write<'a>(view: Self::View<'a, T>, value: T) { } } -impl IoCopyable for IoSysMapBackend { +impl IoCopyReadable for IoSysMapBackend { #[inline] unsafe fn copy_from_io(view: Self::View<'_, [u8]>, buffer: *mut u8) { match view { @@ -1652,20 +1659,22 @@ unsafe fn copy_from_io(view: Self::View<'_, [u8]>, buffer: *mut u8) { } #[inline] - unsafe fn copy_to_io(view: Self::View<'_, [u8]>, buffer: *const u8) { + fn copy_read<T: FromBytes>(view: Self::View<'_, T>) -> T { match view { - // SAFETY: Per safety requirement. - IoSysMap::Io(l) => unsafe { MmioBackend::copy_to_io(l, buffer) }, - // SAFETY: Per safety requirement. - IoSysMap::Sys(r) => unsafe { SysMemBackend::copy_to_io(r, buffer) }, + IoSysMap::Io(l) => MmioBackend::copy_read(l), + IoSysMap::Sys(r) => SysMemBackend::copy_read(r), } } +} +impl IoCopyWritable for IoSysMapBackend { #[inline] - fn copy_read<T: FromBytes>(view: Self::View<'_, T>) -> T { + unsafe fn copy_to_io(view: Self::View<'_, [u8]>, buffer: *const u8) { match view { - IoSysMap::Io(l) => MmioBackend::copy_read(l), - IoSysMap::Sys(r) => SysMemBackend::copy_read(r), + // SAFETY: Per safety requirement. + IoSysMap::Io(l) => unsafe { MmioBackend::copy_to_io(l, buffer) }, + // SAFETY: Per safety requirement. + IoSysMap::Sys(r) => unsafe { SysMemBackend::copy_to_io(r, buffer) }, } } -- 2.56.0
