[PATCH 01/12] rust: io: add Region::try_subregion

Eliot Courtney <[email protected]> Wed, 05 Aug 2026 14:44:48 +0900
Newsgroups gmane.linux.documentation,gmane.linux.kernel.rust,gmane.linux.kernel,gmane.comp.video.dri.devel
Message-ID <[email protected]>
Add a helper to get a subregion of an IO view fallibly.

Signed-off-by: Eliot Courtney <[email protected]>
---
 rust/kernel/io.rs | 31 ++++++++++++++++++++++++++++++-
 1 file changed, 30 insertions(+), 1 deletion(-)

diff --git a/rust/kernel/io.rs b/rust/kernel/io.rs
index 95f46bb75f9e..85fbdcc50c8f 100644
--- a/rust/kernel/io.rs
+++ b/rust/kernel/io.rs
@@ -6,7 +6,8 @@
 
 use core::{
     marker::PhantomData,
-    mem::MaybeUninit, //
+    mem::MaybeUninit,
+    ops::Range, //
 };
 
 use crate::{
@@ -80,6 +81,34 @@ pub fn ptr_try_from_raw_parts_mut(base: *mut u8, size: usize) -> Result<*mut Sel
 
         Ok(Self::ptr_from_raw_parts_mut(base, size))
     }
+
+    /// Try to create a subregion of `io` at the given range.
+    ///
+    /// Runtime checks that `range` is within this region, is at least as large as the given new
+    /// minimum size `NEW_SIZE`, and that [`Region`]'s alignment requirements are satisfied.
+    #[inline]
+    pub fn try_subregion<'a, const NEW_SIZE: usize, IO>(
+        io: IO,
+        range: Range<usize>,
+    ) -> Result<<IO::Backend as IoBackend>::View<'a, Region<NEW_SIZE>>>
+    where
+        IO: IoBase<'a, Target = Self>,
+    {
+        let view = io.as_view();
+        let ptr = IO::Backend::as_ptr(view);
+
+        let size = KnownSize::size(ptr);
+        if range.start > size || range.end > size {
+            return Err(EINVAL);
+        }
+        let region = Region::ptr_try_from_raw_parts_mut(
+            ptr.cast::<u8>().wrapping_add(range.start),
+            range.len(),
+        )?;
+
+        // SAFETY: We have checked bounds and alignment, so this is a valid projection.
+        Ok(unsafe { IO::Backend::project_view(view, region) })
+    }
 }
 
 impl<const SIZE: usize> KnownSize for Region<SIZE> {

-- 
2.55.0