drm/radeon: reset dma engine on gpu reset (v2)
authorJerome Glisse <jglisse@redhat.com>
Wed, 2 Jan 2013 22:30:35 +0000 (17:30 -0500)
committerAlex Deucher <alexander.deucher@amd.com>
Thu, 3 Jan 2013 18:18:41 +0000 (13:18 -0500)
This try to reset the dma engine when performing gpu reset. Hopefully
bringing back the gpu dma engine in sane state.

v2: agd5f: fix dma reset on cayman/TN, add support for SI

Signed-off-by: Jerome Glisse <jglisse@redhat.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/radeon/evergreen.c
drivers/gpu/drm/radeon/evergreend.h
drivers/gpu/drm/radeon/ni.c
drivers/gpu/drm/radeon/nid.h
drivers/gpu/drm/radeon/r600.c
drivers/gpu/drm/radeon/si.c
drivers/gpu/drm/radeon/sid.h

index 6dc9ee78f4a8abe8d312429b4e3492a9c37bb968..f92f6bb18872c6c48bc3f2d8b3dc189a381ba5db 100644 (file)
@@ -2309,19 +2309,19 @@ bool evergreen_gpu_is_lockup(struct radeon_device *rdev, struct radeon_ring *rin
 static int evergreen_gpu_soft_reset(struct radeon_device *rdev)
 {
        struct evergreen_mc_save save;
-       u32 grbm_reset = 0;
+       u32 grbm_reset = 0, tmp;
 
        if (!(RREG32(GRBM_STATUS) & GUI_ACTIVE))
                return 0;
 
        dev_info(rdev->dev, "GPU softreset \n");
-       dev_info(rdev->dev, "  GRBM_STATUS=0x%08X\n",
+       dev_info(rdev->dev, "  GRBM_STATUS               = 0x%08X\n",
                RREG32(GRBM_STATUS));
-       dev_info(rdev->dev, "  GRBM_STATUS_SE0=0x%08X\n",
+       dev_info(rdev->dev, "  GRBM_STATUS_SE0           = 0x%08X\n",
                RREG32(GRBM_STATUS_SE0));
-       dev_info(rdev->dev, "  GRBM_STATUS_SE1=0x%08X\n",
+       dev_info(rdev->dev, "  GRBM_STATUS_SE1           = 0x%08X\n",
                RREG32(GRBM_STATUS_SE1));
-       dev_info(rdev->dev, "  SRBM_STATUS=0x%08X\n",
+       dev_info(rdev->dev, "  SRBM_STATUS               = 0x%08X\n",
                RREG32(SRBM_STATUS));
        dev_info(rdev->dev, "  R_008674_CP_STALLED_STAT1 = 0x%08X\n",
                RREG32(CP_STALLED_STAT1));
@@ -2337,9 +2337,21 @@ static int evergreen_gpu_soft_reset(struct radeon_device *rdev)
        if (evergreen_mc_wait_for_idle(rdev)) {
                dev_warn(rdev->dev, "Wait for MC idle timedout !\n");
        }
+
        /* Disable CP parsing/prefetching */
        WREG32(CP_ME_CNTL, CP_ME_HALT | CP_PFP_HALT);
 
+       /* Disable DMA */
+       tmp = RREG32(DMA_RB_CNTL);
+       tmp &= ~DMA_RB_ENABLE;
+       WREG32(DMA_RB_CNTL, tmp);
+
+       /* Reset dma */
+       WREG32(SRBM_SOFT_RESET, SOFT_RESET_DMA);
+       RREG32(SRBM_SOFT_RESET);
+       udelay(50);
+       WREG32(SRBM_SOFT_RESET, 0);
+
        /* reset all the gfx blocks */
        grbm_reset = (SOFT_RESET_CP |
                      SOFT_RESET_CB |
@@ -2362,13 +2374,13 @@ static int evergreen_gpu_soft_reset(struct radeon_device *rdev)
        (void)RREG32(GRBM_SOFT_RESET);
        /* Wait a little for things to settle down */
        udelay(50);
-       dev_info(rdev->dev, "  GRBM_STATUS=0x%08X\n",
+       dev_info(rdev->dev, "  GRBM_STATUS               = 0x%08X\n",
                RREG32(GRBM_STATUS));
-       dev_info(rdev->dev, "  GRBM_STATUS_SE0=0x%08X\n",
+       dev_info(rdev->dev, "  GRBM_STATUS_SE0           = 0x%08X\n",
                RREG32(GRBM_STATUS_SE0));
-       dev_info(rdev->dev, "  GRBM_STATUS_SE1=0x%08X\n",
+       dev_info(rdev->dev, "  GRBM_STATUS_SE1           = 0x%08X\n",
                RREG32(GRBM_STATUS_SE1));
-       dev_info(rdev->dev, "  SRBM_STATUS=0x%08X\n",
+       dev_info(rdev->dev, "  SRBM_STATUS               = 0x%08X\n",
                RREG32(SRBM_STATUS));
        dev_info(rdev->dev, "  R_008674_CP_STALLED_STAT1 = 0x%08X\n",
                RREG32(CP_STALLED_STAT1));
index f82f98a11a7610091ede6a0a8f5f2cdca8ece8ab..5786a32e7bdae26ac1de91f51b53202c5bdc0069 100644 (file)
 #define                SOFT_RESET_ROM                          (1 << 14)
 #define                SOFT_RESET_SEM                          (1 << 15)
 #define                SOFT_RESET_VMC                          (1 << 17)
+#define                SOFT_RESET_DMA                          (1 << 20)
 #define                SOFT_RESET_TST                          (1 << 21)
-#define                SOFT_RESET_REGBB                        (1 << 22)
+#define                SOFT_RESET_REGBB                        (1 << 22)
 #define                SOFT_RESET_ORB                          (1 << 23)
 
 /* display watermarks */
 #define        CAYMAN_PACKET3_DEALLOC_STATE                    0x14
 
 /* DMA regs common on r6xx/r7xx/evergreen/ni */
+#define DMA_RB_CNTL                                       0xd000
+#       define DMA_RB_ENABLE                              (1 << 0)
+#       define DMA_RB_SIZE(x)                             ((x) << 1) /* log2 */
+#       define DMA_RB_SWAP_ENABLE                         (1 << 9) /* 8IN32 */
+#       define DMA_RPTR_WRITEBACK_ENABLE                  (1 << 12)
+#       define DMA_RPTR_WRITEBACK_SWAP_ENABLE             (1 << 13)  /* 8IN32 */
+#       define DMA_RPTR_WRITEBACK_TIMER(x)                ((x) << 16) /* log2 */
 #define DMA_STATUS_REG                                    0xd034
 
 #endif
index 6dae3878e39716592b08b32b5731d4298d6784ac..8a9a75d1cb00f810277dcec248925b8134c5b1e6 100644 (file)
@@ -1309,19 +1309,19 @@ void cayman_dma_fini(struct radeon_device *rdev)
 static int cayman_gpu_soft_reset(struct radeon_device *rdev)
 {
        struct evergreen_mc_save save;
-       u32 grbm_reset = 0;
+       u32 grbm_reset = 0, tmp;
 
        if (!(RREG32(GRBM_STATUS) & GUI_ACTIVE))
                return 0;
 
        dev_info(rdev->dev, "GPU softreset \n");
-       dev_info(rdev->dev, "  GRBM_STATUS=0x%08X\n",
+       dev_info(rdev->dev, "  GRBM_STATUS               = 0x%08X\n",
                RREG32(GRBM_STATUS));
-       dev_info(rdev->dev, "  GRBM_STATUS_SE0=0x%08X\n",
+       dev_info(rdev->dev, "  GRBM_STATUS_SE0           = 0x%08X\n",
                RREG32(GRBM_STATUS_SE0));
-       dev_info(rdev->dev, "  GRBM_STATUS_SE1=0x%08X\n",
+       dev_info(rdev->dev, "  GRBM_STATUS_SE1           = 0x%08X\n",
                RREG32(GRBM_STATUS_SE1));
-       dev_info(rdev->dev, "  SRBM_STATUS=0x%08X\n",
+       dev_info(rdev->dev, "  SRBM_STATUS               = 0x%08X\n",
                RREG32(SRBM_STATUS));
        dev_info(rdev->dev, "  R_008674_CP_STALLED_STAT1 = 0x%08X\n",
                RREG32(CP_STALLED_STAT1));
@@ -1346,9 +1346,26 @@ static int cayman_gpu_soft_reset(struct radeon_device *rdev)
        if (evergreen_mc_wait_for_idle(rdev)) {
                dev_warn(rdev->dev, "Wait for MC idle timedout !\n");
        }
+
        /* Disable CP parsing/prefetching */
        WREG32(CP_ME_CNTL, CP_ME_HALT | CP_PFP_HALT);
 
+       /* dma0 */
+       tmp = RREG32(DMA_RB_CNTL + DMA0_REGISTER_OFFSET);
+       tmp &= ~DMA_RB_ENABLE;
+       WREG32(DMA_RB_CNTL + DMA0_REGISTER_OFFSET, tmp);
+
+       /* dma1 */
+       tmp = RREG32(DMA_RB_CNTL + DMA1_REGISTER_OFFSET);
+       tmp &= ~DMA_RB_ENABLE;
+       WREG32(DMA_RB_CNTL + DMA1_REGISTER_OFFSET, tmp);
+
+       /* Reset dma */
+       WREG32(SRBM_SOFT_RESET, SOFT_RESET_DMA | SOFT_RESET_DMA1);
+       RREG32(SRBM_SOFT_RESET);
+       udelay(50);
+       WREG32(SRBM_SOFT_RESET, 0);
+
        /* reset all the gfx blocks */
        grbm_reset = (SOFT_RESET_CP |
                      SOFT_RESET_CB |
@@ -1373,13 +1390,13 @@ static int cayman_gpu_soft_reset(struct radeon_device *rdev)
        /* Wait a little for things to settle down */
        udelay(50);
 
-       dev_info(rdev->dev, "  GRBM_STATUS=0x%08X\n",
+       dev_info(rdev->dev, "  GRBM_STATUS               = 0x%08X\n",
                RREG32(GRBM_STATUS));
-       dev_info(rdev->dev, "  GRBM_STATUS_SE0=0x%08X\n",
+       dev_info(rdev->dev, "  GRBM_STATUS_SE0           = 0x%08X\n",
                RREG32(GRBM_STATUS_SE0));
-       dev_info(rdev->dev, "  GRBM_STATUS_SE1=0x%08X\n",
+       dev_info(rdev->dev, "  GRBM_STATUS_SE1           = 0x%08X\n",
                RREG32(GRBM_STATUS_SE1));
-       dev_info(rdev->dev, "  SRBM_STATUS=0x%08X\n",
+       dev_info(rdev->dev, "  SRBM_STATUS               = 0x%08X\n",
                RREG32(SRBM_STATUS));
        dev_info(rdev->dev, "  R_008674_CP_STALLED_STAT1 = 0x%08X\n",
                RREG32(CP_STALLED_STAT1));
index 22a62c673fec3887447f3a48a09cb0671a8386d4..48e5022ee921d33081f86de17d8ab6b0520ea037 100644 (file)
@@ -65,7 +65,7 @@
 #define                SOFT_RESET_VMC                          (1 << 17)
 #define                SOFT_RESET_DMA                          (1 << 20)
 #define                SOFT_RESET_TST                          (1 << 21)
-#define                SOFT_RESET_REGBB                        (1 << 22)
+#define                SOFT_RESET_REGBB                        (1 << 22)
 #define                SOFT_RESET_ORB                          (1 << 23)
 
 #define VM_CONTEXT0_REQUEST_RESPONSE                   0x1470
index 252067bba2d91bbdeb162dd168520f415b59db4c..721b5afd792a569f4d16e174d06cb030b6314e36 100644 (file)
@@ -1283,11 +1283,11 @@ static int r600_gpu_soft_reset(struct radeon_device *rdev)
                return 0;
 
        dev_info(rdev->dev, "GPU softreset \n");
-       dev_info(rdev->dev, "  R_008010_GRBM_STATUS=0x%08X\n",
+       dev_info(rdev->dev, "  R_008010_GRBM_STATUS      = 0x%08X\n",
                RREG32(R_008010_GRBM_STATUS));
-       dev_info(rdev->dev, "  R_008014_GRBM_STATUS2=0x%08X\n",
+       dev_info(rdev->dev, "  R_008014_GRBM_STATUS2     = 0x%08X\n",
                RREG32(R_008014_GRBM_STATUS2));
-       dev_info(rdev->dev, "  R_000E50_SRBM_STATUS=0x%08X\n",
+       dev_info(rdev->dev, "  R_000E50_SRBM_STATUS      = 0x%08X\n",
                RREG32(R_000E50_SRBM_STATUS));
        dev_info(rdev->dev, "  R_008674_CP_STALLED_STAT1 = 0x%08X\n",
                RREG32(CP_STALLED_STAT1));
@@ -1303,8 +1303,24 @@ static int r600_gpu_soft_reset(struct radeon_device *rdev)
        if (r600_mc_wait_for_idle(rdev)) {
                dev_warn(rdev->dev, "Wait for MC idle timedout !\n");
        }
+
        /* Disable CP parsing/prefetching */
        WREG32(R_0086D8_CP_ME_CNTL, S_0086D8_CP_ME_HALT(1));
+
+       /* Disable DMA */
+       tmp = RREG32(DMA_RB_CNTL);
+       tmp &= ~DMA_RB_ENABLE;
+       WREG32(DMA_RB_CNTL, tmp);
+
+       /* Reset dma */
+       if (rdev->family >= CHIP_RV770)
+               WREG32(SRBM_SOFT_RESET, RV770_SOFT_RESET_DMA);
+       else
+               WREG32(SRBM_SOFT_RESET, SOFT_RESET_DMA);
+       RREG32(SRBM_SOFT_RESET);
+       udelay(50);
+       WREG32(SRBM_SOFT_RESET, 0);
+
        /* Check if any of the rendering block is busy and reset it */
        if ((RREG32(R_008010_GRBM_STATUS) & grbm_busy_mask) ||
            (RREG32(R_008014_GRBM_STATUS2) & grbm2_busy_mask)) {
@@ -1336,11 +1352,11 @@ static int r600_gpu_soft_reset(struct radeon_device *rdev)
        WREG32(R_008020_GRBM_SOFT_RESET, 0);
        /* Wait a little for things to settle down */
        mdelay(1);
-       dev_info(rdev->dev, "  R_008010_GRBM_STATUS=0x%08X\n",
+       dev_info(rdev->dev, "  R_008010_GRBM_STATUS      = 0x%08X\n",
                RREG32(R_008010_GRBM_STATUS));
-       dev_info(rdev->dev, "  R_008014_GRBM_STATUS2=0x%08X\n",
+       dev_info(rdev->dev, "  R_008014_GRBM_STATUS2     = 0x%08X\n",
                RREG32(R_008014_GRBM_STATUS2));
-       dev_info(rdev->dev, "  R_000E50_SRBM_STATUS=0x%08X\n",
+       dev_info(rdev->dev, "  R_000E50_SRBM_STATUS      = 0x%08X\n",
                RREG32(R_000E50_SRBM_STATUS));
        dev_info(rdev->dev, "  R_008674_CP_STALLED_STAT1 = 0x%08X\n",
                RREG32(CP_STALLED_STAT1));
index 74d38452c5c18235903d0c9bf3acf085be9e8174..4bf17334927a722e8e38b10f5cbfc927dec8dc79 100644 (file)
@@ -2129,7 +2129,7 @@ bool si_gpu_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring)
 static int si_gpu_soft_reset(struct radeon_device *rdev)
 {
        struct evergreen_mc_save save;
-       u32 grbm_reset = 0;
+       u32 grbm_reset = 0, tmp;
 
        if (!(RREG32(GRBM_STATUS) & GUI_ACTIVE))
                return 0;
@@ -2159,6 +2159,22 @@ static int si_gpu_soft_reset(struct radeon_device *rdev)
        /* Disable CP parsing/prefetching */
        WREG32(CP_ME_CNTL, CP_ME_HALT | CP_PFP_HALT | CP_CE_HALT);
 
+       /* dma0 */
+       tmp = RREG32(DMA_RB_CNTL + DMA0_REGISTER_OFFSET);
+       tmp &= ~DMA_RB_ENABLE;
+       WREG32(DMA_RB_CNTL + DMA0_REGISTER_OFFSET, tmp);
+
+       /* dma1 */
+       tmp = RREG32(DMA_RB_CNTL + DMA1_REGISTER_OFFSET);
+       tmp &= ~DMA_RB_ENABLE;
+       WREG32(DMA_RB_CNTL + DMA1_REGISTER_OFFSET, tmp);
+
+       /* Reset dma */
+       WREG32(SRBM_SOFT_RESET, SOFT_RESET_DMA | SOFT_RESET_DMA1);
+       RREG32(SRBM_SOFT_RESET);
+       udelay(50);
+       WREG32(SRBM_SOFT_RESET, 0);
+
        /* reset all the gfx blocks */
        grbm_reset = (SOFT_RESET_CP |
                      SOFT_RESET_CB |
index 98909b264ac2f2508604b0974443d1bb777308a7..c056aae814f090693a4eb445d83d3ca2be30efd7 100644 (file)
 
 #define        SRBM_STATUS                                     0xE50
 
+#define        SRBM_SOFT_RESET                                 0x0E60
+#define                SOFT_RESET_BIF                          (1 << 1)
+#define                SOFT_RESET_DC                           (1 << 5)
+#define                SOFT_RESET_DMA1                         (1 << 6)
+#define                SOFT_RESET_GRBM                         (1 << 8)
+#define                SOFT_RESET_HDP                          (1 << 9)
+#define                SOFT_RESET_IH                           (1 << 10)
+#define                SOFT_RESET_MC                           (1 << 11)
+#define                SOFT_RESET_ROM                          (1 << 14)
+#define                SOFT_RESET_SEM                          (1 << 15)
+#define                SOFT_RESET_VMC                          (1 << 17)
+#define                SOFT_RESET_DMA                          (1 << 20)
+#define                SOFT_RESET_TST                          (1 << 21)
+#define                SOFT_RESET_REGBB                        (1 << 22)
+#define                SOFT_RESET_ORB                          (1 << 23)
+
 #define        CC_SYS_RB_BACKEND_DISABLE                       0xe80
 #define        GC_USER_SYS_RB_BACKEND_DISABLE                  0xe84