[PATCH v2 01/32] gpu: nova-core: gsp: pass boot context through setup helpers
From: Zhi Wang
Date: Mon Sep 14 2026 - 04:05:47 EST
GSP boot unpacks the device, chipset, BAR and vGPU state from its
context only to pass them to framebuffer setup and GSP_INIT helpers.
The callers duplicate which context fields each helper needs.
Pass GspBootContext through the framebuffer sizing and GSP_INIT payload
helpers. Read the device and mode where they are used, including the
VF topology and WPR2 heap helpers. Keep mode detection, ownership and
firmware values unchanged.
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 | 25 +++++++++----------------
drivers/gpu/nova-core/gsp/hal/gh100.rs | 2 +-
drivers/gpu/nova-core/gsp/hal/tu102.rs | 2 +-
5 files changed, 23 insertions(+), 34 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 38ab737ad798..fa879685bac5 100644
--- a/drivers/gpu/nova-core/gsp/boot.rs
+++ b/drivers/gpu/nova-core/gsp/boot.rs
@@ -123,7 +123,7 @@ pub(crate) fn boot(
// GSP-RM discards any RPC that reaches it before GSP_INIT, so the system information
// and the registry keys go inside that one request.
- let init_payload = commands::build_gsp_init_payload(pdev, chipset, ctx.vgpu.state())?;
+ let init_payload = commands::build_gsp_init_payload(ctx)?;
let bootloader = if super::hal::uses_generic_bootloader(chipset) {
Some(GenericBootloader::new(dev, chipset, gsp_falcon)?)
} else {
diff --git a/drivers/gpu/nova-core/gsp/commands.rs b/drivers/gpu/nova-core/gsp/commands.rs
index 6d250548c165..ce1761c2f398 100644
--- a/drivers/gpu/nova-core/gsp/commands.rs
+++ b/drivers/gpu/nova-core/gsp/commands.rs
@@ -8,14 +8,12 @@
};
use kernel::{
- device,
pci,
prelude::*,
transmute::AsBytes, //
};
use crate::{
- gpu::Chipset,
gsp::{
cmdq::{
Cmdq,
@@ -40,6 +38,7 @@
Encoder,
UnknownKeyPolicy, //
},
+ GspBootContext,
},
sbuffer::SBufferIter,
vgpu::VgpuState, //
@@ -103,37 +102,31 @@ pub(crate) fn gpu_name(&self) -> core::result::Result<&str, GpuNameError> {
/// - `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(crate) fn build_gsp_init_payload(
- pdev: &pci::Device<device::Bound>,
- chipset: Chipset,
- vgpu_state: VgpuState,
-) -> Result<EncodedStream> {
+pub(super) fn build_gsp_init_payload(ctx: &GspBootContext<'_, '_>) -> Result<EncodedStream> {
let mut regkeys = KVVec::new();
for &(name, value) in REGISTRY_ENTRIES {
regkeys.push(RegKey::new(name, value), GFP_KERNEL)?;
}
- if matches!(vgpu_state, VgpuState::Enabled { .. }) {
+ if matches!(ctx.vgpu.state(), VgpuState::Enabled { .. }) {
regkeys.push(RegKey::new(b"RMSetSriovMode\0", 1), GFP_KERNEL)?;
}
- let vf_info = build_vf_info(pdev, vgpu_state)?;
+ let vf_info = build_vf_info(ctx)?;
let mut encoder = Encoder::new();
- GspInitRequest::new(pdev, chipset, regkeys, vf_info).encode(&mut encoder)?;
+ GspInitRequest::new(ctx.pdev, ctx.chipset, regkeys, 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 bbdcf754ec13..c3a87e5c7e0b 100644
--- a/drivers/gpu/nova-core/gsp/hal/tu102.rs
+++ b/drivers/gpu/nova-core/gsp/hal/tu102.rs
@@ -259,7 +259,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