Skip to content

Commit 13f8598

Browse files
apopple-nvidiaGnurou
authored andcommitted
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>
1 parent 0e7d572 commit 13f8598

6 files changed

Lines changed: 266 additions & 0 deletions

File tree

drivers/gpu/nova-core/gsp/boot.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,14 @@ impl super::Gsp {
239239
// Wait until GSP is fully initialized.
240240
commands::wait_gsp_init_done(&mut self.cmdq)?;
241241

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+
242250
Ok(())
243251
}
244252
}

drivers/gpu/nova-core/gsp/commands.rs

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ use kernel::{
1717
};
1818

1919
use crate::{
20+
driver::Bar0,
2021
gsp::{
2122
cmdq::{
2223
Cmdq,
@@ -29,6 +30,7 @@ use crate::{
2930
},
3031
},
3132
sbuffer::SBufferIter,
33+
util,
3234
};
3335

3436
/// The `GspSetSystemInfo` command.
@@ -169,3 +171,57 @@ pub(crate) fn wait_gsp_init_done(cmdq: &mut Cmdq) -> Result {
169171
}
170172
}
171173
}
174+
175+
/// The `GetGspStaticInfo` command.
176+
struct GetGspStaticInfo;
177+
178+
impl CommandToGsp for GetGspStaticInfo {
179+
const FUNCTION: MsgFunction = MsgFunction::GetGspStaticInfo;
180+
type Command = GspStaticConfigInfo;
181+
type InitError = Infallible;
182+
183+
fn init(&self) -> impl Init<Self::Command, Self::InitError> {
184+
GspStaticConfigInfo::init_zeroed()
185+
}
186+
}
187+
188+
/// The reply from the GSP to the [`GetGspInfo`] command.
189+
pub(crate) struct GetGspStaticInfoReply {
190+
gpu_name: [u8; 64],
191+
}
192+
193+
impl MessageFromGsp for GetGspStaticInfoReply {
194+
const FUNCTION: MsgFunction = MsgFunction::GetGspStaticInfo;
195+
type Message = GspStaticConfigInfo;
196+
type InitError = Infallible;
197+
198+
fn read(
199+
msg: &Self::Message,
200+
_sbuffer: &mut SBufferIter<array::IntoIter<&[u8], 2>>,
201+
) -> Result<Self, Self::InitError> {
202+
Ok(GetGspStaticInfoReply {
203+
gpu_name: msg.gpu_name_str(),
204+
})
205+
}
206+
}
207+
208+
impl GetGspStaticInfoReply {
209+
/// Returns the name of the GPU as a string, or `None` if the string given by the GSP was
210+
/// invalid.
211+
pub(crate) fn gpu_name(&self) -> Option<&str> {
212+
util::str_from_null_terminated(&self.gpu_name)
213+
}
214+
}
215+
216+
/// Send the [`GetGspInfo`] command and awaits for its reply.
217+
pub(crate) fn get_gsp_info(cmdq: &mut Cmdq, bar: &Bar0) -> Result<GetGspStaticInfoReply> {
218+
cmdq.send_command(bar, GetGspStaticInfo)?;
219+
220+
loop {
221+
match cmdq.receive_msg::<GetGspStaticInfoReply>(Delta::from_secs(5)) {
222+
Ok(info) => return Ok(info),
223+
Err(ERANGE) => continue,
224+
Err(e) => return Err(e),
225+
}
226+
}
227+
}

drivers/gpu/nova-core/gsp/fw/commands.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,3 +104,25 @@ unsafe impl AsBytes for PackedRegistryTable {}
104104
// SAFETY: This struct only contains integer types for which all bit patterns
105105
// are valid.
106106
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 {}

