sched_main.c 41 KB

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