From: "Grodzovsky, Andrey" <Andrey.Grodzovsky-5C7GfCeVMHo@public.gmane.org>
To: "Koenig,
Christian" <Christian.Koenig-5C7GfCeVMHo@public.gmane.org>,
"dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW@public.gmane.org"
<dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW@public.gmane.org>,
"amd-gfx-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW@public.gmane.org"
<amd-gfx-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW@public.gmane.org>,
"etnaviv-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW@public.gmane.org"
<etnaviv-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW@public.gmane.org>,
"eric-WhKQ6XTQaPysTnJN9+BGXg@public.gmane.org"
<eric-WhKQ6XTQaPysTnJN9+BGXg@public.gmane.org>
Subject: Re: [PATCH 3/3] drm/amdgpu: Avoid HW reset if guilty job already signaled.
Date: Wed, 10 Apr 2019 15:05:24 +0000 [thread overview]
Message-ID: <29ed8a29-4b82-a2f3-92aa-a6c660b19f09@amd.com> (raw)
In-Reply-To: <c3205a35-5c00-bda5-bd3b-2160d453f886-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
On 4/10/19 10:41 AM, Christian König wrote:
> Am 10.04.19 um 16:28 schrieb Grodzovsky, Andrey:
>> On 4/10/19 10:06 AM, Christian König wrote:
>>> Am 09.04.19 um 18:42 schrieb Grodzovsky, Andrey:
>>>> On 4/9/19 10:50 AM, Christian König wrote:
>>>>> Am 08.04.19 um 18:08 schrieb Andrey Grodzovsky:
>>>>>> Also reject TDRs if another one already running.
>>>>>>
>>>>>> Signed-off-by: Andrey Grodzovsky <andrey.grodzovsky@amd.com>
>>>>>> ---
>>>>>> drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 94
>>>>>> +++++++++++++++++++++---------
>>>>>> 1 file changed, 67 insertions(+), 27 deletions(-)
>>>>>>
>>>>>> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
>>>>>> b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
>>>>>> index aabd043..4446892 100644
>>>>>> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
>>>>>> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
>>>>>> @@ -3327,10 +3327,12 @@ bool amdgpu_device_should_recover_gpu(struct
>>>>>> amdgpu_device *adev)
>>>>>> static int amdgpu_device_pre_asic_reset(struct amdgpu_device
>>>>>> *adev,
>>>>>> struct amdgpu_job *job,
>>>>>> - bool *need_full_reset_arg)
>>>>>> + bool *need_full_reset_arg,
>>>>>> + bool *job_signaled)
>>>>>> {
>>>>>> int i, r = 0;
>>>>>> bool need_full_reset = *need_full_reset_arg;
>>>>>> + struct amdgpu_ring *job_ring = job ?
>>>>>> to_amdgpu_ring(job->base.sched) : NULL;
>>>>>> /* block all schedulers and reset given job's ring */
>>>>>> for (i = 0; i < AMDGPU_MAX_RINGS; ++i) {
>>>>>> @@ -3341,6 +3343,17 @@ static int
>>>>>> amdgpu_device_pre_asic_reset(struct
>>>>>> amdgpu_device *adev,
>>>>>> 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_signaled && job && ring == job_ring &&
>>>>>> + job->base.s_fence->parent &&
>>>>>> + dma_fence_is_signaled(job->base.s_fence->parent))
>>>>>> + *job_signaled = true;
>>>>>> +
>>>>> That won't work correctly. See when the guilty job is not on the
>>>>> first
>>>>> scheduler, you would already have force completed some before getting
>>>>> here.
>>>>>
>>>>> Better to stop all schedulers first and then do the check.
>>>>>
>>>>> Christian.
>>>> What do you mean by first scheduler ? There is one scheduler object
>>>> per
>>>> ring so I am not clear what 'first' means here.
>>> Well for example if the guilty job is from a compute ring the we have
>>> already force signaled the gfx ring here.
>>>
>>> Same is true for other devices in the same hive, so it would probably
>>> be a good idea to move the force signaling and the IP reset somewhere
>>> else and this check up a layer.
>>>
>>> Christian.
>>
>> Let me see if I understand you correctly - you want to AVOID ANY force
>> signaling in case we are not going to HW reset and so you want to have
>> the check if guilty is signaled BEFORE any ring fences are force
>> signaled. Correct ?
>
> Correct.
>
> Basically we should do the following:
> 1. Stop all schedulers to make sure that nothing is going on.
> 2. Check the guilty job once more to make sure that it hasn't signaled
> in the meantime.
> 3. Start our reset procedure, with force complete, soft reset
> eventually hard reset etc etc..
> 4. Resubmit all not yet completed jobs.
> 5. Start the schedulers again.
>
> Christian.
Why not just always ensure the guilty job's ring is always checked
first and then do the rest of the rings - inside
amdgpu_device_pre_asic_reset. Seems to me like a much smaller change
with less impact to current code structure.
Andrey
>
>>
>> Andrey
>>
>>>> Andrey
>>>>
>>>>
>>>>>> /* after all hw jobs are reset, hw fence is
>>>>>> meaningless, so
>>>>>> force_completion */
>>>>>> amdgpu_fence_driver_force_completion(ring);
>>>>>> }
>>>>>> @@ -3358,7 +3371,8 @@ static int amdgpu_device_pre_asic_reset(struct
>>>>>> amdgpu_device *adev,
>>>>>> - if (!amdgpu_sriov_vf(adev)) {
>>>>>> + /* Don't suspend on bare metal if we are not going to HW reset
>>>>>> the ASIC */
>>>>>> + if (!amdgpu_sriov_vf(adev) && !(*job_signaled)) {
>>>>>> if (!need_full_reset)
>>>>>> need_full_reset =
>>>>>> amdgpu_device_ip_need_full_reset(adev);
>>>>>> @@ -3495,7 +3509,7 @@ 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 void amdgpu_device_post_asic_reset(struct amdgpu_device
>>>>>> *adev, bool job_signaled)
>>>>>> {
>>>>>> int i;
>>>>>> @@ -3505,7 +3519,8 @@ static void
>>>>>> amdgpu_device_post_asic_reset(struct amdgpu_device *adev)
>>>>>> if (!ring || !ring->sched.thread)
>>>>>> continue;
>>>>>> - if (!adev->asic_reset_res)
>>>>>> + /* No point to resubmit jobs if we didn't HW reset*/
>>>>>> + if (!adev->asic_reset_res && !job_signaled)
>>>>>> drm_sched_resubmit_jobs(&ring->sched);
>>>>>> drm_sched_start(&ring->sched, !adev->asic_reset_res);
>>>>>> @@ -3518,14 +3533,21 @@ static void
>>>>>> amdgpu_device_post_asic_reset(struct amdgpu_device *adev)
>>>>>> adev->asic_reset_res = 0;
>>>>>> }
>>>>>> -static void amdgpu_device_lock_adev(struct amdgpu_device *adev)
>>>>>> +static bool amdgpu_device_lock_adev(struct amdgpu_device *adev,
>>>>>> bool
>>>>>> trylock)
>>>>>> {
>>>>>> - mutex_lock(&adev->lock_reset);
>>>>>> + if (trylock) {
>>>>>> + if (!mutex_trylock(&adev->lock_reset))
>>>>>> + return false;
>>>>>> + } else
>>>>>> + 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)
>>>>>> @@ -3555,29 +3577,44 @@ int amdgpu_device_gpu_recover(struct
>>>>>> amdgpu_device *adev,
>>>>>> {
>>>>>> int r;
>>>>>> 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;
>>>>>> + bool xgmi_topology_present, need_full_reset, job_signaled;
>>>>>> + 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, 0);
>>>>>> + xgmi_topology_present = hive &&
>>>>>> adev->gmc.xgmi.num_physical_nodes > 1;
>>>>>> +
>>>>>> /*
>>>>>> - * 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 tdr 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 (xgmi_topology_present &&
>>>>>> !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);
>>>>>> + if (!amdgpu_device_lock_adev(adev, !xgmi_topology_present)) {
>>>>>> + DRM_INFO("Bailing on TDR for s_job:%llx, as another already
>>>>>> in progress",
>>>>>> + job->base.id);
>>>>>> + return 0;
>>>>>> + }
>>>>>> +
>>>>>> + /* Guilty job will be freed after this*/
>>>>>> r = amdgpu_device_pre_asic_reset(adev,
>>>>>> job,
>>>>>> - &need_full_reset);
>>>>>> + &need_full_reset,
>>>>>> + &job_signaled);
>>>>>> if (r) {
>>>>>> /*TODO Should we stop ?*/
>>>>>> DRM_ERROR("GPU pre asic reset failed with err, %d for
>>>>>> drm
>>>>>> dev, %s ",
>>>>>> @@ -3609,10 +3646,11 @@ int amdgpu_device_gpu_recover(struct
>>>>>> amdgpu_device *adev,
>>>>>> 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);
>>>>>> + &need_full_reset,
>>>>>> + &job_signaled);
>>>>>> /*TODO Should we stop ?*/
>>>>>> if (r) {
>>>>>> DRM_ERROR("GPU pre asic reset failed with err, %d
>>>>>> for
>>>>>> drm dev, %s ",
>>>>>> @@ -3623,19 +3661,21 @@ int amdgpu_device_gpu_recover(struct
>>>>>> amdgpu_device *adev,
>>>>>> /* Actual ASIC resets if needed.*/
>>>>>> /* TODO Implement XGMI hive reset logic for SRIOV */
>>>>>> - if (amdgpu_sriov_vf(adev)) {
>>>>>> - r = amdgpu_device_reset_sriov(adev, job ? false : true);
>>>>>> - if (r)
>>>>>> - adev->asic_reset_res = r;
>>>>>> - } else {
>>>>>> - r = amdgpu_do_asic_reset(hive, device_list_handle,
>>>>>> &need_full_reset);
>>>>>> - if (r && r == -EAGAIN)
>>>>>> - goto retry;
>>>>>> + if (!job || !job_signaled) {
>>>>>> + if (amdgpu_sriov_vf(adev)) {
>>>>>> + r = amdgpu_device_reset_sriov(adev, job ? false :
>>>>>> true);
>>>>>> + if (r)
>>>>>> + adev->asic_reset_res = r;
>>>>>> + } else {
>>>>>> + r = amdgpu_do_asic_reset(hive, device_list_handle,
>>>>>> &need_full_reset);
>>>>>> + if (r && r == -EAGAIN)
>>>>>> + goto retry;
>>>>>> + }
>>>>>> }
>>>>>> /* 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);
>>>>>> + amdgpu_device_post_asic_reset(tmp_adev, job_signaled);
>>>>>> if (r) {
>>>>>> /* bad news, how to tell it to userspace ? */
>>>>>> @@ -3648,7 +3688,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 (xgmi_topology_present)
>>>>>> mutex_unlock(&hive->reset_lock);
>>>>>> if (r)
>>>> _______________________________________________
>>>> amd-gfx mailing list
>>>> amd-gfx@lists.freedesktop.org
>>>> https://lists.freedesktop.org/mailman/listinfo/amd-gfx
>> _______________________________________________
>> amd-gfx mailing list
>> amd-gfx@lists.freedesktop.org
>> https://lists.freedesktop.org/mailman/listinfo/amd-gfx
>
_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx
next prev parent reply other threads:[~2019-04-10 15:05 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-04-08 16:08 [PATCH 1/3] drm/scheduler: rework job destruction Andrey Grodzovsky
2019-04-08 16:08 ` [PATCH 2/3] drm/sched: Keep s_fence->parent pointer Andrey Grodzovsky
2019-04-09 14:37 ` Christian König
[not found] ` <1554739692-6999-1-git-send-email-andrey.grodzovsky-5C7GfCeVMHo@public.gmane.org>
2019-04-08 16:08 ` [PATCH 3/3] drm/amdgpu: Avoid HW reset if guilty job already signaled Andrey Grodzovsky
2019-04-09 14:50 ` Christian König
[not found] ` <6ec23212-740d-7931-40e3-3d60ab591679-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
2019-04-09 16:42 ` Grodzovsky, Andrey
[not found] ` <209e53f7-5842-1f34-f9bb-a800670b31fe-5C7GfCeVMHo@public.gmane.org>
2019-04-10 14:06 ` Christian König
2019-04-10 14:28 ` Grodzovsky, Andrey
[not found] ` <c77c574c-4613-693f-3f11-3f7eb8feae66-5C7GfCeVMHo@public.gmane.org>
2019-04-10 14:41 ` Christian König
[not found] ` <c3205a35-5c00-bda5-bd3b-2160d453f886-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
2019-04-10 15:05 ` Grodzovsky, Andrey [this message]
[not found] ` <29ed8a29-4b82-a2f3-92aa-a6c660b19f09-5C7GfCeVMHo@public.gmane.org>
2019-04-10 15:09 ` Koenig, Christian
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=29ed8a29-4b82-a2f3-92aa-a6c660b19f09@amd.com \
--to=andrey.grodzovsky-5c7gfcevmho@public.gmane.org \
--cc=Christian.Koenig-5C7GfCeVMHo@public.gmane.org \
--cc=amd-gfx-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW@public.gmane.org \
--cc=dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW@public.gmane.org \
--cc=eric-WhKQ6XTQaPysTnJN9+BGXg@public.gmane.org \
--cc=etnaviv-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW@public.gmane.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox