xref: /dflybsd-src/sys/dev/drm/i915/intel_ringbuffer.c (revision 24edb8848e2499ece59b84a04f554a7a897feeab)
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 
3018e26a6dSFrançois Tigeot #include <drm/drmP.h>
31e3adcf8fSFrançois Tigeot #include "i915_drv.h"
32a2fdbec6SFrançois Tigeot #include <drm/i915_drm.h>
33a2fdbec6SFrançois Tigeot #include "i915_trace.h"
34e3adcf8fSFrançois Tigeot #include "intel_drv.h"
35e3adcf8fSFrançois Tigeot 
36ba55f2f5SFrançois Tigeot /* Early gen2 devices have a cacheline of just 32 bytes, using 64 is overkill,
37ba55f2f5SFrançois Tigeot  * but keeps the logic simple. Indeed, the whole purpose of this macro is just
38ba55f2f5SFrançois Tigeot  * to give some inclination as to some of the magic values used in the various
39ba55f2f5SFrançois Tigeot  * workarounds!
40ba55f2f5SFrançois Tigeot  */
41ba55f2f5SFrançois Tigeot #define CACHELINE_BYTES 64
42ba55f2f5SFrançois Tigeot 
43ba55f2f5SFrançois Tigeot static inline int __ring_space(int head, int tail, int size)
44e3adcf8fSFrançois Tigeot {
45ba55f2f5SFrançois Tigeot 	int space = head - (tail + I915_RING_FREE_SPACE);
46e3adcf8fSFrançois Tigeot 	if (space < 0)
47ba55f2f5SFrançois Tigeot 		space += size;
48e3adcf8fSFrançois Tigeot 	return space;
49e3adcf8fSFrançois Tigeot }
50e3adcf8fSFrançois Tigeot 
51*24edb884SFrançois Tigeot static inline int ring_space(struct intel_ringbuffer *ringbuf)
52ba55f2f5SFrançois Tigeot {
53ba55f2f5SFrançois Tigeot 	return __ring_space(ringbuf->head & HEAD_ADDR, ringbuf->tail, ringbuf->size);
54ba55f2f5SFrançois Tigeot }
55ba55f2f5SFrançois Tigeot 
56ba55f2f5SFrançois Tigeot static bool intel_ring_stopped(struct intel_engine_cs *ring)
579edbd4a0SFrançois Tigeot {
589edbd4a0SFrançois Tigeot 	struct drm_i915_private *dev_priv = ring->dev->dev_private;
59ba55f2f5SFrançois Tigeot 	return dev_priv->gpu_error.stop_rings & intel_ring_flag(ring);
60ba55f2f5SFrançois Tigeot }
619edbd4a0SFrançois Tigeot 
62ba55f2f5SFrançois Tigeot void __intel_ring_advance(struct intel_engine_cs *ring)
63ba55f2f5SFrançois Tigeot {
64ba55f2f5SFrançois Tigeot 	struct intel_ringbuffer *ringbuf = ring->buffer;
65ba55f2f5SFrançois Tigeot 	ringbuf->tail &= ringbuf->size - 1;
66ba55f2f5SFrançois Tigeot 	if (intel_ring_stopped(ring))
679edbd4a0SFrançois Tigeot 		return;
68ba55f2f5SFrançois Tigeot 	ring->write_tail(ring, ringbuf->tail);
699edbd4a0SFrançois Tigeot }
709edbd4a0SFrançois Tigeot 
71e3adcf8fSFrançois Tigeot static int
72ba55f2f5SFrançois Tigeot gen2_render_ring_flush(struct intel_engine_cs *ring,
73686a02f1SFrançois Tigeot 		       u32	invalidate_domains,
74686a02f1SFrançois Tigeot 		       u32	flush_domains)
75686a02f1SFrançois Tigeot {
76686a02f1SFrançois Tigeot 	u32 cmd;
77686a02f1SFrançois Tigeot 	int ret;
78686a02f1SFrançois Tigeot 
79686a02f1SFrançois Tigeot 	cmd = MI_FLUSH;
80686a02f1SFrançois Tigeot 	if (((invalidate_domains|flush_domains) & I915_GEM_DOMAIN_RENDER) == 0)
81686a02f1SFrançois Tigeot 		cmd |= MI_NO_WRITE_FLUSH;
82686a02f1SFrançois Tigeot 
83686a02f1SFrançois Tigeot 	if (invalidate_domains & I915_GEM_DOMAIN_SAMPLER)
84686a02f1SFrançois Tigeot 		cmd |= MI_READ_FLUSH;
85686a02f1SFrançois Tigeot 
86686a02f1SFrançois Tigeot 	ret = intel_ring_begin(ring, 2);
87686a02f1SFrançois Tigeot 	if (ret)
88686a02f1SFrançois Tigeot 		return ret;
89686a02f1SFrançois Tigeot 
90686a02f1SFrançois Tigeot 	intel_ring_emit(ring, cmd);
91686a02f1SFrançois Tigeot 	intel_ring_emit(ring, MI_NOOP);
92686a02f1SFrançois Tigeot 	intel_ring_advance(ring);
93686a02f1SFrançois Tigeot 
94686a02f1SFrançois Tigeot 	return 0;
95686a02f1SFrançois Tigeot }
96686a02f1SFrançois Tigeot 
97686a02f1SFrançois Tigeot static int
98ba55f2f5SFrançois Tigeot gen4_render_ring_flush(struct intel_engine_cs *ring,
99686a02f1SFrançois Tigeot 		       u32	invalidate_domains,
100686a02f1SFrançois Tigeot 		       u32	flush_domains)
101e3adcf8fSFrançois Tigeot {
102e3adcf8fSFrançois Tigeot 	struct drm_device *dev = ring->dev;
103686a02f1SFrançois Tigeot 	u32 cmd;
104e3adcf8fSFrançois Tigeot 	int ret;
105e3adcf8fSFrançois Tigeot 
106e3adcf8fSFrançois Tigeot 	/*
107e3adcf8fSFrançois Tigeot 	 * read/write caches:
108e3adcf8fSFrançois Tigeot 	 *
109e3adcf8fSFrançois Tigeot 	 * I915_GEM_DOMAIN_RENDER is always invalidated, but is
110e3adcf8fSFrançois Tigeot 	 * only flushed if MI_NO_WRITE_FLUSH is unset.  On 965, it is
111e3adcf8fSFrançois Tigeot 	 * also flushed at 2d versus 3d pipeline switches.
112e3adcf8fSFrançois Tigeot 	 *
113e3adcf8fSFrançois Tigeot 	 * read-only caches:
114e3adcf8fSFrançois Tigeot 	 *
115e3adcf8fSFrançois Tigeot 	 * I915_GEM_DOMAIN_SAMPLER is flushed on pre-965 if
116e3adcf8fSFrançois Tigeot 	 * MI_READ_FLUSH is set, and is always flushed on 965.
117e3adcf8fSFrançois Tigeot 	 *
118e3adcf8fSFrançois Tigeot 	 * I915_GEM_DOMAIN_COMMAND may not exist?
119e3adcf8fSFrançois Tigeot 	 *
120e3adcf8fSFrançois Tigeot 	 * I915_GEM_DOMAIN_INSTRUCTION, which exists on 965, is
121e3adcf8fSFrançois Tigeot 	 * invalidated when MI_EXE_FLUSH is set.
122e3adcf8fSFrançois Tigeot 	 *
123e3adcf8fSFrançois Tigeot 	 * I915_GEM_DOMAIN_VERTEX, which exists on 965, is
124e3adcf8fSFrançois Tigeot 	 * invalidated with every MI_FLUSH.
125e3adcf8fSFrançois Tigeot 	 *
126e3adcf8fSFrançois Tigeot 	 * TLBs:
127e3adcf8fSFrançois Tigeot 	 *
128e3adcf8fSFrançois Tigeot 	 * On 965, TLBs associated with I915_GEM_DOMAIN_COMMAND
129e3adcf8fSFrançois Tigeot 	 * and I915_GEM_DOMAIN_CPU in are invalidated at PTE write and
130e3adcf8fSFrançois Tigeot 	 * I915_GEM_DOMAIN_RENDER and I915_GEM_DOMAIN_SAMPLER
131e3adcf8fSFrançois Tigeot 	 * are flushed at any MI_FLUSH.
132e3adcf8fSFrançois Tigeot 	 */
133e3adcf8fSFrançois Tigeot 
134e3adcf8fSFrançois Tigeot 	cmd = MI_FLUSH | MI_NO_WRITE_FLUSH;
135686a02f1SFrançois Tigeot 	if ((invalidate_domains|flush_domains) & I915_GEM_DOMAIN_RENDER)
136e3adcf8fSFrançois Tigeot 		cmd &= ~MI_NO_WRITE_FLUSH;
137e3adcf8fSFrançois Tigeot 	if (invalidate_domains & I915_GEM_DOMAIN_INSTRUCTION)
138e3adcf8fSFrançois Tigeot 		cmd |= MI_EXE_FLUSH;
139e3adcf8fSFrançois Tigeot 
140e3adcf8fSFrançois Tigeot 	if (invalidate_domains & I915_GEM_DOMAIN_COMMAND &&
141e3adcf8fSFrançois Tigeot 	    (IS_G4X(dev) || IS_GEN5(dev)))
142e3adcf8fSFrançois Tigeot 		cmd |= MI_INVALIDATE_ISP;
143e3adcf8fSFrançois Tigeot 
144e3adcf8fSFrançois Tigeot 	ret = intel_ring_begin(ring, 2);
145e3adcf8fSFrançois Tigeot 	if (ret)
146e3adcf8fSFrançois Tigeot 		return ret;
147e3adcf8fSFrançois Tigeot 
148e3adcf8fSFrançois Tigeot 	intel_ring_emit(ring, cmd);
149e3adcf8fSFrançois Tigeot 	intel_ring_emit(ring, MI_NOOP);
150e3adcf8fSFrançois Tigeot 	intel_ring_advance(ring);
151e3adcf8fSFrançois Tigeot 
152e3adcf8fSFrançois Tigeot 	return 0;
153e3adcf8fSFrançois Tigeot }
154e3adcf8fSFrançois Tigeot 
155e3adcf8fSFrançois Tigeot /**
156e3adcf8fSFrançois Tigeot  * Emits a PIPE_CONTROL with a non-zero post-sync operation, for
157e3adcf8fSFrançois Tigeot  * implementing two workarounds on gen6.  From section 1.4.7.1
158e3adcf8fSFrançois Tigeot  * "PIPE_CONTROL" of the Sandy Bridge PRM volume 2 part 1:
159e3adcf8fSFrançois Tigeot  *
160e3adcf8fSFrançois Tigeot  * [DevSNB-C+{W/A}] Before any depth stall flush (including those
161e3adcf8fSFrançois Tigeot  * produced by non-pipelined state commands), software needs to first
162e3adcf8fSFrançois Tigeot  * send a PIPE_CONTROL with no bits set except Post-Sync Operation !=
163e3adcf8fSFrançois Tigeot  * 0.
164e3adcf8fSFrançois Tigeot  *
165e3adcf8fSFrançois Tigeot  * [Dev-SNB{W/A}]: Before a PIPE_CONTROL with Write Cache Flush Enable
166e3adcf8fSFrançois Tigeot  * =1, a PIPE_CONTROL with any non-zero post-sync-op is required.
167e3adcf8fSFrançois Tigeot  *
168e3adcf8fSFrançois Tigeot  * And the workaround for these two requires this workaround first:
169e3adcf8fSFrançois Tigeot  *
170e3adcf8fSFrançois Tigeot  * [Dev-SNB{W/A}]: Pipe-control with CS-stall bit set must be sent
171e3adcf8fSFrançois Tigeot  * BEFORE the pipe-control with a post-sync op and no write-cache
172e3adcf8fSFrançois Tigeot  * flushes.
173e3adcf8fSFrançois Tigeot  *
174e3adcf8fSFrançois Tigeot  * And this last workaround is tricky because of the requirements on
175e3adcf8fSFrançois Tigeot  * that bit.  From section 1.4.7.2.3 "Stall" of the Sandy Bridge PRM
176e3adcf8fSFrançois Tigeot  * volume 2 part 1:
177e3adcf8fSFrançois Tigeot  *
178e3adcf8fSFrançois Tigeot  *     "1 of the following must also be set:
179e3adcf8fSFrançois Tigeot  *      - Render Target Cache Flush Enable ([12] of DW1)
180e3adcf8fSFrançois Tigeot  *      - Depth Cache Flush Enable ([0] of DW1)
181e3adcf8fSFrançois Tigeot  *      - Stall at Pixel Scoreboard ([1] of DW1)
182e3adcf8fSFrançois Tigeot  *      - Depth Stall ([13] of DW1)
183e3adcf8fSFrançois Tigeot  *      - Post-Sync Operation ([13] of DW1)
184e3adcf8fSFrançois Tigeot  *      - Notify Enable ([8] of DW1)"
185e3adcf8fSFrançois Tigeot  *
186e3adcf8fSFrançois Tigeot  * The cache flushes require the workaround flush that triggered this
187e3adcf8fSFrançois Tigeot  * one, so we can't use it.  Depth stall would trigger the same.
188e3adcf8fSFrançois Tigeot  * Post-sync nonzero is what triggered this second workaround, so we
189e3adcf8fSFrançois Tigeot  * can't use that one either.  Notify enable is IRQs, which aren't
190e3adcf8fSFrançois Tigeot  * really our business.  That leaves only stall at scoreboard.
191e3adcf8fSFrançois Tigeot  */
192e3adcf8fSFrançois Tigeot static int
193ba55f2f5SFrançois Tigeot intel_emit_post_sync_nonzero_flush(struct intel_engine_cs *ring)
194e3adcf8fSFrançois Tigeot {
195ba55f2f5SFrançois Tigeot 	u32 scratch_addr = ring->scratch.gtt_offset + 2 * CACHELINE_BYTES;
196e3adcf8fSFrançois Tigeot 	int ret;
197e3adcf8fSFrançois Tigeot 
198e3adcf8fSFrançois Tigeot 
199e3adcf8fSFrançois Tigeot 	ret = intel_ring_begin(ring, 6);
200e3adcf8fSFrançois Tigeot 	if (ret)
201e3adcf8fSFrançois Tigeot 		return ret;
202e3adcf8fSFrançois Tigeot 
203e3adcf8fSFrançois Tigeot 	intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(5));
204e3adcf8fSFrançois Tigeot 	intel_ring_emit(ring, PIPE_CONTROL_CS_STALL |
205e3adcf8fSFrançois Tigeot 			PIPE_CONTROL_STALL_AT_SCOREBOARD);
206e3adcf8fSFrançois Tigeot 	intel_ring_emit(ring, scratch_addr | PIPE_CONTROL_GLOBAL_GTT); /* address */
207e3adcf8fSFrançois Tigeot 	intel_ring_emit(ring, 0); /* low dword */
208e3adcf8fSFrançois Tigeot 	intel_ring_emit(ring, 0); /* high dword */
209e3adcf8fSFrançois Tigeot 	intel_ring_emit(ring, MI_NOOP);
210e3adcf8fSFrançois Tigeot 	intel_ring_advance(ring);
211e3adcf8fSFrançois Tigeot 
212e3adcf8fSFrançois Tigeot 	ret = intel_ring_begin(ring, 6);
213e3adcf8fSFrançois Tigeot 	if (ret)
214e3adcf8fSFrançois Tigeot 		return ret;
215e3adcf8fSFrançois Tigeot 
216e3adcf8fSFrançois Tigeot 	intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(5));
217e3adcf8fSFrançois Tigeot 	intel_ring_emit(ring, PIPE_CONTROL_QW_WRITE);
218e3adcf8fSFrançois Tigeot 	intel_ring_emit(ring, scratch_addr | PIPE_CONTROL_GLOBAL_GTT); /* address */
219e3adcf8fSFrançois Tigeot 	intel_ring_emit(ring, 0);
220e3adcf8fSFrançois Tigeot 	intel_ring_emit(ring, 0);
221e3adcf8fSFrançois Tigeot 	intel_ring_emit(ring, MI_NOOP);
222e3adcf8fSFrançois Tigeot 	intel_ring_advance(ring);
223e3adcf8fSFrançois Tigeot 
224e3adcf8fSFrançois Tigeot 	return 0;
225e3adcf8fSFrançois Tigeot }
226e3adcf8fSFrançois Tigeot 
227e3adcf8fSFrançois Tigeot static int
228ba55f2f5SFrançois Tigeot gen6_render_ring_flush(struct intel_engine_cs *ring,
229e3adcf8fSFrançois Tigeot                          u32 invalidate_domains, u32 flush_domains)
230e3adcf8fSFrançois Tigeot {
231e3adcf8fSFrançois Tigeot 	u32 flags = 0;
232ba55f2f5SFrançois Tigeot 	u32 scratch_addr = ring->scratch.gtt_offset + 2 * CACHELINE_BYTES;
233e3adcf8fSFrançois Tigeot 	int ret;
234e3adcf8fSFrançois Tigeot 
235e3adcf8fSFrançois Tigeot 	/* Force SNB workarounds for PIPE_CONTROL flushes */
236686a02f1SFrançois Tigeot 	ret = intel_emit_post_sync_nonzero_flush(ring);
237686a02f1SFrançois Tigeot 	if (ret)
238686a02f1SFrançois Tigeot 		return ret;
239e3adcf8fSFrançois Tigeot 
240e3adcf8fSFrançois Tigeot 	/* Just flush everything.  Experiments have shown that reducing the
241e3adcf8fSFrançois Tigeot 	 * number of bits based on the write domains has little performance
242e3adcf8fSFrançois Tigeot 	 * impact.
243e3adcf8fSFrançois Tigeot 	 */
244b5c29a34SFrançois Tigeot 	if (flush_domains) {
245e3adcf8fSFrançois Tigeot 		flags |= PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH;
246b5c29a34SFrançois Tigeot 		flags |= PIPE_CONTROL_DEPTH_CACHE_FLUSH;
247b5c29a34SFrançois Tigeot 		/*
248b5c29a34SFrançois Tigeot 		 * Ensure that any following seqno writes only happen
249b5c29a34SFrançois Tigeot 		 * when the render cache is indeed flushed.
250b5c29a34SFrançois Tigeot 		 */
251b5c29a34SFrançois Tigeot 		flags |= PIPE_CONTROL_CS_STALL;
252b5c29a34SFrançois Tigeot 	}
253b5c29a34SFrançois Tigeot 	if (invalidate_domains) {
254686a02f1SFrançois Tigeot 		flags |= PIPE_CONTROL_TLB_INVALIDATE;
255e3adcf8fSFrançois Tigeot 		flags |= PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE;
256e3adcf8fSFrançois Tigeot 		flags |= PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE;
257e3adcf8fSFrançois Tigeot 		flags |= PIPE_CONTROL_VF_CACHE_INVALIDATE;
258e3adcf8fSFrançois Tigeot 		flags |= PIPE_CONTROL_CONST_CACHE_INVALIDATE;
259e3adcf8fSFrançois Tigeot 		flags |= PIPE_CONTROL_STATE_CACHE_INVALIDATE;
260686a02f1SFrançois Tigeot 		/*
261b5c29a34SFrançois Tigeot 		 * TLB invalidate requires a post-sync write.
262686a02f1SFrançois Tigeot 		 */
263b5c29a34SFrançois Tigeot 		flags |= PIPE_CONTROL_QW_WRITE | PIPE_CONTROL_CS_STALL;
264b5c29a34SFrançois Tigeot 	}
265e3adcf8fSFrançois Tigeot 
266b5c29a34SFrançois Tigeot 	ret = intel_ring_begin(ring, 4);
267e3adcf8fSFrançois Tigeot 	if (ret)
268e3adcf8fSFrançois Tigeot 		return ret;
269e3adcf8fSFrançois Tigeot 
270b5c29a34SFrançois Tigeot 	intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(4));
271e3adcf8fSFrançois Tigeot 	intel_ring_emit(ring, flags);
272e3adcf8fSFrançois Tigeot 	intel_ring_emit(ring, scratch_addr | PIPE_CONTROL_GLOBAL_GTT);
273b5c29a34SFrançois Tigeot 	intel_ring_emit(ring, 0);
274b5c29a34SFrançois Tigeot 	intel_ring_advance(ring);
275b5c29a34SFrançois Tigeot 
276b5c29a34SFrançois Tigeot 	return 0;
277b5c29a34SFrançois Tigeot }
278b5c29a34SFrançois Tigeot 
279b5c29a34SFrançois Tigeot static int
280ba55f2f5SFrançois Tigeot gen7_render_ring_cs_stall_wa(struct intel_engine_cs *ring)
281b5c29a34SFrançois Tigeot {
282b5c29a34SFrançois Tigeot 	int ret;
283b5c29a34SFrançois Tigeot 
284b5c29a34SFrançois Tigeot 	ret = intel_ring_begin(ring, 4);
285b5c29a34SFrançois Tigeot 	if (ret)
286b5c29a34SFrançois Tigeot 		return ret;
287b5c29a34SFrançois Tigeot 
288b5c29a34SFrançois Tigeot 	intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(4));
289b5c29a34SFrançois Tigeot 	intel_ring_emit(ring, PIPE_CONTROL_CS_STALL |
290b5c29a34SFrançois Tigeot 			      PIPE_CONTROL_STALL_AT_SCOREBOARD);
291b5c29a34SFrançois Tigeot 	intel_ring_emit(ring, 0);
292b5c29a34SFrançois Tigeot 	intel_ring_emit(ring, 0);
293b5c29a34SFrançois Tigeot 	intel_ring_advance(ring);
294b5c29a34SFrançois Tigeot 
295b5c29a34SFrançois Tigeot 	return 0;
296b5c29a34SFrançois Tigeot }
297b5c29a34SFrançois Tigeot 
298ba55f2f5SFrançois Tigeot static int gen7_ring_fbc_flush(struct intel_engine_cs *ring, u32 value)
2995d0b1887SFrançois Tigeot {
3005d0b1887SFrançois Tigeot 	int ret;
3015d0b1887SFrançois Tigeot 
3025d0b1887SFrançois Tigeot 	if (!ring->fbc_dirty)
3035d0b1887SFrançois Tigeot 		return 0;
3045d0b1887SFrançois Tigeot 
3059edbd4a0SFrançois Tigeot 	ret = intel_ring_begin(ring, 6);
3065d0b1887SFrançois Tigeot 	if (ret)
3075d0b1887SFrançois Tigeot 		return ret;
3085d0b1887SFrançois Tigeot 	/* WaFbcNukeOn3DBlt:ivb/hsw */
3095d0b1887SFrançois Tigeot 	intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1));
3105d0b1887SFrançois Tigeot 	intel_ring_emit(ring, MSG_FBC_REND_STATE);
3115d0b1887SFrançois Tigeot 	intel_ring_emit(ring, value);
3129edbd4a0SFrançois Tigeot 	intel_ring_emit(ring, MI_STORE_REGISTER_MEM(1) | MI_SRM_LRM_GLOBAL_GTT);
3139edbd4a0SFrançois Tigeot 	intel_ring_emit(ring, MSG_FBC_REND_STATE);
3149edbd4a0SFrançois Tigeot 	intel_ring_emit(ring, ring->scratch.gtt_offset + 256);
3155d0b1887SFrançois Tigeot 	intel_ring_advance(ring);
3165d0b1887SFrançois Tigeot 
3175d0b1887SFrançois Tigeot 	ring->fbc_dirty = false;
3185d0b1887SFrançois Tigeot 	return 0;
3195d0b1887SFrançois Tigeot }
3205d0b1887SFrançois Tigeot 
321b5c29a34SFrançois Tigeot static int
322ba55f2f5SFrançois Tigeot gen7_render_ring_flush(struct intel_engine_cs *ring,
323b5c29a34SFrançois Tigeot 		       u32 invalidate_domains, u32 flush_domains)
324b5c29a34SFrançois Tigeot {
325b5c29a34SFrançois Tigeot 	u32 flags = 0;
326ba55f2f5SFrançois Tigeot 	u32 scratch_addr = ring->scratch.gtt_offset + 2 * CACHELINE_BYTES;
327b5c29a34SFrançois Tigeot 	int ret;
328b5c29a34SFrançois Tigeot 
329b5c29a34SFrançois Tigeot 	/*
330b5c29a34SFrançois Tigeot 	 * Ensure that any following seqno writes only happen when the render
331b5c29a34SFrançois Tigeot 	 * cache is indeed flushed.
332b5c29a34SFrançois Tigeot 	 *
333b5c29a34SFrançois Tigeot 	 * Workaround: 4th PIPE_CONTROL command (except the ones with only
334b5c29a34SFrançois Tigeot 	 * read-cache invalidate bits set) must have the CS_STALL bit set. We
335b5c29a34SFrançois Tigeot 	 * don't try to be clever and just set it unconditionally.
336b5c29a34SFrançois Tigeot 	 */
337b5c29a34SFrançois Tigeot 	flags |= PIPE_CONTROL_CS_STALL;
338b5c29a34SFrançois Tigeot 
339b5c29a34SFrançois Tigeot 	/* Just flush everything.  Experiments have shown that reducing the
340b5c29a34SFrançois Tigeot 	 * number of bits based on the write domains has little performance
341b5c29a34SFrançois Tigeot 	 * impact.
342b5c29a34SFrançois Tigeot 	 */
343b5c29a34SFrançois Tigeot 	if (flush_domains) {
344b5c29a34SFrançois Tigeot 		flags |= PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH;
345b5c29a34SFrançois Tigeot 		flags |= PIPE_CONTROL_DEPTH_CACHE_FLUSH;
346b5c29a34SFrançois Tigeot 	}
347b5c29a34SFrançois Tigeot 	if (invalidate_domains) {
348b5c29a34SFrançois Tigeot 		flags |= PIPE_CONTROL_TLB_INVALIDATE;
349b5c29a34SFrançois Tigeot 		flags |= PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE;
350b5c29a34SFrançois Tigeot 		flags |= PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE;
351b5c29a34SFrançois Tigeot 		flags |= PIPE_CONTROL_VF_CACHE_INVALIDATE;
352b5c29a34SFrançois Tigeot 		flags |= PIPE_CONTROL_CONST_CACHE_INVALIDATE;
353b5c29a34SFrançois Tigeot 		flags |= PIPE_CONTROL_STATE_CACHE_INVALIDATE;
354b5c29a34SFrançois Tigeot 		/*
355b5c29a34SFrançois Tigeot 		 * TLB invalidate requires a post-sync write.
356b5c29a34SFrançois Tigeot 		 */
357b5c29a34SFrançois Tigeot 		flags |= PIPE_CONTROL_QW_WRITE;
358a2fdbec6SFrançois Tigeot 		flags |= PIPE_CONTROL_GLOBAL_GTT_IVB;
359b5c29a34SFrançois Tigeot 
3600dbf0ea8SMatthew Dillon 		flags |= PIPE_CONTROL_STALL_AT_SCOREBOARD;
3610dbf0ea8SMatthew Dillon 
362b5c29a34SFrançois Tigeot 		/* Workaround: we must issue a pipe_control with CS-stall bit
363b5c29a34SFrançois Tigeot 		 * set before a pipe_control command that has the state cache
364b5c29a34SFrançois Tigeot 		 * invalidate bit set. */
365b5c29a34SFrançois Tigeot 		gen7_render_ring_cs_stall_wa(ring);
366b5c29a34SFrançois Tigeot 	}
367b5c29a34SFrançois Tigeot 
368b5c29a34SFrançois Tigeot 	ret = intel_ring_begin(ring, 4);
369b5c29a34SFrançois Tigeot 	if (ret)
370b5c29a34SFrançois Tigeot 		return ret;
371b5c29a34SFrançois Tigeot 
372b5c29a34SFrançois Tigeot 	intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(4));
373b5c29a34SFrançois Tigeot 	intel_ring_emit(ring, flags);
374a2fdbec6SFrançois Tigeot 	intel_ring_emit(ring, scratch_addr);
375b5c29a34SFrançois Tigeot 	intel_ring_emit(ring, 0);
376e3adcf8fSFrançois Tigeot 	intel_ring_advance(ring);
377e3adcf8fSFrançois Tigeot 
3789edbd4a0SFrançois Tigeot 	if (!invalidate_domains && flush_domains)
3795d0b1887SFrançois Tigeot 		return gen7_ring_fbc_flush(ring, FBC_REND_NUKE);
3805d0b1887SFrançois Tigeot 
381e3adcf8fSFrançois Tigeot 	return 0;
382e3adcf8fSFrançois Tigeot }
383e3adcf8fSFrançois Tigeot 
3849edbd4a0SFrançois Tigeot static int
385*24edb884SFrançois Tigeot gen8_emit_pipe_control(struct intel_engine_cs *ring,
386*24edb884SFrançois Tigeot 		       u32 flags, u32 scratch_addr)
387*24edb884SFrançois Tigeot {
388*24edb884SFrançois Tigeot 	int ret;
389*24edb884SFrançois Tigeot 
390*24edb884SFrançois Tigeot 	ret = intel_ring_begin(ring, 6);
391*24edb884SFrançois Tigeot 	if (ret)
392*24edb884SFrançois Tigeot 		return ret;
393*24edb884SFrançois Tigeot 
394*24edb884SFrançois Tigeot 	intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(6));
395*24edb884SFrançois Tigeot 	intel_ring_emit(ring, flags);
396*24edb884SFrançois Tigeot 	intel_ring_emit(ring, scratch_addr);
397*24edb884SFrançois Tigeot 	intel_ring_emit(ring, 0);
398*24edb884SFrançois Tigeot 	intel_ring_emit(ring, 0);
399*24edb884SFrançois Tigeot 	intel_ring_emit(ring, 0);
400*24edb884SFrançois Tigeot 	intel_ring_advance(ring);
401*24edb884SFrançois Tigeot 
402*24edb884SFrançois Tigeot 	return 0;
403*24edb884SFrançois Tigeot }
404*24edb884SFrançois Tigeot 
405*24edb884SFrançois Tigeot static int
406ba55f2f5SFrançois Tigeot gen8_render_ring_flush(struct intel_engine_cs *ring,
4079edbd4a0SFrançois Tigeot 		       u32 invalidate_domains, u32 flush_domains)
4089edbd4a0SFrançois Tigeot {
4099edbd4a0SFrançois Tigeot 	u32 flags = 0;
410ba55f2f5SFrançois Tigeot 	u32 scratch_addr = ring->scratch.gtt_offset + 2 * CACHELINE_BYTES;
4119edbd4a0SFrançois Tigeot 	int ret;
4129edbd4a0SFrançois Tigeot 
4139edbd4a0SFrançois Tigeot 	flags |= PIPE_CONTROL_CS_STALL;
4149edbd4a0SFrançois Tigeot 
4159edbd4a0SFrançois Tigeot 	if (flush_domains) {
4169edbd4a0SFrançois Tigeot 		flags |= PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH;
4179edbd4a0SFrançois Tigeot 		flags |= PIPE_CONTROL_DEPTH_CACHE_FLUSH;
4189edbd4a0SFrançois Tigeot 	}
4199edbd4a0SFrançois Tigeot 	if (invalidate_domains) {
4209edbd4a0SFrançois Tigeot 		flags |= PIPE_CONTROL_TLB_INVALIDATE;
4219edbd4a0SFrançois Tigeot 		flags |= PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE;
4229edbd4a0SFrançois Tigeot 		flags |= PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE;
4239edbd4a0SFrançois Tigeot 		flags |= PIPE_CONTROL_VF_CACHE_INVALIDATE;
4249edbd4a0SFrançois Tigeot 		flags |= PIPE_CONTROL_CONST_CACHE_INVALIDATE;
4259edbd4a0SFrançois Tigeot 		flags |= PIPE_CONTROL_STATE_CACHE_INVALIDATE;
4269edbd4a0SFrançois Tigeot 		flags |= PIPE_CONTROL_QW_WRITE;
4279edbd4a0SFrançois Tigeot 		flags |= PIPE_CONTROL_GLOBAL_GTT_IVB;
4289edbd4a0SFrançois Tigeot 
429*24edb884SFrançois Tigeot 		/* WaCsStallBeforeStateCacheInvalidate:bdw,chv */
430*24edb884SFrançois Tigeot 		ret = gen8_emit_pipe_control(ring,
431*24edb884SFrançois Tigeot 					     PIPE_CONTROL_CS_STALL |
432*24edb884SFrançois Tigeot 					     PIPE_CONTROL_STALL_AT_SCOREBOARD,
433*24edb884SFrançois Tigeot 					     0);
4349edbd4a0SFrançois Tigeot 		if (ret)
4359edbd4a0SFrançois Tigeot 			return ret;
436*24edb884SFrançois Tigeot 	}
4379edbd4a0SFrançois Tigeot 
438*24edb884SFrançois Tigeot 	return gen8_emit_pipe_control(ring, flags, scratch_addr);
4399edbd4a0SFrançois Tigeot }
4409edbd4a0SFrançois Tigeot 
441ba55f2f5SFrançois Tigeot static void ring_write_tail(struct intel_engine_cs *ring,
442b5c29a34SFrançois Tigeot 			    u32 value)
443e3adcf8fSFrançois Tigeot {
444ba55f2f5SFrançois Tigeot 	struct drm_i915_private *dev_priv = ring->dev->dev_private;
445e3adcf8fSFrançois Tigeot 	I915_WRITE_TAIL(ring, value);
446e3adcf8fSFrançois Tigeot }
447e3adcf8fSFrançois Tigeot 
448ba55f2f5SFrançois Tigeot u64 intel_ring_get_active_head(struct intel_engine_cs *ring)
449e3adcf8fSFrançois Tigeot {
450ba55f2f5SFrançois Tigeot 	struct drm_i915_private *dev_priv = ring->dev->dev_private;
451ba55f2f5SFrançois Tigeot 	u64 acthd;
452e3adcf8fSFrançois Tigeot 
453ba55f2f5SFrançois Tigeot 	if (INTEL_INFO(ring->dev)->gen >= 8)
454ba55f2f5SFrançois Tigeot 		acthd = I915_READ64_2x32(RING_ACTHD(ring->mmio_base),
455ba55f2f5SFrançois Tigeot 					 RING_ACTHD_UDW(ring->mmio_base));
456ba55f2f5SFrançois Tigeot 	else if (INTEL_INFO(ring->dev)->gen >= 4)
457ba55f2f5SFrançois Tigeot 		acthd = I915_READ(RING_ACTHD(ring->mmio_base));
458ba55f2f5SFrançois Tigeot 	else
459ba55f2f5SFrançois Tigeot 		acthd = I915_READ(ACTHD);
460ba55f2f5SFrançois Tigeot 
461ba55f2f5SFrançois Tigeot 	return acthd;
462e3adcf8fSFrançois Tigeot }
463e3adcf8fSFrançois Tigeot 
464ba55f2f5SFrançois Tigeot static void ring_setup_phys_status_page(struct intel_engine_cs *ring)
4655d0b1887SFrançois Tigeot {
4665d0b1887SFrançois Tigeot 	struct drm_i915_private *dev_priv = ring->dev->dev_private;
4675d0b1887SFrançois Tigeot 	u32 addr;
4685d0b1887SFrançois Tigeot 
4695d0b1887SFrançois Tigeot 	addr = dev_priv->status_page_dmah->busaddr;
4705d0b1887SFrançois Tigeot 	if (INTEL_INFO(ring->dev)->gen >= 4)
4715d0b1887SFrançois Tigeot 		addr |= (dev_priv->status_page_dmah->busaddr >> 28) & 0xf0;
4725d0b1887SFrançois Tigeot 	I915_WRITE(HWS_PGA, addr);
4735d0b1887SFrançois Tigeot }
4745d0b1887SFrançois Tigeot 
475ba55f2f5SFrançois Tigeot static bool stop_ring(struct intel_engine_cs *ring)
476e3adcf8fSFrançois Tigeot {
477ba55f2f5SFrançois Tigeot 	struct drm_i915_private *dev_priv = to_i915(ring->dev);
478e3adcf8fSFrançois Tigeot 
479ba55f2f5SFrançois Tigeot 	if (!IS_GEN2(ring->dev)) {
480ba55f2f5SFrançois Tigeot 		I915_WRITE_MODE(ring, _MASKED_BIT_ENABLE(STOP_RING));
481ba55f2f5SFrançois Tigeot 		if (wait_for_atomic((I915_READ_MODE(ring) & MODE_IDLE) != 0, 1000)) {
482ba55f2f5SFrançois Tigeot 			DRM_ERROR("%s :timed out trying to stop ring\n", ring->name);
483ba55f2f5SFrançois Tigeot 			return false;
484ba55f2f5SFrançois Tigeot 		}
485ba55f2f5SFrançois Tigeot 	}
486686a02f1SFrançois Tigeot 
487e3adcf8fSFrançois Tigeot 	I915_WRITE_CTL(ring, 0);
488e3adcf8fSFrançois Tigeot 	I915_WRITE_HEAD(ring, 0);
489e3adcf8fSFrançois Tigeot 	ring->write_tail(ring, 0);
490e3adcf8fSFrançois Tigeot 
491ba55f2f5SFrançois Tigeot 	if (!IS_GEN2(ring->dev)) {
492ba55f2f5SFrançois Tigeot 		(void)I915_READ_CTL(ring);
493ba55f2f5SFrançois Tigeot 		I915_WRITE_MODE(ring, _MASKED_BIT_DISABLE(STOP_RING));
494ba55f2f5SFrançois Tigeot 	}
495e3adcf8fSFrançois Tigeot 
496ba55f2f5SFrançois Tigeot 	return (I915_READ_HEAD(ring) & HEAD_ADDR) == 0;
497ba55f2f5SFrançois Tigeot }
498ba55f2f5SFrançois Tigeot 
499ba55f2f5SFrançois Tigeot static int init_ring_common(struct intel_engine_cs *ring)
500ba55f2f5SFrançois Tigeot {
501ba55f2f5SFrançois Tigeot 	struct drm_device *dev = ring->dev;
502ba55f2f5SFrançois Tigeot 	struct drm_i915_private *dev_priv = dev->dev_private;
503ba55f2f5SFrançois Tigeot 	struct intel_ringbuffer *ringbuf = ring->buffer;
504ba55f2f5SFrançois Tigeot 	struct drm_i915_gem_object *obj = ringbuf->obj;
505ba55f2f5SFrançois Tigeot 	int ret = 0;
506ba55f2f5SFrançois Tigeot 
507ba55f2f5SFrançois Tigeot 	gen6_gt_force_wake_get(dev_priv, FORCEWAKE_ALL);
508ba55f2f5SFrançois Tigeot 
509ba55f2f5SFrançois Tigeot 	if (!stop_ring(ring)) {
510ba55f2f5SFrançois Tigeot 		/* G45 ring initialization often fails to reset head to zero */
511b5c29a34SFrançois Tigeot 		DRM_DEBUG_KMS("%s head not reset to zero "
512e3adcf8fSFrançois Tigeot 			      "ctl %08x head %08x tail %08x start %08x\n",
513e3adcf8fSFrançois Tigeot 			      ring->name,
514e3adcf8fSFrançois Tigeot 			      I915_READ_CTL(ring),
515e3adcf8fSFrançois Tigeot 			      I915_READ_HEAD(ring),
516e3adcf8fSFrançois Tigeot 			      I915_READ_TAIL(ring),
517e3adcf8fSFrançois Tigeot 			      I915_READ_START(ring));
518e3adcf8fSFrançois Tigeot 
519ba55f2f5SFrançois Tigeot 		if (!stop_ring(ring)) {
520e3adcf8fSFrançois Tigeot 			DRM_ERROR("failed to set %s head to zero "
521e3adcf8fSFrançois Tigeot 				  "ctl %08x head %08x tail %08x start %08x\n",
522e3adcf8fSFrançois Tigeot 				  ring->name,
523e3adcf8fSFrançois Tigeot 				  I915_READ_CTL(ring),
524e3adcf8fSFrançois Tigeot 				  I915_READ_HEAD(ring),
525e3adcf8fSFrançois Tigeot 				  I915_READ_TAIL(ring),
526e3adcf8fSFrançois Tigeot 				  I915_READ_START(ring));
527686a02f1SFrançois Tigeot 			ret = -EIO;
528686a02f1SFrançois Tigeot 			goto out;
529e3adcf8fSFrançois Tigeot 		}
530ba55f2f5SFrançois Tigeot 	}
531ba55f2f5SFrançois Tigeot 
532ba55f2f5SFrançois Tigeot 	if (I915_NEED_GFX_HWS(dev))
533ba55f2f5SFrançois Tigeot 		intel_ring_setup_status_page(ring);
534ba55f2f5SFrançois Tigeot 	else
535ba55f2f5SFrançois Tigeot 		ring_setup_phys_status_page(ring);
536ba55f2f5SFrançois Tigeot 
5370f370975SMatthew Dillon 	/* Enforce ordering by reading HEAD register back */
5380f370975SMatthew Dillon 	I915_READ_HEAD(ring);
5390f370975SMatthew Dillon 
540ba55f2f5SFrançois Tigeot 	/* Initialize the ring. This must happen _after_ we've cleared the ring
541ba55f2f5SFrançois Tigeot 	 * registers with the above sequence (the readback of the HEAD registers
542ba55f2f5SFrançois Tigeot 	 * also enforces ordering), otherwise the hw might lose the new ring
543ba55f2f5SFrançois Tigeot 	 * register values. */
544ba55f2f5SFrançois Tigeot 	I915_WRITE_START(ring, i915_gem_obj_ggtt_offset(obj));
545ba55f2f5SFrançois Tigeot 	I915_WRITE_CTL(ring,
546ba55f2f5SFrançois Tigeot 			((ringbuf->size - PAGE_SIZE) & RING_NR_PAGES)
547ba55f2f5SFrançois Tigeot 			| RING_VALID);
548ba55f2f5SFrançois Tigeot 
549ba55f2f5SFrançois Tigeot 	/* If the head is still not zero, the ring is dead */
550ba55f2f5SFrançois Tigeot 	if (wait_for((I915_READ_CTL(ring) & RING_VALID) != 0 &&
551ba55f2f5SFrançois Tigeot 		     I915_READ_START(ring) == i915_gem_obj_ggtt_offset(obj) &&
552ba55f2f5SFrançois Tigeot 		     (I915_READ_HEAD(ring) & HEAD_ADDR) == 0, 50)) {
553ba55f2f5SFrançois Tigeot 		DRM_ERROR("%s initialization failed "
554ba55f2f5SFrançois Tigeot 			  "ctl %08x (valid? %d) head %08x tail %08x start %08x [expected %08lx]\n",
555ba55f2f5SFrançois Tigeot 			  ring->name,
556ba55f2f5SFrançois Tigeot 			  I915_READ_CTL(ring), I915_READ_CTL(ring) & RING_VALID,
557ba55f2f5SFrançois Tigeot 			  I915_READ_HEAD(ring), I915_READ_TAIL(ring),
558ba55f2f5SFrançois Tigeot 			  I915_READ_START(ring), (unsigned long)i915_gem_obj_ggtt_offset(obj));
559ba55f2f5SFrançois Tigeot 		ret = -EIO;
560ba55f2f5SFrançois Tigeot 		goto out;
561ba55f2f5SFrançois Tigeot 	}
562e3adcf8fSFrançois Tigeot 
563e3adcf8fSFrançois Tigeot 	if (!drm_core_check_feature(ring->dev, DRIVER_MODESET))
564e3adcf8fSFrançois Tigeot 		i915_kernel_lost_context(ring->dev);
565e3adcf8fSFrançois Tigeot 	else {
566ba55f2f5SFrançois Tigeot 		ringbuf->head = I915_READ_HEAD(ring);
567ba55f2f5SFrançois Tigeot 		ringbuf->tail = I915_READ_TAIL(ring) & TAIL_ADDR;
568*24edb884SFrançois Tigeot 		ringbuf->space = ring_space(ringbuf);
569ba55f2f5SFrançois Tigeot 		ringbuf->last_retired_head = -1;
570e3adcf8fSFrançois Tigeot 	}
571e3adcf8fSFrançois Tigeot 
5725d0b1887SFrançois Tigeot 	memset(&ring->hangcheck, 0, sizeof(ring->hangcheck));
5735d0b1887SFrançois Tigeot 
574686a02f1SFrançois Tigeot out:
5759edbd4a0SFrançois Tigeot 	gen6_gt_force_wake_put(dev_priv, FORCEWAKE_ALL);
576686a02f1SFrançois Tigeot 
577686a02f1SFrançois Tigeot 	return ret;
578e3adcf8fSFrançois Tigeot }
579e3adcf8fSFrançois Tigeot 
580e3adcf8fSFrançois Tigeot static int
581ba55f2f5SFrançois Tigeot init_pipe_control(struct intel_engine_cs *ring)
582e3adcf8fSFrançois Tigeot {
583e3adcf8fSFrançois Tigeot 	int ret;
584e3adcf8fSFrançois Tigeot 
5859edbd4a0SFrançois Tigeot 	if (ring->scratch.obj)
586e3adcf8fSFrançois Tigeot 		return 0;
587e3adcf8fSFrançois Tigeot 
5889edbd4a0SFrançois Tigeot 	ring->scratch.obj = i915_gem_alloc_object(ring->dev, 4096);
5899edbd4a0SFrançois Tigeot 	if (ring->scratch.obj == NULL) {
590e3adcf8fSFrançois Tigeot 		DRM_ERROR("Failed to allocate seqno page\n");
591e3adcf8fSFrançois Tigeot 		ret = -ENOMEM;
592e3adcf8fSFrançois Tigeot 		goto err;
593e3adcf8fSFrançois Tigeot 	}
594e3adcf8fSFrançois Tigeot 
595ba55f2f5SFrançois Tigeot 	ret = i915_gem_object_set_cache_level(ring->scratch.obj, I915_CACHE_LLC);
596ba55f2f5SFrançois Tigeot 	if (ret)
597ba55f2f5SFrançois Tigeot 		goto err_unref;
598e3adcf8fSFrançois Tigeot 
599ba55f2f5SFrançois Tigeot 	ret = i915_gem_obj_ggtt_pin(ring->scratch.obj, 4096, 0);
600e3adcf8fSFrançois Tigeot 	if (ret)
601e3adcf8fSFrançois Tigeot 		goto err_unref;
602e3adcf8fSFrançois Tigeot 
6039edbd4a0SFrançois Tigeot 	ring->scratch.gtt_offset = i915_gem_obj_ggtt_offset(ring->scratch.obj);
6049edbd4a0SFrançois Tigeot 	ring->scratch.cpu_page = kmap(ring->scratch.obj->pages[0]);
6059edbd4a0SFrançois Tigeot 	if (ring->scratch.cpu_page == NULL) {
6065d0b1887SFrançois Tigeot 		ret = -ENOMEM;
607e3adcf8fSFrançois Tigeot 		goto err_unpin;
6085d0b1887SFrançois Tigeot 	}
609a2fdbec6SFrançois Tigeot 
610a2fdbec6SFrançois Tigeot 	DRM_DEBUG_DRIVER("%s pipe control offset: 0x%08x\n",
6119edbd4a0SFrançois Tigeot 			 ring->name, ring->scratch.gtt_offset);
612e3adcf8fSFrançois Tigeot 	return 0;
613e3adcf8fSFrançois Tigeot 
614e3adcf8fSFrançois Tigeot err_unpin:
615ba55f2f5SFrançois Tigeot 	i915_gem_object_ggtt_unpin(ring->scratch.obj);
616e3adcf8fSFrançois Tigeot err_unref:
6179edbd4a0SFrançois Tigeot 	drm_gem_object_unreference(&ring->scratch.obj->base);
618e3adcf8fSFrançois Tigeot err:
619e3adcf8fSFrançois Tigeot 	return ret;
620e3adcf8fSFrançois Tigeot }
621e3adcf8fSFrançois Tigeot 
622ba55f2f5SFrançois Tigeot static int init_render_ring(struct intel_engine_cs *ring)
623e3adcf8fSFrançois Tigeot {
624e3adcf8fSFrançois Tigeot 	struct drm_device *dev = ring->dev;
625e3adcf8fSFrançois Tigeot 	struct drm_i915_private *dev_priv = dev->dev_private;
626e3adcf8fSFrançois Tigeot 	int ret = init_ring_common(ring);
627*24edb884SFrançois Tigeot 	if (ret)
628*24edb884SFrançois Tigeot 		return ret;
629e3adcf8fSFrançois Tigeot 
630ba55f2f5SFrançois Tigeot 	/* WaTimedSingleVertexDispatch:cl,bw,ctg,elk,ilk,snb */
631ba55f2f5SFrançois Tigeot 	if (INTEL_INFO(dev)->gen >= 4 && INTEL_INFO(dev)->gen < 7)
632f4e1c372SFrançois Tigeot 		I915_WRITE(MI_MODE, _MASKED_BIT_ENABLE(VS_TIMER_DISPATCH));
633f4e1c372SFrançois Tigeot 
634f4e1c372SFrançois Tigeot 	/* We need to disable the AsyncFlip performance optimisations in order
635f4e1c372SFrançois Tigeot 	 * to use MI_WAIT_FOR_EVENT within the CS. It should already be
636f4e1c372SFrançois Tigeot 	 * programmed to '1' on all products.
6375d0b1887SFrançois Tigeot 	 *
638ba55f2f5SFrançois Tigeot 	 * WaDisableAsyncFlipPerfMode:snb,ivb,hsw,vlv,bdw,chv
639f4e1c372SFrançois Tigeot 	 */
640f4e1c372SFrançois Tigeot 	if (INTEL_INFO(dev)->gen >= 6)
641f4e1c372SFrançois Tigeot 		I915_WRITE(MI_MODE, _MASKED_BIT_ENABLE(ASYNC_FLIP_PERF_DISABLE));
642f4e1c372SFrançois Tigeot 
643f4e1c372SFrançois Tigeot 	/* Required for the hardware to program scanline values for waiting */
644ba55f2f5SFrançois Tigeot 	/* WaEnableFlushTlbInvalidationMode:snb */
645f4e1c372SFrançois Tigeot 	if (INTEL_INFO(dev)->gen == 6)
646f4e1c372SFrançois Tigeot 		I915_WRITE(GFX_MODE,
647ba55f2f5SFrançois Tigeot 			   _MASKED_BIT_ENABLE(GFX_TLB_INVALIDATE_EXPLICIT));
648f4e1c372SFrançois Tigeot 
649ba55f2f5SFrançois Tigeot 	/* WaBCSVCSTlbInvalidationMode:ivb,vlv,hsw */
650e3adcf8fSFrançois Tigeot 	if (IS_GEN7(dev))
651e3adcf8fSFrançois Tigeot 		I915_WRITE(GFX_MODE_GEN7,
652ba55f2f5SFrançois Tigeot 			   _MASKED_BIT_ENABLE(GFX_TLB_INVALIDATE_EXPLICIT) |
653f4e1c372SFrançois Tigeot 			   _MASKED_BIT_ENABLE(GFX_REPLAY_MODE));
654e3adcf8fSFrançois Tigeot 
655e3adcf8fSFrançois Tigeot 	if (INTEL_INFO(dev)->gen >= 5) {
656e3adcf8fSFrançois Tigeot 		ret = init_pipe_control(ring);
657e3adcf8fSFrançois Tigeot 		if (ret)
658e3adcf8fSFrançois Tigeot 			return ret;
659e3adcf8fSFrançois Tigeot 	}
660e3adcf8fSFrançois Tigeot 
661e3adcf8fSFrançois Tigeot 	if (IS_GEN6(dev)) {
662e3adcf8fSFrançois Tigeot 		/* From the Sandybridge PRM, volume 1 part 3, page 24:
663e3adcf8fSFrançois Tigeot 		 * "If this bit is set, STCunit will have LRA as replacement
664e3adcf8fSFrançois Tigeot 		 *  policy. [...] This bit must be reset.  LRA replacement
665e3adcf8fSFrançois Tigeot 		 *  policy is not supported."
666e3adcf8fSFrançois Tigeot 		 */
667e3adcf8fSFrançois Tigeot 		I915_WRITE(CACHE_MODE_0,
668f4e1c372SFrançois Tigeot 			   _MASKED_BIT_DISABLE(CM0_STC_EVICT_DISABLE_LRA_SNB));
669e3adcf8fSFrançois Tigeot 	}
670e3adcf8fSFrançois Tigeot 
671f4e1c372SFrançois Tigeot 	if (INTEL_INFO(dev)->gen >= 6)
672f4e1c372SFrançois Tigeot 		I915_WRITE(INSTPM, _MASKED_BIT_ENABLE(INSTPM_FORCE_ORDERING));
673f4e1c372SFrançois Tigeot 
6749edbd4a0SFrançois Tigeot 	if (HAS_L3_DPF(dev))
6759edbd4a0SFrançois Tigeot 		I915_WRITE_IMR(ring, ~GT_PARITY_ERROR(dev));
676e3adcf8fSFrançois Tigeot 
677e3adcf8fSFrançois Tigeot 	return ret;
678e3adcf8fSFrançois Tigeot }
679e3adcf8fSFrançois Tigeot 
680ba55f2f5SFrançois Tigeot static void render_ring_cleanup(struct intel_engine_cs *ring)
681e3adcf8fSFrançois Tigeot {
682b5c29a34SFrançois Tigeot 	struct drm_device *dev = ring->dev;
683*24edb884SFrançois Tigeot 	struct drm_i915_private *dev_priv = dev->dev_private;
684*24edb884SFrançois Tigeot 
685*24edb884SFrançois Tigeot 	if (dev_priv->semaphore_obj) {
686*24edb884SFrançois Tigeot 		i915_gem_object_ggtt_unpin(dev_priv->semaphore_obj);
687*24edb884SFrançois Tigeot 		drm_gem_object_unreference(&dev_priv->semaphore_obj->base);
688*24edb884SFrançois Tigeot 		dev_priv->semaphore_obj = NULL;
689*24edb884SFrançois Tigeot 	}
690b5c29a34SFrançois Tigeot 
6919edbd4a0SFrançois Tigeot 	if (ring->scratch.obj == NULL)
692e3adcf8fSFrançois Tigeot 		return;
693e3adcf8fSFrançois Tigeot 
6949edbd4a0SFrançois Tigeot 	if (INTEL_INFO(dev)->gen >= 5) {
6959edbd4a0SFrançois Tigeot 		kunmap(ring->scratch.obj->pages[0]);
696ba55f2f5SFrançois Tigeot 		i915_gem_object_ggtt_unpin(ring->scratch.obj);
6979edbd4a0SFrançois Tigeot 	}
698b5c29a34SFrançois Tigeot 
6999edbd4a0SFrançois Tigeot 	drm_gem_object_unreference(&ring->scratch.obj->base);
7009edbd4a0SFrançois Tigeot 	ring->scratch.obj = NULL;
701e3adcf8fSFrançois Tigeot }
702e3adcf8fSFrançois Tigeot 
703*24edb884SFrançois Tigeot static int gen8_rcs_signal(struct intel_engine_cs *signaller,
704*24edb884SFrançois Tigeot 			   unsigned int num_dwords)
705*24edb884SFrançois Tigeot {
706*24edb884SFrançois Tigeot #define MBOX_UPDATE_DWORDS 8
707*24edb884SFrançois Tigeot 	struct drm_device *dev = signaller->dev;
708*24edb884SFrançois Tigeot 	struct drm_i915_private *dev_priv = dev->dev_private;
709*24edb884SFrançois Tigeot 	struct intel_engine_cs *waiter;
710*24edb884SFrançois Tigeot 	int i, ret, num_rings;
711*24edb884SFrançois Tigeot 
712*24edb884SFrançois Tigeot 	num_rings = hweight32(INTEL_INFO(dev)->ring_mask);
713*24edb884SFrançois Tigeot 	num_dwords += (num_rings-1) * MBOX_UPDATE_DWORDS;
714*24edb884SFrançois Tigeot #undef MBOX_UPDATE_DWORDS
715*24edb884SFrançois Tigeot 
716*24edb884SFrançois Tigeot 	ret = intel_ring_begin(signaller, num_dwords);
717*24edb884SFrançois Tigeot 	if (ret)
718*24edb884SFrançois Tigeot 		return ret;
719*24edb884SFrançois Tigeot 
720*24edb884SFrançois Tigeot 	for_each_ring(waiter, dev_priv, i) {
721*24edb884SFrançois Tigeot 		u64 gtt_offset = signaller->semaphore.signal_ggtt[i];
722*24edb884SFrançois Tigeot 		if (gtt_offset == MI_SEMAPHORE_SYNC_INVALID)
723*24edb884SFrançois Tigeot 			continue;
724*24edb884SFrançois Tigeot 
725*24edb884SFrançois Tigeot 		intel_ring_emit(signaller, GFX_OP_PIPE_CONTROL(6));
726*24edb884SFrançois Tigeot 		intel_ring_emit(signaller, PIPE_CONTROL_GLOBAL_GTT_IVB |
727*24edb884SFrançois Tigeot 					   PIPE_CONTROL_QW_WRITE |
728*24edb884SFrançois Tigeot 					   PIPE_CONTROL_FLUSH_ENABLE);
729*24edb884SFrançois Tigeot 		intel_ring_emit(signaller, lower_32_bits(gtt_offset));
730*24edb884SFrançois Tigeot 		intel_ring_emit(signaller, upper_32_bits(gtt_offset));
731*24edb884SFrançois Tigeot 		intel_ring_emit(signaller, signaller->outstanding_lazy_seqno);
732*24edb884SFrançois Tigeot 		intel_ring_emit(signaller, 0);
733*24edb884SFrançois Tigeot 		intel_ring_emit(signaller, MI_SEMAPHORE_SIGNAL |
734*24edb884SFrançois Tigeot 					   MI_SEMAPHORE_TARGET(waiter->id));
735*24edb884SFrançois Tigeot 		intel_ring_emit(signaller, 0);
736*24edb884SFrançois Tigeot 	}
737*24edb884SFrançois Tigeot 
738*24edb884SFrançois Tigeot 	return 0;
739*24edb884SFrançois Tigeot }
740*24edb884SFrançois Tigeot 
741*24edb884SFrançois Tigeot static int gen8_xcs_signal(struct intel_engine_cs *signaller,
742*24edb884SFrançois Tigeot 			   unsigned int num_dwords)
743*24edb884SFrançois Tigeot {
744*24edb884SFrançois Tigeot #define MBOX_UPDATE_DWORDS 6
745*24edb884SFrançois Tigeot 	struct drm_device *dev = signaller->dev;
746*24edb884SFrançois Tigeot 	struct drm_i915_private *dev_priv = dev->dev_private;
747*24edb884SFrançois Tigeot 	struct intel_engine_cs *waiter;
748*24edb884SFrançois Tigeot 	int i, ret, num_rings;
749*24edb884SFrançois Tigeot 
750*24edb884SFrançois Tigeot 	num_rings = hweight32(INTEL_INFO(dev)->ring_mask);
751*24edb884SFrançois Tigeot 	num_dwords += (num_rings-1) * MBOX_UPDATE_DWORDS;
752*24edb884SFrançois Tigeot #undef MBOX_UPDATE_DWORDS
753*24edb884SFrançois Tigeot 
754*24edb884SFrançois Tigeot 	ret = intel_ring_begin(signaller, num_dwords);
755*24edb884SFrançois Tigeot 	if (ret)
756*24edb884SFrançois Tigeot 		return ret;
757*24edb884SFrançois Tigeot 
758*24edb884SFrançois Tigeot 	for_each_ring(waiter, dev_priv, i) {
759*24edb884SFrançois Tigeot 		u64 gtt_offset = signaller->semaphore.signal_ggtt[i];
760*24edb884SFrançois Tigeot 		if (gtt_offset == MI_SEMAPHORE_SYNC_INVALID)
761*24edb884SFrançois Tigeot 			continue;
762*24edb884SFrançois Tigeot 
763*24edb884SFrançois Tigeot 		intel_ring_emit(signaller, (MI_FLUSH_DW + 1) |
764*24edb884SFrançois Tigeot 					   MI_FLUSH_DW_OP_STOREDW);
765*24edb884SFrançois Tigeot 		intel_ring_emit(signaller, lower_32_bits(gtt_offset) |
766*24edb884SFrançois Tigeot 					   MI_FLUSH_DW_USE_GTT);
767*24edb884SFrançois Tigeot 		intel_ring_emit(signaller, upper_32_bits(gtt_offset));
768*24edb884SFrançois Tigeot 		intel_ring_emit(signaller, signaller->outstanding_lazy_seqno);
769*24edb884SFrançois Tigeot 		intel_ring_emit(signaller, MI_SEMAPHORE_SIGNAL |
770*24edb884SFrançois Tigeot 					   MI_SEMAPHORE_TARGET(waiter->id));
771*24edb884SFrançois Tigeot 		intel_ring_emit(signaller, 0);
772*24edb884SFrançois Tigeot 	}
773*24edb884SFrançois Tigeot 
774*24edb884SFrançois Tigeot 	return 0;
775*24edb884SFrançois Tigeot }
776*24edb884SFrançois Tigeot 
777ba55f2f5SFrançois Tigeot static int gen6_signal(struct intel_engine_cs *signaller,
778ba55f2f5SFrançois Tigeot 		       unsigned int num_dwords)
779e3adcf8fSFrançois Tigeot {
780ba55f2f5SFrançois Tigeot 	struct drm_device *dev = signaller->dev;
781ba55f2f5SFrançois Tigeot 	struct drm_i915_private *dev_priv = dev->dev_private;
782ba55f2f5SFrançois Tigeot 	struct intel_engine_cs *useless;
783*24edb884SFrançois Tigeot 	int i, ret, num_rings;
784ba55f2f5SFrançois Tigeot 
785*24edb884SFrançois Tigeot #define MBOX_UPDATE_DWORDS 3
786*24edb884SFrançois Tigeot 	num_rings = hweight32(INTEL_INFO(dev)->ring_mask);
787*24edb884SFrançois Tigeot 	num_dwords += round_up((num_rings-1) * MBOX_UPDATE_DWORDS, 2);
788*24edb884SFrançois Tigeot #undef MBOX_UPDATE_DWORDS
789ba55f2f5SFrançois Tigeot 
790ba55f2f5SFrançois Tigeot 	ret = intel_ring_begin(signaller, num_dwords);
791ba55f2f5SFrançois Tigeot 	if (ret)
792ba55f2f5SFrançois Tigeot 		return ret;
793ba55f2f5SFrançois Tigeot 
794ba55f2f5SFrançois Tigeot 	for_each_ring(useless, dev_priv, i) {
795ba55f2f5SFrançois Tigeot 		u32 mbox_reg = signaller->semaphore.mbox.signal[i];
796ba55f2f5SFrançois Tigeot 		if (mbox_reg != GEN6_NOSYNC) {
797ba55f2f5SFrançois Tigeot 			intel_ring_emit(signaller, MI_LOAD_REGISTER_IMM(1));
798ba55f2f5SFrançois Tigeot 			intel_ring_emit(signaller, mbox_reg);
799ba55f2f5SFrançois Tigeot 			intel_ring_emit(signaller, signaller->outstanding_lazy_seqno);
800ba55f2f5SFrançois Tigeot 		}
801ba55f2f5SFrançois Tigeot 	}
802ba55f2f5SFrançois Tigeot 
803*24edb884SFrançois Tigeot 	/* If num_dwords was rounded, make sure the tail pointer is correct */
804*24edb884SFrançois Tigeot 	if (num_rings % 2 == 0)
805*24edb884SFrançois Tigeot 		intel_ring_emit(signaller, MI_NOOP);
806*24edb884SFrançois Tigeot 
807ba55f2f5SFrançois Tigeot 	return 0;
808e3adcf8fSFrançois Tigeot }
809e3adcf8fSFrançois Tigeot 
810e3adcf8fSFrançois Tigeot /**
811e3adcf8fSFrançois Tigeot  * gen6_add_request - Update the semaphore mailbox registers
812e3adcf8fSFrançois Tigeot  *
813e3adcf8fSFrançois Tigeot  * @ring - ring that is adding a request
814e3adcf8fSFrançois Tigeot  * @seqno - return seqno stuck into the ring
815e3adcf8fSFrançois Tigeot  *
816e3adcf8fSFrançois Tigeot  * Update the mailbox registers in the *other* rings with the current seqno.
817e3adcf8fSFrançois Tigeot  * This acts like a signal in the canonical semaphore.
818e3adcf8fSFrançois Tigeot  */
819e3adcf8fSFrançois Tigeot static int
820ba55f2f5SFrançois Tigeot gen6_add_request(struct intel_engine_cs *ring)
821e3adcf8fSFrançois Tigeot {
822ba55f2f5SFrançois Tigeot 	int ret;
823e3adcf8fSFrançois Tigeot 
824*24edb884SFrançois Tigeot 	if (ring->semaphore.signal)
825ba55f2f5SFrançois Tigeot 		ret = ring->semaphore.signal(ring, 4);
826*24edb884SFrançois Tigeot 	else
827*24edb884SFrançois Tigeot 		ret = intel_ring_begin(ring, 4);
828*24edb884SFrançois Tigeot 
8299edbd4a0SFrançois Tigeot 	if (ret)
8309edbd4a0SFrançois Tigeot 		return ret;
8319edbd4a0SFrançois Tigeot 
832e3adcf8fSFrançois Tigeot 	intel_ring_emit(ring, MI_STORE_DWORD_INDEX);
833e3adcf8fSFrançois Tigeot 	intel_ring_emit(ring, I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT);
8349edbd4a0SFrançois Tigeot 	intel_ring_emit(ring, ring->outstanding_lazy_seqno);
835e3adcf8fSFrançois Tigeot 	intel_ring_emit(ring, MI_USER_INTERRUPT);
8369edbd4a0SFrançois Tigeot 	__intel_ring_advance(ring);
837e3adcf8fSFrançois Tigeot 
838e3adcf8fSFrançois Tigeot 	return 0;
839e3adcf8fSFrançois Tigeot }
840e3adcf8fSFrançois Tigeot 
841a2fdbec6SFrançois Tigeot static inline bool i915_gem_has_seqno_wrapped(struct drm_device *dev,
842a2fdbec6SFrançois Tigeot 					      u32 seqno)
843a2fdbec6SFrançois Tigeot {
844a2fdbec6SFrançois Tigeot 	struct drm_i915_private *dev_priv = dev->dev_private;
845a2fdbec6SFrançois Tigeot 	return dev_priv->last_seqno < seqno;
846a2fdbec6SFrançois Tigeot }
847a2fdbec6SFrançois Tigeot 
848e3adcf8fSFrançois Tigeot /**
849e3adcf8fSFrançois Tigeot  * intel_ring_sync - sync the waiter to the signaller on seqno
850e3adcf8fSFrançois Tigeot  *
851e3adcf8fSFrançois Tigeot  * @waiter - ring that is waiting
852e3adcf8fSFrançois Tigeot  * @signaller - ring which has, or will signal
853e3adcf8fSFrançois Tigeot  * @seqno - seqno which the waiter will block on
854e3adcf8fSFrançois Tigeot  */
855*24edb884SFrançois Tigeot 
856*24edb884SFrançois Tigeot static int
857*24edb884SFrançois Tigeot gen8_ring_sync(struct intel_engine_cs *waiter,
858*24edb884SFrançois Tigeot 	       struct intel_engine_cs *signaller,
859*24edb884SFrançois Tigeot 	       u32 seqno)
860*24edb884SFrançois Tigeot {
861*24edb884SFrançois Tigeot 	struct drm_i915_private *dev_priv = waiter->dev->dev_private;
862*24edb884SFrançois Tigeot 	int ret;
863*24edb884SFrançois Tigeot 
864*24edb884SFrançois Tigeot 	ret = intel_ring_begin(waiter, 4);
865*24edb884SFrançois Tigeot 	if (ret)
866*24edb884SFrançois Tigeot 		return ret;
867*24edb884SFrançois Tigeot 
868*24edb884SFrançois Tigeot 	intel_ring_emit(waiter, MI_SEMAPHORE_WAIT |
869*24edb884SFrançois Tigeot 				MI_SEMAPHORE_GLOBAL_GTT |
870*24edb884SFrançois Tigeot 				MI_SEMAPHORE_POLL |
871*24edb884SFrançois Tigeot 				MI_SEMAPHORE_SAD_GTE_SDD);
872*24edb884SFrançois Tigeot 	intel_ring_emit(waiter, seqno);
873*24edb884SFrançois Tigeot 	intel_ring_emit(waiter,
874*24edb884SFrançois Tigeot 			lower_32_bits(GEN8_WAIT_OFFSET(waiter, signaller->id)));
875*24edb884SFrançois Tigeot 	intel_ring_emit(waiter,
876*24edb884SFrançois Tigeot 			upper_32_bits(GEN8_WAIT_OFFSET(waiter, signaller->id)));
877*24edb884SFrançois Tigeot 	intel_ring_advance(waiter);
878*24edb884SFrançois Tigeot 	return 0;
879*24edb884SFrançois Tigeot }
880*24edb884SFrançois Tigeot 
881e3adcf8fSFrançois Tigeot static int
882ba55f2f5SFrançois Tigeot gen6_ring_sync(struct intel_engine_cs *waiter,
883ba55f2f5SFrançois Tigeot 	       struct intel_engine_cs *signaller,
884e3adcf8fSFrançois Tigeot 	       u32 seqno)
885e3adcf8fSFrançois Tigeot {
886e3adcf8fSFrançois Tigeot 	u32 dw1 = MI_SEMAPHORE_MBOX |
887e3adcf8fSFrançois Tigeot 		  MI_SEMAPHORE_COMPARE |
888e3adcf8fSFrançois Tigeot 		  MI_SEMAPHORE_REGISTER;
889ba55f2f5SFrançois Tigeot 	u32 wait_mbox = signaller->semaphore.mbox.wait[waiter->id];
890ba55f2f5SFrançois Tigeot 	int ret;
891e3adcf8fSFrançois Tigeot 
892686a02f1SFrançois Tigeot 	/* Throughout all of the GEM code, seqno passed implies our current
893686a02f1SFrançois Tigeot 	 * seqno is >= the last seqno executed. However for hardware the
894686a02f1SFrançois Tigeot 	 * comparison is strictly greater than.
895686a02f1SFrançois Tigeot 	 */
896686a02f1SFrançois Tigeot 	seqno -= 1;
897686a02f1SFrançois Tigeot 
898ba55f2f5SFrançois Tigeot 	WARN_ON(wait_mbox == MI_SEMAPHORE_SYNC_INVALID);
899686a02f1SFrançois Tigeot 
900e3adcf8fSFrançois Tigeot 	ret = intel_ring_begin(waiter, 4);
901e3adcf8fSFrançois Tigeot 	if (ret)
902e3adcf8fSFrançois Tigeot 		return ret;
903e3adcf8fSFrançois Tigeot 
904a2fdbec6SFrançois Tigeot 	/* If seqno wrap happened, omit the wait with no-ops */
905a2fdbec6SFrançois Tigeot 	if (likely(!i915_gem_has_seqno_wrapped(waiter->dev, seqno))) {
906ba55f2f5SFrançois Tigeot 		intel_ring_emit(waiter, dw1 | wait_mbox);
907e3adcf8fSFrançois Tigeot 		intel_ring_emit(waiter, seqno);
908e3adcf8fSFrançois Tigeot 		intel_ring_emit(waiter, 0);
909e3adcf8fSFrançois Tigeot 		intel_ring_emit(waiter, MI_NOOP);
910a2fdbec6SFrançois Tigeot 	} else {
911a2fdbec6SFrançois Tigeot 		intel_ring_emit(waiter, MI_NOOP);
912a2fdbec6SFrançois Tigeot 		intel_ring_emit(waiter, MI_NOOP);
913a2fdbec6SFrançois Tigeot 		intel_ring_emit(waiter, MI_NOOP);
914a2fdbec6SFrançois Tigeot 		intel_ring_emit(waiter, MI_NOOP);
915a2fdbec6SFrançois Tigeot 	}
916e3adcf8fSFrançois Tigeot 	intel_ring_advance(waiter);
917e3adcf8fSFrançois Tigeot 
918e3adcf8fSFrançois Tigeot 	return 0;
919e3adcf8fSFrançois Tigeot }
920e3adcf8fSFrançois Tigeot 
921e3adcf8fSFrançois Tigeot #define PIPE_CONTROL_FLUSH(ring__, addr__)					\
922e3adcf8fSFrançois Tigeot do {									\
923e3adcf8fSFrançois Tigeot 	intel_ring_emit(ring__, GFX_OP_PIPE_CONTROL(4) | PIPE_CONTROL_QW_WRITE |		\
924e3adcf8fSFrançois Tigeot 		 PIPE_CONTROL_DEPTH_STALL);				\
925e3adcf8fSFrançois Tigeot 	intel_ring_emit(ring__, (addr__) | PIPE_CONTROL_GLOBAL_GTT);			\
926e3adcf8fSFrançois Tigeot 	intel_ring_emit(ring__, 0);							\
927e3adcf8fSFrançois Tigeot 	intel_ring_emit(ring__, 0);							\
928e3adcf8fSFrançois Tigeot } while (0)
929e3adcf8fSFrançois Tigeot 
930e3adcf8fSFrançois Tigeot static int
931ba55f2f5SFrançois Tigeot pc_render_add_request(struct intel_engine_cs *ring)
932e3adcf8fSFrançois Tigeot {
933ba55f2f5SFrançois Tigeot 	u32 scratch_addr = ring->scratch.gtt_offset + 2 * CACHELINE_BYTES;
934e3adcf8fSFrançois Tigeot 	int ret;
935e3adcf8fSFrançois Tigeot 
936e3adcf8fSFrançois Tigeot 	/* For Ironlake, MI_USER_INTERRUPT was deprecated and apparently
937e3adcf8fSFrançois Tigeot 	 * incoherent with writes to memory, i.e. completely fubar,
938e3adcf8fSFrançois Tigeot 	 * so we need to use PIPE_NOTIFY instead.
939e3adcf8fSFrançois Tigeot 	 *
940e3adcf8fSFrançois Tigeot 	 * However, we also need to workaround the qword write
941e3adcf8fSFrançois Tigeot 	 * incoherence by flushing the 6 PIPE_NOTIFY buffers out to
942e3adcf8fSFrançois Tigeot 	 * memory before requesting an interrupt.
943e3adcf8fSFrançois Tigeot 	 */
944e3adcf8fSFrançois Tigeot 	ret = intel_ring_begin(ring, 32);
945e3adcf8fSFrançois Tigeot 	if (ret)
946e3adcf8fSFrançois Tigeot 		return ret;
947e3adcf8fSFrançois Tigeot 
948e3adcf8fSFrançois Tigeot 	intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(4) | PIPE_CONTROL_QW_WRITE |
949e3adcf8fSFrançois Tigeot 			PIPE_CONTROL_WRITE_FLUSH |
950e3adcf8fSFrançois Tigeot 			PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE);
9519edbd4a0SFrançois Tigeot 	intel_ring_emit(ring, ring->scratch.gtt_offset | PIPE_CONTROL_GLOBAL_GTT);
9529edbd4a0SFrançois Tigeot 	intel_ring_emit(ring, ring->outstanding_lazy_seqno);
953e3adcf8fSFrançois Tigeot 	intel_ring_emit(ring, 0);
954e3adcf8fSFrançois Tigeot 	PIPE_CONTROL_FLUSH(ring, scratch_addr);
955ba55f2f5SFrançois Tigeot 	scratch_addr += 2 * CACHELINE_BYTES; /* write to separate cachelines */
956e3adcf8fSFrançois Tigeot 	PIPE_CONTROL_FLUSH(ring, scratch_addr);
957ba55f2f5SFrançois Tigeot 	scratch_addr += 2 * CACHELINE_BYTES;
958e3adcf8fSFrançois Tigeot 	PIPE_CONTROL_FLUSH(ring, scratch_addr);
959ba55f2f5SFrançois Tigeot 	scratch_addr += 2 * CACHELINE_BYTES;
960e3adcf8fSFrançois Tigeot 	PIPE_CONTROL_FLUSH(ring, scratch_addr);
961ba55f2f5SFrançois Tigeot 	scratch_addr += 2 * CACHELINE_BYTES;
962e3adcf8fSFrançois Tigeot 	PIPE_CONTROL_FLUSH(ring, scratch_addr);
963ba55f2f5SFrançois Tigeot 	scratch_addr += 2 * CACHELINE_BYTES;
964e3adcf8fSFrançois Tigeot 	PIPE_CONTROL_FLUSH(ring, scratch_addr);
965b5c29a34SFrançois Tigeot 
966e3adcf8fSFrançois Tigeot 	intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(4) | PIPE_CONTROL_QW_WRITE |
967e3adcf8fSFrançois Tigeot 			PIPE_CONTROL_WRITE_FLUSH |
968e3adcf8fSFrançois Tigeot 			PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE |
969e3adcf8fSFrançois Tigeot 			PIPE_CONTROL_NOTIFY);
9709edbd4a0SFrançois Tigeot 	intel_ring_emit(ring, ring->scratch.gtt_offset | PIPE_CONTROL_GLOBAL_GTT);
9719edbd4a0SFrançois Tigeot 	intel_ring_emit(ring, ring->outstanding_lazy_seqno);
972e3adcf8fSFrançois Tigeot 	intel_ring_emit(ring, 0);
9739edbd4a0SFrançois Tigeot 	__intel_ring_advance(ring);
974e3adcf8fSFrançois Tigeot 
975e3adcf8fSFrançois Tigeot 	return 0;
976e3adcf8fSFrançois Tigeot }
977e3adcf8fSFrançois Tigeot 
978e3adcf8fSFrançois Tigeot static u32
979ba55f2f5SFrançois Tigeot gen6_ring_get_seqno(struct intel_engine_cs *ring, bool lazy_coherency)
980e3adcf8fSFrançois Tigeot {
981e3adcf8fSFrançois Tigeot 	/* Workaround to force correct ordering between irq and seqno writes on
982e3adcf8fSFrançois Tigeot 	 * ivb (and maybe also on snb) by reading from a CS register (like
983e3adcf8fSFrançois Tigeot 	 * ACTHD) before reading the status page. */
984ba55f2f5SFrançois Tigeot 	if (!lazy_coherency) {
985ba55f2f5SFrançois Tigeot 		struct drm_i915_private *dev_priv = ring->dev->dev_private;
986ba55f2f5SFrançois Tigeot 		POSTING_READ(RING_ACTHD(ring->mmio_base));
987ba55f2f5SFrançois Tigeot 	}
988ba55f2f5SFrançois Tigeot 
989e3adcf8fSFrançois Tigeot 	return intel_read_status_page(ring, I915_GEM_HWS_INDEX);
990e3adcf8fSFrançois Tigeot }
991e3adcf8fSFrançois Tigeot 
992b030f26bSFrançois Tigeot static u32
993ba55f2f5SFrançois Tigeot ring_get_seqno(struct intel_engine_cs *ring, bool lazy_coherency)
994e3adcf8fSFrançois Tigeot {
995e3adcf8fSFrançois Tigeot 	return intel_read_status_page(ring, I915_GEM_HWS_INDEX);
996e3adcf8fSFrançois Tigeot }
997e3adcf8fSFrançois Tigeot 
998a2fdbec6SFrançois Tigeot static void
999ba55f2f5SFrançois Tigeot ring_set_seqno(struct intel_engine_cs *ring, u32 seqno)
1000a2fdbec6SFrançois Tigeot {
1001a2fdbec6SFrançois Tigeot 	intel_write_status_page(ring, I915_GEM_HWS_INDEX, seqno);
1002a2fdbec6SFrançois Tigeot }
1003a2fdbec6SFrançois Tigeot 
1004b030f26bSFrançois Tigeot static u32
1005ba55f2f5SFrançois Tigeot pc_render_get_seqno(struct intel_engine_cs *ring, bool lazy_coherency)
1006e3adcf8fSFrançois Tigeot {
10079edbd4a0SFrançois Tigeot 	return ring->scratch.cpu_page[0];
1008e3adcf8fSFrançois Tigeot }
1009e3adcf8fSFrançois Tigeot 
1010a2fdbec6SFrançois Tigeot static void
1011ba55f2f5SFrançois Tigeot pc_render_set_seqno(struct intel_engine_cs *ring, u32 seqno)
1012a2fdbec6SFrançois Tigeot {
10139edbd4a0SFrançois Tigeot 	ring->scratch.cpu_page[0] = seqno;
1014a2fdbec6SFrançois Tigeot }
1015a2fdbec6SFrançois Tigeot 
1016e3adcf8fSFrançois Tigeot static bool
1017ba55f2f5SFrançois Tigeot gen5_ring_get_irq(struct intel_engine_cs *ring)
1018e3adcf8fSFrançois Tigeot {
1019e3adcf8fSFrançois Tigeot 	struct drm_device *dev = ring->dev;
1020ba55f2f5SFrançois Tigeot 	struct drm_i915_private *dev_priv = dev->dev_private;
1021e3adcf8fSFrançois Tigeot 
1022e3adcf8fSFrançois Tigeot 	if (!dev->irq_enabled)
1023e3adcf8fSFrançois Tigeot 		return false;
1024e3adcf8fSFrançois Tigeot 
102502727ecdSFrançois Tigeot 	lockmgr(&dev_priv->irq_lock, LK_EXCLUSIVE);
10269edbd4a0SFrançois Tigeot 	if (ring->irq_refcount++ == 0)
1027*24edb884SFrançois Tigeot 		gen5_enable_gt_irq(dev_priv, ring->irq_enable_mask);
102802727ecdSFrançois Tigeot 	lockmgr(&dev_priv->irq_lock, LK_RELEASE);
1029e3adcf8fSFrançois Tigeot 
1030e3adcf8fSFrançois Tigeot 	return true;
1031e3adcf8fSFrançois Tigeot }
1032e3adcf8fSFrançois Tigeot 
1033e3adcf8fSFrançois Tigeot static void
1034ba55f2f5SFrançois Tigeot gen5_ring_put_irq(struct intel_engine_cs *ring)
1035e3adcf8fSFrançois Tigeot {
1036e3adcf8fSFrançois Tigeot 	struct drm_device *dev = ring->dev;
1037ba55f2f5SFrançois Tigeot 	struct drm_i915_private *dev_priv = dev->dev_private;
1038e3adcf8fSFrançois Tigeot 
103902727ecdSFrançois Tigeot 	lockmgr(&dev_priv->irq_lock, LK_EXCLUSIVE);
10409edbd4a0SFrançois Tigeot 	if (--ring->irq_refcount == 0)
1041*24edb884SFrançois Tigeot 		gen5_disable_gt_irq(dev_priv, ring->irq_enable_mask);
1042686a02f1SFrançois Tigeot 	lockmgr(&dev_priv->irq_lock, LK_RELEASE);
1043686a02f1SFrançois Tigeot }
1044686a02f1SFrançois Tigeot 
1045686a02f1SFrançois Tigeot static bool
1046ba55f2f5SFrançois Tigeot i9xx_ring_get_irq(struct intel_engine_cs *ring)
1047686a02f1SFrançois Tigeot {
1048686a02f1SFrançois Tigeot 	struct drm_device *dev = ring->dev;
1049ba55f2f5SFrançois Tigeot 	struct drm_i915_private *dev_priv = dev->dev_private;
1050686a02f1SFrançois Tigeot 
1051686a02f1SFrançois Tigeot 	if (!dev->irq_enabled)
1052686a02f1SFrançois Tigeot 		return false;
1053686a02f1SFrançois Tigeot 
1054686a02f1SFrançois Tigeot 	lockmgr(&dev_priv->irq_lock, LK_EXCLUSIVE);
10559edbd4a0SFrançois Tigeot 	if (ring->irq_refcount++ == 0) {
1056686a02f1SFrançois Tigeot 		dev_priv->irq_mask &= ~ring->irq_enable_mask;
1057686a02f1SFrançois Tigeot 		I915_WRITE(IMR, dev_priv->irq_mask);
1058686a02f1SFrançois Tigeot 		POSTING_READ(IMR);
1059686a02f1SFrançois Tigeot 	}
1060686a02f1SFrançois Tigeot 	lockmgr(&dev_priv->irq_lock, LK_RELEASE);
1061686a02f1SFrançois Tigeot 
1062686a02f1SFrançois Tigeot 	return true;
1063686a02f1SFrançois Tigeot }
1064686a02f1SFrançois Tigeot 
1065686a02f1SFrançois Tigeot static void
1066ba55f2f5SFrançois Tigeot i9xx_ring_put_irq(struct intel_engine_cs *ring)
1067686a02f1SFrançois Tigeot {
1068686a02f1SFrançois Tigeot 	struct drm_device *dev = ring->dev;
1069ba55f2f5SFrançois Tigeot 	struct drm_i915_private *dev_priv = dev->dev_private;
1070686a02f1SFrançois Tigeot 
1071686a02f1SFrançois Tigeot 	lockmgr(&dev_priv->irq_lock, LK_EXCLUSIVE);
10729edbd4a0SFrançois Tigeot 	if (--ring->irq_refcount == 0) {
1073686a02f1SFrançois Tigeot 		dev_priv->irq_mask |= ring->irq_enable_mask;
1074686a02f1SFrançois Tigeot 		I915_WRITE(IMR, dev_priv->irq_mask);
1075686a02f1SFrançois Tigeot 		POSTING_READ(IMR);
1076686a02f1SFrançois Tigeot 	}
1077686a02f1SFrançois Tigeot 	lockmgr(&dev_priv->irq_lock, LK_RELEASE);
1078686a02f1SFrançois Tigeot }
1079686a02f1SFrançois Tigeot 
1080686a02f1SFrançois Tigeot static bool
1081ba55f2f5SFrançois Tigeot i8xx_ring_get_irq(struct intel_engine_cs *ring)
1082686a02f1SFrançois Tigeot {
1083686a02f1SFrançois Tigeot 	struct drm_device *dev = ring->dev;
1084ba55f2f5SFrançois Tigeot 	struct drm_i915_private *dev_priv = dev->dev_private;
1085686a02f1SFrançois Tigeot 
1086686a02f1SFrançois Tigeot 	if (!dev->irq_enabled)
1087686a02f1SFrançois Tigeot 		return false;
1088686a02f1SFrançois Tigeot 
1089686a02f1SFrançois Tigeot 	lockmgr(&dev_priv->irq_lock, LK_EXCLUSIVE);
10909edbd4a0SFrançois Tigeot 	if (ring->irq_refcount++ == 0) {
1091686a02f1SFrançois Tigeot 		dev_priv->irq_mask &= ~ring->irq_enable_mask;
1092686a02f1SFrançois Tigeot 		I915_WRITE16(IMR, dev_priv->irq_mask);
1093686a02f1SFrançois Tigeot 		POSTING_READ16(IMR);
1094686a02f1SFrançois Tigeot 	}
1095686a02f1SFrançois Tigeot 	lockmgr(&dev_priv->irq_lock, LK_RELEASE);
1096686a02f1SFrançois Tigeot 
1097686a02f1SFrançois Tigeot 	return true;
1098686a02f1SFrançois Tigeot }
1099686a02f1SFrançois Tigeot 
1100686a02f1SFrançois Tigeot static void
1101ba55f2f5SFrançois Tigeot i8xx_ring_put_irq(struct intel_engine_cs *ring)
1102686a02f1SFrançois Tigeot {
1103686a02f1SFrançois Tigeot 	struct drm_device *dev = ring->dev;
1104ba55f2f5SFrançois Tigeot 	struct drm_i915_private *dev_priv = dev->dev_private;
1105686a02f1SFrançois Tigeot 
1106686a02f1SFrançois Tigeot 	lockmgr(&dev_priv->irq_lock, LK_EXCLUSIVE);
11079edbd4a0SFrançois Tigeot 	if (--ring->irq_refcount == 0) {
1108686a02f1SFrançois Tigeot 		dev_priv->irq_mask |= ring->irq_enable_mask;
1109686a02f1SFrançois Tigeot 		I915_WRITE16(IMR, dev_priv->irq_mask);
1110686a02f1SFrançois Tigeot 		POSTING_READ16(IMR);
1111e3adcf8fSFrançois Tigeot 	}
111202727ecdSFrançois Tigeot 	lockmgr(&dev_priv->irq_lock, LK_RELEASE);
1113e3adcf8fSFrançois Tigeot }
1114e3adcf8fSFrançois Tigeot 
1115ba55f2f5SFrançois Tigeot void intel_ring_setup_status_page(struct intel_engine_cs *ring)
1116e3adcf8fSFrançois Tigeot {
1117e3adcf8fSFrançois Tigeot 	struct drm_device *dev = ring->dev;
1118ba55f2f5SFrançois Tigeot 	struct drm_i915_private *dev_priv = ring->dev->dev_private;
1119b5c29a34SFrançois Tigeot 	u32 mmio = 0;
1120e3adcf8fSFrançois Tigeot 
1121e3adcf8fSFrançois Tigeot 	/* The ring status page addresses are no longer next to the rest of
1122e3adcf8fSFrançois Tigeot 	 * the ring registers as of gen7.
1123e3adcf8fSFrançois Tigeot 	 */
1124e3adcf8fSFrançois Tigeot 	if (IS_GEN7(dev)) {
1125e3adcf8fSFrançois Tigeot 		switch (ring->id) {
1126e3adcf8fSFrançois Tigeot 		case RCS:
1127e3adcf8fSFrançois Tigeot 			mmio = RENDER_HWS_PGA_GEN7;
1128e3adcf8fSFrançois Tigeot 			break;
1129e3adcf8fSFrançois Tigeot 		case BCS:
1130e3adcf8fSFrançois Tigeot 			mmio = BLT_HWS_PGA_GEN7;
1131e3adcf8fSFrançois Tigeot 			break;
1132ba55f2f5SFrançois Tigeot 		/*
1133ba55f2f5SFrançois Tigeot 		 * VCS2 actually doesn't exist on Gen7. Only shut up
1134ba55f2f5SFrançois Tigeot 		 * gcc switch check warning
1135ba55f2f5SFrançois Tigeot 		 */
1136ba55f2f5SFrançois Tigeot 		case VCS2:
1137e3adcf8fSFrançois Tigeot 		case VCS:
1138e3adcf8fSFrançois Tigeot 			mmio = BSD_HWS_PGA_GEN7;
1139e3adcf8fSFrançois Tigeot 			break;
11405d0b1887SFrançois Tigeot 		case VECS:
11415d0b1887SFrançois Tigeot 			mmio = VEBOX_HWS_PGA_GEN7;
11425d0b1887SFrançois Tigeot 			break;
1143e3adcf8fSFrançois Tigeot 		}
1144b5c29a34SFrançois Tigeot 	} else if (IS_GEN6(ring->dev)) {
1145e3adcf8fSFrançois Tigeot 		mmio = RING_HWS_PGA_GEN6(ring->mmio_base);
1146e3adcf8fSFrançois Tigeot 	} else {
11479edbd4a0SFrançois Tigeot 		/* XXX: gen8 returns to sanity */
1148e3adcf8fSFrançois Tigeot 		mmio = RING_HWS_PGA(ring->mmio_base);
1149e3adcf8fSFrançois Tigeot 	}
1150e3adcf8fSFrançois Tigeot 
1151e3adcf8fSFrançois Tigeot 	I915_WRITE(mmio, (u32)ring->status_page.gfx_addr);
1152e3adcf8fSFrançois Tigeot 	POSTING_READ(mmio);
11535d0b1887SFrançois Tigeot 
1154ba55f2f5SFrançois Tigeot 	/*
1155ba55f2f5SFrançois Tigeot 	 * Flush the TLB for this page
1156ba55f2f5SFrançois Tigeot 	 *
1157ba55f2f5SFrançois Tigeot 	 * FIXME: These two bits have disappeared on gen8, so a question
1158ba55f2f5SFrançois Tigeot 	 * arises: do we still need this and if so how should we go about
1159ba55f2f5SFrançois Tigeot 	 * invalidating the TLB?
1160ba55f2f5SFrançois Tigeot 	 */
1161ba55f2f5SFrançois Tigeot 	if (INTEL_INFO(dev)->gen >= 6 && INTEL_INFO(dev)->gen < 8) {
11625d0b1887SFrançois Tigeot 		u32 reg = RING_INSTPM(ring->mmio_base);
1163ba55f2f5SFrançois Tigeot 
1164ba55f2f5SFrançois Tigeot 		/* ring should be idle before issuing a sync flush*/
1165ba55f2f5SFrançois Tigeot 		WARN_ON((I915_READ_MODE(ring) & MODE_IDLE) == 0);
1166ba55f2f5SFrançois Tigeot 
11675d0b1887SFrançois Tigeot 		I915_WRITE(reg,
11685d0b1887SFrançois Tigeot 			   _MASKED_BIT_ENABLE(INSTPM_TLB_INVALIDATE |
11695d0b1887SFrançois Tigeot 					      INSTPM_SYNC_FLUSH));
11705d0b1887SFrançois Tigeot 		if (wait_for((I915_READ(reg) & INSTPM_SYNC_FLUSH) == 0,
11715d0b1887SFrançois Tigeot 			     1000))
11725d0b1887SFrançois Tigeot 			DRM_ERROR("%s: wait for SyncFlush to complete for TLB invalidation timed out\n",
11735d0b1887SFrançois Tigeot 				  ring->name);
11745d0b1887SFrançois Tigeot 	}
1175e3adcf8fSFrançois Tigeot }
1176e3adcf8fSFrançois Tigeot 
1177e3adcf8fSFrançois Tigeot static int
1178ba55f2f5SFrançois Tigeot bsd_ring_flush(struct intel_engine_cs *ring,
1179b5c29a34SFrançois Tigeot 	       u32     invalidate_domains,
1180b5c29a34SFrançois Tigeot 	       u32     flush_domains)
1181e3adcf8fSFrançois Tigeot {
1182e3adcf8fSFrançois Tigeot 	int ret;
1183e3adcf8fSFrançois Tigeot 
1184e3adcf8fSFrançois Tigeot 	ret = intel_ring_begin(ring, 2);
1185e3adcf8fSFrançois Tigeot 	if (ret)
1186e3adcf8fSFrançois Tigeot 		return ret;
1187e3adcf8fSFrançois Tigeot 
1188e3adcf8fSFrançois Tigeot 	intel_ring_emit(ring, MI_FLUSH);
1189e3adcf8fSFrançois Tigeot 	intel_ring_emit(ring, MI_NOOP);
1190e3adcf8fSFrançois Tigeot 	intel_ring_advance(ring);
1191e3adcf8fSFrançois Tigeot 	return 0;
1192e3adcf8fSFrançois Tigeot }
1193e3adcf8fSFrançois Tigeot 
1194e3adcf8fSFrançois Tigeot static int
1195ba55f2f5SFrançois Tigeot i9xx_add_request(struct intel_engine_cs *ring)
1196e3adcf8fSFrançois Tigeot {
1197e3adcf8fSFrançois Tigeot 	int ret;
1198e3adcf8fSFrançois Tigeot 
1199e3adcf8fSFrançois Tigeot 	ret = intel_ring_begin(ring, 4);
1200e3adcf8fSFrançois Tigeot 	if (ret)
1201e3adcf8fSFrançois Tigeot 		return ret;
1202e3adcf8fSFrançois Tigeot 
1203e3adcf8fSFrançois Tigeot 	intel_ring_emit(ring, MI_STORE_DWORD_INDEX);
1204e3adcf8fSFrançois Tigeot 	intel_ring_emit(ring, I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT);
12059edbd4a0SFrançois Tigeot 	intel_ring_emit(ring, ring->outstanding_lazy_seqno);
1206e3adcf8fSFrançois Tigeot 	intel_ring_emit(ring, MI_USER_INTERRUPT);
12079edbd4a0SFrançois Tigeot 	__intel_ring_advance(ring);
1208e3adcf8fSFrançois Tigeot 
1209e3adcf8fSFrançois Tigeot 	return 0;
1210e3adcf8fSFrançois Tigeot }
1211e3adcf8fSFrançois Tigeot 
1212e3adcf8fSFrançois Tigeot static bool
1213ba55f2f5SFrançois Tigeot gen6_ring_get_irq(struct intel_engine_cs *ring)
1214e3adcf8fSFrançois Tigeot {
1215e3adcf8fSFrançois Tigeot 	struct drm_device *dev = ring->dev;
1216ba55f2f5SFrançois Tigeot 	struct drm_i915_private *dev_priv = dev->dev_private;
1217e3adcf8fSFrançois Tigeot 
1218e3adcf8fSFrançois Tigeot 	if (!dev->irq_enabled)
1219e3adcf8fSFrançois Tigeot 	       return false;
1220e3adcf8fSFrançois Tigeot 
122102727ecdSFrançois Tigeot 	lockmgr(&dev_priv->irq_lock, LK_EXCLUSIVE);
12229edbd4a0SFrançois Tigeot 	if (ring->irq_refcount++ == 0) {
12239edbd4a0SFrançois Tigeot 		if (HAS_L3_DPF(dev) && ring->id == RCS)
12245d0b1887SFrançois Tigeot 			I915_WRITE_IMR(ring,
12255d0b1887SFrançois Tigeot 				       ~(ring->irq_enable_mask |
12269edbd4a0SFrançois Tigeot 					 GT_PARITY_ERROR(dev)));
1227686a02f1SFrançois Tigeot 		else
1228686a02f1SFrançois Tigeot 			I915_WRITE_IMR(ring, ~ring->irq_enable_mask);
1229*24edb884SFrançois Tigeot 		gen5_enable_gt_irq(dev_priv, ring->irq_enable_mask);
1230e3adcf8fSFrançois Tigeot 	}
123102727ecdSFrançois Tigeot 	lockmgr(&dev_priv->irq_lock, LK_RELEASE);
1232e3adcf8fSFrançois Tigeot 
1233e3adcf8fSFrançois Tigeot 	return true;
1234e3adcf8fSFrançois Tigeot }
1235e3adcf8fSFrançois Tigeot 
1236e3adcf8fSFrançois Tigeot static void
1237ba55f2f5SFrançois Tigeot gen6_ring_put_irq(struct intel_engine_cs *ring)
1238e3adcf8fSFrançois Tigeot {
1239e3adcf8fSFrançois Tigeot 	struct drm_device *dev = ring->dev;
1240ba55f2f5SFrançois Tigeot 	struct drm_i915_private *dev_priv = dev->dev_private;
1241e3adcf8fSFrançois Tigeot 
124202727ecdSFrançois Tigeot 	lockmgr(&dev_priv->irq_lock, LK_EXCLUSIVE);
12439edbd4a0SFrançois Tigeot 	if (--ring->irq_refcount == 0) {
12449edbd4a0SFrançois Tigeot 		if (HAS_L3_DPF(dev) && ring->id == RCS)
12459edbd4a0SFrançois Tigeot 			I915_WRITE_IMR(ring, ~GT_PARITY_ERROR(dev));
1246686a02f1SFrançois Tigeot 		else
1247686a02f1SFrançois Tigeot 			I915_WRITE_IMR(ring, ~0);
1248*24edb884SFrançois Tigeot 		gen5_disable_gt_irq(dev_priv, ring->irq_enable_mask);
1249e3adcf8fSFrançois Tigeot 	}
125002727ecdSFrançois Tigeot 	lockmgr(&dev_priv->irq_lock, LK_RELEASE);
1251e3adcf8fSFrançois Tigeot }
1252e3adcf8fSFrançois Tigeot 
12535d0b1887SFrançois Tigeot static bool
1254ba55f2f5SFrançois Tigeot hsw_vebox_get_irq(struct intel_engine_cs *ring)
12555d0b1887SFrançois Tigeot {
12565d0b1887SFrançois Tigeot 	struct drm_device *dev = ring->dev;
12575d0b1887SFrançois Tigeot 	struct drm_i915_private *dev_priv = dev->dev_private;
12585d0b1887SFrançois Tigeot 
12595d0b1887SFrançois Tigeot 	if (!dev->irq_enabled)
12605d0b1887SFrançois Tigeot 		return false;
12615d0b1887SFrançois Tigeot 
12629edbd4a0SFrançois Tigeot 	lockmgr(&dev_priv->irq_lock, LK_EXCLUSIVE);
12639edbd4a0SFrançois Tigeot 	if (ring->irq_refcount++ == 0) {
12645d0b1887SFrançois Tigeot 		I915_WRITE_IMR(ring, ~ring->irq_enable_mask);
1265*24edb884SFrançois Tigeot 		gen6_enable_pm_irq(dev_priv, ring->irq_enable_mask);
12665d0b1887SFrançois Tigeot 	}
12679edbd4a0SFrançois Tigeot 	lockmgr(&dev_priv->irq_lock, LK_RELEASE);
12685d0b1887SFrançois Tigeot 
12695d0b1887SFrançois Tigeot 	return true;
12705d0b1887SFrançois Tigeot }
12715d0b1887SFrançois Tigeot 
12725d0b1887SFrançois Tigeot static void
1273ba55f2f5SFrançois Tigeot hsw_vebox_put_irq(struct intel_engine_cs *ring)
12745d0b1887SFrançois Tigeot {
12755d0b1887SFrançois Tigeot 	struct drm_device *dev = ring->dev;
12765d0b1887SFrançois Tigeot 	struct drm_i915_private *dev_priv = dev->dev_private;
12775d0b1887SFrançois Tigeot 
12785d0b1887SFrançois Tigeot 	if (!dev->irq_enabled)
12795d0b1887SFrançois Tigeot 		return;
12805d0b1887SFrançois Tigeot 
12819edbd4a0SFrançois Tigeot 	lockmgr(&dev_priv->irq_lock, LK_EXCLUSIVE);
12829edbd4a0SFrançois Tigeot 	if (--ring->irq_refcount == 0) {
12835d0b1887SFrançois Tigeot 		I915_WRITE_IMR(ring, ~0);
1284*24edb884SFrançois Tigeot 		gen6_disable_pm_irq(dev_priv, ring->irq_enable_mask);
12855d0b1887SFrançois Tigeot 	}
12869edbd4a0SFrançois Tigeot 	lockmgr(&dev_priv->irq_lock, LK_RELEASE);
12879edbd4a0SFrançois Tigeot }
12889edbd4a0SFrançois Tigeot 
12899edbd4a0SFrançois Tigeot static bool
1290ba55f2f5SFrançois Tigeot gen8_ring_get_irq(struct intel_engine_cs *ring)
12919edbd4a0SFrançois Tigeot {
12929edbd4a0SFrançois Tigeot 	struct drm_device *dev = ring->dev;
12939edbd4a0SFrançois Tigeot 	struct drm_i915_private *dev_priv = dev->dev_private;
12949edbd4a0SFrançois Tigeot 
12959edbd4a0SFrançois Tigeot 	if (!dev->irq_enabled)
12969edbd4a0SFrançois Tigeot 		return false;
12979edbd4a0SFrançois Tigeot 
12989edbd4a0SFrançois Tigeot 	lockmgr(&dev_priv->irq_lock, LK_EXCLUSIVE);
12999edbd4a0SFrançois Tigeot 	if (ring->irq_refcount++ == 0) {
13009edbd4a0SFrançois Tigeot 		if (HAS_L3_DPF(dev) && ring->id == RCS) {
13019edbd4a0SFrançois Tigeot 			I915_WRITE_IMR(ring,
13029edbd4a0SFrançois Tigeot 				       ~(ring->irq_enable_mask |
13039edbd4a0SFrançois Tigeot 					 GT_RENDER_L3_PARITY_ERROR_INTERRUPT));
13049edbd4a0SFrançois Tigeot 		} else {
13059edbd4a0SFrançois Tigeot 			I915_WRITE_IMR(ring, ~ring->irq_enable_mask);
13069edbd4a0SFrançois Tigeot 		}
13079edbd4a0SFrançois Tigeot 		POSTING_READ(RING_IMR(ring->mmio_base));
13089edbd4a0SFrançois Tigeot 	}
13099edbd4a0SFrançois Tigeot 	lockmgr(&dev_priv->irq_lock, LK_RELEASE);
13109edbd4a0SFrançois Tigeot 
13119edbd4a0SFrançois Tigeot 	return true;
13129edbd4a0SFrançois Tigeot }
13139edbd4a0SFrançois Tigeot 
13149edbd4a0SFrançois Tigeot static void
1315ba55f2f5SFrançois Tigeot gen8_ring_put_irq(struct intel_engine_cs *ring)
13169edbd4a0SFrançois Tigeot {
13179edbd4a0SFrançois Tigeot 	struct drm_device *dev = ring->dev;
13189edbd4a0SFrançois Tigeot 	struct drm_i915_private *dev_priv = dev->dev_private;
13199edbd4a0SFrançois Tigeot 
13209edbd4a0SFrançois Tigeot 	lockmgr(&dev_priv->irq_lock, LK_EXCLUSIVE);
13219edbd4a0SFrançois Tigeot 	if (--ring->irq_refcount == 0) {
13229edbd4a0SFrançois Tigeot 		if (HAS_L3_DPF(dev) && ring->id == RCS) {
13239edbd4a0SFrançois Tigeot 			I915_WRITE_IMR(ring,
13249edbd4a0SFrançois Tigeot 				       ~GT_RENDER_L3_PARITY_ERROR_INTERRUPT);
13259edbd4a0SFrançois Tigeot 		} else {
13269edbd4a0SFrançois Tigeot 			I915_WRITE_IMR(ring, ~0);
13279edbd4a0SFrançois Tigeot 		}
13289edbd4a0SFrançois Tigeot 		POSTING_READ(RING_IMR(ring->mmio_base));
13299edbd4a0SFrançois Tigeot 	}
13309edbd4a0SFrançois Tigeot 	lockmgr(&dev_priv->irq_lock, LK_RELEASE);
13315d0b1887SFrançois Tigeot }
13325d0b1887SFrançois Tigeot 
1333e3adcf8fSFrançois Tigeot static int
1334ba55f2f5SFrançois Tigeot i965_dispatch_execbuffer(struct intel_engine_cs *ring,
1335ba55f2f5SFrançois Tigeot 			 u64 offset, u32 length,
1336b5c29a34SFrançois Tigeot 			 unsigned flags)
1337e3adcf8fSFrançois Tigeot {
1338e3adcf8fSFrançois Tigeot 	int ret;
1339e3adcf8fSFrançois Tigeot 
1340e3adcf8fSFrançois Tigeot 	ret = intel_ring_begin(ring, 2);
1341e3adcf8fSFrançois Tigeot 	if (ret)
1342e3adcf8fSFrançois Tigeot 		return ret;
1343e3adcf8fSFrançois Tigeot 
1344e3adcf8fSFrançois Tigeot 	intel_ring_emit(ring,
1345686a02f1SFrançois Tigeot 			MI_BATCH_BUFFER_START |
1346b5c29a34SFrançois Tigeot 			MI_BATCH_GTT |
1347b5c29a34SFrançois Tigeot 			(flags & I915_DISPATCH_SECURE ? 0 : MI_BATCH_NON_SECURE_I965));
1348e3adcf8fSFrançois Tigeot 	intel_ring_emit(ring, offset);
1349e3adcf8fSFrançois Tigeot 	intel_ring_advance(ring);
1350e3adcf8fSFrançois Tigeot 
1351e3adcf8fSFrançois Tigeot 	return 0;
1352e3adcf8fSFrançois Tigeot }
1353e3adcf8fSFrançois Tigeot 
1354b5c29a34SFrançois Tigeot /* Just userspace ABI convention to limit the wa batch bo to a resonable size */
1355b5c29a34SFrançois Tigeot #define I830_BATCH_LIMIT (256*1024)
1356*24edb884SFrançois Tigeot #define I830_TLB_ENTRIES (2)
1357*24edb884SFrançois Tigeot #define I830_WA_SIZE max(I830_TLB_ENTRIES*4096, I830_BATCH_LIMIT)
1358e3adcf8fSFrançois Tigeot static int
1359ba55f2f5SFrançois Tigeot i830_dispatch_execbuffer(struct intel_engine_cs *ring,
1360ba55f2f5SFrançois Tigeot 				u64 offset, u32 len,
1361b5c29a34SFrançois Tigeot 				unsigned flags)
1362e3adcf8fSFrançois Tigeot {
1363*24edb884SFrançois Tigeot 	u32 cs_offset = ring->scratch.gtt_offset;
1364e3adcf8fSFrançois Tigeot 	int ret;
1365e3adcf8fSFrançois Tigeot 
1366*24edb884SFrançois Tigeot 	ret = intel_ring_begin(ring, 6);
1367*24edb884SFrançois Tigeot 	if (ret)
1368*24edb884SFrançois Tigeot 		return ret;
1369*24edb884SFrançois Tigeot 
1370*24edb884SFrançois Tigeot 	/* Evict the invalid PTE TLBs */
1371*24edb884SFrançois Tigeot 	intel_ring_emit(ring, COLOR_BLT_CMD | BLT_WRITE_RGBA);
1372*24edb884SFrançois Tigeot 	intel_ring_emit(ring, BLT_DEPTH_32 | BLT_ROP_COLOR_COPY | 4096);
1373*24edb884SFrançois Tigeot 	intel_ring_emit(ring, I830_TLB_ENTRIES << 16 | 4); /* load each page */
1374*24edb884SFrançois Tigeot 	intel_ring_emit(ring, cs_offset);
1375*24edb884SFrançois Tigeot 	intel_ring_emit(ring, 0xdeadbeef);
1376*24edb884SFrançois Tigeot 	intel_ring_emit(ring, MI_NOOP);
1377*24edb884SFrançois Tigeot 	intel_ring_advance(ring);
1378*24edb884SFrançois Tigeot 
1379*24edb884SFrançois Tigeot 	if ((flags & I915_DISPATCH_PINNED) == 0) {
1380*24edb884SFrançois Tigeot 		if (len > I830_BATCH_LIMIT)
1381*24edb884SFrançois Tigeot 			return -ENOSPC;
1382*24edb884SFrançois Tigeot 
1383*24edb884SFrançois Tigeot 		ret = intel_ring_begin(ring, 6 + 2);
1384*24edb884SFrançois Tigeot 		if (ret)
1385*24edb884SFrançois Tigeot 			return ret;
1386*24edb884SFrançois Tigeot 
1387*24edb884SFrançois Tigeot 		/* Blit the batch (which has now all relocs applied) to the
1388*24edb884SFrançois Tigeot 		 * stable batch scratch bo area (so that the CS never
1389*24edb884SFrançois Tigeot 		 * stumbles over its tlb invalidation bug) ...
1390*24edb884SFrançois Tigeot 		 */
1391*24edb884SFrançois Tigeot 		intel_ring_emit(ring, SRC_COPY_BLT_CMD | BLT_WRITE_RGBA);
1392*24edb884SFrançois Tigeot 		intel_ring_emit(ring, BLT_DEPTH_32 | BLT_ROP_SRC_COPY | 4096);
1393*24edb884SFrançois Tigeot 		intel_ring_emit(ring, DIV_ROUND_UP(len, 4096) << 16 | 4096);
1394*24edb884SFrançois Tigeot 		intel_ring_emit(ring, cs_offset);
1395*24edb884SFrançois Tigeot 		intel_ring_emit(ring, 4096);
1396*24edb884SFrançois Tigeot 		intel_ring_emit(ring, offset);
1397*24edb884SFrançois Tigeot 
1398*24edb884SFrançois Tigeot 		intel_ring_emit(ring, MI_FLUSH);
1399*24edb884SFrançois Tigeot 		intel_ring_emit(ring, MI_NOOP);
1400*24edb884SFrançois Tigeot 		intel_ring_advance(ring);
1401*24edb884SFrançois Tigeot 
1402*24edb884SFrançois Tigeot 		/* ... and execute it. */
1403*24edb884SFrançois Tigeot 		offset = cs_offset;
1404*24edb884SFrançois Tigeot 	}
1405*24edb884SFrançois Tigeot 
1406e3adcf8fSFrançois Tigeot 	ret = intel_ring_begin(ring, 4);
1407e3adcf8fSFrançois Tigeot 	if (ret)
1408e3adcf8fSFrançois Tigeot 		return ret;
1409e3adcf8fSFrançois Tigeot 
1410e3adcf8fSFrançois Tigeot 	intel_ring_emit(ring, MI_BATCH_BUFFER);
1411b5c29a34SFrançois Tigeot 	intel_ring_emit(ring, offset | (flags & I915_DISPATCH_SECURE ? 0 : MI_BATCH_NON_SECURE));
1412e3adcf8fSFrançois Tigeot 	intel_ring_emit(ring, offset + len - 8);
1413b5c29a34SFrançois Tigeot 	intel_ring_emit(ring, MI_NOOP);
1414686a02f1SFrançois Tigeot 	intel_ring_advance(ring);
1415686a02f1SFrançois Tigeot 
1416686a02f1SFrançois Tigeot 	return 0;
1417686a02f1SFrançois Tigeot }
1418686a02f1SFrançois Tigeot 
1419686a02f1SFrançois Tigeot static int
1420ba55f2f5SFrançois Tigeot i915_dispatch_execbuffer(struct intel_engine_cs *ring,
1421ba55f2f5SFrançois Tigeot 			 u64 offset, u32 len,
1422b5c29a34SFrançois Tigeot 			 unsigned flags)
1423686a02f1SFrançois Tigeot {
1424686a02f1SFrançois Tigeot 	int ret;
1425686a02f1SFrançois Tigeot 
1426e3adcf8fSFrançois Tigeot 	ret = intel_ring_begin(ring, 2);
1427e3adcf8fSFrançois Tigeot 	if (ret)
1428e3adcf8fSFrançois Tigeot 		return ret;
1429e3adcf8fSFrançois Tigeot 
1430686a02f1SFrançois Tigeot 	intel_ring_emit(ring, MI_BATCH_BUFFER_START | MI_BATCH_GTT);
1431686a02f1SFrançois Tigeot 	intel_ring_emit(ring, offset | (flags & I915_DISPATCH_SECURE ? 0 : MI_BATCH_NON_SECURE));
1432e3adcf8fSFrançois Tigeot 	intel_ring_advance(ring);
1433e3adcf8fSFrançois Tigeot 
1434e3adcf8fSFrançois Tigeot 	return 0;
1435e3adcf8fSFrançois Tigeot }
1436e3adcf8fSFrançois Tigeot 
1437ba55f2f5SFrançois Tigeot static void cleanup_status_page(struct intel_engine_cs *ring)
1438e3adcf8fSFrançois Tigeot {
1439e3adcf8fSFrançois Tigeot 	struct drm_i915_gem_object *obj;
1440e3adcf8fSFrançois Tigeot 
1441e3adcf8fSFrançois Tigeot 	obj = ring->status_page.obj;
1442e3adcf8fSFrançois Tigeot 	if (obj == NULL)
1443e3adcf8fSFrançois Tigeot 		return;
1444e3adcf8fSFrançois Tigeot 
14459edbd4a0SFrançois Tigeot 	kunmap(obj->pages[0]);
1446ba55f2f5SFrançois Tigeot 	i915_gem_object_ggtt_unpin(obj);
1447e3adcf8fSFrançois Tigeot 	drm_gem_object_unreference(&obj->base);
1448e3adcf8fSFrançois Tigeot 	ring->status_page.obj = NULL;
1449e3adcf8fSFrançois Tigeot }
1450e3adcf8fSFrançois Tigeot 
1451ba55f2f5SFrançois Tigeot static int init_status_page(struct intel_engine_cs *ring)
1452e3adcf8fSFrançois Tigeot {
1453e3adcf8fSFrançois Tigeot 	struct drm_i915_gem_object *obj;
1454ba55f2f5SFrançois Tigeot 
1455ba55f2f5SFrançois Tigeot 	if ((obj = ring->status_page.obj) == NULL) {
1456*24edb884SFrançois Tigeot 		unsigned flags;
1457e3adcf8fSFrançois Tigeot 		int ret;
1458e3adcf8fSFrançois Tigeot 
1459ba55f2f5SFrançois Tigeot 		obj = i915_gem_alloc_object(ring->dev, 4096);
1460e3adcf8fSFrançois Tigeot 		if (obj == NULL) {
1461e3adcf8fSFrançois Tigeot 			DRM_ERROR("Failed to allocate status page\n");
1462ba55f2f5SFrançois Tigeot 			return -ENOMEM;
1463e3adcf8fSFrançois Tigeot 		}
1464e3adcf8fSFrançois Tigeot 
1465ba55f2f5SFrançois Tigeot 		ret = i915_gem_object_set_cache_level(obj, I915_CACHE_LLC);
1466ba55f2f5SFrançois Tigeot 		if (ret)
1467e3adcf8fSFrançois Tigeot 			goto err_unref;
1468ba55f2f5SFrançois Tigeot 
1469*24edb884SFrançois Tigeot 		flags = 0;
1470*24edb884SFrançois Tigeot 		if (!HAS_LLC(ring->dev))
1471*24edb884SFrançois Tigeot 			/* On g33, we cannot place HWS above 256MiB, so
1472*24edb884SFrançois Tigeot 			 * restrict its pinning to the low mappable arena.
1473*24edb884SFrançois Tigeot 			 * Though this restriction is not documented for
1474*24edb884SFrançois Tigeot 			 * gen4, gen5, or byt, they also behave similarly
1475*24edb884SFrançois Tigeot 			 * and hang if the HWS is placed at the top of the
1476*24edb884SFrançois Tigeot 			 * GTT. To generalise, it appears that all !llc
1477*24edb884SFrançois Tigeot 			 * platforms have issues with us placing the HWS
1478*24edb884SFrançois Tigeot 			 * above the mappable region (even though we never
1479*24edb884SFrançois Tigeot 			 * actualy map it).
1480*24edb884SFrançois Tigeot 			 */
1481*24edb884SFrançois Tigeot 			flags |= PIN_MAPPABLE;
1482*24edb884SFrançois Tigeot 		ret = i915_gem_obj_ggtt_pin(obj, 4096, flags);
1483ba55f2f5SFrançois Tigeot 		if (ret) {
1484ba55f2f5SFrançois Tigeot err_unref:
1485ba55f2f5SFrançois Tigeot 			drm_gem_object_unreference(&obj->base);
1486ba55f2f5SFrançois Tigeot 			return ret;
1487ba55f2f5SFrançois Tigeot 		}
1488ba55f2f5SFrançois Tigeot 
1489ba55f2f5SFrançois Tigeot 		ring->status_page.obj = obj;
1490e3adcf8fSFrançois Tigeot 	}
1491e3adcf8fSFrançois Tigeot 
14929edbd4a0SFrançois Tigeot 	ring->status_page.gfx_addr = i915_gem_obj_ggtt_offset(obj);
1493f4f90b23SFrançois Tigeot 	ring->status_page.page_addr = kmap(obj->pages[0]);
1494e3adcf8fSFrançois Tigeot 	memset(ring->status_page.page_addr, 0, PAGE_SIZE);
1495e3adcf8fSFrançois Tigeot 
1496b5c29a34SFrançois Tigeot 	DRM_DEBUG_DRIVER("%s hws offset: 0x%08x\n",
1497e3adcf8fSFrançois Tigeot 			ring->name, ring->status_page.gfx_addr);
1498e3adcf8fSFrançois Tigeot 
1499e3adcf8fSFrançois Tigeot 	return 0;
1500e3adcf8fSFrançois Tigeot }
1501e3adcf8fSFrançois Tigeot 
1502ba55f2f5SFrançois Tigeot static int init_phys_status_page(struct intel_engine_cs *ring)
1503686a02f1SFrançois Tigeot {
1504686a02f1SFrançois Tigeot 	struct drm_i915_private *dev_priv = ring->dev->dev_private;
1505686a02f1SFrançois Tigeot 
1506686a02f1SFrançois Tigeot 	if (!dev_priv->status_page_dmah) {
1507686a02f1SFrançois Tigeot 		dev_priv->status_page_dmah =
1508b31e9d59SFrançois Tigeot 			drm_pci_alloc(ring->dev, PAGE_SIZE, PAGE_SIZE);
1509686a02f1SFrançois Tigeot 		if (!dev_priv->status_page_dmah)
1510686a02f1SFrançois Tigeot 			return -ENOMEM;
1511686a02f1SFrançois Tigeot 	}
1512686a02f1SFrançois Tigeot 
1513686a02f1SFrançois Tigeot 	ring->status_page.page_addr = dev_priv->status_page_dmah->vaddr;
1514686a02f1SFrançois Tigeot 	memset(ring->status_page.page_addr, 0, PAGE_SIZE);
1515686a02f1SFrançois Tigeot 
1516686a02f1SFrançois Tigeot 	return 0;
1517686a02f1SFrançois Tigeot }
1518686a02f1SFrançois Tigeot 
1519*24edb884SFrançois Tigeot static void intel_destroy_ringbuffer_obj(struct intel_ringbuffer *ringbuf)
1520e3adcf8fSFrançois Tigeot {
1521*24edb884SFrançois Tigeot 	if (!ringbuf->obj)
1522*24edb884SFrançois Tigeot 		return;
1523*24edb884SFrançois Tigeot 
1524*24edb884SFrançois Tigeot 	iounmap(ringbuf->virtual_start, ringbuf->size);
1525*24edb884SFrançois Tigeot 	i915_gem_object_ggtt_unpin(ringbuf->obj);
1526*24edb884SFrançois Tigeot 	drm_gem_object_unreference(&ringbuf->obj->base);
1527*24edb884SFrançois Tigeot 	ringbuf->obj = NULL;
1528*24edb884SFrançois Tigeot }
1529*24edb884SFrançois Tigeot 
1530*24edb884SFrançois Tigeot static int intel_alloc_ringbuffer_obj(struct drm_device *dev,
1531*24edb884SFrançois Tigeot 				      struct intel_ringbuffer *ringbuf)
1532*24edb884SFrançois Tigeot {
1533e3adcf8fSFrançois Tigeot 	struct drm_i915_gem_object *obj;
1534e3adcf8fSFrançois Tigeot 	int ret;
1535e3adcf8fSFrançois Tigeot 
1536*24edb884SFrançois Tigeot 	if (ringbuf->obj)
1537ba55f2f5SFrançois Tigeot 		return 0;
1538e3adcf8fSFrançois Tigeot 
1539a2fdbec6SFrançois Tigeot 	obj = NULL;
1540a2fdbec6SFrançois Tigeot 	if (!HAS_LLC(dev))
1541ba55f2f5SFrançois Tigeot 		obj = i915_gem_object_create_stolen(dev, ringbuf->size);
1542a2fdbec6SFrançois Tigeot 	if (obj == NULL)
1543ba55f2f5SFrançois Tigeot 		obj = i915_gem_alloc_object(dev, ringbuf->size);
1544ba55f2f5SFrançois Tigeot 	if (obj == NULL)
1545ba55f2f5SFrançois Tigeot 		return -ENOMEM;
1546e3adcf8fSFrançois Tigeot 
1547*24edb884SFrançois Tigeot 	/* mark ring buffers as read-only from GPU side by default */
1548*24edb884SFrançois Tigeot 	obj->gt_ro = 1;
1549*24edb884SFrançois Tigeot 
1550ba55f2f5SFrançois Tigeot 	ret = i915_gem_obj_ggtt_pin(obj, PAGE_SIZE, PIN_MAPPABLE);
1551e3adcf8fSFrançois Tigeot 	if (ret)
1552e3adcf8fSFrançois Tigeot 		goto err_unref;
1553e3adcf8fSFrançois Tigeot 
1554686a02f1SFrançois Tigeot 	ret = i915_gem_object_set_to_gtt_domain(obj, true);
1555686a02f1SFrançois Tigeot 	if (ret)
1556686a02f1SFrançois Tigeot 		goto err_unpin;
1557e3adcf8fSFrançois Tigeot 
1558ba55f2f5SFrançois Tigeot 	ringbuf->virtual_start =
15599edbd4a0SFrançois Tigeot 		ioremap_wc(dev->agp->base + i915_gem_obj_ggtt_offset(obj),
1560ba55f2f5SFrançois Tigeot 				ringbuf->size);
1561ba55f2f5SFrançois Tigeot 	if (ringbuf->virtual_start == NULL) {
1562e3adcf8fSFrançois Tigeot 		ret = -EINVAL;
1563e3adcf8fSFrançois Tigeot 		goto err_unpin;
1564e3adcf8fSFrançois Tigeot 	}
1565e3adcf8fSFrançois Tigeot 
1566ba55f2f5SFrançois Tigeot 	ringbuf->obj = obj;
1567ba55f2f5SFrançois Tigeot 	return 0;
1568ba55f2f5SFrançois Tigeot 
1569ba55f2f5SFrançois Tigeot err_unpin:
1570ba55f2f5SFrançois Tigeot 	i915_gem_object_ggtt_unpin(obj);
1571ba55f2f5SFrançois Tigeot err_unref:
1572ba55f2f5SFrançois Tigeot 	drm_gem_object_unreference(&obj->base);
1573ba55f2f5SFrançois Tigeot 	return ret;
1574ba55f2f5SFrançois Tigeot }
1575ba55f2f5SFrançois Tigeot 
1576ba55f2f5SFrançois Tigeot static int intel_init_ring_buffer(struct drm_device *dev,
1577ba55f2f5SFrançois Tigeot 				  struct intel_engine_cs *ring)
1578ba55f2f5SFrançois Tigeot {
1579ba55f2f5SFrançois Tigeot 	struct intel_ringbuffer *ringbuf = ring->buffer;
1580ba55f2f5SFrançois Tigeot 	int ret;
1581ba55f2f5SFrançois Tigeot 
1582ba55f2f5SFrançois Tigeot 	if (ringbuf == NULL) {
1583ba55f2f5SFrançois Tigeot 		ringbuf = kzalloc(sizeof(*ringbuf), GFP_KERNEL);
1584ba55f2f5SFrançois Tigeot 		if (!ringbuf)
1585ba55f2f5SFrançois Tigeot 			return -ENOMEM;
1586ba55f2f5SFrançois Tigeot 		ring->buffer = ringbuf;
1587ba55f2f5SFrançois Tigeot 	}
1588ba55f2f5SFrançois Tigeot 
1589ba55f2f5SFrançois Tigeot 	ring->dev = dev;
1590ba55f2f5SFrançois Tigeot 	INIT_LIST_HEAD(&ring->active_list);
1591ba55f2f5SFrançois Tigeot 	INIT_LIST_HEAD(&ring->request_list);
1592ba55f2f5SFrançois Tigeot 	ringbuf->size = 32 * PAGE_SIZE;
1593ba55f2f5SFrançois Tigeot 	memset(ring->semaphore.sync_seqno, 0, sizeof(ring->semaphore.sync_seqno));
1594ba55f2f5SFrançois Tigeot 
1595ba55f2f5SFrançois Tigeot 	init_waitqueue_head(&ring->irq_queue);
1596ba55f2f5SFrançois Tigeot 
1597ba55f2f5SFrançois Tigeot 	if (I915_NEED_GFX_HWS(dev)) {
1598ba55f2f5SFrançois Tigeot 		ret = init_status_page(ring);
1599e3adcf8fSFrançois Tigeot 		if (ret)
1600ba55f2f5SFrançois Tigeot 			goto error;
1601ba55f2f5SFrançois Tigeot 	} else {
1602ba55f2f5SFrançois Tigeot 		BUG_ON(ring->id != RCS);
1603ba55f2f5SFrançois Tigeot 		ret = init_phys_status_page(ring);
1604ba55f2f5SFrançois Tigeot 		if (ret)
1605ba55f2f5SFrançois Tigeot 			goto error;
1606ba55f2f5SFrançois Tigeot 	}
1607ba55f2f5SFrançois Tigeot 
1608*24edb884SFrançois Tigeot 	ret = intel_alloc_ringbuffer_obj(dev, ringbuf);
1609ba55f2f5SFrançois Tigeot 	if (ret) {
1610ba55f2f5SFrançois Tigeot 		DRM_ERROR("Failed to allocate ringbuffer %s: %d\n", ring->name, ret);
1611ba55f2f5SFrançois Tigeot 		goto error;
1612ba55f2f5SFrançois Tigeot 	}
1613e3adcf8fSFrançois Tigeot 
1614e3adcf8fSFrançois Tigeot 	/* Workaround an erratum on the i830 which causes a hang if
1615e3adcf8fSFrançois Tigeot 	 * the TAIL pointer points to within the last 2 cachelines
1616e3adcf8fSFrançois Tigeot 	 * of the buffer.
1617e3adcf8fSFrançois Tigeot 	 */
1618ba55f2f5SFrançois Tigeot 	ringbuf->effective_size = ringbuf->size;
1619ba55f2f5SFrançois Tigeot 	if (IS_I830(dev) || IS_845G(dev))
1620ba55f2f5SFrançois Tigeot 		ringbuf->effective_size -= 2 * CACHELINE_BYTES;
1621ba55f2f5SFrançois Tigeot 
1622ba55f2f5SFrançois Tigeot 	ret = i915_cmd_parser_init_ring(ring);
1623ba55f2f5SFrançois Tigeot 	if (ret)
1624ba55f2f5SFrançois Tigeot 		goto error;
1625ba55f2f5SFrançois Tigeot 
1626ba55f2f5SFrançois Tigeot 	ret = ring->init(ring);
1627ba55f2f5SFrançois Tigeot 	if (ret)
1628ba55f2f5SFrançois Tigeot 		goto error;
1629e3adcf8fSFrançois Tigeot 
1630e3adcf8fSFrançois Tigeot 	return 0;
1631e3adcf8fSFrançois Tigeot 
1632ba55f2f5SFrançois Tigeot error:
1633ba55f2f5SFrançois Tigeot 	kfree(ringbuf);
1634ba55f2f5SFrançois Tigeot 	ring->buffer = NULL;
1635e3adcf8fSFrançois Tigeot 	return ret;
1636e3adcf8fSFrançois Tigeot }
1637e3adcf8fSFrançois Tigeot 
1638ba55f2f5SFrançois Tigeot void intel_cleanup_ring_buffer(struct intel_engine_cs *ring)
1639e3adcf8fSFrançois Tigeot {
1640ba55f2f5SFrançois Tigeot 	struct drm_i915_private *dev_priv = to_i915(ring->dev);
1641ba55f2f5SFrançois Tigeot 	struct intel_ringbuffer *ringbuf = ring->buffer;
1642e3adcf8fSFrançois Tigeot 
1643ba55f2f5SFrançois Tigeot 	if (!intel_ring_initialized(ring))
1644e3adcf8fSFrançois Tigeot 		return;
1645e3adcf8fSFrançois Tigeot 
1646ba55f2f5SFrançois Tigeot 	intel_stop_ring_buffer(ring);
1647ba55f2f5SFrançois Tigeot 	WARN_ON(!IS_GEN2(ring->dev) && (I915_READ_MODE(ring) & MODE_IDLE) == 0);
1648b030f26bSFrançois Tigeot 
1649*24edb884SFrançois Tigeot 	intel_destroy_ringbuffer_obj(ringbuf);
16509edbd4a0SFrançois Tigeot 	ring->preallocated_lazy_request = NULL;
16519edbd4a0SFrançois Tigeot 	ring->outstanding_lazy_seqno = 0;
1652e3adcf8fSFrançois Tigeot 
1653e3adcf8fSFrançois Tigeot 	if (ring->cleanup)
1654e3adcf8fSFrançois Tigeot 		ring->cleanup(ring);
1655e3adcf8fSFrançois Tigeot 
1656e3adcf8fSFrançois Tigeot 	cleanup_status_page(ring);
1657ba55f2f5SFrançois Tigeot 
1658ba55f2f5SFrançois Tigeot 	i915_cmd_parser_fini_ring(ring);
1659ba55f2f5SFrançois Tigeot 
1660ba55f2f5SFrançois Tigeot 	kfree(ringbuf);
1661ba55f2f5SFrançois Tigeot 	ring->buffer = NULL;
1662e3adcf8fSFrançois Tigeot }
1663e3adcf8fSFrançois Tigeot 
1664ba55f2f5SFrançois Tigeot static int intel_ring_wait_request(struct intel_engine_cs *ring, int n)
1665e3adcf8fSFrançois Tigeot {
1666ba55f2f5SFrançois Tigeot 	struct intel_ringbuffer *ringbuf = ring->buffer;
1667e3adcf8fSFrançois Tigeot 	struct drm_i915_gem_request *request;
1668e3adcf8fSFrançois Tigeot 	u32 seqno = 0;
1669e3adcf8fSFrançois Tigeot 	int ret;
1670e3adcf8fSFrançois Tigeot 
1671ba55f2f5SFrançois Tigeot 	if (ringbuf->last_retired_head != -1) {
1672ba55f2f5SFrançois Tigeot 		ringbuf->head = ringbuf->last_retired_head;
1673ba55f2f5SFrançois Tigeot 		ringbuf->last_retired_head = -1;
1674e3adcf8fSFrançois Tigeot 
1675*24edb884SFrançois Tigeot 		ringbuf->space = ring_space(ringbuf);
1676ba55f2f5SFrançois Tigeot 		if (ringbuf->space >= n)
1677e3adcf8fSFrançois Tigeot 			return 0;
1678e3adcf8fSFrançois Tigeot 	}
1679e3adcf8fSFrançois Tigeot 
1680e3adcf8fSFrançois Tigeot 	list_for_each_entry(request, &ring->request_list, list) {
1681ba55f2f5SFrançois Tigeot 		if (__ring_space(request->tail, ringbuf->tail, ringbuf->size) >= n) {
1682e3adcf8fSFrançois Tigeot 			seqno = request->seqno;
1683e3adcf8fSFrançois Tigeot 			break;
1684e3adcf8fSFrançois Tigeot 		}
1685e3adcf8fSFrançois Tigeot 	}
1686e3adcf8fSFrançois Tigeot 
1687e3adcf8fSFrançois Tigeot 	if (seqno == 0)
1688e3adcf8fSFrançois Tigeot 		return -ENOSPC;
1689e3adcf8fSFrançois Tigeot 
1690ba55f2f5SFrançois Tigeot 	ret = i915_wait_seqno(ring, seqno);
1691e3adcf8fSFrançois Tigeot 	if (ret)
1692e3adcf8fSFrançois Tigeot 		return ret;
1693e3adcf8fSFrançois Tigeot 
1694ba55f2f5SFrançois Tigeot 	i915_gem_retire_requests_ring(ring);
1695ba55f2f5SFrançois Tigeot 	ringbuf->head = ringbuf->last_retired_head;
1696ba55f2f5SFrançois Tigeot 	ringbuf->last_retired_head = -1;
1697e3adcf8fSFrançois Tigeot 
1698*24edb884SFrançois Tigeot 	ringbuf->space = ring_space(ringbuf);
1699e3adcf8fSFrançois Tigeot 	return 0;
1700e3adcf8fSFrançois Tigeot }
1701e3adcf8fSFrançois Tigeot 
1702ba55f2f5SFrançois Tigeot static int ring_wait_for_space(struct intel_engine_cs *ring, int n)
1703e3adcf8fSFrançois Tigeot {
1704e3adcf8fSFrançois Tigeot 	struct drm_device *dev = ring->dev;
1705e3adcf8fSFrançois Tigeot 	struct drm_i915_private *dev_priv = dev->dev_private;
1706ba55f2f5SFrançois Tigeot 	struct intel_ringbuffer *ringbuf = ring->buffer;
1707245593daSFrançois Tigeot 	unsigned long end;
1708e3adcf8fSFrançois Tigeot 	int ret;
1709e3adcf8fSFrançois Tigeot 
1710e3adcf8fSFrançois Tigeot 	ret = intel_ring_wait_request(ring, n);
1711e3adcf8fSFrançois Tigeot 	if (ret != -ENOSPC)
1712e3adcf8fSFrançois Tigeot 		return ret;
1713e3adcf8fSFrançois Tigeot 
17149edbd4a0SFrançois Tigeot 	/* force the tail write in case we have been skipping them */
17159edbd4a0SFrançois Tigeot 	__intel_ring_advance(ring);
17169edbd4a0SFrançois Tigeot 
1717e3adcf8fSFrançois Tigeot 	/* With GEM the hangcheck timer should kick us out of the loop,
1718e3adcf8fSFrançois Tigeot 	 * leaving it early runs the risk of corrupting GEM state (due
1719e3adcf8fSFrançois Tigeot 	 * to running on almost untested codepaths). But on resume
1720e3adcf8fSFrançois Tigeot 	 * timers don't work yet, so prevent a complete hang in that
1721e3adcf8fSFrançois Tigeot 	 * case by choosing an insanely large timeout. */
1722e3440f96SFrançois Tigeot 	end = jiffies + 60 * HZ;
1723245593daSFrançois Tigeot 
1724ba55f2f5SFrançois Tigeot 	trace_i915_ring_wait_begin(ring);
1725e3adcf8fSFrançois Tigeot 	do {
1726ba55f2f5SFrançois Tigeot 		ringbuf->head = I915_READ_HEAD(ring);
1727*24edb884SFrançois Tigeot 		ringbuf->space = ring_space(ringbuf);
1728ba55f2f5SFrançois Tigeot 		if (ringbuf->space >= n) {
1729ba55f2f5SFrançois Tigeot 			ret = 0;
1730ba55f2f5SFrançois Tigeot 			break;
1731e3adcf8fSFrançois Tigeot 		}
1732e3adcf8fSFrançois Tigeot 
1733e3adcf8fSFrançois Tigeot #if 0
1734ba55f2f5SFrançois Tigeot 		if (!drm_core_check_feature(dev, DRIVER_MODESET) &&
1735ba55f2f5SFrançois Tigeot 		    dev->primary->master) {
1736e3adcf8fSFrançois Tigeot 			struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv;
1737e3adcf8fSFrançois Tigeot 			if (master_priv->sarea_priv)
1738e3adcf8fSFrançois Tigeot 				master_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT;
1739e3adcf8fSFrançois Tigeot 		}
1740e3adcf8fSFrançois Tigeot #else
1741e3adcf8fSFrançois Tigeot 		if (dev_priv->sarea_priv)
1742e3adcf8fSFrançois Tigeot 			dev_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT;
1743e3adcf8fSFrançois Tigeot #endif
1744e3adcf8fSFrançois Tigeot 
1745ba55f2f5SFrançois Tigeot 
1746e3440f96SFrançois Tigeot 		msleep(1);
1747245593daSFrançois Tigeot 
1748ba55f2f5SFrançois Tigeot #if 0
1749ba55f2f5SFrançois Tigeot 		if (dev_priv->mm.interruptible && signal_pending(current)) {
1750ba55f2f5SFrançois Tigeot 			ret = -ERESTARTSYS;
1751ba55f2f5SFrançois Tigeot 			break;
1752ba55f2f5SFrançois Tigeot 		}
1753ba55f2f5SFrançois Tigeot #endif
1754ba55f2f5SFrançois Tigeot 
1755a2fdbec6SFrançois Tigeot 		ret = i915_gem_check_wedge(&dev_priv->gpu_error,
1756a2fdbec6SFrançois Tigeot 					   dev_priv->mm.interruptible);
1757245593daSFrançois Tigeot 		if (ret)
1758ba55f2f5SFrançois Tigeot 			break;
1759ba55f2f5SFrançois Tigeot 
1760ba55f2f5SFrançois Tigeot 		if (time_after(jiffies, end)) {
1761ba55f2f5SFrançois Tigeot 			ret = -EBUSY;
1762ba55f2f5SFrançois Tigeot 			break;
1763ba55f2f5SFrançois Tigeot 		}
1764ba55f2f5SFrançois Tigeot 	} while (1);
1765a2fdbec6SFrançois Tigeot 	trace_i915_ring_wait_end(ring);
1766ba55f2f5SFrançois Tigeot 	return ret;
1767e3adcf8fSFrançois Tigeot }
1768e3adcf8fSFrançois Tigeot 
1769ba55f2f5SFrançois Tigeot static int intel_wrap_ring_buffer(struct intel_engine_cs *ring)
1770b030f26bSFrançois Tigeot {
1771b030f26bSFrançois Tigeot 	uint32_t __iomem *virt;
1772ba55f2f5SFrançois Tigeot 	struct intel_ringbuffer *ringbuf = ring->buffer;
1773ba55f2f5SFrançois Tigeot 	int rem = ringbuf->size - ringbuf->tail;
1774b030f26bSFrançois Tigeot 
1775ba55f2f5SFrançois Tigeot 	if (ringbuf->space < rem) {
1776b030f26bSFrançois Tigeot 		int ret = ring_wait_for_space(ring, rem);
1777b030f26bSFrançois Tigeot 		if (ret)
1778b030f26bSFrançois Tigeot 			return ret;
1779b030f26bSFrançois Tigeot 	}
1780b030f26bSFrançois Tigeot 
1781ba55f2f5SFrançois Tigeot 	virt = (unsigned int *)((char *)ringbuf->virtual_start + ringbuf->tail);
1782b030f26bSFrançois Tigeot 	rem /= 4;
1783b030f26bSFrançois Tigeot 	while (rem--)
1784686a02f1SFrançois Tigeot 		iowrite32(MI_NOOP, virt++);
1785b030f26bSFrançois Tigeot 
1786ba55f2f5SFrançois Tigeot 	ringbuf->tail = 0;
1787*24edb884SFrançois Tigeot 	ringbuf->space = ring_space(ringbuf);
1788b030f26bSFrançois Tigeot 
1789b030f26bSFrançois Tigeot 	return 0;
1790b030f26bSFrançois Tigeot }
1791b030f26bSFrançois Tigeot 
1792ba55f2f5SFrançois Tigeot int intel_ring_idle(struct intel_engine_cs *ring)
1793b030f26bSFrançois Tigeot {
1794b5c29a34SFrançois Tigeot 	u32 seqno;
1795b5c29a34SFrançois Tigeot 	int ret;
1796b5c29a34SFrançois Tigeot 
1797b5c29a34SFrançois Tigeot 	/* We need to add any requests required to flush the objects and ring */
17989edbd4a0SFrançois Tigeot 	if (ring->outstanding_lazy_seqno) {
17995d0b1887SFrançois Tigeot 		ret = i915_add_request(ring, NULL);
1800b5c29a34SFrançois Tigeot 		if (ret)
1801b5c29a34SFrançois Tigeot 			return ret;
1802b5c29a34SFrançois Tigeot 	}
1803b5c29a34SFrançois Tigeot 
1804b5c29a34SFrançois Tigeot 	/* Wait upon the last request to be completed */
1805b5c29a34SFrançois Tigeot 	if (list_empty(&ring->request_list))
1806b5c29a34SFrançois Tigeot 		return 0;
1807b5c29a34SFrançois Tigeot 
1808b5c29a34SFrançois Tigeot 	seqno = list_entry(ring->request_list.prev,
1809b5c29a34SFrançois Tigeot 			   struct drm_i915_gem_request,
1810b5c29a34SFrançois Tigeot 			   list)->seqno;
1811b5c29a34SFrançois Tigeot 
1812b5c29a34SFrançois Tigeot 	return i915_wait_seqno(ring, seqno);
1813b5c29a34SFrançois Tigeot }
1814b5c29a34SFrançois Tigeot 
1815b5c29a34SFrançois Tigeot static int
1816ba55f2f5SFrançois Tigeot intel_ring_alloc_seqno(struct intel_engine_cs *ring)
1817b5c29a34SFrançois Tigeot {
18189edbd4a0SFrançois Tigeot 	if (ring->outstanding_lazy_seqno)
1819b5c29a34SFrançois Tigeot 		return 0;
1820b5c29a34SFrançois Tigeot 
18219edbd4a0SFrançois Tigeot 	if (ring->preallocated_lazy_request == NULL) {
18229edbd4a0SFrançois Tigeot 		struct drm_i915_gem_request *request;
18239edbd4a0SFrançois Tigeot 
18249edbd4a0SFrançois Tigeot 		request = kmalloc(sizeof(*request), M_DRM, M_WAITOK);
18259edbd4a0SFrançois Tigeot 		if (request == NULL)
18269edbd4a0SFrançois Tigeot 			return -ENOMEM;
18279edbd4a0SFrançois Tigeot 
18289edbd4a0SFrançois Tigeot 		ring->preallocated_lazy_request = request;
1829b030f26bSFrançois Tigeot 	}
1830b030f26bSFrançois Tigeot 
18319edbd4a0SFrançois Tigeot 	return i915_gem_get_seqno(ring->dev, &ring->outstanding_lazy_seqno);
18329edbd4a0SFrançois Tigeot }
18339edbd4a0SFrançois Tigeot 
1834ba55f2f5SFrançois Tigeot static int __intel_ring_prepare(struct intel_engine_cs *ring,
1835a2fdbec6SFrançois Tigeot 				int bytes)
1836a2fdbec6SFrançois Tigeot {
1837ba55f2f5SFrançois Tigeot 	struct intel_ringbuffer *ringbuf = ring->buffer;
1838a2fdbec6SFrançois Tigeot 	int ret;
1839a2fdbec6SFrançois Tigeot 
1840ba55f2f5SFrançois Tigeot 	if (unlikely(ringbuf->tail + bytes > ringbuf->effective_size)) {
1841a2fdbec6SFrançois Tigeot 		ret = intel_wrap_ring_buffer(ring);
1842a2fdbec6SFrançois Tigeot 		if (unlikely(ret))
1843a2fdbec6SFrançois Tigeot 			return ret;
1844a2fdbec6SFrançois Tigeot 	}
1845a2fdbec6SFrançois Tigeot 
1846ba55f2f5SFrançois Tigeot 	if (unlikely(ringbuf->space < bytes)) {
1847a2fdbec6SFrançois Tigeot 		ret = ring_wait_for_space(ring, bytes);
1848a2fdbec6SFrançois Tigeot 		if (unlikely(ret))
1849a2fdbec6SFrançois Tigeot 			return ret;
1850a2fdbec6SFrançois Tigeot 	}
1851a2fdbec6SFrançois Tigeot 
1852a2fdbec6SFrançois Tigeot 	return 0;
1853a2fdbec6SFrançois Tigeot }
1854a2fdbec6SFrançois Tigeot 
1855ba55f2f5SFrançois Tigeot int intel_ring_begin(struct intel_engine_cs *ring,
1856e3adcf8fSFrançois Tigeot 		     int num_dwords)
1857e3adcf8fSFrançois Tigeot {
1858ba55f2f5SFrançois Tigeot 	struct drm_i915_private *dev_priv = ring->dev->dev_private;
1859e3adcf8fSFrançois Tigeot 	int ret;
1860e3adcf8fSFrançois Tigeot 
1861a2fdbec6SFrançois Tigeot 	ret = i915_gem_check_wedge(&dev_priv->gpu_error,
1862a2fdbec6SFrançois Tigeot 				   dev_priv->mm.interruptible);
1863245593daSFrançois Tigeot 	if (ret)
1864245593daSFrançois Tigeot 		return ret;
1865e3adcf8fSFrançois Tigeot 
18669edbd4a0SFrançois Tigeot 	ret = __intel_ring_prepare(ring, num_dwords * sizeof(uint32_t));
18679edbd4a0SFrançois Tigeot 	if (ret)
18689edbd4a0SFrançois Tigeot 		return ret;
18699edbd4a0SFrançois Tigeot 
1870b5c29a34SFrançois Tigeot 	/* Preallocate the olr before touching the ring */
1871b5c29a34SFrançois Tigeot 	ret = intel_ring_alloc_seqno(ring);
1872b5c29a34SFrançois Tigeot 	if (ret)
1873b5c29a34SFrançois Tigeot 		return ret;
1874b5c29a34SFrançois Tigeot 
1875ba55f2f5SFrançois Tigeot 	ring->buffer->space -= num_dwords * sizeof(uint32_t);
18769edbd4a0SFrançois Tigeot 	return 0;
18779edbd4a0SFrançois Tigeot }
18789edbd4a0SFrançois Tigeot 
18799edbd4a0SFrançois Tigeot /* Align the ring tail to a cacheline boundary */
1880ba55f2f5SFrançois Tigeot int intel_ring_cacheline_align(struct intel_engine_cs *ring)
18819edbd4a0SFrançois Tigeot {
1882ba55f2f5SFrançois Tigeot 	int num_dwords = (ring->buffer->tail & (CACHELINE_BYTES - 1)) / sizeof(uint32_t);
18839edbd4a0SFrançois Tigeot 	int ret;
18849edbd4a0SFrançois Tigeot 
18859edbd4a0SFrançois Tigeot 	if (num_dwords == 0)
18869edbd4a0SFrançois Tigeot 		return 0;
18879edbd4a0SFrançois Tigeot 
1888ba55f2f5SFrançois Tigeot 	num_dwords = CACHELINE_BYTES / sizeof(uint32_t) - num_dwords;
18899edbd4a0SFrançois Tigeot 	ret = intel_ring_begin(ring, num_dwords);
18909edbd4a0SFrançois Tigeot 	if (ret)
18919edbd4a0SFrançois Tigeot 		return ret;
18929edbd4a0SFrançois Tigeot 
18939edbd4a0SFrançois Tigeot 	while (num_dwords--)
18949edbd4a0SFrançois Tigeot 		intel_ring_emit(ring, MI_NOOP);
18959edbd4a0SFrançois Tigeot 
18969edbd4a0SFrançois Tigeot 	intel_ring_advance(ring);
18979edbd4a0SFrançois Tigeot 
18989edbd4a0SFrançois Tigeot 	return 0;
1899e3adcf8fSFrançois Tigeot }
1900e3adcf8fSFrançois Tigeot 
1901ba55f2f5SFrançois Tigeot void intel_ring_init_seqno(struct intel_engine_cs *ring, u32 seqno)
1902a2fdbec6SFrançois Tigeot {
1903*24edb884SFrançois Tigeot 	struct drm_device *dev = ring->dev;
1904*24edb884SFrançois Tigeot 	struct drm_i915_private *dev_priv = dev->dev_private;
1905a2fdbec6SFrançois Tigeot 
19069edbd4a0SFrançois Tigeot 	BUG_ON(ring->outstanding_lazy_seqno);
1907a2fdbec6SFrançois Tigeot 
1908*24edb884SFrançois Tigeot 	if (INTEL_INFO(dev)->gen == 6 || INTEL_INFO(dev)->gen == 7) {
1909a2fdbec6SFrançois Tigeot 		I915_WRITE(RING_SYNC_0(ring->mmio_base), 0);
1910a2fdbec6SFrançois Tigeot 		I915_WRITE(RING_SYNC_1(ring->mmio_base), 0);
1911*24edb884SFrançois Tigeot 		if (HAS_VEBOX(dev))
19129edbd4a0SFrançois Tigeot 			I915_WRITE(RING_SYNC_2(ring->mmio_base), 0);
1913e3adcf8fSFrançois Tigeot 	}
1914e3adcf8fSFrançois Tigeot 
1915a2fdbec6SFrançois Tigeot 	ring->set_seqno(ring, seqno);
19165d0b1887SFrançois Tigeot 	ring->hangcheck.seqno = seqno;
1917e3adcf8fSFrançois Tigeot }
1918e3adcf8fSFrançois Tigeot 
1919ba55f2f5SFrançois Tigeot static void gen6_bsd_ring_write_tail(struct intel_engine_cs *ring,
1920f4e1c372SFrançois Tigeot 				     u32 value)
1921e3adcf8fSFrançois Tigeot {
1922ba55f2f5SFrançois Tigeot 	struct drm_i915_private *dev_priv = ring->dev->dev_private;
1923e3adcf8fSFrançois Tigeot 
1924e3adcf8fSFrançois Tigeot        /* Every tail move must follow the sequence below */
1925f4e1c372SFrançois Tigeot 
1926f4e1c372SFrançois Tigeot 	/* Disable notification that the ring is IDLE. The GT
1927f4e1c372SFrançois Tigeot 	 * will then assume that it is busy and bring it out of rc6.
1928f4e1c372SFrançois Tigeot 	 */
1929e3adcf8fSFrançois Tigeot 	I915_WRITE(GEN6_BSD_SLEEP_PSMI_CONTROL,
1930f4e1c372SFrançois Tigeot 		   _MASKED_BIT_ENABLE(GEN6_BSD_SLEEP_MSG_DISABLE));
1931e3adcf8fSFrançois Tigeot 
1932f4e1c372SFrançois Tigeot 	/* Clear the context id. Here be magic! */
1933f4e1c372SFrançois Tigeot 	I915_WRITE64(GEN6_BSD_RNCID, 0x0);
1934e3adcf8fSFrançois Tigeot 
1935f4e1c372SFrançois Tigeot 	/* Wait for the ring not to be idle, i.e. for it to wake up. */
1936f4e1c372SFrançois Tigeot 	if (wait_for((I915_READ(GEN6_BSD_SLEEP_PSMI_CONTROL) &
1937f4e1c372SFrançois Tigeot 		      GEN6_BSD_SLEEP_INDICATOR) == 0,
1938f4e1c372SFrançois Tigeot 		     50))
1939f4e1c372SFrançois Tigeot 		DRM_ERROR("timed out waiting for the BSD ring to wake up\n");
1940f4e1c372SFrançois Tigeot 
1941f4e1c372SFrançois Tigeot 	/* Now that the ring is fully powered up, update the tail */
1942e3adcf8fSFrançois Tigeot 	I915_WRITE_TAIL(ring, value);
1943f4e1c372SFrançois Tigeot 	POSTING_READ(RING_TAIL(ring->mmio_base));
1944f4e1c372SFrançois Tigeot 
1945f4e1c372SFrançois Tigeot 	/* Let the ring send IDLE messages to the GT again,
1946f4e1c372SFrançois Tigeot 	 * and so let it sleep to conserve power when idle.
1947f4e1c372SFrançois Tigeot 	 */
1948e3adcf8fSFrançois Tigeot 	I915_WRITE(GEN6_BSD_SLEEP_PSMI_CONTROL,
1949f4e1c372SFrançois Tigeot 		   _MASKED_BIT_DISABLE(GEN6_BSD_SLEEP_MSG_DISABLE));
1950e3adcf8fSFrançois Tigeot }
1951e3adcf8fSFrançois Tigeot 
1952ba55f2f5SFrançois Tigeot static int gen6_bsd_ring_flush(struct intel_engine_cs *ring,
1953b5c29a34SFrançois Tigeot 			       u32 invalidate, u32 flush)
1954e3adcf8fSFrançois Tigeot {
1955e3adcf8fSFrançois Tigeot 	uint32_t cmd;
1956e3adcf8fSFrançois Tigeot 	int ret;
1957e3adcf8fSFrançois Tigeot 
1958e3adcf8fSFrançois Tigeot 	ret = intel_ring_begin(ring, 4);
1959e3adcf8fSFrançois Tigeot 	if (ret)
1960e3adcf8fSFrançois Tigeot 		return ret;
1961e3adcf8fSFrançois Tigeot 
1962e3adcf8fSFrançois Tigeot 	cmd = MI_FLUSH_DW;
19639edbd4a0SFrançois Tigeot 	if (INTEL_INFO(ring->dev)->gen >= 8)
19649edbd4a0SFrançois Tigeot 		cmd += 1;
1965b5c29a34SFrançois Tigeot 	/*
1966b5c29a34SFrançois Tigeot 	 * Bspec vol 1c.5 - video engine command streamer:
1967b5c29a34SFrançois Tigeot 	 * "If ENABLED, all TLBs will be invalidated once the flush
1968b5c29a34SFrançois Tigeot 	 * operation is complete. This bit is only valid when the
1969b5c29a34SFrançois Tigeot 	 * Post-Sync Operation field is a value of 1h or 3h."
1970b5c29a34SFrançois Tigeot 	 */
1971e3adcf8fSFrançois Tigeot 	if (invalidate & I915_GEM_GPU_DOMAINS)
1972b5c29a34SFrançois Tigeot 		cmd |= MI_INVALIDATE_TLB | MI_INVALIDATE_BSD |
1973b5c29a34SFrançois Tigeot 			MI_FLUSH_DW_STORE_INDEX | MI_FLUSH_DW_OP_STOREDW;
1974e3adcf8fSFrançois Tigeot 	intel_ring_emit(ring, cmd);
1975b5c29a34SFrançois Tigeot 	intel_ring_emit(ring, I915_GEM_HWS_SCRATCH_ADDR | MI_FLUSH_DW_USE_GTT);
19769edbd4a0SFrançois Tigeot 	if (INTEL_INFO(ring->dev)->gen >= 8) {
19779edbd4a0SFrançois Tigeot 		intel_ring_emit(ring, 0); /* upper addr */
19789edbd4a0SFrançois Tigeot 		intel_ring_emit(ring, 0); /* value */
19799edbd4a0SFrançois Tigeot 	} else  {
19809edbd4a0SFrançois Tigeot 		intel_ring_emit(ring, 0);
19819edbd4a0SFrançois Tigeot 		intel_ring_emit(ring, MI_NOOP);
19829edbd4a0SFrançois Tigeot 	}
19839edbd4a0SFrançois Tigeot 	intel_ring_advance(ring);
19849edbd4a0SFrançois Tigeot 	return 0;
19859edbd4a0SFrançois Tigeot }
19869edbd4a0SFrançois Tigeot 
19879edbd4a0SFrançois Tigeot static int
1988ba55f2f5SFrançois Tigeot gen8_ring_dispatch_execbuffer(struct intel_engine_cs *ring,
1989ba55f2f5SFrançois Tigeot 			      u64 offset, u32 len,
19909edbd4a0SFrançois Tigeot 			      unsigned flags)
19919edbd4a0SFrançois Tigeot {
19929edbd4a0SFrançois Tigeot 	struct drm_i915_private *dev_priv = ring->dev->dev_private;
19939edbd4a0SFrançois Tigeot 	bool ppgtt = dev_priv->mm.aliasing_ppgtt != NULL &&
19949edbd4a0SFrançois Tigeot 		!(flags & I915_DISPATCH_SECURE);
19959edbd4a0SFrançois Tigeot 	int ret;
19969edbd4a0SFrançois Tigeot 
19979edbd4a0SFrançois Tigeot 	ret = intel_ring_begin(ring, 4);
19989edbd4a0SFrançois Tigeot 	if (ret)
19999edbd4a0SFrançois Tigeot 		return ret;
20009edbd4a0SFrançois Tigeot 
20019edbd4a0SFrançois Tigeot 	/* FIXME(BDW): Address space and security selectors. */
20029edbd4a0SFrançois Tigeot 	intel_ring_emit(ring, MI_BATCH_BUFFER_START_GEN8 | (ppgtt<<8));
2003ba55f2f5SFrançois Tigeot 	intel_ring_emit(ring, lower_32_bits(offset));
2004ba55f2f5SFrançois Tigeot 	intel_ring_emit(ring, upper_32_bits(offset));
2005e3adcf8fSFrançois Tigeot 	intel_ring_emit(ring, MI_NOOP);
2006e3adcf8fSFrançois Tigeot 	intel_ring_advance(ring);
20079edbd4a0SFrançois Tigeot 
2008e3adcf8fSFrançois Tigeot 	return 0;
2009e3adcf8fSFrançois Tigeot }
2010e3adcf8fSFrançois Tigeot 
2011e3adcf8fSFrançois Tigeot static int
2012ba55f2f5SFrançois Tigeot hsw_ring_dispatch_execbuffer(struct intel_engine_cs *ring,
2013ba55f2f5SFrançois Tigeot 			      u64 offset, u32 len,
2014b5c29a34SFrançois Tigeot 			      unsigned flags)
2015e3adcf8fSFrançois Tigeot {
2016e3adcf8fSFrançois Tigeot 	int ret;
2017e3adcf8fSFrançois Tigeot 
2018e3adcf8fSFrançois Tigeot 	ret = intel_ring_begin(ring, 2);
2019e3adcf8fSFrançois Tigeot 	if (ret)
2020e3adcf8fSFrançois Tigeot 		return ret;
2021e3adcf8fSFrançois Tigeot 
2022b5c29a34SFrançois Tigeot 	intel_ring_emit(ring,
2023b5c29a34SFrançois Tigeot 			MI_BATCH_BUFFER_START | MI_BATCH_PPGTT_HSW |
2024b5c29a34SFrançois Tigeot 			(flags & I915_DISPATCH_SECURE ? 0 : MI_BATCH_NON_SECURE_HSW));
2025b5c29a34SFrançois Tigeot 	/* bit0-7 is the length on GEN6+ */
2026b5c29a34SFrançois Tigeot 	intel_ring_emit(ring, offset);
2027b5c29a34SFrançois Tigeot 	intel_ring_advance(ring);
2028b5c29a34SFrançois Tigeot 
2029b5c29a34SFrançois Tigeot 	return 0;
2030b5c29a34SFrançois Tigeot }
2031b5c29a34SFrançois Tigeot 
2032b5c29a34SFrançois Tigeot static int
2033ba55f2f5SFrançois Tigeot gen6_ring_dispatch_execbuffer(struct intel_engine_cs *ring,
2034ba55f2f5SFrançois Tigeot 			      u64 offset, u32 len,
2035b5c29a34SFrançois Tigeot 			      unsigned flags)
2036b5c29a34SFrançois Tigeot {
2037b5c29a34SFrançois Tigeot 	int ret;
2038b5c29a34SFrançois Tigeot 
2039b5c29a34SFrançois Tigeot 	ret = intel_ring_begin(ring, 2);
2040b5c29a34SFrançois Tigeot 	if (ret)
2041b5c29a34SFrançois Tigeot 		return ret;
2042b5c29a34SFrançois Tigeot 
2043b5c29a34SFrançois Tigeot 	intel_ring_emit(ring,
2044b5c29a34SFrançois Tigeot 			MI_BATCH_BUFFER_START |
2045b5c29a34SFrançois Tigeot 			(flags & I915_DISPATCH_SECURE ? 0 : MI_BATCH_NON_SECURE_I965));
2046e3adcf8fSFrançois Tigeot 	/* bit0-7 is the length on GEN6+ */
2047e3adcf8fSFrançois Tigeot 	intel_ring_emit(ring, offset);
2048e3adcf8fSFrançois Tigeot 	intel_ring_advance(ring);
2049e3adcf8fSFrançois Tigeot 
2050e3adcf8fSFrançois Tigeot 	return 0;
2051e3adcf8fSFrançois Tigeot }
2052e3adcf8fSFrançois Tigeot 
2053e3adcf8fSFrançois Tigeot /* Blitter support (SandyBridge+) */
2054e3adcf8fSFrançois Tigeot 
2055ba55f2f5SFrançois Tigeot static int gen6_ring_flush(struct intel_engine_cs *ring,
2056b5c29a34SFrançois Tigeot 			   u32 invalidate, u32 flush)
2057e3adcf8fSFrançois Tigeot {
20585d0b1887SFrançois Tigeot 	struct drm_device *dev = ring->dev;
2059e3adcf8fSFrançois Tigeot 	uint32_t cmd;
2060e3adcf8fSFrançois Tigeot 	int ret;
2061e3adcf8fSFrançois Tigeot 
2062e3adcf8fSFrançois Tigeot 	ret = intel_ring_begin(ring, 4);
2063e3adcf8fSFrançois Tigeot 	if (ret)
2064e3adcf8fSFrançois Tigeot 		return ret;
2065e3adcf8fSFrançois Tigeot 
2066e3adcf8fSFrançois Tigeot 	cmd = MI_FLUSH_DW;
20679edbd4a0SFrançois Tigeot 	if (INTEL_INFO(ring->dev)->gen >= 8)
20689edbd4a0SFrançois Tigeot 		cmd += 1;
2069b5c29a34SFrançois Tigeot 	/*
2070b5c29a34SFrançois Tigeot 	 * Bspec vol 1c.3 - blitter engine command streamer:
2071b5c29a34SFrançois Tigeot 	 * "If ENABLED, all TLBs will be invalidated once the flush
2072b5c29a34SFrançois Tigeot 	 * operation is complete. This bit is only valid when the
2073b5c29a34SFrançois Tigeot 	 * Post-Sync Operation field is a value of 1h or 3h."
2074b5c29a34SFrançois Tigeot 	 */
2075e3adcf8fSFrançois Tigeot 	if (invalidate & I915_GEM_DOMAIN_RENDER)
2076b5c29a34SFrançois Tigeot 		cmd |= MI_INVALIDATE_TLB | MI_FLUSH_DW_STORE_INDEX |
2077b5c29a34SFrançois Tigeot 			MI_FLUSH_DW_OP_STOREDW;
2078e3adcf8fSFrançois Tigeot 	intel_ring_emit(ring, cmd);
2079b5c29a34SFrançois Tigeot 	intel_ring_emit(ring, I915_GEM_HWS_SCRATCH_ADDR | MI_FLUSH_DW_USE_GTT);
20809edbd4a0SFrançois Tigeot 	if (INTEL_INFO(ring->dev)->gen >= 8) {
20819edbd4a0SFrançois Tigeot 		intel_ring_emit(ring, 0); /* upper addr */
20829edbd4a0SFrançois Tigeot 		intel_ring_emit(ring, 0); /* value */
20839edbd4a0SFrançois Tigeot 	} else  {
2084e3adcf8fSFrançois Tigeot 		intel_ring_emit(ring, 0);
2085e3adcf8fSFrançois Tigeot 		intel_ring_emit(ring, MI_NOOP);
20869edbd4a0SFrançois Tigeot 	}
2087e3adcf8fSFrançois Tigeot 	intel_ring_advance(ring);
20885d0b1887SFrançois Tigeot 
20899edbd4a0SFrançois Tigeot 	if (IS_GEN7(dev) && !invalidate && flush)
20905d0b1887SFrançois Tigeot 		return gen7_ring_fbc_flush(ring, FBC_REND_CACHE_CLEAN);
20915d0b1887SFrançois Tigeot 
2092e3adcf8fSFrançois Tigeot 	return 0;
2093e3adcf8fSFrançois Tigeot }
2094e3adcf8fSFrançois Tigeot 
2095e3adcf8fSFrançois Tigeot int intel_init_render_ring_buffer(struct drm_device *dev)
2096e3adcf8fSFrançois Tigeot {
2097ba55f2f5SFrançois Tigeot 	struct drm_i915_private *dev_priv = dev->dev_private;
2098ba55f2f5SFrançois Tigeot 	struct intel_engine_cs *ring = &dev_priv->ring[RCS];
2099*24edb884SFrançois Tigeot 	struct drm_i915_gem_object *obj;
2100*24edb884SFrançois Tigeot 	int ret;
2101e3adcf8fSFrançois Tigeot 
2102686a02f1SFrançois Tigeot 	ring->name = "render ring";
2103686a02f1SFrançois Tigeot 	ring->id = RCS;
2104686a02f1SFrançois Tigeot 	ring->mmio_base = RENDER_RING_BASE;
2105686a02f1SFrançois Tigeot 
2106*24edb884SFrançois Tigeot 	if (INTEL_INFO(dev)->gen >= 8) {
2107*24edb884SFrançois Tigeot 		if (i915_semaphore_is_enabled(dev)) {
2108*24edb884SFrançois Tigeot 			obj = i915_gem_alloc_object(dev, 4096);
2109*24edb884SFrançois Tigeot 			if (obj == NULL) {
2110*24edb884SFrançois Tigeot 				DRM_ERROR("Failed to allocate semaphore bo. Disabling semaphores\n");
2111*24edb884SFrançois Tigeot 				i915.semaphores = 0;
2112*24edb884SFrançois Tigeot 			} else {
2113*24edb884SFrançois Tigeot 				i915_gem_object_set_cache_level(obj, I915_CACHE_LLC);
2114*24edb884SFrançois Tigeot 				ret = i915_gem_obj_ggtt_pin(obj, 0, PIN_NONBLOCK);
2115*24edb884SFrançois Tigeot 				if (ret != 0) {
2116*24edb884SFrançois Tigeot 					drm_gem_object_unreference(&obj->base);
2117*24edb884SFrançois Tigeot 					DRM_ERROR("Failed to pin semaphore bo. Disabling semaphores\n");
2118*24edb884SFrançois Tigeot 					i915.semaphores = 0;
2119*24edb884SFrançois Tigeot 				} else
2120*24edb884SFrançois Tigeot 					dev_priv->semaphore_obj = obj;
2121*24edb884SFrançois Tigeot 			}
2122*24edb884SFrançois Tigeot 		}
2123*24edb884SFrançois Tigeot 		ring->add_request = gen6_add_request;
2124*24edb884SFrançois Tigeot 		ring->flush = gen8_render_ring_flush;
2125*24edb884SFrançois Tigeot 		ring->irq_get = gen8_ring_get_irq;
2126*24edb884SFrançois Tigeot 		ring->irq_put = gen8_ring_put_irq;
2127*24edb884SFrançois Tigeot 		ring->irq_enable_mask = GT_RENDER_USER_INTERRUPT;
2128*24edb884SFrançois Tigeot 		ring->get_seqno = gen6_ring_get_seqno;
2129*24edb884SFrançois Tigeot 		ring->set_seqno = ring_set_seqno;
2130*24edb884SFrançois Tigeot 		if (i915_semaphore_is_enabled(dev)) {
2131*24edb884SFrançois Tigeot 			WARN_ON(!dev_priv->semaphore_obj);
2132*24edb884SFrançois Tigeot 			ring->semaphore.sync_to = gen8_ring_sync;
2133*24edb884SFrançois Tigeot 			ring->semaphore.signal = gen8_rcs_signal;
2134*24edb884SFrançois Tigeot 			GEN8_RING_SEMAPHORE_INIT;
2135*24edb884SFrançois Tigeot 		}
2136*24edb884SFrançois Tigeot 	} else if (INTEL_INFO(dev)->gen >= 6) {
2137e3adcf8fSFrançois Tigeot 		ring->add_request = gen6_add_request;
2138b5c29a34SFrançois Tigeot 		ring->flush = gen7_render_ring_flush;
2139b5c29a34SFrançois Tigeot 		if (INTEL_INFO(dev)->gen == 6)
2140e3adcf8fSFrançois Tigeot 			ring->flush = gen6_render_ring_flush;
2141686a02f1SFrançois Tigeot 		ring->irq_get = gen6_ring_get_irq;
2142686a02f1SFrançois Tigeot 		ring->irq_put = gen6_ring_put_irq;
21435d0b1887SFrançois Tigeot 		ring->irq_enable_mask = GT_RENDER_USER_INTERRUPT;
2144e3adcf8fSFrançois Tigeot 		ring->get_seqno = gen6_ring_get_seqno;
2145a2fdbec6SFrançois Tigeot 		ring->set_seqno = ring_set_seqno;
2146*24edb884SFrançois Tigeot 		if (i915_semaphore_is_enabled(dev)) {
2147ba55f2f5SFrançois Tigeot 			ring->semaphore.sync_to = gen6_ring_sync;
2148ba55f2f5SFrançois Tigeot 			ring->semaphore.signal = gen6_signal;
2149ba55f2f5SFrançois Tigeot 			/*
2150*24edb884SFrançois Tigeot 			 * The current semaphore is only applied on pre-gen8
2151*24edb884SFrançois Tigeot 			 * platform.  And there is no VCS2 ring on the pre-gen8
2152*24edb884SFrançois Tigeot 			 * platform. So the semaphore between RCS and VCS2 is
2153*24edb884SFrançois Tigeot 			 * initialized as INVALID.  Gen8 will initialize the
2154*24edb884SFrançois Tigeot 			 * sema between VCS2 and RCS later.
2155ba55f2f5SFrançois Tigeot 			 */
2156ba55f2f5SFrançois Tigeot 			ring->semaphore.mbox.wait[RCS] = MI_SEMAPHORE_SYNC_INVALID;
2157ba55f2f5SFrançois Tigeot 			ring->semaphore.mbox.wait[VCS] = MI_SEMAPHORE_SYNC_RV;
2158ba55f2f5SFrançois Tigeot 			ring->semaphore.mbox.wait[BCS] = MI_SEMAPHORE_SYNC_RB;
2159ba55f2f5SFrançois Tigeot 			ring->semaphore.mbox.wait[VECS] = MI_SEMAPHORE_SYNC_RVE;
2160ba55f2f5SFrançois Tigeot 			ring->semaphore.mbox.wait[VCS2] = MI_SEMAPHORE_SYNC_INVALID;
2161ba55f2f5SFrançois Tigeot 			ring->semaphore.mbox.signal[RCS] = GEN6_NOSYNC;
2162ba55f2f5SFrançois Tigeot 			ring->semaphore.mbox.signal[VCS] = GEN6_VRSYNC;
2163ba55f2f5SFrançois Tigeot 			ring->semaphore.mbox.signal[BCS] = GEN6_BRSYNC;
2164ba55f2f5SFrançois Tigeot 			ring->semaphore.mbox.signal[VECS] = GEN6_VERSYNC;
2165ba55f2f5SFrançois Tigeot 			ring->semaphore.mbox.signal[VCS2] = GEN6_NOSYNC;
2166*24edb884SFrançois Tigeot 		}
2167e3adcf8fSFrançois Tigeot 	} else if (IS_GEN5(dev)) {
2168e3adcf8fSFrançois Tigeot 		ring->add_request = pc_render_add_request;
2169686a02f1SFrançois Tigeot 		ring->flush = gen4_render_ring_flush;
2170e3adcf8fSFrançois Tigeot 		ring->get_seqno = pc_render_get_seqno;
2171a2fdbec6SFrançois Tigeot 		ring->set_seqno = pc_render_set_seqno;
2172686a02f1SFrançois Tigeot 		ring->irq_get = gen5_ring_get_irq;
2173686a02f1SFrançois Tigeot 		ring->irq_put = gen5_ring_put_irq;
21745d0b1887SFrançois Tigeot 		ring->irq_enable_mask = GT_RENDER_USER_INTERRUPT |
21755d0b1887SFrançois Tigeot 					GT_RENDER_PIPECTL_NOTIFY_INTERRUPT;
2176686a02f1SFrançois Tigeot 	} else {
2177686a02f1SFrançois Tigeot 		ring->add_request = i9xx_add_request;
2178686a02f1SFrançois Tigeot 		if (INTEL_INFO(dev)->gen < 4)
2179686a02f1SFrançois Tigeot 			ring->flush = gen2_render_ring_flush;
2180686a02f1SFrançois Tigeot 		else
2181686a02f1SFrançois Tigeot 			ring->flush = gen4_render_ring_flush;
2182686a02f1SFrançois Tigeot 		ring->get_seqno = ring_get_seqno;
2183a2fdbec6SFrançois Tigeot 		ring->set_seqno = ring_set_seqno;
2184686a02f1SFrançois Tigeot 		if (IS_GEN2(dev)) {
2185686a02f1SFrançois Tigeot 			ring->irq_get = i8xx_ring_get_irq;
2186686a02f1SFrançois Tigeot 			ring->irq_put = i8xx_ring_put_irq;
2187686a02f1SFrançois Tigeot 		} else {
2188686a02f1SFrançois Tigeot 			ring->irq_get = i9xx_ring_get_irq;
2189686a02f1SFrançois Tigeot 			ring->irq_put = i9xx_ring_put_irq;
2190e3adcf8fSFrançois Tigeot 		}
2191686a02f1SFrançois Tigeot 		ring->irq_enable_mask = I915_USER_INTERRUPT;
2192686a02f1SFrançois Tigeot 	}
2193686a02f1SFrançois Tigeot 	ring->write_tail = ring_write_tail;
2194*24edb884SFrançois Tigeot 
2195b5c29a34SFrançois Tigeot 	if (IS_HASWELL(dev))
2196b5c29a34SFrançois Tigeot 		ring->dispatch_execbuffer = hsw_ring_dispatch_execbuffer;
21979edbd4a0SFrançois Tigeot 	else if (IS_GEN8(dev))
21989edbd4a0SFrançois Tigeot 		ring->dispatch_execbuffer = gen8_ring_dispatch_execbuffer;
2199b5c29a34SFrançois Tigeot 	else if (INTEL_INFO(dev)->gen >= 6)
2200686a02f1SFrançois Tigeot 		ring->dispatch_execbuffer = gen6_ring_dispatch_execbuffer;
2201686a02f1SFrançois Tigeot 	else if (INTEL_INFO(dev)->gen >= 4)
2202686a02f1SFrançois Tigeot 		ring->dispatch_execbuffer = i965_dispatch_execbuffer;
2203686a02f1SFrançois Tigeot 	else if (IS_I830(dev) || IS_845G(dev))
2204686a02f1SFrançois Tigeot 		ring->dispatch_execbuffer = i830_dispatch_execbuffer;
2205686a02f1SFrançois Tigeot 	else
2206686a02f1SFrançois Tigeot 		ring->dispatch_execbuffer = i915_dispatch_execbuffer;
2207686a02f1SFrançois Tigeot 	ring->init = init_render_ring;
2208686a02f1SFrançois Tigeot 	ring->cleanup = render_ring_cleanup;
2209e3adcf8fSFrançois Tigeot 
2210b5c29a34SFrançois Tigeot 	/* Workaround batchbuffer to combat CS tlb bug. */
2211b5c29a34SFrançois Tigeot 	if (HAS_BROKEN_CS_TLB(dev)) {
2212*24edb884SFrançois Tigeot 		obj = i915_gem_alloc_object(dev, I830_WA_SIZE);
2213b5c29a34SFrançois Tigeot 		if (obj == NULL) {
2214b5c29a34SFrançois Tigeot 			DRM_ERROR("Failed to allocate batch bo\n");
2215b5c29a34SFrançois Tigeot 			return -ENOMEM;
2216b5c29a34SFrançois Tigeot 		}
2217b5c29a34SFrançois Tigeot 
2218ba55f2f5SFrançois Tigeot 		ret = i915_gem_obj_ggtt_pin(obj, 0, 0);
2219b5c29a34SFrançois Tigeot 		if (ret != 0) {
2220b5c29a34SFrançois Tigeot 			drm_gem_object_unreference(&obj->base);
2221b5c29a34SFrançois Tigeot 			DRM_ERROR("Failed to ping batch bo\n");
2222b5c29a34SFrançois Tigeot 			return ret;
2223b5c29a34SFrançois Tigeot 		}
2224b5c29a34SFrançois Tigeot 
22259edbd4a0SFrançois Tigeot 		ring->scratch.obj = obj;
22269edbd4a0SFrançois Tigeot 		ring->scratch.gtt_offset = i915_gem_obj_ggtt_offset(obj);
2227e3adcf8fSFrançois Tigeot 	}
2228e3adcf8fSFrançois Tigeot 
2229e3adcf8fSFrançois Tigeot 	return intel_init_ring_buffer(dev, ring);
2230e3adcf8fSFrançois Tigeot }
2231e3adcf8fSFrançois Tigeot 
2232686a02f1SFrançois Tigeot int intel_render_ring_init_dri(struct drm_device *dev, u64 start, u32 size)
2233e3adcf8fSFrançois Tigeot {
2234ba55f2f5SFrançois Tigeot 	struct drm_i915_private *dev_priv = dev->dev_private;
2235ba55f2f5SFrançois Tigeot 	struct intel_engine_cs *ring = &dev_priv->ring[RCS];
2236ba55f2f5SFrançois Tigeot 	struct intel_ringbuffer *ringbuf = ring->buffer;
2237b5c29a34SFrançois Tigeot 	int ret;
2238e3adcf8fSFrançois Tigeot 
2239ba55f2f5SFrançois Tigeot 	if (ringbuf == NULL) {
2240ba55f2f5SFrançois Tigeot 		ringbuf = kzalloc(sizeof(*ringbuf), GFP_KERNEL);
2241ba55f2f5SFrançois Tigeot 		if (!ringbuf)
2242ba55f2f5SFrançois Tigeot 			return -ENOMEM;
2243ba55f2f5SFrançois Tigeot 		ring->buffer = ringbuf;
2244ba55f2f5SFrançois Tigeot 	}
2245ba55f2f5SFrançois Tigeot 
2246686a02f1SFrançois Tigeot 	ring->name = "render ring";
2247686a02f1SFrançois Tigeot 	ring->id = RCS;
2248686a02f1SFrançois Tigeot 	ring->mmio_base = RENDER_RING_BASE;
2249686a02f1SFrançois Tigeot 
2250e3adcf8fSFrançois Tigeot 	if (INTEL_INFO(dev)->gen >= 6) {
2251686a02f1SFrançois Tigeot 		/* non-kms not supported on gen6+ */
2252ba55f2f5SFrançois Tigeot 		ret = -ENODEV;
2253ba55f2f5SFrançois Tigeot 		goto err_ringbuf;
2254e3adcf8fSFrançois Tigeot 	}
2255e3adcf8fSFrançois Tigeot 
2256686a02f1SFrançois Tigeot 	/* Note: gem is not supported on gen5/ilk without kms (the corresponding
2257686a02f1SFrançois Tigeot 	 * gem_init ioctl returns with -ENODEV). Hence we do not need to set up
2258686a02f1SFrançois Tigeot 	 * the special gen5 functions. */
2259686a02f1SFrançois Tigeot 	ring->add_request = i9xx_add_request;
2260686a02f1SFrançois Tigeot 	if (INTEL_INFO(dev)->gen < 4)
2261686a02f1SFrançois Tigeot 		ring->flush = gen2_render_ring_flush;
2262686a02f1SFrançois Tigeot 	else
2263686a02f1SFrançois Tigeot 		ring->flush = gen4_render_ring_flush;
2264686a02f1SFrançois Tigeot 	ring->get_seqno = ring_get_seqno;
2265a2fdbec6SFrançois Tigeot 	ring->set_seqno = ring_set_seqno;
2266686a02f1SFrançois Tigeot 	if (IS_GEN2(dev)) {
2267686a02f1SFrançois Tigeot 		ring->irq_get = i8xx_ring_get_irq;
2268686a02f1SFrançois Tigeot 		ring->irq_put = i8xx_ring_put_irq;
2269686a02f1SFrançois Tigeot 	} else {
2270686a02f1SFrançois Tigeot 		ring->irq_get = i9xx_ring_get_irq;
2271686a02f1SFrançois Tigeot 		ring->irq_put = i9xx_ring_put_irq;
2272686a02f1SFrançois Tigeot 	}
2273686a02f1SFrançois Tigeot 	ring->irq_enable_mask = I915_USER_INTERRUPT;
2274686a02f1SFrançois Tigeot 	ring->write_tail = ring_write_tail;
2275686a02f1SFrançois Tigeot 	if (INTEL_INFO(dev)->gen >= 4)
2276686a02f1SFrançois Tigeot 		ring->dispatch_execbuffer = i965_dispatch_execbuffer;
2277686a02f1SFrançois Tigeot 	else if (IS_I830(dev) || IS_845G(dev))
2278686a02f1SFrançois Tigeot 		ring->dispatch_execbuffer = i830_dispatch_execbuffer;
2279686a02f1SFrançois Tigeot 	else
2280686a02f1SFrançois Tigeot 		ring->dispatch_execbuffer = i915_dispatch_execbuffer;
2281686a02f1SFrançois Tigeot 	ring->init = init_render_ring;
2282686a02f1SFrançois Tigeot 	ring->cleanup = render_ring_cleanup;
2283686a02f1SFrançois Tigeot 
2284e3adcf8fSFrançois Tigeot 	ring->dev = dev;
2285e3adcf8fSFrançois Tigeot 	INIT_LIST_HEAD(&ring->active_list);
2286e3adcf8fSFrançois Tigeot 	INIT_LIST_HEAD(&ring->request_list);
2287e3adcf8fSFrançois Tigeot 
2288ba55f2f5SFrançois Tigeot 	ringbuf->size = size;
2289ba55f2f5SFrançois Tigeot 	ringbuf->effective_size = ringbuf->size;
2290b5c29a34SFrançois Tigeot 	if (IS_I830(ring->dev) || IS_845G(ring->dev))
2291ba55f2f5SFrançois Tigeot 		ringbuf->effective_size -= 2 * CACHELINE_BYTES;
2292e3adcf8fSFrançois Tigeot 
2293ba55f2f5SFrançois Tigeot 	ringbuf->virtual_start = ioremap_wc(start, size);
2294ba55f2f5SFrançois Tigeot 	if (ringbuf->virtual_start == NULL) {
2295e3adcf8fSFrançois Tigeot 		DRM_ERROR("can not ioremap virtual address for"
2296e3adcf8fSFrançois Tigeot 			  " ring buffer\n");
2297ba55f2f5SFrançois Tigeot 		ret = -ENOMEM;
2298ba55f2f5SFrançois Tigeot 		goto err_ringbuf;
2299e3adcf8fSFrançois Tigeot 	}
2300e3adcf8fSFrançois Tigeot 
2301b5c29a34SFrançois Tigeot 	if (!I915_NEED_GFX_HWS(dev)) {
23025d0b1887SFrançois Tigeot 		ret = init_phys_status_page(ring);
2303b5c29a34SFrançois Tigeot 		if (ret)
2304ba55f2f5SFrançois Tigeot 			goto err_vstart;
2305b5c29a34SFrançois Tigeot 	}
2306b5c29a34SFrançois Tigeot 
2307e3adcf8fSFrançois Tigeot 	return 0;
2308ba55f2f5SFrançois Tigeot 
2309ba55f2f5SFrançois Tigeot err_vstart:
2310ba55f2f5SFrançois Tigeot 	pmap_unmapdev((vm_offset_t)ring->buffer->virtual_start, size);
2311ba55f2f5SFrançois Tigeot err_ringbuf:
2312ba55f2f5SFrançois Tigeot 	kfree(ringbuf);
2313ba55f2f5SFrançois Tigeot 	ring->buffer = NULL;
2314ba55f2f5SFrançois Tigeot 	return ret;
2315e3adcf8fSFrançois Tigeot }
2316e3adcf8fSFrançois Tigeot 
2317e3adcf8fSFrançois Tigeot int intel_init_bsd_ring_buffer(struct drm_device *dev)
2318e3adcf8fSFrançois Tigeot {
2319ba55f2f5SFrançois Tigeot 	struct drm_i915_private *dev_priv = dev->dev_private;
2320ba55f2f5SFrançois Tigeot 	struct intel_engine_cs *ring = &dev_priv->ring[VCS];
2321e3adcf8fSFrançois Tigeot 
2322686a02f1SFrançois Tigeot 	ring->name = "bsd ring";
2323686a02f1SFrançois Tigeot 	ring->id = VCS;
2324686a02f1SFrançois Tigeot 
2325686a02f1SFrançois Tigeot 	ring->write_tail = ring_write_tail;
23269edbd4a0SFrançois Tigeot 	if (INTEL_INFO(dev)->gen >= 6) {
2327686a02f1SFrançois Tigeot 		ring->mmio_base = GEN6_BSD_RING_BASE;
2328686a02f1SFrançois Tigeot 		/* gen6 bsd needs a special wa for tail updates */
2329686a02f1SFrançois Tigeot 		if (IS_GEN6(dev))
2330686a02f1SFrançois Tigeot 			ring->write_tail = gen6_bsd_ring_write_tail;
23315d0b1887SFrançois Tigeot 		ring->flush = gen6_bsd_ring_flush;
2332686a02f1SFrançois Tigeot 		ring->add_request = gen6_add_request;
2333686a02f1SFrançois Tigeot 		ring->get_seqno = gen6_ring_get_seqno;
2334a2fdbec6SFrançois Tigeot 		ring->set_seqno = ring_set_seqno;
23359edbd4a0SFrançois Tigeot 		if (INTEL_INFO(dev)->gen >= 8) {
23369edbd4a0SFrançois Tigeot 			ring->irq_enable_mask =
23379edbd4a0SFrançois Tigeot 				GT_RENDER_USER_INTERRUPT << GEN8_VCS1_IRQ_SHIFT;
23389edbd4a0SFrançois Tigeot 			ring->irq_get = gen8_ring_get_irq;
23399edbd4a0SFrançois Tigeot 			ring->irq_put = gen8_ring_put_irq;
23409edbd4a0SFrançois Tigeot 			ring->dispatch_execbuffer =
23419edbd4a0SFrançois Tigeot 				gen8_ring_dispatch_execbuffer;
2342*24edb884SFrançois Tigeot 			if (i915_semaphore_is_enabled(dev)) {
2343*24edb884SFrançois Tigeot 				ring->semaphore.sync_to = gen8_ring_sync;
2344*24edb884SFrançois Tigeot 				ring->semaphore.signal = gen8_xcs_signal;
2345*24edb884SFrançois Tigeot 				GEN8_RING_SEMAPHORE_INIT;
2346*24edb884SFrançois Tigeot 			}
23479edbd4a0SFrançois Tigeot 		} else {
23485d0b1887SFrançois Tigeot 			ring->irq_enable_mask = GT_BSD_USER_INTERRUPT;
2349686a02f1SFrançois Tigeot 			ring->irq_get = gen6_ring_get_irq;
2350686a02f1SFrançois Tigeot 			ring->irq_put = gen6_ring_put_irq;
23519edbd4a0SFrançois Tigeot 			ring->dispatch_execbuffer =
23529edbd4a0SFrançois Tigeot 				gen6_ring_dispatch_execbuffer;
2353*24edb884SFrançois Tigeot 			if (i915_semaphore_is_enabled(dev)) {
2354ba55f2f5SFrançois Tigeot 				ring->semaphore.sync_to = gen6_ring_sync;
2355ba55f2f5SFrançois Tigeot 				ring->semaphore.signal = gen6_signal;
2356ba55f2f5SFrançois Tigeot 				ring->semaphore.mbox.wait[RCS] = MI_SEMAPHORE_SYNC_VR;
2357ba55f2f5SFrançois Tigeot 				ring->semaphore.mbox.wait[VCS] = MI_SEMAPHORE_SYNC_INVALID;
2358ba55f2f5SFrançois Tigeot 				ring->semaphore.mbox.wait[BCS] = MI_SEMAPHORE_SYNC_VB;
2359ba55f2f5SFrançois Tigeot 				ring->semaphore.mbox.wait[VECS] = MI_SEMAPHORE_SYNC_VVE;
2360ba55f2f5SFrançois Tigeot 				ring->semaphore.mbox.wait[VCS2] = MI_SEMAPHORE_SYNC_INVALID;
2361ba55f2f5SFrançois Tigeot 				ring->semaphore.mbox.signal[RCS] = GEN6_RVSYNC;
2362ba55f2f5SFrançois Tigeot 				ring->semaphore.mbox.signal[VCS] = GEN6_NOSYNC;
2363ba55f2f5SFrançois Tigeot 				ring->semaphore.mbox.signal[BCS] = GEN6_BVSYNC;
2364ba55f2f5SFrançois Tigeot 				ring->semaphore.mbox.signal[VECS] = GEN6_VEVSYNC;
2365ba55f2f5SFrançois Tigeot 				ring->semaphore.mbox.signal[VCS2] = GEN6_NOSYNC;
2366*24edb884SFrançois Tigeot 			}
2367*24edb884SFrançois Tigeot 		}
2368686a02f1SFrançois Tigeot 	} else {
2369686a02f1SFrançois Tigeot 		ring->mmio_base = BSD_RING_BASE;
2370686a02f1SFrançois Tigeot 		ring->flush = bsd_ring_flush;
2371686a02f1SFrançois Tigeot 		ring->add_request = i9xx_add_request;
2372686a02f1SFrançois Tigeot 		ring->get_seqno = ring_get_seqno;
2373a2fdbec6SFrançois Tigeot 		ring->set_seqno = ring_set_seqno;
2374686a02f1SFrançois Tigeot 		if (IS_GEN5(dev)) {
23755d0b1887SFrançois Tigeot 			ring->irq_enable_mask = ILK_BSD_USER_INTERRUPT;
2376686a02f1SFrançois Tigeot 			ring->irq_get = gen5_ring_get_irq;
2377686a02f1SFrançois Tigeot 			ring->irq_put = gen5_ring_put_irq;
2378686a02f1SFrançois Tigeot 		} else {
2379686a02f1SFrançois Tigeot 			ring->irq_enable_mask = I915_BSD_USER_INTERRUPT;
2380686a02f1SFrançois Tigeot 			ring->irq_get = i9xx_ring_get_irq;
2381686a02f1SFrançois Tigeot 			ring->irq_put = i9xx_ring_put_irq;
2382686a02f1SFrançois Tigeot 		}
2383686a02f1SFrançois Tigeot 		ring->dispatch_execbuffer = i965_dispatch_execbuffer;
2384686a02f1SFrançois Tigeot 	}
2385686a02f1SFrançois Tigeot 	ring->init = init_ring_common;
2386e3adcf8fSFrançois Tigeot 
2387e3adcf8fSFrançois Tigeot 	return intel_init_ring_buffer(dev, ring);
2388e3adcf8fSFrançois Tigeot }
2389e3adcf8fSFrançois Tigeot 
2390ba55f2f5SFrançois Tigeot /**
2391ba55f2f5SFrançois Tigeot  * Initialize the second BSD ring for Broadwell GT3.
2392ba55f2f5SFrançois Tigeot  * It is noted that this only exists on Broadwell GT3.
2393ba55f2f5SFrançois Tigeot  */
2394ba55f2f5SFrançois Tigeot int intel_init_bsd2_ring_buffer(struct drm_device *dev)
2395ba55f2f5SFrançois Tigeot {
2396ba55f2f5SFrançois Tigeot 	struct drm_i915_private *dev_priv = dev->dev_private;
2397ba55f2f5SFrançois Tigeot 	struct intel_engine_cs *ring = &dev_priv->ring[VCS2];
2398ba55f2f5SFrançois Tigeot 
2399ba55f2f5SFrançois Tigeot 	if ((INTEL_INFO(dev)->gen != 8)) {
2400ba55f2f5SFrançois Tigeot 		DRM_ERROR("No dual-BSD ring on non-BDW machine\n");
2401ba55f2f5SFrançois Tigeot 		return -EINVAL;
2402ba55f2f5SFrançois Tigeot 	}
2403ba55f2f5SFrançois Tigeot 
2404*24edb884SFrançois Tigeot 	ring->name = "bsd2 ring";
2405ba55f2f5SFrançois Tigeot 	ring->id = VCS2;
2406ba55f2f5SFrançois Tigeot 
2407ba55f2f5SFrançois Tigeot 	ring->write_tail = ring_write_tail;
2408ba55f2f5SFrançois Tigeot 	ring->mmio_base = GEN8_BSD2_RING_BASE;
2409ba55f2f5SFrançois Tigeot 	ring->flush = gen6_bsd_ring_flush;
2410ba55f2f5SFrançois Tigeot 	ring->add_request = gen6_add_request;
2411ba55f2f5SFrançois Tigeot 	ring->get_seqno = gen6_ring_get_seqno;
2412ba55f2f5SFrançois Tigeot 	ring->set_seqno = ring_set_seqno;
2413ba55f2f5SFrançois Tigeot 	ring->irq_enable_mask =
2414ba55f2f5SFrançois Tigeot 			GT_RENDER_USER_INTERRUPT << GEN8_VCS2_IRQ_SHIFT;
2415ba55f2f5SFrançois Tigeot 	ring->irq_get = gen8_ring_get_irq;
2416ba55f2f5SFrançois Tigeot 	ring->irq_put = gen8_ring_put_irq;
2417ba55f2f5SFrançois Tigeot 	ring->dispatch_execbuffer =
2418ba55f2f5SFrançois Tigeot 			gen8_ring_dispatch_execbuffer;
2419*24edb884SFrançois Tigeot 	if (i915_semaphore_is_enabled(dev)) {
2420*24edb884SFrançois Tigeot 		ring->semaphore.sync_to = gen8_ring_sync;
2421*24edb884SFrançois Tigeot 		ring->semaphore.signal = gen8_xcs_signal;
2422*24edb884SFrançois Tigeot 		GEN8_RING_SEMAPHORE_INIT;
2423*24edb884SFrançois Tigeot 	}
2424ba55f2f5SFrançois Tigeot 	ring->init = init_ring_common;
2425ba55f2f5SFrançois Tigeot 
2426ba55f2f5SFrançois Tigeot 	return intel_init_ring_buffer(dev, ring);
2427ba55f2f5SFrançois Tigeot }
2428ba55f2f5SFrançois Tigeot 
2429e3adcf8fSFrançois Tigeot int intel_init_blt_ring_buffer(struct drm_device *dev)
2430e3adcf8fSFrançois Tigeot {
2431ba55f2f5SFrançois Tigeot 	struct drm_i915_private *dev_priv = dev->dev_private;
2432ba55f2f5SFrançois Tigeot 	struct intel_engine_cs *ring = &dev_priv->ring[BCS];
2433e3adcf8fSFrançois Tigeot 
2434686a02f1SFrançois Tigeot 	ring->name = "blitter ring";
2435686a02f1SFrançois Tigeot 	ring->id = BCS;
2436686a02f1SFrançois Tigeot 
2437686a02f1SFrançois Tigeot 	ring->mmio_base = BLT_RING_BASE;
2438686a02f1SFrançois Tigeot 	ring->write_tail = ring_write_tail;
24395d0b1887SFrançois Tigeot 	ring->flush = gen6_ring_flush;
2440686a02f1SFrançois Tigeot 	ring->add_request = gen6_add_request;
2441686a02f1SFrançois Tigeot 	ring->get_seqno = gen6_ring_get_seqno;
2442a2fdbec6SFrançois Tigeot 	ring->set_seqno = ring_set_seqno;
24439edbd4a0SFrançois Tigeot 	if (INTEL_INFO(dev)->gen >= 8) {
24449edbd4a0SFrançois Tigeot 		ring->irq_enable_mask =
24459edbd4a0SFrançois Tigeot 			GT_RENDER_USER_INTERRUPT << GEN8_BCS_IRQ_SHIFT;
24469edbd4a0SFrançois Tigeot 		ring->irq_get = gen8_ring_get_irq;
24479edbd4a0SFrançois Tigeot 		ring->irq_put = gen8_ring_put_irq;
24489edbd4a0SFrançois Tigeot 		ring->dispatch_execbuffer = gen8_ring_dispatch_execbuffer;
2449*24edb884SFrançois Tigeot 		if (i915_semaphore_is_enabled(dev)) {
2450*24edb884SFrançois Tigeot 			ring->semaphore.sync_to = gen8_ring_sync;
2451*24edb884SFrançois Tigeot 			ring->semaphore.signal = gen8_xcs_signal;
2452*24edb884SFrançois Tigeot 			GEN8_RING_SEMAPHORE_INIT;
2453*24edb884SFrançois Tigeot 		}
24549edbd4a0SFrançois Tigeot 	} else {
24555d0b1887SFrançois Tigeot 		ring->irq_enable_mask = GT_BLT_USER_INTERRUPT;
2456686a02f1SFrançois Tigeot 		ring->irq_get = gen6_ring_get_irq;
2457686a02f1SFrançois Tigeot 		ring->irq_put = gen6_ring_put_irq;
2458686a02f1SFrançois Tigeot 		ring->dispatch_execbuffer = gen6_ring_dispatch_execbuffer;
2459*24edb884SFrançois Tigeot 		if (i915_semaphore_is_enabled(dev)) {
2460ba55f2f5SFrançois Tigeot 			ring->semaphore.signal = gen6_signal;
2461*24edb884SFrançois Tigeot 			ring->semaphore.sync_to = gen6_ring_sync;
2462ba55f2f5SFrançois Tigeot 			/*
2463*24edb884SFrançois Tigeot 			 * The current semaphore is only applied on pre-gen8
2464*24edb884SFrançois Tigeot 			 * platform.  And there is no VCS2 ring on the pre-gen8
2465*24edb884SFrançois Tigeot 			 * platform. So the semaphore between BCS and VCS2 is
2466*24edb884SFrançois Tigeot 			 * initialized as INVALID.  Gen8 will initialize the
2467*24edb884SFrançois Tigeot 			 * sema between BCS and VCS2 later.
2468ba55f2f5SFrançois Tigeot 			 */
2469ba55f2f5SFrançois Tigeot 			ring->semaphore.mbox.wait[RCS] = MI_SEMAPHORE_SYNC_BR;
2470ba55f2f5SFrançois Tigeot 			ring->semaphore.mbox.wait[VCS] = MI_SEMAPHORE_SYNC_BV;
2471ba55f2f5SFrançois Tigeot 			ring->semaphore.mbox.wait[BCS] = MI_SEMAPHORE_SYNC_INVALID;
2472ba55f2f5SFrançois Tigeot 			ring->semaphore.mbox.wait[VECS] = MI_SEMAPHORE_SYNC_BVE;
2473ba55f2f5SFrançois Tigeot 			ring->semaphore.mbox.wait[VCS2] = MI_SEMAPHORE_SYNC_INVALID;
2474ba55f2f5SFrançois Tigeot 			ring->semaphore.mbox.signal[RCS] = GEN6_RBSYNC;
2475ba55f2f5SFrançois Tigeot 			ring->semaphore.mbox.signal[VCS] = GEN6_VBSYNC;
2476ba55f2f5SFrançois Tigeot 			ring->semaphore.mbox.signal[BCS] = GEN6_NOSYNC;
2477ba55f2f5SFrançois Tigeot 			ring->semaphore.mbox.signal[VECS] = GEN6_VEBSYNC;
2478ba55f2f5SFrançois Tigeot 			ring->semaphore.mbox.signal[VCS2] = GEN6_NOSYNC;
2479*24edb884SFrançois Tigeot 		}
2480*24edb884SFrançois Tigeot 	}
24815d0b1887SFrançois Tigeot 	ring->init = init_ring_common;
24825d0b1887SFrançois Tigeot 
24835d0b1887SFrançois Tigeot 	return intel_init_ring_buffer(dev, ring);
24845d0b1887SFrançois Tigeot }
24855d0b1887SFrançois Tigeot 
24865d0b1887SFrançois Tigeot int intel_init_vebox_ring_buffer(struct drm_device *dev)
24875d0b1887SFrançois Tigeot {
2488ba55f2f5SFrançois Tigeot 	struct drm_i915_private *dev_priv = dev->dev_private;
2489ba55f2f5SFrançois Tigeot 	struct intel_engine_cs *ring = &dev_priv->ring[VECS];
24905d0b1887SFrançois Tigeot 
24915d0b1887SFrançois Tigeot 	ring->name = "video enhancement ring";
24925d0b1887SFrançois Tigeot 	ring->id = VECS;
24935d0b1887SFrançois Tigeot 
24945d0b1887SFrançois Tigeot 	ring->mmio_base = VEBOX_RING_BASE;
24955d0b1887SFrançois Tigeot 	ring->write_tail = ring_write_tail;
24965d0b1887SFrançois Tigeot 	ring->flush = gen6_ring_flush;
24975d0b1887SFrançois Tigeot 	ring->add_request = gen6_add_request;
24985d0b1887SFrançois Tigeot 	ring->get_seqno = gen6_ring_get_seqno;
24995d0b1887SFrançois Tigeot 	ring->set_seqno = ring_set_seqno;
25009edbd4a0SFrançois Tigeot 
25019edbd4a0SFrançois Tigeot 	if (INTEL_INFO(dev)->gen >= 8) {
25029edbd4a0SFrançois Tigeot 		ring->irq_enable_mask =
25039edbd4a0SFrançois Tigeot 			GT_RENDER_USER_INTERRUPT << GEN8_VECS_IRQ_SHIFT;
25049edbd4a0SFrançois Tigeot 		ring->irq_get = gen8_ring_get_irq;
25059edbd4a0SFrançois Tigeot 		ring->irq_put = gen8_ring_put_irq;
25069edbd4a0SFrançois Tigeot 		ring->dispatch_execbuffer = gen8_ring_dispatch_execbuffer;
2507*24edb884SFrançois Tigeot 		if (i915_semaphore_is_enabled(dev)) {
2508*24edb884SFrançois Tigeot 			ring->semaphore.sync_to = gen8_ring_sync;
2509*24edb884SFrançois Tigeot 			ring->semaphore.signal = gen8_xcs_signal;
2510*24edb884SFrançois Tigeot 			GEN8_RING_SEMAPHORE_INIT;
2511*24edb884SFrançois Tigeot 		}
25129edbd4a0SFrançois Tigeot 	} else {
25139edbd4a0SFrançois Tigeot 		ring->irq_enable_mask = PM_VEBOX_USER_INTERRUPT;
25145d0b1887SFrançois Tigeot 		ring->irq_get = hsw_vebox_get_irq;
25155d0b1887SFrançois Tigeot 		ring->irq_put = hsw_vebox_put_irq;
25165d0b1887SFrançois Tigeot 		ring->dispatch_execbuffer = gen6_ring_dispatch_execbuffer;
2517*24edb884SFrançois Tigeot 		if (i915_semaphore_is_enabled(dev)) {
2518ba55f2f5SFrançois Tigeot 			ring->semaphore.sync_to = gen6_ring_sync;
2519ba55f2f5SFrançois Tigeot 			ring->semaphore.signal = gen6_signal;
2520ba55f2f5SFrançois Tigeot 			ring->semaphore.mbox.wait[RCS] = MI_SEMAPHORE_SYNC_VER;
2521ba55f2f5SFrançois Tigeot 			ring->semaphore.mbox.wait[VCS] = MI_SEMAPHORE_SYNC_VEV;
2522ba55f2f5SFrançois Tigeot 			ring->semaphore.mbox.wait[BCS] = MI_SEMAPHORE_SYNC_VEB;
2523ba55f2f5SFrançois Tigeot 			ring->semaphore.mbox.wait[VECS] = MI_SEMAPHORE_SYNC_INVALID;
2524ba55f2f5SFrançois Tigeot 			ring->semaphore.mbox.wait[VCS2] = MI_SEMAPHORE_SYNC_INVALID;
2525ba55f2f5SFrançois Tigeot 			ring->semaphore.mbox.signal[RCS] = GEN6_RVESYNC;
2526ba55f2f5SFrançois Tigeot 			ring->semaphore.mbox.signal[VCS] = GEN6_VVESYNC;
2527ba55f2f5SFrançois Tigeot 			ring->semaphore.mbox.signal[BCS] = GEN6_BVESYNC;
2528ba55f2f5SFrançois Tigeot 			ring->semaphore.mbox.signal[VECS] = GEN6_NOSYNC;
2529ba55f2f5SFrançois Tigeot 			ring->semaphore.mbox.signal[VCS2] = GEN6_NOSYNC;
2530*24edb884SFrançois Tigeot 		}
2531*24edb884SFrançois Tigeot 	}
2532686a02f1SFrançois Tigeot 	ring->init = init_ring_common;
2533e3adcf8fSFrançois Tigeot 
2534e3adcf8fSFrançois Tigeot 	return intel_init_ring_buffer(dev, ring);
2535e3adcf8fSFrançois Tigeot }
2536b030f26bSFrançois Tigeot 
2537b030f26bSFrançois Tigeot int
2538ba55f2f5SFrançois Tigeot intel_ring_flush_all_caches(struct intel_engine_cs *ring)
2539b030f26bSFrançois Tigeot {
2540b030f26bSFrançois Tigeot 	int ret;
2541b030f26bSFrançois Tigeot 
2542b030f26bSFrançois Tigeot 	if (!ring->gpu_caches_dirty)
2543b030f26bSFrançois Tigeot 		return 0;
2544b030f26bSFrançois Tigeot 
2545b030f26bSFrançois Tigeot 	ret = ring->flush(ring, 0, I915_GEM_GPU_DOMAINS);
2546b030f26bSFrançois Tigeot 	if (ret)
2547b030f26bSFrançois Tigeot 		return ret;
2548b030f26bSFrançois Tigeot 
2549a2fdbec6SFrançois Tigeot 	trace_i915_gem_ring_flush(ring, 0, I915_GEM_GPU_DOMAINS);
2550a2fdbec6SFrançois Tigeot 
2551b030f26bSFrançois Tigeot 	ring->gpu_caches_dirty = false;
2552b030f26bSFrançois Tigeot 	return 0;
2553b030f26bSFrançois Tigeot }
2554b030f26bSFrançois Tigeot 
2555b030f26bSFrançois Tigeot int
2556ba55f2f5SFrançois Tigeot intel_ring_invalidate_all_caches(struct intel_engine_cs *ring)
2557b030f26bSFrançois Tigeot {
2558b030f26bSFrançois Tigeot 	uint32_t flush_domains;
2559b030f26bSFrançois Tigeot 	int ret;
2560b030f26bSFrançois Tigeot 
2561b030f26bSFrançois Tigeot 	flush_domains = 0;
2562b030f26bSFrançois Tigeot 	if (ring->gpu_caches_dirty)
2563b030f26bSFrançois Tigeot 		flush_domains = I915_GEM_GPU_DOMAINS;
2564b030f26bSFrançois Tigeot 
2565b030f26bSFrançois Tigeot 	ret = ring->flush(ring, I915_GEM_GPU_DOMAINS, flush_domains);
2566b030f26bSFrançois Tigeot 	if (ret)
2567b030f26bSFrançois Tigeot 		return ret;
2568b030f26bSFrançois Tigeot 
2569a2fdbec6SFrançois Tigeot 	trace_i915_gem_ring_flush(ring, I915_GEM_GPU_DOMAINS, flush_domains);
2570a2fdbec6SFrançois Tigeot 
2571b030f26bSFrançois Tigeot 	ring->gpu_caches_dirty = false;
2572b030f26bSFrançois Tigeot 	return 0;
2573b030f26bSFrançois Tigeot }
2574ba55f2f5SFrançois Tigeot 
2575ba55f2f5SFrançois Tigeot void
2576ba55f2f5SFrançois Tigeot intel_stop_ring_buffer(struct intel_engine_cs *ring)
2577ba55f2f5SFrançois Tigeot {
2578ba55f2f5SFrançois Tigeot 	int ret;
2579ba55f2f5SFrançois Tigeot 
2580ba55f2f5SFrançois Tigeot 	if (!intel_ring_initialized(ring))
2581ba55f2f5SFrançois Tigeot 		return;
2582ba55f2f5SFrançois Tigeot 
2583ba55f2f5SFrançois Tigeot 	ret = intel_ring_idle(ring);
2584ba55f2f5SFrançois Tigeot 	if (ret && !i915_reset_in_progress(&to_i915(ring->dev)->gpu_error))
2585ba55f2f5SFrançois Tigeot 		DRM_ERROR("failed to quiesce %s whilst cleaning up: %d\n",
2586ba55f2f5SFrançois Tigeot 			  ring->name, ret);
2587ba55f2f5SFrançois Tigeot 
2588ba55f2f5SFrançois Tigeot 	stop_ring(ring);
2589ba55f2f5SFrançois Tigeot }
2590