Commit cc066715 authored by Alex Deucher's avatar Alex Deucher

drm/radeon: update CIK soft reset

Update to the newer programming model.
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 44fa346f
...@@ -72,9 +72,11 @@ extern int r600_ih_ring_alloc(struct radeon_device *rdev); ...@@ -72,9 +72,11 @@ extern int r600_ih_ring_alloc(struct radeon_device *rdev);
extern void r600_ih_ring_fini(struct radeon_device *rdev); extern void r600_ih_ring_fini(struct radeon_device *rdev);
extern void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_save *save); extern void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_save *save);
extern void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_save *save); extern void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_save *save);
extern bool evergreen_is_display_hung(struct radeon_device *rdev);
extern void si_vram_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc); extern void si_vram_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc);
extern void si_rlc_fini(struct radeon_device *rdev); extern void si_rlc_fini(struct radeon_device *rdev);
extern int si_rlc_init(struct radeon_device *rdev); extern int si_rlc_init(struct radeon_device *rdev);
static void cik_rlc_stop(struct radeon_device *rdev);
#define BONAIRE_IO_MC_REGS_SIZE 36 #define BONAIRE_IO_MC_REGS_SIZE 36
...@@ -2733,56 +2735,9 @@ int cik_sdma_ib_test(struct radeon_device *rdev, struct radeon_ring *ring) ...@@ -2733,56 +2735,9 @@ int cik_sdma_ib_test(struct radeon_device *rdev, struct radeon_ring *ring)
return r; return r;
} }
/**
* cik_gpu_is_lockup - check if the 3D engine is locked up
*
* @rdev: radeon_device pointer
* @ring: radeon_ring structure holding ring information
*
* Check if the 3D engine is locked up (CIK).
* Returns true if the engine is locked, false if not.
*/
bool cik_gpu_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring)
{
u32 srbm_status, srbm_status2;
u32 grbm_status, grbm_status2;
u32 grbm_status_se0, grbm_status_se1, grbm_status_se2, grbm_status_se3;
srbm_status = RREG32(SRBM_STATUS);
srbm_status2 = RREG32(SRBM_STATUS2);
grbm_status = RREG32(GRBM_STATUS);
grbm_status2 = RREG32(GRBM_STATUS2);
grbm_status_se0 = RREG32(GRBM_STATUS_SE0);
grbm_status_se1 = RREG32(GRBM_STATUS_SE1);
grbm_status_se2 = RREG32(GRBM_STATUS_SE2);
grbm_status_se3 = RREG32(GRBM_STATUS_SE3);
if (!(grbm_status & GUI_ACTIVE)) {
radeon_ring_lockup_update(ring);
return false;
}
/* force CP activities */
radeon_ring_force_activity(rdev, ring);
return radeon_ring_test_lockup(rdev, ring);
}
/** static void cik_print_gpu_status_regs(struct radeon_device *rdev)
* cik_gfx_gpu_soft_reset - soft reset the 3D engine and CPG
*
* @rdev: radeon_device pointer
*
* Soft reset the GFX engine and CPG blocks (CIK).
* XXX: deal with reseting RLC and CPF
* Returns 0 for success.
*/
static int cik_gfx_gpu_soft_reset(struct radeon_device *rdev)
{ {
struct evergreen_mc_save save;
u32 grbm_reset = 0;
if (!(RREG32(GRBM_STATUS) & GUI_ACTIVE))
return 0;
dev_info(rdev->dev, "GPU GFX softreset \n");
dev_info(rdev->dev, " GRBM_STATUS=0x%08X\n", dev_info(rdev->dev, " GRBM_STATUS=0x%08X\n",
RREG32(GRBM_STATUS)); RREG32(GRBM_STATUS));
dev_info(rdev->dev, " GRBM_STATUS2=0x%08X\n", dev_info(rdev->dev, " GRBM_STATUS2=0x%08X\n",
...@@ -2799,132 +2754,270 @@ static int cik_gfx_gpu_soft_reset(struct radeon_device *rdev) ...@@ -2799,132 +2754,270 @@ static int cik_gfx_gpu_soft_reset(struct radeon_device *rdev)
RREG32(SRBM_STATUS)); RREG32(SRBM_STATUS));
dev_info(rdev->dev, " SRBM_STATUS2=0x%08X\n", dev_info(rdev->dev, " SRBM_STATUS2=0x%08X\n",
RREG32(SRBM_STATUS2)); RREG32(SRBM_STATUS2));
evergreen_mc_stop(rdev, &save); dev_info(rdev->dev, " SDMA0_STATUS_REG = 0x%08X\n",
if (radeon_mc_wait_for_idle(rdev)) { RREG32(SDMA0_STATUS_REG + SDMA0_REGISTER_OFFSET));
dev_warn(rdev->dev, "Wait for MC idle timedout !\n"); dev_info(rdev->dev, " SDMA1_STATUS_REG = 0x%08X\n",
} RREG32(SDMA0_STATUS_REG + SDMA1_REGISTER_OFFSET));
/* Disable CP parsing/prefetching */ }
WREG32(CP_ME_CNTL, CP_ME_HALT | CP_PFP_HALT | CP_CE_HALT);
/* reset all the gfx block and all CPG blocks */ /**
grbm_reset = SOFT_RESET_CPG | SOFT_RESET_GFX; * cik_gpu_check_soft_reset - check which blocks are busy
*
* @rdev: radeon_device pointer
*
* Check which blocks are busy and return the relevant reset
* mask to be used by cik_gpu_soft_reset().
* Returns a mask of the blocks to be reset.
*/
static u32 cik_gpu_check_soft_reset(struct radeon_device *rdev)
{
u32 reset_mask = 0;
u32 tmp;
dev_info(rdev->dev, " GRBM_SOFT_RESET=0x%08X\n", grbm_reset); /* GRBM_STATUS */
WREG32(GRBM_SOFT_RESET, grbm_reset); tmp = RREG32(GRBM_STATUS);
(void)RREG32(GRBM_SOFT_RESET); if (tmp & (PA_BUSY | SC_BUSY |
udelay(50); BCI_BUSY | SX_BUSY |
WREG32(GRBM_SOFT_RESET, 0); TA_BUSY | VGT_BUSY |
(void)RREG32(GRBM_SOFT_RESET); DB_BUSY | CB_BUSY |
/* Wait a little for things to settle down */ GDS_BUSY | SPI_BUSY |
udelay(50); IA_BUSY | IA_BUSY_NO_DMA))
dev_info(rdev->dev, " GRBM_STATUS=0x%08X\n", reset_mask |= RADEON_RESET_GFX;
RREG32(GRBM_STATUS));
dev_info(rdev->dev, " GRBM_STATUS2=0x%08X\n", if (tmp & (CP_BUSY | CP_COHERENCY_BUSY))
RREG32(GRBM_STATUS2)); reset_mask |= RADEON_RESET_CP;
dev_info(rdev->dev, " GRBM_STATUS_SE0=0x%08X\n",
RREG32(GRBM_STATUS_SE0)); /* GRBM_STATUS2 */
dev_info(rdev->dev, " GRBM_STATUS_SE1=0x%08X\n", tmp = RREG32(GRBM_STATUS2);
RREG32(GRBM_STATUS_SE1)); if (tmp & RLC_BUSY)
dev_info(rdev->dev, " GRBM_STATUS_SE2=0x%08X\n", reset_mask |= RADEON_RESET_RLC;
RREG32(GRBM_STATUS_SE2));
dev_info(rdev->dev, " GRBM_STATUS_SE3=0x%08X\n", /* SDMA0_STATUS_REG */
RREG32(GRBM_STATUS_SE3)); tmp = RREG32(SDMA0_STATUS_REG + SDMA0_REGISTER_OFFSET);
dev_info(rdev->dev, " SRBM_STATUS=0x%08X\n", if (!(tmp & SDMA_IDLE))
RREG32(SRBM_STATUS)); reset_mask |= RADEON_RESET_DMA;
dev_info(rdev->dev, " SRBM_STATUS2=0x%08X\n",
RREG32(SRBM_STATUS2)); /* SDMA1_STATUS_REG */
evergreen_mc_resume(rdev, &save); tmp = RREG32(SDMA0_STATUS_REG + SDMA1_REGISTER_OFFSET);
return 0; if (!(tmp & SDMA_IDLE))
reset_mask |= RADEON_RESET_DMA1;
/* SRBM_STATUS2 */
tmp = RREG32(SRBM_STATUS2);
if (tmp & SDMA_BUSY)
reset_mask |= RADEON_RESET_DMA;
if (tmp & SDMA1_BUSY)
reset_mask |= RADEON_RESET_DMA1;
/* SRBM_STATUS */
tmp = RREG32(SRBM_STATUS);
if (tmp & IH_BUSY)
reset_mask |= RADEON_RESET_IH;
if (tmp & SEM_BUSY)
reset_mask |= RADEON_RESET_SEM;
if (tmp & GRBM_RQ_PENDING)
reset_mask |= RADEON_RESET_GRBM;
if (tmp & VMC_BUSY)
reset_mask |= RADEON_RESET_VMC;
if (tmp & (MCB_BUSY | MCB_NON_DISPLAY_BUSY |
MCC_BUSY | MCD_BUSY))
reset_mask |= RADEON_RESET_MC;
if (evergreen_is_display_hung(rdev))
reset_mask |= RADEON_RESET_DISPLAY;
/* Skip MC reset as it's mostly likely not hung, just busy */
if (reset_mask & RADEON_RESET_MC) {
DRM_DEBUG("MC busy: 0x%08X, clearing.\n", reset_mask);
reset_mask &= ~RADEON_RESET_MC;
}
return reset_mask;
} }
/** /**
* cik_compute_gpu_soft_reset - soft reset CPC * cik_gpu_soft_reset - soft reset GPU
* *
* @rdev: radeon_device pointer * @rdev: radeon_device pointer
* @reset_mask: mask of which blocks to reset
* *
* Soft reset the CPC blocks (CIK). * Soft reset the blocks specified in @reset_mask.
* XXX: deal with reseting RLC and CPF
* Returns 0 for success.
*/ */
static int cik_compute_gpu_soft_reset(struct radeon_device *rdev) static void cik_gpu_soft_reset(struct radeon_device *rdev, u32 reset_mask)
{ {
struct evergreen_mc_save save; struct evergreen_mc_save save;
u32 grbm_reset = 0; u32 grbm_soft_reset = 0, srbm_soft_reset = 0;
u32 tmp;
if (reset_mask == 0)
return;
dev_info(rdev->dev, "GPU softreset: 0x%08X\n", reset_mask);
cik_print_gpu_status_regs(rdev);
dev_info(rdev->dev, " VM_CONTEXT1_PROTECTION_FAULT_ADDR 0x%08X\n",
RREG32(VM_CONTEXT1_PROTECTION_FAULT_ADDR));
dev_info(rdev->dev, " VM_CONTEXT1_PROTECTION_FAULT_STATUS 0x%08X\n",
RREG32(VM_CONTEXT1_PROTECTION_FAULT_STATUS));
/* stop the rlc */
cik_rlc_stop(rdev);
/* Disable GFX parsing/prefetching */
WREG32(CP_ME_CNTL, CP_ME_HALT | CP_PFP_HALT | CP_CE_HALT);
/* Disable MEC parsing/prefetching */
WREG32(CP_MEC_CNTL, MEC_ME1_HALT | MEC_ME2_HALT);
if (reset_mask & RADEON_RESET_DMA) {
/* sdma0 */
tmp = RREG32(SDMA0_ME_CNTL + SDMA0_REGISTER_OFFSET);
tmp |= SDMA_HALT;
WREG32(SDMA0_ME_CNTL + SDMA0_REGISTER_OFFSET, tmp);
}
if (reset_mask & RADEON_RESET_DMA1) {
/* sdma1 */
tmp = RREG32(SDMA0_ME_CNTL + SDMA1_REGISTER_OFFSET);
tmp |= SDMA_HALT;
WREG32(SDMA0_ME_CNTL + SDMA1_REGISTER_OFFSET, tmp);
}
dev_info(rdev->dev, "GPU compute softreset \n");
dev_info(rdev->dev, " GRBM_STATUS=0x%08X\n",
RREG32(GRBM_STATUS));
dev_info(rdev->dev, " GRBM_STATUS2=0x%08X\n",
RREG32(GRBM_STATUS2));
dev_info(rdev->dev, " GRBM_STATUS_SE0=0x%08X\n",
RREG32(GRBM_STATUS_SE0));
dev_info(rdev->dev, " GRBM_STATUS_SE1=0x%08X\n",
RREG32(GRBM_STATUS_SE1));
dev_info(rdev->dev, " GRBM_STATUS_SE2=0x%08X\n",
RREG32(GRBM_STATUS_SE2));
dev_info(rdev->dev, " GRBM_STATUS_SE3=0x%08X\n",
RREG32(GRBM_STATUS_SE3));
dev_info(rdev->dev, " SRBM_STATUS=0x%08X\n",
RREG32(SRBM_STATUS));
dev_info(rdev->dev, " SRBM_STATUS2=0x%08X\n",
RREG32(SRBM_STATUS2));
evergreen_mc_stop(rdev, &save); evergreen_mc_stop(rdev, &save);
if (radeon_mc_wait_for_idle(rdev)) { if (evergreen_mc_wait_for_idle(rdev)) {
dev_warn(rdev->dev, "Wait for MC idle timedout !\n"); dev_warn(rdev->dev, "Wait for MC idle timedout !\n");
} }
/* Disable CP parsing/prefetching */
WREG32(CP_MEC_CNTL, MEC_ME1_HALT | MEC_ME2_HALT);
/* reset all the CPC blocks */ if (reset_mask & (RADEON_RESET_GFX | RADEON_RESET_COMPUTE | RADEON_RESET_CP))
grbm_reset = SOFT_RESET_CPG; grbm_soft_reset = SOFT_RESET_CP | SOFT_RESET_GFX;
if (reset_mask & RADEON_RESET_CP) {
grbm_soft_reset |= SOFT_RESET_CP;
srbm_soft_reset |= SOFT_RESET_GRBM;
}
if (reset_mask & RADEON_RESET_DMA)
srbm_soft_reset |= SOFT_RESET_SDMA;
if (reset_mask & RADEON_RESET_DMA1)
srbm_soft_reset |= SOFT_RESET_SDMA1;
if (reset_mask & RADEON_RESET_DISPLAY)
srbm_soft_reset |= SOFT_RESET_DC;
if (reset_mask & RADEON_RESET_RLC)
grbm_soft_reset |= SOFT_RESET_RLC;
if (reset_mask & RADEON_RESET_SEM)
srbm_soft_reset |= SOFT_RESET_SEM;
if (reset_mask & RADEON_RESET_IH)
srbm_soft_reset |= SOFT_RESET_IH;
if (reset_mask & RADEON_RESET_GRBM)
srbm_soft_reset |= SOFT_RESET_GRBM;
if (reset_mask & RADEON_RESET_VMC)
srbm_soft_reset |= SOFT_RESET_VMC;
if (!(rdev->flags & RADEON_IS_IGP)) {
if (reset_mask & RADEON_RESET_MC)
srbm_soft_reset |= SOFT_RESET_MC;
}
if (grbm_soft_reset) {
tmp = RREG32(GRBM_SOFT_RESET);
tmp |= grbm_soft_reset;
dev_info(rdev->dev, "GRBM_SOFT_RESET=0x%08X\n", tmp);
WREG32(GRBM_SOFT_RESET, tmp);
tmp = RREG32(GRBM_SOFT_RESET);
udelay(50);
tmp &= ~grbm_soft_reset;
WREG32(GRBM_SOFT_RESET, tmp);
tmp = RREG32(GRBM_SOFT_RESET);
}
if (srbm_soft_reset) {
tmp = RREG32(SRBM_SOFT_RESET);
tmp |= srbm_soft_reset;
dev_info(rdev->dev, "SRBM_SOFT_RESET=0x%08X\n", tmp);
WREG32(SRBM_SOFT_RESET, tmp);
tmp = RREG32(SRBM_SOFT_RESET);
udelay(50);
tmp &= ~srbm_soft_reset;
WREG32(SRBM_SOFT_RESET, tmp);
tmp = RREG32(SRBM_SOFT_RESET);
}
dev_info(rdev->dev, " GRBM_SOFT_RESET=0x%08X\n", grbm_reset);
WREG32(GRBM_SOFT_RESET, grbm_reset);
(void)RREG32(GRBM_SOFT_RESET);
udelay(50);
WREG32(GRBM_SOFT_RESET, 0);
(void)RREG32(GRBM_SOFT_RESET);
/* Wait a little for things to settle down */ /* Wait a little for things to settle down */
udelay(50); udelay(50);
dev_info(rdev->dev, " GRBM_STATUS=0x%08X\n",
RREG32(GRBM_STATUS));
dev_info(rdev->dev, " GRBM_STATUS2=0x%08X\n",
RREG32(GRBM_STATUS2));
dev_info(rdev->dev, " GRBM_STATUS_SE0=0x%08X\n",
RREG32(GRBM_STATUS_SE0));
dev_info(rdev->dev, " GRBM_STATUS_SE1=0x%08X\n",
RREG32(GRBM_STATUS_SE1));
dev_info(rdev->dev, " GRBM_STATUS_SE2=0x%08X\n",
RREG32(GRBM_STATUS_SE2));
dev_info(rdev->dev, " GRBM_STATUS_SE3=0x%08X\n",
RREG32(GRBM_STATUS_SE3));
dev_info(rdev->dev, " SRBM_STATUS=0x%08X\n",
RREG32(SRBM_STATUS));
dev_info(rdev->dev, " SRBM_STATUS2=0x%08X\n",
RREG32(SRBM_STATUS2));
evergreen_mc_resume(rdev, &save); evergreen_mc_resume(rdev, &save);
return 0; udelay(50);
cik_print_gpu_status_regs(rdev);
} }
/** /**
* cik_asic_reset - soft reset compute and gfx * cik_asic_reset - soft reset GPU
* *
* @rdev: radeon_device pointer * @rdev: radeon_device pointer
* *
* Soft reset the CPC blocks (CIK). * Look up which blocks are hung and attempt
* XXX: make this more fine grained and only reset * to reset them.
* what is necessary.
* Returns 0 for success. * Returns 0 for success.
*/ */
int cik_asic_reset(struct radeon_device *rdev) int cik_asic_reset(struct radeon_device *rdev)
{ {
int r; u32 reset_mask;
r = cik_compute_gpu_soft_reset(rdev); reset_mask = cik_gpu_check_soft_reset(rdev);
if (r)
dev_info(rdev->dev, "Compute reset failed!\n"); if (reset_mask)
r600_set_bios_scratch_engine_hung(rdev, true);
cik_gpu_soft_reset(rdev, reset_mask);
return cik_gfx_gpu_soft_reset(rdev); reset_mask = cik_gpu_check_soft_reset(rdev);
if (!reset_mask)
r600_set_bios_scratch_engine_hung(rdev, false);
return 0;
}
/**
* cik_gfx_is_lockup - check if the 3D engine is locked up
*
* @rdev: radeon_device pointer
* @ring: radeon_ring structure holding ring information
*
* Check if the 3D engine is locked up (CIK).
* Returns true if the engine is locked, false if not.
*/
bool cik_gfx_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring)
{
u32 reset_mask = cik_gpu_check_soft_reset(rdev);
if (!(reset_mask & (RADEON_RESET_GFX |
RADEON_RESET_COMPUTE |
RADEON_RESET_CP))) {
radeon_ring_lockup_update(ring);
return false;
}
/* force CP activities */
radeon_ring_force_activity(rdev, ring);
return radeon_ring_test_lockup(rdev, ring);
} }
/** /**
...@@ -2938,13 +3031,15 @@ int cik_asic_reset(struct radeon_device *rdev) ...@@ -2938,13 +3031,15 @@ int cik_asic_reset(struct radeon_device *rdev)
*/ */
bool cik_sdma_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring) bool cik_sdma_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring)
{ {
u32 dma_status_reg; u32 reset_mask = cik_gpu_check_soft_reset(rdev);
u32 mask;
if (ring->idx == R600_RING_TYPE_DMA_INDEX) if (ring->idx == R600_RING_TYPE_DMA_INDEX)
dma_status_reg = RREG32(SDMA0_STATUS_REG + SDMA0_REGISTER_OFFSET); mask = RADEON_RESET_DMA;
else else
dma_status_reg = RREG32(SDMA0_STATUS_REG + SDMA1_REGISTER_OFFSET); mask = RADEON_RESET_DMA1;
if (dma_status_reg & SDMA_IDLE) {
if (!(reset_mask & mask)) {
radeon_ring_lockup_update(ring); radeon_ring_lockup_update(ring);
return false; return false;
} }
......
...@@ -40,7 +40,19 @@ ...@@ -40,7 +40,19 @@
#define QUEUEID(x) ((x) << 8) #define QUEUEID(x) ((x) << 8)
#define SRBM_STATUS2 0xE4C #define SRBM_STATUS2 0xE4C
#define SDMA_BUSY (1 << 5)
#define SDMA1_BUSY (1 << 6)
#define SRBM_STATUS 0xE50 #define SRBM_STATUS 0xE50
#define UVD_RQ_PENDING (1 << 1)
#define GRBM_RQ_PENDING (1 << 5)
#define VMC_BUSY (1 << 8)
#define MCB_BUSY (1 << 9)
#define MCB_NON_DISPLAY_BUSY (1 << 10)
#define MCC_BUSY (1 << 11)
#define MCD_BUSY (1 << 12)
#define SEM_BUSY (1 << 14)
#define IH_BUSY (1 << 17)
#define UVD_BUSY (1 << 19)
#define SRBM_SOFT_RESET 0xE60 #define SRBM_SOFT_RESET 0xE60
#define SOFT_RESET_BIF (1 << 1) #define SOFT_RESET_BIF (1 << 1)
......
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