xref: /dflybsd-src/sys/dev/drm/i915/intel_ringbuffer.c (revision e3adcf8fcbce54764ec5bd4e133c79456138e35b)
1*e3adcf8fSFrançois Tigeot /*
2*e3adcf8fSFrançois Tigeot  * Copyright © 2008-2010 Intel Corporation
3*e3adcf8fSFrançois Tigeot  *
4*e3adcf8fSFrançois Tigeot  * Permission is hereby granted, free of charge, to any person obtaining a
5*e3adcf8fSFrançois Tigeot  * copy of this software and associated documentation files (the "Software"),
6*e3adcf8fSFrançois Tigeot  * to deal in the Software without restriction, including without limitation
7*e3adcf8fSFrançois Tigeot  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8*e3adcf8fSFrançois Tigeot  * and/or sell copies of the Software, and to permit persons to whom the
9*e3adcf8fSFrançois Tigeot  * Software is furnished to do so, subject to the following conditions:
10*e3adcf8fSFrançois Tigeot  *
11*e3adcf8fSFrançois Tigeot  * The above copyright notice and this permission notice (including the next
12*e3adcf8fSFrançois Tigeot  * paragraph) shall be included in all copies or substantial portions of the
13*e3adcf8fSFrançois Tigeot  * Software.
14*e3adcf8fSFrançois Tigeot  *
15*e3adcf8fSFrançois Tigeot  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16*e3adcf8fSFrançois Tigeot  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17*e3adcf8fSFrançois Tigeot  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18*e3adcf8fSFrançois Tigeot  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19*e3adcf8fSFrançois Tigeot  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20*e3adcf8fSFrançois Tigeot  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21*e3adcf8fSFrançois Tigeot  * IN THE SOFTWARE.
22*e3adcf8fSFrançois Tigeot  *
23*e3adcf8fSFrançois Tigeot  * Authors:
24*e3adcf8fSFrançois Tigeot  *    Eric Anholt <eric@anholt.net>
25*e3adcf8fSFrançois Tigeot  *    Zou Nan hai <nanhai.zou@intel.com>
26*e3adcf8fSFrançois Tigeot  *    Xiang Hai hao<haihao.xiang@intel.com>
27*e3adcf8fSFrançois Tigeot  *
28*e3adcf8fSFrançois Tigeot  * $FreeBSD: head/sys/dev/drm2/i915/intel_ringbuffer.c 253709 2013-07-27 16:42:29Z kib $
29*e3adcf8fSFrançois Tigeot  */
30*e3adcf8fSFrançois Tigeot 
31*e3adcf8fSFrançois Tigeot #include <dev/drm/drmP.h>
32*e3adcf8fSFrançois Tigeot #include <dev/drm/drm.h>
33*e3adcf8fSFrançois Tigeot #include "i915_drm.h"
34*e3adcf8fSFrançois Tigeot #include "i915_drv.h"
35*e3adcf8fSFrançois Tigeot #include "intel_drv.h"
36*e3adcf8fSFrançois Tigeot #include "intel_ringbuffer.h"
37*e3adcf8fSFrançois Tigeot #include <sys/sched.h>
38*e3adcf8fSFrançois Tigeot 
39*e3adcf8fSFrançois Tigeot /*
40*e3adcf8fSFrançois Tigeot  * 965+ support PIPE_CONTROL commands, which provide finer grained control
41*e3adcf8fSFrançois Tigeot  * over cache flushing.
42*e3adcf8fSFrançois Tigeot  */
43*e3adcf8fSFrançois Tigeot struct pipe_control {
44*e3adcf8fSFrançois Tigeot 	struct drm_i915_gem_object *obj;
45*e3adcf8fSFrançois Tigeot 	volatile u32 *cpu_page;
46*e3adcf8fSFrançois Tigeot 	u32 gtt_offset;
47*e3adcf8fSFrançois Tigeot };
48*e3adcf8fSFrançois Tigeot 
49*e3adcf8fSFrançois Tigeot void
50*e3adcf8fSFrançois Tigeot i915_trace_irq_get(struct intel_ring_buffer *ring, uint32_t seqno)
51*e3adcf8fSFrançois Tigeot {
52*e3adcf8fSFrançois Tigeot 
53*e3adcf8fSFrançois Tigeot 	if (ring->trace_irq_seqno == 0) {
54*e3adcf8fSFrançois Tigeot 		lockmgr(&ring->irq_lock, LK_EXCLUSIVE);
55*e3adcf8fSFrançois Tigeot 		if (ring->irq_get(ring))
56*e3adcf8fSFrançois Tigeot 			ring->trace_irq_seqno = seqno;
57*e3adcf8fSFrançois Tigeot 		lockmgr(&ring->irq_lock, LK_RELEASE);
58*e3adcf8fSFrançois Tigeot 	}
59*e3adcf8fSFrançois Tigeot }
60*e3adcf8fSFrançois Tigeot 
61*e3adcf8fSFrançois Tigeot static inline int ring_space(struct intel_ring_buffer *ring)
62*e3adcf8fSFrançois Tigeot {
63*e3adcf8fSFrançois Tigeot 	int space = (ring->head & HEAD_ADDR) - (ring->tail + 8);
64*e3adcf8fSFrançois Tigeot 	if (space < 0)
65*e3adcf8fSFrançois Tigeot 		space += ring->size;
66*e3adcf8fSFrançois Tigeot 	return space;
67*e3adcf8fSFrançois Tigeot }
68*e3adcf8fSFrançois Tigeot 
69*e3adcf8fSFrançois Tigeot static int
70*e3adcf8fSFrançois Tigeot render_ring_flush(struct intel_ring_buffer *ring,
71*e3adcf8fSFrançois Tigeot 		  uint32_t	invalidate_domains,
72*e3adcf8fSFrançois Tigeot 		  uint32_t	flush_domains)
73*e3adcf8fSFrançois Tigeot {
74*e3adcf8fSFrançois Tigeot 	struct drm_device *dev = ring->dev;
75*e3adcf8fSFrançois Tigeot 	uint32_t cmd;
76*e3adcf8fSFrançois Tigeot 	int ret;
77*e3adcf8fSFrançois Tigeot 
78*e3adcf8fSFrançois Tigeot 	/*
79*e3adcf8fSFrançois Tigeot 	 * read/write caches:
80*e3adcf8fSFrançois Tigeot 	 *
81*e3adcf8fSFrançois Tigeot 	 * I915_GEM_DOMAIN_RENDER is always invalidated, but is
82*e3adcf8fSFrançois Tigeot 	 * only flushed if MI_NO_WRITE_FLUSH is unset.  On 965, it is
83*e3adcf8fSFrançois Tigeot 	 * also flushed at 2d versus 3d pipeline switches.
84*e3adcf8fSFrançois Tigeot 	 *
85*e3adcf8fSFrançois Tigeot 	 * read-only caches:
86*e3adcf8fSFrançois Tigeot 	 *
87*e3adcf8fSFrançois Tigeot 	 * I915_GEM_DOMAIN_SAMPLER is flushed on pre-965 if
88*e3adcf8fSFrançois Tigeot 	 * MI_READ_FLUSH is set, and is always flushed on 965.
89*e3adcf8fSFrançois Tigeot 	 *
90*e3adcf8fSFrançois Tigeot 	 * I915_GEM_DOMAIN_COMMAND may not exist?
91*e3adcf8fSFrançois Tigeot 	 *
92*e3adcf8fSFrançois Tigeot 	 * I915_GEM_DOMAIN_INSTRUCTION, which exists on 965, is
93*e3adcf8fSFrançois Tigeot 	 * invalidated when MI_EXE_FLUSH is set.
94*e3adcf8fSFrançois Tigeot 	 *
95*e3adcf8fSFrançois Tigeot 	 * I915_GEM_DOMAIN_VERTEX, which exists on 965, is
96*e3adcf8fSFrançois Tigeot 	 * invalidated with every MI_FLUSH.
97*e3adcf8fSFrançois Tigeot 	 *
98*e3adcf8fSFrançois Tigeot 	 * TLBs:
99*e3adcf8fSFrançois Tigeot 	 *
100*e3adcf8fSFrançois Tigeot 	 * On 965, TLBs associated with I915_GEM_DOMAIN_COMMAND
101*e3adcf8fSFrançois Tigeot 	 * and I915_GEM_DOMAIN_CPU in are invalidated at PTE write and
102*e3adcf8fSFrançois Tigeot 	 * I915_GEM_DOMAIN_RENDER and I915_GEM_DOMAIN_SAMPLER
103*e3adcf8fSFrançois Tigeot 	 * are flushed at any MI_FLUSH.
104*e3adcf8fSFrançois Tigeot 	 */
105*e3adcf8fSFrançois Tigeot 
106*e3adcf8fSFrançois Tigeot 	cmd = MI_FLUSH | MI_NO_WRITE_FLUSH;
107*e3adcf8fSFrançois Tigeot 	if ((invalidate_domains|flush_domains) &
108*e3adcf8fSFrançois Tigeot 	    I915_GEM_DOMAIN_RENDER)
109*e3adcf8fSFrançois Tigeot 		cmd &= ~MI_NO_WRITE_FLUSH;
110*e3adcf8fSFrançois Tigeot 	if (INTEL_INFO(dev)->gen < 4) {
111*e3adcf8fSFrançois Tigeot 		/*
112*e3adcf8fSFrançois Tigeot 		 * On the 965, the sampler cache always gets flushed
113*e3adcf8fSFrançois Tigeot 		 * and this bit is reserved.
114*e3adcf8fSFrançois Tigeot 		 */
115*e3adcf8fSFrançois Tigeot 		if (invalidate_domains & I915_GEM_DOMAIN_SAMPLER)
116*e3adcf8fSFrançois Tigeot 			cmd |= MI_READ_FLUSH;
117*e3adcf8fSFrançois Tigeot 	}
118*e3adcf8fSFrançois Tigeot 	if (invalidate_domains & I915_GEM_DOMAIN_INSTRUCTION)
119*e3adcf8fSFrançois Tigeot 		cmd |= MI_EXE_FLUSH;
120*e3adcf8fSFrançois Tigeot 
121*e3adcf8fSFrançois Tigeot 	if (invalidate_domains & I915_GEM_DOMAIN_COMMAND &&
122*e3adcf8fSFrançois Tigeot 	    (IS_G4X(dev) || IS_GEN5(dev)))
123*e3adcf8fSFrançois Tigeot 		cmd |= MI_INVALIDATE_ISP;
124*e3adcf8fSFrançois Tigeot 
125*e3adcf8fSFrançois Tigeot 	ret = intel_ring_begin(ring, 2);
126*e3adcf8fSFrançois Tigeot 	if (ret)
127*e3adcf8fSFrançois Tigeot 		return ret;
128*e3adcf8fSFrançois Tigeot 
129*e3adcf8fSFrançois Tigeot 	intel_ring_emit(ring, cmd);
130*e3adcf8fSFrançois Tigeot 	intel_ring_emit(ring, MI_NOOP);
131*e3adcf8fSFrançois Tigeot 	intel_ring_advance(ring);
132*e3adcf8fSFrançois Tigeot 
133*e3adcf8fSFrançois Tigeot 	return 0;
134*e3adcf8fSFrançois Tigeot }
135*e3adcf8fSFrançois Tigeot 
136*e3adcf8fSFrançois Tigeot /**
137*e3adcf8fSFrançois Tigeot  * Emits a PIPE_CONTROL with a non-zero post-sync operation, for
138*e3adcf8fSFrançois Tigeot  * implementing two workarounds on gen6.  From section 1.4.7.1
139*e3adcf8fSFrançois Tigeot  * "PIPE_CONTROL" of the Sandy Bridge PRM volume 2 part 1:
140*e3adcf8fSFrançois Tigeot  *
141*e3adcf8fSFrançois Tigeot  * [DevSNB-C+{W/A}] Before any depth stall flush (including those
142*e3adcf8fSFrançois Tigeot  * produced by non-pipelined state commands), software needs to first
143*e3adcf8fSFrançois Tigeot  * send a PIPE_CONTROL with no bits set except Post-Sync Operation !=
144*e3adcf8fSFrançois Tigeot  * 0.
145*e3adcf8fSFrançois Tigeot  *
146*e3adcf8fSFrançois Tigeot  * [Dev-SNB{W/A}]: Before a PIPE_CONTROL with Write Cache Flush Enable
147*e3adcf8fSFrançois Tigeot  * =1, a PIPE_CONTROL with any non-zero post-sync-op is required.
148*e3adcf8fSFrançois Tigeot  *
149*e3adcf8fSFrançois Tigeot  * And the workaround for these two requires this workaround first:
150*e3adcf8fSFrançois Tigeot  *
151*e3adcf8fSFrançois Tigeot  * [Dev-SNB{W/A}]: Pipe-control with CS-stall bit set must be sent
152*e3adcf8fSFrançois Tigeot  * BEFORE the pipe-control with a post-sync op and no write-cache
153*e3adcf8fSFrançois Tigeot  * flushes.
154*e3adcf8fSFrançois Tigeot  *
155*e3adcf8fSFrançois Tigeot  * And this last workaround is tricky because of the requirements on
156*e3adcf8fSFrançois Tigeot  * that bit.  From section 1.4.7.2.3 "Stall" of the Sandy Bridge PRM
157*e3adcf8fSFrançois Tigeot  * volume 2 part 1:
158*e3adcf8fSFrançois Tigeot  *
159*e3adcf8fSFrançois Tigeot  *     "1 of the following must also be set:
160*e3adcf8fSFrançois Tigeot  *      - Render Target Cache Flush Enable ([12] of DW1)
161*e3adcf8fSFrançois Tigeot  *      - Depth Cache Flush Enable ([0] of DW1)
162*e3adcf8fSFrançois Tigeot  *      - Stall at Pixel Scoreboard ([1] of DW1)
163*e3adcf8fSFrançois Tigeot  *      - Depth Stall ([13] of DW1)
164*e3adcf8fSFrançois Tigeot  *      - Post-Sync Operation ([13] of DW1)
165*e3adcf8fSFrançois Tigeot  *      - Notify Enable ([8] of DW1)"
166*e3adcf8fSFrançois Tigeot  *
167*e3adcf8fSFrançois Tigeot  * The cache flushes require the workaround flush that triggered this
168*e3adcf8fSFrançois Tigeot  * one, so we can't use it.  Depth stall would trigger the same.
169*e3adcf8fSFrançois Tigeot  * Post-sync nonzero is what triggered this second workaround, so we
170*e3adcf8fSFrançois Tigeot  * can't use that one either.  Notify enable is IRQs, which aren't
171*e3adcf8fSFrançois Tigeot  * really our business.  That leaves only stall at scoreboard.
172*e3adcf8fSFrançois Tigeot  */
173*e3adcf8fSFrançois Tigeot static int
174*e3adcf8fSFrançois Tigeot intel_emit_post_sync_nonzero_flush(struct intel_ring_buffer *ring)
175*e3adcf8fSFrançois Tigeot {
176*e3adcf8fSFrançois Tigeot 	struct pipe_control *pc = ring->private;
177*e3adcf8fSFrançois Tigeot 	u32 scratch_addr = pc->gtt_offset + 128;
178*e3adcf8fSFrançois Tigeot 	int ret;
179*e3adcf8fSFrançois Tigeot 
180*e3adcf8fSFrançois Tigeot 
181*e3adcf8fSFrançois Tigeot 	ret = intel_ring_begin(ring, 6);
182*e3adcf8fSFrançois Tigeot 	if (ret)
183*e3adcf8fSFrançois Tigeot 		return ret;
184*e3adcf8fSFrançois Tigeot 
185*e3adcf8fSFrançois Tigeot 	intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(5));
186*e3adcf8fSFrançois Tigeot 	intel_ring_emit(ring, PIPE_CONTROL_CS_STALL |
187*e3adcf8fSFrançois Tigeot 			PIPE_CONTROL_STALL_AT_SCOREBOARD);
188*e3adcf8fSFrançois Tigeot 	intel_ring_emit(ring, scratch_addr | PIPE_CONTROL_GLOBAL_GTT); /* address */
189*e3adcf8fSFrançois Tigeot 	intel_ring_emit(ring, 0); /* low dword */
190*e3adcf8fSFrançois Tigeot 	intel_ring_emit(ring, 0); /* high dword */
191*e3adcf8fSFrançois Tigeot 	intel_ring_emit(ring, MI_NOOP);
192*e3adcf8fSFrançois Tigeot 	intel_ring_advance(ring);
193*e3adcf8fSFrançois Tigeot 
194*e3adcf8fSFrançois Tigeot 	ret = intel_ring_begin(ring, 6);
195*e3adcf8fSFrançois Tigeot 	if (ret)
196*e3adcf8fSFrançois Tigeot 		return ret;
197*e3adcf8fSFrançois Tigeot 
198*e3adcf8fSFrançois Tigeot 	intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(5));
199*e3adcf8fSFrançois Tigeot 	intel_ring_emit(ring, PIPE_CONTROL_QW_WRITE);
200*e3adcf8fSFrançois Tigeot 	intel_ring_emit(ring, scratch_addr | PIPE_CONTROL_GLOBAL_GTT); /* address */
201*e3adcf8fSFrançois Tigeot 	intel_ring_emit(ring, 0);
202*e3adcf8fSFrançois Tigeot 	intel_ring_emit(ring, 0);
203*e3adcf8fSFrançois Tigeot 	intel_ring_emit(ring, MI_NOOP);
204*e3adcf8fSFrançois Tigeot 	intel_ring_advance(ring);
205*e3adcf8fSFrançois Tigeot 
206*e3adcf8fSFrançois Tigeot 	return 0;
207*e3adcf8fSFrançois Tigeot }
208*e3adcf8fSFrançois Tigeot 
209*e3adcf8fSFrançois Tigeot static int
210*e3adcf8fSFrançois Tigeot gen6_render_ring_flush(struct intel_ring_buffer *ring,
211*e3adcf8fSFrançois Tigeot                          u32 invalidate_domains, u32 flush_domains)
212*e3adcf8fSFrançois Tigeot {
213*e3adcf8fSFrançois Tigeot 	u32 flags = 0;
214*e3adcf8fSFrançois Tigeot 	struct pipe_control *pc = ring->private;
215*e3adcf8fSFrançois Tigeot 	u32 scratch_addr = pc->gtt_offset + 128;
216*e3adcf8fSFrançois Tigeot 	int ret;
217*e3adcf8fSFrançois Tigeot 
218*e3adcf8fSFrançois Tigeot 	/* Force SNB workarounds for PIPE_CONTROL flushes */
219*e3adcf8fSFrançois Tigeot 	intel_emit_post_sync_nonzero_flush(ring);
220*e3adcf8fSFrançois Tigeot 
221*e3adcf8fSFrançois Tigeot 	/* Just flush everything.  Experiments have shown that reducing the
222*e3adcf8fSFrançois Tigeot 	 * number of bits based on the write domains has little performance
223*e3adcf8fSFrançois Tigeot 	 * impact.
224*e3adcf8fSFrançois Tigeot 	 */
225*e3adcf8fSFrançois Tigeot 	flags |= PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH;
226*e3adcf8fSFrançois Tigeot 	flags |= PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE;
227*e3adcf8fSFrançois Tigeot 	flags |= PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE;
228*e3adcf8fSFrançois Tigeot 	flags |= PIPE_CONTROL_DEPTH_CACHE_FLUSH;
229*e3adcf8fSFrançois Tigeot 	flags |= PIPE_CONTROL_VF_CACHE_INVALIDATE;
230*e3adcf8fSFrançois Tigeot 	flags |= PIPE_CONTROL_CONST_CACHE_INVALIDATE;
231*e3adcf8fSFrançois Tigeot 	flags |= PIPE_CONTROL_STATE_CACHE_INVALIDATE;
232*e3adcf8fSFrançois Tigeot 
233*e3adcf8fSFrançois Tigeot 	ret = intel_ring_begin(ring, 6);
234*e3adcf8fSFrançois Tigeot 	if (ret)
235*e3adcf8fSFrançois Tigeot 		return ret;
236*e3adcf8fSFrançois Tigeot 
237*e3adcf8fSFrançois Tigeot 	intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(5));
238*e3adcf8fSFrançois Tigeot 	intel_ring_emit(ring, flags);
239*e3adcf8fSFrançois Tigeot 	intel_ring_emit(ring, scratch_addr | PIPE_CONTROL_GLOBAL_GTT);
240*e3adcf8fSFrançois Tigeot 	intel_ring_emit(ring, 0); /* lower dword */
241*e3adcf8fSFrançois Tigeot 	intel_ring_emit(ring, 0); /* uppwer dword */
242*e3adcf8fSFrançois Tigeot 	intel_ring_emit(ring, MI_NOOP);
243*e3adcf8fSFrançois Tigeot 	intel_ring_advance(ring);
244*e3adcf8fSFrançois Tigeot 
245*e3adcf8fSFrançois Tigeot 	return 0;
246*e3adcf8fSFrançois Tigeot }
247*e3adcf8fSFrançois Tigeot 
248*e3adcf8fSFrançois Tigeot static void ring_write_tail(struct intel_ring_buffer *ring,
249*e3adcf8fSFrançois Tigeot 			    uint32_t value)
250*e3adcf8fSFrançois Tigeot {
251*e3adcf8fSFrançois Tigeot 	drm_i915_private_t *dev_priv = ring->dev->dev_private;
252*e3adcf8fSFrançois Tigeot 	I915_WRITE_TAIL(ring, value);
253*e3adcf8fSFrançois Tigeot }
254*e3adcf8fSFrançois Tigeot 
255*e3adcf8fSFrançois Tigeot u32 intel_ring_get_active_head(struct intel_ring_buffer *ring)
256*e3adcf8fSFrançois Tigeot {
257*e3adcf8fSFrançois Tigeot 	drm_i915_private_t *dev_priv = ring->dev->dev_private;
258*e3adcf8fSFrançois Tigeot 	uint32_t acthd_reg = INTEL_INFO(ring->dev)->gen >= 4 ?
259*e3adcf8fSFrançois Tigeot 			RING_ACTHD(ring->mmio_base) : ACTHD;
260*e3adcf8fSFrançois Tigeot 
261*e3adcf8fSFrançois Tigeot 	return I915_READ(acthd_reg);
262*e3adcf8fSFrançois Tigeot }
263*e3adcf8fSFrançois Tigeot 
264*e3adcf8fSFrançois Tigeot static int init_ring_common(struct intel_ring_buffer *ring)
265*e3adcf8fSFrançois Tigeot {
266*e3adcf8fSFrançois Tigeot 	drm_i915_private_t *dev_priv = ring->dev->dev_private;
267*e3adcf8fSFrançois Tigeot 	struct drm_i915_gem_object *obj = ring->obj;
268*e3adcf8fSFrançois Tigeot 	uint32_t head;
269*e3adcf8fSFrançois Tigeot 
270*e3adcf8fSFrançois Tigeot 	/* Stop the ring if it's running. */
271*e3adcf8fSFrançois Tigeot 	I915_WRITE_CTL(ring, 0);
272*e3adcf8fSFrançois Tigeot 	I915_WRITE_HEAD(ring, 0);
273*e3adcf8fSFrançois Tigeot 	ring->write_tail(ring, 0);
274*e3adcf8fSFrançois Tigeot 
275*e3adcf8fSFrançois Tigeot 	/* Initialize the ring. */
276*e3adcf8fSFrançois Tigeot 	I915_WRITE_START(ring, obj->gtt_offset);
277*e3adcf8fSFrançois Tigeot 	head = I915_READ_HEAD(ring) & HEAD_ADDR;
278*e3adcf8fSFrançois Tigeot 
279*e3adcf8fSFrançois Tigeot 	/* G45 ring initialization fails to reset head to zero */
280*e3adcf8fSFrançois Tigeot 	if (head != 0) {
281*e3adcf8fSFrançois Tigeot 		DRM_DEBUG("%s head not reset to zero "
282*e3adcf8fSFrançois Tigeot 			      "ctl %08x head %08x tail %08x start %08x\n",
283*e3adcf8fSFrançois Tigeot 			      ring->name,
284*e3adcf8fSFrançois Tigeot 			      I915_READ_CTL(ring),
285*e3adcf8fSFrançois Tigeot 			      I915_READ_HEAD(ring),
286*e3adcf8fSFrançois Tigeot 			      I915_READ_TAIL(ring),
287*e3adcf8fSFrançois Tigeot 			      I915_READ_START(ring));
288*e3adcf8fSFrançois Tigeot 
289*e3adcf8fSFrançois Tigeot 		I915_WRITE_HEAD(ring, 0);
290*e3adcf8fSFrançois Tigeot 
291*e3adcf8fSFrançois Tigeot 		if (I915_READ_HEAD(ring) & HEAD_ADDR) {
292*e3adcf8fSFrançois Tigeot 			DRM_ERROR("failed to set %s head to zero "
293*e3adcf8fSFrançois Tigeot 				  "ctl %08x head %08x tail %08x start %08x\n",
294*e3adcf8fSFrançois Tigeot 				  ring->name,
295*e3adcf8fSFrançois Tigeot 				  I915_READ_CTL(ring),
296*e3adcf8fSFrançois Tigeot 				  I915_READ_HEAD(ring),
297*e3adcf8fSFrançois Tigeot 				  I915_READ_TAIL(ring),
298*e3adcf8fSFrançois Tigeot 				  I915_READ_START(ring));
299*e3adcf8fSFrançois Tigeot 		}
300*e3adcf8fSFrançois Tigeot 	}
301*e3adcf8fSFrançois Tigeot 
302*e3adcf8fSFrançois Tigeot 	I915_WRITE_CTL(ring,
303*e3adcf8fSFrançois Tigeot 			((ring->size - PAGE_SIZE) & RING_NR_PAGES)
304*e3adcf8fSFrançois Tigeot 			| RING_VALID);
305*e3adcf8fSFrançois Tigeot 
306*e3adcf8fSFrançois Tigeot 	/* If the head is still not zero, the ring is dead */
307*e3adcf8fSFrançois Tigeot 	if (_intel_wait_for(ring->dev,
308*e3adcf8fSFrançois Tigeot 	    (I915_READ_CTL(ring) & RING_VALID) != 0 &&
309*e3adcf8fSFrançois Tigeot 	     I915_READ_START(ring) == obj->gtt_offset &&
310*e3adcf8fSFrançois Tigeot 	     (I915_READ_HEAD(ring) & HEAD_ADDR) == 0,
311*e3adcf8fSFrançois Tigeot 	    50, 1, "915rii")) {
312*e3adcf8fSFrançois Tigeot 		DRM_ERROR("%s initialization failed "
313*e3adcf8fSFrançois Tigeot 				"ctl %08x head %08x tail %08x start %08x\n",
314*e3adcf8fSFrançois Tigeot 				ring->name,
315*e3adcf8fSFrançois Tigeot 				I915_READ_CTL(ring),
316*e3adcf8fSFrançois Tigeot 				I915_READ_HEAD(ring),
317*e3adcf8fSFrançois Tigeot 				I915_READ_TAIL(ring),
318*e3adcf8fSFrançois Tigeot 				I915_READ_START(ring));
319*e3adcf8fSFrançois Tigeot 		return -EIO;
320*e3adcf8fSFrançois Tigeot 	}
321*e3adcf8fSFrançois Tigeot 
322*e3adcf8fSFrançois Tigeot 	if (!drm_core_check_feature(ring->dev, DRIVER_MODESET))
323*e3adcf8fSFrançois Tigeot 		i915_kernel_lost_context(ring->dev);
324*e3adcf8fSFrançois Tigeot 	else {
325*e3adcf8fSFrançois Tigeot 		ring->head = I915_READ_HEAD(ring);
326*e3adcf8fSFrançois Tigeot 		ring->tail = I915_READ_TAIL(ring) & TAIL_ADDR;
327*e3adcf8fSFrançois Tigeot 		ring->space = ring_space(ring);
328*e3adcf8fSFrançois Tigeot 	}
329*e3adcf8fSFrançois Tigeot 
330*e3adcf8fSFrançois Tigeot 	return 0;
331*e3adcf8fSFrançois Tigeot }
332*e3adcf8fSFrançois Tigeot 
333*e3adcf8fSFrançois Tigeot static int
334*e3adcf8fSFrançois Tigeot init_pipe_control(struct intel_ring_buffer *ring)
335*e3adcf8fSFrançois Tigeot {
336*e3adcf8fSFrançois Tigeot 	struct pipe_control *pc;
337*e3adcf8fSFrançois Tigeot 	struct drm_i915_gem_object *obj;
338*e3adcf8fSFrançois Tigeot 	int ret;
339*e3adcf8fSFrançois Tigeot 
340*e3adcf8fSFrançois Tigeot 	if (ring->private)
341*e3adcf8fSFrançois Tigeot 		return 0;
342*e3adcf8fSFrançois Tigeot 
343*e3adcf8fSFrançois Tigeot 	pc = kmalloc(sizeof(*pc), DRM_I915_GEM, M_WAITOK);
344*e3adcf8fSFrançois Tigeot 	if (!pc)
345*e3adcf8fSFrançois Tigeot 		return -ENOMEM;
346*e3adcf8fSFrançois Tigeot 
347*e3adcf8fSFrançois Tigeot 	obj = i915_gem_alloc_object(ring->dev, 4096);
348*e3adcf8fSFrançois Tigeot 	if (obj == NULL) {
349*e3adcf8fSFrançois Tigeot 		DRM_ERROR("Failed to allocate seqno page\n");
350*e3adcf8fSFrançois Tigeot 		ret = -ENOMEM;
351*e3adcf8fSFrançois Tigeot 		goto err;
352*e3adcf8fSFrançois Tigeot 	}
353*e3adcf8fSFrançois Tigeot 
354*e3adcf8fSFrançois Tigeot 	i915_gem_object_set_cache_level(obj, I915_CACHE_LLC);
355*e3adcf8fSFrançois Tigeot 
356*e3adcf8fSFrançois Tigeot 	ret = i915_gem_object_pin(obj, 4096, true);
357*e3adcf8fSFrançois Tigeot 	if (ret)
358*e3adcf8fSFrançois Tigeot 		goto err_unref;
359*e3adcf8fSFrançois Tigeot 
360*e3adcf8fSFrançois Tigeot 	pc->gtt_offset = obj->gtt_offset;
361*e3adcf8fSFrançois Tigeot 	pc->cpu_page = (uint32_t *)kmem_alloc_nofault(&kernel_map, PAGE_SIZE, PAGE_SIZE);
362*e3adcf8fSFrançois Tigeot 	if (pc->cpu_page == NULL)
363*e3adcf8fSFrançois Tigeot 		goto err_unpin;
364*e3adcf8fSFrançois Tigeot 	pmap_qenter((uintptr_t)pc->cpu_page, &obj->pages[0], 1);
365*e3adcf8fSFrançois Tigeot 	pmap_invalidate_cache_range((vm_offset_t)pc->cpu_page,
366*e3adcf8fSFrançois Tigeot 	    (vm_offset_t)pc->cpu_page + PAGE_SIZE);
367*e3adcf8fSFrançois Tigeot 
368*e3adcf8fSFrançois Tigeot 	pc->obj = obj;
369*e3adcf8fSFrançois Tigeot 	ring->private = pc;
370*e3adcf8fSFrançois Tigeot 	return 0;
371*e3adcf8fSFrançois Tigeot 
372*e3adcf8fSFrançois Tigeot err_unpin:
373*e3adcf8fSFrançois Tigeot 	i915_gem_object_unpin(obj);
374*e3adcf8fSFrançois Tigeot err_unref:
375*e3adcf8fSFrançois Tigeot 	drm_gem_object_unreference(&obj->base);
376*e3adcf8fSFrançois Tigeot err:
377*e3adcf8fSFrançois Tigeot 	drm_free(pc, DRM_I915_GEM);
378*e3adcf8fSFrançois Tigeot 	return ret;
379*e3adcf8fSFrançois Tigeot }
380*e3adcf8fSFrançois Tigeot 
381*e3adcf8fSFrançois Tigeot static void
382*e3adcf8fSFrançois Tigeot cleanup_pipe_control(struct intel_ring_buffer *ring)
383*e3adcf8fSFrançois Tigeot {
384*e3adcf8fSFrançois Tigeot 	struct pipe_control *pc = ring->private;
385*e3adcf8fSFrançois Tigeot 	struct drm_i915_gem_object *obj;
386*e3adcf8fSFrançois Tigeot 
387*e3adcf8fSFrançois Tigeot 	if (!ring->private)
388*e3adcf8fSFrançois Tigeot 		return;
389*e3adcf8fSFrançois Tigeot 
390*e3adcf8fSFrançois Tigeot 	obj = pc->obj;
391*e3adcf8fSFrançois Tigeot 	pmap_qremove((vm_offset_t)pc->cpu_page, 1);
392*e3adcf8fSFrançois Tigeot 	kmem_free(&kernel_map, (uintptr_t)pc->cpu_page, PAGE_SIZE);
393*e3adcf8fSFrançois Tigeot 	i915_gem_object_unpin(obj);
394*e3adcf8fSFrançois Tigeot 	drm_gem_object_unreference(&obj->base);
395*e3adcf8fSFrançois Tigeot 
396*e3adcf8fSFrançois Tigeot 	drm_free(pc, DRM_I915_GEM);
397*e3adcf8fSFrançois Tigeot 	ring->private = NULL;
398*e3adcf8fSFrançois Tigeot }
399*e3adcf8fSFrançois Tigeot 
400*e3adcf8fSFrançois Tigeot static int init_render_ring(struct intel_ring_buffer *ring)
401*e3adcf8fSFrançois Tigeot {
402*e3adcf8fSFrançois Tigeot 	struct drm_device *dev = ring->dev;
403*e3adcf8fSFrançois Tigeot 	struct drm_i915_private *dev_priv = dev->dev_private;
404*e3adcf8fSFrançois Tigeot 	int ret = init_ring_common(ring);
405*e3adcf8fSFrançois Tigeot 
406*e3adcf8fSFrançois Tigeot 	if (INTEL_INFO(dev)->gen > 3) {
407*e3adcf8fSFrançois Tigeot 		int mode = VS_TIMER_DISPATCH << 16 | VS_TIMER_DISPATCH;
408*e3adcf8fSFrançois Tigeot 		I915_WRITE(MI_MODE, mode);
409*e3adcf8fSFrançois Tigeot 		if (IS_GEN7(dev))
410*e3adcf8fSFrançois Tigeot 			I915_WRITE(GFX_MODE_GEN7,
411*e3adcf8fSFrançois Tigeot 				   GFX_MODE_DISABLE(GFX_TLB_INVALIDATE_ALWAYS) |
412*e3adcf8fSFrançois Tigeot 				   GFX_MODE_ENABLE(GFX_REPLAY_MODE));
413*e3adcf8fSFrançois Tigeot 	}
414*e3adcf8fSFrançois Tigeot 
415*e3adcf8fSFrançois Tigeot 	if (INTEL_INFO(dev)->gen >= 5) {
416*e3adcf8fSFrançois Tigeot 		ret = init_pipe_control(ring);
417*e3adcf8fSFrançois Tigeot 		if (ret)
418*e3adcf8fSFrançois Tigeot 			return ret;
419*e3adcf8fSFrançois Tigeot 	}
420*e3adcf8fSFrançois Tigeot 
421*e3adcf8fSFrançois Tigeot 
422*e3adcf8fSFrançois Tigeot 	if (IS_GEN6(dev)) {
423*e3adcf8fSFrançois Tigeot 		/* From the Sandybridge PRM, volume 1 part 3, page 24:
424*e3adcf8fSFrançois Tigeot 		 * "If this bit is set, STCunit will have LRA as replacement
425*e3adcf8fSFrançois Tigeot 		 *  policy. [...] This bit must be reset.  LRA replacement
426*e3adcf8fSFrançois Tigeot 		 *  policy is not supported."
427*e3adcf8fSFrançois Tigeot 		 */
428*e3adcf8fSFrançois Tigeot 		I915_WRITE(CACHE_MODE_0,
429*e3adcf8fSFrançois Tigeot 			   CM0_STC_EVICT_DISABLE_LRA_SNB << CM0_MASK_SHIFT);
430*e3adcf8fSFrançois Tigeot 	}
431*e3adcf8fSFrançois Tigeot 
432*e3adcf8fSFrançois Tigeot 	if (INTEL_INFO(dev)->gen >= 6) {
433*e3adcf8fSFrançois Tigeot 		I915_WRITE(INSTPM,
434*e3adcf8fSFrançois Tigeot 			   INSTPM_FORCE_ORDERING << 16 | INSTPM_FORCE_ORDERING);
435*e3adcf8fSFrançois Tigeot 	}
436*e3adcf8fSFrançois Tigeot 
437*e3adcf8fSFrançois Tigeot 	return ret;
438*e3adcf8fSFrançois Tigeot }
439*e3adcf8fSFrançois Tigeot 
440*e3adcf8fSFrançois Tigeot static void render_ring_cleanup(struct intel_ring_buffer *ring)
441*e3adcf8fSFrançois Tigeot {
442*e3adcf8fSFrançois Tigeot 	if (!ring->private)
443*e3adcf8fSFrançois Tigeot 		return;
444*e3adcf8fSFrançois Tigeot 
445*e3adcf8fSFrançois Tigeot 	cleanup_pipe_control(ring);
446*e3adcf8fSFrançois Tigeot }
447*e3adcf8fSFrançois Tigeot 
448*e3adcf8fSFrançois Tigeot static void
449*e3adcf8fSFrançois Tigeot update_mboxes(struct intel_ring_buffer *ring,
450*e3adcf8fSFrançois Tigeot 	    u32 seqno,
451*e3adcf8fSFrançois Tigeot 	    u32 mmio_offset)
452*e3adcf8fSFrançois Tigeot {
453*e3adcf8fSFrançois Tigeot 	intel_ring_emit(ring, MI_SEMAPHORE_MBOX |
454*e3adcf8fSFrançois Tigeot 			      MI_SEMAPHORE_GLOBAL_GTT |
455*e3adcf8fSFrançois Tigeot 			      MI_SEMAPHORE_REGISTER |
456*e3adcf8fSFrançois Tigeot 			      MI_SEMAPHORE_UPDATE);
457*e3adcf8fSFrançois Tigeot 	intel_ring_emit(ring, seqno);
458*e3adcf8fSFrançois Tigeot 	intel_ring_emit(ring, mmio_offset);
459*e3adcf8fSFrançois Tigeot }
460*e3adcf8fSFrançois Tigeot 
461*e3adcf8fSFrançois Tigeot /**
462*e3adcf8fSFrançois Tigeot  * gen6_add_request - Update the semaphore mailbox registers
463*e3adcf8fSFrançois Tigeot  *
464*e3adcf8fSFrançois Tigeot  * @ring - ring that is adding a request
465*e3adcf8fSFrançois Tigeot  * @seqno - return seqno stuck into the ring
466*e3adcf8fSFrançois Tigeot  *
467*e3adcf8fSFrançois Tigeot  * Update the mailbox registers in the *other* rings with the current seqno.
468*e3adcf8fSFrançois Tigeot  * This acts like a signal in the canonical semaphore.
469*e3adcf8fSFrançois Tigeot  */
470*e3adcf8fSFrançois Tigeot static int
471*e3adcf8fSFrançois Tigeot gen6_add_request(struct intel_ring_buffer *ring,
472*e3adcf8fSFrançois Tigeot 		 u32 *seqno)
473*e3adcf8fSFrançois Tigeot {
474*e3adcf8fSFrançois Tigeot 	u32 mbox1_reg;
475*e3adcf8fSFrançois Tigeot 	u32 mbox2_reg;
476*e3adcf8fSFrançois Tigeot 	int ret;
477*e3adcf8fSFrançois Tigeot 
478*e3adcf8fSFrançois Tigeot 	ret = intel_ring_begin(ring, 10);
479*e3adcf8fSFrançois Tigeot 	if (ret)
480*e3adcf8fSFrançois Tigeot 		return ret;
481*e3adcf8fSFrançois Tigeot 
482*e3adcf8fSFrançois Tigeot 	mbox1_reg = ring->signal_mbox[0];
483*e3adcf8fSFrançois Tigeot 	mbox2_reg = ring->signal_mbox[1];
484*e3adcf8fSFrançois Tigeot 
485*e3adcf8fSFrançois Tigeot 	*seqno = i915_gem_next_request_seqno(ring);
486*e3adcf8fSFrançois Tigeot 
487*e3adcf8fSFrançois Tigeot 	update_mboxes(ring, *seqno, mbox1_reg);
488*e3adcf8fSFrançois Tigeot 	update_mboxes(ring, *seqno, mbox2_reg);
489*e3adcf8fSFrançois Tigeot 	intel_ring_emit(ring, MI_STORE_DWORD_INDEX);
490*e3adcf8fSFrançois Tigeot 	intel_ring_emit(ring, I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT);
491*e3adcf8fSFrançois Tigeot 	intel_ring_emit(ring, *seqno);
492*e3adcf8fSFrançois Tigeot 	intel_ring_emit(ring, MI_USER_INTERRUPT);
493*e3adcf8fSFrançois Tigeot 	intel_ring_advance(ring);
494*e3adcf8fSFrançois Tigeot 
495*e3adcf8fSFrançois Tigeot 	return 0;
496*e3adcf8fSFrançois Tigeot }
497*e3adcf8fSFrançois Tigeot 
498*e3adcf8fSFrançois Tigeot /**
499*e3adcf8fSFrançois Tigeot  * intel_ring_sync - sync the waiter to the signaller on seqno
500*e3adcf8fSFrançois Tigeot  *
501*e3adcf8fSFrançois Tigeot  * @waiter - ring that is waiting
502*e3adcf8fSFrançois Tigeot  * @signaller - ring which has, or will signal
503*e3adcf8fSFrançois Tigeot  * @seqno - seqno which the waiter will block on
504*e3adcf8fSFrançois Tigeot  */
505*e3adcf8fSFrançois Tigeot static int
506*e3adcf8fSFrançois Tigeot intel_ring_sync(struct intel_ring_buffer *waiter,
507*e3adcf8fSFrançois Tigeot 		struct intel_ring_buffer *signaller,
508*e3adcf8fSFrançois Tigeot 		int ring,
509*e3adcf8fSFrançois Tigeot 		u32 seqno)
510*e3adcf8fSFrançois Tigeot {
511*e3adcf8fSFrançois Tigeot 	int ret;
512*e3adcf8fSFrançois Tigeot 	u32 dw1 = MI_SEMAPHORE_MBOX |
513*e3adcf8fSFrançois Tigeot 		  MI_SEMAPHORE_COMPARE |
514*e3adcf8fSFrançois Tigeot 		  MI_SEMAPHORE_REGISTER;
515*e3adcf8fSFrançois Tigeot 
516*e3adcf8fSFrançois Tigeot 	ret = intel_ring_begin(waiter, 4);
517*e3adcf8fSFrançois Tigeot 	if (ret)
518*e3adcf8fSFrançois Tigeot 		return ret;
519*e3adcf8fSFrançois Tigeot 
520*e3adcf8fSFrançois Tigeot 	intel_ring_emit(waiter, dw1 | signaller->semaphore_register[ring]);
521*e3adcf8fSFrançois Tigeot 	intel_ring_emit(waiter, seqno);
522*e3adcf8fSFrançois Tigeot 	intel_ring_emit(waiter, 0);
523*e3adcf8fSFrançois Tigeot 	intel_ring_emit(waiter, MI_NOOP);
524*e3adcf8fSFrançois Tigeot 	intel_ring_advance(waiter);
525*e3adcf8fSFrançois Tigeot 
526*e3adcf8fSFrançois Tigeot 	return 0;
527*e3adcf8fSFrançois Tigeot }
528*e3adcf8fSFrançois Tigeot 
529*e3adcf8fSFrançois Tigeot int render_ring_sync_to(struct intel_ring_buffer *waiter,
530*e3adcf8fSFrançois Tigeot     struct intel_ring_buffer *signaller, u32 seqno);
531*e3adcf8fSFrançois Tigeot int gen6_bsd_ring_sync_to(struct intel_ring_buffer *waiter,
532*e3adcf8fSFrançois Tigeot     struct intel_ring_buffer *signaller, u32 seqno);
533*e3adcf8fSFrançois Tigeot int gen6_blt_ring_sync_to(struct intel_ring_buffer *waiter,
534*e3adcf8fSFrançois Tigeot     struct intel_ring_buffer *signaller, u32 seqno);
535*e3adcf8fSFrançois Tigeot 
536*e3adcf8fSFrançois Tigeot /* VCS->RCS (RVSYNC) or BCS->RCS (RBSYNC) */
537*e3adcf8fSFrançois Tigeot int
538*e3adcf8fSFrançois Tigeot render_ring_sync_to(struct intel_ring_buffer *waiter,
539*e3adcf8fSFrançois Tigeot 		    struct intel_ring_buffer *signaller,
540*e3adcf8fSFrançois Tigeot 		    u32 seqno)
541*e3adcf8fSFrançois Tigeot {
542*e3adcf8fSFrançois Tigeot 	KASSERT(signaller->semaphore_register[RCS] != MI_SEMAPHORE_SYNC_INVALID,
543*e3adcf8fSFrançois Tigeot 	    ("valid RCS semaphore"));
544*e3adcf8fSFrançois Tigeot 	return intel_ring_sync(waiter,
545*e3adcf8fSFrançois Tigeot 			       signaller,
546*e3adcf8fSFrançois Tigeot 			       RCS,
547*e3adcf8fSFrançois Tigeot 			       seqno);
548*e3adcf8fSFrançois Tigeot }
549*e3adcf8fSFrançois Tigeot 
550*e3adcf8fSFrançois Tigeot /* RCS->VCS (VRSYNC) or BCS->VCS (VBSYNC) */
551*e3adcf8fSFrançois Tigeot int
552*e3adcf8fSFrançois Tigeot gen6_bsd_ring_sync_to(struct intel_ring_buffer *waiter,
553*e3adcf8fSFrançois Tigeot 		      struct intel_ring_buffer *signaller,
554*e3adcf8fSFrançois Tigeot 		      u32 seqno)
555*e3adcf8fSFrançois Tigeot {
556*e3adcf8fSFrançois Tigeot 	KASSERT(signaller->semaphore_register[VCS] != MI_SEMAPHORE_SYNC_INVALID,
557*e3adcf8fSFrançois Tigeot 	    ("Valid VCS semaphore"));
558*e3adcf8fSFrançois Tigeot 	return intel_ring_sync(waiter,
559*e3adcf8fSFrançois Tigeot 			       signaller,
560*e3adcf8fSFrançois Tigeot 			       VCS,
561*e3adcf8fSFrançois Tigeot 			       seqno);
562*e3adcf8fSFrançois Tigeot }
563*e3adcf8fSFrançois Tigeot 
564*e3adcf8fSFrançois Tigeot /* RCS->BCS (BRSYNC) or VCS->BCS (BVSYNC) */
565*e3adcf8fSFrançois Tigeot int
566*e3adcf8fSFrançois Tigeot gen6_blt_ring_sync_to(struct intel_ring_buffer *waiter,
567*e3adcf8fSFrançois Tigeot 		      struct intel_ring_buffer *signaller,
568*e3adcf8fSFrançois Tigeot 		      u32 seqno)
569*e3adcf8fSFrançois Tigeot {
570*e3adcf8fSFrançois Tigeot 	KASSERT(signaller->semaphore_register[BCS] != MI_SEMAPHORE_SYNC_INVALID,
571*e3adcf8fSFrançois Tigeot 	    ("Valid BCS semaphore"));
572*e3adcf8fSFrançois Tigeot 	return intel_ring_sync(waiter,
573*e3adcf8fSFrançois Tigeot 			       signaller,
574*e3adcf8fSFrançois Tigeot 			       BCS,
575*e3adcf8fSFrançois Tigeot 			       seqno);
576*e3adcf8fSFrançois Tigeot }
577*e3adcf8fSFrançois Tigeot 
578*e3adcf8fSFrançois Tigeot #define PIPE_CONTROL_FLUSH(ring__, addr__)					\
579*e3adcf8fSFrançois Tigeot do {									\
580*e3adcf8fSFrançois Tigeot 	intel_ring_emit(ring__, GFX_OP_PIPE_CONTROL(4) | PIPE_CONTROL_QW_WRITE |		\
581*e3adcf8fSFrançois Tigeot 		 PIPE_CONTROL_DEPTH_STALL);				\
582*e3adcf8fSFrançois Tigeot 	intel_ring_emit(ring__, (addr__) | PIPE_CONTROL_GLOBAL_GTT);			\
583*e3adcf8fSFrançois Tigeot 	intel_ring_emit(ring__, 0);							\
584*e3adcf8fSFrançois Tigeot 	intel_ring_emit(ring__, 0);							\
585*e3adcf8fSFrançois Tigeot } while (0)
586*e3adcf8fSFrançois Tigeot 
587*e3adcf8fSFrançois Tigeot static int
588*e3adcf8fSFrançois Tigeot pc_render_add_request(struct intel_ring_buffer *ring,
589*e3adcf8fSFrançois Tigeot 		      uint32_t *result)
590*e3adcf8fSFrançois Tigeot {
591*e3adcf8fSFrançois Tigeot 	u32 seqno = i915_gem_next_request_seqno(ring);
592*e3adcf8fSFrançois Tigeot 	struct pipe_control *pc = ring->private;
593*e3adcf8fSFrançois Tigeot 	u32 scratch_addr = pc->gtt_offset + 128;
594*e3adcf8fSFrançois Tigeot 	int ret;
595*e3adcf8fSFrançois Tigeot 
596*e3adcf8fSFrançois Tigeot 	/* For Ironlake, MI_USER_INTERRUPT was deprecated and apparently
597*e3adcf8fSFrançois Tigeot 	 * incoherent with writes to memory, i.e. completely fubar,
598*e3adcf8fSFrançois Tigeot 	 * so we need to use PIPE_NOTIFY instead.
599*e3adcf8fSFrançois Tigeot 	 *
600*e3adcf8fSFrançois Tigeot 	 * However, we also need to workaround the qword write
601*e3adcf8fSFrançois Tigeot 	 * incoherence by flushing the 6 PIPE_NOTIFY buffers out to
602*e3adcf8fSFrançois Tigeot 	 * memory before requesting an interrupt.
603*e3adcf8fSFrançois Tigeot 	 */
604*e3adcf8fSFrançois Tigeot 	ret = intel_ring_begin(ring, 32);
605*e3adcf8fSFrançois Tigeot 	if (ret)
606*e3adcf8fSFrançois Tigeot 		return ret;
607*e3adcf8fSFrançois Tigeot 
608*e3adcf8fSFrançois Tigeot 	intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(4) | PIPE_CONTROL_QW_WRITE |
609*e3adcf8fSFrançois Tigeot 			PIPE_CONTROL_WRITE_FLUSH |
610*e3adcf8fSFrançois Tigeot 			PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE);
611*e3adcf8fSFrançois Tigeot 	intel_ring_emit(ring, pc->gtt_offset | PIPE_CONTROL_GLOBAL_GTT);
612*e3adcf8fSFrançois Tigeot 	intel_ring_emit(ring, seqno);
613*e3adcf8fSFrançois Tigeot 	intel_ring_emit(ring, 0);
614*e3adcf8fSFrançois Tigeot 	PIPE_CONTROL_FLUSH(ring, scratch_addr);
615*e3adcf8fSFrançois Tigeot 	scratch_addr += 128; /* write to separate cachelines */
616*e3adcf8fSFrançois Tigeot 	PIPE_CONTROL_FLUSH(ring, scratch_addr);
617*e3adcf8fSFrançois Tigeot 	scratch_addr += 128;
618*e3adcf8fSFrançois Tigeot 	PIPE_CONTROL_FLUSH(ring, scratch_addr);
619*e3adcf8fSFrançois Tigeot 	scratch_addr += 128;
620*e3adcf8fSFrançois Tigeot 	PIPE_CONTROL_FLUSH(ring, scratch_addr);
621*e3adcf8fSFrançois Tigeot 	scratch_addr += 128;
622*e3adcf8fSFrançois Tigeot 	PIPE_CONTROL_FLUSH(ring, scratch_addr);
623*e3adcf8fSFrançois Tigeot 	scratch_addr += 128;
624*e3adcf8fSFrançois Tigeot 	PIPE_CONTROL_FLUSH(ring, scratch_addr);
625*e3adcf8fSFrançois Tigeot 	intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(4) | PIPE_CONTROL_QW_WRITE |
626*e3adcf8fSFrançois Tigeot 			PIPE_CONTROL_WRITE_FLUSH |
627*e3adcf8fSFrançois Tigeot 			PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE |
628*e3adcf8fSFrançois Tigeot 			PIPE_CONTROL_NOTIFY);
629*e3adcf8fSFrançois Tigeot 	intel_ring_emit(ring, pc->gtt_offset | PIPE_CONTROL_GLOBAL_GTT);
630*e3adcf8fSFrançois Tigeot 	intel_ring_emit(ring, seqno);
631*e3adcf8fSFrançois Tigeot 	intel_ring_emit(ring, 0);
632*e3adcf8fSFrançois Tigeot 	intel_ring_advance(ring);
633*e3adcf8fSFrançois Tigeot 
634*e3adcf8fSFrançois Tigeot 	*result = seqno;
635*e3adcf8fSFrançois Tigeot 	return 0;
636*e3adcf8fSFrançois Tigeot }
637*e3adcf8fSFrançois Tigeot 
638*e3adcf8fSFrançois Tigeot static int
639*e3adcf8fSFrançois Tigeot render_ring_add_request(struct intel_ring_buffer *ring,
640*e3adcf8fSFrançois Tigeot 			uint32_t *result)
641*e3adcf8fSFrançois Tigeot {
642*e3adcf8fSFrançois Tigeot 	u32 seqno = i915_gem_next_request_seqno(ring);
643*e3adcf8fSFrançois Tigeot 	int ret;
644*e3adcf8fSFrançois Tigeot 
645*e3adcf8fSFrançois Tigeot 	ret = intel_ring_begin(ring, 4);
646*e3adcf8fSFrançois Tigeot 	if (ret)
647*e3adcf8fSFrançois Tigeot 		return ret;
648*e3adcf8fSFrançois Tigeot 
649*e3adcf8fSFrançois Tigeot 	intel_ring_emit(ring, MI_STORE_DWORD_INDEX);
650*e3adcf8fSFrançois Tigeot 	intel_ring_emit(ring, I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT);
651*e3adcf8fSFrançois Tigeot 	intel_ring_emit(ring, seqno);
652*e3adcf8fSFrançois Tigeot 	intel_ring_emit(ring, MI_USER_INTERRUPT);
653*e3adcf8fSFrançois Tigeot 	intel_ring_advance(ring);
654*e3adcf8fSFrançois Tigeot 
655*e3adcf8fSFrançois Tigeot 	*result = seqno;
656*e3adcf8fSFrançois Tigeot 	return 0;
657*e3adcf8fSFrançois Tigeot }
658*e3adcf8fSFrançois Tigeot 
659*e3adcf8fSFrançois Tigeot  static u32
660*e3adcf8fSFrançois Tigeot gen6_ring_get_seqno(struct intel_ring_buffer *ring)
661*e3adcf8fSFrançois Tigeot {
662*e3adcf8fSFrançois Tigeot 	struct drm_device *dev = ring->dev;
663*e3adcf8fSFrançois Tigeot 
664*e3adcf8fSFrançois Tigeot 	/* Workaround to force correct ordering between irq and seqno writes on
665*e3adcf8fSFrançois Tigeot 	 * ivb (and maybe also on snb) by reading from a CS register (like
666*e3adcf8fSFrançois Tigeot 	 * ACTHD) before reading the status page. */
667*e3adcf8fSFrançois Tigeot 	if (/* IS_GEN6(dev) || */IS_GEN7(dev))
668*e3adcf8fSFrançois Tigeot 		intel_ring_get_active_head(ring);
669*e3adcf8fSFrançois Tigeot 	return intel_read_status_page(ring, I915_GEM_HWS_INDEX);
670*e3adcf8fSFrançois Tigeot }
671*e3adcf8fSFrançois Tigeot 
672*e3adcf8fSFrançois Tigeot static uint32_t
673*e3adcf8fSFrançois Tigeot ring_get_seqno(struct intel_ring_buffer *ring)
674*e3adcf8fSFrançois Tigeot {
675*e3adcf8fSFrançois Tigeot 	if (ring->status_page.page_addr == NULL)
676*e3adcf8fSFrançois Tigeot 		return (-1);
677*e3adcf8fSFrançois Tigeot 	return intel_read_status_page(ring, I915_GEM_HWS_INDEX);
678*e3adcf8fSFrançois Tigeot }
679*e3adcf8fSFrançois Tigeot 
680*e3adcf8fSFrançois Tigeot static uint32_t
681*e3adcf8fSFrançois Tigeot pc_render_get_seqno(struct intel_ring_buffer *ring)
682*e3adcf8fSFrançois Tigeot {
683*e3adcf8fSFrançois Tigeot 	struct pipe_control *pc = ring->private;
684*e3adcf8fSFrançois Tigeot 	if (pc != NULL)
685*e3adcf8fSFrançois Tigeot 		return pc->cpu_page[0];
686*e3adcf8fSFrançois Tigeot 	else
687*e3adcf8fSFrançois Tigeot 		return (-1);
688*e3adcf8fSFrançois Tigeot }
689*e3adcf8fSFrançois Tigeot 
690*e3adcf8fSFrançois Tigeot static void
691*e3adcf8fSFrançois Tigeot ironlake_enable_irq(drm_i915_private_t *dev_priv, uint32_t mask)
692*e3adcf8fSFrançois Tigeot {
693*e3adcf8fSFrançois Tigeot 	dev_priv->gt_irq_mask &= ~mask;
694*e3adcf8fSFrançois Tigeot 	I915_WRITE(GTIMR, dev_priv->gt_irq_mask);
695*e3adcf8fSFrançois Tigeot 	POSTING_READ(GTIMR);
696*e3adcf8fSFrançois Tigeot }
697*e3adcf8fSFrançois Tigeot 
698*e3adcf8fSFrançois Tigeot static void
699*e3adcf8fSFrançois Tigeot ironlake_disable_irq(drm_i915_private_t *dev_priv, uint32_t mask)
700*e3adcf8fSFrançois Tigeot {
701*e3adcf8fSFrançois Tigeot 	dev_priv->gt_irq_mask |= mask;
702*e3adcf8fSFrançois Tigeot 	I915_WRITE(GTIMR, dev_priv->gt_irq_mask);
703*e3adcf8fSFrançois Tigeot 	POSTING_READ(GTIMR);
704*e3adcf8fSFrançois Tigeot }
705*e3adcf8fSFrançois Tigeot 
706*e3adcf8fSFrançois Tigeot static void
707*e3adcf8fSFrançois Tigeot i915_enable_irq(drm_i915_private_t *dev_priv, uint32_t mask)
708*e3adcf8fSFrançois Tigeot {
709*e3adcf8fSFrançois Tigeot 	dev_priv->irq_mask &= ~mask;
710*e3adcf8fSFrançois Tigeot 	I915_WRITE(IMR, dev_priv->irq_mask);
711*e3adcf8fSFrançois Tigeot 	POSTING_READ(IMR);
712*e3adcf8fSFrançois Tigeot }
713*e3adcf8fSFrançois Tigeot 
714*e3adcf8fSFrançois Tigeot static void
715*e3adcf8fSFrançois Tigeot i915_disable_irq(drm_i915_private_t *dev_priv, uint32_t mask)
716*e3adcf8fSFrançois Tigeot {
717*e3adcf8fSFrançois Tigeot 	dev_priv->irq_mask |= mask;
718*e3adcf8fSFrançois Tigeot 	I915_WRITE(IMR, dev_priv->irq_mask);
719*e3adcf8fSFrançois Tigeot 	POSTING_READ(IMR);
720*e3adcf8fSFrançois Tigeot }
721*e3adcf8fSFrançois Tigeot 
722*e3adcf8fSFrançois Tigeot static bool
723*e3adcf8fSFrançois Tigeot render_ring_get_irq(struct intel_ring_buffer *ring)
724*e3adcf8fSFrançois Tigeot {
725*e3adcf8fSFrançois Tigeot 	struct drm_device *dev = ring->dev;
726*e3adcf8fSFrançois Tigeot 	drm_i915_private_t *dev_priv = dev->dev_private;
727*e3adcf8fSFrançois Tigeot 
728*e3adcf8fSFrançois Tigeot 	if (!dev->irq_enabled)
729*e3adcf8fSFrançois Tigeot 		return false;
730*e3adcf8fSFrançois Tigeot 
731*e3adcf8fSFrançois Tigeot 	KKASSERT(lockstatus(&ring->irq_lock, curthread) != 0);
732*e3adcf8fSFrançois Tigeot 	if (ring->irq_refcount++ == 0) {
733*e3adcf8fSFrançois Tigeot 		if (HAS_PCH_SPLIT(dev))
734*e3adcf8fSFrançois Tigeot 			ironlake_enable_irq(dev_priv,
735*e3adcf8fSFrançois Tigeot 					    GT_PIPE_NOTIFY | GT_USER_INTERRUPT);
736*e3adcf8fSFrançois Tigeot 		else
737*e3adcf8fSFrançois Tigeot 			i915_enable_irq(dev_priv, I915_USER_INTERRUPT);
738*e3adcf8fSFrançois Tigeot 	}
739*e3adcf8fSFrançois Tigeot 
740*e3adcf8fSFrançois Tigeot 	return true;
741*e3adcf8fSFrançois Tigeot }
742*e3adcf8fSFrançois Tigeot 
743*e3adcf8fSFrançois Tigeot static void
744*e3adcf8fSFrançois Tigeot render_ring_put_irq(struct intel_ring_buffer *ring)
745*e3adcf8fSFrançois Tigeot {
746*e3adcf8fSFrançois Tigeot 	struct drm_device *dev = ring->dev;
747*e3adcf8fSFrançois Tigeot 	drm_i915_private_t *dev_priv = dev->dev_private;
748*e3adcf8fSFrançois Tigeot 
749*e3adcf8fSFrançois Tigeot 	KKASSERT(lockstatus(&ring->irq_lock, curthread) != 0);
750*e3adcf8fSFrançois Tigeot 	if (--ring->irq_refcount == 0) {
751*e3adcf8fSFrançois Tigeot 		if (HAS_PCH_SPLIT(dev))
752*e3adcf8fSFrançois Tigeot 			ironlake_disable_irq(dev_priv,
753*e3adcf8fSFrançois Tigeot 					     GT_USER_INTERRUPT |
754*e3adcf8fSFrançois Tigeot 					     GT_PIPE_NOTIFY);
755*e3adcf8fSFrançois Tigeot 		else
756*e3adcf8fSFrançois Tigeot 			i915_disable_irq(dev_priv, I915_USER_INTERRUPT);
757*e3adcf8fSFrançois Tigeot 	}
758*e3adcf8fSFrançois Tigeot }
759*e3adcf8fSFrançois Tigeot 
760*e3adcf8fSFrançois Tigeot void intel_ring_setup_status_page(struct intel_ring_buffer *ring)
761*e3adcf8fSFrançois Tigeot {
762*e3adcf8fSFrançois Tigeot 	struct drm_device *dev = ring->dev;
763*e3adcf8fSFrançois Tigeot 	drm_i915_private_t *dev_priv = dev->dev_private;
764*e3adcf8fSFrançois Tigeot 	uint32_t mmio = 0;
765*e3adcf8fSFrançois Tigeot 
766*e3adcf8fSFrançois Tigeot 	/* The ring status page addresses are no longer next to the rest of
767*e3adcf8fSFrançois Tigeot 	 * the ring registers as of gen7.
768*e3adcf8fSFrançois Tigeot 	 */
769*e3adcf8fSFrançois Tigeot 	if (IS_GEN7(dev)) {
770*e3adcf8fSFrançois Tigeot 		switch (ring->id) {
771*e3adcf8fSFrançois Tigeot 		case RCS:
772*e3adcf8fSFrançois Tigeot 			mmio = RENDER_HWS_PGA_GEN7;
773*e3adcf8fSFrançois Tigeot 			break;
774*e3adcf8fSFrançois Tigeot 		case BCS:
775*e3adcf8fSFrançois Tigeot 			mmio = BLT_HWS_PGA_GEN7;
776*e3adcf8fSFrançois Tigeot 			break;
777*e3adcf8fSFrançois Tigeot 		case VCS:
778*e3adcf8fSFrançois Tigeot 			mmio = BSD_HWS_PGA_GEN7;
779*e3adcf8fSFrançois Tigeot 			break;
780*e3adcf8fSFrançois Tigeot 		}
781*e3adcf8fSFrançois Tigeot 	} else if (IS_GEN6(dev)) {
782*e3adcf8fSFrançois Tigeot 		mmio = RING_HWS_PGA_GEN6(ring->mmio_base);
783*e3adcf8fSFrançois Tigeot 	} else {
784*e3adcf8fSFrançois Tigeot 		mmio = RING_HWS_PGA(ring->mmio_base);
785*e3adcf8fSFrançois Tigeot 	}
786*e3adcf8fSFrançois Tigeot 
787*e3adcf8fSFrançois Tigeot 	I915_WRITE(mmio, (u32)ring->status_page.gfx_addr);
788*e3adcf8fSFrançois Tigeot 	POSTING_READ(mmio);
789*e3adcf8fSFrançois Tigeot }
790*e3adcf8fSFrançois Tigeot 
791*e3adcf8fSFrançois Tigeot static int
792*e3adcf8fSFrançois Tigeot bsd_ring_flush(struct intel_ring_buffer *ring,
793*e3adcf8fSFrançois Tigeot 	       uint32_t     invalidate_domains,
794*e3adcf8fSFrançois Tigeot 	       uint32_t     flush_domains)
795*e3adcf8fSFrançois Tigeot {
796*e3adcf8fSFrançois Tigeot 	int ret;
797*e3adcf8fSFrançois Tigeot 
798*e3adcf8fSFrançois Tigeot 	ret = intel_ring_begin(ring, 2);
799*e3adcf8fSFrançois Tigeot 	if (ret)
800*e3adcf8fSFrançois Tigeot 		return ret;
801*e3adcf8fSFrançois Tigeot 
802*e3adcf8fSFrançois Tigeot 	intel_ring_emit(ring, MI_FLUSH);
803*e3adcf8fSFrançois Tigeot 	intel_ring_emit(ring, MI_NOOP);
804*e3adcf8fSFrançois Tigeot 	intel_ring_advance(ring);
805*e3adcf8fSFrançois Tigeot 	return 0;
806*e3adcf8fSFrançois Tigeot }
807*e3adcf8fSFrançois Tigeot 
808*e3adcf8fSFrançois Tigeot static int
809*e3adcf8fSFrançois Tigeot ring_add_request(struct intel_ring_buffer *ring,
810*e3adcf8fSFrançois Tigeot 		 uint32_t *result)
811*e3adcf8fSFrançois Tigeot {
812*e3adcf8fSFrançois Tigeot 	uint32_t seqno;
813*e3adcf8fSFrançois Tigeot 	int ret;
814*e3adcf8fSFrançois Tigeot 
815*e3adcf8fSFrançois Tigeot 	ret = intel_ring_begin(ring, 4);
816*e3adcf8fSFrançois Tigeot 	if (ret)
817*e3adcf8fSFrançois Tigeot 		return ret;
818*e3adcf8fSFrançois Tigeot 
819*e3adcf8fSFrançois Tigeot 	seqno = i915_gem_next_request_seqno(ring);
820*e3adcf8fSFrançois Tigeot 
821*e3adcf8fSFrançois Tigeot 	intel_ring_emit(ring, MI_STORE_DWORD_INDEX);
822*e3adcf8fSFrançois Tigeot 	intel_ring_emit(ring, I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT);
823*e3adcf8fSFrançois Tigeot 	intel_ring_emit(ring, seqno);
824*e3adcf8fSFrançois Tigeot 	intel_ring_emit(ring, MI_USER_INTERRUPT);
825*e3adcf8fSFrançois Tigeot 	intel_ring_advance(ring);
826*e3adcf8fSFrançois Tigeot 
827*e3adcf8fSFrançois Tigeot 	*result = seqno;
828*e3adcf8fSFrançois Tigeot 	return 0;
829*e3adcf8fSFrançois Tigeot }
830*e3adcf8fSFrançois Tigeot 
831*e3adcf8fSFrançois Tigeot static bool
832*e3adcf8fSFrançois Tigeot gen6_ring_get_irq(struct intel_ring_buffer *ring, uint32_t gflag, uint32_t rflag)
833*e3adcf8fSFrançois Tigeot {
834*e3adcf8fSFrançois Tigeot 	struct drm_device *dev = ring->dev;
835*e3adcf8fSFrançois Tigeot 	drm_i915_private_t *dev_priv = dev->dev_private;
836*e3adcf8fSFrançois Tigeot 
837*e3adcf8fSFrançois Tigeot 	if (!dev->irq_enabled)
838*e3adcf8fSFrançois Tigeot 	       return false;
839*e3adcf8fSFrançois Tigeot 
840*e3adcf8fSFrançois Tigeot 	gen6_gt_force_wake_get(dev_priv);
841*e3adcf8fSFrançois Tigeot 
842*e3adcf8fSFrançois Tigeot 	KKASSERT(lockstatus(&ring->irq_lock, curthread) != 0);
843*e3adcf8fSFrançois Tigeot 	if (ring->irq_refcount++ == 0) {
844*e3adcf8fSFrançois Tigeot 		ring->irq_mask &= ~rflag;
845*e3adcf8fSFrançois Tigeot 		I915_WRITE_IMR(ring, ring->irq_mask);
846*e3adcf8fSFrançois Tigeot 		ironlake_enable_irq(dev_priv, gflag);
847*e3adcf8fSFrançois Tigeot 	}
848*e3adcf8fSFrançois Tigeot 
849*e3adcf8fSFrançois Tigeot 	return true;
850*e3adcf8fSFrançois Tigeot }
851*e3adcf8fSFrançois Tigeot 
852*e3adcf8fSFrançois Tigeot static void
853*e3adcf8fSFrançois Tigeot gen6_ring_put_irq(struct intel_ring_buffer *ring, uint32_t gflag, uint32_t rflag)
854*e3adcf8fSFrançois Tigeot {
855*e3adcf8fSFrançois Tigeot 	struct drm_device *dev = ring->dev;
856*e3adcf8fSFrançois Tigeot 	drm_i915_private_t *dev_priv = dev->dev_private;
857*e3adcf8fSFrançois Tigeot 
858*e3adcf8fSFrançois Tigeot 	KKASSERT(lockstatus(&ring->irq_lock, curthread) != 0);
859*e3adcf8fSFrançois Tigeot 	if (--ring->irq_refcount == 0) {
860*e3adcf8fSFrançois Tigeot 		ring->irq_mask |= rflag;
861*e3adcf8fSFrançois Tigeot 		I915_WRITE_IMR(ring, ring->irq_mask);
862*e3adcf8fSFrançois Tigeot 		ironlake_disable_irq(dev_priv, gflag);
863*e3adcf8fSFrançois Tigeot 	}
864*e3adcf8fSFrançois Tigeot 
865*e3adcf8fSFrançois Tigeot 	gen6_gt_force_wake_put(dev_priv);
866*e3adcf8fSFrançois Tigeot }
867*e3adcf8fSFrançois Tigeot 
868*e3adcf8fSFrançois Tigeot static bool
869*e3adcf8fSFrançois Tigeot bsd_ring_get_irq(struct intel_ring_buffer *ring)
870*e3adcf8fSFrançois Tigeot {
871*e3adcf8fSFrançois Tigeot 	struct drm_device *dev = ring->dev;
872*e3adcf8fSFrançois Tigeot 	drm_i915_private_t *dev_priv = dev->dev_private;
873*e3adcf8fSFrançois Tigeot 
874*e3adcf8fSFrançois Tigeot 	if (!dev->irq_enabled)
875*e3adcf8fSFrançois Tigeot 		return false;
876*e3adcf8fSFrançois Tigeot 
877*e3adcf8fSFrançois Tigeot 	KKASSERT(lockstatus(&ring->irq_lock, curthread) != 0);
878*e3adcf8fSFrançois Tigeot 	if (ring->irq_refcount++ == 0) {
879*e3adcf8fSFrançois Tigeot 		if (IS_G4X(dev))
880*e3adcf8fSFrançois Tigeot 			i915_enable_irq(dev_priv, I915_BSD_USER_INTERRUPT);
881*e3adcf8fSFrançois Tigeot 		else
882*e3adcf8fSFrançois Tigeot 			ironlake_enable_irq(dev_priv, GT_BSD_USER_INTERRUPT);
883*e3adcf8fSFrançois Tigeot 	}
884*e3adcf8fSFrançois Tigeot 
885*e3adcf8fSFrançois Tigeot 	return true;
886*e3adcf8fSFrançois Tigeot }
887*e3adcf8fSFrançois Tigeot static void
888*e3adcf8fSFrançois Tigeot bsd_ring_put_irq(struct intel_ring_buffer *ring)
889*e3adcf8fSFrançois Tigeot {
890*e3adcf8fSFrançois Tigeot 	struct drm_device *dev = ring->dev;
891*e3adcf8fSFrançois Tigeot 	drm_i915_private_t *dev_priv = dev->dev_private;
892*e3adcf8fSFrançois Tigeot 
893*e3adcf8fSFrançois Tigeot 	KKASSERT(lockstatus(&ring->irq_lock, curthread) != 0);
894*e3adcf8fSFrançois Tigeot 	if (--ring->irq_refcount == 0) {
895*e3adcf8fSFrançois Tigeot 		if (IS_G4X(dev))
896*e3adcf8fSFrançois Tigeot 			i915_disable_irq(dev_priv, I915_BSD_USER_INTERRUPT);
897*e3adcf8fSFrançois Tigeot 		else
898*e3adcf8fSFrançois Tigeot 			ironlake_disable_irq(dev_priv, GT_BSD_USER_INTERRUPT);
899*e3adcf8fSFrançois Tigeot 	}
900*e3adcf8fSFrançois Tigeot }
901*e3adcf8fSFrançois Tigeot 
902*e3adcf8fSFrançois Tigeot static int
903*e3adcf8fSFrançois Tigeot ring_dispatch_execbuffer(struct intel_ring_buffer *ring, uint32_t offset,
904*e3adcf8fSFrançois Tigeot     uint32_t length)
905*e3adcf8fSFrançois Tigeot {
906*e3adcf8fSFrançois Tigeot 	int ret;
907*e3adcf8fSFrançois Tigeot 
908*e3adcf8fSFrançois Tigeot 	ret = intel_ring_begin(ring, 2);
909*e3adcf8fSFrançois Tigeot 	if (ret)
910*e3adcf8fSFrançois Tigeot 		return ret;
911*e3adcf8fSFrançois Tigeot 
912*e3adcf8fSFrançois Tigeot 	intel_ring_emit(ring,
913*e3adcf8fSFrançois Tigeot 			MI_BATCH_BUFFER_START | (2 << 6) |
914*e3adcf8fSFrançois Tigeot 			MI_BATCH_NON_SECURE_I965);
915*e3adcf8fSFrançois Tigeot 	intel_ring_emit(ring, offset);
916*e3adcf8fSFrançois Tigeot 	intel_ring_advance(ring);
917*e3adcf8fSFrançois Tigeot 
918*e3adcf8fSFrançois Tigeot 	return 0;
919*e3adcf8fSFrançois Tigeot }
920*e3adcf8fSFrançois Tigeot 
921*e3adcf8fSFrançois Tigeot static int
922*e3adcf8fSFrançois Tigeot render_ring_dispatch_execbuffer(struct intel_ring_buffer *ring,
923*e3adcf8fSFrançois Tigeot 				uint32_t offset, uint32_t len)
924*e3adcf8fSFrançois Tigeot {
925*e3adcf8fSFrançois Tigeot 	struct drm_device *dev = ring->dev;
926*e3adcf8fSFrançois Tigeot 	int ret;
927*e3adcf8fSFrançois Tigeot 
928*e3adcf8fSFrançois Tigeot 	if (IS_I830(dev) || IS_845G(dev)) {
929*e3adcf8fSFrançois Tigeot 		ret = intel_ring_begin(ring, 4);
930*e3adcf8fSFrançois Tigeot 		if (ret)
931*e3adcf8fSFrançois Tigeot 			return ret;
932*e3adcf8fSFrançois Tigeot 
933*e3adcf8fSFrançois Tigeot 		intel_ring_emit(ring, MI_BATCH_BUFFER);
934*e3adcf8fSFrançois Tigeot 		intel_ring_emit(ring, offset | MI_BATCH_NON_SECURE);
935*e3adcf8fSFrançois Tigeot 		intel_ring_emit(ring, offset + len - 8);
936*e3adcf8fSFrançois Tigeot 		intel_ring_emit(ring, 0);
937*e3adcf8fSFrançois Tigeot 	} else {
938*e3adcf8fSFrançois Tigeot 		ret = intel_ring_begin(ring, 2);
939*e3adcf8fSFrançois Tigeot 		if (ret)
940*e3adcf8fSFrançois Tigeot 			return ret;
941*e3adcf8fSFrançois Tigeot 
942*e3adcf8fSFrançois Tigeot 		if (INTEL_INFO(dev)->gen >= 4) {
943*e3adcf8fSFrançois Tigeot 			intel_ring_emit(ring,
944*e3adcf8fSFrançois Tigeot 					MI_BATCH_BUFFER_START | (2 << 6) |
945*e3adcf8fSFrançois Tigeot 					MI_BATCH_NON_SECURE_I965);
946*e3adcf8fSFrançois Tigeot 			intel_ring_emit(ring, offset);
947*e3adcf8fSFrançois Tigeot 		} else {
948*e3adcf8fSFrançois Tigeot 			intel_ring_emit(ring,
949*e3adcf8fSFrançois Tigeot 					MI_BATCH_BUFFER_START | (2 << 6));
950*e3adcf8fSFrançois Tigeot 			intel_ring_emit(ring, offset | MI_BATCH_NON_SECURE);
951*e3adcf8fSFrançois Tigeot 		}
952*e3adcf8fSFrançois Tigeot 	}
953*e3adcf8fSFrançois Tigeot 	intel_ring_advance(ring);
954*e3adcf8fSFrançois Tigeot 
955*e3adcf8fSFrançois Tigeot 	return 0;
956*e3adcf8fSFrançois Tigeot }
957*e3adcf8fSFrançois Tigeot 
958*e3adcf8fSFrançois Tigeot static void cleanup_status_page(struct intel_ring_buffer *ring)
959*e3adcf8fSFrançois Tigeot {
960*e3adcf8fSFrançois Tigeot 	drm_i915_private_t *dev_priv = ring->dev->dev_private;
961*e3adcf8fSFrançois Tigeot 	struct drm_i915_gem_object *obj;
962*e3adcf8fSFrançois Tigeot 
963*e3adcf8fSFrançois Tigeot 	obj = ring->status_page.obj;
964*e3adcf8fSFrançois Tigeot 	if (obj == NULL)
965*e3adcf8fSFrançois Tigeot 		return;
966*e3adcf8fSFrançois Tigeot 
967*e3adcf8fSFrançois Tigeot 	pmap_qremove((vm_offset_t)ring->status_page.page_addr, 1);
968*e3adcf8fSFrançois Tigeot 	kmem_free(&kernel_map, (vm_offset_t)ring->status_page.page_addr,
969*e3adcf8fSFrançois Tigeot 	    PAGE_SIZE);
970*e3adcf8fSFrançois Tigeot 	i915_gem_object_unpin(obj);
971*e3adcf8fSFrançois Tigeot 	drm_gem_object_unreference(&obj->base);
972*e3adcf8fSFrançois Tigeot 	ring->status_page.obj = NULL;
973*e3adcf8fSFrançois Tigeot 
974*e3adcf8fSFrançois Tigeot 	memset(&dev_priv->hws_map, 0, sizeof(dev_priv->hws_map));
975*e3adcf8fSFrançois Tigeot }
976*e3adcf8fSFrançois Tigeot 
977*e3adcf8fSFrançois Tigeot static int init_status_page(struct intel_ring_buffer *ring)
978*e3adcf8fSFrançois Tigeot {
979*e3adcf8fSFrançois Tigeot 	struct drm_device *dev = ring->dev;
980*e3adcf8fSFrançois Tigeot 	drm_i915_private_t *dev_priv = dev->dev_private;
981*e3adcf8fSFrançois Tigeot 	struct drm_i915_gem_object *obj;
982*e3adcf8fSFrançois Tigeot 	int ret;
983*e3adcf8fSFrançois Tigeot 
984*e3adcf8fSFrançois Tigeot 	obj = i915_gem_alloc_object(dev, 4096);
985*e3adcf8fSFrançois Tigeot 	if (obj == NULL) {
986*e3adcf8fSFrançois Tigeot 		DRM_ERROR("Failed to allocate status page\n");
987*e3adcf8fSFrançois Tigeot 		ret = -ENOMEM;
988*e3adcf8fSFrançois Tigeot 		goto err;
989*e3adcf8fSFrançois Tigeot 	}
990*e3adcf8fSFrançois Tigeot 
991*e3adcf8fSFrançois Tigeot 	i915_gem_object_set_cache_level(obj, I915_CACHE_LLC);
992*e3adcf8fSFrançois Tigeot 
993*e3adcf8fSFrançois Tigeot 	ret = i915_gem_object_pin(obj, 4096, true);
994*e3adcf8fSFrançois Tigeot 	if (ret != 0) {
995*e3adcf8fSFrançois Tigeot 		goto err_unref;
996*e3adcf8fSFrançois Tigeot 	}
997*e3adcf8fSFrançois Tigeot 
998*e3adcf8fSFrançois Tigeot 	ring->status_page.gfx_addr = obj->gtt_offset;
999*e3adcf8fSFrançois Tigeot 	ring->status_page.page_addr = (void *)kmem_alloc_nofault(&kernel_map,
1000*e3adcf8fSFrançois Tigeot 	    PAGE_SIZE, PAGE_SIZE);
1001*e3adcf8fSFrançois Tigeot 	if (ring->status_page.page_addr == NULL) {
1002*e3adcf8fSFrançois Tigeot 		memset(&dev_priv->hws_map, 0, sizeof(dev_priv->hws_map));
1003*e3adcf8fSFrançois Tigeot 		goto err_unpin;
1004*e3adcf8fSFrançois Tigeot 	}
1005*e3adcf8fSFrançois Tigeot 	pmap_qenter((vm_offset_t)ring->status_page.page_addr, &obj->pages[0],
1006*e3adcf8fSFrançois Tigeot 	    1);
1007*e3adcf8fSFrançois Tigeot 	pmap_invalidate_cache_range((vm_offset_t)ring->status_page.page_addr,
1008*e3adcf8fSFrançois Tigeot 	    (vm_offset_t)ring->status_page.page_addr + PAGE_SIZE);
1009*e3adcf8fSFrançois Tigeot 	ring->status_page.obj = obj;
1010*e3adcf8fSFrançois Tigeot 	memset(ring->status_page.page_addr, 0, PAGE_SIZE);
1011*e3adcf8fSFrançois Tigeot 
1012*e3adcf8fSFrançois Tigeot 	intel_ring_setup_status_page(ring);
1013*e3adcf8fSFrançois Tigeot 	DRM_DEBUG("i915: init_status_page %s hws offset: 0x%08x\n",
1014*e3adcf8fSFrançois Tigeot 			ring->name, ring->status_page.gfx_addr);
1015*e3adcf8fSFrançois Tigeot 
1016*e3adcf8fSFrançois Tigeot 	return 0;
1017*e3adcf8fSFrançois Tigeot 
1018*e3adcf8fSFrançois Tigeot err_unpin:
1019*e3adcf8fSFrançois Tigeot 	i915_gem_object_unpin(obj);
1020*e3adcf8fSFrançois Tigeot err_unref:
1021*e3adcf8fSFrançois Tigeot 	drm_gem_object_unreference(&obj->base);
1022*e3adcf8fSFrançois Tigeot err:
1023*e3adcf8fSFrançois Tigeot 	return ret;
1024*e3adcf8fSFrançois Tigeot }
1025*e3adcf8fSFrançois Tigeot 
1026*e3adcf8fSFrançois Tigeot static
1027*e3adcf8fSFrançois Tigeot int intel_init_ring_buffer(struct drm_device *dev,
1028*e3adcf8fSFrançois Tigeot 			   struct intel_ring_buffer *ring)
1029*e3adcf8fSFrançois Tigeot {
1030*e3adcf8fSFrançois Tigeot 	struct drm_i915_gem_object *obj;
1031*e3adcf8fSFrançois Tigeot 	int ret;
1032*e3adcf8fSFrançois Tigeot 
1033*e3adcf8fSFrançois Tigeot 	ring->dev = dev;
1034*e3adcf8fSFrançois Tigeot 	INIT_LIST_HEAD(&ring->active_list);
1035*e3adcf8fSFrançois Tigeot 	INIT_LIST_HEAD(&ring->request_list);
1036*e3adcf8fSFrançois Tigeot 	INIT_LIST_HEAD(&ring->gpu_write_list);
1037*e3adcf8fSFrançois Tigeot 
1038*e3adcf8fSFrançois Tigeot 	lockinit(&ring->irq_lock, "ringb", 0, LK_CANRECURSE);
1039*e3adcf8fSFrançois Tigeot 	ring->irq_mask = ~0;
1040*e3adcf8fSFrançois Tigeot 
1041*e3adcf8fSFrançois Tigeot 	if (I915_NEED_GFX_HWS(dev)) {
1042*e3adcf8fSFrançois Tigeot 		ret = init_status_page(ring);
1043*e3adcf8fSFrançois Tigeot 		if (ret)
1044*e3adcf8fSFrançois Tigeot 			return ret;
1045*e3adcf8fSFrançois Tigeot 	}
1046*e3adcf8fSFrançois Tigeot 
1047*e3adcf8fSFrançois Tigeot 	obj = i915_gem_alloc_object(dev, ring->size);
1048*e3adcf8fSFrançois Tigeot 	if (obj == NULL) {
1049*e3adcf8fSFrançois Tigeot 		DRM_ERROR("Failed to allocate ringbuffer\n");
1050*e3adcf8fSFrançois Tigeot 		ret = -ENOMEM;
1051*e3adcf8fSFrançois Tigeot 		goto err_hws;
1052*e3adcf8fSFrançois Tigeot 	}
1053*e3adcf8fSFrançois Tigeot 
1054*e3adcf8fSFrançois Tigeot 	ring->obj = obj;
1055*e3adcf8fSFrançois Tigeot 
1056*e3adcf8fSFrançois Tigeot 	ret = i915_gem_object_pin(obj, PAGE_SIZE, true);
1057*e3adcf8fSFrançois Tigeot 	if (ret)
1058*e3adcf8fSFrançois Tigeot 		goto err_unref;
1059*e3adcf8fSFrançois Tigeot 
1060*e3adcf8fSFrançois Tigeot 	ring->map.size = ring->size;
1061*e3adcf8fSFrançois Tigeot 	ring->map.offset = dev->agp->base + obj->gtt_offset;
1062*e3adcf8fSFrançois Tigeot 	ring->map.type = 0;
1063*e3adcf8fSFrançois Tigeot 	ring->map.flags = 0;
1064*e3adcf8fSFrançois Tigeot 	ring->map.mtrr = 0;
1065*e3adcf8fSFrançois Tigeot 
1066*e3adcf8fSFrançois Tigeot 	drm_core_ioremap_wc(&ring->map, dev);
1067*e3adcf8fSFrançois Tigeot 	if (ring->map.virtual == NULL) {
1068*e3adcf8fSFrançois Tigeot 		DRM_ERROR("Failed to map ringbuffer.\n");
1069*e3adcf8fSFrançois Tigeot 		ret = -EINVAL;
1070*e3adcf8fSFrançois Tigeot 		goto err_unpin;
1071*e3adcf8fSFrançois Tigeot 	}
1072*e3adcf8fSFrançois Tigeot 
1073*e3adcf8fSFrançois Tigeot 	ring->virtual_start = ring->map.virtual;
1074*e3adcf8fSFrançois Tigeot 	ret = ring->init(ring);
1075*e3adcf8fSFrançois Tigeot 	if (ret)
1076*e3adcf8fSFrançois Tigeot 		goto err_unmap;
1077*e3adcf8fSFrançois Tigeot 
1078*e3adcf8fSFrançois Tigeot 	/* Workaround an erratum on the i830 which causes a hang if
1079*e3adcf8fSFrançois Tigeot 	 * the TAIL pointer points to within the last 2 cachelines
1080*e3adcf8fSFrançois Tigeot 	 * of the buffer.
1081*e3adcf8fSFrançois Tigeot 	 */
1082*e3adcf8fSFrançois Tigeot 	ring->effective_size = ring->size;
1083*e3adcf8fSFrançois Tigeot 	if (IS_I830(ring->dev) || IS_845G(ring->dev))
1084*e3adcf8fSFrançois Tigeot 		ring->effective_size -= 128;
1085*e3adcf8fSFrançois Tigeot 
1086*e3adcf8fSFrançois Tigeot 	return 0;
1087*e3adcf8fSFrançois Tigeot 
1088*e3adcf8fSFrançois Tigeot err_unmap:
1089*e3adcf8fSFrançois Tigeot 	drm_core_ioremapfree(&ring->map, dev);
1090*e3adcf8fSFrançois Tigeot err_unpin:
1091*e3adcf8fSFrançois Tigeot 	i915_gem_object_unpin(obj);
1092*e3adcf8fSFrançois Tigeot err_unref:
1093*e3adcf8fSFrançois Tigeot 	drm_gem_object_unreference(&obj->base);
1094*e3adcf8fSFrançois Tigeot 	ring->obj = NULL;
1095*e3adcf8fSFrançois Tigeot err_hws:
1096*e3adcf8fSFrançois Tigeot 	cleanup_status_page(ring);
1097*e3adcf8fSFrançois Tigeot 	return ret;
1098*e3adcf8fSFrançois Tigeot }
1099*e3adcf8fSFrançois Tigeot 
1100*e3adcf8fSFrançois Tigeot void intel_cleanup_ring_buffer(struct intel_ring_buffer *ring)
1101*e3adcf8fSFrançois Tigeot {
1102*e3adcf8fSFrançois Tigeot 	struct drm_i915_private *dev_priv;
1103*e3adcf8fSFrançois Tigeot 	int ret;
1104*e3adcf8fSFrançois Tigeot 
1105*e3adcf8fSFrançois Tigeot 	if (ring->obj == NULL)
1106*e3adcf8fSFrançois Tigeot 		return;
1107*e3adcf8fSFrançois Tigeot 
1108*e3adcf8fSFrançois Tigeot 	/* Disable the ring buffer. The ring must be idle at this point */
1109*e3adcf8fSFrançois Tigeot 	dev_priv = ring->dev->dev_private;
1110*e3adcf8fSFrançois Tigeot 	ret = intel_wait_ring_idle(ring);
1111*e3adcf8fSFrançois Tigeot 	I915_WRITE_CTL(ring, 0);
1112*e3adcf8fSFrançois Tigeot 
1113*e3adcf8fSFrançois Tigeot 	drm_core_ioremapfree(&ring->map, ring->dev);
1114*e3adcf8fSFrançois Tigeot 
1115*e3adcf8fSFrançois Tigeot 	i915_gem_object_unpin(ring->obj);
1116*e3adcf8fSFrançois Tigeot 	drm_gem_object_unreference(&ring->obj->base);
1117*e3adcf8fSFrançois Tigeot 	ring->obj = NULL;
1118*e3adcf8fSFrançois Tigeot 
1119*e3adcf8fSFrançois Tigeot 	if (ring->cleanup)
1120*e3adcf8fSFrançois Tigeot 		ring->cleanup(ring);
1121*e3adcf8fSFrançois Tigeot 
1122*e3adcf8fSFrançois Tigeot 	cleanup_status_page(ring);
1123*e3adcf8fSFrançois Tigeot }
1124*e3adcf8fSFrançois Tigeot 
1125*e3adcf8fSFrançois Tigeot static int intel_wrap_ring_buffer(struct intel_ring_buffer *ring)
1126*e3adcf8fSFrançois Tigeot {
1127*e3adcf8fSFrançois Tigeot 	unsigned int *virt;
1128*e3adcf8fSFrançois Tigeot 	int rem = ring->size - ring->tail;
1129*e3adcf8fSFrançois Tigeot 
1130*e3adcf8fSFrançois Tigeot 	if (ring->space < rem) {
1131*e3adcf8fSFrançois Tigeot 		int ret = intel_wait_ring_buffer(ring, rem);
1132*e3adcf8fSFrançois Tigeot 		if (ret)
1133*e3adcf8fSFrançois Tigeot 			return ret;
1134*e3adcf8fSFrançois Tigeot 	}
1135*e3adcf8fSFrançois Tigeot 
1136*e3adcf8fSFrançois Tigeot 	virt = (unsigned int *)((char *)ring->virtual_start + ring->tail);
1137*e3adcf8fSFrançois Tigeot 	rem /= 8;
1138*e3adcf8fSFrançois Tigeot 	while (rem--) {
1139*e3adcf8fSFrançois Tigeot 		*virt++ = MI_NOOP;
1140*e3adcf8fSFrançois Tigeot 		*virt++ = MI_NOOP;
1141*e3adcf8fSFrançois Tigeot 	}
1142*e3adcf8fSFrançois Tigeot 
1143*e3adcf8fSFrançois Tigeot 	ring->tail = 0;
1144*e3adcf8fSFrançois Tigeot 	ring->space = ring_space(ring);
1145*e3adcf8fSFrançois Tigeot 
1146*e3adcf8fSFrançois Tigeot 	return 0;
1147*e3adcf8fSFrançois Tigeot }
1148*e3adcf8fSFrançois Tigeot 
1149*e3adcf8fSFrançois Tigeot static int intel_ring_wait_seqno(struct intel_ring_buffer *ring, u32 seqno)
1150*e3adcf8fSFrançois Tigeot {
1151*e3adcf8fSFrançois Tigeot 	struct drm_i915_private *dev_priv = ring->dev->dev_private;
1152*e3adcf8fSFrançois Tigeot 	bool was_interruptible;
1153*e3adcf8fSFrançois Tigeot 	int ret;
1154*e3adcf8fSFrançois Tigeot 
1155*e3adcf8fSFrançois Tigeot 	/* XXX As we have not yet audited all the paths to check that
1156*e3adcf8fSFrançois Tigeot 	 * they are ready for ERESTARTSYS from intel_ring_begin, do not
1157*e3adcf8fSFrançois Tigeot 	 * allow us to be interruptible by a signal.
1158*e3adcf8fSFrançois Tigeot 	 */
1159*e3adcf8fSFrançois Tigeot 	was_interruptible = dev_priv->mm.interruptible;
1160*e3adcf8fSFrançois Tigeot 	dev_priv->mm.interruptible = false;
1161*e3adcf8fSFrançois Tigeot 
1162*e3adcf8fSFrançois Tigeot 	ret = i915_wait_request(ring, seqno, true);
1163*e3adcf8fSFrançois Tigeot 
1164*e3adcf8fSFrançois Tigeot 	dev_priv->mm.interruptible = was_interruptible;
1165*e3adcf8fSFrançois Tigeot 
1166*e3adcf8fSFrançois Tigeot 	return ret;
1167*e3adcf8fSFrançois Tigeot }
1168*e3adcf8fSFrançois Tigeot 
1169*e3adcf8fSFrançois Tigeot static int intel_ring_wait_request(struct intel_ring_buffer *ring, int n)
1170*e3adcf8fSFrançois Tigeot {
1171*e3adcf8fSFrançois Tigeot 	struct drm_i915_gem_request *request;
1172*e3adcf8fSFrançois Tigeot 	u32 seqno = 0;
1173*e3adcf8fSFrançois Tigeot 	int ret;
1174*e3adcf8fSFrançois Tigeot 
1175*e3adcf8fSFrançois Tigeot 	i915_gem_retire_requests_ring(ring);
1176*e3adcf8fSFrançois Tigeot 
1177*e3adcf8fSFrançois Tigeot 	if (ring->last_retired_head != -1) {
1178*e3adcf8fSFrançois Tigeot 		ring->head = ring->last_retired_head;
1179*e3adcf8fSFrançois Tigeot 		ring->last_retired_head = -1;
1180*e3adcf8fSFrançois Tigeot 		ring->space = ring_space(ring);
1181*e3adcf8fSFrançois Tigeot 		if (ring->space >= n)
1182*e3adcf8fSFrançois Tigeot 			return 0;
1183*e3adcf8fSFrançois Tigeot 	}
1184*e3adcf8fSFrançois Tigeot 
1185*e3adcf8fSFrançois Tigeot 	list_for_each_entry(request, &ring->request_list, list) {
1186*e3adcf8fSFrançois Tigeot 		int space;
1187*e3adcf8fSFrançois Tigeot 
1188*e3adcf8fSFrançois Tigeot 		if (request->tail == -1)
1189*e3adcf8fSFrançois Tigeot 			continue;
1190*e3adcf8fSFrançois Tigeot 
1191*e3adcf8fSFrançois Tigeot 		space = request->tail - (ring->tail + 8);
1192*e3adcf8fSFrançois Tigeot 		if (space < 0)
1193*e3adcf8fSFrançois Tigeot 			space += ring->size;
1194*e3adcf8fSFrançois Tigeot 		if (space >= n) {
1195*e3adcf8fSFrançois Tigeot 			seqno = request->seqno;
1196*e3adcf8fSFrançois Tigeot 			break;
1197*e3adcf8fSFrançois Tigeot 		}
1198*e3adcf8fSFrançois Tigeot 
1199*e3adcf8fSFrançois Tigeot 		/* Consume this request in case we need more space than
1200*e3adcf8fSFrançois Tigeot 		 * is available and so need to prevent a race between
1201*e3adcf8fSFrançois Tigeot 		 * updating last_retired_head and direct reads of
1202*e3adcf8fSFrançois Tigeot 		 * I915_RING_HEAD. It also provides a nice sanity check.
1203*e3adcf8fSFrançois Tigeot 		 */
1204*e3adcf8fSFrançois Tigeot 		request->tail = -1;
1205*e3adcf8fSFrançois Tigeot 	}
1206*e3adcf8fSFrançois Tigeot 
1207*e3adcf8fSFrançois Tigeot 	if (seqno == 0)
1208*e3adcf8fSFrançois Tigeot 		return -ENOSPC;
1209*e3adcf8fSFrançois Tigeot 
1210*e3adcf8fSFrançois Tigeot 	ret = intel_ring_wait_seqno(ring, seqno);
1211*e3adcf8fSFrançois Tigeot 	if (ret)
1212*e3adcf8fSFrançois Tigeot 		return ret;
1213*e3adcf8fSFrançois Tigeot 
1214*e3adcf8fSFrançois Tigeot 	if (ring->last_retired_head == -1)
1215*e3adcf8fSFrançois Tigeot 		return -ENOSPC;
1216*e3adcf8fSFrançois Tigeot 
1217*e3adcf8fSFrançois Tigeot 	ring->head = ring->last_retired_head;
1218*e3adcf8fSFrançois Tigeot 	ring->last_retired_head = -1;
1219*e3adcf8fSFrançois Tigeot 	ring->space = ring_space(ring);
1220*e3adcf8fSFrançois Tigeot 	if (ring->space < n)
1221*e3adcf8fSFrançois Tigeot 		return -ENOSPC;
1222*e3adcf8fSFrançois Tigeot 
1223*e3adcf8fSFrançois Tigeot 	return 0;
1224*e3adcf8fSFrançois Tigeot }
1225*e3adcf8fSFrançois Tigeot 
1226*e3adcf8fSFrançois Tigeot int intel_wait_ring_buffer(struct intel_ring_buffer *ring, int n)
1227*e3adcf8fSFrançois Tigeot {
1228*e3adcf8fSFrançois Tigeot 	struct drm_device *dev = ring->dev;
1229*e3adcf8fSFrançois Tigeot 	struct drm_i915_private *dev_priv = dev->dev_private;
1230*e3adcf8fSFrançois Tigeot 	int end;
1231*e3adcf8fSFrançois Tigeot 	int ret;
1232*e3adcf8fSFrançois Tigeot 
1233*e3adcf8fSFrançois Tigeot 	ret = intel_ring_wait_request(ring, n);
1234*e3adcf8fSFrançois Tigeot 	if (ret != -ENOSPC)
1235*e3adcf8fSFrançois Tigeot 		return ret;
1236*e3adcf8fSFrançois Tigeot 
1237*e3adcf8fSFrançois Tigeot 	if (drm_core_check_feature(dev, DRIVER_GEM))
1238*e3adcf8fSFrançois Tigeot 		/* With GEM the hangcheck timer should kick us out of the loop,
1239*e3adcf8fSFrançois Tigeot 		 * leaving it early runs the risk of corrupting GEM state (due
1240*e3adcf8fSFrançois Tigeot 		 * to running on almost untested codepaths). But on resume
1241*e3adcf8fSFrançois Tigeot 		 * timers don't work yet, so prevent a complete hang in that
1242*e3adcf8fSFrançois Tigeot 		 * case by choosing an insanely large timeout. */
1243*e3adcf8fSFrançois Tigeot 		end = ticks + hz * 60;
1244*e3adcf8fSFrançois Tigeot 	else
1245*e3adcf8fSFrançois Tigeot 		end = ticks + hz * 3;
1246*e3adcf8fSFrançois Tigeot 	do {
1247*e3adcf8fSFrançois Tigeot 		ring->head = I915_READ_HEAD(ring);
1248*e3adcf8fSFrançois Tigeot 		ring->space = ring_space(ring);
1249*e3adcf8fSFrançois Tigeot 		if (ring->space >= n) {
1250*e3adcf8fSFrançois Tigeot 			return 0;
1251*e3adcf8fSFrançois Tigeot 		}
1252*e3adcf8fSFrançois Tigeot 
1253*e3adcf8fSFrançois Tigeot #if 0
1254*e3adcf8fSFrançois Tigeot 		if (dev->primary->master) {
1255*e3adcf8fSFrançois Tigeot 			struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv;
1256*e3adcf8fSFrançois Tigeot 			if (master_priv->sarea_priv)
1257*e3adcf8fSFrançois Tigeot 				master_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT;
1258*e3adcf8fSFrançois Tigeot 		}
1259*e3adcf8fSFrançois Tigeot #else
1260*e3adcf8fSFrançois Tigeot 		if (dev_priv->sarea_priv)
1261*e3adcf8fSFrançois Tigeot 			dev_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT;
1262*e3adcf8fSFrançois Tigeot #endif
1263*e3adcf8fSFrançois Tigeot 
1264*e3adcf8fSFrançois Tigeot 		DELAY(1000);
1265*e3adcf8fSFrançois Tigeot 		if (atomic_load_acq_32(&dev_priv->mm.wedged) != 0) {
1266*e3adcf8fSFrançois Tigeot 			return -EAGAIN;
1267*e3adcf8fSFrançois Tigeot 		}
1268*e3adcf8fSFrançois Tigeot 	} while (!time_after(ticks, end));
1269*e3adcf8fSFrançois Tigeot 	return -EBUSY;
1270*e3adcf8fSFrançois Tigeot }
1271*e3adcf8fSFrançois Tigeot 
1272*e3adcf8fSFrançois Tigeot int intel_ring_begin(struct intel_ring_buffer *ring,
1273*e3adcf8fSFrançois Tigeot 		     int num_dwords)
1274*e3adcf8fSFrançois Tigeot {
1275*e3adcf8fSFrançois Tigeot 	struct drm_i915_private *dev_priv = ring->dev->dev_private;
1276*e3adcf8fSFrançois Tigeot 	int n = 4*num_dwords;
1277*e3adcf8fSFrançois Tigeot 	int ret;
1278*e3adcf8fSFrançois Tigeot 
1279*e3adcf8fSFrançois Tigeot 	if (atomic_load_acq_int(&dev_priv->mm.wedged))
1280*e3adcf8fSFrançois Tigeot 		return -EIO;
1281*e3adcf8fSFrançois Tigeot 
1282*e3adcf8fSFrançois Tigeot 	if (ring->tail + n > ring->effective_size) {
1283*e3adcf8fSFrançois Tigeot 		ret = intel_wrap_ring_buffer(ring);
1284*e3adcf8fSFrançois Tigeot 		if (ret != 0)
1285*e3adcf8fSFrançois Tigeot 			return ret;
1286*e3adcf8fSFrançois Tigeot 	}
1287*e3adcf8fSFrançois Tigeot 
1288*e3adcf8fSFrançois Tigeot 	if (ring->space < n) {
1289*e3adcf8fSFrançois Tigeot 		ret = intel_wait_ring_buffer(ring, n);
1290*e3adcf8fSFrançois Tigeot 		if (ret != 0)
1291*e3adcf8fSFrançois Tigeot 			return ret;
1292*e3adcf8fSFrançois Tigeot 	}
1293*e3adcf8fSFrançois Tigeot 
1294*e3adcf8fSFrançois Tigeot 	ring->space -= n;
1295*e3adcf8fSFrançois Tigeot 	return 0;
1296*e3adcf8fSFrançois Tigeot }
1297*e3adcf8fSFrançois Tigeot 
1298*e3adcf8fSFrançois Tigeot void intel_ring_advance(struct intel_ring_buffer *ring)
1299*e3adcf8fSFrançois Tigeot {
1300*e3adcf8fSFrançois Tigeot 	ring->tail &= ring->size - 1;
1301*e3adcf8fSFrançois Tigeot 	ring->write_tail(ring, ring->tail);
1302*e3adcf8fSFrançois Tigeot }
1303*e3adcf8fSFrançois Tigeot 
1304*e3adcf8fSFrançois Tigeot static const struct intel_ring_buffer render_ring = {
1305*e3adcf8fSFrançois Tigeot 	.name			= "render ring",
1306*e3adcf8fSFrançois Tigeot 	.id			= RCS,
1307*e3adcf8fSFrançois Tigeot 	.mmio_base		= RENDER_RING_BASE,
1308*e3adcf8fSFrançois Tigeot 	.size			= 32 * PAGE_SIZE,
1309*e3adcf8fSFrançois Tigeot 	.init			= init_render_ring,
1310*e3adcf8fSFrançois Tigeot 	.write_tail		= ring_write_tail,
1311*e3adcf8fSFrançois Tigeot 	.flush			= render_ring_flush,
1312*e3adcf8fSFrançois Tigeot 	.add_request		= render_ring_add_request,
1313*e3adcf8fSFrançois Tigeot 	.get_seqno		= ring_get_seqno,
1314*e3adcf8fSFrançois Tigeot 	.irq_get		= render_ring_get_irq,
1315*e3adcf8fSFrançois Tigeot 	.irq_put		= render_ring_put_irq,
1316*e3adcf8fSFrançois Tigeot 	.dispatch_execbuffer	= render_ring_dispatch_execbuffer,
1317*e3adcf8fSFrançois Tigeot 	.cleanup		= render_ring_cleanup,
1318*e3adcf8fSFrançois Tigeot 	.sync_to		= render_ring_sync_to,
1319*e3adcf8fSFrançois Tigeot 	.semaphore_register	= {MI_SEMAPHORE_SYNC_INVALID,
1320*e3adcf8fSFrançois Tigeot 				   MI_SEMAPHORE_SYNC_RV,
1321*e3adcf8fSFrançois Tigeot 				   MI_SEMAPHORE_SYNC_RB},
1322*e3adcf8fSFrançois Tigeot 	.signal_mbox		= {GEN6_VRSYNC, GEN6_BRSYNC},
1323*e3adcf8fSFrançois Tigeot };
1324*e3adcf8fSFrançois Tigeot 
1325*e3adcf8fSFrançois Tigeot /* ring buffer for bit-stream decoder */
1326*e3adcf8fSFrançois Tigeot 
1327*e3adcf8fSFrançois Tigeot static const struct intel_ring_buffer bsd_ring = {
1328*e3adcf8fSFrançois Tigeot 	.name                   = "bsd ring",
1329*e3adcf8fSFrançois Tigeot 	.id			= VCS,
1330*e3adcf8fSFrançois Tigeot 	.mmio_base		= BSD_RING_BASE,
1331*e3adcf8fSFrançois Tigeot 	.size			= 32 * PAGE_SIZE,
1332*e3adcf8fSFrançois Tigeot 	.init			= init_ring_common,
1333*e3adcf8fSFrançois Tigeot 	.write_tail		= ring_write_tail,
1334*e3adcf8fSFrançois Tigeot 	.flush			= bsd_ring_flush,
1335*e3adcf8fSFrançois Tigeot 	.add_request		= ring_add_request,
1336*e3adcf8fSFrançois Tigeot 	.get_seqno		= ring_get_seqno,
1337*e3adcf8fSFrançois Tigeot 	.irq_get		= bsd_ring_get_irq,
1338*e3adcf8fSFrançois Tigeot 	.irq_put		= bsd_ring_put_irq,
1339*e3adcf8fSFrançois Tigeot 	.dispatch_execbuffer	= ring_dispatch_execbuffer,
1340*e3adcf8fSFrançois Tigeot };
1341*e3adcf8fSFrançois Tigeot 
1342*e3adcf8fSFrançois Tigeot 
1343*e3adcf8fSFrançois Tigeot static void gen6_bsd_ring_write_tail(struct intel_ring_buffer *ring,
1344*e3adcf8fSFrançois Tigeot 				     uint32_t value)
1345*e3adcf8fSFrançois Tigeot {
1346*e3adcf8fSFrançois Tigeot 	drm_i915_private_t *dev_priv = ring->dev->dev_private;
1347*e3adcf8fSFrançois Tigeot 
1348*e3adcf8fSFrançois Tigeot 	/* Every tail move must follow the sequence below */
1349*e3adcf8fSFrançois Tigeot 	I915_WRITE(GEN6_BSD_SLEEP_PSMI_CONTROL,
1350*e3adcf8fSFrançois Tigeot 	    GEN6_BSD_SLEEP_PSMI_CONTROL_RC_ILDL_MESSAGE_MODIFY_MASK |
1351*e3adcf8fSFrançois Tigeot 	    GEN6_BSD_SLEEP_PSMI_CONTROL_RC_ILDL_MESSAGE_DISABLE);
1352*e3adcf8fSFrançois Tigeot 	I915_WRITE(GEN6_BSD_RNCID, 0x0);
1353*e3adcf8fSFrançois Tigeot 
1354*e3adcf8fSFrançois Tigeot 	if (_intel_wait_for(ring->dev,
1355*e3adcf8fSFrançois Tigeot 	    (I915_READ(GEN6_BSD_SLEEP_PSMI_CONTROL) &
1356*e3adcf8fSFrançois Tigeot 	     GEN6_BSD_SLEEP_PSMI_CONTROL_IDLE_INDICATOR) == 0, 50,
1357*e3adcf8fSFrançois Tigeot 	    true, "915g6i") != 0)
1358*e3adcf8fSFrançois Tigeot 		DRM_ERROR("timed out waiting for IDLE Indicator\n");
1359*e3adcf8fSFrançois Tigeot 
1360*e3adcf8fSFrançois Tigeot 	I915_WRITE_TAIL(ring, value);
1361*e3adcf8fSFrançois Tigeot 	I915_WRITE(GEN6_BSD_SLEEP_PSMI_CONTROL,
1362*e3adcf8fSFrançois Tigeot 	    GEN6_BSD_SLEEP_PSMI_CONTROL_RC_ILDL_MESSAGE_MODIFY_MASK |
1363*e3adcf8fSFrançois Tigeot 	    GEN6_BSD_SLEEP_PSMI_CONTROL_RC_ILDL_MESSAGE_ENABLE);
1364*e3adcf8fSFrançois Tigeot }
1365*e3adcf8fSFrançois Tigeot 
1366*e3adcf8fSFrançois Tigeot static int gen6_ring_flush(struct intel_ring_buffer *ring,
1367*e3adcf8fSFrançois Tigeot 			   uint32_t invalidate, uint32_t flush)
1368*e3adcf8fSFrançois Tigeot {
1369*e3adcf8fSFrançois Tigeot 	uint32_t cmd;
1370*e3adcf8fSFrançois Tigeot 	int ret;
1371*e3adcf8fSFrançois Tigeot 
1372*e3adcf8fSFrançois Tigeot 	ret = intel_ring_begin(ring, 4);
1373*e3adcf8fSFrançois Tigeot 	if (ret)
1374*e3adcf8fSFrançois Tigeot 		return ret;
1375*e3adcf8fSFrançois Tigeot 
1376*e3adcf8fSFrançois Tigeot 	cmd = MI_FLUSH_DW;
1377*e3adcf8fSFrançois Tigeot 	if (invalidate & I915_GEM_GPU_DOMAINS)
1378*e3adcf8fSFrançois Tigeot 		cmd |= MI_INVALIDATE_TLB | MI_INVALIDATE_BSD;
1379*e3adcf8fSFrançois Tigeot 	intel_ring_emit(ring, cmd);
1380*e3adcf8fSFrançois Tigeot 	intel_ring_emit(ring, 0);
1381*e3adcf8fSFrançois Tigeot 	intel_ring_emit(ring, 0);
1382*e3adcf8fSFrançois Tigeot 	intel_ring_emit(ring, MI_NOOP);
1383*e3adcf8fSFrançois Tigeot 	intel_ring_advance(ring);
1384*e3adcf8fSFrançois Tigeot 	return 0;
1385*e3adcf8fSFrançois Tigeot }
1386*e3adcf8fSFrançois Tigeot 
1387*e3adcf8fSFrançois Tigeot static int
1388*e3adcf8fSFrançois Tigeot gen6_ring_dispatch_execbuffer(struct intel_ring_buffer *ring,
1389*e3adcf8fSFrançois Tigeot 			      uint32_t offset, uint32_t len)
1390*e3adcf8fSFrançois Tigeot {
1391*e3adcf8fSFrançois Tigeot 	int ret;
1392*e3adcf8fSFrançois Tigeot 
1393*e3adcf8fSFrançois Tigeot 	ret = intel_ring_begin(ring, 2);
1394*e3adcf8fSFrançois Tigeot 	if (ret)
1395*e3adcf8fSFrançois Tigeot 		return ret;
1396*e3adcf8fSFrançois Tigeot 
1397*e3adcf8fSFrançois Tigeot 	intel_ring_emit(ring, MI_BATCH_BUFFER_START | MI_BATCH_NON_SECURE_I965);
1398*e3adcf8fSFrançois Tigeot 	/* bit0-7 is the length on GEN6+ */
1399*e3adcf8fSFrançois Tigeot 	intel_ring_emit(ring, offset);
1400*e3adcf8fSFrançois Tigeot 	intel_ring_advance(ring);
1401*e3adcf8fSFrançois Tigeot 
1402*e3adcf8fSFrançois Tigeot 	return 0;
1403*e3adcf8fSFrançois Tigeot }
1404*e3adcf8fSFrançois Tigeot 
1405*e3adcf8fSFrançois Tigeot static bool
1406*e3adcf8fSFrançois Tigeot gen6_render_ring_get_irq(struct intel_ring_buffer *ring)
1407*e3adcf8fSFrançois Tigeot {
1408*e3adcf8fSFrançois Tigeot 	return gen6_ring_get_irq(ring,
1409*e3adcf8fSFrançois Tigeot 				 GT_USER_INTERRUPT,
1410*e3adcf8fSFrançois Tigeot 				 GEN6_RENDER_USER_INTERRUPT);
1411*e3adcf8fSFrançois Tigeot }
1412*e3adcf8fSFrançois Tigeot 
1413*e3adcf8fSFrançois Tigeot static void
1414*e3adcf8fSFrançois Tigeot gen6_render_ring_put_irq(struct intel_ring_buffer *ring)
1415*e3adcf8fSFrançois Tigeot {
1416*e3adcf8fSFrançois Tigeot 	return gen6_ring_put_irq(ring,
1417*e3adcf8fSFrançois Tigeot 				 GT_USER_INTERRUPT,
1418*e3adcf8fSFrançois Tigeot 				 GEN6_RENDER_USER_INTERRUPT);
1419*e3adcf8fSFrançois Tigeot }
1420*e3adcf8fSFrançois Tigeot 
1421*e3adcf8fSFrançois Tigeot static bool
1422*e3adcf8fSFrançois Tigeot gen6_bsd_ring_get_irq(struct intel_ring_buffer *ring)
1423*e3adcf8fSFrançois Tigeot {
1424*e3adcf8fSFrançois Tigeot 	return gen6_ring_get_irq(ring,
1425*e3adcf8fSFrançois Tigeot 				 GT_GEN6_BSD_USER_INTERRUPT,
1426*e3adcf8fSFrançois Tigeot 				 GEN6_BSD_USER_INTERRUPT);
1427*e3adcf8fSFrançois Tigeot }
1428*e3adcf8fSFrançois Tigeot 
1429*e3adcf8fSFrançois Tigeot static void
1430*e3adcf8fSFrançois Tigeot gen6_bsd_ring_put_irq(struct intel_ring_buffer *ring)
1431*e3adcf8fSFrançois Tigeot {
1432*e3adcf8fSFrançois Tigeot 	return gen6_ring_put_irq(ring,
1433*e3adcf8fSFrançois Tigeot 				 GT_GEN6_BSD_USER_INTERRUPT,
1434*e3adcf8fSFrançois Tigeot 				 GEN6_BSD_USER_INTERRUPT);
1435*e3adcf8fSFrançois Tigeot }
1436*e3adcf8fSFrançois Tigeot 
1437*e3adcf8fSFrançois Tigeot /* ring buffer for Video Codec for Gen6+ */
1438*e3adcf8fSFrançois Tigeot static const struct intel_ring_buffer gen6_bsd_ring = {
1439*e3adcf8fSFrançois Tigeot 	.name			= "gen6 bsd ring",
1440*e3adcf8fSFrançois Tigeot 	.id			= VCS,
1441*e3adcf8fSFrançois Tigeot 	.mmio_base		= GEN6_BSD_RING_BASE,
1442*e3adcf8fSFrançois Tigeot 	.size			= 32 * PAGE_SIZE,
1443*e3adcf8fSFrançois Tigeot 	.init			= init_ring_common,
1444*e3adcf8fSFrançois Tigeot 	.write_tail		= gen6_bsd_ring_write_tail,
1445*e3adcf8fSFrançois Tigeot 	.flush			= gen6_ring_flush,
1446*e3adcf8fSFrançois Tigeot 	.add_request		= gen6_add_request,
1447*e3adcf8fSFrançois Tigeot 	.get_seqno		= gen6_ring_get_seqno,
1448*e3adcf8fSFrançois Tigeot 	.irq_get		= gen6_bsd_ring_get_irq,
1449*e3adcf8fSFrançois Tigeot 	.irq_put		= gen6_bsd_ring_put_irq,
1450*e3adcf8fSFrançois Tigeot 	.dispatch_execbuffer	= gen6_ring_dispatch_execbuffer,
1451*e3adcf8fSFrançois Tigeot 	.sync_to		= gen6_bsd_ring_sync_to,
1452*e3adcf8fSFrançois Tigeot 	.semaphore_register	= {MI_SEMAPHORE_SYNC_VR,
1453*e3adcf8fSFrançois Tigeot 				   MI_SEMAPHORE_SYNC_INVALID,
1454*e3adcf8fSFrançois Tigeot 				   MI_SEMAPHORE_SYNC_VB},
1455*e3adcf8fSFrançois Tigeot 	.signal_mbox		= {GEN6_RVSYNC, GEN6_BVSYNC},
1456*e3adcf8fSFrançois Tigeot };
1457*e3adcf8fSFrançois Tigeot 
1458*e3adcf8fSFrançois Tigeot /* Blitter support (SandyBridge+) */
1459*e3adcf8fSFrançois Tigeot 
1460*e3adcf8fSFrançois Tigeot static bool
1461*e3adcf8fSFrançois Tigeot blt_ring_get_irq(struct intel_ring_buffer *ring)
1462*e3adcf8fSFrançois Tigeot {
1463*e3adcf8fSFrançois Tigeot 	return gen6_ring_get_irq(ring,
1464*e3adcf8fSFrançois Tigeot 				 GT_BLT_USER_INTERRUPT,
1465*e3adcf8fSFrançois Tigeot 				 GEN6_BLITTER_USER_INTERRUPT);
1466*e3adcf8fSFrançois Tigeot }
1467*e3adcf8fSFrançois Tigeot 
1468*e3adcf8fSFrançois Tigeot static void
1469*e3adcf8fSFrançois Tigeot blt_ring_put_irq(struct intel_ring_buffer *ring)
1470*e3adcf8fSFrançois Tigeot {
1471*e3adcf8fSFrançois Tigeot 	gen6_ring_put_irq(ring,
1472*e3adcf8fSFrançois Tigeot 			  GT_BLT_USER_INTERRUPT,
1473*e3adcf8fSFrançois Tigeot 			  GEN6_BLITTER_USER_INTERRUPT);
1474*e3adcf8fSFrançois Tigeot }
1475*e3adcf8fSFrançois Tigeot 
1476*e3adcf8fSFrançois Tigeot static int blt_ring_flush(struct intel_ring_buffer *ring,
1477*e3adcf8fSFrançois Tigeot 			  uint32_t invalidate, uint32_t flush)
1478*e3adcf8fSFrançois Tigeot {
1479*e3adcf8fSFrançois Tigeot 	uint32_t cmd;
1480*e3adcf8fSFrançois Tigeot 	int ret;
1481*e3adcf8fSFrançois Tigeot 
1482*e3adcf8fSFrançois Tigeot 	ret = intel_ring_begin(ring, 4);
1483*e3adcf8fSFrançois Tigeot 	if (ret)
1484*e3adcf8fSFrançois Tigeot 		return ret;
1485*e3adcf8fSFrançois Tigeot 
1486*e3adcf8fSFrançois Tigeot 	cmd = MI_FLUSH_DW;
1487*e3adcf8fSFrançois Tigeot 	if (invalidate & I915_GEM_DOMAIN_RENDER)
1488*e3adcf8fSFrançois Tigeot 		cmd |= MI_INVALIDATE_TLB;
1489*e3adcf8fSFrançois Tigeot 	intel_ring_emit(ring, cmd);
1490*e3adcf8fSFrançois Tigeot 	intel_ring_emit(ring, 0);
1491*e3adcf8fSFrançois Tigeot 	intel_ring_emit(ring, 0);
1492*e3adcf8fSFrançois Tigeot 	intel_ring_emit(ring, MI_NOOP);
1493*e3adcf8fSFrançois Tigeot 	intel_ring_advance(ring);
1494*e3adcf8fSFrançois Tigeot 	return 0;
1495*e3adcf8fSFrançois Tigeot }
1496*e3adcf8fSFrançois Tigeot 
1497*e3adcf8fSFrançois Tigeot static const struct intel_ring_buffer gen6_blt_ring = {
1498*e3adcf8fSFrançois Tigeot 	.name			= "blt ring",
1499*e3adcf8fSFrançois Tigeot 	.id			= BCS,
1500*e3adcf8fSFrançois Tigeot 	.mmio_base		= BLT_RING_BASE,
1501*e3adcf8fSFrançois Tigeot 	.size			= 32 * PAGE_SIZE,
1502*e3adcf8fSFrançois Tigeot 	.init			= init_ring_common,
1503*e3adcf8fSFrançois Tigeot 	.write_tail		= ring_write_tail,
1504*e3adcf8fSFrançois Tigeot 	.flush			= blt_ring_flush,
1505*e3adcf8fSFrançois Tigeot 	.add_request		= gen6_add_request,
1506*e3adcf8fSFrançois Tigeot 	.get_seqno		= gen6_ring_get_seqno,
1507*e3adcf8fSFrançois Tigeot 	.irq_get		= blt_ring_get_irq,
1508*e3adcf8fSFrançois Tigeot 	.irq_put		= blt_ring_put_irq,
1509*e3adcf8fSFrançois Tigeot 	.dispatch_execbuffer	= gen6_ring_dispatch_execbuffer,
1510*e3adcf8fSFrançois Tigeot 	.sync_to		= gen6_blt_ring_sync_to,
1511*e3adcf8fSFrançois Tigeot 	.semaphore_register	= {MI_SEMAPHORE_SYNC_BR,
1512*e3adcf8fSFrançois Tigeot 				   MI_SEMAPHORE_SYNC_BV,
1513*e3adcf8fSFrançois Tigeot 				   MI_SEMAPHORE_SYNC_INVALID},
1514*e3adcf8fSFrançois Tigeot 	.signal_mbox		= {GEN6_RBSYNC, GEN6_VBSYNC},
1515*e3adcf8fSFrançois Tigeot };
1516*e3adcf8fSFrançois Tigeot 
1517*e3adcf8fSFrançois Tigeot int intel_init_render_ring_buffer(struct drm_device *dev)
1518*e3adcf8fSFrançois Tigeot {
1519*e3adcf8fSFrançois Tigeot 	drm_i915_private_t *dev_priv = dev->dev_private;
1520*e3adcf8fSFrançois Tigeot 	struct intel_ring_buffer *ring = &dev_priv->rings[RCS];
1521*e3adcf8fSFrançois Tigeot 
1522*e3adcf8fSFrançois Tigeot 	*ring = render_ring;
1523*e3adcf8fSFrançois Tigeot 	if (INTEL_INFO(dev)->gen >= 6) {
1524*e3adcf8fSFrançois Tigeot 		ring->add_request = gen6_add_request;
1525*e3adcf8fSFrançois Tigeot 		ring->flush = gen6_render_ring_flush;
1526*e3adcf8fSFrançois Tigeot 		ring->irq_get = gen6_render_ring_get_irq;
1527*e3adcf8fSFrançois Tigeot 		ring->irq_put = gen6_render_ring_put_irq;
1528*e3adcf8fSFrançois Tigeot 		ring->get_seqno = gen6_ring_get_seqno;
1529*e3adcf8fSFrançois Tigeot 	} else if (IS_GEN5(dev)) {
1530*e3adcf8fSFrançois Tigeot 		ring->add_request = pc_render_add_request;
1531*e3adcf8fSFrançois Tigeot 		ring->get_seqno = pc_render_get_seqno;
1532*e3adcf8fSFrançois Tigeot 	}
1533*e3adcf8fSFrançois Tigeot 
1534*e3adcf8fSFrançois Tigeot 	if (!I915_NEED_GFX_HWS(dev)) {
1535*e3adcf8fSFrançois Tigeot 		ring->status_page.page_addr = dev_priv->status_page_dmah->vaddr;
1536*e3adcf8fSFrançois Tigeot 		memset(ring->status_page.page_addr, 0, PAGE_SIZE);
1537*e3adcf8fSFrançois Tigeot 	}
1538*e3adcf8fSFrançois Tigeot 
1539*e3adcf8fSFrançois Tigeot 	return intel_init_ring_buffer(dev, ring);
1540*e3adcf8fSFrançois Tigeot }
1541*e3adcf8fSFrançois Tigeot 
1542*e3adcf8fSFrançois Tigeot int intel_render_ring_init_dri(struct drm_device *dev, uint64_t start,
1543*e3adcf8fSFrançois Tigeot     uint32_t size)
1544*e3adcf8fSFrançois Tigeot {
1545*e3adcf8fSFrançois Tigeot 	drm_i915_private_t *dev_priv = dev->dev_private;
1546*e3adcf8fSFrançois Tigeot 	struct intel_ring_buffer *ring = &dev_priv->rings[RCS];
1547*e3adcf8fSFrançois Tigeot 
1548*e3adcf8fSFrançois Tigeot 	*ring = render_ring;
1549*e3adcf8fSFrançois Tigeot 	if (INTEL_INFO(dev)->gen >= 6) {
1550*e3adcf8fSFrançois Tigeot 		ring->add_request = gen6_add_request;
1551*e3adcf8fSFrançois Tigeot 		ring->irq_get = gen6_render_ring_get_irq;
1552*e3adcf8fSFrançois Tigeot 		ring->irq_put = gen6_render_ring_put_irq;
1553*e3adcf8fSFrançois Tigeot 	} else if (IS_GEN5(dev)) {
1554*e3adcf8fSFrançois Tigeot 		ring->add_request = pc_render_add_request;
1555*e3adcf8fSFrançois Tigeot 		ring->get_seqno = pc_render_get_seqno;
1556*e3adcf8fSFrançois Tigeot 	}
1557*e3adcf8fSFrançois Tigeot 
1558*e3adcf8fSFrançois Tigeot 	ring->dev = dev;
1559*e3adcf8fSFrançois Tigeot 	INIT_LIST_HEAD(&ring->active_list);
1560*e3adcf8fSFrançois Tigeot 	INIT_LIST_HEAD(&ring->request_list);
1561*e3adcf8fSFrançois Tigeot 	INIT_LIST_HEAD(&ring->gpu_write_list);
1562*e3adcf8fSFrançois Tigeot 
1563*e3adcf8fSFrançois Tigeot 	ring->size = size;
1564*e3adcf8fSFrançois Tigeot 	ring->effective_size = ring->size;
1565*e3adcf8fSFrançois Tigeot 	if (IS_I830(ring->dev))
1566*e3adcf8fSFrançois Tigeot 		ring->effective_size -= 128;
1567*e3adcf8fSFrançois Tigeot 
1568*e3adcf8fSFrançois Tigeot 	ring->map.offset = start;
1569*e3adcf8fSFrançois Tigeot 	ring->map.size = size;
1570*e3adcf8fSFrançois Tigeot 	ring->map.type = 0;
1571*e3adcf8fSFrançois Tigeot 	ring->map.flags = 0;
1572*e3adcf8fSFrançois Tigeot 	ring->map.mtrr = 0;
1573*e3adcf8fSFrançois Tigeot 
1574*e3adcf8fSFrançois Tigeot 	drm_core_ioremap_wc(&ring->map, dev);
1575*e3adcf8fSFrançois Tigeot 	if (ring->map.virtual == NULL) {
1576*e3adcf8fSFrançois Tigeot 		DRM_ERROR("can not ioremap virtual address for"
1577*e3adcf8fSFrançois Tigeot 			  " ring buffer\n");
1578*e3adcf8fSFrançois Tigeot 		return -ENOMEM;
1579*e3adcf8fSFrançois Tigeot 	}
1580*e3adcf8fSFrançois Tigeot 
1581*e3adcf8fSFrançois Tigeot 	ring->virtual_start = (void *)ring->map.virtual;
1582*e3adcf8fSFrançois Tigeot 	return 0;
1583*e3adcf8fSFrançois Tigeot }
1584*e3adcf8fSFrançois Tigeot 
1585*e3adcf8fSFrançois Tigeot int intel_init_bsd_ring_buffer(struct drm_device *dev)
1586*e3adcf8fSFrançois Tigeot {
1587*e3adcf8fSFrançois Tigeot 	drm_i915_private_t *dev_priv = dev->dev_private;
1588*e3adcf8fSFrançois Tigeot 	struct intel_ring_buffer *ring = &dev_priv->rings[VCS];
1589*e3adcf8fSFrançois Tigeot 
1590*e3adcf8fSFrançois Tigeot 	if (IS_GEN6(dev) || IS_GEN7(dev))
1591*e3adcf8fSFrançois Tigeot 		*ring = gen6_bsd_ring;
1592*e3adcf8fSFrançois Tigeot 	else
1593*e3adcf8fSFrançois Tigeot 		*ring = bsd_ring;
1594*e3adcf8fSFrançois Tigeot 
1595*e3adcf8fSFrançois Tigeot 	return intel_init_ring_buffer(dev, ring);
1596*e3adcf8fSFrançois Tigeot }
1597*e3adcf8fSFrançois Tigeot 
1598*e3adcf8fSFrançois Tigeot int intel_init_blt_ring_buffer(struct drm_device *dev)
1599*e3adcf8fSFrançois Tigeot {
1600*e3adcf8fSFrançois Tigeot 	drm_i915_private_t *dev_priv = dev->dev_private;
1601*e3adcf8fSFrançois Tigeot 	struct intel_ring_buffer *ring = &dev_priv->rings[BCS];
1602*e3adcf8fSFrançois Tigeot 
1603*e3adcf8fSFrançois Tigeot 	*ring = gen6_blt_ring;
1604*e3adcf8fSFrançois Tigeot 
1605*e3adcf8fSFrançois Tigeot 	return intel_init_ring_buffer(dev, ring);
1606*e3adcf8fSFrançois Tigeot }
1607