drm/amdgpu/gfx: fix MEC interrupt enablement for pipes != 0
authorAlex Deucher <alexander.deucher@amd.com>
Fri, 9 Jun 2017 12:22:31 +0000 (08:22 -0400)
committerAlex Deucher <alexander.deucher@amd.com>
Fri, 9 Jun 2017 15:30:42 +0000 (11:30 -0400)
The interrupt registers are not indexed.

Fixes: 763a47b8e (drm/amdgpu: teach amdgpu how to enable interrupts for any pipe v3)
Acked-by: Christian König <christian.koenig@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c
drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c

index e30c7d0bd0f916bd65abd668bc863869fed6543a..fb0a94c52945da11a4d31f834304c2ee3780cd7c 100644 (file)
@@ -5015,28 +5015,51 @@ static void gfx_v7_0_set_compute_eop_interrupt_state(struct amdgpu_device *adev,
                                                     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,
index 6e541af0e8994d0f70d4d34623e7a7442f1c7428..1a75ab1d18232b153c84b36a4921579ee492c4af 100644 (file)
@@ -6610,26 +6610,51 @@ static void gfx_v8_0_set_compute_eop_interrupt_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,
index 375620afd328f913efc5abfb7e2e3f82d2f7760e..e9dd2c183a584ad97b0221691a7fc17baa4e6fbb 100644 (file)
@@ -3982,26 +3982,53 @@ static void gfx_v9_0_set_compute_eop_interrupt_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,