187df8fc6SFrançois Tigeot /* 287df8fc6SFrançois Tigeot * Copyright © 2008-2015 Intel Corporation 387df8fc6SFrançois Tigeot * 487df8fc6SFrançois Tigeot * Permission is hereby granted, free of charge, to any person obtaining a 587df8fc6SFrançois Tigeot * copy of this software and associated documentation files (the "Software"), 687df8fc6SFrançois Tigeot * to deal in the Software without restriction, including without limitation 787df8fc6SFrançois Tigeot * the rights to use, copy, modify, merge, publish, distribute, sublicense, 887df8fc6SFrançois Tigeot * and/or sell copies of the Software, and to permit persons to whom the 987df8fc6SFrançois Tigeot * Software is furnished to do so, subject to the following conditions: 1087df8fc6SFrançois Tigeot * 1187df8fc6SFrançois Tigeot * The above copyright notice and this permission notice (including the next 1287df8fc6SFrançois Tigeot * paragraph) shall be included in all copies or substantial portions of the 1387df8fc6SFrançois Tigeot * Software. 1487df8fc6SFrançois Tigeot * 1587df8fc6SFrançois Tigeot * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1687df8fc6SFrançois Tigeot * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1787df8fc6SFrançois Tigeot * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 1887df8fc6SFrançois Tigeot * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 1987df8fc6SFrançois Tigeot * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 2087df8fc6SFrançois Tigeot * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 2187df8fc6SFrançois Tigeot * IN THE SOFTWARE. 2287df8fc6SFrançois Tigeot * 2387df8fc6SFrançois Tigeot */ 2487df8fc6SFrançois Tigeot 2587df8fc6SFrançois Tigeot #ifndef I915_GEM_REQUEST_H 2687df8fc6SFrançois Tigeot #define I915_GEM_REQUEST_H 2787df8fc6SFrançois Tigeot 28*6559babbSFrançois Tigeot #include <linux/dma-fence.h> 2987df8fc6SFrançois Tigeot 3087df8fc6SFrançois Tigeot #include "i915_gem.h" 311e12ee3bSFrançois Tigeot #include "i915_sw_fence.h" 3287df8fc6SFrançois Tigeot 3371f41f3eSFrançois Tigeot struct intel_wait { 3471f41f3eSFrançois Tigeot struct rb_node node; 3571f41f3eSFrançois Tigeot struct task_struct *tsk; 3671f41f3eSFrançois Tigeot u32 seqno; 3771f41f3eSFrançois Tigeot }; 3871f41f3eSFrançois Tigeot 3971f41f3eSFrançois Tigeot struct intel_signal_node { 4071f41f3eSFrançois Tigeot struct rb_node node; 4171f41f3eSFrançois Tigeot struct intel_wait wait; 4271f41f3eSFrançois Tigeot }; 4371f41f3eSFrançois Tigeot 4487df8fc6SFrançois Tigeot /** 4587df8fc6SFrançois Tigeot * Request queue structure. 4687df8fc6SFrançois Tigeot * 4787df8fc6SFrançois Tigeot * The request queue allows us to note sequence numbers that have been emitted 4887df8fc6SFrançois Tigeot * and may be associated with active buffers to be retired. 4987df8fc6SFrançois Tigeot * 5087df8fc6SFrançois Tigeot * By keeping this list, we can avoid having to do questionable sequence 5187df8fc6SFrançois Tigeot * number comparisons on buffer last_read|write_seqno. It also allows an 5287df8fc6SFrançois Tigeot * emission time to be associated with the request for tracking how far ahead 5387df8fc6SFrançois Tigeot * of the GPU the submission is. 5487df8fc6SFrançois Tigeot * 5571f41f3eSFrançois Tigeot * When modifying this structure be very aware that we perform a lockless 5671f41f3eSFrançois Tigeot * RCU lookup of it that may race against reallocation of the struct 5771f41f3eSFrançois Tigeot * from the slab freelist. We intentionally do not zero the structure on 5871f41f3eSFrançois Tigeot * allocation so that the lookup can use the dangling pointers (and is 5971f41f3eSFrançois Tigeot * cogniscent that those pointers may be wrong). Instead, everything that 6071f41f3eSFrançois Tigeot * needs to be initialised must be done so explicitly. 6171f41f3eSFrançois Tigeot * 6287df8fc6SFrançois Tigeot * The requests are reference counted. 6387df8fc6SFrançois Tigeot */ 6487df8fc6SFrançois Tigeot struct drm_i915_gem_request { 65*6559babbSFrançois Tigeot struct dma_fence fence; 66*6559babbSFrançois Tigeot spinlock_t lock; 6787df8fc6SFrançois Tigeot 6887df8fc6SFrançois Tigeot /** On Which ring this request was generated */ 6987df8fc6SFrançois Tigeot struct drm_i915_private *i915; 7087df8fc6SFrançois Tigeot 7187df8fc6SFrançois Tigeot /** 7287df8fc6SFrançois Tigeot * Context and ring buffer related to this request 7387df8fc6SFrançois Tigeot * Contexts are refcounted, so when this request is associated with a 7487df8fc6SFrançois Tigeot * context, we must increment the context's refcount, to guarantee that 7587df8fc6SFrançois Tigeot * it persists while any request is linked to it. Requests themselves 7687df8fc6SFrançois Tigeot * are also refcounted, so the request will only be freed when the last 7787df8fc6SFrançois Tigeot * reference to it is dismissed, and the code in 7887df8fc6SFrançois Tigeot * i915_gem_request_free() will then decrement the refcount on the 7987df8fc6SFrançois Tigeot * context. 8087df8fc6SFrançois Tigeot */ 8187df8fc6SFrançois Tigeot struct i915_gem_context *ctx; 8287df8fc6SFrançois Tigeot struct intel_engine_cs *engine; 8371f41f3eSFrançois Tigeot struct intel_ring *ring; 8487df8fc6SFrançois Tigeot struct intel_signal_node signaling; 8587df8fc6SFrançois Tigeot 861e12ee3bSFrançois Tigeot struct i915_sw_fence submit; 871e12ee3bSFrançois Tigeot wait_queue_t submitq; 881e12ee3bSFrançois Tigeot 8987df8fc6SFrançois Tigeot /** GEM sequence number associated with the previous request, 9087df8fc6SFrançois Tigeot * when the HWS breadcrumb is equal to this the GPU is processing 9187df8fc6SFrançois Tigeot * this request. 9287df8fc6SFrançois Tigeot */ 9387df8fc6SFrançois Tigeot u32 previous_seqno; 9487df8fc6SFrançois Tigeot 951e12ee3bSFrançois Tigeot /** Position in the ring of the start of the request */ 9687df8fc6SFrançois Tigeot u32 head; 9787df8fc6SFrançois Tigeot 9887df8fc6SFrançois Tigeot /** 991e12ee3bSFrançois Tigeot * Position in the ring of the start of the postfix. 1001e12ee3bSFrançois Tigeot * This is required to calculate the maximum available ring space 1011e12ee3bSFrançois Tigeot * without overwriting the postfix. 10287df8fc6SFrançois Tigeot */ 10387df8fc6SFrançois Tigeot u32 postfix; 10487df8fc6SFrançois Tigeot 1051e12ee3bSFrançois Tigeot /** Position in the ring of the end of the whole request */ 10687df8fc6SFrançois Tigeot u32 tail; 10787df8fc6SFrançois Tigeot 1081e12ee3bSFrançois Tigeot /** Position in the ring of the end of any workarounds after the tail */ 1091e12ee3bSFrançois Tigeot u32 wa_tail; 1101e12ee3bSFrançois Tigeot 1111e12ee3bSFrançois Tigeot /** Preallocate space in the ring for the emitting the request */ 11287df8fc6SFrançois Tigeot u32 reserved_space; 11387df8fc6SFrançois Tigeot 11487df8fc6SFrançois Tigeot /** 11587df8fc6SFrançois Tigeot * Context related to the previous request. 11687df8fc6SFrançois Tigeot * As the contexts are accessed by the hardware until the switch is 11787df8fc6SFrançois Tigeot * completed to a new context, the hardware may still be writing 11887df8fc6SFrançois Tigeot * to the context object after the breadcrumb is visible. We must 11987df8fc6SFrançois Tigeot * not unpin/unbind/prune that object whilst still active and so 12087df8fc6SFrançois Tigeot * we keep the previous context pinned until the following (this) 12187df8fc6SFrançois Tigeot * request is retired. 12287df8fc6SFrançois Tigeot */ 12387df8fc6SFrançois Tigeot struct i915_gem_context *previous_context; 12487df8fc6SFrançois Tigeot 12587df8fc6SFrançois Tigeot /** Batch buffer related to this request if any (used for 12687df8fc6SFrançois Tigeot * error state dump only). 12787df8fc6SFrançois Tigeot */ 1281e12ee3bSFrançois Tigeot struct i915_vma *batch; 12971f41f3eSFrançois Tigeot struct list_head active_list; 13087df8fc6SFrançois Tigeot 13187df8fc6SFrançois Tigeot /** Time at which this request was emitted, in jiffies. */ 13287df8fc6SFrançois Tigeot unsigned long emitted_jiffies; 13387df8fc6SFrançois Tigeot 13471f41f3eSFrançois Tigeot /** engine->request_list entry for this request */ 13571f41f3eSFrançois Tigeot struct list_head link; 13671f41f3eSFrançois Tigeot 13771f41f3eSFrançois Tigeot /** ring->request_list entry for this request */ 13871f41f3eSFrançois Tigeot struct list_head ring_link; 13987df8fc6SFrançois Tigeot 14087df8fc6SFrançois Tigeot struct drm_i915_file_private *file_priv; 14187df8fc6SFrançois Tigeot /** file_priv list entry for this request */ 14287df8fc6SFrançois Tigeot struct list_head client_list; 14387df8fc6SFrançois Tigeot 1441e12ee3bSFrançois Tigeot /** Link in the execlist submission queue, guarded by execlist_lock. */ 14587df8fc6SFrançois Tigeot struct list_head execlist_link; 14687df8fc6SFrançois Tigeot }; 14787df8fc6SFrançois Tigeot 148*6559babbSFrançois Tigeot extern const struct dma_fence_ops i915_fence_ops; 14987df8fc6SFrançois Tigeot 150*6559babbSFrançois Tigeot static inline bool fence_is_i915(struct dma_fence *fence) 15187df8fc6SFrançois Tigeot { 15287df8fc6SFrançois Tigeot return fence->ops == &i915_fence_ops; 15387df8fc6SFrançois Tigeot } 15487df8fc6SFrançois Tigeot 15587df8fc6SFrançois Tigeot struct drm_i915_gem_request * __must_check 15687df8fc6SFrançois Tigeot i915_gem_request_alloc(struct intel_engine_cs *engine, 15787df8fc6SFrançois Tigeot struct i915_gem_context *ctx); 15887df8fc6SFrançois Tigeot int i915_gem_request_add_to_client(struct drm_i915_gem_request *req, 15987df8fc6SFrançois Tigeot struct drm_file *file); 16087df8fc6SFrançois Tigeot void i915_gem_request_retire_upto(struct drm_i915_gem_request *req); 16187df8fc6SFrançois Tigeot 16287df8fc6SFrançois Tigeot static inline u32 16387df8fc6SFrançois Tigeot i915_gem_request_get_seqno(struct drm_i915_gem_request *req) 16487df8fc6SFrançois Tigeot { 16587df8fc6SFrançois Tigeot return req ? req->fence.seqno : 0; 16687df8fc6SFrançois Tigeot } 16787df8fc6SFrançois Tigeot 16887df8fc6SFrançois Tigeot static inline struct intel_engine_cs * 16987df8fc6SFrançois Tigeot i915_gem_request_get_engine(struct drm_i915_gem_request *req) 17087df8fc6SFrançois Tigeot { 17187df8fc6SFrançois Tigeot return req ? req->engine : NULL; 17287df8fc6SFrançois Tigeot } 17387df8fc6SFrançois Tigeot 17487df8fc6SFrançois Tigeot static inline struct drm_i915_gem_request * 175*6559babbSFrançois Tigeot to_request(struct dma_fence *fence) 17687df8fc6SFrançois Tigeot { 17787df8fc6SFrançois Tigeot /* We assume that NULL fence/request are interoperable */ 17887df8fc6SFrançois Tigeot BUILD_BUG_ON(offsetof(struct drm_i915_gem_request, fence) != 0); 17987df8fc6SFrançois Tigeot GEM_BUG_ON(fence && !fence_is_i915(fence)); 18087df8fc6SFrançois Tigeot return container_of(fence, struct drm_i915_gem_request, fence); 18187df8fc6SFrançois Tigeot } 18287df8fc6SFrançois Tigeot 18387df8fc6SFrançois Tigeot static inline struct drm_i915_gem_request * 18487df8fc6SFrançois Tigeot i915_gem_request_get(struct drm_i915_gem_request *req) 18587df8fc6SFrançois Tigeot { 186*6559babbSFrançois Tigeot return to_request(dma_fence_get(&req->fence)); 18787df8fc6SFrançois Tigeot } 18887df8fc6SFrançois Tigeot 18971f41f3eSFrançois Tigeot static inline struct drm_i915_gem_request * 19071f41f3eSFrançois Tigeot i915_gem_request_get_rcu(struct drm_i915_gem_request *req) 19171f41f3eSFrançois Tigeot { 192*6559babbSFrançois Tigeot return to_request(dma_fence_get_rcu(&req->fence)); 19371f41f3eSFrançois Tigeot } 19471f41f3eSFrançois Tigeot 19587df8fc6SFrançois Tigeot static inline void 19687df8fc6SFrançois Tigeot i915_gem_request_put(struct drm_i915_gem_request *req) 19787df8fc6SFrançois Tigeot { 198*6559babbSFrançois Tigeot dma_fence_put(&req->fence); 19987df8fc6SFrançois Tigeot } 20087df8fc6SFrançois Tigeot 20187df8fc6SFrançois Tigeot static inline void i915_gem_request_assign(struct drm_i915_gem_request **pdst, 20287df8fc6SFrançois Tigeot struct drm_i915_gem_request *src) 20387df8fc6SFrançois Tigeot { 20487df8fc6SFrançois Tigeot if (src) 20587df8fc6SFrançois Tigeot i915_gem_request_get(src); 20687df8fc6SFrançois Tigeot 20787df8fc6SFrançois Tigeot if (*pdst) 20887df8fc6SFrançois Tigeot i915_gem_request_put(*pdst); 20987df8fc6SFrançois Tigeot 21087df8fc6SFrançois Tigeot *pdst = src; 21187df8fc6SFrançois Tigeot } 21287df8fc6SFrançois Tigeot 2131e12ee3bSFrançois Tigeot int 2141e12ee3bSFrançois Tigeot i915_gem_request_await_object(struct drm_i915_gem_request *to, 2151e12ee3bSFrançois Tigeot struct drm_i915_gem_object *obj, 2161e12ee3bSFrançois Tigeot bool write); 2171e12ee3bSFrançois Tigeot 2181e12ee3bSFrançois Tigeot void __i915_add_request(struct drm_i915_gem_request *req, bool flush_caches); 21987df8fc6SFrançois Tigeot #define i915_add_request(req) \ 2201e12ee3bSFrançois Tigeot __i915_add_request(req, true) 22187df8fc6SFrançois Tigeot #define i915_add_request_no_flush(req) \ 2221e12ee3bSFrançois Tigeot __i915_add_request(req, false) 22387df8fc6SFrançois Tigeot 22487df8fc6SFrançois Tigeot struct intel_rps_client; 22587df8fc6SFrançois Tigeot #define NO_WAITBOOST ERR_PTR(-1) 22687df8fc6SFrançois Tigeot #define IS_RPS_CLIENT(p) (!IS_ERR(p)) 22787df8fc6SFrançois Tigeot #define IS_RPS_USER(p) (!IS_ERR_OR_NULL(p)) 22887df8fc6SFrançois Tigeot 22971f41f3eSFrançois Tigeot int i915_wait_request(struct drm_i915_gem_request *req, 2301e12ee3bSFrançois Tigeot unsigned int flags, 23187df8fc6SFrançois Tigeot s64 *timeout, 23271f41f3eSFrançois Tigeot struct intel_rps_client *rps) 23371f41f3eSFrançois Tigeot __attribute__((nonnull(1))); 2341e12ee3bSFrançois Tigeot #define I915_WAIT_INTERRUPTIBLE BIT(0) 2351e12ee3bSFrançois Tigeot #define I915_WAIT_LOCKED BIT(1) /* struct_mutex held, handle GPU reset */ 23687df8fc6SFrançois Tigeot 23771f41f3eSFrançois Tigeot static inline u32 intel_engine_get_seqno(struct intel_engine_cs *engine); 23887df8fc6SFrançois Tigeot 23987df8fc6SFrançois Tigeot /** 24087df8fc6SFrançois Tigeot * Returns true if seq1 is later than seq2. 24187df8fc6SFrançois Tigeot */ 24287df8fc6SFrançois Tigeot static inline bool i915_seqno_passed(u32 seq1, u32 seq2) 24387df8fc6SFrançois Tigeot { 24487df8fc6SFrançois Tigeot return (s32)(seq1 - seq2) >= 0; 24587df8fc6SFrançois Tigeot } 24687df8fc6SFrançois Tigeot 24787df8fc6SFrançois Tigeot static inline bool 24887df8fc6SFrançois Tigeot i915_gem_request_started(const struct drm_i915_gem_request *req) 24987df8fc6SFrançois Tigeot { 25087df8fc6SFrançois Tigeot return i915_seqno_passed(intel_engine_get_seqno(req->engine), 25187df8fc6SFrançois Tigeot req->previous_seqno); 25287df8fc6SFrançois Tigeot } 25387df8fc6SFrançois Tigeot 25487df8fc6SFrançois Tigeot static inline bool 25587df8fc6SFrançois Tigeot i915_gem_request_completed(const struct drm_i915_gem_request *req) 25687df8fc6SFrançois Tigeot { 25787df8fc6SFrançois Tigeot return i915_seqno_passed(intel_engine_get_seqno(req->engine), 25887df8fc6SFrançois Tigeot req->fence.seqno); 25987df8fc6SFrançois Tigeot } 26087df8fc6SFrançois Tigeot 26187df8fc6SFrançois Tigeot bool __i915_spin_request(const struct drm_i915_gem_request *request, 26287df8fc6SFrançois Tigeot int state, unsigned long timeout_us); 26387df8fc6SFrançois Tigeot static inline bool i915_spin_request(const struct drm_i915_gem_request *request, 26487df8fc6SFrançois Tigeot int state, unsigned long timeout_us) 26587df8fc6SFrançois Tigeot { 26687df8fc6SFrançois Tigeot return (i915_gem_request_started(request) && 26787df8fc6SFrançois Tigeot __i915_spin_request(request, state, timeout_us)); 26887df8fc6SFrançois Tigeot } 26987df8fc6SFrançois Tigeot 27071f41f3eSFrançois Tigeot /* We treat requests as fences. This is not be to confused with our 27171f41f3eSFrançois Tigeot * "fence registers" but pipeline synchronisation objects ala GL_ARB_sync. 27271f41f3eSFrançois Tigeot * We use the fences to synchronize access from the CPU with activity on the 27371f41f3eSFrançois Tigeot * GPU, for example, we should not rewrite an object's PTE whilst the GPU 27471f41f3eSFrançois Tigeot * is reading them. We also track fences at a higher level to provide 27571f41f3eSFrançois Tigeot * implicit synchronisation around GEM objects, e.g. set-domain will wait 27671f41f3eSFrançois Tigeot * for outstanding GPU rendering before marking the object ready for CPU 27771f41f3eSFrançois Tigeot * access, or a pageflip will wait until the GPU is complete before showing 27871f41f3eSFrançois Tigeot * the frame on the scanout. 27971f41f3eSFrançois Tigeot * 28071f41f3eSFrançois Tigeot * In order to use a fence, the object must track the fence it needs to 28171f41f3eSFrançois Tigeot * serialise with. For example, GEM objects want to track both read and 28271f41f3eSFrançois Tigeot * write access so that we can perform concurrent read operations between 28371f41f3eSFrançois Tigeot * the CPU and GPU engines, as well as waiting for all rendering to 28471f41f3eSFrançois Tigeot * complete, or waiting for the last GPU user of a "fence register". The 28571f41f3eSFrançois Tigeot * object then embeds a #i915_gem_active to track the most recent (in 28671f41f3eSFrançois Tigeot * retirement order) request relevant for the desired mode of access. 28771f41f3eSFrançois Tigeot * The #i915_gem_active is updated with i915_gem_active_set() to track the 28871f41f3eSFrançois Tigeot * most recent fence request, typically this is done as part of 28971f41f3eSFrançois Tigeot * i915_vma_move_to_active(). 29071f41f3eSFrançois Tigeot * 29171f41f3eSFrançois Tigeot * When the #i915_gem_active completes (is retired), it will 29271f41f3eSFrançois Tigeot * signal its completion to the owner through a callback as well as mark 29371f41f3eSFrançois Tigeot * itself as idle (i915_gem_active.request == NULL). The owner 29471f41f3eSFrançois Tigeot * can then perform any action, such as delayed freeing of an active 29571f41f3eSFrançois Tigeot * resource including itself. 29671f41f3eSFrançois Tigeot */ 29771f41f3eSFrançois Tigeot struct i915_gem_active; 29871f41f3eSFrançois Tigeot 29971f41f3eSFrançois Tigeot typedef void (*i915_gem_retire_fn)(struct i915_gem_active *, 30071f41f3eSFrançois Tigeot struct drm_i915_gem_request *); 30171f41f3eSFrançois Tigeot 30271f41f3eSFrançois Tigeot struct i915_gem_active { 30371f41f3eSFrançois Tigeot struct drm_i915_gem_request __rcu *request; 30471f41f3eSFrançois Tigeot struct list_head link; 30571f41f3eSFrançois Tigeot i915_gem_retire_fn retire; 30671f41f3eSFrançois Tigeot }; 30771f41f3eSFrançois Tigeot 30871f41f3eSFrançois Tigeot void i915_gem_retire_noop(struct i915_gem_active *, 30971f41f3eSFrançois Tigeot struct drm_i915_gem_request *request); 31071f41f3eSFrançois Tigeot 31171f41f3eSFrançois Tigeot /** 31271f41f3eSFrançois Tigeot * init_request_active - prepares the activity tracker for use 31371f41f3eSFrançois Tigeot * @active - the active tracker 31471f41f3eSFrançois Tigeot * @func - a callback when then the tracker is retired (becomes idle), 31571f41f3eSFrançois Tigeot * can be NULL 31671f41f3eSFrançois Tigeot * 31771f41f3eSFrançois Tigeot * init_request_active() prepares the embedded @active struct for use as 31871f41f3eSFrançois Tigeot * an activity tracker, that is for tracking the last known active request 31971f41f3eSFrançois Tigeot * associated with it. When the last request becomes idle, when it is retired 32071f41f3eSFrançois Tigeot * after completion, the optional callback @func is invoked. 32171f41f3eSFrançois Tigeot */ 32271f41f3eSFrançois Tigeot static inline void 32371f41f3eSFrançois Tigeot init_request_active(struct i915_gem_active *active, 32471f41f3eSFrançois Tigeot i915_gem_retire_fn retire) 32571f41f3eSFrançois Tigeot { 32671f41f3eSFrançois Tigeot INIT_LIST_HEAD(&active->link); 32771f41f3eSFrançois Tigeot active->retire = retire ?: i915_gem_retire_noop; 32871f41f3eSFrançois Tigeot } 32971f41f3eSFrançois Tigeot 33071f41f3eSFrançois Tigeot /** 33171f41f3eSFrançois Tigeot * i915_gem_active_set - updates the tracker to watch the current request 33271f41f3eSFrançois Tigeot * @active - the active tracker 33371f41f3eSFrançois Tigeot * @request - the request to watch 33471f41f3eSFrançois Tigeot * 33571f41f3eSFrançois Tigeot * i915_gem_active_set() watches the given @request for completion. Whilst 33671f41f3eSFrançois Tigeot * that @request is busy, the @active reports busy. When that @request is 33771f41f3eSFrançois Tigeot * retired, the @active tracker is updated to report idle. 33871f41f3eSFrançois Tigeot */ 33971f41f3eSFrançois Tigeot static inline void 34071f41f3eSFrançois Tigeot i915_gem_active_set(struct i915_gem_active *active, 34171f41f3eSFrançois Tigeot struct drm_i915_gem_request *request) 34271f41f3eSFrançois Tigeot { 34371f41f3eSFrançois Tigeot list_move(&active->link, &request->active_list); 34471f41f3eSFrançois Tigeot rcu_assign_pointer(active->request, request); 34571f41f3eSFrançois Tigeot } 34671f41f3eSFrançois Tigeot 34771f41f3eSFrançois Tigeot static inline struct drm_i915_gem_request * 34871f41f3eSFrançois Tigeot __i915_gem_active_peek(const struct i915_gem_active *active) 34971f41f3eSFrançois Tigeot { 35071f41f3eSFrançois Tigeot /* Inside the error capture (running with the driver in an unknown 35171f41f3eSFrançois Tigeot * state), we want to bend the rules slightly (a lot). 35271f41f3eSFrançois Tigeot * 35371f41f3eSFrançois Tigeot * Work is in progress to make it safer, in the meantime this keeps 35471f41f3eSFrançois Tigeot * the known issue from spamming the logs. 35571f41f3eSFrançois Tigeot */ 35671f41f3eSFrançois Tigeot return rcu_dereference_protected(active->request, 1); 35771f41f3eSFrançois Tigeot } 35871f41f3eSFrançois Tigeot 35971f41f3eSFrançois Tigeot /** 36071f41f3eSFrançois Tigeot * i915_gem_active_raw - return the active request 36171f41f3eSFrançois Tigeot * @active - the active tracker 36271f41f3eSFrançois Tigeot * 36371f41f3eSFrançois Tigeot * i915_gem_active_raw() returns the current request being tracked, or NULL. 36471f41f3eSFrançois Tigeot * It does not obtain a reference on the request for the caller, so the caller 36571f41f3eSFrançois Tigeot * must hold struct_mutex. 36671f41f3eSFrançois Tigeot */ 36771f41f3eSFrançois Tigeot static inline struct drm_i915_gem_request * 36871f41f3eSFrançois Tigeot i915_gem_active_raw(const struct i915_gem_active *active, struct lock *mutex) 36971f41f3eSFrançois Tigeot { 37071f41f3eSFrançois Tigeot return rcu_dereference_protected(active->request, 37171f41f3eSFrançois Tigeot lockdep_is_held(mutex)); 37271f41f3eSFrançois Tigeot } 37371f41f3eSFrançois Tigeot 37471f41f3eSFrançois Tigeot /** 37571f41f3eSFrançois Tigeot * i915_gem_active_peek - report the active request being monitored 37671f41f3eSFrançois Tigeot * @active - the active tracker 37771f41f3eSFrançois Tigeot * 37871f41f3eSFrançois Tigeot * i915_gem_active_peek() returns the current request being tracked if 37971f41f3eSFrançois Tigeot * still active, or NULL. It does not obtain a reference on the request 38071f41f3eSFrançois Tigeot * for the caller, so the caller must hold struct_mutex. 38171f41f3eSFrançois Tigeot */ 38271f41f3eSFrançois Tigeot static inline struct drm_i915_gem_request * 38371f41f3eSFrançois Tigeot i915_gem_active_peek(const struct i915_gem_active *active, struct lock *mutex) 38471f41f3eSFrançois Tigeot { 38571f41f3eSFrançois Tigeot struct drm_i915_gem_request *request; 38671f41f3eSFrançois Tigeot 38771f41f3eSFrançois Tigeot request = i915_gem_active_raw(active, mutex); 38871f41f3eSFrançois Tigeot if (!request || i915_gem_request_completed(request)) 38971f41f3eSFrançois Tigeot return NULL; 39071f41f3eSFrançois Tigeot 39171f41f3eSFrançois Tigeot return request; 39271f41f3eSFrançois Tigeot } 39371f41f3eSFrançois Tigeot 39471f41f3eSFrançois Tigeot /** 39571f41f3eSFrançois Tigeot * i915_gem_active_get - return a reference to the active request 39671f41f3eSFrançois Tigeot * @active - the active tracker 39771f41f3eSFrançois Tigeot * 39871f41f3eSFrançois Tigeot * i915_gem_active_get() returns a reference to the active request, or NULL 39971f41f3eSFrançois Tigeot * if the active tracker is idle. The caller must hold struct_mutex. 40071f41f3eSFrançois Tigeot */ 40171f41f3eSFrançois Tigeot static inline struct drm_i915_gem_request * 40271f41f3eSFrançois Tigeot i915_gem_active_get(const struct i915_gem_active *active, struct lock *mutex) 40371f41f3eSFrançois Tigeot { 40471f41f3eSFrançois Tigeot return i915_gem_request_get(i915_gem_active_peek(active, mutex)); 40571f41f3eSFrançois Tigeot } 40671f41f3eSFrançois Tigeot 40771f41f3eSFrançois Tigeot /** 40871f41f3eSFrançois Tigeot * __i915_gem_active_get_rcu - return a reference to the active request 40971f41f3eSFrançois Tigeot * @active - the active tracker 41071f41f3eSFrançois Tigeot * 41171f41f3eSFrançois Tigeot * __i915_gem_active_get() returns a reference to the active request, or NULL 41271f41f3eSFrançois Tigeot * if the active tracker is idle. The caller must hold the RCU read lock, but 41371f41f3eSFrançois Tigeot * the returned pointer is safe to use outside of RCU. 41471f41f3eSFrançois Tigeot */ 41571f41f3eSFrançois Tigeot static inline struct drm_i915_gem_request * 41671f41f3eSFrançois Tigeot __i915_gem_active_get_rcu(const struct i915_gem_active *active) 41771f41f3eSFrançois Tigeot { 41871f41f3eSFrançois Tigeot /* Performing a lockless retrieval of the active request is super 41971f41f3eSFrançois Tigeot * tricky. SLAB_DESTROY_BY_RCU merely guarantees that the backing 42071f41f3eSFrançois Tigeot * slab of request objects will not be freed whilst we hold the 42171f41f3eSFrançois Tigeot * RCU read lock. It does not guarantee that the request itself 42271f41f3eSFrançois Tigeot * will not be freed and then *reused*. Viz, 42371f41f3eSFrançois Tigeot * 42471f41f3eSFrançois Tigeot * Thread A Thread B 42571f41f3eSFrançois Tigeot * 42671f41f3eSFrançois Tigeot * req = active.request 42771f41f3eSFrançois Tigeot * retire(req) -> free(req); 42871f41f3eSFrançois Tigeot * (req is now first on the slab freelist) 42971f41f3eSFrançois Tigeot * active.request = NULL 43071f41f3eSFrançois Tigeot * 43171f41f3eSFrançois Tigeot * req = new submission on a new object 43271f41f3eSFrançois Tigeot * ref(req) 43371f41f3eSFrançois Tigeot * 43471f41f3eSFrançois Tigeot * To prevent the request from being reused whilst the caller 43571f41f3eSFrançois Tigeot * uses it, we take a reference like normal. Whilst acquiring 43671f41f3eSFrançois Tigeot * the reference we check that it is not in a destroyed state 43771f41f3eSFrançois Tigeot * (refcnt == 0). That prevents the request being reallocated 43871f41f3eSFrançois Tigeot * whilst the caller holds on to it. To check that the request 43971f41f3eSFrançois Tigeot * was not reallocated as we acquired the reference we have to 44071f41f3eSFrançois Tigeot * check that our request remains the active request across 44171f41f3eSFrançois Tigeot * the lookup, in the same manner as a seqlock. The visibility 44271f41f3eSFrançois Tigeot * of the pointer versus the reference counting is controlled 44371f41f3eSFrançois Tigeot * by using RCU barriers (rcu_dereference and rcu_assign_pointer). 44471f41f3eSFrançois Tigeot * 44571f41f3eSFrançois Tigeot * In the middle of all that, we inspect whether the request is 44671f41f3eSFrançois Tigeot * complete. Retiring is lazy so the request may be completed long 44771f41f3eSFrançois Tigeot * before the active tracker is updated. Querying whether the 44871f41f3eSFrançois Tigeot * request is complete is far cheaper (as it involves no locked 44971f41f3eSFrançois Tigeot * instructions setting cachelines to exclusive) than acquiring 45071f41f3eSFrançois Tigeot * the reference, so we do it first. The RCU read lock ensures the 45171f41f3eSFrançois Tigeot * pointer dereference is valid, but does not ensure that the 45271f41f3eSFrançois Tigeot * seqno nor HWS is the right one! However, if the request was 45371f41f3eSFrançois Tigeot * reallocated, that means the active tracker's request was complete. 45471f41f3eSFrançois Tigeot * If the new request is also complete, then both are and we can 45571f41f3eSFrançois Tigeot * just report the active tracker is idle. If the new request is 45671f41f3eSFrançois Tigeot * incomplete, then we acquire a reference on it and check that 45771f41f3eSFrançois Tigeot * it remained the active request. 45871f41f3eSFrançois Tigeot * 45971f41f3eSFrançois Tigeot * It is then imperative that we do not zero the request on 46071f41f3eSFrançois Tigeot * reallocation, so that we can chase the dangling pointers! 46171f41f3eSFrançois Tigeot * See i915_gem_request_alloc(). 46271f41f3eSFrançois Tigeot */ 46371f41f3eSFrançois Tigeot do { 46471f41f3eSFrançois Tigeot struct drm_i915_gem_request *request; 46571f41f3eSFrançois Tigeot 46671f41f3eSFrançois Tigeot request = rcu_dereference(active->request); 46771f41f3eSFrançois Tigeot if (!request || i915_gem_request_completed(request)) 46871f41f3eSFrançois Tigeot return NULL; 46971f41f3eSFrançois Tigeot 4701e12ee3bSFrançois Tigeot /* An especially silly compiler could decide to recompute the 4711e12ee3bSFrançois Tigeot * result of i915_gem_request_completed, more specifically 4721e12ee3bSFrançois Tigeot * re-emit the load for request->fence.seqno. A race would catch 4731e12ee3bSFrançois Tigeot * a later seqno value, which could flip the result from true to 4741e12ee3bSFrançois Tigeot * false. Which means part of the instructions below might not 4751e12ee3bSFrançois Tigeot * be executed, while later on instructions are executed. Due to 4761e12ee3bSFrançois Tigeot * barriers within the refcounting the inconsistency can't reach 4771e12ee3bSFrançois Tigeot * past the call to i915_gem_request_get_rcu, but not executing 4781e12ee3bSFrançois Tigeot * that while still executing i915_gem_request_put() creates 4791e12ee3bSFrançois Tigeot * havoc enough. Prevent this with a compiler barrier. 4801e12ee3bSFrançois Tigeot */ 4811e12ee3bSFrançois Tigeot barrier(); 4821e12ee3bSFrançois Tigeot 48371f41f3eSFrançois Tigeot request = i915_gem_request_get_rcu(request); 48471f41f3eSFrançois Tigeot 48571f41f3eSFrançois Tigeot /* What stops the following rcu_access_pointer() from occurring 48671f41f3eSFrançois Tigeot * before the above i915_gem_request_get_rcu()? If we were 48771f41f3eSFrançois Tigeot * to read the value before pausing to get the reference to 48871f41f3eSFrançois Tigeot * the request, we may not notice a change in the active 48971f41f3eSFrançois Tigeot * tracker. 49071f41f3eSFrançois Tigeot * 49171f41f3eSFrançois Tigeot * The rcu_access_pointer() is a mere compiler barrier, which 49271f41f3eSFrançois Tigeot * means both the CPU and compiler are free to perform the 49371f41f3eSFrançois Tigeot * memory read without constraint. The compiler only has to 49471f41f3eSFrançois Tigeot * ensure that any operations after the rcu_access_pointer() 49571f41f3eSFrançois Tigeot * occur afterwards in program order. This means the read may 49671f41f3eSFrançois Tigeot * be performed earlier by an out-of-order CPU, or adventurous 49771f41f3eSFrançois Tigeot * compiler. 49871f41f3eSFrançois Tigeot * 49971f41f3eSFrançois Tigeot * The atomic operation at the heart of 500*6559babbSFrançois Tigeot * i915_gem_request_get_rcu(), see dma_fence_get_rcu(), is 50171f41f3eSFrançois Tigeot * atomic_inc_not_zero() which is only a full memory barrier 50271f41f3eSFrançois Tigeot * when successful. That is, if i915_gem_request_get_rcu() 50371f41f3eSFrançois Tigeot * returns the request (and so with the reference counted 50471f41f3eSFrançois Tigeot * incremented) then the following read for rcu_access_pointer() 50571f41f3eSFrançois Tigeot * must occur after the atomic operation and so confirm 50671f41f3eSFrançois Tigeot * that this request is the one currently being tracked. 50771f41f3eSFrançois Tigeot * 50871f41f3eSFrançois Tigeot * The corresponding write barrier is part of 50971f41f3eSFrançois Tigeot * rcu_assign_pointer(). 51071f41f3eSFrançois Tigeot */ 51171f41f3eSFrançois Tigeot if (!request || request == rcu_access_pointer(active->request)) 51271f41f3eSFrançois Tigeot return rcu_pointer_handoff(request); 51371f41f3eSFrançois Tigeot 51471f41f3eSFrançois Tigeot i915_gem_request_put(request); 51571f41f3eSFrançois Tigeot } while (1); 51671f41f3eSFrançois Tigeot } 51771f41f3eSFrançois Tigeot 51871f41f3eSFrançois Tigeot /** 51971f41f3eSFrançois Tigeot * i915_gem_active_get_unlocked - return a reference to the active request 52071f41f3eSFrançois Tigeot * @active - the active tracker 52171f41f3eSFrançois Tigeot * 52271f41f3eSFrançois Tigeot * i915_gem_active_get_unlocked() returns a reference to the active request, 52371f41f3eSFrançois Tigeot * or NULL if the active tracker is idle. The reference is obtained under RCU, 52471f41f3eSFrançois Tigeot * so no locking is required by the caller. 52571f41f3eSFrançois Tigeot * 52671f41f3eSFrançois Tigeot * The reference should be freed with i915_gem_request_put(). 52771f41f3eSFrançois Tigeot */ 52871f41f3eSFrançois Tigeot static inline struct drm_i915_gem_request * 52971f41f3eSFrançois Tigeot i915_gem_active_get_unlocked(const struct i915_gem_active *active) 53071f41f3eSFrançois Tigeot { 53171f41f3eSFrançois Tigeot struct drm_i915_gem_request *request; 53271f41f3eSFrançois Tigeot 53371f41f3eSFrançois Tigeot rcu_read_lock(); 53471f41f3eSFrançois Tigeot request = __i915_gem_active_get_rcu(active); 53571f41f3eSFrançois Tigeot rcu_read_unlock(); 53671f41f3eSFrançois Tigeot 53771f41f3eSFrançois Tigeot return request; 53871f41f3eSFrançois Tigeot } 53971f41f3eSFrançois Tigeot 54071f41f3eSFrançois Tigeot /** 54171f41f3eSFrançois Tigeot * i915_gem_active_isset - report whether the active tracker is assigned 54271f41f3eSFrançois Tigeot * @active - the active tracker 54371f41f3eSFrançois Tigeot * 54471f41f3eSFrançois Tigeot * i915_gem_active_isset() returns true if the active tracker is currently 54571f41f3eSFrançois Tigeot * assigned to a request. Due to the lazy retiring, that request may be idle 54671f41f3eSFrançois Tigeot * and this may report stale information. 54771f41f3eSFrançois Tigeot */ 54871f41f3eSFrançois Tigeot static inline bool 54971f41f3eSFrançois Tigeot i915_gem_active_isset(const struct i915_gem_active *active) 55071f41f3eSFrançois Tigeot { 55171f41f3eSFrançois Tigeot return rcu_access_pointer(active->request); 55271f41f3eSFrançois Tigeot } 55371f41f3eSFrançois Tigeot 55471f41f3eSFrançois Tigeot /** 55571f41f3eSFrançois Tigeot * i915_gem_active_is_idle - report whether the active tracker is idle 55671f41f3eSFrançois Tigeot * @active - the active tracker 55771f41f3eSFrançois Tigeot * 55871f41f3eSFrançois Tigeot * i915_gem_active_is_idle() returns true if the active tracker is currently 55971f41f3eSFrançois Tigeot * unassigned or if the request is complete (but not yet retired). Requires 56071f41f3eSFrançois Tigeot * the caller to hold struct_mutex (but that can be relaxed if desired). 56171f41f3eSFrançois Tigeot */ 56271f41f3eSFrançois Tigeot static inline bool 56371f41f3eSFrançois Tigeot i915_gem_active_is_idle(const struct i915_gem_active *active, 56471f41f3eSFrançois Tigeot struct lock *mutex) 56571f41f3eSFrançois Tigeot { 56671f41f3eSFrançois Tigeot return !i915_gem_active_peek(active, mutex); 56771f41f3eSFrançois Tigeot } 56871f41f3eSFrançois Tigeot 56971f41f3eSFrançois Tigeot /** 57071f41f3eSFrançois Tigeot * i915_gem_active_wait - waits until the request is completed 57171f41f3eSFrançois Tigeot * @active - the active request on which to wait 57271f41f3eSFrançois Tigeot * 57371f41f3eSFrançois Tigeot * i915_gem_active_wait() waits until the request is completed before 57471f41f3eSFrançois Tigeot * returning. Note that it does not guarantee that the request is 57571f41f3eSFrançois Tigeot * retired first, see i915_gem_active_retire(). 57671f41f3eSFrançois Tigeot * 57771f41f3eSFrançois Tigeot * i915_gem_active_wait() returns immediately if the active 57871f41f3eSFrançois Tigeot * request is already complete. 57971f41f3eSFrançois Tigeot */ 58071f41f3eSFrançois Tigeot static inline int __must_check 58171f41f3eSFrançois Tigeot i915_gem_active_wait(const struct i915_gem_active *active, struct lock *mutex) 58271f41f3eSFrançois Tigeot { 58371f41f3eSFrançois Tigeot struct drm_i915_gem_request *request; 58471f41f3eSFrançois Tigeot 58571f41f3eSFrançois Tigeot request = i915_gem_active_peek(active, mutex); 58671f41f3eSFrançois Tigeot if (!request) 58771f41f3eSFrançois Tigeot return 0; 58871f41f3eSFrançois Tigeot 5891e12ee3bSFrançois Tigeot return i915_wait_request(request, 5901e12ee3bSFrançois Tigeot I915_WAIT_INTERRUPTIBLE | I915_WAIT_LOCKED, 5911e12ee3bSFrançois Tigeot NULL, NULL); 59271f41f3eSFrançois Tigeot } 59371f41f3eSFrançois Tigeot 59471f41f3eSFrançois Tigeot /** 59571f41f3eSFrançois Tigeot * i915_gem_active_wait_unlocked - waits until the request is completed 59671f41f3eSFrançois Tigeot * @active - the active request on which to wait 5971e12ee3bSFrançois Tigeot * @flags - how to wait 59871f41f3eSFrançois Tigeot * @timeout - how long to wait at most 59971f41f3eSFrançois Tigeot * @rps - userspace client to charge for a waitboost 60071f41f3eSFrançois Tigeot * 60171f41f3eSFrançois Tigeot * i915_gem_active_wait_unlocked() waits until the request is completed before 60271f41f3eSFrançois Tigeot * returning, without requiring any locks to be held. Note that it does not 60371f41f3eSFrançois Tigeot * retire any requests before returning. 60471f41f3eSFrançois Tigeot * 60571f41f3eSFrançois Tigeot * This function relies on RCU in order to acquire the reference to the active 60671f41f3eSFrançois Tigeot * request without holding any locks. See __i915_gem_active_get_rcu() for the 60771f41f3eSFrançois Tigeot * glory details on how that is managed. Once the reference is acquired, we 60871f41f3eSFrançois Tigeot * can then wait upon the request, and afterwards release our reference, 60971f41f3eSFrançois Tigeot * free of any locking. 61071f41f3eSFrançois Tigeot * 61171f41f3eSFrançois Tigeot * This function wraps i915_wait_request(), see it for the full details on 61271f41f3eSFrançois Tigeot * the arguments. 61371f41f3eSFrançois Tigeot * 61471f41f3eSFrançois Tigeot * Returns 0 if successful, or a negative error code. 61571f41f3eSFrançois Tigeot */ 61671f41f3eSFrançois Tigeot static inline int 61771f41f3eSFrançois Tigeot i915_gem_active_wait_unlocked(const struct i915_gem_active *active, 6181e12ee3bSFrançois Tigeot unsigned int flags, 61971f41f3eSFrançois Tigeot s64 *timeout, 62071f41f3eSFrançois Tigeot struct intel_rps_client *rps) 62171f41f3eSFrançois Tigeot { 62271f41f3eSFrançois Tigeot struct drm_i915_gem_request *request; 62371f41f3eSFrançois Tigeot int ret = 0; 62471f41f3eSFrançois Tigeot 62571f41f3eSFrançois Tigeot request = i915_gem_active_get_unlocked(active); 62671f41f3eSFrançois Tigeot if (request) { 6271e12ee3bSFrançois Tigeot ret = i915_wait_request(request, flags, timeout, rps); 62871f41f3eSFrançois Tigeot i915_gem_request_put(request); 62971f41f3eSFrançois Tigeot } 63071f41f3eSFrançois Tigeot 63171f41f3eSFrançois Tigeot return ret; 63271f41f3eSFrançois Tigeot } 63371f41f3eSFrançois Tigeot 63471f41f3eSFrançois Tigeot /** 63571f41f3eSFrançois Tigeot * i915_gem_active_retire - waits until the request is retired 63671f41f3eSFrançois Tigeot * @active - the active request on which to wait 63771f41f3eSFrançois Tigeot * 63871f41f3eSFrançois Tigeot * i915_gem_active_retire() waits until the request is completed, 63971f41f3eSFrançois Tigeot * and then ensures that at least the retirement handler for this 64071f41f3eSFrançois Tigeot * @active tracker is called before returning. If the @active 64171f41f3eSFrançois Tigeot * tracker is idle, the function returns immediately. 64271f41f3eSFrançois Tigeot */ 64371f41f3eSFrançois Tigeot static inline int __must_check 64471f41f3eSFrançois Tigeot i915_gem_active_retire(struct i915_gem_active *active, 64571f41f3eSFrançois Tigeot struct lock *mutex) 64671f41f3eSFrançois Tigeot { 64771f41f3eSFrançois Tigeot struct drm_i915_gem_request *request; 64871f41f3eSFrançois Tigeot int ret; 64971f41f3eSFrançois Tigeot 65071f41f3eSFrançois Tigeot request = i915_gem_active_raw(active, mutex); 65171f41f3eSFrançois Tigeot if (!request) 65271f41f3eSFrançois Tigeot return 0; 65371f41f3eSFrançois Tigeot 6541e12ee3bSFrançois Tigeot ret = i915_wait_request(request, 6551e12ee3bSFrançois Tigeot I915_WAIT_INTERRUPTIBLE | I915_WAIT_LOCKED, 6561e12ee3bSFrançois Tigeot NULL, NULL); 65771f41f3eSFrançois Tigeot if (ret) 65871f41f3eSFrançois Tigeot return ret; 65971f41f3eSFrançois Tigeot 66071f41f3eSFrançois Tigeot list_del_init(&active->link); 66171f41f3eSFrançois Tigeot RCU_INIT_POINTER(active->request, NULL); 66271f41f3eSFrançois Tigeot 66371f41f3eSFrançois Tigeot active->retire(active, request); 66471f41f3eSFrançois Tigeot 66571f41f3eSFrançois Tigeot return 0; 66671f41f3eSFrançois Tigeot } 66771f41f3eSFrançois Tigeot 66871f41f3eSFrançois Tigeot /* Convenience functions for peeking at state inside active's request whilst 66971f41f3eSFrançois Tigeot * guarded by the struct_mutex. 67071f41f3eSFrançois Tigeot */ 67171f41f3eSFrançois Tigeot 67271f41f3eSFrançois Tigeot static inline uint32_t 67371f41f3eSFrançois Tigeot i915_gem_active_get_seqno(const struct i915_gem_active *active, 67471f41f3eSFrançois Tigeot struct lock *mutex) 67571f41f3eSFrançois Tigeot { 67671f41f3eSFrançois Tigeot return i915_gem_request_get_seqno(i915_gem_active_peek(active, mutex)); 67771f41f3eSFrançois Tigeot } 67871f41f3eSFrançois Tigeot 67971f41f3eSFrançois Tigeot static inline struct intel_engine_cs * 68071f41f3eSFrançois Tigeot i915_gem_active_get_engine(const struct i915_gem_active *active, 68171f41f3eSFrançois Tigeot struct lock *mutex) 68271f41f3eSFrançois Tigeot { 68371f41f3eSFrançois Tigeot return i915_gem_request_get_engine(i915_gem_active_peek(active, mutex)); 68471f41f3eSFrançois Tigeot } 68571f41f3eSFrançois Tigeot 68671f41f3eSFrançois Tigeot #define for_each_active(mask, idx) \ 68771f41f3eSFrançois Tigeot for (; mask ? idx = ffs(mask) - 1, 1 : 0; mask &= ~BIT(idx)) 68871f41f3eSFrançois Tigeot 68987df8fc6SFrançois Tigeot #endif /* I915_GEM_REQUEST_H */ 690