radv: Flush L2 before CP DMA copy/fill when CP DMA doesn't use L2

In case the source or destination were previously written
through L2, we need to writeback L2 to avoid the CP DMA accessing
stale data.

However, as the CP DMA doesn't write L2 either, an invalidation
is also needed to make sure other clients don't access stale data
when they read it through L2 after the CP DMA is complete.

Doing an invalidation before the CP DMA operation should take
care of both.

Additionally, radv_src_access_flush also invalidates L2 before
the copied data can be read.

Cc: mesa-stable
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/36820>
(cherry picked from commit c183eb5bc8)
This commit is contained in:
Timur Kristóf 2025-08-09 06:44:09 +02:00 committed by Eric Engestrom
parent bb2c8704b3
commit e93b3052b4
2 changed files with 11 additions and 7 deletions

View file

@ -5084,7 +5084,7 @@
"description": "radv: Flush L2 before CP DMA copy/fill when CP DMA doesn't use L2",
"nominated": true,
"nomination_type": 1,
"resolution": 0,
"resolution": 1,
"main_sha": null,
"because_sha": null,
"notes": null

View file

@ -232,6 +232,11 @@ radv_cp_dma_copy_memory(struct radv_cmd_buffer *cmd_buffer, uint64_t src_va, uin
uint64_t main_src_va, main_dest_va;
uint64_t skipped_size = 0, realign_size = 0;
if (!(pdev->info.cp_dma_use_L2 && pdev->info.gfx_level >= GFX9)) {
/* Invalidate L2 in case "src_va" or "dest_va" were previously written through L2. */
cmd_buffer->state.flush_bits |= RADV_CMD_FLAG_INV_L2;
}
/* Assume that we are not going to sync after the last DMA operation. */
cmd_buffer->state.dma_is_busy = true;
@ -296,9 +301,6 @@ radv_cp_dma_copy_memory(struct radv_cmd_buffer *cmd_buffer, uint64_t src_va, uin
}
if (realign_size)
radv_cp_dma_realign_engine(cmd_buffer, realign_size);
if (pdev->info.cp_sdma_ge_use_system_memory_scope)
cmd_buffer->state.flush_bits |= RADV_CMD_FLAG_INV_L2;
}
void
@ -310,6 +312,11 @@ radv_cp_dma_fill_memory(struct radv_cmd_buffer *cmd_buffer, uint64_t va, uint64_
if (!size)
return;
if (!(pdev->info.cp_dma_use_L2 && pdev->info.gfx_level >= GFX9)) {
/* Invalidate L2 in case "va" was previously written through L2. */
cmd_buffer->state.flush_bits |= RADV_CMD_FLAG_INV_L2;
}
assert(va % 4 == 0 && size % 4 == 0);
enum amd_gfx_level gfx_level = pdev->info.gfx_level;
@ -339,9 +346,6 @@ radv_cp_dma_fill_memory(struct radv_cmd_buffer *cmd_buffer, uint64_t va, uint64_
size -= byte_count;
va += byte_count;
}
if (pdev->info.cp_sdma_ge_use_system_memory_scope)
cmd_buffer->state.flush_bits |= RADV_CMD_FLAG_INV_L2;
}
void