From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-yw1-f178.google.com (mail-yw1-f178.google.com [209.85.128.178]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 931394E5342 for ; Fri, 16 Oct 2026 15:48:34 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.178 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1792165717; cv=none; b=ZOArUT6V/3ZR3vIJyUUvujvfMiqGmk6OMs1pIX91RakSQ+ljoP2gyG4D2HiMU64OdjWBqKqq+1mj0mTPDAJ4biO61rCIOK2rMW+y1cbIKxtkqlXCNr8/u+awsR44rvP9QFtMyNi9XKOl4RzRDjFtBsNqqKg7oV6TKBb/uEojOFA= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1792165717; c=relaxed/simple; bh=17tedGYcRNdDnq1dKIJYkX8tB8XKf3YAkAWYjfskwm4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=cDXi4VW8LyFqfegUx0VrgJnxxiDo0DfFKRAuzcWA959EUR/YRQ5JFGsEWZtMUQlTCS8Ph/C5aBd3i8L894zfOAv0GNYS/Ff/q0+SFK7Xc640Vm6vEoO+79MffWPJwt282Vdl6DFeCyR4xjGqhu3dZntUTcnwKT9i6OJDSLGfrtA= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=E7XHSded; arc=none smtp.client-ip=209.85.128.178 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="E7XHSded" Received: by mail-yw1-f178.google.com with SMTP id 00721157ae682-8b09e07e149so534317b3.1 for ; Fri, 16 Oct 2026 08:48:34 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1792165713; x=1792770513; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=plcoVhgmwxTvzaBDkme5sEgwM7GIbrXBdBohLzMS+Gs=; b=E7XHSdedTdBbfvbXhK7qDQOcR00m0b8Q8VQmxbETZCxXEFgViVnzU7V+RRj8k4Osd+ KupMFLy1C5WlNrkcZ/M5q9pe+NTwG0hIsOHSCqvgAIKag44xFGHhrGDgLZbAl6J6Mzin WlkgtR0wNvZH+ydGIdAq3gQOPFyUFDlcb0xKYdKwXVNNF3nSiAiBIFkegMpTK74JNatp r9C8ae/QRAJ3sEHRDB8OKsLRgUeL2d0R8K2wcEAGjgRo24H0ZmwTxQquL7j165gl2dEx stnWS7aaeFeo6S74b2vrzgtO/Xbxlxnzge5kmqjP1Q/n1MP7ZZP6/I1iq9NIGBXziI/k bHmA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1792165713; x=1792770513; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=plcoVhgmwxTvzaBDkme5sEgwM7GIbrXBdBohLzMS+Gs=; b=Xf2wphO78HtovWfLTOzNxXh+GYeHrOY479ka63ZQcobNZTFgJX4kRUHQv1NbyD3VVC efj63XQ+hI8JSaKkYIUsAgsgVdI4iRV+rphr+Wdi6VhY3ilB+bUHYKOgjjxO9TrgrcC+ gNn3FX65wjlYIZEPrp2nZrJWg0UtAGmZPYoQ3qMZOkMlzyE2vu6KWl+n8NHRHd+rVGJc LSG1n7+3glwdq7L3oMn4pxv4B3PQqoENoCnbXYzEZahZbK2C7J95zYpadJNr1Y54wzcs YaHMjWm5Ljc+zPy1HkresdtpU6jX4pqrJNoDAmepfTresuVRKc4uZlaNCxxH/hQ8jl5m Tz3A== X-Forwarded-Encrypted: i=1; AKwUvBzOlwCIGQ/C7aqicGKMjrXiXqXvoZxxHY003K+RMwnt1Yn24xfD45SGB4J+SJdgcPZzmrMxPuScLXxgbyI=@vger.kernel.org X-Gm-Message-State: AFq9FYJanH3OU+QKcc1IIUWABoksdWiPOYxY5ueVHq1xCtS5BN7ZoYT6 I+JQGCOLYxqczmWmIxdbcgbOb0L9rmUsaJuCRwT/2gHCe37AiQkr5wOU X-Gm-Gg: AYBFou19LFOzsTGQDr6fQ5+yCJstTR2+ugohLxWGbBmEuFbnV3tWlEP0iS2mWDxM1Xy 94fbUskPKDufgw5SSdPEw9N+FNLsBXjgvxYKhYNyN75M/w4UWcxDDAUcAUNhC+nrWdteqZwXQp+ R6wpqz1DxAKcBPj3xSlnprYb3KfJHgXO1/5AcTLNGBcNkornNvO81UxWvfJihPsdNMHNPSCb+Ce eDrUq+INr5rk+2NV/re9uaZNFThdw40rjI8I6/h3v1LgCeNMQVnLn2FgaVlZAyi/WBwQPrMJA6O 0ZhpGkm1fQH35rJtHrN/dcHh3sFl0o3RBfs5CVXD/MGXoLJiDAtdNQTRdYUEPOjOlzjAJbKnupS u38I6RunN+zCCmjc4pDfCFsOFtPoywgpBLDu1iYCFrmTHLjmLrRpglEAgh+LsnO417Yyg2twfdr LM+1UNoUlNhr7BQJeWd2XDt+aqIjqoEUsAVTs5PnCpXwvmGAwfU1FwvP3yzG5k0E+SR+YOYiYGR R00mkcWBjEnYuxteotpH2OVlPaORzTwJRJrJ9c= X-Received: by 2002:a05:690c:e68e:b0:8b0:6617:e241 with SMTP id 00721157ae682-8b0f20752cfmr1168687b3.4.1792165713522; Fri, 16 Oct 2026 08:48:33 -0700 (PDT) Received: from localhost.localdomain ([180.243.241.21]) by smtp.gmail.com with ESMTPSA id 00721157ae682-8b0e593c65bsm10882167b3.38.2026.10.16.08.48.28 (version=TLS1_3 cipher=TLS_CHACHA20_POLY1305_SHA256 bits=256/256); Fri, 16 Oct 2026 08:48:33 -0700 (PDT) From: Muchamad Coirul Anwar To: Jonathan Cameron , Miguel Ojeda , Igor Korotin , Danilo Krummrich Cc: Alice Ryhl , Daniel Almeida , Lars-Peter Clausen , Mark Brown , Brandon StJohn , linux-iio@vger.kernel.org, linux-i2c@vger.kernel.org, rust-for-linux@vger.kernel.org, driver-core@lists.linux.dev, linux-kernel@vger.kernel.org Subject: [RFC PATCH v6 1/4] rust: io: add FallibleIoCapable Date: Fri, 16 Oct 2026 22:48:16 +0700 Message-ID: <20261016154819.17936-2-muchamadcoirulanwar@gmail.com> X-Mailer: git-send-email 2.50.0 In-Reply-To: <20261016154819.17936-1-muchamadcoirulanwar@gmail.com> References: <20261016154819.17936-1-muchamadcoirulanwar@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Add a fallible I/O capability for backends whose accesses may fail independently of address validation. Route try_read, try_write, try_write_reg, and try_update through the fallible capability. Provide a blanket implementation for infallible IoCapable backends so existing users retain their current behavior. This allows transport-backed implementations such as I2C to expose only fallible access while keeping infallible operations unavailable. Link: https://lore.kernel.org/all/DJVQ852J7SOH.26YBIJTQ9B66G@kernel.org/ Suggested-by: Danilo Krummrich Signed-off-by: Muchamad Coirul Anwar --- rust/kernel/io.rs | 66 +++++++++++++++++++++++++++++++++-------------- 1 file changed, 46 insertions(+), 20 deletions(-) diff --git a/rust/kernel/io.rs b/rust/kernel/io.rs index 95f46bb75f9e..516895ca2082 100644 --- a/rust/kernel/io.rs +++ b/rust/kernel/io.rs @@ -276,6 +276,36 @@ pub trait IoCapable: IoBackend { fn io_write<'a>(view: Self::View<'a, T>, value: T); } +/// Fallible counterpart of [`IoCapable`] for I/O backends where operations can fail at the +/// transport level (e.g. I2C, SPI). +/// +/// Infallible backends ([`IoCapable`] implementors) get this for free via blanket implementation. +/// Fallible-only backends implement this trait directly without implementing [`IoCapable`]; the +/// infallible [`Io::read`], [`Io::write`], and [`Io::update`] methods will then be unavailable, +/// enforcing that callers use the `try_*` variants instead. +pub trait FallibleIoCapable: IoBackend { + /// Performs an I/O read of type `T` at `view` and returns the result, or an error if the + /// transport-level operation fails. + fn io_try_read<'a>(view: Self::View<'a, T>) -> Result; + + /// Performs an I/O write of `value` at `view`, or returns an error if the transport-level + /// operation fails. + fn io_try_write<'a>(view: Self::View<'a, T>, value: T) -> Result; +} + +impl, T> FallibleIoCapable for B { + #[inline(always)] + fn io_try_read<'a>(view: Self::View<'a, T>) -> Result { + Ok(Self::io_read(view)) + } + + #[inline(always)] + fn io_try_write<'a>(view: Self::View<'a, T>, value: T) -> Result { + Self::io_write(view, value); + Ok(()) + } +} + /// Trait indicating that an I/O backend supports memory copy operations. pub trait IoCopyable: IoBackend { /// Copy contents of `view` to `buffer`. @@ -645,7 +675,7 @@ fn copy_to_slice(self, data: &mut [u8]) fn try_read8(self, offset: usize) -> Result where usize: IoLoc, - Self::Backend: IoCapable, + Self::Backend: FallibleIoCapable, { self.try_read(offset) } @@ -655,7 +685,7 @@ fn try_read8(self, offset: usize) -> Result fn try_read16(self, offset: usize) -> Result where usize: IoLoc, - Self::Backend: IoCapable, + Self::Backend: FallibleIoCapable, { self.try_read(offset) } @@ -665,7 +695,7 @@ fn try_read16(self, offset: usize) -> Result fn try_read32(self, offset: usize) -> Result where usize: IoLoc, - Self::Backend: IoCapable, + Self::Backend: FallibleIoCapable, { self.try_read(offset) } @@ -675,7 +705,7 @@ fn try_read32(self, offset: usize) -> Result fn try_read64(self, offset: usize) -> Result where usize: IoLoc, - Self::Backend: IoCapable, + Self::Backend: FallibleIoCapable, { self.try_read(offset) } @@ -685,7 +715,7 @@ fn try_read64(self, offset: usize) -> Result fn try_write8(self, value: u8, offset: usize) -> Result where usize: IoLoc, - Self::Backend: IoCapable, + Self::Backend: FallibleIoCapable, { self.try_write(offset, value) } @@ -695,7 +725,7 @@ fn try_write8(self, value: u8, offset: usize) -> Result fn try_write16(self, value: u16, offset: usize) -> Result where usize: IoLoc, - Self::Backend: IoCapable, + Self::Backend: FallibleIoCapable, { self.try_write(offset, value) } @@ -705,7 +735,7 @@ fn try_write16(self, value: u16, offset: usize) -> Result fn try_write32(self, value: u32, offset: usize) -> Result where usize: IoLoc, - Self::Backend: IoCapable, + Self::Backend: FallibleIoCapable, { self.try_write(offset, value) } @@ -715,7 +745,7 @@ fn try_write32(self, value: u32, offset: usize) -> Result fn try_write64(self, value: u64, offset: usize) -> Result where usize: IoLoc, - Self::Backend: IoCapable, + Self::Backend: FallibleIoCapable, { self.try_write(offset, value) } @@ -827,10 +857,10 @@ fn write64(self, value: u64, offset: usize) fn try_read(self, location: L) -> Result where L: IoLoc, - Self::Backend: IoCapable, + Self::Backend: FallibleIoCapable, { let view = io_view::(self, location.offset())?; - Ok(Self::Backend::io_read(view).into()) + Ok(Self::Backend::io_try_read(view)?.into()) } /// Generic fallible write with runtime bounds check. @@ -860,12 +890,11 @@ fn try_read(self, location: L) -> Result fn try_write(self, location: L, value: T) -> Result where L: IoLoc, - Self::Backend: IoCapable, + Self::Backend: FallibleIoCapable, { let view = io_view::(self, location.offset())?; let io_value = value.into(); - Self::Backend::io_write(view, io_value); - Ok(()) + Self::Backend::io_try_write(view, io_value) } /// Generic fallible write of a fully-located register value. @@ -905,7 +934,7 @@ fn try_write_reg(self, value: V) -> Result where L: IoLoc, V: LocatedRegister, - Self::Backend: IoCapable, + Self::Backend: FallibleIoCapable, { let (location, value) = value.into_io_op(); @@ -938,16 +967,13 @@ fn try_write_reg(self, value: V) -> Result fn try_update(self, location: L, f: F) -> Result where L: IoLoc, - Self::Backend: IoCapable, + Self::Backend: FallibleIoCapable, F: FnOnce(T) -> T, { let view = io_view::(self, location.offset())?; - - let value: T = Self::Backend::io_read(view).into(); + let value: T = Self::Backend::io_try_read(view)?.into(); let io_value = f(value).into(); - Self::Backend::io_write(view, io_value); - - Ok(()) + Self::Backend::io_try_write(view, io_value) } /// Generic infallible read with compile-time bounds check. -- 2.50.0