[PATCH v3 01/31] gpu: nova-core: gsp: pass boot context through setup helpers
From: Zhi Wang
Date: Mon Sep 28 2026 - 06:34:10 EST
The GSP boot paths pass the device, chipset, BAR and vGPU state to the
VRAM layout and GSP_INIT helpers as separate arguments. These values
are already available in GspBootContext, and some are forwarded again
to the WPR2 heap and VF topology helpers.
Pass the boot context through these helpers so each can read the fields
it needs. This simplifies the helper signatures and their call sites.
No functional change is intended.
Cc: Alexandre Courbot <acourbot@xxxxxxxxxx>
Signed-off-by: Zhi Wang <zhiw@xxxxxxxxxx>
---
drivers/gpu/nova-core/fb.rs | 26 +++++++++++---------------
drivers/gpu/nova-core/gsp/boot.rs | 2 +-
drivers/gpu/nova-core/gsp/commands.rs | 26 +++++++++++---------------
drivers/gpu/nova-core/gsp/hal/gh100.rs | 2 +-
drivers/gpu/nova-core/gsp/hal/tu102.rs | 2 +-
5 files changed, 25 insertions(+), 33 deletions(-)
diff --git a/drivers/gpu/nova-core/fb.rs b/drivers/gpu/nova-core/fb.rs
index 5ceb7760c78e..26e94d908b77 100644
--- a/drivers/gpu/nova-core/fb.rs
+++ b/drivers/gpu/nova-core/fb.rs
@@ -174,13 +174,9 @@ pub(crate) struct FbRanges {
impl FbRanges {
/// Computes concrete framebuffer ranges required on non-FSP booting architectures.
- pub(crate) fn new(
- chipset: Chipset,
- bar: Bar0<'_>,
- gsp_fw: &GspFirmware<'_>,
- vgpu_state: VgpuState,
- ) -> Result<Self> {
- let hal = hal::fb_hal(chipset);
+ pub(crate) fn new(ctx: &gsp::GspBootContext<'_, '_>, gsp_fw: &GspFirmware<'_>) -> Result<Self> {
+ let bar = ctx.bar;
+ let hal = hal::fb_hal(ctx.chipset);
let fb = {
let fb_size = hal.vidmem_size(bar);
@@ -242,7 +238,7 @@ pub(crate) fn new(
FbRange(fw_image_addr..fw_image_addr + fw_image_size)
};
- let (vf_partition_count, wpr2_heap_size) = wpr2_heap_params(chipset, vgpu_state, fb.end)?;
+ let (vf_partition_count, wpr2_heap_size) = wpr2_heap_params(ctx, fb.end)?;
let wpr2_heap = {
const WPR2_HEAP_DOWN_ALIGN: Alignment = Alignment::SZ_1M;
@@ -298,11 +294,11 @@ pub(crate) fn wpr2_range(bar: Bar0<'_>) -> Option<Range<u64>> {
}
/// Computes the number of VF partitions and the WPR2 heap size from the vGPU state.
-fn wpr2_heap_params(chipset: Chipset, vgpu_state: VgpuState, fb_size: u64) -> Result<(u8, u64)> {
- Ok(match vgpu_state {
+fn wpr2_heap_params(ctx: &gsp::GspBootContext<'_, '_>, fb_size: u64) -> Result<(u8, u64)> {
+ Ok(match ctx.vgpu.state() {
VgpuState::Disabled => (
0,
- gsp::LibosParams::from_chipset(chipset).wpr_heap_size(chipset, fb_size)?,
+ gsp::LibosParams::from_chipset(ctx.chipset).wpr_heap_size(ctx.chipset, fb_size)?,
),
VgpuState::Enabled { total_vfs } => (
u8::try_from(total_vfs.get()).map_err(|_| EINVAL)?,
@@ -328,10 +324,10 @@ pub(crate) struct FbSizes {
impl FbSizes {
/// Computes the framebuffer region sizes for GSP-FMC boot.
- pub(crate) fn new(chipset: Chipset, bar: Bar0<'_>, vgpu_state: VgpuState) -> Result<Self> {
- let hal = hal::fb_hal(chipset);
- let fb_size = hal.vidmem_size(bar);
- let (vf_partition_count, wpr2_heap_size) = wpr2_heap_params(chipset, vgpu_state, fb_size)?;
+ pub(crate) fn new(ctx: &gsp::GspBootContext<'_, '_>) -> Result<Self> {
+ let hal = hal::fb_hal(ctx.chipset);
+ let fb_size = hal.vidmem_size(ctx.bar);
+ let (vf_partition_count, wpr2_heap_size) = wpr2_heap_params(ctx, fb_size)?;
Ok(Self {
frts_size: hal.frts_size(),
diff --git a/drivers/gpu/nova-core/gsp/boot.rs b/drivers/gpu/nova-core/gsp/boot.rs
index 8848feebb9db..510d32212d41 100644
--- a/drivers/gpu/nova-core/gsp/boot.rs
+++ b/drivers/gpu/nova-core/gsp/boot.rs
@@ -401,7 +401,7 @@ pub(crate) fn boot(
dev_dbg!(pdev, "RISC-V active? {}\n", gsp_falcon.is_riscv_active(),);
- let init_payload = commands::build_gsp_init_payload(pdev, chipset, ctx.vgpu.state())?;
+ let init_payload = commands::build_gsp_init_payload(ctx)?;
let load_exec = LoadExecContext {
bootloader: generic_bootloader.as_ref(),
gsp_falcon,
diff --git a/drivers/gpu/nova-core/gsp/commands.rs b/drivers/gpu/nova-core/gsp/commands.rs
index d12f90d94eb6..d6895dc5207e 100644
--- a/drivers/gpu/nova-core/gsp/commands.rs
+++ b/drivers/gpu/nova-core/gsp/commands.rs
@@ -2,14 +2,12 @@
// SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
use kernel::{
- device,
pci,
prelude::*,
transmute::AsBytes, //
};
use crate::{
- gpu::Chipset,
gsp::{
cmdq::Cmdq,
fw::{
@@ -30,6 +28,7 @@
Encoder,
UnknownKeyPolicy, //
},
+ GspBootContext, //
},
sbuffer::SBufferIter,
vgpu::VgpuState, //
@@ -42,28 +41,25 @@
/// # Errors
///
/// - `ENOMEM` if the request or the encoder buffer cannot be allocated.
-pub(crate) fn build_gsp_init_payload(
- pdev: &pci::Device<device::Bound>,
- chipset: Chipset,
- vgpu_state: VgpuState,
-) -> Result<EncodedStream> {
+/// - `ENODEV` if vGPU mode is enabled but the SR-IOV capability is missing.
+///
+/// Errors reading the PCI configuration or decoding the VF BAR layout are propagated as-is.
+pub(super) fn build_gsp_init_payload(ctx: &GspBootContext<'_, '_>) -> Result<EncodedStream> {
let mut encoder = Encoder::new();
- let vf_info = build_vf_info(pdev, vgpu_state)?;
- GspInitRequest::new(pdev, chipset, vgpu_state, vf_info)?.encode(&mut encoder)?;
+ let vf_info = build_vf_info(ctx)?;
+ GspInitRequest::new(ctx.pdev, ctx.chipset, ctx.vgpu.state(), vf_info)?.encode(&mut encoder)?;
Ok(encoder.finish())
}
/// Builds the optional VF topology portion of the `GSP_INIT` request.
-fn build_vf_info(
- pdev: &pci::Device<device::Bound>,
- vgpu_state: VgpuState,
-) -> Result<Option<VfInfo>> {
- let VgpuState::Enabled { total_vfs } = vgpu_state else {
+fn build_vf_info(ctx: &GspBootContext<'_, '_>) -> Result<Option<VfInfo>> {
+ let VgpuState::Enabled { total_vfs } = ctx.vgpu.state() else {
return Ok(None);
};
- let sriov = pdev
+ let sriov = ctx
+ .pdev
.config_space_extended()?
.find_ext_capability::<pci::ExtSriovRegs>()?
.ok_or(ENODEV)?;
diff --git a/drivers/gpu/nova-core/gsp/hal/gh100.rs b/drivers/gpu/nova-core/gsp/hal/gh100.rs
index 91201b51030e..f91cdd061706 100644
--- a/drivers/gpu/nova-core/gsp/hal/gh100.rs
+++ b/drivers/gpu/nova-core/gsp/hal/gh100.rs
@@ -151,7 +151,7 @@ fn boot<'gpu>(
let chipset = ctx.chipset;
let gsp_falcon = ctx.gsp_falcon;
- let fb_sizes = FbSizes::new(chipset, ctx.bar, ctx.vgpu.state())?;
+ let fb_sizes = FbSizes::new(ctx)?;
dev_dbg!(dev, "{:#x?}\n", fb_sizes);
let wpr_meta =
diff --git a/drivers/gpu/nova-core/gsp/hal/tu102.rs b/drivers/gpu/nova-core/gsp/hal/tu102.rs
index 265039b8ff55..c221797d6f3c 100644
--- a/drivers/gpu/nova-core/gsp/hal/tu102.rs
+++ b/drivers/gpu/nova-core/gsp/hal/tu102.rs
@@ -260,7 +260,7 @@ fn boot<'gpu>(
let gsp_falcon = ctx.gsp_falcon;
let sec2_falcon = ctx.sec2_falcon;
- let fb_ranges = FbRanges::new(chipset, bar, gsp_fw, ctx.vgpu.state())?;
+ let fb_ranges = FbRanges::new(ctx, gsp_fw)?;
dev_dbg!(dev, "{:#x?}\n", fb_ranges);
// Declared before the unload guard so that if Booter fails while running, SEC2 is reset