Re: [PATCH v3 2/5] rust: pci: resolve IRQ in index() and embed IrqRequest in IrqVector

"Gary Guo" <[email protected]>
Newsgroups dev.linux.lists.driver-core,org.kernel.vger.linux-kernel,org.kernel.vger.linux-pci,org.kernel.vger.rust-for-linux
Message-ID <[email protected]>
On Thu Aug 13, 2026 at 5:52 PM BST, Danilo Krummrich wrote:
> 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 <[email protected]>
> Inspired-by: John Hubbard <[email protected]>
> Link: https://lore.kernel.org/all/[email protected]/
> Signed-off-by: Danilo Krummrich <[email protected]>
> ---
>  rust/kernel/pci/irq.rs | 67 +++++++++++++++---------------------------
>  1 file 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 @@ const fn as_raw(self) -> u32 {
>      }
>  }
>  
> -/// 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 @@ pub fn vectors(&self) -> &'a IrqVectorRegistration<'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> {

I feel that this is actually one of the prime candidate of `DerefMove` when (or
if) Rust adds that.

If we have !Leak` in the langauge, then we can drop the unsafe on
`irq::Registration::new`, then we can move that to become a method on
`IrqRequest`; if we also have `DerefMove`, then you'd be able to do

    irq_vector.request_thread_irq(...)

and this will look super clean.

That said, we have neither `DerefMove` nor `!Leak`, so a unsafe constructor + a
`.into()` does sound like the best option so far. But one can dream :)

Best,
Gary

> +    #[inline]
> +    fn from(vector: IrqVector<'a>) -> Self {
> +        vector.request
>      }
>  }
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.