summaryrefslogtreecommitdiff
path: root/rust/kernel
diff options
context:
space:
mode:
authorDanilo Krummrich <dakr@kernel.org>2026-08-13 18:52:02 +0200
committerDanilo Krummrich <dakr@kernel.org>2026-08-17 01:14:23 +0200
commit2fb7755b0a7efb811d7d09f3a6ea06fd611d1ba4 (patch)
tree7edd5819a0e9c193cf27c4cb93911a332b978eee /rust/kernel
parent17d4a399e8b8de0bb7d78cb46f92ffa9d629965d (diff)
downloadlwn-2fb7755b0a7efb811d7d09f3a6ea06fd611d1ba4.tar.gz
lwn-2fb7755b0a7efb811d7d09f3a6ea06fd611d1ba4.zip
rust: pci: resolve IRQ in index() and embed IrqRequest in IrqVector
Move the pci_irq_vector() call from the TryInto<IrqRequest> impl into IrqVectorRegistration::index(), so the IRQ number is resolved eagerly. IrqVector now embeds the resolved IrqRequest and a reference to the IrqVectorRegistration. The conversion to IrqRequest is infallible, which removes the need for pin_init_scope() in request_irq() / request_threaded_irq(). Tested-by: John Hubbard <jhubbard@nvidia.com> Inspired-by: John Hubbard <jhubbard@nvidia.com> Link: https://lore.kernel.org/all/20260808031120.363869-3-jhubbard@nvidia.com/ Reviewed-by: Gary Guo <gary@garyguo.net> Link: https://patch.msgid.link/20260813165234.620555-3-dakr@kernel.org Signed-off-by: Danilo Krummrich <dakr@kernel.org>
Diffstat (limited to 'rust/kernel')
-rw-r--r--rust/kernel/pci/irq.rs67
1 files changed, 23 insertions, 44 deletions
diff --git a/rust/kernel/pci/irq.rs b/rust/kernel/pci/irq.rs
index daba86505cd2..81b74c4c17d9 100644
--- a/rust/kernel/pci/irq.rs
+++ b/rust/kernel/pci/irq.rs
@@ -68,32 +68,25 @@ impl IrqTypes {
}
}
-/// Represents an allocated IRQ vector for a specific PCI device.
+/// A resolved IRQ vector from a PCI interrupt vector allocation.
///
-/// 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)]
+/// Created by [`IrqVectorRegistration::index`] and consumed by [`Device::request_irq`] or
+/// [`Device::request_threaded_irq`]. Borrows the [`IrqVectorRegistration`] it was derived from,
+/// so the allocation stays live until the handler is freed.
pub struct IrqVector<'a> {
- dev: &'a Device<Bound>,
+ request: IrqRequest<'a>,
reg: &'a IrqVectorRegistration<'a>,
- index: u32,
}
impl<'a> IrqVector<'a> {
- /// Creates a new [`IrqVector`] for the given device and index.
+ /// Creates a new [`IrqVector`] with an already resolved [`IrqRequest`].
///
/// # Safety
///
- /// - `index` must be a valid IRQ vector index for `reg`.
- /// - `dev` must be the device `reg` was allocated from.
+ /// `request` must have been resolved from `reg`.
#[inline]
- unsafe fn new(dev: &'a Device<Bound>, reg: &'a IrqVectorRegistration<'a>, index: u32) -> Self {
- Self { dev, reg, index }
- }
-
- /// Returns the raw vector index.
- fn index(&self) -> u32 {
- self.index
+ unsafe fn new(request: IrqRequest<'a>, reg: &'a IrqVectorRegistration<'a>) -> Self {
+ Self { request, reg }
}
/// Returns the [`IrqVectorRegistration`] this vector was derived from.
@@ -103,17 +96,10 @@ impl<'a> IrqVector<'a> {
}
}
-impl<'a> TryInto<IrqRequest<'a>> for IrqVector<'a> {
- type Error = Error;
-
- fn try_into(self) -> Result<IrqRequest<'a>> {
- // SAFETY: `self.dev.as_raw()` returns a valid pointer to a `struct pci_dev`.
- let irq = unsafe { bindings::pci_irq_vector(self.dev.as_raw(), self.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(self.dev.as_ref(), irq as u32) })
+impl<'a> From<IrqVector<'a>> for IrqRequest<'a> {
+ #[inline]
+ fn from(vector: IrqVector<'a>) -> Self {
+ vector.request
}
}
@@ -146,13 +132,14 @@ impl<'a> IrqVectorRegistration<'a> {
/// [`Self::len()`].
#[inline]
pub fn index(&self, index: usize) -> Result<IrqVector<'_>> {
- if index >= self.len.get() {
- return Err(EINVAL);
+ // SAFETY: `self.dev.as_raw()` is a valid pointer to a `struct pci_dev`.
+ let irq = unsafe { bindings::pci_irq_vector(self.dev.as_raw(), index as u32) };
+ if irq < 0 {
+ return Err(Error::from_errno(irq));
}
- // SAFETY: `index` is within bounds of this registration's allocation, and `self.dev` is
- // the device it was allocated from.
- Ok(unsafe { IrqVector::new(self.dev, self, index as u32) })
+ // SAFETY: `irq` is a valid IRQ number for `self.dev`, resolved from this registration.
+ Ok(unsafe { IrqVector::new(IrqRequest::new(self.dev.as_ref(), irq as u32), self) })
}
}
@@ -179,12 +166,8 @@ impl Device<device::Bound> {
name: &'static CStr,
handler: impl PinInit<T, Error> + 'a,
) -> impl PinInit<irq::Registration<'a, T>, Error> + 'a {
- pin_init::pin_init_scope(move || {
- let request = vector.try_into()?;
-
- // SAFETY: Caller guarantees the Registration will not be leaked.
- Ok(unsafe { irq::Registration::<T>::new(request, flags, name, handler) })
- })
+ // SAFETY: Caller guarantees the Registration will not be leaked.
+ unsafe { irq::Registration::<T>::new(vector.into(), flags, name, handler) }
}
/// Returns a [`kernel::irq::ThreadedRegistration`] for the given IRQ vector.
@@ -200,12 +183,8 @@ impl Device<device::Bound> {
name: &'static CStr,
handler: impl PinInit<T, Error> + 'a,
) -> impl PinInit<irq::ThreadedRegistration<'a, T>, Error> + 'a {
- pin_init::pin_init_scope(move || {
- let request = vector.try_into()?;
-
- // SAFETY: Caller guarantees the Registration will not be leaked.
- Ok(unsafe { irq::ThreadedRegistration::<T>::new(request, flags, name, handler) })
- })
+ // SAFETY: Caller guarantees the Registration will not be leaked.
+ unsafe { irq::ThreadedRegistration::<T>::new(vector.into(), flags, name, handler) }
}
/// Allocate IRQ vectors for this PCI device.