1 /*
2  * Copyright 2015 Advanced Micro Devices, Inc.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20  * OTHER DEALINGS IN THE SOFTWARE.
21  *
22  */
23 
24 /**
25  * DOC: Overview
26  *
27  * The GPU scheduler provides entities which allow userspace to push jobs
28  * into software queues which are then scheduled on a hardware run queue.
29  * The software queues have a priority among them. The scheduler selects the entities
30  * from the run queue using a FIFO. The scheduler provides dependency handling
31  * features among jobs. The driver is supposed to provide callback functions for
32  * backend operations to the scheduler like submitting a job to hardware run queue,
33  * returning the dependencies of a job etc.
34  *
35  * The organisation of the scheduler is the following:
36  *
37  * 1. Each hw run queue has one scheduler
38  * 2. Each scheduler has multiple run queues with different priorities
39  *    (e.g., HIGH_HW,HIGH_SW, KERNEL, NORMAL)
40  * 3. Each scheduler run queue has a queue of entities to schedule
41  * 4. Entities themselves maintain a queue of jobs that will be scheduled on
42  *    the hardware.
43  *
44  * The jobs in a entity are always scheduled in the order that they were pushed.
45  *
46  * Note that once a job was taken from the entities queue and pushed to the
47  * hardware, i.e. the pending queue, the entity must not be referenced anymore
48  * through the jobs entity pointer.
49  */
50 
51 /**
52  * DOC: Flow Control
53  *
54  * The DRM GPU scheduler provides a flow control mechanism to regulate the rate
55  * in which the jobs fetched from scheduler entities are executed.
56  *
57  * In this context the &drm_gpu_scheduler keeps track of a driver specified
58  * credit limit representing the capacity of this scheduler and a credit count;
59  * every &drm_sched_job carries a driver specified number of credits.
60  *
61  * Once a job is executed (but not yet finished), the job's credits contribute
62  * to the scheduler's credit count until the job is finished. If by executing
63  * one more job the scheduler's credit count would exceed the scheduler's
64  * credit limit, the job won't be executed. Instead, the scheduler will wait
65  * until the credit count has decreased enough to not overflow its credit limit.
66  * This implies waiting for previously executed jobs.
67  *
68  * Optionally, drivers may register a callback (update_job_credits) provided by
69  * struct drm_sched_backend_ops to update the job's credits dynamically. The
70  * scheduler executes this callback every time the scheduler considers a job for
71  * execution and subsequently checks whether the job fits the scheduler's credit
72  * limit.
73  */
74 
75 #include <linux/wait.h>
76 #include <linux/sched.h>
77 #include <linux/completion.h>
78 #include <linux/dma-resv.h>
79 #ifdef __linux__
80 #include <uapi/linux/sched/types.h>
81 #endif
82 
83 #include <drm/drm_print.h>
84 #include <drm/drm_gem.h>
85 #include <drm/drm_syncobj.h>
86 #include <drm/gpu_scheduler.h>
87 #include <drm/spsc_queue.h>
88 
89 #define CREATE_TRACE_POINTS
90 #include "gpu_scheduler_trace.h"
91 
92 #ifdef CONFIG_LOCKDEP
93 static struct lockdep_map drm_sched_lockdep_map = {
94 	.name = "drm_sched_lockdep_map"
95 };
96 #endif
97 
98 #define to_drm_sched_job(sched_job)		\
99 		container_of((sched_job), struct drm_sched_job, queue_node)
100 
101 int drm_sched_policy = DRM_SCHED_POLICY_FIFO;
102 
103 /**
104  * DOC: sched_policy (int)
105  * Used to override default entities scheduling policy in a run queue.
106  */
107 MODULE_PARM_DESC(sched_policy, "Specify the scheduling policy for entities on a run-queue, " __stringify(DRM_SCHED_POLICY_RR) " = Round Robin, " __stringify(DRM_SCHED_POLICY_FIFO) " = FIFO (default).");
108 module_param_named(sched_policy, drm_sched_policy, int, 0444);
109 
drm_sched_available_credits(struct drm_gpu_scheduler * sched)110 static u32 drm_sched_available_credits(struct drm_gpu_scheduler *sched)
111 {
112 	u32 credits;
113 
114 	drm_WARN_ON(sched, check_sub_overflow(sched->credit_limit,
115 					      atomic_read(&sched->credit_count),
116 					      &credits));
117 
118 	return credits;
119 }
120 
121 /**
122  * drm_sched_can_queue -- Can we queue more to the hardware?
123  * @sched: scheduler instance
124  * @entity: the scheduler entity
125  *
126  * Return true if we can push at least one more job from @entity, false
127  * otherwise.
128  */
drm_sched_can_queue(struct drm_gpu_scheduler * sched,struct drm_sched_entity * entity)129 static bool drm_sched_can_queue(struct drm_gpu_scheduler *sched,
130 				struct drm_sched_entity *entity)
131 {
132 	struct drm_sched_job *s_job;
133 
134 	s_job = to_drm_sched_job(spsc_queue_peek(&entity->job_queue));
135 	if (!s_job)
136 		return false;
137 
138 	if (sched->ops->update_job_credits) {
139 		s_job->credits = sched->ops->update_job_credits(s_job);
140 
141 		drm_WARN(sched, !s_job->credits,
142 			 "Jobs with zero credits bypass job-flow control.\n");
143 	}
144 
145 	/* If a job exceeds the credit limit, truncate it to the credit limit
146 	 * itself to guarantee forward progress.
147 	 */
148 	if (drm_WARN(sched, s_job->credits > sched->credit_limit,
149 		     "Jobs may not exceed the credit limit, truncate.\n"))
150 		s_job->credits = sched->credit_limit;
151 
152 	return drm_sched_available_credits(sched) >= s_job->credits;
153 }
154 
drm_sched_entity_compare_before(struct rb_node * a,const struct rb_node * b)155 static __always_inline bool drm_sched_entity_compare_before(struct rb_node *a,
156 							    const struct rb_node *b)
157 {
158 	struct drm_sched_entity *ent_a =  rb_entry((a), struct drm_sched_entity, rb_tree_node);
159 	struct drm_sched_entity *ent_b =  rb_entry((b), struct drm_sched_entity, rb_tree_node);
160 
161 	return ktime_before(ent_a->oldest_job_waiting, ent_b->oldest_job_waiting);
162 }
163 
drm_sched_rq_remove_fifo_locked(struct drm_sched_entity * entity)164 static inline void drm_sched_rq_remove_fifo_locked(struct drm_sched_entity *entity)
165 {
166 	struct drm_sched_rq *rq = entity->rq;
167 
168 	if (!RB_EMPTY_NODE(&entity->rb_tree_node)) {
169 		rb_erase_cached(&entity->rb_tree_node, &rq->rb_tree_root);
170 		RB_CLEAR_NODE(&entity->rb_tree_node);
171 	}
172 }
173 
drm_sched_rq_update_fifo(struct drm_sched_entity * entity,ktime_t ts)174 void drm_sched_rq_update_fifo(struct drm_sched_entity *entity, ktime_t ts)
175 {
176 	/*
177 	 * Both locks need to be grabbed, one to protect from entity->rq change
178 	 * for entity from within concurrent drm_sched_entity_select_rq and the
179 	 * other to update the rb tree structure.
180 	 */
181 	spin_lock(&entity->rq_lock);
182 	spin_lock(&entity->rq->lock);
183 
184 	drm_sched_rq_remove_fifo_locked(entity);
185 
186 	entity->oldest_job_waiting = ts;
187 
188 	rb_add_cached(&entity->rb_tree_node, &entity->rq->rb_tree_root,
189 		      drm_sched_entity_compare_before);
190 
191 	spin_unlock(&entity->rq->lock);
192 	spin_unlock(&entity->rq_lock);
193 }
194 
195 /**
196  * drm_sched_rq_init - initialize a given run queue struct
197  *
198  * @sched: scheduler instance to associate with this run queue
199  * @rq: scheduler run queue
200  *
201  * Initializes a scheduler runqueue.
202  */
drm_sched_rq_init(struct drm_gpu_scheduler * sched,struct drm_sched_rq * rq)203 static void drm_sched_rq_init(struct drm_gpu_scheduler *sched,
204 			      struct drm_sched_rq *rq)
205 {
206 	mtx_init(&rq->lock, IPL_NONE);
207 	INIT_LIST_HEAD(&rq->entities);
208 	rq->rb_tree_root = RB_ROOT_CACHED;
209 	rq->current_entity = NULL;
210 	rq->sched = sched;
211 }
212 
213 /**
214  * drm_sched_rq_add_entity - add an entity
215  *
216  * @rq: scheduler run queue
217  * @entity: scheduler entity
218  *
219  * Adds a scheduler entity to the run queue.
220  */
drm_sched_rq_add_entity(struct drm_sched_rq * rq,struct drm_sched_entity * entity)221 void drm_sched_rq_add_entity(struct drm_sched_rq *rq,
222 			     struct drm_sched_entity *entity)
223 {
224 	if (!list_empty(&entity->list))
225 		return;
226 
227 	spin_lock(&rq->lock);
228 
229 	atomic_inc(rq->sched->score);
230 	list_add_tail(&entity->list, &rq->entities);
231 
232 	spin_unlock(&rq->lock);
233 }
234 
235 /**
236  * drm_sched_rq_remove_entity - remove an entity
237  *
238  * @rq: scheduler run queue
239  * @entity: scheduler entity
240  *
241  * Removes a scheduler entity from the run queue.
242  */
drm_sched_rq_remove_entity(struct drm_sched_rq * rq,struct drm_sched_entity * entity)243 void drm_sched_rq_remove_entity(struct drm_sched_rq *rq,
244 				struct drm_sched_entity *entity)
245 {
246 	if (list_empty(&entity->list))
247 		return;
248 
249 	spin_lock(&rq->lock);
250 
251 	atomic_dec(rq->sched->score);
252 	list_del_init(&entity->list);
253 
254 	if (rq->current_entity == entity)
255 		rq->current_entity = NULL;
256 
257 	if (drm_sched_policy == DRM_SCHED_POLICY_FIFO)
258 		drm_sched_rq_remove_fifo_locked(entity);
259 
260 	spin_unlock(&rq->lock);
261 }
262 
263 /**
264  * drm_sched_rq_select_entity_rr - Select an entity which could provide a job to run
265  *
266  * @sched: the gpu scheduler
267  * @rq: scheduler run queue to check.
268  *
269  * Try to find the next ready entity.
270  *
271  * Return an entity if one is found; return an error-pointer (!NULL) if an
272  * entity was ready, but the scheduler had insufficient credits to accommodate
273  * its job; return NULL, if no ready entity was found.
274  */
275 static struct drm_sched_entity *
drm_sched_rq_select_entity_rr(struct drm_gpu_scheduler * sched,struct drm_sched_rq * rq)276 drm_sched_rq_select_entity_rr(struct drm_gpu_scheduler *sched,
277 			      struct drm_sched_rq *rq)
278 {
279 	struct drm_sched_entity *entity;
280 
281 	spin_lock(&rq->lock);
282 
283 	entity = rq->current_entity;
284 	if (entity) {
285 		list_for_each_entry_continue(entity, &rq->entities, list) {
286 			if (drm_sched_entity_is_ready(entity)) {
287 				/* If we can't queue yet, preserve the current
288 				 * entity in terms of fairness.
289 				 */
290 				if (!drm_sched_can_queue(sched, entity)) {
291 					spin_unlock(&rq->lock);
292 					return ERR_PTR(-ENOSPC);
293 				}
294 
295 				rq->current_entity = entity;
296 				reinit_completion(&entity->entity_idle);
297 				spin_unlock(&rq->lock);
298 				return entity;
299 			}
300 		}
301 	}
302 
303 	list_for_each_entry(entity, &rq->entities, list) {
304 		if (drm_sched_entity_is_ready(entity)) {
305 			/* If we can't queue yet, preserve the current entity in
306 			 * terms of fairness.
307 			 */
308 			if (!drm_sched_can_queue(sched, entity)) {
309 				spin_unlock(&rq->lock);
310 				return ERR_PTR(-ENOSPC);
311 			}
312 
313 			rq->current_entity = entity;
314 			reinit_completion(&entity->entity_idle);
315 			spin_unlock(&rq->lock);
316 			return entity;
317 		}
318 
319 		if (entity == rq->current_entity)
320 			break;
321 	}
322 
323 	spin_unlock(&rq->lock);
324 
325 	return NULL;
326 }
327 
328 /**
329  * drm_sched_rq_select_entity_fifo - Select an entity which provides a job to run
330  *
331  * @sched: the gpu scheduler
332  * @rq: scheduler run queue to check.
333  *
334  * Find oldest waiting ready entity.
335  *
336  * Return an entity if one is found; return an error-pointer (!NULL) if an
337  * entity was ready, but the scheduler had insufficient credits to accommodate
338  * its job; return NULL, if no ready entity was found.
339  */
340 static struct drm_sched_entity *
drm_sched_rq_select_entity_fifo(struct drm_gpu_scheduler * sched,struct drm_sched_rq * rq)341 drm_sched_rq_select_entity_fifo(struct drm_gpu_scheduler *sched,
342 				struct drm_sched_rq *rq)
343 {
344 	struct rb_node *rb;
345 
346 	spin_lock(&rq->lock);
347 	for (rb = rb_first_cached(&rq->rb_tree_root); rb; rb = rb_next(rb)) {
348 		struct drm_sched_entity *entity;
349 
350 		entity = rb_entry(rb, struct drm_sched_entity, rb_tree_node);
351 		if (drm_sched_entity_is_ready(entity)) {
352 			/* If we can't queue yet, preserve the current entity in
353 			 * terms of fairness.
354 			 */
355 			if (!drm_sched_can_queue(sched, entity)) {
356 				spin_unlock(&rq->lock);
357 				return ERR_PTR(-ENOSPC);
358 			}
359 
360 			rq->current_entity = entity;
361 			reinit_completion(&entity->entity_idle);
362 			break;
363 		}
364 	}
365 	spin_unlock(&rq->lock);
366 
367 	return rb ? rb_entry(rb, struct drm_sched_entity, rb_tree_node) : NULL;
368 }
369 
370 /**
371  * drm_sched_run_job_queue - enqueue run-job work
372  * @sched: scheduler instance
373  */
drm_sched_run_job_queue(struct drm_gpu_scheduler * sched)374 static void drm_sched_run_job_queue(struct drm_gpu_scheduler *sched)
375 {
376 	if (!READ_ONCE(sched->pause_submit))
377 		queue_work(sched->submit_wq, &sched->work_run_job);
378 }
379 
380 /**
381  * __drm_sched_run_free_queue - enqueue free-job work
382  * @sched: scheduler instance
383  */
__drm_sched_run_free_queue(struct drm_gpu_scheduler * sched)384 static void __drm_sched_run_free_queue(struct drm_gpu_scheduler *sched)
385 {
386 	if (!READ_ONCE(sched->pause_submit))
387 		queue_work(sched->submit_wq, &sched->work_free_job);
388 }
389 
390 /**
391  * drm_sched_run_free_queue - enqueue free-job work if ready
392  * @sched: scheduler instance
393  */
drm_sched_run_free_queue(struct drm_gpu_scheduler * sched)394 static void drm_sched_run_free_queue(struct drm_gpu_scheduler *sched)
395 {
396 	struct drm_sched_job *job;
397 
398 	spin_lock(&sched->job_list_lock);
399 	job = list_first_entry_or_null(&sched->pending_list,
400 				       struct drm_sched_job, list);
401 	if (job && dma_fence_is_signaled(&job->s_fence->finished))
402 		__drm_sched_run_free_queue(sched);
403 	spin_unlock(&sched->job_list_lock);
404 }
405 
406 /**
407  * drm_sched_job_done - complete a job
408  * @s_job: pointer to the job which is done
409  *
410  * Finish the job's fence and wake up the worker thread.
411  */
drm_sched_job_done(struct drm_sched_job * s_job,int result)412 static void drm_sched_job_done(struct drm_sched_job *s_job, int result)
413 {
414 	struct drm_sched_fence *s_fence = s_job->s_fence;
415 	struct drm_gpu_scheduler *sched = s_fence->sched;
416 
417 	atomic_sub(s_job->credits, &sched->credit_count);
418 	atomic_dec(sched->score);
419 
420 	trace_drm_sched_process_job(s_fence);
421 
422 	dma_fence_get(&s_fence->finished);
423 	drm_sched_fence_finished(s_fence, result);
424 	dma_fence_put(&s_fence->finished);
425 	__drm_sched_run_free_queue(sched);
426 }
427 
428 /**
429  * drm_sched_job_done_cb - the callback for a done job
430  * @f: fence
431  * @cb: fence callbacks
432  */
drm_sched_job_done_cb(struct dma_fence * f,struct dma_fence_cb * cb)433 static void drm_sched_job_done_cb(struct dma_fence *f, struct dma_fence_cb *cb)
434 {
435 	struct drm_sched_job *s_job = container_of(cb, struct drm_sched_job, cb);
436 
437 	drm_sched_job_done(s_job, f->error);
438 }
439 
440 /**
441  * drm_sched_start_timeout - start timeout for reset worker
442  *
443  * @sched: scheduler instance to start the worker for
444  *
445  * Start the timeout for the given scheduler.
446  */
drm_sched_start_timeout(struct drm_gpu_scheduler * sched)447 static void drm_sched_start_timeout(struct drm_gpu_scheduler *sched)
448 {
449 	lockdep_assert_held(&sched->job_list_lock);
450 
451 	if (sched->timeout != MAX_SCHEDULE_TIMEOUT &&
452 	    !list_empty(&sched->pending_list))
453 		mod_delayed_work(sched->timeout_wq, &sched->work_tdr, sched->timeout);
454 }
455 
drm_sched_start_timeout_unlocked(struct drm_gpu_scheduler * sched)456 static void drm_sched_start_timeout_unlocked(struct drm_gpu_scheduler *sched)
457 {
458 	spin_lock(&sched->job_list_lock);
459 	drm_sched_start_timeout(sched);
460 	spin_unlock(&sched->job_list_lock);
461 }
462 
463 /**
464  * drm_sched_tdr_queue_imm: - immediately start job timeout handler
465  *
466  * @sched: scheduler for which the timeout handling should be started.
467  *
468  * Start timeout handling immediately for the named scheduler.
469  */
drm_sched_tdr_queue_imm(struct drm_gpu_scheduler * sched)470 void drm_sched_tdr_queue_imm(struct drm_gpu_scheduler *sched)
471 {
472 	spin_lock(&sched->job_list_lock);
473 	sched->timeout = 0;
474 	drm_sched_start_timeout(sched);
475 	spin_unlock(&sched->job_list_lock);
476 }
477 EXPORT_SYMBOL(drm_sched_tdr_queue_imm);
478 
479 /**
480  * drm_sched_fault - immediately start timeout handler
481  *
482  * @sched: scheduler where the timeout handling should be started.
483  *
484  * Start timeout handling immediately when the driver detects a hardware fault.
485  */
drm_sched_fault(struct drm_gpu_scheduler * sched)486 void drm_sched_fault(struct drm_gpu_scheduler *sched)
487 {
488 	if (sched->timeout_wq)
489 		mod_delayed_work(sched->timeout_wq, &sched->work_tdr, 0);
490 }
491 EXPORT_SYMBOL(drm_sched_fault);
492 
493 /**
494  * drm_sched_suspend_timeout - Suspend scheduler job timeout
495  *
496  * @sched: scheduler instance for which to suspend the timeout
497  *
498  * Suspend the delayed work timeout for the scheduler. This is done by
499  * modifying the delayed work timeout to an arbitrary large value,
500  * MAX_SCHEDULE_TIMEOUT in this case.
501  *
502  * Returns the timeout remaining
503  *
504  */
drm_sched_suspend_timeout(struct drm_gpu_scheduler * sched)505 unsigned long drm_sched_suspend_timeout(struct drm_gpu_scheduler *sched)
506 {
507 	unsigned long sched_timeout, now = jiffies;
508 
509 #ifdef __linux__
510 	sched_timeout = sched->work_tdr.timer.expires;
511 #else
512 	sched_timeout = sched->work_tdr.to.to_time;
513 #endif
514 
515 	/*
516 	 * Modify the timeout to an arbitrarily large value. This also prevents
517 	 * the timeout to be restarted when new submissions arrive
518 	 */
519 	if (mod_delayed_work(sched->timeout_wq, &sched->work_tdr, MAX_SCHEDULE_TIMEOUT)
520 			&& time_after(sched_timeout, now))
521 		return sched_timeout - now;
522 	else
523 		return sched->timeout;
524 }
525 EXPORT_SYMBOL(drm_sched_suspend_timeout);
526 
527 /**
528  * drm_sched_resume_timeout - Resume scheduler job timeout
529  *
530  * @sched: scheduler instance for which to resume the timeout
531  * @remaining: remaining timeout
532  *
533  * Resume the delayed work timeout for the scheduler.
534  */
drm_sched_resume_timeout(struct drm_gpu_scheduler * sched,unsigned long remaining)535 void drm_sched_resume_timeout(struct drm_gpu_scheduler *sched,
536 		unsigned long remaining)
537 {
538 	spin_lock(&sched->job_list_lock);
539 
540 	if (list_empty(&sched->pending_list))
541 		cancel_delayed_work(&sched->work_tdr);
542 	else
543 		mod_delayed_work(sched->timeout_wq, &sched->work_tdr, remaining);
544 
545 	spin_unlock(&sched->job_list_lock);
546 }
547 EXPORT_SYMBOL(drm_sched_resume_timeout);
548 
drm_sched_job_begin(struct drm_sched_job * s_job)549 static void drm_sched_job_begin(struct drm_sched_job *s_job)
550 {
551 	struct drm_gpu_scheduler *sched = s_job->sched;
552 
553 	spin_lock(&sched->job_list_lock);
554 	list_add_tail(&s_job->list, &sched->pending_list);
555 	drm_sched_start_timeout(sched);
556 	spin_unlock(&sched->job_list_lock);
557 }
558 
drm_sched_job_timedout(struct work_struct * work)559 static void drm_sched_job_timedout(struct work_struct *work)
560 {
561 	struct drm_gpu_scheduler *sched;
562 	struct drm_sched_job *job;
563 	enum drm_gpu_sched_stat status = DRM_GPU_SCHED_STAT_NOMINAL;
564 
565 	sched = container_of(work, struct drm_gpu_scheduler, work_tdr.work);
566 
567 	/* Protects against concurrent deletion in drm_sched_get_finished_job */
568 	spin_lock(&sched->job_list_lock);
569 	job = list_first_entry_or_null(&sched->pending_list,
570 				       struct drm_sched_job, list);
571 
572 	if (job) {
573 		/*
574 		 * Remove the bad job so it cannot be freed by concurrent
575 		 * drm_sched_cleanup_jobs. It will be reinserted back after sched->thread
576 		 * is parked at which point it's safe.
577 		 */
578 		list_del_init(&job->list);
579 		spin_unlock(&sched->job_list_lock);
580 
581 		status = job->sched->ops->timedout_job(job);
582 
583 		/*
584 		 * Guilty job did complete and hence needs to be manually removed
585 		 * See drm_sched_stop doc.
586 		 */
587 		if (sched->free_guilty) {
588 			job->sched->ops->free_job(job);
589 			sched->free_guilty = false;
590 		}
591 	} else {
592 		spin_unlock(&sched->job_list_lock);
593 	}
594 
595 	if (status != DRM_GPU_SCHED_STAT_ENODEV)
596 		drm_sched_start_timeout_unlocked(sched);
597 }
598 
599 /**
600  * drm_sched_stop - stop the scheduler
601  *
602  * @sched: scheduler instance
603  * @bad: job which caused the time out
604  *
605  * Stop the scheduler and also removes and frees all completed jobs.
606  * Note: bad job will not be freed as it might be used later and so it's
607  * callers responsibility to release it manually if it's not part of the
608  * pending list any more.
609  *
610  */
drm_sched_stop(struct drm_gpu_scheduler * sched,struct drm_sched_job * bad)611 void drm_sched_stop(struct drm_gpu_scheduler *sched, struct drm_sched_job *bad)
612 {
613 	struct drm_sched_job *s_job, *tmp;
614 
615 	drm_sched_wqueue_stop(sched);
616 
617 	/*
618 	 * Reinsert back the bad job here - now it's safe as
619 	 * drm_sched_get_finished_job cannot race against us and release the
620 	 * bad job at this point - we parked (waited for) any in progress
621 	 * (earlier) cleanups and drm_sched_get_finished_job will not be called
622 	 * now until the scheduler thread is unparked.
623 	 */
624 	if (bad && bad->sched == sched)
625 		/*
626 		 * Add at the head of the queue to reflect it was the earliest
627 		 * job extracted.
628 		 */
629 		list_add(&bad->list, &sched->pending_list);
630 
631 	/*
632 	 * Iterate the job list from later to  earlier one and either deactive
633 	 * their HW callbacks or remove them from pending list if they already
634 	 * signaled.
635 	 * This iteration is thread safe as sched thread is stopped.
636 	 */
637 	list_for_each_entry_safe_reverse(s_job, tmp, &sched->pending_list,
638 					 list) {
639 		if (s_job->s_fence->parent &&
640 		    dma_fence_remove_callback(s_job->s_fence->parent,
641 					      &s_job->cb)) {
642 			dma_fence_put(s_job->s_fence->parent);
643 			s_job->s_fence->parent = NULL;
644 			atomic_sub(s_job->credits, &sched->credit_count);
645 		} else {
646 			/*
647 			 * remove job from pending_list.
648 			 * Locking here is for concurrent resume timeout
649 			 */
650 			spin_lock(&sched->job_list_lock);
651 			list_del_init(&s_job->list);
652 			spin_unlock(&sched->job_list_lock);
653 
654 			/*
655 			 * Wait for job's HW fence callback to finish using s_job
656 			 * before releasing it.
657 			 *
658 			 * Job is still alive so fence refcount at least 1
659 			 */
660 			dma_fence_wait(&s_job->s_fence->finished, false);
661 
662 			/*
663 			 * We must keep bad job alive for later use during
664 			 * recovery by some of the drivers but leave a hint
665 			 * that the guilty job must be released.
666 			 */
667 			if (bad != s_job)
668 				sched->ops->free_job(s_job);
669 			else
670 				sched->free_guilty = true;
671 		}
672 	}
673 
674 	/*
675 	 * Stop pending timer in flight as we rearm it in  drm_sched_start. This
676 	 * avoids the pending timeout work in progress to fire right away after
677 	 * this TDR finished and before the newly restarted jobs had a
678 	 * chance to complete.
679 	 */
680 	cancel_delayed_work(&sched->work_tdr);
681 }
682 
683 EXPORT_SYMBOL(drm_sched_stop);
684 
685 /**
686  * drm_sched_start - recover jobs after a reset
687  *
688  * @sched: scheduler instance
689  *
690  */
drm_sched_start(struct drm_gpu_scheduler * sched)691 void drm_sched_start(struct drm_gpu_scheduler *sched)
692 {
693 	struct drm_sched_job *s_job, *tmp;
694 
695 	/*
696 	 * Locking the list is not required here as the sched thread is parked
697 	 * so no new jobs are being inserted or removed. Also concurrent
698 	 * GPU recovers can't run in parallel.
699 	 */
700 	list_for_each_entry_safe(s_job, tmp, &sched->pending_list, list) {
701 		struct dma_fence *fence = s_job->s_fence->parent;
702 
703 		atomic_add(s_job->credits, &sched->credit_count);
704 
705 		if (!fence) {
706 			drm_sched_job_done(s_job, -ECANCELED);
707 			continue;
708 		}
709 
710 		if (dma_fence_add_callback(fence, &s_job->cb,
711 					   drm_sched_job_done_cb))
712 			drm_sched_job_done(s_job, fence->error);
713 	}
714 
715 	drm_sched_start_timeout_unlocked(sched);
716 	drm_sched_wqueue_start(sched);
717 }
718 EXPORT_SYMBOL(drm_sched_start);
719 
720 /**
721  * drm_sched_resubmit_jobs - Deprecated, don't use in new code!
722  *
723  * @sched: scheduler instance
724  *
725  * Re-submitting jobs was a concept AMD came up as cheap way to implement
726  * recovery after a job timeout.
727  *
728  * This turned out to be not working very well. First of all there are many
729  * problem with the dma_fence implementation and requirements. Either the
730  * implementation is risking deadlocks with core memory management or violating
731  * documented implementation details of the dma_fence object.
732  *
733  * Drivers can still save and restore their state for recovery operations, but
734  * we shouldn't make this a general scheduler feature around the dma_fence
735  * interface.
736  */
drm_sched_resubmit_jobs(struct drm_gpu_scheduler * sched)737 void drm_sched_resubmit_jobs(struct drm_gpu_scheduler *sched)
738 {
739 	struct drm_sched_job *s_job, *tmp;
740 	uint64_t guilty_context;
741 	bool found_guilty = false;
742 	struct dma_fence *fence;
743 
744 	list_for_each_entry_safe(s_job, tmp, &sched->pending_list, list) {
745 		struct drm_sched_fence *s_fence = s_job->s_fence;
746 
747 		if (!found_guilty && atomic_read(&s_job->karma) > sched->hang_limit) {
748 			found_guilty = true;
749 			guilty_context = s_job->s_fence->scheduled.context;
750 		}
751 
752 		if (found_guilty && s_job->s_fence->scheduled.context == guilty_context)
753 			dma_fence_set_error(&s_fence->finished, -ECANCELED);
754 
755 		fence = sched->ops->run_job(s_job);
756 
757 		if (IS_ERR_OR_NULL(fence)) {
758 			if (IS_ERR(fence))
759 				dma_fence_set_error(&s_fence->finished, PTR_ERR(fence));
760 
761 			s_job->s_fence->parent = NULL;
762 		} else {
763 
764 			s_job->s_fence->parent = dma_fence_get(fence);
765 
766 			/* Drop for orignal kref_init */
767 			dma_fence_put(fence);
768 		}
769 	}
770 }
771 EXPORT_SYMBOL(drm_sched_resubmit_jobs);
772 
773 /**
774  * drm_sched_job_init - init a scheduler job
775  * @job: scheduler job to init
776  * @entity: scheduler entity to use
777  * @credits: the number of credits this job contributes to the schedulers
778  * credit limit
779  * @owner: job owner for debugging
780  *
781  * Refer to drm_sched_entity_push_job() documentation
782  * for locking considerations.
783  *
784  * Drivers must make sure drm_sched_job_cleanup() if this function returns
785  * successfully, even when @job is aborted before drm_sched_job_arm() is called.
786  *
787  * WARNING: amdgpu abuses &drm_sched.ready to signal when the hardware
788  * has died, which can mean that there's no valid runqueue for a @entity.
789  * This function returns -ENOENT in this case (which probably should be -EIO as
790  * a more meanigful return value).
791  *
792  * Returns 0 for success, negative error code otherwise.
793  */
drm_sched_job_init(struct drm_sched_job * job,struct drm_sched_entity * entity,u32 credits,void * owner)794 int drm_sched_job_init(struct drm_sched_job *job,
795 		       struct drm_sched_entity *entity,
796 		       u32 credits, void *owner)
797 {
798 	if (!entity->rq) {
799 		/* This will most likely be followed by missing frames
800 		 * or worse--a blank screen--leave a trail in the
801 		 * logs, so this can be debugged easier.
802 		 */
803 		drm_err(job->sched, "%s: entity has no rq!\n", __func__);
804 		return -ENOENT;
805 	}
806 
807 	if (unlikely(!credits)) {
808 		pr_err("*ERROR* %s: credits cannot be 0!\n", __func__);
809 		return -EINVAL;
810 	}
811 
812 	/*
813 	 * We don't know for sure how the user has allocated. Thus, zero the
814 	 * struct so that unallowed (i.e., too early) usage of pointers that
815 	 * this function does not set is guaranteed to lead to a NULL pointer
816 	 * exception instead of UB.
817 	 */
818 	memset(job, 0, sizeof(*job));
819 
820 	job->entity = entity;
821 	job->credits = credits;
822 	job->s_fence = drm_sched_fence_alloc(entity, owner);
823 	if (!job->s_fence)
824 		return -ENOMEM;
825 
826 	INIT_LIST_HEAD(&job->list);
827 
828 	xa_init_flags(&job->dependencies, XA_FLAGS_ALLOC);
829 
830 	return 0;
831 }
832 EXPORT_SYMBOL(drm_sched_job_init);
833 
834 /**
835  * drm_sched_job_arm - arm a scheduler job for execution
836  * @job: scheduler job to arm
837  *
838  * This arms a scheduler job for execution. Specifically it initializes the
839  * &drm_sched_job.s_fence of @job, so that it can be attached to struct dma_resv
840  * or other places that need to track the completion of this job.
841  *
842  * Refer to drm_sched_entity_push_job() documentation for locking
843  * considerations.
844  *
845  * This can only be called if drm_sched_job_init() succeeded.
846  */
drm_sched_job_arm(struct drm_sched_job * job)847 void drm_sched_job_arm(struct drm_sched_job *job)
848 {
849 	struct drm_gpu_scheduler *sched;
850 	struct drm_sched_entity *entity = job->entity;
851 
852 	BUG_ON(!entity);
853 	drm_sched_entity_select_rq(entity);
854 	sched = entity->rq->sched;
855 
856 	job->sched = sched;
857 	job->s_priority = entity->priority;
858 	job->id = atomic64_inc_return(&sched->job_id_count);
859 
860 	drm_sched_fence_init(job->s_fence, job->entity);
861 }
862 EXPORT_SYMBOL(drm_sched_job_arm);
863 
864 /**
865  * drm_sched_job_add_dependency - adds the fence as a job dependency
866  * @job: scheduler job to add the dependencies to
867  * @fence: the dma_fence to add to the list of dependencies.
868  *
869  * Note that @fence is consumed in both the success and error cases.
870  *
871  * Returns:
872  * 0 on success, or an error on failing to expand the array.
873  */
drm_sched_job_add_dependency(struct drm_sched_job * job,struct dma_fence * fence)874 int drm_sched_job_add_dependency(struct drm_sched_job *job,
875 				 struct dma_fence *fence)
876 {
877 	struct dma_fence *entry;
878 	unsigned long index;
879 	u32 id = 0;
880 	int ret;
881 
882 	if (!fence)
883 		return 0;
884 
885 	/* Deduplicate if we already depend on a fence from the same context.
886 	 * This lets the size of the array of deps scale with the number of
887 	 * engines involved, rather than the number of BOs.
888 	 */
889 	xa_for_each(&job->dependencies, index, entry) {
890 		if (entry->context != fence->context)
891 			continue;
892 
893 		if (dma_fence_is_later(fence, entry)) {
894 			dma_fence_put(entry);
895 			xa_store(&job->dependencies, index, fence, GFP_KERNEL);
896 		} else {
897 			dma_fence_put(fence);
898 		}
899 		return 0;
900 	}
901 
902 	ret = xa_alloc(&job->dependencies, &id, fence, xa_limit_32b, GFP_KERNEL);
903 	if (ret != 0)
904 		dma_fence_put(fence);
905 
906 	return ret;
907 }
908 EXPORT_SYMBOL(drm_sched_job_add_dependency);
909 
910 /**
911  * drm_sched_job_add_syncobj_dependency - adds a syncobj's fence as a job dependency
912  * @job: scheduler job to add the dependencies to
913  * @file: drm file private pointer
914  * @handle: syncobj handle to lookup
915  * @point: timeline point
916  *
917  * This adds the fence matching the given syncobj to @job.
918  *
919  * Returns:
920  * 0 on success, or an error on failing to expand the array.
921  */
drm_sched_job_add_syncobj_dependency(struct drm_sched_job * job,struct drm_file * file,u32 handle,u32 point)922 int drm_sched_job_add_syncobj_dependency(struct drm_sched_job *job,
923 					 struct drm_file *file,
924 					 u32 handle,
925 					 u32 point)
926 {
927 	struct dma_fence *fence;
928 	int ret;
929 
930 	ret = drm_syncobj_find_fence(file, handle, point, 0, &fence);
931 	if (ret)
932 		return ret;
933 
934 	return drm_sched_job_add_dependency(job, fence);
935 }
936 EXPORT_SYMBOL(drm_sched_job_add_syncobj_dependency);
937 
938 /**
939  * drm_sched_job_add_resv_dependencies - add all fences from the resv to the job
940  * @job: scheduler job to add the dependencies to
941  * @resv: the dma_resv object to get the fences from
942  * @usage: the dma_resv_usage to use to filter the fences
943  *
944  * This adds all fences matching the given usage from @resv to @job.
945  * Must be called with the @resv lock held.
946  *
947  * Returns:
948  * 0 on success, or an error on failing to expand the array.
949  */
drm_sched_job_add_resv_dependencies(struct drm_sched_job * job,struct dma_resv * resv,enum dma_resv_usage usage)950 int drm_sched_job_add_resv_dependencies(struct drm_sched_job *job,
951 					struct dma_resv *resv,
952 					enum dma_resv_usage usage)
953 {
954 	struct dma_resv_iter cursor;
955 	struct dma_fence *fence;
956 	int ret;
957 
958 	dma_resv_assert_held(resv);
959 
960 	dma_resv_for_each_fence(&cursor, resv, usage, fence) {
961 		/* Make sure to grab an additional ref on the added fence */
962 		dma_fence_get(fence);
963 		ret = drm_sched_job_add_dependency(job, fence);
964 		if (ret) {
965 			dma_fence_put(fence);
966 			return ret;
967 		}
968 	}
969 	return 0;
970 }
971 EXPORT_SYMBOL(drm_sched_job_add_resv_dependencies);
972 
973 /**
974  * drm_sched_job_add_implicit_dependencies - adds implicit dependencies as job
975  *   dependencies
976  * @job: scheduler job to add the dependencies to
977  * @obj: the gem object to add new dependencies from.
978  * @write: whether the job might write the object (so we need to depend on
979  * shared fences in the reservation object).
980  *
981  * This should be called after drm_gem_lock_reservations() on your array of
982  * GEM objects used in the job but before updating the reservations with your
983  * own fences.
984  *
985  * Returns:
986  * 0 on success, or an error on failing to expand the array.
987  */
drm_sched_job_add_implicit_dependencies(struct drm_sched_job * job,struct drm_gem_object * obj,bool write)988 int drm_sched_job_add_implicit_dependencies(struct drm_sched_job *job,
989 					    struct drm_gem_object *obj,
990 					    bool write)
991 {
992 	return drm_sched_job_add_resv_dependencies(job, obj->resv,
993 						   dma_resv_usage_rw(write));
994 }
995 EXPORT_SYMBOL(drm_sched_job_add_implicit_dependencies);
996 
997 /**
998  * drm_sched_job_cleanup - clean up scheduler job resources
999  * @job: scheduler job to clean up
1000  *
1001  * Cleans up the resources allocated with drm_sched_job_init().
1002  *
1003  * Drivers should call this from their error unwind code if @job is aborted
1004  * before drm_sched_job_arm() is called.
1005  *
1006  * After that point of no return @job is committed to be executed by the
1007  * scheduler, and this function should be called from the
1008  * &drm_sched_backend_ops.free_job callback.
1009  */
drm_sched_job_cleanup(struct drm_sched_job * job)1010 void drm_sched_job_cleanup(struct drm_sched_job *job)
1011 {
1012 	struct dma_fence *fence;
1013 	unsigned long index;
1014 
1015 	if (kref_read(&job->s_fence->finished.refcount)) {
1016 		/* drm_sched_job_arm() has been called */
1017 		dma_fence_put(&job->s_fence->finished);
1018 	} else {
1019 		/* aborted job before committing to run it */
1020 		drm_sched_fence_free(job->s_fence);
1021 	}
1022 
1023 	job->s_fence = NULL;
1024 
1025 	xa_for_each(&job->dependencies, index, fence) {
1026 		dma_fence_put(fence);
1027 	}
1028 	xa_destroy(&job->dependencies);
1029 
1030 }
1031 EXPORT_SYMBOL(drm_sched_job_cleanup);
1032 
1033 /**
1034  * drm_sched_wakeup - Wake up the scheduler if it is ready to queue
1035  * @sched: scheduler instance
1036  *
1037  * Wake up the scheduler if we can queue jobs.
1038  */
drm_sched_wakeup(struct drm_gpu_scheduler * sched)1039 void drm_sched_wakeup(struct drm_gpu_scheduler *sched)
1040 {
1041 	drm_sched_run_job_queue(sched);
1042 }
1043 
1044 /**
1045  * drm_sched_select_entity - Select next entity to process
1046  *
1047  * @sched: scheduler instance
1048  *
1049  * Return an entity to process or NULL if none are found.
1050  *
1051  * Note, that we break out of the for-loop when "entity" is non-null, which can
1052  * also be an error-pointer--this assures we don't process lower priority
1053  * run-queues. See comments in the respectively called functions.
1054  */
1055 static struct drm_sched_entity *
drm_sched_select_entity(struct drm_gpu_scheduler * sched)1056 drm_sched_select_entity(struct drm_gpu_scheduler *sched)
1057 {
1058 	struct drm_sched_entity *entity;
1059 	int i;
1060 
1061 	/* Start with the highest priority.
1062 	 */
1063 	for (i = DRM_SCHED_PRIORITY_KERNEL; i < sched->num_rqs; i++) {
1064 		entity = drm_sched_policy == DRM_SCHED_POLICY_FIFO ?
1065 			drm_sched_rq_select_entity_fifo(sched, sched->sched_rq[i]) :
1066 			drm_sched_rq_select_entity_rr(sched, sched->sched_rq[i]);
1067 		if (entity)
1068 			break;
1069 	}
1070 
1071 	return IS_ERR(entity) ? NULL : entity;
1072 }
1073 
1074 /**
1075  * drm_sched_get_finished_job - fetch the next finished job to be destroyed
1076  *
1077  * @sched: scheduler instance
1078  *
1079  * Returns the next finished job from the pending list (if there is one)
1080  * ready for it to be destroyed.
1081  */
1082 static struct drm_sched_job *
drm_sched_get_finished_job(struct drm_gpu_scheduler * sched)1083 drm_sched_get_finished_job(struct drm_gpu_scheduler *sched)
1084 {
1085 	struct drm_sched_job *job, *next;
1086 
1087 	spin_lock(&sched->job_list_lock);
1088 
1089 	job = list_first_entry_or_null(&sched->pending_list,
1090 				       struct drm_sched_job, list);
1091 
1092 	if (job && dma_fence_is_signaled(&job->s_fence->finished)) {
1093 		/* remove job from pending_list */
1094 		list_del_init(&job->list);
1095 
1096 		/* cancel this job's TO timer */
1097 		cancel_delayed_work(&sched->work_tdr);
1098 		/* make the scheduled timestamp more accurate */
1099 		next = list_first_entry_or_null(&sched->pending_list,
1100 						typeof(*next), list);
1101 
1102 		if (next) {
1103 			if (test_bit(DMA_FENCE_FLAG_TIMESTAMP_BIT,
1104 				     &next->s_fence->scheduled.flags))
1105 				next->s_fence->scheduled.timestamp =
1106 					dma_fence_timestamp(&job->s_fence->finished);
1107 			/* start TO timer for next job */
1108 			drm_sched_start_timeout(sched);
1109 		}
1110 	} else {
1111 		job = NULL;
1112 	}
1113 
1114 	spin_unlock(&sched->job_list_lock);
1115 
1116 	return job;
1117 }
1118 
1119 /**
1120  * drm_sched_pick_best - Get a drm sched from a sched_list with the least load
1121  * @sched_list: list of drm_gpu_schedulers
1122  * @num_sched_list: number of drm_gpu_schedulers in the sched_list
1123  *
1124  * Returns pointer of the sched with the least load or NULL if none of the
1125  * drm_gpu_schedulers are ready
1126  */
1127 struct drm_gpu_scheduler *
drm_sched_pick_best(struct drm_gpu_scheduler ** sched_list,unsigned int num_sched_list)1128 drm_sched_pick_best(struct drm_gpu_scheduler **sched_list,
1129 		     unsigned int num_sched_list)
1130 {
1131 	struct drm_gpu_scheduler *sched, *picked_sched = NULL;
1132 	int i;
1133 	unsigned int min_score = UINT_MAX, num_score;
1134 
1135 	for (i = 0; i < num_sched_list; ++i) {
1136 		sched = sched_list[i];
1137 
1138 		if (!sched->ready) {
1139 			DRM_WARN("scheduler %s is not ready, skipping",
1140 				 sched->name);
1141 			continue;
1142 		}
1143 
1144 		num_score = atomic_read(sched->score);
1145 		if (num_score < min_score) {
1146 			min_score = num_score;
1147 			picked_sched = sched;
1148 		}
1149 	}
1150 
1151 	return picked_sched;
1152 }
1153 EXPORT_SYMBOL(drm_sched_pick_best);
1154 
1155 /**
1156  * drm_sched_free_job_work - worker to call free_job
1157  *
1158  * @w: free job work
1159  */
drm_sched_free_job_work(struct work_struct * w)1160 static void drm_sched_free_job_work(struct work_struct *w)
1161 {
1162 	struct drm_gpu_scheduler *sched =
1163 		container_of(w, struct drm_gpu_scheduler, work_free_job);
1164 	struct drm_sched_job *job;
1165 
1166 	if (READ_ONCE(sched->pause_submit))
1167 		return;
1168 
1169 	job = drm_sched_get_finished_job(sched);
1170 	if (job)
1171 		sched->ops->free_job(job);
1172 
1173 	drm_sched_run_free_queue(sched);
1174 	drm_sched_run_job_queue(sched);
1175 }
1176 
1177 /**
1178  * drm_sched_run_job_work - worker to call run_job
1179  *
1180  * @w: run job work
1181  */
drm_sched_run_job_work(struct work_struct * w)1182 static void drm_sched_run_job_work(struct work_struct *w)
1183 {
1184 	struct drm_gpu_scheduler *sched =
1185 		container_of(w, struct drm_gpu_scheduler, work_run_job);
1186 	struct drm_sched_entity *entity;
1187 	struct dma_fence *fence;
1188 	struct drm_sched_fence *s_fence;
1189 	struct drm_sched_job *sched_job;
1190 	int r;
1191 
1192 	if (READ_ONCE(sched->pause_submit))
1193 		return;
1194 
1195 	/* Find entity with a ready job */
1196 	entity = drm_sched_select_entity(sched);
1197 	if (!entity)
1198 		return;	/* No more work */
1199 
1200 	sched_job = drm_sched_entity_pop_job(entity);
1201 	if (!sched_job) {
1202 		complete_all(&entity->entity_idle);
1203 		drm_sched_run_job_queue(sched);
1204 		return;
1205 	}
1206 
1207 	s_fence = sched_job->s_fence;
1208 
1209 	atomic_add(sched_job->credits, &sched->credit_count);
1210 	drm_sched_job_begin(sched_job);
1211 
1212 	trace_drm_run_job(sched_job, entity);
1213 	fence = sched->ops->run_job(sched_job);
1214 	complete_all(&entity->entity_idle);
1215 	drm_sched_fence_scheduled(s_fence, fence);
1216 
1217 	if (!IS_ERR_OR_NULL(fence)) {
1218 		/* Drop for original kref_init of the fence */
1219 		dma_fence_put(fence);
1220 
1221 		r = dma_fence_add_callback(fence, &sched_job->cb,
1222 					   drm_sched_job_done_cb);
1223 		if (r == -ENOENT)
1224 			drm_sched_job_done(sched_job, fence->error);
1225 		else if (r)
1226 			DRM_DEV_ERROR(sched->dev, "fence add callback failed (%d)\n", r);
1227 	} else {
1228 		drm_sched_job_done(sched_job, IS_ERR(fence) ?
1229 				   PTR_ERR(fence) : 0);
1230 	}
1231 
1232 	wake_up(&sched->job_scheduled);
1233 	drm_sched_run_job_queue(sched);
1234 }
1235 
1236 /**
1237  * drm_sched_init - Init a gpu scheduler instance
1238  *
1239  * @sched: scheduler instance
1240  * @ops: backend operations for this scheduler
1241  * @submit_wq: workqueue to use for submission. If NULL, an ordered wq is
1242  *	       allocated and used
1243  * @num_rqs: number of runqueues, one for each priority, up to DRM_SCHED_PRIORITY_COUNT
1244  * @credit_limit: the number of credits this scheduler can hold from all jobs
1245  * @hang_limit: number of times to allow a job to hang before dropping it
1246  * @timeout: timeout value in jiffies for the scheduler
1247  * @timeout_wq: workqueue to use for timeout work. If NULL, the system_wq is
1248  *		used
1249  * @score: optional score atomic shared with other schedulers
1250  * @name: name used for debugging
1251  * @dev: target &struct device
1252  *
1253  * Return 0 on success, otherwise error code.
1254  */
drm_sched_init(struct drm_gpu_scheduler * sched,const struct drm_sched_backend_ops * ops,struct workqueue_struct * submit_wq,u32 num_rqs,u32 credit_limit,unsigned int hang_limit,long timeout,struct workqueue_struct * timeout_wq,atomic_t * score,const char * name,struct device * dev)1255 int drm_sched_init(struct drm_gpu_scheduler *sched,
1256 		   const struct drm_sched_backend_ops *ops,
1257 		   struct workqueue_struct *submit_wq,
1258 		   u32 num_rqs, u32 credit_limit, unsigned int hang_limit,
1259 		   long timeout, struct workqueue_struct *timeout_wq,
1260 		   atomic_t *score, const char *name, struct device *dev)
1261 {
1262 	int i;
1263 
1264 	sched->ops = ops;
1265 	sched->credit_limit = credit_limit;
1266 	sched->name = name;
1267 	sched->timeout = timeout;
1268 	sched->timeout_wq = timeout_wq ? : system_wq;
1269 	sched->hang_limit = hang_limit;
1270 	sched->score = score ? score : &sched->_score;
1271 	sched->dev = dev;
1272 
1273 	if (num_rqs > DRM_SCHED_PRIORITY_COUNT) {
1274 		/* This is a gross violation--tell drivers what the  problem is.
1275 		 */
1276 		drm_err(sched, "%s: num_rqs cannot be greater than DRM_SCHED_PRIORITY_COUNT\n",
1277 			__func__);
1278 		return -EINVAL;
1279 	} else if (sched->sched_rq) {
1280 		/* Not an error, but warn anyway so drivers can
1281 		 * fine-tune their DRM calling order, and return all
1282 		 * is good.
1283 		 */
1284 		drm_warn(sched, "%s: scheduler already initialized!\n", __func__);
1285 		return 0;
1286 	}
1287 
1288 	if (submit_wq) {
1289 		sched->submit_wq = submit_wq;
1290 		sched->own_submit_wq = false;
1291 	} else {
1292 #ifdef CONFIG_LOCKDEP
1293 		sched->submit_wq = alloc_ordered_workqueue_lockdep_map(name,
1294 								       WQ_MEM_RECLAIM,
1295 								       &drm_sched_lockdep_map);
1296 #else
1297 		sched->submit_wq = alloc_ordered_workqueue(name, WQ_MEM_RECLAIM);
1298 #endif
1299 		if (!sched->submit_wq)
1300 			return -ENOMEM;
1301 
1302 		sched->own_submit_wq = true;
1303 	}
1304 
1305 	sched->sched_rq = kmalloc_array(num_rqs, sizeof(*sched->sched_rq),
1306 					GFP_KERNEL | __GFP_ZERO);
1307 	if (!sched->sched_rq)
1308 		goto Out_check_own;
1309 	sched->num_rqs = num_rqs;
1310 	for (i = DRM_SCHED_PRIORITY_KERNEL; i < sched->num_rqs; i++) {
1311 		sched->sched_rq[i] = kzalloc(sizeof(*sched->sched_rq[i]), GFP_KERNEL);
1312 		if (!sched->sched_rq[i])
1313 			goto Out_unroll;
1314 		drm_sched_rq_init(sched, sched->sched_rq[i]);
1315 	}
1316 
1317 	init_waitqueue_head(&sched->job_scheduled);
1318 	INIT_LIST_HEAD(&sched->pending_list);
1319 	mtx_init(&sched->job_list_lock, IPL_NONE);
1320 	atomic_set(&sched->credit_count, 0);
1321 	INIT_DELAYED_WORK(&sched->work_tdr, drm_sched_job_timedout);
1322 	INIT_WORK(&sched->work_run_job, drm_sched_run_job_work);
1323 	INIT_WORK(&sched->work_free_job, drm_sched_free_job_work);
1324 	atomic_set(&sched->_score, 0);
1325 	atomic64_set(&sched->job_id_count, 0);
1326 	sched->pause_submit = false;
1327 
1328 	sched->ready = true;
1329 	return 0;
1330 Out_unroll:
1331 	for (--i ; i >= DRM_SCHED_PRIORITY_KERNEL; i--)
1332 		kfree(sched->sched_rq[i]);
1333 
1334 	kfree(sched->sched_rq);
1335 	sched->sched_rq = NULL;
1336 Out_check_own:
1337 	if (sched->own_submit_wq)
1338 		destroy_workqueue(sched->submit_wq);
1339 	drm_err(sched, "%s: Failed to setup GPU scheduler--out of memory\n", __func__);
1340 	return -ENOMEM;
1341 }
1342 EXPORT_SYMBOL(drm_sched_init);
1343 
1344 /**
1345  * drm_sched_fini - Destroy a gpu scheduler
1346  *
1347  * @sched: scheduler instance
1348  *
1349  * Tears down and cleans up the scheduler.
1350  */
drm_sched_fini(struct drm_gpu_scheduler * sched)1351 void drm_sched_fini(struct drm_gpu_scheduler *sched)
1352 {
1353 	struct drm_sched_entity *s_entity;
1354 	int i;
1355 
1356 	drm_sched_wqueue_stop(sched);
1357 
1358 	for (i = DRM_SCHED_PRIORITY_KERNEL; i < sched->num_rqs; i++) {
1359 		struct drm_sched_rq *rq = sched->sched_rq[i];
1360 
1361 		spin_lock(&rq->lock);
1362 		list_for_each_entry(s_entity, &rq->entities, list)
1363 			/*
1364 			 * Prevents reinsertion and marks job_queue as idle,
1365 			 * it will removed from rq in drm_sched_entity_fini
1366 			 * eventually
1367 			 */
1368 			s_entity->stopped = true;
1369 		spin_unlock(&rq->lock);
1370 		kfree(sched->sched_rq[i]);
1371 	}
1372 
1373 	/* Wakeup everyone stuck in drm_sched_entity_flush for this scheduler */
1374 	wake_up_all(&sched->job_scheduled);
1375 
1376 	/* Confirm no work left behind accessing device structures */
1377 	cancel_delayed_work_sync(&sched->work_tdr);
1378 
1379 	if (sched->own_submit_wq)
1380 		destroy_workqueue(sched->submit_wq);
1381 	sched->ready = false;
1382 	kfree(sched->sched_rq);
1383 	sched->sched_rq = NULL;
1384 }
1385 EXPORT_SYMBOL(drm_sched_fini);
1386 
1387 /**
1388  * drm_sched_increase_karma - Update sched_entity guilty flag
1389  *
1390  * @bad: The job guilty of time out
1391  *
1392  * Increment on every hang caused by the 'bad' job. If this exceeds the hang
1393  * limit of the scheduler then the respective sched entity is marked guilty and
1394  * jobs from it will not be scheduled further
1395  */
drm_sched_increase_karma(struct drm_sched_job * bad)1396 void drm_sched_increase_karma(struct drm_sched_job *bad)
1397 {
1398 	int i;
1399 	struct drm_sched_entity *tmp;
1400 	struct drm_sched_entity *entity;
1401 	struct drm_gpu_scheduler *sched = bad->sched;
1402 
1403 	/* don't change @bad's karma if it's from KERNEL RQ,
1404 	 * because sometimes GPU hang would cause kernel jobs (like VM updating jobs)
1405 	 * corrupt but keep in mind that kernel jobs always considered good.
1406 	 */
1407 	if (bad->s_priority != DRM_SCHED_PRIORITY_KERNEL) {
1408 		atomic_inc(&bad->karma);
1409 
1410 		for (i = DRM_SCHED_PRIORITY_HIGH; i < sched->num_rqs; i++) {
1411 			struct drm_sched_rq *rq = sched->sched_rq[i];
1412 
1413 			spin_lock(&rq->lock);
1414 			list_for_each_entry_safe(entity, tmp, &rq->entities, list) {
1415 				if (bad->s_fence->scheduled.context ==
1416 				    entity->fence_context) {
1417 					if (entity->guilty)
1418 						atomic_set(entity->guilty, 1);
1419 					break;
1420 				}
1421 			}
1422 			spin_unlock(&rq->lock);
1423 			if (&entity->list != &rq->entities)
1424 				break;
1425 		}
1426 	}
1427 }
1428 EXPORT_SYMBOL(drm_sched_increase_karma);
1429 
1430 /**
1431  * drm_sched_wqueue_ready - Is the scheduler ready for submission
1432  *
1433  * @sched: scheduler instance
1434  *
1435  * Returns true if submission is ready
1436  */
drm_sched_wqueue_ready(struct drm_gpu_scheduler * sched)1437 bool drm_sched_wqueue_ready(struct drm_gpu_scheduler *sched)
1438 {
1439 	return sched->ready;
1440 }
1441 EXPORT_SYMBOL(drm_sched_wqueue_ready);
1442 
1443 /**
1444  * drm_sched_wqueue_stop - stop scheduler submission
1445  *
1446  * @sched: scheduler instance
1447  */
drm_sched_wqueue_stop(struct drm_gpu_scheduler * sched)1448 void drm_sched_wqueue_stop(struct drm_gpu_scheduler *sched)
1449 {
1450 	WRITE_ONCE(sched->pause_submit, true);
1451 	cancel_work_sync(&sched->work_run_job);
1452 	cancel_work_sync(&sched->work_free_job);
1453 }
1454 EXPORT_SYMBOL(drm_sched_wqueue_stop);
1455 
1456 /**
1457  * drm_sched_wqueue_start - start scheduler submission
1458  *
1459  * @sched: scheduler instance
1460  */
drm_sched_wqueue_start(struct drm_gpu_scheduler * sched)1461 void drm_sched_wqueue_start(struct drm_gpu_scheduler *sched)
1462 {
1463 	WRITE_ONCE(sched->pause_submit, false);
1464 	queue_work(sched->submit_wq, &sched->work_run_job);
1465 	queue_work(sched->submit_wq, &sched->work_free_job);
1466 }
1467 EXPORT_SYMBOL(drm_sched_wqueue_start);
1468