xref: /dflybsd-src/sys/dev/drm/i915/intel_ringbuffer.c (revision 303bf2704d314de5be18baeedb8cdc82d3f944de)
1e3adcf8fSFrançois Tigeot /*
2e3adcf8fSFrançois Tigeot  * Copyright © 2008-2010 Intel Corporation
3e3adcf8fSFrançois Tigeot  *
4e3adcf8fSFrançois Tigeot  * Permission is hereby granted, free of charge, to any person obtaining a
5e3adcf8fSFrançois Tigeot  * copy of this software and associated documentation files (the "Software"),
6e3adcf8fSFrançois Tigeot  * to deal in the Software without restriction, including without limitation
7e3adcf8fSFrançois Tigeot  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8e3adcf8fSFrançois Tigeot  * and/or sell copies of the Software, and to permit persons to whom the
9e3adcf8fSFrançois Tigeot  * Software is furnished to do so, subject to the following conditions:
10e3adcf8fSFrançois Tigeot  *
11e3adcf8fSFrançois Tigeot  * The above copyright notice and this permission notice (including the next
12e3adcf8fSFrançois Tigeot  * paragraph) shall be included in all copies or substantial portions of the
13e3adcf8fSFrançois Tigeot  * Software.
14e3adcf8fSFrançois Tigeot  *
15e3adcf8fSFrançois Tigeot  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16e3adcf8fSFrançois Tigeot  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17e3adcf8fSFrançois Tigeot  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18e3adcf8fSFrançois Tigeot  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19e3adcf8fSFrançois Tigeot  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20e3adcf8fSFrançois Tigeot  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21e3adcf8fSFrançois Tigeot  * IN THE SOFTWARE.
22e3adcf8fSFrançois Tigeot  *
23e3adcf8fSFrançois Tigeot  * Authors:
24e3adcf8fSFrançois Tigeot  *    Eric Anholt <eric@anholt.net>
25e3adcf8fSFrançois Tigeot  *    Zou Nan hai <nanhai.zou@intel.com>
26e3adcf8fSFrançois Tigeot  *    Xiang Hai hao<haihao.xiang@intel.com>
27e3adcf8fSFrançois Tigeot  *
28e3adcf8fSFrançois Tigeot  */
29e3adcf8fSFrançois Tigeot 
30aee94f86SFrançois Tigeot #include <linux/log2.h>
3118e26a6dSFrançois Tigeot #include <drm/drmP.h>
32e3adcf8fSFrançois Tigeot #include "i915_drv.h"
33a2fdbec6SFrançois Tigeot #include <drm/i915_drm.h>
34a2fdbec6SFrançois Tigeot #include "i915_trace.h"
35e3adcf8fSFrançois Tigeot #include "intel_drv.h"
36e3adcf8fSFrançois Tigeot 
371487f786SFrançois Tigeot /* Rough estimate of the typical request size, performing a flush,
381487f786SFrançois Tigeot  * set-context and then emitting the batch.
391487f786SFrançois Tigeot  */
401487f786SFrançois Tigeot #define LEGACY_REQUEST_SIZE 200
411487f786SFrançois Tigeot 
421b13d190SFrançois Tigeot int __intel_ring_space(int head, int tail, int size)
43e3adcf8fSFrançois Tigeot {
442c9916cdSFrançois Tigeot 	int space = head - tail;
452c9916cdSFrançois Tigeot 	if (space <= 0)
46ba55f2f5SFrançois Tigeot 		space += size;
472c9916cdSFrançois Tigeot 	return space - I915_RING_FREE_SPACE;
482c9916cdSFrançois Tigeot }
492c9916cdSFrançois Tigeot 
502c9916cdSFrançois Tigeot void intel_ring_update_space(struct intel_ringbuffer *ringbuf)
512c9916cdSFrançois Tigeot {
522c9916cdSFrançois Tigeot 	if (ringbuf->last_retired_head != -1) {
532c9916cdSFrançois Tigeot 		ringbuf->head = ringbuf->last_retired_head;
542c9916cdSFrançois Tigeot 		ringbuf->last_retired_head = -1;
552c9916cdSFrançois Tigeot 	}
562c9916cdSFrançois Tigeot 
572c9916cdSFrançois Tigeot 	ringbuf->space = __intel_ring_space(ringbuf->head & HEAD_ADDR,
582c9916cdSFrançois Tigeot 					    ringbuf->tail, ringbuf->size);
59e3adcf8fSFrançois Tigeot }
60e3adcf8fSFrançois Tigeot 
618621f407SFrançois Tigeot static void __intel_ring_advance(struct intel_engine_cs *engine)
629edbd4a0SFrançois Tigeot {
638621f407SFrançois Tigeot 	struct intel_ringbuffer *ringbuf = engine->buffer;
64ba55f2f5SFrançois Tigeot 	ringbuf->tail &= ringbuf->size - 1;
658621f407SFrançois Tigeot 	engine->write_tail(engine, ringbuf->tail);
669edbd4a0SFrançois Tigeot }
679edbd4a0SFrançois Tigeot 
68e3adcf8fSFrançois Tigeot static int
69a05eeebfSFrançois Tigeot gen2_render_ring_flush(struct drm_i915_gem_request *req,
70686a02f1SFrançois Tigeot 		       u32	invalidate_domains,
71686a02f1SFrançois Tigeot 		       u32	flush_domains)
72686a02f1SFrançois Tigeot {
738621f407SFrançois Tigeot 	struct intel_engine_cs *engine = req->engine;
74686a02f1SFrançois Tigeot 	u32 cmd;
75686a02f1SFrançois Tigeot 	int ret;
76686a02f1SFrançois Tigeot 
77686a02f1SFrançois Tigeot 	cmd = MI_FLUSH;
78686a02f1SFrançois Tigeot 	if (((invalidate_domains|flush_domains) & I915_GEM_DOMAIN_RENDER) == 0)
79686a02f1SFrançois Tigeot 		cmd |= MI_NO_WRITE_FLUSH;
80686a02f1SFrançois Tigeot 
81686a02f1SFrançois Tigeot 	if (invalidate_domains & I915_GEM_DOMAIN_SAMPLER)
82686a02f1SFrançois Tigeot 		cmd |= MI_READ_FLUSH;
83686a02f1SFrançois Tigeot 
84a05eeebfSFrançois Tigeot 	ret = intel_ring_begin(req, 2);
85686a02f1SFrançois Tigeot 	if (ret)
86686a02f1SFrançois Tigeot 		return ret;
87686a02f1SFrançois Tigeot 
888621f407SFrançois Tigeot 	intel_ring_emit(engine, cmd);
898621f407SFrançois Tigeot 	intel_ring_emit(engine, MI_NOOP);
908621f407SFrançois Tigeot 	intel_ring_advance(engine);
91686a02f1SFrançois Tigeot 
92686a02f1SFrançois Tigeot 	return 0;
93686a02f1SFrançois Tigeot }
94686a02f1SFrançois Tigeot 
95686a02f1SFrançois Tigeot static int
96a05eeebfSFrançois Tigeot gen4_render_ring_flush(struct drm_i915_gem_request *req,
97686a02f1SFrançois Tigeot 		       u32	invalidate_domains,
98686a02f1SFrançois Tigeot 		       u32	flush_domains)
99e3adcf8fSFrançois Tigeot {
1008621f407SFrançois Tigeot 	struct intel_engine_cs *engine = req->engine;
101686a02f1SFrançois Tigeot 	u32 cmd;
102e3adcf8fSFrançois Tigeot 	int ret;
103e3adcf8fSFrançois Tigeot 
104e3adcf8fSFrançois Tigeot 	/*
105e3adcf8fSFrançois Tigeot 	 * read/write caches:
106e3adcf8fSFrançois Tigeot 	 *
107e3adcf8fSFrançois Tigeot 	 * I915_GEM_DOMAIN_RENDER is always invalidated, but is
108e3adcf8fSFrançois Tigeot 	 * only flushed if MI_NO_WRITE_FLUSH is unset.  On 965, it is
109e3adcf8fSFrançois Tigeot 	 * also flushed at 2d versus 3d pipeline switches.
110e3adcf8fSFrançois Tigeot 	 *
111e3adcf8fSFrançois Tigeot 	 * read-only caches:
112e3adcf8fSFrançois Tigeot 	 *
113e3adcf8fSFrançois Tigeot 	 * I915_GEM_DOMAIN_SAMPLER is flushed on pre-965 if
114e3adcf8fSFrançois Tigeot 	 * MI_READ_FLUSH is set, and is always flushed on 965.
115e3adcf8fSFrançois Tigeot 	 *
116e3adcf8fSFrançois Tigeot 	 * I915_GEM_DOMAIN_COMMAND may not exist?
117e3adcf8fSFrançois Tigeot 	 *
118e3adcf8fSFrançois Tigeot 	 * I915_GEM_DOMAIN_INSTRUCTION, which exists on 965, is
119e3adcf8fSFrançois Tigeot 	 * invalidated when MI_EXE_FLUSH is set.
120e3adcf8fSFrançois Tigeot 	 *
121e3adcf8fSFrançois Tigeot 	 * I915_GEM_DOMAIN_VERTEX, which exists on 965, is
122e3adcf8fSFrançois Tigeot 	 * invalidated with every MI_FLUSH.
123e3adcf8fSFrançois Tigeot 	 *
124e3adcf8fSFrançois Tigeot 	 * TLBs:
125e3adcf8fSFrançois Tigeot 	 *
126e3adcf8fSFrançois Tigeot 	 * On 965, TLBs associated with I915_GEM_DOMAIN_COMMAND
127e3adcf8fSFrançois Tigeot 	 * and I915_GEM_DOMAIN_CPU in are invalidated at PTE write and
128e3adcf8fSFrançois Tigeot 	 * I915_GEM_DOMAIN_RENDER and I915_GEM_DOMAIN_SAMPLER
129e3adcf8fSFrançois Tigeot 	 * are flushed at any MI_FLUSH.
130e3adcf8fSFrançois Tigeot 	 */
131e3adcf8fSFrançois Tigeot 
132e3adcf8fSFrançois Tigeot 	cmd = MI_FLUSH | MI_NO_WRITE_FLUSH;
133686a02f1SFrançois Tigeot 	if ((invalidate_domains|flush_domains) & I915_GEM_DOMAIN_RENDER)
134e3adcf8fSFrançois Tigeot 		cmd &= ~MI_NO_WRITE_FLUSH;
135e3adcf8fSFrançois Tigeot 	if (invalidate_domains & I915_GEM_DOMAIN_INSTRUCTION)
136e3adcf8fSFrançois Tigeot 		cmd |= MI_EXE_FLUSH;
137e3adcf8fSFrançois Tigeot 
138e3adcf8fSFrançois Tigeot 	if (invalidate_domains & I915_GEM_DOMAIN_COMMAND &&
1391487f786SFrançois Tigeot 	    (IS_G4X(req->i915) || IS_GEN5(req->i915)))
140e3adcf8fSFrançois Tigeot 		cmd |= MI_INVALIDATE_ISP;
141e3adcf8fSFrançois Tigeot 
142a05eeebfSFrançois Tigeot 	ret = intel_ring_begin(req, 2);
143e3adcf8fSFrançois Tigeot 	if (ret)
144e3adcf8fSFrançois Tigeot 		return ret;
145e3adcf8fSFrançois Tigeot 
1468621f407SFrançois Tigeot 	intel_ring_emit(engine, cmd);
1478621f407SFrançois Tigeot 	intel_ring_emit(engine, MI_NOOP);
1488621f407SFrançois Tigeot 	intel_ring_advance(engine);
149e3adcf8fSFrançois Tigeot 
150e3adcf8fSFrançois Tigeot 	return 0;
151e3adcf8fSFrançois Tigeot }
152e3adcf8fSFrançois Tigeot 
153e3adcf8fSFrançois Tigeot /**
154e3adcf8fSFrançois Tigeot  * Emits a PIPE_CONTROL with a non-zero post-sync operation, for
155e3adcf8fSFrançois Tigeot  * implementing two workarounds on gen6.  From section 1.4.7.1
156e3adcf8fSFrançois Tigeot  * "PIPE_CONTROL" of the Sandy Bridge PRM volume 2 part 1:
157e3adcf8fSFrançois Tigeot  *
158e3adcf8fSFrançois Tigeot  * [DevSNB-C+{W/A}] Before any depth stall flush (including those
159e3adcf8fSFrançois Tigeot  * produced by non-pipelined state commands), software needs to first
160e3adcf8fSFrançois Tigeot  * send a PIPE_CONTROL with no bits set except Post-Sync Operation !=
161e3adcf8fSFrançois Tigeot  * 0.
162e3adcf8fSFrançois Tigeot  *
163e3adcf8fSFrançois Tigeot  * [Dev-SNB{W/A}]: Before a PIPE_CONTROL with Write Cache Flush Enable
164e3adcf8fSFrançois Tigeot  * =1, a PIPE_CONTROL with any non-zero post-sync-op is required.
165e3adcf8fSFrançois Tigeot  *
166e3adcf8fSFrançois Tigeot  * And the workaround for these two requires this workaround first:
167e3adcf8fSFrançois Tigeot  *
168e3adcf8fSFrançois Tigeot  * [Dev-SNB{W/A}]: Pipe-control with CS-stall bit set must be sent
169e3adcf8fSFrançois Tigeot  * BEFORE the pipe-control with a post-sync op and no write-cache
170e3adcf8fSFrançois Tigeot  * flushes.
171e3adcf8fSFrançois Tigeot  *
172e3adcf8fSFrançois Tigeot  * And this last workaround is tricky because of the requirements on
173e3adcf8fSFrançois Tigeot  * that bit.  From section 1.4.7.2.3 "Stall" of the Sandy Bridge PRM
174e3adcf8fSFrançois Tigeot  * volume 2 part 1:
175e3adcf8fSFrançois Tigeot  *
176e3adcf8fSFrançois Tigeot  *     "1 of the following must also be set:
177e3adcf8fSFrançois Tigeot  *      - Render Target Cache Flush Enable ([12] of DW1)
178e3adcf8fSFrançois Tigeot  *      - Depth Cache Flush Enable ([0] of DW1)
179e3adcf8fSFrançois Tigeot  *      - Stall at Pixel Scoreboard ([1] of DW1)
180e3adcf8fSFrançois Tigeot  *      - Depth Stall ([13] of DW1)
181e3adcf8fSFrançois Tigeot  *      - Post-Sync Operation ([13] of DW1)
182e3adcf8fSFrançois Tigeot  *      - Notify Enable ([8] of DW1)"
183e3adcf8fSFrançois Tigeot  *
184e3adcf8fSFrançois Tigeot  * The cache flushes require the workaround flush that triggered this
185e3adcf8fSFrançois Tigeot  * one, so we can't use it.  Depth stall would trigger the same.
186e3adcf8fSFrançois Tigeot  * Post-sync nonzero is what triggered this second workaround, so we
187e3adcf8fSFrançois Tigeot  * can't use that one either.  Notify enable is IRQs, which aren't
188e3adcf8fSFrançois Tigeot  * really our business.  That leaves only stall at scoreboard.
189e3adcf8fSFrançois Tigeot  */
190e3adcf8fSFrançois Tigeot static int
191a05eeebfSFrançois Tigeot intel_emit_post_sync_nonzero_flush(struct drm_i915_gem_request *req)
192e3adcf8fSFrançois Tigeot {
1938621f407SFrançois Tigeot 	struct intel_engine_cs *engine = req->engine;
1948621f407SFrançois Tigeot 	u32 scratch_addr = engine->scratch.gtt_offset + 2 * CACHELINE_BYTES;
195e3adcf8fSFrançois Tigeot 	int ret;
196e3adcf8fSFrançois Tigeot 
197a05eeebfSFrançois Tigeot 	ret = intel_ring_begin(req, 6);
198e3adcf8fSFrançois Tigeot 	if (ret)
199e3adcf8fSFrançois Tigeot 		return ret;
200e3adcf8fSFrançois Tigeot 
2018621f407SFrançois Tigeot 	intel_ring_emit(engine, GFX_OP_PIPE_CONTROL(5));
2028621f407SFrançois Tigeot 	intel_ring_emit(engine, PIPE_CONTROL_CS_STALL |
203e3adcf8fSFrançois Tigeot 			PIPE_CONTROL_STALL_AT_SCOREBOARD);
2048621f407SFrançois Tigeot 	intel_ring_emit(engine, scratch_addr | PIPE_CONTROL_GLOBAL_GTT); /* address */
2058621f407SFrançois Tigeot 	intel_ring_emit(engine, 0); /* low dword */
2068621f407SFrançois Tigeot 	intel_ring_emit(engine, 0); /* high dword */
2078621f407SFrançois Tigeot 	intel_ring_emit(engine, MI_NOOP);
2088621f407SFrançois Tigeot 	intel_ring_advance(engine);
209e3adcf8fSFrançois Tigeot 
210a05eeebfSFrançois Tigeot 	ret = intel_ring_begin(req, 6);
211e3adcf8fSFrançois Tigeot 	if (ret)
212e3adcf8fSFrançois Tigeot 		return ret;
213e3adcf8fSFrançois Tigeot 
2148621f407SFrançois Tigeot 	intel_ring_emit(engine, GFX_OP_PIPE_CONTROL(5));
2158621f407SFrançois Tigeot 	intel_ring_emit(engine, PIPE_CONTROL_QW_WRITE);
2168621f407SFrançois Tigeot 	intel_ring_emit(engine, scratch_addr | PIPE_CONTROL_GLOBAL_GTT); /* address */
2178621f407SFrançois Tigeot 	intel_ring_emit(engine, 0);
2188621f407SFrançois Tigeot 	intel_ring_emit(engine, 0);
2198621f407SFrançois Tigeot 	intel_ring_emit(engine, MI_NOOP);
2208621f407SFrançois Tigeot 	intel_ring_advance(engine);
221e3adcf8fSFrançois Tigeot 
222e3adcf8fSFrançois Tigeot 	return 0;
223e3adcf8fSFrançois Tigeot }
224e3adcf8fSFrançois Tigeot 
225e3adcf8fSFrançois Tigeot static int
226a05eeebfSFrançois Tigeot gen6_render_ring_flush(struct drm_i915_gem_request *req,
227e3adcf8fSFrançois Tigeot 		       u32 invalidate_domains, u32 flush_domains)
228e3adcf8fSFrançois Tigeot {
2298621f407SFrançois Tigeot 	struct intel_engine_cs *engine = req->engine;
230e3adcf8fSFrançois Tigeot 	u32 flags = 0;
2318621f407SFrançois Tigeot 	u32 scratch_addr = engine->scratch.gtt_offset + 2 * CACHELINE_BYTES;
232e3adcf8fSFrançois Tigeot 	int ret;
233e3adcf8fSFrançois Tigeot 
234e3adcf8fSFrançois Tigeot 	/* Force SNB workarounds for PIPE_CONTROL flushes */
235a05eeebfSFrançois Tigeot 	ret = intel_emit_post_sync_nonzero_flush(req);
236686a02f1SFrançois Tigeot 	if (ret)
237686a02f1SFrançois Tigeot 		return ret;
238e3adcf8fSFrançois Tigeot 
239e3adcf8fSFrançois Tigeot 	/* Just flush everything.  Experiments have shown that reducing the
240e3adcf8fSFrançois Tigeot 	 * number of bits based on the write domains has little performance
241e3adcf8fSFrançois Tigeot 	 * impact.
242e3adcf8fSFrançois Tigeot 	 */
243b5c29a34SFrançois Tigeot 	if (flush_domains) {
244e3adcf8fSFrançois Tigeot 		flags |= PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH;
245b5c29a34SFrançois Tigeot 		flags |= PIPE_CONTROL_DEPTH_CACHE_FLUSH;
246b5c29a34SFrançois Tigeot 		/*
247b5c29a34SFrançois Tigeot 		 * Ensure that any following seqno writes only happen
248b5c29a34SFrançois Tigeot 		 * when the render cache is indeed flushed.
249b5c29a34SFrançois Tigeot 		 */
250b5c29a34SFrançois Tigeot 		flags |= PIPE_CONTROL_CS_STALL;
251b5c29a34SFrançois Tigeot 	}
252b5c29a34SFrançois Tigeot 	if (invalidate_domains) {
253686a02f1SFrançois Tigeot 		flags |= PIPE_CONTROL_TLB_INVALIDATE;
254e3adcf8fSFrançois Tigeot 		flags |= PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE;
255e3adcf8fSFrançois Tigeot 		flags |= PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE;
256e3adcf8fSFrançois Tigeot 		flags |= PIPE_CONTROL_VF_CACHE_INVALIDATE;
257e3adcf8fSFrançois Tigeot 		flags |= PIPE_CONTROL_CONST_CACHE_INVALIDATE;
258e3adcf8fSFrançois Tigeot 		flags |= PIPE_CONTROL_STATE_CACHE_INVALIDATE;
259686a02f1SFrançois Tigeot 		/*
260b5c29a34SFrançois Tigeot 		 * TLB invalidate requires a post-sync write.
261686a02f1SFrançois Tigeot 		 */
262b5c29a34SFrançois Tigeot 		flags |= PIPE_CONTROL_QW_WRITE | PIPE_CONTROL_CS_STALL;
263b5c29a34SFrançois Tigeot 	}
264e3adcf8fSFrançois Tigeot 
265a05eeebfSFrançois Tigeot 	ret = intel_ring_begin(req, 4);
266e3adcf8fSFrançois Tigeot 	if (ret)
267e3adcf8fSFrançois Tigeot 		return ret;
268e3adcf8fSFrançois Tigeot 
2698621f407SFrançois Tigeot 	intel_ring_emit(engine, GFX_OP_PIPE_CONTROL(4));
2708621f407SFrançois Tigeot 	intel_ring_emit(engine, flags);
2718621f407SFrançois Tigeot 	intel_ring_emit(engine, scratch_addr | PIPE_CONTROL_GLOBAL_GTT);
2728621f407SFrançois Tigeot 	intel_ring_emit(engine, 0);
2738621f407SFrançois Tigeot 	intel_ring_advance(engine);
274b5c29a34SFrançois Tigeot 
275b5c29a34SFrançois Tigeot 	return 0;
276b5c29a34SFrançois Tigeot }
277b5c29a34SFrançois Tigeot 
278b5c29a34SFrançois Tigeot static int
279a05eeebfSFrançois Tigeot gen7_render_ring_cs_stall_wa(struct drm_i915_gem_request *req)
280b5c29a34SFrançois Tigeot {
2818621f407SFrançois Tigeot 	struct intel_engine_cs *engine = req->engine;
282b5c29a34SFrançois Tigeot 	int ret;
283b5c29a34SFrançois Tigeot 
284a05eeebfSFrançois Tigeot 	ret = intel_ring_begin(req, 4);
285b5c29a34SFrançois Tigeot 	if (ret)
286b5c29a34SFrançois Tigeot 		return ret;
287b5c29a34SFrançois Tigeot 
2888621f407SFrançois Tigeot 	intel_ring_emit(engine, GFX_OP_PIPE_CONTROL(4));
2898621f407SFrançois Tigeot 	intel_ring_emit(engine, PIPE_CONTROL_CS_STALL |
290b5c29a34SFrançois Tigeot 			      PIPE_CONTROL_STALL_AT_SCOREBOARD);
2918621f407SFrançois Tigeot 	intel_ring_emit(engine, 0);
2928621f407SFrançois Tigeot 	intel_ring_emit(engine, 0);
2938621f407SFrançois Tigeot 	intel_ring_advance(engine);
294b5c29a34SFrançois Tigeot 
295b5c29a34SFrançois Tigeot 	return 0;
296b5c29a34SFrançois Tigeot }
297b5c29a34SFrançois Tigeot 
298b5c29a34SFrançois Tigeot static int
299a05eeebfSFrançois Tigeot gen7_render_ring_flush(struct drm_i915_gem_request *req,
300b5c29a34SFrançois Tigeot 		       u32 invalidate_domains, u32 flush_domains)
301b5c29a34SFrançois Tigeot {
3028621f407SFrançois Tigeot 	struct intel_engine_cs *engine = req->engine;
303b5c29a34SFrançois Tigeot 	u32 flags = 0;
3048621f407SFrançois Tigeot 	u32 scratch_addr = engine->scratch.gtt_offset + 2 * CACHELINE_BYTES;
305b5c29a34SFrançois Tigeot 	int ret;
306b5c29a34SFrançois Tigeot 
307b5c29a34SFrançois Tigeot 	/*
308b5c29a34SFrançois Tigeot 	 * Ensure that any following seqno writes only happen when the render
309b5c29a34SFrançois Tigeot 	 * cache is indeed flushed.
310b5c29a34SFrançois Tigeot 	 *
311b5c29a34SFrançois Tigeot 	 * Workaround: 4th PIPE_CONTROL command (except the ones with only
312b5c29a34SFrançois Tigeot 	 * read-cache invalidate bits set) must have the CS_STALL bit set. We
313b5c29a34SFrançois Tigeot 	 * don't try to be clever and just set it unconditionally.
314b5c29a34SFrançois Tigeot 	 */
315b5c29a34SFrançois Tigeot 	flags |= PIPE_CONTROL_CS_STALL;
316b5c29a34SFrançois Tigeot 
317b5c29a34SFrançois Tigeot 	/* Just flush everything.  Experiments have shown that reducing the
318b5c29a34SFrançois Tigeot 	 * number of bits based on the write domains has little performance
319b5c29a34SFrançois Tigeot 	 * impact.
320b5c29a34SFrançois Tigeot 	 */
321b5c29a34SFrançois Tigeot 	if (flush_domains) {
322b5c29a34SFrançois Tigeot 		flags |= PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH;
323b5c29a34SFrançois Tigeot 		flags |= PIPE_CONTROL_DEPTH_CACHE_FLUSH;
324aee94f86SFrançois Tigeot 		flags |= PIPE_CONTROL_DC_FLUSH_ENABLE;
325b49c8cf9SFrançois Tigeot 		flags |= PIPE_CONTROL_FLUSH_ENABLE;
326b5c29a34SFrançois Tigeot 	}
327b5c29a34SFrançois Tigeot 	if (invalidate_domains) {
328b5c29a34SFrançois Tigeot 		flags |= PIPE_CONTROL_TLB_INVALIDATE;
329b5c29a34SFrançois Tigeot 		flags |= PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE;
330b5c29a34SFrançois Tigeot 		flags |= PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE;
331b5c29a34SFrançois Tigeot 		flags |= PIPE_CONTROL_VF_CACHE_INVALIDATE;
332b5c29a34SFrançois Tigeot 		flags |= PIPE_CONTROL_CONST_CACHE_INVALIDATE;
333b5c29a34SFrançois Tigeot 		flags |= PIPE_CONTROL_STATE_CACHE_INVALIDATE;
3342c9916cdSFrançois Tigeot 		flags |= PIPE_CONTROL_MEDIA_STATE_CLEAR;
335b5c29a34SFrançois Tigeot 		/*
336b5c29a34SFrançois Tigeot 		 * TLB invalidate requires a post-sync write.
337b5c29a34SFrançois Tigeot 		 */
338b5c29a34SFrançois Tigeot 		flags |= PIPE_CONTROL_QW_WRITE;
339a2fdbec6SFrançois Tigeot 		flags |= PIPE_CONTROL_GLOBAL_GTT_IVB;
340b5c29a34SFrançois Tigeot 
3410dbf0ea8SMatthew Dillon 		flags |= PIPE_CONTROL_STALL_AT_SCOREBOARD;
3420dbf0ea8SMatthew Dillon 
343b5c29a34SFrançois Tigeot 		/* Workaround: we must issue a pipe_control with CS-stall bit
344b5c29a34SFrançois Tigeot 		 * set before a pipe_control command that has the state cache
345b5c29a34SFrançois Tigeot 		 * invalidate bit set. */
346a05eeebfSFrançois Tigeot 		gen7_render_ring_cs_stall_wa(req);
347b5c29a34SFrançois Tigeot 	}
348b5c29a34SFrançois Tigeot 
349a05eeebfSFrançois Tigeot 	ret = intel_ring_begin(req, 4);
350b5c29a34SFrançois Tigeot 	if (ret)
351b5c29a34SFrançois Tigeot 		return ret;
352b5c29a34SFrançois Tigeot 
3538621f407SFrançois Tigeot 	intel_ring_emit(engine, GFX_OP_PIPE_CONTROL(4));
3548621f407SFrançois Tigeot 	intel_ring_emit(engine, flags);
3558621f407SFrançois Tigeot 	intel_ring_emit(engine, scratch_addr);
3568621f407SFrançois Tigeot 	intel_ring_emit(engine, 0);
3578621f407SFrançois Tigeot 	intel_ring_advance(engine);
358e3adcf8fSFrançois Tigeot 
359e3adcf8fSFrançois Tigeot 	return 0;
360e3adcf8fSFrançois Tigeot }
361e3adcf8fSFrançois Tigeot 
3629edbd4a0SFrançois Tigeot static int
363a05eeebfSFrançois Tigeot gen8_emit_pipe_control(struct drm_i915_gem_request *req,
36424edb884SFrançois Tigeot 		       u32 flags, u32 scratch_addr)
36524edb884SFrançois Tigeot {
3668621f407SFrançois Tigeot 	struct intel_engine_cs *engine = req->engine;
36724edb884SFrançois Tigeot 	int ret;
36824edb884SFrançois Tigeot 
369a05eeebfSFrançois Tigeot 	ret = intel_ring_begin(req, 6);
37024edb884SFrançois Tigeot 	if (ret)
37124edb884SFrançois Tigeot 		return ret;
37224edb884SFrançois Tigeot 
3738621f407SFrançois Tigeot 	intel_ring_emit(engine, GFX_OP_PIPE_CONTROL(6));
3748621f407SFrançois Tigeot 	intel_ring_emit(engine, flags);
3758621f407SFrançois Tigeot 	intel_ring_emit(engine, scratch_addr);
3768621f407SFrançois Tigeot 	intel_ring_emit(engine, 0);
3778621f407SFrançois Tigeot 	intel_ring_emit(engine, 0);
3788621f407SFrançois Tigeot 	intel_ring_emit(engine, 0);
3798621f407SFrançois Tigeot 	intel_ring_advance(engine);
38024edb884SFrançois Tigeot 
38124edb884SFrançois Tigeot 	return 0;
38224edb884SFrançois Tigeot }
38324edb884SFrançois Tigeot 
38424edb884SFrançois Tigeot static int
385a05eeebfSFrançois Tigeot gen8_render_ring_flush(struct drm_i915_gem_request *req,
3869edbd4a0SFrançois Tigeot 		       u32 invalidate_domains, u32 flush_domains)
3879edbd4a0SFrançois Tigeot {
3889edbd4a0SFrançois Tigeot 	u32 flags = 0;
3898621f407SFrançois Tigeot 	u32 scratch_addr = req->engine->scratch.gtt_offset + 2 * CACHELINE_BYTES;
3909edbd4a0SFrançois Tigeot 	int ret;
3919edbd4a0SFrançois Tigeot 
3929edbd4a0SFrançois Tigeot 	flags |= PIPE_CONTROL_CS_STALL;
3939edbd4a0SFrançois Tigeot 
3949edbd4a0SFrançois Tigeot 	if (flush_domains) {
3959edbd4a0SFrançois Tigeot 		flags |= PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH;
3969edbd4a0SFrançois Tigeot 		flags |= PIPE_CONTROL_DEPTH_CACHE_FLUSH;
397aee94f86SFrançois Tigeot 		flags |= PIPE_CONTROL_DC_FLUSH_ENABLE;
398b49c8cf9SFrançois Tigeot 		flags |= PIPE_CONTROL_FLUSH_ENABLE;
3999edbd4a0SFrançois Tigeot 	}
4009edbd4a0SFrançois Tigeot 	if (invalidate_domains) {
4019edbd4a0SFrançois Tigeot 		flags |= PIPE_CONTROL_TLB_INVALIDATE;
4029edbd4a0SFrançois Tigeot 		flags |= PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE;
4039edbd4a0SFrançois Tigeot 		flags |= PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE;
4049edbd4a0SFrançois Tigeot 		flags |= PIPE_CONTROL_VF_CACHE_INVALIDATE;
4059edbd4a0SFrançois Tigeot 		flags |= PIPE_CONTROL_CONST_CACHE_INVALIDATE;
4069edbd4a0SFrançois Tigeot 		flags |= PIPE_CONTROL_STATE_CACHE_INVALIDATE;
4079edbd4a0SFrançois Tigeot 		flags |= PIPE_CONTROL_QW_WRITE;
4089edbd4a0SFrançois Tigeot 		flags |= PIPE_CONTROL_GLOBAL_GTT_IVB;
4099edbd4a0SFrançois Tigeot 
41024edb884SFrançois Tigeot 		/* WaCsStallBeforeStateCacheInvalidate:bdw,chv */
411a05eeebfSFrançois Tigeot 		ret = gen8_emit_pipe_control(req,
41224edb884SFrançois Tigeot 					     PIPE_CONTROL_CS_STALL |
41324edb884SFrançois Tigeot 					     PIPE_CONTROL_STALL_AT_SCOREBOARD,
41424edb884SFrançois Tigeot 					     0);
4159edbd4a0SFrançois Tigeot 		if (ret)
4169edbd4a0SFrançois Tigeot 			return ret;
41724edb884SFrançois Tigeot 	}
4189edbd4a0SFrançois Tigeot 
419a05eeebfSFrançois Tigeot 	return gen8_emit_pipe_control(req, flags, scratch_addr);
4209edbd4a0SFrançois Tigeot }
4219edbd4a0SFrançois Tigeot 
4228621f407SFrançois Tigeot static void ring_write_tail(struct intel_engine_cs *engine,
423b5c29a34SFrançois Tigeot 			    u32 value)
424e3adcf8fSFrançois Tigeot {
4251487f786SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
4268621f407SFrançois Tigeot 	I915_WRITE_TAIL(engine, value);
427e3adcf8fSFrançois Tigeot }
428e3adcf8fSFrançois Tigeot 
4298621f407SFrançois Tigeot u64 intel_ring_get_active_head(struct intel_engine_cs *engine)
430e3adcf8fSFrançois Tigeot {
4311487f786SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
432ba55f2f5SFrançois Tigeot 	u64 acthd;
433e3adcf8fSFrançois Tigeot 
4341487f786SFrançois Tigeot 	if (INTEL_GEN(dev_priv) >= 8)
4358621f407SFrançois Tigeot 		acthd = I915_READ64_2x32(RING_ACTHD(engine->mmio_base),
4368621f407SFrançois Tigeot 					 RING_ACTHD_UDW(engine->mmio_base));
4371487f786SFrançois Tigeot 	else if (INTEL_GEN(dev_priv) >= 4)
4388621f407SFrançois Tigeot 		acthd = I915_READ(RING_ACTHD(engine->mmio_base));
439ba55f2f5SFrançois Tigeot 	else
440ba55f2f5SFrançois Tigeot 		acthd = I915_READ(ACTHD);
441ba55f2f5SFrançois Tigeot 
442ba55f2f5SFrançois Tigeot 	return acthd;
443e3adcf8fSFrançois Tigeot }
444e3adcf8fSFrançois Tigeot 
4458621f407SFrançois Tigeot static void ring_setup_phys_status_page(struct intel_engine_cs *engine)
4465d0b1887SFrançois Tigeot {
4471487f786SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
4485d0b1887SFrançois Tigeot 	u32 addr;
4495d0b1887SFrançois Tigeot 
4505d0b1887SFrançois Tigeot 	addr = dev_priv->status_page_dmah->busaddr;
4511487f786SFrançois Tigeot 	if (INTEL_GEN(dev_priv) >= 4)
4525d0b1887SFrançois Tigeot 		addr |= (dev_priv->status_page_dmah->busaddr >> 28) & 0xf0;
4535d0b1887SFrançois Tigeot 	I915_WRITE(HWS_PGA, addr);
4545d0b1887SFrançois Tigeot }
4555d0b1887SFrançois Tigeot 
4568621f407SFrançois Tigeot static void intel_ring_setup_status_page(struct intel_engine_cs *engine)
457477eb7f9SFrançois Tigeot {
4581487f786SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
459aee94f86SFrançois Tigeot 	i915_reg_t mmio;
460477eb7f9SFrançois Tigeot 
461477eb7f9SFrançois Tigeot 	/* The ring status page addresses are no longer next to the rest of
462477eb7f9SFrançois Tigeot 	 * the ring registers as of gen7.
463477eb7f9SFrançois Tigeot 	 */
4641487f786SFrançois Tigeot 	if (IS_GEN7(dev_priv)) {
4658621f407SFrançois Tigeot 		switch (engine->id) {
466477eb7f9SFrançois Tigeot 		case RCS:
467477eb7f9SFrançois Tigeot 			mmio = RENDER_HWS_PGA_GEN7;
468477eb7f9SFrançois Tigeot 			break;
469477eb7f9SFrançois Tigeot 		case BCS:
470477eb7f9SFrançois Tigeot 			mmio = BLT_HWS_PGA_GEN7;
471477eb7f9SFrançois Tigeot 			break;
472477eb7f9SFrançois Tigeot 		/*
473477eb7f9SFrançois Tigeot 		 * VCS2 actually doesn't exist on Gen7. Only shut up
474477eb7f9SFrançois Tigeot 		 * gcc switch check warning
475477eb7f9SFrançois Tigeot 		 */
476477eb7f9SFrançois Tigeot 		case VCS2:
477477eb7f9SFrançois Tigeot 		case VCS:
478477eb7f9SFrançois Tigeot 			mmio = BSD_HWS_PGA_GEN7;
479477eb7f9SFrançois Tigeot 			break;
480477eb7f9SFrançois Tigeot 		case VECS:
481477eb7f9SFrançois Tigeot 			mmio = VEBOX_HWS_PGA_GEN7;
482477eb7f9SFrançois Tigeot 			break;
483477eb7f9SFrançois Tigeot 		}
4841487f786SFrançois Tigeot 	} else if (IS_GEN6(dev_priv)) {
4858621f407SFrançois Tigeot 		mmio = RING_HWS_PGA_GEN6(engine->mmio_base);
486477eb7f9SFrançois Tigeot 	} else {
487477eb7f9SFrançois Tigeot 		/* XXX: gen8 returns to sanity */
4888621f407SFrançois Tigeot 		mmio = RING_HWS_PGA(engine->mmio_base);
489477eb7f9SFrançois Tigeot 	}
490477eb7f9SFrançois Tigeot 
4918621f407SFrançois Tigeot 	I915_WRITE(mmio, (u32)engine->status_page.gfx_addr);
492477eb7f9SFrançois Tigeot 	POSTING_READ(mmio);
493477eb7f9SFrançois Tigeot 
494477eb7f9SFrançois Tigeot 	/*
495477eb7f9SFrançois Tigeot 	 * Flush the TLB for this page
496477eb7f9SFrançois Tigeot 	 *
497477eb7f9SFrançois Tigeot 	 * FIXME: These two bits have disappeared on gen8, so a question
498477eb7f9SFrançois Tigeot 	 * arises: do we still need this and if so how should we go about
499477eb7f9SFrançois Tigeot 	 * invalidating the TLB?
500477eb7f9SFrançois Tigeot 	 */
5011487f786SFrançois Tigeot 	if (IS_GEN(dev_priv, 6, 7)) {
5028621f407SFrançois Tigeot 		i915_reg_t reg = RING_INSTPM(engine->mmio_base);
503477eb7f9SFrançois Tigeot 
504477eb7f9SFrançois Tigeot 		/* ring should be idle before issuing a sync flush*/
5058621f407SFrançois Tigeot 		WARN_ON((I915_READ_MODE(engine) & MODE_IDLE) == 0);
506477eb7f9SFrançois Tigeot 
507477eb7f9SFrançois Tigeot 		I915_WRITE(reg,
508477eb7f9SFrançois Tigeot 			   _MASKED_BIT_ENABLE(INSTPM_TLB_INVALIDATE |
509477eb7f9SFrançois Tigeot 					      INSTPM_SYNC_FLUSH));
5101487f786SFrançois Tigeot 		if (intel_wait_for_register(dev_priv,
5111487f786SFrançois Tigeot 					    reg, INSTPM_SYNC_FLUSH, 0,
512477eb7f9SFrançois Tigeot 					    1000))
513477eb7f9SFrançois Tigeot 			DRM_ERROR("%s: wait for SyncFlush to complete for TLB invalidation timed out\n",
5148621f407SFrançois Tigeot 				  engine->name);
515477eb7f9SFrançois Tigeot 	}
516477eb7f9SFrançois Tigeot }
517477eb7f9SFrançois Tigeot 
5188621f407SFrançois Tigeot static bool stop_ring(struct intel_engine_cs *engine)
519e3adcf8fSFrançois Tigeot {
5201487f786SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
521e3adcf8fSFrançois Tigeot 
5221487f786SFrançois Tigeot 	if (!IS_GEN2(dev_priv)) {
5238621f407SFrançois Tigeot 		I915_WRITE_MODE(engine, _MASKED_BIT_ENABLE(STOP_RING));
5241487f786SFrançois Tigeot 		if (intel_wait_for_register(dev_priv,
5251487f786SFrançois Tigeot 					    RING_MI_MODE(engine->mmio_base),
5261487f786SFrançois Tigeot 					    MODE_IDLE,
5271487f786SFrançois Tigeot 					    MODE_IDLE,
5281487f786SFrançois Tigeot 					    1000)) {
5298621f407SFrançois Tigeot 			DRM_ERROR("%s : timed out trying to stop ring\n",
5308621f407SFrançois Tigeot 				  engine->name);
5311b13d190SFrançois Tigeot 			/* Sometimes we observe that the idle flag is not
5321b13d190SFrançois Tigeot 			 * set even though the ring is empty. So double
5331b13d190SFrançois Tigeot 			 * check before giving up.
5341b13d190SFrançois Tigeot 			 */
5358621f407SFrançois Tigeot 			if (I915_READ_HEAD(engine) != I915_READ_TAIL(engine))
536ba55f2f5SFrançois Tigeot 				return false;
537ba55f2f5SFrançois Tigeot 		}
538ba55f2f5SFrançois Tigeot 	}
539686a02f1SFrançois Tigeot 
5408621f407SFrançois Tigeot 	I915_WRITE_CTL(engine, 0);
5418621f407SFrançois Tigeot 	I915_WRITE_HEAD(engine, 0);
5428621f407SFrançois Tigeot 	engine->write_tail(engine, 0);
543e3adcf8fSFrançois Tigeot 
5441487f786SFrançois Tigeot 	if (!IS_GEN2(dev_priv)) {
5458621f407SFrançois Tigeot 		(void)I915_READ_CTL(engine);
5468621f407SFrançois Tigeot 		I915_WRITE_MODE(engine, _MASKED_BIT_DISABLE(STOP_RING));
547ba55f2f5SFrançois Tigeot 	}
548e3adcf8fSFrançois Tigeot 
5498621f407SFrançois Tigeot 	return (I915_READ_HEAD(engine) & HEAD_ADDR) == 0;
550ba55f2f5SFrançois Tigeot }
551ba55f2f5SFrançois Tigeot 
5528621f407SFrançois Tigeot void intel_engine_init_hangcheck(struct intel_engine_cs *engine)
553ba55f2f5SFrançois Tigeot {
5548621f407SFrançois Tigeot 	memset(&engine->hangcheck, 0, sizeof(engine->hangcheck));
5558621f407SFrançois Tigeot }
5568621f407SFrançois Tigeot 
5578621f407SFrançois Tigeot static int init_ring_common(struct intel_engine_cs *engine)
5588621f407SFrançois Tigeot {
5591487f786SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
5608621f407SFrançois Tigeot 	struct intel_ringbuffer *ringbuf = engine->buffer;
561ba55f2f5SFrançois Tigeot 	struct drm_i915_gem_object *obj = ringbuf->obj;
562ba55f2f5SFrançois Tigeot 	int ret = 0;
563ba55f2f5SFrançois Tigeot 
5642c9916cdSFrançois Tigeot 	intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL);
565ba55f2f5SFrançois Tigeot 
5668621f407SFrançois Tigeot 	if (!stop_ring(engine)) {
567ba55f2f5SFrançois Tigeot 		/* G45 ring initialization often fails to reset head to zero */
568b5c29a34SFrançois Tigeot 		DRM_DEBUG_KMS("%s head not reset to zero "
569e3adcf8fSFrançois Tigeot 			      "ctl %08x head %08x tail %08x start %08x\n",
5708621f407SFrançois Tigeot 			      engine->name,
5718621f407SFrançois Tigeot 			      I915_READ_CTL(engine),
5728621f407SFrançois Tigeot 			      I915_READ_HEAD(engine),
5738621f407SFrançois Tigeot 			      I915_READ_TAIL(engine),
5748621f407SFrançois Tigeot 			      I915_READ_START(engine));
575e3adcf8fSFrançois Tigeot 
5768621f407SFrançois Tigeot 		if (!stop_ring(engine)) {
577e3adcf8fSFrançois Tigeot 			DRM_ERROR("failed to set %s head to zero "
578e3adcf8fSFrançois Tigeot 				  "ctl %08x head %08x tail %08x start %08x\n",
5798621f407SFrançois Tigeot 				  engine->name,
5808621f407SFrançois Tigeot 				  I915_READ_CTL(engine),
5818621f407SFrançois Tigeot 				  I915_READ_HEAD(engine),
5828621f407SFrançois Tigeot 				  I915_READ_TAIL(engine),
5838621f407SFrançois Tigeot 				  I915_READ_START(engine));
584686a02f1SFrançois Tigeot 			ret = -EIO;
585686a02f1SFrançois Tigeot 			goto out;
586e3adcf8fSFrançois Tigeot 		}
587ba55f2f5SFrançois Tigeot 	}
588ba55f2f5SFrançois Tigeot 
5891487f786SFrançois Tigeot 	if (I915_NEED_GFX_HWS(dev_priv))
5908621f407SFrançois Tigeot 		intel_ring_setup_status_page(engine);
591ba55f2f5SFrançois Tigeot 	else
5928621f407SFrançois Tigeot 		ring_setup_phys_status_page(engine);
593ba55f2f5SFrançois Tigeot 
5940f370975SMatthew Dillon 	/* Enforce ordering by reading HEAD register back */
5958621f407SFrançois Tigeot 	I915_READ_HEAD(engine);
5960f370975SMatthew Dillon 
597ba55f2f5SFrançois Tigeot 	/* Initialize the ring. This must happen _after_ we've cleared the ring
598ba55f2f5SFrançois Tigeot 	 * registers with the above sequence (the readback of the HEAD registers
599ba55f2f5SFrançois Tigeot 	 * also enforces ordering), otherwise the hw might lose the new ring
600ba55f2f5SFrançois Tigeot 	 * register values. */
6018621f407SFrançois Tigeot 	I915_WRITE_START(engine, i915_gem_obj_ggtt_offset(obj));
6021b13d190SFrançois Tigeot 
6031b13d190SFrançois Tigeot 	/* WaClearRingBufHeadRegAtInit:ctg,elk */
6048621f407SFrançois Tigeot 	if (I915_READ_HEAD(engine))
6051b13d190SFrançois Tigeot 		DRM_DEBUG("%s initialization failed [head=%08x], fudging\n",
6068621f407SFrançois Tigeot 			  engine->name, I915_READ_HEAD(engine));
6078621f407SFrançois Tigeot 	I915_WRITE_HEAD(engine, 0);
6088621f407SFrançois Tigeot 	(void)I915_READ_HEAD(engine);
6091b13d190SFrançois Tigeot 
6108621f407SFrançois Tigeot 	I915_WRITE_CTL(engine,
611ba55f2f5SFrançois Tigeot 			((ringbuf->size - PAGE_SIZE) & RING_NR_PAGES)
612ba55f2f5SFrançois Tigeot 			| RING_VALID);
613ba55f2f5SFrançois Tigeot 
614ba55f2f5SFrançois Tigeot 	/* If the head is still not zero, the ring is dead */
6158621f407SFrançois Tigeot 	if (wait_for((I915_READ_CTL(engine) & RING_VALID) != 0 &&
6168621f407SFrançois Tigeot 		     I915_READ_START(engine) == i915_gem_obj_ggtt_offset(obj) &&
6178621f407SFrançois Tigeot 		     (I915_READ_HEAD(engine) & HEAD_ADDR) == 0, 50)) {
618ba55f2f5SFrançois Tigeot 		DRM_ERROR("%s initialization failed "
619ba55f2f5SFrançois Tigeot 			  "ctl %08x (valid? %d) head %08x tail %08x start %08x [expected %08lx]\n",
6208621f407SFrançois Tigeot 			  engine->name,
6218621f407SFrançois Tigeot 			  I915_READ_CTL(engine),
6228621f407SFrançois Tigeot 			  I915_READ_CTL(engine) & RING_VALID,
6238621f407SFrançois Tigeot 			  I915_READ_HEAD(engine), I915_READ_TAIL(engine),
6248621f407SFrançois Tigeot 			  I915_READ_START(engine),
6258621f407SFrançois Tigeot 			  (unsigned long)i915_gem_obj_ggtt_offset(obj));
626ba55f2f5SFrançois Tigeot 		ret = -EIO;
627ba55f2f5SFrançois Tigeot 		goto out;
628ba55f2f5SFrançois Tigeot 	}
629e3adcf8fSFrançois Tigeot 
6302c9916cdSFrançois Tigeot 	ringbuf->last_retired_head = -1;
6318621f407SFrançois Tigeot 	ringbuf->head = I915_READ_HEAD(engine);
6328621f407SFrançois Tigeot 	ringbuf->tail = I915_READ_TAIL(engine) & TAIL_ADDR;
6332c9916cdSFrançois Tigeot 	intel_ring_update_space(ringbuf);
634e3adcf8fSFrançois Tigeot 
6358621f407SFrançois Tigeot 	intel_engine_init_hangcheck(engine);
6365d0b1887SFrançois Tigeot 
637686a02f1SFrançois Tigeot out:
6382c9916cdSFrançois Tigeot 	intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL);
639686a02f1SFrançois Tigeot 
640686a02f1SFrançois Tigeot 	return ret;
641e3adcf8fSFrançois Tigeot }
642e3adcf8fSFrançois Tigeot 
643*303bf270SFrançois Tigeot void intel_fini_pipe_control(struct intel_engine_cs *engine)
6441b13d190SFrançois Tigeot {
6458621f407SFrançois Tigeot 	if (engine->scratch.obj == NULL)
6461b13d190SFrançois Tigeot 		return;
6471b13d190SFrançois Tigeot 
6488621f407SFrançois Tigeot 	i915_gem_object_ggtt_unpin(engine->scratch.obj);
6498621f407SFrançois Tigeot 	drm_gem_object_unreference(&engine->scratch.obj->base);
6508621f407SFrançois Tigeot 	engine->scratch.obj = NULL;
6511b13d190SFrançois Tigeot }
6521b13d190SFrançois Tigeot 
653*303bf270SFrançois Tigeot int intel_init_pipe_control(struct intel_engine_cs *engine, int size)
654e3adcf8fSFrançois Tigeot {
655*303bf270SFrançois Tigeot 	struct drm_i915_gem_object *obj;
656e3adcf8fSFrançois Tigeot 	int ret;
657e3adcf8fSFrançois Tigeot 
6588621f407SFrançois Tigeot 	WARN_ON(engine->scratch.obj);
659e3adcf8fSFrançois Tigeot 
660*303bf270SFrançois Tigeot 	obj = i915_gem_object_create_stolen(&engine->i915->drm, size);
661*303bf270SFrançois Tigeot 	if (!obj)
662*303bf270SFrançois Tigeot 		obj = i915_gem_object_create(&engine->i915->drm, size);
663*303bf270SFrançois Tigeot 	if (IS_ERR(obj)) {
664*303bf270SFrançois Tigeot 		DRM_ERROR("Failed to allocate scratch page\n");
665*303bf270SFrançois Tigeot 		ret = PTR_ERR(obj);
666e3adcf8fSFrançois Tigeot 		goto err;
667e3adcf8fSFrançois Tigeot 	}
668e3adcf8fSFrançois Tigeot 
669*303bf270SFrançois Tigeot 	ret = i915_gem_obj_ggtt_pin(obj, 4096, PIN_HIGH);
670ba55f2f5SFrançois Tigeot 	if (ret)
671ba55f2f5SFrançois Tigeot 		goto err_unref;
672e3adcf8fSFrançois Tigeot 
673*303bf270SFrançois Tigeot 	engine->scratch.obj = obj;
674*303bf270SFrançois Tigeot 	engine->scratch.gtt_offset = i915_gem_obj_ggtt_offset(obj);
675a2fdbec6SFrançois Tigeot 	DRM_DEBUG_DRIVER("%s pipe control offset: 0x%08x\n",
6768621f407SFrançois Tigeot 			 engine->name, engine->scratch.gtt_offset);
677e3adcf8fSFrançois Tigeot 	return 0;
678e3adcf8fSFrançois Tigeot 
679e3adcf8fSFrançois Tigeot err_unref:
6808621f407SFrançois Tigeot 	drm_gem_object_unreference(&engine->scratch.obj->base);
681e3adcf8fSFrançois Tigeot err:
682e3adcf8fSFrançois Tigeot 	return ret;
683e3adcf8fSFrançois Tigeot }
684e3adcf8fSFrançois Tigeot 
685a05eeebfSFrançois Tigeot static int intel_ring_workarounds_emit(struct drm_i915_gem_request *req)
6861b13d190SFrançois Tigeot {
6878621f407SFrançois Tigeot 	struct intel_engine_cs *engine = req->engine;
6881487f786SFrançois Tigeot 	struct i915_workarounds *w = &req->i915->workarounds;
6891487f786SFrançois Tigeot 	int ret, i;
6901b13d190SFrançois Tigeot 
691352ff8bdSFrançois Tigeot 	if (w->count == 0)
6922c9916cdSFrançois Tigeot 		return 0;
6931b13d190SFrançois Tigeot 
6948621f407SFrançois Tigeot 	engine->gpu_caches_dirty = true;
695a05eeebfSFrançois Tigeot 	ret = intel_ring_flush_all_caches(req);
6961b13d190SFrançois Tigeot 	if (ret)
6971b13d190SFrançois Tigeot 		return ret;
6981b13d190SFrançois Tigeot 
699a05eeebfSFrançois Tigeot 	ret = intel_ring_begin(req, (w->count * 2 + 2));
7002c9916cdSFrançois Tigeot 	if (ret)
7012c9916cdSFrançois Tigeot 		return ret;
7022c9916cdSFrançois Tigeot 
7038621f407SFrançois Tigeot 	intel_ring_emit(engine, MI_LOAD_REGISTER_IMM(w->count));
7042c9916cdSFrançois Tigeot 	for (i = 0; i < w->count; i++) {
7058621f407SFrançois Tigeot 		intel_ring_emit_reg(engine, w->reg[i].addr);
7068621f407SFrançois Tigeot 		intel_ring_emit(engine, w->reg[i].value);
7072c9916cdSFrançois Tigeot 	}
7088621f407SFrançois Tigeot 	intel_ring_emit(engine, MI_NOOP);
7092c9916cdSFrançois Tigeot 
7108621f407SFrançois Tigeot 	intel_ring_advance(engine);
7112c9916cdSFrançois Tigeot 
7128621f407SFrançois Tigeot 	engine->gpu_caches_dirty = true;
713a05eeebfSFrançois Tigeot 	ret = intel_ring_flush_all_caches(req);
7142c9916cdSFrançois Tigeot 	if (ret)
7152c9916cdSFrançois Tigeot 		return ret;
7162c9916cdSFrançois Tigeot 
7172c9916cdSFrançois Tigeot 	DRM_DEBUG_DRIVER("Number of Workarounds emitted: %d\n", w->count);
7182c9916cdSFrançois Tigeot 
7192c9916cdSFrançois Tigeot 	return 0;
7202c9916cdSFrançois Tigeot }
7212c9916cdSFrançois Tigeot 
722a05eeebfSFrançois Tigeot static int intel_rcs_ctx_init(struct drm_i915_gem_request *req)
7232c9916cdSFrançois Tigeot {
7242c9916cdSFrançois Tigeot 	int ret;
7252c9916cdSFrançois Tigeot 
726a05eeebfSFrançois Tigeot 	ret = intel_ring_workarounds_emit(req);
7272c9916cdSFrançois Tigeot 	if (ret != 0)
7282c9916cdSFrançois Tigeot 		return ret;
7292c9916cdSFrançois Tigeot 
730a05eeebfSFrançois Tigeot 	ret = i915_gem_render_state_init(req);
7312c9916cdSFrançois Tigeot 	if (ret)
7322c9916cdSFrançois Tigeot 		return ret;
733c0e85e96SFrançois Tigeot 
734c0e85e96SFrançois Tigeot 	return 0;
7352c9916cdSFrançois Tigeot }
7362c9916cdSFrançois Tigeot 
7372c9916cdSFrançois Tigeot static int wa_add(struct drm_i915_private *dev_priv,
738aee94f86SFrançois Tigeot 		  i915_reg_t addr,
739aee94f86SFrançois Tigeot 		  const u32 mask, const u32 val)
7402c9916cdSFrançois Tigeot {
7412c9916cdSFrançois Tigeot 	const u32 idx = dev_priv->workarounds.count;
7422c9916cdSFrançois Tigeot 
7432c9916cdSFrançois Tigeot 	if (WARN_ON(idx >= I915_MAX_WA_REGS))
7442c9916cdSFrançois Tigeot 		return -ENOSPC;
7452c9916cdSFrançois Tigeot 
7462c9916cdSFrançois Tigeot 	dev_priv->workarounds.reg[idx].addr = addr;
7472c9916cdSFrançois Tigeot 	dev_priv->workarounds.reg[idx].value = val;
7482c9916cdSFrançois Tigeot 	dev_priv->workarounds.reg[idx].mask = mask;
7492c9916cdSFrançois Tigeot 
7502c9916cdSFrançois Tigeot 	dev_priv->workarounds.count++;
7512c9916cdSFrançois Tigeot 
7522c9916cdSFrançois Tigeot 	return 0;
7532c9916cdSFrançois Tigeot }
7542c9916cdSFrançois Tigeot 
755a05eeebfSFrançois Tigeot #define WA_REG(addr, mask, val) do { \
7562c9916cdSFrançois Tigeot 		const int r = wa_add(dev_priv, (addr), (mask), (val)); \
7572c9916cdSFrançois Tigeot 		if (r) \
7582c9916cdSFrançois Tigeot 			return r; \
759a05eeebfSFrançois Tigeot 	} while (0)
7602c9916cdSFrançois Tigeot 
7612c9916cdSFrançois Tigeot #define WA_SET_BIT_MASKED(addr, mask) \
7622c9916cdSFrançois Tigeot 	WA_REG(addr, (mask), _MASKED_BIT_ENABLE(mask))
7632c9916cdSFrançois Tigeot 
7642c9916cdSFrançois Tigeot #define WA_CLR_BIT_MASKED(addr, mask) \
7652c9916cdSFrançois Tigeot 	WA_REG(addr, (mask), _MASKED_BIT_DISABLE(mask))
7662c9916cdSFrançois Tigeot 
7672c9916cdSFrançois Tigeot #define WA_SET_FIELD_MASKED(addr, mask, value) \
7682c9916cdSFrançois Tigeot 	WA_REG(addr, mask, _MASKED_FIELD(mask, value))
7692c9916cdSFrançois Tigeot 
7702c9916cdSFrançois Tigeot #define WA_SET_BIT(addr, mask) WA_REG(addr, mask, I915_READ(addr) | (mask))
7712c9916cdSFrançois Tigeot #define WA_CLR_BIT(addr, mask) WA_REG(addr, mask, I915_READ(addr) & ~(mask))
7722c9916cdSFrançois Tigeot 
7732c9916cdSFrançois Tigeot #define WA_WRITE(addr, val) WA_REG(addr, 0xffffffff, val)
7742c9916cdSFrançois Tigeot 
7758621f407SFrançois Tigeot static int wa_ring_whitelist_reg(struct intel_engine_cs *engine,
7768621f407SFrançois Tigeot 				 i915_reg_t reg)
777c0e85e96SFrançois Tigeot {
7781487f786SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
779c0e85e96SFrançois Tigeot 	struct i915_workarounds *wa = &dev_priv->workarounds;
7808621f407SFrançois Tigeot 	const uint32_t index = wa->hw_whitelist_count[engine->id];
781c0e85e96SFrançois Tigeot 
782c0e85e96SFrançois Tigeot 	if (WARN_ON(index >= RING_MAX_NONPRIV_SLOTS))
783c0e85e96SFrançois Tigeot 		return -EINVAL;
784c0e85e96SFrançois Tigeot 
7858621f407SFrançois Tigeot 	WA_WRITE(RING_FORCE_TO_NONPRIV(engine->mmio_base, index),
786c0e85e96SFrançois Tigeot 		 i915_mmio_reg_offset(reg));
7878621f407SFrançois Tigeot 	wa->hw_whitelist_count[engine->id]++;
788c0e85e96SFrançois Tigeot 
789c0e85e96SFrançois Tigeot 	return 0;
790c0e85e96SFrançois Tigeot }
791c0e85e96SFrançois Tigeot 
7928621f407SFrançois Tigeot static int gen8_init_workarounds(struct intel_engine_cs *engine)
7932c9916cdSFrançois Tigeot {
7941487f786SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
7952c9916cdSFrançois Tigeot 
796a05eeebfSFrançois Tigeot 	WA_SET_BIT_MASKED(INSTPM, INSTPM_FORCE_ORDERING);
797a05eeebfSFrançois Tigeot 
798352ff8bdSFrançois Tigeot 	/* WaDisableAsyncFlipPerfMode:bdw,chv */
799a05eeebfSFrançois Tigeot 	WA_SET_BIT_MASKED(MI_MODE, ASYNC_FLIP_PERF_DISABLE);
800a05eeebfSFrançois Tigeot 
801352ff8bdSFrançois Tigeot 	/* WaDisablePartialInstShootdown:bdw,chv */
8022c9916cdSFrançois Tigeot 	WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN,
803352ff8bdSFrançois Tigeot 			  PARTIAL_INSTRUCTION_SHOOTDOWN_DISABLE);
8041b13d190SFrançois Tigeot 
8051b13d190SFrançois Tigeot 	/* Use Force Non-Coherent whenever executing a 3D context. This is a
8061b13d190SFrançois Tigeot 	 * workaround for for a possible hang in the unlikely event a TLB
8071b13d190SFrançois Tigeot 	 * invalidation occurs during a PSD flush.
8081b13d190SFrançois Tigeot 	 */
809352ff8bdSFrançois Tigeot 	/* WaForceEnableNonCoherent:bdw,chv */
810352ff8bdSFrançois Tigeot 	/* WaHdcDisableFetchWhenMasked:bdw,chv */
8112c9916cdSFrançois Tigeot 	WA_SET_BIT_MASKED(HDC_CHICKEN0,
8122c9916cdSFrançois Tigeot 			  HDC_DONOT_FETCH_MEM_WHEN_MASKED |
813352ff8bdSFrançois Tigeot 			  HDC_FORCE_NON_COHERENT);
8142c9916cdSFrançois Tigeot 
8152c9916cdSFrançois Tigeot 	/* From the Haswell PRM, Command Reference: Registers, CACHE_MODE_0:
8162c9916cdSFrançois Tigeot 	 * "The Hierarchical Z RAW Stall Optimization allows non-overlapping
8172c9916cdSFrançois Tigeot 	 *  polygons in the same 8x4 pixel/sample area to be processed without
8182c9916cdSFrançois Tigeot 	 *  stalling waiting for the earlier ones to write to Hierarchical Z
8192c9916cdSFrançois Tigeot 	 *  buffer."
8202c9916cdSFrançois Tigeot 	 *
821352ff8bdSFrançois Tigeot 	 * This optimization is off by default for BDW and CHV; turn it on.
8222c9916cdSFrançois Tigeot 	 */
8232c9916cdSFrançois Tigeot 	WA_CLR_BIT_MASKED(CACHE_MODE_0_GEN7, HIZ_RAW_STALL_OPT_DISABLE);
8241b13d190SFrançois Tigeot 
825352ff8bdSFrançois Tigeot 	/* Wa4x4STCOptimizationDisable:bdw,chv */
826352ff8bdSFrançois Tigeot 	WA_SET_BIT_MASKED(CACHE_MODE_1, GEN8_4x4_STC_OPTIMIZATION_DISABLE);
8271b13d190SFrançois Tigeot 
8281b13d190SFrançois Tigeot 	/*
8291b13d190SFrançois Tigeot 	 * BSpec recommends 8x4 when MSAA is used,
8301b13d190SFrançois Tigeot 	 * however in practice 16x4 seems fastest.
8311b13d190SFrançois Tigeot 	 *
8321b13d190SFrançois Tigeot 	 * Note that PS/WM thread counts depend on the WIZ hashing
8331b13d190SFrançois Tigeot 	 * disable bit, which we don't touch here, but it's good
8341b13d190SFrançois Tigeot 	 * to keep in mind (see 3DSTATE_PS and 3DSTATE_WM).
8351b13d190SFrançois Tigeot 	 */
8362c9916cdSFrançois Tigeot 	WA_SET_FIELD_MASKED(GEN7_GT_MODE,
8372c9916cdSFrançois Tigeot 			    GEN6_WIZ_HASHING_MASK,
8382c9916cdSFrançois Tigeot 			    GEN6_WIZ_HASHING_16x4);
8391b13d190SFrançois Tigeot 
8401b13d190SFrançois Tigeot 	return 0;
8411b13d190SFrançois Tigeot }
8421b13d190SFrançois Tigeot 
8438621f407SFrançois Tigeot static int bdw_init_workarounds(struct intel_engine_cs *engine)
8441b13d190SFrançois Tigeot {
8451487f786SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
846352ff8bdSFrançois Tigeot 	int ret;
8471b13d190SFrançois Tigeot 
8488621f407SFrançois Tigeot 	ret = gen8_init_workarounds(engine);
849352ff8bdSFrançois Tigeot 	if (ret)
850352ff8bdSFrançois Tigeot 		return ret;
851a05eeebfSFrançois Tigeot 
852352ff8bdSFrançois Tigeot 	/* WaDisableThreadStallDopClockGating:bdw (pre-production) */
853352ff8bdSFrançois Tigeot 	WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN, STALL_DOP_GATING_DISABLE);
854a05eeebfSFrançois Tigeot 
855352ff8bdSFrançois Tigeot 	/* WaDisableDopClockGating:bdw */
856352ff8bdSFrançois Tigeot 	WA_SET_BIT_MASKED(GEN7_ROW_CHICKEN2,
857352ff8bdSFrançois Tigeot 			  DOP_CLOCK_GATING_DISABLE);
8581b13d190SFrançois Tigeot 
859352ff8bdSFrançois Tigeot 	WA_SET_BIT_MASKED(HALF_SLICE_CHICKEN3,
860352ff8bdSFrançois Tigeot 			  GEN8_SAMPLER_POWER_BYPASS_DIS);
861352ff8bdSFrançois Tigeot 
8622c9916cdSFrançois Tigeot 	WA_SET_BIT_MASKED(HDC_CHICKEN0,
863352ff8bdSFrançois Tigeot 			  /* WaForceContextSaveRestoreNonCoherent:bdw */
864352ff8bdSFrançois Tigeot 			  HDC_FORCE_CONTEXT_SAVE_RESTORE_NON_COHERENT |
865352ff8bdSFrançois Tigeot 			  /* WaDisableFenceDestinationToSLM:bdw (pre-prod) */
8661487f786SFrançois Tigeot 			  (IS_BDW_GT3(dev_priv) ? HDC_FENCE_DEST_SLM_DISABLE : 0));
8671b13d190SFrançois Tigeot 
868352ff8bdSFrançois Tigeot 	return 0;
869352ff8bdSFrançois Tigeot }
8701b13d190SFrançois Tigeot 
8718621f407SFrançois Tigeot static int chv_init_workarounds(struct intel_engine_cs *engine)
872352ff8bdSFrançois Tigeot {
8731487f786SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
874352ff8bdSFrançois Tigeot 	int ret;
875352ff8bdSFrançois Tigeot 
8768621f407SFrançois Tigeot 	ret = gen8_init_workarounds(engine);
877352ff8bdSFrançois Tigeot 	if (ret)
878352ff8bdSFrançois Tigeot 		return ret;
879352ff8bdSFrançois Tigeot 
880352ff8bdSFrançois Tigeot 	/* WaDisableThreadStallDopClockGating:chv */
881352ff8bdSFrançois Tigeot 	WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN, STALL_DOP_GATING_DISABLE);
8822c9916cdSFrançois Tigeot 
8832c9916cdSFrançois Tigeot 	/* Improve HiZ throughput on CHV. */
8842c9916cdSFrançois Tigeot 	WA_SET_BIT_MASKED(HIZ_CHICKEN, CHV_HZ_8X8_MODE_IN_1X);
8852c9916cdSFrançois Tigeot 
8862c9916cdSFrançois Tigeot 	return 0;
8872c9916cdSFrançois Tigeot }
8882c9916cdSFrançois Tigeot 
8898621f407SFrançois Tigeot static int gen9_init_workarounds(struct intel_engine_cs *engine)
890477eb7f9SFrançois Tigeot {
8911487f786SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
892c0e85e96SFrançois Tigeot 	int ret;
893477eb7f9SFrançois Tigeot 
8948621f407SFrançois Tigeot 	/* WaConextSwitchWithConcurrentTLBInvalidate:skl,bxt,kbl */
8958621f407SFrançois Tigeot 	I915_WRITE(GEN9_CSFE_CHICKEN1_RCS, _MASKED_BIT_ENABLE(GEN9_PREEMPT_GPGPU_SYNC_SWITCH_DISABLE));
8968621f407SFrançois Tigeot 
8978621f407SFrançois Tigeot 	/* WaEnableLbsSlaRetryTimerDecrement:skl,bxt,kbl */
898352ff8bdSFrançois Tigeot 	I915_WRITE(BDW_SCRATCH1, I915_READ(BDW_SCRATCH1) |
899352ff8bdSFrançois Tigeot 		   GEN9_LBS_SLA_RETRY_TIMER_DECREMENT_ENABLE);
900352ff8bdSFrançois Tigeot 
9018621f407SFrançois Tigeot 	/* WaDisableKillLogic:bxt,skl,kbl */
902352ff8bdSFrançois Tigeot 	I915_WRITE(GAM_ECOCHK, I915_READ(GAM_ECOCHK) |
903352ff8bdSFrançois Tigeot 		   ECOCHK_DIS_TLB);
904352ff8bdSFrançois Tigeot 
9058621f407SFrançois Tigeot 	/* WaClearFlowControlGpgpuContextSave:skl,bxt,kbl */
9068621f407SFrançois Tigeot 	/* WaDisablePartialInstShootdown:skl,bxt,kbl */
907477eb7f9SFrançois Tigeot 	WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN,
9088621f407SFrançois Tigeot 			  FLOW_CONTROL_ENABLE |
909477eb7f9SFrançois Tigeot 			  PARTIAL_INSTRUCTION_SHOOTDOWN_DISABLE);
910477eb7f9SFrançois Tigeot 
9118621f407SFrançois Tigeot 	/* Syncing dependencies between camera and graphics:skl,bxt,kbl */
912477eb7f9SFrançois Tigeot 	WA_SET_BIT_MASKED(HALF_SLICE_CHICKEN3,
913477eb7f9SFrançois Tigeot 			  GEN9_DISABLE_OCL_OOB_SUPPRESS_LOGIC);
914477eb7f9SFrançois Tigeot 
91519c468b4SFrançois Tigeot 	/* WaDisableDgMirrorFixInHalfSliceChicken5:skl,bxt */
9161487f786SFrançois Tigeot 	if (IS_SKL_REVID(dev_priv, 0, SKL_REVID_B0) ||
9171487f786SFrançois Tigeot 	    IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1))
918477eb7f9SFrançois Tigeot 		WA_CLR_BIT_MASKED(GEN9_HALF_SLICE_CHICKEN5,
919477eb7f9SFrançois Tigeot 				  GEN9_DG_MIRROR_FIX_ENABLE);
920477eb7f9SFrançois Tigeot 
92119c468b4SFrançois Tigeot 	/* WaSetDisablePixMaskCammingAndRhwoInCommonSliceChicken:skl,bxt */
9221487f786SFrançois Tigeot 	if (IS_SKL_REVID(dev_priv, 0, SKL_REVID_B0) ||
9231487f786SFrançois Tigeot 	    IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1)) {
924477eb7f9SFrançois Tigeot 		WA_SET_BIT_MASKED(GEN7_COMMON_SLICE_CHICKEN1,
925477eb7f9SFrançois Tigeot 				  GEN9_RHWO_OPTIMIZATION_DISABLE);
926a05eeebfSFrançois Tigeot 		/*
927a05eeebfSFrançois Tigeot 		 * WA also requires GEN9_SLICE_COMMON_ECO_CHICKEN0[14:14] to be set
928a05eeebfSFrançois Tigeot 		 * but we do that in per ctx batchbuffer as there is an issue
929a05eeebfSFrançois Tigeot 		 * with this register not getting restored on ctx restore
930a05eeebfSFrançois Tigeot 		 */
931477eb7f9SFrançois Tigeot 	}
932477eb7f9SFrançois Tigeot 
9338621f407SFrançois Tigeot 	/* WaEnableYV12BugFixInHalfSliceChicken7:skl,bxt,kbl */
9348621f407SFrançois Tigeot 	/* WaEnableSamplerGPGPUPreemptionSupport:skl,bxt,kbl */
935477eb7f9SFrançois Tigeot 	WA_SET_BIT_MASKED(GEN9_HALF_SLICE_CHICKEN7,
9368621f407SFrançois Tigeot 			  GEN9_ENABLE_YV12_BUGFIX |
9378621f407SFrançois Tigeot 			  GEN9_ENABLE_GPGPU_PREEMPTION);
938477eb7f9SFrançois Tigeot 
9398621f407SFrançois Tigeot 	/* Wa4x4STCOptimizationDisable:skl,bxt,kbl */
9408621f407SFrançois Tigeot 	/* WaDisablePartialResolveInVc:skl,bxt,kbl */
941352ff8bdSFrançois Tigeot 	WA_SET_BIT_MASKED(CACHE_MODE_1, (GEN8_4x4_STC_OPTIMIZATION_DISABLE |
942352ff8bdSFrançois Tigeot 					 GEN9_PARTIAL_RESOLVE_IN_VC_DISABLE));
943477eb7f9SFrançois Tigeot 
9448621f407SFrançois Tigeot 	/* WaCcsTlbPrefetchDisable:skl,bxt,kbl */
945477eb7f9SFrançois Tigeot 	WA_CLR_BIT_MASKED(GEN9_HALF_SLICE_CHICKEN5,
946477eb7f9SFrançois Tigeot 			  GEN9_CCS_TLB_PREFETCH_ENABLE);
947477eb7f9SFrançois Tigeot 
94819c468b4SFrançois Tigeot 	/* WaDisableMaskBasedCammingInRCC:skl,bxt */
9491487f786SFrançois Tigeot 	if (IS_SKL_REVID(dev_priv, SKL_REVID_C0, SKL_REVID_C0) ||
9501487f786SFrançois Tigeot 	    IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1))
95119c468b4SFrançois Tigeot 		WA_SET_BIT_MASKED(SLICE_ECO_CHICKEN0,
95219c468b4SFrançois Tigeot 				  PIXEL_MASK_CAMMING_DISABLE);
95319c468b4SFrançois Tigeot 
9548621f407SFrançois Tigeot 	/* WaForceContextSaveRestoreNonCoherent:skl,bxt,kbl */
9558621f407SFrançois Tigeot 	WA_SET_BIT_MASKED(HDC_CHICKEN0,
9568621f407SFrançois Tigeot 			  HDC_FORCE_CONTEXT_SAVE_RESTORE_NON_COHERENT |
9578621f407SFrançois Tigeot 			  HDC_FORCE_CSR_NON_COHERENT_OVR_DISABLE);
95819c468b4SFrançois Tigeot 
9598621f407SFrançois Tigeot 	/* WaForceEnableNonCoherent and WaDisableHDCInvalidation are
9608621f407SFrançois Tigeot 	 * both tied to WaForceContextSaveRestoreNonCoherent
9618621f407SFrançois Tigeot 	 * in some hsds for skl. We keep the tie for all gen9. The
9628621f407SFrançois Tigeot 	 * documentation is a bit hazy and so we want to get common behaviour,
9638621f407SFrançois Tigeot 	 * even though there is no clear evidence we would need both on kbl/bxt.
9648621f407SFrançois Tigeot 	 * This area has been source of system hangs so we play it safe
9658621f407SFrançois Tigeot 	 * and mimic the skl regardless of what bspec says.
9668621f407SFrançois Tigeot 	 *
9678621f407SFrançois Tigeot 	 * Use Force Non-Coherent whenever executing a 3D context. This
9688621f407SFrançois Tigeot 	 * is a workaround for a possible hang in the unlikely event
9698621f407SFrançois Tigeot 	 * a TLB invalidation occurs during a PSD flush.
9708621f407SFrançois Tigeot 	 */
9718621f407SFrançois Tigeot 
9728621f407SFrançois Tigeot 	/* WaForceEnableNonCoherent:skl,bxt,kbl */
9738621f407SFrançois Tigeot 	WA_SET_BIT_MASKED(HDC_CHICKEN0,
9748621f407SFrançois Tigeot 			  HDC_FORCE_NON_COHERENT);
9758621f407SFrançois Tigeot 
9768621f407SFrançois Tigeot 	/* WaDisableHDCInvalidation:skl,bxt,kbl */
9778621f407SFrançois Tigeot 	I915_WRITE(GAM_ECOCHK, I915_READ(GAM_ECOCHK) |
9788621f407SFrançois Tigeot 		   BDW_DISABLE_HDC_INVALIDATION);
9798621f407SFrançois Tigeot 
9808621f407SFrançois Tigeot 	/* WaDisableSamplerPowerBypassForSOPingPong:skl,bxt,kbl */
9818621f407SFrançois Tigeot 	if (IS_SKYLAKE(dev_priv) ||
9828621f407SFrançois Tigeot 	    IS_KABYLAKE(dev_priv) ||
9838621f407SFrançois Tigeot 	    IS_BXT_REVID(dev_priv, 0, BXT_REVID_B0))
984352ff8bdSFrançois Tigeot 		WA_SET_BIT_MASKED(HALF_SLICE_CHICKEN3,
985352ff8bdSFrançois Tigeot 				  GEN8_SAMPLER_POWER_BYPASS_DIS);
986352ff8bdSFrançois Tigeot 
9878621f407SFrançois Tigeot 	/* WaDisableSTUnitPowerOptimization:skl,bxt,kbl */
988352ff8bdSFrançois Tigeot 	WA_SET_BIT_MASKED(HALF_SLICE_CHICKEN2, GEN8_ST_PO_DISABLE);
989352ff8bdSFrançois Tigeot 
9908621f407SFrançois Tigeot 	/* WaOCLCoherentLineFlush:skl,bxt,kbl */
991c0e85e96SFrançois Tigeot 	I915_WRITE(GEN8_L3SQCREG4, (I915_READ(GEN8_L3SQCREG4) |
992c0e85e96SFrançois Tigeot 				    GEN8_LQSC_FLUSH_COHERENT_LINES));
993c0e85e96SFrançois Tigeot 
9948621f407SFrançois Tigeot 	/* WaVFEStateAfterPipeControlwithMediaStateClear:skl,bxt */
9958621f407SFrançois Tigeot 	ret = wa_ring_whitelist_reg(engine, GEN9_CTX_PREEMPT_REG);
996c0e85e96SFrançois Tigeot 	if (ret)
997c0e85e96SFrançois Tigeot 		return ret;
998c0e85e96SFrançois Tigeot 
9998621f407SFrançois Tigeot 	/* WaEnablePreemptionGranularityControlByUMD:skl,bxt,kbl */
10008621f407SFrançois Tigeot 	ret= wa_ring_whitelist_reg(engine, GEN8_CS_CHICKEN1);
10018621f407SFrançois Tigeot 	if (ret)
10028621f407SFrançois Tigeot 		return ret;
10038621f407SFrançois Tigeot 
10048621f407SFrançois Tigeot 	/* WaAllowUMDToModifyHDCChicken1:skl,bxt,kbl */
10058621f407SFrançois Tigeot 	ret = wa_ring_whitelist_reg(engine, GEN8_HDC_CHICKEN1);
1006c0e85e96SFrançois Tigeot 	if (ret)
1007c0e85e96SFrançois Tigeot 		return ret;
1008c0e85e96SFrançois Tigeot 
1009477eb7f9SFrançois Tigeot 	return 0;
1010477eb7f9SFrançois Tigeot }
1011477eb7f9SFrançois Tigeot 
10128621f407SFrançois Tigeot static int skl_tune_iz_hashing(struct intel_engine_cs *engine)
1013477eb7f9SFrançois Tigeot {
10141487f786SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
1015477eb7f9SFrançois Tigeot 	u8 vals[3] = { 0, 0, 0 };
1016477eb7f9SFrançois Tigeot 	unsigned int i;
1017477eb7f9SFrançois Tigeot 
1018477eb7f9SFrançois Tigeot 	for (i = 0; i < 3; i++) {
1019477eb7f9SFrançois Tigeot 		u8 ss;
1020477eb7f9SFrançois Tigeot 
1021477eb7f9SFrançois Tigeot 		/*
1022477eb7f9SFrançois Tigeot 		 * Only consider slices where one, and only one, subslice has 7
1023477eb7f9SFrançois Tigeot 		 * EUs
1024477eb7f9SFrançois Tigeot 		 */
1025aee94f86SFrançois Tigeot 		if (!is_power_of_2(dev_priv->info.subslice_7eu[i]))
1026477eb7f9SFrançois Tigeot 			continue;
1027477eb7f9SFrançois Tigeot 
1028477eb7f9SFrançois Tigeot 		/*
1029477eb7f9SFrançois Tigeot 		 * subslice_7eu[i] != 0 (because of the check above) and
1030477eb7f9SFrançois Tigeot 		 * ss_max == 4 (maximum number of subslices possible per slice)
1031477eb7f9SFrançois Tigeot 		 *
1032477eb7f9SFrançois Tigeot 		 * ->    0 <= ss <= 3;
1033477eb7f9SFrançois Tigeot 		 */
1034477eb7f9SFrançois Tigeot 		ss = ffs(dev_priv->info.subslice_7eu[i]) - 1;
1035477eb7f9SFrançois Tigeot 		vals[i] = 3 - ss;
1036477eb7f9SFrançois Tigeot 	}
1037477eb7f9SFrançois Tigeot 
1038477eb7f9SFrançois Tigeot 	if (vals[0] == 0 && vals[1] == 0 && vals[2] == 0)
1039477eb7f9SFrançois Tigeot 		return 0;
1040477eb7f9SFrançois Tigeot 
1041477eb7f9SFrançois Tigeot 	/* Tune IZ hashing. See intel_device_info_runtime_init() */
1042477eb7f9SFrançois Tigeot 	WA_SET_FIELD_MASKED(GEN7_GT_MODE,
1043477eb7f9SFrançois Tigeot 			    GEN9_IZ_HASHING_MASK(2) |
1044477eb7f9SFrançois Tigeot 			    GEN9_IZ_HASHING_MASK(1) |
1045477eb7f9SFrançois Tigeot 			    GEN9_IZ_HASHING_MASK(0),
1046477eb7f9SFrançois Tigeot 			    GEN9_IZ_HASHING(2, vals[2]) |
1047477eb7f9SFrançois Tigeot 			    GEN9_IZ_HASHING(1, vals[1]) |
1048477eb7f9SFrançois Tigeot 			    GEN9_IZ_HASHING(0, vals[0]));
1049477eb7f9SFrançois Tigeot 
1050477eb7f9SFrançois Tigeot 	return 0;
1051477eb7f9SFrançois Tigeot }
1052477eb7f9SFrançois Tigeot 
10538621f407SFrançois Tigeot static int skl_init_workarounds(struct intel_engine_cs *engine)
1054477eb7f9SFrançois Tigeot {
10551487f786SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
1056352ff8bdSFrançois Tigeot 	int ret;
1057477eb7f9SFrançois Tigeot 
10588621f407SFrançois Tigeot 	ret = gen9_init_workarounds(engine);
1059352ff8bdSFrançois Tigeot 	if (ret)
1060352ff8bdSFrançois Tigeot 		return ret;
1061352ff8bdSFrançois Tigeot 
1062c0e85e96SFrançois Tigeot 	/*
1063c0e85e96SFrançois Tigeot 	 * Actual WA is to disable percontext preemption granularity control
1064c0e85e96SFrançois Tigeot 	 * until D0 which is the default case so this is equivalent to
1065c0e85e96SFrançois Tigeot 	 * !WaDisablePerCtxtPreemptionGranularityControl:skl
1066c0e85e96SFrançois Tigeot 	 */
10671487f786SFrançois Tigeot 	if (IS_SKL_REVID(dev_priv, SKL_REVID_E0, REVID_FOREVER)) {
1068c0e85e96SFrançois Tigeot 		I915_WRITE(GEN7_FF_SLICE_CS_CHICKEN1,
1069c0e85e96SFrançois Tigeot 			   _MASKED_BIT_ENABLE(GEN9_FFSC_PERCTX_PREEMPT_CTRL));
1070c0e85e96SFrançois Tigeot 	}
1071c0e85e96SFrançois Tigeot 
10721487f786SFrançois Tigeot 	if (IS_SKL_REVID(dev_priv, 0, SKL_REVID_E0)) {
1073352ff8bdSFrançois Tigeot 		/* WaDisableChickenBitTSGBarrierAckForFFSliceCS:skl */
1074352ff8bdSFrançois Tigeot 		I915_WRITE(FF_SLICE_CS_CHICKEN2,
1075352ff8bdSFrançois Tigeot 			   _MASKED_BIT_ENABLE(GEN9_TSG_BARRIER_ACK_DISABLE));
1076352ff8bdSFrançois Tigeot 	}
1077352ff8bdSFrançois Tigeot 
1078352ff8bdSFrançois Tigeot 	/* GEN8_L3SQCREG4 has a dependency with WA batch so any new changes
1079352ff8bdSFrançois Tigeot 	 * involving this register should also be added to WA batch as required.
1080352ff8bdSFrançois Tigeot 	 */
10811487f786SFrançois Tigeot 	if (IS_SKL_REVID(dev_priv, 0, SKL_REVID_E0))
1082352ff8bdSFrançois Tigeot 		/* WaDisableLSQCROPERFforOCL:skl */
1083352ff8bdSFrançois Tigeot 		I915_WRITE(GEN8_L3SQCREG4, I915_READ(GEN8_L3SQCREG4) |
1084352ff8bdSFrançois Tigeot 			   GEN8_LQSC_RO_PERF_DIS);
1085352ff8bdSFrançois Tigeot 
1086352ff8bdSFrançois Tigeot 	/* WaEnableGapsTsvCreditFix:skl */
10871487f786SFrançois Tigeot 	if (IS_SKL_REVID(dev_priv, SKL_REVID_C0, REVID_FOREVER)) {
1088352ff8bdSFrançois Tigeot 		I915_WRITE(GEN8_GARBCNTL, (I915_READ(GEN8_GARBCNTL) |
1089352ff8bdSFrançois Tigeot 					   GEN9_GAPS_TSV_CREDIT_DISABLE));
1090352ff8bdSFrançois Tigeot 	}
1091477eb7f9SFrançois Tigeot 
1092477eb7f9SFrançois Tigeot 	/* WaDisablePowerCompilerClockGating:skl */
10931487f786SFrançois Tigeot 	if (IS_SKL_REVID(dev_priv, SKL_REVID_B0, SKL_REVID_B0))
1094477eb7f9SFrançois Tigeot 		WA_SET_BIT_MASKED(HIZ_CHICKEN,
1095477eb7f9SFrançois Tigeot 				  BDW_HIZ_POWER_COMPILER_CLOCK_GATING_DISABLE);
1096477eb7f9SFrançois Tigeot 
1097a05eeebfSFrançois Tigeot 	/* WaBarrierPerformanceFixDisable:skl */
10981487f786SFrançois Tigeot 	if (IS_SKL_REVID(dev_priv, SKL_REVID_C0, SKL_REVID_D0))
1099a05eeebfSFrançois Tigeot 		WA_SET_BIT_MASKED(HDC_CHICKEN0,
1100a05eeebfSFrançois Tigeot 				  HDC_FENCE_DEST_SLM_DISABLE |
1101a05eeebfSFrançois Tigeot 				  HDC_BARRIER_PERFORMANCE_DISABLE);
1102a05eeebfSFrançois Tigeot 
1103a05eeebfSFrançois Tigeot 	/* WaDisableSbeCacheDispatchPortSharing:skl */
11041487f786SFrançois Tigeot 	if (IS_SKL_REVID(dev_priv, 0, SKL_REVID_F0))
1105a05eeebfSFrançois Tigeot 		WA_SET_BIT_MASKED(
1106a05eeebfSFrançois Tigeot 			GEN7_HALF_SLICE_CHICKEN1,
1107a05eeebfSFrançois Tigeot 			GEN7_SBE_SS_CACHE_DISPATCH_PORT_SHARING_DISABLE);
1108a05eeebfSFrançois Tigeot 
11098621f407SFrançois Tigeot 	/* WaDisableGafsUnitClkGating:skl */
11108621f407SFrançois Tigeot 	WA_SET_BIT(GEN7_UCGCTL4, GEN8_EU_GAUNIT_CLOCK_GATE_DISABLE);
11118621f407SFrançois Tigeot 
1112c0e85e96SFrançois Tigeot 	/* WaDisableLSQCROPERFforOCL:skl */
11138621f407SFrançois Tigeot 	ret = wa_ring_whitelist_reg(engine, GEN8_L3SQCREG4);
1114c0e85e96SFrançois Tigeot 	if (ret)
1115c0e85e96SFrançois Tigeot 		return ret;
1116c0e85e96SFrançois Tigeot 
11178621f407SFrançois Tigeot 	return skl_tune_iz_hashing(engine);
1118477eb7f9SFrançois Tigeot }
1119477eb7f9SFrançois Tigeot 
11208621f407SFrançois Tigeot static int bxt_init_workarounds(struct intel_engine_cs *engine)
112119c468b4SFrançois Tigeot {
11221487f786SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
1123352ff8bdSFrançois Tigeot 	int ret;
112419c468b4SFrançois Tigeot 
11258621f407SFrançois Tigeot 	ret = gen9_init_workarounds(engine);
1126352ff8bdSFrançois Tigeot 	if (ret)
1127352ff8bdSFrançois Tigeot 		return ret;
1128352ff8bdSFrançois Tigeot 
1129352ff8bdSFrançois Tigeot 	/* WaStoreMultiplePTEenable:bxt */
1130352ff8bdSFrançois Tigeot 	/* This is a requirement according to Hardware specification */
11311487f786SFrançois Tigeot 	if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1))
1132352ff8bdSFrançois Tigeot 		I915_WRITE(TILECTL, I915_READ(TILECTL) | TILECTL_TLBPF);
1133352ff8bdSFrançois Tigeot 
1134352ff8bdSFrançois Tigeot 	/* WaSetClckGatingDisableMedia:bxt */
11351487f786SFrançois Tigeot 	if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1)) {
1136352ff8bdSFrançois Tigeot 		I915_WRITE(GEN7_MISCCPCTL, (I915_READ(GEN7_MISCCPCTL) &
1137352ff8bdSFrançois Tigeot 					    ~GEN8_DOP_CLOCK_GATE_MEDIA_ENABLE));
1138352ff8bdSFrançois Tigeot 	}
113919c468b4SFrançois Tigeot 
114019c468b4SFrançois Tigeot 	/* WaDisableThreadStallDopClockGating:bxt */
114119c468b4SFrançois Tigeot 	WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN,
114219c468b4SFrançois Tigeot 			  STALL_DOP_GATING_DISABLE);
114319c468b4SFrançois Tigeot 
11441487f786SFrançois Tigeot 	/* WaDisablePooledEuLoadBalancingFix:bxt */
11451487f786SFrançois Tigeot 	if (IS_BXT_REVID(dev_priv, BXT_REVID_B0, REVID_FOREVER)) {
11461487f786SFrançois Tigeot 		WA_SET_BIT_MASKED(FF_SLICE_CS_CHICKEN2,
11471487f786SFrançois Tigeot 				  GEN9_POOLED_EU_LOAD_BALANCING_FIX_DISABLE);
11481487f786SFrançois Tigeot 	}
11491487f786SFrançois Tigeot 
115019c468b4SFrançois Tigeot 	/* WaDisableSbeCacheDispatchPortSharing:bxt */
11511487f786SFrançois Tigeot 	if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_B0)) {
115219c468b4SFrançois Tigeot 		WA_SET_BIT_MASKED(
115319c468b4SFrançois Tigeot 			GEN7_HALF_SLICE_CHICKEN1,
115419c468b4SFrançois Tigeot 			GEN7_SBE_SS_CACHE_DISPATCH_PORT_SHARING_DISABLE);
115519c468b4SFrançois Tigeot 	}
115619c468b4SFrançois Tigeot 
1157c0e85e96SFrançois Tigeot 	/* WaDisableObjectLevelPreemptionForTrifanOrPolygon:bxt */
1158c0e85e96SFrançois Tigeot 	/* WaDisableObjectLevelPreemptionForInstancedDraw:bxt */
1159c0e85e96SFrançois Tigeot 	/* WaDisableObjectLevelPreemtionForInstanceId:bxt */
1160c0e85e96SFrançois Tigeot 	/* WaDisableLSQCROPERFforOCL:bxt */
11611487f786SFrançois Tigeot 	if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1)) {
11628621f407SFrançois Tigeot 		ret = wa_ring_whitelist_reg(engine, GEN9_CS_DEBUG_MODE1);
1163c0e85e96SFrançois Tigeot 		if (ret)
1164c0e85e96SFrançois Tigeot 			return ret;
1165c0e85e96SFrançois Tigeot 
11668621f407SFrançois Tigeot 		ret = wa_ring_whitelist_reg(engine, GEN8_L3SQCREG4);
1167c0e85e96SFrançois Tigeot 		if (ret)
1168c0e85e96SFrançois Tigeot 			return ret;
1169c0e85e96SFrançois Tigeot 	}
1170c0e85e96SFrançois Tigeot 
11711487f786SFrançois Tigeot 	/* WaProgramL3SqcReg1DefaultForPerf:bxt */
11721487f786SFrançois Tigeot 	if (IS_BXT_REVID(dev_priv, BXT_REVID_B0, REVID_FOREVER))
11731487f786SFrançois Tigeot 		I915_WRITE(GEN8_L3SQCREG1, L3_GENERAL_PRIO_CREDITS(62) |
11741487f786SFrançois Tigeot 					   L3_HIGH_PRIO_CREDITS(2));
11751487f786SFrançois Tigeot 
11768621f407SFrançois Tigeot 	/* WaInsertDummyPushConstPs:bxt */
11778621f407SFrançois Tigeot 	if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_B0))
11788621f407SFrançois Tigeot 		WA_SET_BIT_MASKED(COMMON_SLICE_CHICKEN2,
11798621f407SFrançois Tigeot 				  GEN8_SBE_DISABLE_REPLAY_BUF_OPTIMIZATION);
11808621f407SFrançois Tigeot 
118119c468b4SFrançois Tigeot 	return 0;
118219c468b4SFrançois Tigeot }
118319c468b4SFrançois Tigeot 
11848621f407SFrançois Tigeot static int kbl_init_workarounds(struct intel_engine_cs *engine)
11852c9916cdSFrançois Tigeot {
11861487f786SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
11878621f407SFrançois Tigeot 	int ret;
11888621f407SFrançois Tigeot 
11898621f407SFrançois Tigeot 	ret = gen9_init_workarounds(engine);
11908621f407SFrançois Tigeot 	if (ret)
11918621f407SFrançois Tigeot 		return ret;
11928621f407SFrançois Tigeot 
11938621f407SFrançois Tigeot 	/* WaEnableGapsTsvCreditFix:kbl */
11948621f407SFrançois Tigeot 	I915_WRITE(GEN8_GARBCNTL, (I915_READ(GEN8_GARBCNTL) |
11958621f407SFrançois Tigeot 				   GEN9_GAPS_TSV_CREDIT_DISABLE));
11968621f407SFrançois Tigeot 
11978621f407SFrançois Tigeot 	/* WaDisableDynamicCreditSharing:kbl */
11988621f407SFrançois Tigeot 	if (IS_KBL_REVID(dev_priv, 0, KBL_REVID_B0))
11998621f407SFrançois Tigeot 		WA_SET_BIT(GAMT_CHKN_BIT_REG,
12008621f407SFrançois Tigeot 			   GAMT_CHKN_DISABLE_DYNAMIC_CREDIT_SHARING);
12018621f407SFrançois Tigeot 
12028621f407SFrançois Tigeot 	/* WaDisableFenceDestinationToSLM:kbl (pre-prod) */
12038621f407SFrançois Tigeot 	if (IS_KBL_REVID(dev_priv, KBL_REVID_A0, KBL_REVID_A0))
12048621f407SFrançois Tigeot 		WA_SET_BIT_MASKED(HDC_CHICKEN0,
12058621f407SFrançois Tigeot 				  HDC_FENCE_DEST_SLM_DISABLE);
12068621f407SFrançois Tigeot 
12078621f407SFrançois Tigeot 	/* GEN8_L3SQCREG4 has a dependency with WA batch so any new changes
12088621f407SFrançois Tigeot 	 * involving this register should also be added to WA batch as required.
12098621f407SFrançois Tigeot 	 */
12108621f407SFrançois Tigeot 	if (IS_KBL_REVID(dev_priv, 0, KBL_REVID_E0))
12118621f407SFrançois Tigeot 		/* WaDisableLSQCROPERFforOCL:kbl */
12128621f407SFrançois Tigeot 		I915_WRITE(GEN8_L3SQCREG4, I915_READ(GEN8_L3SQCREG4) |
12138621f407SFrançois Tigeot 			   GEN8_LQSC_RO_PERF_DIS);
12148621f407SFrançois Tigeot 
12158621f407SFrançois Tigeot 	/* WaInsertDummyPushConstPs:kbl */
12168621f407SFrançois Tigeot 	if (IS_KBL_REVID(dev_priv, 0, KBL_REVID_B0))
12178621f407SFrançois Tigeot 		WA_SET_BIT_MASKED(COMMON_SLICE_CHICKEN2,
12188621f407SFrançois Tigeot 				  GEN8_SBE_DISABLE_REPLAY_BUF_OPTIMIZATION);
12198621f407SFrançois Tigeot 
12208621f407SFrançois Tigeot 	/* WaDisableGafsUnitClkGating:kbl */
12218621f407SFrançois Tigeot 	WA_SET_BIT(GEN7_UCGCTL4, GEN8_EU_GAUNIT_CLOCK_GATE_DISABLE);
12228621f407SFrançois Tigeot 
12238621f407SFrançois Tigeot 	/* WaDisableSbeCacheDispatchPortSharing:kbl */
12248621f407SFrançois Tigeot 	WA_SET_BIT_MASKED(
12258621f407SFrançois Tigeot 		GEN7_HALF_SLICE_CHICKEN1,
12268621f407SFrançois Tigeot 		GEN7_SBE_SS_CACHE_DISPATCH_PORT_SHARING_DISABLE);
12278621f407SFrançois Tigeot 
12288621f407SFrançois Tigeot 	/* WaDisableLSQCROPERFforOCL:kbl */
12298621f407SFrançois Tigeot 	ret = wa_ring_whitelist_reg(engine, GEN8_L3SQCREG4);
12308621f407SFrançois Tigeot 	if (ret)
12318621f407SFrançois Tigeot 		return ret;
12328621f407SFrançois Tigeot 
12338621f407SFrançois Tigeot 	return 0;
12348621f407SFrançois Tigeot }
12358621f407SFrançois Tigeot 
12368621f407SFrançois Tigeot int init_workarounds_ring(struct intel_engine_cs *engine)
12378621f407SFrançois Tigeot {
12381487f786SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
12392c9916cdSFrançois Tigeot 
12408621f407SFrançois Tigeot 	WARN_ON(engine->id != RCS);
12412c9916cdSFrançois Tigeot 
12422c9916cdSFrançois Tigeot 	dev_priv->workarounds.count = 0;
1243c0e85e96SFrançois Tigeot 	dev_priv->workarounds.hw_whitelist_count[RCS] = 0;
12442c9916cdSFrançois Tigeot 
12451487f786SFrançois Tigeot 	if (IS_BROADWELL(dev_priv))
12468621f407SFrançois Tigeot 		return bdw_init_workarounds(engine);
12472c9916cdSFrançois Tigeot 
12481487f786SFrançois Tigeot 	if (IS_CHERRYVIEW(dev_priv))
12498621f407SFrançois Tigeot 		return chv_init_workarounds(engine);
12501b13d190SFrançois Tigeot 
12511487f786SFrançois Tigeot 	if (IS_SKYLAKE(dev_priv))
12528621f407SFrançois Tigeot 		return skl_init_workarounds(engine);
125319c468b4SFrançois Tigeot 
12541487f786SFrançois Tigeot 	if (IS_BROXTON(dev_priv))
12558621f407SFrançois Tigeot 		return bxt_init_workarounds(engine);
12568621f407SFrançois Tigeot 
12578621f407SFrançois Tigeot 	if (IS_KABYLAKE(dev_priv))
12588621f407SFrançois Tigeot 		return kbl_init_workarounds(engine);
1259477eb7f9SFrançois Tigeot 
12601b13d190SFrançois Tigeot 	return 0;
12611b13d190SFrançois Tigeot }
12621b13d190SFrançois Tigeot 
12638621f407SFrançois Tigeot static int init_render_ring(struct intel_engine_cs *engine)
1264e3adcf8fSFrançois Tigeot {
12651487f786SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
12668621f407SFrançois Tigeot 	int ret = init_ring_common(engine);
126724edb884SFrançois Tigeot 	if (ret)
126824edb884SFrançois Tigeot 		return ret;
1269e3adcf8fSFrançois Tigeot 
1270ba55f2f5SFrançois Tigeot 	/* WaTimedSingleVertexDispatch:cl,bw,ctg,elk,ilk,snb */
12711487f786SFrançois Tigeot 	if (IS_GEN(dev_priv, 4, 6))
1272f4e1c372SFrançois Tigeot 		I915_WRITE(MI_MODE, _MASKED_BIT_ENABLE(VS_TIMER_DISPATCH));
1273f4e1c372SFrançois Tigeot 
1274f4e1c372SFrançois Tigeot 	/* We need to disable the AsyncFlip performance optimisations in order
1275f4e1c372SFrançois Tigeot 	 * to use MI_WAIT_FOR_EVENT within the CS. It should already be
1276f4e1c372SFrançois Tigeot 	 * programmed to '1' on all products.
12775d0b1887SFrançois Tigeot 	 *
1278a05eeebfSFrançois Tigeot 	 * WaDisableAsyncFlipPerfMode:snb,ivb,hsw,vlv
1279f4e1c372SFrançois Tigeot 	 */
12801487f786SFrançois Tigeot 	if (IS_GEN(dev_priv, 6, 7))
1281f4e1c372SFrançois Tigeot 		I915_WRITE(MI_MODE, _MASKED_BIT_ENABLE(ASYNC_FLIP_PERF_DISABLE));
1282f4e1c372SFrançois Tigeot 
1283f4e1c372SFrançois Tigeot 	/* Required for the hardware to program scanline values for waiting */
1284ba55f2f5SFrançois Tigeot 	/* WaEnableFlushTlbInvalidationMode:snb */
12851487f786SFrançois Tigeot 	if (IS_GEN6(dev_priv))
1286f4e1c372SFrançois Tigeot 		I915_WRITE(GFX_MODE,
1287ba55f2f5SFrançois Tigeot 			   _MASKED_BIT_ENABLE(GFX_TLB_INVALIDATE_EXPLICIT));
1288f4e1c372SFrançois Tigeot 
1289ba55f2f5SFrançois Tigeot 	/* WaBCSVCSTlbInvalidationMode:ivb,vlv,hsw */
12901487f786SFrançois Tigeot 	if (IS_GEN7(dev_priv))
1291e3adcf8fSFrançois Tigeot 		I915_WRITE(GFX_MODE_GEN7,
1292ba55f2f5SFrançois Tigeot 			   _MASKED_BIT_ENABLE(GFX_TLB_INVALIDATE_EXPLICIT) |
1293f4e1c372SFrançois Tigeot 			   _MASKED_BIT_ENABLE(GFX_REPLAY_MODE));
1294e3adcf8fSFrançois Tigeot 
12951487f786SFrançois Tigeot 	if (IS_GEN6(dev_priv)) {
1296e3adcf8fSFrançois Tigeot 		/* From the Sandybridge PRM, volume 1 part 3, page 24:
1297e3adcf8fSFrançois Tigeot 		 * "If this bit is set, STCunit will have LRA as replacement
1298e3adcf8fSFrançois Tigeot 		 *  policy. [...] This bit must be reset.  LRA replacement
1299e3adcf8fSFrançois Tigeot 		 *  policy is not supported."
1300e3adcf8fSFrançois Tigeot 		 */
1301e3adcf8fSFrançois Tigeot 		I915_WRITE(CACHE_MODE_0,
1302f4e1c372SFrançois Tigeot 			   _MASKED_BIT_DISABLE(CM0_STC_EVICT_DISABLE_LRA_SNB));
1303e3adcf8fSFrançois Tigeot 	}
1304e3adcf8fSFrançois Tigeot 
13051487f786SFrançois Tigeot 	if (IS_GEN(dev_priv, 6, 7))
1306f4e1c372SFrançois Tigeot 		I915_WRITE(INSTPM, _MASKED_BIT_ENABLE(INSTPM_FORCE_ORDERING));
1307f4e1c372SFrançois Tigeot 
1308*303bf270SFrançois Tigeot 	if (INTEL_INFO(dev_priv)->gen >= 6)
1309*303bf270SFrançois Tigeot 		I915_WRITE_IMR(engine, ~engine->irq_keep_mask);
1310e3adcf8fSFrançois Tigeot 
13118621f407SFrançois Tigeot 	return init_workarounds_ring(engine);
1312e3adcf8fSFrançois Tigeot }
1313e3adcf8fSFrançois Tigeot 
13148621f407SFrançois Tigeot static void render_ring_cleanup(struct intel_engine_cs *engine)
1315e3adcf8fSFrançois Tigeot {
13161487f786SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
131724edb884SFrançois Tigeot 
131824edb884SFrançois Tigeot 	if (dev_priv->semaphore_obj) {
131924edb884SFrançois Tigeot 		i915_gem_object_ggtt_unpin(dev_priv->semaphore_obj);
132024edb884SFrançois Tigeot 		drm_gem_object_unreference(&dev_priv->semaphore_obj->base);
132124edb884SFrançois Tigeot 		dev_priv->semaphore_obj = NULL;
132224edb884SFrançois Tigeot 	}
1323b5c29a34SFrançois Tigeot 
13248621f407SFrançois Tigeot 	intel_fini_pipe_control(engine);
1325e3adcf8fSFrançois Tigeot }
1326e3adcf8fSFrançois Tigeot 
1327a05eeebfSFrançois Tigeot static int gen8_rcs_signal(struct drm_i915_gem_request *signaller_req,
132824edb884SFrançois Tigeot 			   unsigned int num_dwords)
132924edb884SFrançois Tigeot {
133024edb884SFrançois Tigeot #define MBOX_UPDATE_DWORDS 8
13318621f407SFrançois Tigeot 	struct intel_engine_cs *signaller = signaller_req->engine;
13321487f786SFrançois Tigeot 	struct drm_i915_private *dev_priv = signaller_req->i915;
133324edb884SFrançois Tigeot 	struct intel_engine_cs *waiter;
13348621f407SFrançois Tigeot 	enum intel_engine_id id;
13358621f407SFrançois Tigeot 	int ret, num_rings;
133624edb884SFrançois Tigeot 
13371487f786SFrançois Tigeot 	num_rings = hweight32(INTEL_INFO(dev_priv)->ring_mask);
133824edb884SFrançois Tigeot 	num_dwords += (num_rings-1) * MBOX_UPDATE_DWORDS;
133924edb884SFrançois Tigeot #undef MBOX_UPDATE_DWORDS
134024edb884SFrançois Tigeot 
1341a05eeebfSFrançois Tigeot 	ret = intel_ring_begin(signaller_req, num_dwords);
134224edb884SFrançois Tigeot 	if (ret)
134324edb884SFrançois Tigeot 		return ret;
134424edb884SFrançois Tigeot 
13458621f407SFrançois Tigeot 	for_each_engine_id(waiter, dev_priv, id) {
13468621f407SFrançois Tigeot 		u64 gtt_offset = signaller->semaphore.signal_ggtt[id];
134724edb884SFrançois Tigeot 		if (gtt_offset == MI_SEMAPHORE_SYNC_INVALID)
134824edb884SFrançois Tigeot 			continue;
134924edb884SFrançois Tigeot 
135024edb884SFrançois Tigeot 		intel_ring_emit(signaller, GFX_OP_PIPE_CONTROL(6));
135124edb884SFrançois Tigeot 		intel_ring_emit(signaller, PIPE_CONTROL_GLOBAL_GTT_IVB |
135224edb884SFrançois Tigeot 					   PIPE_CONTROL_QW_WRITE |
13531487f786SFrançois Tigeot 					   PIPE_CONTROL_CS_STALL);
135424edb884SFrançois Tigeot 		intel_ring_emit(signaller, lower_32_bits(gtt_offset));
135524edb884SFrançois Tigeot 		intel_ring_emit(signaller, upper_32_bits(gtt_offset));
1356*303bf270SFrançois Tigeot 		intel_ring_emit(signaller, signaller_req->seqno);
135724edb884SFrançois Tigeot 		intel_ring_emit(signaller, 0);
135824edb884SFrançois Tigeot 		intel_ring_emit(signaller, MI_SEMAPHORE_SIGNAL |
13598621f407SFrançois Tigeot 					   MI_SEMAPHORE_TARGET(waiter->hw_id));
136024edb884SFrançois Tigeot 		intel_ring_emit(signaller, 0);
136124edb884SFrançois Tigeot 	}
136224edb884SFrançois Tigeot 
136324edb884SFrançois Tigeot 	return 0;
136424edb884SFrançois Tigeot }
136524edb884SFrançois Tigeot 
1366a05eeebfSFrançois Tigeot static int gen8_xcs_signal(struct drm_i915_gem_request *signaller_req,
136724edb884SFrançois Tigeot 			   unsigned int num_dwords)
136824edb884SFrançois Tigeot {
136924edb884SFrançois Tigeot #define MBOX_UPDATE_DWORDS 6
13708621f407SFrançois Tigeot 	struct intel_engine_cs *signaller = signaller_req->engine;
13711487f786SFrançois Tigeot 	struct drm_i915_private *dev_priv = signaller_req->i915;
137224edb884SFrançois Tigeot 	struct intel_engine_cs *waiter;
13738621f407SFrançois Tigeot 	enum intel_engine_id id;
13748621f407SFrançois Tigeot 	int ret, num_rings;
137524edb884SFrançois Tigeot 
13761487f786SFrançois Tigeot 	num_rings = hweight32(INTEL_INFO(dev_priv)->ring_mask);
137724edb884SFrançois Tigeot 	num_dwords += (num_rings-1) * MBOX_UPDATE_DWORDS;
137824edb884SFrançois Tigeot #undef MBOX_UPDATE_DWORDS
137924edb884SFrançois Tigeot 
1380a05eeebfSFrançois Tigeot 	ret = intel_ring_begin(signaller_req, num_dwords);
138124edb884SFrançois Tigeot 	if (ret)
138224edb884SFrançois Tigeot 		return ret;
138324edb884SFrançois Tigeot 
13848621f407SFrançois Tigeot 	for_each_engine_id(waiter, dev_priv, id) {
13858621f407SFrançois Tigeot 		u64 gtt_offset = signaller->semaphore.signal_ggtt[id];
138624edb884SFrançois Tigeot 		if (gtt_offset == MI_SEMAPHORE_SYNC_INVALID)
138724edb884SFrançois Tigeot 			continue;
138824edb884SFrançois Tigeot 
138924edb884SFrançois Tigeot 		intel_ring_emit(signaller, (MI_FLUSH_DW + 1) |
139024edb884SFrançois Tigeot 					   MI_FLUSH_DW_OP_STOREDW);
139124edb884SFrançois Tigeot 		intel_ring_emit(signaller, lower_32_bits(gtt_offset) |
139224edb884SFrançois Tigeot 					   MI_FLUSH_DW_USE_GTT);
139324edb884SFrançois Tigeot 		intel_ring_emit(signaller, upper_32_bits(gtt_offset));
1394*303bf270SFrançois Tigeot 		intel_ring_emit(signaller, signaller_req->seqno);
139524edb884SFrançois Tigeot 		intel_ring_emit(signaller, MI_SEMAPHORE_SIGNAL |
13968621f407SFrançois Tigeot 					   MI_SEMAPHORE_TARGET(waiter->hw_id));
139724edb884SFrançois Tigeot 		intel_ring_emit(signaller, 0);
139824edb884SFrançois Tigeot 	}
139924edb884SFrançois Tigeot 
140024edb884SFrançois Tigeot 	return 0;
140124edb884SFrançois Tigeot }
140224edb884SFrançois Tigeot 
1403a05eeebfSFrançois Tigeot static int gen6_signal(struct drm_i915_gem_request *signaller_req,
1404ba55f2f5SFrançois Tigeot 		       unsigned int num_dwords)
1405e3adcf8fSFrançois Tigeot {
14068621f407SFrançois Tigeot 	struct intel_engine_cs *signaller = signaller_req->engine;
14071487f786SFrançois Tigeot 	struct drm_i915_private *dev_priv = signaller_req->i915;
1408ba55f2f5SFrançois Tigeot 	struct intel_engine_cs *useless;
14098621f407SFrançois Tigeot 	enum intel_engine_id id;
14108621f407SFrançois Tigeot 	int ret, num_rings;
1411ba55f2f5SFrançois Tigeot 
141224edb884SFrançois Tigeot #define MBOX_UPDATE_DWORDS 3
14131487f786SFrançois Tigeot 	num_rings = hweight32(INTEL_INFO(dev_priv)->ring_mask);
141424edb884SFrançois Tigeot 	num_dwords += round_up((num_rings-1) * MBOX_UPDATE_DWORDS, 2);
141524edb884SFrançois Tigeot #undef MBOX_UPDATE_DWORDS
1416ba55f2f5SFrançois Tigeot 
1417a05eeebfSFrançois Tigeot 	ret = intel_ring_begin(signaller_req, num_dwords);
1418ba55f2f5SFrançois Tigeot 	if (ret)
1419ba55f2f5SFrançois Tigeot 		return ret;
1420ba55f2f5SFrançois Tigeot 
14218621f407SFrançois Tigeot 	for_each_engine_id(useless, dev_priv, id) {
14228621f407SFrançois Tigeot 		i915_reg_t mbox_reg = signaller->semaphore.mbox.signal[id];
1423aee94f86SFrançois Tigeot 
1424aee94f86SFrançois Tigeot 		if (i915_mmio_reg_valid(mbox_reg)) {
1425ba55f2f5SFrançois Tigeot 			intel_ring_emit(signaller, MI_LOAD_REGISTER_IMM(1));
1426aee94f86SFrançois Tigeot 			intel_ring_emit_reg(signaller, mbox_reg);
1427*303bf270SFrançois Tigeot 			intel_ring_emit(signaller, signaller_req->seqno);
1428ba55f2f5SFrançois Tigeot 		}
1429ba55f2f5SFrançois Tigeot 	}
1430ba55f2f5SFrançois Tigeot 
143124edb884SFrançois Tigeot 	/* If num_dwords was rounded, make sure the tail pointer is correct */
143224edb884SFrançois Tigeot 	if (num_rings % 2 == 0)
143324edb884SFrançois Tigeot 		intel_ring_emit(signaller, MI_NOOP);
143424edb884SFrançois Tigeot 
1435ba55f2f5SFrançois Tigeot 	return 0;
1436e3adcf8fSFrançois Tigeot }
1437e3adcf8fSFrançois Tigeot 
1438e3adcf8fSFrançois Tigeot /**
1439e3adcf8fSFrançois Tigeot  * gen6_add_request - Update the semaphore mailbox registers
1440e3adcf8fSFrançois Tigeot  *
1441a05eeebfSFrançois Tigeot  * @request - request to write to the ring
1442e3adcf8fSFrançois Tigeot  *
1443e3adcf8fSFrançois Tigeot  * Update the mailbox registers in the *other* rings with the current seqno.
1444e3adcf8fSFrançois Tigeot  * This acts like a signal in the canonical semaphore.
1445e3adcf8fSFrançois Tigeot  */
1446e3adcf8fSFrançois Tigeot static int
1447a05eeebfSFrançois Tigeot gen6_add_request(struct drm_i915_gem_request *req)
1448e3adcf8fSFrançois Tigeot {
14498621f407SFrançois Tigeot 	struct intel_engine_cs *engine = req->engine;
1450ba55f2f5SFrançois Tigeot 	int ret;
1451e3adcf8fSFrançois Tigeot 
14528621f407SFrançois Tigeot 	if (engine->semaphore.signal)
14538621f407SFrançois Tigeot 		ret = engine->semaphore.signal(req, 4);
145424edb884SFrançois Tigeot 	else
1455a05eeebfSFrançois Tigeot 		ret = intel_ring_begin(req, 4);
145624edb884SFrançois Tigeot 
14579edbd4a0SFrançois Tigeot 	if (ret)
14589edbd4a0SFrançois Tigeot 		return ret;
14599edbd4a0SFrançois Tigeot 
14608621f407SFrançois Tigeot 	intel_ring_emit(engine, MI_STORE_DWORD_INDEX);
14618621f407SFrançois Tigeot 	intel_ring_emit(engine,
14628621f407SFrançois Tigeot 			I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT);
1463*303bf270SFrançois Tigeot 	intel_ring_emit(engine, req->seqno);
14648621f407SFrançois Tigeot 	intel_ring_emit(engine, MI_USER_INTERRUPT);
14658621f407SFrançois Tigeot 	__intel_ring_advance(engine);
1466e3adcf8fSFrançois Tigeot 
1467e3adcf8fSFrançois Tigeot 	return 0;
1468e3adcf8fSFrançois Tigeot }
1469e3adcf8fSFrançois Tigeot 
14701487f786SFrançois Tigeot static int
14711487f786SFrançois Tigeot gen8_render_add_request(struct drm_i915_gem_request *req)
14721487f786SFrançois Tigeot {
14731487f786SFrançois Tigeot 	struct intel_engine_cs *engine = req->engine;
14741487f786SFrançois Tigeot 	int ret;
14751487f786SFrançois Tigeot 
14761487f786SFrançois Tigeot 	if (engine->semaphore.signal)
14771487f786SFrançois Tigeot 		ret = engine->semaphore.signal(req, 8);
14781487f786SFrançois Tigeot 	else
14791487f786SFrançois Tigeot 		ret = intel_ring_begin(req, 8);
14801487f786SFrançois Tigeot 	if (ret)
14811487f786SFrançois Tigeot 		return ret;
14821487f786SFrançois Tigeot 
14831487f786SFrançois Tigeot 	intel_ring_emit(engine, GFX_OP_PIPE_CONTROL(6));
14841487f786SFrançois Tigeot 	intel_ring_emit(engine, (PIPE_CONTROL_GLOBAL_GTT_IVB |
14851487f786SFrançois Tigeot 				 PIPE_CONTROL_CS_STALL |
14861487f786SFrançois Tigeot 				 PIPE_CONTROL_QW_WRITE));
14871487f786SFrançois Tigeot 	intel_ring_emit(engine, intel_hws_seqno_address(req->engine));
14881487f786SFrançois Tigeot 	intel_ring_emit(engine, 0);
14891487f786SFrançois Tigeot 	intel_ring_emit(engine, i915_gem_request_get_seqno(req));
14901487f786SFrançois Tigeot 	/* We're thrashing one dword of HWS. */
14911487f786SFrançois Tigeot 	intel_ring_emit(engine, 0);
14921487f786SFrançois Tigeot 	intel_ring_emit(engine, MI_USER_INTERRUPT);
14931487f786SFrançois Tigeot 	intel_ring_emit(engine, MI_NOOP);
14941487f786SFrançois Tigeot 	__intel_ring_advance(engine);
14951487f786SFrançois Tigeot 
14961487f786SFrançois Tigeot 	return 0;
14971487f786SFrançois Tigeot }
14981487f786SFrançois Tigeot 
14991487f786SFrançois Tigeot static inline bool i915_gem_has_seqno_wrapped(struct drm_i915_private *dev_priv,
1500a2fdbec6SFrançois Tigeot 					      u32 seqno)
1501a2fdbec6SFrançois Tigeot {
1502a2fdbec6SFrançois Tigeot 	return dev_priv->last_seqno < seqno;
1503a2fdbec6SFrançois Tigeot }
1504a2fdbec6SFrançois Tigeot 
1505e3adcf8fSFrançois Tigeot /**
1506e3adcf8fSFrançois Tigeot  * intel_ring_sync - sync the waiter to the signaller on seqno
1507e3adcf8fSFrançois Tigeot  *
1508e3adcf8fSFrançois Tigeot  * @waiter - ring that is waiting
1509e3adcf8fSFrançois Tigeot  * @signaller - ring which has, or will signal
1510e3adcf8fSFrançois Tigeot  * @seqno - seqno which the waiter will block on
1511e3adcf8fSFrançois Tigeot  */
151224edb884SFrançois Tigeot 
151324edb884SFrançois Tigeot static int
1514a05eeebfSFrançois Tigeot gen8_ring_sync(struct drm_i915_gem_request *waiter_req,
151524edb884SFrançois Tigeot 	       struct intel_engine_cs *signaller,
151624edb884SFrançois Tigeot 	       u32 seqno)
151724edb884SFrançois Tigeot {
15188621f407SFrançois Tigeot 	struct intel_engine_cs *waiter = waiter_req->engine;
15191487f786SFrançois Tigeot 	struct drm_i915_private *dev_priv = waiter_req->i915;
15201487f786SFrançois Tigeot 	u64 offset = GEN8_WAIT_OFFSET(waiter, signaller->id);
15211487f786SFrançois Tigeot 	struct i915_hw_ppgtt *ppgtt;
152224edb884SFrançois Tigeot 	int ret;
152324edb884SFrançois Tigeot 
1524a05eeebfSFrançois Tigeot 	ret = intel_ring_begin(waiter_req, 4);
152524edb884SFrançois Tigeot 	if (ret)
152624edb884SFrançois Tigeot 		return ret;
152724edb884SFrançois Tigeot 
152824edb884SFrançois Tigeot 	intel_ring_emit(waiter, MI_SEMAPHORE_WAIT |
152924edb884SFrançois Tigeot 				MI_SEMAPHORE_GLOBAL_GTT |
153024edb884SFrançois Tigeot 				MI_SEMAPHORE_SAD_GTE_SDD);
153124edb884SFrançois Tigeot 	intel_ring_emit(waiter, seqno);
15321487f786SFrançois Tigeot 	intel_ring_emit(waiter, lower_32_bits(offset));
15331487f786SFrançois Tigeot 	intel_ring_emit(waiter, upper_32_bits(offset));
153424edb884SFrançois Tigeot 	intel_ring_advance(waiter);
15351487f786SFrançois Tigeot 
15361487f786SFrançois Tigeot 	/* When the !RCS engines idle waiting upon a semaphore, they lose their
15371487f786SFrançois Tigeot 	 * pagetables and we must reload them before executing the batch.
15381487f786SFrançois Tigeot 	 * We do this on the i915_switch_context() following the wait and
15391487f786SFrançois Tigeot 	 * before the dispatch.
15401487f786SFrançois Tigeot 	 */
15411487f786SFrançois Tigeot 	ppgtt = waiter_req->ctx->ppgtt;
15421487f786SFrançois Tigeot 	if (ppgtt && waiter_req->engine->id != RCS)
15431487f786SFrançois Tigeot 		ppgtt->pd_dirty_rings |= intel_engine_flag(waiter_req->engine);
154424edb884SFrançois Tigeot 	return 0;
154524edb884SFrançois Tigeot }
154624edb884SFrançois Tigeot 
1547e3adcf8fSFrançois Tigeot static int
1548a05eeebfSFrançois Tigeot gen6_ring_sync(struct drm_i915_gem_request *waiter_req,
1549ba55f2f5SFrançois Tigeot 	       struct intel_engine_cs *signaller,
1550e3adcf8fSFrançois Tigeot 	       u32 seqno)
1551e3adcf8fSFrançois Tigeot {
15528621f407SFrançois Tigeot 	struct intel_engine_cs *waiter = waiter_req->engine;
1553e3adcf8fSFrançois Tigeot 	u32 dw1 = MI_SEMAPHORE_MBOX |
1554e3adcf8fSFrançois Tigeot 		  MI_SEMAPHORE_COMPARE |
1555e3adcf8fSFrançois Tigeot 		  MI_SEMAPHORE_REGISTER;
1556ba55f2f5SFrançois Tigeot 	u32 wait_mbox = signaller->semaphore.mbox.wait[waiter->id];
1557ba55f2f5SFrançois Tigeot 	int ret;
1558e3adcf8fSFrançois Tigeot 
1559686a02f1SFrançois Tigeot 	/* Throughout all of the GEM code, seqno passed implies our current
1560686a02f1SFrançois Tigeot 	 * seqno is >= the last seqno executed. However for hardware the
1561686a02f1SFrançois Tigeot 	 * comparison is strictly greater than.
1562686a02f1SFrançois Tigeot 	 */
1563686a02f1SFrançois Tigeot 	seqno -= 1;
1564686a02f1SFrançois Tigeot 
1565ba55f2f5SFrançois Tigeot 	WARN_ON(wait_mbox == MI_SEMAPHORE_SYNC_INVALID);
1566686a02f1SFrançois Tigeot 
1567a05eeebfSFrançois Tigeot 	ret = intel_ring_begin(waiter_req, 4);
1568e3adcf8fSFrançois Tigeot 	if (ret)
1569e3adcf8fSFrançois Tigeot 		return ret;
1570e3adcf8fSFrançois Tigeot 
1571a2fdbec6SFrançois Tigeot 	/* If seqno wrap happened, omit the wait with no-ops */
15721487f786SFrançois Tigeot 	if (likely(!i915_gem_has_seqno_wrapped(waiter_req->i915, seqno))) {
1573ba55f2f5SFrançois Tigeot 		intel_ring_emit(waiter, dw1 | wait_mbox);
1574e3adcf8fSFrançois Tigeot 		intel_ring_emit(waiter, seqno);
1575e3adcf8fSFrançois Tigeot 		intel_ring_emit(waiter, 0);
1576e3adcf8fSFrançois Tigeot 		intel_ring_emit(waiter, MI_NOOP);
1577a2fdbec6SFrançois Tigeot 	} else {
1578a2fdbec6SFrançois Tigeot 		intel_ring_emit(waiter, MI_NOOP);
1579a2fdbec6SFrançois Tigeot 		intel_ring_emit(waiter, MI_NOOP);
1580a2fdbec6SFrançois Tigeot 		intel_ring_emit(waiter, MI_NOOP);
1581a2fdbec6SFrançois Tigeot 		intel_ring_emit(waiter, MI_NOOP);
1582a2fdbec6SFrançois Tigeot 	}
1583e3adcf8fSFrançois Tigeot 	intel_ring_advance(waiter);
1584e3adcf8fSFrançois Tigeot 
1585e3adcf8fSFrançois Tigeot 	return 0;
1586e3adcf8fSFrançois Tigeot }
1587e3adcf8fSFrançois Tigeot 
1588*303bf270SFrançois Tigeot static void
1589*303bf270SFrançois Tigeot gen5_seqno_barrier(struct intel_engine_cs *ring)
1590e3adcf8fSFrançois Tigeot {
1591*303bf270SFrançois Tigeot 	/* MI_STORE are internally buffered by the GPU and not flushed
1592*303bf270SFrançois Tigeot 	 * either by MI_FLUSH or SyncFlush or any other combination of
1593*303bf270SFrançois Tigeot 	 * MI commands.
1594e3adcf8fSFrançois Tigeot 	 *
1595*303bf270SFrançois Tigeot 	 * "Only the submission of the store operation is guaranteed.
1596*303bf270SFrançois Tigeot 	 * The write result will be complete (coherent) some time later
1597*303bf270SFrançois Tigeot 	 * (this is practically a finite period but there is no guaranteed
1598*303bf270SFrançois Tigeot 	 * latency)."
1599*303bf270SFrançois Tigeot 	 *
1600*303bf270SFrançois Tigeot 	 * Empirically, we observe that we need a delay of at least 75us to
1601*303bf270SFrançois Tigeot 	 * be sure that the seqno write is visible by the CPU.
1602e3adcf8fSFrançois Tigeot 	 */
1603*303bf270SFrançois Tigeot 	usleep_range(125, 250);
1604e3adcf8fSFrançois Tigeot }
1605e3adcf8fSFrançois Tigeot 
16068621f407SFrançois Tigeot static void
16078621f407SFrançois Tigeot gen6_seqno_barrier(struct intel_engine_cs *engine)
1608e3adcf8fSFrançois Tigeot {
16091487f786SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
16108621f407SFrançois Tigeot 
1611e3adcf8fSFrançois Tigeot 	/* Workaround to force correct ordering between irq and seqno writes on
1612e3adcf8fSFrançois Tigeot 	 * ivb (and maybe also on snb) by reading from a CS register (like
16138621f407SFrançois Tigeot 	 * ACTHD) before reading the status page.
16148621f407SFrançois Tigeot 	 *
16158621f407SFrançois Tigeot 	 * Note that this effectively stalls the read by the time it takes to
16168621f407SFrançois Tigeot 	 * do a memory transaction, which more or less ensures that the write
16178621f407SFrançois Tigeot 	 * from the GPU has sufficient time to invalidate the CPU cacheline.
16188621f407SFrançois Tigeot 	 * Alternatively we could delay the interrupt from the CS ring to give
16198621f407SFrançois Tigeot 	 * the write time to land, but that would incur a delay after every
16208621f407SFrançois Tigeot 	 * batch i.e. much more frequent than a delay when waiting for the
16218621f407SFrançois Tigeot 	 * interrupt (with the same net latency).
16228621f407SFrançois Tigeot 	 *
16238621f407SFrançois Tigeot 	 * Also note that to prevent whole machine hangs on gen7, we have to
16248621f407SFrançois Tigeot 	 * take the spinlock to guard against concurrent cacheline access.
16258621f407SFrançois Tigeot 	 */
16268621f407SFrançois Tigeot 	spin_lock_irq(&dev_priv->uncore.lock);
16278621f407SFrançois Tigeot 	POSTING_READ_FW(RING_ACTHD(engine->mmio_base));
16288621f407SFrançois Tigeot 	spin_unlock_irq(&dev_priv->uncore.lock);
1629e3adcf8fSFrançois Tigeot }
1630e3adcf8fSFrançois Tigeot 
1631*303bf270SFrançois Tigeot static void
1632*303bf270SFrançois Tigeot gen5_irq_enable(struct intel_engine_cs *engine)
1633e3adcf8fSFrançois Tigeot {
1634*303bf270SFrançois Tigeot 	gen5_enable_gt_irq(engine->i915, engine->irq_enable_mask);
1635e3adcf8fSFrançois Tigeot }
1636e3adcf8fSFrançois Tigeot 
1637a2fdbec6SFrançois Tigeot static void
1638*303bf270SFrançois Tigeot gen5_irq_disable(struct intel_engine_cs *engine)
1639a2fdbec6SFrançois Tigeot {
1640*303bf270SFrançois Tigeot 	gen5_disable_gt_irq(engine->i915, engine->irq_enable_mask);
1641e3adcf8fSFrançois Tigeot }
1642e3adcf8fSFrançois Tigeot 
1643a2fdbec6SFrançois Tigeot static void
1644*303bf270SFrançois Tigeot i9xx_irq_enable(struct intel_engine_cs *engine)
1645e3adcf8fSFrançois Tigeot {
16461487f786SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
1647e3adcf8fSFrançois Tigeot 
16488621f407SFrançois Tigeot 	dev_priv->irq_mask &= ~engine->irq_enable_mask;
1649686a02f1SFrançois Tigeot 	I915_WRITE(IMR, dev_priv->irq_mask);
1650*303bf270SFrançois Tigeot 	POSTING_READ_FW(RING_IMR(engine->mmio_base));
1651686a02f1SFrançois Tigeot }
1652686a02f1SFrançois Tigeot 
1653686a02f1SFrançois Tigeot static void
1654*303bf270SFrançois Tigeot i9xx_irq_disable(struct intel_engine_cs *engine)
1655686a02f1SFrançois Tigeot {
16561487f786SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
1657686a02f1SFrançois Tigeot 
16588621f407SFrançois Tigeot 	dev_priv->irq_mask |= engine->irq_enable_mask;
1659686a02f1SFrançois Tigeot 	I915_WRITE(IMR, dev_priv->irq_mask);
1660686a02f1SFrançois Tigeot }
1661686a02f1SFrançois Tigeot 
1662686a02f1SFrançois Tigeot static void
1663*303bf270SFrançois Tigeot i8xx_irq_enable(struct intel_engine_cs *engine)
1664686a02f1SFrançois Tigeot {
16651487f786SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
1666686a02f1SFrançois Tigeot 
1667*303bf270SFrançois Tigeot 	dev_priv->irq_mask &= ~engine->irq_enable_mask;
1668*303bf270SFrançois Tigeot 	I915_WRITE16(IMR, dev_priv->irq_mask);
1669*303bf270SFrançois Tigeot 	POSTING_READ16(RING_IMR(engine->mmio_base));
1670*303bf270SFrançois Tigeot }
1671*303bf270SFrançois Tigeot 
1672*303bf270SFrançois Tigeot static void
1673*303bf270SFrançois Tigeot i8xx_irq_disable(struct intel_engine_cs *engine)
1674*303bf270SFrançois Tigeot {
1675*303bf270SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
1676*303bf270SFrançois Tigeot 
16778621f407SFrançois Tigeot 	dev_priv->irq_mask |= engine->irq_enable_mask;
1678686a02f1SFrançois Tigeot 	I915_WRITE16(IMR, dev_priv->irq_mask);
1679e3adcf8fSFrançois Tigeot }
1680e3adcf8fSFrançois Tigeot 
1681e3adcf8fSFrançois Tigeot static int
1682a05eeebfSFrançois Tigeot bsd_ring_flush(struct drm_i915_gem_request *req,
1683b5c29a34SFrançois Tigeot 	       u32     invalidate_domains,
1684b5c29a34SFrançois Tigeot 	       u32     flush_domains)
1685e3adcf8fSFrançois Tigeot {
16868621f407SFrançois Tigeot 	struct intel_engine_cs *engine = req->engine;
1687e3adcf8fSFrançois Tigeot 	int ret;
1688e3adcf8fSFrançois Tigeot 
1689a05eeebfSFrançois Tigeot 	ret = intel_ring_begin(req, 2);
1690e3adcf8fSFrançois Tigeot 	if (ret)
1691e3adcf8fSFrançois Tigeot 		return ret;
1692e3adcf8fSFrançois Tigeot 
16938621f407SFrançois Tigeot 	intel_ring_emit(engine, MI_FLUSH);
16948621f407SFrançois Tigeot 	intel_ring_emit(engine, MI_NOOP);
16958621f407SFrançois Tigeot 	intel_ring_advance(engine);
1696e3adcf8fSFrançois Tigeot 	return 0;
1697e3adcf8fSFrançois Tigeot }
1698e3adcf8fSFrançois Tigeot 
1699e3adcf8fSFrançois Tigeot static int
1700a05eeebfSFrançois Tigeot i9xx_add_request(struct drm_i915_gem_request *req)
1701e3adcf8fSFrançois Tigeot {
17028621f407SFrançois Tigeot 	struct intel_engine_cs *engine = req->engine;
1703e3adcf8fSFrançois Tigeot 	int ret;
1704e3adcf8fSFrançois Tigeot 
1705a05eeebfSFrançois Tigeot 	ret = intel_ring_begin(req, 4);
1706e3adcf8fSFrançois Tigeot 	if (ret)
1707e3adcf8fSFrançois Tigeot 		return ret;
1708e3adcf8fSFrançois Tigeot 
17098621f407SFrançois Tigeot 	intel_ring_emit(engine, MI_STORE_DWORD_INDEX);
17108621f407SFrançois Tigeot 	intel_ring_emit(engine,
17118621f407SFrançois Tigeot 			I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT);
1712*303bf270SFrançois Tigeot 	intel_ring_emit(engine, req->seqno);
17138621f407SFrançois Tigeot 	intel_ring_emit(engine, MI_USER_INTERRUPT);
17148621f407SFrançois Tigeot 	__intel_ring_advance(engine);
1715e3adcf8fSFrançois Tigeot 
1716e3adcf8fSFrançois Tigeot 	return 0;
1717e3adcf8fSFrançois Tigeot }
1718e3adcf8fSFrançois Tigeot 
1719*303bf270SFrançois Tigeot static void
1720*303bf270SFrançois Tigeot gen6_irq_enable(struct intel_engine_cs *engine)
1721e3adcf8fSFrançois Tigeot {
17221487f786SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
1723e3adcf8fSFrançois Tigeot 
17248621f407SFrançois Tigeot 	I915_WRITE_IMR(engine,
17258621f407SFrançois Tigeot 		       ~(engine->irq_enable_mask |
1726*303bf270SFrançois Tigeot 			 engine->irq_keep_mask));
17278621f407SFrançois Tigeot 	gen5_enable_gt_irq(dev_priv, engine->irq_enable_mask);
1728e3adcf8fSFrançois Tigeot }
1729e3adcf8fSFrançois Tigeot 
1730e3adcf8fSFrançois Tigeot static void
1731*303bf270SFrançois Tigeot gen6_irq_disable(struct intel_engine_cs *engine)
1732e3adcf8fSFrançois Tigeot {
17331487f786SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
1734e3adcf8fSFrançois Tigeot 
1735*303bf270SFrançois Tigeot 	I915_WRITE_IMR(engine, ~engine->irq_keep_mask);
17368621f407SFrançois Tigeot 	gen5_disable_gt_irq(dev_priv, engine->irq_enable_mask);
1737e3adcf8fSFrançois Tigeot }
1738e3adcf8fSFrançois Tigeot 
1739*303bf270SFrançois Tigeot static void
1740*303bf270SFrançois Tigeot hsw_vebox_irq_enable(struct intel_engine_cs *engine)
17415d0b1887SFrançois Tigeot {
17421487f786SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
17435d0b1887SFrançois Tigeot 
17448621f407SFrançois Tigeot 	I915_WRITE_IMR(engine, ~engine->irq_enable_mask);
17458621f407SFrançois Tigeot 	gen6_enable_pm_irq(dev_priv, engine->irq_enable_mask);
17465d0b1887SFrançois Tigeot }
17475d0b1887SFrançois Tigeot 
17485d0b1887SFrançois Tigeot static void
1749*303bf270SFrançois Tigeot hsw_vebox_irq_disable(struct intel_engine_cs *engine)
17505d0b1887SFrançois Tigeot {
17511487f786SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
17525d0b1887SFrançois Tigeot 
17538621f407SFrançois Tigeot 	I915_WRITE_IMR(engine, ~0);
17548621f407SFrançois Tigeot 	gen6_disable_pm_irq(dev_priv, engine->irq_enable_mask);
17555d0b1887SFrançois Tigeot }
17569edbd4a0SFrançois Tigeot 
1757*303bf270SFrançois Tigeot static void
1758*303bf270SFrançois Tigeot gen8_irq_enable(struct intel_engine_cs *engine)
17599edbd4a0SFrançois Tigeot {
17601487f786SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
17619edbd4a0SFrançois Tigeot 
17628621f407SFrançois Tigeot 	I915_WRITE_IMR(engine,
17638621f407SFrançois Tigeot 		       ~(engine->irq_enable_mask |
1764*303bf270SFrançois Tigeot 			 engine->irq_keep_mask));
1765*303bf270SFrançois Tigeot 	POSTING_READ_FW(RING_IMR(engine->mmio_base));
17669edbd4a0SFrançois Tigeot }
17679edbd4a0SFrançois Tigeot 
17689edbd4a0SFrançois Tigeot static void
1769*303bf270SFrançois Tigeot gen8_irq_disable(struct intel_engine_cs *engine)
17709edbd4a0SFrançois Tigeot {
17711487f786SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
17729edbd4a0SFrançois Tigeot 
1773*303bf270SFrançois Tigeot 	I915_WRITE_IMR(engine, ~engine->irq_keep_mask);
17745d0b1887SFrançois Tigeot }
17755d0b1887SFrançois Tigeot 
1776e3adcf8fSFrançois Tigeot static int
1777a05eeebfSFrançois Tigeot i965_dispatch_execbuffer(struct drm_i915_gem_request *req,
1778ba55f2f5SFrançois Tigeot 			 u64 offset, u32 length,
1779477eb7f9SFrançois Tigeot 			 unsigned dispatch_flags)
1780e3adcf8fSFrançois Tigeot {
17818621f407SFrançois Tigeot 	struct intel_engine_cs *engine = req->engine;
1782e3adcf8fSFrançois Tigeot 	int ret;
1783e3adcf8fSFrançois Tigeot 
1784a05eeebfSFrançois Tigeot 	ret = intel_ring_begin(req, 2);
1785e3adcf8fSFrançois Tigeot 	if (ret)
1786e3adcf8fSFrançois Tigeot 		return ret;
1787e3adcf8fSFrançois Tigeot 
17888621f407SFrançois Tigeot 	intel_ring_emit(engine,
1789686a02f1SFrançois Tigeot 			MI_BATCH_BUFFER_START |
1790b5c29a34SFrançois Tigeot 			MI_BATCH_GTT |
1791477eb7f9SFrançois Tigeot 			(dispatch_flags & I915_DISPATCH_SECURE ?
1792477eb7f9SFrançois Tigeot 			 0 : MI_BATCH_NON_SECURE_I965));
17938621f407SFrançois Tigeot 	intel_ring_emit(engine, offset);
17948621f407SFrançois Tigeot 	intel_ring_advance(engine);
1795e3adcf8fSFrançois Tigeot 
1796e3adcf8fSFrançois Tigeot 	return 0;
1797e3adcf8fSFrançois Tigeot }
1798e3adcf8fSFrançois Tigeot 
1799b5c29a34SFrançois Tigeot /* Just userspace ABI convention to limit the wa batch bo to a resonable size */
1800b5c29a34SFrançois Tigeot #define I830_BATCH_LIMIT (256*1024)
180124edb884SFrançois Tigeot #define I830_TLB_ENTRIES (2)
180224edb884SFrançois Tigeot #define I830_WA_SIZE max(I830_TLB_ENTRIES*4096, I830_BATCH_LIMIT)
1803e3adcf8fSFrançois Tigeot static int
1804a05eeebfSFrançois Tigeot i830_dispatch_execbuffer(struct drm_i915_gem_request *req,
1805ba55f2f5SFrançois Tigeot 			 u64 offset, u32 len,
1806477eb7f9SFrançois Tigeot 			 unsigned dispatch_flags)
1807e3adcf8fSFrançois Tigeot {
18088621f407SFrançois Tigeot 	struct intel_engine_cs *engine = req->engine;
18098621f407SFrançois Tigeot 	u32 cs_offset = engine->scratch.gtt_offset;
1810e3adcf8fSFrançois Tigeot 	int ret;
1811e3adcf8fSFrançois Tigeot 
1812a05eeebfSFrançois Tigeot 	ret = intel_ring_begin(req, 6);
181324edb884SFrançois Tigeot 	if (ret)
181424edb884SFrançois Tigeot 		return ret;
181524edb884SFrançois Tigeot 
181624edb884SFrançois Tigeot 	/* Evict the invalid PTE TLBs */
18178621f407SFrançois Tigeot 	intel_ring_emit(engine, COLOR_BLT_CMD | BLT_WRITE_RGBA);
18188621f407SFrançois Tigeot 	intel_ring_emit(engine, BLT_DEPTH_32 | BLT_ROP_COLOR_COPY | 4096);
18198621f407SFrançois Tigeot 	intel_ring_emit(engine, I830_TLB_ENTRIES << 16 | 4); /* load each page */
18208621f407SFrançois Tigeot 	intel_ring_emit(engine, cs_offset);
18218621f407SFrançois Tigeot 	intel_ring_emit(engine, 0xdeadbeef);
18228621f407SFrançois Tigeot 	intel_ring_emit(engine, MI_NOOP);
18238621f407SFrançois Tigeot 	intel_ring_advance(engine);
182424edb884SFrançois Tigeot 
1825477eb7f9SFrançois Tigeot 	if ((dispatch_flags & I915_DISPATCH_PINNED) == 0) {
182624edb884SFrançois Tigeot 		if (len > I830_BATCH_LIMIT)
182724edb884SFrançois Tigeot 			return -ENOSPC;
182824edb884SFrançois Tigeot 
1829a05eeebfSFrançois Tigeot 		ret = intel_ring_begin(req, 6 + 2);
183024edb884SFrançois Tigeot 		if (ret)
183124edb884SFrançois Tigeot 			return ret;
183224edb884SFrançois Tigeot 
183324edb884SFrançois Tigeot 		/* Blit the batch (which has now all relocs applied) to the
183424edb884SFrançois Tigeot 		 * stable batch scratch bo area (so that the CS never
183524edb884SFrançois Tigeot 		 * stumbles over its tlb invalidation bug) ...
183624edb884SFrançois Tigeot 		 */
18378621f407SFrançois Tigeot 		intel_ring_emit(engine, SRC_COPY_BLT_CMD | BLT_WRITE_RGBA);
18388621f407SFrançois Tigeot 		intel_ring_emit(engine,
18398621f407SFrançois Tigeot 				BLT_DEPTH_32 | BLT_ROP_SRC_COPY | 4096);
18408621f407SFrançois Tigeot 		intel_ring_emit(engine, DIV_ROUND_UP(len, 4096) << 16 | 4096);
18418621f407SFrançois Tigeot 		intel_ring_emit(engine, cs_offset);
18428621f407SFrançois Tigeot 		intel_ring_emit(engine, 4096);
18438621f407SFrançois Tigeot 		intel_ring_emit(engine, offset);
184424edb884SFrançois Tigeot 
18458621f407SFrançois Tigeot 		intel_ring_emit(engine, MI_FLUSH);
18468621f407SFrançois Tigeot 		intel_ring_emit(engine, MI_NOOP);
18478621f407SFrançois Tigeot 		intel_ring_advance(engine);
184824edb884SFrançois Tigeot 
184924edb884SFrançois Tigeot 		/* ... and execute it. */
185024edb884SFrançois Tigeot 		offset = cs_offset;
185124edb884SFrançois Tigeot 	}
185224edb884SFrançois Tigeot 
1853c0e85e96SFrançois Tigeot 	ret = intel_ring_begin(req, 2);
1854e3adcf8fSFrançois Tigeot 	if (ret)
1855e3adcf8fSFrançois Tigeot 		return ret;
1856e3adcf8fSFrançois Tigeot 
18578621f407SFrançois Tigeot 	intel_ring_emit(engine, MI_BATCH_BUFFER_START | MI_BATCH_GTT);
18588621f407SFrançois Tigeot 	intel_ring_emit(engine, offset | (dispatch_flags & I915_DISPATCH_SECURE ?
1859477eb7f9SFrançois Tigeot 					  0 : MI_BATCH_NON_SECURE));
18608621f407SFrançois Tigeot 	intel_ring_advance(engine);
1861686a02f1SFrançois Tigeot 
1862686a02f1SFrançois Tigeot 	return 0;
1863686a02f1SFrançois Tigeot }
1864686a02f1SFrançois Tigeot 
1865686a02f1SFrançois Tigeot static int
1866a05eeebfSFrançois Tigeot i915_dispatch_execbuffer(struct drm_i915_gem_request *req,
1867ba55f2f5SFrançois Tigeot 			 u64 offset, u32 len,
1868477eb7f9SFrançois Tigeot 			 unsigned dispatch_flags)
1869686a02f1SFrançois Tigeot {
18708621f407SFrançois Tigeot 	struct intel_engine_cs *engine = req->engine;
1871686a02f1SFrançois Tigeot 	int ret;
1872686a02f1SFrançois Tigeot 
1873a05eeebfSFrançois Tigeot 	ret = intel_ring_begin(req, 2);
1874e3adcf8fSFrançois Tigeot 	if (ret)
1875e3adcf8fSFrançois Tigeot 		return ret;
1876e3adcf8fSFrançois Tigeot 
18778621f407SFrançois Tigeot 	intel_ring_emit(engine, MI_BATCH_BUFFER_START | MI_BATCH_GTT);
18788621f407SFrançois Tigeot 	intel_ring_emit(engine, offset | (dispatch_flags & I915_DISPATCH_SECURE ?
1879477eb7f9SFrançois Tigeot 					  0 : MI_BATCH_NON_SECURE));
18808621f407SFrançois Tigeot 	intel_ring_advance(engine);
1881e3adcf8fSFrançois Tigeot 
1882e3adcf8fSFrançois Tigeot 	return 0;
1883e3adcf8fSFrançois Tigeot }
1884e3adcf8fSFrançois Tigeot 
18858621f407SFrançois Tigeot static void cleanup_phys_status_page(struct intel_engine_cs *engine)
1886c0e85e96SFrançois Tigeot {
18871487f786SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
1888c0e85e96SFrançois Tigeot 
1889c0e85e96SFrançois Tigeot 	if (!dev_priv->status_page_dmah)
1890c0e85e96SFrançois Tigeot 		return;
1891c0e85e96SFrançois Tigeot 
1892*303bf270SFrançois Tigeot 	drm_pci_free(&dev_priv->drm, dev_priv->status_page_dmah);
18938621f407SFrançois Tigeot 	engine->status_page.page_addr = NULL;
1894c0e85e96SFrançois Tigeot }
1895c0e85e96SFrançois Tigeot 
18968621f407SFrançois Tigeot static void cleanup_status_page(struct intel_engine_cs *engine)
1897e3adcf8fSFrançois Tigeot {
1898e3adcf8fSFrançois Tigeot 	struct drm_i915_gem_object *obj;
1899e3adcf8fSFrançois Tigeot 
19008621f407SFrançois Tigeot 	obj = engine->status_page.obj;
1901e3adcf8fSFrançois Tigeot 	if (obj == NULL)
1902e3adcf8fSFrançois Tigeot 		return;
1903e3adcf8fSFrançois Tigeot 
19047ec9f8e5SFrançois Tigeot 	kunmap(sg_page(obj->pages->sgl));
1905ba55f2f5SFrançois Tigeot 	i915_gem_object_ggtt_unpin(obj);
1906e3adcf8fSFrançois Tigeot 	drm_gem_object_unreference(&obj->base);
19078621f407SFrançois Tigeot 	engine->status_page.obj = NULL;
1908e3adcf8fSFrançois Tigeot }
1909e3adcf8fSFrançois Tigeot 
19108621f407SFrançois Tigeot static int init_status_page(struct intel_engine_cs *engine)
1911e3adcf8fSFrançois Tigeot {
19128621f407SFrançois Tigeot 	struct drm_i915_gem_object *obj = engine->status_page.obj;
1913ba55f2f5SFrançois Tigeot 
1914c0e85e96SFrançois Tigeot 	if (obj == NULL) {
191524edb884SFrançois Tigeot 		unsigned flags;
1916e3adcf8fSFrançois Tigeot 		int ret;
1917e3adcf8fSFrançois Tigeot 
1918*303bf270SFrançois Tigeot 		obj = i915_gem_object_create(&engine->i915->drm, 4096);
19191487f786SFrançois Tigeot 		if (IS_ERR(obj)) {
1920e3adcf8fSFrançois Tigeot 			DRM_ERROR("Failed to allocate status page\n");
19211487f786SFrançois Tigeot 			return PTR_ERR(obj);
1922e3adcf8fSFrançois Tigeot 		}
1923e3adcf8fSFrançois Tigeot 
1924ba55f2f5SFrançois Tigeot 		ret = i915_gem_object_set_cache_level(obj, I915_CACHE_LLC);
1925ba55f2f5SFrançois Tigeot 		if (ret)
1926e3adcf8fSFrançois Tigeot 			goto err_unref;
1927ba55f2f5SFrançois Tigeot 
192824edb884SFrançois Tigeot 		flags = 0;
19291487f786SFrançois Tigeot 		if (!HAS_LLC(engine->i915))
193024edb884SFrançois Tigeot 			/* On g33, we cannot place HWS above 256MiB, so
193124edb884SFrançois Tigeot 			 * restrict its pinning to the low mappable arena.
193224edb884SFrançois Tigeot 			 * Though this restriction is not documented for
193324edb884SFrançois Tigeot 			 * gen4, gen5, or byt, they also behave similarly
193424edb884SFrançois Tigeot 			 * and hang if the HWS is placed at the top of the
193524edb884SFrançois Tigeot 			 * GTT. To generalise, it appears that all !llc
193624edb884SFrançois Tigeot 			 * platforms have issues with us placing the HWS
193724edb884SFrançois Tigeot 			 * above the mappable region (even though we never
193824edb884SFrançois Tigeot 			 * actualy map it).
193924edb884SFrançois Tigeot 			 */
194024edb884SFrançois Tigeot 			flags |= PIN_MAPPABLE;
194124edb884SFrançois Tigeot 		ret = i915_gem_obj_ggtt_pin(obj, 4096, flags);
1942ba55f2f5SFrançois Tigeot 		if (ret) {
1943ba55f2f5SFrançois Tigeot err_unref:
1944ba55f2f5SFrançois Tigeot 			drm_gem_object_unreference(&obj->base);
1945ba55f2f5SFrançois Tigeot 			return ret;
1946ba55f2f5SFrançois Tigeot 		}
1947ba55f2f5SFrançois Tigeot 
19488621f407SFrançois Tigeot 		engine->status_page.obj = obj;
1949e3adcf8fSFrançois Tigeot 	}
1950e3adcf8fSFrançois Tigeot 
19518621f407SFrançois Tigeot 	engine->status_page.gfx_addr = i915_gem_obj_ggtt_offset(obj);
19528621f407SFrançois Tigeot 	engine->status_page.page_addr = kmap(sg_page(obj->pages->sgl));
19538621f407SFrançois Tigeot 	memset(engine->status_page.page_addr, 0, PAGE_SIZE);
1954e3adcf8fSFrançois Tigeot 
1955b5c29a34SFrançois Tigeot 	DRM_DEBUG_DRIVER("%s hws offset: 0x%08x\n",
19568621f407SFrançois Tigeot 			engine->name, engine->status_page.gfx_addr);
1957e3adcf8fSFrançois Tigeot 
1958e3adcf8fSFrançois Tigeot 	return 0;
1959e3adcf8fSFrançois Tigeot }
1960e3adcf8fSFrançois Tigeot 
19618621f407SFrançois Tigeot static int init_phys_status_page(struct intel_engine_cs *engine)
1962686a02f1SFrançois Tigeot {
19631487f786SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
1964686a02f1SFrançois Tigeot 
1965686a02f1SFrançois Tigeot 	if (!dev_priv->status_page_dmah) {
1966686a02f1SFrançois Tigeot 		dev_priv->status_page_dmah =
1967*303bf270SFrançois Tigeot 			drm_pci_alloc(&dev_priv->drm, PAGE_SIZE, PAGE_SIZE);
1968686a02f1SFrançois Tigeot 		if (!dev_priv->status_page_dmah)
1969686a02f1SFrançois Tigeot 			return -ENOMEM;
1970686a02f1SFrançois Tigeot 	}
1971686a02f1SFrançois Tigeot 
19728621f407SFrançois Tigeot 	engine->status_page.page_addr = dev_priv->status_page_dmah->vaddr;
19738621f407SFrançois Tigeot 	memset(engine->status_page.page_addr, 0, PAGE_SIZE);
1974686a02f1SFrançois Tigeot 
1975686a02f1SFrançois Tigeot 	return 0;
1976686a02f1SFrançois Tigeot }
1977686a02f1SFrançois Tigeot 
19782c9916cdSFrançois Tigeot void intel_unpin_ringbuffer_obj(struct intel_ringbuffer *ringbuf)
19792c9916cdSFrançois Tigeot {
19801487f786SFrançois Tigeot 	GEM_BUG_ON(ringbuf->vma == NULL);
19811487f786SFrançois Tigeot 	GEM_BUG_ON(ringbuf->virtual_start == NULL);
19821487f786SFrançois Tigeot 
1983aee94f86SFrançois Tigeot 	if (HAS_LLC(ringbuf->obj->base.dev) && !ringbuf->obj->stolen)
19848621f407SFrançois Tigeot 		i915_gem_object_unpin_map(ringbuf->obj);
1985aee94f86SFrançois Tigeot 	else
19861487f786SFrançois Tigeot 		i915_vma_unpin_iomap(ringbuf->vma);
19872c9916cdSFrançois Tigeot 	ringbuf->virtual_start = NULL;
19881487f786SFrançois Tigeot 
19892c9916cdSFrançois Tigeot 	i915_gem_object_ggtt_unpin(ringbuf->obj);
19901487f786SFrançois Tigeot 	ringbuf->vma = NULL;
19912c9916cdSFrançois Tigeot }
19922c9916cdSFrançois Tigeot 
19931487f786SFrançois Tigeot int intel_pin_and_map_ringbuffer_obj(struct drm_i915_private *dev_priv,
19942c9916cdSFrançois Tigeot 				     struct intel_ringbuffer *ringbuf)
19952c9916cdSFrançois Tigeot {
19962c9916cdSFrançois Tigeot 	struct drm_i915_gem_object *obj = ringbuf->obj;
1997c0e85e96SFrançois Tigeot 	/* Ring wraparound at offset 0 sometimes hangs. No idea why. */
1998c0e85e96SFrançois Tigeot 	unsigned flags = PIN_OFFSET_BIAS | 4096;
19998621f407SFrançois Tigeot 	void *addr;
20002c9916cdSFrançois Tigeot 	int ret;
20012c9916cdSFrançois Tigeot 
2002aee94f86SFrançois Tigeot 	if (HAS_LLC(dev_priv) && !obj->stolen) {
2003c0e85e96SFrançois Tigeot 		ret = i915_gem_obj_ggtt_pin(obj, PAGE_SIZE, flags);
2004aee94f86SFrançois Tigeot 		if (ret)
2005aee94f86SFrançois Tigeot 			return ret;
2006aee94f86SFrançois Tigeot 
2007aee94f86SFrançois Tigeot 		ret = i915_gem_object_set_to_cpu_domain(obj, true);
20088621f407SFrançois Tigeot 		if (ret)
20098621f407SFrançois Tigeot 			goto err_unpin;
2010aee94f86SFrançois Tigeot 
20118621f407SFrançois Tigeot 		addr = i915_gem_object_pin_map(obj);
20128621f407SFrançois Tigeot 		if (IS_ERR(addr)) {
20138621f407SFrançois Tigeot 			ret = PTR_ERR(addr);
20148621f407SFrançois Tigeot 			goto err_unpin;
2015aee94f86SFrançois Tigeot 		}
2016aee94f86SFrançois Tigeot 	} else {
2017c0e85e96SFrançois Tigeot 		ret = i915_gem_obj_ggtt_pin(obj, PAGE_SIZE,
2018c0e85e96SFrançois Tigeot 					    flags | PIN_MAPPABLE);
20192c9916cdSFrançois Tigeot 		if (ret)
20202c9916cdSFrançois Tigeot 			return ret;
20212c9916cdSFrançois Tigeot 
20222c9916cdSFrançois Tigeot 		ret = i915_gem_object_set_to_gtt_domain(obj, true);
20238621f407SFrançois Tigeot 		if (ret)
20248621f407SFrançois Tigeot 			goto err_unpin;
20252c9916cdSFrançois Tigeot 
2026c0e85e96SFrançois Tigeot 		/* Access through the GTT requires the device to be awake. */
2027c0e85e96SFrançois Tigeot 		assert_rpm_wakelock_held(dev_priv);
2028c0e85e96SFrançois Tigeot 
20291487f786SFrançois Tigeot 		addr = i915_vma_pin_iomap(i915_gem_obj_to_ggtt(obj));
20301487f786SFrançois Tigeot 		if (IS_ERR(addr)) {
20311487f786SFrançois Tigeot 			ret = PTR_ERR(addr);
20328621f407SFrançois Tigeot 			goto err_unpin;
20332c9916cdSFrançois Tigeot 		}
2034aee94f86SFrançois Tigeot 	}
20352c9916cdSFrançois Tigeot 
20368621f407SFrançois Tigeot 	ringbuf->virtual_start = addr;
2037c0e85e96SFrançois Tigeot 	ringbuf->vma = i915_gem_obj_to_ggtt(obj);
20382c9916cdSFrançois Tigeot 	return 0;
20398621f407SFrançois Tigeot 
20408621f407SFrançois Tigeot err_unpin:
20418621f407SFrançois Tigeot 	i915_gem_object_ggtt_unpin(obj);
20428621f407SFrançois Tigeot 	return ret;
20432c9916cdSFrançois Tigeot }
20442c9916cdSFrançois Tigeot 
2045352ff8bdSFrançois Tigeot static void intel_destroy_ringbuffer_obj(struct intel_ringbuffer *ringbuf)
2046e3adcf8fSFrançois Tigeot {
204724edb884SFrançois Tigeot 	drm_gem_object_unreference(&ringbuf->obj->base);
204824edb884SFrançois Tigeot 	ringbuf->obj = NULL;
204924edb884SFrançois Tigeot }
205024edb884SFrançois Tigeot 
2051352ff8bdSFrançois Tigeot static int intel_alloc_ringbuffer_obj(struct drm_device *dev,
205224edb884SFrançois Tigeot 				      struct intel_ringbuffer *ringbuf)
205324edb884SFrançois Tigeot {
2054e3adcf8fSFrançois Tigeot 	struct drm_i915_gem_object *obj;
2055e3adcf8fSFrançois Tigeot 
2056a2fdbec6SFrançois Tigeot 	obj = NULL;
2057a2fdbec6SFrançois Tigeot 	if (!HAS_LLC(dev))
2058ba55f2f5SFrançois Tigeot 		obj = i915_gem_object_create_stolen(dev, ringbuf->size);
2059a2fdbec6SFrançois Tigeot 	if (obj == NULL)
20601487f786SFrançois Tigeot 		obj = i915_gem_object_create(dev, ringbuf->size);
20611487f786SFrançois Tigeot 	if (IS_ERR(obj))
20621487f786SFrançois Tigeot 		return PTR_ERR(obj);
2063e3adcf8fSFrançois Tigeot 
206424edb884SFrançois Tigeot 	/* mark ring buffers as read-only from GPU side by default */
206524edb884SFrançois Tigeot 	obj->gt_ro = 1;
206624edb884SFrançois Tigeot 
2067ba55f2f5SFrançois Tigeot 	ringbuf->obj = obj;
2068ba55f2f5SFrançois Tigeot 
20692c9916cdSFrançois Tigeot 	return 0;
2070ba55f2f5SFrançois Tigeot }
2071ba55f2f5SFrançois Tigeot 
2072352ff8bdSFrançois Tigeot struct intel_ringbuffer *
2073352ff8bdSFrançois Tigeot intel_engine_create_ringbuffer(struct intel_engine_cs *engine, int size)
2074352ff8bdSFrançois Tigeot {
2075352ff8bdSFrançois Tigeot 	struct intel_ringbuffer *ring;
2076352ff8bdSFrançois Tigeot 	int ret;
2077352ff8bdSFrançois Tigeot 
2078352ff8bdSFrançois Tigeot 	ring = kzalloc(sizeof(*ring), GFP_KERNEL);
2079aee94f86SFrançois Tigeot 	if (ring == NULL) {
2080aee94f86SFrançois Tigeot 		DRM_DEBUG_DRIVER("Failed to allocate ringbuffer %s\n",
2081aee94f86SFrançois Tigeot 				 engine->name);
2082352ff8bdSFrançois Tigeot 		return ERR_PTR(-ENOMEM);
2083aee94f86SFrançois Tigeot 	}
2084352ff8bdSFrançois Tigeot 
20858621f407SFrançois Tigeot 	ring->engine = engine;
2086aee94f86SFrançois Tigeot 	list_add(&ring->link, &engine->buffers);
2087352ff8bdSFrançois Tigeot 
2088352ff8bdSFrançois Tigeot 	ring->size = size;
2089352ff8bdSFrançois Tigeot 	/* Workaround an erratum on the i830 which causes a hang if
2090352ff8bdSFrançois Tigeot 	 * the TAIL pointer points to within the last 2 cachelines
2091352ff8bdSFrançois Tigeot 	 * of the buffer.
2092352ff8bdSFrançois Tigeot 	 */
2093352ff8bdSFrançois Tigeot 	ring->effective_size = size;
20941487f786SFrançois Tigeot 	if (IS_I830(engine->i915) || IS_845G(engine->i915))
2095352ff8bdSFrançois Tigeot 		ring->effective_size -= 2 * CACHELINE_BYTES;
2096352ff8bdSFrançois Tigeot 
2097352ff8bdSFrançois Tigeot 	ring->last_retired_head = -1;
2098352ff8bdSFrançois Tigeot 	intel_ring_update_space(ring);
2099352ff8bdSFrançois Tigeot 
2100*303bf270SFrançois Tigeot 	ret = intel_alloc_ringbuffer_obj(&engine->i915->drm, ring);
2101352ff8bdSFrançois Tigeot 	if (ret) {
2102aee94f86SFrançois Tigeot 		DRM_DEBUG_DRIVER("Failed to allocate ringbuffer %s: %d\n",
2103352ff8bdSFrançois Tigeot 				 engine->name, ret);
2104aee94f86SFrançois Tigeot 		list_del(&ring->link);
2105352ff8bdSFrançois Tigeot 		kfree(ring);
2106352ff8bdSFrançois Tigeot 		return ERR_PTR(ret);
2107352ff8bdSFrançois Tigeot 	}
2108352ff8bdSFrançois Tigeot 
2109352ff8bdSFrançois Tigeot 	return ring;
2110352ff8bdSFrançois Tigeot }
2111352ff8bdSFrançois Tigeot 
2112352ff8bdSFrançois Tigeot void
2113352ff8bdSFrançois Tigeot intel_ringbuffer_free(struct intel_ringbuffer *ring)
2114352ff8bdSFrançois Tigeot {
2115352ff8bdSFrançois Tigeot 	intel_destroy_ringbuffer_obj(ring);
2116aee94f86SFrançois Tigeot 	list_del(&ring->link);
2117352ff8bdSFrançois Tigeot 	kfree(ring);
2118352ff8bdSFrançois Tigeot }
2119352ff8bdSFrançois Tigeot 
21201487f786SFrançois Tigeot static int intel_ring_context_pin(struct i915_gem_context *ctx,
21211487f786SFrançois Tigeot 				  struct intel_engine_cs *engine)
21221487f786SFrançois Tigeot {
21231487f786SFrançois Tigeot 	struct intel_context *ce = &ctx->engine[engine->id];
21241487f786SFrançois Tigeot 	int ret;
21251487f786SFrançois Tigeot 
2126*303bf270SFrançois Tigeot 	lockdep_assert_held(&ctx->i915->drm.struct_mutex);
21271487f786SFrançois Tigeot 
21281487f786SFrançois Tigeot 	if (ce->pin_count++)
21291487f786SFrançois Tigeot 		return 0;
21301487f786SFrançois Tigeot 
21311487f786SFrançois Tigeot 	if (ce->state) {
21321487f786SFrançois Tigeot 		ret = i915_gem_obj_ggtt_pin(ce->state, ctx->ggtt_alignment, 0);
21331487f786SFrançois Tigeot 		if (ret)
21341487f786SFrançois Tigeot 			goto error;
21351487f786SFrançois Tigeot 	}
21361487f786SFrançois Tigeot 
21371487f786SFrançois Tigeot 	/* The kernel context is only used as a placeholder for flushing the
21381487f786SFrançois Tigeot 	 * active context. It is never used for submitting user rendering and
21391487f786SFrançois Tigeot 	 * as such never requires the golden render context, and so we can skip
21401487f786SFrançois Tigeot 	 * emitting it when we switch to the kernel context. This is required
21411487f786SFrançois Tigeot 	 * as during eviction we cannot allocate and pin the renderstate in
21421487f786SFrançois Tigeot 	 * order to initialise the context.
21431487f786SFrançois Tigeot 	 */
21441487f786SFrançois Tigeot 	if (ctx == ctx->i915->kernel_context)
21451487f786SFrançois Tigeot 		ce->initialised = true;
21461487f786SFrançois Tigeot 
21471487f786SFrançois Tigeot 	i915_gem_context_reference(ctx);
21481487f786SFrançois Tigeot 	return 0;
21491487f786SFrançois Tigeot 
21501487f786SFrançois Tigeot error:
21511487f786SFrançois Tigeot 	ce->pin_count = 0;
21521487f786SFrançois Tigeot 	return ret;
21531487f786SFrançois Tigeot }
21541487f786SFrançois Tigeot 
21551487f786SFrançois Tigeot static void intel_ring_context_unpin(struct i915_gem_context *ctx,
21561487f786SFrançois Tigeot 				     struct intel_engine_cs *engine)
21571487f786SFrançois Tigeot {
21581487f786SFrançois Tigeot 	struct intel_context *ce = &ctx->engine[engine->id];
21591487f786SFrançois Tigeot 
2160*303bf270SFrançois Tigeot 	lockdep_assert_held(&ctx->i915->drm.struct_mutex);
21611487f786SFrançois Tigeot 
21621487f786SFrançois Tigeot 	if (--ce->pin_count)
21631487f786SFrançois Tigeot 		return;
21641487f786SFrançois Tigeot 
21651487f786SFrançois Tigeot 	if (ce->state)
21661487f786SFrançois Tigeot 		i915_gem_object_ggtt_unpin(ce->state);
21671487f786SFrançois Tigeot 
21681487f786SFrançois Tigeot 	i915_gem_context_unreference(ctx);
21691487f786SFrançois Tigeot }
21701487f786SFrançois Tigeot 
2171ba55f2f5SFrançois Tigeot static int intel_init_ring_buffer(struct drm_device *dev,
21728621f407SFrançois Tigeot 				  struct intel_engine_cs *engine)
2173ba55f2f5SFrançois Tigeot {
21741487f786SFrançois Tigeot 	struct drm_i915_private *dev_priv = to_i915(dev);
21752c9916cdSFrançois Tigeot 	struct intel_ringbuffer *ringbuf;
2176ba55f2f5SFrançois Tigeot 	int ret;
2177ba55f2f5SFrançois Tigeot 
21788621f407SFrançois Tigeot 	WARN_ON(engine->buffer);
21792c9916cdSFrançois Tigeot 
21801487f786SFrançois Tigeot 	engine->i915 = dev_priv;
21818621f407SFrançois Tigeot 	INIT_LIST_HEAD(&engine->active_list);
21828621f407SFrançois Tigeot 	INIT_LIST_HEAD(&engine->request_list);
21838621f407SFrançois Tigeot 	INIT_LIST_HEAD(&engine->execlist_queue);
21848621f407SFrançois Tigeot 	INIT_LIST_HEAD(&engine->buffers);
21858621f407SFrançois Tigeot 	i915_gem_batch_pool_init(dev, &engine->batch_pool);
21868621f407SFrançois Tigeot 	memset(engine->semaphore.sync_seqno, 0,
21878621f407SFrançois Tigeot 	       sizeof(engine->semaphore.sync_seqno));
2188ba55f2f5SFrançois Tigeot 
2189*303bf270SFrançois Tigeot 	ret = intel_engine_init_breadcrumbs(engine);
2190*303bf270SFrançois Tigeot 	if (ret)
2191*303bf270SFrançois Tigeot 		goto error;
2192ba55f2f5SFrançois Tigeot 
21931487f786SFrançois Tigeot 	/* We may need to do things with the shrinker which
21941487f786SFrançois Tigeot 	 * require us to immediately switch back to the default
21951487f786SFrançois Tigeot 	 * context. This can cause a problem as pinning the
21961487f786SFrançois Tigeot 	 * default context also requires GTT space which may not
21971487f786SFrançois Tigeot 	 * be available. To avoid this we always pin the default
21981487f786SFrançois Tigeot 	 * context.
21991487f786SFrançois Tigeot 	 */
22001487f786SFrançois Tigeot 	ret = intel_ring_context_pin(dev_priv->kernel_context, engine);
22011487f786SFrançois Tigeot 	if (ret)
22021487f786SFrançois Tigeot 		goto error;
22031487f786SFrançois Tigeot 
22048621f407SFrançois Tigeot 	ringbuf = intel_engine_create_ringbuffer(engine, 32 * PAGE_SIZE);
2205aee94f86SFrançois Tigeot 	if (IS_ERR(ringbuf)) {
2206aee94f86SFrançois Tigeot 		ret = PTR_ERR(ringbuf);
2207aee94f86SFrançois Tigeot 		goto error;
2208aee94f86SFrançois Tigeot 	}
22098621f407SFrançois Tigeot 	engine->buffer = ringbuf;
2210352ff8bdSFrançois Tigeot 
22111487f786SFrançois Tigeot 	if (I915_NEED_GFX_HWS(dev_priv)) {
22128621f407SFrançois Tigeot 		ret = init_status_page(engine);
2213e3adcf8fSFrançois Tigeot 		if (ret)
2214ba55f2f5SFrançois Tigeot 			goto error;
2215ba55f2f5SFrançois Tigeot 	} else {
22168621f407SFrançois Tigeot 		WARN_ON(engine->id != RCS);
22178621f407SFrançois Tigeot 		ret = init_phys_status_page(engine);
2218ba55f2f5SFrançois Tigeot 		if (ret)
2219ba55f2f5SFrançois Tigeot 			goto error;
2220ba55f2f5SFrançois Tigeot 	}
2221ba55f2f5SFrançois Tigeot 
22221487f786SFrançois Tigeot 	ret = intel_pin_and_map_ringbuffer_obj(dev_priv, ringbuf);
22232c9916cdSFrançois Tigeot 	if (ret) {
22242c9916cdSFrançois Tigeot 		DRM_ERROR("Failed to pin and map ringbuffer %s: %d\n",
22258621f407SFrançois Tigeot 				engine->name, ret);
22262c9916cdSFrançois Tigeot 		intel_destroy_ringbuffer_obj(ringbuf);
2227ba55f2f5SFrançois Tigeot 		goto error;
2228ba55f2f5SFrançois Tigeot 	}
2229e3adcf8fSFrançois Tigeot 
22308621f407SFrançois Tigeot 	ret = i915_cmd_parser_init_ring(engine);
2231ba55f2f5SFrançois Tigeot 	if (ret)
2232ba55f2f5SFrançois Tigeot 		goto error;
2233ba55f2f5SFrançois Tigeot 
2234e3adcf8fSFrançois Tigeot 	return 0;
2235e3adcf8fSFrançois Tigeot 
2236ba55f2f5SFrançois Tigeot error:
22378621f407SFrançois Tigeot 	intel_cleanup_engine(engine);
2238e3adcf8fSFrançois Tigeot 	return ret;
2239e3adcf8fSFrançois Tigeot }
2240e3adcf8fSFrançois Tigeot 
22418621f407SFrançois Tigeot void intel_cleanup_engine(struct intel_engine_cs *engine)
2242e3adcf8fSFrançois Tigeot {
22432c9916cdSFrançois Tigeot 	struct drm_i915_private *dev_priv;
2244e3adcf8fSFrançois Tigeot 
22458621f407SFrançois Tigeot 	if (!intel_engine_initialized(engine))
2246e3adcf8fSFrançois Tigeot 		return;
2247e3adcf8fSFrançois Tigeot 
22481487f786SFrançois Tigeot 	dev_priv = engine->i915;
22492c9916cdSFrançois Tigeot 
22508621f407SFrançois Tigeot 	if (engine->buffer) {
22518621f407SFrançois Tigeot 		intel_stop_engine(engine);
22521487f786SFrançois Tigeot 		WARN_ON(!IS_GEN2(dev_priv) && (I915_READ_MODE(engine) & MODE_IDLE) == 0);
2253b030f26bSFrançois Tigeot 
22548621f407SFrançois Tigeot 		intel_unpin_ringbuffer_obj(engine->buffer);
22558621f407SFrançois Tigeot 		intel_ringbuffer_free(engine->buffer);
22568621f407SFrançois Tigeot 		engine->buffer = NULL;
2257aee94f86SFrançois Tigeot 	}
2258e3adcf8fSFrançois Tigeot 
22598621f407SFrançois Tigeot 	if (engine->cleanup)
22608621f407SFrançois Tigeot 		engine->cleanup(engine);
2261e3adcf8fSFrançois Tigeot 
22621487f786SFrançois Tigeot 	if (I915_NEED_GFX_HWS(dev_priv)) {
22638621f407SFrançois Tigeot 		cleanup_status_page(engine);
2264c0e85e96SFrançois Tigeot 	} else {
22658621f407SFrançois Tigeot 		WARN_ON(engine->id != RCS);
22668621f407SFrançois Tigeot 		cleanup_phys_status_page(engine);
2267c0e85e96SFrançois Tigeot 	}
2268ba55f2f5SFrançois Tigeot 
22698621f407SFrançois Tigeot 	i915_cmd_parser_fini_ring(engine);
22708621f407SFrançois Tigeot 	i915_gem_batch_pool_fini(&engine->batch_pool);
2271*303bf270SFrançois Tigeot 	intel_engine_fini_breadcrumbs(engine);
22721487f786SFrançois Tigeot 
22731487f786SFrançois Tigeot 	intel_ring_context_unpin(dev_priv->kernel_context, engine);
22741487f786SFrançois Tigeot 
22751487f786SFrançois Tigeot 	engine->i915 = NULL;
2276e3adcf8fSFrançois Tigeot }
2277e3adcf8fSFrançois Tigeot 
22788621f407SFrançois Tigeot int intel_engine_idle(struct intel_engine_cs *engine)
2279b030f26bSFrançois Tigeot {
22802c9916cdSFrançois Tigeot 	struct drm_i915_gem_request *req;
2281b5c29a34SFrançois Tigeot 
2282b5c29a34SFrançois Tigeot 	/* Wait upon the last request to be completed */
22838621f407SFrançois Tigeot 	if (list_empty(&engine->request_list))
2284b5c29a34SFrançois Tigeot 		return 0;
2285b5c29a34SFrançois Tigeot 
22868621f407SFrançois Tigeot 	req = list_entry(engine->request_list.prev,
2287b5c29a34SFrançois Tigeot 			 struct drm_i915_gem_request,
22882c9916cdSFrançois Tigeot 			 list);
2289b5c29a34SFrançois Tigeot 
229019c468b4SFrançois Tigeot 	/* Make sure we do not trigger any retires */
229119c468b4SFrançois Tigeot 	return __i915_wait_request(req,
22928621f407SFrançois Tigeot 				   req->i915->mm.interruptible,
229319c468b4SFrançois Tigeot 				   NULL, NULL);
2294b5c29a34SFrançois Tigeot }
2295b5c29a34SFrançois Tigeot 
229619c468b4SFrançois Tigeot int intel_ring_alloc_request_extras(struct drm_i915_gem_request *request)
2297b5c29a34SFrançois Tigeot {
22981487f786SFrançois Tigeot 	int ret;
22999edbd4a0SFrançois Tigeot 
23001487f786SFrançois Tigeot 	/* Flush enough space to reduce the likelihood of waiting after
23011487f786SFrançois Tigeot 	 * we start building the request - in which case we will just
23021487f786SFrançois Tigeot 	 * have to repeat work.
2303a05eeebfSFrançois Tigeot 	 */
23041487f786SFrançois Tigeot 	request->reserved_space += LEGACY_REQUEST_SIZE;
2305a2fdbec6SFrançois Tigeot 
23061487f786SFrançois Tigeot 	request->ringbuf = request->engine->buffer;
2307a2fdbec6SFrançois Tigeot 
23081487f786SFrançois Tigeot 	ret = intel_ring_begin(request, 0);
23091487f786SFrançois Tigeot 	if (ret)
23101487f786SFrançois Tigeot 		return ret;
2311a05eeebfSFrançois Tigeot 
23121487f786SFrançois Tigeot 	request->reserved_space -= LEGACY_REQUEST_SIZE;
23131487f786SFrançois Tigeot 	return 0;
2314a05eeebfSFrançois Tigeot }
2315a05eeebfSFrançois Tigeot 
23168621f407SFrançois Tigeot static int wait_for_space(struct drm_i915_gem_request *req, int bytes)
2317a05eeebfSFrançois Tigeot {
23188621f407SFrançois Tigeot 	struct intel_ringbuffer *ringbuf = req->ringbuf;
23198621f407SFrançois Tigeot 	struct intel_engine_cs *engine = req->engine;
23208621f407SFrançois Tigeot 	struct drm_i915_gem_request *target;
23218621f407SFrançois Tigeot 
23228621f407SFrançois Tigeot 	intel_ring_update_space(ringbuf);
23238621f407SFrançois Tigeot 	if (ringbuf->space >= bytes)
23248621f407SFrançois Tigeot 		return 0;
23258621f407SFrançois Tigeot 
23268621f407SFrançois Tigeot 	/*
23278621f407SFrançois Tigeot 	 * Space is reserved in the ringbuffer for finalising the request,
23288621f407SFrançois Tigeot 	 * as that cannot be allowed to fail. During request finalisation,
23298621f407SFrançois Tigeot 	 * reserved_space is set to 0 to stop the overallocation and the
23308621f407SFrançois Tigeot 	 * assumption is that then we never need to wait (which has the
23318621f407SFrançois Tigeot 	 * risk of failing with EINTR).
23328621f407SFrançois Tigeot 	 *
23338621f407SFrançois Tigeot 	 * See also i915_gem_request_alloc() and i915_add_request().
23348621f407SFrançois Tigeot 	 */
23351487f786SFrançois Tigeot 	GEM_BUG_ON(!req->reserved_space);
23368621f407SFrançois Tigeot 
23378621f407SFrançois Tigeot 	list_for_each_entry(target, &engine->request_list, list) {
23388621f407SFrançois Tigeot 		unsigned space;
23398621f407SFrançois Tigeot 
23408621f407SFrançois Tigeot 		/*
23418621f407SFrançois Tigeot 		 * The request queue is per-engine, so can contain requests
23428621f407SFrançois Tigeot 		 * from multiple ringbuffers. Here, we must ignore any that
23438621f407SFrançois Tigeot 		 * aren't from the ringbuffer we're considering.
23448621f407SFrançois Tigeot 		 */
23458621f407SFrançois Tigeot 		if (target->ringbuf != ringbuf)
23468621f407SFrançois Tigeot 			continue;
23478621f407SFrançois Tigeot 
23488621f407SFrançois Tigeot 		/* Would completion of this request free enough space? */
23498621f407SFrançois Tigeot 		space = __intel_ring_space(target->postfix, ringbuf->tail,
23508621f407SFrançois Tigeot 					   ringbuf->size);
23518621f407SFrançois Tigeot 		if (space >= bytes)
23528621f407SFrançois Tigeot 			break;
23538621f407SFrançois Tigeot 	}
23548621f407SFrançois Tigeot 
23558621f407SFrançois Tigeot 	if (WARN_ON(&target->list == &engine->request_list))
23568621f407SFrançois Tigeot 		return -ENOSPC;
23578621f407SFrançois Tigeot 
23588621f407SFrançois Tigeot 	return i915_wait_request(target);
23598621f407SFrançois Tigeot }
23608621f407SFrançois Tigeot 
23618621f407SFrançois Tigeot int intel_ring_begin(struct drm_i915_gem_request *req, int num_dwords)
23628621f407SFrançois Tigeot {
23638621f407SFrançois Tigeot 	struct intel_ringbuffer *ringbuf = req->ringbuf;
2364a05eeebfSFrançois Tigeot 	int remain_actual = ringbuf->size - ringbuf->tail;
23658621f407SFrançois Tigeot 	int remain_usable = ringbuf->effective_size - ringbuf->tail;
23668621f407SFrançois Tigeot 	int bytes = num_dwords * sizeof(u32);
23678621f407SFrançois Tigeot 	int total_bytes, wait_bytes;
2368a05eeebfSFrançois Tigeot 	bool need_wrap = false;
2369a05eeebfSFrançois Tigeot 
23701487f786SFrançois Tigeot 	total_bytes = bytes + req->reserved_space;
2371a05eeebfSFrançois Tigeot 
2372a05eeebfSFrançois Tigeot 	if (unlikely(bytes > remain_usable)) {
2373a05eeebfSFrançois Tigeot 		/*
2374a05eeebfSFrançois Tigeot 		 * Not enough space for the basic request. So need to flush
2375a05eeebfSFrançois Tigeot 		 * out the remainder and then wait for base + reserved.
2376a05eeebfSFrançois Tigeot 		 */
2377a05eeebfSFrançois Tigeot 		wait_bytes = remain_actual + total_bytes;
2378a05eeebfSFrançois Tigeot 		need_wrap = true;
23798621f407SFrançois Tigeot 	} else if (unlikely(total_bytes > remain_usable)) {
2380a05eeebfSFrançois Tigeot 		/*
2381a05eeebfSFrançois Tigeot 		 * The base request will fit but the reserved space
23828621f407SFrançois Tigeot 		 * falls off the end. So we don't need an immediate wrap
2383c0e85e96SFrançois Tigeot 		 * and only need to effectively wait for the reserved
2384c0e85e96SFrançois Tigeot 		 * size space from the start of ringbuffer.
2385a05eeebfSFrançois Tigeot 		 */
23861487f786SFrançois Tigeot 		wait_bytes = remain_actual + req->reserved_space;
23878621f407SFrançois Tigeot 	} else {
2388a05eeebfSFrançois Tigeot 		/* No wrapping required, just waiting. */
2389a05eeebfSFrançois Tigeot 		wait_bytes = total_bytes;
2390a05eeebfSFrançois Tigeot 	}
2391a05eeebfSFrançois Tigeot 
23928621f407SFrançois Tigeot 	if (wait_bytes > ringbuf->space) {
23938621f407SFrançois Tigeot 		int ret = wait_for_space(req, wait_bytes);
2394a2fdbec6SFrançois Tigeot 		if (unlikely(ret))
2395a2fdbec6SFrançois Tigeot 			return ret;
2396a05eeebfSFrançois Tigeot 
23978621f407SFrançois Tigeot 		intel_ring_update_space(ringbuf);
23988621f407SFrançois Tigeot 		if (unlikely(ringbuf->space < wait_bytes))
23998621f407SFrançois Tigeot 			return -EAGAIN;
2400a2fdbec6SFrançois Tigeot 	}
2401a2fdbec6SFrançois Tigeot 
24028621f407SFrançois Tigeot 	if (unlikely(need_wrap)) {
24038621f407SFrançois Tigeot 		GEM_BUG_ON(remain_actual > ringbuf->space);
24048621f407SFrançois Tigeot 		GEM_BUG_ON(ringbuf->tail + remain_actual > ringbuf->size);
24058621f407SFrançois Tigeot 
24068621f407SFrançois Tigeot 		/* Fill the tail with MI_NOOP */
24078621f407SFrançois Tigeot 		memset(ringbuf->virtual_start + ringbuf->tail,
24088621f407SFrançois Tigeot 		       0, remain_actual);
24098621f407SFrançois Tigeot 		ringbuf->tail = 0;
24108621f407SFrançois Tigeot 		ringbuf->space -= remain_actual;
2411a2fdbec6SFrançois Tigeot 	}
2412a2fdbec6SFrançois Tigeot 
24138621f407SFrançois Tigeot 	ringbuf->space -= bytes;
24148621f407SFrançois Tigeot 	GEM_BUG_ON(ringbuf->space < 0);
24159edbd4a0SFrançois Tigeot 	return 0;
24169edbd4a0SFrançois Tigeot }
24179edbd4a0SFrançois Tigeot 
24189edbd4a0SFrançois Tigeot /* Align the ring tail to a cacheline boundary */
2419a05eeebfSFrançois Tigeot int intel_ring_cacheline_align(struct drm_i915_gem_request *req)
24209edbd4a0SFrançois Tigeot {
24218621f407SFrançois Tigeot 	struct intel_engine_cs *engine = req->engine;
24228621f407SFrançois Tigeot 	int num_dwords = (engine->buffer->tail & (CACHELINE_BYTES - 1)) / sizeof(uint32_t);
24239edbd4a0SFrançois Tigeot 	int ret;
24249edbd4a0SFrançois Tigeot 
24259edbd4a0SFrançois Tigeot 	if (num_dwords == 0)
24269edbd4a0SFrançois Tigeot 		return 0;
24279edbd4a0SFrançois Tigeot 
2428ba55f2f5SFrançois Tigeot 	num_dwords = CACHELINE_BYTES / sizeof(uint32_t) - num_dwords;
2429a05eeebfSFrançois Tigeot 	ret = intel_ring_begin(req, num_dwords);
24309edbd4a0SFrançois Tigeot 	if (ret)
24319edbd4a0SFrançois Tigeot 		return ret;
24329edbd4a0SFrançois Tigeot 
24339edbd4a0SFrançois Tigeot 	while (num_dwords--)
24348621f407SFrançois Tigeot 		intel_ring_emit(engine, MI_NOOP);
24359edbd4a0SFrançois Tigeot 
24368621f407SFrançois Tigeot 	intel_ring_advance(engine);
24379edbd4a0SFrançois Tigeot 
24389edbd4a0SFrançois Tigeot 	return 0;
2439e3adcf8fSFrançois Tigeot }
2440e3adcf8fSFrançois Tigeot 
24418621f407SFrançois Tigeot void intel_ring_init_seqno(struct intel_engine_cs *engine, u32 seqno)
2442a2fdbec6SFrançois Tigeot {
24431487f786SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
2444a2fdbec6SFrançois Tigeot 
24458621f407SFrançois Tigeot 	/* Our semaphore implementation is strictly monotonic (i.e. we proceed
24468621f407SFrançois Tigeot 	 * so long as the semaphore value in the register/page is greater
24478621f407SFrançois Tigeot 	 * than the sync value), so whenever we reset the seqno,
24488621f407SFrançois Tigeot 	 * so long as we reset the tracking semaphore value to 0, it will
24498621f407SFrançois Tigeot 	 * always be before the next request's seqno. If we don't reset
24508621f407SFrançois Tigeot 	 * the semaphore value, then when the seqno moves backwards all
24518621f407SFrançois Tigeot 	 * future waits will complete instantly (causing rendering corruption).
24528621f407SFrançois Tigeot 	 */
24531487f786SFrançois Tigeot 	if (IS_GEN6(dev_priv) || IS_GEN7(dev_priv)) {
24548621f407SFrançois Tigeot 		I915_WRITE(RING_SYNC_0(engine->mmio_base), 0);
24558621f407SFrançois Tigeot 		I915_WRITE(RING_SYNC_1(engine->mmio_base), 0);
24568621f407SFrançois Tigeot 		if (HAS_VEBOX(dev_priv))
24578621f407SFrançois Tigeot 			I915_WRITE(RING_SYNC_2(engine->mmio_base), 0);
24588621f407SFrançois Tigeot 	}
24598621f407SFrançois Tigeot 	if (dev_priv->semaphore_obj) {
24608621f407SFrançois Tigeot 		struct drm_i915_gem_object *obj = dev_priv->semaphore_obj;
2461f0bba3d1SFrançois Tigeot 		struct page *page = i915_gem_object_get_dirty_page(obj, 0);
24621487f786SFrançois Tigeot 		void *semaphores = kmap(page);
24638621f407SFrançois Tigeot 		memset(semaphores + GEN8_SEMAPHORE_OFFSET(engine->id, 0),
24648621f407SFrançois Tigeot 		       0, I915_NUM_ENGINES * gen8_semaphore_seqno_size);
24658621f407SFrançois Tigeot 		kunmap(page);
24668621f407SFrançois Tigeot 	}
24678621f407SFrançois Tigeot 	memset(engine->semaphore.sync_seqno, 0,
24688621f407SFrançois Tigeot 	       sizeof(engine->semaphore.sync_seqno));
24698621f407SFrançois Tigeot 
2470*303bf270SFrançois Tigeot 	intel_write_status_page(engine, I915_GEM_HWS_INDEX, seqno);
2471*303bf270SFrançois Tigeot 	if (engine->irq_seqno_barrier)
2472*303bf270SFrançois Tigeot 		engine->irq_seqno_barrier(engine);
24738621f407SFrançois Tigeot 	engine->last_submitted_seqno = seqno;
24748621f407SFrançois Tigeot 
24758621f407SFrançois Tigeot 	engine->hangcheck.seqno = seqno;
2476*303bf270SFrançois Tigeot 
2477*303bf270SFrançois Tigeot 	/* After manually advancing the seqno, fake the interrupt in case
2478*303bf270SFrançois Tigeot 	 * there are any waiters for that seqno.
2479*303bf270SFrançois Tigeot 	 */
2480*303bf270SFrançois Tigeot 	rcu_read_lock();
2481*303bf270SFrançois Tigeot 	intel_engine_wakeup(engine);
2482*303bf270SFrançois Tigeot 	rcu_read_unlock();
2483e3adcf8fSFrançois Tigeot }
2484e3adcf8fSFrançois Tigeot 
24858621f407SFrançois Tigeot static void gen6_bsd_ring_write_tail(struct intel_engine_cs *engine,
2486f4e1c372SFrançois Tigeot 				     u32 value)
2487e3adcf8fSFrançois Tigeot {
24881487f786SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
24891487f786SFrançois Tigeot 
24901487f786SFrançois Tigeot 	intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL);
2491e3adcf8fSFrançois Tigeot 
2492e3adcf8fSFrançois Tigeot        /* Every tail move must follow the sequence below */
2493f4e1c372SFrançois Tigeot 
2494f4e1c372SFrançois Tigeot 	/* Disable notification that the ring is IDLE. The GT
2495f4e1c372SFrançois Tigeot 	 * will then assume that it is busy and bring it out of rc6.
2496f4e1c372SFrançois Tigeot 	 */
24971487f786SFrançois Tigeot 	I915_WRITE_FW(GEN6_BSD_SLEEP_PSMI_CONTROL,
2498f4e1c372SFrançois Tigeot 		      _MASKED_BIT_ENABLE(GEN6_BSD_SLEEP_MSG_DISABLE));
2499e3adcf8fSFrançois Tigeot 
2500f4e1c372SFrançois Tigeot 	/* Clear the context id. Here be magic! */
25011487f786SFrançois Tigeot 	I915_WRITE64_FW(GEN6_BSD_RNCID, 0x0);
2502e3adcf8fSFrançois Tigeot 
2503f4e1c372SFrançois Tigeot 	/* Wait for the ring not to be idle, i.e. for it to wake up. */
25041487f786SFrançois Tigeot 	if (intel_wait_for_register_fw(dev_priv,
25051487f786SFrançois Tigeot 				       GEN6_BSD_SLEEP_PSMI_CONTROL,
25061487f786SFrançois Tigeot 				       GEN6_BSD_SLEEP_INDICATOR,
25071487f786SFrançois Tigeot 				       0,
2508f4e1c372SFrançois Tigeot 				       50))
2509f4e1c372SFrançois Tigeot 		DRM_ERROR("timed out waiting for the BSD ring to wake up\n");
2510f4e1c372SFrançois Tigeot 
2511f4e1c372SFrançois Tigeot 	/* Now that the ring is fully powered up, update the tail */
25121487f786SFrançois Tigeot 	I915_WRITE_FW(RING_TAIL(engine->mmio_base), value);
25131487f786SFrançois Tigeot 	POSTING_READ_FW(RING_TAIL(engine->mmio_base));
2514f4e1c372SFrançois Tigeot 
2515f4e1c372SFrançois Tigeot 	/* Let the ring send IDLE messages to the GT again,
2516f4e1c372SFrançois Tigeot 	 * and so let it sleep to conserve power when idle.
2517f4e1c372SFrançois Tigeot 	 */
25181487f786SFrançois Tigeot 	I915_WRITE_FW(GEN6_BSD_SLEEP_PSMI_CONTROL,
2519f4e1c372SFrançois Tigeot 		      _MASKED_BIT_DISABLE(GEN6_BSD_SLEEP_MSG_DISABLE));
25201487f786SFrançois Tigeot 
25211487f786SFrançois Tigeot 	intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL);
2522e3adcf8fSFrançois Tigeot }
2523e3adcf8fSFrançois Tigeot 
2524a05eeebfSFrançois Tigeot static int gen6_bsd_ring_flush(struct drm_i915_gem_request *req,
2525b5c29a34SFrançois Tigeot 			       u32 invalidate, u32 flush)
2526e3adcf8fSFrançois Tigeot {
25278621f407SFrançois Tigeot 	struct intel_engine_cs *engine = req->engine;
2528e3adcf8fSFrançois Tigeot 	uint32_t cmd;
2529e3adcf8fSFrançois Tigeot 	int ret;
2530e3adcf8fSFrançois Tigeot 
2531a05eeebfSFrançois Tigeot 	ret = intel_ring_begin(req, 4);
2532e3adcf8fSFrançois Tigeot 	if (ret)
2533e3adcf8fSFrançois Tigeot 		return ret;
2534e3adcf8fSFrançois Tigeot 
2535e3adcf8fSFrançois Tigeot 	cmd = MI_FLUSH_DW;
25361487f786SFrançois Tigeot 	if (INTEL_GEN(req->i915) >= 8)
25379edbd4a0SFrançois Tigeot 		cmd += 1;
25382c9916cdSFrançois Tigeot 
25392c9916cdSFrançois Tigeot 	/* We always require a command barrier so that subsequent
25402c9916cdSFrançois Tigeot 	 * commands, such as breadcrumb interrupts, are strictly ordered
25412c9916cdSFrançois Tigeot 	 * wrt the contents of the write cache being flushed to memory
25422c9916cdSFrançois Tigeot 	 * (and thus being coherent from the CPU).
25432c9916cdSFrançois Tigeot 	 */
25442c9916cdSFrançois Tigeot 	cmd |= MI_FLUSH_DW_STORE_INDEX | MI_FLUSH_DW_OP_STOREDW;
25452c9916cdSFrançois Tigeot 
2546b5c29a34SFrançois Tigeot 	/*
2547b5c29a34SFrançois Tigeot 	 * Bspec vol 1c.5 - video engine command streamer:
2548b5c29a34SFrançois Tigeot 	 * "If ENABLED, all TLBs will be invalidated once the flush
2549b5c29a34SFrançois Tigeot 	 * operation is complete. This bit is only valid when the
2550b5c29a34SFrançois Tigeot 	 * Post-Sync Operation field is a value of 1h or 3h."
2551b5c29a34SFrançois Tigeot 	 */
2552e3adcf8fSFrançois Tigeot 	if (invalidate & I915_GEM_GPU_DOMAINS)
25532c9916cdSFrançois Tigeot 		cmd |= MI_INVALIDATE_TLB | MI_INVALIDATE_BSD;
25542c9916cdSFrançois Tigeot 
25558621f407SFrançois Tigeot 	intel_ring_emit(engine, cmd);
25568621f407SFrançois Tigeot 	intel_ring_emit(engine,
25578621f407SFrançois Tigeot 			I915_GEM_HWS_SCRATCH_ADDR | MI_FLUSH_DW_USE_GTT);
25581487f786SFrançois Tigeot 	if (INTEL_GEN(req->i915) >= 8) {
25598621f407SFrançois Tigeot 		intel_ring_emit(engine, 0); /* upper addr */
25608621f407SFrançois Tigeot 		intel_ring_emit(engine, 0); /* value */
25619edbd4a0SFrançois Tigeot 	} else  {
25628621f407SFrançois Tigeot 		intel_ring_emit(engine, 0);
25638621f407SFrançois Tigeot 		intel_ring_emit(engine, MI_NOOP);
25649edbd4a0SFrançois Tigeot 	}
25658621f407SFrançois Tigeot 	intel_ring_advance(engine);
25669edbd4a0SFrançois Tigeot 	return 0;
25679edbd4a0SFrançois Tigeot }
25689edbd4a0SFrançois Tigeot 
25699edbd4a0SFrançois Tigeot static int
2570a05eeebfSFrançois Tigeot gen8_ring_dispatch_execbuffer(struct drm_i915_gem_request *req,
2571ba55f2f5SFrançois Tigeot 			      u64 offset, u32 len,
2572477eb7f9SFrançois Tigeot 			      unsigned dispatch_flags)
25739edbd4a0SFrançois Tigeot {
25748621f407SFrançois Tigeot 	struct intel_engine_cs *engine = req->engine;
25758621f407SFrançois Tigeot 	bool ppgtt = USES_PPGTT(engine->dev) &&
2576477eb7f9SFrançois Tigeot 			!(dispatch_flags & I915_DISPATCH_SECURE);
25779edbd4a0SFrançois Tigeot 	int ret;
25789edbd4a0SFrançois Tigeot 
2579a05eeebfSFrançois Tigeot 	ret = intel_ring_begin(req, 4);
25809edbd4a0SFrançois Tigeot 	if (ret)
25819edbd4a0SFrançois Tigeot 		return ret;
25829edbd4a0SFrançois Tigeot 
25839edbd4a0SFrançois Tigeot 	/* FIXME(BDW): Address space and security selectors. */
25848621f407SFrançois Tigeot 	intel_ring_emit(engine, MI_BATCH_BUFFER_START_GEN8 | (ppgtt<<8) |
2585a05eeebfSFrançois Tigeot 			(dispatch_flags & I915_DISPATCH_RS ?
2586a05eeebfSFrançois Tigeot 			 MI_BATCH_RESOURCE_STREAMER : 0));
25878621f407SFrançois Tigeot 	intel_ring_emit(engine, lower_32_bits(offset));
25888621f407SFrançois Tigeot 	intel_ring_emit(engine, upper_32_bits(offset));
25898621f407SFrançois Tigeot 	intel_ring_emit(engine, MI_NOOP);
25908621f407SFrançois Tigeot 	intel_ring_advance(engine);
25919edbd4a0SFrançois Tigeot 
2592e3adcf8fSFrançois Tigeot 	return 0;
2593e3adcf8fSFrançois Tigeot }
2594e3adcf8fSFrançois Tigeot 
2595e3adcf8fSFrançois Tigeot static int
2596a05eeebfSFrançois Tigeot hsw_ring_dispatch_execbuffer(struct drm_i915_gem_request *req,
2597ba55f2f5SFrançois Tigeot 			     u64 offset, u32 len,
2598477eb7f9SFrançois Tigeot 			     unsigned dispatch_flags)
2599e3adcf8fSFrançois Tigeot {
26008621f407SFrançois Tigeot 	struct intel_engine_cs *engine = req->engine;
2601e3adcf8fSFrançois Tigeot 	int ret;
2602e3adcf8fSFrançois Tigeot 
2603a05eeebfSFrançois Tigeot 	ret = intel_ring_begin(req, 2);
2604e3adcf8fSFrançois Tigeot 	if (ret)
2605e3adcf8fSFrançois Tigeot 		return ret;
2606e3adcf8fSFrançois Tigeot 
26078621f407SFrançois Tigeot 	intel_ring_emit(engine,
26081b13d190SFrançois Tigeot 			MI_BATCH_BUFFER_START |
2609477eb7f9SFrançois Tigeot 			(dispatch_flags & I915_DISPATCH_SECURE ?
2610a05eeebfSFrançois Tigeot 			 0 : MI_BATCH_PPGTT_HSW | MI_BATCH_NON_SECURE_HSW) |
2611a05eeebfSFrançois Tigeot 			(dispatch_flags & I915_DISPATCH_RS ?
2612a05eeebfSFrançois Tigeot 			 MI_BATCH_RESOURCE_STREAMER : 0));
2613b5c29a34SFrançois Tigeot 	/* bit0-7 is the length on GEN6+ */
26148621f407SFrançois Tigeot 	intel_ring_emit(engine, offset);
26158621f407SFrançois Tigeot 	intel_ring_advance(engine);
2616b5c29a34SFrançois Tigeot 
2617b5c29a34SFrançois Tigeot 	return 0;
2618b5c29a34SFrançois Tigeot }
2619b5c29a34SFrançois Tigeot 
2620b5c29a34SFrançois Tigeot static int
2621a05eeebfSFrançois Tigeot gen6_ring_dispatch_execbuffer(struct drm_i915_gem_request *req,
2622ba55f2f5SFrançois Tigeot 			      u64 offset, u32 len,
2623477eb7f9SFrançois Tigeot 			      unsigned dispatch_flags)
2624b5c29a34SFrançois Tigeot {
26258621f407SFrançois Tigeot 	struct intel_engine_cs *engine = req->engine;
2626b5c29a34SFrançois Tigeot 	int ret;
2627b5c29a34SFrançois Tigeot 
2628a05eeebfSFrançois Tigeot 	ret = intel_ring_begin(req, 2);
2629b5c29a34SFrançois Tigeot 	if (ret)
2630b5c29a34SFrançois Tigeot 		return ret;
2631b5c29a34SFrançois Tigeot 
26328621f407SFrançois Tigeot 	intel_ring_emit(engine,
2633b5c29a34SFrançois Tigeot 			MI_BATCH_BUFFER_START |
2634477eb7f9SFrançois Tigeot 			(dispatch_flags & I915_DISPATCH_SECURE ?
2635477eb7f9SFrançois Tigeot 			 0 : MI_BATCH_NON_SECURE_I965));
2636e3adcf8fSFrançois Tigeot 	/* bit0-7 is the length on GEN6+ */
26378621f407SFrançois Tigeot 	intel_ring_emit(engine, offset);
26388621f407SFrançois Tigeot 	intel_ring_advance(engine);
2639e3adcf8fSFrançois Tigeot 
2640e3adcf8fSFrançois Tigeot 	return 0;
2641e3adcf8fSFrançois Tigeot }
2642e3adcf8fSFrançois Tigeot 
2643e3adcf8fSFrançois Tigeot /* Blitter support (SandyBridge+) */
2644e3adcf8fSFrançois Tigeot 
2645a05eeebfSFrançois Tigeot static int gen6_ring_flush(struct drm_i915_gem_request *req,
2646b5c29a34SFrançois Tigeot 			   u32 invalidate, u32 flush)
2647e3adcf8fSFrançois Tigeot {
26488621f407SFrançois Tigeot 	struct intel_engine_cs *engine = req->engine;
2649e3adcf8fSFrançois Tigeot 	uint32_t cmd;
2650e3adcf8fSFrançois Tigeot 	int ret;
2651e3adcf8fSFrançois Tigeot 
2652a05eeebfSFrançois Tigeot 	ret = intel_ring_begin(req, 4);
2653e3adcf8fSFrançois Tigeot 	if (ret)
2654e3adcf8fSFrançois Tigeot 		return ret;
2655e3adcf8fSFrançois Tigeot 
2656e3adcf8fSFrançois Tigeot 	cmd = MI_FLUSH_DW;
26571487f786SFrançois Tigeot 	if (INTEL_GEN(req->i915) >= 8)
26589edbd4a0SFrançois Tigeot 		cmd += 1;
26592c9916cdSFrançois Tigeot 
26602c9916cdSFrançois Tigeot 	/* We always require a command barrier so that subsequent
26612c9916cdSFrançois Tigeot 	 * commands, such as breadcrumb interrupts, are strictly ordered
26622c9916cdSFrançois Tigeot 	 * wrt the contents of the write cache being flushed to memory
26632c9916cdSFrançois Tigeot 	 * (and thus being coherent from the CPU).
26642c9916cdSFrançois Tigeot 	 */
26652c9916cdSFrançois Tigeot 	cmd |= MI_FLUSH_DW_STORE_INDEX | MI_FLUSH_DW_OP_STOREDW;
26662c9916cdSFrançois Tigeot 
2667b5c29a34SFrançois Tigeot 	/*
2668b5c29a34SFrançois Tigeot 	 * Bspec vol 1c.3 - blitter engine command streamer:
2669b5c29a34SFrançois Tigeot 	 * "If ENABLED, all TLBs will be invalidated once the flush
2670b5c29a34SFrançois Tigeot 	 * operation is complete. This bit is only valid when the
2671b5c29a34SFrançois Tigeot 	 * Post-Sync Operation field is a value of 1h or 3h."
2672b5c29a34SFrançois Tigeot 	 */
2673e3adcf8fSFrançois Tigeot 	if (invalidate & I915_GEM_DOMAIN_RENDER)
26742c9916cdSFrançois Tigeot 		cmd |= MI_INVALIDATE_TLB;
26758621f407SFrançois Tigeot 	intel_ring_emit(engine, cmd);
26768621f407SFrançois Tigeot 	intel_ring_emit(engine,
26778621f407SFrançois Tigeot 			I915_GEM_HWS_SCRATCH_ADDR | MI_FLUSH_DW_USE_GTT);
26781487f786SFrançois Tigeot 	if (INTEL_GEN(req->i915) >= 8) {
26798621f407SFrançois Tigeot 		intel_ring_emit(engine, 0); /* upper addr */
26808621f407SFrançois Tigeot 		intel_ring_emit(engine, 0); /* value */
26819edbd4a0SFrançois Tigeot 	} else  {
26828621f407SFrançois Tigeot 		intel_ring_emit(engine, 0);
26838621f407SFrançois Tigeot 		intel_ring_emit(engine, MI_NOOP);
26849edbd4a0SFrançois Tigeot 	}
26858621f407SFrançois Tigeot 	intel_ring_advance(engine);
26865d0b1887SFrançois Tigeot 
2687e3adcf8fSFrançois Tigeot 	return 0;
2688e3adcf8fSFrançois Tigeot }
2689e3adcf8fSFrançois Tigeot 
26901487f786SFrançois Tigeot static void intel_ring_init_semaphores(struct drm_i915_private *dev_priv,
26911487f786SFrançois Tigeot 				       struct intel_engine_cs *engine)
26921487f786SFrançois Tigeot {
26931487f786SFrançois Tigeot 	struct drm_i915_gem_object *obj;
26941487f786SFrançois Tigeot 	int ret, i;
26951487f786SFrançois Tigeot 
26961487f786SFrançois Tigeot 	if (!i915_semaphore_is_enabled(dev_priv))
26971487f786SFrançois Tigeot 		return;
26981487f786SFrançois Tigeot 
26991487f786SFrançois Tigeot 	if (INTEL_GEN(dev_priv) >= 8 && !dev_priv->semaphore_obj) {
2700*303bf270SFrançois Tigeot 		obj = i915_gem_object_create(&dev_priv->drm, 4096);
27011487f786SFrançois Tigeot 		if (IS_ERR(obj)) {
27021487f786SFrançois Tigeot 			DRM_ERROR("Failed to allocate semaphore bo. Disabling semaphores\n");
27031487f786SFrançois Tigeot 			i915.semaphores = 0;
27041487f786SFrançois Tigeot 		} else {
27051487f786SFrançois Tigeot 			i915_gem_object_set_cache_level(obj, I915_CACHE_LLC);
27061487f786SFrançois Tigeot 			ret = i915_gem_obj_ggtt_pin(obj, 0, PIN_NONBLOCK);
27071487f786SFrançois Tigeot 			if (ret != 0) {
27081487f786SFrançois Tigeot 				drm_gem_object_unreference(&obj->base);
27091487f786SFrançois Tigeot 				DRM_ERROR("Failed to pin semaphore bo. Disabling semaphores\n");
27101487f786SFrançois Tigeot 				i915.semaphores = 0;
27111487f786SFrançois Tigeot 			} else {
27121487f786SFrançois Tigeot 				dev_priv->semaphore_obj = obj;
27131487f786SFrançois Tigeot 			}
27141487f786SFrançois Tigeot 		}
27151487f786SFrançois Tigeot 	}
27161487f786SFrançois Tigeot 
27171487f786SFrançois Tigeot 	if (!i915_semaphore_is_enabled(dev_priv))
27181487f786SFrançois Tigeot 		return;
27191487f786SFrançois Tigeot 
27201487f786SFrançois Tigeot 	if (INTEL_GEN(dev_priv) >= 8) {
27211487f786SFrançois Tigeot 		u64 offset = i915_gem_obj_ggtt_offset(dev_priv->semaphore_obj);
27221487f786SFrançois Tigeot 
27231487f786SFrançois Tigeot 		engine->semaphore.sync_to = gen8_ring_sync;
27241487f786SFrançois Tigeot 		engine->semaphore.signal = gen8_xcs_signal;
27251487f786SFrançois Tigeot 
27261487f786SFrançois Tigeot 		for (i = 0; i < I915_NUM_ENGINES; i++) {
27271487f786SFrançois Tigeot 			u64 ring_offset;
27281487f786SFrançois Tigeot 
27291487f786SFrançois Tigeot 			if (i != engine->id)
27301487f786SFrançois Tigeot 				ring_offset = offset + GEN8_SEMAPHORE_OFFSET(engine->id, i);
27311487f786SFrançois Tigeot 			else
27321487f786SFrançois Tigeot 				ring_offset = MI_SEMAPHORE_SYNC_INVALID;
27331487f786SFrançois Tigeot 
27341487f786SFrançois Tigeot 			engine->semaphore.signal_ggtt[i] = ring_offset;
27351487f786SFrançois Tigeot 		}
27361487f786SFrançois Tigeot 	} else if (INTEL_GEN(dev_priv) >= 6) {
27371487f786SFrançois Tigeot 		engine->semaphore.sync_to = gen6_ring_sync;
27381487f786SFrançois Tigeot 		engine->semaphore.signal = gen6_signal;
27391487f786SFrançois Tigeot 
27401487f786SFrançois Tigeot 		/*
27411487f786SFrançois Tigeot 		 * The current semaphore is only applied on pre-gen8
27421487f786SFrançois Tigeot 		 * platform.  And there is no VCS2 ring on the pre-gen8
27431487f786SFrançois Tigeot 		 * platform. So the semaphore between RCS and VCS2 is
27441487f786SFrançois Tigeot 		 * initialized as INVALID.  Gen8 will initialize the
27451487f786SFrançois Tigeot 		 * sema between VCS2 and RCS later.
27461487f786SFrançois Tigeot 		 */
27471487f786SFrançois Tigeot 		for (i = 0; i < I915_NUM_ENGINES; i++) {
27481487f786SFrançois Tigeot 			static const struct {
27491487f786SFrançois Tigeot 				u32 wait_mbox;
27501487f786SFrançois Tigeot 				i915_reg_t mbox_reg;
27511487f786SFrançois Tigeot 			} sem_data[I915_NUM_ENGINES][I915_NUM_ENGINES] = {
27521487f786SFrançois Tigeot 				[RCS] = {
27531487f786SFrançois Tigeot 					[VCS] =  { .wait_mbox = MI_SEMAPHORE_SYNC_RV,  .mbox_reg = GEN6_VRSYNC },
27541487f786SFrançois Tigeot 					[BCS] =  { .wait_mbox = MI_SEMAPHORE_SYNC_RB,  .mbox_reg = GEN6_BRSYNC },
27551487f786SFrançois Tigeot 					[VECS] = { .wait_mbox = MI_SEMAPHORE_SYNC_RVE, .mbox_reg = GEN6_VERSYNC },
27561487f786SFrançois Tigeot 				},
27571487f786SFrançois Tigeot 				[VCS] = {
27581487f786SFrançois Tigeot 					[RCS] =  { .wait_mbox = MI_SEMAPHORE_SYNC_VR,  .mbox_reg = GEN6_RVSYNC },
27591487f786SFrançois Tigeot 					[BCS] =  { .wait_mbox = MI_SEMAPHORE_SYNC_VB,  .mbox_reg = GEN6_BVSYNC },
27601487f786SFrançois Tigeot 					[VECS] = { .wait_mbox = MI_SEMAPHORE_SYNC_VVE, .mbox_reg = GEN6_VEVSYNC },
27611487f786SFrançois Tigeot 				},
27621487f786SFrançois Tigeot 				[BCS] = {
27631487f786SFrançois Tigeot 					[RCS] =  { .wait_mbox = MI_SEMAPHORE_SYNC_BR,  .mbox_reg = GEN6_RBSYNC },
27641487f786SFrançois Tigeot 					[VCS] =  { .wait_mbox = MI_SEMAPHORE_SYNC_BV,  .mbox_reg = GEN6_VBSYNC },
27651487f786SFrançois Tigeot 					[VECS] = { .wait_mbox = MI_SEMAPHORE_SYNC_BVE, .mbox_reg = GEN6_VEBSYNC },
27661487f786SFrançois Tigeot 				},
27671487f786SFrançois Tigeot 				[VECS] = {
27681487f786SFrançois Tigeot 					[RCS] =  { .wait_mbox = MI_SEMAPHORE_SYNC_VER, .mbox_reg = GEN6_RVESYNC },
27691487f786SFrançois Tigeot 					[VCS] =  { .wait_mbox = MI_SEMAPHORE_SYNC_VEV, .mbox_reg = GEN6_VVESYNC },
27701487f786SFrançois Tigeot 					[BCS] =  { .wait_mbox = MI_SEMAPHORE_SYNC_VEB, .mbox_reg = GEN6_BVESYNC },
27711487f786SFrançois Tigeot 				},
27721487f786SFrançois Tigeot 			};
27731487f786SFrançois Tigeot 			u32 wait_mbox;
27741487f786SFrançois Tigeot 			i915_reg_t mbox_reg;
27751487f786SFrançois Tigeot 
27761487f786SFrançois Tigeot 			if (i == engine->id || i == VCS2) {
27771487f786SFrançois Tigeot 				wait_mbox = MI_SEMAPHORE_SYNC_INVALID;
27781487f786SFrançois Tigeot 				mbox_reg = GEN6_NOSYNC;
27791487f786SFrançois Tigeot 			} else {
27801487f786SFrançois Tigeot 				wait_mbox = sem_data[engine->id][i].wait_mbox;
27811487f786SFrançois Tigeot 				mbox_reg = sem_data[engine->id][i].mbox_reg;
27821487f786SFrançois Tigeot 			}
27831487f786SFrançois Tigeot 
27841487f786SFrançois Tigeot 			engine->semaphore.mbox.wait[i] = wait_mbox;
27851487f786SFrançois Tigeot 			engine->semaphore.mbox.signal[i] = mbox_reg;
27861487f786SFrançois Tigeot 		}
27871487f786SFrançois Tigeot 	}
27881487f786SFrançois Tigeot }
27891487f786SFrançois Tigeot 
27901487f786SFrançois Tigeot static void intel_ring_init_irq(struct drm_i915_private *dev_priv,
27911487f786SFrançois Tigeot 				struct intel_engine_cs *engine)
27921487f786SFrançois Tigeot {
27931487f786SFrançois Tigeot 	if (INTEL_GEN(dev_priv) >= 8) {
2794*303bf270SFrançois Tigeot 		engine->irq_enable = gen8_irq_enable;
2795*303bf270SFrançois Tigeot 		engine->irq_disable = gen8_irq_disable;
27961487f786SFrançois Tigeot 		engine->irq_seqno_barrier = gen6_seqno_barrier;
27971487f786SFrançois Tigeot 	} else if (INTEL_GEN(dev_priv) >= 6) {
2798*303bf270SFrançois Tigeot 		engine->irq_enable = gen6_irq_enable;
2799*303bf270SFrançois Tigeot 		engine->irq_disable = gen6_irq_disable;
28001487f786SFrançois Tigeot 		engine->irq_seqno_barrier = gen6_seqno_barrier;
28011487f786SFrançois Tigeot 	} else if (INTEL_GEN(dev_priv) >= 5) {
2802*303bf270SFrançois Tigeot 		engine->irq_enable = gen5_irq_enable;
2803*303bf270SFrançois Tigeot 		engine->irq_disable = gen5_irq_disable;
2804*303bf270SFrançois Tigeot 		engine->irq_seqno_barrier = gen5_seqno_barrier;
28051487f786SFrançois Tigeot 	} else if (INTEL_GEN(dev_priv) >= 3) {
2806*303bf270SFrançois Tigeot 		engine->irq_enable = i9xx_irq_enable;
2807*303bf270SFrançois Tigeot 		engine->irq_disable = i9xx_irq_disable;
28081487f786SFrançois Tigeot 	} else {
2809*303bf270SFrançois Tigeot 		engine->irq_enable = i8xx_irq_enable;
2810*303bf270SFrançois Tigeot 		engine->irq_disable = i8xx_irq_disable;
28111487f786SFrançois Tigeot 	}
28121487f786SFrançois Tigeot }
28131487f786SFrançois Tigeot 
28141487f786SFrançois Tigeot static void intel_ring_default_vfuncs(struct drm_i915_private *dev_priv,
28151487f786SFrançois Tigeot 				      struct intel_engine_cs *engine)
28161487f786SFrançois Tigeot {
28171487f786SFrançois Tigeot 	engine->init_hw = init_ring_common;
28181487f786SFrançois Tigeot 	engine->write_tail = ring_write_tail;
28191487f786SFrançois Tigeot 
28201487f786SFrançois Tigeot 	engine->add_request = i9xx_add_request;
28211487f786SFrançois Tigeot 	if (INTEL_GEN(dev_priv) >= 6)
28221487f786SFrançois Tigeot 		engine->add_request = gen6_add_request;
28231487f786SFrançois Tigeot 
28241487f786SFrançois Tigeot 	if (INTEL_GEN(dev_priv) >= 8)
28251487f786SFrançois Tigeot 		engine->dispatch_execbuffer = gen8_ring_dispatch_execbuffer;
28261487f786SFrançois Tigeot 	else if (INTEL_GEN(dev_priv) >= 6)
28271487f786SFrançois Tigeot 		engine->dispatch_execbuffer = gen6_ring_dispatch_execbuffer;
28281487f786SFrançois Tigeot 	else if (INTEL_GEN(dev_priv) >= 4)
28291487f786SFrançois Tigeot 		engine->dispatch_execbuffer = i965_dispatch_execbuffer;
28301487f786SFrançois Tigeot 	else if (IS_I830(dev_priv) || IS_845G(dev_priv))
28311487f786SFrançois Tigeot 		engine->dispatch_execbuffer = i830_dispatch_execbuffer;
28321487f786SFrançois Tigeot 	else
28331487f786SFrançois Tigeot 		engine->dispatch_execbuffer = i915_dispatch_execbuffer;
28341487f786SFrançois Tigeot 
28351487f786SFrançois Tigeot 	intel_ring_init_irq(dev_priv, engine);
28361487f786SFrançois Tigeot 	intel_ring_init_semaphores(dev_priv, engine);
28371487f786SFrançois Tigeot }
28381487f786SFrançois Tigeot 
2839e3adcf8fSFrançois Tigeot int intel_init_render_ring_buffer(struct drm_device *dev)
2840e3adcf8fSFrançois Tigeot {
2841*303bf270SFrançois Tigeot 	struct drm_i915_private *dev_priv = to_i915(dev);
28428621f407SFrançois Tigeot 	struct intel_engine_cs *engine = &dev_priv->engine[RCS];
284324edb884SFrançois Tigeot 	int ret;
2844e3adcf8fSFrançois Tigeot 
28458621f407SFrançois Tigeot 	engine->name = "render ring";
28468621f407SFrançois Tigeot 	engine->id = RCS;
28478621f407SFrançois Tigeot 	engine->exec_id = I915_EXEC_RENDER;
28488621f407SFrançois Tigeot 	engine->hw_id = 0;
28498621f407SFrançois Tigeot 	engine->mmio_base = RENDER_RING_BASE;
2850686a02f1SFrançois Tigeot 
28511487f786SFrançois Tigeot 	intel_ring_default_vfuncs(dev_priv, engine);
28522c9916cdSFrançois Tigeot 
2853*303bf270SFrançois Tigeot 	engine->irq_enable_mask = GT_RENDER_USER_INTERRUPT;
2854*303bf270SFrançois Tigeot 	if (HAS_L3_DPF(dev_priv))
2855*303bf270SFrançois Tigeot 		engine->irq_keep_mask = GT_RENDER_L3_PARITY_ERROR_INTERRUPT;
2856*303bf270SFrançois Tigeot 
28571487f786SFrançois Tigeot 	if (INTEL_GEN(dev_priv) >= 8) {
28588621f407SFrançois Tigeot 		engine->init_context = intel_rcs_ctx_init;
28591487f786SFrançois Tigeot 		engine->add_request = gen8_render_add_request;
28608621f407SFrançois Tigeot 		engine->flush = gen8_render_ring_flush;
28611487f786SFrançois Tigeot 		if (i915_semaphore_is_enabled(dev_priv))
28628621f407SFrançois Tigeot 			engine->semaphore.signal = gen8_rcs_signal;
28631487f786SFrançois Tigeot 	} else if (INTEL_GEN(dev_priv) >= 6) {
28648621f407SFrançois Tigeot 		engine->init_context = intel_rcs_ctx_init;
28658621f407SFrançois Tigeot 		engine->flush = gen7_render_ring_flush;
28661487f786SFrançois Tigeot 		if (IS_GEN6(dev_priv))
28678621f407SFrançois Tigeot 			engine->flush = gen6_render_ring_flush;
28681487f786SFrançois Tigeot 	} else if (IS_GEN5(dev_priv)) {
28698621f407SFrançois Tigeot 		engine->flush = gen4_render_ring_flush;
2870686a02f1SFrançois Tigeot 	} else {
28711487f786SFrançois Tigeot 		if (INTEL_GEN(dev_priv) < 4)
28728621f407SFrançois Tigeot 			engine->flush = gen2_render_ring_flush;
2873686a02f1SFrançois Tigeot 		else
28748621f407SFrançois Tigeot 			engine->flush = gen4_render_ring_flush;
28758621f407SFrançois Tigeot 		engine->irq_enable_mask = I915_USER_INTERRUPT;
2876686a02f1SFrançois Tigeot 	}
287724edb884SFrançois Tigeot 
28781487f786SFrançois Tigeot 	if (IS_HASWELL(dev_priv))
28798621f407SFrançois Tigeot 		engine->dispatch_execbuffer = hsw_ring_dispatch_execbuffer;
28801487f786SFrançois Tigeot 
28818621f407SFrançois Tigeot 	engine->init_hw = init_render_ring;
28828621f407SFrançois Tigeot 	engine->cleanup = render_ring_cleanup;
2883e3adcf8fSFrançois Tigeot 
28848621f407SFrançois Tigeot 	ret = intel_init_ring_buffer(dev, engine);
2885b5c29a34SFrançois Tigeot 	if (ret)
28862c9916cdSFrançois Tigeot 		return ret;
28872c9916cdSFrançois Tigeot 
2888*303bf270SFrançois Tigeot 	if (INTEL_GEN(dev_priv) >= 6) {
2889*303bf270SFrançois Tigeot 		ret = intel_init_pipe_control(engine, 4096);
2890*303bf270SFrançois Tigeot 		if (ret)
2891*303bf270SFrançois Tigeot 			return ret;
2892*303bf270SFrançois Tigeot 	} else if (HAS_BROKEN_CS_TLB(dev_priv)) {
2893*303bf270SFrançois Tigeot 		ret = intel_init_pipe_control(engine, I830_WA_SIZE);
28942c9916cdSFrançois Tigeot 		if (ret)
28952c9916cdSFrançois Tigeot 			return ret;
2896b5c29a34SFrançois Tigeot 	}
2897b5c29a34SFrançois Tigeot 
2898e3adcf8fSFrançois Tigeot 	return 0;
2899e3adcf8fSFrançois Tigeot }
2900e3adcf8fSFrançois Tigeot 
2901e3adcf8fSFrançois Tigeot int intel_init_bsd_ring_buffer(struct drm_device *dev)
2902e3adcf8fSFrançois Tigeot {
2903*303bf270SFrançois Tigeot 	struct drm_i915_private *dev_priv = to_i915(dev);
29048621f407SFrançois Tigeot 	struct intel_engine_cs *engine = &dev_priv->engine[VCS];
2905e3adcf8fSFrançois Tigeot 
29068621f407SFrançois Tigeot 	engine->name = "bsd ring";
29078621f407SFrançois Tigeot 	engine->id = VCS;
29088621f407SFrançois Tigeot 	engine->exec_id = I915_EXEC_BSD;
29098621f407SFrançois Tigeot 	engine->hw_id = 1;
2910686a02f1SFrançois Tigeot 
29111487f786SFrançois Tigeot 	intel_ring_default_vfuncs(dev_priv, engine);
29121487f786SFrançois Tigeot 
29131487f786SFrançois Tigeot 	if (INTEL_GEN(dev_priv) >= 6) {
29148621f407SFrançois Tigeot 		engine->mmio_base = GEN6_BSD_RING_BASE;
2915686a02f1SFrançois Tigeot 		/* gen6 bsd needs a special wa for tail updates */
29161487f786SFrançois Tigeot 		if (IS_GEN6(dev_priv))
29178621f407SFrançois Tigeot 			engine->write_tail = gen6_bsd_ring_write_tail;
29188621f407SFrançois Tigeot 		engine->flush = gen6_bsd_ring_flush;
29191487f786SFrançois Tigeot 		if (INTEL_GEN(dev_priv) >= 8)
29208621f407SFrançois Tigeot 			engine->irq_enable_mask =
29219edbd4a0SFrançois Tigeot 				GT_RENDER_USER_INTERRUPT << GEN8_VCS1_IRQ_SHIFT;
29221487f786SFrançois Tigeot 		else
29238621f407SFrançois Tigeot 			engine->irq_enable_mask = GT_BSD_USER_INTERRUPT;
2924686a02f1SFrançois Tigeot 	} else {
29258621f407SFrançois Tigeot 		engine->mmio_base = BSD_RING_BASE;
29268621f407SFrançois Tigeot 		engine->flush = bsd_ring_flush;
29271487f786SFrançois Tigeot 		if (IS_GEN5(dev_priv))
29288621f407SFrançois Tigeot 			engine->irq_enable_mask = ILK_BSD_USER_INTERRUPT;
29291487f786SFrançois Tigeot 		else
29308621f407SFrançois Tigeot 			engine->irq_enable_mask = I915_BSD_USER_INTERRUPT;
2931686a02f1SFrançois Tigeot 	}
2932e3adcf8fSFrançois Tigeot 
29338621f407SFrançois Tigeot 	return intel_init_ring_buffer(dev, engine);
2934e3adcf8fSFrançois Tigeot }
2935e3adcf8fSFrançois Tigeot 
2936ba55f2f5SFrançois Tigeot /**
2937477eb7f9SFrançois Tigeot  * Initialize the second BSD ring (eg. Broadwell GT3, Skylake GT3)
2938ba55f2f5SFrançois Tigeot  */
2939ba55f2f5SFrançois Tigeot int intel_init_bsd2_ring_buffer(struct drm_device *dev)
2940ba55f2f5SFrançois Tigeot {
2941*303bf270SFrançois Tigeot 	struct drm_i915_private *dev_priv = to_i915(dev);
29428621f407SFrançois Tigeot 	struct intel_engine_cs *engine = &dev_priv->engine[VCS2];
2943ba55f2f5SFrançois Tigeot 
29448621f407SFrançois Tigeot 	engine->name = "bsd2 ring";
29458621f407SFrançois Tigeot 	engine->id = VCS2;
29468621f407SFrançois Tigeot 	engine->exec_id = I915_EXEC_BSD;
29478621f407SFrançois Tigeot 	engine->hw_id = 4;
29488621f407SFrançois Tigeot 	engine->mmio_base = GEN8_BSD2_RING_BASE;
29491487f786SFrançois Tigeot 
29501487f786SFrançois Tigeot 	intel_ring_default_vfuncs(dev_priv, engine);
29511487f786SFrançois Tigeot 
29528621f407SFrançois Tigeot 	engine->flush = gen6_bsd_ring_flush;
29538621f407SFrançois Tigeot 	engine->irq_enable_mask =
2954ba55f2f5SFrançois Tigeot 			GT_RENDER_USER_INTERRUPT << GEN8_VCS2_IRQ_SHIFT;
2955ba55f2f5SFrançois Tigeot 
29568621f407SFrançois Tigeot 	return intel_init_ring_buffer(dev, engine);
2957ba55f2f5SFrançois Tigeot }
2958ba55f2f5SFrançois Tigeot 
2959e3adcf8fSFrançois Tigeot int intel_init_blt_ring_buffer(struct drm_device *dev)
2960e3adcf8fSFrançois Tigeot {
2961*303bf270SFrançois Tigeot 	struct drm_i915_private *dev_priv = to_i915(dev);
29628621f407SFrançois Tigeot 	struct intel_engine_cs *engine = &dev_priv->engine[BCS];
2963e3adcf8fSFrançois Tigeot 
29648621f407SFrançois Tigeot 	engine->name = "blitter ring";
29658621f407SFrançois Tigeot 	engine->id = BCS;
29668621f407SFrançois Tigeot 	engine->exec_id = I915_EXEC_BLT;
29678621f407SFrançois Tigeot 	engine->hw_id = 2;
29688621f407SFrançois Tigeot 	engine->mmio_base = BLT_RING_BASE;
29691487f786SFrançois Tigeot 
29701487f786SFrançois Tigeot 	intel_ring_default_vfuncs(dev_priv, engine);
29711487f786SFrançois Tigeot 
29728621f407SFrançois Tigeot 	engine->flush = gen6_ring_flush;
29731487f786SFrançois Tigeot 	if (INTEL_GEN(dev_priv) >= 8)
29748621f407SFrançois Tigeot 		engine->irq_enable_mask =
29759edbd4a0SFrançois Tigeot 			GT_RENDER_USER_INTERRUPT << GEN8_BCS_IRQ_SHIFT;
29761487f786SFrançois Tigeot 	else
29778621f407SFrançois Tigeot 		engine->irq_enable_mask = GT_BLT_USER_INTERRUPT;
29785d0b1887SFrançois Tigeot 
29798621f407SFrançois Tigeot 	return intel_init_ring_buffer(dev, engine);
29805d0b1887SFrançois Tigeot }
29815d0b1887SFrançois Tigeot 
29825d0b1887SFrançois Tigeot int intel_init_vebox_ring_buffer(struct drm_device *dev)
29835d0b1887SFrançois Tigeot {
2984*303bf270SFrançois Tigeot 	struct drm_i915_private *dev_priv = to_i915(dev);
29858621f407SFrançois Tigeot 	struct intel_engine_cs *engine = &dev_priv->engine[VECS];
29865d0b1887SFrançois Tigeot 
29878621f407SFrançois Tigeot 	engine->name = "video enhancement ring";
29888621f407SFrançois Tigeot 	engine->id = VECS;
29898621f407SFrançois Tigeot 	engine->exec_id = I915_EXEC_VEBOX;
29908621f407SFrançois Tigeot 	engine->hw_id = 3;
29918621f407SFrançois Tigeot 	engine->mmio_base = VEBOX_RING_BASE;
29929edbd4a0SFrançois Tigeot 
29931487f786SFrançois Tigeot 	intel_ring_default_vfuncs(dev_priv, engine);
29941487f786SFrançois Tigeot 
29951487f786SFrançois Tigeot 	engine->flush = gen6_ring_flush;
29961487f786SFrançois Tigeot 
29971487f786SFrançois Tigeot 	if (INTEL_GEN(dev_priv) >= 8) {
29988621f407SFrançois Tigeot 		engine->irq_enable_mask =
29999edbd4a0SFrançois Tigeot 			GT_RENDER_USER_INTERRUPT << GEN8_VECS_IRQ_SHIFT;
30009edbd4a0SFrançois Tigeot 	} else {
30018621f407SFrançois Tigeot 		engine->irq_enable_mask = PM_VEBOX_USER_INTERRUPT;
3002*303bf270SFrançois Tigeot 		engine->irq_enable = hsw_vebox_irq_enable;
3003*303bf270SFrançois Tigeot 		engine->irq_disable = hsw_vebox_irq_disable;
300424edb884SFrançois Tigeot 	}
3005e3adcf8fSFrançois Tigeot 
30068621f407SFrançois Tigeot 	return intel_init_ring_buffer(dev, engine);
3007e3adcf8fSFrançois Tigeot }
3008b030f26bSFrançois Tigeot 
3009b030f26bSFrançois Tigeot int
3010a05eeebfSFrançois Tigeot intel_ring_flush_all_caches(struct drm_i915_gem_request *req)
3011b030f26bSFrançois Tigeot {
30128621f407SFrançois Tigeot 	struct intel_engine_cs *engine = req->engine;
3013b030f26bSFrançois Tigeot 	int ret;
3014b030f26bSFrançois Tigeot 
30158621f407SFrançois Tigeot 	if (!engine->gpu_caches_dirty)
3016b030f26bSFrançois Tigeot 		return 0;
3017b030f26bSFrançois Tigeot 
30188621f407SFrançois Tigeot 	ret = engine->flush(req, 0, I915_GEM_GPU_DOMAINS);
3019b030f26bSFrançois Tigeot 	if (ret)
3020b030f26bSFrançois Tigeot 		return ret;
3021b030f26bSFrançois Tigeot 
3022a05eeebfSFrançois Tigeot 	trace_i915_gem_ring_flush(req, 0, I915_GEM_GPU_DOMAINS);
3023a2fdbec6SFrançois Tigeot 
30248621f407SFrançois Tigeot 	engine->gpu_caches_dirty = false;
3025b030f26bSFrançois Tigeot 	return 0;
3026b030f26bSFrançois Tigeot }
3027b030f26bSFrançois Tigeot 
3028b030f26bSFrançois Tigeot int
3029a05eeebfSFrançois Tigeot intel_ring_invalidate_all_caches(struct drm_i915_gem_request *req)
3030b030f26bSFrançois Tigeot {
30318621f407SFrançois Tigeot 	struct intel_engine_cs *engine = req->engine;
3032b030f26bSFrançois Tigeot 	uint32_t flush_domains;
3033b030f26bSFrançois Tigeot 	int ret;
3034b030f26bSFrançois Tigeot 
3035b030f26bSFrançois Tigeot 	flush_domains = 0;
30368621f407SFrançois Tigeot 	if (engine->gpu_caches_dirty)
3037b030f26bSFrançois Tigeot 		flush_domains = I915_GEM_GPU_DOMAINS;
3038b030f26bSFrançois Tigeot 
30398621f407SFrançois Tigeot 	ret = engine->flush(req, I915_GEM_GPU_DOMAINS, flush_domains);
3040b030f26bSFrançois Tigeot 	if (ret)
3041b030f26bSFrançois Tigeot 		return ret;
3042b030f26bSFrançois Tigeot 
3043a05eeebfSFrançois Tigeot 	trace_i915_gem_ring_flush(req, I915_GEM_GPU_DOMAINS, flush_domains);
3044a2fdbec6SFrançois Tigeot 
30458621f407SFrançois Tigeot 	engine->gpu_caches_dirty = false;
3046b030f26bSFrançois Tigeot 	return 0;
3047b030f26bSFrançois Tigeot }
3048ba55f2f5SFrançois Tigeot 
3049ba55f2f5SFrançois Tigeot void
30508621f407SFrançois Tigeot intel_stop_engine(struct intel_engine_cs *engine)
3051ba55f2f5SFrançois Tigeot {
3052ba55f2f5SFrançois Tigeot 	int ret;
3053ba55f2f5SFrançois Tigeot 
30548621f407SFrançois Tigeot 	if (!intel_engine_initialized(engine))
3055ba55f2f5SFrançois Tigeot 		return;
3056ba55f2f5SFrançois Tigeot 
30578621f407SFrançois Tigeot 	ret = intel_engine_idle(engine);
30588621f407SFrançois Tigeot 	if (ret)
3059ba55f2f5SFrançois Tigeot 		DRM_ERROR("failed to quiesce %s whilst cleaning up: %d\n",
30608621f407SFrançois Tigeot 			  engine->name, ret);
3061ba55f2f5SFrançois Tigeot 
30628621f407SFrançois Tigeot 	stop_ring(engine);
3063ba55f2f5SFrançois Tigeot }
3064