When the guilty job has already signaled, amdgpu_device_gpu_recover()
jumps to skip_hw_reset after amdgpu_device_halt_activities(). The
following parts of the halt are only undone in
amdgpu_device_reinit_after_reset(), so they stay in effect after this
"successful" recovery:
- amdgpu_userq_pre_reset() unmapped all user queues and marked them
HUNG; they are never mapped again.
- drm_client_dev_suspend() suspended fbdev; the console stops updating.
- amdgpu_ras_suspend() disabled RAS on all IPs.
- amdgpu_unregister_gpu_instance() dropped the device from mgpu_info.
Seen on navi31 with ring and soft reset disabled and a GFX job that
completes right after its timeout:
amdgpu: ring gfx_0.0.0 timeout, signaled seq=3, emitted seq=4
amdgpu: GPU reset begin!. Source: 1
amdgpu: Guilty job already signaled, skipping HW reset
where tracing shows userq_pre_reset, drm_client_dev_suspend,
ras_suspend and unregister_gpu_instance without their counterparts.
Undo them on the skip path the same way the reinit path does.
Fixes: fdafb3597a2c ("drm/amdgpu: fix MGPU fan boost enablement for XGMI reset")
Fixes: f1c1314be429 ("drm/amdgpu: Disable ras features on all IPs before gpu
reset")
Fixes: 565d19415577 ("drm/amdgpu: add fbdev suspend/resume on gpu reset")
Fixes: 290f46cf5726 ("drm/amdgpu: Implement user queue reset functionality")
Signed-off-by: Jesse Zhang <[email protected]>
---
drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
index e0014611f039..753df841be15 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
@@ -5565,6 +5565,25 @@ static void amdgpu_device_halt_activities(struct
amdgpu_device *adev,
}
}
+/*
+ * Undo the parts of amdgpu_device_halt_activities() that are otherwise only
+ * undone by amdgpu_device_reinit_after_reset(), for a recovery that skips
+ * the HW reset.
+ */
+static void amdgpu_device_resume_activities(struct amdgpu_device *adev,
+ struct list_head *device_list)
+{
+ struct amdgpu_device *tmp_adev = NULL;
+
+ list_for_each_entry(tmp_adev, device_list, reset_list) {
+ amdgpu_register_gpu_instance(tmp_adev);
+ amdgpu_userq_post_reset(tmp_adev, false);
+ drm_client_dev_resume(adev_to_drm(tmp_adev));
+ if (!amdgpu_reset_in_dpc(adev))
+ amdgpu_ras_resume(tmp_adev);
+ }
+}
+
static int amdgpu_device_asic_reset(struct amdgpu_device *adev,
struct list_head *device_list,
struct amdgpu_reset_context *reset_context)
@@ -5806,6 +5825,7 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev,
if (job && (dma_fence_get_status(&job->hw_fence->base) > 0)) {
job_signaled = true;
dev_info(adev->dev, "Guilty job already signaled, skipping HW
reset");
+ amdgpu_device_resume_activities(adev, &device_list);
goto skip_hw_reset;
}
--
2.50.1