linux/drivers/gpu/nova-core/vgpu.rs
Zhi Wang 6dcbb4b132 gpu: nova-core: reserve vGPU WPR2 heap
GSP-RM needs a larger WPR2 heap when booting in vGPU mode. The heap size
is firmware-dependent, so it should come from the generated firmware
bindings instead of being open-coded in nova-core.

Pass the detected vGPU state into the framebuffer layout calculation. Keep
baremetal boots on the existing heap sizing path, and use the 570.144
vGPU default heap binding only when vGPU is enabled. The same state match
also sets the VF partition count, so disabled and invalid 0/1-VF states do
not enter the vGPU heap path.

Cc: Alexandre Courbot <acourbot@nvidia.com>
Signed-off-by: Zhi Wang <zhiw@nvidia.com>
Reviewed-by: Alexandre Courbot <acourbot@nvidia.com>
Link: https://patch.msgid.link/20260722073913.1807677-7-zhiw@nvidia.com
[ Use checked arithmetic to calculate wpr2_heap_addr. - Danilo ]
Signed-off-by: Danilo Krummrich <dakr@kernel.org>
2026-07-24 01:16:02 +02:00

92 lines
2.3 KiB
Rust

// SPDX-License-Identifier: GPL-2.0
use core::num::NonZero;
use kernel::{
device,
pci,
prelude::*, //
};
use crate::{
fsp::{
Fsp,
VgpuMode, //
},
gpu::Chipset, //
};
mod hal;
/// vGPU state detected during GPU construction.
#[derive(Debug, Clone, Copy)]
pub(crate) enum VgpuState {
/// vGPU mode is not enabled for this boot.
Disabled,
/// vGPU mode is enabled for this boot.
Enabled {
/// Total number of SR-IOV VFs supported by this device.
total_vfs: NonZero<u16>,
},
}
/// vGPU state manager.
pub(crate) struct VgpuManager {
state: VgpuState,
}
impl VgpuManager {
/// Creates a vGPU manager by querying SR-IOV and the FSP PRC vGPU knob.
pub(crate) fn new(
pdev: &pci::Device<device::Core<'_>>,
chipset: Chipset,
fsp: Option<&mut Fsp<'_>>,
) -> Self {
let state = Self::detect_state(pdev, chipset, fsp).unwrap_or_else(|e| {
dev_warn!(
pdev,
"vGPU state detection failed: {:?}; disabling vGPU\n",
e
);
VgpuState::Disabled
});
dev_dbg!(pdev, "vGPU state: {:?}\n", state);
Self { state }
}
/// Detects the vGPU state from the chipset, SR-IOV capability and FSP PRC knob.
fn detect_state(
pdev: &pci::Device<device::Core<'_>>,
chipset: Chipset,
fsp: Option<&mut Fsp<'_>>,
) -> Result<VgpuState> {
if !hal::vgpu_hal(chipset).supports_vgpu() {
return Ok(VgpuState::Disabled);
}
let Some(total_vfs) = pdev.sriov_get_totalvfs() else {
return Ok(VgpuState::Disabled);
};
if total_vfs.get() < 2 {
// The current vGPU path does not support single-VF SR-IOV devices yet.
// Treat one total VF as vGPU-disabled for now; single-VF support can relax
// this gate once the manager handles that topology.
return Ok(VgpuState::Disabled);
}
let fsp = fsp.ok_or(ENODEV)?;
match fsp.read_vgpu_mode(pdev.as_ref())? {
VgpuMode::Enabled => Ok(VgpuState::Enabled { total_vfs }),
VgpuMode::Disabled => Ok(VgpuState::Disabled),
}
}
/// Returns the detected vGPU state for this boot.
pub(crate) fn state(&self) -> VgpuState {
self.state
}
}