From nobody Mon Sep 28 23:53:10 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 69A0E32A3FF; Fri, 14 Aug 2026 23:09:35 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786748976; cv=none; b=dYnc78Xj6ouWEBE0nvIhuwH35JnH/mblGlV+XkqnfEBEH7lhB2CC5aGS3wT0oV4AcLbvU652HYSxzRlfj67FZHQjDIepaa4NFxEJeU5Yu0sBCM2GSW4E0oxZ3yRLiVRkOGQXdKIN0pofBECujV/t087AMKHFy8ZIJzqm92RGI/g= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786748976; c=relaxed/simple; bh=gCnahOTTRZRBaWHHJ3aQwZKAoo/pcqlfTs0ymcDEam0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Q8DcOlWUqWvfoXZOGd4y5LOP4R65T9+4gVzuOu1VhN6AciWT8FsTU6GORGETI7z5YYNu11DEJdq12hufEO4awoskLm/8h5JD6CofSYnwaZjhzPaEgkUzuOEs40B9//yflUC7rPS7xst54mgbDPO9iEzB88Y7b37xhNDAnUO3M88= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=kmnOytQh; 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="kmnOytQh" Received: by smtp.kernel.org (Postfix) with ESMTPSA id C9D451F00A3A; Fri, 14 Aug 2026 23:09:30 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1786748975; bh=CcCMjsoinR53+ljjs1ik9JtiuPEjroGPVh8Wrd/zOaI=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=kmnOytQhQyltB48W9oOLQZc9qNqvuyY0HwPA39ujoEUbCSQ5fc8G/oFbx77d0lL3Y ctbxEOoceFhjC2s3GCFtEuD258gY/7NvIZUXIHGB5UKJSiUVp99OSJmqss3OpEy+nq xuE0DVyMrnX7KhT6RIMfDGb77r3nKphlAXAgJMJBdfYkCEjMQZ6q5u7fDhlsQofZIa vJzT2+/DGmij2+FNzhiU5UKK7R2hW4u2cnxyTnI3UC+nex85tM1caLGUKh8GNfBfEX YN2qtoi5qkjGsXf/iAzkC+bezZYi/Xsnreqriof5/i74DUGFVCX1pqR30t0RcHr+hp YO2QTH459On6w== From: Danilo Krummrich To: dakr@kernel.org, aliceryhl@google.com, acourbot@nvidia.com, daniel.almeida@collabora.com, ojeda@kernel.org, boqun@kernel.org, gary@garyguo.net, bjorn3_gh@protonmail.com, lossin@kernel.org, a.hindborg@kernel.org, tmgross@umich.edu, tamird@kernel.org, work@onurozkan.dev, brauner@kernel.org, lyude@redhat.com, j@jananu.net, alvin.sun@linux.dev, deborah.brouwer@collabora.com, laura.nao@collabora.com, beata.michalska@arm.com Cc: nova-gpu@lists.linux.dev, dri-devel@lists.freedesktop.org, rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH 1/7] rust: drm: rename Ioctl device context to Userspace Date: Sat, 15 Aug 2026 01:08:59 +0200 Message-ID: <20260814230923.1292966-2-dakr@kernel.org> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260814230923.1292966-1-dakr@kernel.org> References: <20260814230923.1292966-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" The Ioctl DeviceContext typestate represents a device that has been registered with userspace at some point. This context is not specific to ioctl dispatch; it applies equally to GEM handle callbacks, mmap, fdinfo, and any other operation triggered by userspace on a registered device. Rename it to Userspace to accurately reflect its semantics. Signed-off-by: Danilo Krummrich --- rust/kernel/drm/device.rs | 21 ++++++++++++--------- rust/kernel/drm/ioctl.rs | 12 ++++++------ rust/kernel/drm/mod.rs | 2 +- 3 files changed, 19 insertions(+), 16 deletions(-) diff --git a/rust/kernel/drm/device.rs b/rust/kernel/drm/device.rs index f43c6887ad23..be83287fe161 100644 --- a/rust/kernel/drm/device.rs +++ b/rust/kernel/drm/device.rs @@ -79,12 +79,12 @@ macro_rules! drm_legacy_fields { /// /// - [`Normal`]: The general-purpose, reference-counted context. A [`Devi= ce`] in this context may /// or may not be registered with userspace. -/// - [`Ioctl`]: The device has been registered with userspace at some poi= nt; used in ioctl -/// dispatch context. +/// - [`Userspace`]: The device has been registered with userspace at some= point; used in +/// callbacks triggered by userspace operations. /// - [`Registered`]: The device is currently registered with userspace an= d the parent bus device /// is bound. /// -/// Both `Device` and `Device` dereference to `De= vice` ([`Normal`]), +/// Both `Device` and `Device` dereference to= `Device` ([`Normal`]), /// so any method available on a [`Normal`] device is also available in th= e other contexts. pub trait DeviceContext: Sealed + Send + Sync + 'static {} =20 @@ -120,14 +120,17 @@ impl DeviceContext for Registered {} /// unregistering or already unregistered. `drm_dev_enter()` can guard aga= inst this, ensuring the /// device remains registered for the duration of the critical section. /// +/// This context is used for all callbacks triggered by userspace operatio= ns: ioctls, GEM handle +/// management, mmap, fdinfo, etc. +/// /// # Invariants /// /// A [`Device`] in this context has been registered with userspace via `d= rm_dev_register()` at /// some point. -pub struct Ioctl; +pub struct Userspace; =20 -impl Sealed for Ioctl {} -impl DeviceContext for Ioctl {} +impl Sealed for Userspace {} +impl DeviceContext for Userspace {} =20 /// A [`Device`] which is known at compile-time to be unregistered with us= erspace. /// @@ -343,7 +346,7 @@ pub(crate) unsafe fn assume_ctx(= &self) -> &Device Device { +impl Device { /// Guard against the parent bus device being unbound. /// /// Returns a [`RegistrationGuard`] if the device has not been unplugg= ed, [`None`] otherwise. @@ -466,12 +469,12 @@ fn deref(&self) -> &Self::Target { } } =20 -impl Deref for Device { +impl Deref for Device { type Target =3D Device; =20 #[inline] fn deref(&self) -> &Self::Target { - // SAFETY: The caller holds a `Device`, which guarantees= all invariants + // SAFETY: The caller holds a `Device`, which guaran= tees all invariants // of the weaker `Normal` context. unsafe { self.assume_ctx() } } diff --git a/rust/kernel/drm/ioctl.rs b/rust/kernel/drm/ioctl.rs index 64af9eacc306..9934b23c36eb 100644 --- a/rust/kernel/drm/ioctl.rs +++ b/rust/kernel/drm/ioctl.rs @@ -71,14 +71,14 @@ pub mod internal { pub use bindings::drm_file; pub use bindings::drm_ioctl_desc; =20 - /// Cast an [`Ioctl`] DRM device pointer to [`Registered`], preserving= the driver type + /// Cast a [`Userspace`] DRM device pointer to [`Registered`], preserv= ing the driver type /// parameter `T`. /// /// Used by [`declare_drm_ioctls!`] to anchor type inference. #[doc(hidden)] #[inline] pub const fn __dev_ctx_cast( - ptr: *const crate::drm::Device, + ptr: *const crate::drm::Device, ) -> *const crate::drm::Device { ptr.cast() } @@ -144,14 +144,14 @@ macro_rules! declare_drm_ioctls { // - The DRM device must have been registered = when we're called through // an IOCTL. // - // INVARIANT: The `Ioctl` context requires tha= t the device has been - // registered via `drm_dev_register()` at some= point; the DRM core - // guarantees this for ioctl dispatch callback= s. + // INVARIANT: The `Userspace` context requires= that the device has + // been registered via `drm_dev_register()` at= some point; the DRM + // core guarantees this for ioctl dispatch cal= lbacks. // // FIXME: Currently there is nothing enforcing= that the types of the // dev/file match the current driver these ioc= tls are being declared // for, and it's not clear how to enforce this= within the type system. - let dev: &$crate::drm::device::Device<_, $crat= e::drm::Ioctl> =3D + let dev: &$crate::drm::device::Device<_, $crat= e::drm::Userspace> =3D $crate::drm::device::Device::from_raw(raw_= dev); =20 // Type-inference anchor: the closure is never= called but ties `dev`'s diff --git a/rust/kernel/drm/mod.rs b/rust/kernel/drm/mod.rs index fd6ed35bc35a..7fcf2465a82e 100644 --- a/rust/kernel/drm/mod.rs +++ b/rust/kernel/drm/mod.rs @@ -11,11 +11,11 @@ =20 pub use self::device::Device; pub use self::device::DeviceContext; -pub use self::device::Ioctl; pub use self::device::Normal; pub use self::device::Registered; pub use self::device::RegistrationGuard; pub use self::device::UnregisteredDevice; +pub use self::device::Userspace; pub use self::driver::Driver; pub use self::driver::DriverInfo; pub use self::driver::Registration; --=20 2.55.0 From nobody Mon Sep 28 23:53:10 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 5D7CB34252B; Fri, 14 Aug 2026 23:09: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=1786748981; cv=none; b=VA1NWLX3J37eNvm2kC6nOEfGDlWYXMBn1S/zpvmYc6XhCKIcZt44pFTHAgtzs+HsT3zd7J5qHRNuWr+799ZIyeHBFiR7RO1mPJ7SPEzNLgbjco/fwOD+YsBHx3k/Afu8FGJfkHId7HVe2R+zx+r1PtjZVpAZdty+stOOM/8wFSo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786748981; c=relaxed/simple; bh=G/1K1XMVr5yKDUV9iauQ7JNQt7DvZnhVUGWQIKfu9YI=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=eNhcFP4WQenGZV68kQGh0WLzAcR6LCIL2DO7DYQH/CqwB1+E9unWEjLbfrsKJsDXq3X/EwGWiJGr1RUXNnE52eyRvpMT5ZdNZeWMPa+qHVgzKAUkOiFshTvmPKzovAtN/OyptERnl99qvXq47f/7dVwuE3TcdyuziGfCyMDCJVI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=f25gp82M; 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="f25gp82M" Received: by smtp.kernel.org (Postfix) with ESMTPSA id BB8D01F00A3D; Fri, 14 Aug 2026 23:09:35 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1786748980; bh=sSKhhle7EcwGqQ4E8Sm0jDW4kZ+Q2qKC0uMRA8YVy+o=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=f25gp82M8K21LocoUm752Joix3iCnsavD6WDN+D9Ll7CTeAOL1aTTXNaJM7W+PYwP +2frfr1gC9oRe+tAkPppYQiwqgp72ZGN7AeW3bCzsEIlV/NJ1bc0PnvB20VbST+6XM DwAcUwGcDGjZKOaDyE/mi4l0OTBNaagsj0v+50bFrP5HYTlFvjoxlDg9DFZukkGyyU 8ObKe+ZdvsoydxwN2myzb4nRGXMjY9aCg/oBQrKWLblo5NTGjTYKHWkBlGIJ47BmHW LWoRcIkSIPoc57ksW6R6fGMD7FI0LcxWUgM9f1WbATTnLjZkx3cF+z3QAJw8tM9RVf REb7T99DaGeuw== From: Danilo Krummrich To: dakr@kernel.org, aliceryhl@google.com, acourbot@nvidia.com, daniel.almeida@collabora.com, ojeda@kernel.org, boqun@kernel.org, gary@garyguo.net, bjorn3_gh@protonmail.com, lossin@kernel.org, a.hindborg@kernel.org, tmgross@umich.edu, tamird@kernel.org, work@onurozkan.dev, brauner@kernel.org, lyude@redhat.com, j@jananu.net, alvin.sun@linux.dev, deborah.brouwer@collabora.com, laura.nao@collabora.com, beata.michalska@arm.com Cc: nova-gpu@lists.linux.dev, dri-devel@lists.freedesktop.org, rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH 2/7] rust: drm: gem: gate open/close callbacks with RegistrationGuard Date: Sat, 15 Aug 2026 01:09:00 +0200 Message-ID: <20260814230923.1292966-3-dakr@kernel.org> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260814230923.1292966-1-dakr@kernel.org> References: <20260814230923.1292966-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" Wrap the GEM object open and close callbacks with a RegistrationGuard (drm_dev_enter / drm_dev_exit) to ensure the driver callbacks only run while the parent bus device is bound. If the device has been unbound, open returns -ENODEV and close silently returns. This prevents driver code from accessing device resources after unbind and is a prerequisite for making drm::Driver::File lifetime-parameterized, since GEM callbacks receive a &drm::File that could otherwise be used to access invalidated file private data. Signed-off-by: Danilo Krummrich --- rust/kernel/drm/gem/mod.rs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/rust/kernel/drm/gem/mod.rs b/rust/kernel/drm/gem/mod.rs index 80d8f524f9d5..560403ca8e38 100644 --- a/rust/kernel/drm/gem/mod.rs +++ b/rust/kernel/drm/gem/mod.rs @@ -128,6 +128,14 @@ extern "C" fn open_callback( raw_obj: *mut bindings::drm_gem_object, raw_file: *mut bindings::drm_file, ) -> core::ffi::c_int { + // SAFETY: `raw_obj` is a valid pointer to a `struct drm_gem_object` w= ith a valid `dev`. + let dev: &drm::Device =3D + unsafe { drm::Device::from_raw((*raw_obj).dev) }; + + let Some(_guard) =3D dev.registration_guard() else { + return ENODEV.to_errno(); + }; + // SAFETY: `open_callback` is only ever called with a valid pointer to= a `struct drm_file`. let file =3D unsafe { DriverFile::::from_raw(raw_file) }; =20 @@ -148,6 +156,14 @@ extern "C" fn close_callback( raw_obj: *mut bindings::drm_gem_object, raw_file: *mut bindings::drm_file, ) { + // SAFETY: `raw_obj` is a valid pointer to a `struct drm_gem_object` w= ith a valid `dev`. + let dev: &drm::Device =3D + unsafe { drm::Device::from_raw((*raw_obj).dev) }; + + let Some(_guard) =3D dev.registration_guard() else { + return; + }; + // SAFETY: `open_callback` is only ever called with a valid pointer to= a `struct drm_file`. let file =3D unsafe { DriverFile::::from_raw(raw_file) }; =20 --=20 2.55.0 From nobody Mon Sep 28 23:53:10 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 4C1A63B8120; Fri, 14 Aug 2026 23:09: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=1786748986; cv=none; b=ZP1HjskJT8bjoWZwncB1lH/0R2Ie4GkKExL49Ge8QwhSKD5Mgeu1ir4TdBBkh5tWQYesyaUYKrNnVxGapyDxVDMgbt/UjTmGaVIF27q4HKrmGH2vmKxK1Lt94wogPhZZAk0Hx3LlfbrgF20/n7iv06XDQ6NSV4t+oYxs2sFPMZs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786748986; c=relaxed/simple; bh=1t4zyBQenZPN/8uKpRxmMUMeynk1L33DrO2kaz3Yqp4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=awAK0OJlowJj4Re/wMNUkN1DynHn4rAdTxKIyRB+iFYxcuvqvIXeHl581dHOCer3PnpNDYms5/RCll95DucEQEzFYnn+jTh9JV9plt13BQmWnrS6jPBXlgAKjhWPnSEbrlW3RRwYn2OcaHT7SSijhG2hiyIvfbnlesyfvyrEZ44= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=MEA4iLnM; 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="MEA4iLnM" Received: by smtp.kernel.org (Postfix) with ESMTPSA id AD47C1F000E9; Fri, 14 Aug 2026 23:09:40 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1786748985; bh=YPEpqexwPWF2SDDlO5NIsqZNVaXDThMuN9H2rr7FxkU=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=MEA4iLnMmJze1K0C80G9/JwNG6PTldNvVze91r7Y8Kkon6p6cTMBLi3mOkc5KVwR/ tMoJkawUo/VRooauoqxTJfUzTEx1afUWJzNLkqnLx9q5A5ct8CgBdpNCFV6+mxNwnv lGBw7hcoNe6mumL6jEhdoEQpenyBgmxvBDLjAdjNBZABZMie1cuQSVH/JWye8YLINB 41JDyyBsI77TcS52+Es/J8ut+e6vYJMF1uqikmzdtnhPigmlu3Lv4nVJGK3E9zxGji trMf4yd8l1UGdA1rnOzoatDrYQfFRfkcRv3mFTfMmk4dKctAeX/snxrOJOiG23Ce0Y QYquYjl2qgYIA== From: Danilo Krummrich To: dakr@kernel.org, aliceryhl@google.com, acourbot@nvidia.com, daniel.almeida@collabora.com, ojeda@kernel.org, boqun@kernel.org, gary@garyguo.net, bjorn3_gh@protonmail.com, lossin@kernel.org, a.hindborg@kernel.org, tmgross@umich.edu, tamird@kernel.org, work@onurozkan.dev, brauner@kernel.org, lyude@redhat.com, j@jananu.net, alvin.sun@linux.dev, deborah.brouwer@collabora.com, laura.nao@collabora.com, beata.michalska@arm.com Cc: nova-gpu@lists.linux.dev, dri-devel@lists.freedesktop.org, rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH 3/7] rust: drm: move file_operations from gem to device Date: Sat, 15 Aug 2026 01:09:01 +0200 Message-ID: <20260814230923.1292966-4-dakr@kernel.org> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260814230923.1292966-1-dakr@kernel.org> References: <20260814230923.1292966-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 file_operations definition from drm::gem::create_fops() into UnregisteredDevice in drm::device. This is the file_operations of the DRM minor device, set through the drm_driver struct. It is not specific to GEM. Signed-off-by: Danilo Krummrich --- rust/kernel/drm/device.rs | 22 ++++++++++++++++++++-- rust/kernel/drm/gem/mod.rs | 20 -------------------- 2 files changed, 20 insertions(+), 22 deletions(-) diff --git a/rust/kernel/drm/device.rs b/rust/kernel/drm/device.rs index be83287fe161..a2940e172073 100644 --- a/rust/kernel/drm/device.rs +++ b/rust/kernel/drm/device.rs @@ -195,10 +195,28 @@ const fn compute_features() -> u32 { driver_features: Self::compute_features(), ioctls: T::IOCTLS.as_ptr(), num_ioctls: T::IOCTLS.len() as i32, - fops: &Self::GEM_FOPS, + fops: &Self::FOPS, }; =20 - const GEM_FOPS: bindings::file_operations =3D drm::gem::create_fops(); + const FOPS: bindings::file_operations =3D { + let mut fops: bindings::file_operations =3D pin_init::zeroed(); + + fops.owner =3D core::ptr::null_mut(); + fops.open =3D Some(bindings::drm_open); + fops.release =3D Some(bindings::drm_release); + fops.unlocked_ioctl =3D Some(bindings::drm_ioctl); + #[cfg(CONFIG_COMPAT)] + { + fops.compat_ioctl =3D Some(bindings::drm_compat_ioctl); + } + fops.poll =3D Some(bindings::drm_poll); + fops.read =3D Some(bindings::drm_read); + fops.llseek =3D Some(bindings::noop_llseek); + fops.mmap =3D Some(bindings::drm_gem_mmap); + fops.fop_flags =3D bindings::FOP_UNSIGNED_OFFSET; + + fops + }; =20 /// Create a new `UnregisteredDevice` for a `drm::Driver`. /// diff --git a/rust/kernel/drm/gem/mod.rs b/rust/kernel/drm/gem/mod.rs index 560403ca8e38..ee048febfbdc 100644 --- a/rust/kernel/drm/gem/mod.rs +++ b/rust/kernel/drm/gem/mod.rs @@ -399,23 +399,3 @@ impl AllocImpl fo= r Object { dumb_map_offset: None, }; } - -pub(super) const fn create_fops() -> bindings::file_operations { - let mut fops: bindings::file_operations =3D pin_init::zeroed(); - - fops.owner =3D core::ptr::null_mut(); - fops.open =3D Some(bindings::drm_open); - fops.release =3D Some(bindings::drm_release); - fops.unlocked_ioctl =3D Some(bindings::drm_ioctl); - #[cfg(CONFIG_COMPAT)] - { - fops.compat_ioctl =3D Some(bindings::drm_compat_ioctl); - } - fops.poll =3D Some(bindings::drm_poll); - fops.read =3D Some(bindings::drm_read); - fops.llseek =3D Some(bindings::noop_llseek); - fops.mmap =3D Some(bindings::drm_gem_mmap); - fops.fop_flags =3D bindings::FOP_UNSIGNED_OFFSET; - - fops -} --=20 2.55.0 From nobody Mon Sep 28 23:53:10 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 46EA53B8120; Fri, 14 Aug 2026 23:09:50 +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=1786748991; cv=none; b=AfUNPoegX7NR4qN2U/PWjJFqUmdx9MxKAwtfdttcSLyljzapdTTXttstXpgg7TUuH69V+h/Y9Hsyd18RUMl0e0je79B1IfUSUugSJ63L6Yb3s16+BJF2O3W9DB4xHSRB9nhmGUq2RZ2tebZVpZRSf30ygKAnA7cfZfb3N6bSulg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786748991; c=relaxed/simple; bh=jmJlsOUR+tvIzSDyik2faVUup1QzcYWgSEaT6kMFMzA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=VmYO/Tz1hsvcJOohiOzGhbxYZ9ympvW1kHbwymvP/l7Sy9RWMWGTAVrh3AME7FsvSI7z6uC4UqcbSeBSMvQt88/KCzVV5L35uv2LY3ITfbWg2n5JdZbiN7T/YANXx0mspwjSJU/JLQwBmdSHl6GzDPPUbEy4pByZjXULv6YaAgw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=klIwKAVc; 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="klIwKAVc" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 9E6781F00A3A; Fri, 14 Aug 2026 23:09:45 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1786748990; bh=duuk6GqeoZYD9b1T5EoO3ZVOSGx2xP5WwTkfsxIM2Mg=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=klIwKAVcrqKEMzr6LEehcpxVD9MEoUPr+7yL8WGqi+/7zfwY0kgFdJYvmHvV/O10m vu2CgWIZSJdVXB8RN/HLDJt4wRidQQsTV6v5Jg17WlqLe4Qwbq3vGrY+ZLO1HT0YAi 4MDStLbCXA/7Dgt8zBXWZzB16IbD72CVM7BqVVYrQnG23l5w43GgCPy3D2H4b0JGjN 4fnCUIpkNtgE6oII7q799o1KjEm/TdfvqtTx7uWsN8cgyMrpA+Iy5E1z70H34Sbq2x 6WzEMQm+L8V+CxmiuvlHseeaMv8CwiAR+Ezye0Gqwwvuuraj179cmtfQr5g51DfSie eZhExL+zBC2qA== From: Danilo Krummrich To: dakr@kernel.org, aliceryhl@google.com, acourbot@nvidia.com, daniel.almeida@collabora.com, ojeda@kernel.org, boqun@kernel.org, gary@garyguo.net, bjorn3_gh@protonmail.com, lossin@kernel.org, a.hindborg@kernel.org, tmgross@umich.edu, tamird@kernel.org, work@onurozkan.dev, brauner@kernel.org, lyude@redhat.com, j@jananu.net, alvin.sun@linux.dev, deborah.brouwer@collabora.com, laura.nao@collabora.com, beata.michalska@arm.com Cc: nova-gpu@lists.linux.dev, dri-devel@lists.freedesktop.org, rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH 4/7] rust: fs: add iminor() helper Date: Sat, 15 Aug 2026 01:09:02 +0200 Message-ID: <20260814230923.1292966-5-dakr@kernel.org> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260814230923.1292966-1-dakr@kernel.org> References: <20260814230923.1292966-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 Rust helper for iminor(), which extracts the minor number from a struct inode. This is a static inline function in the C headers, so bindgen does not generate a binding for it. Signed-off-by: Danilo Krummrich --- rust/helpers/fs.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/rust/helpers/fs.c b/rust/helpers/fs.c index 789d60fb8908..d6f9782db178 100644 --- a/rust/helpers/fs.c +++ b/rust/helpers/fs.c @@ -10,3 +10,8 @@ __rust_helper struct file *rust_helper_get_file(struct fi= le *f) { return get_file(f); } + +__rust_helper unsigned int rust_helper_iminor(const struct inode *inode) +{ + return iminor(inode); +} --=20 2.55.0 From nobody Mon Sep 28 23:53:10 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 399E83B8120; Fri, 14 Aug 2026 23:09:55 +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=1786748996; cv=none; b=XEzA7eDoDCOd0OhEGwQjTsV+LBxP0ZerQSX0ldBuBsyoGCXlKP5ofE9iqUOuWE6P2KR4GGM4h+VQpL33MibOsKZMxX+xirI8KJcfC/HuEmQI6wz/PnOGbMnWdTwS2erVErINHF00OT9sT2Cp5u96VL9Ui8gbO3kKnH4HxJ0HVsw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786748996; c=relaxed/simple; bh=LN+eY6naGWu+lFbYf30RJ6vZtr9qFwL+iPNb9bD1i9M=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Er70km9RFHSSEXTpqOOpvkHn1iCW/MLpezWRirFf+0YjDdgWL3FcIMwAi0xgCvqgVTqe1N4tOG0hCjjpi4rDTb5U3eh6o5SO3UUIeBx3TxFz0QJWK0C6Py9W7MPqjySsQ9j/W4kEk0+z06ti4bQFWtZ45pTIP/cTshZrImZtHiY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=cGR+vdgN; 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="cGR+vdgN" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 9983C1F000E9; Fri, 14 Aug 2026 23:09:50 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1786748995; bh=W8jExBi0QxHteBboXNh2hw2w9UoJVj//coupeb7xVIA=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=cGR+vdgNS0EOwbb+Iwi9zyaK9ifG/cBh7PBJotdMZo0FFHft83iOCMM3w81N65ztG FqkzZqbdRmpaaAT9b8PaF9mt88lEuF0Zn/SSc+W9fq1m3WcFhUZQ2rTCD8Sxqk/Ibk rNXKlo8WaDtCMXJ9PlghCepkyMEinZJd5YpKMNVCZWJPJDKyWc4Qnnf4dCeNYXF5nn G65oPMQ9GQj8wGZ1nvOyBfQsN0kwf8Ros+9VGE8egK5lpXL9s3SfcVf0puLliYb1xm 6hlfeCT/gnLX/9WfH9apGccQtu5UxyGoxXrEETAh687GtvAa3NCU7MOsq2FeMmw1fD /sDy0tr7ttqFQ== From: Danilo Krummrich To: dakr@kernel.org, aliceryhl@google.com, acourbot@nvidia.com, daniel.almeida@collabora.com, ojeda@kernel.org, boqun@kernel.org, gary@garyguo.net, bjorn3_gh@protonmail.com, lossin@kernel.org, a.hindborg@kernel.org, tmgross@umich.edu, tamird@kernel.org, work@onurozkan.dev, brauner@kernel.org, lyude@redhat.com, j@jananu.net, alvin.sun@linux.dev, deborah.brouwer@collabora.com, laura.nao@collabora.com, beata.michalska@arm.com Cc: nova-gpu@lists.linux.dev, dri-devel@lists.freedesktop.org, rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH 5/7] rust: drm: wrap fops open with RegistrationGuard Date: Sat, 15 Aug 2026 01:09:03 +0200 Message-ID: <20260814230923.1292966-6-dakr@kernel.org> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260814230923.1292966-1-dakr@kernel.org> References: <20260814230923.1292966-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 Minor abstraction with RAII release and a fops_open() wrapper that holds a RegistrationGuard (drm_dev_enter / drm_dev_exit) across the entire drm_open() call. This guarantees that drm_dev_unplug() in Registration::drop() waits for the full open sequence to complete, so all files are visible in the filelist when iterating for cleanup. Signed-off-by: Danilo Krummrich --- rust/kernel/drm/device.rs | 63 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 62 insertions(+), 1 deletion(-) diff --git a/rust/kernel/drm/device.rs b/rust/kernel/drm/device.rs index a2940e172073..09903ed783e1 100644 --- a/rust/kernel/drm/device.rs +++ b/rust/kernel/drm/device.rs @@ -42,6 +42,42 @@ }, }; =20 +/// A reference to a `struct drm_minor` with RAII release. +struct Minor(NonNull); + +// Methods use `#[inline(never)]` to prevent the unexported `drm_minor_acq= uire()` / +// `drm_minor_release()` symbols from being inlined into driver modules. +impl Minor { + /// Acquire a minor by ID. Increments the underlying device's refcount. + #[inline(never)] + fn acquire(minor_id: u32) -> Result { + // SAFETY: `drm_minors_xa` is a valid global xarray; any `minor_id= ` is safe to + // look up (returns ERR_PTR on failure). + let ptr =3D + unsafe { bindings::drm_minor_acquire(&raw mut bindings::drm_mi= nors_xa, minor_id) }; + Ok(Self(NonNull::new(from_err_ptr(ptr)?).ok_or(ENODEV)?)) + } + + /// Returns a reference to the DRM device for this minor. + /// + /// # Safety + /// + /// The caller must ensure that the minor belongs to a `Device`. + unsafe fn device(&self) -> &Device { + // SAFETY: The minor is valid (from `drm_minor_acquire()`) and `mi= nor->dev` + // is a valid `drm_device`. The caller guarantees it is a `Device<= T>`. + unsafe { Device::from_raw((*self.0.as_ptr()).dev) } + } +} + +impl Drop for Minor { + #[inline(never)] + fn drop(&mut self) { + // SAFETY: `self.0` came from `drm_minor_acquire()` and has not be= en released yet. + unsafe { bindings::drm_minor_release(self.0.as_ptr()) } + } +} + #[cfg(CONFIG_DRM_LEGACY)] macro_rules! drm_legacy_fields { ( $($field:ident: $val:expr),* $(,)? ) =3D> { @@ -198,11 +234,36 @@ const fn compute_features() -> u32 { fops: &Self::FOPS, }; =20 + /// Wrapper for `fops.open` that holds a [`RegistrationGuard`] across = the entire `drm_open()` + /// call. This guarantees that `drm_dev_unplug()` in `Registration::dr= op()` waits for the full + /// open sequence. + extern "C" fn fops_open(inode: *mut bindings::inode, filp: *mut bindin= gs::file) -> c_int { + let f =3D || -> Result { + // SAFETY: `inode` is valid. + let minor_id =3D unsafe { bindings::iminor(inode) }; + let minor =3D Minor::acquire(minor_id)?; + + // SAFETY: `fops_open` is only installed for devices of type `= T` (via `FOPS`). + let _guard =3D (unsafe { minor.device::() }) + .registration_guard() + .ok_or(ENODEV)?; + + // SAFETY: `inode` and `filp` are valid. The RegistrationGuard= ensures the entire + // `drm_open()` runs within the SRCU critical section. + Ok(unsafe { bindings::drm_open(inode, filp) }) + }; + + match f() { + Ok(ret) =3D> ret, + Err(e) =3D> e.to_errno(), + } + } + const FOPS: bindings::file_operations =3D { let mut fops: bindings::file_operations =3D pin_init::zeroed(); =20 fops.owner =3D core::ptr::null_mut(); - fops.open =3D Some(bindings::drm_open); + fops.open =3D Some(Self::fops_open); fops.release =3D Some(bindings::drm_release); fops.unlocked_ioctl =3D Some(bindings::drm_ioctl); #[cfg(CONFIG_COMPAT)] --=20 2.55.0 From nobody Mon Sep 28 23:53:10 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 2CE373B71AC; Fri, 14 Aug 2026 23:10:00 +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=1786749002; cv=none; b=jnV8gswyLxey0yNG84vIsHweUlJfqr0kZrEq076Nd8/N3Rad+d3NaC/DviR8jTuB2Vq2694YQkz+MBuE8NNPDgB59BbfNNBTW/v/pcnRk2O69dp9cWphLkRZG6OT9a0vHcdp7VXw6DDatbpb9Tq6728YBtcQbXgM5fNNhYY7bYY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786749002; c=relaxed/simple; bh=1VN3uppIRvK0SYZjoGDsfMBRy4GPHgUCKnBgZNrTxEo=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=KXoFYUlEQ+VLk+g0lJiiq7nKla3Ct5ZUT6BsF6uYWFeUoNQuXZOVARvowN2LLvBLR8LDfsOT4RI8+iWAxl4cOOyXYpe7+oAyCe2rkF/YVrDrOkowTJ3PZ9q0r8ZWl02FlCYneyUTTT8Xrn3AluXz7VNW2WViO1GkIVKSEKzX3ew= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=f4hytynj; 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="f4hytynj" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 8C4CC1F00A3A; Fri, 14 Aug 2026 23:09:55 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1786749000; bh=LaItPQ0o3O7N1/dhhAb06mIPwLY4EhUW6EmJGpPxoGI=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=f4hytynjujccUOXQEWikO3gIAV4GGTHvmrWLN20+O+lbdbee9IzJWrJS26kfm7bp8 i1f7qrlXU74MwHqkzGvT+lyVqAnV35eAk+qxvIvIB7zQ8IPeVWVZmTje8rwLLU+0OD ObymO299jien3EX+uy+oDoG6hDQFwAUix/Np80yAcNLJpt8XQf3n8BrbxY1rgikx5b O5Cv8kUN0JuHDj585QMbztNTAXTTXShFAiBcAW6Iv6hQ1xCD6rDrl9udg88cmKrqOU tZfbSr1Lob4x6+bgbsr/4H4pL3w0g0olML7T8aO5vQWMGRecWoPsb9JoDLuT/xXw6K ovwUIEUt0A3sA== From: Danilo Krummrich To: dakr@kernel.org, aliceryhl@google.com, acourbot@nvidia.com, daniel.almeida@collabora.com, ojeda@kernel.org, boqun@kernel.org, gary@garyguo.net, bjorn3_gh@protonmail.com, lossin@kernel.org, a.hindborg@kernel.org, tmgross@umich.edu, tamird@kernel.org, work@onurozkan.dev, brauner@kernel.org, lyude@redhat.com, j@jananu.net, alvin.sun@linux.dev, deborah.brouwer@collabora.com, laura.nao@collabora.com, beata.michalska@arm.com Cc: nova-gpu@lists.linux.dev, dri-devel@lists.freedesktop.org, rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH 6/7] rust: drm: make Driver::File lifetime-parameterized Date: Sat, 15 Aug 2026 01:09:04 +0200 Message-ID: <20260814230923.1292966-7-dakr@kernel.org> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260814230923.1292966-1-dakr@kernel.org> References: <20260814230923.1292966-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 DRM file private data lifetime-parameterized, allowing drivers to borrow from RegistrationData in their per-file data. Introduce DriverFile<'a> as a lifetime-parameterized trait that receives both the device and registration data in open(). Parametrize File on the driver type rather than the file data type, deriving the concrete file type through ForLt. Add inner() for covariant file types and inner_with() for invariant ones to access the driver file data from a File reference. Ensure file data is always dropped before registration data: - In Registration::drop(), iterate the filelist under filelist_mutex and drop driver_priv for all open files, then wait for in-flight postclose_callback() calls to complete via an open_count / WaitQueue pair on drm::Device. - In postclose_callback(), skip the drop if driver_priv has already been NULLed by the filelist iteration. The NULL write is visible through the filelist_mutex acquire/release chain in drm_close_helper(). Signed-off-by: Danilo Krummrich --- drivers/gpu/drm/nova/driver.rs | 5 +- drivers/gpu/drm/nova/file.rs | 11 ++- drivers/gpu/drm/nova/gem.rs | 8 +- drivers/gpu/drm/tyr/driver.rs | 5 +- drivers/gpu/drm/tyr/file.rs | 11 ++- rust/kernel/drm/device.rs | 35 ++++++-- rust/kernel/drm/driver.rs | 69 ++++++++++++++- rust/kernel/drm/file.rs | 150 ++++++++++++++++++++++----------- rust/kernel/drm/gem/mod.rs | 12 ++- rust/kernel/drm/gem/shmem.rs | 12 ++- rust/kernel/drm/ioctl.rs | 2 +- 11 files changed, 231 insertions(+), 89 deletions(-) diff --git a/drivers/gpu/drm/nova/driver.rs b/drivers/gpu/drm/nova/driver.rs index 739690bc2db5..a8f61086773d 100644 --- a/drivers/gpu/drm/nova/driver.rs +++ b/drivers/gpu/drm/nova/driver.rs @@ -12,7 +12,8 @@ ioctl, // }, prelude::*, - sync::aref::ARef, // + sync::aref::ARef, + types::CovariantForLt, // }; =20 use crate::file::File; @@ -75,7 +76,7 @@ fn probe<'bound>( impl drm::Driver for NovaDriver { type Data =3D (); type RegistrationData<'a> =3D (); - type File =3D File; + type File =3D CovariantForLt!(File); type Object =3D gem::Object; type ParentDevice =3D auxiliary::Device; =20 diff --git a/drivers/gpu/drm/nova/file.rs b/drivers/gpu/drm/nova/file.rs index 298c02bacb4b..1f94201af92b 100644 --- a/drivers/gpu/drm/nova/file.rs +++ b/drivers/gpu/drm/nova/file.rs @@ -3,7 +3,6 @@ use crate::driver::{NovaDevice, NovaDriver}; use crate::gem::NovaObject; use kernel::{ - alloc::flags::*, auxiliary, device::Bound, drm::{ @@ -18,10 +17,10 @@ =20 pub(crate) struct File; =20 -impl drm::file::DriverFile for File { +impl drm::file::DriverFile<'_> for File { type Driver =3D NovaDriver; =20 - fn open(_dev: &NovaDevice) -> Result>> { + fn open(_device: &NovaDevice, _reg_data: &()) -> Result>> { Ok(KBox::new(Self, GFP_KERNEL)?.into()) } } @@ -32,7 +31,7 @@ pub(crate) fn get_param( dev: &NovaDevice, _reg_data: &(), getparam: &mut uapi::drm_nova_getparam, - _file: &drm::File, + _file: &drm::File, ) -> Result { let adev: &auxiliary::Device =3D dev.as_ref(); let pdev: &pci::Device =3D adev.parent().try_into()?; @@ -52,7 +51,7 @@ pub(crate) fn gem_create( dev: &NovaDevice, _reg_data: &(), req: &mut uapi::drm_nova_gem_create, - file: &drm::File, + file: &drm::File, ) -> Result { let obj =3D NovaObject::new(dev, req.size.try_into()?)?; =20 @@ -66,7 +65,7 @@ pub(crate) fn gem_info( _dev: &NovaDevice, _reg_data: &(), req: &mut uapi::drm_nova_gem_info, - file: &drm::File, + file: &drm::File, ) -> Result { let bo =3D NovaObject::lookup_handle(file, req.handle)?; =20 diff --git a/drivers/gpu/drm/nova/gem.rs b/drivers/gpu/drm/nova/gem.rs index 2b6fe9dc0bfa..2a21ff8ba579 100644 --- a/drivers/gpu/drm/nova/gem.rs +++ b/drivers/gpu/drm/nova/gem.rs @@ -11,9 +11,9 @@ sync::aref::ARef, }; =20 -use crate::{ - driver::{NovaDevice, NovaDriver}, - file::File, +use crate::driver::{ + NovaDevice, + NovaDriver, // }; =20 /// GEM Object inner driver data @@ -43,7 +43,7 @@ pub(crate) fn new(dev: &NovaDevice, size: usize) -> Resul= t, + file: &drm::File, handle: u32, ) -> Result>> { gem::Object::lookup_handle(file, handle) diff --git a/drivers/gpu/drm/tyr/driver.rs b/drivers/gpu/drm/tyr/driver.rs index d78ad9d292ff..94bc85635725 100644 --- a/drivers/gpu/drm/tyr/driver.rs +++ b/drivers/gpu/drm/tyr/driver.rs @@ -32,7 +32,8 @@ Arc, Mutex, // }, - time, // + time, + types::CovariantForLt, // }; =20 use crate::{ @@ -206,7 +207,7 @@ fn drop(self: Pin<&mut Self>) {} impl drm::Driver for TyrDrmDriver { type Data =3D (); type RegistrationData<'drm> =3D TyrDrmRegistrationData<'drm>; - type File =3D TyrDrmFileData; + type File =3D CovariantForLt!(TyrDrmFileData); type Object =3D Bo; type ParentDevice =3D platform::Device; =20 diff --git a/drivers/gpu/drm/tyr/file.rs b/drivers/gpu/drm/tyr/file.rs index 9f60a90d4948..0e0878090de6 100644 --- a/drivers/gpu/drm/tyr/file.rs +++ b/drivers/gpu/drm/tyr/file.rs @@ -19,13 +19,16 @@ #[pin_data] pub(crate) struct TyrDrmFileData {} =20 -/// Convenience type alias for our DRM `File` type -pub(crate) type TyrDrmFile =3D drm::file::File; +/// Convenience type alias for our DRM `File` type. +pub(crate) type TyrDrmFile =3D drm::file::File; =20 -impl drm::file::DriverFile for TyrDrmFileData { +impl drm::file::DriverFile<'_> for TyrDrmFileData { type Driver =3D TyrDrmDriver; =20 - fn open(_dev: &drm::Device) -> Result>> { + fn open( + _device: &TyrDrmDevice, + _reg_data: &TyrDrmRegistrationData<'_>, + ) -> Result>> { KBox::try_pin_init(try_pin_init!(Self {}), GFP_KERNEL) } } diff --git a/rust/kernel/drm/device.rs b/rust/kernel/drm/device.rs index 09903ed783e1..29512d0e2ddb 100644 --- a/rust/kernel/drm/device.rs +++ b/rust/kernel/drm/device.rs @@ -15,11 +15,16 @@ }, error::from_err_ptr, prelude::*, - sync::aref::{ - ARef, - AlwaysRefCounted, // + sync::{ + aref::{ + ARef, + AlwaysRefCounted, // + }, + atomic::Atomic, + WaitQueue, }, types::{ + ForLt, NotThreadSafe, Opaque, // }, @@ -190,7 +195,10 @@ fn deref(&self) -> &Self::Target { } } =20 -impl UnregisteredDevice { +impl UnregisteredDevice +where + for<'a> ::Of<'a>: drm::file::DriverFile<'a, Driver = =3D T>, +{ const fn compute_features() -> u32 { let mut features =3D drm::driver::FEAT_GEM; =20 @@ -203,8 +211,8 @@ const fn compute_features() -> u32 { =20 const VTABLE: bindings::drm_driver =3D drm_legacy_fields! { load: None, - open: Some(drm::File::::open_callback), - postclose: Some(drm::File::::postclose_callback), + open: Some(drm::File::::open_callback), + postclose: Some(drm::File::::postclose_callback), unload: None, release: Some(Device::::release), master_set: None, @@ -333,6 +341,19 @@ pub fn new( // SAFETY: `raw_drm` is valid; no concurrent access before registr= ation. unsafe { (*raw_drm.as_ptr()).registration_data =3D UnsafeCell::new= (NonNull::dangling()) }; =20 + // SAFETY: `raw_drm` is valid; no concurrent access before registr= ation. + unsafe { (*raw_drm.as_ptr()).open_count =3D Atomic::new(0) }; + + // SAFETY: + // - `raw_drm` is valid; no concurrent access before registration. + // - The field is pinned because the Device is pinned (refcounted,= allocated by + // `__drm_dev_alloc()`, never moved). + // - The init is infallible. + let Ok(()) =3D unsafe { + crate::new_waitqueue!("drm_open_count") + .__pinned_init(&raw mut (*raw_drm.as_ptr()).open_count_wq) + }; + // SAFETY: The reference count is one, and now we take ownership o= f that reference as a // `drm::Device`. // INVARIANT: We just created the device above, but have yet to ca= ll `drm_dev_register`. @@ -357,6 +378,8 @@ pub struct Device { dev: Opaque, data: T::Data, pub(super) registration_data: UnsafeCell>>, + pub(super) open_count: Atomic, + pub(super) open_count_wq: WaitQueue, _ctx: PhantomData, } =20 diff --git a/rust/kernel/drm/driver.rs b/rust/kernel/drm/driver.rs index 74f6ed690d8b..2aa534149d78 100644 --- a/rust/kernel/drm/driver.rs +++ b/rust/kernel/drm/driver.rs @@ -9,8 +9,17 @@ device, drm, error::to_result, + interop::list::clist_create, prelude::*, - sync::aref::ARef, // + sync::{ + aref::ARef, + atomic::{ + Acquire, + Release, // + }, + Mutex, // + }, + types::ForLt, // }; use core::ptr::NonNull; =20 @@ -117,8 +126,15 @@ pub trait Driver { /// The type used to manage memory for this driver. type Object: AllocImpl; =20 - /// The type used to represent a DRM File (client) - type File: drm::file::DriverFile; + /// The type used to represent a DRM File (client). + /// + /// File data may borrow from [`RegistrationData`](Driver::Registratio= nData). File data is + /// guaranteed to be dropped before registration data, either when the= file is closed or + /// when the device is unregistered, whichever comes first. + /// + /// Drivers set this to `CovariantForLt!(MyFileData)` (or `ForLt!` for= invariant types) + /// and implement [`DriverFile`](drm::file::DriverFile) for their file= data type. + type File: ForLt + 'static; =20 /// The bus device type of the parent device that the DRM device is as= sociated with. type ParentDevice: device::AsBusDevice; @@ -221,6 +237,51 @@ fn drop(&mut self) { unsafe { bindings::drm_dev_unplug(self.drm.as_raw()) }; // After drm_dev_unplug(), the SRCU barrier guarantees that all Re= gistrationGuard critical // sections have completed, so no one holds a reference to reg_dat= a anymore. - // reg_data is dropped here automatically. + + // Drop all remaining file private data before dropping registrati= on data. This guarantees + // that file data (which may borrow from RegistrationData) is alwa= ys dropped first. + let raw =3D self.drm.as_raw(); + + // SAFETY: `filelist_mutex` is initialized by `drm_dev_init()` and= remains valid for + // the lifetime of the `struct drm_device`. + let filelist_mutex =3D unsafe { Mutex::from_raw(&raw mut (*raw).fi= lelist_mutex) }; + { + let _guard =3D filelist_mutex.lock(); + + // SAFETY: `filelist` is a valid, initialized sentinel `list_h= ead`; the mutex + // guard prevents concurrent modification. + let filelist =3D unsafe { + clist_create!( + &raw mut (*raw).filelist, + drm::File, + bindings::drm_file, + lhead + ) + }; + + for file in filelist.iter() { + // SAFETY: `file` is a valid `drm_file` on this device's f= ilelist. + let priv_ptr =3D unsafe { (*file.as_raw()).driver_priv }; + + // SAFETY: Setting `driver_priv` to NULL is visible to `po= stclose_callback()` + // through the `filelist_mutex` acquire/release chain in `= drm_close_helper()`. + unsafe { (*file.as_raw()).driver_priv =3D core::ptr::null_= mut() }; + + // SAFETY: `driver_priv` was created by `open_callback()` = via `KBox::into_raw` and + // has not yet been freed (the file is still in the list, = so `postclose_callback()` + // has not run). + drop(unsafe { KBox::from_raw(priv_ptr.cast::<::Of<'static>>()) }); + + self.drm.open_count.fetch_sub(1, Release); + } + } + + // Wait for in-flight `postclose_callback()` calls to complete. Af= ter `drm_dev_unplug()`, no + // new opens can succeed, so `open_count` is monotonically decreas= ing. + self.drm + .open_count_wq + .wait_event(|| self.drm.open_count.load(Acquire) =3D=3D 0); + + // `_reg_data` is dropped here automatically, after all file data = has been dropped. } } diff --git a/rust/kernel/drm/file.rs b/rust/kernel/drm/file.rs index 10160601ce5a..6491ec5707a0 100644 --- a/rust/kernel/drm/file.rs +++ b/rust/kernel/drm/file.rs @@ -8,17 +8,34 @@ bindings, drm, prelude::*, - types::Opaque, // + sync::atomic::{ + Relaxed, + Release, // + }, + types::{ + CovariantForLt, + ForLt, + Opaque, // + }, // }; use core::marker::PhantomData; =20 /// Trait that must be implemented by DRM drivers to represent a DRM File = (a client instance). -pub trait DriverFile { +/// +/// The lifetime `'a` allows the file data to borrow from +/// [`RegistrationData`](drm::Driver::RegistrationData). +pub trait DriverFile<'a>: Sized { /// The parent `Driver` implementation for this `DriverFile`. type Driver: drm::Driver; =20 - /// Open a new file (called when a client opens the DRM device). - fn open(device: &drm::Device) -> Result>>; + /// Open a new DRM file, creating the per-file driver data. + /// + /// Called when a client opens the DRM device. The returned file data = may borrow from + /// `reg_data` with lifetime `'a`. + fn open( + device: &drm::Device, + reg_data: &'a ::RegistrationData<'a>, + ) -> Result>>; } =20 /// An open DRM File. @@ -27,17 +44,17 @@ pub trait DriverFile { /// /// `self.0` is a valid instance of a `struct drm_file`. #[repr(transparent)] -pub struct File(Opaque, PhantomData); +pub struct File(Opaque, PhantomData= ); =20 -impl File { +impl File { #[doc(hidden)] /// Not intended to be called externally, except via declare_drm_ioctl= s!() /// /// # Safety /// - /// `raw_file` must be a valid pointer to an open `struct drm_file`, o= pened through `T::open`. - pub unsafe fn from_raw<'a>(ptr: *mut bindings::drm_file) -> &'a File { - // SAFETY: `raw_file` is valid by the safety requirements of this = function. + /// `ptr` must be a valid pointer to an open `struct drm_file`. + pub unsafe fn from_raw<'a>(ptr: *mut bindings::drm_file) -> &'a File { + // SAFETY: `ptr` is valid by the safety requirements of this funct= ion. unsafe { &*ptr.cast() } } =20 @@ -45,59 +62,94 @@ pub(super) fn as_raw(&self) -> *mut bindings::drm_file { self.0.get() } =20 - fn driver_priv(&self) -> *mut T { - // SAFETY: By the type invariants of `Self`, `self.as_raw()` is al= ways valid. - unsafe { (*self.as_raw()).driver_priv }.cast() + /// Return a pinned reference to the driver file data. + /// + /// Only available when `D::File` implements [`trait@CovariantForLt`].= For invariant types, use + /// [`inner_with()`](Self::inner_with). + pub fn inner(&self) -> Pin<&::Of<'_>> + where + D::File: CovariantForLt, + { + // SAFETY: `driver_priv` was initialized by `open_callback()`. `Co= variantForLt` guarantees + // the lifetime shortening from `'static` to `'_` is sound. + unsafe { Pin::new_unchecked(&*(*self.as_raw()).driver_priv.cast_co= nst().cast()) } } =20 - /// Return a pinned reference to the driver file structure. - pub fn inner(&self) -> Pin<&T> { - // SAFETY: By the type invariant the pointer `self.as_raw()` point= s to a valid and opened - // `struct drm_file`, hence `driver_priv` has been properly initia= lized by `open_callback`. - unsafe { Pin::new_unchecked(&*(self.driver_priv())) } + /// Access the driver file data through a closure. + /// + /// This works for all file data types, including invariant ones. For = covariant types, + /// [`inner()`](Self::inner) provides direct access without a closure. + pub fn inner_with(&self, f: F) -> R + where + F: for<'a> FnOnce(Pin<&'a ::Of<'a>>) -> R, + { + // SAFETY: `driver_priv` was initialized by `open_callback()`. The= HRTB `for<'a>` prevents + // the caller from choosing a concrete lifetime, making the lifeti= me shortening sound + // regardless of variance. + f(unsafe { Pin::new_unchecked(&*(*self.as_raw()).driver_priv.cast_= const().cast()) }) } =20 /// The open callback of a `struct drm_file`. + /// + /// Called from `drm_open()`, which is itself called from `fops_open()= `. The latter holds a + /// `RegistrationGuard`, so the device is guaranteed to be registered = for the duration of this + /// callback. pub(crate) extern "C" fn open_callback( raw_dev: *mut bindings::drm_device, raw_file: *mut bindings::drm_file, - ) -> core::ffi::c_int { - // SAFETY: A callback from `struct drm_driver::open` guarantees th= at - // - `raw_dev` is valid pointer to a `struct drm_device`, - // - the corresponding `struct drm_device` has been registered. - let drm =3D unsafe { drm::Device::from_raw(raw_dev) }; - - // SAFETY: `raw_file` is a valid pointer to a `struct drm_file`. - let file =3D unsafe { File::::from_raw(raw_file) }; - - let inner =3D match T::open(drm) { - Err(e) =3D> { - return e.to_errno(); - } - Ok(i) =3D> i, - }; - - // SAFETY: This pointer is treated as pinned, and the Drop guarant= ee is upheld in - // `postclose_callback()`. - let driver_priv =3D KBox::into_raw(unsafe { Pin::into_inner_unchec= ked(inner) }); - - // SAFETY: By the type invariants of `Self`, `self.as_raw()` is al= ways valid. - unsafe { (*file.as_raw()).driver_priv =3D driver_priv.cast() }; - - 0 + ) -> core::ffi::c_int + where + for<'a> ::Of<'a>: DriverFile<'a, Driver =3D D>, + { + // SAFETY: The DRM core guarantees that `raw_dev` is valid. `fops_= open()` holds a + // `RegistrationGuard`, so the device is registered and the `Regis= tered` context holds. + let dev: &drm::device::Device =3D + unsafe { drm::device::Device::from_raw(raw_dev) }; + + dev.registration_data_with(|reg_data| { + let inner =3D match <::Of<'_> as DriverFile<= '_>>::open(dev, reg_data) { + Err(e) =3D> return e.to_errno(), + Ok(i) =3D> i, + }; + + // SAFETY: This pointer is treated as pinned, and the Drop gua= rantee is upheld in + // `postclose_callback()` or the filelist iteration in `Regist= ration::drop()`. + let driver_priv =3D KBox::into_raw(unsafe { Pin::into_inner_un= checked(inner) }); + + dev.open_count.fetch_add(1, Relaxed); + + // SAFETY: `raw_file` is a valid pointer to a `struct drm_file= `. + unsafe { (*raw_file).driver_priv =3D driver_priv.cast() }; + + 0 + }) } =20 /// The postclose callback of a `struct drm_file`. pub(crate) extern "C" fn postclose_callback( - _raw_dev: *mut bindings::drm_device, + raw_dev: *mut bindings::drm_device, raw_file: *mut bindings::drm_file, - ) { - // SAFETY: This reference won't escape this function - let file =3D unsafe { File::::from_raw(raw_file) }; - - // SAFETY: `file.driver_priv` has been created in `open_callback` = through `KBox::into_raw`. - let _ =3D unsafe { KBox::from_raw(file.driver_priv()) }; + ) where + for<'a> ::Of<'a>: DriverFile<'a, Driver =3D D>, + { + // SAFETY: `raw_file` is a valid pointer to a `struct drm_file`. + let driver_priv =3D unsafe { (*raw_file).driver_priv }; + + if driver_priv.is_null() { + return; + } + + // SAFETY: `driver_priv` was created in `open_callback()` through = `KBox::into_raw` and has + // not been dropped yet (the NULL check above guards against doubl= e-free from the filelist + // iteration in `Registration::drop()`). + let _ =3D unsafe { KBox::from_raw(driver_priv.cast::<::Of<'static>>()) }; + + // SAFETY: `raw_dev` is valid for the lifetime of the `struct drm_= file`. + let dev: &drm::device::Device =3D unsafe { drm::device::Device:= :from_raw(raw_dev) }; + if dev.open_count.fetch_sub(1, Release) =3D=3D 1 { + dev.open_count_wq.wake_up(); + } } } =20 -impl super::private::Sealed for File {} +impl super::private::Sealed for File {} diff --git a/rust/kernel/drm/gem/mod.rs b/rust/kernel/drm/gem/mod.rs index ee048febfbdc..1aa18f0b172c 100644 --- a/rust/kernel/drm/gem/mod.rs +++ b/rust/kernel/drm/gem/mod.rs @@ -76,7 +76,7 @@ unsafe fn dec_ref(obj: core::ptr::NonNull) { /// /// [`Driver`]: drm::Driver /// [`DriverFile`]: drm::file::DriverFile -pub type DriverFile =3D drm::File<<::Driver as drm::= Driver>::File>; +pub type DriverFile =3D drm::File<::Driver>; =20 /// A type alias for retrieving the current [`AllocImpl`] for a given [`Dr= iverObject`]. /// @@ -196,11 +196,10 @@ fn size(&self) -> usize { =20 /// Creates a new handle for the object associated with a given `File` /// (or returns an existing one). - fn create_handle(&self, file: &drm::File) -> Result + fn create_handle(&self, file: &drm::File) -> Result where Self: AllocImpl, - D: drm::Driver, - F: drm::file::DriverFile, + D: drm::Driver, { let mut handle: u32 =3D 0; // SAFETY: The arguments are all valid per the type invariants. @@ -211,11 +210,10 @@ fn create_handle(&self, file: &drm::File) ->= Result } =20 /// Looks up an object by its handle for a given `File`. - fn lookup_handle(file: &drm::File, handle: u32) -> Result> + fn lookup_handle(file: &drm::File, handle: u32) -> Result> where Self: AllocImpl + AlwaysRefCounted, - D: drm::Driver, - F: drm::file::DriverFile, + D: drm::Driver, { // SAFETY: The arguments are all valid per the type invariants. let ptr =3D unsafe { bindings::drm_gem_object_lookup(file.as_raw()= .cast(), handle) }; diff --git a/rust/kernel/drm/gem/shmem.rs b/rust/kernel/drm/gem/shmem.rs index a687d46d170d..793b4883de3a 100644 --- a/rust/kernel/drm/gem/shmem.rs +++ b/rust/kernel/drm/gem/shmem.rs @@ -584,7 +584,8 @@ mod tests { }, faux, io::Io, - page::PAGE_SIZE, // + page::PAGE_SIZE, + types::CovariantForLt, // }; =20 // The bare minimum needed to create a fake drm driver for kunit @@ -604,10 +605,13 @@ struct KunitObject {} desc: c"Kunit", }; =20 - impl drm::file::DriverFile for KunitFile { + impl drm::file::DriverFile<'_> for KunitFile { type Driver =3D KunitDriver; =20 - fn open(_dev: &drm::Device) -> Result>= > { + fn open( + _device: &drm::Device, + _reg_data: &(), + ) -> Result>> { Ok(KBox::new(Self, GFP_KERNEL)?.into()) } } @@ -629,7 +633,7 @@ fn new( impl drm::Driver for KunitDriver { type Data =3D KunitData; type RegistrationData<'a> =3D (); - type File =3D KunitFile; + type File =3D CovariantForLt!(KunitFile); type Object =3D Object; type ParentDevice =3D faux::Device; =20 diff --git a/rust/kernel/drm/ioctl.rs b/rust/kernel/drm/ioctl.rs index 9934b23c36eb..8ac7fb1d4ec2 100644 --- a/rust/kernel/drm/ioctl.rs +++ b/rust/kernel/drm/ioctl.rs @@ -97,7 +97,7 @@ pub const fn __dev_ctx_cast( /// fn foo(device: &kernel::drm::Device, /// reg_data: &Self::RegistrationData<'_>, /// data: &mut uapi::argument_type, -/// file: &kernel::drm::File, +/// file: &kernel::drm::File, /// ) -> Result /// ``` /// where `Self` is the drm::drv::Driver implementation these ioctls are b= eing declared within. --=20 2.55.0 From nobody Mon Sep 28 23:53:10 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 24CF73DEACE; Fri, 14 Aug 2026 23:10:05 +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=1786749007; cv=none; b=rri1HHAtUfJKWNbjm2xrxSj2qSkRrgYu40s/Ia/vSbDs4sJeuDU0UjGe5uduuvoUw/HbLblFBJbz9ObaC/Ygkt7yeakfjXb4ATLKB1MXEsJD0ShTnoHFHJ0aP79Abh1kLJ6fnj6rvTO+3/G61h3iDhyJnpYRHkc8krLSE9RxBxs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786749007; c=relaxed/simple; bh=23qqp3tV/Af4FpxnD6uOnEfexkKPNPXn9Eqvow8dJeU=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=lILNL+OCCLXobRcIUpJUaGcWEsvEkKYD8/DbbHD7HonQMaOzjnAcEkHRUFHW2GP0MSTXvOfSyfISQQp61P2Z2fVyXCWJ4gxySMdYRfkOgP18zT0ew6g155Ps41ECzNe9ce8DnxMKNCyzCSHfHs5s81+9Nho8sU6sCux2OSWMOPc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=PW9O/W4y; 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="PW9O/W4y" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 7F9C21F00ACA; Fri, 14 Aug 2026 23:10:00 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1786749005; bh=ezGmrhqJWxcPMTxdp1bMwe75jVYSM3ZOzLYKZoXyWOw=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=PW9O/W4yJhdsuTGeeFrVntyLiEUfVRIfxdxa3ss7tY3ZmpcvOoiUzICi2jsoV/79K nm6hh7GBwQD1dyThq0+EMTGTEfInkdnkXQ0h4H8eRRJ4mOog/ypKnN6TBBPSYwNzb0 dB2/xyeFsXEPNHtqnQplOaAfWTWm297Jp5r1wOHgO4twftphDNc8hdEhwHzmgd1a48 qnz8TBlSDO1FsRSM7JE53ZutKSstl70fcdCXUiM6NGoiiNd1ki9bZgivclqTBjOimV AWSGSeoPVd05vENQdM8vhiNAgQrH6y9kRLkQk47dza+Yfy0SED4Pj9gseav4LVvzEm hOooO9ZoSRaXw== From: Danilo Krummrich To: dakr@kernel.org, aliceryhl@google.com, acourbot@nvidia.com, daniel.almeida@collabora.com, ojeda@kernel.org, boqun@kernel.org, gary@garyguo.net, bjorn3_gh@protonmail.com, lossin@kernel.org, a.hindborg@kernel.org, tmgross@umich.edu, tamird@kernel.org, work@onurozkan.dev, brauner@kernel.org, lyude@redhat.com, j@jananu.net, alvin.sun@linux.dev, deborah.brouwer@collabora.com, laura.nao@collabora.com, beata.michalska@arm.com Cc: nova-gpu@lists.linux.dev, dri-devel@lists.freedesktop.org, rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH 7/7] rust: drm: return impl PinInit from DriverFile::open() Date: Sat, 15 Aug 2026 01:09:05 +0200 Message-ID: <20260814230923.1292966-8-dakr@kernel.org> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260814230923.1292966-1-dakr@kernel.org> References: <20260814230923.1292966-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" Change DriverFile::open() to return impl PinInit instead of Result>>, consistent with how bus device private data works. Drivers no longer need to allocate a Pin> themselves; they just return an initializer and the subsystem takes care of the allocation. Signed-off-by: Danilo Krummrich --- drivers/gpu/drm/nova/file.rs | 4 ++-- drivers/gpu/drm/tyr/file.rs | 4 ++-- rust/kernel/drm/file.rs | 7 ++++--- rust/kernel/drm/gem/shmem.rs | 4 ++-- 4 files changed, 10 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/nova/file.rs b/drivers/gpu/drm/nova/file.rs index 1f94201af92b..30bbabe6ee78 100644 --- a/drivers/gpu/drm/nova/file.rs +++ b/drivers/gpu/drm/nova/file.rs @@ -20,8 +20,8 @@ impl drm::file::DriverFile<'_> for File { type Driver =3D NovaDriver; =20 - fn open(_device: &NovaDevice, _reg_data: &()) -> Result>> { - Ok(KBox::new(Self, GFP_KERNEL)?.into()) + fn open(_device: &NovaDevice, _reg_data: &()) -> impl PinI= nit { + Ok(Self) } } =20 diff --git a/drivers/gpu/drm/tyr/file.rs b/drivers/gpu/drm/tyr/file.rs index 0e0878090de6..933a365cb016 100644 --- a/drivers/gpu/drm/tyr/file.rs +++ b/drivers/gpu/drm/tyr/file.rs @@ -28,8 +28,8 @@ impl drm::file::DriverFile<'_> for TyrDrmFileData { fn open( _device: &TyrDrmDevice, _reg_data: &TyrDrmRegistrationData<'_>, - ) -> Result>> { - KBox::try_pin_init(try_pin_init!(Self {}), GFP_KERNEL) + ) -> impl PinInit { + Ok(Self {}) } } =20 diff --git a/rust/kernel/drm/file.rs b/rust/kernel/drm/file.rs index 6491ec5707a0..31fc318eb535 100644 --- a/rust/kernel/drm/file.rs +++ b/rust/kernel/drm/file.rs @@ -30,12 +30,12 @@ pub trait DriverFile<'a>: Sized { =20 /// Open a new DRM file, creating the per-file driver data. /// - /// Called when a client opens the DRM device. The returned file data = may borrow from + /// Called when a client opens the DRM device. The returned initialize= r may borrow from /// `reg_data` with lifetime `'a`. fn open( device: &drm::Device, reg_data: &'a ::RegistrationData<'a>, - ) -> Result>>; + ) -> impl PinInit; } =20 /// An open DRM File. @@ -107,7 +107,8 @@ pub(crate) extern "C" fn open_callback( unsafe { drm::device::Device::from_raw(raw_dev) }; =20 dev.registration_data_with(|reg_data| { - let inner =3D match <::Of<'_> as DriverFile<= '_>>::open(dev, reg_data) { + let init =3D <::Of<'_> as DriverFile<'_>>::o= pen(dev, reg_data); + let inner =3D match KBox::try_pin_init(init, GFP_KERNEL) { Err(e) =3D> return e.to_errno(), Ok(i) =3D> i, }; diff --git a/rust/kernel/drm/gem/shmem.rs b/rust/kernel/drm/gem/shmem.rs index 793b4883de3a..d882b505fe0f 100644 --- a/rust/kernel/drm/gem/shmem.rs +++ b/rust/kernel/drm/gem/shmem.rs @@ -611,8 +611,8 @@ impl drm::file::DriverFile<'_> for KunitFile { fn open( _device: &drm::Device, _reg_data: &(), - ) -> Result>> { - Ok(KBox::new(Self, GFP_KERNEL)?.into()) + ) -> impl PinInit { + Ok(Self) } } =20 --=20 2.55.0