xref: /dflybsd-src/sys/dev/drm/i915/intel_ringbuffer.c (revision 71f41f3eaecc1bac4c44cc81622db5b5dddc7dc4)
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 
50*71f41f3eSFrançois Tigeot void intel_ring_update_space(struct intel_ring *ring)
512c9916cdSFrançois Tigeot {
52*71f41f3eSFrançois Tigeot 	if (ring->last_retired_head != -1) {
53*71f41f3eSFrançois Tigeot 		ring->head = ring->last_retired_head;
54*71f41f3eSFrançois Tigeot 		ring->last_retired_head = -1;
552c9916cdSFrançois Tigeot 	}
562c9916cdSFrançois Tigeot 
57*71f41f3eSFrançois Tigeot 	ring->space = __intel_ring_space(ring->head & HEAD_ADDR,
58*71f41f3eSFrançois Tigeot 					 ring->tail, ring->size);
599edbd4a0SFrançois Tigeot }
609edbd4a0SFrançois Tigeot 
61e3adcf8fSFrançois Tigeot static int
62*71f41f3eSFrançois Tigeot gen2_render_ring_flush(struct drm_i915_gem_request *req, u32 mode)
63686a02f1SFrançois Tigeot {
64*71f41f3eSFrançois Tigeot 	struct intel_ring *ring = req->ring;
65686a02f1SFrançois Tigeot 	u32 cmd;
66686a02f1SFrançois Tigeot 	int ret;
67686a02f1SFrançois Tigeot 
68686a02f1SFrançois Tigeot 	cmd = MI_FLUSH;
69686a02f1SFrançois Tigeot 
70*71f41f3eSFrançois Tigeot 	if (mode & EMIT_INVALIDATE)
71686a02f1SFrançois Tigeot 		cmd |= MI_READ_FLUSH;
72686a02f1SFrançois Tigeot 
73a05eeebfSFrançois Tigeot 	ret = intel_ring_begin(req, 2);
74686a02f1SFrançois Tigeot 	if (ret)
75686a02f1SFrançois Tigeot 		return ret;
76686a02f1SFrançois Tigeot 
77*71f41f3eSFrançois Tigeot 	intel_ring_emit(ring, cmd);
78*71f41f3eSFrançois Tigeot 	intel_ring_emit(ring, MI_NOOP);
79*71f41f3eSFrançois Tigeot 	intel_ring_advance(ring);
80686a02f1SFrançois Tigeot 
81686a02f1SFrançois Tigeot 	return 0;
82686a02f1SFrançois Tigeot }
83686a02f1SFrançois Tigeot 
84686a02f1SFrançois Tigeot static int
85*71f41f3eSFrançois Tigeot gen4_render_ring_flush(struct drm_i915_gem_request *req, u32 mode)
86e3adcf8fSFrançois Tigeot {
87*71f41f3eSFrançois Tigeot 	struct intel_ring *ring = req->ring;
88686a02f1SFrançois Tigeot 	u32 cmd;
89e3adcf8fSFrançois Tigeot 	int ret;
90e3adcf8fSFrançois Tigeot 
91e3adcf8fSFrançois Tigeot 	/*
92e3adcf8fSFrançois Tigeot 	 * read/write caches:
93e3adcf8fSFrançois Tigeot 	 *
94e3adcf8fSFrançois Tigeot 	 * I915_GEM_DOMAIN_RENDER is always invalidated, but is
95e3adcf8fSFrançois Tigeot 	 * only flushed if MI_NO_WRITE_FLUSH is unset.  On 965, it is
96e3adcf8fSFrançois Tigeot 	 * also flushed at 2d versus 3d pipeline switches.
97e3adcf8fSFrançois Tigeot 	 *
98e3adcf8fSFrançois Tigeot 	 * read-only caches:
99e3adcf8fSFrançois Tigeot 	 *
100e3adcf8fSFrançois Tigeot 	 * I915_GEM_DOMAIN_SAMPLER is flushed on pre-965 if
101e3adcf8fSFrançois Tigeot 	 * MI_READ_FLUSH is set, and is always flushed on 965.
102e3adcf8fSFrançois Tigeot 	 *
103e3adcf8fSFrançois Tigeot 	 * I915_GEM_DOMAIN_COMMAND may not exist?
104e3adcf8fSFrançois Tigeot 	 *
105e3adcf8fSFrançois Tigeot 	 * I915_GEM_DOMAIN_INSTRUCTION, which exists on 965, is
106e3adcf8fSFrançois Tigeot 	 * invalidated when MI_EXE_FLUSH is set.
107e3adcf8fSFrançois Tigeot 	 *
108e3adcf8fSFrançois Tigeot 	 * I915_GEM_DOMAIN_VERTEX, which exists on 965, is
109e3adcf8fSFrançois Tigeot 	 * invalidated with every MI_FLUSH.
110e3adcf8fSFrançois Tigeot 	 *
111e3adcf8fSFrançois Tigeot 	 * TLBs:
112e3adcf8fSFrançois Tigeot 	 *
113e3adcf8fSFrançois Tigeot 	 * On 965, TLBs associated with I915_GEM_DOMAIN_COMMAND
114e3adcf8fSFrançois Tigeot 	 * and I915_GEM_DOMAIN_CPU in are invalidated at PTE write and
115e3adcf8fSFrançois Tigeot 	 * I915_GEM_DOMAIN_RENDER and I915_GEM_DOMAIN_SAMPLER
116e3adcf8fSFrançois Tigeot 	 * are flushed at any MI_FLUSH.
117e3adcf8fSFrançois Tigeot 	 */
118e3adcf8fSFrançois Tigeot 
119*71f41f3eSFrançois Tigeot 	cmd = MI_FLUSH;
120*71f41f3eSFrançois Tigeot 	if (mode & EMIT_INVALIDATE) {
121e3adcf8fSFrançois Tigeot 		cmd |= MI_EXE_FLUSH;
122*71f41f3eSFrançois Tigeot 		if (IS_G4X(req->i915) || IS_GEN5(req->i915))
123e3adcf8fSFrançois Tigeot 			cmd |= MI_INVALIDATE_ISP;
124*71f41f3eSFrançois Tigeot 	}
125e3adcf8fSFrançois Tigeot 
126a05eeebfSFrançois Tigeot 	ret = intel_ring_begin(req, 2);
127e3adcf8fSFrançois Tigeot 	if (ret)
128e3adcf8fSFrançois Tigeot 		return ret;
129e3adcf8fSFrançois Tigeot 
130*71f41f3eSFrançois Tigeot 	intel_ring_emit(ring, cmd);
131*71f41f3eSFrançois Tigeot 	intel_ring_emit(ring, MI_NOOP);
132*71f41f3eSFrançois Tigeot 	intel_ring_advance(ring);
133e3adcf8fSFrançois Tigeot 
134e3adcf8fSFrançois Tigeot 	return 0;
135e3adcf8fSFrançois Tigeot }
136e3adcf8fSFrançois Tigeot 
137e3adcf8fSFrançois Tigeot /**
138e3adcf8fSFrançois Tigeot  * Emits a PIPE_CONTROL with a non-zero post-sync operation, for
139e3adcf8fSFrançois Tigeot  * implementing two workarounds on gen6.  From section 1.4.7.1
140e3adcf8fSFrançois Tigeot  * "PIPE_CONTROL" of the Sandy Bridge PRM volume 2 part 1:
141e3adcf8fSFrançois Tigeot  *
142e3adcf8fSFrançois Tigeot  * [DevSNB-C+{W/A}] Before any depth stall flush (including those
143e3adcf8fSFrançois Tigeot  * produced by non-pipelined state commands), software needs to first
144e3adcf8fSFrançois Tigeot  * send a PIPE_CONTROL with no bits set except Post-Sync Operation !=
145e3adcf8fSFrançois Tigeot  * 0.
146e3adcf8fSFrançois Tigeot  *
147e3adcf8fSFrançois Tigeot  * [Dev-SNB{W/A}]: Before a PIPE_CONTROL with Write Cache Flush Enable
148e3adcf8fSFrançois Tigeot  * =1, a PIPE_CONTROL with any non-zero post-sync-op is required.
149e3adcf8fSFrançois Tigeot  *
150e3adcf8fSFrançois Tigeot  * And the workaround for these two requires this workaround first:
151e3adcf8fSFrançois Tigeot  *
152e3adcf8fSFrançois Tigeot  * [Dev-SNB{W/A}]: Pipe-control with CS-stall bit set must be sent
153e3adcf8fSFrançois Tigeot  * BEFORE the pipe-control with a post-sync op and no write-cache
154e3adcf8fSFrançois Tigeot  * flushes.
155e3adcf8fSFrançois Tigeot  *
156e3adcf8fSFrançois Tigeot  * And this last workaround is tricky because of the requirements on
157e3adcf8fSFrançois Tigeot  * that bit.  From section 1.4.7.2.3 "Stall" of the Sandy Bridge PRM
158e3adcf8fSFrançois Tigeot  * volume 2 part 1:
159e3adcf8fSFrançois Tigeot  *
160e3adcf8fSFrançois Tigeot  *     "1 of the following must also be set:
161e3adcf8fSFrançois Tigeot  *      - Render Target Cache Flush Enable ([12] of DW1)
162e3adcf8fSFrançois Tigeot  *      - Depth Cache Flush Enable ([0] of DW1)
163e3adcf8fSFrançois Tigeot  *      - Stall at Pixel Scoreboard ([1] of DW1)
164e3adcf8fSFrançois Tigeot  *      - Depth Stall ([13] of DW1)
165e3adcf8fSFrançois Tigeot  *      - Post-Sync Operation ([13] of DW1)
166e3adcf8fSFrançois Tigeot  *      - Notify Enable ([8] of DW1)"
167e3adcf8fSFrançois Tigeot  *
168e3adcf8fSFrançois Tigeot  * The cache flushes require the workaround flush that triggered this
169e3adcf8fSFrançois Tigeot  * one, so we can't use it.  Depth stall would trigger the same.
170e3adcf8fSFrançois Tigeot  * Post-sync nonzero is what triggered this second workaround, so we
171e3adcf8fSFrançois Tigeot  * can't use that one either.  Notify enable is IRQs, which aren't
172e3adcf8fSFrançois Tigeot  * really our business.  That leaves only stall at scoreboard.
173e3adcf8fSFrançois Tigeot  */
174e3adcf8fSFrançois Tigeot static int
175a05eeebfSFrançois Tigeot intel_emit_post_sync_nonzero_flush(struct drm_i915_gem_request *req)
176e3adcf8fSFrançois Tigeot {
177*71f41f3eSFrançois Tigeot 	struct intel_ring *ring = req->ring;
178*71f41f3eSFrançois Tigeot 	u32 scratch_addr =
179*71f41f3eSFrançois Tigeot 		req->engine->scratch.gtt_offset + 2 * CACHELINE_BYTES;
180e3adcf8fSFrançois Tigeot 	int ret;
181e3adcf8fSFrançois Tigeot 
182a05eeebfSFrançois Tigeot 	ret = intel_ring_begin(req, 6);
183e3adcf8fSFrançois Tigeot 	if (ret)
184e3adcf8fSFrançois Tigeot 		return ret;
185e3adcf8fSFrançois Tigeot 
186*71f41f3eSFrançois Tigeot 	intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(5));
187*71f41f3eSFrançois Tigeot 	intel_ring_emit(ring, PIPE_CONTROL_CS_STALL |
188e3adcf8fSFrançois Tigeot 			PIPE_CONTROL_STALL_AT_SCOREBOARD);
189*71f41f3eSFrançois Tigeot 	intel_ring_emit(ring, scratch_addr | PIPE_CONTROL_GLOBAL_GTT);
190*71f41f3eSFrançois Tigeot 	intel_ring_emit(ring, 0); /* low dword */
191*71f41f3eSFrançois Tigeot 	intel_ring_emit(ring, 0); /* high dword */
192*71f41f3eSFrançois Tigeot 	intel_ring_emit(ring, MI_NOOP);
193*71f41f3eSFrançois Tigeot 	intel_ring_advance(ring);
194e3adcf8fSFrançois Tigeot 
195a05eeebfSFrançois Tigeot 	ret = intel_ring_begin(req, 6);
196e3adcf8fSFrançois Tigeot 	if (ret)
197e3adcf8fSFrançois Tigeot 		return ret;
198e3adcf8fSFrançois Tigeot 
199*71f41f3eSFrançois Tigeot 	intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(5));
200*71f41f3eSFrançois Tigeot 	intel_ring_emit(ring, PIPE_CONTROL_QW_WRITE);
201*71f41f3eSFrançois Tigeot 	intel_ring_emit(ring, scratch_addr | PIPE_CONTROL_GLOBAL_GTT);
202*71f41f3eSFrançois Tigeot 	intel_ring_emit(ring, 0);
203*71f41f3eSFrançois Tigeot 	intel_ring_emit(ring, 0);
204*71f41f3eSFrançois Tigeot 	intel_ring_emit(ring, MI_NOOP);
205*71f41f3eSFrançois Tigeot 	intel_ring_advance(ring);
206e3adcf8fSFrançois Tigeot 
207e3adcf8fSFrançois Tigeot 	return 0;
208e3adcf8fSFrançois Tigeot }
209e3adcf8fSFrançois Tigeot 
210e3adcf8fSFrançois Tigeot static int
211*71f41f3eSFrançois Tigeot gen6_render_ring_flush(struct drm_i915_gem_request *req, u32 mode)
212e3adcf8fSFrançois Tigeot {
213*71f41f3eSFrançois Tigeot 	struct intel_ring *ring = req->ring;
214*71f41f3eSFrançois Tigeot 	u32 scratch_addr =
215*71f41f3eSFrançois Tigeot 		req->engine->scratch.gtt_offset + 2 * CACHELINE_BYTES;
216e3adcf8fSFrançois Tigeot 	u32 flags = 0;
217e3adcf8fSFrançois Tigeot 	int ret;
218e3adcf8fSFrançois Tigeot 
219e3adcf8fSFrançois Tigeot 	/* Force SNB workarounds for PIPE_CONTROL flushes */
220a05eeebfSFrançois Tigeot 	ret = intel_emit_post_sync_nonzero_flush(req);
221686a02f1SFrançois Tigeot 	if (ret)
222686a02f1SFrançois Tigeot 		return ret;
223e3adcf8fSFrançois Tigeot 
224e3adcf8fSFrançois Tigeot 	/* Just flush everything.  Experiments have shown that reducing the
225e3adcf8fSFrançois Tigeot 	 * number of bits based on the write domains has little performance
226e3adcf8fSFrançois Tigeot 	 * impact.
227e3adcf8fSFrançois Tigeot 	 */
228*71f41f3eSFrançois Tigeot 	if (mode & EMIT_FLUSH) {
229e3adcf8fSFrançois Tigeot 		flags |= PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH;
230b5c29a34SFrançois Tigeot 		flags |= PIPE_CONTROL_DEPTH_CACHE_FLUSH;
231b5c29a34SFrançois Tigeot 		/*
232b5c29a34SFrançois Tigeot 		 * Ensure that any following seqno writes only happen
233b5c29a34SFrançois Tigeot 		 * when the render cache is indeed flushed.
234b5c29a34SFrançois Tigeot 		 */
235b5c29a34SFrançois Tigeot 		flags |= PIPE_CONTROL_CS_STALL;
236b5c29a34SFrançois Tigeot 	}
237*71f41f3eSFrançois Tigeot 	if (mode & EMIT_INVALIDATE) {
238686a02f1SFrançois Tigeot 		flags |= PIPE_CONTROL_TLB_INVALIDATE;
239e3adcf8fSFrançois Tigeot 		flags |= PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE;
240e3adcf8fSFrançois Tigeot 		flags |= PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE;
241e3adcf8fSFrançois Tigeot 		flags |= PIPE_CONTROL_VF_CACHE_INVALIDATE;
242e3adcf8fSFrançois Tigeot 		flags |= PIPE_CONTROL_CONST_CACHE_INVALIDATE;
243e3adcf8fSFrançois Tigeot 		flags |= PIPE_CONTROL_STATE_CACHE_INVALIDATE;
244686a02f1SFrançois Tigeot 		/*
245b5c29a34SFrançois Tigeot 		 * TLB invalidate requires a post-sync write.
246686a02f1SFrançois Tigeot 		 */
247b5c29a34SFrançois Tigeot 		flags |= PIPE_CONTROL_QW_WRITE | PIPE_CONTROL_CS_STALL;
248b5c29a34SFrançois Tigeot 	}
249e3adcf8fSFrançois Tigeot 
250a05eeebfSFrançois Tigeot 	ret = intel_ring_begin(req, 4);
251e3adcf8fSFrançois Tigeot 	if (ret)
252e3adcf8fSFrançois Tigeot 		return ret;
253e3adcf8fSFrançois Tigeot 
254*71f41f3eSFrançois Tigeot 	intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(4));
255*71f41f3eSFrançois Tigeot 	intel_ring_emit(ring, flags);
256*71f41f3eSFrançois Tigeot 	intel_ring_emit(ring, scratch_addr | PIPE_CONTROL_GLOBAL_GTT);
257*71f41f3eSFrançois Tigeot 	intel_ring_emit(ring, 0);
258*71f41f3eSFrançois Tigeot 	intel_ring_advance(ring);
259b5c29a34SFrançois Tigeot 
260b5c29a34SFrançois Tigeot 	return 0;
261b5c29a34SFrançois Tigeot }
262b5c29a34SFrançois Tigeot 
263b5c29a34SFrançois Tigeot static int
264a05eeebfSFrançois Tigeot gen7_render_ring_cs_stall_wa(struct drm_i915_gem_request *req)
265b5c29a34SFrançois Tigeot {
266*71f41f3eSFrançois Tigeot 	struct intel_ring *ring = req->ring;
267b5c29a34SFrançois Tigeot 	int ret;
268b5c29a34SFrançois Tigeot 
269a05eeebfSFrançois Tigeot 	ret = intel_ring_begin(req, 4);
270b5c29a34SFrançois Tigeot 	if (ret)
271b5c29a34SFrançois Tigeot 		return ret;
272b5c29a34SFrançois Tigeot 
273*71f41f3eSFrançois Tigeot 	intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(4));
274*71f41f3eSFrançois Tigeot 	intel_ring_emit(ring,
275*71f41f3eSFrançois Tigeot 			PIPE_CONTROL_CS_STALL |
276b5c29a34SFrançois Tigeot 			PIPE_CONTROL_STALL_AT_SCOREBOARD);
277*71f41f3eSFrançois Tigeot 	intel_ring_emit(ring, 0);
278*71f41f3eSFrançois Tigeot 	intel_ring_emit(ring, 0);
279*71f41f3eSFrançois Tigeot 	intel_ring_advance(ring);
280b5c29a34SFrançois Tigeot 
281b5c29a34SFrançois Tigeot 	return 0;
282b5c29a34SFrançois Tigeot }
283b5c29a34SFrançois Tigeot 
284b5c29a34SFrançois Tigeot static int
285*71f41f3eSFrançois Tigeot gen7_render_ring_flush(struct drm_i915_gem_request *req, u32 mode)
286b5c29a34SFrançois Tigeot {
287*71f41f3eSFrançois Tigeot 	struct intel_ring *ring = req->ring;
288*71f41f3eSFrançois Tigeot 	u32 scratch_addr =
289*71f41f3eSFrançois Tigeot 		req->engine->scratch.gtt_offset + 2 * CACHELINE_BYTES;
290b5c29a34SFrançois Tigeot 	u32 flags = 0;
291b5c29a34SFrançois Tigeot 	int ret;
292b5c29a34SFrançois Tigeot 
293b5c29a34SFrançois Tigeot 	/*
294b5c29a34SFrançois Tigeot 	 * Ensure that any following seqno writes only happen when the render
295b5c29a34SFrançois Tigeot 	 * cache is indeed flushed.
296b5c29a34SFrançois Tigeot 	 *
297b5c29a34SFrançois Tigeot 	 * Workaround: 4th PIPE_CONTROL command (except the ones with only
298b5c29a34SFrançois Tigeot 	 * read-cache invalidate bits set) must have the CS_STALL bit set. We
299b5c29a34SFrançois Tigeot 	 * don't try to be clever and just set it unconditionally.
300b5c29a34SFrançois Tigeot 	 */
301b5c29a34SFrançois Tigeot 	flags |= PIPE_CONTROL_CS_STALL;
302b5c29a34SFrançois Tigeot 
303b5c29a34SFrançois Tigeot 	/* Just flush everything.  Experiments have shown that reducing the
304b5c29a34SFrançois Tigeot 	 * number of bits based on the write domains has little performance
305b5c29a34SFrançois Tigeot 	 * impact.
306b5c29a34SFrançois Tigeot 	 */
307*71f41f3eSFrançois Tigeot 	if (mode & EMIT_FLUSH) {
308b5c29a34SFrançois Tigeot 		flags |= PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH;
309b5c29a34SFrançois Tigeot 		flags |= PIPE_CONTROL_DEPTH_CACHE_FLUSH;
310aee94f86SFrançois Tigeot 		flags |= PIPE_CONTROL_DC_FLUSH_ENABLE;
311b49c8cf9SFrançois Tigeot 		flags |= PIPE_CONTROL_FLUSH_ENABLE;
312b5c29a34SFrançois Tigeot 	}
313*71f41f3eSFrançois Tigeot 	if (mode & EMIT_INVALIDATE) {
314b5c29a34SFrançois Tigeot 		flags |= PIPE_CONTROL_TLB_INVALIDATE;
315b5c29a34SFrançois Tigeot 		flags |= PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE;
316b5c29a34SFrançois Tigeot 		flags |= PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE;
317b5c29a34SFrançois Tigeot 		flags |= PIPE_CONTROL_VF_CACHE_INVALIDATE;
318b5c29a34SFrançois Tigeot 		flags |= PIPE_CONTROL_CONST_CACHE_INVALIDATE;
319b5c29a34SFrançois Tigeot 		flags |= PIPE_CONTROL_STATE_CACHE_INVALIDATE;
3202c9916cdSFrançois Tigeot 		flags |= PIPE_CONTROL_MEDIA_STATE_CLEAR;
321b5c29a34SFrançois Tigeot 		/*
322b5c29a34SFrançois Tigeot 		 * TLB invalidate requires a post-sync write.
323b5c29a34SFrançois Tigeot 		 */
324b5c29a34SFrançois Tigeot 		flags |= PIPE_CONTROL_QW_WRITE;
325a2fdbec6SFrançois Tigeot 		flags |= PIPE_CONTROL_GLOBAL_GTT_IVB;
326b5c29a34SFrançois Tigeot 
3270dbf0ea8SMatthew Dillon 		flags |= PIPE_CONTROL_STALL_AT_SCOREBOARD;
3280dbf0ea8SMatthew Dillon 
329b5c29a34SFrançois Tigeot 		/* Workaround: we must issue a pipe_control with CS-stall bit
330b5c29a34SFrançois Tigeot 		 * set before a pipe_control command that has the state cache
331b5c29a34SFrançois Tigeot 		 * invalidate bit set. */
332a05eeebfSFrançois Tigeot 		gen7_render_ring_cs_stall_wa(req);
333b5c29a34SFrançois Tigeot 	}
334b5c29a34SFrançois Tigeot 
335a05eeebfSFrançois Tigeot 	ret = intel_ring_begin(req, 4);
336b5c29a34SFrançois Tigeot 	if (ret)
337b5c29a34SFrançois Tigeot 		return ret;
338b5c29a34SFrançois Tigeot 
339*71f41f3eSFrançois Tigeot 	intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(4));
340*71f41f3eSFrançois Tigeot 	intel_ring_emit(ring, flags);
341*71f41f3eSFrançois Tigeot 	intel_ring_emit(ring, scratch_addr);
342*71f41f3eSFrançois Tigeot 	intel_ring_emit(ring, 0);
343*71f41f3eSFrançois Tigeot 	intel_ring_advance(ring);
344e3adcf8fSFrançois Tigeot 
345e3adcf8fSFrançois Tigeot 	return 0;
346e3adcf8fSFrançois Tigeot }
347e3adcf8fSFrançois Tigeot 
3489edbd4a0SFrançois Tigeot static int
349a05eeebfSFrançois Tigeot gen8_emit_pipe_control(struct drm_i915_gem_request *req,
35024edb884SFrançois Tigeot 		       u32 flags, u32 scratch_addr)
35124edb884SFrançois Tigeot {
352*71f41f3eSFrançois Tigeot 	struct intel_ring *ring = req->ring;
35324edb884SFrançois Tigeot 	int ret;
35424edb884SFrançois Tigeot 
355a05eeebfSFrançois Tigeot 	ret = intel_ring_begin(req, 6);
35624edb884SFrançois Tigeot 	if (ret)
35724edb884SFrançois Tigeot 		return ret;
35824edb884SFrançois Tigeot 
359*71f41f3eSFrançois Tigeot 	intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(6));
360*71f41f3eSFrançois Tigeot 	intel_ring_emit(ring, flags);
361*71f41f3eSFrançois Tigeot 	intel_ring_emit(ring, scratch_addr);
362*71f41f3eSFrançois Tigeot 	intel_ring_emit(ring, 0);
363*71f41f3eSFrançois Tigeot 	intel_ring_emit(ring, 0);
364*71f41f3eSFrançois Tigeot 	intel_ring_emit(ring, 0);
365*71f41f3eSFrançois Tigeot 	intel_ring_advance(ring);
36624edb884SFrançois Tigeot 
36724edb884SFrançois Tigeot 	return 0;
36824edb884SFrançois Tigeot }
36924edb884SFrançois Tigeot 
37024edb884SFrançois Tigeot static int
371*71f41f3eSFrançois Tigeot gen8_render_ring_flush(struct drm_i915_gem_request *req, u32 mode)
3729edbd4a0SFrançois Tigeot {
3738621f407SFrançois Tigeot 	u32 scratch_addr = req->engine->scratch.gtt_offset + 2 * CACHELINE_BYTES;
374*71f41f3eSFrançois Tigeot 	u32 flags = 0;
3759edbd4a0SFrançois Tigeot 	int ret;
3769edbd4a0SFrançois Tigeot 
3779edbd4a0SFrançois Tigeot 	flags |= PIPE_CONTROL_CS_STALL;
3789edbd4a0SFrançois Tigeot 
379*71f41f3eSFrançois Tigeot 	if (mode & EMIT_FLUSH) {
3809edbd4a0SFrançois Tigeot 		flags |= PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH;
3819edbd4a0SFrançois Tigeot 		flags |= PIPE_CONTROL_DEPTH_CACHE_FLUSH;
382aee94f86SFrançois Tigeot 		flags |= PIPE_CONTROL_DC_FLUSH_ENABLE;
383b49c8cf9SFrançois Tigeot 		flags |= PIPE_CONTROL_FLUSH_ENABLE;
3849edbd4a0SFrançois Tigeot 	}
385*71f41f3eSFrançois Tigeot 	if (mode & EMIT_INVALIDATE) {
3869edbd4a0SFrançois Tigeot 		flags |= PIPE_CONTROL_TLB_INVALIDATE;
3879edbd4a0SFrançois Tigeot 		flags |= PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE;
3889edbd4a0SFrançois Tigeot 		flags |= PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE;
3899edbd4a0SFrançois Tigeot 		flags |= PIPE_CONTROL_VF_CACHE_INVALIDATE;
3909edbd4a0SFrançois Tigeot 		flags |= PIPE_CONTROL_CONST_CACHE_INVALIDATE;
3919edbd4a0SFrançois Tigeot 		flags |= PIPE_CONTROL_STATE_CACHE_INVALIDATE;
3929edbd4a0SFrançois Tigeot 		flags |= PIPE_CONTROL_QW_WRITE;
3939edbd4a0SFrançois Tigeot 		flags |= PIPE_CONTROL_GLOBAL_GTT_IVB;
3949edbd4a0SFrançois Tigeot 
39524edb884SFrançois Tigeot 		/* WaCsStallBeforeStateCacheInvalidate:bdw,chv */
396a05eeebfSFrançois Tigeot 		ret = gen8_emit_pipe_control(req,
39724edb884SFrançois Tigeot 					     PIPE_CONTROL_CS_STALL |
39824edb884SFrançois Tigeot 					     PIPE_CONTROL_STALL_AT_SCOREBOARD,
39924edb884SFrançois Tigeot 					     0);
4009edbd4a0SFrançois Tigeot 		if (ret)
4019edbd4a0SFrançois Tigeot 			return ret;
40224edb884SFrançois Tigeot 	}
4039edbd4a0SFrançois Tigeot 
404a05eeebfSFrançois Tigeot 	return gen8_emit_pipe_control(req, flags, scratch_addr);
4059edbd4a0SFrançois Tigeot }
4069edbd4a0SFrançois Tigeot 
407*71f41f3eSFrançois Tigeot u64 intel_engine_get_active_head(struct intel_engine_cs *engine)
408e3adcf8fSFrançois Tigeot {
4091487f786SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
410ba55f2f5SFrançois Tigeot 	u64 acthd;
411e3adcf8fSFrançois Tigeot 
4121487f786SFrançois Tigeot 	if (INTEL_GEN(dev_priv) >= 8)
4138621f407SFrançois Tigeot 		acthd = I915_READ64_2x32(RING_ACTHD(engine->mmio_base),
4148621f407SFrançois Tigeot 					 RING_ACTHD_UDW(engine->mmio_base));
4151487f786SFrançois Tigeot 	else if (INTEL_GEN(dev_priv) >= 4)
4168621f407SFrançois Tigeot 		acthd = I915_READ(RING_ACTHD(engine->mmio_base));
417ba55f2f5SFrançois Tigeot 	else
418ba55f2f5SFrançois Tigeot 		acthd = I915_READ(ACTHD);
419ba55f2f5SFrançois Tigeot 
420ba55f2f5SFrançois Tigeot 	return acthd;
421e3adcf8fSFrançois Tigeot }
422e3adcf8fSFrançois Tigeot 
4238621f407SFrançois Tigeot static void ring_setup_phys_status_page(struct intel_engine_cs *engine)
4245d0b1887SFrançois Tigeot {
4251487f786SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
4265d0b1887SFrançois Tigeot 	u32 addr;
4275d0b1887SFrançois Tigeot 
4285d0b1887SFrançois Tigeot 	addr = dev_priv->status_page_dmah->busaddr;
4291487f786SFrançois Tigeot 	if (INTEL_GEN(dev_priv) >= 4)
4305d0b1887SFrançois Tigeot 		addr |= (dev_priv->status_page_dmah->busaddr >> 28) & 0xf0;
4315d0b1887SFrançois Tigeot 	I915_WRITE(HWS_PGA, addr);
4325d0b1887SFrançois Tigeot }
4335d0b1887SFrançois Tigeot 
4348621f407SFrançois Tigeot static void intel_ring_setup_status_page(struct intel_engine_cs *engine)
435477eb7f9SFrançois Tigeot {
4361487f786SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
437aee94f86SFrançois Tigeot 	i915_reg_t mmio;
438477eb7f9SFrançois Tigeot 
439477eb7f9SFrançois Tigeot 	/* The ring status page addresses are no longer next to the rest of
440477eb7f9SFrançois Tigeot 	 * the ring registers as of gen7.
441477eb7f9SFrançois Tigeot 	 */
4421487f786SFrançois Tigeot 	if (IS_GEN7(dev_priv)) {
4438621f407SFrançois Tigeot 		switch (engine->id) {
444477eb7f9SFrançois Tigeot 		case RCS:
445477eb7f9SFrançois Tigeot 			mmio = RENDER_HWS_PGA_GEN7;
446477eb7f9SFrançois Tigeot 			break;
447477eb7f9SFrançois Tigeot 		case BCS:
448477eb7f9SFrançois Tigeot 			mmio = BLT_HWS_PGA_GEN7;
449477eb7f9SFrançois Tigeot 			break;
450477eb7f9SFrançois Tigeot 		/*
451477eb7f9SFrançois Tigeot 		 * VCS2 actually doesn't exist on Gen7. Only shut up
452477eb7f9SFrançois Tigeot 		 * gcc switch check warning
453477eb7f9SFrançois Tigeot 		 */
454477eb7f9SFrançois Tigeot 		case VCS2:
455477eb7f9SFrançois Tigeot 		case VCS:
456477eb7f9SFrançois Tigeot 			mmio = BSD_HWS_PGA_GEN7;
457477eb7f9SFrançois Tigeot 			break;
458477eb7f9SFrançois Tigeot 		case VECS:
459477eb7f9SFrançois Tigeot 			mmio = VEBOX_HWS_PGA_GEN7;
460477eb7f9SFrançois Tigeot 			break;
461477eb7f9SFrançois Tigeot 		}
4621487f786SFrançois Tigeot 	} else if (IS_GEN6(dev_priv)) {
4638621f407SFrançois Tigeot 		mmio = RING_HWS_PGA_GEN6(engine->mmio_base);
464477eb7f9SFrançois Tigeot 	} else {
465477eb7f9SFrançois Tigeot 		/* XXX: gen8 returns to sanity */
4668621f407SFrançois Tigeot 		mmio = RING_HWS_PGA(engine->mmio_base);
467477eb7f9SFrançois Tigeot 	}
468477eb7f9SFrançois Tigeot 
4698621f407SFrançois Tigeot 	I915_WRITE(mmio, (u32)engine->status_page.gfx_addr);
470477eb7f9SFrançois Tigeot 	POSTING_READ(mmio);
471477eb7f9SFrançois Tigeot 
472477eb7f9SFrançois Tigeot 	/*
473477eb7f9SFrançois Tigeot 	 * Flush the TLB for this page
474477eb7f9SFrançois Tigeot 	 *
475477eb7f9SFrançois Tigeot 	 * FIXME: These two bits have disappeared on gen8, so a question
476477eb7f9SFrançois Tigeot 	 * arises: do we still need this and if so how should we go about
477477eb7f9SFrançois Tigeot 	 * invalidating the TLB?
478477eb7f9SFrançois Tigeot 	 */
4791487f786SFrançois Tigeot 	if (IS_GEN(dev_priv, 6, 7)) {
4808621f407SFrançois Tigeot 		i915_reg_t reg = RING_INSTPM(engine->mmio_base);
481477eb7f9SFrançois Tigeot 
482477eb7f9SFrançois Tigeot 		/* ring should be idle before issuing a sync flush*/
4838621f407SFrançois Tigeot 		WARN_ON((I915_READ_MODE(engine) & MODE_IDLE) == 0);
484477eb7f9SFrançois Tigeot 
485477eb7f9SFrançois Tigeot 		I915_WRITE(reg,
486477eb7f9SFrançois Tigeot 			   _MASKED_BIT_ENABLE(INSTPM_TLB_INVALIDATE |
487477eb7f9SFrançois Tigeot 					      INSTPM_SYNC_FLUSH));
4881487f786SFrançois Tigeot 		if (intel_wait_for_register(dev_priv,
4891487f786SFrançois Tigeot 					    reg, INSTPM_SYNC_FLUSH, 0,
490477eb7f9SFrançois Tigeot 					    1000))
491477eb7f9SFrançois Tigeot 			DRM_ERROR("%s: wait for SyncFlush to complete for TLB invalidation timed out\n",
4928621f407SFrançois Tigeot 				  engine->name);
493477eb7f9SFrançois Tigeot 	}
494477eb7f9SFrançois Tigeot }
495477eb7f9SFrançois Tigeot 
4968621f407SFrançois Tigeot static bool stop_ring(struct intel_engine_cs *engine)
497e3adcf8fSFrançois Tigeot {
4981487f786SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
499e3adcf8fSFrançois Tigeot 
5001487f786SFrançois Tigeot 	if (!IS_GEN2(dev_priv)) {
5018621f407SFrançois Tigeot 		I915_WRITE_MODE(engine, _MASKED_BIT_ENABLE(STOP_RING));
5021487f786SFrançois Tigeot 		if (intel_wait_for_register(dev_priv,
5031487f786SFrançois Tigeot 					    RING_MI_MODE(engine->mmio_base),
5041487f786SFrançois Tigeot 					    MODE_IDLE,
5051487f786SFrançois Tigeot 					    MODE_IDLE,
5061487f786SFrançois Tigeot 					    1000)) {
5078621f407SFrançois Tigeot 			DRM_ERROR("%s : timed out trying to stop ring\n",
5088621f407SFrançois Tigeot 				  engine->name);
5091b13d190SFrançois Tigeot 			/* Sometimes we observe that the idle flag is not
5101b13d190SFrançois Tigeot 			 * set even though the ring is empty. So double
5111b13d190SFrançois Tigeot 			 * check before giving up.
5121b13d190SFrançois Tigeot 			 */
5138621f407SFrançois Tigeot 			if (I915_READ_HEAD(engine) != I915_READ_TAIL(engine))
514ba55f2f5SFrançois Tigeot 				return false;
515ba55f2f5SFrançois Tigeot 		}
516ba55f2f5SFrançois Tigeot 	}
517686a02f1SFrançois Tigeot 
5188621f407SFrançois Tigeot 	I915_WRITE_CTL(engine, 0);
5198621f407SFrançois Tigeot 	I915_WRITE_HEAD(engine, 0);
520*71f41f3eSFrançois Tigeot 	I915_WRITE_TAIL(engine, 0);
521e3adcf8fSFrançois Tigeot 
5221487f786SFrançois Tigeot 	if (!IS_GEN2(dev_priv)) {
5238621f407SFrançois Tigeot 		(void)I915_READ_CTL(engine);
5248621f407SFrançois Tigeot 		I915_WRITE_MODE(engine, _MASKED_BIT_DISABLE(STOP_RING));
525ba55f2f5SFrançois Tigeot 	}
526e3adcf8fSFrançois Tigeot 
5278621f407SFrançois Tigeot 	return (I915_READ_HEAD(engine) & HEAD_ADDR) == 0;
528ba55f2f5SFrançois Tigeot }
529ba55f2f5SFrançois Tigeot 
5308621f407SFrançois Tigeot static int init_ring_common(struct intel_engine_cs *engine)
5318621f407SFrançois Tigeot {
5321487f786SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
533*71f41f3eSFrançois Tigeot 	struct intel_ring *ring = engine->buffer;
534*71f41f3eSFrançois Tigeot 	struct drm_i915_gem_object *obj = ring->obj;
535ba55f2f5SFrançois Tigeot 	int ret = 0;
536ba55f2f5SFrançois Tigeot 
5372c9916cdSFrançois Tigeot 	intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL);
538ba55f2f5SFrançois Tigeot 
5398621f407SFrançois Tigeot 	if (!stop_ring(engine)) {
540ba55f2f5SFrançois Tigeot 		/* G45 ring initialization often fails to reset head to zero */
541b5c29a34SFrançois Tigeot 		DRM_DEBUG_KMS("%s head not reset to zero "
542e3adcf8fSFrançois Tigeot 			      "ctl %08x head %08x tail %08x start %08x\n",
5438621f407SFrançois Tigeot 			      engine->name,
5448621f407SFrançois Tigeot 			      I915_READ_CTL(engine),
5458621f407SFrançois Tigeot 			      I915_READ_HEAD(engine),
5468621f407SFrançois Tigeot 			      I915_READ_TAIL(engine),
5478621f407SFrançois Tigeot 			      I915_READ_START(engine));
548e3adcf8fSFrançois Tigeot 
5498621f407SFrançois Tigeot 		if (!stop_ring(engine)) {
550e3adcf8fSFrançois Tigeot 			DRM_ERROR("failed to set %s head to zero "
551e3adcf8fSFrançois Tigeot 				  "ctl %08x head %08x tail %08x start %08x\n",
5528621f407SFrançois Tigeot 				  engine->name,
5538621f407SFrançois Tigeot 				  I915_READ_CTL(engine),
5548621f407SFrançois Tigeot 				  I915_READ_HEAD(engine),
5558621f407SFrançois Tigeot 				  I915_READ_TAIL(engine),
5568621f407SFrançois Tigeot 				  I915_READ_START(engine));
557686a02f1SFrançois Tigeot 			ret = -EIO;
558686a02f1SFrançois Tigeot 			goto out;
559e3adcf8fSFrançois Tigeot 		}
560ba55f2f5SFrançois Tigeot 	}
561ba55f2f5SFrançois Tigeot 
5621487f786SFrançois Tigeot 	if (I915_NEED_GFX_HWS(dev_priv))
5638621f407SFrançois Tigeot 		intel_ring_setup_status_page(engine);
564ba55f2f5SFrançois Tigeot 	else
5658621f407SFrançois Tigeot 		ring_setup_phys_status_page(engine);
566ba55f2f5SFrançois Tigeot 
5670f370975SMatthew Dillon 	/* Enforce ordering by reading HEAD register back */
5688621f407SFrançois Tigeot 	I915_READ_HEAD(engine);
5690f370975SMatthew Dillon 
570ba55f2f5SFrançois Tigeot 	/* Initialize the ring. This must happen _after_ we've cleared the ring
571ba55f2f5SFrançois Tigeot 	 * registers with the above sequence (the readback of the HEAD registers
572ba55f2f5SFrançois Tigeot 	 * also enforces ordering), otherwise the hw might lose the new ring
573ba55f2f5SFrançois Tigeot 	 * register values. */
5748621f407SFrançois Tigeot 	I915_WRITE_START(engine, i915_gem_obj_ggtt_offset(obj));
5751b13d190SFrançois Tigeot 
5761b13d190SFrançois Tigeot 	/* WaClearRingBufHeadRegAtInit:ctg,elk */
5778621f407SFrançois Tigeot 	if (I915_READ_HEAD(engine))
5781b13d190SFrançois Tigeot 		DRM_DEBUG("%s initialization failed [head=%08x], fudging\n",
5798621f407SFrançois Tigeot 			  engine->name, I915_READ_HEAD(engine));
5808621f407SFrançois Tigeot 	I915_WRITE_HEAD(engine, 0);
5818621f407SFrançois Tigeot 	(void)I915_READ_HEAD(engine);
5821b13d190SFrançois Tigeot 
5838621f407SFrançois Tigeot 	I915_WRITE_CTL(engine,
584*71f41f3eSFrançois Tigeot 			((ring->size - PAGE_SIZE) & RING_NR_PAGES)
585ba55f2f5SFrançois Tigeot 			| RING_VALID);
586ba55f2f5SFrançois Tigeot 
587ba55f2f5SFrançois Tigeot 	/* If the head is still not zero, the ring is dead */
5888621f407SFrançois Tigeot 	if (wait_for((I915_READ_CTL(engine) & RING_VALID) != 0 &&
5898621f407SFrançois Tigeot 		     I915_READ_START(engine) == i915_gem_obj_ggtt_offset(obj) &&
5908621f407SFrançois Tigeot 		     (I915_READ_HEAD(engine) & HEAD_ADDR) == 0, 50)) {
591ba55f2f5SFrançois Tigeot 		DRM_ERROR("%s initialization failed "
592ba55f2f5SFrançois Tigeot 			  "ctl %08x (valid? %d) head %08x tail %08x start %08x [expected %08lx]\n",
5938621f407SFrançois Tigeot 			  engine->name,
5948621f407SFrançois Tigeot 			  I915_READ_CTL(engine),
5958621f407SFrançois Tigeot 			  I915_READ_CTL(engine) & RING_VALID,
5968621f407SFrançois Tigeot 			  I915_READ_HEAD(engine), I915_READ_TAIL(engine),
5978621f407SFrançois Tigeot 			  I915_READ_START(engine),
5988621f407SFrançois Tigeot 			  (unsigned long)i915_gem_obj_ggtt_offset(obj));
599ba55f2f5SFrançois Tigeot 		ret = -EIO;
600ba55f2f5SFrançois Tigeot 		goto out;
601ba55f2f5SFrançois Tigeot 	}
602e3adcf8fSFrançois Tigeot 
603*71f41f3eSFrançois Tigeot 	ring->last_retired_head = -1;
604*71f41f3eSFrançois Tigeot 	ring->head = I915_READ_HEAD(engine);
605*71f41f3eSFrançois Tigeot 	ring->tail = I915_READ_TAIL(engine) & TAIL_ADDR;
606*71f41f3eSFrançois Tigeot 	intel_ring_update_space(ring);
607e3adcf8fSFrançois Tigeot 
6088621f407SFrançois Tigeot 	intel_engine_init_hangcheck(engine);
6095d0b1887SFrançois Tigeot 
610686a02f1SFrançois Tigeot out:
6112c9916cdSFrançois Tigeot 	intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL);
612686a02f1SFrançois Tigeot 
613686a02f1SFrançois Tigeot 	return ret;
614e3adcf8fSFrançois Tigeot }
615e3adcf8fSFrançois Tigeot 
616303bf270SFrançois Tigeot void intel_fini_pipe_control(struct intel_engine_cs *engine)
6171b13d190SFrançois Tigeot {
6188621f407SFrançois Tigeot 	if (engine->scratch.obj == NULL)
6191b13d190SFrançois Tigeot 		return;
6201b13d190SFrançois Tigeot 
6218621f407SFrançois Tigeot 	i915_gem_object_ggtt_unpin(engine->scratch.obj);
62287df8fc6SFrançois Tigeot 	i915_gem_object_put(engine->scratch.obj);
6238621f407SFrançois Tigeot 	engine->scratch.obj = NULL;
6241b13d190SFrançois Tigeot }
6251b13d190SFrançois Tigeot 
626303bf270SFrançois Tigeot int intel_init_pipe_control(struct intel_engine_cs *engine, int size)
627e3adcf8fSFrançois Tigeot {
628303bf270SFrançois Tigeot 	struct drm_i915_gem_object *obj;
629e3adcf8fSFrançois Tigeot 	int ret;
630e3adcf8fSFrançois Tigeot 
6318621f407SFrançois Tigeot 	WARN_ON(engine->scratch.obj);
632e3adcf8fSFrançois Tigeot 
633303bf270SFrançois Tigeot 	obj = i915_gem_object_create_stolen(&engine->i915->drm, size);
634303bf270SFrançois Tigeot 	if (!obj)
635303bf270SFrançois Tigeot 		obj = i915_gem_object_create(&engine->i915->drm, size);
636303bf270SFrançois Tigeot 	if (IS_ERR(obj)) {
637303bf270SFrançois Tigeot 		DRM_ERROR("Failed to allocate scratch page\n");
638303bf270SFrançois Tigeot 		ret = PTR_ERR(obj);
639e3adcf8fSFrançois Tigeot 		goto err;
640e3adcf8fSFrançois Tigeot 	}
641e3adcf8fSFrançois Tigeot 
642*71f41f3eSFrançois Tigeot 	ret = i915_gem_object_ggtt_pin(obj, NULL, 0, 4096, PIN_HIGH);
643ba55f2f5SFrançois Tigeot 	if (ret)
644ba55f2f5SFrançois Tigeot 		goto err_unref;
645e3adcf8fSFrançois Tigeot 
646303bf270SFrançois Tigeot 	engine->scratch.obj = obj;
647303bf270SFrançois Tigeot 	engine->scratch.gtt_offset = i915_gem_obj_ggtt_offset(obj);
648a2fdbec6SFrançois Tigeot 	DRM_DEBUG_DRIVER("%s pipe control offset: 0x%08x\n",
6498621f407SFrançois Tigeot 			 engine->name, engine->scratch.gtt_offset);
650e3adcf8fSFrançois Tigeot 	return 0;
651e3adcf8fSFrançois Tigeot 
652e3adcf8fSFrançois Tigeot err_unref:
65387df8fc6SFrançois Tigeot 	i915_gem_object_put(engine->scratch.obj);
654e3adcf8fSFrançois Tigeot err:
655e3adcf8fSFrançois Tigeot 	return ret;
656e3adcf8fSFrançois Tigeot }
657e3adcf8fSFrançois Tigeot 
658a05eeebfSFrançois Tigeot static int intel_ring_workarounds_emit(struct drm_i915_gem_request *req)
6591b13d190SFrançois Tigeot {
660*71f41f3eSFrançois Tigeot 	struct intel_ring *ring = req->ring;
6611487f786SFrançois Tigeot 	struct i915_workarounds *w = &req->i915->workarounds;
6621487f786SFrançois Tigeot 	int ret, i;
6631b13d190SFrançois Tigeot 
664352ff8bdSFrançois Tigeot 	if (w->count == 0)
6652c9916cdSFrançois Tigeot 		return 0;
6661b13d190SFrançois Tigeot 
667*71f41f3eSFrançois Tigeot 	ret = req->engine->emit_flush(req, EMIT_BARRIER);
6681b13d190SFrançois Tigeot 	if (ret)
6691b13d190SFrançois Tigeot 		return ret;
6701b13d190SFrançois Tigeot 
671a05eeebfSFrançois Tigeot 	ret = intel_ring_begin(req, (w->count * 2 + 2));
6722c9916cdSFrançois Tigeot 	if (ret)
6732c9916cdSFrançois Tigeot 		return ret;
6742c9916cdSFrançois Tigeot 
675*71f41f3eSFrançois Tigeot 	intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(w->count));
6762c9916cdSFrançois Tigeot 	for (i = 0; i < w->count; i++) {
677*71f41f3eSFrançois Tigeot 		intel_ring_emit_reg(ring, w->reg[i].addr);
678*71f41f3eSFrançois Tigeot 		intel_ring_emit(ring, w->reg[i].value);
6792c9916cdSFrançois Tigeot 	}
680*71f41f3eSFrançois Tigeot 	intel_ring_emit(ring, MI_NOOP);
6812c9916cdSFrançois Tigeot 
682*71f41f3eSFrançois Tigeot 	intel_ring_advance(ring);
6832c9916cdSFrançois Tigeot 
684*71f41f3eSFrançois Tigeot 	ret = req->engine->emit_flush(req, EMIT_BARRIER);
6852c9916cdSFrançois Tigeot 	if (ret)
6862c9916cdSFrançois Tigeot 		return ret;
6872c9916cdSFrançois Tigeot 
6882c9916cdSFrançois Tigeot 	DRM_DEBUG_DRIVER("Number of Workarounds emitted: %d\n", w->count);
6892c9916cdSFrançois Tigeot 
6902c9916cdSFrançois Tigeot 	return 0;
6912c9916cdSFrançois Tigeot }
6922c9916cdSFrançois Tigeot 
693a05eeebfSFrançois Tigeot static int intel_rcs_ctx_init(struct drm_i915_gem_request *req)
6942c9916cdSFrançois Tigeot {
6952c9916cdSFrançois Tigeot 	int ret;
6962c9916cdSFrançois Tigeot 
697a05eeebfSFrançois Tigeot 	ret = intel_ring_workarounds_emit(req);
6982c9916cdSFrançois Tigeot 	if (ret != 0)
6992c9916cdSFrançois Tigeot 		return ret;
7002c9916cdSFrançois Tigeot 
701a05eeebfSFrançois Tigeot 	ret = i915_gem_render_state_init(req);
7022c9916cdSFrançois Tigeot 	if (ret)
7032c9916cdSFrançois Tigeot 		return ret;
704c0e85e96SFrançois Tigeot 
705c0e85e96SFrançois Tigeot 	return 0;
7062c9916cdSFrançois Tigeot }
7072c9916cdSFrançois Tigeot 
7082c9916cdSFrançois Tigeot static int wa_add(struct drm_i915_private *dev_priv,
709aee94f86SFrançois Tigeot 		  i915_reg_t addr,
710aee94f86SFrançois Tigeot 		  const u32 mask, const u32 val)
7112c9916cdSFrançois Tigeot {
7122c9916cdSFrançois Tigeot 	const u32 idx = dev_priv->workarounds.count;
7132c9916cdSFrançois Tigeot 
7142c9916cdSFrançois Tigeot 	if (WARN_ON(idx >= I915_MAX_WA_REGS))
7152c9916cdSFrançois Tigeot 		return -ENOSPC;
7162c9916cdSFrançois Tigeot 
7172c9916cdSFrançois Tigeot 	dev_priv->workarounds.reg[idx].addr = addr;
7182c9916cdSFrançois Tigeot 	dev_priv->workarounds.reg[idx].value = val;
7192c9916cdSFrançois Tigeot 	dev_priv->workarounds.reg[idx].mask = mask;
7202c9916cdSFrançois Tigeot 
7212c9916cdSFrançois Tigeot 	dev_priv->workarounds.count++;
7222c9916cdSFrançois Tigeot 
7232c9916cdSFrançois Tigeot 	return 0;
7242c9916cdSFrançois Tigeot }
7252c9916cdSFrançois Tigeot 
726a05eeebfSFrançois Tigeot #define WA_REG(addr, mask, val) do { \
7272c9916cdSFrançois Tigeot 		const int r = wa_add(dev_priv, (addr), (mask), (val)); \
7282c9916cdSFrançois Tigeot 		if (r) \
7292c9916cdSFrançois Tigeot 			return r; \
730a05eeebfSFrançois Tigeot 	} while (0)
7312c9916cdSFrançois Tigeot 
7322c9916cdSFrançois Tigeot #define WA_SET_BIT_MASKED(addr, mask) \
7332c9916cdSFrançois Tigeot 	WA_REG(addr, (mask), _MASKED_BIT_ENABLE(mask))
7342c9916cdSFrançois Tigeot 
7352c9916cdSFrançois Tigeot #define WA_CLR_BIT_MASKED(addr, mask) \
7362c9916cdSFrançois Tigeot 	WA_REG(addr, (mask), _MASKED_BIT_DISABLE(mask))
7372c9916cdSFrançois Tigeot 
7382c9916cdSFrançois Tigeot #define WA_SET_FIELD_MASKED(addr, mask, value) \
7392c9916cdSFrançois Tigeot 	WA_REG(addr, mask, _MASKED_FIELD(mask, value))
7402c9916cdSFrançois Tigeot 
7412c9916cdSFrançois Tigeot #define WA_SET_BIT(addr, mask) WA_REG(addr, mask, I915_READ(addr) | (mask))
7422c9916cdSFrançois Tigeot #define WA_CLR_BIT(addr, mask) WA_REG(addr, mask, I915_READ(addr) & ~(mask))
7432c9916cdSFrançois Tigeot 
7442c9916cdSFrançois Tigeot #define WA_WRITE(addr, val) WA_REG(addr, 0xffffffff, val)
7452c9916cdSFrançois Tigeot 
7468621f407SFrançois Tigeot static int wa_ring_whitelist_reg(struct intel_engine_cs *engine,
7478621f407SFrançois Tigeot 				 i915_reg_t reg)
748c0e85e96SFrançois Tigeot {
7491487f786SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
750c0e85e96SFrançois Tigeot 	struct i915_workarounds *wa = &dev_priv->workarounds;
7518621f407SFrançois Tigeot 	const uint32_t index = wa->hw_whitelist_count[engine->id];
752c0e85e96SFrançois Tigeot 
753c0e85e96SFrançois Tigeot 	if (WARN_ON(index >= RING_MAX_NONPRIV_SLOTS))
754c0e85e96SFrançois Tigeot 		return -EINVAL;
755c0e85e96SFrançois Tigeot 
7568621f407SFrançois Tigeot 	WA_WRITE(RING_FORCE_TO_NONPRIV(engine->mmio_base, index),
757c0e85e96SFrançois Tigeot 		 i915_mmio_reg_offset(reg));
7588621f407SFrançois Tigeot 	wa->hw_whitelist_count[engine->id]++;
759c0e85e96SFrançois Tigeot 
760c0e85e96SFrançois Tigeot 	return 0;
761c0e85e96SFrançois Tigeot }
762c0e85e96SFrançois Tigeot 
7638621f407SFrançois Tigeot static int gen8_init_workarounds(struct intel_engine_cs *engine)
7642c9916cdSFrançois Tigeot {
7651487f786SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
7662c9916cdSFrançois Tigeot 
767a05eeebfSFrançois Tigeot 	WA_SET_BIT_MASKED(INSTPM, INSTPM_FORCE_ORDERING);
768a05eeebfSFrançois Tigeot 
769352ff8bdSFrançois Tigeot 	/* WaDisableAsyncFlipPerfMode:bdw,chv */
770a05eeebfSFrançois Tigeot 	WA_SET_BIT_MASKED(MI_MODE, ASYNC_FLIP_PERF_DISABLE);
771a05eeebfSFrançois Tigeot 
772352ff8bdSFrançois Tigeot 	/* WaDisablePartialInstShootdown:bdw,chv */
7732c9916cdSFrançois Tigeot 	WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN,
774352ff8bdSFrançois Tigeot 			  PARTIAL_INSTRUCTION_SHOOTDOWN_DISABLE);
7751b13d190SFrançois Tigeot 
7761b13d190SFrançois Tigeot 	/* Use Force Non-Coherent whenever executing a 3D context. This is a
7771b13d190SFrançois Tigeot 	 * workaround for for a possible hang in the unlikely event a TLB
7781b13d190SFrançois Tigeot 	 * invalidation occurs during a PSD flush.
7791b13d190SFrançois Tigeot 	 */
780352ff8bdSFrançois Tigeot 	/* WaForceEnableNonCoherent:bdw,chv */
781352ff8bdSFrançois Tigeot 	/* WaHdcDisableFetchWhenMasked:bdw,chv */
7822c9916cdSFrançois Tigeot 	WA_SET_BIT_MASKED(HDC_CHICKEN0,
7832c9916cdSFrançois Tigeot 			  HDC_DONOT_FETCH_MEM_WHEN_MASKED |
784352ff8bdSFrançois Tigeot 			  HDC_FORCE_NON_COHERENT);
7852c9916cdSFrançois Tigeot 
7862c9916cdSFrançois Tigeot 	/* From the Haswell PRM, Command Reference: Registers, CACHE_MODE_0:
7872c9916cdSFrançois Tigeot 	 * "The Hierarchical Z RAW Stall Optimization allows non-overlapping
7882c9916cdSFrançois Tigeot 	 *  polygons in the same 8x4 pixel/sample area to be processed without
7892c9916cdSFrançois Tigeot 	 *  stalling waiting for the earlier ones to write to Hierarchical Z
7902c9916cdSFrançois Tigeot 	 *  buffer."
7912c9916cdSFrançois Tigeot 	 *
792352ff8bdSFrançois Tigeot 	 * This optimization is off by default for BDW and CHV; turn it on.
7932c9916cdSFrançois Tigeot 	 */
7942c9916cdSFrançois Tigeot 	WA_CLR_BIT_MASKED(CACHE_MODE_0_GEN7, HIZ_RAW_STALL_OPT_DISABLE);
7951b13d190SFrançois Tigeot 
796352ff8bdSFrançois Tigeot 	/* Wa4x4STCOptimizationDisable:bdw,chv */
797352ff8bdSFrançois Tigeot 	WA_SET_BIT_MASKED(CACHE_MODE_1, GEN8_4x4_STC_OPTIMIZATION_DISABLE);
7981b13d190SFrançois Tigeot 
7991b13d190SFrançois Tigeot 	/*
8001b13d190SFrançois Tigeot 	 * BSpec recommends 8x4 when MSAA is used,
8011b13d190SFrançois Tigeot 	 * however in practice 16x4 seems fastest.
8021b13d190SFrançois Tigeot 	 *
8031b13d190SFrançois Tigeot 	 * Note that PS/WM thread counts depend on the WIZ hashing
8041b13d190SFrançois Tigeot 	 * disable bit, which we don't touch here, but it's good
8051b13d190SFrançois Tigeot 	 * to keep in mind (see 3DSTATE_PS and 3DSTATE_WM).
8061b13d190SFrançois Tigeot 	 */
8072c9916cdSFrançois Tigeot 	WA_SET_FIELD_MASKED(GEN7_GT_MODE,
8082c9916cdSFrançois Tigeot 			    GEN6_WIZ_HASHING_MASK,
8092c9916cdSFrançois Tigeot 			    GEN6_WIZ_HASHING_16x4);
8101b13d190SFrançois Tigeot 
8111b13d190SFrançois Tigeot 	return 0;
8121b13d190SFrançois Tigeot }
8131b13d190SFrançois Tigeot 
8148621f407SFrançois Tigeot static int bdw_init_workarounds(struct intel_engine_cs *engine)
8151b13d190SFrançois Tigeot {
8161487f786SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
817352ff8bdSFrançois Tigeot 	int ret;
8181b13d190SFrançois Tigeot 
8198621f407SFrançois Tigeot 	ret = gen8_init_workarounds(engine);
820352ff8bdSFrançois Tigeot 	if (ret)
821352ff8bdSFrançois Tigeot 		return ret;
822a05eeebfSFrançois Tigeot 
823352ff8bdSFrançois Tigeot 	/* WaDisableThreadStallDopClockGating:bdw (pre-production) */
824352ff8bdSFrançois Tigeot 	WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN, STALL_DOP_GATING_DISABLE);
825a05eeebfSFrançois Tigeot 
826352ff8bdSFrançois Tigeot 	/* WaDisableDopClockGating:bdw */
827352ff8bdSFrançois Tigeot 	WA_SET_BIT_MASKED(GEN7_ROW_CHICKEN2,
828352ff8bdSFrançois Tigeot 			  DOP_CLOCK_GATING_DISABLE);
8291b13d190SFrançois Tigeot 
830352ff8bdSFrançois Tigeot 	WA_SET_BIT_MASKED(HALF_SLICE_CHICKEN3,
831352ff8bdSFrançois Tigeot 			  GEN8_SAMPLER_POWER_BYPASS_DIS);
832352ff8bdSFrançois Tigeot 
8332c9916cdSFrançois Tigeot 	WA_SET_BIT_MASKED(HDC_CHICKEN0,
834352ff8bdSFrançois Tigeot 			  /* WaForceContextSaveRestoreNonCoherent:bdw */
835352ff8bdSFrançois Tigeot 			  HDC_FORCE_CONTEXT_SAVE_RESTORE_NON_COHERENT |
836352ff8bdSFrançois Tigeot 			  /* WaDisableFenceDestinationToSLM:bdw (pre-prod) */
8371487f786SFrançois Tigeot 			  (IS_BDW_GT3(dev_priv) ? HDC_FENCE_DEST_SLM_DISABLE : 0));
8381b13d190SFrançois Tigeot 
839352ff8bdSFrançois Tigeot 	return 0;
840352ff8bdSFrançois Tigeot }
8411b13d190SFrançois Tigeot 
8428621f407SFrançois Tigeot static int chv_init_workarounds(struct intel_engine_cs *engine)
843352ff8bdSFrançois Tigeot {
8441487f786SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
845352ff8bdSFrançois Tigeot 	int ret;
846352ff8bdSFrançois Tigeot 
8478621f407SFrançois Tigeot 	ret = gen8_init_workarounds(engine);
848352ff8bdSFrançois Tigeot 	if (ret)
849352ff8bdSFrançois Tigeot 		return ret;
850352ff8bdSFrançois Tigeot 
851352ff8bdSFrançois Tigeot 	/* WaDisableThreadStallDopClockGating:chv */
852352ff8bdSFrançois Tigeot 	WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN, STALL_DOP_GATING_DISABLE);
8532c9916cdSFrançois Tigeot 
8542c9916cdSFrançois Tigeot 	/* Improve HiZ throughput on CHV. */
8552c9916cdSFrançois Tigeot 	WA_SET_BIT_MASKED(HIZ_CHICKEN, CHV_HZ_8X8_MODE_IN_1X);
8562c9916cdSFrançois Tigeot 
8572c9916cdSFrançois Tigeot 	return 0;
8582c9916cdSFrançois Tigeot }
8592c9916cdSFrançois Tigeot 
8608621f407SFrançois Tigeot static int gen9_init_workarounds(struct intel_engine_cs *engine)
861477eb7f9SFrançois Tigeot {
8621487f786SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
863c0e85e96SFrançois Tigeot 	int ret;
864477eb7f9SFrançois Tigeot 
8658621f407SFrançois Tigeot 	/* WaConextSwitchWithConcurrentTLBInvalidate:skl,bxt,kbl */
8668621f407SFrançois Tigeot 	I915_WRITE(GEN9_CSFE_CHICKEN1_RCS, _MASKED_BIT_ENABLE(GEN9_PREEMPT_GPGPU_SYNC_SWITCH_DISABLE));
8678621f407SFrançois Tigeot 
8688621f407SFrançois Tigeot 	/* WaEnableLbsSlaRetryTimerDecrement:skl,bxt,kbl */
869352ff8bdSFrançois Tigeot 	I915_WRITE(BDW_SCRATCH1, I915_READ(BDW_SCRATCH1) |
870352ff8bdSFrançois Tigeot 		   GEN9_LBS_SLA_RETRY_TIMER_DECREMENT_ENABLE);
871352ff8bdSFrançois Tigeot 
8728621f407SFrançois Tigeot 	/* WaDisableKillLogic:bxt,skl,kbl */
873352ff8bdSFrançois Tigeot 	I915_WRITE(GAM_ECOCHK, I915_READ(GAM_ECOCHK) |
874352ff8bdSFrançois Tigeot 		   ECOCHK_DIS_TLB);
875352ff8bdSFrançois Tigeot 
8768621f407SFrançois Tigeot 	/* WaClearFlowControlGpgpuContextSave:skl,bxt,kbl */
8778621f407SFrançois Tigeot 	/* WaDisablePartialInstShootdown:skl,bxt,kbl */
878477eb7f9SFrançois Tigeot 	WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN,
8798621f407SFrançois Tigeot 			  FLOW_CONTROL_ENABLE |
880477eb7f9SFrançois Tigeot 			  PARTIAL_INSTRUCTION_SHOOTDOWN_DISABLE);
881477eb7f9SFrançois Tigeot 
8828621f407SFrançois Tigeot 	/* Syncing dependencies between camera and graphics:skl,bxt,kbl */
883477eb7f9SFrançois Tigeot 	WA_SET_BIT_MASKED(HALF_SLICE_CHICKEN3,
884477eb7f9SFrançois Tigeot 			  GEN9_DISABLE_OCL_OOB_SUPPRESS_LOGIC);
885477eb7f9SFrançois Tigeot 
88619c468b4SFrançois Tigeot 	/* WaDisableDgMirrorFixInHalfSliceChicken5:skl,bxt */
8871487f786SFrançois Tigeot 	if (IS_SKL_REVID(dev_priv, 0, SKL_REVID_B0) ||
8881487f786SFrançois Tigeot 	    IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1))
889477eb7f9SFrançois Tigeot 		WA_CLR_BIT_MASKED(GEN9_HALF_SLICE_CHICKEN5,
890477eb7f9SFrançois Tigeot 				  GEN9_DG_MIRROR_FIX_ENABLE);
891477eb7f9SFrançois Tigeot 
89219c468b4SFrançois Tigeot 	/* WaSetDisablePixMaskCammingAndRhwoInCommonSliceChicken:skl,bxt */
8931487f786SFrançois Tigeot 	if (IS_SKL_REVID(dev_priv, 0, SKL_REVID_B0) ||
8941487f786SFrançois Tigeot 	    IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1)) {
895477eb7f9SFrançois Tigeot 		WA_SET_BIT_MASKED(GEN7_COMMON_SLICE_CHICKEN1,
896477eb7f9SFrançois Tigeot 				  GEN9_RHWO_OPTIMIZATION_DISABLE);
897a05eeebfSFrançois Tigeot 		/*
898a05eeebfSFrançois Tigeot 		 * WA also requires GEN9_SLICE_COMMON_ECO_CHICKEN0[14:14] to be set
899a05eeebfSFrançois Tigeot 		 * but we do that in per ctx batchbuffer as there is an issue
900a05eeebfSFrançois Tigeot 		 * with this register not getting restored on ctx restore
901a05eeebfSFrançois Tigeot 		 */
902477eb7f9SFrançois Tigeot 	}
903477eb7f9SFrançois Tigeot 
9048621f407SFrançois Tigeot 	/* WaEnableYV12BugFixInHalfSliceChicken7:skl,bxt,kbl */
9058621f407SFrançois Tigeot 	/* WaEnableSamplerGPGPUPreemptionSupport:skl,bxt,kbl */
906477eb7f9SFrançois Tigeot 	WA_SET_BIT_MASKED(GEN9_HALF_SLICE_CHICKEN7,
9078621f407SFrançois Tigeot 			  GEN9_ENABLE_YV12_BUGFIX |
9088621f407SFrançois Tigeot 			  GEN9_ENABLE_GPGPU_PREEMPTION);
909477eb7f9SFrançois Tigeot 
9108621f407SFrançois Tigeot 	/* Wa4x4STCOptimizationDisable:skl,bxt,kbl */
9118621f407SFrançois Tigeot 	/* WaDisablePartialResolveInVc:skl,bxt,kbl */
912352ff8bdSFrançois Tigeot 	WA_SET_BIT_MASKED(CACHE_MODE_1, (GEN8_4x4_STC_OPTIMIZATION_DISABLE |
913352ff8bdSFrançois Tigeot 					 GEN9_PARTIAL_RESOLVE_IN_VC_DISABLE));
914477eb7f9SFrançois Tigeot 
9158621f407SFrançois Tigeot 	/* WaCcsTlbPrefetchDisable:skl,bxt,kbl */
916477eb7f9SFrançois Tigeot 	WA_CLR_BIT_MASKED(GEN9_HALF_SLICE_CHICKEN5,
917477eb7f9SFrançois Tigeot 			  GEN9_CCS_TLB_PREFETCH_ENABLE);
918477eb7f9SFrançois Tigeot 
91919c468b4SFrançois Tigeot 	/* WaDisableMaskBasedCammingInRCC:skl,bxt */
9201487f786SFrançois Tigeot 	if (IS_SKL_REVID(dev_priv, SKL_REVID_C0, SKL_REVID_C0) ||
9211487f786SFrançois Tigeot 	    IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1))
92219c468b4SFrançois Tigeot 		WA_SET_BIT_MASKED(SLICE_ECO_CHICKEN0,
92319c468b4SFrançois Tigeot 				  PIXEL_MASK_CAMMING_DISABLE);
92419c468b4SFrançois Tigeot 
9258621f407SFrançois Tigeot 	/* WaForceContextSaveRestoreNonCoherent:skl,bxt,kbl */
9268621f407SFrançois Tigeot 	WA_SET_BIT_MASKED(HDC_CHICKEN0,
9278621f407SFrançois Tigeot 			  HDC_FORCE_CONTEXT_SAVE_RESTORE_NON_COHERENT |
9288621f407SFrançois Tigeot 			  HDC_FORCE_CSR_NON_COHERENT_OVR_DISABLE);
92919c468b4SFrançois Tigeot 
9308621f407SFrançois Tigeot 	/* WaForceEnableNonCoherent and WaDisableHDCInvalidation are
9318621f407SFrançois Tigeot 	 * both tied to WaForceContextSaveRestoreNonCoherent
9328621f407SFrançois Tigeot 	 * in some hsds for skl. We keep the tie for all gen9. The
9338621f407SFrançois Tigeot 	 * documentation is a bit hazy and so we want to get common behaviour,
9348621f407SFrançois Tigeot 	 * even though there is no clear evidence we would need both on kbl/bxt.
9358621f407SFrançois Tigeot 	 * This area has been source of system hangs so we play it safe
9368621f407SFrançois Tigeot 	 * and mimic the skl regardless of what bspec says.
9378621f407SFrançois Tigeot 	 *
9388621f407SFrançois Tigeot 	 * Use Force Non-Coherent whenever executing a 3D context. This
9398621f407SFrançois Tigeot 	 * is a workaround for a possible hang in the unlikely event
9408621f407SFrançois Tigeot 	 * a TLB invalidation occurs during a PSD flush.
9418621f407SFrançois Tigeot 	 */
9428621f407SFrançois Tigeot 
9438621f407SFrançois Tigeot 	/* WaForceEnableNonCoherent:skl,bxt,kbl */
9448621f407SFrançois Tigeot 	WA_SET_BIT_MASKED(HDC_CHICKEN0,
9458621f407SFrançois Tigeot 			  HDC_FORCE_NON_COHERENT);
9468621f407SFrançois Tigeot 
9478621f407SFrançois Tigeot 	/* WaDisableHDCInvalidation:skl,bxt,kbl */
9488621f407SFrançois Tigeot 	I915_WRITE(GAM_ECOCHK, I915_READ(GAM_ECOCHK) |
9498621f407SFrançois Tigeot 		   BDW_DISABLE_HDC_INVALIDATION);
9508621f407SFrançois Tigeot 
9518621f407SFrançois Tigeot 	/* WaDisableSamplerPowerBypassForSOPingPong:skl,bxt,kbl */
9528621f407SFrançois Tigeot 	if (IS_SKYLAKE(dev_priv) ||
9538621f407SFrançois Tigeot 	    IS_KABYLAKE(dev_priv) ||
9548621f407SFrançois Tigeot 	    IS_BXT_REVID(dev_priv, 0, BXT_REVID_B0))
955352ff8bdSFrançois Tigeot 		WA_SET_BIT_MASKED(HALF_SLICE_CHICKEN3,
956352ff8bdSFrançois Tigeot 				  GEN8_SAMPLER_POWER_BYPASS_DIS);
957352ff8bdSFrançois Tigeot 
9588621f407SFrançois Tigeot 	/* WaDisableSTUnitPowerOptimization:skl,bxt,kbl */
959352ff8bdSFrançois Tigeot 	WA_SET_BIT_MASKED(HALF_SLICE_CHICKEN2, GEN8_ST_PO_DISABLE);
960352ff8bdSFrançois Tigeot 
9618621f407SFrançois Tigeot 	/* WaOCLCoherentLineFlush:skl,bxt,kbl */
962c0e85e96SFrançois Tigeot 	I915_WRITE(GEN8_L3SQCREG4, (I915_READ(GEN8_L3SQCREG4) |
963c0e85e96SFrançois Tigeot 				    GEN8_LQSC_FLUSH_COHERENT_LINES));
964c0e85e96SFrançois Tigeot 
9658621f407SFrançois Tigeot 	/* WaVFEStateAfterPipeControlwithMediaStateClear:skl,bxt */
9668621f407SFrançois Tigeot 	ret = wa_ring_whitelist_reg(engine, GEN9_CTX_PREEMPT_REG);
967c0e85e96SFrançois Tigeot 	if (ret)
968c0e85e96SFrançois Tigeot 		return ret;
969c0e85e96SFrançois Tigeot 
9708621f407SFrançois Tigeot 	/* WaEnablePreemptionGranularityControlByUMD:skl,bxt,kbl */
9718621f407SFrançois Tigeot 	ret= wa_ring_whitelist_reg(engine, GEN8_CS_CHICKEN1);
9728621f407SFrançois Tigeot 	if (ret)
9738621f407SFrançois Tigeot 		return ret;
9748621f407SFrançois Tigeot 
9758621f407SFrançois Tigeot 	/* WaAllowUMDToModifyHDCChicken1:skl,bxt,kbl */
9768621f407SFrançois Tigeot 	ret = wa_ring_whitelist_reg(engine, GEN8_HDC_CHICKEN1);
977c0e85e96SFrançois Tigeot 	if (ret)
978c0e85e96SFrançois Tigeot 		return ret;
979c0e85e96SFrançois Tigeot 
980477eb7f9SFrançois Tigeot 	return 0;
981477eb7f9SFrançois Tigeot }
982477eb7f9SFrançois Tigeot 
9838621f407SFrançois Tigeot static int skl_tune_iz_hashing(struct intel_engine_cs *engine)
984477eb7f9SFrançois Tigeot {
9851487f786SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
986477eb7f9SFrançois Tigeot 	u8 vals[3] = { 0, 0, 0 };
987477eb7f9SFrançois Tigeot 	unsigned int i;
988477eb7f9SFrançois Tigeot 
989477eb7f9SFrançois Tigeot 	for (i = 0; i < 3; i++) {
990477eb7f9SFrançois Tigeot 		u8 ss;
991477eb7f9SFrançois Tigeot 
992477eb7f9SFrançois Tigeot 		/*
993477eb7f9SFrançois Tigeot 		 * Only consider slices where one, and only one, subslice has 7
994477eb7f9SFrançois Tigeot 		 * EUs
995477eb7f9SFrançois Tigeot 		 */
996aee94f86SFrançois Tigeot 		if (!is_power_of_2(dev_priv->info.subslice_7eu[i]))
997477eb7f9SFrançois Tigeot 			continue;
998477eb7f9SFrançois Tigeot 
999477eb7f9SFrançois Tigeot 		/*
1000477eb7f9SFrançois Tigeot 		 * subslice_7eu[i] != 0 (because of the check above) and
1001477eb7f9SFrançois Tigeot 		 * ss_max == 4 (maximum number of subslices possible per slice)
1002477eb7f9SFrançois Tigeot 		 *
1003477eb7f9SFrançois Tigeot 		 * ->    0 <= ss <= 3;
1004477eb7f9SFrançois Tigeot 		 */
1005477eb7f9SFrançois Tigeot 		ss = ffs(dev_priv->info.subslice_7eu[i]) - 1;
1006477eb7f9SFrançois Tigeot 		vals[i] = 3 - ss;
1007477eb7f9SFrançois Tigeot 	}
1008477eb7f9SFrançois Tigeot 
1009477eb7f9SFrançois Tigeot 	if (vals[0] == 0 && vals[1] == 0 && vals[2] == 0)
1010477eb7f9SFrançois Tigeot 		return 0;
1011477eb7f9SFrançois Tigeot 
1012477eb7f9SFrançois Tigeot 	/* Tune IZ hashing. See intel_device_info_runtime_init() */
1013477eb7f9SFrançois Tigeot 	WA_SET_FIELD_MASKED(GEN7_GT_MODE,
1014477eb7f9SFrançois Tigeot 			    GEN9_IZ_HASHING_MASK(2) |
1015477eb7f9SFrançois Tigeot 			    GEN9_IZ_HASHING_MASK(1) |
1016477eb7f9SFrançois Tigeot 			    GEN9_IZ_HASHING_MASK(0),
1017477eb7f9SFrançois Tigeot 			    GEN9_IZ_HASHING(2, vals[2]) |
1018477eb7f9SFrançois Tigeot 			    GEN9_IZ_HASHING(1, vals[1]) |
1019477eb7f9SFrançois Tigeot 			    GEN9_IZ_HASHING(0, vals[0]));
1020477eb7f9SFrançois Tigeot 
1021477eb7f9SFrançois Tigeot 	return 0;
1022477eb7f9SFrançois Tigeot }
1023477eb7f9SFrançois Tigeot 
10248621f407SFrançois Tigeot static int skl_init_workarounds(struct intel_engine_cs *engine)
1025477eb7f9SFrançois Tigeot {
10261487f786SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
1027352ff8bdSFrançois Tigeot 	int ret;
1028477eb7f9SFrançois Tigeot 
10298621f407SFrançois Tigeot 	ret = gen9_init_workarounds(engine);
1030352ff8bdSFrançois Tigeot 	if (ret)
1031352ff8bdSFrançois Tigeot 		return ret;
1032352ff8bdSFrançois Tigeot 
1033c0e85e96SFrançois Tigeot 	/*
1034c0e85e96SFrançois Tigeot 	 * Actual WA is to disable percontext preemption granularity control
1035c0e85e96SFrançois Tigeot 	 * until D0 which is the default case so this is equivalent to
1036c0e85e96SFrançois Tigeot 	 * !WaDisablePerCtxtPreemptionGranularityControl:skl
1037c0e85e96SFrançois Tigeot 	 */
10381487f786SFrançois Tigeot 	if (IS_SKL_REVID(dev_priv, SKL_REVID_E0, REVID_FOREVER)) {
1039c0e85e96SFrançois Tigeot 		I915_WRITE(GEN7_FF_SLICE_CS_CHICKEN1,
1040c0e85e96SFrançois Tigeot 			   _MASKED_BIT_ENABLE(GEN9_FFSC_PERCTX_PREEMPT_CTRL));
1041c0e85e96SFrançois Tigeot 	}
1042c0e85e96SFrançois Tigeot 
10431487f786SFrançois Tigeot 	if (IS_SKL_REVID(dev_priv, 0, SKL_REVID_E0)) {
1044352ff8bdSFrançois Tigeot 		/* WaDisableChickenBitTSGBarrierAckForFFSliceCS:skl */
1045352ff8bdSFrançois Tigeot 		I915_WRITE(FF_SLICE_CS_CHICKEN2,
1046352ff8bdSFrançois Tigeot 			   _MASKED_BIT_ENABLE(GEN9_TSG_BARRIER_ACK_DISABLE));
1047352ff8bdSFrançois Tigeot 	}
1048352ff8bdSFrançois Tigeot 
1049352ff8bdSFrançois Tigeot 	/* GEN8_L3SQCREG4 has a dependency with WA batch so any new changes
1050352ff8bdSFrançois Tigeot 	 * involving this register should also be added to WA batch as required.
1051352ff8bdSFrançois Tigeot 	 */
10521487f786SFrançois Tigeot 	if (IS_SKL_REVID(dev_priv, 0, SKL_REVID_E0))
1053352ff8bdSFrançois Tigeot 		/* WaDisableLSQCROPERFforOCL:skl */
1054352ff8bdSFrançois Tigeot 		I915_WRITE(GEN8_L3SQCREG4, I915_READ(GEN8_L3SQCREG4) |
1055352ff8bdSFrançois Tigeot 			   GEN8_LQSC_RO_PERF_DIS);
1056352ff8bdSFrançois Tigeot 
1057352ff8bdSFrançois Tigeot 	/* WaEnableGapsTsvCreditFix:skl */
10581487f786SFrançois Tigeot 	if (IS_SKL_REVID(dev_priv, SKL_REVID_C0, REVID_FOREVER)) {
1059352ff8bdSFrançois Tigeot 		I915_WRITE(GEN8_GARBCNTL, (I915_READ(GEN8_GARBCNTL) |
1060352ff8bdSFrançois Tigeot 					   GEN9_GAPS_TSV_CREDIT_DISABLE));
1061352ff8bdSFrançois Tigeot 	}
1062477eb7f9SFrançois Tigeot 
1063477eb7f9SFrançois Tigeot 	/* WaDisablePowerCompilerClockGating:skl */
10641487f786SFrançois Tigeot 	if (IS_SKL_REVID(dev_priv, SKL_REVID_B0, SKL_REVID_B0))
1065477eb7f9SFrançois Tigeot 		WA_SET_BIT_MASKED(HIZ_CHICKEN,
1066477eb7f9SFrançois Tigeot 				  BDW_HIZ_POWER_COMPILER_CLOCK_GATING_DISABLE);
1067477eb7f9SFrançois Tigeot 
1068a05eeebfSFrançois Tigeot 	/* WaBarrierPerformanceFixDisable:skl */
10691487f786SFrançois Tigeot 	if (IS_SKL_REVID(dev_priv, SKL_REVID_C0, SKL_REVID_D0))
1070a05eeebfSFrançois Tigeot 		WA_SET_BIT_MASKED(HDC_CHICKEN0,
1071a05eeebfSFrançois Tigeot 				  HDC_FENCE_DEST_SLM_DISABLE |
1072a05eeebfSFrançois Tigeot 				  HDC_BARRIER_PERFORMANCE_DISABLE);
1073a05eeebfSFrançois Tigeot 
1074a05eeebfSFrançois Tigeot 	/* WaDisableSbeCacheDispatchPortSharing:skl */
10751487f786SFrançois Tigeot 	if (IS_SKL_REVID(dev_priv, 0, SKL_REVID_F0))
1076a05eeebfSFrançois Tigeot 		WA_SET_BIT_MASKED(
1077a05eeebfSFrançois Tigeot 			GEN7_HALF_SLICE_CHICKEN1,
1078a05eeebfSFrançois Tigeot 			GEN7_SBE_SS_CACHE_DISPATCH_PORT_SHARING_DISABLE);
1079a05eeebfSFrançois Tigeot 
10808621f407SFrançois Tigeot 	/* WaDisableGafsUnitClkGating:skl */
10818621f407SFrançois Tigeot 	WA_SET_BIT(GEN7_UCGCTL4, GEN8_EU_GAUNIT_CLOCK_GATE_DISABLE);
10828621f407SFrançois Tigeot 
1083bf017597SFrançois Tigeot 	/* WaInPlaceDecompressionHang:skl */
1084bf017597SFrançois Tigeot 	if (IS_SKL_REVID(dev_priv, SKL_REVID_H0, REVID_FOREVER))
1085bf017597SFrançois Tigeot 		WA_SET_BIT(GEN9_GAMT_ECO_REG_RW_IA,
1086bf017597SFrançois Tigeot 			   GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS);
1087bf017597SFrançois Tigeot 
1088c0e85e96SFrançois Tigeot 	/* WaDisableLSQCROPERFforOCL:skl */
10898621f407SFrançois Tigeot 	ret = wa_ring_whitelist_reg(engine, GEN8_L3SQCREG4);
1090c0e85e96SFrançois Tigeot 	if (ret)
1091c0e85e96SFrançois Tigeot 		return ret;
1092c0e85e96SFrançois Tigeot 
10938621f407SFrançois Tigeot 	return skl_tune_iz_hashing(engine);
1094477eb7f9SFrançois Tigeot }
1095477eb7f9SFrançois Tigeot 
10968621f407SFrançois Tigeot static int bxt_init_workarounds(struct intel_engine_cs *engine)
109719c468b4SFrançois Tigeot {
10981487f786SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
1099352ff8bdSFrançois Tigeot 	int ret;
110019c468b4SFrançois Tigeot 
11018621f407SFrançois Tigeot 	ret = gen9_init_workarounds(engine);
1102352ff8bdSFrançois Tigeot 	if (ret)
1103352ff8bdSFrançois Tigeot 		return ret;
1104352ff8bdSFrançois Tigeot 
1105352ff8bdSFrançois Tigeot 	/* WaStoreMultiplePTEenable:bxt */
1106352ff8bdSFrançois Tigeot 	/* This is a requirement according to Hardware specification */
11071487f786SFrançois Tigeot 	if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1))
1108352ff8bdSFrançois Tigeot 		I915_WRITE(TILECTL, I915_READ(TILECTL) | TILECTL_TLBPF);
1109352ff8bdSFrançois Tigeot 
1110352ff8bdSFrançois Tigeot 	/* WaSetClckGatingDisableMedia:bxt */
11111487f786SFrançois Tigeot 	if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1)) {
1112352ff8bdSFrançois Tigeot 		I915_WRITE(GEN7_MISCCPCTL, (I915_READ(GEN7_MISCCPCTL) &
1113352ff8bdSFrançois Tigeot 					    ~GEN8_DOP_CLOCK_GATE_MEDIA_ENABLE));
1114352ff8bdSFrançois Tigeot 	}
111519c468b4SFrançois Tigeot 
111619c468b4SFrançois Tigeot 	/* WaDisableThreadStallDopClockGating:bxt */
111719c468b4SFrançois Tigeot 	WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN,
111819c468b4SFrançois Tigeot 			  STALL_DOP_GATING_DISABLE);
111919c468b4SFrançois Tigeot 
11201487f786SFrançois Tigeot 	/* WaDisablePooledEuLoadBalancingFix:bxt */
11211487f786SFrançois Tigeot 	if (IS_BXT_REVID(dev_priv, BXT_REVID_B0, REVID_FOREVER)) {
11221487f786SFrançois Tigeot 		WA_SET_BIT_MASKED(FF_SLICE_CS_CHICKEN2,
11231487f786SFrançois Tigeot 				  GEN9_POOLED_EU_LOAD_BALANCING_FIX_DISABLE);
11241487f786SFrançois Tigeot 	}
11251487f786SFrançois Tigeot 
112619c468b4SFrançois Tigeot 	/* WaDisableSbeCacheDispatchPortSharing:bxt */
11271487f786SFrançois Tigeot 	if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_B0)) {
112819c468b4SFrançois Tigeot 		WA_SET_BIT_MASKED(
112919c468b4SFrançois Tigeot 			GEN7_HALF_SLICE_CHICKEN1,
113019c468b4SFrançois Tigeot 			GEN7_SBE_SS_CACHE_DISPATCH_PORT_SHARING_DISABLE);
113119c468b4SFrançois Tigeot 	}
113219c468b4SFrançois Tigeot 
1133c0e85e96SFrançois Tigeot 	/* WaDisableObjectLevelPreemptionForTrifanOrPolygon:bxt */
1134c0e85e96SFrançois Tigeot 	/* WaDisableObjectLevelPreemptionForInstancedDraw:bxt */
1135c0e85e96SFrançois Tigeot 	/* WaDisableObjectLevelPreemtionForInstanceId:bxt */
1136c0e85e96SFrançois Tigeot 	/* WaDisableLSQCROPERFforOCL:bxt */
11371487f786SFrançois Tigeot 	if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1)) {
11388621f407SFrançois Tigeot 		ret = wa_ring_whitelist_reg(engine, GEN9_CS_DEBUG_MODE1);
1139c0e85e96SFrançois Tigeot 		if (ret)
1140c0e85e96SFrançois Tigeot 			return ret;
1141c0e85e96SFrançois Tigeot 
11428621f407SFrançois Tigeot 		ret = wa_ring_whitelist_reg(engine, GEN8_L3SQCREG4);
1143c0e85e96SFrançois Tigeot 		if (ret)
1144c0e85e96SFrançois Tigeot 			return ret;
1145c0e85e96SFrançois Tigeot 	}
1146c0e85e96SFrançois Tigeot 
11471487f786SFrançois Tigeot 	/* WaProgramL3SqcReg1DefaultForPerf:bxt */
11481487f786SFrançois Tigeot 	if (IS_BXT_REVID(dev_priv, BXT_REVID_B0, REVID_FOREVER))
11491487f786SFrançois Tigeot 		I915_WRITE(GEN8_L3SQCREG1, L3_GENERAL_PRIO_CREDITS(62) |
11501487f786SFrançois Tigeot 					   L3_HIGH_PRIO_CREDITS(2));
11511487f786SFrançois Tigeot 
1152bf017597SFrançois Tigeot 	/* WaToEnableHwFixForPushConstHWBug:bxt */
1153bf017597SFrançois Tigeot 	if (IS_BXT_REVID(dev_priv, BXT_REVID_C0, REVID_FOREVER))
11548621f407SFrançois Tigeot 		WA_SET_BIT_MASKED(COMMON_SLICE_CHICKEN2,
11558621f407SFrançois Tigeot 				  GEN8_SBE_DISABLE_REPLAY_BUF_OPTIMIZATION);
11568621f407SFrançois Tigeot 
1157bf017597SFrançois Tigeot 	/* WaInPlaceDecompressionHang:bxt */
1158bf017597SFrançois Tigeot 	if (IS_BXT_REVID(dev_priv, BXT_REVID_C0, REVID_FOREVER))
1159bf017597SFrançois Tigeot 		WA_SET_BIT(GEN9_GAMT_ECO_REG_RW_IA,
1160bf017597SFrançois Tigeot 			   GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS);
1161bf017597SFrançois Tigeot 
116219c468b4SFrançois Tigeot 	return 0;
116319c468b4SFrançois Tigeot }
116419c468b4SFrançois Tigeot 
11658621f407SFrançois Tigeot static int kbl_init_workarounds(struct intel_engine_cs *engine)
11662c9916cdSFrançois Tigeot {
11671487f786SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
11688621f407SFrançois Tigeot 	int ret;
11698621f407SFrançois Tigeot 
11708621f407SFrançois Tigeot 	ret = gen9_init_workarounds(engine);
11718621f407SFrançois Tigeot 	if (ret)
11728621f407SFrançois Tigeot 		return ret;
11738621f407SFrançois Tigeot 
11748621f407SFrançois Tigeot 	/* WaEnableGapsTsvCreditFix:kbl */
11758621f407SFrançois Tigeot 	I915_WRITE(GEN8_GARBCNTL, (I915_READ(GEN8_GARBCNTL) |
11768621f407SFrançois Tigeot 				   GEN9_GAPS_TSV_CREDIT_DISABLE));
11778621f407SFrançois Tigeot 
11788621f407SFrançois Tigeot 	/* WaDisableDynamicCreditSharing:kbl */
11798621f407SFrançois Tigeot 	if (IS_KBL_REVID(dev_priv, 0, KBL_REVID_B0))
11808621f407SFrançois Tigeot 		WA_SET_BIT(GAMT_CHKN_BIT_REG,
11818621f407SFrançois Tigeot 			   GAMT_CHKN_DISABLE_DYNAMIC_CREDIT_SHARING);
11828621f407SFrançois Tigeot 
11838621f407SFrançois Tigeot 	/* WaDisableFenceDestinationToSLM:kbl (pre-prod) */
11848621f407SFrançois Tigeot 	if (IS_KBL_REVID(dev_priv, KBL_REVID_A0, KBL_REVID_A0))
11858621f407SFrançois Tigeot 		WA_SET_BIT_MASKED(HDC_CHICKEN0,
11868621f407SFrançois Tigeot 				  HDC_FENCE_DEST_SLM_DISABLE);
11878621f407SFrançois Tigeot 
11888621f407SFrançois Tigeot 	/* GEN8_L3SQCREG4 has a dependency with WA batch so any new changes
11898621f407SFrançois Tigeot 	 * involving this register should also be added to WA batch as required.
11908621f407SFrançois Tigeot 	 */
11918621f407SFrançois Tigeot 	if (IS_KBL_REVID(dev_priv, 0, KBL_REVID_E0))
11928621f407SFrançois Tigeot 		/* WaDisableLSQCROPERFforOCL:kbl */
11938621f407SFrançois Tigeot 		I915_WRITE(GEN8_L3SQCREG4, I915_READ(GEN8_L3SQCREG4) |
11948621f407SFrançois Tigeot 			   GEN8_LQSC_RO_PERF_DIS);
11958621f407SFrançois Tigeot 
1196bf017597SFrançois Tigeot 	/* WaToEnableHwFixForPushConstHWBug:kbl */
1197bf017597SFrançois Tigeot 	if (IS_KBL_REVID(dev_priv, KBL_REVID_C0, REVID_FOREVER))
11988621f407SFrançois Tigeot 		WA_SET_BIT_MASKED(COMMON_SLICE_CHICKEN2,
11998621f407SFrançois Tigeot 				  GEN8_SBE_DISABLE_REPLAY_BUF_OPTIMIZATION);
12008621f407SFrançois Tigeot 
12018621f407SFrançois Tigeot 	/* WaDisableGafsUnitClkGating:kbl */
12028621f407SFrançois Tigeot 	WA_SET_BIT(GEN7_UCGCTL4, GEN8_EU_GAUNIT_CLOCK_GATE_DISABLE);
12038621f407SFrançois Tigeot 
12048621f407SFrançois Tigeot 	/* WaDisableSbeCacheDispatchPortSharing:kbl */
12058621f407SFrançois Tigeot 	WA_SET_BIT_MASKED(
12068621f407SFrançois Tigeot 		GEN7_HALF_SLICE_CHICKEN1,
12078621f407SFrançois Tigeot 		GEN7_SBE_SS_CACHE_DISPATCH_PORT_SHARING_DISABLE);
12088621f407SFrançois Tigeot 
1209bf017597SFrançois Tigeot 	/* WaInPlaceDecompressionHang:kbl */
1210bf017597SFrançois Tigeot 	WA_SET_BIT(GEN9_GAMT_ECO_REG_RW_IA,
1211bf017597SFrançois Tigeot 		   GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS);
1212bf017597SFrançois Tigeot 
12138621f407SFrançois Tigeot 	/* WaDisableLSQCROPERFforOCL:kbl */
12148621f407SFrançois Tigeot 	ret = wa_ring_whitelist_reg(engine, GEN8_L3SQCREG4);
12158621f407SFrançois Tigeot 	if (ret)
12168621f407SFrançois Tigeot 		return ret;
12178621f407SFrançois Tigeot 
12188621f407SFrançois Tigeot 	return 0;
12198621f407SFrançois Tigeot }
12208621f407SFrançois Tigeot 
12218621f407SFrançois Tigeot int init_workarounds_ring(struct intel_engine_cs *engine)
12228621f407SFrançois Tigeot {
12231487f786SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
12242c9916cdSFrançois Tigeot 
12258621f407SFrançois Tigeot 	WARN_ON(engine->id != RCS);
12262c9916cdSFrançois Tigeot 
12272c9916cdSFrançois Tigeot 	dev_priv->workarounds.count = 0;
1228c0e85e96SFrançois Tigeot 	dev_priv->workarounds.hw_whitelist_count[RCS] = 0;
12292c9916cdSFrançois Tigeot 
12301487f786SFrançois Tigeot 	if (IS_BROADWELL(dev_priv))
12318621f407SFrançois Tigeot 		return bdw_init_workarounds(engine);
12322c9916cdSFrançois Tigeot 
12331487f786SFrançois Tigeot 	if (IS_CHERRYVIEW(dev_priv))
12348621f407SFrançois Tigeot 		return chv_init_workarounds(engine);
12351b13d190SFrançois Tigeot 
12361487f786SFrançois Tigeot 	if (IS_SKYLAKE(dev_priv))
12378621f407SFrançois Tigeot 		return skl_init_workarounds(engine);
123819c468b4SFrançois Tigeot 
12391487f786SFrançois Tigeot 	if (IS_BROXTON(dev_priv))
12408621f407SFrançois Tigeot 		return bxt_init_workarounds(engine);
12418621f407SFrançois Tigeot 
12428621f407SFrançois Tigeot 	if (IS_KABYLAKE(dev_priv))
12438621f407SFrançois Tigeot 		return kbl_init_workarounds(engine);
1244477eb7f9SFrançois Tigeot 
12451b13d190SFrançois Tigeot 	return 0;
12461b13d190SFrançois Tigeot }
12471b13d190SFrançois Tigeot 
12488621f407SFrançois Tigeot static int init_render_ring(struct intel_engine_cs *engine)
1249e3adcf8fSFrançois Tigeot {
12501487f786SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
12518621f407SFrançois Tigeot 	int ret = init_ring_common(engine);
125224edb884SFrançois Tigeot 	if (ret)
125324edb884SFrançois Tigeot 		return ret;
1254e3adcf8fSFrançois Tigeot 
1255ba55f2f5SFrançois Tigeot 	/* WaTimedSingleVertexDispatch:cl,bw,ctg,elk,ilk,snb */
12561487f786SFrançois Tigeot 	if (IS_GEN(dev_priv, 4, 6))
1257f4e1c372SFrançois Tigeot 		I915_WRITE(MI_MODE, _MASKED_BIT_ENABLE(VS_TIMER_DISPATCH));
1258f4e1c372SFrançois Tigeot 
1259f4e1c372SFrançois Tigeot 	/* We need to disable the AsyncFlip performance optimisations in order
1260f4e1c372SFrançois Tigeot 	 * to use MI_WAIT_FOR_EVENT within the CS. It should already be
1261f4e1c372SFrançois Tigeot 	 * programmed to '1' on all products.
12625d0b1887SFrançois Tigeot 	 *
1263a05eeebfSFrançois Tigeot 	 * WaDisableAsyncFlipPerfMode:snb,ivb,hsw,vlv
1264f4e1c372SFrançois Tigeot 	 */
12651487f786SFrançois Tigeot 	if (IS_GEN(dev_priv, 6, 7))
1266f4e1c372SFrançois Tigeot 		I915_WRITE(MI_MODE, _MASKED_BIT_ENABLE(ASYNC_FLIP_PERF_DISABLE));
1267f4e1c372SFrançois Tigeot 
1268f4e1c372SFrançois Tigeot 	/* Required for the hardware to program scanline values for waiting */
1269ba55f2f5SFrançois Tigeot 	/* WaEnableFlushTlbInvalidationMode:snb */
12701487f786SFrançois Tigeot 	if (IS_GEN6(dev_priv))
1271f4e1c372SFrançois Tigeot 		I915_WRITE(GFX_MODE,
1272ba55f2f5SFrançois Tigeot 			   _MASKED_BIT_ENABLE(GFX_TLB_INVALIDATE_EXPLICIT));
1273f4e1c372SFrançois Tigeot 
1274ba55f2f5SFrançois Tigeot 	/* WaBCSVCSTlbInvalidationMode:ivb,vlv,hsw */
12751487f786SFrançois Tigeot 	if (IS_GEN7(dev_priv))
1276e3adcf8fSFrançois Tigeot 		I915_WRITE(GFX_MODE_GEN7,
1277ba55f2f5SFrançois Tigeot 			   _MASKED_BIT_ENABLE(GFX_TLB_INVALIDATE_EXPLICIT) |
1278f4e1c372SFrançois Tigeot 			   _MASKED_BIT_ENABLE(GFX_REPLAY_MODE));
1279e3adcf8fSFrançois Tigeot 
12801487f786SFrançois Tigeot 	if (IS_GEN6(dev_priv)) {
1281e3adcf8fSFrançois Tigeot 		/* From the Sandybridge PRM, volume 1 part 3, page 24:
1282e3adcf8fSFrançois Tigeot 		 * "If this bit is set, STCunit will have LRA as replacement
1283e3adcf8fSFrançois Tigeot 		 *  policy. [...] This bit must be reset.  LRA replacement
1284e3adcf8fSFrançois Tigeot 		 *  policy is not supported."
1285e3adcf8fSFrançois Tigeot 		 */
1286e3adcf8fSFrançois Tigeot 		I915_WRITE(CACHE_MODE_0,
1287f4e1c372SFrançois Tigeot 			   _MASKED_BIT_DISABLE(CM0_STC_EVICT_DISABLE_LRA_SNB));
1288e3adcf8fSFrançois Tigeot 	}
1289e3adcf8fSFrançois Tigeot 
12901487f786SFrançois Tigeot 	if (IS_GEN(dev_priv, 6, 7))
1291f4e1c372SFrançois Tigeot 		I915_WRITE(INSTPM, _MASKED_BIT_ENABLE(INSTPM_FORCE_ORDERING));
1292f4e1c372SFrançois Tigeot 
1293303bf270SFrançois Tigeot 	if (INTEL_INFO(dev_priv)->gen >= 6)
1294303bf270SFrançois Tigeot 		I915_WRITE_IMR(engine, ~engine->irq_keep_mask);
1295e3adcf8fSFrançois Tigeot 
12968621f407SFrançois Tigeot 	return init_workarounds_ring(engine);
1297e3adcf8fSFrançois Tigeot }
1298e3adcf8fSFrançois Tigeot 
12998621f407SFrançois Tigeot static void render_ring_cleanup(struct intel_engine_cs *engine)
1300e3adcf8fSFrançois Tigeot {
13011487f786SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
130224edb884SFrançois Tigeot 
130324edb884SFrançois Tigeot 	if (dev_priv->semaphore_obj) {
130424edb884SFrançois Tigeot 		i915_gem_object_ggtt_unpin(dev_priv->semaphore_obj);
130587df8fc6SFrançois Tigeot 		i915_gem_object_put(dev_priv->semaphore_obj);
130624edb884SFrançois Tigeot 		dev_priv->semaphore_obj = NULL;
130724edb884SFrançois Tigeot 	}
1308b5c29a34SFrançois Tigeot 
13098621f407SFrançois Tigeot 	intel_fini_pipe_control(engine);
1310e3adcf8fSFrançois Tigeot }
1311e3adcf8fSFrançois Tigeot 
1312*71f41f3eSFrançois Tigeot static int gen8_rcs_signal(struct drm_i915_gem_request *req)
131324edb884SFrançois Tigeot {
1314*71f41f3eSFrançois Tigeot 	struct intel_ring *ring = req->ring;
1315*71f41f3eSFrançois Tigeot 	struct drm_i915_private *dev_priv = req->i915;
131624edb884SFrançois Tigeot 	struct intel_engine_cs *waiter;
13178621f407SFrançois Tigeot 	enum intel_engine_id id;
13188621f407SFrançois Tigeot 	int ret, num_rings;
131924edb884SFrançois Tigeot 
13201487f786SFrançois Tigeot 	num_rings = hweight32(INTEL_INFO(dev_priv)->ring_mask);
1321*71f41f3eSFrançois Tigeot 	ret = intel_ring_begin(req, (num_rings-1) * 8);
132224edb884SFrançois Tigeot 	if (ret)
132324edb884SFrançois Tigeot 		return ret;
132424edb884SFrançois Tigeot 
13258621f407SFrançois Tigeot 	for_each_engine_id(waiter, dev_priv, id) {
1326*71f41f3eSFrançois Tigeot 		u64 gtt_offset = req->engine->semaphore.signal_ggtt[id];
132724edb884SFrançois Tigeot 		if (gtt_offset == MI_SEMAPHORE_SYNC_INVALID)
132824edb884SFrançois Tigeot 			continue;
132924edb884SFrançois Tigeot 
1330*71f41f3eSFrançois Tigeot 		intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(6));
1331*71f41f3eSFrançois Tigeot 		intel_ring_emit(ring,
1332*71f41f3eSFrançois Tigeot 				PIPE_CONTROL_GLOBAL_GTT_IVB |
133324edb884SFrançois Tigeot 				PIPE_CONTROL_QW_WRITE |
13341487f786SFrançois Tigeot 				PIPE_CONTROL_CS_STALL);
1335*71f41f3eSFrançois Tigeot 		intel_ring_emit(ring, lower_32_bits(gtt_offset));
1336*71f41f3eSFrançois Tigeot 		intel_ring_emit(ring, upper_32_bits(gtt_offset));
1337*71f41f3eSFrançois Tigeot 		intel_ring_emit(ring, req->fence.seqno);
1338*71f41f3eSFrançois Tigeot 		intel_ring_emit(ring, 0);
1339*71f41f3eSFrançois Tigeot 		intel_ring_emit(ring,
1340*71f41f3eSFrançois Tigeot 				MI_SEMAPHORE_SIGNAL |
13418621f407SFrançois Tigeot 				MI_SEMAPHORE_TARGET(waiter->hw_id));
1342*71f41f3eSFrançois Tigeot 		intel_ring_emit(ring, 0);
134324edb884SFrançois Tigeot 	}
1344*71f41f3eSFrançois Tigeot 	intel_ring_advance(ring);
134524edb884SFrançois Tigeot 
134624edb884SFrançois Tigeot 	return 0;
134724edb884SFrançois Tigeot }
134824edb884SFrançois Tigeot 
1349*71f41f3eSFrançois Tigeot static int gen8_xcs_signal(struct drm_i915_gem_request *req)
135024edb884SFrançois Tigeot {
1351*71f41f3eSFrançois Tigeot 	struct intel_ring *ring = req->ring;
1352*71f41f3eSFrançois Tigeot 	struct drm_i915_private *dev_priv = req->i915;
135324edb884SFrançois Tigeot 	struct intel_engine_cs *waiter;
13548621f407SFrançois Tigeot 	enum intel_engine_id id;
13558621f407SFrançois Tigeot 	int ret, num_rings;
135624edb884SFrançois Tigeot 
13571487f786SFrançois Tigeot 	num_rings = hweight32(INTEL_INFO(dev_priv)->ring_mask);
1358*71f41f3eSFrançois Tigeot 	ret = intel_ring_begin(req, (num_rings-1) * 6);
135924edb884SFrançois Tigeot 	if (ret)
136024edb884SFrançois Tigeot 		return ret;
136124edb884SFrançois Tigeot 
13628621f407SFrançois Tigeot 	for_each_engine_id(waiter, dev_priv, id) {
1363*71f41f3eSFrançois Tigeot 		u64 gtt_offset = req->engine->semaphore.signal_ggtt[id];
136424edb884SFrançois Tigeot 		if (gtt_offset == MI_SEMAPHORE_SYNC_INVALID)
136524edb884SFrançois Tigeot 			continue;
136624edb884SFrançois Tigeot 
1367*71f41f3eSFrançois Tigeot 		intel_ring_emit(ring,
1368*71f41f3eSFrançois Tigeot 				(MI_FLUSH_DW + 1) | MI_FLUSH_DW_OP_STOREDW);
1369*71f41f3eSFrançois Tigeot 		intel_ring_emit(ring,
1370*71f41f3eSFrançois Tigeot 				lower_32_bits(gtt_offset) |
137124edb884SFrançois Tigeot 				MI_FLUSH_DW_USE_GTT);
1372*71f41f3eSFrançois Tigeot 		intel_ring_emit(ring, upper_32_bits(gtt_offset));
1373*71f41f3eSFrançois Tigeot 		intel_ring_emit(ring, req->fence.seqno);
1374*71f41f3eSFrançois Tigeot 		intel_ring_emit(ring,
1375*71f41f3eSFrançois Tigeot 				MI_SEMAPHORE_SIGNAL |
13768621f407SFrançois Tigeot 				MI_SEMAPHORE_TARGET(waiter->hw_id));
1377*71f41f3eSFrançois Tigeot 		intel_ring_emit(ring, 0);
137824edb884SFrançois Tigeot 	}
1379*71f41f3eSFrançois Tigeot 	intel_ring_advance(ring);
138024edb884SFrançois Tigeot 
138124edb884SFrançois Tigeot 	return 0;
138224edb884SFrançois Tigeot }
138324edb884SFrançois Tigeot 
1384*71f41f3eSFrançois Tigeot static int gen6_signal(struct drm_i915_gem_request *req)
1385e3adcf8fSFrançois Tigeot {
1386*71f41f3eSFrançois Tigeot 	struct intel_ring *ring = req->ring;
1387*71f41f3eSFrançois Tigeot 	struct drm_i915_private *dev_priv = req->i915;
1388ba55f2f5SFrançois Tigeot 	struct intel_engine_cs *useless;
13898621f407SFrançois Tigeot 	enum intel_engine_id id;
13908621f407SFrançois Tigeot 	int ret, num_rings;
1391ba55f2f5SFrançois Tigeot 
13921487f786SFrançois Tigeot 	num_rings = hweight32(INTEL_INFO(dev_priv)->ring_mask);
1393*71f41f3eSFrançois Tigeot 	ret = intel_ring_begin(req, round_up((num_rings-1) * 3, 2));
1394ba55f2f5SFrançois Tigeot 	if (ret)
1395ba55f2f5SFrançois Tigeot 		return ret;
1396ba55f2f5SFrançois Tigeot 
13978621f407SFrançois Tigeot 	for_each_engine_id(useless, dev_priv, id) {
1398*71f41f3eSFrançois Tigeot 		i915_reg_t mbox_reg = req->engine->semaphore.mbox.signal[id];
1399aee94f86SFrançois Tigeot 
1400aee94f86SFrançois Tigeot 		if (i915_mmio_reg_valid(mbox_reg)) {
1401*71f41f3eSFrançois Tigeot 			intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1));
1402*71f41f3eSFrançois Tigeot 			intel_ring_emit_reg(ring, mbox_reg);
1403*71f41f3eSFrançois Tigeot 			intel_ring_emit(ring, req->fence.seqno);
1404ba55f2f5SFrançois Tigeot 		}
1405ba55f2f5SFrançois Tigeot 	}
1406ba55f2f5SFrançois Tigeot 
140724edb884SFrançois Tigeot 	/* If num_dwords was rounded, make sure the tail pointer is correct */
140824edb884SFrançois Tigeot 	if (num_rings % 2 == 0)
1409*71f41f3eSFrançois Tigeot 		intel_ring_emit(ring, MI_NOOP);
1410*71f41f3eSFrançois Tigeot 	intel_ring_advance(ring);
1411*71f41f3eSFrançois Tigeot 
1412*71f41f3eSFrançois Tigeot 	return 0;
1413*71f41f3eSFrançois Tigeot }
1414*71f41f3eSFrançois Tigeot 
1415*71f41f3eSFrançois Tigeot static void i9xx_submit_request(struct drm_i915_gem_request *request)
1416*71f41f3eSFrançois Tigeot {
1417*71f41f3eSFrançois Tigeot 	struct drm_i915_private *dev_priv = request->i915;
1418*71f41f3eSFrançois Tigeot 
1419*71f41f3eSFrançois Tigeot 	I915_WRITE_TAIL(request->engine,
1420*71f41f3eSFrançois Tigeot 			intel_ring_offset(request->ring, request->tail));
1421*71f41f3eSFrançois Tigeot }
1422*71f41f3eSFrançois Tigeot 
1423*71f41f3eSFrançois Tigeot static int i9xx_emit_request(struct drm_i915_gem_request *req)
1424*71f41f3eSFrançois Tigeot {
1425*71f41f3eSFrançois Tigeot 	struct intel_ring *ring = req->ring;
1426*71f41f3eSFrançois Tigeot 	int ret;
1427*71f41f3eSFrançois Tigeot 
1428*71f41f3eSFrançois Tigeot 	ret = intel_ring_begin(req, 4);
1429*71f41f3eSFrançois Tigeot 	if (ret)
1430*71f41f3eSFrançois Tigeot 		return ret;
1431*71f41f3eSFrançois Tigeot 
1432*71f41f3eSFrançois Tigeot 	intel_ring_emit(ring, MI_STORE_DWORD_INDEX);
1433*71f41f3eSFrançois Tigeot 	intel_ring_emit(ring, I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT);
1434*71f41f3eSFrançois Tigeot 	intel_ring_emit(ring, req->fence.seqno);
1435*71f41f3eSFrançois Tigeot 	intel_ring_emit(ring, MI_USER_INTERRUPT);
1436*71f41f3eSFrançois Tigeot 	intel_ring_advance(ring);
1437*71f41f3eSFrançois Tigeot 
1438*71f41f3eSFrançois Tigeot 	req->tail = ring->tail;
143924edb884SFrançois Tigeot 
1440ba55f2f5SFrançois Tigeot 	return 0;
1441e3adcf8fSFrançois Tigeot }
1442e3adcf8fSFrançois Tigeot 
1443e3adcf8fSFrançois Tigeot /**
1444*71f41f3eSFrançois Tigeot  * gen6_sema_emit_request - Update the semaphore mailbox registers
1445e3adcf8fSFrançois Tigeot  *
1446a05eeebfSFrançois Tigeot  * @request - request to write to the ring
1447e3adcf8fSFrançois Tigeot  *
1448e3adcf8fSFrançois Tigeot  * Update the mailbox registers in the *other* rings with the current seqno.
1449e3adcf8fSFrançois Tigeot  * This acts like a signal in the canonical semaphore.
1450e3adcf8fSFrançois Tigeot  */
1451*71f41f3eSFrançois Tigeot static int gen6_sema_emit_request(struct drm_i915_gem_request *req)
1452e3adcf8fSFrançois Tigeot {
1453ba55f2f5SFrançois Tigeot 	int ret;
1454e3adcf8fSFrançois Tigeot 
1455*71f41f3eSFrançois Tigeot 	ret = req->engine->semaphore.signal(req);
14569edbd4a0SFrançois Tigeot 	if (ret)
14579edbd4a0SFrançois Tigeot 		return ret;
14589edbd4a0SFrançois Tigeot 
1459*71f41f3eSFrançois Tigeot 	return i9xx_emit_request(req);
1460e3adcf8fSFrançois Tigeot }
1461e3adcf8fSFrançois Tigeot 
1462*71f41f3eSFrançois Tigeot static int gen8_render_emit_request(struct drm_i915_gem_request *req)
14631487f786SFrançois Tigeot {
14641487f786SFrançois Tigeot 	struct intel_engine_cs *engine = req->engine;
1465*71f41f3eSFrançois Tigeot 	struct intel_ring *ring = req->ring;
14661487f786SFrançois Tigeot 	int ret;
14671487f786SFrançois Tigeot 
1468*71f41f3eSFrançois Tigeot 	if (engine->semaphore.signal) {
1469*71f41f3eSFrançois Tigeot 		ret = engine->semaphore.signal(req);
1470*71f41f3eSFrançois Tigeot 		if (ret)
1471*71f41f3eSFrançois Tigeot 			return ret;
1472*71f41f3eSFrançois Tigeot 	}
1473*71f41f3eSFrançois Tigeot 
14741487f786SFrançois Tigeot 	ret = intel_ring_begin(req, 8);
14751487f786SFrançois Tigeot 	if (ret)
14761487f786SFrançois Tigeot 		return ret;
14771487f786SFrançois Tigeot 
1478*71f41f3eSFrançois Tigeot 	intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(6));
1479*71f41f3eSFrançois Tigeot 	intel_ring_emit(ring, (PIPE_CONTROL_GLOBAL_GTT_IVB |
14801487f786SFrançois Tigeot 			       PIPE_CONTROL_CS_STALL |
14811487f786SFrançois Tigeot 			       PIPE_CONTROL_QW_WRITE));
1482*71f41f3eSFrançois Tigeot 	intel_ring_emit(ring, intel_hws_seqno_address(engine));
1483*71f41f3eSFrançois Tigeot 	intel_ring_emit(ring, 0);
1484*71f41f3eSFrançois Tigeot 	intel_ring_emit(ring, i915_gem_request_get_seqno(req));
14851487f786SFrançois Tigeot 	/* We're thrashing one dword of HWS. */
1486*71f41f3eSFrançois Tigeot 	intel_ring_emit(ring, 0);
1487*71f41f3eSFrançois Tigeot 	intel_ring_emit(ring, MI_USER_INTERRUPT);
1488*71f41f3eSFrançois Tigeot 	intel_ring_emit(ring, MI_NOOP);
1489*71f41f3eSFrançois Tigeot 	intel_ring_advance(ring);
1490*71f41f3eSFrançois Tigeot 
1491*71f41f3eSFrançois Tigeot 	req->tail = ring->tail;
14921487f786SFrançois Tigeot 
14931487f786SFrançois Tigeot 	return 0;
14941487f786SFrançois Tigeot }
14951487f786SFrançois Tigeot 
1496e3adcf8fSFrançois Tigeot /**
1497e3adcf8fSFrançois Tigeot  * intel_ring_sync - sync the waiter to the signaller on seqno
1498e3adcf8fSFrançois Tigeot  *
1499e3adcf8fSFrançois Tigeot  * @waiter - ring that is waiting
1500e3adcf8fSFrançois Tigeot  * @signaller - ring which has, or will signal
1501e3adcf8fSFrançois Tigeot  * @seqno - seqno which the waiter will block on
1502e3adcf8fSFrançois Tigeot  */
150324edb884SFrançois Tigeot 
150424edb884SFrançois Tigeot static int
1505*71f41f3eSFrançois Tigeot gen8_ring_sync_to(struct drm_i915_gem_request *req,
1506*71f41f3eSFrançois Tigeot 		  struct drm_i915_gem_request *signal)
150724edb884SFrançois Tigeot {
1508*71f41f3eSFrançois Tigeot 	struct intel_ring *ring = req->ring;
1509*71f41f3eSFrançois Tigeot 	struct drm_i915_private *dev_priv = req->i915;
1510*71f41f3eSFrançois Tigeot 	u64 offset = GEN8_WAIT_OFFSET(req->engine, signal->engine->id);
15111487f786SFrançois Tigeot 	struct i915_hw_ppgtt *ppgtt;
151224edb884SFrançois Tigeot 	int ret;
151324edb884SFrançois Tigeot 
1514*71f41f3eSFrançois Tigeot 	ret = intel_ring_begin(req, 4);
151524edb884SFrançois Tigeot 	if (ret)
151624edb884SFrançois Tigeot 		return ret;
151724edb884SFrançois Tigeot 
1518*71f41f3eSFrançois Tigeot 	intel_ring_emit(ring,
1519*71f41f3eSFrançois Tigeot 			MI_SEMAPHORE_WAIT |
152024edb884SFrançois Tigeot 			MI_SEMAPHORE_GLOBAL_GTT |
152124edb884SFrançois Tigeot 			MI_SEMAPHORE_SAD_GTE_SDD);
1522*71f41f3eSFrançois Tigeot 	intel_ring_emit(ring, signal->fence.seqno);
1523*71f41f3eSFrançois Tigeot 	intel_ring_emit(ring, lower_32_bits(offset));
1524*71f41f3eSFrançois Tigeot 	intel_ring_emit(ring, upper_32_bits(offset));
1525*71f41f3eSFrançois Tigeot 	intel_ring_advance(ring);
15261487f786SFrançois Tigeot 
15271487f786SFrançois Tigeot 	/* When the !RCS engines idle waiting upon a semaphore, they lose their
15281487f786SFrançois Tigeot 	 * pagetables and we must reload them before executing the batch.
15291487f786SFrançois Tigeot 	 * We do this on the i915_switch_context() following the wait and
15301487f786SFrançois Tigeot 	 * before the dispatch.
15311487f786SFrançois Tigeot 	 */
1532*71f41f3eSFrançois Tigeot 	ppgtt = req->ctx->ppgtt;
1533*71f41f3eSFrançois Tigeot 	if (ppgtt && req->engine->id != RCS)
1534*71f41f3eSFrançois Tigeot 		ppgtt->pd_dirty_rings |= intel_engine_flag(req->engine);
153524edb884SFrançois Tigeot 	return 0;
153624edb884SFrançois Tigeot }
153724edb884SFrançois Tigeot 
1538e3adcf8fSFrançois Tigeot static int
1539*71f41f3eSFrançois Tigeot gen6_ring_sync_to(struct drm_i915_gem_request *req,
1540*71f41f3eSFrançois Tigeot 		  struct drm_i915_gem_request *signal)
1541e3adcf8fSFrançois Tigeot {
1542*71f41f3eSFrançois Tigeot 	struct intel_ring *ring = req->ring;
1543e3adcf8fSFrançois Tigeot 	u32 dw1 = MI_SEMAPHORE_MBOX |
1544e3adcf8fSFrançois Tigeot 		  MI_SEMAPHORE_COMPARE |
1545e3adcf8fSFrançois Tigeot 		  MI_SEMAPHORE_REGISTER;
1546*71f41f3eSFrançois Tigeot 	u32 wait_mbox = signal->engine->semaphore.mbox.wait[req->engine->id];
1547ba55f2f5SFrançois Tigeot 	int ret;
1548e3adcf8fSFrançois Tigeot 
1549*71f41f3eSFrançois Tigeot 	WARN_ON(wait_mbox == MI_SEMAPHORE_SYNC_INVALID);
1550*71f41f3eSFrançois Tigeot 
1551*71f41f3eSFrançois Tigeot 	ret = intel_ring_begin(req, 4);
1552*71f41f3eSFrançois Tigeot 	if (ret)
1553*71f41f3eSFrançois Tigeot 		return ret;
1554*71f41f3eSFrançois Tigeot 
1555*71f41f3eSFrançois Tigeot 	intel_ring_emit(ring, dw1 | wait_mbox);
1556686a02f1SFrançois Tigeot 	/* Throughout all of the GEM code, seqno passed implies our current
1557686a02f1SFrançois Tigeot 	 * seqno is >= the last seqno executed. However for hardware the
1558686a02f1SFrançois Tigeot 	 * comparison is strictly greater than.
1559686a02f1SFrançois Tigeot 	 */
1560*71f41f3eSFrançois Tigeot 	intel_ring_emit(ring, signal->fence.seqno - 1);
1561*71f41f3eSFrançois Tigeot 	intel_ring_emit(ring, 0);
1562*71f41f3eSFrançois Tigeot 	intel_ring_emit(ring, MI_NOOP);
1563*71f41f3eSFrançois Tigeot 	intel_ring_advance(ring);
1564e3adcf8fSFrançois Tigeot 
1565e3adcf8fSFrançois Tigeot 	return 0;
1566e3adcf8fSFrançois Tigeot }
1567e3adcf8fSFrançois Tigeot 
1568303bf270SFrançois Tigeot static void
156987df8fc6SFrançois Tigeot gen5_seqno_barrier(struct intel_engine_cs *engine)
1570e3adcf8fSFrançois Tigeot {
1571303bf270SFrançois Tigeot 	/* MI_STORE are internally buffered by the GPU and not flushed
1572303bf270SFrançois Tigeot 	 * either by MI_FLUSH or SyncFlush or any other combination of
1573303bf270SFrançois Tigeot 	 * MI commands.
1574e3adcf8fSFrançois Tigeot 	 *
1575303bf270SFrançois Tigeot 	 * "Only the submission of the store operation is guaranteed.
1576303bf270SFrançois Tigeot 	 * The write result will be complete (coherent) some time later
1577303bf270SFrançois Tigeot 	 * (this is practically a finite period but there is no guaranteed
1578303bf270SFrançois Tigeot 	 * latency)."
1579303bf270SFrançois Tigeot 	 *
1580303bf270SFrançois Tigeot 	 * Empirically, we observe that we need a delay of at least 75us to
1581303bf270SFrançois Tigeot 	 * be sure that the seqno write is visible by the CPU.
1582e3adcf8fSFrançois Tigeot 	 */
1583303bf270SFrançois Tigeot 	usleep_range(125, 250);
1584e3adcf8fSFrançois Tigeot }
1585e3adcf8fSFrançois Tigeot 
15868621f407SFrançois Tigeot static void
15878621f407SFrançois Tigeot gen6_seqno_barrier(struct intel_engine_cs *engine)
1588e3adcf8fSFrançois Tigeot {
15891487f786SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
15908621f407SFrançois Tigeot 
1591e3adcf8fSFrançois Tigeot 	/* Workaround to force correct ordering between irq and seqno writes on
1592e3adcf8fSFrançois Tigeot 	 * ivb (and maybe also on snb) by reading from a CS register (like
15938621f407SFrançois Tigeot 	 * ACTHD) before reading the status page.
15948621f407SFrançois Tigeot 	 *
15958621f407SFrançois Tigeot 	 * Note that this effectively stalls the read by the time it takes to
15968621f407SFrançois Tigeot 	 * do a memory transaction, which more or less ensures that the write
15978621f407SFrançois Tigeot 	 * from the GPU has sufficient time to invalidate the CPU cacheline.
15988621f407SFrançois Tigeot 	 * Alternatively we could delay the interrupt from the CS ring to give
15998621f407SFrançois Tigeot 	 * the write time to land, but that would incur a delay after every
16008621f407SFrançois Tigeot 	 * batch i.e. much more frequent than a delay when waiting for the
16018621f407SFrançois Tigeot 	 * interrupt (with the same net latency).
16028621f407SFrançois Tigeot 	 *
16038621f407SFrançois Tigeot 	 * Also note that to prevent whole machine hangs on gen7, we have to
16048621f407SFrançois Tigeot 	 * take the spinlock to guard against concurrent cacheline access.
16058621f407SFrançois Tigeot 	 */
16068621f407SFrançois Tigeot 	spin_lock_irq(&dev_priv->uncore.lock);
16078621f407SFrançois Tigeot 	POSTING_READ_FW(RING_ACTHD(engine->mmio_base));
16088621f407SFrançois Tigeot 	spin_unlock_irq(&dev_priv->uncore.lock);
1609e3adcf8fSFrançois Tigeot }
1610e3adcf8fSFrançois Tigeot 
1611303bf270SFrançois Tigeot static void
1612303bf270SFrançois Tigeot gen5_irq_enable(struct intel_engine_cs *engine)
1613e3adcf8fSFrançois Tigeot {
1614303bf270SFrançois Tigeot 	gen5_enable_gt_irq(engine->i915, engine->irq_enable_mask);
1615e3adcf8fSFrançois Tigeot }
1616e3adcf8fSFrançois Tigeot 
1617a2fdbec6SFrançois Tigeot static void
1618303bf270SFrançois Tigeot gen5_irq_disable(struct intel_engine_cs *engine)
1619a2fdbec6SFrançois Tigeot {
1620303bf270SFrançois Tigeot 	gen5_disable_gt_irq(engine->i915, engine->irq_enable_mask);
1621e3adcf8fSFrançois Tigeot }
1622e3adcf8fSFrançois Tigeot 
1623a2fdbec6SFrançois Tigeot static void
1624303bf270SFrançois Tigeot i9xx_irq_enable(struct intel_engine_cs *engine)
1625e3adcf8fSFrançois Tigeot {
16261487f786SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
1627e3adcf8fSFrançois Tigeot 
16288621f407SFrançois Tigeot 	dev_priv->irq_mask &= ~engine->irq_enable_mask;
1629686a02f1SFrançois Tigeot 	I915_WRITE(IMR, dev_priv->irq_mask);
1630303bf270SFrançois Tigeot 	POSTING_READ_FW(RING_IMR(engine->mmio_base));
1631686a02f1SFrançois Tigeot }
1632686a02f1SFrançois Tigeot 
1633686a02f1SFrançois Tigeot static void
1634303bf270SFrançois Tigeot i9xx_irq_disable(struct intel_engine_cs *engine)
1635686a02f1SFrançois Tigeot {
16361487f786SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
1637686a02f1SFrançois Tigeot 
16388621f407SFrançois Tigeot 	dev_priv->irq_mask |= engine->irq_enable_mask;
1639686a02f1SFrançois Tigeot 	I915_WRITE(IMR, dev_priv->irq_mask);
1640686a02f1SFrançois Tigeot }
1641686a02f1SFrançois Tigeot 
1642686a02f1SFrançois Tigeot static void
1643303bf270SFrançois Tigeot i8xx_irq_enable(struct intel_engine_cs *engine)
1644686a02f1SFrançois Tigeot {
16451487f786SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
1646686a02f1SFrançois Tigeot 
1647303bf270SFrançois Tigeot 	dev_priv->irq_mask &= ~engine->irq_enable_mask;
1648303bf270SFrançois Tigeot 	I915_WRITE16(IMR, dev_priv->irq_mask);
1649303bf270SFrançois Tigeot 	POSTING_READ16(RING_IMR(engine->mmio_base));
1650303bf270SFrançois Tigeot }
1651303bf270SFrançois Tigeot 
1652303bf270SFrançois Tigeot static void
1653303bf270SFrançois Tigeot i8xx_irq_disable(struct intel_engine_cs *engine)
1654303bf270SFrançois Tigeot {
1655303bf270SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
1656303bf270SFrançois Tigeot 
16578621f407SFrançois Tigeot 	dev_priv->irq_mask |= engine->irq_enable_mask;
1658686a02f1SFrançois Tigeot 	I915_WRITE16(IMR, dev_priv->irq_mask);
1659e3adcf8fSFrançois Tigeot }
1660e3adcf8fSFrançois Tigeot 
1661e3adcf8fSFrançois Tigeot static int
1662*71f41f3eSFrançois Tigeot bsd_ring_flush(struct drm_i915_gem_request *req, u32 mode)
1663e3adcf8fSFrançois Tigeot {
1664*71f41f3eSFrançois Tigeot 	struct intel_ring *ring = req->ring;
1665e3adcf8fSFrançois Tigeot 	int ret;
1666e3adcf8fSFrançois Tigeot 
1667a05eeebfSFrançois Tigeot 	ret = intel_ring_begin(req, 2);
1668e3adcf8fSFrançois Tigeot 	if (ret)
1669e3adcf8fSFrançois Tigeot 		return ret;
1670e3adcf8fSFrançois Tigeot 
1671*71f41f3eSFrançois Tigeot 	intel_ring_emit(ring, MI_FLUSH);
1672*71f41f3eSFrançois Tigeot 	intel_ring_emit(ring, MI_NOOP);
1673*71f41f3eSFrançois Tigeot 	intel_ring_advance(ring);
1674e3adcf8fSFrançois Tigeot 	return 0;
1675e3adcf8fSFrançois Tigeot }
1676e3adcf8fSFrançois Tigeot 
1677303bf270SFrançois Tigeot static void
1678303bf270SFrançois Tigeot gen6_irq_enable(struct intel_engine_cs *engine)
1679e3adcf8fSFrançois Tigeot {
16801487f786SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
1681e3adcf8fSFrançois Tigeot 
16828621f407SFrançois Tigeot 	I915_WRITE_IMR(engine,
16838621f407SFrançois Tigeot 		       ~(engine->irq_enable_mask |
1684303bf270SFrançois Tigeot 			 engine->irq_keep_mask));
16858621f407SFrançois Tigeot 	gen5_enable_gt_irq(dev_priv, engine->irq_enable_mask);
1686e3adcf8fSFrançois Tigeot }
1687e3adcf8fSFrançois Tigeot 
1688e3adcf8fSFrançois Tigeot static void
1689303bf270SFrançois Tigeot gen6_irq_disable(struct intel_engine_cs *engine)
1690e3adcf8fSFrançois Tigeot {
16911487f786SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
1692e3adcf8fSFrançois Tigeot 
1693303bf270SFrançois Tigeot 	I915_WRITE_IMR(engine, ~engine->irq_keep_mask);
16948621f407SFrançois Tigeot 	gen5_disable_gt_irq(dev_priv, engine->irq_enable_mask);
1695e3adcf8fSFrançois Tigeot }
1696e3adcf8fSFrançois Tigeot 
1697303bf270SFrançois Tigeot static void
1698303bf270SFrançois Tigeot hsw_vebox_irq_enable(struct intel_engine_cs *engine)
16995d0b1887SFrançois Tigeot {
17001487f786SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
17015d0b1887SFrançois Tigeot 
17028621f407SFrançois Tigeot 	I915_WRITE_IMR(engine, ~engine->irq_enable_mask);
17038621f407SFrançois Tigeot 	gen6_enable_pm_irq(dev_priv, engine->irq_enable_mask);
17045d0b1887SFrançois Tigeot }
17055d0b1887SFrançois Tigeot 
17065d0b1887SFrançois Tigeot static void
1707303bf270SFrançois Tigeot hsw_vebox_irq_disable(struct intel_engine_cs *engine)
17085d0b1887SFrançois Tigeot {
17091487f786SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
17105d0b1887SFrançois Tigeot 
17118621f407SFrançois Tigeot 	I915_WRITE_IMR(engine, ~0);
17128621f407SFrançois Tigeot 	gen6_disable_pm_irq(dev_priv, engine->irq_enable_mask);
17135d0b1887SFrançois Tigeot }
17149edbd4a0SFrançois Tigeot 
1715303bf270SFrançois Tigeot static void
1716303bf270SFrançois Tigeot gen8_irq_enable(struct intel_engine_cs *engine)
17179edbd4a0SFrançois Tigeot {
17181487f786SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
17199edbd4a0SFrançois Tigeot 
17208621f407SFrançois Tigeot 	I915_WRITE_IMR(engine,
17218621f407SFrançois Tigeot 		       ~(engine->irq_enable_mask |
1722303bf270SFrançois Tigeot 			 engine->irq_keep_mask));
1723303bf270SFrançois Tigeot 	POSTING_READ_FW(RING_IMR(engine->mmio_base));
17249edbd4a0SFrançois Tigeot }
17259edbd4a0SFrançois Tigeot 
17269edbd4a0SFrançois Tigeot static void
1727303bf270SFrançois Tigeot gen8_irq_disable(struct intel_engine_cs *engine)
17289edbd4a0SFrançois Tigeot {
17291487f786SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
17309edbd4a0SFrançois Tigeot 
1731303bf270SFrançois Tigeot 	I915_WRITE_IMR(engine, ~engine->irq_keep_mask);
17325d0b1887SFrançois Tigeot }
17335d0b1887SFrançois Tigeot 
1734e3adcf8fSFrançois Tigeot static int
1735*71f41f3eSFrançois Tigeot i965_emit_bb_start(struct drm_i915_gem_request *req,
1736ba55f2f5SFrançois Tigeot 		   u64 offset, u32 length,
1737*71f41f3eSFrançois Tigeot 		   unsigned int dispatch_flags)
1738e3adcf8fSFrançois Tigeot {
1739*71f41f3eSFrançois Tigeot 	struct intel_ring *ring = req->ring;
1740e3adcf8fSFrançois Tigeot 	int ret;
1741e3adcf8fSFrançois Tigeot 
1742a05eeebfSFrançois Tigeot 	ret = intel_ring_begin(req, 2);
1743e3adcf8fSFrançois Tigeot 	if (ret)
1744e3adcf8fSFrançois Tigeot 		return ret;
1745e3adcf8fSFrançois Tigeot 
1746*71f41f3eSFrançois Tigeot 	intel_ring_emit(ring,
1747686a02f1SFrançois Tigeot 			MI_BATCH_BUFFER_START |
1748b5c29a34SFrançois Tigeot 			MI_BATCH_GTT |
1749477eb7f9SFrançois Tigeot 			(dispatch_flags & I915_DISPATCH_SECURE ?
1750477eb7f9SFrançois Tigeot 			 0 : MI_BATCH_NON_SECURE_I965));
1751*71f41f3eSFrançois Tigeot 	intel_ring_emit(ring, offset);
1752*71f41f3eSFrançois Tigeot 	intel_ring_advance(ring);
1753e3adcf8fSFrançois Tigeot 
1754e3adcf8fSFrançois Tigeot 	return 0;
1755e3adcf8fSFrançois Tigeot }
1756e3adcf8fSFrançois Tigeot 
1757b5c29a34SFrançois Tigeot /* Just userspace ABI convention to limit the wa batch bo to a resonable size */
1758b5c29a34SFrançois Tigeot #define I830_BATCH_LIMIT (256*1024)
175924edb884SFrançois Tigeot #define I830_TLB_ENTRIES (2)
176024edb884SFrançois Tigeot #define I830_WA_SIZE max(I830_TLB_ENTRIES*4096, I830_BATCH_LIMIT)
1761e3adcf8fSFrançois Tigeot static int
1762*71f41f3eSFrançois Tigeot i830_emit_bb_start(struct drm_i915_gem_request *req,
1763ba55f2f5SFrançois Tigeot 		   u64 offset, u32 len,
1764*71f41f3eSFrançois Tigeot 		   unsigned int dispatch_flags)
1765e3adcf8fSFrançois Tigeot {
1766*71f41f3eSFrançois Tigeot 	struct intel_ring *ring = req->ring;
1767*71f41f3eSFrançois Tigeot 	u32 cs_offset = req->engine->scratch.gtt_offset;
1768e3adcf8fSFrançois Tigeot 	int ret;
1769e3adcf8fSFrançois Tigeot 
1770a05eeebfSFrançois Tigeot 	ret = intel_ring_begin(req, 6);
177124edb884SFrançois Tigeot 	if (ret)
177224edb884SFrançois Tigeot 		return ret;
177324edb884SFrançois Tigeot 
177424edb884SFrançois Tigeot 	/* Evict the invalid PTE TLBs */
1775*71f41f3eSFrançois Tigeot 	intel_ring_emit(ring, COLOR_BLT_CMD | BLT_WRITE_RGBA);
1776*71f41f3eSFrançois Tigeot 	intel_ring_emit(ring, BLT_DEPTH_32 | BLT_ROP_COLOR_COPY | 4096);
1777*71f41f3eSFrançois Tigeot 	intel_ring_emit(ring, I830_TLB_ENTRIES << 16 | 4); /* load each page */
1778*71f41f3eSFrançois Tigeot 	intel_ring_emit(ring, cs_offset);
1779*71f41f3eSFrançois Tigeot 	intel_ring_emit(ring, 0xdeadbeef);
1780*71f41f3eSFrançois Tigeot 	intel_ring_emit(ring, MI_NOOP);
1781*71f41f3eSFrançois Tigeot 	intel_ring_advance(ring);
178224edb884SFrançois Tigeot 
1783477eb7f9SFrançois Tigeot 	if ((dispatch_flags & I915_DISPATCH_PINNED) == 0) {
178424edb884SFrançois Tigeot 		if (len > I830_BATCH_LIMIT)
178524edb884SFrançois Tigeot 			return -ENOSPC;
178624edb884SFrançois Tigeot 
1787a05eeebfSFrançois Tigeot 		ret = intel_ring_begin(req, 6 + 2);
178824edb884SFrançois Tigeot 		if (ret)
178924edb884SFrançois Tigeot 			return ret;
179024edb884SFrançois Tigeot 
179124edb884SFrançois Tigeot 		/* Blit the batch (which has now all relocs applied) to the
179224edb884SFrançois Tigeot 		 * stable batch scratch bo area (so that the CS never
179324edb884SFrançois Tigeot 		 * stumbles over its tlb invalidation bug) ...
179424edb884SFrançois Tigeot 		 */
1795*71f41f3eSFrançois Tigeot 		intel_ring_emit(ring, SRC_COPY_BLT_CMD | BLT_WRITE_RGBA);
1796*71f41f3eSFrançois Tigeot 		intel_ring_emit(ring,
17978621f407SFrançois Tigeot 				BLT_DEPTH_32 | BLT_ROP_SRC_COPY | 4096);
1798*71f41f3eSFrançois Tigeot 		intel_ring_emit(ring, DIV_ROUND_UP(len, 4096) << 16 | 4096);
1799*71f41f3eSFrançois Tigeot 		intel_ring_emit(ring, cs_offset);
1800*71f41f3eSFrançois Tigeot 		intel_ring_emit(ring, 4096);
1801*71f41f3eSFrançois Tigeot 		intel_ring_emit(ring, offset);
180224edb884SFrançois Tigeot 
1803*71f41f3eSFrançois Tigeot 		intel_ring_emit(ring, MI_FLUSH);
1804*71f41f3eSFrançois Tigeot 		intel_ring_emit(ring, MI_NOOP);
1805*71f41f3eSFrançois Tigeot 		intel_ring_advance(ring);
180624edb884SFrançois Tigeot 
180724edb884SFrançois Tigeot 		/* ... and execute it. */
180824edb884SFrançois Tigeot 		offset = cs_offset;
180924edb884SFrançois Tigeot 	}
181024edb884SFrançois Tigeot 
1811c0e85e96SFrançois Tigeot 	ret = intel_ring_begin(req, 2);
1812e3adcf8fSFrançois Tigeot 	if (ret)
1813e3adcf8fSFrançois Tigeot 		return ret;
1814e3adcf8fSFrançois Tigeot 
1815*71f41f3eSFrançois Tigeot 	intel_ring_emit(ring, MI_BATCH_BUFFER_START | MI_BATCH_GTT);
1816*71f41f3eSFrançois Tigeot 	intel_ring_emit(ring, offset | (dispatch_flags & I915_DISPATCH_SECURE ?
1817477eb7f9SFrançois Tigeot 					0 : MI_BATCH_NON_SECURE));
1818*71f41f3eSFrançois Tigeot 	intel_ring_advance(ring);
1819686a02f1SFrançois Tigeot 
1820686a02f1SFrançois Tigeot 	return 0;
1821686a02f1SFrançois Tigeot }
1822686a02f1SFrançois Tigeot 
1823686a02f1SFrançois Tigeot static int
1824*71f41f3eSFrançois Tigeot i915_emit_bb_start(struct drm_i915_gem_request *req,
1825ba55f2f5SFrançois Tigeot 		   u64 offset, u32 len,
1826*71f41f3eSFrançois Tigeot 		   unsigned int dispatch_flags)
1827686a02f1SFrançois Tigeot {
1828*71f41f3eSFrançois Tigeot 	struct intel_ring *ring = req->ring;
1829686a02f1SFrançois Tigeot 	int ret;
1830686a02f1SFrançois Tigeot 
1831a05eeebfSFrançois Tigeot 	ret = intel_ring_begin(req, 2);
1832e3adcf8fSFrançois Tigeot 	if (ret)
1833e3adcf8fSFrançois Tigeot 		return ret;
1834e3adcf8fSFrançois Tigeot 
1835*71f41f3eSFrançois Tigeot 	intel_ring_emit(ring, MI_BATCH_BUFFER_START | MI_BATCH_GTT);
1836*71f41f3eSFrançois Tigeot 	intel_ring_emit(ring, offset | (dispatch_flags & I915_DISPATCH_SECURE ?
1837477eb7f9SFrançois Tigeot 					0 : MI_BATCH_NON_SECURE));
1838*71f41f3eSFrançois Tigeot 	intel_ring_advance(ring);
1839e3adcf8fSFrançois Tigeot 
1840e3adcf8fSFrançois Tigeot 	return 0;
1841e3adcf8fSFrançois Tigeot }
1842e3adcf8fSFrançois Tigeot 
18438621f407SFrançois Tigeot static void cleanup_phys_status_page(struct intel_engine_cs *engine)
1844c0e85e96SFrançois Tigeot {
18451487f786SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
1846c0e85e96SFrançois Tigeot 
1847c0e85e96SFrançois Tigeot 	if (!dev_priv->status_page_dmah)
1848c0e85e96SFrançois Tigeot 		return;
1849c0e85e96SFrançois Tigeot 
1850303bf270SFrançois Tigeot 	drm_pci_free(&dev_priv->drm, dev_priv->status_page_dmah);
18518621f407SFrançois Tigeot 	engine->status_page.page_addr = NULL;
1852c0e85e96SFrançois Tigeot }
1853c0e85e96SFrançois Tigeot 
18548621f407SFrançois Tigeot static void cleanup_status_page(struct intel_engine_cs *engine)
1855e3adcf8fSFrançois Tigeot {
1856e3adcf8fSFrançois Tigeot 	struct drm_i915_gem_object *obj;
1857e3adcf8fSFrançois Tigeot 
18588621f407SFrançois Tigeot 	obj = engine->status_page.obj;
1859e3adcf8fSFrançois Tigeot 	if (obj == NULL)
1860e3adcf8fSFrançois Tigeot 		return;
1861e3adcf8fSFrançois Tigeot 
18627ec9f8e5SFrançois Tigeot 	kunmap(sg_page(obj->pages->sgl));
1863ba55f2f5SFrançois Tigeot 	i915_gem_object_ggtt_unpin(obj);
186487df8fc6SFrançois Tigeot 	i915_gem_object_put(obj);
18658621f407SFrançois Tigeot 	engine->status_page.obj = NULL;
1866e3adcf8fSFrançois Tigeot }
1867e3adcf8fSFrançois Tigeot 
18688621f407SFrançois Tigeot static int init_status_page(struct intel_engine_cs *engine)
1869e3adcf8fSFrançois Tigeot {
18708621f407SFrançois Tigeot 	struct drm_i915_gem_object *obj = engine->status_page.obj;
1871ba55f2f5SFrançois Tigeot 
1872c0e85e96SFrançois Tigeot 	if (obj == NULL) {
187324edb884SFrançois Tigeot 		unsigned flags;
1874e3adcf8fSFrançois Tigeot 		int ret;
1875e3adcf8fSFrançois Tigeot 
1876303bf270SFrançois Tigeot 		obj = i915_gem_object_create(&engine->i915->drm, 4096);
18771487f786SFrançois Tigeot 		if (IS_ERR(obj)) {
1878e3adcf8fSFrançois Tigeot 			DRM_ERROR("Failed to allocate status page\n");
18791487f786SFrançois Tigeot 			return PTR_ERR(obj);
1880e3adcf8fSFrançois Tigeot 		}
1881e3adcf8fSFrançois Tigeot 
1882ba55f2f5SFrançois Tigeot 		ret = i915_gem_object_set_cache_level(obj, I915_CACHE_LLC);
1883ba55f2f5SFrançois Tigeot 		if (ret)
1884e3adcf8fSFrançois Tigeot 			goto err_unref;
1885ba55f2f5SFrançois Tigeot 
188624edb884SFrançois Tigeot 		flags = 0;
18871487f786SFrançois Tigeot 		if (!HAS_LLC(engine->i915))
188824edb884SFrançois Tigeot 			/* On g33, we cannot place HWS above 256MiB, so
188924edb884SFrançois Tigeot 			 * restrict its pinning to the low mappable arena.
189024edb884SFrançois Tigeot 			 * Though this restriction is not documented for
189124edb884SFrançois Tigeot 			 * gen4, gen5, or byt, they also behave similarly
189224edb884SFrançois Tigeot 			 * and hang if the HWS is placed at the top of the
189324edb884SFrançois Tigeot 			 * GTT. To generalise, it appears that all !llc
189424edb884SFrançois Tigeot 			 * platforms have issues with us placing the HWS
189524edb884SFrançois Tigeot 			 * above the mappable region (even though we never
189624edb884SFrançois Tigeot 			 * actualy map it).
189724edb884SFrançois Tigeot 			 */
189824edb884SFrançois Tigeot 			flags |= PIN_MAPPABLE;
1899*71f41f3eSFrançois Tigeot 		ret = i915_gem_object_ggtt_pin(obj, NULL, 0, 4096, flags);
1900ba55f2f5SFrançois Tigeot 		if (ret) {
1901ba55f2f5SFrançois Tigeot err_unref:
190287df8fc6SFrançois Tigeot 			i915_gem_object_put(obj);
1903ba55f2f5SFrançois Tigeot 			return ret;
1904ba55f2f5SFrançois Tigeot 		}
1905ba55f2f5SFrançois Tigeot 
19068621f407SFrançois Tigeot 		engine->status_page.obj = obj;
1907e3adcf8fSFrançois Tigeot 	}
1908e3adcf8fSFrançois Tigeot 
19098621f407SFrançois Tigeot 	engine->status_page.gfx_addr = i915_gem_obj_ggtt_offset(obj);
19108621f407SFrançois Tigeot 	engine->status_page.page_addr = kmap(sg_page(obj->pages->sgl));
19118621f407SFrançois Tigeot 	memset(engine->status_page.page_addr, 0, PAGE_SIZE);
1912e3adcf8fSFrançois Tigeot 
1913b5c29a34SFrançois Tigeot 	DRM_DEBUG_DRIVER("%s hws offset: 0x%08x\n",
19148621f407SFrançois Tigeot 			engine->name, engine->status_page.gfx_addr);
1915e3adcf8fSFrançois Tigeot 
1916e3adcf8fSFrançois Tigeot 	return 0;
1917e3adcf8fSFrançois Tigeot }
1918e3adcf8fSFrançois Tigeot 
19198621f407SFrançois Tigeot static int init_phys_status_page(struct intel_engine_cs *engine)
1920686a02f1SFrançois Tigeot {
19211487f786SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
1922686a02f1SFrançois Tigeot 
1923686a02f1SFrançois Tigeot 	if (!dev_priv->status_page_dmah) {
1924686a02f1SFrançois Tigeot 		dev_priv->status_page_dmah =
1925303bf270SFrançois Tigeot 			drm_pci_alloc(&dev_priv->drm, PAGE_SIZE, PAGE_SIZE);
1926686a02f1SFrançois Tigeot 		if (!dev_priv->status_page_dmah)
1927686a02f1SFrançois Tigeot 			return -ENOMEM;
1928686a02f1SFrançois Tigeot 	}
1929686a02f1SFrançois Tigeot 
19308621f407SFrançois Tigeot 	engine->status_page.page_addr = dev_priv->status_page_dmah->vaddr;
19318621f407SFrançois Tigeot 	memset(engine->status_page.page_addr, 0, PAGE_SIZE);
1932686a02f1SFrançois Tigeot 
1933686a02f1SFrançois Tigeot 	return 0;
1934686a02f1SFrançois Tigeot }
1935686a02f1SFrançois Tigeot 
1936*71f41f3eSFrançois Tigeot int intel_ring_pin(struct intel_ring *ring)
19372c9916cdSFrançois Tigeot {
1938*71f41f3eSFrançois Tigeot 	struct drm_i915_private *dev_priv = ring->engine->i915;
1939*71f41f3eSFrançois Tigeot 	struct drm_i915_gem_object *obj = ring->obj;
1940c0e85e96SFrançois Tigeot 	/* Ring wraparound at offset 0 sometimes hangs. No idea why. */
1941c0e85e96SFrançois Tigeot 	unsigned flags = PIN_OFFSET_BIAS | 4096;
19428621f407SFrançois Tigeot 	void *addr;
19432c9916cdSFrançois Tigeot 	int ret;
19442c9916cdSFrançois Tigeot 
1945aee94f86SFrançois Tigeot 	if (HAS_LLC(dev_priv) && !obj->stolen) {
1946*71f41f3eSFrançois Tigeot 		ret = i915_gem_object_ggtt_pin(obj, NULL, 0, PAGE_SIZE, flags);
1947aee94f86SFrançois Tigeot 		if (ret)
1948aee94f86SFrançois Tigeot 			return ret;
1949aee94f86SFrançois Tigeot 
1950aee94f86SFrançois Tigeot 		ret = i915_gem_object_set_to_cpu_domain(obj, true);
19518621f407SFrançois Tigeot 		if (ret)
19528621f407SFrançois Tigeot 			goto err_unpin;
1953aee94f86SFrançois Tigeot 
19548621f407SFrançois Tigeot 		addr = i915_gem_object_pin_map(obj);
19558621f407SFrançois Tigeot 		if (IS_ERR(addr)) {
19568621f407SFrançois Tigeot 			ret = PTR_ERR(addr);
19578621f407SFrançois Tigeot 			goto err_unpin;
1958aee94f86SFrançois Tigeot 		}
1959aee94f86SFrançois Tigeot 	} else {
1960*71f41f3eSFrançois Tigeot 		ret = i915_gem_object_ggtt_pin(obj, NULL, 0, PAGE_SIZE,
1961c0e85e96SFrançois Tigeot 					       flags | PIN_MAPPABLE);
19622c9916cdSFrançois Tigeot 		if (ret)
19632c9916cdSFrançois Tigeot 			return ret;
19642c9916cdSFrançois Tigeot 
19652c9916cdSFrançois Tigeot 		ret = i915_gem_object_set_to_gtt_domain(obj, true);
19668621f407SFrançois Tigeot 		if (ret)
19678621f407SFrançois Tigeot 			goto err_unpin;
19682c9916cdSFrançois Tigeot 
1969c0e85e96SFrançois Tigeot 		/* Access through the GTT requires the device to be awake. */
1970c0e85e96SFrançois Tigeot 		assert_rpm_wakelock_held(dev_priv);
1971c0e85e96SFrançois Tigeot 
197287df8fc6SFrançois Tigeot 		addr = (void __force *)
197387df8fc6SFrançois Tigeot 			i915_vma_pin_iomap(i915_gem_obj_to_ggtt(obj));
19741487f786SFrançois Tigeot 		if (IS_ERR(addr)) {
19751487f786SFrançois Tigeot 			ret = PTR_ERR(addr);
19768621f407SFrançois Tigeot 			goto err_unpin;
19772c9916cdSFrançois Tigeot 		}
1978aee94f86SFrançois Tigeot 	}
19792c9916cdSFrançois Tigeot 
1980*71f41f3eSFrançois Tigeot 	ring->vaddr = addr;
1981*71f41f3eSFrançois Tigeot 	ring->vma = i915_gem_obj_to_ggtt(obj);
19822c9916cdSFrançois Tigeot 	return 0;
19838621f407SFrançois Tigeot 
19848621f407SFrançois Tigeot err_unpin:
19858621f407SFrançois Tigeot 	i915_gem_object_ggtt_unpin(obj);
19868621f407SFrançois Tigeot 	return ret;
19872c9916cdSFrançois Tigeot }
19882c9916cdSFrançois Tigeot 
1989*71f41f3eSFrançois Tigeot void intel_ring_unpin(struct intel_ring *ring)
1990e3adcf8fSFrançois Tigeot {
1991*71f41f3eSFrançois Tigeot 	GEM_BUG_ON(!ring->vma);
1992*71f41f3eSFrançois Tigeot 	GEM_BUG_ON(!ring->vaddr);
1993*71f41f3eSFrançois Tigeot 
1994*71f41f3eSFrançois Tigeot 	if (HAS_LLC(ring->engine->i915) && !ring->obj->stolen)
1995*71f41f3eSFrançois Tigeot 		i915_gem_object_unpin_map(ring->obj);
1996*71f41f3eSFrançois Tigeot 	else
1997*71f41f3eSFrançois Tigeot 		i915_vma_unpin_iomap(ring->vma);
1998*71f41f3eSFrançois Tigeot 	ring->vaddr = NULL;
1999*71f41f3eSFrançois Tigeot 
2000*71f41f3eSFrançois Tigeot 	i915_gem_object_ggtt_unpin(ring->obj);
2001*71f41f3eSFrançois Tigeot 	ring->vma = NULL;
2002*71f41f3eSFrançois Tigeot }
2003*71f41f3eSFrançois Tigeot 
2004*71f41f3eSFrançois Tigeot static void intel_destroy_ringbuffer_obj(struct intel_ring *ring)
2005*71f41f3eSFrançois Tigeot {
2006*71f41f3eSFrançois Tigeot 	i915_gem_object_put(ring->obj);
2007*71f41f3eSFrançois Tigeot 	ring->obj = NULL;
200824edb884SFrançois Tigeot }
200924edb884SFrançois Tigeot 
2010352ff8bdSFrançois Tigeot static int intel_alloc_ringbuffer_obj(struct drm_device *dev,
2011*71f41f3eSFrançois Tigeot 				      struct intel_ring *ring)
201224edb884SFrançois Tigeot {
2013e3adcf8fSFrançois Tigeot 	struct drm_i915_gem_object *obj;
2014e3adcf8fSFrançois Tigeot 
2015a2fdbec6SFrançois Tigeot 	obj = NULL;
2016a2fdbec6SFrançois Tigeot 	if (!HAS_LLC(dev))
2017*71f41f3eSFrançois Tigeot 		obj = i915_gem_object_create_stolen(dev, ring->size);
2018a2fdbec6SFrançois Tigeot 	if (obj == NULL)
2019*71f41f3eSFrançois Tigeot 		obj = i915_gem_object_create(dev, ring->size);
20201487f786SFrançois Tigeot 	if (IS_ERR(obj))
20211487f786SFrançois Tigeot 		return PTR_ERR(obj);
2022e3adcf8fSFrançois Tigeot 
202324edb884SFrançois Tigeot 	/* mark ring buffers as read-only from GPU side by default */
202424edb884SFrançois Tigeot 	obj->gt_ro = 1;
202524edb884SFrançois Tigeot 
2026*71f41f3eSFrançois Tigeot 	ring->obj = obj;
2027ba55f2f5SFrançois Tigeot 
20282c9916cdSFrançois Tigeot 	return 0;
2029ba55f2f5SFrançois Tigeot }
2030ba55f2f5SFrançois Tigeot 
2031*71f41f3eSFrançois Tigeot struct intel_ring *
2032*71f41f3eSFrançois Tigeot intel_engine_create_ring(struct intel_engine_cs *engine, int size)
2033352ff8bdSFrançois Tigeot {
2034*71f41f3eSFrançois Tigeot 	struct intel_ring *ring;
2035352ff8bdSFrançois Tigeot 	int ret;
2036352ff8bdSFrançois Tigeot 
2037*71f41f3eSFrançois Tigeot 	GEM_BUG_ON(!is_power_of_2(size));
2038*71f41f3eSFrançois Tigeot 
2039352ff8bdSFrançois Tigeot 	ring = kzalloc(sizeof(*ring), GFP_KERNEL);
2040aee94f86SFrançois Tigeot 	if (ring == NULL) {
2041aee94f86SFrançois Tigeot 		DRM_DEBUG_DRIVER("Failed to allocate ringbuffer %s\n",
2042aee94f86SFrançois Tigeot 				 engine->name);
2043352ff8bdSFrançois Tigeot 		return ERR_PTR(-ENOMEM);
2044aee94f86SFrançois Tigeot 	}
2045352ff8bdSFrançois Tigeot 
20468621f407SFrançois Tigeot 	ring->engine = engine;
2047aee94f86SFrançois Tigeot 	list_add(&ring->link, &engine->buffers);
2048352ff8bdSFrançois Tigeot 
2049*71f41f3eSFrançois Tigeot 	INIT_LIST_HEAD(&ring->request_list);
2050*71f41f3eSFrançois Tigeot 
2051352ff8bdSFrançois Tigeot 	ring->size = size;
2052352ff8bdSFrançois Tigeot 	/* Workaround an erratum on the i830 which causes a hang if
2053352ff8bdSFrançois Tigeot 	 * the TAIL pointer points to within the last 2 cachelines
2054352ff8bdSFrançois Tigeot 	 * of the buffer.
2055352ff8bdSFrançois Tigeot 	 */
2056352ff8bdSFrançois Tigeot 	ring->effective_size = size;
20571487f786SFrançois Tigeot 	if (IS_I830(engine->i915) || IS_845G(engine->i915))
2058352ff8bdSFrançois Tigeot 		ring->effective_size -= 2 * CACHELINE_BYTES;
2059352ff8bdSFrançois Tigeot 
2060352ff8bdSFrançois Tigeot 	ring->last_retired_head = -1;
2061352ff8bdSFrançois Tigeot 	intel_ring_update_space(ring);
2062352ff8bdSFrançois Tigeot 
2063303bf270SFrançois Tigeot 	ret = intel_alloc_ringbuffer_obj(&engine->i915->drm, ring);
2064352ff8bdSFrançois Tigeot 	if (ret) {
2065aee94f86SFrançois Tigeot 		DRM_DEBUG_DRIVER("Failed to allocate ringbuffer %s: %d\n",
2066352ff8bdSFrançois Tigeot 				 engine->name, ret);
2067aee94f86SFrançois Tigeot 		list_del(&ring->link);
2068352ff8bdSFrançois Tigeot 		kfree(ring);
2069352ff8bdSFrançois Tigeot 		return ERR_PTR(ret);
2070352ff8bdSFrançois Tigeot 	}
2071352ff8bdSFrançois Tigeot 
2072352ff8bdSFrançois Tigeot 	return ring;
2073352ff8bdSFrançois Tigeot }
2074352ff8bdSFrançois Tigeot 
2075352ff8bdSFrançois Tigeot void
2076*71f41f3eSFrançois Tigeot intel_ring_free(struct intel_ring *ring)
2077352ff8bdSFrançois Tigeot {
2078352ff8bdSFrançois Tigeot 	intel_destroy_ringbuffer_obj(ring);
2079aee94f86SFrançois Tigeot 	list_del(&ring->link);
2080352ff8bdSFrançois Tigeot 	kfree(ring);
2081352ff8bdSFrançois Tigeot }
2082352ff8bdSFrançois Tigeot 
20831487f786SFrançois Tigeot static int intel_ring_context_pin(struct i915_gem_context *ctx,
20841487f786SFrançois Tigeot 				  struct intel_engine_cs *engine)
20851487f786SFrançois Tigeot {
20861487f786SFrançois Tigeot 	struct intel_context *ce = &ctx->engine[engine->id];
20871487f786SFrançois Tigeot 	int ret;
20881487f786SFrançois Tigeot 
2089303bf270SFrançois Tigeot 	lockdep_assert_held(&ctx->i915->drm.struct_mutex);
20901487f786SFrançois Tigeot 
20911487f786SFrançois Tigeot 	if (ce->pin_count++)
20921487f786SFrançois Tigeot 		return 0;
20931487f786SFrançois Tigeot 
20941487f786SFrançois Tigeot 	if (ce->state) {
2095*71f41f3eSFrançois Tigeot 		ret = i915_gem_object_ggtt_pin(ce->state, NULL, 0,
2096*71f41f3eSFrançois Tigeot 					       ctx->ggtt_alignment, 0);
20971487f786SFrançois Tigeot 		if (ret)
20981487f786SFrançois Tigeot 			goto error;
20991487f786SFrançois Tigeot 	}
21001487f786SFrançois Tigeot 
21011487f786SFrançois Tigeot 	/* The kernel context is only used as a placeholder for flushing the
21021487f786SFrançois Tigeot 	 * active context. It is never used for submitting user rendering and
21031487f786SFrançois Tigeot 	 * as such never requires the golden render context, and so we can skip
21041487f786SFrançois Tigeot 	 * emitting it when we switch to the kernel context. This is required
21051487f786SFrançois Tigeot 	 * as during eviction we cannot allocate and pin the renderstate in
21061487f786SFrançois Tigeot 	 * order to initialise the context.
21071487f786SFrançois Tigeot 	 */
21081487f786SFrançois Tigeot 	if (ctx == ctx->i915->kernel_context)
21091487f786SFrançois Tigeot 		ce->initialised = true;
21101487f786SFrançois Tigeot 
211187df8fc6SFrançois Tigeot 	i915_gem_context_get(ctx);
21121487f786SFrançois Tigeot 	return 0;
21131487f786SFrançois Tigeot 
21141487f786SFrançois Tigeot error:
21151487f786SFrançois Tigeot 	ce->pin_count = 0;
21161487f786SFrançois Tigeot 	return ret;
21171487f786SFrançois Tigeot }
21181487f786SFrançois Tigeot 
21191487f786SFrançois Tigeot static void intel_ring_context_unpin(struct i915_gem_context *ctx,
21201487f786SFrançois Tigeot 				     struct intel_engine_cs *engine)
21211487f786SFrançois Tigeot {
21221487f786SFrançois Tigeot 	struct intel_context *ce = &ctx->engine[engine->id];
21231487f786SFrançois Tigeot 
2124303bf270SFrançois Tigeot 	lockdep_assert_held(&ctx->i915->drm.struct_mutex);
21251487f786SFrançois Tigeot 
21261487f786SFrançois Tigeot 	if (--ce->pin_count)
21271487f786SFrançois Tigeot 		return;
21281487f786SFrançois Tigeot 
21291487f786SFrançois Tigeot 	if (ce->state)
21301487f786SFrançois Tigeot 		i915_gem_object_ggtt_unpin(ce->state);
21311487f786SFrançois Tigeot 
213287df8fc6SFrançois Tigeot 	i915_gem_context_put(ctx);
21331487f786SFrançois Tigeot }
21341487f786SFrançois Tigeot 
213587df8fc6SFrançois Tigeot static int intel_init_ring_buffer(struct intel_engine_cs *engine)
2136ba55f2f5SFrançois Tigeot {
213787df8fc6SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
2138*71f41f3eSFrançois Tigeot 	struct intel_ring *ring;
2139ba55f2f5SFrançois Tigeot 	int ret;
2140ba55f2f5SFrançois Tigeot 
21418621f407SFrançois Tigeot 	WARN_ON(engine->buffer);
21422c9916cdSFrançois Tigeot 
214387df8fc6SFrançois Tigeot 	intel_engine_setup_common(engine);
214487df8fc6SFrançois Tigeot 
21458621f407SFrançois Tigeot 	memset(engine->semaphore.sync_seqno, 0,
21468621f407SFrançois Tigeot 	       sizeof(engine->semaphore.sync_seqno));
2147ba55f2f5SFrançois Tigeot 
214887df8fc6SFrançois Tigeot 	ret = intel_engine_init_common(engine);
2149303bf270SFrançois Tigeot 	if (ret)
2150303bf270SFrançois Tigeot 		goto error;
2151ba55f2f5SFrançois Tigeot 
21521487f786SFrançois Tigeot 	/* We may need to do things with the shrinker which
21531487f786SFrançois Tigeot 	 * require us to immediately switch back to the default
21541487f786SFrançois Tigeot 	 * context. This can cause a problem as pinning the
21551487f786SFrançois Tigeot 	 * default context also requires GTT space which may not
21561487f786SFrançois Tigeot 	 * be available. To avoid this we always pin the default
21571487f786SFrançois Tigeot 	 * context.
21581487f786SFrançois Tigeot 	 */
21591487f786SFrançois Tigeot 	ret = intel_ring_context_pin(dev_priv->kernel_context, engine);
21601487f786SFrançois Tigeot 	if (ret)
21611487f786SFrançois Tigeot 		goto error;
21621487f786SFrançois Tigeot 
2163*71f41f3eSFrançois Tigeot 	ring = intel_engine_create_ring(engine, 32 * PAGE_SIZE);
2164*71f41f3eSFrançois Tigeot 	if (IS_ERR(ring)) {
2165*71f41f3eSFrançois Tigeot 		ret = PTR_ERR(ring);
2166aee94f86SFrançois Tigeot 		goto error;
2167aee94f86SFrançois Tigeot 	}
2168*71f41f3eSFrançois Tigeot 	engine->buffer = ring;
2169352ff8bdSFrançois Tigeot 
21701487f786SFrançois Tigeot 	if (I915_NEED_GFX_HWS(dev_priv)) {
21718621f407SFrançois Tigeot 		ret = init_status_page(engine);
2172e3adcf8fSFrançois Tigeot 		if (ret)
2173ba55f2f5SFrançois Tigeot 			goto error;
2174ba55f2f5SFrançois Tigeot 	} else {
21758621f407SFrançois Tigeot 		WARN_ON(engine->id != RCS);
21768621f407SFrançois Tigeot 		ret = init_phys_status_page(engine);
2177ba55f2f5SFrançois Tigeot 		if (ret)
2178ba55f2f5SFrançois Tigeot 			goto error;
2179ba55f2f5SFrançois Tigeot 	}
2180ba55f2f5SFrançois Tigeot 
2181*71f41f3eSFrançois Tigeot 	ret = intel_ring_pin(ring);
21822c9916cdSFrançois Tigeot 	if (ret) {
21832c9916cdSFrançois Tigeot 		DRM_ERROR("Failed to pin and map ringbuffer %s: %d\n",
21848621f407SFrançois Tigeot 				engine->name, ret);
2185*71f41f3eSFrançois Tigeot 		intel_destroy_ringbuffer_obj(ring);
2186ba55f2f5SFrançois Tigeot 		goto error;
2187ba55f2f5SFrançois Tigeot 	}
2188e3adcf8fSFrançois Tigeot 
2189e3adcf8fSFrançois Tigeot 	return 0;
2190e3adcf8fSFrançois Tigeot 
2191ba55f2f5SFrançois Tigeot error:
2192*71f41f3eSFrançois Tigeot 	intel_engine_cleanup(engine);
2193e3adcf8fSFrançois Tigeot 	return ret;
2194e3adcf8fSFrançois Tigeot }
2195e3adcf8fSFrançois Tigeot 
2196*71f41f3eSFrançois Tigeot void intel_engine_cleanup(struct intel_engine_cs *engine)
2197e3adcf8fSFrançois Tigeot {
21982c9916cdSFrançois Tigeot 	struct drm_i915_private *dev_priv;
2199e3adcf8fSFrançois Tigeot 
22008621f407SFrançois Tigeot 	if (!intel_engine_initialized(engine))
2201e3adcf8fSFrançois Tigeot 		return;
2202e3adcf8fSFrançois Tigeot 
22031487f786SFrançois Tigeot 	dev_priv = engine->i915;
22042c9916cdSFrançois Tigeot 
22058621f407SFrançois Tigeot 	if (engine->buffer) {
22061487f786SFrançois Tigeot 		WARN_ON(!IS_GEN2(dev_priv) && (I915_READ_MODE(engine) & MODE_IDLE) == 0);
2207b030f26bSFrançois Tigeot 
2208*71f41f3eSFrançois Tigeot 		intel_ring_unpin(engine->buffer);
2209*71f41f3eSFrançois Tigeot 		intel_ring_free(engine->buffer);
22108621f407SFrançois Tigeot 		engine->buffer = NULL;
2211aee94f86SFrançois Tigeot 	}
2212e3adcf8fSFrançois Tigeot 
22138621f407SFrançois Tigeot 	if (engine->cleanup)
22148621f407SFrançois Tigeot 		engine->cleanup(engine);
2215e3adcf8fSFrançois Tigeot 
22161487f786SFrançois Tigeot 	if (I915_NEED_GFX_HWS(dev_priv)) {
22178621f407SFrançois Tigeot 		cleanup_status_page(engine);
2218c0e85e96SFrançois Tigeot 	} else {
22198621f407SFrançois Tigeot 		WARN_ON(engine->id != RCS);
22208621f407SFrançois Tigeot 		cleanup_phys_status_page(engine);
2221c0e85e96SFrançois Tigeot 	}
2222ba55f2f5SFrançois Tigeot 
2223*71f41f3eSFrançois Tigeot 	intel_engine_cleanup_common(engine);
22241487f786SFrançois Tigeot 
22251487f786SFrançois Tigeot 	intel_ring_context_unpin(dev_priv->kernel_context, engine);
22261487f786SFrançois Tigeot 
22271487f786SFrançois Tigeot 	engine->i915 = NULL;
2228e3adcf8fSFrançois Tigeot }
2229e3adcf8fSFrançois Tigeot 
223019c468b4SFrançois Tigeot int intel_ring_alloc_request_extras(struct drm_i915_gem_request *request)
2231b5c29a34SFrançois Tigeot {
22321487f786SFrançois Tigeot 	int ret;
22339edbd4a0SFrançois Tigeot 
22341487f786SFrançois Tigeot 	/* Flush enough space to reduce the likelihood of waiting after
22351487f786SFrançois Tigeot 	 * we start building the request - in which case we will just
22361487f786SFrançois Tigeot 	 * have to repeat work.
2237a05eeebfSFrançois Tigeot 	 */
22381487f786SFrançois Tigeot 	request->reserved_space += LEGACY_REQUEST_SIZE;
2239a2fdbec6SFrançois Tigeot 
2240*71f41f3eSFrançois Tigeot 	request->ring = request->engine->buffer;
2241a2fdbec6SFrançois Tigeot 
22421487f786SFrançois Tigeot 	ret = intel_ring_begin(request, 0);
22431487f786SFrançois Tigeot 	if (ret)
22441487f786SFrançois Tigeot 		return ret;
2245a05eeebfSFrançois Tigeot 
22461487f786SFrançois Tigeot 	request->reserved_space -= LEGACY_REQUEST_SIZE;
22471487f786SFrançois Tigeot 	return 0;
2248a05eeebfSFrançois Tigeot }
2249a05eeebfSFrançois Tigeot 
22508621f407SFrançois Tigeot static int wait_for_space(struct drm_i915_gem_request *req, int bytes)
2251a05eeebfSFrançois Tigeot {
2252*71f41f3eSFrançois Tigeot 	struct intel_ring *ring = req->ring;
22538621f407SFrançois Tigeot 	struct drm_i915_gem_request *target;
2254*71f41f3eSFrançois Tigeot 	int ret;
22558621f407SFrançois Tigeot 
2256*71f41f3eSFrançois Tigeot 	intel_ring_update_space(ring);
2257*71f41f3eSFrançois Tigeot 	if (ring->space >= bytes)
22588621f407SFrançois Tigeot 		return 0;
22598621f407SFrançois Tigeot 
22608621f407SFrançois Tigeot 	/*
22618621f407SFrançois Tigeot 	 * Space is reserved in the ringbuffer for finalising the request,
22628621f407SFrançois Tigeot 	 * as that cannot be allowed to fail. During request finalisation,
22638621f407SFrançois Tigeot 	 * reserved_space is set to 0 to stop the overallocation and the
22648621f407SFrançois Tigeot 	 * assumption is that then we never need to wait (which has the
22658621f407SFrançois Tigeot 	 * risk of failing with EINTR).
22668621f407SFrançois Tigeot 	 *
22678621f407SFrançois Tigeot 	 * See also i915_gem_request_alloc() and i915_add_request().
22688621f407SFrançois Tigeot 	 */
22691487f786SFrançois Tigeot 	GEM_BUG_ON(!req->reserved_space);
22708621f407SFrançois Tigeot 
2271*71f41f3eSFrançois Tigeot 	list_for_each_entry(target, &ring->request_list, ring_link) {
22728621f407SFrançois Tigeot 		unsigned space;
22738621f407SFrançois Tigeot 
22748621f407SFrançois Tigeot 		/* Would completion of this request free enough space? */
2275*71f41f3eSFrançois Tigeot 		space = __intel_ring_space(target->postfix, ring->tail,
2276*71f41f3eSFrançois Tigeot 					   ring->size);
22778621f407SFrançois Tigeot 		if (space >= bytes)
22788621f407SFrançois Tigeot 			break;
22798621f407SFrançois Tigeot 	}
22808621f407SFrançois Tigeot 
2281*71f41f3eSFrançois Tigeot 	if (WARN_ON(&target->ring_link == &ring->request_list))
22828621f407SFrançois Tigeot 		return -ENOSPC;
22838621f407SFrançois Tigeot 
2284*71f41f3eSFrançois Tigeot 	ret = i915_wait_request(target, true, NULL, NO_WAITBOOST);
2285*71f41f3eSFrançois Tigeot 	if (ret)
2286*71f41f3eSFrançois Tigeot 		return ret;
2287*71f41f3eSFrançois Tigeot 
2288*71f41f3eSFrançois Tigeot 	if (i915_reset_in_progress(&target->i915->gpu_error))
2289*71f41f3eSFrançois Tigeot 		return -EAGAIN;
2290*71f41f3eSFrançois Tigeot 
2291*71f41f3eSFrançois Tigeot 	i915_gem_request_retire_upto(target);
2292*71f41f3eSFrançois Tigeot 
2293*71f41f3eSFrançois Tigeot 	intel_ring_update_space(ring);
2294*71f41f3eSFrançois Tigeot 	GEM_BUG_ON(ring->space < bytes);
2295*71f41f3eSFrançois Tigeot 	return 0;
22968621f407SFrançois Tigeot }
22978621f407SFrançois Tigeot 
22988621f407SFrançois Tigeot int intel_ring_begin(struct drm_i915_gem_request *req, int num_dwords)
22998621f407SFrançois Tigeot {
2300*71f41f3eSFrançois Tigeot 	struct intel_ring *ring = req->ring;
2301*71f41f3eSFrançois Tigeot 	int remain_actual = ring->size - ring->tail;
2302*71f41f3eSFrançois Tigeot 	int remain_usable = ring->effective_size - ring->tail;
23038621f407SFrançois Tigeot 	int bytes = num_dwords * sizeof(u32);
23048621f407SFrançois Tigeot 	int total_bytes, wait_bytes;
2305a05eeebfSFrançois Tigeot 	bool need_wrap = false;
2306a05eeebfSFrançois Tigeot 
23071487f786SFrançois Tigeot 	total_bytes = bytes + req->reserved_space;
2308a05eeebfSFrançois Tigeot 
2309a05eeebfSFrançois Tigeot 	if (unlikely(bytes > remain_usable)) {
2310a05eeebfSFrançois Tigeot 		/*
2311a05eeebfSFrançois Tigeot 		 * Not enough space for the basic request. So need to flush
2312a05eeebfSFrançois Tigeot 		 * out the remainder and then wait for base + reserved.
2313a05eeebfSFrançois Tigeot 		 */
2314a05eeebfSFrançois Tigeot 		wait_bytes = remain_actual + total_bytes;
2315a05eeebfSFrançois Tigeot 		need_wrap = true;
23168621f407SFrançois Tigeot 	} else if (unlikely(total_bytes > remain_usable)) {
2317a05eeebfSFrançois Tigeot 		/*
2318a05eeebfSFrançois Tigeot 		 * The base request will fit but the reserved space
23198621f407SFrançois Tigeot 		 * falls off the end. So we don't need an immediate wrap
2320c0e85e96SFrançois Tigeot 		 * and only need to effectively wait for the reserved
2321c0e85e96SFrançois Tigeot 		 * size space from the start of ringbuffer.
2322a05eeebfSFrançois Tigeot 		 */
23231487f786SFrançois Tigeot 		wait_bytes = remain_actual + req->reserved_space;
23248621f407SFrançois Tigeot 	} else {
2325a05eeebfSFrançois Tigeot 		/* No wrapping required, just waiting. */
2326a05eeebfSFrançois Tigeot 		wait_bytes = total_bytes;
2327a05eeebfSFrançois Tigeot 	}
2328a05eeebfSFrançois Tigeot 
2329*71f41f3eSFrançois Tigeot 	if (wait_bytes > ring->space) {
23308621f407SFrançois Tigeot 		int ret = wait_for_space(req, wait_bytes);
2331a2fdbec6SFrançois Tigeot 		if (unlikely(ret))
2332a2fdbec6SFrançois Tigeot 			return ret;
2333a2fdbec6SFrançois Tigeot 	}
2334a2fdbec6SFrançois Tigeot 
23358621f407SFrançois Tigeot 	if (unlikely(need_wrap)) {
2336*71f41f3eSFrançois Tigeot 		GEM_BUG_ON(remain_actual > ring->space);
2337*71f41f3eSFrançois Tigeot 		GEM_BUG_ON(ring->tail + remain_actual > ring->size);
23388621f407SFrançois Tigeot 
23398621f407SFrançois Tigeot 		/* Fill the tail with MI_NOOP */
2340*71f41f3eSFrançois Tigeot 		memset(ring->vaddr + ring->tail, 0, remain_actual);
2341*71f41f3eSFrançois Tigeot 		ring->tail = 0;
2342*71f41f3eSFrançois Tigeot 		ring->space -= remain_actual;
2343a2fdbec6SFrançois Tigeot 	}
2344a2fdbec6SFrançois Tigeot 
2345*71f41f3eSFrançois Tigeot 	ring->space -= bytes;
2346*71f41f3eSFrançois Tigeot 	GEM_BUG_ON(ring->space < 0);
23479edbd4a0SFrançois Tigeot 	return 0;
23489edbd4a0SFrançois Tigeot }
23499edbd4a0SFrançois Tigeot 
23509edbd4a0SFrançois Tigeot /* Align the ring tail to a cacheline boundary */
2351a05eeebfSFrançois Tigeot int intel_ring_cacheline_align(struct drm_i915_gem_request *req)
23529edbd4a0SFrançois Tigeot {
2353*71f41f3eSFrançois Tigeot 	struct intel_ring *ring = req->ring;
2354*71f41f3eSFrançois Tigeot 	int num_dwords =
2355*71f41f3eSFrançois Tigeot 		(ring->tail & (CACHELINE_BYTES - 1)) / sizeof(uint32_t);
23569edbd4a0SFrançois Tigeot 	int ret;
23579edbd4a0SFrançois Tigeot 
23589edbd4a0SFrançois Tigeot 	if (num_dwords == 0)
23599edbd4a0SFrançois Tigeot 		return 0;
23609edbd4a0SFrançois Tigeot 
2361ba55f2f5SFrançois Tigeot 	num_dwords = CACHELINE_BYTES / sizeof(uint32_t) - num_dwords;
2362a05eeebfSFrançois Tigeot 	ret = intel_ring_begin(req, num_dwords);
23639edbd4a0SFrançois Tigeot 	if (ret)
23649edbd4a0SFrançois Tigeot 		return ret;
23659edbd4a0SFrançois Tigeot 
23669edbd4a0SFrançois Tigeot 	while (num_dwords--)
2367*71f41f3eSFrançois Tigeot 		intel_ring_emit(ring, MI_NOOP);
23689edbd4a0SFrançois Tigeot 
2369*71f41f3eSFrançois Tigeot 	intel_ring_advance(ring);
23709edbd4a0SFrançois Tigeot 
23719edbd4a0SFrançois Tigeot 	return 0;
2372e3adcf8fSFrançois Tigeot }
2373e3adcf8fSFrançois Tigeot 
2374*71f41f3eSFrançois Tigeot void intel_engine_init_seqno(struct intel_engine_cs *engine, u32 seqno)
2375a2fdbec6SFrançois Tigeot {
23761487f786SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
2377a2fdbec6SFrançois Tigeot 
23788621f407SFrançois Tigeot 	/* Our semaphore implementation is strictly monotonic (i.e. we proceed
23798621f407SFrançois Tigeot 	 * so long as the semaphore value in the register/page is greater
23808621f407SFrançois Tigeot 	 * than the sync value), so whenever we reset the seqno,
23818621f407SFrançois Tigeot 	 * so long as we reset the tracking semaphore value to 0, it will
23828621f407SFrançois Tigeot 	 * always be before the next request's seqno. If we don't reset
23838621f407SFrançois Tigeot 	 * the semaphore value, then when the seqno moves backwards all
23848621f407SFrançois Tigeot 	 * future waits will complete instantly (causing rendering corruption).
23858621f407SFrançois Tigeot 	 */
23861487f786SFrançois Tigeot 	if (IS_GEN6(dev_priv) || IS_GEN7(dev_priv)) {
23878621f407SFrançois Tigeot 		I915_WRITE(RING_SYNC_0(engine->mmio_base), 0);
23888621f407SFrançois Tigeot 		I915_WRITE(RING_SYNC_1(engine->mmio_base), 0);
23898621f407SFrançois Tigeot 		if (HAS_VEBOX(dev_priv))
23908621f407SFrançois Tigeot 			I915_WRITE(RING_SYNC_2(engine->mmio_base), 0);
23918621f407SFrançois Tigeot 	}
23928621f407SFrançois Tigeot 	if (dev_priv->semaphore_obj) {
23938621f407SFrançois Tigeot 		struct drm_i915_gem_object *obj = dev_priv->semaphore_obj;
2394f0bba3d1SFrançois Tigeot 		struct page *page = i915_gem_object_get_dirty_page(obj, 0);
23951487f786SFrançois Tigeot 		void *semaphores = kmap(page);
23968621f407SFrançois Tigeot 		memset(semaphores + GEN8_SEMAPHORE_OFFSET(engine->id, 0),
23978621f407SFrançois Tigeot 		       0, I915_NUM_ENGINES * gen8_semaphore_seqno_size);
23988621f407SFrançois Tigeot 		kunmap(page);
23998621f407SFrançois Tigeot 	}
24008621f407SFrançois Tigeot 	memset(engine->semaphore.sync_seqno, 0,
24018621f407SFrançois Tigeot 	       sizeof(engine->semaphore.sync_seqno));
24028621f407SFrançois Tigeot 
2403303bf270SFrançois Tigeot 	intel_write_status_page(engine, I915_GEM_HWS_INDEX, seqno);
2404303bf270SFrançois Tigeot 	if (engine->irq_seqno_barrier)
2405303bf270SFrançois Tigeot 		engine->irq_seqno_barrier(engine);
24068621f407SFrançois Tigeot 	engine->last_submitted_seqno = seqno;
24078621f407SFrançois Tigeot 
24088621f407SFrançois Tigeot 	engine->hangcheck.seqno = seqno;
2409303bf270SFrançois Tigeot 
2410303bf270SFrançois Tigeot 	/* After manually advancing the seqno, fake the interrupt in case
2411303bf270SFrançois Tigeot 	 * there are any waiters for that seqno.
2412303bf270SFrançois Tigeot 	 */
2413303bf270SFrançois Tigeot 	rcu_read_lock();
2414303bf270SFrançois Tigeot 	intel_engine_wakeup(engine);
2415303bf270SFrançois Tigeot 	rcu_read_unlock();
2416e3adcf8fSFrançois Tigeot }
2417e3adcf8fSFrançois Tigeot 
2418*71f41f3eSFrançois Tigeot static void gen6_bsd_submit_request(struct drm_i915_gem_request *request)
2419e3adcf8fSFrançois Tigeot {
2420*71f41f3eSFrançois Tigeot 	struct drm_i915_private *dev_priv = request->i915;
24211487f786SFrançois Tigeot 
24221487f786SFrançois Tigeot 	intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL);
2423e3adcf8fSFrançois Tigeot 
2424e3adcf8fSFrançois Tigeot        /* Every tail move must follow the sequence below */
2425f4e1c372SFrançois Tigeot 
2426f4e1c372SFrançois Tigeot 	/* Disable notification that the ring is IDLE. The GT
2427f4e1c372SFrançois Tigeot 	 * will then assume that it is busy and bring it out of rc6.
2428f4e1c372SFrançois Tigeot 	 */
24291487f786SFrançois Tigeot 	I915_WRITE_FW(GEN6_BSD_SLEEP_PSMI_CONTROL,
2430f4e1c372SFrançois Tigeot 		      _MASKED_BIT_ENABLE(GEN6_BSD_SLEEP_MSG_DISABLE));
2431e3adcf8fSFrançois Tigeot 
2432f4e1c372SFrançois Tigeot 	/* Clear the context id. Here be magic! */
24331487f786SFrançois Tigeot 	I915_WRITE64_FW(GEN6_BSD_RNCID, 0x0);
2434e3adcf8fSFrançois Tigeot 
2435f4e1c372SFrançois Tigeot 	/* Wait for the ring not to be idle, i.e. for it to wake up. */
24361487f786SFrançois Tigeot 	if (intel_wait_for_register_fw(dev_priv,
24371487f786SFrançois Tigeot 				       GEN6_BSD_SLEEP_PSMI_CONTROL,
24381487f786SFrançois Tigeot 				       GEN6_BSD_SLEEP_INDICATOR,
24391487f786SFrançois Tigeot 				       0,
2440f4e1c372SFrançois Tigeot 				       50))
2441f4e1c372SFrançois Tigeot 		DRM_ERROR("timed out waiting for the BSD ring to wake up\n");
2442f4e1c372SFrançois Tigeot 
2443f4e1c372SFrançois Tigeot 	/* Now that the ring is fully powered up, update the tail */
2444*71f41f3eSFrançois Tigeot 	i9xx_submit_request(request);
2445f4e1c372SFrançois Tigeot 
2446f4e1c372SFrançois Tigeot 	/* Let the ring send IDLE messages to the GT again,
2447f4e1c372SFrançois Tigeot 	 * and so let it sleep to conserve power when idle.
2448f4e1c372SFrançois Tigeot 	 */
24491487f786SFrançois Tigeot 	I915_WRITE_FW(GEN6_BSD_SLEEP_PSMI_CONTROL,
2450f4e1c372SFrançois Tigeot 		      _MASKED_BIT_DISABLE(GEN6_BSD_SLEEP_MSG_DISABLE));
24511487f786SFrançois Tigeot 
24521487f786SFrançois Tigeot 	intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL);
2453e3adcf8fSFrançois Tigeot }
2454e3adcf8fSFrançois Tigeot 
2455*71f41f3eSFrançois Tigeot static int gen6_bsd_ring_flush(struct drm_i915_gem_request *req, u32 mode)
2456e3adcf8fSFrançois Tigeot {
2457*71f41f3eSFrançois Tigeot 	struct intel_ring *ring = req->ring;
2458e3adcf8fSFrançois Tigeot 	uint32_t cmd;
2459e3adcf8fSFrançois Tigeot 	int ret;
2460e3adcf8fSFrançois Tigeot 
2461a05eeebfSFrançois Tigeot 	ret = intel_ring_begin(req, 4);
2462e3adcf8fSFrançois Tigeot 	if (ret)
2463e3adcf8fSFrançois Tigeot 		return ret;
2464e3adcf8fSFrançois Tigeot 
2465e3adcf8fSFrançois Tigeot 	cmd = MI_FLUSH_DW;
24661487f786SFrançois Tigeot 	if (INTEL_GEN(req->i915) >= 8)
24679edbd4a0SFrançois Tigeot 		cmd += 1;
24682c9916cdSFrançois Tigeot 
24692c9916cdSFrançois Tigeot 	/* We always require a command barrier so that subsequent
24702c9916cdSFrançois Tigeot 	 * commands, such as breadcrumb interrupts, are strictly ordered
24712c9916cdSFrançois Tigeot 	 * wrt the contents of the write cache being flushed to memory
24722c9916cdSFrançois Tigeot 	 * (and thus being coherent from the CPU).
24732c9916cdSFrançois Tigeot 	 */
24742c9916cdSFrançois Tigeot 	cmd |= MI_FLUSH_DW_STORE_INDEX | MI_FLUSH_DW_OP_STOREDW;
24752c9916cdSFrançois Tigeot 
2476b5c29a34SFrançois Tigeot 	/*
2477b5c29a34SFrançois Tigeot 	 * Bspec vol 1c.5 - video engine command streamer:
2478b5c29a34SFrançois Tigeot 	 * "If ENABLED, all TLBs will be invalidated once the flush
2479b5c29a34SFrançois Tigeot 	 * operation is complete. This bit is only valid when the
2480b5c29a34SFrançois Tigeot 	 * Post-Sync Operation field is a value of 1h or 3h."
2481b5c29a34SFrançois Tigeot 	 */
2482*71f41f3eSFrançois Tigeot 	if (mode & EMIT_INVALIDATE)
24832c9916cdSFrançois Tigeot 		cmd |= MI_INVALIDATE_TLB | MI_INVALIDATE_BSD;
24842c9916cdSFrançois Tigeot 
2485*71f41f3eSFrançois Tigeot 	intel_ring_emit(ring, cmd);
2486*71f41f3eSFrançois Tigeot 	intel_ring_emit(ring, I915_GEM_HWS_SCRATCH_ADDR | MI_FLUSH_DW_USE_GTT);
24871487f786SFrançois Tigeot 	if (INTEL_GEN(req->i915) >= 8) {
2488*71f41f3eSFrançois Tigeot 		intel_ring_emit(ring, 0); /* upper addr */
2489*71f41f3eSFrançois Tigeot 		intel_ring_emit(ring, 0); /* value */
24909edbd4a0SFrançois Tigeot 	} else  {
2491*71f41f3eSFrançois Tigeot 		intel_ring_emit(ring, 0);
2492*71f41f3eSFrançois Tigeot 		intel_ring_emit(ring, MI_NOOP);
24939edbd4a0SFrançois Tigeot 	}
2494*71f41f3eSFrançois Tigeot 	intel_ring_advance(ring);
24959edbd4a0SFrançois Tigeot 	return 0;
24969edbd4a0SFrançois Tigeot }
24979edbd4a0SFrançois Tigeot 
24989edbd4a0SFrançois Tigeot static int
2499*71f41f3eSFrançois Tigeot gen8_emit_bb_start(struct drm_i915_gem_request *req,
2500ba55f2f5SFrançois Tigeot 		   u64 offset, u32 len,
2501*71f41f3eSFrançois Tigeot 		   unsigned int dispatch_flags)
25029edbd4a0SFrançois Tigeot {
2503*71f41f3eSFrançois Tigeot 	struct intel_ring *ring = req->ring;
2504*71f41f3eSFrançois Tigeot 	bool ppgtt = USES_PPGTT(req->i915) &&
2505477eb7f9SFrançois Tigeot 			!(dispatch_flags & I915_DISPATCH_SECURE);
25069edbd4a0SFrançois Tigeot 	int ret;
25079edbd4a0SFrançois Tigeot 
2508a05eeebfSFrançois Tigeot 	ret = intel_ring_begin(req, 4);
25099edbd4a0SFrançois Tigeot 	if (ret)
25109edbd4a0SFrançois Tigeot 		return ret;
25119edbd4a0SFrançois Tigeot 
25129edbd4a0SFrançois Tigeot 	/* FIXME(BDW): Address space and security selectors. */
2513*71f41f3eSFrançois Tigeot 	intel_ring_emit(ring, MI_BATCH_BUFFER_START_GEN8 | (ppgtt<<8) |
2514a05eeebfSFrançois Tigeot 			(dispatch_flags & I915_DISPATCH_RS ?
2515a05eeebfSFrançois Tigeot 			 MI_BATCH_RESOURCE_STREAMER : 0));
2516*71f41f3eSFrançois Tigeot 	intel_ring_emit(ring, lower_32_bits(offset));
2517*71f41f3eSFrançois Tigeot 	intel_ring_emit(ring, upper_32_bits(offset));
2518*71f41f3eSFrançois Tigeot 	intel_ring_emit(ring, MI_NOOP);
2519*71f41f3eSFrançois Tigeot 	intel_ring_advance(ring);
25209edbd4a0SFrançois Tigeot 
2521e3adcf8fSFrançois Tigeot 	return 0;
2522e3adcf8fSFrançois Tigeot }
2523e3adcf8fSFrançois Tigeot 
2524e3adcf8fSFrançois Tigeot static int
2525*71f41f3eSFrançois Tigeot hsw_emit_bb_start(struct drm_i915_gem_request *req,
2526ba55f2f5SFrançois Tigeot 		  u64 offset, u32 len,
2527*71f41f3eSFrançois Tigeot 		  unsigned int dispatch_flags)
2528e3adcf8fSFrançois Tigeot {
2529*71f41f3eSFrançois Tigeot 	struct intel_ring *ring = req->ring;
2530e3adcf8fSFrançois Tigeot 	int ret;
2531e3adcf8fSFrançois Tigeot 
2532a05eeebfSFrançois Tigeot 	ret = intel_ring_begin(req, 2);
2533e3adcf8fSFrançois Tigeot 	if (ret)
2534e3adcf8fSFrançois Tigeot 		return ret;
2535e3adcf8fSFrançois Tigeot 
2536*71f41f3eSFrançois Tigeot 	intel_ring_emit(ring,
25371b13d190SFrançois Tigeot 			MI_BATCH_BUFFER_START |
2538477eb7f9SFrançois Tigeot 			(dispatch_flags & I915_DISPATCH_SECURE ?
2539a05eeebfSFrançois Tigeot 			 0 : MI_BATCH_PPGTT_HSW | MI_BATCH_NON_SECURE_HSW) |
2540a05eeebfSFrançois Tigeot 			(dispatch_flags & I915_DISPATCH_RS ?
2541a05eeebfSFrançois Tigeot 			 MI_BATCH_RESOURCE_STREAMER : 0));
2542b5c29a34SFrançois Tigeot 	/* bit0-7 is the length on GEN6+ */
2543*71f41f3eSFrançois Tigeot 	intel_ring_emit(ring, offset);
2544*71f41f3eSFrançois Tigeot 	intel_ring_advance(ring);
2545b5c29a34SFrançois Tigeot 
2546b5c29a34SFrançois Tigeot 	return 0;
2547b5c29a34SFrançois Tigeot }
2548b5c29a34SFrançois Tigeot 
2549b5c29a34SFrançois Tigeot static int
2550*71f41f3eSFrançois Tigeot gen6_emit_bb_start(struct drm_i915_gem_request *req,
2551ba55f2f5SFrançois Tigeot 		   u64 offset, u32 len,
2552*71f41f3eSFrançois Tigeot 		   unsigned int dispatch_flags)
2553b5c29a34SFrançois Tigeot {
2554*71f41f3eSFrançois Tigeot 	struct intel_ring *ring = req->ring;
2555b5c29a34SFrançois Tigeot 	int ret;
2556b5c29a34SFrançois Tigeot 
2557a05eeebfSFrançois Tigeot 	ret = intel_ring_begin(req, 2);
2558b5c29a34SFrançois Tigeot 	if (ret)
2559b5c29a34SFrançois Tigeot 		return ret;
2560b5c29a34SFrançois Tigeot 
2561*71f41f3eSFrançois Tigeot 	intel_ring_emit(ring,
2562b5c29a34SFrançois Tigeot 			MI_BATCH_BUFFER_START |
2563477eb7f9SFrançois Tigeot 			(dispatch_flags & I915_DISPATCH_SECURE ?
2564477eb7f9SFrançois Tigeot 			 0 : MI_BATCH_NON_SECURE_I965));
2565e3adcf8fSFrançois Tigeot 	/* bit0-7 is the length on GEN6+ */
2566*71f41f3eSFrançois Tigeot 	intel_ring_emit(ring, offset);
2567*71f41f3eSFrançois Tigeot 	intel_ring_advance(ring);
2568e3adcf8fSFrançois Tigeot 
2569e3adcf8fSFrançois Tigeot 	return 0;
2570e3adcf8fSFrançois Tigeot }
2571e3adcf8fSFrançois Tigeot 
2572e3adcf8fSFrançois Tigeot /* Blitter support (SandyBridge+) */
2573e3adcf8fSFrançois Tigeot 
2574*71f41f3eSFrançois Tigeot static int gen6_ring_flush(struct drm_i915_gem_request *req, u32 mode)
2575e3adcf8fSFrançois Tigeot {
2576*71f41f3eSFrançois Tigeot 	struct intel_ring *ring = req->ring;
2577e3adcf8fSFrançois Tigeot 	uint32_t cmd;
2578e3adcf8fSFrançois Tigeot 	int ret;
2579e3adcf8fSFrançois Tigeot 
2580a05eeebfSFrançois Tigeot 	ret = intel_ring_begin(req, 4);
2581e3adcf8fSFrançois Tigeot 	if (ret)
2582e3adcf8fSFrançois Tigeot 		return ret;
2583e3adcf8fSFrançois Tigeot 
2584e3adcf8fSFrançois Tigeot 	cmd = MI_FLUSH_DW;
25851487f786SFrançois Tigeot 	if (INTEL_GEN(req->i915) >= 8)
25869edbd4a0SFrançois Tigeot 		cmd += 1;
25872c9916cdSFrançois Tigeot 
25882c9916cdSFrançois Tigeot 	/* We always require a command barrier so that subsequent
25892c9916cdSFrançois Tigeot 	 * commands, such as breadcrumb interrupts, are strictly ordered
25902c9916cdSFrançois Tigeot 	 * wrt the contents of the write cache being flushed to memory
25912c9916cdSFrançois Tigeot 	 * (and thus being coherent from the CPU).
25922c9916cdSFrançois Tigeot 	 */
25932c9916cdSFrançois Tigeot 	cmd |= MI_FLUSH_DW_STORE_INDEX | MI_FLUSH_DW_OP_STOREDW;
25942c9916cdSFrançois Tigeot 
2595b5c29a34SFrançois Tigeot 	/*
2596b5c29a34SFrançois Tigeot 	 * Bspec vol 1c.3 - blitter engine command streamer:
2597b5c29a34SFrançois Tigeot 	 * "If ENABLED, all TLBs will be invalidated once the flush
2598b5c29a34SFrançois Tigeot 	 * operation is complete. This bit is only valid when the
2599b5c29a34SFrançois Tigeot 	 * Post-Sync Operation field is a value of 1h or 3h."
2600b5c29a34SFrançois Tigeot 	 */
2601*71f41f3eSFrançois Tigeot 	if (mode & EMIT_INVALIDATE)
26022c9916cdSFrançois Tigeot 		cmd |= MI_INVALIDATE_TLB;
2603*71f41f3eSFrançois Tigeot 	intel_ring_emit(ring, cmd);
2604*71f41f3eSFrançois Tigeot 	intel_ring_emit(ring,
26058621f407SFrançois Tigeot 			I915_GEM_HWS_SCRATCH_ADDR | MI_FLUSH_DW_USE_GTT);
26061487f786SFrançois Tigeot 	if (INTEL_GEN(req->i915) >= 8) {
2607*71f41f3eSFrançois Tigeot 		intel_ring_emit(ring, 0); /* upper addr */
2608*71f41f3eSFrançois Tigeot 		intel_ring_emit(ring, 0); /* value */
26099edbd4a0SFrançois Tigeot 	} else  {
2610*71f41f3eSFrançois Tigeot 		intel_ring_emit(ring, 0);
2611*71f41f3eSFrançois Tigeot 		intel_ring_emit(ring, MI_NOOP);
26129edbd4a0SFrançois Tigeot 	}
2613*71f41f3eSFrançois Tigeot 	intel_ring_advance(ring);
26145d0b1887SFrançois Tigeot 
2615e3adcf8fSFrançois Tigeot 	return 0;
2616e3adcf8fSFrançois Tigeot }
2617e3adcf8fSFrançois Tigeot 
26181487f786SFrançois Tigeot static void intel_ring_init_semaphores(struct drm_i915_private *dev_priv,
26191487f786SFrançois Tigeot 				       struct intel_engine_cs *engine)
26201487f786SFrançois Tigeot {
26211487f786SFrançois Tigeot 	struct drm_i915_gem_object *obj;
26221487f786SFrançois Tigeot 	int ret, i;
26231487f786SFrançois Tigeot 
262487df8fc6SFrançois Tigeot 	if (!i915.semaphores)
26251487f786SFrançois Tigeot 		return;
26261487f786SFrançois Tigeot 
26271487f786SFrançois Tigeot 	if (INTEL_GEN(dev_priv) >= 8 && !dev_priv->semaphore_obj) {
2628303bf270SFrançois Tigeot 		obj = i915_gem_object_create(&dev_priv->drm, 4096);
26291487f786SFrançois Tigeot 		if (IS_ERR(obj)) {
26301487f786SFrançois Tigeot 			DRM_ERROR("Failed to allocate semaphore bo. Disabling semaphores\n");
26311487f786SFrançois Tigeot 			i915.semaphores = 0;
26321487f786SFrançois Tigeot 		} else {
26331487f786SFrançois Tigeot 			i915_gem_object_set_cache_level(obj, I915_CACHE_LLC);
2634*71f41f3eSFrançois Tigeot 			ret = i915_gem_object_ggtt_pin(obj, NULL, 0, 0, 0);
26351487f786SFrançois Tigeot 			if (ret != 0) {
263687df8fc6SFrançois Tigeot 				i915_gem_object_put(obj);
26371487f786SFrançois Tigeot 				DRM_ERROR("Failed to pin semaphore bo. Disabling semaphores\n");
26381487f786SFrançois Tigeot 				i915.semaphores = 0;
26391487f786SFrançois Tigeot 			} else {
26401487f786SFrançois Tigeot 				dev_priv->semaphore_obj = obj;
26411487f786SFrançois Tigeot 			}
26421487f786SFrançois Tigeot 		}
26431487f786SFrançois Tigeot 	}
26441487f786SFrançois Tigeot 
264587df8fc6SFrançois Tigeot 	if (!i915.semaphores)
26461487f786SFrançois Tigeot 		return;
26471487f786SFrançois Tigeot 
26481487f786SFrançois Tigeot 	if (INTEL_GEN(dev_priv) >= 8) {
26491487f786SFrançois Tigeot 		u64 offset = i915_gem_obj_ggtt_offset(dev_priv->semaphore_obj);
26501487f786SFrançois Tigeot 
2651*71f41f3eSFrançois Tigeot 		engine->semaphore.sync_to = gen8_ring_sync_to;
26521487f786SFrançois Tigeot 		engine->semaphore.signal = gen8_xcs_signal;
26531487f786SFrançois Tigeot 
26541487f786SFrançois Tigeot 		for (i = 0; i < I915_NUM_ENGINES; i++) {
26551487f786SFrançois Tigeot 			u64 ring_offset;
26561487f786SFrançois Tigeot 
26571487f786SFrançois Tigeot 			if (i != engine->id)
26581487f786SFrançois Tigeot 				ring_offset = offset + GEN8_SEMAPHORE_OFFSET(engine->id, i);
26591487f786SFrançois Tigeot 			else
26601487f786SFrançois Tigeot 				ring_offset = MI_SEMAPHORE_SYNC_INVALID;
26611487f786SFrançois Tigeot 
26621487f786SFrançois Tigeot 			engine->semaphore.signal_ggtt[i] = ring_offset;
26631487f786SFrançois Tigeot 		}
26641487f786SFrançois Tigeot 	} else if (INTEL_GEN(dev_priv) >= 6) {
2665*71f41f3eSFrançois Tigeot 		engine->semaphore.sync_to = gen6_ring_sync_to;
26661487f786SFrançois Tigeot 		engine->semaphore.signal = gen6_signal;
26671487f786SFrançois Tigeot 
26681487f786SFrançois Tigeot 		/*
26691487f786SFrançois Tigeot 		 * The current semaphore is only applied on pre-gen8
26701487f786SFrançois Tigeot 		 * platform.  And there is no VCS2 ring on the pre-gen8
26711487f786SFrançois Tigeot 		 * platform. So the semaphore between RCS and VCS2 is
26721487f786SFrançois Tigeot 		 * initialized as INVALID.  Gen8 will initialize the
26731487f786SFrançois Tigeot 		 * sema between VCS2 and RCS later.
26741487f786SFrançois Tigeot 		 */
26751487f786SFrançois Tigeot 		for (i = 0; i < I915_NUM_ENGINES; i++) {
26761487f786SFrançois Tigeot 			static const struct {
26771487f786SFrançois Tigeot 				u32 wait_mbox;
26781487f786SFrançois Tigeot 				i915_reg_t mbox_reg;
26791487f786SFrançois Tigeot 			} sem_data[I915_NUM_ENGINES][I915_NUM_ENGINES] = {
26801487f786SFrançois Tigeot 				[RCS] = {
26811487f786SFrançois Tigeot 					[VCS] =  { .wait_mbox = MI_SEMAPHORE_SYNC_RV,  .mbox_reg = GEN6_VRSYNC },
26821487f786SFrançois Tigeot 					[BCS] =  { .wait_mbox = MI_SEMAPHORE_SYNC_RB,  .mbox_reg = GEN6_BRSYNC },
26831487f786SFrançois Tigeot 					[VECS] = { .wait_mbox = MI_SEMAPHORE_SYNC_RVE, .mbox_reg = GEN6_VERSYNC },
26841487f786SFrançois Tigeot 				},
26851487f786SFrançois Tigeot 				[VCS] = {
26861487f786SFrançois Tigeot 					[RCS] =  { .wait_mbox = MI_SEMAPHORE_SYNC_VR,  .mbox_reg = GEN6_RVSYNC },
26871487f786SFrançois Tigeot 					[BCS] =  { .wait_mbox = MI_SEMAPHORE_SYNC_VB,  .mbox_reg = GEN6_BVSYNC },
26881487f786SFrançois Tigeot 					[VECS] = { .wait_mbox = MI_SEMAPHORE_SYNC_VVE, .mbox_reg = GEN6_VEVSYNC },
26891487f786SFrançois Tigeot 				},
26901487f786SFrançois Tigeot 				[BCS] = {
26911487f786SFrançois Tigeot 					[RCS] =  { .wait_mbox = MI_SEMAPHORE_SYNC_BR,  .mbox_reg = GEN6_RBSYNC },
26921487f786SFrançois Tigeot 					[VCS] =  { .wait_mbox = MI_SEMAPHORE_SYNC_BV,  .mbox_reg = GEN6_VBSYNC },
26931487f786SFrançois Tigeot 					[VECS] = { .wait_mbox = MI_SEMAPHORE_SYNC_BVE, .mbox_reg = GEN6_VEBSYNC },
26941487f786SFrançois Tigeot 				},
26951487f786SFrançois Tigeot 				[VECS] = {
26961487f786SFrançois Tigeot 					[RCS] =  { .wait_mbox = MI_SEMAPHORE_SYNC_VER, .mbox_reg = GEN6_RVESYNC },
26971487f786SFrançois Tigeot 					[VCS] =  { .wait_mbox = MI_SEMAPHORE_SYNC_VEV, .mbox_reg = GEN6_VVESYNC },
26981487f786SFrançois Tigeot 					[BCS] =  { .wait_mbox = MI_SEMAPHORE_SYNC_VEB, .mbox_reg = GEN6_BVESYNC },
26991487f786SFrançois Tigeot 				},
27001487f786SFrançois Tigeot 			};
27011487f786SFrançois Tigeot 			u32 wait_mbox;
27021487f786SFrançois Tigeot 			i915_reg_t mbox_reg;
27031487f786SFrançois Tigeot 
27041487f786SFrançois Tigeot 			if (i == engine->id || i == VCS2) {
27051487f786SFrançois Tigeot 				wait_mbox = MI_SEMAPHORE_SYNC_INVALID;
27061487f786SFrançois Tigeot 				mbox_reg = GEN6_NOSYNC;
27071487f786SFrançois Tigeot 			} else {
27081487f786SFrançois Tigeot 				wait_mbox = sem_data[engine->id][i].wait_mbox;
27091487f786SFrançois Tigeot 				mbox_reg = sem_data[engine->id][i].mbox_reg;
27101487f786SFrançois Tigeot 			}
27111487f786SFrançois Tigeot 
27121487f786SFrançois Tigeot 			engine->semaphore.mbox.wait[i] = wait_mbox;
27131487f786SFrançois Tigeot 			engine->semaphore.mbox.signal[i] = mbox_reg;
27141487f786SFrançois Tigeot 		}
27151487f786SFrançois Tigeot 	}
27161487f786SFrançois Tigeot }
27171487f786SFrançois Tigeot 
27181487f786SFrançois Tigeot static void intel_ring_init_irq(struct drm_i915_private *dev_priv,
27191487f786SFrançois Tigeot 				struct intel_engine_cs *engine)
27201487f786SFrançois Tigeot {
272187df8fc6SFrançois Tigeot 	engine->irq_enable_mask = GT_RENDER_USER_INTERRUPT << engine->irq_shift;
272287df8fc6SFrançois Tigeot 
27231487f786SFrançois Tigeot 	if (INTEL_GEN(dev_priv) >= 8) {
2724303bf270SFrançois Tigeot 		engine->irq_enable = gen8_irq_enable;
2725303bf270SFrançois Tigeot 		engine->irq_disable = gen8_irq_disable;
27261487f786SFrançois Tigeot 		engine->irq_seqno_barrier = gen6_seqno_barrier;
27271487f786SFrançois Tigeot 	} else if (INTEL_GEN(dev_priv) >= 6) {
2728303bf270SFrançois Tigeot 		engine->irq_enable = gen6_irq_enable;
2729303bf270SFrançois Tigeot 		engine->irq_disable = gen6_irq_disable;
27301487f786SFrançois Tigeot 		engine->irq_seqno_barrier = gen6_seqno_barrier;
27311487f786SFrançois Tigeot 	} else if (INTEL_GEN(dev_priv) >= 5) {
2732303bf270SFrançois Tigeot 		engine->irq_enable = gen5_irq_enable;
2733303bf270SFrançois Tigeot 		engine->irq_disable = gen5_irq_disable;
2734303bf270SFrançois Tigeot 		engine->irq_seqno_barrier = gen5_seqno_barrier;
27351487f786SFrançois Tigeot 	} else if (INTEL_GEN(dev_priv) >= 3) {
2736303bf270SFrançois Tigeot 		engine->irq_enable = i9xx_irq_enable;
2737303bf270SFrançois Tigeot 		engine->irq_disable = i9xx_irq_disable;
27381487f786SFrançois Tigeot 	} else {
2739303bf270SFrançois Tigeot 		engine->irq_enable = i8xx_irq_enable;
2740303bf270SFrançois Tigeot 		engine->irq_disable = i8xx_irq_disable;
27411487f786SFrançois Tigeot 	}
27421487f786SFrançois Tigeot }
27431487f786SFrançois Tigeot 
27441487f786SFrançois Tigeot static void intel_ring_default_vfuncs(struct drm_i915_private *dev_priv,
27451487f786SFrançois Tigeot 				      struct intel_engine_cs *engine)
27461487f786SFrançois Tigeot {
27471487f786SFrançois Tigeot 	intel_ring_init_irq(dev_priv, engine);
27481487f786SFrançois Tigeot 	intel_ring_init_semaphores(dev_priv, engine);
2749*71f41f3eSFrançois Tigeot 
2750*71f41f3eSFrançois Tigeot 	engine->init_hw = init_ring_common;
2751*71f41f3eSFrançois Tigeot 
2752*71f41f3eSFrançois Tigeot 	engine->emit_request = i9xx_emit_request;
2753*71f41f3eSFrançois Tigeot 	if (i915.semaphores)
2754*71f41f3eSFrançois Tigeot 		engine->emit_request = gen6_sema_emit_request;
2755*71f41f3eSFrançois Tigeot 	engine->submit_request = i9xx_submit_request;
2756*71f41f3eSFrançois Tigeot 
2757*71f41f3eSFrançois Tigeot 	if (INTEL_GEN(dev_priv) >= 8)
2758*71f41f3eSFrançois Tigeot 		engine->emit_bb_start = gen8_emit_bb_start;
2759*71f41f3eSFrançois Tigeot 	else if (INTEL_GEN(dev_priv) >= 6)
2760*71f41f3eSFrançois Tigeot 		engine->emit_bb_start = gen6_emit_bb_start;
2761*71f41f3eSFrançois Tigeot 	else if (INTEL_GEN(dev_priv) >= 4)
2762*71f41f3eSFrançois Tigeot 		engine->emit_bb_start = i965_emit_bb_start;
2763*71f41f3eSFrançois Tigeot 	else if (IS_I830(dev_priv) || IS_845G(dev_priv))
2764*71f41f3eSFrançois Tigeot 		engine->emit_bb_start = i830_emit_bb_start;
2765*71f41f3eSFrançois Tigeot 	else
2766*71f41f3eSFrançois Tigeot 		engine->emit_bb_start = i915_emit_bb_start;
27671487f786SFrançois Tigeot }
27681487f786SFrançois Tigeot 
276987df8fc6SFrançois Tigeot int intel_init_render_ring_buffer(struct intel_engine_cs *engine)
2770e3adcf8fSFrançois Tigeot {
277187df8fc6SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
277224edb884SFrançois Tigeot 	int ret;
2773e3adcf8fSFrançois Tigeot 
27741487f786SFrançois Tigeot 	intel_ring_default_vfuncs(dev_priv, engine);
27752c9916cdSFrançois Tigeot 
2776303bf270SFrançois Tigeot 	if (HAS_L3_DPF(dev_priv))
2777303bf270SFrançois Tigeot 		engine->irq_keep_mask = GT_RENDER_L3_PARITY_ERROR_INTERRUPT;
2778303bf270SFrançois Tigeot 
27791487f786SFrançois Tigeot 	if (INTEL_GEN(dev_priv) >= 8) {
27808621f407SFrançois Tigeot 		engine->init_context = intel_rcs_ctx_init;
2781*71f41f3eSFrançois Tigeot 		engine->emit_request = gen8_render_emit_request;
2782*71f41f3eSFrançois Tigeot 		engine->emit_flush = gen8_render_ring_flush;
278387df8fc6SFrançois Tigeot 		if (i915.semaphores)
27848621f407SFrançois Tigeot 			engine->semaphore.signal = gen8_rcs_signal;
27851487f786SFrançois Tigeot 	} else if (INTEL_GEN(dev_priv) >= 6) {
27868621f407SFrançois Tigeot 		engine->init_context = intel_rcs_ctx_init;
2787*71f41f3eSFrançois Tigeot 		engine->emit_flush = gen7_render_ring_flush;
27881487f786SFrançois Tigeot 		if (IS_GEN6(dev_priv))
2789*71f41f3eSFrançois Tigeot 			engine->emit_flush = gen6_render_ring_flush;
27901487f786SFrançois Tigeot 	} else if (IS_GEN5(dev_priv)) {
2791*71f41f3eSFrançois Tigeot 		engine->emit_flush = gen4_render_ring_flush;
2792686a02f1SFrançois Tigeot 	} else {
27931487f786SFrançois Tigeot 		if (INTEL_GEN(dev_priv) < 4)
2794*71f41f3eSFrançois Tigeot 			engine->emit_flush = gen2_render_ring_flush;
2795686a02f1SFrançois Tigeot 		else
2796*71f41f3eSFrançois Tigeot 			engine->emit_flush = gen4_render_ring_flush;
27978621f407SFrançois Tigeot 		engine->irq_enable_mask = I915_USER_INTERRUPT;
2798686a02f1SFrançois Tigeot 	}
279924edb884SFrançois Tigeot 
28001487f786SFrançois Tigeot 	if (IS_HASWELL(dev_priv))
2801*71f41f3eSFrançois Tigeot 		engine->emit_bb_start = hsw_emit_bb_start;
28021487f786SFrançois Tigeot 
28038621f407SFrançois Tigeot 	engine->init_hw = init_render_ring;
28048621f407SFrançois Tigeot 	engine->cleanup = render_ring_cleanup;
2805e3adcf8fSFrançois Tigeot 
280687df8fc6SFrançois Tigeot 	ret = intel_init_ring_buffer(engine);
2807b5c29a34SFrançois Tigeot 	if (ret)
28082c9916cdSFrançois Tigeot 		return ret;
28092c9916cdSFrançois Tigeot 
2810303bf270SFrançois Tigeot 	if (INTEL_GEN(dev_priv) >= 6) {
2811303bf270SFrançois Tigeot 		ret = intel_init_pipe_control(engine, 4096);
2812303bf270SFrançois Tigeot 		if (ret)
2813303bf270SFrançois Tigeot 			return ret;
2814303bf270SFrançois Tigeot 	} else if (HAS_BROKEN_CS_TLB(dev_priv)) {
2815303bf270SFrançois Tigeot 		ret = intel_init_pipe_control(engine, I830_WA_SIZE);
28162c9916cdSFrançois Tigeot 		if (ret)
28172c9916cdSFrançois Tigeot 			return ret;
2818b5c29a34SFrançois Tigeot 	}
2819b5c29a34SFrançois Tigeot 
2820e3adcf8fSFrançois Tigeot 	return 0;
2821e3adcf8fSFrançois Tigeot }
2822e3adcf8fSFrançois Tigeot 
282387df8fc6SFrançois Tigeot int intel_init_bsd_ring_buffer(struct intel_engine_cs *engine)
2824e3adcf8fSFrançois Tigeot {
282587df8fc6SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
2826686a02f1SFrançois Tigeot 
28271487f786SFrançois Tigeot 	intel_ring_default_vfuncs(dev_priv, engine);
28281487f786SFrançois Tigeot 
28291487f786SFrançois Tigeot 	if (INTEL_GEN(dev_priv) >= 6) {
2830686a02f1SFrançois Tigeot 		/* gen6 bsd needs a special wa for tail updates */
28311487f786SFrançois Tigeot 		if (IS_GEN6(dev_priv))
2832*71f41f3eSFrançois Tigeot 			engine->submit_request = gen6_bsd_submit_request;
2833*71f41f3eSFrançois Tigeot 		engine->emit_flush = gen6_bsd_ring_flush;
283487df8fc6SFrançois Tigeot 		if (INTEL_GEN(dev_priv) < 8)
28358621f407SFrançois Tigeot 			engine->irq_enable_mask = GT_BSD_USER_INTERRUPT;
2836686a02f1SFrançois Tigeot 	} else {
28378621f407SFrançois Tigeot 		engine->mmio_base = BSD_RING_BASE;
2838*71f41f3eSFrançois Tigeot 		engine->emit_flush = bsd_ring_flush;
28391487f786SFrançois Tigeot 		if (IS_GEN5(dev_priv))
28408621f407SFrançois Tigeot 			engine->irq_enable_mask = ILK_BSD_USER_INTERRUPT;
28411487f786SFrançois Tigeot 		else
28428621f407SFrançois Tigeot 			engine->irq_enable_mask = I915_BSD_USER_INTERRUPT;
2843686a02f1SFrançois Tigeot 	}
2844e3adcf8fSFrançois Tigeot 
284587df8fc6SFrançois Tigeot 	return intel_init_ring_buffer(engine);
2846e3adcf8fSFrançois Tigeot }
2847e3adcf8fSFrançois Tigeot 
2848ba55f2f5SFrançois Tigeot /**
2849477eb7f9SFrançois Tigeot  * Initialize the second BSD ring (eg. Broadwell GT3, Skylake GT3)
2850ba55f2f5SFrançois Tigeot  */
285187df8fc6SFrançois Tigeot int intel_init_bsd2_ring_buffer(struct intel_engine_cs *engine)
2852ba55f2f5SFrançois Tigeot {
285387df8fc6SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
28541487f786SFrançois Tigeot 
28551487f786SFrançois Tigeot 	intel_ring_default_vfuncs(dev_priv, engine);
28561487f786SFrançois Tigeot 
2857*71f41f3eSFrançois Tigeot 	engine->emit_flush = gen6_bsd_ring_flush;
2858ba55f2f5SFrançois Tigeot 
285987df8fc6SFrançois Tigeot 	return intel_init_ring_buffer(engine);
2860ba55f2f5SFrançois Tigeot }
2861ba55f2f5SFrançois Tigeot 
286287df8fc6SFrançois Tigeot int intel_init_blt_ring_buffer(struct intel_engine_cs *engine)
2863e3adcf8fSFrançois Tigeot {
286487df8fc6SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
28651487f786SFrançois Tigeot 
28661487f786SFrançois Tigeot 	intel_ring_default_vfuncs(dev_priv, engine);
28671487f786SFrançois Tigeot 
2868*71f41f3eSFrançois Tigeot 	engine->emit_flush = gen6_ring_flush;
286987df8fc6SFrançois Tigeot 	if (INTEL_GEN(dev_priv) < 8)
28708621f407SFrançois Tigeot 		engine->irq_enable_mask = GT_BLT_USER_INTERRUPT;
28715d0b1887SFrançois Tigeot 
287287df8fc6SFrançois Tigeot 	return intel_init_ring_buffer(engine);
28735d0b1887SFrançois Tigeot }
28745d0b1887SFrançois Tigeot 
287587df8fc6SFrançois Tigeot int intel_init_vebox_ring_buffer(struct intel_engine_cs *engine)
28765d0b1887SFrançois Tigeot {
287787df8fc6SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
28789edbd4a0SFrançois Tigeot 
28791487f786SFrançois Tigeot 	intel_ring_default_vfuncs(dev_priv, engine);
28801487f786SFrançois Tigeot 
2881*71f41f3eSFrançois Tigeot 	engine->emit_flush = gen6_ring_flush;
28821487f786SFrançois Tigeot 
288387df8fc6SFrançois Tigeot 	if (INTEL_GEN(dev_priv) < 8) {
28848621f407SFrançois Tigeot 		engine->irq_enable_mask = PM_VEBOX_USER_INTERRUPT;
2885303bf270SFrançois Tigeot 		engine->irq_enable = hsw_vebox_irq_enable;
2886303bf270SFrançois Tigeot 		engine->irq_disable = hsw_vebox_irq_disable;
288724edb884SFrançois Tigeot 	}
2888e3adcf8fSFrançois Tigeot 
288987df8fc6SFrançois Tigeot 	return intel_init_ring_buffer(engine);
2890e3adcf8fSFrançois Tigeot }
2891