[PATCH v3 11/13] gpu: nova-core: falcon: use src_start as FB offset for all DMA transfers
From: Alexandre Courbot
Date: Tue Nov 10 2026 - 05:31:01 EST
dma_wr() splits the source offset of a transfer between DMATRFBASE and
DMATRFFBOFFS differently depending on the target memory. This separation
adds branching to the code, and is not strictly needed as DMATRFFBOFFS
supports 32-bit offsets.
Remove that distinction by programming the start of the source into
DMATRFBASE and `src_start` into DMATRFFBOFFS for all transfers, which
also removes the `fb_offset` and `base_offset` local variables.
This changes the register values programmed for untagged DMEM
transfers, but not the addresses they read from. No change of behavior
has been observed on either r570 or r615.
Suggested-by: Eliot Courtney <ecourtney@xxxxxxxxxx>
Link: https://lore.kernel.org/all/DMQI0G2K6Z3B.1YEH6D2ZILRBI@xxxxxxxxxx/
Signed-off-by: Alexandre Courbot <acourbot@xxxxxxxxxx>
---
drivers/gpu/nova-core/falcon.rs | 21 +++++----------------
1 file changed, 5 insertions(+), 16 deletions(-)
diff --git a/drivers/gpu/nova-core/falcon.rs b/drivers/gpu/nova-core/falcon.rs
index facf65a17c0f..a7e41e282ec2 100644
--- a/drivers/gpu/nova-core/falcon.rs
+++ b/drivers/gpu/nova-core/falcon.rs
@@ -566,17 +566,6 @@ fn dma_wr(
// need to perform.
let num_transfers = load_offsets.len.div_ceil(DMA_LEN);
- // 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 untagged DMEM, the start offset is folded into the DMA base.
- let (fb_offset, base_offset) = match target_mem {
- 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 = match src {
FalconDmaSource::Sysmem(dma_obj) => {
// Upper limit of transfer is `(num_transfers * DMA_LEN) + load_offsets.src_start`.
@@ -586,11 +575,9 @@ fn dma_wr(
.map(usize::from_safe_cast)
.ok_or(EOVERFLOW)?;
- io_project!(dma_obj, [try: base_offset..end_offset]).dma_address()
+ io_project!(dma_obj, [try: 0..end_offset]).dma_address()
}
- FalconDmaSource::Framebuffer { base } => base
- .checked_add(u64::from_safe_cast(base_offset))
- .ok_or(EOVERFLOW)?,
+ FalconDmaSource::Framebuffer { base } => base,
};
if dma_base % DmaAddress::from(DMA_LEN) > 0 {
@@ -624,8 +611,10 @@ fn dma_wr(
regs::NV_PFALCON_FALCON_DMATRFMOFFS::zeroed()
.try_with_offs(load_offsets.dst_start + pos)?,
);
+ // The source offset doubles as the virtual address tag for IMEM and tagged DMEM.
self.pfalcon.write_reg(
- regs::NV_PFALCON_FALCON_DMATRFFBOFFS::zeroed().with_offs(fb_offset + pos),
+ regs::NV_PFALCON_FALCON_DMATRFFBOFFS::zeroed()
+ .with_offs(load_offsets.src_start + pos),
);
self.pfalcon.write_reg(cmd);
--
2.56.0