mirror of
https://github.com/torvalds/linux.git
synced 2025-12-07 20:06:24 +00:00
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>
This commit is contained in:
committed by
Alexandre Courbot
parent
0e7d572b4b
commit
13f85988d4
@@ -239,6 +239,14 @@ impl super::Gsp {
|
||||
// Wait until GSP is fully initialized.
|
||||
commands::wait_gsp_init_done(&mut self.cmdq)?;
|
||||
|
||||
// Obtain and display basic GPU information.
|
||||
let info = commands::get_gsp_info(&mut self.cmdq, bar)?;
|
||||
dev_info!(
|
||||
pdev.as_ref(),
|
||||
"GPU name: {}\n",
|
||||
info.gpu_name().unwrap_or("invalid GPU name")
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ use kernel::{
|
||||
};
|
||||
|
||||
use crate::{
|
||||
driver::Bar0,
|
||||
gsp::{
|
||||
cmdq::{
|
||||
Cmdq,
|
||||
@@ -29,6 +30,7 @@ use crate::{
|
||||
},
|
||||
},
|
||||
sbuffer::SBufferIter,
|
||||
util,
|
||||
};
|
||||
|
||||
/// The `GspSetSystemInfo` command.
|
||||
@@ -169,3 +171,57 @@ pub(crate) fn wait_gsp_init_done(cmdq: &mut Cmdq) -> Result {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The `GetGspStaticInfo` command.
|
||||
struct GetGspStaticInfo;
|
||||
|
||||
impl CommandToGsp for GetGspStaticInfo {
|
||||
const FUNCTION: MsgFunction = MsgFunction::GetGspStaticInfo;
|
||||
type Command = GspStaticConfigInfo;
|
||||
type InitError = Infallible;
|
||||
|
||||
fn init(&self) -> impl Init<Self::Command, Self::InitError> {
|
||||
GspStaticConfigInfo::init_zeroed()
|
||||
}
|
||||
}
|
||||
|
||||
/// The reply from the GSP to the [`GetGspInfo`] command.
|
||||
pub(crate) struct GetGspStaticInfoReply {
|
||||
gpu_name: [u8; 64],
|
||||
}
|
||||
|
||||
impl MessageFromGsp for GetGspStaticInfoReply {
|
||||
const FUNCTION: MsgFunction = MsgFunction::GetGspStaticInfo;
|
||||
type Message = GspStaticConfigInfo;
|
||||
type InitError = Infallible;
|
||||
|
||||
fn read(
|
||||
msg: &Self::Message,
|
||||
_sbuffer: &mut SBufferIter<array::IntoIter<&[u8], 2>>,
|
||||
) -> Result<Self, Self::InitError> {
|
||||
Ok(GetGspStaticInfoReply {
|
||||
gpu_name: msg.gpu_name_str(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl GetGspStaticInfoReply {
|
||||
/// Returns the name of the GPU as a string, or `None` if the string given by the GSP was
|
||||
/// invalid.
|
||||
pub(crate) fn gpu_name(&self) -> Option<&str> {
|
||||
util::str_from_null_terminated(&self.gpu_name)
|
||||
}
|
||||
}
|
||||
|
||||
/// Send the [`GetGspInfo`] command and awaits for its reply.
|
||||
pub(crate) fn get_gsp_info(cmdq: &mut Cmdq, bar: &Bar0) -> Result<GetGspStaticInfoReply> {
|
||||
cmdq.send_command(bar, GetGspStaticInfo)?;
|
||||
|
||||
loop {
|
||||
match cmdq.receive_msg::<GetGspStaticInfoReply>(Delta::from_secs(5)) {
|
||||
Ok(info) => return Ok(info),
|
||||
Err(ERANGE) => continue,
|
||||
Err(e) => return Err(e),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -104,3 +104,25 @@ unsafe impl AsBytes for PackedRegistryTable {}
|
||||
// SAFETY: This struct only contains integer types for which all bit patterns
|
||||
// are valid.
|
||||
unsafe impl FromBytes for PackedRegistryTable {}
|
||||
|
||||
/// Payload of the `GetGspStaticInfo` command and message.
|
||||
#[repr(transparent)]
|
||||
pub(crate) struct GspStaticConfigInfo(bindings::GspStaticConfigInfo_t);
|
||||
|
||||
impl GspStaticConfigInfo {
|
||||
/// Returns a bytes array containing the (hopefully) zero-terminated name of this GPU.
|
||||
pub(crate) fn gpu_name_str(&self) -> [u8; 64] {
|
||||
self.0.gpuNameString
|
||||
}
|
||||
}
|
||||
|
||||
// SAFETY: Padding is explicit and will not contain uninitialized data.
|
||||
unsafe impl AsBytes for GspStaticConfigInfo {}
|
||||
|
||||
// SAFETY: This struct only contains integer types for which all bit patterns
|
||||
// are valid.
|
||||
unsafe impl FromBytes for GspStaticConfigInfo {}
|
||||
|
||||
// SAFETY: This struct only contains integer types and fixed-size arrays for which
|
||||
// all bit patterns are valid.
|
||||
unsafe impl Zeroable for GspStaticConfigInfo {}
|
||||
|
||||
@@ -320,6 +320,77 @@ pub const NV_VGPU_MSG_EVENT_RECOVERY_ACTION: _bindgen_ty_3 = 4130;
|
||||
pub const NV_VGPU_MSG_EVENT_NUM_EVENTS: _bindgen_ty_3 = 4131;
|
||||
pub type _bindgen_ty_3 = ffi::c_uint;
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Default, Copy, Clone)]
|
||||
pub struct NV0080_CTRL_GPU_GET_SRIOV_CAPS_PARAMS {
|
||||
pub totalVFs: u32_,
|
||||
pub firstVfOffset: u32_,
|
||||
pub vfFeatureMask: u32_,
|
||||
pub FirstVFBar0Address: u64_,
|
||||
pub FirstVFBar1Address: u64_,
|
||||
pub FirstVFBar2Address: u64_,
|
||||
pub bar0Size: u64_,
|
||||
pub bar1Size: u64_,
|
||||
pub bar2Size: u64_,
|
||||
pub b64bitBar0: u8_,
|
||||
pub b64bitBar1: u8_,
|
||||
pub b64bitBar2: u8_,
|
||||
pub bSriovEnabled: u8_,
|
||||
pub bSriovHeavyEnabled: u8_,
|
||||
pub bEmulateVFBar0TlbInvalidationRegister: u8_,
|
||||
pub bClientRmAllocatedCtxBuffer: u8_,
|
||||
pub bNonPowerOf2ChannelCountSupported: u8_,
|
||||
pub bVfResizableBAR1Supported: u8_,
|
||||
}
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Default, Copy, Clone)]
|
||||
pub struct NV2080_CTRL_BIOS_GET_SKU_INFO_PARAMS {
|
||||
pub BoardID: u32_,
|
||||
pub chipSKU: [ffi::c_char; 9usize],
|
||||
pub chipSKUMod: [ffi::c_char; 5usize],
|
||||
pub skuConfigVersion: u32_,
|
||||
pub project: [ffi::c_char; 5usize],
|
||||
pub projectSKU: [ffi::c_char; 5usize],
|
||||
pub CDP: [ffi::c_char; 6usize],
|
||||
pub projectSKUMod: [ffi::c_char; 2usize],
|
||||
pub businessCycle: u32_,
|
||||
}
|
||||
pub type NV2080_CTRL_CMD_FB_GET_FB_REGION_SURFACE_MEM_TYPE_FLAG = [u8_; 17usize];
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Default, Copy, Clone)]
|
||||
pub struct NV2080_CTRL_CMD_FB_GET_FB_REGION_FB_REGION_INFO {
|
||||
pub base: u64_,
|
||||
pub limit: u64_,
|
||||
pub reserved: u64_,
|
||||
pub performance: u32_,
|
||||
pub supportCompressed: u8_,
|
||||
pub supportISO: u8_,
|
||||
pub bProtected: u8_,
|
||||
pub blackList: NV2080_CTRL_CMD_FB_GET_FB_REGION_SURFACE_MEM_TYPE_FLAG,
|
||||
}
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Default, Copy, Clone)]
|
||||
pub struct NV2080_CTRL_CMD_FB_GET_FB_REGION_INFO_PARAMS {
|
||||
pub numFBRegions: u32_,
|
||||
pub fbRegion: [NV2080_CTRL_CMD_FB_GET_FB_REGION_FB_REGION_INFO; 16usize],
|
||||
}
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct NV2080_CTRL_GPU_GET_GID_INFO_PARAMS {
|
||||
pub index: u32_,
|
||||
pub flags: u32_,
|
||||
pub length: u32_,
|
||||
pub data: [u8_; 256usize],
|
||||
}
|
||||
impl Default for NV2080_CTRL_GPU_GET_GID_INFO_PARAMS {
|
||||
fn default() -> Self {
|
||||
let mut s = ::core::mem::MaybeUninit::<Self>::uninit();
|
||||
unsafe {
|
||||
::core::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
|
||||
s.assume_init()
|
||||
}
|
||||
}
|
||||
}
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Default, Copy, Clone, Zeroable)]
|
||||
pub struct DOD_METHOD_DATA {
|
||||
pub status: u32_,
|
||||
@@ -367,6 +438,19 @@ pub struct ACPI_METHOD_DATA {
|
||||
pub capsMethodData: CAPS_METHOD_DATA,
|
||||
}
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Default, Copy, Clone)]
|
||||
pub struct VIRTUAL_DISPLAY_GET_MAX_RESOLUTION_PARAMS {
|
||||
pub headIndex: u32_,
|
||||
pub maxHResolution: u32_,
|
||||
pub maxVResolution: u32_,
|
||||
}
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Default, Copy, Clone)]
|
||||
pub struct VIRTUAL_DISPLAY_GET_NUM_HEADS_PARAMS {
|
||||
pub numHeads: u32_,
|
||||
pub maxNumHeads: u32_,
|
||||
}
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Default, Copy, Clone, Zeroable)]
|
||||
pub struct BUSINFO {
|
||||
pub deviceID: u16_,
|
||||
@@ -395,6 +479,85 @@ pub struct GSP_PCIE_CONFIG_REG {
|
||||
pub linkCap: u32_,
|
||||
}
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Default, Copy, Clone)]
|
||||
pub struct EcidManufacturingInfo {
|
||||
pub ecidLow: u32_,
|
||||
pub ecidHigh: u32_,
|
||||
pub ecidExtended: u32_,
|
||||
}
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Default, Copy, Clone)]
|
||||
pub struct FW_WPR_LAYOUT_OFFSET {
|
||||
pub nonWprHeapOffset: u64_,
|
||||
pub frtsOffset: u64_,
|
||||
}
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct GspStaticConfigInfo_t {
|
||||
pub grCapsBits: [u8_; 23usize],
|
||||
pub gidInfo: NV2080_CTRL_GPU_GET_GID_INFO_PARAMS,
|
||||
pub SKUInfo: NV2080_CTRL_BIOS_GET_SKU_INFO_PARAMS,
|
||||
pub fbRegionInfoParams: NV2080_CTRL_CMD_FB_GET_FB_REGION_INFO_PARAMS,
|
||||
pub sriovCaps: NV0080_CTRL_GPU_GET_SRIOV_CAPS_PARAMS,
|
||||
pub sriovMaxGfid: u32_,
|
||||
pub engineCaps: [u32_; 3usize],
|
||||
pub poisonFuseEnabled: u8_,
|
||||
pub fb_length: u64_,
|
||||
pub fbio_mask: u64_,
|
||||
pub fb_bus_width: u32_,
|
||||
pub fb_ram_type: u32_,
|
||||
pub fbp_mask: u64_,
|
||||
pub l2_cache_size: u32_,
|
||||
pub gpuNameString: [u8_; 64usize],
|
||||
pub gpuShortNameString: [u8_; 64usize],
|
||||
pub gpuNameString_Unicode: [u16_; 64usize],
|
||||
pub bGpuInternalSku: u8_,
|
||||
pub bIsQuadroGeneric: u8_,
|
||||
pub bIsQuadroAd: u8_,
|
||||
pub bIsNvidiaNvs: u8_,
|
||||
pub bIsVgx: u8_,
|
||||
pub bGeforceSmb: u8_,
|
||||
pub bIsTitan: u8_,
|
||||
pub bIsTesla: u8_,
|
||||
pub bIsMobile: u8_,
|
||||
pub bIsGc6Rtd3Allowed: u8_,
|
||||
pub bIsGc8Rtd3Allowed: u8_,
|
||||
pub bIsGcOffRtd3Allowed: u8_,
|
||||
pub bIsGcoffLegacyAllowed: u8_,
|
||||
pub bIsMigSupported: u8_,
|
||||
pub RTD3GC6TotalBoardPower: u16_,
|
||||
pub RTD3GC6PerstDelay: u16_,
|
||||
pub bar1PdeBase: u64_,
|
||||
pub bar2PdeBase: u64_,
|
||||
pub bVbiosValid: u8_,
|
||||
pub vbiosSubVendor: u32_,
|
||||
pub vbiosSubDevice: u32_,
|
||||
pub bPageRetirementSupported: u8_,
|
||||
pub bSplitVasBetweenServerClientRm: u8_,
|
||||
pub bClRootportNeedsNosnoopWAR: u8_,
|
||||
pub displaylessMaxHeads: VIRTUAL_DISPLAY_GET_NUM_HEADS_PARAMS,
|
||||
pub displaylessMaxResolution: VIRTUAL_DISPLAY_GET_MAX_RESOLUTION_PARAMS,
|
||||
pub displaylessMaxPixels: u64_,
|
||||
pub hInternalClient: u32_,
|
||||
pub hInternalDevice: u32_,
|
||||
pub hInternalSubdevice: u32_,
|
||||
pub bSelfHostedMode: u8_,
|
||||
pub bAtsSupported: u8_,
|
||||
pub bIsGpuUefi: u8_,
|
||||
pub bIsEfiInit: u8_,
|
||||
pub ecidInfo: [EcidManufacturingInfo; 2usize],
|
||||
pub fwWprLayoutOffset: FW_WPR_LAYOUT_OFFSET,
|
||||
}
|
||||
impl Default for GspStaticConfigInfo_t {
|
||||
fn default() -> Self {
|
||||
let mut s = ::core::mem::MaybeUninit::<Self>::uninit();
|
||||
unsafe {
|
||||
::core::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
|
||||
s.assume_init()
|
||||
}
|
||||
}
|
||||
}
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Default, Copy, Clone, Zeroable)]
|
||||
pub struct GspSystemInfo {
|
||||
pub gpuPhysAddr: u64_,
|
||||
|
||||
@@ -16,6 +16,7 @@ mod gsp;
|
||||
mod num;
|
||||
mod regs;
|
||||
mod sbuffer;
|
||||
mod util;
|
||||
mod vbios;
|
||||
|
||||
pub(crate) const MODULE_NAME: &kernel::str::CStr = <LocalModule as kernel::ModuleMetadata>::NAME;
|
||||
|
||||
16
drivers/gpu/nova-core/util.rs
Normal file
16
drivers/gpu/nova-core/util.rs
Normal file
@@ -0,0 +1,16 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
/// Converts a null-terminated byte slice to a string, or `None` if the array does not
|
||||
/// contains any null byte or contains invalid characters.
|
||||
///
|
||||
/// Contrary to [`kernel::str::CStr::from_bytes_with_nul`], the null byte can be anywhere in the
|
||||
/// slice, and not only in the last position.
|
||||
pub(crate) fn str_from_null_terminated(bytes: &[u8]) -> Option<&str> {
|
||||
use kernel::str::CStr;
|
||||
|
||||
bytes
|
||||
.iter()
|
||||
.position(|&b| b == 0)
|
||||
.and_then(|null_pos| CStr::from_bytes_with_nul(&bytes[..=null_pos]).ok())
|
||||
.and_then(|cstr| cstr.to_str().ok())
|
||||
}
|
||||
Reference in New Issue
Block a user