From nobody Tue Sep 29 07:39:11 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 260F73B19D9; Mon, 10 Aug 2026 22:50:01 +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=1786402203; cv=none; b=XebNFjLdRwWGn3HedKmqZxwGKBf8cHPBKZSUaM2uR5G+3spdG4Av+Z/P58kC8y3CWldBaRNwpwtHTZOvOmq4ipoPi8m1MYqeSYZXci+1hYMdM6u/Atf9uXMsZaaAninFXYYp3meR7K4BimpAHDRCXrWqIKlscjHPZhXEhhx+VD0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786402203; c=relaxed/simple; bh=wMqEVW5kWhDeIECn7gd5WW2NWRQ88U2SA09YBzsxIWQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=E/TR7K730T5I1zali24oH9k66UWW+W+2kqAMogYDQ0hHnTJvY33ziTnxgFT2KOk0M8MbXOI+/HjAUAMxulpfP9UD1kAihb6FwuvDS4OpV/Lp/wsXgRN5n2lGZ6mUlumP7vxxl625Xer8Nu56WuganN24xuq/uFl5xAJ5ZvegN6o= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=O96udFG4; 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="O96udFG4" Received: by smtp.kernel.org (Postfix) with ESMTPSA id D1BB71F00A3A; Mon, 10 Aug 2026 22:49:56 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1786402201; bh=37IhENiCIf1Rxw+TUNdCHt8A5GZ16leg1dT5esUP9zE=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=O96udFG4ZkgHwcvEbW8Kwb0fguD6dKXMADB8xh/Wday4AU0IPJLxZ5a/EUFZVd/sH 0bl4Ik5Z8DnDPjfi56IV8EIvaA7kBFDNmE7s2x5GKL+VefkCD2RtGNzuSw5CFFYT9L 9InXtj6Yp2Gz5ZzIE6PlqusUe0YhEotu5FRw8otelEEf5UPIEczgKP9WPiV1ylsjNV IzZUMkpbapa8VfqNUzn29l7vBvmVEJEcqlf2TvSCH9uK2WrYWEy0qpp6J6wbmGxpoC 6v3o6HLpUen1xppY9OsCekWrxy2SCVIhAbvvC6QjS/WdZYdo/Drs0qix2cH0Xs9/7Y kForV2k4FXapw== From: Danilo Krummrich To: bhelgaas@google.com, dakr@kernel.org, kwilczynski@kernel.org, aliceryhl@google.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, acourbot@nvidia.com, work@onurozkan.dev, jhubbard@nvidia.com, ttabi@nvidia.com, apopple@nvidia.com, ecourtney@nvidia.com, shashanks@nvidia.com, zhiw@nvidia.com Cc: driver-core@lists.linux.dev, linux-pci@vger.kernel.org, rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH 1/5] rust: irq: add anchor generic to IrqRequest and Registration Date: Tue, 11 Aug 2026 00:47:40 +0200 Message-ID: <20260810224800.2314458-2-dakr@kernel.org> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260810224800.2314458-1-dakr@kernel.org> References: <20260810224800.2314458-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 an IrqRequestAnchor marker trait and a generic parameter A (defaulting to ()) on IrqRequest, Registration, and ThreadedRegistration. Bus-specific IRQ sources can implement IrqRequestAnchor for a reference to their allocation type, so that the Registration stores a real borrow of the allocation and prevents it from being dropped while the handler is live. The default anchor () keeps all existing behavior unchanged; platform devices are unaffected. Add a new constructor IrqRequest::new_anchored() that accepts the anchor value. The existing IrqRequest::new() continues to produce IrqRequest<'a, ()>. Signed-off-by: Danilo Krummrich --- rust/kernel/irq.rs | 10 ++++- rust/kernel/irq/request.rs | 86 ++++++++++++++++++++++++++++---------- 2 files changed, 71 insertions(+), 25 deletions(-) diff --git a/rust/kernel/irq.rs b/rust/kernel/irq.rs index 09ef1e7f853c..dd3cc6969ebf 100644 --- a/rust/kernel/irq.rs +++ b/rust/kernel/irq.rs @@ -19,6 +19,12 @@ pub use flags::Flags; =20 pub use request::{ - Handler, IrqRequest, IrqReturn, Registration, ThreadedHandler, Threade= dIrqReturn, - ThreadedRegistration, + Handler, + IrqRequest, + IrqRequestAnchor, + IrqReturn, + Registration, + ThreadedHandler, + ThreadedIrqReturn, + ThreadedRegistration, // }; diff --git a/rust/kernel/irq/request.rs b/rust/kernel/irq/request.rs index c1c6525a676a..760381a07816 100644 --- a/rust/kernel/irq/request.rs +++ b/rust/kernel/irq/request.rs @@ -44,17 +44,31 @@ pub trait Handler: Sync { fn handle(&self) -> IrqReturn; } =20 +/// Marker trait for the anchor stored in an [`IrqRequest`]. +/// +/// Bus-specific IRQ sources can implement this for a reference to their a= llocation type, so that +/// the [`Registration`] that stores the request keeps the allocation aliv= e. The default `()` +/// imposes no constraint beyond the device lifetime. +pub trait IrqRequestAnchor: Send + Sync {} + +impl IrqRequestAnchor for () {} + /// A request for an IRQ line for a given device. /// +/// The anchor `A` is stored in the [`Registration`] built from this reque= st. When `A` is a +/// reference to a bus-specific allocation, the borrow prevents the alloca= tion from being dropped +/// before the handler is freed. +/// /// # Invariants /// /// - `=C3=ACrq` is the number of an interrupt source of `dev`. /// - `irq` has not been registered yet; this is consumed by [`Registratio= n::new()`]. -pub struct IrqRequest<'a> { +pub struct IrqRequest<'a, A: IrqRequestAnchor =3D ()> { irq: u32, /// Proves the device is bound at registration time and ties `'a` to t= he device's bound /// lifetime, ensuring the [`Registration`] cannot outlive it. _dev: PhantomData<&'a Device>, + anchor: A, } =20 impl<'a> IrqRequest<'a> { @@ -63,14 +77,34 @@ impl<'a> IrqRequest<'a> { /// # Safety /// /// - `irq` should be a valid IRQ number for `dev`. + #[inline] pub(crate) unsafe fn new(_dev: &'a Device, irq: u32) -> Self { + // SAFETY: Caller guarantees `irq` is valid for `dev`. + unsafe { Self::new_anchored(_dev, irq, ()) } + } +} + +impl<'a, A: IrqRequestAnchor> IrqRequest<'a, A> { + /// Creates a new IRQ request with an anchor to a bus-specific resourc= e allocation. + /// + /// # Safety + /// + /// `irq` must be a valid IRQ number for `dev`. + #[inline] + pub(crate) unsafe fn new_anchored(_dev: &'a Device, irq: u32, a= nchor: A) -> Self { // INVARIANT: `irq` is a valid IRQ number for `dev`. IrqRequest { irq, _dev: PhantomData, + anchor, } } =20 + /// Returns a reference to the anchor. + pub fn anchor(&self) -> &A { + &self.anchor + } + /// Returns the IRQ number of an [`IrqRequest`]. #[inline] pub fn irq(&self) -> u32 { @@ -154,8 +188,8 @@ pub fn irq(&self) -> u32 { /// /// * We own an irq handler registered via `request_irq` whose cookie is a= pointer to `Self`. #[pin_data(PinnedDrop)] -pub struct Registration<'a, T: Handler> { - request: IrqRequest<'a>, +pub struct Registration<'a, T: Handler, A: IrqRequestAnchor =3D ()> { + request: IrqRequest<'a, A>, =20 #[pin] handler: T, @@ -166,7 +200,7 @@ pub struct Registration<'a, T: Handler> { _pin: PhantomPinned, } =20 -impl<'a, T: Handler> Registration<'a, T> { +impl<'a, T: Handler, A: IrqRequestAnchor + 'a> Registration<'a, T, A> { /// Registers the IRQ handler with the system for the given IRQ number. /// /// # Safety @@ -174,7 +208,7 @@ impl<'a, T: Handler> Registration<'a, T> { /// Callers must not `mem::forget()` the returned [`Registration`] or = otherwise prevent its /// [`Drop`] implementation from running. pub unsafe fn new( - request: IrqRequest<'a>, + request: IrqRequest<'a, A>, flags: Flags, name: &'static CStr, handler: impl PinInit + 'a, @@ -199,7 +233,7 @@ pub unsafe fn new( to_result(unsafe { bindings::request_irq( request.irq, - Some(handle_irq_callback::), + Some(handle_irq_callback::), flags.into_inner(), name.as_char_ptr(), this.as_ptr().cast::(), @@ -223,7 +257,7 @@ pub fn synchronize(&self) { } =20 #[pinned_drop] -impl PinnedDrop for Registration<'_, T> { +impl PinnedDrop for Registration<'_, T, A= > { fn drop(self: Pin<&mut Self>) { // SAFETY: The cookie was set to a pointer to `Self` in `Registrat= ion::new()`. This blocks // until all in-flight handlers complete, so no references to `sel= f` remain after this @@ -240,9 +274,12 @@ fn drop(self: Pin<&mut Self>) { /// # Safety /// /// This function should be only used as the callback in `request_irq`. -unsafe extern "C" fn handle_irq_callback(_irq: i32, ptr: *mut = c_void) -> c_uint { - let ptr =3D ptr.cast_const().cast::>(); - // SAFETY: `ptr` is a pointer to `Registration<'_, T>` set in `Registr= ation::new()`. +unsafe extern "C" fn handle_irq_callback( + _irq: i32, + ptr: *mut c_void, +) -> c_uint { + let ptr =3D ptr.cast_const().cast::>(); + // SAFETY: `ptr` is a pointer to `Registration<'_, T, A>` set in `Regi= stration::new()`. let registration =3D unsafe { &*ptr }; =20 T::handle(®istration.handler) as c_uint @@ -371,8 +408,8 @@ fn handle(&self) -> ThreadedIrqReturn { /// * We own an irq handler registered via `request_threaded_irq` whose co= okie is a pointer to /// `Self`. #[pin_data(PinnedDrop)] -pub struct ThreadedRegistration<'a, T: ThreadedHandler> { - request: IrqRequest<'a>, +pub struct ThreadedRegistration<'a, T: ThreadedHandler, A: IrqRequestAncho= r =3D ()> { + request: IrqRequest<'a, A>, =20 #[pin] handler: T, @@ -383,7 +420,7 @@ pub struct ThreadedRegistration<'a, T: ThreadedHandler>= { _pin: PhantomPinned, } =20 -impl<'a, T: ThreadedHandler> ThreadedRegistration<'a, T> { +impl<'a, T: ThreadedHandler, A: IrqRequestAnchor + 'a> ThreadedRegistratio= n<'a, T, A> { /// Registers the IRQ handler with the system for the given IRQ number. /// /// # Safety @@ -391,7 +428,7 @@ impl<'a, T: ThreadedHandler> ThreadedRegistration<'a, T= > { /// Callers must not `mem::forget()` the returned [`ThreadedRegistrati= on`] or otherwise prevent /// its [`Drop`] implementation from running. pub unsafe fn new( - request: IrqRequest<'a>, + request: IrqRequest<'a, A>, flags: Flags, name: &'static CStr, handler: impl PinInit + 'a, @@ -416,8 +453,8 @@ pub unsafe fn new( to_result(unsafe { bindings::request_threaded_irq( request.irq, - Some(handle_threaded_irq_callback::), - Some(thread_fn_callback::), + Some(handle_threaded_irq_callback::), + Some(thread_fn_callback::), flags.into_inner(), name.as_char_ptr(), this.as_ptr().cast::(), @@ -441,7 +478,7 @@ pub fn synchronize(&self) { } =20 #[pinned_drop] -impl PinnedDrop for ThreadedRegistration<'_, T> { +impl PinnedDrop for ThreadedRegis= tration<'_, T, A> { fn drop(self: Pin<&mut Self>) { // SAFETY: The cookie was set to a pointer to `Self` in `ThreadedR= egistration::new()`. This // blocks until all in-flight handlers complete, so no references = to `self` remain after @@ -458,12 +495,12 @@ fn drop(self: Pin<&mut Self>) { /// # Safety /// /// This function should be only used as the callback in `request_threaded= _irq`. -unsafe extern "C" fn handle_threaded_irq_callback( +unsafe extern "C" fn handle_threaded_irq_callback( _irq: i32, ptr: *mut c_void, ) -> c_uint { - let ptr =3D ptr.cast_const().cast::>(); - // SAFETY: `ptr` is a pointer to `ThreadedRegistration<'_, T>` set in + let ptr =3D ptr.cast_const().cast::>(); + // SAFETY: `ptr` is a pointer to `ThreadedRegistration<'_, T, A>` set = in // `ThreadedRegistration::new()`. let registration =3D unsafe { &*ptr }; =20 @@ -473,9 +510,12 @@ fn drop(self: Pin<&mut Self>) { /// # Safety /// /// This function should be only used as the callback in `request_threaded= _irq`. -unsafe extern "C" fn thread_fn_callback(_irq: i32, ptr= : *mut c_void) -> c_uint { - let ptr =3D ptr.cast_const().cast::>(); - // SAFETY: `ptr` is a pointer to `ThreadedRegistration<'_, T>` set in +unsafe extern "C" fn thread_fn_callback( + _irq: i32, + ptr: *mut c_void, +) -> c_uint { + let ptr =3D ptr.cast_const().cast::>(); + // SAFETY: `ptr` is a pointer to `ThreadedRegistration<'_, T, A>` set = in // `ThreadedRegistration::new()`. let registration =3D unsafe { &*ptr }; =20 --=20 2.55.0 From nobody Tue Sep 29 07:39:11 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 724193B71DD; Mon, 10 Aug 2026 22:50:07 +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=1786402209; cv=none; b=aWxqdjwc+PeqtUqtd5+5K840ugFNiEGH/dGJpzvOeofhC+STYOsNQOFEO5eB058r11dRpdpT9BIKcMajX+dO7AfKLR4d8ZPK3XJyAPvUntNTox5fS93nBO7zGA47yBAsrQwtDF1YvW6h81J9zXvf2lRbOu0/KQh00XuxSlpxHsA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786402209; c=relaxed/simple; bh=Lvfzj5zN7Zwm6y+3PnVJ3bn6c9irRDFYizK1UrugL98=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=eHy4fMrtWj5dbIYpQZ9Ti9xZjJ4rOq343anNSXAhM1oj3fxpgioTqeqmZoQ1jAk7hk8Sqo8qkmzoQRMhbs4nvHKy+/f7aw5teOm4cSlIrbrC4/B/G6JG3dNTRkPPxmFkkZlL2vTVGeK5brbBd9wDKp2nx6n5mhq8plp6k17oCXI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=UcQLSXWl; 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="UcQLSXWl" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 367D61F00A3D; Mon, 10 Aug 2026 22:50:02 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1786402207; bh=3Uy2Drsg3lgnFSs2+IXD1x4C86h7DBNQn78tkm2llMk=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=UcQLSXWl2BEvzt+25JfScVknhOOhojUcIXGowv42zyYP2IytncG+/s5LgFSbyhd+7 FCl7FiLKURliVcnCoy04MR1SZhoY8CQpvaLg1BdcRyIG2rfjsOpMyoHzNJw8QCmVVB jqZS8GUlShhLdEqUiz3Vu/NnVkrn7dhQqsrvRFVcCnvc6GvvmHnIFKEqwzq78MexMp o2SDl1brrwXK5DpATJqEn8tjt3UlwwDC02xB62uLhFHOObKD3zWnt8YoqOp6zBAU0o TZFYyDoXvQMfzDwPvXs1aObz4ZV4N4dkUqBVWDfd4z+ixaEu56BokuqoS4X4AExspB zINfjcXE60JCQ== From: Danilo Krummrich To: bhelgaas@google.com, dakr@kernel.org, kwilczynski@kernel.org, aliceryhl@google.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, acourbot@nvidia.com, work@onurozkan.dev, jhubbard@nvidia.com, ttabi@nvidia.com, apopple@nvidia.com, ecourtney@nvidia.com, shashanks@nvidia.com, zhiw@nvidia.com Cc: driver-core@lists.linux.dev, linux-pci@vger.kernel.org, rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH 2/5] rust: pci: convert IrqVectorRegistration to a lifetime-managed owning type Date: Tue, 11 Aug 2026 00:47:41 +0200 Message-ID: <20260810224800.2314458-3-dakr@kernel.org> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260810224800.2314458-1-dakr@kernel.org> References: <20260810224800.2314458-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 IrqVectorRegistration from a devres-managed internal type to a lifetime-annotated type that owns the PCI interrupt vector allocation. Dropping it frees the vectors. IrqVector gains a reference to the IrqVectorRegistration it was derived from. This reference flows through IrqRequest (via the IrqRequestAnchor generic) into irq::Registration, creating a borrow chain that prevents the vector allocation from being dropped while any handler is still registered. alloc_irq_vectors() returns IrqVectorRegistration<'_> directly, giving drivers explicit control over the allocation lifetime. This is also needed by e.g. net and block drivers that re-allocate vectors, e.g. during queue reconfiguration or device recovery. Signed-off-by: Danilo Krummrich --- rust/kernel/pci.rs | 3 +- rust/kernel/pci/irq.rs | 149 ++++++++++++++++++++++------------------- 2 files changed, 83 insertions(+), 69 deletions(-) diff --git a/rust/kernel/pci.rs b/rust/kernel/pci.rs index c6417af2bb17..2757a0cc0f11 100644 --- a/rust/kernel/pci.rs +++ b/rust/kernel/pci.rs @@ -51,7 +51,8 @@ pub use self::irq::{ IrqType, IrqTypes, - IrqVector, // + IrqVector, + IrqVectorRegistration, // }; =20 /// An adapter for the registration of PCI drivers. diff --git a/rust/kernel/pci/irq.rs b/rust/kernel/pci/irq.rs index fea484dcf9cf..38a7d72dcda7 100644 --- a/rust/kernel/pci/irq.rs +++ b/rust/kernel/pci/irq.rs @@ -7,17 +7,15 @@ bindings, device, device::Bound, - devres, error::to_result, irq::{ self, - IrqRequest, // + IrqRequest, + IrqRequestAnchor, // }, - prelude::*, - str::CStr, - sync::aref::ARef, // + prelude::*, // }; -use core::ops::RangeInclusive; +use core::num::NonZero; =20 /// IRQ type flags for PCI interrupt allocation. #[derive(Debug, Clone, Copy)] @@ -78,6 +76,7 @@ const fn as_raw(self) -> u32 { #[derive(Clone, Copy)] pub struct IrqVector<'a> { dev: &'a Device, + reg: &'a IrqVectorRegistration<'a>, index: u32, } =20 @@ -86,10 +85,11 @@ impl<'a> IrqVector<'a> { /// /// # Safety /// - /// - `index` must be a valid IRQ vector index for `dev`. - /// - `dev` must point to a [`Device`] that has successfully allocated= IRQ vectors. - unsafe fn new(dev: &'a Device, index: u32) -> Self { - Self { dev, index } + /// - `index` must be a valid IRQ vector index for `reg`. + /// - `dev` must be the device `reg` was allocated from. + #[inline] + unsafe fn new(dev: &'a Device, reg: &'a IrqVectorRegistration<'= a>, index: u32) -> Self { + Self { dev, reg, index } } =20 /// Returns the raw vector index. @@ -98,75 +98,72 @@ fn index(&self) -> u32 { } } =20 -impl<'a> TryInto> for IrqVector<'a> { +impl IrqRequestAnchor for &IrqVectorRegistration<'_> {} + +impl<'a> IrqRequest<'a, &'a IrqVectorRegistration<'a>> { + /// Returns the [`IrqVectorRegistration`] this request was derived fro= m. + pub fn vectors(&self) -> &'a IrqVectorRegistration<'a> { + self.anchor() + } +} + +impl<'a> TryInto>> for IrqVec= tor<'a> { type Error =3D Error; =20 - fn try_into(self) -> Result> { - // SAFETY: `self.as_raw` returns a valid pointer to a `struct pci_= dev`. + fn try_into(self) -> Result>> { + // SAFETY: `self.dev.as_raw()` returns a valid pointer to a `struc= t pci_dev`. let irq =3D unsafe { bindings::pci_irq_vector(self.dev.as_raw(), s= elf.index()) }; if irq < 0 { return Err(crate::error::Error::from_errno(irq)); } - // SAFETY: `irq` is guaranteed to be a valid IRQ number for `&self= `. - Ok(unsafe { IrqRequest::new(self.dev.as_ref(), irq as u32) }) + // SAFETY: `irq` is guaranteed to be a valid IRQ number for `self.= dev`. + Ok(unsafe { IrqRequest::new_anchored(self.dev.as_ref(), irq as u32= , self.reg) }) } } =20 -/// Represents an IRQ vector allocation for a PCI device. +/// An allocation of PCI interrupt vectors for a device. /// -/// This type ensures that IRQ vectors are properly allocated and freed by -/// tying the allocation to the lifetime of this registration object. +/// This type owns the vector allocation; dropping it frees the vectors. I= RQ handlers borrow from +/// this registration and must be dropped before it is. /// /// # Invariants /// -/// The [`Device`] has successfully allocated IRQ vectors. -struct IrqVectorRegistration { - dev: ARef, +/// `dev` has an allocation of `count` interrupt vectors. +pub struct IrqVectorRegistration<'a> { + dev: &'a Device, + count: NonZero, } =20 -impl IrqVectorRegistration { - /// Allocate and register IRQ vectors for the given PCI device. +impl<'a> IrqVectorRegistration<'a> { + /// Returns the number of allocated vectors. /// - /// Allocates IRQ vectors and registers them with devres for automatic= cleanup. - /// Returns a range of valid IRQ vectors. - fn register<'a>( - dev: &'a Device, - min_vecs: u32, - max_vecs: u32, - irq_types: IrqTypes, - ) -> Result>> { - // SAFETY: - // - `dev.as_raw()` is guaranteed to be a valid pointer to a `stru= ct pci_dev` - // by the type invariant of `Device`. - // - `pci_alloc_irq_vectors` internally validates all other parame= ters - // and returns error codes. - let ret =3D unsafe { - bindings::pci_alloc_irq_vectors(dev.as_raw(), min_vecs, max_ve= cs, irq_types.as_raw()) - }; - - to_result(ret)?; - let count =3D ret as u32; - - // SAFETY: - // - `pci_alloc_irq_vectors` returns the number of allocated vecto= rs on success. - // - Vectors are 0-based, so valid indices are [0, count-1]. - // - `pci_alloc_irq_vectors` guarantees `count >=3D min_vecs > 0`,= so both `0` and - // `count - 1` are valid IRQ vector indices for `dev`. - let range =3D unsafe { IrqVector::new(dev, 0)..=3DIrqVector::new(d= ev, count - 1) }; + /// This is at least the `min_vecs` that [`Device::alloc_irq_vectors`]= was asked for. + #[inline] + pub fn vector_count(&self) -> usize { + self.count.get() + } =20 - // INVARIANT: The IRQ vector allocation for `dev` above was succes= sful. - let irq_vecs =3D Self { dev: dev.into() }; - devres::register(dev.as_ref(), irq_vecs, GFP_KERNEL)?; + /// Returns the [`IrqVector`] at `index`. + /// + /// The returned [`IrqVector`] borrows from this registration, ensurin= g the vector allocation + /// remains live while any handler is registered on it. + #[inline] + pub fn vector(&self, index: usize) -> Result> { + if index >=3D self.count.get() { + return Err(EINVAL); + } =20 - Ok(range) + // SAFETY: `index` is within bounds of this registration's allocat= ion, and `self.dev` is + // the device it was allocated from. + Ok(unsafe { IrqVector::new(self.dev, self, index as u32) }) } } =20 -impl Drop for IrqVectorRegistration { +impl Drop for IrqVectorRegistration<'_> { + #[inline] fn drop(&mut self) { - // SAFETY: - // - By the type invariant, `self.dev.as_raw()` is a valid pointer= to a `struct pci_dev`. - // - `self.dev` has successfully allocated IRQ vectors. + // SAFETY: By the type invariant, `self.dev.as_raw()` is a valid p= ointer to a + // `struct pci_dev` that has successfully allocated IRQ vectors. unsafe { bindings::pci_free_irq_vectors(self.dev.as_raw()) }; } } @@ -184,12 +181,12 @@ pub unsafe fn request_irq<'a, T: crate::irq::Handler = + 'a>( flags: irq::Flags, name: &'static CStr, handler: impl PinInit + 'a, - ) -> impl PinInit, Error> + 'a { + ) -> impl PinInit>, Error> + 'a { pin_init::pin_init_scope(move || { let request =3D vector.try_into()?; =20 // SAFETY: Caller guarantees the Registration will not be leak= ed. - Ok(unsafe { irq::Registration::::new(request, flags, name, = handler) }) + Ok(unsafe { irq::Registration::new(request, flags, name, handl= er) }) }) } =20 @@ -205,24 +202,26 @@ pub unsafe fn request_threaded_irq<'a, T: crate::irq:= :ThreadedHandler + 'a>( flags: irq::Flags, name: &'static CStr, handler: impl PinInit + 'a, - ) -> impl PinInit, Error> + 'a { + ) -> impl PinInit>, Error> + 'a + { pin_init::pin_init_scope(move || { let request =3D vector.try_into()?; =20 // SAFETY: Caller guarantees the Registration will not be leak= ed. - Ok(unsafe { irq::ThreadedRegistration::::new(request, flags= , name, handler) }) + Ok(unsafe { irq::ThreadedRegistration::new(request, flags, nam= e, handler) }) }) } =20 - /// Allocate IRQ vectors for this PCI device with automatic cleanup. + /// Allocate IRQ vectors for this PCI device. /// /// Allocates between `min_vecs` and `max_vecs` interrupt vectors for = the device. /// The allocation will use MSI-X, MSI, or INTx interrupts based on th= e `irq_types` /// parameter and hardware capabilities. When multiple types are speci= fied, the kernel /// will try them in order of preference: MSI-X first, then MSI, then = INTx interrupts. /// - /// The allocated vectors are automatically freed when the device is u= nbound, using the - /// devres (device resource management) system. + /// The allocated vectors are freed when the returned [`IrqVectorRegis= tration`] is dropped. + /// IRQ handlers registered via [`Self::request_irq`] or [`Self::reque= st_threaded_irq`] + /// borrow from the registration, so the compiler ensures they are fre= ed first. /// /// # Arguments /// @@ -232,8 +231,8 @@ pub unsafe fn request_threaded_irq<'a, T: crate::irq::T= hreadedHandler + 'a>( /// /// # Returns /// - /// Returns a range of IRQ vectors that were successfully allocated, o= r an error if the - /// allocation fails or cannot meet the minimum requirement. + /// Returns the IRQ vector registration, or an error if `min_vecs` vec= tors cannot be + /// allocated. /// /// # Examples /// @@ -256,7 +255,21 @@ pub fn alloc_irq_vectors( min_vecs: u32, max_vecs: u32, irq_types: IrqTypes, - ) -> Result>> { - IrqVectorRegistration::register(self, min_vecs, max_vecs, irq_type= s) + ) -> Result> { + // SAFETY: + // - `self.as_raw()` is guaranteed to be a valid pointer to a `str= uct pci_dev` + // by the type invariant of `Device`. + // - `pci_alloc_irq_vectors` internally validates all other parame= ters + // and returns error codes. + let ret =3D unsafe { + bindings::pci_alloc_irq_vectors(self.as_raw(), min_vecs, max_v= ecs, irq_types.as_raw()) + }; + + to_result(ret)?; + + let count =3D NonZero::new(ret as usize).ok_or(EINVAL)?; + + // INVARIANT: `pci_alloc_irq_vectors()` allocated `count` vectors = for `self`. + Ok(IrqVectorRegistration { dev: self, count }) } } --=20 2.55.0 From nobody Tue Sep 29 07:39:11 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 C324939AD3B; Mon, 10 Aug 2026 22:50: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=1786402214; cv=none; b=gCj1h4jc8/S7t5D+iuDx0yUTT4r6h92K+PiTH7001aS2xp/PI8C2lCWXh//qSerHibLyRaZYl0iwgJ3qVbuIhMxn2V/HTgw71+LPtjqA0oGuiaCBvWld497qCtPCO7heV0JRHyAeHe23FabiNzG3eGQaHF1ONEr+xX3KqfBSQEc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786402214; c=relaxed/simple; bh=fVhkaAYsHwHl2ZNPSTLjEiNP4c8pdj212fQ2gFanOrc=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=sayN762SxEwlUUun0VrrSjl+J8/NLWnugaUl7QWUJC4onYECKKkBMkEHT3pxRZMFaY/6YWgoo072BnALvQ/FxucQWnsiVvNI7YVmIrxA3qHY/gpUXE6Acm9Oo/Ktc/rZDSYtYF82oVQQMgNxLhONphpsrYusdkAUjlhH5C1J6sA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=otj9Z5At; 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="otj9Z5At" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 9121E1F000E9; Mon, 10 Aug 2026 22:50:07 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1786402212; bh=w2oNiNgPZWWxJG/BlshTlKa5yCRKRo3XyNXanMUjbsw=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=otj9Z5AtirQQb1ZuJlRqiGIJ7hCqdiVS48Ti913qz1cP+yceqUe5Ho2SSCB+jodG8 y0d9cFiQodSvpneg6zrOXhS/VDftD+Mv+D/btv7wVqcDXZW+K2HJuAUroFIpGTG+6e 0EEpvjZVqDql0CrcL23N4SaIKmYuGr8HHS7mhoe61NVaqD9Ll3kGJrJ45VdDcWC5Ek 8yWXSFVkw9aTTgovgDomxHvBQtXbggy5DQ1b+7M1lWk3BJHCGrFx78cLZrT9pvcLWC sNwCpbjAn36FAxseHUykiWRfTUhzvdiKS2/UQQnU3uu6EgUwMfMKQVnheLgXCyLOoq 0uF7YQLeW4XOg== From: Danilo Krummrich To: bhelgaas@google.com, dakr@kernel.org, kwilczynski@kernel.org, aliceryhl@google.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, acourbot@nvidia.com, work@onurozkan.dev, jhubbard@nvidia.com, ttabi@nvidia.com, apopple@nvidia.com, ecourtney@nvidia.com, shashanks@nvidia.com, zhiw@nvidia.com Cc: driver-core@lists.linux.dev, linux-pci@vger.kernel.org, rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH 3/5] rust: pci: remove IrqVector and resolve IrqRequest directly Date: Tue, 11 Aug 2026 00:47:42 +0200 Message-ID: <20260810224800.2314458-4-dakr@kernel.org> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260810224800.2314458-1-dakr@kernel.org> References: <20260810224800.2314458-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" Remove the IrqVector intermediate type; IrqVectorRegistration::request() now resolves a vector index to an IrqRequest directly, combining the bounds check and pci_irq_vector() call in one step. Also remove Device::request_irq() and Device::request_threaded_irq(), which only exist to convert IrqVector to IrqRequest. Drivers pass the IrqRequest from IrqVectorRegistration::request() to irq::Registration::new() directly. Signed-off-by: Danilo Krummrich --- rust/kernel/pci.rs | 1 - rust/kernel/pci/irq.rs | 109 +++++------------------------------------ 2 files changed, 13 insertions(+), 97 deletions(-) diff --git a/rust/kernel/pci.rs b/rust/kernel/pci.rs index 2757a0cc0f11..f7f6b21f64bf 100644 --- a/rust/kernel/pci.rs +++ b/rust/kernel/pci.rs @@ -51,7 +51,6 @@ pub use self::irq::{ IrqType, IrqTypes, - IrqVector, IrqVectorRegistration, // }; =20 diff --git a/rust/kernel/pci/irq.rs b/rust/kernel/pci/irq.rs index 38a7d72dcda7..d69ab6435a80 100644 --- a/rust/kernel/pci/irq.rs +++ b/rust/kernel/pci/irq.rs @@ -9,7 +9,6 @@ device::Bound, error::to_result, irq::{ - self, IrqRequest, IrqRequestAnchor, // }, @@ -69,35 +68,6 @@ const fn as_raw(self) -> u32 { } } =20 -/// Represents an allocated IRQ vector for a specific PCI device. -/// -/// This type ties an IRQ vector to the device it was allocated for, -/// ensuring the vector is only used with the correct device. -#[derive(Clone, Copy)] -pub struct IrqVector<'a> { - dev: &'a Device, - reg: &'a IrqVectorRegistration<'a>, - index: u32, -} - -impl<'a> IrqVector<'a> { - /// Creates a new [`IrqVector`] for the given device and index. - /// - /// # Safety - /// - /// - `index` must be a valid IRQ vector index for `reg`. - /// - `dev` must be the device `reg` was allocated from. - #[inline] - unsafe fn new(dev: &'a Device, reg: &'a IrqVectorRegistration<'= a>, index: u32) -> Self { - Self { dev, reg, index } - } - - /// Returns the raw vector index. - fn index(&self) -> u32 { - self.index - } -} - impl IrqRequestAnchor for &IrqVectorRegistration<'_> {} =20 impl<'a> IrqRequest<'a, &'a IrqVectorRegistration<'a>> { @@ -107,20 +77,6 @@ pub fn vectors(&self) -> &'a IrqVectorRegistration<'a> { } } =20 -impl<'a> TryInto>> for IrqVec= tor<'a> { - type Error =3D Error; - - fn try_into(self) -> Result>> { - // SAFETY: `self.dev.as_raw()` returns a valid pointer to a `struc= t pci_dev`. - let irq =3D unsafe { bindings::pci_irq_vector(self.dev.as_raw(), s= elf.index()) }; - if irq < 0 { - return Err(crate::error::Error::from_errno(irq)); - } - // SAFETY: `irq` is guaranteed to be a valid IRQ number for `self.= dev`. - Ok(unsafe { IrqRequest::new_anchored(self.dev.as_ref(), irq as u32= , self.reg) }) - } -} - /// An allocation of PCI interrupt vectors for a device. /// /// This type owns the vector allocation; dropping it frees the vectors. I= RQ handlers borrow from @@ -143,19 +99,23 @@ pub fn vector_count(&self) -> usize { self.count.get() } =20 - /// Returns the [`IrqVector`] at `index`. + /// Resolves the vector at `index` to an [`IrqRequest`]. /// - /// The returned [`IrqVector`] borrows from this registration, ensurin= g the vector allocation + /// The returned [`IrqRequest`] borrows from this registration, ensuri= ng the vector allocation /// remains live while any handler is registered on it. - #[inline] - pub fn vector(&self, index: usize) -> Result> { + pub fn request(&self, index: usize) -> Result= > { if index >=3D self.count.get() { return Err(EINVAL); } =20 - // SAFETY: `index` is within bounds of this registration's allocat= ion, and `self.dev` is - // the device it was allocated from. - Ok(unsafe { IrqVector::new(self.dev, self, index as u32) }) + // SAFETY: `self.dev.as_raw()` is a valid pointer to a `struct pci= _dev`. + let irq =3D unsafe { bindings::pci_irq_vector(self.dev.as_raw(), i= ndex as u32) }; + if irq < 0 { + return Err(Error::from_errno(irq)); + } + + // SAFETY: `irq` is a valid IRQ number for `self.dev`. + Ok(unsafe { IrqRequest::new_anchored(self.dev.as_ref(), irq as u32= , self) }) } } =20 @@ -169,49 +129,6 @@ fn drop(&mut self) { } =20 impl Device { - /// Returns a [`kernel::irq::Registration`] for the given IRQ vector. - /// - /// # Safety - /// - /// Callers must not `mem::forget()` the resulting [`irq::Registration= `] or otherwise prevent - /// its [`Drop`] implementation from running. - pub unsafe fn request_irq<'a, T: crate::irq::Handler + 'a>( - &'a self, - vector: IrqVector<'a>, - flags: irq::Flags, - name: &'static CStr, - handler: impl PinInit + 'a, - ) -> impl PinInit>, Error> + 'a { - pin_init::pin_init_scope(move || { - let request =3D vector.try_into()?; - - // SAFETY: Caller guarantees the Registration will not be leak= ed. - Ok(unsafe { irq::Registration::new(request, flags, name, handl= er) }) - }) - } - - /// Returns a [`kernel::irq::ThreadedRegistration`] for the given IRQ = vector. - /// - /// # Safety - /// - /// Callers must not `mem::forget()` the resulting [`irq::ThreadedRegi= stration`] or otherwise - /// prevent its [`Drop`] implementation from running. - pub unsafe fn request_threaded_irq<'a, T: crate::irq::ThreadedHandler = + 'a>( - &'a self, - vector: IrqVector<'a>, - flags: irq::Flags, - name: &'static CStr, - handler: impl PinInit + 'a, - ) -> impl PinInit>, Error> + 'a - { - pin_init::pin_init_scope(move || { - let request =3D vector.try_into()?; - - // SAFETY: Caller guarantees the Registration will not be leak= ed. - Ok(unsafe { irq::ThreadedRegistration::new(request, flags, nam= e, handler) }) - }) - } - /// Allocate IRQ vectors for this PCI device. /// /// Allocates between `min_vecs` and `max_vecs` interrupt vectors for = the device. @@ -220,8 +137,8 @@ pub unsafe fn request_threaded_irq<'a, T: crate::irq::T= hreadedHandler + 'a>( /// will try them in order of preference: MSI-X first, then MSI, then = INTx interrupts. /// /// The allocated vectors are freed when the returned [`IrqVectorRegis= tration`] is dropped. - /// IRQ handlers registered via [`Self::request_irq`] or [`Self::reque= st_threaded_irq`] - /// borrow from the registration, so the compiler ensures they are fre= ed first. + /// Use [`IrqVectorRegistration::request`] to obtain an [`IrqRequest`]= for a given vector + /// index. /// /// # Arguments /// --=20 2.55.0 From nobody Tue Sep 29 07:39:11 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 3574439AD3B; Mon, 10 Aug 2026 22:50: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=1786402219; cv=none; b=ACikwXA1ImdgDiVMdeKr5VJN7RM79uS5/On6KoXeGOT39LInAp2FUf6bnkoD0F3vaiqk/kLv9W013RbZ+4Mk5vKAAHE371aQvSEZ9mQtEvFzvRizFEEd2GWFdbGwgUmphF+SOI+YxaaGB25VD5oxy3qnj0Toj/N1zXbL2W514kY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786402219; c=relaxed/simple; bh=gP/fNVBFjn0Rdf4qPPe94sujlET025pmS/jkSNT7CXk=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=XAlwIuH/5cVwS6FdfDtzB27Q5/oYK81zfUanNtLxnNbLiWHOypSIggAd7QKjQ12fNi72rccg6NfihAkp938OcV65j358aghv3DGGbAMvCUuQKxY2pkkP09oNVwDl2T/KGgsvqiqVEOa+RR3W7h9Fzox1EkswxLWsucNXQXBm5Ro= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=JX90LC4J; 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="JX90LC4J" Received: by smtp.kernel.org (Postfix) with ESMTPSA id E6DE01F00A3A; Mon, 10 Aug 2026 22:50:12 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1786402217; bh=+D4M/uHINnEQaeAisENwcFYZdRyOd0W8ZlKKo1bHHe4=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=JX90LC4JDSOGj/m4G6MJBm87B083EOWD/lEMpNFvsFMP8+D1aJ4ujqlGPMB7SzjfJ BpKYfsrVBXJl5k/dugHYt2niL/COIDKQ61wzEtuHlMcrBE16rLatdpyJ4SKfDLcyu8 Ooc/IGPl2RzOZhrmzs6dLDyRgO1br6CdIMUo127xkxhaOYEG4Aqm4f+6kBlXMBY/cl P9Y+Wjr39uv5l9JokCI0fXvEueUAJpw8V5MWVIEcko45nQSYkfTKeg5jP2/IMzqCGj PM9vYpVGnWuVutmmMWD1v3+EwvTDauRwRcnv/m8MHeOoI1YJADEJiLM6sGPufPW35c vQwlnl55l4whA== From: Danilo Krummrich To: bhelgaas@google.com, dakr@kernel.org, kwilczynski@kernel.org, aliceryhl@google.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, acourbot@nvidia.com, work@onurozkan.dev, jhubbard@nvidia.com, ttabi@nvidia.com, apopple@nvidia.com, ecourtney@nvidia.com, shashanks@nvidia.com, zhiw@nvidia.com Cc: driver-core@lists.linux.dev, linux-pci@vger.kernel.org, rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH 4/5] PCI: add pci_irq_type() to query the allocated interrupt type Date: Tue, 11 Aug 2026 00:47:43 +0200 Message-ID: <20260810224800.2314458-5-dakr@kernel.org> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260810224800.2314458-1-dakr@kernel.org> References: <20260810224800.2314458-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 helper that returns PCI_IRQ_MSIX, PCI_IRQ_MSI, or PCI_IRQ_INTX based on the interrupt type the PCI core selected after pci_alloc_irq_vectors(). Several drivers already open-code this check against pdev->msix_enabled and pdev->msi_enabled, or even open code this helper [1]. A common helper avoids the duplication and keeps drivers from accessing the bitfield directly (see also [2]). Link: https://elixir.bootlin.com/linux/v7.1/source/drivers/net/ethernet/aqu= antia/atlantic/aq_pci_func.c#L196 [1] Inspired-by: John Hubbard Link: https://lore.kernel.org/all/DKKG2QM3YJYB.Z2H2B2UXJ75N@kernel.org/ [2] Signed-off-by: Danilo Krummrich Acked-by: Bjorn Helgaas --- include/linux/pci.h | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/include/linux/pci.h b/include/linux/pci.h index 64b308b6e61c..80b8561b5be0 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -1783,6 +1783,26 @@ void pci_free_irq_vectors(struct pci_dev *dev); int pci_irq_vector(struct pci_dev *dev, unsigned int nr); const struct cpumask *pci_irq_get_affinity(struct pci_dev *pdev, int vec); =20 +/** + * pci_irq_type - Get the interrupt type of a PCI device + * @pdev: the PCI device to operate on + * + * Discriminate the interrupt type the PCI core selected for this device + * after a successful pci_alloc_irq_vectors() call. + * + * Return: %PCI_IRQ_MSIX, %PCI_IRQ_MSI, or %PCI_IRQ_INTX. + */ +static inline unsigned int pci_irq_type(struct pci_dev *pdev) +{ + if (pdev->msix_enabled) + return PCI_IRQ_MSIX; + + if (pdev->msi_enabled) + return PCI_IRQ_MSI; + + return PCI_IRQ_INTX; +} + #else static inline int pci_msi_vec_count(struct pci_dev *dev) { return -ENOSYS;= } static inline void pci_disable_msi(struct pci_dev *dev) { } @@ -1845,6 +1865,11 @@ static inline const struct cpumask *pci_irq_get_affi= nity(struct pci_dev *pdev, { return cpu_possible_mask; } + +static inline unsigned int pci_irq_type(struct pci_dev *pdev) +{ + return PCI_IRQ_INTX; +} #endif =20 /** --=20 2.55.0 From nobody Tue Sep 29 07:39:11 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 964453B6BF5; Mon, 10 Aug 2026 22:50:23 +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=1786402224; cv=none; b=hpYVefXqBXzFczqcd+1hEav1SexiILhk6THvwTvsgtz18DHvK303f7EIYtit/9fpPR67wqQMBmqhIPd8bN8H2YGQr9CzYKgWnPL3HUOfW7z80f4uH1Evkad/N7sFV+lzY0l3Fhx/CRMVd/zKWoxKT+n/ynJtfpLC9dNpcu3Jhtw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786402224; c=relaxed/simple; bh=XqQVkPra4BwUQnNOr+Dt76+oCEZeQ2AKrFE4hCCngkc=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Ck/pxtugV2gzEF+XaQ5og1A4LkIPNtW8tYDQMhGG0PdzB2cDrlwCtMxdEUXFE7eneqQtM1E0PbVu7ecmrA+l5mIA1D4O+U73XKGaJKxh2Of5gej6XbY3yF4Wo+jzpZLn1QaDZmUBLyfesQzvUw56p7Adh00Ze6eQgBEW82425Qc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=N3F9aYJH; 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="N3F9aYJH" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 49D361F000E9; Mon, 10 Aug 2026 22:50:18 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1786402223; bh=2RRlOwVysOpjD6022bpwR8qZ3gP+k7XooabvZKC9zOY=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=N3F9aYJHb0zWBxS7H5baZ7K3WRZR1XLay4HIAJAdWJ76ANvVHu3kpL57oWyi3i5UF SD79QYk3uPItB+9e9aGlDQrvSQ3EpAyLT4dsSPf4Xw0co24mADX0LAP6KVe9cPSzhq TYfD3RtmAKLu1LYKgCjaBqM+167VmXVYVcFYmE5m9Pftqe7gkCNQX7wFu9jn8WL5YU jebI3iYf6QTVtNnw8+F0c53/PEyuCLU+vy499NySQO6ErAU4Fo6ffwNcu/pAjJhcD1 t4fzgDovce866zWWllO6I5VRtJL+FCmOQWFhHu4V/6FFrB5nzoY1cl76k5Z8/hfCAl p7j0hpF5D4OZA== From: Danilo Krummrich To: bhelgaas@google.com, dakr@kernel.org, kwilczynski@kernel.org, aliceryhl@google.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, acourbot@nvidia.com, work@onurozkan.dev, jhubbard@nvidia.com, ttabi@nvidia.com, apopple@nvidia.com, ecourtney@nvidia.com, shashanks@nvidia.com, zhiw@nvidia.com Cc: driver-core@lists.linux.dev, linux-pci@vger.kernel.org, rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH 5/5] rust: pci: expose the allocated interrupt type Date: Tue, 11 Aug 2026 00:47:44 +0200 Message-ID: <20260810224800.2314458-6-dakr@kernel.org> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260810224800.2314458-1-dakr@kernel.org> References: <20260810224800.2314458-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 irq_type() on IrqVectorRegistration, wrapping the new pci_irq_type() C function. A driver whose interrupt acknowledgment depends on the type (MSI-X vs MSI vs INTx) queries it here rather than assuming which type the PCI core selected. Suggested-by: John Hubbard Link: https://lore.kernel.org/all/20260808031120.363869-4-jhubbard@nvidia.c= om/ Signed-off-by: Danilo Krummrich --- rust/helpers/pci.c | 5 +++++ rust/kernel/pci/irq.rs | 17 +++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/rust/helpers/pci.c b/rust/helpers/pci.c index e44905317d75..23b06becb448 100644 --- a/rust/helpers/pci.c +++ b/rust/helpers/pci.c @@ -24,6 +24,11 @@ __rust_helper bool rust_helper_dev_is_pci(const struct d= evice *dev) return dev_is_pci(dev); } =20 +__rust_helper unsigned int rust_helper_pci_irq_type(struct pci_dev *pdev) +{ + return pci_irq_type(pdev); +} + #ifndef CONFIG_PCI_MSI __rust_helper int rust_helper_pci_alloc_irq_vectors(struct pci_dev *dev, unsigned int min_vecs, diff --git a/rust/kernel/pci/irq.rs b/rust/kernel/pci/irq.rs index d69ab6435a80..618310e4535c 100644 --- a/rust/kernel/pci/irq.rs +++ b/rust/kernel/pci/irq.rs @@ -36,6 +36,16 @@ const fn as_raw(self) -> u32 { IrqType::MsiX =3D> bindings::PCI_IRQ_MSIX, } } + + /// Construct from raw value. + #[inline] + const fn from_raw(raw: u32) -> Self { + match raw { + bindings::PCI_IRQ_MSIX =3D> IrqType::MsiX, + bindings::PCI_IRQ_MSI =3D> IrqType::Msi, + _ =3D> IrqType::Intx, + } + } } =20 /// Set of IRQ types that can be used for PCI interrupt allocation. @@ -99,6 +109,13 @@ pub fn vector_count(&self) -> usize { self.count.get() } =20 + /// Returns the interrupt type the PCI core selected for this allocati= on. + #[inline] + pub fn irq_type(&self) -> IrqType { + // SAFETY: `self.dev.as_raw()` is a valid pointer to a `struct pci= _dev`. + IrqType::from_raw(unsafe { bindings::pci_irq_type(self.dev.as_raw(= )) }) + } + /// Resolves the vector at `index` to an [`IrqRequest`]. /// /// The returned [`IrqRequest`] borrows from this registration, ensuri= ng the vector allocation --=20 2.55.0