Commit 9b6d4fb9 authored by Daniel Almeida's avatar Daniel Almeida Committed by Danilo Krummrich
Browse files

rust: pci: add irq accessors



These accessors can be used to retrieve a irq::Registration or a
irq::ThreadedRegistration from a pci device. Alternatively, drivers can
retrieve an IrqRequest from a bound PCI device for later use.

These accessors ensure that only valid IRQ lines can ever be registered.

Reviewed-by: default avatarAlice Ryhl <aliceryhl@google.com>
Tested-by: default avatarJoel Fernandes <joelagnelf@nvidia.com>
Tested-by: default avatarDirk Behme <dirk.behme@de.bosch.com>
Signed-off-by: default avatarDaniel Almeida <daniel.almeida@collabora.com>
Link: https://lore.kernel.org/r/20250811-topics-tyr-request_irq2-v9-6-0485dcd9bcbf@collabora.com


Signed-off-by: default avatarDanilo Krummrich <dakr@kernel.org>
parent 17e70f0c
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -11,3 +11,11 @@ bool rust_helper_dev_is_pci(const struct device *dev)
{
	return dev_is_pci(dev);
}

#ifndef CONFIG_PCI_MSI
int rust_helper_pci_irq_vector(struct pci_dev *pdev, unsigned int nvec)
{
	return pci_irq_vector(pdev, nvec);
}

#endif
+43 −2
Original line number Diff line number Diff line
@@ -10,8 +10,8 @@
    devres::Devres,
    driver,
    error::{from_result, to_result, Result},
    io::Io,
    io::IoRaw,
    io::{Io, IoRaw},
    irq::{self, IrqRequest},
    str::CStr,
    types::{ARef, Opaque},
    ThisModule,
@@ -431,6 +431,47 @@ pub fn iomap_region<'a>(
    ) -> impl PinInit<Devres<Bar>, Error> + 'a {
        self.iomap_region_sized::<0>(bar, name)
    }

    /// Returns an [`IrqRequest`] for the IRQ vector at the given index, if any.
    pub fn irq_vector(&self, index: u32) -> Result<IrqRequest<'_>> {
        // SAFETY: `self.as_raw` returns a valid pointer to a `struct pci_dev`.
        let irq = unsafe { crate::bindings::pci_irq_vector(self.as_raw(), 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.as_ref(), irq as u32) })
    }

    /// Returns a [`kernel::irq::Registration`] for the IRQ vector at the given
    /// index.
    pub fn request_irq<'a, T: crate::irq::Handler + 'static>(
        &'a self,
        index: u32,
        flags: irq::Flags,
        name: &'static CStr,
        handler: impl PinInit<T, Error> + 'a,
    ) -> Result<impl PinInit<irq::Registration<T>, Error> + 'a> {
        let request = self.irq_vector(index)?;

        Ok(irq::Registration::<T>::new(request, flags, name, handler))
    }

    /// Returns a [`kernel::irq::ThreadedRegistration`] for the IRQ vector at
    /// the given index.
    pub fn request_threaded_irq<'a, T: crate::irq::ThreadedHandler + 'static>(
        &'a self,
        index: u32,
        flags: irq::Flags,
        name: &'static CStr,
        handler: impl PinInit<T, Error> + 'a,
    ) -> Result<impl PinInit<irq::ThreadedRegistration<T>, Error> + 'a> {
        let request = self.irq_vector(index)?;

        Ok(irq::ThreadedRegistration::<T>::new(
            request, flags, name, handler,
        ))
    }
}

impl Device<device::Core> {