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 361b13d190SFrançois Tigeot bool 371b13d190SFrançois Tigeot intel_ring_initialized(struct intel_engine_cs *ring) 381b13d190SFrançois Tigeot { 391b13d190SFrançois Tigeot struct drm_device *dev = ring->dev; 40ba55f2f5SFrançois Tigeot 411b13d190SFrançois Tigeot if (!dev) 421b13d190SFrançois Tigeot return false; 431b13d190SFrançois Tigeot 441b13d190SFrançois Tigeot if (i915.enable_execlists) { 451b13d190SFrançois Tigeot struct intel_context *dctx = ring->default_context; 461b13d190SFrançois Tigeot struct intel_ringbuffer *ringbuf = dctx->engine[ring->id].ringbuf; 471b13d190SFrançois Tigeot 481b13d190SFrançois Tigeot return ringbuf->obj; 491b13d190SFrançois Tigeot } else 501b13d190SFrançois Tigeot return ring->buffer && ring->buffer->obj; 511b13d190SFrançois Tigeot } 521b13d190SFrançois Tigeot 531b13d190SFrançois Tigeot int __intel_ring_space(int head, int tail, int size) 54e3adcf8fSFrançois Tigeot { 552c9916cdSFrançois Tigeot int space = head - tail; 562c9916cdSFrançois Tigeot if (space <= 0) 57ba55f2f5SFrançois Tigeot space += size; 582c9916cdSFrançois Tigeot return space - I915_RING_FREE_SPACE; 592c9916cdSFrançois Tigeot } 602c9916cdSFrançois Tigeot 612c9916cdSFrançois Tigeot void intel_ring_update_space(struct intel_ringbuffer *ringbuf) 622c9916cdSFrançois Tigeot { 632c9916cdSFrançois Tigeot if (ringbuf->last_retired_head != -1) { 642c9916cdSFrançois Tigeot ringbuf->head = ringbuf->last_retired_head; 652c9916cdSFrançois Tigeot ringbuf->last_retired_head = -1; 662c9916cdSFrançois Tigeot } 672c9916cdSFrançois Tigeot 682c9916cdSFrançois Tigeot ringbuf->space = __intel_ring_space(ringbuf->head & HEAD_ADDR, 692c9916cdSFrançois Tigeot ringbuf->tail, ringbuf->size); 70e3adcf8fSFrançois Tigeot } 71e3adcf8fSFrançois Tigeot 721b13d190SFrançois Tigeot int intel_ring_space(struct intel_ringbuffer *ringbuf) 73ba55f2f5SFrançois Tigeot { 742c9916cdSFrançois Tigeot intel_ring_update_space(ringbuf); 752c9916cdSFrançois Tigeot return ringbuf->space; 76ba55f2f5SFrançois Tigeot } 77ba55f2f5SFrançois Tigeot 781b13d190SFrançois Tigeot bool intel_ring_stopped(struct intel_engine_cs *ring) 799edbd4a0SFrançois Tigeot { 809edbd4a0SFrançois Tigeot struct drm_i915_private *dev_priv = ring->dev->dev_private; 81ba55f2f5SFrançois Tigeot return dev_priv->gpu_error.stop_rings & intel_ring_flag(ring); 82ba55f2f5SFrançois Tigeot } 839edbd4a0SFrançois Tigeot 84ba55f2f5SFrançois Tigeot void __intel_ring_advance(struct intel_engine_cs *ring) 85ba55f2f5SFrançois Tigeot { 86ba55f2f5SFrançois Tigeot struct intel_ringbuffer *ringbuf = ring->buffer; 87ba55f2f5SFrançois Tigeot ringbuf->tail &= ringbuf->size - 1; 88ba55f2f5SFrançois Tigeot if (intel_ring_stopped(ring)) 899edbd4a0SFrançois Tigeot return; 90ba55f2f5SFrançois Tigeot ring->write_tail(ring, ringbuf->tail); 919edbd4a0SFrançois Tigeot } 929edbd4a0SFrançois Tigeot 93e3adcf8fSFrançois Tigeot static int 94ba55f2f5SFrançois Tigeot gen2_render_ring_flush(struct intel_engine_cs *ring, 95686a02f1SFrançois Tigeot u32 invalidate_domains, 96686a02f1SFrançois Tigeot u32 flush_domains) 97686a02f1SFrançois Tigeot { 98686a02f1SFrançois Tigeot u32 cmd; 99686a02f1SFrançois Tigeot int ret; 100686a02f1SFrançois Tigeot 101686a02f1SFrançois Tigeot cmd = MI_FLUSH; 102686a02f1SFrançois Tigeot if (((invalidate_domains|flush_domains) & I915_GEM_DOMAIN_RENDER) == 0) 103686a02f1SFrançois Tigeot cmd |= MI_NO_WRITE_FLUSH; 104686a02f1SFrançois Tigeot 105686a02f1SFrançois Tigeot if (invalidate_domains & I915_GEM_DOMAIN_SAMPLER) 106686a02f1SFrançois Tigeot cmd |= MI_READ_FLUSH; 107686a02f1SFrançois Tigeot 108686a02f1SFrançois Tigeot ret = intel_ring_begin(ring, 2); 109686a02f1SFrançois Tigeot if (ret) 110686a02f1SFrançois Tigeot return ret; 111686a02f1SFrançois Tigeot 112686a02f1SFrançois Tigeot intel_ring_emit(ring, cmd); 113686a02f1SFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 114686a02f1SFrançois Tigeot intel_ring_advance(ring); 115686a02f1SFrançois Tigeot 116686a02f1SFrançois Tigeot return 0; 117686a02f1SFrançois Tigeot } 118686a02f1SFrançois Tigeot 119686a02f1SFrançois Tigeot static int 120ba55f2f5SFrançois Tigeot gen4_render_ring_flush(struct intel_engine_cs *ring, 121686a02f1SFrançois Tigeot u32 invalidate_domains, 122686a02f1SFrançois Tigeot u32 flush_domains) 123e3adcf8fSFrançois Tigeot { 124e3adcf8fSFrançois Tigeot struct drm_device *dev = ring->dev; 125686a02f1SFrançois Tigeot u32 cmd; 126e3adcf8fSFrançois Tigeot int ret; 127e3adcf8fSFrançois Tigeot 128e3adcf8fSFrançois Tigeot /* 129e3adcf8fSFrançois Tigeot * read/write caches: 130e3adcf8fSFrançois Tigeot * 131e3adcf8fSFrançois Tigeot * I915_GEM_DOMAIN_RENDER is always invalidated, but is 132e3adcf8fSFrançois Tigeot * only flushed if MI_NO_WRITE_FLUSH is unset. On 965, it is 133e3adcf8fSFrançois Tigeot * also flushed at 2d versus 3d pipeline switches. 134e3adcf8fSFrançois Tigeot * 135e3adcf8fSFrançois Tigeot * read-only caches: 136e3adcf8fSFrançois Tigeot * 137e3adcf8fSFrançois Tigeot * I915_GEM_DOMAIN_SAMPLER is flushed on pre-965 if 138e3adcf8fSFrançois Tigeot * MI_READ_FLUSH is set, and is always flushed on 965. 139e3adcf8fSFrançois Tigeot * 140e3adcf8fSFrançois Tigeot * I915_GEM_DOMAIN_COMMAND may not exist? 141e3adcf8fSFrançois Tigeot * 142e3adcf8fSFrançois Tigeot * I915_GEM_DOMAIN_INSTRUCTION, which exists on 965, is 143e3adcf8fSFrançois Tigeot * invalidated when MI_EXE_FLUSH is set. 144e3adcf8fSFrançois Tigeot * 145e3adcf8fSFrançois Tigeot * I915_GEM_DOMAIN_VERTEX, which exists on 965, is 146e3adcf8fSFrançois Tigeot * invalidated with every MI_FLUSH. 147e3adcf8fSFrançois Tigeot * 148e3adcf8fSFrançois Tigeot * TLBs: 149e3adcf8fSFrançois Tigeot * 150e3adcf8fSFrançois Tigeot * On 965, TLBs associated with I915_GEM_DOMAIN_COMMAND 151e3adcf8fSFrançois Tigeot * and I915_GEM_DOMAIN_CPU in are invalidated at PTE write and 152e3adcf8fSFrançois Tigeot * I915_GEM_DOMAIN_RENDER and I915_GEM_DOMAIN_SAMPLER 153e3adcf8fSFrançois Tigeot * are flushed at any MI_FLUSH. 154e3adcf8fSFrançois Tigeot */ 155e3adcf8fSFrançois Tigeot 156e3adcf8fSFrançois Tigeot cmd = MI_FLUSH | MI_NO_WRITE_FLUSH; 157686a02f1SFrançois Tigeot if ((invalidate_domains|flush_domains) & I915_GEM_DOMAIN_RENDER) 158e3adcf8fSFrançois Tigeot cmd &= ~MI_NO_WRITE_FLUSH; 159e3adcf8fSFrançois Tigeot if (invalidate_domains & I915_GEM_DOMAIN_INSTRUCTION) 160e3adcf8fSFrançois Tigeot cmd |= MI_EXE_FLUSH; 161e3adcf8fSFrançois Tigeot 162e3adcf8fSFrançois Tigeot if (invalidate_domains & I915_GEM_DOMAIN_COMMAND && 163e3adcf8fSFrançois Tigeot (IS_G4X(dev) || IS_GEN5(dev))) 164e3adcf8fSFrançois Tigeot cmd |= MI_INVALIDATE_ISP; 165e3adcf8fSFrançois Tigeot 166e3adcf8fSFrançois Tigeot ret = intel_ring_begin(ring, 2); 167e3adcf8fSFrançois Tigeot if (ret) 168e3adcf8fSFrançois Tigeot return ret; 169e3adcf8fSFrançois Tigeot 170e3adcf8fSFrançois Tigeot intel_ring_emit(ring, cmd); 171e3adcf8fSFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 172e3adcf8fSFrançois Tigeot intel_ring_advance(ring); 173e3adcf8fSFrançois Tigeot 174e3adcf8fSFrançois Tigeot return 0; 175e3adcf8fSFrançois Tigeot } 176e3adcf8fSFrançois Tigeot 177e3adcf8fSFrançois Tigeot /** 178e3adcf8fSFrançois Tigeot * Emits a PIPE_CONTROL with a non-zero post-sync operation, for 179e3adcf8fSFrançois Tigeot * implementing two workarounds on gen6. From section 1.4.7.1 180e3adcf8fSFrançois Tigeot * "PIPE_CONTROL" of the Sandy Bridge PRM volume 2 part 1: 181e3adcf8fSFrançois Tigeot * 182e3adcf8fSFrançois Tigeot * [DevSNB-C+{W/A}] Before any depth stall flush (including those 183e3adcf8fSFrançois Tigeot * produced by non-pipelined state commands), software needs to first 184e3adcf8fSFrançois Tigeot * send a PIPE_CONTROL with no bits set except Post-Sync Operation != 185e3adcf8fSFrançois Tigeot * 0. 186e3adcf8fSFrançois Tigeot * 187e3adcf8fSFrançois Tigeot * [Dev-SNB{W/A}]: Before a PIPE_CONTROL with Write Cache Flush Enable 188e3adcf8fSFrançois Tigeot * =1, a PIPE_CONTROL with any non-zero post-sync-op is required. 189e3adcf8fSFrançois Tigeot * 190e3adcf8fSFrançois Tigeot * And the workaround for these two requires this workaround first: 191e3adcf8fSFrançois Tigeot * 192e3adcf8fSFrançois Tigeot * [Dev-SNB{W/A}]: Pipe-control with CS-stall bit set must be sent 193e3adcf8fSFrançois Tigeot * BEFORE the pipe-control with a post-sync op and no write-cache 194e3adcf8fSFrançois Tigeot * flushes. 195e3adcf8fSFrançois Tigeot * 196e3adcf8fSFrançois Tigeot * And this last workaround is tricky because of the requirements on 197e3adcf8fSFrançois Tigeot * that bit. From section 1.4.7.2.3 "Stall" of the Sandy Bridge PRM 198e3adcf8fSFrançois Tigeot * volume 2 part 1: 199e3adcf8fSFrançois Tigeot * 200e3adcf8fSFrançois Tigeot * "1 of the following must also be set: 201e3adcf8fSFrançois Tigeot * - Render Target Cache Flush Enable ([12] of DW1) 202e3adcf8fSFrançois Tigeot * - Depth Cache Flush Enable ([0] of DW1) 203e3adcf8fSFrançois Tigeot * - Stall at Pixel Scoreboard ([1] of DW1) 204e3adcf8fSFrançois Tigeot * - Depth Stall ([13] of DW1) 205e3adcf8fSFrançois Tigeot * - Post-Sync Operation ([13] of DW1) 206e3adcf8fSFrançois Tigeot * - Notify Enable ([8] of DW1)" 207e3adcf8fSFrançois Tigeot * 208e3adcf8fSFrançois Tigeot * The cache flushes require the workaround flush that triggered this 209e3adcf8fSFrançois Tigeot * one, so we can't use it. Depth stall would trigger the same. 210e3adcf8fSFrançois Tigeot * Post-sync nonzero is what triggered this second workaround, so we 211e3adcf8fSFrançois Tigeot * can't use that one either. Notify enable is IRQs, which aren't 212e3adcf8fSFrançois Tigeot * really our business. That leaves only stall at scoreboard. 213e3adcf8fSFrançois Tigeot */ 214e3adcf8fSFrançois Tigeot static int 215ba55f2f5SFrançois Tigeot intel_emit_post_sync_nonzero_flush(struct intel_engine_cs *ring) 216e3adcf8fSFrançois Tigeot { 217ba55f2f5SFrançois Tigeot u32 scratch_addr = ring->scratch.gtt_offset + 2 * CACHELINE_BYTES; 218e3adcf8fSFrançois Tigeot int ret; 219e3adcf8fSFrançois Tigeot 220e3adcf8fSFrançois Tigeot 221e3adcf8fSFrançois Tigeot ret = intel_ring_begin(ring, 6); 222e3adcf8fSFrançois Tigeot if (ret) 223e3adcf8fSFrançois Tigeot return ret; 224e3adcf8fSFrançois Tigeot 225e3adcf8fSFrançois Tigeot intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(5)); 226e3adcf8fSFrançois Tigeot intel_ring_emit(ring, PIPE_CONTROL_CS_STALL | 227e3adcf8fSFrançois Tigeot PIPE_CONTROL_STALL_AT_SCOREBOARD); 228e3adcf8fSFrançois Tigeot intel_ring_emit(ring, scratch_addr | PIPE_CONTROL_GLOBAL_GTT); /* address */ 229e3adcf8fSFrançois Tigeot intel_ring_emit(ring, 0); /* low dword */ 230e3adcf8fSFrançois Tigeot intel_ring_emit(ring, 0); /* high dword */ 231e3adcf8fSFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 232e3adcf8fSFrançois Tigeot intel_ring_advance(ring); 233e3adcf8fSFrançois Tigeot 234e3adcf8fSFrançois Tigeot ret = intel_ring_begin(ring, 6); 235e3adcf8fSFrançois Tigeot if (ret) 236e3adcf8fSFrançois Tigeot return ret; 237e3adcf8fSFrançois Tigeot 238e3adcf8fSFrançois Tigeot intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(5)); 239e3adcf8fSFrançois Tigeot intel_ring_emit(ring, PIPE_CONTROL_QW_WRITE); 240e3adcf8fSFrançois Tigeot intel_ring_emit(ring, scratch_addr | PIPE_CONTROL_GLOBAL_GTT); /* address */ 241e3adcf8fSFrançois Tigeot intel_ring_emit(ring, 0); 242e3adcf8fSFrançois Tigeot intel_ring_emit(ring, 0); 243e3adcf8fSFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 244e3adcf8fSFrançois Tigeot intel_ring_advance(ring); 245e3adcf8fSFrançois Tigeot 246e3adcf8fSFrançois Tigeot return 0; 247e3adcf8fSFrançois Tigeot } 248e3adcf8fSFrançois Tigeot 249e3adcf8fSFrançois Tigeot static int 250ba55f2f5SFrançois Tigeot gen6_render_ring_flush(struct intel_engine_cs *ring, 251e3adcf8fSFrançois Tigeot u32 invalidate_domains, u32 flush_domains) 252e3adcf8fSFrançois Tigeot { 253e3adcf8fSFrançois Tigeot u32 flags = 0; 254ba55f2f5SFrançois Tigeot u32 scratch_addr = ring->scratch.gtt_offset + 2 * CACHELINE_BYTES; 255e3adcf8fSFrançois Tigeot int ret; 256e3adcf8fSFrançois Tigeot 257e3adcf8fSFrançois Tigeot /* Force SNB workarounds for PIPE_CONTROL flushes */ 258686a02f1SFrançois Tigeot ret = intel_emit_post_sync_nonzero_flush(ring); 259686a02f1SFrançois Tigeot if (ret) 260686a02f1SFrançois Tigeot return ret; 261e3adcf8fSFrançois Tigeot 262e3adcf8fSFrançois Tigeot /* Just flush everything. Experiments have shown that reducing the 263e3adcf8fSFrançois Tigeot * number of bits based on the write domains has little performance 264e3adcf8fSFrançois Tigeot * impact. 265e3adcf8fSFrançois Tigeot */ 266b5c29a34SFrançois Tigeot if (flush_domains) { 267e3adcf8fSFrançois Tigeot flags |= PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH; 268b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_DEPTH_CACHE_FLUSH; 269b5c29a34SFrançois Tigeot /* 270b5c29a34SFrançois Tigeot * Ensure that any following seqno writes only happen 271b5c29a34SFrançois Tigeot * when the render cache is indeed flushed. 272b5c29a34SFrançois Tigeot */ 273b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_CS_STALL; 274b5c29a34SFrançois Tigeot } 275b5c29a34SFrançois Tigeot if (invalidate_domains) { 276686a02f1SFrançois Tigeot flags |= PIPE_CONTROL_TLB_INVALIDATE; 277e3adcf8fSFrançois Tigeot flags |= PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE; 278e3adcf8fSFrançois Tigeot flags |= PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE; 279e3adcf8fSFrançois Tigeot flags |= PIPE_CONTROL_VF_CACHE_INVALIDATE; 280e3adcf8fSFrançois Tigeot flags |= PIPE_CONTROL_CONST_CACHE_INVALIDATE; 281e3adcf8fSFrançois Tigeot flags |= PIPE_CONTROL_STATE_CACHE_INVALIDATE; 282686a02f1SFrançois Tigeot /* 283b5c29a34SFrançois Tigeot * TLB invalidate requires a post-sync write. 284686a02f1SFrançois Tigeot */ 285b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_QW_WRITE | PIPE_CONTROL_CS_STALL; 286b5c29a34SFrançois Tigeot } 287e3adcf8fSFrançois Tigeot 288b5c29a34SFrançois Tigeot ret = intel_ring_begin(ring, 4); 289e3adcf8fSFrançois Tigeot if (ret) 290e3adcf8fSFrançois Tigeot return ret; 291e3adcf8fSFrançois Tigeot 292b5c29a34SFrançois Tigeot intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(4)); 293e3adcf8fSFrançois Tigeot intel_ring_emit(ring, flags); 294e3adcf8fSFrançois Tigeot intel_ring_emit(ring, scratch_addr | PIPE_CONTROL_GLOBAL_GTT); 295b5c29a34SFrançois Tigeot intel_ring_emit(ring, 0); 296b5c29a34SFrançois Tigeot intel_ring_advance(ring); 297b5c29a34SFrançois Tigeot 298b5c29a34SFrançois Tigeot return 0; 299b5c29a34SFrançois Tigeot } 300b5c29a34SFrançois Tigeot 301b5c29a34SFrançois Tigeot static int 302ba55f2f5SFrançois Tigeot gen7_render_ring_cs_stall_wa(struct intel_engine_cs *ring) 303b5c29a34SFrançois Tigeot { 304b5c29a34SFrançois Tigeot int ret; 305b5c29a34SFrançois Tigeot 306b5c29a34SFrançois Tigeot ret = intel_ring_begin(ring, 4); 307b5c29a34SFrançois Tigeot if (ret) 308b5c29a34SFrançois Tigeot return ret; 309b5c29a34SFrançois Tigeot 310b5c29a34SFrançois Tigeot intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(4)); 311b5c29a34SFrançois Tigeot intel_ring_emit(ring, PIPE_CONTROL_CS_STALL | 312b5c29a34SFrançois Tigeot PIPE_CONTROL_STALL_AT_SCOREBOARD); 313b5c29a34SFrançois Tigeot intel_ring_emit(ring, 0); 314b5c29a34SFrançois Tigeot intel_ring_emit(ring, 0); 315b5c29a34SFrançois Tigeot intel_ring_advance(ring); 316b5c29a34SFrançois Tigeot 317b5c29a34SFrançois Tigeot return 0; 318b5c29a34SFrançois Tigeot } 319b5c29a34SFrançois Tigeot 320b5c29a34SFrançois Tigeot static int 321ba55f2f5SFrançois Tigeot gen7_render_ring_flush(struct intel_engine_cs *ring, 322b5c29a34SFrançois Tigeot u32 invalidate_domains, u32 flush_domains) 323b5c29a34SFrançois Tigeot { 324b5c29a34SFrançois Tigeot u32 flags = 0; 325ba55f2f5SFrançois Tigeot u32 scratch_addr = ring->scratch.gtt_offset + 2 * CACHELINE_BYTES; 326b5c29a34SFrançois Tigeot int ret; 327b5c29a34SFrançois Tigeot 328b5c29a34SFrançois Tigeot /* 329b5c29a34SFrançois Tigeot * Ensure that any following seqno writes only happen when the render 330b5c29a34SFrançois Tigeot * cache is indeed flushed. 331b5c29a34SFrançois Tigeot * 332b5c29a34SFrançois Tigeot * Workaround: 4th PIPE_CONTROL command (except the ones with only 333b5c29a34SFrançois Tigeot * read-cache invalidate bits set) must have the CS_STALL bit set. We 334b5c29a34SFrançois Tigeot * don't try to be clever and just set it unconditionally. 335b5c29a34SFrançois Tigeot */ 336b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_CS_STALL; 337b5c29a34SFrançois Tigeot 338b5c29a34SFrançois Tigeot /* Just flush everything. Experiments have shown that reducing the 339b5c29a34SFrançois Tigeot * number of bits based on the write domains has little performance 340b5c29a34SFrançois Tigeot * impact. 341b5c29a34SFrançois Tigeot */ 342b5c29a34SFrançois Tigeot if (flush_domains) { 343b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH; 344b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_DEPTH_CACHE_FLUSH; 345*b49c8cf9SFrançois Tigeot flags |= PIPE_CONTROL_FLUSH_ENABLE; 346b5c29a34SFrançois Tigeot } 347b5c29a34SFrançois Tigeot if (invalidate_domains) { 348b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_TLB_INVALIDATE; 349b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE; 350b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE; 351b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_VF_CACHE_INVALIDATE; 352b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_CONST_CACHE_INVALIDATE; 353b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_STATE_CACHE_INVALIDATE; 3542c9916cdSFrançois Tigeot flags |= PIPE_CONTROL_MEDIA_STATE_CLEAR; 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 3610dbf0ea8SMatthew Dillon flags |= PIPE_CONTROL_STALL_AT_SCOREBOARD; 3620dbf0ea8SMatthew Dillon 363b5c29a34SFrançois Tigeot /* Workaround: we must issue a pipe_control with CS-stall bit 364b5c29a34SFrançois Tigeot * set before a pipe_control command that has the state cache 365b5c29a34SFrançois Tigeot * invalidate bit set. */ 366b5c29a34SFrançois Tigeot gen7_render_ring_cs_stall_wa(ring); 367b5c29a34SFrançois Tigeot } 368b5c29a34SFrançois Tigeot 369b5c29a34SFrançois Tigeot ret = intel_ring_begin(ring, 4); 370b5c29a34SFrançois Tigeot if (ret) 371b5c29a34SFrançois Tigeot return ret; 372b5c29a34SFrançois Tigeot 373b5c29a34SFrançois Tigeot intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(4)); 374b5c29a34SFrançois Tigeot intel_ring_emit(ring, flags); 375a2fdbec6SFrançois Tigeot intel_ring_emit(ring, scratch_addr); 376b5c29a34SFrançois Tigeot intel_ring_emit(ring, 0); 377e3adcf8fSFrançois Tigeot intel_ring_advance(ring); 378e3adcf8fSFrançois Tigeot 379e3adcf8fSFrançois Tigeot return 0; 380e3adcf8fSFrançois Tigeot } 381e3adcf8fSFrançois Tigeot 3829edbd4a0SFrançois Tigeot static int 38324edb884SFrançois Tigeot gen8_emit_pipe_control(struct intel_engine_cs *ring, 38424edb884SFrançois Tigeot u32 flags, u32 scratch_addr) 38524edb884SFrançois Tigeot { 38624edb884SFrançois Tigeot int ret; 38724edb884SFrançois Tigeot 38824edb884SFrançois Tigeot ret = intel_ring_begin(ring, 6); 38924edb884SFrançois Tigeot if (ret) 39024edb884SFrançois Tigeot return ret; 39124edb884SFrançois Tigeot 39224edb884SFrançois Tigeot intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(6)); 39324edb884SFrançois Tigeot intel_ring_emit(ring, flags); 39424edb884SFrançois Tigeot intel_ring_emit(ring, scratch_addr); 39524edb884SFrançois Tigeot intel_ring_emit(ring, 0); 39624edb884SFrançois Tigeot intel_ring_emit(ring, 0); 39724edb884SFrançois Tigeot intel_ring_emit(ring, 0); 39824edb884SFrançois Tigeot intel_ring_advance(ring); 39924edb884SFrançois Tigeot 40024edb884SFrançois Tigeot return 0; 40124edb884SFrançois Tigeot } 40224edb884SFrançois Tigeot 40324edb884SFrançois Tigeot static int 404ba55f2f5SFrançois Tigeot gen8_render_ring_flush(struct intel_engine_cs *ring, 4059edbd4a0SFrançois Tigeot u32 invalidate_domains, u32 flush_domains) 4069edbd4a0SFrançois Tigeot { 4079edbd4a0SFrançois Tigeot u32 flags = 0; 408ba55f2f5SFrançois Tigeot u32 scratch_addr = ring->scratch.gtt_offset + 2 * CACHELINE_BYTES; 4099edbd4a0SFrançois Tigeot int ret; 4109edbd4a0SFrançois Tigeot 4119edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_CS_STALL; 4129edbd4a0SFrançois Tigeot 4139edbd4a0SFrançois Tigeot if (flush_domains) { 4149edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH; 4159edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_DEPTH_CACHE_FLUSH; 416*b49c8cf9SFrançois Tigeot flags |= PIPE_CONTROL_FLUSH_ENABLE; 4179edbd4a0SFrançois Tigeot } 4189edbd4a0SFrançois Tigeot if (invalidate_domains) { 4199edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_TLB_INVALIDATE; 4209edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE; 4219edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE; 4229edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_VF_CACHE_INVALIDATE; 4239edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_CONST_CACHE_INVALIDATE; 4249edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_STATE_CACHE_INVALIDATE; 4259edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_QW_WRITE; 4269edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_GLOBAL_GTT_IVB; 4279edbd4a0SFrançois Tigeot 42824edb884SFrançois Tigeot /* WaCsStallBeforeStateCacheInvalidate:bdw,chv */ 42924edb884SFrançois Tigeot ret = gen8_emit_pipe_control(ring, 43024edb884SFrançois Tigeot PIPE_CONTROL_CS_STALL | 43124edb884SFrançois Tigeot PIPE_CONTROL_STALL_AT_SCOREBOARD, 43224edb884SFrançois Tigeot 0); 4339edbd4a0SFrançois Tigeot if (ret) 4349edbd4a0SFrançois Tigeot return ret; 43524edb884SFrançois Tigeot } 4369edbd4a0SFrançois Tigeot 437477eb7f9SFrançois Tigeot return gen8_emit_pipe_control(ring, flags, scratch_addr); 4389edbd4a0SFrançois Tigeot } 4399edbd4a0SFrançois Tigeot 440ba55f2f5SFrançois Tigeot static void ring_write_tail(struct intel_engine_cs *ring, 441b5c29a34SFrançois Tigeot u32 value) 442e3adcf8fSFrançois Tigeot { 443ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = ring->dev->dev_private; 444e3adcf8fSFrançois Tigeot I915_WRITE_TAIL(ring, value); 445e3adcf8fSFrançois Tigeot } 446e3adcf8fSFrançois Tigeot 447ba55f2f5SFrançois Tigeot u64 intel_ring_get_active_head(struct intel_engine_cs *ring) 448e3adcf8fSFrançois Tigeot { 449ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = ring->dev->dev_private; 450ba55f2f5SFrançois Tigeot u64 acthd; 451e3adcf8fSFrançois Tigeot 452ba55f2f5SFrançois Tigeot if (INTEL_INFO(ring->dev)->gen >= 8) 453ba55f2f5SFrançois Tigeot acthd = I915_READ64_2x32(RING_ACTHD(ring->mmio_base), 454ba55f2f5SFrançois Tigeot RING_ACTHD_UDW(ring->mmio_base)); 455ba55f2f5SFrançois Tigeot else if (INTEL_INFO(ring->dev)->gen >= 4) 456ba55f2f5SFrançois Tigeot acthd = I915_READ(RING_ACTHD(ring->mmio_base)); 457ba55f2f5SFrançois Tigeot else 458ba55f2f5SFrançois Tigeot acthd = I915_READ(ACTHD); 459ba55f2f5SFrançois Tigeot 460ba55f2f5SFrançois Tigeot return acthd; 461e3adcf8fSFrançois Tigeot } 462e3adcf8fSFrançois Tigeot 463ba55f2f5SFrançois Tigeot static void ring_setup_phys_status_page(struct intel_engine_cs *ring) 4645d0b1887SFrançois Tigeot { 4655d0b1887SFrançois Tigeot struct drm_i915_private *dev_priv = ring->dev->dev_private; 4665d0b1887SFrançois Tigeot u32 addr; 4675d0b1887SFrançois Tigeot 4685d0b1887SFrançois Tigeot addr = dev_priv->status_page_dmah->busaddr; 4695d0b1887SFrançois Tigeot if (INTEL_INFO(ring->dev)->gen >= 4) 4705d0b1887SFrançois Tigeot addr |= (dev_priv->status_page_dmah->busaddr >> 28) & 0xf0; 4715d0b1887SFrançois Tigeot I915_WRITE(HWS_PGA, addr); 4725d0b1887SFrançois Tigeot } 4735d0b1887SFrançois Tigeot 474477eb7f9SFrançois Tigeot static void intel_ring_setup_status_page(struct intel_engine_cs *ring) 475477eb7f9SFrançois Tigeot { 476477eb7f9SFrançois Tigeot struct drm_device *dev = ring->dev; 477477eb7f9SFrançois Tigeot struct drm_i915_private *dev_priv = ring->dev->dev_private; 478477eb7f9SFrançois Tigeot u32 mmio = 0; 479477eb7f9SFrançois Tigeot 480477eb7f9SFrançois Tigeot /* The ring status page addresses are no longer next to the rest of 481477eb7f9SFrançois Tigeot * the ring registers as of gen7. 482477eb7f9SFrançois Tigeot */ 483477eb7f9SFrançois Tigeot if (IS_GEN7(dev)) { 484477eb7f9SFrançois Tigeot switch (ring->id) { 485477eb7f9SFrançois Tigeot case RCS: 486477eb7f9SFrançois Tigeot mmio = RENDER_HWS_PGA_GEN7; 487477eb7f9SFrançois Tigeot break; 488477eb7f9SFrançois Tigeot case BCS: 489477eb7f9SFrançois Tigeot mmio = BLT_HWS_PGA_GEN7; 490477eb7f9SFrançois Tigeot break; 491477eb7f9SFrançois Tigeot /* 492477eb7f9SFrançois Tigeot * VCS2 actually doesn't exist on Gen7. Only shut up 493477eb7f9SFrançois Tigeot * gcc switch check warning 494477eb7f9SFrançois Tigeot */ 495477eb7f9SFrançois Tigeot case VCS2: 496477eb7f9SFrançois Tigeot case VCS: 497477eb7f9SFrançois Tigeot mmio = BSD_HWS_PGA_GEN7; 498477eb7f9SFrançois Tigeot break; 499477eb7f9SFrançois Tigeot case VECS: 500477eb7f9SFrançois Tigeot mmio = VEBOX_HWS_PGA_GEN7; 501477eb7f9SFrançois Tigeot break; 502477eb7f9SFrançois Tigeot } 503477eb7f9SFrançois Tigeot } else if (IS_GEN6(ring->dev)) { 504477eb7f9SFrançois Tigeot mmio = RING_HWS_PGA_GEN6(ring->mmio_base); 505477eb7f9SFrançois Tigeot } else { 506477eb7f9SFrançois Tigeot /* XXX: gen8 returns to sanity */ 507477eb7f9SFrançois Tigeot mmio = RING_HWS_PGA(ring->mmio_base); 508477eb7f9SFrançois Tigeot } 509477eb7f9SFrançois Tigeot 510477eb7f9SFrançois Tigeot I915_WRITE(mmio, (u32)ring->status_page.gfx_addr); 511477eb7f9SFrançois Tigeot POSTING_READ(mmio); 512477eb7f9SFrançois Tigeot 513477eb7f9SFrançois Tigeot /* 514477eb7f9SFrançois Tigeot * Flush the TLB for this page 515477eb7f9SFrançois Tigeot * 516477eb7f9SFrançois Tigeot * FIXME: These two bits have disappeared on gen8, so a question 517477eb7f9SFrançois Tigeot * arises: do we still need this and if so how should we go about 518477eb7f9SFrançois Tigeot * invalidating the TLB? 519477eb7f9SFrançois Tigeot */ 520477eb7f9SFrançois Tigeot if (INTEL_INFO(dev)->gen >= 6 && INTEL_INFO(dev)->gen < 8) { 521477eb7f9SFrançois Tigeot u32 reg = RING_INSTPM(ring->mmio_base); 522477eb7f9SFrançois Tigeot 523477eb7f9SFrançois Tigeot /* ring should be idle before issuing a sync flush*/ 524477eb7f9SFrançois Tigeot WARN_ON((I915_READ_MODE(ring) & MODE_IDLE) == 0); 525477eb7f9SFrançois Tigeot 526477eb7f9SFrançois Tigeot I915_WRITE(reg, 527477eb7f9SFrançois Tigeot _MASKED_BIT_ENABLE(INSTPM_TLB_INVALIDATE | 528477eb7f9SFrançois Tigeot INSTPM_SYNC_FLUSH)); 529477eb7f9SFrançois Tigeot if (wait_for((I915_READ(reg) & INSTPM_SYNC_FLUSH) == 0, 530477eb7f9SFrançois Tigeot 1000)) 531477eb7f9SFrançois Tigeot DRM_ERROR("%s: wait for SyncFlush to complete for TLB invalidation timed out\n", 532477eb7f9SFrançois Tigeot ring->name); 533477eb7f9SFrançois Tigeot } 534477eb7f9SFrançois Tigeot } 535477eb7f9SFrançois Tigeot 536ba55f2f5SFrançois Tigeot static bool stop_ring(struct intel_engine_cs *ring) 537e3adcf8fSFrançois Tigeot { 538ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = to_i915(ring->dev); 539e3adcf8fSFrançois Tigeot 540ba55f2f5SFrançois Tigeot if (!IS_GEN2(ring->dev)) { 541ba55f2f5SFrançois Tigeot I915_WRITE_MODE(ring, _MASKED_BIT_ENABLE(STOP_RING)); 5421b13d190SFrançois Tigeot if (wait_for((I915_READ_MODE(ring) & MODE_IDLE) != 0, 1000)) { 543ba55f2f5SFrançois Tigeot DRM_ERROR("%s : timed out trying to stop ring\n", ring->name); 5441b13d190SFrançois Tigeot /* Sometimes we observe that the idle flag is not 5451b13d190SFrançois Tigeot * set even though the ring is empty. So double 5461b13d190SFrançois Tigeot * check before giving up. 5471b13d190SFrançois Tigeot */ 5481b13d190SFrançois Tigeot if (I915_READ_HEAD(ring) != I915_READ_TAIL(ring)) 549ba55f2f5SFrançois Tigeot return false; 550ba55f2f5SFrançois Tigeot } 551ba55f2f5SFrançois Tigeot } 552686a02f1SFrançois Tigeot 553e3adcf8fSFrançois Tigeot I915_WRITE_CTL(ring, 0); 554e3adcf8fSFrançois Tigeot I915_WRITE_HEAD(ring, 0); 555e3adcf8fSFrançois Tigeot ring->write_tail(ring, 0); 556e3adcf8fSFrançois Tigeot 557ba55f2f5SFrançois Tigeot if (!IS_GEN2(ring->dev)) { 558ba55f2f5SFrançois Tigeot (void)I915_READ_CTL(ring); 559ba55f2f5SFrançois Tigeot I915_WRITE_MODE(ring, _MASKED_BIT_DISABLE(STOP_RING)); 560ba55f2f5SFrançois Tigeot } 561e3adcf8fSFrançois Tigeot 562ba55f2f5SFrançois Tigeot return (I915_READ_HEAD(ring) & HEAD_ADDR) == 0; 563ba55f2f5SFrançois Tigeot } 564ba55f2f5SFrançois Tigeot 565ba55f2f5SFrançois Tigeot static int init_ring_common(struct intel_engine_cs *ring) 566ba55f2f5SFrançois Tigeot { 567ba55f2f5SFrançois Tigeot struct drm_device *dev = ring->dev; 568ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 569ba55f2f5SFrançois Tigeot struct intel_ringbuffer *ringbuf = ring->buffer; 570ba55f2f5SFrançois Tigeot struct drm_i915_gem_object *obj = ringbuf->obj; 571ba55f2f5SFrançois Tigeot int ret = 0; 572ba55f2f5SFrançois Tigeot 5732c9916cdSFrançois Tigeot intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL); 574ba55f2f5SFrançois Tigeot 575ba55f2f5SFrançois Tigeot if (!stop_ring(ring)) { 576ba55f2f5SFrançois Tigeot /* G45 ring initialization often fails to reset head to zero */ 577b5c29a34SFrançois Tigeot DRM_DEBUG_KMS("%s head not reset to zero " 578e3adcf8fSFrançois Tigeot "ctl %08x head %08x tail %08x start %08x\n", 579e3adcf8fSFrançois Tigeot ring->name, 580e3adcf8fSFrançois Tigeot I915_READ_CTL(ring), 581e3adcf8fSFrançois Tigeot I915_READ_HEAD(ring), 582e3adcf8fSFrançois Tigeot I915_READ_TAIL(ring), 583e3adcf8fSFrançois Tigeot I915_READ_START(ring)); 584e3adcf8fSFrançois Tigeot 585ba55f2f5SFrançois Tigeot if (!stop_ring(ring)) { 586e3adcf8fSFrançois Tigeot DRM_ERROR("failed to set %s head to zero " 587e3adcf8fSFrançois Tigeot "ctl %08x head %08x tail %08x start %08x\n", 588e3adcf8fSFrançois Tigeot ring->name, 589e3adcf8fSFrançois Tigeot I915_READ_CTL(ring), 590e3adcf8fSFrançois Tigeot I915_READ_HEAD(ring), 591e3adcf8fSFrançois Tigeot I915_READ_TAIL(ring), 592e3adcf8fSFrançois Tigeot I915_READ_START(ring)); 593686a02f1SFrançois Tigeot ret = -EIO; 594686a02f1SFrançois Tigeot goto out; 595e3adcf8fSFrançois Tigeot } 596ba55f2f5SFrançois Tigeot } 597ba55f2f5SFrançois Tigeot 598ba55f2f5SFrançois Tigeot if (I915_NEED_GFX_HWS(dev)) 599ba55f2f5SFrançois Tigeot intel_ring_setup_status_page(ring); 600ba55f2f5SFrançois Tigeot else 601ba55f2f5SFrançois Tigeot ring_setup_phys_status_page(ring); 602ba55f2f5SFrançois Tigeot 6030f370975SMatthew Dillon /* Enforce ordering by reading HEAD register back */ 6040f370975SMatthew Dillon I915_READ_HEAD(ring); 6050f370975SMatthew Dillon 606ba55f2f5SFrançois Tigeot /* Initialize the ring. This must happen _after_ we've cleared the ring 607ba55f2f5SFrançois Tigeot * registers with the above sequence (the readback of the HEAD registers 608ba55f2f5SFrançois Tigeot * also enforces ordering), otherwise the hw might lose the new ring 609ba55f2f5SFrançois Tigeot * register values. */ 610ba55f2f5SFrançois Tigeot I915_WRITE_START(ring, i915_gem_obj_ggtt_offset(obj)); 6111b13d190SFrançois Tigeot 6121b13d190SFrançois Tigeot /* WaClearRingBufHeadRegAtInit:ctg,elk */ 6131b13d190SFrançois Tigeot if (I915_READ_HEAD(ring)) 6141b13d190SFrançois Tigeot DRM_DEBUG("%s initialization failed [head=%08x], fudging\n", 6151b13d190SFrançois Tigeot ring->name, I915_READ_HEAD(ring)); 6161b13d190SFrançois Tigeot I915_WRITE_HEAD(ring, 0); 6171b13d190SFrançois Tigeot (void)I915_READ_HEAD(ring); 6181b13d190SFrançois Tigeot 619ba55f2f5SFrançois Tigeot I915_WRITE_CTL(ring, 620ba55f2f5SFrançois Tigeot ((ringbuf->size - PAGE_SIZE) & RING_NR_PAGES) 621ba55f2f5SFrançois Tigeot | RING_VALID); 622ba55f2f5SFrançois Tigeot 623ba55f2f5SFrançois Tigeot /* If the head is still not zero, the ring is dead */ 624ba55f2f5SFrançois Tigeot if (wait_for((I915_READ_CTL(ring) & RING_VALID) != 0 && 625ba55f2f5SFrançois Tigeot I915_READ_START(ring) == i915_gem_obj_ggtt_offset(obj) && 626ba55f2f5SFrançois Tigeot (I915_READ_HEAD(ring) & HEAD_ADDR) == 0, 50)) { 627ba55f2f5SFrançois Tigeot DRM_ERROR("%s initialization failed " 628ba55f2f5SFrançois Tigeot "ctl %08x (valid? %d) head %08x tail %08x start %08x [expected %08lx]\n", 629ba55f2f5SFrançois Tigeot ring->name, 630ba55f2f5SFrançois Tigeot I915_READ_CTL(ring), I915_READ_CTL(ring) & RING_VALID, 631ba55f2f5SFrançois Tigeot I915_READ_HEAD(ring), I915_READ_TAIL(ring), 632ba55f2f5SFrançois Tigeot I915_READ_START(ring), (unsigned long)i915_gem_obj_ggtt_offset(obj)); 633ba55f2f5SFrançois Tigeot ret = -EIO; 634ba55f2f5SFrançois Tigeot goto out; 635ba55f2f5SFrançois Tigeot } 636e3adcf8fSFrançois Tigeot 6372c9916cdSFrançois Tigeot ringbuf->last_retired_head = -1; 638ba55f2f5SFrançois Tigeot ringbuf->head = I915_READ_HEAD(ring); 639ba55f2f5SFrançois Tigeot ringbuf->tail = I915_READ_TAIL(ring) & TAIL_ADDR; 6402c9916cdSFrançois Tigeot intel_ring_update_space(ringbuf); 641e3adcf8fSFrançois Tigeot 6425d0b1887SFrançois Tigeot memset(&ring->hangcheck, 0, sizeof(ring->hangcheck)); 6435d0b1887SFrançois Tigeot 644686a02f1SFrançois Tigeot out: 6452c9916cdSFrançois Tigeot intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL); 646686a02f1SFrançois Tigeot 647686a02f1SFrançois Tigeot return ret; 648e3adcf8fSFrançois Tigeot } 649e3adcf8fSFrançois Tigeot 6501b13d190SFrançois Tigeot void 6511b13d190SFrançois Tigeot intel_fini_pipe_control(struct intel_engine_cs *ring) 6521b13d190SFrançois Tigeot { 6531b13d190SFrançois Tigeot struct drm_device *dev = ring->dev; 6541b13d190SFrançois Tigeot 6551b13d190SFrançois Tigeot if (ring->scratch.obj == NULL) 6561b13d190SFrançois Tigeot return; 6571b13d190SFrançois Tigeot 6581b13d190SFrançois Tigeot if (INTEL_INFO(dev)->gen >= 5) { 6591b13d190SFrançois Tigeot kunmap(ring->scratch.obj->pages[0]); 6601b13d190SFrançois Tigeot i915_gem_object_ggtt_unpin(ring->scratch.obj); 6611b13d190SFrançois Tigeot } 6621b13d190SFrançois Tigeot 6631b13d190SFrançois Tigeot drm_gem_object_unreference(&ring->scratch.obj->base); 6641b13d190SFrançois Tigeot ring->scratch.obj = NULL; 6651b13d190SFrançois Tigeot } 6661b13d190SFrançois Tigeot 6671b13d190SFrançois Tigeot int 6681b13d190SFrançois Tigeot intel_init_pipe_control(struct intel_engine_cs *ring) 669e3adcf8fSFrançois Tigeot { 670e3adcf8fSFrançois Tigeot int ret; 671e3adcf8fSFrançois Tigeot 6722c9916cdSFrançois Tigeot WARN_ON(ring->scratch.obj); 673e3adcf8fSFrançois Tigeot 6749edbd4a0SFrançois Tigeot ring->scratch.obj = i915_gem_alloc_object(ring->dev, 4096); 6759edbd4a0SFrançois Tigeot if (ring->scratch.obj == NULL) { 676e3adcf8fSFrançois Tigeot DRM_ERROR("Failed to allocate seqno page\n"); 677e3adcf8fSFrançois Tigeot ret = -ENOMEM; 678e3adcf8fSFrançois Tigeot goto err; 679e3adcf8fSFrançois Tigeot } 680e3adcf8fSFrançois Tigeot 681ba55f2f5SFrançois Tigeot ret = i915_gem_object_set_cache_level(ring->scratch.obj, I915_CACHE_LLC); 682ba55f2f5SFrançois Tigeot if (ret) 683ba55f2f5SFrançois Tigeot goto err_unref; 684e3adcf8fSFrançois Tigeot 685ba55f2f5SFrançois Tigeot ret = i915_gem_obj_ggtt_pin(ring->scratch.obj, 4096, 0); 686e3adcf8fSFrançois Tigeot if (ret) 687e3adcf8fSFrançois Tigeot goto err_unref; 688e3adcf8fSFrançois Tigeot 6899edbd4a0SFrançois Tigeot ring->scratch.gtt_offset = i915_gem_obj_ggtt_offset(ring->scratch.obj); 6909edbd4a0SFrançois Tigeot ring->scratch.cpu_page = kmap(ring->scratch.obj->pages[0]); 6919edbd4a0SFrançois Tigeot if (ring->scratch.cpu_page == NULL) { 6925d0b1887SFrançois Tigeot ret = -ENOMEM; 693e3adcf8fSFrançois Tigeot goto err_unpin; 6945d0b1887SFrançois Tigeot } 695a2fdbec6SFrançois Tigeot 696a2fdbec6SFrançois Tigeot DRM_DEBUG_DRIVER("%s pipe control offset: 0x%08x\n", 6979edbd4a0SFrançois Tigeot ring->name, ring->scratch.gtt_offset); 698e3adcf8fSFrançois Tigeot return 0; 699e3adcf8fSFrançois Tigeot 700e3adcf8fSFrançois Tigeot err_unpin: 701ba55f2f5SFrançois Tigeot i915_gem_object_ggtt_unpin(ring->scratch.obj); 702e3adcf8fSFrançois Tigeot err_unref: 7039edbd4a0SFrançois Tigeot drm_gem_object_unreference(&ring->scratch.obj->base); 704e3adcf8fSFrançois Tigeot err: 705e3adcf8fSFrançois Tigeot return ret; 706e3adcf8fSFrançois Tigeot } 707e3adcf8fSFrançois Tigeot 7082c9916cdSFrançois Tigeot static int intel_ring_workarounds_emit(struct intel_engine_cs *ring, 7092c9916cdSFrançois Tigeot struct intel_context *ctx) 7101b13d190SFrançois Tigeot { 7112c9916cdSFrançois Tigeot int ret, i; 7121b13d190SFrançois Tigeot struct drm_device *dev = ring->dev; 7131b13d190SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 7142c9916cdSFrançois Tigeot struct i915_workarounds *w = &dev_priv->workarounds; 7151b13d190SFrançois Tigeot 7162c9916cdSFrançois Tigeot if (WARN_ON_ONCE(w->count == 0)) 7172c9916cdSFrançois Tigeot return 0; 7181b13d190SFrançois Tigeot 7192c9916cdSFrançois Tigeot ring->gpu_caches_dirty = true; 7202c9916cdSFrançois Tigeot ret = intel_ring_flush_all_caches(ring); 7211b13d190SFrançois Tigeot if (ret) 7221b13d190SFrançois Tigeot return ret; 7231b13d190SFrançois Tigeot 7242c9916cdSFrançois Tigeot ret = intel_ring_begin(ring, (w->count * 2 + 2)); 7252c9916cdSFrançois Tigeot if (ret) 7262c9916cdSFrançois Tigeot return ret; 7272c9916cdSFrançois Tigeot 7282c9916cdSFrançois Tigeot intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(w->count)); 7292c9916cdSFrançois Tigeot for (i = 0; i < w->count; i++) { 7302c9916cdSFrançois Tigeot intel_ring_emit(ring, w->reg[i].addr); 7312c9916cdSFrançois Tigeot intel_ring_emit(ring, w->reg[i].value); 7322c9916cdSFrançois Tigeot } 7332c9916cdSFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 7342c9916cdSFrançois Tigeot 7352c9916cdSFrançois Tigeot intel_ring_advance(ring); 7362c9916cdSFrançois Tigeot 7372c9916cdSFrançois Tigeot ring->gpu_caches_dirty = true; 7382c9916cdSFrançois Tigeot ret = intel_ring_flush_all_caches(ring); 7392c9916cdSFrançois Tigeot if (ret) 7402c9916cdSFrançois Tigeot return ret; 7412c9916cdSFrançois Tigeot 7422c9916cdSFrançois Tigeot DRM_DEBUG_DRIVER("Number of Workarounds emitted: %d\n", w->count); 7432c9916cdSFrançois Tigeot 7442c9916cdSFrançois Tigeot return 0; 7452c9916cdSFrançois Tigeot } 7462c9916cdSFrançois Tigeot 7472c9916cdSFrançois Tigeot static int intel_rcs_ctx_init(struct intel_engine_cs *ring, 7482c9916cdSFrançois Tigeot struct intel_context *ctx) 7492c9916cdSFrançois Tigeot { 7502c9916cdSFrançois Tigeot int ret; 7512c9916cdSFrançois Tigeot 7522c9916cdSFrançois Tigeot ret = intel_ring_workarounds_emit(ring, ctx); 7532c9916cdSFrançois Tigeot if (ret != 0) 7542c9916cdSFrançois Tigeot return ret; 7552c9916cdSFrançois Tigeot 7562c9916cdSFrançois Tigeot ret = i915_gem_render_state_init(ring); 7572c9916cdSFrançois Tigeot if (ret) 7582c9916cdSFrançois Tigeot DRM_ERROR("init render state: %d\n", ret); 7592c9916cdSFrançois Tigeot 7602c9916cdSFrançois Tigeot return ret; 7612c9916cdSFrançois Tigeot } 7622c9916cdSFrançois Tigeot 7632c9916cdSFrançois Tigeot static int wa_add(struct drm_i915_private *dev_priv, 7642c9916cdSFrançois Tigeot const u32 addr, const u32 mask, const u32 val) 7652c9916cdSFrançois Tigeot { 7662c9916cdSFrançois Tigeot const u32 idx = dev_priv->workarounds.count; 7672c9916cdSFrançois Tigeot 7682c9916cdSFrançois Tigeot if (WARN_ON(idx >= I915_MAX_WA_REGS)) 7692c9916cdSFrançois Tigeot return -ENOSPC; 7702c9916cdSFrançois Tigeot 7712c9916cdSFrançois Tigeot dev_priv->workarounds.reg[idx].addr = addr; 7722c9916cdSFrançois Tigeot dev_priv->workarounds.reg[idx].value = val; 7732c9916cdSFrançois Tigeot dev_priv->workarounds.reg[idx].mask = mask; 7742c9916cdSFrançois Tigeot 7752c9916cdSFrançois Tigeot dev_priv->workarounds.count++; 7762c9916cdSFrançois Tigeot 7772c9916cdSFrançois Tigeot return 0; 7782c9916cdSFrançois Tigeot } 7792c9916cdSFrançois Tigeot 7802c9916cdSFrançois Tigeot #define WA_REG(addr, mask, val) { \ 7812c9916cdSFrançois Tigeot const int r = wa_add(dev_priv, (addr), (mask), (val)); \ 7822c9916cdSFrançois Tigeot if (r) \ 7832c9916cdSFrançois Tigeot return r; \ 7842c9916cdSFrançois Tigeot } 7852c9916cdSFrançois Tigeot 7862c9916cdSFrançois Tigeot #define WA_SET_BIT_MASKED(addr, mask) \ 7872c9916cdSFrançois Tigeot WA_REG(addr, (mask), _MASKED_BIT_ENABLE(mask)) 7882c9916cdSFrançois Tigeot 7892c9916cdSFrançois Tigeot #define WA_CLR_BIT_MASKED(addr, mask) \ 7902c9916cdSFrançois Tigeot WA_REG(addr, (mask), _MASKED_BIT_DISABLE(mask)) 7912c9916cdSFrançois Tigeot 7922c9916cdSFrançois Tigeot #define WA_SET_FIELD_MASKED(addr, mask, value) \ 7932c9916cdSFrançois Tigeot WA_REG(addr, mask, _MASKED_FIELD(mask, value)) 7942c9916cdSFrançois Tigeot 7952c9916cdSFrançois Tigeot #define WA_SET_BIT(addr, mask) WA_REG(addr, mask, I915_READ(addr) | (mask)) 7962c9916cdSFrançois Tigeot #define WA_CLR_BIT(addr, mask) WA_REG(addr, mask, I915_READ(addr) & ~(mask)) 7972c9916cdSFrançois Tigeot 7982c9916cdSFrançois Tigeot #define WA_WRITE(addr, val) WA_REG(addr, 0xffffffff, val) 7992c9916cdSFrançois Tigeot 8002c9916cdSFrançois Tigeot static int bdw_init_workarounds(struct intel_engine_cs *ring) 8012c9916cdSFrançois Tigeot { 8022c9916cdSFrançois Tigeot struct drm_device *dev = ring->dev; 8032c9916cdSFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 8042c9916cdSFrançois Tigeot 8051b13d190SFrançois Tigeot /* WaDisablePartialInstShootdown:bdw */ 8062c9916cdSFrançois Tigeot /* WaDisableThreadStallDopClockGating:bdw (pre-production) */ 8072c9916cdSFrançois Tigeot WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN, 8082c9916cdSFrançois Tigeot PARTIAL_INSTRUCTION_SHOOTDOWN_DISABLE | 8092c9916cdSFrançois Tigeot STALL_DOP_GATING_DISABLE); 8101b13d190SFrançois Tigeot 8112c9916cdSFrançois Tigeot /* WaDisableDopClockGating:bdw */ 8122c9916cdSFrançois Tigeot WA_SET_BIT_MASKED(GEN7_ROW_CHICKEN2, 8132c9916cdSFrançois Tigeot DOP_CLOCK_GATING_DISABLE); 8141b13d190SFrançois Tigeot 8152c9916cdSFrançois Tigeot WA_SET_BIT_MASKED(HALF_SLICE_CHICKEN3, 8162c9916cdSFrançois Tigeot GEN8_SAMPLER_POWER_BYPASS_DIS); 8171b13d190SFrançois Tigeot 8181b13d190SFrançois Tigeot /* Use Force Non-Coherent whenever executing a 3D context. This is a 8191b13d190SFrançois Tigeot * workaround for for a possible hang in the unlikely event a TLB 8201b13d190SFrançois Tigeot * invalidation occurs during a PSD flush. 8211b13d190SFrançois Tigeot */ 8222c9916cdSFrançois Tigeot WA_SET_BIT_MASKED(HDC_CHICKEN0, 823477eb7f9SFrançois Tigeot /* WaForceEnableNonCoherent:bdw */ 8242c9916cdSFrançois Tigeot HDC_FORCE_NON_COHERENT | 825477eb7f9SFrançois Tigeot /* WaForceContextSaveRestoreNonCoherent:bdw */ 826477eb7f9SFrançois Tigeot HDC_FORCE_CONTEXT_SAVE_RESTORE_NON_COHERENT | 827477eb7f9SFrançois Tigeot /* WaHdcDisableFetchWhenMasked:bdw */ 8282c9916cdSFrançois Tigeot HDC_DONOT_FETCH_MEM_WHEN_MASKED | 829477eb7f9SFrançois Tigeot /* WaDisableFenceDestinationToSLM:bdw (pre-prod) */ 8302c9916cdSFrançois Tigeot (IS_BDW_GT3(dev) ? HDC_FENCE_DEST_SLM_DISABLE : 0)); 8312c9916cdSFrançois Tigeot 8322c9916cdSFrançois Tigeot /* From the Haswell PRM, Command Reference: Registers, CACHE_MODE_0: 8332c9916cdSFrançois Tigeot * "The Hierarchical Z RAW Stall Optimization allows non-overlapping 8342c9916cdSFrançois Tigeot * polygons in the same 8x4 pixel/sample area to be processed without 8352c9916cdSFrançois Tigeot * stalling waiting for the earlier ones to write to Hierarchical Z 8362c9916cdSFrançois Tigeot * buffer." 8372c9916cdSFrançois Tigeot * 8382c9916cdSFrançois Tigeot * This optimization is off by default for Broadwell; turn it on. 8392c9916cdSFrançois Tigeot */ 8402c9916cdSFrançois Tigeot WA_CLR_BIT_MASKED(CACHE_MODE_0_GEN7, HIZ_RAW_STALL_OPT_DISABLE); 8411b13d190SFrançois Tigeot 8421b13d190SFrançois Tigeot /* Wa4x4STCOptimizationDisable:bdw */ 8432c9916cdSFrançois Tigeot WA_SET_BIT_MASKED(CACHE_MODE_1, 8442c9916cdSFrançois Tigeot GEN8_4x4_STC_OPTIMIZATION_DISABLE); 8451b13d190SFrançois Tigeot 8461b13d190SFrançois Tigeot /* 8471b13d190SFrançois Tigeot * BSpec recommends 8x4 when MSAA is used, 8481b13d190SFrançois Tigeot * however in practice 16x4 seems fastest. 8491b13d190SFrançois Tigeot * 8501b13d190SFrançois Tigeot * Note that PS/WM thread counts depend on the WIZ hashing 8511b13d190SFrançois Tigeot * disable bit, which we don't touch here, but it's good 8521b13d190SFrançois Tigeot * to keep in mind (see 3DSTATE_PS and 3DSTATE_WM). 8531b13d190SFrançois Tigeot */ 8542c9916cdSFrançois Tigeot WA_SET_FIELD_MASKED(GEN7_GT_MODE, 8552c9916cdSFrançois Tigeot GEN6_WIZ_HASHING_MASK, 8562c9916cdSFrançois Tigeot GEN6_WIZ_HASHING_16x4); 8571b13d190SFrançois Tigeot 8581b13d190SFrançois Tigeot return 0; 8591b13d190SFrançois Tigeot } 8601b13d190SFrançois Tigeot 8611b13d190SFrançois Tigeot static int chv_init_workarounds(struct intel_engine_cs *ring) 8621b13d190SFrançois Tigeot { 8631b13d190SFrançois Tigeot struct drm_device *dev = ring->dev; 8641b13d190SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 8651b13d190SFrançois Tigeot 8661b13d190SFrançois Tigeot /* WaDisablePartialInstShootdown:chv */ 8671b13d190SFrançois Tigeot /* WaDisableThreadStallDopClockGating:chv */ 8682c9916cdSFrançois Tigeot WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN, 8692c9916cdSFrançois Tigeot PARTIAL_INSTRUCTION_SHOOTDOWN_DISABLE | 8702c9916cdSFrançois Tigeot STALL_DOP_GATING_DISABLE); 8711b13d190SFrançois Tigeot 8722c9916cdSFrançois Tigeot /* Use Force Non-Coherent whenever executing a 3D context. This is a 8732c9916cdSFrançois Tigeot * workaround for a possible hang in the unlikely event a TLB 8742c9916cdSFrançois Tigeot * invalidation occurs during a PSD flush. 8752c9916cdSFrançois Tigeot */ 8762c9916cdSFrançois Tigeot /* WaForceEnableNonCoherent:chv */ 8772c9916cdSFrançois Tigeot /* WaHdcDisableFetchWhenMasked:chv */ 8782c9916cdSFrançois Tigeot WA_SET_BIT_MASKED(HDC_CHICKEN0, 8792c9916cdSFrançois Tigeot HDC_FORCE_NON_COHERENT | 8802c9916cdSFrançois Tigeot HDC_DONOT_FETCH_MEM_WHEN_MASKED); 8811b13d190SFrançois Tigeot 8822c9916cdSFrançois Tigeot /* According to the CACHE_MODE_0 default value documentation, some 8832c9916cdSFrançois Tigeot * CHV platforms disable this optimization by default. Turn it on. 8842c9916cdSFrançois Tigeot */ 8852c9916cdSFrançois Tigeot WA_CLR_BIT_MASKED(CACHE_MODE_0_GEN7, HIZ_RAW_STALL_OPT_DISABLE); 8861b13d190SFrançois Tigeot 8872c9916cdSFrançois Tigeot /* Wa4x4STCOptimizationDisable:chv */ 8882c9916cdSFrançois Tigeot WA_SET_BIT_MASKED(CACHE_MODE_1, 8892c9916cdSFrançois Tigeot GEN8_4x4_STC_OPTIMIZATION_DISABLE); 8902c9916cdSFrançois Tigeot 8912c9916cdSFrançois Tigeot /* Improve HiZ throughput on CHV. */ 8922c9916cdSFrançois Tigeot WA_SET_BIT_MASKED(HIZ_CHICKEN, CHV_HZ_8X8_MODE_IN_1X); 8932c9916cdSFrançois Tigeot 8942c9916cdSFrançois Tigeot /* 8952c9916cdSFrançois Tigeot * BSpec recommends 8x4 when MSAA is used, 8962c9916cdSFrançois Tigeot * however in practice 16x4 seems fastest. 8972c9916cdSFrançois Tigeot * 8982c9916cdSFrançois Tigeot * Note that PS/WM thread counts depend on the WIZ hashing 8992c9916cdSFrançois Tigeot * disable bit, which we don't touch here, but it's good 9002c9916cdSFrançois Tigeot * to keep in mind (see 3DSTATE_PS and 3DSTATE_WM). 9012c9916cdSFrançois Tigeot */ 9022c9916cdSFrançois Tigeot WA_SET_FIELD_MASKED(GEN7_GT_MODE, 9032c9916cdSFrançois Tigeot GEN6_WIZ_HASHING_MASK, 9042c9916cdSFrançois Tigeot GEN6_WIZ_HASHING_16x4); 9052c9916cdSFrançois Tigeot 9062c9916cdSFrançois Tigeot return 0; 9072c9916cdSFrançois Tigeot } 9082c9916cdSFrançois Tigeot 909477eb7f9SFrançois Tigeot static int gen9_init_workarounds(struct intel_engine_cs *ring) 910477eb7f9SFrançois Tigeot { 911477eb7f9SFrançois Tigeot struct drm_device *dev = ring->dev; 912477eb7f9SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 91319c468b4SFrançois Tigeot uint32_t tmp; 914477eb7f9SFrançois Tigeot 91519c468b4SFrançois Tigeot /* WaDisablePartialInstShootdown:skl,bxt */ 916477eb7f9SFrançois Tigeot WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN, 917477eb7f9SFrançois Tigeot PARTIAL_INSTRUCTION_SHOOTDOWN_DISABLE); 918477eb7f9SFrançois Tigeot 91919c468b4SFrançois Tigeot /* Syncing dependencies between camera and graphics:skl,bxt */ 920477eb7f9SFrançois Tigeot WA_SET_BIT_MASKED(HALF_SLICE_CHICKEN3, 921477eb7f9SFrançois Tigeot GEN9_DISABLE_OCL_OOB_SUPPRESS_LOGIC); 922477eb7f9SFrançois Tigeot 92319c468b4SFrançois Tigeot if ((IS_SKYLAKE(dev) && (INTEL_REVID(dev) == SKL_REVID_A0 || 92419c468b4SFrançois Tigeot INTEL_REVID(dev) == SKL_REVID_B0)) || 92519c468b4SFrançois Tigeot (IS_BROXTON(dev) && INTEL_REVID(dev) < BXT_REVID_B0)) { 92619c468b4SFrançois Tigeot /* WaDisableDgMirrorFixInHalfSliceChicken5:skl,bxt */ 927477eb7f9SFrançois Tigeot WA_CLR_BIT_MASKED(GEN9_HALF_SLICE_CHICKEN5, 928477eb7f9SFrançois Tigeot GEN9_DG_MIRROR_FIX_ENABLE); 929477eb7f9SFrançois Tigeot } 930477eb7f9SFrançois Tigeot 93119c468b4SFrançois Tigeot if ((IS_SKYLAKE(dev) && INTEL_REVID(dev) <= SKL_REVID_B0) || 93219c468b4SFrançois Tigeot (IS_BROXTON(dev) && INTEL_REVID(dev) < BXT_REVID_B0)) { 93319c468b4SFrançois Tigeot /* WaSetDisablePixMaskCammingAndRhwoInCommonSliceChicken:skl,bxt */ 934477eb7f9SFrançois Tigeot WA_SET_BIT_MASKED(GEN7_COMMON_SLICE_CHICKEN1, 935477eb7f9SFrançois Tigeot GEN9_RHWO_OPTIMIZATION_DISABLE); 936477eb7f9SFrançois Tigeot WA_SET_BIT_MASKED(GEN9_SLICE_COMMON_ECO_CHICKEN0, 937477eb7f9SFrançois Tigeot DISABLE_PIXEL_MASK_CAMMING); 938477eb7f9SFrançois Tigeot } 939477eb7f9SFrançois Tigeot 94019c468b4SFrançois Tigeot if ((IS_SKYLAKE(dev) && INTEL_REVID(dev) >= SKL_REVID_C0) || 94119c468b4SFrançois Tigeot IS_BROXTON(dev)) { 94219c468b4SFrançois Tigeot /* WaEnableYV12BugFixInHalfSliceChicken7:skl,bxt */ 943477eb7f9SFrançois Tigeot WA_SET_BIT_MASKED(GEN9_HALF_SLICE_CHICKEN7, 944477eb7f9SFrançois Tigeot GEN9_ENABLE_YV12_BUGFIX); 945477eb7f9SFrançois Tigeot } 946477eb7f9SFrançois Tigeot 94719c468b4SFrançois Tigeot /* Wa4x4STCOptimizationDisable:skl,bxt */ 948477eb7f9SFrançois Tigeot WA_SET_BIT_MASKED(CACHE_MODE_1, GEN8_4x4_STC_OPTIMIZATION_DISABLE); 949477eb7f9SFrançois Tigeot 95019c468b4SFrançois Tigeot /* WaDisablePartialResolveInVc:skl,bxt */ 951477eb7f9SFrançois Tigeot WA_SET_BIT_MASKED(CACHE_MODE_1, GEN9_PARTIAL_RESOLVE_IN_VC_DISABLE); 952477eb7f9SFrançois Tigeot 95319c468b4SFrançois Tigeot /* WaCcsTlbPrefetchDisable:skl,bxt */ 954477eb7f9SFrançois Tigeot WA_CLR_BIT_MASKED(GEN9_HALF_SLICE_CHICKEN5, 955477eb7f9SFrançois Tigeot GEN9_CCS_TLB_PREFETCH_ENABLE); 956477eb7f9SFrançois Tigeot 95719c468b4SFrançois Tigeot /* WaDisableMaskBasedCammingInRCC:skl,bxt */ 95819c468b4SFrançois Tigeot if ((IS_SKYLAKE(dev) && INTEL_REVID(dev) == SKL_REVID_C0) || 95919c468b4SFrançois Tigeot (IS_BROXTON(dev) && INTEL_REVID(dev) < BXT_REVID_B0)) 96019c468b4SFrançois Tigeot WA_SET_BIT_MASKED(SLICE_ECO_CHICKEN0, 96119c468b4SFrançois Tigeot PIXEL_MASK_CAMMING_DISABLE); 96219c468b4SFrançois Tigeot 96319c468b4SFrançois Tigeot /* WaForceContextSaveRestoreNonCoherent:skl,bxt */ 96419c468b4SFrançois Tigeot tmp = HDC_FORCE_CONTEXT_SAVE_RESTORE_NON_COHERENT; 96519c468b4SFrançois Tigeot if ((IS_SKYLAKE(dev) && INTEL_REVID(dev) == SKL_REVID_F0) || 96619c468b4SFrançois Tigeot (IS_BROXTON(dev) && INTEL_REVID(dev) >= BXT_REVID_B0)) 96719c468b4SFrançois Tigeot tmp |= HDC_FORCE_CSR_NON_COHERENT_OVR_DISABLE; 96819c468b4SFrançois Tigeot WA_SET_BIT_MASKED(HDC_CHICKEN0, tmp); 96919c468b4SFrançois Tigeot 970477eb7f9SFrançois Tigeot return 0; 971477eb7f9SFrançois Tigeot } 972477eb7f9SFrançois Tigeot 973477eb7f9SFrançois Tigeot static int skl_tune_iz_hashing(struct intel_engine_cs *ring) 974477eb7f9SFrançois Tigeot { 975477eb7f9SFrançois Tigeot struct drm_device *dev = ring->dev; 976477eb7f9SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 977477eb7f9SFrançois Tigeot u8 vals[3] = { 0, 0, 0 }; 978477eb7f9SFrançois Tigeot unsigned int i; 979477eb7f9SFrançois Tigeot 980477eb7f9SFrançois Tigeot for (i = 0; i < 3; i++) { 981477eb7f9SFrançois Tigeot u8 ss; 982477eb7f9SFrançois Tigeot 983477eb7f9SFrançois Tigeot /* 984477eb7f9SFrançois Tigeot * Only consider slices where one, and only one, subslice has 7 985477eb7f9SFrançois Tigeot * EUs 986477eb7f9SFrançois Tigeot */ 987477eb7f9SFrançois Tigeot if (hweight8(dev_priv->info.subslice_7eu[i]) != 1) 988477eb7f9SFrançois Tigeot continue; 989477eb7f9SFrançois Tigeot 990477eb7f9SFrançois Tigeot /* 991477eb7f9SFrançois Tigeot * subslice_7eu[i] != 0 (because of the check above) and 992477eb7f9SFrançois Tigeot * ss_max == 4 (maximum number of subslices possible per slice) 993477eb7f9SFrançois Tigeot * 994477eb7f9SFrançois Tigeot * -> 0 <= ss <= 3; 995477eb7f9SFrançois Tigeot */ 996477eb7f9SFrançois Tigeot ss = ffs(dev_priv->info.subslice_7eu[i]) - 1; 997477eb7f9SFrançois Tigeot vals[i] = 3 - ss; 998477eb7f9SFrançois Tigeot } 999477eb7f9SFrançois Tigeot 1000477eb7f9SFrançois Tigeot if (vals[0] == 0 && vals[1] == 0 && vals[2] == 0) 1001477eb7f9SFrançois Tigeot return 0; 1002477eb7f9SFrançois Tigeot 1003477eb7f9SFrançois Tigeot /* Tune IZ hashing. See intel_device_info_runtime_init() */ 1004477eb7f9SFrançois Tigeot WA_SET_FIELD_MASKED(GEN7_GT_MODE, 1005477eb7f9SFrançois Tigeot GEN9_IZ_HASHING_MASK(2) | 1006477eb7f9SFrançois Tigeot GEN9_IZ_HASHING_MASK(1) | 1007477eb7f9SFrançois Tigeot GEN9_IZ_HASHING_MASK(0), 1008477eb7f9SFrançois Tigeot GEN9_IZ_HASHING(2, vals[2]) | 1009477eb7f9SFrançois Tigeot GEN9_IZ_HASHING(1, vals[1]) | 1010477eb7f9SFrançois Tigeot GEN9_IZ_HASHING(0, vals[0])); 1011477eb7f9SFrançois Tigeot 1012477eb7f9SFrançois Tigeot return 0; 1013477eb7f9SFrançois Tigeot } 1014477eb7f9SFrançois Tigeot 1015477eb7f9SFrançois Tigeot 1016477eb7f9SFrançois Tigeot static int skl_init_workarounds(struct intel_engine_cs *ring) 1017477eb7f9SFrançois Tigeot { 1018477eb7f9SFrançois Tigeot struct drm_device *dev = ring->dev; 1019477eb7f9SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 1020477eb7f9SFrançois Tigeot 1021477eb7f9SFrançois Tigeot gen9_init_workarounds(ring); 1022477eb7f9SFrançois Tigeot 1023477eb7f9SFrançois Tigeot /* WaDisablePowerCompilerClockGating:skl */ 1024477eb7f9SFrançois Tigeot if (INTEL_REVID(dev) == SKL_REVID_B0) 1025477eb7f9SFrançois Tigeot WA_SET_BIT_MASKED(HIZ_CHICKEN, 1026477eb7f9SFrançois Tigeot BDW_HIZ_POWER_COMPILER_CLOCK_GATING_DISABLE); 1027477eb7f9SFrançois Tigeot 1028477eb7f9SFrançois Tigeot if (INTEL_REVID(dev) == SKL_REVID_C0 || 1029477eb7f9SFrançois Tigeot INTEL_REVID(dev) == SKL_REVID_D0) 1030477eb7f9SFrançois Tigeot /* WaBarrierPerformanceFixDisable:skl */ 1031477eb7f9SFrançois Tigeot WA_SET_BIT_MASKED(HDC_CHICKEN0, 1032477eb7f9SFrançois Tigeot HDC_FENCE_DEST_SLM_DISABLE | 1033477eb7f9SFrançois Tigeot HDC_BARRIER_PERFORMANCE_DISABLE); 1034477eb7f9SFrançois Tigeot 103519c468b4SFrançois Tigeot if (INTEL_REVID(dev) <= SKL_REVID_D0) { 103619c468b4SFrançois Tigeot /* 103719c468b4SFrançois Tigeot *Use Force Non-Coherent whenever executing a 3D context. This 103819c468b4SFrançois Tigeot * is a workaround for a possible hang in the unlikely event 103919c468b4SFrançois Tigeot * a TLB invalidation occurs during a PSD flush. 104019c468b4SFrançois Tigeot */ 104119c468b4SFrançois Tigeot /* WaForceEnableNonCoherent:skl */ 104219c468b4SFrançois Tigeot WA_SET_BIT_MASKED(HDC_CHICKEN0, 104319c468b4SFrançois Tigeot HDC_FORCE_NON_COHERENT); 104419c468b4SFrançois Tigeot } 104519c468b4SFrançois Tigeot 1046477eb7f9SFrançois Tigeot return skl_tune_iz_hashing(ring); 1047477eb7f9SFrançois Tigeot } 1048477eb7f9SFrançois Tigeot 104919c468b4SFrançois Tigeot static int bxt_init_workarounds(struct intel_engine_cs *ring) 105019c468b4SFrançois Tigeot { 105119c468b4SFrançois Tigeot struct drm_device *dev = ring->dev; 105219c468b4SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 105319c468b4SFrançois Tigeot 105419c468b4SFrançois Tigeot gen9_init_workarounds(ring); 105519c468b4SFrançois Tigeot 105619c468b4SFrançois Tigeot /* WaDisableThreadStallDopClockGating:bxt */ 105719c468b4SFrançois Tigeot WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN, 105819c468b4SFrançois Tigeot STALL_DOP_GATING_DISABLE); 105919c468b4SFrançois Tigeot 106019c468b4SFrançois Tigeot /* WaDisableSbeCacheDispatchPortSharing:bxt */ 106119c468b4SFrançois Tigeot if (INTEL_REVID(dev) <= BXT_REVID_B0) { 106219c468b4SFrançois Tigeot WA_SET_BIT_MASKED( 106319c468b4SFrançois Tigeot GEN7_HALF_SLICE_CHICKEN1, 106419c468b4SFrançois Tigeot GEN7_SBE_SS_CACHE_DISPATCH_PORT_SHARING_DISABLE); 106519c468b4SFrançois Tigeot } 106619c468b4SFrançois Tigeot 106719c468b4SFrançois Tigeot return 0; 106819c468b4SFrançois Tigeot } 106919c468b4SFrançois Tigeot 10702c9916cdSFrançois Tigeot int init_workarounds_ring(struct intel_engine_cs *ring) 10712c9916cdSFrançois Tigeot { 10722c9916cdSFrançois Tigeot struct drm_device *dev = ring->dev; 10732c9916cdSFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 10742c9916cdSFrançois Tigeot 10752c9916cdSFrançois Tigeot WARN_ON(ring->id != RCS); 10762c9916cdSFrançois Tigeot 10772c9916cdSFrançois Tigeot dev_priv->workarounds.count = 0; 10782c9916cdSFrançois Tigeot 10792c9916cdSFrançois Tigeot if (IS_BROADWELL(dev)) 10802c9916cdSFrançois Tigeot return bdw_init_workarounds(ring); 10812c9916cdSFrançois Tigeot 10822c9916cdSFrançois Tigeot if (IS_CHERRYVIEW(dev)) 10832c9916cdSFrançois Tigeot return chv_init_workarounds(ring); 10841b13d190SFrançois Tigeot 1085477eb7f9SFrançois Tigeot if (IS_SKYLAKE(dev)) 1086477eb7f9SFrançois Tigeot return skl_init_workarounds(ring); 108719c468b4SFrançois Tigeot 108819c468b4SFrançois Tigeot if (IS_BROXTON(dev)) 108919c468b4SFrançois Tigeot return bxt_init_workarounds(ring); 1090477eb7f9SFrançois Tigeot 10911b13d190SFrançois Tigeot return 0; 10921b13d190SFrançois Tigeot } 10931b13d190SFrançois Tigeot 1094ba55f2f5SFrançois Tigeot static int init_render_ring(struct intel_engine_cs *ring) 1095e3adcf8fSFrançois Tigeot { 1096e3adcf8fSFrançois Tigeot struct drm_device *dev = ring->dev; 1097e3adcf8fSFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 1098e3adcf8fSFrançois Tigeot int ret = init_ring_common(ring); 109924edb884SFrançois Tigeot if (ret) 110024edb884SFrançois Tigeot return ret; 1101e3adcf8fSFrançois Tigeot 1102ba55f2f5SFrançois Tigeot /* WaTimedSingleVertexDispatch:cl,bw,ctg,elk,ilk,snb */ 1103ba55f2f5SFrançois Tigeot if (INTEL_INFO(dev)->gen >= 4 && INTEL_INFO(dev)->gen < 7) 1104f4e1c372SFrançois Tigeot I915_WRITE(MI_MODE, _MASKED_BIT_ENABLE(VS_TIMER_DISPATCH)); 1105f4e1c372SFrançois Tigeot 1106f4e1c372SFrançois Tigeot /* We need to disable the AsyncFlip performance optimisations in order 1107f4e1c372SFrançois Tigeot * to use MI_WAIT_FOR_EVENT within the CS. It should already be 1108f4e1c372SFrançois Tigeot * programmed to '1' on all products. 11095d0b1887SFrançois Tigeot * 1110ba55f2f5SFrançois Tigeot * WaDisableAsyncFlipPerfMode:snb,ivb,hsw,vlv,bdw,chv 1111f4e1c372SFrançois Tigeot */ 11122c9916cdSFrançois Tigeot if (INTEL_INFO(dev)->gen >= 6 && INTEL_INFO(dev)->gen < 9) 1113f4e1c372SFrançois Tigeot I915_WRITE(MI_MODE, _MASKED_BIT_ENABLE(ASYNC_FLIP_PERF_DISABLE)); 1114f4e1c372SFrançois Tigeot 1115f4e1c372SFrançois Tigeot /* Required for the hardware to program scanline values for waiting */ 1116ba55f2f5SFrançois Tigeot /* WaEnableFlushTlbInvalidationMode:snb */ 1117f4e1c372SFrançois Tigeot if (INTEL_INFO(dev)->gen == 6) 1118f4e1c372SFrançois Tigeot I915_WRITE(GFX_MODE, 1119ba55f2f5SFrançois Tigeot _MASKED_BIT_ENABLE(GFX_TLB_INVALIDATE_EXPLICIT)); 1120f4e1c372SFrançois Tigeot 1121ba55f2f5SFrançois Tigeot /* WaBCSVCSTlbInvalidationMode:ivb,vlv,hsw */ 1122e3adcf8fSFrançois Tigeot if (IS_GEN7(dev)) 1123e3adcf8fSFrançois Tigeot I915_WRITE(GFX_MODE_GEN7, 1124ba55f2f5SFrançois Tigeot _MASKED_BIT_ENABLE(GFX_TLB_INVALIDATE_EXPLICIT) | 1125f4e1c372SFrançois Tigeot _MASKED_BIT_ENABLE(GFX_REPLAY_MODE)); 1126e3adcf8fSFrançois Tigeot 1127e3adcf8fSFrançois Tigeot if (IS_GEN6(dev)) { 1128e3adcf8fSFrançois Tigeot /* From the Sandybridge PRM, volume 1 part 3, page 24: 1129e3adcf8fSFrançois Tigeot * "If this bit is set, STCunit will have LRA as replacement 1130e3adcf8fSFrançois Tigeot * policy. [...] This bit must be reset. LRA replacement 1131e3adcf8fSFrançois Tigeot * policy is not supported." 1132e3adcf8fSFrançois Tigeot */ 1133e3adcf8fSFrançois Tigeot I915_WRITE(CACHE_MODE_0, 1134f4e1c372SFrançois Tigeot _MASKED_BIT_DISABLE(CM0_STC_EVICT_DISABLE_LRA_SNB)); 1135e3adcf8fSFrançois Tigeot } 1136e3adcf8fSFrançois Tigeot 1137f4e1c372SFrançois Tigeot if (INTEL_INFO(dev)->gen >= 6) 1138f4e1c372SFrançois Tigeot I915_WRITE(INSTPM, _MASKED_BIT_ENABLE(INSTPM_FORCE_ORDERING)); 1139f4e1c372SFrançois Tigeot 11409edbd4a0SFrançois Tigeot if (HAS_L3_DPF(dev)) 11419edbd4a0SFrançois Tigeot I915_WRITE_IMR(ring, ~GT_PARITY_ERROR(dev)); 1142e3adcf8fSFrançois Tigeot 11432c9916cdSFrançois Tigeot return init_workarounds_ring(ring); 1144e3adcf8fSFrançois Tigeot } 1145e3adcf8fSFrançois Tigeot 1146ba55f2f5SFrançois Tigeot static void render_ring_cleanup(struct intel_engine_cs *ring) 1147e3adcf8fSFrançois Tigeot { 1148b5c29a34SFrançois Tigeot struct drm_device *dev = ring->dev; 114924edb884SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 115024edb884SFrançois Tigeot 115124edb884SFrançois Tigeot if (dev_priv->semaphore_obj) { 115224edb884SFrançois Tigeot i915_gem_object_ggtt_unpin(dev_priv->semaphore_obj); 115324edb884SFrançois Tigeot drm_gem_object_unreference(&dev_priv->semaphore_obj->base); 115424edb884SFrançois Tigeot dev_priv->semaphore_obj = NULL; 115524edb884SFrançois Tigeot } 1156b5c29a34SFrançois Tigeot 11571b13d190SFrançois Tigeot intel_fini_pipe_control(ring); 1158e3adcf8fSFrançois Tigeot } 1159e3adcf8fSFrançois Tigeot 116024edb884SFrançois Tigeot static int gen8_rcs_signal(struct intel_engine_cs *signaller, 116124edb884SFrançois Tigeot unsigned int num_dwords) 116224edb884SFrançois Tigeot { 116324edb884SFrançois Tigeot #define MBOX_UPDATE_DWORDS 8 116424edb884SFrançois Tigeot struct drm_device *dev = signaller->dev; 116524edb884SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 116624edb884SFrançois Tigeot struct intel_engine_cs *waiter; 116724edb884SFrançois Tigeot int i, ret, num_rings; 116824edb884SFrançois Tigeot 116924edb884SFrançois Tigeot num_rings = hweight32(INTEL_INFO(dev)->ring_mask); 117024edb884SFrançois Tigeot num_dwords += (num_rings-1) * MBOX_UPDATE_DWORDS; 117124edb884SFrançois Tigeot #undef MBOX_UPDATE_DWORDS 117224edb884SFrançois Tigeot 117324edb884SFrançois Tigeot ret = intel_ring_begin(signaller, num_dwords); 117424edb884SFrançois Tigeot if (ret) 117524edb884SFrançois Tigeot return ret; 117624edb884SFrançois Tigeot 117724edb884SFrançois Tigeot for_each_ring(waiter, dev_priv, i) { 11782c9916cdSFrançois Tigeot u32 seqno; 117924edb884SFrançois Tigeot u64 gtt_offset = signaller->semaphore.signal_ggtt[i]; 118024edb884SFrançois Tigeot if (gtt_offset == MI_SEMAPHORE_SYNC_INVALID) 118124edb884SFrançois Tigeot continue; 118224edb884SFrançois Tigeot 11832c9916cdSFrançois Tigeot seqno = i915_gem_request_get_seqno( 11842c9916cdSFrançois Tigeot signaller->outstanding_lazy_request); 118524edb884SFrançois Tigeot intel_ring_emit(signaller, GFX_OP_PIPE_CONTROL(6)); 118624edb884SFrançois Tigeot intel_ring_emit(signaller, PIPE_CONTROL_GLOBAL_GTT_IVB | 118724edb884SFrançois Tigeot PIPE_CONTROL_QW_WRITE | 118824edb884SFrançois Tigeot PIPE_CONTROL_FLUSH_ENABLE); 118924edb884SFrançois Tigeot intel_ring_emit(signaller, lower_32_bits(gtt_offset)); 119024edb884SFrançois Tigeot intel_ring_emit(signaller, upper_32_bits(gtt_offset)); 11912c9916cdSFrançois Tigeot intel_ring_emit(signaller, seqno); 119224edb884SFrançois Tigeot intel_ring_emit(signaller, 0); 119324edb884SFrançois Tigeot intel_ring_emit(signaller, MI_SEMAPHORE_SIGNAL | 119424edb884SFrançois Tigeot MI_SEMAPHORE_TARGET(waiter->id)); 119524edb884SFrançois Tigeot intel_ring_emit(signaller, 0); 119624edb884SFrançois Tigeot } 119724edb884SFrançois Tigeot 119824edb884SFrançois Tigeot return 0; 119924edb884SFrançois Tigeot } 120024edb884SFrançois Tigeot 120124edb884SFrançois Tigeot static int gen8_xcs_signal(struct intel_engine_cs *signaller, 120224edb884SFrançois Tigeot unsigned int num_dwords) 120324edb884SFrançois Tigeot { 120424edb884SFrançois Tigeot #define MBOX_UPDATE_DWORDS 6 120524edb884SFrançois Tigeot struct drm_device *dev = signaller->dev; 120624edb884SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 120724edb884SFrançois Tigeot struct intel_engine_cs *waiter; 120824edb884SFrançois Tigeot int i, ret, num_rings; 120924edb884SFrançois Tigeot 121024edb884SFrançois Tigeot num_rings = hweight32(INTEL_INFO(dev)->ring_mask); 121124edb884SFrançois Tigeot num_dwords += (num_rings-1) * MBOX_UPDATE_DWORDS; 121224edb884SFrançois Tigeot #undef MBOX_UPDATE_DWORDS 121324edb884SFrançois Tigeot 121424edb884SFrançois Tigeot ret = intel_ring_begin(signaller, num_dwords); 121524edb884SFrançois Tigeot if (ret) 121624edb884SFrançois Tigeot return ret; 121724edb884SFrançois Tigeot 121824edb884SFrançois Tigeot for_each_ring(waiter, dev_priv, i) { 12192c9916cdSFrançois Tigeot u32 seqno; 122024edb884SFrançois Tigeot u64 gtt_offset = signaller->semaphore.signal_ggtt[i]; 122124edb884SFrançois Tigeot if (gtt_offset == MI_SEMAPHORE_SYNC_INVALID) 122224edb884SFrançois Tigeot continue; 122324edb884SFrançois Tigeot 12242c9916cdSFrançois Tigeot seqno = i915_gem_request_get_seqno( 12252c9916cdSFrançois Tigeot signaller->outstanding_lazy_request); 122624edb884SFrançois Tigeot intel_ring_emit(signaller, (MI_FLUSH_DW + 1) | 122724edb884SFrançois Tigeot MI_FLUSH_DW_OP_STOREDW); 122824edb884SFrançois Tigeot intel_ring_emit(signaller, lower_32_bits(gtt_offset) | 122924edb884SFrançois Tigeot MI_FLUSH_DW_USE_GTT); 123024edb884SFrançois Tigeot intel_ring_emit(signaller, upper_32_bits(gtt_offset)); 12312c9916cdSFrançois Tigeot intel_ring_emit(signaller, seqno); 123224edb884SFrançois Tigeot intel_ring_emit(signaller, MI_SEMAPHORE_SIGNAL | 123324edb884SFrançois Tigeot MI_SEMAPHORE_TARGET(waiter->id)); 123424edb884SFrançois Tigeot intel_ring_emit(signaller, 0); 123524edb884SFrançois Tigeot } 123624edb884SFrançois Tigeot 123724edb884SFrançois Tigeot return 0; 123824edb884SFrançois Tigeot } 123924edb884SFrançois Tigeot 1240ba55f2f5SFrançois Tigeot static int gen6_signal(struct intel_engine_cs *signaller, 1241ba55f2f5SFrançois Tigeot unsigned int num_dwords) 1242e3adcf8fSFrançois Tigeot { 1243ba55f2f5SFrançois Tigeot struct drm_device *dev = signaller->dev; 1244ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 1245ba55f2f5SFrançois Tigeot struct intel_engine_cs *useless; 124624edb884SFrançois Tigeot int i, ret, num_rings; 1247ba55f2f5SFrançois Tigeot 124824edb884SFrançois Tigeot #define MBOX_UPDATE_DWORDS 3 124924edb884SFrançois Tigeot num_rings = hweight32(INTEL_INFO(dev)->ring_mask); 125024edb884SFrançois Tigeot num_dwords += round_up((num_rings-1) * MBOX_UPDATE_DWORDS, 2); 125124edb884SFrançois Tigeot #undef MBOX_UPDATE_DWORDS 1252ba55f2f5SFrançois Tigeot 1253ba55f2f5SFrançois Tigeot ret = intel_ring_begin(signaller, num_dwords); 1254ba55f2f5SFrançois Tigeot if (ret) 1255ba55f2f5SFrançois Tigeot return ret; 1256ba55f2f5SFrançois Tigeot 1257ba55f2f5SFrançois Tigeot for_each_ring(useless, dev_priv, i) { 1258ba55f2f5SFrançois Tigeot u32 mbox_reg = signaller->semaphore.mbox.signal[i]; 1259ba55f2f5SFrançois Tigeot if (mbox_reg != GEN6_NOSYNC) { 12602c9916cdSFrançois Tigeot u32 seqno = i915_gem_request_get_seqno( 12612c9916cdSFrançois Tigeot signaller->outstanding_lazy_request); 1262ba55f2f5SFrançois Tigeot intel_ring_emit(signaller, MI_LOAD_REGISTER_IMM(1)); 1263ba55f2f5SFrançois Tigeot intel_ring_emit(signaller, mbox_reg); 12642c9916cdSFrançois Tigeot intel_ring_emit(signaller, seqno); 1265ba55f2f5SFrançois Tigeot } 1266ba55f2f5SFrançois Tigeot } 1267ba55f2f5SFrançois Tigeot 126824edb884SFrançois Tigeot /* If num_dwords was rounded, make sure the tail pointer is correct */ 126924edb884SFrançois Tigeot if (num_rings % 2 == 0) 127024edb884SFrançois Tigeot intel_ring_emit(signaller, MI_NOOP); 127124edb884SFrançois Tigeot 1272ba55f2f5SFrançois Tigeot return 0; 1273e3adcf8fSFrançois Tigeot } 1274e3adcf8fSFrançois Tigeot 1275e3adcf8fSFrançois Tigeot /** 1276e3adcf8fSFrançois Tigeot * gen6_add_request - Update the semaphore mailbox registers 1277e3adcf8fSFrançois Tigeot * 1278e3adcf8fSFrançois Tigeot * @ring - ring that is adding a request 1279e3adcf8fSFrançois Tigeot * @seqno - return seqno stuck into the ring 1280e3adcf8fSFrançois Tigeot * 1281e3adcf8fSFrançois Tigeot * Update the mailbox registers in the *other* rings with the current seqno. 1282e3adcf8fSFrançois Tigeot * This acts like a signal in the canonical semaphore. 1283e3adcf8fSFrançois Tigeot */ 1284e3adcf8fSFrançois Tigeot static int 1285ba55f2f5SFrançois Tigeot gen6_add_request(struct intel_engine_cs *ring) 1286e3adcf8fSFrançois Tigeot { 1287ba55f2f5SFrançois Tigeot int ret; 1288e3adcf8fSFrançois Tigeot 128924edb884SFrançois Tigeot if (ring->semaphore.signal) 1290ba55f2f5SFrançois Tigeot ret = ring->semaphore.signal(ring, 4); 129124edb884SFrançois Tigeot else 129224edb884SFrançois Tigeot ret = intel_ring_begin(ring, 4); 129324edb884SFrançois Tigeot 12949edbd4a0SFrançois Tigeot if (ret) 12959edbd4a0SFrançois Tigeot return ret; 12969edbd4a0SFrançois Tigeot 1297e3adcf8fSFrançois Tigeot intel_ring_emit(ring, MI_STORE_DWORD_INDEX); 1298e3adcf8fSFrançois Tigeot intel_ring_emit(ring, I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT); 12992c9916cdSFrançois Tigeot intel_ring_emit(ring, 13002c9916cdSFrançois Tigeot i915_gem_request_get_seqno(ring->outstanding_lazy_request)); 1301e3adcf8fSFrançois Tigeot intel_ring_emit(ring, MI_USER_INTERRUPT); 13029edbd4a0SFrançois Tigeot __intel_ring_advance(ring); 1303e3adcf8fSFrançois Tigeot 1304e3adcf8fSFrançois Tigeot return 0; 1305e3adcf8fSFrançois Tigeot } 1306e3adcf8fSFrançois Tigeot 1307a2fdbec6SFrançois Tigeot static inline bool i915_gem_has_seqno_wrapped(struct drm_device *dev, 1308a2fdbec6SFrançois Tigeot u32 seqno) 1309a2fdbec6SFrançois Tigeot { 1310a2fdbec6SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 1311a2fdbec6SFrançois Tigeot return dev_priv->last_seqno < seqno; 1312a2fdbec6SFrançois Tigeot } 1313a2fdbec6SFrançois Tigeot 1314e3adcf8fSFrançois Tigeot /** 1315e3adcf8fSFrançois Tigeot * intel_ring_sync - sync the waiter to the signaller on seqno 1316e3adcf8fSFrançois Tigeot * 1317e3adcf8fSFrançois Tigeot * @waiter - ring that is waiting 1318e3adcf8fSFrançois Tigeot * @signaller - ring which has, or will signal 1319e3adcf8fSFrançois Tigeot * @seqno - seqno which the waiter will block on 1320e3adcf8fSFrançois Tigeot */ 132124edb884SFrançois Tigeot 132224edb884SFrançois Tigeot static int 132324edb884SFrançois Tigeot gen8_ring_sync(struct intel_engine_cs *waiter, 132424edb884SFrançois Tigeot struct intel_engine_cs *signaller, 132524edb884SFrançois Tigeot u32 seqno) 132624edb884SFrançois Tigeot { 132724edb884SFrançois Tigeot struct drm_i915_private *dev_priv = waiter->dev->dev_private; 132824edb884SFrançois Tigeot int ret; 132924edb884SFrançois Tigeot 133024edb884SFrançois Tigeot ret = intel_ring_begin(waiter, 4); 133124edb884SFrançois Tigeot if (ret) 133224edb884SFrançois Tigeot return ret; 133324edb884SFrançois Tigeot 133424edb884SFrançois Tigeot intel_ring_emit(waiter, MI_SEMAPHORE_WAIT | 133524edb884SFrançois Tigeot MI_SEMAPHORE_GLOBAL_GTT | 133624edb884SFrançois Tigeot MI_SEMAPHORE_POLL | 133724edb884SFrançois Tigeot MI_SEMAPHORE_SAD_GTE_SDD); 133824edb884SFrançois Tigeot intel_ring_emit(waiter, seqno); 133924edb884SFrançois Tigeot intel_ring_emit(waiter, 134024edb884SFrançois Tigeot lower_32_bits(GEN8_WAIT_OFFSET(waiter, signaller->id))); 134124edb884SFrançois Tigeot intel_ring_emit(waiter, 134224edb884SFrançois Tigeot upper_32_bits(GEN8_WAIT_OFFSET(waiter, signaller->id))); 134324edb884SFrançois Tigeot intel_ring_advance(waiter); 134424edb884SFrançois Tigeot return 0; 134524edb884SFrançois Tigeot } 134624edb884SFrançois Tigeot 1347e3adcf8fSFrançois Tigeot static int 1348ba55f2f5SFrançois Tigeot gen6_ring_sync(struct intel_engine_cs *waiter, 1349ba55f2f5SFrançois Tigeot struct intel_engine_cs *signaller, 1350e3adcf8fSFrançois Tigeot u32 seqno) 1351e3adcf8fSFrançois Tigeot { 1352e3adcf8fSFrançois Tigeot u32 dw1 = MI_SEMAPHORE_MBOX | 1353e3adcf8fSFrançois Tigeot MI_SEMAPHORE_COMPARE | 1354e3adcf8fSFrançois Tigeot MI_SEMAPHORE_REGISTER; 1355ba55f2f5SFrançois Tigeot u32 wait_mbox = signaller->semaphore.mbox.wait[waiter->id]; 1356ba55f2f5SFrançois Tigeot int ret; 1357e3adcf8fSFrançois Tigeot 1358686a02f1SFrançois Tigeot /* Throughout all of the GEM code, seqno passed implies our current 1359686a02f1SFrançois Tigeot * seqno is >= the last seqno executed. However for hardware the 1360686a02f1SFrançois Tigeot * comparison is strictly greater than. 1361686a02f1SFrançois Tigeot */ 1362686a02f1SFrançois Tigeot seqno -= 1; 1363686a02f1SFrançois Tigeot 1364ba55f2f5SFrançois Tigeot WARN_ON(wait_mbox == MI_SEMAPHORE_SYNC_INVALID); 1365686a02f1SFrançois Tigeot 1366e3adcf8fSFrançois Tigeot ret = intel_ring_begin(waiter, 4); 1367e3adcf8fSFrançois Tigeot if (ret) 1368e3adcf8fSFrançois Tigeot return ret; 1369e3adcf8fSFrançois Tigeot 1370a2fdbec6SFrançois Tigeot /* If seqno wrap happened, omit the wait with no-ops */ 1371a2fdbec6SFrançois Tigeot if (likely(!i915_gem_has_seqno_wrapped(waiter->dev, seqno))) { 1372ba55f2f5SFrançois Tigeot intel_ring_emit(waiter, dw1 | wait_mbox); 1373e3adcf8fSFrançois Tigeot intel_ring_emit(waiter, seqno); 1374e3adcf8fSFrançois Tigeot intel_ring_emit(waiter, 0); 1375e3adcf8fSFrançois Tigeot intel_ring_emit(waiter, MI_NOOP); 1376a2fdbec6SFrançois Tigeot } else { 1377a2fdbec6SFrançois Tigeot intel_ring_emit(waiter, MI_NOOP); 1378a2fdbec6SFrançois Tigeot intel_ring_emit(waiter, MI_NOOP); 1379a2fdbec6SFrançois Tigeot intel_ring_emit(waiter, MI_NOOP); 1380a2fdbec6SFrançois Tigeot intel_ring_emit(waiter, MI_NOOP); 1381a2fdbec6SFrançois Tigeot } 1382e3adcf8fSFrançois Tigeot intel_ring_advance(waiter); 1383e3adcf8fSFrançois Tigeot 1384e3adcf8fSFrançois Tigeot return 0; 1385e3adcf8fSFrançois Tigeot } 1386e3adcf8fSFrançois Tigeot 1387e3adcf8fSFrançois Tigeot #define PIPE_CONTROL_FLUSH(ring__, addr__) \ 1388e3adcf8fSFrançois Tigeot do { \ 1389e3adcf8fSFrançois Tigeot intel_ring_emit(ring__, GFX_OP_PIPE_CONTROL(4) | PIPE_CONTROL_QW_WRITE | \ 1390e3adcf8fSFrançois Tigeot PIPE_CONTROL_DEPTH_STALL); \ 1391e3adcf8fSFrançois Tigeot intel_ring_emit(ring__, (addr__) | PIPE_CONTROL_GLOBAL_GTT); \ 1392e3adcf8fSFrançois Tigeot intel_ring_emit(ring__, 0); \ 1393e3adcf8fSFrançois Tigeot intel_ring_emit(ring__, 0); \ 1394e3adcf8fSFrançois Tigeot } while (0) 1395e3adcf8fSFrançois Tigeot 1396e3adcf8fSFrançois Tigeot static int 1397ba55f2f5SFrançois Tigeot pc_render_add_request(struct intel_engine_cs *ring) 1398e3adcf8fSFrançois Tigeot { 1399ba55f2f5SFrançois Tigeot u32 scratch_addr = ring->scratch.gtt_offset + 2 * CACHELINE_BYTES; 1400e3adcf8fSFrançois Tigeot int ret; 1401e3adcf8fSFrançois Tigeot 1402e3adcf8fSFrançois Tigeot /* For Ironlake, MI_USER_INTERRUPT was deprecated and apparently 1403e3adcf8fSFrançois Tigeot * incoherent with writes to memory, i.e. completely fubar, 1404e3adcf8fSFrançois Tigeot * so we need to use PIPE_NOTIFY instead. 1405e3adcf8fSFrançois Tigeot * 1406e3adcf8fSFrançois Tigeot * However, we also need to workaround the qword write 1407e3adcf8fSFrançois Tigeot * incoherence by flushing the 6 PIPE_NOTIFY buffers out to 1408e3adcf8fSFrançois Tigeot * memory before requesting an interrupt. 1409e3adcf8fSFrançois Tigeot */ 1410e3adcf8fSFrançois Tigeot ret = intel_ring_begin(ring, 32); 1411e3adcf8fSFrançois Tigeot if (ret) 1412e3adcf8fSFrançois Tigeot return ret; 1413e3adcf8fSFrançois Tigeot 1414e3adcf8fSFrançois Tigeot intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(4) | PIPE_CONTROL_QW_WRITE | 1415e3adcf8fSFrançois Tigeot PIPE_CONTROL_WRITE_FLUSH | 1416e3adcf8fSFrançois Tigeot PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE); 14179edbd4a0SFrançois Tigeot intel_ring_emit(ring, ring->scratch.gtt_offset | PIPE_CONTROL_GLOBAL_GTT); 14182c9916cdSFrançois Tigeot intel_ring_emit(ring, 14192c9916cdSFrançois Tigeot i915_gem_request_get_seqno(ring->outstanding_lazy_request)); 1420e3adcf8fSFrançois Tigeot intel_ring_emit(ring, 0); 1421e3adcf8fSFrançois Tigeot PIPE_CONTROL_FLUSH(ring, scratch_addr); 1422ba55f2f5SFrançois Tigeot scratch_addr += 2 * CACHELINE_BYTES; /* write to separate cachelines */ 1423e3adcf8fSFrançois Tigeot PIPE_CONTROL_FLUSH(ring, scratch_addr); 1424ba55f2f5SFrançois Tigeot scratch_addr += 2 * CACHELINE_BYTES; 1425e3adcf8fSFrançois Tigeot PIPE_CONTROL_FLUSH(ring, scratch_addr); 1426ba55f2f5SFrançois Tigeot scratch_addr += 2 * CACHELINE_BYTES; 1427e3adcf8fSFrançois Tigeot PIPE_CONTROL_FLUSH(ring, scratch_addr); 1428ba55f2f5SFrançois Tigeot scratch_addr += 2 * CACHELINE_BYTES; 1429e3adcf8fSFrançois Tigeot PIPE_CONTROL_FLUSH(ring, scratch_addr); 1430ba55f2f5SFrançois Tigeot scratch_addr += 2 * CACHELINE_BYTES; 1431e3adcf8fSFrançois Tigeot PIPE_CONTROL_FLUSH(ring, scratch_addr); 1432b5c29a34SFrançois Tigeot 1433e3adcf8fSFrançois Tigeot intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(4) | PIPE_CONTROL_QW_WRITE | 1434e3adcf8fSFrançois Tigeot PIPE_CONTROL_WRITE_FLUSH | 1435e3adcf8fSFrançois Tigeot PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE | 1436e3adcf8fSFrançois Tigeot PIPE_CONTROL_NOTIFY); 14379edbd4a0SFrançois Tigeot intel_ring_emit(ring, ring->scratch.gtt_offset | PIPE_CONTROL_GLOBAL_GTT); 14382c9916cdSFrançois Tigeot intel_ring_emit(ring, 14392c9916cdSFrançois Tigeot i915_gem_request_get_seqno(ring->outstanding_lazy_request)); 1440e3adcf8fSFrançois Tigeot intel_ring_emit(ring, 0); 14419edbd4a0SFrançois Tigeot __intel_ring_advance(ring); 1442e3adcf8fSFrançois Tigeot 1443e3adcf8fSFrançois Tigeot return 0; 1444e3adcf8fSFrançois Tigeot } 1445e3adcf8fSFrançois Tigeot 1446e3adcf8fSFrançois Tigeot static u32 1447ba55f2f5SFrançois Tigeot gen6_ring_get_seqno(struct intel_engine_cs *ring, bool lazy_coherency) 1448e3adcf8fSFrançois Tigeot { 1449e3adcf8fSFrançois Tigeot /* Workaround to force correct ordering between irq and seqno writes on 1450e3adcf8fSFrançois Tigeot * ivb (and maybe also on snb) by reading from a CS register (like 1451e3adcf8fSFrançois Tigeot * ACTHD) before reading the status page. */ 1452ba55f2f5SFrançois Tigeot if (!lazy_coherency) { 1453ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = ring->dev->dev_private; 1454ba55f2f5SFrançois Tigeot POSTING_READ(RING_ACTHD(ring->mmio_base)); 1455ba55f2f5SFrançois Tigeot } 1456ba55f2f5SFrançois Tigeot 1457e3adcf8fSFrançois Tigeot return intel_read_status_page(ring, I915_GEM_HWS_INDEX); 1458e3adcf8fSFrançois Tigeot } 1459e3adcf8fSFrançois Tigeot 1460b030f26bSFrançois Tigeot static u32 1461ba55f2f5SFrançois Tigeot ring_get_seqno(struct intel_engine_cs *ring, bool lazy_coherency) 1462e3adcf8fSFrançois Tigeot { 1463e3adcf8fSFrançois Tigeot return intel_read_status_page(ring, I915_GEM_HWS_INDEX); 1464e3adcf8fSFrançois Tigeot } 1465e3adcf8fSFrançois Tigeot 1466a2fdbec6SFrançois Tigeot static void 1467ba55f2f5SFrançois Tigeot ring_set_seqno(struct intel_engine_cs *ring, u32 seqno) 1468a2fdbec6SFrançois Tigeot { 1469a2fdbec6SFrançois Tigeot intel_write_status_page(ring, I915_GEM_HWS_INDEX, seqno); 1470a2fdbec6SFrançois Tigeot } 1471a2fdbec6SFrançois Tigeot 1472b030f26bSFrançois Tigeot static u32 1473ba55f2f5SFrançois Tigeot pc_render_get_seqno(struct intel_engine_cs *ring, bool lazy_coherency) 1474e3adcf8fSFrançois Tigeot { 14759edbd4a0SFrançois Tigeot return ring->scratch.cpu_page[0]; 1476e3adcf8fSFrançois Tigeot } 1477e3adcf8fSFrançois Tigeot 1478a2fdbec6SFrançois Tigeot static void 1479ba55f2f5SFrançois Tigeot pc_render_set_seqno(struct intel_engine_cs *ring, u32 seqno) 1480a2fdbec6SFrançois Tigeot { 14819edbd4a0SFrançois Tigeot ring->scratch.cpu_page[0] = seqno; 1482a2fdbec6SFrançois Tigeot } 1483a2fdbec6SFrançois Tigeot 1484e3adcf8fSFrançois Tigeot static bool 1485ba55f2f5SFrançois Tigeot gen5_ring_get_irq(struct intel_engine_cs *ring) 1486e3adcf8fSFrançois Tigeot { 1487e3adcf8fSFrançois Tigeot struct drm_device *dev = ring->dev; 1488ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 1489e3adcf8fSFrançois Tigeot 14902c9916cdSFrançois Tigeot if (WARN_ON(!intel_irqs_enabled(dev_priv))) 1491e3adcf8fSFrançois Tigeot return false; 1492e3adcf8fSFrançois Tigeot 149302727ecdSFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_EXCLUSIVE); 14949edbd4a0SFrançois Tigeot if (ring->irq_refcount++ == 0) 149524edb884SFrançois Tigeot gen5_enable_gt_irq(dev_priv, ring->irq_enable_mask); 149602727ecdSFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_RELEASE); 1497e3adcf8fSFrançois Tigeot 1498e3adcf8fSFrançois Tigeot return true; 1499e3adcf8fSFrançois Tigeot } 1500e3adcf8fSFrançois Tigeot 1501e3adcf8fSFrançois Tigeot static void 1502ba55f2f5SFrançois Tigeot gen5_ring_put_irq(struct intel_engine_cs *ring) 1503e3adcf8fSFrançois Tigeot { 1504e3adcf8fSFrançois Tigeot struct drm_device *dev = ring->dev; 1505ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 1506e3adcf8fSFrançois Tigeot 150702727ecdSFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_EXCLUSIVE); 15089edbd4a0SFrançois Tigeot if (--ring->irq_refcount == 0) 150924edb884SFrançois Tigeot gen5_disable_gt_irq(dev_priv, ring->irq_enable_mask); 1510686a02f1SFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_RELEASE); 1511686a02f1SFrançois Tigeot } 1512686a02f1SFrançois Tigeot 1513686a02f1SFrançois Tigeot static bool 1514ba55f2f5SFrançois Tigeot i9xx_ring_get_irq(struct intel_engine_cs *ring) 1515686a02f1SFrançois Tigeot { 1516686a02f1SFrançois Tigeot struct drm_device *dev = ring->dev; 1517ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 1518686a02f1SFrançois Tigeot 15192c9916cdSFrançois Tigeot if (!intel_irqs_enabled(dev_priv)) 1520686a02f1SFrançois Tigeot return false; 1521686a02f1SFrançois Tigeot 1522686a02f1SFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_EXCLUSIVE); 15239edbd4a0SFrançois Tigeot if (ring->irq_refcount++ == 0) { 1524686a02f1SFrançois Tigeot dev_priv->irq_mask &= ~ring->irq_enable_mask; 1525686a02f1SFrançois Tigeot I915_WRITE(IMR, dev_priv->irq_mask); 1526686a02f1SFrançois Tigeot POSTING_READ(IMR); 1527686a02f1SFrançois Tigeot } 1528686a02f1SFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_RELEASE); 1529686a02f1SFrançois Tigeot 1530686a02f1SFrançois Tigeot return true; 1531686a02f1SFrançois Tigeot } 1532686a02f1SFrançois Tigeot 1533686a02f1SFrançois Tigeot static void 1534ba55f2f5SFrançois Tigeot i9xx_ring_put_irq(struct intel_engine_cs *ring) 1535686a02f1SFrançois Tigeot { 1536686a02f1SFrançois Tigeot struct drm_device *dev = ring->dev; 1537ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 1538686a02f1SFrançois Tigeot 1539686a02f1SFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_EXCLUSIVE); 15409edbd4a0SFrançois Tigeot if (--ring->irq_refcount == 0) { 1541686a02f1SFrançois Tigeot dev_priv->irq_mask |= ring->irq_enable_mask; 1542686a02f1SFrançois Tigeot I915_WRITE(IMR, dev_priv->irq_mask); 1543686a02f1SFrançois Tigeot POSTING_READ(IMR); 1544686a02f1SFrançois Tigeot } 1545686a02f1SFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_RELEASE); 1546686a02f1SFrançois Tigeot } 1547686a02f1SFrançois Tigeot 1548686a02f1SFrançois Tigeot static bool 1549ba55f2f5SFrançois Tigeot i8xx_ring_get_irq(struct intel_engine_cs *ring) 1550686a02f1SFrançois Tigeot { 1551686a02f1SFrançois Tigeot struct drm_device *dev = ring->dev; 1552ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 1553686a02f1SFrançois Tigeot 15542c9916cdSFrançois Tigeot if (!intel_irqs_enabled(dev_priv)) 1555686a02f1SFrançois Tigeot return false; 1556686a02f1SFrançois Tigeot 1557686a02f1SFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_EXCLUSIVE); 15589edbd4a0SFrançois Tigeot if (ring->irq_refcount++ == 0) { 1559686a02f1SFrançois Tigeot dev_priv->irq_mask &= ~ring->irq_enable_mask; 1560686a02f1SFrançois Tigeot I915_WRITE16(IMR, dev_priv->irq_mask); 1561686a02f1SFrançois Tigeot POSTING_READ16(IMR); 1562686a02f1SFrançois Tigeot } 1563686a02f1SFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_RELEASE); 1564686a02f1SFrançois Tigeot 1565686a02f1SFrançois Tigeot return true; 1566686a02f1SFrançois Tigeot } 1567686a02f1SFrançois Tigeot 1568686a02f1SFrançois Tigeot static void 1569ba55f2f5SFrançois Tigeot i8xx_ring_put_irq(struct intel_engine_cs *ring) 1570686a02f1SFrançois Tigeot { 1571686a02f1SFrançois Tigeot struct drm_device *dev = ring->dev; 1572ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 1573686a02f1SFrançois Tigeot 1574686a02f1SFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_EXCLUSIVE); 15759edbd4a0SFrançois Tigeot if (--ring->irq_refcount == 0) { 1576686a02f1SFrançois Tigeot dev_priv->irq_mask |= ring->irq_enable_mask; 1577686a02f1SFrançois Tigeot I915_WRITE16(IMR, dev_priv->irq_mask); 1578686a02f1SFrançois Tigeot POSTING_READ16(IMR); 1579e3adcf8fSFrançois Tigeot } 158002727ecdSFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_RELEASE); 1581e3adcf8fSFrançois Tigeot } 1582e3adcf8fSFrançois Tigeot 1583e3adcf8fSFrançois Tigeot static int 1584ba55f2f5SFrançois Tigeot bsd_ring_flush(struct intel_engine_cs *ring, 1585b5c29a34SFrançois Tigeot u32 invalidate_domains, 1586b5c29a34SFrançois Tigeot u32 flush_domains) 1587e3adcf8fSFrançois Tigeot { 1588e3adcf8fSFrançois Tigeot int ret; 1589e3adcf8fSFrançois Tigeot 1590e3adcf8fSFrançois Tigeot ret = intel_ring_begin(ring, 2); 1591e3adcf8fSFrançois Tigeot if (ret) 1592e3adcf8fSFrançois Tigeot return ret; 1593e3adcf8fSFrançois Tigeot 1594e3adcf8fSFrançois Tigeot intel_ring_emit(ring, MI_FLUSH); 1595e3adcf8fSFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 1596e3adcf8fSFrançois Tigeot intel_ring_advance(ring); 1597e3adcf8fSFrançois Tigeot return 0; 1598e3adcf8fSFrançois Tigeot } 1599e3adcf8fSFrançois Tigeot 1600e3adcf8fSFrançois Tigeot static int 1601ba55f2f5SFrançois Tigeot i9xx_add_request(struct intel_engine_cs *ring) 1602e3adcf8fSFrançois Tigeot { 1603e3adcf8fSFrançois Tigeot int ret; 1604e3adcf8fSFrançois Tigeot 1605e3adcf8fSFrançois Tigeot ret = intel_ring_begin(ring, 4); 1606e3adcf8fSFrançois Tigeot if (ret) 1607e3adcf8fSFrançois Tigeot return ret; 1608e3adcf8fSFrançois Tigeot 1609e3adcf8fSFrançois Tigeot intel_ring_emit(ring, MI_STORE_DWORD_INDEX); 1610e3adcf8fSFrançois Tigeot intel_ring_emit(ring, I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT); 16112c9916cdSFrançois Tigeot intel_ring_emit(ring, 16122c9916cdSFrançois Tigeot i915_gem_request_get_seqno(ring->outstanding_lazy_request)); 1613e3adcf8fSFrançois Tigeot intel_ring_emit(ring, MI_USER_INTERRUPT); 16149edbd4a0SFrançois Tigeot __intel_ring_advance(ring); 1615e3adcf8fSFrançois Tigeot 1616e3adcf8fSFrançois Tigeot return 0; 1617e3adcf8fSFrançois Tigeot } 1618e3adcf8fSFrançois Tigeot 1619e3adcf8fSFrançois Tigeot static bool 1620ba55f2f5SFrançois Tigeot gen6_ring_get_irq(struct intel_engine_cs *ring) 1621e3adcf8fSFrançois Tigeot { 1622e3adcf8fSFrançois Tigeot struct drm_device *dev = ring->dev; 1623ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 1624e3adcf8fSFrançois Tigeot 16252c9916cdSFrançois Tigeot if (WARN_ON(!intel_irqs_enabled(dev_priv))) 1626e3adcf8fSFrançois Tigeot return false; 1627e3adcf8fSFrançois Tigeot 162802727ecdSFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_EXCLUSIVE); 16299edbd4a0SFrançois Tigeot if (ring->irq_refcount++ == 0) { 16309edbd4a0SFrançois Tigeot if (HAS_L3_DPF(dev) && ring->id == RCS) 16315d0b1887SFrançois Tigeot I915_WRITE_IMR(ring, 16325d0b1887SFrançois Tigeot ~(ring->irq_enable_mask | 16339edbd4a0SFrançois Tigeot GT_PARITY_ERROR(dev))); 1634686a02f1SFrançois Tigeot else 1635686a02f1SFrançois Tigeot I915_WRITE_IMR(ring, ~ring->irq_enable_mask); 163624edb884SFrançois Tigeot gen5_enable_gt_irq(dev_priv, ring->irq_enable_mask); 1637e3adcf8fSFrançois Tigeot } 163802727ecdSFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_RELEASE); 1639e3adcf8fSFrançois Tigeot 1640e3adcf8fSFrançois Tigeot return true; 1641e3adcf8fSFrançois Tigeot } 1642e3adcf8fSFrançois Tigeot 1643e3adcf8fSFrançois Tigeot static void 1644ba55f2f5SFrançois Tigeot gen6_ring_put_irq(struct intel_engine_cs *ring) 1645e3adcf8fSFrançois Tigeot { 1646e3adcf8fSFrançois Tigeot struct drm_device *dev = ring->dev; 1647ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 1648e3adcf8fSFrançois Tigeot 164902727ecdSFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_EXCLUSIVE); 16509edbd4a0SFrançois Tigeot if (--ring->irq_refcount == 0) { 16519edbd4a0SFrançois Tigeot if (HAS_L3_DPF(dev) && ring->id == RCS) 16529edbd4a0SFrançois Tigeot I915_WRITE_IMR(ring, ~GT_PARITY_ERROR(dev)); 1653686a02f1SFrançois Tigeot else 1654686a02f1SFrançois Tigeot I915_WRITE_IMR(ring, ~0); 165524edb884SFrançois Tigeot gen5_disable_gt_irq(dev_priv, ring->irq_enable_mask); 1656e3adcf8fSFrançois Tigeot } 165702727ecdSFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_RELEASE); 1658e3adcf8fSFrançois Tigeot } 1659e3adcf8fSFrançois Tigeot 16605d0b1887SFrançois Tigeot static bool 1661ba55f2f5SFrançois Tigeot hsw_vebox_get_irq(struct intel_engine_cs *ring) 16625d0b1887SFrançois Tigeot { 16635d0b1887SFrançois Tigeot struct drm_device *dev = ring->dev; 16645d0b1887SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 16655d0b1887SFrançois Tigeot 16662c9916cdSFrançois Tigeot if (WARN_ON(!intel_irqs_enabled(dev_priv))) 16675d0b1887SFrançois Tigeot return false; 16685d0b1887SFrançois Tigeot 16699edbd4a0SFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_EXCLUSIVE); 16709edbd4a0SFrançois Tigeot if (ring->irq_refcount++ == 0) { 16715d0b1887SFrançois Tigeot I915_WRITE_IMR(ring, ~ring->irq_enable_mask); 167224edb884SFrançois Tigeot gen6_enable_pm_irq(dev_priv, ring->irq_enable_mask); 16735d0b1887SFrançois Tigeot } 16749edbd4a0SFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_RELEASE); 16755d0b1887SFrançois Tigeot 16765d0b1887SFrançois Tigeot return true; 16775d0b1887SFrançois Tigeot } 16785d0b1887SFrançois Tigeot 16795d0b1887SFrançois Tigeot static void 1680ba55f2f5SFrançois Tigeot hsw_vebox_put_irq(struct intel_engine_cs *ring) 16815d0b1887SFrançois Tigeot { 16825d0b1887SFrançois Tigeot struct drm_device *dev = ring->dev; 16835d0b1887SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 16845d0b1887SFrançois Tigeot 16859edbd4a0SFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_EXCLUSIVE); 16869edbd4a0SFrançois Tigeot if (--ring->irq_refcount == 0) { 16875d0b1887SFrançois Tigeot I915_WRITE_IMR(ring, ~0); 168824edb884SFrançois Tigeot gen6_disable_pm_irq(dev_priv, ring->irq_enable_mask); 16895d0b1887SFrançois Tigeot } 16909edbd4a0SFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_RELEASE); 16919edbd4a0SFrançois Tigeot } 16929edbd4a0SFrançois Tigeot 16939edbd4a0SFrançois Tigeot static bool 1694ba55f2f5SFrançois Tigeot gen8_ring_get_irq(struct intel_engine_cs *ring) 16959edbd4a0SFrançois Tigeot { 16969edbd4a0SFrançois Tigeot struct drm_device *dev = ring->dev; 16979edbd4a0SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 16989edbd4a0SFrançois Tigeot 16992c9916cdSFrançois Tigeot if (WARN_ON(!intel_irqs_enabled(dev_priv))) 17009edbd4a0SFrançois Tigeot return false; 17019edbd4a0SFrançois Tigeot 17029edbd4a0SFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_EXCLUSIVE); 17039edbd4a0SFrançois Tigeot if (ring->irq_refcount++ == 0) { 17049edbd4a0SFrançois Tigeot if (HAS_L3_DPF(dev) && ring->id == RCS) { 17059edbd4a0SFrançois Tigeot I915_WRITE_IMR(ring, 17069edbd4a0SFrançois Tigeot ~(ring->irq_enable_mask | 17079edbd4a0SFrançois Tigeot GT_RENDER_L3_PARITY_ERROR_INTERRUPT)); 17089edbd4a0SFrançois Tigeot } else { 17099edbd4a0SFrançois Tigeot I915_WRITE_IMR(ring, ~ring->irq_enable_mask); 17109edbd4a0SFrançois Tigeot } 17119edbd4a0SFrançois Tigeot POSTING_READ(RING_IMR(ring->mmio_base)); 17129edbd4a0SFrançois Tigeot } 17139edbd4a0SFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_RELEASE); 17149edbd4a0SFrançois Tigeot 17159edbd4a0SFrançois Tigeot return true; 17169edbd4a0SFrançois Tigeot } 17179edbd4a0SFrançois Tigeot 17189edbd4a0SFrançois Tigeot static void 1719ba55f2f5SFrançois Tigeot gen8_ring_put_irq(struct intel_engine_cs *ring) 17209edbd4a0SFrançois Tigeot { 17219edbd4a0SFrançois Tigeot struct drm_device *dev = ring->dev; 17229edbd4a0SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 17239edbd4a0SFrançois Tigeot 17249edbd4a0SFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_EXCLUSIVE); 17259edbd4a0SFrançois Tigeot if (--ring->irq_refcount == 0) { 17269edbd4a0SFrançois Tigeot if (HAS_L3_DPF(dev) && ring->id == RCS) { 17279edbd4a0SFrançois Tigeot I915_WRITE_IMR(ring, 17289edbd4a0SFrançois Tigeot ~GT_RENDER_L3_PARITY_ERROR_INTERRUPT); 17299edbd4a0SFrançois Tigeot } else { 17309edbd4a0SFrançois Tigeot I915_WRITE_IMR(ring, ~0); 17319edbd4a0SFrançois Tigeot } 17329edbd4a0SFrançois Tigeot POSTING_READ(RING_IMR(ring->mmio_base)); 17339edbd4a0SFrançois Tigeot } 17349edbd4a0SFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_RELEASE); 17355d0b1887SFrançois Tigeot } 17365d0b1887SFrançois Tigeot 1737e3adcf8fSFrançois Tigeot static int 1738ba55f2f5SFrançois Tigeot i965_dispatch_execbuffer(struct intel_engine_cs *ring, 1739ba55f2f5SFrançois Tigeot u64 offset, u32 length, 1740477eb7f9SFrançois Tigeot unsigned dispatch_flags) 1741e3adcf8fSFrançois Tigeot { 1742e3adcf8fSFrançois Tigeot int ret; 1743e3adcf8fSFrançois Tigeot 1744e3adcf8fSFrançois Tigeot ret = intel_ring_begin(ring, 2); 1745e3adcf8fSFrançois Tigeot if (ret) 1746e3adcf8fSFrançois Tigeot return ret; 1747e3adcf8fSFrançois Tigeot 1748e3adcf8fSFrançois Tigeot intel_ring_emit(ring, 1749686a02f1SFrançois Tigeot MI_BATCH_BUFFER_START | 1750b5c29a34SFrançois Tigeot MI_BATCH_GTT | 1751477eb7f9SFrançois Tigeot (dispatch_flags & I915_DISPATCH_SECURE ? 1752477eb7f9SFrançois Tigeot 0 : MI_BATCH_NON_SECURE_I965)); 1753e3adcf8fSFrançois Tigeot intel_ring_emit(ring, offset); 1754e3adcf8fSFrançois Tigeot intel_ring_advance(ring); 1755e3adcf8fSFrançois Tigeot 1756e3adcf8fSFrançois Tigeot return 0; 1757e3adcf8fSFrançois Tigeot } 1758e3adcf8fSFrançois Tigeot 1759b5c29a34SFrançois Tigeot /* Just userspace ABI convention to limit the wa batch bo to a resonable size */ 1760b5c29a34SFrançois Tigeot #define I830_BATCH_LIMIT (256*1024) 176124edb884SFrançois Tigeot #define I830_TLB_ENTRIES (2) 176224edb884SFrançois Tigeot #define I830_WA_SIZE max(I830_TLB_ENTRIES*4096, I830_BATCH_LIMIT) 1763e3adcf8fSFrançois Tigeot static int 1764ba55f2f5SFrançois Tigeot i830_dispatch_execbuffer(struct intel_engine_cs *ring, 1765ba55f2f5SFrançois Tigeot u64 offset, u32 len, 1766477eb7f9SFrançois Tigeot unsigned dispatch_flags) 1767e3adcf8fSFrançois Tigeot { 176824edb884SFrançois Tigeot u32 cs_offset = ring->scratch.gtt_offset; 1769e3adcf8fSFrançois Tigeot int ret; 1770e3adcf8fSFrançois Tigeot 177124edb884SFrançois Tigeot ret = intel_ring_begin(ring, 6); 177224edb884SFrançois Tigeot if (ret) 177324edb884SFrançois Tigeot return ret; 177424edb884SFrançois Tigeot 177524edb884SFrançois Tigeot /* Evict the invalid PTE TLBs */ 177624edb884SFrançois Tigeot intel_ring_emit(ring, COLOR_BLT_CMD | BLT_WRITE_RGBA); 177724edb884SFrançois Tigeot intel_ring_emit(ring, BLT_DEPTH_32 | BLT_ROP_COLOR_COPY | 4096); 177824edb884SFrançois Tigeot intel_ring_emit(ring, I830_TLB_ENTRIES << 16 | 4); /* load each page */ 177924edb884SFrançois Tigeot intel_ring_emit(ring, cs_offset); 178024edb884SFrançois Tigeot intel_ring_emit(ring, 0xdeadbeef); 178124edb884SFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 178224edb884SFrançois Tigeot intel_ring_advance(ring); 178324edb884SFrançois Tigeot 1784477eb7f9SFrançois Tigeot if ((dispatch_flags & I915_DISPATCH_PINNED) == 0) { 178524edb884SFrançois Tigeot if (len > I830_BATCH_LIMIT) 178624edb884SFrançois Tigeot return -ENOSPC; 178724edb884SFrançois Tigeot 178824edb884SFrançois Tigeot ret = intel_ring_begin(ring, 6 + 2); 178924edb884SFrançois Tigeot if (ret) 179024edb884SFrançois Tigeot return ret; 179124edb884SFrançois Tigeot 179224edb884SFrançois Tigeot /* Blit the batch (which has now all relocs applied) to the 179324edb884SFrançois Tigeot * stable batch scratch bo area (so that the CS never 179424edb884SFrançois Tigeot * stumbles over its tlb invalidation bug) ... 179524edb884SFrançois Tigeot */ 179624edb884SFrançois Tigeot intel_ring_emit(ring, SRC_COPY_BLT_CMD | BLT_WRITE_RGBA); 179724edb884SFrançois Tigeot intel_ring_emit(ring, BLT_DEPTH_32 | BLT_ROP_SRC_COPY | 4096); 179824edb884SFrançois Tigeot intel_ring_emit(ring, DIV_ROUND_UP(len, 4096) << 16 | 4096); 179924edb884SFrançois Tigeot intel_ring_emit(ring, cs_offset); 180024edb884SFrançois Tigeot intel_ring_emit(ring, 4096); 180124edb884SFrançois Tigeot intel_ring_emit(ring, offset); 180224edb884SFrançois Tigeot 180324edb884SFrançois Tigeot intel_ring_emit(ring, MI_FLUSH); 180424edb884SFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 180524edb884SFrançois Tigeot intel_ring_advance(ring); 180624edb884SFrançois Tigeot 180724edb884SFrançois Tigeot /* ... and execute it. */ 180824edb884SFrançois Tigeot offset = cs_offset; 180924edb884SFrançois Tigeot } 181024edb884SFrançois Tigeot 1811e3adcf8fSFrançois Tigeot ret = intel_ring_begin(ring, 4); 1812e3adcf8fSFrançois Tigeot if (ret) 1813e3adcf8fSFrançois Tigeot return ret; 1814e3adcf8fSFrançois Tigeot 1815e3adcf8fSFrançois Tigeot intel_ring_emit(ring, MI_BATCH_BUFFER); 1816477eb7f9SFrançois Tigeot intel_ring_emit(ring, offset | (dispatch_flags & I915_DISPATCH_SECURE ? 1817477eb7f9SFrançois Tigeot 0 : MI_BATCH_NON_SECURE)); 1818e3adcf8fSFrançois Tigeot intel_ring_emit(ring, offset + len - 8); 1819b5c29a34SFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 1820686a02f1SFrançois Tigeot intel_ring_advance(ring); 1821686a02f1SFrançois Tigeot 1822686a02f1SFrançois Tigeot return 0; 1823686a02f1SFrançois Tigeot } 1824686a02f1SFrançois Tigeot 1825686a02f1SFrançois Tigeot static int 1826ba55f2f5SFrançois Tigeot i915_dispatch_execbuffer(struct intel_engine_cs *ring, 1827ba55f2f5SFrançois Tigeot u64 offset, u32 len, 1828477eb7f9SFrançois Tigeot unsigned dispatch_flags) 1829686a02f1SFrançois Tigeot { 1830686a02f1SFrançois Tigeot int ret; 1831686a02f1SFrançois Tigeot 1832e3adcf8fSFrançois Tigeot ret = intel_ring_begin(ring, 2); 1833e3adcf8fSFrançois Tigeot if (ret) 1834e3adcf8fSFrançois Tigeot return ret; 1835e3adcf8fSFrançois Tigeot 1836686a02f1SFrançois Tigeot intel_ring_emit(ring, MI_BATCH_BUFFER_START | MI_BATCH_GTT); 1837477eb7f9SFrançois Tigeot intel_ring_emit(ring, offset | (dispatch_flags & I915_DISPATCH_SECURE ? 1838477eb7f9SFrançois Tigeot 0 : MI_BATCH_NON_SECURE)); 1839e3adcf8fSFrançois Tigeot intel_ring_advance(ring); 1840e3adcf8fSFrançois Tigeot 1841e3adcf8fSFrançois Tigeot return 0; 1842e3adcf8fSFrançois Tigeot } 1843e3adcf8fSFrançois Tigeot 1844ba55f2f5SFrançois Tigeot static void cleanup_status_page(struct intel_engine_cs *ring) 1845e3adcf8fSFrançois Tigeot { 1846e3adcf8fSFrançois Tigeot struct drm_i915_gem_object *obj; 1847e3adcf8fSFrançois Tigeot 1848e3adcf8fSFrançois Tigeot obj = ring->status_page.obj; 1849e3adcf8fSFrançois Tigeot if (obj == NULL) 1850e3adcf8fSFrançois Tigeot return; 1851e3adcf8fSFrançois Tigeot 18529edbd4a0SFrançois Tigeot kunmap(obj->pages[0]); 1853ba55f2f5SFrançois Tigeot i915_gem_object_ggtt_unpin(obj); 1854e3adcf8fSFrançois Tigeot drm_gem_object_unreference(&obj->base); 1855e3adcf8fSFrançois Tigeot ring->status_page.obj = NULL; 1856e3adcf8fSFrançois Tigeot } 1857e3adcf8fSFrançois Tigeot 1858ba55f2f5SFrançois Tigeot static int init_status_page(struct intel_engine_cs *ring) 1859e3adcf8fSFrançois Tigeot { 1860e3adcf8fSFrançois Tigeot struct drm_i915_gem_object *obj; 1861ba55f2f5SFrançois Tigeot 1862ba55f2f5SFrançois Tigeot if ((obj = ring->status_page.obj) == NULL) { 186324edb884SFrançois Tigeot unsigned flags; 1864e3adcf8fSFrançois Tigeot int ret; 1865e3adcf8fSFrançois Tigeot 1866ba55f2f5SFrançois Tigeot obj = i915_gem_alloc_object(ring->dev, 4096); 1867e3adcf8fSFrançois Tigeot if (obj == NULL) { 1868e3adcf8fSFrançois Tigeot DRM_ERROR("Failed to allocate status page\n"); 1869ba55f2f5SFrançois Tigeot return -ENOMEM; 1870e3adcf8fSFrançois Tigeot } 1871e3adcf8fSFrançois Tigeot 1872ba55f2f5SFrançois Tigeot ret = i915_gem_object_set_cache_level(obj, I915_CACHE_LLC); 1873ba55f2f5SFrançois Tigeot if (ret) 1874e3adcf8fSFrançois Tigeot goto err_unref; 1875ba55f2f5SFrançois Tigeot 187624edb884SFrançois Tigeot flags = 0; 187724edb884SFrançois Tigeot if (!HAS_LLC(ring->dev)) 187824edb884SFrançois Tigeot /* On g33, we cannot place HWS above 256MiB, so 187924edb884SFrançois Tigeot * restrict its pinning to the low mappable arena. 188024edb884SFrançois Tigeot * Though this restriction is not documented for 188124edb884SFrançois Tigeot * gen4, gen5, or byt, they also behave similarly 188224edb884SFrançois Tigeot * and hang if the HWS is placed at the top of the 188324edb884SFrançois Tigeot * GTT. To generalise, it appears that all !llc 188424edb884SFrançois Tigeot * platforms have issues with us placing the HWS 188524edb884SFrançois Tigeot * above the mappable region (even though we never 188624edb884SFrançois Tigeot * actualy map it). 188724edb884SFrançois Tigeot */ 188824edb884SFrançois Tigeot flags |= PIN_MAPPABLE; 188924edb884SFrançois Tigeot ret = i915_gem_obj_ggtt_pin(obj, 4096, flags); 1890ba55f2f5SFrançois Tigeot if (ret) { 1891ba55f2f5SFrançois Tigeot err_unref: 1892ba55f2f5SFrançois Tigeot drm_gem_object_unreference(&obj->base); 1893ba55f2f5SFrançois Tigeot return ret; 1894ba55f2f5SFrançois Tigeot } 1895ba55f2f5SFrançois Tigeot 1896ba55f2f5SFrançois Tigeot ring->status_page.obj = obj; 1897e3adcf8fSFrançois Tigeot } 1898e3adcf8fSFrançois Tigeot 18999edbd4a0SFrançois Tigeot ring->status_page.gfx_addr = i915_gem_obj_ggtt_offset(obj); 1900f4f90b23SFrançois Tigeot ring->status_page.page_addr = kmap(obj->pages[0]); 1901e3adcf8fSFrançois Tigeot memset(ring->status_page.page_addr, 0, PAGE_SIZE); 1902e3adcf8fSFrançois Tigeot 1903b5c29a34SFrançois Tigeot DRM_DEBUG_DRIVER("%s hws offset: 0x%08x\n", 1904e3adcf8fSFrançois Tigeot ring->name, ring->status_page.gfx_addr); 1905e3adcf8fSFrançois Tigeot 1906e3adcf8fSFrançois Tigeot return 0; 1907e3adcf8fSFrançois Tigeot } 1908e3adcf8fSFrançois Tigeot 1909ba55f2f5SFrançois Tigeot static int init_phys_status_page(struct intel_engine_cs *ring) 1910686a02f1SFrançois Tigeot { 1911686a02f1SFrançois Tigeot struct drm_i915_private *dev_priv = ring->dev->dev_private; 1912686a02f1SFrançois Tigeot 1913686a02f1SFrançois Tigeot if (!dev_priv->status_page_dmah) { 1914686a02f1SFrançois Tigeot dev_priv->status_page_dmah = 1915b31e9d59SFrançois Tigeot drm_pci_alloc(ring->dev, PAGE_SIZE, PAGE_SIZE); 1916686a02f1SFrançois Tigeot if (!dev_priv->status_page_dmah) 1917686a02f1SFrançois Tigeot return -ENOMEM; 1918686a02f1SFrançois Tigeot } 1919686a02f1SFrançois Tigeot 1920686a02f1SFrançois Tigeot ring->status_page.page_addr = dev_priv->status_page_dmah->vaddr; 1921686a02f1SFrançois Tigeot memset(ring->status_page.page_addr, 0, PAGE_SIZE); 1922686a02f1SFrançois Tigeot 1923686a02f1SFrançois Tigeot return 0; 1924686a02f1SFrançois Tigeot } 1925686a02f1SFrançois Tigeot 19262c9916cdSFrançois Tigeot void intel_unpin_ringbuffer_obj(struct intel_ringbuffer *ringbuf) 19272c9916cdSFrançois Tigeot { 192824409b39SFrançois Tigeot iounmap(ringbuf->virtual_start); 19292c9916cdSFrançois Tigeot ringbuf->virtual_start = NULL; 19302c9916cdSFrançois Tigeot i915_gem_object_ggtt_unpin(ringbuf->obj); 19312c9916cdSFrançois Tigeot } 19322c9916cdSFrançois Tigeot 19332c9916cdSFrançois Tigeot int intel_pin_and_map_ringbuffer_obj(struct drm_device *dev, 19342c9916cdSFrançois Tigeot struct intel_ringbuffer *ringbuf) 19352c9916cdSFrançois Tigeot { 19362c9916cdSFrançois Tigeot struct drm_i915_private *dev_priv = to_i915(dev); 19372c9916cdSFrançois Tigeot struct drm_i915_gem_object *obj = ringbuf->obj; 19382c9916cdSFrançois Tigeot int ret; 19392c9916cdSFrançois Tigeot 19402c9916cdSFrançois Tigeot ret = i915_gem_obj_ggtt_pin(obj, PAGE_SIZE, PIN_MAPPABLE); 19412c9916cdSFrançois Tigeot if (ret) 19422c9916cdSFrançois Tigeot return ret; 19432c9916cdSFrançois Tigeot 19442c9916cdSFrançois Tigeot ret = i915_gem_object_set_to_gtt_domain(obj, true); 19452c9916cdSFrançois Tigeot if (ret) { 19462c9916cdSFrançois Tigeot i915_gem_object_ggtt_unpin(obj); 19472c9916cdSFrançois Tigeot return ret; 19482c9916cdSFrançois Tigeot } 19492c9916cdSFrançois Tigeot 19502c9916cdSFrançois Tigeot ringbuf->virtual_start = ioremap_wc(dev_priv->gtt.mappable_base + 19512c9916cdSFrançois Tigeot i915_gem_obj_ggtt_offset(obj), ringbuf->size); 19522c9916cdSFrançois Tigeot if (ringbuf->virtual_start == NULL) { 19532c9916cdSFrançois Tigeot i915_gem_object_ggtt_unpin(obj); 19542c9916cdSFrançois Tigeot return -EINVAL; 19552c9916cdSFrançois Tigeot } 19562c9916cdSFrançois Tigeot 19572c9916cdSFrançois Tigeot return 0; 19582c9916cdSFrançois Tigeot } 19592c9916cdSFrançois Tigeot 19601b13d190SFrançois Tigeot void intel_destroy_ringbuffer_obj(struct intel_ringbuffer *ringbuf) 1961e3adcf8fSFrançois Tigeot { 196224edb884SFrançois Tigeot drm_gem_object_unreference(&ringbuf->obj->base); 196324edb884SFrançois Tigeot ringbuf->obj = NULL; 196424edb884SFrançois Tigeot } 196524edb884SFrançois Tigeot 19661b13d190SFrançois Tigeot int intel_alloc_ringbuffer_obj(struct drm_device *dev, 196724edb884SFrançois Tigeot struct intel_ringbuffer *ringbuf) 196824edb884SFrançois Tigeot { 1969e3adcf8fSFrançois Tigeot struct drm_i915_gem_object *obj; 1970e3adcf8fSFrançois Tigeot 1971a2fdbec6SFrançois Tigeot obj = NULL; 1972a2fdbec6SFrançois Tigeot if (!HAS_LLC(dev)) 1973ba55f2f5SFrançois Tigeot obj = i915_gem_object_create_stolen(dev, ringbuf->size); 1974a2fdbec6SFrançois Tigeot if (obj == NULL) 1975ba55f2f5SFrançois Tigeot obj = i915_gem_alloc_object(dev, ringbuf->size); 1976ba55f2f5SFrançois Tigeot if (obj == NULL) 1977ba55f2f5SFrançois Tigeot return -ENOMEM; 1978e3adcf8fSFrançois Tigeot 197924edb884SFrançois Tigeot /* mark ring buffers as read-only from GPU side by default */ 198024edb884SFrançois Tigeot obj->gt_ro = 1; 198124edb884SFrançois Tigeot 1982ba55f2f5SFrançois Tigeot ringbuf->obj = obj; 1983ba55f2f5SFrançois Tigeot 19842c9916cdSFrançois Tigeot return 0; 1985ba55f2f5SFrançois Tigeot } 1986ba55f2f5SFrançois Tigeot 1987ba55f2f5SFrançois Tigeot static int intel_init_ring_buffer(struct drm_device *dev, 1988ba55f2f5SFrançois Tigeot struct intel_engine_cs *ring) 1989ba55f2f5SFrançois Tigeot { 19902c9916cdSFrançois Tigeot struct intel_ringbuffer *ringbuf; 1991ba55f2f5SFrançois Tigeot int ret; 1992ba55f2f5SFrançois Tigeot 19932c9916cdSFrançois Tigeot WARN_ON(ring->buffer); 19942c9916cdSFrançois Tigeot 1995ba55f2f5SFrançois Tigeot ringbuf = kzalloc(sizeof(*ringbuf), GFP_KERNEL); 1996ba55f2f5SFrançois Tigeot if (!ringbuf) 1997ba55f2f5SFrançois Tigeot return -ENOMEM; 1998ba55f2f5SFrançois Tigeot ring->buffer = ringbuf; 1999ba55f2f5SFrançois Tigeot 2000ba55f2f5SFrançois Tigeot ring->dev = dev; 2001ba55f2f5SFrançois Tigeot INIT_LIST_HEAD(&ring->active_list); 2002ba55f2f5SFrançois Tigeot INIT_LIST_HEAD(&ring->request_list); 20031b13d190SFrançois Tigeot INIT_LIST_HEAD(&ring->execlist_queue); 200419c468b4SFrançois Tigeot i915_gem_batch_pool_init(dev, &ring->batch_pool); 2005ba55f2f5SFrançois Tigeot ringbuf->size = 32 * PAGE_SIZE; 20061b13d190SFrançois Tigeot ringbuf->ring = ring; 2007ba55f2f5SFrançois Tigeot memset(ring->semaphore.sync_seqno, 0, sizeof(ring->semaphore.sync_seqno)); 2008ba55f2f5SFrançois Tigeot 2009ba55f2f5SFrançois Tigeot init_waitqueue_head(&ring->irq_queue); 2010ba55f2f5SFrançois Tigeot 2011ba55f2f5SFrançois Tigeot if (I915_NEED_GFX_HWS(dev)) { 2012ba55f2f5SFrançois Tigeot ret = init_status_page(ring); 2013e3adcf8fSFrançois Tigeot if (ret) 2014ba55f2f5SFrançois Tigeot goto error; 2015ba55f2f5SFrançois Tigeot } else { 2016ba55f2f5SFrançois Tigeot BUG_ON(ring->id != RCS); 2017ba55f2f5SFrançois Tigeot ret = init_phys_status_page(ring); 2018ba55f2f5SFrançois Tigeot if (ret) 2019ba55f2f5SFrançois Tigeot goto error; 2020ba55f2f5SFrançois Tigeot } 2021ba55f2f5SFrançois Tigeot 20222c9916cdSFrançois Tigeot WARN_ON(ringbuf->obj); 20232c9916cdSFrançois Tigeot 202424edb884SFrançois Tigeot ret = intel_alloc_ringbuffer_obj(dev, ringbuf); 2025ba55f2f5SFrançois Tigeot if (ret) { 20262c9916cdSFrançois Tigeot DRM_ERROR("Failed to allocate ringbuffer %s: %d\n", 20272c9916cdSFrançois Tigeot ring->name, ret); 20282c9916cdSFrançois Tigeot goto error; 20292c9916cdSFrançois Tigeot } 20302c9916cdSFrançois Tigeot 20312c9916cdSFrançois Tigeot ret = intel_pin_and_map_ringbuffer_obj(dev, ringbuf); 20322c9916cdSFrançois Tigeot if (ret) { 20332c9916cdSFrançois Tigeot DRM_ERROR("Failed to pin and map ringbuffer %s: %d\n", 20342c9916cdSFrançois Tigeot ring->name, ret); 20352c9916cdSFrançois Tigeot intel_destroy_ringbuffer_obj(ringbuf); 2036ba55f2f5SFrançois Tigeot goto error; 2037ba55f2f5SFrançois Tigeot } 2038e3adcf8fSFrançois Tigeot 2039e3adcf8fSFrançois Tigeot /* Workaround an erratum on the i830 which causes a hang if 2040e3adcf8fSFrançois Tigeot * the TAIL pointer points to within the last 2 cachelines 2041e3adcf8fSFrançois Tigeot * of the buffer. 2042e3adcf8fSFrançois Tigeot */ 2043ba55f2f5SFrançois Tigeot ringbuf->effective_size = ringbuf->size; 2044ba55f2f5SFrançois Tigeot if (IS_I830(dev) || IS_845G(dev)) 2045ba55f2f5SFrançois Tigeot ringbuf->effective_size -= 2 * CACHELINE_BYTES; 2046ba55f2f5SFrançois Tigeot 2047ba55f2f5SFrançois Tigeot ret = i915_cmd_parser_init_ring(ring); 2048ba55f2f5SFrançois Tigeot if (ret) 2049ba55f2f5SFrançois Tigeot goto error; 2050ba55f2f5SFrançois Tigeot 2051e3adcf8fSFrançois Tigeot return 0; 2052e3adcf8fSFrançois Tigeot 2053ba55f2f5SFrançois Tigeot error: 2054ba55f2f5SFrançois Tigeot kfree(ringbuf); 2055ba55f2f5SFrançois Tigeot ring->buffer = NULL; 2056e3adcf8fSFrançois Tigeot return ret; 2057e3adcf8fSFrançois Tigeot } 2058e3adcf8fSFrançois Tigeot 2059ba55f2f5SFrançois Tigeot void intel_cleanup_ring_buffer(struct intel_engine_cs *ring) 2060e3adcf8fSFrançois Tigeot { 20612c9916cdSFrançois Tigeot struct drm_i915_private *dev_priv; 20622c9916cdSFrançois Tigeot struct intel_ringbuffer *ringbuf; 2063e3adcf8fSFrançois Tigeot 2064ba55f2f5SFrançois Tigeot if (!intel_ring_initialized(ring)) 2065e3adcf8fSFrançois Tigeot return; 2066e3adcf8fSFrançois Tigeot 20672c9916cdSFrançois Tigeot dev_priv = to_i915(ring->dev); 20682c9916cdSFrançois Tigeot ringbuf = ring->buffer; 20692c9916cdSFrançois Tigeot 2070ba55f2f5SFrançois Tigeot intel_stop_ring_buffer(ring); 2071ba55f2f5SFrançois Tigeot WARN_ON(!IS_GEN2(ring->dev) && (I915_READ_MODE(ring) & MODE_IDLE) == 0); 2072b030f26bSFrançois Tigeot 20732c9916cdSFrançois Tigeot intel_unpin_ringbuffer_obj(ringbuf); 207424edb884SFrançois Tigeot intel_destroy_ringbuffer_obj(ringbuf); 20752c9916cdSFrançois Tigeot i915_gem_request_assign(&ring->outstanding_lazy_request, NULL); 2076e3adcf8fSFrançois Tigeot 2077e3adcf8fSFrançois Tigeot if (ring->cleanup) 2078e3adcf8fSFrançois Tigeot ring->cleanup(ring); 2079e3adcf8fSFrançois Tigeot 2080e3adcf8fSFrançois Tigeot cleanup_status_page(ring); 2081ba55f2f5SFrançois Tigeot 2082ba55f2f5SFrançois Tigeot i915_cmd_parser_fini_ring(ring); 208319c468b4SFrançois Tigeot i915_gem_batch_pool_fini(&ring->batch_pool); 2084ba55f2f5SFrançois Tigeot 2085ba55f2f5SFrançois Tigeot kfree(ringbuf); 2086ba55f2f5SFrançois Tigeot ring->buffer = NULL; 2087e3adcf8fSFrançois Tigeot } 2088e3adcf8fSFrançois Tigeot 208919c468b4SFrançois Tigeot static int ring_wait_for_space(struct intel_engine_cs *ring, int n) 2090e3adcf8fSFrançois Tigeot { 2091ba55f2f5SFrançois Tigeot struct intel_ringbuffer *ringbuf = ring->buffer; 2092e3adcf8fSFrançois Tigeot struct drm_i915_gem_request *request; 209319c468b4SFrançois Tigeot unsigned space; 2094e3adcf8fSFrançois Tigeot int ret; 2095e3adcf8fSFrançois Tigeot 20962c9916cdSFrançois Tigeot if (intel_ring_space(ringbuf) >= n) 2097e3adcf8fSFrançois Tigeot return 0; 2098e3adcf8fSFrançois Tigeot 2099e3adcf8fSFrançois Tigeot list_for_each_entry(request, &ring->request_list, list) { 210019c468b4SFrançois Tigeot space = __intel_ring_space(request->postfix, ringbuf->tail, 210119c468b4SFrançois Tigeot ringbuf->size); 210219c468b4SFrançois Tigeot if (space >= n) 2103e3adcf8fSFrançois Tigeot break; 2104e3adcf8fSFrançois Tigeot } 2105e3adcf8fSFrançois Tigeot 210619c468b4SFrançois Tigeot if (WARN_ON(&request->list == &ring->request_list)) 2107e3adcf8fSFrançois Tigeot return -ENOSPC; 2108e3adcf8fSFrançois Tigeot 21092c9916cdSFrançois Tigeot ret = i915_wait_request(request); 2110e3adcf8fSFrançois Tigeot if (ret) 2111e3adcf8fSFrançois Tigeot return ret; 2112e3adcf8fSFrançois Tigeot 211319c468b4SFrançois Tigeot ringbuf->space = space; 2114e3adcf8fSFrançois Tigeot return 0; 2115e3adcf8fSFrançois Tigeot } 2116e3adcf8fSFrançois Tigeot 2117ba55f2f5SFrançois Tigeot static int intel_wrap_ring_buffer(struct intel_engine_cs *ring) 2118b030f26bSFrançois Tigeot { 2119b030f26bSFrançois Tigeot uint32_t __iomem *virt; 2120ba55f2f5SFrançois Tigeot struct intel_ringbuffer *ringbuf = ring->buffer; 2121ba55f2f5SFrançois Tigeot int rem = ringbuf->size - ringbuf->tail; 2122b030f26bSFrançois Tigeot 2123ba55f2f5SFrançois Tigeot if (ringbuf->space < rem) { 2124b030f26bSFrançois Tigeot int ret = ring_wait_for_space(ring, rem); 2125b030f26bSFrançois Tigeot if (ret) 2126b030f26bSFrançois Tigeot return ret; 2127b030f26bSFrançois Tigeot } 2128b030f26bSFrançois Tigeot 2129ba55f2f5SFrançois Tigeot virt = (unsigned int *)((char *)ringbuf->virtual_start + ringbuf->tail); 2130b030f26bSFrançois Tigeot rem /= 4; 2131b030f26bSFrançois Tigeot while (rem--) 2132686a02f1SFrançois Tigeot iowrite32(MI_NOOP, virt++); 2133b030f26bSFrançois Tigeot 2134ba55f2f5SFrançois Tigeot ringbuf->tail = 0; 21352c9916cdSFrançois Tigeot intel_ring_update_space(ringbuf); 2136b030f26bSFrançois Tigeot 2137b030f26bSFrançois Tigeot return 0; 2138b030f26bSFrançois Tigeot } 2139b030f26bSFrançois Tigeot 2140ba55f2f5SFrançois Tigeot int intel_ring_idle(struct intel_engine_cs *ring) 2141b030f26bSFrançois Tigeot { 21422c9916cdSFrançois Tigeot struct drm_i915_gem_request *req; 2143b5c29a34SFrançois Tigeot int ret; 2144b5c29a34SFrançois Tigeot 2145b5c29a34SFrançois Tigeot /* We need to add any requests required to flush the objects and ring */ 21462c9916cdSFrançois Tigeot if (ring->outstanding_lazy_request) { 21472c9916cdSFrançois Tigeot ret = i915_add_request(ring); 2148b5c29a34SFrançois Tigeot if (ret) 2149b5c29a34SFrançois Tigeot return ret; 2150b5c29a34SFrançois Tigeot } 2151b5c29a34SFrançois Tigeot 2152b5c29a34SFrançois Tigeot /* Wait upon the last request to be completed */ 2153b5c29a34SFrançois Tigeot if (list_empty(&ring->request_list)) 2154b5c29a34SFrançois Tigeot return 0; 2155b5c29a34SFrançois Tigeot 21562c9916cdSFrançois Tigeot req = list_entry(ring->request_list.prev, 2157b5c29a34SFrançois Tigeot struct drm_i915_gem_request, 21582c9916cdSFrançois Tigeot list); 2159b5c29a34SFrançois Tigeot 216019c468b4SFrançois Tigeot /* Make sure we do not trigger any retires */ 216119c468b4SFrançois Tigeot return __i915_wait_request(req, 216219c468b4SFrançois Tigeot atomic_read(&to_i915(ring->dev)->gpu_error.reset_counter), 216319c468b4SFrançois Tigeot to_i915(ring->dev)->mm.interruptible, 216419c468b4SFrançois Tigeot NULL, NULL); 2165b5c29a34SFrançois Tigeot } 2166b5c29a34SFrançois Tigeot 216719c468b4SFrançois Tigeot int intel_ring_alloc_request_extras(struct drm_i915_gem_request *request) 2168b5c29a34SFrançois Tigeot { 216919c468b4SFrançois Tigeot request->ringbuf = request->ring->buffer; 21702c9916cdSFrançois Tigeot return 0; 21719edbd4a0SFrançois Tigeot } 21729edbd4a0SFrançois Tigeot 2173ba55f2f5SFrançois Tigeot static int __intel_ring_prepare(struct intel_engine_cs *ring, 2174a2fdbec6SFrançois Tigeot int bytes) 2175a2fdbec6SFrançois Tigeot { 2176ba55f2f5SFrançois Tigeot struct intel_ringbuffer *ringbuf = ring->buffer; 2177a2fdbec6SFrançois Tigeot int ret; 2178a2fdbec6SFrançois Tigeot 2179ba55f2f5SFrançois Tigeot if (unlikely(ringbuf->tail + bytes > ringbuf->effective_size)) { 2180a2fdbec6SFrançois Tigeot ret = intel_wrap_ring_buffer(ring); 2181a2fdbec6SFrançois Tigeot if (unlikely(ret)) 2182a2fdbec6SFrançois Tigeot return ret; 2183a2fdbec6SFrançois Tigeot } 2184a2fdbec6SFrançois Tigeot 2185ba55f2f5SFrançois Tigeot if (unlikely(ringbuf->space < bytes)) { 2186a2fdbec6SFrançois Tigeot ret = ring_wait_for_space(ring, bytes); 2187a2fdbec6SFrançois Tigeot if (unlikely(ret)) 2188a2fdbec6SFrançois Tigeot return ret; 2189a2fdbec6SFrançois Tigeot } 2190a2fdbec6SFrançois Tigeot 2191a2fdbec6SFrançois Tigeot return 0; 2192a2fdbec6SFrançois Tigeot } 2193a2fdbec6SFrançois Tigeot 2194ba55f2f5SFrançois Tigeot int intel_ring_begin(struct intel_engine_cs *ring, 2195e3adcf8fSFrançois Tigeot int num_dwords) 2196e3adcf8fSFrançois Tigeot { 2197ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = ring->dev->dev_private; 2198e3adcf8fSFrançois Tigeot int ret; 2199e3adcf8fSFrançois Tigeot 2200a2fdbec6SFrançois Tigeot ret = i915_gem_check_wedge(&dev_priv->gpu_error, 2201a2fdbec6SFrançois Tigeot dev_priv->mm.interruptible); 2202245593daSFrançois Tigeot if (ret) 2203245593daSFrançois Tigeot return ret; 2204e3adcf8fSFrançois Tigeot 22059edbd4a0SFrançois Tigeot ret = __intel_ring_prepare(ring, num_dwords * sizeof(uint32_t)); 22069edbd4a0SFrançois Tigeot if (ret) 22079edbd4a0SFrançois Tigeot return ret; 22089edbd4a0SFrançois Tigeot 2209b5c29a34SFrançois Tigeot /* Preallocate the olr before touching the ring */ 221019c468b4SFrançois Tigeot ret = i915_gem_request_alloc(ring, ring->default_context); 2211b5c29a34SFrançois Tigeot if (ret) 2212b5c29a34SFrançois Tigeot return ret; 2213b5c29a34SFrançois Tigeot 2214ba55f2f5SFrançois Tigeot ring->buffer->space -= num_dwords * sizeof(uint32_t); 22159edbd4a0SFrançois Tigeot return 0; 22169edbd4a0SFrançois Tigeot } 22179edbd4a0SFrançois Tigeot 22189edbd4a0SFrançois Tigeot /* Align the ring tail to a cacheline boundary */ 2219ba55f2f5SFrançois Tigeot int intel_ring_cacheline_align(struct intel_engine_cs *ring) 22209edbd4a0SFrançois Tigeot { 2221ba55f2f5SFrançois Tigeot int num_dwords = (ring->buffer->tail & (CACHELINE_BYTES - 1)) / sizeof(uint32_t); 22229edbd4a0SFrançois Tigeot int ret; 22239edbd4a0SFrançois Tigeot 22249edbd4a0SFrançois Tigeot if (num_dwords == 0) 22259edbd4a0SFrançois Tigeot return 0; 22269edbd4a0SFrançois Tigeot 2227ba55f2f5SFrançois Tigeot num_dwords = CACHELINE_BYTES / sizeof(uint32_t) - num_dwords; 22289edbd4a0SFrançois Tigeot ret = intel_ring_begin(ring, num_dwords); 22299edbd4a0SFrançois Tigeot if (ret) 22309edbd4a0SFrançois Tigeot return ret; 22319edbd4a0SFrançois Tigeot 22329edbd4a0SFrançois Tigeot while (num_dwords--) 22339edbd4a0SFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 22349edbd4a0SFrançois Tigeot 22359edbd4a0SFrançois Tigeot intel_ring_advance(ring); 22369edbd4a0SFrançois Tigeot 22379edbd4a0SFrançois Tigeot return 0; 2238e3adcf8fSFrançois Tigeot } 2239e3adcf8fSFrançois Tigeot 2240ba55f2f5SFrançois Tigeot void intel_ring_init_seqno(struct intel_engine_cs *ring, u32 seqno) 2241a2fdbec6SFrançois Tigeot { 224224edb884SFrançois Tigeot struct drm_device *dev = ring->dev; 224324edb884SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 2244a2fdbec6SFrançois Tigeot 22452c9916cdSFrançois Tigeot BUG_ON(ring->outstanding_lazy_request); 2246a2fdbec6SFrançois Tigeot 224724edb884SFrançois Tigeot if (INTEL_INFO(dev)->gen == 6 || INTEL_INFO(dev)->gen == 7) { 2248a2fdbec6SFrançois Tigeot I915_WRITE(RING_SYNC_0(ring->mmio_base), 0); 2249a2fdbec6SFrançois Tigeot I915_WRITE(RING_SYNC_1(ring->mmio_base), 0); 225024edb884SFrançois Tigeot if (HAS_VEBOX(dev)) 22519edbd4a0SFrançois Tigeot I915_WRITE(RING_SYNC_2(ring->mmio_base), 0); 2252e3adcf8fSFrançois Tigeot } 2253e3adcf8fSFrançois Tigeot 2254a2fdbec6SFrançois Tigeot ring->set_seqno(ring, seqno); 22555d0b1887SFrançois Tigeot ring->hangcheck.seqno = seqno; 2256e3adcf8fSFrançois Tigeot } 2257e3adcf8fSFrançois Tigeot 2258ba55f2f5SFrançois Tigeot static void gen6_bsd_ring_write_tail(struct intel_engine_cs *ring, 2259f4e1c372SFrançois Tigeot u32 value) 2260e3adcf8fSFrançois Tigeot { 2261ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = ring->dev->dev_private; 2262e3adcf8fSFrançois Tigeot 2263e3adcf8fSFrançois Tigeot /* Every tail move must follow the sequence below */ 2264f4e1c372SFrançois Tigeot 2265f4e1c372SFrançois Tigeot /* Disable notification that the ring is IDLE. The GT 2266f4e1c372SFrançois Tigeot * will then assume that it is busy and bring it out of rc6. 2267f4e1c372SFrançois Tigeot */ 2268e3adcf8fSFrançois Tigeot I915_WRITE(GEN6_BSD_SLEEP_PSMI_CONTROL, 2269f4e1c372SFrançois Tigeot _MASKED_BIT_ENABLE(GEN6_BSD_SLEEP_MSG_DISABLE)); 2270e3adcf8fSFrançois Tigeot 2271f4e1c372SFrançois Tigeot /* Clear the context id. Here be magic! */ 2272f4e1c372SFrançois Tigeot I915_WRITE64(GEN6_BSD_RNCID, 0x0); 2273e3adcf8fSFrançois Tigeot 2274f4e1c372SFrançois Tigeot /* Wait for the ring not to be idle, i.e. for it to wake up. */ 2275f4e1c372SFrançois Tigeot if (wait_for((I915_READ(GEN6_BSD_SLEEP_PSMI_CONTROL) & 2276f4e1c372SFrançois Tigeot GEN6_BSD_SLEEP_INDICATOR) == 0, 2277f4e1c372SFrançois Tigeot 50)) 2278f4e1c372SFrançois Tigeot DRM_ERROR("timed out waiting for the BSD ring to wake up\n"); 2279f4e1c372SFrançois Tigeot 2280f4e1c372SFrançois Tigeot /* Now that the ring is fully powered up, update the tail */ 2281e3adcf8fSFrançois Tigeot I915_WRITE_TAIL(ring, value); 2282f4e1c372SFrançois Tigeot POSTING_READ(RING_TAIL(ring->mmio_base)); 2283f4e1c372SFrançois Tigeot 2284f4e1c372SFrançois Tigeot /* Let the ring send IDLE messages to the GT again, 2285f4e1c372SFrançois Tigeot * and so let it sleep to conserve power when idle. 2286f4e1c372SFrançois Tigeot */ 2287e3adcf8fSFrançois Tigeot I915_WRITE(GEN6_BSD_SLEEP_PSMI_CONTROL, 2288f4e1c372SFrançois Tigeot _MASKED_BIT_DISABLE(GEN6_BSD_SLEEP_MSG_DISABLE)); 2289e3adcf8fSFrançois Tigeot } 2290e3adcf8fSFrançois Tigeot 2291ba55f2f5SFrançois Tigeot static int gen6_bsd_ring_flush(struct intel_engine_cs *ring, 2292b5c29a34SFrançois Tigeot u32 invalidate, u32 flush) 2293e3adcf8fSFrançois Tigeot { 2294e3adcf8fSFrançois Tigeot uint32_t cmd; 2295e3adcf8fSFrançois Tigeot int ret; 2296e3adcf8fSFrançois Tigeot 2297e3adcf8fSFrançois Tigeot ret = intel_ring_begin(ring, 4); 2298e3adcf8fSFrançois Tigeot if (ret) 2299e3adcf8fSFrançois Tigeot return ret; 2300e3adcf8fSFrançois Tigeot 2301e3adcf8fSFrançois Tigeot cmd = MI_FLUSH_DW; 23029edbd4a0SFrançois Tigeot if (INTEL_INFO(ring->dev)->gen >= 8) 23039edbd4a0SFrançois Tigeot cmd += 1; 23042c9916cdSFrançois Tigeot 23052c9916cdSFrançois Tigeot /* We always require a command barrier so that subsequent 23062c9916cdSFrançois Tigeot * commands, such as breadcrumb interrupts, are strictly ordered 23072c9916cdSFrançois Tigeot * wrt the contents of the write cache being flushed to memory 23082c9916cdSFrançois Tigeot * (and thus being coherent from the CPU). 23092c9916cdSFrançois Tigeot */ 23102c9916cdSFrançois Tigeot cmd |= MI_FLUSH_DW_STORE_INDEX | MI_FLUSH_DW_OP_STOREDW; 23112c9916cdSFrançois Tigeot 2312b5c29a34SFrançois Tigeot /* 2313b5c29a34SFrançois Tigeot * Bspec vol 1c.5 - video engine command streamer: 2314b5c29a34SFrançois Tigeot * "If ENABLED, all TLBs will be invalidated once the flush 2315b5c29a34SFrançois Tigeot * operation is complete. This bit is only valid when the 2316b5c29a34SFrançois Tigeot * Post-Sync Operation field is a value of 1h or 3h." 2317b5c29a34SFrançois Tigeot */ 2318e3adcf8fSFrançois Tigeot if (invalidate & I915_GEM_GPU_DOMAINS) 23192c9916cdSFrançois Tigeot cmd |= MI_INVALIDATE_TLB | MI_INVALIDATE_BSD; 23202c9916cdSFrançois Tigeot 2321e3adcf8fSFrançois Tigeot intel_ring_emit(ring, cmd); 2322b5c29a34SFrançois Tigeot intel_ring_emit(ring, I915_GEM_HWS_SCRATCH_ADDR | MI_FLUSH_DW_USE_GTT); 23239edbd4a0SFrançois Tigeot if (INTEL_INFO(ring->dev)->gen >= 8) { 23249edbd4a0SFrançois Tigeot intel_ring_emit(ring, 0); /* upper addr */ 23259edbd4a0SFrançois Tigeot intel_ring_emit(ring, 0); /* value */ 23269edbd4a0SFrançois Tigeot } else { 23279edbd4a0SFrançois Tigeot intel_ring_emit(ring, 0); 23289edbd4a0SFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 23299edbd4a0SFrançois Tigeot } 23309edbd4a0SFrançois Tigeot intel_ring_advance(ring); 23319edbd4a0SFrançois Tigeot return 0; 23329edbd4a0SFrançois Tigeot } 23339edbd4a0SFrançois Tigeot 23349edbd4a0SFrançois Tigeot static int 2335ba55f2f5SFrançois Tigeot gen8_ring_dispatch_execbuffer(struct intel_engine_cs *ring, 2336ba55f2f5SFrançois Tigeot u64 offset, u32 len, 2337477eb7f9SFrançois Tigeot unsigned dispatch_flags) 23389edbd4a0SFrançois Tigeot { 2339477eb7f9SFrançois Tigeot bool ppgtt = USES_PPGTT(ring->dev) && 2340477eb7f9SFrançois Tigeot !(dispatch_flags & I915_DISPATCH_SECURE); 23419edbd4a0SFrançois Tigeot int ret; 23429edbd4a0SFrançois Tigeot 23439edbd4a0SFrançois Tigeot ret = intel_ring_begin(ring, 4); 23449edbd4a0SFrançois Tigeot if (ret) 23459edbd4a0SFrançois Tigeot return ret; 23469edbd4a0SFrançois Tigeot 23479edbd4a0SFrançois Tigeot /* FIXME(BDW): Address space and security selectors. */ 23489edbd4a0SFrançois Tigeot intel_ring_emit(ring, MI_BATCH_BUFFER_START_GEN8 | (ppgtt<<8)); 2349ba55f2f5SFrançois Tigeot intel_ring_emit(ring, lower_32_bits(offset)); 2350ba55f2f5SFrançois Tigeot intel_ring_emit(ring, upper_32_bits(offset)); 2351e3adcf8fSFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 2352e3adcf8fSFrançois Tigeot intel_ring_advance(ring); 23539edbd4a0SFrançois Tigeot 2354e3adcf8fSFrançois Tigeot return 0; 2355e3adcf8fSFrançois Tigeot } 2356e3adcf8fSFrançois Tigeot 2357e3adcf8fSFrançois Tigeot static int 2358ba55f2f5SFrançois Tigeot hsw_ring_dispatch_execbuffer(struct intel_engine_cs *ring, 2359ba55f2f5SFrançois Tigeot u64 offset, u32 len, 2360477eb7f9SFrançois Tigeot unsigned dispatch_flags) 2361e3adcf8fSFrançois Tigeot { 2362e3adcf8fSFrançois Tigeot int ret; 2363e3adcf8fSFrançois Tigeot 2364e3adcf8fSFrançois Tigeot ret = intel_ring_begin(ring, 2); 2365e3adcf8fSFrançois Tigeot if (ret) 2366e3adcf8fSFrançois Tigeot return ret; 2367e3adcf8fSFrançois Tigeot 2368b5c29a34SFrançois Tigeot intel_ring_emit(ring, 23691b13d190SFrançois Tigeot MI_BATCH_BUFFER_START | 2370477eb7f9SFrançois Tigeot (dispatch_flags & I915_DISPATCH_SECURE ? 23711b13d190SFrançois Tigeot 0 : MI_BATCH_PPGTT_HSW | MI_BATCH_NON_SECURE_HSW)); 2372b5c29a34SFrançois Tigeot /* bit0-7 is the length on GEN6+ */ 2373b5c29a34SFrançois Tigeot intel_ring_emit(ring, offset); 2374b5c29a34SFrançois Tigeot intel_ring_advance(ring); 2375b5c29a34SFrançois Tigeot 2376b5c29a34SFrançois Tigeot return 0; 2377b5c29a34SFrançois Tigeot } 2378b5c29a34SFrançois Tigeot 2379b5c29a34SFrançois Tigeot static int 2380ba55f2f5SFrançois Tigeot gen6_ring_dispatch_execbuffer(struct intel_engine_cs *ring, 2381ba55f2f5SFrançois Tigeot u64 offset, u32 len, 2382477eb7f9SFrançois Tigeot unsigned dispatch_flags) 2383b5c29a34SFrançois Tigeot { 2384b5c29a34SFrançois Tigeot int ret; 2385b5c29a34SFrançois Tigeot 2386b5c29a34SFrançois Tigeot ret = intel_ring_begin(ring, 2); 2387b5c29a34SFrançois Tigeot if (ret) 2388b5c29a34SFrançois Tigeot return ret; 2389b5c29a34SFrançois Tigeot 2390b5c29a34SFrançois Tigeot intel_ring_emit(ring, 2391b5c29a34SFrançois Tigeot MI_BATCH_BUFFER_START | 2392477eb7f9SFrançois Tigeot (dispatch_flags & I915_DISPATCH_SECURE ? 2393477eb7f9SFrançois Tigeot 0 : MI_BATCH_NON_SECURE_I965)); 2394e3adcf8fSFrançois Tigeot /* bit0-7 is the length on GEN6+ */ 2395e3adcf8fSFrançois Tigeot intel_ring_emit(ring, offset); 2396e3adcf8fSFrançois Tigeot intel_ring_advance(ring); 2397e3adcf8fSFrançois Tigeot 2398e3adcf8fSFrançois Tigeot return 0; 2399e3adcf8fSFrançois Tigeot } 2400e3adcf8fSFrançois Tigeot 2401e3adcf8fSFrançois Tigeot /* Blitter support (SandyBridge+) */ 2402e3adcf8fSFrançois Tigeot 2403ba55f2f5SFrançois Tigeot static int gen6_ring_flush(struct intel_engine_cs *ring, 2404b5c29a34SFrançois Tigeot u32 invalidate, u32 flush) 2405e3adcf8fSFrançois Tigeot { 24065d0b1887SFrançois Tigeot struct drm_device *dev = ring->dev; 2407e3adcf8fSFrançois Tigeot uint32_t cmd; 2408e3adcf8fSFrançois Tigeot int ret; 2409e3adcf8fSFrançois Tigeot 2410e3adcf8fSFrançois Tigeot ret = intel_ring_begin(ring, 4); 2411e3adcf8fSFrançois Tigeot if (ret) 2412e3adcf8fSFrançois Tigeot return ret; 2413e3adcf8fSFrançois Tigeot 2414e3adcf8fSFrançois Tigeot cmd = MI_FLUSH_DW; 2415477eb7f9SFrançois Tigeot if (INTEL_INFO(dev)->gen >= 8) 24169edbd4a0SFrançois Tigeot cmd += 1; 24172c9916cdSFrançois Tigeot 24182c9916cdSFrançois Tigeot /* We always require a command barrier so that subsequent 24192c9916cdSFrançois Tigeot * commands, such as breadcrumb interrupts, are strictly ordered 24202c9916cdSFrançois Tigeot * wrt the contents of the write cache being flushed to memory 24212c9916cdSFrançois Tigeot * (and thus being coherent from the CPU). 24222c9916cdSFrançois Tigeot */ 24232c9916cdSFrançois Tigeot cmd |= MI_FLUSH_DW_STORE_INDEX | MI_FLUSH_DW_OP_STOREDW; 24242c9916cdSFrançois Tigeot 2425b5c29a34SFrançois Tigeot /* 2426b5c29a34SFrançois Tigeot * Bspec vol 1c.3 - blitter engine command streamer: 2427b5c29a34SFrançois Tigeot * "If ENABLED, all TLBs will be invalidated once the flush 2428b5c29a34SFrançois Tigeot * operation is complete. This bit is only valid when the 2429b5c29a34SFrançois Tigeot * Post-Sync Operation field is a value of 1h or 3h." 2430b5c29a34SFrançois Tigeot */ 2431e3adcf8fSFrançois Tigeot if (invalidate & I915_GEM_DOMAIN_RENDER) 24322c9916cdSFrançois Tigeot cmd |= MI_INVALIDATE_TLB; 2433e3adcf8fSFrançois Tigeot intel_ring_emit(ring, cmd); 2434b5c29a34SFrançois Tigeot intel_ring_emit(ring, I915_GEM_HWS_SCRATCH_ADDR | MI_FLUSH_DW_USE_GTT); 2435477eb7f9SFrançois Tigeot if (INTEL_INFO(dev)->gen >= 8) { 24369edbd4a0SFrançois Tigeot intel_ring_emit(ring, 0); /* upper addr */ 24379edbd4a0SFrançois Tigeot intel_ring_emit(ring, 0); /* value */ 24389edbd4a0SFrançois Tigeot } else { 2439e3adcf8fSFrançois Tigeot intel_ring_emit(ring, 0); 2440e3adcf8fSFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 24419edbd4a0SFrançois Tigeot } 2442e3adcf8fSFrançois Tigeot intel_ring_advance(ring); 24435d0b1887SFrançois Tigeot 2444e3adcf8fSFrançois Tigeot return 0; 2445e3adcf8fSFrançois Tigeot } 2446e3adcf8fSFrançois Tigeot 2447e3adcf8fSFrançois Tigeot int intel_init_render_ring_buffer(struct drm_device *dev) 2448e3adcf8fSFrançois Tigeot { 2449ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 2450ba55f2f5SFrançois Tigeot struct intel_engine_cs *ring = &dev_priv->ring[RCS]; 245124edb884SFrançois Tigeot struct drm_i915_gem_object *obj; 245224edb884SFrançois Tigeot int ret; 2453e3adcf8fSFrançois Tigeot 2454686a02f1SFrançois Tigeot ring->name = "render ring"; 2455686a02f1SFrançois Tigeot ring->id = RCS; 2456686a02f1SFrançois Tigeot ring->mmio_base = RENDER_RING_BASE; 2457686a02f1SFrançois Tigeot 245824edb884SFrançois Tigeot if (INTEL_INFO(dev)->gen >= 8) { 245924edb884SFrançois Tigeot if (i915_semaphore_is_enabled(dev)) { 246024edb884SFrançois Tigeot obj = i915_gem_alloc_object(dev, 4096); 246124edb884SFrançois Tigeot if (obj == NULL) { 246224edb884SFrançois Tigeot DRM_ERROR("Failed to allocate semaphore bo. Disabling semaphores\n"); 246324edb884SFrançois Tigeot i915.semaphores = 0; 246424edb884SFrançois Tigeot } else { 246524edb884SFrançois Tigeot i915_gem_object_set_cache_level(obj, I915_CACHE_LLC); 246624edb884SFrançois Tigeot ret = i915_gem_obj_ggtt_pin(obj, 0, PIN_NONBLOCK); 246724edb884SFrançois Tigeot if (ret != 0) { 246824edb884SFrançois Tigeot drm_gem_object_unreference(&obj->base); 246924edb884SFrançois Tigeot DRM_ERROR("Failed to pin semaphore bo. Disabling semaphores\n"); 247024edb884SFrançois Tigeot i915.semaphores = 0; 247124edb884SFrançois Tigeot } else 247224edb884SFrançois Tigeot dev_priv->semaphore_obj = obj; 247324edb884SFrançois Tigeot } 247424edb884SFrançois Tigeot } 24752c9916cdSFrançois Tigeot 24762c9916cdSFrançois Tigeot ring->init_context = intel_rcs_ctx_init; 247724edb884SFrançois Tigeot ring->add_request = gen6_add_request; 247824edb884SFrançois Tigeot ring->flush = gen8_render_ring_flush; 247924edb884SFrançois Tigeot ring->irq_get = gen8_ring_get_irq; 248024edb884SFrançois Tigeot ring->irq_put = gen8_ring_put_irq; 248124edb884SFrançois Tigeot ring->irq_enable_mask = GT_RENDER_USER_INTERRUPT; 248224edb884SFrançois Tigeot ring->get_seqno = gen6_ring_get_seqno; 248324edb884SFrançois Tigeot ring->set_seqno = ring_set_seqno; 248424edb884SFrançois Tigeot if (i915_semaphore_is_enabled(dev)) { 248524edb884SFrançois Tigeot WARN_ON(!dev_priv->semaphore_obj); 248624edb884SFrançois Tigeot ring->semaphore.sync_to = gen8_ring_sync; 248724edb884SFrançois Tigeot ring->semaphore.signal = gen8_rcs_signal; 248824edb884SFrançois Tigeot GEN8_RING_SEMAPHORE_INIT; 248924edb884SFrançois Tigeot } 249024edb884SFrançois Tigeot } else if (INTEL_INFO(dev)->gen >= 6) { 2491e3adcf8fSFrançois Tigeot ring->add_request = gen6_add_request; 2492b5c29a34SFrançois Tigeot ring->flush = gen7_render_ring_flush; 2493b5c29a34SFrançois Tigeot if (INTEL_INFO(dev)->gen == 6) 2494e3adcf8fSFrançois Tigeot ring->flush = gen6_render_ring_flush; 2495686a02f1SFrançois Tigeot ring->irq_get = gen6_ring_get_irq; 2496686a02f1SFrançois Tigeot ring->irq_put = gen6_ring_put_irq; 24975d0b1887SFrançois Tigeot ring->irq_enable_mask = GT_RENDER_USER_INTERRUPT; 2498e3adcf8fSFrançois Tigeot ring->get_seqno = gen6_ring_get_seqno; 2499a2fdbec6SFrançois Tigeot ring->set_seqno = ring_set_seqno; 250024edb884SFrançois Tigeot if (i915_semaphore_is_enabled(dev)) { 2501ba55f2f5SFrançois Tigeot ring->semaphore.sync_to = gen6_ring_sync; 2502ba55f2f5SFrançois Tigeot ring->semaphore.signal = gen6_signal; 2503ba55f2f5SFrançois Tigeot /* 250424edb884SFrançois Tigeot * The current semaphore is only applied on pre-gen8 250524edb884SFrançois Tigeot * platform. And there is no VCS2 ring on the pre-gen8 250624edb884SFrançois Tigeot * platform. So the semaphore between RCS and VCS2 is 250724edb884SFrançois Tigeot * initialized as INVALID. Gen8 will initialize the 250824edb884SFrançois Tigeot * sema between VCS2 and RCS later. 2509ba55f2f5SFrançois Tigeot */ 2510ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[RCS] = MI_SEMAPHORE_SYNC_INVALID; 2511ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[VCS] = MI_SEMAPHORE_SYNC_RV; 2512ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[BCS] = MI_SEMAPHORE_SYNC_RB; 2513ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[VECS] = MI_SEMAPHORE_SYNC_RVE; 2514ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[VCS2] = MI_SEMAPHORE_SYNC_INVALID; 2515ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[RCS] = GEN6_NOSYNC; 2516ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[VCS] = GEN6_VRSYNC; 2517ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[BCS] = GEN6_BRSYNC; 2518ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[VECS] = GEN6_VERSYNC; 2519ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[VCS2] = GEN6_NOSYNC; 252024edb884SFrançois Tigeot } 2521e3adcf8fSFrançois Tigeot } else if (IS_GEN5(dev)) { 2522e3adcf8fSFrançois Tigeot ring->add_request = pc_render_add_request; 2523686a02f1SFrançois Tigeot ring->flush = gen4_render_ring_flush; 2524e3adcf8fSFrançois Tigeot ring->get_seqno = pc_render_get_seqno; 2525a2fdbec6SFrançois Tigeot ring->set_seqno = pc_render_set_seqno; 2526686a02f1SFrançois Tigeot ring->irq_get = gen5_ring_get_irq; 2527686a02f1SFrançois Tigeot ring->irq_put = gen5_ring_put_irq; 25285d0b1887SFrançois Tigeot ring->irq_enable_mask = GT_RENDER_USER_INTERRUPT | 25295d0b1887SFrançois Tigeot GT_RENDER_PIPECTL_NOTIFY_INTERRUPT; 2530686a02f1SFrançois Tigeot } else { 2531686a02f1SFrançois Tigeot ring->add_request = i9xx_add_request; 2532686a02f1SFrançois Tigeot if (INTEL_INFO(dev)->gen < 4) 2533686a02f1SFrançois Tigeot ring->flush = gen2_render_ring_flush; 2534686a02f1SFrançois Tigeot else 2535686a02f1SFrançois Tigeot ring->flush = gen4_render_ring_flush; 2536686a02f1SFrançois Tigeot ring->get_seqno = ring_get_seqno; 2537a2fdbec6SFrançois Tigeot ring->set_seqno = ring_set_seqno; 2538686a02f1SFrançois Tigeot if (IS_GEN2(dev)) { 2539686a02f1SFrançois Tigeot ring->irq_get = i8xx_ring_get_irq; 2540686a02f1SFrançois Tigeot ring->irq_put = i8xx_ring_put_irq; 2541686a02f1SFrançois Tigeot } else { 2542686a02f1SFrançois Tigeot ring->irq_get = i9xx_ring_get_irq; 2543686a02f1SFrançois Tigeot ring->irq_put = i9xx_ring_put_irq; 2544e3adcf8fSFrançois Tigeot } 2545686a02f1SFrançois Tigeot ring->irq_enable_mask = I915_USER_INTERRUPT; 2546686a02f1SFrançois Tigeot } 2547686a02f1SFrançois Tigeot ring->write_tail = ring_write_tail; 254824edb884SFrançois Tigeot 2549b5c29a34SFrançois Tigeot if (IS_HASWELL(dev)) 2550b5c29a34SFrançois Tigeot ring->dispatch_execbuffer = hsw_ring_dispatch_execbuffer; 25519edbd4a0SFrançois Tigeot else if (IS_GEN8(dev)) 25529edbd4a0SFrançois Tigeot ring->dispatch_execbuffer = gen8_ring_dispatch_execbuffer; 2553b5c29a34SFrançois Tigeot else if (INTEL_INFO(dev)->gen >= 6) 2554686a02f1SFrançois Tigeot ring->dispatch_execbuffer = gen6_ring_dispatch_execbuffer; 2555686a02f1SFrançois Tigeot else if (INTEL_INFO(dev)->gen >= 4) 2556686a02f1SFrançois Tigeot ring->dispatch_execbuffer = i965_dispatch_execbuffer; 2557686a02f1SFrançois Tigeot else if (IS_I830(dev) || IS_845G(dev)) 2558686a02f1SFrançois Tigeot ring->dispatch_execbuffer = i830_dispatch_execbuffer; 2559686a02f1SFrançois Tigeot else 2560686a02f1SFrançois Tigeot ring->dispatch_execbuffer = i915_dispatch_execbuffer; 25612c9916cdSFrançois Tigeot ring->init_hw = init_render_ring; 2562686a02f1SFrançois Tigeot ring->cleanup = render_ring_cleanup; 2563e3adcf8fSFrançois Tigeot 2564b5c29a34SFrançois Tigeot /* Workaround batchbuffer to combat CS tlb bug. */ 2565b5c29a34SFrançois Tigeot if (HAS_BROKEN_CS_TLB(dev)) { 256624edb884SFrançois Tigeot obj = i915_gem_alloc_object(dev, I830_WA_SIZE); 2567b5c29a34SFrançois Tigeot if (obj == NULL) { 2568b5c29a34SFrançois Tigeot DRM_ERROR("Failed to allocate batch bo\n"); 2569b5c29a34SFrançois Tigeot return -ENOMEM; 2570b5c29a34SFrançois Tigeot } 2571b5c29a34SFrançois Tigeot 2572ba55f2f5SFrançois Tigeot ret = i915_gem_obj_ggtt_pin(obj, 0, 0); 2573b5c29a34SFrançois Tigeot if (ret != 0) { 2574b5c29a34SFrançois Tigeot drm_gem_object_unreference(&obj->base); 2575b5c29a34SFrançois Tigeot DRM_ERROR("Failed to ping batch bo\n"); 2576b5c29a34SFrançois Tigeot return ret; 2577b5c29a34SFrançois Tigeot } 2578b5c29a34SFrançois Tigeot 25799edbd4a0SFrançois Tigeot ring->scratch.obj = obj; 25809edbd4a0SFrançois Tigeot ring->scratch.gtt_offset = i915_gem_obj_ggtt_offset(obj); 2581e3adcf8fSFrançois Tigeot } 2582e3adcf8fSFrançois Tigeot 25832c9916cdSFrançois Tigeot ret = intel_init_ring_buffer(dev, ring); 2584b5c29a34SFrançois Tigeot if (ret) 25852c9916cdSFrançois Tigeot return ret; 25862c9916cdSFrançois Tigeot 25872c9916cdSFrançois Tigeot if (INTEL_INFO(dev)->gen >= 5) { 25882c9916cdSFrançois Tigeot ret = intel_init_pipe_control(ring); 25892c9916cdSFrançois Tigeot if (ret) 25902c9916cdSFrançois Tigeot return ret; 2591b5c29a34SFrançois Tigeot } 2592b5c29a34SFrançois Tigeot 2593e3adcf8fSFrançois Tigeot return 0; 2594e3adcf8fSFrançois Tigeot } 2595e3adcf8fSFrançois Tigeot 2596e3adcf8fSFrançois Tigeot int intel_init_bsd_ring_buffer(struct drm_device *dev) 2597e3adcf8fSFrançois Tigeot { 2598ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 2599ba55f2f5SFrançois Tigeot struct intel_engine_cs *ring = &dev_priv->ring[VCS]; 2600e3adcf8fSFrançois Tigeot 2601686a02f1SFrançois Tigeot ring->name = "bsd ring"; 2602686a02f1SFrançois Tigeot ring->id = VCS; 2603686a02f1SFrançois Tigeot 2604686a02f1SFrançois Tigeot ring->write_tail = ring_write_tail; 26059edbd4a0SFrançois Tigeot if (INTEL_INFO(dev)->gen >= 6) { 2606686a02f1SFrançois Tigeot ring->mmio_base = GEN6_BSD_RING_BASE; 2607686a02f1SFrançois Tigeot /* gen6 bsd needs a special wa for tail updates */ 2608686a02f1SFrançois Tigeot if (IS_GEN6(dev)) 2609686a02f1SFrançois Tigeot ring->write_tail = gen6_bsd_ring_write_tail; 26105d0b1887SFrançois Tigeot ring->flush = gen6_bsd_ring_flush; 2611686a02f1SFrançois Tigeot ring->add_request = gen6_add_request; 2612686a02f1SFrançois Tigeot ring->get_seqno = gen6_ring_get_seqno; 2613a2fdbec6SFrançois Tigeot ring->set_seqno = ring_set_seqno; 26149edbd4a0SFrançois Tigeot if (INTEL_INFO(dev)->gen >= 8) { 26159edbd4a0SFrançois Tigeot ring->irq_enable_mask = 26169edbd4a0SFrançois Tigeot GT_RENDER_USER_INTERRUPT << GEN8_VCS1_IRQ_SHIFT; 26179edbd4a0SFrançois Tigeot ring->irq_get = gen8_ring_get_irq; 26189edbd4a0SFrançois Tigeot ring->irq_put = gen8_ring_put_irq; 26199edbd4a0SFrançois Tigeot ring->dispatch_execbuffer = 26209edbd4a0SFrançois Tigeot gen8_ring_dispatch_execbuffer; 262124edb884SFrançois Tigeot if (i915_semaphore_is_enabled(dev)) { 262224edb884SFrançois Tigeot ring->semaphore.sync_to = gen8_ring_sync; 262324edb884SFrançois Tigeot ring->semaphore.signal = gen8_xcs_signal; 262424edb884SFrançois Tigeot GEN8_RING_SEMAPHORE_INIT; 262524edb884SFrançois Tigeot } 26269edbd4a0SFrançois Tigeot } else { 26275d0b1887SFrançois Tigeot ring->irq_enable_mask = GT_BSD_USER_INTERRUPT; 2628686a02f1SFrançois Tigeot ring->irq_get = gen6_ring_get_irq; 2629686a02f1SFrançois Tigeot ring->irq_put = gen6_ring_put_irq; 26309edbd4a0SFrançois Tigeot ring->dispatch_execbuffer = 26319edbd4a0SFrançois Tigeot gen6_ring_dispatch_execbuffer; 263224edb884SFrançois Tigeot if (i915_semaphore_is_enabled(dev)) { 2633ba55f2f5SFrançois Tigeot ring->semaphore.sync_to = gen6_ring_sync; 2634ba55f2f5SFrançois Tigeot ring->semaphore.signal = gen6_signal; 2635ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[RCS] = MI_SEMAPHORE_SYNC_VR; 2636ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[VCS] = MI_SEMAPHORE_SYNC_INVALID; 2637ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[BCS] = MI_SEMAPHORE_SYNC_VB; 2638ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[VECS] = MI_SEMAPHORE_SYNC_VVE; 2639ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[VCS2] = MI_SEMAPHORE_SYNC_INVALID; 2640ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[RCS] = GEN6_RVSYNC; 2641ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[VCS] = GEN6_NOSYNC; 2642ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[BCS] = GEN6_BVSYNC; 2643ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[VECS] = GEN6_VEVSYNC; 2644ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[VCS2] = GEN6_NOSYNC; 264524edb884SFrançois Tigeot } 264624edb884SFrançois Tigeot } 2647686a02f1SFrançois Tigeot } else { 2648686a02f1SFrançois Tigeot ring->mmio_base = BSD_RING_BASE; 2649686a02f1SFrançois Tigeot ring->flush = bsd_ring_flush; 2650686a02f1SFrançois Tigeot ring->add_request = i9xx_add_request; 2651686a02f1SFrançois Tigeot ring->get_seqno = ring_get_seqno; 2652a2fdbec6SFrançois Tigeot ring->set_seqno = ring_set_seqno; 2653686a02f1SFrançois Tigeot if (IS_GEN5(dev)) { 26545d0b1887SFrançois Tigeot ring->irq_enable_mask = ILK_BSD_USER_INTERRUPT; 2655686a02f1SFrançois Tigeot ring->irq_get = gen5_ring_get_irq; 2656686a02f1SFrançois Tigeot ring->irq_put = gen5_ring_put_irq; 2657686a02f1SFrançois Tigeot } else { 2658686a02f1SFrançois Tigeot ring->irq_enable_mask = I915_BSD_USER_INTERRUPT; 2659686a02f1SFrançois Tigeot ring->irq_get = i9xx_ring_get_irq; 2660686a02f1SFrançois Tigeot ring->irq_put = i9xx_ring_put_irq; 2661686a02f1SFrançois Tigeot } 2662686a02f1SFrançois Tigeot ring->dispatch_execbuffer = i965_dispatch_execbuffer; 2663686a02f1SFrançois Tigeot } 26642c9916cdSFrançois Tigeot ring->init_hw = init_ring_common; 2665e3adcf8fSFrançois Tigeot 2666e3adcf8fSFrançois Tigeot return intel_init_ring_buffer(dev, ring); 2667e3adcf8fSFrançois Tigeot } 2668e3adcf8fSFrançois Tigeot 2669ba55f2f5SFrançois Tigeot /** 2670477eb7f9SFrançois Tigeot * Initialize the second BSD ring (eg. Broadwell GT3, Skylake GT3) 2671ba55f2f5SFrançois Tigeot */ 2672ba55f2f5SFrançois Tigeot int intel_init_bsd2_ring_buffer(struct drm_device *dev) 2673ba55f2f5SFrançois Tigeot { 2674ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 2675ba55f2f5SFrançois Tigeot struct intel_engine_cs *ring = &dev_priv->ring[VCS2]; 2676ba55f2f5SFrançois Tigeot 267724edb884SFrançois Tigeot ring->name = "bsd2 ring"; 2678ba55f2f5SFrançois Tigeot ring->id = VCS2; 2679ba55f2f5SFrançois Tigeot 2680ba55f2f5SFrançois Tigeot ring->write_tail = ring_write_tail; 2681ba55f2f5SFrançois Tigeot ring->mmio_base = GEN8_BSD2_RING_BASE; 2682ba55f2f5SFrançois Tigeot ring->flush = gen6_bsd_ring_flush; 2683ba55f2f5SFrançois Tigeot ring->add_request = gen6_add_request; 2684ba55f2f5SFrançois Tigeot ring->get_seqno = gen6_ring_get_seqno; 2685ba55f2f5SFrançois Tigeot ring->set_seqno = ring_set_seqno; 2686ba55f2f5SFrançois Tigeot ring->irq_enable_mask = 2687ba55f2f5SFrançois Tigeot GT_RENDER_USER_INTERRUPT << GEN8_VCS2_IRQ_SHIFT; 2688ba55f2f5SFrançois Tigeot ring->irq_get = gen8_ring_get_irq; 2689ba55f2f5SFrançois Tigeot ring->irq_put = gen8_ring_put_irq; 2690ba55f2f5SFrançois Tigeot ring->dispatch_execbuffer = 2691ba55f2f5SFrançois Tigeot gen8_ring_dispatch_execbuffer; 269224edb884SFrançois Tigeot if (i915_semaphore_is_enabled(dev)) { 269324edb884SFrançois Tigeot ring->semaphore.sync_to = gen8_ring_sync; 269424edb884SFrançois Tigeot ring->semaphore.signal = gen8_xcs_signal; 269524edb884SFrançois Tigeot GEN8_RING_SEMAPHORE_INIT; 269624edb884SFrançois Tigeot } 26972c9916cdSFrançois Tigeot ring->init_hw = init_ring_common; 2698ba55f2f5SFrançois Tigeot 2699ba55f2f5SFrançois Tigeot return intel_init_ring_buffer(dev, ring); 2700ba55f2f5SFrançois Tigeot } 2701ba55f2f5SFrançois Tigeot 2702e3adcf8fSFrançois Tigeot int intel_init_blt_ring_buffer(struct drm_device *dev) 2703e3adcf8fSFrançois Tigeot { 2704ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 2705ba55f2f5SFrançois Tigeot struct intel_engine_cs *ring = &dev_priv->ring[BCS]; 2706e3adcf8fSFrançois Tigeot 2707686a02f1SFrançois Tigeot ring->name = "blitter ring"; 2708686a02f1SFrançois Tigeot ring->id = BCS; 2709686a02f1SFrançois Tigeot 2710686a02f1SFrançois Tigeot ring->mmio_base = BLT_RING_BASE; 2711686a02f1SFrançois Tigeot ring->write_tail = ring_write_tail; 27125d0b1887SFrançois Tigeot ring->flush = gen6_ring_flush; 2713686a02f1SFrançois Tigeot ring->add_request = gen6_add_request; 2714686a02f1SFrançois Tigeot ring->get_seqno = gen6_ring_get_seqno; 2715a2fdbec6SFrançois Tigeot ring->set_seqno = ring_set_seqno; 27169edbd4a0SFrançois Tigeot if (INTEL_INFO(dev)->gen >= 8) { 27179edbd4a0SFrançois Tigeot ring->irq_enable_mask = 27189edbd4a0SFrançois Tigeot GT_RENDER_USER_INTERRUPT << GEN8_BCS_IRQ_SHIFT; 27199edbd4a0SFrançois Tigeot ring->irq_get = gen8_ring_get_irq; 27209edbd4a0SFrançois Tigeot ring->irq_put = gen8_ring_put_irq; 27219edbd4a0SFrançois Tigeot ring->dispatch_execbuffer = gen8_ring_dispatch_execbuffer; 272224edb884SFrançois Tigeot if (i915_semaphore_is_enabled(dev)) { 272324edb884SFrançois Tigeot ring->semaphore.sync_to = gen8_ring_sync; 272424edb884SFrançois Tigeot ring->semaphore.signal = gen8_xcs_signal; 272524edb884SFrançois Tigeot GEN8_RING_SEMAPHORE_INIT; 272624edb884SFrançois Tigeot } 27279edbd4a0SFrançois Tigeot } else { 27285d0b1887SFrançois Tigeot ring->irq_enable_mask = GT_BLT_USER_INTERRUPT; 2729686a02f1SFrançois Tigeot ring->irq_get = gen6_ring_get_irq; 2730686a02f1SFrançois Tigeot ring->irq_put = gen6_ring_put_irq; 2731686a02f1SFrançois Tigeot ring->dispatch_execbuffer = gen6_ring_dispatch_execbuffer; 273224edb884SFrançois Tigeot if (i915_semaphore_is_enabled(dev)) { 2733ba55f2f5SFrançois Tigeot ring->semaphore.signal = gen6_signal; 273424edb884SFrançois Tigeot ring->semaphore.sync_to = gen6_ring_sync; 2735ba55f2f5SFrançois Tigeot /* 273624edb884SFrançois Tigeot * The current semaphore is only applied on pre-gen8 273724edb884SFrançois Tigeot * platform. And there is no VCS2 ring on the pre-gen8 273824edb884SFrançois Tigeot * platform. So the semaphore between BCS and VCS2 is 273924edb884SFrançois Tigeot * initialized as INVALID. Gen8 will initialize the 274024edb884SFrançois Tigeot * sema between BCS and VCS2 later. 2741ba55f2f5SFrançois Tigeot */ 2742ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[RCS] = MI_SEMAPHORE_SYNC_BR; 2743ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[VCS] = MI_SEMAPHORE_SYNC_BV; 2744ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[BCS] = MI_SEMAPHORE_SYNC_INVALID; 2745ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[VECS] = MI_SEMAPHORE_SYNC_BVE; 2746ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[VCS2] = MI_SEMAPHORE_SYNC_INVALID; 2747ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[RCS] = GEN6_RBSYNC; 2748ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[VCS] = GEN6_VBSYNC; 2749ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[BCS] = GEN6_NOSYNC; 2750ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[VECS] = GEN6_VEBSYNC; 2751ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[VCS2] = GEN6_NOSYNC; 275224edb884SFrançois Tigeot } 275324edb884SFrançois Tigeot } 27542c9916cdSFrançois Tigeot ring->init_hw = init_ring_common; 27555d0b1887SFrançois Tigeot 27565d0b1887SFrançois Tigeot return intel_init_ring_buffer(dev, ring); 27575d0b1887SFrançois Tigeot } 27585d0b1887SFrançois Tigeot 27595d0b1887SFrançois Tigeot int intel_init_vebox_ring_buffer(struct drm_device *dev) 27605d0b1887SFrançois Tigeot { 2761ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 2762ba55f2f5SFrançois Tigeot struct intel_engine_cs *ring = &dev_priv->ring[VECS]; 27635d0b1887SFrançois Tigeot 27645d0b1887SFrançois Tigeot ring->name = "video enhancement ring"; 27655d0b1887SFrançois Tigeot ring->id = VECS; 27665d0b1887SFrançois Tigeot 27675d0b1887SFrançois Tigeot ring->mmio_base = VEBOX_RING_BASE; 27685d0b1887SFrançois Tigeot ring->write_tail = ring_write_tail; 27695d0b1887SFrançois Tigeot ring->flush = gen6_ring_flush; 27705d0b1887SFrançois Tigeot ring->add_request = gen6_add_request; 27715d0b1887SFrançois Tigeot ring->get_seqno = gen6_ring_get_seqno; 27725d0b1887SFrançois Tigeot ring->set_seqno = ring_set_seqno; 27739edbd4a0SFrançois Tigeot 27749edbd4a0SFrançois Tigeot if (INTEL_INFO(dev)->gen >= 8) { 27759edbd4a0SFrançois Tigeot ring->irq_enable_mask = 27769edbd4a0SFrançois Tigeot GT_RENDER_USER_INTERRUPT << GEN8_VECS_IRQ_SHIFT; 27779edbd4a0SFrançois Tigeot ring->irq_get = gen8_ring_get_irq; 27789edbd4a0SFrançois Tigeot ring->irq_put = gen8_ring_put_irq; 27799edbd4a0SFrançois Tigeot ring->dispatch_execbuffer = gen8_ring_dispatch_execbuffer; 278024edb884SFrançois Tigeot if (i915_semaphore_is_enabled(dev)) { 278124edb884SFrançois Tigeot ring->semaphore.sync_to = gen8_ring_sync; 278224edb884SFrançois Tigeot ring->semaphore.signal = gen8_xcs_signal; 278324edb884SFrançois Tigeot GEN8_RING_SEMAPHORE_INIT; 278424edb884SFrançois Tigeot } 27859edbd4a0SFrançois Tigeot } else { 27869edbd4a0SFrançois Tigeot ring->irq_enable_mask = PM_VEBOX_USER_INTERRUPT; 27875d0b1887SFrançois Tigeot ring->irq_get = hsw_vebox_get_irq; 27885d0b1887SFrançois Tigeot ring->irq_put = hsw_vebox_put_irq; 27895d0b1887SFrançois Tigeot ring->dispatch_execbuffer = gen6_ring_dispatch_execbuffer; 279024edb884SFrançois Tigeot if (i915_semaphore_is_enabled(dev)) { 2791ba55f2f5SFrançois Tigeot ring->semaphore.sync_to = gen6_ring_sync; 2792ba55f2f5SFrançois Tigeot ring->semaphore.signal = gen6_signal; 2793ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[RCS] = MI_SEMAPHORE_SYNC_VER; 2794ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[VCS] = MI_SEMAPHORE_SYNC_VEV; 2795ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[BCS] = MI_SEMAPHORE_SYNC_VEB; 2796ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[VECS] = MI_SEMAPHORE_SYNC_INVALID; 2797ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[VCS2] = MI_SEMAPHORE_SYNC_INVALID; 2798ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[RCS] = GEN6_RVESYNC; 2799ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[VCS] = GEN6_VVESYNC; 2800ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[BCS] = GEN6_BVESYNC; 2801ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[VECS] = GEN6_NOSYNC; 2802ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[VCS2] = GEN6_NOSYNC; 280324edb884SFrançois Tigeot } 280424edb884SFrançois Tigeot } 28052c9916cdSFrançois Tigeot ring->init_hw = init_ring_common; 2806e3adcf8fSFrançois Tigeot 2807e3adcf8fSFrançois Tigeot return intel_init_ring_buffer(dev, ring); 2808e3adcf8fSFrançois Tigeot } 2809b030f26bSFrançois Tigeot 2810b030f26bSFrançois Tigeot int 2811ba55f2f5SFrançois Tigeot intel_ring_flush_all_caches(struct intel_engine_cs *ring) 2812b030f26bSFrançois Tigeot { 2813b030f26bSFrançois Tigeot int ret; 2814b030f26bSFrançois Tigeot 2815b030f26bSFrançois Tigeot if (!ring->gpu_caches_dirty) 2816b030f26bSFrançois Tigeot return 0; 2817b030f26bSFrançois Tigeot 2818b030f26bSFrançois Tigeot ret = ring->flush(ring, 0, I915_GEM_GPU_DOMAINS); 2819b030f26bSFrançois Tigeot if (ret) 2820b030f26bSFrançois Tigeot return ret; 2821b030f26bSFrançois Tigeot 2822a2fdbec6SFrançois Tigeot trace_i915_gem_ring_flush(ring, 0, I915_GEM_GPU_DOMAINS); 2823a2fdbec6SFrançois Tigeot 2824b030f26bSFrançois Tigeot ring->gpu_caches_dirty = false; 2825b030f26bSFrançois Tigeot return 0; 2826b030f26bSFrançois Tigeot } 2827b030f26bSFrançois Tigeot 2828b030f26bSFrançois Tigeot int 2829ba55f2f5SFrançois Tigeot intel_ring_invalidate_all_caches(struct intel_engine_cs *ring) 2830b030f26bSFrançois Tigeot { 2831b030f26bSFrançois Tigeot uint32_t flush_domains; 2832b030f26bSFrançois Tigeot int ret; 2833b030f26bSFrançois Tigeot 2834b030f26bSFrançois Tigeot flush_domains = 0; 2835b030f26bSFrançois Tigeot if (ring->gpu_caches_dirty) 2836b030f26bSFrançois Tigeot flush_domains = I915_GEM_GPU_DOMAINS; 2837b030f26bSFrançois Tigeot 2838b030f26bSFrançois Tigeot ret = ring->flush(ring, I915_GEM_GPU_DOMAINS, flush_domains); 2839b030f26bSFrançois Tigeot if (ret) 2840b030f26bSFrançois Tigeot return ret; 2841b030f26bSFrançois Tigeot 2842a2fdbec6SFrançois Tigeot trace_i915_gem_ring_flush(ring, I915_GEM_GPU_DOMAINS, flush_domains); 2843a2fdbec6SFrançois Tigeot 2844b030f26bSFrançois Tigeot ring->gpu_caches_dirty = false; 2845b030f26bSFrançois Tigeot return 0; 2846b030f26bSFrançois Tigeot } 2847ba55f2f5SFrançois Tigeot 2848ba55f2f5SFrançois Tigeot void 2849ba55f2f5SFrançois Tigeot intel_stop_ring_buffer(struct intel_engine_cs *ring) 2850ba55f2f5SFrançois Tigeot { 2851ba55f2f5SFrançois Tigeot int ret; 2852ba55f2f5SFrançois Tigeot 2853ba55f2f5SFrançois Tigeot if (!intel_ring_initialized(ring)) 2854ba55f2f5SFrançois Tigeot return; 2855ba55f2f5SFrançois Tigeot 2856ba55f2f5SFrançois Tigeot ret = intel_ring_idle(ring); 2857ba55f2f5SFrançois Tigeot if (ret && !i915_reset_in_progress(&to_i915(ring->dev)->gpu_error)) 2858ba55f2f5SFrançois Tigeot DRM_ERROR("failed to quiesce %s whilst cleaning up: %d\n", 2859ba55f2f5SFrançois Tigeot ring->name, ret); 2860ba55f2f5SFrançois Tigeot 2861ba55f2f5SFrançois Tigeot stop_ring(ring); 2862ba55f2f5SFrançois Tigeot } 2863