[PATCH v3 06/12] gpu: nova-core: gsp: fold TU102 unload bundle construction into HAL method

From: Alexandre Courbot

Date: Mon Jun 29 2026 - 08:34:55 EST


The construction of the unload bundle is currently a bit convoluted and
could be done in one function instead of two.

Additionally, turn that function into a method of `Tu102`. A following
patch will turn the "use FWSEC bootloader" property into a flag of the
TU102 HAL itself, and making this a method will allow the code to access
it instead of querying `Chipset`.

Signed-off-by: Alexandre Courbot <acourbot@xxxxxxxxxx>
---
drivers/gpu/nova-core/gsp/hal/tu102.rs | 96 ++++++++++++++++------------------
1 file changed, 45 insertions(+), 51 deletions(-)

diff --git a/drivers/gpu/nova-core/gsp/hal/tu102.rs b/drivers/gpu/nova-core/gsp/hal/tu102.rs
index d669ce7625a8..22b4927cbaa6 100644
--- a/drivers/gpu/nova-core/gsp/hal/tu102.rs
+++ b/drivers/gpu/nova-core/gsp/hal/tu102.rs
@@ -56,23 +56,6 @@ enum FwsecUnloadFirmware {
}

impl FwsecUnloadFirmware {
- /// Loads the FWSEC SB firmware, as well as its bootloader if `chipset` requires it.
- fn new(
- dev: &device::Device<device::Bound>,
- bar: Bar0<'_>,
- chipset: Chipset,
- bios: &Vbios,
- gsp_falcon: &Falcon<GspEngine>,
- ) -> Result<Self> {
- let fwsec_sb = FwsecFirmware::new(dev, gsp_falcon, bar, bios, FwsecCommand::Sb)?;
-
- Ok(if chipset.needs_fwsec_bootloader() {
- Self::WithBl(FwsecFirmwareWithBl::new(fwsec_sb, dev, chipset)?)
- } else {
- Self::WithoutBl(fwsec_sb)
- })
- }
-
/// Runs the FWSEC SB firmware.
fn run(
&self,
@@ -94,35 +77,6 @@ struct Sec2UnloadBundle {
booter_unloader: BooterFirmware,
}

-impl Sec2UnloadBundle {
- /// Load and prepare the resources required to properly reset the GSP after it has been stopped.
- fn build(
- dev: &device::Device<device::Bound>,
- bar: Bar0<'_>,
- chipset: Chipset,
- bios: &Vbios,
- gsp_falcon: &Falcon<GspEngine>,
- sec2_falcon: &Falcon<Sec2>,
- ) -> Result<KBox<dyn UnloadBundle>> {
- KBox::new(
- Self {
- fwsec_sb: FwsecUnloadFirmware::new(dev, bar, chipset, bios, gsp_falcon)?,
- booter_unloader: BooterFirmware::new(
- dev,
- BooterKind::Unloader,
- chipset,
- FIRMWARE_VERSION,
- sec2_falcon,
- bar,
- )?,
- },
- GFP_KERNEL,
- )
- .map(|b| b as KBox<dyn UnloadBundle>)
- .map_err(Into::into)
- }
-}
-
impl UnloadBundle for Sec2UnloadBundle {
fn run(&self, ctx: &GspBootContext<'_>) -> Result {
let dev = ctx.dev();
@@ -261,6 +215,47 @@ fn run_fwsec_frts(

struct Tu102;

+impl Tu102 {
+ /// Load and prepare the resources required to properly reset the GSP after it has been stopped.
+ fn build_unload_bundle(
+ &self,
+ dev: &device::Device<device::Bound>,
+ bar: Bar0<'_>,
+ chipset: Chipset,
+ bios: &Vbios,
+ gsp_falcon: &Falcon<GspEngine>,
+ sec2_falcon: &Falcon<Sec2>,
+ ) -> Result<crate::gsp::UnloadBundle> {
+ // Load the FWSEC SB firmware, as well as its bootloader if required.
+ let fwsec_sb = FwsecFirmware::new(dev, gsp_falcon, bar, bios, FwsecCommand::Sb).and_then(
+ |fwsec_sb| {
+ Ok(if chipset.needs_fwsec_bootloader() {
+ FwsecUnloadFirmware::WithBl(FwsecFirmwareWithBl::new(fwsec_sb, dev, chipset)?)
+ } else {
+ FwsecUnloadFirmware::WithoutBl(fwsec_sb)
+ })
+ },
+ )?;
+
+ KBox::new(
+ Sec2UnloadBundle {
+ fwsec_sb,
+ booter_unloader: BooterFirmware::new(
+ dev,
+ BooterKind::Unloader,
+ chipset,
+ FIRMWARE_VERSION,
+ sec2_falcon,
+ bar,
+ )?,
+ },
+ GFP_KERNEL,
+ )
+ .map(|b| crate::gsp::UnloadBundle(b))
+ .map_err(Into::into)
+ }
+}
+
impl GspHal for Tu102 {
fn boot(
&self,
@@ -281,11 +276,10 @@ fn boot(
//
// If the unload bundle creation fails, the GPU will need to be reset before the driver can
// be probed again.
- let unload_bundle =
- Sec2UnloadBundle::build(dev, bar, chipset, &bios, gsp_falcon, sec2_falcon)
- .inspect_err(|e| dev_warn!(dev, "Failed to prepare unload firmware: {:?}\n", e))
- .ok()
- .map(crate::gsp::UnloadBundle);
+ let unload_bundle = self
+ .build_unload_bundle(dev, bar, chipset, &bios, gsp_falcon, sec2_falcon)
+ .inspect_err(|e| dev_warn!(dev, "Failed to prepare unload firmware: {:?}\n", e))
+ .ok();

// Run the unload bundle to try and recover the GSP if an error occurs.
let unload_guard = ScopeGuard::new_with_data(unload_bundle, |unload_bundle| {

--
2.54.0