Well you at least have to give me time till after the holidays to get going again :) Not sure exactly jet why we need patch number 5. And we should probably commit patch #1 and #2. Christian. Am 22.04.19 um 13:54 schrieb Grodzovsky, Andrey: > Ping for patches 3, new patch 5 and patch 6. > > Andrey > > On 4/18/19 11:00 AM, Andrey Grodzovsky wrote: >> Also reject TDRs if another one already running. >> >> v2: >> Stop all schedulers across device and entire XGMI hive before >> force signaling HW fences. >> Avoid passing job_signaled to helper fnctions to keep all the decision >> making about skipping HW reset in one place. >> >> v3: >> Fix SW sched. hang after non HW reset. sched.hw_rq_count has to be balanced >> against it's decrement in drm_sched_stop in non HW reset case. >> v4: rebase >> v5: Revert v3 as we do it now in sceduler code. >> >> Signed-off-by: Andrey Grodzovsky <andrey.grodzovsky@xxxxxxx> >> --- >> drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 143 +++++++++++++++++++---------- >> 1 file changed, 95 insertions(+), 48 deletions(-) >> >> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c >> index a0e165c..85f8792 100644 >> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c >> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c >> @@ -3334,8 +3334,6 @@ static int amdgpu_device_pre_asic_reset(struct amdgpu_device *adev, >> if (!ring || !ring->sched.thread) >> continue; >> >> - drm_sched_stop(&ring->sched, &job->base); >> - >> /* after all hw jobs are reset, hw fence is meaningless, so force_completion */ >> amdgpu_fence_driver_force_completion(ring); >> } >> @@ -3343,6 +3341,7 @@ static int amdgpu_device_pre_asic_reset(struct amdgpu_device *adev, >> if(job) >> drm_sched_increase_karma(&job->base); >> >> + /* Don't suspend on bare metal if we are not going to HW reset the ASIC */ >> if (!amdgpu_sriov_vf(adev)) { >> >> if (!need_full_reset) >> @@ -3480,37 +3479,21 @@ static int amdgpu_do_asic_reset(struct amdgpu_hive_info *hive, >> return r; >> } >> >> -static void amdgpu_device_post_asic_reset(struct amdgpu_device *adev) >> +static bool amdgpu_device_lock_adev(struct amdgpu_device *adev, bool trylock) >> { >> - int i; >> - >> - for (i = 0; i < AMDGPU_MAX_RINGS; ++i) { >> - struct amdgpu_ring *ring = adev->rings[i]; >> - >> - if (!ring || !ring->sched.thread) >> - continue; >> - >> - if (!adev->asic_reset_res) >> - drm_sched_resubmit_jobs(&ring->sched); >> + if (trylock) { >> + if (!mutex_trylock(&adev->lock_reset)) >> + return false; >> + } else >> + mutex_lock(&adev->lock_reset); >> >> - drm_sched_start(&ring->sched, !adev->asic_reset_res); >> - } >> - >> - if (!amdgpu_device_has_dc_support(adev)) { >> - drm_helper_resume_force_mode(adev->ddev); >> - } >> - >> - adev->asic_reset_res = 0; >> -} >> - >> -static void amdgpu_device_lock_adev(struct amdgpu_device *adev) >> -{ >> - mutex_lock(&adev->lock_reset); >> atomic_inc(&adev->gpu_reset_counter); >> adev->in_gpu_reset = 1; >> /* Block kfd: SRIOV would do it separately */ >> if (!amdgpu_sriov_vf(adev)) >> amdgpu_amdkfd_pre_reset(adev); >> + >> + return true; >> } >> >> static void amdgpu_device_unlock_adev(struct amdgpu_device *adev) >> @@ -3538,40 +3521,42 @@ static void amdgpu_device_unlock_adev(struct amdgpu_device *adev) >> int amdgpu_device_gpu_recover(struct amdgpu_device *adev, >> struct amdgpu_job *job) >> { >> - int r; >> + struct list_head device_list, *device_list_handle = NULL; >> + bool need_full_reset, job_signaled; >> struct amdgpu_hive_info *hive = NULL; >> - bool need_full_reset = false; >> struct amdgpu_device *tmp_adev = NULL; >> - struct list_head device_list, *device_list_handle = NULL; >> + int i, r = 0; >> >> + need_full_reset = job_signaled = false; >> INIT_LIST_HEAD(&device_list); >> >> dev_info(adev->dev, "GPU reset begin!\n"); >> >> + hive = amdgpu_get_xgmi_hive(adev, false); >> + >> /* >> - * In case of XGMI hive disallow concurrent resets to be triggered >> - * by different nodes. No point also since the one node already executing >> - * reset will also reset all the other nodes in the hive. >> + * Here we trylock to avoid chain of resets executing from >> + * either trigger by jobs on different adevs in XGMI hive or jobs on >> + * different schedulers for same device while this TO handler is running. >> + * We always reset all schedulers for device and all devices for XGMI >> + * hive so that should take care of them too. >> */ >> - hive = amdgpu_get_xgmi_hive(adev, 0); >> - if (hive && adev->gmc.xgmi.num_physical_nodes > 1 && >> - !mutex_trylock(&hive->reset_lock)) >> + >> + if (hive && !mutex_trylock(&hive->reset_lock)) { >> + DRM_INFO("Bailing on TDR for s_job:%llx, hive: %llx as another already in progress", >> + job->base.id, hive->hive_id); >> return 0; >> + } >> >> /* Start with adev pre asic reset first for soft reset check.*/ >> - amdgpu_device_lock_adev(adev); >> - r = amdgpu_device_pre_asic_reset(adev, >> - job, >> - &need_full_reset); >> - if (r) { >> - /*TODO Should we stop ?*/ >> - DRM_ERROR("GPU pre asic reset failed with err, %d for drm dev, %s ", >> - r, adev->ddev->unique); >> - adev->asic_reset_res = r; >> + if (!amdgpu_device_lock_adev(adev, !hive)) { >> + DRM_INFO("Bailing on TDR for s_job:%llx, as another already in progress", >> + job->base.id); >> + return 0; >> } >> >> /* Build list of devices to reset */ >> - if (need_full_reset && adev->gmc.xgmi.num_physical_nodes > 1) { >> + if (adev->gmc.xgmi.num_physical_nodes > 1) { >> if (!hive) { >> amdgpu_device_unlock_adev(adev); >> return -ENODEV; >> @@ -3588,13 +3573,56 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev, >> device_list_handle = &device_list; >> } >> >> + /* block all schedulers and reset given job's ring */ >> + list_for_each_entry(tmp_adev, device_list_handle, gmc.xgmi.head) { >> + for (i = 0; i < AMDGPU_MAX_RINGS; ++i) { >> + struct amdgpu_ring *ring = tmp_adev->rings[i]; >> + >> + if (!ring || !ring->sched.thread) >> + continue; >> + >> + drm_sched_stop(&ring->sched, &job->base); >> + } >> + } >> + >> + >> + /* >> + * Must check guilty signal here since after this point all old >> + * HW fences are force signaled. >> + * >> + * job->base holds a reference to parent fence >> + */ >> + if (job && job->base.s_fence->parent && >> + dma_fence_is_signaled(job->base.s_fence->parent)) >> + job_signaled = true; >> + >> + if (!amdgpu_device_ip_need_full_reset(adev)) >> + device_list_handle = &device_list; >> + >> + if (job_signaled) { >> + dev_info(adev->dev, "Guilty job already signaled, skipping HW reset"); >> + goto skip_hw_reset; >> + } >> + >> + >> + /* Guilty job will be freed after this*/ >> + r = amdgpu_device_pre_asic_reset(adev, >> + job, >> + &need_full_reset); >> + if (r) { >> + /*TODO Should we stop ?*/ >> + DRM_ERROR("GPU pre asic reset failed with err, %d for drm dev, %s ", >> + r, adev->ddev->unique); >> + adev->asic_reset_res = r; >> + } >> + >> retry: /* Rest of adevs pre asic reset from XGMI hive. */ >> list_for_each_entry(tmp_adev, device_list_handle, gmc.xgmi.head) { >> >> if (tmp_adev == adev) >> continue; >> >> - amdgpu_device_lock_adev(tmp_adev); >> + amdgpu_device_lock_adev(tmp_adev, false); >> r = amdgpu_device_pre_asic_reset(tmp_adev, >> NULL, >> &need_full_reset); >> @@ -3618,9 +3646,28 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev, >> goto retry; >> } >> >> +skip_hw_reset: >> + >> /* Post ASIC reset for all devs .*/ >> list_for_each_entry(tmp_adev, device_list_handle, gmc.xgmi.head) { >> - amdgpu_device_post_asic_reset(tmp_adev); >> + for (i = 0; i < AMDGPU_MAX_RINGS; ++i) { >> + struct amdgpu_ring *ring = tmp_adev->rings[i]; >> + >> + if (!ring || !ring->sched.thread) >> + continue; >> + >> + /* No point to resubmit jobs if we didn't HW reset*/ >> + if (!tmp_adev->asic_reset_res && !job_signaled) >> + drm_sched_resubmit_jobs(&ring->sched); >> + >> + drm_sched_start(&ring->sched, !tmp_adev->asic_reset_res); >> + } >> + >> + if (!amdgpu_device_has_dc_support(tmp_adev) && !job_signaled) { >> + drm_helper_resume_force_mode(tmp_adev->ddev); >> + } >> + >> + tmp_adev->asic_reset_res = 0; >> >> if (r) { >> /* bad news, how to tell it to userspace ? */ >> @@ -3633,7 +3680,7 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev, >> amdgpu_device_unlock_adev(tmp_adev); >> } >> >> - if (hive && adev->gmc.xgmi.num_physical_nodes > 1) >> + if (hive) >> mutex_unlock(&hive->reset_lock); >> >> if (r) _______________________________________________ amd-gfx mailing list amd-gfx@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/amd-gfx