int me, int pipe,
enum amdgpu_interrupt_state state)
{
- /* 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
+ u32 mec_int_cntl, mec_int_cntl_reg;
+
+ /*
+ * amdgpu controls only the first MEC. That's why this function only
+ * handles the setting of interrupts for this specific MEC. All other
+ * pipes' interrupts are set by amdkfd.
*/
- if (me != 1) {
- DRM_ERROR("Ignoring request to enable interrupts for invalid me:%d\n", me);
- return;
- }
- 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);
+ if (me == 1) {
+ switch (pipe) {
+ case 0:
+ mec_int_cntl_reg = mmCP_ME1_PIPE0_INT_CNTL;
+ break;
+ case 1:
+ mec_int_cntl_reg = mmCP_ME1_PIPE1_INT_CNTL;
+ break;
+ case 2:
+ mec_int_cntl_reg = mmCP_ME1_PIPE2_INT_CNTL;
+ break;
+ case 3:
+ mec_int_cntl_reg = mmCP_ME1_PIPE3_INT_CNTL;
+ break;
+ default:
+ DRM_DEBUG("invalid pipe %d\n", pipe);
+ return;
+ }
+ } else {
+ DRM_DEBUG("invalid me %d\n", 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);
+ 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;
+ }
}
static int gfx_v7_0_set_priv_reg_fault_state(struct amdgpu_device *adev,
int me, int pipe,
enum amdgpu_interrupt_state state)
{
- /* 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;
- }
+ u32 mec_int_cntl, mec_int_cntl_reg;
- 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);
+ /*
+ * amdgpu controls only the first MEC. That's why this function only
+ * handles the setting of interrupts for this specific MEC. All other
+ * pipes' interrupts are set by amdkfd.
+ */
+
+ if (me == 1) {
+ switch (pipe) {
+ case 0:
+ mec_int_cntl_reg = mmCP_ME1_PIPE0_INT_CNTL;
+ break;
+ case 1:
+ mec_int_cntl_reg = mmCP_ME1_PIPE1_INT_CNTL;
+ break;
+ case 2:
+ mec_int_cntl_reg = mmCP_ME1_PIPE2_INT_CNTL;
+ break;
+ case 3:
+ mec_int_cntl_reg = mmCP_ME1_PIPE3_INT_CNTL;
+ break;
+ default:
+ DRM_DEBUG("invalid pipe %d\n", pipe);
+ return;
+ }
+ } else {
+ DRM_DEBUG("invalid me %d\n", me);
return;
}
- 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);
+ 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;
+ }
}
static int gfx_v8_0_set_priv_reg_fault_state(struct amdgpu_device *adev,
int me, int pipe,
enum amdgpu_interrupt_state state)
{
- /* 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;
- }
+ u32 mec_int_cntl, mec_int_cntl_reg;
- 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);
+ /*
+ * amdgpu controls only the first MEC. That's why this function only
+ * handles the setting of interrupts for this specific MEC. 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;
+ case 1:
+ mec_int_cntl_reg = SOC15_REG_OFFSET(GC, 0, mmCP_ME1_PIPE1_INT_CNTL);
+ break;
+ case 2:
+ mec_int_cntl_reg = SOC15_REG_OFFSET(GC, 0, mmCP_ME1_PIPE2_INT_CNTL);
+ break;
+ case 3:
+ mec_int_cntl_reg = SOC15_REG_OFFSET(GC, 0, mmCP_ME1_PIPE3_INT_CNTL);
+ break;
+ default:
+ DRM_DEBUG("invalid pipe %d\n", pipe);
+ return;
+ }
+ } else {
+ DRM_DEBUG("invalid me %d\n", 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);
+ 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;
+ }
}
static int gfx_v9_0_set_priv_reg_fault_state(struct amdgpu_device *adev,