* [PATCH 01/12] drm/amdgpu/sdma: Refactor SI DMA functions to be per instance
2026-09-07 20:33 [PATCH 00/12] RFC: drm/amdgpu/sdma: Refactor SDMA v4 and older functions to be per-instance Timur Kristóf
@ 2026-09-07 20:33 ` Timur Kristóf
2026-09-07 20:33 ` [PATCH 02/12] drm/amdgpu/sdma: Refactor SI DMA clock gating functions to be per-instance Timur Kristóf
` (11 subsequent siblings)
12 siblings, 0 replies; 17+ messages in thread
From: Timur Kristóf @ 2026-09-07 20:33 UTC (permalink / raw)
To: amd-gfx, Marek Olšák, Alex Deucher,
Christian König, Tvrtko Ursulin, pierre-eric.pelloux-prayer,
Natalie Vock, Lijo Lazar, Felix Kuehling
Cc: Timur Kristóf
This prepares the code for implementing recovery for SI DMA.
Reorganize the SI DMA code so that the functions that are
responsible for managing the DMA engines take an instance ID
as an argument.
This makes it possible to manage the two DMA instances
independently of each other, which will enable us to
also use these functions to implement resetting and
recovering them independently.
Signed-off-by: Timur Kristóf <timur.kristof@gmail.com>
---
drivers/gpu/drm/amd/amdgpu/si_dma.c | 97 ++++++++++++++---------------
1 file changed, 47 insertions(+), 50 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/si_dma.c b/drivers/gpu/drm/amd/amdgpu/si_dma.c
index 31ab701d45d3..483a0cfb7c8f 100644
--- a/drivers/gpu/drm/amd/amdgpu/si_dma.c
+++ b/drivers/gpu/drm/amd/amdgpu/si_dma.c
@@ -125,74 +125,64 @@ static void si_dma_ring_emit_fence(struct amdgpu_ring *ring, u64 addr, u64 seq,
amdgpu_ring_write(ring, DMA_PACKET(DMA_PACKET_TRAP, 0, 0, 0, 0));
}
-static void si_dma_stop(struct amdgpu_device *adev)
+static void si_dma_stop(struct amdgpu_device *adev, const u32 instance_id)
{
+ const u32 reg_offset = sdma_offsets[instance_id];
u32 rb_cntl;
- unsigned i;
- for (i = 0; i < adev->sdma.num_instances; i++) {
- /* dma0 */
- rb_cntl = RREG32(mmDMA_GFX_RB_CNTL + sdma_offsets[i]);
- rb_cntl &= ~DMA_GFX_RB_CNTL__RB_ENABLE_MASK;
- WREG32(mmDMA_GFX_RB_CNTL + sdma_offsets[i], rb_cntl);
- }
+ rb_cntl = RREG32(mmDMA_GFX_RB_CNTL + reg_offset);
+ rb_cntl &= ~DMA_GFX_RB_CNTL__RB_ENABLE_MASK;
+ WREG32(mmDMA_GFX_RB_CNTL + reg_offset, rb_cntl);
}
-static int si_dma_start(struct amdgpu_device *adev)
+static int si_dma_start(struct amdgpu_device *adev, const u32 instance_id)
{
- struct amdgpu_ring *ring;
+ struct amdgpu_ring *ring = &adev->sdma.instance[instance_id].ring;
+ const u32 reg_offset = sdma_offsets[instance_id];
u32 rb_cntl, dma_cntl, ib_cntl, rb_bufsz;
- int i, r;
uint64_t rptr_addr;
- for (i = 0; i < adev->sdma.num_instances; i++) {
- ring = &adev->sdma.instance[i].ring;
-
- WREG32(mmDMA_SEM_INCOMPLETE_TIMER_CNTL + sdma_offsets[i], 0);
- WREG32(mmDMA_SEM_WAIT_FAIL_TIMER_CNTL + sdma_offsets[i], 0);
+ WREG32(mmDMA_SEM_INCOMPLETE_TIMER_CNTL + reg_offset, 0);
+ WREG32(mmDMA_SEM_WAIT_FAIL_TIMER_CNTL + reg_offset, 0);
- /* Set ring buffer size in dwords */
- rb_bufsz = order_base_2(ring->ring_size / 4);
- rb_cntl = rb_bufsz << 1;
+ /* Set ring buffer size in dwords */
+ rb_bufsz = order_base_2(ring->ring_size / 4);
+ rb_cntl = rb_bufsz << 1;
#ifdef __BIG_ENDIAN
- rb_cntl |= DMA_GFX_RB_CNTL__RB_SWAP_ENABLE_MASK | DMA_GFX_RB_CNTL__RPTR_WRITEBACK_SWAP_ENABLE_MASK;
+ rb_cntl |= DMA_GFX_RB_CNTL__RB_SWAP_ENABLE_MASK |
+ DMA_GFX_RB_CNTL__RPTR_WRITEBACK_SWAP_ENABLE_MASK;
#endif
- WREG32(mmDMA_GFX_RB_CNTL + sdma_offsets[i], rb_cntl);
+ WREG32(mmDMA_GFX_RB_CNTL + reg_offset, rb_cntl);
- /* Initialize the ring buffer's read and write pointers */
- WREG32(mmDMA_GFX_RB_RPTR + sdma_offsets[i], 0);
- WREG32(mmDMA_GFX_RB_WPTR + sdma_offsets[i], 0);
+ /* Initialize the ring buffer's read and write pointers */
+ WREG32(mmDMA_GFX_RB_RPTR + reg_offset, 0);
+ WREG32(mmDMA_GFX_RB_WPTR + reg_offset, 0);
- rptr_addr = ring->rptr_gpu_addr;
+ rptr_addr = ring->rptr_gpu_addr;
- WREG32(mmDMA_GFX_RB_RPTR_ADDR_LO + sdma_offsets[i], lower_32_bits(rptr_addr));
- WREG32(mmDMA_GFX_RB_RPTR_ADDR_HI + sdma_offsets[i], upper_32_bits(rptr_addr) & 0xFF);
+ WREG32(mmDMA_GFX_RB_RPTR_ADDR_LO + reg_offset, lower_32_bits(rptr_addr));
+ WREG32(mmDMA_GFX_RB_RPTR_ADDR_HI + reg_offset, upper_32_bits(rptr_addr) & 0xFF);
- rb_cntl |= DMA_GFX_RB_CNTL__RPTR_WRITEBACK_ENABLE_MASK;
+ rb_cntl |= DMA_GFX_RB_CNTL__RPTR_WRITEBACK_ENABLE_MASK;
- WREG32(mmDMA_GFX_RB_BASE + sdma_offsets[i], ring->gpu_addr >> 8);
+ WREG32(mmDMA_GFX_RB_BASE + reg_offset, ring->gpu_addr >> 8);
- /* enable DMA IBs */
- ib_cntl = DMA_GFX_IB_CNTL__IB_ENABLE_MASK | DMA_GFX_IB_CNTL__CMD_VMID_FORCE_MASK;
+ /* enable DMA IBs */
+ ib_cntl = DMA_GFX_IB_CNTL__IB_ENABLE_MASK | DMA_GFX_IB_CNTL__CMD_VMID_FORCE_MASK;
#ifdef __BIG_ENDIAN
- ib_cntl |= DMA_GFX_IB_CNTL__IB_SWAP_ENABLE_MASK;
+ ib_cntl |= DMA_GFX_IB_CNTL__IB_SWAP_ENABLE_MASK;
#endif
- WREG32(mmDMA_GFX_IB_CNTL + sdma_offsets[i], ib_cntl);
-
- dma_cntl = RREG32(mmDMA_CNTL + sdma_offsets[i]);
- dma_cntl &= ~DMA_CNTL__CTXEMPTY_INT_ENABLE_MASK;
- WREG32(mmDMA_CNTL + sdma_offsets[i], dma_cntl);
+ WREG32(mmDMA_GFX_IB_CNTL + reg_offset, ib_cntl);
- ring->wptr = 0;
- WREG32(mmDMA_GFX_RB_WPTR + sdma_offsets[i], ring->wptr << 2);
- WREG32(mmDMA_GFX_RB_CNTL + sdma_offsets[i], rb_cntl | DMA_GFX_RB_CNTL__RB_ENABLE_MASK);
+ dma_cntl = RREG32(mmDMA_CNTL + reg_offset);
+ dma_cntl &= ~DMA_CNTL__CTXEMPTY_INT_ENABLE_MASK;
+ WREG32(mmDMA_CNTL + reg_offset, dma_cntl);
- r = amdgpu_ring_test_helper(ring);
- if (r)
- return r;
- }
+ ring->wptr = 0;
+ WREG32(mmDMA_GFX_RB_WPTR + reg_offset, ring->wptr << 2);
+ WREG32(mmDMA_GFX_RB_CNTL + reg_offset, rb_cntl | DMA_GFX_RB_CNTL__RB_ENABLE_MASK);
- return 0;
+ return amdgpu_ring_test_helper(ring);
}
/**
@@ -548,11 +538,14 @@ static int si_dma_sw_fini(struct amdgpu_ip_block *ip_block)
static int si_dma_hw_init(struct amdgpu_ip_block *ip_block)
{
struct amdgpu_device *adev = ip_block->adev;
- int r;
+ int i, r;
+
+ for (i = 0; i < adev->sdma.num_instances; ++i) {
+ r = si_dma_start(adev, i);
+ if (r)
+ return r;
+ }
- r = si_dma_start(adev);
- if (r)
- return r;
si_dma_set_buffer_funcs(adev);
return 0;
@@ -560,7 +553,11 @@ static int si_dma_hw_init(struct amdgpu_ip_block *ip_block)
static int si_dma_hw_fini(struct amdgpu_ip_block *ip_block)
{
- si_dma_stop(ip_block->adev);
+ struct amdgpu_device *adev = ip_block->adev;
+ int i;
+
+ for (i = 0; i < adev->sdma.num_instances; ++i)
+ si_dma_stop(adev, i);
return 0;
}
--
2.55.0
^ permalink raw reply related [flat|nested] 17+ messages in thread* [PATCH 02/12] drm/amdgpu/sdma: Refactor SI DMA clock gating functions to be per-instance
2026-09-07 20:33 [PATCH 00/12] RFC: drm/amdgpu/sdma: Refactor SDMA v4 and older functions to be per-instance Timur Kristóf
2026-09-07 20:33 ` [PATCH 01/12] drm/amdgpu/sdma: Refactor SI DMA functions to be per instance Timur Kristóf
@ 2026-09-07 20:33 ` Timur Kristóf
2026-09-07 20:33 ` [PATCH 03/12] drm/amdgpu/sdma: Refactor CIK SDMA functions to be per instance Timur Kristóf
` (10 subsequent siblings)
12 siblings, 0 replies; 17+ messages in thread
From: Timur Kristóf @ 2026-09-07 20:33 UTC (permalink / raw)
To: amd-gfx, Marek Olšák, Alex Deucher,
Christian König, Tvrtko Ursulin, pierre-eric.pelloux-prayer,
Natalie Vock, Lijo Lazar, Felix Kuehling
Cc: Timur Kristóf
Refactor clock gating functions to take the SDMA engine
instance ID as an argument and only affect one SDMA engine
instance at once.
Signed-off-by: Timur Kristóf <timur.kristof@gmail.com>
---
drivers/gpu/drm/amd/amdgpu/si_dma.c | 63 +++++++++++++----------------
1 file changed, 29 insertions(+), 34 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/si_dma.c b/drivers/gpu/drm/amd/amdgpu/si_dma.c
index 483a0cfb7c8f..fa67415acbc4 100644
--- a/drivers/gpu/drm/amd/amdgpu/si_dma.c
+++ b/drivers/gpu/drm/amd/amdgpu/si_dma.c
@@ -654,45 +654,40 @@ static int si_dma_process_trap_irq(struct amdgpu_device *adev,
return 0;
}
-static int si_dma_set_clockgating_state(struct amdgpu_ip_block *ip_block,
- enum amd_clockgating_state state)
+static void si_dma_enable_mgcg(struct amdgpu_device *adev,
+ const u32 instance_id,
+ const bool enable)
{
- u32 orig, data, offset;
- int i;
- bool enable;
- struct amdgpu_device *adev = ip_block->adev;
-
- enable = (state == AMD_CG_STATE_GATE);
+ const u32 reg_offset = sdma_offsets[instance_id];
+ u32 orig, data;
if (enable && (adev->cg_flags & AMD_CG_SUPPORT_SDMA_MGCG)) {
- for (i = 0; i < adev->sdma.num_instances; i++) {
- if (i == 0)
- offset = DMA0_REGISTER_OFFSET;
- else
- offset = DMA1_REGISTER_OFFSET;
- orig = data = RREG32(mmDMA_POWER_CNTL + offset);
- data &= ~DMA_POWER_CNTL__MEM_POWER_OVERRIDE_MASK;
- if (data != orig)
- WREG32(mmDMA_POWER_CNTL + offset, data);
- WREG32(mmDMA_CLK_CTRL + offset, 0x00000100);
- }
+ orig = data = RREG32(mmDMA_POWER_CNTL + reg_offset);
+ data &= ~DMA_POWER_CNTL__MEM_POWER_OVERRIDE_MASK;
+ if (data != orig)
+ WREG32(mmDMA_POWER_CNTL + reg_offset, data);
+ WREG32(mmDMA_CLK_CTRL + reg_offset, 0x00000100);
} else {
- for (i = 0; i < adev->sdma.num_instances; i++) {
- if (i == 0)
- offset = DMA0_REGISTER_OFFSET;
- else
- offset = DMA1_REGISTER_OFFSET;
- orig = data = RREG32(mmDMA_POWER_CNTL + offset);
- data |= DMA_POWER_CNTL__MEM_POWER_OVERRIDE_MASK;
- if (data != orig)
- WREG32(mmDMA_POWER_CNTL + offset, data);
-
- orig = data = RREG32(mmDMA_CLK_CTRL + offset);
- data = 0xff000000;
- if (data != orig)
- WREG32(mmDMA_CLK_CTRL + offset, data);
- }
+ orig = data = RREG32(mmDMA_POWER_CNTL + reg_offset);
+ data |= DMA_POWER_CNTL__MEM_POWER_OVERRIDE_MASK;
+ if (data != orig)
+ WREG32(mmDMA_POWER_CNTL + reg_offset, data);
+
+ orig = data = RREG32(mmDMA_CLK_CTRL + reg_offset);
+ data = 0xff000000;
+ if (data != orig)
+ WREG32(mmDMA_CLK_CTRL + reg_offset, data);
}
+}
+
+static int si_dma_set_clockgating_state(struct amdgpu_ip_block *const ip_block,
+ const enum amd_clockgating_state state)
+{
+ struct amdgpu_device *const adev = ip_block->adev;
+ int i;
+
+ for (i = 0; i < adev->sdma.num_instances; i++)
+ si_dma_enable_mgcg(adev, i, state == AMD_CG_STATE_GATE);
return 0;
}
--
2.55.0
^ permalink raw reply related [flat|nested] 17+ messages in thread* [PATCH 03/12] drm/amdgpu/sdma: Refactor CIK SDMA functions to be per instance
2026-09-07 20:33 [PATCH 00/12] RFC: drm/amdgpu/sdma: Refactor SDMA v4 and older functions to be per-instance Timur Kristóf
2026-09-07 20:33 ` [PATCH 01/12] drm/amdgpu/sdma: Refactor SI DMA functions to be per instance Timur Kristóf
2026-09-07 20:33 ` [PATCH 02/12] drm/amdgpu/sdma: Refactor SI DMA clock gating functions to be per-instance Timur Kristóf
@ 2026-09-07 20:33 ` Timur Kristóf
2026-09-07 20:33 ` [PATCH 04/12] drm/amdgpu/sdma: Refactor CIK SDMA clock gating functions to be per-instance Timur Kristóf
` (9 subsequent siblings)
12 siblings, 0 replies; 17+ messages in thread
From: Timur Kristóf @ 2026-09-07 20:33 UTC (permalink / raw)
To: amd-gfx, Marek Olšák, Alex Deucher,
Christian König, Tvrtko Ursulin, pierre-eric.pelloux-prayer,
Natalie Vock, Lijo Lazar, Felix Kuehling
Cc: Timur Kristóf
This prepares the code for implementing recovery for CIK SDMA.
Reorganize the CIK SDMA code so that the functions that are
responsible for managing the SDMA engines take an instance ID
as an argument.
This makes it possible to manage the SDMA instances
independently of each other, which will enable us to
also use these functions to implement resetting and
recovering them independently.
Signed-off-by: Timur Kristóf <timur.kristof@gmail.com>
---
drivers/gpu/drm/amd/amdgpu/cik_sdma.c | 272 ++++++++++++++------------
1 file changed, 142 insertions(+), 130 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/cik_sdma.c b/drivers/gpu/drm/amd/amdgpu/cik_sdma.c
index f444207fa550..78fea0621ed9 100644
--- a/drivers/gpu/drm/amd/amdgpu/cik_sdma.c
+++ b/drivers/gpu/drm/amd/amdgpu/cik_sdma.c
@@ -300,34 +300,36 @@ static void cik_sdma_ring_emit_fence(struct amdgpu_ring *ring, u64 addr, u64 seq
* cik_sdma_gfx_stop - stop the gfx async dma engines
*
* @adev: amdgpu_device pointer
+ * @instance_id: SDMA engine instance ID
*
* Stop the gfx async dma ring buffers (CIK).
*/
-static void cik_sdma_gfx_stop(struct amdgpu_device *adev)
+static void cik_sdma_gfx_stop(struct amdgpu_device *adev, const u32 instance_id)
{
+ const u32 reg_offset = sdma_offsets[instance_id];
u32 rb_cntl;
- int i;
- for (i = 0; i < adev->sdma.num_instances; i++) {
- rb_cntl = RREG32(mmSDMA0_GFX_RB_CNTL + sdma_offsets[i]);
- rb_cntl &= ~SDMA0_GFX_RB_CNTL__RB_ENABLE_MASK;
- WREG32(mmSDMA0_GFX_RB_CNTL + sdma_offsets[i], rb_cntl);
- WREG32(mmSDMA0_GFX_IB_CNTL + sdma_offsets[i], 0);
- }
+ rb_cntl = RREG32(mmSDMA0_GFX_RB_CNTL + reg_offset);
+ rb_cntl &= ~SDMA0_GFX_RB_CNTL__RB_ENABLE_MASK;
+ WREG32(mmSDMA0_GFX_RB_CNTL + reg_offset, rb_cntl);
+ WREG32(mmSDMA0_GFX_IB_CNTL + reg_offset, 0);
}
/**
* cik_ctx_switch_enable - stop the async dma engines context switch
*
* @adev: amdgpu_device pointer
+ * @instance_id: SDMA engine instance ID
* @enable: enable/disable the DMA MEs context switch.
*
* Halt or unhalt the async dma engines context switch (VI).
*/
-static void cik_ctx_switch_enable(struct amdgpu_device *adev, bool enable)
+static void cik_ctx_switch_enable(struct amdgpu_device *adev,
+ const u32 instance_id,
+ const bool enable)
{
+ const u32 reg_offset = sdma_offsets[instance_id];
u32 f32_cntl, phase_quantum = 0;
- int i;
if (amdgpu_sdma_phase_quantum) {
unsigned value = amdgpu_sdma_phase_quantum;
@@ -353,176 +355,172 @@ static void cik_ctx_switch_enable(struct amdgpu_device *adev, bool enable)
unit << SDMA0_PHASE0_QUANTUM__UNIT__SHIFT;
}
- for (i = 0; i < adev->sdma.num_instances; i++) {
- f32_cntl = RREG32(mmSDMA0_CNTL + sdma_offsets[i]);
- if (enable) {
- f32_cntl = REG_SET_FIELD(f32_cntl, SDMA0_CNTL,
- AUTO_CTXSW_ENABLE, 1);
- if (amdgpu_sdma_phase_quantum) {
- WREG32(mmSDMA0_PHASE0_QUANTUM + sdma_offsets[i],
- phase_quantum);
- WREG32(mmSDMA0_PHASE1_QUANTUM + sdma_offsets[i],
- phase_quantum);
- }
- } else {
- f32_cntl = REG_SET_FIELD(f32_cntl, SDMA0_CNTL,
- AUTO_CTXSW_ENABLE, 0);
+ f32_cntl = RREG32(mmSDMA0_CNTL + reg_offset);
+ if (enable) {
+ f32_cntl = REG_SET_FIELD(f32_cntl, SDMA0_CNTL,
+ AUTO_CTXSW_ENABLE, 1);
+ if (amdgpu_sdma_phase_quantum) {
+ WREG32(mmSDMA0_PHASE0_QUANTUM + reg_offset,
+ phase_quantum);
+ WREG32(mmSDMA0_PHASE1_QUANTUM + reg_offset,
+ phase_quantum);
}
-
- WREG32(mmSDMA0_CNTL + sdma_offsets[i], f32_cntl);
+ } else {
+ f32_cntl = REG_SET_FIELD(f32_cntl, SDMA0_CNTL,
+ AUTO_CTXSW_ENABLE, 0);
}
+
+ WREG32(mmSDMA0_CNTL + reg_offset, f32_cntl);
}
/**
* cik_sdma_enable - stop the async dma engines
*
* @adev: amdgpu_device pointer
+ * @instance_id: SDMA engine instance ID
* @enable: enable/disable the DMA MEs.
*
* Halt or unhalt the async dma engines (CIK).
*/
-static void cik_sdma_enable(struct amdgpu_device *adev, bool enable)
+static void cik_sdma_enable(struct amdgpu_device *adev,
+ const u32 instance_id,
+ const bool enable)
{
+ const u32 reg_offset = sdma_offsets[instance_id];
u32 me_cntl;
- int i;
if (!enable) {
- cik_sdma_gfx_stop(adev);
+ cik_sdma_gfx_stop(adev, instance_id);
}
- for (i = 0; i < adev->sdma.num_instances; i++) {
- me_cntl = RREG32(mmSDMA0_F32_CNTL + sdma_offsets[i]);
- if (enable)
- me_cntl &= ~SDMA0_F32_CNTL__HALT_MASK;
- else
- me_cntl |= SDMA0_F32_CNTL__HALT_MASK;
- WREG32(mmSDMA0_F32_CNTL + sdma_offsets[i], me_cntl);
- }
+ me_cntl = RREG32(mmSDMA0_F32_CNTL + reg_offset);
+ if (enable)
+ me_cntl &= ~SDMA0_F32_CNTL__HALT_MASK;
+ else
+ me_cntl |= SDMA0_F32_CNTL__HALT_MASK;
+ WREG32(mmSDMA0_F32_CNTL + reg_offset, me_cntl);
}
/**
* cik_sdma_gfx_resume - setup and start the async dma engines
*
* @adev: amdgpu_device pointer
+ * @instance_id: SDMA engine instance ID
*
* Set up the gfx DMA ring buffers and enable them (CIK).
* Returns 0 for success, error for failure.
*/
-static int cik_sdma_gfx_resume(struct amdgpu_device *adev)
+static int cik_sdma_gfx_resume(struct amdgpu_device *adev, const u32 instance_id)
{
- struct amdgpu_ring *ring;
+ struct amdgpu_ring *const ring = &adev->sdma.instance[instance_id].ring;
+ const u32 reg_offset = sdma_offsets[instance_id];
u32 rb_cntl, ib_cntl;
u32 rb_bufsz;
- int i, j, r;
-
- for (i = 0; i < adev->sdma.num_instances; i++) {
- ring = &adev->sdma.instance[i].ring;
-
- mutex_lock(&adev->srbm_mutex);
- for (j = 0; j < 16; j++) {
- cik_srbm_select(adev, 0, 0, 0, j);
- /* SDMA GFX */
- WREG32(mmSDMA0_GFX_VIRTUAL_ADDR + sdma_offsets[i], 0);
- WREG32(mmSDMA0_GFX_APE1_CNTL + sdma_offsets[i], 0);
- /* XXX SDMA RLC - todo */
- }
- cik_srbm_select(adev, 0, 0, 0, 0);
- mutex_unlock(&adev->srbm_mutex);
+ int j;
+
+ mutex_lock(&adev->srbm_mutex);
+ for (j = 0; j < 16; j++) {
+ cik_srbm_select(adev, 0, 0, 0, j);
+ /* SDMA GFX */
+ WREG32(mmSDMA0_GFX_VIRTUAL_ADDR + reg_offset, 0);
+ WREG32(mmSDMA0_GFX_APE1_CNTL + reg_offset, 0);
+ /* XXX SDMA RLC - todo */
+ }
+ cik_srbm_select(adev, 0, 0, 0, 0);
+ mutex_unlock(&adev->srbm_mutex);
- WREG32(mmSDMA0_TILING_CONFIG + sdma_offsets[i],
- adev->gfx.config.gb_addr_config & 0x70);
+ WREG32(mmSDMA0_TILING_CONFIG + reg_offset,
+ adev->gfx.config.gb_addr_config & 0x70);
- WREG32(mmSDMA0_SEM_INCOMPLETE_TIMER_CNTL + sdma_offsets[i], 0);
- WREG32(mmSDMA0_SEM_WAIT_FAIL_TIMER_CNTL + sdma_offsets[i], 0);
+ WREG32(mmSDMA0_SEM_INCOMPLETE_TIMER_CNTL + reg_offset, 0);
+ WREG32(mmSDMA0_SEM_WAIT_FAIL_TIMER_CNTL + reg_offset, 0);
- /* Set ring buffer size in dwords */
- rb_bufsz = order_base_2(ring->ring_size / 4);
- rb_cntl = rb_bufsz << 1;
+ /* Set ring buffer size in dwords */
+ rb_bufsz = order_base_2(ring->ring_size / 4);
+ rb_cntl = rb_bufsz << 1;
#ifdef __BIG_ENDIAN
- rb_cntl |= SDMA0_GFX_RB_CNTL__RB_SWAP_ENABLE_MASK |
- SDMA0_GFX_RB_CNTL__RPTR_WRITEBACK_SWAP_ENABLE_MASK;
+ rb_cntl |= SDMA0_GFX_RB_CNTL__RB_SWAP_ENABLE_MASK |
+ SDMA0_GFX_RB_CNTL__RPTR_WRITEBACK_SWAP_ENABLE_MASK;
#endif
- WREG32(mmSDMA0_GFX_RB_CNTL + sdma_offsets[i], rb_cntl);
+ WREG32(mmSDMA0_GFX_RB_CNTL + reg_offset, rb_cntl);
- /* Initialize the ring buffer's read and write pointers */
- WREG32(mmSDMA0_GFX_RB_RPTR + sdma_offsets[i], 0);
- WREG32(mmSDMA0_GFX_RB_WPTR + sdma_offsets[i], 0);
- WREG32(mmSDMA0_GFX_IB_RPTR + sdma_offsets[i], 0);
- WREG32(mmSDMA0_GFX_IB_OFFSET + sdma_offsets[i], 0);
+ /* Initialize the ring buffer's read and write pointers */
+ WREG32(mmSDMA0_GFX_RB_RPTR + reg_offset, 0);
+ WREG32(mmSDMA0_GFX_RB_WPTR + reg_offset, 0);
+ WREG32(mmSDMA0_GFX_IB_RPTR + reg_offset, 0);
+ WREG32(mmSDMA0_GFX_IB_OFFSET + reg_offset, 0);
- /* set the wb address whether it's enabled or not */
- WREG32(mmSDMA0_GFX_RB_RPTR_ADDR_HI + sdma_offsets[i],
- upper_32_bits(ring->rptr_gpu_addr) & 0xFFFFFFFF);
- WREG32(mmSDMA0_GFX_RB_RPTR_ADDR_LO + sdma_offsets[i],
- ((ring->rptr_gpu_addr) & 0xFFFFFFFC));
+ /* set the wb address whether it's enabled or not */
+ WREG32(mmSDMA0_GFX_RB_RPTR_ADDR_HI + reg_offset,
+ upper_32_bits(ring->rptr_gpu_addr) & 0xFFFFFFFF);
+ WREG32(mmSDMA0_GFX_RB_RPTR_ADDR_LO + reg_offset,
+ ((ring->rptr_gpu_addr) & 0xFFFFFFFC));
- rb_cntl |= SDMA0_GFX_RB_CNTL__RPTR_WRITEBACK_ENABLE_MASK;
+ rb_cntl |= SDMA0_GFX_RB_CNTL__RPTR_WRITEBACK_ENABLE_MASK;
- WREG32(mmSDMA0_GFX_RB_BASE + sdma_offsets[i], ring->gpu_addr >> 8);
- WREG32(mmSDMA0_GFX_RB_BASE_HI + sdma_offsets[i], ring->gpu_addr >> 40);
+ WREG32(mmSDMA0_GFX_RB_BASE + reg_offset, ring->gpu_addr >> 8);
+ WREG32(mmSDMA0_GFX_RB_BASE_HI + reg_offset, ring->gpu_addr >> 40);
- ring->wptr = 0;
- WREG32(mmSDMA0_GFX_RB_WPTR + sdma_offsets[i], ring->wptr << 2);
+ ring->wptr = 0;
+ WREG32(mmSDMA0_GFX_RB_WPTR + reg_offset, ring->wptr << 2);
- /* enable DMA RB */
- WREG32(mmSDMA0_GFX_RB_CNTL + sdma_offsets[i],
- rb_cntl | SDMA0_GFX_RB_CNTL__RB_ENABLE_MASK);
+ /* enable DMA RB */
+ WREG32(mmSDMA0_GFX_RB_CNTL + reg_offset,
+ rb_cntl | SDMA0_GFX_RB_CNTL__RB_ENABLE_MASK);
- ib_cntl = SDMA0_GFX_IB_CNTL__IB_ENABLE_MASK;
+ ib_cntl = SDMA0_GFX_IB_CNTL__IB_ENABLE_MASK;
#ifdef __BIG_ENDIAN
- ib_cntl |= SDMA0_GFX_IB_CNTL__IB_SWAP_ENABLE_MASK;
+ ib_cntl |= SDMA0_GFX_IB_CNTL__IB_SWAP_ENABLE_MASK;
#endif
- /* enable DMA IBs */
- WREG32(mmSDMA0_GFX_IB_CNTL + sdma_offsets[i], ib_cntl);
- }
+ /* enable DMA IBs */
+ WREG32(mmSDMA0_GFX_IB_CNTL + reg_offset, ib_cntl);
- cik_sdma_enable(adev, true);
-
- for (i = 0; i < adev->sdma.num_instances; i++) {
- ring = &adev->sdma.instance[i].ring;
- r = amdgpu_ring_test_helper(ring);
- if (r)
- return r;
- }
+ cik_sdma_enable(adev, instance_id, true);
- return 0;
+ return amdgpu_ring_test_helper(ring);
}
/**
* cik_sdma_load_microcode - load the sDMA ME ucode
*
* @adev: amdgpu_device pointer
+ * @instance_id: SDMA engine instance ID
*
* Loads the sDMA0/1 ucode.
* Returns 0 for success, -EINVAL if the ucode is not available.
*/
-static int cik_sdma_load_microcode(struct amdgpu_device *adev)
+static int cik_sdma_load_microcode(struct amdgpu_device *adev, const u32 instance_id)
{
+ struct amdgpu_sdma_instance *const instance = &adev->sdma.instance[instance_id];
+ const u32 reg_offset = sdma_offsets[instance_id];
const struct sdma_firmware_header_v1_0 *hdr;
const __le32 *fw_data;
u32 fw_size;
- int i, j;
+ int j;
/* halt the MEs */
- cik_sdma_enable(adev, false);
+ cik_sdma_enable(adev, instance_id, false);
- for (i = 0; i < adev->sdma.num_instances; i++) {
- if (!adev->sdma.instance[i].fw)
- return -EINVAL;
- hdr = (const struct sdma_firmware_header_v1_0 *)adev->sdma.instance[i].fw->data;
- amdgpu_ucode_print_sdma_hdr(&hdr->header);
- fw_size = le32_to_cpu(hdr->header.ucode_size_bytes) / 4;
- adev->sdma.instance[i].fw_version = le32_to_cpu(hdr->header.ucode_version);
- adev->sdma.instance[i].feature_version = le32_to_cpu(hdr->ucode_feature_version);
- if (adev->sdma.instance[i].feature_version >= 20)
- adev->sdma.instance[i].burst_nop = true;
- fw_data = (const __le32 *)
- (adev->sdma.instance[i].fw->data + le32_to_cpu(hdr->header.ucode_array_offset_bytes));
- WREG32(mmSDMA0_UCODE_ADDR + sdma_offsets[i], 0);
- for (j = 0; j < fw_size; j++)
- WREG32(mmSDMA0_UCODE_DATA + sdma_offsets[i], le32_to_cpup(fw_data++));
- WREG32(mmSDMA0_UCODE_ADDR + sdma_offsets[i], adev->sdma.instance[i].fw_version);
- }
+ if (!adev->sdma.instance[instance_id].fw)
+ return -EINVAL;
+
+ hdr = (const struct sdma_firmware_header_v1_0 *)instance->fw->data;
+ amdgpu_ucode_print_sdma_hdr(&hdr->header);
+
+ fw_size = le32_to_cpu(hdr->header.ucode_size_bytes) / 4;
+ instance->fw_version = le32_to_cpu(hdr->header.ucode_version);
+ instance->feature_version = le32_to_cpu(hdr->ucode_feature_version);
+
+ if (instance->feature_version >= 20)
+ instance->burst_nop = true;
+
+ fw_data = (const __le32 *)
+ (instance->fw->data + le32_to_cpu(hdr->header.ucode_array_offset_bytes));
+
+ WREG32(mmSDMA0_UCODE_ADDR + reg_offset, 0);
+ for (j = 0; j < fw_size; j++)
+ WREG32(mmSDMA0_UCODE_DATA + reg_offset, le32_to_cpup(fw_data++));
+ WREG32(mmSDMA0_UCODE_ADDR + reg_offset, instance->fw_version);
return 0;
}
@@ -531,29 +529,40 @@ static int cik_sdma_load_microcode(struct amdgpu_device *adev)
* cik_sdma_start - setup and start the async dma engines
*
* @adev: amdgpu_device pointer
+ * @instance_id: SDMA engine instance ID
*
* Set up the DMA engines and enable them (CIK).
* Returns 0 for success, error for failure.
*/
-static int cik_sdma_start(struct amdgpu_device *adev)
+static int cik_sdma_start(struct amdgpu_device *adev, const u32 instance_id)
{
int r;
- r = cik_sdma_load_microcode(adev);
+ r = cik_sdma_load_microcode(adev, instance_id);
if (r)
return r;
/* halt the engine before programing */
- cik_sdma_enable(adev, false);
+ cik_sdma_enable(adev, instance_id, false);
/* enable sdma ring preemption */
- cik_ctx_switch_enable(adev, true);
+ cik_ctx_switch_enable(adev, instance_id, true);
/* start the gfx rings and rlc compute queues */
- r = cik_sdma_gfx_resume(adev);
- if (r)
- return r;
+ return cik_sdma_gfx_resume(adev, instance_id);
+}
- return 0;
+/**
+ * cik_sdma_stop() - Stop an SDMA engine
+ *
+ * @adev: amdgpu_device pointer
+ * @instance_id: SDMA engine instance ID
+ *
+ * Stop the given SDMA engine instance (CIK).
+ */
+static void cik_sdma_stop(struct amdgpu_device *adev, const u32 instance_id)
+{
+ cik_ctx_switch_enable(adev, instance_id, false);
+ cik_sdma_enable(adev, instance_id, false);
}
/**
@@ -974,11 +983,13 @@ static int cik_sdma_sw_fini(struct amdgpu_ip_block *ip_block)
static int cik_sdma_hw_init(struct amdgpu_ip_block *ip_block)
{
struct amdgpu_device *adev = ip_block->adev;
- int r;
+ int i, r;
- r = cik_sdma_start(adev);
- if (r)
- return r;
+ for (i = 0; i < adev->sdma.num_instances; ++i) {
+ r = cik_sdma_start(adev, i);
+ if (r)
+ return r;
+ }
cik_sdma_set_buffer_funcs(adev);
@@ -988,9 +999,10 @@ static int cik_sdma_hw_init(struct amdgpu_ip_block *ip_block)
static int cik_sdma_hw_fini(struct amdgpu_ip_block *ip_block)
{
struct amdgpu_device *adev = ip_block->adev;
+ int i;
- cik_ctx_switch_enable(adev, false);
- cik_sdma_enable(adev, false);
+ for (i = 0; i < adev->sdma.num_instances; ++i)
+ cik_sdma_stop(adev, i);
return 0;
}
--
2.55.0
^ permalink raw reply related [flat|nested] 17+ messages in thread* [PATCH 04/12] drm/amdgpu/sdma: Refactor CIK SDMA clock gating functions to be per-instance
2026-09-07 20:33 [PATCH 00/12] RFC: drm/amdgpu/sdma: Refactor SDMA v4 and older functions to be per-instance Timur Kristóf
` (2 preceding siblings ...)
2026-09-07 20:33 ` [PATCH 03/12] drm/amdgpu/sdma: Refactor CIK SDMA functions to be per instance Timur Kristóf
@ 2026-09-07 20:33 ` Timur Kristóf
2026-09-07 20:33 ` [PATCH 05/12] drm/amdgpu/sdma: Refactor SDMA v2.4 functions to be per instance Timur Kristóf
` (8 subsequent siblings)
12 siblings, 0 replies; 17+ messages in thread
From: Timur Kristóf @ 2026-09-07 20:33 UTC (permalink / raw)
To: amd-gfx, Marek Olšák, Alex Deucher,
Christian König, Tvrtko Ursulin, pierre-eric.pelloux-prayer,
Natalie Vock, Lijo Lazar, Felix Kuehling
Cc: Timur Kristóf
Refactor clock gating functions to take the SDMA engine
instance ID as an argument and only affect one SDMA engine
instance at once.
Signed-off-by: Timur Kristóf <timur.kristof@gmail.com>
---
drivers/gpu/drm/amd/amdgpu/cik_sdma.c | 50 ++++++++++-----------------
1 file changed, 19 insertions(+), 31 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/cik_sdma.c b/drivers/gpu/drm/amd/amdgpu/cik_sdma.c
index 78fea0621ed9..61ff76fb8fc2 100644
--- a/drivers/gpu/drm/amd/amdgpu/cik_sdma.c
+++ b/drivers/gpu/drm/amd/amdgpu/cik_sdma.c
@@ -854,51 +854,39 @@ static void cik_sdma_ring_emit_wreg(struct amdgpu_ring *ring,
}
static void cik_enable_sdma_mgcg(struct amdgpu_device *adev,
- bool enable)
+ const u32 instance_id,
+ const bool enable)
{
+ const u32 reg_offset = sdma_offsets[instance_id];
u32 orig, data;
if (enable && (adev->cg_flags & AMD_CG_SUPPORT_SDMA_MGCG)) {
- WREG32(mmSDMA0_CLK_CTRL + SDMA0_REGISTER_OFFSET, 0x00000100);
- WREG32(mmSDMA0_CLK_CTRL + SDMA1_REGISTER_OFFSET, 0x00000100);
+ WREG32(mmSDMA0_CLK_CTRL + reg_offset, 0x00000100);
} else {
- orig = data = RREG32(mmSDMA0_CLK_CTRL + SDMA0_REGISTER_OFFSET);
- data |= 0xff000000;
- if (data != orig)
- WREG32(mmSDMA0_CLK_CTRL + SDMA0_REGISTER_OFFSET, data);
-
- orig = data = RREG32(mmSDMA0_CLK_CTRL + SDMA1_REGISTER_OFFSET);
+ orig = data = RREG32(mmSDMA0_CLK_CTRL + reg_offset);
data |= 0xff000000;
if (data != orig)
- WREG32(mmSDMA0_CLK_CTRL + SDMA1_REGISTER_OFFSET, data);
+ WREG32(mmSDMA0_CLK_CTRL + reg_offset, data);
}
}
static void cik_enable_sdma_mgls(struct amdgpu_device *adev,
- bool enable)
+ const u32 instance_id,
+ const bool enable)
{
+ const u32 reg_offset = sdma_offsets[instance_id];
u32 orig, data;
if (enable && (adev->cg_flags & AMD_CG_SUPPORT_SDMA_LS)) {
- orig = data = RREG32(mmSDMA0_POWER_CNTL + SDMA0_REGISTER_OFFSET);
- data |= 0x100;
- if (orig != data)
- WREG32(mmSDMA0_POWER_CNTL + SDMA0_REGISTER_OFFSET, data);
-
- orig = data = RREG32(mmSDMA0_POWER_CNTL + SDMA1_REGISTER_OFFSET);
+ orig = data = RREG32(mmSDMA0_POWER_CNTL + reg_offset);
data |= 0x100;
if (orig != data)
- WREG32(mmSDMA0_POWER_CNTL + SDMA1_REGISTER_OFFSET, data);
+ WREG32(mmSDMA0_POWER_CNTL + reg_offset, data);
} else {
- orig = data = RREG32(mmSDMA0_POWER_CNTL + SDMA0_REGISTER_OFFSET);
+ orig = data = RREG32(mmSDMA0_POWER_CNTL + reg_offset);
data &= ~0x100;
if (orig != data)
- WREG32(mmSDMA0_POWER_CNTL + SDMA0_REGISTER_OFFSET, data);
-
- orig = data = RREG32(mmSDMA0_POWER_CNTL + SDMA1_REGISTER_OFFSET);
- data &= ~0x100;
- if (orig != data)
- WREG32(mmSDMA0_POWER_CNTL + SDMA1_REGISTER_OFFSET, data);
+ WREG32(mmSDMA0_POWER_CNTL + reg_offset, data);
}
}
@@ -1184,14 +1172,14 @@ static int cik_sdma_process_illegal_inst_irq(struct amdgpu_device *adev,
static int cik_sdma_set_clockgating_state(struct amdgpu_ip_block *ip_block,
enum amd_clockgating_state state)
{
- bool gate = false;
+ const bool gate = state == AMD_CG_STATE_GATE;
struct amdgpu_device *adev = ip_block->adev;
+ int i;
- if (state == AMD_CG_STATE_GATE)
- gate = true;
-
- cik_enable_sdma_mgcg(adev, gate);
- cik_enable_sdma_mgls(adev, gate);
+ for (i = 0; i < adev->sdma.num_instances; i++) {
+ cik_enable_sdma_mgcg(adev, i, gate);
+ cik_enable_sdma_mgls(adev, i, gate);
+ }
return 0;
}
--
2.55.0
^ permalink raw reply related [flat|nested] 17+ messages in thread* [PATCH 05/12] drm/amdgpu/sdma: Refactor SDMA v2.4 functions to be per instance
2026-09-07 20:33 [PATCH 00/12] RFC: drm/amdgpu/sdma: Refactor SDMA v4 and older functions to be per-instance Timur Kristóf
` (3 preceding siblings ...)
2026-09-07 20:33 ` [PATCH 04/12] drm/amdgpu/sdma: Refactor CIK SDMA clock gating functions to be per-instance Timur Kristóf
@ 2026-09-07 20:33 ` Timur Kristóf
2026-09-07 20:33 ` [PATCH 06/12] drm/amdgpu/sdma: Refactor SDMA v2.4 golden registers to be per-instance Timur Kristóf
` (7 subsequent siblings)
12 siblings, 0 replies; 17+ messages in thread
From: Timur Kristóf @ 2026-09-07 20:33 UTC (permalink / raw)
To: amd-gfx, Marek Olšák, Alex Deucher,
Christian König, Tvrtko Ursulin, pierre-eric.pelloux-prayer,
Natalie Vock, Lijo Lazar, Felix Kuehling
Cc: Timur Kristóf
This prepares the code for implementing recovery for SDMA 2.4.
Reorganize the SDMA 2.4 code so that the functions that are
responsible for managing the SDMA engines take an instance ID
as an argument.
This makes it possible to manage the SDMA instances
independently of each other, which will enable us to
also use these functions to implement resetting and
recovering them independently.
Signed-off-by: Timur Kristóf <timur.kristof@gmail.com>
---
drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c | 189 +++++++++++++------------
1 file changed, 100 insertions(+), 89 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c b/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c
index 7c8acdf73d44..0743b782527a 100644
--- a/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c
+++ b/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c
@@ -331,163 +331,168 @@ static void sdma_v2_4_ring_emit_fence(struct amdgpu_ring *ring, u64 addr, u64 se
* sdma_v2_4_gfx_stop - stop the gfx async dma engines
*
* @adev: amdgpu_device pointer
+ * @instance_id: SDMA engine instance ID
*
* Stop the gfx async dma ring buffers (VI).
*/
-static void sdma_v2_4_gfx_stop(struct amdgpu_device *adev)
+static void sdma_v2_4_gfx_stop(struct amdgpu_device *adev, const u32 instance_id)
{
+ const u32 reg_offset = sdma_offsets[instance_id];
u32 rb_cntl, ib_cntl;
- int i;
- for (i = 0; i < adev->sdma.num_instances; i++) {
- rb_cntl = RREG32(mmSDMA0_GFX_RB_CNTL + sdma_offsets[i]);
- rb_cntl = REG_SET_FIELD(rb_cntl, SDMA0_GFX_RB_CNTL, RB_ENABLE, 0);
- WREG32(mmSDMA0_GFX_RB_CNTL + sdma_offsets[i], rb_cntl);
- ib_cntl = RREG32(mmSDMA0_GFX_IB_CNTL + sdma_offsets[i]);
- ib_cntl = REG_SET_FIELD(ib_cntl, SDMA0_GFX_IB_CNTL, IB_ENABLE, 0);
- WREG32(mmSDMA0_GFX_IB_CNTL + sdma_offsets[i], ib_cntl);
- }
+ rb_cntl = RREG32(mmSDMA0_GFX_RB_CNTL + reg_offset);
+ rb_cntl = REG_SET_FIELD(rb_cntl, SDMA0_GFX_RB_CNTL, RB_ENABLE, 0);
+ WREG32(mmSDMA0_GFX_RB_CNTL + reg_offset, rb_cntl);
+ ib_cntl = RREG32(mmSDMA0_GFX_IB_CNTL + reg_offset);
+ ib_cntl = REG_SET_FIELD(ib_cntl, SDMA0_GFX_IB_CNTL, IB_ENABLE, 0);
+ WREG32(mmSDMA0_GFX_IB_CNTL + reg_offset, ib_cntl);
}
/**
* sdma_v2_4_enable - stop the async dma engines
*
* @adev: amdgpu_device pointer
+ * @instance_id: SDMA engine instance ID
* @enable: enable/disable the DMA MEs.
*
* Halt or unhalt the async dma engines (VI).
*/
-static void sdma_v2_4_enable(struct amdgpu_device *adev, bool enable)
+static void sdma_v2_4_enable(struct amdgpu_device *adev,
+ const u32 instance_id,
+ const bool enable)
{
+ const u32 reg_offset = sdma_offsets[instance_id];
u32 f32_cntl;
- int i;
if (!enable) {
- sdma_v2_4_gfx_stop(adev);
+ sdma_v2_4_gfx_stop(adev, instance_id);
}
- for (i = 0; i < adev->sdma.num_instances; i++) {
- f32_cntl = RREG32(mmSDMA0_F32_CNTL + sdma_offsets[i]);
- if (enable)
- f32_cntl = REG_SET_FIELD(f32_cntl, SDMA0_F32_CNTL, HALT, 0);
- else
- f32_cntl = REG_SET_FIELD(f32_cntl, SDMA0_F32_CNTL, HALT, 1);
- WREG32(mmSDMA0_F32_CNTL + sdma_offsets[i], f32_cntl);
- }
+ f32_cntl = RREG32(mmSDMA0_F32_CNTL + reg_offset);
+ if (enable)
+ f32_cntl = REG_SET_FIELD(f32_cntl, SDMA0_F32_CNTL, HALT, 0);
+ else
+ f32_cntl = REG_SET_FIELD(f32_cntl, SDMA0_F32_CNTL, HALT, 1);
+ WREG32(mmSDMA0_F32_CNTL + reg_offset, f32_cntl);
}
/**
* sdma_v2_4_gfx_resume - setup and start the async dma engines
*
* @adev: amdgpu_device pointer
+ * @instance_id: SDMA engine instance ID
*
* Set up the gfx DMA ring buffers and enable them (VI).
* Returns 0 for success, error for failure.
*/
-static int sdma_v2_4_gfx_resume(struct amdgpu_device *adev)
+static int sdma_v2_4_gfx_resume(struct amdgpu_device *adev, const u32 instance_id)
{
- struct amdgpu_ring *ring;
+ struct amdgpu_ring *const ring = &adev->sdma.instance[instance_id].ring;
+ const u32 reg_offset = sdma_offsets[instance_id];
u32 rb_cntl, ib_cntl;
u32 rb_bufsz;
- int i, j, r;
-
- for (i = 0; i < adev->sdma.num_instances; i++) {
- ring = &adev->sdma.instance[i].ring;
-
- mutex_lock(&adev->srbm_mutex);
- for (j = 0; j < 16; j++) {
- vi_srbm_select(adev, 0, 0, 0, j);
- /* SDMA GFX */
- WREG32(mmSDMA0_GFX_VIRTUAL_ADDR + sdma_offsets[i], 0);
- WREG32(mmSDMA0_GFX_APE1_CNTL + sdma_offsets[i], 0);
- }
- vi_srbm_select(adev, 0, 0, 0, 0);
- mutex_unlock(&adev->srbm_mutex);
+ int j;
+
+ mutex_lock(&adev->srbm_mutex);
+ for (j = 0; j < 16; j++) {
+ vi_srbm_select(adev, 0, 0, 0, j);
+ /* SDMA GFX */
+ WREG32(mmSDMA0_GFX_VIRTUAL_ADDR + reg_offset, 0);
+ WREG32(mmSDMA0_GFX_APE1_CNTL + reg_offset, 0);
+ }
+ vi_srbm_select(adev, 0, 0, 0, 0);
+ mutex_unlock(&adev->srbm_mutex);
- WREG32(mmSDMA0_TILING_CONFIG + sdma_offsets[i],
- adev->gfx.config.gb_addr_config & 0x70);
+ WREG32(mmSDMA0_TILING_CONFIG + reg_offset,
+ adev->gfx.config.gb_addr_config & 0x70);
- WREG32(mmSDMA0_SEM_WAIT_FAIL_TIMER_CNTL + sdma_offsets[i], 0);
+ WREG32(mmSDMA0_SEM_WAIT_FAIL_TIMER_CNTL + reg_offset, 0);
- /* Set ring buffer size in dwords */
- rb_bufsz = order_base_2(ring->ring_size / 4);
- rb_cntl = RREG32(mmSDMA0_GFX_RB_CNTL + sdma_offsets[i]);
- rb_cntl = REG_SET_FIELD(rb_cntl, SDMA0_GFX_RB_CNTL, RB_SIZE, rb_bufsz);
+ /* Set ring buffer size in dwords */
+ rb_bufsz = order_base_2(ring->ring_size / 4);
+ rb_cntl = RREG32(mmSDMA0_GFX_RB_CNTL + reg_offset);
+ rb_cntl = REG_SET_FIELD(rb_cntl, SDMA0_GFX_RB_CNTL, RB_SIZE, rb_bufsz);
#ifdef __BIG_ENDIAN
- rb_cntl = REG_SET_FIELD(rb_cntl, SDMA0_GFX_RB_CNTL, RB_SWAP_ENABLE, 1);
- rb_cntl = REG_SET_FIELD(rb_cntl, SDMA0_GFX_RB_CNTL,
- RPTR_WRITEBACK_SWAP_ENABLE, 1);
+ rb_cntl = REG_SET_FIELD(rb_cntl, SDMA0_GFX_RB_CNTL, RB_SWAP_ENABLE, 1);
+ rb_cntl = REG_SET_FIELD(rb_cntl, SDMA0_GFX_RB_CNTL,
+ RPTR_WRITEBACK_SWAP_ENABLE, 1);
#endif
- WREG32(mmSDMA0_GFX_RB_CNTL + sdma_offsets[i], rb_cntl);
+ WREG32(mmSDMA0_GFX_RB_CNTL + reg_offset, rb_cntl);
- /* Initialize the ring buffer's read and write pointers */
- WREG32(mmSDMA0_GFX_RB_RPTR + sdma_offsets[i], 0);
- WREG32(mmSDMA0_GFX_RB_WPTR + sdma_offsets[i], 0);
- WREG32(mmSDMA0_GFX_IB_RPTR + sdma_offsets[i], 0);
- WREG32(mmSDMA0_GFX_IB_OFFSET + sdma_offsets[i], 0);
+ /* Initialize the ring buffer's read and write pointers */
+ WREG32(mmSDMA0_GFX_RB_RPTR + reg_offset, 0);
+ WREG32(mmSDMA0_GFX_RB_WPTR + reg_offset, 0);
+ WREG32(mmSDMA0_GFX_IB_RPTR + reg_offset, 0);
+ WREG32(mmSDMA0_GFX_IB_OFFSET + reg_offset, 0);
- /* set the wb address whether it's enabled or not */
- WREG32(mmSDMA0_GFX_RB_RPTR_ADDR_HI + sdma_offsets[i],
- upper_32_bits(ring->rptr_gpu_addr) & 0xFFFFFFFF);
- WREG32(mmSDMA0_GFX_RB_RPTR_ADDR_LO + sdma_offsets[i],
- lower_32_bits(ring->rptr_gpu_addr) & 0xFFFFFFFC);
+ /* set the wb address whether it's enabled or not */
+ WREG32(mmSDMA0_GFX_RB_RPTR_ADDR_HI + reg_offset,
+ upper_32_bits(ring->rptr_gpu_addr) & 0xFFFFFFFF);
+ WREG32(mmSDMA0_GFX_RB_RPTR_ADDR_LO + reg_offset,
+ lower_32_bits(ring->rptr_gpu_addr) & 0xFFFFFFFC);
- rb_cntl = REG_SET_FIELD(rb_cntl, SDMA0_GFX_RB_CNTL, RPTR_WRITEBACK_ENABLE, 1);
+ rb_cntl = REG_SET_FIELD(rb_cntl, SDMA0_GFX_RB_CNTL, RPTR_WRITEBACK_ENABLE, 1);
- WREG32(mmSDMA0_GFX_RB_BASE + sdma_offsets[i], ring->gpu_addr >> 8);
- WREG32(mmSDMA0_GFX_RB_BASE_HI + sdma_offsets[i], ring->gpu_addr >> 40);
+ WREG32(mmSDMA0_GFX_RB_BASE + reg_offset, ring->gpu_addr >> 8);
+ WREG32(mmSDMA0_GFX_RB_BASE_HI + reg_offset, ring->gpu_addr >> 40);
- ring->wptr = 0;
- WREG32(mmSDMA0_GFX_RB_WPTR + sdma_offsets[i], ring->wptr << 2);
+ ring->wptr = 0;
+ WREG32(mmSDMA0_GFX_RB_WPTR + reg_offset, ring->wptr << 2);
- /* enable DMA RB */
- rb_cntl = REG_SET_FIELD(rb_cntl, SDMA0_GFX_RB_CNTL, RB_ENABLE, 1);
- WREG32(mmSDMA0_GFX_RB_CNTL + sdma_offsets[i], rb_cntl);
+ /* enable DMA RB */
+ rb_cntl = REG_SET_FIELD(rb_cntl, SDMA0_GFX_RB_CNTL, RB_ENABLE, 1);
+ WREG32(mmSDMA0_GFX_RB_CNTL + reg_offset, rb_cntl);
- ib_cntl = RREG32(mmSDMA0_GFX_IB_CNTL + sdma_offsets[i]);
- ib_cntl = REG_SET_FIELD(ib_cntl, SDMA0_GFX_IB_CNTL, IB_ENABLE, 1);
+ ib_cntl = RREG32(mmSDMA0_GFX_IB_CNTL + reg_offset);
+ ib_cntl = REG_SET_FIELD(ib_cntl, SDMA0_GFX_IB_CNTL, IB_ENABLE, 1);
#ifdef __BIG_ENDIAN
- ib_cntl = REG_SET_FIELD(ib_cntl, SDMA0_GFX_IB_CNTL, IB_SWAP_ENABLE, 1);
+ ib_cntl = REG_SET_FIELD(ib_cntl, SDMA0_GFX_IB_CNTL, IB_SWAP_ENABLE, 1);
#endif
- /* enable DMA IBs */
- WREG32(mmSDMA0_GFX_IB_CNTL + sdma_offsets[i], ib_cntl);
- }
+ /* enable DMA IBs */
+ WREG32(mmSDMA0_GFX_IB_CNTL + reg_offset, ib_cntl);
- sdma_v2_4_enable(adev, true);
- for (i = 0; i < adev->sdma.num_instances; i++) {
- ring = &adev->sdma.instance[i].ring;
- r = amdgpu_ring_test_helper(ring);
- if (r)
- return r;
- }
+ sdma_v2_4_enable(adev, instance_id, true);
- return 0;
+ return amdgpu_ring_test_helper(ring);
}
-
/**
* sdma_v2_4_start - setup and start the async dma engines
*
* @adev: amdgpu_device pointer
+ * @instance_id: SDMA engine instance ID
*
* Set up the DMA engines and enable them (VI).
* Returns 0 for success, error for failure.
*/
-static int sdma_v2_4_start(struct amdgpu_device *adev)
+static int sdma_v2_4_start(struct amdgpu_device *adev, const u32 instance_id)
{
int r;
/* halt the engine before programing */
- sdma_v2_4_enable(adev, false);
+ sdma_v2_4_enable(adev, instance_id, false);
/* start the gfx rings and rlc compute queues */
- r = sdma_v2_4_gfx_resume(adev);
+ r = sdma_v2_4_gfx_resume(adev, instance_id);
if (r)
return r;
return 0;
}
+/**
+ * sdma_v2_4_stop() - Stop an SDMA engine
+ *
+ * @adev: amdgpu_device pointer
+ * @instance_id: SDMA engine instance ID
+ *
+ * Stop the given SDMA engine instance (VI).
+ */
+static void sdma_v2_4_stop(struct amdgpu_device *adev, const u32 instance_id)
+{
+ sdma_v2_4_enable(adev, instance_id, false);
+}
+
/**
* sdma_v2_4_ring_test_ring - simple async dma engine test
*
@@ -863,14 +868,16 @@ static int sdma_v2_4_sw_fini(struct amdgpu_ip_block *ip_block)
static int sdma_v2_4_hw_init(struct amdgpu_ip_block *ip_block)
{
- int r;
struct amdgpu_device *adev = ip_block->adev;
+ int i, r;
sdma_v2_4_init_golden_registers(adev);
- r = sdma_v2_4_start(adev);
- if (r)
- return r;
+ for (i = 0; i < adev->sdma.num_instances; ++i) {
+ r = sdma_v2_4_start(adev, i);
+ if (r)
+ return r;
+ }
sdma_v2_4_set_buffer_funcs(adev);
@@ -879,7 +886,11 @@ static int sdma_v2_4_hw_init(struct amdgpu_ip_block *ip_block)
static int sdma_v2_4_hw_fini(struct amdgpu_ip_block *ip_block)
{
- sdma_v2_4_enable(ip_block->adev, false);
+ struct amdgpu_device *adev = ip_block->adev;
+ int i;
+
+ for (i = 0; i < adev->sdma.num_instances; ++i)
+ sdma_v2_4_stop(adev, i);
return 0;
}
--
2.55.0
^ permalink raw reply related [flat|nested] 17+ messages in thread* [PATCH 06/12] drm/amdgpu/sdma: Refactor SDMA v2.4 golden registers to be per-instance
2026-09-07 20:33 [PATCH 00/12] RFC: drm/amdgpu/sdma: Refactor SDMA v4 and older functions to be per-instance Timur Kristóf
` (4 preceding siblings ...)
2026-09-07 20:33 ` [PATCH 05/12] drm/amdgpu/sdma: Refactor SDMA v2.4 functions to be per instance Timur Kristóf
@ 2026-09-07 20:33 ` Timur Kristóf
2026-09-07 20:33 ` [PATCH 07/12] drm/amdgpu/sdma: Refactor SDMA v3.0 functions to be per instance Timur Kristóf
` (6 subsequent siblings)
12 siblings, 0 replies; 17+ messages in thread
From: Timur Kristóf @ 2026-09-07 20:33 UTC (permalink / raw)
To: amd-gfx, Marek Olšák, Alex Deucher,
Christian König, Tvrtko Ursulin, pierre-eric.pelloux-prayer,
Natalie Vock, Lijo Lazar, Felix Kuehling
Cc: Timur Kristóf
Refactor golden registers initialization to take the SDMA
engine instance ID as an argument and only program the
golden registers for one SDMA engine at once.
Signed-off-by: Timur Kristóf <timur.kristof@gmail.com>
---
drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c | 43 +++++++++++++++++++-------
1 file changed, 31 insertions(+), 12 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c b/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c
index 0743b782527a..a771e9ab3a9e 100644
--- a/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c
+++ b/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c
@@ -61,16 +61,22 @@ static const u32 sdma_offsets[SDMA_MAX_INSTANCE] = {
SDMA1_REGISTER_OFFSET
};
-static const u32 golden_settings_iceland_a11[] = {
+static const u32 golden_settings_iceland_a11_sdma0[] = {
mmSDMA0_CHICKEN_BITS, 0xfc910007, 0x00810007,
mmSDMA0_CLK_CTRL, 0xff000fff, 0x00000000,
+};
+
+static const u32 golden_settings_iceland_a11_sdma1[] = {
mmSDMA1_CHICKEN_BITS, 0xfc910007, 0x00810007,
mmSDMA1_CLK_CTRL, 0xff000fff, 0x00000000,
};
-static const u32 iceland_mgcg_cgcg_init[] = {
+static const u32 iceland_mgcg_cgcg_init_sdma0[] = {
mmSDMA0_CLK_CTRL, 0xff000ff0, 0x00000100,
- mmSDMA1_CLK_CTRL, 0xff000ff0, 0x00000100
+};
+
+static const u32 iceland_mgcg_cgcg_init_sdma1[] = {
+ mmSDMA1_CLK_CTRL, 0xff000ff0, 0x00000100,
};
/*
@@ -90,16 +96,29 @@ static const u32 iceland_mgcg_cgcg_init[] = {
* buffers.
*/
-static void sdma_v2_4_init_golden_registers(struct amdgpu_device *adev)
+static void sdma_v2_4_init_golden_registers(struct amdgpu_device *adev, const u32 instance_id)
{
switch (adev->asic_type) {
case CHIP_TOPAZ:
- amdgpu_device_program_register_sequence(adev,
- iceland_mgcg_cgcg_init,
- ARRAY_SIZE(iceland_mgcg_cgcg_init));
- amdgpu_device_program_register_sequence(adev,
- golden_settings_iceland_a11,
- ARRAY_SIZE(golden_settings_iceland_a11));
+ if (instance_id == 0) {
+ amdgpu_device_program_register_sequence(
+ adev,
+ iceland_mgcg_cgcg_init_sdma0,
+ ARRAY_SIZE(iceland_mgcg_cgcg_init_sdma0));
+ amdgpu_device_program_register_sequence(
+ adev,
+ golden_settings_iceland_a11_sdma0,
+ ARRAY_SIZE(golden_settings_iceland_a11_sdma0));
+ } else {
+ amdgpu_device_program_register_sequence(
+ adev,
+ iceland_mgcg_cgcg_init_sdma1,
+ ARRAY_SIZE(iceland_mgcg_cgcg_init_sdma1));
+ amdgpu_device_program_register_sequence(
+ adev,
+ golden_settings_iceland_a11_sdma1,
+ ARRAY_SIZE(golden_settings_iceland_a11_sdma1));
+ }
break;
default:
break;
@@ -469,6 +488,8 @@ static int sdma_v2_4_start(struct amdgpu_device *adev, const u32 instance_id)
{
int r;
+ sdma_v2_4_init_golden_registers(adev, instance_id);
+
/* halt the engine before programing */
sdma_v2_4_enable(adev, instance_id, false);
@@ -871,8 +892,6 @@ static int sdma_v2_4_hw_init(struct amdgpu_ip_block *ip_block)
struct amdgpu_device *adev = ip_block->adev;
int i, r;
- sdma_v2_4_init_golden_registers(adev);
-
for (i = 0; i < adev->sdma.num_instances; ++i) {
r = sdma_v2_4_start(adev, i);
if (r)
--
2.55.0
^ permalink raw reply related [flat|nested] 17+ messages in thread* [PATCH 07/12] drm/amdgpu/sdma: Refactor SDMA v3.0 functions to be per instance
2026-09-07 20:33 [PATCH 00/12] RFC: drm/amdgpu/sdma: Refactor SDMA v4 and older functions to be per-instance Timur Kristóf
` (5 preceding siblings ...)
2026-09-07 20:33 ` [PATCH 06/12] drm/amdgpu/sdma: Refactor SDMA v2.4 golden registers to be per-instance Timur Kristóf
@ 2026-09-07 20:33 ` Timur Kristóf
2026-09-07 20:33 ` [PATCH 08/12] drm/amdgpu/sdma: Refactor SDMA v3.0 clock gating functions to be per-instance Timur Kristóf
` (5 subsequent siblings)
12 siblings, 0 replies; 17+ messages in thread
From: Timur Kristóf @ 2026-09-07 20:33 UTC (permalink / raw)
To: amd-gfx, Marek Olšák, Alex Deucher,
Christian König, Tvrtko Ursulin, pierre-eric.pelloux-prayer,
Natalie Vock, Lijo Lazar, Felix Kuehling
Cc: Timur Kristóf
This prepares the code for implementing recovery for SDMA 3.0.
Reorganize the SDMA 3.0 code so that the functions that are
responsible for managing the SDMA engines take an instance ID
as an argument.
This makes it possible to manage the SDMA instances
independently of each other, which will enable us to
also use these functions to implement resetting and
recovering them independently.
Signed-off-by: Timur Kristóf <timur.kristof@gmail.com>
---
drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c | 298 +++++++++++++------------
1 file changed, 155 insertions(+), 143 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c
index e929d62721b3..6213a0c77590 100644
--- a/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c
@@ -508,36 +508,38 @@ static void sdma_v3_0_ring_emit_fence(struct amdgpu_ring *ring, u64 addr, u64 se
* sdma_v3_0_gfx_stop - stop the gfx async dma engines
*
* @adev: amdgpu_device pointer
+ * @instance_id: SDMA engine instance ID
*
* Stop the gfx async dma ring buffers (VI).
*/
-static void sdma_v3_0_gfx_stop(struct amdgpu_device *adev)
+static void sdma_v3_0_gfx_stop(struct amdgpu_device *adev, const u32 instance_id)
{
+ const u32 reg_offset = sdma_offsets[instance_id];
u32 rb_cntl, ib_cntl;
- int i;
- for (i = 0; i < adev->sdma.num_instances; i++) {
- rb_cntl = RREG32(mmSDMA0_GFX_RB_CNTL + sdma_offsets[i]);
- rb_cntl = REG_SET_FIELD(rb_cntl, SDMA0_GFX_RB_CNTL, RB_ENABLE, 0);
- WREG32(mmSDMA0_GFX_RB_CNTL + sdma_offsets[i], rb_cntl);
- ib_cntl = RREG32(mmSDMA0_GFX_IB_CNTL + sdma_offsets[i]);
- ib_cntl = REG_SET_FIELD(ib_cntl, SDMA0_GFX_IB_CNTL, IB_ENABLE, 0);
- WREG32(mmSDMA0_GFX_IB_CNTL + sdma_offsets[i], ib_cntl);
- }
+ rb_cntl = RREG32(mmSDMA0_GFX_RB_CNTL + reg_offset);
+ rb_cntl = REG_SET_FIELD(rb_cntl, SDMA0_GFX_RB_CNTL, RB_ENABLE, 0);
+ WREG32(mmSDMA0_GFX_RB_CNTL + reg_offset, rb_cntl);
+ ib_cntl = RREG32(mmSDMA0_GFX_IB_CNTL + reg_offset);
+ ib_cntl = REG_SET_FIELD(ib_cntl, SDMA0_GFX_IB_CNTL, IB_ENABLE, 0);
+ WREG32(mmSDMA0_GFX_IB_CNTL + reg_offset, ib_cntl);
}
/**
* sdma_v3_0_ctx_switch_enable - stop the async dma engines context switch
*
* @adev: amdgpu_device pointer
+ * @instance_id: SDMA engine instance ID
* @enable: enable/disable the DMA MEs context switch.
*
* Halt or unhalt the async dma engines context switch (VI).
*/
-static void sdma_v3_0_ctx_switch_enable(struct amdgpu_device *adev, bool enable)
+static void sdma_v3_0_ctx_switch_enable(struct amdgpu_device *adev,
+ const u32 instance_id,
+ const bool enable)
{
+ const u32 reg_offset = sdma_offsets[instance_id];
u32 f32_cntl, phase_quantum = 0;
- int i;
if (amdgpu_sdma_phase_quantum) {
unsigned value = amdgpu_sdma_phase_quantum;
@@ -563,206 +565,212 @@ static void sdma_v3_0_ctx_switch_enable(struct amdgpu_device *adev, bool enable)
unit << SDMA0_PHASE0_QUANTUM__UNIT__SHIFT;
}
- for (i = 0; i < adev->sdma.num_instances; i++) {
- f32_cntl = RREG32(mmSDMA0_CNTL + sdma_offsets[i]);
- if (enable) {
- f32_cntl = REG_SET_FIELD(f32_cntl, SDMA0_CNTL,
- AUTO_CTXSW_ENABLE, 1);
- f32_cntl = REG_SET_FIELD(f32_cntl, SDMA0_CNTL,
- ATC_L1_ENABLE, 1);
- if (amdgpu_sdma_phase_quantum) {
- WREG32(mmSDMA0_PHASE0_QUANTUM + sdma_offsets[i],
- phase_quantum);
- WREG32(mmSDMA0_PHASE1_QUANTUM + sdma_offsets[i],
- phase_quantum);
- }
- } else {
- f32_cntl = REG_SET_FIELD(f32_cntl, SDMA0_CNTL,
- AUTO_CTXSW_ENABLE, 0);
- f32_cntl = REG_SET_FIELD(f32_cntl, SDMA0_CNTL,
- ATC_L1_ENABLE, 1);
+ f32_cntl = RREG32(mmSDMA0_CNTL + reg_offset);
+ if (enable) {
+ f32_cntl = REG_SET_FIELD(f32_cntl, SDMA0_CNTL,
+ AUTO_CTXSW_ENABLE, 1);
+ f32_cntl = REG_SET_FIELD(f32_cntl, SDMA0_CNTL,
+ ATC_L1_ENABLE, 1);
+ if (amdgpu_sdma_phase_quantum) {
+ WREG32(mmSDMA0_PHASE0_QUANTUM + reg_offset,
+ phase_quantum);
+ WREG32(mmSDMA0_PHASE1_QUANTUM + reg_offset,
+ phase_quantum);
}
-
- WREG32(mmSDMA0_CNTL + sdma_offsets[i], f32_cntl);
+ } else {
+ f32_cntl = REG_SET_FIELD(f32_cntl, SDMA0_CNTL,
+ AUTO_CTXSW_ENABLE, 0);
+ f32_cntl = REG_SET_FIELD(f32_cntl, SDMA0_CNTL,
+ ATC_L1_ENABLE, 1);
}
+
+ WREG32(mmSDMA0_CNTL + reg_offset, f32_cntl);
}
/**
* sdma_v3_0_enable - stop the async dma engines
*
* @adev: amdgpu_device pointer
+ * @instance_id: SDMA engine instance ID
* @enable: enable/disable the DMA MEs.
*
* Halt or unhalt the async dma engines (VI).
*/
-static void sdma_v3_0_enable(struct amdgpu_device *adev, bool enable)
+static void sdma_v3_0_enable(struct amdgpu_device *adev,
+ const u32 instance_id,
+ const bool enable)
{
+ const u32 reg_offset = sdma_offsets[instance_id];
u32 f32_cntl;
- int i;
if (!enable) {
- sdma_v3_0_gfx_stop(adev);
+ sdma_v3_0_gfx_stop(adev, instance_id);
}
- for (i = 0; i < adev->sdma.num_instances; i++) {
- f32_cntl = RREG32(mmSDMA0_F32_CNTL + sdma_offsets[i]);
- if (enable)
- f32_cntl = REG_SET_FIELD(f32_cntl, SDMA0_F32_CNTL, HALT, 0);
- else
- f32_cntl = REG_SET_FIELD(f32_cntl, SDMA0_F32_CNTL, HALT, 1);
- WREG32(mmSDMA0_F32_CNTL + sdma_offsets[i], f32_cntl);
- }
+ f32_cntl = RREG32(mmSDMA0_F32_CNTL + reg_offset);
+ if (enable)
+ f32_cntl = REG_SET_FIELD(f32_cntl, SDMA0_F32_CNTL, HALT, 0);
+ else
+ f32_cntl = REG_SET_FIELD(f32_cntl, SDMA0_F32_CNTL, HALT, 1);
+ WREG32(mmSDMA0_F32_CNTL + reg_offset, f32_cntl);
}
/**
* sdma_v3_0_gfx_resume - setup and start the async dma engines
*
* @adev: amdgpu_device pointer
+ * @instance_id: SDMA engine instance ID
*
* Set up the gfx DMA ring buffers and enable them (VI).
* Returns 0 for success, error for failure.
*/
-static int sdma_v3_0_gfx_resume(struct amdgpu_device *adev)
+static int sdma_v3_0_gfx_resume(struct amdgpu_device *adev, const u32 instance_id)
{
- struct amdgpu_ring *ring;
+ struct amdgpu_ring *const ring = &adev->sdma.instance[instance_id].ring;
+ const u32 reg_offset = sdma_offsets[instance_id];
u32 rb_cntl, ib_cntl, wptr_poll_cntl;
u32 rb_bufsz;
u32 doorbell;
u64 wptr_gpu_addr;
- int i, j, r;
+ int j;
- for (i = 0; i < adev->sdma.num_instances; i++) {
- ring = &adev->sdma.instance[i].ring;
- amdgpu_ring_clear_ring(ring);
-
- mutex_lock(&adev->srbm_mutex);
- for (j = 0; j < 16; j++) {
- vi_srbm_select(adev, 0, 0, 0, j);
- /* SDMA GFX */
- WREG32(mmSDMA0_GFX_VIRTUAL_ADDR + sdma_offsets[i], 0);
- WREG32(mmSDMA0_GFX_APE1_CNTL + sdma_offsets[i], 0);
- }
- vi_srbm_select(adev, 0, 0, 0, 0);
- mutex_unlock(&adev->srbm_mutex);
+ amdgpu_ring_clear_ring(ring);
- WREG32(mmSDMA0_TILING_CONFIG + sdma_offsets[i],
- adev->gfx.config.gb_addr_config & 0x70);
+ mutex_lock(&adev->srbm_mutex);
+ for (j = 0; j < 16; j++) {
+ vi_srbm_select(adev, 0, 0, 0, j);
+ /* SDMA GFX */
+ WREG32(mmSDMA0_GFX_VIRTUAL_ADDR + reg_offset, 0);
+ WREG32(mmSDMA0_GFX_APE1_CNTL + reg_offset, 0);
+ }
+ vi_srbm_select(adev, 0, 0, 0, 0);
+ mutex_unlock(&adev->srbm_mutex);
+
+ WREG32(mmSDMA0_TILING_CONFIG + reg_offset,
+ adev->gfx.config.gb_addr_config & 0x70);
- WREG32(mmSDMA0_SEM_WAIT_FAIL_TIMER_CNTL + sdma_offsets[i], 0);
+ WREG32(mmSDMA0_SEM_WAIT_FAIL_TIMER_CNTL + reg_offset, 0);
- /* Set ring buffer size in dwords */
- rb_bufsz = order_base_2(ring->ring_size / 4);
- rb_cntl = RREG32(mmSDMA0_GFX_RB_CNTL + sdma_offsets[i]);
- rb_cntl = REG_SET_FIELD(rb_cntl, SDMA0_GFX_RB_CNTL, RB_SIZE, rb_bufsz);
+ /* Set ring buffer size in dwords */
+ rb_bufsz = order_base_2(ring->ring_size / 4);
+ rb_cntl = RREG32(mmSDMA0_GFX_RB_CNTL + reg_offset);
+ rb_cntl = REG_SET_FIELD(rb_cntl, SDMA0_GFX_RB_CNTL, RB_SIZE, rb_bufsz);
#ifdef __BIG_ENDIAN
- rb_cntl = REG_SET_FIELD(rb_cntl, SDMA0_GFX_RB_CNTL, RB_SWAP_ENABLE, 1);
- rb_cntl = REG_SET_FIELD(rb_cntl, SDMA0_GFX_RB_CNTL,
- RPTR_WRITEBACK_SWAP_ENABLE, 1);
+ rb_cntl = REG_SET_FIELD(rb_cntl, SDMA0_GFX_RB_CNTL, RB_SWAP_ENABLE, 1);
+ rb_cntl = REG_SET_FIELD(rb_cntl, SDMA0_GFX_RB_CNTL,
+ RPTR_WRITEBACK_SWAP_ENABLE, 1);
#endif
- WREG32(mmSDMA0_GFX_RB_CNTL + sdma_offsets[i], rb_cntl);
+ WREG32(mmSDMA0_GFX_RB_CNTL + reg_offset, rb_cntl);
- /* Initialize the ring buffer's read and write pointers */
- ring->wptr = 0;
- WREG32(mmSDMA0_GFX_RB_RPTR + sdma_offsets[i], 0);
- sdma_v3_0_ring_set_wptr(ring);
- WREG32(mmSDMA0_GFX_IB_RPTR + sdma_offsets[i], 0);
- WREG32(mmSDMA0_GFX_IB_OFFSET + sdma_offsets[i], 0);
+ /* Initialize the ring buffer's read and write pointers */
+ ring->wptr = 0;
+ WREG32(mmSDMA0_GFX_RB_RPTR + reg_offset, 0);
+ sdma_v3_0_ring_set_wptr(ring);
+ WREG32(mmSDMA0_GFX_IB_RPTR + reg_offset, 0);
+ WREG32(mmSDMA0_GFX_IB_OFFSET + reg_offset, 0);
- /* set the wb address whether it's enabled or not */
- WREG32(mmSDMA0_GFX_RB_RPTR_ADDR_HI + sdma_offsets[i],
- upper_32_bits(ring->rptr_gpu_addr) & 0xFFFFFFFF);
- WREG32(mmSDMA0_GFX_RB_RPTR_ADDR_LO + sdma_offsets[i],
- lower_32_bits(ring->rptr_gpu_addr) & 0xFFFFFFFC);
+ /* set the wb address whether it's enabled or not */
+ WREG32(mmSDMA0_GFX_RB_RPTR_ADDR_HI + reg_offset,
+ upper_32_bits(ring->rptr_gpu_addr) & 0xFFFFFFFF);
+ WREG32(mmSDMA0_GFX_RB_RPTR_ADDR_LO + reg_offset,
+ lower_32_bits(ring->rptr_gpu_addr) & 0xFFFFFFFC);
- rb_cntl = REG_SET_FIELD(rb_cntl, SDMA0_GFX_RB_CNTL, RPTR_WRITEBACK_ENABLE, 1);
+ rb_cntl = REG_SET_FIELD(rb_cntl, SDMA0_GFX_RB_CNTL, RPTR_WRITEBACK_ENABLE, 1);
- WREG32(mmSDMA0_GFX_RB_BASE + sdma_offsets[i], ring->gpu_addr >> 8);
- WREG32(mmSDMA0_GFX_RB_BASE_HI + sdma_offsets[i], ring->gpu_addr >> 40);
+ WREG32(mmSDMA0_GFX_RB_BASE + reg_offset, ring->gpu_addr >> 8);
+ WREG32(mmSDMA0_GFX_RB_BASE_HI + reg_offset, ring->gpu_addr >> 40);
- doorbell = RREG32(mmSDMA0_GFX_DOORBELL + sdma_offsets[i]);
+ doorbell = RREG32(mmSDMA0_GFX_DOORBELL + reg_offset);
- if (ring->use_doorbell) {
- doorbell = REG_SET_FIELD(doorbell, SDMA0_GFX_DOORBELL,
- OFFSET, ring->doorbell_index);
- doorbell = REG_SET_FIELD(doorbell, SDMA0_GFX_DOORBELL, ENABLE, 1);
- } else {
- doorbell = REG_SET_FIELD(doorbell, SDMA0_GFX_DOORBELL, ENABLE, 0);
- }
- WREG32(mmSDMA0_GFX_DOORBELL + sdma_offsets[i], doorbell);
-
- /* setup the wptr shadow polling */
- wptr_gpu_addr = ring->wptr_gpu_addr;
-
- WREG32(mmSDMA0_GFX_RB_WPTR_POLL_ADDR_LO + sdma_offsets[i],
- lower_32_bits(wptr_gpu_addr));
- WREG32(mmSDMA0_GFX_RB_WPTR_POLL_ADDR_HI + sdma_offsets[i],
- upper_32_bits(wptr_gpu_addr));
- wptr_poll_cntl = RREG32(mmSDMA0_GFX_RB_WPTR_POLL_CNTL + sdma_offsets[i]);
- if (ring->use_pollmem) {
- /*wptr polling is not enough fast, directly clean the wptr register */
- WREG32(mmSDMA0_GFX_RB_WPTR + sdma_offsets[i], 0);
- wptr_poll_cntl = REG_SET_FIELD(wptr_poll_cntl,
- SDMA0_GFX_RB_WPTR_POLL_CNTL,
- ENABLE, 1);
- } else {
- wptr_poll_cntl = REG_SET_FIELD(wptr_poll_cntl,
- SDMA0_GFX_RB_WPTR_POLL_CNTL,
- ENABLE, 0);
- }
- WREG32(mmSDMA0_GFX_RB_WPTR_POLL_CNTL + sdma_offsets[i], wptr_poll_cntl);
+ if (ring->use_doorbell) {
+ doorbell = REG_SET_FIELD(doorbell, SDMA0_GFX_DOORBELL,
+ OFFSET, ring->doorbell_index);
+ doorbell = REG_SET_FIELD(doorbell, SDMA0_GFX_DOORBELL, ENABLE, 1);
+ } else {
+ doorbell = REG_SET_FIELD(doorbell, SDMA0_GFX_DOORBELL, ENABLE, 0);
+ }
+ WREG32(mmSDMA0_GFX_DOORBELL + reg_offset, doorbell);
+
+ /* setup the wptr shadow polling */
+ wptr_gpu_addr = ring->wptr_gpu_addr;
+
+ WREG32(mmSDMA0_GFX_RB_WPTR_POLL_ADDR_LO + reg_offset,
+ lower_32_bits(wptr_gpu_addr));
+ WREG32(mmSDMA0_GFX_RB_WPTR_POLL_ADDR_HI + reg_offset,
+ upper_32_bits(wptr_gpu_addr));
+ wptr_poll_cntl = RREG32(mmSDMA0_GFX_RB_WPTR_POLL_CNTL + reg_offset);
+ if (ring->use_pollmem) {
+ /*wptr polling is not enough fast, directly clean the wptr register */
+ WREG32(mmSDMA0_GFX_RB_WPTR + reg_offset, 0);
+ wptr_poll_cntl = REG_SET_FIELD(wptr_poll_cntl,
+ SDMA0_GFX_RB_WPTR_POLL_CNTL,
+ ENABLE, 1);
+ } else {
+ wptr_poll_cntl = REG_SET_FIELD(wptr_poll_cntl,
+ SDMA0_GFX_RB_WPTR_POLL_CNTL,
+ ENABLE, 0);
+ }
+ WREG32(mmSDMA0_GFX_RB_WPTR_POLL_CNTL + reg_offset, wptr_poll_cntl);
- /* enable DMA RB */
- rb_cntl = REG_SET_FIELD(rb_cntl, SDMA0_GFX_RB_CNTL, RB_ENABLE, 1);
- WREG32(mmSDMA0_GFX_RB_CNTL + sdma_offsets[i], rb_cntl);
+ /* enable DMA RB */
+ rb_cntl = REG_SET_FIELD(rb_cntl, SDMA0_GFX_RB_CNTL, RB_ENABLE, 1);
+ WREG32(mmSDMA0_GFX_RB_CNTL + reg_offset, rb_cntl);
- ib_cntl = RREG32(mmSDMA0_GFX_IB_CNTL + sdma_offsets[i]);
- ib_cntl = REG_SET_FIELD(ib_cntl, SDMA0_GFX_IB_CNTL, IB_ENABLE, 1);
+ ib_cntl = RREG32(mmSDMA0_GFX_IB_CNTL + reg_offset);
+ ib_cntl = REG_SET_FIELD(ib_cntl, SDMA0_GFX_IB_CNTL, IB_ENABLE, 1);
#ifdef __BIG_ENDIAN
- ib_cntl = REG_SET_FIELD(ib_cntl, SDMA0_GFX_IB_CNTL, IB_SWAP_ENABLE, 1);
+ ib_cntl = REG_SET_FIELD(ib_cntl, SDMA0_GFX_IB_CNTL, IB_SWAP_ENABLE, 1);
#endif
- /* enable DMA IBs */
- WREG32(mmSDMA0_GFX_IB_CNTL + sdma_offsets[i], ib_cntl);
- }
+ /* enable DMA IBs */
+ WREG32(mmSDMA0_GFX_IB_CNTL + reg_offset, ib_cntl);
/* unhalt the MEs */
- sdma_v3_0_enable(adev, true);
+ sdma_v3_0_enable(adev, instance_id, true);
/* enable sdma ring preemption */
- sdma_v3_0_ctx_switch_enable(adev, true);
+ sdma_v3_0_ctx_switch_enable(adev, instance_id, true);
- for (i = 0; i < adev->sdma.num_instances; i++) {
- ring = &adev->sdma.instance[i].ring;
- r = amdgpu_ring_test_helper(ring);
- if (r)
- return r;
- }
-
- return 0;
+ return amdgpu_ring_test_helper(ring);
}
/**
* sdma_v3_0_start - setup and start the async dma engines
*
* @adev: amdgpu_device pointer
+ * @instance_id: SDMA engine instance ID
*
* Set up the DMA engines and enable them (VI).
* Returns 0 for success, error for failure.
*/
-static int sdma_v3_0_start(struct amdgpu_device *adev)
+static int sdma_v3_0_start(struct amdgpu_device *adev, const u32 instance_id)
{
int r;
/* disable sdma engine before programing it */
- sdma_v3_0_ctx_switch_enable(adev, false);
- sdma_v3_0_enable(adev, false);
+ sdma_v3_0_ctx_switch_enable(adev, instance_id, false);
+ sdma_v3_0_enable(adev, instance_id, false);
/* start the gfx rings and rlc compute queues */
- r = sdma_v3_0_gfx_resume(adev);
+ r = sdma_v3_0_gfx_resume(adev, instance_id);
if (r)
return r;
return 0;
}
+/**
+ * sdma_v3_0_stop() - Stop an SDMA engine
+ *
+ * @adev: amdgpu_device pointer
+ * @instance_id: SDMA engine instance ID
+ *
+ * Stop the given SDMA engine instance (VI).
+ */
+static void sdma_v3_0_stop(struct amdgpu_device *adev, const u32 instance_id)
+{
+ sdma_v3_0_ctx_switch_enable(adev, instance_id, false);
+ sdma_v3_0_enable(adev, instance_id, false);
+}
+
/**
* sdma_v3_0_ring_test_ring - simple async dma engine test
*
@@ -1150,14 +1158,17 @@ static int sdma_v3_0_sw_fini(struct amdgpu_ip_block *ip_block)
static int sdma_v3_0_hw_init(struct amdgpu_ip_block *ip_block)
{
- int r;
+
struct amdgpu_device *adev = ip_block->adev;
+ int i, r;
sdma_v3_0_init_golden_registers(adev);
- r = sdma_v3_0_start(adev);
- if (r)
- return r;
+ for (i = 0; i < adev->sdma.num_instances; ++i) {
+ r = sdma_v3_0_start(adev, i);
+ if (r)
+ return r;
+ }
sdma_v3_0_set_buffer_funcs(adev);
@@ -1167,9 +1178,10 @@ static int sdma_v3_0_hw_init(struct amdgpu_ip_block *ip_block)
static int sdma_v3_0_hw_fini(struct amdgpu_ip_block *ip_block)
{
struct amdgpu_device *adev = ip_block->adev;
+ int i;
- sdma_v3_0_ctx_switch_enable(adev, false);
- sdma_v3_0_enable(adev, false);
+ for (i = 0; i < adev->sdma.num_instances; ++i)
+ sdma_v3_0_stop(adev, i);
return 0;
}
--
2.55.0
^ permalink raw reply related [flat|nested] 17+ messages in thread* [PATCH 08/12] drm/amdgpu/sdma: Refactor SDMA v3.0 clock gating functions to be per-instance
2026-09-07 20:33 [PATCH 00/12] RFC: drm/amdgpu/sdma: Refactor SDMA v4 and older functions to be per-instance Timur Kristóf
` (6 preceding siblings ...)
2026-09-07 20:33 ` [PATCH 07/12] drm/amdgpu/sdma: Refactor SDMA v3.0 functions to be per instance Timur Kristóf
@ 2026-09-07 20:33 ` Timur Kristóf
2026-09-07 20:33 ` [PATCH 09/12] drm/amdgpu/sdma: Refactor SDMA v3.0 golden registers " Timur Kristóf
` (4 subsequent siblings)
12 siblings, 0 replies; 17+ messages in thread
From: Timur Kristóf @ 2026-09-07 20:33 UTC (permalink / raw)
To: amd-gfx, Marek Olšák, Alex Deucher,
Christian König, Tvrtko Ursulin, pierre-eric.pelloux-prayer,
Natalie Vock, Lijo Lazar, Felix Kuehling
Cc: Timur Kristóf
Refactor clock gating functions to take the SDMA engine
instance ID as an argument and only affect one SDMA engine
instance at once.
Signed-off-by: Timur Kristóf <timur.kristof@gmail.com>
---
drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c | 81 +++++++++++++-------------
1 file changed, 39 insertions(+), 42 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c
index 6213a0c77590..3d0f94372e04 100644
--- a/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c
@@ -1345,66 +1345,60 @@ static int sdma_v3_0_process_illegal_inst_irq(struct amdgpu_device *adev,
static void sdma_v3_0_update_sdma_medium_grain_clock_gating(
struct amdgpu_device *adev,
- bool enable)
+ const u32 instance_id,
+ const bool enable)
{
+ const u32 reg_offset = sdma_offsets[instance_id];
uint32_t temp, data;
- int i;
if (enable && (adev->cg_flags & AMD_CG_SUPPORT_SDMA_MGCG)) {
- for (i = 0; i < adev->sdma.num_instances; i++) {
- temp = data = RREG32(mmSDMA0_CLK_CTRL + sdma_offsets[i]);
- data &= ~(SDMA0_CLK_CTRL__SOFT_OVERRIDE7_MASK |
- SDMA0_CLK_CTRL__SOFT_OVERRIDE6_MASK |
- SDMA0_CLK_CTRL__SOFT_OVERRIDE5_MASK |
- SDMA0_CLK_CTRL__SOFT_OVERRIDE4_MASK |
- SDMA0_CLK_CTRL__SOFT_OVERRIDE3_MASK |
- SDMA0_CLK_CTRL__SOFT_OVERRIDE2_MASK |
- SDMA0_CLK_CTRL__SOFT_OVERRIDE1_MASK |
- SDMA0_CLK_CTRL__SOFT_OVERRIDE0_MASK);
- if (data != temp)
- WREG32(mmSDMA0_CLK_CTRL + sdma_offsets[i], data);
- }
- } else {
- for (i = 0; i < adev->sdma.num_instances; i++) {
- temp = data = RREG32(mmSDMA0_CLK_CTRL + sdma_offsets[i]);
- data |= SDMA0_CLK_CTRL__SOFT_OVERRIDE7_MASK |
+ temp = data = RREG32(mmSDMA0_CLK_CTRL + reg_offset);
+ data &= ~(SDMA0_CLK_CTRL__SOFT_OVERRIDE7_MASK |
SDMA0_CLK_CTRL__SOFT_OVERRIDE6_MASK |
SDMA0_CLK_CTRL__SOFT_OVERRIDE5_MASK |
SDMA0_CLK_CTRL__SOFT_OVERRIDE4_MASK |
SDMA0_CLK_CTRL__SOFT_OVERRIDE3_MASK |
SDMA0_CLK_CTRL__SOFT_OVERRIDE2_MASK |
SDMA0_CLK_CTRL__SOFT_OVERRIDE1_MASK |
- SDMA0_CLK_CTRL__SOFT_OVERRIDE0_MASK;
-
- if (data != temp)
- WREG32(mmSDMA0_CLK_CTRL + sdma_offsets[i], data);
- }
+ SDMA0_CLK_CTRL__SOFT_OVERRIDE0_MASK);
+ if (data != temp)
+ WREG32(mmSDMA0_CLK_CTRL + reg_offset, data);
+ } else {
+ temp = data = RREG32(mmSDMA0_CLK_CTRL + reg_offset);
+ data |= SDMA0_CLK_CTRL__SOFT_OVERRIDE7_MASK |
+ SDMA0_CLK_CTRL__SOFT_OVERRIDE6_MASK |
+ SDMA0_CLK_CTRL__SOFT_OVERRIDE5_MASK |
+ SDMA0_CLK_CTRL__SOFT_OVERRIDE4_MASK |
+ SDMA0_CLK_CTRL__SOFT_OVERRIDE3_MASK |
+ SDMA0_CLK_CTRL__SOFT_OVERRIDE2_MASK |
+ SDMA0_CLK_CTRL__SOFT_OVERRIDE1_MASK |
+ SDMA0_CLK_CTRL__SOFT_OVERRIDE0_MASK;
+
+ if (data != temp)
+ WREG32(mmSDMA0_CLK_CTRL + reg_offset, data);
}
}
static void sdma_v3_0_update_sdma_medium_grain_light_sleep(
struct amdgpu_device *adev,
- bool enable)
+ const u32 instance_id,
+ const bool enable)
{
+ const u32 reg_offset = sdma_offsets[instance_id];
uint32_t temp, data;
- int i;
if (enable && (adev->cg_flags & AMD_CG_SUPPORT_SDMA_LS)) {
- for (i = 0; i < adev->sdma.num_instances; i++) {
- temp = data = RREG32(mmSDMA0_POWER_CNTL + sdma_offsets[i]);
- data |= SDMA0_POWER_CNTL__MEM_POWER_OVERRIDE_MASK;
+ temp = data = RREG32(mmSDMA0_POWER_CNTL + reg_offset);
+ data |= SDMA0_POWER_CNTL__MEM_POWER_OVERRIDE_MASK;
- if (temp != data)
- WREG32(mmSDMA0_POWER_CNTL + sdma_offsets[i], data);
- }
+ if (temp != data)
+ WREG32(mmSDMA0_POWER_CNTL + reg_offset, data);
} else {
- for (i = 0; i < adev->sdma.num_instances; i++) {
- temp = data = RREG32(mmSDMA0_POWER_CNTL + sdma_offsets[i]);
- data &= ~SDMA0_POWER_CNTL__MEM_POWER_OVERRIDE_MASK;
+ temp = data = RREG32(mmSDMA0_POWER_CNTL + reg_offset);
+ data &= ~SDMA0_POWER_CNTL__MEM_POWER_OVERRIDE_MASK;
- if (temp != data)
- WREG32(mmSDMA0_POWER_CNTL + sdma_offsets[i], data);
- }
+ if (temp != data)
+ WREG32(mmSDMA0_POWER_CNTL + reg_offset, data);
}
}
@@ -1412,6 +1406,7 @@ static int sdma_v3_0_set_clockgating_state(struct amdgpu_ip_block *ip_block,
enum amd_clockgating_state state)
{
struct amdgpu_device *adev = ip_block->adev;
+ int i;
if (amdgpu_sriov_vf(adev))
return 0;
@@ -1420,10 +1415,12 @@ static int sdma_v3_0_set_clockgating_state(struct amdgpu_ip_block *ip_block,
case CHIP_FIJI:
case CHIP_CARRIZO:
case CHIP_STONEY:
- sdma_v3_0_update_sdma_medium_grain_clock_gating(adev,
- state == AMD_CG_STATE_GATE);
- sdma_v3_0_update_sdma_medium_grain_light_sleep(adev,
- state == AMD_CG_STATE_GATE);
+ for (i = 0; i < adev->sdma.num_instances; i++) {
+ sdma_v3_0_update_sdma_medium_grain_clock_gating(
+ adev, i, state == AMD_CG_STATE_GATE);
+ sdma_v3_0_update_sdma_medium_grain_light_sleep(
+ adev, i, state == AMD_CG_STATE_GATE);
+ }
break;
default:
break;
--
2.55.0
^ permalink raw reply related [flat|nested] 17+ messages in thread* [PATCH 09/12] drm/amdgpu/sdma: Refactor SDMA v3.0 golden registers to be per-instance
2026-09-07 20:33 [PATCH 00/12] RFC: drm/amdgpu/sdma: Refactor SDMA v4 and older functions to be per-instance Timur Kristóf
` (7 preceding siblings ...)
2026-09-07 20:33 ` [PATCH 08/12] drm/amdgpu/sdma: Refactor SDMA v3.0 clock gating functions to be per-instance Timur Kristóf
@ 2026-09-07 20:33 ` Timur Kristóf
2026-09-07 20:33 ` [PATCH 10/12] drm/amdgpu/sdma: Refactor SDMA v4.0 functions to be per instance Timur Kristóf
` (3 subsequent siblings)
12 siblings, 0 replies; 17+ messages in thread
From: Timur Kristóf @ 2026-09-07 20:33 UTC (permalink / raw)
To: amd-gfx, Marek Olšák, Alex Deucher,
Christian König, Tvrtko Ursulin, pierre-eric.pelloux-prayer,
Natalie Vock, Lijo Lazar, Felix Kuehling
Cc: Timur Kristóf
Refactor golden registers initialization to take the SDMA
engine instance ID as an argument and only program the
golden registers for one SDMA engine at once.
Signed-off-by: Timur Kristóf <timur.kristof@gmail.com>
---
drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c | 182 +++++++++++++++++--------
1 file changed, 127 insertions(+), 55 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c
index 3d0f94372e04..4e6fa9db9948 100644
--- a/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c
@@ -76,13 +76,15 @@ static const u32 sdma_offsets[SDMA_MAX_INSTANCE] =
SDMA1_REGISTER_OFFSET
};
-static const u32 golden_settings_tonga_a11[] =
-{
+static const u32 golden_settings_tonga_a11_sdma0[] = {
mmSDMA0_CHICKEN_BITS, 0xfc910007, 0x00810007,
mmSDMA0_CLK_CTRL, 0xff000fff, 0x00000000,
mmSDMA0_GFX_IB_CNTL, 0x800f0111, 0x00000100,
mmSDMA0_RLC0_IB_CNTL, 0x800f0111, 0x00000100,
mmSDMA0_RLC1_IB_CNTL, 0x800f0111, 0x00000100,
+};
+
+static const u32 golden_settings_tonga_a11_sdma1[] = {
mmSDMA1_CHICKEN_BITS, 0xfc910007, 0x00810007,
mmSDMA1_CLK_CTRL, 0xff000fff, 0x00000000,
mmSDMA1_GFX_IB_CNTL, 0x800f0111, 0x00000100,
@@ -90,37 +92,45 @@ static const u32 golden_settings_tonga_a11[] =
mmSDMA1_RLC1_IB_CNTL, 0x800f0111, 0x00000100,
};
-static const u32 tonga_mgcg_cgcg_init[] =
-{
+static const u32 tonga_mgcg_cgcg_init_sdma0[] = {
mmSDMA0_CLK_CTRL, 0xff000ff0, 0x00000100,
- mmSDMA1_CLK_CTRL, 0xff000ff0, 0x00000100
};
-static const u32 golden_settings_fiji_a10[] =
-{
+static const u32 tonga_mgcg_cgcg_init_sdma1[] = {
+ mmSDMA1_CLK_CTRL, 0xff000ff0, 0x00000100,
+};
+
+static const u32 golden_settings_fiji_a10_sdma0[] = {
mmSDMA0_CHICKEN_BITS, 0xfc910007, 0x00810007,
mmSDMA0_GFX_IB_CNTL, 0x800f0111, 0x00000100,
mmSDMA0_RLC0_IB_CNTL, 0x800f0111, 0x00000100,
mmSDMA0_RLC1_IB_CNTL, 0x800f0111, 0x00000100,
+};
+
+static const u32 golden_settings_fiji_a10_sdma1[] = {
mmSDMA1_CHICKEN_BITS, 0xfc910007, 0x00810007,
mmSDMA1_GFX_IB_CNTL, 0x800f0111, 0x00000100,
mmSDMA1_RLC0_IB_CNTL, 0x800f0111, 0x00000100,
mmSDMA1_RLC1_IB_CNTL, 0x800f0111, 0x00000100,
};
-static const u32 fiji_mgcg_cgcg_init[] =
-{
+static const u32 fiji_mgcg_cgcg_init_sdma0[] = {
mmSDMA0_CLK_CTRL, 0xff000ff0, 0x00000100,
- mmSDMA1_CLK_CTRL, 0xff000ff0, 0x00000100
};
-static const u32 golden_settings_polaris11_a11[] =
-{
+static const u32 fiji_mgcg_cgcg_init_sdma1[] = {
+ mmSDMA1_CLK_CTRL, 0xff000ff0, 0x00000100,
+};
+
+static const u32 golden_settings_polaris11_a11_sdma0[] = {
mmSDMA0_CHICKEN_BITS, 0xfc910007, 0x00810007,
mmSDMA0_CLK_CTRL, 0xff000fff, 0x00000000,
mmSDMA0_GFX_IB_CNTL, 0x800f0111, 0x00000100,
mmSDMA0_RLC0_IB_CNTL, 0x800f0111, 0x00000100,
mmSDMA0_RLC1_IB_CNTL, 0x800f0111, 0x00000100,
+};
+
+static const u32 golden_settings_polaris11_a11_sdma1[] = {
mmSDMA1_CHICKEN_BITS, 0xfc910007, 0x00810007,
mmSDMA1_CLK_CTRL, 0xff000fff, 0x00000000,
mmSDMA1_GFX_IB_CNTL, 0x800f0111, 0x00000100,
@@ -128,13 +138,15 @@ static const u32 golden_settings_polaris11_a11[] =
mmSDMA1_RLC1_IB_CNTL, 0x800f0111, 0x00000100,
};
-static const u32 golden_settings_polaris10_a11[] =
-{
+static const u32 golden_settings_polaris10_a11_sdma0[] = {
mmSDMA0_CHICKEN_BITS, 0xfc910007, 0x00810007,
mmSDMA0_CLK_CTRL, 0xff000fff, 0x00000000,
mmSDMA0_GFX_IB_CNTL, 0x800f0111, 0x00000100,
mmSDMA0_RLC0_IB_CNTL, 0x800f0111, 0x00000100,
mmSDMA0_RLC1_IB_CNTL, 0x800f0111, 0x00000100,
+};
+
+static const u32 golden_settings_polaris10_a11_sdma1[] = {
mmSDMA1_CHICKEN_BITS, 0xfc910007, 0x00810007,
mmSDMA1_CLK_CTRL, 0xff000fff, 0x00000000,
mmSDMA1_GFX_IB_CNTL, 0x800f0111, 0x00000100,
@@ -142,14 +154,16 @@ static const u32 golden_settings_polaris10_a11[] =
mmSDMA1_RLC1_IB_CNTL, 0x800f0111, 0x00000100,
};
-static const u32 cz_golden_settings_a11[] =
-{
+static const u32 cz_golden_settings_a11_sdma0[] = {
mmSDMA0_CHICKEN_BITS, 0xfc910007, 0x00810007,
mmSDMA0_CLK_CTRL, 0xff000fff, 0x00000000,
mmSDMA0_GFX_IB_CNTL, 0x00000100, 0x00000100,
mmSDMA0_POWER_CNTL, 0x00000800, 0x0003c800,
mmSDMA0_RLC0_IB_CNTL, 0x00000100, 0x00000100,
mmSDMA0_RLC1_IB_CNTL, 0x00000100, 0x00000100,
+};
+
+static const u32 cz_golden_settings_a11_sdma1[] = {
mmSDMA1_CHICKEN_BITS, 0xfc910007, 0x00810007,
mmSDMA1_CLK_CTRL, 0xff000fff, 0x00000000,
mmSDMA1_GFX_IB_CNTL, 0x00000100, 0x00000100,
@@ -158,22 +172,22 @@ static const u32 cz_golden_settings_a11[] =
mmSDMA1_RLC1_IB_CNTL, 0x00000100, 0x00000100,
};
-static const u32 cz_mgcg_cgcg_init[] =
-{
+static const u32 cz_mgcg_cgcg_init_sdma0[] = {
mmSDMA0_CLK_CTRL, 0xff000ff0, 0x00000100,
- mmSDMA1_CLK_CTRL, 0xff000ff0, 0x00000100
};
-static const u32 stoney_golden_settings_a11[] =
-{
+static const u32 cz_mgcg_cgcg_init_sdma1[] = {
+ mmSDMA1_CLK_CTRL, 0xff000ff0, 0x00000100,
+};
+
+static const u32 stoney_golden_settings_a11_sdma0[] = {
mmSDMA0_GFX_IB_CNTL, 0x00000100, 0x00000100,
mmSDMA0_POWER_CNTL, 0x00000800, 0x0003c800,
mmSDMA0_RLC0_IB_CNTL, 0x00000100, 0x00000100,
mmSDMA0_RLC1_IB_CNTL, 0x00000100, 0x00000100,
};
-static const u32 stoney_mgcg_cgcg_init[] =
-{
+static const u32 stoney_mgcg_cgcg_init_sdma0[] = {
mmSDMA0_CLK_CTRL, 0xffffffff, 0x00000100,
};
@@ -194,52 +208,110 @@ static const u32 stoney_mgcg_cgcg_init[] =
* buffers.
*/
-static void sdma_v3_0_init_golden_registers(struct amdgpu_device *adev)
+static void sdma_v3_0_init_golden_registers(struct amdgpu_device *adev, const u32 instance_id)
{
+ ASSERT(instance_id < adev->sdma.num_instances);
+
switch (adev->asic_type) {
case CHIP_FIJI:
- amdgpu_device_program_register_sequence(adev,
- fiji_mgcg_cgcg_init,
- ARRAY_SIZE(fiji_mgcg_cgcg_init));
- amdgpu_device_program_register_sequence(adev,
- golden_settings_fiji_a10,
- ARRAY_SIZE(golden_settings_fiji_a10));
+ if (instance_id == 0) {
+ amdgpu_device_program_register_sequence(
+ adev,
+ fiji_mgcg_cgcg_init_sdma0,
+ ARRAY_SIZE(fiji_mgcg_cgcg_init_sdma0));
+ amdgpu_device_program_register_sequence(
+ adev,
+ golden_settings_fiji_a10_sdma0,
+ ARRAY_SIZE(golden_settings_fiji_a10_sdma0));
+ } else {
+ amdgpu_device_program_register_sequence(
+ adev,
+ fiji_mgcg_cgcg_init_sdma1,
+ ARRAY_SIZE(fiji_mgcg_cgcg_init_sdma1));
+ amdgpu_device_program_register_sequence(
+ adev,
+ golden_settings_fiji_a10_sdma1,
+ ARRAY_SIZE(golden_settings_fiji_a10_sdma1));
+ }
break;
case CHIP_TONGA:
- amdgpu_device_program_register_sequence(adev,
- tonga_mgcg_cgcg_init,
- ARRAY_SIZE(tonga_mgcg_cgcg_init));
- amdgpu_device_program_register_sequence(adev,
- golden_settings_tonga_a11,
- ARRAY_SIZE(golden_settings_tonga_a11));
+ if (instance_id == 0) {
+ amdgpu_device_program_register_sequence(
+ adev,
+ tonga_mgcg_cgcg_init_sdma0,
+ ARRAY_SIZE(tonga_mgcg_cgcg_init_sdma0));
+ amdgpu_device_program_register_sequence(
+ adev,
+ golden_settings_tonga_a11_sdma0,
+ ARRAY_SIZE(golden_settings_tonga_a11_sdma0));
+ } else {
+ amdgpu_device_program_register_sequence(
+ adev,
+ tonga_mgcg_cgcg_init_sdma1,
+ ARRAY_SIZE(tonga_mgcg_cgcg_init_sdma1));
+ amdgpu_device_program_register_sequence(
+ adev,
+ golden_settings_tonga_a11_sdma1,
+ ARRAY_SIZE(golden_settings_tonga_a11_sdma1));
+ }
break;
case CHIP_POLARIS11:
case CHIP_POLARIS12:
case CHIP_VEGAM:
- amdgpu_device_program_register_sequence(adev,
- golden_settings_polaris11_a11,
- ARRAY_SIZE(golden_settings_polaris11_a11));
+ if (instance_id == 0) {
+ amdgpu_device_program_register_sequence(
+ adev,
+ golden_settings_polaris11_a11_sdma0,
+ ARRAY_SIZE(golden_settings_polaris11_a11_sdma0));
+ } else {
+ amdgpu_device_program_register_sequence(
+ adev,
+ golden_settings_polaris11_a11_sdma1,
+ ARRAY_SIZE(golden_settings_polaris11_a11_sdma1));
+ }
break;
case CHIP_POLARIS10:
- amdgpu_device_program_register_sequence(adev,
- golden_settings_polaris10_a11,
- ARRAY_SIZE(golden_settings_polaris10_a11));
+ if (instance_id == 0) {
+ amdgpu_device_program_register_sequence(
+ adev,
+ golden_settings_polaris10_a11_sdma0,
+ ARRAY_SIZE(golden_settings_polaris10_a11_sdma0));
+ } else {
+ amdgpu_device_program_register_sequence(
+ adev,
+ golden_settings_polaris10_a11_sdma1,
+ ARRAY_SIZE(golden_settings_polaris10_a11_sdma1));
+ }
break;
case CHIP_CARRIZO:
- amdgpu_device_program_register_sequence(adev,
- cz_mgcg_cgcg_init,
- ARRAY_SIZE(cz_mgcg_cgcg_init));
- amdgpu_device_program_register_sequence(adev,
- cz_golden_settings_a11,
- ARRAY_SIZE(cz_golden_settings_a11));
+ if (instance_id == 0) {
+ amdgpu_device_program_register_sequence(
+ adev,
+ cz_mgcg_cgcg_init_sdma0,
+ ARRAY_SIZE(cz_mgcg_cgcg_init_sdma0));
+ amdgpu_device_program_register_sequence(
+ adev,
+ cz_golden_settings_a11_sdma0,
+ ARRAY_SIZE(cz_golden_settings_a11_sdma0));
+ } else {
+ amdgpu_device_program_register_sequence(
+ adev,
+ cz_mgcg_cgcg_init_sdma1,
+ ARRAY_SIZE(cz_mgcg_cgcg_init_sdma1));
+ amdgpu_device_program_register_sequence(
+ adev,
+ cz_golden_settings_a11_sdma1,
+ ARRAY_SIZE(cz_golden_settings_a11_sdma1));
+ }
break;
case CHIP_STONEY:
+ amdgpu_device_program_register_sequence(
+ adev,
+ stoney_mgcg_cgcg_init_sdma0,
+ ARRAY_SIZE(stoney_mgcg_cgcg_init_sdma0));
amdgpu_device_program_register_sequence(adev,
- stoney_mgcg_cgcg_init,
- ARRAY_SIZE(stoney_mgcg_cgcg_init));
- amdgpu_device_program_register_sequence(adev,
- stoney_golden_settings_a11,
- ARRAY_SIZE(stoney_golden_settings_a11));
+ stoney_golden_settings_a11_sdma0,
+ ARRAY_SIZE(stoney_golden_settings_a11_sdma0));
break;
default:
break;
@@ -745,6 +817,8 @@ static int sdma_v3_0_start(struct amdgpu_device *adev, const u32 instance_id)
{
int r;
+ sdma_v3_0_init_golden_registers(adev, instance_id);
+
/* disable sdma engine before programing it */
sdma_v3_0_ctx_switch_enable(adev, instance_id, false);
sdma_v3_0_enable(adev, instance_id, false);
@@ -1162,8 +1236,6 @@ static int sdma_v3_0_hw_init(struct amdgpu_ip_block *ip_block)
struct amdgpu_device *adev = ip_block->adev;
int i, r;
- sdma_v3_0_init_golden_registers(adev);
-
for (i = 0; i < adev->sdma.num_instances; ++i) {
r = sdma_v3_0_start(adev, i);
if (r)
--
2.55.0
^ permalink raw reply related [flat|nested] 17+ messages in thread* [PATCH 10/12] drm/amdgpu/sdma: Refactor SDMA v4.0 functions to be per instance
2026-09-07 20:33 [PATCH 00/12] RFC: drm/amdgpu/sdma: Refactor SDMA v4 and older functions to be per-instance Timur Kristóf
` (8 preceding siblings ...)
2026-09-07 20:33 ` [PATCH 09/12] drm/amdgpu/sdma: Refactor SDMA v3.0 golden registers " Timur Kristóf
@ 2026-09-07 20:33 ` Timur Kristóf
2026-09-08 7:41 ` Tvrtko Ursulin
2026-09-07 20:33 ` [PATCH 11/12] drm/amdgpu/sdma: Refactor SDMA v4.0 clock gating functions to be per-instance Timur Kristóf
` (2 subsequent siblings)
12 siblings, 1 reply; 17+ messages in thread
From: Timur Kristóf @ 2026-09-07 20:33 UTC (permalink / raw)
To: amd-gfx, Marek Olšák, Alex Deucher,
Christian König, Tvrtko Ursulin, pierre-eric.pelloux-prayer,
Natalie Vock, Lijo Lazar, Felix Kuehling
Cc: Timur Kristóf
This prepares the code for implementing recovery for SDMA 4.0.
Reorganize the SDMA 4.0 code so that the functions that are
responsible for managing the SDMA engines take an instance ID
as an argument.
This makes it possible to manage the SDMA instances
independently of each other, which will enable us to
also use these functions to implement resetting and
recovering them independently.
Signed-off-by: Timur Kristóf <timur.kristof@gmail.com>
---
drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c | 253 +++++++++++++------------
1 file changed, 131 insertions(+), 122 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c
index bdd140887e10..038e1ee8ff4c 100644
--- a/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c
@@ -915,60 +915,61 @@ static void sdma_v4_0_ring_emit_fence(struct amdgpu_ring *ring, u64 addr, u64 se
* sdma_v4_0_gfx_enable - enable the gfx async dma engines
*
* @adev: amdgpu_device pointer
+ * @instance_id: SDMA engine instance ID
* @enable: enable SDMA RB/IB
* control the gfx async dma ring buffers (VEGA10).
*/
-static void sdma_v4_0_gfx_enable(struct amdgpu_device *adev, bool enable)
+static void sdma_v4_0_gfx_enable(struct amdgpu_device *adev,
+ const u32 instance_id,
+ const bool enable)
{
u32 rb_cntl, ib_cntl;
- int i;
- for (i = 0; i < adev->sdma.num_instances; i++) {
- rb_cntl = RREG32_SDMA(i, mmSDMA0_GFX_RB_CNTL);
- rb_cntl = REG_SET_FIELD(rb_cntl, SDMA0_GFX_RB_CNTL, RB_ENABLE, enable ? 1 : 0);
- WREG32_SDMA(i, mmSDMA0_GFX_RB_CNTL, rb_cntl);
- ib_cntl = RREG32_SDMA(i, mmSDMA0_GFX_IB_CNTL);
- ib_cntl = REG_SET_FIELD(ib_cntl, SDMA0_GFX_IB_CNTL, IB_ENABLE, enable ? 1 : 0);
- WREG32_SDMA(i, mmSDMA0_GFX_IB_CNTL, ib_cntl);
- }
+ rb_cntl = RREG32_SDMA(instance_id, mmSDMA0_GFX_RB_CNTL);
+ rb_cntl = REG_SET_FIELD(rb_cntl, SDMA0_GFX_RB_CNTL, RB_ENABLE, enable ? 1 : 0);
+ WREG32_SDMA(instance_id, mmSDMA0_GFX_RB_CNTL, rb_cntl);
+ ib_cntl = RREG32_SDMA(instance_id, mmSDMA0_GFX_IB_CNTL);
+ ib_cntl = REG_SET_FIELD(ib_cntl, SDMA0_GFX_IB_CNTL, IB_ENABLE, enable ? 1 : 0);
+ WREG32_SDMA(instance_id, mmSDMA0_GFX_IB_CNTL, ib_cntl);
}
/**
* sdma_v4_0_page_stop - stop the page async dma engines
*
* @adev: amdgpu_device pointer
+ * @instance_id: SDMA engine instance ID
*
* Stop the page async dma ring buffers (VEGA10).
*/
-static void sdma_v4_0_page_stop(struct amdgpu_device *adev)
+static void sdma_v4_0_page_stop(struct amdgpu_device *adev,
+ const u32 instance_id)
{
u32 rb_cntl, ib_cntl;
- int i;
- for (i = 0; i < adev->sdma.num_instances; i++) {
- rb_cntl = RREG32_SDMA(i, mmSDMA0_PAGE_RB_CNTL);
- rb_cntl = REG_SET_FIELD(rb_cntl, SDMA0_PAGE_RB_CNTL,
- RB_ENABLE, 0);
- WREG32_SDMA(i, mmSDMA0_PAGE_RB_CNTL, rb_cntl);
- ib_cntl = RREG32_SDMA(i, mmSDMA0_PAGE_IB_CNTL);
- ib_cntl = REG_SET_FIELD(ib_cntl, SDMA0_PAGE_IB_CNTL,
- IB_ENABLE, 0);
- WREG32_SDMA(i, mmSDMA0_PAGE_IB_CNTL, ib_cntl);
- }
+ rb_cntl = RREG32_SDMA(instance_id, mmSDMA0_PAGE_RB_CNTL);
+ rb_cntl = REG_SET_FIELD(rb_cntl, SDMA0_PAGE_RB_CNTL,
+ RB_ENABLE, 0);
+ WREG32_SDMA(instance_id, mmSDMA0_PAGE_RB_CNTL, rb_cntl);
+ ib_cntl = RREG32_SDMA(instance_id, mmSDMA0_PAGE_IB_CNTL);
+ ib_cntl = REG_SET_FIELD(ib_cntl, SDMA0_PAGE_IB_CNTL,
+ IB_ENABLE, 0);
+ WREG32_SDMA(instance_id, mmSDMA0_PAGE_IB_CNTL, ib_cntl);
}
/**
* sdma_v4_0_ctx_switch_enable - stop the async dma engines context switch
*
* @adev: amdgpu_device pointer
+ * @instance_id: SDMA engine instance ID
* @enable: enable/disable the DMA MEs context switch.
*
* Halt or unhalt the async dma engines context switch (VEGA10).
*/
-static void sdma_v4_0_ctx_switch_enable(struct amdgpu_device *adev, bool enable)
+static void sdma_v4_0_ctx_switch_enable(struct amdgpu_device *adev,
+ const u32 instance_id,
+ const bool enable)
{
u32 f32_cntl, phase_quantum = 0;
- int i;
if (amdgpu_sdma_phase_quantum) {
unsigned value = amdgpu_sdma_phase_quantum;
@@ -994,56 +995,52 @@ static void sdma_v4_0_ctx_switch_enable(struct amdgpu_device *adev, bool enable)
unit << SDMA0_PHASE0_QUANTUM__UNIT__SHIFT;
}
- for (i = 0; i < adev->sdma.num_instances; i++) {
- f32_cntl = RREG32_SDMA(i, mmSDMA0_CNTL);
- f32_cntl = REG_SET_FIELD(f32_cntl, SDMA0_CNTL,
- AUTO_CTXSW_ENABLE, enable ? 1 : 0);
- if (enable && amdgpu_sdma_phase_quantum) {
- WREG32_SDMA(i, mmSDMA0_PHASE0_QUANTUM, phase_quantum);
- WREG32_SDMA(i, mmSDMA0_PHASE1_QUANTUM, phase_quantum);
- WREG32_SDMA(i, mmSDMA0_PHASE2_QUANTUM, phase_quantum);
- }
- WREG32_SDMA(i, mmSDMA0_CNTL, f32_cntl);
-
- /*
- * Enable SDMA utilization. Its only supported on
- * Arcturus for the moment and firmware version 14
- * and above.
- */
- if (amdgpu_ip_version(adev, SDMA0_HWIP, 0) ==
- IP_VERSION(4, 2, 2) &&
- adev->sdma.instance[i].fw_version >= 14)
- WREG32_SDMA(i, mmSDMA0_PUB_DUMMY_REG2, enable);
- /* Extend page fault timeout to avoid interrupt storm */
- WREG32_SDMA(i, mmSDMA0_UTCL1_TIMEOUT, 0x00800080);
+ f32_cntl = RREG32_SDMA(instance_id, mmSDMA0_CNTL);
+ f32_cntl = REG_SET_FIELD(f32_cntl, SDMA0_CNTL,
+ AUTO_CTXSW_ENABLE, enable ? 1 : 0);
+ if (enable && amdgpu_sdma_phase_quantum) {
+ WREG32_SDMA(instance_id, mmSDMA0_PHASE0_QUANTUM, phase_quantum);
+ WREG32_SDMA(instance_id, mmSDMA0_PHASE1_QUANTUM, phase_quantum);
+ WREG32_SDMA(instance_id, mmSDMA0_PHASE2_QUANTUM, phase_quantum);
}
+ WREG32_SDMA(instance_id, mmSDMA0_CNTL, f32_cntl);
+ /*
+ * Enable SDMA utilization. Its only supported on
+ * Arcturus for the moment and firmware version 14
+ * and above.
+ */
+ if (amdgpu_ip_version(adev, SDMA0_HWIP, 0) == IP_VERSION(4, 2, 2) &&
+ adev->sdma.instance[instance_id].fw_version >= 14)
+ WREG32_SDMA(instance_id, mmSDMA0_PUB_DUMMY_REG2, enable);
+ /* Extend page fault timeout to avoid interrupt storm */
+ WREG32_SDMA(instance_id, mmSDMA0_UTCL1_TIMEOUT, 0x00800080);
}
/**
* sdma_v4_0_enable - stop the async dma engines
*
* @adev: amdgpu_device pointer
+ * @instance_id: SDMA engine instance ID
* @enable: enable/disable the DMA MEs.
*
* Halt or unhalt the async dma engines (VEGA10).
*/
-static void sdma_v4_0_enable(struct amdgpu_device *adev, bool enable)
+static void sdma_v4_0_enable(struct amdgpu_device *adev,
+ const u32 instance_id,
+ const bool enable)
{
u32 f32_cntl;
- int i;
if (!enable) {
- sdma_v4_0_gfx_enable(adev, enable);
+ sdma_v4_0_gfx_enable(adev, instance_id, enable);
if (adev->sdma.has_page_queue)
- sdma_v4_0_page_stop(adev);
+ sdma_v4_0_page_stop(adev, instance_id);
}
- for (i = 0; i < adev->sdma.num_instances; i++) {
- f32_cntl = RREG32_SDMA(i, mmSDMA0_F32_CNTL);
- f32_cntl = REG_SET_FIELD(f32_cntl, SDMA0_F32_CNTL, HALT, enable ? 0 : 1);
- WREG32_SDMA(i, mmSDMA0_F32_CNTL, f32_cntl);
- }
+ f32_cntl = RREG32_SDMA(instance_id, mmSDMA0_F32_CNTL);
+ f32_cntl = REG_SET_FIELD(f32_cntl, SDMA0_F32_CNTL, HALT, enable ? 0 : 1);
+ WREG32_SDMA(instance_id, mmSDMA0_F32_CNTL, f32_cntl);
}
/*
@@ -1303,41 +1300,38 @@ static void sdma_v4_0_init_pg(struct amdgpu_device *adev)
* sdma_v4_0_load_microcode - load the sDMA ME ucode
*
* @adev: amdgpu_device pointer
+ * @instance_id: SDMA engine instance ID
*
* Loads the sDMA0/1 ucode.
* Returns 0 for success, -EINVAL if the ucode is not available.
*/
-static int sdma_v4_0_load_microcode(struct amdgpu_device *adev)
+static int sdma_v4_0_load_microcode(struct amdgpu_device *adev, const u32 instance_id)
{
const struct sdma_firmware_header_v1_0 *hdr;
const __le32 *fw_data;
u32 fw_size;
- int i, j;
+ int j;
/* halt the MEs */
- sdma_v4_0_enable(adev, false);
+ sdma_v4_0_enable(adev, instance_id, false);
- for (i = 0; i < adev->sdma.num_instances; i++) {
- if (!adev->sdma.instance[i].fw)
- return -EINVAL;
+ if (!adev->sdma.instance[instance_id].fw)
+ return -EINVAL;
- hdr = (const struct sdma_firmware_header_v1_0 *)adev->sdma.instance[i].fw->data;
- amdgpu_ucode_print_sdma_hdr(&hdr->header);
- fw_size = le32_to_cpu(hdr->header.ucode_size_bytes) / 4;
+ hdr = (const struct sdma_firmware_header_v1_0 *)adev->sdma.instance[instance_id].fw->data;
+ amdgpu_ucode_print_sdma_hdr(&hdr->header);
+ fw_size = le32_to_cpu(hdr->header.ucode_size_bytes) / 4;
- fw_data = (const __le32 *)
- (adev->sdma.instance[i].fw->data +
- le32_to_cpu(hdr->header.ucode_array_offset_bytes));
+ fw_data =
+ (const __le32 *)(adev->sdma.instance[instance_id].fw->data +
+ le32_to_cpu(hdr->header.ucode_array_offset_bytes));
- WREG32_SDMA(i, mmSDMA0_UCODE_ADDR, 0);
+ WREG32_SDMA(instance_id, mmSDMA0_UCODE_ADDR, 0);
- for (j = 0; j < fw_size; j++)
- WREG32_SDMA(i, mmSDMA0_UCODE_DATA,
- le32_to_cpup(fw_data++));
+ for (j = 0; j < fw_size; j++)
+ WREG32_SDMA(instance_id, mmSDMA0_UCODE_DATA, le32_to_cpup(fw_data++));
- WREG32_SDMA(i, mmSDMA0_UCODE_ADDR,
- adev->sdma.instance[i].fw_version);
- }
+ WREG32_SDMA(instance_id, mmSDMA0_UCODE_ADDR, adev->sdma.instance[instance_id].fw_version);
return 0;
}
@@ -1346,80 +1340,86 @@ static int sdma_v4_0_load_microcode(struct amdgpu_device *adev)
* sdma_v4_0_start - setup and start the async dma engines
*
* @adev: amdgpu_device pointer
+ * @instance_id: SDMA engine instance ID
*
* Set up the DMA engines and enable them (VEGA10).
* Returns 0 for success, error for failure.
*/
-static int sdma_v4_0_start(struct amdgpu_device *adev)
+static int sdma_v4_0_start(struct amdgpu_device *adev, const u32 instance_id)
{
- struct amdgpu_ring *ring;
- int i, r = 0;
+ int r = 0;
if (amdgpu_sriov_vf(adev)) {
- sdma_v4_0_ctx_switch_enable(adev, false);
- sdma_v4_0_enable(adev, false);
+ sdma_v4_0_ctx_switch_enable(adev, instance_id, false);
+ sdma_v4_0_enable(adev, instance_id, false);
} else {
if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP) {
- r = sdma_v4_0_load_microcode(adev);
+ r = sdma_v4_0_load_microcode(adev, instance_id);
if (r)
return r;
}
/* unhalt the MEs */
- sdma_v4_0_enable(adev, true);
+ sdma_v4_0_enable(adev, instance_id, true);
/* enable sdma ring preemption */
- sdma_v4_0_ctx_switch_enable(adev, true);
+ sdma_v4_0_ctx_switch_enable(adev, instance_id, true);
}
/* start the gfx rings and rlc compute queues */
- for (i = 0; i < adev->sdma.num_instances; i++) {
- uint32_t temp;
-
- WREG32_SDMA(i, mmSDMA0_SEM_WAIT_FAIL_TIMER_CNTL, 0);
- sdma_v4_0_gfx_resume(adev, i);
- if (adev->sdma.has_page_queue)
- sdma_v4_0_page_resume(adev, i);
-
- /* set utc l1 enable flag always to 1 */
- temp = RREG32_SDMA(i, mmSDMA0_CNTL);
- temp = REG_SET_FIELD(temp, SDMA0_CNTL, UTC_L1_ENABLE, 1);
- WREG32_SDMA(i, mmSDMA0_CNTL, temp);
-
- if (!amdgpu_sriov_vf(adev)) {
- /* unhalt engine */
- temp = RREG32_SDMA(i, mmSDMA0_F32_CNTL);
- temp = REG_SET_FIELD(temp, SDMA0_F32_CNTL, HALT, 0);
- WREG32_SDMA(i, mmSDMA0_F32_CNTL, temp);
- }
+ uint32_t temp;
+
+ WREG32_SDMA(instance_id, mmSDMA0_SEM_WAIT_FAIL_TIMER_CNTL, 0);
+ sdma_v4_0_gfx_resume(adev, instance_id);
+ if (adev->sdma.has_page_queue)
+ sdma_v4_0_page_resume(adev, instance_id);
+
+ /* set utc l1 enable flag always to 1 */
+ temp = RREG32_SDMA(instance_id, mmSDMA0_CNTL);
+ temp = REG_SET_FIELD(temp, SDMA0_CNTL, UTC_L1_ENABLE, 1);
+ WREG32_SDMA(instance_id, mmSDMA0_CNTL, temp);
+
+ if (!amdgpu_sriov_vf(adev)) {
+ /* unhalt engine */
+ temp = RREG32_SDMA(instance_id, mmSDMA0_F32_CNTL);
+ temp = REG_SET_FIELD(temp, SDMA0_F32_CNTL, HALT, 0);
+ WREG32_SDMA(instance_id, mmSDMA0_F32_CNTL, temp);
}
if (amdgpu_sriov_vf(adev)) {
- sdma_v4_0_ctx_switch_enable(adev, true);
- sdma_v4_0_enable(adev, true);
+ sdma_v4_0_ctx_switch_enable(adev, instance_id, true);
+ sdma_v4_0_enable(adev, instance_id, true);
} else {
sdma_v4_0_init_pg(adev);
}
- for (i = 0; i < adev->sdma.num_instances; i++) {
- ring = &adev->sdma.instance[i].ring;
+ r = amdgpu_ring_test_helper(&adev->sdma.instance[instance_id].ring);
+ if (r)
+ return r;
- r = amdgpu_ring_test_helper(ring);
+ if (adev->sdma.has_page_queue) {
+ r = amdgpu_ring_test_helper(&adev->sdma.instance[instance_id].page);
if (r)
return r;
-
- if (adev->sdma.has_page_queue) {
- struct amdgpu_ring *page = &adev->sdma.instance[i].page;
-
- r = amdgpu_ring_test_helper(page);
- if (r)
- return r;
- }
}
return r;
}
+/**
+ * sdma_v3_0_stop() - Stop an SDMA engine
+ *
+ * @adev: amdgpu_device pointer
+ * @instance_id: SDMA engine instance ID
+ *
+ * Stop the given SDMA engine instance (VEGA10).
+ */
+static void sdma_v4_0_stop(struct amdgpu_device *adev, const u32 instance_id)
+{
+ sdma_v4_0_ctx_switch_enable(adev, instance_id, false);
+ sdma_v4_0_enable(adev, instance_id, false);
+}
+
/**
* sdma_v4_0_ring_test_ring - simple async dma engine test
*
@@ -1935,6 +1935,7 @@ static int sdma_v4_0_sw_fini(struct amdgpu_ip_block *ip_block)
static int sdma_v4_0_hw_init(struct amdgpu_ip_block *ip_block)
{
struct amdgpu_device *adev = ip_block->adev;
+ int i;
int r;
if (adev->flags & AMD_IS_APU)
@@ -1943,9 +1944,12 @@ static int sdma_v4_0_hw_init(struct amdgpu_ip_block *ip_block)
if (!amdgpu_sriov_vf(adev))
sdma_v4_0_init_golden_registers(adev);
- r = sdma_v4_0_start(adev);
- if (r)
- return r;
+ for (i = 0; i < adev->sdma.num_instances; ++i) {
+ r = sdma_v4_0_start(adev, i);
+ if (r)
+ return r;
+ }
+
sdma_v4_0_set_buffer_funcs(adev);
return 0;
@@ -1966,8 +1970,8 @@ static int sdma_v4_0_hw_fini(struct amdgpu_ip_block *ip_block)
}
}
- sdma_v4_0_ctx_switch_enable(adev, false);
- sdma_v4_0_enable(adev, false);
+ for (i = 0; i < adev->sdma.num_instances; ++i)
+ sdma_v4_0_stop(adev, i);
if (adev->flags & AMD_IS_APU)
amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_SDMA, true, 0);
@@ -1978,10 +1982,12 @@ static int sdma_v4_0_hw_fini(struct amdgpu_ip_block *ip_block)
static int sdma_v4_0_suspend(struct amdgpu_ip_block *ip_block)
{
struct amdgpu_device *adev = ip_block->adev;
+ int i;
/* SMU saves SDMA state for us */
if (adev->in_s0ix) {
- sdma_v4_0_gfx_enable(adev, false);
+ for (i = 0; i < adev->sdma.num_instances; ++i)
+ sdma_v4_0_gfx_enable(adev, i, false);
return 0;
}
@@ -1991,11 +1997,14 @@ static int sdma_v4_0_suspend(struct amdgpu_ip_block *ip_block)
static int sdma_v4_0_resume(struct amdgpu_ip_block *ip_block)
{
struct amdgpu_device *adev = ip_block->adev;
+ int i;
/* SMU restores SDMA state for us */
if (adev->in_s0ix) {
- sdma_v4_0_enable(adev, true);
- sdma_v4_0_gfx_enable(adev, true);
+ for (i = 0; i < adev->sdma.num_instances; ++i) {
+ sdma_v4_0_enable(adev, i, true);
+ sdma_v4_0_gfx_enable(adev, i, true);
+ }
return 0;
}
--
2.55.0
^ permalink raw reply related [flat|nested] 17+ messages in thread* Re: [PATCH 10/12] drm/amdgpu/sdma: Refactor SDMA v4.0 functions to be per instance
2026-09-07 20:33 ` [PATCH 10/12] drm/amdgpu/sdma: Refactor SDMA v4.0 functions to be per instance Timur Kristóf
@ 2026-09-08 7:41 ` Tvrtko Ursulin
2026-09-08 8:14 ` Timur Kristóf
0 siblings, 1 reply; 17+ messages in thread
From: Tvrtko Ursulin @ 2026-09-08 7:41 UTC (permalink / raw)
To: Timur Kristóf, amd-gfx, Marek Olšák, Alex Deucher,
Christian König, pierre-eric.pelloux-prayer, Natalie Vock,
Lijo Lazar, Felix Kuehling
On 07/09/2026 21:33, Timur Kristóf wrote:
> This prepares the code for implementing recovery for SDMA 4.0.
>
> Reorganize the SDMA 4.0 code so that the functions that are
> responsible for managing the SDMA engines take an instance ID
> as an argument.
>
> This makes it possible to manage the SDMA instances
> independently of each other, which will enable us to
> also use these functions to implement resetting and
> recovering them independently.
Radom patch to drop a comment on the whole series. It looks clean and
reasonable to me. Once the pre-requisite series is reviewed I can do a
more detail pass and slap an r-b to it.
One discussion point could be is do we maybe want the prototype for all
to be "struct amdgpu_sdma_instance *" instead of "struct amdgpu_device,
const u32 instance_id"?
Could I also interest you in a related cleanup:
https://lore.kernel.org/amd-gfx/20260622143649.54632-1-tvrtko.ursulin@igalia.com/#t
?
I could make my patch store the self-index in struct
amdgpu_sdma_instance and then respecitve callsite could get it from
there. Maybe adev too unless we could rely on the existing
sdma_instance->ring->adev.
Regards,
Tvrtko
> Signed-off-by: Timur Kristóf <timur.kristof@gmail.com>
> ---
> drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c | 253 +++++++++++++------------
> 1 file changed, 131 insertions(+), 122 deletions(-)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c
> index bdd140887e10..038e1ee8ff4c 100644
> --- a/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c
> +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c
> @@ -915,60 +915,61 @@ static void sdma_v4_0_ring_emit_fence(struct amdgpu_ring *ring, u64 addr, u64 se
> * sdma_v4_0_gfx_enable - enable the gfx async dma engines
> *
> * @adev: amdgpu_device pointer
> + * @instance_id: SDMA engine instance ID
> * @enable: enable SDMA RB/IB
> * control the gfx async dma ring buffers (VEGA10).
> */
> -static void sdma_v4_0_gfx_enable(struct amdgpu_device *adev, bool enable)
> +static void sdma_v4_0_gfx_enable(struct amdgpu_device *adev,
> + const u32 instance_id,
> + const bool enable)
> {
> u32 rb_cntl, ib_cntl;
> - int i;
>
> - for (i = 0; i < adev->sdma.num_instances; i++) {
> - rb_cntl = RREG32_SDMA(i, mmSDMA0_GFX_RB_CNTL);
> - rb_cntl = REG_SET_FIELD(rb_cntl, SDMA0_GFX_RB_CNTL, RB_ENABLE, enable ? 1 : 0);
> - WREG32_SDMA(i, mmSDMA0_GFX_RB_CNTL, rb_cntl);
> - ib_cntl = RREG32_SDMA(i, mmSDMA0_GFX_IB_CNTL);
> - ib_cntl = REG_SET_FIELD(ib_cntl, SDMA0_GFX_IB_CNTL, IB_ENABLE, enable ? 1 : 0);
> - WREG32_SDMA(i, mmSDMA0_GFX_IB_CNTL, ib_cntl);
> - }
> + rb_cntl = RREG32_SDMA(instance_id, mmSDMA0_GFX_RB_CNTL);
> + rb_cntl = REG_SET_FIELD(rb_cntl, SDMA0_GFX_RB_CNTL, RB_ENABLE, enable ? 1 : 0);
> + WREG32_SDMA(instance_id, mmSDMA0_GFX_RB_CNTL, rb_cntl);
> + ib_cntl = RREG32_SDMA(instance_id, mmSDMA0_GFX_IB_CNTL);
> + ib_cntl = REG_SET_FIELD(ib_cntl, SDMA0_GFX_IB_CNTL, IB_ENABLE, enable ? 1 : 0);
> + WREG32_SDMA(instance_id, mmSDMA0_GFX_IB_CNTL, ib_cntl);
> }
>
> /**
> * sdma_v4_0_page_stop - stop the page async dma engines
> *
> * @adev: amdgpu_device pointer
> + * @instance_id: SDMA engine instance ID
> *
> * Stop the page async dma ring buffers (VEGA10).
> */
> -static void sdma_v4_0_page_stop(struct amdgpu_device *adev)
> +static void sdma_v4_0_page_stop(struct amdgpu_device *adev,
> + const u32 instance_id)
> {
> u32 rb_cntl, ib_cntl;
> - int i;
>
> - for (i = 0; i < adev->sdma.num_instances; i++) {
> - rb_cntl = RREG32_SDMA(i, mmSDMA0_PAGE_RB_CNTL);
> - rb_cntl = REG_SET_FIELD(rb_cntl, SDMA0_PAGE_RB_CNTL,
> - RB_ENABLE, 0);
> - WREG32_SDMA(i, mmSDMA0_PAGE_RB_CNTL, rb_cntl);
> - ib_cntl = RREG32_SDMA(i, mmSDMA0_PAGE_IB_CNTL);
> - ib_cntl = REG_SET_FIELD(ib_cntl, SDMA0_PAGE_IB_CNTL,
> - IB_ENABLE, 0);
> - WREG32_SDMA(i, mmSDMA0_PAGE_IB_CNTL, ib_cntl);
> - }
> + rb_cntl = RREG32_SDMA(instance_id, mmSDMA0_PAGE_RB_CNTL);
> + rb_cntl = REG_SET_FIELD(rb_cntl, SDMA0_PAGE_RB_CNTL,
> + RB_ENABLE, 0);
> + WREG32_SDMA(instance_id, mmSDMA0_PAGE_RB_CNTL, rb_cntl);
> + ib_cntl = RREG32_SDMA(instance_id, mmSDMA0_PAGE_IB_CNTL);
> + ib_cntl = REG_SET_FIELD(ib_cntl, SDMA0_PAGE_IB_CNTL,
> + IB_ENABLE, 0);
> + WREG32_SDMA(instance_id, mmSDMA0_PAGE_IB_CNTL, ib_cntl);
> }
>
> /**
> * sdma_v4_0_ctx_switch_enable - stop the async dma engines context switch
> *
> * @adev: amdgpu_device pointer
> + * @instance_id: SDMA engine instance ID
> * @enable: enable/disable the DMA MEs context switch.
> *
> * Halt or unhalt the async dma engines context switch (VEGA10).
> */
> -static void sdma_v4_0_ctx_switch_enable(struct amdgpu_device *adev, bool enable)
> +static void sdma_v4_0_ctx_switch_enable(struct amdgpu_device *adev,
> + const u32 instance_id,
> + const bool enable)
> {
> u32 f32_cntl, phase_quantum = 0;
> - int i;
>
> if (amdgpu_sdma_phase_quantum) {
> unsigned value = amdgpu_sdma_phase_quantum;
> @@ -994,56 +995,52 @@ static void sdma_v4_0_ctx_switch_enable(struct amdgpu_device *adev, bool enable)
> unit << SDMA0_PHASE0_QUANTUM__UNIT__SHIFT;
> }
>
> - for (i = 0; i < adev->sdma.num_instances; i++) {
> - f32_cntl = RREG32_SDMA(i, mmSDMA0_CNTL);
> - f32_cntl = REG_SET_FIELD(f32_cntl, SDMA0_CNTL,
> - AUTO_CTXSW_ENABLE, enable ? 1 : 0);
> - if (enable && amdgpu_sdma_phase_quantum) {
> - WREG32_SDMA(i, mmSDMA0_PHASE0_QUANTUM, phase_quantum);
> - WREG32_SDMA(i, mmSDMA0_PHASE1_QUANTUM, phase_quantum);
> - WREG32_SDMA(i, mmSDMA0_PHASE2_QUANTUM, phase_quantum);
> - }
> - WREG32_SDMA(i, mmSDMA0_CNTL, f32_cntl);
> -
> - /*
> - * Enable SDMA utilization. Its only supported on
> - * Arcturus for the moment and firmware version 14
> - * and above.
> - */
> - if (amdgpu_ip_version(adev, SDMA0_HWIP, 0) ==
> - IP_VERSION(4, 2, 2) &&
> - adev->sdma.instance[i].fw_version >= 14)
> - WREG32_SDMA(i, mmSDMA0_PUB_DUMMY_REG2, enable);
> - /* Extend page fault timeout to avoid interrupt storm */
> - WREG32_SDMA(i, mmSDMA0_UTCL1_TIMEOUT, 0x00800080);
> + f32_cntl = RREG32_SDMA(instance_id, mmSDMA0_CNTL);
> + f32_cntl = REG_SET_FIELD(f32_cntl, SDMA0_CNTL,
> + AUTO_CTXSW_ENABLE, enable ? 1 : 0);
> + if (enable && amdgpu_sdma_phase_quantum) {
> + WREG32_SDMA(instance_id, mmSDMA0_PHASE0_QUANTUM, phase_quantum);
> + WREG32_SDMA(instance_id, mmSDMA0_PHASE1_QUANTUM, phase_quantum);
> + WREG32_SDMA(instance_id, mmSDMA0_PHASE2_QUANTUM, phase_quantum);
> }
> + WREG32_SDMA(instance_id, mmSDMA0_CNTL, f32_cntl);
>
> + /*
> + * Enable SDMA utilization. Its only supported on
> + * Arcturus for the moment and firmware version 14
> + * and above.
> + */
> + if (amdgpu_ip_version(adev, SDMA0_HWIP, 0) == IP_VERSION(4, 2, 2) &&
> + adev->sdma.instance[instance_id].fw_version >= 14)
> + WREG32_SDMA(instance_id, mmSDMA0_PUB_DUMMY_REG2, enable);
> + /* Extend page fault timeout to avoid interrupt storm */
> + WREG32_SDMA(instance_id, mmSDMA0_UTCL1_TIMEOUT, 0x00800080);
> }
>
> /**
> * sdma_v4_0_enable - stop the async dma engines
> *
> * @adev: amdgpu_device pointer
> + * @instance_id: SDMA engine instance ID
> * @enable: enable/disable the DMA MEs.
> *
> * Halt or unhalt the async dma engines (VEGA10).
> */
> -static void sdma_v4_0_enable(struct amdgpu_device *adev, bool enable)
> +static void sdma_v4_0_enable(struct amdgpu_device *adev,
> + const u32 instance_id,
> + const bool enable)
> {
> u32 f32_cntl;
> - int i;
>
> if (!enable) {
> - sdma_v4_0_gfx_enable(adev, enable);
> + sdma_v4_0_gfx_enable(adev, instance_id, enable);
> if (adev->sdma.has_page_queue)
> - sdma_v4_0_page_stop(adev);
> + sdma_v4_0_page_stop(adev, instance_id);
> }
>
> - for (i = 0; i < adev->sdma.num_instances; i++) {
> - f32_cntl = RREG32_SDMA(i, mmSDMA0_F32_CNTL);
> - f32_cntl = REG_SET_FIELD(f32_cntl, SDMA0_F32_CNTL, HALT, enable ? 0 : 1);
> - WREG32_SDMA(i, mmSDMA0_F32_CNTL, f32_cntl);
> - }
> + f32_cntl = RREG32_SDMA(instance_id, mmSDMA0_F32_CNTL);
> + f32_cntl = REG_SET_FIELD(f32_cntl, SDMA0_F32_CNTL, HALT, enable ? 0 : 1);
> + WREG32_SDMA(instance_id, mmSDMA0_F32_CNTL, f32_cntl);
> }
>
> /*
> @@ -1303,41 +1300,38 @@ static void sdma_v4_0_init_pg(struct amdgpu_device *adev)
> * sdma_v4_0_load_microcode - load the sDMA ME ucode
> *
> * @adev: amdgpu_device pointer
> + * @instance_id: SDMA engine instance ID
> *
> * Loads the sDMA0/1 ucode.
> * Returns 0 for success, -EINVAL if the ucode is not available.
> */
> -static int sdma_v4_0_load_microcode(struct amdgpu_device *adev)
> +static int sdma_v4_0_load_microcode(struct amdgpu_device *adev, const u32 instance_id)
> {
> const struct sdma_firmware_header_v1_0 *hdr;
> const __le32 *fw_data;
> u32 fw_size;
> - int i, j;
> + int j;
>
> /* halt the MEs */
> - sdma_v4_0_enable(adev, false);
> + sdma_v4_0_enable(adev, instance_id, false);
>
> - for (i = 0; i < adev->sdma.num_instances; i++) {
> - if (!adev->sdma.instance[i].fw)
> - return -EINVAL;
> + if (!adev->sdma.instance[instance_id].fw)
> + return -EINVAL;
>
> - hdr = (const struct sdma_firmware_header_v1_0 *)adev->sdma.instance[i].fw->data;
> - amdgpu_ucode_print_sdma_hdr(&hdr->header);
> - fw_size = le32_to_cpu(hdr->header.ucode_size_bytes) / 4;
> + hdr = (const struct sdma_firmware_header_v1_0 *)adev->sdma.instance[instance_id].fw->data;
> + amdgpu_ucode_print_sdma_hdr(&hdr->header);
> + fw_size = le32_to_cpu(hdr->header.ucode_size_bytes) / 4;
>
> - fw_data = (const __le32 *)
> - (adev->sdma.instance[i].fw->data +
> - le32_to_cpu(hdr->header.ucode_array_offset_bytes));
> + fw_data =
> + (const __le32 *)(adev->sdma.instance[instance_id].fw->data +
> + le32_to_cpu(hdr->header.ucode_array_offset_bytes));
>
> - WREG32_SDMA(i, mmSDMA0_UCODE_ADDR, 0);
> + WREG32_SDMA(instance_id, mmSDMA0_UCODE_ADDR, 0);
>
> - for (j = 0; j < fw_size; j++)
> - WREG32_SDMA(i, mmSDMA0_UCODE_DATA,
> - le32_to_cpup(fw_data++));
> + for (j = 0; j < fw_size; j++)
> + WREG32_SDMA(instance_id, mmSDMA0_UCODE_DATA, le32_to_cpup(fw_data++));
>
> - WREG32_SDMA(i, mmSDMA0_UCODE_ADDR,
> - adev->sdma.instance[i].fw_version);
> - }
> + WREG32_SDMA(instance_id, mmSDMA0_UCODE_ADDR, adev->sdma.instance[instance_id].fw_version);
>
> return 0;
> }
> @@ -1346,80 +1340,86 @@ static int sdma_v4_0_load_microcode(struct amdgpu_device *adev)
> * sdma_v4_0_start - setup and start the async dma engines
> *
> * @adev: amdgpu_device pointer
> + * @instance_id: SDMA engine instance ID
> *
> * Set up the DMA engines and enable them (VEGA10).
> * Returns 0 for success, error for failure.
> */
> -static int sdma_v4_0_start(struct amdgpu_device *adev)
> +static int sdma_v4_0_start(struct amdgpu_device *adev, const u32 instance_id)
> {
> - struct amdgpu_ring *ring;
> - int i, r = 0;
> + int r = 0;
>
> if (amdgpu_sriov_vf(adev)) {
> - sdma_v4_0_ctx_switch_enable(adev, false);
> - sdma_v4_0_enable(adev, false);
> + sdma_v4_0_ctx_switch_enable(adev, instance_id, false);
> + sdma_v4_0_enable(adev, instance_id, false);
> } else {
>
> if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP) {
> - r = sdma_v4_0_load_microcode(adev);
> + r = sdma_v4_0_load_microcode(adev, instance_id);
> if (r)
> return r;
> }
>
> /* unhalt the MEs */
> - sdma_v4_0_enable(adev, true);
> + sdma_v4_0_enable(adev, instance_id, true);
> /* enable sdma ring preemption */
> - sdma_v4_0_ctx_switch_enable(adev, true);
> + sdma_v4_0_ctx_switch_enable(adev, instance_id, true);
> }
>
> /* start the gfx rings and rlc compute queues */
> - for (i = 0; i < adev->sdma.num_instances; i++) {
> - uint32_t temp;
> -
> - WREG32_SDMA(i, mmSDMA0_SEM_WAIT_FAIL_TIMER_CNTL, 0);
> - sdma_v4_0_gfx_resume(adev, i);
> - if (adev->sdma.has_page_queue)
> - sdma_v4_0_page_resume(adev, i);
> -
> - /* set utc l1 enable flag always to 1 */
> - temp = RREG32_SDMA(i, mmSDMA0_CNTL);
> - temp = REG_SET_FIELD(temp, SDMA0_CNTL, UTC_L1_ENABLE, 1);
> - WREG32_SDMA(i, mmSDMA0_CNTL, temp);
> -
> - if (!amdgpu_sriov_vf(adev)) {
> - /* unhalt engine */
> - temp = RREG32_SDMA(i, mmSDMA0_F32_CNTL);
> - temp = REG_SET_FIELD(temp, SDMA0_F32_CNTL, HALT, 0);
> - WREG32_SDMA(i, mmSDMA0_F32_CNTL, temp);
> - }
> + uint32_t temp;
> +
> + WREG32_SDMA(instance_id, mmSDMA0_SEM_WAIT_FAIL_TIMER_CNTL, 0);
> + sdma_v4_0_gfx_resume(adev, instance_id);
> + if (adev->sdma.has_page_queue)
> + sdma_v4_0_page_resume(adev, instance_id);
> +
> + /* set utc l1 enable flag always to 1 */
> + temp = RREG32_SDMA(instance_id, mmSDMA0_CNTL);
> + temp = REG_SET_FIELD(temp, SDMA0_CNTL, UTC_L1_ENABLE, 1);
> + WREG32_SDMA(instance_id, mmSDMA0_CNTL, temp);
> +
> + if (!amdgpu_sriov_vf(adev)) {
> + /* unhalt engine */
> + temp = RREG32_SDMA(instance_id, mmSDMA0_F32_CNTL);
> + temp = REG_SET_FIELD(temp, SDMA0_F32_CNTL, HALT, 0);
> + WREG32_SDMA(instance_id, mmSDMA0_F32_CNTL, temp);
> }
>
> if (amdgpu_sriov_vf(adev)) {
> - sdma_v4_0_ctx_switch_enable(adev, true);
> - sdma_v4_0_enable(adev, true);
> + sdma_v4_0_ctx_switch_enable(adev, instance_id, true);
> + sdma_v4_0_enable(adev, instance_id, true);
> } else {
> sdma_v4_0_init_pg(adev);
> }
>
> - for (i = 0; i < adev->sdma.num_instances; i++) {
> - ring = &adev->sdma.instance[i].ring;
> + r = amdgpu_ring_test_helper(&adev->sdma.instance[instance_id].ring);
> + if (r)
> + return r;
>
> - r = amdgpu_ring_test_helper(ring);
> + if (adev->sdma.has_page_queue) {
> + r = amdgpu_ring_test_helper(&adev->sdma.instance[instance_id].page);
> if (r)
> return r;
> -
> - if (adev->sdma.has_page_queue) {
> - struct amdgpu_ring *page = &adev->sdma.instance[i].page;
> -
> - r = amdgpu_ring_test_helper(page);
> - if (r)
> - return r;
> - }
> }
>
> return r;
> }
>
> +/**
> + * sdma_v3_0_stop() - Stop an SDMA engine
> + *
> + * @adev: amdgpu_device pointer
> + * @instance_id: SDMA engine instance ID
> + *
> + * Stop the given SDMA engine instance (VEGA10).
> + */
> +static void sdma_v4_0_stop(struct amdgpu_device *adev, const u32 instance_id)
> +{
> + sdma_v4_0_ctx_switch_enable(adev, instance_id, false);
> + sdma_v4_0_enable(adev, instance_id, false);
> +}
> +
> /**
> * sdma_v4_0_ring_test_ring - simple async dma engine test
> *
> @@ -1935,6 +1935,7 @@ static int sdma_v4_0_sw_fini(struct amdgpu_ip_block *ip_block)
> static int sdma_v4_0_hw_init(struct amdgpu_ip_block *ip_block)
> {
> struct amdgpu_device *adev = ip_block->adev;
> + int i;
> int r;
>
> if (adev->flags & AMD_IS_APU)
> @@ -1943,9 +1944,12 @@ static int sdma_v4_0_hw_init(struct amdgpu_ip_block *ip_block)
> if (!amdgpu_sriov_vf(adev))
> sdma_v4_0_init_golden_registers(adev);
>
> - r = sdma_v4_0_start(adev);
> - if (r)
> - return r;
> + for (i = 0; i < adev->sdma.num_instances; ++i) {
> + r = sdma_v4_0_start(adev, i);
> + if (r)
> + return r;
> + }
> +
> sdma_v4_0_set_buffer_funcs(adev);
>
> return 0;
> @@ -1966,8 +1970,8 @@ static int sdma_v4_0_hw_fini(struct amdgpu_ip_block *ip_block)
> }
> }
>
> - sdma_v4_0_ctx_switch_enable(adev, false);
> - sdma_v4_0_enable(adev, false);
> + for (i = 0; i < adev->sdma.num_instances; ++i)
> + sdma_v4_0_stop(adev, i);
>
> if (adev->flags & AMD_IS_APU)
> amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_SDMA, true, 0);
> @@ -1978,10 +1982,12 @@ static int sdma_v4_0_hw_fini(struct amdgpu_ip_block *ip_block)
> static int sdma_v4_0_suspend(struct amdgpu_ip_block *ip_block)
> {
> struct amdgpu_device *adev = ip_block->adev;
> + int i;
>
> /* SMU saves SDMA state for us */
> if (adev->in_s0ix) {
> - sdma_v4_0_gfx_enable(adev, false);
> + for (i = 0; i < adev->sdma.num_instances; ++i)
> + sdma_v4_0_gfx_enable(adev, i, false);
> return 0;
> }
>
> @@ -1991,11 +1997,14 @@ static int sdma_v4_0_suspend(struct amdgpu_ip_block *ip_block)
> static int sdma_v4_0_resume(struct amdgpu_ip_block *ip_block)
> {
> struct amdgpu_device *adev = ip_block->adev;
> + int i;
>
> /* SMU restores SDMA state for us */
> if (adev->in_s0ix) {
> - sdma_v4_0_enable(adev, true);
> - sdma_v4_0_gfx_enable(adev, true);
> + for (i = 0; i < adev->sdma.num_instances; ++i) {
> + sdma_v4_0_enable(adev, i, true);
> + sdma_v4_0_gfx_enable(adev, i, true);
> + }
> return 0;
> }
>
^ permalink raw reply [flat|nested] 17+ messages in thread* Re: [PATCH 10/12] drm/amdgpu/sdma: Refactor SDMA v4.0 functions to be per instance
2026-09-08 7:41 ` Tvrtko Ursulin
@ 2026-09-08 8:14 ` Timur Kristóf
2026-09-10 14:44 ` Tvrtko Ursulin
0 siblings, 1 reply; 17+ messages in thread
From: Timur Kristóf @ 2026-09-08 8:14 UTC (permalink / raw)
To: amd-gfx, Marek Olšák, Alex Deucher,
Christian König, pierre-eric.pelloux-prayer, Natalie Vock,
Lijo Lazar, Felix Kuehling, Tvrtko Ursulin
On 2026. szeptember 8., kedd 9:41:48 közép-európai nyári idő Tvrtko Ursulin
wrote:
> On 07/09/2026 21:33, Timur Kristóf wrote:
> > This prepares the code for implementing recovery for SDMA 4.0.
> >
> > Reorganize the SDMA 4.0 code so that the functions that are
> > responsible for managing the SDMA engines take an instance ID
> > as an argument.
> >
> > This makes it possible to manage the SDMA instances
> > independently of each other, which will enable us to
> > also use these functions to implement resetting and
> > recovering them independently.
>
> Radom patch to drop a comment on the whole series. It looks clean and
> reasonable to me. Once the pre-requisite series is reviewed I can do a
> more detail pass and slap an r-b to it.
Thanks! If we agree this is the right approach, I would like to do the same
refactor for all the newer SDMA blocks as well for the sake of consistency.
This refactor is necessary because I want to reuse the same functions for
implementing per-instance SDMA soft reset (as opposed to duplicating a lot of
code which seems to me to be more error-prone).
> One discussion point could be is do we maybe want the prototype for all
> to be "struct amdgpu_sdma_instance *" instead of "struct amdgpu_device,
> const u32 instance_id"?
I don't want to complicate this with the amdgpu_sdma_instance struct, because
these functions only need the instance ID, and only for the purpose of knowing
the register offset.
> Could I also interest you in a related cleanup:
>
> https://lore.kernel.org/amd-gfx/20260622143649.54632-1-tvrtko.ursulin@igalia
> .com/#t
>
> ?
I've taken a quick look, I'd suggest a different approach to it.
I will reply on your commits.
Thanks & best regards,
Timur
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH 10/12] drm/amdgpu/sdma: Refactor SDMA v4.0 functions to be per instance
2026-09-08 8:14 ` Timur Kristóf
@ 2026-09-10 14:44 ` Tvrtko Ursulin
0 siblings, 0 replies; 17+ messages in thread
From: Tvrtko Ursulin @ 2026-09-10 14:44 UTC (permalink / raw)
To: Timur Kristóf, amd-gfx, Marek Olšák, Alex Deucher,
Christian König, pierre-eric.pelloux-prayer, Natalie Vock,
Lijo Lazar, Felix Kuehling
On 08/09/2026 09:14, Timur Kristóf wrote:
> On 2026. szeptember 8., kedd 9:41:48 közép-európai nyári idő Tvrtko Ursulin
> wrote:
>> On 07/09/2026 21:33, Timur Kristóf wrote:
>>> This prepares the code for implementing recovery for SDMA 4.0.
>>>
>>> Reorganize the SDMA 4.0 code so that the functions that are
>>> responsible for managing the SDMA engines take an instance ID
>>> as an argument.
>>>
>>> This makes it possible to manage the SDMA instances
>>> independently of each other, which will enable us to
>>> also use these functions to implement resetting and
>>> recovering them independently.
>>
>> Radom patch to drop a comment on the whole series. It looks clean and
>> reasonable to me. Once the pre-requisite series is reviewed I can do a
>> more detail pass and slap an r-b to it.
>
> Thanks! If we agree this is the right approach, I would like to do the same
> refactor for all the newer SDMA blocks as well for the sake of consistency.
>
> This refactor is necessary because I want to reuse the same functions for
> implementing per-instance SDMA soft reset (as opposed to duplicating a lot of
> code which seems to me to be more error-prone).
>
>> One discussion point could be is do we maybe want the prototype for all
>> to be "struct amdgpu_sdma_instance *" instead of "struct amdgpu_device,
>> const u32 instance_id"?
>
> I don't want to complicate this with the amdgpu_sdma_instance struct, because
> these functions only need the instance ID, and only for the purpose of knowing
> the register offset.
Fine by me to keep the signatures as you have them.
Regards,
Tvrtko
>> Could I also interest you in a related cleanup:
>>
>> https://lore.kernel.org/amd-gfx/20260622143649.54632-1-tvrtko.ursulin@igalia
>> .com/#t
>>
>> ?
>
> I've taken a quick look, I'd suggest a different approach to it.
> I will reply on your commits.
>
> Thanks & best regards,
> Timur
>
>
^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH 11/12] drm/amdgpu/sdma: Refactor SDMA v4.0 clock gating functions to be per-instance
2026-09-07 20:33 [PATCH 00/12] RFC: drm/amdgpu/sdma: Refactor SDMA v4 and older functions to be per-instance Timur Kristóf
` (9 preceding siblings ...)
2026-09-07 20:33 ` [PATCH 10/12] drm/amdgpu/sdma: Refactor SDMA v4.0 functions to be per instance Timur Kristóf
@ 2026-09-07 20:33 ` Timur Kristóf
2026-09-07 20:33 ` [PATCH 12/12] drm/amdgpu/sdma: Refactor SDMA v4.0 golden registers " Timur Kristóf
2026-09-11 19:00 ` [PATCH 00/12] RFC: drm/amdgpu/sdma: Refactor SDMA v4 and older functions " Alex Deucher
12 siblings, 0 replies; 17+ messages in thread
From: Timur Kristóf @ 2026-09-07 20:33 UTC (permalink / raw)
To: amd-gfx, Marek Olšák, Alex Deucher,
Christian König, Tvrtko Ursulin, pierre-eric.pelloux-prayer,
Natalie Vock, Lijo Lazar, Felix Kuehling
Cc: Timur Kristóf
Refactor clock gating functions to take the SDMA engine
instance ID as an argument and only affect one SDMA engine
instance at once.
Signed-off-by: Timur Kristóf <timur.kristof@gmail.com>
---
drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c | 89 ++++++++++++--------------
1 file changed, 42 insertions(+), 47 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c
index 038e1ee8ff4c..259857596cfd 100644
--- a/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c
@@ -2208,66 +2208,58 @@ static int sdma_v4_0_process_srbm_write_irq(struct amdgpu_device *adev,
static void sdma_v4_0_update_medium_grain_clock_gating(
struct amdgpu_device *adev,
- bool enable)
+ const u32 instance_id,
+ const bool enable)
{
uint32_t data, def;
- int i;
if (enable && (adev->cg_flags & AMD_CG_SUPPORT_SDMA_MGCG)) {
- for (i = 0; i < adev->sdma.num_instances; i++) {
- def = data = RREG32_SDMA(i, mmSDMA0_CLK_CTRL);
- data &= ~(SDMA0_CLK_CTRL__SOFT_OVERRIDE7_MASK |
- SDMA0_CLK_CTRL__SOFT_OVERRIDE6_MASK |
- SDMA0_CLK_CTRL__SOFT_OVERRIDE5_MASK |
- SDMA0_CLK_CTRL__SOFT_OVERRIDE4_MASK |
- SDMA0_CLK_CTRL__SOFT_OVERRIDE3_MASK |
- SDMA0_CLK_CTRL__SOFT_OVERRIDE2_MASK |
- SDMA0_CLK_CTRL__SOFT_OVERRIDE1_MASK |
- SDMA0_CLK_CTRL__SOFT_OVERRIDE0_MASK);
- if (def != data)
- WREG32_SDMA(i, mmSDMA0_CLK_CTRL, data);
- }
+ def = data = RREG32_SDMA(instance_id, mmSDMA0_CLK_CTRL);
+ data &= ~(SDMA0_CLK_CTRL__SOFT_OVERRIDE7_MASK |
+ SDMA0_CLK_CTRL__SOFT_OVERRIDE6_MASK |
+ SDMA0_CLK_CTRL__SOFT_OVERRIDE5_MASK |
+ SDMA0_CLK_CTRL__SOFT_OVERRIDE4_MASK |
+ SDMA0_CLK_CTRL__SOFT_OVERRIDE3_MASK |
+ SDMA0_CLK_CTRL__SOFT_OVERRIDE2_MASK |
+ SDMA0_CLK_CTRL__SOFT_OVERRIDE1_MASK |
+ SDMA0_CLK_CTRL__SOFT_OVERRIDE0_MASK);
+ if (def != data)
+ WREG32_SDMA(instance_id, mmSDMA0_CLK_CTRL, data);
} else {
- for (i = 0; i < adev->sdma.num_instances; i++) {
- def = data = RREG32_SDMA(i, mmSDMA0_CLK_CTRL);
- data |= (SDMA0_CLK_CTRL__SOFT_OVERRIDE7_MASK |
- SDMA0_CLK_CTRL__SOFT_OVERRIDE6_MASK |
- SDMA0_CLK_CTRL__SOFT_OVERRIDE5_MASK |
- SDMA0_CLK_CTRL__SOFT_OVERRIDE4_MASK |
- SDMA0_CLK_CTRL__SOFT_OVERRIDE3_MASK |
- SDMA0_CLK_CTRL__SOFT_OVERRIDE2_MASK |
- SDMA0_CLK_CTRL__SOFT_OVERRIDE1_MASK |
- SDMA0_CLK_CTRL__SOFT_OVERRIDE0_MASK);
- if (def != data)
- WREG32_SDMA(i, mmSDMA0_CLK_CTRL, data);
- }
+ def = data = RREG32_SDMA(instance_id, mmSDMA0_CLK_CTRL);
+ data |= (SDMA0_CLK_CTRL__SOFT_OVERRIDE7_MASK |
+ SDMA0_CLK_CTRL__SOFT_OVERRIDE6_MASK |
+ SDMA0_CLK_CTRL__SOFT_OVERRIDE5_MASK |
+ SDMA0_CLK_CTRL__SOFT_OVERRIDE4_MASK |
+ SDMA0_CLK_CTRL__SOFT_OVERRIDE3_MASK |
+ SDMA0_CLK_CTRL__SOFT_OVERRIDE2_MASK |
+ SDMA0_CLK_CTRL__SOFT_OVERRIDE1_MASK |
+ SDMA0_CLK_CTRL__SOFT_OVERRIDE0_MASK);
+ if (def != data)
+ WREG32_SDMA(instance_id, mmSDMA0_CLK_CTRL, data);
}
}
static void sdma_v4_0_update_medium_grain_light_sleep(
struct amdgpu_device *adev,
- bool enable)
+ const u32 instance_id,
+ const bool enable)
{
uint32_t data, def;
- int i;
if (enable && (adev->cg_flags & AMD_CG_SUPPORT_SDMA_LS)) {
- for (i = 0; i < adev->sdma.num_instances; i++) {
- /* 1-not override: enable sdma mem light sleep */
- def = data = RREG32_SDMA(0, mmSDMA0_POWER_CNTL);
- data |= SDMA0_POWER_CNTL__MEM_POWER_OVERRIDE_MASK;
- if (def != data)
- WREG32_SDMA(0, mmSDMA0_POWER_CNTL, data);
- }
+ /* 1-not override: enable sdma mem light sleep */
+ def = data = RREG32_SDMA(instance_id, mmSDMA0_POWER_CNTL);
+ data |= SDMA0_POWER_CNTL__MEM_POWER_OVERRIDE_MASK;
+ if (def != data)
+ WREG32_SDMA(instance_id, mmSDMA0_POWER_CNTL, data);
} else {
- for (i = 0; i < adev->sdma.num_instances; i++) {
/* 0-override:disable sdma mem light sleep */
- def = data = RREG32_SDMA(0, mmSDMA0_POWER_CNTL);
- data &= ~SDMA0_POWER_CNTL__MEM_POWER_OVERRIDE_MASK;
- if (def != data)
- WREG32_SDMA(0, mmSDMA0_POWER_CNTL, data);
- }
+ def = data = RREG32_SDMA(instance_id, mmSDMA0_POWER_CNTL);
+ data &= ~SDMA0_POWER_CNTL__MEM_POWER_OVERRIDE_MASK;
+ if (def != data)
+ WREG32_SDMA(instance_id, mmSDMA0_POWER_CNTL, data);
}
}
@@ -2275,14 +2267,17 @@ static int sdma_v4_0_set_clockgating_state(struct amdgpu_ip_block *ip_block,
enum amd_clockgating_state state)
{
struct amdgpu_device *adev = ip_block->adev;
+ int i;
if (amdgpu_sriov_vf(adev))
return 0;
- sdma_v4_0_update_medium_grain_clock_gating(adev,
- state == AMD_CG_STATE_GATE);
- sdma_v4_0_update_medium_grain_light_sleep(adev,
- state == AMD_CG_STATE_GATE);
+ for (i = 0; i < adev->sdma.num_instances; i++) {
+ sdma_v4_0_update_medium_grain_clock_gating(
+ adev, i, state == AMD_CG_STATE_GATE);
+ sdma_v4_0_update_medium_grain_light_sleep(
+ adev, i, state == AMD_CG_STATE_GATE);
+ }
return 0;
}
--
2.55.0
^ permalink raw reply related [flat|nested] 17+ messages in thread* [PATCH 12/12] drm/amdgpu/sdma: Refactor SDMA v4.0 golden registers to be per-instance
2026-09-07 20:33 [PATCH 00/12] RFC: drm/amdgpu/sdma: Refactor SDMA v4 and older functions to be per-instance Timur Kristóf
` (10 preceding siblings ...)
2026-09-07 20:33 ` [PATCH 11/12] drm/amdgpu/sdma: Refactor SDMA v4.0 clock gating functions to be per-instance Timur Kristóf
@ 2026-09-07 20:33 ` Timur Kristóf
2026-09-11 19:00 ` [PATCH 00/12] RFC: drm/amdgpu/sdma: Refactor SDMA v4 and older functions " Alex Deucher
12 siblings, 0 replies; 17+ messages in thread
From: Timur Kristóf @ 2026-09-07 20:33 UTC (permalink / raw)
To: amd-gfx, Marek Olšák, Alex Deucher,
Christian König, Tvrtko Ursulin, pierre-eric.pelloux-prayer,
Natalie Vock, Lijo Lazar, Felix Kuehling
Cc: Timur Kristóf
Refactor golden registers initialization to take the SDMA
engine instance ID as an argument and only program the
golden registers for one SDMA engine at once.
Signed-off-by: Timur Kristóf <timur.kristof@gmail.com>
---
drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c | 237 +++++++++++++++++++------
1 file changed, 182 insertions(+), 55 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c
index 259857596cfd..ef9058dd1082 100644
--- a/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c
@@ -132,7 +132,7 @@ static void sdma_v4_0_set_buffer_funcs(struct amdgpu_device *adev);
static void sdma_v4_0_set_irq_funcs(struct amdgpu_device *adev);
static void sdma_v4_0_set_ras_funcs(struct amdgpu_device *adev);
-static const struct soc15_reg_golden golden_settings_sdma_4[] = {
+static const struct soc15_reg_golden golden_settings_v4_0_sdma0[] = {
SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_CHICKEN_BITS, 0xfe931f07, 0x02831d07),
SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_CLK_CTRL, 0xff000ff0, 0x3f000100),
SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_GFX_IB_CNTL, 0x800f0100, 0x00000100),
@@ -146,6 +146,9 @@ static const struct soc15_reg_golden golden_settings_sdma_4[] = {
SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_RLC1_RB_WPTR_POLL_CNTL, 0x0000fff0, 0x00403000),
SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_UTCL1_PAGE, 0x000003ff, 0x000003c0),
SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_UTCL1_WATERMK, 0xfc000000, 0x00000000),
+};
+
+static const struct soc15_reg_golden golden_settings_v4_0_sdma1[] = {
SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_CLK_CTRL, 0xffffffff, 0x3f000100),
SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_GFX_IB_CNTL, 0x800f0100, 0x00000100),
SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_GFX_RB_WPTR_POLL_CNTL, 0x0000fff0, 0x00403000),
@@ -160,27 +163,33 @@ static const struct soc15_reg_golden golden_settings_sdma_4[] = {
SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_UTCL1_WATERMK, 0xfc000000, 0x00000000)
};
-static const struct soc15_reg_golden golden_settings_sdma_vg10[] = {
+static const struct soc15_reg_golden golden_settings_vg10_sdma0[] = {
SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_GB_ADDR_CONFIG, 0x0018773f, 0x00104002),
SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_GB_ADDR_CONFIG_READ, 0x0018773f, 0x00104002),
SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_UTCL1_TIMEOUT, 0xffffffff, 0x00010001),
+};
+
+static const struct soc15_reg_golden golden_settings_vg10_sdma1[] = {
SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_CHICKEN_BITS, 0xfe931f07, 0x02831d07),
SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_GB_ADDR_CONFIG, 0x0018773f, 0x00104002),
SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_GB_ADDR_CONFIG_READ, 0x0018773f, 0x00104002),
SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_UTCL1_TIMEOUT, 0xffffffff, 0x00010001),
};
-static const struct soc15_reg_golden golden_settings_sdma_vg12[] = {
+static const struct soc15_reg_golden golden_settings_vg12_sdma0[] = {
SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_GB_ADDR_CONFIG, 0x0018773f, 0x00104001),
SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_GB_ADDR_CONFIG_READ, 0x0018773f, 0x00104001),
SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_UTCL1_TIMEOUT, 0xffffffff, 0x00010001),
+};
+
+static const struct soc15_reg_golden golden_settings_vg12_sdma1[] = {
SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_CHICKEN_BITS, 0xfe931f07, 0x02831d07),
SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_GB_ADDR_CONFIG, 0x0018773f, 0x00104001),
SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_GB_ADDR_CONFIG_READ, 0x0018773f, 0x00104001),
SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_UTCL1_TIMEOUT, 0xffffffff, 0x00010001),
};
-static const struct soc15_reg_golden golden_settings_sdma_4_1[] = {
+static const struct soc15_reg_golden golden_settings_v4_1_sdma0[] = {
SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_CHICKEN_BITS, 0xfe931f07, 0x02831d07),
SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_CLK_CTRL, 0xffffffff, 0x3f000100),
SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_GFX_IB_CNTL, 0x800f0111, 0x00000100),
@@ -194,12 +203,11 @@ static const struct soc15_reg_golden golden_settings_sdma_4_1[] = {
SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_UTCL1_WATERMK, 0xfc000000, 0x00000000)
};
-static const struct soc15_reg_golden golden_settings_sdma0_4_2_init[] = {
+static const struct soc15_reg_golden golden_settings_v4_2_sdma0_init[] = {
SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_RLC0_RB_WPTR_POLL_CNTL, 0xfffffff0, 0x00403000),
};
-static const struct soc15_reg_golden golden_settings_sdma0_4_2[] =
-{
+static const struct soc15_reg_golden golden_settings_v4_2_sdma0[] = {
SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_CHICKEN_BITS, 0xfe931f07, 0x02831f07),
SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_CLK_CTRL, 0xffffffff, 0x3f000100),
SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_GB_ADDR_CONFIG, 0x0000773f, 0x00004002),
@@ -229,7 +237,7 @@ static const struct soc15_reg_golden golden_settings_sdma0_4_2[] =
SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_UTCL1_TIMEOUT, 0xffffffff, 0x00010001),
};
-static const struct soc15_reg_golden golden_settings_sdma1_4_2[] = {
+static const struct soc15_reg_golden golden_settings_v4_2_sdma1[] = {
SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_CHICKEN_BITS, 0xfe931f07, 0x02831f07),
SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_CLK_CTRL, 0xffffffff, 0x3f000100),
SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_GB_ADDR_CONFIG, 0x0000773f, 0x00004002),
@@ -259,73 +267,103 @@ static const struct soc15_reg_golden golden_settings_sdma1_4_2[] = {
SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_UTCL1_TIMEOUT, 0xffffffff, 0x00010001),
};
-static const struct soc15_reg_golden golden_settings_sdma_rv1[] =
-{
+static const struct soc15_reg_golden golden_settings_rv1_sdma0[] = {
SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_GB_ADDR_CONFIG, 0x0018773f, 0x00000002),
SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_GB_ADDR_CONFIG_READ, 0x0018773f, 0x00000002)
};
-static const struct soc15_reg_golden golden_settings_sdma_rv2[] =
-{
+static const struct soc15_reg_golden golden_settings_rv2_sdma0[] = {
SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_GB_ADDR_CONFIG, 0x0018773f, 0x00003001),
SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_GB_ADDR_CONFIG_READ, 0x0018773f, 0x00003001)
};
-static const struct soc15_reg_golden golden_settings_sdma_arct[] =
-{
+static const struct soc15_reg_golden golden_settings_arct_sdma0[] = {
SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_CHICKEN_BITS, 0xfe931f07, 0x02831f07),
SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_GB_ADDR_CONFIG, 0x0000773f, 0x00004002),
SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_GB_ADDR_CONFIG_READ, 0x0000773f, 0x00004002),
SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_UTCL1_TIMEOUT, 0xffffffff, 0x00010001),
+};
+
+static const struct soc15_reg_golden golden_settings_arct_sdma1[] = {
SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_CHICKEN_BITS, 0xfe931f07, 0x02831f07),
SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_GB_ADDR_CONFIG, 0x0000773f, 0x00004002),
SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_GB_ADDR_CONFIG_READ, 0x0000773f, 0x00004002),
SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_UTCL1_TIMEOUT, 0xffffffff, 0x00010001),
+};
+
+static const struct soc15_reg_golden golden_settings_arct_sdma2[] = {
SOC15_REG_GOLDEN_VALUE(SDMA2, 0, mmSDMA2_CHICKEN_BITS, 0xfe931f07, 0x02831f07),
SOC15_REG_GOLDEN_VALUE(SDMA2, 0, mmSDMA2_GB_ADDR_CONFIG, 0x0000773f, 0x00004002),
SOC15_REG_GOLDEN_VALUE(SDMA2, 0, mmSDMA2_GB_ADDR_CONFIG_READ, 0x0000773f, 0x00004002),
SOC15_REG_GOLDEN_VALUE(SDMA2, 0, mmSDMA2_UTCL1_TIMEOUT, 0xffffffff, 0x00010001),
+};
+
+static const struct soc15_reg_golden golden_settings_arct_sdma3[] = {
SOC15_REG_GOLDEN_VALUE(SDMA3, 0, mmSDMA3_CHICKEN_BITS, 0xfe931f07, 0x02831f07),
SOC15_REG_GOLDEN_VALUE(SDMA3, 0, mmSDMA3_GB_ADDR_CONFIG, 0x0000773f, 0x00004002),
SOC15_REG_GOLDEN_VALUE(SDMA3, 0, mmSDMA3_GB_ADDR_CONFIG_READ, 0x0000773f, 0x00004002),
SOC15_REG_GOLDEN_VALUE(SDMA3, 0, mmSDMA3_UTCL1_TIMEOUT, 0xffffffff, 0x00010001),
+};
+
+static const struct soc15_reg_golden golden_settings_arct_sdma4[] = {
SOC15_REG_GOLDEN_VALUE(SDMA4, 0, mmSDMA4_CHICKEN_BITS, 0xfe931f07, 0x02831f07),
SOC15_REG_GOLDEN_VALUE(SDMA4, 0, mmSDMA4_GB_ADDR_CONFIG, 0x0000773f, 0x00004002),
SOC15_REG_GOLDEN_VALUE(SDMA4, 0, mmSDMA4_GB_ADDR_CONFIG_READ, 0x0000773f, 0x00004002),
SOC15_REG_GOLDEN_VALUE(SDMA4, 0, mmSDMA4_UTCL1_TIMEOUT, 0xffffffff, 0x00010001),
+};
+
+static const struct soc15_reg_golden golden_settings_arct_sdma5[] = {
SOC15_REG_GOLDEN_VALUE(SDMA5, 0, mmSDMA5_CHICKEN_BITS, 0xfe931f07, 0x02831f07),
SOC15_REG_GOLDEN_VALUE(SDMA5, 0, mmSDMA5_GB_ADDR_CONFIG, 0x0000773f, 0x00004002),
SOC15_REG_GOLDEN_VALUE(SDMA5, 0, mmSDMA5_GB_ADDR_CONFIG_READ, 0x0000773f, 0x00004002),
SOC15_REG_GOLDEN_VALUE(SDMA5, 0, mmSDMA5_UTCL1_TIMEOUT, 0xffffffff, 0x00010001),
+};
+
+static const struct soc15_reg_golden golden_settings_arct_sdma6[] = {
SOC15_REG_GOLDEN_VALUE(SDMA6, 0, mmSDMA6_CHICKEN_BITS, 0xfe931f07, 0x02831f07),
SOC15_REG_GOLDEN_VALUE(SDMA6, 0, mmSDMA6_GB_ADDR_CONFIG, 0x0000773f, 0x00004002),
SOC15_REG_GOLDEN_VALUE(SDMA6, 0, mmSDMA6_GB_ADDR_CONFIG_READ, 0x0000773f, 0x00004002),
SOC15_REG_GOLDEN_VALUE(SDMA6, 0, mmSDMA6_UTCL1_TIMEOUT, 0xffffffff, 0x00010001),
+};
+
+static const struct soc15_reg_golden golden_settings_arct_sdma7[] = {
SOC15_REG_GOLDEN_VALUE(SDMA7, 0, mmSDMA7_CHICKEN_BITS, 0xfe931f07, 0x02831f07),
SOC15_REG_GOLDEN_VALUE(SDMA7, 0, mmSDMA7_GB_ADDR_CONFIG, 0x0000773f, 0x00004002),
SOC15_REG_GOLDEN_VALUE(SDMA7, 0, mmSDMA7_GB_ADDR_CONFIG_READ, 0x0000773f, 0x00004002),
SOC15_REG_GOLDEN_VALUE(SDMA7, 0, mmSDMA7_UTCL1_TIMEOUT, 0xffffffff, 0x00010001)
};
-static const struct soc15_reg_golden golden_settings_sdma_aldebaran[] = {
+static const struct soc15_reg_golden golden_settings_aldebaran_sdma0[] = {
SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_GB_ADDR_CONFIG, 0x0018773f, 0x00104002),
SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_GB_ADDR_CONFIG_READ, 0x0018773f, 0x00104002),
SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_UTCL1_TIMEOUT, 0xffffffff, 0x00010001),
+};
+
+static const struct soc15_reg_golden golden_settings_aldebaran_sdma1[] = {
SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_GB_ADDR_CONFIG, 0x0018773f, 0x00104002),
SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_GB_ADDR_CONFIG_READ, 0x0018773f, 0x00104002),
SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_UTCL1_TIMEOUT, 0xffffffff, 0x00010001),
+};
+
+static const struct soc15_reg_golden golden_settings_aldebaran_sdma2[] = {
SOC15_REG_GOLDEN_VALUE(SDMA2, 0, mmSDMA2_GB_ADDR_CONFIG, 0x0018773f, 0x00104002),
SOC15_REG_GOLDEN_VALUE(SDMA2, 0, mmSDMA2_GB_ADDR_CONFIG_READ, 0x0018773f, 0x00104002),
SOC15_REG_GOLDEN_VALUE(SDMA3, 0, mmSDMA2_UTCL1_TIMEOUT, 0xffffffff, 0x00010001),
+};
+
+static const struct soc15_reg_golden golden_settings_aldebaran_sdma3[] = {
SOC15_REG_GOLDEN_VALUE(SDMA3, 0, mmSDMA3_GB_ADDR_CONFIG, 0x0018773f, 0x00104002),
SOC15_REG_GOLDEN_VALUE(SDMA3, 0, mmSDMA3_GB_ADDR_CONFIG_READ, 0x0018773f, 0x00104002),
SOC15_REG_GOLDEN_VALUE(SDMA3, 0, mmSDMA3_UTCL1_TIMEOUT, 0xffffffff, 0x00010001),
+};
+
+static const struct soc15_reg_golden golden_settings_aldebaran_sdma4[] = {
SOC15_REG_GOLDEN_VALUE(SDMA4, 0, mmSDMA4_GB_ADDR_CONFIG, 0x0018773f, 0x00104002),
SOC15_REG_GOLDEN_VALUE(SDMA4, 0, mmSDMA4_GB_ADDR_CONFIG_READ, 0x0018773f, 0x00104002),
SOC15_REG_GOLDEN_VALUE(SDMA4, 0, mmSDMA4_UTCL1_TIMEOUT, 0xffffffff, 0x00010001),
};
-static const struct soc15_reg_golden golden_settings_sdma_4_3[] = {
+static const struct soc15_reg_golden golden_settings_v4_3_sdma0[] = {
SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_CHICKEN_BITS, 0xfe931f07, 0x02831f07),
SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_CLK_CTRL, 0xffffffff, 0x3f000100),
SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_GB_ADDR_CONFIG, 0x0018773f, 0x00000002),
@@ -513,64 +551,155 @@ static int sdma_v4_0_irq_id_to_seq(unsigned client_id)
return -EINVAL;
}
-static void sdma_v4_0_init_golden_registers(struct amdgpu_device *adev)
+static void sdma_v4_0_init_golden_registers(struct amdgpu_device *adev, const u32 instance_id)
{
switch (amdgpu_ip_version(adev, SDMA0_HWIP, 0)) {
case IP_VERSION(4, 0, 0):
- soc15_program_register_sequence(adev,
- golden_settings_sdma_4,
- ARRAY_SIZE(golden_settings_sdma_4));
- soc15_program_register_sequence(adev,
- golden_settings_sdma_vg10,
- ARRAY_SIZE(golden_settings_sdma_vg10));
+ if (instance_id == 0) {
+ soc15_program_register_sequence(
+ adev,
+ golden_settings_v4_0_sdma0,
+ ARRAY_SIZE(golden_settings_v4_0_sdma0));
+ soc15_program_register_sequence(
+ adev,
+ golden_settings_vg10_sdma0,
+ ARRAY_SIZE(golden_settings_vg10_sdma0));
+ } else if (instance_id == 1) {
+ soc15_program_register_sequence(
+ adev,
+ golden_settings_v4_0_sdma1,
+ ARRAY_SIZE(golden_settings_v4_0_sdma1));
+ soc15_program_register_sequence(
+ adev,
+ golden_settings_vg10_sdma1,
+ ARRAY_SIZE(golden_settings_vg10_sdma1));
+ }
break;
case IP_VERSION(4, 0, 1):
- soc15_program_register_sequence(adev,
- golden_settings_sdma_4,
- ARRAY_SIZE(golden_settings_sdma_4));
- soc15_program_register_sequence(adev,
- golden_settings_sdma_vg12,
- ARRAY_SIZE(golden_settings_sdma_vg12));
+ if (instance_id == 0) {
+ soc15_program_register_sequence(
+ adev,
+ golden_settings_v4_0_sdma0,
+ ARRAY_SIZE(golden_settings_v4_0_sdma0));
+ soc15_program_register_sequence(
+ adev,
+ golden_settings_vg12_sdma0,
+ ARRAY_SIZE(golden_settings_vg12_sdma0));
+ } else if (instance_id == 1) {
+ soc15_program_register_sequence(
+ adev,
+ golden_settings_v4_0_sdma1,
+ ARRAY_SIZE(golden_settings_v4_0_sdma1));
+ soc15_program_register_sequence(
+ adev,
+ golden_settings_vg12_sdma1,
+ ARRAY_SIZE(golden_settings_vg12_sdma1));
+ }
break;
case IP_VERSION(4, 2, 0):
- soc15_program_register_sequence(adev,
- golden_settings_sdma0_4_2_init,
- ARRAY_SIZE(golden_settings_sdma0_4_2_init));
- soc15_program_register_sequence(adev,
- golden_settings_sdma0_4_2,
- ARRAY_SIZE(golden_settings_sdma0_4_2));
- soc15_program_register_sequence(adev,
- golden_settings_sdma1_4_2,
- ARRAY_SIZE(golden_settings_sdma1_4_2));
+ if (instance_id == 0) {
+ soc15_program_register_sequence(
+ adev,
+ golden_settings_v4_2_sdma0_init,
+ ARRAY_SIZE(golden_settings_v4_2_sdma0_init));
+ soc15_program_register_sequence(
+ adev,
+ golden_settings_v4_2_sdma0,
+ ARRAY_SIZE(golden_settings_v4_2_sdma0));
+ } else if (instance_id == 1) {
+ soc15_program_register_sequence(
+ adev,
+ golden_settings_v4_2_sdma1,
+ ARRAY_SIZE(golden_settings_v4_2_sdma1));
+ }
break;
case IP_VERSION(4, 2, 2):
- soc15_program_register_sequence(adev,
- golden_settings_sdma_arct,
- ARRAY_SIZE(golden_settings_sdma_arct));
+ if (instance_id == 0)
+ soc15_program_register_sequence(
+ adev,
+ golden_settings_arct_sdma0,
+ ARRAY_SIZE(golden_settings_arct_sdma0));
+ else if (instance_id == 1)
+ soc15_program_register_sequence(
+ adev,
+ golden_settings_arct_sdma1,
+ ARRAY_SIZE(golden_settings_arct_sdma1));
+ else if (instance_id == 2)
+ soc15_program_register_sequence(
+ adev,
+ golden_settings_arct_sdma2,
+ ARRAY_SIZE(golden_settings_arct_sdma2));
+ else if (instance_id == 3)
+ soc15_program_register_sequence(
+ adev,
+ golden_settings_arct_sdma3,
+ ARRAY_SIZE(golden_settings_arct_sdma3));
+ else if (instance_id == 4)
+ soc15_program_register_sequence(
+ adev,
+ golden_settings_arct_sdma4,
+ ARRAY_SIZE(golden_settings_arct_sdma4));
+ else if (instance_id == 5)
+ soc15_program_register_sequence(
+ adev,
+ golden_settings_arct_sdma5,
+ ARRAY_SIZE(golden_settings_arct_sdma5));
+ else if (instance_id == 6)
+ soc15_program_register_sequence(
+ adev,
+ golden_settings_arct_sdma6,
+ ARRAY_SIZE(golden_settings_arct_sdma6));
+ else if (instance_id == 7)
+ soc15_program_register_sequence(
+ adev,
+ golden_settings_arct_sdma7,
+ ARRAY_SIZE(golden_settings_arct_sdma7));
break;
case IP_VERSION(4, 4, 0):
- soc15_program_register_sequence(adev,
- golden_settings_sdma_aldebaran,
- ARRAY_SIZE(golden_settings_sdma_aldebaran));
+ if (instance_id == 0)
+ soc15_program_register_sequence(
+ adev,
+ golden_settings_aldebaran_sdma0,
+ ARRAY_SIZE(golden_settings_aldebaran_sdma0));
+ else if (instance_id == 1)
+ soc15_program_register_sequence(
+ adev,
+ golden_settings_aldebaran_sdma1,
+ ARRAY_SIZE(golden_settings_aldebaran_sdma1));
+ else if (instance_id == 2)
+ soc15_program_register_sequence(
+ adev,
+ golden_settings_aldebaran_sdma2,
+ ARRAY_SIZE(golden_settings_aldebaran_sdma2));
+ else if (instance_id == 3)
+ soc15_program_register_sequence(
+ adev,
+ golden_settings_aldebaran_sdma3,
+ ARRAY_SIZE(golden_settings_aldebaran_sdma3));
+ else if (instance_id == 4)
+ soc15_program_register_sequence(
+ adev,
+ golden_settings_aldebaran_sdma4,
+ ARRAY_SIZE(golden_settings_aldebaran_sdma4));
break;
case IP_VERSION(4, 1, 0):
case IP_VERSION(4, 1, 1):
soc15_program_register_sequence(adev,
- golden_settings_sdma_4_1,
- ARRAY_SIZE(golden_settings_sdma_4_1));
+ golden_settings_v4_1_sdma0,
+ ARRAY_SIZE(golden_settings_v4_1_sdma0));
if (adev->apu_flags & AMD_APU_IS_RAVEN2)
soc15_program_register_sequence(adev,
- golden_settings_sdma_rv2,
- ARRAY_SIZE(golden_settings_sdma_rv2));
+ golden_settings_rv2_sdma0,
+ ARRAY_SIZE(golden_settings_rv2_sdma0));
else
soc15_program_register_sequence(adev,
- golden_settings_sdma_rv1,
- ARRAY_SIZE(golden_settings_sdma_rv1));
+ golden_settings_rv1_sdma0,
+ ARRAY_SIZE(golden_settings_rv1_sdma0));
break;
case IP_VERSION(4, 1, 2):
soc15_program_register_sequence(adev,
- golden_settings_sdma_4_3,
- ARRAY_SIZE(golden_settings_sdma_4_3));
+ golden_settings_v4_3_sdma0,
+ ARRAY_SIZE(golden_settings_v4_3_sdma0));
break;
default:
break;
@@ -1353,6 +1482,7 @@ static int sdma_v4_0_start(struct amdgpu_device *adev, const u32 instance_id)
sdma_v4_0_ctx_switch_enable(adev, instance_id, false);
sdma_v4_0_enable(adev, instance_id, false);
} else {
+ sdma_v4_0_init_golden_registers(adev, instance_id);
if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP) {
r = sdma_v4_0_load_microcode(adev, instance_id);
@@ -1941,9 +2071,6 @@ static int sdma_v4_0_hw_init(struct amdgpu_ip_block *ip_block)
if (adev->flags & AMD_IS_APU)
amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_SDMA, false, 0);
- if (!amdgpu_sriov_vf(adev))
- sdma_v4_0_init_golden_registers(adev);
-
for (i = 0; i < adev->sdma.num_instances; ++i) {
r = sdma_v4_0_start(adev, i);
if (r)
--
2.55.0
^ permalink raw reply related [flat|nested] 17+ messages in thread* Re: [PATCH 00/12] RFC: drm/amdgpu/sdma: Refactor SDMA v4 and older functions to be per-instance
2026-09-07 20:33 [PATCH 00/12] RFC: drm/amdgpu/sdma: Refactor SDMA v4 and older functions to be per-instance Timur Kristóf
` (11 preceding siblings ...)
2026-09-07 20:33 ` [PATCH 12/12] drm/amdgpu/sdma: Refactor SDMA v4.0 golden registers " Timur Kristóf
@ 2026-09-11 19:00 ` Alex Deucher
12 siblings, 0 replies; 17+ messages in thread
From: Alex Deucher @ 2026-09-11 19:00 UTC (permalink / raw)
To: Timur Kristóf
Cc: amd-gfx, Marek Olšák, Alex Deucher,
Christian König, Tvrtko Ursulin, pierre-eric.pelloux-prayer,
Natalie Vock, Lijo Lazar, Felix Kuehling
On Mon, Sep 7, 2026 at 4:40 PM Timur Kristóf <timur.kristof@gmail.com> wrote:
>
> This series applies on top of my previous series:
> "Improve existing SDMA queue resets" (currently under review)
>
> Prepare the code for implementing recovery for
> SDMA v4 and all older SDMA (and SI DMA) versions.
> Reorganize the SDMA 4.0 code so that the functions that are
> responsible for managing the SDMA engines take an instance ID
> as an argument.
>
> This makes it possible to manage the SDMA instances
> independently of each other, which will enable us to
> also use these functions to implement resetting and
> recovering them independently. (The actual recovery
> implementation will be in a follow-up patch series
> which I will submit after this one is accepted.)
This series looks fine to me, although I think I would prefer to apply
it along with the relevant soft reset changes to avoid churning the
code until each family is ready. E.g., apply the cik_sdma refactor
along with the CIK soft reset support, etc. Unless you have something
else in mind. Series in general is:
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Alex
>
> Timur Kristóf (12):
> drm/amdgpu/sdma: Refactor SI DMA functions to be per instance
> drm/amdgpu/sdma: Refactor SI DMA clock gating functions to be
> per-instance
> drm/amdgpu/sdma: Refactor CIK SDMA functions to be per instance
> drm/amdgpu/sdma: Refactor CIK SDMA clock gating functions to be
> per-instance
> drm/amdgpu/sdma: Refactor SDMA v2.4 functions to be per instance
> drm/amdgpu/sdma: Refactor SDMA v2.4 golden registers to be
> per-instance
> drm/amdgpu/sdma: Refactor SDMA v3.0 functions to be per instance
> drm/amdgpu/sdma: Refactor SDMA v3.0 clock gating functions to be
> per-instance
> drm/amdgpu/sdma: Refactor SDMA v3.0 golden registers to be
> per-instance
> drm/amdgpu/sdma: Refactor SDMA v4.0 functions to be per instance
> drm/amdgpu/sdma: Refactor SDMA v4.0 clock gating functions to be
> per-instance
> drm/amdgpu/sdma: Refactor SDMA v4.0 golden registers to be
> per-instance
>
> drivers/gpu/drm/amd/amdgpu/cik_sdma.c | 322 +++++++-------
> drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c | 232 +++++-----
> drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c | 561 ++++++++++++++----------
> drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c | 577 +++++++++++++++----------
> drivers/gpu/drm/amd/amdgpu/si_dma.c | 160 ++++---
> 5 files changed, 1043 insertions(+), 809 deletions(-)
>
> --
> 2.55.0
>
^ permalink raw reply [flat|nested] 17+ messages in thread