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: Retrieve GSP static info to gather GPU information

After GSP initialization is complete, retrieve the static configuration
information from GSP-RM. This information includes GPU name, capabilities,
memory configuration, and other properties. On some GPU variants, it is
also required to do this for initialization to complete.

Signed-off-by: Alistair Popple <apopple@nvidia.com>
Co-developed-by: Joel Fernandes <joelagnelf@nvidia.com>
Signed-off-by: Joel Fernandes <joelagnelf@nvidia.com>
Reviewed-by: Lyude Paul <lyude@redhat.com>
[acourbot@nvidia.com: properly abstract the command's bindings, add
relevant methods, make str_from_null_terminated return an Option, fix
size of GPU name array.]
Co-developed-by: Alexandre Courbot <acourbot@nvidia.com>
Signed-off-by: Alexandre Courbot <acourbot@nvidia.com>
Message-ID: <20251114195552.739371-14-joelagnelf@nvidia.com>

authored by

Alistair Popple and committed by
Alexandre Courbot
13f85988 0e7d572b

+266
+8
drivers/gpu/nova-core/gsp/boot.rs
··· 239 239 // Wait until GSP is fully initialized. 240 240 commands::wait_gsp_init_done(&mut self.cmdq)?; 241 241 242 + // Obtain and display basic GPU information. 243 + let info = commands::get_gsp_info(&mut self.cmdq, bar)?; 244 + dev_info!( 245 + pdev.as_ref(), 246 + "GPU name: {}\n", 247 + info.gpu_name().unwrap_or("invalid GPU name") 248 + ); 249 + 242 250 Ok(()) 243 251 } 244 252 }
+56
drivers/gpu/nova-core/gsp/commands.rs
··· 17 17 }; 18 18 19 19 use crate::{ 20 + driver::Bar0, 20 21 gsp::{ 21 22 cmdq::{ 22 23 Cmdq, ··· 30 29 }, 31 30 }, 32 31 sbuffer::SBufferIter, 32 + util, 33 33 }; 34 34 35 35 /// The `GspSetSystemInfo` command. ··· 168 166 Ok(_) => break Ok(()), 169 167 Err(ERANGE) => continue, 170 168 Err(e) => break Err(e), 169 + } 170 + } 171 + } 172 + 173 + /// The `GetGspStaticInfo` command. 174 + struct GetGspStaticInfo; 175 + 176 + impl CommandToGsp for GetGspStaticInfo { 177 + const FUNCTION: MsgFunction = MsgFunction::GetGspStaticInfo; 178 + type Command = GspStaticConfigInfo; 179 + type InitError = Infallible; 180 + 181 + fn init(&self) -> impl Init<Self::Command, Self::InitError> { 182 + GspStaticConfigInfo::init_zeroed() 183 + } 184 + } 185 + 186 + /// The reply from the GSP to the [`GetGspInfo`] command. 187 + pub(crate) struct GetGspStaticInfoReply { 188 + gpu_name: [u8; 64], 189 + } 190 + 191 + impl MessageFromGsp for GetGspStaticInfoReply { 192 + const FUNCTION: MsgFunction = MsgFunction::GetGspStaticInfo; 193 + type Message = GspStaticConfigInfo; 194 + type InitError = Infallible; 195 + 196 + fn read( 197 + msg: &Self::Message, 198 + _sbuffer: &mut SBufferIter<array::IntoIter<&[u8], 2>>, 199 + ) -> Result<Self, Self::InitError> { 200 + Ok(GetGspStaticInfoReply { 201 + gpu_name: msg.gpu_name_str(), 202 + }) 203 + } 204 + } 205 + 206 + impl GetGspStaticInfoReply { 207 + /// Returns the name of the GPU as a string, or `None` if the string given by the GSP was 208 + /// invalid. 209 + pub(crate) fn gpu_name(&self) -> Option<&str> { 210 + util::str_from_null_terminated(&self.gpu_name) 211 + } 212 + } 213 + 214 + /// Send the [`GetGspInfo`] command and awaits for its reply. 215 + pub(crate) fn get_gsp_info(cmdq: &mut Cmdq, bar: &Bar0) -> Result<GetGspStaticInfoReply> { 216 + cmdq.send_command(bar, GetGspStaticInfo)?; 217 + 218 + loop { 219 + match cmdq.receive_msg::<GetGspStaticInfoReply>(Delta::from_secs(5)) { 220 + Ok(info) => return Ok(info), 221 + Err(ERANGE) => continue, 222 + Err(e) => return Err(e), 171 223 } 172 224 } 173 225 }
+22
drivers/gpu/nova-core/gsp/fw/commands.rs
··· 104 104 // SAFETY: This struct only contains integer types for which all bit patterns 105 105 // are valid. 106 106 unsafe impl FromBytes for PackedRegistryTable {} 107 + 108 + /// Payload of the `GetGspStaticInfo` command and message. 109 + #[repr(transparent)] 110 + pub(crate) struct GspStaticConfigInfo(bindings::GspStaticConfigInfo_t); 111 + 112 + impl GspStaticConfigInfo { 113 + /// Returns a bytes array containing the (hopefully) zero-terminated name of this GPU. 114 + pub(crate) fn gpu_name_str(&self) -> [u8; 64] { 115 + self.0.gpuNameString 116 + } 117 + } 118 + 119 + // SAFETY: Padding is explicit and will not contain uninitialized data. 120 + unsafe impl AsBytes for GspStaticConfigInfo {} 121 + 122 + // SAFETY: This struct only contains integer types for which all bit patterns 123 + // are valid. 124 + unsafe impl FromBytes for GspStaticConfigInfo {} 125 + 126 + // SAFETY: This struct only contains integer types and fixed-size arrays for which 127 + // all bit patterns are valid. 128 + unsafe impl Zeroable for GspStaticConfigInfo {}
+163
drivers/gpu/nova-core/gsp/fw/r570_144/bindings.rs
··· 320 320 pub const NV_VGPU_MSG_EVENT_NUM_EVENTS: _bindgen_ty_3 = 4131; 321 321 pub type _bindgen_ty_3 = ffi::c_uint; 322 322 #[repr(C)] 323 + #[derive(Debug, Default, Copy, Clone)] 324 + pub struct NV0080_CTRL_GPU_GET_SRIOV_CAPS_PARAMS { 325 + pub totalVFs: u32_, 326 + pub firstVfOffset: u32_, 327 + pub vfFeatureMask: u32_, 328 + pub FirstVFBar0Address: u64_, 329 + pub FirstVFBar1Address: u64_, 330 + pub FirstVFBar2Address: u64_, 331 + pub bar0Size: u64_, 332 + pub bar1Size: u64_, 333 + pub bar2Size: u64_, 334 + pub b64bitBar0: u8_, 335 + pub b64bitBar1: u8_, 336 + pub b64bitBar2: u8_, 337 + pub bSriovEnabled: u8_, 338 + pub bSriovHeavyEnabled: u8_, 339 + pub bEmulateVFBar0TlbInvalidationRegister: u8_, 340 + pub bClientRmAllocatedCtxBuffer: u8_, 341 + pub bNonPowerOf2ChannelCountSupported: u8_, 342 + pub bVfResizableBAR1Supported: u8_, 343 + } 344 + #[repr(C)] 345 + #[derive(Debug, Default, Copy, Clone)] 346 + pub struct NV2080_CTRL_BIOS_GET_SKU_INFO_PARAMS { 347 + pub BoardID: u32_, 348 + pub chipSKU: [ffi::c_char; 9usize], 349 + pub chipSKUMod: [ffi::c_char; 5usize], 350 + pub skuConfigVersion: u32_, 351 + pub project: [ffi::c_char; 5usize], 352 + pub projectSKU: [ffi::c_char; 5usize], 353 + pub CDP: [ffi::c_char; 6usize], 354 + pub projectSKUMod: [ffi::c_char; 2usize], 355 + pub businessCycle: u32_, 356 + } 357 + pub type NV2080_CTRL_CMD_FB_GET_FB_REGION_SURFACE_MEM_TYPE_FLAG = [u8_; 17usize]; 358 + #[repr(C)] 359 + #[derive(Debug, Default, Copy, Clone)] 360 + pub struct NV2080_CTRL_CMD_FB_GET_FB_REGION_FB_REGION_INFO { 361 + pub base: u64_, 362 + pub limit: u64_, 363 + pub reserved: u64_, 364 + pub performance: u32_, 365 + pub supportCompressed: u8_, 366 + pub supportISO: u8_, 367 + pub bProtected: u8_, 368 + pub blackList: NV2080_CTRL_CMD_FB_GET_FB_REGION_SURFACE_MEM_TYPE_FLAG, 369 + } 370 + #[repr(C)] 371 + #[derive(Debug, Default, Copy, Clone)] 372 + pub struct NV2080_CTRL_CMD_FB_GET_FB_REGION_INFO_PARAMS { 373 + pub numFBRegions: u32_, 374 + pub fbRegion: [NV2080_CTRL_CMD_FB_GET_FB_REGION_FB_REGION_INFO; 16usize], 375 + } 376 + #[repr(C)] 377 + #[derive(Debug, Copy, Clone)] 378 + pub struct NV2080_CTRL_GPU_GET_GID_INFO_PARAMS { 379 + pub index: u32_, 380 + pub flags: u32_, 381 + pub length: u32_, 382 + pub data: [u8_; 256usize], 383 + } 384 + impl Default for NV2080_CTRL_GPU_GET_GID_INFO_PARAMS { 385 + fn default() -> Self { 386 + let mut s = ::core::mem::MaybeUninit::<Self>::uninit(); 387 + unsafe { 388 + ::core::ptr::write_bytes(s.as_mut_ptr(), 0, 1); 389 + s.assume_init() 390 + } 391 + } 392 + } 393 + #[repr(C)] 323 394 #[derive(Debug, Default, Copy, Clone, Zeroable)] 324 395 pub struct DOD_METHOD_DATA { 325 396 pub status: u32_, ··· 438 367 pub capsMethodData: CAPS_METHOD_DATA, 439 368 } 440 369 #[repr(C)] 370 + #[derive(Debug, Default, Copy, Clone)] 371 + pub struct VIRTUAL_DISPLAY_GET_MAX_RESOLUTION_PARAMS { 372 + pub headIndex: u32_, 373 + pub maxHResolution: u32_, 374 + pub maxVResolution: u32_, 375 + } 376 + #[repr(C)] 377 + #[derive(Debug, Default, Copy, Clone)] 378 + pub struct VIRTUAL_DISPLAY_GET_NUM_HEADS_PARAMS { 379 + pub numHeads: u32_, 380 + pub maxNumHeads: u32_, 381 + } 382 + #[repr(C)] 441 383 #[derive(Debug, Default, Copy, Clone, Zeroable)] 442 384 pub struct BUSINFO { 443 385 pub deviceID: u16_, ··· 477 393 #[derive(Debug, Default, Copy, Clone, Zeroable)] 478 394 pub struct GSP_PCIE_CONFIG_REG { 479 395 pub linkCap: u32_, 396 + } 397 + #[repr(C)] 398 + #[derive(Debug, Default, Copy, Clone)] 399 + pub struct EcidManufacturingInfo { 400 + pub ecidLow: u32_, 401 + pub ecidHigh: u32_, 402 + pub ecidExtended: u32_, 403 + } 404 + #[repr(C)] 405 + #[derive(Debug, Default, Copy, Clone)] 406 + pub struct FW_WPR_LAYOUT_OFFSET { 407 + pub nonWprHeapOffset: u64_, 408 + pub frtsOffset: u64_, 409 + } 410 + #[repr(C)] 411 + #[derive(Debug, Copy, Clone)] 412 + pub struct GspStaticConfigInfo_t { 413 + pub grCapsBits: [u8_; 23usize], 414 + pub gidInfo: NV2080_CTRL_GPU_GET_GID_INFO_PARAMS, 415 + pub SKUInfo: NV2080_CTRL_BIOS_GET_SKU_INFO_PARAMS, 416 + pub fbRegionInfoParams: NV2080_CTRL_CMD_FB_GET_FB_REGION_INFO_PARAMS, 417 + pub sriovCaps: NV0080_CTRL_GPU_GET_SRIOV_CAPS_PARAMS, 418 + pub sriovMaxGfid: u32_, 419 + pub engineCaps: [u32_; 3usize], 420 + pub poisonFuseEnabled: u8_, 421 + pub fb_length: u64_, 422 + pub fbio_mask: u64_, 423 + pub fb_bus_width: u32_, 424 + pub fb_ram_type: u32_, 425 + pub fbp_mask: u64_, 426 + pub l2_cache_size: u32_, 427 + pub gpuNameString: [u8_; 64usize], 428 + pub gpuShortNameString: [u8_; 64usize], 429 + pub gpuNameString_Unicode: [u16_; 64usize], 430 + pub bGpuInternalSku: u8_, 431 + pub bIsQuadroGeneric: u8_, 432 + pub bIsQuadroAd: u8_, 433 + pub bIsNvidiaNvs: u8_, 434 + pub bIsVgx: u8_, 435 + pub bGeforceSmb: u8_, 436 + pub bIsTitan: u8_, 437 + pub bIsTesla: u8_, 438 + pub bIsMobile: u8_, 439 + pub bIsGc6Rtd3Allowed: u8_, 440 + pub bIsGc8Rtd3Allowed: u8_, 441 + pub bIsGcOffRtd3Allowed: u8_, 442 + pub bIsGcoffLegacyAllowed: u8_, 443 + pub bIsMigSupported: u8_, 444 + pub RTD3GC6TotalBoardPower: u16_, 445 + pub RTD3GC6PerstDelay: u16_, 446 + pub bar1PdeBase: u64_, 447 + pub bar2PdeBase: u64_, 448 + pub bVbiosValid: u8_, 449 + pub vbiosSubVendor: u32_, 450 + pub vbiosSubDevice: u32_, 451 + pub bPageRetirementSupported: u8_, 452 + pub bSplitVasBetweenServerClientRm: u8_, 453 + pub bClRootportNeedsNosnoopWAR: u8_, 454 + pub displaylessMaxHeads: VIRTUAL_DISPLAY_GET_NUM_HEADS_PARAMS, 455 + pub displaylessMaxResolution: VIRTUAL_DISPLAY_GET_MAX_RESOLUTION_PARAMS, 456 + pub displaylessMaxPixels: u64_, 457 + pub hInternalClient: u32_, 458 + pub hInternalDevice: u32_, 459 + pub hInternalSubdevice: u32_, 460 + pub bSelfHostedMode: u8_, 461 + pub bAtsSupported: u8_, 462 + pub bIsGpuUefi: u8_, 463 + pub bIsEfiInit: u8_, 464 + pub ecidInfo: [EcidManufacturingInfo; 2usize], 465 + pub fwWprLayoutOffset: FW_WPR_LAYOUT_OFFSET, 466 + } 467 + impl Default for GspStaticConfigInfo_t { 468 + fn default() -> Self { 469 + let mut s = ::core::mem::MaybeUninit::<Self>::uninit(); 470 + unsafe { 471 + ::core::ptr::write_bytes(s.as_mut_ptr(), 0, 1); 472 + s.assume_init() 473 + } 474 + } 480 475 } 481 476 #[repr(C)] 482 477 #[derive(Debug, Default, Copy, Clone, Zeroable)]
+1
drivers/gpu/nova-core/nova_core.rs
··· 16 16 mod num; 17 17 mod regs; 18 18 mod sbuffer; 19 + mod util; 19 20 mod vbios; 20 21 21 22 pub(crate) const MODULE_NAME: &kernel::str::CStr = <LocalModule as kernel::ModuleMetadata>::NAME;
+16
drivers/gpu/nova-core/util.rs
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + 3 + /// Converts a null-terminated byte slice to a string, or `None` if the array does not 4 + /// contains any null byte or contains invalid characters. 5 + /// 6 + /// Contrary to [`kernel::str::CStr::from_bytes_with_nul`], the null byte can be anywhere in the 7 + /// slice, and not only in the last position. 8 + pub(crate) fn str_from_null_terminated(bytes: &[u8]) -> Option<&str> { 9 + use kernel::str::CStr; 10 + 11 + bytes 12 + .iter() 13 + .position(|&b| b == 0) 14 + .and_then(|null_pos| CStr::from_bytes_with_nul(&bytes[..=null_pos]).ok()) 15 + .and_then(|cstr| cstr.to_str().ok()) 16 + }