From: Zhi Wang 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 Signed-off-by: Alok Kumar --- drivers/gpu/nova-core/gsp.rs | 2 +- drivers/gpu/nova-core/gsp/commands/gmc.rs | 12 ++------- drivers/gpu/nova-core/gsp/nvkv.rs | 31 ++++++++++++++++++++++- 3 files changed, 33 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/nova-core/gsp.rs b/drivers/gpu/nova-core/gsp.rs index cac123cbeac4..8424aa3937e7 100644 --- a/drivers/gpu/nova-core/gsp.rs +++ b/drivers/gpu/nova-core/gsp.rs @@ -28,7 +28,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/gmc.rs b/drivers/gpu/nova-core/gsp/commands/gmc.rs index 6f88c99349ac..33aea614cf72 100644 --- a/drivers/gpu/nova-core/gsp/commands/gmc.rs +++ b/drivers/gpu/nova-core/gsp/commands/gmc.rs @@ -29,6 +29,7 @@ GmcCommandId, // }, nvkv::{ + nvkv_words, Decoder, Encodable, Encoder, @@ -151,16 +152,7 @@ impl MessageFromGsp for GspStaticInfo { fn read(payload: &mut SBufferIter>) -> Result { let bytes = payload.flush_into_kvec(GFP_KERNEL)?; - let chunks = bytes.chunks_exact(size_of::()); - if !chunks.remainder().is_empty() { - return Err(EINVAL); - } - let mut words = KVVec::with_capacity(chunks.len(), GFP_KERNEL)?; - for chunk in chunks { - // `chunks_exact` yields slices of exactly `size_of::()` bytes. - let word = chunk.try_into().map_err(|_| EINVAL)?; - words.push(u64::from_le_bytes(word), GFP_KERNEL)?; - } + let words = nvkv_words(&bytes, &[])?; let decoder = Decoder::new(&words, UnknownKeyPolicy::Ignore); let mut schema = KBox::init(GspInitResponseSchema::init(), GFP_KERNEL)?; diff --git a/drivers/gpu/nova-core/gsp/nvkv.rs b/drivers/gpu/nova-core/gsp/nvkv.rs index f81a9e60d89c..5887a61af02a 100644 --- a/drivers/gpu/nova-core/gsp/nvkv.rs +++ b/drivers/gpu/nova-core/gsp/nvkv.rs @@ -20,11 +20,40 @@ use kernel::{ alloc::ArrayVec, bitfield, - num::Bounded, // + num::Bounded, + prelude::*, // }; use crate::bounded_enum; +use crate::sbuffer::SBufferIter; + +/// Joins the two halves of a wrapped payload into the `u64` words an NVKV stream is made of. +/// +/// # Errors +/// +/// - `EINVAL` 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> { + const WORD_SIZE: usize = size_of::(); + + // Each byte slice is at most `isize::MAX` bytes, so their sum fits in `usize`. + let len = payload_0.len() + payload_1.len(); + if len % WORD_SIZE != 0 { + return Err(EINVAL); + } + + let mut words = KVVec::with_capacity(len / WORD_SIZE, GFP_KERNEL)?; + let mut bytes = SBufferIter::new_reader([payload_0, payload_1]); + for _ in 0..len / WORD_SIZE { + let mut word = [0u8; WORD_SIZE]; + bytes.read_exact(&mut word)?; + words.push(u64::from_le_bytes(word), GFP_KERNEL)?; + } + + Ok(words) +} + mod encode; pub(crate) use encode::*; -- 2.53.0