[PATCH v6 11/15] gpu: nova-core: gsp: cmdq: do not sleep when waiting for a message with timeout 0
From: Alexandre Courbot
Date: Tue Oct 27 2026 - 03:41:38 EST
`read_poll_timeout` can potentially sleep for the specified
`sleep_delta` if `timeout_delta` is `Delta::ZERO` and the system clock
is coarse enough to not register a tick between the time the function
has been called and the time the loop test is done. `wait_for_msg` has a
short test condition and is particularly vulnerable to this condition.
Add a dedicated branch when `timeout` is `Delta::ZERO` to perform the
test without calling `read_poll_timeout` and avoid potentially sleeping
for 1ms.
Signed-off-by: Alexandre Courbot <acourbot@xxxxxxxxxx>
---
drivers/gpu/nova-core/gsp/cmdq.rs | 24 ++++++++++++++++++------
1 file changed, 18 insertions(+), 6 deletions(-)
diff --git a/drivers/gpu/nova-core/gsp/cmdq.rs b/drivers/gpu/nova-core/gsp/cmdq.rs
index 9e678715c624..9c2c8fbad045 100644
--- a/drivers/gpu/nova-core/gsp/cmdq.rs
+++ b/drivers/gpu/nova-core/gsp/cmdq.rs
@@ -909,12 +909,24 @@ fn send_command<M>(&mut self, command: M) -> Result
/// - `EIO` if a message fails framing or checksum validation.
fn wait_for_msg(&self, timeout: Delta) -> Result<GspMessage<'_>> {
// Wait for a message to arrive from the GSP.
- let (slice_1, slice_2) = read_poll_timeout(
- || Ok(self.gsp_mem.driver_read_area()),
- |driver_area| !driver_area.0.is_empty(),
- Delta::from_millis(1),
- timeout,
- )
+ let (slice_1, slice_2) = if timeout == Delta::ZERO {
+ // If `timeout == Delta::ZERO`, check the message queue once as `read_poll_timeout` can
+ // potentially sleep if the clock hasn't moved forward while the condition was being
+ // checked.
+ let slices = self.gsp_mem.driver_read_area();
+ if !slices.0.is_empty() {
+ Ok(slices)
+ } else {
+ Err(ETIMEDOUT)
+ }
+ } else {
+ read_poll_timeout(
+ || Ok(self.gsp_mem.driver_read_area()),
+ |driver_area| !driver_area.0.is_empty(),
+ Delta::from_millis(1),
+ timeout,
+ )
+ }
.map(|(slice_1, slice_2)| (slice_1.as_flattened(), slice_2.as_flattened()))?;
// Extract the `GspMsgElement`.
--
2.56.0