[PATCH v2 31/31] gpu: nova-core: distinguish GMC event and response debug logs
From: John Hubbard
Date: Fri Aug 21 2026 - 22:05:50 EST
GSP-initiated GMC events assign sequence numbers starting at bit 63 so
they cannot collide with driver request sequences, which start at zero.
The receive debug line printed the raw 64-bit value, so the first boot
event showed seq# 9223372036854775808 (0x8000000000000000), and it
labeled the GSP_INIT reply as an event.
Print the sequence with that bit cleared, and label a reply as a
response. Sample output on a Turing GPU:
nova-core 0000:c1:00.0: GSP GMC: send: seq# 0, command=GSP_INIT (0x10001), length=0xf8
nova-core 0000:c1:00.0: GSP GMC: event: seq# 0, command=EXEC_GENERIC_BOOTLOADER (0x10002), length=0xb0
nova-core 0000:c1:00.0: GSP GMC: response: seq# 0, command=GSP_INIT (0x10001), length=0x450
Assisted-by: Cursor:grok-4.6
Signed-off-by: John Hubbard <jhubbard@xxxxxxxxxx>
---
drivers/gpu/nova-core/gsp/cmdq.rs | 10 ++++++++--
drivers/gpu/nova-core/gsp/fw.rs | 17 +++++++++++++++++
2 files changed, 25 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/nova-core/gsp/cmdq.rs b/drivers/gpu/nova-core/gsp/cmdq.rs
index 8e97cc71f2b6..e6931f65b167 100644
--- a/drivers/gpu/nova-core/gsp/cmdq.rs
+++ b/drivers/gpu/nova-core/gsp/cmdq.rs
@@ -1299,11 +1299,17 @@ fn receive_gmc_and_dispatch<R>(
(None, QueuePointers::Unchanged)
} else {
let command_id = header.gmc.command_id();
+ let kind = if header.gmc.is_response() {
+ "response"
+ } else {
+ "event"
+ };
dev_dbg!(
&self.dev,
- "GSP GMC: event: seq# {}, command={}, length=0x{:x}\n",
- header.gmc.sequence,
+ "GSP GMC: {}: seq# {}, command={}, length=0x{:x}\n",
+ kind,
+ header.gmc.sequence_number(),
GmcCommand(command_id),
length,
);
diff --git a/drivers/gpu/nova-core/gsp/fw.rs b/drivers/gpu/nova-core/gsp/fw.rs
index 927332203a43..150c8042867a 100644
--- a/drivers/gpu/nova-core/gsp/fw.rs
+++ b/drivers/gpu/nova-core/gsp/fw.rs
@@ -674,6 +674,13 @@ pub(crate) struct GmcApiHeader {
/// `GMCAPI_HEADER_COMMAND_ID_MASK`. The remaining byte carries flags.
const GMCAPI_COMMAND_ID_MASK: u32 = 0x00ff_ffff;
+/// Response flag in the high byte of [`GmcApiHeader::command`].
+const GMCAPI_COMMAND_FLAGS_RESPONSE: u32 = 0x0100_0000;
+
+/// GSP-initiated events set [`GmcApiHeader::sequence`] starting at this value so they
+/// cannot collide with driver request sequences, which start at zero.
+const GMC_EVENT_SEQUENCE_BASE: u64 = 1 << 63;
+
/// GMC command that hands GSP-RM its system information and registry keys and returns the static
/// GPU configuration. Its reply is also what signals that GSP-RM has finished starting.
pub(crate) const GMCAPI_CMD_GSP_INIT: u32 = bindings::GMCAPI_COMMANDS_GMCAPI_CMD_GSP_INIT;
@@ -715,6 +722,16 @@ impl GmcApiHeader {
pub(crate) fn command_id(&self) -> u32 {
self.command & GMCAPI_COMMAND_ID_MASK
}
+
+ /// Returns `true` if this header is a reply to a driver request.
+ pub(crate) fn is_response(&self) -> bool {
+ self.command & GMCAPI_COMMAND_FLAGS_RESPONSE != 0
+ }
+
+ /// Returns [`Self::sequence`] with the GSP-initiated-event bit cleared.
+ pub(crate) fn sequence_number(&self) -> u64 {
+ self.sequence & !GMC_EVENT_SEQUENCE_BASE
+ }
}
// SAFETY: All fields are integer types with no uninitialized padding bytes.
--
2.55.0