drm/radeon: Add support for CIK GPU reset (v2)
v2: split soft reset into compute and gfx. Still need to make reset more fine grained, but this should be a start. Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
parent
8cc1a5328b
commit
6f2043ce15
|
@ -27,9 +27,13 @@
|
|||
#include <linux/module.h>
|
||||
#include "drmP.h"
|
||||
#include "radeon.h"
|
||||
#include "radeon_asic.h"
|
||||
#include "cikd.h"
|
||||
#include "atom.h"
|
||||
|
||||
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);
|
||||
|
||||
/*
|
||||
* Core functions
|
||||
*/
|
||||
|
@ -1190,3 +1194,196 @@ static void cik_gpu_init(struct radeon_device *rdev)
|
|||
udelay(50);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
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",
|
||||
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)) {
|
||||
dev_warn(rdev->dev, "Wait for MC idle timedout !\n");
|
||||
}
|
||||
/* 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;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* cik_compute_gpu_soft_reset - soft reset CPC
|
||||
*
|
||||
* @rdev: radeon_device pointer
|
||||
*
|
||||
* Soft reset the CPC blocks (CIK).
|
||||
* XXX: deal with reseting RLC and CPF
|
||||
* Returns 0 for success.
|
||||
*/
|
||||
static int cik_compute_gpu_soft_reset(struct radeon_device *rdev)
|
||||
{
|
||||
struct evergreen_mc_save save;
|
||||
u32 grbm_reset = 0;
|
||||
|
||||
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)) {
|
||||
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;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* cik_asic_reset - soft reset compute and gfx
|
||||
*
|
||||
* @rdev: radeon_device pointer
|
||||
*
|
||||
* Soft reset the CPC blocks (CIK).
|
||||
* XXX: make this more fine grained and only reset
|
||||
* what is necessary.
|
||||
* Returns 0 for success.
|
||||
*/
|
||||
int cik_asic_reset(struct radeon_device *rdev)
|
||||
{
|
||||
int r;
|
||||
|
||||
r = cik_compute_gpu_soft_reset(rdev);
|
||||
if (r)
|
||||
dev_info(rdev->dev, "Compute reset failed!\n");
|
||||
|
||||
return cik_gfx_gpu_soft_reset(rdev);
|
||||
}
|
||||
|
|
|
@ -30,6 +30,9 @@
|
|||
|
||||
#define DMIF_ADDR_CALC 0xC00
|
||||
|
||||
#define SRBM_STATUS2 0xE4C
|
||||
#define SRBM_STATUS 0xE50
|
||||
|
||||
#define MC_SHARED_CHMAP 0x2004
|
||||
#define NOOFCHAN_SHIFT 12
|
||||
#define NOOFCHAN_MASK 0x0000f000
|
||||
|
@ -65,6 +68,83 @@
|
|||
#define GRBM_CNTL 0x8000
|
||||
#define GRBM_READ_TIMEOUT(x) ((x) << 0)
|
||||
|
||||
#define GRBM_STATUS2 0x8008
|
||||
#define ME0PIPE1_CMDFIFO_AVAIL_MASK 0x0000000F
|
||||
#define ME0PIPE1_CF_RQ_PENDING (1 << 4)
|
||||
#define ME0PIPE1_PF_RQ_PENDING (1 << 5)
|
||||
#define ME1PIPE0_RQ_PENDING (1 << 6)
|
||||
#define ME1PIPE1_RQ_PENDING (1 << 7)
|
||||
#define ME1PIPE2_RQ_PENDING (1 << 8)
|
||||
#define ME1PIPE3_RQ_PENDING (1 << 9)
|
||||
#define ME2PIPE0_RQ_PENDING (1 << 10)
|
||||
#define ME2PIPE1_RQ_PENDING (1 << 11)
|
||||
#define ME2PIPE2_RQ_PENDING (1 << 12)
|
||||
#define ME2PIPE3_RQ_PENDING (1 << 13)
|
||||
#define RLC_RQ_PENDING (1 << 14)
|
||||
#define RLC_BUSY (1 << 24)
|
||||
#define TC_BUSY (1 << 25)
|
||||
#define CPF_BUSY (1 << 28)
|
||||
#define CPC_BUSY (1 << 29)
|
||||
#define CPG_BUSY (1 << 30)
|
||||
|
||||
#define GRBM_STATUS 0x8010
|
||||
#define ME0PIPE0_CMDFIFO_AVAIL_MASK 0x0000000F
|
||||
#define SRBM_RQ_PENDING (1 << 5)
|
||||
#define ME0PIPE0_CF_RQ_PENDING (1 << 7)
|
||||
#define ME0PIPE0_PF_RQ_PENDING (1 << 8)
|
||||
#define GDS_DMA_RQ_PENDING (1 << 9)
|
||||
#define DB_CLEAN (1 << 12)
|
||||
#define CB_CLEAN (1 << 13)
|
||||
#define TA_BUSY (1 << 14)
|
||||
#define GDS_BUSY (1 << 15)
|
||||
#define WD_BUSY_NO_DMA (1 << 16)
|
||||
#define VGT_BUSY (1 << 17)
|
||||
#define IA_BUSY_NO_DMA (1 << 18)
|
||||
#define IA_BUSY (1 << 19)
|
||||
#define SX_BUSY (1 << 20)
|
||||
#define WD_BUSY (1 << 21)
|
||||
#define SPI_BUSY (1 << 22)
|
||||
#define BCI_BUSY (1 << 23)
|
||||
#define SC_BUSY (1 << 24)
|
||||
#define PA_BUSY (1 << 25)
|
||||
#define DB_BUSY (1 << 26)
|
||||
#define CP_COHERENCY_BUSY (1 << 28)
|
||||
#define CP_BUSY (1 << 29)
|
||||
#define CB_BUSY (1 << 30)
|
||||
#define GUI_ACTIVE (1 << 31)
|
||||
#define GRBM_STATUS_SE0 0x8014
|
||||
#define GRBM_STATUS_SE1 0x8018
|
||||
#define GRBM_STATUS_SE2 0x8038
|
||||
#define GRBM_STATUS_SE3 0x803C
|
||||
#define SE_DB_CLEAN (1 << 1)
|
||||
#define SE_CB_CLEAN (1 << 2)
|
||||
#define SE_BCI_BUSY (1 << 22)
|
||||
#define SE_VGT_BUSY (1 << 23)
|
||||
#define SE_PA_BUSY (1 << 24)
|
||||
#define SE_TA_BUSY (1 << 25)
|
||||
#define SE_SX_BUSY (1 << 26)
|
||||
#define SE_SPI_BUSY (1 << 27)
|
||||
#define SE_SC_BUSY (1 << 29)
|
||||
#define SE_DB_BUSY (1 << 30)
|
||||
#define SE_CB_BUSY (1 << 31)
|
||||
|
||||
#define GRBM_SOFT_RESET 0x8020
|
||||
#define SOFT_RESET_CP (1 << 0) /* All CP blocks */
|
||||
#define SOFT_RESET_RLC (1 << 2) /* RLC */
|
||||
#define SOFT_RESET_GFX (1 << 16) /* GFX */
|
||||
#define SOFT_RESET_CPF (1 << 17) /* CP fetcher shared by gfx and compute */
|
||||
#define SOFT_RESET_CPC (1 << 18) /* CP Compute (MEC1/2) */
|
||||
#define SOFT_RESET_CPG (1 << 19) /* CP GFX (PFP, ME, CE) */
|
||||
|
||||
#define CP_MEC_CNTL 0x8234
|
||||
#define MEC_ME2_HALT (1 << 28)
|
||||
#define MEC_ME1_HALT (1 << 30)
|
||||
|
||||
#define CP_ME_CNTL 0x86D8
|
||||
#define CP_CE_HALT (1 << 24)
|
||||
#define CP_PFP_HALT (1 << 26)
|
||||
#define CP_ME_HALT (1 << 28)
|
||||
|
||||
#define CP_MEQ_THRESHOLDS 0x8764
|
||||
#define MEQ1_START(x) ((x) << 0)
|
||||
#define MEQ2_START(x) ((x) << 8)
|
||||
|
|
Loading…
Reference in a new issue