summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTimur Kristóf <timur.kristof@gmail.com>2026-06-17 21:14:27 +0200
committerAlex Deucher <alexander.deucher@amd.com>2026-07-01 11:14:29 -0400
commit459813d418e05ed9848502486e8cb1119a93bfca (patch)
tree1fcaac6e4d2e8354340dd429a5dcd1ad04bb513a
parent01f4b82944a05ac6e4c72a071e5f2a56676349af (diff)
downloadlinux-stable-459813d418e05ed9848502486e8cb1119a93bfca.tar.gz
linux-stable-459813d418e05ed9848502486e8cb1119a93bfca.zip
drm/amdgpu/gfx8: Fixup IP block soft reset
Always reset everything in the GFX block at once as opposed to trying to figure out which blocks need to be reset based on their busy flags. This makes the reset more robust and predictable. Increase delays when waiting for the GRBM and SRBM soft reset to complete. Call IP block suspend/resume to ensure correct operation now that we no longer have pre/post_soft_reset(). Call clock/powergating functions, otherwise power consumption will increase after the GFX IP block is soft reset. Return correct error code to signal failure in case not all rings are functional after the IP block is soft reset. Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Timur Kristóf <timur.kristof@gmail.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c43
2 files changed, 34 insertions, 11 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h
index 381fc17274b9..aefd4f03b443 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h
@@ -485,8 +485,6 @@ struct amdgpu_gfx {
const struct amdgpu_gfx_funcs *funcs;
/* reset mask */
- uint32_t grbm_soft_reset;
- uint32_t srbm_soft_reset;
uint32_t gfx_supported_reset;
uint32_t compute_supported_reset;
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
index 7643077ad318..88dcadc53d91 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
@@ -4904,13 +4904,19 @@ static int gfx_v8_0_soft_reset(struct amdgpu_ip_block *ip_block)
u32 grbm_soft_reset = 0, srbm_soft_reset = 0;
u32 tmp;
int i;
+ int r;
- if ((!adev->gfx.grbm_soft_reset) &&
- (!adev->gfx.srbm_soft_reset))
- return 0;
+ grbm_soft_reset =
+ REG_SET_FIELD(0, GRBM_SOFT_RESET, SOFT_RESET_RLC, 1) |
+ REG_SET_FIELD(0, GRBM_SOFT_RESET, SOFT_RESET_GFX, 1) |
+ REG_SET_FIELD(0, GRBM_SOFT_RESET, SOFT_RESET_CP, 1) |
+ REG_SET_FIELD(0, GRBM_SOFT_RESET, SOFT_RESET_CPF, 1) |
+ REG_SET_FIELD(0, GRBM_SOFT_RESET, SOFT_RESET_CPC, 1) |
+ REG_SET_FIELD(0, GRBM_SOFT_RESET, SOFT_RESET_CPG, 1);
- grbm_soft_reset = adev->gfx.grbm_soft_reset;
- srbm_soft_reset = adev->gfx.srbm_soft_reset;
+ srbm_soft_reset =
+ REG_SET_FIELD(0, SRBM_SOFT_RESET, SOFT_RESET_GRBM, 1) |
+ REG_SET_FIELD(0, SRBM_SOFT_RESET, SOFT_RESET_SEM, 1);
for (i = 0; i < adev->gfx.num_compute_rings; i++) {
struct amdgpu_ring *ring = &adev->gfx.compute_ring[i];
@@ -4920,14 +4926,21 @@ static int gfx_v8_0_soft_reset(struct amdgpu_ip_block *ip_block)
gfx_v8_0_deactivate_hqd(adev, 2);
vi_srbm_select(adev, 0, 0, 0, 0);
mutex_unlock(&adev->srbm_mutex);
+
+ udelay(50);
}
+ ip_block->version->funcs->set_clockgating_state(ip_block, AMD_CG_STATE_UNGATE);
+ ip_block->version->funcs->set_powergating_state(ip_block, AMD_PG_STATE_UNGATE);
+ ip_block->version->funcs->suspend(ip_block);
+
if (grbm_soft_reset || srbm_soft_reset) {
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);
+
+ udelay(100);
}
if (grbm_soft_reset) {
@@ -4937,11 +4950,13 @@ static int gfx_v8_0_soft_reset(struct amdgpu_ip_block *ip_block)
WREG32(mmGRBM_SOFT_RESET, tmp);
tmp = RREG32(mmGRBM_SOFT_RESET);
- udelay(50);
+ udelay(100);
tmp &= ~grbm_soft_reset;
WREG32(mmGRBM_SOFT_RESET, tmp);
tmp = RREG32(mmGRBM_SOFT_RESET);
+
+ udelay(100);
}
if (srbm_soft_reset) {
@@ -4951,11 +4966,13 @@ static int gfx_v8_0_soft_reset(struct amdgpu_ip_block *ip_block)
WREG32(mmSRBM_SOFT_RESET, tmp);
tmp = RREG32(mmSRBM_SOFT_RESET);
- udelay(50);
+ udelay(100);
tmp &= ~srbm_soft_reset;
WREG32(mmSRBM_SOFT_RESET, tmp);
tmp = RREG32(mmSRBM_SOFT_RESET);
+
+ udelay(100);
}
if (grbm_soft_reset || srbm_soft_reset) {
@@ -4966,7 +4983,15 @@ static int gfx_v8_0_soft_reset(struct amdgpu_ip_block *ip_block)
}
/* Wait a little for things to settle down */
- udelay(50);
+ udelay(100);
+
+ r = ip_block->version->funcs->resume(ip_block);
+ r |= ip_block->version->funcs->late_init(ip_block);
+ if (r)
+ return r;
+
+ ip_block->version->funcs->set_clockgating_state(ip_block, AMD_CG_STATE_GATE);
+ ip_block->version->funcs->set_powergating_state(ip_block, AMD_PG_STATE_GATE);
return 0;
}