Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 64c56e8c authored by Jerome Glisse's avatar Jerome Glisse Committed by Alex Deucher
Browse files

drm/radeon: reset dma engine on gpu reset (v2)



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: default avatarJerome Glisse <jglisse@redhat.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent eaaa6983
Loading
Loading
Loading
Loading
+21 −9
Original line number Diff line number Diff line
@@ -2309,7 +2309,7 @@ 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;
@@ -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 |
+9 −1
Original line number Diff line number Diff line
@@ -742,6 +742,7 @@
#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)
@@ -2028,6 +2029,13 @@
#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
+26 −9
Original line number Diff line number Diff line
@@ -1309,7 +1309,7 @@ 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;
@@ -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 |
+22 −6
Original line number Diff line number Diff line
@@ -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)) {
+17 −1
Original line number Diff line number Diff line
@@ -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 |
Loading