All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/10] drm/amdgpu/gfx6: Use GFX IP block soft reset on GFX6 (v2)
@ 2026-08-03 13:22 Timur Kristóf
  2026-08-03 13:23 ` [PATCH 01/10] drm/amdgpu/gfx6: Fixup emit_cntxcntl() Timur Kristóf
                   ` (9 more replies)
  0 siblings, 10 replies; 12+ messages in thread
From: Timur Kristóf @ 2026-08-03 13:22 UTC (permalink / raw)
  To: amd-gfx, Alex Deucher, Christian König, Tvrtko Ursulin,
	Natalie Vock
  Cc: Timur Kristóf

Fix up various things in the GFX6 code to prepare it
to work with IP block soft reset. The main challenge
was figuring out how to properly initialize the
compute queues so that they work well after a reset,
as well as realizing that on GFX6 the compute queues
also have a PFP (as opposed to GFX7+ where PFP is
a graphics only thing). There are also other minor
fixes.

Implement GFX6 IP block soft reset: just reset everything
in the GFX IP block (instead of taking a guess at which
parts need to be reset) to make it consistent, and
also handle clock and power gating to make sure not to
degrade GPU functionality after a GFX IP block soft reset.

This improves current user experience on all GFX6 chips:

On GFX6 dGPUs, the current GPU recovery method
always clears the contents of VRAM, which means that
a buggy (hanging) app can crash the whole graphical
session, which is less than ideal.

Using GFX IP block soft reset means that we can now
move on from GFX hangs on dGPUs without crashing the
whole system.

Tested on the following chips:

Tahiti (FirePro W9000, Radeon HD 7870 XT)
Cape Verde (Radeon R7 450)
Pitcairn (Radeon R9 270X)
Oland (Radeon 430)

Changes from v1 to v2:

* Add more explanation to various patches
* Drop patch that enables some IRQs
* Drop VM flush changes (will be submitted separately)

Timur Kristóf (10):
  drm/amdgpu/gfx6: Fixup emit_cntxcntl()
  drm/amdgpu/gfx6: Fixup emitting SWITCH_BUFFER packets
  drm/amdgpu/gfx6: Use PFP on the compute queues too
  drm/amdgpu/gfx6: Initialize compute rings before CP start
  drm/amdgpu/gfx6: Clean up rings during reset
  drm/amdgpu/gfx6: Execute CLEAR_STATE when initializing compute rings
  drm/amdgpu/gfx6: Adjust how harvested TCCs are set up
  drm/amdgpu/gfx6: Use COND_EXEC
  drm/amdgpu/gfx6: Add IP block soft reset implementation
  drm/amdgpu/gfx6: Enable IP block soft reset as a GPU recovery method

 drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c         | 374 +++++++++++++-----
 .../include/asic_reg/gca/gfx_6_0_sh_mask.h    |  32 +-
 2 files changed, 295 insertions(+), 111 deletions(-)

-- 
2.55.0


^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH 01/10] drm/amdgpu/gfx6: Fixup emit_cntxcntl()
  2026-08-03 13:22 [PATCH 00/10] drm/amdgpu/gfx6: Use GFX IP block soft reset on GFX6 (v2) Timur Kristóf
@ 2026-08-03 13:23 ` Timur Kristóf
  2026-08-04 15:11   ` Alex Deucher
  2026-08-03 13:23 ` [PATCH 02/10] drm/amdgpu/gfx6: Fixup emitting SWITCH_BUFFER packets Timur Kristóf
                   ` (8 subsequent siblings)
  9 siblings, 1 reply; 12+ messages in thread
From: Timur Kristóf @ 2026-08-03 13:23 UTC (permalink / raw)
  To: amd-gfx, Alex Deucher, Christian König, Tvrtko Ursulin,
	Natalie Vock
  Cc: Timur Kristóf

Set bits on dword 2 like GFX7-8 except load_global_uconfig
which doesn't exist on GFX6.

Emit VS_PARTIAL_FLUSH before VGT_FLUSH like GFX7-8.

For reference see old PAL which explains the bit fields in
this register and that load_global_uconfig doesn't exist on GFX6
and also see gfx_v7_ring_emit_cntxcntl() for the GFX7 code
which this commit follows.

Fixes: 2cd46ad22383 ("drm/amdgpu: add graphic pipeline implementation for si v8")
Signed-off-by: Timur Kristóf <timur.kristof@gmail.com>
---
 drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c | 28 ++++++++++++++++++++-------
 1 file changed, 21 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c
index cd2a14ecdba8..0cbaae73a0bf 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c
@@ -1882,11 +1882,13 @@ static int gfx_v6_0_ring_test_ring(struct amdgpu_ring *ring)
 	return r;
 }
 
-static void gfx_v6_0_ring_emit_vgt_flush(struct amdgpu_ring *ring)
+static void gfx_v6_0_ring_emit_event_write(struct amdgpu_ring *ring,
+					   uint32_t event_type,
+					   uint32_t event_index)
 {
 	amdgpu_ring_write(ring, PACKET3(PACKET3_EVENT_WRITE, 0));
-	amdgpu_ring_write(ring, EVENT_TYPE(VGT_FLUSH) |
-		EVENT_INDEX(0));
+	amdgpu_ring_write(ring, EVENT_TYPE(event_type) |
+				EVENT_INDEX(event_index));
 }
 
 static void gfx_v6_0_ring_emit_fence(struct amdgpu_ring *ring, u64 addr,
@@ -2997,10 +2999,22 @@ static uint64_t gfx_v6_0_get_gpu_clock_counter(struct amdgpu_device *adev)
 
 static void gfx_v6_ring_emit_cntxcntl(struct amdgpu_ring *ring, uint32_t flags)
 {
-	if (flags & AMDGPU_HAVE_CTX_SWITCH)
-		gfx_v6_0_ring_emit_vgt_flush(ring);
+	u32 dw2 = 0x80000000; /* set load_enable otherwise this package is just NOPs */
+
+	if (flags & AMDGPU_HAVE_CTX_SWITCH) {
+		gfx_v6_0_ring_emit_event_write(ring, VS_PARTIAL_FLUSH, 4);
+		gfx_v6_0_ring_emit_event_write(ring, VGT_FLUSH, 0);
+
+		/* set load_global_config (load_global_uconfig doesn't exist on GFX6) */
+		dw2 |= 0x1;
+		/* set load_cs_sh_regs */
+		dw2 |= 0x01000000;
+		/* set load_per_context_state & load_gfx_sh_regs */
+		dw2 |= 0x10002;
+	}
+
 	amdgpu_ring_write(ring, PACKET3(PACKET3_CONTEXT_CONTROL, 1));
-	amdgpu_ring_write(ring, 0x80000000);
+	amdgpu_ring_write(ring, dw2);
 	amdgpu_ring_write(ring, 0);
 }
 
@@ -3527,7 +3541,7 @@ static const struct amdgpu_ring_funcs gfx_v6_0_ring_funcs_gfx = {
 		14 + 14 + 14 + /* gfx_v6_0_ring_emit_fence x3 for user fence, vm fence */
 		7 + 4 + /* gfx_v6_0_ring_emit_pipeline_sync */
 		SI_FLUSH_GPU_TLB_NUM_WREG * 5 + 7 + 6 + /* gfx_v6_0_ring_emit_vm_flush */
-		3 + 2 + /* gfx_v6_ring_emit_cntxcntl including vgt flush */
+		3 + 2 + 2 + /* gfx_v6_ring_emit_cntxcntl including VGT flush */
 		5, /* SURFACE_SYNC */
 	.emit_ib_size = 6, /* gfx_v6_0_ring_emit_ib */
 	.emit_ib = gfx_v6_0_ring_emit_ib,
-- 
2.55.0


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 02/10] drm/amdgpu/gfx6: Fixup emitting SWITCH_BUFFER packets
  2026-08-03 13:22 [PATCH 00/10] drm/amdgpu/gfx6: Use GFX IP block soft reset on GFX6 (v2) Timur Kristóf
  2026-08-03 13:23 ` [PATCH 01/10] drm/amdgpu/gfx6: Fixup emit_cntxcntl() Timur Kristóf
@ 2026-08-03 13:23 ` Timur Kristóf
  2026-08-03 13:23 ` [PATCH 03/10] drm/amdgpu/gfx6: Use PFP on the compute queues too Timur Kristóf
                   ` (7 subsequent siblings)
  9 siblings, 0 replies; 12+ messages in thread
From: Timur Kristóf @ 2026-08-03 13:23 UTC (permalink / raw)
  To: amd-gfx, Alex Deucher, Christian König, Tvrtko Ursulin,
	Natalie Vock
  Cc: Timur Kristóf

Implement the emit_switch_buffer() function instead of emitting
them duing emit_ib, emit_pipeline_sync and emit_vm_flush.

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.

Fixes: 2cd46ad22383 ("drm/amdgpu: add graphic pipeline implementation for si v8")
Signed-off-by: Timur Kristóf <timur.kristof@gmail.com>
---
 drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c | 38 ++++++++++-----------------
 1 file changed, 14 insertions(+), 24 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c
index 0cbaae73a0bf..b84d05e7f09e 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c
@@ -1927,12 +1927,6 @@ static void gfx_v6_0_ring_emit_ib(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);
-	}
-
 	if (ib->flags & AMDGPU_IB_FLAG_CE)
 		header = PACKET3(PACKET3_INDIRECT_BUFFER_CONST, 2);
 	else
