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