drivers/gpu/nova-core/gsp/fw/r570_144/bindings.rs

Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -320,6 +320,77 @@ pub const NV_VGPU_MSG_EVENT_RECOVERY_ACTION: _bindgen_ty_3 = 4130;
320320
pub const NV_VGPU_MSG_EVENT_NUM_EVENTS: _bindgen_ty_3 = 4131;
321321
pub type _bindgen_ty_3 = ffi::c_uint;
322322
#[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)]
323394
#[derive(Debug, Default, Copy, Clone, Zeroable)]
324395
pub struct DOD_METHOD_DATA {
325396
pub status: u32_,
@@ -367,6 +438,19 @@ pub struct ACPI_METHOD_DATA {
367438
pub capsMethodData: CAPS_METHOD_DATA,
368439
}
369440
#[repr(C)]
441+
#[derive(Debug, Default, Copy, Clone)]
442+
pub struct VIRTUAL_DISPLAY_GET_MAX_RESOLUTION_PARAMS {
443+
pub headIndex: u32_,
444+
pub maxHResolution: u32_,
445+
pub maxVResolution: u32_,
446+
}
447+
#[repr(C)]
448+
#[derive(Debug, Default, Copy, Clone)]
449+
pub struct VIRTUAL_DISPLAY_GET_NUM_HEADS_PARAMS {
450+
pub numHeads: u32_,
451+
pub maxNumHeads: u32_,
452+
}
453+
#[repr(C)]
370454
#[derive(Debug, Default, Copy, Clone, Zeroable)]
371455
pub struct BUSINFO {
372456
pub deviceID: u16_,
@@ -395,6 +479,85 @@ pub struct GSP_PCIE_CONFIG_REG {
395479
pub linkCap: u32_,
396480
}
397481
#[repr(C)]
482+
#[derive(Debug, Default, Copy, Clone)]
483+
pub struct EcidManufacturingInfo {
484+
pub ecidLow: u32_,
485+
pub ecidHigh: u32_,
486+
pub ecidExtended: u32_,
487+
}
488+
#[repr(C)]
489+
#[derive(Debug, Default, Copy, Clone)]
490+
pub struct FW_WPR_LAYOUT_OFFSET {
491+
pub nonWprHeapOffset: u64_,
492+
pub frtsOffset: u64_,
493+
}
494+
#[repr(C)]
495+
#[derive(Debug, Copy, Clone)]
496+
pub struct GspStaticConfigInfo_t {
497+
pub grCapsBits: [u8_; 23usize],
498+
pub gidInfo: NV2080_CTRL_GPU_GET_GID_INFO_PARAMS,
499+
pub SKUInfo: NV2080_CTRL_BIOS_GET_SKU_INFO_PARAMS,
500+
pub fbRegionInfoParams: NV2080_CTRL_CMD_FB_GET_FB_REGION_INFO_PARAMS,
501+
pub sriovCaps: NV0080_CTRL_GPU_GET_SRIOV_CAPS_PARAMS,
502+
pub sriovMaxGfid: u32_,
503+
pub engineCaps: [u32_; 3usize],
504+
pub poisonFuseEnabled: u8_,
505+
pub fb_length: u64_,
506+
pub fbio_mask: u64_,
507+
pub fb_bus_width: u32_,
508+
pub fb_ram_type: u32_,
509+
pub fbp_mask: u64_,
510+
pub l2_cache_size: u32_,
511+
pub gpuNameString: [u8_; 64usize],
512+
pub gpuShortNameString: [u8_; 64usize],
513+
pub gpuNameString_Unicode: [u16_; 64usize],
514+
pub bGpuInternalSku: u8_,
515+
pub bIsQuadroGeneric: u8_,
516+
pub bIsQuadroAd: u8_,
517+
pub bIsNvidiaNvs: u8_,
518+
pub bIsVgx: u8_,
519+
pub bGeforceSmb: u8_,
520+
pub bIsTitan: u8_,
521+
pub bIsTesla: u8_,
522+
pub bIsMobile: u8_,
523+
pub bIsGc6Rtd3Allowed: u8_,
524+
pub bIsGc8Rtd3Allowed: u8_,
525+
pub bIsGcOffRtd3Allowed: u8_,
526+
pub bIsGcoffLegacyAllowed: u8_,
527+
pub bIsMigSupported: u8_,
528+
pub RTD3GC6TotalBoardPower: u16_,
529+
pub RTD3GC6PerstDelay: u16_,
530+
pub bar1PdeBase: u64_,
531+
pub bar2PdeBase: u64_,
532+
pub bVbiosValid: u8_,
533+
pub vbiosSubVendor: u32_,
534+
pub vbiosSubDevice: u32_,
535+
pub bPageRetirementSupported: u8_,
536+
pub bSplitVasBetweenServerClientRm: u8_,
537+
pub bClRootportNeedsNosnoopWAR: u8_,
538+
pub displaylessMaxHeads: VIRTUAL_DISPLAY_GET_NUM_HEADS_PARAMS,
539+
pub displaylessMaxResolution: VIRTUAL_DISPLAY_GET_MAX_RESOLUTION_PARAMS,
540+
pub displaylessMaxPixels: u64_,
541+
pub hInternalClient: u32_,
542+
pub hInternalDevice: u32_,
543+
pub hInternalSubdevice: u32_,
544+
pub bSelfHostedMode: u8_,
545+
pub bAtsSupported: u8_,
546+
pub bIsGpuUefi: u8_,
547+
pub bIsEfiInit: u8_,
548+
pub ecidInfo: [EcidManufacturingInfo; 2usize],
549+
pub fwWprLayoutOffset: FW_WPR_LAYOUT_OFFSET,
550+
}
551+
impl Default for GspStaticConfigInfo_t {
552+
fn default() -> Self {
553+
let mut s = ::core::mem::MaybeUninit::<Self>::uninit();
554+
unsafe {
555+
::core::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
556+
s.assume_init()
557+
}
558+
}
559+
}
560+
#[repr(C)]
398561
#[derive(Debug, Default, Copy, Clone, Zeroable)]
399562
pub struct GspSystemInfo {
400563
pub gpuPhysAddr: u64_,

drivers/gpu/nova-core/nova_core.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ mod gsp;
1616
mod num;
1717
mod regs;
1818
mod sbuffer;
19+
mod util;
1920
mod vbios;
2021

2122
pub(crate) const MODULE_NAME: &kernel::str::CStr = <LocalModule as kernel::ModuleMetadata>::NAME;

drivers/gpu/nova-core/util.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
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+
}

0 commit comments

Comments
 (0)