1e3adcf8fSFrançois Tigeot /* 2e3adcf8fSFrançois Tigeot * Copyright © 2008-2010 Intel Corporation 3e3adcf8fSFrançois Tigeot * 4e3adcf8fSFrançois Tigeot * Permission is hereby granted, free of charge, to any person obtaining a 5e3adcf8fSFrançois Tigeot * copy of this software and associated documentation files (the "Software"), 6e3adcf8fSFrançois Tigeot * to deal in the Software without restriction, including without limitation 7e3adcf8fSFrançois Tigeot * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8e3adcf8fSFrançois Tigeot * and/or sell copies of the Software, and to permit persons to whom the 9e3adcf8fSFrançois Tigeot * Software is furnished to do so, subject to the following conditions: 10e3adcf8fSFrançois Tigeot * 11e3adcf8fSFrançois Tigeot * The above copyright notice and this permission notice (including the next 12e3adcf8fSFrançois Tigeot * paragraph) shall be included in all copies or substantial portions of the 13e3adcf8fSFrançois Tigeot * Software. 14e3adcf8fSFrançois Tigeot * 15e3adcf8fSFrançois Tigeot * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16e3adcf8fSFrançois Tigeot * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17e3adcf8fSFrançois Tigeot * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18e3adcf8fSFrançois Tigeot * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19e3adcf8fSFrançois Tigeot * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20e3adcf8fSFrançois Tigeot * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21e3adcf8fSFrançois Tigeot * IN THE SOFTWARE. 22e3adcf8fSFrançois Tigeot * 23e3adcf8fSFrançois Tigeot * Authors: 24e3adcf8fSFrançois Tigeot * Eric Anholt <eric@anholt.net> 25e3adcf8fSFrançois Tigeot * Zou Nan hai <nanhai.zou@intel.com> 26e3adcf8fSFrançois Tigeot * Xiang Hai hao<haihao.xiang@intel.com> 27e3adcf8fSFrançois Tigeot * 28e3adcf8fSFrançois Tigeot */ 29e3adcf8fSFrançois Tigeot 3018e26a6dSFrançois Tigeot #include <drm/drmP.h> 31e3adcf8fSFrançois Tigeot #include "i915_drv.h" 32a2fdbec6SFrançois Tigeot #include <drm/i915_drm.h> 33a2fdbec6SFrançois Tigeot #include "i915_trace.h" 34e3adcf8fSFrançois Tigeot #include "intel_drv.h" 35e3adcf8fSFrançois Tigeot 36*ba55f2f5SFrançois Tigeot /* Early gen2 devices have a cacheline of just 32 bytes, using 64 is overkill, 37*ba55f2f5SFrançois Tigeot * but keeps the logic simple. Indeed, the whole purpose of this macro is just 38*ba55f2f5SFrançois Tigeot * to give some inclination as to some of the magic values used in the various 39*ba55f2f5SFrançois Tigeot * workarounds! 40*ba55f2f5SFrançois Tigeot */ 41*ba55f2f5SFrançois Tigeot #define CACHELINE_BYTES 64 42*ba55f2f5SFrançois Tigeot 43*ba55f2f5SFrançois Tigeot static inline int __ring_space(int head, int tail, int size) 44e3adcf8fSFrançois Tigeot { 45*ba55f2f5SFrançois Tigeot int space = head - (tail + I915_RING_FREE_SPACE); 46e3adcf8fSFrançois Tigeot if (space < 0) 47*ba55f2f5SFrançois Tigeot space += size; 48e3adcf8fSFrançois Tigeot return space; 49e3adcf8fSFrançois Tigeot } 50e3adcf8fSFrançois Tigeot 51*ba55f2f5SFrançois Tigeot static inline int ring_space(struct intel_engine_cs *ring) 52*ba55f2f5SFrançois Tigeot { 53*ba55f2f5SFrançois Tigeot struct intel_ringbuffer *ringbuf = ring->buffer; 54*ba55f2f5SFrançois Tigeot return __ring_space(ringbuf->head & HEAD_ADDR, ringbuf->tail, ringbuf->size); 55*ba55f2f5SFrançois Tigeot } 56*ba55f2f5SFrançois Tigeot 57*ba55f2f5SFrançois Tigeot static bool intel_ring_stopped(struct intel_engine_cs *ring) 589edbd4a0SFrançois Tigeot { 599edbd4a0SFrançois Tigeot struct drm_i915_private *dev_priv = ring->dev->dev_private; 60*ba55f2f5SFrançois Tigeot return dev_priv->gpu_error.stop_rings & intel_ring_flag(ring); 61*ba55f2f5SFrançois Tigeot } 629edbd4a0SFrançois Tigeot 63*ba55f2f5SFrançois Tigeot void __intel_ring_advance(struct intel_engine_cs *ring) 64*ba55f2f5SFrançois Tigeot { 65*ba55f2f5SFrançois Tigeot struct intel_ringbuffer *ringbuf = ring->buffer; 66*ba55f2f5SFrançois Tigeot ringbuf->tail &= ringbuf->size - 1; 67*ba55f2f5SFrançois Tigeot if (intel_ring_stopped(ring)) 689edbd4a0SFrançois Tigeot return; 69*ba55f2f5SFrançois Tigeot ring->write_tail(ring, ringbuf->tail); 709edbd4a0SFrançois Tigeot } 719edbd4a0SFrançois Tigeot 72e3adcf8fSFrançois Tigeot static int 73*ba55f2f5SFrançois Tigeot gen2_render_ring_flush(struct intel_engine_cs *ring, 74686a02f1SFrançois Tigeot u32 invalidate_domains, 75686a02f1SFrançois Tigeot u32 flush_domains) 76686a02f1SFrançois Tigeot { 77686a02f1SFrançois Tigeot u32 cmd; 78686a02f1SFrançois Tigeot int ret; 79686a02f1SFrançois Tigeot 80686a02f1SFrançois Tigeot cmd = MI_FLUSH; 81686a02f1SFrançois Tigeot if (((invalidate_domains|flush_domains) & I915_GEM_DOMAIN_RENDER) == 0) 82686a02f1SFrançois Tigeot cmd |= MI_NO_WRITE_FLUSH; 83686a02f1SFrançois Tigeot 84686a02f1SFrançois Tigeot if (invalidate_domains & I915_GEM_DOMAIN_SAMPLER) 85686a02f1SFrançois Tigeot cmd |= MI_READ_FLUSH; 86686a02f1SFrançois Tigeot 87686a02f1SFrançois Tigeot ret = intel_ring_begin(ring, 2); 88686a02f1SFrançois Tigeot if (ret) 89686a02f1SFrançois Tigeot return ret; 90686a02f1SFrançois Tigeot 91686a02f1SFrançois Tigeot intel_ring_emit(ring, cmd); 92686a02f1SFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 93686a02f1SFrançois Tigeot intel_ring_advance(ring); 94686a02f1SFrançois Tigeot 95686a02f1SFrançois Tigeot return 0; 96686a02f1SFrançois Tigeot } 97686a02f1SFrançois Tigeot 98686a02f1SFrançois Tigeot static int 99*ba55f2f5SFrançois Tigeot gen4_render_ring_flush(struct intel_engine_cs *ring, 100686a02f1SFrançois Tigeot u32 invalidate_domains, 101686a02f1SFrançois Tigeot u32 flush_domains) 102e3adcf8fSFrançois Tigeot { 103e3adcf8fSFrançois Tigeot struct drm_device *dev = ring->dev; 104686a02f1SFrançois Tigeot u32 cmd; 105e3adcf8fSFrançois Tigeot int ret; 106e3adcf8fSFrançois Tigeot 107e3adcf8fSFrançois Tigeot /* 108e3adcf8fSFrançois Tigeot * read/write caches: 109e3adcf8fSFrançois Tigeot * 110e3adcf8fSFrançois Tigeot * I915_GEM_DOMAIN_RENDER is always invalidated, but is 111e3adcf8fSFrançois Tigeot * only flushed if MI_NO_WRITE_FLUSH is unset. On 965, it is 112e3adcf8fSFrançois Tigeot * also flushed at 2d versus 3d pipeline switches. 113e3adcf8fSFrançois Tigeot * 114e3adcf8fSFrançois Tigeot * read-only caches: 115e3adcf8fSFrançois Tigeot * 116e3adcf8fSFrançois Tigeot * I915_GEM_DOMAIN_SAMPLER is flushed on pre-965 if 117e3adcf8fSFrançois Tigeot * MI_READ_FLUSH is set, and is always flushed on 965. 118e3adcf8fSFrançois Tigeot * 119e3adcf8fSFrançois Tigeot * I915_GEM_DOMAIN_COMMAND may not exist? 120e3adcf8fSFrançois Tigeot * 121e3adcf8fSFrançois Tigeot * I915_GEM_DOMAIN_INSTRUCTION, which exists on 965, is 122e3adcf8fSFrançois Tigeot * invalidated when MI_EXE_FLUSH is set. 123e3adcf8fSFrançois Tigeot * 124e3adcf8fSFrançois Tigeot * I915_GEM_DOMAIN_VERTEX, which exists on 965, is 125e3adcf8fSFrançois Tigeot * invalidated with every MI_FLUSH. 126e3adcf8fSFrançois Tigeot * 127e3adcf8fSFrançois Tigeot * TLBs: 128e3adcf8fSFrançois Tigeot * 129e3adcf8fSFrançois Tigeot * On 965, TLBs associated with I915_GEM_DOMAIN_COMMAND 130e3adcf8fSFrançois Tigeot * and I915_GEM_DOMAIN_CPU in are invalidated at PTE write and 131e3adcf8fSFrançois Tigeot * I915_GEM_DOMAIN_RENDER and I915_GEM_DOMAIN_SAMPLER 132e3adcf8fSFrançois Tigeot * are flushed at any MI_FLUSH. 133e3adcf8fSFrançois Tigeot */ 134e3adcf8fSFrançois Tigeot 135e3adcf8fSFrançois Tigeot cmd = MI_FLUSH | MI_NO_WRITE_FLUSH; 136686a02f1SFrançois Tigeot if ((invalidate_domains|flush_domains) & I915_GEM_DOMAIN_RENDER) 137e3adcf8fSFrançois Tigeot cmd &= ~MI_NO_WRITE_FLUSH; 138e3adcf8fSFrançois Tigeot if (invalidate_domains & I915_GEM_DOMAIN_INSTRUCTION) 139e3adcf8fSFrançois Tigeot cmd |= MI_EXE_FLUSH; 140e3adcf8fSFrançois Tigeot 141e3adcf8fSFrançois Tigeot if (invalidate_domains & I915_GEM_DOMAIN_COMMAND && 142e3adcf8fSFrançois Tigeot (IS_G4X(dev) || IS_GEN5(dev))) 143e3adcf8fSFrançois Tigeot cmd |= MI_INVALIDATE_ISP; 144e3adcf8fSFrançois Tigeot 145e3adcf8fSFrançois Tigeot ret = intel_ring_begin(ring, 2); 146e3adcf8fSFrançois Tigeot if (ret) 147e3adcf8fSFrançois Tigeot return ret; 148e3adcf8fSFrançois Tigeot 149e3adcf8fSFrançois Tigeot intel_ring_emit(ring, cmd); 150e3adcf8fSFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 151e3adcf8fSFrançois Tigeot intel_ring_advance(ring); 152e3adcf8fSFrançois Tigeot 153e3adcf8fSFrançois Tigeot return 0; 154e3adcf8fSFrançois Tigeot } 155e3adcf8fSFrançois Tigeot 156e3adcf8fSFrançois Tigeot /** 157e3adcf8fSFrançois Tigeot * Emits a PIPE_CONTROL with a non-zero post-sync operation, for 158e3adcf8fSFrançois Tigeot * implementing two workarounds on gen6. From section 1.4.7.1 159e3adcf8fSFrançois Tigeot * "PIPE_CONTROL" of the Sandy Bridge PRM volume 2 part 1: 160e3adcf8fSFrançois Tigeot * 161e3adcf8fSFrançois Tigeot * [DevSNB-C+{W/A}] Before any depth stall flush (including those 162e3adcf8fSFrançois Tigeot * produced by non-pipelined state commands), software needs to first 163e3adcf8fSFrançois Tigeot * send a PIPE_CONTROL with no bits set except Post-Sync Operation != 164e3adcf8fSFrançois Tigeot * 0. 165e3adcf8fSFrançois Tigeot * 166e3adcf8fSFrançois Tigeot * [Dev-SNB{W/A}]: Before a PIPE_CONTROL with Write Cache Flush Enable 167e3adcf8fSFrançois Tigeot * =1, a PIPE_CONTROL with any non-zero post-sync-op is required. 168e3adcf8fSFrançois Tigeot * 169e3adcf8fSFrançois Tigeot * And the workaround for these two requires this workaround first: 170e3adcf8fSFrançois Tigeot * 171e3adcf8fSFrançois Tigeot * [Dev-SNB{W/A}]: Pipe-control with CS-stall bit set must be sent 172e3adcf8fSFrançois Tigeot * BEFORE the pipe-control with a post-sync op and no write-cache 173e3adcf8fSFrançois Tigeot * flushes. 174e3adcf8fSFrançois Tigeot * 175e3adcf8fSFrançois Tigeot * And this last workaround is tricky because of the requirements on 176e3adcf8fSFrançois Tigeot * that bit. From section 1.4.7.2.3 "Stall" of the Sandy Bridge PRM 177e3adcf8fSFrançois Tigeot * volume 2 part 1: 178e3adcf8fSFrançois Tigeot * 179e3adcf8fSFrançois Tigeot * "1 of the following must also be set: 180e3adcf8fSFrançois Tigeot * - Render Target Cache Flush Enable ([12] of DW1) 181e3adcf8fSFrançois Tigeot * - Depth Cache Flush Enable ([0] of DW1) 182e3adcf8fSFrançois Tigeot * - Stall at Pixel Scoreboard ([1] of DW1) 183e3adcf8fSFrançois Tigeot * - Depth Stall ([13] of DW1) 184e3adcf8fSFrançois Tigeot * - Post-Sync Operation ([13] of DW1) 185e3adcf8fSFrançois Tigeot * - Notify Enable ([8] of DW1)" 186e3adcf8fSFrançois Tigeot * 187e3adcf8fSFrançois Tigeot * The cache flushes require the workaround flush that triggered this 188e3adcf8fSFrançois Tigeot * one, so we can't use it. Depth stall would trigger the same. 189e3adcf8fSFrançois Tigeot * Post-sync nonzero is what triggered this second workaround, so we 190e3adcf8fSFrançois Tigeot * can't use that one either. Notify enable is IRQs, which aren't 191e3adcf8fSFrançois Tigeot * really our business. That leaves only stall at scoreboard. 192e3adcf8fSFrançois Tigeot */ 193e3adcf8fSFrançois Tigeot static int 194*ba55f2f5SFrançois Tigeot intel_emit_post_sync_nonzero_flush(struct intel_engine_cs *ring) 195e3adcf8fSFrançois Tigeot { 196*ba55f2f5SFrançois Tigeot u32 scratch_addr = ring->scratch.gtt_offset + 2 * CACHELINE_BYTES; 197e3adcf8fSFrançois Tigeot int ret; 198e3adcf8fSFrançois Tigeot 199e3adcf8fSFrançois Tigeot 200e3adcf8fSFrançois Tigeot ret = intel_ring_begin(ring, 6); 201e3adcf8fSFrançois Tigeot if (ret) 202e3adcf8fSFrançois Tigeot return ret; 203e3adcf8fSFrançois Tigeot 204e3adcf8fSFrançois Tigeot intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(5)); 205e3adcf8fSFrançois Tigeot intel_ring_emit(ring, PIPE_CONTROL_CS_STALL | 206e3adcf8fSFrançois Tigeot PIPE_CONTROL_STALL_AT_SCOREBOARD); 207e3adcf8fSFrançois Tigeot intel_ring_emit(ring, scratch_addr | PIPE_CONTROL_GLOBAL_GTT); /* address */ 208e3adcf8fSFrançois Tigeot intel_ring_emit(ring, 0); /* low dword */ 209e3adcf8fSFrançois Tigeot intel_ring_emit(ring, 0); /* high dword */ 210e3adcf8fSFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 211e3adcf8fSFrançois Tigeot intel_ring_advance(ring); 212e3adcf8fSFrançois Tigeot 213e3adcf8fSFrançois Tigeot ret = intel_ring_begin(ring, 6); 214e3adcf8fSFrançois Tigeot if (ret) 215e3adcf8fSFrançois Tigeot return ret; 216e3adcf8fSFrançois Tigeot 217e3adcf8fSFrançois Tigeot intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(5)); 218e3adcf8fSFrançois Tigeot intel_ring_emit(ring, PIPE_CONTROL_QW_WRITE); 219e3adcf8fSFrançois Tigeot intel_ring_emit(ring, scratch_addr | PIPE_CONTROL_GLOBAL_GTT); /* address */ 220e3adcf8fSFrançois Tigeot intel_ring_emit(ring, 0); 221e3adcf8fSFrançois Tigeot intel_ring_emit(ring, 0); 222e3adcf8fSFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 223e3adcf8fSFrançois Tigeot intel_ring_advance(ring); 224e3adcf8fSFrançois Tigeot 225e3adcf8fSFrançois Tigeot return 0; 226e3adcf8fSFrançois Tigeot } 227e3adcf8fSFrançois Tigeot 228e3adcf8fSFrançois Tigeot static int 229*ba55f2f5SFrançois Tigeot gen6_render_ring_flush(struct intel_engine_cs *ring, 230e3adcf8fSFrançois Tigeot u32 invalidate_domains, u32 flush_domains) 231e3adcf8fSFrançois Tigeot { 232e3adcf8fSFrançois Tigeot u32 flags = 0; 233*ba55f2f5SFrançois Tigeot u32 scratch_addr = ring->scratch.gtt_offset + 2 * CACHELINE_BYTES; 234e3adcf8fSFrançois Tigeot int ret; 235e3adcf8fSFrançois Tigeot 236e3adcf8fSFrançois Tigeot /* Force SNB workarounds for PIPE_CONTROL flushes */ 237686a02f1SFrançois Tigeot ret = intel_emit_post_sync_nonzero_flush(ring); 238686a02f1SFrançois Tigeot if (ret) 239686a02f1SFrançois Tigeot return ret; 240e3adcf8fSFrançois Tigeot 241e3adcf8fSFrançois Tigeot /* Just flush everything. Experiments have shown that reducing the 242e3adcf8fSFrançois Tigeot * number of bits based on the write domains has little performance 243e3adcf8fSFrançois Tigeot * impact. 244e3adcf8fSFrançois Tigeot */ 245b5c29a34SFrançois Tigeot if (flush_domains) { 246e3adcf8fSFrançois Tigeot flags |= PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH; 247b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_DEPTH_CACHE_FLUSH; 248b5c29a34SFrançois Tigeot /* 249b5c29a34SFrançois Tigeot * Ensure that any following seqno writes only happen 250b5c29a34SFrançois Tigeot * when the render cache is indeed flushed. 251b5c29a34SFrançois Tigeot */ 252b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_CS_STALL; 253b5c29a34SFrançois Tigeot } 254b5c29a34SFrançois Tigeot if (invalidate_domains) { 255686a02f1SFrançois Tigeot flags |= PIPE_CONTROL_TLB_INVALIDATE; 256e3adcf8fSFrançois Tigeot flags |= PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE; 257e3adcf8fSFrançois Tigeot flags |= PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE; 258e3adcf8fSFrançois Tigeot flags |= PIPE_CONTROL_VF_CACHE_INVALIDATE; 259e3adcf8fSFrançois Tigeot flags |= PIPE_CONTROL_CONST_CACHE_INVALIDATE; 260e3adcf8fSFrançois Tigeot flags |= PIPE_CONTROL_STATE_CACHE_INVALIDATE; 261686a02f1SFrançois Tigeot /* 262b5c29a34SFrançois Tigeot * TLB invalidate requires a post-sync write. 263686a02f1SFrançois Tigeot */ 264b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_QW_WRITE | PIPE_CONTROL_CS_STALL; 265b5c29a34SFrançois Tigeot } 266e3adcf8fSFrançois Tigeot 267b5c29a34SFrançois Tigeot ret = intel_ring_begin(ring, 4); 268e3adcf8fSFrançois Tigeot if (ret) 269e3adcf8fSFrançois Tigeot return ret; 270e3adcf8fSFrançois Tigeot 271b5c29a34SFrançois Tigeot intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(4)); 272e3adcf8fSFrançois Tigeot intel_ring_emit(ring, flags); 273e3adcf8fSFrançois Tigeot intel_ring_emit(ring, scratch_addr | PIPE_CONTROL_GLOBAL_GTT); 274b5c29a34SFrançois Tigeot intel_ring_emit(ring, 0); 275b5c29a34SFrançois Tigeot intel_ring_advance(ring); 276b5c29a34SFrançois Tigeot 277b5c29a34SFrançois Tigeot return 0; 278b5c29a34SFrançois Tigeot } 279b5c29a34SFrançois Tigeot 280b5c29a34SFrançois Tigeot static int 281*ba55f2f5SFrançois Tigeot gen7_render_ring_cs_stall_wa(struct intel_engine_cs *ring) 282b5c29a34SFrançois Tigeot { 283b5c29a34SFrançois Tigeot int ret; 284b5c29a34SFrançois Tigeot 285b5c29a34SFrançois Tigeot ret = intel_ring_begin(ring, 4); 286b5c29a34SFrançois Tigeot if (ret) 287b5c29a34SFrançois Tigeot return ret; 288b5c29a34SFrançois Tigeot 289b5c29a34SFrançois Tigeot intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(4)); 290b5c29a34SFrançois Tigeot intel_ring_emit(ring, PIPE_CONTROL_CS_STALL | 291b5c29a34SFrançois Tigeot PIPE_CONTROL_STALL_AT_SCOREBOARD); 292b5c29a34SFrançois Tigeot intel_ring_emit(ring, 0); 293b5c29a34SFrançois Tigeot intel_ring_emit(ring, 0); 294b5c29a34SFrançois Tigeot intel_ring_advance(ring); 295b5c29a34SFrançois Tigeot 296b5c29a34SFrançois Tigeot return 0; 297b5c29a34SFrançois Tigeot } 298b5c29a34SFrançois Tigeot 299*ba55f2f5SFrançois Tigeot static int gen7_ring_fbc_flush(struct intel_engine_cs *ring, u32 value) 3005d0b1887SFrançois Tigeot { 3015d0b1887SFrançois Tigeot int ret; 3025d0b1887SFrançois Tigeot 3035d0b1887SFrançois Tigeot if (!ring->fbc_dirty) 3045d0b1887SFrançois Tigeot return 0; 3055d0b1887SFrançois Tigeot 3069edbd4a0SFrançois Tigeot ret = intel_ring_begin(ring, 6); 3075d0b1887SFrançois Tigeot if (ret) 3085d0b1887SFrançois Tigeot return ret; 3095d0b1887SFrançois Tigeot /* WaFbcNukeOn3DBlt:ivb/hsw */ 3105d0b1887SFrançois Tigeot intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1)); 3115d0b1887SFrançois Tigeot intel_ring_emit(ring, MSG_FBC_REND_STATE); 3125d0b1887SFrançois Tigeot intel_ring_emit(ring, value); 3139edbd4a0SFrançois Tigeot intel_ring_emit(ring, MI_STORE_REGISTER_MEM(1) | MI_SRM_LRM_GLOBAL_GTT); 3149edbd4a0SFrançois Tigeot intel_ring_emit(ring, MSG_FBC_REND_STATE); 3159edbd4a0SFrançois Tigeot intel_ring_emit(ring, ring->scratch.gtt_offset + 256); 3165d0b1887SFrançois Tigeot intel_ring_advance(ring); 3175d0b1887SFrançois Tigeot 3185d0b1887SFrançois Tigeot ring->fbc_dirty = false; 3195d0b1887SFrançois Tigeot return 0; 3205d0b1887SFrançois Tigeot } 3215d0b1887SFrançois Tigeot 322b5c29a34SFrançois Tigeot static int 323*ba55f2f5SFrançois Tigeot gen7_render_ring_flush(struct intel_engine_cs *ring, 324b5c29a34SFrançois Tigeot u32 invalidate_domains, u32 flush_domains) 325b5c29a34SFrançois Tigeot { 326b5c29a34SFrançois Tigeot u32 flags = 0; 327*ba55f2f5SFrançois Tigeot u32 scratch_addr = ring->scratch.gtt_offset + 2 * CACHELINE_BYTES; 328b5c29a34SFrançois Tigeot int ret; 329b5c29a34SFrançois Tigeot 330b5c29a34SFrançois Tigeot /* 331b5c29a34SFrançois Tigeot * Ensure that any following seqno writes only happen when the render 332b5c29a34SFrançois Tigeot * cache is indeed flushed. 333b5c29a34SFrançois Tigeot * 334b5c29a34SFrançois Tigeot * Workaround: 4th PIPE_CONTROL command (except the ones with only 335b5c29a34SFrançois Tigeot * read-cache invalidate bits set) must have the CS_STALL bit set. We 336b5c29a34SFrançois Tigeot * don't try to be clever and just set it unconditionally. 337b5c29a34SFrançois Tigeot */ 338b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_CS_STALL; 339b5c29a34SFrançois Tigeot 340b5c29a34SFrançois Tigeot /* Just flush everything. Experiments have shown that reducing the 341b5c29a34SFrançois Tigeot * number of bits based on the write domains has little performance 342b5c29a34SFrançois Tigeot * impact. 343b5c29a34SFrançois Tigeot */ 344b5c29a34SFrançois Tigeot if (flush_domains) { 345b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH; 346b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_DEPTH_CACHE_FLUSH; 347b5c29a34SFrançois Tigeot } 348b5c29a34SFrançois Tigeot if (invalidate_domains) { 349b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_TLB_INVALIDATE; 350b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE; 351b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE; 352b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_VF_CACHE_INVALIDATE; 353b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_CONST_CACHE_INVALIDATE; 354b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_STATE_CACHE_INVALIDATE; 355b5c29a34SFrançois Tigeot /* 356b5c29a34SFrançois Tigeot * TLB invalidate requires a post-sync write. 357b5c29a34SFrançois Tigeot */ 358b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_QW_WRITE; 359a2fdbec6SFrançois Tigeot flags |= PIPE_CONTROL_GLOBAL_GTT_IVB; 360b5c29a34SFrançois Tigeot 361b5c29a34SFrançois Tigeot /* Workaround: we must issue a pipe_control with CS-stall bit 362b5c29a34SFrançois Tigeot * set before a pipe_control command that has the state cache 363b5c29a34SFrançois Tigeot * invalidate bit set. */ 364b5c29a34SFrançois Tigeot gen7_render_ring_cs_stall_wa(ring); 365b5c29a34SFrançois Tigeot } 366b5c29a34SFrançois Tigeot 367b5c29a34SFrançois Tigeot ret = intel_ring_begin(ring, 4); 368b5c29a34SFrançois Tigeot if (ret) 369b5c29a34SFrançois Tigeot return ret; 370b5c29a34SFrançois Tigeot 371b5c29a34SFrançois Tigeot intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(4)); 372b5c29a34SFrançois Tigeot intel_ring_emit(ring, flags); 373a2fdbec6SFrançois Tigeot intel_ring_emit(ring, scratch_addr); 374b5c29a34SFrançois Tigeot intel_ring_emit(ring, 0); 375e3adcf8fSFrançois Tigeot intel_ring_advance(ring); 376e3adcf8fSFrançois Tigeot 3779edbd4a0SFrançois Tigeot if (!invalidate_domains && flush_domains) 3785d0b1887SFrançois Tigeot return gen7_ring_fbc_flush(ring, FBC_REND_NUKE); 3795d0b1887SFrançois Tigeot 380e3adcf8fSFrançois Tigeot return 0; 381e3adcf8fSFrançois Tigeot } 382e3adcf8fSFrançois Tigeot 3839edbd4a0SFrançois Tigeot static int 384*ba55f2f5SFrançois Tigeot gen8_render_ring_flush(struct intel_engine_cs *ring, 3859edbd4a0SFrançois Tigeot u32 invalidate_domains, u32 flush_domains) 3869edbd4a0SFrançois Tigeot { 3879edbd4a0SFrançois Tigeot u32 flags = 0; 388*ba55f2f5SFrançois Tigeot u32 scratch_addr = ring->scratch.gtt_offset + 2 * CACHELINE_BYTES; 3899edbd4a0SFrançois Tigeot int ret; 3909edbd4a0SFrançois Tigeot 3919edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_CS_STALL; 3929edbd4a0SFrançois Tigeot 3939edbd4a0SFrançois Tigeot if (flush_domains) { 3949edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH; 3959edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_DEPTH_CACHE_FLUSH; 3969edbd4a0SFrançois Tigeot } 3979edbd4a0SFrançois Tigeot if (invalidate_domains) { 3989edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_TLB_INVALIDATE; 3999edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE; 4009edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE; 4019edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_VF_CACHE_INVALIDATE; 4029edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_CONST_CACHE_INVALIDATE; 4039edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_STATE_CACHE_INVALIDATE; 4049edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_QW_WRITE; 4059edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_GLOBAL_GTT_IVB; 4069edbd4a0SFrançois Tigeot } 4079edbd4a0SFrançois Tigeot 4089edbd4a0SFrançois Tigeot ret = intel_ring_begin(ring, 6); 4099edbd4a0SFrançois Tigeot if (ret) 4109edbd4a0SFrançois Tigeot return ret; 4119edbd4a0SFrançois Tigeot 4129edbd4a0SFrançois Tigeot intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(6)); 4139edbd4a0SFrançois Tigeot intel_ring_emit(ring, flags); 4149edbd4a0SFrançois Tigeot intel_ring_emit(ring, scratch_addr); 4159edbd4a0SFrançois Tigeot intel_ring_emit(ring, 0); 4169edbd4a0SFrançois Tigeot intel_ring_emit(ring, 0); 4179edbd4a0SFrançois Tigeot intel_ring_emit(ring, 0); 4189edbd4a0SFrançois Tigeot intel_ring_advance(ring); 4199edbd4a0SFrançois Tigeot 4209edbd4a0SFrançois Tigeot return 0; 4219edbd4a0SFrançois Tigeot 4229edbd4a0SFrançois Tigeot } 4239edbd4a0SFrançois Tigeot 424*ba55f2f5SFrançois Tigeot static void ring_write_tail(struct intel_engine_cs *ring, 425b5c29a34SFrançois Tigeot u32 value) 426e3adcf8fSFrançois Tigeot { 427*ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = ring->dev->dev_private; 428e3adcf8fSFrançois Tigeot I915_WRITE_TAIL(ring, value); 429e3adcf8fSFrançois Tigeot } 430e3adcf8fSFrançois Tigeot 431*ba55f2f5SFrançois Tigeot u64 intel_ring_get_active_head(struct intel_engine_cs *ring) 432e3adcf8fSFrançois Tigeot { 433*ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = ring->dev->dev_private; 434*ba55f2f5SFrançois Tigeot u64 acthd; 435e3adcf8fSFrançois Tigeot 436*ba55f2f5SFrançois Tigeot if (INTEL_INFO(ring->dev)->gen >= 8) 437*ba55f2f5SFrançois Tigeot acthd = I915_READ64_2x32(RING_ACTHD(ring->mmio_base), 438*ba55f2f5SFrançois Tigeot RING_ACTHD_UDW(ring->mmio_base)); 439*ba55f2f5SFrançois Tigeot else if (INTEL_INFO(ring->dev)->gen >= 4) 440*ba55f2f5SFrançois Tigeot acthd = I915_READ(RING_ACTHD(ring->mmio_base)); 441*ba55f2f5SFrançois Tigeot else 442*ba55f2f5SFrançois Tigeot acthd = I915_READ(ACTHD); 443*ba55f2f5SFrançois Tigeot 444*ba55f2f5SFrançois Tigeot return acthd; 445e3adcf8fSFrançois Tigeot } 446e3adcf8fSFrançois Tigeot 447*ba55f2f5SFrançois Tigeot static void ring_setup_phys_status_page(struct intel_engine_cs *ring) 4485d0b1887SFrançois Tigeot { 4495d0b1887SFrançois Tigeot struct drm_i915_private *dev_priv = ring->dev->dev_private; 4505d0b1887SFrançois Tigeot u32 addr; 4515d0b1887SFrançois Tigeot 4525d0b1887SFrançois Tigeot addr = dev_priv->status_page_dmah->busaddr; 4535d0b1887SFrançois Tigeot if (INTEL_INFO(ring->dev)->gen >= 4) 4545d0b1887SFrançois Tigeot addr |= (dev_priv->status_page_dmah->busaddr >> 28) & 0xf0; 4555d0b1887SFrançois Tigeot I915_WRITE(HWS_PGA, addr); 4565d0b1887SFrançois Tigeot } 4575d0b1887SFrançois Tigeot 458*ba55f2f5SFrançois Tigeot static bool stop_ring(struct intel_engine_cs *ring) 459e3adcf8fSFrançois Tigeot { 460*ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = to_i915(ring->dev); 461e3adcf8fSFrançois Tigeot 462*ba55f2f5SFrançois Tigeot if (!IS_GEN2(ring->dev)) { 463*ba55f2f5SFrançois Tigeot I915_WRITE_MODE(ring, _MASKED_BIT_ENABLE(STOP_RING)); 464*ba55f2f5SFrançois Tigeot if (wait_for_atomic((I915_READ_MODE(ring) & MODE_IDLE) != 0, 1000)) { 465*ba55f2f5SFrançois Tigeot DRM_ERROR("%s :timed out trying to stop ring\n", ring->name); 466*ba55f2f5SFrançois Tigeot return false; 467*ba55f2f5SFrançois Tigeot } 468*ba55f2f5SFrançois Tigeot } 469686a02f1SFrançois Tigeot 470e3adcf8fSFrançois Tigeot I915_WRITE_CTL(ring, 0); 471e3adcf8fSFrançois Tigeot I915_WRITE_HEAD(ring, 0); 472e3adcf8fSFrançois Tigeot ring->write_tail(ring, 0); 473e3adcf8fSFrançois Tigeot 474*ba55f2f5SFrançois Tigeot if (!IS_GEN2(ring->dev)) { 475*ba55f2f5SFrançois Tigeot (void)I915_READ_CTL(ring); 476*ba55f2f5SFrançois Tigeot I915_WRITE_MODE(ring, _MASKED_BIT_DISABLE(STOP_RING)); 477*ba55f2f5SFrançois Tigeot } 478e3adcf8fSFrançois Tigeot 479*ba55f2f5SFrançois Tigeot return (I915_READ_HEAD(ring) & HEAD_ADDR) == 0; 480*ba55f2f5SFrançois Tigeot } 481*ba55f2f5SFrançois Tigeot 482*ba55f2f5SFrançois Tigeot static int init_ring_common(struct intel_engine_cs *ring) 483*ba55f2f5SFrançois Tigeot { 484*ba55f2f5SFrançois Tigeot struct drm_device *dev = ring->dev; 485*ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 486*ba55f2f5SFrançois Tigeot struct intel_ringbuffer *ringbuf = ring->buffer; 487*ba55f2f5SFrançois Tigeot struct drm_i915_gem_object *obj = ringbuf->obj; 488*ba55f2f5SFrançois Tigeot int ret = 0; 489*ba55f2f5SFrançois Tigeot 490*ba55f2f5SFrançois Tigeot gen6_gt_force_wake_get(dev_priv, FORCEWAKE_ALL); 491*ba55f2f5SFrançois Tigeot 492*ba55f2f5SFrançois Tigeot if (!stop_ring(ring)) { 493*ba55f2f5SFrançois Tigeot /* G45 ring initialization often fails to reset head to zero */ 494b5c29a34SFrançois Tigeot DRM_DEBUG_KMS("%s head not reset to zero " 495e3adcf8fSFrançois Tigeot "ctl %08x head %08x tail %08x start %08x\n", 496e3adcf8fSFrançois Tigeot ring->name, 497e3adcf8fSFrançois Tigeot I915_READ_CTL(ring), 498e3adcf8fSFrançois Tigeot I915_READ_HEAD(ring), 499e3adcf8fSFrançois Tigeot I915_READ_TAIL(ring), 500e3adcf8fSFrançois Tigeot I915_READ_START(ring)); 501e3adcf8fSFrançois Tigeot 502*ba55f2f5SFrançois Tigeot if (!stop_ring(ring)) { 503e3adcf8fSFrançois Tigeot DRM_ERROR("failed to set %s head to zero " 504e3adcf8fSFrançois Tigeot "ctl %08x head %08x tail %08x start %08x\n", 505e3adcf8fSFrançois Tigeot ring->name, 506e3adcf8fSFrançois Tigeot I915_READ_CTL(ring), 507e3adcf8fSFrançois Tigeot I915_READ_HEAD(ring), 508e3adcf8fSFrançois Tigeot I915_READ_TAIL(ring), 509e3adcf8fSFrançois Tigeot I915_READ_START(ring)); 510686a02f1SFrançois Tigeot ret = -EIO; 511686a02f1SFrançois Tigeot goto out; 512e3adcf8fSFrançois Tigeot } 513*ba55f2f5SFrançois Tigeot } 514*ba55f2f5SFrançois Tigeot 515*ba55f2f5SFrançois Tigeot if (I915_NEED_GFX_HWS(dev)) 516*ba55f2f5SFrançois Tigeot intel_ring_setup_status_page(ring); 517*ba55f2f5SFrançois Tigeot else 518*ba55f2f5SFrançois Tigeot ring_setup_phys_status_page(ring); 519*ba55f2f5SFrançois Tigeot 520*ba55f2f5SFrançois Tigeot /* Initialize the ring. This must happen _after_ we've cleared the ring 521*ba55f2f5SFrançois Tigeot * registers with the above sequence (the readback of the HEAD registers 522*ba55f2f5SFrançois Tigeot * also enforces ordering), otherwise the hw might lose the new ring 523*ba55f2f5SFrançois Tigeot * register values. */ 524*ba55f2f5SFrançois Tigeot I915_WRITE_START(ring, i915_gem_obj_ggtt_offset(obj)); 525*ba55f2f5SFrançois Tigeot I915_WRITE_CTL(ring, 526*ba55f2f5SFrançois Tigeot ((ringbuf->size - PAGE_SIZE) & RING_NR_PAGES) 527*ba55f2f5SFrançois Tigeot | RING_VALID); 528*ba55f2f5SFrançois Tigeot 529*ba55f2f5SFrançois Tigeot /* If the head is still not zero, the ring is dead */ 530*ba55f2f5SFrançois Tigeot if (wait_for((I915_READ_CTL(ring) & RING_VALID) != 0 && 531*ba55f2f5SFrançois Tigeot I915_READ_START(ring) == i915_gem_obj_ggtt_offset(obj) && 532*ba55f2f5SFrançois Tigeot (I915_READ_HEAD(ring) & HEAD_ADDR) == 0, 50)) { 533*ba55f2f5SFrançois Tigeot DRM_ERROR("%s initialization failed " 534*ba55f2f5SFrançois Tigeot "ctl %08x (valid? %d) head %08x tail %08x start %08x [expected %08lx]\n", 535*ba55f2f5SFrançois Tigeot ring->name, 536*ba55f2f5SFrançois Tigeot I915_READ_CTL(ring), I915_READ_CTL(ring) & RING_VALID, 537*ba55f2f5SFrançois Tigeot I915_READ_HEAD(ring), I915_READ_TAIL(ring), 538*ba55f2f5SFrançois Tigeot I915_READ_START(ring), (unsigned long)i915_gem_obj_ggtt_offset(obj)); 539*ba55f2f5SFrançois Tigeot ret = -EIO; 540*ba55f2f5SFrançois Tigeot goto out; 541*ba55f2f5SFrançois Tigeot } 542e3adcf8fSFrançois Tigeot 543e3adcf8fSFrançois Tigeot if (!drm_core_check_feature(ring->dev, DRIVER_MODESET)) 544e3adcf8fSFrançois Tigeot i915_kernel_lost_context(ring->dev); 545e3adcf8fSFrançois Tigeot else { 546*ba55f2f5SFrançois Tigeot ringbuf->head = I915_READ_HEAD(ring); 547*ba55f2f5SFrançois Tigeot ringbuf->tail = I915_READ_TAIL(ring) & TAIL_ADDR; 548*ba55f2f5SFrançois Tigeot ringbuf->space = ring_space(ring); 549*ba55f2f5SFrançois Tigeot ringbuf->last_retired_head = -1; 550e3adcf8fSFrançois Tigeot } 551e3adcf8fSFrançois Tigeot 5525d0b1887SFrançois Tigeot memset(&ring->hangcheck, 0, sizeof(ring->hangcheck)); 5535d0b1887SFrançois Tigeot 554686a02f1SFrançois Tigeot out: 5559edbd4a0SFrançois Tigeot gen6_gt_force_wake_put(dev_priv, FORCEWAKE_ALL); 556686a02f1SFrançois Tigeot 557686a02f1SFrançois Tigeot return ret; 558e3adcf8fSFrançois Tigeot } 559e3adcf8fSFrançois Tigeot 560e3adcf8fSFrançois Tigeot static int 561*ba55f2f5SFrançois Tigeot init_pipe_control(struct intel_engine_cs *ring) 562e3adcf8fSFrançois Tigeot { 563e3adcf8fSFrançois Tigeot int ret; 564e3adcf8fSFrançois Tigeot 5659edbd4a0SFrançois Tigeot if (ring->scratch.obj) 566e3adcf8fSFrançois Tigeot return 0; 567e3adcf8fSFrançois Tigeot 5689edbd4a0SFrançois Tigeot ring->scratch.obj = i915_gem_alloc_object(ring->dev, 4096); 5699edbd4a0SFrançois Tigeot if (ring->scratch.obj == NULL) { 570e3adcf8fSFrançois Tigeot DRM_ERROR("Failed to allocate seqno page\n"); 571e3adcf8fSFrançois Tigeot ret = -ENOMEM; 572e3adcf8fSFrançois Tigeot goto err; 573e3adcf8fSFrançois Tigeot } 574e3adcf8fSFrançois Tigeot 575*ba55f2f5SFrançois Tigeot ret = i915_gem_object_set_cache_level(ring->scratch.obj, I915_CACHE_LLC); 576*ba55f2f5SFrançois Tigeot if (ret) 577*ba55f2f5SFrançois Tigeot goto err_unref; 578e3adcf8fSFrançois Tigeot 579*ba55f2f5SFrançois Tigeot ret = i915_gem_obj_ggtt_pin(ring->scratch.obj, 4096, 0); 580e3adcf8fSFrançois Tigeot if (ret) 581e3adcf8fSFrançois Tigeot goto err_unref; 582e3adcf8fSFrançois Tigeot 5839edbd4a0SFrançois Tigeot ring->scratch.gtt_offset = i915_gem_obj_ggtt_offset(ring->scratch.obj); 5849edbd4a0SFrançois Tigeot ring->scratch.cpu_page = kmap(ring->scratch.obj->pages[0]); 5859edbd4a0SFrançois Tigeot if (ring->scratch.cpu_page == NULL) { 5865d0b1887SFrançois Tigeot ret = -ENOMEM; 587e3adcf8fSFrançois Tigeot goto err_unpin; 5885d0b1887SFrançois Tigeot } 589a2fdbec6SFrançois Tigeot 590a2fdbec6SFrançois Tigeot DRM_DEBUG_DRIVER("%s pipe control offset: 0x%08x\n", 5919edbd4a0SFrançois Tigeot ring->name, ring->scratch.gtt_offset); 592e3adcf8fSFrançois Tigeot return 0; 593e3adcf8fSFrançois Tigeot 594e3adcf8fSFrançois Tigeot err_unpin: 595*ba55f2f5SFrançois Tigeot i915_gem_object_ggtt_unpin(ring->scratch.obj); 596e3adcf8fSFrançois Tigeot err_unref: 5979edbd4a0SFrançois Tigeot drm_gem_object_unreference(&ring->scratch.obj->base); 598e3adcf8fSFrançois Tigeot err: 599e3adcf8fSFrançois Tigeot return ret; 600e3adcf8fSFrançois Tigeot } 601e3adcf8fSFrançois Tigeot 602*ba55f2f5SFrançois Tigeot static int init_render_ring(struct intel_engine_cs *ring) 603e3adcf8fSFrançois Tigeot { 604e3adcf8fSFrançois Tigeot struct drm_device *dev = ring->dev; 605e3adcf8fSFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 606e3adcf8fSFrançois Tigeot int ret = init_ring_common(ring); 607e3adcf8fSFrançois Tigeot 608*ba55f2f5SFrançois Tigeot /* WaTimedSingleVertexDispatch:cl,bw,ctg,elk,ilk,snb */ 609*ba55f2f5SFrançois Tigeot if (INTEL_INFO(dev)->gen >= 4 && INTEL_INFO(dev)->gen < 7) 610f4e1c372SFrançois Tigeot I915_WRITE(MI_MODE, _MASKED_BIT_ENABLE(VS_TIMER_DISPATCH)); 611f4e1c372SFrançois Tigeot 612f4e1c372SFrançois Tigeot /* We need to disable the AsyncFlip performance optimisations in order 613f4e1c372SFrançois Tigeot * to use MI_WAIT_FOR_EVENT within the CS. It should already be 614f4e1c372SFrançois Tigeot * programmed to '1' on all products. 6155d0b1887SFrançois Tigeot * 616*ba55f2f5SFrançois Tigeot * WaDisableAsyncFlipPerfMode:snb,ivb,hsw,vlv,bdw,chv 617f4e1c372SFrançois Tigeot */ 618f4e1c372SFrançois Tigeot if (INTEL_INFO(dev)->gen >= 6) 619f4e1c372SFrançois Tigeot I915_WRITE(MI_MODE, _MASKED_BIT_ENABLE(ASYNC_FLIP_PERF_DISABLE)); 620f4e1c372SFrançois Tigeot 621f4e1c372SFrançois Tigeot /* Required for the hardware to program scanline values for waiting */ 622*ba55f2f5SFrançois Tigeot /* WaEnableFlushTlbInvalidationMode:snb */ 623f4e1c372SFrançois Tigeot if (INTEL_INFO(dev)->gen == 6) 624f4e1c372SFrançois Tigeot I915_WRITE(GFX_MODE, 625*ba55f2f5SFrançois Tigeot _MASKED_BIT_ENABLE(GFX_TLB_INVALIDATE_EXPLICIT)); 626f4e1c372SFrançois Tigeot 627*ba55f2f5SFrançois Tigeot /* WaBCSVCSTlbInvalidationMode:ivb,vlv,hsw */ 628e3adcf8fSFrançois Tigeot if (IS_GEN7(dev)) 629e3adcf8fSFrançois Tigeot I915_WRITE(GFX_MODE_GEN7, 630*ba55f2f5SFrançois Tigeot _MASKED_BIT_ENABLE(GFX_TLB_INVALIDATE_EXPLICIT) | 631f4e1c372SFrançois Tigeot _MASKED_BIT_ENABLE(GFX_REPLAY_MODE)); 632e3adcf8fSFrançois Tigeot 633e3adcf8fSFrançois Tigeot if (INTEL_INFO(dev)->gen >= 5) { 634e3adcf8fSFrançois Tigeot ret = init_pipe_control(ring); 635e3adcf8fSFrançois Tigeot if (ret) 636e3adcf8fSFrançois Tigeot return ret; 637e3adcf8fSFrançois Tigeot } 638e3adcf8fSFrançois Tigeot 639e3adcf8fSFrançois Tigeot if (IS_GEN6(dev)) { 640e3adcf8fSFrançois Tigeot /* From the Sandybridge PRM, volume 1 part 3, page 24: 641e3adcf8fSFrançois Tigeot * "If this bit is set, STCunit will have LRA as replacement 642e3adcf8fSFrançois Tigeot * policy. [...] This bit must be reset. LRA replacement 643e3adcf8fSFrançois Tigeot * policy is not supported." 644e3adcf8fSFrançois Tigeot */ 645e3adcf8fSFrançois Tigeot I915_WRITE(CACHE_MODE_0, 646f4e1c372SFrançois Tigeot _MASKED_BIT_DISABLE(CM0_STC_EVICT_DISABLE_LRA_SNB)); 647e3adcf8fSFrançois Tigeot } 648e3adcf8fSFrançois Tigeot 649f4e1c372SFrançois Tigeot if (INTEL_INFO(dev)->gen >= 6) 650f4e1c372SFrançois Tigeot I915_WRITE(INSTPM, _MASKED_BIT_ENABLE(INSTPM_FORCE_ORDERING)); 651f4e1c372SFrançois Tigeot 6529edbd4a0SFrançois Tigeot if (HAS_L3_DPF(dev)) 6539edbd4a0SFrançois Tigeot I915_WRITE_IMR(ring, ~GT_PARITY_ERROR(dev)); 654e3adcf8fSFrançois Tigeot 655e3adcf8fSFrançois Tigeot return ret; 656e3adcf8fSFrançois Tigeot } 657e3adcf8fSFrançois Tigeot 658*ba55f2f5SFrançois Tigeot static void render_ring_cleanup(struct intel_engine_cs *ring) 659e3adcf8fSFrançois Tigeot { 660b5c29a34SFrançois Tigeot struct drm_device *dev = ring->dev; 661b5c29a34SFrançois Tigeot 6629edbd4a0SFrançois Tigeot if (ring->scratch.obj == NULL) 663e3adcf8fSFrançois Tigeot return; 664e3adcf8fSFrançois Tigeot 6659edbd4a0SFrançois Tigeot if (INTEL_INFO(dev)->gen >= 5) { 6669edbd4a0SFrançois Tigeot kunmap(ring->scratch.obj->pages[0]); 667*ba55f2f5SFrançois Tigeot i915_gem_object_ggtt_unpin(ring->scratch.obj); 6689edbd4a0SFrançois Tigeot } 669b5c29a34SFrançois Tigeot 6709edbd4a0SFrançois Tigeot drm_gem_object_unreference(&ring->scratch.obj->base); 6719edbd4a0SFrançois Tigeot ring->scratch.obj = NULL; 672e3adcf8fSFrançois Tigeot } 673e3adcf8fSFrançois Tigeot 674*ba55f2f5SFrançois Tigeot static int gen6_signal(struct intel_engine_cs *signaller, 675*ba55f2f5SFrançois Tigeot unsigned int num_dwords) 676e3adcf8fSFrançois Tigeot { 677*ba55f2f5SFrançois Tigeot struct drm_device *dev = signaller->dev; 678*ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 679*ba55f2f5SFrançois Tigeot struct intel_engine_cs *useless; 680*ba55f2f5SFrançois Tigeot int i, ret; 681*ba55f2f5SFrançois Tigeot 682*ba55f2f5SFrançois Tigeot /* NB: In order to be able to do semaphore MBOX updates for varying 683*ba55f2f5SFrançois Tigeot * number of rings, it's easiest if we round up each individual update 684*ba55f2f5SFrançois Tigeot * to a multiple of 2 (since ring updates must always be a multiple of 685*ba55f2f5SFrançois Tigeot * 2) even though the actual update only requires 3 dwords. 6865d0b1887SFrançois Tigeot */ 6875d0b1887SFrançois Tigeot #define MBOX_UPDATE_DWORDS 4 688*ba55f2f5SFrançois Tigeot if (i915_semaphore_is_enabled(dev)) 689*ba55f2f5SFrançois Tigeot num_dwords += ((I915_NUM_RINGS-1) * MBOX_UPDATE_DWORDS); 690*ba55f2f5SFrançois Tigeot else 691*ba55f2f5SFrançois Tigeot return intel_ring_begin(signaller, num_dwords); 692*ba55f2f5SFrançois Tigeot 693*ba55f2f5SFrançois Tigeot ret = intel_ring_begin(signaller, num_dwords); 694*ba55f2f5SFrançois Tigeot if (ret) 695*ba55f2f5SFrançois Tigeot return ret; 696*ba55f2f5SFrançois Tigeot #undef MBOX_UPDATE_DWORDS 697*ba55f2f5SFrançois Tigeot 698*ba55f2f5SFrançois Tigeot for_each_ring(useless, dev_priv, i) { 699*ba55f2f5SFrançois Tigeot u32 mbox_reg = signaller->semaphore.mbox.signal[i]; 700*ba55f2f5SFrançois Tigeot if (mbox_reg != GEN6_NOSYNC) { 701*ba55f2f5SFrançois Tigeot intel_ring_emit(signaller, MI_LOAD_REGISTER_IMM(1)); 702*ba55f2f5SFrançois Tigeot intel_ring_emit(signaller, mbox_reg); 703*ba55f2f5SFrançois Tigeot intel_ring_emit(signaller, signaller->outstanding_lazy_seqno); 704*ba55f2f5SFrançois Tigeot intel_ring_emit(signaller, MI_NOOP); 705*ba55f2f5SFrançois Tigeot } else { 706*ba55f2f5SFrançois Tigeot intel_ring_emit(signaller, MI_NOOP); 707*ba55f2f5SFrançois Tigeot intel_ring_emit(signaller, MI_NOOP); 708*ba55f2f5SFrançois Tigeot intel_ring_emit(signaller, MI_NOOP); 709*ba55f2f5SFrançois Tigeot intel_ring_emit(signaller, MI_NOOP); 710*ba55f2f5SFrançois Tigeot } 711*ba55f2f5SFrançois Tigeot } 712*ba55f2f5SFrançois Tigeot 713*ba55f2f5SFrançois Tigeot return 0; 714e3adcf8fSFrançois Tigeot } 715e3adcf8fSFrançois Tigeot 716e3adcf8fSFrançois Tigeot /** 717e3adcf8fSFrançois Tigeot * gen6_add_request - Update the semaphore mailbox registers 718e3adcf8fSFrançois Tigeot * 719e3adcf8fSFrançois Tigeot * @ring - ring that is adding a request 720e3adcf8fSFrançois Tigeot * @seqno - return seqno stuck into the ring 721e3adcf8fSFrançois Tigeot * 722e3adcf8fSFrançois Tigeot * Update the mailbox registers in the *other* rings with the current seqno. 723e3adcf8fSFrançois Tigeot * This acts like a signal in the canonical semaphore. 724e3adcf8fSFrançois Tigeot */ 725e3adcf8fSFrançois Tigeot static int 726*ba55f2f5SFrançois Tigeot gen6_add_request(struct intel_engine_cs *ring) 727e3adcf8fSFrançois Tigeot { 728*ba55f2f5SFrançois Tigeot int ret; 729e3adcf8fSFrançois Tigeot 730*ba55f2f5SFrançois Tigeot ret = ring->semaphore.signal(ring, 4); 7319edbd4a0SFrançois Tigeot if (ret) 7329edbd4a0SFrançois Tigeot return ret; 7339edbd4a0SFrançois Tigeot 734e3adcf8fSFrançois Tigeot intel_ring_emit(ring, MI_STORE_DWORD_INDEX); 735e3adcf8fSFrançois Tigeot intel_ring_emit(ring, I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT); 7369edbd4a0SFrançois Tigeot intel_ring_emit(ring, ring->outstanding_lazy_seqno); 737e3adcf8fSFrançois Tigeot intel_ring_emit(ring, MI_USER_INTERRUPT); 7389edbd4a0SFrançois Tigeot __intel_ring_advance(ring); 739e3adcf8fSFrançois Tigeot 740e3adcf8fSFrançois Tigeot return 0; 741e3adcf8fSFrançois Tigeot } 742e3adcf8fSFrançois Tigeot 743a2fdbec6SFrançois Tigeot static inline bool i915_gem_has_seqno_wrapped(struct drm_device *dev, 744a2fdbec6SFrançois Tigeot u32 seqno) 745a2fdbec6SFrançois Tigeot { 746a2fdbec6SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 747a2fdbec6SFrançois Tigeot return dev_priv->last_seqno < seqno; 748a2fdbec6SFrançois Tigeot } 749a2fdbec6SFrançois Tigeot 750e3adcf8fSFrançois Tigeot /** 751e3adcf8fSFrançois Tigeot * intel_ring_sync - sync the waiter to the signaller on seqno 752e3adcf8fSFrançois Tigeot * 753e3adcf8fSFrançois Tigeot * @waiter - ring that is waiting 754e3adcf8fSFrançois Tigeot * @signaller - ring which has, or will signal 755e3adcf8fSFrançois Tigeot * @seqno - seqno which the waiter will block on 756e3adcf8fSFrançois Tigeot */ 757e3adcf8fSFrançois Tigeot static int 758*ba55f2f5SFrançois Tigeot gen6_ring_sync(struct intel_engine_cs *waiter, 759*ba55f2f5SFrançois Tigeot struct intel_engine_cs *signaller, 760e3adcf8fSFrançois Tigeot u32 seqno) 761e3adcf8fSFrançois Tigeot { 762e3adcf8fSFrançois Tigeot u32 dw1 = MI_SEMAPHORE_MBOX | 763e3adcf8fSFrançois Tigeot MI_SEMAPHORE_COMPARE | 764e3adcf8fSFrançois Tigeot MI_SEMAPHORE_REGISTER; 765*ba55f2f5SFrançois Tigeot u32 wait_mbox = signaller->semaphore.mbox.wait[waiter->id]; 766*ba55f2f5SFrançois Tigeot int ret; 767e3adcf8fSFrançois Tigeot 768686a02f1SFrançois Tigeot /* Throughout all of the GEM code, seqno passed implies our current 769686a02f1SFrançois Tigeot * seqno is >= the last seqno executed. However for hardware the 770686a02f1SFrançois Tigeot * comparison is strictly greater than. 771686a02f1SFrançois Tigeot */ 772686a02f1SFrançois Tigeot seqno -= 1; 773686a02f1SFrançois Tigeot 774*ba55f2f5SFrançois Tigeot WARN_ON(wait_mbox == MI_SEMAPHORE_SYNC_INVALID); 775686a02f1SFrançois Tigeot 776e3adcf8fSFrançois Tigeot ret = intel_ring_begin(waiter, 4); 777e3adcf8fSFrançois Tigeot if (ret) 778e3adcf8fSFrançois Tigeot return ret; 779e3adcf8fSFrançois Tigeot 780a2fdbec6SFrançois Tigeot /* If seqno wrap happened, omit the wait with no-ops */ 781a2fdbec6SFrançois Tigeot if (likely(!i915_gem_has_seqno_wrapped(waiter->dev, seqno))) { 782*ba55f2f5SFrançois Tigeot intel_ring_emit(waiter, dw1 | wait_mbox); 783e3adcf8fSFrançois Tigeot intel_ring_emit(waiter, seqno); 784e3adcf8fSFrançois Tigeot intel_ring_emit(waiter, 0); 785e3adcf8fSFrançois Tigeot intel_ring_emit(waiter, MI_NOOP); 786a2fdbec6SFrançois Tigeot } else { 787a2fdbec6SFrançois Tigeot intel_ring_emit(waiter, MI_NOOP); 788a2fdbec6SFrançois Tigeot intel_ring_emit(waiter, MI_NOOP); 789a2fdbec6SFrançois Tigeot intel_ring_emit(waiter, MI_NOOP); 790a2fdbec6SFrançois Tigeot intel_ring_emit(waiter, MI_NOOP); 791a2fdbec6SFrançois Tigeot } 792e3adcf8fSFrançois Tigeot intel_ring_advance(waiter); 793e3adcf8fSFrançois Tigeot 794e3adcf8fSFrançois Tigeot return 0; 795e3adcf8fSFrançois Tigeot } 796e3adcf8fSFrançois Tigeot 797e3adcf8fSFrançois Tigeot #define PIPE_CONTROL_FLUSH(ring__, addr__) \ 798e3adcf8fSFrançois Tigeot do { \ 799e3adcf8fSFrançois Tigeot intel_ring_emit(ring__, GFX_OP_PIPE_CONTROL(4) | PIPE_CONTROL_QW_WRITE | \ 800e3adcf8fSFrançois Tigeot PIPE_CONTROL_DEPTH_STALL); \ 801e3adcf8fSFrançois Tigeot intel_ring_emit(ring__, (addr__) | PIPE_CONTROL_GLOBAL_GTT); \ 802e3adcf8fSFrançois Tigeot intel_ring_emit(ring__, 0); \ 803e3adcf8fSFrançois Tigeot intel_ring_emit(ring__, 0); \ 804e3adcf8fSFrançois Tigeot } while (0) 805e3adcf8fSFrançois Tigeot 806e3adcf8fSFrançois Tigeot static int 807*ba55f2f5SFrançois Tigeot pc_render_add_request(struct intel_engine_cs *ring) 808e3adcf8fSFrançois Tigeot { 809*ba55f2f5SFrançois Tigeot u32 scratch_addr = ring->scratch.gtt_offset + 2 * CACHELINE_BYTES; 810e3adcf8fSFrançois Tigeot int ret; 811e3adcf8fSFrançois Tigeot 812e3adcf8fSFrançois Tigeot /* For Ironlake, MI_USER_INTERRUPT was deprecated and apparently 813e3adcf8fSFrançois Tigeot * incoherent with writes to memory, i.e. completely fubar, 814e3adcf8fSFrançois Tigeot * so we need to use PIPE_NOTIFY instead. 815e3adcf8fSFrançois Tigeot * 816e3adcf8fSFrançois Tigeot * However, we also need to workaround the qword write 817e3adcf8fSFrançois Tigeot * incoherence by flushing the 6 PIPE_NOTIFY buffers out to 818e3adcf8fSFrançois Tigeot * memory before requesting an interrupt. 819e3adcf8fSFrançois Tigeot */ 820e3adcf8fSFrançois Tigeot ret = intel_ring_begin(ring, 32); 821e3adcf8fSFrançois Tigeot if (ret) 822e3adcf8fSFrançois Tigeot return ret; 823e3adcf8fSFrançois Tigeot 824e3adcf8fSFrançois Tigeot intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(4) | PIPE_CONTROL_QW_WRITE | 825e3adcf8fSFrançois Tigeot PIPE_CONTROL_WRITE_FLUSH | 826e3adcf8fSFrançois Tigeot PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE); 8279edbd4a0SFrançois Tigeot intel_ring_emit(ring, ring->scratch.gtt_offset | PIPE_CONTROL_GLOBAL_GTT); 8289edbd4a0SFrançois Tigeot intel_ring_emit(ring, ring->outstanding_lazy_seqno); 829e3adcf8fSFrançois Tigeot intel_ring_emit(ring, 0); 830e3adcf8fSFrançois Tigeot PIPE_CONTROL_FLUSH(ring, scratch_addr); 831*ba55f2f5SFrançois Tigeot scratch_addr += 2 * CACHELINE_BYTES; /* write to separate cachelines */ 832e3adcf8fSFrançois Tigeot PIPE_CONTROL_FLUSH(ring, scratch_addr); 833*ba55f2f5SFrançois Tigeot scratch_addr += 2 * CACHELINE_BYTES; 834e3adcf8fSFrançois Tigeot PIPE_CONTROL_FLUSH(ring, scratch_addr); 835*ba55f2f5SFrançois Tigeot scratch_addr += 2 * CACHELINE_BYTES; 836e3adcf8fSFrançois Tigeot PIPE_CONTROL_FLUSH(ring, scratch_addr); 837*ba55f2f5SFrançois Tigeot scratch_addr += 2 * CACHELINE_BYTES; 838e3adcf8fSFrançois Tigeot PIPE_CONTROL_FLUSH(ring, scratch_addr); 839*ba55f2f5SFrançois Tigeot scratch_addr += 2 * CACHELINE_BYTES; 840e3adcf8fSFrançois Tigeot PIPE_CONTROL_FLUSH(ring, scratch_addr); 841b5c29a34SFrançois Tigeot 842e3adcf8fSFrançois Tigeot intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(4) | PIPE_CONTROL_QW_WRITE | 843e3adcf8fSFrançois Tigeot PIPE_CONTROL_WRITE_FLUSH | 844e3adcf8fSFrançois Tigeot PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE | 845e3adcf8fSFrançois Tigeot PIPE_CONTROL_NOTIFY); 8469edbd4a0SFrançois Tigeot intel_ring_emit(ring, ring->scratch.gtt_offset | PIPE_CONTROL_GLOBAL_GTT); 8479edbd4a0SFrançois Tigeot intel_ring_emit(ring, ring->outstanding_lazy_seqno); 848e3adcf8fSFrançois Tigeot intel_ring_emit(ring, 0); 8499edbd4a0SFrançois Tigeot __intel_ring_advance(ring); 850e3adcf8fSFrançois Tigeot 851e3adcf8fSFrançois Tigeot return 0; 852e3adcf8fSFrançois Tigeot } 853e3adcf8fSFrançois Tigeot 854e3adcf8fSFrançois Tigeot static u32 855*ba55f2f5SFrançois Tigeot gen6_ring_get_seqno(struct intel_engine_cs *ring, bool lazy_coherency) 856e3adcf8fSFrançois Tigeot { 857e3adcf8fSFrançois Tigeot /* Workaround to force correct ordering between irq and seqno writes on 858e3adcf8fSFrançois Tigeot * ivb (and maybe also on snb) by reading from a CS register (like 859e3adcf8fSFrançois Tigeot * ACTHD) before reading the status page. */ 860*ba55f2f5SFrançois Tigeot if (!lazy_coherency) { 861*ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = ring->dev->dev_private; 862*ba55f2f5SFrançois Tigeot POSTING_READ(RING_ACTHD(ring->mmio_base)); 863*ba55f2f5SFrançois Tigeot } 864*ba55f2f5SFrançois Tigeot 865e3adcf8fSFrançois Tigeot return intel_read_status_page(ring, I915_GEM_HWS_INDEX); 866e3adcf8fSFrançois Tigeot } 867e3adcf8fSFrançois Tigeot 868b030f26bSFrançois Tigeot static u32 869*ba55f2f5SFrançois Tigeot ring_get_seqno(struct intel_engine_cs *ring, bool lazy_coherency) 870e3adcf8fSFrançois Tigeot { 871e3adcf8fSFrançois Tigeot return intel_read_status_page(ring, I915_GEM_HWS_INDEX); 872e3adcf8fSFrançois Tigeot } 873e3adcf8fSFrançois Tigeot 874a2fdbec6SFrançois Tigeot static void 875*ba55f2f5SFrançois Tigeot ring_set_seqno(struct intel_engine_cs *ring, u32 seqno) 876a2fdbec6SFrançois Tigeot { 877a2fdbec6SFrançois Tigeot intel_write_status_page(ring, I915_GEM_HWS_INDEX, seqno); 878a2fdbec6SFrançois Tigeot } 879a2fdbec6SFrançois Tigeot 880b030f26bSFrançois Tigeot static u32 881*ba55f2f5SFrançois Tigeot pc_render_get_seqno(struct intel_engine_cs *ring, bool lazy_coherency) 882e3adcf8fSFrançois Tigeot { 8839edbd4a0SFrançois Tigeot return ring->scratch.cpu_page[0]; 884e3adcf8fSFrançois Tigeot } 885e3adcf8fSFrançois Tigeot 886a2fdbec6SFrançois Tigeot static void 887*ba55f2f5SFrançois Tigeot pc_render_set_seqno(struct intel_engine_cs *ring, u32 seqno) 888a2fdbec6SFrançois Tigeot { 8899edbd4a0SFrançois Tigeot ring->scratch.cpu_page[0] = seqno; 890a2fdbec6SFrançois Tigeot } 891a2fdbec6SFrançois Tigeot 892e3adcf8fSFrançois Tigeot static bool 893*ba55f2f5SFrançois Tigeot gen5_ring_get_irq(struct intel_engine_cs *ring) 894e3adcf8fSFrançois Tigeot { 895e3adcf8fSFrançois Tigeot struct drm_device *dev = ring->dev; 896*ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 897e3adcf8fSFrançois Tigeot 898e3adcf8fSFrançois Tigeot if (!dev->irq_enabled) 899e3adcf8fSFrançois Tigeot return false; 900e3adcf8fSFrançois Tigeot 90102727ecdSFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_EXCLUSIVE); 9029edbd4a0SFrançois Tigeot if (ring->irq_refcount++ == 0) 9039edbd4a0SFrançois Tigeot ilk_enable_gt_irq(dev_priv, ring->irq_enable_mask); 90402727ecdSFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_RELEASE); 905e3adcf8fSFrançois Tigeot 906e3adcf8fSFrançois Tigeot return true; 907e3adcf8fSFrançois Tigeot } 908e3adcf8fSFrançois Tigeot 909e3adcf8fSFrançois Tigeot static void 910*ba55f2f5SFrançois Tigeot gen5_ring_put_irq(struct intel_engine_cs *ring) 911e3adcf8fSFrançois Tigeot { 912e3adcf8fSFrançois Tigeot struct drm_device *dev = ring->dev; 913*ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 914e3adcf8fSFrançois Tigeot 91502727ecdSFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_EXCLUSIVE); 9169edbd4a0SFrançois Tigeot if (--ring->irq_refcount == 0) 9179edbd4a0SFrançois Tigeot ilk_disable_gt_irq(dev_priv, ring->irq_enable_mask); 918686a02f1SFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_RELEASE); 919686a02f1SFrançois Tigeot } 920686a02f1SFrançois Tigeot 921686a02f1SFrançois Tigeot static bool 922*ba55f2f5SFrançois Tigeot i9xx_ring_get_irq(struct intel_engine_cs *ring) 923686a02f1SFrançois Tigeot { 924686a02f1SFrançois Tigeot struct drm_device *dev = ring->dev; 925*ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 926686a02f1SFrançois Tigeot 927686a02f1SFrançois Tigeot if (!dev->irq_enabled) 928686a02f1SFrançois Tigeot return false; 929686a02f1SFrançois Tigeot 930686a02f1SFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_EXCLUSIVE); 9319edbd4a0SFrançois Tigeot if (ring->irq_refcount++ == 0) { 932686a02f1SFrançois Tigeot dev_priv->irq_mask &= ~ring->irq_enable_mask; 933686a02f1SFrançois Tigeot I915_WRITE(IMR, dev_priv->irq_mask); 934686a02f1SFrançois Tigeot POSTING_READ(IMR); 935686a02f1SFrançois Tigeot } 936686a02f1SFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_RELEASE); 937686a02f1SFrançois Tigeot 938686a02f1SFrançois Tigeot return true; 939686a02f1SFrançois Tigeot } 940686a02f1SFrançois Tigeot 941686a02f1SFrançois Tigeot static void 942*ba55f2f5SFrançois Tigeot i9xx_ring_put_irq(struct intel_engine_cs *ring) 943686a02f1SFrançois Tigeot { 944686a02f1SFrançois Tigeot struct drm_device *dev = ring->dev; 945*ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 946686a02f1SFrançois Tigeot 947686a02f1SFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_EXCLUSIVE); 9489edbd4a0SFrançois Tigeot if (--ring->irq_refcount == 0) { 949686a02f1SFrançois Tigeot dev_priv->irq_mask |= ring->irq_enable_mask; 950686a02f1SFrançois Tigeot I915_WRITE(IMR, dev_priv->irq_mask); 951686a02f1SFrançois Tigeot POSTING_READ(IMR); 952686a02f1SFrançois Tigeot } 953686a02f1SFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_RELEASE); 954686a02f1SFrançois Tigeot } 955686a02f1SFrançois Tigeot 956686a02f1SFrançois Tigeot static bool 957*ba55f2f5SFrançois Tigeot i8xx_ring_get_irq(struct intel_engine_cs *ring) 958686a02f1SFrançois Tigeot { 959686a02f1SFrançois Tigeot struct drm_device *dev = ring->dev; 960*ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 961686a02f1SFrançois Tigeot 962686a02f1SFrançois Tigeot if (!dev->irq_enabled) 963686a02f1SFrançois Tigeot return false; 964686a02f1SFrançois Tigeot 965686a02f1SFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_EXCLUSIVE); 9669edbd4a0SFrançois Tigeot if (ring->irq_refcount++ == 0) { 967686a02f1SFrançois Tigeot dev_priv->irq_mask &= ~ring->irq_enable_mask; 968686a02f1SFrançois Tigeot I915_WRITE16(IMR, dev_priv->irq_mask); 969686a02f1SFrançois Tigeot POSTING_READ16(IMR); 970686a02f1SFrançois Tigeot } 971686a02f1SFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_RELEASE); 972686a02f1SFrançois Tigeot 973686a02f1SFrançois Tigeot return true; 974686a02f1SFrançois Tigeot } 975686a02f1SFrançois Tigeot 976686a02f1SFrançois Tigeot static void 977*ba55f2f5SFrançois Tigeot i8xx_ring_put_irq(struct intel_engine_cs *ring) 978686a02f1SFrançois Tigeot { 979686a02f1SFrançois Tigeot struct drm_device *dev = ring->dev; 980*ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 981686a02f1SFrançois Tigeot 982686a02f1SFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_EXCLUSIVE); 9839edbd4a0SFrançois Tigeot if (--ring->irq_refcount == 0) { 984686a02f1SFrançois Tigeot dev_priv->irq_mask |= ring->irq_enable_mask; 985686a02f1SFrançois Tigeot I915_WRITE16(IMR, dev_priv->irq_mask); 986686a02f1SFrançois Tigeot POSTING_READ16(IMR); 987e3adcf8fSFrançois Tigeot } 98802727ecdSFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_RELEASE); 989e3adcf8fSFrançois Tigeot } 990e3adcf8fSFrançois Tigeot 991*ba55f2f5SFrançois Tigeot void intel_ring_setup_status_page(struct intel_engine_cs *ring) 992e3adcf8fSFrançois Tigeot { 993e3adcf8fSFrançois Tigeot struct drm_device *dev = ring->dev; 994*ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = ring->dev->dev_private; 995b5c29a34SFrançois Tigeot u32 mmio = 0; 996e3adcf8fSFrançois Tigeot 997e3adcf8fSFrançois Tigeot /* The ring status page addresses are no longer next to the rest of 998e3adcf8fSFrançois Tigeot * the ring registers as of gen7. 999e3adcf8fSFrançois Tigeot */ 1000e3adcf8fSFrançois Tigeot if (IS_GEN7(dev)) { 1001e3adcf8fSFrançois Tigeot switch (ring->id) { 1002e3adcf8fSFrançois Tigeot case RCS: 1003e3adcf8fSFrançois Tigeot mmio = RENDER_HWS_PGA_GEN7; 1004e3adcf8fSFrançois Tigeot break; 1005e3adcf8fSFrançois Tigeot case BCS: 1006e3adcf8fSFrançois Tigeot mmio = BLT_HWS_PGA_GEN7; 1007e3adcf8fSFrançois Tigeot break; 1008*ba55f2f5SFrançois Tigeot /* 1009*ba55f2f5SFrançois Tigeot * VCS2 actually doesn't exist on Gen7. Only shut up 1010*ba55f2f5SFrançois Tigeot * gcc switch check warning 1011*ba55f2f5SFrançois Tigeot */ 1012*ba55f2f5SFrançois Tigeot case VCS2: 1013e3adcf8fSFrançois Tigeot case VCS: 1014e3adcf8fSFrançois Tigeot mmio = BSD_HWS_PGA_GEN7; 1015e3adcf8fSFrançois Tigeot break; 10165d0b1887SFrançois Tigeot case VECS: 10175d0b1887SFrançois Tigeot mmio = VEBOX_HWS_PGA_GEN7; 10185d0b1887SFrançois Tigeot break; 1019e3adcf8fSFrançois Tigeot } 1020b5c29a34SFrançois Tigeot } else if (IS_GEN6(ring->dev)) { 1021e3adcf8fSFrançois Tigeot mmio = RING_HWS_PGA_GEN6(ring->mmio_base); 1022e3adcf8fSFrançois Tigeot } else { 10239edbd4a0SFrançois Tigeot /* XXX: gen8 returns to sanity */ 1024e3adcf8fSFrançois Tigeot mmio = RING_HWS_PGA(ring->mmio_base); 1025e3adcf8fSFrançois Tigeot } 1026e3adcf8fSFrançois Tigeot 1027e3adcf8fSFrançois Tigeot I915_WRITE(mmio, (u32)ring->status_page.gfx_addr); 1028e3adcf8fSFrançois Tigeot POSTING_READ(mmio); 10295d0b1887SFrançois Tigeot 1030*ba55f2f5SFrançois Tigeot /* 1031*ba55f2f5SFrançois Tigeot * Flush the TLB for this page 1032*ba55f2f5SFrançois Tigeot * 1033*ba55f2f5SFrançois Tigeot * FIXME: These two bits have disappeared on gen8, so a question 1034*ba55f2f5SFrançois Tigeot * arises: do we still need this and if so how should we go about 1035*ba55f2f5SFrançois Tigeot * invalidating the TLB? 1036*ba55f2f5SFrançois Tigeot */ 1037*ba55f2f5SFrançois Tigeot if (INTEL_INFO(dev)->gen >= 6 && INTEL_INFO(dev)->gen < 8) { 10385d0b1887SFrançois Tigeot u32 reg = RING_INSTPM(ring->mmio_base); 1039*ba55f2f5SFrançois Tigeot 1040*ba55f2f5SFrançois Tigeot /* ring should be idle before issuing a sync flush*/ 1041*ba55f2f5SFrançois Tigeot WARN_ON((I915_READ_MODE(ring) & MODE_IDLE) == 0); 1042*ba55f2f5SFrançois Tigeot 10435d0b1887SFrançois Tigeot I915_WRITE(reg, 10445d0b1887SFrançois Tigeot _MASKED_BIT_ENABLE(INSTPM_TLB_INVALIDATE | 10455d0b1887SFrançois Tigeot INSTPM_SYNC_FLUSH)); 10465d0b1887SFrançois Tigeot if (wait_for((I915_READ(reg) & INSTPM_SYNC_FLUSH) == 0, 10475d0b1887SFrançois Tigeot 1000)) 10485d0b1887SFrançois Tigeot DRM_ERROR("%s: wait for SyncFlush to complete for TLB invalidation timed out\n", 10495d0b1887SFrançois Tigeot ring->name); 10505d0b1887SFrançois Tigeot } 1051e3adcf8fSFrançois Tigeot } 1052e3adcf8fSFrançois Tigeot 1053e3adcf8fSFrançois Tigeot static int 1054*ba55f2f5SFrançois Tigeot bsd_ring_flush(struct intel_engine_cs *ring, 1055b5c29a34SFrançois Tigeot u32 invalidate_domains, 1056b5c29a34SFrançois Tigeot u32 flush_domains) 1057e3adcf8fSFrançois Tigeot { 1058e3adcf8fSFrançois Tigeot int ret; 1059e3adcf8fSFrançois Tigeot 1060e3adcf8fSFrançois Tigeot ret = intel_ring_begin(ring, 2); 1061e3adcf8fSFrançois Tigeot if (ret) 1062e3adcf8fSFrançois Tigeot return ret; 1063e3adcf8fSFrançois Tigeot 1064e3adcf8fSFrançois Tigeot intel_ring_emit(ring, MI_FLUSH); 1065e3adcf8fSFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 1066e3adcf8fSFrançois Tigeot intel_ring_advance(ring); 1067e3adcf8fSFrançois Tigeot return 0; 1068e3adcf8fSFrançois Tigeot } 1069e3adcf8fSFrançois Tigeot 1070e3adcf8fSFrançois Tigeot static int 1071*ba55f2f5SFrançois Tigeot i9xx_add_request(struct intel_engine_cs *ring) 1072e3adcf8fSFrançois Tigeot { 1073e3adcf8fSFrançois Tigeot int ret; 1074e3adcf8fSFrançois Tigeot 1075e3adcf8fSFrançois Tigeot ret = intel_ring_begin(ring, 4); 1076e3adcf8fSFrançois Tigeot if (ret) 1077e3adcf8fSFrançois Tigeot return ret; 1078e3adcf8fSFrançois Tigeot 1079e3adcf8fSFrançois Tigeot intel_ring_emit(ring, MI_STORE_DWORD_INDEX); 1080e3adcf8fSFrançois Tigeot intel_ring_emit(ring, I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT); 10819edbd4a0SFrançois Tigeot intel_ring_emit(ring, ring->outstanding_lazy_seqno); 1082e3adcf8fSFrançois Tigeot intel_ring_emit(ring, MI_USER_INTERRUPT); 10839edbd4a0SFrançois Tigeot __intel_ring_advance(ring); 1084e3adcf8fSFrançois Tigeot 1085e3adcf8fSFrançois Tigeot return 0; 1086e3adcf8fSFrançois Tigeot } 1087e3adcf8fSFrançois Tigeot 1088e3adcf8fSFrançois Tigeot static bool 1089*ba55f2f5SFrançois Tigeot gen6_ring_get_irq(struct intel_engine_cs *ring) 1090e3adcf8fSFrançois Tigeot { 1091e3adcf8fSFrançois Tigeot struct drm_device *dev = ring->dev; 1092*ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 1093e3adcf8fSFrançois Tigeot 1094e3adcf8fSFrançois Tigeot if (!dev->irq_enabled) 1095e3adcf8fSFrançois Tigeot return false; 1096e3adcf8fSFrançois Tigeot 109702727ecdSFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_EXCLUSIVE); 10989edbd4a0SFrançois Tigeot if (ring->irq_refcount++ == 0) { 10999edbd4a0SFrançois Tigeot if (HAS_L3_DPF(dev) && ring->id == RCS) 11005d0b1887SFrançois Tigeot I915_WRITE_IMR(ring, 11015d0b1887SFrançois Tigeot ~(ring->irq_enable_mask | 11029edbd4a0SFrançois Tigeot GT_PARITY_ERROR(dev))); 1103686a02f1SFrançois Tigeot else 1104686a02f1SFrançois Tigeot I915_WRITE_IMR(ring, ~ring->irq_enable_mask); 11059edbd4a0SFrançois Tigeot ilk_enable_gt_irq(dev_priv, ring->irq_enable_mask); 1106e3adcf8fSFrançois Tigeot } 110702727ecdSFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_RELEASE); 1108e3adcf8fSFrançois Tigeot 1109e3adcf8fSFrançois Tigeot return true; 1110e3adcf8fSFrançois Tigeot } 1111e3adcf8fSFrançois Tigeot 1112e3adcf8fSFrançois Tigeot static void 1113*ba55f2f5SFrançois Tigeot gen6_ring_put_irq(struct intel_engine_cs *ring) 1114e3adcf8fSFrançois Tigeot { 1115e3adcf8fSFrançois Tigeot struct drm_device *dev = ring->dev; 1116*ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 1117e3adcf8fSFrançois Tigeot 111802727ecdSFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_EXCLUSIVE); 11199edbd4a0SFrançois Tigeot if (--ring->irq_refcount == 0) { 11209edbd4a0SFrançois Tigeot if (HAS_L3_DPF(dev) && ring->id == RCS) 11219edbd4a0SFrançois Tigeot I915_WRITE_IMR(ring, ~GT_PARITY_ERROR(dev)); 1122686a02f1SFrançois Tigeot else 1123686a02f1SFrançois Tigeot I915_WRITE_IMR(ring, ~0); 11249edbd4a0SFrançois Tigeot ilk_disable_gt_irq(dev_priv, ring->irq_enable_mask); 1125e3adcf8fSFrançois Tigeot } 112602727ecdSFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_RELEASE); 1127e3adcf8fSFrançois Tigeot } 1128e3adcf8fSFrançois Tigeot 11295d0b1887SFrançois Tigeot static bool 1130*ba55f2f5SFrançois Tigeot hsw_vebox_get_irq(struct intel_engine_cs *ring) 11315d0b1887SFrançois Tigeot { 11325d0b1887SFrançois Tigeot struct drm_device *dev = ring->dev; 11335d0b1887SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 11345d0b1887SFrançois Tigeot 11355d0b1887SFrançois Tigeot if (!dev->irq_enabled) 11365d0b1887SFrançois Tigeot return false; 11375d0b1887SFrançois Tigeot 11389edbd4a0SFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_EXCLUSIVE); 11399edbd4a0SFrançois Tigeot if (ring->irq_refcount++ == 0) { 11405d0b1887SFrançois Tigeot I915_WRITE_IMR(ring, ~ring->irq_enable_mask); 11419edbd4a0SFrançois Tigeot snb_enable_pm_irq(dev_priv, ring->irq_enable_mask); 11425d0b1887SFrançois Tigeot } 11439edbd4a0SFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_RELEASE); 11445d0b1887SFrançois Tigeot 11455d0b1887SFrançois Tigeot return true; 11465d0b1887SFrançois Tigeot } 11475d0b1887SFrançois Tigeot 11485d0b1887SFrançois Tigeot static void 1149*ba55f2f5SFrançois Tigeot hsw_vebox_put_irq(struct intel_engine_cs *ring) 11505d0b1887SFrançois Tigeot { 11515d0b1887SFrançois Tigeot struct drm_device *dev = ring->dev; 11525d0b1887SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 11535d0b1887SFrançois Tigeot 11545d0b1887SFrançois Tigeot if (!dev->irq_enabled) 11555d0b1887SFrançois Tigeot return; 11565d0b1887SFrançois Tigeot 11579edbd4a0SFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_EXCLUSIVE); 11589edbd4a0SFrançois Tigeot if (--ring->irq_refcount == 0) { 11595d0b1887SFrançois Tigeot I915_WRITE_IMR(ring, ~0); 11609edbd4a0SFrançois Tigeot snb_disable_pm_irq(dev_priv, ring->irq_enable_mask); 11615d0b1887SFrançois Tigeot } 11629edbd4a0SFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_RELEASE); 11639edbd4a0SFrançois Tigeot } 11649edbd4a0SFrançois Tigeot 11659edbd4a0SFrançois Tigeot static bool 1166*ba55f2f5SFrançois Tigeot gen8_ring_get_irq(struct intel_engine_cs *ring) 11679edbd4a0SFrançois Tigeot { 11689edbd4a0SFrançois Tigeot struct drm_device *dev = ring->dev; 11699edbd4a0SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 11709edbd4a0SFrançois Tigeot 11719edbd4a0SFrançois Tigeot if (!dev->irq_enabled) 11729edbd4a0SFrançois Tigeot return false; 11739edbd4a0SFrançois Tigeot 11749edbd4a0SFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_EXCLUSIVE); 11759edbd4a0SFrançois Tigeot if (ring->irq_refcount++ == 0) { 11769edbd4a0SFrançois Tigeot if (HAS_L3_DPF(dev) && ring->id == RCS) { 11779edbd4a0SFrançois Tigeot I915_WRITE_IMR(ring, 11789edbd4a0SFrançois Tigeot ~(ring->irq_enable_mask | 11799edbd4a0SFrançois Tigeot GT_RENDER_L3_PARITY_ERROR_INTERRUPT)); 11809edbd4a0SFrançois Tigeot } else { 11819edbd4a0SFrançois Tigeot I915_WRITE_IMR(ring, ~ring->irq_enable_mask); 11829edbd4a0SFrançois Tigeot } 11839edbd4a0SFrançois Tigeot POSTING_READ(RING_IMR(ring->mmio_base)); 11849edbd4a0SFrançois Tigeot } 11859edbd4a0SFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_RELEASE); 11869edbd4a0SFrançois Tigeot 11879edbd4a0SFrançois Tigeot return true; 11889edbd4a0SFrançois Tigeot } 11899edbd4a0SFrançois Tigeot 11909edbd4a0SFrançois Tigeot static void 1191*ba55f2f5SFrançois Tigeot gen8_ring_put_irq(struct intel_engine_cs *ring) 11929edbd4a0SFrançois Tigeot { 11939edbd4a0SFrançois Tigeot struct drm_device *dev = ring->dev; 11949edbd4a0SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 11959edbd4a0SFrançois Tigeot 11969edbd4a0SFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_EXCLUSIVE); 11979edbd4a0SFrançois Tigeot if (--ring->irq_refcount == 0) { 11989edbd4a0SFrançois Tigeot if (HAS_L3_DPF(dev) && ring->id == RCS) { 11999edbd4a0SFrançois Tigeot I915_WRITE_IMR(ring, 12009edbd4a0SFrançois Tigeot ~GT_RENDER_L3_PARITY_ERROR_INTERRUPT); 12019edbd4a0SFrançois Tigeot } else { 12029edbd4a0SFrançois Tigeot I915_WRITE_IMR(ring, ~0); 12039edbd4a0SFrançois Tigeot } 12049edbd4a0SFrançois Tigeot POSTING_READ(RING_IMR(ring->mmio_base)); 12059edbd4a0SFrançois Tigeot } 12069edbd4a0SFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_RELEASE); 12075d0b1887SFrançois Tigeot } 12085d0b1887SFrançois Tigeot 1209e3adcf8fSFrançois Tigeot static int 1210*ba55f2f5SFrançois Tigeot i965_dispatch_execbuffer(struct intel_engine_cs *ring, 1211*ba55f2f5SFrançois Tigeot u64 offset, u32 length, 1212b5c29a34SFrançois Tigeot unsigned flags) 1213e3adcf8fSFrançois Tigeot { 1214e3adcf8fSFrançois Tigeot int ret; 1215e3adcf8fSFrançois Tigeot 1216e3adcf8fSFrançois Tigeot ret = intel_ring_begin(ring, 2); 1217e3adcf8fSFrançois Tigeot if (ret) 1218e3adcf8fSFrançois Tigeot return ret; 1219e3adcf8fSFrançois Tigeot 1220e3adcf8fSFrançois Tigeot intel_ring_emit(ring, 1221686a02f1SFrançois Tigeot MI_BATCH_BUFFER_START | 1222b5c29a34SFrançois Tigeot MI_BATCH_GTT | 1223b5c29a34SFrançois Tigeot (flags & I915_DISPATCH_SECURE ? 0 : MI_BATCH_NON_SECURE_I965)); 1224e3adcf8fSFrançois Tigeot intel_ring_emit(ring, offset); 1225e3adcf8fSFrançois Tigeot intel_ring_advance(ring); 1226e3adcf8fSFrançois Tigeot 1227e3adcf8fSFrançois Tigeot return 0; 1228e3adcf8fSFrançois Tigeot } 1229e3adcf8fSFrançois Tigeot 1230b5c29a34SFrançois Tigeot /* Just userspace ABI convention to limit the wa batch bo to a resonable size */ 1231b5c29a34SFrançois Tigeot #define I830_BATCH_LIMIT (256*1024) 1232e3adcf8fSFrançois Tigeot static int 1233*ba55f2f5SFrançois Tigeot i830_dispatch_execbuffer(struct intel_engine_cs *ring, 1234*ba55f2f5SFrançois Tigeot u64 offset, u32 len, 1235b5c29a34SFrançois Tigeot unsigned flags) 1236e3adcf8fSFrançois Tigeot { 1237e3adcf8fSFrançois Tigeot int ret; 1238e3adcf8fSFrançois Tigeot 1239b5c29a34SFrançois Tigeot if (flags & I915_DISPATCH_PINNED) { 1240e3adcf8fSFrançois Tigeot ret = intel_ring_begin(ring, 4); 1241e3adcf8fSFrançois Tigeot if (ret) 1242e3adcf8fSFrançois Tigeot return ret; 1243e3adcf8fSFrançois Tigeot 1244e3adcf8fSFrançois Tigeot intel_ring_emit(ring, MI_BATCH_BUFFER); 1245b5c29a34SFrançois Tigeot intel_ring_emit(ring, offset | (flags & I915_DISPATCH_SECURE ? 0 : MI_BATCH_NON_SECURE)); 1246e3adcf8fSFrançois Tigeot intel_ring_emit(ring, offset + len - 8); 1247b5c29a34SFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 1248686a02f1SFrançois Tigeot intel_ring_advance(ring); 1249b5c29a34SFrançois Tigeot } else { 12509edbd4a0SFrançois Tigeot u32 cs_offset = ring->scratch.gtt_offset; 1251b5c29a34SFrançois Tigeot 1252b5c29a34SFrançois Tigeot if (len > I830_BATCH_LIMIT) 1253b5c29a34SFrançois Tigeot return -ENOSPC; 1254b5c29a34SFrançois Tigeot 1255b5c29a34SFrançois Tigeot ret = intel_ring_begin(ring, 9+3); 1256b5c29a34SFrançois Tigeot if (ret) 1257b5c29a34SFrançois Tigeot return ret; 1258b5c29a34SFrançois Tigeot /* Blit the batch (which has now all relocs applied) to the stable batch 1259b5c29a34SFrançois Tigeot * scratch bo area (so that the CS never stumbles over its tlb 1260b5c29a34SFrançois Tigeot * invalidation bug) ... */ 1261b5c29a34SFrançois Tigeot intel_ring_emit(ring, XY_SRC_COPY_BLT_CMD | 1262b5c29a34SFrançois Tigeot XY_SRC_COPY_BLT_WRITE_ALPHA | 1263b5c29a34SFrançois Tigeot XY_SRC_COPY_BLT_WRITE_RGB); 1264b5c29a34SFrançois Tigeot intel_ring_emit(ring, BLT_DEPTH_32 | BLT_ROP_GXCOPY | 4096); 1265b5c29a34SFrançois Tigeot intel_ring_emit(ring, 0); 1266b5c29a34SFrançois Tigeot intel_ring_emit(ring, (DIV_ROUND_UP(len, 4096) << 16) | 1024); 1267b5c29a34SFrançois Tigeot intel_ring_emit(ring, cs_offset); 1268b5c29a34SFrançois Tigeot intel_ring_emit(ring, 0); 1269b5c29a34SFrançois Tigeot intel_ring_emit(ring, 4096); 1270b5c29a34SFrançois Tigeot intel_ring_emit(ring, offset); 1271b5c29a34SFrançois Tigeot intel_ring_emit(ring, MI_FLUSH); 1272b5c29a34SFrançois Tigeot 1273b5c29a34SFrançois Tigeot /* ... and execute it. */ 1274b5c29a34SFrançois Tigeot intel_ring_emit(ring, MI_BATCH_BUFFER); 1275b5c29a34SFrançois Tigeot intel_ring_emit(ring, cs_offset | (flags & I915_DISPATCH_SECURE ? 0 : MI_BATCH_NON_SECURE)); 1276b5c29a34SFrançois Tigeot intel_ring_emit(ring, cs_offset + len - 8); 1277b5c29a34SFrançois Tigeot intel_ring_advance(ring); 1278b5c29a34SFrançois Tigeot } 1279686a02f1SFrançois Tigeot 1280686a02f1SFrançois Tigeot return 0; 1281686a02f1SFrançois Tigeot } 1282686a02f1SFrançois Tigeot 1283686a02f1SFrançois Tigeot static int 1284*ba55f2f5SFrançois Tigeot i915_dispatch_execbuffer(struct intel_engine_cs *ring, 1285*ba55f2f5SFrançois Tigeot u64 offset, u32 len, 1286b5c29a34SFrançois Tigeot unsigned flags) 1287686a02f1SFrançois Tigeot { 1288686a02f1SFrançois Tigeot int ret; 1289686a02f1SFrançois Tigeot 1290e3adcf8fSFrançois Tigeot ret = intel_ring_begin(ring, 2); 1291e3adcf8fSFrançois Tigeot if (ret) 1292e3adcf8fSFrançois Tigeot return ret; 1293e3adcf8fSFrançois Tigeot 1294686a02f1SFrançois Tigeot intel_ring_emit(ring, MI_BATCH_BUFFER_START | MI_BATCH_GTT); 1295686a02f1SFrançois Tigeot intel_ring_emit(ring, offset | (flags & I915_DISPATCH_SECURE ? 0 : MI_BATCH_NON_SECURE)); 1296e3adcf8fSFrançois Tigeot intel_ring_advance(ring); 1297e3adcf8fSFrançois Tigeot 1298e3adcf8fSFrançois Tigeot return 0; 1299e3adcf8fSFrançois Tigeot } 1300e3adcf8fSFrançois Tigeot 1301*ba55f2f5SFrançois Tigeot static void cleanup_status_page(struct intel_engine_cs *ring) 1302e3adcf8fSFrançois Tigeot { 1303e3adcf8fSFrançois Tigeot struct drm_i915_gem_object *obj; 1304e3adcf8fSFrançois Tigeot 1305e3adcf8fSFrançois Tigeot obj = ring->status_page.obj; 1306e3adcf8fSFrançois Tigeot if (obj == NULL) 1307e3adcf8fSFrançois Tigeot return; 1308e3adcf8fSFrançois Tigeot 13099edbd4a0SFrançois Tigeot kunmap(obj->pages[0]); 1310*ba55f2f5SFrançois Tigeot i915_gem_object_ggtt_unpin(obj); 1311e3adcf8fSFrançois Tigeot drm_gem_object_unreference(&obj->base); 1312e3adcf8fSFrançois Tigeot ring->status_page.obj = NULL; 1313e3adcf8fSFrançois Tigeot } 1314e3adcf8fSFrançois Tigeot 1315*ba55f2f5SFrançois Tigeot static int init_status_page(struct intel_engine_cs *ring) 1316e3adcf8fSFrançois Tigeot { 1317e3adcf8fSFrançois Tigeot struct drm_i915_gem_object *obj; 1318*ba55f2f5SFrançois Tigeot 1319*ba55f2f5SFrançois Tigeot if ((obj = ring->status_page.obj) == NULL) { 1320e3adcf8fSFrançois Tigeot int ret; 1321e3adcf8fSFrançois Tigeot 1322*ba55f2f5SFrançois Tigeot obj = i915_gem_alloc_object(ring->dev, 4096); 1323e3adcf8fSFrançois Tigeot if (obj == NULL) { 1324e3adcf8fSFrançois Tigeot DRM_ERROR("Failed to allocate status page\n"); 1325*ba55f2f5SFrançois Tigeot return -ENOMEM; 1326e3adcf8fSFrançois Tigeot } 1327e3adcf8fSFrançois Tigeot 1328*ba55f2f5SFrançois Tigeot ret = i915_gem_object_set_cache_level(obj, I915_CACHE_LLC); 1329*ba55f2f5SFrançois Tigeot if (ret) 1330e3adcf8fSFrançois Tigeot goto err_unref; 1331*ba55f2f5SFrançois Tigeot 1332*ba55f2f5SFrançois Tigeot ret = i915_gem_obj_ggtt_pin(obj, 4096, 0); 1333*ba55f2f5SFrançois Tigeot if (ret) { 1334*ba55f2f5SFrançois Tigeot err_unref: 1335*ba55f2f5SFrançois Tigeot drm_gem_object_unreference(&obj->base); 1336*ba55f2f5SFrançois Tigeot return ret; 1337*ba55f2f5SFrançois Tigeot } 1338*ba55f2f5SFrançois Tigeot 1339*ba55f2f5SFrançois Tigeot ring->status_page.obj = obj; 1340e3adcf8fSFrançois Tigeot } 1341e3adcf8fSFrançois Tigeot 13429edbd4a0SFrançois Tigeot ring->status_page.gfx_addr = i915_gem_obj_ggtt_offset(obj); 1343f4f90b23SFrançois Tigeot ring->status_page.page_addr = kmap(obj->pages[0]); 1344e3adcf8fSFrançois Tigeot memset(ring->status_page.page_addr, 0, PAGE_SIZE); 1345e3adcf8fSFrançois Tigeot 1346b5c29a34SFrançois Tigeot DRM_DEBUG_DRIVER("%s hws offset: 0x%08x\n", 1347e3adcf8fSFrançois Tigeot ring->name, ring->status_page.gfx_addr); 1348e3adcf8fSFrançois Tigeot 1349e3adcf8fSFrançois Tigeot return 0; 1350e3adcf8fSFrançois Tigeot } 1351e3adcf8fSFrançois Tigeot 1352*ba55f2f5SFrançois Tigeot static int init_phys_status_page(struct intel_engine_cs *ring) 1353686a02f1SFrançois Tigeot { 1354686a02f1SFrançois Tigeot struct drm_i915_private *dev_priv = ring->dev->dev_private; 1355686a02f1SFrançois Tigeot 1356686a02f1SFrançois Tigeot if (!dev_priv->status_page_dmah) { 1357686a02f1SFrançois Tigeot dev_priv->status_page_dmah = 1358b31e9d59SFrançois Tigeot drm_pci_alloc(ring->dev, PAGE_SIZE, PAGE_SIZE); 1359686a02f1SFrançois Tigeot if (!dev_priv->status_page_dmah) 1360686a02f1SFrançois Tigeot return -ENOMEM; 1361686a02f1SFrançois Tigeot } 1362686a02f1SFrançois Tigeot 1363686a02f1SFrançois Tigeot ring->status_page.page_addr = dev_priv->status_page_dmah->vaddr; 1364686a02f1SFrançois Tigeot memset(ring->status_page.page_addr, 0, PAGE_SIZE); 1365686a02f1SFrançois Tigeot 1366686a02f1SFrançois Tigeot return 0; 1367686a02f1SFrançois Tigeot } 1368686a02f1SFrançois Tigeot 1369*ba55f2f5SFrançois Tigeot static int allocate_ring_buffer(struct intel_engine_cs *ring) 1370e3adcf8fSFrançois Tigeot { 1371*ba55f2f5SFrançois Tigeot struct drm_device *dev = ring->dev; 1372*ba55f2f5SFrançois Tigeot struct intel_ringbuffer *ringbuf = ring->buffer; 1373e3adcf8fSFrançois Tigeot struct drm_i915_gem_object *obj; 1374e3adcf8fSFrançois Tigeot int ret; 1375e3adcf8fSFrançois Tigeot 1376*ba55f2f5SFrançois Tigeot if (intel_ring_initialized(ring)) 1377*ba55f2f5SFrançois Tigeot return 0; 1378e3adcf8fSFrançois Tigeot 1379a2fdbec6SFrançois Tigeot obj = NULL; 1380a2fdbec6SFrançois Tigeot if (!HAS_LLC(dev)) 1381*ba55f2f5SFrançois Tigeot obj = i915_gem_object_create_stolen(dev, ringbuf->size); 1382a2fdbec6SFrançois Tigeot if (obj == NULL) 1383*ba55f2f5SFrançois Tigeot obj = i915_gem_alloc_object(dev, ringbuf->size); 1384*ba55f2f5SFrançois Tigeot if (obj == NULL) 1385*ba55f2f5SFrançois Tigeot return -ENOMEM; 1386e3adcf8fSFrançois Tigeot 1387*ba55f2f5SFrançois Tigeot ret = i915_gem_obj_ggtt_pin(obj, PAGE_SIZE, PIN_MAPPABLE); 1388e3adcf8fSFrançois Tigeot if (ret) 1389e3adcf8fSFrançois Tigeot goto err_unref; 1390e3adcf8fSFrançois Tigeot 1391686a02f1SFrançois Tigeot ret = i915_gem_object_set_to_gtt_domain(obj, true); 1392686a02f1SFrançois Tigeot if (ret) 1393686a02f1SFrançois Tigeot goto err_unpin; 1394e3adcf8fSFrançois Tigeot 1395*ba55f2f5SFrançois Tigeot ringbuf->virtual_start = 13969edbd4a0SFrançois Tigeot ioremap_wc(dev->agp->base + i915_gem_obj_ggtt_offset(obj), 1397*ba55f2f5SFrançois Tigeot ringbuf->size); 1398*ba55f2f5SFrançois Tigeot if (ringbuf->virtual_start == NULL) { 1399e3adcf8fSFrançois Tigeot ret = -EINVAL; 1400e3adcf8fSFrançois Tigeot goto err_unpin; 1401e3adcf8fSFrançois Tigeot } 1402e3adcf8fSFrançois Tigeot 1403*ba55f2f5SFrançois Tigeot ringbuf->obj = obj; 1404*ba55f2f5SFrançois Tigeot return 0; 1405*ba55f2f5SFrançois Tigeot 1406*ba55f2f5SFrançois Tigeot err_unpin: 1407*ba55f2f5SFrançois Tigeot i915_gem_object_ggtt_unpin(obj); 1408*ba55f2f5SFrançois Tigeot err_unref: 1409*ba55f2f5SFrançois Tigeot drm_gem_object_unreference(&obj->base); 1410*ba55f2f5SFrançois Tigeot return ret; 1411*ba55f2f5SFrançois Tigeot } 1412*ba55f2f5SFrançois Tigeot 1413*ba55f2f5SFrançois Tigeot static int intel_init_ring_buffer(struct drm_device *dev, 1414*ba55f2f5SFrançois Tigeot struct intel_engine_cs *ring) 1415*ba55f2f5SFrançois Tigeot { 1416*ba55f2f5SFrançois Tigeot struct intel_ringbuffer *ringbuf = ring->buffer; 1417*ba55f2f5SFrançois Tigeot int ret; 1418*ba55f2f5SFrançois Tigeot 1419*ba55f2f5SFrançois Tigeot if (ringbuf == NULL) { 1420*ba55f2f5SFrançois Tigeot ringbuf = kzalloc(sizeof(*ringbuf), GFP_KERNEL); 1421*ba55f2f5SFrançois Tigeot if (!ringbuf) 1422*ba55f2f5SFrançois Tigeot return -ENOMEM; 1423*ba55f2f5SFrançois Tigeot ring->buffer = ringbuf; 1424*ba55f2f5SFrançois Tigeot } 1425*ba55f2f5SFrançois Tigeot 1426*ba55f2f5SFrançois Tigeot ring->dev = dev; 1427*ba55f2f5SFrançois Tigeot INIT_LIST_HEAD(&ring->active_list); 1428*ba55f2f5SFrançois Tigeot INIT_LIST_HEAD(&ring->request_list); 1429*ba55f2f5SFrançois Tigeot ringbuf->size = 32 * PAGE_SIZE; 1430*ba55f2f5SFrançois Tigeot memset(ring->semaphore.sync_seqno, 0, sizeof(ring->semaphore.sync_seqno)); 1431*ba55f2f5SFrançois Tigeot 1432*ba55f2f5SFrançois Tigeot init_waitqueue_head(&ring->irq_queue); 1433*ba55f2f5SFrançois Tigeot 1434*ba55f2f5SFrançois Tigeot if (I915_NEED_GFX_HWS(dev)) { 1435*ba55f2f5SFrançois Tigeot ret = init_status_page(ring); 1436e3adcf8fSFrançois Tigeot if (ret) 1437*ba55f2f5SFrançois Tigeot goto error; 1438*ba55f2f5SFrançois Tigeot } else { 1439*ba55f2f5SFrançois Tigeot BUG_ON(ring->id != RCS); 1440*ba55f2f5SFrançois Tigeot ret = init_phys_status_page(ring); 1441*ba55f2f5SFrançois Tigeot if (ret) 1442*ba55f2f5SFrançois Tigeot goto error; 1443*ba55f2f5SFrançois Tigeot } 1444*ba55f2f5SFrançois Tigeot 1445*ba55f2f5SFrançois Tigeot ret = allocate_ring_buffer(ring); 1446*ba55f2f5SFrançois Tigeot if (ret) { 1447*ba55f2f5SFrançois Tigeot DRM_ERROR("Failed to allocate ringbuffer %s: %d\n", ring->name, ret); 1448*ba55f2f5SFrançois Tigeot goto error; 1449*ba55f2f5SFrançois Tigeot } 1450e3adcf8fSFrançois Tigeot 1451e3adcf8fSFrançois Tigeot /* Workaround an erratum on the i830 which causes a hang if 1452e3adcf8fSFrançois Tigeot * the TAIL pointer points to within the last 2 cachelines 1453e3adcf8fSFrançois Tigeot * of the buffer. 1454e3adcf8fSFrançois Tigeot */ 1455*ba55f2f5SFrançois Tigeot ringbuf->effective_size = ringbuf->size; 1456*ba55f2f5SFrançois Tigeot if (IS_I830(dev) || IS_845G(dev)) 1457*ba55f2f5SFrançois Tigeot ringbuf->effective_size -= 2 * CACHELINE_BYTES; 1458*ba55f2f5SFrançois Tigeot 1459*ba55f2f5SFrançois Tigeot ret = i915_cmd_parser_init_ring(ring); 1460*ba55f2f5SFrançois Tigeot if (ret) 1461*ba55f2f5SFrançois Tigeot goto error; 1462*ba55f2f5SFrançois Tigeot 1463*ba55f2f5SFrançois Tigeot ret = ring->init(ring); 1464*ba55f2f5SFrançois Tigeot if (ret) 1465*ba55f2f5SFrançois Tigeot goto error; 1466e3adcf8fSFrançois Tigeot 1467e3adcf8fSFrançois Tigeot return 0; 1468e3adcf8fSFrançois Tigeot 1469*ba55f2f5SFrançois Tigeot error: 1470*ba55f2f5SFrançois Tigeot kfree(ringbuf); 1471*ba55f2f5SFrançois Tigeot ring->buffer = NULL; 1472e3adcf8fSFrançois Tigeot return ret; 1473e3adcf8fSFrançois Tigeot } 1474e3adcf8fSFrançois Tigeot 1475*ba55f2f5SFrançois Tigeot void intel_cleanup_ring_buffer(struct intel_engine_cs *ring) 1476e3adcf8fSFrançois Tigeot { 1477*ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = to_i915(ring->dev); 1478*ba55f2f5SFrançois Tigeot struct intel_ringbuffer *ringbuf = ring->buffer; 1479e3adcf8fSFrançois Tigeot 1480*ba55f2f5SFrançois Tigeot if (!intel_ring_initialized(ring)) 1481e3adcf8fSFrançois Tigeot return; 1482e3adcf8fSFrançois Tigeot 1483*ba55f2f5SFrançois Tigeot intel_stop_ring_buffer(ring); 1484*ba55f2f5SFrançois Tigeot WARN_ON(!IS_GEN2(ring->dev) && (I915_READ_MODE(ring) & MODE_IDLE) == 0); 1485b030f26bSFrançois Tigeot 1486*ba55f2f5SFrançois Tigeot pmap_unmapdev((vm_offset_t)ringbuf->virtual_start, ringbuf->size); 1487e3adcf8fSFrançois Tigeot 1488*ba55f2f5SFrançois Tigeot i915_gem_object_ggtt_unpin(ringbuf->obj); 1489*ba55f2f5SFrançois Tigeot drm_gem_object_unreference(&ringbuf->obj->base); 1490*ba55f2f5SFrançois Tigeot ringbuf->obj = NULL; 14919edbd4a0SFrançois Tigeot ring->preallocated_lazy_request = NULL; 14929edbd4a0SFrançois Tigeot ring->outstanding_lazy_seqno = 0; 1493e3adcf8fSFrançois Tigeot 1494e3adcf8fSFrançois Tigeot if (ring->cleanup) 1495e3adcf8fSFrançois Tigeot ring->cleanup(ring); 1496e3adcf8fSFrançois Tigeot 1497e3adcf8fSFrançois Tigeot cleanup_status_page(ring); 1498*ba55f2f5SFrançois Tigeot 1499*ba55f2f5SFrançois Tigeot i915_cmd_parser_fini_ring(ring); 1500*ba55f2f5SFrançois Tigeot 1501*ba55f2f5SFrançois Tigeot kfree(ringbuf); 1502*ba55f2f5SFrançois Tigeot ring->buffer = NULL; 1503e3adcf8fSFrançois Tigeot } 1504e3adcf8fSFrançois Tigeot 1505*ba55f2f5SFrançois Tigeot static int intel_ring_wait_request(struct intel_engine_cs *ring, int n) 1506e3adcf8fSFrançois Tigeot { 1507*ba55f2f5SFrançois Tigeot struct intel_ringbuffer *ringbuf = ring->buffer; 1508e3adcf8fSFrançois Tigeot struct drm_i915_gem_request *request; 1509e3adcf8fSFrançois Tigeot u32 seqno = 0; 1510e3adcf8fSFrançois Tigeot int ret; 1511e3adcf8fSFrançois Tigeot 1512*ba55f2f5SFrançois Tigeot if (ringbuf->last_retired_head != -1) { 1513*ba55f2f5SFrançois Tigeot ringbuf->head = ringbuf->last_retired_head; 1514*ba55f2f5SFrançois Tigeot ringbuf->last_retired_head = -1; 1515e3adcf8fSFrançois Tigeot 1516*ba55f2f5SFrançois Tigeot ringbuf->space = ring_space(ring); 1517*ba55f2f5SFrançois Tigeot if (ringbuf->space >= n) 1518e3adcf8fSFrançois Tigeot return 0; 1519e3adcf8fSFrançois Tigeot } 1520e3adcf8fSFrançois Tigeot 1521e3adcf8fSFrançois Tigeot list_for_each_entry(request, &ring->request_list, list) { 1522*ba55f2f5SFrançois Tigeot if (__ring_space(request->tail, ringbuf->tail, ringbuf->size) >= n) { 1523e3adcf8fSFrançois Tigeot seqno = request->seqno; 1524e3adcf8fSFrançois Tigeot break; 1525e3adcf8fSFrançois Tigeot } 1526e3adcf8fSFrançois Tigeot } 1527e3adcf8fSFrançois Tigeot 1528e3adcf8fSFrançois Tigeot if (seqno == 0) 1529e3adcf8fSFrançois Tigeot return -ENOSPC; 1530e3adcf8fSFrançois Tigeot 1531*ba55f2f5SFrançois Tigeot ret = i915_wait_seqno(ring, seqno); 1532e3adcf8fSFrançois Tigeot if (ret) 1533e3adcf8fSFrançois Tigeot return ret; 1534e3adcf8fSFrançois Tigeot 1535*ba55f2f5SFrançois Tigeot i915_gem_retire_requests_ring(ring); 1536*ba55f2f5SFrançois Tigeot ringbuf->head = ringbuf->last_retired_head; 1537*ba55f2f5SFrançois Tigeot ringbuf->last_retired_head = -1; 1538e3adcf8fSFrançois Tigeot 1539*ba55f2f5SFrançois Tigeot ringbuf->space = ring_space(ring); 1540e3adcf8fSFrançois Tigeot return 0; 1541e3adcf8fSFrançois Tigeot } 1542e3adcf8fSFrançois Tigeot 1543*ba55f2f5SFrançois Tigeot static int ring_wait_for_space(struct intel_engine_cs *ring, int n) 1544e3adcf8fSFrançois Tigeot { 1545e3adcf8fSFrançois Tigeot struct drm_device *dev = ring->dev; 1546e3adcf8fSFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 1547*ba55f2f5SFrançois Tigeot struct intel_ringbuffer *ringbuf = ring->buffer; 1548245593daSFrançois Tigeot unsigned long end; 1549e3adcf8fSFrançois Tigeot int ret; 1550e3adcf8fSFrançois Tigeot 1551e3adcf8fSFrançois Tigeot ret = intel_ring_wait_request(ring, n); 1552e3adcf8fSFrançois Tigeot if (ret != -ENOSPC) 1553e3adcf8fSFrançois Tigeot return ret; 1554e3adcf8fSFrançois Tigeot 15559edbd4a0SFrançois Tigeot /* force the tail write in case we have been skipping them */ 15569edbd4a0SFrançois Tigeot __intel_ring_advance(ring); 15579edbd4a0SFrançois Tigeot 1558e3adcf8fSFrançois Tigeot /* With GEM the hangcheck timer should kick us out of the loop, 1559e3adcf8fSFrançois Tigeot * leaving it early runs the risk of corrupting GEM state (due 1560e3adcf8fSFrançois Tigeot * to running on almost untested codepaths). But on resume 1561e3adcf8fSFrançois Tigeot * timers don't work yet, so prevent a complete hang in that 1562e3adcf8fSFrançois Tigeot * case by choosing an insanely large timeout. */ 1563e3440f96SFrançois Tigeot end = jiffies + 60 * HZ; 1564245593daSFrançois Tigeot 1565*ba55f2f5SFrançois Tigeot trace_i915_ring_wait_begin(ring); 1566e3adcf8fSFrançois Tigeot do { 1567*ba55f2f5SFrançois Tigeot ringbuf->head = I915_READ_HEAD(ring); 1568*ba55f2f5SFrançois Tigeot ringbuf->space = ring_space(ring); 1569*ba55f2f5SFrançois Tigeot if (ringbuf->space >= n) { 1570*ba55f2f5SFrançois Tigeot ret = 0; 1571*ba55f2f5SFrançois Tigeot break; 1572e3adcf8fSFrançois Tigeot } 1573e3adcf8fSFrançois Tigeot 1574e3adcf8fSFrançois Tigeot #if 0 1575*ba55f2f5SFrançois Tigeot if (!drm_core_check_feature(dev, DRIVER_MODESET) && 1576*ba55f2f5SFrançois Tigeot dev->primary->master) { 1577e3adcf8fSFrançois Tigeot struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv; 1578e3adcf8fSFrançois Tigeot if (master_priv->sarea_priv) 1579e3adcf8fSFrançois Tigeot master_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT; 1580e3adcf8fSFrançois Tigeot } 1581e3adcf8fSFrançois Tigeot #else 1582e3adcf8fSFrançois Tigeot if (dev_priv->sarea_priv) 1583e3adcf8fSFrançois Tigeot dev_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT; 1584e3adcf8fSFrançois Tigeot #endif 1585e3adcf8fSFrançois Tigeot 1586*ba55f2f5SFrançois Tigeot 1587e3440f96SFrançois Tigeot msleep(1); 1588245593daSFrançois Tigeot 1589*ba55f2f5SFrançois Tigeot #if 0 1590*ba55f2f5SFrançois Tigeot if (dev_priv->mm.interruptible && signal_pending(current)) { 1591*ba55f2f5SFrançois Tigeot ret = -ERESTARTSYS; 1592*ba55f2f5SFrançois Tigeot break; 1593*ba55f2f5SFrançois Tigeot } 1594*ba55f2f5SFrançois Tigeot #endif 1595*ba55f2f5SFrançois Tigeot 1596a2fdbec6SFrançois Tigeot ret = i915_gem_check_wedge(&dev_priv->gpu_error, 1597a2fdbec6SFrançois Tigeot dev_priv->mm.interruptible); 1598245593daSFrançois Tigeot if (ret) 1599*ba55f2f5SFrançois Tigeot break; 1600*ba55f2f5SFrançois Tigeot 1601*ba55f2f5SFrançois Tigeot if (time_after(jiffies, end)) { 1602*ba55f2f5SFrançois Tigeot ret = -EBUSY; 1603*ba55f2f5SFrançois Tigeot break; 1604*ba55f2f5SFrançois Tigeot } 1605*ba55f2f5SFrançois Tigeot } while (1); 1606a2fdbec6SFrançois Tigeot trace_i915_ring_wait_end(ring); 1607*ba55f2f5SFrançois Tigeot return ret; 1608e3adcf8fSFrançois Tigeot } 1609e3adcf8fSFrançois Tigeot 1610*ba55f2f5SFrançois Tigeot static int intel_wrap_ring_buffer(struct intel_engine_cs *ring) 1611b030f26bSFrançois Tigeot { 1612b030f26bSFrançois Tigeot uint32_t __iomem *virt; 1613*ba55f2f5SFrançois Tigeot struct intel_ringbuffer *ringbuf = ring->buffer; 1614*ba55f2f5SFrançois Tigeot int rem = ringbuf->size - ringbuf->tail; 1615b030f26bSFrançois Tigeot 1616*ba55f2f5SFrançois Tigeot if (ringbuf->space < rem) { 1617b030f26bSFrançois Tigeot int ret = ring_wait_for_space(ring, rem); 1618b030f26bSFrançois Tigeot if (ret) 1619b030f26bSFrançois Tigeot return ret; 1620b030f26bSFrançois Tigeot } 1621b030f26bSFrançois Tigeot 1622*ba55f2f5SFrançois Tigeot virt = (unsigned int *)((char *)ringbuf->virtual_start + ringbuf->tail); 1623b030f26bSFrançois Tigeot rem /= 4; 1624b030f26bSFrançois Tigeot while (rem--) 1625686a02f1SFrançois Tigeot iowrite32(MI_NOOP, virt++); 1626b030f26bSFrançois Tigeot 1627*ba55f2f5SFrançois Tigeot ringbuf->tail = 0; 1628*ba55f2f5SFrançois Tigeot ringbuf->space = ring_space(ring); 1629b030f26bSFrançois Tigeot 1630b030f26bSFrançois Tigeot return 0; 1631b030f26bSFrançois Tigeot } 1632b030f26bSFrançois Tigeot 1633*ba55f2f5SFrançois Tigeot int intel_ring_idle(struct intel_engine_cs *ring) 1634b030f26bSFrançois Tigeot { 1635b5c29a34SFrançois Tigeot u32 seqno; 1636b5c29a34SFrançois Tigeot int ret; 1637b5c29a34SFrançois Tigeot 1638b5c29a34SFrançois Tigeot /* We need to add any requests required to flush the objects and ring */ 16399edbd4a0SFrançois Tigeot if (ring->outstanding_lazy_seqno) { 16405d0b1887SFrançois Tigeot ret = i915_add_request(ring, NULL); 1641b5c29a34SFrançois Tigeot if (ret) 1642b5c29a34SFrançois Tigeot return ret; 1643b5c29a34SFrançois Tigeot } 1644b5c29a34SFrançois Tigeot 1645b5c29a34SFrançois Tigeot /* Wait upon the last request to be completed */ 1646b5c29a34SFrançois Tigeot if (list_empty(&ring->request_list)) 1647b5c29a34SFrançois Tigeot return 0; 1648b5c29a34SFrançois Tigeot 1649b5c29a34SFrançois Tigeot seqno = list_entry(ring->request_list.prev, 1650b5c29a34SFrançois Tigeot struct drm_i915_gem_request, 1651b5c29a34SFrançois Tigeot list)->seqno; 1652b5c29a34SFrançois Tigeot 1653b5c29a34SFrançois Tigeot return i915_wait_seqno(ring, seqno); 1654b5c29a34SFrançois Tigeot } 1655b5c29a34SFrançois Tigeot 1656b5c29a34SFrançois Tigeot static int 1657*ba55f2f5SFrançois Tigeot intel_ring_alloc_seqno(struct intel_engine_cs *ring) 1658b5c29a34SFrançois Tigeot { 16599edbd4a0SFrançois Tigeot if (ring->outstanding_lazy_seqno) 1660b5c29a34SFrançois Tigeot return 0; 1661b5c29a34SFrançois Tigeot 16629edbd4a0SFrançois Tigeot if (ring->preallocated_lazy_request == NULL) { 16639edbd4a0SFrançois Tigeot struct drm_i915_gem_request *request; 16649edbd4a0SFrançois Tigeot 16659edbd4a0SFrançois Tigeot request = kmalloc(sizeof(*request), M_DRM, M_WAITOK); 16669edbd4a0SFrançois Tigeot if (request == NULL) 16679edbd4a0SFrançois Tigeot return -ENOMEM; 16689edbd4a0SFrançois Tigeot 16699edbd4a0SFrançois Tigeot ring->preallocated_lazy_request = request; 1670b030f26bSFrançois Tigeot } 1671b030f26bSFrançois Tigeot 16729edbd4a0SFrançois Tigeot return i915_gem_get_seqno(ring->dev, &ring->outstanding_lazy_seqno); 16739edbd4a0SFrançois Tigeot } 16749edbd4a0SFrançois Tigeot 1675*ba55f2f5SFrançois Tigeot static int __intel_ring_prepare(struct intel_engine_cs *ring, 1676a2fdbec6SFrançois Tigeot int bytes) 1677a2fdbec6SFrançois Tigeot { 1678*ba55f2f5SFrançois Tigeot struct intel_ringbuffer *ringbuf = ring->buffer; 1679a2fdbec6SFrançois Tigeot int ret; 1680a2fdbec6SFrançois Tigeot 1681*ba55f2f5SFrançois Tigeot if (unlikely(ringbuf->tail + bytes > ringbuf->effective_size)) { 1682a2fdbec6SFrançois Tigeot ret = intel_wrap_ring_buffer(ring); 1683a2fdbec6SFrançois Tigeot if (unlikely(ret)) 1684a2fdbec6SFrançois Tigeot return ret; 1685a2fdbec6SFrançois Tigeot } 1686a2fdbec6SFrançois Tigeot 1687*ba55f2f5SFrançois Tigeot if (unlikely(ringbuf->space < bytes)) { 1688a2fdbec6SFrançois Tigeot ret = ring_wait_for_space(ring, bytes); 1689a2fdbec6SFrançois Tigeot if (unlikely(ret)) 1690a2fdbec6SFrançois Tigeot return ret; 1691a2fdbec6SFrançois Tigeot } 1692a2fdbec6SFrançois Tigeot 1693a2fdbec6SFrançois Tigeot return 0; 1694a2fdbec6SFrançois Tigeot } 1695a2fdbec6SFrançois Tigeot 1696*ba55f2f5SFrançois Tigeot int intel_ring_begin(struct intel_engine_cs *ring, 1697e3adcf8fSFrançois Tigeot int num_dwords) 1698e3adcf8fSFrançois Tigeot { 1699*ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = ring->dev->dev_private; 1700e3adcf8fSFrançois Tigeot int ret; 1701e3adcf8fSFrançois Tigeot 1702a2fdbec6SFrançois Tigeot ret = i915_gem_check_wedge(&dev_priv->gpu_error, 1703a2fdbec6SFrançois Tigeot dev_priv->mm.interruptible); 1704245593daSFrançois Tigeot if (ret) 1705245593daSFrançois Tigeot return ret; 1706e3adcf8fSFrançois Tigeot 17079edbd4a0SFrançois Tigeot ret = __intel_ring_prepare(ring, num_dwords * sizeof(uint32_t)); 17089edbd4a0SFrançois Tigeot if (ret) 17099edbd4a0SFrançois Tigeot return ret; 17109edbd4a0SFrançois Tigeot 1711b5c29a34SFrançois Tigeot /* Preallocate the olr before touching the ring */ 1712b5c29a34SFrançois Tigeot ret = intel_ring_alloc_seqno(ring); 1713b5c29a34SFrançois Tigeot if (ret) 1714b5c29a34SFrançois Tigeot return ret; 1715b5c29a34SFrançois Tigeot 1716*ba55f2f5SFrançois Tigeot ring->buffer->space -= num_dwords * sizeof(uint32_t); 17179edbd4a0SFrançois Tigeot return 0; 17189edbd4a0SFrançois Tigeot } 17199edbd4a0SFrançois Tigeot 17209edbd4a0SFrançois Tigeot /* Align the ring tail to a cacheline boundary */ 1721*ba55f2f5SFrançois Tigeot int intel_ring_cacheline_align(struct intel_engine_cs *ring) 17229edbd4a0SFrançois Tigeot { 1723*ba55f2f5SFrançois Tigeot int num_dwords = (ring->buffer->tail & (CACHELINE_BYTES - 1)) / sizeof(uint32_t); 17249edbd4a0SFrançois Tigeot int ret; 17259edbd4a0SFrançois Tigeot 17269edbd4a0SFrançois Tigeot if (num_dwords == 0) 17279edbd4a0SFrançois Tigeot return 0; 17289edbd4a0SFrançois Tigeot 1729*ba55f2f5SFrançois Tigeot num_dwords = CACHELINE_BYTES / sizeof(uint32_t) - num_dwords; 17309edbd4a0SFrançois Tigeot ret = intel_ring_begin(ring, num_dwords); 17319edbd4a0SFrançois Tigeot if (ret) 17329edbd4a0SFrançois Tigeot return ret; 17339edbd4a0SFrançois Tigeot 17349edbd4a0SFrançois Tigeot while (num_dwords--) 17359edbd4a0SFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 17369edbd4a0SFrançois Tigeot 17379edbd4a0SFrançois Tigeot intel_ring_advance(ring); 17389edbd4a0SFrançois Tigeot 17399edbd4a0SFrançois Tigeot return 0; 1740e3adcf8fSFrançois Tigeot } 1741e3adcf8fSFrançois Tigeot 1742*ba55f2f5SFrançois Tigeot void intel_ring_init_seqno(struct intel_engine_cs *ring, u32 seqno) 1743a2fdbec6SFrançois Tigeot { 1744a2fdbec6SFrançois Tigeot struct drm_i915_private *dev_priv = ring->dev->dev_private; 1745a2fdbec6SFrançois Tigeot 17469edbd4a0SFrançois Tigeot BUG_ON(ring->outstanding_lazy_seqno); 1747a2fdbec6SFrançois Tigeot 1748a2fdbec6SFrançois Tigeot if (INTEL_INFO(ring->dev)->gen >= 6) { 1749a2fdbec6SFrançois Tigeot I915_WRITE(RING_SYNC_0(ring->mmio_base), 0); 1750a2fdbec6SFrançois Tigeot I915_WRITE(RING_SYNC_1(ring->mmio_base), 0); 17519edbd4a0SFrançois Tigeot if (HAS_VEBOX(ring->dev)) 17529edbd4a0SFrançois Tigeot I915_WRITE(RING_SYNC_2(ring->mmio_base), 0); 1753e3adcf8fSFrançois Tigeot } 1754e3adcf8fSFrançois Tigeot 1755a2fdbec6SFrançois Tigeot ring->set_seqno(ring, seqno); 17565d0b1887SFrançois Tigeot ring->hangcheck.seqno = seqno; 1757e3adcf8fSFrançois Tigeot } 1758e3adcf8fSFrançois Tigeot 1759*ba55f2f5SFrançois Tigeot static void gen6_bsd_ring_write_tail(struct intel_engine_cs *ring, 1760f4e1c372SFrançois Tigeot u32 value) 1761e3adcf8fSFrançois Tigeot { 1762*ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = ring->dev->dev_private; 1763e3adcf8fSFrançois Tigeot 1764e3adcf8fSFrançois Tigeot /* Every tail move must follow the sequence below */ 1765f4e1c372SFrançois Tigeot 1766f4e1c372SFrançois Tigeot /* Disable notification that the ring is IDLE. The GT 1767f4e1c372SFrançois Tigeot * will then assume that it is busy and bring it out of rc6. 1768f4e1c372SFrançois Tigeot */ 1769e3adcf8fSFrançois Tigeot I915_WRITE(GEN6_BSD_SLEEP_PSMI_CONTROL, 1770f4e1c372SFrançois Tigeot _MASKED_BIT_ENABLE(GEN6_BSD_SLEEP_MSG_DISABLE)); 1771e3adcf8fSFrançois Tigeot 1772f4e1c372SFrançois Tigeot /* Clear the context id. Here be magic! */ 1773f4e1c372SFrançois Tigeot I915_WRITE64(GEN6_BSD_RNCID, 0x0); 1774e3adcf8fSFrançois Tigeot 1775f4e1c372SFrançois Tigeot /* Wait for the ring not to be idle, i.e. for it to wake up. */ 1776f4e1c372SFrançois Tigeot if (wait_for((I915_READ(GEN6_BSD_SLEEP_PSMI_CONTROL) & 1777f4e1c372SFrançois Tigeot GEN6_BSD_SLEEP_INDICATOR) == 0, 1778f4e1c372SFrançois Tigeot 50)) 1779f4e1c372SFrançois Tigeot DRM_ERROR("timed out waiting for the BSD ring to wake up\n"); 1780f4e1c372SFrançois Tigeot 1781f4e1c372SFrançois Tigeot /* Now that the ring is fully powered up, update the tail */ 1782e3adcf8fSFrançois Tigeot I915_WRITE_TAIL(ring, value); 1783f4e1c372SFrançois Tigeot POSTING_READ(RING_TAIL(ring->mmio_base)); 1784f4e1c372SFrançois Tigeot 1785f4e1c372SFrançois Tigeot /* Let the ring send IDLE messages to the GT again, 1786f4e1c372SFrançois Tigeot * and so let it sleep to conserve power when idle. 1787f4e1c372SFrançois Tigeot */ 1788e3adcf8fSFrançois Tigeot I915_WRITE(GEN6_BSD_SLEEP_PSMI_CONTROL, 1789f4e1c372SFrançois Tigeot _MASKED_BIT_DISABLE(GEN6_BSD_SLEEP_MSG_DISABLE)); 1790e3adcf8fSFrançois Tigeot } 1791e3adcf8fSFrançois Tigeot 1792*ba55f2f5SFrançois Tigeot static int gen6_bsd_ring_flush(struct intel_engine_cs *ring, 1793b5c29a34SFrançois Tigeot u32 invalidate, u32 flush) 1794e3adcf8fSFrançois Tigeot { 1795e3adcf8fSFrançois Tigeot uint32_t cmd; 1796e3adcf8fSFrançois Tigeot int ret; 1797e3adcf8fSFrançois Tigeot 1798e3adcf8fSFrançois Tigeot ret = intel_ring_begin(ring, 4); 1799e3adcf8fSFrançois Tigeot if (ret) 1800e3adcf8fSFrançois Tigeot return ret; 1801e3adcf8fSFrançois Tigeot 1802e3adcf8fSFrançois Tigeot cmd = MI_FLUSH_DW; 18039edbd4a0SFrançois Tigeot if (INTEL_INFO(ring->dev)->gen >= 8) 18049edbd4a0SFrançois Tigeot cmd += 1; 1805b5c29a34SFrançois Tigeot /* 1806b5c29a34SFrançois Tigeot * Bspec vol 1c.5 - video engine command streamer: 1807b5c29a34SFrançois Tigeot * "If ENABLED, all TLBs will be invalidated once the flush 1808b5c29a34SFrançois Tigeot * operation is complete. This bit is only valid when the 1809b5c29a34SFrançois Tigeot * Post-Sync Operation field is a value of 1h or 3h." 1810b5c29a34SFrançois Tigeot */ 1811e3adcf8fSFrançois Tigeot if (invalidate & I915_GEM_GPU_DOMAINS) 1812b5c29a34SFrançois Tigeot cmd |= MI_INVALIDATE_TLB | MI_INVALIDATE_BSD | 1813b5c29a34SFrançois Tigeot MI_FLUSH_DW_STORE_INDEX | MI_FLUSH_DW_OP_STOREDW; 1814e3adcf8fSFrançois Tigeot intel_ring_emit(ring, cmd); 1815b5c29a34SFrançois Tigeot intel_ring_emit(ring, I915_GEM_HWS_SCRATCH_ADDR | MI_FLUSH_DW_USE_GTT); 18169edbd4a0SFrançois Tigeot if (INTEL_INFO(ring->dev)->gen >= 8) { 18179edbd4a0SFrançois Tigeot intel_ring_emit(ring, 0); /* upper addr */ 18189edbd4a0SFrançois Tigeot intel_ring_emit(ring, 0); /* value */ 18199edbd4a0SFrançois Tigeot } else { 18209edbd4a0SFrançois Tigeot intel_ring_emit(ring, 0); 18219edbd4a0SFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 18229edbd4a0SFrançois Tigeot } 18239edbd4a0SFrançois Tigeot intel_ring_advance(ring); 18249edbd4a0SFrançois Tigeot return 0; 18259edbd4a0SFrançois Tigeot } 18269edbd4a0SFrançois Tigeot 18279edbd4a0SFrançois Tigeot static int 1828*ba55f2f5SFrançois Tigeot gen8_ring_dispatch_execbuffer(struct intel_engine_cs *ring, 1829*ba55f2f5SFrançois Tigeot u64 offset, u32 len, 18309edbd4a0SFrançois Tigeot unsigned flags) 18319edbd4a0SFrançois Tigeot { 18329edbd4a0SFrançois Tigeot struct drm_i915_private *dev_priv = ring->dev->dev_private; 18339edbd4a0SFrançois Tigeot bool ppgtt = dev_priv->mm.aliasing_ppgtt != NULL && 18349edbd4a0SFrançois Tigeot !(flags & I915_DISPATCH_SECURE); 18359edbd4a0SFrançois Tigeot int ret; 18369edbd4a0SFrançois Tigeot 18379edbd4a0SFrançois Tigeot ret = intel_ring_begin(ring, 4); 18389edbd4a0SFrançois Tigeot if (ret) 18399edbd4a0SFrançois Tigeot return ret; 18409edbd4a0SFrançois Tigeot 18419edbd4a0SFrançois Tigeot /* FIXME(BDW): Address space and security selectors. */ 18429edbd4a0SFrançois Tigeot intel_ring_emit(ring, MI_BATCH_BUFFER_START_GEN8 | (ppgtt<<8)); 1843*ba55f2f5SFrançois Tigeot intel_ring_emit(ring, lower_32_bits(offset)); 1844*ba55f2f5SFrançois Tigeot intel_ring_emit(ring, upper_32_bits(offset)); 1845e3adcf8fSFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 1846e3adcf8fSFrançois Tigeot intel_ring_advance(ring); 18479edbd4a0SFrançois Tigeot 1848e3adcf8fSFrançois Tigeot return 0; 1849e3adcf8fSFrançois Tigeot } 1850e3adcf8fSFrançois Tigeot 1851e3adcf8fSFrançois Tigeot static int 1852*ba55f2f5SFrançois Tigeot hsw_ring_dispatch_execbuffer(struct intel_engine_cs *ring, 1853*ba55f2f5SFrançois Tigeot u64 offset, u32 len, 1854b5c29a34SFrançois Tigeot unsigned flags) 1855e3adcf8fSFrançois Tigeot { 1856e3adcf8fSFrançois Tigeot int ret; 1857e3adcf8fSFrançois Tigeot 1858e3adcf8fSFrançois Tigeot ret = intel_ring_begin(ring, 2); 1859e3adcf8fSFrançois Tigeot if (ret) 1860e3adcf8fSFrançois Tigeot return ret; 1861e3adcf8fSFrançois Tigeot 1862b5c29a34SFrançois Tigeot intel_ring_emit(ring, 1863b5c29a34SFrançois Tigeot MI_BATCH_BUFFER_START | MI_BATCH_PPGTT_HSW | 1864b5c29a34SFrançois Tigeot (flags & I915_DISPATCH_SECURE ? 0 : MI_BATCH_NON_SECURE_HSW)); 1865b5c29a34SFrançois Tigeot /* bit0-7 is the length on GEN6+ */ 1866b5c29a34SFrançois Tigeot intel_ring_emit(ring, offset); 1867b5c29a34SFrançois Tigeot intel_ring_advance(ring); 1868b5c29a34SFrançois Tigeot 1869b5c29a34SFrançois Tigeot return 0; 1870b5c29a34SFrançois Tigeot } 1871b5c29a34SFrançois Tigeot 1872b5c29a34SFrançois Tigeot static int 1873*ba55f2f5SFrançois Tigeot gen6_ring_dispatch_execbuffer(struct intel_engine_cs *ring, 1874*ba55f2f5SFrançois Tigeot u64 offset, u32 len, 1875b5c29a34SFrançois Tigeot unsigned flags) 1876b5c29a34SFrançois Tigeot { 1877b5c29a34SFrançois Tigeot int ret; 1878b5c29a34SFrançois Tigeot 1879b5c29a34SFrançois Tigeot ret = intel_ring_begin(ring, 2); 1880b5c29a34SFrançois Tigeot if (ret) 1881b5c29a34SFrançois Tigeot return ret; 1882b5c29a34SFrançois Tigeot 1883b5c29a34SFrançois Tigeot intel_ring_emit(ring, 1884b5c29a34SFrançois Tigeot MI_BATCH_BUFFER_START | 1885b5c29a34SFrançois Tigeot (flags & I915_DISPATCH_SECURE ? 0 : MI_BATCH_NON_SECURE_I965)); 1886e3adcf8fSFrançois Tigeot /* bit0-7 is the length on GEN6+ */ 1887e3adcf8fSFrançois Tigeot intel_ring_emit(ring, offset); 1888e3adcf8fSFrançois Tigeot intel_ring_advance(ring); 1889e3adcf8fSFrançois Tigeot 1890e3adcf8fSFrançois Tigeot return 0; 1891e3adcf8fSFrançois Tigeot } 1892e3adcf8fSFrançois Tigeot 1893e3adcf8fSFrançois Tigeot /* Blitter support (SandyBridge+) */ 1894e3adcf8fSFrançois Tigeot 1895*ba55f2f5SFrançois Tigeot static int gen6_ring_flush(struct intel_engine_cs *ring, 1896b5c29a34SFrançois Tigeot u32 invalidate, u32 flush) 1897e3adcf8fSFrançois Tigeot { 18985d0b1887SFrançois Tigeot struct drm_device *dev = ring->dev; 1899e3adcf8fSFrançois Tigeot uint32_t cmd; 1900e3adcf8fSFrançois Tigeot int ret; 1901e3adcf8fSFrançois Tigeot 1902e3adcf8fSFrançois Tigeot ret = intel_ring_begin(ring, 4); 1903e3adcf8fSFrançois Tigeot if (ret) 1904e3adcf8fSFrançois Tigeot return ret; 1905e3adcf8fSFrançois Tigeot 1906e3adcf8fSFrançois Tigeot cmd = MI_FLUSH_DW; 19079edbd4a0SFrançois Tigeot if (INTEL_INFO(ring->dev)->gen >= 8) 19089edbd4a0SFrançois Tigeot cmd += 1; 1909b5c29a34SFrançois Tigeot /* 1910b5c29a34SFrançois Tigeot * Bspec vol 1c.3 - blitter engine command streamer: 1911b5c29a34SFrançois Tigeot * "If ENABLED, all TLBs will be invalidated once the flush 1912b5c29a34SFrançois Tigeot * operation is complete. This bit is only valid when the 1913b5c29a34SFrançois Tigeot * Post-Sync Operation field is a value of 1h or 3h." 1914b5c29a34SFrançois Tigeot */ 1915e3adcf8fSFrançois Tigeot if (invalidate & I915_GEM_DOMAIN_RENDER) 1916b5c29a34SFrançois Tigeot cmd |= MI_INVALIDATE_TLB | MI_FLUSH_DW_STORE_INDEX | 1917b5c29a34SFrançois Tigeot MI_FLUSH_DW_OP_STOREDW; 1918e3adcf8fSFrançois Tigeot intel_ring_emit(ring, cmd); 1919b5c29a34SFrançois Tigeot intel_ring_emit(ring, I915_GEM_HWS_SCRATCH_ADDR | MI_FLUSH_DW_USE_GTT); 19209edbd4a0SFrançois Tigeot if (INTEL_INFO(ring->dev)->gen >= 8) { 19219edbd4a0SFrançois Tigeot intel_ring_emit(ring, 0); /* upper addr */ 19229edbd4a0SFrançois Tigeot intel_ring_emit(ring, 0); /* value */ 19239edbd4a0SFrançois Tigeot } else { 1924e3adcf8fSFrançois Tigeot intel_ring_emit(ring, 0); 1925e3adcf8fSFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 19269edbd4a0SFrançois Tigeot } 1927e3adcf8fSFrançois Tigeot intel_ring_advance(ring); 19285d0b1887SFrançois Tigeot 19299edbd4a0SFrançois Tigeot if (IS_GEN7(dev) && !invalidate && flush) 19305d0b1887SFrançois Tigeot return gen7_ring_fbc_flush(ring, FBC_REND_CACHE_CLEAN); 19315d0b1887SFrançois Tigeot 1932e3adcf8fSFrançois Tigeot return 0; 1933e3adcf8fSFrançois Tigeot } 1934e3adcf8fSFrançois Tigeot 1935e3adcf8fSFrançois Tigeot int intel_init_render_ring_buffer(struct drm_device *dev) 1936e3adcf8fSFrançois Tigeot { 1937*ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 1938*ba55f2f5SFrançois Tigeot struct intel_engine_cs *ring = &dev_priv->ring[RCS]; 1939e3adcf8fSFrançois Tigeot 1940686a02f1SFrançois Tigeot ring->name = "render ring"; 1941686a02f1SFrançois Tigeot ring->id = RCS; 1942686a02f1SFrançois Tigeot ring->mmio_base = RENDER_RING_BASE; 1943686a02f1SFrançois Tigeot 1944e3adcf8fSFrançois Tigeot if (INTEL_INFO(dev)->gen >= 6) { 1945e3adcf8fSFrançois Tigeot ring->add_request = gen6_add_request; 1946b5c29a34SFrançois Tigeot ring->flush = gen7_render_ring_flush; 1947b5c29a34SFrançois Tigeot if (INTEL_INFO(dev)->gen == 6) 1948e3adcf8fSFrançois Tigeot ring->flush = gen6_render_ring_flush; 19499edbd4a0SFrançois Tigeot if (INTEL_INFO(dev)->gen >= 8) { 19509edbd4a0SFrançois Tigeot ring->flush = gen8_render_ring_flush; 19519edbd4a0SFrançois Tigeot ring->irq_get = gen8_ring_get_irq; 19529edbd4a0SFrançois Tigeot ring->irq_put = gen8_ring_put_irq; 19539edbd4a0SFrançois Tigeot } else { 1954686a02f1SFrançois Tigeot ring->irq_get = gen6_ring_get_irq; 1955686a02f1SFrançois Tigeot ring->irq_put = gen6_ring_put_irq; 19569edbd4a0SFrançois Tigeot } 19575d0b1887SFrançois Tigeot ring->irq_enable_mask = GT_RENDER_USER_INTERRUPT; 1958e3adcf8fSFrançois Tigeot ring->get_seqno = gen6_ring_get_seqno; 1959a2fdbec6SFrançois Tigeot ring->set_seqno = ring_set_seqno; 1960*ba55f2f5SFrançois Tigeot ring->semaphore.sync_to = gen6_ring_sync; 1961*ba55f2f5SFrançois Tigeot ring->semaphore.signal = gen6_signal; 1962*ba55f2f5SFrançois Tigeot /* 1963*ba55f2f5SFrançois Tigeot * The current semaphore is only applied on pre-gen8 platform. 1964*ba55f2f5SFrançois Tigeot * And there is no VCS2 ring on the pre-gen8 platform. So the 1965*ba55f2f5SFrançois Tigeot * semaphore between RCS and VCS2 is initialized as INVALID. 1966*ba55f2f5SFrançois Tigeot * Gen8 will initialize the sema between VCS2 and RCS later. 1967*ba55f2f5SFrançois Tigeot */ 1968*ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[RCS] = MI_SEMAPHORE_SYNC_INVALID; 1969*ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[VCS] = MI_SEMAPHORE_SYNC_RV; 1970*ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[BCS] = MI_SEMAPHORE_SYNC_RB; 1971*ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[VECS] = MI_SEMAPHORE_SYNC_RVE; 1972*ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[VCS2] = MI_SEMAPHORE_SYNC_INVALID; 1973*ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[RCS] = GEN6_NOSYNC; 1974*ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[VCS] = GEN6_VRSYNC; 1975*ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[BCS] = GEN6_BRSYNC; 1976*ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[VECS] = GEN6_VERSYNC; 1977*ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[VCS2] = GEN6_NOSYNC; 1978e3adcf8fSFrançois Tigeot } else if (IS_GEN5(dev)) { 1979e3adcf8fSFrançois Tigeot ring->add_request = pc_render_add_request; 1980686a02f1SFrançois Tigeot ring->flush = gen4_render_ring_flush; 1981e3adcf8fSFrançois Tigeot ring->get_seqno = pc_render_get_seqno; 1982a2fdbec6SFrançois Tigeot ring->set_seqno = pc_render_set_seqno; 1983686a02f1SFrançois Tigeot ring->irq_get = gen5_ring_get_irq; 1984686a02f1SFrançois Tigeot ring->irq_put = gen5_ring_put_irq; 19855d0b1887SFrançois Tigeot ring->irq_enable_mask = GT_RENDER_USER_INTERRUPT | 19865d0b1887SFrançois Tigeot GT_RENDER_PIPECTL_NOTIFY_INTERRUPT; 1987686a02f1SFrançois Tigeot } else { 1988686a02f1SFrançois Tigeot ring->add_request = i9xx_add_request; 1989686a02f1SFrançois Tigeot if (INTEL_INFO(dev)->gen < 4) 1990686a02f1SFrançois Tigeot ring->flush = gen2_render_ring_flush; 1991686a02f1SFrançois Tigeot else 1992686a02f1SFrançois Tigeot ring->flush = gen4_render_ring_flush; 1993686a02f1SFrançois Tigeot ring->get_seqno = ring_get_seqno; 1994a2fdbec6SFrançois Tigeot ring->set_seqno = ring_set_seqno; 1995686a02f1SFrançois Tigeot if (IS_GEN2(dev)) { 1996686a02f1SFrançois Tigeot ring->irq_get = i8xx_ring_get_irq; 1997686a02f1SFrançois Tigeot ring->irq_put = i8xx_ring_put_irq; 1998686a02f1SFrançois Tigeot } else { 1999686a02f1SFrançois Tigeot ring->irq_get = i9xx_ring_get_irq; 2000686a02f1SFrançois Tigeot ring->irq_put = i9xx_ring_put_irq; 2001e3adcf8fSFrançois Tigeot } 2002686a02f1SFrançois Tigeot ring->irq_enable_mask = I915_USER_INTERRUPT; 2003686a02f1SFrançois Tigeot } 2004686a02f1SFrançois Tigeot ring->write_tail = ring_write_tail; 2005b5c29a34SFrançois Tigeot if (IS_HASWELL(dev)) 2006b5c29a34SFrançois Tigeot ring->dispatch_execbuffer = hsw_ring_dispatch_execbuffer; 20079edbd4a0SFrançois Tigeot else if (IS_GEN8(dev)) 20089edbd4a0SFrançois Tigeot ring->dispatch_execbuffer = gen8_ring_dispatch_execbuffer; 2009b5c29a34SFrançois Tigeot else if (INTEL_INFO(dev)->gen >= 6) 2010686a02f1SFrançois Tigeot ring->dispatch_execbuffer = gen6_ring_dispatch_execbuffer; 2011686a02f1SFrançois Tigeot else if (INTEL_INFO(dev)->gen >= 4) 2012686a02f1SFrançois Tigeot ring->dispatch_execbuffer = i965_dispatch_execbuffer; 2013686a02f1SFrançois Tigeot else if (IS_I830(dev) || IS_845G(dev)) 2014686a02f1SFrançois Tigeot ring->dispatch_execbuffer = i830_dispatch_execbuffer; 2015686a02f1SFrançois Tigeot else 2016686a02f1SFrançois Tigeot ring->dispatch_execbuffer = i915_dispatch_execbuffer; 2017686a02f1SFrançois Tigeot ring->init = init_render_ring; 2018686a02f1SFrançois Tigeot ring->cleanup = render_ring_cleanup; 2019e3adcf8fSFrançois Tigeot 2020b5c29a34SFrançois Tigeot /* Workaround batchbuffer to combat CS tlb bug. */ 2021b5c29a34SFrançois Tigeot if (HAS_BROKEN_CS_TLB(dev)) { 2022b5c29a34SFrançois Tigeot struct drm_i915_gem_object *obj; 2023b5c29a34SFrançois Tigeot int ret; 2024b5c29a34SFrançois Tigeot 2025b5c29a34SFrançois Tigeot obj = i915_gem_alloc_object(dev, I830_BATCH_LIMIT); 2026b5c29a34SFrançois Tigeot if (obj == NULL) { 2027b5c29a34SFrançois Tigeot DRM_ERROR("Failed to allocate batch bo\n"); 2028b5c29a34SFrançois Tigeot return -ENOMEM; 2029b5c29a34SFrançois Tigeot } 2030b5c29a34SFrançois Tigeot 2031*ba55f2f5SFrançois Tigeot ret = i915_gem_obj_ggtt_pin(obj, 0, 0); 2032b5c29a34SFrançois Tigeot if (ret != 0) { 2033b5c29a34SFrançois Tigeot drm_gem_object_unreference(&obj->base); 2034b5c29a34SFrançois Tigeot DRM_ERROR("Failed to ping batch bo\n"); 2035b5c29a34SFrançois Tigeot return ret; 2036b5c29a34SFrançois Tigeot } 2037b5c29a34SFrançois Tigeot 20389edbd4a0SFrançois Tigeot ring->scratch.obj = obj; 20399edbd4a0SFrançois Tigeot ring->scratch.gtt_offset = i915_gem_obj_ggtt_offset(obj); 2040e3adcf8fSFrançois Tigeot } 2041e3adcf8fSFrançois Tigeot 2042e3adcf8fSFrançois Tigeot return intel_init_ring_buffer(dev, ring); 2043e3adcf8fSFrançois Tigeot } 2044e3adcf8fSFrançois Tigeot 2045686a02f1SFrançois Tigeot int intel_render_ring_init_dri(struct drm_device *dev, u64 start, u32 size) 2046e3adcf8fSFrançois Tigeot { 2047*ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 2048*ba55f2f5SFrançois Tigeot struct intel_engine_cs *ring = &dev_priv->ring[RCS]; 2049*ba55f2f5SFrançois Tigeot struct intel_ringbuffer *ringbuf = ring->buffer; 2050b5c29a34SFrançois Tigeot int ret; 2051e3adcf8fSFrançois Tigeot 2052*ba55f2f5SFrançois Tigeot if (ringbuf == NULL) { 2053*ba55f2f5SFrançois Tigeot ringbuf = kzalloc(sizeof(*ringbuf), GFP_KERNEL); 2054*ba55f2f5SFrançois Tigeot if (!ringbuf) 2055*ba55f2f5SFrançois Tigeot return -ENOMEM; 2056*ba55f2f5SFrançois Tigeot ring->buffer = ringbuf; 2057*ba55f2f5SFrançois Tigeot } 2058*ba55f2f5SFrançois Tigeot 2059686a02f1SFrançois Tigeot ring->name = "render ring"; 2060686a02f1SFrançois Tigeot ring->id = RCS; 2061686a02f1SFrançois Tigeot ring->mmio_base = RENDER_RING_BASE; 2062686a02f1SFrançois Tigeot 2063e3adcf8fSFrançois Tigeot if (INTEL_INFO(dev)->gen >= 6) { 2064686a02f1SFrançois Tigeot /* non-kms not supported on gen6+ */ 2065*ba55f2f5SFrançois Tigeot ret = -ENODEV; 2066*ba55f2f5SFrançois Tigeot goto err_ringbuf; 2067e3adcf8fSFrançois Tigeot } 2068e3adcf8fSFrançois Tigeot 2069686a02f1SFrançois Tigeot /* Note: gem is not supported on gen5/ilk without kms (the corresponding 2070686a02f1SFrançois Tigeot * gem_init ioctl returns with -ENODEV). Hence we do not need to set up 2071686a02f1SFrançois Tigeot * the special gen5 functions. */ 2072686a02f1SFrançois Tigeot ring->add_request = i9xx_add_request; 2073686a02f1SFrançois Tigeot if (INTEL_INFO(dev)->gen < 4) 2074686a02f1SFrançois Tigeot ring->flush = gen2_render_ring_flush; 2075686a02f1SFrançois Tigeot else 2076686a02f1SFrançois Tigeot ring->flush = gen4_render_ring_flush; 2077686a02f1SFrançois Tigeot ring->get_seqno = ring_get_seqno; 2078a2fdbec6SFrançois Tigeot ring->set_seqno = ring_set_seqno; 2079686a02f1SFrançois Tigeot if (IS_GEN2(dev)) { 2080686a02f1SFrançois Tigeot ring->irq_get = i8xx_ring_get_irq; 2081686a02f1SFrançois Tigeot ring->irq_put = i8xx_ring_put_irq; 2082686a02f1SFrançois Tigeot } else { 2083686a02f1SFrançois Tigeot ring->irq_get = i9xx_ring_get_irq; 2084686a02f1SFrançois Tigeot ring->irq_put = i9xx_ring_put_irq; 2085686a02f1SFrançois Tigeot } 2086686a02f1SFrançois Tigeot ring->irq_enable_mask = I915_USER_INTERRUPT; 2087686a02f1SFrançois Tigeot ring->write_tail = ring_write_tail; 2088686a02f1SFrançois Tigeot if (INTEL_INFO(dev)->gen >= 4) 2089686a02f1SFrançois Tigeot ring->dispatch_execbuffer = i965_dispatch_execbuffer; 2090686a02f1SFrançois Tigeot else if (IS_I830(dev) || IS_845G(dev)) 2091686a02f1SFrançois Tigeot ring->dispatch_execbuffer = i830_dispatch_execbuffer; 2092686a02f1SFrançois Tigeot else 2093686a02f1SFrançois Tigeot ring->dispatch_execbuffer = i915_dispatch_execbuffer; 2094686a02f1SFrançois Tigeot ring->init = init_render_ring; 2095686a02f1SFrançois Tigeot ring->cleanup = render_ring_cleanup; 2096686a02f1SFrançois Tigeot 2097e3adcf8fSFrançois Tigeot ring->dev = dev; 2098e3adcf8fSFrançois Tigeot INIT_LIST_HEAD(&ring->active_list); 2099e3adcf8fSFrançois Tigeot INIT_LIST_HEAD(&ring->request_list); 2100e3adcf8fSFrançois Tigeot 2101*ba55f2f5SFrançois Tigeot ringbuf->size = size; 2102*ba55f2f5SFrançois Tigeot ringbuf->effective_size = ringbuf->size; 2103b5c29a34SFrançois Tigeot if (IS_I830(ring->dev) || IS_845G(ring->dev)) 2104*ba55f2f5SFrançois Tigeot ringbuf->effective_size -= 2 * CACHELINE_BYTES; 2105e3adcf8fSFrançois Tigeot 2106*ba55f2f5SFrançois Tigeot ringbuf->virtual_start = ioremap_wc(start, size); 2107*ba55f2f5SFrançois Tigeot if (ringbuf->virtual_start == NULL) { 2108e3adcf8fSFrançois Tigeot DRM_ERROR("can not ioremap virtual address for" 2109e3adcf8fSFrançois Tigeot " ring buffer\n"); 2110*ba55f2f5SFrançois Tigeot ret = -ENOMEM; 2111*ba55f2f5SFrançois Tigeot goto err_ringbuf; 2112e3adcf8fSFrançois Tigeot } 2113e3adcf8fSFrançois Tigeot 2114b5c29a34SFrançois Tigeot if (!I915_NEED_GFX_HWS(dev)) { 21155d0b1887SFrançois Tigeot ret = init_phys_status_page(ring); 2116b5c29a34SFrançois Tigeot if (ret) 2117*ba55f2f5SFrançois Tigeot goto err_vstart; 2118b5c29a34SFrançois Tigeot } 2119b5c29a34SFrançois Tigeot 2120e3adcf8fSFrançois Tigeot return 0; 2121*ba55f2f5SFrançois Tigeot 2122*ba55f2f5SFrançois Tigeot err_vstart: 2123*ba55f2f5SFrançois Tigeot pmap_unmapdev((vm_offset_t)ring->buffer->virtual_start, size); 2124*ba55f2f5SFrançois Tigeot err_ringbuf: 2125*ba55f2f5SFrançois Tigeot kfree(ringbuf); 2126*ba55f2f5SFrançois Tigeot ring->buffer = NULL; 2127*ba55f2f5SFrançois Tigeot return ret; 2128e3adcf8fSFrançois Tigeot } 2129e3adcf8fSFrançois Tigeot 2130e3adcf8fSFrançois Tigeot int intel_init_bsd_ring_buffer(struct drm_device *dev) 2131e3adcf8fSFrançois Tigeot { 2132*ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 2133*ba55f2f5SFrançois Tigeot struct intel_engine_cs *ring = &dev_priv->ring[VCS]; 2134e3adcf8fSFrançois Tigeot 2135686a02f1SFrançois Tigeot ring->name = "bsd ring"; 2136686a02f1SFrançois Tigeot ring->id = VCS; 2137686a02f1SFrançois Tigeot 2138686a02f1SFrançois Tigeot ring->write_tail = ring_write_tail; 21399edbd4a0SFrançois Tigeot if (INTEL_INFO(dev)->gen >= 6) { 2140686a02f1SFrançois Tigeot ring->mmio_base = GEN6_BSD_RING_BASE; 2141686a02f1SFrançois Tigeot /* gen6 bsd needs a special wa for tail updates */ 2142686a02f1SFrançois Tigeot if (IS_GEN6(dev)) 2143686a02f1SFrançois Tigeot ring->write_tail = gen6_bsd_ring_write_tail; 21445d0b1887SFrançois Tigeot ring->flush = gen6_bsd_ring_flush; 2145686a02f1SFrançois Tigeot ring->add_request = gen6_add_request; 2146686a02f1SFrançois Tigeot ring->get_seqno = gen6_ring_get_seqno; 2147a2fdbec6SFrançois Tigeot ring->set_seqno = ring_set_seqno; 21489edbd4a0SFrançois Tigeot if (INTEL_INFO(dev)->gen >= 8) { 21499edbd4a0SFrançois Tigeot ring->irq_enable_mask = 21509edbd4a0SFrançois Tigeot GT_RENDER_USER_INTERRUPT << GEN8_VCS1_IRQ_SHIFT; 21519edbd4a0SFrançois Tigeot ring->irq_get = gen8_ring_get_irq; 21529edbd4a0SFrançois Tigeot ring->irq_put = gen8_ring_put_irq; 21539edbd4a0SFrançois Tigeot ring->dispatch_execbuffer = 21549edbd4a0SFrançois Tigeot gen8_ring_dispatch_execbuffer; 21559edbd4a0SFrançois Tigeot } else { 21565d0b1887SFrançois Tigeot ring->irq_enable_mask = GT_BSD_USER_INTERRUPT; 2157686a02f1SFrançois Tigeot ring->irq_get = gen6_ring_get_irq; 2158686a02f1SFrançois Tigeot ring->irq_put = gen6_ring_put_irq; 21599edbd4a0SFrançois Tigeot ring->dispatch_execbuffer = 21609edbd4a0SFrançois Tigeot gen6_ring_dispatch_execbuffer; 21619edbd4a0SFrançois Tigeot } 2162*ba55f2f5SFrançois Tigeot ring->semaphore.sync_to = gen6_ring_sync; 2163*ba55f2f5SFrançois Tigeot ring->semaphore.signal = gen6_signal; 2164*ba55f2f5SFrançois Tigeot /* 2165*ba55f2f5SFrançois Tigeot * The current semaphore is only applied on pre-gen8 platform. 2166*ba55f2f5SFrançois Tigeot * And there is no VCS2 ring on the pre-gen8 platform. So the 2167*ba55f2f5SFrançois Tigeot * semaphore between VCS and VCS2 is initialized as INVALID. 2168*ba55f2f5SFrançois Tigeot * Gen8 will initialize the sema between VCS2 and VCS later. 2169*ba55f2f5SFrançois Tigeot */ 2170*ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[RCS] = MI_SEMAPHORE_SYNC_VR; 2171*ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[VCS] = MI_SEMAPHORE_SYNC_INVALID; 2172*ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[BCS] = MI_SEMAPHORE_SYNC_VB; 2173*ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[VECS] = MI_SEMAPHORE_SYNC_VVE; 2174*ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[VCS2] = MI_SEMAPHORE_SYNC_INVALID; 2175*ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[RCS] = GEN6_RVSYNC; 2176*ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[VCS] = GEN6_NOSYNC; 2177*ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[BCS] = GEN6_BVSYNC; 2178*ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[VECS] = GEN6_VEVSYNC; 2179*ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[VCS2] = GEN6_NOSYNC; 2180686a02f1SFrançois Tigeot } else { 2181686a02f1SFrançois Tigeot ring->mmio_base = BSD_RING_BASE; 2182686a02f1SFrançois Tigeot ring->flush = bsd_ring_flush; 2183686a02f1SFrançois Tigeot ring->add_request = i9xx_add_request; 2184686a02f1SFrançois Tigeot ring->get_seqno = ring_get_seqno; 2185a2fdbec6SFrançois Tigeot ring->set_seqno = ring_set_seqno; 2186686a02f1SFrançois Tigeot if (IS_GEN5(dev)) { 21875d0b1887SFrançois Tigeot ring->irq_enable_mask = ILK_BSD_USER_INTERRUPT; 2188686a02f1SFrançois Tigeot ring->irq_get = gen5_ring_get_irq; 2189686a02f1SFrançois Tigeot ring->irq_put = gen5_ring_put_irq; 2190686a02f1SFrançois Tigeot } else { 2191686a02f1SFrançois Tigeot ring->irq_enable_mask = I915_BSD_USER_INTERRUPT; 2192686a02f1SFrançois Tigeot ring->irq_get = i9xx_ring_get_irq; 2193686a02f1SFrançois Tigeot ring->irq_put = i9xx_ring_put_irq; 2194686a02f1SFrançois Tigeot } 2195686a02f1SFrançois Tigeot ring->dispatch_execbuffer = i965_dispatch_execbuffer; 2196686a02f1SFrançois Tigeot } 2197686a02f1SFrançois Tigeot ring->init = init_ring_common; 2198e3adcf8fSFrançois Tigeot 2199e3adcf8fSFrançois Tigeot return intel_init_ring_buffer(dev, ring); 2200e3adcf8fSFrançois Tigeot } 2201e3adcf8fSFrançois Tigeot 2202*ba55f2f5SFrançois Tigeot /** 2203*ba55f2f5SFrançois Tigeot * Initialize the second BSD ring for Broadwell GT3. 2204*ba55f2f5SFrançois Tigeot * It is noted that this only exists on Broadwell GT3. 2205*ba55f2f5SFrançois Tigeot */ 2206*ba55f2f5SFrançois Tigeot int intel_init_bsd2_ring_buffer(struct drm_device *dev) 2207*ba55f2f5SFrançois Tigeot { 2208*ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 2209*ba55f2f5SFrançois Tigeot struct intel_engine_cs *ring = &dev_priv->ring[VCS2]; 2210*ba55f2f5SFrançois Tigeot 2211*ba55f2f5SFrançois Tigeot if ((INTEL_INFO(dev)->gen != 8)) { 2212*ba55f2f5SFrançois Tigeot DRM_ERROR("No dual-BSD ring on non-BDW machine\n"); 2213*ba55f2f5SFrançois Tigeot return -EINVAL; 2214*ba55f2f5SFrançois Tigeot } 2215*ba55f2f5SFrançois Tigeot 2216*ba55f2f5SFrançois Tigeot ring->name = "bds2_ring"; 2217*ba55f2f5SFrançois Tigeot ring->id = VCS2; 2218*ba55f2f5SFrançois Tigeot 2219*ba55f2f5SFrançois Tigeot ring->write_tail = ring_write_tail; 2220*ba55f2f5SFrançois Tigeot ring->mmio_base = GEN8_BSD2_RING_BASE; 2221*ba55f2f5SFrançois Tigeot ring->flush = gen6_bsd_ring_flush; 2222*ba55f2f5SFrançois Tigeot ring->add_request = gen6_add_request; 2223*ba55f2f5SFrançois Tigeot ring->get_seqno = gen6_ring_get_seqno; 2224*ba55f2f5SFrançois Tigeot ring->set_seqno = ring_set_seqno; 2225*ba55f2f5SFrançois Tigeot ring->irq_enable_mask = 2226*ba55f2f5SFrançois Tigeot GT_RENDER_USER_INTERRUPT << GEN8_VCS2_IRQ_SHIFT; 2227*ba55f2f5SFrançois Tigeot ring->irq_get = gen8_ring_get_irq; 2228*ba55f2f5SFrançois Tigeot ring->irq_put = gen8_ring_put_irq; 2229*ba55f2f5SFrançois Tigeot ring->dispatch_execbuffer = 2230*ba55f2f5SFrançois Tigeot gen8_ring_dispatch_execbuffer; 2231*ba55f2f5SFrançois Tigeot ring->semaphore.sync_to = gen6_ring_sync; 2232*ba55f2f5SFrançois Tigeot ring->semaphore.signal = gen6_signal; 2233*ba55f2f5SFrançois Tigeot /* 2234*ba55f2f5SFrançois Tigeot * The current semaphore is only applied on the pre-gen8. And there 2235*ba55f2f5SFrançois Tigeot * is no bsd2 ring on the pre-gen8. So now the semaphore_register 2236*ba55f2f5SFrançois Tigeot * between VCS2 and other ring is initialized as invalid. 2237*ba55f2f5SFrançois Tigeot * Gen8 will initialize the sema between VCS2 and other ring later. 2238*ba55f2f5SFrançois Tigeot */ 2239*ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[RCS] = MI_SEMAPHORE_SYNC_INVALID; 2240*ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[VCS] = MI_SEMAPHORE_SYNC_INVALID; 2241*ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[BCS] = MI_SEMAPHORE_SYNC_INVALID; 2242*ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[VECS] = MI_SEMAPHORE_SYNC_INVALID; 2243*ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[VCS2] = MI_SEMAPHORE_SYNC_INVALID; 2244*ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[RCS] = GEN6_NOSYNC; 2245*ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[VCS] = GEN6_NOSYNC; 2246*ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[BCS] = GEN6_NOSYNC; 2247*ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[VECS] = GEN6_NOSYNC; 2248*ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[VCS2] = GEN6_NOSYNC; 2249*ba55f2f5SFrançois Tigeot 2250*ba55f2f5SFrançois Tigeot ring->init = init_ring_common; 2251*ba55f2f5SFrançois Tigeot 2252*ba55f2f5SFrançois Tigeot return intel_init_ring_buffer(dev, ring); 2253*ba55f2f5SFrançois Tigeot } 2254*ba55f2f5SFrançois Tigeot 2255e3adcf8fSFrançois Tigeot int intel_init_blt_ring_buffer(struct drm_device *dev) 2256e3adcf8fSFrançois Tigeot { 2257*ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 2258*ba55f2f5SFrançois Tigeot struct intel_engine_cs *ring = &dev_priv->ring[BCS]; 2259e3adcf8fSFrançois Tigeot 2260686a02f1SFrançois Tigeot ring->name = "blitter ring"; 2261686a02f1SFrançois Tigeot ring->id = BCS; 2262686a02f1SFrançois Tigeot 2263686a02f1SFrançois Tigeot ring->mmio_base = BLT_RING_BASE; 2264686a02f1SFrançois Tigeot ring->write_tail = ring_write_tail; 22655d0b1887SFrançois Tigeot ring->flush = gen6_ring_flush; 2266686a02f1SFrançois Tigeot ring->add_request = gen6_add_request; 2267686a02f1SFrançois Tigeot ring->get_seqno = gen6_ring_get_seqno; 2268a2fdbec6SFrançois Tigeot ring->set_seqno = ring_set_seqno; 22699edbd4a0SFrançois Tigeot if (INTEL_INFO(dev)->gen >= 8) { 22709edbd4a0SFrançois Tigeot ring->irq_enable_mask = 22719edbd4a0SFrançois Tigeot GT_RENDER_USER_INTERRUPT << GEN8_BCS_IRQ_SHIFT; 22729edbd4a0SFrançois Tigeot ring->irq_get = gen8_ring_get_irq; 22739edbd4a0SFrançois Tigeot ring->irq_put = gen8_ring_put_irq; 22749edbd4a0SFrançois Tigeot ring->dispatch_execbuffer = gen8_ring_dispatch_execbuffer; 22759edbd4a0SFrançois Tigeot } else { 22765d0b1887SFrançois Tigeot ring->irq_enable_mask = GT_BLT_USER_INTERRUPT; 2277686a02f1SFrançois Tigeot ring->irq_get = gen6_ring_get_irq; 2278686a02f1SFrançois Tigeot ring->irq_put = gen6_ring_put_irq; 2279686a02f1SFrançois Tigeot ring->dispatch_execbuffer = gen6_ring_dispatch_execbuffer; 22809edbd4a0SFrançois Tigeot } 2281*ba55f2f5SFrançois Tigeot ring->semaphore.sync_to = gen6_ring_sync; 2282*ba55f2f5SFrançois Tigeot ring->semaphore.signal = gen6_signal; 2283*ba55f2f5SFrançois Tigeot /* 2284*ba55f2f5SFrançois Tigeot * The current semaphore is only applied on pre-gen8 platform. And 2285*ba55f2f5SFrançois Tigeot * there is no VCS2 ring on the pre-gen8 platform. So the semaphore 2286*ba55f2f5SFrançois Tigeot * between BCS and VCS2 is initialized as INVALID. 2287*ba55f2f5SFrançois Tigeot * Gen8 will initialize the sema between BCS and VCS2 later. 2288*ba55f2f5SFrançois Tigeot */ 2289*ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[RCS] = MI_SEMAPHORE_SYNC_BR; 2290*ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[VCS] = MI_SEMAPHORE_SYNC_BV; 2291*ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[BCS] = MI_SEMAPHORE_SYNC_INVALID; 2292*ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[VECS] = MI_SEMAPHORE_SYNC_BVE; 2293*ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[VCS2] = MI_SEMAPHORE_SYNC_INVALID; 2294*ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[RCS] = GEN6_RBSYNC; 2295*ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[VCS] = GEN6_VBSYNC; 2296*ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[BCS] = GEN6_NOSYNC; 2297*ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[VECS] = GEN6_VEBSYNC; 2298*ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[VCS2] = GEN6_NOSYNC; 22995d0b1887SFrançois Tigeot ring->init = init_ring_common; 23005d0b1887SFrançois Tigeot 23015d0b1887SFrançois Tigeot return intel_init_ring_buffer(dev, ring); 23025d0b1887SFrançois Tigeot } 23035d0b1887SFrançois Tigeot 23045d0b1887SFrançois Tigeot int intel_init_vebox_ring_buffer(struct drm_device *dev) 23055d0b1887SFrançois Tigeot { 2306*ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 2307*ba55f2f5SFrançois Tigeot struct intel_engine_cs *ring = &dev_priv->ring[VECS]; 23085d0b1887SFrançois Tigeot 23095d0b1887SFrançois Tigeot ring->name = "video enhancement ring"; 23105d0b1887SFrançois Tigeot ring->id = VECS; 23115d0b1887SFrançois Tigeot 23125d0b1887SFrançois Tigeot ring->mmio_base = VEBOX_RING_BASE; 23135d0b1887SFrançois Tigeot ring->write_tail = ring_write_tail; 23145d0b1887SFrançois Tigeot ring->flush = gen6_ring_flush; 23155d0b1887SFrançois Tigeot ring->add_request = gen6_add_request; 23165d0b1887SFrançois Tigeot ring->get_seqno = gen6_ring_get_seqno; 23175d0b1887SFrançois Tigeot ring->set_seqno = ring_set_seqno; 23189edbd4a0SFrançois Tigeot 23199edbd4a0SFrançois Tigeot if (INTEL_INFO(dev)->gen >= 8) { 23209edbd4a0SFrançois Tigeot ring->irq_enable_mask = 23219edbd4a0SFrançois Tigeot GT_RENDER_USER_INTERRUPT << GEN8_VECS_IRQ_SHIFT; 23229edbd4a0SFrançois Tigeot ring->irq_get = gen8_ring_get_irq; 23239edbd4a0SFrançois Tigeot ring->irq_put = gen8_ring_put_irq; 23249edbd4a0SFrançois Tigeot ring->dispatch_execbuffer = gen8_ring_dispatch_execbuffer; 23259edbd4a0SFrançois Tigeot } else { 23269edbd4a0SFrançois Tigeot ring->irq_enable_mask = PM_VEBOX_USER_INTERRUPT; 23275d0b1887SFrançois Tigeot ring->irq_get = hsw_vebox_get_irq; 23285d0b1887SFrançois Tigeot ring->irq_put = hsw_vebox_put_irq; 23295d0b1887SFrançois Tigeot ring->dispatch_execbuffer = gen6_ring_dispatch_execbuffer; 23309edbd4a0SFrançois Tigeot } 2331*ba55f2f5SFrançois Tigeot ring->semaphore.sync_to = gen6_ring_sync; 2332*ba55f2f5SFrançois Tigeot ring->semaphore.signal = gen6_signal; 2333*ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[RCS] = MI_SEMAPHORE_SYNC_VER; 2334*ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[VCS] = MI_SEMAPHORE_SYNC_VEV; 2335*ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[BCS] = MI_SEMAPHORE_SYNC_VEB; 2336*ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[VECS] = MI_SEMAPHORE_SYNC_INVALID; 2337*ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[VCS2] = MI_SEMAPHORE_SYNC_INVALID; 2338*ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[RCS] = GEN6_RVESYNC; 2339*ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[VCS] = GEN6_VVESYNC; 2340*ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[BCS] = GEN6_BVESYNC; 2341*ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[VECS] = GEN6_NOSYNC; 2342*ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[VCS2] = GEN6_NOSYNC; 2343686a02f1SFrançois Tigeot ring->init = init_ring_common; 2344e3adcf8fSFrançois Tigeot 2345e3adcf8fSFrançois Tigeot return intel_init_ring_buffer(dev, ring); 2346e3adcf8fSFrançois Tigeot } 2347b030f26bSFrançois Tigeot 2348b030f26bSFrançois Tigeot int 2349*ba55f2f5SFrançois Tigeot intel_ring_flush_all_caches(struct intel_engine_cs *ring) 2350b030f26bSFrançois Tigeot { 2351b030f26bSFrançois Tigeot int ret; 2352b030f26bSFrançois Tigeot 2353b030f26bSFrançois Tigeot if (!ring->gpu_caches_dirty) 2354b030f26bSFrançois Tigeot return 0; 2355b030f26bSFrançois Tigeot 2356b030f26bSFrançois Tigeot ret = ring->flush(ring, 0, I915_GEM_GPU_DOMAINS); 2357b030f26bSFrançois Tigeot if (ret) 2358b030f26bSFrançois Tigeot return ret; 2359b030f26bSFrançois Tigeot 2360a2fdbec6SFrançois Tigeot trace_i915_gem_ring_flush(ring, 0, I915_GEM_GPU_DOMAINS); 2361a2fdbec6SFrançois Tigeot 2362b030f26bSFrançois Tigeot ring->gpu_caches_dirty = false; 2363b030f26bSFrançois Tigeot return 0; 2364b030f26bSFrançois Tigeot } 2365b030f26bSFrançois Tigeot 2366b030f26bSFrançois Tigeot int 2367*ba55f2f5SFrançois Tigeot intel_ring_invalidate_all_caches(struct intel_engine_cs *ring) 2368b030f26bSFrançois Tigeot { 2369b030f26bSFrançois Tigeot uint32_t flush_domains; 2370b030f26bSFrançois Tigeot int ret; 2371b030f26bSFrançois Tigeot 2372b030f26bSFrançois Tigeot flush_domains = 0; 2373b030f26bSFrançois Tigeot if (ring->gpu_caches_dirty) 2374b030f26bSFrançois Tigeot flush_domains = I915_GEM_GPU_DOMAINS; 2375b030f26bSFrançois Tigeot 2376b030f26bSFrançois Tigeot ret = ring->flush(ring, I915_GEM_GPU_DOMAINS, flush_domains); 2377b030f26bSFrançois Tigeot if (ret) 2378b030f26bSFrançois Tigeot return ret; 2379b030f26bSFrançois Tigeot 2380a2fdbec6SFrançois Tigeot trace_i915_gem_ring_flush(ring, I915_GEM_GPU_DOMAINS, flush_domains); 2381a2fdbec6SFrançois Tigeot 2382b030f26bSFrançois Tigeot ring->gpu_caches_dirty = false; 2383b030f26bSFrançois Tigeot return 0; 2384b030f26bSFrançois Tigeot } 2385*ba55f2f5SFrançois Tigeot 2386*ba55f2f5SFrançois Tigeot void 2387*ba55f2f5SFrançois Tigeot intel_stop_ring_buffer(struct intel_engine_cs *ring) 2388*ba55f2f5SFrançois Tigeot { 2389*ba55f2f5SFrançois Tigeot int ret; 2390*ba55f2f5SFrançois Tigeot 2391*ba55f2f5SFrançois Tigeot if (!intel_ring_initialized(ring)) 2392*ba55f2f5SFrançois Tigeot return; 2393*ba55f2f5SFrançois Tigeot 2394*ba55f2f5SFrançois Tigeot ret = intel_ring_idle(ring); 2395*ba55f2f5SFrançois Tigeot if (ret && !i915_reset_in_progress(&to_i915(ring->dev)->gpu_error)) 2396*ba55f2f5SFrançois Tigeot DRM_ERROR("failed to quiesce %s whilst cleaning up: %d\n", 2397*ba55f2f5SFrançois Tigeot ring->name, ret); 2398*ba55f2f5SFrançois Tigeot 2399*ba55f2f5SFrançois Tigeot stop_ring(ring); 2400*ba55f2f5SFrançois Tigeot } 2401