1 /*
2 *
3 * (C) COPYRIGHT 2011-2017 ARM Limited. All rights reserved.
4 *
5 * This program is free software and is provided to you under the terms of the
6 * GNU General Public License version 2 as published by the Free Software
7 * Foundation, and any use by you of this program is subject to the terms
8 * of such GNU licence.
9 *
10 * A copy of the licence is included with the program, and can also be obtained
11 * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
12 * Boston, MA 02110-1301, USA.
13 *
14 */
15
16 /* #define ENABLE_DEBUG_LOG */
17 #include "./platform/rk/custom_log.h"
18
19 /*
20 * Job Scheduler Implementation
21 */
22 #include <mali_kbase.h>
23 #include <mali_kbase_js.h>
24 #if defined(CONFIG_MALI_GATOR_SUPPORT)
25 #include <mali_kbase_gator.h>
26 #endif
27 #include <mali_kbase_tlstream.h>
28 #include <mali_kbase_hw.h>
29 #include <mali_kbase_ctx_sched.h>
30
31 #include <mali_kbase_defs.h>
32 #include <mali_kbase_config_defaults.h>
33
34 #include "mali_kbase_jm.h"
35 #include "mali_kbase_hwaccess_jm.h"
36
37 /*
38 * Private types
39 */
40
41 /* Bitpattern indicating the result of releasing a context */
42 enum {
43 /* The context was descheduled - caller should try scheduling in a new
44 * one to keep the runpool full */
45 KBASEP_JS_RELEASE_RESULT_WAS_DESCHEDULED = (1u << 0),
46 /* Ctx attributes were changed - caller should try scheduling all
47 * contexts */
48 KBASEP_JS_RELEASE_RESULT_SCHED_ALL = (1u << 1)
49 };
50
51 typedef u32 kbasep_js_release_result;
52
53 const int kbasep_js_atom_priority_to_relative[BASE_JD_NR_PRIO_LEVELS] = {
54 KBASE_JS_ATOM_SCHED_PRIO_MED, /* BASE_JD_PRIO_MEDIUM */
55 KBASE_JS_ATOM_SCHED_PRIO_HIGH, /* BASE_JD_PRIO_HIGH */
56 KBASE_JS_ATOM_SCHED_PRIO_LOW /* BASE_JD_PRIO_LOW */
57 };
58
59 const base_jd_prio
60 kbasep_js_relative_priority_to_atom[KBASE_JS_ATOM_SCHED_PRIO_COUNT] = {
61 BASE_JD_PRIO_HIGH, /* KBASE_JS_ATOM_SCHED_PRIO_HIGH */
62 BASE_JD_PRIO_MEDIUM, /* KBASE_JS_ATOM_SCHED_PRIO_MED */
63 BASE_JD_PRIO_LOW /* KBASE_JS_ATOM_SCHED_PRIO_LOW */
64 };
65
66
67 /*
68 * Private function prototypes
69 */
70 static kbasep_js_release_result kbasep_js_runpool_release_ctx_internal(
71 struct kbase_device *kbdev, struct kbase_context *kctx,
72 struct kbasep_js_atom_retained_state *katom_retained_state);
73
74 static int kbase_js_get_slot(struct kbase_device *kbdev,
75 struct kbase_jd_atom *katom);
76
77 static void kbase_js_foreach_ctx_job(struct kbase_context *kctx,
78 kbasep_js_ctx_job_cb callback);
79
80 /* Helper for trace subcodes */
81 #if KBASE_TRACE_ENABLE
kbasep_js_trace_get_refcnt(struct kbase_device *kbdev, struct kbase_context *kctx)82 static int kbasep_js_trace_get_refcnt(struct kbase_device *kbdev,
83 struct kbase_context *kctx)
84 {
85 return atomic_read(&kctx->refcount);
86 }
87 #else /* KBASE_TRACE_ENABLE */
kbasep_js_trace_get_refcnt(struct kbase_device *kbdev, struct kbase_context *kctx)88 static int kbasep_js_trace_get_refcnt(struct kbase_device *kbdev,
89 struct kbase_context *kctx)
90 {
91 CSTD_UNUSED(kbdev);
92 CSTD_UNUSED(kctx);
93 return 0;
94 }
95 #endif /* KBASE_TRACE_ENABLE */
96
97 /*
98 * Private functions
99 */
100
101 /**
102 * core_reqs_from_jsn_features - Convert JSn_FEATURES to core requirements
103 * @features: JSn_FEATURE register value
104 *
105 * Given a JSn_FEATURE register value returns the core requirements that match
106 *
107 * Return: Core requirement bit mask
108 */
core_reqs_from_jsn_features(u16 features)109 static base_jd_core_req core_reqs_from_jsn_features(u16 features)
110 {
111 base_jd_core_req core_req = 0u;
112
113 if ((features & JS_FEATURE_SET_VALUE_JOB) != 0)
114 core_req |= BASE_JD_REQ_V;
115
116 if ((features & JS_FEATURE_CACHE_FLUSH_JOB) != 0)
117 core_req |= BASE_JD_REQ_CF;
118
119 if ((features & JS_FEATURE_COMPUTE_JOB) != 0)
120 core_req |= BASE_JD_REQ_CS;
121
122 if ((features & JS_FEATURE_TILER_JOB) != 0)
123 core_req |= BASE_JD_REQ_T;
124
125 if ((features & JS_FEATURE_FRAGMENT_JOB) != 0)
126 core_req |= BASE_JD_REQ_FS;
127
128 return core_req;
129 }
130
kbase_js_sync_timers(struct kbase_device *kbdev)131 static void kbase_js_sync_timers(struct kbase_device *kbdev)
132 {
133 mutex_lock(&kbdev->js_data.runpool_mutex);
134 kbase_backend_ctx_count_changed(kbdev);
135 mutex_unlock(&kbdev->js_data.runpool_mutex);
136 }
137
138 /* Hold the mmu_hw_mutex and hwaccess_lock for this */
kbasep_js_runpool_retain_ctx_nolock(struct kbase_device *kbdev, struct kbase_context *kctx)139 bool kbasep_js_runpool_retain_ctx_nolock(struct kbase_device *kbdev,
140 struct kbase_context *kctx)
141 {
142 struct kbasep_js_device_data *js_devdata;
143 bool result = false;
144 int as_nr;
145
146 KBASE_DEBUG_ASSERT(kbdev != NULL);
147 KBASE_DEBUG_ASSERT(kctx != NULL);
148 js_devdata = &kbdev->js_data;
149
150 lockdep_assert_held(&kbdev->hwaccess_lock);
151
152 as_nr = kctx->as_nr;
153 if (atomic_read(&kctx->refcount) > 0) {
154 KBASE_DEBUG_ASSERT(as_nr >= 0);
155
156 kbase_ctx_sched_retain_ctx_refcount(kctx);
157 KBASE_TRACE_ADD_REFCOUNT(kbdev, JS_RETAIN_CTX_NOLOCK, kctx,
158 NULL, 0u, atomic_read(&kctx->refcount));
159 result = true;
160 }
161
162 return result;
163 }
164
165 /**
166 * jsctx_rb_none_to_pull_prio(): - Check if there are no pullable atoms
167 * @kctx: Pointer to kbase context with ring buffer.
168 * @js: Job slot id to check.
169 * @prio: Priority to check.
170 *
171 * Return true if there are no atoms to pull. There may be running atoms in the
172 * ring buffer even if there are no atoms to pull. It is also possible for the
173 * ring buffer to be full (with running atoms) when this functions returns
174 * true.
175 *
176 * Return: true if there are no atoms to pull, false otherwise.
177 */
178 static inline bool
jsctx_rb_none_to_pull_prio(struct kbase_context *kctx, int js, int prio)179 jsctx_rb_none_to_pull_prio(struct kbase_context *kctx, int js, int prio)
180 {
181 struct jsctx_queue *rb = &kctx->jsctx_queue[prio][js];
182
183 lockdep_assert_held(&kctx->kbdev->hwaccess_lock);
184
185 return RB_EMPTY_ROOT(&rb->runnable_tree);
186 }
187
188 /**
189 * jsctx_rb_none_to_pull(): - Check if all priority ring buffers have no
190 * pullable atoms
191 * @kctx: Pointer to kbase context with ring buffer.
192 * @js: Job slot id to check.
193 *
194 * Caller must hold hwaccess_lock
195 *
196 * Return: true if the ring buffers for all priorities have no pullable atoms,
197 * false otherwise.
198 */
199 static inline bool
jsctx_rb_none_to_pull(struct kbase_context *kctx, int js)200 jsctx_rb_none_to_pull(struct kbase_context *kctx, int js)
201 {
202 int prio;
203
204 lockdep_assert_held(&kctx->kbdev->hwaccess_lock);
205
206 for (prio = 0; prio < KBASE_JS_ATOM_SCHED_PRIO_COUNT; prio++) {
207 if (!jsctx_rb_none_to_pull_prio(kctx, js, prio))
208 return false;
209 }
210
211 return true;
212 }
213
214 /**
215 * jsctx_queue_foreach_prio(): - Execute callback for each entry in the queue.
216 * @kctx: Pointer to kbase context with the queue.
217 * @js: Job slot id to iterate.
218 * @prio: Priority id to iterate.
219 * @callback: Function pointer to callback.
220 *
221 * Iterate over a queue and invoke @callback for each entry in the queue, and
222 * remove the entry from the queue.
223 *
224 * If entries are added to the queue while this is running those entries may, or
225 * may not be covered. To ensure that all entries in the buffer have been
226 * enumerated when this function returns jsctx->lock must be held when calling
227 * this function.
228 *
229 * The HW access lock must always be held when calling this function.
230 */
231 static void
jsctx_queue_foreach_prio(struct kbase_context *kctx, int js, int prio, kbasep_js_ctx_job_cb callback)232 jsctx_queue_foreach_prio(struct kbase_context *kctx, int js, int prio,
233 kbasep_js_ctx_job_cb callback)
234 {
235 struct jsctx_queue *queue = &kctx->jsctx_queue[prio][js];
236
237 lockdep_assert_held(&kctx->kbdev->hwaccess_lock);
238
239 while (!RB_EMPTY_ROOT(&queue->runnable_tree)) {
240 struct rb_node *node = rb_first(&queue->runnable_tree);
241 struct kbase_jd_atom *entry = rb_entry(node,
242 struct kbase_jd_atom, runnable_tree_node);
243
244 rb_erase(node, &queue->runnable_tree);
245 callback(kctx->kbdev, entry);
246 }
247
248 while (!list_empty(&queue->x_dep_head)) {
249 struct kbase_jd_atom *entry = list_entry(queue->x_dep_head.next,
250 struct kbase_jd_atom, queue);
251
252 list_del(queue->x_dep_head.next);
253
254 callback(kctx->kbdev, entry);
255 }
256 }
257
258 /**
259 * jsctx_queue_foreach(): - Execute callback for each entry in every queue
260 * @kctx: Pointer to kbase context with queue.
261 * @js: Job slot id to iterate.
262 * @callback: Function pointer to callback.
263 *
264 * Iterate over all the different priorities, and for each call
265 * jsctx_queue_foreach_prio() to iterate over the queue and invoke @callback
266 * for each entry, and remove the entry from the queue.
267 */
268 static inline void
jsctx_queue_foreach(struct kbase_context *kctx, int js, kbasep_js_ctx_job_cb callback)269 jsctx_queue_foreach(struct kbase_context *kctx, int js,
270 kbasep_js_ctx_job_cb callback)
271 {
272 int prio;
273
274 for (prio = 0; prio < KBASE_JS_ATOM_SCHED_PRIO_COUNT; prio++)
275 jsctx_queue_foreach_prio(kctx, js, prio, callback);
276 }
277
278 /**
279 * jsctx_rb_peek_prio(): - Check buffer and get next atom
280 * @kctx: Pointer to kbase context with ring buffer.
281 * @js: Job slot id to check.
282 * @prio: Priority id to check.
283 *
284 * Check the ring buffer for the specified @js and @prio and return a pointer to
285 * the next atom, unless the ring buffer is empty.
286 *
287 * Return: Pointer to next atom in buffer, or NULL if there is no atom.
288 */
289 static inline struct kbase_jd_atom *
jsctx_rb_peek_prio(struct kbase_context *kctx, int js, int prio)290 jsctx_rb_peek_prio(struct kbase_context *kctx, int js, int prio)
291 {
292 struct jsctx_queue *rb = &kctx->jsctx_queue[prio][js];
293 struct rb_node *node;
294
295 lockdep_assert_held(&kctx->kbdev->hwaccess_lock);
296
297 node = rb_first(&rb->runnable_tree);
298 if (!node)
299 return NULL;
300
301 return rb_entry(node, struct kbase_jd_atom, runnable_tree_node);
302 }
303
304 /**
305 * jsctx_rb_peek(): - Check all priority buffers and get next atom
306 * @kctx: Pointer to kbase context with ring buffer.
307 * @js: Job slot id to check.
308 *
309 * Check the ring buffers for all priorities, starting from
310 * KBASE_JS_ATOM_SCHED_PRIO_HIGH, for the specified @js and @prio and return a
311 * pointer to the next atom, unless all the priority's ring buffers are empty.
312 *
313 * Caller must hold the hwaccess_lock.
314 *
315 * Return: Pointer to next atom in buffer, or NULL if there is no atom.
316 */
317 static inline struct kbase_jd_atom *
jsctx_rb_peek(struct kbase_context *kctx, int js)318 jsctx_rb_peek(struct kbase_context *kctx, int js)
319 {
320 int prio;
321
322 lockdep_assert_held(&kctx->kbdev->hwaccess_lock);
323
324 for (prio = 0; prio < KBASE_JS_ATOM_SCHED_PRIO_COUNT; prio++) {
325 struct kbase_jd_atom *katom;
326
327 katom = jsctx_rb_peek_prio(kctx, js, prio);
328 if (katom)
329 return katom;
330 }
331
332 return NULL;
333 }
334
335 /**
336 * jsctx_rb_pull(): - Mark atom in list as running
337 * @kctx: Pointer to kbase context with ring buffer.
338 * @katom: Pointer to katom to pull.
339 *
340 * Mark an atom previously obtained from jsctx_rb_peek() as running.
341 *
342 * @katom must currently be at the head of the ring buffer.
343 */
344 static inline void
jsctx_rb_pull(struct kbase_context *kctx, struct kbase_jd_atom *katom)345 jsctx_rb_pull(struct kbase_context *kctx, struct kbase_jd_atom *katom)
346 {
347 int prio = katom->sched_priority;
348 int js = katom->slot_nr;
349 struct jsctx_queue *rb = &kctx->jsctx_queue[prio][js];
350
351 lockdep_assert_held(&kctx->kbdev->hwaccess_lock);
352
353 /* Atoms must be pulled in the correct order. */
354 WARN_ON(katom != jsctx_rb_peek_prio(kctx, js, prio));
355
356 rb_erase(&katom->runnable_tree_node, &rb->runnable_tree);
357 }
358
359 #define LESS_THAN_WRAP(a, b) ((s32)(a - b) < 0)
360
361 static void
jsctx_tree_add(struct kbase_context *kctx, struct kbase_jd_atom *katom)362 jsctx_tree_add(struct kbase_context *kctx, struct kbase_jd_atom *katom)
363 {
364 int prio = katom->sched_priority;
365 int js = katom->slot_nr;
366 struct jsctx_queue *queue = &kctx->jsctx_queue[prio][js];
367 struct rb_node **new = &(queue->runnable_tree.rb_node), *parent = NULL;
368
369 lockdep_assert_held(&kctx->kbdev->hwaccess_lock);
370
371 while (*new) {
372 struct kbase_jd_atom *entry = container_of(*new,
373 struct kbase_jd_atom, runnable_tree_node);
374
375 parent = *new;
376 if (LESS_THAN_WRAP(katom->age, entry->age))
377 new = &((*new)->rb_left);
378 else
379 new = &((*new)->rb_right);
380 }
381
382 /* Add new node and rebalance tree. */
383 rb_link_node(&katom->runnable_tree_node, parent, new);
384 rb_insert_color(&katom->runnable_tree_node, &queue->runnable_tree);
385 }
386
387 /**
388 * jsctx_rb_unpull(): - Undo marking of atom in list as running
389 * @kctx: Pointer to kbase context with ring buffer.
390 * @katom: Pointer to katom to unpull.
391 *
392 * Undo jsctx_rb_pull() and put @katom back in the queue.
393 *
394 * jsctx_rb_unpull() must be called on atoms in the same order the atoms were
395 * pulled.
396 */
397 static inline void
jsctx_rb_unpull(struct kbase_context *kctx, struct kbase_jd_atom *katom)398 jsctx_rb_unpull(struct kbase_context *kctx, struct kbase_jd_atom *katom)
399 {
400 lockdep_assert_held(&kctx->kbdev->hwaccess_lock);
401
402 jsctx_tree_add(kctx, katom);
403 }
404
405 static bool kbase_js_ctx_pullable(struct kbase_context *kctx,
406 int js,
407 bool is_scheduled);
408 static bool kbase_js_ctx_list_add_pullable_nolock(struct kbase_device *kbdev,
409 struct kbase_context *kctx,
410 int js);
411 static bool kbase_js_ctx_list_add_unpullable_nolock(struct kbase_device *kbdev,
412 struct kbase_context *kctx,
413 int js);
414
415 /*
416 * Functions private to KBase ('Protected' functions)
417 */
kbasep_js_devdata_init(struct kbase_device * const kbdev)418 int kbasep_js_devdata_init(struct kbase_device * const kbdev)
419 {
420 struct kbasep_js_device_data *jsdd;
421 int i;
422
423 KBASE_DEBUG_ASSERT(kbdev != NULL);
424
425 jsdd = &kbdev->js_data;
426
427 #ifdef CONFIG_MALI_DEBUG
428 /* Soft-stop will be disabled on a single context by default unless
429 * softstop_always is set */
430 jsdd->softstop_always = false;
431 #endif /* CONFIG_MALI_DEBUG */
432 jsdd->nr_all_contexts_running = 0;
433 jsdd->nr_user_contexts_running = 0;
434 jsdd->nr_contexts_pullable = 0;
435 atomic_set(&jsdd->nr_contexts_runnable, 0);
436 /* No ctx allowed to submit */
437 jsdd->runpool_irq.submit_allowed = 0u;
438 memset(jsdd->runpool_irq.ctx_attr_ref_count, 0,
439 sizeof(jsdd->runpool_irq.ctx_attr_ref_count));
440 memset(jsdd->runpool_irq.slot_affinities, 0,
441 sizeof(jsdd->runpool_irq.slot_affinities));
442 memset(jsdd->runpool_irq.slot_affinity_refcount, 0,
443 sizeof(jsdd->runpool_irq.slot_affinity_refcount));
444 INIT_LIST_HEAD(&jsdd->suspended_soft_jobs_list);
445
446 /* Config attributes */
447 jsdd->scheduling_period_ns = DEFAULT_JS_SCHEDULING_PERIOD_NS;
448 jsdd->soft_stop_ticks = DEFAULT_JS_SOFT_STOP_TICKS;
449 jsdd->soft_stop_ticks_cl = DEFAULT_JS_SOFT_STOP_TICKS_CL;
450 if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_8408))
451 jsdd->hard_stop_ticks_ss = DEFAULT_JS_HARD_STOP_TICKS_SS_8408;
452 else
453 jsdd->hard_stop_ticks_ss = DEFAULT_JS_HARD_STOP_TICKS_SS;
454 jsdd->hard_stop_ticks_cl = DEFAULT_JS_HARD_STOP_TICKS_CL;
455 jsdd->hard_stop_ticks_dumping = DEFAULT_JS_HARD_STOP_TICKS_DUMPING;
456 if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_8408))
457 jsdd->gpu_reset_ticks_ss = DEFAULT_JS_RESET_TICKS_SS_8408;
458 else
459 jsdd->gpu_reset_ticks_ss = DEFAULT_JS_RESET_TICKS_SS;
460 jsdd->gpu_reset_ticks_cl = DEFAULT_JS_RESET_TICKS_CL;
461 jsdd->gpu_reset_ticks_dumping = DEFAULT_JS_RESET_TICKS_DUMPING;
462 jsdd->ctx_timeslice_ns = DEFAULT_JS_CTX_TIMESLICE_NS;
463 atomic_set(&jsdd->soft_job_timeout_ms, DEFAULT_JS_SOFT_JOB_TIMEOUT);
464
465 dev_dbg(kbdev->dev, "JS Config Attribs: ");
466 dev_dbg(kbdev->dev, "\tscheduling_period_ns:%u",
467 jsdd->scheduling_period_ns);
468 dev_dbg(kbdev->dev, "\tsoft_stop_ticks:%u",
469 jsdd->soft_stop_ticks);
470 dev_dbg(kbdev->dev, "\tsoft_stop_ticks_cl:%u",
471 jsdd->soft_stop_ticks_cl);
472 dev_dbg(kbdev->dev, "\thard_stop_ticks_ss:%u",
473 jsdd->hard_stop_ticks_ss);
474 dev_dbg(kbdev->dev, "\thard_stop_ticks_cl:%u",
475 jsdd->hard_stop_ticks_cl);
476 dev_dbg(kbdev->dev, "\thard_stop_ticks_dumping:%u",
477 jsdd->hard_stop_ticks_dumping);
478 dev_dbg(kbdev->dev, "\tgpu_reset_ticks_ss:%u",
479 jsdd->gpu_reset_ticks_ss);
480 dev_dbg(kbdev->dev, "\tgpu_reset_ticks_cl:%u",
481 jsdd->gpu_reset_ticks_cl);
482 dev_dbg(kbdev->dev, "\tgpu_reset_ticks_dumping:%u",
483 jsdd->gpu_reset_ticks_dumping);
484 dev_dbg(kbdev->dev, "\tctx_timeslice_ns:%u",
485 jsdd->ctx_timeslice_ns);
486 dev_dbg(kbdev->dev, "\tsoft_job_timeout:%i",
487 atomic_read(&jsdd->soft_job_timeout_ms));
488
489 if (!(jsdd->soft_stop_ticks < jsdd->hard_stop_ticks_ss &&
490 jsdd->hard_stop_ticks_ss < jsdd->gpu_reset_ticks_ss &&
491 jsdd->soft_stop_ticks < jsdd->hard_stop_ticks_dumping &&
492 jsdd->hard_stop_ticks_dumping <
493 jsdd->gpu_reset_ticks_dumping)) {
494 dev_err(kbdev->dev, "Job scheduler timeouts invalid; soft/hard/reset tick counts should be in increasing order\n");
495 return -EINVAL;
496 }
497
498 #if KBASE_DISABLE_SCHEDULING_SOFT_STOPS
499 dev_dbg(kbdev->dev, "Job Scheduling Soft-stops disabled, ignoring value for soft_stop_ticks==%u at %uns per tick. Other soft-stops may still occur.",
500 jsdd->soft_stop_ticks,
501 jsdd->scheduling_period_ns);
502 #endif
503 #if KBASE_DISABLE_SCHEDULING_HARD_STOPS
504 dev_dbg(kbdev->dev, "Job Scheduling Hard-stops disabled, ignoring values for hard_stop_ticks_ss==%d and hard_stop_ticks_dumping==%u at %uns per tick. Other hard-stops may still occur.",
505 jsdd->hard_stop_ticks_ss,
506 jsdd->hard_stop_ticks_dumping,
507 jsdd->scheduling_period_ns);
508 #endif
509 #if KBASE_DISABLE_SCHEDULING_SOFT_STOPS && KBASE_DISABLE_SCHEDULING_HARD_STOPS
510 dev_dbg(kbdev->dev, "Note: The JS tick timer (if coded) will still be run, but do nothing.");
511 #endif
512
513 for (i = 0; i < kbdev->gpu_props.num_job_slots; ++i)
514 jsdd->js_reqs[i] = core_reqs_from_jsn_features(
515 kbdev->gpu_props.props.raw_props.js_features[i]);
516
517 /* On error, we could continue on: providing none of the below resources
518 * rely on the ones above */
519
520 mutex_init(&jsdd->runpool_mutex);
521 mutex_init(&jsdd->queue_mutex);
522 spin_lock_init(&kbdev->hwaccess_lock);
523 sema_init(&jsdd->schedule_sem, 1);
524
525 for (i = 0; i < kbdev->gpu_props.num_job_slots; ++i) {
526 INIT_LIST_HEAD(&jsdd->ctx_list_pullable[i]);
527 INIT_LIST_HEAD(&jsdd->ctx_list_unpullable[i]);
528 }
529
530 return 0;
531 }
532
kbasep_js_devdata_halt(struct kbase_device *kbdev)533 void kbasep_js_devdata_halt(struct kbase_device *kbdev)
534 {
535 CSTD_UNUSED(kbdev);
536 }
537
kbasep_js_devdata_term(struct kbase_device *kbdev)538 void kbasep_js_devdata_term(struct kbase_device *kbdev)
539 {
540 struct kbasep_js_device_data *js_devdata;
541 s8 zero_ctx_attr_ref_count[KBASEP_JS_CTX_ATTR_COUNT] = { 0, };
542
543 KBASE_DEBUG_ASSERT(kbdev != NULL);
544
545 js_devdata = &kbdev->js_data;
546
547 /* The caller must de-register all contexts before calling this
548 */
549 KBASE_DEBUG_ASSERT(js_devdata->nr_all_contexts_running == 0);
550 KBASE_DEBUG_ASSERT(memcmp(
551 js_devdata->runpool_irq.ctx_attr_ref_count,
552 zero_ctx_attr_ref_count,
553 sizeof(zero_ctx_attr_ref_count)) == 0);
554 CSTD_UNUSED(zero_ctx_attr_ref_count);
555 }
556
kbasep_js_kctx_init(struct kbase_context * const kctx)557 int kbasep_js_kctx_init(struct kbase_context * const kctx)
558 {
559 struct kbase_device *kbdev;
560 struct kbasep_js_kctx_info *js_kctx_info;
561 int i, j;
562
563 KBASE_DEBUG_ASSERT(kctx != NULL);
564
565 kbdev = kctx->kbdev;
566 KBASE_DEBUG_ASSERT(kbdev != NULL);
567
568 for (i = 0; i < BASE_JM_MAX_NR_SLOTS; ++i)
569 INIT_LIST_HEAD(&kctx->jctx.sched_info.ctx.ctx_list_entry[i]);
570
571 js_kctx_info = &kctx->jctx.sched_info;
572
573 js_kctx_info->ctx.nr_jobs = 0;
574 kbase_ctx_flag_clear(kctx, KCTX_SCHEDULED);
575 kbase_ctx_flag_clear(kctx, KCTX_DYING);
576 memset(js_kctx_info->ctx.ctx_attr_ref_count, 0,
577 sizeof(js_kctx_info->ctx.ctx_attr_ref_count));
578
579 /* Initially, the context is disabled from submission until the create
580 * flags are set */
581 kbase_ctx_flag_set(kctx, KCTX_SUBMIT_DISABLED);
582
583 /* On error, we could continue on: providing none of the below resources
584 * rely on the ones above */
585 mutex_init(&js_kctx_info->ctx.jsctx_mutex);
586
587 init_waitqueue_head(&js_kctx_info->ctx.is_scheduled_wait);
588
589 for (i = 0; i < KBASE_JS_ATOM_SCHED_PRIO_COUNT; i++) {
590 for (j = 0; j < BASE_JM_MAX_NR_SLOTS; j++) {
591 INIT_LIST_HEAD(&kctx->jsctx_queue[i][j].x_dep_head);
592 kctx->jsctx_queue[i][j].runnable_tree = RB_ROOT;
593 }
594 }
595
596 return 0;
597 }
598
kbasep_js_kctx_term(struct kbase_context *kctx)599 void kbasep_js_kctx_term(struct kbase_context *kctx)
600 {
601 struct kbase_device *kbdev;
602 struct kbasep_js_kctx_info *js_kctx_info;
603 int js;
604 bool update_ctx_count = false;
605
606 KBASE_DEBUG_ASSERT(kctx != NULL);
607
608 kbdev = kctx->kbdev;
609 KBASE_DEBUG_ASSERT(kbdev != NULL);
610
611 js_kctx_info = &kctx->jctx.sched_info;
612
613 /* The caller must de-register all jobs before calling this */
614 KBASE_DEBUG_ASSERT(!kbase_ctx_flag(kctx, KCTX_SCHEDULED));
615 KBASE_DEBUG_ASSERT(js_kctx_info->ctx.nr_jobs == 0);
616
617 mutex_lock(&kbdev->js_data.queue_mutex);
618 mutex_lock(&kctx->jctx.sched_info.ctx.jsctx_mutex);
619
620 for (js = 0; js < kbdev->gpu_props.num_job_slots; js++)
621 list_del_init(&kctx->jctx.sched_info.ctx.ctx_list_entry[js]);
622
623 if (kbase_ctx_flag(kctx, KCTX_RUNNABLE_REF)) {
624 WARN_ON(atomic_read(&kbdev->js_data.nr_contexts_runnable) <= 0);
625 atomic_dec(&kbdev->js_data.nr_contexts_runnable);
626 update_ctx_count = true;
627 kbase_ctx_flag_clear(kctx, KCTX_RUNNABLE_REF);
628 }
629
630 mutex_unlock(&kctx->jctx.sched_info.ctx.jsctx_mutex);
631 mutex_unlock(&kbdev->js_data.queue_mutex);
632
633 if (update_ctx_count) {
634 mutex_lock(&kbdev->js_data.runpool_mutex);
635 kbase_backend_ctx_count_changed(kbdev);
636 mutex_unlock(&kbdev->js_data.runpool_mutex);
637 }
638 }
639
640 /**
641 * kbase_js_ctx_list_add_pullable_nolock - Variant of
642 * kbase_jd_ctx_list_add_pullable()
643 * where the caller must hold
644 * hwaccess_lock
645 * @kbdev: Device pointer
646 * @kctx: Context to add to queue
647 * @js: Job slot to use
648 *
649 * Caller must hold hwaccess_lock
650 *
651 * Return: true if caller should call kbase_backend_ctx_count_changed()
652 */
kbase_js_ctx_list_add_pullable_nolock(struct kbase_device *kbdev, struct kbase_context *kctx, int js)653 static bool kbase_js_ctx_list_add_pullable_nolock(struct kbase_device *kbdev,
654 struct kbase_context *kctx,
655 int js)
656 {
657 bool ret = false;
658
659 lockdep_assert_held(&kbdev->hwaccess_lock);
660
661 if (!list_empty(&kctx->jctx.sched_info.ctx.ctx_list_entry[js]))
662 list_del_init(&kctx->jctx.sched_info.ctx.ctx_list_entry[js]);
663
664 list_add_tail(&kctx->jctx.sched_info.ctx.ctx_list_entry[js],
665 &kbdev->js_data.ctx_list_pullable[js]);
666
667 if (!kctx->slots_pullable) {
668 kbdev->js_data.nr_contexts_pullable++;
669 ret = true;
670 if (!atomic_read(&kctx->atoms_pulled)) {
671 WARN_ON(kbase_ctx_flag(kctx, KCTX_RUNNABLE_REF));
672 kbase_ctx_flag_set(kctx, KCTX_RUNNABLE_REF);
673 atomic_inc(&kbdev->js_data.nr_contexts_runnable);
674 }
675 }
676 kctx->slots_pullable |= (1 << js);
677
678 return ret;
679 }
680
681 /**
682 * kbase_js_ctx_list_add_pullable_head_nolock - Variant of
683 * kbase_js_ctx_list_add_pullable_head()
684 * where the caller must hold
685 * hwaccess_lock
686 * @kbdev: Device pointer
687 * @kctx: Context to add to queue
688 * @js: Job slot to use
689 *
690 * Caller must hold hwaccess_lock
691 *
692 * Return: true if caller should call kbase_backend_ctx_count_changed()
693 */
kbase_js_ctx_list_add_pullable_head_nolock( struct kbase_device *kbdev, struct kbase_context *kctx, int js)694 static bool kbase_js_ctx_list_add_pullable_head_nolock(
695 struct kbase_device *kbdev, struct kbase_context *kctx, int js)
696 {
697 bool ret = false;
698
699 lockdep_assert_held(&kbdev->hwaccess_lock);
700
701 if (!list_empty(&kctx->jctx.sched_info.ctx.ctx_list_entry[js]))
702 list_del_init(&kctx->jctx.sched_info.ctx.ctx_list_entry[js]);
703
704 list_add(&kctx->jctx.sched_info.ctx.ctx_list_entry[js],
705 &kbdev->js_data.ctx_list_pullable[js]);
706
707 if (!kctx->slots_pullable) {
708 kbdev->js_data.nr_contexts_pullable++;
709 ret = true;
710 if (!atomic_read(&kctx->atoms_pulled)) {
711 WARN_ON(kbase_ctx_flag(kctx, KCTX_RUNNABLE_REF));
712 kbase_ctx_flag_set(kctx, KCTX_RUNNABLE_REF);
713 atomic_inc(&kbdev->js_data.nr_contexts_runnable);
714 }
715 }
716 kctx->slots_pullable |= (1 << js);
717
718 return ret;
719 }
720
721 /**
722 * kbase_js_ctx_list_add_pullable_head - Add context to the head of the
723 * per-slot pullable context queue
724 * @kbdev: Device pointer
725 * @kctx: Context to add to queue
726 * @js: Job slot to use
727 *
728 * If the context is on either the pullable or unpullable queues, then it is
729 * removed before being added to the head.
730 *
731 * This function should be used when a context has been scheduled, but no jobs
732 * can currently be pulled from it.
733 *
734 * Return: true if caller should call kbase_backend_ctx_count_changed()
735 */
kbase_js_ctx_list_add_pullable_head(struct kbase_device *kbdev, struct kbase_context *kctx, int js)736 static bool kbase_js_ctx_list_add_pullable_head(struct kbase_device *kbdev,
737 struct kbase_context *kctx,
738 int js)
739 {
740 bool ret;
741 unsigned long flags;
742
743 spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
744 ret = kbase_js_ctx_list_add_pullable_head_nolock(kbdev, kctx, js);
745 spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
746
747 return ret;
748 }
749
750 /**
751 * kbase_js_ctx_list_add_unpullable_nolock - Add context to the tail of the
752 * per-slot unpullable context queue
753 * @kbdev: Device pointer
754 * @kctx: Context to add to queue
755 * @js: Job slot to use
756 *
757 * The context must already be on the per-slot pullable queue. It will be
758 * removed from the pullable queue before being added to the unpullable queue.
759 *
760 * This function should be used when a context has been pulled from, and there
761 * are no jobs remaining on the specified slot.
762 *
763 * Caller must hold hwaccess_lock
764 *
765 * Return: true if caller should call kbase_backend_ctx_count_changed()
766 */
kbase_js_ctx_list_add_unpullable_nolock(struct kbase_device *kbdev, struct kbase_context *kctx, int js)767 static bool kbase_js_ctx_list_add_unpullable_nolock(struct kbase_device *kbdev,
768 struct kbase_context *kctx,
769 int js)
770 {
771 bool ret = false;
772
773 lockdep_assert_held(&kbdev->hwaccess_lock);
774
775 list_move_tail(&kctx->jctx.sched_info.ctx.ctx_list_entry[js],
776 &kbdev->js_data.ctx_list_unpullable[js]);
777
778 if (kctx->slots_pullable == (1 << js)) {
779 kbdev->js_data.nr_contexts_pullable--;
780 ret = true;
781 if (!atomic_read(&kctx->atoms_pulled)) {
782 WARN_ON(!kbase_ctx_flag(kctx, KCTX_RUNNABLE_REF));
783 kbase_ctx_flag_clear(kctx, KCTX_RUNNABLE_REF);
784 atomic_dec(&kbdev->js_data.nr_contexts_runnable);
785 }
786 }
787 kctx->slots_pullable &= ~(1 << js);
788
789 return ret;
790 }
791
792 /**
793 * kbase_js_ctx_list_remove_nolock - Remove context from the per-slot pullable
794 * or unpullable context queues
795 * @kbdev: Device pointer
796 * @kctx: Context to remove from queue
797 * @js: Job slot to use
798 *
799 * The context must already be on one of the queues.
800 *
801 * This function should be used when a context has no jobs on the GPU, and no
802 * jobs remaining for the specified slot.
803 *
804 * Caller must hold hwaccess_lock
805 *
806 * Return: true if caller should call kbase_backend_ctx_count_changed()
807 */
kbase_js_ctx_list_remove_nolock(struct kbase_device *kbdev, struct kbase_context *kctx, int js)808 static bool kbase_js_ctx_list_remove_nolock(struct kbase_device *kbdev,
809 struct kbase_context *kctx,
810 int js)
811 {
812 bool ret = false;
813
814 lockdep_assert_held(&kbdev->hwaccess_lock);
815
816 WARN_ON(list_empty(&kctx->jctx.sched_info.ctx.ctx_list_entry[js]));
817
818 list_del_init(&kctx->jctx.sched_info.ctx.ctx_list_entry[js]);
819
820 if (kctx->slots_pullable == (1 << js)) {
821 kbdev->js_data.nr_contexts_pullable--;
822 ret = true;
823 if (!atomic_read(&kctx->atoms_pulled)) {
824 WARN_ON(!kbase_ctx_flag(kctx, KCTX_RUNNABLE_REF));
825 kbase_ctx_flag_clear(kctx, KCTX_RUNNABLE_REF);
826 atomic_dec(&kbdev->js_data.nr_contexts_runnable);
827 }
828 }
829 kctx->slots_pullable &= ~(1 << js);
830
831 return ret;
832 }
833
834 /**
835 * kbase_js_ctx_list_pop_head_nolock - Variant of kbase_js_ctx_list_pop_head()
836 * where the caller must hold
837 * hwaccess_lock
838 * @kbdev: Device pointer
839 * @js: Job slot to use
840 *
841 * Caller must hold hwaccess_lock
842 *
843 * Return: Context to use for specified slot.
844 * NULL if no contexts present for specified slot
845 */
kbase_js_ctx_list_pop_head_nolock( struct kbase_device *kbdev, int js)846 static struct kbase_context *kbase_js_ctx_list_pop_head_nolock(
847 struct kbase_device *kbdev,
848 int js)
849 {
850 struct kbase_context *kctx;
851
852 lockdep_assert_held(&kbdev->hwaccess_lock);
853
854 if (list_empty(&kbdev->js_data.ctx_list_pullable[js]))
855 return NULL;
856
857 kctx = list_entry(kbdev->js_data.ctx_list_pullable[js].next,
858 struct kbase_context,
859 jctx.sched_info.ctx.ctx_list_entry[js]);
860
861 list_del_init(&kctx->jctx.sched_info.ctx.ctx_list_entry[js]);
862
863 return kctx;
864 }
865
866 /**
867 * kbase_js_ctx_list_pop_head - Pop the head context off the per-slot pullable
868 * queue.
869 * @kbdev: Device pointer
870 * @js: Job slot to use
871 *
872 * Return: Context to use for specified slot.
873 * NULL if no contexts present for specified slot
874 */
kbase_js_ctx_list_pop_head( struct kbase_device *kbdev, int js)875 static struct kbase_context *kbase_js_ctx_list_pop_head(
876 struct kbase_device *kbdev, int js)
877 {
878 struct kbase_context *kctx;
879 unsigned long flags;
880
881 spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
882 kctx = kbase_js_ctx_list_pop_head_nolock(kbdev, js);
883 spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
884
885 return kctx;
886 }
887
888 /**
889 * kbase_js_ctx_pullable - Return if a context can be pulled from on the
890 * specified slot
891 * @kctx: Context pointer
892 * @js: Job slot to use
893 * @is_scheduled: true if the context is currently scheduled
894 *
895 * Caller must hold hwaccess_lock
896 *
897 * Return: true if context can be pulled from on specified slot
898 * false otherwise
899 */
kbase_js_ctx_pullable(struct kbase_context *kctx, int js, bool is_scheduled)900 static bool kbase_js_ctx_pullable(struct kbase_context *kctx, int js,
901 bool is_scheduled)
902 {
903 struct kbasep_js_device_data *js_devdata;
904 struct kbase_jd_atom *katom;
905
906 lockdep_assert_held(&kctx->kbdev->hwaccess_lock);
907
908 js_devdata = &kctx->kbdev->js_data;
909
910 if (is_scheduled) {
911 if (!kbasep_js_is_submit_allowed(js_devdata, kctx))
912 return false;
913 }
914 katom = jsctx_rb_peek(kctx, js);
915 if (!katom)
916 return false; /* No pullable atoms */
917 if (kctx->blocked_js[js][katom->sched_priority])
918 return false;
919 if (atomic_read(&katom->blocked))
920 return false; /* next atom blocked */
921 if (katom->atom_flags & KBASE_KATOM_FLAG_X_DEP_BLOCKED) {
922 if (katom->x_pre_dep->gpu_rb_state ==
923 KBASE_ATOM_GPU_RB_NOT_IN_SLOT_RB ||
924 katom->x_pre_dep->will_fail_event_code)
925 return false;
926 if ((katom->atom_flags & KBASE_KATOM_FLAG_FAIL_BLOCKER) &&
927 kbase_backend_nr_atoms_on_slot(kctx->kbdev, js))
928 return false;
929 }
930
931 return true;
932 }
933
kbase_js_dep_validate(struct kbase_context *kctx, struct kbase_jd_atom *katom)934 static bool kbase_js_dep_validate(struct kbase_context *kctx,
935 struct kbase_jd_atom *katom)
936 {
937 struct kbase_device *kbdev = kctx->kbdev;
938 bool ret = true;
939 bool has_dep = false, has_x_dep = false;
940 int js = kbase_js_get_slot(kbdev, katom);
941 int prio = katom->sched_priority;
942 int i;
943
944 for (i = 0; i < 2; i++) {
945 struct kbase_jd_atom *dep_atom = katom->dep[i].atom;
946
947 if (dep_atom) {
948 int dep_js = kbase_js_get_slot(kbdev, dep_atom);
949 int dep_prio = dep_atom->sched_priority;
950
951 /* Dependent atom must already have been submitted */
952 if (!(dep_atom->atom_flags &
953 KBASE_KATOM_FLAG_JSCTX_IN_TREE)) {
954 ret = false;
955 break;
956 }
957
958 /* Dependencies with different priorities can't
959 be represented in the ringbuffer */
960 if (prio != dep_prio) {
961 ret = false;
962 break;
963 }
964
965 if (js == dep_js) {
966 /* Only one same-slot dependency can be
967 * represented in the ringbuffer */
968 if (has_dep) {
969 ret = false;
970 break;
971 }
972 /* Each dependee atom can only have one
973 * same-slot dependency */
974 if (dep_atom->post_dep) {
975 ret = false;
976 break;
977 }
978 has_dep = true;
979 } else {
980 /* Only one cross-slot dependency can be
981 * represented in the ringbuffer */
982 if (has_x_dep) {
983 ret = false;
984 break;
985 }
986 /* Each dependee atom can only have one
987 * cross-slot dependency */
988 if (dep_atom->x_post_dep) {
989 ret = false;
990 break;
991 }
992 /* The dependee atom can not already be in the
993 * HW access ringbuffer */
994 if (dep_atom->gpu_rb_state !=
995 KBASE_ATOM_GPU_RB_NOT_IN_SLOT_RB) {
996 ret = false;
997 break;
998 }
999 /* The dependee atom can not already have
1000 * completed */
1001 if (dep_atom->status !=
1002 KBASE_JD_ATOM_STATE_IN_JS) {
1003 ret = false;
1004 break;
1005 }
1006 /* Cross-slot dependencies must not violate
1007 * PRLAM-8987 affinity restrictions */
1008 if (kbase_hw_has_issue(kbdev,
1009 BASE_HW_ISSUE_8987) &&
1010 (js == 2 || dep_js == 2)) {
1011 ret = false;
1012 break;
1013 }
1014 has_x_dep = true;
1015 }
1016
1017 /* Dependency can be represented in ringbuffers */
1018 }
1019 }
1020
1021 /* If dependencies can be represented by ringbuffer then clear them from
1022 * atom structure */
1023 if (ret) {
1024 for (i = 0; i < 2; i++) {
1025 struct kbase_jd_atom *dep_atom = katom->dep[i].atom;
1026
1027 if (dep_atom) {
1028 int dep_js = kbase_js_get_slot(kbdev, dep_atom);
1029
1030 if ((js != dep_js) &&
1031 (dep_atom->status !=
1032 KBASE_JD_ATOM_STATE_COMPLETED)
1033 && (dep_atom->status !=
1034 KBASE_JD_ATOM_STATE_HW_COMPLETED)
1035 && (dep_atom->status !=
1036 KBASE_JD_ATOM_STATE_UNUSED)) {
1037
1038 katom->atom_flags |=
1039 KBASE_KATOM_FLAG_X_DEP_BLOCKED;
1040 katom->x_pre_dep = dep_atom;
1041 dep_atom->x_post_dep = katom;
1042 if (kbase_jd_katom_dep_type(
1043 &katom->dep[i]) ==
1044 BASE_JD_DEP_TYPE_DATA)
1045 katom->atom_flags |=
1046 KBASE_KATOM_FLAG_FAIL_BLOCKER;
1047 }
1048 if ((kbase_jd_katom_dep_type(&katom->dep[i])
1049 == BASE_JD_DEP_TYPE_DATA) &&
1050 (js == dep_js)) {
1051 katom->pre_dep = dep_atom;
1052 dep_atom->post_dep = katom;
1053 }
1054
1055 list_del(&katom->dep_item[i]);
1056 kbase_jd_katom_dep_clear(&katom->dep[i]);
1057 }
1058 }
1059 }
1060
1061 return ret;
1062 }
1063
kbasep_js_add_job(struct kbase_context *kctx, struct kbase_jd_atom *atom)1064 bool kbasep_js_add_job(struct kbase_context *kctx,
1065 struct kbase_jd_atom *atom)
1066 {
1067 unsigned long flags;
1068 struct kbasep_js_kctx_info *js_kctx_info;
1069 struct kbase_device *kbdev;
1070 struct kbasep_js_device_data *js_devdata;
1071
1072 bool enqueue_required = false;
1073 bool timer_sync = false;
1074
1075 KBASE_DEBUG_ASSERT(kctx != NULL);
1076 KBASE_DEBUG_ASSERT(atom != NULL);
1077 lockdep_assert_held(&kctx->jctx.lock);
1078
1079 kbdev = kctx->kbdev;
1080 js_devdata = &kbdev->js_data;
1081 js_kctx_info = &kctx->jctx.sched_info;
1082
1083 mutex_lock(&js_devdata->queue_mutex);
1084 mutex_lock(&js_kctx_info->ctx.jsctx_mutex);
1085
1086 /*
1087 * Begin Runpool transaction
1088 */
1089 mutex_lock(&js_devdata->runpool_mutex);
1090
1091 /* Refcount ctx.nr_jobs */
1092 KBASE_DEBUG_ASSERT(js_kctx_info->ctx.nr_jobs < U32_MAX);
1093 ++(js_kctx_info->ctx.nr_jobs);
1094
1095 /* Setup any scheduling information */
1096 kbasep_js_clear_job_retry_submit(atom);
1097
1098 /* Lock for state available during IRQ */
1099 spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
1100
1101 if (!kbase_js_dep_validate(kctx, atom)) {
1102 /* Dependencies could not be represented */
1103 --(js_kctx_info->ctx.nr_jobs);
1104
1105 /* Setting atom status back to queued as it still has unresolved
1106 * dependencies */
1107 atom->status = KBASE_JD_ATOM_STATE_QUEUED;
1108
1109 spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
1110 mutex_unlock(&js_devdata->runpool_mutex);
1111
1112 goto out_unlock;
1113 }
1114
1115 KBASE_TLSTREAM_TL_ATTRIB_ATOM_STATE(atom, TL_ATOM_STATE_READY);
1116 KBASE_TIMELINE_ATOM_READY(kctx, kbase_jd_atom_id(kctx, atom));
1117
1118 enqueue_required = kbase_js_dep_resolved_submit(kctx, atom);
1119
1120 KBASE_TRACE_ADD_REFCOUNT(kbdev, JS_ADD_JOB, kctx, atom, atom->jc,
1121 kbasep_js_trace_get_refcnt(kbdev, kctx));
1122
1123 /* Context Attribute Refcounting */
1124 kbasep_js_ctx_attr_ctx_retain_atom(kbdev, kctx, atom);
1125
1126 if (enqueue_required) {
1127 if (kbase_js_ctx_pullable(kctx, atom->slot_nr, false))
1128 timer_sync = kbase_js_ctx_list_add_pullable_nolock(
1129 kbdev, kctx, atom->slot_nr);
1130 else
1131 timer_sync = kbase_js_ctx_list_add_unpullable_nolock(
1132 kbdev, kctx, atom->slot_nr);
1133 }
1134 /* If this context is active and the atom is the first on its slot,
1135 * kick the job manager to attempt to fast-start the atom */
1136 if (enqueue_required && kctx == kbdev->hwaccess.active_kctx)
1137 kbase_jm_try_kick(kbdev, 1 << atom->slot_nr);
1138
1139 spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
1140 if (timer_sync)
1141 kbase_backend_ctx_count_changed(kbdev);
1142 mutex_unlock(&js_devdata->runpool_mutex);
1143 /* End runpool transaction */
1144
1145 if (!kbase_ctx_flag(kctx, KCTX_SCHEDULED)) {
1146 if (kbase_ctx_flag(kctx, KCTX_DYING)) {
1147 /* A job got added while/after kbase_job_zap_context()
1148 * was called on a non-scheduled context (e.g. KDS
1149 * dependency resolved). Kill that job by killing the
1150 * context. */
1151 kbasep_js_runpool_requeue_or_kill_ctx(kbdev, kctx,
1152 false);
1153 } else if (js_kctx_info->ctx.nr_jobs == 1) {
1154 /* Handle Refcount going from 0 to 1: schedule the
1155 * context on the Queue */
1156 KBASE_DEBUG_ASSERT(!kbase_ctx_flag(kctx, KCTX_SCHEDULED));
1157 dev_dbg(kbdev->dev, "JS: Enqueue Context %p", kctx);
1158
1159 /* Queue was updated - caller must try to
1160 * schedule the head context */
1161 WARN_ON(!enqueue_required);
1162 }
1163 }
1164 out_unlock:
1165 mutex_unlock(&js_kctx_info->ctx.jsctx_mutex);
1166
1167 mutex_unlock(&js_devdata->queue_mutex);
1168
1169 return enqueue_required;
1170 }
1171
kbasep_js_remove_job(struct kbase_device *kbdev, struct kbase_context *kctx, struct kbase_jd_atom *atom)1172 void kbasep_js_remove_job(struct kbase_device *kbdev,
1173 struct kbase_context *kctx, struct kbase_jd_atom *atom)
1174 {
1175 struct kbasep_js_kctx_info *js_kctx_info;
1176 struct kbasep_js_device_data *js_devdata;
1177
1178 KBASE_DEBUG_ASSERT(kbdev != NULL);
1179 KBASE_DEBUG_ASSERT(kctx != NULL);
1180 KBASE_DEBUG_ASSERT(atom != NULL);
1181
1182 js_devdata = &kbdev->js_data;
1183 js_kctx_info = &kctx->jctx.sched_info;
1184
1185 KBASE_TRACE_ADD_REFCOUNT(kbdev, JS_REMOVE_JOB, kctx, atom, atom->jc,
1186 kbasep_js_trace_get_refcnt(kbdev, kctx));
1187
1188 /* De-refcount ctx.nr_jobs */
1189 KBASE_DEBUG_ASSERT(js_kctx_info->ctx.nr_jobs > 0);
1190 --(js_kctx_info->ctx.nr_jobs);
1191 }
1192
kbasep_js_remove_cancelled_job(struct kbase_device *kbdev, struct kbase_context *kctx, struct kbase_jd_atom *katom)1193 bool kbasep_js_remove_cancelled_job(struct kbase_device *kbdev,
1194 struct kbase_context *kctx, struct kbase_jd_atom *katom)
1195 {
1196 unsigned long flags;
1197 struct kbasep_js_atom_retained_state katom_retained_state;
1198 struct kbasep_js_device_data *js_devdata;
1199 bool attr_state_changed;
1200
1201 KBASE_DEBUG_ASSERT(kbdev != NULL);
1202 KBASE_DEBUG_ASSERT(kctx != NULL);
1203 KBASE_DEBUG_ASSERT(katom != NULL);
1204
1205 js_devdata = &kbdev->js_data;
1206
1207 kbasep_js_atom_retained_state_copy(&katom_retained_state, katom);
1208 kbasep_js_remove_job(kbdev, kctx, katom);
1209
1210 spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
1211
1212 /* The atom has 'finished' (will not be re-run), so no need to call
1213 * kbasep_js_has_atom_finished().
1214 *
1215 * This is because it returns false for soft-stopped atoms, but we
1216 * want to override that, because we're cancelling an atom regardless of
1217 * whether it was soft-stopped or not */
1218 attr_state_changed = kbasep_js_ctx_attr_ctx_release_atom(kbdev, kctx,
1219 &katom_retained_state);
1220 spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
1221
1222 return attr_state_changed;
1223 }
1224
kbasep_js_runpool_retain_ctx(struct kbase_device *kbdev, struct kbase_context *kctx)1225 bool kbasep_js_runpool_retain_ctx(struct kbase_device *kbdev,
1226 struct kbase_context *kctx)
1227 {
1228 unsigned long flags;
1229 struct kbasep_js_device_data *js_devdata;
1230 bool result;
1231
1232 KBASE_DEBUG_ASSERT(kbdev != NULL);
1233 js_devdata = &kbdev->js_data;
1234
1235 mutex_lock(&kbdev->mmu_hw_mutex);
1236 spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
1237 result = kbasep_js_runpool_retain_ctx_nolock(kbdev, kctx);
1238 spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
1239 mutex_unlock(&kbdev->mmu_hw_mutex);
1240
1241 return result;
1242 }
1243
kbasep_js_runpool_lookup_ctx(struct kbase_device *kbdev, int as_nr)1244 struct kbase_context *kbasep_js_runpool_lookup_ctx(struct kbase_device *kbdev,
1245 int as_nr)
1246 {
1247 int ret = 0;
1248 unsigned long flags;
1249 struct kbasep_js_device_data *js_devdata;
1250 struct kbase_context *found_kctx = NULL;
1251
1252 KBASE_DEBUG_ASSERT(kbdev != NULL);
1253 KBASE_DEBUG_ASSERT(0 <= as_nr && as_nr < BASE_MAX_NR_AS);
1254 js_devdata = &kbdev->js_data;
1255
1256 spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
1257
1258 found_kctx = kbdev->as_to_kctx[as_nr];
1259
1260 if (found_kctx != NULL) {
1261 ret = kbase_ctx_sched_retain_ctx_refcount(found_kctx);
1262 if (ret != 0) {
1263 E("fail to retain ctx_refcount, ret : %d.", ret);
1264 found_kctx = NULL;
1265 }
1266 }
1267
1268 spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
1269
1270 return found_kctx;
1271 }
1272
1273 /**
1274 * kbasep_js_release_result - Try running more jobs after releasing a context
1275 * and/or atom
1276 *
1277 * @kbdev: The kbase_device to operate on
1278 * @kctx: The kbase_context to operate on
1279 * @katom_retained_state: Retained state from the atom
1280 * @runpool_ctx_attr_change: True if the runpool context attributes have changed
1281 *
1282 * This collates a set of actions that must happen whilst hwaccess_lock is held.
1283 *
1284 * This includes running more jobs when:
1285 * - The previously released kctx caused a ctx attribute change,
1286 * - The released atom caused a ctx attribute change,
1287 * - Slots were previously blocked due to affinity restrictions,
1288 * - Submission during IRQ handling failed.
1289 *
1290 * Return: %KBASEP_JS_RELEASE_RESULT_SCHED_ALL if context attributes were
1291 * changed. The caller should try scheduling all contexts
1292 */
kbasep_js_run_jobs_after_ctx_and_atom_release( struct kbase_device *kbdev, struct kbase_context *kctx, struct kbasep_js_atom_retained_state *katom_retained_state, bool runpool_ctx_attr_change)1293 static kbasep_js_release_result kbasep_js_run_jobs_after_ctx_and_atom_release(
1294 struct kbase_device *kbdev,
1295 struct kbase_context *kctx,
1296 struct kbasep_js_atom_retained_state *katom_retained_state,
1297 bool runpool_ctx_attr_change)
1298 {
1299 struct kbasep_js_device_data *js_devdata;
1300 kbasep_js_release_result result = 0;
1301
1302 KBASE_DEBUG_ASSERT(kbdev != NULL);
1303 KBASE_DEBUG_ASSERT(kctx != NULL);
1304 KBASE_DEBUG_ASSERT(katom_retained_state != NULL);
1305 js_devdata = &kbdev->js_data;
1306
1307 lockdep_assert_held(&kctx->jctx.sched_info.ctx.jsctx_mutex);
1308 lockdep_assert_held(&js_devdata->runpool_mutex);
1309 lockdep_assert_held(&kbdev->hwaccess_lock);
1310
1311 if (js_devdata->nr_user_contexts_running != 0) {
1312 bool retry_submit = false;
1313 int retry_jobslot = 0;
1314
1315 if (katom_retained_state)
1316 retry_submit = kbasep_js_get_atom_retry_submit_slot(
1317 katom_retained_state, &retry_jobslot);
1318
1319 if (runpool_ctx_attr_change || retry_submit) {
1320 /* A change in runpool ctx attributes might mean we can
1321 * run more jobs than before */
1322 result = KBASEP_JS_RELEASE_RESULT_SCHED_ALL;
1323
1324 KBASE_TRACE_ADD_SLOT(kbdev, JD_DONE_TRY_RUN_NEXT_JOB,
1325 kctx, NULL, 0u, retry_jobslot);
1326 }
1327 }
1328 return result;
1329 }
1330
1331 /*
1332 * Internal function to release the reference on a ctx and an atom's "retained
1333 * state", only taking the runpool and as transaction mutexes
1334 *
1335 * This also starts more jobs running in the case of an ctx-attribute state
1336 * change
1337 *
1338 * This does none of the followup actions for scheduling:
1339 * - It does not schedule in a new context
1340 * - It does not requeue or handle dying contexts
1341 *
1342 * For those tasks, just call kbasep_js_runpool_release_ctx() instead
1343 *
1344 * Requires:
1345 * - Context is scheduled in, and kctx->as_nr matches kctx_as_nr
1346 * - Context has a non-zero refcount
1347 * - Caller holds js_kctx_info->ctx.jsctx_mutex
1348 * - Caller holds js_devdata->runpool_mutex
1349 */
kbasep_js_runpool_release_ctx_internal( struct kbase_device *kbdev, struct kbase_context *kctx, struct kbasep_js_atom_retained_state *katom_retained_state)1350 static kbasep_js_release_result kbasep_js_runpool_release_ctx_internal(
1351 struct kbase_device *kbdev,
1352 struct kbase_context *kctx,
1353 struct kbasep_js_atom_retained_state *katom_retained_state)
1354 {
1355 unsigned long flags;
1356 struct kbasep_js_device_data *js_devdata;
1357 struct kbasep_js_kctx_info *js_kctx_info;
1358
1359 kbasep_js_release_result release_result = 0u;
1360 bool runpool_ctx_attr_change = false;
1361 int kctx_as_nr;
1362 struct kbase_as *current_as;
1363 int new_ref_count;
1364
1365 KBASE_DEBUG_ASSERT(kbdev != NULL);
1366 KBASE_DEBUG_ASSERT(kctx != NULL);
1367 js_kctx_info = &kctx->jctx.sched_info;
1368 js_devdata = &kbdev->js_data;
1369
1370 /* Ensure context really is scheduled in */
1371 KBASE_DEBUG_ASSERT(kbase_ctx_flag(kctx, KCTX_SCHEDULED));
1372
1373 kctx_as_nr = kctx->as_nr;
1374 KBASE_DEBUG_ASSERT(kctx_as_nr != KBASEP_AS_NR_INVALID);
1375 KBASE_DEBUG_ASSERT(atomic_read(&kctx->refcount) > 0);
1376
1377 /*
1378 * Transaction begins on AS and runpool_irq
1379 *
1380 * Assert about out calling contract
1381 */
1382 current_as = &kbdev->as[kctx_as_nr];
1383 mutex_lock(&kbdev->pm.lock);
1384 spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
1385
1386 KBASE_DEBUG_ASSERT(kctx_as_nr == kctx->as_nr);
1387 KBASE_DEBUG_ASSERT(atomic_read(&kctx->refcount) > 0);
1388
1389 /* Update refcount */
1390 kbase_ctx_sched_release_ctx(kctx);
1391 new_ref_count = atomic_read(&kctx->refcount);
1392
1393 /* Release the atom if it finished (i.e. wasn't soft-stopped) */
1394 if (kbasep_js_has_atom_finished(katom_retained_state))
1395 runpool_ctx_attr_change |= kbasep_js_ctx_attr_ctx_release_atom(
1396 kbdev, kctx, katom_retained_state);
1397
1398 KBASE_TRACE_ADD_REFCOUNT(kbdev, JS_RELEASE_CTX, kctx, NULL, 0u,
1399 new_ref_count);
1400
1401 if (new_ref_count == 2 && kbase_ctx_flag(kctx, KCTX_PRIVILEGED) &&
1402 !kbase_pm_is_suspending(kbdev)) {
1403 /* Context is kept scheduled into an address space even when
1404 * there are no jobs, in this case we have to handle the
1405 * situation where all jobs have been evicted from the GPU and
1406 * submission is disabled.
1407 *
1408 * At this point we re-enable submission to allow further jobs
1409 * to be executed
1410 */
1411 kbasep_js_set_submit_allowed(js_devdata, kctx);
1412 }
1413
1414 /* Make a set of checks to see if the context should be scheduled out.
1415 * Note that there'll always be at least 1 reference to the context
1416 * which was previously acquired by kbasep_js_schedule_ctx(). */
1417 if (new_ref_count == 1 &&
1418 (!kbasep_js_is_submit_allowed(js_devdata, kctx) ||
1419 kbdev->pm.suspending)) {
1420 int num_slots = kbdev->gpu_props.num_job_slots;
1421 int slot;
1422
1423 /* Last reference, and we've been told to remove this context
1424 * from the Run Pool */
1425 dev_dbg(kbdev->dev, "JS: RunPool Remove Context %p because refcount=%d, jobs=%d, allowed=%d",
1426 kctx, new_ref_count, js_kctx_info->ctx.nr_jobs,
1427 kbasep_js_is_submit_allowed(js_devdata, kctx));
1428
1429 #if defined(CONFIG_MALI_GATOR_SUPPORT)
1430 kbase_trace_mali_mmu_as_released(kctx->as_nr);
1431 #endif
1432 KBASE_TLSTREAM_TL_NRET_AS_CTX(&kbdev->as[kctx->as_nr], kctx);
1433
1434 kbase_backend_release_ctx_irq(kbdev, kctx);
1435
1436 if (kbdev->hwaccess.active_kctx == kctx)
1437 kbdev->hwaccess.active_kctx = NULL;
1438
1439 /* Ctx Attribute handling
1440 *
1441 * Releasing atoms attributes must either happen before this, or
1442 * after the KCTX_SHEDULED flag is changed, otherwise we
1443 * double-decount the attributes
1444 */
1445 runpool_ctx_attr_change |=
1446 kbasep_js_ctx_attr_runpool_release_ctx(kbdev, kctx);
1447
1448 /* Releasing the context and katom retained state can allow
1449 * more jobs to run */
1450 release_result |=
1451 kbasep_js_run_jobs_after_ctx_and_atom_release(kbdev,
1452 kctx, katom_retained_state,
1453 runpool_ctx_attr_change);
1454
1455 /*
1456 * Transaction ends on AS and runpool_irq:
1457 *
1458 * By this point, the AS-related data is now clear and ready
1459 * for re-use.
1460 *
1461 * Since releases only occur once for each previous successful
1462 * retain, and no more retains are allowed on this context, no
1463 * other thread will be operating in this
1464 * code whilst we are
1465 */
1466
1467 /* Recalculate pullable status for all slots */
1468 for (slot = 0; slot < num_slots; slot++) {
1469 if (kbase_js_ctx_pullable(kctx, slot, false))
1470 kbase_js_ctx_list_add_pullable_nolock(kbdev,
1471 kctx, slot);
1472 }
1473
1474 spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
1475
1476 kbase_backend_release_ctx_noirq(kbdev, kctx);
1477
1478 mutex_unlock(&kbdev->pm.lock);
1479
1480 /* Note: Don't reuse kctx_as_nr now */
1481
1482 /* Synchronize with any timers */
1483 kbase_backend_ctx_count_changed(kbdev);
1484
1485 /* update book-keeping info */
1486 kbase_ctx_flag_clear(kctx, KCTX_SCHEDULED);
1487 /* Signal any waiter that the context is not scheduled, so is
1488 * safe for termination - once the jsctx_mutex is also dropped,
1489 * and jobs have finished. */
1490 wake_up(&js_kctx_info->ctx.is_scheduled_wait);
1491
1492 /* Queue an action to occur after we've dropped the lock */
1493 release_result |= KBASEP_JS_RELEASE_RESULT_WAS_DESCHEDULED |
1494 KBASEP_JS_RELEASE_RESULT_SCHED_ALL;
1495 } else {
1496 kbasep_js_run_jobs_after_ctx_and_atom_release(kbdev, kctx,
1497 katom_retained_state, runpool_ctx_attr_change);
1498
1499 spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
1500 mutex_unlock(&kbdev->pm.lock);
1501 }
1502
1503 return release_result;
1504 }
1505
kbasep_js_runpool_release_ctx_nolock(struct kbase_device *kbdev, struct kbase_context *kctx)1506 void kbasep_js_runpool_release_ctx_nolock(struct kbase_device *kbdev,
1507 struct kbase_context *kctx)
1508 {
1509 struct kbasep_js_atom_retained_state katom_retained_state;
1510
1511 /* Setup a dummy katom_retained_state */
1512 kbasep_js_atom_retained_state_init_invalid(&katom_retained_state);
1513
1514 kbasep_js_runpool_release_ctx_internal(kbdev, kctx,
1515 &katom_retained_state);
1516 }
1517
kbasep_js_runpool_requeue_or_kill_ctx(struct kbase_device *kbdev, struct kbase_context *kctx, bool has_pm_ref)1518 void kbasep_js_runpool_requeue_or_kill_ctx(struct kbase_device *kbdev,
1519 struct kbase_context *kctx, bool has_pm_ref)
1520 {
1521 struct kbasep_js_device_data *js_devdata;
1522
1523 KBASE_DEBUG_ASSERT(kbdev != NULL);
1524 KBASE_DEBUG_ASSERT(kctx != NULL);
1525 js_devdata = &kbdev->js_data;
1526
1527 /* This is called if and only if you've you've detached the context from
1528 * the Runpool Queue, and not added it back to the Runpool
1529 */
1530 KBASE_DEBUG_ASSERT(!kbase_ctx_flag(kctx, KCTX_SCHEDULED));
1531
1532 if (kbase_ctx_flag(kctx, KCTX_DYING)) {
1533 /* Dying: don't requeue, but kill all jobs on the context. This
1534 * happens asynchronously */
1535 dev_dbg(kbdev->dev,
1536 "JS: ** Killing Context %p on RunPool Remove **", kctx);
1537 kbase_js_foreach_ctx_job(kctx, &kbase_jd_cancel);
1538 }
1539 }
1540
kbasep_js_runpool_release_ctx_and_katom_retained_state( struct kbase_device *kbdev, struct kbase_context *kctx, struct kbasep_js_atom_retained_state *katom_retained_state)1541 void kbasep_js_runpool_release_ctx_and_katom_retained_state(
1542 struct kbase_device *kbdev, struct kbase_context *kctx,
1543 struct kbasep_js_atom_retained_state *katom_retained_state)
1544 {
1545 struct kbasep_js_device_data *js_devdata;
1546 struct kbasep_js_kctx_info *js_kctx_info;
1547 kbasep_js_release_result release_result;
1548
1549 KBASE_DEBUG_ASSERT(kbdev != NULL);
1550 KBASE_DEBUG_ASSERT(kctx != NULL);
1551 js_kctx_info = &kctx->jctx.sched_info;
1552 js_devdata = &kbdev->js_data;
1553
1554 mutex_lock(&js_devdata->queue_mutex);
1555 mutex_lock(&js_kctx_info->ctx.jsctx_mutex);
1556 mutex_lock(&js_devdata->runpool_mutex);
1557
1558 release_result = kbasep_js_runpool_release_ctx_internal(kbdev, kctx,
1559 katom_retained_state);
1560
1561 /* Drop the runpool mutex to allow requeing kctx */
1562 mutex_unlock(&js_devdata->runpool_mutex);
1563
1564 if ((release_result & KBASEP_JS_RELEASE_RESULT_WAS_DESCHEDULED) != 0u)
1565 kbasep_js_runpool_requeue_or_kill_ctx(kbdev, kctx, true);
1566
1567 /* Drop the jsctx_mutex to allow scheduling in a new context */
1568
1569 mutex_unlock(&js_kctx_info->ctx.jsctx_mutex);
1570 mutex_unlock(&js_devdata->queue_mutex);
1571
1572 if (release_result & KBASEP_JS_RELEASE_RESULT_SCHED_ALL)
1573 kbase_js_sched_all(kbdev);
1574 }
1575
kbasep_js_runpool_release_ctx(struct kbase_device *kbdev, struct kbase_context *kctx)1576 void kbasep_js_runpool_release_ctx(struct kbase_device *kbdev,
1577 struct kbase_context *kctx)
1578 {
1579 struct kbasep_js_atom_retained_state katom_retained_state;
1580
1581 kbasep_js_atom_retained_state_init_invalid(&katom_retained_state);
1582
1583 kbasep_js_runpool_release_ctx_and_katom_retained_state(kbdev, kctx,
1584 &katom_retained_state);
1585 }
1586
1587 /* Variant of kbasep_js_runpool_release_ctx() that doesn't call into
1588 * kbase_js_sched_all() */
kbasep_js_runpool_release_ctx_no_schedule( struct kbase_device *kbdev, struct kbase_context *kctx)1589 static void kbasep_js_runpool_release_ctx_no_schedule(
1590 struct kbase_device *kbdev, struct kbase_context *kctx)
1591 {
1592 struct kbasep_js_device_data *js_devdata;
1593 struct kbasep_js_kctx_info *js_kctx_info;
1594 kbasep_js_release_result release_result;
1595 struct kbasep_js_atom_retained_state katom_retained_state_struct;
1596 struct kbasep_js_atom_retained_state *katom_retained_state =
1597 &katom_retained_state_struct;
1598
1599 KBASE_DEBUG_ASSERT(kbdev != NULL);
1600 KBASE_DEBUG_ASSERT(kctx != NULL);
1601 js_kctx_info = &kctx->jctx.sched_info;
1602 js_devdata = &kbdev->js_data;
1603 kbasep_js_atom_retained_state_init_invalid(katom_retained_state);
1604
1605 mutex_lock(&js_kctx_info->ctx.jsctx_mutex);
1606 mutex_lock(&js_devdata->runpool_mutex);
1607
1608 release_result = kbasep_js_runpool_release_ctx_internal(kbdev, kctx,
1609 katom_retained_state);
1610
1611 /* Drop the runpool mutex to allow requeing kctx */
1612 mutex_unlock(&js_devdata->runpool_mutex);
1613 if ((release_result & KBASEP_JS_RELEASE_RESULT_WAS_DESCHEDULED) != 0u)
1614 kbasep_js_runpool_requeue_or_kill_ctx(kbdev, kctx, true);
1615
1616 /* Drop the jsctx_mutex to allow scheduling in a new context */
1617 mutex_unlock(&js_kctx_info->ctx.jsctx_mutex);
1618
1619 /* NOTE: could return release_result if the caller would like to know
1620 * whether it should schedule a new context, but currently no callers do
1621 */
1622 }
1623
kbase_js_set_timeouts(struct kbase_device *kbdev)1624 void kbase_js_set_timeouts(struct kbase_device *kbdev)
1625 {
1626 lockdep_assert_held(&kbdev->hwaccess_lock);
1627
1628 kbase_backend_timeouts_changed(kbdev);
1629 }
1630
kbasep_js_schedule_ctx(struct kbase_device *kbdev, struct kbase_context *kctx)1631 static bool kbasep_js_schedule_ctx(struct kbase_device *kbdev,
1632 struct kbase_context *kctx)
1633 {
1634 struct kbasep_js_device_data *js_devdata;
1635 struct kbasep_js_kctx_info *js_kctx_info;
1636 struct kbase_as *new_address_space = NULL;
1637 unsigned long flags;
1638 bool kctx_suspended = false;
1639 int as_nr;
1640
1641 js_devdata = &kbdev->js_data;
1642 js_kctx_info = &kctx->jctx.sched_info;
1643
1644 /* Pick available address space for this context */
1645 mutex_lock(&kbdev->mmu_hw_mutex);
1646 spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
1647 as_nr = kbase_ctx_sched_retain_ctx(kctx);
1648 spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
1649 mutex_unlock(&kbdev->mmu_hw_mutex);
1650 if (as_nr == KBASEP_AS_NR_INVALID) {
1651 as_nr = kbase_backend_find_and_release_free_address_space(
1652 kbdev, kctx);
1653 if (as_nr != KBASEP_AS_NR_INVALID) {
1654 /* Attempt to retain the context again, this should
1655 * succeed */
1656 mutex_lock(&kbdev->mmu_hw_mutex);
1657 spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
1658 as_nr = kbase_ctx_sched_retain_ctx(kctx);
1659 spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
1660 mutex_unlock(&kbdev->mmu_hw_mutex);
1661
1662 WARN_ON(as_nr == KBASEP_AS_NR_INVALID);
1663 }
1664 }
1665 if (as_nr == KBASEP_AS_NR_INVALID)
1666 return false; /* No address spaces currently available */
1667
1668 new_address_space = &kbdev->as[as_nr];
1669
1670 /*
1671 * Atomic transaction on the Context and Run Pool begins
1672 */
1673 mutex_lock(&js_kctx_info->ctx.jsctx_mutex);
1674 mutex_lock(&js_devdata->runpool_mutex);
1675 mutex_lock(&kbdev->mmu_hw_mutex);
1676 spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
1677
1678 /* Check to see if context is dying due to kbase_job_zap_context() */
1679 if (kbase_ctx_flag(kctx, KCTX_DYING)) {
1680 /* Roll back the transaction so far and return */
1681 kbase_ctx_sched_release_ctx(kctx);
1682
1683 spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
1684 mutex_unlock(&kbdev->mmu_hw_mutex);
1685 mutex_unlock(&js_devdata->runpool_mutex);
1686 mutex_unlock(&js_kctx_info->ctx.jsctx_mutex);
1687
1688 return false;
1689 }
1690
1691 KBASE_TRACE_ADD_REFCOUNT(kbdev, JS_TRY_SCHEDULE_HEAD_CTX, kctx, NULL,
1692 0u,
1693 kbasep_js_trace_get_refcnt(kbdev, kctx));
1694
1695 kbase_ctx_flag_set(kctx, KCTX_SCHEDULED);
1696
1697 /* Assign context to previously chosen address space */
1698 if (!kbase_backend_use_ctx(kbdev, kctx, as_nr)) {
1699 /* Roll back the transaction so far and return */
1700 kbase_ctx_sched_release_ctx(kctx);
1701 kbase_ctx_flag_clear(kctx, KCTX_SCHEDULED);
1702
1703 spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
1704 mutex_unlock(&kbdev->mmu_hw_mutex);
1705 mutex_unlock(&js_devdata->runpool_mutex);
1706 mutex_unlock(&js_kctx_info->ctx.jsctx_mutex);
1707
1708 return false;
1709 }
1710
1711 kbdev->hwaccess.active_kctx = kctx;
1712
1713 #if defined(CONFIG_MALI_GATOR_SUPPORT)
1714 kbase_trace_mali_mmu_as_in_use(kctx->as_nr);
1715 #endif
1716 KBASE_TLSTREAM_TL_RET_AS_CTX(&kbdev->as[kctx->as_nr], kctx);
1717
1718 /* Cause any future waiter-on-termination to wait until the context is
1719 * descheduled */
1720 wake_up(&js_kctx_info->ctx.is_scheduled_wait);
1721
1722 /* Re-check for suspending: a suspend could've occurred, and all the
1723 * contexts could've been removed from the runpool before we took this
1724 * lock. In this case, we don't want to allow this context to run jobs,
1725 * we just want it out immediately.
1726 *
1727 * The DMB required to read the suspend flag was issued recently as part
1728 * of the hwaccess_lock locking. If a suspend occurs *after* that lock
1729 * was taken (i.e. this condition doesn't execute), then the
1730 * kbasep_js_suspend() code will cleanup this context instead (by virtue
1731 * of it being called strictly after the suspend flag is set, and will
1732 * wait for this lock to drop) */
1733 if (kbase_pm_is_suspending(kbdev)) {
1734 /* Cause it to leave at some later point */
1735 bool retained;
1736
1737 retained = kbasep_js_runpool_retain_ctx_nolock(kbdev, kctx);
1738 KBASE_DEBUG_ASSERT(retained);
1739
1740 kbasep_js_clear_submit_allowed(js_devdata, kctx);
1741 kctx_suspended = true;
1742 }
1743
1744 /* Transaction complete */
1745 spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
1746 mutex_unlock(&kbdev->mmu_hw_mutex);
1747
1748 /* Synchronize with any timers */
1749 kbase_backend_ctx_count_changed(kbdev);
1750
1751 mutex_unlock(&js_devdata->runpool_mutex);
1752 mutex_unlock(&js_kctx_info->ctx.jsctx_mutex);
1753 /* Note: after this point, the context could potentially get scheduled
1754 * out immediately */
1755
1756 if (kctx_suspended) {
1757 /* Finishing forcing out the context due to a suspend. Use a
1758 * variant of kbasep_js_runpool_release_ctx() that doesn't
1759 * schedule a new context, to prevent a risk of recursion back
1760 * into this function */
1761 kbasep_js_runpool_release_ctx_no_schedule(kbdev, kctx);
1762 return false;
1763 }
1764 return true;
1765 }
1766
kbase_js_use_ctx(struct kbase_device *kbdev, struct kbase_context *kctx)1767 static bool kbase_js_use_ctx(struct kbase_device *kbdev,
1768 struct kbase_context *kctx)
1769 {
1770 unsigned long flags;
1771
1772 spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
1773
1774 if (kbase_ctx_flag(kctx, KCTX_SCHEDULED) &&
1775 kbase_backend_use_ctx_sched(kbdev, kctx)) {
1776 /* Context already has ASID - mark as active */
1777 kbdev->hwaccess.active_kctx = kctx;
1778 spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
1779 return true; /* Context already scheduled */
1780 }
1781
1782 spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
1783
1784 return kbasep_js_schedule_ctx(kbdev, kctx);
1785 }
1786
kbasep_js_schedule_privileged_ctx(struct kbase_device *kbdev, struct kbase_context *kctx)1787 void kbasep_js_schedule_privileged_ctx(struct kbase_device *kbdev,
1788 struct kbase_context *kctx)
1789 {
1790 struct kbasep_js_kctx_info *js_kctx_info;
1791 struct kbasep_js_device_data *js_devdata;
1792 bool is_scheduled;
1793
1794 KBASE_DEBUG_ASSERT(kbdev != NULL);
1795 KBASE_DEBUG_ASSERT(kctx != NULL);
1796
1797 js_devdata = &kbdev->js_data;
1798 js_kctx_info = &kctx->jctx.sched_info;
1799
1800 /* This must never be attempted whilst suspending - i.e. it should only
1801 * happen in response to a syscall from a user-space thread */
1802 BUG_ON(kbase_pm_is_suspending(kbdev));
1803
1804 mutex_lock(&js_devdata->queue_mutex);
1805 mutex_lock(&js_kctx_info->ctx.jsctx_mutex);
1806
1807 /* Mark the context as privileged */
1808 kbase_ctx_flag_set(kctx, KCTX_PRIVILEGED);
1809
1810 is_scheduled = kbase_ctx_flag(kctx, KCTX_SCHEDULED);
1811 if (!is_scheduled) {
1812 /* Add the context to the pullable list */
1813 if (kbase_js_ctx_list_add_pullable_head(kbdev, kctx, 0))
1814 kbase_js_sync_timers(kbdev);
1815
1816 /* Fast-starting requires the jsctx_mutex to be dropped,
1817 * because it works on multiple ctxs */
1818 mutex_unlock(&js_kctx_info->ctx.jsctx_mutex);
1819 mutex_unlock(&js_devdata->queue_mutex);
1820
1821 /* Try to schedule the context in */
1822 kbase_js_sched_all(kbdev);
1823
1824 /* Wait for the context to be scheduled in */
1825 wait_event(kctx->jctx.sched_info.ctx.is_scheduled_wait,
1826 kbase_ctx_flag(kctx, KCTX_SCHEDULED));
1827 } else {
1828 /* Already scheduled in - We need to retain it to keep the
1829 * corresponding address space */
1830 kbasep_js_runpool_retain_ctx(kbdev, kctx);
1831 mutex_unlock(&js_kctx_info->ctx.jsctx_mutex);
1832 mutex_unlock(&js_devdata->queue_mutex);
1833 }
1834 }
1835 KBASE_EXPORT_TEST_API(kbasep_js_schedule_privileged_ctx);
1836
kbasep_js_release_privileged_ctx(struct kbase_device *kbdev, struct kbase_context *kctx)1837 void kbasep_js_release_privileged_ctx(struct kbase_device *kbdev,
1838 struct kbase_context *kctx)
1839 {
1840 struct kbasep_js_kctx_info *js_kctx_info;
1841
1842 KBASE_DEBUG_ASSERT(kctx != NULL);
1843 js_kctx_info = &kctx->jctx.sched_info;
1844
1845 /* We don't need to use the address space anymore */
1846 mutex_lock(&js_kctx_info->ctx.jsctx_mutex);
1847 kbase_ctx_flag_clear(kctx, KCTX_PRIVILEGED);
1848 mutex_unlock(&js_kctx_info->ctx.jsctx_mutex);
1849
1850 /* Release the context - it will be scheduled out */
1851 kbasep_js_runpool_release_ctx(kbdev, kctx);
1852
1853 kbase_js_sched_all(kbdev);
1854 }
1855 KBASE_EXPORT_TEST_API(kbasep_js_release_privileged_ctx);
1856
kbasep_js_suspend(struct kbase_device *kbdev)1857 void kbasep_js_suspend(struct kbase_device *kbdev)
1858 {
1859 unsigned long flags;
1860 struct kbasep_js_device_data *js_devdata;
1861 int i;
1862 u16 retained = 0u;
1863 int nr_privileged_ctx = 0;
1864
1865 KBASE_DEBUG_ASSERT(kbdev);
1866 KBASE_DEBUG_ASSERT(kbase_pm_is_suspending(kbdev));
1867 js_devdata = &kbdev->js_data;
1868
1869 spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
1870
1871 /* Prevent all contexts from submitting */
1872 js_devdata->runpool_irq.submit_allowed = 0;
1873
1874 /* Retain each of the contexts, so we can cause it to leave even if it
1875 * had no refcount to begin with */
1876 for (i = BASE_MAX_NR_AS - 1; i >= 0; --i) {
1877 struct kbase_context *kctx = kbdev->as_to_kctx[i];
1878
1879 retained = retained << 1;
1880
1881 if (kctx) {
1882 kbase_ctx_sched_retain_ctx_refcount(kctx);
1883 retained |= 1u;
1884 /* We can only cope with up to 1 privileged context -
1885 * the instrumented context. It'll be suspended by
1886 * disabling instrumentation */
1887 if (kbase_ctx_flag(kctx, KCTX_PRIVILEGED)) {
1888 ++nr_privileged_ctx;
1889 WARN_ON(nr_privileged_ctx != 1);
1890 }
1891 }
1892 }
1893 CSTD_UNUSED(nr_privileged_ctx);
1894
1895 spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
1896
1897 /* De-ref the previous retain to ensure each context gets pulled out
1898 * sometime later. */
1899 for (i = 0;
1900 i < BASE_MAX_NR_AS;
1901 ++i, retained = retained >> 1) {
1902 struct kbase_context *kctx = kbdev->as_to_kctx[i];
1903
1904 if (retained & 1u)
1905 kbasep_js_runpool_release_ctx(kbdev, kctx);
1906 }
1907
1908 /* Caller must wait for all Power Manager active references to be
1909 * dropped */
1910 }
1911
kbasep_js_resume(struct kbase_device *kbdev)1912 void kbasep_js_resume(struct kbase_device *kbdev)
1913 {
1914 struct kbasep_js_device_data *js_devdata;
1915 int js;
1916
1917 KBASE_DEBUG_ASSERT(kbdev);
1918 js_devdata = &kbdev->js_data;
1919 KBASE_DEBUG_ASSERT(!kbase_pm_is_suspending(kbdev));
1920
1921 mutex_lock(&js_devdata->queue_mutex);
1922 for (js = 0; js < kbdev->gpu_props.num_job_slots; js++) {
1923 struct kbase_context *kctx, *n;
1924
1925 list_for_each_entry_safe(kctx, n,
1926 &kbdev->js_data.ctx_list_unpullable[js],
1927 jctx.sched_info.ctx.ctx_list_entry[js]) {
1928 struct kbasep_js_kctx_info *js_kctx_info;
1929 unsigned long flags;
1930 bool timer_sync = false;
1931
1932 js_kctx_info = &kctx->jctx.sched_info;
1933
1934 mutex_lock(&js_kctx_info->ctx.jsctx_mutex);
1935 mutex_lock(&js_devdata->runpool_mutex);
1936 spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
1937
1938 if (!kbase_ctx_flag(kctx, KCTX_SCHEDULED) &&
1939 kbase_js_ctx_pullable(kctx, js, false))
1940 timer_sync =
1941 kbase_js_ctx_list_add_pullable_nolock(
1942 kbdev, kctx, js);
1943 spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
1944 if (timer_sync)
1945 kbase_backend_ctx_count_changed(kbdev);
1946 mutex_unlock(&js_devdata->runpool_mutex);
1947 mutex_unlock(&js_kctx_info->ctx.jsctx_mutex);
1948 }
1949 }
1950 mutex_unlock(&js_devdata->queue_mutex);
1951
1952 /* Restart atom processing */
1953 kbase_js_sched_all(kbdev);
1954
1955 /* JS Resume complete */
1956 }
1957
kbase_js_is_atom_valid(struct kbase_device *kbdev, struct kbase_jd_atom *katom)1958 bool kbase_js_is_atom_valid(struct kbase_device *kbdev,
1959 struct kbase_jd_atom *katom)
1960 {
1961 if ((katom->core_req & BASE_JD_REQ_FS) &&
1962 (katom->core_req & (BASE_JD_REQ_CS | BASE_JD_REQ_ONLY_COMPUTE |
1963 BASE_JD_REQ_T)))
1964 return false;
1965
1966 if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_8987) &&
1967 (katom->core_req & BASE_JD_REQ_ONLY_COMPUTE) &&
1968 (katom->core_req & (BASE_JD_REQ_CS | BASE_JD_REQ_T)))
1969 return false;
1970
1971 return true;
1972 }
1973
kbase_js_get_slot(struct kbase_device *kbdev, struct kbase_jd_atom *katom)1974 static int kbase_js_get_slot(struct kbase_device *kbdev,
1975 struct kbase_jd_atom *katom)
1976 {
1977 if (katom->core_req & BASE_JD_REQ_FS)
1978 return 0;
1979
1980 if (katom->core_req & BASE_JD_REQ_ONLY_COMPUTE) {
1981 if (katom->device_nr == 1 &&
1982 kbdev->gpu_props.num_core_groups == 2)
1983 return 2;
1984 if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_8987))
1985 return 2;
1986 }
1987
1988 return 1;
1989 }
1990
kbase_js_dep_resolved_submit(struct kbase_context *kctx, struct kbase_jd_atom *katom)1991 bool kbase_js_dep_resolved_submit(struct kbase_context *kctx,
1992 struct kbase_jd_atom *katom)
1993 {
1994 bool enqueue_required;
1995
1996 katom->slot_nr = kbase_js_get_slot(kctx->kbdev, katom);
1997
1998 lockdep_assert_held(&kctx->kbdev->hwaccess_lock);
1999 lockdep_assert_held(&kctx->jctx.lock);
2000
2001 /* If slot will transition from unpullable to pullable then add to
2002 * pullable list */
2003 if (jsctx_rb_none_to_pull(kctx, katom->slot_nr)) {
2004 enqueue_required = true;
2005 } else {
2006 enqueue_required = false;
2007 }
2008 if ((katom->atom_flags & KBASE_KATOM_FLAG_X_DEP_BLOCKED) ||
2009 (katom->pre_dep && (katom->pre_dep->atom_flags &
2010 KBASE_KATOM_FLAG_JSCTX_IN_X_DEP_LIST))) {
2011 int prio = katom->sched_priority;
2012 int js = katom->slot_nr;
2013 struct jsctx_queue *queue = &kctx->jsctx_queue[prio][js];
2014
2015 list_add_tail(&katom->queue, &queue->x_dep_head);
2016 katom->atom_flags |= KBASE_KATOM_FLAG_JSCTX_IN_X_DEP_LIST;
2017 enqueue_required = false;
2018 } else {
2019 /* Check if there are lower priority jobs to soft stop */
2020 kbase_job_slot_ctx_priority_check_locked(kctx, katom);
2021
2022 /* Add atom to ring buffer. */
2023 jsctx_tree_add(kctx, katom);
2024 katom->atom_flags |= KBASE_KATOM_FLAG_JSCTX_IN_TREE;
2025 }
2026
2027 return enqueue_required;
2028 }
2029
2030 /**
2031 * kbase_js_move_to_tree - Move atom (and any dependent atoms) to the
2032 * runnable_tree, ready for execution
2033 * @katom: Atom to submit
2034 *
2035 * It is assumed that @katom does not have KBASE_KATOM_FLAG_X_DEP_BLOCKED set,
2036 * but is still present in the x_dep list. If @katom has a same-slot dependent
2037 * atom then that atom (and any dependents) will also be moved.
2038 */
kbase_js_move_to_tree(struct kbase_jd_atom *katom)2039 static void kbase_js_move_to_tree(struct kbase_jd_atom *katom)
2040 {
2041 lockdep_assert_held(&katom->kctx->kbdev->hwaccess_lock);
2042
2043 while (katom) {
2044 WARN_ON(!(katom->atom_flags &
2045 KBASE_KATOM_FLAG_JSCTX_IN_X_DEP_LIST));
2046
2047 if (!(katom->atom_flags & KBASE_KATOM_FLAG_X_DEP_BLOCKED)) {
2048 list_del(&katom->queue);
2049 katom->atom_flags &=
2050 ~KBASE_KATOM_FLAG_JSCTX_IN_X_DEP_LIST;
2051 jsctx_tree_add(katom->kctx, katom);
2052 katom->atom_flags |= KBASE_KATOM_FLAG_JSCTX_IN_TREE;
2053 } else {
2054 break;
2055 }
2056
2057 katom = katom->post_dep;
2058 }
2059 }
2060
2061
2062 /**
2063 * kbase_js_evict_deps - Evict dependencies of a failed atom.
2064 * @kctx: Context pointer
2065 * @katom: Pointer to the atom that has failed.
2066 * @js: The job slot the katom was run on.
2067 * @prio: Priority of the katom.
2068 *
2069 * Remove all post dependencies of an atom from the context ringbuffers.
2070 *
2071 * The original atom's event_code will be propogated to all dependent atoms.
2072 *
2073 * Context: Caller must hold the HW access lock
2074 */
kbase_js_evict_deps(struct kbase_context *kctx, struct kbase_jd_atom *katom, int js, int prio)2075 static void kbase_js_evict_deps(struct kbase_context *kctx,
2076 struct kbase_jd_atom *katom, int js, int prio)
2077 {
2078 struct kbase_jd_atom *x_dep = katom->x_post_dep;
2079 struct kbase_jd_atom *next_katom = katom->post_dep;
2080
2081 lockdep_assert_held(&kctx->kbdev->hwaccess_lock);
2082
2083 if (next_katom) {
2084 KBASE_DEBUG_ASSERT(next_katom->status !=
2085 KBASE_JD_ATOM_STATE_HW_COMPLETED);
2086 next_katom->will_fail_event_code = katom->event_code;
2087
2088 }
2089
2090 /* Has cross slot depenency. */
2091 if (x_dep && (x_dep->atom_flags & (KBASE_KATOM_FLAG_JSCTX_IN_TREE |
2092 KBASE_KATOM_FLAG_JSCTX_IN_X_DEP_LIST))) {
2093 /* Remove dependency.*/
2094 x_dep->atom_flags &= ~KBASE_KATOM_FLAG_X_DEP_BLOCKED;
2095
2096 /* Fail if it had a data dependency. */
2097 if (x_dep->atom_flags & KBASE_KATOM_FLAG_FAIL_BLOCKER) {
2098 x_dep->will_fail_event_code = katom->event_code;
2099 }
2100 if (x_dep->atom_flags & KBASE_KATOM_FLAG_JSCTX_IN_X_DEP_LIST)
2101 kbase_js_move_to_tree(x_dep);
2102 }
2103 }
2104
kbase_js_pull(struct kbase_context *kctx, int js)2105 struct kbase_jd_atom *kbase_js_pull(struct kbase_context *kctx, int js)
2106 {
2107 struct kbase_jd_atom *katom;
2108 struct kbasep_js_device_data *js_devdata;
2109 struct kbase_device *kbdev;
2110 int pulled;
2111
2112 KBASE_DEBUG_ASSERT(kctx);
2113
2114 kbdev = kctx->kbdev;
2115
2116 js_devdata = &kbdev->js_data;
2117 lockdep_assert_held(&kbdev->hwaccess_lock);
2118
2119 if (!kbasep_js_is_submit_allowed(js_devdata, kctx))
2120 return NULL;
2121 if (kbase_pm_is_suspending(kbdev))
2122 return NULL;
2123
2124 katom = jsctx_rb_peek(kctx, js);
2125 if (!katom)
2126 return NULL;
2127 if (kctx->blocked_js[js][katom->sched_priority])
2128 return NULL;
2129 if (atomic_read(&katom->blocked))
2130 return NULL;
2131
2132 /* Due to ordering restrictions when unpulling atoms on failure, we do
2133 * not allow multiple runs of fail-dep atoms from the same context to be
2134 * present on the same slot */
2135 if (katom->pre_dep && atomic_read(&kctx->atoms_pulled_slot[js])) {
2136 struct kbase_jd_atom *prev_atom =
2137 kbase_backend_inspect_tail(kbdev, js);
2138
2139 if (prev_atom && prev_atom->kctx != kctx)
2140 return NULL;
2141 }
2142
2143 if (katom->atom_flags & KBASE_KATOM_FLAG_X_DEP_BLOCKED) {
2144 if (katom->x_pre_dep->gpu_rb_state ==
2145 KBASE_ATOM_GPU_RB_NOT_IN_SLOT_RB ||
2146 katom->x_pre_dep->will_fail_event_code)
2147 return NULL;
2148 if ((katom->atom_flags & KBASE_KATOM_FLAG_FAIL_BLOCKER) &&
2149 kbase_backend_nr_atoms_on_slot(kbdev, js))
2150 return NULL;
2151 }
2152
2153 kbase_ctx_flag_set(kctx, KCTX_PULLED);
2154
2155 pulled = atomic_inc_return(&kctx->atoms_pulled);
2156 if (pulled == 1 && !kctx->slots_pullable) {
2157 WARN_ON(kbase_ctx_flag(kctx, KCTX_RUNNABLE_REF));
2158 kbase_ctx_flag_set(kctx, KCTX_RUNNABLE_REF);
2159 atomic_inc(&kbdev->js_data.nr_contexts_runnable);
2160 }
2161 atomic_inc(&kctx->atoms_pulled_slot[katom->slot_nr]);
2162 kctx->atoms_pulled_slot_pri[katom->slot_nr][katom->sched_priority]++;
2163 jsctx_rb_pull(kctx, katom);
2164
2165 kbasep_js_runpool_retain_ctx_nolock(kbdev, kctx);
2166
2167 katom->atom_flags |= KBASE_KATOM_FLAG_HOLDING_CTX_REF;
2168
2169 katom->ticks = 0;
2170
2171 return katom;
2172 }
2173
2174
js_return_worker(struct work_struct *data)2175 static void js_return_worker(struct work_struct *data)
2176 {
2177 struct kbase_jd_atom *katom = container_of(data, struct kbase_jd_atom,
2178 work);
2179 struct kbase_context *kctx = katom->kctx;
2180 struct kbase_device *kbdev = kctx->kbdev;
2181 struct kbasep_js_device_data *js_devdata = &kbdev->js_data;
2182 struct kbasep_js_kctx_info *js_kctx_info = &kctx->jctx.sched_info;
2183 struct kbasep_js_atom_retained_state retained_state;
2184 int js = katom->slot_nr;
2185 int prio = katom->sched_priority;
2186 bool timer_sync = false;
2187 bool context_idle = false;
2188 unsigned long flags;
2189 base_jd_core_req core_req = katom->core_req;
2190 u64 affinity = katom->affinity;
2191 enum kbase_atom_coreref_state coreref_state = katom->coreref_state;
2192
2193 KBASE_TLSTREAM_TL_EVENT_ATOM_SOFTSTOP_EX(katom);
2194
2195 kbase_backend_complete_wq(kbdev, katom);
2196
2197 if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_8316))
2198 kbase_as_poking_timer_release_atom(kbdev, kctx, katom);
2199
2200 kbasep_js_atom_retained_state_copy(&retained_state, katom);
2201
2202 mutex_lock(&js_devdata->queue_mutex);
2203 mutex_lock(&js_kctx_info->ctx.jsctx_mutex);
2204
2205 atomic_dec(&kctx->atoms_pulled);
2206 atomic_dec(&kctx->atoms_pulled_slot[js]);
2207
2208 atomic_dec(&katom->blocked);
2209
2210 spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
2211
2212 kctx->atoms_pulled_slot_pri[js][katom->sched_priority]--;
2213
2214 if (!atomic_read(&kctx->atoms_pulled_slot[js]) &&
2215 jsctx_rb_none_to_pull(kctx, js))
2216 timer_sync |= kbase_js_ctx_list_remove_nolock(kbdev, kctx, js);
2217
2218 /* If this slot has been blocked due to soft-stopped atoms, and all
2219 * atoms have now been processed, then unblock the slot */
2220 if (!kctx->atoms_pulled_slot_pri[js][prio] &&
2221 kctx->blocked_js[js][prio]) {
2222 kctx->blocked_js[js][prio] = false;
2223
2224 /* Only mark the slot as pullable if the context is not idle -
2225 * that case is handled below */
2226 if (atomic_read(&kctx->atoms_pulled) &&
2227 kbase_js_ctx_pullable(kctx, js, true))
2228 timer_sync |= kbase_js_ctx_list_add_pullable_nolock(
2229 kbdev, kctx, js);
2230 }
2231
2232 if (!atomic_read(&kctx->atoms_pulled)) {
2233 if (!kctx->slots_pullable) {
2234 WARN_ON(!kbase_ctx_flag(kctx, KCTX_RUNNABLE_REF));
2235 kbase_ctx_flag_clear(kctx, KCTX_RUNNABLE_REF);
2236 atomic_dec(&kbdev->js_data.nr_contexts_runnable);
2237 timer_sync = true;
2238 }
2239
2240 if (kctx->as_nr != KBASEP_AS_NR_INVALID &&
2241 !kbase_ctx_flag(kctx, KCTX_DYING)) {
2242 int num_slots = kbdev->gpu_props.num_job_slots;
2243 int slot;
2244
2245 if (!kbasep_js_is_submit_allowed(js_devdata, kctx))
2246 kbasep_js_set_submit_allowed(js_devdata, kctx);
2247
2248 for (slot = 0; slot < num_slots; slot++) {
2249 if (kbase_js_ctx_pullable(kctx, slot, true))
2250 timer_sync |=
2251 kbase_js_ctx_list_add_pullable_nolock(
2252 kbdev, kctx, slot);
2253 }
2254 }
2255
2256 kbase_jm_idle_ctx(kbdev, kctx);
2257
2258 context_idle = true;
2259 }
2260
2261 spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
2262
2263 if (context_idle) {
2264 WARN_ON(!kbase_ctx_flag(kctx, KCTX_ACTIVE));
2265 kbase_ctx_flag_clear(kctx, KCTX_ACTIVE);
2266 kbase_pm_context_idle(kbdev);
2267 }
2268
2269 if (timer_sync)
2270 kbase_js_sync_timers(kbdev);
2271
2272 mutex_unlock(&js_kctx_info->ctx.jsctx_mutex);
2273 mutex_unlock(&js_devdata->queue_mutex);
2274
2275 katom->atom_flags &= ~KBASE_KATOM_FLAG_HOLDING_CTX_REF;
2276 kbasep_js_runpool_release_ctx_and_katom_retained_state(kbdev, kctx,
2277 &retained_state);
2278
2279 kbase_js_sched_all(kbdev);
2280
2281 kbase_backend_complete_wq_post_sched(kbdev, core_req, affinity,
2282 coreref_state);
2283 }
2284
kbase_js_unpull(struct kbase_context *kctx, struct kbase_jd_atom *katom)2285 void kbase_js_unpull(struct kbase_context *kctx, struct kbase_jd_atom *katom)
2286 {
2287 lockdep_assert_held(&kctx->kbdev->hwaccess_lock);
2288
2289 jsctx_rb_unpull(kctx, katom);
2290
2291 WARN_ON(work_pending(&katom->work));
2292
2293 /* Block re-submission until workqueue has run */
2294 atomic_inc(&katom->blocked);
2295
2296 kbase_job_check_leave_disjoint(kctx->kbdev, katom);
2297
2298 KBASE_DEBUG_ASSERT(0 == object_is_on_stack(&katom->work));
2299 INIT_WORK(&katom->work, js_return_worker);
2300 queue_work(kctx->jctx.job_done_wq, &katom->work);
2301 }
2302
kbase_js_complete_atom_wq(struct kbase_context *kctx, struct kbase_jd_atom *katom)2303 bool kbase_js_complete_atom_wq(struct kbase_context *kctx,
2304 struct kbase_jd_atom *katom)
2305 {
2306 struct kbasep_js_kctx_info *js_kctx_info;
2307 struct kbasep_js_device_data *js_devdata;
2308 struct kbase_device *kbdev;
2309 unsigned long flags;
2310 bool timer_sync = false;
2311 int atom_slot;
2312 bool context_idle = false;
2313 int prio = katom->sched_priority;
2314
2315 kbdev = kctx->kbdev;
2316 atom_slot = katom->slot_nr;
2317
2318 js_kctx_info = &kctx->jctx.sched_info;
2319 js_devdata = &kbdev->js_data;
2320
2321 lockdep_assert_held(&js_kctx_info->ctx.jsctx_mutex);
2322
2323 mutex_lock(&js_devdata->runpool_mutex);
2324 spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
2325
2326 if (katom->atom_flags & KBASE_KATOM_FLAG_JSCTX_IN_TREE) {
2327 context_idle = !atomic_dec_return(&kctx->atoms_pulled);
2328 atomic_dec(&kctx->atoms_pulled_slot[atom_slot]);
2329 kctx->atoms_pulled_slot_pri[atom_slot][prio]--;
2330
2331 if (!atomic_read(&kctx->atoms_pulled) &&
2332 !kctx->slots_pullable) {
2333 WARN_ON(!kbase_ctx_flag(kctx, KCTX_RUNNABLE_REF));
2334 kbase_ctx_flag_clear(kctx, KCTX_RUNNABLE_REF);
2335 atomic_dec(&kbdev->js_data.nr_contexts_runnable);
2336 timer_sync = true;
2337 }
2338
2339 /* If this slot has been blocked due to soft-stopped atoms, and
2340 * all atoms have now been processed, then unblock the slot */
2341 if (!kctx->atoms_pulled_slot_pri[atom_slot][prio]
2342 && kctx->blocked_js[atom_slot][prio]) {
2343 kctx->blocked_js[atom_slot][prio] = false;
2344 if (kbase_js_ctx_pullable(kctx, atom_slot, true))
2345 timer_sync |=
2346 kbase_js_ctx_list_add_pullable_nolock(
2347 kbdev, kctx, atom_slot);
2348 }
2349 }
2350 WARN_ON(!(katom->atom_flags & KBASE_KATOM_FLAG_JSCTX_IN_TREE));
2351
2352 if (!atomic_read(&kctx->atoms_pulled_slot[atom_slot]) &&
2353 jsctx_rb_none_to_pull(kctx, atom_slot)) {
2354 if (!list_empty(
2355 &kctx->jctx.sched_info.ctx.ctx_list_entry[atom_slot]))
2356 timer_sync |= kbase_js_ctx_list_remove_nolock(
2357 kctx->kbdev, kctx, atom_slot);
2358 }
2359
2360 /*
2361 * If submission is disabled on this context (most likely due to an
2362 * atom failure) and there are now no atoms left in the system then
2363 * re-enable submission so that context can be scheduled again.
2364 */
2365 if (!kbasep_js_is_submit_allowed(js_devdata, kctx) &&
2366 !atomic_read(&kctx->atoms_pulled) &&
2367 !kbase_ctx_flag(kctx, KCTX_DYING)) {
2368 int js;
2369
2370 kbasep_js_set_submit_allowed(js_devdata, kctx);
2371
2372 for (js = 0; js < kbdev->gpu_props.num_job_slots; js++) {
2373 if (kbase_js_ctx_pullable(kctx, js, true))
2374 timer_sync |=
2375 kbase_js_ctx_list_add_pullable_nolock(
2376 kbdev, kctx, js);
2377 }
2378 } else if (katom->x_post_dep &&
2379 kbasep_js_is_submit_allowed(js_devdata, kctx)) {
2380 int js;
2381
2382 for (js = 0; js < kbdev->gpu_props.num_job_slots; js++) {
2383 if (kbase_js_ctx_pullable(kctx, js, true))
2384 timer_sync |=
2385 kbase_js_ctx_list_add_pullable_nolock(
2386 kbdev, kctx, js);
2387 }
2388 }
2389
2390 /* Mark context as inactive. The pm reference will be dropped later in
2391 * jd_done_worker().
2392 */
2393 if (context_idle)
2394 kbase_ctx_flag_clear(kctx, KCTX_ACTIVE);
2395
2396 spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
2397 if (timer_sync)
2398 kbase_backend_ctx_count_changed(kbdev);
2399 mutex_unlock(&js_devdata->runpool_mutex);
2400
2401 return context_idle;
2402 }
2403
kbase_js_complete_atom(struct kbase_jd_atom *katom, ktime_t *end_timestamp)2404 struct kbase_jd_atom *kbase_js_complete_atom(struct kbase_jd_atom *katom,
2405 ktime_t *end_timestamp)
2406 {
2407 u64 microseconds_spent = 0;
2408 struct kbase_device *kbdev;
2409 struct kbase_context *kctx = katom->kctx;
2410 struct kbase_jd_atom *x_dep = katom->x_post_dep;
2411
2412 kbdev = kctx->kbdev;
2413
2414
2415 lockdep_assert_held(&kctx->kbdev->hwaccess_lock);
2416
2417 if (katom->will_fail_event_code)
2418 katom->event_code = katom->will_fail_event_code;
2419
2420 katom->status = KBASE_JD_ATOM_STATE_HW_COMPLETED;
2421
2422 if (katom->event_code != BASE_JD_EVENT_DONE) {
2423 kbase_js_evict_deps(kctx, katom, katom->slot_nr,
2424 katom->sched_priority);
2425 }
2426
2427 #if defined(CONFIG_MALI_GATOR_SUPPORT)
2428 kbase_trace_mali_job_slots_event(GATOR_MAKE_EVENT(GATOR_JOB_SLOT_STOP,
2429 katom->slot_nr), NULL, 0);
2430 #endif
2431
2432 /* Calculate the job's time used */
2433 if (end_timestamp != NULL) {
2434 /* Only calculating it for jobs that really run on the HW (e.g.
2435 * removed from next jobs never actually ran, so really did take
2436 * zero time) */
2437 ktime_t tick_diff = ktime_sub(*end_timestamp,
2438 katom->start_timestamp);
2439
2440 microseconds_spent = ktime_to_ns(tick_diff);
2441
2442 do_div(microseconds_spent, 1000);
2443
2444 /* Round up time spent to the minimum timer resolution */
2445 if (microseconds_spent < KBASEP_JS_TICK_RESOLUTION_US)
2446 microseconds_spent = KBASEP_JS_TICK_RESOLUTION_US;
2447 }
2448
2449
2450 kbase_jd_done(katom, katom->slot_nr, end_timestamp, 0);
2451
2452 /* Unblock cross dependency if present */
2453 if (x_dep && (katom->event_code == BASE_JD_EVENT_DONE ||
2454 !(x_dep->atom_flags & KBASE_KATOM_FLAG_FAIL_BLOCKER)) &&
2455 (x_dep->atom_flags & KBASE_KATOM_FLAG_X_DEP_BLOCKED)) {
2456 bool was_pullable = kbase_js_ctx_pullable(kctx, x_dep->slot_nr,
2457 false);
2458 x_dep->atom_flags &= ~KBASE_KATOM_FLAG_X_DEP_BLOCKED;
2459 kbase_js_move_to_tree(x_dep);
2460 if (!was_pullable && kbase_js_ctx_pullable(kctx, x_dep->slot_nr,
2461 false))
2462 kbase_js_ctx_list_add_pullable_nolock(kbdev, kctx,
2463 x_dep->slot_nr);
2464
2465 if (x_dep->atom_flags & KBASE_KATOM_FLAG_JSCTX_IN_TREE)
2466 return x_dep;
2467 }
2468
2469 return NULL;
2470 }
2471
kbase_js_sched(struct kbase_device *kbdev, int js_mask)2472 void kbase_js_sched(struct kbase_device *kbdev, int js_mask)
2473 {
2474 struct kbasep_js_device_data *js_devdata;
2475 struct kbase_context *last_active;
2476 bool timer_sync = false;
2477 bool ctx_waiting = false;
2478
2479 js_devdata = &kbdev->js_data;
2480
2481 down(&js_devdata->schedule_sem);
2482 mutex_lock(&js_devdata->queue_mutex);
2483
2484 last_active = kbdev->hwaccess.active_kctx;
2485
2486 while (js_mask) {
2487 int js;
2488
2489 js = ffs(js_mask) - 1;
2490
2491 while (1) {
2492 struct kbase_context *kctx;
2493 unsigned long flags;
2494 bool context_idle = false;
2495
2496 kctx = kbase_js_ctx_list_pop_head(kbdev, js);
2497
2498 if (!kctx) {
2499 js_mask &= ~(1 << js);
2500 break; /* No contexts on pullable list */
2501 }
2502
2503 if (!kbase_ctx_flag(kctx, KCTX_ACTIVE)) {
2504 context_idle = true;
2505
2506 if (kbase_pm_context_active_handle_suspend(
2507 kbdev,
2508 KBASE_PM_SUSPEND_HANDLER_DONT_INCREASE)) {
2509 /* Suspend pending - return context to
2510 * queue and stop scheduling */
2511 mutex_lock(
2512 &kctx->jctx.sched_info.ctx.jsctx_mutex);
2513 if (kbase_js_ctx_list_add_pullable_head(
2514 kctx->kbdev, kctx, js))
2515 kbase_js_sync_timers(kbdev);
2516 mutex_unlock(
2517 &kctx->jctx.sched_info.ctx.jsctx_mutex);
2518 mutex_unlock(&js_devdata->queue_mutex);
2519 up(&js_devdata->schedule_sem);
2520 return;
2521 }
2522 kbase_ctx_flag_set(kctx, KCTX_ACTIVE);
2523 }
2524
2525 if (!kbase_js_use_ctx(kbdev, kctx)) {
2526 mutex_lock(
2527 &kctx->jctx.sched_info.ctx.jsctx_mutex);
2528 /* Context can not be used at this time */
2529 spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
2530 if (kbase_js_ctx_pullable(kctx, js, false)
2531 || kbase_ctx_flag(kctx, KCTX_PRIVILEGED))
2532 timer_sync |=
2533 kbase_js_ctx_list_add_pullable_head_nolock(
2534 kctx->kbdev, kctx, js);
2535 else
2536 timer_sync |=
2537 kbase_js_ctx_list_add_unpullable_nolock(
2538 kctx->kbdev, kctx, js);
2539 spin_unlock_irqrestore(&kbdev->hwaccess_lock,
2540 flags);
2541 mutex_unlock(
2542 &kctx->jctx.sched_info.ctx.jsctx_mutex);
2543 if (context_idle) {
2544 WARN_ON(!kbase_ctx_flag(kctx, KCTX_ACTIVE));
2545 kbase_ctx_flag_clear(kctx, KCTX_ACTIVE);
2546 kbase_pm_context_idle(kbdev);
2547 }
2548
2549 /* No more jobs can be submitted on this slot */
2550 js_mask &= ~(1 << js);
2551 break;
2552 }
2553 mutex_lock(&kctx->jctx.sched_info.ctx.jsctx_mutex);
2554 spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
2555
2556 kbase_ctx_flag_clear(kctx, KCTX_PULLED);
2557
2558 if (!kbase_jm_kick(kbdev, 1 << js))
2559 /* No more jobs can be submitted on this slot */
2560 js_mask &= ~(1 << js);
2561
2562 if (!kbase_ctx_flag(kctx, KCTX_PULLED)) {
2563 bool pullable = kbase_js_ctx_pullable(kctx, js,
2564 true);
2565
2566 /* Failed to pull jobs - push to head of list.
2567 * Unless this context is already 'active', in
2568 * which case it's effectively already scheduled
2569 * so push it to the back of the list. */
2570 if (pullable && kctx == last_active)
2571 timer_sync |=
2572 kbase_js_ctx_list_add_pullable_nolock(
2573 kctx->kbdev,
2574 kctx, js);
2575 else if (pullable)
2576 timer_sync |=
2577 kbase_js_ctx_list_add_pullable_head_nolock(
2578 kctx->kbdev,
2579 kctx, js);
2580 else
2581 timer_sync |=
2582 kbase_js_ctx_list_add_unpullable_nolock(
2583 kctx->kbdev,
2584 kctx, js);
2585
2586 /* If this context is not the active context,
2587 * but the active context is pullable on this
2588 * slot, then we need to remove the active
2589 * marker to prevent it from submitting atoms in
2590 * the IRQ handler, which would prevent this
2591 * context from making progress. */
2592 if (last_active && kctx != last_active &&
2593 kbase_js_ctx_pullable(
2594 last_active, js, true))
2595 ctx_waiting = true;
2596
2597 if (context_idle) {
2598 kbase_jm_idle_ctx(kbdev, kctx);
2599 spin_unlock_irqrestore(
2600 &kbdev->hwaccess_lock,
2601 flags);
2602 WARN_ON(!kbase_ctx_flag(kctx, KCTX_ACTIVE));
2603 kbase_ctx_flag_clear(kctx, KCTX_ACTIVE);
2604 kbase_pm_context_idle(kbdev);
2605 } else {
2606 spin_unlock_irqrestore(
2607 &kbdev->hwaccess_lock,
2608 flags);
2609 }
2610 mutex_unlock(
2611 &kctx->jctx.sched_info.ctx.jsctx_mutex);
2612
2613 js_mask &= ~(1 << js);
2614 break; /* Could not run atoms on this slot */
2615 }
2616
2617 /* Push to back of list */
2618 if (kbase_js_ctx_pullable(kctx, js, true))
2619 timer_sync |=
2620 kbase_js_ctx_list_add_pullable_nolock(
2621 kctx->kbdev, kctx, js);
2622 else
2623 timer_sync |=
2624 kbase_js_ctx_list_add_unpullable_nolock(
2625 kctx->kbdev, kctx, js);
2626
2627 spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
2628 mutex_unlock(&kctx->jctx.sched_info.ctx.jsctx_mutex);
2629 }
2630 }
2631
2632 if (timer_sync)
2633 kbase_js_sync_timers(kbdev);
2634
2635 if (kbdev->hwaccess.active_kctx == last_active && ctx_waiting)
2636 kbdev->hwaccess.active_kctx = NULL;
2637
2638 mutex_unlock(&js_devdata->queue_mutex);
2639 up(&js_devdata->schedule_sem);
2640 }
2641
kbase_js_zap_context(struct kbase_context *kctx)2642 void kbase_js_zap_context(struct kbase_context *kctx)
2643 {
2644 struct kbase_device *kbdev = kctx->kbdev;
2645 struct kbasep_js_device_data *js_devdata = &kbdev->js_data;
2646 struct kbasep_js_kctx_info *js_kctx_info = &kctx->jctx.sched_info;
2647 int js;
2648
2649 /*
2650 * Critical assumption: No more submission is possible outside of the
2651 * workqueue. This is because the OS *must* prevent U/K calls (IOCTLs)
2652 * whilst the struct kbase_context is terminating.
2653 */
2654
2655 /* First, atomically do the following:
2656 * - mark the context as dying
2657 * - try to evict it from the queue */
2658 mutex_lock(&kctx->jctx.lock);
2659 mutex_lock(&js_devdata->queue_mutex);
2660 mutex_lock(&js_kctx_info->ctx.jsctx_mutex);
2661 kbase_ctx_flag_set(kctx, KCTX_DYING);
2662
2663 dev_dbg(kbdev->dev, "Zap: Try Evict Ctx %p", kctx);
2664
2665 /*
2666 * At this point we know:
2667 * - If eviction succeeded, it was in the queue, but now no
2668 * longer is
2669 * - We must cancel the jobs here. No Power Manager active reference to
2670 * release.
2671 * - This happens asynchronously - kbase_jd_zap_context() will wait for
2672 * those jobs to be killed.
2673 * - If eviction failed, then it wasn't in the queue. It is one
2674 * of the following:
2675 * - a. it didn't have any jobs, and so is not in the Queue or
2676 * the Run Pool (not scheduled)
2677 * - Hence, no more work required to cancel jobs. No Power Manager
2678 * active reference to release.
2679 * - b. it was in the middle of a scheduling transaction (and thus must
2680 * have at least 1 job). This can happen from a syscall or a
2681 * kernel thread. We still hold the jsctx_mutex, and so the thread
2682 * must be waiting inside kbasep_js_try_schedule_head_ctx(),
2683 * before checking whether the runpool is full. That thread will
2684 * continue after we drop the mutex, and will notice the context
2685 * is dying. It will rollback the transaction, killing all jobs at
2686 * the same time. kbase_jd_zap_context() will wait for those jobs
2687 * to be killed.
2688 * - Hence, no more work required to cancel jobs, or to release the
2689 * Power Manager active reference.
2690 * - c. it is scheduled, and may or may not be running jobs
2691 * - We must cause it to leave the runpool by stopping it from
2692 * submitting any more jobs. When it finally does leave,
2693 * kbasep_js_runpool_requeue_or_kill_ctx() will kill all remaining jobs
2694 * (because it is dying), release the Power Manager active reference,
2695 * and will not requeue the context in the queue.
2696 * kbase_jd_zap_context() will wait for those jobs to be killed.
2697 * - Hence, work required just to make it leave the runpool. Cancelling
2698 * jobs and releasing the Power manager active reference will be
2699 * handled when it leaves the runpool.
2700 */
2701 if (!kbase_ctx_flag(kctx, KCTX_SCHEDULED)) {
2702 for (js = 0; js < kbdev->gpu_props.num_job_slots; js++) {
2703 if (!list_empty(
2704 &kctx->jctx.sched_info.ctx.ctx_list_entry[js]))
2705 list_del_init(
2706 &kctx->jctx.sched_info.ctx.ctx_list_entry[js]);
2707 }
2708
2709 /* The following events require us to kill off remaining jobs
2710 * and update PM book-keeping:
2711 * - we evicted it correctly (it must have jobs to be in the
2712 * Queue)
2713 *
2714 * These events need no action, but take this path anyway:
2715 * - Case a: it didn't have any jobs, and was never in the Queue
2716 * - Case b: scheduling transaction will be partially rolled-
2717 * back (this already cancels the jobs)
2718 */
2719
2720 KBASE_TRACE_ADD(kbdev, JM_ZAP_NON_SCHEDULED, kctx, NULL, 0u,
2721 kbase_ctx_flag(kctx, KCTX_SCHEDULED));
2722
2723 dev_dbg(kbdev->dev, "Zap: Ctx %p scheduled=0", kctx);
2724
2725 /* Only cancel jobs when we evicted from the
2726 * queue. No Power Manager active reference was held.
2727 *
2728 * Having is_dying set ensures that this kills, and
2729 * doesn't requeue */
2730 kbasep_js_runpool_requeue_or_kill_ctx(kbdev, kctx, false);
2731
2732 mutex_unlock(&js_kctx_info->ctx.jsctx_mutex);
2733 mutex_unlock(&js_devdata->queue_mutex);
2734 mutex_unlock(&kctx->jctx.lock);
2735 } else {
2736 unsigned long flags;
2737 bool was_retained;
2738
2739 /* Case c: didn't evict, but it is scheduled - it's in the Run
2740 * Pool */
2741 KBASE_TRACE_ADD(kbdev, JM_ZAP_SCHEDULED, kctx, NULL, 0u,
2742 kbase_ctx_flag(kctx, KCTX_SCHEDULED));
2743 dev_dbg(kbdev->dev, "Zap: Ctx %p is in RunPool", kctx);
2744
2745 /* Disable the ctx from submitting any more jobs */
2746 spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
2747
2748 kbasep_js_clear_submit_allowed(js_devdata, kctx);
2749
2750 /* Retain and (later) release the context whilst it is is now
2751 * disallowed from submitting jobs - ensures that someone
2752 * somewhere will be removing the context later on */
2753 was_retained = kbasep_js_runpool_retain_ctx_nolock(kbdev, kctx);
2754
2755 /* Since it's scheduled and we have the jsctx_mutex, it must be
2756 * retained successfully */
2757 KBASE_DEBUG_ASSERT(was_retained);
2758
2759 dev_dbg(kbdev->dev, "Zap: Ctx %p Kill Any Running jobs", kctx);
2760
2761 /* Cancel any remaining running jobs for this kctx - if any.
2762 * Submit is disallowed which takes effect immediately, so no
2763 * more new jobs will appear after we do this. */
2764 for (js = 0; js < kbdev->gpu_props.num_job_slots; js++)
2765 kbase_job_slot_hardstop(kctx, js, NULL);
2766
2767 spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
2768 mutex_unlock(&js_kctx_info->ctx.jsctx_mutex);
2769 mutex_unlock(&js_devdata->queue_mutex);
2770 mutex_unlock(&kctx->jctx.lock);
2771
2772 dev_dbg(kbdev->dev, "Zap: Ctx %p Release (may or may not schedule out immediately)",
2773 kctx);
2774
2775 kbasep_js_runpool_release_ctx(kbdev, kctx);
2776 }
2777
2778 KBASE_TRACE_ADD(kbdev, JM_ZAP_DONE, kctx, NULL, 0u, 0u);
2779
2780 /* After this, you must wait on both the
2781 * kbase_jd_context::zero_jobs_wait and the
2782 * kbasep_js_kctx_info::ctx::is_scheduled_waitq - to wait for the jobs
2783 * to be destroyed, and the context to be de-scheduled (if it was on the
2784 * runpool).
2785 *
2786 * kbase_jd_zap_context() will do this. */
2787 }
2788
trace_get_refcnt(struct kbase_device *kbdev, struct kbase_context *kctx)2789 static inline int trace_get_refcnt(struct kbase_device *kbdev,
2790 struct kbase_context *kctx)
2791 {
2792 return atomic_read(&kctx->refcount);
2793 }
2794
2795 /**
2796 * kbase_js_foreach_ctx_job(): - Call a function on all jobs in context
2797 * @kctx: Pointer to context.
2798 * @callback: Pointer to function to call for each job.
2799 *
2800 * Call a function on all jobs belonging to a non-queued, non-running
2801 * context, and detach the jobs from the context as it goes.
2802 *
2803 * Due to the locks that might be held at the time of the call, the callback
2804 * may need to defer work on a workqueue to complete its actions (e.g. when
2805 * cancelling jobs)
2806 *
2807 * Atoms will be removed from the queue, so this must only be called when
2808 * cancelling jobs (which occurs as part of context destruction).
2809 *
2810 * The locking conditions on the caller are as follows:
2811 * - it will be holding kbasep_js_kctx_info::ctx::jsctx_mutex.
2812 */
kbase_js_foreach_ctx_job(struct kbase_context *kctx, kbasep_js_ctx_job_cb callback)2813 static void kbase_js_foreach_ctx_job(struct kbase_context *kctx,
2814 kbasep_js_ctx_job_cb callback)
2815 {
2816 struct kbase_device *kbdev;
2817 struct kbasep_js_device_data *js_devdata;
2818 unsigned long flags;
2819 u32 js;
2820
2821 kbdev = kctx->kbdev;
2822 js_devdata = &kbdev->js_data;
2823
2824 spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
2825
2826 KBASE_TRACE_ADD_REFCOUNT(kbdev, JS_POLICY_FOREACH_CTX_JOBS, kctx, NULL,
2827 0u, trace_get_refcnt(kbdev, kctx));
2828
2829 /* Invoke callback on jobs on each slot in turn */
2830 for (js = 0; js < kbdev->gpu_props.num_job_slots; js++)
2831 jsctx_queue_foreach(kctx, js, callback);
2832
2833 spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
2834 }
2835