[PATCH v2 4/6] gpu: nova-core: gsp: cmdq: move message trimming into its own function

From: Alexandre Courbot

Date: Fri Nov 06 2026 - 02:08:05 EST


Trimming the two driver-owned slices of the command queue to the
advertised length of a message is going to be used by both RPC and GMC
messages, so factor that part out into a private function.

The parsing itself can be improved by leveraging `split_at_checked` and
`get`, so use them.

No functional change intended.

Suggested-by: Eliot Courtney <ecourtney@xxxxxxxxxx>
Link: https://lore.kernel.org/all/DMN62G2CDG3N.ETT4GRFXWKKU@xxxxxxxxxx/
Signed-off-by: Alexandre Courbot <acourbot@xxxxxxxxxx>
---
drivers/gpu/nova-core/gsp/cmdq.rs | 21 +++++++++++++++++++++
drivers/gpu/nova-core/gsp/cmdq/rpc.rs | 20 +-------------------
2 files changed, 22 insertions(+), 19 deletions(-)

diff --git a/drivers/gpu/nova-core/gsp/cmdq.rs b/drivers/gpu/nova-core/gsp/cmdq.rs
index 9dd11ac8952b..f3151aa8ea26 100644
--- a/drivers/gpu/nova-core/gsp/cmdq.rs
+++ b/drivers/gpu/nova-core/gsp/cmdq.rs
@@ -719,3 +719,24 @@ fn drain(&mut self) -> Result {
}
}
}
+
+/// Helper function that trims the concatenation of `slice_1` and `slice_2` to `length`.
+///
+/// Returns the truncated `(slice_1, slice_2)` pair, or `EIO` if `length > slice_1.len() +
+/// slice_2.len()`.
+fn trim_message_slice<'a>(
+ (slice_1, slice_2): (&'a [u8], &'a [u8]),
+ length: usize,
+) -> Result<(&'a [u8], &'a [u8])> {
+ // See if `slice_1` covers the whole message, take it entirely if it doesn't.
+ let slice_1 = slice_1
+ .split_at_checked(length)
+ .map(|split| split.0)
+ .unwrap_or(slice_1);
+ // `slice_2` is the remainder of the message not covered by `slice_1`.
+ let slice_2 = slice_2
+ .get(..length.saturating_sub(slice_1.len()))
+ .ok_or(EIO)?;
+
+ Ok((slice_1, slice_2))
+}
diff --git a/drivers/gpu/nova-core/gsp/cmdq/rpc.rs b/drivers/gpu/nova-core/gsp/cmdq/rpc.rs
index 36cba7c28d3e..6ee28e93586b 100644
--- a/drivers/gpu/nova-core/gsp/cmdq/rpc.rs
+++ b/drivers/gpu/nova-core/gsp/cmdq/rpc.rs
@@ -214,27 +214,9 @@ pub(super) fn parse(dev: &device::Device, element: GspMessage<'a>) -> Result<Rpc
payload_length,
);

- // Check that the driver read area is large enough for the message.
- if slice_1.len() + slice_2.len() < payload_length {
- return Err(EIO);
- }
-
- // Cut the message slices down to the actual length of the message.
- let (slice_1, slice_2) = if slice_1.len() > payload_length {
- // PANIC: we checked above that `slice_1` is at least as long as `payload_length`.
- (slice_1.split_at(payload_length).0, &slice_2[0..0])
- } else {
- (
- slice_1,
- // PANIC: we checked above that `slice_1.len() + slice_2.len()` is at least as
- // large as `payload_length`.
- slice_2.split_at(payload_length - slice_1.len()).0,
- )
- };
-
Ok(RpcMessage {
header: rpc_header,
- contents: (slice_1, slice_2),
+ contents: super::trim_message_slice((slice_1, slice_2), payload_length)?,
})
}


--
2.56.0