The current implementation is hardcoded to enable ME1/PIPE0 interrupts only. This patch allows amdgpu to enable interrupts for any pipe of ME1. v2: added gfx9 support v3: use soc15_grbm_select for gfx9 Acked-by: Felix Kuehling <Felix.Kuehling at amd.com> Signed-off-by: Andres Rodriguez <andresx7 at gmail.com> --- drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c | 48 ++++++++++++--------------------- drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c | 33 +++++++++++------------ drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c | 50 +++++++++++------------------------ 3 files changed, 49 insertions(+), 82 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c index 8520b4b..8969c69 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c @@ -5047,76 +5047,62 @@ static void gfx_v7_0_set_gfx_eop_interrupt_state(struct amdgpu_device *adev, switch (state) { case AMDGPU_IRQ_STATE_DISABLE: cp_int_cntl = RREG32(mmCP_INT_CNTL_RING0); cp_int_cntl &= ~CP_INT_CNTL_RING0__TIME_STAMP_INT_ENABLE_MASK; WREG32(mmCP_INT_CNTL_RING0, cp_int_cntl); break; case AMDGPU_IRQ_STATE_ENABLE: cp_int_cntl = RREG32(mmCP_INT_CNTL_RING0); cp_int_cntl |= CP_INT_CNTL_RING0__TIME_STAMP_INT_ENABLE_MASK; WREG32(mmCP_INT_CNTL_RING0, cp_int_cntl); break; default: break; } } static void gfx_v7_0_set_compute_eop_interrupt_state(struct amdgpu_device *adev, int me, int pipe, enum amdgpu_interrupt_state state) { - u32 mec_int_cntl, mec_int_cntl_reg; - - /* - * amdgpu controls only pipe 0 of MEC1. That's why this function only - * handles the setting of interrupts for this specific pipe. All other - * pipes' interrupts are set by amdkfd. + /* Me 0 is for graphics and Me 2 is reserved for HW scheduling + * So we should only really be configuring ME 1 i.e. MEC0 */ - - if (me == 1) { - switch (pipe) { - case 0: - mec_int_cntl_reg = mmCP_ME1_PIPE0_INT_CNTL; - break; - default: - DRM_DEBUG("invalid pipe %d\n", pipe); - return; - } - } else { - DRM_DEBUG("invalid me %d\n", me); + if (me != 1) { + DRM_ERROR("Ignoring request to enable interrupts for invalid me:%d\n", me); return; } - switch (state) { - case AMDGPU_IRQ_STATE_DISABLE: - mec_int_cntl = RREG32(mec_int_cntl_reg); - mec_int_cntl &= ~CP_INT_CNTL_RING0__TIME_STAMP_INT_ENABLE_MASK; - WREG32(mec_int_cntl_reg, mec_int_cntl); - break; - case AMDGPU_IRQ_STATE_ENABLE: - mec_int_cntl = RREG32(mec_int_cntl_reg); - mec_int_cntl |= CP_INT_CNTL_RING0__TIME_STAMP_INT_ENABLE_MASK; - WREG32(mec_int_cntl_reg, mec_int_cntl); - break; - default: - break; + if (pipe >= adev->gfx.mec.num_pipe_per_mec) { + DRM_ERROR("Ignoring request to enable interrupts for invalid " + "me:%d pipe:%d\n", pipe, me); + return; } + + mutex_lock(&adev->srbm_mutex); + cik_srbm_select(adev, me, pipe, 0, 0); + + WREG32_FIELD(CPC_INT_CNTL, TIME_STAMP_INT_ENABLE, + state == AMDGPU_IRQ_STATE_DISABLE ? 0 : 1); + + cik_srbm_select(adev, 0, 0, 0, 0); + mutex_unlock(&adev->srbm_mutex); } static int gfx_v7_0_set_priv_reg_fault_state(struct amdgpu_device *adev, struct amdgpu_irq_src *src, unsigned type, enum amdgpu_interrupt_state state) { u32 cp_int_cntl; switch (state) { case AMDGPU_IRQ_STATE_DISABLE: cp_int_cntl = RREG32(mmCP_INT_CNTL_RING0); cp_int_cntl &= ~CP_INT_CNTL_RING0__PRIV_REG_INT_ENABLE_MASK; WREG32(mmCP_INT_CNTL_RING0, cp_int_cntl); break; case AMDGPU_IRQ_STATE_ENABLE: cp_int_cntl = RREG32(mmCP_INT_CNTL_RING0); cp_int_cntl |= CP_INT_CNTL_RING0__PRIV_REG_INT_ENABLE_MASK; WREG32(mmCP_INT_CNTL_RING0, cp_int_cntl); break; diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c index fc94e2b..8cc9874 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c @@ -6769,61 +6769,60 @@ static void gfx_v8_0_ring_emit_wreg(struct amdgpu_ring *ring, uint32_t reg, uint32_t val) { amdgpu_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3)); amdgpu_ring_write(ring, (1 << 16)); /* no inc addr */ amdgpu_ring_write(ring, reg); amdgpu_ring_write(ring, 0); amdgpu_ring_write(ring, val); } static void gfx_v8_0_set_gfx_eop_interrupt_state(struct amdgpu_device *adev, enum amdgpu_interrupt_state state) { WREG32_FIELD(CP_INT_CNTL_RING0, TIME_STAMP_INT_ENABLE, state == AMDGPU_IRQ_STATE_DISABLE ? 0 : 1); } static void gfx_v8_0_set_compute_eop_interrupt_state(struct amdgpu_device *adev, int me, int pipe, enum amdgpu_interrupt_state state) { - /* - * amdgpu controls only pipe 0 of MEC1. That's why this function only - * handles the setting of interrupts for this specific pipe. All other - * pipes' interrupts are set by amdkfd. - */ + /* Me 0 is reserved for graphics */ + if (me < 1 || me > adev->gfx.mec.num_mec) { + DRM_ERROR("Ignoring request to enable interrupts for invalid me:%d\n", me); + return; + } - if (me == 1) { - switch (pipe) { - case 0: - break; - default: - DRM_DEBUG("invalid pipe %d\n", pipe); - return; - } - } else { - DRM_DEBUG("invalid me %d\n", me); + if (pipe >= adev->gfx.mec.num_pipe_per_mec) { + DRM_ERROR("Ignoring request to enable interrupts for invalid " + "me:%d pipe:%d\n", pipe, me); return; } - WREG32_FIELD(CP_ME1_PIPE0_INT_CNTL, TIME_STAMP_INT_ENABLE, - state == AMDGPU_IRQ_STATE_DISABLE ? 0 : 1); + mutex_lock(&adev->srbm_mutex); + vi_srbm_select(adev, me, pipe, 0, 0); + + WREG32_FIELD(CPC_INT_CNTL, TIME_STAMP_INT_ENABLE, + state == AMDGPU_IRQ_STATE_DISABLE ? 0 : 1); + + vi_srbm_select(adev, 0, 0, 0, 0); + mutex_unlock(&adev->srbm_mutex); } static int gfx_v8_0_set_priv_reg_fault_state(struct amdgpu_device *adev, struct amdgpu_irq_src *source, unsigned type, enum amdgpu_interrupt_state state) { WREG32_FIELD(CP_INT_CNTL_RING0, PRIV_REG_INT_ENABLE, state == AMDGPU_IRQ_STATE_DISABLE ? 0 : 1); return 0; } static int gfx_v8_0_set_priv_inst_fault_state(struct amdgpu_device *adev, struct amdgpu_irq_src *source, unsigned type, enum amdgpu_interrupt_state state) { WREG32_FIELD(CP_INT_CNTL_RING0, PRIV_INSTR_INT_ENABLE, state == AMDGPU_IRQ_STATE_DISABLE ? 0 : 1); diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c index fef0fbf..6208493 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c @@ -3257,78 +3257,60 @@ static void gfx_v9_0_ring_emit_wreg(struct amdgpu_ring *ring, uint32_t reg, static void gfx_v9_0_set_gfx_eop_interrupt_state(struct amdgpu_device *adev, enum amdgpu_interrupt_state state) { switch (state) { case AMDGPU_IRQ_STATE_DISABLE: case AMDGPU_IRQ_STATE_ENABLE: WREG32_FIELD15(GC, 0, CP_INT_CNTL_RING0, TIME_STAMP_INT_ENABLE, state == AMDGPU_IRQ_STATE_ENABLE ? 1 : 0); break; default: break; } } static void gfx_v9_0_set_compute_eop_interrupt_state(struct amdgpu_device *adev, int me, int pipe, enum amdgpu_interrupt_state state) { - u32 mec_int_cntl, mec_int_cntl_reg; - - /* - * amdgpu controls only pipe 0 of MEC1. That's why this function only - * handles the setting of interrupts for this specific pipe. All other - * pipes' interrupts are set by amdkfd. - */ - - if (me == 1) { - switch (pipe) { - case 0: - mec_int_cntl_reg = SOC15_REG_OFFSET(GC, 0, mmCP_ME1_PIPE0_INT_CNTL); - break; - default: - DRM_DEBUG("invalid pipe %d\n", pipe); - return; - } - } else { - DRM_DEBUG("invalid me %d\n", me); + /* Me 0 is reserved for graphics */ + if (me < 1 || me > adev->gfx.mec.num_mec) { + DRM_ERROR("Ignoring request to enable interrupts for invalid me:%d\n", me); return; } - switch (state) { - case AMDGPU_IRQ_STATE_DISABLE: - mec_int_cntl = RREG32(mec_int_cntl_reg); - mec_int_cntl = REG_SET_FIELD(mec_int_cntl, CP_ME1_PIPE0_INT_CNTL, - TIME_STAMP_INT_ENABLE, 0); - WREG32(mec_int_cntl_reg, mec_int_cntl); - break; - case AMDGPU_IRQ_STATE_ENABLE: - mec_int_cntl = RREG32(mec_int_cntl_reg); - mec_int_cntl = REG_SET_FIELD(mec_int_cntl, CP_ME1_PIPE0_INT_CNTL, - TIME_STAMP_INT_ENABLE, 1); - WREG32(mec_int_cntl_reg, mec_int_cntl); - break; - default: - break; + if (pipe >= adev->gfx.mec.num_pipe_per_mec) { + DRM_ERROR("Ignoring request to enable interrupts for invalid " + "me:%d pipe:%d\n", pipe, me); + return; } + + mutex_lock(&adev->srbm_mutex); + soc15_grbm_select(adev, me, pipe, 0, 0); + + WREG32_FIELD(CPC_INT_CNTL, TIME_STAMP_INT_ENABLE, + state == AMDGPU_IRQ_STATE_DISABLE ? 0 : 1); + + soc15_grbm_select(adev, 0, 0, 0, 0); + mutex_unlock(&adev->srbm_mutex); } static int gfx_v9_0_set_priv_reg_fault_state(struct amdgpu_device *adev, struct amdgpu_irq_src *source, unsigned type, enum amdgpu_interrupt_state state) { switch (state) { case AMDGPU_IRQ_STATE_DISABLE: case AMDGPU_IRQ_STATE_ENABLE: WREG32_FIELD15(GC, 0, CP_INT_CNTL_RING0, PRIV_REG_INT_ENABLE, state == AMDGPU_IRQ_STATE_ENABLE ? 1 : 0); break; default: break; } return 0; } -- 2.9.3