Re: [PATCH 5/9] drm/amdgpu/gfx7: Fixup emitting SWITCH_BUFFER packets
Tvrtko Ursulin <[email protected]>
| Newsgroups | org.freedesktop.lists.amd-gfx |
|---|---|
| Message-ID | <[email protected]> |
On 13/07/2026 13:58, Timur Kristóf wrote:
> Implement the emit_switch_buffer() function instead of emitting
> them duing emit_ib, emit_pipeline_sync and emit_vm_flush.
during
>
> Note that it isn't necessary to emit these in both
> emit_pipeline_sync() and emit_vm_flush() because
> amdgpu_vm_flush() already calls these when calling
> either of those functions.
The amdgpu_vm_flush indeed does emit two switch buffers:
/* the double SWITCH_BUFFER here *cannot* be skipped by COND_EXEC */
if (ring->funcs->emit_switch_buffer) {
amdgpu_ring_emit_switch_buffer(ring);
amdgpu_ring_emit_switch_buffer(ring);
}
Comments are different though:
/* sync CE with ME to prevent CE fetch CEIB before context switch done */
Are you confident the two emissions are about the same thing?
>
> Signed-off-by: Timur Kristóf <[email protected]>
> ---
> drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c | 32 +++++++++------------------
> 1 file changed, 10 insertions(+), 22 deletions(-)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c
> index 0ceadb107d26..a93cc02c3400 100644
> --- a/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c
> +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c
> @@ -2201,12 +2201,6 @@ static void gfx_v7_0_ring_emit_ib_gfx(struct amdgpu_ring *ring,
> unsigned vmid = AMDGPU_JOB_GET_VMID(job);
> u32 header, control = 0;
>
> - /* insert SWITCH_BUFFER packet before first IB in the ring frame */
> - if (flags & AMDGPU_HAVE_CTX_SWITCH) {
> - amdgpu_ring_write(ring, PACKET3(PACKET3_SWITCH_BUFFER, 0));
> - amdgpu_ring_write(ring, 0);
> - }
Commit message does not explain why the change of ring buffer command
this creates is okay. Current flow is:
amdgpu_ib_schedule()
{
...
amdgpu_ring_emit_ib
amdgpu_ring_write(ring, PACKET3(PACKET3_SWITCH_BUFFER, 0));
New flow is:
...
amdgpu_ring_emit_ib
... other ring commands ...
amdgpu_ring_emit_switch_buffer
amdgpu_ring_write(ring, PACKET3(PACKET3_SWITCH_BUFFER, 0));
Is this okay? Specifically due the above comment saying "insert
SWITCH_BUFFER packet before first IB in the ring frame" - is the "first"
part not important?
Also, amdgpu_ib_schedule only emits amdgpu_ring_emit_switch_buffer if
there is a job. Currently it is always emitted.
Final interesting part is how amdgpu_ib_schedule clears
AMDGPU_HAVE_CTX_SWITCH after having called amdgpu_ring_emit_ib.
After this change only gfx6 remains the user of that flag in
gfx_v6_0_ring_emit_ib. Everyone else only use it in emit_cntxcntl. If
gfx6 was adjusted too (later), amdgpu_ib_schedule could reduce the scope
of that flag to just the scope where it calls amdgpu_ring_emit_frame_cntl.
Regards,
Tvrtko
> -
> if (ib->flags & AMDGPU_IB_FLAG_CE)
> header = PACKET3(PACKET3_INDIRECT_BUFFER_CONST, 2);
> else
> @@ -2258,6 +2252,12 @@ static void gfx_v7_0_ring_emit_ib_compute(struct amdgpu_ring *ring,
> amdgpu_ring_write(ring, control);
> }
>
> +static void gfx_v7_0_ring_emit_sb(struct amdgpu_ring *ring)
> +{
> + amdgpu_ring_write(ring, PACKET3(PACKET3_SWITCH_BUFFER, 0));
> + amdgpu_ring_write(ring, 0);
> +}
> +
> static void gfx_v7_ring_emit_cntxcntl(struct amdgpu_ring *ring, uint32_t flags)
> {
> uint32_t dw2 = 0;
> @@ -3111,14 +3111,6 @@ static void gfx_v7_0_ring_emit_pipeline_sync(struct amdgpu_ring *ring)
> amdgpu_ring_write(ring, seq);
> amdgpu_ring_write(ring, 0xffffffff);
> amdgpu_ring_write(ring, 4); /* poll interval */
> -
> - if (usepfp) {
> - /* sync CE with ME to prevent CE fetch CEIB before context switch done */
> - amdgpu_ring_write(ring, PACKET3(PACKET3_SWITCH_BUFFER, 0));
> - amdgpu_ring_write(ring, 0);
> - amdgpu_ring_write(ring, PACKET3(PACKET3_SWITCH_BUFFER, 0));
> - amdgpu_ring_write(ring, 0);
> - }
> }
>
> /*
> @@ -3160,12 +3152,6 @@ static void gfx_v7_0_ring_emit_vm_flush(struct amdgpu_ring *ring,
> /* sync PFP to ME, otherwise we might get invalid PFP reads */
> amdgpu_ring_write(ring, PACKET3(PACKET3_PFP_SYNC_ME, 0));
> amdgpu_ring_write(ring, 0x0);
> -
> - /* synce CE with ME to prevent CE fetch CEIB before context switch done */
> - amdgpu_ring_write(ring, PACKET3(PACKET3_SWITCH_BUFFER, 0));
> - amdgpu_ring_write(ring, 0);
> - amdgpu_ring_write(ring, PACKET3(PACKET3_SWITCH_BUFFER, 0));
> - amdgpu_ring_write(ring, 0);
> }
> }
>
> @@ -4954,8 +4940,9 @@ static const struct amdgpu_ring_funcs gfx_v7_0_ring_funcs_gfx = {
> 7 + /* gfx_v7_0_ring_emit_hdp_flush */
> 5 + /* hdp invalidate */
> 12 + 12 + 12 + /* gfx_v7_0_ring_emit_fence_gfx x3 for user fence, vm fence */
> - 7 + 4 + /* gfx_v7_0_ring_emit_pipeline_sync */
> - CIK_FLUSH_GPU_TLB_NUM_WREG * 5 + 7 + 6 + /* gfx_v7_0_ring_emit_vm_flush */
> + 7 + /* gfx_v7_0_ring_emit_pipeline_sync */
> + CIK_FLUSH_GPU_TLB_NUM_WREG * 5 + 7 + 2 + /* gfx_v7_0_ring_emit_vm_flush */
> + 3 * 2 + /* gfx_v7_0_ring_emit_sb x3 (from amdgpu_vm_flush, amdgpu_ib_schedule) */
> 3 + 4 + /* gfx_v7_ring_emit_cntxcntl including vgt flush*/
> 5, /* SURFACE_SYNC */
> .emit_ib_size = 4, /* gfx_v7_0_ring_emit_ib_gfx */
> @@ -4969,6 +4956,7 @@ static const struct amdgpu_ring_funcs gfx_v7_0_ring_funcs_gfx = {
> .test_ib = gfx_v7_0_ring_test_ib,
> .insert_nop = amdgpu_ring_insert_nop,
> .pad_ib = amdgpu_ring_generic_pad_ib,
> + .emit_switch_buffer = gfx_v7_0_ring_emit_sb,
> .emit_cntxcntl = gfx_v7_ring_emit_cntxcntl,
> .emit_wreg = gfx_v7_0_ring_emit_wreg,
> .soft_recovery = gfx_v7_0_ring_soft_recovery,