| /* | 
|  * | 
|  * (C) COPYRIGHT 2011-2017 ARM Limited. All rights reserved. | 
|  * | 
|  * This program is free software and is provided to you under the terms of the | 
|  * GNU General Public License version 2 as published by the Free Software | 
|  * Foundation, and any use by you of this program is subject to the terms | 
|  * of such GNU licence. | 
|  * | 
|  * A copy of the licence is included with the program, and can also be obtained | 
|  * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | 
|  * Boston, MA  02110-1301, USA. | 
|  * | 
|  */ | 
|   | 
|   | 
|   | 
|   | 
|   | 
| /** | 
|  * @file mali_kbase_js.h | 
|  * Job Scheduler APIs. | 
|  */ | 
|   | 
| #ifndef _KBASE_JS_H_ | 
| #define _KBASE_JS_H_ | 
|   | 
| #include "mali_kbase_js_defs.h" | 
| #include "mali_kbase_context.h" | 
| #include "mali_kbase_defs.h" | 
| #include "mali_kbase_debug.h" | 
|   | 
| #include "mali_kbase_js_ctx_attr.h" | 
|   | 
| /** | 
|  * @addtogroup base_api | 
|  * @{ | 
|  */ | 
|   | 
| /** | 
|  * @addtogroup base_kbase_api | 
|  * @{ | 
|  */ | 
|   | 
| /** | 
|  * @addtogroup kbase_js Job Scheduler Internal APIs | 
|  * @{ | 
|  * | 
|  * These APIs are Internal to KBase. | 
|  */ | 
|   | 
| /** | 
|  * @brief Initialize the Job Scheduler | 
|  * | 
|  * The struct kbasep_js_device_data sub-structure of \a kbdev must be zero | 
|  * initialized before passing to the kbasep_js_devdata_init() function. This is | 
|  * to give efficient error path code. | 
|  */ | 
| int kbasep_js_devdata_init(struct kbase_device * const kbdev); | 
|   | 
| /** | 
|  * @brief Halt the Job Scheduler. | 
|  * | 
|  * It is safe to call this on \a kbdev even if it the kbasep_js_device_data | 
|  * sub-structure was never initialized/failed initialization, to give efficient | 
|  * error-path code. | 
|  * | 
|  * For this to work, the struct kbasep_js_device_data sub-structure of \a kbdev must | 
|  * be zero initialized before passing to the kbasep_js_devdata_init() | 
|  * function. This is to give efficient error path code. | 
|  * | 
|  * It is a Programming Error to call this whilst there are still kbase_context | 
|  * structures registered with this scheduler. | 
|  * | 
|  */ | 
| void kbasep_js_devdata_halt(struct kbase_device *kbdev); | 
|   | 
| /** | 
|  * @brief Terminate the Job Scheduler | 
|  * | 
|  * It is safe to call this on \a kbdev even if it the kbasep_js_device_data | 
|  * sub-structure was never initialized/failed initialization, to give efficient | 
|  * error-path code. | 
|  * | 
|  * For this to work, the struct kbasep_js_device_data sub-structure of \a kbdev must | 
|  * be zero initialized before passing to the kbasep_js_devdata_init() | 
|  * function. This is to give efficient error path code. | 
|  * | 
|  * It is a Programming Error to call this whilst there are still kbase_context | 
|  * structures registered with this scheduler. | 
|  */ | 
| void kbasep_js_devdata_term(struct kbase_device *kbdev); | 
|   | 
| /** | 
|  * @brief Initialize the Scheduling Component of a struct kbase_context on the Job Scheduler. | 
|  * | 
|  * This effectively registers a struct kbase_context with a Job Scheduler. | 
|  * | 
|  * It does not register any jobs owned by the struct kbase_context with the scheduler. | 
|  * Those must be separately registered by kbasep_js_add_job(). | 
|  * | 
|  * The struct kbase_context must be zero intitialized before passing to the | 
|  * kbase_js_init() function. This is to give efficient error path code. | 
|  */ | 
| int kbasep_js_kctx_init(struct kbase_context * const kctx); | 
|   | 
| /** | 
|  * @brief Terminate the Scheduling Component of a struct kbase_context on the Job Scheduler | 
|  * | 
|  * This effectively de-registers a struct kbase_context from its Job Scheduler | 
|  * | 
|  * It is safe to call this on a struct kbase_context that has never had or failed | 
|  * initialization of its jctx.sched_info member, to give efficient error-path | 
|  * code. | 
|  * | 
|  * For this to work, the struct kbase_context must be zero intitialized before passing | 
|  * to the kbase_js_init() function. | 
|  * | 
|  * It is a Programming Error to call this whilst there are still jobs | 
|  * registered with this context. | 
|  */ | 
| void kbasep_js_kctx_term(struct kbase_context *kctx); | 
|   | 
| /** | 
|  * @brief Add a job chain to the Job Scheduler, and take necessary actions to | 
|  * schedule the context/run the job. | 
|  * | 
|  * This atomically does the following: | 
|  * - Update the numbers of jobs information | 
|  * - Add the job to the run pool if necessary (part of init_job) | 
|  * | 
|  * Once this is done, then an appropriate action is taken: | 
|  * - If the ctx is scheduled, it attempts to start the next job (which might be | 
|  * this added job) | 
|  * - Otherwise, and if this is the first job on the context, it enqueues it on | 
|  * the Policy Queue | 
|  * | 
|  * The Policy's Queue can be updated by this in the following ways: | 
|  * - In the above case that this is the first job on the context | 
|  * - If the context is high priority and the context is not scheduled, then it | 
|  * could cause the Policy to schedule out a low-priority context, allowing | 
|  * this context to be scheduled in. | 
|  * | 
|  * If the context is already scheduled on the RunPool, then adding a job to it | 
|  * is guarenteed not to update the Policy Queue. And so, the caller is | 
|  * guarenteed to not need to try scheduling a context from the Run Pool - it | 
|  * can safely assert that the result is false. | 
|  * | 
|  * It is a programming error to have more than U32_MAX jobs in flight at a time. | 
|  * | 
|  * The following locking conditions are made on the caller: | 
|  * - it must \em not hold kbasep_js_kctx_info::ctx::jsctx_mutex. | 
|  * - it must \em not hold hwaccess_lock (as this will be obtained internally) | 
|  * - it must \em not hold kbasep_js_device_data::runpool_mutex (as this will be | 
|  * obtained internally) | 
|  * - it must \em not hold kbasep_jd_device_data::queue_mutex (again, it's used internally). | 
|  * | 
|  * @return true indicates that the Policy Queue was updated, and so the | 
|  * caller will need to try scheduling a context onto the Run Pool. | 
|  * @return false indicates that no updates were made to the Policy Queue, | 
|  * so no further action is required from the caller. This is \b always returned | 
|  * when the context is currently scheduled. | 
|  */ | 
| bool kbasep_js_add_job(struct kbase_context *kctx, struct kbase_jd_atom *atom); | 
|   | 
| /** | 
|  * @brief Remove a job chain from the Job Scheduler, except for its 'retained state'. | 
|  * | 
|  * Completely removing a job requires several calls: | 
|  * - kbasep_js_copy_atom_retained_state(), to capture the 'retained state' of | 
|  *   the atom | 
|  * - kbasep_js_remove_job(), to partially remove the atom from the Job Scheduler | 
|  * - kbasep_js_runpool_release_ctx_and_katom_retained_state(), to release the | 
|  *   remaining state held as part of the job having been run. | 
|  * | 
|  * In the common case of atoms completing normally, this set of actions is more optimal for spinlock purposes than having kbasep_js_remove_job() handle all of the actions. | 
|  * | 
|  * In the case of cancelling atoms, it is easier to call kbasep_js_remove_cancelled_job(), which handles all the necessary actions. | 
|  * | 
|  * It is a programming error to call this when: | 
|  * - \a atom is not a job belonging to kctx. | 
|  * - \a atom has already been removed from the Job Scheduler. | 
|  * - \a atom is still in the runpool | 
|  * | 
|  * Do not use this for removing jobs being killed by kbase_jd_cancel() - use | 
|  * kbasep_js_remove_cancelled_job() instead. | 
|  * | 
|  * The following locking conditions are made on the caller: | 
|  * - it must hold kbasep_js_kctx_info::ctx::jsctx_mutex. | 
|  * | 
|  */ | 
| void kbasep_js_remove_job(struct kbase_device *kbdev, struct kbase_context *kctx, struct kbase_jd_atom *atom); | 
|   | 
| /** | 
|  * @brief Completely remove a job chain from the Job Scheduler, in the case | 
|  * where the job chain was cancelled. | 
|  * | 
|  * This is a variant of kbasep_js_remove_job() that takes care of removing all | 
|  * of the retained state too. This is generally useful for cancelled atoms, | 
|  * which need not be handled in an optimal way. | 
|  * | 
|  * It is a programming error to call this when: | 
|  * - \a atom is not a job belonging to kctx. | 
|  * - \a atom has already been removed from the Job Scheduler. | 
|  * - \a atom is still in the runpool: | 
|  *  - it is not being killed with kbasep_jd_cancel() | 
|  * | 
|  * The following locking conditions are made on the caller: | 
|  * - it must hold kbasep_js_kctx_info::ctx::jsctx_mutex. | 
|  * - it must \em not hold the hwaccess_lock, (as this will be obtained | 
|  *   internally) | 
|  * - it must \em not hold kbasep_js_device_data::runpool_mutex (as this could be | 
|  * obtained internally) | 
|  * | 
|  * @return true indicates that ctx attributes have changed and the caller | 
|  * should call kbase_js_sched_all() to try to run more jobs | 
|  * @return false otherwise | 
|  */ | 
| bool kbasep_js_remove_cancelled_job(struct kbase_device *kbdev, | 
|                         struct kbase_context *kctx, | 
|                         struct kbase_jd_atom *katom); | 
|   | 
| /** | 
|  * @brief Refcount a context as being busy, preventing it from being scheduled | 
|  * out. | 
|  * | 
|  * @note This function can safely be called from IRQ context. | 
|  * | 
|  * The following locking conditions are made on the caller: | 
|  * - it must \em not hold mmu_hw_mutex and hwaccess_lock, because they will be | 
|  *   used internally. | 
|  * | 
|  * @return value != false if the retain succeeded, and the context will not be scheduled out. | 
|  * @return false if the retain failed (because the context is being/has been scheduled out). | 
|  */ | 
| bool kbasep_js_runpool_retain_ctx(struct kbase_device *kbdev, struct kbase_context *kctx); | 
|   | 
| /** | 
|  * @brief Refcount a context as being busy, preventing it from being scheduled | 
|  * out. | 
|  * | 
|  * @note This function can safely be called from IRQ context. | 
|  * | 
|  * The following locks must be held by the caller: | 
|  * - mmu_hw_mutex, hwaccess_lock | 
|  * | 
|  * @return value != false if the retain succeeded, and the context will not be scheduled out. | 
|  * @return false if the retain failed (because the context is being/has been scheduled out). | 
|  */ | 
| bool kbasep_js_runpool_retain_ctx_nolock(struct kbase_device *kbdev, struct kbase_context *kctx); | 
|   | 
| /** | 
|  * @brief Lookup a context in the Run Pool based upon its current address space | 
|  * and ensure that is stays scheduled in. | 
|  * | 
|  * The context is refcounted as being busy to prevent it from scheduling | 
|  * out. It must be released with kbasep_js_runpool_release_ctx() when it is no | 
|  * longer required to stay scheduled in. | 
|  * | 
|  * @note This function can safely be called from IRQ context. | 
|  * | 
|  * The following locking conditions are made on the caller: | 
|  * - it must \em not hold the hwaccess_lock, because it will be used internally. | 
|  *   If the hwaccess_lock is already held, then the caller should use | 
|  *   kbasep_js_runpool_lookup_ctx_nolock() instead. | 
|  * | 
|  * @return a valid struct kbase_context on success, which has been refcounted as being busy. | 
|  * @return NULL on failure, indicating that no context was found in \a as_nr | 
|  */ | 
| struct kbase_context *kbasep_js_runpool_lookup_ctx(struct kbase_device *kbdev, int as_nr); | 
|   | 
| /** | 
|  * @brief Handling the requeuing/killing of a context that was evicted from the | 
|  * policy queue or runpool. | 
|  * | 
|  * This should be used whenever handing off a context that has been evicted | 
|  * from the policy queue or the runpool: | 
|  * - If the context is not dying and has jobs, it gets re-added to the policy | 
|  * queue | 
|  * - Otherwise, it is not added | 
|  * | 
|  * In addition, if the context is dying the jobs are killed asynchronously. | 
|  * | 
|  * In all cases, the Power Manager active reference is released | 
|  * (kbase_pm_context_idle()) whenever the has_pm_ref parameter is true.  \a | 
|  * has_pm_ref must be set to false whenever the context was not previously in | 
|  * the runpool and does not hold a Power Manager active refcount. Note that | 
|  * contexts in a rollback of kbasep_js_try_schedule_head_ctx() might have an | 
|  * active refcount even though they weren't in the runpool. | 
|  * | 
|  * The following locking conditions are made on the caller: | 
|  * - it must hold kbasep_js_kctx_info::ctx::jsctx_mutex. | 
|  * - it must \em not hold kbasep_jd_device_data::queue_mutex (as this will be | 
|  * obtained internally) | 
|  */ | 
| void kbasep_js_runpool_requeue_or_kill_ctx(struct kbase_device *kbdev, struct kbase_context *kctx, bool has_pm_ref); | 
|   | 
| /** | 
|  * @brief Release a refcount of a context being busy, allowing it to be | 
|  * scheduled out. | 
|  * | 
|  * When the refcount reaches zero and the context \em might be scheduled out | 
|  * (depending on whether the Scheudling Policy has deemed it so, or if it has run | 
|  * out of jobs). | 
|  * | 
|  * If the context does get scheduled out, then The following actions will be | 
|  * taken as part of deschduling a context: | 
|  * - For the context being descheduled: | 
|  *  - If the context is in the processing of dying (all the jobs are being | 
|  * removed from it), then descheduling also kills off any jobs remaining in the | 
|  * context. | 
|  *  - If the context is not dying, and any jobs remain after descheduling the | 
|  * context then it is re-enqueued to the Policy's Queue. | 
|  *  - Otherwise, the context is still known to the scheduler, but remains absent | 
|  * from the Policy Queue until a job is next added to it. | 
|  *  - In all descheduling cases, the Power Manager active reference (obtained | 
|  * during kbasep_js_try_schedule_head_ctx()) is released (kbase_pm_context_idle()). | 
|  * | 
|  * Whilst the context is being descheduled, this also handles actions that | 
|  * cause more atoms to be run: | 
|  * - Attempt submitting atoms when the Context Attributes on the Runpool have | 
|  * changed. This is because the context being scheduled out could mean that | 
|  * there are more opportunities to run atoms. | 
|  * - Attempt submitting to a slot that was previously blocked due to affinity | 
|  * restrictions. This is usually only necessary when releasing a context | 
|  * happens as part of completing a previous job, but is harmless nonetheless. | 
|  * - Attempt scheduling in a new context (if one is available), and if necessary, | 
|  * running a job from that new context. | 
|  * | 
|  * Unlike retaining a context in the runpool, this function \b cannot be called | 
|  * from IRQ context. | 
|  * | 
|  * It is a programming error to call this on a \a kctx that is not currently | 
|  * scheduled, or that already has a zero refcount. | 
|  * | 
|  * The following locking conditions are made on the caller: | 
|  * - it must \em not hold the hwaccess_lock, because it will be used internally. | 
|  * - it must \em not hold kbasep_js_kctx_info::ctx::jsctx_mutex. | 
|  * - it must \em not hold kbasep_js_device_data::runpool_mutex (as this will be | 
|  * obtained internally) | 
|  * - it must \em not hold the kbase_device::mmu_hw_mutex (as this will be | 
|  * obtained internally) | 
|  * - it must \em not hold kbasep_jd_device_data::queue_mutex (as this will be | 
|  * obtained internally) | 
|  * | 
|  */ | 
| void kbasep_js_runpool_release_ctx(struct kbase_device *kbdev, struct kbase_context *kctx); | 
|   | 
| /** | 
|  * @brief Variant of kbasep_js_runpool_release_ctx() that handles additional | 
|  * actions from completing an atom. | 
|  * | 
|  * This is usually called as part of completing an atom and releasing the | 
|  * refcount on the context held by the atom. | 
|  * | 
|  * Therefore, the extra actions carried out are part of handling actions queued | 
|  * on a completed atom, namely: | 
|  * - Releasing the atom's context attributes | 
|  * - Retrying the submission on a particular slot, because we couldn't submit | 
|  * on that slot from an IRQ handler. | 
|  * | 
|  * The locking conditions of this function are the same as those for | 
|  * kbasep_js_runpool_release_ctx() | 
|  */ | 
| void 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); | 
|   | 
| /** | 
|  * @brief Variant of kbase_js_runpool_release_ctx() that assumes that | 
|  * kbasep_js_device_data::runpool_mutex and | 
|  * kbasep_js_kctx_info::ctx::jsctx_mutex are held by the caller, and does not | 
|  * attempt to schedule new contexts. | 
|  */ | 
| void kbasep_js_runpool_release_ctx_nolock(struct kbase_device *kbdev, | 
|                         struct kbase_context *kctx); | 
|   | 
| /** | 
|  * @brief Schedule in a privileged context | 
|  * | 
|  * This schedules a context in regardless of the context priority. | 
|  * If the runpool is full, a context will be forced out of the runpool and the function will wait | 
|  * for the new context to be scheduled in. | 
|  * The context will be kept scheduled in (and the corresponding address space reserved) until | 
|  * kbasep_js_release_privileged_ctx is called). | 
|  * | 
|  * The following locking conditions are made on the caller: | 
|  * - it must \em not hold the hwaccess_lock, because it will be used internally. | 
|  * - it must \em not hold kbasep_js_device_data::runpool_mutex (as this will be | 
|  * obtained internally) | 
|  * - it must \em not hold the kbase_device::mmu_hw_mutex (as this will be | 
|  * obtained internally) | 
|  * - it must \em not hold kbasep_jd_device_data::queue_mutex (again, it's used internally). | 
|  * - it must \em not hold kbasep_js_kctx_info::ctx::jsctx_mutex, because it will | 
|  * be used internally. | 
|  * | 
|  */ | 
| void kbasep_js_schedule_privileged_ctx(struct kbase_device *kbdev, struct kbase_context *kctx); | 
|   | 
| /** | 
|  * @brief Release a privileged context, allowing it to be scheduled out. | 
|  * | 
|  * See kbasep_js_runpool_release_ctx for potential side effects. | 
|  * | 
|  * The following locking conditions are made on the caller: | 
|  * - it must \em not hold the hwaccess_lock, because it will be used internally. | 
|  * - it must \em not hold kbasep_js_kctx_info::ctx::jsctx_mutex. | 
|  * - it must \em not hold kbasep_js_device_data::runpool_mutex (as this will be | 
|  * obtained internally) | 
|  * - it must \em not hold the kbase_device::mmu_hw_mutex (as this will be | 
|  * obtained internally) | 
|  * | 
|  */ | 
| void kbasep_js_release_privileged_ctx(struct kbase_device *kbdev, struct kbase_context *kctx); | 
|   | 
| /** | 
|  * @brief Try to submit the next job on each slot | 
|  * | 
|  * The following locks may be used: | 
|  * - kbasep_js_device_data::runpool_mutex | 
|  * - hwaccess_lock | 
|  */ | 
| void kbase_js_try_run_jobs(struct kbase_device *kbdev); | 
|   | 
| /** | 
|  * @brief Suspend the job scheduler during a Power Management Suspend event. | 
|  * | 
|  * Causes all contexts to be removed from the runpool, and prevents any | 
|  * contexts from (re)entering the runpool. | 
|  * | 
|  * This does not handle suspending the one privileged context: the caller must | 
|  * instead do this by by suspending the GPU HW Counter Instrumentation. | 
|  * | 
|  * This will eventually cause all Power Management active references held by | 
|  * contexts on the runpool to be released, without running any more atoms. | 
|  * | 
|  * The caller must then wait for all Power Mangement active refcount to become | 
|  * zero before completing the suspend. | 
|  * | 
|  * The emptying mechanism may take some time to complete, since it can wait for | 
|  * jobs to complete naturally instead of forcing them to end quickly. However, | 
|  * this is bounded by the Job Scheduler's Job Timeouts. Hence, this | 
|  * function is guaranteed to complete in a finite time. | 
|  */ | 
| void kbasep_js_suspend(struct kbase_device *kbdev); | 
|   | 
| /** | 
|  * @brief Resume the Job Scheduler after a Power Management Resume event. | 
|  * | 
|  * This restores the actions from kbasep_js_suspend(): | 
|  * - Schedules contexts back into the runpool | 
|  * - Resumes running atoms on the GPU | 
|  */ | 
| void kbasep_js_resume(struct kbase_device *kbdev); | 
|   | 
| /** | 
|  * @brief Submit an atom to the job scheduler. | 
|  * | 
|  * The atom is enqueued on the context's ringbuffer. The caller must have | 
|  * ensured that all dependencies can be represented in the ringbuffer. | 
|  * | 
|  * Caller must hold jctx->lock | 
|  * | 
|  * @param[in] kctx  Context pointer | 
|  * @param[in] atom  Pointer to the atom to submit | 
|  * | 
|  * @return Whether the context requires to be enqueued. */ | 
| bool kbase_js_dep_resolved_submit(struct kbase_context *kctx, | 
|                     struct kbase_jd_atom *katom); | 
|   | 
| /** | 
|   * jsctx_ll_flush_to_rb() - Pushes atoms from the linked list to ringbuffer. | 
|   * @kctx:  Context Pointer | 
|   * @prio:  Priority (specifies the queue together with js). | 
|   * @js:    Job slot (specifies the queue together with prio). | 
|   * | 
|   * Pushes all possible atoms from the linked list to the ringbuffer. | 
|   * Number of atoms are limited to free space in the ringbuffer and | 
|   * number of available atoms in the linked list. | 
|   * | 
|   */ | 
| void jsctx_ll_flush_to_rb(struct kbase_context *kctx, int prio, int js); | 
| /** | 
|  * @brief Pull an atom from a context in the job scheduler for execution. | 
|  * | 
|  * The atom will not be removed from the ringbuffer at this stage. | 
|  * | 
|  * The HW access lock must be held when calling this function. | 
|  * | 
|  * @param[in] kctx  Context to pull from | 
|  * @param[in] js    Job slot to pull from | 
|  * @return          Pointer to an atom, or NULL if there are no atoms for this | 
|  *                  slot that can be currently run. | 
|  */ | 
| struct kbase_jd_atom *kbase_js_pull(struct kbase_context *kctx, int js); | 
|   | 
| /** | 
|  * @brief Return an atom to the job scheduler ringbuffer. | 
|  * | 
|  * An atom is 'unpulled' if execution is stopped but intended to be returned to | 
|  * later. The most common reason for this is that the atom has been | 
|  * soft-stopped. | 
|  * | 
|  * Note that if multiple atoms are to be 'unpulled', they must be returned in | 
|  * the reverse order to which they were originally pulled. It is a programming | 
|  * error to return atoms in any other order. | 
|  * | 
|  * The HW access lock must be held when calling this function. | 
|  * | 
|  * @param[in] kctx  Context pointer | 
|  * @param[in] atom  Pointer to the atom to unpull | 
|  */ | 
| void kbase_js_unpull(struct kbase_context *kctx, struct kbase_jd_atom *katom); | 
|   | 
| /** | 
|  * @brief Complete an atom from jd_done_worker(), removing it from the job | 
|  * scheduler ringbuffer. | 
|  * | 
|  * If the atom failed then all dependee atoms marked for failure propagation | 
|  * will also fail. | 
|  * | 
|  * @param[in] kctx  Context pointer | 
|  * @param[in] katom Pointer to the atom to complete | 
|  * @return true if the context is now idle (no jobs pulled) | 
|  *         false otherwise | 
|  */ | 
| bool kbase_js_complete_atom_wq(struct kbase_context *kctx, | 
|                 struct kbase_jd_atom *katom); | 
|   | 
| /** | 
|  * @brief Complete an atom. | 
|  * | 
|  * Most of the work required to complete an atom will be performed by | 
|  * jd_done_worker(). | 
|  * | 
|  * The HW access lock must be held when calling this function. | 
|  * | 
|  * @param[in] katom         Pointer to the atom to complete | 
|  * @param[in] end_timestamp The time that the atom completed (may be NULL) | 
|  * | 
|  * Return: Atom that has now been unblocked and can now be run, or NULL if none | 
|  */ | 
| struct kbase_jd_atom *kbase_js_complete_atom(struct kbase_jd_atom *katom, | 
|         ktime_t *end_timestamp); | 
|   | 
| /** | 
|  * @brief Submit atoms from all available contexts. | 
|  * | 
|  * This will attempt to submit as many jobs as possible to the provided job | 
|  * slots. It will exit when either all job slots are full, or all contexts have | 
|  * been used. | 
|  * | 
|  * @param[in] kbdev    Device pointer | 
|  * @param[in] js_mask  Mask of job slots to submit to | 
|  */ | 
| void kbase_js_sched(struct kbase_device *kbdev, int js_mask); | 
|   | 
| /** | 
|  * kbase_jd_zap_context - Attempt to deschedule a context that is being | 
|  *                        destroyed | 
|  * @kctx: Context pointer | 
|  * | 
|  * This will attempt to remove a context from any internal job scheduler queues | 
|  * and perform any other actions to ensure a context will not be submitted | 
|  * from. | 
|  * | 
|  * If the context is currently scheduled, then the caller must wait for all | 
|  * pending jobs to complete before taking any further action. | 
|  */ | 
| void kbase_js_zap_context(struct kbase_context *kctx); | 
|   | 
| /** | 
|  * @brief Validate an atom | 
|  * | 
|  * This will determine whether the atom can be scheduled onto the GPU. Atoms | 
|  * with invalid combinations of core requirements will be rejected. | 
|  * | 
|  * @param[in] kbdev  Device pointer | 
|  * @param[in] katom  Atom to validate | 
|  * @return           true if atom is valid | 
|  *                   false otherwise | 
|  */ | 
| bool kbase_js_is_atom_valid(struct kbase_device *kbdev, | 
|                 struct kbase_jd_atom *katom); | 
|   | 
| /** | 
|  * kbase_js_set_timeouts - update all JS timeouts with user specified data | 
|  * @kbdev: Device pointer | 
|  * | 
|  * Timeouts are specified through the 'js_timeouts' sysfs file. If a timeout is | 
|  * set to a positive number then that becomes the new value used, if a timeout | 
|  * is negative then the default is set. | 
|  */ | 
| void kbase_js_set_timeouts(struct kbase_device *kbdev); | 
|   | 
| /* | 
|  * Helpers follow | 
|  */ | 
|   | 
| /** | 
|  * @brief Check that a context is allowed to submit jobs on this policy | 
|  * | 
|  * The purpose of this abstraction is to hide the underlying data size, and wrap up | 
|  * the long repeated line of code. | 
|  * | 
|  * As with any bool, never test the return value with true. | 
|  * | 
|  * The caller must hold hwaccess_lock. | 
|  */ | 
| static inline bool kbasep_js_is_submit_allowed(struct kbasep_js_device_data *js_devdata, struct kbase_context *kctx) | 
| { | 
|     u16 test_bit; | 
|   | 
|     /* Ensure context really is scheduled in */ | 
|     KBASE_DEBUG_ASSERT(kctx->as_nr != KBASEP_AS_NR_INVALID); | 
|     KBASE_DEBUG_ASSERT(kbase_ctx_flag(kctx, KCTX_SCHEDULED)); | 
|   | 
|     test_bit = (u16) (1u << kctx->as_nr); | 
|   | 
|     return (bool) (js_devdata->runpool_irq.submit_allowed & test_bit); | 
| } | 
|   | 
| /** | 
|  * @brief Allow a context to submit jobs on this policy | 
|  * | 
|  * The purpose of this abstraction is to hide the underlying data size, and wrap up | 
|  * the long repeated line of code. | 
|  * | 
|  * The caller must hold hwaccess_lock. | 
|  */ | 
| static inline void kbasep_js_set_submit_allowed(struct kbasep_js_device_data *js_devdata, struct kbase_context *kctx) | 
| { | 
|     u16 set_bit; | 
|   | 
|     /* Ensure context really is scheduled in */ | 
|     KBASE_DEBUG_ASSERT(kctx->as_nr != KBASEP_AS_NR_INVALID); | 
|     KBASE_DEBUG_ASSERT(kbase_ctx_flag(kctx, KCTX_SCHEDULED)); | 
|   | 
|     set_bit = (u16) (1u << kctx->as_nr); | 
|   | 
|     dev_dbg(kctx->kbdev->dev, "JS: Setting Submit Allowed on %p (as=%d)", kctx, kctx->as_nr); | 
|   | 
|     js_devdata->runpool_irq.submit_allowed |= set_bit; | 
| } | 
|   | 
| /** | 
|  * @brief Prevent a context from submitting more jobs on this policy | 
|  * | 
|  * The purpose of this abstraction is to hide the underlying data size, and wrap up | 
|  * the long repeated line of code. | 
|  * | 
|  * The caller must hold hwaccess_lock. | 
|  */ | 
| static inline void kbasep_js_clear_submit_allowed(struct kbasep_js_device_data *js_devdata, struct kbase_context *kctx) | 
| { | 
|     u16 clear_bit; | 
|     u16 clear_mask; | 
|   | 
|     /* Ensure context really is scheduled in */ | 
|     KBASE_DEBUG_ASSERT(kctx->as_nr != KBASEP_AS_NR_INVALID); | 
|     KBASE_DEBUG_ASSERT(kbase_ctx_flag(kctx, KCTX_SCHEDULED)); | 
|   | 
|     clear_bit = (u16) (1u << kctx->as_nr); | 
|     clear_mask = ~clear_bit; | 
|   | 
|     dev_dbg(kctx->kbdev->dev, "JS: Clearing Submit Allowed on %p (as=%d)", kctx, kctx->as_nr); | 
|   | 
|     js_devdata->runpool_irq.submit_allowed &= clear_mask; | 
| } | 
|   | 
| /** | 
|  * @brief Manage the 'retry_submit_on_slot' part of a kbase_jd_atom | 
|  */ | 
| static inline void kbasep_js_clear_job_retry_submit(struct kbase_jd_atom *atom) | 
| { | 
|     atom->retry_submit_on_slot = KBASEP_JS_RETRY_SUBMIT_SLOT_INVALID; | 
| } | 
|   | 
| /** | 
|  * Mark a slot as requiring resubmission by carrying that information on a | 
|  * completing atom. | 
|  * | 
|  * @note This can ASSERT in debug builds if the submit slot has been set to | 
|  * something other than the current value for @a js. This is because you might | 
|  * be unintentionally stopping more jobs being submitted on the old submit | 
|  * slot, and that might cause a scheduling-hang. | 
|  * | 
|  * @note If you can guarantee that the atoms for the original slot will be | 
|  * submitted on some other slot, then call kbasep_js_clear_job_retry_submit() | 
|  * first to silence the ASSERT. | 
|  */ | 
| static inline void kbasep_js_set_job_retry_submit_slot(struct kbase_jd_atom *atom, int js) | 
| { | 
|     KBASE_DEBUG_ASSERT(0 <= js && js <= BASE_JM_MAX_NR_SLOTS); | 
|     KBASE_DEBUG_ASSERT((atom->retry_submit_on_slot == | 
|                     KBASEP_JS_RETRY_SUBMIT_SLOT_INVALID) | 
|                 || (atom->retry_submit_on_slot == js)); | 
|   | 
|     atom->retry_submit_on_slot = js; | 
| } | 
|   | 
| /** | 
|  * Create an initial 'invalid' atom retained state, that requires no | 
|  * atom-related work to be done on releasing with | 
|  * kbasep_js_runpool_release_ctx_and_katom_retained_state() | 
|  */ | 
| static inline void kbasep_js_atom_retained_state_init_invalid(struct kbasep_js_atom_retained_state *retained_state) | 
| { | 
|     retained_state->event_code = BASE_JD_EVENT_NOT_STARTED; | 
|     retained_state->core_req = KBASEP_JS_ATOM_RETAINED_STATE_CORE_REQ_INVALID; | 
|     retained_state->retry_submit_on_slot = KBASEP_JS_RETRY_SUBMIT_SLOT_INVALID; | 
| } | 
|   | 
| /** | 
|  * Copy atom state that can be made available after jd_done_nolock() is called | 
|  * on that atom. | 
|  */ | 
| static inline void kbasep_js_atom_retained_state_copy(struct kbasep_js_atom_retained_state *retained_state, const struct kbase_jd_atom *katom) | 
| { | 
|     retained_state->event_code = katom->event_code; | 
|     retained_state->core_req = katom->core_req; | 
|     retained_state->retry_submit_on_slot = katom->retry_submit_on_slot; | 
|     retained_state->sched_priority = katom->sched_priority; | 
|     retained_state->device_nr = katom->device_nr; | 
| } | 
|   | 
| /** | 
|  * @brief Determine whether an atom has finished (given its retained state), | 
|  * and so should be given back to userspace/removed from the system. | 
|  * | 
|  * Reasons for an atom not finishing include: | 
|  * - Being soft-stopped (and so, the atom should be resubmitted sometime later) | 
|  * | 
|  * @param[in] katom_retained_state the retained state of the atom to check | 
|  * @return    false if the atom has not finished | 
|  * @return    !=false if the atom has finished | 
|  */ | 
| static inline bool kbasep_js_has_atom_finished(const struct kbasep_js_atom_retained_state *katom_retained_state) | 
| { | 
|     return (bool) (katom_retained_state->event_code != BASE_JD_EVENT_STOPPED && katom_retained_state->event_code != BASE_JD_EVENT_REMOVED_FROM_NEXT); | 
| } | 
|   | 
| /** | 
|  * @brief Determine whether a struct kbasep_js_atom_retained_state is valid | 
|  * | 
|  * An invalid struct kbasep_js_atom_retained_state is allowed, and indicates that the | 
|  * code should just ignore it. | 
|  * | 
|  * @param[in] katom_retained_state the atom's retained state to check | 
|  * @return    false if the retained state is invalid, and can be ignored | 
|  * @return    !=false if the retained state is valid | 
|  */ | 
| static inline bool kbasep_js_atom_retained_state_is_valid(const struct kbasep_js_atom_retained_state *katom_retained_state) | 
| { | 
|     return (bool) (katom_retained_state->core_req != KBASEP_JS_ATOM_RETAINED_STATE_CORE_REQ_INVALID); | 
| } | 
|   | 
| static inline bool kbasep_js_get_atom_retry_submit_slot(const struct kbasep_js_atom_retained_state *katom_retained_state, int *res) | 
| { | 
|     int js = katom_retained_state->retry_submit_on_slot; | 
|   | 
|     *res = js; | 
|     return (bool) (js >= 0); | 
| } | 
|   | 
| /** | 
|  * @brief Variant of kbasep_js_runpool_lookup_ctx() that can be used when the | 
|  * context is guaranteed to be already previously retained. | 
|  * | 
|  * It is a programming error to supply the \a as_nr of a context that has not | 
|  * been previously retained/has a busy refcount of zero. The only exception is | 
|  * when there is no ctx in \a as_nr (NULL returned). | 
|  * | 
|  * The following locking conditions are made on the caller: | 
|  * - it must \em not hold the hwaccess_lock, because it will be used internally. | 
|  * | 
|  * @return a valid struct kbase_context on success, with a refcount that is guaranteed | 
|  * to be non-zero and unmodified by this function. | 
|  * @return NULL on failure, indicating that no context was found in \a as_nr | 
|  */ | 
| static inline struct kbase_context *kbasep_js_runpool_lookup_ctx_noretain(struct kbase_device *kbdev, int as_nr) | 
| { | 
|     struct kbase_context *found_kctx; | 
|   | 
|     KBASE_DEBUG_ASSERT(kbdev != NULL); | 
|     KBASE_DEBUG_ASSERT(0 <= as_nr && as_nr < BASE_MAX_NR_AS); | 
|   | 
|     found_kctx = kbdev->as_to_kctx[as_nr]; | 
|     KBASE_DEBUG_ASSERT(found_kctx == NULL || | 
|             atomic_read(&found_kctx->refcount) > 0); | 
|   | 
|     return found_kctx; | 
| } | 
|   | 
| /* | 
|  * The following locking conditions are made on the caller: | 
|  * - The caller must hold the kbasep_js_kctx_info::ctx::jsctx_mutex. | 
|  * - The caller must hold the kbasep_js_device_data::runpool_mutex | 
|  */ | 
| static inline void kbase_js_runpool_inc_context_count( | 
|                         struct kbase_device *kbdev, | 
|                         struct kbase_context *kctx) | 
| { | 
|     struct kbasep_js_device_data *js_devdata; | 
|     struct kbasep_js_kctx_info *js_kctx_info; | 
|   | 
|     KBASE_DEBUG_ASSERT(kbdev != NULL); | 
|     KBASE_DEBUG_ASSERT(kctx != NULL); | 
|   | 
|     js_devdata = &kbdev->js_data; | 
|     js_kctx_info = &kctx->jctx.sched_info; | 
|   | 
|     lockdep_assert_held(&js_kctx_info->ctx.jsctx_mutex); | 
|     lockdep_assert_held(&js_devdata->runpool_mutex); | 
|   | 
|     /* Track total contexts */ | 
|     KBASE_DEBUG_ASSERT(js_devdata->nr_all_contexts_running < S8_MAX); | 
|     ++(js_devdata->nr_all_contexts_running); | 
|   | 
|     if (!kbase_ctx_flag(kctx, KCTX_SUBMIT_DISABLED)) { | 
|         /* Track contexts that can submit jobs */ | 
|         KBASE_DEBUG_ASSERT(js_devdata->nr_user_contexts_running < | 
|                                     S8_MAX); | 
|         ++(js_devdata->nr_user_contexts_running); | 
|     } | 
| } | 
|   | 
| /* | 
|  * The following locking conditions are made on the caller: | 
|  * - The caller must hold the kbasep_js_kctx_info::ctx::jsctx_mutex. | 
|  * - The caller must hold the kbasep_js_device_data::runpool_mutex | 
|  */ | 
| static inline void kbase_js_runpool_dec_context_count( | 
|                         struct kbase_device *kbdev, | 
|                         struct kbase_context *kctx) | 
| { | 
|     struct kbasep_js_device_data *js_devdata; | 
|     struct kbasep_js_kctx_info *js_kctx_info; | 
|   | 
|     KBASE_DEBUG_ASSERT(kbdev != NULL); | 
|     KBASE_DEBUG_ASSERT(kctx != NULL); | 
|   | 
|     js_devdata = &kbdev->js_data; | 
|     js_kctx_info = &kctx->jctx.sched_info; | 
|   | 
|     lockdep_assert_held(&js_kctx_info->ctx.jsctx_mutex); | 
|     lockdep_assert_held(&js_devdata->runpool_mutex); | 
|   | 
|     /* Track total contexts */ | 
|     --(js_devdata->nr_all_contexts_running); | 
|     KBASE_DEBUG_ASSERT(js_devdata->nr_all_contexts_running >= 0); | 
|   | 
|     if (!kbase_ctx_flag(kctx, KCTX_SUBMIT_DISABLED)) { | 
|         /* Track contexts that can submit jobs */ | 
|         --(js_devdata->nr_user_contexts_running); | 
|         KBASE_DEBUG_ASSERT(js_devdata->nr_user_contexts_running >= 0); | 
|     } | 
| } | 
|   | 
|   | 
| /** | 
|  * @brief Submit atoms from all available contexts to all job slots. | 
|  * | 
|  * This will attempt to submit as many jobs as possible. It will exit when | 
|  * either all job slots are full, or all contexts have been used. | 
|  * | 
|  * @param[in] kbdev    Device pointer | 
|  */ | 
| static inline void kbase_js_sched_all(struct kbase_device *kbdev) | 
| { | 
|     kbase_js_sched(kbdev, (1 << kbdev->gpu_props.num_job_slots) - 1); | 
| } | 
|   | 
| extern const int | 
| kbasep_js_atom_priority_to_relative[BASE_JD_NR_PRIO_LEVELS]; | 
|   | 
| extern const base_jd_prio | 
| kbasep_js_relative_priority_to_atom[KBASE_JS_ATOM_SCHED_PRIO_COUNT]; | 
|   | 
| /** | 
|  * kbasep_js_atom_prio_to_sched_prio(): - Convert atom priority (base_jd_prio) | 
|  *                                        to relative ordering | 
|  * @atom_prio: Priority ID to translate. | 
|  * | 
|  * Atom priority values for @ref base_jd_prio cannot be compared directly to | 
|  * find out which are higher or lower. | 
|  * | 
|  * This function will convert base_jd_prio values for successively lower | 
|  * priorities into a monotonically increasing sequence. That is, the lower the | 
|  * base_jd_prio priority, the higher the value produced by this function. This | 
|  * is in accordance with how the rest of the kernel treates priority. | 
|  * | 
|  * The mapping is 1:1 and the size of the valid input range is the same as the | 
|  * size of the valid output range, i.e. | 
|  * KBASE_JS_ATOM_SCHED_PRIO_COUNT == BASE_JD_NR_PRIO_LEVELS | 
|  * | 
|  * Note This must be kept in sync with BASE_JD_PRIO_<...> definitions | 
|  * | 
|  * Return: On success: a value in the inclusive range | 
|  *         0..KBASE_JS_ATOM_SCHED_PRIO_COUNT-1. On failure: | 
|  *         KBASE_JS_ATOM_SCHED_PRIO_INVALID | 
|  */ | 
| static inline int kbasep_js_atom_prio_to_sched_prio(base_jd_prio atom_prio) | 
| { | 
|     if (atom_prio >= BASE_JD_NR_PRIO_LEVELS) | 
|         return KBASE_JS_ATOM_SCHED_PRIO_INVALID; | 
|   | 
|     return kbasep_js_atom_priority_to_relative[atom_prio]; | 
| } | 
|   | 
| static inline base_jd_prio kbasep_js_sched_prio_to_atom_prio(int sched_prio) | 
| { | 
|     unsigned int prio_idx; | 
|   | 
|     KBASE_DEBUG_ASSERT(0 <= sched_prio | 
|             && sched_prio < KBASE_JS_ATOM_SCHED_PRIO_COUNT); | 
|   | 
|     prio_idx = (unsigned int)sched_prio; | 
|   | 
|     return kbasep_js_relative_priority_to_atom[prio_idx]; | 
| } | 
|   | 
|       /** @} *//* end group kbase_js */ | 
|       /** @} *//* end group base_kbase_api */ | 
|       /** @} *//* end group base_api */ | 
|   | 
| #endif                /* _KBASE_JS_H_ */ |