[PATCH v4 16/20] drm/tyr: wait for global interface readiness
From: Deborah Brouwer
Date: Fri Apr 24 2026 - 19:44:37 EST
Add a wait helper for global interface readiness using the Job IRQ. The
IRQ handler latches readiness in fw_ready and wakes waiters. After
booting the firmware, probe waits until the firmware reports that the
global interface is ready to accept requests.
Register the Job IRQ before booting the firmware so that the initial GLB
event is not missed.
Co-developed-by: Daniel Almeida <daniel.almeida@xxxxxxxxxxxxx>
Signed-off-by: Daniel Almeida <daniel.almeida@xxxxxxxxxxxxx>
Signed-off-by: Deborah Brouwer <deborah.brouwer@xxxxxxxxxxxxx>
---
drivers/gpu/drm/tyr/driver.rs | 18 +++++++++++++++++-
drivers/gpu/drm/tyr/fw.rs | 35 +++++++++++++++++++++++++++++++++--
drivers/gpu/drm/tyr/fw/irq.rs | 1 -
drivers/gpu/drm/tyr/wait.rs | 1 -
4 files changed, 50 insertions(+), 5 deletions(-)
diff --git a/drivers/gpu/drm/tyr/driver.rs b/drivers/gpu/drm/tyr/driver.rs
index da007aded92d..3225385cd511 100644
--- a/drivers/gpu/drm/tyr/driver.rs
+++ b/drivers/gpu/drm/tyr/driver.rs
@@ -12,6 +12,7 @@
Core,
Device, //
},
+ devres,
devres::Devres,
dma::{
Device as DmaDevice,
@@ -51,7 +52,10 @@
use crate::{
file::TyrDrmFileData,
- fw::Firmware,
+ fw::{
+ irq::job_irq_init,
+ Firmware, //
+ },
gem::BoData,
gpu,
gpu::GpuInfo,
@@ -176,8 +180,20 @@ fn probe(
&gpu_info,
)?;
+ let job_irq = job_irq_init(
+ pdev,
+ iomem.clone(),
+ firmware.fw_ready.clone(),
+ firmware.ready_wait.clone(),
+ )?;
+ devres::register(pdev.as_ref(), job_irq, GFP_KERNEL)?;
+
firmware.boot()?;
+ firmware
+ .wait_ready(1000)
+ .inspect_err(|_| pr_err!("Timed out waiting for firmware to be ready.\n"))?;
+
let data = try_pin_init!(TyrDrmDeviceData {
pdev: platform.clone(),
fw: firmware,
diff --git a/drivers/gpu/drm/tyr/fw.rs b/drivers/gpu/drm/tyr/fw.rs
index b5ccacf891a3..14815cdafac8 100644
--- a/drivers/gpu/drm/tyr/fw.rs
+++ b/drivers/gpu/drm/tyr/fw.rs
@@ -13,6 +13,11 @@
//! [`Firmware`]: crate::fw::Firmware
//! [`Section`]: crate::fw::Section
+use core::sync::atomic::{
+ AtomicBool,
+ Ordering, //
+};
+
use kernel::{
bits::genmask_u32,
devres::Devres,
@@ -25,6 +30,7 @@
poll,
Io, //
},
+ new_mutex,
platform,
prelude::*,
str::CString,
@@ -52,6 +58,7 @@
},
gpu::GpuInfo,
mmu::Mmu,
+ new_wait,
regs::gpu_control::{
McuControlMode,
McuStatus,
@@ -59,13 +66,18 @@
MCU_CONTROL,
MCU_STATUS, //
},
- vm::Vm, //
+ vm::Vm,
+ wait::{
+ Wait,
+ WaitResult, //
+ }, //
};
pub(crate) mod irq;
mod parser;
-const MAX_CSG: u32 = 16;
+/// Maximum number of CSG interfaces supported by hardware.
+const MAX_CSG: usize = 16;
impl_flags!(
#[derive(Debug, Clone, Default, Copy, PartialEq, Eq)]
@@ -142,6 +154,12 @@ pub(crate) struct Firmware {
/// List of firmware sections.
#[expect(dead_code)]
sections: KVec<Section>,
+
+ /// A condvar representing a wait on a firmware event.
+ pub(crate) ready_wait: Arc<Wait>,
+
+ /// Latched to `true` by the IRQ handler when the firmware signals readiness via the GLB bit.
+ pub(crate) fw_ready: Arc<AtomicBool>,
}
impl Drop for Firmware {
@@ -246,6 +264,8 @@ pub(crate) fn new(
iomem,
vm,
sections,
+ ready_wait: new_wait!()?,
+ fw_ready: Arc::new(AtomicBool::new(false), GFP_KERNEL)?,
},
GFP_KERNEL,
)?;
@@ -272,4 +292,15 @@ pub(crate) fn boot(&self) -> Result {
}
Ok(())
}
+
+ /// Waits until the firmware signals readiness via the GLB IRQ bit.
+ pub(crate) fn wait_ready(&self, timeout_ms: u32) -> Result {
+ self.ready_wait.wait_interruptible_timeout(timeout_ms, || {
+ if self.fw_ready.load(Ordering::Acquire) {
+ Ok(WaitResult::Done)
+ } else {
+ Ok(WaitResult::Retry)
+ }
+ })
+ }
}
diff --git a/drivers/gpu/drm/tyr/fw/irq.rs b/drivers/gpu/drm/tyr/fw/irq.rs
index 0eff5a14f69e..0f371000679c 100644
--- a/drivers/gpu/drm/tyr/fw/irq.rs
+++ b/drivers/gpu/drm/tyr/fw/irq.rs
@@ -3,7 +3,6 @@
//! IRQ handling for the Job IRQ.
//!
//! The Job IRQ signals events from the MCU, including global interface acknowledgements.
-#![allow(dead_code)]
use core::sync::atomic::{
AtomicBool,
diff --git a/drivers/gpu/drm/tyr/wait.rs b/drivers/gpu/drm/tyr/wait.rs
index 2a4d691c443c..1db4c1827fd7 100644
--- a/drivers/gpu/drm/tyr/wait.rs
+++ b/drivers/gpu/drm/tyr/wait.rs
@@ -1,7 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 or MIT
//! Code to wait on GPU events.
-#![allow(dead_code)]
use kernel::{
new_condvar,
--
2.53.0