gpu: nova-core: build SetRegistry entries dynamically

The GSP SetRegistry command currently stores its registry entries in a
fixed-size array. That makes every additional runtime-dependent registry
object require reshaping the command data structure at the same time as the
feature that needs the new entry.

Keep the existing registry contents unchanged, but store them in a KVec so
SetRegistry can be constructed dynamically. The constructor now returns a
Result to propagate allocation failures while the command payload layout is
still computed from the final entry list.

Cc: Alexandre Courbot <acourbot@nvidia.com>
Signed-off-by: Zhi Wang <zhiw@nvidia.com>
Link: https://patch.msgid.link/20260701062622.3499033-7-zhiw@nvidia.com
[acourbot: remove orphan comment.]
Signed-off-by: Alexandre Courbot <acourbot@nvidia.com>
This commit is contained in:
Zhi Wang
2026-07-01 09:26:20 +03:00
committed by Alexandre Courbot
parent 2493c44165
commit d85845b64c
2 changed files with 44 additions and 34 deletions

View File

@@ -135,7 +135,7 @@ pub(crate) fn boot(
self.cmdq
.send_command_no_wait(bar, commands::SetSystemInfo::new(pdev, chipset))?;
self.cmdq
.send_command_no_wait(bar, commands::SetRegistry::new())?;
.send_command_no_wait(bar, commands::SetRegistry::new()?)?;
hal.post_boot(&self, &ctx, &gsp_fw)?;

View File

@@ -67,37 +67,44 @@ struct RegistryEntry {
/// The `SetRegistry` command.
pub(crate) struct SetRegistry {
entries: [RegistryEntry; Self::NUM_ENTRIES],
entries: KVec<RegistryEntry>,
}
impl SetRegistry {
// For now we hard-code the registry entries. Future work will allow others to
// be added as module parameters.
const NUM_ENTRIES: usize = 3;
/// Creates a new `SetRegistry` command, using a set of hardcoded entries.
pub(crate) fn new() -> Self {
Self {
entries: [
// RMSecBusResetEnable - enables PCI secondary bus reset
RegistryEntry {
key: "RMSecBusResetEnable",
value: 1,
},
// RMForcePcieConfigSave - forces GSP-RM to preserve PCI configuration registers on
// any PCI reset.
RegistryEntry {
key: "RMForcePcieConfigSave",
value: 1,
},
// RMDevidCheckIgnore - allows GSP-RM to boot even if the PCI dev ID is not found
// in the internal product name database.
RegistryEntry {
key: "RMDevidCheckIgnore",
value: 1,
},
],
}
pub(crate) fn new() -> Result<Self> {
let mut entries = KVec::new();
// RMSecBusResetEnable - enables PCI secondary bus reset
entries.push(
RegistryEntry {
key: "RMSecBusResetEnable",
value: 1,
},
GFP_KERNEL,
)?;
// RMForcePcieConfigSave - forces GSP-RM to preserve PCI configuration registers on
// any PCI reset.
entries.push(
RegistryEntry {
key: "RMForcePcieConfigSave",
value: 1,
},
GFP_KERNEL,
)?;
// RMDevidCheckIgnore - allows GSP-RM to boot even if the PCI dev ID is not found
// in the internal product name database.
entries.push(
RegistryEntry {
key: "RMDevidCheckIgnore",
value: 1,
},
GFP_KERNEL,
)?;
Ok(Self { entries })
}
}
@@ -108,15 +115,18 @@ impl CommandToGsp for SetRegistry {
type InitError = Infallible;
fn init(&self) -> impl Init<Self::Command, Self::InitError> {
Self::Command::init(Self::NUM_ENTRIES as u32, self.variable_payload_len() as u32)
Self::Command::init(
self.entries.len() as u32,
self.variable_payload_len() as u32,
)
}
fn variable_payload_len(&self) -> usize {
let mut key_size = 0;
for i in 0..Self::NUM_ENTRIES {
key_size += self.entries[i].key.len() + 1; // +1 for NULL terminator
for entry in self.entries.iter() {
key_size += entry.key.len() + 1; // +1 for NULL terminator
}
Self::NUM_ENTRIES * size_of::<fw::commands::PackedRegistryEntry>() + key_size
self.entries.len() * size_of::<fw::commands::PackedRegistryEntry>() + key_size
}
fn init_variable_payload(
@@ -124,12 +134,12 @@ fn init_variable_payload(
dst: &mut SBufferIter<core::array::IntoIter<&mut [u8], 2>>,
) -> Result {
let string_data_start_offset = size_of::<Self::Command>()
+ Self::NUM_ENTRIES * size_of::<fw::commands::PackedRegistryEntry>();
+ self.entries.len() * size_of::<fw::commands::PackedRegistryEntry>();
// Array for string data.
let mut string_data = KVec::new();
for entry in self.entries.iter().take(Self::NUM_ENTRIES) {
for entry in self.entries.iter() {
dst.write_all(
fw::commands::PackedRegistryEntry::new(
(string_data_start_offset + string_data.len()) as u32,