xref: /dflybsd-src/sys/dev/drm/i915/intel_ringbuffer.h (revision a85cb24f18e3804e75ab8bcda7692564d0563317)
1e3adcf8fSFrançois Tigeot #ifndef _INTEL_RINGBUFFER_H_
2e3adcf8fSFrançois Tigeot #define _INTEL_RINGBUFFER_H_
3e3adcf8fSFrançois Tigeot 
4ba55f2f5SFrançois Tigeot #include <linux/hashtable.h>
519c468b4SFrançois Tigeot #include "i915_gem_batch_pool.h"
671f41f3eSFrançois Tigeot #include "i915_gem_request.h"
74be47400SFrançois Tigeot #include "i915_gem_timeline.h"
8*a85cb24fSFrançois Tigeot #include "i915_selftest.h"
9ba55f2f5SFrançois Tigeot 
10ba55f2f5SFrançois Tigeot #define I915_CMD_HASH_ORDER 9
11ba55f2f5SFrançois Tigeot 
121b13d190SFrançois Tigeot /* Early gen2 devices have a cacheline of just 32 bytes, using 64 is overkill,
131b13d190SFrançois Tigeot  * but keeps the logic simple. Indeed, the whole purpose of this macro is just
141b13d190SFrançois Tigeot  * to give some inclination as to some of the magic values used in the various
151b13d190SFrançois Tigeot  * workarounds!
161b13d190SFrançois Tigeot  */
171b13d190SFrançois Tigeot #define CACHELINE_BYTES 64
18a05eeebfSFrançois Tigeot #define CACHELINE_DWORDS (CACHELINE_BYTES / sizeof(uint32_t))
191b13d190SFrançois Tigeot 
20f4e1c372SFrançois Tigeot /*
21f4e1c372SFrançois Tigeot  * Gen2 BSpec "1. Programming Environment" / 1.4.4.6 "Ring Buffer Use"
22f4e1c372SFrançois Tigeot  * Gen3 BSpec "vol1c Memory Interface Functions" / 2.3.4.5 "Ring Buffer Use"
23f4e1c372SFrançois Tigeot  * Gen4+ BSpec "vol1c Memory Interface and Command Stream" / 5.3.4.5 "Ring Buffer Use"
24f4e1c372SFrançois Tigeot  *
25f4e1c372SFrançois Tigeot  * "If the Ring Buffer Head Pointer and the Tail Pointer are on the same
26f4e1c372SFrançois Tigeot  * cacheline, the Head Pointer must not be greater than the Tail
27f4e1c372SFrançois Tigeot  * Pointer."
28f4e1c372SFrançois Tigeot  */
29f4e1c372SFrançois Tigeot #define I915_RING_FREE_SPACE 64
30f4e1c372SFrançois Tigeot 
31e3adcf8fSFrançois Tigeot struct intel_hw_status_page {
321e12ee3bSFrançois Tigeot 	struct i915_vma *vma;
33f4e1c372SFrançois Tigeot 	u32 *page_addr;
341e12ee3bSFrançois Tigeot 	u32 ggtt_offset;
35e3adcf8fSFrançois Tigeot };
36e3adcf8fSFrançois Tigeot 
3787df8fc6SFrançois Tigeot #define I915_READ_TAIL(engine) I915_READ(RING_TAIL((engine)->mmio_base))
3887df8fc6SFrançois Tigeot #define I915_WRITE_TAIL(engine, val) I915_WRITE(RING_TAIL((engine)->mmio_base), val)
39e3adcf8fSFrançois Tigeot 
4087df8fc6SFrançois Tigeot #define I915_READ_START(engine) I915_READ(RING_START((engine)->mmio_base))
4187df8fc6SFrançois Tigeot #define I915_WRITE_START(engine, val) I915_WRITE(RING_START((engine)->mmio_base), val)
42e3adcf8fSFrançois Tigeot 
4387df8fc6SFrançois Tigeot #define I915_READ_HEAD(engine)  I915_READ(RING_HEAD((engine)->mmio_base))
4487df8fc6SFrançois Tigeot #define I915_WRITE_HEAD(engine, val) I915_WRITE(RING_HEAD((engine)->mmio_base), val)
45e3adcf8fSFrançois Tigeot 
4687df8fc6SFrançois Tigeot #define I915_READ_CTL(engine) I915_READ(RING_CTL((engine)->mmio_base))
4787df8fc6SFrançois Tigeot #define I915_WRITE_CTL(engine, val) I915_WRITE(RING_CTL((engine)->mmio_base), val)
48e3adcf8fSFrançois Tigeot 
4987df8fc6SFrançois Tigeot #define I915_READ_IMR(engine) I915_READ(RING_IMR((engine)->mmio_base))
5087df8fc6SFrançois Tigeot #define I915_WRITE_IMR(engine, val) I915_WRITE(RING_IMR((engine)->mmio_base), val)
51e3adcf8fSFrançois Tigeot 
5287df8fc6SFrançois Tigeot #define I915_READ_MODE(engine) I915_READ(RING_MI_MODE((engine)->mmio_base))
5387df8fc6SFrançois Tigeot #define I915_WRITE_MODE(engine, val) I915_WRITE(RING_MI_MODE((engine)->mmio_base), val)
54ba55f2f5SFrançois Tigeot 
5524edb884SFrançois Tigeot /* seqno size is actually only a uint32, but since we plan to use MI_FLUSH_DW to
5624edb884SFrançois Tigeot  * do the writes, and that must have qw aligned offsets, simply pretend it's 8b.
5724edb884SFrançois Tigeot  */
588621f407SFrançois Tigeot #define gen8_semaphore_seqno_size sizeof(uint64_t)
598621f407SFrançois Tigeot #define GEN8_SEMAPHORE_OFFSET(__from, __to)			     \
608621f407SFrançois Tigeot 	(((__from) * I915_NUM_ENGINES  + (__to)) * gen8_semaphore_seqno_size)
6124edb884SFrançois Tigeot #define GEN8_SIGNAL_OFFSET(__ring, to)			     \
621e12ee3bSFrançois Tigeot 	(dev_priv->semaphore->node.start + \
638621f407SFrançois Tigeot 	 GEN8_SEMAPHORE_OFFSET((__ring)->id, (to)))
6424edb884SFrançois Tigeot #define GEN8_WAIT_OFFSET(__ring, from)			     \
651e12ee3bSFrançois Tigeot 	(dev_priv->semaphore->node.start + \
668621f407SFrançois Tigeot 	 GEN8_SEMAPHORE_OFFSET(from, (__ring)->id))
6724edb884SFrançois Tigeot 
6871f41f3eSFrançois Tigeot enum intel_engine_hangcheck_action {
69*a85cb24fSFrançois Tigeot 	ENGINE_IDLE = 0,
70*a85cb24fSFrançois Tigeot 	ENGINE_WAIT,
71*a85cb24fSFrançois Tigeot 	ENGINE_ACTIVE_SEQNO,
72*a85cb24fSFrançois Tigeot 	ENGINE_ACTIVE_HEAD,
73*a85cb24fSFrançois Tigeot 	ENGINE_ACTIVE_SUBUNITS,
74*a85cb24fSFrançois Tigeot 	ENGINE_WAIT_KICK,
75*a85cb24fSFrançois Tigeot 	ENGINE_DEAD,
769edbd4a0SFrançois Tigeot };
775d0b1887SFrançois Tigeot 
78*a85cb24fSFrançois Tigeot static inline const char *
79*a85cb24fSFrançois Tigeot hangcheck_action_to_str(const enum intel_engine_hangcheck_action a)
80*a85cb24fSFrançois Tigeot {
81*a85cb24fSFrançois Tigeot 	switch (a) {
82*a85cb24fSFrançois Tigeot 	case ENGINE_IDLE:
83*a85cb24fSFrançois Tigeot 		return "idle";
84*a85cb24fSFrançois Tigeot 	case ENGINE_WAIT:
85*a85cb24fSFrançois Tigeot 		return "wait";
86*a85cb24fSFrançois Tigeot 	case ENGINE_ACTIVE_SEQNO:
87*a85cb24fSFrançois Tigeot 		return "active seqno";
88*a85cb24fSFrançois Tigeot 	case ENGINE_ACTIVE_HEAD:
89*a85cb24fSFrançois Tigeot 		return "active head";
90*a85cb24fSFrançois Tigeot 	case ENGINE_ACTIVE_SUBUNITS:
91*a85cb24fSFrançois Tigeot 		return "active subunits";
92*a85cb24fSFrançois Tigeot 	case ENGINE_WAIT_KICK:
93*a85cb24fSFrançois Tigeot 		return "wait kick";
94*a85cb24fSFrançois Tigeot 	case ENGINE_DEAD:
95*a85cb24fSFrançois Tigeot 		return "dead";
96*a85cb24fSFrançois Tigeot 	}
97*a85cb24fSFrançois Tigeot 
98*a85cb24fSFrançois Tigeot 	return "unknown";
99*a85cb24fSFrançois Tigeot }
100ba55f2f5SFrançois Tigeot 
1011e12ee3bSFrançois Tigeot #define I915_MAX_SLICES	3
1021e12ee3bSFrançois Tigeot #define I915_MAX_SUBSLICES 3
1031e12ee3bSFrançois Tigeot 
1041e12ee3bSFrançois Tigeot #define instdone_slice_mask(dev_priv__) \
1051e12ee3bSFrançois Tigeot 	(INTEL_GEN(dev_priv__) == 7 ? \
1061e12ee3bSFrançois Tigeot 	 1 : INTEL_INFO(dev_priv__)->sseu.slice_mask)
1071e12ee3bSFrançois Tigeot 
1081e12ee3bSFrançois Tigeot #define instdone_subslice_mask(dev_priv__) \
1091e12ee3bSFrançois Tigeot 	(INTEL_GEN(dev_priv__) == 7 ? \
1101e12ee3bSFrançois Tigeot 	 1 : INTEL_INFO(dev_priv__)->sseu.subslice_mask)
1111e12ee3bSFrançois Tigeot 
1121e12ee3bSFrançois Tigeot #define for_each_instdone_slice_subslice(dev_priv__, slice__, subslice__) \
1131e12ee3bSFrançois Tigeot 	for ((slice__) = 0, (subslice__) = 0; \
1141e12ee3bSFrançois Tigeot 	     (slice__) < I915_MAX_SLICES; \
1151e12ee3bSFrançois Tigeot 	     (subslice__) = ((subslice__) + 1) < I915_MAX_SUBSLICES ? (subslice__) + 1 : 0, \
1161e12ee3bSFrançois Tigeot 	       (slice__) += ((subslice__) == 0)) \
1171e12ee3bSFrançois Tigeot 		for_each_if((BIT(slice__) & instdone_slice_mask(dev_priv__)) && \
1181e12ee3bSFrançois Tigeot 			    (BIT(subslice__) & instdone_subslice_mask(dev_priv__)))
1191e12ee3bSFrançois Tigeot 
1201e12ee3bSFrançois Tigeot struct intel_instdone {
1211e12ee3bSFrançois Tigeot 	u32 instdone;
1221e12ee3bSFrançois Tigeot 	/* The following exist only in the RCS engine */
1231e12ee3bSFrançois Tigeot 	u32 slice_common;
1241e12ee3bSFrançois Tigeot 	u32 sampler[I915_MAX_SLICES][I915_MAX_SUBSLICES];
1251e12ee3bSFrançois Tigeot 	u32 row[I915_MAX_SLICES][I915_MAX_SUBSLICES];
1261e12ee3bSFrançois Tigeot };
1271e12ee3bSFrançois Tigeot 
12871f41f3eSFrançois Tigeot struct intel_engine_hangcheck {
129ba55f2f5SFrançois Tigeot 	u64 acthd;
1305d0b1887SFrançois Tigeot 	u32 seqno;
13171f41f3eSFrançois Tigeot 	enum intel_engine_hangcheck_action action;
132*a85cb24fSFrançois Tigeot 	unsigned long action_timestamp;
133ba55f2f5SFrançois Tigeot 	int deadlock;
1341e12ee3bSFrançois Tigeot 	struct intel_instdone instdone;
135*a85cb24fSFrançois Tigeot 	bool stalled;
1365d0b1887SFrançois Tigeot };
1375d0b1887SFrançois Tigeot 
13871f41f3eSFrançois Tigeot struct intel_ring {
139c0e85e96SFrançois Tigeot 	struct i915_vma *vma;
1401e12ee3bSFrançois Tigeot 	void *vaddr;
141e3adcf8fSFrançois Tigeot 
1428621f407SFrançois Tigeot 	struct intel_engine_cs *engine;
1431b13d190SFrançois Tigeot 
14471f41f3eSFrançois Tigeot 	struct list_head request_list;
14571f41f3eSFrançois Tigeot 
14615ac6249SFrançois Tigeot 	u32 head;
14715ac6249SFrançois Tigeot 	u32 tail;
148*a85cb24fSFrançois Tigeot 	u32 emit;
149*a85cb24fSFrançois Tigeot 
150e3adcf8fSFrançois Tigeot 	int space;
151e3adcf8fSFrançois Tigeot 	int size;
152e3adcf8fSFrançois Tigeot 	int effective_size;
153ba55f2f5SFrançois Tigeot };
154ba55f2f5SFrançois Tigeot 
1551487f786SFrançois Tigeot struct i915_gem_context;
1568621f407SFrançois Tigeot struct drm_i915_reg_table;
1572c9916cdSFrançois Tigeot 
158a05eeebfSFrançois Tigeot /*
159a05eeebfSFrançois Tigeot  * we use a single page to load ctx workarounds so all of these
160a05eeebfSFrançois Tigeot  * values are referred in terms of dwords
161a05eeebfSFrançois Tigeot  *
162a05eeebfSFrançois Tigeot  * struct i915_wa_ctx_bb:
163a05eeebfSFrançois Tigeot  *  offset: specifies batch starting position, also helpful in case
164a05eeebfSFrançois Tigeot  *    if we want to have multiple batches at different offsets based on
165a05eeebfSFrançois Tigeot  *    some criteria. It is not a requirement at the moment but provides
166a05eeebfSFrançois Tigeot  *    an option for future use.
167a05eeebfSFrançois Tigeot  *  size: size of the batch in DWORDS
168a05eeebfSFrançois Tigeot  */
169a05eeebfSFrançois Tigeot struct i915_ctx_workarounds {
170a05eeebfSFrançois Tigeot 	struct i915_wa_ctx_bb {
171a05eeebfSFrançois Tigeot 		u32 offset;
172a05eeebfSFrançois Tigeot 		u32 size;
173a05eeebfSFrançois Tigeot 	} indirect_ctx, per_ctx;
1741e12ee3bSFrançois Tigeot 	struct i915_vma *vma;
175a05eeebfSFrançois Tigeot };
176a05eeebfSFrançois Tigeot 
177303bf270SFrançois Tigeot struct drm_i915_gem_request;
1784be47400SFrançois Tigeot struct intel_render_state;
179303bf270SFrançois Tigeot 
180*a85cb24fSFrançois Tigeot /*
181*a85cb24fSFrançois Tigeot  * Engine IDs definitions.
182*a85cb24fSFrançois Tigeot  * Keep instances of the same type engine together.
183*a85cb24fSFrançois Tigeot  */
1848621f407SFrançois Tigeot enum intel_engine_id {
185c0e85e96SFrançois Tigeot 	RCS = 0,
186ba55f2f5SFrançois Tigeot 	BCS,
187c0e85e96SFrançois Tigeot 	VCS,
188*a85cb24fSFrançois Tigeot 	VCS2,
189c0e85e96SFrançois Tigeot #define _VCS(n) (VCS + (n))
190*a85cb24fSFrançois Tigeot 	VECS
191*a85cb24fSFrançois Tigeot };
192*a85cb24fSFrançois Tigeot 
193*a85cb24fSFrançois Tigeot struct intel_engine_cs {
194*a85cb24fSFrançois Tigeot 	struct drm_i915_private *i915;
195*a85cb24fSFrançois Tigeot 	const char	*name;
196*a85cb24fSFrançois Tigeot 	enum intel_engine_id id;
197c0e85e96SFrançois Tigeot 	unsigned int exec_id;
198*a85cb24fSFrançois Tigeot 	unsigned int hw_id;
199*a85cb24fSFrançois Tigeot 	unsigned int guc_id;
200ba55f2f5SFrançois Tigeot 	u32		mmio_base;
20187df8fc6SFrançois Tigeot 	unsigned int irq_shift;
20271f41f3eSFrançois Tigeot 	struct intel_ring *buffer;
2034be47400SFrançois Tigeot 	struct intel_timeline *timeline;
2044be47400SFrançois Tigeot 
2054be47400SFrançois Tigeot 	struct intel_render_state *render_state;
206ba55f2f5SFrançois Tigeot 
207*a85cb24fSFrançois Tigeot 	atomic_t irq_count;
208*a85cb24fSFrançois Tigeot 	unsigned long irq_posted;
209*a85cb24fSFrançois Tigeot #define ENGINE_IRQ_BREADCRUMB 0
210*a85cb24fSFrançois Tigeot #define ENGINE_IRQ_EXECLIST 1
211*a85cb24fSFrançois Tigeot 
212303bf270SFrançois Tigeot 	/* Rather than have every client wait upon all user interrupts,
213303bf270SFrançois Tigeot 	 * with the herd waking after every interrupt and each doing the
214303bf270SFrançois Tigeot 	 * heavyweight seqno dance, we delegate the task (of being the
215303bf270SFrançois Tigeot 	 * bottom-half of the user interrupt) to the first client. After
216303bf270SFrançois Tigeot 	 * every interrupt, we wake up one client, who does the heavyweight
217303bf270SFrançois Tigeot 	 * coherent seqno read and either goes back to sleep (if incomplete),
218303bf270SFrançois Tigeot 	 * or wakes up all the completed clients in parallel, before then
219303bf270SFrançois Tigeot 	 * transferring the bottom-half status to the next client in the queue.
220303bf270SFrançois Tigeot 	 *
221303bf270SFrançois Tigeot 	 * Compared to walking the entire list of waiters in a single dedicated
222303bf270SFrançois Tigeot 	 * bottom-half, we reduce the latency of the first waiter by avoiding
223303bf270SFrançois Tigeot 	 * a context switch, but incur additional coherent seqno reads when
224303bf270SFrançois Tigeot 	 * following the chain of request breadcrumbs. Since it is most likely
225303bf270SFrançois Tigeot 	 * that we have a single client waiting on each seqno, then reducing
226303bf270SFrançois Tigeot 	 * the overhead of waking that client is much preferred.
227303bf270SFrançois Tigeot 	 */
228303bf270SFrançois Tigeot 	struct intel_breadcrumbs {
229*a85cb24fSFrançois Tigeot 		spinlock_t irq_lock; /* protects irq_*; irqsafe */
230*a85cb24fSFrançois Tigeot 		struct intel_wait *irq_wait; /* oldest waiter by retirement */
231303bf270SFrançois Tigeot 
232*a85cb24fSFrançois Tigeot 		spinlock_t rb_lock; /* protects the rb and wraps irq_lock */
233303bf270SFrançois Tigeot 		struct rb_root waiters; /* sorted by retirement, priority */
234303bf270SFrançois Tigeot 		struct rb_root signals; /* sorted by retirement */
235303bf270SFrançois Tigeot 		struct task_struct *signaler; /* used for fence signalling */
236*a85cb24fSFrançois Tigeot 		struct drm_i915_gem_request __rcu *first_signal;
237303bf270SFrançois Tigeot 		struct timer_list fake_irq; /* used after a missed interrupt */
2381e12ee3bSFrançois Tigeot 		struct timer_list hangcheck; /* detect missed interrupts */
2391e12ee3bSFrançois Tigeot 
240*a85cb24fSFrançois Tigeot 		unsigned int hangcheck_interrupts;
241303bf270SFrançois Tigeot 
242*a85cb24fSFrançois Tigeot 		bool irq_armed : 1;
243303bf270SFrançois Tigeot 		bool irq_enabled : 1;
244*a85cb24fSFrançois Tigeot 		I915_SELFTEST_DECLARE(bool mock : 1);
245303bf270SFrançois Tigeot 	} breadcrumbs;
246303bf270SFrançois Tigeot 
24719c468b4SFrançois Tigeot 	/*
24819c468b4SFrançois Tigeot 	 * A pool of objects to use as shadow copies of client batch buffers
24919c468b4SFrançois Tigeot 	 * when the command parser is enabled. Prevents the client from
25019c468b4SFrançois Tigeot 	 * modifying the batch contents after software parsing.
25119c468b4SFrançois Tigeot 	 */
25219c468b4SFrançois Tigeot 	struct i915_gem_batch_pool batch_pool;
25319c468b4SFrançois Tigeot 
254ba55f2f5SFrançois Tigeot 	struct intel_hw_status_page status_page;
255a05eeebfSFrançois Tigeot 	struct i915_ctx_workarounds wa_ctx;
2561e12ee3bSFrançois Tigeot 	struct i915_vma *scratch;
257e3adcf8fSFrançois Tigeot 
258303bf270SFrançois Tigeot 	u32             irq_keep_mask; /* always keep these interrupts */
25915ac6249SFrançois Tigeot 	u32		irq_enable_mask; /* bitmask to enable ring interrupt */
26087df8fc6SFrançois Tigeot 	void		(*irq_enable)(struct intel_engine_cs *engine);
26187df8fc6SFrançois Tigeot 	void		(*irq_disable)(struct intel_engine_cs *engine);
262e3adcf8fSFrançois Tigeot 
26387df8fc6SFrançois Tigeot 	int		(*init_hw)(struct intel_engine_cs *engine);
2641e12ee3bSFrançois Tigeot 	void		(*reset_hw)(struct intel_engine_cs *engine,
2651e12ee3bSFrançois Tigeot 				    struct drm_i915_gem_request *req);
266e3adcf8fSFrançois Tigeot 
267*a85cb24fSFrançois Tigeot 	void		(*set_default_submission)(struct intel_engine_cs *engine);
268*a85cb24fSFrançois Tigeot 
269*a85cb24fSFrançois Tigeot 	int		(*context_pin)(struct intel_engine_cs *engine,
270*a85cb24fSFrançois Tigeot 				       struct i915_gem_context *ctx);
271*a85cb24fSFrançois Tigeot 	void		(*context_unpin)(struct intel_engine_cs *engine,
272*a85cb24fSFrançois Tigeot 					 struct i915_gem_context *ctx);
273*a85cb24fSFrançois Tigeot 	int		(*request_alloc)(struct drm_i915_gem_request *req);
274a05eeebfSFrançois Tigeot 	int		(*init_context)(struct drm_i915_gem_request *req);
2751b13d190SFrançois Tigeot 
27671f41f3eSFrançois Tigeot 	int		(*emit_flush)(struct drm_i915_gem_request *request,
27771f41f3eSFrançois Tigeot 				      u32 mode);
27871f41f3eSFrançois Tigeot #define EMIT_INVALIDATE	BIT(0)
27971f41f3eSFrançois Tigeot #define EMIT_FLUSH	BIT(1)
28071f41f3eSFrançois Tigeot #define EMIT_BARRIER	(EMIT_INVALIDATE | EMIT_FLUSH)
28171f41f3eSFrançois Tigeot 	int		(*emit_bb_start)(struct drm_i915_gem_request *req,
28271f41f3eSFrançois Tigeot 					 u64 offset, u32 length,
28371f41f3eSFrançois Tigeot 					 unsigned int dispatch_flags);
28471f41f3eSFrançois Tigeot #define I915_DISPATCH_SECURE BIT(0)
28571f41f3eSFrançois Tigeot #define I915_DISPATCH_PINNED BIT(1)
28671f41f3eSFrançois Tigeot #define I915_DISPATCH_RS     BIT(2)
2874be47400SFrançois Tigeot 	void		(*emit_breadcrumb)(struct drm_i915_gem_request *req,
288*a85cb24fSFrançois Tigeot 					   u32 *cs);
2894be47400SFrançois Tigeot 	int		emit_breadcrumb_sz;
2901e12ee3bSFrançois Tigeot 
2911e12ee3bSFrançois Tigeot 	/* Pass the request to the hardware queue (e.g. directly into
2921e12ee3bSFrançois Tigeot 	 * the legacy ringbuffer or to the end of an execlist).
2931e12ee3bSFrançois Tigeot 	 *
2941e12ee3bSFrançois Tigeot 	 * This is called from an atomic context with irqs disabled; must
2951e12ee3bSFrançois Tigeot 	 * be irq safe.
2961e12ee3bSFrançois Tigeot 	 */
29771f41f3eSFrançois Tigeot 	void		(*submit_request)(struct drm_i915_gem_request *req);
2981e12ee3bSFrançois Tigeot 
2994be47400SFrançois Tigeot 	/* Call when the priority on a request has changed and it and its
3004be47400SFrançois Tigeot 	 * dependencies may need rescheduling. Note the request itself may
3014be47400SFrançois Tigeot 	 * not be ready to run!
3024be47400SFrançois Tigeot 	 *
3034be47400SFrançois Tigeot 	 * Called under the struct_mutex.
3044be47400SFrançois Tigeot 	 */
3054be47400SFrançois Tigeot 	void		(*schedule)(struct drm_i915_gem_request *request,
3064be47400SFrançois Tigeot 				    int priority);
3074be47400SFrançois Tigeot 
308b030f26bSFrançois Tigeot 	/* Some chipsets are not quite as coherent as advertised and need
309b030f26bSFrançois Tigeot 	 * an expensive kick to force a true read of the up-to-date seqno.
310b030f26bSFrançois Tigeot 	 * However, the up-to-date seqno is not always required and the last
311b030f26bSFrançois Tigeot 	 * seen value is good enough. Note that the seqno will always be
312b030f26bSFrançois Tigeot 	 * monotonic, even if not coherent.
313b030f26bSFrançois Tigeot 	 */
31487df8fc6SFrançois Tigeot 	void		(*irq_seqno_barrier)(struct intel_engine_cs *engine);
31587df8fc6SFrançois Tigeot 	void		(*cleanup)(struct intel_engine_cs *engine);
316e3adcf8fSFrançois Tigeot 
31724edb884SFrançois Tigeot 	/* GEN8 signal/wait table - never trust comments!
31824edb884SFrançois Tigeot 	 *	  signal to	signal to    signal to   signal to      signal to
31924edb884SFrançois Tigeot 	 *	    RCS		   VCS          BCS        VECS		 VCS2
32024edb884SFrançois Tigeot 	 *      --------------------------------------------------------------------
32124edb884SFrançois Tigeot 	 *  RCS | NOP (0x00) | VCS (0x08) | BCS (0x10) | VECS (0x18) | VCS2 (0x20) |
32224edb884SFrançois Tigeot 	 *	|-------------------------------------------------------------------
32324edb884SFrançois Tigeot 	 *  VCS | RCS (0x28) | NOP (0x30) | BCS (0x38) | VECS (0x40) | VCS2 (0x48) |
32424edb884SFrançois Tigeot 	 *	|-------------------------------------------------------------------
32524edb884SFrançois Tigeot 	 *  BCS | RCS (0x50) | VCS (0x58) | NOP (0x60) | VECS (0x68) | VCS2 (0x70) |
32624edb884SFrançois Tigeot 	 *	|-------------------------------------------------------------------
32724edb884SFrançois Tigeot 	 * VECS | RCS (0x78) | VCS (0x80) | BCS (0x88) |  NOP (0x90) | VCS2 (0x98) |
32824edb884SFrançois Tigeot 	 *	|-------------------------------------------------------------------
32924edb884SFrançois Tigeot 	 * VCS2 | RCS (0xa0) | VCS (0xa8) | BCS (0xb0) | VECS (0xb8) | NOP  (0xc0) |
33024edb884SFrançois Tigeot 	 *	|-------------------------------------------------------------------
33124edb884SFrançois Tigeot 	 *
33224edb884SFrançois Tigeot 	 * Generalization:
33324edb884SFrançois Tigeot 	 *  f(x, y) := (x->id * NUM_RINGS * seqno_size) + (seqno_size * y->id)
33424edb884SFrançois Tigeot 	 *  ie. transpose of g(x, y)
33524edb884SFrançois Tigeot 	 *
33624edb884SFrançois Tigeot 	 *	 sync from	sync from    sync from    sync from	sync from
33724edb884SFrançois Tigeot 	 *	    RCS		   VCS          BCS        VECS		 VCS2
33824edb884SFrançois Tigeot 	 *      --------------------------------------------------------------------
33924edb884SFrançois Tigeot 	 *  RCS | NOP (0x00) | VCS (0x28) | BCS (0x50) | VECS (0x78) | VCS2 (0xa0) |
34024edb884SFrançois Tigeot 	 *	|-------------------------------------------------------------------
34124edb884SFrançois Tigeot 	 *  VCS | RCS (0x08) | NOP (0x30) | BCS (0x58) | VECS (0x80) | VCS2 (0xa8) |
34224edb884SFrançois Tigeot 	 *	|-------------------------------------------------------------------
34324edb884SFrançois Tigeot 	 *  BCS | RCS (0x10) | VCS (0x38) | NOP (0x60) | VECS (0x88) | VCS2 (0xb0) |
34424edb884SFrançois Tigeot 	 *	|-------------------------------------------------------------------
34524edb884SFrançois Tigeot 	 * VECS | RCS (0x18) | VCS (0x40) | BCS (0x68) |  NOP (0x90) | VCS2 (0xb8) |
34624edb884SFrançois Tigeot 	 *	|-------------------------------------------------------------------
34724edb884SFrançois Tigeot 	 * VCS2 | RCS (0x20) | VCS (0x48) | BCS (0x70) | VECS (0x98) |  NOP (0xc0) |
34824edb884SFrançois Tigeot 	 *	|-------------------------------------------------------------------
34924edb884SFrançois Tigeot 	 *
35024edb884SFrançois Tigeot 	 * Generalization:
35124edb884SFrançois Tigeot 	 *  g(x, y) := (y->id * NUM_RINGS * seqno_size) + (seqno_size * x->id)
35224edb884SFrançois Tigeot 	 *  ie. transpose of f(x, y)
35324edb884SFrançois Tigeot 	 */
354ba55f2f5SFrançois Tigeot 	struct {
35524edb884SFrançois Tigeot 		union {
3561e12ee3bSFrançois Tigeot #define GEN6_SEMAPHORE_LAST	VECS_HW
3571e12ee3bSFrançois Tigeot #define GEN6_NUM_SEMAPHORES	(GEN6_SEMAPHORE_LAST + 1)
3581e12ee3bSFrançois Tigeot #define GEN6_SEMAPHORES_MASK	GENMASK(GEN6_SEMAPHORE_LAST, 0)
359ba55f2f5SFrançois Tigeot 			struct {
3605d0b1887SFrançois Tigeot 				/* our mbox written by others */
3611e12ee3bSFrançois Tigeot 				u32		wait[GEN6_NUM_SEMAPHORES];
3625d0b1887SFrançois Tigeot 				/* mboxes this ring signals to */
3631e12ee3bSFrançois Tigeot 				i915_reg_t	signal[GEN6_NUM_SEMAPHORES];
364ba55f2f5SFrançois Tigeot 			} mbox;
3658621f407SFrançois Tigeot 			u64		signal_ggtt[I915_NUM_ENGINES];
36624edb884SFrançois Tigeot 		};
367ba55f2f5SFrançois Tigeot 
368ba55f2f5SFrançois Tigeot 		/* AKA wait() */
36971f41f3eSFrançois Tigeot 		int	(*sync_to)(struct drm_i915_gem_request *req,
37071f41f3eSFrançois Tigeot 				   struct drm_i915_gem_request *signal);
371*a85cb24fSFrançois Tigeot 		u32	*(*signal)(struct drm_i915_gem_request *req, u32 *cs);
372ba55f2f5SFrançois Tigeot 	} semaphore;
3735d0b1887SFrançois Tigeot 
3741b13d190SFrançois Tigeot 	/* Execlists */
3758621f407SFrançois Tigeot 	struct tasklet_struct irq_tasklet;
3761e12ee3bSFrançois Tigeot 	struct execlist_port {
3771e12ee3bSFrançois Tigeot 		struct drm_i915_gem_request *request;
3781e12ee3bSFrançois Tigeot 		unsigned int count;
379*a85cb24fSFrançois Tigeot 		GEM_DEBUG_DECL(u32 context_id);
3801e12ee3bSFrançois Tigeot 	} execlist_port[2];
3814be47400SFrançois Tigeot 	struct rb_root execlist_queue;
3824be47400SFrançois Tigeot 	struct rb_node *execlist_first;
3838621f407SFrançois Tigeot 	unsigned int fw_domains;
384e3adcf8fSFrançois Tigeot 
385*a85cb24fSFrançois Tigeot 	/* Contexts are pinned whilst they are active on the GPU. The last
386*a85cb24fSFrançois Tigeot 	 * context executed remains active whilst the GPU is idle - the
387*a85cb24fSFrançois Tigeot 	 * switch away and write to the context object only occurs on the
388*a85cb24fSFrançois Tigeot 	 * next execution.  Contexts are only unpinned on retirement of the
389*a85cb24fSFrançois Tigeot 	 * following request ensuring that we can always write to the object
390*a85cb24fSFrançois Tigeot 	 * on the context switch even after idling. Across suspend, we switch
391*a85cb24fSFrançois Tigeot 	 * to the kernel context and trash it as the save may not happen
392*a85cb24fSFrançois Tigeot 	 * before the hardware is powered down.
393*a85cb24fSFrançois Tigeot 	 */
394*a85cb24fSFrançois Tigeot 	struct i915_gem_context *last_retired_context;
395*a85cb24fSFrançois Tigeot 
396*a85cb24fSFrançois Tigeot 	/* We track the current MI_SET_CONTEXT in order to eliminate
397*a85cb24fSFrançois Tigeot 	 * redudant context switches. This presumes that requests are not
398*a85cb24fSFrançois Tigeot 	 * reordered! Or when they are the tracking is updated along with
399*a85cb24fSFrançois Tigeot 	 * the emission of individual requests into the legacy command
400*a85cb24fSFrançois Tigeot 	 * stream (ring).
401*a85cb24fSFrançois Tigeot 	 */
402*a85cb24fSFrançois Tigeot 	struct i915_gem_context *legacy_active_context;
403*a85cb24fSFrançois Tigeot 
404*a85cb24fSFrançois Tigeot 	/* status_notifier: list of callbacks for context-switch changes */
405*a85cb24fSFrançois Tigeot 	struct atomic_notifier_head context_status_notifier;
4065d0b1887SFrançois Tigeot 
40771f41f3eSFrançois Tigeot 	struct intel_engine_hangcheck hangcheck;
40815ac6249SFrançois Tigeot 
409ba55f2f5SFrançois Tigeot 	bool needs_cmd_parser;
410ba55f2f5SFrançois Tigeot 
411ba55f2f5SFrançois Tigeot 	/*
412ba55f2f5SFrançois Tigeot 	 * Table of commands the command parser needs to know about
41371f41f3eSFrançois Tigeot 	 * for this engine.
414ba55f2f5SFrançois Tigeot 	 */
415ba55f2f5SFrançois Tigeot 	DECLARE_HASHTABLE(cmd_hash, I915_CMD_HASH_ORDER);
416ba55f2f5SFrançois Tigeot 
417ba55f2f5SFrançois Tigeot 	/*
418ba55f2f5SFrançois Tigeot 	 * Table of registers allowed in commands that read/write registers.
419ba55f2f5SFrançois Tigeot 	 */
4208621f407SFrançois Tigeot 	const struct drm_i915_reg_table *reg_tables;
4218621f407SFrançois Tigeot 	int reg_table_count;
422ba55f2f5SFrançois Tigeot 
423ba55f2f5SFrançois Tigeot 	/*
424ba55f2f5SFrançois Tigeot 	 * Returns the bitmask for the length field of the specified command.
425ba55f2f5SFrançois Tigeot 	 * Return 0 for an unrecognized/invalid command.
426ba55f2f5SFrançois Tigeot 	 *
42771f41f3eSFrançois Tigeot 	 * If the command parser finds an entry for a command in the engine's
428ba55f2f5SFrançois Tigeot 	 * cmd_tables, it gets the command's length based on the table entry.
42971f41f3eSFrançois Tigeot 	 * If not, it calls this function to determine the per-engine length
43071f41f3eSFrançois Tigeot 	 * field encoding for the command (i.e. different opcode ranges use
43171f41f3eSFrançois Tigeot 	 * certain bits to encode the command length in the header).
432ba55f2f5SFrançois Tigeot 	 */
433ba55f2f5SFrançois Tigeot 	u32 (*get_cmd_length_mask)(u32 cmd_header);
434e3adcf8fSFrançois Tigeot };
435e3adcf8fSFrançois Tigeot 
436*a85cb24fSFrançois Tigeot static inline unsigned int
437303bf270SFrançois Tigeot intel_engine_flag(const struct intel_engine_cs *engine)
438e3adcf8fSFrançois Tigeot {
439*a85cb24fSFrançois Tigeot 	return BIT(engine->id);
440352ff8bdSFrançois Tigeot }
441352ff8bdSFrançois Tigeot 
442f4e1c372SFrançois Tigeot static inline u32
4438621f407SFrançois Tigeot intel_read_status_page(struct intel_engine_cs *engine, int reg)
444e3adcf8fSFrançois Tigeot {
445f4e1c372SFrançois Tigeot 	/* Ensure that the compiler doesn't optimize away the load. */
4468621f407SFrançois Tigeot 	return READ_ONCE(engine->status_page.page_addr[reg]);
447e3adcf8fSFrançois Tigeot }
448e3adcf8fSFrançois Tigeot 
449a2fdbec6SFrançois Tigeot static inline void
450*a85cb24fSFrançois Tigeot intel_write_status_page(struct intel_engine_cs *engine, int reg, u32 value)
451a2fdbec6SFrançois Tigeot {
452*a85cb24fSFrançois Tigeot 	/* Writing into the status page should be done sparingly. Since
453*a85cb24fSFrançois Tigeot 	 * we do when we are uncertain of the device state, we take a bit
454*a85cb24fSFrançois Tigeot 	 * of extra paranoia to try and ensure that the HWS takes the value
455*a85cb24fSFrançois Tigeot 	 * we give and that it doesn't end up trapped inside the CPU!
456*a85cb24fSFrançois Tigeot 	 */
457*a85cb24fSFrançois Tigeot 	if (static_cpu_has(X86_FEATURE_CLFLUSH)) {
458*a85cb24fSFrançois Tigeot 		mb();
459*a85cb24fSFrançois Tigeot 		linux_clflush(&engine->status_page.page_addr[reg]);
4608621f407SFrançois Tigeot 		engine->status_page.page_addr[reg] = value;
461*a85cb24fSFrançois Tigeot 		linux_clflush(&engine->status_page.page_addr[reg]);
462*a85cb24fSFrançois Tigeot 		mb();
463*a85cb24fSFrançois Tigeot 	} else {
464*a85cb24fSFrançois Tigeot 		WRITE_ONCE(engine->status_page.page_addr[reg], value);
465*a85cb24fSFrançois Tigeot 	}
466a2fdbec6SFrançois Tigeot }
467a2fdbec6SFrançois Tigeot 
468c0e85e96SFrançois Tigeot /*
469f4e1c372SFrançois Tigeot  * Reads a dword out of the status page, which is written to from the command
470f4e1c372SFrançois Tigeot  * queue by automatic updates, MI_REPORT_HEAD, MI_STORE_DATA_INDEX, or
471f4e1c372SFrançois Tigeot  * MI_STORE_DATA_IMM.
472f4e1c372SFrançois Tigeot  *
473f4e1c372SFrançois Tigeot  * The following dwords have a reserved meaning:
474f4e1c372SFrançois Tigeot  * 0x00: ISR copy, updated when an ISR bit not set in the HWSTAM changes.
475f4e1c372SFrançois Tigeot  * 0x04: ring 0 head pointer
476f4e1c372SFrançois Tigeot  * 0x05: ring 1 head pointer (915-class)
477f4e1c372SFrançois Tigeot  * 0x06: ring 2 head pointer (915-class)
478f4e1c372SFrançois Tigeot  * 0x10-0x1b: Context status DWords (GM45)
479f4e1c372SFrançois Tigeot  * 0x1f: Last written status offset. (GM45)
480477eb7f9SFrançois Tigeot  * 0x20-0x2f: Reserved (Gen6+)
481f4e1c372SFrançois Tigeot  *
482477eb7f9SFrançois Tigeot  * The area from dword 0x30 to 0x3ff is available for driver usage.
483f4e1c372SFrançois Tigeot  */
484477eb7f9SFrançois Tigeot #define I915_GEM_HWS_INDEX		0x30
485c0e85e96SFrançois Tigeot #define I915_GEM_HWS_INDEX_ADDR (I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT)
486477eb7f9SFrançois Tigeot #define I915_GEM_HWS_SCRATCH_INDEX	0x40
487f4e1c372SFrançois Tigeot #define I915_GEM_HWS_SCRATCH_ADDR (I915_GEM_HWS_SCRATCH_INDEX << MI_STORE_DWORD_INDEX_SHIFT)
488e3adcf8fSFrançois Tigeot 
48971f41f3eSFrançois Tigeot struct intel_ring *
49071f41f3eSFrançois Tigeot intel_engine_create_ring(struct intel_engine_cs *engine, int size);
491*a85cb24fSFrançois Tigeot int intel_ring_pin(struct intel_ring *ring, unsigned int offset_bias);
492*a85cb24fSFrançois Tigeot void intel_ring_reset(struct intel_ring *ring, u32 tail);
493*a85cb24fSFrançois Tigeot void intel_ring_update_space(struct intel_ring *ring);
49471f41f3eSFrançois Tigeot void intel_ring_unpin(struct intel_ring *ring);
49571f41f3eSFrançois Tigeot void intel_ring_free(struct intel_ring *ring);
4961b13d190SFrançois Tigeot 
49771f41f3eSFrançois Tigeot void intel_engine_stop(struct intel_engine_cs *engine);
49871f41f3eSFrançois Tigeot void intel_engine_cleanup(struct intel_engine_cs *engine);
499f4e1c372SFrançois Tigeot 
5001e12ee3bSFrançois Tigeot void intel_legacy_submission_resume(struct drm_i915_private *dev_priv);
5011e12ee3bSFrançois Tigeot 
502a05eeebfSFrançois Tigeot int __must_check intel_ring_cacheline_align(struct drm_i915_gem_request *req);
50387df8fc6SFrançois Tigeot 
504*a85cb24fSFrançois Tigeot u32 __must_check *intel_ring_begin(struct drm_i915_gem_request *req, int n);
50587df8fc6SFrançois Tigeot 
506*a85cb24fSFrançois Tigeot static inline void
507*a85cb24fSFrançois Tigeot intel_ring_advance(struct drm_i915_gem_request *req, u32 *cs)
50887df8fc6SFrançois Tigeot {
50971f41f3eSFrançois Tigeot 	/* Dummy function.
51071f41f3eSFrançois Tigeot 	 *
51171f41f3eSFrançois Tigeot 	 * This serves as a placeholder in the code so that the reader
51271f41f3eSFrançois Tigeot 	 * can compare against the preceding intel_ring_begin() and
51371f41f3eSFrançois Tigeot 	 * check that the number of dwords emitted matches the space
51471f41f3eSFrançois Tigeot 	 * reserved for the command packet (i.e. the value passed to
51571f41f3eSFrançois Tigeot 	 * intel_ring_begin()).
51671f41f3eSFrançois Tigeot 	 */
517*a85cb24fSFrançois Tigeot 	GEM_BUG_ON((req->ring->vaddr + req->ring->emit) != cs);
51887df8fc6SFrançois Tigeot }
51987df8fc6SFrançois Tigeot 
520*a85cb24fSFrançois Tigeot static inline u32
521*a85cb24fSFrançois Tigeot intel_ring_wrap(const struct intel_ring *ring, u32 pos)
522*a85cb24fSFrançois Tigeot {
523*a85cb24fSFrançois Tigeot 	return pos & (ring->size - 1);
524*a85cb24fSFrançois Tigeot }
525*a85cb24fSFrançois Tigeot 
526*a85cb24fSFrançois Tigeot static inline u32
527*a85cb24fSFrançois Tigeot intel_ring_offset(const struct drm_i915_gem_request *req, void *addr)
528aee94f86SFrançois Tigeot {
52971f41f3eSFrançois Tigeot 	/* Don't write ring->size (equivalent to 0) as that hangs some GPUs. */
530*a85cb24fSFrançois Tigeot 	u32 offset = addr - req->ring->vaddr;
531*a85cb24fSFrançois Tigeot 	GEM_BUG_ON(offset > req->ring->size);
532*a85cb24fSFrançois Tigeot 	return intel_ring_wrap(req->ring, offset);
5339edbd4a0SFrançois Tigeot }
53487df8fc6SFrançois Tigeot 
535*a85cb24fSFrançois Tigeot static inline void
536*a85cb24fSFrançois Tigeot assert_ring_tail_valid(const struct intel_ring *ring, unsigned int tail)
537*a85cb24fSFrançois Tigeot {
538*a85cb24fSFrançois Tigeot 	/* We could combine these into a single tail operation, but keeping
539*a85cb24fSFrançois Tigeot 	 * them as seperate tests will help identify the cause should one
540*a85cb24fSFrançois Tigeot 	 * ever fire.
541*a85cb24fSFrançois Tigeot 	 */
542*a85cb24fSFrançois Tigeot 	GEM_BUG_ON(!IS_ALIGNED(tail, 8));
543*a85cb24fSFrançois Tigeot 	GEM_BUG_ON(tail >= ring->size);
544*a85cb24fSFrançois Tigeot }
545*a85cb24fSFrançois Tigeot 
546*a85cb24fSFrançois Tigeot static inline unsigned int
547*a85cb24fSFrançois Tigeot intel_ring_set_tail(struct intel_ring *ring, unsigned int tail)
548*a85cb24fSFrançois Tigeot {
549*a85cb24fSFrançois Tigeot 	/* Whilst writes to the tail are strictly order, there is no
550*a85cb24fSFrançois Tigeot 	 * serialisation between readers and the writers. The tail may be
551*a85cb24fSFrançois Tigeot 	 * read by i915_gem_request_retire() just as it is being updated
552*a85cb24fSFrançois Tigeot 	 * by execlists, as although the breadcrumb is complete, the context
553*a85cb24fSFrançois Tigeot 	 * switch hasn't been seen.
554*a85cb24fSFrançois Tigeot 	 */
555*a85cb24fSFrançois Tigeot 	assert_ring_tail_valid(ring, tail);
556*a85cb24fSFrançois Tigeot 	ring->tail = tail;
557*a85cb24fSFrançois Tigeot 	return tail;
558*a85cb24fSFrançois Tigeot }
5599edbd4a0SFrançois Tigeot 
5604be47400SFrançois Tigeot void intel_engine_init_global_seqno(struct intel_engine_cs *engine, u32 seqno);
561e3adcf8fSFrançois Tigeot 
56287df8fc6SFrançois Tigeot void intel_engine_setup_common(struct intel_engine_cs *engine);
56387df8fc6SFrançois Tigeot int intel_engine_init_common(struct intel_engine_cs *engine);
5641e12ee3bSFrançois Tigeot int intel_engine_create_scratch(struct intel_engine_cs *engine, int size);
56571f41f3eSFrançois Tigeot void intel_engine_cleanup_common(struct intel_engine_cs *engine);
56671f41f3eSFrançois Tigeot 
56787df8fc6SFrançois Tigeot int intel_init_render_ring_buffer(struct intel_engine_cs *engine);
56887df8fc6SFrançois Tigeot int intel_init_bsd_ring_buffer(struct intel_engine_cs *engine);
56987df8fc6SFrançois Tigeot int intel_init_bsd2_ring_buffer(struct intel_engine_cs *engine);
57087df8fc6SFrançois Tigeot int intel_init_blt_ring_buffer(struct intel_engine_cs *engine);
57187df8fc6SFrançois Tigeot int intel_init_vebox_ring_buffer(struct intel_engine_cs *engine);
572e3adcf8fSFrançois Tigeot 
57371f41f3eSFrançois Tigeot u64 intel_engine_get_active_head(struct intel_engine_cs *engine);
5741e12ee3bSFrançois Tigeot u64 intel_engine_get_last_batch_head(struct intel_engine_cs *engine);
5751e12ee3bSFrançois Tigeot 
576303bf270SFrançois Tigeot static inline u32 intel_engine_get_seqno(struct intel_engine_cs *engine)
577303bf270SFrançois Tigeot {
578303bf270SFrançois Tigeot 	return intel_read_status_page(engine, I915_GEM_HWS_INDEX);
579303bf270SFrançois Tigeot }
580e3adcf8fSFrançois Tigeot 
5814be47400SFrançois Tigeot static inline u32 intel_engine_last_submit(struct intel_engine_cs *engine)
5824be47400SFrançois Tigeot {
5834be47400SFrançois Tigeot 	/* We are only peeking at the tail of the submit queue (and not the
5844be47400SFrançois Tigeot 	 * queue itself) in order to gain a hint as to the current active
5854be47400SFrançois Tigeot 	 * state of the engine. Callers are not expected to be taking
5864be47400SFrançois Tigeot 	 * engine->timeline->lock, nor are they expected to be concerned
5874be47400SFrançois Tigeot 	 * wtih serialising this hint with anything, so document it as
5884be47400SFrançois Tigeot 	 * a hint and nothing more.
5894be47400SFrançois Tigeot 	 */
590*a85cb24fSFrançois Tigeot 	return READ_ONCE(engine->timeline->seqno);
5914be47400SFrançois Tigeot }
5924be47400SFrançois Tigeot 
5938621f407SFrançois Tigeot int init_workarounds_ring(struct intel_engine_cs *engine);
594*a85cb24fSFrançois Tigeot int intel_ring_workarounds_emit(struct drm_i915_gem_request *req);
5952c9916cdSFrançois Tigeot 
5961e12ee3bSFrançois Tigeot void intel_engine_get_instdone(struct intel_engine_cs *engine,
5971e12ee3bSFrançois Tigeot 			       struct intel_instdone *instdone);
5981e12ee3bSFrançois Tigeot 
599a05eeebfSFrançois Tigeot /*
600a05eeebfSFrançois Tigeot  * Arbitrary size for largest possible 'add request' sequence. The code paths
601a05eeebfSFrançois Tigeot  * are complex and variable. Empirical measurement shows that the worst case
6021487f786SFrançois Tigeot  * is BDW at 192 bytes (6 + 6 + 36 dwords), then ILK at 136 bytes. However,
6031487f786SFrançois Tigeot  * we need to allocate double the largest single packet within that emission
6041487f786SFrançois Tigeot  * to account for tail wraparound (so 6 + 6 + 72 dwords for BDW).
605a05eeebfSFrançois Tigeot  */
6061487f786SFrançois Tigeot #define MIN_SPACE_FOR_ADD_REQUEST 336
607a05eeebfSFrançois Tigeot 
6081487f786SFrançois Tigeot static inline u32 intel_hws_seqno_address(struct intel_engine_cs *engine)
6091487f786SFrançois Tigeot {
6101e12ee3bSFrançois Tigeot 	return engine->status_page.ggtt_offset + I915_GEM_HWS_INDEX_ADDR;
6111487f786SFrançois Tigeot }
612f4e1c372SFrançois Tigeot 
613303bf270SFrançois Tigeot /* intel_breadcrumbs.c -- user interrupt bottom-half for waiters */
614303bf270SFrançois Tigeot int intel_engine_init_breadcrumbs(struct intel_engine_cs *engine);
615303bf270SFrançois Tigeot 
616*a85cb24fSFrançois Tigeot static inline void intel_wait_init(struct intel_wait *wait,
617*a85cb24fSFrançois Tigeot 				   struct drm_i915_gem_request *rq)
618*a85cb24fSFrançois Tigeot {
619*a85cb24fSFrançois Tigeot 	wait->tsk = current;
620*a85cb24fSFrançois Tigeot 	wait->request = rq;
621*a85cb24fSFrançois Tigeot }
622*a85cb24fSFrançois Tigeot 
623*a85cb24fSFrançois Tigeot static inline void intel_wait_init_for_seqno(struct intel_wait *wait, u32 seqno)
624303bf270SFrançois Tigeot {
625303bf270SFrançois Tigeot 	wait->tsk = current;
626303bf270SFrançois Tigeot 	wait->seqno = seqno;
627303bf270SFrançois Tigeot }
628303bf270SFrançois Tigeot 
629*a85cb24fSFrançois Tigeot static inline bool intel_wait_has_seqno(const struct intel_wait *wait)
630*a85cb24fSFrançois Tigeot {
631*a85cb24fSFrançois Tigeot 	return wait->seqno;
632*a85cb24fSFrançois Tigeot }
633*a85cb24fSFrançois Tigeot 
634*a85cb24fSFrançois Tigeot static inline bool
635*a85cb24fSFrançois Tigeot intel_wait_update_seqno(struct intel_wait *wait, u32 seqno)
636*a85cb24fSFrançois Tigeot {
637*a85cb24fSFrançois Tigeot 	wait->seqno = seqno;
638*a85cb24fSFrançois Tigeot 	return intel_wait_has_seqno(wait);
639*a85cb24fSFrançois Tigeot }
640*a85cb24fSFrançois Tigeot 
641*a85cb24fSFrançois Tigeot static inline bool
642*a85cb24fSFrançois Tigeot intel_wait_update_request(struct intel_wait *wait,
643*a85cb24fSFrançois Tigeot 			  const struct drm_i915_gem_request *rq)
644*a85cb24fSFrançois Tigeot {
645*a85cb24fSFrançois Tigeot 	return intel_wait_update_seqno(wait, i915_gem_request_global_seqno(rq));
646*a85cb24fSFrançois Tigeot }
647*a85cb24fSFrançois Tigeot 
648*a85cb24fSFrançois Tigeot static inline bool
649*a85cb24fSFrançois Tigeot intel_wait_check_seqno(const struct intel_wait *wait, u32 seqno)
650*a85cb24fSFrançois Tigeot {
651*a85cb24fSFrançois Tigeot 	return wait->seqno == seqno;
652*a85cb24fSFrançois Tigeot }
653*a85cb24fSFrançois Tigeot 
654*a85cb24fSFrançois Tigeot static inline bool
655*a85cb24fSFrançois Tigeot intel_wait_check_request(const struct intel_wait *wait,
656*a85cb24fSFrançois Tigeot 			 const struct drm_i915_gem_request *rq)
657*a85cb24fSFrançois Tigeot {
658*a85cb24fSFrançois Tigeot 	return intel_wait_check_seqno(wait, i915_gem_request_global_seqno(rq));
659*a85cb24fSFrançois Tigeot }
660*a85cb24fSFrançois Tigeot 
661303bf270SFrançois Tigeot static inline bool intel_wait_complete(const struct intel_wait *wait)
662303bf270SFrançois Tigeot {
663303bf270SFrançois Tigeot 	return RB_EMPTY_NODE(&wait->node);
664303bf270SFrançois Tigeot }
665303bf270SFrançois Tigeot 
666303bf270SFrançois Tigeot bool intel_engine_add_wait(struct intel_engine_cs *engine,
667303bf270SFrançois Tigeot 			   struct intel_wait *wait);
668303bf270SFrançois Tigeot void intel_engine_remove_wait(struct intel_engine_cs *engine,
669303bf270SFrançois Tigeot 			      struct intel_wait *wait);
670303bf270SFrançois Tigeot void intel_engine_enable_signaling(struct drm_i915_gem_request *request);
671*a85cb24fSFrançois Tigeot void intel_engine_cancel_signaling(struct drm_i915_gem_request *request);
672303bf270SFrançois Tigeot 
6731e12ee3bSFrançois Tigeot static inline bool intel_engine_has_waiter(const struct intel_engine_cs *engine)
674303bf270SFrançois Tigeot {
675*a85cb24fSFrançois Tigeot 	return READ_ONCE(engine->breadcrumbs.irq_wait);
676303bf270SFrançois Tigeot }
677303bf270SFrançois Tigeot 
678*a85cb24fSFrançois Tigeot unsigned int intel_engine_wakeup(struct intel_engine_cs *engine);
679*a85cb24fSFrançois Tigeot #define ENGINE_WAKEUP_WAITER BIT(0)
680*a85cb24fSFrançois Tigeot #define ENGINE_WAKEUP_ASLEEP BIT(1)
6811e12ee3bSFrançois Tigeot 
682*a85cb24fSFrançois Tigeot void __intel_engine_disarm_breadcrumbs(struct intel_engine_cs *engine);
683*a85cb24fSFrançois Tigeot void intel_engine_disarm_breadcrumbs(struct intel_engine_cs *engine);
684303bf270SFrançois Tigeot 
6851e12ee3bSFrançois Tigeot void intel_engine_reset_breadcrumbs(struct intel_engine_cs *engine);
686303bf270SFrançois Tigeot void intel_engine_fini_breadcrumbs(struct intel_engine_cs *engine);
687*a85cb24fSFrançois Tigeot bool intel_breadcrumbs_busy(struct intel_engine_cs *engine);
688*a85cb24fSFrançois Tigeot 
689*a85cb24fSFrançois Tigeot static inline u32 *gen8_emit_pipe_control(u32 *batch, u32 flags, u32 offset)
690*a85cb24fSFrançois Tigeot {
691*a85cb24fSFrançois Tigeot 	memset(batch, 0, 6 * sizeof(u32));
692*a85cb24fSFrançois Tigeot 
693*a85cb24fSFrançois Tigeot 	batch[0] = GFX_OP_PIPE_CONTROL(6);
694*a85cb24fSFrançois Tigeot 	batch[1] = flags;
695*a85cb24fSFrançois Tigeot 	batch[2] = offset;
696*a85cb24fSFrançois Tigeot 
697*a85cb24fSFrançois Tigeot 	return batch + 6;
698*a85cb24fSFrançois Tigeot }
699*a85cb24fSFrançois Tigeot 
700*a85cb24fSFrançois Tigeot bool intel_engine_is_idle(struct intel_engine_cs *engine);
701*a85cb24fSFrançois Tigeot bool intel_engines_are_idle(struct drm_i915_private *dev_priv);
702*a85cb24fSFrançois Tigeot 
703*a85cb24fSFrançois Tigeot void intel_engines_reset_default_submission(struct drm_i915_private *i915);
70471f41f3eSFrançois Tigeot 
705e3adcf8fSFrançois Tigeot #endif /* _INTEL_RINGBUFFER_H_ */
706