xref: /dflybsd-src/sys/dev/drm/i915/intel_ringbuffer.c (revision 1e12ee3baa16120663cde9c6c4c8e92b69b00794)
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 
5071f41f3eSFrançois Tigeot void intel_ring_update_space(struct intel_ring *ring)
512c9916cdSFrançois Tigeot {
5271f41f3eSFrançois Tigeot 	if (ring->last_retired_head != -1) {
5371f41f3eSFrançois Tigeot 		ring->head = ring->last_retired_head;
5471f41f3eSFrançois Tigeot 		ring->last_retired_head = -1;
552c9916cdSFrançois Tigeot 	}
562c9916cdSFrançois Tigeot 
5771f41f3eSFrançois Tigeot 	ring->space = __intel_ring_space(ring->head & HEAD_ADDR,
5871f41f3eSFrançois Tigeot 					 ring->tail, ring->size);
599edbd4a0SFrançois Tigeot }
609edbd4a0SFrançois Tigeot 
61e3adcf8fSFrançois Tigeot static int
6271f41f3eSFrançois Tigeot gen2_render_ring_flush(struct drm_i915_gem_request *req, u32 mode)
63686a02f1SFrançois Tigeot {
6471f41f3eSFranç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 
7071f41f3eSFranç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 
7771f41f3eSFrançois Tigeot 	intel_ring_emit(ring, cmd);
7871f41f3eSFrançois Tigeot 	intel_ring_emit(ring, MI_NOOP);
7971f41f3eSFranç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
8571f41f3eSFrançois Tigeot gen4_render_ring_flush(struct drm_i915_gem_request *req, u32 mode)
86e3adcf8fSFrançois Tigeot {
8771f41f3eSFranç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 
11971f41f3eSFrançois Tigeot 	cmd = MI_FLUSH;
12071f41f3eSFrançois Tigeot 	if (mode & EMIT_INVALIDATE) {
121e3adcf8fSFrançois Tigeot 		cmd |= MI_EXE_FLUSH;
12271f41f3eSFrançois Tigeot 		if (IS_G4X(req->i915) || IS_GEN5(req->i915))
123e3adcf8fSFrançois Tigeot 			cmd |= MI_INVALIDATE_ISP;
12471f41f3eSFranç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 
13071f41f3eSFrançois Tigeot 	intel_ring_emit(ring, cmd);
13171f41f3eSFrançois Tigeot 	intel_ring_emit(ring, MI_NOOP);
13271f41f3eSFranç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 {
17771f41f3eSFrançois Tigeot 	struct intel_ring *ring = req->ring;
17871f41f3eSFrançois Tigeot 	u32 scratch_addr =
179*1e12ee3bSFrançois Tigeot 		i915_ggtt_offset(req->engine->scratch) + 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 
18671f41f3eSFrançois Tigeot 	intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(5));
18771f41f3eSFrançois Tigeot 	intel_ring_emit(ring, PIPE_CONTROL_CS_STALL |
188e3adcf8fSFrançois Tigeot 			PIPE_CONTROL_STALL_AT_SCOREBOARD);
18971f41f3eSFrançois Tigeot 	intel_ring_emit(ring, scratch_addr | PIPE_CONTROL_GLOBAL_GTT);
19071f41f3eSFrançois Tigeot 	intel_ring_emit(ring, 0); /* low dword */
19171f41f3eSFrançois Tigeot 	intel_ring_emit(ring, 0); /* high dword */
19271f41f3eSFrançois Tigeot 	intel_ring_emit(ring, MI_NOOP);
19371f41f3eSFranç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 
19971f41f3eSFrançois Tigeot 	intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(5));
20071f41f3eSFrançois Tigeot 	intel_ring_emit(ring, PIPE_CONTROL_QW_WRITE);
20171f41f3eSFrançois Tigeot 	intel_ring_emit(ring, scratch_addr | PIPE_CONTROL_GLOBAL_GTT);
20271f41f3eSFrançois Tigeot 	intel_ring_emit(ring, 0);
20371f41f3eSFrançois Tigeot 	intel_ring_emit(ring, 0);
20471f41f3eSFrançois Tigeot 	intel_ring_emit(ring, MI_NOOP);
20571f41f3eSFranç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
21171f41f3eSFrançois Tigeot gen6_render_ring_flush(struct drm_i915_gem_request *req, u32 mode)
212e3adcf8fSFrançois Tigeot {
21371f41f3eSFrançois Tigeot 	struct intel_ring *ring = req->ring;
21471f41f3eSFrançois Tigeot 	u32 scratch_addr =
215*1e12ee3bSFrançois Tigeot 		i915_ggtt_offset(req->engine->scratch) + 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 	 */
22871f41f3eSFranç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 	}
23771f41f3eSFranç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 
25471f41f3eSFrançois Tigeot 	intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(4));
25571f41f3eSFrançois Tigeot 	intel_ring_emit(ring, flags);
25671f41f3eSFrançois Tigeot 	intel_ring_emit(ring, scratch_addr | PIPE_CONTROL_GLOBAL_GTT);
25771f41f3eSFrançois Tigeot 	intel_ring_emit(ring, 0);
25871f41f3eSFranç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 {
26671f41f3eSFranç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 
27371f41f3eSFrançois Tigeot 	intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(4));
27471f41f3eSFrançois Tigeot 	intel_ring_emit(ring,
27571f41f3eSFrançois Tigeot 			PIPE_CONTROL_CS_STALL |
276b5c29a34SFrançois Tigeot 			PIPE_CONTROL_STALL_AT_SCOREBOARD);
27771f41f3eSFrançois Tigeot 	intel_ring_emit(ring, 0);
27871f41f3eSFrançois Tigeot 	intel_ring_emit(ring, 0);
27971f41f3eSFranç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
28571f41f3eSFrançois Tigeot gen7_render_ring_flush(struct drm_i915_gem_request *req, u32 mode)
286b5c29a34SFrançois Tigeot {
28771f41f3eSFrançois Tigeot 	struct intel_ring *ring = req->ring;
28871f41f3eSFrançois Tigeot 	u32 scratch_addr =
289*1e12ee3bSFrançois Tigeot 		i915_ggtt_offset(req->engine->scratch) + 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 	 */
30771f41f3eSFranç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 	}
31371f41f3eSFranç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 
33971f41f3eSFrançois Tigeot 	intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(4));
34071f41f3eSFrançois Tigeot 	intel_ring_emit(ring, flags);
34171f41f3eSFrançois Tigeot 	intel_ring_emit(ring, scratch_addr);
34271f41f3eSFrançois Tigeot 	intel_ring_emit(ring, 0);
34371f41f3eSFranç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 {
35271f41f3eSFranç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 
35971f41f3eSFrançois Tigeot 	intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(6));
36071f41f3eSFrançois Tigeot 	intel_ring_emit(ring, flags);
36171f41f3eSFrançois Tigeot 	intel_ring_emit(ring, scratch_addr);
36271f41f3eSFrançois Tigeot 	intel_ring_emit(ring, 0);
36371f41f3eSFrançois Tigeot 	intel_ring_emit(ring, 0);
36471f41f3eSFrançois Tigeot 	intel_ring_emit(ring, 0);
36571f41f3eSFranç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
37171f41f3eSFrançois Tigeot gen8_render_ring_flush(struct drm_i915_gem_request *req, u32 mode)
3729edbd4a0SFrançois Tigeot {
373*1e12ee3bSFrançois Tigeot 	u32 scratch_addr =
374*1e12ee3bSFrançois Tigeot 		i915_ggtt_offset(req->engine->scratch) + 2 * CACHELINE_BYTES;
37571f41f3eSFrançois Tigeot 	u32 flags = 0;
3769edbd4a0SFrançois Tigeot 	int ret;
3779edbd4a0SFrançois Tigeot 
3789edbd4a0SFrançois Tigeot 	flags |= PIPE_CONTROL_CS_STALL;
3799edbd4a0SFrançois Tigeot 
38071f41f3eSFrançois Tigeot 	if (mode & EMIT_FLUSH) {
3819edbd4a0SFrançois Tigeot 		flags |= PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH;
3829edbd4a0SFrançois Tigeot 		flags |= PIPE_CONTROL_DEPTH_CACHE_FLUSH;
383aee94f86SFrançois Tigeot 		flags |= PIPE_CONTROL_DC_FLUSH_ENABLE;
384b49c8cf9SFrançois Tigeot 		flags |= PIPE_CONTROL_FLUSH_ENABLE;
3859edbd4a0SFrançois Tigeot 	}
38671f41f3eSFrançois Tigeot 	if (mode & EMIT_INVALIDATE) {
3879edbd4a0SFrançois Tigeot 		flags |= PIPE_CONTROL_TLB_INVALIDATE;
3889edbd4a0SFrançois Tigeot 		flags |= PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE;
3899edbd4a0SFrançois Tigeot 		flags |= PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE;
3909edbd4a0SFrançois Tigeot 		flags |= PIPE_CONTROL_VF_CACHE_INVALIDATE;
3919edbd4a0SFrançois Tigeot 		flags |= PIPE_CONTROL_CONST_CACHE_INVALIDATE;
3929edbd4a0SFrançois Tigeot 		flags |= PIPE_CONTROL_STATE_CACHE_INVALIDATE;
3939edbd4a0SFrançois Tigeot 		flags |= PIPE_CONTROL_QW_WRITE;
3949edbd4a0SFrançois Tigeot 		flags |= PIPE_CONTROL_GLOBAL_GTT_IVB;
3959edbd4a0SFrançois Tigeot 
39624edb884SFrançois Tigeot 		/* WaCsStallBeforeStateCacheInvalidate:bdw,chv */
397a05eeebfSFrançois Tigeot 		ret = gen8_emit_pipe_control(req,
39824edb884SFrançois Tigeot 					     PIPE_CONTROL_CS_STALL |
39924edb884SFrançois Tigeot 					     PIPE_CONTROL_STALL_AT_SCOREBOARD,
40024edb884SFrançois Tigeot 					     0);
4019edbd4a0SFrançois Tigeot 		if (ret)
4029edbd4a0SFrançois Tigeot 			return ret;
40324edb884SFrançois Tigeot 	}
4049edbd4a0SFrançois Tigeot 
405a05eeebfSFrançois Tigeot 	return gen8_emit_pipe_control(req, flags, scratch_addr);
4069edbd4a0SFrançois Tigeot }
4079edbd4a0SFrançois Tigeot 
4088621f407SFrançois Tigeot static void ring_setup_phys_status_page(struct intel_engine_cs *engine)
4095d0b1887SFrançois Tigeot {
4101487f786SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
4115d0b1887SFrançois Tigeot 	u32 addr;
4125d0b1887SFrançois Tigeot 
4135d0b1887SFrançois Tigeot 	addr = dev_priv->status_page_dmah->busaddr;
4141487f786SFrançois Tigeot 	if (INTEL_GEN(dev_priv) >= 4)
4155d0b1887SFrançois Tigeot 		addr |= (dev_priv->status_page_dmah->busaddr >> 28) & 0xf0;
4165d0b1887SFrançois Tigeot 	I915_WRITE(HWS_PGA, addr);
4175d0b1887SFrançois Tigeot }
4185d0b1887SFrançois Tigeot 
4198621f407SFrançois Tigeot static void intel_ring_setup_status_page(struct intel_engine_cs *engine)
420477eb7f9SFrançois Tigeot {
4211487f786SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
422aee94f86SFrançois Tigeot 	i915_reg_t mmio;
423477eb7f9SFrançois Tigeot 
424477eb7f9SFrançois Tigeot 	/* The ring status page addresses are no longer next to the rest of
425477eb7f9SFrançois Tigeot 	 * the ring registers as of gen7.
426477eb7f9SFrançois Tigeot 	 */
4271487f786SFrançois Tigeot 	if (IS_GEN7(dev_priv)) {
4288621f407SFrançois Tigeot 		switch (engine->id) {
429477eb7f9SFrançois Tigeot 		case RCS:
430477eb7f9SFrançois Tigeot 			mmio = RENDER_HWS_PGA_GEN7;
431477eb7f9SFrançois Tigeot 			break;
432477eb7f9SFrançois Tigeot 		case BCS:
433477eb7f9SFrançois Tigeot 			mmio = BLT_HWS_PGA_GEN7;
434477eb7f9SFrançois Tigeot 			break;
435477eb7f9SFrançois Tigeot 		/*
436477eb7f9SFrançois Tigeot 		 * VCS2 actually doesn't exist on Gen7. Only shut up
437477eb7f9SFrançois Tigeot 		 * gcc switch check warning
438477eb7f9SFrançois Tigeot 		 */
439477eb7f9SFrançois Tigeot 		case VCS2:
440477eb7f9SFrançois Tigeot 		case VCS:
441477eb7f9SFrançois Tigeot 			mmio = BSD_HWS_PGA_GEN7;
442477eb7f9SFrançois Tigeot 			break;
443477eb7f9SFrançois Tigeot 		case VECS:
444477eb7f9SFrançois Tigeot 			mmio = VEBOX_HWS_PGA_GEN7;
445477eb7f9SFrançois Tigeot 			break;
446477eb7f9SFrançois Tigeot 		}
4471487f786SFrançois Tigeot 	} else if (IS_GEN6(dev_priv)) {
4488621f407SFrançois Tigeot 		mmio = RING_HWS_PGA_GEN6(engine->mmio_base);
449477eb7f9SFrançois Tigeot 	} else {
450477eb7f9SFrançois Tigeot 		/* XXX: gen8 returns to sanity */
4518621f407SFrançois Tigeot 		mmio = RING_HWS_PGA(engine->mmio_base);
452477eb7f9SFrançois Tigeot 	}
453477eb7f9SFrançois Tigeot 
454*1e12ee3bSFrançois Tigeot 	I915_WRITE(mmio, engine->status_page.ggtt_offset);
455477eb7f9SFrançois Tigeot 	POSTING_READ(mmio);
456477eb7f9SFrançois Tigeot 
457477eb7f9SFrançois Tigeot 	/*
458477eb7f9SFrançois Tigeot 	 * Flush the TLB for this page
459477eb7f9SFrançois Tigeot 	 *
460477eb7f9SFrançois Tigeot 	 * FIXME: These two bits have disappeared on gen8, so a question
461477eb7f9SFrançois Tigeot 	 * arises: do we still need this and if so how should we go about
462477eb7f9SFrançois Tigeot 	 * invalidating the TLB?
463477eb7f9SFrançois Tigeot 	 */
4641487f786SFrançois Tigeot 	if (IS_GEN(dev_priv, 6, 7)) {
4658621f407SFrançois Tigeot 		i915_reg_t reg = RING_INSTPM(engine->mmio_base);
466477eb7f9SFrançois Tigeot 
467477eb7f9SFrançois Tigeot 		/* ring should be idle before issuing a sync flush*/
4688621f407SFrançois Tigeot 		WARN_ON((I915_READ_MODE(engine) & MODE_IDLE) == 0);
469477eb7f9SFrançois Tigeot 
470477eb7f9SFrançois Tigeot 		I915_WRITE(reg,
471477eb7f9SFrançois Tigeot 			   _MASKED_BIT_ENABLE(INSTPM_TLB_INVALIDATE |
472477eb7f9SFrançois Tigeot 					      INSTPM_SYNC_FLUSH));
4731487f786SFrançois Tigeot 		if (intel_wait_for_register(dev_priv,
4741487f786SFrançois Tigeot 					    reg, INSTPM_SYNC_FLUSH, 0,
475477eb7f9SFrançois Tigeot 					    1000))
476477eb7f9SFrançois Tigeot 			DRM_ERROR("%s: wait for SyncFlush to complete for TLB invalidation timed out\n",
4778621f407SFrançois Tigeot 				  engine->name);
478477eb7f9SFrançois Tigeot 	}
479477eb7f9SFrançois Tigeot }
480477eb7f9SFrançois Tigeot 
4818621f407SFrançois Tigeot static bool stop_ring(struct intel_engine_cs *engine)
482e3adcf8fSFrançois Tigeot {
4831487f786SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
484e3adcf8fSFrançois Tigeot 
485*1e12ee3bSFrançois Tigeot 	if (INTEL_GEN(dev_priv) > 2) {
4868621f407SFrançois Tigeot 		I915_WRITE_MODE(engine, _MASKED_BIT_ENABLE(STOP_RING));
4871487f786SFrançois Tigeot 		if (intel_wait_for_register(dev_priv,
4881487f786SFrançois Tigeot 					    RING_MI_MODE(engine->mmio_base),
4891487f786SFrançois Tigeot 					    MODE_IDLE,
4901487f786SFrançois Tigeot 					    MODE_IDLE,
4911487f786SFrançois Tigeot 					    1000)) {
4928621f407SFrançois Tigeot 			DRM_ERROR("%s : timed out trying to stop ring\n",
4938621f407SFrançois Tigeot 				  engine->name);
4941b13d190SFrançois Tigeot 			/* Sometimes we observe that the idle flag is not
4951b13d190SFrançois Tigeot 			 * set even though the ring is empty. So double
4961b13d190SFrançois Tigeot 			 * check before giving up.
4971b13d190SFrançois Tigeot 			 */
4988621f407SFrançois Tigeot 			if (I915_READ_HEAD(engine) != I915_READ_TAIL(engine))
499ba55f2f5SFrançois Tigeot 				return false;
500ba55f2f5SFrançois Tigeot 		}
501ba55f2f5SFrançois Tigeot 	}
502686a02f1SFrançois Tigeot 
5038621f407SFrançois Tigeot 	I915_WRITE_CTL(engine, 0);
5048621f407SFrançois Tigeot 	I915_WRITE_HEAD(engine, 0);
50571f41f3eSFrançois Tigeot 	I915_WRITE_TAIL(engine, 0);
506e3adcf8fSFrançois Tigeot 
507*1e12ee3bSFrançois Tigeot 	if (INTEL_GEN(dev_priv) > 2) {
5088621f407SFrançois Tigeot 		(void)I915_READ_CTL(engine);
5098621f407SFrançois Tigeot 		I915_WRITE_MODE(engine, _MASKED_BIT_DISABLE(STOP_RING));
510ba55f2f5SFrançois Tigeot 	}
511e3adcf8fSFrançois Tigeot 
5128621f407SFrançois Tigeot 	return (I915_READ_HEAD(engine) & HEAD_ADDR) == 0;
513ba55f2f5SFrançois Tigeot }
514ba55f2f5SFrançois Tigeot 
5158621f407SFrançois Tigeot static int init_ring_common(struct intel_engine_cs *engine)
5168621f407SFrançois Tigeot {
5171487f786SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
51871f41f3eSFrançois Tigeot 	struct intel_ring *ring = engine->buffer;
519ba55f2f5SFrançois Tigeot 	int ret = 0;
520ba55f2f5SFrançois Tigeot 
5212c9916cdSFrançois Tigeot 	intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL);
522ba55f2f5SFrançois Tigeot 
5238621f407SFrançois Tigeot 	if (!stop_ring(engine)) {
524ba55f2f5SFrançois Tigeot 		/* G45 ring initialization often fails to reset head to zero */
525b5c29a34SFrançois Tigeot 		DRM_DEBUG_KMS("%s head not reset to zero "
526e3adcf8fSFrançois Tigeot 			      "ctl %08x head %08x tail %08x start %08x\n",
5278621f407SFrançois Tigeot 			      engine->name,
5288621f407SFrançois Tigeot 			      I915_READ_CTL(engine),
5298621f407SFrançois Tigeot 			      I915_READ_HEAD(engine),
5308621f407SFrançois Tigeot 			      I915_READ_TAIL(engine),
5318621f407SFrançois Tigeot 			      I915_READ_START(engine));
532e3adcf8fSFrançois Tigeot 
5338621f407SFrançois Tigeot 		if (!stop_ring(engine)) {
534e3adcf8fSFrançois Tigeot 			DRM_ERROR("failed to set %s head to zero "
535e3adcf8fSFrançois Tigeot 				  "ctl %08x head %08x tail %08x start %08x\n",
5368621f407SFrançois Tigeot 				  engine->name,
5378621f407SFrançois Tigeot 				  I915_READ_CTL(engine),
5388621f407SFrançois Tigeot 				  I915_READ_HEAD(engine),
5398621f407SFrançois Tigeot 				  I915_READ_TAIL(engine),
5408621f407SFrançois Tigeot 				  I915_READ_START(engine));
541686a02f1SFrançois Tigeot 			ret = -EIO;
542686a02f1SFrançois Tigeot 			goto out;
543e3adcf8fSFrançois Tigeot 		}
544ba55f2f5SFrançois Tigeot 	}
545ba55f2f5SFrançois Tigeot 
546*1e12ee3bSFrançois Tigeot 	if (HWS_NEEDS_PHYSICAL(dev_priv))
5478621f407SFrançois Tigeot 		ring_setup_phys_status_page(engine);
548*1e12ee3bSFrançois Tigeot 	else
549*1e12ee3bSFrançois Tigeot 		intel_ring_setup_status_page(engine);
550*1e12ee3bSFrançois Tigeot 
551*1e12ee3bSFrançois Tigeot 	intel_engine_reset_breadcrumbs(engine);
552ba55f2f5SFrançois Tigeot 
5530f370975SMatthew Dillon 	/* Enforce ordering by reading HEAD register back */
5548621f407SFrançois Tigeot 	I915_READ_HEAD(engine);
5550f370975SMatthew Dillon 
556ba55f2f5SFrançois Tigeot 	/* Initialize the ring. This must happen _after_ we've cleared the ring
557ba55f2f5SFrançois Tigeot 	 * registers with the above sequence (the readback of the HEAD registers
558ba55f2f5SFrançois Tigeot 	 * also enforces ordering), otherwise the hw might lose the new ring
559ba55f2f5SFrançois Tigeot 	 * register values. */
560*1e12ee3bSFrançois Tigeot 	I915_WRITE_START(engine, i915_ggtt_offset(ring->vma));
5611b13d190SFrançois Tigeot 
5621b13d190SFrançois Tigeot 	/* WaClearRingBufHeadRegAtInit:ctg,elk */
5638621f407SFrançois Tigeot 	if (I915_READ_HEAD(engine))
5641b13d190SFrançois Tigeot 		DRM_DEBUG("%s initialization failed [head=%08x], fudging\n",
5658621f407SFrançois Tigeot 			  engine->name, I915_READ_HEAD(engine));
5661b13d190SFrançois Tigeot 
567*1e12ee3bSFrançois Tigeot 	intel_ring_update_space(ring);
568*1e12ee3bSFrançois Tigeot 	I915_WRITE_HEAD(engine, ring->head);
569*1e12ee3bSFrançois Tigeot 	I915_WRITE_TAIL(engine, ring->tail);
570*1e12ee3bSFrançois Tigeot 	(void)I915_READ_TAIL(engine);
571*1e12ee3bSFrançois Tigeot 
572*1e12ee3bSFrançois Tigeot 	I915_WRITE_CTL(engine, RING_CTL_SIZE(ring->size) | RING_VALID);
573ba55f2f5SFrançois Tigeot 
574ba55f2f5SFrançois Tigeot 	/* If the head is still not zero, the ring is dead */
575*1e12ee3bSFrançois Tigeot 	if (intel_wait_for_register_fw(dev_priv, RING_CTL(engine->mmio_base),
576*1e12ee3bSFrançois Tigeot 				       RING_VALID, RING_VALID,
577*1e12ee3bSFrançois Tigeot 				       50)) {
578ba55f2f5SFrançois Tigeot 		DRM_ERROR("%s initialization failed "
579*1e12ee3bSFrançois Tigeot 			  "ctl %08x (valid? %d) head %08x [%08x] tail %08x [%08x] start %08x [expected %08x]\n",
5808621f407SFrançois Tigeot 			  engine->name,
5818621f407SFrançois Tigeot 			  I915_READ_CTL(engine),
5828621f407SFrançois Tigeot 			  I915_READ_CTL(engine) & RING_VALID,
583*1e12ee3bSFrançois Tigeot 			  I915_READ_HEAD(engine), ring->head,
584*1e12ee3bSFrançois Tigeot 			  I915_READ_TAIL(engine), ring->tail,
5858621f407SFrançois Tigeot 			  I915_READ_START(engine),
586*1e12ee3bSFrançois Tigeot 			  i915_ggtt_offset(ring->vma));
587ba55f2f5SFrançois Tigeot 		ret = -EIO;
588ba55f2f5SFrançois Tigeot 		goto out;
589ba55f2f5SFrançois Tigeot 	}
590e3adcf8fSFrançois Tigeot 
5918621f407SFrançois Tigeot 	intel_engine_init_hangcheck(engine);
5925d0b1887SFrançois Tigeot 
593686a02f1SFrançois Tigeot out:
5942c9916cdSFrançois Tigeot 	intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL);
595686a02f1SFrançois Tigeot 
596686a02f1SFrançois Tigeot 	return ret;
597e3adcf8fSFrançois Tigeot }
598e3adcf8fSFrançois Tigeot 
599*1e12ee3bSFrançois Tigeot static void reset_ring_common(struct intel_engine_cs *engine,
600*1e12ee3bSFrançois Tigeot 			      struct drm_i915_gem_request *request)
6011b13d190SFrançois Tigeot {
602*1e12ee3bSFrançois Tigeot 	struct intel_ring *ring = request->ring;
6031b13d190SFrançois Tigeot 
604*1e12ee3bSFrançois Tigeot 	ring->head = request->postfix;
605*1e12ee3bSFrançois Tigeot 	ring->last_retired_head = -1;
606e3adcf8fSFrançois Tigeot }
607e3adcf8fSFrançois Tigeot 
608a05eeebfSFrançois Tigeot static int intel_ring_workarounds_emit(struct drm_i915_gem_request *req)
6091b13d190SFrançois Tigeot {
61071f41f3eSFrançois Tigeot 	struct intel_ring *ring = req->ring;
6111487f786SFrançois Tigeot 	struct i915_workarounds *w = &req->i915->workarounds;
6121487f786SFrançois Tigeot 	int ret, i;
6131b13d190SFrançois Tigeot 
614352ff8bdSFrançois Tigeot 	if (w->count == 0)
6152c9916cdSFrançois Tigeot 		return 0;
6161b13d190SFrançois Tigeot 
61771f41f3eSFrançois Tigeot 	ret = req->engine->emit_flush(req, EMIT_BARRIER);
6181b13d190SFrançois Tigeot 	if (ret)
6191b13d190SFrançois Tigeot 		return ret;
6201b13d190SFrançois Tigeot 
621a05eeebfSFrançois Tigeot 	ret = intel_ring_begin(req, (w->count * 2 + 2));
6222c9916cdSFrançois Tigeot 	if (ret)
6232c9916cdSFrançois Tigeot 		return ret;
6242c9916cdSFrançois Tigeot 
62571f41f3eSFrançois Tigeot 	intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(w->count));
6262c9916cdSFrançois Tigeot 	for (i = 0; i < w->count; i++) {
62771f41f3eSFrançois Tigeot 		intel_ring_emit_reg(ring, w->reg[i].addr);
62871f41f3eSFrançois Tigeot 		intel_ring_emit(ring, w->reg[i].value);
6292c9916cdSFrançois Tigeot 	}
63071f41f3eSFrançois Tigeot 	intel_ring_emit(ring, MI_NOOP);
6312c9916cdSFrançois Tigeot 
63271f41f3eSFrançois Tigeot 	intel_ring_advance(ring);
6332c9916cdSFrançois Tigeot 
63471f41f3eSFrançois Tigeot 	ret = req->engine->emit_flush(req, EMIT_BARRIER);
6352c9916cdSFrançois Tigeot 	if (ret)
6362c9916cdSFrançois Tigeot 		return ret;
6372c9916cdSFrançois Tigeot 
6382c9916cdSFrançois Tigeot 	DRM_DEBUG_DRIVER("Number of Workarounds emitted: %d\n", w->count);
6392c9916cdSFrançois Tigeot 
6402c9916cdSFrançois Tigeot 	return 0;
6412c9916cdSFrançois Tigeot }
6422c9916cdSFrançois Tigeot 
643a05eeebfSFrançois Tigeot static int intel_rcs_ctx_init(struct drm_i915_gem_request *req)
6442c9916cdSFrançois Tigeot {
6452c9916cdSFrançois Tigeot 	int ret;
6462c9916cdSFrançois Tigeot 
647a05eeebfSFrançois Tigeot 	ret = intel_ring_workarounds_emit(req);
6482c9916cdSFrançois Tigeot 	if (ret != 0)
6492c9916cdSFrançois Tigeot 		return ret;
6502c9916cdSFrançois Tigeot 
651a05eeebfSFrançois Tigeot 	ret = i915_gem_render_state_init(req);
6522c9916cdSFrançois Tigeot 	if (ret)
6532c9916cdSFrançois Tigeot 		return ret;
654c0e85e96SFrançois Tigeot 
655c0e85e96SFrançois Tigeot 	return 0;
6562c9916cdSFrançois Tigeot }
6572c9916cdSFrançois Tigeot 
6582c9916cdSFrançois Tigeot static int wa_add(struct drm_i915_private *dev_priv,
659aee94f86SFrançois Tigeot 		  i915_reg_t addr,
660aee94f86SFrançois Tigeot 		  const u32 mask, const u32 val)
6612c9916cdSFrançois Tigeot {
6622c9916cdSFrançois Tigeot 	const u32 idx = dev_priv->workarounds.count;
6632c9916cdSFrançois Tigeot 
6642c9916cdSFrançois Tigeot 	if (WARN_ON(idx >= I915_MAX_WA_REGS))
6652c9916cdSFrançois Tigeot 		return -ENOSPC;
6662c9916cdSFrançois Tigeot 
6672c9916cdSFrançois Tigeot 	dev_priv->workarounds.reg[idx].addr = addr;
6682c9916cdSFrançois Tigeot 	dev_priv->workarounds.reg[idx].value = val;
6692c9916cdSFrançois Tigeot 	dev_priv->workarounds.reg[idx].mask = mask;
6702c9916cdSFrançois Tigeot 
6712c9916cdSFrançois Tigeot 	dev_priv->workarounds.count++;
6722c9916cdSFrançois Tigeot 
6732c9916cdSFrançois Tigeot 	return 0;
6742c9916cdSFrançois Tigeot }
6752c9916cdSFrançois Tigeot 
676a05eeebfSFrançois Tigeot #define WA_REG(addr, mask, val) do { \
6772c9916cdSFrançois Tigeot 		const int r = wa_add(dev_priv, (addr), (mask), (val)); \
6782c9916cdSFrançois Tigeot 		if (r) \
6792c9916cdSFrançois Tigeot 			return r; \
680a05eeebfSFrançois Tigeot 	} while (0)
6812c9916cdSFrançois Tigeot 
6822c9916cdSFrançois Tigeot #define WA_SET_BIT_MASKED(addr, mask) \
6832c9916cdSFrançois Tigeot 	WA_REG(addr, (mask), _MASKED_BIT_ENABLE(mask))
6842c9916cdSFrançois Tigeot 
6852c9916cdSFrançois Tigeot #define WA_CLR_BIT_MASKED(addr, mask) \
6862c9916cdSFrançois Tigeot 	WA_REG(addr, (mask), _MASKED_BIT_DISABLE(mask))
6872c9916cdSFrançois Tigeot 
6882c9916cdSFrançois Tigeot #define WA_SET_FIELD_MASKED(addr, mask, value) \
6892c9916cdSFrançois Tigeot 	WA_REG(addr, mask, _MASKED_FIELD(mask, value))
6902c9916cdSFrançois Tigeot 
6912c9916cdSFrançois Tigeot #define WA_SET_BIT(addr, mask) WA_REG(addr, mask, I915_READ(addr) | (mask))
6922c9916cdSFrançois Tigeot #define WA_CLR_BIT(addr, mask) WA_REG(addr, mask, I915_READ(addr) & ~(mask))
6932c9916cdSFrançois Tigeot 
6942c9916cdSFrançois Tigeot #define WA_WRITE(addr, val) WA_REG(addr, 0xffffffff, val)
6952c9916cdSFrançois Tigeot 
6968621f407SFrançois Tigeot static int wa_ring_whitelist_reg(struct intel_engine_cs *engine,
6978621f407SFrançois Tigeot 				 i915_reg_t reg)
698c0e85e96SFrançois Tigeot {
6991487f786SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
700c0e85e96SFrançois Tigeot 	struct i915_workarounds *wa = &dev_priv->workarounds;
7018621f407SFrançois Tigeot 	const uint32_t index = wa->hw_whitelist_count[engine->id];
702c0e85e96SFrançois Tigeot 
703c0e85e96SFrançois Tigeot 	if (WARN_ON(index >= RING_MAX_NONPRIV_SLOTS))
704c0e85e96SFrançois Tigeot 		return -EINVAL;
705c0e85e96SFrançois Tigeot 
7068621f407SFrançois Tigeot 	WA_WRITE(RING_FORCE_TO_NONPRIV(engine->mmio_base, index),
707c0e85e96SFrançois Tigeot 		 i915_mmio_reg_offset(reg));
7088621f407SFrançois Tigeot 	wa->hw_whitelist_count[engine->id]++;
709c0e85e96SFrançois Tigeot 
710c0e85e96SFrançois Tigeot 	return 0;
711c0e85e96SFrançois Tigeot }
712c0e85e96SFrançois Tigeot 
7138621f407SFrançois Tigeot static int gen8_init_workarounds(struct intel_engine_cs *engine)
7142c9916cdSFrançois Tigeot {
7151487f786SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
7162c9916cdSFrançois Tigeot 
717a05eeebfSFrançois Tigeot 	WA_SET_BIT_MASKED(INSTPM, INSTPM_FORCE_ORDERING);
718a05eeebfSFrançois Tigeot 
719352ff8bdSFrançois Tigeot 	/* WaDisableAsyncFlipPerfMode:bdw,chv */
720a05eeebfSFrançois Tigeot 	WA_SET_BIT_MASKED(MI_MODE, ASYNC_FLIP_PERF_DISABLE);
721a05eeebfSFrançois Tigeot 
722352ff8bdSFrançois Tigeot 	/* WaDisablePartialInstShootdown:bdw,chv */
7232c9916cdSFrançois Tigeot 	WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN,
724352ff8bdSFrançois Tigeot 			  PARTIAL_INSTRUCTION_SHOOTDOWN_DISABLE);
7251b13d190SFrançois Tigeot 
7261b13d190SFrançois Tigeot 	/* Use Force Non-Coherent whenever executing a 3D context. This is a
7271b13d190SFrançois Tigeot 	 * workaround for for a possible hang in the unlikely event a TLB
7281b13d190SFrançois Tigeot 	 * invalidation occurs during a PSD flush.
7291b13d190SFrançois Tigeot 	 */
730352ff8bdSFrançois Tigeot 	/* WaForceEnableNonCoherent:bdw,chv */
731352ff8bdSFrançois Tigeot 	/* WaHdcDisableFetchWhenMasked:bdw,chv */
7322c9916cdSFrançois Tigeot 	WA_SET_BIT_MASKED(HDC_CHICKEN0,
7332c9916cdSFrançois Tigeot 			  HDC_DONOT_FETCH_MEM_WHEN_MASKED |
734352ff8bdSFrançois Tigeot 			  HDC_FORCE_NON_COHERENT);
7352c9916cdSFrançois Tigeot 
7362c9916cdSFrançois Tigeot 	/* From the Haswell PRM, Command Reference: Registers, CACHE_MODE_0:
7372c9916cdSFrançois Tigeot 	 * "The Hierarchical Z RAW Stall Optimization allows non-overlapping
7382c9916cdSFrançois Tigeot 	 *  polygons in the same 8x4 pixel/sample area to be processed without
7392c9916cdSFrançois Tigeot 	 *  stalling waiting for the earlier ones to write to Hierarchical Z
7402c9916cdSFrançois Tigeot 	 *  buffer."
7412c9916cdSFrançois Tigeot 	 *
742352ff8bdSFrançois Tigeot 	 * This optimization is off by default for BDW and CHV; turn it on.
7432c9916cdSFrançois Tigeot 	 */
7442c9916cdSFrançois Tigeot 	WA_CLR_BIT_MASKED(CACHE_MODE_0_GEN7, HIZ_RAW_STALL_OPT_DISABLE);
7451b13d190SFrançois Tigeot 
746352ff8bdSFrançois Tigeot 	/* Wa4x4STCOptimizationDisable:bdw,chv */
747352ff8bdSFrançois Tigeot 	WA_SET_BIT_MASKED(CACHE_MODE_1, GEN8_4x4_STC_OPTIMIZATION_DISABLE);
7481b13d190SFrançois Tigeot 
7491b13d190SFrançois Tigeot 	/*
7501b13d190SFrançois Tigeot 	 * BSpec recommends 8x4 when MSAA is used,
7511b13d190SFrançois Tigeot 	 * however in practice 16x4 seems fastest.
7521b13d190SFrançois Tigeot 	 *
7531b13d190SFrançois Tigeot 	 * Note that PS/WM thread counts depend on the WIZ hashing
7541b13d190SFrançois Tigeot 	 * disable bit, which we don't touch here, but it's good
7551b13d190SFrançois Tigeot 	 * to keep in mind (see 3DSTATE_PS and 3DSTATE_WM).
7561b13d190SFrançois Tigeot 	 */
7572c9916cdSFrançois Tigeot 	WA_SET_FIELD_MASKED(GEN7_GT_MODE,
7582c9916cdSFrançois Tigeot 			    GEN6_WIZ_HASHING_MASK,
7592c9916cdSFrançois Tigeot 			    GEN6_WIZ_HASHING_16x4);
7601b13d190SFrançois Tigeot 
7611b13d190SFrançois Tigeot 	return 0;
7621b13d190SFrançois Tigeot }
7631b13d190SFrançois Tigeot 
7648621f407SFrançois Tigeot static int bdw_init_workarounds(struct intel_engine_cs *engine)
7651b13d190SFrançois Tigeot {
7661487f786SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
767352ff8bdSFrançois Tigeot 	int ret;
7681b13d190SFrançois Tigeot 
7698621f407SFrançois Tigeot 	ret = gen8_init_workarounds(engine);
770352ff8bdSFrançois Tigeot 	if (ret)
771352ff8bdSFrançois Tigeot 		return ret;
772a05eeebfSFrançois Tigeot 
773352ff8bdSFrançois Tigeot 	/* WaDisableThreadStallDopClockGating:bdw (pre-production) */
774352ff8bdSFrançois Tigeot 	WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN, STALL_DOP_GATING_DISABLE);
775a05eeebfSFrançois Tigeot 
776352ff8bdSFrançois Tigeot 	/* WaDisableDopClockGating:bdw */
777352ff8bdSFrançois Tigeot 	WA_SET_BIT_MASKED(GEN7_ROW_CHICKEN2,
778352ff8bdSFrançois Tigeot 			  DOP_CLOCK_GATING_DISABLE);
7791b13d190SFrançois Tigeot 
780352ff8bdSFrançois Tigeot 	WA_SET_BIT_MASKED(HALF_SLICE_CHICKEN3,
781352ff8bdSFrançois Tigeot 			  GEN8_SAMPLER_POWER_BYPASS_DIS);
782352ff8bdSFrançois Tigeot 
7832c9916cdSFrançois Tigeot 	WA_SET_BIT_MASKED(HDC_CHICKEN0,
784352ff8bdSFrançois Tigeot 			  /* WaForceContextSaveRestoreNonCoherent:bdw */
785352ff8bdSFrançois Tigeot 			  HDC_FORCE_CONTEXT_SAVE_RESTORE_NON_COHERENT |
786352ff8bdSFrançois Tigeot 			  /* WaDisableFenceDestinationToSLM:bdw (pre-prod) */
7871487f786SFrançois Tigeot 			  (IS_BDW_GT3(dev_priv) ? HDC_FENCE_DEST_SLM_DISABLE : 0));
7881b13d190SFrançois Tigeot 
789352ff8bdSFrançois Tigeot 	return 0;
790352ff8bdSFrançois Tigeot }
7911b13d190SFrançois Tigeot 
7928621f407SFrançois Tigeot static int chv_init_workarounds(struct intel_engine_cs *engine)
793352ff8bdSFrançois Tigeot {
7941487f786SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
795352ff8bdSFrançois Tigeot 	int ret;
796352ff8bdSFrançois Tigeot 
7978621f407SFrançois Tigeot 	ret = gen8_init_workarounds(engine);
798352ff8bdSFrançois Tigeot 	if (ret)
799352ff8bdSFrançois Tigeot 		return ret;
800352ff8bdSFrançois Tigeot 
801352ff8bdSFrançois Tigeot 	/* WaDisableThreadStallDopClockGating:chv */
802352ff8bdSFrançois Tigeot 	WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN, STALL_DOP_GATING_DISABLE);
8032c9916cdSFrançois Tigeot 
8042c9916cdSFrançois Tigeot 	/* Improve HiZ throughput on CHV. */
8052c9916cdSFrançois Tigeot 	WA_SET_BIT_MASKED(HIZ_CHICKEN, CHV_HZ_8X8_MODE_IN_1X);
8062c9916cdSFrançois Tigeot 
8072c9916cdSFrançois Tigeot 	return 0;
8082c9916cdSFrançois Tigeot }
8092c9916cdSFrançois Tigeot 
8108621f407SFrançois Tigeot static int gen9_init_workarounds(struct intel_engine_cs *engine)
811477eb7f9SFrançois Tigeot {
8121487f786SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
813c0e85e96SFrançois Tigeot 	int ret;
814477eb7f9SFrançois Tigeot 
8158621f407SFrançois Tigeot 	/* WaConextSwitchWithConcurrentTLBInvalidate:skl,bxt,kbl */
8168621f407SFrançois Tigeot 	I915_WRITE(GEN9_CSFE_CHICKEN1_RCS, _MASKED_BIT_ENABLE(GEN9_PREEMPT_GPGPU_SYNC_SWITCH_DISABLE));
8178621f407SFrançois Tigeot 
8188621f407SFrançois Tigeot 	/* WaEnableLbsSlaRetryTimerDecrement:skl,bxt,kbl */
819352ff8bdSFrançois Tigeot 	I915_WRITE(BDW_SCRATCH1, I915_READ(BDW_SCRATCH1) |
820352ff8bdSFrançois Tigeot 		   GEN9_LBS_SLA_RETRY_TIMER_DECREMENT_ENABLE);
821352ff8bdSFrançois Tigeot 
8228621f407SFrançois Tigeot 	/* WaDisableKillLogic:bxt,skl,kbl */
823352ff8bdSFrançois Tigeot 	I915_WRITE(GAM_ECOCHK, I915_READ(GAM_ECOCHK) |
824352ff8bdSFrançois Tigeot 		   ECOCHK_DIS_TLB);
825352ff8bdSFrançois Tigeot 
8268621f407SFrançois Tigeot 	/* WaClearFlowControlGpgpuContextSave:skl,bxt,kbl */
8278621f407SFrançois Tigeot 	/* WaDisablePartialInstShootdown:skl,bxt,kbl */
828477eb7f9SFrançois Tigeot 	WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN,
8298621f407SFrançois Tigeot 			  FLOW_CONTROL_ENABLE |
830477eb7f9SFrançois Tigeot 			  PARTIAL_INSTRUCTION_SHOOTDOWN_DISABLE);
831477eb7f9SFrançois Tigeot 
8328621f407SFrançois Tigeot 	/* Syncing dependencies between camera and graphics:skl,bxt,kbl */
833477eb7f9SFrançois Tigeot 	WA_SET_BIT_MASKED(HALF_SLICE_CHICKEN3,
834477eb7f9SFrançois Tigeot 			  GEN9_DISABLE_OCL_OOB_SUPPRESS_LOGIC);
835477eb7f9SFrançois Tigeot 
836*1e12ee3bSFrançois Tigeot 	/* WaDisableDgMirrorFixInHalfSliceChicken5:bxt */
837*1e12ee3bSFrançois Tigeot 	if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1))
838477eb7f9SFrançois Tigeot 		WA_CLR_BIT_MASKED(GEN9_HALF_SLICE_CHICKEN5,
839477eb7f9SFrançois Tigeot 				  GEN9_DG_MIRROR_FIX_ENABLE);
840477eb7f9SFrançois Tigeot 
841*1e12ee3bSFrançois Tigeot 	/* WaSetDisablePixMaskCammingAndRhwoInCommonSliceChicken:bxt */
842*1e12ee3bSFrançois Tigeot 	if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1)) {
843477eb7f9SFrançois Tigeot 		WA_SET_BIT_MASKED(GEN7_COMMON_SLICE_CHICKEN1,
844477eb7f9SFrançois Tigeot 				  GEN9_RHWO_OPTIMIZATION_DISABLE);
845a05eeebfSFrançois Tigeot 		/*
846a05eeebfSFrançois Tigeot 		 * WA also requires GEN9_SLICE_COMMON_ECO_CHICKEN0[14:14] to be set
847a05eeebfSFrançois Tigeot 		 * but we do that in per ctx batchbuffer as there is an issue
848a05eeebfSFrançois Tigeot 		 * with this register not getting restored on ctx restore
849a05eeebfSFrançois Tigeot 		 */
850477eb7f9SFrançois Tigeot 	}
851477eb7f9SFrançois Tigeot 
8528621f407SFrançois Tigeot 	/* WaEnableSamplerGPGPUPreemptionSupport:skl,bxt,kbl */
853477eb7f9SFrançois Tigeot 	WA_SET_BIT_MASKED(GEN9_HALF_SLICE_CHICKEN7,
8548621f407SFrançois Tigeot 			  GEN9_ENABLE_GPGPU_PREEMPTION);
855477eb7f9SFrançois Tigeot 
8568621f407SFrançois Tigeot 	/* Wa4x4STCOptimizationDisable:skl,bxt,kbl */
8578621f407SFrançois Tigeot 	/* WaDisablePartialResolveInVc:skl,bxt,kbl */
858352ff8bdSFrançois Tigeot 	WA_SET_BIT_MASKED(CACHE_MODE_1, (GEN8_4x4_STC_OPTIMIZATION_DISABLE |
859352ff8bdSFrançois Tigeot 					 GEN9_PARTIAL_RESOLVE_IN_VC_DISABLE));
860477eb7f9SFrançois Tigeot 
8618621f407SFrançois Tigeot 	/* WaCcsTlbPrefetchDisable:skl,bxt,kbl */
862477eb7f9SFrançois Tigeot 	WA_CLR_BIT_MASKED(GEN9_HALF_SLICE_CHICKEN5,
863477eb7f9SFrançois Tigeot 			  GEN9_CCS_TLB_PREFETCH_ENABLE);
864477eb7f9SFrançois Tigeot 
865*1e12ee3bSFrançois Tigeot 	/* WaDisableMaskBasedCammingInRCC:bxt */
866*1e12ee3bSFrançois Tigeot 	if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1))
86719c468b4SFrançois Tigeot 		WA_SET_BIT_MASKED(SLICE_ECO_CHICKEN0,
86819c468b4SFrançois Tigeot 				  PIXEL_MASK_CAMMING_DISABLE);
86919c468b4SFrançois Tigeot 
8708621f407SFrançois Tigeot 	/* WaForceContextSaveRestoreNonCoherent:skl,bxt,kbl */
8718621f407SFrançois Tigeot 	WA_SET_BIT_MASKED(HDC_CHICKEN0,
8728621f407SFrançois Tigeot 			  HDC_FORCE_CONTEXT_SAVE_RESTORE_NON_COHERENT |
8738621f407SFrançois Tigeot 			  HDC_FORCE_CSR_NON_COHERENT_OVR_DISABLE);
87419c468b4SFrançois Tigeot 
8758621f407SFrançois Tigeot 	/* WaForceEnableNonCoherent and WaDisableHDCInvalidation are
8768621f407SFrançois Tigeot 	 * both tied to WaForceContextSaveRestoreNonCoherent
8778621f407SFrançois Tigeot 	 * in some hsds for skl. We keep the tie for all gen9. The
8788621f407SFrançois Tigeot 	 * documentation is a bit hazy and so we want to get common behaviour,
8798621f407SFrançois Tigeot 	 * even though there is no clear evidence we would need both on kbl/bxt.
8808621f407SFrançois Tigeot 	 * This area has been source of system hangs so we play it safe
8818621f407SFrançois Tigeot 	 * and mimic the skl regardless of what bspec says.
8828621f407SFrançois Tigeot 	 *
8838621f407SFrançois Tigeot 	 * Use Force Non-Coherent whenever executing a 3D context. This
8848621f407SFrançois Tigeot 	 * is a workaround for a possible hang in the unlikely event
8858621f407SFrançois Tigeot 	 * a TLB invalidation occurs during a PSD flush.
8868621f407SFrançois Tigeot 	 */
8878621f407SFrançois Tigeot 
8888621f407SFrançois Tigeot 	/* WaForceEnableNonCoherent:skl,bxt,kbl */
8898621f407SFrançois Tigeot 	WA_SET_BIT_MASKED(HDC_CHICKEN0,
8908621f407SFrançois Tigeot 			  HDC_FORCE_NON_COHERENT);
8918621f407SFrançois Tigeot 
8928621f407SFrançois Tigeot 	/* WaDisableHDCInvalidation:skl,bxt,kbl */
8938621f407SFrançois Tigeot 	I915_WRITE(GAM_ECOCHK, I915_READ(GAM_ECOCHK) |
8948621f407SFrançois Tigeot 		   BDW_DISABLE_HDC_INVALIDATION);
8958621f407SFrançois Tigeot 
8968621f407SFrançois Tigeot 	/* WaDisableSamplerPowerBypassForSOPingPong:skl,bxt,kbl */
8978621f407SFrançois Tigeot 	if (IS_SKYLAKE(dev_priv) ||
8988621f407SFrançois Tigeot 	    IS_KABYLAKE(dev_priv) ||
8998621f407SFrançois Tigeot 	    IS_BXT_REVID(dev_priv, 0, BXT_REVID_B0))
900352ff8bdSFrançois Tigeot 		WA_SET_BIT_MASKED(HALF_SLICE_CHICKEN3,
901352ff8bdSFrançois Tigeot 				  GEN8_SAMPLER_POWER_BYPASS_DIS);
902352ff8bdSFrançois Tigeot 
9038621f407SFrançois Tigeot 	/* WaDisableSTUnitPowerOptimization:skl,bxt,kbl */
904352ff8bdSFrançois Tigeot 	WA_SET_BIT_MASKED(HALF_SLICE_CHICKEN2, GEN8_ST_PO_DISABLE);
905352ff8bdSFrançois Tigeot 
9068621f407SFrançois Tigeot 	/* WaOCLCoherentLineFlush:skl,bxt,kbl */
907c0e85e96SFrançois Tigeot 	I915_WRITE(GEN8_L3SQCREG4, (I915_READ(GEN8_L3SQCREG4) |
908c0e85e96SFrançois Tigeot 				    GEN8_LQSC_FLUSH_COHERENT_LINES));
909c0e85e96SFrançois Tigeot 
9108621f407SFrançois Tigeot 	/* WaVFEStateAfterPipeControlwithMediaStateClear:skl,bxt */
9118621f407SFrançois Tigeot 	ret = wa_ring_whitelist_reg(engine, GEN9_CTX_PREEMPT_REG);
912c0e85e96SFrançois Tigeot 	if (ret)
913c0e85e96SFrançois Tigeot 		return ret;
914c0e85e96SFrançois Tigeot 
9158621f407SFrançois Tigeot 	/* WaEnablePreemptionGranularityControlByUMD:skl,bxt,kbl */
9168621f407SFrançois Tigeot 	ret= wa_ring_whitelist_reg(engine, GEN8_CS_CHICKEN1);
9178621f407SFrançois Tigeot 	if (ret)
9188621f407SFrançois Tigeot 		return ret;
9198621f407SFrançois Tigeot 
9208621f407SFrançois Tigeot 	/* WaAllowUMDToModifyHDCChicken1:skl,bxt,kbl */
9218621f407SFrançois Tigeot 	ret = wa_ring_whitelist_reg(engine, GEN8_HDC_CHICKEN1);
922c0e85e96SFrançois Tigeot 	if (ret)
923c0e85e96SFrançois Tigeot 		return ret;
924c0e85e96SFrançois Tigeot 
925477eb7f9SFrançois Tigeot 	return 0;
926477eb7f9SFrançois Tigeot }
927477eb7f9SFrançois Tigeot 
9288621f407SFrançois Tigeot static int skl_tune_iz_hashing(struct intel_engine_cs *engine)
929477eb7f9SFrançois Tigeot {
9301487f786SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
931477eb7f9SFrançois Tigeot 	u8 vals[3] = { 0, 0, 0 };
932477eb7f9SFrançois Tigeot 	unsigned int i;
933477eb7f9SFrançois Tigeot 
934477eb7f9SFrançois Tigeot 	for (i = 0; i < 3; i++) {
935477eb7f9SFrançois Tigeot 		u8 ss;
936477eb7f9SFrançois Tigeot 
937477eb7f9SFrançois Tigeot 		/*
938477eb7f9SFrançois Tigeot 		 * Only consider slices where one, and only one, subslice has 7
939477eb7f9SFrançois Tigeot 		 * EUs
940477eb7f9SFrançois Tigeot 		 */
941*1e12ee3bSFrançois Tigeot 		if (!is_power_of_2(INTEL_INFO(dev_priv)->sseu.subslice_7eu[i]))
942477eb7f9SFrançois Tigeot 			continue;
943477eb7f9SFrançois Tigeot 
944477eb7f9SFrançois Tigeot 		/*
945477eb7f9SFrançois Tigeot 		 * subslice_7eu[i] != 0 (because of the check above) and
946477eb7f9SFrançois Tigeot 		 * ss_max == 4 (maximum number of subslices possible per slice)
947477eb7f9SFrançois Tigeot 		 *
948477eb7f9SFrançois Tigeot 		 * ->    0 <= ss <= 3;
949477eb7f9SFrançois Tigeot 		 */
950*1e12ee3bSFrançois Tigeot 		ss = ffs(INTEL_INFO(dev_priv)->sseu.subslice_7eu[i]) - 1;
951477eb7f9SFrançois Tigeot 		vals[i] = 3 - ss;
952477eb7f9SFrançois Tigeot 	}
953477eb7f9SFrançois Tigeot 
954477eb7f9SFrançois Tigeot 	if (vals[0] == 0 && vals[1] == 0 && vals[2] == 0)
955477eb7f9SFrançois Tigeot 		return 0;
956477eb7f9SFrançois Tigeot 
957477eb7f9SFrançois Tigeot 	/* Tune IZ hashing. See intel_device_info_runtime_init() */
958477eb7f9SFrançois Tigeot 	WA_SET_FIELD_MASKED(GEN7_GT_MODE,
959477eb7f9SFrançois Tigeot 			    GEN9_IZ_HASHING_MASK(2) |
960477eb7f9SFrançois Tigeot 			    GEN9_IZ_HASHING_MASK(1) |
961477eb7f9SFrançois Tigeot 			    GEN9_IZ_HASHING_MASK(0),
962477eb7f9SFrançois Tigeot 			    GEN9_IZ_HASHING(2, vals[2]) |
963477eb7f9SFrançois Tigeot 			    GEN9_IZ_HASHING(1, vals[1]) |
964477eb7f9SFrançois Tigeot 			    GEN9_IZ_HASHING(0, vals[0]));
965477eb7f9SFrançois Tigeot 
966477eb7f9SFrançois Tigeot 	return 0;
967477eb7f9SFrançois Tigeot }
968477eb7f9SFrançois Tigeot 
9698621f407SFrançois Tigeot static int skl_init_workarounds(struct intel_engine_cs *engine)
970477eb7f9SFrançois Tigeot {
9711487f786SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
972352ff8bdSFrançois Tigeot 	int ret;
973477eb7f9SFrançois Tigeot 
9748621f407SFrançois Tigeot 	ret = gen9_init_workarounds(engine);
975352ff8bdSFrançois Tigeot 	if (ret)
976352ff8bdSFrançois Tigeot 		return ret;
977352ff8bdSFrançois Tigeot 
978c0e85e96SFrançois Tigeot 	/*
979c0e85e96SFrançois Tigeot 	 * Actual WA is to disable percontext preemption granularity control
980c0e85e96SFrançois Tigeot 	 * until D0 which is the default case so this is equivalent to
981c0e85e96SFrançois Tigeot 	 * !WaDisablePerCtxtPreemptionGranularityControl:skl
982c0e85e96SFrançois Tigeot 	 */
983c0e85e96SFrançois Tigeot 	I915_WRITE(GEN7_FF_SLICE_CS_CHICKEN1,
984c0e85e96SFrançois Tigeot 		   _MASKED_BIT_ENABLE(GEN9_FFSC_PERCTX_PREEMPT_CTRL));
985352ff8bdSFrançois Tigeot 
986352ff8bdSFrançois Tigeot 	/* WaEnableGapsTsvCreditFix:skl */
987352ff8bdSFrançois Tigeot 	I915_WRITE(GEN8_GARBCNTL, (I915_READ(GEN8_GARBCNTL) |
988352ff8bdSFrançois Tigeot 				   GEN9_GAPS_TSV_CREDIT_DISABLE));
989a05eeebfSFrançois Tigeot 
9908621f407SFrançois Tigeot 	/* WaDisableGafsUnitClkGating:skl */
9918621f407SFrançois Tigeot 	WA_SET_BIT(GEN7_UCGCTL4, GEN8_EU_GAUNIT_CLOCK_GATE_DISABLE);
9928621f407SFrançois Tigeot 
993bf017597SFrançois Tigeot 	/* WaInPlaceDecompressionHang:skl */
994bf017597SFrançois Tigeot 	if (IS_SKL_REVID(dev_priv, SKL_REVID_H0, REVID_FOREVER))
995bf017597SFrançois Tigeot 		WA_SET_BIT(GEN9_GAMT_ECO_REG_RW_IA,
996bf017597SFrançois Tigeot 			   GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS);
997bf017597SFrançois Tigeot 
998c0e85e96SFrançois Tigeot 	/* WaDisableLSQCROPERFforOCL:skl */
9998621f407SFrançois Tigeot 	ret = wa_ring_whitelist_reg(engine, GEN8_L3SQCREG4);
1000c0e85e96SFrançois Tigeot 	if (ret)
1001c0e85e96SFrançois Tigeot 		return ret;
1002c0e85e96SFrançois Tigeot 
10038621f407SFrançois Tigeot 	return skl_tune_iz_hashing(engine);
1004477eb7f9SFrançois Tigeot }
1005477eb7f9SFrançois Tigeot 
10068621f407SFrançois Tigeot static int bxt_init_workarounds(struct intel_engine_cs *engine)
100719c468b4SFrançois Tigeot {
10081487f786SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
1009352ff8bdSFrançois Tigeot 	int ret;
101019c468b4SFrançois Tigeot 
10118621f407SFrançois Tigeot 	ret = gen9_init_workarounds(engine);
1012352ff8bdSFrançois Tigeot 	if (ret)
1013352ff8bdSFrançois Tigeot 		return ret;
1014352ff8bdSFrançois Tigeot 
1015352ff8bdSFrançois Tigeot 	/* WaStoreMultiplePTEenable:bxt */
1016352ff8bdSFrançois Tigeot 	/* This is a requirement according to Hardware specification */
10171487f786SFrançois Tigeot 	if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1))
1018352ff8bdSFrançois Tigeot 		I915_WRITE(TILECTL, I915_READ(TILECTL) | TILECTL_TLBPF);
1019352ff8bdSFrançois Tigeot 
1020352ff8bdSFrançois Tigeot 	/* WaSetClckGatingDisableMedia:bxt */
10211487f786SFrançois Tigeot 	if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1)) {
1022352ff8bdSFrançois Tigeot 		I915_WRITE(GEN7_MISCCPCTL, (I915_READ(GEN7_MISCCPCTL) &
1023352ff8bdSFrançois Tigeot 					    ~GEN8_DOP_CLOCK_GATE_MEDIA_ENABLE));
1024352ff8bdSFrançois Tigeot 	}
102519c468b4SFrançois Tigeot 
102619c468b4SFrançois Tigeot 	/* WaDisableThreadStallDopClockGating:bxt */
102719c468b4SFrançois Tigeot 	WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN,
102819c468b4SFrançois Tigeot 			  STALL_DOP_GATING_DISABLE);
102919c468b4SFrançois Tigeot 
10301487f786SFrançois Tigeot 	/* WaDisablePooledEuLoadBalancingFix:bxt */
10311487f786SFrançois Tigeot 	if (IS_BXT_REVID(dev_priv, BXT_REVID_B0, REVID_FOREVER)) {
10321487f786SFrançois Tigeot 		WA_SET_BIT_MASKED(FF_SLICE_CS_CHICKEN2,
10331487f786SFrançois Tigeot 				  GEN9_POOLED_EU_LOAD_BALANCING_FIX_DISABLE);
10341487f786SFrançois Tigeot 	}
10351487f786SFrançois Tigeot 
103619c468b4SFrançois Tigeot 	/* WaDisableSbeCacheDispatchPortSharing:bxt */
10371487f786SFrançois Tigeot 	if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_B0)) {
103819c468b4SFrançois Tigeot 		WA_SET_BIT_MASKED(
103919c468b4SFrançois Tigeot 			GEN7_HALF_SLICE_CHICKEN1,
104019c468b4SFrançois Tigeot 			GEN7_SBE_SS_CACHE_DISPATCH_PORT_SHARING_DISABLE);
104119c468b4SFrançois Tigeot 	}
104219c468b4SFrançois Tigeot 
1043c0e85e96SFrançois Tigeot 	/* WaDisableObjectLevelPreemptionForTrifanOrPolygon:bxt */
1044c0e85e96SFrançois Tigeot 	/* WaDisableObjectLevelPreemptionForInstancedDraw:bxt */
1045c0e85e96SFrançois Tigeot 	/* WaDisableObjectLevelPreemtionForInstanceId:bxt */
1046c0e85e96SFrançois Tigeot 	/* WaDisableLSQCROPERFforOCL:bxt */
10471487f786SFrançois Tigeot 	if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1)) {
10488621f407SFrançois Tigeot 		ret = wa_ring_whitelist_reg(engine, GEN9_CS_DEBUG_MODE1);
1049c0e85e96SFrançois Tigeot 		if (ret)
1050c0e85e96SFrançois Tigeot 			return ret;
1051c0e85e96SFrançois Tigeot 
10528621f407SFrançois Tigeot 		ret = wa_ring_whitelist_reg(engine, GEN8_L3SQCREG4);
1053c0e85e96SFrançois Tigeot 		if (ret)
1054c0e85e96SFrançois Tigeot 			return ret;
1055c0e85e96SFrançois Tigeot 	}
1056c0e85e96SFrançois Tigeot 
10571487f786SFrançois Tigeot 	/* WaProgramL3SqcReg1DefaultForPerf:bxt */
10581487f786SFrançois Tigeot 	if (IS_BXT_REVID(dev_priv, BXT_REVID_B0, REVID_FOREVER))
10591487f786SFrançois Tigeot 		I915_WRITE(GEN8_L3SQCREG1, L3_GENERAL_PRIO_CREDITS(62) |
10601487f786SFrançois Tigeot 					   L3_HIGH_PRIO_CREDITS(2));
10611487f786SFrançois Tigeot 
1062bf017597SFrançois Tigeot 	/* WaToEnableHwFixForPushConstHWBug:bxt */
1063bf017597SFrançois Tigeot 	if (IS_BXT_REVID(dev_priv, BXT_REVID_C0, REVID_FOREVER))
10648621f407SFrançois Tigeot 		WA_SET_BIT_MASKED(COMMON_SLICE_CHICKEN2,
10658621f407SFrançois Tigeot 				  GEN8_SBE_DISABLE_REPLAY_BUF_OPTIMIZATION);
10668621f407SFrançois Tigeot 
1067bf017597SFrançois Tigeot 	/* WaInPlaceDecompressionHang:bxt */
1068bf017597SFrançois Tigeot 	if (IS_BXT_REVID(dev_priv, BXT_REVID_C0, REVID_FOREVER))
1069bf017597SFrançois Tigeot 		WA_SET_BIT(GEN9_GAMT_ECO_REG_RW_IA,
1070bf017597SFrançois Tigeot 			   GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS);
1071bf017597SFrançois Tigeot 
107219c468b4SFrançois Tigeot 	return 0;
107319c468b4SFrançois Tigeot }
107419c468b4SFrançois Tigeot 
10758621f407SFrançois Tigeot static int kbl_init_workarounds(struct intel_engine_cs *engine)
10762c9916cdSFrançois Tigeot {
10771487f786SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
10788621f407SFrançois Tigeot 	int ret;
10798621f407SFrançois Tigeot 
10808621f407SFrançois Tigeot 	ret = gen9_init_workarounds(engine);
10818621f407SFrançois Tigeot 	if (ret)
10828621f407SFrançois Tigeot 		return ret;
10838621f407SFrançois Tigeot 
10848621f407SFrançois Tigeot 	/* WaEnableGapsTsvCreditFix:kbl */
10858621f407SFrançois Tigeot 	I915_WRITE(GEN8_GARBCNTL, (I915_READ(GEN8_GARBCNTL) |
10868621f407SFrançois Tigeot 				   GEN9_GAPS_TSV_CREDIT_DISABLE));
10878621f407SFrançois Tigeot 
10888621f407SFrançois Tigeot 	/* WaDisableDynamicCreditSharing:kbl */
10898621f407SFrançois Tigeot 	if (IS_KBL_REVID(dev_priv, 0, KBL_REVID_B0))
10908621f407SFrançois Tigeot 		WA_SET_BIT(GAMT_CHKN_BIT_REG,
10918621f407SFrançois Tigeot 			   GAMT_CHKN_DISABLE_DYNAMIC_CREDIT_SHARING);
10928621f407SFrançois Tigeot 
10938621f407SFrançois Tigeot 	/* WaDisableFenceDestinationToSLM:kbl (pre-prod) */
10948621f407SFrançois Tigeot 	if (IS_KBL_REVID(dev_priv, KBL_REVID_A0, KBL_REVID_A0))
10958621f407SFrançois Tigeot 		WA_SET_BIT_MASKED(HDC_CHICKEN0,
10968621f407SFrançois Tigeot 				  HDC_FENCE_DEST_SLM_DISABLE);
10978621f407SFrançois Tigeot 
10988621f407SFrançois Tigeot 	/* GEN8_L3SQCREG4 has a dependency with WA batch so any new changes
10998621f407SFrançois Tigeot 	 * involving this register should also be added to WA batch as required.
11008621f407SFrançois Tigeot 	 */
11018621f407SFrançois Tigeot 	if (IS_KBL_REVID(dev_priv, 0, KBL_REVID_E0))
11028621f407SFrançois Tigeot 		/* WaDisableLSQCROPERFforOCL:kbl */
11038621f407SFrançois Tigeot 		I915_WRITE(GEN8_L3SQCREG4, I915_READ(GEN8_L3SQCREG4) |
11048621f407SFrançois Tigeot 			   GEN8_LQSC_RO_PERF_DIS);
11058621f407SFrançois Tigeot 
1106bf017597SFrançois Tigeot 	/* WaToEnableHwFixForPushConstHWBug:kbl */
1107bf017597SFrançois Tigeot 	if (IS_KBL_REVID(dev_priv, KBL_REVID_C0, REVID_FOREVER))
11088621f407SFrançois Tigeot 		WA_SET_BIT_MASKED(COMMON_SLICE_CHICKEN2,
11098621f407SFrançois Tigeot 				  GEN8_SBE_DISABLE_REPLAY_BUF_OPTIMIZATION);
11108621f407SFrançois Tigeot 
11118621f407SFrançois Tigeot 	/* WaDisableGafsUnitClkGating:kbl */
11128621f407SFrançois Tigeot 	WA_SET_BIT(GEN7_UCGCTL4, GEN8_EU_GAUNIT_CLOCK_GATE_DISABLE);
11138621f407SFrançois Tigeot 
11148621f407SFrançois Tigeot 	/* WaDisableSbeCacheDispatchPortSharing:kbl */
11158621f407SFrançois Tigeot 	WA_SET_BIT_MASKED(
11168621f407SFrançois Tigeot 		GEN7_HALF_SLICE_CHICKEN1,
11178621f407SFrançois Tigeot 		GEN7_SBE_SS_CACHE_DISPATCH_PORT_SHARING_DISABLE);
11188621f407SFrançois Tigeot 
1119bf017597SFrançois Tigeot 	/* WaInPlaceDecompressionHang:kbl */
1120bf017597SFrançois Tigeot 	WA_SET_BIT(GEN9_GAMT_ECO_REG_RW_IA,
1121bf017597SFrançois Tigeot 		   GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS);
1122bf017597SFrançois Tigeot 
11238621f407SFrançois Tigeot 	/* WaDisableLSQCROPERFforOCL:kbl */
11248621f407SFrançois Tigeot 	ret = wa_ring_whitelist_reg(engine, GEN8_L3SQCREG4);
11258621f407SFrançois Tigeot 	if (ret)
11268621f407SFrançois Tigeot 		return ret;
11278621f407SFrançois Tigeot 
11288621f407SFrançois Tigeot 	return 0;
11298621f407SFrançois Tigeot }
11308621f407SFrançois Tigeot 
11318621f407SFrançois Tigeot int init_workarounds_ring(struct intel_engine_cs *engine)
11328621f407SFrançois Tigeot {
11331487f786SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
11342c9916cdSFrançois Tigeot 
11358621f407SFrançois Tigeot 	WARN_ON(engine->id != RCS);
11362c9916cdSFrançois Tigeot 
11372c9916cdSFrançois Tigeot 	dev_priv->workarounds.count = 0;
1138c0e85e96SFrançois Tigeot 	dev_priv->workarounds.hw_whitelist_count[RCS] = 0;
11392c9916cdSFrançois Tigeot 
11401487f786SFrançois Tigeot 	if (IS_BROADWELL(dev_priv))
11418621f407SFrançois Tigeot 		return bdw_init_workarounds(engine);
11422c9916cdSFrançois Tigeot 
11431487f786SFrançois Tigeot 	if (IS_CHERRYVIEW(dev_priv))
11448621f407SFrançois Tigeot 		return chv_init_workarounds(engine);
11451b13d190SFrançois Tigeot 
11461487f786SFrançois Tigeot 	if (IS_SKYLAKE(dev_priv))
11478621f407SFrançois Tigeot 		return skl_init_workarounds(engine);
114819c468b4SFrançois Tigeot 
11491487f786SFrançois Tigeot 	if (IS_BROXTON(dev_priv))
11508621f407SFrançois Tigeot 		return bxt_init_workarounds(engine);
11518621f407SFrançois Tigeot 
11528621f407SFrançois Tigeot 	if (IS_KABYLAKE(dev_priv))
11538621f407SFrançois Tigeot 		return kbl_init_workarounds(engine);
1154477eb7f9SFrançois Tigeot 
11551b13d190SFrançois Tigeot 	return 0;
11561b13d190SFrançois Tigeot }
11571b13d190SFrançois Tigeot 
11588621f407SFrançois Tigeot static int init_render_ring(struct intel_engine_cs *engine)
1159e3adcf8fSFrançois Tigeot {
11601487f786SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
11618621f407SFrançois Tigeot 	int ret = init_ring_common(engine);
116224edb884SFrançois Tigeot 	if (ret)
116324edb884SFrançois Tigeot 		return ret;
1164e3adcf8fSFrançois Tigeot 
1165ba55f2f5SFrançois Tigeot 	/* WaTimedSingleVertexDispatch:cl,bw,ctg,elk,ilk,snb */
11661487f786SFrançois Tigeot 	if (IS_GEN(dev_priv, 4, 6))
1167f4e1c372SFrançois Tigeot 		I915_WRITE(MI_MODE, _MASKED_BIT_ENABLE(VS_TIMER_DISPATCH));
1168f4e1c372SFrançois Tigeot 
1169f4e1c372SFrançois Tigeot 	/* We need to disable the AsyncFlip performance optimisations in order
1170f4e1c372SFrançois Tigeot 	 * to use MI_WAIT_FOR_EVENT within the CS. It should already be
1171f4e1c372SFrançois Tigeot 	 * programmed to '1' on all products.
11725d0b1887SFrançois Tigeot 	 *
1173a05eeebfSFrançois Tigeot 	 * WaDisableAsyncFlipPerfMode:snb,ivb,hsw,vlv
1174f4e1c372SFrançois Tigeot 	 */
11751487f786SFrançois Tigeot 	if (IS_GEN(dev_priv, 6, 7))
1176f4e1c372SFrançois Tigeot 		I915_WRITE(MI_MODE, _MASKED_BIT_ENABLE(ASYNC_FLIP_PERF_DISABLE));
1177f4e1c372SFrançois Tigeot 
1178f4e1c372SFrançois Tigeot 	/* Required for the hardware to program scanline values for waiting */
1179ba55f2f5SFrançois Tigeot 	/* WaEnableFlushTlbInvalidationMode:snb */
11801487f786SFrançois Tigeot 	if (IS_GEN6(dev_priv))
1181f4e1c372SFrançois Tigeot 		I915_WRITE(GFX_MODE,
1182ba55f2f5SFrançois Tigeot 			   _MASKED_BIT_ENABLE(GFX_TLB_INVALIDATE_EXPLICIT));
1183f4e1c372SFrançois Tigeot 
1184ba55f2f5SFrançois Tigeot 	/* WaBCSVCSTlbInvalidationMode:ivb,vlv,hsw */
11851487f786SFrançois Tigeot 	if (IS_GEN7(dev_priv))
1186e3adcf8fSFrançois Tigeot 		I915_WRITE(GFX_MODE_GEN7,
1187ba55f2f5SFrançois Tigeot 			   _MASKED_BIT_ENABLE(GFX_TLB_INVALIDATE_EXPLICIT) |
1188f4e1c372SFrançois Tigeot 			   _MASKED_BIT_ENABLE(GFX_REPLAY_MODE));
1189e3adcf8fSFrançois Tigeot 
11901487f786SFrançois Tigeot 	if (IS_GEN6(dev_priv)) {
1191e3adcf8fSFrançois Tigeot 		/* From the Sandybridge PRM, volume 1 part 3, page 24:
1192e3adcf8fSFrançois Tigeot 		 * "If this bit is set, STCunit will have LRA as replacement
1193e3adcf8fSFrançois Tigeot 		 *  policy. [...] This bit must be reset.  LRA replacement
1194e3adcf8fSFrançois Tigeot 		 *  policy is not supported."
1195e3adcf8fSFrançois Tigeot 		 */
1196e3adcf8fSFrançois Tigeot 		I915_WRITE(CACHE_MODE_0,
1197f4e1c372SFrançois Tigeot 			   _MASKED_BIT_DISABLE(CM0_STC_EVICT_DISABLE_LRA_SNB));
1198e3adcf8fSFrançois Tigeot 	}
1199e3adcf8fSFrançois Tigeot 
12001487f786SFrançois Tigeot 	if (IS_GEN(dev_priv, 6, 7))
1201f4e1c372SFrançois Tigeot 		I915_WRITE(INSTPM, _MASKED_BIT_ENABLE(INSTPM_FORCE_ORDERING));
1202f4e1c372SFrançois Tigeot 
1203303bf270SFrançois Tigeot 	if (INTEL_INFO(dev_priv)->gen >= 6)
1204303bf270SFrançois Tigeot 		I915_WRITE_IMR(engine, ~engine->irq_keep_mask);
1205e3adcf8fSFrançois Tigeot 
12068621f407SFrançois Tigeot 	return init_workarounds_ring(engine);
1207e3adcf8fSFrançois Tigeot }
1208e3adcf8fSFrançois Tigeot 
12098621f407SFrançois Tigeot static void render_ring_cleanup(struct intel_engine_cs *engine)
1210e3adcf8fSFrançois Tigeot {
12111487f786SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
121224edb884SFrançois Tigeot 
1213*1e12ee3bSFrançois Tigeot 	i915_vma_unpin_and_release(&dev_priv->semaphore);
1214e3adcf8fSFrançois Tigeot }
1215e3adcf8fSFrançois Tigeot 
121671f41f3eSFrançois Tigeot static int gen8_rcs_signal(struct drm_i915_gem_request *req)
121724edb884SFrançois Tigeot {
121871f41f3eSFrançois Tigeot 	struct intel_ring *ring = req->ring;
121971f41f3eSFrançois Tigeot 	struct drm_i915_private *dev_priv = req->i915;
122024edb884SFrançois Tigeot 	struct intel_engine_cs *waiter;
12218621f407SFrançois Tigeot 	enum intel_engine_id id;
12228621f407SFrançois Tigeot 	int ret, num_rings;
122324edb884SFrançois Tigeot 
1224*1e12ee3bSFrançois Tigeot 	num_rings = INTEL_INFO(dev_priv)->num_rings;
122571f41f3eSFrançois Tigeot 	ret = intel_ring_begin(req, (num_rings-1) * 8);
122624edb884SFrançois Tigeot 	if (ret)
122724edb884SFrançois Tigeot 		return ret;
122824edb884SFrançois Tigeot 
1229*1e12ee3bSFrançois Tigeot 	for_each_engine(waiter, dev_priv, id) {
123071f41f3eSFrançois Tigeot 		u64 gtt_offset = req->engine->semaphore.signal_ggtt[id];
123124edb884SFrançois Tigeot 		if (gtt_offset == MI_SEMAPHORE_SYNC_INVALID)
123224edb884SFrançois Tigeot 			continue;
123324edb884SFrançois Tigeot 
123471f41f3eSFrançois Tigeot 		intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(6));
123571f41f3eSFrançois Tigeot 		intel_ring_emit(ring,
123671f41f3eSFrançois Tigeot 				PIPE_CONTROL_GLOBAL_GTT_IVB |
123724edb884SFrançois Tigeot 				PIPE_CONTROL_QW_WRITE |
12381487f786SFrançois Tigeot 				PIPE_CONTROL_CS_STALL);
123971f41f3eSFrançois Tigeot 		intel_ring_emit(ring, lower_32_bits(gtt_offset));
124071f41f3eSFrançois Tigeot 		intel_ring_emit(ring, upper_32_bits(gtt_offset));
124171f41f3eSFrançois Tigeot 		intel_ring_emit(ring, req->fence.seqno);
124271f41f3eSFrançois Tigeot 		intel_ring_emit(ring, 0);
124371f41f3eSFrançois Tigeot 		intel_ring_emit(ring,
124471f41f3eSFrançois Tigeot 				MI_SEMAPHORE_SIGNAL |
12458621f407SFrançois Tigeot 				MI_SEMAPHORE_TARGET(waiter->hw_id));
124671f41f3eSFrançois Tigeot 		intel_ring_emit(ring, 0);
124724edb884SFrançois Tigeot 	}
124871f41f3eSFrançois Tigeot 	intel_ring_advance(ring);
124924edb884SFrançois Tigeot 
125024edb884SFrançois Tigeot 	return 0;
125124edb884SFrançois Tigeot }
125224edb884SFrançois Tigeot 
125371f41f3eSFrançois Tigeot static int gen8_xcs_signal(struct drm_i915_gem_request *req)
125424edb884SFrançois Tigeot {
125571f41f3eSFrançois Tigeot 	struct intel_ring *ring = req->ring;
125671f41f3eSFrançois Tigeot 	struct drm_i915_private *dev_priv = req->i915;
125724edb884SFrançois Tigeot 	struct intel_engine_cs *waiter;
12588621f407SFrançois Tigeot 	enum intel_engine_id id;
12598621f407SFrançois Tigeot 	int ret, num_rings;
126024edb884SFrançois Tigeot 
1261*1e12ee3bSFrançois Tigeot 	num_rings = INTEL_INFO(dev_priv)->num_rings;
126271f41f3eSFrançois Tigeot 	ret = intel_ring_begin(req, (num_rings-1) * 6);
126324edb884SFrançois Tigeot 	if (ret)
126424edb884SFrançois Tigeot 		return ret;
126524edb884SFrançois Tigeot 
1266*1e12ee3bSFrançois Tigeot 	for_each_engine(waiter, dev_priv, id) {
126771f41f3eSFrançois Tigeot 		u64 gtt_offset = req->engine->semaphore.signal_ggtt[id];
126824edb884SFrançois Tigeot 		if (gtt_offset == MI_SEMAPHORE_SYNC_INVALID)
126924edb884SFrançois Tigeot 			continue;
127024edb884SFrançois Tigeot 
127171f41f3eSFrançois Tigeot 		intel_ring_emit(ring,
127271f41f3eSFrançois Tigeot 				(MI_FLUSH_DW + 1) | MI_FLUSH_DW_OP_STOREDW);
127371f41f3eSFrançois Tigeot 		intel_ring_emit(ring,
127471f41f3eSFrançois Tigeot 				lower_32_bits(gtt_offset) |
127524edb884SFrançois Tigeot 				MI_FLUSH_DW_USE_GTT);
127671f41f3eSFrançois Tigeot 		intel_ring_emit(ring, upper_32_bits(gtt_offset));
127771f41f3eSFrançois Tigeot 		intel_ring_emit(ring, req->fence.seqno);
127871f41f3eSFrançois Tigeot 		intel_ring_emit(ring,
127971f41f3eSFrançois Tigeot 				MI_SEMAPHORE_SIGNAL |
12808621f407SFrançois Tigeot 				MI_SEMAPHORE_TARGET(waiter->hw_id));
128171f41f3eSFrançois Tigeot 		intel_ring_emit(ring, 0);
128224edb884SFrançois Tigeot 	}
128371f41f3eSFrançois Tigeot 	intel_ring_advance(ring);
128424edb884SFrançois Tigeot 
128524edb884SFrançois Tigeot 	return 0;
128624edb884SFrançois Tigeot }
128724edb884SFrançois Tigeot 
128871f41f3eSFrançois Tigeot static int gen6_signal(struct drm_i915_gem_request *req)
1289e3adcf8fSFrançois Tigeot {
129071f41f3eSFrançois Tigeot 	struct intel_ring *ring = req->ring;
129171f41f3eSFrançois Tigeot 	struct drm_i915_private *dev_priv = req->i915;
1292*1e12ee3bSFrançois Tigeot 	struct intel_engine_cs *engine;
12938621f407SFrançois Tigeot 	enum intel_engine_id id;
12948621f407SFrançois Tigeot 	int ret, num_rings;
1295ba55f2f5SFrançois Tigeot 
1296*1e12ee3bSFrançois Tigeot 	num_rings = INTEL_INFO(dev_priv)->num_rings;
129771f41f3eSFrançois Tigeot 	ret = intel_ring_begin(req, round_up((num_rings-1) * 3, 2));
1298ba55f2f5SFrançois Tigeot 	if (ret)
1299ba55f2f5SFrançois Tigeot 		return ret;
1300ba55f2f5SFrançois Tigeot 
1301*1e12ee3bSFrançois Tigeot 	for_each_engine(engine, dev_priv, id) {
1302*1e12ee3bSFrançois Tigeot 		i915_reg_t mbox_reg;
1303aee94f86SFrançois Tigeot 
1304*1e12ee3bSFrançois Tigeot 		if (!(BIT(engine->hw_id) & GEN6_SEMAPHORES_MASK))
1305*1e12ee3bSFrançois Tigeot 			continue;
1306*1e12ee3bSFrançois Tigeot 
1307*1e12ee3bSFrançois Tigeot 		mbox_reg = req->engine->semaphore.mbox.signal[engine->hw_id];
1308aee94f86SFrançois Tigeot 		if (i915_mmio_reg_valid(mbox_reg)) {
130971f41f3eSFrançois Tigeot 			intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1));
131071f41f3eSFrançois Tigeot 			intel_ring_emit_reg(ring, mbox_reg);
131171f41f3eSFrançois Tigeot 			intel_ring_emit(ring, req->fence.seqno);
1312ba55f2f5SFrançois Tigeot 		}
1313ba55f2f5SFrançois Tigeot 	}
1314ba55f2f5SFrançois Tigeot 
131524edb884SFrançois Tigeot 	/* If num_dwords was rounded, make sure the tail pointer is correct */
131624edb884SFrançois Tigeot 	if (num_rings % 2 == 0)
131771f41f3eSFrançois Tigeot 		intel_ring_emit(ring, MI_NOOP);
131871f41f3eSFrançois Tigeot 	intel_ring_advance(ring);
131971f41f3eSFrançois Tigeot 
132071f41f3eSFrançois Tigeot 	return 0;
132171f41f3eSFrançois Tigeot }
132271f41f3eSFrançois Tigeot 
132371f41f3eSFrançois Tigeot static void i9xx_submit_request(struct drm_i915_gem_request *request)
132471f41f3eSFrançois Tigeot {
132571f41f3eSFrançois Tigeot 	struct drm_i915_private *dev_priv = request->i915;
132671f41f3eSFrançois Tigeot 
132771f41f3eSFrançois Tigeot 	I915_WRITE_TAIL(request->engine,
132871f41f3eSFrançois Tigeot 			intel_ring_offset(request->ring, request->tail));
132971f41f3eSFrançois Tigeot }
133071f41f3eSFrançois Tigeot 
133171f41f3eSFrançois Tigeot static int i9xx_emit_request(struct drm_i915_gem_request *req)
133271f41f3eSFrançois Tigeot {
133371f41f3eSFrançois Tigeot 	struct intel_ring *ring = req->ring;
133471f41f3eSFrançois Tigeot 	int ret;
133571f41f3eSFrançois Tigeot 
133671f41f3eSFrançois Tigeot 	ret = intel_ring_begin(req, 4);
133771f41f3eSFrançois Tigeot 	if (ret)
133871f41f3eSFrançois Tigeot 		return ret;
133971f41f3eSFrançois Tigeot 
134071f41f3eSFrançois Tigeot 	intel_ring_emit(ring, MI_STORE_DWORD_INDEX);
134171f41f3eSFrançois Tigeot 	intel_ring_emit(ring, I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT);
134271f41f3eSFrançois Tigeot 	intel_ring_emit(ring, req->fence.seqno);
134371f41f3eSFrançois Tigeot 	intel_ring_emit(ring, MI_USER_INTERRUPT);
134471f41f3eSFrançois Tigeot 	intel_ring_advance(ring);
134571f41f3eSFrançois Tigeot 
134671f41f3eSFrançois Tigeot 	req->tail = ring->tail;
134724edb884SFrançois Tigeot 
1348ba55f2f5SFrançois Tigeot 	return 0;
1349e3adcf8fSFrançois Tigeot }
1350e3adcf8fSFrançois Tigeot 
1351e3adcf8fSFrançois Tigeot /**
135271f41f3eSFrançois Tigeot  * gen6_sema_emit_request - Update the semaphore mailbox registers
1353e3adcf8fSFrançois Tigeot  *
1354a05eeebfSFrançois Tigeot  * @request - request to write to the ring
1355e3adcf8fSFrançois Tigeot  *
1356e3adcf8fSFrançois Tigeot  * Update the mailbox registers in the *other* rings with the current seqno.
1357e3adcf8fSFrançois Tigeot  * This acts like a signal in the canonical semaphore.
1358e3adcf8fSFrançois Tigeot  */
135971f41f3eSFrançois Tigeot static int gen6_sema_emit_request(struct drm_i915_gem_request *req)
1360e3adcf8fSFrançois Tigeot {
1361ba55f2f5SFrançois Tigeot 	int ret;
1362e3adcf8fSFrançois Tigeot 
136371f41f3eSFrançois Tigeot 	ret = req->engine->semaphore.signal(req);
13649edbd4a0SFrançois Tigeot 	if (ret)
13659edbd4a0SFrançois Tigeot 		return ret;
13669edbd4a0SFrançois Tigeot 
136771f41f3eSFrançois Tigeot 	return i9xx_emit_request(req);
1368e3adcf8fSFrançois Tigeot }
1369e3adcf8fSFrançois Tigeot 
137071f41f3eSFrançois Tigeot static int gen8_render_emit_request(struct drm_i915_gem_request *req)
13711487f786SFrançois Tigeot {
13721487f786SFrançois Tigeot 	struct intel_engine_cs *engine = req->engine;
137371f41f3eSFrançois Tigeot 	struct intel_ring *ring = req->ring;
13741487f786SFrançois Tigeot 	int ret;
13751487f786SFrançois Tigeot 
137671f41f3eSFrançois Tigeot 	if (engine->semaphore.signal) {
137771f41f3eSFrançois Tigeot 		ret = engine->semaphore.signal(req);
137871f41f3eSFrançois Tigeot 		if (ret)
137971f41f3eSFrançois Tigeot 			return ret;
138071f41f3eSFrançois Tigeot 	}
138171f41f3eSFrançois Tigeot 
13821487f786SFrançois Tigeot 	ret = intel_ring_begin(req, 8);
13831487f786SFrançois Tigeot 	if (ret)
13841487f786SFrançois Tigeot 		return ret;
13851487f786SFrançois Tigeot 
138671f41f3eSFrançois Tigeot 	intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(6));
138771f41f3eSFrançois Tigeot 	intel_ring_emit(ring, (PIPE_CONTROL_GLOBAL_GTT_IVB |
13881487f786SFrançois Tigeot 			       PIPE_CONTROL_CS_STALL |
13891487f786SFrançois Tigeot 			       PIPE_CONTROL_QW_WRITE));
139071f41f3eSFrançois Tigeot 	intel_ring_emit(ring, intel_hws_seqno_address(engine));
139171f41f3eSFrançois Tigeot 	intel_ring_emit(ring, 0);
139271f41f3eSFrançois Tigeot 	intel_ring_emit(ring, i915_gem_request_get_seqno(req));
13931487f786SFrançois Tigeot 	/* We're thrashing one dword of HWS. */
139471f41f3eSFrançois Tigeot 	intel_ring_emit(ring, 0);
139571f41f3eSFrançois Tigeot 	intel_ring_emit(ring, MI_USER_INTERRUPT);
139671f41f3eSFrançois Tigeot 	intel_ring_emit(ring, MI_NOOP);
139771f41f3eSFrançois Tigeot 	intel_ring_advance(ring);
139871f41f3eSFrançois Tigeot 
139971f41f3eSFrançois Tigeot 	req->tail = ring->tail;
14001487f786SFrançois Tigeot 
14011487f786SFrançois Tigeot 	return 0;
14021487f786SFrançois Tigeot }
14031487f786SFrançois Tigeot 
1404e3adcf8fSFrançois Tigeot /**
1405e3adcf8fSFrançois Tigeot  * intel_ring_sync - sync the waiter to the signaller on seqno
1406e3adcf8fSFrançois Tigeot  *
1407e3adcf8fSFrançois Tigeot  * @waiter - ring that is waiting
1408e3adcf8fSFrançois Tigeot  * @signaller - ring which has, or will signal
1409e3adcf8fSFrançois Tigeot  * @seqno - seqno which the waiter will block on
1410e3adcf8fSFrançois Tigeot  */
141124edb884SFrançois Tigeot 
141224edb884SFrançois Tigeot static int
141371f41f3eSFrançois Tigeot gen8_ring_sync_to(struct drm_i915_gem_request *req,
141471f41f3eSFrançois Tigeot 		  struct drm_i915_gem_request *signal)
141524edb884SFrançois Tigeot {
141671f41f3eSFrançois Tigeot 	struct intel_ring *ring = req->ring;
141771f41f3eSFrançois Tigeot 	struct drm_i915_private *dev_priv = req->i915;
141871f41f3eSFrançois Tigeot 	u64 offset = GEN8_WAIT_OFFSET(req->engine, signal->engine->id);
14191487f786SFrançois Tigeot 	struct i915_hw_ppgtt *ppgtt;
142024edb884SFrançois Tigeot 	int ret;
142124edb884SFrançois Tigeot 
142271f41f3eSFrançois Tigeot 	ret = intel_ring_begin(req, 4);
142324edb884SFrançois Tigeot 	if (ret)
142424edb884SFrançois Tigeot 		return ret;
142524edb884SFrançois Tigeot 
142671f41f3eSFrançois Tigeot 	intel_ring_emit(ring,
142771f41f3eSFrançois Tigeot 			MI_SEMAPHORE_WAIT |
142824edb884SFrançois Tigeot 			MI_SEMAPHORE_GLOBAL_GTT |
142924edb884SFrançois Tigeot 			MI_SEMAPHORE_SAD_GTE_SDD);
143071f41f3eSFrançois Tigeot 	intel_ring_emit(ring, signal->fence.seqno);
143171f41f3eSFrançois Tigeot 	intel_ring_emit(ring, lower_32_bits(offset));
143271f41f3eSFrançois Tigeot 	intel_ring_emit(ring, upper_32_bits(offset));
143371f41f3eSFrançois Tigeot 	intel_ring_advance(ring);
14341487f786SFrançois Tigeot 
14351487f786SFrançois Tigeot 	/* When the !RCS engines idle waiting upon a semaphore, they lose their
14361487f786SFrançois Tigeot 	 * pagetables and we must reload them before executing the batch.
14371487f786SFrançois Tigeot 	 * We do this on the i915_switch_context() following the wait and
14381487f786SFrançois Tigeot 	 * before the dispatch.
14391487f786SFrançois Tigeot 	 */
144071f41f3eSFrançois Tigeot 	ppgtt = req->ctx->ppgtt;
144171f41f3eSFrançois Tigeot 	if (ppgtt && req->engine->id != RCS)
144271f41f3eSFrançois Tigeot 		ppgtt->pd_dirty_rings |= intel_engine_flag(req->engine);
144324edb884SFrançois Tigeot 	return 0;
144424edb884SFrançois Tigeot }
144524edb884SFrançois Tigeot 
1446e3adcf8fSFrançois Tigeot static int
144771f41f3eSFrançois Tigeot gen6_ring_sync_to(struct drm_i915_gem_request *req,
144871f41f3eSFrançois Tigeot 		  struct drm_i915_gem_request *signal)
1449e3adcf8fSFrançois Tigeot {
145071f41f3eSFrançois Tigeot 	struct intel_ring *ring = req->ring;
1451e3adcf8fSFrançois Tigeot 	u32 dw1 = MI_SEMAPHORE_MBOX |
1452e3adcf8fSFrançois Tigeot 		  MI_SEMAPHORE_COMPARE |
1453e3adcf8fSFrançois Tigeot 		  MI_SEMAPHORE_REGISTER;
1454*1e12ee3bSFrançois Tigeot 	u32 wait_mbox = signal->engine->semaphore.mbox.wait[req->engine->hw_id];
1455ba55f2f5SFrançois Tigeot 	int ret;
1456e3adcf8fSFrançois Tigeot 
145771f41f3eSFrançois Tigeot 	WARN_ON(wait_mbox == MI_SEMAPHORE_SYNC_INVALID);
145871f41f3eSFrançois Tigeot 
145971f41f3eSFrançois Tigeot 	ret = intel_ring_begin(req, 4);
146071f41f3eSFrançois Tigeot 	if (ret)
146171f41f3eSFrançois Tigeot 		return ret;
146271f41f3eSFrançois Tigeot 
146371f41f3eSFrançois Tigeot 	intel_ring_emit(ring, dw1 | wait_mbox);
1464686a02f1SFrançois Tigeot 	/* Throughout all of the GEM code, seqno passed implies our current
1465686a02f1SFrançois Tigeot 	 * seqno is >= the last seqno executed. However for hardware the
1466686a02f1SFrançois Tigeot 	 * comparison is strictly greater than.
1467686a02f1SFrançois Tigeot 	 */
146871f41f3eSFrançois Tigeot 	intel_ring_emit(ring, signal->fence.seqno - 1);
146971f41f3eSFrançois Tigeot 	intel_ring_emit(ring, 0);
147071f41f3eSFrançois Tigeot 	intel_ring_emit(ring, MI_NOOP);
147171f41f3eSFrançois Tigeot 	intel_ring_advance(ring);
1472e3adcf8fSFrançois Tigeot 
1473e3adcf8fSFrançois Tigeot 	return 0;
1474e3adcf8fSFrançois Tigeot }
1475e3adcf8fSFrançois Tigeot 
1476303bf270SFrançois Tigeot static void
147787df8fc6SFrançois Tigeot gen5_seqno_barrier(struct intel_engine_cs *engine)
1478e3adcf8fSFrançois Tigeot {
1479303bf270SFrançois Tigeot 	/* MI_STORE are internally buffered by the GPU and not flushed
1480303bf270SFrançois Tigeot 	 * either by MI_FLUSH or SyncFlush or any other combination of
1481303bf270SFrançois Tigeot 	 * MI commands.
1482e3adcf8fSFrançois Tigeot 	 *
1483303bf270SFrançois Tigeot 	 * "Only the submission of the store operation is guaranteed.
1484303bf270SFrançois Tigeot 	 * The write result will be complete (coherent) some time later
1485303bf270SFrançois Tigeot 	 * (this is practically a finite period but there is no guaranteed
1486303bf270SFrançois Tigeot 	 * latency)."
1487303bf270SFrançois Tigeot 	 *
1488303bf270SFrançois Tigeot 	 * Empirically, we observe that we need a delay of at least 75us to
1489303bf270SFrançois Tigeot 	 * be sure that the seqno write is visible by the CPU.
1490e3adcf8fSFrançois Tigeot 	 */
1491303bf270SFrançois Tigeot 	usleep_range(125, 250);
1492e3adcf8fSFrançois Tigeot }
1493e3adcf8fSFrançois Tigeot 
14948621f407SFrançois Tigeot static void
14958621f407SFrançois Tigeot gen6_seqno_barrier(struct intel_engine_cs *engine)
1496e3adcf8fSFrançois Tigeot {
14971487f786SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
14988621f407SFrançois Tigeot 
1499e3adcf8fSFrançois Tigeot 	/* Workaround to force correct ordering between irq and seqno writes on
1500e3adcf8fSFrançois Tigeot 	 * ivb (and maybe also on snb) by reading from a CS register (like
15018621f407SFrançois Tigeot 	 * ACTHD) before reading the status page.
15028621f407SFrançois Tigeot 	 *
15038621f407SFrançois Tigeot 	 * Note that this effectively stalls the read by the time it takes to
15048621f407SFrançois Tigeot 	 * do a memory transaction, which more or less ensures that the write
15058621f407SFrançois Tigeot 	 * from the GPU has sufficient time to invalidate the CPU cacheline.
15068621f407SFrançois Tigeot 	 * Alternatively we could delay the interrupt from the CS ring to give
15078621f407SFrançois Tigeot 	 * the write time to land, but that would incur a delay after every
15088621f407SFrançois Tigeot 	 * batch i.e. much more frequent than a delay when waiting for the
15098621f407SFrançois Tigeot 	 * interrupt (with the same net latency).
15108621f407SFrançois Tigeot 	 *
15118621f407SFrançois Tigeot 	 * Also note that to prevent whole machine hangs on gen7, we have to
15128621f407SFrançois Tigeot 	 * take the spinlock to guard against concurrent cacheline access.
15138621f407SFrançois Tigeot 	 */
15148621f407SFrançois Tigeot 	spin_lock_irq(&dev_priv->uncore.lock);
15158621f407SFrançois Tigeot 	POSTING_READ_FW(RING_ACTHD(engine->mmio_base));
15168621f407SFrançois Tigeot 	spin_unlock_irq(&dev_priv->uncore.lock);
1517e3adcf8fSFrançois Tigeot }
1518e3adcf8fSFrançois Tigeot 
1519303bf270SFrançois Tigeot static void
1520303bf270SFrançois Tigeot gen5_irq_enable(struct intel_engine_cs *engine)
1521e3adcf8fSFrançois Tigeot {
1522303bf270SFrançois Tigeot 	gen5_enable_gt_irq(engine->i915, engine->irq_enable_mask);
1523e3adcf8fSFrançois Tigeot }
1524e3adcf8fSFrançois Tigeot 
1525a2fdbec6SFrançois Tigeot static void
1526303bf270SFrançois Tigeot gen5_irq_disable(struct intel_engine_cs *engine)
1527a2fdbec6SFrançois Tigeot {
1528303bf270SFrançois Tigeot 	gen5_disable_gt_irq(engine->i915, engine->irq_enable_mask);
1529e3adcf8fSFrançois Tigeot }
1530e3adcf8fSFrançois Tigeot 
1531a2fdbec6SFrançois Tigeot static void
1532303bf270SFrançois Tigeot i9xx_irq_enable(struct intel_engine_cs *engine)
1533e3adcf8fSFrançois Tigeot {
15341487f786SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
1535e3adcf8fSFrançois Tigeot 
15368621f407SFrançois Tigeot 	dev_priv->irq_mask &= ~engine->irq_enable_mask;
1537686a02f1SFrançois Tigeot 	I915_WRITE(IMR, dev_priv->irq_mask);
1538303bf270SFrançois Tigeot 	POSTING_READ_FW(RING_IMR(engine->mmio_base));
1539686a02f1SFrançois Tigeot }
1540686a02f1SFrançois Tigeot 
1541686a02f1SFrançois Tigeot static void
1542303bf270SFrançois Tigeot i9xx_irq_disable(struct intel_engine_cs *engine)
1543686a02f1SFrançois Tigeot {
15441487f786SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
1545686a02f1SFrançois Tigeot 
15468621f407SFrançois Tigeot 	dev_priv->irq_mask |= engine->irq_enable_mask;
1547686a02f1SFrançois Tigeot 	I915_WRITE(IMR, dev_priv->irq_mask);
1548686a02f1SFrançois Tigeot }
1549686a02f1SFrançois Tigeot 
1550686a02f1SFrançois Tigeot static void
1551303bf270SFrançois Tigeot i8xx_irq_enable(struct intel_engine_cs *engine)
1552686a02f1SFrançois Tigeot {
15531487f786SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
1554686a02f1SFrançois Tigeot 
1555303bf270SFrançois Tigeot 	dev_priv->irq_mask &= ~engine->irq_enable_mask;
1556303bf270SFrançois Tigeot 	I915_WRITE16(IMR, dev_priv->irq_mask);
1557303bf270SFrançois Tigeot 	POSTING_READ16(RING_IMR(engine->mmio_base));
1558303bf270SFrançois Tigeot }
1559303bf270SFrançois Tigeot 
1560303bf270SFrançois Tigeot static void
1561303bf270SFrançois Tigeot i8xx_irq_disable(struct intel_engine_cs *engine)
1562303bf270SFrançois Tigeot {
1563303bf270SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
1564303bf270SFrançois Tigeot 
15658621f407SFrançois Tigeot 	dev_priv->irq_mask |= engine->irq_enable_mask;
1566686a02f1SFrançois Tigeot 	I915_WRITE16(IMR, dev_priv->irq_mask);
1567e3adcf8fSFrançois Tigeot }
1568e3adcf8fSFrançois Tigeot 
1569e3adcf8fSFrançois Tigeot static int
157071f41f3eSFrançois Tigeot bsd_ring_flush(struct drm_i915_gem_request *req, u32 mode)
1571e3adcf8fSFrançois Tigeot {
157271f41f3eSFrançois Tigeot 	struct intel_ring *ring = req->ring;
1573e3adcf8fSFrançois Tigeot 	int ret;
1574e3adcf8fSFrançois Tigeot 
1575a05eeebfSFrançois Tigeot 	ret = intel_ring_begin(req, 2);
1576e3adcf8fSFrançois Tigeot 	if (ret)
1577e3adcf8fSFrançois Tigeot 		return ret;
1578e3adcf8fSFrançois Tigeot 
157971f41f3eSFrançois Tigeot 	intel_ring_emit(ring, MI_FLUSH);
158071f41f3eSFrançois Tigeot 	intel_ring_emit(ring, MI_NOOP);
158171f41f3eSFrançois Tigeot 	intel_ring_advance(ring);
1582e3adcf8fSFrançois Tigeot 	return 0;
1583e3adcf8fSFrançois Tigeot }
1584e3adcf8fSFrançois Tigeot 
1585303bf270SFrançois Tigeot static void
1586303bf270SFrançois Tigeot gen6_irq_enable(struct intel_engine_cs *engine)
1587e3adcf8fSFrançois Tigeot {
15881487f786SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
1589e3adcf8fSFrançois Tigeot 
15908621f407SFrançois Tigeot 	I915_WRITE_IMR(engine,
15918621f407SFrançois Tigeot 		       ~(engine->irq_enable_mask |
1592303bf270SFrançois Tigeot 			 engine->irq_keep_mask));
15938621f407SFrançois Tigeot 	gen5_enable_gt_irq(dev_priv, engine->irq_enable_mask);
1594e3adcf8fSFrançois Tigeot }
1595e3adcf8fSFrançois Tigeot 
1596e3adcf8fSFrançois Tigeot static void
1597303bf270SFrançois Tigeot gen6_irq_disable(struct intel_engine_cs *engine)
1598e3adcf8fSFrançois Tigeot {
15991487f786SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
1600e3adcf8fSFrançois Tigeot 
1601303bf270SFrançois Tigeot 	I915_WRITE_IMR(engine, ~engine->irq_keep_mask);
16028621f407SFrançois Tigeot 	gen5_disable_gt_irq(dev_priv, engine->irq_enable_mask);
1603e3adcf8fSFrançois Tigeot }
1604e3adcf8fSFrançois Tigeot 
1605303bf270SFrançois Tigeot static void
1606303bf270SFrançois Tigeot hsw_vebox_irq_enable(struct intel_engine_cs *engine)
16075d0b1887SFrançois Tigeot {
16081487f786SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
16095d0b1887SFrançois Tigeot 
16108621f407SFrançois Tigeot 	I915_WRITE_IMR(engine, ~engine->irq_enable_mask);
16118621f407SFrançois Tigeot 	gen6_enable_pm_irq(dev_priv, engine->irq_enable_mask);
16125d0b1887SFrançois Tigeot }
16135d0b1887SFrançois Tigeot 
16145d0b1887SFrançois Tigeot static void
1615303bf270SFrançois Tigeot hsw_vebox_irq_disable(struct intel_engine_cs *engine)
16165d0b1887SFrançois Tigeot {
16171487f786SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
16185d0b1887SFrançois Tigeot 
16198621f407SFrançois Tigeot 	I915_WRITE_IMR(engine, ~0);
16208621f407SFrançois Tigeot 	gen6_disable_pm_irq(dev_priv, engine->irq_enable_mask);
16215d0b1887SFrançois Tigeot }
16229edbd4a0SFrançois Tigeot 
1623303bf270SFrançois Tigeot static void
1624303bf270SFrançois Tigeot gen8_irq_enable(struct intel_engine_cs *engine)
16259edbd4a0SFrançois Tigeot {
16261487f786SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
16279edbd4a0SFrançois Tigeot 
16288621f407SFrançois Tigeot 	I915_WRITE_IMR(engine,
16298621f407SFrançois Tigeot 		       ~(engine->irq_enable_mask |
1630303bf270SFrançois Tigeot 			 engine->irq_keep_mask));
1631303bf270SFrançois Tigeot 	POSTING_READ_FW(RING_IMR(engine->mmio_base));
16329edbd4a0SFrançois Tigeot }
16339edbd4a0SFrançois Tigeot 
16349edbd4a0SFrançois Tigeot static void
1635303bf270SFrançois Tigeot gen8_irq_disable(struct intel_engine_cs *engine)
16369edbd4a0SFrançois Tigeot {
16371487f786SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
16389edbd4a0SFrançois Tigeot 
1639303bf270SFrançois Tigeot 	I915_WRITE_IMR(engine, ~engine->irq_keep_mask);
16405d0b1887SFrançois Tigeot }
16415d0b1887SFrançois Tigeot 
1642e3adcf8fSFrançois Tigeot static int
164371f41f3eSFrançois Tigeot i965_emit_bb_start(struct drm_i915_gem_request *req,
1644ba55f2f5SFrançois Tigeot 		   u64 offset, u32 length,
164571f41f3eSFrançois Tigeot 		   unsigned int dispatch_flags)
1646e3adcf8fSFrançois Tigeot {
164771f41f3eSFrançois Tigeot 	struct intel_ring *ring = req->ring;
1648e3adcf8fSFrançois Tigeot 	int ret;
1649e3adcf8fSFrançois Tigeot 
1650a05eeebfSFrançois Tigeot 	ret = intel_ring_begin(req, 2);
1651e3adcf8fSFrançois Tigeot 	if (ret)
1652e3adcf8fSFrançois Tigeot 		return ret;
1653e3adcf8fSFrançois Tigeot 
165471f41f3eSFrançois Tigeot 	intel_ring_emit(ring,
1655686a02f1SFrançois Tigeot 			MI_BATCH_BUFFER_START |
1656b5c29a34SFrançois Tigeot 			MI_BATCH_GTT |
1657477eb7f9SFrançois Tigeot 			(dispatch_flags & I915_DISPATCH_SECURE ?
1658477eb7f9SFrançois Tigeot 			 0 : MI_BATCH_NON_SECURE_I965));
165971f41f3eSFrançois Tigeot 	intel_ring_emit(ring, offset);
166071f41f3eSFrançois Tigeot 	intel_ring_advance(ring);
1661e3adcf8fSFrançois Tigeot 
1662e3adcf8fSFrançois Tigeot 	return 0;
1663e3adcf8fSFrançois Tigeot }
1664e3adcf8fSFrançois Tigeot 
1665b5c29a34SFrançois Tigeot /* Just userspace ABI convention to limit the wa batch bo to a resonable size */
1666b5c29a34SFrançois Tigeot #define I830_BATCH_LIMIT (256*1024)
166724edb884SFrançois Tigeot #define I830_TLB_ENTRIES (2)
166824edb884SFrançois Tigeot #define I830_WA_SIZE max(I830_TLB_ENTRIES*4096, I830_BATCH_LIMIT)
1669e3adcf8fSFrançois Tigeot static int
167071f41f3eSFrançois Tigeot i830_emit_bb_start(struct drm_i915_gem_request *req,
1671ba55f2f5SFrançois Tigeot 		   u64 offset, u32 len,
167271f41f3eSFrançois Tigeot 		   unsigned int dispatch_flags)
1673e3adcf8fSFrançois Tigeot {
167471f41f3eSFrançois Tigeot 	struct intel_ring *ring = req->ring;
1675*1e12ee3bSFrançois Tigeot 	u32 cs_offset = i915_ggtt_offset(req->engine->scratch);
1676e3adcf8fSFrançois Tigeot 	int ret;
1677e3adcf8fSFrançois Tigeot 
1678a05eeebfSFrançois Tigeot 	ret = intel_ring_begin(req, 6);
167924edb884SFrançois Tigeot 	if (ret)
168024edb884SFrançois Tigeot 		return ret;
168124edb884SFrançois Tigeot 
168224edb884SFrançois Tigeot 	/* Evict the invalid PTE TLBs */
168371f41f3eSFrançois Tigeot 	intel_ring_emit(ring, COLOR_BLT_CMD | BLT_WRITE_RGBA);
168471f41f3eSFrançois Tigeot 	intel_ring_emit(ring, BLT_DEPTH_32 | BLT_ROP_COLOR_COPY | 4096);
168571f41f3eSFrançois Tigeot 	intel_ring_emit(ring, I830_TLB_ENTRIES << 16 | 4); /* load each page */
168671f41f3eSFrançois Tigeot 	intel_ring_emit(ring, cs_offset);
168771f41f3eSFrançois Tigeot 	intel_ring_emit(ring, 0xdeadbeef);
168871f41f3eSFrançois Tigeot 	intel_ring_emit(ring, MI_NOOP);
168971f41f3eSFrançois Tigeot 	intel_ring_advance(ring);
169024edb884SFrançois Tigeot 
1691477eb7f9SFrançois Tigeot 	if ((dispatch_flags & I915_DISPATCH_PINNED) == 0) {
169224edb884SFrançois Tigeot 		if (len > I830_BATCH_LIMIT)
169324edb884SFrançois Tigeot 			return -ENOSPC;
169424edb884SFrançois Tigeot 
1695a05eeebfSFrançois Tigeot 		ret = intel_ring_begin(req, 6 + 2);
169624edb884SFrançois Tigeot 		if (ret)
169724edb884SFrançois Tigeot 			return ret;
169824edb884SFrançois Tigeot 
169924edb884SFrançois Tigeot 		/* Blit the batch (which has now all relocs applied) to the
170024edb884SFrançois Tigeot 		 * stable batch scratch bo area (so that the CS never
170124edb884SFrançois Tigeot 		 * stumbles over its tlb invalidation bug) ...
170224edb884SFrançois Tigeot 		 */
170371f41f3eSFrançois Tigeot 		intel_ring_emit(ring, SRC_COPY_BLT_CMD | BLT_WRITE_RGBA);
170471f41f3eSFrançois Tigeot 		intel_ring_emit(ring,
17058621f407SFrançois Tigeot 				BLT_DEPTH_32 | BLT_ROP_SRC_COPY | 4096);
170671f41f3eSFrançois Tigeot 		intel_ring_emit(ring, DIV_ROUND_UP(len, 4096) << 16 | 4096);
170771f41f3eSFrançois Tigeot 		intel_ring_emit(ring, cs_offset);
170871f41f3eSFrançois Tigeot 		intel_ring_emit(ring, 4096);
170971f41f3eSFrançois Tigeot 		intel_ring_emit(ring, offset);
171024edb884SFrançois Tigeot 
171171f41f3eSFrançois Tigeot 		intel_ring_emit(ring, MI_FLUSH);
171271f41f3eSFrançois Tigeot 		intel_ring_emit(ring, MI_NOOP);
171371f41f3eSFrançois Tigeot 		intel_ring_advance(ring);
171424edb884SFrançois Tigeot 
171524edb884SFrançois Tigeot 		/* ... and execute it. */
171624edb884SFrançois Tigeot 		offset = cs_offset;
171724edb884SFrançois Tigeot 	}
171824edb884SFrançois Tigeot 
1719c0e85e96SFrançois Tigeot 	ret = intel_ring_begin(req, 2);
1720e3adcf8fSFrançois Tigeot 	if (ret)
1721e3adcf8fSFrançois Tigeot 		return ret;
1722e3adcf8fSFrançois Tigeot 
172371f41f3eSFrançois Tigeot 	intel_ring_emit(ring, MI_BATCH_BUFFER_START | MI_BATCH_GTT);
172471f41f3eSFrançois Tigeot 	intel_ring_emit(ring, offset | (dispatch_flags & I915_DISPATCH_SECURE ?
1725477eb7f9SFrançois Tigeot 					0 : MI_BATCH_NON_SECURE));
172671f41f3eSFrançois Tigeot 	intel_ring_advance(ring);
1727686a02f1SFrançois Tigeot 
1728686a02f1SFrançois Tigeot 	return 0;
1729686a02f1SFrançois Tigeot }
1730686a02f1SFrançois Tigeot 
1731686a02f1SFrançois Tigeot static int
173271f41f3eSFrançois Tigeot i915_emit_bb_start(struct drm_i915_gem_request *req,
1733ba55f2f5SFrançois Tigeot 		   u64 offset, u32 len,
173471f41f3eSFrançois Tigeot 		   unsigned int dispatch_flags)
1735686a02f1SFrançois Tigeot {
173671f41f3eSFrançois Tigeot 	struct intel_ring *ring = req->ring;
1737686a02f1SFrançois Tigeot 	int ret;
1738686a02f1SFrançois Tigeot 
1739a05eeebfSFrançois Tigeot 	ret = intel_ring_begin(req, 2);
1740e3adcf8fSFrançois Tigeot 	if (ret)
1741e3adcf8fSFrançois Tigeot 		return ret;
1742e3adcf8fSFrançois Tigeot 
174371f41f3eSFrançois Tigeot 	intel_ring_emit(ring, MI_BATCH_BUFFER_START | MI_BATCH_GTT);
174471f41f3eSFrançois Tigeot 	intel_ring_emit(ring, offset | (dispatch_flags & I915_DISPATCH_SECURE ?
1745477eb7f9SFrançois Tigeot 					0 : MI_BATCH_NON_SECURE));
174671f41f3eSFrançois Tigeot 	intel_ring_advance(ring);
1747e3adcf8fSFrançois Tigeot 
1748e3adcf8fSFrançois Tigeot 	return 0;
1749e3adcf8fSFrançois Tigeot }
1750e3adcf8fSFrançois Tigeot 
17518621f407SFrançois Tigeot static void cleanup_phys_status_page(struct intel_engine_cs *engine)
1752c0e85e96SFrançois Tigeot {
17531487f786SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
1754c0e85e96SFrançois Tigeot 
1755c0e85e96SFrançois Tigeot 	if (!dev_priv->status_page_dmah)
1756c0e85e96SFrançois Tigeot 		return;
1757c0e85e96SFrançois Tigeot 
1758303bf270SFrançois Tigeot 	drm_pci_free(&dev_priv->drm, dev_priv->status_page_dmah);
17598621f407SFrançois Tigeot 	engine->status_page.page_addr = NULL;
1760c0e85e96SFrançois Tigeot }
1761c0e85e96SFrançois Tigeot 
17628621f407SFrançois Tigeot static void cleanup_status_page(struct intel_engine_cs *engine)
1763e3adcf8fSFrançois Tigeot {
1764*1e12ee3bSFrançois Tigeot 	struct i915_vma *vma;
1765e3adcf8fSFrançois Tigeot 
1766*1e12ee3bSFrançois Tigeot 	vma = fetch_and_zero(&engine->status_page.vma);
1767*1e12ee3bSFrançois Tigeot 	if (!vma)
1768e3adcf8fSFrançois Tigeot 		return;
1769e3adcf8fSFrançois Tigeot 
1770*1e12ee3bSFrançois Tigeot 	i915_vma_unpin(vma);
1771*1e12ee3bSFrançois Tigeot 	i915_gem_object_unpin_map(vma->obj);
1772*1e12ee3bSFrançois Tigeot 	i915_vma_put(vma);
1773e3adcf8fSFrançois Tigeot }
1774e3adcf8fSFrançois Tigeot 
17758621f407SFrançois Tigeot static int init_status_page(struct intel_engine_cs *engine)
1776e3adcf8fSFrançois Tigeot {
1777*1e12ee3bSFrançois Tigeot 	struct drm_i915_gem_object *obj;
1778*1e12ee3bSFrançois Tigeot 	struct i915_vma *vma;
1779*1e12ee3bSFrançois Tigeot 	unsigned int flags;
1780e3adcf8fSFrançois Tigeot 	int ret;
1781e3adcf8fSFrançois Tigeot 
1782303bf270SFrançois Tigeot 	obj = i915_gem_object_create(&engine->i915->drm, 4096);
17831487f786SFrançois Tigeot 	if (IS_ERR(obj)) {
1784e3adcf8fSFrançois Tigeot 		DRM_ERROR("Failed to allocate status page\n");
17851487f786SFrançois Tigeot 		return PTR_ERR(obj);
1786e3adcf8fSFrançois Tigeot 	}
1787e3adcf8fSFrançois Tigeot 
1788ba55f2f5SFrançois Tigeot 	ret = i915_gem_object_set_cache_level(obj, I915_CACHE_LLC);
1789ba55f2f5SFrançois Tigeot 	if (ret)
1790*1e12ee3bSFrançois Tigeot 		goto err;
1791ba55f2f5SFrançois Tigeot 
1792*1e12ee3bSFrançois Tigeot 	vma = i915_vma_create(obj, &engine->i915->ggtt.base, NULL);
1793*1e12ee3bSFrançois Tigeot 	if (IS_ERR(vma)) {
1794*1e12ee3bSFrançois Tigeot 		ret = PTR_ERR(vma);
1795*1e12ee3bSFrançois Tigeot 		goto err;
1796*1e12ee3bSFrançois Tigeot 	}
1797*1e12ee3bSFrançois Tigeot 
1798*1e12ee3bSFrançois Tigeot 	flags = PIN_GLOBAL;
17991487f786SFrançois Tigeot 	if (!HAS_LLC(engine->i915))
180024edb884SFrançois Tigeot 		/* On g33, we cannot place HWS above 256MiB, so
180124edb884SFrançois Tigeot 		 * restrict its pinning to the low mappable arena.
180224edb884SFrançois Tigeot 		 * Though this restriction is not documented for
180324edb884SFrançois Tigeot 		 * gen4, gen5, or byt, they also behave similarly
180424edb884SFrançois Tigeot 		 * and hang if the HWS is placed at the top of the
180524edb884SFrançois Tigeot 		 * GTT. To generalise, it appears that all !llc
180624edb884SFrançois Tigeot 		 * platforms have issues with us placing the HWS
180724edb884SFrançois Tigeot 		 * above the mappable region (even though we never
180824edb884SFrançois Tigeot 		 * actualy map it).
180924edb884SFrançois Tigeot 		 */
181024edb884SFrançois Tigeot 		flags |= PIN_MAPPABLE;
1811*1e12ee3bSFrançois Tigeot 	ret = i915_vma_pin(vma, 0, 4096, flags);
1812*1e12ee3bSFrançois Tigeot 	if (ret)
1813*1e12ee3bSFrançois Tigeot 		goto err;
1814ba55f2f5SFrançois Tigeot 
1815*1e12ee3bSFrançois Tigeot 	engine->status_page.vma = vma;
1816*1e12ee3bSFrançois Tigeot 	engine->status_page.ggtt_offset = i915_ggtt_offset(vma);
1817*1e12ee3bSFrançois Tigeot 	engine->status_page.page_addr =
1818*1e12ee3bSFrançois Tigeot 		i915_gem_object_pin_map(obj, I915_MAP_WB);
1819e3adcf8fSFrançois Tigeot 
1820b5c29a34SFrançois Tigeot 	DRM_DEBUG_DRIVER("%s hws offset: 0x%08x\n",
1821*1e12ee3bSFrançois Tigeot 			 engine->name, i915_ggtt_offset(vma));
1822e3adcf8fSFrançois Tigeot 	return 0;
1823*1e12ee3bSFrançois Tigeot 
1824*1e12ee3bSFrançois Tigeot err:
1825*1e12ee3bSFrançois Tigeot 	i915_gem_object_put(obj);
1826*1e12ee3bSFrançois Tigeot 	return ret;
1827e3adcf8fSFrançois Tigeot }
1828e3adcf8fSFrançois Tigeot 
18298621f407SFrançois Tigeot static int init_phys_status_page(struct intel_engine_cs *engine)
1830686a02f1SFrançois Tigeot {
18311487f786SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
1832686a02f1SFrançois Tigeot 
1833686a02f1SFrançois Tigeot 	dev_priv->status_page_dmah =
1834303bf270SFrançois Tigeot 		drm_pci_alloc(&dev_priv->drm, PAGE_SIZE, PAGE_SIZE);
1835686a02f1SFrançois Tigeot 	if (!dev_priv->status_page_dmah)
1836686a02f1SFrançois Tigeot 		return -ENOMEM;
1837686a02f1SFrançois Tigeot 
18388621f407SFrançois Tigeot 	engine->status_page.page_addr = dev_priv->status_page_dmah->vaddr;
18398621f407SFrançois Tigeot 	memset(engine->status_page.page_addr, 0, PAGE_SIZE);
1840686a02f1SFrançois Tigeot 
1841686a02f1SFrançois Tigeot 	return 0;
1842686a02f1SFrançois Tigeot }
1843686a02f1SFrançois Tigeot 
184471f41f3eSFrançois Tigeot int intel_ring_pin(struct intel_ring *ring)
18452c9916cdSFrançois Tigeot {
1846c0e85e96SFrançois Tigeot 	/* Ring wraparound at offset 0 sometimes hangs. No idea why. */
1847*1e12ee3bSFrançois Tigeot 	unsigned int flags = PIN_GLOBAL | PIN_OFFSET_BIAS | 4096;
1848*1e12ee3bSFrançois Tigeot 	enum i915_map_type map;
1849*1e12ee3bSFrançois Tigeot 	struct i915_vma *vma = ring->vma;
18508621f407SFrançois Tigeot 	void *addr;
18512c9916cdSFrançois Tigeot 	int ret;
18522c9916cdSFrançois Tigeot 
1853*1e12ee3bSFrançois Tigeot 	GEM_BUG_ON(ring->vaddr);
1854*1e12ee3bSFrançois Tigeot 
1855*1e12ee3bSFrançois Tigeot 	map = HAS_LLC(ring->engine->i915) ? I915_MAP_WB : I915_MAP_WC;
1856*1e12ee3bSFrançois Tigeot 
1857*1e12ee3bSFrançois Tigeot 	if (vma->obj->stolen)
1858*1e12ee3bSFrançois Tigeot 		flags |= PIN_MAPPABLE;
1859*1e12ee3bSFrançois Tigeot 
1860*1e12ee3bSFrançois Tigeot 	if (!(vma->flags & I915_VMA_GLOBAL_BIND)) {
1861*1e12ee3bSFrançois Tigeot 		if (flags & PIN_MAPPABLE || map == I915_MAP_WC)
1862*1e12ee3bSFrançois Tigeot 			ret = i915_gem_object_set_to_gtt_domain(vma->obj, true);
1863*1e12ee3bSFrançois Tigeot 		else
1864*1e12ee3bSFrançois Tigeot 			ret = i915_gem_object_set_to_cpu_domain(vma->obj, true);
1865*1e12ee3bSFrançois Tigeot 		if (unlikely(ret))
1866*1e12ee3bSFrançois Tigeot 			return ret;
1867*1e12ee3bSFrançois Tigeot 	}
1868*1e12ee3bSFrançois Tigeot 
1869*1e12ee3bSFrançois Tigeot 	ret = i915_vma_pin(vma, 0, PAGE_SIZE, flags);
1870*1e12ee3bSFrançois Tigeot 	if (unlikely(ret))
1871aee94f86SFrançois Tigeot 		return ret;
1872aee94f86SFrançois Tigeot 
1873*1e12ee3bSFrançois Tigeot 	if (i915_vma_is_map_and_fenceable(vma))
1874*1e12ee3bSFrançois Tigeot 		addr = (void __force *)i915_vma_pin_iomap(vma);
1875*1e12ee3bSFrançois Tigeot 	else
1876*1e12ee3bSFrançois Tigeot 		addr = i915_gem_object_pin_map(vma->obj, map);
1877*1e12ee3bSFrançois Tigeot 	if (IS_ERR(addr))
1878*1e12ee3bSFrançois Tigeot 		goto err;
18792c9916cdSFrançois Tigeot 
188071f41f3eSFrançois Tigeot 	ring->vaddr = addr;
18812c9916cdSFrançois Tigeot 	return 0;
18828621f407SFrançois Tigeot 
1883*1e12ee3bSFrançois Tigeot err:
1884*1e12ee3bSFrançois Tigeot 	i915_vma_unpin(vma);
1885*1e12ee3bSFrançois Tigeot 	return PTR_ERR(addr);
18862c9916cdSFrançois Tigeot }
18872c9916cdSFrançois Tigeot 
188871f41f3eSFrançois Tigeot void intel_ring_unpin(struct intel_ring *ring)
1889e3adcf8fSFrançois Tigeot {
189071f41f3eSFrançois Tigeot 	GEM_BUG_ON(!ring->vma);
189171f41f3eSFrançois Tigeot 	GEM_BUG_ON(!ring->vaddr);
189271f41f3eSFrançois Tigeot 
1893*1e12ee3bSFrançois Tigeot 	if (i915_vma_is_map_and_fenceable(ring->vma))
189471f41f3eSFrançois Tigeot 		i915_vma_unpin_iomap(ring->vma);
1895*1e12ee3bSFrançois Tigeot 	else
1896*1e12ee3bSFrançois Tigeot 		i915_gem_object_unpin_map(ring->vma->obj);
189771f41f3eSFrançois Tigeot 	ring->vaddr = NULL;
189871f41f3eSFrançois Tigeot 
1899*1e12ee3bSFrançois Tigeot 	i915_vma_unpin(ring->vma);
190071f41f3eSFrançois Tigeot }
190171f41f3eSFrançois Tigeot 
1902*1e12ee3bSFrançois Tigeot static struct i915_vma *
1903*1e12ee3bSFrançois Tigeot intel_ring_create_vma(struct drm_i915_private *dev_priv, int size)
190424edb884SFrançois Tigeot {
1905e3adcf8fSFrançois Tigeot 	struct drm_i915_gem_object *obj;
1906*1e12ee3bSFrançois Tigeot 	struct i915_vma *vma;
1907e3adcf8fSFrançois Tigeot 
1908*1e12ee3bSFrançois Tigeot 	obj = i915_gem_object_create_stolen(&dev_priv->drm, size);
1909*1e12ee3bSFrançois Tigeot 	if (!obj)
1910*1e12ee3bSFrançois Tigeot 		obj = i915_gem_object_create(&dev_priv->drm, size);
19111487f786SFrançois Tigeot 	if (IS_ERR(obj))
1912*1e12ee3bSFrançois Tigeot 		return ERR_CAST(obj);
1913e3adcf8fSFrançois Tigeot 
191424edb884SFrançois Tigeot 	/* mark ring buffers as read-only from GPU side by default */
191524edb884SFrançois Tigeot 	obj->gt_ro = 1;
191624edb884SFrançois Tigeot 
1917*1e12ee3bSFrançois Tigeot 	vma = i915_vma_create(obj, &dev_priv->ggtt.base, NULL);
1918*1e12ee3bSFrançois Tigeot 	if (IS_ERR(vma))
1919*1e12ee3bSFrançois Tigeot 		goto err;
1920ba55f2f5SFrançois Tigeot 
1921*1e12ee3bSFrançois Tigeot 	return vma;
1922*1e12ee3bSFrançois Tigeot 
1923*1e12ee3bSFrançois Tigeot err:
1924*1e12ee3bSFrançois Tigeot 	i915_gem_object_put(obj);
1925*1e12ee3bSFrançois Tigeot 	return vma;
1926ba55f2f5SFrançois Tigeot }
1927ba55f2f5SFrançois Tigeot 
192871f41f3eSFrançois Tigeot struct intel_ring *
192971f41f3eSFrançois Tigeot intel_engine_create_ring(struct intel_engine_cs *engine, int size)
1930352ff8bdSFrançois Tigeot {
193171f41f3eSFrançois Tigeot 	struct intel_ring *ring;
1932*1e12ee3bSFrançois Tigeot 	struct i915_vma *vma;
1933352ff8bdSFrançois Tigeot 
193471f41f3eSFrançois Tigeot 	GEM_BUG_ON(!is_power_of_2(size));
1935*1e12ee3bSFrançois Tigeot 	GEM_BUG_ON(RING_CTL_SIZE(size) & ~RING_NR_PAGES);
193671f41f3eSFrançois Tigeot 
1937352ff8bdSFrançois Tigeot 	ring = kzalloc(sizeof(*ring), GFP_KERNEL);
1938*1e12ee3bSFrançois Tigeot 	if (!ring)
1939352ff8bdSFrançois Tigeot 		return ERR_PTR(-ENOMEM);
1940352ff8bdSFrançois Tigeot 
19418621f407SFrançois Tigeot 	ring->engine = engine;
1942352ff8bdSFrançois Tigeot 
194371f41f3eSFrançois Tigeot 	INIT_LIST_HEAD(&ring->request_list);
194471f41f3eSFrançois Tigeot 
1945352ff8bdSFrançois Tigeot 	ring->size = size;
1946352ff8bdSFrançois Tigeot 	/* Workaround an erratum on the i830 which causes a hang if
1947352ff8bdSFrançois Tigeot 	 * the TAIL pointer points to within the last 2 cachelines
1948352ff8bdSFrançois Tigeot 	 * of the buffer.
1949352ff8bdSFrançois Tigeot 	 */
1950352ff8bdSFrançois Tigeot 	ring->effective_size = size;
19511487f786SFrançois Tigeot 	if (IS_I830(engine->i915) || IS_845G(engine->i915))
1952352ff8bdSFrançois Tigeot 		ring->effective_size -= 2 * CACHELINE_BYTES;
1953352ff8bdSFrançois Tigeot 
1954352ff8bdSFrançois Tigeot 	ring->last_retired_head = -1;
1955352ff8bdSFrançois Tigeot 	intel_ring_update_space(ring);
1956352ff8bdSFrançois Tigeot 
1957*1e12ee3bSFrançois Tigeot 	vma = intel_ring_create_vma(engine->i915, size);
1958*1e12ee3bSFrançois Tigeot 	if (IS_ERR(vma)) {
1959352ff8bdSFrançois Tigeot 		kfree(ring);
1960*1e12ee3bSFrançois Tigeot 		return ERR_CAST(vma);
1961352ff8bdSFrançois Tigeot 	}
1962*1e12ee3bSFrançois Tigeot 	ring->vma = vma;
1963352ff8bdSFrançois Tigeot 
1964352ff8bdSFrançois Tigeot 	return ring;
1965352ff8bdSFrançois Tigeot }
1966352ff8bdSFrançois Tigeot 
1967352ff8bdSFrançois Tigeot void
196871f41f3eSFrançois Tigeot intel_ring_free(struct intel_ring *ring)
1969352ff8bdSFrançois Tigeot {
1970*1e12ee3bSFrançois Tigeot 	i915_vma_put(ring->vma);
1971352ff8bdSFrançois Tigeot 	kfree(ring);
1972352ff8bdSFrançois Tigeot }
1973352ff8bdSFrançois Tigeot 
19741487f786SFrançois Tigeot static int intel_ring_context_pin(struct i915_gem_context *ctx,
19751487f786SFrançois Tigeot 				  struct intel_engine_cs *engine)
19761487f786SFrançois Tigeot {
19771487f786SFrançois Tigeot 	struct intel_context *ce = &ctx->engine[engine->id];
19781487f786SFrançois Tigeot 	int ret;
19791487f786SFrançois Tigeot 
1980303bf270SFrançois Tigeot 	lockdep_assert_held(&ctx->i915->drm.struct_mutex);
19811487f786SFrançois Tigeot 
19821487f786SFrançois Tigeot 	if (ce->pin_count++)
19831487f786SFrançois Tigeot 		return 0;
19841487f786SFrançois Tigeot 
19851487f786SFrançois Tigeot 	if (ce->state) {
1986*1e12ee3bSFrançois Tigeot 		ret = i915_gem_object_set_to_gtt_domain(ce->state->obj, false);
1987*1e12ee3bSFrançois Tigeot 		if (ret)
1988*1e12ee3bSFrançois Tigeot 			goto error;
1989*1e12ee3bSFrançois Tigeot 
1990*1e12ee3bSFrançois Tigeot 		ret = i915_vma_pin(ce->state, 0, ctx->ggtt_alignment,
1991*1e12ee3bSFrançois Tigeot 				   PIN_GLOBAL | PIN_HIGH);
19921487f786SFrançois Tigeot 		if (ret)
19931487f786SFrançois Tigeot 			goto error;
19941487f786SFrançois Tigeot 	}
19951487f786SFrançois Tigeot 
19961487f786SFrançois Tigeot 	/* The kernel context is only used as a placeholder for flushing the
19971487f786SFrançois Tigeot 	 * active context. It is never used for submitting user rendering and
19981487f786SFrançois Tigeot 	 * as such never requires the golden render context, and so we can skip
19991487f786SFrançois Tigeot 	 * emitting it when we switch to the kernel context. This is required
20001487f786SFrançois Tigeot 	 * as during eviction we cannot allocate and pin the renderstate in
20011487f786SFrançois Tigeot 	 * order to initialise the context.
20021487f786SFrançois Tigeot 	 */
20031487f786SFrançois Tigeot 	if (ctx == ctx->i915->kernel_context)
20041487f786SFrançois Tigeot 		ce->initialised = true;
20051487f786SFrançois Tigeot 
200687df8fc6SFrançois Tigeot 	i915_gem_context_get(ctx);
20071487f786SFrançois Tigeot 	return 0;
20081487f786SFrançois Tigeot 
20091487f786SFrançois Tigeot error:
20101487f786SFrançois Tigeot 	ce->pin_count = 0;
20111487f786SFrançois Tigeot 	return ret;
20121487f786SFrançois Tigeot }
20131487f786SFrançois Tigeot 
20141487f786SFrançois Tigeot static void intel_ring_context_unpin(struct i915_gem_context *ctx,
20151487f786SFrançois Tigeot 				     struct intel_engine_cs *engine)
20161487f786SFrançois Tigeot {
20171487f786SFrançois Tigeot 	struct intel_context *ce = &ctx->engine[engine->id];
20181487f786SFrançois Tigeot 
2019303bf270SFrançois Tigeot 	lockdep_assert_held(&ctx->i915->drm.struct_mutex);
20201487f786SFrançois Tigeot 
20211487f786SFrançois Tigeot 	if (--ce->pin_count)
20221487f786SFrançois Tigeot 		return;
20231487f786SFrançois Tigeot 
20241487f786SFrançois Tigeot 	if (ce->state)
2025*1e12ee3bSFrançois Tigeot 		i915_vma_unpin(ce->state);
20261487f786SFrançois Tigeot 
202787df8fc6SFrançois Tigeot 	i915_gem_context_put(ctx);
20281487f786SFrançois Tigeot }
20291487f786SFrançois Tigeot 
203087df8fc6SFrançois Tigeot static int intel_init_ring_buffer(struct intel_engine_cs *engine)
2031ba55f2f5SFrançois Tigeot {
203287df8fc6SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
203371f41f3eSFrançois Tigeot 	struct intel_ring *ring;
2034ba55f2f5SFrançois Tigeot 	int ret;
2035ba55f2f5SFrançois Tigeot 
20368621f407SFrançois Tigeot 	WARN_ON(engine->buffer);
20372c9916cdSFrançois Tigeot 
203887df8fc6SFrançois Tigeot 	intel_engine_setup_common(engine);
203987df8fc6SFrançois Tigeot 
20408621f407SFrançois Tigeot 	memset(engine->semaphore.sync_seqno, 0,
20418621f407SFrançois Tigeot 	       sizeof(engine->semaphore.sync_seqno));
2042ba55f2f5SFrançois Tigeot 
204387df8fc6SFrançois Tigeot 	ret = intel_engine_init_common(engine);
2044303bf270SFrançois Tigeot 	if (ret)
2045303bf270SFrançois Tigeot 		goto error;
2046ba55f2f5SFrançois Tigeot 
20471487f786SFrançois Tigeot 	/* We may need to do things with the shrinker which
20481487f786SFrançois Tigeot 	 * require us to immediately switch back to the default
20491487f786SFrançois Tigeot 	 * context. This can cause a problem as pinning the
20501487f786SFrançois Tigeot 	 * default context also requires GTT space which may not
20511487f786SFrançois Tigeot 	 * be available. To avoid this we always pin the default
20521487f786SFrançois Tigeot 	 * context.
20531487f786SFrançois Tigeot 	 */
20541487f786SFrançois Tigeot 	ret = intel_ring_context_pin(dev_priv->kernel_context, engine);
20551487f786SFrançois Tigeot 	if (ret)
20561487f786SFrançois Tigeot 		goto error;
20571487f786SFrançois Tigeot 
205871f41f3eSFrançois Tigeot 	ring = intel_engine_create_ring(engine, 32 * PAGE_SIZE);
205971f41f3eSFrançois Tigeot 	if (IS_ERR(ring)) {
206071f41f3eSFrançois Tigeot 		ret = PTR_ERR(ring);
2061aee94f86SFrançois Tigeot 		goto error;
2062aee94f86SFrançois Tigeot 	}
2063352ff8bdSFrançois Tigeot 
2064*1e12ee3bSFrançois Tigeot 	if (HWS_NEEDS_PHYSICAL(dev_priv)) {
2065*1e12ee3bSFrançois Tigeot 		WARN_ON(engine->id != RCS);
2066*1e12ee3bSFrançois Tigeot 		ret = init_phys_status_page(engine);
2067e3adcf8fSFrançois Tigeot 		if (ret)
2068ba55f2f5SFrançois Tigeot 			goto error;
2069ba55f2f5SFrançois Tigeot 	} else {
2070*1e12ee3bSFrançois Tigeot 		ret = init_status_page(engine);
2071ba55f2f5SFrançois Tigeot 		if (ret)
2072ba55f2f5SFrançois Tigeot 			goto error;
2073ba55f2f5SFrançois Tigeot 	}
2074ba55f2f5SFrançois Tigeot 
207571f41f3eSFrançois Tigeot 	ret = intel_ring_pin(ring);
20762c9916cdSFrançois Tigeot 	if (ret) {
2077*1e12ee3bSFrançois Tigeot 		intel_ring_free(ring);
2078ba55f2f5SFrançois Tigeot 		goto error;
2079ba55f2f5SFrançois Tigeot 	}
2080*1e12ee3bSFrançois Tigeot 	engine->buffer = ring;
2081e3adcf8fSFrançois Tigeot 
2082e3adcf8fSFrançois Tigeot 	return 0;
2083e3adcf8fSFrançois Tigeot 
2084ba55f2f5SFrançois Tigeot error:
208571f41f3eSFrançois Tigeot 	intel_engine_cleanup(engine);
2086e3adcf8fSFrançois Tigeot 	return ret;
2087e3adcf8fSFrançois Tigeot }
2088e3adcf8fSFrançois Tigeot 
208971f41f3eSFrançois Tigeot void intel_engine_cleanup(struct intel_engine_cs *engine)
2090e3adcf8fSFrançois Tigeot {
20912c9916cdSFrançois Tigeot 	struct drm_i915_private *dev_priv;
2092e3adcf8fSFrançois Tigeot 
20931487f786SFrançois Tigeot 	dev_priv = engine->i915;
20942c9916cdSFrançois Tigeot 
20958621f407SFrançois Tigeot 	if (engine->buffer) {
2096*1e12ee3bSFrançois Tigeot 		WARN_ON(INTEL_GEN(dev_priv) > 2 &&
2097*1e12ee3bSFrançois Tigeot 			(I915_READ_MODE(engine) & MODE_IDLE) == 0);
2098b030f26bSFrançois Tigeot 
209971f41f3eSFrançois Tigeot 		intel_ring_unpin(engine->buffer);
210071f41f3eSFrançois Tigeot 		intel_ring_free(engine->buffer);
21018621f407SFrançois Tigeot 		engine->buffer = NULL;
2102aee94f86SFrançois Tigeot 	}
2103e3adcf8fSFrançois Tigeot 
21048621f407SFrançois Tigeot 	if (engine->cleanup)
21058621f407SFrançois Tigeot 		engine->cleanup(engine);
2106e3adcf8fSFrançois Tigeot 
2107*1e12ee3bSFrançois Tigeot 	if (HWS_NEEDS_PHYSICAL(dev_priv)) {
21088621f407SFrançois Tigeot 		WARN_ON(engine->id != RCS);
21098621f407SFrançois Tigeot 		cleanup_phys_status_page(engine);
2110*1e12ee3bSFrançois Tigeot 	} else {
2111*1e12ee3bSFrançois Tigeot 		cleanup_status_page(engine);
2112c0e85e96SFrançois Tigeot 	}
2113ba55f2f5SFrançois Tigeot 
211471f41f3eSFrançois Tigeot 	intel_engine_cleanup_common(engine);
21151487f786SFrançois Tigeot 
21161487f786SFrançois Tigeot 	intel_ring_context_unpin(dev_priv->kernel_context, engine);
21171487f786SFrançois Tigeot 
21181487f786SFrançois Tigeot 	engine->i915 = NULL;
2119*1e12ee3bSFrançois Tigeot 	dev_priv->engine[engine->id] = NULL;
2120*1e12ee3bSFrançois Tigeot 	kfree(engine);
2121*1e12ee3bSFrançois Tigeot }
2122*1e12ee3bSFrançois Tigeot 
2123*1e12ee3bSFrançois Tigeot void intel_legacy_submission_resume(struct drm_i915_private *dev_priv)
2124*1e12ee3bSFrançois Tigeot {
2125*1e12ee3bSFrançois Tigeot 	struct intel_engine_cs *engine;
2126*1e12ee3bSFrançois Tigeot 	enum intel_engine_id id;
2127*1e12ee3bSFrançois Tigeot 
2128*1e12ee3bSFrançois Tigeot 	for_each_engine(engine, dev_priv, id) {
2129*1e12ee3bSFrançois Tigeot 		engine->buffer->head = engine->buffer->tail;
2130*1e12ee3bSFrançois Tigeot 		engine->buffer->last_retired_head = -1;
2131*1e12ee3bSFrançois Tigeot 	}
2132e3adcf8fSFrançois Tigeot }
2133e3adcf8fSFrançois Tigeot 
213419c468b4SFrançois Tigeot int intel_ring_alloc_request_extras(struct drm_i915_gem_request *request)
2135b5c29a34SFrançois Tigeot {
21361487f786SFrançois Tigeot 	int ret;
21379edbd4a0SFrançois Tigeot 
21381487f786SFrançois Tigeot 	/* Flush enough space to reduce the likelihood of waiting after
21391487f786SFrançois Tigeot 	 * we start building the request - in which case we will just
21401487f786SFrançois Tigeot 	 * have to repeat work.
2141a05eeebfSFrançois Tigeot 	 */
21421487f786SFrançois Tigeot 	request->reserved_space += LEGACY_REQUEST_SIZE;
2143a2fdbec6SFrançois Tigeot 
214471f41f3eSFrançois Tigeot 	request->ring = request->engine->buffer;
2145a2fdbec6SFrançois Tigeot 
21461487f786SFrançois Tigeot 	ret = intel_ring_begin(request, 0);
21471487f786SFrançois Tigeot 	if (ret)
21481487f786SFrançois Tigeot 		return ret;
2149a05eeebfSFrançois Tigeot 
21501487f786SFrançois Tigeot 	request->reserved_space -= LEGACY_REQUEST_SIZE;
21511487f786SFrançois Tigeot 	return 0;
2152a05eeebfSFrançois Tigeot }
2153a05eeebfSFrançois Tigeot 
21548621f407SFrançois Tigeot static int wait_for_space(struct drm_i915_gem_request *req, int bytes)
2155a05eeebfSFrançois Tigeot {
215671f41f3eSFrançois Tigeot 	struct intel_ring *ring = req->ring;
21578621f407SFrançois Tigeot 	struct drm_i915_gem_request *target;
215871f41f3eSFrançois Tigeot 	int ret;
21598621f407SFrançois Tigeot 
216071f41f3eSFrançois Tigeot 	intel_ring_update_space(ring);
216171f41f3eSFrançois Tigeot 	if (ring->space >= bytes)
21628621f407SFrançois Tigeot 		return 0;
21638621f407SFrançois Tigeot 
21648621f407SFrançois Tigeot 	/*
21658621f407SFrançois Tigeot 	 * Space is reserved in the ringbuffer for finalising the request,
21668621f407SFrançois Tigeot 	 * as that cannot be allowed to fail. During request finalisation,
21678621f407SFrançois Tigeot 	 * reserved_space is set to 0 to stop the overallocation and the
21688621f407SFrançois Tigeot 	 * assumption is that then we never need to wait (which has the
21698621f407SFrançois Tigeot 	 * risk of failing with EINTR).
21708621f407SFrançois Tigeot 	 *
21718621f407SFrançois Tigeot 	 * See also i915_gem_request_alloc() and i915_add_request().
21728621f407SFrançois Tigeot 	 */
21731487f786SFrançois Tigeot 	GEM_BUG_ON(!req->reserved_space);
21748621f407SFrançois Tigeot 
217571f41f3eSFrançois Tigeot 	list_for_each_entry(target, &ring->request_list, ring_link) {
21768621f407SFrançois Tigeot 		unsigned space;
21778621f407SFrançois Tigeot 
21788621f407SFrançois Tigeot 		/* Would completion of this request free enough space? */
217971f41f3eSFrançois Tigeot 		space = __intel_ring_space(target->postfix, ring->tail,
218071f41f3eSFrançois Tigeot 					   ring->size);
21818621f407SFrançois Tigeot 		if (space >= bytes)
21828621f407SFrançois Tigeot 			break;
21838621f407SFrançois Tigeot 	}
21848621f407SFrançois Tigeot 
218571f41f3eSFrançois Tigeot 	if (WARN_ON(&target->ring_link == &ring->request_list))
21868621f407SFrançois Tigeot 		return -ENOSPC;
21878621f407SFrançois Tigeot 
2188*1e12ee3bSFrançois Tigeot 	ret = i915_wait_request(target,
2189*1e12ee3bSFrançois Tigeot 				I915_WAIT_INTERRUPTIBLE | I915_WAIT_LOCKED,
2190*1e12ee3bSFrançois Tigeot 				NULL, NO_WAITBOOST);
219171f41f3eSFrançois Tigeot 	if (ret)
219271f41f3eSFrançois Tigeot 		return ret;
219371f41f3eSFrançois Tigeot 
219471f41f3eSFrançois Tigeot 	i915_gem_request_retire_upto(target);
219571f41f3eSFrançois Tigeot 
219671f41f3eSFrançois Tigeot 	intel_ring_update_space(ring);
219771f41f3eSFrançois Tigeot 	GEM_BUG_ON(ring->space < bytes);
219871f41f3eSFrançois Tigeot 	return 0;
21998621f407SFrançois Tigeot }
22008621f407SFrançois Tigeot 
22018621f407SFrançois Tigeot int intel_ring_begin(struct drm_i915_gem_request *req, int num_dwords)
22028621f407SFrançois Tigeot {
220371f41f3eSFrançois Tigeot 	struct intel_ring *ring = req->ring;
220471f41f3eSFrançois Tigeot 	int remain_actual = ring->size - ring->tail;
220571f41f3eSFrançois Tigeot 	int remain_usable = ring->effective_size - ring->tail;
22068621f407SFrançois Tigeot 	int bytes = num_dwords * sizeof(u32);
22078621f407SFrançois Tigeot 	int total_bytes, wait_bytes;
2208a05eeebfSFrançois Tigeot 	bool need_wrap = false;
2209a05eeebfSFrançois Tigeot 
22101487f786SFrançois Tigeot 	total_bytes = bytes + req->reserved_space;
2211a05eeebfSFrançois Tigeot 
2212a05eeebfSFrançois Tigeot 	if (unlikely(bytes > remain_usable)) {
2213a05eeebfSFrançois Tigeot 		/*
2214a05eeebfSFrançois Tigeot 		 * Not enough space for the basic request. So need to flush
2215a05eeebfSFrançois Tigeot 		 * out the remainder and then wait for base + reserved.
2216a05eeebfSFrançois Tigeot 		 */
2217a05eeebfSFrançois Tigeot 		wait_bytes = remain_actual + total_bytes;
2218a05eeebfSFrançois Tigeot 		need_wrap = true;
22198621f407SFrançois Tigeot 	} else if (unlikely(total_bytes > remain_usable)) {
2220a05eeebfSFrançois Tigeot 		/*
2221a05eeebfSFrançois Tigeot 		 * The base request will fit but the reserved space
22228621f407SFrançois Tigeot 		 * falls off the end. So we don't need an immediate wrap
2223c0e85e96SFrançois Tigeot 		 * and only need to effectively wait for the reserved
2224c0e85e96SFrançois Tigeot 		 * size space from the start of ringbuffer.
2225a05eeebfSFrançois Tigeot 		 */
22261487f786SFrançois Tigeot 		wait_bytes = remain_actual + req->reserved_space;
22278621f407SFrançois Tigeot 	} else {
2228a05eeebfSFrançois Tigeot 		/* No wrapping required, just waiting. */
2229a05eeebfSFrançois Tigeot 		wait_bytes = total_bytes;
2230a05eeebfSFrançois Tigeot 	}
2231a05eeebfSFrançois Tigeot 
223271f41f3eSFrançois Tigeot 	if (wait_bytes > ring->space) {
22338621f407SFrançois Tigeot 		int ret = wait_for_space(req, wait_bytes);
2234a2fdbec6SFrançois Tigeot 		if (unlikely(ret))
2235a2fdbec6SFrançois Tigeot 			return ret;
2236a2fdbec6SFrançois Tigeot 	}
2237a2fdbec6SFrançois Tigeot 
22388621f407SFrançois Tigeot 	if (unlikely(need_wrap)) {
223971f41f3eSFrançois Tigeot 		GEM_BUG_ON(remain_actual > ring->space);
224071f41f3eSFrançois Tigeot 		GEM_BUG_ON(ring->tail + remain_actual > ring->size);
22418621f407SFrançois Tigeot 
22428621f407SFrançois Tigeot 		/* Fill the tail with MI_NOOP */
224371f41f3eSFrançois Tigeot 		memset(ring->vaddr + ring->tail, 0, remain_actual);
224471f41f3eSFrançois Tigeot 		ring->tail = 0;
224571f41f3eSFrançois Tigeot 		ring->space -= remain_actual;
2246a2fdbec6SFrançois Tigeot 	}
2247a2fdbec6SFrançois Tigeot 
224871f41f3eSFrançois Tigeot 	ring->space -= bytes;
224971f41f3eSFrançois Tigeot 	GEM_BUG_ON(ring->space < 0);
22509edbd4a0SFrançois Tigeot 	return 0;
22519edbd4a0SFrançois Tigeot }
22529edbd4a0SFrançois Tigeot 
22539edbd4a0SFrançois Tigeot /* Align the ring tail to a cacheline boundary */
2254a05eeebfSFrançois Tigeot int intel_ring_cacheline_align(struct drm_i915_gem_request *req)
22559edbd4a0SFrançois Tigeot {
225671f41f3eSFrançois Tigeot 	struct intel_ring *ring = req->ring;
225771f41f3eSFrançois Tigeot 	int num_dwords =
225871f41f3eSFrançois Tigeot 		(ring->tail & (CACHELINE_BYTES - 1)) / sizeof(uint32_t);
22599edbd4a0SFrançois Tigeot 	int ret;
22609edbd4a0SFrançois Tigeot 
22619edbd4a0SFrançois Tigeot 	if (num_dwords == 0)
22629edbd4a0SFrançois Tigeot 		return 0;
22639edbd4a0SFrançois Tigeot 
2264ba55f2f5SFrançois Tigeot 	num_dwords = CACHELINE_BYTES / sizeof(uint32_t) - num_dwords;
2265a05eeebfSFrançois Tigeot 	ret = intel_ring_begin(req, num_dwords);
22669edbd4a0SFrançois Tigeot 	if (ret)
22679edbd4a0SFrançois Tigeot 		return ret;
22689edbd4a0SFrançois Tigeot 
22699edbd4a0SFrançois Tigeot 	while (num_dwords--)
227071f41f3eSFrançois Tigeot 		intel_ring_emit(ring, MI_NOOP);
22719edbd4a0SFrançois Tigeot 
227271f41f3eSFrançois Tigeot 	intel_ring_advance(ring);
22739edbd4a0SFrançois Tigeot 
22749edbd4a0SFrançois Tigeot 	return 0;
2275e3adcf8fSFrançois Tigeot }
2276e3adcf8fSFrançois Tigeot 
227771f41f3eSFrançois Tigeot static void gen6_bsd_submit_request(struct drm_i915_gem_request *request)
2278e3adcf8fSFrançois Tigeot {
227971f41f3eSFrançois Tigeot 	struct drm_i915_private *dev_priv = request->i915;
22801487f786SFrançois Tigeot 
22811487f786SFrançois Tigeot 	intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL);
2282e3adcf8fSFrançois Tigeot 
2283e3adcf8fSFrançois Tigeot        /* Every tail move must follow the sequence below */
2284f4e1c372SFrançois Tigeot 
2285f4e1c372SFrançois Tigeot 	/* Disable notification that the ring is IDLE. The GT
2286f4e1c372SFrançois Tigeot 	 * will then assume that it is busy and bring it out of rc6.
2287f4e1c372SFrançois Tigeot 	 */
22881487f786SFrançois Tigeot 	I915_WRITE_FW(GEN6_BSD_SLEEP_PSMI_CONTROL,
2289f4e1c372SFrançois Tigeot 		      _MASKED_BIT_ENABLE(GEN6_BSD_SLEEP_MSG_DISABLE));
2290e3adcf8fSFrançois Tigeot 
2291f4e1c372SFrançois Tigeot 	/* Clear the context id. Here be magic! */
22921487f786SFrançois Tigeot 	I915_WRITE64_FW(GEN6_BSD_RNCID, 0x0);
2293e3adcf8fSFrançois Tigeot 
2294f4e1c372SFrançois Tigeot 	/* Wait for the ring not to be idle, i.e. for it to wake up. */
22951487f786SFrançois Tigeot 	if (intel_wait_for_register_fw(dev_priv,
22961487f786SFrançois Tigeot 				       GEN6_BSD_SLEEP_PSMI_CONTROL,
22971487f786SFrançois Tigeot 				       GEN6_BSD_SLEEP_INDICATOR,
22981487f786SFrançois Tigeot 				       0,
2299f4e1c372SFrançois Tigeot 				       50))
2300f4e1c372SFrançois Tigeot 		DRM_ERROR("timed out waiting for the BSD ring to wake up\n");
2301f4e1c372SFrançois Tigeot 
2302f4e1c372SFrançois Tigeot 	/* Now that the ring is fully powered up, update the tail */
230371f41f3eSFrançois Tigeot 	i9xx_submit_request(request);
2304f4e1c372SFrançois Tigeot 
2305f4e1c372SFrançois Tigeot 	/* Let the ring send IDLE messages to the GT again,
2306f4e1c372SFrançois Tigeot 	 * and so let it sleep to conserve power when idle.
2307f4e1c372SFrançois Tigeot 	 */
23081487f786SFrançois Tigeot 	I915_WRITE_FW(GEN6_BSD_SLEEP_PSMI_CONTROL,
2309f4e1c372SFrançois Tigeot 		      _MASKED_BIT_DISABLE(GEN6_BSD_SLEEP_MSG_DISABLE));
23101487f786SFrançois Tigeot 
23111487f786SFrançois Tigeot 	intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL);
2312e3adcf8fSFrançois Tigeot }
2313e3adcf8fSFrançois Tigeot 
231471f41f3eSFrançois Tigeot static int gen6_bsd_ring_flush(struct drm_i915_gem_request *req, u32 mode)
2315e3adcf8fSFrançois Tigeot {
231671f41f3eSFrançois Tigeot 	struct intel_ring *ring = req->ring;
2317e3adcf8fSFrançois Tigeot 	uint32_t cmd;
2318e3adcf8fSFrançois Tigeot 	int ret;
2319e3adcf8fSFrançois Tigeot 
2320a05eeebfSFrançois Tigeot 	ret = intel_ring_begin(req, 4);
2321e3adcf8fSFrançois Tigeot 	if (ret)
2322e3adcf8fSFrançois Tigeot 		return ret;
2323e3adcf8fSFrançois Tigeot 
2324e3adcf8fSFrançois Tigeot 	cmd = MI_FLUSH_DW;
23251487f786SFrançois Tigeot 	if (INTEL_GEN(req->i915) >= 8)
23269edbd4a0SFrançois Tigeot 		cmd += 1;
23272c9916cdSFrançois Tigeot 
23282c9916cdSFrançois Tigeot 	/* We always require a command barrier so that subsequent
23292c9916cdSFrançois Tigeot 	 * commands, such as breadcrumb interrupts, are strictly ordered
23302c9916cdSFrançois Tigeot 	 * wrt the contents of the write cache being flushed to memory
23312c9916cdSFrançois Tigeot 	 * (and thus being coherent from the CPU).
23322c9916cdSFrançois Tigeot 	 */
23332c9916cdSFrançois Tigeot 	cmd |= MI_FLUSH_DW_STORE_INDEX | MI_FLUSH_DW_OP_STOREDW;
23342c9916cdSFrançois Tigeot 
2335b5c29a34SFrançois Tigeot 	/*
2336b5c29a34SFrançois Tigeot 	 * Bspec vol 1c.5 - video engine command streamer:
2337b5c29a34SFrançois Tigeot 	 * "If ENABLED, all TLBs will be invalidated once the flush
2338b5c29a34SFrançois Tigeot 	 * operation is complete. This bit is only valid when the
2339b5c29a34SFrançois Tigeot 	 * Post-Sync Operation field is a value of 1h or 3h."
2340b5c29a34SFrançois Tigeot 	 */
234171f41f3eSFrançois Tigeot 	if (mode & EMIT_INVALIDATE)
23422c9916cdSFrançois Tigeot 		cmd |= MI_INVALIDATE_TLB | MI_INVALIDATE_BSD;
23432c9916cdSFrançois Tigeot 
234471f41f3eSFrançois Tigeot 	intel_ring_emit(ring, cmd);
234571f41f3eSFrançois Tigeot 	intel_ring_emit(ring, I915_GEM_HWS_SCRATCH_ADDR | MI_FLUSH_DW_USE_GTT);
23461487f786SFrançois Tigeot 	if (INTEL_GEN(req->i915) >= 8) {
234771f41f3eSFrançois Tigeot 		intel_ring_emit(ring, 0); /* upper addr */
234871f41f3eSFrançois Tigeot 		intel_ring_emit(ring, 0); /* value */
23499edbd4a0SFrançois Tigeot 	} else  {
235071f41f3eSFrançois Tigeot 		intel_ring_emit(ring, 0);
235171f41f3eSFrançois Tigeot 		intel_ring_emit(ring, MI_NOOP);
23529edbd4a0SFrançois Tigeot 	}
235371f41f3eSFrançois Tigeot 	intel_ring_advance(ring);
23549edbd4a0SFrançois Tigeot 	return 0;
23559edbd4a0SFrançois Tigeot }
23569edbd4a0SFrançois Tigeot 
23579edbd4a0SFrançois Tigeot static int
235871f41f3eSFrançois Tigeot gen8_emit_bb_start(struct drm_i915_gem_request *req,
2359ba55f2f5SFrançois Tigeot 		   u64 offset, u32 len,
236071f41f3eSFrançois Tigeot 		   unsigned int dispatch_flags)
23619edbd4a0SFrançois Tigeot {
236271f41f3eSFrançois Tigeot 	struct intel_ring *ring = req->ring;
236371f41f3eSFrançois Tigeot 	bool ppgtt = USES_PPGTT(req->i915) &&
2364477eb7f9SFrançois Tigeot 			!(dispatch_flags & I915_DISPATCH_SECURE);
23659edbd4a0SFrançois Tigeot 	int ret;
23669edbd4a0SFrançois Tigeot 
2367a05eeebfSFrançois Tigeot 	ret = intel_ring_begin(req, 4);
23689edbd4a0SFrançois Tigeot 	if (ret)
23699edbd4a0SFrançois Tigeot 		return ret;
23709edbd4a0SFrançois Tigeot 
23719edbd4a0SFrançois Tigeot 	/* FIXME(BDW): Address space and security selectors. */
237271f41f3eSFrançois Tigeot 	intel_ring_emit(ring, MI_BATCH_BUFFER_START_GEN8 | (ppgtt<<8) |
2373a05eeebfSFrançois Tigeot 			(dispatch_flags & I915_DISPATCH_RS ?
2374a05eeebfSFrançois Tigeot 			 MI_BATCH_RESOURCE_STREAMER : 0));
237571f41f3eSFrançois Tigeot 	intel_ring_emit(ring, lower_32_bits(offset));
237671f41f3eSFrançois Tigeot 	intel_ring_emit(ring, upper_32_bits(offset));
237771f41f3eSFrançois Tigeot 	intel_ring_emit(ring, MI_NOOP);
237871f41f3eSFrançois Tigeot 	intel_ring_advance(ring);
23799edbd4a0SFrançois Tigeot 
2380e3adcf8fSFrançois Tigeot 	return 0;
2381e3adcf8fSFrançois Tigeot }
2382e3adcf8fSFrançois Tigeot 
2383e3adcf8fSFrançois Tigeot static int
238471f41f3eSFrançois Tigeot hsw_emit_bb_start(struct drm_i915_gem_request *req,
2385ba55f2f5SFrançois Tigeot 		  u64 offset, u32 len,
238671f41f3eSFrançois Tigeot 		  unsigned int dispatch_flags)
2387e3adcf8fSFrançois Tigeot {
238871f41f3eSFrançois Tigeot 	struct intel_ring *ring = req->ring;
2389e3adcf8fSFrançois Tigeot 	int ret;
2390e3adcf8fSFrançois Tigeot 
2391a05eeebfSFrançois Tigeot 	ret = intel_ring_begin(req, 2);
2392e3adcf8fSFrançois Tigeot 	if (ret)
2393e3adcf8fSFrançois Tigeot 		return ret;
2394e3adcf8fSFrançois Tigeot 
239571f41f3eSFrançois Tigeot 	intel_ring_emit(ring,
23961b13d190SFrançois Tigeot 			MI_BATCH_BUFFER_START |
2397477eb7f9SFrançois Tigeot 			(dispatch_flags & I915_DISPATCH_SECURE ?
2398a05eeebfSFrançois Tigeot 			 0 : MI_BATCH_PPGTT_HSW | MI_BATCH_NON_SECURE_HSW) |
2399a05eeebfSFrançois Tigeot 			(dispatch_flags & I915_DISPATCH_RS ?
2400a05eeebfSFrançois Tigeot 			 MI_BATCH_RESOURCE_STREAMER : 0));
2401b5c29a34SFrançois Tigeot 	/* bit0-7 is the length on GEN6+ */
240271f41f3eSFrançois Tigeot 	intel_ring_emit(ring, offset);
240371f41f3eSFrançois Tigeot 	intel_ring_advance(ring);
2404b5c29a34SFrançois Tigeot 
2405b5c29a34SFrançois Tigeot 	return 0;
2406b5c29a34SFrançois Tigeot }
2407b5c29a34SFrançois Tigeot 
2408b5c29a34SFrançois Tigeot static int
240971f41f3eSFrançois Tigeot gen6_emit_bb_start(struct drm_i915_gem_request *req,
2410ba55f2f5SFrançois Tigeot 		   u64 offset, u32 len,
241171f41f3eSFrançois Tigeot 		   unsigned int dispatch_flags)
2412b5c29a34SFrançois Tigeot {
241371f41f3eSFrançois Tigeot 	struct intel_ring *ring = req->ring;
2414b5c29a34SFrançois Tigeot 	int ret;
2415b5c29a34SFrançois Tigeot 
2416a05eeebfSFrançois Tigeot 	ret = intel_ring_begin(req, 2);
2417b5c29a34SFrançois Tigeot 	if (ret)
2418b5c29a34SFrançois Tigeot 		return ret;
2419b5c29a34SFrançois Tigeot 
242071f41f3eSFrançois Tigeot 	intel_ring_emit(ring,
2421b5c29a34SFrançois Tigeot 			MI_BATCH_BUFFER_START |
2422477eb7f9SFrançois Tigeot 			(dispatch_flags & I915_DISPATCH_SECURE ?
2423477eb7f9SFrançois Tigeot 			 0 : MI_BATCH_NON_SECURE_I965));
2424e3adcf8fSFrançois Tigeot 	/* bit0-7 is the length on GEN6+ */
242571f41f3eSFrançois Tigeot 	intel_ring_emit(ring, offset);
242671f41f3eSFrançois Tigeot 	intel_ring_advance(ring);
2427e3adcf8fSFrançois Tigeot 
2428e3adcf8fSFrançois Tigeot 	return 0;
2429e3adcf8fSFrançois Tigeot }
2430e3adcf8fSFrançois Tigeot 
2431e3adcf8fSFrançois Tigeot /* Blitter support (SandyBridge+) */
2432e3adcf8fSFrançois Tigeot 
243371f41f3eSFrançois Tigeot static int gen6_ring_flush(struct drm_i915_gem_request *req, u32 mode)
2434e3adcf8fSFrançois Tigeot {
243571f41f3eSFrançois Tigeot 	struct intel_ring *ring = req->ring;
2436e3adcf8fSFrançois Tigeot 	uint32_t cmd;
2437e3adcf8fSFrançois Tigeot 	int ret;
2438e3adcf8fSFrançois Tigeot 
2439a05eeebfSFrançois Tigeot 	ret = intel_ring_begin(req, 4);
2440e3adcf8fSFrançois Tigeot 	if (ret)
2441e3adcf8fSFrançois Tigeot 		return ret;
2442e3adcf8fSFrançois Tigeot 
2443e3adcf8fSFrançois Tigeot 	cmd = MI_FLUSH_DW;
24441487f786SFrançois Tigeot 	if (INTEL_GEN(req->i915) >= 8)
24459edbd4a0SFrançois Tigeot 		cmd += 1;
24462c9916cdSFrançois Tigeot 
24472c9916cdSFrançois Tigeot 	/* We always require a command barrier so that subsequent
24482c9916cdSFrançois Tigeot 	 * commands, such as breadcrumb interrupts, are strictly ordered
24492c9916cdSFrançois Tigeot 	 * wrt the contents of the write cache being flushed to memory
24502c9916cdSFrançois Tigeot 	 * (and thus being coherent from the CPU).
24512c9916cdSFrançois Tigeot 	 */
24522c9916cdSFrançois Tigeot 	cmd |= MI_FLUSH_DW_STORE_INDEX | MI_FLUSH_DW_OP_STOREDW;
24532c9916cdSFrançois Tigeot 
2454b5c29a34SFrançois Tigeot 	/*
2455b5c29a34SFrançois Tigeot 	 * Bspec vol 1c.3 - blitter engine command streamer:
2456b5c29a34SFrançois Tigeot 	 * "If ENABLED, all TLBs will be invalidated once the flush
2457b5c29a34SFrançois Tigeot 	 * operation is complete. This bit is only valid when the
2458b5c29a34SFrançois Tigeot 	 * Post-Sync Operation field is a value of 1h or 3h."
2459b5c29a34SFrançois Tigeot 	 */
246071f41f3eSFrançois Tigeot 	if (mode & EMIT_INVALIDATE)
24612c9916cdSFrançois Tigeot 		cmd |= MI_INVALIDATE_TLB;
246271f41f3eSFrançois Tigeot 	intel_ring_emit(ring, cmd);
246371f41f3eSFrançois Tigeot 	intel_ring_emit(ring,
24648621f407SFrançois Tigeot 			I915_GEM_HWS_SCRATCH_ADDR | MI_FLUSH_DW_USE_GTT);
24651487f786SFrançois Tigeot 	if (INTEL_GEN(req->i915) >= 8) {
246671f41f3eSFrançois Tigeot 		intel_ring_emit(ring, 0); /* upper addr */
246771f41f3eSFrançois Tigeot 		intel_ring_emit(ring, 0); /* value */
24689edbd4a0SFrançois Tigeot 	} else  {
246971f41f3eSFrançois Tigeot 		intel_ring_emit(ring, 0);
247071f41f3eSFrançois Tigeot 		intel_ring_emit(ring, MI_NOOP);
24719edbd4a0SFrançois Tigeot 	}
247271f41f3eSFrançois Tigeot 	intel_ring_advance(ring);
24735d0b1887SFrançois Tigeot 
2474e3adcf8fSFrançois Tigeot 	return 0;
2475e3adcf8fSFrançois Tigeot }
2476e3adcf8fSFrançois Tigeot 
24771487f786SFrançois Tigeot static void intel_ring_init_semaphores(struct drm_i915_private *dev_priv,
24781487f786SFrançois Tigeot 				       struct intel_engine_cs *engine)
24791487f786SFrançois Tigeot {
24801487f786SFrançois Tigeot 	struct drm_i915_gem_object *obj;
24811487f786SFrançois Tigeot 	int ret, i;
24821487f786SFrançois Tigeot 
248387df8fc6SFrançois Tigeot 	if (!i915.semaphores)
24841487f786SFrançois Tigeot 		return;
24851487f786SFrançois Tigeot 
2486*1e12ee3bSFrançois Tigeot 	if (INTEL_GEN(dev_priv) >= 8 && !dev_priv->semaphore) {
2487*1e12ee3bSFrançois Tigeot 		struct i915_vma *vma;
24881487f786SFrançois Tigeot 
2489*1e12ee3bSFrançois Tigeot 		obj = i915_gem_object_create(&dev_priv->drm, 4096);
2490*1e12ee3bSFrançois Tigeot 		if (IS_ERR(obj))
2491*1e12ee3bSFrançois Tigeot 			goto err;
2492*1e12ee3bSFrançois Tigeot 
2493*1e12ee3bSFrançois Tigeot 		vma = i915_vma_create(obj, &dev_priv->ggtt.base, NULL);
2494*1e12ee3bSFrançois Tigeot 		if (IS_ERR(vma))
2495*1e12ee3bSFrançois Tigeot 			goto err_obj;
2496*1e12ee3bSFrançois Tigeot 
2497*1e12ee3bSFrançois Tigeot 		ret = i915_gem_object_set_to_gtt_domain(obj, false);
2498*1e12ee3bSFrançois Tigeot 		if (ret)
2499*1e12ee3bSFrançois Tigeot 			goto err_obj;
2500*1e12ee3bSFrançois Tigeot 
2501*1e12ee3bSFrançois Tigeot 		ret = i915_vma_pin(vma, 0, 0, PIN_GLOBAL | PIN_HIGH);
2502*1e12ee3bSFrançois Tigeot 		if (ret)
2503*1e12ee3bSFrançois Tigeot 			goto err_obj;
2504*1e12ee3bSFrançois Tigeot 
2505*1e12ee3bSFrançois Tigeot 		dev_priv->semaphore = vma;
2506*1e12ee3bSFrançois Tigeot 	}
25071487f786SFrançois Tigeot 
25081487f786SFrançois Tigeot 	if (INTEL_GEN(dev_priv) >= 8) {
2509*1e12ee3bSFrançois Tigeot 		u32 offset = i915_ggtt_offset(dev_priv->semaphore);
25101487f786SFrançois Tigeot 
251171f41f3eSFrançois Tigeot 		engine->semaphore.sync_to = gen8_ring_sync_to;
25121487f786SFrançois Tigeot 		engine->semaphore.signal = gen8_xcs_signal;
25131487f786SFrançois Tigeot 
25141487f786SFrançois Tigeot 		for (i = 0; i < I915_NUM_ENGINES; i++) {
2515*1e12ee3bSFrançois Tigeot 			u32 ring_offset;
25161487f786SFrançois Tigeot 
25171487f786SFrançois Tigeot 			if (i != engine->id)
25181487f786SFrançois Tigeot 				ring_offset = offset + GEN8_SEMAPHORE_OFFSET(engine->id, i);
25191487f786SFrançois Tigeot 			else
25201487f786SFrançois Tigeot 				ring_offset = MI_SEMAPHORE_SYNC_INVALID;
25211487f786SFrançois Tigeot 
25221487f786SFrançois Tigeot 			engine->semaphore.signal_ggtt[i] = ring_offset;
25231487f786SFrançois Tigeot 		}
25241487f786SFrançois Tigeot 	} else if (INTEL_GEN(dev_priv) >= 6) {
252571f41f3eSFrançois Tigeot 		engine->semaphore.sync_to = gen6_ring_sync_to;
25261487f786SFrançois Tigeot 		engine->semaphore.signal = gen6_signal;
25271487f786SFrançois Tigeot 
25281487f786SFrançois Tigeot 		/*
25291487f786SFrançois Tigeot 		 * The current semaphore is only applied on pre-gen8
25301487f786SFrançois Tigeot 		 * platform.  And there is no VCS2 ring on the pre-gen8
25311487f786SFrançois Tigeot 		 * platform. So the semaphore between RCS and VCS2 is
25321487f786SFrançois Tigeot 		 * initialized as INVALID.  Gen8 will initialize the
25331487f786SFrançois Tigeot 		 * sema between VCS2 and RCS later.
25341487f786SFrançois Tigeot 		 */
2535*1e12ee3bSFrançois Tigeot 		for (i = 0; i < GEN6_NUM_SEMAPHORES; i++) {
25361487f786SFrançois Tigeot 			static const struct {
25371487f786SFrançois Tigeot 				u32 wait_mbox;
25381487f786SFrançois Tigeot 				i915_reg_t mbox_reg;
2539*1e12ee3bSFrançois Tigeot 			} sem_data[GEN6_NUM_SEMAPHORES][GEN6_NUM_SEMAPHORES] = {
2540*1e12ee3bSFrançois Tigeot 				[RCS_HW] = {
2541*1e12ee3bSFrançois Tigeot 					[VCS_HW] =  { .wait_mbox = MI_SEMAPHORE_SYNC_RV,  .mbox_reg = GEN6_VRSYNC },
2542*1e12ee3bSFrançois Tigeot 					[BCS_HW] =  { .wait_mbox = MI_SEMAPHORE_SYNC_RB,  .mbox_reg = GEN6_BRSYNC },
2543*1e12ee3bSFrançois Tigeot 					[VECS_HW] = { .wait_mbox = MI_SEMAPHORE_SYNC_RVE, .mbox_reg = GEN6_VERSYNC },
25441487f786SFrançois Tigeot 				},
2545*1e12ee3bSFrançois Tigeot 				[VCS_HW] = {
2546*1e12ee3bSFrançois Tigeot 					[RCS_HW] =  { .wait_mbox = MI_SEMAPHORE_SYNC_VR,  .mbox_reg = GEN6_RVSYNC },
2547*1e12ee3bSFrançois Tigeot 					[BCS_HW] =  { .wait_mbox = MI_SEMAPHORE_SYNC_VB,  .mbox_reg = GEN6_BVSYNC },
2548*1e12ee3bSFrançois Tigeot 					[VECS_HW] = { .wait_mbox = MI_SEMAPHORE_SYNC_VVE, .mbox_reg = GEN6_VEVSYNC },
25491487f786SFrançois Tigeot 				},
2550*1e12ee3bSFrançois Tigeot 				[BCS_HW] = {
2551*1e12ee3bSFrançois Tigeot 					[RCS_HW] =  { .wait_mbox = MI_SEMAPHORE_SYNC_BR,  .mbox_reg = GEN6_RBSYNC },
2552*1e12ee3bSFrançois Tigeot 					[VCS_HW] =  { .wait_mbox = MI_SEMAPHORE_SYNC_BV,  .mbox_reg = GEN6_VBSYNC },
2553*1e12ee3bSFrançois Tigeot 					[VECS_HW] = { .wait_mbox = MI_SEMAPHORE_SYNC_BVE, .mbox_reg = GEN6_VEBSYNC },
25541487f786SFrançois Tigeot 				},
2555*1e12ee3bSFrançois Tigeot 				[VECS_HW] = {
2556*1e12ee3bSFrançois Tigeot 					[RCS_HW] =  { .wait_mbox = MI_SEMAPHORE_SYNC_VER, .mbox_reg = GEN6_RVESYNC },
2557*1e12ee3bSFrançois Tigeot 					[VCS_HW] =  { .wait_mbox = MI_SEMAPHORE_SYNC_VEV, .mbox_reg = GEN6_VVESYNC },
2558*1e12ee3bSFrançois Tigeot 					[BCS_HW] =  { .wait_mbox = MI_SEMAPHORE_SYNC_VEB, .mbox_reg = GEN6_BVESYNC },
25591487f786SFrançois Tigeot 				},
25601487f786SFrançois Tigeot 			};
25611487f786SFrançois Tigeot 			u32 wait_mbox;
25621487f786SFrançois Tigeot 			i915_reg_t mbox_reg;
25631487f786SFrançois Tigeot 
2564*1e12ee3bSFrançois Tigeot 			if (i == engine->hw_id) {
25651487f786SFrançois Tigeot 				wait_mbox = MI_SEMAPHORE_SYNC_INVALID;
25661487f786SFrançois Tigeot 				mbox_reg = GEN6_NOSYNC;
25671487f786SFrançois Tigeot 			} else {
2568*1e12ee3bSFrançois Tigeot 				wait_mbox = sem_data[engine->hw_id][i].wait_mbox;
2569*1e12ee3bSFrançois Tigeot 				mbox_reg = sem_data[engine->hw_id][i].mbox_reg;
25701487f786SFrançois Tigeot 			}
25711487f786SFrançois Tigeot 
25721487f786SFrançois Tigeot 			engine->semaphore.mbox.wait[i] = wait_mbox;
25731487f786SFrançois Tigeot 			engine->semaphore.mbox.signal[i] = mbox_reg;
25741487f786SFrançois Tigeot 		}
25751487f786SFrançois Tigeot 	}
2576*1e12ee3bSFrançois Tigeot 
2577*1e12ee3bSFrançois Tigeot 	return;
2578*1e12ee3bSFrançois Tigeot 
2579*1e12ee3bSFrançois Tigeot err_obj:
2580*1e12ee3bSFrançois Tigeot 	i915_gem_object_put(obj);
2581*1e12ee3bSFrançois Tigeot err:
2582*1e12ee3bSFrançois Tigeot 	DRM_DEBUG_DRIVER("Failed to allocate space for semaphores, disabling\n");
2583*1e12ee3bSFrançois Tigeot 	i915.semaphores = 0;
25841487f786SFrançois Tigeot }
25851487f786SFrançois Tigeot 
25861487f786SFrançois Tigeot static void intel_ring_init_irq(struct drm_i915_private *dev_priv,
25871487f786SFrançois Tigeot 				struct intel_engine_cs *engine)
25881487f786SFrançois Tigeot {
258987df8fc6SFrançois Tigeot 	engine->irq_enable_mask = GT_RENDER_USER_INTERRUPT << engine->irq_shift;
259087df8fc6SFrançois Tigeot 
25911487f786SFrançois Tigeot 	if (INTEL_GEN(dev_priv) >= 8) {
2592303bf270SFrançois Tigeot 		engine->irq_enable = gen8_irq_enable;
2593303bf270SFrançois Tigeot 		engine->irq_disable = gen8_irq_disable;
25941487f786SFrançois Tigeot 		engine->irq_seqno_barrier = gen6_seqno_barrier;
25951487f786SFrançois Tigeot 	} else if (INTEL_GEN(dev_priv) >= 6) {
2596303bf270SFrançois Tigeot 		engine->irq_enable = gen6_irq_enable;
2597303bf270SFrançois Tigeot 		engine->irq_disable = gen6_irq_disable;
25981487f786SFrançois Tigeot 		engine->irq_seqno_barrier = gen6_seqno_barrier;
25991487f786SFrançois Tigeot 	} else if (INTEL_GEN(dev_priv) >= 5) {
2600303bf270SFrançois Tigeot 		engine->irq_enable = gen5_irq_enable;
2601303bf270SFrançois Tigeot 		engine->irq_disable = gen5_irq_disable;
2602303bf270SFrançois Tigeot 		engine->irq_seqno_barrier = gen5_seqno_barrier;
26031487f786SFrançois Tigeot 	} else if (INTEL_GEN(dev_priv) >= 3) {
2604303bf270SFrançois Tigeot 		engine->irq_enable = i9xx_irq_enable;
2605303bf270SFrançois Tigeot 		engine->irq_disable = i9xx_irq_disable;
26061487f786SFrançois Tigeot 	} else {
2607303bf270SFrançois Tigeot 		engine->irq_enable = i8xx_irq_enable;
2608303bf270SFrançois Tigeot 		engine->irq_disable = i8xx_irq_disable;
26091487f786SFrançois Tigeot 	}
26101487f786SFrançois Tigeot }
26111487f786SFrançois Tigeot 
26121487f786SFrançois Tigeot static void intel_ring_default_vfuncs(struct drm_i915_private *dev_priv,
26131487f786SFrançois Tigeot 				      struct intel_engine_cs *engine)
26141487f786SFrançois Tigeot {
26151487f786SFrançois Tigeot 	intel_ring_init_irq(dev_priv, engine);
26161487f786SFrançois Tigeot 	intel_ring_init_semaphores(dev_priv, engine);
261771f41f3eSFrançois Tigeot 
261871f41f3eSFrançois Tigeot 	engine->init_hw = init_ring_common;
2619*1e12ee3bSFrançois Tigeot 	engine->reset_hw = reset_ring_common;
262071f41f3eSFrançois Tigeot 
262171f41f3eSFrançois Tigeot 	engine->emit_request = i9xx_emit_request;
262271f41f3eSFrançois Tigeot 	if (i915.semaphores)
262371f41f3eSFrançois Tigeot 		engine->emit_request = gen6_sema_emit_request;
262471f41f3eSFrançois Tigeot 	engine->submit_request = i9xx_submit_request;
262571f41f3eSFrançois Tigeot 
262671f41f3eSFrançois Tigeot 	if (INTEL_GEN(dev_priv) >= 8)
262771f41f3eSFrançois Tigeot 		engine->emit_bb_start = gen8_emit_bb_start;
262871f41f3eSFrançois Tigeot 	else if (INTEL_GEN(dev_priv) >= 6)
262971f41f3eSFrançois Tigeot 		engine->emit_bb_start = gen6_emit_bb_start;
263071f41f3eSFrançois Tigeot 	else if (INTEL_GEN(dev_priv) >= 4)
263171f41f3eSFrançois Tigeot 		engine->emit_bb_start = i965_emit_bb_start;
263271f41f3eSFrançois Tigeot 	else if (IS_I830(dev_priv) || IS_845G(dev_priv))
263371f41f3eSFrançois Tigeot 		engine->emit_bb_start = i830_emit_bb_start;
263471f41f3eSFrançois Tigeot 	else
263571f41f3eSFrançois Tigeot 		engine->emit_bb_start = i915_emit_bb_start;
26361487f786SFrançois Tigeot }
26371487f786SFrançois Tigeot 
263887df8fc6SFrançois Tigeot int intel_init_render_ring_buffer(struct intel_engine_cs *engine)
2639e3adcf8fSFrançois Tigeot {
264087df8fc6SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
264124edb884SFrançois Tigeot 	int ret;
2642e3adcf8fSFrançois Tigeot 
26431487f786SFrançois Tigeot 	intel_ring_default_vfuncs(dev_priv, engine);
26442c9916cdSFrançois Tigeot 
2645303bf270SFrançois Tigeot 	if (HAS_L3_DPF(dev_priv))
2646303bf270SFrançois Tigeot 		engine->irq_keep_mask = GT_RENDER_L3_PARITY_ERROR_INTERRUPT;
2647303bf270SFrançois Tigeot 
26481487f786SFrançois Tigeot 	if (INTEL_GEN(dev_priv) >= 8) {
26498621f407SFrançois Tigeot 		engine->init_context = intel_rcs_ctx_init;
265071f41f3eSFrançois Tigeot 		engine->emit_request = gen8_render_emit_request;
265171f41f3eSFrançois Tigeot 		engine->emit_flush = gen8_render_ring_flush;
265287df8fc6SFrançois Tigeot 		if (i915.semaphores)
26538621f407SFrançois Tigeot 			engine->semaphore.signal = gen8_rcs_signal;
26541487f786SFrançois Tigeot 	} else if (INTEL_GEN(dev_priv) >= 6) {
26558621f407SFrançois Tigeot 		engine->init_context = intel_rcs_ctx_init;
265671f41f3eSFrançois Tigeot 		engine->emit_flush = gen7_render_ring_flush;
26571487f786SFrançois Tigeot 		if (IS_GEN6(dev_priv))
265871f41f3eSFrançois Tigeot 			engine->emit_flush = gen6_render_ring_flush;
26591487f786SFrançois Tigeot 	} else if (IS_GEN5(dev_priv)) {
266071f41f3eSFrançois Tigeot 		engine->emit_flush = gen4_render_ring_flush;
2661686a02f1SFrançois Tigeot 	} else {
26621487f786SFrançois Tigeot 		if (INTEL_GEN(dev_priv) < 4)
266371f41f3eSFrançois Tigeot 			engine->emit_flush = gen2_render_ring_flush;
2664686a02f1SFrançois Tigeot 		else
266571f41f3eSFrançois Tigeot 			engine->emit_flush = gen4_render_ring_flush;
26668621f407SFrançois Tigeot 		engine->irq_enable_mask = I915_USER_INTERRUPT;
2667686a02f1SFrançois Tigeot 	}
266824edb884SFrançois Tigeot 
26691487f786SFrançois Tigeot 	if (IS_HASWELL(dev_priv))
267071f41f3eSFrançois Tigeot 		engine->emit_bb_start = hsw_emit_bb_start;
26711487f786SFrançois Tigeot 
26728621f407SFrançois Tigeot 	engine->init_hw = init_render_ring;
26738621f407SFrançois Tigeot 	engine->cleanup = render_ring_cleanup;
2674e3adcf8fSFrançois Tigeot 
267587df8fc6SFrançois Tigeot 	ret = intel_init_ring_buffer(engine);
2676b5c29a34SFrançois Tigeot 	if (ret)
26772c9916cdSFrançois Tigeot 		return ret;
26782c9916cdSFrançois Tigeot 
2679303bf270SFrançois Tigeot 	if (INTEL_GEN(dev_priv) >= 6) {
2680*1e12ee3bSFrançois Tigeot 		ret = intel_engine_create_scratch(engine, 4096);
2681303bf270SFrançois Tigeot 		if (ret)
2682303bf270SFrançois Tigeot 			return ret;
2683303bf270SFrançois Tigeot 	} else if (HAS_BROKEN_CS_TLB(dev_priv)) {
2684*1e12ee3bSFrançois Tigeot 		ret = intel_engine_create_scratch(engine, I830_WA_SIZE);
26852c9916cdSFrançois Tigeot 		if (ret)
26862c9916cdSFrançois Tigeot 			return ret;
2687b5c29a34SFrançois Tigeot 	}
2688b5c29a34SFrançois Tigeot 
2689e3adcf8fSFrançois Tigeot 	return 0;
2690e3adcf8fSFrançois Tigeot }
2691e3adcf8fSFrançois Tigeot 
269287df8fc6SFrançois Tigeot int intel_init_bsd_ring_buffer(struct intel_engine_cs *engine)
2693e3adcf8fSFrançois Tigeot {
269487df8fc6SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
2695686a02f1SFrançois Tigeot 
26961487f786SFrançois Tigeot 	intel_ring_default_vfuncs(dev_priv, engine);
26971487f786SFrançois Tigeot 
26981487f786SFrançois Tigeot 	if (INTEL_GEN(dev_priv) >= 6) {
2699686a02f1SFrançois Tigeot 		/* gen6 bsd needs a special wa for tail updates */
27001487f786SFrançois Tigeot 		if (IS_GEN6(dev_priv))
270171f41f3eSFrançois Tigeot 			engine->submit_request = gen6_bsd_submit_request;
270271f41f3eSFrançois Tigeot 		engine->emit_flush = gen6_bsd_ring_flush;
270387df8fc6SFrançois Tigeot 		if (INTEL_GEN(dev_priv) < 8)
27048621f407SFrançois Tigeot 			engine->irq_enable_mask = GT_BSD_USER_INTERRUPT;
2705686a02f1SFrançois Tigeot 	} else {
27068621f407SFrançois Tigeot 		engine->mmio_base = BSD_RING_BASE;
270771f41f3eSFrançois Tigeot 		engine->emit_flush = bsd_ring_flush;
27081487f786SFrançois Tigeot 		if (IS_GEN5(dev_priv))
27098621f407SFrançois Tigeot 			engine->irq_enable_mask = ILK_BSD_USER_INTERRUPT;
27101487f786SFrançois Tigeot 		else
27118621f407SFrançois Tigeot 			engine->irq_enable_mask = I915_BSD_USER_INTERRUPT;
2712686a02f1SFrançois Tigeot 	}
2713e3adcf8fSFrançois Tigeot 
271487df8fc6SFrançois Tigeot 	return intel_init_ring_buffer(engine);
2715e3adcf8fSFrançois Tigeot }
2716e3adcf8fSFrançois Tigeot 
2717ba55f2f5SFrançois Tigeot /**
2718477eb7f9SFrançois Tigeot  * Initialize the second BSD ring (eg. Broadwell GT3, Skylake GT3)
2719ba55f2f5SFrançois Tigeot  */
272087df8fc6SFrançois Tigeot int intel_init_bsd2_ring_buffer(struct intel_engine_cs *engine)
2721ba55f2f5SFrançois Tigeot {
272287df8fc6SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
27231487f786SFrançois Tigeot 
27241487f786SFrançois Tigeot 	intel_ring_default_vfuncs(dev_priv, engine);
27251487f786SFrançois Tigeot 
272671f41f3eSFrançois Tigeot 	engine->emit_flush = gen6_bsd_ring_flush;
2727ba55f2f5SFrançois Tigeot 
272887df8fc6SFrançois Tigeot 	return intel_init_ring_buffer(engine);
2729ba55f2f5SFrançois Tigeot }
2730ba55f2f5SFrançois Tigeot 
273187df8fc6SFrançois Tigeot int intel_init_blt_ring_buffer(struct intel_engine_cs *engine)
2732e3adcf8fSFrançois Tigeot {
273387df8fc6SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
27341487f786SFrançois Tigeot 
27351487f786SFrançois Tigeot 	intel_ring_default_vfuncs(dev_priv, engine);
27361487f786SFrançois Tigeot 
273771f41f3eSFrançois Tigeot 	engine->emit_flush = gen6_ring_flush;
273887df8fc6SFrançois Tigeot 	if (INTEL_GEN(dev_priv) < 8)
27398621f407SFrançois Tigeot 		engine->irq_enable_mask = GT_BLT_USER_INTERRUPT;
27405d0b1887SFrançois Tigeot 
274187df8fc6SFrançois Tigeot 	return intel_init_ring_buffer(engine);
27425d0b1887SFrançois Tigeot }
27435d0b1887SFrançois Tigeot 
274487df8fc6SFrançois Tigeot int intel_init_vebox_ring_buffer(struct intel_engine_cs *engine)
27455d0b1887SFrançois Tigeot {
274687df8fc6SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
27479edbd4a0SFrançois Tigeot 
27481487f786SFrançois Tigeot 	intel_ring_default_vfuncs(dev_priv, engine);
27491487f786SFrançois Tigeot 
275071f41f3eSFrançois Tigeot 	engine->emit_flush = gen6_ring_flush;
27511487f786SFrançois Tigeot 
275287df8fc6SFrançois Tigeot 	if (INTEL_GEN(dev_priv) < 8) {
27538621f407SFrançois Tigeot 		engine->irq_enable_mask = PM_VEBOX_USER_INTERRUPT;
2754303bf270SFrançois Tigeot 		engine->irq_enable = hsw_vebox_irq_enable;
2755303bf270SFrançois Tigeot 		engine->irq_disable = hsw_vebox_irq_disable;
275624edb884SFrançois Tigeot 	}
2757e3adcf8fSFrançois Tigeot 
275887df8fc6SFrançois Tigeot 	return intel_init_ring_buffer(engine);
2759e3adcf8fSFrançois Tigeot }
2760