[PATCH v2 19/32] gpu: nova-core: gsp: factor out NVKV payload conversion
From: Zhi Wang
Date: Mon Sep 14 2026 - 04:05:25 EST
Both GSP initialization and vGPU property queries decode their replies as
NVKV streams.
Move the byte-to-word conversion helper into the NVKV module and make
that module accessible to the vGPU firmware interface.
No functional change is intended.
Signed-off-by: Zhi Wang <zhiw@xxxxxxxxxx>
---
drivers/gpu/nova-core/gsp.rs | 2 +-
drivers/gpu/nova-core/gsp/commands.rs | 24 +-----------------------
drivers/gpu/nova-core/gsp/nvkv.rs | 24 ++++++++++++++++++++++++
3 files changed, 26 insertions(+), 24 deletions(-)
diff --git a/drivers/gpu/nova-core/gsp.rs b/drivers/gpu/nova-core/gsp.rs
index 93291c67d6de..5b1e4eb7cad8 100644
--- a/drivers/gpu/nova-core/gsp.rs
+++ b/drivers/gpu/nova-core/gsp.rs
@@ -24,7 +24,7 @@
pub(crate) mod cmdq;
pub(crate) mod commands;
mod fw;
-mod nvkv;
+pub(crate) mod nvkv;
mod regs;
pub(crate) use fw::{
diff --git a/drivers/gpu/nova-core/gsp/commands.rs b/drivers/gpu/nova-core/gsp/commands.rs
index 7ca5ec2a58d9..7945a191bd08 100644
--- a/drivers/gpu/nova-core/gsp/commands.rs
+++ b/drivers/gpu/nova-core/gsp/commands.rs
@@ -33,6 +33,7 @@
GMCAPI_CMD_GSP_SUSPEND, //
},
nvkv::{
+ nvkv_words,
Decoder,
Encodable,
EncodedStream,
@@ -41,7 +42,6 @@
},
GspBootContext,
},
- sbuffer::SBufferIter,
vgpu::VgpuState, //
};
@@ -256,28 +256,6 @@ fn decode_gsp_init_reply(
decode_gsp_info(&nvkv_words(payload_0, payload_1)?)
}
-/// Joins the two halves of a wrapped payload into the `u64` words an NVKV stream is made of.
-///
-/// # Errors
-///
-/// - `EIO` if the combined length is not a whole number of words.
-/// - `ENOMEM` if the buffer cannot be allocated.
-fn nvkv_words(payload_0: &[u8], payload_1: &[u8]) -> Result<KVVec<u64>> {
- let bytes = SBufferIter::new_reader([payload_0, payload_1]).flush_into_kvec(GFP_KERNEL)?;
- let words = bytes.chunks_exact(size_of::<u64>());
- if !words.remainder().is_empty() {
- return Err(EIO);
- }
-
- let mut out = KVVec::with_capacity(bytes.len() / size_of::<u64>(), GFP_KERNEL)?;
- for word in words {
- let word: [u8; size_of::<u64>()] = word.try_into().map_err(|_| EIO)?;
- out.push(u64::from_le_bytes(word), GFP_KERNEL)?;
- }
-
- Ok(out)
-}
-
/// Decodes the static GPU configuration from an NVKV stream.
///
/// # Errors
diff --git a/drivers/gpu/nova-core/gsp/nvkv.rs b/drivers/gpu/nova-core/gsp/nvkv.rs
index e7a9549919fb..9f2119b98b26 100644
--- a/drivers/gpu/nova-core/gsp/nvkv.rs
+++ b/drivers/gpu/nova-core/gsp/nvkv.rs
@@ -27,6 +27,30 @@
};
use zerocopy::Immutable;
+use crate::sbuffer::SBufferIter;
+
+/// Joins the two halves of a wrapped payload into the `u64` words an NVKV stream is made of.
+///
+/// # Errors
+///
+/// - `EIO` if the combined length is not a whole number of words.
+/// - `ENOMEM` if the buffer cannot be allocated.
+pub(crate) fn nvkv_words(payload_0: &[u8], payload_1: &[u8]) -> Result<KVVec<u64>> {
+ let bytes = SBufferIter::new_reader([payload_0, payload_1]).flush_into_kvec(GFP_KERNEL)?;
+ let words = bytes.chunks_exact(size_of::<u64>());
+ if !words.remainder().is_empty() {
+ return Err(EIO);
+ }
+
+ let mut out = KVVec::with_capacity(bytes.len() / size_of::<u64>(), GFP_KERNEL)?;
+ for word in words {
+ let word: [u8; size_of::<u64>()] = word.try_into().map_err(|_| EIO)?;
+ out.push(u64::from_le_bytes(word), GFP_KERNEL)?;
+ }
+
+ Ok(out)
+}
+
mod encode;
pub(crate) use encode::*;