Loading drivers/gpu/drm/radeon/cik.c +241 −146 Original line number Diff line number Diff line Loading @@ -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 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 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_rlc_fini(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 Loading Loading @@ -2733,56 +2735,9 @@ int cik_sdma_ib_test(struct radeon_device *rdev, struct radeon_ring *ring) 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); } /** * 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) static void cik_print_gpu_status_regs(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", RREG32(GRBM_STATUS)); dev_info(rdev->dev, " GRBM_STATUS2=0x%08X\n", Loading @@ -2799,132 +2754,270 @@ static int cik_gfx_gpu_soft_reset(struct radeon_device *rdev) RREG32(SRBM_STATUS)); dev_info(rdev->dev, " SRBM_STATUS2=0x%08X\n", RREG32(SRBM_STATUS2)); evergreen_mc_stop(rdev, &save); if (radeon_mc_wait_for_idle(rdev)) { dev_warn(rdev->dev, "Wait for MC idle timedout !\n"); dev_info(rdev->dev, " SDMA0_STATUS_REG = 0x%08X\n", RREG32(SDMA0_STATUS_REG + SDMA0_REGISTER_OFFSET)); 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); 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 */ 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); return 0; /* GRBM_STATUS */ tmp = RREG32(GRBM_STATUS); if (tmp & (PA_BUSY | SC_BUSY | BCI_BUSY | SX_BUSY | TA_BUSY | VGT_BUSY | DB_BUSY | CB_BUSY | GDS_BUSY | SPI_BUSY | IA_BUSY | IA_BUSY_NO_DMA)) reset_mask |= RADEON_RESET_GFX; if (tmp & (CP_BUSY | CP_COHERENCY_BUSY)) reset_mask |= RADEON_RESET_CP; /* GRBM_STATUS2 */ tmp = RREG32(GRBM_STATUS2); if (tmp & RLC_BUSY) reset_mask |= RADEON_RESET_RLC; /* SDMA0_STATUS_REG */ tmp = RREG32(SDMA0_STATUS_REG + SDMA0_REGISTER_OFFSET); if (!(tmp & SDMA_IDLE)) reset_mask |= RADEON_RESET_DMA; /* SDMA1_STATUS_REG */ tmp = RREG32(SDMA0_STATUS_REG + SDMA1_REGISTER_OFFSET); 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 * @reset_mask: mask of which blocks to reset * * Soft reset the CPC blocks (CIK). * XXX: deal with reseting RLC and CPF * Returns 0 for success. * Soft reset the blocks specified in @reset_mask. */ 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; 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); if (radeon_mc_wait_for_idle(rdev)) { if (evergreen_mc_wait_for_idle(rdev)) { 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 */ grbm_reset = SOFT_RESET_CPG; if (reset_mask & (RADEON_RESET_GFX | RADEON_RESET_COMPUTE | RADEON_RESET_CP)) 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); 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); 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); } /* Wait a little for things to settle down */ 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); 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 * * Soft reset the CPC blocks (CIK). * XXX: make this more fine grained and only reset * what is necessary. * Look up which blocks are hung and attempt * to reset them. * Returns 0 for success. */ int cik_asic_reset(struct radeon_device *rdev) { int r; u32 reset_mask; r = cik_compute_gpu_soft_reset(rdev); if (r) dev_info(rdev->dev, "Compute reset failed!\n"); reset_mask = cik_gpu_check_soft_reset(rdev); 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); } /** Loading @@ -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) { u32 dma_status_reg; u32 reset_mask = cik_gpu_check_soft_reset(rdev); u32 mask; if (ring->idx == R600_RING_TYPE_DMA_INDEX) dma_status_reg = RREG32(SDMA0_STATUS_REG + SDMA0_REGISTER_OFFSET); mask = RADEON_RESET_DMA; else dma_status_reg = RREG32(SDMA0_STATUS_REG + SDMA1_REGISTER_OFFSET); if (dma_status_reg & SDMA_IDLE) { mask = RADEON_RESET_DMA1; if (!(reset_mask & mask)) { radeon_ring_lockup_update(ring); return false; } Loading drivers/gpu/drm/radeon/cikd.h +12 −0 Original line number Diff line number Diff line Loading @@ -40,7 +40,19 @@ #define QUEUEID(x) ((x) << 8) #define SRBM_STATUS2 0xE4C #define SDMA_BUSY (1 << 5) #define SDMA1_BUSY (1 << 6) #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 SOFT_RESET_BIF (1 << 1) Loading Loading
drivers/gpu/drm/radeon/cik.c +241 −146 Original line number Diff line number Diff line Loading @@ -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 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 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_rlc_fini(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 Loading Loading @@ -2733,56 +2735,9 @@ int cik_sdma_ib_test(struct radeon_device *rdev, struct radeon_ring *ring) 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); } /** * 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) static void cik_print_gpu_status_regs(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", RREG32(GRBM_STATUS)); dev_info(rdev->dev, " GRBM_STATUS2=0x%08X\n", Loading @@ -2799,132 +2754,270 @@ static int cik_gfx_gpu_soft_reset(struct radeon_device *rdev) RREG32(SRBM_STATUS)); dev_info(rdev->dev, " SRBM_STATUS2=0x%08X\n", RREG32(SRBM_STATUS2)); evergreen_mc_stop(rdev, &save); if (radeon_mc_wait_for_idle(rdev)) { dev_warn(rdev->dev, "Wait for MC idle timedout !\n"); dev_info(rdev->dev, " SDMA0_STATUS_REG = 0x%08X\n", RREG32(SDMA0_STATUS_REG + SDMA0_REGISTER_OFFSET)); 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); 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 */ 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); return 0; /* GRBM_STATUS */ tmp = RREG32(GRBM_STATUS); if (tmp & (PA_BUSY | SC_BUSY | BCI_BUSY | SX_BUSY | TA_BUSY | VGT_BUSY | DB_BUSY | CB_BUSY | GDS_BUSY | SPI_BUSY | IA_BUSY | IA_BUSY_NO_DMA)) reset_mask |= RADEON_RESET_GFX; if (tmp & (CP_BUSY | CP_COHERENCY_BUSY)) reset_mask |= RADEON_RESET_CP; /* GRBM_STATUS2 */ tmp = RREG32(GRBM_STATUS2); if (tmp & RLC_BUSY) reset_mask |= RADEON_RESET_RLC; /* SDMA0_STATUS_REG */ tmp = RREG32(SDMA0_STATUS_REG + SDMA0_REGISTER_OFFSET); if (!(tmp & SDMA_IDLE)) reset_mask |= RADEON_RESET_DMA; /* SDMA1_STATUS_REG */ tmp = RREG32(SDMA0_STATUS_REG + SDMA1_REGISTER_OFFSET); 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 * @reset_mask: mask of which blocks to reset * * Soft reset the CPC blocks (CIK). * XXX: deal with reseting RLC and CPF * Returns 0 for success. * Soft reset the blocks specified in @reset_mask. */ 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; 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); if (radeon_mc_wait_for_idle(rdev)) { if (evergreen_mc_wait_for_idle(rdev)) { 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 */ grbm_reset = SOFT_RESET_CPG; if (reset_mask & (RADEON_RESET_GFX | RADEON_RESET_COMPUTE | RADEON_RESET_CP)) 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); 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); 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); } /* Wait a little for things to settle down */ 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); 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 * * Soft reset the CPC blocks (CIK). * XXX: make this more fine grained and only reset * what is necessary. * Look up which blocks are hung and attempt * to reset them. * Returns 0 for success. */ int cik_asic_reset(struct radeon_device *rdev) { int r; u32 reset_mask; r = cik_compute_gpu_soft_reset(rdev); if (r) dev_info(rdev->dev, "Compute reset failed!\n"); reset_mask = cik_gpu_check_soft_reset(rdev); 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); } /** Loading @@ -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) { u32 dma_status_reg; u32 reset_mask = cik_gpu_check_soft_reset(rdev); u32 mask; if (ring->idx == R600_RING_TYPE_DMA_INDEX) dma_status_reg = RREG32(SDMA0_STATUS_REG + SDMA0_REGISTER_OFFSET); mask = RADEON_RESET_DMA; else dma_status_reg = RREG32(SDMA0_STATUS_REG + SDMA1_REGISTER_OFFSET); if (dma_status_reg & SDMA_IDLE) { mask = RADEON_RESET_DMA1; if (!(reset_mask & mask)) { radeon_ring_lockup_update(ring); return false; } Loading
drivers/gpu/drm/radeon/cikd.h +12 −0 Original line number Diff line number Diff line Loading @@ -40,7 +40,19 @@ #define QUEUEID(x) ((x) << 8) #define SRBM_STATUS2 0xE4C #define SDMA_BUSY (1 << 5) #define SDMA1_BUSY (1 << 6) #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 SOFT_RESET_BIF (1 << 1) Loading