[PATCH v3 09/13] drm/sched: Submit job before starting TDR

Luben Tuikov luben.tuikov at amd.com
Thu Sep 21 03:35:13 UTC 2023


On 2023-09-14 13:48, Matthew Brost wrote:
> On Wed, Sep 13, 2023 at 10:56:10PM -0400, Luben Tuikov wrote:
>> On 2023-09-11 22:16, Matthew Brost wrote:
>>> If the TDR is set to a value, it can fire before a job is submitted in
>>> drm_sched_main. The job should be always be submitted before the TDR
>>> fires, fix this ordering.
>>>
>>> v2:
>>>   - Add to pending list before run_job, start TDR after (Luben, Boris)
>>>
>>> Signed-off-by: Matthew Brost <matthew.brost at intel.com>
>>> ---
>>>  drivers/gpu/drm/scheduler/sched_main.c | 2 +-
>>>  1 file changed, 1 insertion(+), 1 deletion(-)
>>>
>>> diff --git a/drivers/gpu/drm/scheduler/sched_main.c b/drivers/gpu/drm/scheduler/sched_main.c
>>> index c627d3e6494a..9dbfab7be2c6 100644
>>> --- a/drivers/gpu/drm/scheduler/sched_main.c
>>> +++ b/drivers/gpu/drm/scheduler/sched_main.c
>>> @@ -498,7 +498,6 @@ static void drm_sched_job_begin(struct drm_sched_job *s_job)
>>>  
>>>  	spin_lock(&sched->job_list_lock);
>>>  	list_add_tail(&s_job->list, &sched->pending_list);
>>> -	drm_sched_start_timeout(sched);
>>>  	spin_unlock(&sched->job_list_lock);
>>>  }
>>>  
>>> @@ -1234,6 +1233,7 @@ static void drm_sched_run_job_work(struct work_struct *w)
>>>  		fence = sched->ops->run_job(sched_job);
>>>  		complete_all(&entity->entity_idle);
>>>  		drm_sched_fence_scheduled(s_fence, fence);
>>> +		drm_sched_start_timeout_unlocked(sched);
>>>  
>>>  		if (!IS_ERR_OR_NULL(fence)) {
>>>  			/* Drop for original kref_init of the fence */
>>
>> So, sched->ops->run_job(), is a "job inflection point" from the point of view of
>> the DRM scheduler. After that call, DRM has relinquished control of the job to the
>> firmware/hardware.
>>
>> Putting the job in the pending list, before submitting it to down to the firmware/hardware,
>> goes along with starting a timeout timer for the job. The timeout always includes
>> time for the firmware/hardware to get it prepped, as well as time for the actual
>> execution of the job (task). Thus, we want to do this:
>> 	1. Put the job in pending list. "Pending list" means "pends in hardware".
>> 	2. Start a timeout timer for the job.
>> 	3. Start executing the job/task. This usually involves giving it to firmware/hardware,
>> 	   i.e. ownership of the job/task changes to another domain. In our case this is accomplished
>> 	   by calling sched->ops->run_job().
>> Perhaps move drm_sched_start_timeout() closer to sched->ops->run_job() from above and/or increase
>> the timeout value?
> 
> I disagree. It is clear race if the timeout starts before run_job() that
> the TDR can fire before run_job() is called. The entire point of this

Then that would mean that 1) the timeout time is too short, and/or 2) the firmware/hardware
took a really long time to complete the job (from the point of view of the scheduler TDR).

> patch is to seal this race by starting the TDR after run_job() is
> called.

Once you call run_job() you're no longer in control of the job and things can
happen, like this job being returned/cancelled due to reasons out of the scheduler's
control. If you started the timeout _after_ submitting the job to the hardware,
you may be racing with what the hardware might want to do to the job as described
in the previous sentence.

The timeout timer should start before we give away the job to the hardware.
This is not that dissimilar to sending a network packet out the interface.

If you need a longer timeout time, then we can do that, but starting the timeout
after giving away the job to the hardware is a no-go.

-- 
Regards,
Luben



More information about the dri-devel mailing list