[PATCH v3 07/13] gpu: nova-core: falcon: introduce and use with_fbif_transcfg
From: Alexandre Courbot
Date: Tue Nov 10 2026 - 05:39:05 EST
From: John Hubbard <jhubbard@xxxxxxxxxx>
The generic bootloader programs the FBIF aperture of its context DMA
slot and leaves it set after the bootloader has run. The r000
load-and-execute events will need to do the same with apertures that
GSP-RM chooses, and should not leave them behind.
Add a falcon method that programs an FBIF context DMA slot, runs a
closure, and restores the slot's previous value once the closure has
succeeded, and use it to run the generic bootloader. The slot used by
FWSEC is now restored after FWSEC has halted.
Signed-off-by: John Hubbard <jhubbard@xxxxxxxxxx>
[acourbot: extract from later patch of the r000 series, convert unneeded
call to `update` into a `write`, only check the validity of the DMA
context once.]
Co-developed-by: Alexandre Courbot <acourbot@xxxxxxxxxx>
Signed-off-by: Alexandre Courbot <acourbot@xxxxxxxxxx>
Reviewed-by: Eliot Courtney <ecourtney@xxxxxxxxxx>
---
drivers/gpu/nova-core/falcon.rs | 30 ++++++++++++++++++++++++
drivers/gpu/nova-core/firmware/gen_bootloader.rs | 30 ++++++++++--------------
2 files changed, 42 insertions(+), 18 deletions(-)
diff --git a/drivers/gpu/nova-core/falcon.rs b/drivers/gpu/nova-core/falcon.rs
index b17a997860ef..c888f29f34ce 100644
--- a/drivers/gpu/nova-core/falcon.rs
+++ b/drivers/gpu/nova-core/falcon.rs
@@ -513,6 +513,36 @@ pub(crate) fn pio_load<F: FalconFirmware<Target = E> + FalconPioLoadable>(
Ok(())
}
+ /// Programs FBIF context DMA slot `ctx_dma` with the value that `configure` returns, runs `f`,
+ /// and restores the slot once `f` has returned `Ok`.
+ ///
+ /// The slot keeps the programmed value if `f` fails, since a falcon that `f` started and that
+ /// has not halted may still be reading through the aperture.
+ ///
+ /// # Errors
+ ///
+ /// - `EINVAL` if `ctx_dma` is not a context DMA slot that the falcon has.
+ ///
+ /// Errors from `f` are propagated as-is.
+ pub(crate) fn with_fbif_transcfg<R>(
+ &self,
+ ctx_dma: u32,
+ configure: impl FnOnce(regs::NV_PFALCON_FBIF_TRANSCFG) -> regs::NV_PFALCON_FBIF_TRANSCFG,
+ f: impl FnOnce() -> Result<R>,
+ ) -> Result<R> {
+ let transcfg =
+ regs::NV_PFALCON_FBIF_TRANSCFG::try_at(usize::from_safe_cast(ctx_dma)).ok_or(EINVAL)?;
+
+ let saved = self.pfalcon.read(transcfg);
+ self.pfalcon.write(transcfg, configure(saved));
+
+ let result = f()?;
+
+ self.pfalcon.write(transcfg, saved);
+
+ Ok(result)
+ }
+
/// Perform a DMA write according to `load_offsets` from `dma_obj` into the falcon's
/// `target_mem`.
///
diff --git a/drivers/gpu/nova-core/firmware/gen_bootloader.rs b/drivers/gpu/nova-core/firmware/gen_bootloader.rs
index 54d9796b4897..751335c97e35 100644
--- a/drivers/gpu/nova-core/firmware/gen_bootloader.rs
+++ b/drivers/gpu/nova-core/firmware/gen_bootloader.rs
@@ -7,10 +7,6 @@
use kernel::{
device,
- io::{
- register::Array,
- Io, //
- },
num::{
Bounded,
TryIntoBounded, //
@@ -39,8 +35,7 @@
Tlv,
},
gpu::Chipset,
- num::FromSafeCast,
- regs, //
+ num::FromSafeCast, //
};
/// Structure used by the boot-loader to load the rest of the code.
@@ -221,23 +216,22 @@ pub(crate) fn run(
.try_into_bounded()
.ok_or(EINVAL)?;
- // Configure DMA index for the bootloader to fetch the FWSEC firmware from system memory.
- falcon.pfalcon.update(
- regs::NV_PFALCON_FBIF_TRANSCFG::try_at(usize::from_safe_cast(dmem_desc.ctx_dma))
- .ok_or(EINVAL)?,
+ falcon.with_fbif_transcfg(
+ dmem_desc.ctx_dma,
|v| {
v.with_target(target)
.with_mem_type(FalconFbifMemType::Physical)
},
- );
+ || {
+ falcon.pio_load(&GenericBootloaderLoad {
+ bootloader: self,
+ imem_dst_start,
+ dmem_desc,
+ })?;
- falcon.pio_load(&GenericBootloaderLoad {
- bootloader: self,
- imem_dst_start,
- dmem_desc,
- })?;
-
- falcon.boot(Some(mbox0), None)
+ falcon.boot(Some(mbox0), None)
+ },
+ )
}
}
--
2.56.0