Change-Id: Ic63353077f8dc24d144b1f0cbba992987d4daf0e Signed-off-by: Chunming Zhou <David1.Zhou at amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 2 + drivers/gpu/drm/amd/amdgpu/vi.c | 130 ++++++++++++++++++++++++++++++++++++ 2 files changed, 132 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 9aa2a79..5f79a31 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -134,6 +134,8 @@ extern unsigned amdgpu_pg_mask; #define AMDGPU_RESET_UVD (1 << 12) #define AMDGPU_RESET_VCE (1 << 13) #define AMDGPU_RESET_VCE1 (1 << 14) +#define AMDGPU_RESET_COMP1 (1 << 15) +#define AMDGPU_RESET_COMP2 (1 << 16) /* GFX current status */ #define AMDGPU_GFX_NORMAL_MODE 0x00000000L diff --git a/drivers/gpu/drm/amd/amdgpu/vi.c b/drivers/gpu/drm/amd/amdgpu/vi.c index 1ac0c91..c860291 100644 --- a/drivers/gpu/drm/amd/amdgpu/vi.c +++ b/drivers/gpu/drm/amd/amdgpu/vi.c @@ -584,6 +584,135 @@ static int vi_read_register(struct amdgpu_device *adev, u32 se_num, return -EINVAL; } +#define AMDGPU_VCE_STATUS_BUSY_MASK 0x78 +#define AMDGPU_UVD_STATUS_BUSY_MASK 0xfd + +/** + * vi_gpu_check_soft_reset - check which blocks are busy + * + * @adev: amdsoc_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 vi_gpu_check_soft_reset(struct amdgpu_device *adev) +{ + u32 reset_mask = 0; + u32 tmp; + + /* GRBM_STATUS */ + tmp = RREG32(mmGRBM_STATUS); + if (REG_GET_FIELD(tmp, GRBM_STATUS, PA_BUSY) || + REG_GET_FIELD(tmp, GRBM_STATUS, SC_BUSY) || + REG_GET_FIELD(tmp, GRBM_STATUS, BCI_BUSY) || + REG_GET_FIELD(tmp, GRBM_STATUS, SX_BUSY) || + REG_GET_FIELD(tmp, GRBM_STATUS, TA_BUSY) || + REG_GET_FIELD(tmp, GRBM_STATUS, VGT_BUSY) || + REG_GET_FIELD(tmp, GRBM_STATUS, DB_BUSY) || + REG_GET_FIELD(tmp, GRBM_STATUS, CB_BUSY) || + REG_GET_FIELD(tmp, GRBM_STATUS, GDS_BUSY) || + REG_GET_FIELD(tmp, GRBM_STATUS, SPI_BUSY) || + REG_GET_FIELD(tmp, GRBM_STATUS, IA_BUSY) || + REG_GET_FIELD(tmp, GRBM_STATUS, IA_BUSY_NO_DMA)) + reset_mask |= AMDGPU_RESET_GFX; + + if (REG_GET_FIELD(tmp, GRBM_STATUS, CP_BUSY) || + REG_GET_FIELD(tmp, GRBM_STATUS, CP_COHERENCY_BUSY)) + reset_mask |= AMDGPU_RESET_CP; + + /* GRBM_STATUS2 */ + tmp = RREG32(mmGRBM_STATUS2); + if (REG_GET_FIELD(tmp, GRBM_STATUS2, RLC_BUSY)) + reset_mask |= AMDGPU_RESET_RLC; + + if (REG_GET_FIELD(tmp, GRBM_STATUS2, ME1PIPE0_RQ_PENDING) || + REG_GET_FIELD(tmp, GRBM_STATUS2, ME1PIPE1_RQ_PENDING) || + REG_GET_FIELD(tmp, GRBM_STATUS2, ME1PIPE2_RQ_PENDING) || + REG_GET_FIELD(tmp, GRBM_STATUS2, ME1PIPE3_RQ_PENDING)) + reset_mask |= AMDGPU_RESET_COMP1; + + if (REG_GET_FIELD(tmp, GRBM_STATUS2, ME2PIPE0_RQ_PENDING) || + REG_GET_FIELD(tmp, GRBM_STATUS2, ME2PIPE1_RQ_PENDING) || + REG_GET_FIELD(tmp, GRBM_STATUS2, ME2PIPE2_RQ_PENDING) || + REG_GET_FIELD(tmp, GRBM_STATUS2, ME2PIPE3_RQ_PENDING)) + reset_mask |= AMDGPU_RESET_COMP2; + + /* SRBM_STATUS2 */ + tmp = RREG32(mmSRBM_STATUS2); + if (REG_GET_FIELD(tmp, SRBM_STATUS2, SDMA_BUSY)) + reset_mask |= AMDGPU_RESET_DMA; + else if (!(REG_GET_FIELD(RREG32(mmSDMA0_STATUS_REG), SDMA0_STATUS_REG, IDLE))) + reset_mask |= AMDGPU_RESET_DMA; + + if (REG_GET_FIELD(tmp, SRBM_STATUS2, SDMA1_BUSY)) + reset_mask |= AMDGPU_RESET_DMA1; + else if (!(REG_GET_FIELD(RREG32(mmSDMA1_STATUS_REG), SDMA1_STATUS_REG, IDLE))) + reset_mask |= AMDGPU_RESET_DMA1; + + /* According to VCE team , we should use VCE_STATUS instead + * SRBM_STATUS.VCE_BUSY bit for busy status checking. + * GRBM_GFX_INDEX.INSTANCE_INDEX is used to specify which VCE + * instance's registers are accessed + * (0 for 1st instance, 10 for 2nd instance). + * + *VCE_STATUS + *|UENC|ACPI|AUTO ACTIVE|RB1 |RB0 |RB2 | |FW_LOADED|JOB | + *|----+----+-----------+----+----+----+----------+---------+----| + *|bit8|bit7| bit6 |bit5|bit4|bit3| bit2 | bit1 |bit0| + * + * VCE team suggest use bit 3--bit 6 for busy status check + */ + tmp = RREG32(mmGRBM_GFX_INDEX); + tmp = REG_SET_FIELD(tmp, GRBM_GFX_INDEX, INSTANCE_INDEX, 0); + WREG32(mmGRBM_GFX_INDEX, tmp); + if (RREG32(mmVCE_STATUS) & AMDGPU_VCE_STATUS_BUSY_MASK) + reset_mask |= AMDGPU_RESET_VCE; + tmp = RREG32(mmGRBM_GFX_INDEX); + tmp = REG_SET_FIELD(tmp, GRBM_GFX_INDEX, INSTANCE_INDEX, 0x10); + WREG32(mmGRBM_GFX_INDEX, tmp); + if (RREG32(mmVCE_STATUS) & AMDGPU_VCE_STATUS_BUSY_MASK) + reset_mask |= AMDGPU_RESET_VCE; + tmp = RREG32(mmGRBM_GFX_INDEX); + tmp = REG_SET_FIELD(tmp, GRBM_GFX_INDEX, INSTANCE_INDEX, 0); + WREG32(mmGRBM_GFX_INDEX, tmp); + + /* SRBM_STATUS */ + tmp = RREG32(mmSRBM_STATUS); + + if (REG_GET_FIELD(tmp, SRBM_STATUS, IH_BUSY)) + reset_mask |= AMDGPU_RESET_IH; + + if (REG_GET_FIELD(tmp, SRBM_STATUS, SEM_BUSY)) + reset_mask |= AMDGPU_RESET_SEM; + + if (REG_GET_FIELD(tmp, SRBM_STATUS, GRBM_RQ_PENDING)) + reset_mask |= AMDGPU_RESET_GRBM; + + if (REG_GET_FIELD(tmp, SRBM_STATUS, VMC_BUSY)) + reset_mask |= AMDGPU_RESET_VMC; + + if (REG_GET_FIELD(tmp, SRBM_STATUS, MCB_BUSY) || + REG_GET_FIELD(tmp, SRBM_STATUS, MCB_NON_DISPLAY_BUSY) || + REG_GET_FIELD(tmp, SRBM_STATUS, MCC_BUSY) || + REG_GET_FIELD(tmp, SRBM_STATUS, MCD_BUSY)) + reset_mask |= AMDGPU_RESET_MC; + + if (reset_mask & AMDGPU_RESET_MC) + if (amdgpu_wait_for_idle(adev, AMD_IP_BLOCK_TYPE_GMC) == 0) + reset_mask &= ~AMDGPU_RESET_MC; + + if (REG_GET_FIELD(tmp, SRBM_STATUS, UVD_RQ_PENDING) || + REG_GET_FIELD(tmp, SRBM_STATUS, UVD_BUSY) || + (RREG32(mmUVD_STATUS) & AMDGPU_UVD_STATUS_BUSY_MASK)) + reset_mask |= AMDGPU_RESET_UVD; + + if (amdgpu_display_is_display_hung(adev)) + reset_mask |= AMDGPU_RESET_DISPLAY; + + return reset_mask; +} + static int vi_gpu_pci_config_reset(struct amdgpu_device *adev) { u32 i; @@ -1447,6 +1576,7 @@ static const struct amdgpu_asic_funcs vi_asic_funcs = .read_disabled_bios = &vi_read_disabled_bios, .read_bios_from_rom = &vi_read_bios_from_rom, .read_register = &vi_read_register, + .check_soft_reset = &vi_gpu_check_soft_reset, .reset = &vi_asic_reset, .set_vga_state = &vi_vga_set_state, .get_xclk = &vi_get_xclk, -- 1.9.1