From nobody Sun May 24 19:33:20 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 E5A8731F98E; Thu, 21 May 2026 23:39:26 +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=1779406768; cv=none; b=GRrmVBKTTBYeqH67otHOBWiYaFfhgppfdr/n1zEQvMQc83mbwKRR/lOs7Ubzja3INDEyRTCxnS2PHEbuLyjjMVcPPOhQQb4DNiHNWZy9/nGt45OROV4SsK+Ks8unbiZHsXGWNxzep9Y7UwkdE8wTeU6K7Xja6Oi0ExlkL83VeIM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779406768; c=relaxed/simple; bh=x3dZFMUUtuu6ylR0hw38q6QBb93LtOcHpn8biD5uuVk=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=KLOirMJYsQp969zB6/LOhhMDjiOTLMLXcWY4LvCA2xjhUdoFbX1uq+fDN1idpInK9y3BWPci98Hy1ld60CjEVnnZ0UsH39btt3i50jRg404i/iTeS0JbPCtHpJBXuON199+NdkB7QdZQeFkCdNspmdpxE4rtmDPXctu2/x1+oDo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=NaPJnacM; 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="NaPJnacM" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 2B7341F00A3B; Thu, 21 May 2026 23:39:20 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1779406766; bh=ijMJWtwRHur6EZev09qU6JpbliROeigizWCF7odkHNY=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=NaPJnacMvbtT9B3VgmxVX6ENRoNeBTGOAI/2DA7+M7cjr52RbwBRR5VKw+DglxgL8 +cpsQafoQbKfoPHIOg05XHrA3fAKP730W6xoiiX4h+B9/Jy60MXYHkAMRPuO1r0owq fSUNhiU8D4LBVks6kD31yF63wLlUXK+BIx3r+Mf+g6N4NjOn3UKCn4eT+ORA0+cPJ4 5HeV42MOf9g+cYlY6xRbT7+WMyDEjSYKb1KcJAUmYOxw/vCvdHZ6v+az/oL6Qj/vZJ 8emOPqhe40vTi0bVXZyIk7MsziizylOXqssSAHZdMffPiCOjH6BFCBima3vBaInTQ+ Sy3Dgs4x96Bmg== 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 v4 01/27] rust: alloc: remove `'static` bound on `ForeignOwnable` Date: Fri, 22 May 2026 01:34:27 +0200 Message-ID: <20260521233501.1191842-2-dakr@kernel.org> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260521233501.1191842-1-dakr@kernel.org> References: <20260521233501.1191842-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 Signed-off-by: Gary Guo Signed-off-by: Danilo Krummrich Reviewed-by: Greg Kroah-Hartman --- 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 Sun May 24 19:33:20 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 B2A94365A13; Thu, 21 May 2026 23:39:33 +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=1779406775; cv=none; b=Ay0oescWgcLhYj/QDTTvibxCiqUq2eX+uDA/zecQLm6DIYtfi9dn+t4b+EROxhRn1sBzuzHm3nhRw0gok5PUxh/hVHCWuE11uqBy3FYczIREJpqJCnLY3kIskG34sTkbD1n6vSzDs0V1cWlghbvkcxFm16Dz9iKNPE4z0TBEVfk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779406775; c=relaxed/simple; bh=bt3SId9ZCYtgEGXJDVZR+Nta3u//CSeobMyGWFsPtWI=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=u2HyU6YIwTIxrLe5vopyKRMfL5Mdo4P56O6mluZYowSlsR3NTB5IdOMjErmA8jEvh1GWIg9rsxdPfbwqv0W0tmPLQwoUclT9Kt1u35khwIE3vhwYJPiNNbvz5sTSjQx+Tfi3ORt1WpcbI3rdouxsPXixn4A6MM2JpVsJg/F7ELk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=QeXhqMf3; 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="QeXhqMf3" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 00C381F000E9; Thu, 21 May 2026 23:39:26 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1779406773; bh=oAC+oYVs4iVm2wJeSIDjCP5mSv0R6QMsV4IYq1BN6aM=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=QeXhqMf3FETATNckDpEiMHVSUfQgJTxpgJuzaNiTsLPFfyP5PxKAZcaPkunSGCOOo pQZTRyXQGSUPCIlJKvRPq/hQgzE7wa1LOTVOkRDM/Tv6jb06g7qJeMOkiK9SBiSSYv mT+nxlGrSUSKBbcYwkRfiI3BUU+MfMP359BG0O390xXvTPIm7jl3wBSW15uE9f7Kfn nm4LAJTqGwDmEIzRkr64bKcEJGf98iOnFSOK2PjWaQM23rjYh65P1+u2OCKp2H8XDh zGcaoU3dOlzoQVyU+mjV4a+di2JvW11NtlL8SLG7KYfbVDnPclrXwEVuBgaD4n7fzp r45bD5TGt55BA== 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 v4 02/27] rust: driver: move 'static bounds to constructor Date: Fri, 22 May 2026 01:34:28 +0200 Message-ID: <20260521233501.1191842-3-dakr@kernel.org> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260521233501.1191842-1-dakr@kernel.org> References: <20260521233501.1191842-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 Signed-off-by: Gary Guo Co-developed-by: Danilo Krummrich Signed-off-by: Danilo Krummrich Reviewed-by: Greg Kroah-Hartman --- 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 93e5dd6ae371..586091cfa45c 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 Sun May 24 19:33:20 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 7F29F265623; Thu, 21 May 2026 23:39: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=1779406783; cv=none; b=SapAdlAmaDB/iBixZxdyCnot1GKR8aqsHZqboT0cWP//m2Sk9A7RlP6j5rF/qaZ7Z4c5+RATmGILOJc5oAvpF5TRaTSqqJgpaLBtlcE7d9Hy6204E5Tv/RJbQZRrm4+nMgr1hj0I6RSz52thX+CxDsQWgfxrduuuBzZYODfMFT4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779406783; c=relaxed/simple; bh=puW7qRfP71gKmNTdJJF98av0Y+daksKDuQfjSU0iUTE=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Dnfwl7YsduK6ApOWQjHdRtQlAhHn1Rju4vv3XvwpKSE5g/z6OOORCk8rvv/2CMY2sWgSH9zw3jXTUYxVGy89wBs3Ln+rZUlIuN17Vd52lwCSPU6qQJZUwSQhytwJ8et4SgYX0q49b15ASBMDJ4tQskfKt49AU76wjKW03VoQe48= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=iZXBtUNZ; 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="iZXBtUNZ" Received: by smtp.kernel.org (Postfix) with ESMTPSA id CDA3B1F00A3B; Thu, 21 May 2026 23:39:33 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1779406780; bh=ZOcSgfBjmv79LogDWRgIiXuFb+vqErBdbY05BQCG5nI=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=iZXBtUNZ6bwptFvwIBZSsynJ0EoCRPVCA0nLT4Sc07jObNAds7K9LB0Cj/94SLh0W orHy3CBPmnCySXDlleWn0+N8bIZUMaAriYyyFB0QBDFnei7ipOctuN6UO9nuSJjyKj ES+hXt+PyChnLDotwUJ8d0qxX9Y5yjw69QIoFByTvGM0O7IuXwl+KJde0Z3kXTPBze F2qG3vWAMCd8t+t0YjZzgBAXAFkGuy8vUK+q39c681XGXZgV7E/695YsEtl1XKIQDt XCJSUaQ5wPEnmAJ5WVaXRijf7NXZlY6QjcRVyWJCLPCqRmlSsPW94ciSJp/ooS2Fbt SexxLURTiKQWA== 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 v4 03/27] rust: driver: decouple driver private data from driver type Date: Fri, 22 May 2026 01:34:29 +0200 Message-ID: <20260521233501.1191842-4-dakr@kernel.org> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260521233501.1191842-1-dakr@kernel.org> References: <20260521233501.1191842-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 Signed-off-by: Danilo Krummrich Reviewed-by: Greg Kroah-Hartman --- 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 586091cfa45c..07cb2d79e0d8 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 Sun May 24 19:33:20 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 AFB9D366575; Thu, 21 May 2026 23:39: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=1779406789; cv=none; b=gvRUT5nQIJ5zng7DgPaDMGRgPgGrWifoeor8vKeJJDc3RPL2WvppNE/u1hJEn+kkx6cynM7q82I0E750fioVsMDYTagr+/uFE9VVXtlMCRMQqsTVxLbVHEJsl4fLVaD0z+mRrHdQUA5CyuRIQrqh5ku+9077+4xABqWvrI/EO9o= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779406789; c=relaxed/simple; bh=N+dQ9R858IFab6sDliOX+WXIW3nM16SDJa7A0V0XkW8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=K818IwJRLsyEC2mfEj6MuVI0bWYYxVXrZGuC9tgh/W6WyKXl0BYfb2o+952pBrWTaOAMwlK6SdDtzDgjrk5z6JPtCVk09nciJ4j85IOi8ZB57wUeaT8AXdDitUH96CSZ2FiEWq1X93O7MGmElQhSkPCWN3iwYjan4M6uRraldjU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=gnguhUw2; 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="gnguhUw2" Received: by smtp.kernel.org (Postfix) with ESMTPSA id CDB001F00A3C; Thu, 21 May 2026 23:39:40 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1779406787; bh=qqJeHisKz9tKPC5oGLkBiVcNisuJUN2ymiHZ2LTXoNA=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=gnguhUw2JaYKIx9C5lY0v1KlVL0Z7hZvH7Z0FHl654xPSfEvKPb2CiHFV9onZtHQQ YAfAJJifdDF7W4UHGbeKoxZ/I0cX4bnch+1HeW4d661sHVDxNFq4nJjZ67hop9cxIG 5icFvyW9T+fasedyNNbL4x+MmsQZ5ThiA6qWFSfbOu0tRWs27OEGYZ2YSjBskIw6sp imyCJhsFLg7yvUawC1neOOhGg7SW2Ss6j+nZ4OrcyjLk7FPpW0hRJGqQ5kmul5/1Qh Sp1qX4Jj1krYlCLrvubEaANjokqe9JJVgF9sIVc85iM7Dj3o4Zl5NZ5XoK2BZag184 27db7wF+ZuNJw== 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 v4 04/27] rust: driver core: drop drvdata before devres release Date: Fri, 22 May 2026 01:34:30 +0200 Message-ID: <20260521233501.1191842-5-dakr@kernel.org> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260521233501.1191842-1-dakr@kernel.org> References: <20260521233501.1191842-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 Signed-off-by: Danilo Krummrich Reviewed-by: Greg Kroah-Hartman --- 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 5799a60fd058..be59d2e13a15 100644 --- a/drivers/base/dd.c +++ b/drivers/base/dd.c @@ -593,9 +593,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 07cb2d79e0d8..f47814b1401c 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 Sun May 24 19:33:20 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 6720236B048; Thu, 21 May 2026 23:39: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=1779406795; cv=none; b=cWCQNLKG5oZk1Xf6KCEfefc/einlG9FgJYcVA0QAOUqAwtV6Qbm1ZgK44O3RIBfRJYWrSttIt7oGr0rtbTdULgTeoteqcmYZVKdRvR+6awBlcIVeC9mKB/m68Y6aOXX3n7AFzmohFayoE6lgo6tI681AyOgKu9N5apC+afXgAhg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779406795; c=relaxed/simple; bh=hna61WJP0RDs57bd7mfxmd4QbdnJ1KjrGXp6F69Aw3o=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=cDe1sOH/mx7OgAsFEv+6OI5w6GBfshddF9lffdyaJGu0AUiru2xERgTXkNBkRzstniLG3zJyFKxTuLtZSnGVGJWINoTIhe5Ye3LxPxP2uRKACYfxTdFWaH29qME90Y+UbvCtYuWT/L7Pefbi5mrBMcuCQ9VK3rHKNq++6K0ZhIc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=E4T/GfN/; 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="E4T/GfN/" Received: by smtp.kernel.org (Postfix) with ESMTPSA id A57BC1F000E9; Thu, 21 May 2026 23:39:47 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1779406794; bh=OzXy2w5PU87H6eEYeVna3xlZ4hqBInN6XC1Tl8qUBhg=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=E4T/GfN/f+kR6XhUcjg+MHAVda0eVSfgw/EN08wOOSCdVo+vuOuvK8aT3NOZYZFvM QJ7GGYCTexmXpY42uhRXiZBMwYzaMlQoq3wGTGqs6wUjDMvv5D2Gt0wUKYQebx2lKk eVljZW+UZkJW5xn063yrlLF+wRVGrQBi68+ib5dBEA2abmJBQ6/Txbr04ZNKTQMC2Z CACaX8f9Xv+PmtR84JjFP2DrNxmGRsrMgJg00nMx90Kzv26+txTxyAy9qqgLtr2gIp TipSCDNOIIH19V8asPoqGxdcKn6DmwbqY1Z7v5xFKKoS4/v0q2kMnRljjPVzuPvNgv l5qiHIKvou2Nw== 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 v4 05/27] rust: pci: implement Sync for Device Date: Fri, 22 May 2026 01:34:31 +0200 Message-ID: <20260521233501.1191842-6-dakr@kernel.org> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260521233501.1191842-1-dakr@kernel.org> References: <20260521233501.1191842-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 Signed-off-by: Danilo Krummrich Reviewed-by: Greg Kroah-Hartman --- 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 Sun May 24 19:33:20 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 70B82372684; Thu, 21 May 2026 23:40: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=1779406807; cv=none; b=U0XUF/KoIZb3YDxpTnCRSiUvKcv+p+ZQdIOjH5BSQh6RJJHSqZwgRq91YjuUmKoqwDEfe8cVIaSG57HUIJFdD1m2whVbUvFe+EI60e6PTE4gKT1qLSeoVzBkSUIrr66YnmQ0jZdXAWU9j/ezqNU6qChlLlOu41Dx9CcVZFhs9S0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779406807; c=relaxed/simple; bh=6bmHwQfqzUdZCNWXIzrI0o/hWjRhRCEEbytqokdPs9g=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=JHrQDaWJu8LMwzUPJiQJe5182fCD54czoJldfKAeT72YJuOgaOdFy/VETazAlWCBeja5WFknA4xhH5rpqKIy6t03SXFZsyDQZeWwAi0pYNFcxrd2QZ+TMojCGX617GpG8wwnH6WfyO6s8uSwy6fScyLDOIM5q28+v7nGhCw4D+A= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=h3Mxnpbc; 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="h3Mxnpbc" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 7B64C1F00A3B; Thu, 21 May 2026 23:39:54 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1779406800; bh=DC62fw7JzD1U4MkR4ipXU/wF9jbNm3QIotQzvyRxdaQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=h3MxnpbcG3xWduuC6xAGxuv0HSg4TkMTQ0SebM/4Ct1eDr9HphgDjzdiW4noIVcuM jN8NuHh1qYeeS873aE8AUQelobDdVW+U85QqhRPXwN+3CkcHySG9PtRLQDAfcQEyX3 KQTccLlRMvyqUobI9HpVPtbl09hOHaEOvzIxNzfzfGqN9R0OtnYPffvXUIeUbQlWX6 mNFuHmRtC1hJvuvdkka6Bi1BBHcAPM8T4PA0ICjFD4XyEZANQOi4OdsocvDIveO9mr XpbctJ2g1SeV9akfJ6O8SLDR34Xkre5OhKOE893j5q6O+VFsSzXwPjcIDd/HoZqT0M haHASIf1W8Ayw== 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 v4 06/27] rust: platform: implement Sync for Device Date: Fri, 22 May 2026 01:34:32 +0200 Message-ID: <20260521233501.1191842-7-dakr@kernel.org> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260521233501.1191842-1-dakr@kernel.org> References: <20260521233501.1191842-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 Signed-off-by: Danilo Krummrich Reviewed-by: Greg Kroah-Hartman --- 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 Sun May 24 19:33:20 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 3454831F98E; Thu, 21 May 2026 23:40: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=1779406816; cv=none; b=bVId08gCfSBDTMLHLGVpAQn/iEXkK7hLvgSymj49yDyTIUy/HsntgXO1ygAjSNd5MFDKQvHdtHoEhn16stSuepf3aYk1n+b2DjILt6juDTTRKKAumxYPCUfBL6S7zMISf8pMFZoeguYWKinNrwJSpkjWvbWWj2YcVKvHEeSpM7o= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779406816; c=relaxed/simple; bh=MQaVY3wn5Fr9Ki7syMwZESRCGHvN5F5kTZE869GysQc=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=obwnz0U1002/M90aN1Jae1VC8B+l0r0sQc2LJyt+Bnwnj1GY/03Ze77E8SADd+wahoh8qaJjVUCu+2ZAJMaKDSugtANYi459KPSeC6Nem2Fx03uIrBUcraSNwlVW7yoeseJ1gGmZPiIBScLma/7mTTjCakDcmWJ58FB6UXL1zEQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=NRztFjac; 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="NRztFjac" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 52B531F000E9; Thu, 21 May 2026 23:40:01 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1779406807; bh=ZhrVRWnv8zNdxXcPSXmUKIJuAuNCE6ADfKvZitNDWSY=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=NRztFjacPD5/OZIzlRctcJhFSCoVS8vrrtffhaKXdEOrFCj6CHm3C75ntBkDGQ799 xm9dUNxesoukHHbiIEatxULSbbMrslyqWAu8qItUGWxu34th1NP3nF8QPW8KJSYZx1 +M3y91d5/7ufqBNSO7fVsl4c15Toukv76GXuJQijBKTaWLKnSTGsq7WODnCR1XXkka YqgeIa8LK/KuUt5u+rJGWpXnyy3UyvFTNx8cHiTo6VqxR4Vq8ZuWoeuR3kYa9nXLK6 5NppZmRhG+CZo6XJv+eHIlL//GPbxqmWZ+vxjlmsttWwoLOBHFn1npbcx9T/GaMUz6 WKdylY3qxs3Qg== 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 v4 07/27] rust: auxiliary: implement Sync for Device Date: Fri, 22 May 2026 01:34:33 +0200 Message-ID: <20260521233501.1191842-8-dakr@kernel.org> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260521233501.1191842-1-dakr@kernel.org> References: <20260521233501.1191842-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 Signed-off-by: Danilo Krummrich Reviewed-by: Greg Kroah-Hartman --- 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 Sun May 24 19:33:20 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 49906374758; Thu, 21 May 2026 23:40:15 +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=1779406820; cv=none; b=gckiegH18+9qcJBKBc4oo0jXdzqZEAGbJB0CxYFmoJ20+g3gDi69duKoZX4iiGuN7lYwO4TPd7BxBzvl/fa0Ski3vJl4TmUZaZBAxVboiMp/Kx4Y/qLKp0Ke3xKjeLpoasz7NIsMDWQnNsTfV4wdOFC7WP7qaTNMH7XGLa2y3g4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779406820; c=relaxed/simple; bh=qTF5Y6aKb7spGXK8meoI5pO/KT/AWjwpH/fzWjglAfA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=niMprz7aQrMmUJ9VI1aNi/SHBR4kLwVv0AOi1TO1wKJQBcTHXou47BnzPU8JtuiO1t5iA4aaz3+iESoG1u58hR18GMJ5vLsqhv3a3OD+3sGLVHm0+T9odF1mw/oAbOkf9Beyz+kcAhylLLBSVfxiSZuFp58cqZxhhevT48W36ps= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=k7zjIvWd; 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="k7zjIvWd" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 2B6971F00A3B; Thu, 21 May 2026 23:40:07 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1779406814; bh=ggJY/UJJUIurxIjGS19alaA47Bxd3KuWm+WJgDSyvC0=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=k7zjIvWd+VGBCSOvUB86+/MHTdB2856fFXG9wO030mFsM1A99tCNEpFMmgGcwOrvH 44r/pHNRp4ruC80cSDkePGveT0NqDmh9OpQX8RZIZpcYZBdNm+or0xOOV+3rE5DNDG OU2uCgfW6CbzJ9fE4j5B4MvUIXwnybq1UuUTSxYPMMKfpuo/VZ+En/8NqHGoFpPVW+ UPsh+gVmNckJtDgAG0TRJjEXGdFbRhK6NOFyZnQzI44MA5tgIXZ1S5dme7t8d4NM1O fJqAY43w5dpLjN55VwUndsv0L91SXR0De/zlc8GczmH70e27kit8z3drjWx51VnZmF GeTUTOjroaKLw== 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 v4 08/27] rust: usb: implement Sync for Device Date: Fri, 22 May 2026 01:34:34 +0200 Message-ID: <20260521233501.1191842-9-dakr@kernel.org> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260521233501.1191842-1-dakr@kernel.org> References: <20260521233501.1191842-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 Signed-off-by: Danilo Krummrich Reviewed-by: Greg Kroah-Hartman --- 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 Sun May 24 19:33:20 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 8CA9E378823; Thu, 21 May 2026 23:40: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=1779406830; cv=none; b=Cp7N6XqZC8b/Dxpg+xth2MH2XM//RQiBumxskRQNx/k+SOSd3eQ5xEV72eZCF0OM0ULkKDoPeDHblM0Mb+YADYjOjK3WafsjhBvTTDloXst+rvk7+rU6RmiRKQNoMdhXtHfrK4cwlaSn3MLp7P8qH04vPf6lqMCLQ3cXrVCFXG8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779406830; c=relaxed/simple; bh=JXccmOWpRcrxSO/NFM8G2pwnV88QKz/08Cw423hCPw4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Sxg5HeO5QU4tlk6/2KyCRG+UbC/DhYhyMV69+OWRtrFdIDjGd69T09J3J/zQtm/mkDVuSB0+GDfVfXpfU/r21L+DQ1tjCWdIPMGKMoLpvIcXlO+nh/oX16UgHNwHZLsMEpbrm14u+p50qytRf31fyyIShiAuL5WD1hKD5r1BJ1M= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Hs/9BRzA; 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="Hs/9BRzA" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 00F881F00A3C; Thu, 21 May 2026 23:40:14 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1779406821; bh=e6xTb/0g7FVUv3sF33GAdUqdbfpeGXi2qCe2Zvc8fNM=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=Hs/9BRzA8yHSFgq4PHMUssbNdcbHK7xdh8d8dTguIOsX9YHZsgRLHS48aORQNfBi6 jbkMqxIQDuSqBAYcRrl+/S0zKSEwH2ysmY7h9TGs/M8nE9AqMw8KpPbYiqNsbXcdqJ 9vthGbstXyD/R2uJvyhtq7xHzF+s4FUa7+FEk0gkOsXThInc1zMjSZTYvxGG1YLHAk k5sZH1jWO/sMBbooqd0xRk2W2yV01q3PkQVUZchsZ7eT6mhXqbqeK2gNOAjXRlUeiz WSV7wlVDlBN2n09uejGgzLsRugIsGtY0w0amifZKhtwmThNasBKW76woiVmtDC85ga Fi/1EH7mjBerg== 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 v4 09/27] rust: device: implement Sync for Device Date: Fri, 22 May 2026 01:34:35 +0200 Message-ID: <20260521233501.1191842-10-dakr@kernel.org> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260521233501.1191842-1-dakr@kernel.org> References: <20260521233501.1191842-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 Signed-off-by: Danilo Krummrich Reviewed-by: Greg Kroah-Hartman --- 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 Sun May 24 19:33:20 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 2C930377EA7; Thu, 21 May 2026 23:40:30 +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=1779406839; cv=none; b=DcmOdHj5qlJx6zHn2XdvahlOmsjf/lia613e2TlT5ONBd8cn3evtg2lkXCmQeoW6WagFX86Lrfh1y9iPcVblbUp2OejaQRsYiJnmc4+rZCc5uNT2IBrWYCh4/z24qX7VaLb02368V59RaAxun4NHVeQz57v7rQOe7EpwAM0Fd1k= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779406839; c=relaxed/simple; bh=UiJJ6mQIBh+sAqk0757+2eLSw/MIliQ0m7az4GFQkXY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=NVsThdgF6XdqgDfrwHH9wbXIXZNIkvZTbs5fE++kmUFXtXoeMa78GFf99PzsV/TdxeyRFHuPZIhd+Kev0vRQ8mbeqJG3lzzM+A8IF0qP5PDTFiRaa25gXuE7xl+yDBPHPFm4t3okzp4KqgCxq5TUH7x7ZWbq3DjNeVbGUrFnku0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=jUxDcnWG; 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="jUxDcnWG" Received: by smtp.kernel.org (Postfix) with ESMTPSA id CA81D1F000E9; Thu, 21 May 2026 23:40:21 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1779406828; bh=yDTki7mhoHnfOTmNT9Z44hX4pbRe9V9Ogl/CrdRLtBE=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=jUxDcnWGfXjak6po/wydbNZYr/+banL7zy73LAs9J0Z5RbytovmKARfM1iKEa7VSL QGVArQxSLiV1zIuUe8QzPriRU0n0gNCbFUuwePJNhgaooEtWxdXvlFJJz7RvNHXQwT jfzHWcLk3giTKaDG5ZF4mKsm32Py6qR5NzNVIJJtVlmLGYpTzhrZPFuAWzQIykz8Sl VRd52iGft4OD2XyxkBKfeChtoLC1ZnlULVKGRRqIYlVx3D1wwCEvKZuoWQ5oAtAQTF z3fM8Vd9/UAbUNig9jcyBzSzKLnhlyYl/fzmqqBWXAdh2qr9KdzIYfxaKIcft539+r WHTI0kJt0KFRw== 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 v4 10/27] rust: device: make Core and CoreInternal lifetime-parameterized Date: Fri, 22 May 2026 01:34:36 +0200 Message-ID: <20260521233501.1191842-11-dakr@kernel.org> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260521233501.1191842-1-dakr@kernel.org> References: <20260521233501.1191842-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 Signed-off-by: Danilo Krummrich Reviewed-by: Greg Kroah-Hartman --- 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 f47814b1401c..93df26ec7caf 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 Sun May 24 19:33:20 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 3420F37A4BC; Thu, 21 May 2026 23:40:37 +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=1779406842; cv=none; b=Cmub3tM8Leaz0JXH8Kts50qc8M4v9AUioPhDWfLXVRU3rdz8E1JRkipFlQixrh7sV7Yk4uhFUFAimTS36zUOQ25dZXOh5wAbQqzzaXLSdLpv/g0yuIwDPz7pXumQFJ+XnWNKPC5n4Kc80JjbyBBacStHN7grH2fioBKTYZtdWaY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779406842; c=relaxed/simple; bh=o8aCweeQi46lwoXnvwgQeqQN1xXc0gp1yYV0waqWBnI=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=AxzHvrp5DrL2FDFxMgm2+BGDQGD3hJaTZA3UnXKD/sTEKSM9k3Z0CpZSmDWHET1ZMh4Dkt+xwLdGrS26XenXqsSSMiU/g0PmQ6fcCH8iakGGj/7th7S+DpDzmsTMG2FyK5h0VGbpltL57BRSj5WMZKYhnGJLAdFAE/IpMIpQKy4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=JZnGZFzV; 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="JZnGZFzV" Received: by smtp.kernel.org (Postfix) with ESMTPSA id A0EC11F00A3D; Thu, 21 May 2026 23:40:28 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1779406835; bh=NnGjcL7KCY7DeRdXWPfnt63zevGpvRoRbOoOP1ZRnLg=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=JZnGZFzVjcVBf9TSnNANcehypJGLZGBPSOKZCChqBWXe0xI6j2iMBRWja7mm9cRIZ VL33JrehzPK+KXunaZXoq8aDGRF9Sr/oSeYy/nycEHB9Thec5PWodH5GP/8HZevUNs LgaRXDR4znVRnX9dP6hZduxBZMAq+oFVn8zQdFnD3elCkswwQphmmGy7bNDX/qBhXO YawScoJvpEydH/x2/uF1zEX0fr4Ke5FFVWhRL6kwsXYFJOUmxcTTcYhgojlBsQTGYx 0hn/AS9OiQ0S/ozmDFbNsw1mvW1fkuL5do8vKVfiBslWKo2PWa5UCI/GGhMMTsJb9J Nu6SZ5X4l+hWw== 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 v4 11/27] rust: pci: make Driver trait lifetime-parameterized Date: Fri, 22 May 2026 01:34:37 +0200 Message-ID: <20260521233501.1191842-12-dakr@kernel.org> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260521233501.1191842-1-dakr@kernel.org> References: <20260521233501.1191842-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 Signed-off-by: Danilo Krummrich Reviewed-by: Greg Kroah-Hartman --- drivers/gpu/nova-core/driver.rs | 9 ++++++--- rust/kernel/pci.rs | 26 +++++++++++++------------- samples/rust/rust_dma.rs | 7 +++++-- samples/rust/rust_driver_auxiliary.rs | 7 +++++-- samples/rust/rust_driver_pci.rs | 7 +++++-- 5 files changed, 34 insertions(+), 22 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..a462f4e8f5f3 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 @@ -130,7 +130,7 @@ extern "C" fn remove_callback(pdev: *mut bindings::pci_= dev) { // 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::() }; + 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 Sun May 24 19:33:20 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 EF5C337AA98; Thu, 21 May 2026 23:40: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=1779406850; cv=none; b=d7GaArf8wjU1r0yJZhbFfqLY4Bm7apgBRRk09iQFHrplz+7WB7xf7O8TzpH7uAWgtsGjYR8SIXLQX9IxpWhcuBQcXFJJDm8zcoqZk5bZT8NasxVzgRUBnrQIYrD27xEYIG7vDzhUmkEpJVD2JiEYvPxy4hjhVaJdrI3t+um63hA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779406850; c=relaxed/simple; bh=4mBnT+XCk3fYBL73tUA9IcFSyce8Cof0UyELaL6VX9A=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=MwCHb6kpg/TSR7bfY7zBUSFKNBNINJkRWo3wltj7Ar1rvLfwLq7qDkyt3UXtczdoVbaKff/7RV0sEYy2KSOc9l3sX/sYll0K/dmAcXSzyt3VXfBx+qQmZ1VnY92cxpS6MZP9tKZWSUw7xjfOGRbe8HGqA4qyy9FX8K/jnJQozrU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=ZWeSp50s; 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="ZWeSp50s" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 769131F00A3B; Thu, 21 May 2026 23:40:35 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1779406841; bh=TCATN4a3J13CaAJic6O/YHUTHiJNywIl5P/UqO/Kk68=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=ZWeSp50sQ86wRbADZPpdXpJ0xDg+2mCbW3rZZsaiYYNzue7BnkhEkgYvCM/9KXKoP WLtc2eSbUcHwDWJBKihr8hrYlLhF8eo6xPuL4iq0xfqY3EryefZJMQPveFBfc8I3Vl bFsmJGLGrpwQ1SUffzDpv3Ire0mTMpuLrFnUdx8iv0rIy1xgyR900FrXEYE8cV5G5j sA7G19r+CksL21tOGCX+q6IS/0917xStjjmh2/yHbOFfjPFwuK845bcje+uDxg0qM0 UJvyRRvoZ2CS01a8O9Qq37UWAoM1zhIa5NJSvR9Y71wLaBBfS48P4dxw7V7U/qPNtz bWJb/talzJ4jw== 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 v4 12/27] rust: platform: make Driver trait lifetime-parameterized Date: Fri, 22 May 2026 01:34:38 +0200 Message-ID: <20260521233501.1191842-13-dakr@kernel.org> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260521233501.1191842-1-dakr@kernel.org> References: <20260521233501.1191842-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 Signed-off-by: Danilo Krummrich Reviewed-by: Greg Kroah-Hartman --- 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 | 26 +++++++++++++------------- 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, 67 insertions(+), 64 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..2d841e8d1ad3 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 @@ -118,7 +118,7 @@ extern "C" fn remove_callback(pdev: *mut bindings::plat= form_device) { // 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::() }; + 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 Sun May 24 19:33:20 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 5C6593783DB; Thu, 21 May 2026 23:40: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=1779406856; cv=none; b=eo+zWNn29zByYixgLwvRWX4Sq+bnRDB232xxvruunBy5qu+rPXwF405uP8i4fwD/vj6xfSvYhZHoVPrfYFW1iKDYAGWQXteP9bHnAVwhp0NjSPCi/quyus1pgBa8u/14ack3XkdeMY93DmdZObzxv5RB8whlRB+nq3DbCxJg/U4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779406856; c=relaxed/simple; bh=e0jspvouZkiyrH2SPBAFhl5Q2C6Gk3Lbzoa6e0IGpyU=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=gCCSt8fS28gffnJs/nmdSgCQvEDQPUBZU7BXkL9U3JUaq6oNZIlR+vh/eW/7cz6cakb51ZZcDTvsPc88KN5NnIA8jkzFzlZ5OlfzVvTZsKMKUGL80z2AYmjgYswilvRpETsbJYkpXwgLO18zl/f0PFmenKNFIjqMCsDN/ojFnmo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=oYQxh1bx; 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="oYQxh1bx" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 4C6E41F00A3C; Thu, 21 May 2026 23:40:42 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1779406848; bh=QpF4w0yZ/AivrhZ9KACyFbY/eeTlz1cmCXatORmv+kY=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=oYQxh1bxkE3iUJAh6VV/3HUy2plmWIo8oULBngJn1zaBDyWmeGWTfo8KIX13TPoKW hsuM6noHrSAkC4HrivfAwPrImmX7z1XPz6eDvLeZAi1wRP8HOGtprjIG6PVq0vfUD5 36fVeE84ZMk9LYMru2hN/dQzLuDPl1eKAOVMAgYYXNLLyUeumjHrwm/eNeExlwQrei Cwvzz0Y7EBc8VHT/8pOzkmeCQdOxJ/L+EYu/tYyoBS30sTBmpAarZyrnaD1L3GOtwt ZFDeOsgWJjmm9T2xS3wvD16UxmPdlDLcPdAAzG7BBQtBz1PMJk8WnZc3yZkgPmDTax kT/6LScL+HYUw== 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 v4 13/27] rust: auxiliary: make Driver trait lifetime-parameterized Date: Fri, 22 May 2026 01:34:39 +0200 Message-ID: <20260521233501.1191842-14-dakr@kernel.org> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260521233501.1191842-1-dakr@kernel.org> References: <20260521233501.1191842-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 Signed-off-by: Danilo Krummrich Reviewed-by: Greg Kroah-Hartman --- drivers/gpu/drm/nova/driver.rs | 10 +++++----- rust/kernel/auxiliary.rs | 16 ++++++++-------- samples/rust/rust_driver_auxiliary.rs | 10 +++++----- 3 files changed, 18 insertions(+), 18 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..5591f97f12f7 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 @@ -112,7 +112,7 @@ extern "C" fn remove_callback(adev: *mut bindings::auxi= liary_device) { // 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::() }; + 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 Sun May 24 19:33:20 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 060F937757C; Thu, 21 May 2026 23:40:56 +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=1779406862; cv=none; b=rGiG/wN4waLZ/MFJ7pk6rrlp7ed+x0Jhmc7GZXxYK98S4pR28pNHBkoG5DNii6toI35tFIAVqkHcfGl/LhVfJERU0+14/usWULhAQiTlLM7XL2obSQipkq+nxWaGB1Uy6mz6jJFujl4iEtF1k7tAVZvYDkytFgv4HgDeenvgqBE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779406862; c=relaxed/simple; bh=gRp3gY4UStiDPWDlo3loGe6oXR97c3BA2TzeyFi7YhM=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=hyqx5UmHmyMlYWXkLO/oq3qZpPap/hGiDvRWmsYoLWltHP8zAIomgKMYbdTWlGFe22ct9pv/IrQf5Sh+CC8clhYZyexNoea+TGUSZ/r4WzO5HzGZZFADDF5Y5+0P400s+sU2sIX/1FL4p3KQ1azB6inzKKzXHfUL6HMUPd27xm8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=lxFHd+KU; 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="lxFHd+KU" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 231E21F000E9; Thu, 21 May 2026 23:40:48 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1779406855; bh=15eNXHw81vxGZI2GuAH5sskwDscXxddG3uEgbge1xYM=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=lxFHd+KUMZsSzj66D9XOJgjAN9GEaL5TZWTMAHDNzG/cgT8pTyus9z0P3gClcrTGk KPO0sqX6FNiEAN0Vz7IhL4wLUHcGBoKR3YgukbnA8GUsw/VyICZIeWiOpJ7JCI6suC LVorl+hajTRCLKBS63eg5MBbbqGD6nY8cgCq5wSzDy8gqWAe81DR3ve+iwS57TMSRa SZAA1py/SgApGIubm+YTYlUnI4e4hhbSKALfz2dYzJIL0w12Jr1lV291Jp4Df7K5aY dFYguw7rxMB4doOPe37XldKUlAaMkQQJEsIofRascNMeWexdFNzBQFZKkU9rL+9AoD FtYbcRbgewMEQ== 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 v4 14/27] rust: usb: make Driver trait lifetime-parameterized Date: Fri, 22 May 2026 01:34:40 +0200 Message-ID: <20260521233501.1191842-15-dakr@kernel.org> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260521233501.1191842-1-dakr@kernel.org> References: <20260521233501.1191842-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 Signed-off-by: Danilo Krummrich Reviewed-by: Greg Kroah-Hartman --- rust/kernel/usb.rs | 39 +++++++++++++++++++-------------- samples/rust/rust_driver_usb.rs | 14 ++++++------ 2 files changed, 30 insertions(+), 23 deletions(-) diff --git a/rust/kernel/usb.rs b/rust/kernel/usb.rs index 1dbb8387b463..616e22e34c6f 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 @@ -110,7 +110,7 @@ extern "C" fn disconnect_callback(intf: *mut bindings::= usb_interface) { // 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::() }; + 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>, -/// _id: &usb::DeviceId, -/// _info: &Self::IdInfo, -/// ) -> impl PinInit { +/// fn probe<'bound>( +/// _interface: &'bound usb::Interface>, +/// _id: &'bound usb::DeviceId, +/// _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>, - id: &DeviceId, - id_info: &Self::IdInfo, - ) -> impl PinInit; + fn probe<'bound>( + interface: &'bound Interface>, + id: &'bound DeviceId, + 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..918d5766cc06 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>, - _id: &usb::DeviceId, - _info: &Self::IdInfo, - ) -> impl PinInit { + fn probe<'bound>( + intf: &'bound usb::Interface>, + _id: &'bound usb::DeviceId, + _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 Sun May 24 19:33:20 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 6C487378D7D; Thu, 21 May 2026 23:41:03 +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=1779406868; cv=none; b=AfBAsRRJFfifo8CvsTDZCdLReQ0vJtWjjjhzS/dAWq5fNwHnWKsR7o4QLqGNW/EjVwY3an239h2SYxd++JUbt56WFqlA3xHVl70JOmNsLS1SBbtMnBr2N2IhsAoTFTwURiUt3+Kn3PGdw7Xf9Q/4OYlLhybMOj3k6scrx4iLU3U= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779406868; c=relaxed/simple; bh=hFwq4rxJ4hLU8uep19pm3k2HDHFR/lEj2oP8SSUZwuQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=rB/AqjabLonqTDuDzTqkRGuoaHI9/fbEYD4iAcHSaojC8Tcw5zLoma+O6yLRg1SXBsy8y8YmP5u+j8aZizwD7tMek60HghcDoaESfD0purzhrcBG0bnFEYRC/qj+cNxiyICvVsC23rCkczQhsxtpNwh3oM+gS0Bkf5Ups/Rzr38= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=ojRpc083; 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="ojRpc083" Received: by smtp.kernel.org (Postfix) with ESMTPSA id ED1741F00A3B; Thu, 21 May 2026 23:40:55 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1779406862; bh=BPjizT1U2YETmq9izMu6+7SN+Rex8/U/rfjmjkOVVMw=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=ojRpc083p2phegVaTInxnkgz4BlCGVA+VIvjrWZ0d7o32p7PAYnf7DqeMQfybPamw 5qApm4mVs/LbYCxbaksnhoKm+tY+YQaOUE98z6p/G+u/xvAdNfZu0nlLwxjfbZCsXR xqkg1hflRpt90B3XYbPBEluY9TT5k9S36mptpXQ+7SK96xiLDDXMcyAC2gGNtE31cU xFypqny/xCk9hxeWNsS0foBRaO8Deqygt+jA+Ty/KDifW0cRvrFWVjzWTuCT1gyrP6 Gce0Wz+tqDRdq0qZIX0zGKvaW2R3N3sxuwYw/O12vnHu4nK7jMQBwW26kqfpRLtJw6 dYp1hiNqqGJ7A== 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 v4 15/27] rust: i2c: make Driver trait lifetime-parameterized Date: Fri, 22 May 2026 01:34:41 +0200 Message-ID: <20260521233501.1191842-16-dakr@kernel.org> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260521233501.1191842-1-dakr@kernel.org> References: <20260521233501.1191842-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 Signed-off-by: Danilo Krummrich Reviewed-by: Greg Kroah-Hartman --- rust/kernel/i2c.rs | 35 ++++++++++++++++++--------------- samples/rust/rust_driver_i2c.rs | 14 ++++++------- 2 files changed, 26 insertions(+), 23 deletions(-) diff --git a/rust/kernel/i2c.rs b/rust/kernel/i2c.rs index 50feade0fb58..13b16afad9f5 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 @@ -177,7 +177,7 @@ extern "C" fn remove_callback(idev: *mut bindings::i2c_= client) { // 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::() }; + let data =3D unsafe { idev.as_ref().drvdata_borrow::>(= ) }; =20 T::unbind(idev, data); } @@ -189,7 +189,7 @@ extern "C" fn shutdown_callback(idev: *mut bindings::i2= c_client) { // 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::() }; + 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 Sun May 24 19:33:20 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 36300371888; Thu, 21 May 2026 23:41:10 +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=1779406874; cv=none; b=QKItICdXUTcf3Rv9RzIT8gFhaJB/ehR4bxZdAc6dC5iWwEB9wRUwYuJ40upzkCw9WnOFw9dGHZzcpxQBJEI/RJasP1mmr01qyS4HQ3G4ggKDuQVsQeXqYqfzphxxvaaXVh7bTAwdRU3g+NzaxCqwE0PwYxLdaHp3NRujZpa21tU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779406874; c=relaxed/simple; bh=OQslwCmDtW//31f/bssd5QXIOeASEqVhoSDrONJcCNA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=j54r3W8O1ybLgI8YkqcYJsQ1sNAmI4t9bbIPbybArvYa6jvtk+kWFP1Zjz9jvDg1CEAKoBFwoph8boZoHR/iByzSs9rkPJJ0wuGSHm66xPxvr9bOtWo8iJU/vIFMv3aTm3jnaOVhi7hkkqrKujpUdUl0tpf+pBwXJ+pUE4zDW4E= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=LyhRh4YP; 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="LyhRh4YP" Received: by smtp.kernel.org (Postfix) with ESMTPSA id C25261F00A3C; Thu, 21 May 2026 23:41:02 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1779406869; bh=JwcbKbNRK8uAfwmPt5zsBCbjPSi2Kcj3uVLASq+gxic=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=LyhRh4YPeVfL1qX1kZKG7e/4oRdnyxvm1ypMMuVFPQyzJB2VUBVaYZLOd39JuOICT Ub9YkDZK43HQNUtA3inAbs0dREXFiRSf7elgywVJOGbGZG/RyTjN0vtSd6zitwk+r/ PUb+JszKvMDLpz4K98EQ/Gz3rJvZCEeFogVMQfYiv9RvKSEDHJRvOBXvGAKdpsQB76 9cKNE1UfQW9/I9ukWnGQanP8BD7dp6YaVWvtOGm/GK/2W4SQ7yJRGkkAfrWcxdx9Jc sbz1tqNWQVp2J2QqnnuOlDQYD6ywO7pSoHH+MoNJinI8U1cXkAPNoKEWGV3XKPDxeR YLt49vmo8xGIg== 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 v4 16/27] rust: driver: update module documentation for GAT-based Data type Date: Fri, 22 May 2026 01:34:42 +0200 Message-ID: <20260521233501.1191842-17-dakr@kernel.org> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260521233501.1191842-1-dakr@kernel.org> References: <20260521233501.1191842-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 Signed-off-by: Danilo Krummrich Reviewed-by: Greg Kroah-Hartman --- 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 93df26ec7caf..bf5ba0d27553 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 Sun May 24 19:33:20 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 4242F38238B; Thu, 21 May 2026 23:41:17 +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=1779406881; cv=none; b=SRap3KxUd4d8yILVhkGAhpxlODe8GNfeVxQ6EXyW1eaRbaYrCCN2Qy124q46/4XJCh/DL7egED8t06YSM/+WdoIk3SkaoWdUl8hByjUS1yNfXy3xfHrZus26u+dzmJ+ev0M6Uhx0LY21COTCamngN/Xn6ESdActgJ5ma9AirjZc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779406881; c=relaxed/simple; bh=7nEdXucS0Vd89jowIwSqsoIjtg3p7PaosA+6j2vTvnQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=rlwchYTDJjiLR09+vvFgWJ0bC4iy/y/vHkx31/9+fwq9Mzf+/+7B0V+ujxoJ/ycfi5mRn8B2O1OOqW1Ow+ajR9BObSBhulejbZae+dXZkEtTDroZww0g8ZLs0cEQ5qOy1KLzD+25tjMLze8A4DdhtBMEWoKQxMChzAzlfuOgRJ4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=CtIIPXF1; 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="CtIIPXF1" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 98A8C1F000E9; Thu, 21 May 2026 23:41:09 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1779406876; bh=uvm0h/diC9y+jPP01SbuPaWogBCeoGFMzjyQpNZZskc=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=CtIIPXF1HRBA2V4qZtI2LzaE+f6o77N+lNsckZeypE+V/4dHqPsDEF/3E3YHqXLFp QOSEixy8L174lXpyBmpcQyvxnhXuocRoOg00UufQVi0FzaUS3qEJnELuexFM7ybpLc Y3skiFaWlKtgaEpKk2d5JeCiQXTi68vWe6SFIcIM0HMdYmAPRTZm6B1q6gictC9h3L /gPe8Vi3DAXoNz566poyRx1/oe3N9hWlJ1cWMpHCZkTWxMgHB/RnSA4PY49V+NmCU7 qi3FUZV2glaQ/LJVGz41sDr5njoQYvrcN/SO9tjadkDo+fjbT0h7XNlx06hBM+oDc7 S+mM2dNFmg/zA== 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 v4 17/27] rust: pci: make Bar lifetime-parameterized Date: Fri, 22 May 2026 01:34:43 +0200 Message-ID: <20260521233501.1191842-18-dakr@kernel.org> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260521233501.1191842-1-dakr@kernel.org> References: <20260521233501.1191842-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>. 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 Signed-off-by: Danilo Krummrich Reviewed-by: Greg Kroah-Hartman --- drivers/gpu/nova-core/driver.rs | 7 +++-- rust/kernel/devres.rs | 2 +- rust/kernel/pci/io.rs | 50 ++++++++++++++++++--------------- samples/rust/rust_driver_pci.rs | 5 ++-- 4 files changed, 35 insertions(+), 29 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 ae78676c927f..6116c55412bc 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,14 @@ 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: &CStr) -> Result { +impl<'a, const SIZE: usize> Bar<'a, SIZE> { + pub(super) fn new(pdev: &'a Device, num: u32, name: &CS= tr) -> Result { let len =3D pdev.resource_len(num)?; if len =3D=3D 0 { return Err(ENOMEM); @@ -196,11 +195,7 @@ pub(super) fn new(pdev: &Device, num: u32, name: &CStr= ) -> Result { } }; =20 - Ok(Bar { - pdev: pdev.into(), - io, - num, - }) + Ok(Bar { pdev, io, num }) } =20 /// # Safety @@ -219,11 +214,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 +239,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 { @@ -252,17 +260,13 @@ impl Device { pub fn iomap_region_sized<'a, const SIZE: usize>( &'a self, bar: u32, - name: &'a CStr, - ) -> impl PinInit>, Error> + 'a { - Devres::new(self.as_ref(), Bar::::new(self, bar, name)) + name: &CStr, + ) -> 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: &'a CStr, - ) -> impl PinInit, Error> + 'a { + pub fn iomap_region<'a>(&'a self, bar: u32, name: &CStr) -> Result> { 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 Sun May 24 19:33:20 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 B8CB1378D9E; Thu, 21 May 2026 23:41: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=1779406889; cv=none; b=W7JLGmNUbwIZMI6MNv9UWl/5a/7za1/34G+MT886HuxeOxR62d3lxYb2jdxnUm84ih4b2ljOracvqgG41o6EvUgk9sPDbvhKFgPWOLCESx9m0aMUI613mU75nwtLgZChKv9heOVjOyrD6OeBNGT5/kKt5j0OZJJtXDrua5M4sGw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779406889; c=relaxed/simple; bh=XC/m7Eo1pjqY+ccRLxQHX5P3WSnClMgFocqpJDIY0/k=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=g9sa4Y8qQZvY8qA5976is2eMdju6ClUgSnLPeX6q7uvfE7N9RSMyhmsEnx4RBU4tR8TKnSiDbd7t2s0K6gSmLMJiaC5LZMTqMtNVGtYGusxA8p70LBMzYHAZXk0XtjGwcvL4FQYAAQfm6l/HTbJ7LwJhLUgp2+I/xObDkIo+IQc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=iIu2NYsD; 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="iIu2NYsD" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 998BE1F00A3B; Thu, 21 May 2026 23:41:16 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1779406883; bh=3gGtk1HaMSOrNjSuBv1vNVcxZdaUJzZy2YhNgkmnK8M=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=iIu2NYsDwUMoNVqXejhPr7N1nulrwGg5RmVR8LbT1MRumGi4ECvOc9uClytjyL9+F BOlQgoVVGb5e3raTNsT9g+dA+fos5CasEaINUGXHEyKkem2v0uli+fV3DZS3Y+AKZd Lb5K8WBEMoPyih9pSou24+YqkV2LNwIA9tCG+YPOIPJz8MRarTdZ8MnOO2Xab8Kp3c 6jnORlVwFIPOS+Y2llqbkhE/hvbja5bSCyuagxLxed/KxIWButX2VjYBf3s0lj+MmI iaAQKf0nrHDEskHES1y5hvdEi2FWoA8xK7M0ogs7r+n1hE8jVUxa+EfaQzlt0FXMl2 ZYxPzhoaQ88kw== 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 v4 18/27] rust: io: make IoMem and ExclusiveIoMem lifetime-parameterized Date: Fri, 22 May 2026 01:34:44 +0200 Message-ID: <20260521233501.1191842-19-dakr@kernel.org> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260521233501.1191842-1-dakr@kernel.org> References: <20260521233501.1191842-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 Signed-off-by: Danilo Krummrich Reviewed-by: Greg Kroah-Hartman --- 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 Sun May 24 19:33:20 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 B6007387596; Thu, 21 May 2026 23:41:31 +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=1779406897; cv=none; b=JgbJSHvtmM9T3gqV7VBMlUJewVJ/zyDpHS/rflL4P3oHxx2rs0KnraavgqNcavT8vis1ArVd6PoU7cjZ3/3KZ7RKP5C+fsSafd0IzArJ+FSM4lx7Glmu7J5VB1gxfE2SukHI00mklx9XdmszKYCPMeljxdkxkP7UO+R+zheBv74= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779406897; c=relaxed/simple; bh=xHgKVPGVfOWtieNSvIbyzkBESHRgg2F9YKYBnEngkC8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=XAFQPLk2u1dpaL5p2UjbLacCN1T+wcMUrn+KIzhP8S8nvP4+CYQrH544GpFXvaXVioE9fcFbxe+BhvP0Gungi1bz2qWiQlUwrwNo3bbBbNWR6Ehm2sacz7w+1xlhJN6tos6b+aYYExEiJOrId6++DM0Buv7OwCTU6s4kBFXHTXI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=KeJEoyCH; 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="KeJEoyCH" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 9AF5A1F00A3C; Thu, 21 May 2026 23:41:23 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1779406890; bh=YS3MIWt7wBP8jQ9SbXuqnDqrROA1jOXopyH7kmiVFAM=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=KeJEoyCH9u6rLuX3kBFyOlxstdiVTi8CFJ+DideoIrB5QE04w1KBuBjQiwlt7suTX wI4+rgNELgACQmsSSAWm6pAv3P53pdnMzAQWM0gZnJNUhrF/moUTE0F7uxY7673keH 5PnJM6/MLBlXRyUYl9YxvuFmJtFhTH91zwhB7AmSGytSEpIU4dXo95r7eDGrmpxrkb khmGPx/4DAvXlWXMZzQ+cmx80uOpolOIRQ+B3qeQ9aPA9qfm6EWlnxboxiclAznevh GvuhOejpZNl7U28THr038UGzBJyi8fOgj0ZgCP8KrRCO/20FPejyHEHj1jbOLo9ebl GVo1KO7st9H2w== 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 v4 19/27] samples: rust: rust_driver_pci: use HRT lifetime for Bar Date: Fri, 22 May 2026 01:34:45 +0200 Message-ID: <20260521233501.1191842-20-dakr@kernel.org> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260521233501.1191842-1-dakr@kernel.org> References: <20260521233501.1191842-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 Signed-off-by: Danilo Krummrich Reviewed-by: Greg Kroah-Hartman --- 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..0ae2373d74fd 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<&'bo= und Self::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 Sun May 24 19:33:20 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 1545F383312; Thu, 21 May 2026 23:41:37 +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=1779406903; cv=none; b=N0qyvdHgFxRIHLkESQcHAUGGNv8ZTPnWp1t2VubmzjNxwASgpiVmaKzs6IVHOo0EM7XbbzG18n5hZxdSpyyYxnlsKl4x2w9ciOE0J1ZurBPEHfYsnlQkatEELV77sY6oe6J+1x29GdIEsk1SGxti5GBJqkPmB8uSk1rHn72mk0M= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779406903; c=relaxed/simple; bh=O/PiN/M13rEh8PebwaJw39IrIuO/6xTAHGvIk/OXc/s=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=MUNryd7vHW2dL/CUU1pAYDN+TLGkZOArAHiZoN2TgdaLRt0XvX8hlTapto2SR5maE+Vdr/nIweChe//5i4/Kz1MrWGRtCi3FB6cpki0U2Uq49QtV4s61a0mvt2u2cH2KrVBWxCkvQv4vzNWOqGXHVshj7qv0e7Us0lkfZZTsl6I= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=bHg2jr2c; 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="bHg2jr2c" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 9B6211F000E9; Thu, 21 May 2026 23:41:30 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1779406897; bh=zQyEv5LctNSyn/SsGR1f7Ge4LhX0SjTKeMVIeRtvjcA=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=bHg2jr2cY1Ob9lxZl3xD91EiFjr5hGao1v6PV+MRSSQHxYN1KT29eQcZ3Y1XqKTUC 6vhBcBIBnDXCwJpzw8Aro+raBpSLGHJwP75OYAvxpbjTKPGH+L/pQdyIY1wNhYUHfM NoXBOQPA7AEFL2paB9NMkq8crWHe8DDE119R4PjdTulQSoNu0B0I9/q/Ip96PV/D0Y qen2+hxXbU6rGlPFI2beWYAWK4+BXUlNsgoYAixzEgOoYjpJgkDRsBDBlCJCwTSWve NyCJGTff5873eqak1DoWV8w9SPQd/8OxATqMu30pCH98ii6LL+KRv8vzUQqYo8NpTy 72Lvz4qnQG4LA== 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 v4 20/27] gpu: nova-core: separate driver type from driver data Date: Fri, 22 May 2026 01:34:46 +0200 Message-ID: <20260521233501.1191842-21-dakr@kernel.org> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260521233501.1191842-1-dakr@kernel.org> References: <20260521233501.1191842-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. Signed-off-by: Danilo Krummrich Reviewed-by: Greg Kroah-Hartman --- 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 Sun May 24 19:33:20 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 C402637C0ED; Thu, 21 May 2026 23:41: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=1779406910; cv=none; b=bI70v0bGBx58ZLucPwPVmIsm2JSEEUZ1Yl6fKihgLFj1HQjXvKajD1u9+uTOMH7Ye49ErW5vG3F0H/QCUq0ve8rTEF56zXRNh50eYD1CI6ee0qd5DTW72T9vrbRou+UA0VtiZIPpTieoInhJCdad0p0OBVw70QRP1IEcgwU7v5Y= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779406910; c=relaxed/simple; bh=p8wTHkVlKxAFxMw/PWj6DQBuMJY/KNyS3LIG4VYQ51o=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=TMLG/ZGNmxribVTEPKeq91851w89MDY9ccMlzp0nwrja14cg7gtydOTt5J+SA245Wj0jyKY4a2W3ZlUdlyq0/erDwHZVi9QEIa+bI8aWglV00gZBpgldi8kYJg+VmWi82GHx4v9rJHetzwOknYzH22qTXjjZMhxnM5zdDwNo/qw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=bUXDLNsE; 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="bUXDLNsE" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 708751F00A3B; Thu, 21 May 2026 23:41:37 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1779406903; bh=Ego8byUs7P29LqVR84rGjhRQOOkkALcV1PVKPOT6ebY=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=bUXDLNsEYdICWtnDWcHLLJnZ076bf8agQPihVJ8JRdFoN06dN1DoDI7hcXdQ/lNWU qpCGGYqz81gieHnYWooyBPUj/DDwDhQvm/kiLAhJIL3EPB4A0VXmZrZbejeAait9/w fIxFi4qTIpX2rnHaHCkoJ80ShDxGAeoELt3GmD2EJkWFZf95pkhbux0undw+G9fr3T 2owFYgXAKfjQ+3VfwtK+YWA4tIp48WVILPNo/ZCxrsMqLRtx4vCnJqB97fIz11JbD7 23vO6MRDRvZXApAd2K93t+dB6h4DOFPhYGX4LzkFk9CkrysIkWD/ktamBnOJ72RFXj vROmryBM+Ntyg== 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 v4 21/27] rust: types: add `ForLt` trait for higher-ranked lifetime support Date: Fri, 22 May 2026 01:34:47 +0200 Message-ID: <20260521233501.1191842-22-dakr@kernel.org> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260521233501.1191842-1-dakr@kernel.org> References: <20260521233501.1191842-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 are generic over lifetimes. For example, if you want 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 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 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] Signed-off-by: Gary Guo [ Handle macro_rules! invocations in the ForLt! proc macro's covariance and WF checks. Proc macros cannot expand macro_rules! invocations, so the syn::Visit-based has_lifetime() and replace_lifetime() helpers cannot inspect types hidden behind macro calls. This caused the covariance proof to be silently skipped and lifetime substitution to fail for such types. Add an explicit Type::Macro arm to Prover::prove to conservatively require a compiler-assisted covariance proof. Detect macro-containing types with has_macro() and use a WithLt trait projection for lifetime substitution instead of AST-level replacement. - Danilo ] Signed-off-by: Danilo Krummrich Reviewed-by: Greg Kroah-Hartman --- Gary, please let me know if I got those changes right or whether you prefer= this handled in a different way. --- rust/Makefile | 1 + rust/kernel/types.rs | 4 + rust/kernel/types/for_lt.rs | 117 +++++++++++++++ rust/macros/for_lt.rs | 274 ++++++++++++++++++++++++++++++++++++ rust/macros/lib.rs | 12 ++ 5 files changed, 408 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..22b4518a115b --- /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 shorterned. +/// +/// 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 does not involved 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 refer 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..184c9dca1577 --- /dev/null +++ b/rust/macros/for_lt.rs @@ -0,0 +1,274 @@ +// 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; + fn has_macro(&self) -> 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; + } + } + } + + let mut visitor =3D HasLifetime(lt, false); + visitor.visit_type(self); + visitor.1 + } + + fn has_macro(&self) -> bool { + struct HasMacro(bool); + + impl<'ast> Visit<'ast> for HasMacro { + fn visit_macro(&mut self, _: &'ast syn::Macro) { + self.0 =3D true; + } + } + + let mut visitor =3D HasMacro(false); + visitor.visit_type(self); + visitor.0 + } +} + +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> (), + + // Macro invocations are opaque to proc macros; conservatively= require + // a compiler proof since we cannot determine lifetime usage. + Type::Macro(_) =3D> self.1.push(ty), + + // 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. + // + // Proc macros cannot expand macro invocations, so AST-level lifetime = replacement cannot + // see into them. When macros are present, use a WithLt trait projecti= on to let the + // compiler handle the substitution instead. + let ty_static: TokenStream =3D if ty.has_macro() { + quote!( + ::kernel::types::for_lt::WithLt< + #lifetime, Of =3D #ty + > as ::kernel::types::for_lt::WithLt<'static>>::Of + ) + } else { + let ty_static =3D ty.replace_lifetime( + &lifetime, + &Lifetime { + apostrophe: Span::mixed_site(), + ident: format_ident!("static"), + }, + ); + quote!(#ty_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 Sun May 24 19:33:20 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 D5AE039D3DB; Thu, 21 May 2026 23:41:51 +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=1779406917; cv=none; b=J/kl2FNGqzfH+ZrPvoyiYgduHSg43CJza1Jagh6PeU/vITSo4IYMiv0Lfvya8+wST97SS1s/yRlk7zaNmKpS63uBhlXqJqCGyngLerDypbHZ7tswGy5PKAJDXBD8Bij/ZDwxpJ/PiAO/qQJ5z2M9DL1Ah0xPDhakhwPTmHgc/IY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779406917; c=relaxed/simple; bh=t1xCuAf2IDbLGvLbYP55xYCp+E/EXrc7L51cvyq0km8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=CDTEgdJ9L8pts9zOi6OLuaylbdRqE+LFpB9yRpOxDuOFKqENQF9LqisyG9fXHm6BPUsb0/JkueFC1ToenhxL1VDACPXuY8nHD3j0ontdruNVfrRRsOIaG3bhBN7lpU8m+T2McqVfYnnabs0z8OpoMhlQoHkjS6QCC59CXv+ETsw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=CSO7LTO0; 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="CSO7LTO0" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 46F491F000E9; Thu, 21 May 2026 23:41:44 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1779406910; bh=Czfh5ydbOfGz6Q2n6/SdfnZJdUmQKxhQtqygkK8QwQU=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=CSO7LTO0oD0KU2pUKVtnzhHKBruRBowKSIRZI9Y28WCFHwqHNhYhnTVo+JQKOE2/J /ULi+MGZ4GG1huYHnlV9EPM+KAFI8FnLlN8/YcCE+T0SlAWcgbXMgS1ToQLrXZaSL3 dkohCBoDDfRlocUVDfiMfW8V7m/L7hZn/J/tyR4HW4lIeeuHBQmQeJvQJ1xZKNQvpz bTIb62LwRA8Blgc77yaWNuy6uORGSUd9DTbn4gKQrjSyY8yg12FT4qb5sFlUqEZAgR LiGoP/dJS92UnqfRcK7Y7jM/YWgqr6lUfwPrtvOFYjBlRBqudeLkT6tE4MCnx0IMWT gnbTww9rn+odA== 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 v4 22/27] rust: auxiliary: generalize Registration over ForLt Date: Fri, 22 May 2026 01:34:48 +0200 Message-ID: <20260521233501.1191842-23-dakr@kernel.org> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260521233501.1191842-1-dakr@kernel.org> References: <20260521233501.1191842-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. Signed-off-by: Danilo Krummrich Reviewed-by: Greg Kroah-Hartman --- 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 5591f97f12f7..edc4b50f54d8 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 Sun May 24 19:33:20 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 7318B383312; Thu, 21 May 2026 23:41:58 +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=1779406924; cv=none; b=IVYKnCPyIIbHvHkk1cD4bpBGCsJUubDKxxXYOA88aZqh2cqx1rSGRCb1a9yZmTAxlA164KUsgPgxLtY6EmIfmtRWyN1FDsCxG4zwhI0GH9Ej0/NASm2VxyzQQnF+XL8m5LUrI4kVpFGqpvSPWpL3m5mft1LbKwe0cz8PLArsRnQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779406924; c=relaxed/simple; bh=URv7kDky/fzF48yyZX8bZFxKK2Zco6+d0cntaCwf/Ds=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=pFM6zFeb9+u0jBAeMmssBGRpwB9s6etv/24JJscDfqsNwI/6YfmUeA1ZaUC0yIAaPIfGDBdf67izimZNCdO2f69WuI0E9qBsYFOqoSGDN29VklWGFM2eAW2XreIstW3wH7DGLskgY3yzsXG1D91wruer9Jl3lTI/ybGKAXJbo6c= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=T/AMtvU7; 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="T/AMtvU7" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 1C47D1F00A3F; Thu, 21 May 2026 23:41:50 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1779406917; bh=K3j4lL+2mHxp0flNXouCMSDh28DfNlEwKKwd9IHTneY=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=T/AMtvU7TEIn4q026laXEglQYz0gh9HbSnPY1WlGi9txqlikR/jJq2HXA+5B6etyf u02+XzLy7UXY8wvyvVLeBLsbBi4cxT29Ss4BpqDELTg4njoJ9JHLxACVxjDXMeCNuu Svqoi/LLDWurkwVK2Phtk6a1BzMTZi76s4c7diSvir0cIt57y7d3vn6VinK9FBwUqa vwowsKkh+vCk4WDgPKxmxeknikdunoxvNOdJBIRFmWAzZDjqyPCmbdLCnixiXJwVuO 8hWF/p2OPBlmAkllu3+zdLoPHcIuOL4NQLELdKf/ENX4GpSQAfu7/I+j2HSPxpcnoG LRalpVdJJ4VEQ== 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 v4 23/27] samples: rust: rust_driver_auxiliary: showcase lifetime-bound registration data Date: Fri, 22 May 2026 01:34:49 +0200 Message-ID: <20260521233501.1191842-24-dakr@kernel.org> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260521233501.1191842-1-dakr@kernel.org> References: <20260521233501.1191842-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 Signed-off-by: Danilo Krummrich Reviewed-by: Greg Kroah-Hartman --- 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 From nobody Sun May 24 19:33:20 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 BEE8537CD44; Thu, 21 May 2026 23:42: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=1779406932; cv=none; b=da0XiiOmL6Hhyh9nWsUyvsaHS68SVS4uUdiYgIZ/JGOscuIdnlKcGDFJIPN2UOX6/tVPNl6QGWAF0Ve+rZeDIa8NV9Qsx+WG6T7rGj/5jyuB4ZP55WSVdIupWiCZnl3T6DAJDZzKzjGObz6CwHacbS6k0bzReICAAhcShBd10+I= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779406932; c=relaxed/simple; bh=CuQ7qIU+BHd6reTZImgtyilW90DC+YtbmxWxQx8ToF8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=kE+tH1cyhOLwUZN+O+ZGDUld9HlySZcVlBQovhTOWvBcqLiV46yyqFaOJuflDYr51xZhHc5iBKBGoa8hDHZ2LjP0HNdJc95YP4sjfGHkdSbCpGxLuUPG+MtsuMC19CF4WjN7XqRTazfwGvuPwX3cq4h1YBRc8Xn9sRKCeuPHMr0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=kpJT7zq9; 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="kpJT7zq9" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 1E2A01F000E9; Thu, 21 May 2026 23:41:57 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1779406924; bh=hpkmLWMZxfJfm6p78iGk3YLCLFrtdb80RZEsvdpd5WE=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=kpJT7zq9EiSpL8AeAL/YALB24BOzxueNibg6wF2gVxtTyDErrPm2lSGhdodnaMCZq BavfL6jdbfsW4H6SwilwsEzygY4JZFQ+x8R4bGJzGliaJwJNeHZlGZJMjOQ95+uuI2 7gIsBl53SDHktbkz0/KhS3MFiQ/AGsiDIwX08h7nFn7fWB91vQ6AJ4QoCWehXZ/PHS 5DbZoXVMcKiOZbdXUAne914i4inTL46BdOes/rt7K04L2f1sp4Dp2eZFvWGjZ7vCeR QJDkISQOwZXwPKupYr4Zm3kP2awRBGOs2uGBXIbi7VOa4rMb91XNCv5ZeSrUbur1vT 6X/l/UYBlU70Q== 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 REF v4 24/27] gpu: nova-core: use lifetime for Bar Date: Fri, 22 May 2026 01:34:50 +0200 Message-ID: <20260521233501.1191842-25-dakr@kernel.org> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260521233501.1191842-1-dakr@kernel.org> References: <20260521233501.1191842-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" Take advantage of the lifetime-parameterized pci::Bar<'bound> to hold the BAR mapping directly in NovaCore<'bound>, and pass a borrowed reference to Gpu<'bound>. This eliminates the Arc> indirection, removes runtime revocation checks for BAR access, and simplifies Gpu::unbind(). Signed-off-by: Danilo Krummrich Reviewed-by: Greg Kroah-Hartman --- drivers/gpu/nova-core/driver.rs | 32 +++++++++++++++----------------- drivers/gpu/nova-core/gpu.rs | 33 +++++++++++++-------------------- 2 files changed, 28 insertions(+), 37 deletions(-) diff --git a/drivers/gpu/nova-core/driver.rs b/drivers/gpu/nova-core/driver= .rs index d3f2245ba2e0..d4cf4379ee87 100644 --- a/drivers/gpu/nova-core/driver.rs +++ b/drivers/gpu/nova-core/driver.rs @@ -13,12 +13,9 @@ }, prelude::*, sizes::SZ_16M, - sync::{ - atomic::{ - Atomic, - Relaxed, // - }, - Arc, + sync::atomic::{ + Atomic, + Relaxed, // }, types::ForLt, }; @@ -31,7 +28,8 @@ #[pin_data] pub(crate) struct NovaCore<'bound> { #[pin] - pub(crate) gpu: Gpu, + pub(crate) gpu: Gpu<'bound>, + bar: pci::Bar<'bound, BAR0_SIZE>, #[allow(clippy::type_complexity)] _reg: auxiliary::Registration<'bound, ForLt!(())>, } @@ -48,7 +46,7 @@ pub(crate) struct NovaCore<'bound> { // DMA addresses. These systems should be quite rare. const GPU_DMA_BITS: u32 =3D 47; =20 -pub(crate) type Bar0 =3D pci::Bar<'static, BAR0_SIZE>; +pub(crate) type Bar0 =3D kernel::io::Mmio; =20 kernel::pci_device_table!( PCI_TABLE, @@ -95,14 +93,14 @@ fn probe<'bound>( // other threads of execution. unsafe { pdev.dma_set_mask_and_coherent(DmaMask::new::())? }; =20 - let bar =3D Arc::new( - pdev.iomap_region_sized::(0, c"nova-core/bar0")? - .into_devres()?, - GFP_KERNEL, - )?; - Ok(try_pin_init!(NovaCore { - gpu <- Gpu::new(pdev, bar.clone(), bar.access(pdev.as_ref(= ))?), + bar: pdev.iomap_region_sized::(0, c"nova-core/b= ar0")?, + // TODO: Use `&bar` self-referential pin-init syntax once = available. + // + // SAFETY: `bar` is initialized before this expression is = evaluated + // (`try_pin_init!()` initializes fields in declaration or= der), lives at a pinned + // stable address, and is dropped after `gpu` (struct fiel= d drop order). + gpu <- Gpu::new(pdev, unsafe { &*core::ptr::from_ref(bar) = }), _reg: auxiliary::Registration::new( pdev.as_ref(), c"nova-drm", @@ -116,7 +114,7 @@ fn probe<'bound>( }) } =20 - fn unbind<'bound>(pdev: &'bound pci::Device>, this: Pin<&Self= ::Data<'bound>>) { - this.gpu.unbind(pdev.as_ref()); + fn unbind<'bound>(_pdev: &'bound pci::Device>, this: Pin<&Sel= f::Data<'bound>>) { + this.gpu.unbind(); } } diff --git a/drivers/gpu/nova-core/gpu.rs b/drivers/gpu/nova-core/gpu.rs index 4ffb506342a9..8d2d6b0a917b 100644 --- a/drivers/gpu/nova-core/gpu.rs +++ b/drivers/gpu/nova-core/gpu.rs @@ -2,13 +2,11 @@ =20 use kernel::{ device, - devres::Devres, fmt, io::Io, num::Bounded, pci, - prelude::*, - sync::Arc, // + prelude::*, // }; =20 use crate::{ @@ -224,10 +222,10 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Res= ult { =20 /// Structure holding the resources required to operate the GPU. #[pin_data] -pub(crate) struct Gpu { +pub(crate) struct Gpu<'gpu> { spec: Spec, - /// MMIO mapping of PCI BAR 0 - bar: Arc>, + /// MMIO mapping of PCI BAR 0. + bar: &'gpu Bar0, /// System memory page required for flushing all pending GPU-side memo= ry writes done through /// PCIE into system memory, via sysmembar (A GPU-initiated HW memory-= barrier operation). sysmem_flush: SysmemFlush, @@ -240,12 +238,11 @@ pub(crate) struct Gpu { gsp: Gsp, } =20 -impl Gpu { - pub(crate) fn new<'a>( - pdev: &'a pci::Device, - devres_bar: Arc>, - bar: &'a Bar0, - ) -> impl PinInit + 'a { +impl<'gpu> Gpu<'gpu> { + pub(crate) fn new( + pdev: &'gpu pci::Device, + bar: &'gpu Bar0, + ) -> impl PinInit + 'gpu { try_pin_init!(Self { spec: Spec::new(pdev.as_ref(), bar).inspect(|spec| { dev_info!(pdev,"NVIDIA ({})\n", spec); @@ -257,6 +254,8 @@ pub(crate) fn new<'a>( .inspect_err(|_| dev_err!(pdev, "GFW boot did not comp= lete\n"))?; }, =20 + bar, + sysmem_flush: SysmemFlush::register(pdev.as_ref(), bar, spec.c= hipset)?, =20 gsp_falcon: Falcon::new( @@ -270,19 +269,13 @@ pub(crate) fn new<'a>( gsp <- Gsp::new(pdev), =20 _: { gsp.boot(pdev, bar, spec.chipset, gsp_falcon, sec2_falcon= )? }, - - bar: devres_bar, }) } =20 /// 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>) { - kernel::warn_on!(self - .bar - .access(dev) - .inspect(|bar| self.sysmem_flush.unregister(bar)) - .is_err()); + pub(crate) fn unbind(&self) { + self.sysmem_flush.unregister(self.bar); } } --=20 2.54.0 From nobody Sun May 24 19:33:20 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 B9EAF37DEB9; Thu, 21 May 2026 23:42:12 +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=1779406939; cv=none; b=jp8zpjU/gFMpIaGv1mj6n429F91qwtI5lm3UU3ipJOcZZlHM/b4eCPp9NEut947+Ka1XaYsDZ8httVT71nUt5Gz6PqfR1w4d/fMawZRTTHB9BrNycgaRZi3Nd5U/A6N+TihDI9Gn5lv5hl9vEgaTGywDkzY76w+511kzPRCj+KM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779406939; c=relaxed/simple; bh=9TiMPMFi9DqkpvtnjcM0UBtE0MRykgEWhUsOuQopYuI=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=WAA1bkD0vKIM29bWta9Hcbi2KxcnL1MuOKgBOKwgVxZsQWoXDzTu4NtDH7JPHWrMPUJw4E5odO0rdbUYIYvUHyPI83dha7VXdxDwm8jJktp3/3HVYLxQ8xQ+KPz25NuH7g9153jHZB8Ss1mjz0DZ4mLpoOubXwWDV66MNsBhLls= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=ISmCq4b9; 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="ISmCq4b9" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 130BE1F00A3C; Thu, 21 May 2026 23:42:04 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1779406931; bh=dt2mnOGqU/dqsuuyNJuAquOOYfNTnXCcO5ozbuHU/2c=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=ISmCq4b9VzLkR0djpnh6Fmawpyk8xNpakXw7NeNDJ3TJiol7XZ+aYh+98jtzXjO2q I1Oov7EHyhGVxh4FLSoCSKVIJfeahDEzWHwDVPFbJsyPJoqhZtxHKHDOdx/SmBmk1M J42rYG2jP0CuWMAYvafiLcgmtgCfuGY1IpTEbZByMszZsJU5IKJjiJ4UQlZMRLu5p7 ul0pD7/uQ6nkHYmzOZQPyqx1lraJRzqisbTV7XXezAhPAxMGjMXSu4QzdaoY5/U+Z4 XmM5/L10wpsekjXKskd3l0MqKITM+V8EsoryqS93IZ28xeMPDonHdPqUjB7BucVHpe Vzs7p6ZwRu7jg== 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 REF v4 25/27] gpu: nova-core: unregister sysmem flush page from Drop Date: Fri, 22 May 2026 01:34:51 +0200 Message-ID: <20260521233501.1191842-26-dakr@kernel.org> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260521233501.1191842-1-dakr@kernel.org> References: <20260521233501.1191842-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 SysmemFlush can borrow the Bar via HRT lifetime, store a &'bound Bar0 reference and implement Drop to automatically unregister the sysmem flush page. This removes the need for manual unregister() calls and the Gpu::unbind() method. Reported-by: Eliot Courtney Closes: https://lore.kernel.org/all/20260409-fix-systemflush-v1-1-a1d6c968f= 17c@nvidia.com/ Fixes: 6554ad65b589 ("gpu: nova-core: register sysmem flush page") Signed-off-by: Danilo Krummrich Reviewed-by: Greg Kroah-Hartman --- drivers/gpu/nova-core/driver.rs | 4 ---- drivers/gpu/nova-core/fb.rs | 22 ++++++++++------------ drivers/gpu/nova-core/gpu.rs | 9 +-------- 3 files changed, 11 insertions(+), 24 deletions(-) diff --git a/drivers/gpu/nova-core/driver.rs b/drivers/gpu/nova-core/driver= .rs index d4cf4379ee87..cff5034c2dcd 100644 --- a/drivers/gpu/nova-core/driver.rs +++ b/drivers/gpu/nova-core/driver.rs @@ -113,8 +113,4 @@ fn probe<'bound>( })) }) } - - fn unbind<'bound>(_pdev: &'bound pci::Device>, this: Pin<&Sel= f::Data<'bound>>) { - this.gpu.unbind(); - } } diff --git a/drivers/gpu/nova-core/fb.rs b/drivers/gpu/nova-core/fb.rs index bdd5eed760e1..64fe5f27f41e 100644 --- a/drivers/gpu/nova-core/fb.rs +++ b/drivers/gpu/nova-core/fb.rs @@ -46,21 +46,20 @@ /// Because of this, the sysmem flush memory page must be registered as ea= rly as possible during /// driver initialization, and before any falcon is reset. /// -/// Users are responsible for manually calling [`Self::unregister`] before= dropping this object, -/// otherwise the GPU might still use it even after it has been freed. -pub(crate) struct SysmemFlush { +pub(crate) struct SysmemFlush<'sys> { /// Chipset we are operating on. chipset: Chipset, device: ARef, + bar: &'sys Bar0, /// Keep the page alive as long as we need it. page: CoherentHandle, } =20 -impl SysmemFlush { +impl<'sys> SysmemFlush<'sys> { /// Allocate a memory page and register it as the sysmem flush page. pub(crate) fn register( dev: &device::Device, - bar: &Bar0, + bar: &'sys Bar0, chipset: Chipset, ) -> Result { let page =3D CoherentHandle::alloc(dev, kernel::page::PAGE_SIZE, G= FP_KERNEL)?; @@ -70,19 +69,18 @@ pub(crate) fn register( Ok(Self { chipset, device: dev.into(), + bar, page, }) } +} =20 - /// Unregister the managed sysmem flush page. - /// - /// In order to gracefully tear down the GPU, users must make sure to = call this method before - /// dropping the object. - pub(crate) fn unregister(&self, bar: &Bar0) { +impl Drop for SysmemFlush<'_> { + fn drop(&mut self) { let hal =3D hal::fb_hal(self.chipset); =20 - if hal.read_sysmem_flush_page(bar) =3D=3D self.page.dma_handle() { - let _ =3D hal.write_sysmem_flush_page(bar, 0).inspect_err(|e| { + if hal.read_sysmem_flush_page(self.bar) =3D=3D self.page.dma_handl= e() { + let _ =3D hal.write_sysmem_flush_page(self.bar, 0).inspect_err= (|e| { dev_warn!( &self.device, "failed to unregister sysmem flush page: {:?}\n", diff --git a/drivers/gpu/nova-core/gpu.rs b/drivers/gpu/nova-core/gpu.rs index 8d2d6b0a917b..c907d11580d6 100644 --- a/drivers/gpu/nova-core/gpu.rs +++ b/drivers/gpu/nova-core/gpu.rs @@ -228,7 +228,7 @@ pub(crate) struct Gpu<'gpu> { bar: &'gpu Bar0, /// System memory page required for flushing all pending GPU-side memo= ry writes done through /// PCIE into system memory, via sysmembar (A GPU-initiated HW memory-= barrier operation). - sysmem_flush: SysmemFlush, + sysmem_flush: SysmemFlush<'gpu>, /// GSP falcon instance, used for GSP boot up and cleanup. gsp_falcon: Falcon, /// SEC2 falcon instance, used for GSP boot up and cleanup. @@ -271,11 +271,4 @@ pub(crate) fn new( _: { gsp.boot(pdev, bar, spec.chipset, gsp_falcon, sec2_falcon= )? }, }) } - - /// 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) { - self.sysmem_flush.unregister(self.bar); - } } --=20 2.54.0 From nobody Sun May 24 19:33:20 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 E5A2637B01A; Thu, 21 May 2026 23:42:19 +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=1779406942; cv=none; b=SDe6yMhQXgPVZs99KAlXVDjUTG1TiMhymPp6ZFepjvoPOZ8C0hAs2SRUEvccCccVzo4cvh5err2zwKE0gBbsqsNLQOrfXR6w2hot9nXrNlIQlpXS1sY7gMKnYr2bTTorTGDU0EvDp8vqCgnjHLHgqQYyGj25C2KmZhxUechC4kU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779406942; c=relaxed/simple; bh=30+CXHKZzbMY6HTqt2CGaTc/27ir1Eup+a00Q2x9++c=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Qd/pesi0VRBuO6t3NbdieQfneeCI04CYH5V3SZOsqG77avQha4sPuDs5sGAEkXyTupKtvZSrgOykN+PdqcNNP7UGrxncQKczZnB8ArhmShXmCyrihuqRm/hsdf4OYtGz8GgPa+PE9djIlLvvKhXOXI9cJ4wrfM/111SGARFhhbM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Mjjb3pTF; 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="Mjjb3pTF" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 152301F00A3B; Thu, 21 May 2026 23:42:11 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1779406938; bh=EUQ1dgH+Jyb+iJ0OBBSC5/6K6i+s/brVe5Q1aK+jsiA=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=Mjjb3pTFTRHPO4mbx3Vh8ag9znkvUUe4BtoO8mKwMGVzyI7n3hmU1X7Aw+hWWP2L9 8enW+0CfNr8WuhyaEhYmspiUpmZVjIQiDwOjADaF40QJpRhwOgNBwpa6GR+WMM22x6 69OskBld1hY/idl8L81q5wULVGwHanbXsraf2fPa61qF8sMPL8JrpLMTbd7vmZe3IP yIM7arsDv017pwldXss0Y8jldP8YfXFR7VpAaeKGeOKi5wf5SE55svl2FbFZXSw1L6 +/8xNhNAytYBOhXEXOAS3eWDIswMxnm8pLP46CKxu+vbiyw+Vhgd02ytijb2LGups0 GRUHPF59ecDfw== 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 REF v4 26/27] gpu: nova-core: replace ARef with &'bound Device in SysmemFlush Date: Fri, 22 May 2026 01:34:52 +0200 Message-ID: <20260521233501.1191842-27-dakr@kernel.org> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260521233501.1191842-1-dakr@kernel.org> References: <20260521233501.1191842-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 SysmemFlush is lifetime-parameterized, the ARef is unnecessary -- a plain &'bound Device reference suffices. Signed-off-by: Danilo Krummrich Reviewed-by: Greg Kroah-Hartman --- drivers/gpu/nova-core/fb.rs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/nova-core/fb.rs b/drivers/gpu/nova-core/fb.rs index 64fe5f27f41e..a1c5ccd0a534 100644 --- a/drivers/gpu/nova-core/fb.rs +++ b/drivers/gpu/nova-core/fb.rs @@ -15,8 +15,7 @@ Alignable, Alignment, // }, - sizes::*, - sync::aref::ARef, // + sizes::*, // }; =20 use crate::{ @@ -49,7 +48,7 @@ pub(crate) struct SysmemFlush<'sys> { /// Chipset we are operating on. chipset: Chipset, - device: ARef, + device: &'sys device::Device, bar: &'sys Bar0, /// Keep the page alive as long as we need it. page: CoherentHandle, @@ -58,7 +57,7 @@ pub(crate) struct SysmemFlush<'sys> { impl<'sys> SysmemFlush<'sys> { /// Allocate a memory page and register it as the sysmem flush page. pub(crate) fn register( - dev: &device::Device, + dev: &'sys device::Device, bar: &'sys Bar0, chipset: Chipset, ) -> Result { @@ -68,7 +67,7 @@ pub(crate) fn register( =20 Ok(Self { chipset, - device: dev.into(), + device: dev, bar, page, }) --=20 2.54.0 From nobody Sun May 24 19:33:20 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 AD4BA3A6F06; Thu, 21 May 2026 23:42:26 +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=1779406951; cv=none; b=Q37469vBDT722ereW7Q7AJtNbtzTSbaQ88F4tyGni/Vzj6I89xYKUUdCylEkCTRmwQm86slPIJvIEF6V/2EStU1T0d/0Dsr9uitoTihavVDtm/tA7vxabw0f+bMiiDXKvBT3nEVRSbAYKVCKyON9R9UWsyX3Fr5DaVxytEgWmnc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779406951; c=relaxed/simple; bh=1pqlI0q50ZlsodfxIO4XBVa2HMRipR+UTaeQVIkQ/0c=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=f+6FbgJBrMsiqZr+p9QwNSdt6LRD3qk2Rd/BadvsOVWdVpYto5kUfcYG4gyjrkCbd46Oo8+7D4ILFsVKSp4Ol32yNNFt0UmYJO6lQCEHnCmcAKwcVoHaMRdAyC7WI3dDfvfpgVRT8sVkQG/SBIRr0Uy4ybfH74BvPYaFH5mj+zg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=VqdUczTA; 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="VqdUczTA" Received: by smtp.kernel.org (Postfix) with ESMTPSA id E059E1F000E9; Thu, 21 May 2026 23:42:18 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1779406945; bh=RBPPIslRfw5zXe9mto9RQQTrjgY7NH52CbC9tVuj2I8=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=VqdUczTAqWf26hDVbpNAFCMYsoUqwlYyAQCIyItdsy+U7mejKIZnNXq2jajlsqrIg +/6pOmZxDgcfURNUCE2JbwjhFQgZZyTvuCgjO/hqVhCw6fbQ1PSFN9y7OLH2+nQ6bX UnOXI2FFDd4UyyD/Dj153fdKNpPhQCBkKz91nle7eAK/FQRNT5jy7LlPiMQ7R5Mcyu xqoJU9Lx9HlbNg8anQdQ1oS6O2YkfXTSStoZPQS/VbeAxkUc7P76QdVuuUWGc25IRO cYKJpVp6a0RkbErXJQoES9jeQwjDQk+mvpDwKu2wc/kJYgqkBKvlAa7zUtyMFrk78a NKgHvKjH6OB+Q== 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 REF v4 27/27] gpu: drm: tyr: use lifetime for IoMem Date: Fri, 22 May 2026 01:34:53 +0200 Message-ID: <20260521233501.1191842-28-dakr@kernel.org> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260521233501.1191842-1-dakr@kernel.org> References: <20260521233501.1191842-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" Take advantage of the lifetime-parameterized IoMem<'bound> to use the memory mapping directly during probe, eliminating the Arc> indirection. Since the IoMem is only used during probe, this also simplifies Register::read/write to be infallible -- the Devres access check is no longer needed, so reads return u32 directly and writes return (). Signed-off-by: Danilo Krummrich Reviewed-by: Greg Kroah-Hartman --- Not yet updated to Tyr using the register!() macro, but probably good enoug= h for reference. --- drivers/gpu/drm/tyr/driver.rs | 14 ++++---- drivers/gpu/drm/tyr/gpu.rs | 62 +++++++++++++++++------------------ drivers/gpu/drm/tyr/regs.rs | 21 +++--------- 3 files changed, 41 insertions(+), 56 deletions(-) diff --git a/drivers/gpu/drm/tyr/driver.rs b/drivers/gpu/drm/tyr/driver.rs index 04f83fcf0937..d0aa42129530 100644 --- a/drivers/gpu/drm/tyr/driver.rs +++ b/drivers/gpu/drm/tyr/driver.rs @@ -10,7 +10,6 @@ Core, Device, // }, - devres::Devres, drm, drm::ioctl, io::poll, @@ -23,7 +22,6 @@ sizes::SZ_2M, sync::{ aref::ARef, - Arc, Mutex, // }, time, // @@ -37,7 +35,7 @@ regs, // }; =20 -pub(crate) type IoMem =3D kernel::io::mem::IoMem<'static, SZ_2M>; +pub(crate) type IoMem =3D kernel::io::Mmio; =20 pub(crate) struct TyrDrmDriver; =20 @@ -65,11 +63,11 @@ pub(crate) struct TyrDrmDeviceData { pub(crate) gpu_info: GpuInfo, } =20 -fn issue_soft_reset(dev: &Device, iomem: &Devres) -> Result { - regs::GPU_CMD.write(dev, iomem, regs::GPU_CMD_SOFT_RESET)?; +fn issue_soft_reset(dev: &Device, iomem: &IoMem) -> Result { + regs::GPU_CMD.write(iomem, regs::GPU_CMD_SOFT_RESET); =20 poll::read_poll_timeout( - || regs::GPU_IRQ_RAWSTAT.read(dev, iomem), + || Ok(regs::GPU_IRQ_RAWSTAT.read(iomem)), |status| *status & regs::GPU_IRQ_RAWSTAT_RESET_COMPLETED !=3D 0, time::Delta::from_millis(1), time::Delta::from_millis(100), @@ -110,12 +108,12 @@ 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::new(request.iomap_sized::()?.into_devres= ()?, GFP_KERNEL)?; + let iomem =3D request.iomap_sized::()?; =20 issue_soft_reset(pdev.as_ref(), &iomem)?; gpu::l2_power_on(pdev.as_ref(), &iomem)?; =20 - let gpu_info =3D GpuInfo::new(pdev.as_ref(), &iomem)?; + let gpu_info =3D GpuInfo::new(&iomem); gpu_info.log(pdev); =20 let platform: ARef =3D pdev.into(); diff --git a/drivers/gpu/drm/tyr/gpu.rs b/drivers/gpu/drm/tyr/gpu.rs index a88775160f98..bb0473c85bf7 100644 --- a/drivers/gpu/drm/tyr/gpu.rs +++ b/drivers/gpu/drm/tyr/gpu.rs @@ -10,7 +10,6 @@ Bound, Device, // }, - devres::Devres, io::poll, platform, prelude::*, @@ -35,37 +34,36 @@ pub(crate) struct GpuInfo(pub(crate) uapi::drm_panthor_gpu_info); =20 impl GpuInfo { - pub(crate) fn new(dev: &Device, iomem: &Devres) -> Resul= t { - let gpu_id =3D regs::GPU_ID.read(dev, iomem)?; - let csf_id =3D regs::GPU_CSF_ID.read(dev, iomem)?; - let gpu_rev =3D regs::GPU_REVID.read(dev, iomem)?; - let core_features =3D regs::GPU_CORE_FEATURES.read(dev, iomem)?; - let l2_features =3D regs::GPU_L2_FEATURES.read(dev, iomem)?; - let tiler_features =3D regs::GPU_TILER_FEATURES.read(dev, iomem)?; - let mem_features =3D regs::GPU_MEM_FEATURES.read(dev, iomem)?; - let mmu_features =3D regs::GPU_MMU_FEATURES.read(dev, iomem)?; - let thread_features =3D regs::GPU_THREAD_FEATURES.read(dev, iomem)= ?; - let max_threads =3D regs::GPU_THREAD_MAX_THREADS.read(dev, iomem)?; - let thread_max_workgroup_size =3D regs::GPU_THREAD_MAX_WORKGROUP_S= IZE.read(dev, iomem)?; - let thread_max_barrier_size =3D regs::GPU_THREAD_MAX_BARRIER_SIZE.= read(dev, iomem)?; - let coherency_features =3D regs::GPU_COHERENCY_FEATURES.read(dev, = iomem)?; - - let texture_features =3D regs::GPU_TEXTURE_FEATURES0.read(dev, iom= em)?; - - let as_present =3D regs::GPU_AS_PRESENT.read(dev, iomem)?; - - let shader_present =3D u64::from(regs::GPU_SHADER_PRESENT_LO.read(= dev, iomem)?); + pub(crate) fn new(iomem: &IoMem) -> Self { + let gpu_id =3D regs::GPU_ID.read(iomem); + let csf_id =3D regs::GPU_CSF_ID.read(iomem); + let gpu_rev =3D regs::GPU_REVID.read(iomem); + let core_features =3D regs::GPU_CORE_FEATURES.read(iomem); + let l2_features =3D regs::GPU_L2_FEATURES.read(iomem); + let tiler_features =3D regs::GPU_TILER_FEATURES.read(iomem); + let mem_features =3D regs::GPU_MEM_FEATURES.read(iomem); + let mmu_features =3D regs::GPU_MMU_FEATURES.read(iomem); + let thread_features =3D regs::GPU_THREAD_FEATURES.read(iomem); + let max_threads =3D regs::GPU_THREAD_MAX_THREADS.read(iomem); + let thread_max_workgroup_size =3D regs::GPU_THREAD_MAX_WORKGROUP_S= IZE.read(iomem); + let thread_max_barrier_size =3D regs::GPU_THREAD_MAX_BARRIER_SIZE.= read(iomem); + let coherency_features =3D regs::GPU_COHERENCY_FEATURES.read(iomem= ); + + let texture_features =3D regs::GPU_TEXTURE_FEATURES0.read(iomem); + + let as_present =3D regs::GPU_AS_PRESENT.read(iomem); + + let shader_present =3D u64::from(regs::GPU_SHADER_PRESENT_LO.read(= iomem)); let shader_present =3D - shader_present | u64::from(regs::GPU_SHADER_PRESENT_HI.read(de= v, iomem)?) << 32; + shader_present | u64::from(regs::GPU_SHADER_PRESENT_HI.read(io= mem)) << 32; =20 - let tiler_present =3D u64::from(regs::GPU_TILER_PRESENT_LO.read(de= v, iomem)?); - let tiler_present =3D - tiler_present | u64::from(regs::GPU_TILER_PRESENT_HI.read(dev,= iomem)?) << 32; + let tiler_present =3D u64::from(regs::GPU_TILER_PRESENT_LO.read(io= mem)); + let tiler_present =3D tiler_present | u64::from(regs::GPU_TILER_PR= ESENT_HI.read(iomem)) << 32; =20 - let l2_present =3D u64::from(regs::GPU_L2_PRESENT_LO.read(dev, iom= em)?); - let l2_present =3D l2_present | u64::from(regs::GPU_L2_PRESENT_HI.= read(dev, iomem)?) << 32; + let l2_present =3D u64::from(regs::GPU_L2_PRESENT_LO.read(iomem)); + let l2_present =3D l2_present | u64::from(regs::GPU_L2_PRESENT_HI.= read(iomem)) << 32; =20 - Ok(Self(uapi::drm_panthor_gpu_info { + Self(uapi::drm_panthor_gpu_info { gpu_id, gpu_rev, csf_id, @@ -88,7 +86,7 @@ pub(crate) fn new(dev: &Device, iomem: &Devres) -> Result { core_features, pad: 0, gpu_features: 0, - })) + }) } =20 pub(crate) fn log(&self, pdev: &platform::Device) { @@ -208,11 +206,11 @@ fn from(value: u32) -> Self { } =20 /// Powers on the l2 block. -pub(crate) fn l2_power_on(dev: &Device, iomem: &Devres) -> R= esult { - regs::L2_PWRON_LO.write(dev, iomem, 1)?; +pub(crate) fn l2_power_on(dev: &Device, iomem: &IoMem) -> Result { + regs::L2_PWRON_LO.write(iomem, 1); =20 poll::read_poll_timeout( - || regs::L2_READY_LO.read(dev, iomem), + || Ok(regs::L2_READY_LO.read(iomem)), |status| *status =3D=3D 1, Delta::from_millis(1), Delta::from_millis(100), diff --git a/drivers/gpu/drm/tyr/regs.rs b/drivers/gpu/drm/tyr/regs.rs index 611870c2e6af..0881b3812afd 100644 --- a/drivers/gpu/drm/tyr/regs.rs +++ b/drivers/gpu/drm/tyr/regs.rs @@ -7,16 +7,7 @@ // does. #![allow(dead_code)] =20 -use kernel::{ - bits::bit_u32, - device::{ - Bound, - Device, // - }, - devres::Devres, - io::Io, - prelude::*, // -}; +use kernel::{bits::bit_u32, io::Io}; =20 use crate::driver::IoMem; =20 @@ -29,15 +20,13 @@ =20 impl Register { #[inline] - pub(crate) fn read(&self, dev: &Device, iomem: &Devres) = -> Result { - let value =3D (*iomem).access(dev)?.read32(OFFSET); - Ok(value) + pub(crate) fn read(&self, iomem: &IoMem) -> u32 { + iomem.read32(OFFSET) } =20 #[inline] - pub(crate) fn write(&self, dev: &Device, iomem: &Devres,= value: u32) -> Result { - (*iomem).access(dev)?.write32(value, OFFSET); - Ok(()) + pub(crate) fn write(&self, iomem: &IoMem, value: u32) { + iomem.write32(value, OFFSET); } } =20 --=20 2.54.0