xref: /dflybsd-src/sys/dev/drm/i915/intel_ringbuffer.c (revision a85cb24f18e3804e75ab8bcda7692564d0563317)
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 
42*a85cb24fSFrançois Tigeot static 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 {
52*a85cb24fSFrançois Tigeot 	ring->space = __intel_ring_space(ring->head, ring->emit, ring->size);
539edbd4a0SFrançois Tigeot }
549edbd4a0SFrançois Tigeot 
55e3adcf8fSFrançois Tigeot static int
5671f41f3eSFrançois Tigeot gen2_render_ring_flush(struct drm_i915_gem_request *req, u32 mode)
57686a02f1SFrançois Tigeot {
58*a85cb24fSFrançois Tigeot 	u32 cmd, *cs;
59686a02f1SFrançois Tigeot 
60686a02f1SFrançois Tigeot 	cmd = MI_FLUSH;
61686a02f1SFrançois Tigeot 
6271f41f3eSFrançois Tigeot 	if (mode & EMIT_INVALIDATE)
63686a02f1SFrançois Tigeot 		cmd |= MI_READ_FLUSH;
64686a02f1SFrançois Tigeot 
65*a85cb24fSFrançois Tigeot 	cs = intel_ring_begin(req, 2);
66*a85cb24fSFrançois Tigeot 	if (IS_ERR(cs))
67*a85cb24fSFrançois Tigeot 		return PTR_ERR(cs);
68686a02f1SFrançois Tigeot 
69*a85cb24fSFrançois Tigeot 	*cs++ = cmd;
70*a85cb24fSFrançois Tigeot 	*cs++ = MI_NOOP;
71*a85cb24fSFrançois Tigeot 	intel_ring_advance(req, cs);
72686a02f1SFrançois Tigeot 
73686a02f1SFrançois Tigeot 	return 0;
74686a02f1SFrançois Tigeot }
75686a02f1SFrançois Tigeot 
76686a02f1SFrançois Tigeot static int
7771f41f3eSFrançois Tigeot gen4_render_ring_flush(struct drm_i915_gem_request *req, u32 mode)
78e3adcf8fSFrançois Tigeot {
79*a85cb24fSFrançois Tigeot 	u32 cmd, *cs;
80e3adcf8fSFrançois Tigeot 
81e3adcf8fSFrançois Tigeot 	/*
82e3adcf8fSFrançois Tigeot 	 * read/write caches:
83e3adcf8fSFrançois Tigeot 	 *
84e3adcf8fSFrançois Tigeot 	 * I915_GEM_DOMAIN_RENDER is always invalidated, but is
85e3adcf8fSFrançois Tigeot 	 * only flushed if MI_NO_WRITE_FLUSH is unset.  On 965, it is
86e3adcf8fSFrançois Tigeot 	 * also flushed at 2d versus 3d pipeline switches.
87e3adcf8fSFrançois Tigeot 	 *
88e3adcf8fSFrançois Tigeot 	 * read-only caches:
89e3adcf8fSFrançois Tigeot 	 *
90e3adcf8fSFrançois Tigeot 	 * I915_GEM_DOMAIN_SAMPLER is flushed on pre-965 if
91e3adcf8fSFrançois Tigeot 	 * MI_READ_FLUSH is set, and is always flushed on 965.
92e3adcf8fSFrançois Tigeot 	 *
93e3adcf8fSFrançois Tigeot 	 * I915_GEM_DOMAIN_COMMAND may not exist?
94e3adcf8fSFrançois Tigeot 	 *
95e3adcf8fSFrançois Tigeot 	 * I915_GEM_DOMAIN_INSTRUCTION, which exists on 965, is
96e3adcf8fSFrançois Tigeot 	 * invalidated when MI_EXE_FLUSH is set.
97e3adcf8fSFrançois Tigeot 	 *
98e3adcf8fSFrançois Tigeot 	 * I915_GEM_DOMAIN_VERTEX, which exists on 965, is
99e3adcf8fSFrançois Tigeot 	 * invalidated with every MI_FLUSH.
100e3adcf8fSFrançois Tigeot 	 *
101e3adcf8fSFrançois Tigeot 	 * TLBs:
102e3adcf8fSFrançois Tigeot 	 *
103e3adcf8fSFrançois Tigeot 	 * On 965, TLBs associated with I915_GEM_DOMAIN_COMMAND
104e3adcf8fSFrançois Tigeot 	 * and I915_GEM_DOMAIN_CPU in are invalidated at PTE write and
105e3adcf8fSFrançois Tigeot 	 * I915_GEM_DOMAIN_RENDER and I915_GEM_DOMAIN_SAMPLER
106e3adcf8fSFrançois Tigeot 	 * are flushed at any MI_FLUSH.
107e3adcf8fSFrançois Tigeot 	 */
108e3adcf8fSFrançois Tigeot 
10971f41f3eSFrançois Tigeot 	cmd = MI_FLUSH;
11071f41f3eSFrançois Tigeot 	if (mode & EMIT_INVALIDATE) {
111e3adcf8fSFrançois Tigeot 		cmd |= MI_EXE_FLUSH;
11271f41f3eSFrançois Tigeot 		if (IS_G4X(req->i915) || IS_GEN5(req->i915))
113e3adcf8fSFrançois Tigeot 			cmd |= MI_INVALIDATE_ISP;
11471f41f3eSFrançois Tigeot 	}
115e3adcf8fSFrançois Tigeot 
116*a85cb24fSFrançois Tigeot 	cs = intel_ring_begin(req, 2);
117*a85cb24fSFrançois Tigeot 	if (IS_ERR(cs))
118*a85cb24fSFrançois Tigeot 		return PTR_ERR(cs);
119e3adcf8fSFrançois Tigeot 
120*a85cb24fSFrançois Tigeot 	*cs++ = cmd;
121*a85cb24fSFrançois Tigeot 	*cs++ = MI_NOOP;
122*a85cb24fSFrançois Tigeot 	intel_ring_advance(req, cs);
123e3adcf8fSFrançois Tigeot 
124e3adcf8fSFrançois Tigeot 	return 0;
125e3adcf8fSFrançois Tigeot }
126e3adcf8fSFrançois Tigeot 
127e3adcf8fSFrançois Tigeot /**
128e3adcf8fSFrançois Tigeot  * Emits a PIPE_CONTROL with a non-zero post-sync operation, for
129e3adcf8fSFrançois Tigeot  * implementing two workarounds on gen6.  From section 1.4.7.1
130e3adcf8fSFrançois Tigeot  * "PIPE_CONTROL" of the Sandy Bridge PRM volume 2 part 1:
131e3adcf8fSFrançois Tigeot  *
132e3adcf8fSFrançois Tigeot  * [DevSNB-C+{W/A}] Before any depth stall flush (including those
133e3adcf8fSFrançois Tigeot  * produced by non-pipelined state commands), software needs to first
134e3adcf8fSFrançois Tigeot  * send a PIPE_CONTROL with no bits set except Post-Sync Operation !=
135e3adcf8fSFrançois Tigeot  * 0.
136e3adcf8fSFrançois Tigeot  *
137e3adcf8fSFrançois Tigeot  * [Dev-SNB{W/A}]: Before a PIPE_CONTROL with Write Cache Flush Enable
138e3adcf8fSFrançois Tigeot  * =1, a PIPE_CONTROL with any non-zero post-sync-op is required.
139e3adcf8fSFrançois Tigeot  *
140e3adcf8fSFrançois Tigeot  * And the workaround for these two requires this workaround first:
141e3adcf8fSFrançois Tigeot  *
142e3adcf8fSFrançois Tigeot  * [Dev-SNB{W/A}]: Pipe-control with CS-stall bit set must be sent
143e3adcf8fSFrançois Tigeot  * BEFORE the pipe-control with a post-sync op and no write-cache
144e3adcf8fSFrançois Tigeot  * flushes.
145e3adcf8fSFrançois Tigeot  *
146e3adcf8fSFrançois Tigeot  * And this last workaround is tricky because of the requirements on
147e3adcf8fSFrançois Tigeot  * that bit.  From section 1.4.7.2.3 "Stall" of the Sandy Bridge PRM
148e3adcf8fSFrançois Tigeot  * volume 2 part 1:
149e3adcf8fSFrançois Tigeot  *
150e3adcf8fSFrançois Tigeot  *     "1 of the following must also be set:
151e3adcf8fSFrançois Tigeot  *      - Render Target Cache Flush Enable ([12] of DW1)
152e3adcf8fSFrançois Tigeot  *      - Depth Cache Flush Enable ([0] of DW1)
153e3adcf8fSFrançois Tigeot  *      - Stall at Pixel Scoreboard ([1] of DW1)
154e3adcf8fSFrançois Tigeot  *      - Depth Stall ([13] of DW1)
155e3adcf8fSFrançois Tigeot  *      - Post-Sync Operation ([13] of DW1)
156e3adcf8fSFrançois Tigeot  *      - Notify Enable ([8] of DW1)"
157e3adcf8fSFrançois Tigeot  *
158e3adcf8fSFrançois Tigeot  * The cache flushes require the workaround flush that triggered this
159e3adcf8fSFrançois Tigeot  * one, so we can't use it.  Depth stall would trigger the same.
160e3adcf8fSFrançois Tigeot  * Post-sync nonzero is what triggered this second workaround, so we
161e3adcf8fSFrançois Tigeot  * can't use that one either.  Notify enable is IRQs, which aren't
162e3adcf8fSFrançois Tigeot  * really our business.  That leaves only stall at scoreboard.
163e3adcf8fSFrançois Tigeot  */
164e3adcf8fSFrançois Tigeot static int
165a05eeebfSFrançois Tigeot intel_emit_post_sync_nonzero_flush(struct drm_i915_gem_request *req)
166e3adcf8fSFrançois Tigeot {
16771f41f3eSFrançois Tigeot 	u32 scratch_addr =
1681e12ee3bSFrançois Tigeot 		i915_ggtt_offset(req->engine->scratch) + 2 * CACHELINE_BYTES;
169*a85cb24fSFrançois Tigeot 	u32 *cs;
170e3adcf8fSFrançois Tigeot 
171*a85cb24fSFrançois Tigeot 	cs = intel_ring_begin(req, 6);
172*a85cb24fSFrançois Tigeot 	if (IS_ERR(cs))
173*a85cb24fSFrançois Tigeot 		return PTR_ERR(cs);
174e3adcf8fSFrançois Tigeot 
175*a85cb24fSFrançois Tigeot 	*cs++ = GFX_OP_PIPE_CONTROL(5);
176*a85cb24fSFrançois Tigeot 	*cs++ = PIPE_CONTROL_CS_STALL | PIPE_CONTROL_STALL_AT_SCOREBOARD;
177*a85cb24fSFrançois Tigeot 	*cs++ = scratch_addr | PIPE_CONTROL_GLOBAL_GTT;
178*a85cb24fSFrançois Tigeot 	*cs++ = 0; /* low dword */
179*a85cb24fSFrançois Tigeot 	*cs++ = 0; /* high dword */
180*a85cb24fSFrançois Tigeot 	*cs++ = MI_NOOP;
181*a85cb24fSFrançois Tigeot 	intel_ring_advance(req, cs);
182e3adcf8fSFrançois Tigeot 
183*a85cb24fSFrançois Tigeot 	cs = intel_ring_begin(req, 6);
184*a85cb24fSFrançois Tigeot 	if (IS_ERR(cs))
185*a85cb24fSFrançois Tigeot 		return PTR_ERR(cs);
186e3adcf8fSFrançois Tigeot 
187*a85cb24fSFrançois Tigeot 	*cs++ = GFX_OP_PIPE_CONTROL(5);
188*a85cb24fSFrançois Tigeot 	*cs++ = PIPE_CONTROL_QW_WRITE;
189*a85cb24fSFrançois Tigeot 	*cs++ = scratch_addr | PIPE_CONTROL_GLOBAL_GTT;
190*a85cb24fSFrançois Tigeot 	*cs++ = 0;
191*a85cb24fSFrançois Tigeot 	*cs++ = 0;
192*a85cb24fSFrançois Tigeot 	*cs++ = MI_NOOP;
193*a85cb24fSFrançois Tigeot 	intel_ring_advance(req, cs);
194e3adcf8fSFrançois Tigeot 
195e3adcf8fSFrançois Tigeot 	return 0;
196e3adcf8fSFrançois Tigeot }
197e3adcf8fSFrançois Tigeot 
198e3adcf8fSFrançois Tigeot static int
19971f41f3eSFrançois Tigeot gen6_render_ring_flush(struct drm_i915_gem_request *req, u32 mode)
200e3adcf8fSFrançois Tigeot {
20171f41f3eSFrançois Tigeot 	u32 scratch_addr =
2021e12ee3bSFrançois Tigeot 		i915_ggtt_offset(req->engine->scratch) + 2 * CACHELINE_BYTES;
203*a85cb24fSFrançois Tigeot 	u32 *cs, flags = 0;
204e3adcf8fSFrançois Tigeot 	int ret;
205e3adcf8fSFrançois Tigeot 
206e3adcf8fSFrançois Tigeot 	/* Force SNB workarounds for PIPE_CONTROL flushes */
207a05eeebfSFrançois Tigeot 	ret = intel_emit_post_sync_nonzero_flush(req);
208686a02f1SFrançois Tigeot 	if (ret)
209686a02f1SFrançois Tigeot 		return ret;
210e3adcf8fSFrançois Tigeot 
211e3adcf8fSFrançois Tigeot 	/* Just flush everything.  Experiments have shown that reducing the
212e3adcf8fSFrançois Tigeot 	 * number of bits based on the write domains has little performance
213e3adcf8fSFrançois Tigeot 	 * impact.
214e3adcf8fSFrançois Tigeot 	 */
21571f41f3eSFrançois Tigeot 	if (mode & EMIT_FLUSH) {
216e3adcf8fSFrançois Tigeot 		flags |= PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH;
217b5c29a34SFrançois Tigeot 		flags |= PIPE_CONTROL_DEPTH_CACHE_FLUSH;
218b5c29a34SFrançois Tigeot 		/*
219b5c29a34SFrançois Tigeot 		 * Ensure that any following seqno writes only happen
220b5c29a34SFrançois Tigeot 		 * when the render cache is indeed flushed.
221b5c29a34SFrançois Tigeot 		 */
222b5c29a34SFrançois Tigeot 		flags |= PIPE_CONTROL_CS_STALL;
223b5c29a34SFrançois Tigeot 	}
22471f41f3eSFrançois Tigeot 	if (mode & EMIT_INVALIDATE) {
225686a02f1SFrançois Tigeot 		flags |= PIPE_CONTROL_TLB_INVALIDATE;
226e3adcf8fSFrançois Tigeot 		flags |= PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE;
227e3adcf8fSFrançois Tigeot 		flags |= PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE;
228e3adcf8fSFrançois Tigeot 		flags |= PIPE_CONTROL_VF_CACHE_INVALIDATE;
229e3adcf8fSFrançois Tigeot 		flags |= PIPE_CONTROL_CONST_CACHE_INVALIDATE;
230e3adcf8fSFrançois Tigeot 		flags |= PIPE_CONTROL_STATE_CACHE_INVALIDATE;
231686a02f1SFrançois Tigeot 		/*
232b5c29a34SFrançois Tigeot 		 * TLB invalidate requires a post-sync write.
233686a02f1SFrançois Tigeot 		 */
234b5c29a34SFrançois Tigeot 		flags |= PIPE_CONTROL_QW_WRITE | PIPE_CONTROL_CS_STALL;
235b5c29a34SFrançois Tigeot 	}
236e3adcf8fSFrançois Tigeot 
237*a85cb24fSFrançois Tigeot 	cs = intel_ring_begin(req, 4);
238*a85cb24fSFrançois Tigeot 	if (IS_ERR(cs))
239*a85cb24fSFrançois Tigeot 		return PTR_ERR(cs);
240e3adcf8fSFrançois Tigeot 
241*a85cb24fSFrançois Tigeot 	*cs++ = GFX_OP_PIPE_CONTROL(4);
242*a85cb24fSFrançois Tigeot 	*cs++ = flags;
243*a85cb24fSFrançois Tigeot 	*cs++ = scratch_addr | PIPE_CONTROL_GLOBAL_GTT;
244*a85cb24fSFrançois Tigeot 	*cs++ = 0;
245*a85cb24fSFrançois Tigeot 	intel_ring_advance(req, cs);
246b5c29a34SFrançois Tigeot 
247b5c29a34SFrançois Tigeot 	return 0;
248b5c29a34SFrançois Tigeot }
249b5c29a34SFrançois Tigeot 
250b5c29a34SFrançois Tigeot static int
251a05eeebfSFrançois Tigeot gen7_render_ring_cs_stall_wa(struct drm_i915_gem_request *req)
252b5c29a34SFrançois Tigeot {
253*a85cb24fSFrançois Tigeot 	u32 *cs;
254b5c29a34SFrançois Tigeot 
255*a85cb24fSFrançois Tigeot 	cs = intel_ring_begin(req, 4);
256*a85cb24fSFrançois Tigeot 	if (IS_ERR(cs))
257*a85cb24fSFrançois Tigeot 		return PTR_ERR(cs);
258b5c29a34SFrançois Tigeot 
259*a85cb24fSFrançois Tigeot 	*cs++ = GFX_OP_PIPE_CONTROL(4);
260*a85cb24fSFrançois Tigeot 	*cs++ = PIPE_CONTROL_CS_STALL | PIPE_CONTROL_STALL_AT_SCOREBOARD;
261*a85cb24fSFrançois Tigeot 	*cs++ = 0;
262*a85cb24fSFrançois Tigeot 	*cs++ = 0;
263*a85cb24fSFrançois Tigeot 	intel_ring_advance(req, cs);
264b5c29a34SFrançois Tigeot 
265b5c29a34SFrançois Tigeot 	return 0;
266b5c29a34SFrançois Tigeot }
267b5c29a34SFrançois Tigeot 
268b5c29a34SFrançois Tigeot static int
26971f41f3eSFrançois Tigeot gen7_render_ring_flush(struct drm_i915_gem_request *req, u32 mode)
270b5c29a34SFrançois Tigeot {
27171f41f3eSFrançois Tigeot 	u32 scratch_addr =
2721e12ee3bSFrançois Tigeot 		i915_ggtt_offset(req->engine->scratch) + 2 * CACHELINE_BYTES;
273*a85cb24fSFrançois Tigeot 	u32 *cs, flags = 0;
274b5c29a34SFrançois Tigeot 
275b5c29a34SFrançois Tigeot 	/*
276b5c29a34SFrançois Tigeot 	 * Ensure that any following seqno writes only happen when the render
277b5c29a34SFrançois Tigeot 	 * cache is indeed flushed.
278b5c29a34SFrançois Tigeot 	 *
279b5c29a34SFrançois Tigeot 	 * Workaround: 4th PIPE_CONTROL command (except the ones with only
280b5c29a34SFrançois Tigeot 	 * read-cache invalidate bits set) must have the CS_STALL bit set. We
281b5c29a34SFrançois Tigeot 	 * don't try to be clever and just set it unconditionally.
282b5c29a34SFrançois Tigeot 	 */
283b5c29a34SFrançois Tigeot 	flags |= PIPE_CONTROL_CS_STALL;
284b5c29a34SFrançois Tigeot 
285b5c29a34SFrançois Tigeot 	/* Just flush everything.  Experiments have shown that reducing the
286b5c29a34SFrançois Tigeot 	 * number of bits based on the write domains has little performance
287b5c29a34SFrançois Tigeot 	 * impact.
288b5c29a34SFrançois Tigeot 	 */
28971f41f3eSFrançois Tigeot 	if (mode & EMIT_FLUSH) {
290b5c29a34SFrançois Tigeot 		flags |= PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH;
291b5c29a34SFrançois Tigeot 		flags |= PIPE_CONTROL_DEPTH_CACHE_FLUSH;
292aee94f86SFrançois Tigeot 		flags |= PIPE_CONTROL_DC_FLUSH_ENABLE;
293b49c8cf9SFrançois Tigeot 		flags |= PIPE_CONTROL_FLUSH_ENABLE;
294b5c29a34SFrançois Tigeot 	}
29571f41f3eSFrançois Tigeot 	if (mode & EMIT_INVALIDATE) {
296b5c29a34SFrançois Tigeot 		flags |= PIPE_CONTROL_TLB_INVALIDATE;
297b5c29a34SFrançois Tigeot 		flags |= PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE;
298b5c29a34SFrançois Tigeot 		flags |= PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE;
299b5c29a34SFrançois Tigeot 		flags |= PIPE_CONTROL_VF_CACHE_INVALIDATE;
300b5c29a34SFrançois Tigeot 		flags |= PIPE_CONTROL_CONST_CACHE_INVALIDATE;
301b5c29a34SFrançois Tigeot 		flags |= PIPE_CONTROL_STATE_CACHE_INVALIDATE;
3022c9916cdSFrançois Tigeot 		flags |= PIPE_CONTROL_MEDIA_STATE_CLEAR;
303b5c29a34SFrançois Tigeot 		/*
304b5c29a34SFrançois Tigeot 		 * TLB invalidate requires a post-sync write.
305b5c29a34SFrançois Tigeot 		 */
306b5c29a34SFrançois Tigeot 		flags |= PIPE_CONTROL_QW_WRITE;
307a2fdbec6SFrançois Tigeot 		flags |= PIPE_CONTROL_GLOBAL_GTT_IVB;
308b5c29a34SFrançois Tigeot 
3090dbf0ea8SMatthew Dillon 		flags |= PIPE_CONTROL_STALL_AT_SCOREBOARD;
3100dbf0ea8SMatthew Dillon 
311b5c29a34SFrançois Tigeot 		/* Workaround: we must issue a pipe_control with CS-stall bit
312b5c29a34SFrançois Tigeot 		 * set before a pipe_control command that has the state cache
313b5c29a34SFrançois Tigeot 		 * invalidate bit set. */
314a05eeebfSFrançois Tigeot 		gen7_render_ring_cs_stall_wa(req);
315b5c29a34SFrançois Tigeot 	}
316b5c29a34SFrançois Tigeot 
317*a85cb24fSFrançois Tigeot 	cs = intel_ring_begin(req, 4);
318*a85cb24fSFrançois Tigeot 	if (IS_ERR(cs))
319*a85cb24fSFrançois Tigeot 		return PTR_ERR(cs);
320b5c29a34SFrançois Tigeot 
321*a85cb24fSFrançois Tigeot 	*cs++ = GFX_OP_PIPE_CONTROL(4);
322*a85cb24fSFrançois Tigeot 	*cs++ = flags;
323*a85cb24fSFrançois Tigeot 	*cs++ = scratch_addr;
324*a85cb24fSFrançois Tigeot 	*cs++ = 0;
325*a85cb24fSFrançois Tigeot 	intel_ring_advance(req, cs);
32624edb884SFrançois Tigeot 
32724edb884SFrançois Tigeot 	return 0;
32824edb884SFrançois Tigeot }
32924edb884SFrançois Tigeot 
33024edb884SFrançois Tigeot static int
33171f41f3eSFrançois Tigeot gen8_render_ring_flush(struct drm_i915_gem_request *req, u32 mode)
3329edbd4a0SFrançois Tigeot {
333*a85cb24fSFrançois Tigeot 	u32 flags;
334*a85cb24fSFrançois Tigeot 	u32 *cs;
3359edbd4a0SFrançois Tigeot 
336*a85cb24fSFrançois Tigeot 	cs = intel_ring_begin(req, mode & EMIT_INVALIDATE ? 12 : 6);
337*a85cb24fSFrançois Tigeot 	if (IS_ERR(cs))
338*a85cb24fSFrançois Tigeot 		return PTR_ERR(cs);
339*a85cb24fSFrançois Tigeot 
340*a85cb24fSFrançois Tigeot 	flags = PIPE_CONTROL_CS_STALL;
3419edbd4a0SFrançois Tigeot 
34271f41f3eSFrançois Tigeot 	if (mode & EMIT_FLUSH) {
3439edbd4a0SFrançois Tigeot 		flags |= PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH;
3449edbd4a0SFrançois Tigeot 		flags |= PIPE_CONTROL_DEPTH_CACHE_FLUSH;
345aee94f86SFrançois Tigeot 		flags |= PIPE_CONTROL_DC_FLUSH_ENABLE;
346b49c8cf9SFrançois Tigeot 		flags |= PIPE_CONTROL_FLUSH_ENABLE;
3479edbd4a0SFrançois Tigeot 	}
34871f41f3eSFrançois Tigeot 	if (mode & EMIT_INVALIDATE) {
3499edbd4a0SFrançois Tigeot 		flags |= PIPE_CONTROL_TLB_INVALIDATE;
3509edbd4a0SFrançois Tigeot 		flags |= PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE;
3519edbd4a0SFrançois Tigeot 		flags |= PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE;
3529edbd4a0SFrançois Tigeot 		flags |= PIPE_CONTROL_VF_CACHE_INVALIDATE;
3539edbd4a0SFrançois Tigeot 		flags |= PIPE_CONTROL_CONST_CACHE_INVALIDATE;
3549edbd4a0SFrançois Tigeot 		flags |= PIPE_CONTROL_STATE_CACHE_INVALIDATE;
3559edbd4a0SFrançois Tigeot 		flags |= PIPE_CONTROL_QW_WRITE;
3569edbd4a0SFrançois Tigeot 		flags |= PIPE_CONTROL_GLOBAL_GTT_IVB;
3579edbd4a0SFrançois Tigeot 
35824edb884SFrançois Tigeot 		/* WaCsStallBeforeStateCacheInvalidate:bdw,chv */
359*a85cb24fSFrançois Tigeot 		cs = gen8_emit_pipe_control(cs,
36024edb884SFrançois Tigeot 					    PIPE_CONTROL_CS_STALL |
36124edb884SFrançois Tigeot 					    PIPE_CONTROL_STALL_AT_SCOREBOARD,
36224edb884SFrançois Tigeot 					    0);
36324edb884SFrançois Tigeot 	}
3649edbd4a0SFrançois Tigeot 
365*a85cb24fSFrançois Tigeot 	cs = gen8_emit_pipe_control(cs, flags,
366*a85cb24fSFrançois Tigeot 				    i915_ggtt_offset(req->engine->scratch) +
367*a85cb24fSFrançois Tigeot 				    2 * CACHELINE_BYTES);
368*a85cb24fSFrançois Tigeot 
369*a85cb24fSFrançois Tigeot 	intel_ring_advance(req, cs);
370*a85cb24fSFrançois Tigeot 
371*a85cb24fSFrançois Tigeot 	return 0;
3729edbd4a0SFrançois Tigeot }
3739edbd4a0SFrançois Tigeot 
3748621f407SFrançois Tigeot static void ring_setup_phys_status_page(struct intel_engine_cs *engine)
3755d0b1887SFrançois Tigeot {
3761487f786SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
3775d0b1887SFrançois Tigeot 	u32 addr;
3785d0b1887SFrançois Tigeot 
3795d0b1887SFrançois Tigeot 	addr = dev_priv->status_page_dmah->busaddr;
3801487f786SFrançois Tigeot 	if (INTEL_GEN(dev_priv) >= 4)
3815d0b1887SFrançois Tigeot 		addr |= (dev_priv->status_page_dmah->busaddr >> 28) & 0xf0;
3825d0b1887SFrançois Tigeot 	I915_WRITE(HWS_PGA, addr);
3835d0b1887SFrançois Tigeot }
3845d0b1887SFrançois Tigeot 
3858621f407SFrançois Tigeot static void intel_ring_setup_status_page(struct intel_engine_cs *engine)
386477eb7f9SFrançois Tigeot {
3871487f786SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
388aee94f86SFrançois Tigeot 	i915_reg_t mmio;
389477eb7f9SFrançois Tigeot 
390477eb7f9SFrançois Tigeot 	/* The ring status page addresses are no longer next to the rest of
391477eb7f9SFrançois Tigeot 	 * the ring registers as of gen7.
392477eb7f9SFrançois Tigeot 	 */
3931487f786SFrançois Tigeot 	if (IS_GEN7(dev_priv)) {
3948621f407SFrançois Tigeot 		switch (engine->id) {
395477eb7f9SFrançois Tigeot 		case RCS:
396477eb7f9SFrançois Tigeot 			mmio = RENDER_HWS_PGA_GEN7;
397477eb7f9SFrançois Tigeot 			break;
398477eb7f9SFrançois Tigeot 		case BCS:
399477eb7f9SFrançois Tigeot 			mmio = BLT_HWS_PGA_GEN7;
400477eb7f9SFrançois Tigeot 			break;
401477eb7f9SFrançois Tigeot 		/*
402477eb7f9SFrançois Tigeot 		 * VCS2 actually doesn't exist on Gen7. Only shut up
403477eb7f9SFrançois Tigeot 		 * gcc switch check warning
404477eb7f9SFrançois Tigeot 		 */
405477eb7f9SFrançois Tigeot 		case VCS2:
406477eb7f9SFrançois Tigeot 		case VCS:
407477eb7f9SFrançois Tigeot 			mmio = BSD_HWS_PGA_GEN7;
408477eb7f9SFrançois Tigeot 			break;
409477eb7f9SFrançois Tigeot 		case VECS:
410477eb7f9SFrançois Tigeot 			mmio = VEBOX_HWS_PGA_GEN7;
411477eb7f9SFrançois Tigeot 			break;
412477eb7f9SFrançois Tigeot 		}
4131487f786SFrançois Tigeot 	} else if (IS_GEN6(dev_priv)) {
4148621f407SFrançois Tigeot 		mmio = RING_HWS_PGA_GEN6(engine->mmio_base);
415477eb7f9SFrançois Tigeot 	} else {
416477eb7f9SFrançois Tigeot 		/* XXX: gen8 returns to sanity */
4178621f407SFrançois Tigeot 		mmio = RING_HWS_PGA(engine->mmio_base);
418477eb7f9SFrançois Tigeot 	}
419477eb7f9SFrançois Tigeot 
4201e12ee3bSFrançois Tigeot 	I915_WRITE(mmio, engine->status_page.ggtt_offset);
421477eb7f9SFrançois Tigeot 	POSTING_READ(mmio);
422477eb7f9SFrançois Tigeot 
423477eb7f9SFrançois Tigeot 	/*
424477eb7f9SFrançois Tigeot 	 * Flush the TLB for this page
425477eb7f9SFrançois Tigeot 	 *
426477eb7f9SFrançois Tigeot 	 * FIXME: These two bits have disappeared on gen8, so a question
427477eb7f9SFrançois Tigeot 	 * arises: do we still need this and if so how should we go about
428477eb7f9SFrançois Tigeot 	 * invalidating the TLB?
429477eb7f9SFrançois Tigeot 	 */
4301487f786SFrançois Tigeot 	if (IS_GEN(dev_priv, 6, 7)) {
4318621f407SFrançois Tigeot 		i915_reg_t reg = RING_INSTPM(engine->mmio_base);
432477eb7f9SFrançois Tigeot 
433477eb7f9SFrançois Tigeot 		/* ring should be idle before issuing a sync flush*/
4348621f407SFrançois Tigeot 		WARN_ON((I915_READ_MODE(engine) & MODE_IDLE) == 0);
435477eb7f9SFrançois Tigeot 
436477eb7f9SFrançois Tigeot 		I915_WRITE(reg,
437477eb7f9SFrançois Tigeot 			   _MASKED_BIT_ENABLE(INSTPM_TLB_INVALIDATE |
438477eb7f9SFrançois Tigeot 					      INSTPM_SYNC_FLUSH));
4391487f786SFrançois Tigeot 		if (intel_wait_for_register(dev_priv,
4401487f786SFrançois Tigeot 					    reg, INSTPM_SYNC_FLUSH, 0,
441477eb7f9SFrançois Tigeot 					    1000))
442477eb7f9SFrançois Tigeot 			DRM_ERROR("%s: wait for SyncFlush to complete for TLB invalidation timed out\n",
4438621f407SFrançois Tigeot 				  engine->name);
444477eb7f9SFrançois Tigeot 	}
445477eb7f9SFrançois Tigeot }
446477eb7f9SFrançois Tigeot 
4478621f407SFrançois Tigeot static bool stop_ring(struct intel_engine_cs *engine)
448e3adcf8fSFrançois Tigeot {
4491487f786SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
450e3adcf8fSFrançois Tigeot 
4511e12ee3bSFrançois Tigeot 	if (INTEL_GEN(dev_priv) > 2) {
4528621f407SFrançois Tigeot 		I915_WRITE_MODE(engine, _MASKED_BIT_ENABLE(STOP_RING));
4531487f786SFrançois Tigeot 		if (intel_wait_for_register(dev_priv,
4541487f786SFrançois Tigeot 					    RING_MI_MODE(engine->mmio_base),
4551487f786SFrançois Tigeot 					    MODE_IDLE,
4561487f786SFrançois Tigeot 					    MODE_IDLE,
4571487f786SFrançois Tigeot 					    1000)) {
4588621f407SFrançois Tigeot 			DRM_ERROR("%s : timed out trying to stop ring\n",
4598621f407SFrançois Tigeot 				  engine->name);
4601b13d190SFrançois Tigeot 			/* Sometimes we observe that the idle flag is not
4611b13d190SFrançois Tigeot 			 * set even though the ring is empty. So double
4621b13d190SFrançois Tigeot 			 * check before giving up.
4631b13d190SFrançois Tigeot 			 */
4648621f407SFrançois Tigeot 			if (I915_READ_HEAD(engine) != I915_READ_TAIL(engine))
465ba55f2f5SFrançois Tigeot 				return false;
466ba55f2f5SFrançois Tigeot 		}
467ba55f2f5SFrançois Tigeot 	}
468686a02f1SFrançois Tigeot 
4698621f407SFrançois Tigeot 	I915_WRITE_CTL(engine, 0);
4708621f407SFrançois Tigeot 	I915_WRITE_HEAD(engine, 0);
47171f41f3eSFrançois Tigeot 	I915_WRITE_TAIL(engine, 0);
472e3adcf8fSFrançois Tigeot 
4731e12ee3bSFrançois Tigeot 	if (INTEL_GEN(dev_priv) > 2) {
4748621f407SFrançois Tigeot 		(void)I915_READ_CTL(engine);
4758621f407SFrançois Tigeot 		I915_WRITE_MODE(engine, _MASKED_BIT_DISABLE(STOP_RING));
476ba55f2f5SFrançois Tigeot 	}
477e3adcf8fSFrançois Tigeot 
4788621f407SFrançois Tigeot 	return (I915_READ_HEAD(engine) & HEAD_ADDR) == 0;
479ba55f2f5SFrançois Tigeot }
480ba55f2f5SFrançois Tigeot 
4818621f407SFrançois Tigeot static int init_ring_common(struct intel_engine_cs *engine)
4828621f407SFrançois Tigeot {
4831487f786SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
48471f41f3eSFrançois Tigeot 	struct intel_ring *ring = engine->buffer;
485ba55f2f5SFrançois Tigeot 	int ret = 0;
486ba55f2f5SFrançois Tigeot 
4872c9916cdSFrançois Tigeot 	intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL);
488ba55f2f5SFrançois Tigeot 
4898621f407SFrançois Tigeot 	if (!stop_ring(engine)) {
490ba55f2f5SFrançois Tigeot 		/* G45 ring initialization often fails to reset head to zero */
491b5c29a34SFrançois Tigeot 		DRM_DEBUG_KMS("%s head not reset to zero "
492e3adcf8fSFrançois Tigeot 			      "ctl %08x head %08x tail %08x start %08x\n",
4938621f407SFrançois Tigeot 			      engine->name,
4948621f407SFrançois Tigeot 			      I915_READ_CTL(engine),
4958621f407SFrançois Tigeot 			      I915_READ_HEAD(engine),
4968621f407SFrançois Tigeot 			      I915_READ_TAIL(engine),
4978621f407SFrançois Tigeot 			      I915_READ_START(engine));
498e3adcf8fSFrançois Tigeot 
4998621f407SFrançois Tigeot 		if (!stop_ring(engine)) {
500e3adcf8fSFrançois Tigeot 			DRM_ERROR("failed to set %s head to zero "
501e3adcf8fSFrançois Tigeot 				  "ctl %08x head %08x tail %08x start %08x\n",
5028621f407SFrançois Tigeot 				  engine->name,
5038621f407SFrançois Tigeot 				  I915_READ_CTL(engine),
5048621f407SFrançois Tigeot 				  I915_READ_HEAD(engine),
5058621f407SFrançois Tigeot 				  I915_READ_TAIL(engine),
5068621f407SFrançois Tigeot 				  I915_READ_START(engine));
507686a02f1SFrançois Tigeot 			ret = -EIO;
508686a02f1SFrançois Tigeot 			goto out;
509e3adcf8fSFrançois Tigeot 		}
510ba55f2f5SFrançois Tigeot 	}
511ba55f2f5SFrançois Tigeot 
5121e12ee3bSFrançois Tigeot 	if (HWS_NEEDS_PHYSICAL(dev_priv))
5138621f407SFrançois Tigeot 		ring_setup_phys_status_page(engine);
5141e12ee3bSFrançois Tigeot 	else
5151e12ee3bSFrançois Tigeot 		intel_ring_setup_status_page(engine);
5161e12ee3bSFrançois Tigeot 
5171e12ee3bSFrançois Tigeot 	intel_engine_reset_breadcrumbs(engine);
518ba55f2f5SFrançois Tigeot 
5190f370975SMatthew Dillon 	/* Enforce ordering by reading HEAD register back */
5208621f407SFrançois Tigeot 	I915_READ_HEAD(engine);
5210f370975SMatthew Dillon 
522ba55f2f5SFrançois Tigeot 	/* Initialize the ring. This must happen _after_ we've cleared the ring
523ba55f2f5SFrançois Tigeot 	 * registers with the above sequence (the readback of the HEAD registers
524ba55f2f5SFrançois Tigeot 	 * also enforces ordering), otherwise the hw might lose the new ring
525ba55f2f5SFrançois Tigeot 	 * register values. */
5261e12ee3bSFrançois Tigeot 	I915_WRITE_START(engine, i915_ggtt_offset(ring->vma));
5271b13d190SFrançois Tigeot 
5281b13d190SFrançois Tigeot 	/* WaClearRingBufHeadRegAtInit:ctg,elk */
5298621f407SFrançois Tigeot 	if (I915_READ_HEAD(engine))
5301b13d190SFrançois Tigeot 		DRM_DEBUG("%s initialization failed [head=%08x], fudging\n",
5318621f407SFrançois Tigeot 			  engine->name, I915_READ_HEAD(engine));
5321b13d190SFrançois Tigeot 
5331e12ee3bSFrançois Tigeot 	intel_ring_update_space(ring);
5341e12ee3bSFrançois Tigeot 	I915_WRITE_HEAD(engine, ring->head);
5351e12ee3bSFrançois Tigeot 	I915_WRITE_TAIL(engine, ring->tail);
5361e12ee3bSFrançois Tigeot 	(void)I915_READ_TAIL(engine);
5371e12ee3bSFrançois Tigeot 
5381e12ee3bSFrançois Tigeot 	I915_WRITE_CTL(engine, RING_CTL_SIZE(ring->size) | RING_VALID);
539ba55f2f5SFrançois Tigeot 
540ba55f2f5SFrançois Tigeot 	/* If the head is still not zero, the ring is dead */
5411e12ee3bSFrançois Tigeot 	if (intel_wait_for_register_fw(dev_priv, RING_CTL(engine->mmio_base),
5421e12ee3bSFrançois Tigeot 				       RING_VALID, RING_VALID,
5431e12ee3bSFrançois Tigeot 				       50)) {
544ba55f2f5SFrançois Tigeot 		DRM_ERROR("%s initialization failed "
5451e12ee3bSFrançois Tigeot 			  "ctl %08x (valid? %d) head %08x [%08x] tail %08x [%08x] start %08x [expected %08x]\n",
5468621f407SFrançois Tigeot 			  engine->name,
5478621f407SFrançois Tigeot 			  I915_READ_CTL(engine),
5488621f407SFrançois Tigeot 			  I915_READ_CTL(engine) & RING_VALID,
5491e12ee3bSFrançois Tigeot 			  I915_READ_HEAD(engine), ring->head,
5501e12ee3bSFrançois Tigeot 			  I915_READ_TAIL(engine), ring->tail,
5518621f407SFrançois Tigeot 			  I915_READ_START(engine),
5521e12ee3bSFrançois Tigeot 			  i915_ggtt_offset(ring->vma));
553ba55f2f5SFrançois Tigeot 		ret = -EIO;
554ba55f2f5SFrançois Tigeot 		goto out;
555ba55f2f5SFrançois Tigeot 	}
556e3adcf8fSFrançois Tigeot 
5578621f407SFrançois Tigeot 	intel_engine_init_hangcheck(engine);
5585d0b1887SFrançois Tigeot 
559686a02f1SFrançois Tigeot out:
5602c9916cdSFrançois Tigeot 	intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL);
561686a02f1SFrançois Tigeot 
562686a02f1SFrançois Tigeot 	return ret;
563e3adcf8fSFrançois Tigeot }
564e3adcf8fSFrançois Tigeot 
5651e12ee3bSFrançois Tigeot static void reset_ring_common(struct intel_engine_cs *engine,
5661e12ee3bSFrançois Tigeot 			      struct drm_i915_gem_request *request)
5671b13d190SFrançois Tigeot {
568*a85cb24fSFrançois Tigeot 	/* Try to restore the logical GPU state to match the continuation
569*a85cb24fSFrançois Tigeot 	 * of the request queue. If we skip the context/PD restore, then
570*a85cb24fSFrançois Tigeot 	 * the next request may try to execute assuming that its context
571*a85cb24fSFrançois Tigeot 	 * is valid and loaded on the GPU and so may try to access invalid
572*a85cb24fSFrançois Tigeot 	 * memory, prompting repeated GPU hangs.
573*a85cb24fSFrançois Tigeot 	 *
574*a85cb24fSFrançois Tigeot 	 * If the request was guilty, we still restore the logical state
575*a85cb24fSFrançois Tigeot 	 * in case the next request requires it (e.g. the aliasing ppgtt),
576*a85cb24fSFrançois Tigeot 	 * but skip over the hung batch.
577*a85cb24fSFrançois Tigeot 	 *
578*a85cb24fSFrançois Tigeot 	 * If the request was innocent, we try to replay the request with
579*a85cb24fSFrançois Tigeot 	 * the restored context.
580*a85cb24fSFrançois Tigeot 	 */
581*a85cb24fSFrançois Tigeot 	if (request) {
582*a85cb24fSFrançois Tigeot 		struct drm_i915_private *dev_priv = request->i915;
583*a85cb24fSFrançois Tigeot 		struct intel_context *ce = &request->ctx->engine[engine->id];
584*a85cb24fSFrançois Tigeot 		struct i915_hw_ppgtt *ppgtt;
5851b13d190SFrançois Tigeot 
586*a85cb24fSFrançois Tigeot 		/* FIXME consider gen8 reset */
587*a85cb24fSFrançois Tigeot 
588*a85cb24fSFrançois Tigeot 		if (ce->state) {
589*a85cb24fSFrançois Tigeot 			I915_WRITE(CCID,
590*a85cb24fSFrançois Tigeot 				   i915_ggtt_offset(ce->state) |
591*a85cb24fSFrançois Tigeot 				   BIT(8) /* must be set! */ |
592*a85cb24fSFrançois Tigeot 				   CCID_EXTENDED_STATE_SAVE |
593*a85cb24fSFrançois Tigeot 				   CCID_EXTENDED_STATE_RESTORE |
594*a85cb24fSFrançois Tigeot 				   CCID_EN);
595e3adcf8fSFrançois Tigeot 		}
596e3adcf8fSFrançois Tigeot 
597*a85cb24fSFrançois Tigeot 		ppgtt = request->ctx->ppgtt ?: engine->i915->mm.aliasing_ppgtt;
598*a85cb24fSFrançois Tigeot 		if (ppgtt) {
599*a85cb24fSFrançois Tigeot 			u32 pd_offset = ppgtt->pd.base.ggtt_offset << 10;
6001b13d190SFrançois Tigeot 
601*a85cb24fSFrançois Tigeot 			I915_WRITE(RING_PP_DIR_DCLV(engine), PP_DIR_DCLV_2G);
602*a85cb24fSFrançois Tigeot 			I915_WRITE(RING_PP_DIR_BASE(engine), pd_offset);
6031b13d190SFrançois Tigeot 
604*a85cb24fSFrançois Tigeot 			/* Wait for the PD reload to complete */
605*a85cb24fSFrançois Tigeot 			if (intel_wait_for_register(dev_priv,
606*a85cb24fSFrançois Tigeot 						    RING_PP_DIR_BASE(engine),
607*a85cb24fSFrançois Tigeot 						    BIT(0), 0,
608*a85cb24fSFrançois Tigeot 						    10))
609*a85cb24fSFrançois Tigeot 				DRM_ERROR("Wait for reload of ppgtt page-directory timed out\n");
6101b13d190SFrançois Tigeot 
611*a85cb24fSFrançois Tigeot 			ppgtt->pd_dirty_rings &= ~intel_engine_flag(engine);
6122c9916cdSFrançois Tigeot 		}
6132c9916cdSFrançois Tigeot 
614*a85cb24fSFrançois Tigeot 		/* If the rq hung, jump to its breadcrumb and skip the batch */
615*a85cb24fSFrançois Tigeot 		if (request->fence.error == -EIO)
616*a85cb24fSFrançois Tigeot 			request->ring->head = request->postfix;
617*a85cb24fSFrançois Tigeot 	} else {
618*a85cb24fSFrançois Tigeot 		engine->legacy_active_context = NULL;
619*a85cb24fSFrançois Tigeot 	}
6202c9916cdSFrançois Tigeot }
6212c9916cdSFrançois Tigeot 
622a05eeebfSFrançois Tigeot static int intel_rcs_ctx_init(struct drm_i915_gem_request *req)
6232c9916cdSFrançois Tigeot {
6242c9916cdSFrançois Tigeot 	int ret;
6252c9916cdSFrançois Tigeot 
626a05eeebfSFrançois Tigeot 	ret = intel_ring_workarounds_emit(req);
6272c9916cdSFrançois Tigeot 	if (ret != 0)
6282c9916cdSFrançois Tigeot 		return ret;
6292c9916cdSFrançois Tigeot 
6304be47400SFrançois Tigeot 	ret = i915_gem_render_state_emit(req);
6312c9916cdSFrançois Tigeot 	if (ret)
6322c9916cdSFrançois Tigeot 		return ret;
633c0e85e96SFrançois Tigeot 
634c0e85e96SFrançois Tigeot 	return 0;
6352c9916cdSFrançois Tigeot }
6362c9916cdSFrançois Tigeot 
6378621f407SFrançois Tigeot static int init_render_ring(struct intel_engine_cs *engine)
638e3adcf8fSFrançois Tigeot {
6391487f786SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
6408621f407SFrançois Tigeot 	int ret = init_ring_common(engine);
64124edb884SFrançois Tigeot 	if (ret)
64224edb884SFrançois Tigeot 		return ret;
643e3adcf8fSFrançois Tigeot 
644ba55f2f5SFrançois Tigeot 	/* WaTimedSingleVertexDispatch:cl,bw,ctg,elk,ilk,snb */
6451487f786SFrançois Tigeot 	if (IS_GEN(dev_priv, 4, 6))
646f4e1c372SFrançois Tigeot 		I915_WRITE(MI_MODE, _MASKED_BIT_ENABLE(VS_TIMER_DISPATCH));
647f4e1c372SFrançois Tigeot 
648f4e1c372SFrançois Tigeot 	/* We need to disable the AsyncFlip performance optimisations in order
649f4e1c372SFrançois Tigeot 	 * to use MI_WAIT_FOR_EVENT within the CS. It should already be
650f4e1c372SFrançois Tigeot 	 * programmed to '1' on all products.
6515d0b1887SFrançois Tigeot 	 *
652a05eeebfSFrançois Tigeot 	 * WaDisableAsyncFlipPerfMode:snb,ivb,hsw,vlv
653f4e1c372SFrançois Tigeot 	 */
6541487f786SFrançois Tigeot 	if (IS_GEN(dev_priv, 6, 7))
655f4e1c372SFrançois Tigeot 		I915_WRITE(MI_MODE, _MASKED_BIT_ENABLE(ASYNC_FLIP_PERF_DISABLE));
656f4e1c372SFrançois Tigeot 
657f4e1c372SFrançois Tigeot 	/* Required for the hardware to program scanline values for waiting */
658ba55f2f5SFrançois Tigeot 	/* WaEnableFlushTlbInvalidationMode:snb */
6591487f786SFrançois Tigeot 	if (IS_GEN6(dev_priv))
660f4e1c372SFrançois Tigeot 		I915_WRITE(GFX_MODE,
661ba55f2f5SFrançois Tigeot 			   _MASKED_BIT_ENABLE(GFX_TLB_INVALIDATE_EXPLICIT));
662f4e1c372SFrançois Tigeot 
663ba55f2f5SFrançois Tigeot 	/* WaBCSVCSTlbInvalidationMode:ivb,vlv,hsw */
6641487f786SFrançois Tigeot 	if (IS_GEN7(dev_priv))
665e3adcf8fSFrançois Tigeot 		I915_WRITE(GFX_MODE_GEN7,
666ba55f2f5SFrançois Tigeot 			   _MASKED_BIT_ENABLE(GFX_TLB_INVALIDATE_EXPLICIT) |
667f4e1c372SFrançois Tigeot 			   _MASKED_BIT_ENABLE(GFX_REPLAY_MODE));
668e3adcf8fSFrançois Tigeot 
6691487f786SFrançois Tigeot 	if (IS_GEN6(dev_priv)) {
670e3adcf8fSFrançois Tigeot 		/* From the Sandybridge PRM, volume 1 part 3, page 24:
671e3adcf8fSFrançois Tigeot 		 * "If this bit is set, STCunit will have LRA as replacement
672e3adcf8fSFrançois Tigeot 		 *  policy. [...] This bit must be reset.  LRA replacement
673e3adcf8fSFrançois Tigeot 		 *  policy is not supported."
674e3adcf8fSFrançois Tigeot 		 */
675e3adcf8fSFrançois Tigeot 		I915_WRITE(CACHE_MODE_0,
676f4e1c372SFrançois Tigeot 			   _MASKED_BIT_DISABLE(CM0_STC_EVICT_DISABLE_LRA_SNB));
677e3adcf8fSFrançois Tigeot 	}
678e3adcf8fSFrançois Tigeot 
6791487f786SFrançois Tigeot 	if (IS_GEN(dev_priv, 6, 7))
680f4e1c372SFrançois Tigeot 		I915_WRITE(INSTPM, _MASKED_BIT_ENABLE(INSTPM_FORCE_ORDERING));
681f4e1c372SFrançois Tigeot 
682303bf270SFrançois Tigeot 	if (INTEL_INFO(dev_priv)->gen >= 6)
683303bf270SFrançois Tigeot 		I915_WRITE_IMR(engine, ~engine->irq_keep_mask);
684e3adcf8fSFrançois Tigeot 
6858621f407SFrançois Tigeot 	return init_workarounds_ring(engine);
686e3adcf8fSFrançois Tigeot }
687e3adcf8fSFrançois Tigeot 
6888621f407SFrançois Tigeot static void render_ring_cleanup(struct intel_engine_cs *engine)
689e3adcf8fSFrançois Tigeot {
6901487f786SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
69124edb884SFrançois Tigeot 
6921e12ee3bSFrançois Tigeot 	i915_vma_unpin_and_release(&dev_priv->semaphore);
693e3adcf8fSFrançois Tigeot }
694e3adcf8fSFrançois Tigeot 
695*a85cb24fSFrançois Tigeot static u32 *gen8_rcs_signal(struct drm_i915_gem_request *req, u32 *cs)
69624edb884SFrançois Tigeot {
69771f41f3eSFrançois Tigeot 	struct drm_i915_private *dev_priv = req->i915;
69824edb884SFrançois Tigeot 	struct intel_engine_cs *waiter;
6998621f407SFrançois Tigeot 	enum intel_engine_id id;
70024edb884SFrançois Tigeot 
7011e12ee3bSFrançois Tigeot 	for_each_engine(waiter, dev_priv, id) {
70271f41f3eSFrançois Tigeot 		u64 gtt_offset = req->engine->semaphore.signal_ggtt[id];
70324edb884SFrançois Tigeot 		if (gtt_offset == MI_SEMAPHORE_SYNC_INVALID)
70424edb884SFrançois Tigeot 			continue;
70524edb884SFrançois Tigeot 
706*a85cb24fSFrançois Tigeot 		*cs++ = GFX_OP_PIPE_CONTROL(6);
707*a85cb24fSFrançois Tigeot 		*cs++ = PIPE_CONTROL_GLOBAL_GTT_IVB | PIPE_CONTROL_QW_WRITE |
708*a85cb24fSFrançois Tigeot 			PIPE_CONTROL_CS_STALL;
709*a85cb24fSFrançois Tigeot 		*cs++ = lower_32_bits(gtt_offset);
710*a85cb24fSFrançois Tigeot 		*cs++ = upper_32_bits(gtt_offset);
711*a85cb24fSFrançois Tigeot 		*cs++ = req->global_seqno;
712*a85cb24fSFrançois Tigeot 		*cs++ = 0;
713*a85cb24fSFrançois Tigeot 		*cs++ = MI_SEMAPHORE_SIGNAL |
714*a85cb24fSFrançois Tigeot 			MI_SEMAPHORE_TARGET(waiter->hw_id);
715*a85cb24fSFrançois Tigeot 		*cs++ = 0;
71624edb884SFrançois Tigeot 	}
71724edb884SFrançois Tigeot 
718*a85cb24fSFrançois Tigeot 	return cs;
7194be47400SFrançois Tigeot }
7204be47400SFrançois Tigeot 
721*a85cb24fSFrançois Tigeot static u32 *gen8_xcs_signal(struct drm_i915_gem_request *req, u32 *cs)
72224edb884SFrançois Tigeot {
72371f41f3eSFrançois Tigeot 	struct drm_i915_private *dev_priv = req->i915;
72424edb884SFrançois Tigeot 	struct intel_engine_cs *waiter;
7258621f407SFrançois Tigeot 	enum intel_engine_id id;
72624edb884SFrançois Tigeot 
7271e12ee3bSFrançois Tigeot 	for_each_engine(waiter, dev_priv, id) {
72871f41f3eSFrançois Tigeot 		u64 gtt_offset = req->engine->semaphore.signal_ggtt[id];
72924edb884SFrançois Tigeot 		if (gtt_offset == MI_SEMAPHORE_SYNC_INVALID)
73024edb884SFrançois Tigeot 			continue;
73124edb884SFrançois Tigeot 
732*a85cb24fSFrançois Tigeot 		*cs++ = (MI_FLUSH_DW + 1) | MI_FLUSH_DW_OP_STOREDW;
733*a85cb24fSFrançois Tigeot 		*cs++ = lower_32_bits(gtt_offset) | MI_FLUSH_DW_USE_GTT;
734*a85cb24fSFrançois Tigeot 		*cs++ = upper_32_bits(gtt_offset);
735*a85cb24fSFrançois Tigeot 		*cs++ = req->global_seqno;
736*a85cb24fSFrançois Tigeot 		*cs++ = MI_SEMAPHORE_SIGNAL |
737*a85cb24fSFrançois Tigeot 			MI_SEMAPHORE_TARGET(waiter->hw_id);
738*a85cb24fSFrançois Tigeot 		*cs++ = 0;
73924edb884SFrançois Tigeot 	}
74024edb884SFrançois Tigeot 
741*a85cb24fSFrançois Tigeot 	return cs;
7424be47400SFrançois Tigeot }
7434be47400SFrançois Tigeot 
744*a85cb24fSFrançois Tigeot static u32 *gen6_signal(struct drm_i915_gem_request *req, u32 *cs)
745e3adcf8fSFrançois Tigeot {
74671f41f3eSFrançois Tigeot 	struct drm_i915_private *dev_priv = req->i915;
7471e12ee3bSFrançois Tigeot 	struct intel_engine_cs *engine;
7488621f407SFrançois Tigeot 	enum intel_engine_id id;
7494be47400SFrançois Tigeot 	int num_rings = 0;
750ba55f2f5SFrançois Tigeot 
7511e12ee3bSFrançois Tigeot 	for_each_engine(engine, dev_priv, id) {
7521e12ee3bSFrançois Tigeot 		i915_reg_t mbox_reg;
753aee94f86SFrançois Tigeot 
7541e12ee3bSFrançois Tigeot 		if (!(BIT(engine->hw_id) & GEN6_SEMAPHORES_MASK))
7551e12ee3bSFrançois Tigeot 			continue;
7561e12ee3bSFrançois Tigeot 
7571e12ee3bSFrançois Tigeot 		mbox_reg = req->engine->semaphore.mbox.signal[engine->hw_id];
758aee94f86SFrançois Tigeot 		if (i915_mmio_reg_valid(mbox_reg)) {
759*a85cb24fSFrançois Tigeot 			*cs++ = MI_LOAD_REGISTER_IMM(1);
760*a85cb24fSFrançois Tigeot 			*cs++ = i915_mmio_reg_offset(mbox_reg);
761*a85cb24fSFrançois Tigeot 			*cs++ = req->global_seqno;
7624be47400SFrançois Tigeot 			num_rings++;
763ba55f2f5SFrançois Tigeot 		}
764ba55f2f5SFrançois Tigeot 	}
7654be47400SFrançois Tigeot 	if (num_rings & 1)
766*a85cb24fSFrançois Tigeot 		*cs++ = MI_NOOP;
767ba55f2f5SFrançois Tigeot 
768*a85cb24fSFrançois Tigeot 	return cs;
76971f41f3eSFrançois Tigeot }
77071f41f3eSFrançois Tigeot 
77171f41f3eSFrançois Tigeot static void i9xx_submit_request(struct drm_i915_gem_request *request)
77271f41f3eSFrançois Tigeot {
77371f41f3eSFrançois Tigeot 	struct drm_i915_private *dev_priv = request->i915;
77471f41f3eSFrançois Tigeot 
7754be47400SFrançois Tigeot 	i915_gem_request_submit(request);
7764be47400SFrançois Tigeot 
777*a85cb24fSFrançois Tigeot 	I915_WRITE_TAIL(request->engine,
778*a85cb24fSFrançois Tigeot 			intel_ring_set_tail(request->ring, request->tail));
77971f41f3eSFrançois Tigeot }
78071f41f3eSFrançois Tigeot 
781*a85cb24fSFrançois Tigeot static void i9xx_emit_breadcrumb(struct drm_i915_gem_request *req, u32 *cs)
78271f41f3eSFrançois Tigeot {
783*a85cb24fSFrançois Tigeot 	*cs++ = MI_STORE_DWORD_INDEX;
784*a85cb24fSFrançois Tigeot 	*cs++ = I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT;
785*a85cb24fSFrançois Tigeot 	*cs++ = req->global_seqno;
786*a85cb24fSFrançois Tigeot 	*cs++ = MI_USER_INTERRUPT;
78771f41f3eSFrançois Tigeot 
788*a85cb24fSFrançois Tigeot 	req->tail = intel_ring_offset(req, cs);
789*a85cb24fSFrançois Tigeot 	assert_ring_tail_valid(req->ring, req->tail);
790e3adcf8fSFrançois Tigeot }
791e3adcf8fSFrançois Tigeot 
7924be47400SFrançois Tigeot static const int i9xx_emit_breadcrumb_sz = 4;
7934be47400SFrançois Tigeot 
794e3adcf8fSFrançois Tigeot /**
7954be47400SFrançois Tigeot  * gen6_sema_emit_breadcrumb - Update the semaphore mailbox registers
796e3adcf8fSFrançois Tigeot  *
797a05eeebfSFrançois Tigeot  * @request - request to write to the ring
798e3adcf8fSFrançois Tigeot  *
799e3adcf8fSFrançois Tigeot  * Update the mailbox registers in the *other* rings with the current seqno.
800e3adcf8fSFrançois Tigeot  * This acts like a signal in the canonical semaphore.
801e3adcf8fSFrançois Tigeot  */
802*a85cb24fSFrançois Tigeot static void gen6_sema_emit_breadcrumb(struct drm_i915_gem_request *req, u32 *cs)
803e3adcf8fSFrançois Tigeot {
8044be47400SFrançois Tigeot 	return i9xx_emit_breadcrumb(req,
805*a85cb24fSFrançois Tigeot 				    req->engine->semaphore.signal(req, cs));
806e3adcf8fSFrançois Tigeot }
807e3adcf8fSFrançois Tigeot 
8084be47400SFrançois Tigeot static void gen8_render_emit_breadcrumb(struct drm_i915_gem_request *req,
809*a85cb24fSFrançois Tigeot 					u32 *cs)
8101487f786SFrançois Tigeot {
8111487f786SFrançois Tigeot 	struct intel_engine_cs *engine = req->engine;
8121487f786SFrançois Tigeot 
8134be47400SFrançois Tigeot 	if (engine->semaphore.signal)
814*a85cb24fSFrançois Tigeot 		cs = engine->semaphore.signal(req, cs);
81571f41f3eSFrançois Tigeot 
816*a85cb24fSFrançois Tigeot 	*cs++ = GFX_OP_PIPE_CONTROL(6);
817*a85cb24fSFrançois Tigeot 	*cs++ = PIPE_CONTROL_GLOBAL_GTT_IVB | PIPE_CONTROL_CS_STALL |
818*a85cb24fSFrançois Tigeot 		PIPE_CONTROL_QW_WRITE;
819*a85cb24fSFrançois Tigeot 	*cs++ = intel_hws_seqno_address(engine);
820*a85cb24fSFrançois Tigeot 	*cs++ = 0;
821*a85cb24fSFrançois Tigeot 	*cs++ = req->global_seqno;
8221487f786SFrançois Tigeot 	/* We're thrashing one dword of HWS. */
823*a85cb24fSFrançois Tigeot 	*cs++ = 0;
824*a85cb24fSFrançois Tigeot 	*cs++ = MI_USER_INTERRUPT;
825*a85cb24fSFrançois Tigeot 	*cs++ = MI_NOOP;
82671f41f3eSFrançois Tigeot 
827*a85cb24fSFrançois Tigeot 	req->tail = intel_ring_offset(req, cs);
828*a85cb24fSFrançois Tigeot 	assert_ring_tail_valid(req->ring, req->tail);
8291487f786SFrançois Tigeot }
8301487f786SFrançois Tigeot 
8314be47400SFrançois Tigeot static const int gen8_render_emit_breadcrumb_sz = 8;
8324be47400SFrançois Tigeot 
833e3adcf8fSFrançois Tigeot /**
834e3adcf8fSFrançois Tigeot  * intel_ring_sync - sync the waiter to the signaller on seqno
835e3adcf8fSFrançois Tigeot  *
836e3adcf8fSFrançois Tigeot  * @waiter - ring that is waiting
837e3adcf8fSFrançois Tigeot  * @signaller - ring which has, or will signal
838e3adcf8fSFrançois Tigeot  * @seqno - seqno which the waiter will block on
839e3adcf8fSFrançois Tigeot  */
84024edb884SFrançois Tigeot 
84124edb884SFrançois Tigeot static int
84271f41f3eSFrançois Tigeot gen8_ring_sync_to(struct drm_i915_gem_request *req,
84371f41f3eSFrançois Tigeot 		  struct drm_i915_gem_request *signal)
84424edb884SFrançois Tigeot {
84571f41f3eSFrançois Tigeot 	struct drm_i915_private *dev_priv = req->i915;
84671f41f3eSFrançois Tigeot 	u64 offset = GEN8_WAIT_OFFSET(req->engine, signal->engine->id);
8471487f786SFrançois Tigeot 	struct i915_hw_ppgtt *ppgtt;
848*a85cb24fSFrançois Tigeot 	u32 *cs;
84924edb884SFrançois Tigeot 
850*a85cb24fSFrançois Tigeot 	cs = intel_ring_begin(req, 4);
851*a85cb24fSFrançois Tigeot 	if (IS_ERR(cs))
852*a85cb24fSFrançois Tigeot 		return PTR_ERR(cs);
85324edb884SFrançois Tigeot 
854*a85cb24fSFrançois Tigeot 	*cs++ = MI_SEMAPHORE_WAIT | MI_SEMAPHORE_GLOBAL_GTT |
855*a85cb24fSFrançois Tigeot 		MI_SEMAPHORE_SAD_GTE_SDD;
856*a85cb24fSFrançois Tigeot 	*cs++ = signal->global_seqno;
857*a85cb24fSFrançois Tigeot 	*cs++ = lower_32_bits(offset);
858*a85cb24fSFrançois Tigeot 	*cs++ = upper_32_bits(offset);
859*a85cb24fSFrançois Tigeot 	intel_ring_advance(req, cs);
8601487f786SFrançois Tigeot 
8611487f786SFrançois Tigeot 	/* When the !RCS engines idle waiting upon a semaphore, they lose their
8621487f786SFrançois Tigeot 	 * pagetables and we must reload them before executing the batch.
8631487f786SFrançois Tigeot 	 * We do this on the i915_switch_context() following the wait and
8641487f786SFrançois Tigeot 	 * before the dispatch.
8651487f786SFrançois Tigeot 	 */
86671f41f3eSFrançois Tigeot 	ppgtt = req->ctx->ppgtt;
86771f41f3eSFrançois Tigeot 	if (ppgtt && req->engine->id != RCS)
86871f41f3eSFrançois Tigeot 		ppgtt->pd_dirty_rings |= intel_engine_flag(req->engine);
86924edb884SFrançois Tigeot 	return 0;
87024edb884SFrançois Tigeot }
87124edb884SFrançois Tigeot 
872e3adcf8fSFrançois Tigeot static int
87371f41f3eSFrançois Tigeot gen6_ring_sync_to(struct drm_i915_gem_request *req,
87471f41f3eSFrançois Tigeot 		  struct drm_i915_gem_request *signal)
875e3adcf8fSFrançois Tigeot {
876e3adcf8fSFrançois Tigeot 	u32 dw1 = MI_SEMAPHORE_MBOX |
877e3adcf8fSFrançois Tigeot 		  MI_SEMAPHORE_COMPARE |
878e3adcf8fSFrançois Tigeot 		  MI_SEMAPHORE_REGISTER;
8791e12ee3bSFrançois Tigeot 	u32 wait_mbox = signal->engine->semaphore.mbox.wait[req->engine->hw_id];
880*a85cb24fSFrançois Tigeot 	u32 *cs;
881e3adcf8fSFrançois Tigeot 
88271f41f3eSFrançois Tigeot 	WARN_ON(wait_mbox == MI_SEMAPHORE_SYNC_INVALID);
88371f41f3eSFrançois Tigeot 
884*a85cb24fSFrançois Tigeot 	cs = intel_ring_begin(req, 4);
885*a85cb24fSFrançois Tigeot 	if (IS_ERR(cs))
886*a85cb24fSFrançois Tigeot 		return PTR_ERR(cs);
88771f41f3eSFrançois Tigeot 
888*a85cb24fSFrançois Tigeot 	*cs++ = dw1 | wait_mbox;
889686a02f1SFrançois Tigeot 	/* Throughout all of the GEM code, seqno passed implies our current
890686a02f1SFrançois Tigeot 	 * seqno is >= the last seqno executed. However for hardware the
891686a02f1SFrançois Tigeot 	 * comparison is strictly greater than.
892686a02f1SFrançois Tigeot 	 */
893*a85cb24fSFrançois Tigeot 	*cs++ = signal->global_seqno - 1;
894*a85cb24fSFrançois Tigeot 	*cs++ = 0;
895*a85cb24fSFrançois Tigeot 	*cs++ = MI_NOOP;
896*a85cb24fSFrançois Tigeot 	intel_ring_advance(req, cs);
897e3adcf8fSFrançois Tigeot 
898e3adcf8fSFrançois Tigeot 	return 0;
899e3adcf8fSFrançois Tigeot }
900e3adcf8fSFrançois Tigeot 
901303bf270SFrançois Tigeot static void
90287df8fc6SFrançois Tigeot gen5_seqno_barrier(struct intel_engine_cs *engine)
903e3adcf8fSFrançois Tigeot {
904303bf270SFrançois Tigeot 	/* MI_STORE are internally buffered by the GPU and not flushed
905303bf270SFrançois Tigeot 	 * either by MI_FLUSH or SyncFlush or any other combination of
906303bf270SFrançois Tigeot 	 * MI commands.
907e3adcf8fSFrançois Tigeot 	 *
908303bf270SFrançois Tigeot 	 * "Only the submission of the store operation is guaranteed.
909303bf270SFrançois Tigeot 	 * The write result will be complete (coherent) some time later
910303bf270SFrançois Tigeot 	 * (this is practically a finite period but there is no guaranteed
911303bf270SFrançois Tigeot 	 * latency)."
912303bf270SFrançois Tigeot 	 *
913303bf270SFrançois Tigeot 	 * Empirically, we observe that we need a delay of at least 75us to
914303bf270SFrançois Tigeot 	 * be sure that the seqno write is visible by the CPU.
915e3adcf8fSFrançois Tigeot 	 */
916303bf270SFrançois Tigeot 	usleep_range(125, 250);
917e3adcf8fSFrançois Tigeot }
918e3adcf8fSFrançois Tigeot 
9198621f407SFrançois Tigeot static void
9208621f407SFrançois Tigeot gen6_seqno_barrier(struct intel_engine_cs *engine)
921e3adcf8fSFrançois Tigeot {
9221487f786SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
9238621f407SFrançois Tigeot 
924e3adcf8fSFrançois Tigeot 	/* Workaround to force correct ordering between irq and seqno writes on
925e3adcf8fSFrançois Tigeot 	 * ivb (and maybe also on snb) by reading from a CS register (like
9268621f407SFrançois Tigeot 	 * ACTHD) before reading the status page.
9278621f407SFrançois Tigeot 	 *
9288621f407SFrançois Tigeot 	 * Note that this effectively stalls the read by the time it takes to
9298621f407SFrançois Tigeot 	 * do a memory transaction, which more or less ensures that the write
9308621f407SFrançois Tigeot 	 * from the GPU has sufficient time to invalidate the CPU cacheline.
9318621f407SFrançois Tigeot 	 * Alternatively we could delay the interrupt from the CS ring to give
9328621f407SFrançois Tigeot 	 * the write time to land, but that would incur a delay after every
9338621f407SFrançois Tigeot 	 * batch i.e. much more frequent than a delay when waiting for the
9348621f407SFrançois Tigeot 	 * interrupt (with the same net latency).
9358621f407SFrançois Tigeot 	 *
9368621f407SFrançois Tigeot 	 * Also note that to prevent whole machine hangs on gen7, we have to
9378621f407SFrançois Tigeot 	 * take the spinlock to guard against concurrent cacheline access.
9388621f407SFrançois Tigeot 	 */
9398621f407SFrançois Tigeot 	spin_lock_irq(&dev_priv->uncore.lock);
9408621f407SFrançois Tigeot 	POSTING_READ_FW(RING_ACTHD(engine->mmio_base));
9418621f407SFrançois Tigeot 	spin_unlock_irq(&dev_priv->uncore.lock);
942e3adcf8fSFrançois Tigeot }
943e3adcf8fSFrançois Tigeot 
944303bf270SFrançois Tigeot static void
945303bf270SFrançois Tigeot gen5_irq_enable(struct intel_engine_cs *engine)
946e3adcf8fSFrançois Tigeot {
947303bf270SFrançois Tigeot 	gen5_enable_gt_irq(engine->i915, engine->irq_enable_mask);
948e3adcf8fSFrançois Tigeot }
949e3adcf8fSFrançois Tigeot 
950a2fdbec6SFrançois Tigeot static void
951303bf270SFrançois Tigeot gen5_irq_disable(struct intel_engine_cs *engine)
952a2fdbec6SFrançois Tigeot {
953303bf270SFrançois Tigeot 	gen5_disable_gt_irq(engine->i915, engine->irq_enable_mask);
954e3adcf8fSFrançois Tigeot }
955e3adcf8fSFrançois Tigeot 
956a2fdbec6SFrançois Tigeot static void
957303bf270SFrançois Tigeot i9xx_irq_enable(struct intel_engine_cs *engine)
958e3adcf8fSFrançois Tigeot {
9591487f786SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
960e3adcf8fSFrançois Tigeot 
9618621f407SFrançois Tigeot 	dev_priv->irq_mask &= ~engine->irq_enable_mask;
962686a02f1SFrançois Tigeot 	I915_WRITE(IMR, dev_priv->irq_mask);
963303bf270SFrançois Tigeot 	POSTING_READ_FW(RING_IMR(engine->mmio_base));
964686a02f1SFrançois Tigeot }
965686a02f1SFrançois Tigeot 
966686a02f1SFrançois Tigeot static void
967303bf270SFrançois Tigeot i9xx_irq_disable(struct intel_engine_cs *engine)
968686a02f1SFrançois Tigeot {
9691487f786SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
970686a02f1SFrançois Tigeot 
9718621f407SFrançois Tigeot 	dev_priv->irq_mask |= engine->irq_enable_mask;
972686a02f1SFrançois Tigeot 	I915_WRITE(IMR, dev_priv->irq_mask);
973686a02f1SFrançois Tigeot }
974686a02f1SFrançois Tigeot 
975686a02f1SFrançois Tigeot static void
976303bf270SFrançois Tigeot i8xx_irq_enable(struct intel_engine_cs *engine)
977686a02f1SFrançois Tigeot {
9781487f786SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
979686a02f1SFrançois Tigeot 
980303bf270SFrançois Tigeot 	dev_priv->irq_mask &= ~engine->irq_enable_mask;
981303bf270SFrançois Tigeot 	I915_WRITE16(IMR, dev_priv->irq_mask);
982303bf270SFrançois Tigeot 	POSTING_READ16(RING_IMR(engine->mmio_base));
983303bf270SFrançois Tigeot }
984303bf270SFrançois Tigeot 
985303bf270SFrançois Tigeot static void
986303bf270SFrançois Tigeot i8xx_irq_disable(struct intel_engine_cs *engine)
987303bf270SFrançois Tigeot {
988303bf270SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
989303bf270SFrançois Tigeot 
9908621f407SFrançois Tigeot 	dev_priv->irq_mask |= engine->irq_enable_mask;
991686a02f1SFrançois Tigeot 	I915_WRITE16(IMR, dev_priv->irq_mask);
992e3adcf8fSFrançois Tigeot }
993e3adcf8fSFrançois Tigeot 
994e3adcf8fSFrançois Tigeot static int
99571f41f3eSFrançois Tigeot bsd_ring_flush(struct drm_i915_gem_request *req, u32 mode)
996e3adcf8fSFrançois Tigeot {
997*a85cb24fSFrançois Tigeot 	u32 *cs;
998e3adcf8fSFrançois Tigeot 
999*a85cb24fSFrançois Tigeot 	cs = intel_ring_begin(req, 2);
1000*a85cb24fSFrançois Tigeot 	if (IS_ERR(cs))
1001*a85cb24fSFrançois Tigeot 		return PTR_ERR(cs);
1002e3adcf8fSFrançois Tigeot 
1003*a85cb24fSFrançois Tigeot 	*cs++ = MI_FLUSH;
1004*a85cb24fSFrançois Tigeot 	*cs++ = MI_NOOP;
1005*a85cb24fSFrançois Tigeot 	intel_ring_advance(req, cs);
1006e3adcf8fSFrançois Tigeot 	return 0;
1007e3adcf8fSFrançois Tigeot }
1008e3adcf8fSFrançois Tigeot 
1009303bf270SFrançois Tigeot static void
1010303bf270SFrançois Tigeot gen6_irq_enable(struct intel_engine_cs *engine)
1011e3adcf8fSFrançois Tigeot {
10121487f786SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
1013e3adcf8fSFrançois Tigeot 
10148621f407SFrançois Tigeot 	I915_WRITE_IMR(engine,
10158621f407SFrançois Tigeot 		       ~(engine->irq_enable_mask |
1016303bf270SFrançois Tigeot 			 engine->irq_keep_mask));
10178621f407SFrançois Tigeot 	gen5_enable_gt_irq(dev_priv, engine->irq_enable_mask);
1018e3adcf8fSFrançois Tigeot }
1019e3adcf8fSFrançois Tigeot 
1020e3adcf8fSFrançois Tigeot static void
1021303bf270SFrançois Tigeot gen6_irq_disable(struct intel_engine_cs *engine)
1022e3adcf8fSFrançois Tigeot {
10231487f786SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
1024e3adcf8fSFrançois Tigeot 
1025303bf270SFrançois Tigeot 	I915_WRITE_IMR(engine, ~engine->irq_keep_mask);
10268621f407SFrançois Tigeot 	gen5_disable_gt_irq(dev_priv, engine->irq_enable_mask);
1027e3adcf8fSFrançois Tigeot }
1028e3adcf8fSFrançois Tigeot 
1029303bf270SFrançois Tigeot static void
1030303bf270SFrançois Tigeot hsw_vebox_irq_enable(struct intel_engine_cs *engine)
10315d0b1887SFrançois Tigeot {
10321487f786SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
10335d0b1887SFrançois Tigeot 
10348621f407SFrançois Tigeot 	I915_WRITE_IMR(engine, ~engine->irq_enable_mask);
10354be47400SFrançois Tigeot 	gen6_unmask_pm_irq(dev_priv, engine->irq_enable_mask);
10365d0b1887SFrançois Tigeot }
10375d0b1887SFrançois Tigeot 
10385d0b1887SFrançois Tigeot static void
1039303bf270SFrançois Tigeot hsw_vebox_irq_disable(struct intel_engine_cs *engine)
10405d0b1887SFrançois Tigeot {
10411487f786SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
10425d0b1887SFrançois Tigeot 
10438621f407SFrançois Tigeot 	I915_WRITE_IMR(engine, ~0);
10444be47400SFrançois Tigeot 	gen6_mask_pm_irq(dev_priv, engine->irq_enable_mask);
10455d0b1887SFrançois Tigeot }
10469edbd4a0SFrançois Tigeot 
1047303bf270SFrançois Tigeot static void
1048303bf270SFrançois Tigeot gen8_irq_enable(struct intel_engine_cs *engine)
10499edbd4a0SFrançois Tigeot {
10501487f786SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
10519edbd4a0SFrançois Tigeot 
10528621f407SFrançois Tigeot 	I915_WRITE_IMR(engine,
10538621f407SFrançois Tigeot 		       ~(engine->irq_enable_mask |
1054303bf270SFrançois Tigeot 			 engine->irq_keep_mask));
1055303bf270SFrançois Tigeot 	POSTING_READ_FW(RING_IMR(engine->mmio_base));
10569edbd4a0SFrançois Tigeot }
10579edbd4a0SFrançois Tigeot 
10589edbd4a0SFrançois Tigeot static void
1059303bf270SFrançois Tigeot gen8_irq_disable(struct intel_engine_cs *engine)
10609edbd4a0SFrançois Tigeot {
10611487f786SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
10629edbd4a0SFrançois Tigeot 
1063303bf270SFrançois Tigeot 	I915_WRITE_IMR(engine, ~engine->irq_keep_mask);
10645d0b1887SFrançois Tigeot }
10655d0b1887SFrançois Tigeot 
1066e3adcf8fSFrançois Tigeot static int
106771f41f3eSFrançois Tigeot i965_emit_bb_start(struct drm_i915_gem_request *req,
1068ba55f2f5SFrançois Tigeot 		   u64 offset, u32 length,
106971f41f3eSFrançois Tigeot 		   unsigned int dispatch_flags)
1070e3adcf8fSFrançois Tigeot {
1071*a85cb24fSFrançois Tigeot 	u32 *cs;
1072e3adcf8fSFrançois Tigeot 
1073*a85cb24fSFrançois Tigeot 	cs = intel_ring_begin(req, 2);
1074*a85cb24fSFrançois Tigeot 	if (IS_ERR(cs))
1075*a85cb24fSFrançois Tigeot 		return PTR_ERR(cs);
1076e3adcf8fSFrançois Tigeot 
1077*a85cb24fSFrançois Tigeot 	*cs++ = MI_BATCH_BUFFER_START | MI_BATCH_GTT | (dispatch_flags &
1078*a85cb24fSFrançois Tigeot 		I915_DISPATCH_SECURE ? 0 : MI_BATCH_NON_SECURE_I965);
1079*a85cb24fSFrançois Tigeot 	*cs++ = offset;
1080*a85cb24fSFrançois Tigeot 	intel_ring_advance(req, cs);
1081e3adcf8fSFrançois Tigeot 
1082e3adcf8fSFrançois Tigeot 	return 0;
1083e3adcf8fSFrançois Tigeot }
1084e3adcf8fSFrançois Tigeot 
1085b5c29a34SFrançois Tigeot /* Just userspace ABI convention to limit the wa batch bo to a resonable size */
1086b5c29a34SFrançois Tigeot #define I830_BATCH_LIMIT (256*1024)
108724edb884SFrançois Tigeot #define I830_TLB_ENTRIES (2)
108824edb884SFrançois Tigeot #define I830_WA_SIZE max(I830_TLB_ENTRIES*4096, I830_BATCH_LIMIT)
1089e3adcf8fSFrançois Tigeot static int
109071f41f3eSFrançois Tigeot i830_emit_bb_start(struct drm_i915_gem_request *req,
1091ba55f2f5SFrançois Tigeot 		   u64 offset, u32 len,
109271f41f3eSFrançois Tigeot 		   unsigned int dispatch_flags)
1093e3adcf8fSFrançois Tigeot {
1094*a85cb24fSFrançois Tigeot 	u32 *cs, cs_offset = i915_ggtt_offset(req->engine->scratch);
1095e3adcf8fSFrançois Tigeot 
1096*a85cb24fSFrançois Tigeot 	cs = intel_ring_begin(req, 6);
1097*a85cb24fSFrançois Tigeot 	if (IS_ERR(cs))
1098*a85cb24fSFrançois Tigeot 		return PTR_ERR(cs);
109924edb884SFrançois Tigeot 
110024edb884SFrançois Tigeot 	/* Evict the invalid PTE TLBs */
1101*a85cb24fSFrançois Tigeot 	*cs++ = COLOR_BLT_CMD | BLT_WRITE_RGBA;
1102*a85cb24fSFrançois Tigeot 	*cs++ = BLT_DEPTH_32 | BLT_ROP_COLOR_COPY | 4096;
1103*a85cb24fSFrançois Tigeot 	*cs++ = I830_TLB_ENTRIES << 16 | 4; /* load each page */
1104*a85cb24fSFrançois Tigeot 	*cs++ = cs_offset;
1105*a85cb24fSFrançois Tigeot 	*cs++ = 0xdeadbeef;
1106*a85cb24fSFrançois Tigeot 	*cs++ = MI_NOOP;
1107*a85cb24fSFrançois Tigeot 	intel_ring_advance(req, cs);
110824edb884SFrançois Tigeot 
1109477eb7f9SFrançois Tigeot 	if ((dispatch_flags & I915_DISPATCH_PINNED) == 0) {
111024edb884SFrançois Tigeot 		if (len > I830_BATCH_LIMIT)
111124edb884SFrançois Tigeot 			return -ENOSPC;
111224edb884SFrançois Tigeot 
1113*a85cb24fSFrançois Tigeot 		cs = intel_ring_begin(req, 6 + 2);
1114*a85cb24fSFrançois Tigeot 		if (IS_ERR(cs))
1115*a85cb24fSFrançois Tigeot 			return PTR_ERR(cs);
111624edb884SFrançois Tigeot 
111724edb884SFrançois Tigeot 		/* Blit the batch (which has now all relocs applied) to the
111824edb884SFrançois Tigeot 		 * stable batch scratch bo area (so that the CS never
111924edb884SFrançois Tigeot 		 * stumbles over its tlb invalidation bug) ...
112024edb884SFrançois Tigeot 		 */
1121*a85cb24fSFrançois Tigeot 		*cs++ = SRC_COPY_BLT_CMD | BLT_WRITE_RGBA;
1122*a85cb24fSFrançois Tigeot 		*cs++ = BLT_DEPTH_32 | BLT_ROP_SRC_COPY | 4096;
1123*a85cb24fSFrançois Tigeot 		*cs++ = DIV_ROUND_UP(len, 4096) << 16 | 4096;
1124*a85cb24fSFrançois Tigeot 		*cs++ = cs_offset;
1125*a85cb24fSFrançois Tigeot 		*cs++ = 4096;
1126*a85cb24fSFrançois Tigeot 		*cs++ = offset;
112724edb884SFrançois Tigeot 
1128*a85cb24fSFrançois Tigeot 		*cs++ = MI_FLUSH;
1129*a85cb24fSFrançois Tigeot 		*cs++ = MI_NOOP;
1130*a85cb24fSFrançois Tigeot 		intel_ring_advance(req, cs);
113124edb884SFrançois Tigeot 
113224edb884SFrançois Tigeot 		/* ... and execute it. */
113324edb884SFrançois Tigeot 		offset = cs_offset;
113424edb884SFrançois Tigeot 	}
113524edb884SFrançois Tigeot 
1136*a85cb24fSFrançois Tigeot 	cs = intel_ring_begin(req, 2);
1137*a85cb24fSFrançois Tigeot 	if (IS_ERR(cs))
1138*a85cb24fSFrançois Tigeot 		return PTR_ERR(cs);
1139e3adcf8fSFrançois Tigeot 
1140*a85cb24fSFrançois Tigeot 	*cs++ = MI_BATCH_BUFFER_START | MI_BATCH_GTT;
1141*a85cb24fSFrançois Tigeot 	*cs++ = offset | (dispatch_flags & I915_DISPATCH_SECURE ? 0 :
1142*a85cb24fSFrançois Tigeot 		MI_BATCH_NON_SECURE);
1143*a85cb24fSFrançois Tigeot 	intel_ring_advance(req, cs);
1144686a02f1SFrançois Tigeot 
1145686a02f1SFrançois Tigeot 	return 0;
1146686a02f1SFrançois Tigeot }
1147686a02f1SFrançois Tigeot 
1148686a02f1SFrançois Tigeot static int
114971f41f3eSFrançois Tigeot i915_emit_bb_start(struct drm_i915_gem_request *req,
1150ba55f2f5SFrançois Tigeot 		   u64 offset, u32 len,
115171f41f3eSFrançois Tigeot 		   unsigned int dispatch_flags)
1152686a02f1SFrançois Tigeot {
1153*a85cb24fSFrançois Tigeot 	u32 *cs;
1154686a02f1SFrançois Tigeot 
1155*a85cb24fSFrançois Tigeot 	cs = intel_ring_begin(req, 2);
1156*a85cb24fSFrançois Tigeot 	if (IS_ERR(cs))
1157*a85cb24fSFrançois Tigeot 		return PTR_ERR(cs);
1158e3adcf8fSFrançois Tigeot 
1159*a85cb24fSFrançois Tigeot 	*cs++ = MI_BATCH_BUFFER_START | MI_BATCH_GTT;
1160*a85cb24fSFrançois Tigeot 	*cs++ = offset | (dispatch_flags & I915_DISPATCH_SECURE ? 0 :
1161*a85cb24fSFrançois Tigeot 		MI_BATCH_NON_SECURE);
1162*a85cb24fSFrançois Tigeot 	intel_ring_advance(req, cs);
1163e3adcf8fSFrançois Tigeot 
1164e3adcf8fSFrançois Tigeot 	return 0;
1165e3adcf8fSFrançois Tigeot }
1166e3adcf8fSFrançois Tigeot 
11678621f407SFrançois Tigeot static void cleanup_phys_status_page(struct intel_engine_cs *engine)
1168c0e85e96SFrançois Tigeot {
11691487f786SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
1170c0e85e96SFrançois Tigeot 
1171c0e85e96SFrançois Tigeot 	if (!dev_priv->status_page_dmah)
1172c0e85e96SFrançois Tigeot 		return;
1173c0e85e96SFrançois Tigeot 
1174303bf270SFrançois Tigeot 	drm_pci_free(&dev_priv->drm, dev_priv->status_page_dmah);
11758621f407SFrançois Tigeot 	engine->status_page.page_addr = NULL;
1176c0e85e96SFrançois Tigeot }
1177c0e85e96SFrançois Tigeot 
11788621f407SFrançois Tigeot static void cleanup_status_page(struct intel_engine_cs *engine)
1179e3adcf8fSFrançois Tigeot {
11801e12ee3bSFrançois Tigeot 	struct i915_vma *vma;
11814be47400SFrançois Tigeot 	struct drm_i915_gem_object *obj;
1182e3adcf8fSFrançois Tigeot 
11831e12ee3bSFrançois Tigeot 	vma = fetch_and_zero(&engine->status_page.vma);
11841e12ee3bSFrançois Tigeot 	if (!vma)
1185e3adcf8fSFrançois Tigeot 		return;
1186e3adcf8fSFrançois Tigeot 
11874be47400SFrançois Tigeot 	obj = vma->obj;
11884be47400SFrançois Tigeot 
11891e12ee3bSFrançois Tigeot 	i915_vma_unpin(vma);
11904be47400SFrançois Tigeot 	i915_vma_close(vma);
11914be47400SFrançois Tigeot 
11924be47400SFrançois Tigeot 	i915_gem_object_unpin_map(obj);
11934be47400SFrançois Tigeot 	__i915_gem_object_release_unless_active(obj);
1194e3adcf8fSFrançois Tigeot }
1195e3adcf8fSFrançois Tigeot 
11968621f407SFrançois Tigeot static int init_status_page(struct intel_engine_cs *engine)
1197e3adcf8fSFrançois Tigeot {
11981e12ee3bSFrançois Tigeot 	struct drm_i915_gem_object *obj;
11991e12ee3bSFrançois Tigeot 	struct i915_vma *vma;
12001e12ee3bSFrançois Tigeot 	unsigned int flags;
12014be47400SFrançois Tigeot 	void *vaddr;
1202e3adcf8fSFrançois Tigeot 	int ret;
1203e3adcf8fSFrançois Tigeot 
1204*a85cb24fSFrançois Tigeot 	obj = i915_gem_object_create_internal(engine->i915, PAGE_SIZE);
12051487f786SFrançois Tigeot 	if (IS_ERR(obj)) {
1206e3adcf8fSFrançois Tigeot 		DRM_ERROR("Failed to allocate status page\n");
12071487f786SFrançois Tigeot 		return PTR_ERR(obj);
1208e3adcf8fSFrançois Tigeot 	}
1209e3adcf8fSFrançois Tigeot 
1210ba55f2f5SFrançois Tigeot 	ret = i915_gem_object_set_cache_level(obj, I915_CACHE_LLC);
1211ba55f2f5SFrançois Tigeot 	if (ret)
12121e12ee3bSFrançois Tigeot 		goto err;
1213ba55f2f5SFrançois Tigeot 
1214*a85cb24fSFrançois Tigeot 	vma = i915_vma_instance(obj, &engine->i915->ggtt.base, NULL);
12151e12ee3bSFrançois Tigeot 	if (IS_ERR(vma)) {
12161e12ee3bSFrançois Tigeot 		ret = PTR_ERR(vma);
12171e12ee3bSFrançois Tigeot 		goto err;
12181e12ee3bSFrançois Tigeot 	}
12191e12ee3bSFrançois Tigeot 
12201e12ee3bSFrançois Tigeot 	flags = PIN_GLOBAL;
12211487f786SFrançois Tigeot 	if (!HAS_LLC(engine->i915))
122224edb884SFrançois Tigeot 		/* On g33, we cannot place HWS above 256MiB, so
122324edb884SFrançois Tigeot 		 * restrict its pinning to the low mappable arena.
122424edb884SFrançois Tigeot 		 * Though this restriction is not documented for
122524edb884SFrançois Tigeot 		 * gen4, gen5, or byt, they also behave similarly
122624edb884SFrançois Tigeot 		 * and hang if the HWS is placed at the top of the
122724edb884SFrançois Tigeot 		 * GTT. To generalise, it appears that all !llc
122824edb884SFrançois Tigeot 		 * platforms have issues with us placing the HWS
122924edb884SFrançois Tigeot 		 * above the mappable region (even though we never
123024edb884SFrançois Tigeot 		 * actualy map it).
123124edb884SFrançois Tigeot 		 */
123224edb884SFrançois Tigeot 		flags |= PIN_MAPPABLE;
12331e12ee3bSFrançois Tigeot 	ret = i915_vma_pin(vma, 0, 4096, flags);
12341e12ee3bSFrançois Tigeot 	if (ret)
12351e12ee3bSFrançois Tigeot 		goto err;
1236ba55f2f5SFrançois Tigeot 
12374be47400SFrançois Tigeot 	vaddr = i915_gem_object_pin_map(obj, I915_MAP_WB);
12384be47400SFrançois Tigeot 	if (IS_ERR(vaddr)) {
12394be47400SFrançois Tigeot 		ret = PTR_ERR(vaddr);
12404be47400SFrançois Tigeot 		goto err_unpin;
12414be47400SFrançois Tigeot 	}
12424be47400SFrançois Tigeot 
12431e12ee3bSFrançois Tigeot 	engine->status_page.vma = vma;
12441e12ee3bSFrançois Tigeot 	engine->status_page.ggtt_offset = i915_ggtt_offset(vma);
1245*a85cb24fSFrançois Tigeot 	engine->status_page.page_addr = memset(vaddr, 0, PAGE_SIZE);
1246e3adcf8fSFrançois Tigeot 
1247b5c29a34SFrançois Tigeot 	DRM_DEBUG_DRIVER("%s hws offset: 0x%08x\n",
12481e12ee3bSFrançois Tigeot 			 engine->name, i915_ggtt_offset(vma));
1249e3adcf8fSFrançois Tigeot 	return 0;
12501e12ee3bSFrançois Tigeot 
12514be47400SFrançois Tigeot err_unpin:
12524be47400SFrançois Tigeot 	i915_vma_unpin(vma);
12531e12ee3bSFrançois Tigeot err:
12541e12ee3bSFrançois Tigeot 	i915_gem_object_put(obj);
12551e12ee3bSFrançois Tigeot 	return ret;
1256e3adcf8fSFrançois Tigeot }
1257e3adcf8fSFrançois Tigeot 
12588621f407SFrançois Tigeot static int init_phys_status_page(struct intel_engine_cs *engine)
1259686a02f1SFrançois Tigeot {
12601487f786SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
1261686a02f1SFrançois Tigeot 
1262686a02f1SFrançois Tigeot 	dev_priv->status_page_dmah =
1263303bf270SFrançois Tigeot 		drm_pci_alloc(&dev_priv->drm, PAGE_SIZE, PAGE_SIZE);
1264686a02f1SFrançois Tigeot 	if (!dev_priv->status_page_dmah)
1265686a02f1SFrançois Tigeot 		return -ENOMEM;
1266686a02f1SFrançois Tigeot 
12678621f407SFrançois Tigeot 	engine->status_page.page_addr = dev_priv->status_page_dmah->vaddr;
12688621f407SFrançois Tigeot 	memset(engine->status_page.page_addr, 0, PAGE_SIZE);
1269686a02f1SFrançois Tigeot 
1270686a02f1SFrançois Tigeot 	return 0;
1271686a02f1SFrançois Tigeot }
1272686a02f1SFrançois Tigeot 
1273*a85cb24fSFrançois Tigeot int intel_ring_pin(struct intel_ring *ring, unsigned int offset_bias)
12742c9916cdSFrançois Tigeot {
1275*a85cb24fSFrançois Tigeot 	unsigned int flags;
12761e12ee3bSFrançois Tigeot 	enum i915_map_type map;
12771e12ee3bSFrançois Tigeot 	struct i915_vma *vma = ring->vma;
12788621f407SFrançois Tigeot 	void *addr;
12792c9916cdSFrançois Tigeot 	int ret;
12802c9916cdSFrançois Tigeot 
12811e12ee3bSFrançois Tigeot 	GEM_BUG_ON(ring->vaddr);
12821e12ee3bSFrançois Tigeot 
12831e12ee3bSFrançois Tigeot 	map = HAS_LLC(ring->engine->i915) ? I915_MAP_WB : I915_MAP_WC;
12841e12ee3bSFrançois Tigeot 
1285*a85cb24fSFrançois Tigeot 	flags = PIN_GLOBAL;
1286*a85cb24fSFrançois Tigeot 	if (offset_bias)
1287*a85cb24fSFrançois Tigeot 		flags |= PIN_OFFSET_BIAS | offset_bias;
12881e12ee3bSFrançois Tigeot 	if (vma->obj->stolen)
12891e12ee3bSFrançois Tigeot 		flags |= PIN_MAPPABLE;
12901e12ee3bSFrançois Tigeot 
12911e12ee3bSFrançois Tigeot 	if (!(vma->flags & I915_VMA_GLOBAL_BIND)) {
12921e12ee3bSFrançois Tigeot 		if (flags & PIN_MAPPABLE || map == I915_MAP_WC)
12931e12ee3bSFrançois Tigeot 			ret = i915_gem_object_set_to_gtt_domain(vma->obj, true);
12941e12ee3bSFrançois Tigeot 		else
12951e12ee3bSFrançois Tigeot 			ret = i915_gem_object_set_to_cpu_domain(vma->obj, true);
12961e12ee3bSFrançois Tigeot 		if (unlikely(ret))
12971e12ee3bSFrançois Tigeot 			return ret;
12981e12ee3bSFrançois Tigeot 	}
12991e12ee3bSFrançois Tigeot 
13001e12ee3bSFrançois Tigeot 	ret = i915_vma_pin(vma, 0, PAGE_SIZE, flags);
13011e12ee3bSFrançois Tigeot 	if (unlikely(ret))
1302aee94f86SFrançois Tigeot 		return ret;
1303aee94f86SFrançois Tigeot 
13041e12ee3bSFrançois Tigeot 	if (i915_vma_is_map_and_fenceable(vma))
13051e12ee3bSFrançois Tigeot 		addr = (void __force *)i915_vma_pin_iomap(vma);
13061e12ee3bSFrançois Tigeot 	else
13071e12ee3bSFrançois Tigeot 		addr = i915_gem_object_pin_map(vma->obj, map);
13081e12ee3bSFrançois Tigeot 	if (IS_ERR(addr))
13091e12ee3bSFrançois Tigeot 		goto err;
13102c9916cdSFrançois Tigeot 
131171f41f3eSFrançois Tigeot 	ring->vaddr = addr;
13122c9916cdSFrançois Tigeot 	return 0;
13138621f407SFrançois Tigeot 
13141e12ee3bSFrançois Tigeot err:
13151e12ee3bSFrançois Tigeot 	i915_vma_unpin(vma);
13161e12ee3bSFrançois Tigeot 	return PTR_ERR(addr);
13172c9916cdSFrançois Tigeot }
13182c9916cdSFrançois Tigeot 
1319*a85cb24fSFrançois Tigeot void intel_ring_reset(struct intel_ring *ring, u32 tail)
1320*a85cb24fSFrançois Tigeot {
1321*a85cb24fSFrançois Tigeot 	GEM_BUG_ON(!list_empty(&ring->request_list));
1322*a85cb24fSFrançois Tigeot 	ring->tail = tail;
1323*a85cb24fSFrançois Tigeot 	ring->head = tail;
1324*a85cb24fSFrançois Tigeot 	ring->emit = tail;
1325*a85cb24fSFrançois Tigeot 	intel_ring_update_space(ring);
1326*a85cb24fSFrançois Tigeot }
1327*a85cb24fSFrançois Tigeot 
132871f41f3eSFrançois Tigeot void intel_ring_unpin(struct intel_ring *ring)
1329e3adcf8fSFrançois Tigeot {
133071f41f3eSFrançois Tigeot 	GEM_BUG_ON(!ring->vma);
133171f41f3eSFrançois Tigeot 	GEM_BUG_ON(!ring->vaddr);
133271f41f3eSFrançois Tigeot 
1333*a85cb24fSFrançois Tigeot 	/* Discard any unused bytes beyond that submitted to hw. */
1334*a85cb24fSFrançois Tigeot 	intel_ring_reset(ring, ring->tail);
1335*a85cb24fSFrançois Tigeot 
13361e12ee3bSFrançois Tigeot 	if (i915_vma_is_map_and_fenceable(ring->vma))
133771f41f3eSFrançois Tigeot 		i915_vma_unpin_iomap(ring->vma);
13381e12ee3bSFrançois Tigeot 	else
13391e12ee3bSFrançois Tigeot 		i915_gem_object_unpin_map(ring->vma->obj);
134071f41f3eSFrançois Tigeot 	ring->vaddr = NULL;
134171f41f3eSFrançois Tigeot 
13421e12ee3bSFrançois Tigeot 	i915_vma_unpin(ring->vma);
134371f41f3eSFrançois Tigeot }
134471f41f3eSFrançois Tigeot 
13451e12ee3bSFrançois Tigeot static struct i915_vma *
13461e12ee3bSFrançois Tigeot intel_ring_create_vma(struct drm_i915_private *dev_priv, int size)
134724edb884SFrançois Tigeot {
1348e3adcf8fSFrançois Tigeot 	struct drm_i915_gem_object *obj;
13491e12ee3bSFrançois Tigeot 	struct i915_vma *vma;
1350e3adcf8fSFrançois Tigeot 
1351*a85cb24fSFrançois Tigeot 	obj = i915_gem_object_create_stolen(dev_priv, size);
13521e12ee3bSFrançois Tigeot 	if (!obj)
1353*a85cb24fSFrançois Tigeot 		obj = i915_gem_object_create(dev_priv, size);
13541487f786SFrançois Tigeot 	if (IS_ERR(obj))
13551e12ee3bSFrançois Tigeot 		return ERR_CAST(obj);
1356e3adcf8fSFrançois Tigeot 
135724edb884SFrançois Tigeot 	/* mark ring buffers as read-only from GPU side by default */
135824edb884SFrançois Tigeot 	obj->gt_ro = 1;
135924edb884SFrançois Tigeot 
1360*a85cb24fSFrançois Tigeot 	vma = i915_vma_instance(obj, &dev_priv->ggtt.base, NULL);
13611e12ee3bSFrançois Tigeot 	if (IS_ERR(vma))
13621e12ee3bSFrançois Tigeot 		goto err;
1363ba55f2f5SFrançois Tigeot 
13641e12ee3bSFrançois Tigeot 	return vma;
13651e12ee3bSFrançois Tigeot 
13661e12ee3bSFrançois Tigeot err:
13671e12ee3bSFrançois Tigeot 	i915_gem_object_put(obj);
13681e12ee3bSFrançois Tigeot 	return vma;
1369ba55f2f5SFrançois Tigeot }
1370ba55f2f5SFrançois Tigeot 
137171f41f3eSFrançois Tigeot struct intel_ring *
137271f41f3eSFrançois Tigeot intel_engine_create_ring(struct intel_engine_cs *engine, int size)
1373352ff8bdSFrançois Tigeot {
137471f41f3eSFrançois Tigeot 	struct intel_ring *ring;
13751e12ee3bSFrançois Tigeot 	struct i915_vma *vma;
1376352ff8bdSFrançois Tigeot 
137771f41f3eSFrançois Tigeot 	GEM_BUG_ON(!is_power_of_2(size));
13781e12ee3bSFrançois Tigeot 	GEM_BUG_ON(RING_CTL_SIZE(size) & ~RING_NR_PAGES);
137971f41f3eSFrançois Tigeot 
1380352ff8bdSFrançois Tigeot 	ring = kzalloc(sizeof(*ring), GFP_KERNEL);
13811e12ee3bSFrançois Tigeot 	if (!ring)
1382352ff8bdSFrançois Tigeot 		return ERR_PTR(-ENOMEM);
1383352ff8bdSFrançois Tigeot 
13848621f407SFrançois Tigeot 	ring->engine = engine;
1385352ff8bdSFrançois Tigeot 
138671f41f3eSFrançois Tigeot 	INIT_LIST_HEAD(&ring->request_list);
138771f41f3eSFrançois Tigeot 
1388352ff8bdSFrançois Tigeot 	ring->size = size;
1389352ff8bdSFrançois Tigeot 	/* Workaround an erratum on the i830 which causes a hang if
1390352ff8bdSFrançois Tigeot 	 * the TAIL pointer points to within the last 2 cachelines
1391352ff8bdSFrançois Tigeot 	 * of the buffer.
1392352ff8bdSFrançois Tigeot 	 */
1393352ff8bdSFrançois Tigeot 	ring->effective_size = size;
1394*a85cb24fSFrançois Tigeot 	if (IS_I830(engine->i915) || IS_I845G(engine->i915))
1395352ff8bdSFrançois Tigeot 		ring->effective_size -= 2 * CACHELINE_BYTES;
1396352ff8bdSFrançois Tigeot 
1397352ff8bdSFrançois Tigeot 	intel_ring_update_space(ring);
1398352ff8bdSFrançois Tigeot 
13991e12ee3bSFrançois Tigeot 	vma = intel_ring_create_vma(engine->i915, size);
14001e12ee3bSFrançois Tigeot 	if (IS_ERR(vma)) {
1401352ff8bdSFrançois Tigeot 		kfree(ring);
14021e12ee3bSFrançois Tigeot 		return ERR_CAST(vma);
1403352ff8bdSFrançois Tigeot 	}
14041e12ee3bSFrançois Tigeot 	ring->vma = vma;
1405352ff8bdSFrançois Tigeot 
1406352ff8bdSFrançois Tigeot 	return ring;
1407352ff8bdSFrançois Tigeot }
1408352ff8bdSFrançois Tigeot 
1409352ff8bdSFrançois Tigeot void
141071f41f3eSFrançois Tigeot intel_ring_free(struct intel_ring *ring)
1411352ff8bdSFrançois Tigeot {
14124be47400SFrançois Tigeot 	struct drm_i915_gem_object *obj = ring->vma->obj;
14134be47400SFrançois Tigeot 
14144be47400SFrançois Tigeot 	i915_vma_close(ring->vma);
14154be47400SFrançois Tigeot 	__i915_gem_object_release_unless_active(obj);
14164be47400SFrançois Tigeot 
1417352ff8bdSFrançois Tigeot 	kfree(ring);
1418352ff8bdSFrançois Tigeot }
1419352ff8bdSFrançois Tigeot 
1420*a85cb24fSFrançois Tigeot static int context_pin(struct i915_gem_context *ctx)
1421*a85cb24fSFrançois Tigeot {
1422*a85cb24fSFrançois Tigeot 	struct i915_vma *vma = ctx->engine[RCS].state;
1423*a85cb24fSFrançois Tigeot 	int ret;
1424*a85cb24fSFrançois Tigeot 
1425*a85cb24fSFrançois Tigeot 	/* Clear this page out of any CPU caches for coherent swap-in/out.
1426*a85cb24fSFrançois Tigeot 	 * We only want to do this on the first bind so that we do not stall
1427*a85cb24fSFrançois Tigeot 	 * on an active context (which by nature is already on the GPU).
1428*a85cb24fSFrançois Tigeot 	 */
1429*a85cb24fSFrançois Tigeot 	if (!(vma->flags & I915_VMA_GLOBAL_BIND)) {
1430*a85cb24fSFrançois Tigeot 		ret = i915_gem_object_set_to_gtt_domain(vma->obj, false);
1431*a85cb24fSFrançois Tigeot 		if (ret)
1432*a85cb24fSFrançois Tigeot 			return ret;
1433*a85cb24fSFrançois Tigeot 	}
1434*a85cb24fSFrançois Tigeot 
1435*a85cb24fSFrançois Tigeot 	return i915_vma_pin(vma, 0, I915_GTT_MIN_ALIGNMENT,
1436*a85cb24fSFrançois Tigeot 			    PIN_GLOBAL | PIN_HIGH);
1437*a85cb24fSFrançois Tigeot }
1438*a85cb24fSFrançois Tigeot 
1439*a85cb24fSFrançois Tigeot static int intel_ring_context_pin(struct intel_engine_cs *engine,
1440*a85cb24fSFrançois Tigeot 				  struct i915_gem_context *ctx)
14411487f786SFrançois Tigeot {
14421487f786SFrançois Tigeot 	struct intel_context *ce = &ctx->engine[engine->id];
14431487f786SFrançois Tigeot 	int ret;
14441487f786SFrançois Tigeot 
1445303bf270SFrançois Tigeot 	lockdep_assert_held(&ctx->i915->drm.struct_mutex);
14461487f786SFrançois Tigeot 
14471487f786SFrançois Tigeot 	if (ce->pin_count++)
14481487f786SFrançois Tigeot 		return 0;
1449*a85cb24fSFrançois Tigeot 	GEM_BUG_ON(!ce->pin_count); /* no overflow please! */
14501487f786SFrançois Tigeot 
14511487f786SFrançois Tigeot 	if (ce->state) {
1452*a85cb24fSFrançois Tigeot 		ret = context_pin(ctx);
1453*a85cb24fSFrançois Tigeot 		if (ret)
14541487f786SFrançois Tigeot 			goto error;
1455*a85cb24fSFrançois Tigeot 
1456*a85cb24fSFrançois Tigeot 		ce->state->obj->mm.dirty = true;
14574be47400SFrançois Tigeot 	}
14581487f786SFrançois Tigeot 
14591487f786SFrançois Tigeot 	/* The kernel context is only used as a placeholder for flushing the
14601487f786SFrançois Tigeot 	 * active context. It is never used for submitting user rendering and
14611487f786SFrançois Tigeot 	 * as such never requires the golden render context, and so we can skip
14621487f786SFrançois Tigeot 	 * emitting it when we switch to the kernel context. This is required
14631487f786SFrançois Tigeot 	 * as during eviction we cannot allocate and pin the renderstate in
14641487f786SFrançois Tigeot 	 * order to initialise the context.
14651487f786SFrançois Tigeot 	 */
1466*a85cb24fSFrançois Tigeot 	if (i915_gem_context_is_kernel(ctx))
14671487f786SFrançois Tigeot 		ce->initialised = true;
14681487f786SFrançois Tigeot 
146987df8fc6SFrançois Tigeot 	i915_gem_context_get(ctx);
14701487f786SFrançois Tigeot 	return 0;
14711487f786SFrançois Tigeot 
14721487f786SFrançois Tigeot error:
14731487f786SFrançois Tigeot 	ce->pin_count = 0;
14741487f786SFrançois Tigeot 	return ret;
14751487f786SFrançois Tigeot }
14761487f786SFrançois Tigeot 
1477*a85cb24fSFrançois Tigeot static void intel_ring_context_unpin(struct intel_engine_cs *engine,
1478*a85cb24fSFrançois Tigeot 				     struct i915_gem_context *ctx)
14791487f786SFrançois Tigeot {
14801487f786SFrançois Tigeot 	struct intel_context *ce = &ctx->engine[engine->id];
14811487f786SFrançois Tigeot 
1482303bf270SFrançois Tigeot 	lockdep_assert_held(&ctx->i915->drm.struct_mutex);
1483*a85cb24fSFrançois Tigeot 	GEM_BUG_ON(ce->pin_count == 0);
14841487f786SFrançois Tigeot 
14851487f786SFrançois Tigeot 	if (--ce->pin_count)
14861487f786SFrançois Tigeot 		return;
14871487f786SFrançois Tigeot 
14881487f786SFrançois Tigeot 	if (ce->state)
14891e12ee3bSFrançois Tigeot 		i915_vma_unpin(ce->state);
14901487f786SFrançois Tigeot 
149187df8fc6SFrançois Tigeot 	i915_gem_context_put(ctx);
14921487f786SFrançois Tigeot }
14931487f786SFrançois Tigeot 
149487df8fc6SFrançois Tigeot static int intel_init_ring_buffer(struct intel_engine_cs *engine)
1495ba55f2f5SFrançois Tigeot {
149687df8fc6SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
149771f41f3eSFrançois Tigeot 	struct intel_ring *ring;
1498ba55f2f5SFrançois Tigeot 	int ret;
1499ba55f2f5SFrançois Tigeot 
15008621f407SFrançois Tigeot 	WARN_ON(engine->buffer);
15012c9916cdSFrançois Tigeot 
150287df8fc6SFrançois Tigeot 	intel_engine_setup_common(engine);
150387df8fc6SFrançois Tigeot 
150487df8fc6SFrançois Tigeot 	ret = intel_engine_init_common(engine);
1505303bf270SFrançois Tigeot 	if (ret)
1506303bf270SFrançois Tigeot 		goto error;
1507ba55f2f5SFrançois Tigeot 
150871f41f3eSFrançois Tigeot 	ring = intel_engine_create_ring(engine, 32 * PAGE_SIZE);
150971f41f3eSFrançois Tigeot 	if (IS_ERR(ring)) {
151071f41f3eSFrançois Tigeot 		ret = PTR_ERR(ring);
1511aee94f86SFrançois Tigeot 		goto error;
1512aee94f86SFrançois Tigeot 	}
1513352ff8bdSFrançois Tigeot 
15141e12ee3bSFrançois Tigeot 	if (HWS_NEEDS_PHYSICAL(dev_priv)) {
15151e12ee3bSFrançois Tigeot 		WARN_ON(engine->id != RCS);
15161e12ee3bSFrançois Tigeot 		ret = init_phys_status_page(engine);
1517e3adcf8fSFrançois Tigeot 		if (ret)
1518ba55f2f5SFrançois Tigeot 			goto error;
1519ba55f2f5SFrançois Tigeot 	} else {
15201e12ee3bSFrançois Tigeot 		ret = init_status_page(engine);
1521ba55f2f5SFrançois Tigeot 		if (ret)
1522ba55f2f5SFrançois Tigeot 			goto error;
1523ba55f2f5SFrançois Tigeot 	}
1524ba55f2f5SFrançois Tigeot 
1525*a85cb24fSFrançois Tigeot 	/* Ring wraparound at offset 0 sometimes hangs. No idea why. */
1526*a85cb24fSFrançois Tigeot 	ret = intel_ring_pin(ring, I915_GTT_PAGE_SIZE);
15272c9916cdSFrançois Tigeot 	if (ret) {
15281e12ee3bSFrançois Tigeot 		intel_ring_free(ring);
1529ba55f2f5SFrançois Tigeot 		goto error;
1530ba55f2f5SFrançois Tigeot 	}
15311e12ee3bSFrançois Tigeot 	engine->buffer = ring;
1532e3adcf8fSFrançois Tigeot 
1533e3adcf8fSFrançois Tigeot 	return 0;
1534e3adcf8fSFrançois Tigeot 
1535ba55f2f5SFrançois Tigeot error:
153671f41f3eSFrançois Tigeot 	intel_engine_cleanup(engine);
1537e3adcf8fSFrançois Tigeot 	return ret;
1538e3adcf8fSFrançois Tigeot }
1539e3adcf8fSFrançois Tigeot 
154071f41f3eSFrançois Tigeot void intel_engine_cleanup(struct intel_engine_cs *engine)
1541e3adcf8fSFrançois Tigeot {
15422c9916cdSFrançois Tigeot 	struct drm_i915_private *dev_priv;
1543e3adcf8fSFrançois Tigeot 
15441487f786SFrançois Tigeot 	dev_priv = engine->i915;
15452c9916cdSFrançois Tigeot 
15468621f407SFrançois Tigeot 	if (engine->buffer) {
15471e12ee3bSFrançois Tigeot 		WARN_ON(INTEL_GEN(dev_priv) > 2 &&
15481e12ee3bSFrançois Tigeot 			(I915_READ_MODE(engine) & MODE_IDLE) == 0);
1549b030f26bSFrançois Tigeot 
155071f41f3eSFrançois Tigeot 		intel_ring_unpin(engine->buffer);
155171f41f3eSFrançois Tigeot 		intel_ring_free(engine->buffer);
15528621f407SFrançois Tigeot 		engine->buffer = NULL;
1553aee94f86SFrançois Tigeot 	}
1554e3adcf8fSFrançois Tigeot 
15558621f407SFrançois Tigeot 	if (engine->cleanup)
15568621f407SFrançois Tigeot 		engine->cleanup(engine);
1557e3adcf8fSFrançois Tigeot 
15581e12ee3bSFrançois Tigeot 	if (HWS_NEEDS_PHYSICAL(dev_priv)) {
15598621f407SFrançois Tigeot 		WARN_ON(engine->id != RCS);
15608621f407SFrançois Tigeot 		cleanup_phys_status_page(engine);
15611e12ee3bSFrançois Tigeot 	} else {
15621e12ee3bSFrançois Tigeot 		cleanup_status_page(engine);
1563c0e85e96SFrançois Tigeot 	}
1564ba55f2f5SFrançois Tigeot 
156571f41f3eSFrançois Tigeot 	intel_engine_cleanup_common(engine);
15661487f786SFrançois Tigeot 
15671487f786SFrançois Tigeot 	engine->i915 = NULL;
15681e12ee3bSFrançois Tigeot 	dev_priv->engine[engine->id] = NULL;
15691e12ee3bSFrançois Tigeot 	kfree(engine);
15701e12ee3bSFrançois Tigeot }
15711e12ee3bSFrançois Tigeot 
15721e12ee3bSFrançois Tigeot void intel_legacy_submission_resume(struct drm_i915_private *dev_priv)
15731e12ee3bSFrançois Tigeot {
15741e12ee3bSFrançois Tigeot 	struct intel_engine_cs *engine;
15751e12ee3bSFrançois Tigeot 	enum intel_engine_id id;
15761e12ee3bSFrançois Tigeot 
1577*a85cb24fSFrançois Tigeot 	/* Restart from the beginning of the rings for convenience */
1578*a85cb24fSFrançois Tigeot 	for_each_engine(engine, dev_priv, id)
1579*a85cb24fSFrançois Tigeot 		intel_ring_reset(engine->buffer, 0);
1580e3adcf8fSFrançois Tigeot }
1581e3adcf8fSFrançois Tigeot 
1582*a85cb24fSFrançois Tigeot static int ring_request_alloc(struct drm_i915_gem_request *request)
1583b5c29a34SFrançois Tigeot {
1584*a85cb24fSFrançois Tigeot 	u32 *cs;
1585*a85cb24fSFrançois Tigeot 
1586*a85cb24fSFrançois Tigeot 	GEM_BUG_ON(!request->ctx->engine[request->engine->id].pin_count);
15879edbd4a0SFrançois Tigeot 
15881487f786SFrançois Tigeot 	/* Flush enough space to reduce the likelihood of waiting after
15891487f786SFrançois Tigeot 	 * we start building the request - in which case we will just
15901487f786SFrançois Tigeot 	 * have to repeat work.
1591a05eeebfSFrançois Tigeot 	 */
15921487f786SFrançois Tigeot 	request->reserved_space += LEGACY_REQUEST_SIZE;
1593a2fdbec6SFrançois Tigeot 
1594*a85cb24fSFrançois Tigeot 	GEM_BUG_ON(!request->engine->buffer);
159571f41f3eSFrançois Tigeot 	request->ring = request->engine->buffer;
1596a2fdbec6SFrançois Tigeot 
1597*a85cb24fSFrançois Tigeot 	cs = intel_ring_begin(request, 0);
1598*a85cb24fSFrançois Tigeot 	if (IS_ERR(cs))
1599*a85cb24fSFrançois Tigeot 		return PTR_ERR(cs);
1600a05eeebfSFrançois Tigeot 
16011487f786SFrançois Tigeot 	request->reserved_space -= LEGACY_REQUEST_SIZE;
16021487f786SFrançois Tigeot 	return 0;
1603a05eeebfSFrançois Tigeot }
1604a05eeebfSFrançois Tigeot 
16058621f407SFrançois Tigeot static int wait_for_space(struct drm_i915_gem_request *req, int bytes)
1606a05eeebfSFrançois Tigeot {
160771f41f3eSFrançois Tigeot 	struct intel_ring *ring = req->ring;
16088621f407SFrançois Tigeot 	struct drm_i915_gem_request *target;
16094be47400SFrançois Tigeot 	long timeout;
16104be47400SFrançois Tigeot 
16114be47400SFrançois Tigeot 	lockdep_assert_held(&req->i915->drm.struct_mutex);
16128621f407SFrançois Tigeot 
161371f41f3eSFrançois Tigeot 	intel_ring_update_space(ring);
161471f41f3eSFrançois Tigeot 	if (ring->space >= bytes)
16158621f407SFrançois Tigeot 		return 0;
16168621f407SFrançois Tigeot 
16178621f407SFrançois Tigeot 	/*
16188621f407SFrançois Tigeot 	 * Space is reserved in the ringbuffer for finalising the request,
16198621f407SFrançois Tigeot 	 * as that cannot be allowed to fail. During request finalisation,
16208621f407SFrançois Tigeot 	 * reserved_space is set to 0 to stop the overallocation and the
16218621f407SFrançois Tigeot 	 * assumption is that then we never need to wait (which has the
16228621f407SFrançois Tigeot 	 * risk of failing with EINTR).
16238621f407SFrançois Tigeot 	 *
16248621f407SFrançois Tigeot 	 * See also i915_gem_request_alloc() and i915_add_request().
16258621f407SFrançois Tigeot 	 */
16261487f786SFrançois Tigeot 	GEM_BUG_ON(!req->reserved_space);
16278621f407SFrançois Tigeot 
162871f41f3eSFrançois Tigeot 	list_for_each_entry(target, &ring->request_list, ring_link) {
16298621f407SFrançois Tigeot 		unsigned space;
16308621f407SFrançois Tigeot 
16318621f407SFrançois Tigeot 		/* Would completion of this request free enough space? */
1632*a85cb24fSFrançois Tigeot 		space = __intel_ring_space(target->postfix, ring->emit,
163371f41f3eSFrançois Tigeot 					   ring->size);
16348621f407SFrançois Tigeot 		if (space >= bytes)
16358621f407SFrançois Tigeot 			break;
16368621f407SFrançois Tigeot 	}
16378621f407SFrançois Tigeot 
163871f41f3eSFrançois Tigeot 	if (WARN_ON(&target->ring_link == &ring->request_list))
16398621f407SFrançois Tigeot 		return -ENOSPC;
16408621f407SFrançois Tigeot 
16414be47400SFrançois Tigeot 	timeout = i915_wait_request(target,
16421e12ee3bSFrançois Tigeot 				    I915_WAIT_INTERRUPTIBLE | I915_WAIT_LOCKED,
16434be47400SFrançois Tigeot 				    MAX_SCHEDULE_TIMEOUT);
16444be47400SFrançois Tigeot 	if (timeout < 0)
16454be47400SFrançois Tigeot 		return timeout;
164671f41f3eSFrançois Tigeot 
164771f41f3eSFrançois Tigeot 	i915_gem_request_retire_upto(target);
164871f41f3eSFrançois Tigeot 
164971f41f3eSFrançois Tigeot 	intel_ring_update_space(ring);
165071f41f3eSFrançois Tigeot 	GEM_BUG_ON(ring->space < bytes);
165171f41f3eSFrançois Tigeot 	return 0;
16528621f407SFrançois Tigeot }
16538621f407SFrançois Tigeot 
1654*a85cb24fSFrançois Tigeot u32 *intel_ring_begin(struct drm_i915_gem_request *req, int num_dwords)
16558621f407SFrançois Tigeot {
165671f41f3eSFrançois Tigeot 	struct intel_ring *ring = req->ring;
1657*a85cb24fSFrançois Tigeot 	int remain_actual = ring->size - ring->emit;
1658*a85cb24fSFrançois Tigeot 	int remain_usable = ring->effective_size - ring->emit;
16598621f407SFrançois Tigeot 	int bytes = num_dwords * sizeof(u32);
16608621f407SFrançois Tigeot 	int total_bytes, wait_bytes;
1661a05eeebfSFrançois Tigeot 	bool need_wrap = false;
1662*a85cb24fSFrançois Tigeot 	u32 *cs;
1663a05eeebfSFrançois Tigeot 
16641487f786SFrançois Tigeot 	total_bytes = bytes + req->reserved_space;
1665a05eeebfSFrançois Tigeot 
1666a05eeebfSFrançois Tigeot 	if (unlikely(bytes > remain_usable)) {
1667a05eeebfSFrançois Tigeot 		/*
1668a05eeebfSFrançois Tigeot 		 * Not enough space for the basic request. So need to flush
1669a05eeebfSFrançois Tigeot 		 * out the remainder and then wait for base + reserved.
1670a05eeebfSFrançois Tigeot 		 */
1671a05eeebfSFrançois Tigeot 		wait_bytes = remain_actual + total_bytes;
1672a05eeebfSFrançois Tigeot 		need_wrap = true;
16738621f407SFrançois Tigeot 	} else if (unlikely(total_bytes > remain_usable)) {
1674a05eeebfSFrançois Tigeot 		/*
1675a05eeebfSFrançois Tigeot 		 * The base request will fit but the reserved space
16768621f407SFrançois Tigeot 		 * falls off the end. So we don't need an immediate wrap
1677c0e85e96SFrançois Tigeot 		 * and only need to effectively wait for the reserved
1678c0e85e96SFrançois Tigeot 		 * size space from the start of ringbuffer.
1679a05eeebfSFrançois Tigeot 		 */
16801487f786SFrançois Tigeot 		wait_bytes = remain_actual + req->reserved_space;
16818621f407SFrançois Tigeot 	} else {
1682a05eeebfSFrançois Tigeot 		/* No wrapping required, just waiting. */
1683a05eeebfSFrançois Tigeot 		wait_bytes = total_bytes;
1684a05eeebfSFrançois Tigeot 	}
1685a05eeebfSFrançois Tigeot 
168671f41f3eSFrançois Tigeot 	if (wait_bytes > ring->space) {
16878621f407SFrançois Tigeot 		int ret = wait_for_space(req, wait_bytes);
1688a2fdbec6SFrançois Tigeot 		if (unlikely(ret))
1689*a85cb24fSFrançois Tigeot 			return ERR_PTR(ret);
1690a2fdbec6SFrançois Tigeot 	}
1691a2fdbec6SFrançois Tigeot 
16928621f407SFrançois Tigeot 	if (unlikely(need_wrap)) {
169371f41f3eSFrançois Tigeot 		GEM_BUG_ON(remain_actual > ring->space);
1694*a85cb24fSFrançois Tigeot 		GEM_BUG_ON(ring->emit + remain_actual > ring->size);
16958621f407SFrançois Tigeot 
16968621f407SFrançois Tigeot 		/* Fill the tail with MI_NOOP */
1697*a85cb24fSFrançois Tigeot 		memset(ring->vaddr + ring->emit, 0, remain_actual);
1698*a85cb24fSFrançois Tigeot 		ring->emit = 0;
169971f41f3eSFrançois Tigeot 		ring->space -= remain_actual;
1700a2fdbec6SFrançois Tigeot 	}
1701a2fdbec6SFrançois Tigeot 
1702*a85cb24fSFrançois Tigeot 	GEM_BUG_ON(ring->emit > ring->size - bytes);
1703*a85cb24fSFrançois Tigeot 	cs = ring->vaddr + ring->emit;
1704*a85cb24fSFrançois Tigeot 	ring->emit += bytes;
170571f41f3eSFrançois Tigeot 	ring->space -= bytes;
170671f41f3eSFrançois Tigeot 	GEM_BUG_ON(ring->space < 0);
1707*a85cb24fSFrançois Tigeot 
1708*a85cb24fSFrançois Tigeot 	return cs;
17099edbd4a0SFrançois Tigeot }
17109edbd4a0SFrançois Tigeot 
17119edbd4a0SFrançois Tigeot /* Align the ring tail to a cacheline boundary */
1712a05eeebfSFrançois Tigeot int intel_ring_cacheline_align(struct drm_i915_gem_request *req)
17139edbd4a0SFrançois Tigeot {
171471f41f3eSFrançois Tigeot 	int num_dwords =
1715*a85cb24fSFrançois Tigeot 		(req->ring->emit & (CACHELINE_BYTES - 1)) / sizeof(uint32_t);
1716*a85cb24fSFrançois Tigeot 	u32 *cs;
17179edbd4a0SFrançois Tigeot 
17189edbd4a0SFrançois Tigeot 	if (num_dwords == 0)
17199edbd4a0SFrançois Tigeot 		return 0;
17209edbd4a0SFrançois Tigeot 
1721ba55f2f5SFrançois Tigeot 	num_dwords = CACHELINE_BYTES / sizeof(uint32_t) - num_dwords;
1722*a85cb24fSFrançois Tigeot 	cs = intel_ring_begin(req, num_dwords);
1723*a85cb24fSFrançois Tigeot 	if (IS_ERR(cs))
1724*a85cb24fSFrançois Tigeot 		return PTR_ERR(cs);
17259edbd4a0SFrançois Tigeot 
17269edbd4a0SFrançois Tigeot 	while (num_dwords--)
1727*a85cb24fSFrançois Tigeot 		*cs++ = MI_NOOP;
17289edbd4a0SFrançois Tigeot 
1729*a85cb24fSFrançois Tigeot 	intel_ring_advance(req, cs);
17309edbd4a0SFrançois Tigeot 
17319edbd4a0SFrançois Tigeot 	return 0;
1732e3adcf8fSFrançois Tigeot }
1733e3adcf8fSFrançois Tigeot 
173471f41f3eSFrançois Tigeot static void gen6_bsd_submit_request(struct drm_i915_gem_request *request)
1735e3adcf8fSFrançois Tigeot {
173671f41f3eSFrançois Tigeot 	struct drm_i915_private *dev_priv = request->i915;
17371487f786SFrançois Tigeot 
17381487f786SFrançois Tigeot 	intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL);
1739e3adcf8fSFrançois Tigeot 
1740e3adcf8fSFrançois Tigeot        /* Every tail move must follow the sequence below */
1741f4e1c372SFrançois Tigeot 
1742f4e1c372SFrançois Tigeot 	/* Disable notification that the ring is IDLE. The GT
1743f4e1c372SFrançois Tigeot 	 * will then assume that it is busy and bring it out of rc6.
1744f4e1c372SFrançois Tigeot 	 */
17451487f786SFrançois Tigeot 	I915_WRITE_FW(GEN6_BSD_SLEEP_PSMI_CONTROL,
1746f4e1c372SFrançois Tigeot 		      _MASKED_BIT_ENABLE(GEN6_BSD_SLEEP_MSG_DISABLE));
1747e3adcf8fSFrançois Tigeot 
1748f4e1c372SFrançois Tigeot 	/* Clear the context id. Here be magic! */
17491487f786SFrançois Tigeot 	I915_WRITE64_FW(GEN6_BSD_RNCID, 0x0);
1750e3adcf8fSFrançois Tigeot 
1751f4e1c372SFrançois Tigeot 	/* Wait for the ring not to be idle, i.e. for it to wake up. */
17521487f786SFrançois Tigeot 	if (intel_wait_for_register_fw(dev_priv,
17531487f786SFrançois Tigeot 				       GEN6_BSD_SLEEP_PSMI_CONTROL,
17541487f786SFrançois Tigeot 				       GEN6_BSD_SLEEP_INDICATOR,
17551487f786SFrançois Tigeot 				       0,
1756f4e1c372SFrançois Tigeot 				       50))
1757f4e1c372SFrançois Tigeot 		DRM_ERROR("timed out waiting for the BSD ring to wake up\n");
1758f4e1c372SFrançois Tigeot 
1759f4e1c372SFrançois Tigeot 	/* Now that the ring is fully powered up, update the tail */
176071f41f3eSFrançois Tigeot 	i9xx_submit_request(request);
1761f4e1c372SFrançois Tigeot 
1762f4e1c372SFrançois Tigeot 	/* Let the ring send IDLE messages to the GT again,
1763f4e1c372SFrançois Tigeot 	 * and so let it sleep to conserve power when idle.
1764f4e1c372SFrançois Tigeot 	 */
17651487f786SFrançois Tigeot 	I915_WRITE_FW(GEN6_BSD_SLEEP_PSMI_CONTROL,
1766f4e1c372SFrançois Tigeot 		      _MASKED_BIT_DISABLE(GEN6_BSD_SLEEP_MSG_DISABLE));
17671487f786SFrançois Tigeot 
17681487f786SFrançois Tigeot 	intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL);
1769e3adcf8fSFrançois Tigeot }
1770e3adcf8fSFrançois Tigeot 
177171f41f3eSFrançois Tigeot static int gen6_bsd_ring_flush(struct drm_i915_gem_request *req, u32 mode)
1772e3adcf8fSFrançois Tigeot {
1773*a85cb24fSFrançois Tigeot 	u32 cmd, *cs;
1774e3adcf8fSFrançois Tigeot 
1775*a85cb24fSFrançois Tigeot 	cs = intel_ring_begin(req, 4);
1776*a85cb24fSFrançois Tigeot 	if (IS_ERR(cs))
1777*a85cb24fSFrançois Tigeot 		return PTR_ERR(cs);
1778e3adcf8fSFrançois Tigeot 
1779e3adcf8fSFrançois Tigeot 	cmd = MI_FLUSH_DW;
17801487f786SFrançois Tigeot 	if (INTEL_GEN(req->i915) >= 8)
17819edbd4a0SFrançois Tigeot 		cmd += 1;
17822c9916cdSFrançois Tigeot 
17832c9916cdSFrançois Tigeot 	/* We always require a command barrier so that subsequent
17842c9916cdSFrançois Tigeot 	 * commands, such as breadcrumb interrupts, are strictly ordered
17852c9916cdSFrançois Tigeot 	 * wrt the contents of the write cache being flushed to memory
17862c9916cdSFrançois Tigeot 	 * (and thus being coherent from the CPU).
17872c9916cdSFrançois Tigeot 	 */
17882c9916cdSFrançois Tigeot 	cmd |= MI_FLUSH_DW_STORE_INDEX | MI_FLUSH_DW_OP_STOREDW;
17892c9916cdSFrançois Tigeot 
1790b5c29a34SFrançois Tigeot 	/*
1791b5c29a34SFrançois Tigeot 	 * Bspec vol 1c.5 - video engine command streamer:
1792b5c29a34SFrançois Tigeot 	 * "If ENABLED, all TLBs will be invalidated once the flush
1793b5c29a34SFrançois Tigeot 	 * operation is complete. This bit is only valid when the
1794b5c29a34SFrançois Tigeot 	 * Post-Sync Operation field is a value of 1h or 3h."
1795b5c29a34SFrançois Tigeot 	 */
179671f41f3eSFrançois Tigeot 	if (mode & EMIT_INVALIDATE)
17972c9916cdSFrançois Tigeot 		cmd |= MI_INVALIDATE_TLB | MI_INVALIDATE_BSD;
17982c9916cdSFrançois Tigeot 
1799*a85cb24fSFrançois Tigeot 	*cs++ = cmd;
1800*a85cb24fSFrançois Tigeot 	*cs++ = I915_GEM_HWS_SCRATCH_ADDR | MI_FLUSH_DW_USE_GTT;
18011487f786SFrançois Tigeot 	if (INTEL_GEN(req->i915) >= 8) {
1802*a85cb24fSFrançois Tigeot 		*cs++ = 0; /* upper addr */
1803*a85cb24fSFrançois Tigeot 		*cs++ = 0; /* value */
18049edbd4a0SFrançois Tigeot 	} else  {
1805*a85cb24fSFrançois Tigeot 		*cs++ = 0;
1806*a85cb24fSFrançois Tigeot 		*cs++ = MI_NOOP;
18079edbd4a0SFrançois Tigeot 	}
1808*a85cb24fSFrançois Tigeot 	intel_ring_advance(req, cs);
18099edbd4a0SFrançois Tigeot 	return 0;
18109edbd4a0SFrançois Tigeot }
18119edbd4a0SFrançois Tigeot 
18129edbd4a0SFrançois Tigeot static int
181371f41f3eSFrançois Tigeot gen8_emit_bb_start(struct drm_i915_gem_request *req,
1814ba55f2f5SFrançois Tigeot 		   u64 offset, u32 len,
181571f41f3eSFrançois Tigeot 		   unsigned int dispatch_flags)
18169edbd4a0SFrançois Tigeot {
181771f41f3eSFrançois Tigeot 	bool ppgtt = USES_PPGTT(req->i915) &&
1818477eb7f9SFrançois Tigeot 			!(dispatch_flags & I915_DISPATCH_SECURE);
1819*a85cb24fSFrançois Tigeot 	u32 *cs;
18209edbd4a0SFrançois Tigeot 
1821*a85cb24fSFrançois Tigeot 	cs = intel_ring_begin(req, 4);
1822*a85cb24fSFrançois Tigeot 	if (IS_ERR(cs))
1823*a85cb24fSFrançois Tigeot 		return PTR_ERR(cs);
18249edbd4a0SFrançois Tigeot 
18259edbd4a0SFrançois Tigeot 	/* FIXME(BDW): Address space and security selectors. */
1826*a85cb24fSFrançois Tigeot 	*cs++ = MI_BATCH_BUFFER_START_GEN8 | (ppgtt << 8) | (dispatch_flags &
1827*a85cb24fSFrançois Tigeot 		I915_DISPATCH_RS ? MI_BATCH_RESOURCE_STREAMER : 0);
1828*a85cb24fSFrançois Tigeot 	*cs++ = lower_32_bits(offset);
1829*a85cb24fSFrançois Tigeot 	*cs++ = upper_32_bits(offset);
1830*a85cb24fSFrançois Tigeot 	*cs++ = MI_NOOP;
1831*a85cb24fSFrançois Tigeot 	intel_ring_advance(req, cs);
18329edbd4a0SFrançois Tigeot 
1833e3adcf8fSFrançois Tigeot 	return 0;
1834e3adcf8fSFrançois Tigeot }
1835e3adcf8fSFrançois Tigeot 
1836e3adcf8fSFrançois Tigeot static int
183771f41f3eSFrançois Tigeot hsw_emit_bb_start(struct drm_i915_gem_request *req,
1838ba55f2f5SFrançois Tigeot 		  u64 offset, u32 len,
183971f41f3eSFrançois Tigeot 		  unsigned int dispatch_flags)
1840e3adcf8fSFrançois Tigeot {
1841*a85cb24fSFrançois Tigeot 	u32 *cs;
1842e3adcf8fSFrançois Tigeot 
1843*a85cb24fSFrançois Tigeot 	cs = intel_ring_begin(req, 2);
1844*a85cb24fSFrançois Tigeot 	if (IS_ERR(cs))
1845*a85cb24fSFrançois Tigeot 		return PTR_ERR(cs);
1846e3adcf8fSFrançois Tigeot 
1847*a85cb24fSFrançois Tigeot 	*cs++ = MI_BATCH_BUFFER_START | (dispatch_flags & I915_DISPATCH_SECURE ?
1848a05eeebfSFrançois Tigeot 		0 : MI_BATCH_PPGTT_HSW | MI_BATCH_NON_SECURE_HSW) |
1849a05eeebfSFrançois Tigeot 		(dispatch_flags & I915_DISPATCH_RS ?
1850*a85cb24fSFrançois Tigeot 		MI_BATCH_RESOURCE_STREAMER : 0);
1851b5c29a34SFrançois Tigeot 	/* bit0-7 is the length on GEN6+ */
1852*a85cb24fSFrançois Tigeot 	*cs++ = offset;
1853*a85cb24fSFrançois Tigeot 	intel_ring_advance(req, cs);
1854b5c29a34SFrançois Tigeot 
1855b5c29a34SFrançois Tigeot 	return 0;
1856b5c29a34SFrançois Tigeot }
1857b5c29a34SFrançois Tigeot 
1858b5c29a34SFrançois Tigeot static int
185971f41f3eSFrançois Tigeot gen6_emit_bb_start(struct drm_i915_gem_request *req,
1860ba55f2f5SFrançois Tigeot 		   u64 offset, u32 len,
186171f41f3eSFrançois Tigeot 		   unsigned int dispatch_flags)
1862b5c29a34SFrançois Tigeot {
1863*a85cb24fSFrançois Tigeot 	u32 *cs;
1864b5c29a34SFrançois Tigeot 
1865*a85cb24fSFrançois Tigeot 	cs = intel_ring_begin(req, 2);
1866*a85cb24fSFrançois Tigeot 	if (IS_ERR(cs))
1867*a85cb24fSFrançois Tigeot 		return PTR_ERR(cs);
1868b5c29a34SFrançois Tigeot 
1869*a85cb24fSFrançois Tigeot 	*cs++ = MI_BATCH_BUFFER_START | (dispatch_flags & I915_DISPATCH_SECURE ?
1870*a85cb24fSFrançois Tigeot 		0 : MI_BATCH_NON_SECURE_I965);
1871e3adcf8fSFrançois Tigeot 	/* bit0-7 is the length on GEN6+ */
1872*a85cb24fSFrançois Tigeot 	*cs++ = offset;
1873*a85cb24fSFrançois Tigeot 	intel_ring_advance(req, cs);
1874e3adcf8fSFrançois Tigeot 
1875e3adcf8fSFrançois Tigeot 	return 0;
1876e3adcf8fSFrançois Tigeot }
1877e3adcf8fSFrançois Tigeot 
1878e3adcf8fSFrançois Tigeot /* Blitter support (SandyBridge+) */
1879e3adcf8fSFrançois Tigeot 
188071f41f3eSFrançois Tigeot static int gen6_ring_flush(struct drm_i915_gem_request *req, u32 mode)
1881e3adcf8fSFrançois Tigeot {
1882*a85cb24fSFrançois Tigeot 	u32 cmd, *cs;
1883e3adcf8fSFrançois Tigeot 
1884*a85cb24fSFrançois Tigeot 	cs = intel_ring_begin(req, 4);
1885*a85cb24fSFrançois Tigeot 	if (IS_ERR(cs))
1886*a85cb24fSFrançois Tigeot 		return PTR_ERR(cs);
1887e3adcf8fSFrançois Tigeot 
1888e3adcf8fSFrançois Tigeot 	cmd = MI_FLUSH_DW;
18891487f786SFrançois Tigeot 	if (INTEL_GEN(req->i915) >= 8)
18909edbd4a0SFrançois Tigeot 		cmd += 1;
18912c9916cdSFrançois Tigeot 
18922c9916cdSFrançois Tigeot 	/* We always require a command barrier so that subsequent
18932c9916cdSFrançois Tigeot 	 * commands, such as breadcrumb interrupts, are strictly ordered
18942c9916cdSFrançois Tigeot 	 * wrt the contents of the write cache being flushed to memory
18952c9916cdSFrançois Tigeot 	 * (and thus being coherent from the CPU).
18962c9916cdSFrançois Tigeot 	 */
18972c9916cdSFrançois Tigeot 	cmd |= MI_FLUSH_DW_STORE_INDEX | MI_FLUSH_DW_OP_STOREDW;
18982c9916cdSFrançois Tigeot 
1899b5c29a34SFrançois Tigeot 	/*
1900b5c29a34SFrançois Tigeot 	 * Bspec vol 1c.3 - blitter engine command streamer:
1901b5c29a34SFrançois Tigeot 	 * "If ENABLED, all TLBs will be invalidated once the flush
1902b5c29a34SFrançois Tigeot 	 * operation is complete. This bit is only valid when the
1903b5c29a34SFrançois Tigeot 	 * Post-Sync Operation field is a value of 1h or 3h."
1904b5c29a34SFrançois Tigeot 	 */
190571f41f3eSFrançois Tigeot 	if (mode & EMIT_INVALIDATE)
19062c9916cdSFrançois Tigeot 		cmd |= MI_INVALIDATE_TLB;
1907*a85cb24fSFrançois Tigeot 	*cs++ = cmd;
1908*a85cb24fSFrançois Tigeot 	*cs++ = I915_GEM_HWS_SCRATCH_ADDR | MI_FLUSH_DW_USE_GTT;
19091487f786SFrançois Tigeot 	if (INTEL_GEN(req->i915) >= 8) {
1910*a85cb24fSFrançois Tigeot 		*cs++ = 0; /* upper addr */
1911*a85cb24fSFrançois Tigeot 		*cs++ = 0; /* value */
19129edbd4a0SFrançois Tigeot 	} else  {
1913*a85cb24fSFrançois Tigeot 		*cs++ = 0;
1914*a85cb24fSFrançois Tigeot 		*cs++ = MI_NOOP;
19159edbd4a0SFrançois Tigeot 	}
1916*a85cb24fSFrançois Tigeot 	intel_ring_advance(req, cs);
19175d0b1887SFrançois Tigeot 
1918e3adcf8fSFrançois Tigeot 	return 0;
1919e3adcf8fSFrançois Tigeot }
1920e3adcf8fSFrançois Tigeot 
19211487f786SFrançois Tigeot static void intel_ring_init_semaphores(struct drm_i915_private *dev_priv,
19221487f786SFrançois Tigeot 				       struct intel_engine_cs *engine)
19231487f786SFrançois Tigeot {
19241487f786SFrançois Tigeot 	struct drm_i915_gem_object *obj;
19251487f786SFrançois Tigeot 	int ret, i;
19261487f786SFrançois Tigeot 
192787df8fc6SFrançois Tigeot 	if (!i915.semaphores)
19281487f786SFrançois Tigeot 		return;
19291487f786SFrançois Tigeot 
19301e12ee3bSFrançois Tigeot 	if (INTEL_GEN(dev_priv) >= 8 && !dev_priv->semaphore) {
19311e12ee3bSFrançois Tigeot 		struct i915_vma *vma;
19321487f786SFrançois Tigeot 
1933*a85cb24fSFrançois Tigeot 		obj = i915_gem_object_create(dev_priv, PAGE_SIZE);
19341e12ee3bSFrançois Tigeot 		if (IS_ERR(obj))
19351e12ee3bSFrançois Tigeot 			goto err;
19361e12ee3bSFrançois Tigeot 
1937*a85cb24fSFrançois Tigeot 		vma = i915_vma_instance(obj, &dev_priv->ggtt.base, NULL);
19381e12ee3bSFrançois Tigeot 		if (IS_ERR(vma))
19391e12ee3bSFrançois Tigeot 			goto err_obj;
19401e12ee3bSFrançois Tigeot 
19411e12ee3bSFrançois Tigeot 		ret = i915_gem_object_set_to_gtt_domain(obj, false);
19421e12ee3bSFrançois Tigeot 		if (ret)
19431e12ee3bSFrançois Tigeot 			goto err_obj;
19441e12ee3bSFrançois Tigeot 
19451e12ee3bSFrançois Tigeot 		ret = i915_vma_pin(vma, 0, 0, PIN_GLOBAL | PIN_HIGH);
19461e12ee3bSFrançois Tigeot 		if (ret)
19471e12ee3bSFrançois Tigeot 			goto err_obj;
19481e12ee3bSFrançois Tigeot 
19491e12ee3bSFrançois Tigeot 		dev_priv->semaphore = vma;
19501e12ee3bSFrançois Tigeot 	}
19511487f786SFrançois Tigeot 
19521487f786SFrançois Tigeot 	if (INTEL_GEN(dev_priv) >= 8) {
19531e12ee3bSFrançois Tigeot 		u32 offset = i915_ggtt_offset(dev_priv->semaphore);
19541487f786SFrançois Tigeot 
195571f41f3eSFrançois Tigeot 		engine->semaphore.sync_to = gen8_ring_sync_to;
19561487f786SFrançois Tigeot 		engine->semaphore.signal = gen8_xcs_signal;
19571487f786SFrançois Tigeot 
19581487f786SFrançois Tigeot 		for (i = 0; i < I915_NUM_ENGINES; i++) {
19591e12ee3bSFrançois Tigeot 			u32 ring_offset;
19601487f786SFrançois Tigeot 
19611487f786SFrançois Tigeot 			if (i != engine->id)
19621487f786SFrançois Tigeot 				ring_offset = offset + GEN8_SEMAPHORE_OFFSET(engine->id, i);
19631487f786SFrançois Tigeot 			else
19641487f786SFrançois Tigeot 				ring_offset = MI_SEMAPHORE_SYNC_INVALID;
19651487f786SFrançois Tigeot 
19661487f786SFrançois Tigeot 			engine->semaphore.signal_ggtt[i] = ring_offset;
19671487f786SFrançois Tigeot 		}
19681487f786SFrançois Tigeot 	} else if (INTEL_GEN(dev_priv) >= 6) {
196971f41f3eSFrançois Tigeot 		engine->semaphore.sync_to = gen6_ring_sync_to;
19701487f786SFrançois Tigeot 		engine->semaphore.signal = gen6_signal;
19711487f786SFrançois Tigeot 
19721487f786SFrançois Tigeot 		/*
19731487f786SFrançois Tigeot 		 * The current semaphore is only applied on pre-gen8
19741487f786SFrançois Tigeot 		 * platform.  And there is no VCS2 ring on the pre-gen8
19751487f786SFrançois Tigeot 		 * platform. So the semaphore between RCS and VCS2 is
19761487f786SFrançois Tigeot 		 * initialized as INVALID.  Gen8 will initialize the
19771487f786SFrançois Tigeot 		 * sema between VCS2 and RCS later.
19781487f786SFrançois Tigeot 		 */
19791e12ee3bSFrançois Tigeot 		for (i = 0; i < GEN6_NUM_SEMAPHORES; i++) {
19801487f786SFrançois Tigeot 			static const struct {
19811487f786SFrançois Tigeot 				u32 wait_mbox;
19821487f786SFrançois Tigeot 				i915_reg_t mbox_reg;
19831e12ee3bSFrançois Tigeot 			} sem_data[GEN6_NUM_SEMAPHORES][GEN6_NUM_SEMAPHORES] = {
19841e12ee3bSFrançois Tigeot 				[RCS_HW] = {
19851e12ee3bSFrançois Tigeot 					[VCS_HW] =  { .wait_mbox = MI_SEMAPHORE_SYNC_RV,  .mbox_reg = GEN6_VRSYNC },
19861e12ee3bSFrançois Tigeot 					[BCS_HW] =  { .wait_mbox = MI_SEMAPHORE_SYNC_RB,  .mbox_reg = GEN6_BRSYNC },
19871e12ee3bSFrançois Tigeot 					[VECS_HW] = { .wait_mbox = MI_SEMAPHORE_SYNC_RVE, .mbox_reg = GEN6_VERSYNC },
19881487f786SFrançois Tigeot 				},
19891e12ee3bSFrançois Tigeot 				[VCS_HW] = {
19901e12ee3bSFrançois Tigeot 					[RCS_HW] =  { .wait_mbox = MI_SEMAPHORE_SYNC_VR,  .mbox_reg = GEN6_RVSYNC },
19911e12ee3bSFrançois Tigeot 					[BCS_HW] =  { .wait_mbox = MI_SEMAPHORE_SYNC_VB,  .mbox_reg = GEN6_BVSYNC },
19921e12ee3bSFrançois Tigeot 					[VECS_HW] = { .wait_mbox = MI_SEMAPHORE_SYNC_VVE, .mbox_reg = GEN6_VEVSYNC },
19931487f786SFrançois Tigeot 				},
19941e12ee3bSFrançois Tigeot 				[BCS_HW] = {
19951e12ee3bSFrançois Tigeot 					[RCS_HW] =  { .wait_mbox = MI_SEMAPHORE_SYNC_BR,  .mbox_reg = GEN6_RBSYNC },
19961e12ee3bSFrançois Tigeot 					[VCS_HW] =  { .wait_mbox = MI_SEMAPHORE_SYNC_BV,  .mbox_reg = GEN6_VBSYNC },
19971e12ee3bSFrançois Tigeot 					[VECS_HW] = { .wait_mbox = MI_SEMAPHORE_SYNC_BVE, .mbox_reg = GEN6_VEBSYNC },
19981487f786SFrançois Tigeot 				},
19991e12ee3bSFrançois Tigeot 				[VECS_HW] = {
20001e12ee3bSFrançois Tigeot 					[RCS_HW] =  { .wait_mbox = MI_SEMAPHORE_SYNC_VER, .mbox_reg = GEN6_RVESYNC },
20011e12ee3bSFrançois Tigeot 					[VCS_HW] =  { .wait_mbox = MI_SEMAPHORE_SYNC_VEV, .mbox_reg = GEN6_VVESYNC },
20021e12ee3bSFrançois Tigeot 					[BCS_HW] =  { .wait_mbox = MI_SEMAPHORE_SYNC_VEB, .mbox_reg = GEN6_BVESYNC },
20031487f786SFrançois Tigeot 				},
20041487f786SFrançois Tigeot 			};
20051487f786SFrançois Tigeot 			u32 wait_mbox;
20061487f786SFrançois Tigeot 			i915_reg_t mbox_reg;
20071487f786SFrançois Tigeot 
20081e12ee3bSFrançois Tigeot 			if (i == engine->hw_id) {
20091487f786SFrançois Tigeot 				wait_mbox = MI_SEMAPHORE_SYNC_INVALID;
20101487f786SFrançois Tigeot 				mbox_reg = GEN6_NOSYNC;
20111487f786SFrançois Tigeot 			} else {
20121e12ee3bSFrançois Tigeot 				wait_mbox = sem_data[engine->hw_id][i].wait_mbox;
20131e12ee3bSFrançois Tigeot 				mbox_reg = sem_data[engine->hw_id][i].mbox_reg;
20141487f786SFrançois Tigeot 			}
20151487f786SFrançois Tigeot 
20161487f786SFrançois Tigeot 			engine->semaphore.mbox.wait[i] = wait_mbox;
20171487f786SFrançois Tigeot 			engine->semaphore.mbox.signal[i] = mbox_reg;
20181487f786SFrançois Tigeot 		}
20191487f786SFrançois Tigeot 	}
20201e12ee3bSFrançois Tigeot 
20211e12ee3bSFrançois Tigeot 	return;
20221e12ee3bSFrançois Tigeot 
20231e12ee3bSFrançois Tigeot err_obj:
20241e12ee3bSFrançois Tigeot 	i915_gem_object_put(obj);
20251e12ee3bSFrançois Tigeot err:
20261e12ee3bSFrançois Tigeot 	DRM_DEBUG_DRIVER("Failed to allocate space for semaphores, disabling\n");
20271e12ee3bSFrançois Tigeot 	i915.semaphores = 0;
20281487f786SFrançois Tigeot }
20291487f786SFrançois Tigeot 
20301487f786SFrançois Tigeot static void intel_ring_init_irq(struct drm_i915_private *dev_priv,
20311487f786SFrançois Tigeot 				struct intel_engine_cs *engine)
20321487f786SFrançois Tigeot {
203387df8fc6SFrançois Tigeot 	engine->irq_enable_mask = GT_RENDER_USER_INTERRUPT << engine->irq_shift;
203487df8fc6SFrançois Tigeot 
20351487f786SFrançois Tigeot 	if (INTEL_GEN(dev_priv) >= 8) {
2036303bf270SFrançois Tigeot 		engine->irq_enable = gen8_irq_enable;
2037303bf270SFrançois Tigeot 		engine->irq_disable = gen8_irq_disable;
20381487f786SFrançois Tigeot 		engine->irq_seqno_barrier = gen6_seqno_barrier;
20391487f786SFrançois Tigeot 	} else if (INTEL_GEN(dev_priv) >= 6) {
2040303bf270SFrançois Tigeot 		engine->irq_enable = gen6_irq_enable;
2041303bf270SFrançois Tigeot 		engine->irq_disable = gen6_irq_disable;
20421487f786SFrançois Tigeot 		engine->irq_seqno_barrier = gen6_seqno_barrier;
20431487f786SFrançois Tigeot 	} else if (INTEL_GEN(dev_priv) >= 5) {
2044303bf270SFrançois Tigeot 		engine->irq_enable = gen5_irq_enable;
2045303bf270SFrançois Tigeot 		engine->irq_disable = gen5_irq_disable;
2046303bf270SFrançois Tigeot 		engine->irq_seqno_barrier = gen5_seqno_barrier;
20471487f786SFrançois Tigeot 	} else if (INTEL_GEN(dev_priv) >= 3) {
2048303bf270SFrançois Tigeot 		engine->irq_enable = i9xx_irq_enable;
2049303bf270SFrançois Tigeot 		engine->irq_disable = i9xx_irq_disable;
20501487f786SFrançois Tigeot 	} else {
2051303bf270SFrançois Tigeot 		engine->irq_enable = i8xx_irq_enable;
2052303bf270SFrançois Tigeot 		engine->irq_disable = i8xx_irq_disable;
20531487f786SFrançois Tigeot 	}
20541487f786SFrançois Tigeot }
20551487f786SFrançois Tigeot 
2056*a85cb24fSFrançois Tigeot static void i9xx_set_default_submission(struct intel_engine_cs *engine)
2057*a85cb24fSFrançois Tigeot {
2058*a85cb24fSFrançois Tigeot 	engine->submit_request = i9xx_submit_request;
2059*a85cb24fSFrançois Tigeot }
2060*a85cb24fSFrançois Tigeot 
2061*a85cb24fSFrançois Tigeot static void gen6_bsd_set_default_submission(struct intel_engine_cs *engine)
2062*a85cb24fSFrançois Tigeot {
2063*a85cb24fSFrançois Tigeot 	engine->submit_request = gen6_bsd_submit_request;
2064*a85cb24fSFrançois Tigeot }
2065*a85cb24fSFrançois Tigeot 
20661487f786SFrançois Tigeot static void intel_ring_default_vfuncs(struct drm_i915_private *dev_priv,
20671487f786SFrançois Tigeot 				      struct intel_engine_cs *engine)
20681487f786SFrançois Tigeot {
20691487f786SFrançois Tigeot 	intel_ring_init_irq(dev_priv, engine);
20701487f786SFrançois Tigeot 	intel_ring_init_semaphores(dev_priv, engine);
207171f41f3eSFrançois Tigeot 
207271f41f3eSFrançois Tigeot 	engine->init_hw = init_ring_common;
20731e12ee3bSFrançois Tigeot 	engine->reset_hw = reset_ring_common;
207471f41f3eSFrançois Tigeot 
2075*a85cb24fSFrançois Tigeot 	engine->context_pin = intel_ring_context_pin;
2076*a85cb24fSFrançois Tigeot 	engine->context_unpin = intel_ring_context_unpin;
2077*a85cb24fSFrançois Tigeot 
2078*a85cb24fSFrançois Tigeot 	engine->request_alloc = ring_request_alloc;
2079*a85cb24fSFrançois Tigeot 
20804be47400SFrançois Tigeot 	engine->emit_breadcrumb = i9xx_emit_breadcrumb;
20814be47400SFrançois Tigeot 	engine->emit_breadcrumb_sz = i9xx_emit_breadcrumb_sz;
20824be47400SFrançois Tigeot 	if (i915.semaphores) {
20834be47400SFrançois Tigeot 		int num_rings;
20844be47400SFrançois Tigeot 
20854be47400SFrançois Tigeot 		engine->emit_breadcrumb = gen6_sema_emit_breadcrumb;
20864be47400SFrançois Tigeot 
20874be47400SFrançois Tigeot 		num_rings = hweight32(INTEL_INFO(dev_priv)->ring_mask) - 1;
20884be47400SFrançois Tigeot 		if (INTEL_GEN(dev_priv) >= 8) {
20894be47400SFrançois Tigeot 			engine->emit_breadcrumb_sz += num_rings * 6;
20904be47400SFrançois Tigeot 		} else {
20914be47400SFrançois Tigeot 			engine->emit_breadcrumb_sz += num_rings * 3;
20924be47400SFrançois Tigeot 			if (num_rings & 1)
20934be47400SFrançois Tigeot 				engine->emit_breadcrumb_sz++;
20944be47400SFrançois Tigeot 		}
20954be47400SFrançois Tigeot 	}
2096*a85cb24fSFrançois Tigeot 
2097*a85cb24fSFrançois Tigeot 	engine->set_default_submission = i9xx_set_default_submission;
209871f41f3eSFrançois Tigeot 
209971f41f3eSFrançois Tigeot 	if (INTEL_GEN(dev_priv) >= 8)
210071f41f3eSFrançois Tigeot 		engine->emit_bb_start = gen8_emit_bb_start;
210171f41f3eSFrançois Tigeot 	else if (INTEL_GEN(dev_priv) >= 6)
210271f41f3eSFrançois Tigeot 		engine->emit_bb_start = gen6_emit_bb_start;
210371f41f3eSFrançois Tigeot 	else if (INTEL_GEN(dev_priv) >= 4)
210471f41f3eSFrançois Tigeot 		engine->emit_bb_start = i965_emit_bb_start;
2105*a85cb24fSFrançois Tigeot 	else if (IS_I830(dev_priv) || IS_I845G(dev_priv))
210671f41f3eSFrançois Tigeot 		engine->emit_bb_start = i830_emit_bb_start;
210771f41f3eSFrançois Tigeot 	else
210871f41f3eSFrançois Tigeot 		engine->emit_bb_start = i915_emit_bb_start;
21091487f786SFrançois Tigeot }
21101487f786SFrançois Tigeot 
211187df8fc6SFrançois Tigeot int intel_init_render_ring_buffer(struct intel_engine_cs *engine)
2112e3adcf8fSFrançois Tigeot {
211387df8fc6SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
211424edb884SFrançois Tigeot 	int ret;
2115e3adcf8fSFrançois Tigeot 
21161487f786SFrançois Tigeot 	intel_ring_default_vfuncs(dev_priv, engine);
21172c9916cdSFrançois Tigeot 
2118303bf270SFrançois Tigeot 	if (HAS_L3_DPF(dev_priv))
2119303bf270SFrançois Tigeot 		engine->irq_keep_mask = GT_RENDER_L3_PARITY_ERROR_INTERRUPT;
2120303bf270SFrançois Tigeot 
21211487f786SFrançois Tigeot 	if (INTEL_GEN(dev_priv) >= 8) {
21228621f407SFrançois Tigeot 		engine->init_context = intel_rcs_ctx_init;
21234be47400SFrançois Tigeot 		engine->emit_breadcrumb = gen8_render_emit_breadcrumb;
21244be47400SFrançois Tigeot 		engine->emit_breadcrumb_sz = gen8_render_emit_breadcrumb_sz;
212571f41f3eSFrançois Tigeot 		engine->emit_flush = gen8_render_ring_flush;
21264be47400SFrançois Tigeot 		if (i915.semaphores) {
21274be47400SFrançois Tigeot 			int num_rings;
21284be47400SFrançois Tigeot 
21298621f407SFrançois Tigeot 			engine->semaphore.signal = gen8_rcs_signal;
21304be47400SFrançois Tigeot 
21314be47400SFrançois Tigeot 			num_rings =
21324be47400SFrançois Tigeot 				hweight32(INTEL_INFO(dev_priv)->ring_mask) - 1;
2133*a85cb24fSFrançois Tigeot 			engine->emit_breadcrumb_sz += num_rings * 8;
21344be47400SFrançois Tigeot 		}
21351487f786SFrançois Tigeot 	} else if (INTEL_GEN(dev_priv) >= 6) {
21368621f407SFrançois Tigeot 		engine->init_context = intel_rcs_ctx_init;
213771f41f3eSFrançois Tigeot 		engine->emit_flush = gen7_render_ring_flush;
21381487f786SFrançois Tigeot 		if (IS_GEN6(dev_priv))
213971f41f3eSFrançois Tigeot 			engine->emit_flush = gen6_render_ring_flush;
21401487f786SFrançois Tigeot 	} else if (IS_GEN5(dev_priv)) {
214171f41f3eSFrançois Tigeot 		engine->emit_flush = gen4_render_ring_flush;
2142686a02f1SFrançois Tigeot 	} else {
21431487f786SFrançois Tigeot 		if (INTEL_GEN(dev_priv) < 4)
214471f41f3eSFrançois Tigeot 			engine->emit_flush = gen2_render_ring_flush;
2145686a02f1SFrançois Tigeot 		else
214671f41f3eSFrançois Tigeot 			engine->emit_flush = gen4_render_ring_flush;
21478621f407SFrançois Tigeot 		engine->irq_enable_mask = I915_USER_INTERRUPT;
2148686a02f1SFrançois Tigeot 	}
214924edb884SFrançois Tigeot 
21501487f786SFrançois Tigeot 	if (IS_HASWELL(dev_priv))
215171f41f3eSFrançois Tigeot 		engine->emit_bb_start = hsw_emit_bb_start;
21521487f786SFrançois Tigeot 
21538621f407SFrançois Tigeot 	engine->init_hw = init_render_ring;
21548621f407SFrançois Tigeot 	engine->cleanup = render_ring_cleanup;
2155e3adcf8fSFrançois Tigeot 
215687df8fc6SFrançois Tigeot 	ret = intel_init_ring_buffer(engine);
2157b5c29a34SFrançois Tigeot 	if (ret)
21582c9916cdSFrançois Tigeot 		return ret;
21592c9916cdSFrançois Tigeot 
2160303bf270SFrançois Tigeot 	if (INTEL_GEN(dev_priv) >= 6) {
2161*a85cb24fSFrançois Tigeot 		ret = intel_engine_create_scratch(engine, PAGE_SIZE);
2162303bf270SFrançois Tigeot 		if (ret)
2163303bf270SFrançois Tigeot 			return ret;
2164303bf270SFrançois Tigeot 	} else if (HAS_BROKEN_CS_TLB(dev_priv)) {
21651e12ee3bSFrançois Tigeot 		ret = intel_engine_create_scratch(engine, I830_WA_SIZE);
21662c9916cdSFrançois Tigeot 		if (ret)
21672c9916cdSFrançois Tigeot 			return ret;
2168b5c29a34SFrançois Tigeot 	}
2169b5c29a34SFrançois Tigeot 
2170e3adcf8fSFrançois Tigeot 	return 0;
2171e3adcf8fSFrançois Tigeot }
2172e3adcf8fSFrançois Tigeot 
217387df8fc6SFrançois Tigeot int intel_init_bsd_ring_buffer(struct intel_engine_cs *engine)
2174e3adcf8fSFrançois Tigeot {
217587df8fc6SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
2176686a02f1SFrançois Tigeot 
21771487f786SFrançois Tigeot 	intel_ring_default_vfuncs(dev_priv, engine);
21781487f786SFrançois Tigeot 
21791487f786SFrançois Tigeot 	if (INTEL_GEN(dev_priv) >= 6) {
2180686a02f1SFrançois Tigeot 		/* gen6 bsd needs a special wa for tail updates */
21811487f786SFrançois Tigeot 		if (IS_GEN6(dev_priv))
2182*a85cb24fSFrançois Tigeot 			engine->set_default_submission = gen6_bsd_set_default_submission;
218371f41f3eSFrançois Tigeot 		engine->emit_flush = gen6_bsd_ring_flush;
218487df8fc6SFrançois Tigeot 		if (INTEL_GEN(dev_priv) < 8)
21858621f407SFrançois Tigeot 			engine->irq_enable_mask = GT_BSD_USER_INTERRUPT;
2186686a02f1SFrançois Tigeot 	} else {
21878621f407SFrançois Tigeot 		engine->mmio_base = BSD_RING_BASE;
218871f41f3eSFrançois Tigeot 		engine->emit_flush = bsd_ring_flush;
21891487f786SFrançois Tigeot 		if (IS_GEN5(dev_priv))
21908621f407SFrançois Tigeot 			engine->irq_enable_mask = ILK_BSD_USER_INTERRUPT;
21911487f786SFrançois Tigeot 		else
21928621f407SFrançois Tigeot 			engine->irq_enable_mask = I915_BSD_USER_INTERRUPT;
2193686a02f1SFrançois Tigeot 	}
2194e3adcf8fSFrançois Tigeot 
219587df8fc6SFrançois Tigeot 	return intel_init_ring_buffer(engine);
2196e3adcf8fSFrançois Tigeot }
2197e3adcf8fSFrançois Tigeot 
2198ba55f2f5SFrançois Tigeot /**
2199477eb7f9SFrançois Tigeot  * Initialize the second BSD ring (eg. Broadwell GT3, Skylake GT3)
2200ba55f2f5SFrançois Tigeot  */
220187df8fc6SFrançois Tigeot int intel_init_bsd2_ring_buffer(struct intel_engine_cs *engine)
2202ba55f2f5SFrançois Tigeot {
220387df8fc6SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
22041487f786SFrançois Tigeot 
22051487f786SFrançois Tigeot 	intel_ring_default_vfuncs(dev_priv, engine);
22061487f786SFrançois Tigeot 
220771f41f3eSFrançois Tigeot 	engine->emit_flush = gen6_bsd_ring_flush;
2208ba55f2f5SFrançois Tigeot 
220987df8fc6SFrançois Tigeot 	return intel_init_ring_buffer(engine);
2210ba55f2f5SFrançois Tigeot }
2211ba55f2f5SFrançois Tigeot 
221287df8fc6SFrançois Tigeot int intel_init_blt_ring_buffer(struct intel_engine_cs *engine)
2213e3adcf8fSFrançois Tigeot {
221487df8fc6SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
22151487f786SFrançois Tigeot 
22161487f786SFrançois Tigeot 	intel_ring_default_vfuncs(dev_priv, engine);
22171487f786SFrançois Tigeot 
221871f41f3eSFrançois Tigeot 	engine->emit_flush = gen6_ring_flush;
221987df8fc6SFrançois Tigeot 	if (INTEL_GEN(dev_priv) < 8)
22208621f407SFrançois Tigeot 		engine->irq_enable_mask = GT_BLT_USER_INTERRUPT;
22215d0b1887SFrançois Tigeot 
222287df8fc6SFrançois Tigeot 	return intel_init_ring_buffer(engine);
22235d0b1887SFrançois Tigeot }
22245d0b1887SFrançois Tigeot 
222587df8fc6SFrançois Tigeot int intel_init_vebox_ring_buffer(struct intel_engine_cs *engine)
22265d0b1887SFrançois Tigeot {
222787df8fc6SFrançois Tigeot 	struct drm_i915_private *dev_priv = engine->i915;
22289edbd4a0SFrançois Tigeot 
22291487f786SFrançois Tigeot 	intel_ring_default_vfuncs(dev_priv, engine);
22301487f786SFrançois Tigeot 
223171f41f3eSFrançois Tigeot 	engine->emit_flush = gen6_ring_flush;
22321487f786SFrançois Tigeot 
223387df8fc6SFrançois Tigeot 	if (INTEL_GEN(dev_priv) < 8) {
22348621f407SFrançois Tigeot 		engine->irq_enable_mask = PM_VEBOX_USER_INTERRUPT;
2235303bf270SFrançois Tigeot 		engine->irq_enable = hsw_vebox_irq_enable;
2236303bf270SFrançois Tigeot 		engine->irq_disable = hsw_vebox_irq_disable;
223724edb884SFrançois Tigeot 	}
2238e3adcf8fSFrançois Tigeot 
223987df8fc6SFrançois Tigeot 	return intel_init_ring_buffer(engine);
2240e3adcf8fSFrançois Tigeot }
2241