18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * Copyright © 2008-2018 Intel Corporation 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 58c2ecf20Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 68c2ecf20Sopenharmony_ci * to deal in the Software without restriction, including without limitation 78c2ecf20Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 88c2ecf20Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 98c2ecf20Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 108c2ecf20Sopenharmony_ci * 118c2ecf20Sopenharmony_ci * The above copyright notice and this permission notice (including the next 128c2ecf20Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the 138c2ecf20Sopenharmony_ci * Software. 148c2ecf20Sopenharmony_ci * 158c2ecf20Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 168c2ecf20Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 178c2ecf20Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 188c2ecf20Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 198c2ecf20Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 208c2ecf20Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 218c2ecf20Sopenharmony_ci * IN THE SOFTWARE. 228c2ecf20Sopenharmony_ci * 238c2ecf20Sopenharmony_ci */ 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_ci#ifndef I915_REQUEST_H 268c2ecf20Sopenharmony_ci#define I915_REQUEST_H 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_ci#include <linux/dma-fence.h> 298c2ecf20Sopenharmony_ci#include <linux/irq_work.h> 308c2ecf20Sopenharmony_ci#include <linux/lockdep.h> 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_ci#include "gem/i915_gem_context_types.h" 338c2ecf20Sopenharmony_ci#include "gt/intel_context_types.h" 348c2ecf20Sopenharmony_ci#include "gt/intel_engine_types.h" 358c2ecf20Sopenharmony_ci#include "gt/intel_timeline_types.h" 368c2ecf20Sopenharmony_ci 378c2ecf20Sopenharmony_ci#include "i915_gem.h" 388c2ecf20Sopenharmony_ci#include "i915_scheduler.h" 398c2ecf20Sopenharmony_ci#include "i915_selftest.h" 408c2ecf20Sopenharmony_ci#include "i915_sw_fence.h" 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_ci#include <uapi/drm/i915_drm.h> 438c2ecf20Sopenharmony_ci 448c2ecf20Sopenharmony_cistruct drm_file; 458c2ecf20Sopenharmony_cistruct drm_i915_gem_object; 468c2ecf20Sopenharmony_cistruct i915_request; 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_cistruct i915_capture_list { 498c2ecf20Sopenharmony_ci struct i915_capture_list *next; 508c2ecf20Sopenharmony_ci struct i915_vma *vma; 518c2ecf20Sopenharmony_ci}; 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_ci#define RQ_TRACE(rq, fmt, ...) do { \ 548c2ecf20Sopenharmony_ci const struct i915_request *rq__ = (rq); \ 558c2ecf20Sopenharmony_ci ENGINE_TRACE(rq__->engine, "fence %llx:%lld, current %d " fmt, \ 568c2ecf20Sopenharmony_ci rq__->fence.context, rq__->fence.seqno, \ 578c2ecf20Sopenharmony_ci hwsp_seqno(rq__), ##__VA_ARGS__); \ 588c2ecf20Sopenharmony_ci} while (0) 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_cienum { 618c2ecf20Sopenharmony_ci /* 628c2ecf20Sopenharmony_ci * I915_FENCE_FLAG_ACTIVE - this request is currently submitted to HW. 638c2ecf20Sopenharmony_ci * 648c2ecf20Sopenharmony_ci * Set by __i915_request_submit() on handing over to HW, and cleared 658c2ecf20Sopenharmony_ci * by __i915_request_unsubmit() if we preempt this request. 668c2ecf20Sopenharmony_ci * 678c2ecf20Sopenharmony_ci * Finally cleared for consistency on retiring the request, when 688c2ecf20Sopenharmony_ci * we know the HW is no longer running this request. 698c2ecf20Sopenharmony_ci * 708c2ecf20Sopenharmony_ci * See i915_request_is_active() 718c2ecf20Sopenharmony_ci */ 728c2ecf20Sopenharmony_ci I915_FENCE_FLAG_ACTIVE = DMA_FENCE_FLAG_USER_BITS, 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_ci /* 758c2ecf20Sopenharmony_ci * I915_FENCE_FLAG_PQUEUE - this request is ready for execution 768c2ecf20Sopenharmony_ci * 778c2ecf20Sopenharmony_ci * Using the scheduler, when a request is ready for execution it is put 788c2ecf20Sopenharmony_ci * into the priority queue, and removed from that queue when transferred 798c2ecf20Sopenharmony_ci * to the HW runlists. We want to track its membership within the 808c2ecf20Sopenharmony_ci * priority queue so that we can easily check before rescheduling. 818c2ecf20Sopenharmony_ci * 828c2ecf20Sopenharmony_ci * See i915_request_in_priority_queue() 838c2ecf20Sopenharmony_ci */ 848c2ecf20Sopenharmony_ci I915_FENCE_FLAG_PQUEUE, 858c2ecf20Sopenharmony_ci 868c2ecf20Sopenharmony_ci /* 878c2ecf20Sopenharmony_ci * I915_FENCE_FLAG_HOLD - this request is currently on hold 888c2ecf20Sopenharmony_ci * 898c2ecf20Sopenharmony_ci * This request has been suspended, pending an ongoing investigation. 908c2ecf20Sopenharmony_ci */ 918c2ecf20Sopenharmony_ci I915_FENCE_FLAG_HOLD, 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_ci /* 948c2ecf20Sopenharmony_ci * I915_FENCE_FLAG_INITIAL_BREADCRUMB - this request has the initial 958c2ecf20Sopenharmony_ci * breadcrumb that marks the end of semaphore waits and start of the 968c2ecf20Sopenharmony_ci * user payload. 978c2ecf20Sopenharmony_ci */ 988c2ecf20Sopenharmony_ci I915_FENCE_FLAG_INITIAL_BREADCRUMB, 998c2ecf20Sopenharmony_ci 1008c2ecf20Sopenharmony_ci /* 1018c2ecf20Sopenharmony_ci * I915_FENCE_FLAG_SIGNAL - this request is currently on signal_list 1028c2ecf20Sopenharmony_ci * 1038c2ecf20Sopenharmony_ci * Internal bookkeeping used by the breadcrumb code to track when 1048c2ecf20Sopenharmony_ci * a request is on the various signal_list. 1058c2ecf20Sopenharmony_ci */ 1068c2ecf20Sopenharmony_ci I915_FENCE_FLAG_SIGNAL, 1078c2ecf20Sopenharmony_ci 1088c2ecf20Sopenharmony_ci /* 1098c2ecf20Sopenharmony_ci * I915_FENCE_FLAG_NOPREEMPT - this request should not be preempted 1108c2ecf20Sopenharmony_ci * 1118c2ecf20Sopenharmony_ci * The execution of some requests should not be interrupted. This is 1128c2ecf20Sopenharmony_ci * a sensitive operation as it makes the request super important, 1138c2ecf20Sopenharmony_ci * blocking other higher priority work. Abuse of this flag will 1148c2ecf20Sopenharmony_ci * lead to quality of service issues. 1158c2ecf20Sopenharmony_ci */ 1168c2ecf20Sopenharmony_ci I915_FENCE_FLAG_NOPREEMPT, 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_ci /* 1198c2ecf20Sopenharmony_ci * I915_FENCE_FLAG_SENTINEL - this request should be last in the queue 1208c2ecf20Sopenharmony_ci * 1218c2ecf20Sopenharmony_ci * A high priority sentinel request may be submitted to clear the 1228c2ecf20Sopenharmony_ci * submission queue. As it will be the only request in-flight, upon 1238c2ecf20Sopenharmony_ci * execution all other active requests will have been preempted and 1248c2ecf20Sopenharmony_ci * unsubmitted. This preemptive pulse is used to re-evaluate the 1258c2ecf20Sopenharmony_ci * in-flight requests, particularly in cases where an active context 1268c2ecf20Sopenharmony_ci * is banned and those active requests need to be cancelled. 1278c2ecf20Sopenharmony_ci */ 1288c2ecf20Sopenharmony_ci I915_FENCE_FLAG_SENTINEL, 1298c2ecf20Sopenharmony_ci 1308c2ecf20Sopenharmony_ci /* 1318c2ecf20Sopenharmony_ci * I915_FENCE_FLAG_BOOST - upclock the gpu for this request 1328c2ecf20Sopenharmony_ci * 1338c2ecf20Sopenharmony_ci * Some requests are more important than others! In particular, a 1348c2ecf20Sopenharmony_ci * request that the user is waiting on is typically required for 1358c2ecf20Sopenharmony_ci * interactive latency, for which we want to minimise by upclocking 1368c2ecf20Sopenharmony_ci * the GPU. Here we track such boost requests on a per-request basis. 1378c2ecf20Sopenharmony_ci */ 1388c2ecf20Sopenharmony_ci I915_FENCE_FLAG_BOOST, 1398c2ecf20Sopenharmony_ci}; 1408c2ecf20Sopenharmony_ci 1418c2ecf20Sopenharmony_ci/** 1428c2ecf20Sopenharmony_ci * Request queue structure. 1438c2ecf20Sopenharmony_ci * 1448c2ecf20Sopenharmony_ci * The request queue allows us to note sequence numbers that have been emitted 1458c2ecf20Sopenharmony_ci * and may be associated with active buffers to be retired. 1468c2ecf20Sopenharmony_ci * 1478c2ecf20Sopenharmony_ci * By keeping this list, we can avoid having to do questionable sequence 1488c2ecf20Sopenharmony_ci * number comparisons on buffer last_read|write_seqno. It also allows an 1498c2ecf20Sopenharmony_ci * emission time to be associated with the request for tracking how far ahead 1508c2ecf20Sopenharmony_ci * of the GPU the submission is. 1518c2ecf20Sopenharmony_ci * 1528c2ecf20Sopenharmony_ci * When modifying this structure be very aware that we perform a lockless 1538c2ecf20Sopenharmony_ci * RCU lookup of it that may race against reallocation of the struct 1548c2ecf20Sopenharmony_ci * from the slab freelist. We intentionally do not zero the structure on 1558c2ecf20Sopenharmony_ci * allocation so that the lookup can use the dangling pointers (and is 1568c2ecf20Sopenharmony_ci * cogniscent that those pointers may be wrong). Instead, everything that 1578c2ecf20Sopenharmony_ci * needs to be initialised must be done so explicitly. 1588c2ecf20Sopenharmony_ci * 1598c2ecf20Sopenharmony_ci * The requests are reference counted. 1608c2ecf20Sopenharmony_ci */ 1618c2ecf20Sopenharmony_cistruct i915_request { 1628c2ecf20Sopenharmony_ci struct dma_fence fence; 1638c2ecf20Sopenharmony_ci spinlock_t lock; 1648c2ecf20Sopenharmony_ci 1658c2ecf20Sopenharmony_ci /** 1668c2ecf20Sopenharmony_ci * Context and ring buffer related to this request 1678c2ecf20Sopenharmony_ci * Contexts are refcounted, so when this request is associated with a 1688c2ecf20Sopenharmony_ci * context, we must increment the context's refcount, to guarantee that 1698c2ecf20Sopenharmony_ci * it persists while any request is linked to it. Requests themselves 1708c2ecf20Sopenharmony_ci * are also refcounted, so the request will only be freed when the last 1718c2ecf20Sopenharmony_ci * reference to it is dismissed, and the code in 1728c2ecf20Sopenharmony_ci * i915_request_free() will then decrement the refcount on the 1738c2ecf20Sopenharmony_ci * context. 1748c2ecf20Sopenharmony_ci */ 1758c2ecf20Sopenharmony_ci struct intel_engine_cs *engine; 1768c2ecf20Sopenharmony_ci struct intel_context *context; 1778c2ecf20Sopenharmony_ci struct intel_ring *ring; 1788c2ecf20Sopenharmony_ci struct intel_timeline __rcu *timeline; 1798c2ecf20Sopenharmony_ci 1808c2ecf20Sopenharmony_ci struct list_head signal_link; 1818c2ecf20Sopenharmony_ci struct llist_node signal_node; 1828c2ecf20Sopenharmony_ci 1838c2ecf20Sopenharmony_ci /* 1848c2ecf20Sopenharmony_ci * The rcu epoch of when this request was allocated. Used to judiciously 1858c2ecf20Sopenharmony_ci * apply backpressure on future allocations to ensure that under 1868c2ecf20Sopenharmony_ci * mempressure there is sufficient RCU ticks for us to reclaim our 1878c2ecf20Sopenharmony_ci * RCU protected slabs. 1888c2ecf20Sopenharmony_ci */ 1898c2ecf20Sopenharmony_ci unsigned long rcustate; 1908c2ecf20Sopenharmony_ci 1918c2ecf20Sopenharmony_ci /* 1928c2ecf20Sopenharmony_ci * We pin the timeline->mutex while constructing the request to 1938c2ecf20Sopenharmony_ci * ensure that no caller accidentally drops it during construction. 1948c2ecf20Sopenharmony_ci * The timeline->mutex must be held to ensure that only this caller 1958c2ecf20Sopenharmony_ci * can use the ring and manipulate the associated timeline during 1968c2ecf20Sopenharmony_ci * construction. 1978c2ecf20Sopenharmony_ci */ 1988c2ecf20Sopenharmony_ci struct pin_cookie cookie; 1998c2ecf20Sopenharmony_ci 2008c2ecf20Sopenharmony_ci /* 2018c2ecf20Sopenharmony_ci * Fences for the various phases in the request's lifetime. 2028c2ecf20Sopenharmony_ci * 2038c2ecf20Sopenharmony_ci * The submit fence is used to await upon all of the request's 2048c2ecf20Sopenharmony_ci * dependencies. When it is signaled, the request is ready to run. 2058c2ecf20Sopenharmony_ci * It is used by the driver to then queue the request for execution. 2068c2ecf20Sopenharmony_ci */ 2078c2ecf20Sopenharmony_ci struct i915_sw_fence submit; 2088c2ecf20Sopenharmony_ci union { 2098c2ecf20Sopenharmony_ci wait_queue_entry_t submitq; 2108c2ecf20Sopenharmony_ci struct i915_sw_dma_fence_cb dmaq; 2118c2ecf20Sopenharmony_ci struct i915_request_duration_cb { 2128c2ecf20Sopenharmony_ci struct dma_fence_cb cb; 2138c2ecf20Sopenharmony_ci ktime_t emitted; 2148c2ecf20Sopenharmony_ci } duration; 2158c2ecf20Sopenharmony_ci }; 2168c2ecf20Sopenharmony_ci struct llist_head execute_cb; 2178c2ecf20Sopenharmony_ci struct i915_sw_fence semaphore; 2188c2ecf20Sopenharmony_ci 2198c2ecf20Sopenharmony_ci /* 2208c2ecf20Sopenharmony_ci * A list of everyone we wait upon, and everyone who waits upon us. 2218c2ecf20Sopenharmony_ci * Even though we will not be submitted to the hardware before the 2228c2ecf20Sopenharmony_ci * submit fence is signaled (it waits for all external events as well 2238c2ecf20Sopenharmony_ci * as our own requests), the scheduler still needs to know the 2248c2ecf20Sopenharmony_ci * dependency tree for the lifetime of the request (from execbuf 2258c2ecf20Sopenharmony_ci * to retirement), i.e. bidirectional dependency information for the 2268c2ecf20Sopenharmony_ci * request not tied to individual fences. 2278c2ecf20Sopenharmony_ci */ 2288c2ecf20Sopenharmony_ci struct i915_sched_node sched; 2298c2ecf20Sopenharmony_ci struct i915_dependency dep; 2308c2ecf20Sopenharmony_ci intel_engine_mask_t execution_mask; 2318c2ecf20Sopenharmony_ci 2328c2ecf20Sopenharmony_ci /* 2338c2ecf20Sopenharmony_ci * A convenience pointer to the current breadcrumb value stored in 2348c2ecf20Sopenharmony_ci * the HW status page (or our timeline's local equivalent). The full 2358c2ecf20Sopenharmony_ci * path would be rq->hw_context->ring->timeline->hwsp_seqno. 2368c2ecf20Sopenharmony_ci */ 2378c2ecf20Sopenharmony_ci const u32 *hwsp_seqno; 2388c2ecf20Sopenharmony_ci 2398c2ecf20Sopenharmony_ci /* 2408c2ecf20Sopenharmony_ci * If we need to access the timeline's seqno for this request in 2418c2ecf20Sopenharmony_ci * another request, we need to keep a read reference to this associated 2428c2ecf20Sopenharmony_ci * cacheline, so that we do not free and recycle it before the foreign 2438c2ecf20Sopenharmony_ci * observers have completed. Hence, we keep a pointer to the cacheline 2448c2ecf20Sopenharmony_ci * inside the timeline's HWSP vma, but it is only valid while this 2458c2ecf20Sopenharmony_ci * request has not completed and guarded by the timeline mutex. 2468c2ecf20Sopenharmony_ci */ 2478c2ecf20Sopenharmony_ci struct intel_timeline_cacheline __rcu *hwsp_cacheline; 2488c2ecf20Sopenharmony_ci 2498c2ecf20Sopenharmony_ci /** Position in the ring of the start of the request */ 2508c2ecf20Sopenharmony_ci u32 head; 2518c2ecf20Sopenharmony_ci 2528c2ecf20Sopenharmony_ci /** Position in the ring of the start of the user packets */ 2538c2ecf20Sopenharmony_ci u32 infix; 2548c2ecf20Sopenharmony_ci 2558c2ecf20Sopenharmony_ci /** 2568c2ecf20Sopenharmony_ci * Position in the ring of the start of the postfix. 2578c2ecf20Sopenharmony_ci * This is required to calculate the maximum available ring space 2588c2ecf20Sopenharmony_ci * without overwriting the postfix. 2598c2ecf20Sopenharmony_ci */ 2608c2ecf20Sopenharmony_ci u32 postfix; 2618c2ecf20Sopenharmony_ci 2628c2ecf20Sopenharmony_ci /** Position in the ring of the end of the whole request */ 2638c2ecf20Sopenharmony_ci u32 tail; 2648c2ecf20Sopenharmony_ci 2658c2ecf20Sopenharmony_ci /** Position in the ring of the end of any workarounds after the tail */ 2668c2ecf20Sopenharmony_ci u32 wa_tail; 2678c2ecf20Sopenharmony_ci 2688c2ecf20Sopenharmony_ci /** Preallocate space in the ring for the emitting the request */ 2698c2ecf20Sopenharmony_ci u32 reserved_space; 2708c2ecf20Sopenharmony_ci 2718c2ecf20Sopenharmony_ci /** Batch buffer related to this request if any (used for 2728c2ecf20Sopenharmony_ci * error state dump only). 2738c2ecf20Sopenharmony_ci */ 2748c2ecf20Sopenharmony_ci struct i915_vma *batch; 2758c2ecf20Sopenharmony_ci /** 2768c2ecf20Sopenharmony_ci * Additional buffers requested by userspace to be captured upon 2778c2ecf20Sopenharmony_ci * a GPU hang. The vma/obj on this list are protected by their 2788c2ecf20Sopenharmony_ci * active reference - all objects on this list must also be 2798c2ecf20Sopenharmony_ci * on the active_list (of their final request). 2808c2ecf20Sopenharmony_ci */ 2818c2ecf20Sopenharmony_ci struct i915_capture_list *capture_list; 2828c2ecf20Sopenharmony_ci 2838c2ecf20Sopenharmony_ci /** Time at which this request was emitted, in jiffies. */ 2848c2ecf20Sopenharmony_ci unsigned long emitted_jiffies; 2858c2ecf20Sopenharmony_ci 2868c2ecf20Sopenharmony_ci /** timeline->request entry for this request */ 2878c2ecf20Sopenharmony_ci struct list_head link; 2888c2ecf20Sopenharmony_ci 2898c2ecf20Sopenharmony_ci I915_SELFTEST_DECLARE(struct { 2908c2ecf20Sopenharmony_ci struct list_head link; 2918c2ecf20Sopenharmony_ci unsigned long delay; 2928c2ecf20Sopenharmony_ci } mock;) 2938c2ecf20Sopenharmony_ci}; 2948c2ecf20Sopenharmony_ci 2958c2ecf20Sopenharmony_ci#define I915_FENCE_GFP (GFP_KERNEL | __GFP_RETRY_MAYFAIL | __GFP_NOWARN) 2968c2ecf20Sopenharmony_ci 2978c2ecf20Sopenharmony_ciextern const struct dma_fence_ops i915_fence_ops; 2988c2ecf20Sopenharmony_ci 2998c2ecf20Sopenharmony_cistatic inline bool dma_fence_is_i915(const struct dma_fence *fence) 3008c2ecf20Sopenharmony_ci{ 3018c2ecf20Sopenharmony_ci return fence->ops == &i915_fence_ops; 3028c2ecf20Sopenharmony_ci} 3038c2ecf20Sopenharmony_ci 3048c2ecf20Sopenharmony_cistruct kmem_cache *i915_request_slab_cache(void); 3058c2ecf20Sopenharmony_ci 3068c2ecf20Sopenharmony_cistruct i915_request * __must_check 3078c2ecf20Sopenharmony_ci__i915_request_create(struct intel_context *ce, gfp_t gfp); 3088c2ecf20Sopenharmony_cistruct i915_request * __must_check 3098c2ecf20Sopenharmony_cii915_request_create(struct intel_context *ce); 3108c2ecf20Sopenharmony_ci 3118c2ecf20Sopenharmony_civoid i915_request_set_error_once(struct i915_request *rq, int error); 3128c2ecf20Sopenharmony_civoid __i915_request_skip(struct i915_request *rq); 3138c2ecf20Sopenharmony_ci 3148c2ecf20Sopenharmony_cistruct i915_request *__i915_request_commit(struct i915_request *request); 3158c2ecf20Sopenharmony_civoid __i915_request_queue(struct i915_request *rq, 3168c2ecf20Sopenharmony_ci const struct i915_sched_attr *attr); 3178c2ecf20Sopenharmony_ci 3188c2ecf20Sopenharmony_cibool i915_request_retire(struct i915_request *rq); 3198c2ecf20Sopenharmony_civoid i915_request_retire_upto(struct i915_request *rq); 3208c2ecf20Sopenharmony_ci 3218c2ecf20Sopenharmony_cistatic inline struct i915_request * 3228c2ecf20Sopenharmony_cito_request(struct dma_fence *fence) 3238c2ecf20Sopenharmony_ci{ 3248c2ecf20Sopenharmony_ci /* We assume that NULL fence/request are interoperable */ 3258c2ecf20Sopenharmony_ci BUILD_BUG_ON(offsetof(struct i915_request, fence) != 0); 3268c2ecf20Sopenharmony_ci GEM_BUG_ON(fence && !dma_fence_is_i915(fence)); 3278c2ecf20Sopenharmony_ci return container_of(fence, struct i915_request, fence); 3288c2ecf20Sopenharmony_ci} 3298c2ecf20Sopenharmony_ci 3308c2ecf20Sopenharmony_cistatic inline struct i915_request * 3318c2ecf20Sopenharmony_cii915_request_get(struct i915_request *rq) 3328c2ecf20Sopenharmony_ci{ 3338c2ecf20Sopenharmony_ci return to_request(dma_fence_get(&rq->fence)); 3348c2ecf20Sopenharmony_ci} 3358c2ecf20Sopenharmony_ci 3368c2ecf20Sopenharmony_cistatic inline struct i915_request * 3378c2ecf20Sopenharmony_cii915_request_get_rcu(struct i915_request *rq) 3388c2ecf20Sopenharmony_ci{ 3398c2ecf20Sopenharmony_ci return to_request(dma_fence_get_rcu(&rq->fence)); 3408c2ecf20Sopenharmony_ci} 3418c2ecf20Sopenharmony_ci 3428c2ecf20Sopenharmony_cistatic inline void 3438c2ecf20Sopenharmony_cii915_request_put(struct i915_request *rq) 3448c2ecf20Sopenharmony_ci{ 3458c2ecf20Sopenharmony_ci dma_fence_put(&rq->fence); 3468c2ecf20Sopenharmony_ci} 3478c2ecf20Sopenharmony_ci 3488c2ecf20Sopenharmony_ciint i915_request_await_object(struct i915_request *to, 3498c2ecf20Sopenharmony_ci struct drm_i915_gem_object *obj, 3508c2ecf20Sopenharmony_ci bool write); 3518c2ecf20Sopenharmony_ciint i915_request_await_dma_fence(struct i915_request *rq, 3528c2ecf20Sopenharmony_ci struct dma_fence *fence); 3538c2ecf20Sopenharmony_ciint i915_request_await_execution(struct i915_request *rq, 3548c2ecf20Sopenharmony_ci struct dma_fence *fence, 3558c2ecf20Sopenharmony_ci void (*hook)(struct i915_request *rq, 3568c2ecf20Sopenharmony_ci struct dma_fence *signal)); 3578c2ecf20Sopenharmony_ci 3588c2ecf20Sopenharmony_civoid i915_request_add(struct i915_request *rq); 3598c2ecf20Sopenharmony_ci 3608c2ecf20Sopenharmony_cibool __i915_request_submit(struct i915_request *request); 3618c2ecf20Sopenharmony_civoid i915_request_submit(struct i915_request *request); 3628c2ecf20Sopenharmony_ci 3638c2ecf20Sopenharmony_civoid __i915_request_unsubmit(struct i915_request *request); 3648c2ecf20Sopenharmony_civoid i915_request_unsubmit(struct i915_request *request); 3658c2ecf20Sopenharmony_ci 3668c2ecf20Sopenharmony_cilong i915_request_wait(struct i915_request *rq, 3678c2ecf20Sopenharmony_ci unsigned int flags, 3688c2ecf20Sopenharmony_ci long timeout) 3698c2ecf20Sopenharmony_ci __attribute__((nonnull(1))); 3708c2ecf20Sopenharmony_ci#define I915_WAIT_INTERRUPTIBLE BIT(0) 3718c2ecf20Sopenharmony_ci#define I915_WAIT_PRIORITY BIT(1) /* small priority bump for the request */ 3728c2ecf20Sopenharmony_ci#define I915_WAIT_ALL BIT(2) /* used by i915_gem_object_wait() */ 3738c2ecf20Sopenharmony_ci 3748c2ecf20Sopenharmony_cistatic inline bool i915_request_signaled(const struct i915_request *rq) 3758c2ecf20Sopenharmony_ci{ 3768c2ecf20Sopenharmony_ci /* The request may live longer than its HWSP, so check flags first! */ 3778c2ecf20Sopenharmony_ci return test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &rq->fence.flags); 3788c2ecf20Sopenharmony_ci} 3798c2ecf20Sopenharmony_ci 3808c2ecf20Sopenharmony_cistatic inline bool i915_request_is_active(const struct i915_request *rq) 3818c2ecf20Sopenharmony_ci{ 3828c2ecf20Sopenharmony_ci return test_bit(I915_FENCE_FLAG_ACTIVE, &rq->fence.flags); 3838c2ecf20Sopenharmony_ci} 3848c2ecf20Sopenharmony_ci 3858c2ecf20Sopenharmony_cistatic inline bool i915_request_in_priority_queue(const struct i915_request *rq) 3868c2ecf20Sopenharmony_ci{ 3878c2ecf20Sopenharmony_ci return test_bit(I915_FENCE_FLAG_PQUEUE, &rq->fence.flags); 3888c2ecf20Sopenharmony_ci} 3898c2ecf20Sopenharmony_ci 3908c2ecf20Sopenharmony_cistatic inline bool 3918c2ecf20Sopenharmony_cii915_request_has_initial_breadcrumb(const struct i915_request *rq) 3928c2ecf20Sopenharmony_ci{ 3938c2ecf20Sopenharmony_ci return test_bit(I915_FENCE_FLAG_INITIAL_BREADCRUMB, &rq->fence.flags); 3948c2ecf20Sopenharmony_ci} 3958c2ecf20Sopenharmony_ci 3968c2ecf20Sopenharmony_ci/** 3978c2ecf20Sopenharmony_ci * Returns true if seq1 is later than seq2. 3988c2ecf20Sopenharmony_ci */ 3998c2ecf20Sopenharmony_cistatic inline bool i915_seqno_passed(u32 seq1, u32 seq2) 4008c2ecf20Sopenharmony_ci{ 4018c2ecf20Sopenharmony_ci return (s32)(seq1 - seq2) >= 0; 4028c2ecf20Sopenharmony_ci} 4038c2ecf20Sopenharmony_ci 4048c2ecf20Sopenharmony_cistatic inline u32 __hwsp_seqno(const struct i915_request *rq) 4058c2ecf20Sopenharmony_ci{ 4068c2ecf20Sopenharmony_ci const u32 *hwsp = READ_ONCE(rq->hwsp_seqno); 4078c2ecf20Sopenharmony_ci 4088c2ecf20Sopenharmony_ci return READ_ONCE(*hwsp); 4098c2ecf20Sopenharmony_ci} 4108c2ecf20Sopenharmony_ci 4118c2ecf20Sopenharmony_ci/** 4128c2ecf20Sopenharmony_ci * hwsp_seqno - the current breadcrumb value in the HW status page 4138c2ecf20Sopenharmony_ci * @rq: the request, to chase the relevant HW status page 4148c2ecf20Sopenharmony_ci * 4158c2ecf20Sopenharmony_ci * The emphasis in naming here is that hwsp_seqno() is not a property of the 4168c2ecf20Sopenharmony_ci * request, but an indication of the current HW state (associated with this 4178c2ecf20Sopenharmony_ci * request). Its value will change as the GPU executes more requests. 4188c2ecf20Sopenharmony_ci * 4198c2ecf20Sopenharmony_ci * Returns the current breadcrumb value in the associated HW status page (or 4208c2ecf20Sopenharmony_ci * the local timeline's equivalent) for this request. The request itself 4218c2ecf20Sopenharmony_ci * has the associated breadcrumb value of rq->fence.seqno, when the HW 4228c2ecf20Sopenharmony_ci * status page has that breadcrumb or later, this request is complete. 4238c2ecf20Sopenharmony_ci */ 4248c2ecf20Sopenharmony_cistatic inline u32 hwsp_seqno(const struct i915_request *rq) 4258c2ecf20Sopenharmony_ci{ 4268c2ecf20Sopenharmony_ci u32 seqno; 4278c2ecf20Sopenharmony_ci 4288c2ecf20Sopenharmony_ci rcu_read_lock(); /* the HWSP may be freed at runtime */ 4298c2ecf20Sopenharmony_ci seqno = __hwsp_seqno(rq); 4308c2ecf20Sopenharmony_ci rcu_read_unlock(); 4318c2ecf20Sopenharmony_ci 4328c2ecf20Sopenharmony_ci return seqno; 4338c2ecf20Sopenharmony_ci} 4348c2ecf20Sopenharmony_ci 4358c2ecf20Sopenharmony_cistatic inline bool __i915_request_has_started(const struct i915_request *rq) 4368c2ecf20Sopenharmony_ci{ 4378c2ecf20Sopenharmony_ci return i915_seqno_passed(__hwsp_seqno(rq), rq->fence.seqno - 1); 4388c2ecf20Sopenharmony_ci} 4398c2ecf20Sopenharmony_ci 4408c2ecf20Sopenharmony_ci/** 4418c2ecf20Sopenharmony_ci * i915_request_started - check if the request has begun being executed 4428c2ecf20Sopenharmony_ci * @rq: the request 4438c2ecf20Sopenharmony_ci * 4448c2ecf20Sopenharmony_ci * If the timeline is not using initial breadcrumbs, a request is 4458c2ecf20Sopenharmony_ci * considered started if the previous request on its timeline (i.e. 4468c2ecf20Sopenharmony_ci * context) has been signaled. 4478c2ecf20Sopenharmony_ci * 4488c2ecf20Sopenharmony_ci * If the timeline is using semaphores, it will also be emitting an 4498c2ecf20Sopenharmony_ci * "initial breadcrumb" after the semaphores are complete and just before 4508c2ecf20Sopenharmony_ci * it began executing the user payload. A request can therefore be active 4518c2ecf20Sopenharmony_ci * on the HW and not yet started as it is still busywaiting on its 4528c2ecf20Sopenharmony_ci * dependencies (via HW semaphores). 4538c2ecf20Sopenharmony_ci * 4548c2ecf20Sopenharmony_ci * If the request has started, its dependencies will have been signaled 4558c2ecf20Sopenharmony_ci * (either by fences or by semaphores) and it will have begun processing 4568c2ecf20Sopenharmony_ci * the user payload. 4578c2ecf20Sopenharmony_ci * 4588c2ecf20Sopenharmony_ci * However, even if a request has started, it may have been preempted and 4598c2ecf20Sopenharmony_ci * so no longer active, or it may have already completed. 4608c2ecf20Sopenharmony_ci * 4618c2ecf20Sopenharmony_ci * See also i915_request_is_active(). 4628c2ecf20Sopenharmony_ci * 4638c2ecf20Sopenharmony_ci * Returns true if the request has begun executing the user payload, or 4648c2ecf20Sopenharmony_ci * has completed: 4658c2ecf20Sopenharmony_ci */ 4668c2ecf20Sopenharmony_cistatic inline bool i915_request_started(const struct i915_request *rq) 4678c2ecf20Sopenharmony_ci{ 4688c2ecf20Sopenharmony_ci bool result; 4698c2ecf20Sopenharmony_ci 4708c2ecf20Sopenharmony_ci if (i915_request_signaled(rq)) 4718c2ecf20Sopenharmony_ci return true; 4728c2ecf20Sopenharmony_ci 4738c2ecf20Sopenharmony_ci result = true; 4748c2ecf20Sopenharmony_ci rcu_read_lock(); /* the HWSP may be freed at runtime */ 4758c2ecf20Sopenharmony_ci if (likely(!i915_request_signaled(rq))) 4768c2ecf20Sopenharmony_ci /* Remember: started but may have since been preempted! */ 4778c2ecf20Sopenharmony_ci result = __i915_request_has_started(rq); 4788c2ecf20Sopenharmony_ci rcu_read_unlock(); 4798c2ecf20Sopenharmony_ci 4808c2ecf20Sopenharmony_ci return result; 4818c2ecf20Sopenharmony_ci} 4828c2ecf20Sopenharmony_ci 4838c2ecf20Sopenharmony_ci/** 4848c2ecf20Sopenharmony_ci * i915_request_is_running - check if the request may actually be executing 4858c2ecf20Sopenharmony_ci * @rq: the request 4868c2ecf20Sopenharmony_ci * 4878c2ecf20Sopenharmony_ci * Returns true if the request is currently submitted to hardware, has passed 4888c2ecf20Sopenharmony_ci * its start point (i.e. the context is setup and not busywaiting). Note that 4898c2ecf20Sopenharmony_ci * it may no longer be running by the time the function returns! 4908c2ecf20Sopenharmony_ci */ 4918c2ecf20Sopenharmony_cistatic inline bool i915_request_is_running(const struct i915_request *rq) 4928c2ecf20Sopenharmony_ci{ 4938c2ecf20Sopenharmony_ci bool result; 4948c2ecf20Sopenharmony_ci 4958c2ecf20Sopenharmony_ci if (!i915_request_is_active(rq)) 4968c2ecf20Sopenharmony_ci return false; 4978c2ecf20Sopenharmony_ci 4988c2ecf20Sopenharmony_ci rcu_read_lock(); 4998c2ecf20Sopenharmony_ci result = __i915_request_has_started(rq) && i915_request_is_active(rq); 5008c2ecf20Sopenharmony_ci rcu_read_unlock(); 5018c2ecf20Sopenharmony_ci 5028c2ecf20Sopenharmony_ci return result; 5038c2ecf20Sopenharmony_ci} 5048c2ecf20Sopenharmony_ci 5058c2ecf20Sopenharmony_ci/** 5068c2ecf20Sopenharmony_ci * i915_request_is_ready - check if the request is ready for execution 5078c2ecf20Sopenharmony_ci * @rq: the request 5088c2ecf20Sopenharmony_ci * 5098c2ecf20Sopenharmony_ci * Upon construction, the request is instructed to wait upon various 5108c2ecf20Sopenharmony_ci * signals before it is ready to be executed by the HW. That is, we do 5118c2ecf20Sopenharmony_ci * not want to start execution and read data before it is written. In practice, 5128c2ecf20Sopenharmony_ci * this is controlled with a mixture of interrupts and semaphores. Once 5138c2ecf20Sopenharmony_ci * the submit fence is completed, the backend scheduler will place the 5148c2ecf20Sopenharmony_ci * request into its queue and from there submit it for execution. So we 5158c2ecf20Sopenharmony_ci * can detect when a request is eligible for execution (and is under control 5168c2ecf20Sopenharmony_ci * of the scheduler) by querying where it is in any of the scheduler's lists. 5178c2ecf20Sopenharmony_ci * 5188c2ecf20Sopenharmony_ci * Returns true if the request is ready for execution (it may be inflight), 5198c2ecf20Sopenharmony_ci * false otherwise. 5208c2ecf20Sopenharmony_ci */ 5218c2ecf20Sopenharmony_cistatic inline bool i915_request_is_ready(const struct i915_request *rq) 5228c2ecf20Sopenharmony_ci{ 5238c2ecf20Sopenharmony_ci return !list_empty(&rq->sched.link); 5248c2ecf20Sopenharmony_ci} 5258c2ecf20Sopenharmony_ci 5268c2ecf20Sopenharmony_cistatic inline bool __i915_request_is_complete(const struct i915_request *rq) 5278c2ecf20Sopenharmony_ci{ 5288c2ecf20Sopenharmony_ci return i915_seqno_passed(__hwsp_seqno(rq), rq->fence.seqno); 5298c2ecf20Sopenharmony_ci} 5308c2ecf20Sopenharmony_ci 5318c2ecf20Sopenharmony_cistatic inline bool i915_request_completed(const struct i915_request *rq) 5328c2ecf20Sopenharmony_ci{ 5338c2ecf20Sopenharmony_ci bool result; 5348c2ecf20Sopenharmony_ci 5358c2ecf20Sopenharmony_ci if (i915_request_signaled(rq)) 5368c2ecf20Sopenharmony_ci return true; 5378c2ecf20Sopenharmony_ci 5388c2ecf20Sopenharmony_ci result = true; 5398c2ecf20Sopenharmony_ci rcu_read_lock(); /* the HWSP may be freed at runtime */ 5408c2ecf20Sopenharmony_ci if (likely(!i915_request_signaled(rq))) 5418c2ecf20Sopenharmony_ci result = __i915_request_is_complete(rq); 5428c2ecf20Sopenharmony_ci rcu_read_unlock(); 5438c2ecf20Sopenharmony_ci 5448c2ecf20Sopenharmony_ci return result; 5458c2ecf20Sopenharmony_ci} 5468c2ecf20Sopenharmony_ci 5478c2ecf20Sopenharmony_cistatic inline void i915_request_mark_complete(struct i915_request *rq) 5488c2ecf20Sopenharmony_ci{ 5498c2ecf20Sopenharmony_ci WRITE_ONCE(rq->hwsp_seqno, /* decouple from HWSP */ 5508c2ecf20Sopenharmony_ci (u32 *)&rq->fence.seqno); 5518c2ecf20Sopenharmony_ci} 5528c2ecf20Sopenharmony_ci 5538c2ecf20Sopenharmony_cistatic inline bool i915_request_has_waitboost(const struct i915_request *rq) 5548c2ecf20Sopenharmony_ci{ 5558c2ecf20Sopenharmony_ci return test_bit(I915_FENCE_FLAG_BOOST, &rq->fence.flags); 5568c2ecf20Sopenharmony_ci} 5578c2ecf20Sopenharmony_ci 5588c2ecf20Sopenharmony_cistatic inline bool i915_request_has_nopreempt(const struct i915_request *rq) 5598c2ecf20Sopenharmony_ci{ 5608c2ecf20Sopenharmony_ci /* Preemption should only be disabled very rarely */ 5618c2ecf20Sopenharmony_ci return unlikely(test_bit(I915_FENCE_FLAG_NOPREEMPT, &rq->fence.flags)); 5628c2ecf20Sopenharmony_ci} 5638c2ecf20Sopenharmony_ci 5648c2ecf20Sopenharmony_cistatic inline bool i915_request_has_sentinel(const struct i915_request *rq) 5658c2ecf20Sopenharmony_ci{ 5668c2ecf20Sopenharmony_ci return unlikely(test_bit(I915_FENCE_FLAG_SENTINEL, &rq->fence.flags)); 5678c2ecf20Sopenharmony_ci} 5688c2ecf20Sopenharmony_ci 5698c2ecf20Sopenharmony_cistatic inline bool i915_request_on_hold(const struct i915_request *rq) 5708c2ecf20Sopenharmony_ci{ 5718c2ecf20Sopenharmony_ci return unlikely(test_bit(I915_FENCE_FLAG_HOLD, &rq->fence.flags)); 5728c2ecf20Sopenharmony_ci} 5738c2ecf20Sopenharmony_ci 5748c2ecf20Sopenharmony_cistatic inline void i915_request_set_hold(struct i915_request *rq) 5758c2ecf20Sopenharmony_ci{ 5768c2ecf20Sopenharmony_ci set_bit(I915_FENCE_FLAG_HOLD, &rq->fence.flags); 5778c2ecf20Sopenharmony_ci} 5788c2ecf20Sopenharmony_ci 5798c2ecf20Sopenharmony_cistatic inline void i915_request_clear_hold(struct i915_request *rq) 5808c2ecf20Sopenharmony_ci{ 5818c2ecf20Sopenharmony_ci clear_bit(I915_FENCE_FLAG_HOLD, &rq->fence.flags); 5828c2ecf20Sopenharmony_ci} 5838c2ecf20Sopenharmony_ci 5848c2ecf20Sopenharmony_cistatic inline struct intel_timeline * 5858c2ecf20Sopenharmony_cii915_request_timeline(const struct i915_request *rq) 5868c2ecf20Sopenharmony_ci{ 5878c2ecf20Sopenharmony_ci /* Valid only while the request is being constructed (or retired). */ 5888c2ecf20Sopenharmony_ci return rcu_dereference_protected(rq->timeline, 5898c2ecf20Sopenharmony_ci lockdep_is_held(&rcu_access_pointer(rq->timeline)->mutex)); 5908c2ecf20Sopenharmony_ci} 5918c2ecf20Sopenharmony_ci 5928c2ecf20Sopenharmony_cistatic inline struct i915_gem_context * 5938c2ecf20Sopenharmony_cii915_request_gem_context(const struct i915_request *rq) 5948c2ecf20Sopenharmony_ci{ 5958c2ecf20Sopenharmony_ci /* Valid only while the request is being constructed (or retired). */ 5968c2ecf20Sopenharmony_ci return rcu_dereference_protected(rq->context->gem_context, true); 5978c2ecf20Sopenharmony_ci} 5988c2ecf20Sopenharmony_ci 5998c2ecf20Sopenharmony_cistatic inline struct intel_timeline * 6008c2ecf20Sopenharmony_cii915_request_active_timeline(const struct i915_request *rq) 6018c2ecf20Sopenharmony_ci{ 6028c2ecf20Sopenharmony_ci /* 6038c2ecf20Sopenharmony_ci * When in use during submission, we are protected by a guarantee that 6048c2ecf20Sopenharmony_ci * the context/timeline is pinned and must remain pinned until after 6058c2ecf20Sopenharmony_ci * this submission. 6068c2ecf20Sopenharmony_ci */ 6078c2ecf20Sopenharmony_ci return rcu_dereference_protected(rq->timeline, 6088c2ecf20Sopenharmony_ci lockdep_is_held(&rq->engine->active.lock)); 6098c2ecf20Sopenharmony_ci} 6108c2ecf20Sopenharmony_ci 6118c2ecf20Sopenharmony_ci#endif /* I915_REQUEST_H */ 612