From nobody Sun Sep 27 02:52:22 2026 Received: from bali.collaboradmins.com (bali.collaboradmins.com [148.251.105.195]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7A2413A4513; Thu, 27 Aug 2026 08:01:40 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=148.251.105.195 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787817702; cv=none; b=Myx5ndXQzIaoUo5YTwkr6ec5z/TjHYuYlHFPPxbUstIxYxTKNWq8lL/XtoB802lP63Lex27yVngJOvBwcBnfMQ3/AzNqtaOQniAEgF4rpwNmnR9HnszUPukx78JbpiRPAz0q/D6+p/4PQYAarF4qMNtuIEyeLRUADPaNw567F1I= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787817702; c=relaxed/simple; bh=M1sla4NI7Z2SPj1X+URJliQyRjhU54PnMBlz9sucijQ=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=Ezp9ud/CkcpHPZU+msVWAtB22hTRBV4W1/PyLFcMOiV56Fj4jvhJ2/V4RxB2iNq7V1bO6QcyqbFx4dNZexdlnnxDgTkWOTYNbRPJvk+/4a36SftoU4Y3GDJ7KlYaaXx9RW1xsummir3C6w8i3vZ8dz3hgjUY8E/Tidl0c0Blc6o= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=collabora.com; spf=pass smtp.mailfrom=collabora.com; dkim=pass (2048-bit key) header.d=collabora.com header.i=@collabora.com header.b=KmA7Vapz; arc=none smtp.client-ip=148.251.105.195 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=collabora.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=collabora.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=collabora.com header.i=@collabora.com header.b="KmA7Vapz" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=collabora.com; s=mail; t=1787817698; bh=M1sla4NI7Z2SPj1X+URJliQyRjhU54PnMBlz9sucijQ=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=KmA7VapziNpyndCRUlOBLl3iQwwuORFPmQ3iaWwhBo0aiCZgupHCC9/sZNS0y5qnV 1DdSDEeUmn9ii3aSj/BX3en9PXinTFJba6GoCjMq4QdMlpA/EVcxfRG5FLPrcCYLrJ eeowYjkwXxYo6s6n4eMdOt/frb51lFIZfzj9fUl5Blf8SMsAne4rgIp+9/ZtzpJKUA bYE6Xu5Dw6wSYYBHHUI5BLuQ3SrITda6BFf6XL8fKaIUxbGOPrUyxp3enAL1nFR5vl BiJZ3xu+vpDdmozQb7PSVtbI8AgBgXfEmD9udR20IvB4j+SLVPNXTBcLv9WS6GatCF Jlp1KdXvVFQ7w== Received: from laura.lan (unknown [100.64.0.215]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange x25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) (Authenticated sender: laura.nao) by bali.collaboradmins.com (Postfix) with ESMTPSA id E4F9317E052E; Thu, 27 Aug 2026 10:01:37 +0200 (CEST) From: Laura Nao Date: Thu, 27 Aug 2026 10:01:10 +0200 Subject: [PATCH v6 1/2] drm/tyr: add TyrIrq threaded IRQ wrapper Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260728-tyr-irq-v2-v6-1-15c90baed949@collabora.com> References: <20260728-tyr-irq-v2-v6-0-15c90baed949@collabora.com> In-Reply-To: <20260728-tyr-irq-v2-v6-0-15c90baed949@collabora.com> To: Daniel Almeida , Alice Ryhl , Danilo Krummrich , David Airlie , Simona Vetter , Miguel Ojeda , Boqun Feng , Gary Guo , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= , Benno Lossin , Andreas Hindborg , Trevor Gross , Tamir Duberstein , Alexandre Courbot , =?utf-8?q?Onur_=C3=96zkan?= Cc: linux-kernel@vger.kernel.org, dri-devel@lists.freedesktop.org, rust-for-linux@vger.kernel.org, kernel@collabora.com, Laura Nao , Deborah Brouwer X-Mailer: b4 0.12.0 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 Signed-off-by: Daniel Almeida Co-developed-by: Deborah Brouwer Signed-off-by: Deborah Brouwer Signed-off-by: Laura Nao --- 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 so= urce. +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 sour= ces. + 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 { + /// The interrupt source. + irq: T, + #[pin] + _pin: PhantomPinned, +} + +impl TyrIrq { + /// Requests a threaded IRQ registration for `irq`, using `name` to lo= ok up the interrupt. + /// + /// # Safety + /// + /// Callers must not `mem::forget()` the resulting registration or oth= erwise prevent its + /// [`Drop`] implementation from running. + pub(crate) unsafe fn request<'a>( + pdev: &'a platform::Device, + name: &'static CStr, + irq: T, + ) -> Result, Error> + 'a> + where + T: 'a, + { + let handler =3D try_pin_init!(Self { + irq, + _pin: PhantomPinned, + }); + + // SAFETY: The caller guarantees the resulting registration will n= ot be leaked. + let registration =3D + 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 =3D ®.handler().irq; + irq.clear_status(irq.mask()); + irq.reenable_mask(); + Ok(()) + })) + } +} + +impl ThreadedHandler for TyrIrq { + fn handle(&self) -> ThreadedIrqReturn { + let masked_status =3D self.irq.read_status(); + + if masked_status =3D=3D 0 { + return ThreadedIrqReturn::None; + } + self.irq.clear_mask(); + ThreadedIrqReturn::WakeThread + } + + fn handle_threaded(&self) -> IrqReturn { + let mut ret =3D IrqReturn::None; + + loop { + let raw_status =3D self.irq.read_raw_status() & self.irq.mask(= ); + if raw_status =3D=3D 0 { + break; + } + self.irq.clear_status(raw_status); + self.irq.handle(raw_status); + ret =3D 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; --=20 2.39.5 From nobody Sun Sep 27 02:52:22 2026 Received: from bali.collaboradmins.com (bali.collaboradmins.com [148.251.105.195]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5D62431ED93; Thu, 27 Aug 2026 08:01:41 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=148.251.105.195 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787817703; cv=none; b=GxWu2cYH4OjmvJAFb7hJZsGlUS3K84lWUt88EvkeGjXOOcKNwHLS8QVe/G6j7ki+rhD4J5v81tqYgU5VgOiAV4uWlyoMx6/7Cna4Ld+ZY5PNIQbFif4+962gLJr4CRHPecos3tx+YZuAZsH+wtg3R8EuRjq3z1WNd33QwK/Anjc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787817703; c=relaxed/simple; bh=77OMG1yMlk2S+XLapaAHmA8HLMfeEQjwSs54ZOhvf8k=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=hQ8mIwXUut9mWX3S5QKKI86W6nYWZB3rz0uKzA3mndtGOJePFhz2FRLUhs+0ubsw7iNwaSZ04PPT9JBpe7odpF/AR5hCdoxpQFfzUlW2qNl9WSgMGRoWd2giPP7YR6wXpfGLwA2PfO48/XgsinruHnK6pU2jgT1v2ZF+W2zG17Y= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=collabora.com; spf=pass smtp.mailfrom=collabora.com; dkim=pass (2048-bit key) header.d=collabora.com header.i=@collabora.com header.b=l5KJYXne; arc=none smtp.client-ip=148.251.105.195 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=collabora.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=collabora.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=collabora.com header.i=@collabora.com header.b="l5KJYXne" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=collabora.com; s=mail; t=1787817699; bh=77OMG1yMlk2S+XLapaAHmA8HLMfeEQjwSs54ZOhvf8k=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=l5KJYXneUGFURdYQ8dEXKb9WainViQfpBucw8qMIcVUDwNmkm3dTIBQijvgGMLyhl tuSYAT0KMsG08EkYKJ/8b2PJnH0B9Fm6I6uk/W542gkQl4jQYBp8LPPPj5GPDWYDeD 8swfO4TOt3Kr4F7Lb4r1nra74eP3ArAvWE7SRb1a0uIGnHvqXizDlEncSvb7AyM+XJ 793BpdctqQ41WS2qWLaCjnvde7xb0IcrEzMea+iR3/YVGZQ3JdF4rFr7k5//91E7mz LHXja94/74m+sSTuzmmVrl+OWyW/LDpyUYNjFjWza0Q8jq3cTD749cuEdSO2FmH5i3 ZRKhOAGJaKHPg== Received: from laura.lan (unknown [100.64.0.215]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange x25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) (Authenticated sender: laura.nao) by bali.collaboradmins.com (Postfix) with ESMTPSA id CA5E417E0566; Thu, 27 Aug 2026 10:01:38 +0200 (CEST) From: Laura Nao Date: Thu, 27 Aug 2026 10:01:11 +0200 Subject: [PATCH v6 2/2] drm/tyr: add Job IRQ handling Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260728-tyr-irq-v2-v6-2-15c90baed949@collabora.com> References: <20260728-tyr-irq-v2-v6-0-15c90baed949@collabora.com> In-Reply-To: <20260728-tyr-irq-v2-v6-0-15c90baed949@collabora.com> To: Daniel Almeida , Alice Ryhl , Danilo Krummrich , David Airlie , Simona Vetter , Miguel Ojeda , Boqun Feng , Gary Guo , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= , Benno Lossin , Andreas Hindborg , Trevor Gross , Tamir Duberstein , Alexandre Courbot , =?utf-8?q?Onur_=C3=96zkan?= Cc: linux-kernel@vger.kernel.org, dri-devel@lists.freedesktop.org, rust-for-linux@vger.kernel.org, kernel@collabora.com, Laura Nao , Deborah Brouwer X-Mailer: b4 0.12.0 The Job IRQ reports requests from the CSF firmware, including global interface requests and CSG attention bits. Only the GLB bit is currently handled, as it will be used to check firmware readiness. CSG bits handling will be added at a later stage. The Job IRQ handler masks the interrupt in the primary IRQ handler, processes pending raw status in the threaded handler, clears the handled bits, and reenables the mask before returning. Add JobIrqEvents to hold the wait queue and the ready flag used to signal firmware readiness when the GLB bit is set, and JobIrqMaskGuard to ensure the Job IRQ is masked before its registration is freed. Co-developed-by: Daniel Almeida Signed-off-by: Daniel Almeida Co-developed-by: Deborah Brouwer Signed-off-by: Deborah Brouwer Signed-off-by: Laura Nao --- drivers/gpu/drm/tyr/fw.rs | 1 + drivers/gpu/drm/tyr/fw/irq.rs | 174 ++++++++++++++++++++++++++++++++++++++= ++++ drivers/gpu/drm/tyr/irq.rs | 1 - 3 files changed, 175 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/tyr/fw.rs b/drivers/gpu/drm/tyr/fw.rs index 47d25c901bd0..8162b9806c97 100644 --- a/drivers/gpu/drm/tyr/fw.rs +++ b/drivers/gpu/drm/tyr/fw.rs @@ -69,6 +69,7 @@ vm::Vm, // }; =20 +pub(crate) mod irq; mod parser; =20 pub(super) const CSF_MCU_SHARED_REGION_START: u32 =3D 0x04000000; diff --git a/drivers/gpu/drm/tyr/fw/irq.rs b/drivers/gpu/drm/tyr/fw/irq.rs new file mode 100644 index 000000000000..7dd894de18cb --- /dev/null +++ b/drivers/gpu/drm/tyr/fw/irq.rs @@ -0,0 +1,174 @@ +// SPDX-License-Identifier: GPL-2.0 or MIT + +//! IRQ handling for the Job IRQ. +//! +//! The Job IRQ signals events from the MCU, including global interface ac= knowledgements. +#![allow(dead_code)] + +use kernel::{ + device::Bound, // + io::Io, + irq::ThreadedRegistration, + new_waitqueue, + platform, + prelude::*, + sync::{ + atomic::{ + ordering, + Atomic, // + }, + Arc, + WaitQueue, // + }, + time::{ + msecs_to_jiffies, + Msecs, // + }, +}; + +use crate::{ + driver::IoMem, + irq::{ + TyrIrq, + TyrIrqTrait, // + }, + regs::job_control::{ + JOB_IRQ_CLEAR, + JOB_IRQ_MASK, + JOB_IRQ_RAWSTAT, + JOB_IRQ_STATUS, // + }, // +}; + +/// The firmware events published by the Job IRQ handler, and the queue us= ed to announce them. +#[pin_data] +pub(crate) struct JobIrqEvents { + #[pin] + wait: WaitQueue, + /// Set once the firmware has signalled that the global interface is r= eady. + ready: Atomic, +} + +impl JobIrqEvents { + /// Creates a new, empty set of Job IRQ events. + pub(crate) fn new() -> Result> { + Arc::pin_init( + pin_init!(JobIrqEvents { + wait <- new_waitqueue!(), + ready: Atomic::new(false), + }), + GFP_KERNEL, + ) + } + + /// Clears the firmware-ready state. + pub(crate) fn clear_ready(&self) { + self.ready.store(false, ordering::Relaxed); + } + + /// Waits until the firmware signals readiness via the GLB IRQ bit, or= the timeout expires. + pub(crate) fn wait_ready(&self, timeout_ms: Msecs) -> Result { + self.wait.wait_event_timeout( + || self.ready.load(ordering::Acquire), + msecs_to_jiffies(timeout_ms), + )?; + + Ok(()) + } + + /// Updates state and wakes up waiters + fn signal(&self, status: u32) { + // TODO: handle other Job IRQ events (e.g. CSG attention bits) her= e once + // support for them is added. + + // The GLB bit only signals firmware readiness once, at power up + if JOB_IRQ_RAWSTAT::from_raw(status).glb() && !self.ready.load(ord= ering::Relaxed) { + self.ready.store(true, ordering::Release); + } + + self.wait.wake_up_all(); + } +} + +// The Job IRQ, signalling requests or notification from the MCU. +pub(crate) struct JobIrq<'a> { + /// GPU MMIO register mapping. + iomem: Arc>, + /// Firmware events signalled by this IRQ. + events: Arc, +} + +/// Guard that masks the Job IRQ when dropped. +/// +/// To mask the Job IRQ before it is freed, this guard must be stored in a= field declared +/// before the corresponding `ThreadedRegistration` in the struct that own= s both. Since +/// struct fields are dropped in declaration order, this guarantees the Jo= b IRQ is masked +/// first, and only then does `free_irq()` run and wait for any in-flight = handler to +/// complete. +pub(crate) struct JobIrqMaskGuard<'a>(Arc>); + +impl Drop for JobIrqMaskGuard<'_> { + fn drop(&mut self) { + self.0.write_reg(JOB_IRQ_MASK::zeroed()); + } +} + +/// Requests a threaded IRQ registration for the Job IRQ. +/// +/// Returns a [`JobIrqMaskGuard`] alongside the registration. The guard mu= st be stored in a +/// field declared before the registration in the struct that owns both, s= o that the Job +/// IRQ is masked before it is freed. See [`JobIrqMaskGuard`] for details. +/// +/// # Safety +/// +/// Callers must not `mem::forget()` the resulting registration or otherwi= se prevent its +/// [`Drop`] implementation from running. +pub(crate) unsafe fn job_irq_init<'a>( + pdev: &'a platform::Device, + iomem: Arc>, + events: Arc, +) -> Result<( + JobIrqMaskGuard<'a>, + impl PinInit>>, Error> + 'a, +)> { + let mask_guard =3D JobIrqMaskGuard(iomem.clone()); + + let job_irq =3D JobIrq { iomem, events }; + // Ensure interrupt sources are disabled until the handler is register= ed. + job_irq.clear_mask(); + + // SAFETY: The caller guarantees the resulting registration will not b= e leaked. + let registration =3D unsafe { TyrIrq::request(pdev, c"job", job_irq) }= ?; + + Ok((mask_guard, registration)) +} + +impl TyrIrqTrait for JobIrq<'_> { + fn read_status(&self) -> u32 { + self.iomem.read(JOB_IRQ_STATUS).into_raw() + } + + fn clear_mask(&self) { + self.iomem.write_reg(JOB_IRQ_MASK::zeroed()); + } + + fn reenable_mask(&self) { + self.iomem.write_reg(JOB_IRQ_MASK::from_raw(self.mask())); + } + + fn read_raw_status(&self) -> u32 { + self.iomem.read(JOB_IRQ_RAWSTAT).into_raw() + } + + fn clear_status(&self, status: u32) { + self.iomem.write_reg(JOB_IRQ_CLEAR::from_raw(status)); + } + + fn mask(&self) -> u32 { + JOB_IRQ_MASK::zeroed().with_glb(true).into_raw() + } + + fn handle(&self, status: u32) { + self.events.signal(status); + } +} diff --git a/drivers/gpu/drm/tyr/irq.rs b/drivers/gpu/drm/tyr/irq.rs index e6a739532daa..1905fd251ead 100644 --- a/drivers/gpu/drm/tyr/irq.rs +++ b/drivers/gpu/drm/tyr/irq.rs @@ -1,7 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 or MIT =20 //! Threaded IRQ wrapper shared by all Tyr interrupt sources. -#![allow(dead_code)] use core::marker::PhantomPinned; =20 use kernel::{ --=20 2.39.5