Since all soft reset is though GRBM/SRBM, why not write them at a time. This can avoid potiential soft reset sequence problem. Change-Id: I18bc723df863474f3200e5b5852569ef98e9d8ca Signed-off-by: Chunming Zhou <David1.Zhou at amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 14 ++----- drivers/gpu/drm/amd/amdgpu/vi.c | 61 ++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 2e077e7..d795164 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -2001,19 +2001,11 @@ static bool amdgpu_need_full_reset(struct amdgpu_device *adev) static int amdgpu_soft_reset(struct amdgpu_device *adev) { - int i, r = 0; + int r; - for (i = 0; i < adev->num_ip_blocks; i++) { - if (!adev->ip_block_status[i].valid) - continue; - if (adev->ip_block_status[i].hang && - adev->ip_blocks[i].funcs->soft_reset) - r = adev->ip_blocks[i].funcs->soft_reset(adev); - if (r) - return r; - } + r = adev->ip_blocks[AMD_IP_BLOCK_TYPE_COMMON].funcs->soft_reset(adev); - return 0; + return r; } static int amdgpu_post_soft_reset(struct amdgpu_device *adev) diff --git a/drivers/gpu/drm/amd/amdgpu/vi.c b/drivers/gpu/drm/amd/amdgpu/vi.c index 1ac0c91..1f8b623 100644 --- a/drivers/gpu/drm/amd/amdgpu/vi.c +++ b/drivers/gpu/drm/amd/amdgpu/vi.c @@ -1651,6 +1651,67 @@ static int vi_common_wait_for_idle(void *handle) static int vi_common_soft_reset(void *handle) { + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + u32 grbm_soft_reset = 0, srbm_soft_reset = 0; + u32 tmp; + int i; + + for (i = AMD_IP_BLOCK_TYPE_COMMON + 1; i < adev->num_ip_blocks; i++) { + if (!adev->ip_block_status[i].hang) + continue; + + grbm_soft_reset |= adev->ip_block_status[i].grbm_soft_reset; + srbm_soft_reset |= adev->ip_block_status[i].srbm_soft_reset; + } + + if (REG_GET_FIELD(grbm_soft_reset, GRBM_SOFT_RESET, SOFT_RESET_CP) || + REG_GET_FIELD(grbm_soft_reset, GRBM_SOFT_RESET, SOFT_RESET_GFX)) { + tmp = RREG32(mmGMCON_DEBUG); + tmp = REG_SET_FIELD(tmp, GMCON_DEBUG, GFX_STALL, 1); + tmp = REG_SET_FIELD(tmp, GMCON_DEBUG, GFX_CLEAR, 1); + WREG32(mmGMCON_DEBUG, tmp); + udelay(50); + } + + if (grbm_soft_reset) { + tmp = RREG32(mmGRBM_SOFT_RESET); + tmp |= grbm_soft_reset; + dev_info(adev->dev, "GRBM_SOFT_RESET=0x%08X\n", tmp); + WREG32(mmGRBM_SOFT_RESET, tmp); + tmp = RREG32(mmGRBM_SOFT_RESET); + + udelay(50); + + tmp &= ~grbm_soft_reset; + WREG32(mmGRBM_SOFT_RESET, tmp); + tmp = RREG32(mmGRBM_SOFT_RESET); + } + + if (srbm_soft_reset) { + tmp = RREG32(mmSRBM_SOFT_RESET); + tmp |= srbm_soft_reset; + dev_info(adev->dev, "SRBM_SOFT_RESET=0x%08X\n", tmp); + WREG32(mmSRBM_SOFT_RESET, tmp); + tmp = RREG32(mmSRBM_SOFT_RESET); + + udelay(50); + + tmp &= ~srbm_soft_reset; + WREG32(mmSRBM_SOFT_RESET, tmp); + tmp = RREG32(mmSRBM_SOFT_RESET); + } + + if (REG_GET_FIELD(grbm_soft_reset, GRBM_SOFT_RESET, SOFT_RESET_CP) || + REG_GET_FIELD(grbm_soft_reset, GRBM_SOFT_RESET, SOFT_RESET_GFX)) { + tmp = RREG32(mmGMCON_DEBUG); + tmp = REG_SET_FIELD(tmp, GMCON_DEBUG, GFX_STALL, 0); + tmp = REG_SET_FIELD(tmp, GMCON_DEBUG, GFX_CLEAR, 0); + WREG32(mmGMCON_DEBUG, tmp); + } + + /* Wait a little for things to settle down */ + udelay(50); + return 0; } -- 1.9.1