@@ -2365,14 +2359,6 @@ static void gfx_v6_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) {
-		/* 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);
-	}
 }
 
 static void gfx_v6_0_ring_emit_vm_flush(struct amdgpu_ring *ring,
@@ -2396,12 +2382,6 @@ static void gfx_v6_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);
 	}
 }
 
@@ -2997,6 +2977,12 @@ static uint64_t gfx_v6_0_get_gpu_clock_counter(struct amdgpu_device *adev)
 	return clock;
 }
 
+static void gfx_v6_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_v6_ring_emit_cntxcntl(struct amdgpu_ring *ring, uint32_t flags)
 {
 	u32 dw2 = 0x80000000; /* set load_enable otherwise this package is just NOPs */
@@ -3539,11 +3525,12 @@ static const struct amdgpu_ring_funcs gfx_v6_0_ring_funcs_gfx = {
 	.emit_frame_size =
 		5 + 5 + /* hdp flush / invalidate */
 		14 + 14 + 14 + /* gfx_v6_0_ring_emit_fence x3 for user fence, vm fence */
-		7 + 4 + /* gfx_v6_0_ring_emit_pipeline_sync */
-		SI_FLUSH_GPU_TLB_NUM_WREG * 5 + 7 + 6 + /* gfx_v6_0_ring_emit_vm_flush */
+		7 + /* gfx_v6_0_ring_emit_pipeline_sync */
+		SI_FLUSH_GPU_TLB_NUM_WREG * 5 + 7 + 2 + /* gfx_v6_0_ring_emit_vm_flush */
+		3 * 2 + /* gfx_v6_0_ring_emit_sb x3 (from amdgpu_vm_flush, amdgpu_ib_schedule) */
 		3 + 2 + 2 + /* gfx_v6_ring_emit_cntxcntl including VGT flush */
 		5, /* SURFACE_SYNC */
-	.emit_ib_size = 6, /* gfx_v6_0_ring_emit_ib */
+	.emit_ib_size = 4, /* gfx_v6_0_ring_emit_ib */
 	.emit_ib = gfx_v6_0_ring_emit_ib,
 	.emit_fence = gfx_v6_0_ring_emit_fence,
 	.emit_pipeline_sync = gfx_v6_0_ring_emit_pipeline_sync,
@@ -3551,6 +3538,7 @@ static const struct amdgpu_ring_funcs gfx_v6_0_ring_funcs_gfx = {
 	.test_ring = gfx_v6_0_ring_test_ring,
 	.test_ib = gfx_v6_0_ring_test_ib,
 	.insert_nop = amdgpu_ring_insert_nop,
+	.emit_switch_buffer = gfx_v6_0_ring_emit_sb,
 	.emit_cntxcntl = gfx_v6_ring_emit_cntxcntl,
 	.emit_wreg = gfx_v6_0_ring_emit_wreg,
 	.emit_mem_sync = gfx_v6_0_emit_mem_sync,
@@ -3568,8 +3556,9 @@ static const struct amdgpu_ring_funcs gfx_v6_0_ring_funcs_compute = {
 		7 + /* gfx_v6_0_ring_emit_pipeline_sync */
 		SI_FLUSH_GPU_TLB_NUM_WREG * 5 + 7 + /* gfx_v6_0_ring_emit_vm_flush */
 		14 + 14 + 14 + /* gfx_v6_0_ring_emit_fence x3 for user fence, vm fence */
+		3 * 2 + /* gfx_v6_0_ring_emit_sb x3 (from amdgpu_vm_flush, amdgpu_ib_schedule) */
 		5, /* SURFACE_SYNC */
-	.emit_ib_size = 6, /* gfx_v6_0_ring_emit_ib */
+	.emit_ib_size = 4, /* gfx_v6_0_ring_emit_ib */
 	.emit_ib = gfx_v6_0_ring_emit_ib,
 	.emit_fence = gfx_v6_0_ring_emit_fence,
 	.emit_pipeline_sync = gfx_v6_0_ring_emit_pipeline_sync,
@@ -3577,6 +3566,7 @@ static const struct amdgpu_ring_funcs gfx_v6_0_ring_funcs_compute = {
 	.test_ring = gfx_v6_0_ring_test_ring,
 	.test_ib = gfx_v6_0_ring_test_ib,
 	.insert_nop = amdgpu_ring_insert_nop,
+	.emit_switch_buffer = gfx_v6_0_ring_emit_sb,
 	.emit_wreg = gfx_v6_0_ring_emit_wreg,
 	.emit_mem_sync = gfx_v6_0_emit_mem_sync,
 };
-- 
2.55.0


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 03/10] drm/amdgpu/gfx6: Use PFP on the compute queues too
  2026-08-03 13:22 [PATCH 00/10] drm/amdgpu/gfx6: Use GFX IP block soft reset on GFX6 (v2) Timur Kristóf
  2026-08-03 13:23 ` [PATCH 01/10] drm/amdgpu/gfx6: Fixup emit_cntxcntl() Timur Kristóf
  2026-08-03 13:23 ` [PATCH 02/10] drm/amdgpu/gfx6: Fixup emitting SWITCH_BUFFER packets Timur Kristóf
@ 2026-08-03 13:23 ` Timur Kristóf
  2026-08-03 13:23 ` [PATCH 04/10] drm/amdgpu/gfx6: Initialize compute rings before CP start Timur Kristóf
                   ` (6 subsequent siblings)
  9 siblings, 0 replies; 12+ messages in thread
From: Timur Kristóf @ 2026-08-03 13:23 UTC (permalink / raw)
  To: amd-gfx, Alex Deucher, Christian König, Tvrtko Ursulin,
	Natalie Vock
  Cc: Timur Kristóf

On GFX6, the compute rings use the same CP path as
the graphics ring. The only difference is that they
don't support draw commands. (As opposed to GFX7 and
newer which have a separate command parser that is
called MEC for compute queues.)

This means that we have to take into consideration
that the PFP also exists on compute queues on GFX6:

Use PFP for register writes on both graphics and
compute queues.

In the pipeline sync, use the PFP to wait for the
previous fence (and not the ME) to prevent the PFP
from starting to execute the next submission while
the ME is still in the previous submission.

After a VM flush, emit PFP_SYNC_ME on compute
queues as well.

Fixes: 2cd46ad22383 ("drm/amdgpu: add graphic pipeline implementation for si v8")
Signed-off-by: Timur Kristóf <timur.kristof@gmail.com>
---
 drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c
index b84d05e7f09e..9b18ddcd597b 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c
@@ -2346,7 +2346,7 @@ static int gfx_v6_0_cp_resume(struct amdgpu_device *adev)
 
 static void gfx_v6_0_ring_emit_pipeline_sync(struct amdgpu_ring *ring)
 {
-	int usepfp = (ring->funcs->type == AMDGPU_RING_TYPE_GFX);
+	int usepfp = 1;
 	uint32_t seq = ring->fence_drv.sync_seq;
 	uint64_t addr = ring->fence_drv.gpu_addr;
 
@@ -2364,7 +2364,7 @@ static void gfx_v6_0_ring_emit_pipeline_sync(struct amdgpu_ring *ring)
 static void gfx_v6_0_ring_emit_vm_flush(struct amdgpu_ring *ring,
 					unsigned vmid, uint64_t pd_addr)
 {
-	int usepfp = (ring->funcs->type == AMDGPU_RING_TYPE_GFX);
+	int usepfp = 1;
 
 	amdgpu_gmc_emit_flush_gpu_tlb(ring, vmid, pd_addr);
 
@@ -2388,7 +2388,7 @@ static void gfx_v6_0_ring_emit_vm_flush(struct amdgpu_ring *ring,
 static void gfx_v6_0_ring_emit_wreg(struct amdgpu_ring *ring,
 				    uint32_t reg, uint32_t val)
 {
-	int usepfp = (ring->funcs->type == AMDGPU_RING_TYPE_GFX);
+	int usepfp = 1;
 
 	amdgpu_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3));
 	amdgpu_ring_write(ring, (WRITE_DATA_ENGINE_SEL(usepfp) |
@@ -3554,7 +3554,7 @@ static const struct amdgpu_ring_funcs gfx_v6_0_ring_funcs_compute = {
 	.emit_frame_size =
 		5 + 5 + /* hdp flush / invalidate */
 		7 + /* gfx_v6_0_ring_emit_pipeline_sync */
-		SI_FLUSH_GPU_TLB_NUM_WREG * 5 + 7 + /* gfx_v6_0_ring_emit_vm_flush */
+		SI_FLUSH_GPU_TLB_NUM_WREG * 5 + 7 + 2 + /* gfx_v6_0_ring_emit_vm_flush */
 		14 + 14 + 14 + /* gfx_v6_0_ring_emit_fence x3 for user fence, vm fence */
 		3 * 2 + /* gfx_v6_0_ring_emit_sb x3 (from amdgpu_vm_flush, amdgpu_ib_schedule) */
 		5, /* SURFACE_SYNC */
-- 
2.55.0


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 04/10] drm/amdgpu/gfx6: Initialize compute rings before CP start
  2026-08-03 13:22 [PATCH 00/10] drm/amdgpu/gfx6: Use GFX IP block soft reset on GFX6 (v2) Timur Kristóf
                   ` (2 preceding siblings ...)
  2026-08-03 13:23 ` [PATCH 03/10] drm/amdgpu/gfx6: Use PFP on the compute queues too Timur Kristóf
@ 2026-08-03 13:23 ` Timur Kristóf
  2026-08-03 13:23 ` [PATCH 05/10] drm/amdgpu/gfx6: Clean up rings during reset Timur Kristóf
                   ` (5 subsequent siblings)
  9 siblings, 0 replies; 12+ messages in thread
From: Timur Kristóf @ 2026-08-03 13:23 UTC (permalink / raw)
  To: amd-gfx, Alex Deucher, Christian König, Tvrtko Ursulin,
	Natalie Vock
  Cc: Timur Kristóf

In GFX6 GPUs, compute takes the same CP path as graphics.
CP ME command parser executes packets for each ring buffer:
RB0 supports graphics, RB1 and RB2 are compute only.
Initialize all three rings before calling gfx_v6_0_cp_gfx_start()
to make sure they are all in a sane state before execution starts.

Previously, the two compute-only rings were initialized after
the ME had been already started, which could cause the ME to
start executing the ring contents before the rings could be
properly initialized. This happens to work when the HW is first
initialized, but not during an IP block reset where we want
to reinitialize the compute rings before starting the ME
to prevent it from executing garbage from these rings.

Signed-off-by: Timur Kristóf <timur.kristof@gmail.com>
---
 drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c | 134 ++++++++++++++------------
 1 file changed, 70 insertions(+), 64 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c
index 9b18ddcd597b..cd8a34d87c6d 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c
@@ -2129,12 +2129,24 @@ static int gfx_v6_0_cp_gfx_start(struct amdgpu_device *adev)
 	return 0;
 }
 
+/**
+ * gfx_v6_0_cp_gfx_resume() - Initialize CP rings
+ *
+ * @adev: amdgpu_device pointer
+ *
+ * In GFX6 GPUs, compute takes the same CP path as graphics.
+ * CP ME command parser executes packets for each ring buffer:
+ * RB0 supports graphics, RB1 and RB2 are compute only.
+ * Initialize all three rings before calling gfx_v6_0_cp_gfx_start()
+ * to make sure they are all in a sane state before execution starts.
+ */
 static int gfx_v6_0_cp_gfx_resume(struct amdgpu_device *adev)
 {
 	struct amdgpu_ring *ring;
 	u32 tmp;
 	u32 rb_bufsz;
 	int r;
+	int i;
 	u64 rptr_addr;
 
 	WREG32(mmCP_SEM_WAIT_TIMER, 0x0);
@@ -2174,12 +2186,69 @@ static int gfx_v6_0_cp_gfx_resume(struct amdgpu_device *adev)
 
 	WREG32(mmCP_RB0_BASE, ring->gpu_addr >> 8);
 
+	/* ring 1  - compute only */
+	if (adev->gfx.num_compute_rings >= 1) {
+		ring = &adev->gfx.compute_ring[0];
+
+		rb_bufsz = order_base_2(ring->ring_size / 8);
+		tmp = (order_base_2(AMDGPU_GPU_PAGE_SIZE / 8) << 8) | rb_bufsz;
+#ifdef __BIG_ENDIAN
+		tmp |= BUF_SWAP_32BIT;
+#endif
+		WREG32(mmCP_RB1_CNTL, tmp);
+
+		WREG32(mmCP_RB1_CNTL, tmp | CP_RB1_CNTL__RB_RPTR_WR_ENA_MASK);
+		ring->wptr = 0;
+		WREG32(mmCP_RB1_WPTR, ring->wptr);
+
+		rptr_addr = ring->rptr_gpu_addr;
+		WREG32(mmCP_RB1_RPTR_ADDR, lower_32_bits(rptr_addr));
+		WREG32(mmCP_RB1_RPTR_ADDR_HI, upper_32_bits(rptr_addr) & 0xFF);
+
+		mdelay(1);
+		WREG32(mmCP_RB1_CNTL, tmp);
+		WREG32(mmCP_RB1_BASE, ring->gpu_addr >> 8);
+	}
+
+	/* ring 2 - compute only */
+	if (adev->gfx.num_compute_rings >= 2) {
+		ring = &adev->gfx.compute_ring[1];
+
+		rb_bufsz = order_base_2(ring->ring_size / 8);
+		tmp = (order_base_2(AMDGPU_GPU_PAGE_SIZE / 8) << 8) | rb_bufsz;
+#ifdef __BIG_ENDIAN
+		tmp |= BUF_SWAP_32BIT;
+#endif
+		WREG32(mmCP_RB2_CNTL, tmp);
+
+		WREG32(mmCP_RB2_CNTL, tmp | CP_RB2_CNTL__RB_RPTR_WR_ENA_MASK);
+		ring->wptr = 0;
+		WREG32(mmCP_RB2_WPTR, ring->wptr);
+		rptr_addr = ring->rptr_gpu_addr;
+		WREG32(mmCP_RB2_RPTR_ADDR, lower_32_bits(rptr_addr));
+		WREG32(mmCP_RB2_RPTR_ADDR_HI, upper_32_bits(rptr_addr) & 0xFF);
+
+		mdelay(1);
+		WREG32(mmCP_RB2_CNTL, tmp);
+		WREG32(mmCP_RB2_BASE, ring->gpu_addr >> 8);
+	}
+
 	/* start the rings */
 	gfx_v6_0_cp_gfx_start(adev);
-	r = amdgpu_ring_test_helper(ring);
+
+	/* Wait for the initial packets to finish, run gfx ring test */
+	r = amdgpu_ring_test_helper(&adev->gfx.gfx_ring[0]);
 	if (r)
 		return r;
 
+	for (i = 0; i < adev->gfx.num_compute_rings; i++) {
+		ring = &adev->gfx.compute_ring[i];
+
+		r = amdgpu_ring_test_helper(ring);
+		if (r)
+			return r;
+	}
+
 	return 0;
 }
 
@@ -2224,66 +2293,6 @@ static void gfx_v6_0_ring_set_wptr_compute(struct amdgpu_ring *ring)
 
 }
 
-static int gfx_v6_0_cp_compute_resume(struct amdgpu_device *adev)
-{
-	struct amdgpu_ring *ring;
-	u32 tmp;
-	u32 rb_bufsz;
-	int i, r;
-	u64 rptr_addr;
-
-	/* ring1  - compute only */
-	/* Set ring buffer size */
-
-	ring = &adev->gfx.compute_ring[0];
-	rb_bufsz = order_base_2(ring->ring_size / 8);
-	tmp = (order_base_2(AMDGPU_GPU_PAGE_SIZE/8) << 8) | rb_bufsz;
-#ifdef __BIG_ENDIAN
-	tmp |= BUF_SWAP_32BIT;
-#endif
-	WREG32(mmCP_RB1_CNTL, tmp);
-
-	WREG32(mmCP_RB1_CNTL, tmp | CP_RB1_CNTL__RB_RPTR_WR_ENA_MASK);
-	ring->wptr = 0;
-	WREG32(mmCP_RB1_WPTR, ring->wptr);
-
-	rptr_addr = ring->rptr_gpu_addr;
-	WREG32(mmCP_RB1_RPTR_ADDR, lower_32_bits(rptr_addr));
-	WREG32(mmCP_RB1_RPTR_ADDR_HI, upper_32_bits(rptr_addr) & 0xFF);
-
-	mdelay(1);
-	WREG32(mmCP_RB1_CNTL, tmp);
-	WREG32(mmCP_RB1_BASE, ring->gpu_addr >> 8);
-
-	ring = &adev->gfx.compute_ring[1];
-	rb_bufsz = order_base_2(ring->ring_size / 8);
-	tmp = (order_base_2(AMDGPU_GPU_PAGE_SIZE/8) << 8) | rb_bufsz;
-#ifdef __BIG_ENDIAN
-	tmp |= BUF_SWAP_32BIT;
-#endif
-	WREG32(mmCP_RB2_CNTL, tmp);
-
-	WREG32(mmCP_RB2_CNTL, tmp | CP_RB2_CNTL__RB_RPTR_WR_ENA_MASK);
-	ring->wptr = 0;
-	WREG32(mmCP_RB2_WPTR, ring->wptr);
-	rptr_addr = ring->rptr_gpu_addr;
-	WREG32(mmCP_RB2_RPTR_ADDR, lower_32_bits(rptr_addr));
-	WREG32(mmCP_RB2_RPTR_ADDR_HI, upper_32_bits(rptr_addr) & 0xFF);
-
-	mdelay(1);
-	WREG32(mmCP_RB2_CNTL, tmp);
-	WREG32(mmCP_RB2_BASE, ring->gpu_addr >> 8);
-
-
-	for (i = 0; i < 2; i++) {
-		r = amdgpu_ring_test_helper(&adev->gfx.compute_ring[i]);
-		if (r)
-			return r;
-	}
-
-	return 0;
-}
-
 static void gfx_v6_0_cp_enable(struct amdgpu_device *adev, bool enable)
 {
 	gfx_v6_0_cp_gfx_enable(adev, enable);
@@ -2333,9 +2342,6 @@ static int gfx_v6_0_cp_resume(struct amdgpu_device *adev)
 		return r;
 
 	r = gfx_v6_0_cp_gfx_resume(adev);
-	if (r)
-		return r;
-	r = gfx_v6_0_cp_compute_resume(adev);
 	if (r)
 		return r;
 
-- 
2.55.0


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 05/10] drm/amdgpu/gfx6: Clean up rings during reset
  2026-08-03 13:22 [PATCH 00/10] drm/amdgpu/gfx6: Use GFX IP block soft reset on GFX6 (v2) Timur Kristóf
                   ` (3 preceding siblings ...)
  2026-08-03 13:23 ` [PATCH 04/10] drm/amdgpu/gfx6: Initialize compute rings before CP start Timur Kristóf
@ 2026-08-03 13:23 ` Timur Kristóf
  2026-08-03 13:23 ` [PATCH 06/10] drm/amdgpu/gfx6: Execute CLEAR_STATE when initializing compute rings Timur Kristóf
                   ` (4 subsequent siblings)
  9 siblings, 0 replies; 12+ messages in thread
From: Timur Kristóf @ 2026-08-03 13:23 UTC (permalink / raw)
  To: amd-gfx, Alex Deucher, Christian König, Tvrtko Ursulin,
	Natalie Vock
  Cc: Timur Kristóf

Clear the WPTR and RPTR at ring initialization.
Additionally clear the ring contents too.
This is necessary so that the IP block soft reset can
bring the rings back to a clean state.

After a reset, the ring contents could contain packets
emitted before the reset, and thus need to be cleared
to prevent the command processor from executing packets
left over in the ring from before the reset.

Signed-off-by: Timur Kristóf <timur.kristof@gmail.com>
---
 drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c | 22 ++++++++++++++++++----
 1 file changed, 18 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c
index cd8a34d87c6d..ce63417ae17e 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c
@@ -2159,8 +2159,12 @@ static int gfx_v6_0_cp_gfx_resume(struct amdgpu_device *adev)
 	WREG32(mmSCRATCH_ADDR, 0);
 
 	/* ring 0 - compute and gfx */
-	/* Set ring buffer size */
 	ring = &adev->gfx.gfx_ring[0];
+	*ring->wptr_cpu_addr = 0;
+	*ring->rptr_cpu_addr = 0;
+	amdgpu_ring_clear_ring(ring);
+
+	/* Set ring buffer size */
 	rb_bufsz = order_base_2(ring->ring_size / 8);
 	tmp = (order_base_2(AMDGPU_GPU_PAGE_SIZE/8) << 8) | rb_bufsz;
 
@@ -2172,7 +2176,8 @@ static int gfx_v6_0_cp_gfx_resume(struct amdgpu_device *adev)
 	/* Initialize the ring buffer's read and write pointers */
 	WREG32(mmCP_RB0_CNTL, tmp | CP_RB0_CNTL__RB_RPTR_WR_ENA_MASK);
 	ring->wptr = 0;
-	WREG32(mmCP_RB0_WPTR, ring->wptr);
+	WREG32(mmCP_RB0_WPTR, lower_32_bits(ring->wptr));
+	WREG32(mmCP_RB0_RPTR, lower_32_bits(ring->wptr));
 
 	/* set the wb address whether it's enabled or not */
 	rptr_addr = ring->rptr_gpu_addr;
@@ -2189,6 +2194,9 @@ static int gfx_v6_0_cp_gfx_resume(struct amdgpu_device *adev)
 	/* ring 1  - compute only */
 	if (adev->gfx.num_compute_rings >= 1) {
 		ring = &adev->gfx.compute_ring[0];
+		*ring->wptr_cpu_addr = 0;
+		*ring->rptr_cpu_addr = 0;
+		amdgpu_ring_clear_ring(ring);
 
 		rb_bufsz = order_base_2(ring->ring_size / 8);
 		tmp = (order_base_2(AMDGPU_GPU_PAGE_SIZE / 8) << 8) | rb_bufsz;
@@ -2199,7 +2207,8 @@ static int gfx_v6_0_cp_gfx_resume(struct amdgpu_device *adev)
 
 		WREG32(mmCP_RB1_CNTL, tmp | CP_RB1_CNTL__RB_RPTR_WR_ENA_MASK);
 		ring->wptr = 0;
-		WREG32(mmCP_RB1_WPTR, ring->wptr);
+		WREG32(mmCP_RB1_WPTR, lower_32_bits(ring->wptr));
+		WREG32(mmCP_RB1_RPTR, lower_32_bits(ring->wptr));
 
 		rptr_addr = ring->rptr_gpu_addr;
 		WREG32(mmCP_RB1_RPTR_ADDR, lower_32_bits(rptr_addr));
@@ -2213,6 +2222,9 @@ static int gfx_v6_0_cp_gfx_resume(struct amdgpu_device *adev)
 	/* ring 2 - compute only */
 	if (adev->gfx.num_compute_rings >= 2) {
 		ring = &adev->gfx.compute_ring[1];
+		*ring->wptr_cpu_addr = 0;
+		*ring->rptr_cpu_addr = 0;
+		amdgpu_ring_clear_ring(ring);
 
 		rb_bufsz = order_base_2(ring->ring_size / 8);
 		tmp = (order_base_2(AMDGPU_GPU_PAGE_SIZE / 8) << 8) | rb_bufsz;
@@ -2223,7 +2235,9 @@ static int gfx_v6_0_cp_gfx_resume(struct amdgpu_device *adev)
 
 		WREG32(mmCP_RB2_CNTL, tmp | CP_RB2_CNTL__RB_RPTR_WR_ENA_MASK);
 		ring->wptr = 0;
-		WREG32(mmCP_RB2_WPTR, ring->wptr);
+		WREG32(mmCP_RB2_WPTR, lower_32_bits(ring->wptr));
+		WREG32(mmCP_RB2_RPTR, lower_32_bits(ring->wptr));
+
 		rptr_addr = ring->rptr_gpu_addr;
 		WREG32(mmCP_RB2_RPTR_ADDR, lower_32_bits(rptr_addr));
 		WREG32(mmCP_RB2_RPTR_ADDR_HI, upper_32_bits(rptr_addr) & 0xFF);
-- 
2.55.0


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 06/10] drm/amdgpu/gfx6: Execute CLEAR_STATE when initializing compute rings
  2026-08-03 13:22 [PATCH 00/10] drm/amdgpu/gfx6: Use GFX IP block soft reset on GFX6 (v2) Timur Kristóf
                   ` (4 preceding siblings ...)
  2026-08-03 13:23 ` [PATCH 05/10] drm/amdgpu/gfx6: Clean up rings during reset Timur Kristóf
@ 2026-08-03 13:23 ` Timur Kristóf
  2026-08-03 13:23 ` [PATCH 07/10] drm/amdgpu/gfx6: Adjust how harvested TCCs are set up Timur Kristóf
                   ` (3 subsequent siblings)
  9 siblings, 0 replies; 12+ messages in thread
From: Timur Kristóf @ 2026-08-03 13:23 UTC (permalink / raw)
  To: amd-gfx, Alex Deucher, Christian König, Tvrtko Ursulin,
	Natalie Vock
  Cc: Timur Kristóf

Emit a compute CLEAR_STATE packet on the compute rings after
the GFX ring already finished executing ME_INITIALIZE and
before the ring test, so that gfx_v6_0_cp_gfx_resume() can
wait until the CLEAR_STATE is complete.

For reference, see si_cp_start() in the old radeon driver.

Signed-off-by: Timur Kristóf <timur.kristof@gmail.com>
---
 drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c
index ce63417ae17e..b1dfcbe9640c 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c
@@ -2258,6 +2258,14 @@ static int gfx_v6_0_cp_gfx_resume(struct amdgpu_device *adev)
 	for (i = 0; i < adev->gfx.num_compute_rings; i++) {
 		ring = &adev->gfx.compute_ring[i];
 
+		r = amdgpu_ring_alloc(ring, 2);
+		if (r)
+			return r;
+
+		amdgpu_ring_write(ring, PACKET3_COMPUTE(PACKET3_CLEAR_STATE, 0));
+		amdgpu_ring_write(ring, 0);
+		amdgpu_ring_commit(ring);
+
 		r = amdgpu_ring_test_helper(ring);
 		if (r)
 			return r;
-- 
2.55.0


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 07/10] drm/amdgpu/gfx6: Adjust how harvested TCCs are set up
  2026-08-03 13:22 [PATCH 00/10] drm/amdgpu/gfx6: Use GFX IP block soft reset on GFX6 (v2) Timur Kristóf
                   ` (5 preceding siblings ...)
  2026-08-03 13:23 ` [PATCH 06/10] drm/amdgpu/gfx6: Execute CLEAR_STATE when initializing compute rings Timur Kristóf
@ 2026-08-03 13:23 ` Timur Kristóf
  2026-08-03 13:23 ` [PATCH 08/10] drm/amdgpu/gfx6: Use COND_EXEC Timur Kristóf
                   ` (2 subsequent siblings)
  9 siblings, 0 replies; 12+ messages in thread
From: Timur Kristóf @ 2026-08-03 13:23 UTC (permalink / raw)
  To: amd-gfx, Alex Deucher, Christian König, Tvrtko Ursulin,
	Natalie Vock
  Cc: Timur Kristóf

Adjust gfx_v6_0_setup_tcc() to keep it working after
a GFX IP block soft reset. On a soft reset, the
TCP_CHAN_STEER_LO/HI registers are not cleared so
the function needs a slight adjustment to how the
number of active TCCs are calculated.

Additionally, let's expose the disabled TCC mask
in the tcc_disabled_mask field, like on other GPUs.

Signed-off-by: Timur Kristóf <timur.kristof@gmail.com>
---
 drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c | 11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c
index b1dfcbe9640c..a51403caa342 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c
@@ -1597,7 +1597,7 @@ static void gfx_v6_0_setup_spi(struct amdgpu_device *adev)
  */
 static void gfx_v6_0_setup_tcc(struct amdgpu_device *adev)
 {
-	u32 i, tcc, tcp_addr_config, num_active_tcc = 0;
+	u32 i, tcc, tcp_addr_config, num_active_tcc = 0, num_max_active_tcc;
 	u64 chan_steer, patched_chan_steer = 0;
 	const u32 num_max_tcc = adev->gfx.config.max_texture_channel_caches;
 	const u32 dis_tcc_mask =
@@ -1611,6 +1611,8 @@ static void gfx_v6_0_setup_tcc(struct amdgpu_device *adev)
 	if (!dis_tcc_mask)
 		return;
 
+	num_max_active_tcc = num_max_tcc - hweight32(dis_tcc_mask);
+
 	/* Each 4-bit nibble contains the index of a TCC used by all TCPs */
 	chan_steer = RREG32(mmTCP_CHAN_STEER_LO) | ((u64)RREG32(mmTCP_CHAN_STEER_HI) << 32ull);
 
@@ -1623,9 +1625,12 @@ static void gfx_v6_0_setup_tcc(struct amdgpu_device *adev)
 			patched_chan_steer |= (u64)tcc << (u64)(4 * num_active_tcc);
 			++num_active_tcc;
 		}
+
+		if (num_active_tcc == num_max_active_tcc)
+			break;
 	}
 
-	WARN_ON(num_active_tcc != num_max_tcc - hweight32(dis_tcc_mask));
+	WARN_ON(num_active_tcc != num_max_active_tcc);
 
 	/* Patch number of TCCs used by TCPs */
 	tcp_addr_config = REG_SET_FIELD(RREG32(mmTCP_ADDR_CONFIG),
@@ -1635,6 +1640,8 @@ static void gfx_v6_0_setup_tcc(struct amdgpu_device *adev)
 	WREG32(mmTCP_ADDR_CONFIG, tcp_addr_config);
 	WREG32(mmTCP_CHAN_STEER_HI, upper_32_bits(patched_chan_steer));
 	WREG32(mmTCP_CHAN_STEER_LO, lower_32_bits(patched_chan_steer));
+
+	adev->gfx.config.tcc_disabled_mask = dis_tcc_mask;
 }
 
 static void gfx_v6_0_config_init(struct amdgpu_device *adev)
-- 
2.55.0


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 08/10] drm/amdgpu/gfx6: Use COND_EXEC
  2026-08-03 13:22 [PATCH 00/10] drm/amdgpu/gfx6: Use GFX IP block soft reset on GFX6 (v2) Timur Kristóf
                   ` (6 preceding siblings ...)
  2026-08-03 13:23 ` [PATCH 07/10] drm/amdgpu/gfx6: Adjust how harvested TCCs are set up Timur Kristóf
@ 2026-08-03 13:23 ` Timur Kristóf
  2026-08-03 13:23 ` [PATCH 09/10] drm/amdgpu/gfx6: Add IP block soft reset implementation Timur Kristóf
  2026-08-03 13:23 ` [PATCH 10/10] drm/amdgpu/gfx6: Enable IP block soft reset as a GPU recovery method Timur Kristóf
  9 siblings, 0 replies; 12+ messages in thread
From: Timur Kristóf @ 2026-08-03 13:23 UTC (permalink / raw)
  To: amd-gfx, Alex Deucher, Christian König, Tvrtko Ursulin,
	Natalie Vock
  Cc: Timur Kristóf

COND_EXEC tells the CP to discard the dwords following it
when its condition is zero (false).

This is useful for GPU recovery because it can help reduce
collateral damage during GFX IP block soft reset, meaning
that it reduces the likelyhood that we fail some jobs which
are not guilty of the hang as the IP block soft reset
mechanism clears the condition before doing the reset.

Note that this packet is only 4 DW on GFX6 (as opposed
to GFX7 and newer where it's 5 DW).

Signed-off-by: Timur Kristóf <timur.kristof@gmail.com>
---
 drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c | 24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c
index a51403caa342..2fcd2d70c0ce 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c
@@ -2420,6 +2420,24 @@ static void gfx_v6_0_ring_emit_vm_flush(struct amdgpu_ring *ring,
 	}
 }
 
+static unsigned int gfx_v6_0_ring_emit_init_cond_exec(struct amdgpu_ring *ring,
+						  uint64_t gpu_addr)
+{
+	unsigned int ret;
+
+	/*
+	 * Discard following DWs after this packet when gpu_addr==0
+	 * The packet is only 4 DW on GFX6 (as opposed to GFX7+).
+	 */
+	amdgpu_ring_write(ring, PACKET3(PACKET3_COND_EXEC, 2));
+	amdgpu_ring_write(ring, lower_32_bits(gpu_addr));
+	amdgpu_ring_write(ring, upper_32_bits(gpu_addr));
+	ret = ring->wptr & ring->buf_mask;
+	/* patch dummy value later */
+	amdgpu_ring_write(ring, 0);
+	return ret;
+}
+
 static void gfx_v6_0_ring_emit_wreg(struct amdgpu_ring *ring,
 				    uint32_t reg, uint32_t val)
 {
@@ -3558,6 +3576,8 @@ static const struct amdgpu_ring_funcs gfx_v6_0_ring_funcs_gfx = {
 	.get_wptr = gfx_v6_0_ring_get_wptr,
 	.set_wptr = gfx_v6_0_ring_set_wptr_gfx,
 	.emit_frame_size =
+		4 + /* gfx_v6_0_ring_emit_init_cond_exec (from amdgpu_ib_schedule) */
+		4 + /* gfx_v6_0_ring_emit_init_cond_exec (from amdgpu_vm_flush) */
 		5 + 5 + /* hdp flush / invalidate */
 		14 + 14 + 14 + /* gfx_v6_0_ring_emit_fence x3 for user fence, vm fence */
 		7 + /* gfx_v6_0_ring_emit_pipeline_sync */
@@ -3575,6 +3595,7 @@ static const struct amdgpu_ring_funcs gfx_v6_0_ring_funcs_gfx = {
 	.insert_nop = amdgpu_ring_insert_nop,
 	.emit_switch_buffer = gfx_v6_0_ring_emit_sb,
 	.emit_cntxcntl = gfx_v6_ring_emit_cntxcntl,
+	.init_cond_exec = gfx_v6_0_ring_emit_init_cond_exec,
 	.emit_wreg = gfx_v6_0_ring_emit_wreg,
 	.emit_mem_sync = gfx_v6_0_emit_mem_sync,
 };
@@ -3587,6 +3608,8 @@ static const struct amdgpu_ring_funcs gfx_v6_0_ring_funcs_compute = {
 	.get_wptr = gfx_v6_0_ring_get_wptr,
 	.set_wptr = gfx_v6_0_ring_set_wptr_compute,
 	.emit_frame_size =
+		4 + /* gfx_v6_0_ring_emit_init_cond_exec (from amdgpu_ib_schedule) */
+		4 + /* gfx_v6_0_ring_emit_init_cond_exec (from amdgpu_vm_flush) */
 		5 + 5 + /* hdp flush / invalidate */
 		7 + /* gfx_v6_0_ring_emit_pipeline_sync */
 		SI_FLUSH_GPU_TLB_NUM_WREG * 5 + 7 + 2 + /* gfx_v6_0_ring_emit_vm_flush */
@@ -3602,6 +3625,7 @@ static const struct amdgpu_ring_funcs gfx_v6_0_ring_funcs_compute = {
 	.test_ib = gfx_v6_0_ring_test_ib,
 	.insert_nop = amdgpu_ring_insert_nop,
 	.emit_switch_buffer = gfx_v6_0_ring_emit_sb,
+	.init_cond_exec = gfx_v6_0_ring_emit_init_cond_exec,
 	.emit_wreg = gfx_v6_0_ring_emit_wreg,
 	.emit_mem_sync = gfx_v6_0_emit_mem_sync,
 };
-- 
2.55.0


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 09/10] drm/amdgpu/gfx6: Add IP block soft reset implementation
  2026-08-03 13:22 [PATCH 00/10] drm/amdgpu/gfx6: Use GFX IP block soft reset on GFX6 (v2) Timur Kristóf
                   ` (7 preceding siblings ...)
  2026-08-03 13:23 ` [PATCH 08/10] drm/amdgpu/gfx6: Use COND_EXEC Timur Kristóf
@ 2026-08-03 13:23 ` Timur Kristóf
  2026-08-03 13:23 ` [PATCH 10/10] drm/amdgpu/gfx6: Enable IP block soft reset as a GPU recovery method Timur Kristóf
  9 siblings, 0 replies; 12+ messages in thread
From: Timur Kristóf @ 2026-08-03 13:23 UTC (permalink / raw)
  To: amd-gfx, Alex Deucher, Christian König, Tvrtko Ursulin,
	Natalie Vock
  Cc: Timur Kristóf

Update the register definition for GRBM_SOFT_RESET
to match what was in the old radeon driver and use
these bits in the soft reset implementation.

For the soft reset, use basically the same
implementation as GFX7-8, the main difference being
the GRBM_SOFT_RESET bit fields and the fact that
GFX6 doesn't have MQD/HQD. Reset every block using
the GRBM, then proceed to reset the GRBM and SEM blocks
using the SRBM.

The soft reset also calls the clock and powergating
functions of the IP block. This is necessary for
correct operation, otherwise the GPU might fall
off the PCIe bus.

Add a gfx_v6_0_late_init() function for consistency
with other GPU generations. This function will
later serve the same purpose as it does on GFX7+
when we get around to enable more IRQs on GFX6.

Signed-off-by: Timur Kristóf <timur.kristof@gmail.com>
---
 drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c         | 100 ++++++++++++++++++
 .../include/asic_reg/gca/gfx_6_0_sh_mask.h    |  32 ++++--
 2 files changed, 124 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c
index 2fcd2d70c0ce..6de58e85a3ae 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c
@@ -3155,6 +3155,11 @@ static int gfx_v6_0_early_init(struct amdgpu_ip_block *ip_block)
 	return 0;
 }
 
+static int gfx_v6_0_late_init(struct amdgpu_ip_block *ip_block)
+{
+	return 0;
+}
+
 static int gfx_v6_0_sw_init(struct amdgpu_ip_block *ip_block)
 {
 	struct amdgpu_ring *ring;
@@ -3307,6 +3312,99 @@ static int gfx_v6_0_wait_for_idle(struct amdgpu_ip_block *ip_block)
 	return -ETIMEDOUT;
 }
 
+static int gfx_v6_0_soft_reset(struct amdgpu_ip_block *ip_block)
+{
+	struct amdgpu_device *adev = ip_block->adev;
+	u32 grbm_soft_reset = 0, srbm_soft_reset = 0;
+	u32 tmp;
+	int r;
+
+	grbm_soft_reset =
+		REG_SET_FIELD(0, GRBM_SOFT_RESET, SOFT_RESET_CP, 1) |
+		REG_SET_FIELD(0, GRBM_SOFT_RESET, SOFT_RESET_CB, 1) |
+		REG_SET_FIELD(0, GRBM_SOFT_RESET, SOFT_RESET_RLC, 1) |
+		REG_SET_FIELD(0, GRBM_SOFT_RESET, SOFT_RESET_DB, 1) |
+		REG_SET_FIELD(0, GRBM_SOFT_RESET, SOFT_RESET_GDS, 1) |
+		REG_SET_FIELD(0, GRBM_SOFT_RESET, SOFT_RESET_PA, 1) |
+		REG_SET_FIELD(0, GRBM_SOFT_RESET, SOFT_RESET_SC, 1) |
+		REG_SET_FIELD(0, GRBM_SOFT_RESET, SOFT_RESET_BCI, 1) |
+		REG_SET_FIELD(0, GRBM_SOFT_RESET, SOFT_RESET_SPI, 1) |
+		REG_SET_FIELD(0, GRBM_SOFT_RESET, SOFT_RESET_SX, 1) |
+		REG_SET_FIELD(0, GRBM_SOFT_RESET, SOFT_RESET_TC, 1) |
+		REG_SET_FIELD(0, GRBM_SOFT_RESET, SOFT_RESET_TA, 1) |
+		REG_SET_FIELD(0, GRBM_SOFT_RESET, SOFT_RESET_VGT, 1) |
+		REG_SET_FIELD(0, GRBM_SOFT_RESET, SOFT_RESET_IA, 1);
+
+	srbm_soft_reset =
+		REG_SET_FIELD(0, SRBM_SOFT_RESET, SOFT_RESET_GRBM, 1) |
+		REG_SET_FIELD(0, SRBM_SOFT_RESET, SOFT_RESET_SEM, 1);
+
+	ip_block->version->funcs->set_clockgating_state(ip_block, AMD_CG_STATE_UNGATE);
+	ip_block->version->funcs->set_powergating_state(ip_block, AMD_PG_STATE_UNGATE);
+	ip_block->version->funcs->suspend(ip_block);
+
+	if (grbm_soft_reset || srbm_soft_reset) {
+		tmp = RREG32(mmGMCON_DEBUG);
+		tmp = REG_SET_FIELD(tmp, GMCON_DEBUG, GFX_STALL, 1);
+		tmp = REG_SET_FIELD(tmp, GMCON_DEBUG, GFX_CLEAR, 1);
+		WREG32(mmGMCON_DEBUG, tmp);
+
+		udelay(100);
+	}
+
+	if (grbm_soft_reset) {
+		tmp = RREG32(mmGRBM_SOFT_RESET);
+		tmp |= grbm_soft_reset;
+		dev_info(adev->dev, "GRBM_SOFT_RESET=0x%08X\n", tmp);
+		WREG32(mmGRBM_SOFT_RESET, tmp);
+		tmp = RREG32(mmGRBM_SOFT_RESET);
+
+		udelay(100);
+
+		tmp &= ~grbm_soft_reset;
+		WREG32(mmGRBM_SOFT_RESET, tmp);
+		tmp = RREG32(mmGRBM_SOFT_RESET);
+
+		udelay(100);
+	}
+
+	if (srbm_soft_reset) {
+		tmp = RREG32(mmSRBM_SOFT_RESET);
+		tmp |= srbm_soft_reset;
+		dev_info(adev->dev, "SRBM_SOFT_RESET=0x%08X\n", tmp);
+		WREG32(mmSRBM_SOFT_RESET, tmp);
+		tmp = RREG32(mmSRBM_SOFT_RESET);
+
+		udelay(100);
+
+		tmp &= ~srbm_soft_reset;
+		WREG32(mmSRBM_SOFT_RESET, tmp);
+		tmp = RREG32(mmSRBM_SOFT_RESET);
+
+		udelay(100);
+	}
+
+	if (grbm_soft_reset || srbm_soft_reset) {
+		tmp = RREG32(mmGMCON_DEBUG);
+		tmp = REG_SET_FIELD(tmp, GMCON_DEBUG, GFX_STALL, 0);
+		tmp = REG_SET_FIELD(tmp, GMCON_DEBUG, GFX_CLEAR, 0);
+		WREG32(mmGMCON_DEBUG, tmp);
+	}
+
+	/* Wait a little for things to settle down */
+	udelay(100);
+
+	r = ip_block->version->funcs->resume(ip_block);
+	r |= ip_block->version->funcs->late_init(ip_block);
+	if (r)
+		return r;
+
+	ip_block->version->funcs->set_clockgating_state(ip_block, AMD_CG_STATE_GATE);
+	ip_block->version->funcs->set_powergating_state(ip_block, AMD_PG_STATE_GATE);
+
+	return 0;
+}
+
 static void gfx_v6_0_set_gfx_eop_interrupt_state(struct amdgpu_device *adev,
 						 enum amdgpu_interrupt_state state)
 {
@@ -3555,6 +3653,7 @@ static void gfx_v6_0_emit_mem_sync(struct amdgpu_ring *ring)
 static const struct amd_ip_funcs gfx_v6_0_ip_funcs = {
 	.name = "gfx_v6_0",
 	.early_init = gfx_v6_0_early_init,
+	.late_init = gfx_v6_0_late_init,
 	.sw_init = gfx_v6_0_sw_init,
 	.sw_fini = gfx_v6_0_sw_fini,
 	.hw_init = gfx_v6_0_hw_init,
@@ -3563,6 +3662,7 @@ static const struct amd_ip_funcs gfx_v6_0_ip_funcs = {
 	.resume = gfx_v6_0_resume,
 	.is_idle = gfx_v6_0_is_idle,
 	.wait_for_idle = gfx_v6_0_wait_for_idle,
+	.soft_reset = gfx_v6_0_soft_reset,
 	.set_clockgating_state = gfx_v6_0_set_clockgating_state,
 	.set_powergating_state = gfx_v6_0_set_powergating_state,
 };
diff --git a/drivers/gpu/drm/amd/include/asic_reg/gca/gfx_6_0_sh_mask.h b/drivers/gpu/drm/amd/include/asic_reg/gca/gfx_6_0_sh_mask.h
index b5e634749665..0434fc2ba710 100644
--- a/drivers/gpu/drm/amd/include/asic_reg/gca/gfx_6_0_sh_mask.h
+++ b/drivers/gpu/drm/amd/include/asic_reg/gca/gfx_6_0_sh_mask.h
@@ -4877,18 +4877,34 @@
 #define GRBM_SKEW_CNTL__SKEW_COUNT__SHIFT 0x00000006
 #define GRBM_SKEW_CNTL__SKEW_TOP_THRESHOLD_MASK 0x0000003fL
 #define GRBM_SKEW_CNTL__SKEW_TOP_THRESHOLD__SHIFT 0x00000000
-#define GRBM_SOFT_RESET__SOFT_RESET_CPC_MASK 0x00040000L
-#define GRBM_SOFT_RESET__SOFT_RESET_CPC__SHIFT 0x00000012
-#define GRBM_SOFT_RESET__SOFT_RESET_CPF_MASK 0x00020000L
-#define GRBM_SOFT_RESET__SOFT_RESET_CPF__SHIFT 0x00000011
-#define GRBM_SOFT_RESET__SOFT_RESET_CPG_MASK 0x00080000L
-#define GRBM_SOFT_RESET__SOFT_RESET_CPG__SHIFT 0x00000013
 #define GRBM_SOFT_RESET__SOFT_RESET_CP_MASK 0x00000001L
 #define GRBM_SOFT_RESET__SOFT_RESET_CP__SHIFT 0x00000000
-#define GRBM_SOFT_RESET__SOFT_RESET_GFX_MASK 0x00010000L
-#define GRBM_SOFT_RESET__SOFT_RESET_GFX__SHIFT 0x00000010
+#define GRBM_SOFT_RESET__SOFT_RESET_CB_MASK 0x00000002L
+#define GRBM_SOFT_RESET__SOFT_RESET_CB__SHIFT 0x00000001
 #define GRBM_SOFT_RESET__SOFT_RESET_RLC_MASK 0x00000004L
 #define GRBM_SOFT_RESET__SOFT_RESET_RLC__SHIFT 0x00000002
+#define GRBM_SOFT_RESET__SOFT_RESET_DB_MASK 0x00000008L
+#define GRBM_SOFT_RESET__SOFT_RESET_DB__SHIFT 0x00000003
+#define GRBM_SOFT_RESET__SOFT_RESET_GDS_MASK 0x00000010L
+#define GRBM_SOFT_RESET__SOFT_RESET_GDS__SHIFT 0x00000004
+#define GRBM_SOFT_RESET__SOFT_RESET_PA_MASK 0x00000020L
+#define GRBM_SOFT_RESET__SOFT_RESET_PA__SHIFT 0x00000005
+#define GRBM_SOFT_RESET__SOFT_RESET_SC_MASK 0x00000040L
+#define GRBM_SOFT_RESET__SOFT_RESET_SC__SHIFT 0x00000006
+#define GRBM_SOFT_RESET__SOFT_RESET_BCI_MASK 0x00000080L
+#define GRBM_SOFT_RESET__SOFT_RESET_BCI__SHIFT 0x00000007
+#define GRBM_SOFT_RESET__SOFT_RESET_SPI_MASK 0x00000100L
+#define GRBM_SOFT_RESET__SOFT_RESET_SPI__SHIFT 0x00000008
+#define GRBM_SOFT_RESET__SOFT_RESET_SX_MASK 0x00000400L
+#define GRBM_SOFT_RESET__SOFT_RESET_SX__SHIFT 0x0000000a
+#define GRBM_SOFT_RESET__SOFT_RESET_TC_MASK 0x00000800L
+#define GRBM_SOFT_RESET__SOFT_RESET_TC__SHIFT 0x0000000b
+#define GRBM_SOFT_RESET__SOFT_RESET_TA_MASK 0x00001000L
+#define GRBM_SOFT_RESET__SOFT_RESET_TA__SHIFT 0x0000000c
+#define GRBM_SOFT_RESET__SOFT_RESET_VGT_MASK 0x00004000L
+#define GRBM_SOFT_RESET__SOFT_RESET_VGT__SHIFT 0x0000000e
+#define GRBM_SOFT_RESET__SOFT_RESET_IA_MASK 0x00008000L
+#define GRBM_SOFT_RESET__SOFT_RESET_IA__SHIFT 0x0000000f
 #define GRBM_STATUS2__CPC_BUSY_MASK 0x20000000L
 #define GRBM_STATUS2__CPC_BUSY__SHIFT 0x0000001d
 #define GRBM_STATUS2__CPF_BUSY_MASK 0x10000000L
-- 
2.55.0


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 10/10] drm/amdgpu/gfx6: Enable IP block soft reset as a GPU recovery method
  2026-08-03 13:22 [PATCH 00/10] drm/amdgpu/gfx6: Use GFX IP block soft reset on GFX6 (v2) Timur Kristóf
                   ` (8 preceding siblings ...)
  2026-08-03 13:23 ` [PATCH 09/10] drm/amdgpu/gfx6: Add IP block soft reset implementation Timur Kristóf
@ 2026-08-03 13:23 ` Timur Kristóf
  9 siblings, 0 replies; 12+ messages in thread
From: Timur Kristóf @ 2026-08-03 13:23 UTC (permalink / raw)
  To: amd-gfx, Alex Deucher, Christian König, Tvrtko Ursulin,
	Natalie Vock
  Cc: Timur Kristóf

Enable IP block soft reset as a GPU recovery method for GFX6
graphics and compute rings.

This improves current user experience on all GFX6 chips.
The current GPU recovery method is a legacy ASIC reset which
always clears the contents of VRAM, which means that a buggy
(hanging) app can crash the whole graphical session, which
is less than ideal. Also on some GPUs the ASIC reset causes
the GPU to fall off the PCIe bus so it's not desireable.

Using GFX IP block soft reset means that we can now
move on from GFX hangs on GFX6 dGPUs without crashing the
whole system.

Tested with the "hard_reset_cp_wait" test case from the
Hang Test Suite created by Natalie Vock and Konstantin Seurer.
This Vulkan testcase waits for an event that never occurs,
effectively a WAIT_REG_MEM packet that intentionally hangs.
IP block soft reset can resolve that hang and allow
the rest of the system to move on and keep functioning
without needing a full ASIC reset.

Tested on the following chips:

Tahiti (FirePro W9000, Radeon HD 7870 XT)
Cape Verde (Radeon R7 450)
Pitcairn (Radeon R9 270X)
Oland (Radeon 430)

Signed-off-by: Timur Kristóf <timur.kristof@gmail.com>
---
 drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c
index 6de58e85a3ae..563abcf718b7 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c
@@ -3230,6 +3230,11 @@ static int gfx_v6_0_sw_init(struct amdgpu_ip_block *ip_block)
 	adev->gfx.compute_supported_reset =
 		amdgpu_get_soft_full_reset_mask(&adev->gfx.compute_ring[0]);
 
+	if (!amdgpu_sriov_vf(adev) && !adev->debug_disable_ip_block_soft_reset) {
+		adev->gfx.compute_supported_reset |= AMDGPU_RESET_TYPE_IP_BLOCK_SOFT_RESET;
+		adev->gfx.gfx_supported_reset |= AMDGPU_RESET_TYPE_IP_BLOCK_SOFT_RESET;
+	}
+
 	return r;
 }
 
-- 
2.55.0


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* Re: [PATCH 01/10] drm/amdgpu/gfx6: Fixup emit_cntxcntl()
  2026-08-03 13:23 ` [PATCH 01/10] drm/amdgpu/gfx6: Fixup emit_cntxcntl() Timur Kristóf
@ 2026-08-04 15:11   ` Alex Deucher
  0 siblings, 0 replies; 12+ messages in thread
From: Alex Deucher @ 2026-08-04 15:11 UTC (permalink / raw)
  To: Timur Kristóf
  Cc: amd-gfx, Alex Deucher, Christian König, Tvrtko Ursulin,
	Natalie Vock

Applied the series.  Thanks!

Alex

On Mon, Aug 3, 2026 at 11:13 AM Timur Kristóf <timur.kristof@gmail.com> wrote:
>
> Set bits on dword 2 like GFX7-8 except load_global_uconfig
> which doesn't exist on GFX6.
>
> Emit VS_PARTIAL_FLUSH before VGT_FLUSH like GFX7-8.
>
> For reference see old PAL which explains the bit fields in
> this register and that load_global_uconfig doesn't exist on GFX6
> and also see gfx_v7_ring_emit_cntxcntl() for the GFX7 code
> which this commit follows.
>
> Fixes: 2cd46ad22383 ("drm/amdgpu: add graphic pipeline implementation for si v8")
> Signed-off-by: Timur Kristóf <timur.kristof@gmail.com>
> ---
>  drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c | 28 ++++++++++++++++++++-------
>  1 file changed, 21 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c
> index cd2a14ecdba8..0cbaae73a0bf 100644
> --- a/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c
> +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c
> @@ -1882,11 +1882,13 @@ static int gfx_v6_0_ring_test_ring(struct amdgpu_ring *ring)
>         return r;
>  }
>
> -static void gfx_v6_0_ring_emit_vgt_flush(struct amdgpu_ring *ring)
> +static void gfx_v6_0_ring_emit_event_write(struct amdgpu_ring *ring,
> +                                          uint32_t event_type,
> +                                          uint32_t event_index)
>  {
>         amdgpu_ring_write(ring, PACKET3(PACKET3_EVENT_WRITE, 0));
> -       amdgpu_ring_write(ring, EVENT_TYPE(VGT_FLUSH) |
> -               EVENT_INDEX(0));
> +       amdgpu_ring_write(ring, EVENT_TYPE(event_type) |
> +                               EVENT_INDEX(event_index));
>  }
>
>  static void gfx_v6_0_ring_emit_fence(struct amdgpu_ring *ring, u64 addr,
> @@ -2997,10 +2999,22 @@ static uint64_t gfx_v6_0_get_gpu_clock_counter(struct amdgpu_device *adev)
>
>  static void gfx_v6_ring_emit_cntxcntl(struct amdgpu_ring *ring, uint32_t flags)
>  {
> -       if (flags & AMDGPU_HAVE_CTX_SWITCH)
> -               gfx_v6_0_ring_emit_vgt_flush(ring);
> +       u32 dw2 = 0x80000000; /* set load_enable otherwise this package is just NOPs */
> +
> +       if (flags & AMDGPU_HAVE_CTX_SWITCH) {
> +               gfx_v6_0_ring_emit_event_write(ring, VS_PARTIAL_FLUSH, 4);
> +               gfx_v6_0_ring_emit_event_write(ring, VGT_FLUSH, 0);
> +
> +               /* set load_global_config (load_global_uconfig doesn't exist on GFX6) */
> +               dw2 |= 0x1;
> +               /* set load_cs_sh_regs */
> +               dw2 |= 0x01000000;
> +               /* set load_per_context_state & load_gfx_sh_regs */
> +               dw2 |= 0x10002;
> +       }
> +
>         amdgpu_ring_write(ring, PACKET3(PACKET3_CONTEXT_CONTROL, 1));
> -       amdgpu_ring_write(ring, 0x80000000);
> +       amdgpu_ring_write(ring, dw2);
>         amdgpu_ring_write(ring, 0);
>  }
>
> @@ -3527,7 +3541,7 @@ static const struct amdgpu_ring_funcs gfx_v6_0_ring_funcs_gfx = {
>                 14 + 14 + 14 + /* gfx_v6_0_ring_emit_fence x3 for user fence, vm fence */
>                 7 + 4 + /* gfx_v6_0_ring_emit_pipeline_sync */
>                 SI_FLUSH_GPU_TLB_NUM_WREG * 5 + 7 + 6 + /* gfx_v6_0_ring_emit_vm_flush */
> -               3 + 2 + /* gfx_v6_ring_emit_cntxcntl including vgt flush */
> +               3 + 2 + 2 + /* gfx_v6_ring_emit_cntxcntl including VGT flush */
>                 5, /* SURFACE_SYNC */
>         .emit_ib_size = 6, /* gfx_v6_0_ring_emit_ib */
>         .emit_ib = gfx_v6_0_ring_emit_ib,
> --
> 2.55.0
>

^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2026-08-04 15:12 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-03 13:22 [PATCH 00/10] drm/amdgpu/gfx6: Use GFX IP block soft reset on GFX6 (v2) Timur Kristóf
2026-08-03 13:23 ` [PATCH 01/10] drm/amdgpu/gfx6: Fixup emit_cntxcntl() Timur Kristóf
2026-08-04 15:11   ` Alex Deucher
2026-08-03 13:23 ` [PATCH 02/10] drm/amdgpu/gfx6: Fixup emitting SWITCH_BUFFER packets Timur Kristóf
2026-08-03 13:23 ` [PATCH 03/10] drm/amdgpu/gfx6: Use PFP on the compute queues too Timur Kristóf
2026-08-03 13:23 ` [PATCH 04/10] drm/amdgpu/gfx6: Initialize compute rings before CP start Timur Kristóf
2026-08-03 13:23 ` [PATCH 05/10] drm/amdgpu/gfx6: Clean up rings during reset Timur Kristóf
2026-08-03 13:23 ` [PATCH 06/10] drm/amdgpu/gfx6: Execute CLEAR_STATE when initializing compute rings Timur Kristóf
2026-08-03 13:23 ` [PATCH 07/10] drm/amdgpu/gfx6: Adjust how harvested TCCs are set up Timur Kristóf
2026-08-03 13:23 ` [PATCH 08/10] drm/amdgpu/gfx6: Use COND_EXEC Timur Kristóf
2026-08-03 13:23 ` [PATCH 09/10] drm/amdgpu/gfx6: Add IP block soft reset implementation Timur Kristóf
2026-08-03 13:23 ` [PATCH 10/10] drm/amdgpu/gfx6: Enable IP block soft reset as a GPU recovery method Timur Kristóf

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.