[PATCH v6 1/2] drm/tyr: add TyrIrq threaded IRQ wrapper
Laura Nao <[email protected]>
| Newsgroups | org.kernel.vger.rust-for-linux,org.freedesktop.lists.dri-devel,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <[email protected]> |
Introduce a generic TyrIrq threaded IRQ wrapper along with the TyrIrqTrait trait describing the operations required to handle a Tyr interrupt source. Co-developed-by: Daniel Almeida <[email protected]> Signed-off-by: Daniel Almeida <[email protected]> Co-developed-by: Deborah Brouwer <[email protected]> Signed-off-by: Deborah Brouwer <[email protected]> Signed-off-by: Laura Nao <[email protected]> --- drivers/gpu/drm/tyr/irq.rs | 115 +++++++++++++++++++++++++++++++++++++++++++++ drivers/gpu/drm/tyr/tyr.rs | 1 + 2 files changed, 116 insertions(+) diff --git a/drivers/gpu/drm/tyr/irq.rs b/drivers/gpu/drm/tyr/irq.rs new file mode 100644 index 000000000000..e6a739532daa --- /dev/null +++ b/drivers/gpu/drm/tyr/irq.rs @@ -0,0 +1,115 @@ +// SPDX-License-Identifier: GPL-2.0 or MIT + +//! Threaded IRQ wrapper shared by all Tyr interrupt sources. +#![allow(dead_code)] +use core::marker::PhantomPinned; + +use kernel::{ + device::Bound, + irq::{ + Flags, + IrqReturn, + ThreadedHandler, + ThreadedIrqReturn, + ThreadedRegistration, // + }, + platform, + prelude::*, // +}; + +/// Trait describing the operations required to service a Tyr interrupt source. +pub(crate) trait TyrIrqTrait: Sync { + /// Returns the masked interrupt status. + fn read_status(&self) -> u32; + + /// Clears all bits in the mask register, disabling the interrupt sources. + fn clear_mask(&self); + + /// Sets the mask register to re-enable the interrupt sources. + fn reenable_mask(&self); + + /// Returns the raw interrupt status, regardless of the current mask. + fn read_raw_status(&self) -> u32; + + /// Clears the given bits in the interrupt status register. + fn clear_status(&self, status: u32); + + /// Returns the bitmask of interrupt sources handled by this instance. + fn mask(&self) -> u32; + + /// Handles the given pending, unmasked interrupt bits. + fn handle(&self, status: u32); +} + +/// A threaded IRQ wrapper shared by all Tyr interrupt sources. +#[pin_data] +pub(crate) struct TyrIrq<T: TyrIrqTrait> { + /// The interrupt source. + irq: T, + #[pin] + _pin: PhantomPinned, +} + +impl<T: TyrIrqTrait> TyrIrq<T> { + /// Requests a threaded IRQ registration for `irq`, using `name` to look up the interrupt. + /// + /// # Safety + /// + /// Callers must not `mem::forget()` the resulting registration or otherwise prevent its + /// [`Drop`] implementation from running. + pub(crate) unsafe fn request<'a>( + pdev: &'a platform::Device<Bound>, + name: &'static CStr, + irq: T, + ) -> Result<impl PinInit<ThreadedRegistration<'a, Self>, Error> + 'a> + where + T: 'a, + { + let handler = try_pin_init!(Self { + irq, + _pin: PhantomPinned, + }); + + // SAFETY: The caller guarantees the resulting registration will not be leaked. + let registration = + unsafe { pdev.request_threaded_irq_by_name(Flags::SHARED, name, name, handler) }; + + // Clear the status and unmask once the handler has been + // successfully registered. + Ok(registration.pin_chain(|reg| { + let irq = ®.handler().irq; + irq.clear_status(irq.mask()); + irq.reenable_mask(); + Ok(()) + })) + } +} + +impl<T: TyrIrqTrait> ThreadedHandler for TyrIrq<T> { + fn handle(&self) -> ThreadedIrqReturn { + let masked_status = self.irq.read_status(); + + if masked_status == 0 { + return ThreadedIrqReturn::None; + } + self.irq.clear_mask(); + ThreadedIrqReturn::WakeThread + } + + fn handle_threaded(&self) -> IrqReturn { + let mut ret = IrqReturn::None; + + loop { + let raw_status = self.irq.read_raw_status() & self.irq.mask(); + if raw_status == 0 { + break; + } + self.irq.clear_status(raw_status); + self.irq.handle(raw_status); + ret = IrqReturn::Handled; + } + + self.irq.reenable_mask(); + ret + } +} diff --git a/drivers/gpu/drm/tyr/tyr.rs b/drivers/gpu/drm/tyr/tyr.rs index e7ec450bdc9c..31205e3bf0e7 100644 --- a/drivers/gpu/drm/tyr/tyr.rs +++ b/drivers/gpu/drm/tyr/tyr.rs @@ -12,6 +12,7 @@ mod fw; mod gem; mod gpu; +mod irq; mod mmu; mod regs; mod slot; -- 2.39.5