From nobody Mon Jun 8 22:51:08 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4F3343955E6; Mon, 25 May 2026 20:29:38 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779740979; cv=none; b=N8kfUvcr/WsIaWH9yXapJ3nLLDcGhE9z47zLxYeWME1ReglL0/qPAT5e5njw8N60QqjIv2U/wy1I+0WWquyY7xhdD3Y+z7E2xqs/mBKZJ2rS0r2BHHqUyCs/2lLX7S8wway3JH+FLSZEW73QeVjYx/0AarZQ9XzhssUo5MT8RBs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779740979; c=relaxed/simple; bh=rAFNx8RypDYKG+dpWgDHjGVQ/4vHb+Tv98qyCpRhLTw=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=OtApthCnN2jF7iIs58cVVjRQmcfIzIUhBKcyj0tiZXZ34uStzvQUSc7Y/Daeujy7HPQ+JnWdBme9qE1hTRB+VLLiGiHI71l2xeCFQHOG8GsHoZ31R534uGIUBxV6BxVbcunmTyQYXPzSaagnN4PVGTA0KI2GkKgIzN67vQFNaWY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=QSgKPNc+; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="QSgKPNc+" Received: by smtp.kernel.org (Postfix) with ESMTPSA id DD7E81F00A3A; Mon, 25 May 2026 20:29:30 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1779740978; bh=f29QOiLOmTtepPqGTyUIO0rU++hJKbjbxryGjGLUDYY=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=QSgKPNc+JoRjxcpaHyht4zv1jP+wZg3OUncC/d7JZRePkLU6NHmtZSEMDQb/QPWct GC9fW/BK9+kX9xOJtJ8M5dqXJYz9pte2/JD4eyCF16z9U3H13hkrsyqNN5dwmuG1f8 TmSVS0dtRu1Hzt2fUn6Ibro2kAlCFH4xfrxqSTmnRwkHxL2qvzJmEl4oLgc3/CGBwA DxDk4mTWDwYVGItXOj8QDkK6pN+snuv1e9ECsoWqGa8SXd5mTfBXhBO3xMV+kcHwdD PLwi7aMRYda8UA46SspnWMp2Z9WMz2eLc+2BHNjOcsNmA4vj6p6j6qfaH1V44+RmQn VvuK2ddEc9WhQ== From: Danilo Krummrich To: gregkh@linuxfoundation.org, rafael@kernel.org, acourbot@nvidia.com, aliceryhl@google.com, david.m.ertman@intel.com, ira.weiny@intel.com, leon@kernel.org, viresh.kumar@linaro.org, m.wilczynski@samsung.com, ukleinek@kernel.org, bhelgaas@google.com, kwilczynski@kernel.org, abdiel.janulgue@gmail.com, robin.murphy@arm.com, markus.probst@posteo.de, ojeda@kernel.org, boqun@kernel.org, gary@garyguo.net, bjorn3_gh@protonmail.com, lossin@kernel.org, a.hindborg@kernel.org, tmgross@umich.edu, igor.korotin@linux.dev, daniel.almeida@collabora.com, pcolberg@redhat.com Cc: driver-core@lists.linux.dev, linux-kernel@vger.kernel.org, nova-gpu@lists.linux.dev, dri-devel@lists.freedesktop.org, linux-pm@vger.kernel.org, linux-pwm@vger.kernel.org, linux-pci@vger.kernel.org, rust-for-linux@vger.kernel.org, Danilo Krummrich , stable@vger.kernel.org, Sashiko Subject: [PATCH v5 01/24] rust: pci: use 'static lifetime for PCI BAR resource names Date: Mon, 25 May 2026 22:20:48 +0200 Message-ID: <20260525202921.124698-2-dakr@kernel.org> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260525202921.124698-1-dakr@kernel.org> References: <20260525202921.124698-1-dakr@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" pci_request_region() stores the name pointer directly in struct resource; use &'static CStr to ensure the pointer remains valid even if the Bar is leaked. Cc: stable@vger.kernel.org Reported-by: Sashiko Closes: https://lore.kernel.org/all/20260522004943.CDA7C1F000E9@smtp.kernel= .org/ Fixes: 3c2e31d717ac ("rust: pci: move I/O infrastructure to separate file") Signed-off-by: Danilo Krummrich Reviewed-by: Alexandre Courbot Reviewed-by: Eliot Courtney Reviewed-by: Gary Guo --- rust/kernel/pci/io.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/rust/kernel/pci/io.rs b/rust/kernel/pci/io.rs index ae78676c927f..3ce21482b079 100644 --- a/rust/kernel/pci/io.rs +++ b/rust/kernel/pci/io.rs @@ -153,7 +153,7 @@ pub struct Bar { } =20 impl Bar { - pub(super) fn new(pdev: &Device, num: u32, name: &CStr) -> Result { + pub(super) fn new(pdev: &Device, num: u32, name: &'static CStr) -> Res= ult { let len =3D pdev.resource_len(num)?; if len =3D=3D 0 { return Err(ENOMEM); @@ -252,7 +252,7 @@ impl Device { pub fn iomap_region_sized<'a, const SIZE: usize>( &'a self, bar: u32, - name: &'a CStr, + name: &'static CStr, ) -> impl PinInit>, Error> + 'a { Devres::new(self.as_ref(), Bar::::new(self, bar, name)) } @@ -261,7 +261,7 @@ pub fn iomap_region_sized<'a, const SIZE: usize>( pub fn iomap_region<'a>( &'a self, bar: u32, - name: &'a CStr, + name: &'static CStr, ) -> impl PinInit, Error> + 'a { self.iomap_region_sized::<0>(bar, name) } --=20 2.54.0 From nobody Mon Jun 8 22:51:08 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6830228E0; Mon, 25 May 2026 20:29:45 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779740986; cv=none; b=mx5dz4nE90lmSevnnVfiG35OhWgR8z33he8PHJIZaqnHjjQO7oiOMVa1jp2FqiGrmrRaidwtE2hRFfo3xJrQ0nZoYRhdQjX6wj8Jwd9HphNkfwTaRbNO1ukwRL/EFekTiRMrrrmS1zyRCb5GzxErjhdTcO+TEktJURZd9BvaqP8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779740986; c=relaxed/simple; bh=4BLgZuFs8LVFNWq+TMoAP1f22BiBhWxaI/2axMWi1ec=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=i4Dq97Lra34k5LGoiAlKJfgIpOwd/4sqwFFrDF+FxXF7ON4jmJnzBRNIBCHuqwDYKOxR9Wnl0KTkq0wm62w4KzhxIPe3yMJIsIm0WmA8/Fwxu19/B/ZJyKV++0swwuGQ+zVKds2qirzMqzfT5BMH4T2howfziyPAm4ozNG6xVV4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=KpduoAIr; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="KpduoAIr" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 66C501F000E9; Mon, 25 May 2026 20:29:38 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1779740985; bh=CvsWKx5YQe9ahMUZVvp0ojIrus3es8Io68N4EoQNks0=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=KpduoAIr0LeDIRVPVRU0Ks2uAUTfj4bIY+YARKxe/qUadknx+sc+/0ys/MCuAtH8o 9x/F+Y4eIJ/pvHBzJXMO/VVPJJYiIR98t6JGsQdGfkyaPLSBMn50p8p94E4PqKu30d N5/tDY5d+OTB7CgA+rde2mus8bXXYpCImZqkEI09XT5Tophca2IJUAoMsx1J1wxILm ovpLRaYvuq1C9zDYFN53npOxUuu28YK2DD5sB1sU3eXWP02BmHnUEp5osWhtajC2IQ J7tGd39Qbd1XlaxcPt7EvDPsvCQuFs5knqcLU+qv3q1LrLMCa7VMkcX8eCKNz3YOoX kNEtI26E5U9XA== From: Danilo Krummrich To: gregkh@linuxfoundation.org, rafael@kernel.org, acourbot@nvidia.com, aliceryhl@google.com, david.m.ertman@intel.com, ira.weiny@intel.com, leon@kernel.org, viresh.kumar@linaro.org, m.wilczynski@samsung.com, ukleinek@kernel.org, bhelgaas@google.com, kwilczynski@kernel.org, abdiel.janulgue@gmail.com, robin.murphy@arm.com, markus.probst@posteo.de, ojeda@kernel.org, boqun@kernel.org, gary@garyguo.net, bjorn3_gh@protonmail.com, lossin@kernel.org, a.hindborg@kernel.org, tmgross@umich.edu, igor.korotin@linux.dev, daniel.almeida@collabora.com, pcolberg@redhat.com Cc: driver-core@lists.linux.dev, linux-kernel@vger.kernel.org, nova-gpu@lists.linux.dev, dri-devel@lists.freedesktop.org, linux-pm@vger.kernel.org, linux-pwm@vger.kernel.org, linux-pci@vger.kernel.org, rust-for-linux@vger.kernel.org, Danilo Krummrich Subject: [PATCH v5 02/24] rust: alloc: remove `'static` bound on `ForeignOwnable` Date: Mon, 25 May 2026 22:20:49 +0200 Message-ID: <20260525202921.124698-3-dakr@kernel.org> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260525202921.124698-1-dakr@kernel.org> References: <20260525202921.124698-1-dakr@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Gary Guo The `'static` bound is currently necessary because there's no restriction on the lifetime of the GAT. Add a `Self: 'a` bound to restrict possible lifetimes on `Borrowed` and `BorrowedMut`, and lift the `'static` requirement. Reviewed-by: Alexandre Courbot Reviewed-by: Greg Kroah-Hartman Signed-off-by: Gary Guo Signed-off-by: Danilo Krummrich Acked-by: Miguel Ojeda --- rust/kernel/alloc/kbox.rs | 24 ++++++++++++++++++------ rust/kernel/types.rs | 8 ++++++-- 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/rust/kernel/alloc/kbox.rs b/rust/kernel/alloc/kbox.rs index c824ed6e1523..2f8c16473c2c 100644 --- a/rust/kernel/alloc/kbox.rs +++ b/rust/kernel/alloc/kbox.rs @@ -477,7 +477,7 @@ fn try_init(init: impl Init, flags: Flags) -> = Result =20 // SAFETY: The pointer returned by `into_foreign` comes from a well aligned // pointer to `T` allocated by `A`. -unsafe impl ForeignOwnable for Box +unsafe impl ForeignOwnable for Box where A: Allocator, { @@ -487,8 +487,14 @@ unsafe impl ForeignOwnable for Box core::mem::align_of::() }; =20 - type Borrowed<'a> =3D &'a T; - type BorrowedMut<'a> =3D &'a mut T; + type Borrowed<'a> + =3D &'a T + where + Self: 'a; + type BorrowedMut<'a> + =3D &'a mut T + where + Self: 'a; =20 fn into_foreign(self) -> *mut c_void { Box::into_raw(self).cast() @@ -516,13 +522,19 @@ unsafe fn borrow_mut<'a>(ptr: *mut c_void) -> &'a mut= T { =20 // SAFETY: The pointer returned by `into_foreign` comes from a well aligned // pointer to `T` allocated by `A`. -unsafe impl ForeignOwnable for Pin> +unsafe impl ForeignOwnable for Pin> where A: Allocator, { const FOREIGN_ALIGN: usize =3D as ForeignOwnable>::FOREIGN_= ALIGN; - type Borrowed<'a> =3D Pin<&'a T>; - type BorrowedMut<'a> =3D Pin<&'a mut T>; + type Borrowed<'a> + =3D Pin<&'a T> + where + Self: 'a; + type BorrowedMut<'a> + =3D Pin<&'a mut T> + where + Self: 'a; =20 fn into_foreign(self) -> *mut c_void { // SAFETY: We are still treating the box as pinned. diff --git a/rust/kernel/types.rs b/rust/kernel/types.rs index 4329d3c2c2e5..9cf9f869d195 100644 --- a/rust/kernel/types.rs +++ b/rust/kernel/types.rs @@ -27,10 +27,14 @@ pub unsafe trait ForeignOwnable: Sized { const FOREIGN_ALIGN: usize; =20 /// Type used to immutably borrow a value that is currently foreign-ow= ned. - type Borrowed<'a>; + type Borrowed<'a> + where + Self: 'a; =20 /// Type used to mutably borrow a value that is currently foreign-owne= d. - type BorrowedMut<'a>; + type BorrowedMut<'a> + where + Self: 'a; =20 /// Converts a Rust-owned object to a foreign-owned one. /// --=20 2.54.0 From nobody Mon Jun 8 22:51:08 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7F12B3955F4; Mon, 25 May 2026 20:29:52 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779740994; cv=none; b=SO8wuX79oV6/IAnZrisggGRFiOD7NzvCCNoZZXHkaUaIqHfHNKTFApVVe9C6eANgdGqW8MU0kE6DINs6IaO3GxlbWCtwxl3XicjPy2wnmR5iwgdw2m8hPnwNS9oPxsZVzbBXmKoq6PmIpUblN3BK1bX5cgMWJbDmKsFVKAPB8vA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779740994; c=relaxed/simple; bh=rwZCAFhELeLtNLK+r5w4aR9OO0te4hTnjkDHRM+FM+k=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=FKPn7EyOAo0V2aW9jS0JEBQxHR19oDzwjAMlc5XjEn8m7C8ptDeaGR/mtgChuYRzw3pAEqSiYtAO2+vCHemRXukq6WEF1C6iDKLmogsTxO1p/dxofFS0QPDNNpw5RHmBVKqs3Jmp7o+gwXO0xBq0XFbOX8BBqCYnT/o5DisGv40= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=FQgWIuLc; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="FQgWIuLc" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 8861E1F00A3A; Mon, 25 May 2026 20:29:45 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1779740992; bh=lvGrU2igniPCHmh11/tYEXfXrdYrMryxZKMyGL+/290=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=FQgWIuLcqzfeCCHmIIWiu4svdtEx6DRpx8wc/PAzclgcYHSPoA3CW1KcEfwiUS8qF MFDlh+iDHbL0We6CJvw7I2uJiJkyNDsV1ZozSSVDWTv5kjY3TOYCXC6I9b4aH2XB10 2ha24xUL8YEMoj0wF0KmZD85J02SB3MfHRvS0n8qAiNRdTV100GFngVjL5gPQ6T33S UIplVxrFk8EciZVch2zFuv1Ftr5thahR5ijddUNZBXF9pK+jmAtG8Okw3D2/NS7tUS W51+b155b8K3MV6yVqxdNOB8xOXVEcBmO4RRghzqq8bGtR85e0/VF+fBa3SUmjvvH3 hGZeB39papaKA== From: Danilo Krummrich To: gregkh@linuxfoundation.org, rafael@kernel.org, acourbot@nvidia.com, aliceryhl@google.com, david.m.ertman@intel.com, ira.weiny@intel.com, leon@kernel.org, viresh.kumar@linaro.org, m.wilczynski@samsung.com, ukleinek@kernel.org, bhelgaas@google.com, kwilczynski@kernel.org, abdiel.janulgue@gmail.com, robin.murphy@arm.com, markus.probst@posteo.de, ojeda@kernel.org, boqun@kernel.org, gary@garyguo.net, bjorn3_gh@protonmail.com, lossin@kernel.org, a.hindborg@kernel.org, tmgross@umich.edu, igor.korotin@linux.dev, daniel.almeida@collabora.com, pcolberg@redhat.com Cc: driver-core@lists.linux.dev, linux-kernel@vger.kernel.org, nova-gpu@lists.linux.dev, dri-devel@lists.freedesktop.org, linux-pm@vger.kernel.org, linux-pwm@vger.kernel.org, linux-pci@vger.kernel.org, rust-for-linux@vger.kernel.org, Danilo Krummrich Subject: [PATCH v5 03/24] rust: driver: move 'static bounds to constructor Date: Mon, 25 May 2026 22:20:50 +0200 Message-ID: <20260525202921.124698-4-dakr@kernel.org> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260525202921.124698-1-dakr@kernel.org> References: <20260525202921.124698-1-dakr@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Gary Guo With the ForeignOwnable lifetime change, the 'static bound is no longer necessary on the drvdata methods or bus adapter impls. Move it to the Registration constructor instead. Reviewed-by: Alexandre Courbot Reviewed-by: Greg Kroah-Hartman Signed-off-by: Gary Guo Co-developed-by: Danilo Krummrich Signed-off-by: Danilo Krummrich --- rust/kernel/auxiliary.rs | 6 +++--- rust/kernel/device.rs | 8 ++++---- rust/kernel/driver.rs | 7 +++++-- rust/kernel/i2c.rs | 8 ++++---- rust/kernel/pci.rs | 6 +++--- rust/kernel/platform.rs | 8 ++++---- rust/kernel/usb.rs | 6 +++--- 7 files changed, 26 insertions(+), 23 deletions(-) diff --git a/rust/kernel/auxiliary.rs b/rust/kernel/auxiliary.rs index 19aec94aa95b..35b44d194f67 100644 --- a/rust/kernel/auxiliary.rs +++ b/rust/kernel/auxiliary.rs @@ -44,7 +44,7 @@ // - `T` is the type of the driver's device private data. // - `struct auxiliary_driver` embeds a `struct device_driver`. // - `DEVICE_DRIVER_OFFSET` is the correct byte offset to the embedded `st= ruct device_driver`. -unsafe impl driver::DriverLayout for Adapter { +unsafe impl driver::DriverLayout for Adapter { type DriverType =3D bindings::auxiliary_driver; type DriverData =3D T; const DEVICE_DRIVER_OFFSET: usize =3D core::mem::offset_of!(Self::Driv= erType, driver); @@ -52,7 +52,7 @@ unsafe impl driver::DriverLayout for= Adapter { =20 // SAFETY: A call to `unregister` for a given instance of `DriverType` is = guaranteed to be valid if // a preceding call to `register` has been successful. -unsafe impl driver::RegistrationOps for Adapter { +unsafe impl driver::RegistrationOps for Adapter { unsafe fn register( adrv: &Opaque, name: &'static CStr, @@ -78,7 +78,7 @@ unsafe fn unregister(adrv: &Opaque) { } } =20 -impl Adapter { +impl Adapter { extern "C" fn probe_callback( adev: *mut bindings::auxiliary_device, id: *const bindings::auxiliary_device_id, diff --git a/rust/kernel/device.rs b/rust/kernel/device.rs index fd50399aadea..5df8fa108a52 100644 --- a/rust/kernel/device.rs +++ b/rust/kernel/device.rs @@ -203,7 +203,7 @@ pub unsafe fn as_bound(&self) -> &Device { =20 impl Device { /// Store a pointer to the bound driver's private data. - pub fn set_drvdata(&self, data: impl PinInit) ->= Result { + pub fn set_drvdata(&self, data: impl PinInit) -> Result { let data =3D KBox::pin_init(data, GFP_KERNEL)?; =20 // SAFETY: By the type invariants, `self.as_raw()` is a valid poin= ter to a `struct device`. @@ -218,7 +218,7 @@ pub fn set_drvdata(&self, data: impl PinIni= t) -> Result { /// /// - The type `T` must match the type of the `ForeignOwnable` previou= sly stored by /// [`Device::set_drvdata`]. - pub(crate) unsafe fn drvdata_obtain(&self) -> Option>> { + pub(crate) unsafe fn drvdata_obtain(&self) -> Option>> { // SAFETY: By the type invariants, `self.as_raw()` is a valid poin= ter to a `struct device`. let ptr =3D unsafe { bindings::dev_get_drvdata(self.as_raw()) }; =20 @@ -244,7 +244,7 @@ pub(crate) unsafe fn drvdata_obtain(&self) = -> Option>> { /// device is fully unbound. /// - The type `T` must match the type of the `ForeignOwnable` previou= sly stored by /// [`Device::set_drvdata`]. - pub unsafe fn drvdata_borrow(&self) -> Pin<&T> { + pub unsafe fn drvdata_borrow(&self) -> Pin<&T> { // SAFETY: `drvdata_unchecked()` has the exact same safety require= ments as the ones // required by this method. unsafe { self.drvdata_unchecked() } @@ -260,7 +260,7 @@ impl Device { /// the device is fully unbound. /// - The type `T` must match the type of the `ForeignOwnable` previou= sly stored by /// [`Device::set_drvdata`]. - unsafe fn drvdata_unchecked(&self) -> Pin<&T> { + unsafe fn drvdata_unchecked(&self) -> Pin<&T> { // SAFETY: By the type invariants, `self.as_raw()` is a valid poin= ter to a `struct device`. let ptr =3D unsafe { bindings::dev_get_drvdata(self.as_raw()) }; =20 diff --git a/rust/kernel/driver.rs b/rust/kernel/driver.rs index 36de8098754d..c8406dc4da60 100644 --- a/rust/kernel/driver.rs +++ b/rust/kernel/driver.rs @@ -181,7 +181,7 @@ unsafe impl Sync for Registration {} // any thread, so `Registration` is `Send`. unsafe impl Send for Registration {} =20 -impl Registration { +impl Registration { extern "C" fn post_unbind_callback(dev: *mut bindings::device) { // SAFETY: The driver core only ever calls the post unbind callbac= k with a valid pointer to // a `struct device`. @@ -215,7 +215,10 @@ fn callbacks_attach(drv: &Opaque) { } =20 /// Creates a new instance of the registration object. - pub fn new(name: &'static CStr, module: &'static ThisModule) -> impl P= inInit { + pub fn new(name: &'static CStr, module: &'static ThisModule) -> impl P= inInit + where + T: 'static, + { try_pin_init!(Self { reg <- Opaque::try_ffi_init(|ptr: *mut T::DriverType| { // SAFETY: `try_ffi_init` guarantees that `ptr` is valid f= or write. diff --git a/rust/kernel/i2c.rs b/rust/kernel/i2c.rs index 7b908f0c5a58..4ccee4ba4f23 100644 --- a/rust/kernel/i2c.rs +++ b/rust/kernel/i2c.rs @@ -96,7 +96,7 @@ macro_rules! i2c_device_table { // - `T` is the type of the driver's device private data. // - `struct i2c_driver` embeds a `struct device_driver`. // - `DEVICE_DRIVER_OFFSET` is the correct byte offset to the embedded `st= ruct device_driver`. -unsafe impl driver::DriverLayout for Adapter { +unsafe impl driver::DriverLayout for Adapter { type DriverType =3D bindings::i2c_driver; type DriverData =3D T; const DEVICE_DRIVER_OFFSET: usize =3D core::mem::offset_of!(Self::Driv= erType, driver); @@ -104,7 +104,7 @@ unsafe impl driver::DriverLayout f= or Adapter { =20 // SAFETY: A call to `unregister` for a given instance of `DriverType` is = guaranteed to be valid if // a preceding call to `register` has been successful. -unsafe impl driver::RegistrationOps for Adapter { +unsafe impl driver::RegistrationOps for Adapter { unsafe fn register( idrv: &Opaque, name: &'static CStr, @@ -151,7 +151,7 @@ unsafe fn unregister(idrv: &Opaque) { } } =20 -impl Adapter { +impl Adapter { extern "C" fn probe_callback(idev: *mut bindings::i2c_client) -> kerne= l::ffi::c_int { // SAFETY: The I2C bus only ever calls the probe callback with a v= alid pointer to a // `struct i2c_client`. @@ -222,7 +222,7 @@ fn i2c_id_info(dev: &I2cClient) -> Option<&'static ::Id } } =20 -impl driver::Adapter for Adapter { +impl driver::Adapter for Adapter { type IdInfo =3D T::IdInfo; =20 fn of_id_table() -> Option> { diff --git a/rust/kernel/pci.rs b/rust/kernel/pci.rs index af74ddff6114..17a33819dc0a 100644 --- a/rust/kernel/pci.rs +++ b/rust/kernel/pci.rs @@ -62,7 +62,7 @@ // - `T` is the type of the driver's device private data. // - `struct pci_driver` embeds a `struct device_driver`. // - `DEVICE_DRIVER_OFFSET` is the correct byte offset to the embedded `st= ruct device_driver`. -unsafe impl driver::DriverLayout for Adapter { +unsafe impl driver::DriverLayout for Adapter { type DriverType =3D bindings::pci_driver; type DriverData =3D T; const DEVICE_DRIVER_OFFSET: usize =3D core::mem::offset_of!(Self::Driv= erType, driver); @@ -70,7 +70,7 @@ unsafe impl driver::DriverLayout for= Adapter { =20 // SAFETY: A call to `unregister` for a given instance of `DriverType` is = guaranteed to be valid if // a preceding call to `register` has been successful. -unsafe impl driver::RegistrationOps for Adapter { +unsafe impl driver::RegistrationOps for Adapter { unsafe fn register( pdrv: &Opaque, name: &'static CStr, @@ -96,7 +96,7 @@ unsafe fn unregister(pdrv: &Opaque) { } } =20 -impl Adapter { +impl Adapter { extern "C" fn probe_callback( pdev: *mut bindings::pci_dev, id: *const bindings::pci_device_id, diff --git a/rust/kernel/platform.rs b/rust/kernel/platform.rs index 8917d4ee499f..c7a3dcdde3b1 100644 --- a/rust/kernel/platform.rs +++ b/rust/kernel/platform.rs @@ -48,7 +48,7 @@ // - `T` is the type of the driver's device private data. // - `struct platform_driver` embeds a `struct device_driver`. // - `DEVICE_DRIVER_OFFSET` is the correct byte offset to the embedded `st= ruct device_driver`. -unsafe impl driver::DriverLayout for Adapter { +unsafe impl driver::DriverLayout for Adapter { type DriverType =3D bindings::platform_driver; type DriverData =3D T; const DEVICE_DRIVER_OFFSET: usize =3D core::mem::offset_of!(Self::Driv= erType, driver); @@ -56,7 +56,7 @@ unsafe impl driver::DriverLayout for= Adapter { =20 // SAFETY: A call to `unregister` for a given instance of `DriverType` is = guaranteed to be valid if // a preceding call to `register` has been successful. -unsafe impl driver::RegistrationOps for Adapter { +unsafe impl driver::RegistrationOps for Adapter { unsafe fn register( pdrv: &Opaque, name: &'static CStr, @@ -91,7 +91,7 @@ unsafe fn unregister(pdrv: &Opaque) { } } =20 -impl Adapter { +impl Adapter { extern "C" fn probe_callback(pdev: *mut bindings::platform_device) -> = kernel::ffi::c_int { // SAFETY: The platform bus only ever calls the probe callback wit= h a valid pointer to a // `struct platform_device`. @@ -124,7 +124,7 @@ extern "C" fn remove_callback(pdev: *mut bindings::plat= form_device) { } } =20 -impl driver::Adapter for Adapter { +impl driver::Adapter for Adapter { type IdInfo =3D T::IdInfo; =20 fn of_id_table() -> Option> { diff --git a/rust/kernel/usb.rs b/rust/kernel/usb.rs index 9c17a672cd27..3f62da585281 100644 --- a/rust/kernel/usb.rs +++ b/rust/kernel/usb.rs @@ -39,7 +39,7 @@ // - `T` is the type of the driver's device private data. // - `struct usb_driver` embeds a `struct device_driver`. // - `DEVICE_DRIVER_OFFSET` is the correct byte offset to the embedded `st= ruct device_driver`. -unsafe impl driver::DriverLayout for Adapter { +unsafe impl driver::DriverLayout for Adapter { type DriverType =3D bindings::usb_driver; type DriverData =3D T; const DEVICE_DRIVER_OFFSET: usize =3D core::mem::offset_of!(Self::Driv= erType, driver); @@ -47,7 +47,7 @@ unsafe impl driver::DriverLayout for= Adapter { =20 // SAFETY: A call to `unregister` for a given instance of `DriverType` is = guaranteed to be valid if // a preceding call to `register` has been successful. -unsafe impl driver::RegistrationOps for Adapter { +unsafe impl driver::RegistrationOps for Adapter { unsafe fn register( udrv: &Opaque, name: &'static CStr, @@ -73,7 +73,7 @@ unsafe fn unregister(udrv: &Opaque) { } } =20 -impl Adapter { +impl Adapter { extern "C" fn probe_callback( intf: *mut bindings::usb_interface, id: *const bindings::usb_device_id, --=20 2.54.0 From nobody Mon Jun 8 22:51:08 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E19E83955F4; Mon, 25 May 2026 20:29:59 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779741002; cv=none; b=nAJbQDqUk1Agtm/OCaA79xooWnkKzlJAAdXFSQ07po1SxXwaeNfJ3wdh+0ejEYkwcDzkVfOIbbHUZ058dceGaml6OUwvNeePgH8Lp0SEu2qc8dS8TqiyY55uBCiTZDc9n6NrtkaSk2GP/ftzoZIrjlnYmyhJ9syRfVl4ygTEd8g= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779741002; c=relaxed/simple; bh=jsxWW33MlkwtfKju181aNOljKAsUse2QnDaSAaJDcxo=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=LNtNYML71Gxgd6obO4+FMWzN0UstbbvC96qx7fTD3pL2rPB4Kb2z7ds+x6cGICOMtOzMv1xyrzo3w28/sjsoqfk7rCjNi7LRxGDwPuxmj+JXaccfhHg26im9pDGn6V3VgzfgYjmkLnlD//IrleRpZ/aGub8i6v6BwctMx5vV3hU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=jnPwiRC3; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="jnPwiRC3" Received: by smtp.kernel.org (Postfix) with ESMTPSA id A9CEB1F000E9; Mon, 25 May 2026 20:29:52 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1779740999; bh=0iP7sZBb9E3qme6lvOuUvj+4Ge60LO6CjY0iXVsayTQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=jnPwiRC3VhnkYbmCyxSNqxITPLRYMJg6ARNiA5Mu1Csy+7gL49EVAMdfm1L9I2iCx SPF7p/Tz354db6t7yTyCP9px92hYwavYPkbWgESUrBESucS103D2QtDAiOQBtGfIHB iyASSyRaUn0Q2r2teGtPPHnBPzspy7LozKSFnFaNTOXtQjKXi99pck+0xwH81sSF7e Ce2ONE94Xh4zLGQyXZL+AdqK0uiO/air8u2Y883Ce8ZbdxzXHS3EfNuQy06boftZct Lj4DopGMEV8hVvdcA5W9lJ1OVVQpsNJ30w8ieEWC6v9vCRcJFCDyz3C0BMJtEusu5N ++P/j+/rFtWvw== From: Danilo Krummrich To: gregkh@linuxfoundation.org, rafael@kernel.org, acourbot@nvidia.com, aliceryhl@google.com, david.m.ertman@intel.com, ira.weiny@intel.com, leon@kernel.org, viresh.kumar@linaro.org, m.wilczynski@samsung.com, ukleinek@kernel.org, bhelgaas@google.com, kwilczynski@kernel.org, abdiel.janulgue@gmail.com, robin.murphy@arm.com, markus.probst@posteo.de, ojeda@kernel.org, boqun@kernel.org, gary@garyguo.net, bjorn3_gh@protonmail.com, lossin@kernel.org, a.hindborg@kernel.org, tmgross@umich.edu, igor.korotin@linux.dev, daniel.almeida@collabora.com, pcolberg@redhat.com Cc: driver-core@lists.linux.dev, linux-kernel@vger.kernel.org, nova-gpu@lists.linux.dev, dri-devel@lists.freedesktop.org, linux-pm@vger.kernel.org, linux-pwm@vger.kernel.org, linux-pci@vger.kernel.org, rust-for-linux@vger.kernel.org, Danilo Krummrich Subject: [PATCH v5 04/24] rust: driver: decouple driver private data from driver type Date: Mon, 25 May 2026 22:20:51 +0200 Message-ID: <20260525202921.124698-5-dakr@kernel.org> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260525202921.124698-1-dakr@kernel.org> References: <20260525202921.124698-1-dakr@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add a type Data<'bound> associated type to all bus driver traits, decoupling the driver's bus device private data type from the driver struct itself. In the context of adding a 'bound lifetime, making this an associated type has the advantage that it allows us to avoid a driver trait global lifetime and it avoids the need for ForLt for bus device private data; both of which make the subsequent implementation by buses much simpler. All existing drivers and doc examples set type Data =3D Self to preserve the current behavior. Reviewed-by: Alexandre Courbot Reviewed-by: Gary Guo Reviewed-by: Greg Kroah-Hartman Signed-off-by: Danilo Krummrich --- drivers/cpufreq/rcpufreq_dt.rs | 1 + drivers/gpu/drm/nova/driver.rs | 1 + drivers/gpu/drm/tyr/driver.rs | 1 + drivers/gpu/nova-core/driver.rs | 1 + drivers/pwm/pwm_th1520.rs | 1 + rust/kernel/auxiliary.rs | 18 +++++++++------ rust/kernel/cpufreq.rs | 1 + rust/kernel/driver.rs | 24 +++++++++++--------- rust/kernel/i2c.rs | 32 +++++++++++++++------------ rust/kernel/io/mem.rs | 2 ++ rust/kernel/pci.rs | 21 +++++++++++------- rust/kernel/platform.rs | 20 ++++++++++------- rust/kernel/usb.rs | 20 ++++++++++------- samples/rust/rust_debugfs.rs | 1 + samples/rust/rust_dma.rs | 1 + samples/rust/rust_driver_auxiliary.rs | 2 ++ samples/rust/rust_driver_i2c.rs | 1 + samples/rust/rust_driver_pci.rs | 1 + samples/rust/rust_driver_platform.rs | 1 + samples/rust/rust_driver_usb.rs | 1 + samples/rust/rust_i2c_client.rs | 1 + samples/rust/rust_soc.rs | 1 + 22 files changed, 98 insertions(+), 55 deletions(-) diff --git a/drivers/cpufreq/rcpufreq_dt.rs b/drivers/cpufreq/rcpufreq_dt.rs index f17bf64c22e2..b7eeb2730eb0 100644 --- a/drivers/cpufreq/rcpufreq_dt.rs +++ b/drivers/cpufreq/rcpufreq_dt.rs @@ -201,6 +201,7 @@ fn register_em(policy: &mut cpufreq::Policy) { =20 impl platform::Driver for CPUFreqDTDriver { type IdInfo =3D (); + type Data =3D Self; const OF_ID_TABLE: Option> =3D Some(&OF_TABL= E); =20 fn probe( diff --git a/drivers/gpu/drm/nova/driver.rs b/drivers/gpu/drm/nova/driver.rs index b1af0a099551..08136ec0bccb 100644 --- a/drivers/gpu/drm/nova/driver.rs +++ b/drivers/gpu/drm/nova/driver.rs @@ -51,6 +51,7 @@ pub(crate) struct NovaData { =20 impl auxiliary::Driver for NovaDriver { type IdInfo =3D (); + type Data =3D Self; const ID_TABLE: auxiliary::IdTable =3D &AUX_TABLE; =20 fn probe(adev: &auxiliary::Device, _info: &Self::IdInfo) -> impl= PinInit { diff --git a/drivers/gpu/drm/tyr/driver.rs b/drivers/gpu/drm/tyr/driver.rs index 279710b36a10..c81bf217743d 100644 --- a/drivers/gpu/drm/tyr/driver.rs +++ b/drivers/gpu/drm/tyr/driver.rs @@ -91,6 +91,7 @@ fn issue_soft_reset(dev: &Device, iomem: &Devres) -> Result { =20 impl platform::Driver for TyrPlatformDriverData { type IdInfo =3D (); + type Data =3D Self; const OF_ID_TABLE: Option> =3D Some(&OF_TABL= E); =20 fn probe( diff --git a/drivers/gpu/nova-core/driver.rs b/drivers/gpu/nova-core/driver= .rs index 8fe484d357f6..699e27046c93 100644 --- a/drivers/gpu/nova-core/driver.rs +++ b/drivers/gpu/nova-core/driver.rs @@ -74,6 +74,7 @@ pub(crate) struct NovaCore { =20 impl pci::Driver for NovaCore { type IdInfo =3D (); + type Data =3D Self; const ID_TABLE: pci::IdTable =3D &PCI_TABLE; =20 fn probe(pdev: &pci::Device, _info: &Self::IdInfo) -> impl PinIn= it { diff --git a/drivers/pwm/pwm_th1520.rs b/drivers/pwm/pwm_th1520.rs index ddd44a5ce497..07795910a0b5 100644 --- a/drivers/pwm/pwm_th1520.rs +++ b/drivers/pwm/pwm_th1520.rs @@ -316,6 +316,7 @@ fn drop(self: Pin<&mut Self>) { =20 impl platform::Driver for Th1520PwmPlatformDriver { type IdInfo =3D (); + type Data =3D Self; const OF_ID_TABLE: Option> =3D Some(&OF_TABL= E); =20 fn probe( diff --git a/rust/kernel/auxiliary.rs b/rust/kernel/auxiliary.rs index 35b44d194f67..4e83f9e27d78 100644 --- a/rust/kernel/auxiliary.rs +++ b/rust/kernel/auxiliary.rs @@ -41,12 +41,12 @@ =20 // SAFETY: // - `bindings::auxiliary_driver` is a C type declared as `repr(C)`. -// - `T` is the type of the driver's device private data. +// - `T::Data` is the type of the driver's device private data. // - `struct auxiliary_driver` embeds a `struct device_driver`. // - `DEVICE_DRIVER_OFFSET` is the correct byte offset to the embedded `st= ruct device_driver`. unsafe impl driver::DriverLayout for Adapter { type DriverType =3D bindings::auxiliary_driver; - type DriverData =3D T; + type DriverData<'bound> =3D T::Data; const DEVICE_DRIVER_OFFSET: usize =3D core::mem::offset_of!(Self::Driv= erType, driver); } =20 @@ -111,8 +111,8 @@ extern "C" fn remove_callback(adev: *mut bindings::auxi= liary_device) { =20 // SAFETY: `remove_callback` is only ever called after a successfu= l call to // `probe_callback`, hence it's guaranteed that `Device::set_drvda= ta()` has been called - // and stored a `Pin>`. - let data =3D unsafe { adev.as_ref().drvdata_borrow::() }; + // and stored a `Pin>`. + let data =3D unsafe { adev.as_ref().drvdata_borrow::() }; =20 T::unbind(adev, data); } @@ -202,13 +202,17 @@ pub trait Driver { /// type IdInfo: 'static =3D (); type IdInfo: 'static; =20 + /// The type of the driver's bus device private data. + type Data: Send; + /// The table of device ids supported by the driver. const ID_TABLE: IdTable; =20 /// Auxiliary driver probe. /// /// Called when an auxiliary device is matches a corresponding driver. - fn probe(dev: &Device, id_info: &Self::IdInfo) -> impl P= inInit; + fn probe(dev: &Device, id_info: &Self::IdInfo) + -> impl PinInit; =20 /// Auxiliary driver unbind. /// @@ -219,8 +223,8 @@ pub trait Driver { /// `&Device` or `&Device` reference. For instance, drive= rs may try to perform I/O /// operations to gracefully tear down the device. /// - /// Otherwise, release operations for driver resources should be perfo= rmed in `Self::drop`. - fn unbind(dev: &Device, this: Pin<&Self>) { + /// Otherwise, release operations for driver resources should be perfo= rmed in `Drop`. + fn unbind(dev: &Device, this: Pin<&Self::Data>) { let _ =3D (dev, this); } } diff --git a/rust/kernel/cpufreq.rs b/rust/kernel/cpufreq.rs index d8d26870bea2..50dd2a2c3e81 100644 --- a/rust/kernel/cpufreq.rs +++ b/rust/kernel/cpufreq.rs @@ -888,6 +888,7 @@ fn register_em(_policy: &mut Policy) { /// /// impl platform::Driver for SampleDriver { /// type IdInfo =3D (); +/// type Data =3D Self; /// const OF_ID_TABLE: Option> =3D None; /// /// fn probe( diff --git a/rust/kernel/driver.rs b/rust/kernel/driver.rs index c8406dc4da60..5fd1cfd64e93 100644 --- a/rust/kernel/driver.rs +++ b/rust/kernel/driver.rs @@ -13,10 +13,13 @@ //! The main driver interface is defined by a bus specific driver trait. F= or instance: //! //! ```ignore -//! pub trait Driver: Send { +//! pub trait Driver { //! /// The type holding information about each device ID supported by= the driver. //! type IdInfo: 'static; //! +//! /// The type of the driver's bus device private data. +//! type Data: Send; +//! //! /// The table of OF device ids supported by the driver. //! const OF_ID_TABLE: Option> =3D None; //! @@ -24,10 +27,11 @@ //! const ACPI_ID_TABLE: Option> =3D None; //! //! /// Driver probe. -//! fn probe(dev: &Device, id_info: &Self::IdInfo) -> im= pl PinInit; +//! fn probe(dev: &Device, id_info: &Self::IdInfo) +//! -> impl PinInit; //! //! /// Driver unbind (optional). -//! fn unbind(dev: &Device, this: Pin<&Self>) { +//! fn unbind(dev: &Device, this: Pin<&Self::Data>) { //! let _ =3D (dev, this); //! } //! } @@ -42,9 +46,9 @@ )] #![cfg_attr(CONFIG_PCI, doc =3D "* [`pci::Driver`](kernel::pci::Driver)")] //! -//! The `probe()` callback should return a `impl PinInit`, i.= e. the driver's private -//! data. The bus abstraction should store the pointer in the correspondin= g bus device. The generic -//! [`Device`] infrastructure provides common helpers for this purpose on = its +//! The `probe()` callback should return a `impl PinInit`, i.e. the driver's +//! private data. The bus abstraction should store the pointer in the corr= esponding bus device. The +//! generic [`Device`] infrastructure provides common helpers for this pur= pose on its //! [`Device`] implementation. //! //! All driver callbacks should provide a reference to the driver's privat= e data. Once the driver @@ -118,8 +122,8 @@ pub unsafe trait DriverLayout { /// The specific driver type embedding a `struct device_driver`. type DriverType: Default; =20 - /// The type of the driver's device private data. - type DriverData; + /// The type of the driver's bus device private data. + type DriverData<'bound>; =20 /// Byte offset of the embedded `struct device_driver` within `DriverT= ype`. /// @@ -193,8 +197,8 @@ extern "C" fn post_unbind_callback(dev: *mut bindings::= device) { // driver's device private data. // // SAFETY: By the safety requirements of the `Driver` trait, `T::D= riverData` is the - // driver's device private data type. - drop(unsafe { dev.drvdata_obtain::() }); + // driver's bus device private data type. + drop(unsafe { dev.drvdata_obtain::>() }); } =20 /// Attach generic `struct device_driver` callbacks. diff --git a/rust/kernel/i2c.rs b/rust/kernel/i2c.rs index 4ccee4ba4f23..bfd081518615 100644 --- a/rust/kernel/i2c.rs +++ b/rust/kernel/i2c.rs @@ -93,12 +93,12 @@ macro_rules! i2c_device_table { =20 // SAFETY: // - `bindings::i2c_driver` is a C type declared as `repr(C)`. -// - `T` is the type of the driver's device private data. +// - `T::Data` is the type of the driver's device private data. // - `struct i2c_driver` embeds a `struct device_driver`. // - `DEVICE_DRIVER_OFFSET` is the correct byte offset to the embedded `st= ruct device_driver`. unsafe impl driver::DriverLayout for Adapter { type DriverType =3D bindings::i2c_driver; - type DriverData =3D T; + type DriverData<'bound> =3D T::Data; const DEVICE_DRIVER_OFFSET: usize =3D core::mem::offset_of!(Self::Driv= erType, driver); } =20 @@ -176,8 +176,8 @@ extern "C" fn remove_callback(idev: *mut bindings::i2c_= client) { =20 // SAFETY: `remove_callback` is only ever called after a successfu= l call to // `probe_callback`, hence it's guaranteed that `I2cClient::set_dr= vdata()` has been called - // and stored a `Pin>`. - let data =3D unsafe { idev.as_ref().drvdata_borrow::() }; + // and stored a `Pin>`. + let data =3D unsafe { idev.as_ref().drvdata_borrow::() }; =20 T::unbind(idev, data); } @@ -188,8 +188,8 @@ extern "C" fn shutdown_callback(idev: *mut bindings::i2= c_client) { =20 // SAFETY: `shutdown_callback` is only ever called after a success= ful call to // `probe_callback`, hence it's guaranteed that `Device::set_drvda= ta()` has been called - // and stored a `Pin>`. - let data =3D unsafe { idev.as_ref().drvdata_borrow::() }; + // and stored a `Pin>`. + let data =3D unsafe { idev.as_ref().drvdata_borrow::() }; =20 T::shutdown(idev, data); } @@ -294,6 +294,7 @@ macro_rules! module_i2c_driver { /// /// impl i2c::Driver for MyDriver { /// type IdInfo =3D (); +/// type Data =3D Self; /// const I2C_ID_TABLE: Option> =3D Some(&I= 2C_TABLE); /// const OF_ID_TABLE: Option> =3D Some(&OF_= TABLE); /// const ACPI_ID_TABLE: Option> =3D Some(= &ACPI_TABLE); @@ -301,15 +302,15 @@ macro_rules! module_i2c_driver { /// fn probe( /// _idev: &i2c::I2cClient, /// _id_info: Option<&Self::IdInfo>, -/// ) -> impl PinInit { +/// ) -> impl PinInit { /// Err(ENODEV) /// } /// -/// fn shutdown(_idev: &i2c::I2cClient, this: Pin<&Self>) { +/// fn shutdown(_idev: &i2c::I2cClient, this: Pin<&Self::Data>) { /// } /// } ///``` -pub trait Driver: Send { +pub trait Driver { /// The type holding information about each device id supported by the= driver. // TODO: Use `associated_type_defaults` once stabilized: // @@ -318,6 +319,9 @@ pub trait Driver: Send { // ``` type IdInfo: 'static; =20 + /// The type of the driver's bus device private data. + type Data: Send; + /// The table of device ids supported by the driver. const I2C_ID_TABLE: Option> =3D None; =20 @@ -334,7 +338,7 @@ pub trait Driver: Send { fn probe( dev: &I2cClient, id_info: Option<&Self::IdInfo>, - ) -> impl PinInit; + ) -> impl PinInit; =20 /// I2C driver shutdown. /// @@ -346,8 +350,8 @@ fn probe( /// /// This callback is distinct from final resource cleanup, as the driv= er instance remains valid /// after it returns. Any deallocation or teardown of driver-owned res= ources should instead be - /// handled in `Self::drop`. - fn shutdown(dev: &I2cClient, this: Pin<&Self>) { + /// handled in `Drop`. + fn shutdown(dev: &I2cClient, this: Pin<&Self::Data>) { let _ =3D (dev, this); } =20 @@ -360,8 +364,8 @@ fn shutdown(dev: &I2cClient, this: Pin<&S= elf>) { /// `&Device` or `&Device` reference. For instance, drive= rs may try to perform I/O /// operations to gracefully tear down the device. /// - /// Otherwise, release operations for driver resources should be perfo= rmed in `Self::drop`. - fn unbind(dev: &I2cClient, this: Pin<&Self>) { + /// Otherwise, release operations for driver resources should be perfo= rmed in `Drop`. + fn unbind(dev: &I2cClient, this: Pin<&Self::Data>) { let _ =3D (dev, this); } } diff --git a/rust/kernel/io/mem.rs b/rust/kernel/io/mem.rs index 7dc78d547f7a..e136b676d372 100644 --- a/rust/kernel/io/mem.rs +++ b/rust/kernel/io/mem.rs @@ -62,6 +62,7 @@ pub(crate) unsafe fn new(device: &'a Device, resou= rce: &'a Resource) -> S /// /// impl platform::Driver for SampleDriver { /// # type IdInfo =3D (); + /// # type Data =3D Self; /// /// fn probe( /// pdev: &platform::Device, @@ -126,6 +127,7 @@ pub fn iomap_exclusive_sized( /// /// impl platform::Driver for SampleDriver { /// # type IdInfo =3D (); + /// # type Data =3D Self; /// /// fn probe( /// pdev: &platform::Device, diff --git a/rust/kernel/pci.rs b/rust/kernel/pci.rs index 17a33819dc0a..c743f2abb62f 100644 --- a/rust/kernel/pci.rs +++ b/rust/kernel/pci.rs @@ -59,12 +59,12 @@ =20 // SAFETY: // - `bindings::pci_driver` is a C type declared as `repr(C)`. -// - `T` is the type of the driver's device private data. +// - `T::Data` is the type of the driver's device private data. // - `struct pci_driver` embeds a `struct device_driver`. // - `DEVICE_DRIVER_OFFSET` is the correct byte offset to the embedded `st= ruct device_driver`. unsafe impl driver::DriverLayout for Adapter { type DriverType =3D bindings::pci_driver; - type DriverData =3D T; + type DriverData<'bound> =3D T::Data; const DEVICE_DRIVER_OFFSET: usize =3D core::mem::offset_of!(Self::Driv= erType, driver); } =20 @@ -129,8 +129,8 @@ extern "C" fn remove_callback(pdev: *mut bindings::pci_= dev) { =20 // SAFETY: `remove_callback` is only ever called after a successfu= l call to // `probe_callback`, hence it's guaranteed that `Device::set_drvda= ta()` has been called - // and stored a `Pin>`. - let data =3D unsafe { pdev.as_ref().drvdata_borrow::() }; + // and stored a `Pin>`. + let data =3D unsafe { pdev.as_ref().drvdata_borrow::() }; =20 T::unbind(pdev, data); } @@ -279,6 +279,7 @@ macro_rules! pci_device_table { /// /// impl pci::Driver for MyDriver { /// type IdInfo =3D (); +/// type Data =3D Self; /// const ID_TABLE: pci::IdTable =3D &PCI_TABLE; /// /// fn probe( @@ -291,7 +292,7 @@ macro_rules! pci_device_table { ///``` /// Drivers must implement this trait in order to get a PCI driver registe= red. Please refer to the /// `Adapter` documentation for an example. -pub trait Driver: Send { +pub trait Driver { /// The type holding information about each device id supported by the= driver. // TODO: Use `associated_type_defaults` once stabilized: // @@ -300,6 +301,9 @@ pub trait Driver: Send { // ``` type IdInfo: 'static; =20 + /// The type of the driver's bus device private data. + type Data: Send; + /// The table of device ids supported by the driver. const ID_TABLE: IdTable; =20 @@ -307,7 +311,8 @@ pub trait Driver: Send { /// /// Called when a new pci device is added or discovered. Implementers = should /// attempt to initialize the device here. - fn probe(dev: &Device, id_info: &Self::IdInfo) -> impl P= inInit; + fn probe(dev: &Device, id_info: &Self::IdInfo) + -> impl PinInit; =20 /// PCI driver unbind. /// @@ -318,8 +323,8 @@ pub trait Driver: Send { /// `&Device` or `&Device` reference. For instance, drive= rs may try to perform I/O /// operations to gracefully tear down the device. /// - /// Otherwise, release operations for driver resources should be perfo= rmed in `Self::drop`. - fn unbind(dev: &Device, this: Pin<&Self>) { + /// Otherwise, release operations for driver resources should be perfo= rmed in `Drop`. + fn unbind(dev: &Device, this: Pin<&Self::Data>) { let _ =3D (dev, this); } } diff --git a/rust/kernel/platform.rs b/rust/kernel/platform.rs index c7a3dcdde3b1..975b22ffe5db 100644 --- a/rust/kernel/platform.rs +++ b/rust/kernel/platform.rs @@ -45,12 +45,12 @@ =20 // SAFETY: // - `bindings::platform_driver` is a C type declared as `repr(C)`. -// - `T` is the type of the driver's device private data. +// - `T::Data` is the type of the driver's device private data. // - `struct platform_driver` embeds a `struct device_driver`. // - `DEVICE_DRIVER_OFFSET` is the correct byte offset to the embedded `st= ruct device_driver`. unsafe impl driver::DriverLayout for Adapter { type DriverType =3D bindings::platform_driver; - type DriverData =3D T; + type DriverData<'bound> =3D T::Data; const DEVICE_DRIVER_OFFSET: usize =3D core::mem::offset_of!(Self::Driv= erType, driver); } =20 @@ -117,8 +117,8 @@ extern "C" fn remove_callback(pdev: *mut bindings::plat= form_device) { =20 // SAFETY: `remove_callback` is only ever called after a successfu= l call to // `probe_callback`, hence it's guaranteed that `Device::set_drvda= ta()` has been called - // and stored a `Pin>`. - let data =3D unsafe { pdev.as_ref().drvdata_borrow::() }; + // and stored a `Pin>`. + let data =3D unsafe { pdev.as_ref().drvdata_borrow::() }; =20 T::unbind(pdev, data); } @@ -192,6 +192,7 @@ macro_rules! module_platform_driver { /// /// impl platform::Driver for MyDriver { /// type IdInfo =3D (); +/// type Data =3D Self; /// const OF_ID_TABLE: Option> =3D Some(&OF_= TABLE); /// const ACPI_ID_TABLE: Option> =3D Some(= &ACPI_TABLE); /// @@ -203,7 +204,7 @@ macro_rules! module_platform_driver { /// } /// } ///``` -pub trait Driver: Send { +pub trait Driver { /// The type holding driver private data about each device id supporte= d by the driver. // TODO: Use associated_type_defaults once stabilized: // @@ -212,6 +213,9 @@ pub trait Driver: Send { // ``` type IdInfo: 'static; =20 + /// The type of the driver's bus device private data. + type Data: Send; + /// The table of OF device ids supported by the driver. const OF_ID_TABLE: Option> =3D None; =20 @@ -225,7 +229,7 @@ pub trait Driver: Send { fn probe( dev: &Device, id_info: Option<&Self::IdInfo>, - ) -> impl PinInit; + ) -> impl PinInit; =20 /// Platform driver unbind. /// @@ -236,8 +240,8 @@ fn probe( /// `&Device` or `&Device` reference. For instance, drive= rs may try to perform I/O /// operations to gracefully tear down the device. /// - /// Otherwise, release operations for driver resources should be perfo= rmed in `Self::drop`. - fn unbind(dev: &Device, this: Pin<&Self>) { + /// Otherwise, release operations for driver resources should be perfo= rmed in `Drop`. + fn unbind(dev: &Device, this: Pin<&Self::Data>) { let _ =3D (dev, this); } } diff --git a/rust/kernel/usb.rs b/rust/kernel/usb.rs index 3f62da585281..88721970afcb 100644 --- a/rust/kernel/usb.rs +++ b/rust/kernel/usb.rs @@ -36,12 +36,12 @@ =20 // SAFETY: // - `bindings::usb_driver` is a C type declared as `repr(C)`. -// - `T` is the type of the driver's device private data. +// - `T::Data` is the type of the driver's device private data. // - `struct usb_driver` embeds a `struct device_driver`. // - `DEVICE_DRIVER_OFFSET` is the correct byte offset to the embedded `st= ruct device_driver`. unsafe impl driver::DriverLayout for Adapter { type DriverType =3D bindings::usb_driver; - type DriverData =3D T; + type DriverData<'bound> =3D T::Data; const DEVICE_DRIVER_OFFSET: usize =3D core::mem::offset_of!(Self::Driv= erType, driver); } =20 @@ -109,8 +109,8 @@ extern "C" fn disconnect_callback(intf: *mut bindings::= usb_interface) { =20 // SAFETY: `disconnect_callback` is only ever called after a succe= ssful call to // `probe_callback`, hence it's guaranteed that `Device::set_drvda= ta()` has been called - // and stored a `Pin>`. - let data =3D unsafe { dev.drvdata_borrow::() }; + // and stored a `Pin>`. + let data =3D unsafe { dev.drvdata_borrow::() }; =20 T::disconnect(intf, data); } @@ -287,23 +287,27 @@ macro_rules! usb_device_table { /// /// impl usb::Driver for MyDriver { /// type IdInfo =3D (); +/// type Data =3D Self; /// const ID_TABLE: usb::IdTable =3D &USB_TABLE; /// /// fn probe( /// _interface: &usb::Interface, /// _id: &usb::DeviceId, /// _info: &Self::IdInfo, -/// ) -> impl PinInit { +/// ) -> impl PinInit { /// Err(ENODEV) /// } /// -/// fn disconnect(_interface: &usb::Interface, _data: Pin<&Self>= ) {} +/// fn disconnect(_interface: &usb::Interface, _data: Pin<&Self:= :Data>) {} /// } ///``` pub trait Driver { /// The type holding information about each one of the device ids supp= orted by the driver. type IdInfo: 'static; =20 + /// The type of the driver's bus device private data. + type Data: Send; + /// The table of device ids supported by the driver. const ID_TABLE: IdTable; =20 @@ -315,12 +319,12 @@ fn probe( interface: &Interface, id: &DeviceId, id_info: &Self::IdInfo, - ) -> impl PinInit; + ) -> impl PinInit; =20 /// USB driver disconnect. /// /// Called when the USB interface is about to be unbound from this dri= ver. - fn disconnect(interface: &Interface, data: Pin<&Self>); + fn disconnect(interface: &Interface, data: Pin<&Self::Da= ta>); } =20 /// A USB interface. diff --git a/samples/rust/rust_debugfs.rs b/samples/rust/rust_debugfs.rs index 0963efe19f93..478c4f693deb 100644 --- a/samples/rust/rust_debugfs.rs +++ b/samples/rust/rust_debugfs.rs @@ -117,6 +117,7 @@ fn from_str(s: &str) -> Result { =20 impl platform::Driver for RustDebugFs { type IdInfo =3D (); + type Data =3D Self; const OF_ID_TABLE: Option> =3D None; const ACPI_ID_TABLE: Option> =3D Some(&ACP= I_TABLE); =20 diff --git a/samples/rust/rust_dma.rs b/samples/rust/rust_dma.rs index 129bb4b39c04..e583c6b8390a 100644 --- a/samples/rust/rust_dma.rs +++ b/samples/rust/rust_dma.rs @@ -58,6 +58,7 @@ unsafe impl kernel::transmute::FromBytes for MyStruct {} =20 impl pci::Driver for DmaSampleDriver { type IdInfo =3D (); + type Data =3D Self; const ID_TABLE: pci::IdTable =3D &PCI_TABLE; =20 fn probe(pdev: &pci::Device, _info: &Self::IdInfo) -> impl PinIn= it { diff --git a/samples/rust/rust_driver_auxiliary.rs b/samples/rust/rust_driv= er_auxiliary.rs index 319ef734c02b..61d5bf2e8c0d 100644 --- a/samples/rust/rust_driver_auxiliary.rs +++ b/samples/rust/rust_driver_auxiliary.rs @@ -31,6 +31,7 @@ =20 impl auxiliary::Driver for AuxiliaryDriver { type IdInfo =3D (); + type Data =3D Self; =20 const ID_TABLE: auxiliary::IdTable =3D &AUX_TABLE; =20 @@ -65,6 +66,7 @@ struct ParentDriver { =20 impl pci::Driver for ParentDriver { type IdInfo =3D (); + type Data =3D Self; =20 const ID_TABLE: pci::IdTable =3D &PCI_TABLE; =20 diff --git a/samples/rust/rust_driver_i2c.rs b/samples/rust/rust_driver_i2c= .rs index 6be79f9e9fb5..8269f1798611 100644 --- a/samples/rust/rust_driver_i2c.rs +++ b/samples/rust/rust_driver_i2c.rs @@ -35,6 +35,7 @@ =20 impl i2c::Driver for SampleDriver { type IdInfo =3D u32; + type Data =3D Self; =20 const ACPI_ID_TABLE: Option> =3D Some(&ACP= I_TABLE); const I2C_ID_TABLE: Option> =3D Some(&I2C_T= ABLE); diff --git a/samples/rust/rust_driver_pci.rs b/samples/rust/rust_driver_pci= .rs index 47d3e84fab63..f43c6a660b39 100644 --- a/samples/rust/rust_driver_pci.rs +++ b/samples/rust/rust_driver_pci.rs @@ -140,6 +140,7 @@ fn config_space(pdev: &pci::Device) { =20 impl pci::Driver for SampleDriver { type IdInfo =3D TestIndex; + type Data =3D Self; =20 const ID_TABLE: pci::IdTable =3D &PCI_TABLE; =20 diff --git a/samples/rust/rust_driver_platform.rs b/samples/rust/rust_drive= r_platform.rs index f2229d176fb9..6505902f8200 100644 --- a/samples/rust/rust_driver_platform.rs +++ b/samples/rust/rust_driver_platform.rs @@ -101,6 +101,7 @@ struct SampleDriver { =20 impl platform::Driver for SampleDriver { type IdInfo =3D Info; + type Data =3D Self; const OF_ID_TABLE: Option> =3D Some(&OF_TABL= E); const ACPI_ID_TABLE: Option> =3D Some(&ACP= I_TABLE); =20 diff --git a/samples/rust/rust_driver_usb.rs b/samples/rust/rust_driver_usb= .rs index ab72e99e1274..5942e4b01fd8 100644 --- a/samples/rust/rust_driver_usb.rs +++ b/samples/rust/rust_driver_usb.rs @@ -26,6 +26,7 @@ struct SampleDriver { =20 impl usb::Driver for SampleDriver { type IdInfo =3D (); + type Data =3D Self; const ID_TABLE: usb::IdTable =3D &USB_TABLE; =20 fn probe( diff --git a/samples/rust/rust_i2c_client.rs b/samples/rust/rust_i2c_client= .rs index 8d2c12e535b0..5956b647294d 100644 --- a/samples/rust/rust_i2c_client.rs +++ b/samples/rust/rust_i2c_client.rs @@ -106,6 +106,7 @@ struct SampleDriver { =20 impl platform::Driver for SampleDriver { type IdInfo =3D (); + type Data =3D Self; const OF_ID_TABLE: Option> =3D Some(&OF_TABL= E); const ACPI_ID_TABLE: Option> =3D Some(&ACP= I_TABLE); =20 diff --git a/samples/rust/rust_soc.rs b/samples/rust/rust_soc.rs index 8079c1c48416..a5e72582f4a2 100644 --- a/samples/rust/rust_soc.rs +++ b/samples/rust/rust_soc.rs @@ -37,6 +37,7 @@ struct SampleSocDriver { =20 impl platform::Driver for SampleSocDriver { type IdInfo =3D (); + type Data =3D Self; const OF_ID_TABLE: Option> =3D Some(&OF_TABL= E); const ACPI_ID_TABLE: Option> =3D Some(&ACP= I_TABLE); =20 --=20 2.54.0 From nobody Mon Jun 8 22:51:08 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id DDAC13451A7; Mon, 25 May 2026 20:30:06 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779741008; cv=none; b=DY4q7xApSI6siXpYo9YTph1jS90cP6p2ghY4Xim3DFo0j1qOoSQewgfwa4KywqXCzoodbpfZnGD8/NJlgjSZhSQrXFL0xZDdGgOTsyn25bMXnaMhxKORzhriOYYNeHcDhoxsg6EQHnAawlBUd7XCSXWCIbPZZQxLrr4paUS4WRw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779741008; c=relaxed/simple; bh=DzmbuehWP/n+z9bBA3kIKR03PtD9qEhtHM53dYd3cEg=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=YsXk+oYvX8LmnROxesJRlvzcVPLghqhliC56Ws+cx/TFyLCxDJJgyXNIaycVe0gR8VUPqftDLC3UfwSHFl46+QtsSfhxA1nrehLfiynNBKawplC2pfCLaOI0IfhkjTLVzwdidthJ6/0RlhgWnuntGZV6pc5p9tUY0mtNrxICpZg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=cc/Sa11s; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="cc/Sa11s" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 03D261F00A3A; Mon, 25 May 2026 20:29:59 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1779741006; bh=chpl2dAT305MB/BwkNuO7Y8z5fBgSREADsJUl5S4kCw=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=cc/Sa11s9zjXzmchlAii/dpVBnPe8UJOcKIAC3wyF7B/6LT1W150LAfz/J4YslPHV gj/GWvUTSSHfWc3sUghykHhwCZq7bUJX+3gMmnBNRQ6s8xEYupgjmLQtzFnRTdFM9d TkCUihgzbCPQ48zNJvaTILpSSimR8v0W4P2OAKKjgS82npPAYXmaogacuxIH+Dx8Kw R2r0bratOD5sGpALpE+ll/rVNqZU/aKaduqKMSGbo4Nr9bmRH5kr0NozLAcvCYoHnH 73ljS70s/HS31DVgbc0sXYlK5kRFTeixW67Xtywa7nPBwL0TyGcBQLI6d790uzSULx iKSGpVNc8J8fA== From: Danilo Krummrich To: gregkh@linuxfoundation.org, rafael@kernel.org, acourbot@nvidia.com, aliceryhl@google.com, david.m.ertman@intel.com, ira.weiny@intel.com, leon@kernel.org, viresh.kumar@linaro.org, m.wilczynski@samsung.com, ukleinek@kernel.org, bhelgaas@google.com, kwilczynski@kernel.org, abdiel.janulgue@gmail.com, robin.murphy@arm.com, markus.probst@posteo.de, ojeda@kernel.org, boqun@kernel.org, gary@garyguo.net, bjorn3_gh@protonmail.com, lossin@kernel.org, a.hindborg@kernel.org, tmgross@umich.edu, igor.korotin@linux.dev, daniel.almeida@collabora.com, pcolberg@redhat.com Cc: driver-core@lists.linux.dev, linux-kernel@vger.kernel.org, nova-gpu@lists.linux.dev, dri-devel@lists.freedesktop.org, linux-pm@vger.kernel.org, linux-pwm@vger.kernel.org, linux-pci@vger.kernel.org, rust-for-linux@vger.kernel.org, Danilo Krummrich Subject: [PATCH v5 05/24] rust: driver core: drop drvdata before devres release Date: Mon, 25 May 2026 22:20:52 +0200 Message-ID: <20260525202921.124698-6-dakr@kernel.org> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260525202921.124698-1-dakr@kernel.org> References: <20260525202921.124698-1-dakr@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Move the post_unbind_rust callback before devres_release_all() in device_unbind_cleanup(). With drvdata() removed, the driver's bus device private data is only accessible by the owning driver itself. It is hence safe to drop the driver's bus device private data before devres actions are released. This reordering is the key enabler for Higher-Ranked Lifetime Types (HRT) in Rust device drivers -- it allows driver structs to hold direct references to devres-managed resources, because the bus device private data (and with it all such references) is guaranteed to be dropped while the underlying devres resources are still alive. Without this change, devres resources would be freed first, leaving the driver's bus device private data with dangling references during its destructor. Reviewed-by: Alexandre Courbot Reviewed-by: Gary Guo Reviewed-by: Greg Kroah-Hartman Signed-off-by: Danilo Krummrich --- drivers/base/dd.c | 2 +- include/linux/device/driver.h | 4 ++-- rust/kernel/driver.rs | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/base/dd.c b/drivers/base/dd.c index 1dc1e3528043..73801b40a416 100644 --- a/drivers/base/dd.c +++ b/drivers/base/dd.c @@ -595,9 +595,9 @@ static DEVICE_ATTR_RW(state_synced); =20 static void device_unbind_cleanup(struct device *dev) { - devres_release_all(dev); if (dev->driver->p_cb.post_unbind_rust) dev->driver->p_cb.post_unbind_rust(dev); + devres_release_all(dev); arch_teardown_dma_ops(dev); kfree(dev->dma_range_map); dev->dma_range_map =3D NULL; diff --git a/include/linux/device/driver.h b/include/linux/device/driver.h index bbc67ec513ed..38e9a4679447 100644 --- a/include/linux/device/driver.h +++ b/include/linux/device/driver.h @@ -123,8 +123,8 @@ struct device_driver { struct driver_private *p; struct { /* - * Called after remove() and after all devres entries have been - * processed. This is a Rust only callback. + * Called after remove() but before devres entries are released. + * This is a Rust only callback. */ void (*post_unbind_rust)(struct device *dev); } p_cb; diff --git a/rust/kernel/driver.rs b/rust/kernel/driver.rs index 5fd1cfd64e93..a95dafaa9d68 100644 --- a/rust/kernel/driver.rs +++ b/rust/kernel/driver.rs @@ -193,8 +193,8 @@ extern "C" fn post_unbind_callback(dev: *mut bindings::= device) { // INVARIANT: `dev` is valid for the duration of the `post_unbind_= callback()`. let dev =3D unsafe { &*dev.cast::>() }; =20 - // `remove()` and all devres callbacks have been completed at this= point, hence drop the - // driver's device private data. + // `remove()` has been completed at this point; devres resources a= re still valid and will + // be released after the driver's bus device private data is dropp= ed. // // SAFETY: By the safety requirements of the `Driver` trait, `T::D= riverData` is the // driver's bus device private data type. --=20 2.54.0 From nobody Mon Jun 8 22:51:08 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 0DF9A346781; Mon, 25 May 2026 20:30:14 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779741015; cv=none; b=F4uqG9uJDqDm52JX1hgaxCTK9awId2e/JJ5zdAtkk1Y9Vczb1G/qOHukCuWPyw4SnTmdr65h3r6bP3ROINSYC8FUYod1yQfbRpZtAb0GKlU79SS7hmpW8Ci5PjAB/re7+perMttI46klTKlhgZcjK0zpgVAGXDwN6pthgWClvZU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779741015; c=relaxed/simple; bh=WW+1cUg1yAXWCMqkMdSPHBHujbz4NnRLGmhwkRosZAo=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=jy9yaXl3Dwx5qljUnR08dc5FU86UqCbrAk4GzXtlW5eksjQDBIh5aFxrWCa3+fWGzhaOBRnsw5rsyX5YvBAsUlrEcIn9BKDnTJadRGAM1CBUOt6IwI62R0kCpTdf9RQz3dS38tTMjFpUQBaQJ6xOCt7xzROP94o6Hi8SOlm/Xog= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=UW1tvsGt; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="UW1tvsGt" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 412281F000E9; Mon, 25 May 2026 20:30:07 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1779741013; bh=dGlGg1KPjf9GE4pvZqVXon2ZHwLzVeQvY3zCiGlsuuM=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=UW1tvsGtlDOjd+UIaKlP96Ukh7FPeYR6mwTF7N5GK/N/ldSB3x0fmf/iay/YMAPsv H2ShdlrBL6nIZ/WIRngJrvAjL5Y1ds2MU68GVm4+msI+ZKWfxp46NZVPEOldnOSALp 6kMpovj/FP0XkbSKqXyeYwqzjYRxKEu+fYQY61m8yyMUGxUfuKg0mTeQoqjfpy15W0 JwWCT7IXNg6UAzps6buMDuAJPxLa/6tpwSOo8VZKkktdJyBEOk+aS0WaqJpqI5xzRl GwQqDSgfxdEfB5ahn3mEbRSPuccyW26stmfWnWsZDMIn6OqQtmQRnDsXITLfCT5zYx uwOyFzgtCOENg== From: Danilo Krummrich To: gregkh@linuxfoundation.org, rafael@kernel.org, acourbot@nvidia.com, aliceryhl@google.com, david.m.ertman@intel.com, ira.weiny@intel.com, leon@kernel.org, viresh.kumar@linaro.org, m.wilczynski@samsung.com, ukleinek@kernel.org, bhelgaas@google.com, kwilczynski@kernel.org, abdiel.janulgue@gmail.com, robin.murphy@arm.com, markus.probst@posteo.de, ojeda@kernel.org, boqun@kernel.org, gary@garyguo.net, bjorn3_gh@protonmail.com, lossin@kernel.org, a.hindborg@kernel.org, tmgross@umich.edu, igor.korotin@linux.dev, daniel.almeida@collabora.com, pcolberg@redhat.com Cc: driver-core@lists.linux.dev, linux-kernel@vger.kernel.org, nova-gpu@lists.linux.dev, dri-devel@lists.freedesktop.org, linux-pm@vger.kernel.org, linux-pwm@vger.kernel.org, linux-pci@vger.kernel.org, rust-for-linux@vger.kernel.org, Danilo Krummrich Subject: [PATCH v5 06/24] rust: pci: implement Sync for Device Date: Mon, 25 May 2026 22:20:53 +0200 Message-ID: <20260525202921.124698-7-dakr@kernel.org> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260525202921.124698-1-dakr@kernel.org> References: <20260525202921.124698-1-dakr@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Implement Sync for Device in addition to Device. Device uses the same underlying struct pci_dev as Device; Bound is a zero-sized type-state marker that does not affect thread safety. This is needed for drivers to store &'bound pci::Device in their private data while remaining Send. Reviewed-by: Alexandre Courbot Reviewed-by: Gary Guo Reviewed-by: Greg Kroah-Hartman Signed-off-by: Danilo Krummrich --- rust/kernel/pci.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/rust/kernel/pci.rs b/rust/kernel/pci.rs index c743f2abb62f..d214a861375d 100644 --- a/rust/kernel/pci.rs +++ b/rust/kernel/pci.rs @@ -528,3 +528,7 @@ unsafe impl Send for Device {} // SAFETY: `Device` can be shared among threads because all methods of `De= vice` // (i.e. `Device) are thread safe. unsafe impl Sync for Device {} + +// SAFETY: Same as `Device` -- the underlying `struct pci_dev` is = the same; +// `Bound` is a zero-sized type-state marker that does not affect thread s= afety. +unsafe impl Sync for Device {} --=20 2.54.0 From nobody Mon Jun 8 22:51:08 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2DEA435E1DB; Mon, 25 May 2026 20:30:21 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779741022; cv=none; b=h8gobXyksQh0H8s6qHBvNMs+XONqshYw7ESUfMb0jHe1+Am+ganjE3WBU4Nyd3kWG+z/vnZjjR0aBKg9SeqOQWoCdYvrX4EvDsr/b3kDKVxJmUQnMtejyy0YCx5Mog0ORdgN8LFahzsfSk3HaqZ/ImoUSayAQGERTe219I1//wU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779741022; c=relaxed/simple; bh=tzMwvI73cS5cWVAt0VIEQ8qV29HoK+axG+FEZGe7j5A=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=G/RX+j0LwgY355OHnaIQgXZtrzAzazpSNAnORtGi3Edm8Ui4Z+wCxrMHXh4igaj/pqDxEHjdF3iD9IZVR787cX4tXaqxcbBLxXmcePoZ8jevhzXj2zpOE/ObKdM1hrUpxWnTJh7OAagkO5g+uXN9mwH+FWOjH9Kk17c0jmtPPoM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=molm00d/; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="molm00d/" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 61B861F00A3A; Mon, 25 May 2026 20:30:14 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1779741021; bh=D81pVtNSTXvXcGqgktNfZxQo456sX2/TTMaOxXAnkyE=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=molm00d/AMMa7zZ/Rn2ObkrByVfNEPa9xuDWH5mntF2CkOank5tpaTESELMDdS44e rNE/0/lb7J4IuQgbBWPMdHzft94nz4AP5386Sl7wf65MRbdfT+Q+FyTu2zIhD5kWpQ 73szHgjGZpYu3dn7QY3jo+pMEETtNMrE2yhRSAj/lBvtkjcHkvfa43tIvbG9G2Ismx dAndxBkqTnzU53xWe2IIrDc7MUgjmqgX5FVhnC8zlVNnCnvbVzScwsWo+X4ZXQ4rvZ pn0giGI71r2wQhbxRVfhvIrY+EgrAXA2mmbXJs98rQ+A4dVzrc73XPDMWw0VKjjIF7 rvlrAowTygFPQ== From: Danilo Krummrich To: gregkh@linuxfoundation.org, rafael@kernel.org, acourbot@nvidia.com, aliceryhl@google.com, david.m.ertman@intel.com, ira.weiny@intel.com, leon@kernel.org, viresh.kumar@linaro.org, m.wilczynski@samsung.com, ukleinek@kernel.org, bhelgaas@google.com, kwilczynski@kernel.org, abdiel.janulgue@gmail.com, robin.murphy@arm.com, markus.probst@posteo.de, ojeda@kernel.org, boqun@kernel.org, gary@garyguo.net, bjorn3_gh@protonmail.com, lossin@kernel.org, a.hindborg@kernel.org, tmgross@umich.edu, igor.korotin@linux.dev, daniel.almeida@collabora.com, pcolberg@redhat.com Cc: driver-core@lists.linux.dev, linux-kernel@vger.kernel.org, nova-gpu@lists.linux.dev, dri-devel@lists.freedesktop.org, linux-pm@vger.kernel.org, linux-pwm@vger.kernel.org, linux-pci@vger.kernel.org, rust-for-linux@vger.kernel.org, Danilo Krummrich Subject: [PATCH v5 07/24] rust: platform: implement Sync for Device Date: Mon, 25 May 2026 22:20:54 +0200 Message-ID: <20260525202921.124698-8-dakr@kernel.org> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260525202921.124698-1-dakr@kernel.org> References: <20260525202921.124698-1-dakr@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Implement Sync for Device in addition to Device. Device uses the same underlying struct platform_device as Device; Bound is a zero-sized type-state marker that does not affect thread safety. This is needed for drivers to store &'bound platform::Device in their private data while remaining Send. Reviewed-by: Alexandre Courbot Reviewed-by: Gary Guo Reviewed-by: Greg Kroah-Hartman Signed-off-by: Danilo Krummrich --- rust/kernel/platform.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/rust/kernel/platform.rs b/rust/kernel/platform.rs index 975b22ffe5db..106a5ed57ea6 100644 --- a/rust/kernel/platform.rs +++ b/rust/kernel/platform.rs @@ -565,3 +565,7 @@ unsafe impl Send for Device {} // SAFETY: `Device` can be shared among threads because all methods of `De= vice` // (i.e. `Device) are thread safe. unsafe impl Sync for Device {} + +// SAFETY: Same as `Device` -- the underlying `struct platform_dev= ice` is the same; +// `Bound` is a zero-sized type-state marker that does not affect thread s= afety. +unsafe impl Sync for Device {} --=20 2.54.0 From nobody Mon Jun 8 22:51:08 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A2801388363; Mon, 25 May 2026 20:30:28 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779741029; cv=none; b=OV7KMu6udn80XBmC/gmNIA/S+FhfLRXdUfmQBTGEJoIvHJ5+9AfZrAVCSGieYlDgQXIzX5HSIXVzE7JeEcG95XpUn0RM1gy9qAaxTTmufds4/YwB2azpKJs3trV6vm34Br8gaS2Y6eZxBqDEyXNgxtyn9aRaxehhUsRUs66s10Y= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779741029; c=relaxed/simple; bh=BC1h/IFGFPQBOYuZJnLBqh7aupaXZODluoDtPDcPPF8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=WyMIbVkDNM06BJX2F4cfl+aSL4hABTzZs4gIatFST6Pt3yCKKMSqdHmcrDfviiaulS0Pnp8H3q+4SeFrY8MAqsm+H3lqfE1hyrJQv8OrS5XpqvJ65EqMCGr8Mv9PLFjim7Df8E2ZODxqvcv8CWu8RP1cpzr6KhL+LwU4Uw62BLU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=d18Bmy4S; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="d18Bmy4S" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 82EF71F000E9; Mon, 25 May 2026 20:30:21 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1779741028; bh=mqdVjByct2ZDI65nBQw9txg9uw6/mNnafA68BwYf80c=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=d18Bmy4SZ2CcTi/2slLXuKXSCKMsS6fpjL9bhhYrO1G56zfXslcsEcOYSNJxtSq24 vZGpEQ2rRFRdaINIz+ZejqMJTWT2z3d0gRHq6EIl63abhZrpwwMBy/fBs1EtfaCzfc qmdI2WQANPlye7Xet/MvlGvTEKMD0XywYvT0+/LCWeuRDzxRBoqR+7WHZlX74rONo9 w0f58QybvwE+q4dwii1RR6isNwD/SNxfMjdKx7OLtCac+9DSMnZOQG/SxUJwPPkWCm 5r991him+Hv9o6qyXTxQZ42yZmVa3woUe9xiULjEbVNiS7q/Y0idtPUZ1xwuXOQIXQ hp3BZfzMKY2yQ== From: Danilo Krummrich To: gregkh@linuxfoundation.org, rafael@kernel.org, acourbot@nvidia.com, aliceryhl@google.com, david.m.ertman@intel.com, ira.weiny@intel.com, leon@kernel.org, viresh.kumar@linaro.org, m.wilczynski@samsung.com, ukleinek@kernel.org, bhelgaas@google.com, kwilczynski@kernel.org, abdiel.janulgue@gmail.com, robin.murphy@arm.com, markus.probst@posteo.de, ojeda@kernel.org, boqun@kernel.org, gary@garyguo.net, bjorn3_gh@protonmail.com, lossin@kernel.org, a.hindborg@kernel.org, tmgross@umich.edu, igor.korotin@linux.dev, daniel.almeida@collabora.com, pcolberg@redhat.com Cc: driver-core@lists.linux.dev, linux-kernel@vger.kernel.org, nova-gpu@lists.linux.dev, dri-devel@lists.freedesktop.org, linux-pm@vger.kernel.org, linux-pwm@vger.kernel.org, linux-pci@vger.kernel.org, rust-for-linux@vger.kernel.org, Danilo Krummrich Subject: [PATCH v5 08/24] rust: auxiliary: implement Sync for Device Date: Mon, 25 May 2026 22:20:55 +0200 Message-ID: <20260525202921.124698-9-dakr@kernel.org> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260525202921.124698-1-dakr@kernel.org> References: <20260525202921.124698-1-dakr@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Implement Sync for Device in addition to Device. Device uses the same underlying struct auxiliary_device as Device; Bound is a zero-sized type-state marker that does not affect thread safety. This is needed for drivers to store &'bound auxiliary::Device in their private data while remaining Send. Reviewed-by: Alexandre Courbot Reviewed-by: Gary Guo Reviewed-by: Greg Kroah-Hartman Signed-off-by: Danilo Krummrich --- rust/kernel/auxiliary.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/rust/kernel/auxiliary.rs b/rust/kernel/auxiliary.rs index 4e83f9e27d78..df2c97423dcc 100644 --- a/rust/kernel/auxiliary.rs +++ b/rust/kernel/auxiliary.rs @@ -369,6 +369,10 @@ unsafe impl Send for Device {} // (i.e. `Device) are thread safe. unsafe impl Sync for Device {} =20 +// SAFETY: Same as `Device` -- the underlying `struct auxiliary_de= vice` is the same; +// `Bound` is a zero-sized type-state marker that does not affect thread s= afety. +unsafe impl Sync for Device {} + /// Wrapper that stores a [`TypeId`] alongside the registration data for r= untime type checking. #[repr(C)] #[pin_data] --=20 2.54.0 From nobody Mon Jun 8 22:51:08 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A71F7396D2E; Mon, 25 May 2026 20:30:35 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779741036; cv=none; b=fLzyBXcnd7UBzIMuXLCX3h+dHwY3vrhiZHb0dqdcWzDuuQH5zWA6WGxnW0+y9+Lvu9GYwPEGAxVexaAARqKyKrNPTMOq4xqrOmCQoxlRUdOMZVwfF4idm1lEU+DnG6ZQJnVc+TTfmDWlSi9YFFs+XjVGkMrAEf+kGAzpamzTi2M= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779741036; c=relaxed/simple; bh=QpOSs/EphbyzeReYezQJNbQQg8W/3eJTmGEltj0uFeY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=k6sql5iF6n/SATPlfEs/yb5YS3BUlPqhRXCHiyqf3rddTOKRavmQNZjNTJBm3ZynCYDIwi+aPmFS8BXz7MGITZk2C/11Q1EAfaaGtgTmol9ACQO9dpJZKK7MV3L9q3OKyRwhxwreDXtD0OzPW+imasP/84kBz65MBXGUFQD47eM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=ZDJiCTd5; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="ZDJiCTd5" Received: by smtp.kernel.org (Postfix) with ESMTPSA id A42FF1F00A3C; Mon, 25 May 2026 20:30:28 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1779741035; bh=FsXPjNDjSp9++e5VYHQ4V4V9GNNCrz4C2Wggi5ivyfU=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=ZDJiCTd5pgbF79ZrJHPBOcYWcEHXu0Cp0Ig2cMHXyrL61ywlKBxQChATWj+n4jwfu H2qvptgpw35wA7RbrFxMSENCDp0QFO2MRcgMGPIseiFFrHghfFnxV21rVx2qjGsGkx fdQW0Y6gnZ5sOqrAQbupBYnDIAAnR54lCRDX9KhjHNg9ty8pslwzJgyDt5KqBO7AP8 0FlV8zIAjXpFSUe6ihcvBp9loDh752+VJAv3sPx1IabB4xh4QMaPOPG7YoUMfPen73 zfL0tLomSMC8+p4B78UqvjPGpHE9seL7MjM2+OHDwl0G1el1BAcbMRvk5bVTjWpj+8 amJBUKzf5GKVw== From: Danilo Krummrich To: gregkh@linuxfoundation.org, rafael@kernel.org, acourbot@nvidia.com, aliceryhl@google.com, david.m.ertman@intel.com, ira.weiny@intel.com, leon@kernel.org, viresh.kumar@linaro.org, m.wilczynski@samsung.com, ukleinek@kernel.org, bhelgaas@google.com, kwilczynski@kernel.org, abdiel.janulgue@gmail.com, robin.murphy@arm.com, markus.probst@posteo.de, ojeda@kernel.org, boqun@kernel.org, gary@garyguo.net, bjorn3_gh@protonmail.com, lossin@kernel.org, a.hindborg@kernel.org, tmgross@umich.edu, igor.korotin@linux.dev, daniel.almeida@collabora.com, pcolberg@redhat.com Cc: driver-core@lists.linux.dev, linux-kernel@vger.kernel.org, nova-gpu@lists.linux.dev, dri-devel@lists.freedesktop.org, linux-pm@vger.kernel.org, linux-pwm@vger.kernel.org, linux-pci@vger.kernel.org, rust-for-linux@vger.kernel.org, Danilo Krummrich Subject: [PATCH v5 09/24] rust: usb: implement Sync for Device Date: Mon, 25 May 2026 22:20:56 +0200 Message-ID: <20260525202921.124698-10-dakr@kernel.org> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260525202921.124698-1-dakr@kernel.org> References: <20260525202921.124698-1-dakr@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Implement Sync for Device in addition to Device. Device uses the same underlying struct usb_device as Device; Bound is a zero-sized type-state marker that does not affect thread safety. This is needed for drivers to store &'bound usb::Device in their private data while remaining Send. Reviewed-by: Alexandre Courbot Reviewed-by: Gary Guo Reviewed-by: Greg Kroah-Hartman Signed-off-by: Danilo Krummrich --- rust/kernel/usb.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/rust/kernel/usb.rs b/rust/kernel/usb.rs index 88721970afcb..6c917d8fa883 100644 --- a/rust/kernel/usb.rs +++ b/rust/kernel/usb.rs @@ -468,6 +468,10 @@ unsafe impl Send for Device {} // allow any mutation through a shared reference. unsafe impl Sync for Device {} =20 +// SAFETY: Same as `Device` -- the underlying `struct usb_device` = is the same; +// `Bound` is a zero-sized type-state marker that does not affect thread s= afety. +unsafe impl Sync for Device {} + /// Declares a kernel module that exposes a single USB driver. /// /// # Examples --=20 2.54.0 From nobody Mon Jun 8 22:51:08 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D4A83396D2E; Mon, 25 May 2026 20:30:42 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779741044; cv=none; b=WMQtjIZPbR66NW8veRwe6yQl2bLSMwUQVoW175LbhwFzujMKxZ6fvmSW6dSk5v1jkeI8f8n7hQTGJGFwGgFVgFOIM2bwQ3Gyrf+Ak6HzRbTwJOsa+wJL93deKAnI3rFHuNFSaSV8oDW62HQ+vEa7t5iZoQzQk10uC4LUF2BvsNY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779741044; c=relaxed/simple; bh=urF5Rk5jTMNT+4K+VC8PjkjsSN5q9iMcbGqWQJmJOoY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=pX3zclWBATEwl1Z8Uc2w0Q96WWBK1LwVo9Qz5cPJPKkjYwEgWR3b+FGMMxkup15+QImo6vkp/ptFSe00iYCKzrrVxtUvjTEGW/KsNH4CAPPL3guvLMyV0VNevboJUokmnIz6UznaeyWu0m/2nCSjSR/+KSmfhdOnuhqR7MLY1Qw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=ElarxhLU; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="ElarxhLU" Received: by smtp.kernel.org (Postfix) with ESMTPSA id C40B01F000E9; Mon, 25 May 2026 20:30:35 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1779741042; bh=3s2zR/dj1pWywn+EHbTTBpMMpSw/+K1EkrL3Cwr8X6M=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=ElarxhLU1zbvsRiXjQE2HRAf9RzqAxiN+/aY1YzYKn0cMizSvwGYZi9PF1PpXaxBw GN5JcQJb13eg1Ff6z1YZ2xnNT86FQ49B1+oVS8CDfslKwOjRd9sIQ3YKVUdEx1KXrU pEivvJkNRHW9olkpHM84adUi00g9ZpOFGpIhCuAwd8qFCU+K6BeA5HVcVFPeF2lnK/ 6B0TQrgEeerUkPgmUXKVzdmNnkpwIni/5pD04a3pUeG2rGQcr9kVF7EZUKbXA10KwU tBDYO5gySLP9NC5SYrEQiWJ0w24yS74gLlLyydVIppynaFXJObHZxyRc81WQ6e2thP 6p/P3Ttt/5ABw== From: Danilo Krummrich To: gregkh@linuxfoundation.org, rafael@kernel.org, acourbot@nvidia.com, aliceryhl@google.com, david.m.ertman@intel.com, ira.weiny@intel.com, leon@kernel.org, viresh.kumar@linaro.org, m.wilczynski@samsung.com, ukleinek@kernel.org, bhelgaas@google.com, kwilczynski@kernel.org, abdiel.janulgue@gmail.com, robin.murphy@arm.com, markus.probst@posteo.de, ojeda@kernel.org, boqun@kernel.org, gary@garyguo.net, bjorn3_gh@protonmail.com, lossin@kernel.org, a.hindborg@kernel.org, tmgross@umich.edu, igor.korotin@linux.dev, daniel.almeida@collabora.com, pcolberg@redhat.com Cc: driver-core@lists.linux.dev, linux-kernel@vger.kernel.org, nova-gpu@lists.linux.dev, dri-devel@lists.freedesktop.org, linux-pm@vger.kernel.org, linux-pwm@vger.kernel.org, linux-pci@vger.kernel.org, rust-for-linux@vger.kernel.org, Danilo Krummrich Subject: [PATCH v5 10/24] rust: device: implement Sync for Device Date: Mon, 25 May 2026 22:20:57 +0200 Message-ID: <20260525202921.124698-11-dakr@kernel.org> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260525202921.124698-1-dakr@kernel.org> References: <20260525202921.124698-1-dakr@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Implement Sync for Device in addition to Device. Device uses the same underlying struct device as Device; Bound is a zero-sized type-state marker that does not affect thread safety. This is needed for types that hold &'bound Device, such as io::mem::IoMem, to be Send. Reviewed-by: Alexandre Courbot Reviewed-by: Gary Guo Reviewed-by: Greg Kroah-Hartman Signed-off-by: Danilo Krummrich --- rust/kernel/device.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/rust/kernel/device.rs b/rust/kernel/device.rs index 5df8fa108a52..c4486f4b8c40 100644 --- a/rust/kernel/device.rs +++ b/rust/kernel/device.rs @@ -467,6 +467,10 @@ unsafe impl Send for Device {} // synchronization in `struct device`. unsafe impl Sync for Device {} =20 +// SAFETY: Same as `Device` -- the underlying `struct device` is t= he same; `Bound` is a +// zero-sized type-state marker that does not affect thread safety. +unsafe impl Sync for Device {} + /// Marker trait for the context or scope of a bus specific device. /// /// [`DeviceContext`] is a marker trait for types representing the context= of a bus specific --=20 2.54.0 From nobody Mon Jun 8 22:51:08 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id DD623399361; Mon, 25 May 2026 20:30:49 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779741052; cv=none; b=PeIlEVUZKjN8hGHVSBOpVuFa3Ki1H0OISJAyYlW6YVIKXjFhJ0Xv64yFPmYA1CkbdzBltFzAPGtfoJTm8M48WvaAHj2p2glTAKvSTQ8hThHLiPkKkJ5JfbjxqpNNygI7mKLxEWFxf8KkFw7XcOMbOK07A10/1r8O1XcK+FjhoUc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779741052; c=relaxed/simple; bh=50D6t8+0oUtDBOpJDrW3EF3onkyCnc9U1gK9w/evXws=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Zh8qQ3oQtJHKbyaPNAo5Z98zd/UOvI6yflZW/l8DIjYi4BMgV1DQ3UizpT0IE/hXYbF9QzdBTI2eCXyK4tWywmUrEEILpXiR/GPE2yYRAzlkpnkAtxZhqtxXmmo/ALoT8Cb/qRUS350L+oW38Lzs9tgI3SI+QaZ9lmZlSBZVQ50= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=ABHKWEIc; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="ABHKWEIc" Received: by smtp.kernel.org (Postfix) with ESMTPSA id E4CC41F00A3A; Mon, 25 May 2026 20:30:42 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1779741049; bh=qOtdbnxa2fGYScIB4KV2XtQfYAxoC7Df3/OSi2+f/0U=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=ABHKWEIc2deGqW049It1LAJPYGVANHg41nHPtFReYV8ByO9h8NQGl9T9IxBdjtwuu 992t3mVT/DLi+37RUS6gprjwdp2hQDc6Z30Pp7AV3LMZdIBWyUApAkRm2jIzF65vbF COmcnXAlCW0BvhOCpO7zs2YtYDReRQGnAR7hHJzAyJLzCJ22qwwQOQY6jtCZzjIf2l W+bm23qErPpQmTj/yFlj2QGKOSxfes8C8JwD5q+R6ugNQGdkQt8jIKtZVcEo6pyVUh jpgNIc+6mNeYRb/hfPXL1lxdvRUiu5JzLPWNgFfemH0rl9W8lN7xqmD76AMOhccB37 +bQPekMcgjIyQ== From: Danilo Krummrich To: gregkh@linuxfoundation.org, rafael@kernel.org, acourbot@nvidia.com, aliceryhl@google.com, david.m.ertman@intel.com, ira.weiny@intel.com, leon@kernel.org, viresh.kumar@linaro.org, m.wilczynski@samsung.com, ukleinek@kernel.org, bhelgaas@google.com, kwilczynski@kernel.org, abdiel.janulgue@gmail.com, robin.murphy@arm.com, markus.probst@posteo.de, ojeda@kernel.org, boqun@kernel.org, gary@garyguo.net, bjorn3_gh@protonmail.com, lossin@kernel.org, a.hindborg@kernel.org, tmgross@umich.edu, igor.korotin@linux.dev, daniel.almeida@collabora.com, pcolberg@redhat.com Cc: driver-core@lists.linux.dev, linux-kernel@vger.kernel.org, nova-gpu@lists.linux.dev, dri-devel@lists.freedesktop.org, linux-pm@vger.kernel.org, linux-pwm@vger.kernel.org, linux-pci@vger.kernel.org, rust-for-linux@vger.kernel.org, Danilo Krummrich , Eliot Courtney Subject: [PATCH v5 11/24] rust: device: make Core and CoreInternal lifetime-parameterized Date: Mon, 25 May 2026 22:20:58 +0200 Message-ID: <20260525202921.124698-12-dakr@kernel.org> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260525202921.124698-1-dakr@kernel.org> References: <20260525202921.124698-1-dakr@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Device references in probe callbacks are scoped to the callback, not the full binding duration. Add a lifetime parameter to Core and CoreInternal to accurately represent this in the type system. Suggested-by: Gary Guo Reviewed-by: Greg Kroah-Hartman Reviewed-by: Alexandre Courbot Reviewed-by: Eliot Courtney Signed-off-by: Danilo Krummrich Reviewed-by: Gary Guo --- drivers/cpufreq/rcpufreq_dt.rs | 2 +- drivers/gpu/drm/nova/driver.rs | 5 ++- drivers/gpu/drm/tyr/driver.rs | 2 +- drivers/gpu/nova-core/driver.rs | 4 +-- drivers/gpu/nova-core/gpu.rs | 2 +- drivers/pwm/pwm_th1520.rs | 2 +- rust/kernel/auxiliary.rs | 12 ++++--- rust/kernel/cpufreq.rs | 2 +- rust/kernel/device.rs | 49 +++++++++++++++++++++------ rust/kernel/devres.rs | 2 +- rust/kernel/dma.rs | 2 +- rust/kernel/driver.rs | 6 ++-- rust/kernel/i2c.rs | 16 ++++----- rust/kernel/io/mem.rs | 4 +-- rust/kernel/pci.rs | 20 ++++++----- rust/kernel/pci/id.rs | 2 +- rust/kernel/platform.rs | 12 +++---- rust/kernel/usb.rs | 16 ++++----- samples/rust/rust_debugfs.rs | 4 +-- samples/rust/rust_dma.rs | 2 +- samples/rust/rust_driver_auxiliary.rs | 7 ++-- samples/rust/rust_driver_i2c.rs | 6 ++-- samples/rust/rust_driver_pci.rs | 4 +-- samples/rust/rust_driver_platform.rs | 2 +- samples/rust/rust_driver_usb.rs | 8 ++--- samples/rust/rust_i2c_client.rs | 4 +-- samples/rust/rust_soc.rs | 2 +- 27 files changed, 118 insertions(+), 81 deletions(-) diff --git a/drivers/cpufreq/rcpufreq_dt.rs b/drivers/cpufreq/rcpufreq_dt.rs index b7eeb2730eb0..5e0b224f6699 100644 --- a/drivers/cpufreq/rcpufreq_dt.rs +++ b/drivers/cpufreq/rcpufreq_dt.rs @@ -205,7 +205,7 @@ impl platform::Driver for CPUFreqDTDriver { const OF_ID_TABLE: Option> =3D Some(&OF_TABL= E); =20 fn probe( - pdev: &platform::Device, + pdev: &platform::Device>, _id_info: Option<&Self::IdInfo>, ) -> impl PinInit { cpufreq::Registration::::new_foreign_owned(pdev.a= s_ref())?; diff --git a/drivers/gpu/drm/nova/driver.rs b/drivers/gpu/drm/nova/driver.rs index 08136ec0bccb..7605348af994 100644 --- a/drivers/gpu/drm/nova/driver.rs +++ b/drivers/gpu/drm/nova/driver.rs @@ -54,7 +54,10 @@ impl auxiliary::Driver for NovaDriver { type Data =3D Self; const ID_TABLE: auxiliary::IdTable =3D &AUX_TABLE; =20 - fn probe(adev: &auxiliary::Device, _info: &Self::IdInfo) -> impl= PinInit { + fn probe( + adev: &auxiliary::Device>, + _info: &Self::IdInfo, + ) -> impl PinInit { let data =3D try_pin_init!(NovaData { adev: adev.into() }); =20 let drm =3D drm::Device::::new(adev.as_ref(), data)?; diff --git a/drivers/gpu/drm/tyr/driver.rs b/drivers/gpu/drm/tyr/driver.rs index c81bf217743d..001727f44fc8 100644 --- a/drivers/gpu/drm/tyr/driver.rs +++ b/drivers/gpu/drm/tyr/driver.rs @@ -95,7 +95,7 @@ impl platform::Driver for TyrPlatformDriverData { const OF_ID_TABLE: Option> =3D Some(&OF_TABL= E); =20 fn probe( - pdev: &platform::Device, + pdev: &platform::Device>, _info: Option<&Self::IdInfo>, ) -> impl PinInit { let core_clk =3D Clk::get(pdev.as_ref(), Some(c"core"))?; diff --git a/drivers/gpu/nova-core/driver.rs b/drivers/gpu/nova-core/driver= .rs index 699e27046c93..13c5ff15e87f 100644 --- a/drivers/gpu/nova-core/driver.rs +++ b/drivers/gpu/nova-core/driver.rs @@ -77,7 +77,7 @@ impl pci::Driver for NovaCore { type Data =3D Self; const ID_TABLE: pci::IdTable =3D &PCI_TABLE; =20 - fn probe(pdev: &pci::Device, _info: &Self::IdInfo) -> impl PinIn= it { + fn probe(pdev: &pci::Device>, _info: &Self::IdInfo) -> impl P= inInit { pin_init::pin_init_scope(move || { dev_dbg!(pdev, "Probe Nova Core GPU driver.\n"); =20 @@ -109,7 +109,7 @@ fn probe(pdev: &pci::Device, _info: &Self::IdInfo= ) -> impl PinInit, this: Pin<&Self>) { + fn unbind(pdev: &pci::Device>, this: Pin<&Self>) { this.gpu.unbind(pdev.as_ref()); } } diff --git a/drivers/gpu/nova-core/gpu.rs b/drivers/gpu/nova-core/gpu.rs index 0f6fe9a1b955..4ffb506342a9 100644 --- a/drivers/gpu/nova-core/gpu.rs +++ b/drivers/gpu/nova-core/gpu.rs @@ -278,7 +278,7 @@ pub(crate) fn new<'a>( /// Called when the corresponding [`Device`](device::Device) is unboun= d. /// /// Note: This method must only be called from `Driver::unbind`. - pub(crate) fn unbind(&self, dev: &device::Device) { + pub(crate) fn unbind(&self, dev: &device::Device>) { kernel::warn_on!(self .bar .access(dev) diff --git a/drivers/pwm/pwm_th1520.rs b/drivers/pwm/pwm_th1520.rs index 07795910a0b5..df83a4a9a507 100644 --- a/drivers/pwm/pwm_th1520.rs +++ b/drivers/pwm/pwm_th1520.rs @@ -320,7 +320,7 @@ impl platform::Driver for Th1520PwmPlatformDriver { const OF_ID_TABLE: Option> =3D Some(&OF_TABL= E); =20 fn probe( - pdev: &platform::Device, + pdev: &platform::Device>, _id_info: Option<&Self::IdInfo>, ) -> impl PinInit { let dev =3D pdev.as_ref(); diff --git a/rust/kernel/auxiliary.rs b/rust/kernel/auxiliary.rs index df2c97423dcc..6d504b0933d5 100644 --- a/rust/kernel/auxiliary.rs +++ b/rust/kernel/auxiliary.rs @@ -87,7 +87,7 @@ extern "C" fn probe_callback( // `struct auxiliary_device`. // // INVARIANT: `adev` is valid for the duration of `probe_callback(= )`. - let adev =3D unsafe { &*adev.cast::>(= ) }; + let adev =3D unsafe { &*adev.cast::>>() }; =20 // SAFETY: `DeviceId` is a `#[repr(transparent)`] wrapper of `stru= ct auxiliary_device_id` // and does not add additional invariants, so it's safe to transmu= te. @@ -107,7 +107,7 @@ extern "C" fn remove_callback(adev: *mut bindings::auxi= liary_device) { // `struct auxiliary_device`. // // INVARIANT: `adev` is valid for the duration of `remove_callback= ()`. - let adev =3D unsafe { &*adev.cast::>(= ) }; + let adev =3D unsafe { &*adev.cast::>>() }; =20 // SAFETY: `remove_callback` is only ever called after a successfu= l call to // `probe_callback`, hence it's guaranteed that `Device::set_drvda= ta()` has been called @@ -211,8 +211,10 @@ pub trait Driver { /// Auxiliary driver probe. /// /// Called when an auxiliary device is matches a corresponding driver. - fn probe(dev: &Device, id_info: &Self::IdInfo) - -> impl PinInit; + fn probe( + dev: &Device>, + id_info: &Self::IdInfo, + ) -> impl PinInit; =20 /// Auxiliary driver unbind. /// @@ -224,7 +226,7 @@ fn probe(dev: &Device, id_info: &Self::Id= Info) /// operations to gracefully tear down the device. /// /// Otherwise, release operations for driver resources should be perfo= rmed in `Drop`. - fn unbind(dev: &Device, this: Pin<&Self::Data>) { + fn unbind(dev: &Device>, this: Pin<&Self::Data>) { let _ =3D (dev, this); } } diff --git a/rust/kernel/cpufreq.rs b/rust/kernel/cpufreq.rs index 50dd2a2c3e81..0df518fa1d77 100644 --- a/rust/kernel/cpufreq.rs +++ b/rust/kernel/cpufreq.rs @@ -892,7 +892,7 @@ fn register_em(_policy: &mut Policy) { /// const OF_ID_TABLE: Option> =3D None; /// /// fn probe( -/// pdev: &platform::Device, +/// pdev: &platform::Device>, /// _id_info: Option<&Self::IdInfo>, /// ) -> impl PinInit { /// cpufreq::Registration::::new_foreign_owned(pdev.= as_ref())?; diff --git a/rust/kernel/device.rs b/rust/kernel/device.rs index c4486f4b8c40..645afc49a27d 100644 --- a/rust/kernel/device.rs +++ b/rust/kernel/device.rs @@ -201,7 +201,7 @@ pub unsafe fn as_bound(&self) -> &Device { } } =20 -impl Device { +impl<'a> Device> { /// Store a pointer to the bound driver's private data. pub fn set_drvdata(&self, data: impl PinInit) -> Result { let data =3D KBox::pin_init(data, GFP_KERNEL)?; @@ -511,7 +511,7 @@ pub trait DeviceContext: private::Sealed {} /// callback it appears in. It is intended to be used for synchronization = purposes. Bus device /// implementations can implement methods for [`Device`], such that = they can only be called /// from bus callbacks. -pub struct Core; +pub struct Core<'a>(PhantomData<&'a ()>); =20 /// Semantically the same as [`Core`], but reserved for internal usage of = the corresponding bus /// abstraction. @@ -522,7 +522,7 @@ pub trait DeviceContext: private::Sealed {} /// /// This context mainly exists to share generic [`Device`] infrastructure = that should only be called /// from bus callbacks with bus abstractions, but without making them acce= ssible for drivers. -pub struct CoreInternal; +pub struct CoreInternal<'a>(PhantomData<&'a ()>); =20 /// The [`Bound`] context is the [`DeviceContext`] of a bus specific devic= e when it is guaranteed to /// be bound to a driver. @@ -546,14 +546,14 @@ mod private { pub trait Sealed {} =20 impl Sealed for super::Bound {} - impl Sealed for super::Core {} - impl Sealed for super::CoreInternal {} + impl<'a> Sealed for super::Core<'a> {} + impl<'a> Sealed for super::CoreInternal<'a> {} impl Sealed for super::Normal {} } =20 impl DeviceContext for Bound {} -impl DeviceContext for Core {} -impl DeviceContext for CoreInternal {} +impl<'a> DeviceContext for Core<'a> {} +impl<'a> DeviceContext for CoreInternal<'a> {} impl DeviceContext for Normal {} =20 impl AsRef> for Device { @@ -603,6 +603,22 @@ unsafe fn from_device(dev: &Device) -> &Self #[doc(hidden)] #[macro_export] macro_rules! __impl_device_context_deref { + (unsafe { $device:ident, <$lt:lifetime> $src:ty =3D> $dst:ty }) =3D> { + impl<$lt> ::core::ops::Deref for $device<$src> { + type Target =3D $device<$dst>; + + fn deref(&self) -> &Self::Target { + let ptr: *const Self =3D self; + + // CAST: `$device<$src>` and `$device<$dst>` transparently= wrap the same type by the + // safety requirement of the macro. + let ptr =3D ptr.cast::(); + + // SAFETY: `ptr` was derived from `&self`. + unsafe { &*ptr } + } + } + }; (unsafe { $device:ident, $src:ty =3D> $dst:ty }) =3D> { impl ::core::ops::Deref for $device<$src> { type Target =3D $device<$dst>; @@ -635,14 +651,14 @@ macro_rules! impl_device_context_deref { // `__impl_device_context_deref!`. ::kernel::__impl_device_context_deref!(unsafe { $device, - $crate::device::CoreInternal =3D> $crate::device::Core + <'a> $crate::device::CoreInternal<'a> =3D> $crate::device::Cor= e<'a> }); =20 // SAFETY: This macro has the exact same safety requirement as // `__impl_device_context_deref!`. ::kernel::__impl_device_context_deref!(unsafe { $device, - $crate::device::Core =3D> $crate::device::Bound + <'a> $crate::device::Core<'a> =3D> $crate::device::Bound }); =20 // SAFETY: This macro has the exact same safety requirement as @@ -657,6 +673,13 @@ macro_rules! impl_device_context_deref { #[doc(hidden)] #[macro_export] macro_rules! __impl_device_context_into_aref { + (<$lt:lifetime> $src:ty, $device:tt) =3D> { + impl<$lt> ::core::convert::From<&$device<$src>> for $crate::sync::= aref::ARef<$device> { + fn from(dev: &$device<$src>) -> Self { + (&**dev).into() + } + } + }; ($src:ty, $device:tt) =3D> { impl ::core::convert::From<&$device<$src>> for $crate::sync::aref:= :ARef<$device> { fn from(dev: &$device<$src>) -> Self { @@ -671,8 +694,12 @@ fn from(dev: &$device<$src>) -> Self { #[macro_export] macro_rules! impl_device_context_into_aref { ($device:tt) =3D> { - ::kernel::__impl_device_context_into_aref!($crate::device::CoreInt= ernal, $device); - ::kernel::__impl_device_context_into_aref!($crate::device::Core, $= device); + ::kernel::__impl_device_context_into_aref!( + <'a> $crate::device::CoreInternal<'a>, $device + ); + ::kernel::__impl_device_context_into_aref!( + <'a> $crate::device::Core<'a>, $device + ); ::kernel::__impl_device_context_into_aref!($crate::device::Bound, = $device); }; } diff --git a/rust/kernel/devres.rs b/rust/kernel/devres.rs index 9e5f93aed20c..fd4633f977f6 100644 --- a/rust/kernel/devres.rs +++ b/rust/kernel/devres.rs @@ -304,7 +304,7 @@ pub fn device(&self) -> &Device { /// pci, // /// }; /// - /// fn from_core(dev: &pci::Device, devres: Devres= >) -> Result { + /// fn from_core(dev: &pci::Device>, devres: Devres>) -> Result { /// let bar =3D devres.access(dev.as_ref())?; /// /// let _ =3D bar.read32(0x0); diff --git a/rust/kernel/dma.rs b/rust/kernel/dma.rs index 4995ee5dc689..8f97916e0688 100644 --- a/rust/kernel/dma.rs +++ b/rust/kernel/dma.rs @@ -47,7 +47,7 @@ /// where the underlying bus is DMA capable, such as: #[cfg_attr(CONFIG_PCI, doc =3D "* [`pci::Device`](kernel::pci::Device)")] /// * [`platform::Device`](::kernel::platform::Device) -pub trait Device: AsRef> { +pub trait Device<'a>: AsRef>> { /// Set up the device's DMA streaming addressing capabilities. /// /// This method is usually called once from `probe()` as soon as the d= evice capabilities are diff --git a/rust/kernel/driver.rs b/rust/kernel/driver.rs index a95dafaa9d68..558fdef4a1c6 100644 --- a/rust/kernel/driver.rs +++ b/rust/kernel/driver.rs @@ -27,11 +27,11 @@ //! const ACPI_ID_TABLE: Option> =3D None; //! //! /// Driver probe. -//! fn probe(dev: &Device, id_info: &Self::IdInfo) +//! fn probe(dev: &Device>, id_info: &Self::IdInfo) //! -> impl PinInit; //! //! /// Driver unbind (optional). -//! fn unbind(dev: &Device, this: Pin<&Self::Data>) { +//! fn unbind(dev: &Device>, this: Pin<&Self::Data>) { //! let _ =3D (dev, this); //! } //! } @@ -191,7 +191,7 @@ extern "C" fn post_unbind_callback(dev: *mut bindings::= device) { // a `struct device`. // // INVARIANT: `dev` is valid for the duration of the `post_unbind_= callback()`. - let dev =3D unsafe { &*dev.cast::>() }; + let dev =3D unsafe { &*dev.cast::>>() }; =20 // `remove()` has been completed at this point; devres resources a= re still valid and will // be released after the driver's bus device private data is dropp= ed. diff --git a/rust/kernel/i2c.rs b/rust/kernel/i2c.rs index bfd081518615..50feade0fb58 100644 --- a/rust/kernel/i2c.rs +++ b/rust/kernel/i2c.rs @@ -157,7 +157,7 @@ extern "C" fn probe_callback(idev: *mut bindings::i2c_c= lient) -> kernel::ffi::c_ // `struct i2c_client`. // // INVARIANT: `idev` is valid for the duration of `probe_callback(= )`. - let idev =3D unsafe { &*idev.cast::>() }; + let idev =3D unsafe { &*idev.cast::>>() }; =20 let info =3D Self::i2c_id_info(idev).or_else(|| ::= id_info(idev.as_ref())); @@ -172,7 +172,7 @@ extern "C" fn probe_callback(idev: *mut bindings::i2c_c= lient) -> kernel::ffi::c_ =20 extern "C" fn remove_callback(idev: *mut bindings::i2c_client) { // SAFETY: `idev` is a valid pointer to a `struct i2c_client`. - let idev =3D unsafe { &*idev.cast::>() }; + let idev =3D unsafe { &*idev.cast::>>() }; =20 // SAFETY: `remove_callback` is only ever called after a successfu= l call to // `probe_callback`, hence it's guaranteed that `I2cClient::set_dr= vdata()` has been called @@ -184,7 +184,7 @@ extern "C" fn remove_callback(idev: *mut bindings::i2c_= client) { =20 extern "C" fn shutdown_callback(idev: *mut bindings::i2c_client) { // SAFETY: `shutdown_callback` is only ever called for a valid `id= ev` - let idev =3D unsafe { &*idev.cast::>() }; + let idev =3D unsafe { &*idev.cast::>>() }; =20 // SAFETY: `shutdown_callback` is only ever called after a success= ful call to // `probe_callback`, hence it's guaranteed that `Device::set_drvda= ta()` has been called @@ -300,13 +300,13 @@ macro_rules! module_i2c_driver { /// const ACPI_ID_TABLE: Option> =3D Some(= &ACPI_TABLE); /// /// fn probe( -/// _idev: &i2c::I2cClient, +/// _idev: &i2c::I2cClient>, /// _id_info: Option<&Self::IdInfo>, /// ) -> impl PinInit { /// Err(ENODEV) /// } /// -/// fn shutdown(_idev: &i2c::I2cClient, this: Pin<&Self::Data>) { +/// fn shutdown(_idev: &i2c::I2cClient>, this: Pin<&Self::Dat= a>) { /// } /// } ///``` @@ -336,7 +336,7 @@ pub trait Driver { /// Called when a new i2c client is added or discovered. /// Implementers should attempt to initialize the client here. fn probe( - dev: &I2cClient, + dev: &I2cClient>, id_info: Option<&Self::IdInfo>, ) -> impl PinInit; =20 @@ -351,7 +351,7 @@ fn probe( /// This callback is distinct from final resource cleanup, as the driv= er instance remains valid /// after it returns. Any deallocation or teardown of driver-owned res= ources should instead be /// handled in `Drop`. - fn shutdown(dev: &I2cClient, this: Pin<&Self::Data>) { + fn shutdown(dev: &I2cClient>, this: Pin<&Self::Data>)= { let _ =3D (dev, this); } =20 @@ -365,7 +365,7 @@ fn shutdown(dev: &I2cClient, this: Pin<&S= elf::Data>) { /// operations to gracefully tear down the device. /// /// Otherwise, release operations for driver resources should be perfo= rmed in `Drop`. - fn unbind(dev: &I2cClient, this: Pin<&Self::Data>) { + fn unbind(dev: &I2cClient>, this: Pin<&Self::Data>) { let _ =3D (dev, this); } } diff --git a/rust/kernel/io/mem.rs b/rust/kernel/io/mem.rs index e136b676d372..03d8745b5e1d 100644 --- a/rust/kernel/io/mem.rs +++ b/rust/kernel/io/mem.rs @@ -65,7 +65,7 @@ pub(crate) unsafe fn new(device: &'a Device, resou= rce: &'a Resource) -> S /// # type Data =3D Self; /// /// fn probe( - /// pdev: &platform::Device, + /// pdev: &platform::Device>, /// info: Option<&Self::IdInfo>, /// ) -> impl PinInit { /// let offset =3D 0; // Some offset. @@ -130,7 +130,7 @@ pub fn iomap_exclusive_sized( /// # type Data =3D Self; /// /// fn probe( - /// pdev: &platform::Device, + /// pdev: &platform::Device>, /// info: Option<&Self::IdInfo>, /// ) -> impl PinInit { /// let offset =3D 0; // Some offset. diff --git a/rust/kernel/pci.rs b/rust/kernel/pci.rs index d214a861375d..314ad9fefdb0 100644 --- a/rust/kernel/pci.rs +++ b/rust/kernel/pci.rs @@ -105,7 +105,7 @@ extern "C" fn probe_callback( // `struct pci_dev`. // // INVARIANT: `pdev` is valid for the duration of `probe_callback(= )`. - let pdev =3D unsafe { &*pdev.cast::>(= ) }; + let pdev =3D unsafe { &*pdev.cast::>>() }; =20 // SAFETY: `DeviceId` is a `#[repr(transparent)]` wrapper of `stru= ct pci_device_id` and // does not add additional invariants, so it's safe to transmute. @@ -125,7 +125,7 @@ extern "C" fn remove_callback(pdev: *mut bindings::pci_= dev) { // `struct pci_dev`. // // INVARIANT: `pdev` is valid for the duration of `remove_callback= ()`. - let pdev =3D unsafe { &*pdev.cast::>(= ) }; + let pdev =3D unsafe { &*pdev.cast::>>() }; =20 // SAFETY: `remove_callback` is only ever called after a successfu= l call to // `probe_callback`, hence it's guaranteed that `Device::set_drvda= ta()` has been called @@ -283,7 +283,7 @@ macro_rules! pci_device_table { /// const ID_TABLE: pci::IdTable =3D &PCI_TABLE; /// /// fn probe( -/// _pdev: &pci::Device, +/// _pdev: &pci::Device>, /// _id_info: &Self::IdInfo, /// ) -> impl PinInit { /// Err(ENODEV) @@ -311,8 +311,10 @@ pub trait Driver { /// /// Called when a new pci device is added or discovered. Implementers = should /// attempt to initialize the device here. - fn probe(dev: &Device, id_info: &Self::IdInfo) - -> impl PinInit; + fn probe( + dev: &Device>, + id_info: &Self::IdInfo, + ) -> impl PinInit; =20 /// PCI driver unbind. /// @@ -324,7 +326,7 @@ fn probe(dev: &Device, id_info: &Self::Id= Info) /// operations to gracefully tear down the device. /// /// Otherwise, release operations for driver resources should be perfo= rmed in `Drop`. - fn unbind(dev: &Device, this: Pin<&Self::Data>) { + fn unbind(dev: &Device>, this: Pin<&Self::Data>) { let _ =3D (dev, this); } } @@ -359,7 +361,7 @@ impl Device { /// /// ``` /// # use kernel::{device::Core, pci::{self, Vendor}, prelude::*}; - /// fn log_device_info(pdev: &pci::Device) -> Result { + /// fn log_device_info(pdev: &pci::Device>) -> Result { /// // Get an instance of `Vendor`. /// let vendor =3D pdev.vendor_id(); /// dev_info!( @@ -450,7 +452,7 @@ pub fn pci_class(&self) -> Class { } } =20 -impl Device { +impl<'a> Device> { /// Enable memory resources for this device. pub fn enable_device_mem(&self) -> Result { // SAFETY: `self.as_raw` is guaranteed to be a pointer to a valid = `struct pci_dev`. @@ -476,7 +478,7 @@ unsafe impl device::AsBusDe= vice for Device kernel::impl_device_context_deref!(unsafe { Device }); kernel::impl_device_context_into_aref!(Device); =20 -impl crate::dma::Device for Device {} +impl<'a> crate::dma::Device<'a> for Device> {} =20 // SAFETY: Instances of `Device` are always reference-counted. unsafe impl crate::sync::aref::AlwaysRefCounted for Device { diff --git a/rust/kernel/pci/id.rs b/rust/kernel/pci/id.rs index 50005d176561..dbaf301666e7 100644 --- a/rust/kernel/pci/id.rs +++ b/rust/kernel/pci/id.rs @@ -19,7 +19,7 @@ /// /// ``` /// # use kernel::{device::Core, pci::{self, Class}, prelude::*}; -/// fn probe_device(pdev: &pci::Device) -> Result { +/// fn probe_device(pdev: &pci::Device>) -> Result { /// let pci_class =3D pdev.pci_class(); /// dev_info!( /// pdev, diff --git a/rust/kernel/platform.rs b/rust/kernel/platform.rs index 106a5ed57ea6..257b7084338c 100644 --- a/rust/kernel/platform.rs +++ b/rust/kernel/platform.rs @@ -97,7 +97,7 @@ extern "C" fn probe_callback(pdev: *mut bindings::platfor= m_device) -> kernel::ff // `struct platform_device`. // // INVARIANT: `pdev` is valid for the duration of `probe_callback(= )`. - let pdev =3D unsafe { &*pdev.cast::>(= ) }; + let pdev =3D unsafe { &*pdev.cast::>>() }; let info =3D ::id_info(pdev.as_ref()); =20 from_result(|| { @@ -113,7 +113,7 @@ extern "C" fn remove_callback(pdev: *mut bindings::plat= form_device) { // `struct platform_device`. // // INVARIANT: `pdev` is valid for the duration of `remove_callback= ()`. - let pdev =3D unsafe { &*pdev.cast::>(= ) }; + let pdev =3D unsafe { &*pdev.cast::>>() }; =20 // SAFETY: `remove_callback` is only ever called after a successfu= l call to // `probe_callback`, hence it's guaranteed that `Device::set_drvda= ta()` has been called @@ -197,7 +197,7 @@ macro_rules! module_platform_driver { /// const ACPI_ID_TABLE: Option> =3D Some(= &ACPI_TABLE); /// /// fn probe( -/// _pdev: &platform::Device, +/// _pdev: &platform::Device>, /// _id_info: Option<&Self::IdInfo>, /// ) -> impl PinInit { /// Err(ENODEV) @@ -227,7 +227,7 @@ pub trait Driver { /// Called when a new platform device is added or discovered. /// Implementers should attempt to initialize the device here. fn probe( - dev: &Device, + dev: &Device>, id_info: Option<&Self::IdInfo>, ) -> impl PinInit; =20 @@ -241,7 +241,7 @@ fn probe( /// operations to gracefully tear down the device. /// /// Otherwise, release operations for driver resources should be perfo= rmed in `Drop`. - fn unbind(dev: &Device, this: Pin<&Self::Data>) { + fn unbind(dev: &Device>, this: Pin<&Self::Data>) { let _ =3D (dev, this); } } @@ -513,7 +513,7 @@ pub fn optional_irq_by_name(&self, name: &CStr) -> Resu= lt> { kernel::impl_device_context_deref!(unsafe { Device }); kernel::impl_device_context_into_aref!(Device); =20 -impl crate::dma::Device for Device {} +impl<'a> crate::dma::Device<'a> for Device> {} =20 // SAFETY: Instances of `Device` are always reference-counted. unsafe impl crate::sync::aref::AlwaysRefCounted for Device { diff --git a/rust/kernel/usb.rs b/rust/kernel/usb.rs index 6c917d8fa883..1dbb8387b463 100644 --- a/rust/kernel/usb.rs +++ b/rust/kernel/usb.rs @@ -82,7 +82,7 @@ extern "C" fn probe_callback( // `struct usb_interface` and `struct usb_device_id`. // // INVARIANT: `intf` is valid for the duration of `probe_callback(= )`. - let intf =3D unsafe { &*intf.cast::>() }; + let intf =3D unsafe { &*intf.cast::>>() }; =20 from_result(|| { // SAFETY: `DeviceId` is a `#[repr(transparent)]` wrapper of `= struct usb_device_id` and @@ -92,7 +92,7 @@ extern "C" fn probe_callback( let info =3D T::ID_TABLE.info(id.index()); let data =3D T::probe(intf, id, info); =20 - let dev: &device::Device =3D intf.as_ref= (); + let dev: &device::Device> =3D intf.as= _ref(); dev.set_drvdata(data)?; Ok(0) }) @@ -103,9 +103,9 @@ extern "C" fn disconnect_callback(intf: *mut bindings::= usb_interface) { // `struct usb_interface`. // // INVARIANT: `intf` is valid for the duration of `disconnect_call= back()`. - let intf =3D unsafe { &*intf.cast::>() }; + let intf =3D unsafe { &*intf.cast::>>() }; =20 - let dev: &device::Device =3D intf.as_ref(); + let dev: &device::Device> =3D intf.as_ref= (); =20 // SAFETY: `disconnect_callback` is only ever called after a succe= ssful call to // `probe_callback`, hence it's guaranteed that `Device::set_drvda= ta()` has been called @@ -291,14 +291,14 @@ macro_rules! usb_device_table { /// const ID_TABLE: usb::IdTable =3D &USB_TABLE; /// /// fn probe( -/// _interface: &usb::Interface, +/// _interface: &usb::Interface>, /// _id: &usb::DeviceId, /// _info: &Self::IdInfo, /// ) -> impl PinInit { /// Err(ENODEV) /// } /// -/// fn disconnect(_interface: &usb::Interface, _data: Pin<&Self:= :Data>) {} +/// fn disconnect(_interface: &usb::Interface>, _data: Pin<&S= elf::Data>) {} /// } ///``` pub trait Driver { @@ -316,7 +316,7 @@ pub trait Driver { /// Called when a new USB interface is bound to this driver. /// Implementers should attempt to initialize the interface here. fn probe( - interface: &Interface, + interface: &Interface>, id: &DeviceId, id_info: &Self::IdInfo, ) -> impl PinInit; @@ -324,7 +324,7 @@ fn probe( /// USB driver disconnect. /// /// Called when the USB interface is about to be unbound from this dri= ver. - fn disconnect(interface: &Interface, data: Pin<&Self::Da= ta>); + fn disconnect(interface: &Interface>, data: Pin<&Self= ::Data>); } =20 /// A USB interface. diff --git a/samples/rust/rust_debugfs.rs b/samples/rust/rust_debugfs.rs index 478c4f693deb..37640ed33642 100644 --- a/samples/rust/rust_debugfs.rs +++ b/samples/rust/rust_debugfs.rs @@ -122,7 +122,7 @@ impl platform::Driver for RustDebugFs { const ACPI_ID_TABLE: Option> =3D Some(&ACP= I_TABLE); =20 fn probe( - pdev: &platform::Device, + pdev: &platform::Device>, _info: Option<&Self::IdInfo>, ) -> impl PinInit { RustDebugFs::new(pdev).pin_chain(|this| { @@ -147,7 +147,7 @@ fn build_inner(dir: &Dir) -> impl PinInit>> + '_ { dir.read_write_file(c"pair", new_mutex!(Inner { x: 3, y: 10 })) } =20 - fn new(pdev: &platform::Device) -> impl PinInit + '= _ { + fn new<'a>(pdev: &'a platform::Device>) -> impl PinInit + 'a { let debugfs =3D Dir::new(c"sample_debugfs"); let dev =3D pdev.as_ref(); =20 diff --git a/samples/rust/rust_dma.rs b/samples/rust/rust_dma.rs index e583c6b8390a..9a243e7c7298 100644 --- a/samples/rust/rust_dma.rs +++ b/samples/rust/rust_dma.rs @@ -61,7 +61,7 @@ impl pci::Driver for DmaSampleDriver { type Data =3D Self; const ID_TABLE: pci::IdTable =3D &PCI_TABLE; =20 - fn probe(pdev: &pci::Device, _info: &Self::IdInfo) -> impl PinIn= it { + fn probe(pdev: &pci::Device>, _info: &Self::IdInfo) -> impl P= inInit { pin_init::pin_init_scope(move || { dev_info!(pdev, "Probe DMA test driver.\n"); =20 diff --git a/samples/rust/rust_driver_auxiliary.rs b/samples/rust/rust_driv= er_auxiliary.rs index 61d5bf2e8c0d..f0d419823f9a 100644 --- a/samples/rust/rust_driver_auxiliary.rs +++ b/samples/rust/rust_driver_auxiliary.rs @@ -35,7 +35,10 @@ impl auxiliary::Driver for AuxiliaryDriver { =20 const ID_TABLE: auxiliary::IdTable =3D &AUX_TABLE; =20 - fn probe(adev: &auxiliary::Device, _info: &Self::IdInfo) -> impl= PinInit { + fn probe( + adev: &auxiliary::Device>, + _info: &Self::IdInfo, + ) -> impl PinInit { dev_info!( adev, "Probing auxiliary driver for auxiliary device with id=3D{}\n", @@ -70,7 +73,7 @@ impl pci::Driver for ParentDriver { =20 const ID_TABLE: pci::IdTable =3D &PCI_TABLE; =20 - fn probe(pdev: &pci::Device, _info: &Self::IdInfo) -> impl PinIn= it { + fn probe(pdev: &pci::Device>, _info: &Self::IdInfo) -> impl P= inInit { Ok(Self { _reg0: auxiliary::Registration::new( pdev.as_ref(), diff --git a/samples/rust/rust_driver_i2c.rs b/samples/rust/rust_driver_i2c= .rs index 8269f1798611..171550ea0b6f 100644 --- a/samples/rust/rust_driver_i2c.rs +++ b/samples/rust/rust_driver_i2c.rs @@ -42,7 +42,7 @@ impl i2c::Driver for SampleDriver { const OF_ID_TABLE: Option> =3D Some(&OF_TABL= E); =20 fn probe( - idev: &i2c::I2cClient, + idev: &i2c::I2cClient>, info: Option<&Self::IdInfo>, ) -> impl PinInit { let dev =3D idev.as_ref(); @@ -56,11 +56,11 @@ fn probe( Ok(Self) } =20 - fn shutdown(idev: &i2c::I2cClient, _this: Pin<&Self>) { + fn shutdown(idev: &i2c::I2cClient>, _this: Pin<&Self>) { dev_info!(idev.as_ref(), "Shutdown Rust I2C driver sample.\n"); } =20 - fn unbind(idev: &i2c::I2cClient, _this: Pin<&Self>) { + fn unbind(idev: &i2c::I2cClient>, _this: Pin<&Self>) { dev_info!(idev.as_ref(), "Unbind Rust I2C driver sample.\n"); } } diff --git a/samples/rust/rust_driver_pci.rs b/samples/rust/rust_driver_pci= .rs index f43c6a660b39..3106f766fd93 100644 --- a/samples/rust/rust_driver_pci.rs +++ b/samples/rust/rust_driver_pci.rs @@ -144,7 +144,7 @@ impl pci::Driver for SampleDriver { =20 const ID_TABLE: pci::IdTable =3D &PCI_TABLE; =20 - fn probe(pdev: &pci::Device, info: &Self::IdInfo) -> impl PinIni= t { + fn probe(pdev: &pci::Device>, info: &Self::IdInfo) -> impl Pi= nInit { pin_init::pin_init_scope(move || { let vendor =3D pdev.vendor_id(); dev_dbg!( @@ -175,7 +175,7 @@ fn probe(pdev: &pci::Device, info: &Self::IdInfo)= -> impl PinInit, this: Pin<&Self>) { + fn unbind(pdev: &pci::Device>, this: Pin<&Self>) { if let Ok(bar) =3D this.bar.access(pdev.as_ref()) { // Reset pci-testdev by writing a new test index. bar.write_reg(regs::TEST::zeroed().with_index(this.index)); diff --git a/samples/rust/rust_driver_platform.rs b/samples/rust/rust_drive= r_platform.rs index 6505902f8200..04d40f836275 100644 --- a/samples/rust/rust_driver_platform.rs +++ b/samples/rust/rust_driver_platform.rs @@ -106,7 +106,7 @@ impl platform::Driver for SampleDriver { const ACPI_ID_TABLE: Option> =3D Some(&ACP= I_TABLE); =20 fn probe( - pdev: &platform::Device, + pdev: &platform::Device>, info: Option<&Self::IdInfo>, ) -> impl PinInit { let dev =3D pdev.as_ref(); diff --git a/samples/rust/rust_driver_usb.rs b/samples/rust/rust_driver_usb= .rs index 5942e4b01fd8..e900993335e9 100644 --- a/samples/rust/rust_driver_usb.rs +++ b/samples/rust/rust_driver_usb.rs @@ -30,18 +30,18 @@ impl usb::Driver for SampleDriver { const ID_TABLE: usb::IdTable =3D &USB_TABLE; =20 fn probe( - intf: &usb::Interface, + intf: &usb::Interface>, _id: &usb::DeviceId, _info: &Self::IdInfo, ) -> impl PinInit { - let dev: &device::Device =3D intf.as_ref(); + let dev: &device::Device> =3D intf.as_ref(); dev_info!(dev, "Rust USB driver sample probed\n"); =20 Ok(Self { _intf: intf.into() }) } =20 - fn disconnect(intf: &usb::Interface, _data: Pin<&Self>) { - let dev: &device::Device =3D intf.as_ref(); + fn disconnect(intf: &usb::Interface>, _data: Pin<&Self>) { + let dev: &device::Device> =3D intf.as_ref(); dev_info!(dev, "Rust USB driver sample disconnected\n"); } } diff --git a/samples/rust/rust_i2c_client.rs b/samples/rust/rust_i2c_client= .rs index 5956b647294d..3f273c754f86 100644 --- a/samples/rust/rust_i2c_client.rs +++ b/samples/rust/rust_i2c_client.rs @@ -111,7 +111,7 @@ impl platform::Driver for SampleDriver { const ACPI_ID_TABLE: Option> =3D Some(&ACP= I_TABLE); =20 fn probe( - pdev: &platform::Device, + pdev: &platform::Device>, _info: Option<&Self::IdInfo>, ) -> impl PinInit { dev_info!( @@ -130,7 +130,7 @@ fn probe( }) } =20 - fn unbind(pdev: &platform::Device, _this: Pin<&Self>) { + fn unbind(pdev: &platform::Device>, _this: Pin<&Self>= ) { dev_info!( pdev.as_ref(), "Unbind Rust I2C Client registration sample.\n" diff --git a/samples/rust/rust_soc.rs b/samples/rust/rust_soc.rs index a5e72582f4a2..c466653491d2 100644 --- a/samples/rust/rust_soc.rs +++ b/samples/rust/rust_soc.rs @@ -42,7 +42,7 @@ impl platform::Driver for SampleSocDriver { const ACPI_ID_TABLE: Option> =3D Some(&ACP= I_TABLE); =20 fn probe( - pdev: &platform::Device, + pdev: &platform::Device>, _info: Option<&Self::IdInfo>, ) -> impl PinInit { dev_dbg!(pdev, "Probe Rust SoC driver sample.\n"); --=20 2.54.0 From nobody Mon Jun 8 22:51:08 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4D89D39659A; Mon, 25 May 2026 20:30:57 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779741058; cv=none; b=GadXM1OX5dIwiFMjZAXnh5UH3dX/U52fxlRrmY1XIw8p9lhmCmaHf7bQTPThfpb5iaGct+4W2fQktm/GI0YK3AOOUozdnO7nyVplqZOyDqrsFmrAdoqezTVHWiSJ6If+RRQikbYY7zYl8AfgXEFMrIcHD8KVrGL3sKIlimSRays= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779741058; c=relaxed/simple; bh=fXaeSDfREP9bnZmI++n2HCNRWeF6gSJAy1bOeUTJZBs=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=bFWGWGT8TwJLfR4IiHIczLEiW56uM0RbMmDI5w1zvH+R3QOimD3bCQTBGpbBmGDzdWT37oHV6uo4Cfv2qyeGmWe0BkiN0uPmb+hWrRunvXR0KoUei5hPa3iBlLMzH47V87/zTGsRteIL6UjZ6LwwBdotS70rZnGZ2OjCUB8fNaY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=ZC2dqR/4; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="ZC2dqR/4" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 3E8E61F00A3C; Mon, 25 May 2026 20:30:50 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1779741056; bh=e/ruxIt7bItp6WoB6RoFUctWcJsAU8bvZ7E04s5i07s=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=ZC2dqR/43O+aW71wvrxhcPbTT8rx28Ss+RWd0NNHTHxaEox3omWo/PL3SLe1meEfg uBjLTPCFkhHp7AbuxBGmIV76NvHn9g9+Q9akInpFtQIazWRkmWB7Q8mgmZdR50gMIz RHT/kD13vE2A2AhFybNnNnmJv1O8WGTN9R5Ab+Y3fdujiDuShbjNs5FzAcxx+qcApl Rbvx6Qh3We5lwpuRVHaOA0uP3UkkgoRtFueoAtGtcjJEuiN6KU7gTqjblyztCc1Dr7 fCP1rc3epAZV8m5kqhp7JJFuy3aavMgi7Bfy4OCwFLAje0wPYPt27mXift62bOV/Cn AUiBb8QQE+P4w== From: Danilo Krummrich To: gregkh@linuxfoundation.org, rafael@kernel.org, acourbot@nvidia.com, aliceryhl@google.com, david.m.ertman@intel.com, ira.weiny@intel.com, leon@kernel.org, viresh.kumar@linaro.org, m.wilczynski@samsung.com, ukleinek@kernel.org, bhelgaas@google.com, kwilczynski@kernel.org, abdiel.janulgue@gmail.com, robin.murphy@arm.com, markus.probst@posteo.de, ojeda@kernel.org, boqun@kernel.org, gary@garyguo.net, bjorn3_gh@protonmail.com, lossin@kernel.org, a.hindborg@kernel.org, tmgross@umich.edu, igor.korotin@linux.dev, daniel.almeida@collabora.com, pcolberg@redhat.com Cc: driver-core@lists.linux.dev, linux-kernel@vger.kernel.org, nova-gpu@lists.linux.dev, dri-devel@lists.freedesktop.org, linux-pm@vger.kernel.org, linux-pwm@vger.kernel.org, linux-pci@vger.kernel.org, rust-for-linux@vger.kernel.org, Danilo Krummrich Subject: [PATCH v5 12/24] rust: pci: make Driver trait lifetime-parameterized Date: Mon, 25 May 2026 22:20:59 +0200 Message-ID: <20260525202921.124698-13-dakr@kernel.org> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260525202921.124698-1-dakr@kernel.org> References: <20260525202921.124698-1-dakr@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add a 'bound lifetime to the associated Data, changing type Data to type Data<'bound>. This allows the driver's bus device private data to capture the device / driver bound lifetime; device resources can be stored directly by reference rather than requiring Devres. The probe() and unbind() callbacks thus gain a 'bound lifetime parameter on the methods themselves; avoiding a global lifetime on the trait impl. Existing drivers set type Data<'bound> =3D Self, preserving the current behavior. Reviewed-by: Alexandre Courbot Reviewed-by: Greg Kroah-Hartman Signed-off-by: Danilo Krummrich Reviewed-by: Gary Guo --- drivers/gpu/nova-core/driver.rs | 9 ++++++--- rust/kernel/pci.rs | 28 +++++++++++++-------------- samples/rust/rust_dma.rs | 7 +++++-- samples/rust/rust_driver_auxiliary.rs | 7 +++++-- samples/rust/rust_driver_pci.rs | 7 +++++-- 5 files changed, 35 insertions(+), 23 deletions(-) diff --git a/drivers/gpu/nova-core/driver.rs b/drivers/gpu/nova-core/driver= .rs index 13c5ff15e87f..6ad1a856694c 100644 --- a/drivers/gpu/nova-core/driver.rs +++ b/drivers/gpu/nova-core/driver.rs @@ -74,10 +74,13 @@ pub(crate) struct NovaCore { =20 impl pci::Driver for NovaCore { type IdInfo =3D (); - type Data =3D Self; + type Data<'bound> =3D Self; const ID_TABLE: pci::IdTable =3D &PCI_TABLE; =20 - fn probe(pdev: &pci::Device>, _info: &Self::IdInfo) -> impl P= inInit { + fn probe<'bound>( + pdev: &'bound pci::Device>, + _info: &'bound Self::IdInfo, + ) -> impl PinInit + 'bound { pin_init::pin_init_scope(move || { dev_dbg!(pdev, "Probe Nova Core GPU driver.\n"); =20 @@ -109,7 +112,7 @@ fn probe(pdev: &pci::Device>, _info: &Self::Id= Info) -> impl PinInit>, this: Pin<&Self>) { + fn unbind<'bound>(pdev: &'bound pci::Device>, this: Pin<&Self= >) { this.gpu.unbind(pdev.as_ref()); } } diff --git a/rust/kernel/pci.rs b/rust/kernel/pci.rs index 314ad9fefdb0..5071cae6543f 100644 --- a/rust/kernel/pci.rs +++ b/rust/kernel/pci.rs @@ -64,7 +64,7 @@ // - `DEVICE_DRIVER_OFFSET` is the correct byte offset to the embedded `st= ruct device_driver`. unsafe impl driver::DriverLayout for Adapter { type DriverType =3D bindings::pci_driver; - type DriverData<'bound> =3D T::Data; + type DriverData<'bound> =3D T::Data<'bound>; const DEVICE_DRIVER_OFFSET: usize =3D core::mem::offset_of!(Self::Driv= erType, driver); } =20 @@ -129,8 +129,8 @@ extern "C" fn remove_callback(pdev: *mut bindings::pci_= dev) { =20 // SAFETY: `remove_callback` is only ever called after a successfu= l call to // `probe_callback`, hence it's guaranteed that `Device::set_drvda= ta()` has been called - // and stored a `Pin>`. - let data =3D unsafe { pdev.as_ref().drvdata_borrow::() }; + // and stored a `Pin>>`. + let data =3D unsafe { pdev.as_ref().drvdata_borrow::>(= ) }; =20 T::unbind(pdev, data); } @@ -279,13 +279,13 @@ macro_rules! pci_device_table { /// /// impl pci::Driver for MyDriver { /// type IdInfo =3D (); -/// type Data =3D Self; +/// type Data<'bound> =3D Self; /// const ID_TABLE: pci::IdTable =3D &PCI_TABLE; /// -/// fn probe( -/// _pdev: &pci::Device>, -/// _id_info: &Self::IdInfo, -/// ) -> impl PinInit { +/// fn probe<'bound>( +/// _pdev: &'bound pci::Device>, +/// _id_info: &'bound Self::IdInfo, +/// ) -> impl PinInit, Error> + 'bound { /// Err(ENODEV) /// } /// } @@ -302,7 +302,7 @@ pub trait Driver { type IdInfo: 'static; =20 /// The type of the driver's bus device private data. - type Data: Send; + type Data<'bound>: Send + 'bound; =20 /// The table of device ids supported by the driver. const ID_TABLE: IdTable; @@ -311,10 +311,10 @@ pub trait Driver { /// /// Called when a new pci device is added or discovered. Implementers = should /// attempt to initialize the device here. - fn probe( - dev: &Device>, - id_info: &Self::IdInfo, - ) -> impl PinInit; + fn probe<'bound>( + dev: &'bound Device>, + id_info: &'bound Self::IdInfo, + ) -> impl PinInit, Error> + 'bound; =20 /// PCI driver unbind. /// @@ -326,7 +326,7 @@ fn probe( /// operations to gracefully tear down the device. /// /// Otherwise, release operations for driver resources should be perfo= rmed in `Drop`. - fn unbind(dev: &Device>, this: Pin<&Self::Data>) { + fn unbind<'bound>(dev: &'bound Device>, this: Pin<&Se= lf::Data<'bound>>) { let _ =3D (dev, this); } } diff --git a/samples/rust/rust_dma.rs b/samples/rust/rust_dma.rs index 9a243e7c7298..c4d2d36602af 100644 --- a/samples/rust/rust_dma.rs +++ b/samples/rust/rust_dma.rs @@ -58,10 +58,13 @@ unsafe impl kernel::transmute::FromBytes for MyStruct {} =20 impl pci::Driver for DmaSampleDriver { type IdInfo =3D (); - type Data =3D Self; + type Data<'bound> =3D Self; const ID_TABLE: pci::IdTable =3D &PCI_TABLE; =20 - fn probe(pdev: &pci::Device>, _info: &Self::IdInfo) -> impl P= inInit { + fn probe<'bound>( + pdev: &'bound pci::Device>, + _info: &'bound Self::IdInfo, + ) -> impl PinInit + 'bound { pin_init::pin_init_scope(move || { dev_info!(pdev, "Probe DMA test driver.\n"); =20 diff --git a/samples/rust/rust_driver_auxiliary.rs b/samples/rust/rust_driv= er_auxiliary.rs index f0d419823f9a..0e979f45cd68 100644 --- a/samples/rust/rust_driver_auxiliary.rs +++ b/samples/rust/rust_driver_auxiliary.rs @@ -69,11 +69,14 @@ struct ParentDriver { =20 impl pci::Driver for ParentDriver { type IdInfo =3D (); - type Data =3D Self; + type Data<'bound> =3D Self; =20 const ID_TABLE: pci::IdTable =3D &PCI_TABLE; =20 - fn probe(pdev: &pci::Device>, _info: &Self::IdInfo) -> impl P= inInit { + fn probe<'bound>( + pdev: &'bound pci::Device>, + _info: &'bound Self::IdInfo, + ) -> impl PinInit + 'bound { Ok(Self { _reg0: auxiliary::Registration::new( pdev.as_ref(), diff --git a/samples/rust/rust_driver_pci.rs b/samples/rust/rust_driver_pci= .rs index 3106f766fd93..6791d98e1c79 100644 --- a/samples/rust/rust_driver_pci.rs +++ b/samples/rust/rust_driver_pci.rs @@ -140,11 +140,14 @@ fn config_space(pdev: &pci::Device) { =20 impl pci::Driver for SampleDriver { type IdInfo =3D TestIndex; - type Data =3D Self; + type Data<'bound> =3D Self; =20 const ID_TABLE: pci::IdTable =3D &PCI_TABLE; =20 - fn probe(pdev: &pci::Device>, info: &Self::IdInfo) -> impl Pi= nInit { + fn probe<'bound>( + pdev: &'bound pci::Device>, + info: &'bound Self::IdInfo, + ) -> impl PinInit + 'bound { pin_init::pin_init_scope(move || { let vendor =3D pdev.vendor_id(); dev_dbg!( --=20 2.54.0 From nobody Mon Jun 8 22:51:08 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 75E87399CE4; Mon, 25 May 2026 20:31:04 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779741066; cv=none; b=YKiZa8ypyk/+6Pm3RIVMHaP5RZJw3OZ6Kyt0ZAdLA2tut7a/uG3AOq/T5y8mPRDE6H8cC4yP8YjvRu6uSr4BzihH+ExXhVhM7NIuQnlMGaITMgdj+lzSjKtM8FELrY5iOCHjpbRayXLehXHe/oW2z06e5uCa0mQ4dvOktrXS2Qs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779741066; c=relaxed/simple; bh=+mqPifTe6v0r+vvFPje8xyxouSApu09oLmORUEn0xCA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=u1gBnir4MRilh27pEbLt5QBQtE6SAuTO16aDgqxzwEvCGELOovoJ1cztqwhOr/OLk5NMFdzVA9STtFbd3pBjPYeFn48orhpWL+US5XSFXpL5pqTNKQwO2sjETsRadfZQbp9Q074V6/DE2hjrffDgfmnLD6d5ATnZ122eT4Dsblo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=WJYYiquo; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="WJYYiquo" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 5ED0F1F000E9; Mon, 25 May 2026 20:30:57 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1779741064; bh=aO3Sx4h2WwjmkdD/wEAhzhvqYD9OmYrnQfNGx5fX4B4=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=WJYYiquoFste45dI5X1p/U0FBDziI2y9CyLESK8EbDKtJZ8Ey/gaExSDdiLCONUiU JT961ypmnu5ApHtjS371eqqwBnqZ3RsGDgr06/Epn9wAUQ/11cVoVbNQdSHnEB+QZ+ 0mRMYiSBUhRze4YLaDxYzdgiPUuGXyaqDxCyi1r+eiJF3ZkPLV7U8wIpj0hqgUb+OC 7pwXjkZmL9hllPC3xlv4NvhecHxyaRXr9ZOaz+gq6KZISaAejHheqgsNVhHSyh+Yj6 +fyKDA3QfZJOmCoyluOl3ZaBr6LjVqDOEqZKsIBK/91DVQPxnp4D4jSOHJsDZtyQAi 4uNyWHw0umvRQ== From: Danilo Krummrich To: gregkh@linuxfoundation.org, rafael@kernel.org, acourbot@nvidia.com, aliceryhl@google.com, david.m.ertman@intel.com, ira.weiny@intel.com, leon@kernel.org, viresh.kumar@linaro.org, m.wilczynski@samsung.com, ukleinek@kernel.org, bhelgaas@google.com, kwilczynski@kernel.org, abdiel.janulgue@gmail.com, robin.murphy@arm.com, markus.probst@posteo.de, ojeda@kernel.org, boqun@kernel.org, gary@garyguo.net, bjorn3_gh@protonmail.com, lossin@kernel.org, a.hindborg@kernel.org, tmgross@umich.edu, igor.korotin@linux.dev, daniel.almeida@collabora.com, pcolberg@redhat.com Cc: driver-core@lists.linux.dev, linux-kernel@vger.kernel.org, nova-gpu@lists.linux.dev, dri-devel@lists.freedesktop.org, linux-pm@vger.kernel.org, linux-pwm@vger.kernel.org, linux-pci@vger.kernel.org, rust-for-linux@vger.kernel.org, Danilo Krummrich Subject: [PATCH v5 13/24] rust: platform: make Driver trait lifetime-parameterized Date: Mon, 25 May 2026 22:21:00 +0200 Message-ID: <20260525202921.124698-14-dakr@kernel.org> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260525202921.124698-1-dakr@kernel.org> References: <20260525202921.124698-1-dakr@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Add a 'bound lifetime to the associated Data, changing type Data to type Data<'bound>. This allows the driver's bus device private data to capture the device / driver bound lifetime; device resources can be stored directly by reference rather than requiring Devres. The probe() and unbind() callbacks thus gain a 'bound lifetime parameter on the methods themselves; avoiding a global lifetime on the trait impl. Existing drivers set type Data<'bound> =3D Self, preserving the current behavior. Acked-by: Uwe Kleine-K=C3=B6nig Reviewed-by: Alexandre Courbot Reviewed-by: Greg Kroah-Hartman Signed-off-by: Danilo Krummrich Reviewed-by: Gary Guo --- drivers/cpufreq/rcpufreq_dt.rs | 10 +++++----- drivers/gpu/drm/tyr/driver.rs | 10 +++++----- drivers/pwm/pwm_th1520.rs | 10 +++++----- rust/kernel/cpufreq.rs | 10 +++++----- rust/kernel/io/mem.rs | 20 ++++++++++---------- rust/kernel/platform.rs | 28 ++++++++++++++-------------- samples/rust/rust_debugfs.rs | 10 +++++----- samples/rust/rust_driver_platform.rs | 10 +++++----- samples/rust/rust_i2c_client.rs | 15 +++++++++------ samples/rust/rust_soc.rs | 10 +++++----- 10 files changed, 68 insertions(+), 65 deletions(-) diff --git a/drivers/cpufreq/rcpufreq_dt.rs b/drivers/cpufreq/rcpufreq_dt.rs index 5e0b224f6699..10106fa13095 100644 --- a/drivers/cpufreq/rcpufreq_dt.rs +++ b/drivers/cpufreq/rcpufreq_dt.rs @@ -201,13 +201,13 @@ fn register_em(policy: &mut cpufreq::Policy) { =20 impl platform::Driver for CPUFreqDTDriver { type IdInfo =3D (); - type Data =3D Self; + type Data<'bound> =3D Self; const OF_ID_TABLE: Option> =3D Some(&OF_TABL= E); =20 - fn probe( - pdev: &platform::Device>, - _id_info: Option<&Self::IdInfo>, - ) -> impl PinInit { + fn probe<'bound>( + pdev: &'bound platform::Device>, + _id_info: Option<&'bound Self::IdInfo>, + ) -> impl PinInit + 'bound { cpufreq::Registration::::new_foreign_owned(pdev.a= s_ref())?; Ok(Self {}) } diff --git a/drivers/gpu/drm/tyr/driver.rs b/drivers/gpu/drm/tyr/driver.rs index 001727f44fc8..797f09e23a4c 100644 --- a/drivers/gpu/drm/tyr/driver.rs +++ b/drivers/gpu/drm/tyr/driver.rs @@ -91,13 +91,13 @@ fn issue_soft_reset(dev: &Device, iomem: &Devres= ) -> Result { =20 impl platform::Driver for TyrPlatformDriverData { type IdInfo =3D (); - type Data =3D Self; + type Data<'bound> =3D Self; const OF_ID_TABLE: Option> =3D Some(&OF_TABL= E); =20 - fn probe( - pdev: &platform::Device>, - _info: Option<&Self::IdInfo>, - ) -> impl PinInit { + fn probe<'bound>( + pdev: &'bound platform::Device>, + _info: Option<&'bound Self::IdInfo>, + ) -> impl PinInit + 'bound { let core_clk =3D Clk::get(pdev.as_ref(), Some(c"core"))?; let stacks_clk =3D OptionalClk::get(pdev.as_ref(), Some(c"stacks")= )?; let coregroup_clk =3D OptionalClk::get(pdev.as_ref(), Some(c"coreg= roup"))?; diff --git a/drivers/pwm/pwm_th1520.rs b/drivers/pwm/pwm_th1520.rs index df83a4a9a507..6c5b791f3153 100644 --- a/drivers/pwm/pwm_th1520.rs +++ b/drivers/pwm/pwm_th1520.rs @@ -316,13 +316,13 @@ fn drop(self: Pin<&mut Self>) { =20 impl platform::Driver for Th1520PwmPlatformDriver { type IdInfo =3D (); - type Data =3D Self; + type Data<'bound> =3D Self; const OF_ID_TABLE: Option> =3D Some(&OF_TABL= E); =20 - fn probe( - pdev: &platform::Device>, - _id_info: Option<&Self::IdInfo>, - ) -> impl PinInit { + fn probe<'bound>( + pdev: &'bound platform::Device>, + _id_info: Option<&'bound Self::IdInfo>, + ) -> impl PinInit + 'bound { let dev =3D pdev.as_ref(); let request =3D pdev.io_request_by_index(0).ok_or(ENODEV)?; =20 diff --git a/rust/kernel/cpufreq.rs b/rust/kernel/cpufreq.rs index 0df518fa1d77..d94c6cdbc45a 100644 --- a/rust/kernel/cpufreq.rs +++ b/rust/kernel/cpufreq.rs @@ -888,13 +888,13 @@ fn register_em(_policy: &mut Policy) { /// /// impl platform::Driver for SampleDriver { /// type IdInfo =3D (); -/// type Data =3D Self; +/// type Data<'bound> =3D Self; /// const OF_ID_TABLE: Option> =3D None; /// -/// fn probe( -/// pdev: &platform::Device>, -/// _id_info: Option<&Self::IdInfo>, -/// ) -> impl PinInit { +/// fn probe<'bound>( +/// pdev: &'bound platform::Device>, +/// _id_info: Option<&'bound Self::IdInfo>, +/// ) -> impl PinInit + 'bound { /// cpufreq::Registration::::new_foreign_owned(pdev.= as_ref())?; /// Ok(Self {}) /// } diff --git a/rust/kernel/io/mem.rs b/rust/kernel/io/mem.rs index 03d8745b5e1d..51ba347220ee 100644 --- a/rust/kernel/io/mem.rs +++ b/rust/kernel/io/mem.rs @@ -62,12 +62,12 @@ pub(crate) unsafe fn new(device: &'a Device, res= ource: &'a Resource) -> S /// /// impl platform::Driver for SampleDriver { /// # type IdInfo =3D (); - /// # type Data =3D Self; + /// # type Data<'bound> =3D Self; /// - /// fn probe( - /// pdev: &platform::Device>, - /// info: Option<&Self::IdInfo>, - /// ) -> impl PinInit { + /// fn probe<'bound>( + /// pdev: &'bound platform::Device>, + /// info: Option<&'bound Self::IdInfo>, + /// ) -> impl PinInit + 'bound { /// let offset =3D 0; // Some offset. /// /// // If the size is known at compile time, use [`Self::iomap_s= ized`]. @@ -127,12 +127,12 @@ pub fn iomap_exclusive_sized( /// /// impl platform::Driver for SampleDriver { /// # type IdInfo =3D (); - /// # type Data =3D Self; + /// # type Data<'bound> =3D Self; /// - /// fn probe( - /// pdev: &platform::Device>, - /// info: Option<&Self::IdInfo>, - /// ) -> impl PinInit { + /// fn probe<'bound>( + /// pdev: &'bound platform::Device>, + /// info: Option<&'bound Self::IdInfo>, + /// ) -> impl PinInit + 'bound { /// let offset =3D 0; // Some offset. /// /// // Unlike [`Self::iomap_sized`], here the size of the memory= region diff --git a/rust/kernel/platform.rs b/rust/kernel/platform.rs index 257b7084338c..d8d48f60b0b9 100644 --- a/rust/kernel/platform.rs +++ b/rust/kernel/platform.rs @@ -50,7 +50,7 @@ // - `DEVICE_DRIVER_OFFSET` is the correct byte offset to the embedded `st= ruct device_driver`. unsafe impl driver::DriverLayout for Adapter { type DriverType =3D bindings::platform_driver; - type DriverData<'bound> =3D T::Data; + type DriverData<'bound> =3D T::Data<'bound>; const DEVICE_DRIVER_OFFSET: usize =3D core::mem::offset_of!(Self::Driv= erType, driver); } =20 @@ -117,8 +117,8 @@ extern "C" fn remove_callback(pdev: *mut bindings::plat= form_device) { =20 // SAFETY: `remove_callback` is only ever called after a successfu= l call to // `probe_callback`, hence it's guaranteed that `Device::set_drvda= ta()` has been called - // and stored a `Pin>`. - let data =3D unsafe { pdev.as_ref().drvdata_borrow::() }; + // and stored a `Pin>>`. + let data =3D unsafe { pdev.as_ref().drvdata_borrow::>(= ) }; =20 T::unbind(pdev, data); } @@ -192,14 +192,14 @@ macro_rules! module_platform_driver { /// /// impl platform::Driver for MyDriver { /// type IdInfo =3D (); -/// type Data =3D Self; +/// type Data<'bound> =3D Self; /// const OF_ID_TABLE: Option> =3D Some(&OF_= TABLE); /// const ACPI_ID_TABLE: Option> =3D Some(= &ACPI_TABLE); /// -/// fn probe( -/// _pdev: &platform::Device>, -/// _id_info: Option<&Self::IdInfo>, -/// ) -> impl PinInit { +/// fn probe<'bound>( +/// _pdev: &'bound platform::Device>, +/// _id_info: Option<&'bound Self::IdInfo>, +/// ) -> impl PinInit, Error> + 'bound { /// Err(ENODEV) /// } /// } @@ -214,7 +214,7 @@ pub trait Driver { type IdInfo: 'static; =20 /// The type of the driver's bus device private data. - type Data: Send; + type Data<'bound>: Send + 'bound; =20 /// The table of OF device ids supported by the driver. const OF_ID_TABLE: Option> =3D None; @@ -226,10 +226,10 @@ pub trait Driver { /// /// Called when a new platform device is added or discovered. /// Implementers should attempt to initialize the device here. - fn probe( - dev: &Device>, - id_info: Option<&Self::IdInfo>, - ) -> impl PinInit; + fn probe<'bound>( + dev: &'bound Device>, + id_info: Option<&'bound Self::IdInfo>, + ) -> impl PinInit, Error> + 'bound; =20 /// Platform driver unbind. /// @@ -241,7 +241,7 @@ fn probe( /// operations to gracefully tear down the device. /// /// Otherwise, release operations for driver resources should be perfo= rmed in `Drop`. - fn unbind(dev: &Device>, this: Pin<&Self::Data>) { + fn unbind<'bound>(dev: &'bound Device>, this: Pin<&Se= lf::Data<'bound>>) { let _ =3D (dev, this); } } diff --git a/samples/rust/rust_debugfs.rs b/samples/rust/rust_debugfs.rs index 37640ed33642..1f59e08aaa4b 100644 --- a/samples/rust/rust_debugfs.rs +++ b/samples/rust/rust_debugfs.rs @@ -117,14 +117,14 @@ fn from_str(s: &str) -> Result { =20 impl platform::Driver for RustDebugFs { type IdInfo =3D (); - type Data =3D Self; + type Data<'bound> =3D Self; const OF_ID_TABLE: Option> =3D None; const ACPI_ID_TABLE: Option> =3D Some(&ACP= I_TABLE); =20 - fn probe( - pdev: &platform::Device>, - _info: Option<&Self::IdInfo>, - ) -> impl PinInit { + fn probe<'bound>( + pdev: &'bound platform::Device>, + _info: Option<&'bound Self::IdInfo>, + ) -> impl PinInit + 'bound { RustDebugFs::new(pdev).pin_chain(|this| { this.counter.store(91, Relaxed); { diff --git a/samples/rust/rust_driver_platform.rs b/samples/rust/rust_drive= r_platform.rs index 04d40f836275..ec0d6cac4f57 100644 --- a/samples/rust/rust_driver_platform.rs +++ b/samples/rust/rust_driver_platform.rs @@ -101,14 +101,14 @@ struct SampleDriver { =20 impl platform::Driver for SampleDriver { type IdInfo =3D Info; - type Data =3D Self; + type Data<'bound> =3D Self; const OF_ID_TABLE: Option> =3D Some(&OF_TABL= E); const ACPI_ID_TABLE: Option> =3D Some(&ACP= I_TABLE); =20 - fn probe( - pdev: &platform::Device>, - info: Option<&Self::IdInfo>, - ) -> impl PinInit { + fn probe<'bound>( + pdev: &'bound platform::Device>, + info: Option<&'bound Self::IdInfo>, + ) -> impl PinInit + 'bound { let dev =3D pdev.as_ref(); =20 dev_dbg!(dev, "Probe Rust Platform driver sample.\n"); diff --git a/samples/rust/rust_i2c_client.rs b/samples/rust/rust_i2c_client= .rs index 3f273c754f86..2d876f4e3ee0 100644 --- a/samples/rust/rust_i2c_client.rs +++ b/samples/rust/rust_i2c_client.rs @@ -106,14 +106,14 @@ struct SampleDriver { =20 impl platform::Driver for SampleDriver { type IdInfo =3D (); - type Data =3D Self; + type Data<'bound> =3D Self; const OF_ID_TABLE: Option> =3D Some(&OF_TABL= E); const ACPI_ID_TABLE: Option> =3D Some(&ACP= I_TABLE); =20 - fn probe( - pdev: &platform::Device>, - _info: Option<&Self::IdInfo>, - ) -> impl PinInit { + fn probe<'bound>( + pdev: &'bound platform::Device>, + _info: Option<&'bound Self::IdInfo>, + ) -> impl PinInit + 'bound { dev_info!( pdev.as_ref(), "Probe Rust I2C Client registration sample.\n" @@ -130,7 +130,10 @@ fn probe( }) } =20 - fn unbind(pdev: &platform::Device>, _this: Pin<&Self>= ) { + fn unbind<'bound>( + pdev: &'bound platform::Device>, + _this: Pin<&Self::Data<'bound>>, + ) { dev_info!( pdev.as_ref(), "Unbind Rust I2C Client registration sample.\n" diff --git a/samples/rust/rust_soc.rs b/samples/rust/rust_soc.rs index c466653491d2..808d58200eb6 100644 --- a/samples/rust/rust_soc.rs +++ b/samples/rust/rust_soc.rs @@ -37,14 +37,14 @@ struct SampleSocDriver { =20 impl platform::Driver for SampleSocDriver { type IdInfo =3D (); - type Data =3D Self; + type Data<'bound> =3D Self; const OF_ID_TABLE: Option> =3D Some(&OF_TABL= E); const ACPI_ID_TABLE: Option> =3D Some(&ACP= I_TABLE); =20 - fn probe( - pdev: &platform::Device>, - _info: Option<&Self::IdInfo>, - ) -> impl PinInit { + fn probe<'bound>( + pdev: &'bound platform::Device>, + _info: Option<&'bound Self::IdInfo>, + ) -> impl PinInit + 'bound { dev_dbg!(pdev, "Probe Rust SoC driver sample.\n"); =20 let pdev =3D pdev.into(); --=20 2.54.0 From nobody Mon Jun 8 22:51:08 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9201C3A1687; Mon, 25 May 2026 20:31:11 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779741072; cv=none; b=HtFl9dKDfe/N8eGMAfrO/4k4I1ZNzGyQHBr++tXC9f4guT3ET+BcIogEockc+qRH5ZrtRvOTAZUbR9uKjQfv1nqpNfKir5pkuWJx2RIsg0g7iYKrDnyiUNlxuGZzgBfS6IIz0FdDqA+N+bN3tkmM/6cm5oMP6Ml8fYTZPhl3zEg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779741072; c=relaxed/simple; bh=UPbGLPphjYsNgSb4lPLsznFi8G9U9oyShTBHn3iDEBU=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=hU4MWFHSaxVy5KJTkB/tPVhx4EFI1kgFrvwcOr30PQPs6WXELCFC9mmBCvq4aVOpySXpHyrl1y9NE8toXHW7gFicXKFob3eh//MghyjQ4kVS0mNbcT+r9k5sGLaQM5PHtj0/7WZU3Z7aZRI2bmWIqejOZKCboZq2+UcXaNe5wv4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=I7aqvAA+; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="I7aqvAA+" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 7FEBB1F00A3A; Mon, 25 May 2026 20:31:04 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1779741071; bh=1tyepCiVgJNuYusD1QZKVrZCX4CBBzMSmwqkHJY+0nE=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=I7aqvAA+wThSELUhlihIju+qqmOdQvJToY58rWFJex04DFrflaluKlhSfFO4tOfSo BGXOPKCG6VUJuxVEioQdN9Af8gwfc6H6PzLmYMBtZ/YoFa1RZ1fg+CWDoll2ZGYjoW R0GAmgJuJeoa6VlZJdi16b4X5p8IzdIfsJwfNsYAKihVHdz4kH5W3E/OIg7h7R3n2m bIEpMg1pVpMhrdE0fR0My1JedUW4sE7h1wCrUNqSCCXwwjDrXpgq6DZeFxmrk8wBcD MUxN7R4ryyHNdc442esBMsTjnYoAzjgZMcUuf0Ht+qgLHZ18PBzPuoXVeDT/7LXCbJ pw99XjHalXwrw== From: Danilo Krummrich To: gregkh@linuxfoundation.org, rafael@kernel.org, acourbot@nvidia.com, aliceryhl@google.com, david.m.ertman@intel.com, ira.weiny@intel.com, leon@kernel.org, viresh.kumar@linaro.org, m.wilczynski@samsung.com, ukleinek@kernel.org, bhelgaas@google.com, kwilczynski@kernel.org, abdiel.janulgue@gmail.com, robin.murphy@arm.com, markus.probst@posteo.de, ojeda@kernel.org, boqun@kernel.org, gary@garyguo.net, bjorn3_gh@protonmail.com, lossin@kernel.org, a.hindborg@kernel.org, tmgross@umich.edu, igor.korotin@linux.dev, daniel.almeida@collabora.com, pcolberg@redhat.com Cc: driver-core@lists.linux.dev, linux-kernel@vger.kernel.org, nova-gpu@lists.linux.dev, dri-devel@lists.freedesktop.org, linux-pm@vger.kernel.org, linux-pwm@vger.kernel.org, linux-pci@vger.kernel.org, rust-for-linux@vger.kernel.org, Danilo Krummrich Subject: [PATCH v5 14/24] rust: auxiliary: make Driver trait lifetime-parameterized Date: Mon, 25 May 2026 22:21:01 +0200 Message-ID: <20260525202921.124698-15-dakr@kernel.org> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260525202921.124698-1-dakr@kernel.org> References: <20260525202921.124698-1-dakr@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add a 'bound lifetime to the associated Data, changing type Data to type Data<'bound>. This allows the driver's bus device private data to capture the device / driver bound lifetime; device resources can be stored directly by reference rather than requiring Devres. The probe() and unbind() callbacks thus gain a 'bound lifetime parameter on the methods themselves; avoiding a global lifetime on the trait impl. Existing drivers set type Data<'bound> =3D Self, preserving the current behavior. Reviewed-by: Alexandre Courbot Reviewed-by: Greg Kroah-Hartman Signed-off-by: Danilo Krummrich Reviewed-by: Gary Guo --- drivers/gpu/drm/nova/driver.rs | 10 +++++----- rust/kernel/auxiliary.rs | 18 +++++++++--------- samples/rust/rust_driver_auxiliary.rs | 10 +++++----- 3 files changed, 19 insertions(+), 19 deletions(-) diff --git a/drivers/gpu/drm/nova/driver.rs b/drivers/gpu/drm/nova/driver.rs index 7605348af994..aa08644012f7 100644 --- a/drivers/gpu/drm/nova/driver.rs +++ b/drivers/gpu/drm/nova/driver.rs @@ -51,13 +51,13 @@ pub(crate) struct NovaData { =20 impl auxiliary::Driver for NovaDriver { type IdInfo =3D (); - type Data =3D Self; + type Data<'bound> =3D Self; const ID_TABLE: auxiliary::IdTable =3D &AUX_TABLE; =20 - fn probe( - adev: &auxiliary::Device>, - _info: &Self::IdInfo, - ) -> impl PinInit { + fn probe<'bound>( + adev: &'bound auxiliary::Device>, + _info: &'bound Self::IdInfo, + ) -> impl PinInit + 'bound { let data =3D try_pin_init!(NovaData { adev: adev.into() }); =20 let drm =3D drm::Device::::new(adev.as_ref(), data)?; diff --git a/rust/kernel/auxiliary.rs b/rust/kernel/auxiliary.rs index 6d504b0933d5..7a1b1a7b7ca6 100644 --- a/rust/kernel/auxiliary.rs +++ b/rust/kernel/auxiliary.rs @@ -46,7 +46,7 @@ // - `DEVICE_DRIVER_OFFSET` is the correct byte offset to the embedded `st= ruct device_driver`. unsafe impl driver::DriverLayout for Adapter { type DriverType =3D bindings::auxiliary_driver; - type DriverData<'bound> =3D T::Data; + type DriverData<'bound> =3D T::Data<'bound>; const DEVICE_DRIVER_OFFSET: usize =3D core::mem::offset_of!(Self::Driv= erType, driver); } =20 @@ -111,8 +111,8 @@ extern "C" fn remove_callback(adev: *mut bindings::auxi= liary_device) { =20 // SAFETY: `remove_callback` is only ever called after a successfu= l call to // `probe_callback`, hence it's guaranteed that `Device::set_drvda= ta()` has been called - // and stored a `Pin>`. - let data =3D unsafe { adev.as_ref().drvdata_borrow::() }; + // and stored a `Pin>>`. + let data =3D unsafe { adev.as_ref().drvdata_borrow::>(= ) }; =20 T::unbind(adev, data); } @@ -203,7 +203,7 @@ pub trait Driver { type IdInfo: 'static; =20 /// The type of the driver's bus device private data. - type Data: Send; + type Data<'bound>: Send + 'bound; =20 /// The table of device ids supported by the driver. const ID_TABLE: IdTable; @@ -211,10 +211,10 @@ pub trait Driver { /// Auxiliary driver probe. /// /// Called when an auxiliary device is matches a corresponding driver. - fn probe( - dev: &Device>, - id_info: &Self::IdInfo, - ) -> impl PinInit; + fn probe<'bound>( + dev: &'bound Device>, + id_info: &'bound Self::IdInfo, + ) -> impl PinInit, Error> + 'bound; =20 /// Auxiliary driver unbind. /// @@ -226,7 +226,7 @@ fn probe( /// operations to gracefully tear down the device. /// /// Otherwise, release operations for driver resources should be perfo= rmed in `Drop`. - fn unbind(dev: &Device>, this: Pin<&Self::Data>) { + fn unbind<'bound>(dev: &'bound Device>, this: Pin<&Se= lf::Data<'bound>>) { let _ =3D (dev, this); } } diff --git a/samples/rust/rust_driver_auxiliary.rs b/samples/rust/rust_driv= er_auxiliary.rs index 0e979f45cd68..b30a4d5cdf8a 100644 --- a/samples/rust/rust_driver_auxiliary.rs +++ b/samples/rust/rust_driver_auxiliary.rs @@ -31,14 +31,14 @@ =20 impl auxiliary::Driver for AuxiliaryDriver { type IdInfo =3D (); - type Data =3D Self; + type Data<'bound> =3D Self; =20 const ID_TABLE: auxiliary::IdTable =3D &AUX_TABLE; =20 - fn probe( - adev: &auxiliary::Device>, - _info: &Self::IdInfo, - ) -> impl PinInit { + fn probe<'bound>( + adev: &'bound auxiliary::Device>, + _info: &'bound Self::IdInfo, + ) -> impl PinInit + 'bound { dev_info!( adev, "Probing auxiliary driver for auxiliary device with id=3D{}\n", --=20 2.54.0 From nobody Mon Jun 8 22:51:08 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E59F03A5445; Mon, 25 May 2026 20:31:18 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779741080; cv=none; b=X3hfROM2h4ljCgJP5UrJXHS8ALw3Qij/QQmLu/dieh4CbqV6xDVJ/ozjq6hEWLMo0PigetVBVyBNfBlow2al6COxKmKlT+45LvBMFUvseAehNMGsfphcF79OUWaH0d7eIy1XUpOSn8oSfW3uFXgctBPu/ioflHZJZDqy7/ie0zE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779741080; c=relaxed/simple; bh=UGUo7ln++sMgeCMPj/bJISQXaob/SZ3WKNOovtSb5EE=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=iXiAXgA5KWB0LOv+Atu1wUqhDdm73szF92Q/KFRoXP0Uow50V4O/3BYMVraJNpI9xUvCUzAU3rmV52H1CZdsPIkVQfW5+z3v0FGozddHQ8YgbW5/1OG84WK32kUZQ8fvfNtHeuX6DbKwgKMnzE3JRA9IITWuUCVxmP0ytnXdsGI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=LOPTHp7v; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="LOPTHp7v" Received: by smtp.kernel.org (Postfix) with ESMTPSA id A05BC1F000E9; Mon, 25 May 2026 20:31:11 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1779741078; bh=a2o69Vls+2LExzNW7VJcfY7abYptUomgAsmgqcBlrbM=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=LOPTHp7v+ngjAkvkvlxodPVMlfS+Eqr5rEOAn5nOIKXIXw/EJJ0zz6nRj7EIGQFeN jvAgCx4crC+w9fS0vXxTeXghGpv2pc0435QskiYySHPGxGhFngCRbxq7I4OQ6qVFnK 21ot788FG39stifcpWBzlF5ZG7AWeAmh4B1ye2/uY5sxz5xqdIBulLJWP36pvDjIlj IFmQGfXRcrYRCHAwkf6882HSNfDFFJ9k3iLS+ybvX6tzsQ4I7F56jQ8ufe0HZ+fsBo NlkKOzL8+YC8SN9qnhoKNJlh6bPV3DpotRTyIVUrvQajDMVLoIEqlVaGasZzlM6ren y5ruk0HbPtiFg== From: Danilo Krummrich To: gregkh@linuxfoundation.org, rafael@kernel.org, acourbot@nvidia.com, aliceryhl@google.com, david.m.ertman@intel.com, ira.weiny@intel.com, leon@kernel.org, viresh.kumar@linaro.org, m.wilczynski@samsung.com, ukleinek@kernel.org, bhelgaas@google.com, kwilczynski@kernel.org, abdiel.janulgue@gmail.com, robin.murphy@arm.com, markus.probst@posteo.de, ojeda@kernel.org, boqun@kernel.org, gary@garyguo.net, bjorn3_gh@protonmail.com, lossin@kernel.org, a.hindborg@kernel.org, tmgross@umich.edu, igor.korotin@linux.dev, daniel.almeida@collabora.com, pcolberg@redhat.com Cc: driver-core@lists.linux.dev, linux-kernel@vger.kernel.org, nova-gpu@lists.linux.dev, dri-devel@lists.freedesktop.org, linux-pm@vger.kernel.org, linux-pwm@vger.kernel.org, linux-pci@vger.kernel.org, rust-for-linux@vger.kernel.org, Danilo Krummrich , Eliot Courtney Subject: [PATCH v5 15/24] rust: usb: make Driver trait lifetime-parameterized Date: Mon, 25 May 2026 22:21:02 +0200 Message-ID: <20260525202921.124698-16-dakr@kernel.org> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260525202921.124698-1-dakr@kernel.org> References: <20260525202921.124698-1-dakr@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add a 'bound lifetime to the associated Data, changing type Data to type Data<'bound>. This allows the driver's bus device private data to capture the device / driver bound lifetime; device resources can be stored directly by reference rather than requiring Devres. The probe() and disconnect() callbacks thus gain a 'bound lifetime parameter on the methods themselves; avoiding a global lifetime on the trait impl. Existing drivers set type Data<'bound> =3D Self, preserving the current behavior. Reviewed-by: Alexandre Courbot Reviewed-by: Greg Kroah-Hartman Reviewed-by: Eliot Courtney Signed-off-by: Danilo Krummrich Reviewed-by: Daniel Almeida Reviewed-by: Gary Guo --- rust/kernel/usb.rs | 37 ++++++++++++++++++++------------- samples/rust/rust_driver_usb.rs | 12 +++++------ 2 files changed, 28 insertions(+), 21 deletions(-) diff --git a/rust/kernel/usb.rs b/rust/kernel/usb.rs index 1dbb8387b463..7aff0c82d0af 100644 --- a/rust/kernel/usb.rs +++ b/rust/kernel/usb.rs @@ -41,7 +41,7 @@ // - `DEVICE_DRIVER_OFFSET` is the correct byte offset to the embedded `st= ruct device_driver`. unsafe impl driver::DriverLayout for Adapter { type DriverType =3D bindings::usb_driver; - type DriverData<'bound> =3D T::Data; + type DriverData<'bound> =3D T::Data<'bound>; const DEVICE_DRIVER_OFFSET: usize =3D core::mem::offset_of!(Self::Driv= erType, driver); } =20 @@ -109,8 +109,8 @@ extern "C" fn disconnect_callback(intf: *mut bindings::= usb_interface) { =20 // SAFETY: `disconnect_callback` is only ever called after a succe= ssful call to // `probe_callback`, hence it's guaranteed that `Device::set_drvda= ta()` has been called - // and stored a `Pin>`. - let data =3D unsafe { dev.drvdata_borrow::() }; + // and stored a `Pin>>`. + let data =3D unsafe { dev.drvdata_borrow::>() }; =20 T::disconnect(intf, data); } @@ -287,18 +287,22 @@ macro_rules! usb_device_table { /// /// impl usb::Driver for MyDriver { /// type IdInfo =3D (); -/// type Data =3D Self; +/// type Data<'bound> =3D Self; /// const ID_TABLE: usb::IdTable =3D &USB_TABLE; /// -/// fn probe( -/// _interface: &usb::Interface>, +/// fn probe<'bound>( +/// _interface: &'bound usb::Interface>, /// _id: &usb::DeviceId, -/// _info: &Self::IdInfo, -/// ) -> impl PinInit { +/// _info: &'bound Self::IdInfo, +/// ) -> impl PinInit, Error> + 'bound { /// Err(ENODEV) /// } /// -/// fn disconnect(_interface: &usb::Interface>, _data: Pin<&S= elf::Data>) {} +/// fn disconnect<'bound>( +/// _interface: &'bound usb::Interface>, +/// _data: Pin<&Self::Data<'bound>>, +/// ) { +/// } /// } ///``` pub trait Driver { @@ -306,7 +310,7 @@ pub trait Driver { type IdInfo: 'static; =20 /// The type of the driver's bus device private data. - type Data: Send; + type Data<'bound>: Send + 'bound; =20 /// The table of device ids supported by the driver. const ID_TABLE: IdTable; @@ -315,16 +319,19 @@ pub trait Driver { /// /// Called when a new USB interface is bound to this driver. /// Implementers should attempt to initialize the interface here. - fn probe( - interface: &Interface>, + fn probe<'bound>( + interface: &'bound Interface>, id: &DeviceId, - id_info: &Self::IdInfo, - ) -> impl PinInit; + id_info: &'bound Self::IdInfo, + ) -> impl PinInit, Error> + 'bound; =20 /// USB driver disconnect. /// /// Called when the USB interface is about to be unbound from this dri= ver. - fn disconnect(interface: &Interface>, data: Pin<&Self= ::Data>); + fn disconnect<'bound>( + interface: &'bound Interface>, + data: Pin<&Self::Data<'bound>>, + ); } =20 /// A USB interface. diff --git a/samples/rust/rust_driver_usb.rs b/samples/rust/rust_driver_usb= .rs index e900993335e9..02bd5085f9bc 100644 --- a/samples/rust/rust_driver_usb.rs +++ b/samples/rust/rust_driver_usb.rs @@ -26,21 +26,21 @@ struct SampleDriver { =20 impl usb::Driver for SampleDriver { type IdInfo =3D (); - type Data =3D Self; + type Data<'bound> =3D Self; const ID_TABLE: usb::IdTable =3D &USB_TABLE; =20 - fn probe( - intf: &usb::Interface>, + fn probe<'bound>( + intf: &'bound usb::Interface>, _id: &usb::DeviceId, - _info: &Self::IdInfo, - ) -> impl PinInit { + _info: &'bound Self::IdInfo, + ) -> impl PinInit + 'bound { let dev: &device::Device> =3D intf.as_ref(); dev_info!(dev, "Rust USB driver sample probed\n"); =20 Ok(Self { _intf: intf.into() }) } =20 - fn disconnect(intf: &usb::Interface>, _data: Pin<&Self>) { + fn disconnect<'bound>(intf: &'bound usb::Interface>, _data: P= in<&Self>) { let dev: &device::Device> =3D intf.as_ref(); dev_info!(dev, "Rust USB driver sample disconnected\n"); } --=20 2.54.0 From nobody Mon Jun 8 22:51:08 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 0528D1922FD; Mon, 25 May 2026 20:31:25 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779741087; cv=none; b=pBwgKXFJB8SgJ08/hReYcms4T0d1rYSaM4/iqDEWEJVe64kh9IaufT5wwE6WVSNUzA7NBevsnqJmV+/X1sZMGF4QXTUKkv782ge296pUsjo/ozAQLACkHv/DZNvnUlP7hKpizJW2mxvYNzKR/HN7mhSwUrHNN4mcxlO5Xxb4Sq0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779741087; c=relaxed/simple; bh=/SWg18ccHjfD3K9cefVN7ySt6yV1yOnUZbAdMsv2wLI=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=b8sNnVNxrZYSfSYJynQNdzKnvRrL363rDUm+NUsq2+oOsUHXjI1gI0llEpqnyGo1W8lpcQYjEffSsxZHAGrCE3YA2gfeT++eKfV1qobXmDpUsPVrRNAM5uy/zXLB4m0jtRlFPOc5W5yIaLKA1kjWGHBblhxLOTfgwAo4VeX43GA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=RgzFvYdH; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="RgzFvYdH" Received: by smtp.kernel.org (Postfix) with ESMTPSA id EDE501F00A3A; Mon, 25 May 2026 20:31:18 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1779741085; bh=z11UvhgWKKI+6/EKxkmzn/nsBmglIioHgcmgo3Ma1ao=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=RgzFvYdHim5i70pkW58BdnAg7eHxoPEq5f3D+giQr18kn6I23lyT6ZwTuL5+CpRzU I2zTTrGxspIqDOjSK4K+RiEaW2Sk9W10Pekqol5UtikwbHelFc2CFSvILbaFtu+k/W avV5JASb6F7JLAGxtW5LpXCjUCWbwtPhq/7L6mNdOAliQZlJdH7rsL2XYx9pdtIBqI qanJPfl1Yn+JPxVoqwvt1I5IttuwaSV+KV5eBlOftCmix0dxK+b2Lx50TeFxQEk3rS LcPCsbQObOax6sc0EpPnPRwRqq2iBsQlOuS5Z9stTcj4iLLf0iNlCzxOCWIhJf8/Gq AaZDcjAnuoGww== From: Danilo Krummrich To: gregkh@linuxfoundation.org, rafael@kernel.org, acourbot@nvidia.com, aliceryhl@google.com, david.m.ertman@intel.com, ira.weiny@intel.com, leon@kernel.org, viresh.kumar@linaro.org, m.wilczynski@samsung.com, ukleinek@kernel.org, bhelgaas@google.com, kwilczynski@kernel.org, abdiel.janulgue@gmail.com, robin.murphy@arm.com, markus.probst@posteo.de, ojeda@kernel.org, boqun@kernel.org, gary@garyguo.net, bjorn3_gh@protonmail.com, lossin@kernel.org, a.hindborg@kernel.org, tmgross@umich.edu, igor.korotin@linux.dev, daniel.almeida@collabora.com, pcolberg@redhat.com Cc: driver-core@lists.linux.dev, linux-kernel@vger.kernel.org, nova-gpu@lists.linux.dev, dri-devel@lists.freedesktop.org, linux-pm@vger.kernel.org, linux-pwm@vger.kernel.org, linux-pci@vger.kernel.org, rust-for-linux@vger.kernel.org, Danilo Krummrich Subject: [PATCH v5 16/24] rust: i2c: make Driver trait lifetime-parameterized Date: Mon, 25 May 2026 22:21:03 +0200 Message-ID: <20260525202921.124698-17-dakr@kernel.org> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260525202921.124698-1-dakr@kernel.org> References: <20260525202921.124698-1-dakr@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add a 'bound lifetime to the associated Data, changing type Data to type Data<'bound>. This allows the driver's bus device private data to capture the device / driver bound lifetime; device resources can be stored directly by reference rather than requiring Devres. The probe() and unbind() callbacks thus gain a 'bound lifetime parameter on the methods themselves; avoiding a global lifetime on the trait impl. Existing drivers set type Data<'bound> =3D Self, preserving the current behavior. Acked-by: Igor Korotin Reviewed-by: Alexandre Courbot Reviewed-by: Greg Kroah-Hartman Signed-off-by: Danilo Krummrich Reviewed-by: Gary Guo --- rust/kernel/i2c.rs | 39 ++++++++++++++++++--------------- samples/rust/rust_driver_i2c.rs | 14 ++++++------ 2 files changed, 28 insertions(+), 25 deletions(-) diff --git a/rust/kernel/i2c.rs b/rust/kernel/i2c.rs index 50feade0fb58..6094d32652e3 100644 --- a/rust/kernel/i2c.rs +++ b/rust/kernel/i2c.rs @@ -98,7 +98,7 @@ macro_rules! i2c_device_table { // - `DEVICE_DRIVER_OFFSET` is the correct byte offset to the embedded `st= ruct device_driver`. unsafe impl driver::DriverLayout for Adapter { type DriverType =3D bindings::i2c_driver; - type DriverData<'bound> =3D T::Data; + type DriverData<'bound> =3D T::Data<'bound>; const DEVICE_DRIVER_OFFSET: usize =3D core::mem::offset_of!(Self::Driv= erType, driver); } =20 @@ -176,8 +176,8 @@ extern "C" fn remove_callback(idev: *mut bindings::i2c_= client) { =20 // SAFETY: `remove_callback` is only ever called after a successfu= l call to // `probe_callback`, hence it's guaranteed that `I2cClient::set_dr= vdata()` has been called - // and stored a `Pin>`. - let data =3D unsafe { idev.as_ref().drvdata_borrow::() }; + // and stored a `Pin>>`. + let data =3D unsafe { idev.as_ref().drvdata_borrow::>(= ) }; =20 T::unbind(idev, data); } @@ -188,8 +188,8 @@ extern "C" fn shutdown_callback(idev: *mut bindings::i2= c_client) { =20 // SAFETY: `shutdown_callback` is only ever called after a success= ful call to // `probe_callback`, hence it's guaranteed that `Device::set_drvda= ta()` has been called - // and stored a `Pin>`. - let data =3D unsafe { idev.as_ref().drvdata_borrow::() }; + // and stored a `Pin>>`. + let data =3D unsafe { idev.as_ref().drvdata_borrow::>(= ) }; =20 T::shutdown(idev, data); } @@ -294,19 +294,22 @@ macro_rules! module_i2c_driver { /// /// impl i2c::Driver for MyDriver { /// type IdInfo =3D (); -/// type Data =3D Self; +/// type Data<'bound> =3D Self; /// const I2C_ID_TABLE: Option> =3D Some(&I= 2C_TABLE); /// const OF_ID_TABLE: Option> =3D Some(&OF_= TABLE); /// const ACPI_ID_TABLE: Option> =3D Some(= &ACPI_TABLE); /// -/// fn probe( -/// _idev: &i2c::I2cClient>, -/// _id_info: Option<&Self::IdInfo>, -/// ) -> impl PinInit { +/// fn probe<'bound>( +/// _idev: &'bound i2c::I2cClient>, +/// _id_info: Option<&'bound Self::IdInfo>, +/// ) -> impl PinInit, Error> + 'bound { /// Err(ENODEV) /// } /// -/// fn shutdown(_idev: &i2c::I2cClient>, this: Pin<&Self::Dat= a>) { +/// fn shutdown<'bound>( +/// _idev: &'bound i2c::I2cClient>, +/// this: Pin<&Self::Data<'bound>>, +/// ) { /// } /// } ///``` @@ -320,7 +323,7 @@ pub trait Driver { type IdInfo: 'static; =20 /// The type of the driver's bus device private data. - type Data: Send; + type Data<'bound>: Send + 'bound; =20 /// The table of device ids supported by the driver. const I2C_ID_TABLE: Option> =3D None; @@ -335,10 +338,10 @@ pub trait Driver { /// /// Called when a new i2c client is added or discovered. /// Implementers should attempt to initialize the client here. - fn probe( - dev: &I2cClient>, - id_info: Option<&Self::IdInfo>, - ) -> impl PinInit; + fn probe<'bound>( + dev: &'bound I2cClient>, + id_info: Option<&'bound Self::IdInfo>, + ) -> impl PinInit, Error> + 'bound; =20 /// I2C driver shutdown. /// @@ -351,7 +354,7 @@ fn probe( /// This callback is distinct from final resource cleanup, as the driv= er instance remains valid /// after it returns. Any deallocation or teardown of driver-owned res= ources should instead be /// handled in `Drop`. - fn shutdown(dev: &I2cClient>, this: Pin<&Self::Data>)= { + fn shutdown<'bound>(dev: &'bound I2cClient>, this: Pi= n<&Self::Data<'bound>>) { let _ =3D (dev, this); } =20 @@ -365,7 +368,7 @@ fn shutdown(dev: &I2cClient>, this: Pi= n<&Self::Data>) { /// operations to gracefully tear down the device. /// /// Otherwise, release operations for driver resources should be perfo= rmed in `Drop`. - fn unbind(dev: &I2cClient>, this: Pin<&Self::Data>) { + fn unbind<'bound>(dev: &'bound I2cClient>, this: Pin<= &Self::Data<'bound>>) { let _ =3D (dev, this); } } diff --git a/samples/rust/rust_driver_i2c.rs b/samples/rust/rust_driver_i2c= .rs index 171550ea0b6f..ead8263a7d48 100644 --- a/samples/rust/rust_driver_i2c.rs +++ b/samples/rust/rust_driver_i2c.rs @@ -35,16 +35,16 @@ =20 impl i2c::Driver for SampleDriver { type IdInfo =3D u32; - type Data =3D Self; + type Data<'bound> =3D Self; =20 const ACPI_ID_TABLE: Option> =3D Some(&ACP= I_TABLE); const I2C_ID_TABLE: Option> =3D Some(&I2C_T= ABLE); const OF_ID_TABLE: Option> =3D Some(&OF_TABL= E); =20 - fn probe( - idev: &i2c::I2cClient>, - info: Option<&Self::IdInfo>, - ) -> impl PinInit { + fn probe<'bound>( + idev: &'bound i2c::I2cClient>, + info: Option<&'bound Self::IdInfo>, + ) -> impl PinInit + 'bound { let dev =3D idev.as_ref(); =20 dev_info!(dev, "Probe Rust I2C driver sample.\n"); @@ -56,11 +56,11 @@ fn probe( Ok(Self) } =20 - fn shutdown(idev: &i2c::I2cClient>, _this: Pin<&Self>) { + fn shutdown<'bound>(idev: &'bound i2c::I2cClient>, _this: Pin= <&Self>) { dev_info!(idev.as_ref(), "Shutdown Rust I2C driver sample.\n"); } =20 - fn unbind(idev: &i2c::I2cClient>, _this: Pin<&Self>) { + fn unbind<'bound>(idev: &'bound i2c::I2cClient>, _this: Pin<&= Self>) { dev_info!(idev.as_ref(), "Unbind Rust I2C driver sample.\n"); } } --=20 2.54.0 From nobody Mon Jun 8 22:51:08 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 275EE388395; Mon, 25 May 2026 20:31:32 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779741094; cv=none; b=fbSg0a7oIubX4vugKB3cZtP2RIXWdUH6jzHAkqpT7AgyeH9zV0kdQspJcBJZAK50211x/ns4QsIF9YxlYsA8z1Q/erG4r/2tZmTV/TRwKr0/NXVO5haBcRQFIPgPcgd6ta0dOLtUi0itCbXe0ABNEEHoO5DCjJik8mgz9oVDWNU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779741094; c=relaxed/simple; bh=4lUdb3GLV0bIT4cTMl+sMY7+bby0f6VtUE0KQm+Iua8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=J/7CmMvJW6Ky25N7ETF/U9Qxx2cxtrjHT5OzzYyaEVafNZ2HQjRjHRTZcGa/d+mrLcDg9mPNf2XeKjNKU6nmS3C3fG7bmTo3FOYB4eri785tG3ts1zwwliwe1j1bJduaEbB2uOv/NEFNOMKCCEe8+4QRt6NYVwfBqCuJQt2G3yY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=iGqL+gBh; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="iGqL+gBh" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 1C5431F00A3C; Mon, 25 May 2026 20:31:25 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1779741092; bh=Se+m8/YyT4y61WXM80uAn3qM9HqLztSmo/d1R/PiPM0=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=iGqL+gBhYw6zBQp6KgNgwxdmLs9m0TBr/SSZlfKne4Vr3qbvp+59sUzQJdbQbKk3K 7ZhUFF6yPnVy5leu9VG2kgzIap10ibL87kYsXVKngvbNwTldOJcISU6cYrRSLPffOO P4m0V+pMx/X0UbyYAizJxQ+ck4GYw0FyoqfrTpFe3YP/4T81txh4n9P+BWUaLf2cWh c1Ju9gtCP1meNHqIM0sWVV80XeEjwdARl6QkRf6838/Cz/VVdFdYAsc4hPGKcyc56+ im4yJJ6m1uTM2yzVXBCjXT4PRAVoJrfndobKovSkaUasruFtXZvAMTcMLpOWw1K/Ta GwEOCVOvfDPOg== From: Danilo Krummrich To: gregkh@linuxfoundation.org, rafael@kernel.org, acourbot@nvidia.com, aliceryhl@google.com, david.m.ertman@intel.com, ira.weiny@intel.com, leon@kernel.org, viresh.kumar@linaro.org, m.wilczynski@samsung.com, ukleinek@kernel.org, bhelgaas@google.com, kwilczynski@kernel.org, abdiel.janulgue@gmail.com, robin.murphy@arm.com, markus.probst@posteo.de, ojeda@kernel.org, boqun@kernel.org, gary@garyguo.net, bjorn3_gh@protonmail.com, lossin@kernel.org, a.hindborg@kernel.org, tmgross@umich.edu, igor.korotin@linux.dev, daniel.almeida@collabora.com, pcolberg@redhat.com Cc: driver-core@lists.linux.dev, linux-kernel@vger.kernel.org, nova-gpu@lists.linux.dev, dri-devel@lists.freedesktop.org, linux-pm@vger.kernel.org, linux-pwm@vger.kernel.org, linux-pci@vger.kernel.org, rust-for-linux@vger.kernel.org, Danilo Krummrich Subject: [PATCH v5 17/24] rust: driver: update module documentation for GAT-based Data type Date: Mon, 25 May 2026 22:21:04 +0200 Message-ID: <20260525202921.124698-18-dakr@kernel.org> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260525202921.124698-1-dakr@kernel.org> References: <20260525202921.124698-1-dakr@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Now that all bus driver traits use type Data<'bound>: 'bound, update the illustrative driver trait in the module documentation to reflect the GAT pattern and lifetime-parameterized callbacks. Reviewed-by: Alexandre Courbot Reviewed-by: Greg Kroah-Hartman Signed-off-by: Danilo Krummrich Reviewed-by: Gary Guo --- rust/kernel/driver.rs | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/rust/kernel/driver.rs b/rust/kernel/driver.rs index 558fdef4a1c6..03c0dd713f4c 100644 --- a/rust/kernel/driver.rs +++ b/rust/kernel/driver.rs @@ -18,7 +18,7 @@ //! type IdInfo: 'static; //! //! /// The type of the driver's bus device private data. -//! type Data: Send; +//! type Data<'bound>: Send + 'bound; //! //! /// The table of OF device ids supported by the driver. //! const OF_ID_TABLE: Option> =3D None; @@ -27,11 +27,16 @@ //! const ACPI_ID_TABLE: Option> =3D None; //! //! /// Driver probe. -//! fn probe(dev: &Device>, id_info: &Self::IdInfo) -//! -> impl PinInit; +//! fn probe<'bound>( +//! dev: &'bound Device>, +//! id_info: &'bound Self::IdInfo, +//! ) -> impl PinInit, Error> + 'bound; //! //! /// Driver unbind (optional). -//! fn unbind(dev: &Device>, this: Pin<&Self::Data>) { +//! fn unbind<'bound>( +//! dev: &'bound Device>, +//! this: Pin<&Self::Data<'bound>>, +//! ) { //! let _ =3D (dev, this); //! } //! } @@ -46,9 +51,10 @@ )] #![cfg_attr(CONFIG_PCI, doc =3D "* [`pci::Driver`](kernel::pci::Driver)")] //! -//! The `probe()` callback should return a `impl PinInit`, i.e. the driver's -//! private data. The bus abstraction should store the pointer in the corr= esponding bus device. The -//! generic [`Device`] infrastructure provides common helpers for this pur= pose on its +//! The `probe()` callback should return a +//! `impl PinInit, Error>`, i.e. the driver's private d= ata. The bus +//! abstraction should store the pointer in the corresponding bus device. = The generic +//! [`Device`] infrastructure provides common helpers for this purpose on = its //! [`Device`] implementation. //! //! All driver callbacks should provide a reference to the driver's privat= e data. Once the driver --=20 2.54.0 From nobody Mon Jun 8 22:51:08 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6E921346781; Mon, 25 May 2026 20:31:40 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779741101; cv=none; b=fa73tLHSHR8ocGlPejHB2QEbvKDOJP6e+p87jW9qQWLi4m3wcSVzZrq9zNglG3nP6u5ImCMqLoOjqp/OYocKvxL0qdsVj339jiYW22tN3V+HELhNjzoqgfiV+5gAkID1c7gHjgP7kAgSUXK3Doe7w3nqK2qHxM50QP/7dint3CU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779741101; c=relaxed/simple; bh=YgjMVlOnOEnOgJfSzyZZhjx0/WQEcOL7rF0Q96bVxhc=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=e/D7gPNMJPb8EvWZSAeAai54se3jSER3bxwZhJ/QcxjVnpzLOm5fG1ggMp6yv2VuE1paeatYanUFLpCLZ3eD5BqiWULaDFN5+/qkzla/7WRVAE2Do4rDHgNWtAOlvrn3eRCYOJIJO+M8FENsaMRF6FYso7K5XQi0gCBs0NaXrWQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=h2wxHi3t; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="h2wxHi3t" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 3C0A81F000E9; Mon, 25 May 2026 20:31:33 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1779741100; bh=pYMsChqTO3W2bfJZCzKzWuNhJ1vdYr5kTucdQkADqYM=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=h2wxHi3tukLONpF+s+2OoV+pnqU1G1hB6dQ3C+rU/zsZL3MzhaSOVz8Sb6t60Vk0h CaoAFPGpeA3h254wEBydvZnrkgINEoOXNeaNa4vxRnTnqtGOCFCwnbXB/cfIxhKd6j hLoUnCWUjfN1Re3fRJfIiRTaz/+BrHV4/a/FBcVwAYseWRhCR39iq9Vb1t3tcl1qow WDBTO1j48ySGQi81ejGW0XLzqaNCY1ZSgQKU9j3DvfP01O1fvUvYAPlNzT6RjZOvNs bD9vkFDF3Uc7Jx9RhZ8a0rWguuNDkNWwFlhL0Rsr/7xuKWUkEGJXQmfHGgDGltGrzi +asZ9+R3Iyn2Q== From: Danilo Krummrich To: gregkh@linuxfoundation.org, rafael@kernel.org, acourbot@nvidia.com, aliceryhl@google.com, david.m.ertman@intel.com, ira.weiny@intel.com, leon@kernel.org, viresh.kumar@linaro.org, m.wilczynski@samsung.com, ukleinek@kernel.org, bhelgaas@google.com, kwilczynski@kernel.org, abdiel.janulgue@gmail.com, robin.murphy@arm.com, markus.probst@posteo.de, ojeda@kernel.org, boqun@kernel.org, gary@garyguo.net, bjorn3_gh@protonmail.com, lossin@kernel.org, a.hindborg@kernel.org, tmgross@umich.edu, igor.korotin@linux.dev, daniel.almeida@collabora.com, pcolberg@redhat.com Cc: driver-core@lists.linux.dev, linux-kernel@vger.kernel.org, nova-gpu@lists.linux.dev, dri-devel@lists.freedesktop.org, linux-pm@vger.kernel.org, linux-pwm@vger.kernel.org, linux-pci@vger.kernel.org, rust-for-linux@vger.kernel.org, Danilo Krummrich , Eliot Courtney Subject: [PATCH v5 18/24] rust: pci: make Bar lifetime-parameterized Date: Mon, 25 May 2026 22:21:05 +0200 Message-ID: <20260525202921.124698-19-dakr@kernel.org> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260525202921.124698-1-dakr@kernel.org> References: <20260525202921.124698-1-dakr@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Convert pci::Bar to pci::Bar<'a, SIZE>, storing &'a Device to tie the BAR mapping lifetime to the device. iomap_region_sized() now returns Result> directly instead of impl PinInit>, Error>. Since the lifetime ties the mapping to the device's bound state, callers no longer need Devres for the common case where the Bar lives in the driver's private data. Add Bar::into_devres() to consume the bar and register it as a device-managed resource, returning Devres>. The lifetime is erased to 'static because Devres guarantees the bar does not actually outlive the device -- access is revoked on unbind. Reviewed-by: Eliot Courtney Reviewed-by: Greg Kroah-Hartman Reviewed-by: Alexandre Courbot Signed-off-by: Danilo Krummrich Reviewed-by: Gary Guo --- drivers/gpu/nova-core/driver.rs | 7 +++-- rust/kernel/devres.rs | 2 +- rust/kernel/pci/io.rs | 52 +++++++++++++++++++-------------- samples/rust/rust_driver_pci.rs | 5 ++-- 4 files changed, 38 insertions(+), 28 deletions(-) diff --git a/drivers/gpu/nova-core/driver.rs b/drivers/gpu/nova-core/driver= .rs index 6ad1a856694c..7dbec0470c26 100644 --- a/drivers/gpu/nova-core/driver.rs +++ b/drivers/gpu/nova-core/driver.rs @@ -45,7 +45,7 @@ pub(crate) struct NovaCore { // DMA addresses. These systems should be quite rare. const GPU_DMA_BITS: u32 =3D 47; =20 -pub(crate) type Bar0 =3D pci::Bar; +pub(crate) type Bar0 =3D pci::Bar<'static, BAR0_SIZE>; =20 kernel::pci_device_table!( PCI_TABLE, @@ -92,8 +92,9 @@ fn probe<'bound>( // other threads of execution. unsafe { pdev.dma_set_mask_and_coherent(DmaMask::new::())? }; =20 - let bar =3D Arc::pin_init( - pdev.iomap_region_sized::(0, c"nova-core/bar0"), + let bar =3D Arc::new( + pdev.iomap_region_sized::(0, c"nova-core/bar0")? + .into_devres()?, GFP_KERNEL, )?; =20 diff --git a/rust/kernel/devres.rs b/rust/kernel/devres.rs index fd4633f977f6..82cbd8b969fb 100644 --- a/rust/kernel/devres.rs +++ b/rust/kernel/devres.rs @@ -304,7 +304,7 @@ pub fn device(&self) -> &Device { /// pci, // /// }; /// - /// fn from_core(dev: &pci::Device>, devres: Devres>) -> Result { + /// fn from_core(dev: &pci::Device>, devres: Devres>) -> Result { /// let bar =3D devres.access(dev.as_ref())?; /// /// let _ =3D bar.read32(0x0); diff --git a/rust/kernel/pci/io.rs b/rust/kernel/pci/io.rs index 3ce21482b079..0461e01aaa20 100644 --- a/rust/kernel/pci/io.rs +++ b/rust/kernel/pci/io.rs @@ -14,8 +14,7 @@ Mmio, MmioRaw, // }, - prelude::*, - sync::aref::ARef, // + prelude::*, // }; use core::{ marker::PhantomData, @@ -146,14 +145,18 @@ impl<'a, S: ConfigSpaceKind> IoKnownSize for ConfigSp= ace<'a, S> { /// /// `Bar` always holds an `IoRaw` instance that holds a valid pointer to t= he start of the I/O /// memory mapped PCI BAR and its size. -pub struct Bar { - pdev: ARef, +pub struct Bar<'a, const SIZE: usize =3D 0> { + pdev: &'a Device, io: MmioRaw, num: i32, } =20 -impl Bar { - pub(super) fn new(pdev: &Device, num: u32, name: &'static CStr) -> Res= ult { +impl<'a, const SIZE: usize> Bar<'a, SIZE> { + pub(super) fn new( + pdev: &'a Device, + num: u32, + name: &'static CStr, + ) -> Result { let len =3D pdev.resource_len(num)?; if len =3D=3D 0 { return Err(ENOMEM); @@ -196,11 +199,7 @@ pub(super) fn new(pdev: &Device, num: u32, name: &'sta= tic CStr) -> Result } }; =20 - Ok(Bar { - pdev: pdev.into(), - io, - num, - }) + Ok(Bar { pdev, io, num }) } =20 /// # Safety @@ -219,11 +218,24 @@ unsafe fn do_release(pdev: &Device, ioptr: usize, num= : i32) { =20 fn release(&self) { // SAFETY: The safety requirements are guaranteed by the type inva= riant of `self.pdev`. - unsafe { Self::do_release(&self.pdev, self.io.addr(), self.num) }; + unsafe { Self::do_release(self.pdev, self.io.addr(), self.num) }; + } + + /// Consume the `Bar` and register it as a device-managed resource. + /// + /// The returned `Devres>` can outlive the original= lifetime `'a`. Access + /// to the BAR is revoked when the device is unbound. + pub fn into_devres(self) -> Result>> { + // SAFETY: Casting to `'static` is sound because `Devres` guarante= es the `Bar` does not + // actually outlive the device -- access is revoked and the resour= ce is released when the + // device is unbound. + let bar: Bar<'static, SIZE> =3D unsafe { core::mem::transmute(self= ) }; + let pdev =3D bar.pdev; + Devres::new(pdev.as_ref(), bar) } } =20 -impl Bar { +impl Bar<'_> { #[inline] pub(super) fn index_is_valid(index: u32) -> bool { // A `struct pci_dev` owns an array of resources with at most `PCI= _NUM_RESOURCES` entries. @@ -231,13 +243,13 @@ pub(super) fn index_is_valid(index: u32) -> bool { } } =20 -impl Drop for Bar { +impl Drop for Bar<'_, SIZE> { fn drop(&mut self) { self.release(); } } =20 -impl Deref for Bar { +impl Deref for Bar<'_, SIZE> { type Target =3D Mmio; =20 fn deref(&self) -> &Self::Target { @@ -253,16 +265,12 @@ pub fn iomap_region_sized<'a, const SIZE: usize>( &'a self, bar: u32, name: &'static CStr, - ) -> impl PinInit>, Error> + 'a { - Devres::new(self.as_ref(), Bar::::new(self, bar, name)) + ) -> Result> { + Bar::new(self, bar, name) } =20 /// Maps an entire PCI BAR after performing a region-request on it. - pub fn iomap_region<'a>( - &'a self, - bar: u32, - name: &'static CStr, - ) -> impl PinInit, Error> + 'a { + pub fn iomap_region<'a>(&'a self, bar: u32, name: &'static CStr) -> Re= sult> { self.iomap_region_sized::<0>(bar, name) } =20 diff --git a/samples/rust/rust_driver_pci.rs b/samples/rust/rust_driver_pci= .rs index 6791d98e1c79..0353481b0690 100644 --- a/samples/rust/rust_driver_pci.rs +++ b/samples/rust/rust_driver_pci.rs @@ -45,7 +45,7 @@ mod regs { pub(super) const END: usize =3D 0x10; } =20 -type Bar0 =3D pci::Bar<{ regs::END }>; +type Bar0 =3D pci::Bar<'static, { regs::END }>; =20 #[derive(Copy, Clone, Debug)] struct TestIndex(u8); @@ -161,7 +161,8 @@ fn probe<'bound>( pdev.set_master(); =20 Ok(try_pin_init!(Self { - bar <- pdev.iomap_region_sized::<{ regs::END }>(0, c"rust_= driver_pci"), + bar: pdev.iomap_region_sized::<{ regs::END }>(0, c"rust_dr= iver_pci")? + .into_devres()?, index: *info, _: { let bar =3D bar.access(pdev.as_ref())?; --=20 2.54.0 From nobody Mon Jun 8 22:51:08 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 124D639B49E; Mon, 25 May 2026 20:31:47 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779741109; cv=none; b=FWz/IUVlMYdTlBizBNISqjYvlcZ36GkR4npGyOHOuh7y7lemVATClY2owgfKz7ZR2C+KunxkPfqNtAQEaEjA/ZV3vshBTFxal0uwQbE1Ipge0iK4lxQP7sWdRBb9rTa5D522Xl6VTvAScpW01Jh2hBl723ZrF3cw1BcbGXcHMnM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779741109; c=relaxed/simple; bh=4haRq1vbJd2fRcQo8B9tOKkWxj2WfgnF+h+Lo1XjcEI=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=p1CqYgSYb6Py5iI+XkRihLwJtmPjtdfylK1lSKPGtVlYlh2BmfAdmrmLvL+ph2Wu7XO+8jIys72Y2RVXTmvpGPiRhkC7DQ1JXpiCWkxaUZXH7rSXDo9itScFn12VOqms3C6RaIQt91psNFsTX9kiUfoMRZ2CDOHSFJo4egKY5PY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=aOLuWrRT; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="aOLuWrRT" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 8A0641F00A3A; Mon, 25 May 2026 20:31:40 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1779741107; bh=FAC3DL61CBDdZZhQYeFer0JqaOgTXK5sDK42iWhKYgc=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=aOLuWrRTeUs8E/1PYAxtGmQpgPpQKyCJfUlHYnIIsNB4/8DjOAnw/p5xa6kIfN1KV 4A7WANBGLmbUKwr2Ia4J7UJ85+/31PD4b0JVNkKQpQxFiTAz0kb+ghHhmFB3clNd6/ wDcpB8VuGUv0AYzE+xmz+wQS5zj1L/pcTgVoxfGo+ePYswwZzshJwhp1cS62/2Gu5/ aUA+sSLFoFP9iuzJHpwbtoLddA95NrrXESjhiIXP6wWzI6DVj9nkl3vIBhlvdENtYt xh5swJKBDT9O2mKe2TyHnjTbxMxl8vLl+ZI7tddMltHQXpOFhNbX2/7fM+I2p8Gp3X 0nL3G1agbrAFA== From: Danilo Krummrich To: gregkh@linuxfoundation.org, rafael@kernel.org, acourbot@nvidia.com, aliceryhl@google.com, david.m.ertman@intel.com, ira.weiny@intel.com, leon@kernel.org, viresh.kumar@linaro.org, m.wilczynski@samsung.com, ukleinek@kernel.org, bhelgaas@google.com, kwilczynski@kernel.org, abdiel.janulgue@gmail.com, robin.murphy@arm.com, markus.probst@posteo.de, ojeda@kernel.org, boqun@kernel.org, gary@garyguo.net, bjorn3_gh@protonmail.com, lossin@kernel.org, a.hindborg@kernel.org, tmgross@umich.edu, igor.korotin@linux.dev, daniel.almeida@collabora.com, pcolberg@redhat.com Cc: driver-core@lists.linux.dev, linux-kernel@vger.kernel.org, nova-gpu@lists.linux.dev, dri-devel@lists.freedesktop.org, linux-pm@vger.kernel.org, linux-pwm@vger.kernel.org, linux-pci@vger.kernel.org, rust-for-linux@vger.kernel.org, Danilo Krummrich , Eliot Courtney Subject: [PATCH v5 19/24] rust: io: make IoMem and ExclusiveIoMem lifetime-parameterized Date: Mon, 25 May 2026 22:21:06 +0200 Message-ID: <20260525202921.124698-20-dakr@kernel.org> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260525202921.124698-1-dakr@kernel.org> References: <20260525202921.124698-1-dakr@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Add a lifetime parameter to IoMem<'a, SIZE> and ExclusiveIoMem<'a, SIZE>, storing a &'a Device reference to tie the mapping to the device's lifetime. This mirrors the pci::Bar<'a, SIZE> design and enables drivers to hold I/O memory mappings directly in their HRT private data, tied to the device lifetime. IoRequest::iomap_* methods now return the mapping directly instead of wrapping it in Devres. Callers that need device-managed revocation can call the new into_devres() method. Acked-by: Uwe Kleine-K=C3=B6nig Reviewed-by: Eliot Courtney Reviewed-by: Greg Kroah-Hartman Reviewed-by: Alexandre Courbot Signed-off-by: Danilo Krummrich Reviewed-by: Gary Guo --- drivers/gpu/drm/tyr/driver.rs | 4 +- drivers/pwm/pwm_th1520.rs | 4 +- rust/kernel/io/mem.rs | 103 +++++++++++++++++----------------- 3 files changed, 56 insertions(+), 55 deletions(-) diff --git a/drivers/gpu/drm/tyr/driver.rs b/drivers/gpu/drm/tyr/driver.rs index 797f09e23a4c..04f83fcf0937 100644 --- a/drivers/gpu/drm/tyr/driver.rs +++ b/drivers/gpu/drm/tyr/driver.rs @@ -37,7 +37,7 @@ regs, // }; =20 -pub(crate) type IoMem =3D kernel::io::mem::IoMem; +pub(crate) type IoMem =3D kernel::io::mem::IoMem<'static, SZ_2M>; =20 pub(crate) struct TyrDrmDriver; =20 @@ -110,7 +110,7 @@ fn probe<'bound>( let sram_regulator =3D Regulator::::get(pdev.a= s_ref(), c"sram")?; =20 let request =3D pdev.io_request_by_index(0).ok_or(ENODEV)?; - let iomem =3D Arc::pin_init(request.iomap_sized::(), GFP_KE= RNEL)?; + let iomem =3D Arc::new(request.iomap_sized::()?.into_devres= ()?, GFP_KERNEL)?; =20 issue_soft_reset(pdev.as_ref(), &iomem)?; gpu::l2_power_on(pdev.as_ref(), &iomem)?; diff --git a/drivers/pwm/pwm_th1520.rs b/drivers/pwm/pwm_th1520.rs index 6c5b791f3153..48808cd80737 100644 --- a/drivers/pwm/pwm_th1520.rs +++ b/drivers/pwm/pwm_th1520.rs @@ -92,7 +92,7 @@ struct Th1520WfHw { #[pin_data(PinnedDrop)] struct Th1520PwmDriverData { #[pin] - iomem: devres::Devres>, + iomem: devres::Devres>, clk: Clk, } =20 @@ -352,7 +352,7 @@ fn probe<'bound>( dev, TH1520_MAX_PWM_NUM, try_pin_init!(Th1520PwmDriverData { - iomem <- request.iomap_sized::(), + iomem <- request.iomap_sized::()?.int= o_devres(), clk <- clk, }), )?; diff --git a/rust/kernel/io/mem.rs b/rust/kernel/io/mem.rs index 51ba347220ee..fc2a3e24f8d5 100644 --- a/rust/kernel/io/mem.rs +++ b/rust/kernel/io/mem.rs @@ -74,22 +74,19 @@ pub(crate) unsafe fn new(device: &'a Device, res= ource: &'a Resource) -> S /// // /// // No runtime checks will apply when reading and writing. /// let request =3D pdev.io_request_by_index(0).ok_or(ENODEV)?; - /// let iomem =3D request.iomap_sized::<42>(); - /// let iomem =3D KBox::pin_init(iomem, GFP_KERNEL)?; - /// - /// let io =3D iomem.access(pdev.as_ref())?; + /// let iomem =3D request.iomap_sized::<42>()?; /// /// // Read and write a 32-bit value at `offset`. - /// let data =3D io.read32(offset); + /// let data =3D iomem.read32(offset); /// - /// io.write32(data, offset); + /// iomem.write32(data, offset); /// /// # Ok(SampleDriver) /// } /// } /// ``` - pub fn iomap_sized(self) -> impl PinInit>, Error> + 'a { - IoMem::new(self) + pub fn iomap_sized(self) -> Result>= { + IoMem::ioremap(self.device, self.resource) } =20 /// Same as [`Self::iomap_sized`] but with exclusive access to the @@ -98,10 +95,8 @@ pub fn iomap_sized(self) -> impl PinI= nit>, /// This uses the [`ioremap()`] C API. /// /// [`ioremap()`]: https://docs.kernel.org/driver-api/device-io.html#g= etting-access-to-the-device - pub fn iomap_exclusive_sized( - self, - ) -> impl PinInit>, Error> + 'a { - ExclusiveIoMem::new(self) + pub fn iomap_exclusive_sized(self) -> Result> { + ExclusiveIoMem::ioremap(self.device, self.resource) } =20 /// Maps an [`IoRequest`] where the size is not known at compile time, @@ -140,27 +135,24 @@ pub fn iomap_exclusive_sized( /// // family of functions should be used, leading to runtime ch= ecks on every /// // access. /// let request =3D pdev.io_request_by_index(0).ok_or(ENODEV)?; - /// let iomem =3D request.iomap(); - /// let iomem =3D KBox::pin_init(iomem, GFP_KERNEL)?; - /// - /// let io =3D iomem.access(pdev.as_ref())?; + /// let iomem =3D request.iomap()?; /// - /// let data =3D io.try_read32(offset)?; + /// let data =3D iomem.try_read32(offset)?; /// - /// io.try_write32(data, offset)?; + /// iomem.try_write32(data, offset)?; /// /// # Ok(SampleDriver) /// } /// } /// ``` - pub fn iomap(self) -> impl PinInit>, Error> + 'a { - Self::iomap_sized::<0>(self) + pub fn iomap(self) -> Result> { + self.iomap_sized::<0>() } =20 /// Same as [`Self::iomap`] but with exclusive access to the underlying /// region. - pub fn iomap_exclusive(self) -> impl PinInit>= , Error> + 'a { - Self::iomap_exclusive_sized::<0>(self) + pub fn iomap_exclusive(self) -> Result> { + self.iomap_exclusive_sized::<0>() } } =20 @@ -169,9 +161,9 @@ pub fn iomap_exclusive(self) -> impl PinInit>, Error> + /// # Invariants /// /// - [`ExclusiveIoMem`] has exclusive access to the underlying [`IoMem`]. -pub struct ExclusiveIoMem { +pub struct ExclusiveIoMem<'a, const SIZE: usize> { /// The underlying `IoMem` instance. - iomem: IoMem, + iomem: IoMem<'a, SIZE>, =20 /// The region abstraction. This represents exclusive access to the /// range represented by the underlying `iomem`. @@ -180,9 +172,9 @@ pub struct ExclusiveIoMem { _region: Region, } =20 -impl ExclusiveIoMem { +impl<'a, const SIZE: usize> ExclusiveIoMem<'a, SIZE> { /// Creates a new `ExclusiveIoMem` instance. - fn ioremap(resource: &Resource) -> Result { + fn ioremap(dev: &'a Device, resource: &Resource) -> Result { let start =3D resource.start(); let size =3D resource.size(); let name =3D resource.name().unwrap_or_default(); @@ -196,26 +188,29 @@ fn ioremap(resource: &Resource) -> Result { ) .ok_or(EBUSY)?; =20 - let iomem =3D IoMem::ioremap(resource)?; + let iomem =3D IoMem::ioremap(dev, resource)?; =20 - let iomem =3D ExclusiveIoMem { + Ok(ExclusiveIoMem { iomem, _region: region, - }; - - Ok(iomem) + }) } =20 - /// Creates a new `ExclusiveIoMem` instance from a previously acquired= [`IoRequest`]. - pub fn new<'a>(io_request: IoRequest<'a>) -> impl PinInit= , Error> + 'a { - let dev =3D io_request.device; - let res =3D io_request.resource; - - Devres::new(dev, Self::ioremap(res)) + /// Consume the `ExclusiveIoMem` and register it as a device-managed r= esource. + /// + /// The returned `Devres>` can outlive t= he original lifetime + /// `'a`. Access to the I/O memory is revoked when the device is unbou= nd. + pub fn into_devres(self) -> Result>> { + // SAFETY: Casting to `'static` is sound because `Devres` guarante= es the + // `ExclusiveIoMem` does not actually outlive the device -- access= is revoked and the + // resource is released when the device is unbound. + let iomem: ExclusiveIoMem<'static, SIZE> =3D unsafe { core::mem::t= ransmute(self) }; + let dev =3D iomem.iomem.dev; + Devres::new(dev, iomem) } } =20 -impl Deref for ExclusiveIoMem { +impl Deref for ExclusiveIoMem<'_, SIZE> { type Target =3D Mmio; =20 fn deref(&self) -> &Self::Target { @@ -232,12 +227,13 @@ fn deref(&self) -> &Self::Target { /// /// [`IoMem`] always holds an [`MmioRaw`] instance that holds a valid poin= ter to the /// start of the I/O memory mapped region. -pub struct IoMem { +pub struct IoMem<'a, const SIZE: usize =3D 0> { + dev: &'a Device, io: MmioRaw, } =20 -impl IoMem { - fn ioremap(resource: &Resource) -> Result { +impl<'a, const SIZE: usize> IoMem<'a, SIZE> { + fn ioremap(dev: &'a Device, resource: &Resource) -> Result { // Note: Some ioremap() implementations use types that depend on t= he CPU // word width rather than the bus address width. // @@ -269,28 +265,33 @@ fn ioremap(resource: &Resource) -> Result { } =20 let io =3D MmioRaw::new(addr as usize, size)?; - let io =3D IoMem { io }; =20 - Ok(io) + Ok(IoMem { dev, io }) } =20 - /// Creates a new `IoMem` instance from a previously acquired [`IoRequ= est`]. - pub fn new<'a>(io_request: IoRequest<'a>) -> impl PinInit= , Error> + 'a { - let dev =3D io_request.device; - let res =3D io_request.resource; - - Devres::new(dev, Self::ioremap(res)) + /// Consume the `IoMem` and register it as a device-managed resource. + /// + /// The returned `Devres>` can outlive the origin= al + /// lifetime `'a`. Access to the I/O memory is revoked when the device + /// is unbound. + pub fn into_devres(self) -> Result>> { + // SAFETY: Casting to `'static` is sound because `Devres` guarante= es the `IoMem` does not + // actually outlive the device -- access is revoked and the resour= ce is released when the + // device is unbound. + let iomem: IoMem<'static, SIZE> =3D unsafe { core::mem::transmute(= self) }; + let dev =3D iomem.dev; + Devres::new(dev, iomem) } } =20 -impl Drop for IoMem { +impl Drop for IoMem<'_, SIZE> { fn drop(&mut self) { // SAFETY: Safe as by the invariant of `Io`. unsafe { bindings::iounmap(self.io.addr() as *mut c_void) } } } =20 -impl Deref for IoMem { +impl Deref for IoMem<'_, SIZE> { type Target =3D Mmio; =20 fn deref(&self) -> &Self::Target { --=20 2.54.0 From nobody Mon Jun 8 22:51:08 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 16B4339B49E; Mon, 25 May 2026 20:31:54 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779741116; cv=none; b=fWcEoas8PlBHWobECdgjh4HOAfXc29IapqNX9EEF6lMjCVe81eS4bvHG4MnQMxfYLdcwtbqo5s76M3n9TQIk3Xz4ZM64HN1HSWhnH4QgbABP0o2+yjm+tXDS6Tt1wlcKuclf73jm+vRqL3bwtguLJTkmQn5qwIvXp2X1NSOQbvE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779741116; c=relaxed/simple; bh=tlD6i2CG+7bm/bwxk8qAZUUAAaJ0DgIod5ITrIouP/8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=KvF5VWWKsZx/e7+1uoHA3XmckMHbgbpfmRN8Os9YqEVSA7N+FBP7O7jtXzl1opKWomEb76Wwhkgmw1OPMdTYVw94QOtePJstHIziwGTLFJ5jXQSmGIwceSQX/7BXLk2HVv+nsH2wktyEXxNT6i9JRR4eSpDUhiv3KYvchlQ/YjE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=VKa3uY3M; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="VKa3uY3M" Received: by smtp.kernel.org (Postfix) with ESMTPSA id D706B1F000E9; Mon, 25 May 2026 20:31:47 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1779741114; bh=IHbdc7IMEfqk2So28I5grd/dDRiGUS4OZyecULC2DA4=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=VKa3uY3MWPYbWizj+8Nuy1rZxDqMw49pIaVhTmEFQu2VXATSaQ8stRPn4r6Qa58k7 xoSlSrbnvzoPf87UuETq4Sb07REWsi1CmVeflsGesQSHI5zcmeET236KeaRvVMOAok NI3GzH1g9c6FnMHL6SuJcAWtTuR/bos37J5AhjnIU0R8cYNw4NHByHYmtGEITU+r5r jgM1UOITaGyxjxWUbfEuWnzZWl/d38rx5qCuyVVQT9eVSoZlrcaLij1TZrpyNK23RP 2sRkeMvU1yLGBftNWrMufMKctiAz1YjaSMc99kkQJVjKg2ty5FLC90/TlzKvb0JFTy pKF35wnphRcpA== From: Danilo Krummrich To: gregkh@linuxfoundation.org, rafael@kernel.org, acourbot@nvidia.com, aliceryhl@google.com, david.m.ertman@intel.com, ira.weiny@intel.com, leon@kernel.org, viresh.kumar@linaro.org, m.wilczynski@samsung.com, ukleinek@kernel.org, bhelgaas@google.com, kwilczynski@kernel.org, abdiel.janulgue@gmail.com, robin.murphy@arm.com, markus.probst@posteo.de, ojeda@kernel.org, boqun@kernel.org, gary@garyguo.net, bjorn3_gh@protonmail.com, lossin@kernel.org, a.hindborg@kernel.org, tmgross@umich.edu, igor.korotin@linux.dev, daniel.almeida@collabora.com, pcolberg@redhat.com Cc: driver-core@lists.linux.dev, linux-kernel@vger.kernel.org, nova-gpu@lists.linux.dev, dri-devel@lists.freedesktop.org, linux-pm@vger.kernel.org, linux-pwm@vger.kernel.org, linux-pci@vger.kernel.org, rust-for-linux@vger.kernel.org, Danilo Krummrich , Eliot Courtney Subject: [PATCH v5 20/24] samples: rust: rust_driver_pci: use HRT lifetime for Bar Date: Mon, 25 May 2026 22:21:07 +0200 Message-ID: <20260525202921.124698-21-dakr@kernel.org> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260525202921.124698-1-dakr@kernel.org> References: <20260525202921.124698-1-dakr@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Convert the sample driver to SampleDriver<'bound>, taking advantage of the lifetime-parameterized Driver trait. The driver struct holds &'bound pci::Device directly instead of ARef, and pci::Bar<'bound> directly instead of Devres. This removes PinnedDrop, pin_init_scope, and runtime revocation checks on BAR access. Reviewed-by: Eliot Courtney Reviewed-by: Greg Kroah-Hartman Reviewed-by: Alexandre Courbot Signed-off-by: Danilo Krummrich Reviewed-by: Gary Guo --- samples/rust/rust_driver_pci.rs | 89 +++++++++++++++------------------ 1 file changed, 40 insertions(+), 49 deletions(-) diff --git a/samples/rust/rust_driver_pci.rs b/samples/rust/rust_driver_pci= .rs index 0353481b0690..1aa8197d8698 100644 --- a/samples/rust/rust_driver_pci.rs +++ b/samples/rust/rust_driver_pci.rs @@ -9,7 +9,6 @@ Bound, Core, // }, - devres::Devres, io::{ register, register::Array, @@ -17,8 +16,7 @@ }, num::Bounded, pci, - prelude::*, - sync::aref::ARef, // + prelude::*, // }; =20 mod regs { @@ -45,7 +43,7 @@ mod regs { pub(super) const END: usize =3D 0x10; } =20 -type Bar0 =3D pci::Bar<'static, { regs::END }>; +type Bar0<'bound> =3D pci::Bar<'bound, { regs::END }>; =20 #[derive(Copy, Clone, Debug)] struct TestIndex(u8); @@ -66,14 +64,14 @@ impl TestIndex { const NO_EVENTFD: Self =3D Self(0); } =20 -#[pin_data(PinnedDrop)] -struct SampleDriver { - pdev: ARef, - #[pin] - bar: Devres, +struct SampleDriverData<'bound> { + pdev: &'bound pci::Device, + bar: Bar0<'bound>, index: TestIndex, } =20 +struct SampleDriver; + kernel::pci_device_table!( PCI_TABLE, MODULE_PCI_TABLE, @@ -84,8 +82,8 @@ struct SampleDriver { )] ); =20 -impl SampleDriver { - fn testdev(index: &TestIndex, bar: &Bar0) -> Result { +impl SampleDriverData<'_> { + fn testdev(index: &TestIndex, bar: &Bar0<'_>) -> Result { // Select the test. bar.write_reg(regs::TEST::zeroed().with_index(*index)); =20 @@ -140,56 +138,49 @@ fn config_space(pdev: &pci::Device) { =20 impl pci::Driver for SampleDriver { type IdInfo =3D TestIndex; - type Data<'bound> =3D Self; + type Data<'bound> =3D SampleDriverData<'bound>; =20 const ID_TABLE: pci::IdTable =3D &PCI_TABLE; =20 fn probe<'bound>( pdev: &'bound pci::Device>, info: &'bound Self::IdInfo, - ) -> impl PinInit + 'bound { - pin_init::pin_init_scope(move || { - let vendor =3D pdev.vendor_id(); - dev_dbg!( - pdev, - "Probe Rust PCI driver sample (PCI ID: {}, 0x{:x}).\n", - vendor, - pdev.device_id() - ); - - pdev.enable_device_mem()?; - pdev.set_master(); - - Ok(try_pin_init!(Self { - bar: pdev.iomap_region_sized::<{ regs::END }>(0, c"rust_dr= iver_pci")? - .into_devres()?, - index: *info, - _: { - let bar =3D bar.access(pdev.as_ref())?; - - dev_info!( - pdev, - "pci-testdev data-match count: {}\n", - Self::testdev(info, bar)? - ); - Self::config_space(pdev); - }, - pdev: pdev.into(), - })) + ) -> impl PinInit, Error> + 'bound { + let vendor =3D pdev.vendor_id(); + dev_dbg!( + pdev, + "Probe Rust PCI driver sample (PCI ID: {}, 0x{:x}).\n", + vendor, + pdev.device_id() + ); + + pdev.enable_device_mem()?; + pdev.set_master(); + + let bar =3D pdev.iomap_region_sized::<{ regs::END }>(0, c"rust_dri= ver_pci")?; + + dev_info!( + pdev, + "pci-testdev data-match count: {}\n", + SampleDriverData::testdev(info, &bar)? + ); + SampleDriverData::config_space(pdev); + + Ok(SampleDriverData { + pdev, + bar, + index: *info, }) } =20 - fn unbind(pdev: &pci::Device>, this: Pin<&Self>) { - if let Ok(bar) =3D this.bar.access(pdev.as_ref()) { - // Reset pci-testdev by writing a new test index. - bar.write_reg(regs::TEST::zeroed().with_index(this.index)); - } + fn unbind<'bound>(_pdev: &'bound pci::Device>, this: Pin<&Sel= f::Data<'bound>>) { + this.bar + .write_reg(regs::TEST::zeroed().with_index(this.index)); } } =20 -#[pinned_drop] -impl PinnedDrop for SampleDriver { - fn drop(self: Pin<&mut Self>) { +impl Drop for SampleDriverData<'_> { + fn drop(&mut self) { dev_dbg!(self.pdev, "Remove Rust PCI driver sample.\n"); } } --=20 2.54.0 From nobody Mon Jun 8 22:51:08 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6D79E3A2E12; Mon, 25 May 2026 20:32:02 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779741123; cv=none; b=CHjglhpwlQMIqQOEIoB1b0xFhxbZa8fStf4wiJfQXkPyBY/0kah6qot2wbLb1Mkka+pqGvOzIoNZ47KwHJnZNkCzZU05LR4M651+u8562PBbPR+7bFsMsjDBIq8/3mVTrljqdBacinhjmQZ0pSyXO+tEosFq7evtfcJZsmzdnQM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779741123; c=relaxed/simple; bh=eMZYEAwO/dcQVCHMuVBPQlQnic9bmNikibb0MAHefbc=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=hrZZ982uq5UP5usjSpghmg+FsuEgMDAsL1vLbzjUcxOVOGrF9EtuQ7noe58sY9uTlQz68GdABKZxZiJHLY8QTyJYtGXBINI0T/yaoPm9SpWIMIrz2/W1MDsuVFCr2mycbMTQ8U9JSYfS5bVvu8rO/Jbabnl1YsB+rKqEa6ltaxQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=kB36nmiP; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="kB36nmiP" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 313461F00A3A; Mon, 25 May 2026 20:31:55 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1779741122; bh=cz4y8M1GiwY6FWOeDCyuhnlKEpB7EMBObHZNfzMoKFc=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=kB36nmiPeLWjK9MuZYO1n2hhOVi1mahYYeE42W+5vQvO7zNrGoUHFZhxd1AxFPRTY yEthQETelTJ/OzNxVRaJ7e80BFACQSImycJoXQYlsHtRqcBu5KAMw+9ufCabc3f7+b AlwV97p4vX4lsdIf7ZFlrexP1rr0h2n9SRMrUOKcdAlz8iK9ErbmXmx9yrTUGyJz3C 6YlR3TxSSuY2TeK7eaQVHo2FA2G+yvbMo+qR3+Y4HGs3PdvEin70Ik/V7Kv008hN0K /sxxVcq6Kj2l5RlAedLUjwOaFi1/yHxhUitBTK+P3f796Pjvf5TUYwa0weV6m7BepT ifCWNxla4rVNQ== From: Danilo Krummrich To: gregkh@linuxfoundation.org, rafael@kernel.org, acourbot@nvidia.com, aliceryhl@google.com, david.m.ertman@intel.com, ira.weiny@intel.com, leon@kernel.org, viresh.kumar@linaro.org, m.wilczynski@samsung.com, ukleinek@kernel.org, bhelgaas@google.com, kwilczynski@kernel.org, abdiel.janulgue@gmail.com, robin.murphy@arm.com, markus.probst@posteo.de, ojeda@kernel.org, boqun@kernel.org, gary@garyguo.net, bjorn3_gh@protonmail.com, lossin@kernel.org, a.hindborg@kernel.org, tmgross@umich.edu, igor.korotin@linux.dev, daniel.almeida@collabora.com, pcolberg@redhat.com Cc: driver-core@lists.linux.dev, linux-kernel@vger.kernel.org, nova-gpu@lists.linux.dev, dri-devel@lists.freedesktop.org, linux-pm@vger.kernel.org, linux-pwm@vger.kernel.org, linux-pci@vger.kernel.org, rust-for-linux@vger.kernel.org, Danilo Krummrich , Eliot Courtney Subject: [PATCH v5 21/24] gpu: nova-core: separate driver type from driver data Date: Mon, 25 May 2026 22:21:08 +0200 Message-ID: <20260525202921.124698-22-dakr@kernel.org> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260525202921.124698-1-dakr@kernel.org> References: <20260525202921.124698-1-dakr@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Introduce NovaCoreDriver as the driver type implementing pci::Driver, keeping NovaCore as the per-device data type. This prepares for making NovaCore lifetime-parameterized once auxiliary::Registration requires a lifetime for the binding scope. Reviewed-by: Greg Kroah-Hartman Reviewed-by: Alexandre Courbot Reviewed-by: Eliot Courtney Signed-off-by: Danilo Krummrich Reviewed-by: Gary Guo --- drivers/gpu/nova-core/driver.rs | 14 ++++++++------ drivers/gpu/nova-core/nova_core.rs | 2 +- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/nova-core/driver.rs b/drivers/gpu/nova-core/driver= .rs index 7dbec0470c26..fa898fe5c893 100644 --- a/drivers/gpu/nova-core/driver.rs +++ b/drivers/gpu/nova-core/driver.rs @@ -35,6 +35,8 @@ pub(crate) struct NovaCore { _reg: Devres>, } =20 +pub(crate) struct NovaCoreDriver; + const BAR0_SIZE: usize =3D SZ_16M; =20 // For now we only support Ampere which can use up to 47-bit DMA addresses. @@ -50,7 +52,7 @@ pub(crate) struct NovaCore { kernel::pci_device_table!( PCI_TABLE, MODULE_PCI_TABLE, - ::IdInfo, + ::IdInfo, [ // Modern NVIDIA GPUs will show up as either VGA or 3D controllers. ( @@ -72,15 +74,15 @@ pub(crate) struct NovaCore { ] ); =20 -impl pci::Driver for NovaCore { +impl pci::Driver for NovaCoreDriver { type IdInfo =3D (); - type Data<'bound> =3D Self; + type Data<'bound> =3D NovaCore; const ID_TABLE: pci::IdTable =3D &PCI_TABLE; =20 fn probe<'bound>( pdev: &'bound pci::Device>, _info: &'bound Self::IdInfo, - ) -> impl PinInit + 'bound { + ) -> impl PinInit + 'bound { pin_init::pin_init_scope(move || { dev_dbg!(pdev, "Probe Nova Core GPU driver.\n"); =20 @@ -98,7 +100,7 @@ fn probe<'bound>( GFP_KERNEL, )?; =20 - Ok(try_pin_init!(Self { + Ok(try_pin_init!(NovaCore { gpu <- Gpu::new(pdev, bar.clone(), bar.access(pdev.as_ref(= ))?), _reg: auxiliary::Registration::new( pdev.as_ref(), @@ -113,7 +115,7 @@ fn probe<'bound>( }) } =20 - fn unbind<'bound>(pdev: &'bound pci::Device>, this: Pin<&Self= >) { + fn unbind<'bound>(pdev: &'bound pci::Device>, this: Pin<&Nova= Core>) { this.gpu.unbind(pdev.as_ref()); } } diff --git a/drivers/gpu/nova-core/nova_core.rs b/drivers/gpu/nova-core/nov= a_core.rs index 04a1fa6b25f8..073d87714d3a 100644 --- a/drivers/gpu/nova-core/nova_core.rs +++ b/drivers/gpu/nova-core/nova_core.rs @@ -47,7 +47,7 @@ struct NovaCoreModule { // Fields are dropped in declaration order, so `_driver` is dropped fi= rst, // then `_debugfs_guard` clears `DEBUGFS_ROOT`. #[pin] - _driver: Registration>, + _driver: Registration>, _debugfs_guard: DebugfsRootGuard, } =20 --=20 2.54.0 From nobody Mon Jun 8 22:51:08 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C0A7D391507; Mon, 25 May 2026 20:32:09 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779741131; cv=none; b=DJr1I7JLU9gryM2kDuJo+fHBWpbtu64HKbaKZvnxoTKLxMt9sfp8yUb+3gGY8NHixToA43upmhHSrXXJHAydtfMSwvtlgqEd6mGdB8ex45aT1obthtnmRVsIuSv5gvsG1AnG+hu16+OVlbRY29WRhJjuBK8wBS1T01er3pKjD3M= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779741131; c=relaxed/simple; bh=IHaQuYg47hr3k5rgYo+NWVHsY8Vit+dpA/FBU0wY9v0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=MTHtYgG7q/nplioCXZoaRGyR2ftjQ/faBL7nJ6aRuIIhGYmThS85nnrmI79YPPEkXYBC9qOu2JmQoFKI5elLfAd6copu2FltvjC9tXSt+fFvQHovYZWLTihX53PFsNzgStRpuvWvdgtI+bcq3BXSsTHazEX96JstDcFmvZe9s8o= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=iiV7E+8/; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="iiV7E+8/" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 7F6701F000E9; Mon, 25 May 2026 20:32:02 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1779741129; bh=E4zpEusCdMf/QfSnJexsP+YgJXnkpXYP1sIafBv7Uns=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=iiV7E+8/ez7RDbMoL5i5Djq3p9M6HrPjjaop21XzjQsVxNawCoXnky/AGoVSX0bpd vl+D22vjYoFHafu8IAos4nID/ExaJcfPvYl6kASZT1JmqkBtdmBrcYIk8DD7WqNTFb Rtv0ROWNJBNYXeDljBQq7Ti98Fwfv8P5AHE8+DFWGvOj+5d4IuuqS+kErDXt/tTAJP N4YBtja9AR6cIUpYenvCJLNT+pbEvvLu/kVGXBEry3YqlQIgBVmBOHLf1Sl5X3jLNW ouF88teIFJMZaC1EVOcE4CSGPPNxUyPI3xeyk/ehgr9nCHjVyMf5+Ebmk5mOXM1fMB S3MdPldemIzWw== From: Danilo Krummrich To: gregkh@linuxfoundation.org, rafael@kernel.org, acourbot@nvidia.com, aliceryhl@google.com, david.m.ertman@intel.com, ira.weiny@intel.com, leon@kernel.org, viresh.kumar@linaro.org, m.wilczynski@samsung.com, ukleinek@kernel.org, bhelgaas@google.com, kwilczynski@kernel.org, abdiel.janulgue@gmail.com, robin.murphy@arm.com, markus.probst@posteo.de, ojeda@kernel.org, boqun@kernel.org, gary@garyguo.net, bjorn3_gh@protonmail.com, lossin@kernel.org, a.hindborg@kernel.org, tmgross@umich.edu, igor.korotin@linux.dev, daniel.almeida@collabora.com, pcolberg@redhat.com Cc: driver-core@lists.linux.dev, linux-kernel@vger.kernel.org, nova-gpu@lists.linux.dev, dri-devel@lists.freedesktop.org, linux-pm@vger.kernel.org, linux-pwm@vger.kernel.org, linux-pci@vger.kernel.org, rust-for-linux@vger.kernel.org, Eliot Courtney , Danilo Krummrich Subject: [PATCH v5 22/24] rust: types: add `ForLt` trait for higher-ranked lifetime support Date: Mon, 25 May 2026 22:21:09 +0200 Message-ID: <20260525202921.124698-23-dakr@kernel.org> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260525202921.124698-1-dakr@kernel.org> References: <20260525202921.124698-1-dakr@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Gary Guo There are a few cases, e.g. when dealing with data referencing each other, one might want to write code that is generic over lifetimes. For example, if you want to take a function that takes `&'a Foo` and gives `Bar<'a>`, you can write: f: impl for<'a> FnOnce(&'a Foo) -> Bar<'a>, However, it becomes tricky when you want that function to not have a fixed `Bar`, but have it be generic again. In this case, one needs something that is generic over types that are themselves generic over lifetimes. `ForLt` provides such support. It provides a trait `ForLt` which describes a type generic over a lifetime. One may use `ForLt::Of<'a>` to get an instance of a type for a specific lifetime. For the case of cross referencing, one would almost always want the lifetime to be covariant. Therefore this is also made a requirement for the `ForLt` trait, so functions with `ForLt` trait bound can assume covariance. A macro `ForLt!()` is provided to be able to obtain a type that implements `ForLt`. For example, `ForLt!(for<'a> Bar<'a>)` would yield a type that `::Of<'a>` is `Bar<'a>`. This also works with lifetime elision, e.g. `ForLt!(Bar<'_>)` or for types without lifetime at all, e.g. `ForLt!(u32)`. The API design draws inspiration from the higher-kinded-types [1] crate, however a different design decision has been taken (e.g. covariance requirement) and the implementation is independent. License headers use "Apache-2.0 OR MIT" because I anticipate this to be used in pin-init crate too which is licensed as such. Link: https://docs.rs/higher-kinded-types/ [1] Reviewed-by: Greg Kroah-Hartman Reviewed-by: Eliot Courtney Signed-off-by: Gary Guo [ Handle macro_rules! invocations in the ForLt! proc macro's covariance and WF checks. Since proc macros cannot expand macro_rules!, add a visit_macro() implementation to conservatively assume macro invocations may contain lifetimes, forcing them through the compiler-assisted covariance proof. While at it, fix a few typos in the documentation and in the commit message. - Danilo ] Signed-off-by: Danilo Krummrich Acked-by: Miguel Ojeda Reviewed-by: Alexandre Courbot --- rust/Makefile | 1 + rust/kernel/types.rs | 4 + rust/kernel/types/for_lt.rs | 117 +++++++++++++++++ rust/macros/for_lt.rs | 248 ++++++++++++++++++++++++++++++++++++ rust/macros/lib.rs | 12 ++ 5 files changed, 382 insertions(+) create mode 100644 rust/kernel/types/for_lt.rs create mode 100644 rust/macros/for_lt.rs diff --git a/rust/Makefile b/rust/Makefile index b361bfedfdf0..c5a9a3339416 100644 --- a/rust/Makefile +++ b/rust/Makefile @@ -110,6 +110,7 @@ syn-cfgs :=3D \ feature=3D"parsing" \ feature=3D"printing" \ feature=3D"proc-macro" \ + feature=3D"visit" \ feature=3D"visit-mut" =20 syn-flags :=3D \ diff --git a/rust/kernel/types.rs b/rust/kernel/types.rs index 9cf9f869d195..ac316fd7b538 100644 --- a/rust/kernel/types.rs +++ b/rust/kernel/types.rs @@ -11,6 +11,10 @@ }; use pin_init::{PinInit, Wrapper, Zeroable}; =20 +#[doc(hidden)] +pub mod for_lt; +pub use for_lt::ForLt; + /// Used to transfer ownership to and from foreign (non-Rust) languages. /// /// Ownership is transferred from Rust to a foreign language by calling [`= Self::into_foreign`] and diff --git a/rust/kernel/types/for_lt.rs b/rust/kernel/types/for_lt.rs new file mode 100644 index 000000000000..a54acdbfb12b --- /dev/null +++ b/rust/kernel/types/for_lt.rs @@ -0,0 +1,117 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT + +//! Provide implementation and test of the `ForLt` trait and macro. +//! +//! This module is hidden and user should just use `ForLt!` directly. + +use core::marker::PhantomData; + +/// Representation of types generic over a lifetime. +/// +/// The type must be covariant over the generic lifetime, i.e. the lifetim= e parameter +/// can be soundly shortened. +/// +/// The lifetime involved must be covariant. +/// +/// # Macro +/// +/// It is not recommended to implement this trait directly. `ForLt!` macro= is provided to obtain a +/// type that implements this trait. +/// +/// The full syntax is +/// ``` +/// # use kernel::types::ForLt; +/// # fn expect_lt() {} +/// # struct TypeThatUse<'a>(&'a ()); +/// # expect_lt::< +/// ForLt!(for<'a> TypeThatUse<'a>) +/// # >(); +/// ``` +/// which gives a type so that ` TypeThatUse<'a>) as ForLt>= ::Of<'b>` +/// is `TypeThatUse<'b>`. +/// +/// You may also use a short-hand syntax which works similar to lifetime e= lision. +/// The macro also accepts types that do not involve a lifetime at all. +/// ``` +/// # use kernel::types::ForLt; +/// # fn expect_lt() {} +/// # struct TypeThatUse<'a>(&'a ()); +/// # expect_lt::< +/// ForLt!(TypeThatUse<'_>) // Equivalent to `ForLt!(for<'a> TypeThatUse<'= a>)` +/// # >(); +/// # expect_lt::< +/// ForLt!(&u32) // Equivalent to `ForLt!(for<'a> &'a u32)` +/// # >(); +/// # expect_lt::< +/// ForLt!(u32) // Equivalent to `ForLt!(for<'a> u32)` +/// # >(); +/// ``` +/// +/// The macro will attempt to prove that the type is indeed covariant over= the lifetime supplied. +/// When it cannot be syntactically proven, it will emit checks to ask the= Rust compiler to prove +/// it. +/// ```ignore,compile_fail +/// # use kernel::types::ForLt; +/// # fn expect_lt() {} +/// # expect_lt::< +/// ForLt!(fn(&u32)) // Contravariant, will fail compilation. +/// # >(); +/// ``` +/// +/// There is a limitation if the type refers to generic parameters; if the= macro cannot prove the +/// covariance syntactically, the emitted checks will fail the compilation= as it needs to refer to +/// the generic parameter but is in a separate item. +/// ``` +/// # use kernel::types::ForLt; +/// fn expect_lt() {} +/// # #[allow(clippy::unnecessary_safety_comment, reason =3D "false positi= ve")] +/// fn generic_fn() { +/// // Syntactically proven by the macro +/// expect_lt::(); +/// // Syntactically proven by the macro +/// expect_lt::)>(); +/// // Cannot be syntactically proven, need to check covariance of `KB= ox` +/// // expect_lt::)>(); +/// } +/// ``` +/// +/// # Safety +/// +/// `Self::Of<'a>` must be covariant over the lifetime `'a`. +pub unsafe trait ForLt { + /// The type parameterized by the lifetime. + type Of<'a>: 'a; + + /// Cast a reference to a shorter lifetime. + #[inline(always)] + fn cast_ref<'r, 'short: 'r, 'long: 'short>(long: &'r Self::Of<'long>) = -> &'r Self::Of<'short> { + // SAFETY: This is sound as this trait guarantees covariance. + unsafe { core::mem::transmute(long) } + } +} +pub use macros::ForLt; + +/// This is intended to be an "unsafe-to-refer-to" type. +/// +/// Must only be used by the `ForLt!` macro. +/// +/// `T` is the magic `dyn for<'a> WithLt<'a, TypeThatUse<'a>>` generated b= y macro. +/// +/// `WF` is a type that the macro can use to assert some specific type is = well-formed. +/// +/// `N` is to provide the macro a place to emit arbitrary items, in case i= t needs to prove +/// additional properties. +#[doc(hidden)] +pub struct UnsafeForLtImpl(PhantomData<(WF,= T)>); + +// This is a helper trait for implementation `ForLt` to be able to use HRT= B. +#[doc(hidden)] +pub trait WithLt<'a> { + type Of: 'a; +} + +// SAFETY: In `ForLt!` macro, a covariance proof is generated when naming = `UnsafeForLtImpl` +// and it will fail to evaluate if the type is not covariant. +unsafe impl WithLt<'a>, WF> ForLt for UnsafeForLtImpl<= T, WF, 0> { + type Of<'a> =3D >::Of; +} diff --git a/rust/macros/for_lt.rs b/rust/macros/for_lt.rs new file mode 100644 index 000000000000..75d0ce450bf0 --- /dev/null +++ b/rust/macros/for_lt.rs @@ -0,0 +1,248 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT + +use proc_macro2::{ + Span, + TokenStream, // +}; +use quote::{ + format_ident, + quote, // +}; +use syn::{ + parse::{ + Parse, + ParseStream, // + }, + visit::Visit, + visit_mut::VisitMut, + Lifetime, + Result, + Token, + Type, // +}; + +pub(crate) enum HigherRankedType { + Explicit { + _for_token: Token![for], + _lt_token: Token![<], + lifetime: Lifetime, + _gt_token: Token![>], + ty: Type, + }, + Implicit { + ty: Type, + }, +} + +impl Parse for HigherRankedType { + fn parse(input: ParseStream<'_>) -> Result { + if input.peek(Token![for]) { + Ok(Self::Explicit { + _for_token: input.parse()?, + _lt_token: input.parse()?, + lifetime: input.parse()?, + _gt_token: input.parse()?, + ty: input.parse()?, + }) + } else { + Ok(Self::Implicit { ty: input.parse()? }) + } + } +} + +trait TypeExt { + fn expand_elided_lifetime(&self, explicit_lt: &Lifetime) -> Type; + fn replace_lifetime(&self, src: &Lifetime, dst: &Lifetime) -> Type; + fn has_lifetime(&self, lt: &Lifetime) -> bool; +} + +impl TypeExt for Type { + fn expand_elided_lifetime(&self, explicit_lt: &Lifetime) -> Type { + struct ElidedLifetimeExpander<'a>(&'a Lifetime); + + impl VisitMut for ElidedLifetimeExpander<'_> { + fn visit_lifetime_mut(&mut self, lifetime: &mut Lifetime) { + // Expand explicit `'_` + if lifetime.ident =3D=3D "_" { + *lifetime =3D self.0.clone(); + } + } + + fn visit_type_reference_mut(&mut self, reference: &mut syn::Ty= peReference) { + syn::visit_mut::visit_type_reference_mut(self, reference); + + if reference.lifetime.is_none() { + reference.lifetime =3D Some(self.0.clone()); + } + } + } + + let mut ret =3D self.clone(); + ElidedLifetimeExpander(explicit_lt).visit_type_mut(&mut ret); + ret + } + + fn replace_lifetime(&self, src: &Lifetime, dst: &Lifetime) -> Type { + struct LifetimeReplacer<'a>(&'a Lifetime, &'a Lifetime); + + impl VisitMut for LifetimeReplacer<'_> { + fn visit_lifetime_mut(&mut self, lifetime: &mut Lifetime) { + if lifetime.ident =3D=3D self.0.ident { + *lifetime =3D self.1.clone(); + } + } + } + + let mut ret =3D self.clone(); + LifetimeReplacer(src, dst).visit_type_mut(&mut ret); + ret + } + + fn has_lifetime(&self, lt: &Lifetime) -> bool { + struct HasLifetime<'a>(&'a Lifetime, bool); + + impl Visit<'_> for HasLifetime<'_> { + fn visit_lifetime(&mut self, lifetime: &Lifetime) { + if lifetime.ident =3D=3D self.0.ident { + self.1 =3D true; + } + } + + // Macro invocations are opaque; conservatively assume they may + // reference the lifetime. + fn visit_macro(&mut self, _: &syn::Macro) { + self.1 =3D true; + } + } + + let mut visitor =3D HasLifetime(lt, false); + visitor.visit_type(self); + visitor.1 + } +} + +struct Prover<'a>(&'a Lifetime, Vec<&'a Type>); + +impl<'a> Prover<'a> { + /// Prove that `ty` is covariant over `'lt`. + /// + /// This also needs to prove that it'll be wellformed for any instance= of `'lt`. + /// It can be assumed that `ty` will be wellformed if `'lt` is substit= uted to `'static`. + fn prove(&mut self, ty: &'a Type) { + match ty { + Type::Paren(ty) =3D> self.prove(&ty.elem), + Type::Group(ty) =3D> self.prove(&ty.elem), + + // No lifetime involved + Type::Never(_) =3D> {} + + // `[T; N]` and `[T]` is covariant over `T`. + Type::Array(ty) =3D> self.prove(&ty.elem), + Type::Slice(ty) =3D> self.prove(&ty.elem), + + Type::Tuple(ty) =3D> { + for elem in &ty.elems { + self.prove(elem); + } + } + + // `*const T` is covariant over `T` + Type::Ptr(ty) if ty.const_token.is_some() =3D> self.prove(&ty.= elem), + + // `&T` is covariant over `T` and lifetime. + // + // Note that if we encounter `&'other_lt T`, then we still nee= d to make sure the type + // is wellformed if `T` involves `&'lt`, so we defer to the co= mpiler. + // + // This is to block cases like `ForLt!(for<'a> &'static &'a u3= 2)`, as the presence of + // the type implies `'a: 'static` but this is unsound. + Type::Reference(ty) + if ty.mutability.is_none() && ty.lifetime.as_ref() =3D=3D = Some(self.0) =3D> + { + self.prove(&ty.elem) + } + + // `&[mut] T` is covariant over lifetime. + // In case we have `&[mut] NoLifetime`, we don't need to do ad= ditional checks. + Type::Reference(ty) if !ty.elem.has_lifetime(self.0) =3D> (), + + // No mention of lifetime at all, no need to perform compiler = check. + ty if !ty.has_lifetime(self.0) =3D> (), + + // Otherwise, we need to emit checks so that compiler can dete= rmine if the types are + // actually covariant. + ty =3D> self.1.push(ty), + } + } +} + +pub(crate) fn for_lt(input: HigherRankedType) -> TokenStream { + let (ty, lifetime) =3D match input { + HigherRankedType::Explicit { lifetime, ty, .. } =3D> (ty, lifetime= ), + HigherRankedType::Implicit { ty } =3D> { + // If there's no explicit `for<'a>` binder, inject a synthetic= `'__elided` lifetime + // and expand elided sites. + let lifetime =3D Lifetime { + apostrophe: Span::mixed_site(), + ident: format_ident!("__elided", span =3D Span::mixed_site= ()), + }; + (ty.expand_elided_lifetime(&lifetime), lifetime) + } + }; + + let mut prover =3D Prover(&lifetime, Vec::new()); + prover.prove(&ty); + + let mut proof =3D Vec::new(); + + // Emit proofs for every type that requires additional compiler help i= n proving covariance. + for (idx, required_proof) in prover.1.into_iter().enumerate() { + // Insert a proof that the type is well-formed. + // + // This is intended to workaround a Rust compiler soundness bug re= lated to HRTB. + // https://github.com/rust-lang/rust/issues/152489 + // + // This needs to be a struct instead of fn to avoid the implied WF= bounds. + let wf_proof_name =3D format_ident!("ProveWf{idx}"); + proof.push(quote!( + struct #wf_proof_name<#lifetime>( + ::core::marker::PhantomData<&#lifetime ()>, #required_proof + ); + )); + + // Insert a proof that the type is covariant. + let cov_proof_name =3D format_ident!("prove_covariant_{idx}"); + proof.push(quote!( + fn #cov_proof_name<'__short, '__long: '__short>( + long: #wf_proof_name<'__long> + ) -> #wf_proof_name<'__short> { + long + } + )); + } + + // Make sure that the type is wellformed when substituting lifetime wi= th `'static`. + // + // Currently the Rust compiler doesn't check this, see the above Prove= Wf documentation. + // + // We prefer to use this way of proving WF-ness as it can work when ge= nerics are involved. + let ty_static =3D ty.replace_lifetime( + &lifetime, + &Lifetime { + apostrophe: Span::mixed_site(), + ident: format_ident!("static"), + }, + ); + + quote!( + ::kernel::types::for_lt::UnsafeForLtImpl::< + dyn for<#lifetime> ::kernel::types::for_lt::WithLt<#lifetime, = Of =3D #ty>, + #ty_static, + { + #(#proof)* + + 0 + } + > + ) +} diff --git a/rust/macros/lib.rs b/rust/macros/lib.rs index 2cfd59e0f9e7..e5f6f8318112 100644 --- a/rust/macros/lib.rs +++ b/rust/macros/lib.rs @@ -17,6 +17,7 @@ mod concat_idents; mod export; mod fmt; +mod for_lt; mod helpers; mod kunit; mod module; @@ -489,3 +490,14 @@ pub fn kunit_tests(attr: TokenStream, input: TokenStre= am) -> TokenStream { .unwrap_or_else(|e| e.into_compile_error()) .into() } + +/// Obtain a type that implements `ForLt` for the given higher-ranked type. +/// +/// Please refer to the documentation of [`ForLt`] trait. +/// +/// [`ForLt`]: trait.ForLt.html +#[proc_macro] +#[allow(non_snake_case)] // The macro shares the name with the trait. +pub fn ForLt(input: TokenStream) -> TokenStream { + for_lt::for_lt(parse_macro_input!(input)).into() +} --=20 2.54.0 From nobody Mon Jun 8 22:51:08 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 07ED03AD52E; Mon, 25 May 2026 20:32:16 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779741139; cv=none; b=Tv8NXe/y0gAPwBOzdij1Yhk3JEDArXL4nJsyV5I73SKluEGMvMN61Wd6UasEzs+oa7yFNtkxwqCSgRE8RR01AY2s/thy0cv6ge0kJdBJFdDn4B4NBrKVDS3N+2PMpp985ZS+GCW5t4TWy0l773PfiMPukaL2S/BhpdrxvYfER0g= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779741139; c=relaxed/simple; bh=4DHQw9eKOJiPSF0yo6o6S+FEkFSRtACLgacvFmGr/OU=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=EL+vzjnza5AwYgtIXcSNWMjdoc/k8FmSzkeoShcuVylVzeITYScO2q9OP9pmgT/dNuN3jLalpcrKBW0nXNbTMzGjkBF6uhYxFKghq6kOkQFtKcUZjRsv/k3HuCBPlDkOahUU6kJphOTcnXI9docqClLXkdaKvJDDPTVqXUFReHg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=YMWblnp9; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="YMWblnp9" Received: by smtp.kernel.org (Postfix) with ESMTPSA id CE3731F00A3C; Mon, 25 May 2026 20:32:09 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1779741136; bh=VlEFGAzw+HUYppR1B8Mu1locJbyWufzNCgGKfk+h2vA=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=YMWblnp9Hf07OuhKdAsN4znef0aXSHAyDlnUxBDP4HyFIoim2Xep6kUHK9w9BlE9v cCgo1RKqi+dY0zW+s2PzVY00LtG2lqeUQrUMgimS2ebIbQz74KI8bfoXRY1Qbw9qWx 7x9r8lQJkfu1CMpa/rsCrjkmbasbjWXqRg2md3Ur7M3f7VGo90flssuxW1kc4MACjP 63hJidMnB9rQBjykWkvqR/wDrSQkcnKJRzFGiHm238fZicQGlKWf1CS8+nRo/hcbvd lzYiYOsiGJja7dGd/+WWahJU+0c1nC1eBjXq9oJvCqTIfFQb/lkZSi387r96a3vcyv iPSnvdWT7cNKQ== From: Danilo Krummrich To: gregkh@linuxfoundation.org, rafael@kernel.org, acourbot@nvidia.com, aliceryhl@google.com, david.m.ertman@intel.com, ira.weiny@intel.com, leon@kernel.org, viresh.kumar@linaro.org, m.wilczynski@samsung.com, ukleinek@kernel.org, bhelgaas@google.com, kwilczynski@kernel.org, abdiel.janulgue@gmail.com, robin.murphy@arm.com, markus.probst@posteo.de, ojeda@kernel.org, boqun@kernel.org, gary@garyguo.net, bjorn3_gh@protonmail.com, lossin@kernel.org, a.hindborg@kernel.org, tmgross@umich.edu, igor.korotin@linux.dev, daniel.almeida@collabora.com, pcolberg@redhat.com Cc: driver-core@lists.linux.dev, linux-kernel@vger.kernel.org, nova-gpu@lists.linux.dev, dri-devel@lists.freedesktop.org, linux-pm@vger.kernel.org, linux-pwm@vger.kernel.org, linux-pci@vger.kernel.org, rust-for-linux@vger.kernel.org, Danilo Krummrich , Eliot Courtney Subject: [PATCH v5 23/24] rust: auxiliary: generalize Registration over ForLt Date: Mon, 25 May 2026 22:21:10 +0200 Message-ID: <20260525202921.124698-24-dakr@kernel.org> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260525202921.124698-1-dakr@kernel.org> References: <20260525202921.124698-1-dakr@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Generalize Registration to Registration and Device::registration_data() to return Pin<&F::Of<'_>>. The stored 'static lifetime is shortened to the borrow lifetime of &self via ForLt::cast_ref; ForLt's covariance guarantee makes this sound. Reviewed-by: Greg Kroah-Hartman Reviewed-by: Alexandre Courbot Reviewed-by: Eliot Courtney Signed-off-by: Danilo Krummrich --- drivers/gpu/nova-core/driver.rs | 13 ++-- rust/kernel/auxiliary.rs | 108 +++++++++++++++++++------- samples/rust/rust_driver_auxiliary.rs | 19 +++-- 3 files changed, 96 insertions(+), 44 deletions(-) diff --git a/drivers/gpu/nova-core/driver.rs b/drivers/gpu/nova-core/driver= .rs index fa898fe5c893..d3f2245ba2e0 100644 --- a/drivers/gpu/nova-core/driver.rs +++ b/drivers/gpu/nova-core/driver.rs @@ -3,7 +3,6 @@ use kernel::{ auxiliary, device::Core, - devres::Devres, dma::Device, dma::DmaMask, pci, @@ -21,6 +20,7 @@ }, Arc, }, + types::ForLt, }; =20 use crate::gpu::Gpu; @@ -29,10 +29,11 @@ static AUXILIARY_ID_COUNTER: Atomic =3D Atomic::new(0); =20 #[pin_data] -pub(crate) struct NovaCore { +pub(crate) struct NovaCore<'bound> { #[pin] pub(crate) gpu: Gpu, - _reg: Devres>, + #[allow(clippy::type_complexity)] + _reg: auxiliary::Registration<'bound, ForLt!(())>, } =20 pub(crate) struct NovaCoreDriver; @@ -76,13 +77,13 @@ pub(crate) struct NovaCore { =20 impl pci::Driver for NovaCoreDriver { type IdInfo =3D (); - type Data<'bound> =3D NovaCore; + type Data<'bound> =3D NovaCore<'bound>; const ID_TABLE: pci::IdTable =3D &PCI_TABLE; =20 fn probe<'bound>( pdev: &'bound pci::Device>, _info: &'bound Self::IdInfo, - ) -> impl PinInit + 'bound { + ) -> impl PinInit, Error> + 'bound { pin_init::pin_init_scope(move || { dev_dbg!(pdev, "Probe Nova Core GPU driver.\n"); =20 @@ -115,7 +116,7 @@ fn probe<'bound>( }) } =20 - fn unbind<'bound>(pdev: &'bound pci::Device>, this: Pin<&Nova= Core>) { + fn unbind<'bound>(pdev: &'bound pci::Device>, this: Pin<&Self= ::Data<'bound>>) { this.gpu.unbind(pdev.as_ref()); } } diff --git a/rust/kernel/auxiliary.rs b/rust/kernel/auxiliary.rs index 7a1b1a7b7ca6..75ddb0220748 100644 --- a/rust/kernel/auxiliary.rs +++ b/rust/kernel/auxiliary.rs @@ -12,7 +12,7 @@ RawDeviceId, RawDeviceIdIndex, // }, - devres::Devres, + driver, error::{ from_result, @@ -20,6 +20,7 @@ }, prelude::*, types::{ + ForLt, ForeignOwnable, Opaque, // }, @@ -271,12 +272,16 @@ pub fn parent(&self) -> &device::Device { =20 /// Returns a pinned reference to the registration data set by the reg= istering (parent) driver. /// - /// Returns [`EINVAL`] if `T` does not match the type used by the pare= nt driver when calling + /// `F` is the [`ForLt`](trait@ForLt) encoding of the data type. The r= eturned + /// reference has its lifetime shortened from `'static` to `&self`'s b= orrow lifetime via + /// [`ForLt::cast_ref`]. + /// + /// Returns [`EINVAL`] if `F` does not match the type used by the pare= nt driver when calling /// [`Registration::new()`]. /// /// Returns [`ENOENT`] if no registration data has been set, e.g. when= the device was /// registered by a C driver. - pub fn registration_data(&self) -> Result> { + pub fn registration_data(&self) -> Result>> { // SAFETY: By the type invariant, `self.as_raw()` is a valid `stru= ct auxiliary_device`. let ptr =3D unsafe { (*self.as_raw()).registration_data_rust }; if ptr.is_null() { @@ -289,18 +294,23 @@ pub fn registration_data(&self) -> Result= > { =20 // SAFETY: `ptr` is non-null and was set via `into_foreign()` in `= Registration::new()`; // `RegistrationData` is `#[repr(C)]` with `type_id` at offset 0, = so reading a `TypeId` - // at the start of the allocation is valid regardless of `T`. + // at the start of the allocation is valid regardless of `F`. let type_id =3D unsafe { ptr.cast::().read() }; - if type_id !=3D TypeId::of::() { + if type_id !=3D TypeId::of::() { return Err(EINVAL); } =20 - // SAFETY: The `TypeId` check above confirms that the stored type = is `T`; `ptr` remains - // valid until `Registration::drop()` calls `from_foreign()`. - let wrapper =3D unsafe { Pin::>>::borrow(= ptr) }; + // SAFETY: The `TypeId` check above confirms that the stored type = matches + // `F::Of<'static>`; `ptr` remains valid until `Registration::drop= ()` calls + // `from_foreign()`. + let wrapper =3D unsafe { Pin::>>>::borrow(ptr) }; =20 // SAFETY: `data` is a structurally pinned field of `RegistrationD= ata`. - Ok(unsafe { wrapper.map_unchecked(|w| &w.data) }) + let pinned: Pin<&F::Of<'static>> =3D unsafe { wrapper.map_unchecke= d(|w| &w.data) }; + + // SAFETY: The data was pinned when stored; `cast_ref` only shorte= ns + // the lifetime, so the pinning guarantee is preserved. + Ok(unsafe { Pin::new_unchecked(F::cast_ref(pinned.get_ref())) }) } } =20 @@ -389,43 +399,61 @@ struct RegistrationData { /// This type represents the registration of a [`struct auxiliary_device`]= . When its parent device /// is unbound, the corresponding auxiliary device will be unregistered fr= om the system. /// -/// The type parameter `T` is the type of the registration data owned by t= he registering (parent) -/// driver. It can be accessed by the auxiliary driver through -/// [`Device::registration_data()`]. +/// The type parameter `F` is a [`ForLt`](trait@ForLt) encoding of the reg= istration +/// data type. For non-lifetime-parameterized types, use [`ForLt!(T)`](mac= ro@ForLt). +/// The data can be accessed by the auxiliary driver through [`Device::reg= istration_data()`]. /// /// # Invariants /// /// `self.adev` always holds a valid pointer to an initialized and registe= red /// [`struct auxiliary_device`] whose `registration_data_rust` field point= s to a -/// valid `Pin>>`. -pub struct Registration { +/// valid `Pin>>>`. +pub struct Registration<'a, F: ForLt + 'static> { adev: NonNull, - _data: PhantomData, + #[allow(clippy::type_complexity)] + _phantom: PhantomData<(fn(&'a ()) -> &'a (), F)>, } =20 -impl Registration { +impl<'a, F: ForLt> Registration<'a, F> +where + for<'b> F::Of<'b>: Send + Sync, +{ /// Create and register a new auxiliary device with the given registra= tion data. /// /// The `data` is owned by the registration and can be accessed throug= h the auxiliary device /// via [`Device::registration_data()`]. - pub fn new( - parent: &device::Device, + /// + /// # Safety + /// + /// The caller must not `mem::forget()` the returned [`Registration`] = or otherwise prevent its + /// [`Drop`] implementation from running, since the registration data = may contain borrowed + /// references that become invalid after `'a` ends. + /// + /// If the registration data is `'static`, use the safe [`Registration= ::new()`] instead. + pub unsafe fn new_with_lt( + parent: &'a device::Device, name: &CStr, id: u32, modname: &CStr, - data: impl PinInit, - ) -> Result> + data: impl PinInit, E>, + ) -> Result where Error: From, { let data =3D KBox::pin_init::( try_pin_init!(RegistrationData { - type_id: TypeId::of::(), + type_id: TypeId::of::(), data <- data, }), GFP_KERNEL, )?; =20 + // SAFETY: `'a` is invariant (via `Registration`'s `PhantomData`).= Lifetimes do not + // affect layout, so RegistrationData> and RegistrationD= ata> + // have identical representation. + let data: Pin>>> =3D + unsafe { core::mem::transmute(data) }; + let boxed: KBox> =3D KBox::zero= ed(GFP_KERNEL)?; let adev =3D boxed.get(); =20 @@ -455,7 +483,9 @@ pub fn new( if ret !=3D 0 { // SAFETY: `registration_data` was set above via `into_foreign= ()`. drop(unsafe { - Pin::>>::from_foreign((*adev).reg= istration_data_rust) + Pin::>>>::from_foreig= n( + (*adev).registration_data_rust, + ) }); =20 // SAFETY: `adev` is guaranteed to be a valid pointer to a @@ -467,18 +497,36 @@ pub fn new( =20 // INVARIANT: The device will remain registered until `auxiliary_d= evice_delete()` is // called, which happens in `Self::drop()`. - let reg =3D Self { + Ok(Self { // SAFETY: `adev` is guaranteed to be non-null, since the `KBo= x` was allocated // successfully. adev: unsafe { NonNull::new_unchecked(adev) }, - _data: PhantomData, - }; + _phantom: PhantomData, + }) + } =20 - Devres::new::(parent, reg) + /// Create and register a new auxiliary device with `'static` registra= tion data. + /// + /// Safe variant of [`Registration::new_with_lt()`] for registration d= ata that does not contain + /// borrowed references. + pub fn new( + parent: &'a device::Device, + name: &CStr, + id: u32, + modname: &CStr, + data: impl PinInit, E>, + ) -> Result + where + F::Of<'a>: 'static, + Error: From, + { + // SAFETY: `F::Of<'a>: 'static` guarantees the data contains no bo= rrowed references, + // so forgetting the `Registration` cannot cause use-after-free. + unsafe { Self::new_with_lt(parent, name, id, modname, data) } } } =20 -impl Drop for Registration { +impl Drop for Registration<'_, F> { fn drop(&mut self) { // SAFETY: By the type invariant of `Self`, `self.adev.as_ptr()` i= s a valid registered // `struct auxiliary_device`. @@ -486,7 +534,7 @@ fn drop(&mut self) { =20 // SAFETY: `registration_data` was set in `new()` via `into_foreig= n()`. drop(unsafe { - Pin::>>::from_foreign( + Pin::>>>::from_foreign( (*self.adev.as_ptr()).registration_data_rust, ) }); @@ -500,7 +548,7 @@ fn drop(&mut self) { } =20 // SAFETY: A `Registration` of a `struct auxiliary_device` can be released= from any thread. -unsafe impl Send for Registration {} +unsafe impl Send for Registration<'_, F> where for<'a> F::Of<'a>= : Send {} =20 // SAFETY: `Registration` does not expose any methods or fields that need = synchronization. -unsafe impl Sync for Registration {} +unsafe impl Sync for Registration<'_, F> where for<'a> F::Of<'a>= : Send {} diff --git a/samples/rust/rust_driver_auxiliary.rs b/samples/rust/rust_driv= er_auxiliary.rs index b30a4d5cdf8a..e3e811a14110 100644 --- a/samples/rust/rust_driver_auxiliary.rs +++ b/samples/rust/rust_driver_auxiliary.rs @@ -10,10 +10,10 @@ Bound, Core, // }, - devres::Devres, driver, pci, prelude::*, + types::ForLt, InPlaceModule, // }; =20 @@ -55,9 +55,12 @@ struct Data { index: u32, } =20 -struct ParentDriver { - _reg0: Devres>, - _reg1: Devres>, +struct ParentDriver; + +#[allow(clippy::type_complexity)] +struct ParentData<'bound> { + _reg0: auxiliary::Registration<'bound, ForLt!(Data)>, + _reg1: auxiliary::Registration<'bound, ForLt!(Data)>, } =20 kernel::pci_device_table!( @@ -69,15 +72,15 @@ struct ParentDriver { =20 impl pci::Driver for ParentDriver { type IdInfo =3D (); - type Data<'bound> =3D Self; + type Data<'bound> =3D ParentData<'bound>; =20 const ID_TABLE: pci::IdTable =3D &PCI_TABLE; =20 fn probe<'bound>( pdev: &'bound pci::Device>, _info: &'bound Self::IdInfo, - ) -> impl PinInit + 'bound { - Ok(Self { + ) -> impl PinInit, Error> + 'bound { + Ok(ParentData { _reg0: auxiliary::Registration::new( pdev.as_ref(), AUXILIARY_NAME, @@ -101,7 +104,7 @@ fn connect(adev: &auxiliary::Device) -> Result { let dev =3D adev.parent(); let pdev: &pci::Device =3D dev.try_into()?; =20 - let data =3D adev.registration_data::()?; + let data =3D adev.registration_data::()?; =20 dev_info!( dev, --=20 2.54.0 From nobody Mon Jun 8 22:51:08 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 76FD2388363; Mon, 25 May 2026 20:32:24 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779741145; cv=none; b=cNgld8Zjrqv00uy3tbspT9WeUlzO3liyLSo9ihkzcl91sGrKaGRbSOXdu/lPE36zffMeIlh7YKXKlFH9/LUZwqOK19ViPu9Kro542hbCYNlS+arzaSbnQLO/mPHuqyjFmmI4Mj+/XOx/UvSJWssMS5ZD7smiSNdRcj4CQuRFIrE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779741145; c=relaxed/simple; bh=n9OSdO3AwMmlBW0KtaOxaurI9/V+4mxLjp0ERUUz9nQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=AGR6gBjiieySNa93kFsAp/QlF3o23HYyHiqscYzw72pVc28tn5N1W16i84hwNZY8ANwsTAt2aVmqwX2Sfp7T2LFzHInxWdcqzz5BQubJBIv1FuscIWNCqPz3lhvRzy1AuasYhVtjihPRkKoCK/LhkzDRz5rKpGQIPsC3cOTcfck= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=E5Z15P9j; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="E5Z15P9j" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 269F31F000E9; Mon, 25 May 2026 20:32:16 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1779741144; bh=+rPmKZf6uaQzYhVqY2DDZC+3sDd3VtNWS1o0vbSmOWw=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=E5Z15P9jRyUCpIVYHnJfOk9/D8atKgXHRLvLuzY1yly8rDaOEcFJr6aenLpt9wHkp /w1H2/iDK/CnanATE6FZIVUJjMGIiJaMeujyma+KBb5394RaHkIALs2YfTi5S4eZQZ IVmrNIqu0IQYPP5bqkgyH5stRJqYoDMAzQb4A9Jkw2dJoegGPX1CSsF+cCMMZ56PG7 QR0c7fRMSXTWyNelz2+V3zbiV6ZLXRloDG7wZ48WsDWNiMGDkVK6VBjERevJDCeaeI GohDsI7+lvwSPSkn9t8Cud0GrpoCkF8iQUbbZLpfaCFu+vtTFo/qYNVAEJKeNpHz2x UHOVDH2VZAwEg== From: Danilo Krummrich To: gregkh@linuxfoundation.org, rafael@kernel.org, acourbot@nvidia.com, aliceryhl@google.com, david.m.ertman@intel.com, ira.weiny@intel.com, leon@kernel.org, viresh.kumar@linaro.org, m.wilczynski@samsung.com, ukleinek@kernel.org, bhelgaas@google.com, kwilczynski@kernel.org, abdiel.janulgue@gmail.com, robin.murphy@arm.com, markus.probst@posteo.de, ojeda@kernel.org, boqun@kernel.org, gary@garyguo.net, bjorn3_gh@protonmail.com, lossin@kernel.org, a.hindborg@kernel.org, tmgross@umich.edu, igor.korotin@linux.dev, daniel.almeida@collabora.com, pcolberg@redhat.com Cc: driver-core@lists.linux.dev, linux-kernel@vger.kernel.org, nova-gpu@lists.linux.dev, dri-devel@lists.freedesktop.org, linux-pm@vger.kernel.org, linux-pwm@vger.kernel.org, linux-pci@vger.kernel.org, rust-for-linux@vger.kernel.org, Danilo Krummrich , Eliot Courtney Subject: [PATCH v5 24/24] samples: rust: rust_driver_auxiliary: showcase lifetime-bound registration data Date: Mon, 25 May 2026 22:21:11 +0200 Message-ID: <20260525202921.124698-25-dakr@kernel.org> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260525202921.124698-1-dakr@kernel.org> References: <20260525202921.124698-1-dakr@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Make the Data struct lifetime-parameterized, storing a reference to the parent pci::Device. This demonstrates that registration data can hold device resources tied to the parent driver's lifetime. In connect(), retrieve the parent PCI device from the registration data rather than casting through adev.parent(). Reviewed-by: Eliot Courtney Reviewed-by: Gary Guo Reviewed-by: Greg Kroah-Hartman Reviewed-by: Alexandre Courbot Signed-off-by: Danilo Krummrich --- samples/rust/rust_driver_auxiliary.rs | 58 ++++++++++++++++----------- 1 file changed, 35 insertions(+), 23 deletions(-) diff --git a/samples/rust/rust_driver_auxiliary.rs b/samples/rust/rust_driv= er_auxiliary.rs index e3e811a14110..2c1351040e45 100644 --- a/samples/rust/rust_driver_auxiliary.rs +++ b/samples/rust/rust_driver_auxiliary.rs @@ -51,16 +51,17 @@ fn probe<'bound>( } } =20 -struct Data { +struct Data<'bound> { index: u32, + parent: &'bound pci::Device, } =20 struct ParentDriver; =20 #[allow(clippy::type_complexity)] struct ParentData<'bound> { - _reg0: auxiliary::Registration<'bound, ForLt!(Data)>, - _reg1: auxiliary::Registration<'bound, ForLt!(Data)>, + _reg0: auxiliary::Registration<'bound, ForLt!(Data<'_>)>, + _reg1: auxiliary::Registration<'bound, ForLt!(Data<'_>)>, } =20 kernel::pci_device_table!( @@ -81,33 +82,44 @@ fn probe<'bound>( _info: &'bound Self::IdInfo, ) -> impl PinInit, Error> + 'bound { Ok(ParentData { - _reg0: auxiliary::Registration::new( - pdev.as_ref(), - AUXILIARY_NAME, - 0, - MODULE_NAME, - Data { index: 0 }, - )?, - _reg1: auxiliary::Registration::new( - pdev.as_ref(), - AUXILIARY_NAME, - 1, - MODULE_NAME, - Data { index: 1 }, - )?, + // SAFETY: `ParentData` is the driver's private data, which is= dropped when the + // device is unbound; i.e. `mem::forget()` is never called on = it. + _reg0: unsafe { + auxiliary::Registration::new_with_lt( + pdev.as_ref(), + AUXILIARY_NAME, + 0, + MODULE_NAME, + Data { + index: 0, + parent: pdev, + }, + )? + }, + // SAFETY: See `_reg0` above. + _reg1: unsafe { + auxiliary::Registration::new_with_lt( + pdev.as_ref(), + AUXILIARY_NAME, + 1, + MODULE_NAME, + Data { + index: 1, + parent: pdev, + }, + )? + }, }) } } =20 impl ParentDriver { fn connect(adev: &auxiliary::Device) -> Result { - let dev =3D adev.parent(); - let pdev: &pci::Device =3D dev.try_into()?; - - let data =3D adev.registration_data::()?; + let data =3D adev.registration_data::)>()?; + let pdev =3D data.parent; =20 dev_info!( - dev, + pdev, "Connect auxiliary {} with parent: VendorID=3D{}, DeviceID=3D{= :#x}\n", adev.id(), pdev.vendor_id(), @@ -115,7 +127,7 @@ fn connect(adev: &auxiliary::Device) -> Result { ); =20 dev_info!( - dev, + pdev, "Connected to auxiliary device with index {}.\n", data.index ); --=20 2.54.0