[PATCH v3 09/13] gpu: nova-core: falcon: allow DMEM DMA transfers to request tagging
From: Alexandre Courbot
Date: Tue Nov 10 2026 - 05:28:04 EST
Add a tag flag to `FalconMem::Dmem` and set DMATRFCMD's DMTAG bit from
it.
Similarly to IMEM, when tagging is requested the DMA engine tags each
DMEM block it writes with the block's source offset, which the loaded
image then uses as its DMEM virtual address. The r000 load-and-execute
HS binary event will provide a DMEM virtual address for images that
need one.
No functional change intended.
Reviewed-by: Eliot Courtney <ecourtney@xxxxxxxxxx>
Signed-off-by: Alexandre Courbot <acourbot@xxxxxxxxxx>
---
drivers/gpu/nova-core/falcon.rs | 23 +++++++++++++++--------
drivers/gpu/nova-core/regs.rs | 6 ++++--
2 files changed, 19 insertions(+), 10 deletions(-)
diff --git a/drivers/gpu/nova-core/falcon.rs b/drivers/gpu/nova-core/falcon.rs
index 299f17b1218a..04da14d48895 100644
--- a/drivers/gpu/nova-core/falcon.rs
+++ b/drivers/gpu/nova-core/falcon.rs
@@ -135,8 +135,9 @@ pub(crate) enum FalconMem {
/// Non-Secure Instruction Memory.
#[expect(unused)]
ImemNonSecure,
- /// Data Memory.
- Dmem,
+ /// Data Memory. If `tag` is set, a transfer into DMEM also tags each block with its source
+ /// offset, which is then the DMEM virtual address of the image.
+ Dmem { tag: bool },
}
bounded_enum! {
@@ -559,13 +560,15 @@ fn dma_wr(
// need to perform.
let num_transfers = load_offsets.len.div_ceil(DMA_LEN);
- // For IMEM, we want to use the start offset as a virtual address tag for each page, since
- // code addresses in the firmware (and the boot vector) are virtual.
+ // For IMEM and tagged DMEM, we want to use the start offset as a virtual address tag for
+ // each page, since addresses in the firmware (and the boot vector) are virtual.
//
- // For DMEM, the start offset is folded into the DMA base.
+ // For untagged DMEM, the start offset is folded into the DMA base.
let (fb_offset, base_offset) = match target_mem {
- FalconMem::ImemSecure | FalconMem::ImemNonSecure => (load_offsets.src_start, 0),
- FalconMem::Dmem => (0, usize::from_safe_cast(load_offsets.src_start)),
+ FalconMem::ImemSecure | FalconMem::ImemNonSecure | FalconMem::Dmem { tag: true } => {
+ (load_offsets.src_start, 0)
+ }
+ FalconMem::Dmem { tag: false } => (0, usize::from_safe_cast(load_offsets.src_start)),
};
let dma_base = {
@@ -659,7 +662,11 @@ fn dma_load<F: FalconFirmware<Target = E> + FalconDmaLoadable>(&self, fw: &F) ->
});
self.dma_wr(&dma_obj, FalconMem::ImemSecure, fw.imem_sec_load_params())?;
- self.dma_wr(&dma_obj, FalconMem::Dmem, fw.dmem_load_params())?;
+ self.dma_wr(
+ &dma_obj,
+ FalconMem::Dmem { tag: false },
+ fw.dmem_load_params(),
+ )?;
self.hal.program_brom(self, &fw.brom_params());
diff --git a/drivers/gpu/nova-core/regs.rs b/drivers/gpu/nova-core/regs.rs
index af0bbb92e992..7e997478ab42 100644
--- a/drivers/gpu/nova-core/regs.rs
+++ b/drivers/gpu/nova-core/regs.rs
@@ -321,9 +321,11 @@ pub(crate) fn mem_scrubbing_done(self) -> bool {
}
impl NV_PFALCON_FALCON_DMATRFCMD {
- /// Programs the `imem` and `sec` fields for the given FalconMem
+ /// Programs the `imem`, `sec` and `set_dmtag` fields for the given FalconMem
pub(crate) fn with_falcon_mem(self, mem: FalconMem) -> Self {
- let this = self.with_imem(mem != FalconMem::Dmem);
+ let this = self
+ .with_imem(!matches!(mem, FalconMem::Dmem { .. }))
+ .with_set_dmtag(matches!(mem, FalconMem::Dmem { tag: true }));
match mem {
FalconMem::ImemSecure => this.with_const_sec::<1>(),
--
2.56.0