[PATCH v3 2/5] rust: pci: resolve IRQ in index() and embed IrqRequest in IrqVector
Danilo Krummrich <[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]> |
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> { + #[inline] + fn from(vector: IrqVector<'a>) -> Self { + vector.request } } @@ -146,13 +132,14 @@ pub fn len(&self) -> usize { /// [`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 @@ pub unsafe fn request_irq<'a, T: crate::irq::Handler + 'a>( 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 @@ pub unsafe fn request_threaded_irq<'a, T: crate::irq::ThreadedHandler + 'a>( 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. -- 2.55.0