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 <[email protected]> --- 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
