Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

gpu: nova-core: gsp: Add SetRegistry command

Add support for sending the SetRegistry command, which is critical to
GSP initialization.

The RM registry is serialized into a packed format and sent via the
command queue. For now only three parameters which are required to boot
GSP are hardcoded. In the future a kernel module parameter will be added
to enable other parameters to be added.

Signed-off-by: Alistair Popple <apopple@nvidia.com>
[acourbot@nvidia.com: split into its own patch.]
Signed-off-by: Alexandre Courbot <acourbot@nvidia.com>
Message-ID: <20251110-gsp_boot-v9-12-8ae4058e3c0e@nvidia.com>

authored by

Alistair Popple and committed by
Alexandre Courbot
19b0a6e7 edcb1342

+165 -7
+1
drivers/gpu/nova-core/gsp/boot.rs
··· 158 158 159 159 self.cmdq 160 160 .send_command(bar, commands::SetSystemInfo::new(pdev))?; 161 + self.cmdq.send_command(bar, commands::SetRegistry::new())?; 161 162 162 163 Ok(()) 163 164 }
+98 -6
drivers/gpu/nova-core/gsp/commands.rs
··· 1 1 // SPDX-License-Identifier: GPL-2.0 2 2 3 + use core::convert::Infallible; 4 + 3 5 use kernel::{ 4 6 device, 5 7 pci, 6 - prelude::*, // 8 + prelude::*, 9 + transmute::AsBytes, // 7 10 }; 8 11 9 - use crate::gsp::{ 10 - cmdq::CommandToGsp, 11 - fw::{ 12 - commands::GspSetSystemInfo, 13 - MsgFunction, // 12 + use crate::{ 13 + gsp::{ 14 + cmdq::CommandToGsp, 15 + fw::{ 16 + commands::*, 17 + MsgFunction, // 18 + }, 14 19 }, 20 + sbuffer::SBufferIter, 15 21 }; 16 22 17 23 /// The `GspSetSystemInfo` command. ··· 39 33 40 34 fn init(&self) -> impl Init<Self::Command, Self::InitError> { 41 35 GspSetSystemInfo::init(self.pdev) 36 + } 37 + } 38 + 39 + struct RegistryEntry { 40 + key: &'static str, 41 + value: u32, 42 + } 43 + 44 + /// The `SetRegistry` command. 45 + pub(crate) struct SetRegistry { 46 + entries: [RegistryEntry; Self::NUM_ENTRIES], 47 + } 48 + 49 + impl SetRegistry { 50 + // For now we hard-code the registry entries. Future work will allow others to 51 + // be added as module parameters. 52 + const NUM_ENTRIES: usize = 3; 53 + 54 + /// Creates a new `SetRegistry` command, using a set of hardcoded entries. 55 + pub(crate) fn new() -> Self { 56 + Self { 57 + entries: [ 58 + // RMSecBusResetEnable - enables PCI secondary bus reset 59 + RegistryEntry { 60 + key: "RMSecBusResetEnable", 61 + value: 1, 62 + }, 63 + // RMForcePcieConfigSave - forces GSP-RM to preserve PCI configuration registers on 64 + // any PCI reset. 65 + RegistryEntry { 66 + key: "RMForcePcieConfigSave", 67 + value: 1, 68 + }, 69 + // RMDevidCheckIgnore - allows GSP-RM to boot even if the PCI dev ID is not found 70 + // in the internal product name database. 71 + RegistryEntry { 72 + key: "RMDevidCheckIgnore", 73 + value: 1, 74 + }, 75 + ], 76 + } 77 + } 78 + } 79 + 80 + impl CommandToGsp for SetRegistry { 81 + const FUNCTION: MsgFunction = MsgFunction::SetRegistry; 82 + type Command = PackedRegistryTable; 83 + type InitError = Infallible; 84 + 85 + fn init(&self) -> impl Init<Self::Command, Self::InitError> { 86 + PackedRegistryTable::init(Self::NUM_ENTRIES as u32, self.variable_payload_len() as u32) 87 + } 88 + 89 + fn variable_payload_len(&self) -> usize { 90 + let mut key_size = 0; 91 + for i in 0..Self::NUM_ENTRIES { 92 + key_size += self.entries[i].key.len() + 1; // +1 for NULL terminator 93 + } 94 + Self::NUM_ENTRIES * size_of::<PackedRegistryEntry>() + key_size 95 + } 96 + 97 + fn init_variable_payload( 98 + &self, 99 + dst: &mut SBufferIter<core::array::IntoIter<&mut [u8], 2>>, 100 + ) -> Result { 101 + let string_data_start_offset = 102 + size_of::<PackedRegistryTable>() + Self::NUM_ENTRIES * size_of::<PackedRegistryEntry>(); 103 + 104 + // Array for string data. 105 + let mut string_data = KVec::new(); 106 + 107 + for entry in self.entries.iter().take(Self::NUM_ENTRIES) { 108 + dst.write_all( 109 + PackedRegistryEntry::new( 110 + (string_data_start_offset + string_data.len()) as u32, 111 + entry.value, 112 + ) 113 + .as_bytes(), 114 + )?; 115 + 116 + let key_bytes = entry.key.as_bytes(); 117 + string_data.extend_from_slice(key_bytes, GFP_KERNEL)?; 118 + string_data.push(0, GFP_KERNEL)?; 119 + } 120 + 121 + dst.write_all(string_data.as_slice()) 42 122 } 43 123 }
+50
drivers/gpu/nova-core/gsp/fw/commands.rs
··· 54 54 // SAFETY: These structs don't meet the no-padding requirements of FromBytes but 55 55 // that is not a problem because they are not used outside the kernel. 56 56 unsafe impl FromBytes for GspSetSystemInfo {} 57 + 58 + #[repr(transparent)] 59 + pub(crate) struct PackedRegistryEntry(bindings::PACKED_REGISTRY_ENTRY); 60 + 61 + impl PackedRegistryEntry { 62 + pub(crate) fn new(offset: u32, value: u32) -> Self { 63 + Self({ 64 + bindings::PACKED_REGISTRY_ENTRY { 65 + nameOffset: offset, 66 + 67 + // We only support DWORD types for now. Support for other types 68 + // will come later if required. 69 + type_: bindings::REGISTRY_TABLE_ENTRY_TYPE_DWORD as u8, 70 + __bindgen_padding_0: Default::default(), 71 + data: value, 72 + length: 0, 73 + } 74 + }) 75 + } 76 + } 77 + 78 + // SAFETY: Padding is explicit and will not contain uninitialized data. 79 + unsafe impl AsBytes for PackedRegistryEntry {} 80 + 81 + /// Payload of the `SetRegistry` command. 82 + #[repr(transparent)] 83 + pub(crate) struct PackedRegistryTable { 84 + inner: bindings::PACKED_REGISTRY_TABLE, 85 + } 86 + 87 + impl PackedRegistryTable { 88 + #[allow(non_snake_case)] 89 + pub(crate) fn init(num_entries: u32, size: u32) -> impl Init<Self> { 90 + type InnerPackedRegistryTable = bindings::PACKED_REGISTRY_TABLE; 91 + let init_inner = init!(InnerPackedRegistryTable { 92 + numEntries: num_entries, 93 + size, 94 + entries: Default::default() 95 + }); 96 + 97 + init!(PackedRegistryTable { inner <- init_inner }) 98 + } 99 + } 100 + 101 + // SAFETY: Padding is explicit and will not contain uninitialized data. 102 + unsafe impl AsBytes for PackedRegistryTable {} 103 + 104 + // SAFETY: This struct only contains integer types for which all bit patterns 105 + // are valid. 106 + unsafe impl FromBytes for PackedRegistryTable {}
+16
drivers/gpu/nova-core/gsp/fw/r570_144/bindings.rs
··· 649 649 pub __bindgen_padding_0: [u8; 6usize], 650 650 } 651 651 #[repr(C)] 652 + #[derive(Debug, Default, Copy, Clone)] 653 + pub struct PACKED_REGISTRY_ENTRY { 654 + pub nameOffset: u32_, 655 + pub type_: u8_, 656 + pub __bindgen_padding_0: [u8; 3usize], 657 + pub data: u32_, 658 + pub length: u32_, 659 + } 660 + #[repr(C)] 661 + #[derive(Debug, Default)] 662 + pub struct PACKED_REGISTRY_TABLE { 663 + pub size: u32_, 664 + pub numEntries: u32_, 665 + pub entries: __IncompleteArrayField<PACKED_REGISTRY_ENTRY>, 666 + } 667 + #[repr(C)] 652 668 #[derive(Debug, Default, Copy, Clone, Zeroable)] 653 669 pub struct msgqTxHeader { 654 670 pub version: u32_,
-1
drivers/gpu/nova-core/sbuffer.rs
··· 199 199 200 200 /// Ideally we would implement [`Write`], but it is not available in `core`. 201 201 /// So mimic `std::io::Write::write_all`. 202 - #[expect(unused)] 203 202 pub(crate) fn write_all(&mut self, mut src: &[u8]) -> Result { 204 203 while !src.is_empty() { 205 204 match self.get_slice_mut(src.len()) {