Commit 763a47b8 authored by Andres Rodriguez's avatar Andres Rodriguez Committed by Alex Deucher

drm/amdgpu: teach amdgpu how to enable interrupts for any pipe v3

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: default avatarFelix Kuehling <Felix.Kuehling@amd.com>
Signed-off-by: default avatarAndres Rodriguez <andresx7@gmail.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 78c16834
...@@ -5066,42 +5066,28 @@ static void gfx_v7_0_set_compute_eop_interrupt_state(struct amdgpu_device *adev, ...@@ -5066,42 +5066,28 @@ static void gfx_v7_0_set_compute_eop_interrupt_state(struct amdgpu_device *adev,
int me, int pipe, int me, int pipe,
enum amdgpu_interrupt_state state) enum amdgpu_interrupt_state state)
{ {
u32 mec_int_cntl, mec_int_cntl_reg; /* 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
/*
* 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) {
if (me == 1) { DRM_ERROR("Ignoring request to enable interrupts for invalid me:%d\n", me);
switch (pipe) {
case 0:
mec_int_cntl_reg = mmCP_ME1_PIPE0_INT_CNTL;
break;
default:
DRM_DEBUG("invalid pipe %d\n", pipe);
return; 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; return;
} }
switch (state) { mutex_lock(&adev->srbm_mutex);
case AMDGPU_IRQ_STATE_DISABLE: cik_srbm_select(adev, me, pipe, 0, 0);
mec_int_cntl = RREG32(mec_int_cntl_reg);
mec_int_cntl &= ~CP_INT_CNTL_RING0__TIME_STAMP_INT_ENABLE_MASK; WREG32_FIELD(CPC_INT_CNTL, TIME_STAMP_INT_ENABLE,
WREG32(mec_int_cntl_reg, mec_int_cntl); state == AMDGPU_IRQ_STATE_DISABLE ? 0 : 1);
break;
case AMDGPU_IRQ_STATE_ENABLE: cik_srbm_select(adev, 0, 0, 0, 0);
mec_int_cntl = RREG32(mec_int_cntl_reg); mutex_unlock(&adev->srbm_mutex);
mec_int_cntl |= CP_INT_CNTL_RING0__TIME_STAMP_INT_ENABLE_MASK;
WREG32(mec_int_cntl_reg, mec_int_cntl);
break;
default:
break;
}
} }
static int gfx_v7_0_set_priv_reg_fault_state(struct amdgpu_device *adev, static int gfx_v7_0_set_priv_reg_fault_state(struct amdgpu_device *adev,
......
...@@ -6803,27 +6803,26 @@ static void gfx_v8_0_set_compute_eop_interrupt_state(struct amdgpu_device *adev, ...@@ -6803,27 +6803,26 @@ static void gfx_v8_0_set_compute_eop_interrupt_state(struct amdgpu_device *adev,
int me, int pipe, int me, int pipe,
enum amdgpu_interrupt_state state) enum amdgpu_interrupt_state state)
{ {
/* /* Me 0 is reserved for graphics */
* amdgpu controls only pipe 0 of MEC1. That's why this function only if (me < 1 || me > adev->gfx.mec.num_mec) {
* handles the setting of interrupts for this specific pipe. All other DRM_ERROR("Ignoring request to enable interrupts for invalid me:%d\n", me);
* pipes' interrupts are set by amdkfd.
*/
if (me == 1) {
switch (pipe) {
case 0:
break;
default:
DRM_DEBUG("invalid pipe %d\n", pipe);
return; 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; return;
} }
WREG32_FIELD(CP_ME1_PIPE0_INT_CNTL, TIME_STAMP_INT_ENABLE, 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); 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, static int gfx_v8_0_set_priv_reg_fault_state(struct amdgpu_device *adev,
......
...@@ -4147,44 +4147,26 @@ static void gfx_v9_0_set_compute_eop_interrupt_state(struct amdgpu_device *adev, ...@@ -4147,44 +4147,26 @@ static void gfx_v9_0_set_compute_eop_interrupt_state(struct amdgpu_device *adev,
int me, int pipe, int me, int pipe,
enum amdgpu_interrupt_state state) enum amdgpu_interrupt_state state)
{ {
u32 mec_int_cntl, mec_int_cntl_reg; /* 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);
* 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; 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; return;
} }
switch (state) { mutex_lock(&adev->srbm_mutex);
case AMDGPU_IRQ_STATE_DISABLE: soc15_grbm_select(adev, me, pipe, 0, 0);
mec_int_cntl = RREG32(mec_int_cntl_reg);
mec_int_cntl = REG_SET_FIELD(mec_int_cntl, CP_ME1_PIPE0_INT_CNTL, WREG32_FIELD(CPC_INT_CNTL, TIME_STAMP_INT_ENABLE,
TIME_STAMP_INT_ENABLE, 0); state == AMDGPU_IRQ_STATE_DISABLE ? 0 : 1);
WREG32(mec_int_cntl_reg, mec_int_cntl);
break; soc15_grbm_select(adev, 0, 0, 0, 0);
case AMDGPU_IRQ_STATE_ENABLE: mutex_unlock(&adev->srbm_mutex);
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;
}
} }
static int gfx_v9_0_set_priv_reg_fault_state(struct amdgpu_device *adev, static int gfx_v9_0_set_priv_reg_fault_state(struct amdgpu_device *adev,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment