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 84*a05eeebfSFrançois Tigeot static 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 94*a05eeebfSFrançois Tigeot gen2_render_ring_flush(struct drm_i915_gem_request *req, 95686a02f1SFrançois Tigeot u32 invalidate_domains, 96686a02f1SFrançois Tigeot u32 flush_domains) 97686a02f1SFrançois Tigeot { 98*a05eeebfSFrançois Tigeot struct intel_engine_cs *ring = req->ring; 99686a02f1SFrançois Tigeot u32 cmd; 100686a02f1SFrançois Tigeot int ret; 101686a02f1SFrançois Tigeot 102686a02f1SFrançois Tigeot cmd = MI_FLUSH; 103686a02f1SFrançois Tigeot if (((invalidate_domains|flush_domains) & I915_GEM_DOMAIN_RENDER) == 0) 104686a02f1SFrançois Tigeot cmd |= MI_NO_WRITE_FLUSH; 105686a02f1SFrançois Tigeot 106686a02f1SFrançois Tigeot if (invalidate_domains & I915_GEM_DOMAIN_SAMPLER) 107686a02f1SFrançois Tigeot cmd |= MI_READ_FLUSH; 108686a02f1SFrançois Tigeot 109*a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 2); 110686a02f1SFrançois Tigeot if (ret) 111686a02f1SFrançois Tigeot return ret; 112686a02f1SFrançois Tigeot 113686a02f1SFrançois Tigeot intel_ring_emit(ring, cmd); 114686a02f1SFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 115686a02f1SFrançois Tigeot intel_ring_advance(ring); 116686a02f1SFrançois Tigeot 117686a02f1SFrançois Tigeot return 0; 118686a02f1SFrançois Tigeot } 119686a02f1SFrançois Tigeot 120686a02f1SFrançois Tigeot static int 121*a05eeebfSFrançois Tigeot gen4_render_ring_flush(struct drm_i915_gem_request *req, 122686a02f1SFrançois Tigeot u32 invalidate_domains, 123686a02f1SFrançois Tigeot u32 flush_domains) 124e3adcf8fSFrançois Tigeot { 125*a05eeebfSFrançois Tigeot struct intel_engine_cs *ring = req->ring; 126e3adcf8fSFrançois Tigeot struct drm_device *dev = ring->dev; 127686a02f1SFrançois Tigeot u32 cmd; 128e3adcf8fSFrançois Tigeot int ret; 129e3adcf8fSFrançois Tigeot 130e3adcf8fSFrançois Tigeot /* 131e3adcf8fSFrançois Tigeot * read/write caches: 132e3adcf8fSFrançois Tigeot * 133e3adcf8fSFrançois Tigeot * I915_GEM_DOMAIN_RENDER is always invalidated, but is 134e3adcf8fSFrançois Tigeot * only flushed if MI_NO_WRITE_FLUSH is unset. On 965, it is 135e3adcf8fSFrançois Tigeot * also flushed at 2d versus 3d pipeline switches. 136e3adcf8fSFrançois Tigeot * 137e3adcf8fSFrançois Tigeot * read-only caches: 138e3adcf8fSFrançois Tigeot * 139e3adcf8fSFrançois Tigeot * I915_GEM_DOMAIN_SAMPLER is flushed on pre-965 if 140e3adcf8fSFrançois Tigeot * MI_READ_FLUSH is set, and is always flushed on 965. 141e3adcf8fSFrançois Tigeot * 142e3adcf8fSFrançois Tigeot * I915_GEM_DOMAIN_COMMAND may not exist? 143e3adcf8fSFrançois Tigeot * 144e3adcf8fSFrançois Tigeot * I915_GEM_DOMAIN_INSTRUCTION, which exists on 965, is 145e3adcf8fSFrançois Tigeot * invalidated when MI_EXE_FLUSH is set. 146e3adcf8fSFrançois Tigeot * 147e3adcf8fSFrançois Tigeot * I915_GEM_DOMAIN_VERTEX, which exists on 965, is 148e3adcf8fSFrançois Tigeot * invalidated with every MI_FLUSH. 149e3adcf8fSFrançois Tigeot * 150e3adcf8fSFrançois Tigeot * TLBs: 151e3adcf8fSFrançois Tigeot * 152e3adcf8fSFrançois Tigeot * On 965, TLBs associated with I915_GEM_DOMAIN_COMMAND 153e3adcf8fSFrançois Tigeot * and I915_GEM_DOMAIN_CPU in are invalidated at PTE write and 154e3adcf8fSFrançois Tigeot * I915_GEM_DOMAIN_RENDER and I915_GEM_DOMAIN_SAMPLER 155e3adcf8fSFrançois Tigeot * are flushed at any MI_FLUSH. 156e3adcf8fSFrançois Tigeot */ 157e3adcf8fSFrançois Tigeot 158e3adcf8fSFrançois Tigeot cmd = MI_FLUSH | MI_NO_WRITE_FLUSH; 159686a02f1SFrançois Tigeot if ((invalidate_domains|flush_domains) & I915_GEM_DOMAIN_RENDER) 160e3adcf8fSFrançois Tigeot cmd &= ~MI_NO_WRITE_FLUSH; 161e3adcf8fSFrançois Tigeot if (invalidate_domains & I915_GEM_DOMAIN_INSTRUCTION) 162e3adcf8fSFrançois Tigeot cmd |= MI_EXE_FLUSH; 163e3adcf8fSFrançois Tigeot 164e3adcf8fSFrançois Tigeot if (invalidate_domains & I915_GEM_DOMAIN_COMMAND && 165e3adcf8fSFrançois Tigeot (IS_G4X(dev) || IS_GEN5(dev))) 166e3adcf8fSFrançois Tigeot cmd |= MI_INVALIDATE_ISP; 167e3adcf8fSFrançois Tigeot 168*a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 2); 169e3adcf8fSFrançois Tigeot if (ret) 170e3adcf8fSFrançois Tigeot return ret; 171e3adcf8fSFrançois Tigeot 172e3adcf8fSFrançois Tigeot intel_ring_emit(ring, cmd); 173e3adcf8fSFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 174e3adcf8fSFrançois Tigeot intel_ring_advance(ring); 175e3adcf8fSFrançois Tigeot 176e3adcf8fSFrançois Tigeot return 0; 177e3adcf8fSFrançois Tigeot } 178e3adcf8fSFrançois Tigeot 179e3adcf8fSFrançois Tigeot /** 180e3adcf8fSFrançois Tigeot * Emits a PIPE_CONTROL with a non-zero post-sync operation, for 181e3adcf8fSFrançois Tigeot * implementing two workarounds on gen6. From section 1.4.7.1 182e3adcf8fSFrançois Tigeot * "PIPE_CONTROL" of the Sandy Bridge PRM volume 2 part 1: 183e3adcf8fSFrançois Tigeot * 184e3adcf8fSFrançois Tigeot * [DevSNB-C+{W/A}] Before any depth stall flush (including those 185e3adcf8fSFrançois Tigeot * produced by non-pipelined state commands), software needs to first 186e3adcf8fSFrançois Tigeot * send a PIPE_CONTROL with no bits set except Post-Sync Operation != 187e3adcf8fSFrançois Tigeot * 0. 188e3adcf8fSFrançois Tigeot * 189e3adcf8fSFrançois Tigeot * [Dev-SNB{W/A}]: Before a PIPE_CONTROL with Write Cache Flush Enable 190e3adcf8fSFrançois Tigeot * =1, a PIPE_CONTROL with any non-zero post-sync-op is required. 191e3adcf8fSFrançois Tigeot * 192e3adcf8fSFrançois Tigeot * And the workaround for these two requires this workaround first: 193e3adcf8fSFrançois Tigeot * 194e3adcf8fSFrançois Tigeot * [Dev-SNB{W/A}]: Pipe-control with CS-stall bit set must be sent 195e3adcf8fSFrançois Tigeot * BEFORE the pipe-control with a post-sync op and no write-cache 196e3adcf8fSFrançois Tigeot * flushes. 197e3adcf8fSFrançois Tigeot * 198e3adcf8fSFrançois Tigeot * And this last workaround is tricky because of the requirements on 199e3adcf8fSFrançois Tigeot * that bit. From section 1.4.7.2.3 "Stall" of the Sandy Bridge PRM 200e3adcf8fSFrançois Tigeot * volume 2 part 1: 201e3adcf8fSFrançois Tigeot * 202e3adcf8fSFrançois Tigeot * "1 of the following must also be set: 203e3adcf8fSFrançois Tigeot * - Render Target Cache Flush Enable ([12] of DW1) 204e3adcf8fSFrançois Tigeot * - Depth Cache Flush Enable ([0] of DW1) 205e3adcf8fSFrançois Tigeot * - Stall at Pixel Scoreboard ([1] of DW1) 206e3adcf8fSFrançois Tigeot * - Depth Stall ([13] of DW1) 207e3adcf8fSFrançois Tigeot * - Post-Sync Operation ([13] of DW1) 208e3adcf8fSFrançois Tigeot * - Notify Enable ([8] of DW1)" 209e3adcf8fSFrançois Tigeot * 210e3adcf8fSFrançois Tigeot * The cache flushes require the workaround flush that triggered this 211e3adcf8fSFrançois Tigeot * one, so we can't use it. Depth stall would trigger the same. 212e3adcf8fSFrançois Tigeot * Post-sync nonzero is what triggered this second workaround, so we 213e3adcf8fSFrançois Tigeot * can't use that one either. Notify enable is IRQs, which aren't 214e3adcf8fSFrançois Tigeot * really our business. That leaves only stall at scoreboard. 215e3adcf8fSFrançois Tigeot */ 216e3adcf8fSFrançois Tigeot static int 217*a05eeebfSFrançois Tigeot intel_emit_post_sync_nonzero_flush(struct drm_i915_gem_request *req) 218e3adcf8fSFrançois Tigeot { 219*a05eeebfSFrançois Tigeot struct intel_engine_cs *ring = req->ring; 220ba55f2f5SFrançois Tigeot u32 scratch_addr = ring->scratch.gtt_offset + 2 * CACHELINE_BYTES; 221e3adcf8fSFrançois Tigeot int ret; 222e3adcf8fSFrançois Tigeot 223*a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 6); 224e3adcf8fSFrançois Tigeot if (ret) 225e3adcf8fSFrançois Tigeot return ret; 226e3adcf8fSFrançois Tigeot 227e3adcf8fSFrançois Tigeot intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(5)); 228e3adcf8fSFrançois Tigeot intel_ring_emit(ring, PIPE_CONTROL_CS_STALL | 229e3adcf8fSFrançois Tigeot PIPE_CONTROL_STALL_AT_SCOREBOARD); 230e3adcf8fSFrançois Tigeot intel_ring_emit(ring, scratch_addr | PIPE_CONTROL_GLOBAL_GTT); /* address */ 231e3adcf8fSFrançois Tigeot intel_ring_emit(ring, 0); /* low dword */ 232e3adcf8fSFrançois Tigeot intel_ring_emit(ring, 0); /* high dword */ 233e3adcf8fSFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 234e3adcf8fSFrançois Tigeot intel_ring_advance(ring); 235e3adcf8fSFrançois Tigeot 236*a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 6); 237e3adcf8fSFrançois Tigeot if (ret) 238e3adcf8fSFrançois Tigeot return ret; 239e3adcf8fSFrançois Tigeot 240e3adcf8fSFrançois Tigeot intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(5)); 241e3adcf8fSFrançois Tigeot intel_ring_emit(ring, PIPE_CONTROL_QW_WRITE); 242e3adcf8fSFrançois Tigeot intel_ring_emit(ring, scratch_addr | PIPE_CONTROL_GLOBAL_GTT); /* address */ 243e3adcf8fSFrançois Tigeot intel_ring_emit(ring, 0); 244e3adcf8fSFrançois Tigeot intel_ring_emit(ring, 0); 245e3adcf8fSFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 246e3adcf8fSFrançois Tigeot intel_ring_advance(ring); 247e3adcf8fSFrançois Tigeot 248e3adcf8fSFrançois Tigeot return 0; 249e3adcf8fSFrançois Tigeot } 250e3adcf8fSFrançois Tigeot 251e3adcf8fSFrançois Tigeot static int 252*a05eeebfSFrançois Tigeot gen6_render_ring_flush(struct drm_i915_gem_request *req, 253e3adcf8fSFrançois Tigeot u32 invalidate_domains, u32 flush_domains) 254e3adcf8fSFrançois Tigeot { 255*a05eeebfSFrançois Tigeot struct intel_engine_cs *ring = req->ring; 256e3adcf8fSFrançois Tigeot u32 flags = 0; 257ba55f2f5SFrançois Tigeot u32 scratch_addr = ring->scratch.gtt_offset + 2 * CACHELINE_BYTES; 258e3adcf8fSFrançois Tigeot int ret; 259e3adcf8fSFrançois Tigeot 260e3adcf8fSFrançois Tigeot /* Force SNB workarounds for PIPE_CONTROL flushes */ 261*a05eeebfSFrançois Tigeot ret = intel_emit_post_sync_nonzero_flush(req); 262686a02f1SFrançois Tigeot if (ret) 263686a02f1SFrançois Tigeot return ret; 264e3adcf8fSFrançois Tigeot 265e3adcf8fSFrançois Tigeot /* Just flush everything. Experiments have shown that reducing the 266e3adcf8fSFrançois Tigeot * number of bits based on the write domains has little performance 267e3adcf8fSFrançois Tigeot * impact. 268e3adcf8fSFrançois Tigeot */ 269b5c29a34SFrançois Tigeot if (flush_domains) { 270e3adcf8fSFrançois Tigeot flags |= PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH; 271b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_DEPTH_CACHE_FLUSH; 272b5c29a34SFrançois Tigeot /* 273b5c29a34SFrançois Tigeot * Ensure that any following seqno writes only happen 274b5c29a34SFrançois Tigeot * when the render cache is indeed flushed. 275b5c29a34SFrançois Tigeot */ 276b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_CS_STALL; 277b5c29a34SFrançois Tigeot } 278b5c29a34SFrançois Tigeot if (invalidate_domains) { 279686a02f1SFrançois Tigeot flags |= PIPE_CONTROL_TLB_INVALIDATE; 280e3adcf8fSFrançois Tigeot flags |= PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE; 281e3adcf8fSFrançois Tigeot flags |= PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE; 282e3adcf8fSFrançois Tigeot flags |= PIPE_CONTROL_VF_CACHE_INVALIDATE; 283e3adcf8fSFrançois Tigeot flags |= PIPE_CONTROL_CONST_CACHE_INVALIDATE; 284e3adcf8fSFrançois Tigeot flags |= PIPE_CONTROL_STATE_CACHE_INVALIDATE; 285686a02f1SFrançois Tigeot /* 286b5c29a34SFrançois Tigeot * TLB invalidate requires a post-sync write. 287686a02f1SFrançois Tigeot */ 288b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_QW_WRITE | PIPE_CONTROL_CS_STALL; 289b5c29a34SFrançois Tigeot } 290e3adcf8fSFrançois Tigeot 291*a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 4); 292e3adcf8fSFrançois Tigeot if (ret) 293e3adcf8fSFrançois Tigeot return ret; 294e3adcf8fSFrançois Tigeot 295b5c29a34SFrançois Tigeot intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(4)); 296e3adcf8fSFrançois Tigeot intel_ring_emit(ring, flags); 297e3adcf8fSFrançois Tigeot intel_ring_emit(ring, scratch_addr | PIPE_CONTROL_GLOBAL_GTT); 298b5c29a34SFrançois Tigeot intel_ring_emit(ring, 0); 299b5c29a34SFrançois Tigeot intel_ring_advance(ring); 300b5c29a34SFrançois Tigeot 301b5c29a34SFrançois Tigeot return 0; 302b5c29a34SFrançois Tigeot } 303b5c29a34SFrançois Tigeot 304b5c29a34SFrançois Tigeot static int 305*a05eeebfSFrançois Tigeot gen7_render_ring_cs_stall_wa(struct drm_i915_gem_request *req) 306b5c29a34SFrançois Tigeot { 307*a05eeebfSFrançois Tigeot struct intel_engine_cs *ring = req->ring; 308b5c29a34SFrançois Tigeot int ret; 309b5c29a34SFrançois Tigeot 310*a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 4); 311b5c29a34SFrançois Tigeot if (ret) 312b5c29a34SFrançois Tigeot return ret; 313b5c29a34SFrançois Tigeot 314b5c29a34SFrançois Tigeot intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(4)); 315b5c29a34SFrançois Tigeot intel_ring_emit(ring, PIPE_CONTROL_CS_STALL | 316b5c29a34SFrançois Tigeot PIPE_CONTROL_STALL_AT_SCOREBOARD); 317b5c29a34SFrançois Tigeot intel_ring_emit(ring, 0); 318b5c29a34SFrançois Tigeot intel_ring_emit(ring, 0); 319b5c29a34SFrançois Tigeot intel_ring_advance(ring); 320b5c29a34SFrançois Tigeot 321b5c29a34SFrançois Tigeot return 0; 322b5c29a34SFrançois Tigeot } 323b5c29a34SFrançois Tigeot 324b5c29a34SFrançois Tigeot static int 325*a05eeebfSFrançois Tigeot gen7_render_ring_flush(struct drm_i915_gem_request *req, 326b5c29a34SFrançois Tigeot u32 invalidate_domains, u32 flush_domains) 327b5c29a34SFrançois Tigeot { 328*a05eeebfSFrançois Tigeot struct intel_engine_cs *ring = req->ring; 329b5c29a34SFrançois Tigeot u32 flags = 0; 330ba55f2f5SFrançois Tigeot u32 scratch_addr = ring->scratch.gtt_offset + 2 * CACHELINE_BYTES; 331b5c29a34SFrançois Tigeot int ret; 332b5c29a34SFrançois Tigeot 333b5c29a34SFrançois Tigeot /* 334b5c29a34SFrançois Tigeot * Ensure that any following seqno writes only happen when the render 335b5c29a34SFrançois Tigeot * cache is indeed flushed. 336b5c29a34SFrançois Tigeot * 337b5c29a34SFrançois Tigeot * Workaround: 4th PIPE_CONTROL command (except the ones with only 338b5c29a34SFrançois Tigeot * read-cache invalidate bits set) must have the CS_STALL bit set. We 339b5c29a34SFrançois Tigeot * don't try to be clever and just set it unconditionally. 340b5c29a34SFrançois Tigeot */ 341b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_CS_STALL; 342b5c29a34SFrançois Tigeot 343b5c29a34SFrançois Tigeot /* Just flush everything. Experiments have shown that reducing the 344b5c29a34SFrançois Tigeot * number of bits based on the write domains has little performance 345b5c29a34SFrançois Tigeot * impact. 346b5c29a34SFrançois Tigeot */ 347b5c29a34SFrançois Tigeot if (flush_domains) { 348b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH; 349b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_DEPTH_CACHE_FLUSH; 350b49c8cf9SFrançois Tigeot flags |= PIPE_CONTROL_FLUSH_ENABLE; 351b5c29a34SFrançois Tigeot } 352b5c29a34SFrançois Tigeot if (invalidate_domains) { 353b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_TLB_INVALIDATE; 354b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE; 355b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE; 356b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_VF_CACHE_INVALIDATE; 357b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_CONST_CACHE_INVALIDATE; 358b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_STATE_CACHE_INVALIDATE; 3592c9916cdSFrançois Tigeot flags |= PIPE_CONTROL_MEDIA_STATE_CLEAR; 360b5c29a34SFrançois Tigeot /* 361b5c29a34SFrançois Tigeot * TLB invalidate requires a post-sync write. 362b5c29a34SFrançois Tigeot */ 363b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_QW_WRITE; 364a2fdbec6SFrançois Tigeot flags |= PIPE_CONTROL_GLOBAL_GTT_IVB; 365b5c29a34SFrançois Tigeot 3660dbf0ea8SMatthew Dillon flags |= PIPE_CONTROL_STALL_AT_SCOREBOARD; 3670dbf0ea8SMatthew Dillon 368b5c29a34SFrançois Tigeot /* Workaround: we must issue a pipe_control with CS-stall bit 369b5c29a34SFrançois Tigeot * set before a pipe_control command that has the state cache 370b5c29a34SFrançois Tigeot * invalidate bit set. */ 371*a05eeebfSFrançois Tigeot gen7_render_ring_cs_stall_wa(req); 372b5c29a34SFrançois Tigeot } 373b5c29a34SFrançois Tigeot 374*a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 4); 375b5c29a34SFrançois Tigeot if (ret) 376b5c29a34SFrançois Tigeot return ret; 377b5c29a34SFrançois Tigeot 378b5c29a34SFrançois Tigeot intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(4)); 379b5c29a34SFrançois Tigeot intel_ring_emit(ring, flags); 380a2fdbec6SFrançois Tigeot intel_ring_emit(ring, scratch_addr); 381b5c29a34SFrançois Tigeot intel_ring_emit(ring, 0); 382e3adcf8fSFrançois Tigeot intel_ring_advance(ring); 383e3adcf8fSFrançois Tigeot 384e3adcf8fSFrançois Tigeot return 0; 385e3adcf8fSFrançois Tigeot } 386e3adcf8fSFrançois Tigeot 3879edbd4a0SFrançois Tigeot static int 388*a05eeebfSFrançois Tigeot gen8_emit_pipe_control(struct drm_i915_gem_request *req, 38924edb884SFrançois Tigeot u32 flags, u32 scratch_addr) 39024edb884SFrançois Tigeot { 391*a05eeebfSFrançois Tigeot struct intel_engine_cs *ring = req->ring; 39224edb884SFrançois Tigeot int ret; 39324edb884SFrançois Tigeot 394*a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 6); 39524edb884SFrançois Tigeot if (ret) 39624edb884SFrançois Tigeot return ret; 39724edb884SFrançois Tigeot 39824edb884SFrançois Tigeot intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(6)); 39924edb884SFrançois Tigeot intel_ring_emit(ring, flags); 40024edb884SFrançois Tigeot intel_ring_emit(ring, scratch_addr); 40124edb884SFrançois Tigeot intel_ring_emit(ring, 0); 40224edb884SFrançois Tigeot intel_ring_emit(ring, 0); 40324edb884SFrançois Tigeot intel_ring_emit(ring, 0); 40424edb884SFrançois Tigeot intel_ring_advance(ring); 40524edb884SFrançois Tigeot 40624edb884SFrançois Tigeot return 0; 40724edb884SFrançois Tigeot } 40824edb884SFrançois Tigeot 40924edb884SFrançois Tigeot static int 410*a05eeebfSFrançois Tigeot gen8_render_ring_flush(struct drm_i915_gem_request *req, 4119edbd4a0SFrançois Tigeot u32 invalidate_domains, u32 flush_domains) 4129edbd4a0SFrançois Tigeot { 4139edbd4a0SFrançois Tigeot u32 flags = 0; 414*a05eeebfSFrançois Tigeot u32 scratch_addr = req->ring->scratch.gtt_offset + 2 * CACHELINE_BYTES; 4159edbd4a0SFrançois Tigeot int ret; 4169edbd4a0SFrançois Tigeot 4179edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_CS_STALL; 4189edbd4a0SFrançois Tigeot 4199edbd4a0SFrançois Tigeot if (flush_domains) { 4209edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH; 4219edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_DEPTH_CACHE_FLUSH; 422b49c8cf9SFrançois Tigeot flags |= PIPE_CONTROL_FLUSH_ENABLE; 4239edbd4a0SFrançois Tigeot } 4249edbd4a0SFrançois Tigeot if (invalidate_domains) { 4259edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_TLB_INVALIDATE; 4269edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE; 4279edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE; 4289edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_VF_CACHE_INVALIDATE; 4299edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_CONST_CACHE_INVALIDATE; 4309edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_STATE_CACHE_INVALIDATE; 4319edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_QW_WRITE; 4329edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_GLOBAL_GTT_IVB; 4339edbd4a0SFrançois Tigeot 43424edb884SFrançois Tigeot /* WaCsStallBeforeStateCacheInvalidate:bdw,chv */ 435*a05eeebfSFrançois Tigeot ret = gen8_emit_pipe_control(req, 43624edb884SFrançois Tigeot PIPE_CONTROL_CS_STALL | 43724edb884SFrançois Tigeot PIPE_CONTROL_STALL_AT_SCOREBOARD, 43824edb884SFrançois Tigeot 0); 4399edbd4a0SFrançois Tigeot if (ret) 4409edbd4a0SFrançois Tigeot return ret; 44124edb884SFrançois Tigeot } 4429edbd4a0SFrançois Tigeot 443*a05eeebfSFrançois Tigeot return gen8_emit_pipe_control(req, flags, scratch_addr); 4449edbd4a0SFrançois Tigeot } 4459edbd4a0SFrançois Tigeot 446ba55f2f5SFrançois Tigeot static void ring_write_tail(struct intel_engine_cs *ring, 447b5c29a34SFrançois Tigeot u32 value) 448e3adcf8fSFrançois Tigeot { 449ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = ring->dev->dev_private; 450e3adcf8fSFrançois Tigeot I915_WRITE_TAIL(ring, value); 451e3adcf8fSFrançois Tigeot } 452e3adcf8fSFrançois Tigeot 453ba55f2f5SFrançois Tigeot u64 intel_ring_get_active_head(struct intel_engine_cs *ring) 454e3adcf8fSFrançois Tigeot { 455ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = ring->dev->dev_private; 456ba55f2f5SFrançois Tigeot u64 acthd; 457e3adcf8fSFrançois Tigeot 458ba55f2f5SFrançois Tigeot if (INTEL_INFO(ring->dev)->gen >= 8) 459ba55f2f5SFrançois Tigeot acthd = I915_READ64_2x32(RING_ACTHD(ring->mmio_base), 460ba55f2f5SFrançois Tigeot RING_ACTHD_UDW(ring->mmio_base)); 461ba55f2f5SFrançois Tigeot else if (INTEL_INFO(ring->dev)->gen >= 4) 462ba55f2f5SFrançois Tigeot acthd = I915_READ(RING_ACTHD(ring->mmio_base)); 463ba55f2f5SFrançois Tigeot else 464ba55f2f5SFrançois Tigeot acthd = I915_READ(ACTHD); 465ba55f2f5SFrançois Tigeot 466ba55f2f5SFrançois Tigeot return acthd; 467e3adcf8fSFrançois Tigeot } 468e3adcf8fSFrançois Tigeot 469ba55f2f5SFrançois Tigeot static void ring_setup_phys_status_page(struct intel_engine_cs *ring) 4705d0b1887SFrançois Tigeot { 4715d0b1887SFrançois Tigeot struct drm_i915_private *dev_priv = ring->dev->dev_private; 4725d0b1887SFrançois Tigeot u32 addr; 4735d0b1887SFrançois Tigeot 4745d0b1887SFrançois Tigeot addr = dev_priv->status_page_dmah->busaddr; 4755d0b1887SFrançois Tigeot if (INTEL_INFO(ring->dev)->gen >= 4) 4765d0b1887SFrançois Tigeot addr |= (dev_priv->status_page_dmah->busaddr >> 28) & 0xf0; 4775d0b1887SFrançois Tigeot I915_WRITE(HWS_PGA, addr); 4785d0b1887SFrançois Tigeot } 4795d0b1887SFrançois Tigeot 480477eb7f9SFrançois Tigeot static void intel_ring_setup_status_page(struct intel_engine_cs *ring) 481477eb7f9SFrançois Tigeot { 482477eb7f9SFrançois Tigeot struct drm_device *dev = ring->dev; 483477eb7f9SFrançois Tigeot struct drm_i915_private *dev_priv = ring->dev->dev_private; 484477eb7f9SFrançois Tigeot u32 mmio = 0; 485477eb7f9SFrançois Tigeot 486477eb7f9SFrançois Tigeot /* The ring status page addresses are no longer next to the rest of 487477eb7f9SFrançois Tigeot * the ring registers as of gen7. 488477eb7f9SFrançois Tigeot */ 489477eb7f9SFrançois Tigeot if (IS_GEN7(dev)) { 490477eb7f9SFrançois Tigeot switch (ring->id) { 491477eb7f9SFrançois Tigeot case RCS: 492477eb7f9SFrançois Tigeot mmio = RENDER_HWS_PGA_GEN7; 493477eb7f9SFrançois Tigeot break; 494477eb7f9SFrançois Tigeot case BCS: 495477eb7f9SFrançois Tigeot mmio = BLT_HWS_PGA_GEN7; 496477eb7f9SFrançois Tigeot break; 497477eb7f9SFrançois Tigeot /* 498477eb7f9SFrançois Tigeot * VCS2 actually doesn't exist on Gen7. Only shut up 499477eb7f9SFrançois Tigeot * gcc switch check warning 500477eb7f9SFrançois Tigeot */ 501477eb7f9SFrançois Tigeot case VCS2: 502477eb7f9SFrançois Tigeot case VCS: 503477eb7f9SFrançois Tigeot mmio = BSD_HWS_PGA_GEN7; 504477eb7f9SFrançois Tigeot break; 505477eb7f9SFrançois Tigeot case VECS: 506477eb7f9SFrançois Tigeot mmio = VEBOX_HWS_PGA_GEN7; 507477eb7f9SFrançois Tigeot break; 508477eb7f9SFrançois Tigeot } 509477eb7f9SFrançois Tigeot } else if (IS_GEN6(ring->dev)) { 510477eb7f9SFrançois Tigeot mmio = RING_HWS_PGA_GEN6(ring->mmio_base); 511477eb7f9SFrançois Tigeot } else { 512477eb7f9SFrançois Tigeot /* XXX: gen8 returns to sanity */ 513477eb7f9SFrançois Tigeot mmio = RING_HWS_PGA(ring->mmio_base); 514477eb7f9SFrançois Tigeot } 515477eb7f9SFrançois Tigeot 516477eb7f9SFrançois Tigeot I915_WRITE(mmio, (u32)ring->status_page.gfx_addr); 517477eb7f9SFrançois Tigeot POSTING_READ(mmio); 518477eb7f9SFrançois Tigeot 519477eb7f9SFrançois Tigeot /* 520477eb7f9SFrançois Tigeot * Flush the TLB for this page 521477eb7f9SFrançois Tigeot * 522477eb7f9SFrançois Tigeot * FIXME: These two bits have disappeared on gen8, so a question 523477eb7f9SFrançois Tigeot * arises: do we still need this and if so how should we go about 524477eb7f9SFrançois Tigeot * invalidating the TLB? 525477eb7f9SFrançois Tigeot */ 526477eb7f9SFrançois Tigeot if (INTEL_INFO(dev)->gen >= 6 && INTEL_INFO(dev)->gen < 8) { 527477eb7f9SFrançois Tigeot u32 reg = RING_INSTPM(ring->mmio_base); 528477eb7f9SFrançois Tigeot 529477eb7f9SFrançois Tigeot /* ring should be idle before issuing a sync flush*/ 530477eb7f9SFrançois Tigeot WARN_ON((I915_READ_MODE(ring) & MODE_IDLE) == 0); 531477eb7f9SFrançois Tigeot 532477eb7f9SFrançois Tigeot I915_WRITE(reg, 533477eb7f9SFrançois Tigeot _MASKED_BIT_ENABLE(INSTPM_TLB_INVALIDATE | 534477eb7f9SFrançois Tigeot INSTPM_SYNC_FLUSH)); 535477eb7f9SFrançois Tigeot if (wait_for((I915_READ(reg) & INSTPM_SYNC_FLUSH) == 0, 536477eb7f9SFrançois Tigeot 1000)) 537477eb7f9SFrançois Tigeot DRM_ERROR("%s: wait for SyncFlush to complete for TLB invalidation timed out\n", 538477eb7f9SFrançois Tigeot ring->name); 539477eb7f9SFrançois Tigeot } 540477eb7f9SFrançois Tigeot } 541477eb7f9SFrançois Tigeot 542ba55f2f5SFrançois Tigeot static bool stop_ring(struct intel_engine_cs *ring) 543e3adcf8fSFrançois Tigeot { 544ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = to_i915(ring->dev); 545e3adcf8fSFrançois Tigeot 546ba55f2f5SFrançois Tigeot if (!IS_GEN2(ring->dev)) { 547ba55f2f5SFrançois Tigeot I915_WRITE_MODE(ring, _MASKED_BIT_ENABLE(STOP_RING)); 5481b13d190SFrançois Tigeot if (wait_for((I915_READ_MODE(ring) & MODE_IDLE) != 0, 1000)) { 549ba55f2f5SFrançois Tigeot DRM_ERROR("%s : timed out trying to stop ring\n", ring->name); 5501b13d190SFrançois Tigeot /* Sometimes we observe that the idle flag is not 5511b13d190SFrançois Tigeot * set even though the ring is empty. So double 5521b13d190SFrançois Tigeot * check before giving up. 5531b13d190SFrançois Tigeot */ 5541b13d190SFrançois Tigeot if (I915_READ_HEAD(ring) != I915_READ_TAIL(ring)) 555ba55f2f5SFrançois Tigeot return false; 556ba55f2f5SFrançois Tigeot } 557ba55f2f5SFrançois Tigeot } 558686a02f1SFrançois Tigeot 559e3adcf8fSFrançois Tigeot I915_WRITE_CTL(ring, 0); 560e3adcf8fSFrançois Tigeot I915_WRITE_HEAD(ring, 0); 561e3adcf8fSFrançois Tigeot ring->write_tail(ring, 0); 562e3adcf8fSFrançois Tigeot 563ba55f2f5SFrançois Tigeot if (!IS_GEN2(ring->dev)) { 564ba55f2f5SFrançois Tigeot (void)I915_READ_CTL(ring); 565ba55f2f5SFrançois Tigeot I915_WRITE_MODE(ring, _MASKED_BIT_DISABLE(STOP_RING)); 566ba55f2f5SFrançois Tigeot } 567e3adcf8fSFrançois Tigeot 568ba55f2f5SFrançois Tigeot return (I915_READ_HEAD(ring) & HEAD_ADDR) == 0; 569ba55f2f5SFrançois Tigeot } 570ba55f2f5SFrançois Tigeot 571ba55f2f5SFrançois Tigeot static int init_ring_common(struct intel_engine_cs *ring) 572ba55f2f5SFrançois Tigeot { 573ba55f2f5SFrançois Tigeot struct drm_device *dev = ring->dev; 574ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 575ba55f2f5SFrançois Tigeot struct intel_ringbuffer *ringbuf = ring->buffer; 576ba55f2f5SFrançois Tigeot struct drm_i915_gem_object *obj = ringbuf->obj; 577ba55f2f5SFrançois Tigeot int ret = 0; 578ba55f2f5SFrançois Tigeot 5792c9916cdSFrançois Tigeot intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL); 580ba55f2f5SFrançois Tigeot 581ba55f2f5SFrançois Tigeot if (!stop_ring(ring)) { 582ba55f2f5SFrançois Tigeot /* G45 ring initialization often fails to reset head to zero */ 583b5c29a34SFrançois Tigeot DRM_DEBUG_KMS("%s head not reset to zero " 584e3adcf8fSFrançois Tigeot "ctl %08x head %08x tail %08x start %08x\n", 585e3adcf8fSFrançois Tigeot ring->name, 586e3adcf8fSFrançois Tigeot I915_READ_CTL(ring), 587e3adcf8fSFrançois Tigeot I915_READ_HEAD(ring), 588e3adcf8fSFrançois Tigeot I915_READ_TAIL(ring), 589e3adcf8fSFrançois Tigeot I915_READ_START(ring)); 590e3adcf8fSFrançois Tigeot 591ba55f2f5SFrançois Tigeot if (!stop_ring(ring)) { 592e3adcf8fSFrançois Tigeot DRM_ERROR("failed to set %s head to zero " 593e3adcf8fSFrançois Tigeot "ctl %08x head %08x tail %08x start %08x\n", 594e3adcf8fSFrançois Tigeot ring->name, 595e3adcf8fSFrançois Tigeot I915_READ_CTL(ring), 596e3adcf8fSFrançois Tigeot I915_READ_HEAD(ring), 597e3adcf8fSFrançois Tigeot I915_READ_TAIL(ring), 598e3adcf8fSFrançois Tigeot I915_READ_START(ring)); 599686a02f1SFrançois Tigeot ret = -EIO; 600686a02f1SFrançois Tigeot goto out; 601e3adcf8fSFrançois Tigeot } 602ba55f2f5SFrançois Tigeot } 603ba55f2f5SFrançois Tigeot 604ba55f2f5SFrançois Tigeot if (I915_NEED_GFX_HWS(dev)) 605ba55f2f5SFrançois Tigeot intel_ring_setup_status_page(ring); 606ba55f2f5SFrançois Tigeot else 607ba55f2f5SFrançois Tigeot ring_setup_phys_status_page(ring); 608ba55f2f5SFrançois Tigeot 6090f370975SMatthew Dillon /* Enforce ordering by reading HEAD register back */ 6100f370975SMatthew Dillon I915_READ_HEAD(ring); 6110f370975SMatthew Dillon 612ba55f2f5SFrançois Tigeot /* Initialize the ring. This must happen _after_ we've cleared the ring 613ba55f2f5SFrançois Tigeot * registers with the above sequence (the readback of the HEAD registers 614ba55f2f5SFrançois Tigeot * also enforces ordering), otherwise the hw might lose the new ring 615ba55f2f5SFrançois Tigeot * register values. */ 616ba55f2f5SFrançois Tigeot I915_WRITE_START(ring, i915_gem_obj_ggtt_offset(obj)); 6171b13d190SFrançois Tigeot 6181b13d190SFrançois Tigeot /* WaClearRingBufHeadRegAtInit:ctg,elk */ 6191b13d190SFrançois Tigeot if (I915_READ_HEAD(ring)) 6201b13d190SFrançois Tigeot DRM_DEBUG("%s initialization failed [head=%08x], fudging\n", 6211b13d190SFrançois Tigeot ring->name, I915_READ_HEAD(ring)); 6221b13d190SFrançois Tigeot I915_WRITE_HEAD(ring, 0); 6231b13d190SFrançois Tigeot (void)I915_READ_HEAD(ring); 6241b13d190SFrançois Tigeot 625ba55f2f5SFrançois Tigeot I915_WRITE_CTL(ring, 626ba55f2f5SFrançois Tigeot ((ringbuf->size - PAGE_SIZE) & RING_NR_PAGES) 627ba55f2f5SFrançois Tigeot | RING_VALID); 628ba55f2f5SFrançois Tigeot 629ba55f2f5SFrançois Tigeot /* If the head is still not zero, the ring is dead */ 630ba55f2f5SFrançois Tigeot if (wait_for((I915_READ_CTL(ring) & RING_VALID) != 0 && 631ba55f2f5SFrançois Tigeot I915_READ_START(ring) == i915_gem_obj_ggtt_offset(obj) && 632ba55f2f5SFrançois Tigeot (I915_READ_HEAD(ring) & HEAD_ADDR) == 0, 50)) { 633ba55f2f5SFrançois Tigeot DRM_ERROR("%s initialization failed " 634ba55f2f5SFrançois Tigeot "ctl %08x (valid? %d) head %08x tail %08x start %08x [expected %08lx]\n", 635ba55f2f5SFrançois Tigeot ring->name, 636ba55f2f5SFrançois Tigeot I915_READ_CTL(ring), I915_READ_CTL(ring) & RING_VALID, 637ba55f2f5SFrançois Tigeot I915_READ_HEAD(ring), I915_READ_TAIL(ring), 638ba55f2f5SFrançois Tigeot I915_READ_START(ring), (unsigned long)i915_gem_obj_ggtt_offset(obj)); 639ba55f2f5SFrançois Tigeot ret = -EIO; 640ba55f2f5SFrançois Tigeot goto out; 641ba55f2f5SFrançois Tigeot } 642e3adcf8fSFrançois Tigeot 6432c9916cdSFrançois Tigeot ringbuf->last_retired_head = -1; 644ba55f2f5SFrançois Tigeot ringbuf->head = I915_READ_HEAD(ring); 645ba55f2f5SFrançois Tigeot ringbuf->tail = I915_READ_TAIL(ring) & TAIL_ADDR; 6462c9916cdSFrançois Tigeot intel_ring_update_space(ringbuf); 647e3adcf8fSFrançois Tigeot 6485d0b1887SFrançois Tigeot memset(&ring->hangcheck, 0, sizeof(ring->hangcheck)); 6495d0b1887SFrançois Tigeot 650686a02f1SFrançois Tigeot out: 6512c9916cdSFrançois Tigeot intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL); 652686a02f1SFrançois Tigeot 653686a02f1SFrançois Tigeot return ret; 654e3adcf8fSFrançois Tigeot } 655e3adcf8fSFrançois Tigeot 6561b13d190SFrançois Tigeot void 6571b13d190SFrançois Tigeot intel_fini_pipe_control(struct intel_engine_cs *ring) 6581b13d190SFrançois Tigeot { 6591b13d190SFrançois Tigeot struct drm_device *dev = ring->dev; 6601b13d190SFrançois Tigeot 6611b13d190SFrançois Tigeot if (ring->scratch.obj == NULL) 6621b13d190SFrançois Tigeot return; 6631b13d190SFrançois Tigeot 6641b13d190SFrançois Tigeot if (INTEL_INFO(dev)->gen >= 5) { 6657ec9f8e5SFrançois Tigeot kunmap(sg_page(ring->scratch.obj->pages->sgl)); 6661b13d190SFrançois Tigeot i915_gem_object_ggtt_unpin(ring->scratch.obj); 6671b13d190SFrançois Tigeot } 6681b13d190SFrançois Tigeot 6691b13d190SFrançois Tigeot drm_gem_object_unreference(&ring->scratch.obj->base); 6701b13d190SFrançois Tigeot ring->scratch.obj = NULL; 6711b13d190SFrançois Tigeot } 6721b13d190SFrançois Tigeot 6731b13d190SFrançois Tigeot int 6741b13d190SFrançois Tigeot intel_init_pipe_control(struct intel_engine_cs *ring) 675e3adcf8fSFrançois Tigeot { 676e3adcf8fSFrançois Tigeot int ret; 677e3adcf8fSFrançois Tigeot 6782c9916cdSFrançois Tigeot WARN_ON(ring->scratch.obj); 679e3adcf8fSFrançois Tigeot 6809edbd4a0SFrançois Tigeot ring->scratch.obj = i915_gem_alloc_object(ring->dev, 4096); 6819edbd4a0SFrançois Tigeot if (ring->scratch.obj == NULL) { 682e3adcf8fSFrançois Tigeot DRM_ERROR("Failed to allocate seqno page\n"); 683e3adcf8fSFrançois Tigeot ret = -ENOMEM; 684e3adcf8fSFrançois Tigeot goto err; 685e3adcf8fSFrançois Tigeot } 686e3adcf8fSFrançois Tigeot 687ba55f2f5SFrançois Tigeot ret = i915_gem_object_set_cache_level(ring->scratch.obj, I915_CACHE_LLC); 688ba55f2f5SFrançois Tigeot if (ret) 689ba55f2f5SFrançois Tigeot goto err_unref; 690e3adcf8fSFrançois Tigeot 691ba55f2f5SFrançois Tigeot ret = i915_gem_obj_ggtt_pin(ring->scratch.obj, 4096, 0); 692e3adcf8fSFrançois Tigeot if (ret) 693e3adcf8fSFrançois Tigeot goto err_unref; 694e3adcf8fSFrançois Tigeot 6959edbd4a0SFrançois Tigeot ring->scratch.gtt_offset = i915_gem_obj_ggtt_offset(ring->scratch.obj); 6967ec9f8e5SFrançois Tigeot ring->scratch.cpu_page = kmap(sg_page(ring->scratch.obj->pages->sgl)); 6979edbd4a0SFrançois Tigeot if (ring->scratch.cpu_page == NULL) { 6985d0b1887SFrançois Tigeot ret = -ENOMEM; 699e3adcf8fSFrançois Tigeot goto err_unpin; 7005d0b1887SFrançois Tigeot } 701a2fdbec6SFrançois Tigeot 702a2fdbec6SFrançois Tigeot DRM_DEBUG_DRIVER("%s pipe control offset: 0x%08x\n", 7039edbd4a0SFrançois Tigeot ring->name, ring->scratch.gtt_offset); 704e3adcf8fSFrançois Tigeot return 0; 705e3adcf8fSFrançois Tigeot 706e3adcf8fSFrançois Tigeot err_unpin: 707ba55f2f5SFrançois Tigeot i915_gem_object_ggtt_unpin(ring->scratch.obj); 708e3adcf8fSFrançois Tigeot err_unref: 7099edbd4a0SFrançois Tigeot drm_gem_object_unreference(&ring->scratch.obj->base); 710e3adcf8fSFrançois Tigeot err: 711e3adcf8fSFrançois Tigeot return ret; 712e3adcf8fSFrançois Tigeot } 713e3adcf8fSFrançois Tigeot 714*a05eeebfSFrançois Tigeot static int intel_ring_workarounds_emit(struct drm_i915_gem_request *req) 7151b13d190SFrançois Tigeot { 7162c9916cdSFrançois Tigeot int ret, i; 717*a05eeebfSFrançois Tigeot struct intel_engine_cs *ring = req->ring; 7181b13d190SFrançois Tigeot struct drm_device *dev = ring->dev; 7191b13d190SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 7202c9916cdSFrançois Tigeot struct i915_workarounds *w = &dev_priv->workarounds; 7211b13d190SFrançois Tigeot 7222c9916cdSFrançois Tigeot if (WARN_ON_ONCE(w->count == 0)) 7232c9916cdSFrançois Tigeot return 0; 7241b13d190SFrançois Tigeot 7252c9916cdSFrançois Tigeot ring->gpu_caches_dirty = true; 726*a05eeebfSFrançois Tigeot ret = intel_ring_flush_all_caches(req); 7271b13d190SFrançois Tigeot if (ret) 7281b13d190SFrançois Tigeot return ret; 7291b13d190SFrançois Tigeot 730*a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, (w->count * 2 + 2)); 7312c9916cdSFrançois Tigeot if (ret) 7322c9916cdSFrançois Tigeot return ret; 7332c9916cdSFrançois Tigeot 7342c9916cdSFrançois Tigeot intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(w->count)); 7352c9916cdSFrançois Tigeot for (i = 0; i < w->count; i++) { 7362c9916cdSFrançois Tigeot intel_ring_emit(ring, w->reg[i].addr); 7372c9916cdSFrançois Tigeot intel_ring_emit(ring, w->reg[i].value); 7382c9916cdSFrançois Tigeot } 7392c9916cdSFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 7402c9916cdSFrançois Tigeot 7412c9916cdSFrançois Tigeot intel_ring_advance(ring); 7422c9916cdSFrançois Tigeot 7432c9916cdSFrançois Tigeot ring->gpu_caches_dirty = true; 744*a05eeebfSFrançois Tigeot ret = intel_ring_flush_all_caches(req); 7452c9916cdSFrançois Tigeot if (ret) 7462c9916cdSFrançois Tigeot return ret; 7472c9916cdSFrançois Tigeot 7482c9916cdSFrançois Tigeot DRM_DEBUG_DRIVER("Number of Workarounds emitted: %d\n", w->count); 7492c9916cdSFrançois Tigeot 7502c9916cdSFrançois Tigeot return 0; 7512c9916cdSFrançois Tigeot } 7522c9916cdSFrançois Tigeot 753*a05eeebfSFrançois Tigeot static int intel_rcs_ctx_init(struct drm_i915_gem_request *req) 7542c9916cdSFrançois Tigeot { 7552c9916cdSFrançois Tigeot int ret; 7562c9916cdSFrançois Tigeot 757*a05eeebfSFrançois Tigeot ret = intel_ring_workarounds_emit(req); 7582c9916cdSFrançois Tigeot if (ret != 0) 7592c9916cdSFrançois Tigeot return ret; 7602c9916cdSFrançois Tigeot 761*a05eeebfSFrançois Tigeot ret = i915_gem_render_state_init(req); 7622c9916cdSFrançois Tigeot if (ret) 7632c9916cdSFrançois Tigeot DRM_ERROR("init render state: %d\n", ret); 7642c9916cdSFrançois Tigeot 7652c9916cdSFrançois Tigeot return ret; 7662c9916cdSFrançois Tigeot } 7672c9916cdSFrançois Tigeot 7682c9916cdSFrançois Tigeot static int wa_add(struct drm_i915_private *dev_priv, 7692c9916cdSFrançois Tigeot const u32 addr, const u32 mask, const u32 val) 7702c9916cdSFrançois Tigeot { 7712c9916cdSFrançois Tigeot const u32 idx = dev_priv->workarounds.count; 7722c9916cdSFrançois Tigeot 7732c9916cdSFrançois Tigeot if (WARN_ON(idx >= I915_MAX_WA_REGS)) 7742c9916cdSFrançois Tigeot return -ENOSPC; 7752c9916cdSFrançois Tigeot 7762c9916cdSFrançois Tigeot dev_priv->workarounds.reg[idx].addr = addr; 7772c9916cdSFrançois Tigeot dev_priv->workarounds.reg[idx].value = val; 7782c9916cdSFrançois Tigeot dev_priv->workarounds.reg[idx].mask = mask; 7792c9916cdSFrançois Tigeot 7802c9916cdSFrançois Tigeot dev_priv->workarounds.count++; 7812c9916cdSFrançois Tigeot 7822c9916cdSFrançois Tigeot return 0; 7832c9916cdSFrançois Tigeot } 7842c9916cdSFrançois Tigeot 785*a05eeebfSFrançois Tigeot #define WA_REG(addr, mask, val) do { \ 7862c9916cdSFrançois Tigeot const int r = wa_add(dev_priv, (addr), (mask), (val)); \ 7872c9916cdSFrançois Tigeot if (r) \ 7882c9916cdSFrançois Tigeot return r; \ 789*a05eeebfSFrançois Tigeot } while (0) 7902c9916cdSFrançois Tigeot 7912c9916cdSFrançois Tigeot #define WA_SET_BIT_MASKED(addr, mask) \ 7922c9916cdSFrançois Tigeot WA_REG(addr, (mask), _MASKED_BIT_ENABLE(mask)) 7932c9916cdSFrançois Tigeot 7942c9916cdSFrançois Tigeot #define WA_CLR_BIT_MASKED(addr, mask) \ 7952c9916cdSFrançois Tigeot WA_REG(addr, (mask), _MASKED_BIT_DISABLE(mask)) 7962c9916cdSFrançois Tigeot 7972c9916cdSFrançois Tigeot #define WA_SET_FIELD_MASKED(addr, mask, value) \ 7982c9916cdSFrançois Tigeot WA_REG(addr, mask, _MASKED_FIELD(mask, value)) 7992c9916cdSFrançois Tigeot 8002c9916cdSFrançois Tigeot #define WA_SET_BIT(addr, mask) WA_REG(addr, mask, I915_READ(addr) | (mask)) 8012c9916cdSFrançois Tigeot #define WA_CLR_BIT(addr, mask) WA_REG(addr, mask, I915_READ(addr) & ~(mask)) 8022c9916cdSFrançois Tigeot 8032c9916cdSFrançois Tigeot #define WA_WRITE(addr, val) WA_REG(addr, 0xffffffff, val) 8042c9916cdSFrançois Tigeot 8052c9916cdSFrançois Tigeot static int bdw_init_workarounds(struct intel_engine_cs *ring) 8062c9916cdSFrançois Tigeot { 8072c9916cdSFrançois Tigeot struct drm_device *dev = ring->dev; 8082c9916cdSFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 8092c9916cdSFrançois Tigeot 810*a05eeebfSFrançois Tigeot WA_SET_BIT_MASKED(INSTPM, INSTPM_FORCE_ORDERING); 811*a05eeebfSFrançois Tigeot 812*a05eeebfSFrançois Tigeot /* WaDisableAsyncFlipPerfMode:bdw */ 813*a05eeebfSFrançois Tigeot WA_SET_BIT_MASKED(MI_MODE, ASYNC_FLIP_PERF_DISABLE); 814*a05eeebfSFrançois Tigeot 8151b13d190SFrançois Tigeot /* WaDisablePartialInstShootdown:bdw */ 8162c9916cdSFrançois Tigeot /* WaDisableThreadStallDopClockGating:bdw (pre-production) */ 8172c9916cdSFrançois Tigeot WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN, 8182c9916cdSFrançois Tigeot PARTIAL_INSTRUCTION_SHOOTDOWN_DISABLE | 8192c9916cdSFrançois Tigeot STALL_DOP_GATING_DISABLE); 8201b13d190SFrançois Tigeot 8212c9916cdSFrançois Tigeot /* WaDisableDopClockGating:bdw */ 8222c9916cdSFrançois Tigeot WA_SET_BIT_MASKED(GEN7_ROW_CHICKEN2, 8232c9916cdSFrançois Tigeot DOP_CLOCK_GATING_DISABLE); 8241b13d190SFrançois Tigeot 8252c9916cdSFrançois Tigeot WA_SET_BIT_MASKED(HALF_SLICE_CHICKEN3, 8262c9916cdSFrançois Tigeot GEN8_SAMPLER_POWER_BYPASS_DIS); 8271b13d190SFrançois Tigeot 8281b13d190SFrançois Tigeot /* Use Force Non-Coherent whenever executing a 3D context. This is a 8291b13d190SFrançois Tigeot * workaround for for a possible hang in the unlikely event a TLB 8301b13d190SFrançois Tigeot * invalidation occurs during a PSD flush. 8311b13d190SFrançois Tigeot */ 8322c9916cdSFrançois Tigeot WA_SET_BIT_MASKED(HDC_CHICKEN0, 833477eb7f9SFrançois Tigeot /* WaForceEnableNonCoherent:bdw */ 8342c9916cdSFrançois Tigeot HDC_FORCE_NON_COHERENT | 835477eb7f9SFrançois Tigeot /* WaForceContextSaveRestoreNonCoherent:bdw */ 836477eb7f9SFrançois Tigeot HDC_FORCE_CONTEXT_SAVE_RESTORE_NON_COHERENT | 837477eb7f9SFrançois Tigeot /* WaHdcDisableFetchWhenMasked:bdw */ 8382c9916cdSFrançois Tigeot HDC_DONOT_FETCH_MEM_WHEN_MASKED | 839477eb7f9SFrançois Tigeot /* WaDisableFenceDestinationToSLM:bdw (pre-prod) */ 8402c9916cdSFrançois Tigeot (IS_BDW_GT3(dev) ? HDC_FENCE_DEST_SLM_DISABLE : 0)); 8412c9916cdSFrançois Tigeot 8422c9916cdSFrançois Tigeot /* From the Haswell PRM, Command Reference: Registers, CACHE_MODE_0: 8432c9916cdSFrançois Tigeot * "The Hierarchical Z RAW Stall Optimization allows non-overlapping 8442c9916cdSFrançois Tigeot * polygons in the same 8x4 pixel/sample area to be processed without 8452c9916cdSFrançois Tigeot * stalling waiting for the earlier ones to write to Hierarchical Z 8462c9916cdSFrançois Tigeot * buffer." 8472c9916cdSFrançois Tigeot * 8482c9916cdSFrançois Tigeot * This optimization is off by default for Broadwell; turn it on. 8492c9916cdSFrançois Tigeot */ 8502c9916cdSFrançois Tigeot WA_CLR_BIT_MASKED(CACHE_MODE_0_GEN7, HIZ_RAW_STALL_OPT_DISABLE); 8511b13d190SFrançois Tigeot 8521b13d190SFrançois Tigeot /* Wa4x4STCOptimizationDisable:bdw */ 8532c9916cdSFrançois Tigeot WA_SET_BIT_MASKED(CACHE_MODE_1, 8542c9916cdSFrançois Tigeot GEN8_4x4_STC_OPTIMIZATION_DISABLE); 8551b13d190SFrançois Tigeot 8561b13d190SFrançois Tigeot /* 8571b13d190SFrançois Tigeot * BSpec recommends 8x4 when MSAA is used, 8581b13d190SFrançois Tigeot * however in practice 16x4 seems fastest. 8591b13d190SFrançois Tigeot * 8601b13d190SFrançois Tigeot * Note that PS/WM thread counts depend on the WIZ hashing 8611b13d190SFrançois Tigeot * disable bit, which we don't touch here, but it's good 8621b13d190SFrançois Tigeot * to keep in mind (see 3DSTATE_PS and 3DSTATE_WM). 8631b13d190SFrançois Tigeot */ 8642c9916cdSFrançois Tigeot WA_SET_FIELD_MASKED(GEN7_GT_MODE, 8652c9916cdSFrançois Tigeot GEN6_WIZ_HASHING_MASK, 8662c9916cdSFrançois Tigeot GEN6_WIZ_HASHING_16x4); 8671b13d190SFrançois Tigeot 8681b13d190SFrançois Tigeot return 0; 8691b13d190SFrançois Tigeot } 8701b13d190SFrançois Tigeot 8711b13d190SFrançois Tigeot static int chv_init_workarounds(struct intel_engine_cs *ring) 8721b13d190SFrançois Tigeot { 8731b13d190SFrançois Tigeot struct drm_device *dev = ring->dev; 8741b13d190SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 8751b13d190SFrançois Tigeot 876*a05eeebfSFrançois Tigeot WA_SET_BIT_MASKED(INSTPM, INSTPM_FORCE_ORDERING); 877*a05eeebfSFrançois Tigeot 878*a05eeebfSFrançois Tigeot /* WaDisableAsyncFlipPerfMode:chv */ 879*a05eeebfSFrançois Tigeot WA_SET_BIT_MASKED(MI_MODE, ASYNC_FLIP_PERF_DISABLE); 880*a05eeebfSFrançois Tigeot 8811b13d190SFrançois Tigeot /* WaDisablePartialInstShootdown:chv */ 8821b13d190SFrançois Tigeot /* WaDisableThreadStallDopClockGating:chv */ 8832c9916cdSFrançois Tigeot WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN, 8842c9916cdSFrançois Tigeot PARTIAL_INSTRUCTION_SHOOTDOWN_DISABLE | 8852c9916cdSFrançois Tigeot STALL_DOP_GATING_DISABLE); 8861b13d190SFrançois Tigeot 8872c9916cdSFrançois Tigeot /* Use Force Non-Coherent whenever executing a 3D context. This is a 8882c9916cdSFrançois Tigeot * workaround for a possible hang in the unlikely event a TLB 8892c9916cdSFrançois Tigeot * invalidation occurs during a PSD flush. 8902c9916cdSFrançois Tigeot */ 8912c9916cdSFrançois Tigeot /* WaForceEnableNonCoherent:chv */ 8922c9916cdSFrançois Tigeot /* WaHdcDisableFetchWhenMasked:chv */ 8932c9916cdSFrançois Tigeot WA_SET_BIT_MASKED(HDC_CHICKEN0, 8942c9916cdSFrançois Tigeot HDC_FORCE_NON_COHERENT | 8952c9916cdSFrançois Tigeot HDC_DONOT_FETCH_MEM_WHEN_MASKED); 8961b13d190SFrançois Tigeot 8972c9916cdSFrançois Tigeot /* According to the CACHE_MODE_0 default value documentation, some 8982c9916cdSFrançois Tigeot * CHV platforms disable this optimization by default. Turn it on. 8992c9916cdSFrançois Tigeot */ 9002c9916cdSFrançois Tigeot WA_CLR_BIT_MASKED(CACHE_MODE_0_GEN7, HIZ_RAW_STALL_OPT_DISABLE); 9011b13d190SFrançois Tigeot 9022c9916cdSFrançois Tigeot /* Wa4x4STCOptimizationDisable:chv */ 9032c9916cdSFrançois Tigeot WA_SET_BIT_MASKED(CACHE_MODE_1, 9042c9916cdSFrançois Tigeot GEN8_4x4_STC_OPTIMIZATION_DISABLE); 9052c9916cdSFrançois Tigeot 9062c9916cdSFrançois Tigeot /* Improve HiZ throughput on CHV. */ 9072c9916cdSFrançois Tigeot WA_SET_BIT_MASKED(HIZ_CHICKEN, CHV_HZ_8X8_MODE_IN_1X); 9082c9916cdSFrançois Tigeot 9092c9916cdSFrançois Tigeot /* 9102c9916cdSFrançois Tigeot * BSpec recommends 8x4 when MSAA is used, 9112c9916cdSFrançois Tigeot * however in practice 16x4 seems fastest. 9122c9916cdSFrançois Tigeot * 9132c9916cdSFrançois Tigeot * Note that PS/WM thread counts depend on the WIZ hashing 9142c9916cdSFrançois Tigeot * disable bit, which we don't touch here, but it's good 9152c9916cdSFrançois Tigeot * to keep in mind (see 3DSTATE_PS and 3DSTATE_WM). 9162c9916cdSFrançois Tigeot */ 9172c9916cdSFrançois Tigeot WA_SET_FIELD_MASKED(GEN7_GT_MODE, 9182c9916cdSFrançois Tigeot GEN6_WIZ_HASHING_MASK, 9192c9916cdSFrançois Tigeot GEN6_WIZ_HASHING_16x4); 9202c9916cdSFrançois Tigeot 9212c9916cdSFrançois Tigeot return 0; 9222c9916cdSFrançois Tigeot } 9232c9916cdSFrançois Tigeot 924477eb7f9SFrançois Tigeot static int gen9_init_workarounds(struct intel_engine_cs *ring) 925477eb7f9SFrançois Tigeot { 926477eb7f9SFrançois Tigeot struct drm_device *dev = ring->dev; 927477eb7f9SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 92819c468b4SFrançois Tigeot uint32_t tmp; 929477eb7f9SFrançois Tigeot 93019c468b4SFrançois Tigeot /* WaDisablePartialInstShootdown:skl,bxt */ 931477eb7f9SFrançois Tigeot WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN, 932477eb7f9SFrançois Tigeot PARTIAL_INSTRUCTION_SHOOTDOWN_DISABLE); 933477eb7f9SFrançois Tigeot 93419c468b4SFrançois Tigeot /* Syncing dependencies between camera and graphics:skl,bxt */ 935477eb7f9SFrançois Tigeot WA_SET_BIT_MASKED(HALF_SLICE_CHICKEN3, 936477eb7f9SFrançois Tigeot GEN9_DISABLE_OCL_OOB_SUPPRESS_LOGIC); 937477eb7f9SFrançois Tigeot 93819c468b4SFrançois Tigeot if ((IS_SKYLAKE(dev) && (INTEL_REVID(dev) == SKL_REVID_A0 || 93919c468b4SFrançois Tigeot INTEL_REVID(dev) == SKL_REVID_B0)) || 94019c468b4SFrançois Tigeot (IS_BROXTON(dev) && INTEL_REVID(dev) < BXT_REVID_B0)) { 94119c468b4SFrançois Tigeot /* WaDisableDgMirrorFixInHalfSliceChicken5:skl,bxt */ 942477eb7f9SFrançois Tigeot WA_CLR_BIT_MASKED(GEN9_HALF_SLICE_CHICKEN5, 943477eb7f9SFrançois Tigeot GEN9_DG_MIRROR_FIX_ENABLE); 944477eb7f9SFrançois Tigeot } 945477eb7f9SFrançois Tigeot 94619c468b4SFrançois Tigeot if ((IS_SKYLAKE(dev) && INTEL_REVID(dev) <= SKL_REVID_B0) || 94719c468b4SFrançois Tigeot (IS_BROXTON(dev) && INTEL_REVID(dev) < BXT_REVID_B0)) { 94819c468b4SFrançois Tigeot /* WaSetDisablePixMaskCammingAndRhwoInCommonSliceChicken:skl,bxt */ 949477eb7f9SFrançois Tigeot WA_SET_BIT_MASKED(GEN7_COMMON_SLICE_CHICKEN1, 950477eb7f9SFrançois Tigeot GEN9_RHWO_OPTIMIZATION_DISABLE); 951*a05eeebfSFrançois Tigeot /* 952*a05eeebfSFrançois Tigeot * WA also requires GEN9_SLICE_COMMON_ECO_CHICKEN0[14:14] to be set 953*a05eeebfSFrançois Tigeot * but we do that in per ctx batchbuffer as there is an issue 954*a05eeebfSFrançois Tigeot * with this register not getting restored on ctx restore 955*a05eeebfSFrançois Tigeot */ 956477eb7f9SFrançois Tigeot } 957477eb7f9SFrançois Tigeot 95819c468b4SFrançois Tigeot if ((IS_SKYLAKE(dev) && INTEL_REVID(dev) >= SKL_REVID_C0) || 95919c468b4SFrançois Tigeot IS_BROXTON(dev)) { 96019c468b4SFrançois Tigeot /* WaEnableYV12BugFixInHalfSliceChicken7:skl,bxt */ 961477eb7f9SFrançois Tigeot WA_SET_BIT_MASKED(GEN9_HALF_SLICE_CHICKEN7, 962477eb7f9SFrançois Tigeot GEN9_ENABLE_YV12_BUGFIX); 963477eb7f9SFrançois Tigeot } 964477eb7f9SFrançois Tigeot 96519c468b4SFrançois Tigeot /* Wa4x4STCOptimizationDisable:skl,bxt */ 966477eb7f9SFrançois Tigeot WA_SET_BIT_MASKED(CACHE_MODE_1, GEN8_4x4_STC_OPTIMIZATION_DISABLE); 967477eb7f9SFrançois Tigeot 96819c468b4SFrançois Tigeot /* WaDisablePartialResolveInVc:skl,bxt */ 969477eb7f9SFrançois Tigeot WA_SET_BIT_MASKED(CACHE_MODE_1, GEN9_PARTIAL_RESOLVE_IN_VC_DISABLE); 970477eb7f9SFrançois Tigeot 97119c468b4SFrançois Tigeot /* WaCcsTlbPrefetchDisable:skl,bxt */ 972477eb7f9SFrançois Tigeot WA_CLR_BIT_MASKED(GEN9_HALF_SLICE_CHICKEN5, 973477eb7f9SFrançois Tigeot GEN9_CCS_TLB_PREFETCH_ENABLE); 974477eb7f9SFrançois Tigeot 97519c468b4SFrançois Tigeot /* WaDisableMaskBasedCammingInRCC:skl,bxt */ 97619c468b4SFrançois Tigeot if ((IS_SKYLAKE(dev) && INTEL_REVID(dev) == SKL_REVID_C0) || 97719c468b4SFrançois Tigeot (IS_BROXTON(dev) && INTEL_REVID(dev) < BXT_REVID_B0)) 97819c468b4SFrançois Tigeot WA_SET_BIT_MASKED(SLICE_ECO_CHICKEN0, 97919c468b4SFrançois Tigeot PIXEL_MASK_CAMMING_DISABLE); 98019c468b4SFrançois Tigeot 98119c468b4SFrançois Tigeot /* WaForceContextSaveRestoreNonCoherent:skl,bxt */ 98219c468b4SFrançois Tigeot tmp = HDC_FORCE_CONTEXT_SAVE_RESTORE_NON_COHERENT; 98319c468b4SFrançois Tigeot if ((IS_SKYLAKE(dev) && INTEL_REVID(dev) == SKL_REVID_F0) || 98419c468b4SFrançois Tigeot (IS_BROXTON(dev) && INTEL_REVID(dev) >= BXT_REVID_B0)) 98519c468b4SFrançois Tigeot tmp |= HDC_FORCE_CSR_NON_COHERENT_OVR_DISABLE; 98619c468b4SFrançois Tigeot WA_SET_BIT_MASKED(HDC_CHICKEN0, tmp); 98719c468b4SFrançois Tigeot 988477eb7f9SFrançois Tigeot return 0; 989477eb7f9SFrançois Tigeot } 990477eb7f9SFrançois Tigeot 991477eb7f9SFrançois Tigeot static int skl_tune_iz_hashing(struct intel_engine_cs *ring) 992477eb7f9SFrançois Tigeot { 993477eb7f9SFrançois Tigeot struct drm_device *dev = ring->dev; 994477eb7f9SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 995477eb7f9SFrançois Tigeot u8 vals[3] = { 0, 0, 0 }; 996477eb7f9SFrançois Tigeot unsigned int i; 997477eb7f9SFrançois Tigeot 998477eb7f9SFrançois Tigeot for (i = 0; i < 3; i++) { 999477eb7f9SFrançois Tigeot u8 ss; 1000477eb7f9SFrançois Tigeot 1001477eb7f9SFrançois Tigeot /* 1002477eb7f9SFrançois Tigeot * Only consider slices where one, and only one, subslice has 7 1003477eb7f9SFrançois Tigeot * EUs 1004477eb7f9SFrançois Tigeot */ 1005477eb7f9SFrançois Tigeot if (hweight8(dev_priv->info.subslice_7eu[i]) != 1) 1006477eb7f9SFrançois Tigeot continue; 1007477eb7f9SFrançois Tigeot 1008477eb7f9SFrançois Tigeot /* 1009477eb7f9SFrançois Tigeot * subslice_7eu[i] != 0 (because of the check above) and 1010477eb7f9SFrançois Tigeot * ss_max == 4 (maximum number of subslices possible per slice) 1011477eb7f9SFrançois Tigeot * 1012477eb7f9SFrançois Tigeot * -> 0 <= ss <= 3; 1013477eb7f9SFrançois Tigeot */ 1014477eb7f9SFrançois Tigeot ss = ffs(dev_priv->info.subslice_7eu[i]) - 1; 1015477eb7f9SFrançois Tigeot vals[i] = 3 - ss; 1016477eb7f9SFrançois Tigeot } 1017477eb7f9SFrançois Tigeot 1018477eb7f9SFrançois Tigeot if (vals[0] == 0 && vals[1] == 0 && vals[2] == 0) 1019477eb7f9SFrançois Tigeot return 0; 1020477eb7f9SFrançois Tigeot 1021477eb7f9SFrançois Tigeot /* Tune IZ hashing. See intel_device_info_runtime_init() */ 1022477eb7f9SFrançois Tigeot WA_SET_FIELD_MASKED(GEN7_GT_MODE, 1023477eb7f9SFrançois Tigeot GEN9_IZ_HASHING_MASK(2) | 1024477eb7f9SFrançois Tigeot GEN9_IZ_HASHING_MASK(1) | 1025477eb7f9SFrançois Tigeot GEN9_IZ_HASHING_MASK(0), 1026477eb7f9SFrançois Tigeot GEN9_IZ_HASHING(2, vals[2]) | 1027477eb7f9SFrançois Tigeot GEN9_IZ_HASHING(1, vals[1]) | 1028477eb7f9SFrançois Tigeot GEN9_IZ_HASHING(0, vals[0])); 1029477eb7f9SFrançois Tigeot 1030477eb7f9SFrançois Tigeot return 0; 1031477eb7f9SFrançois Tigeot } 1032477eb7f9SFrançois Tigeot 1033477eb7f9SFrançois Tigeot 1034477eb7f9SFrançois Tigeot static int skl_init_workarounds(struct intel_engine_cs *ring) 1035477eb7f9SFrançois Tigeot { 1036477eb7f9SFrançois Tigeot struct drm_device *dev = ring->dev; 1037477eb7f9SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 1038477eb7f9SFrançois Tigeot 1039477eb7f9SFrançois Tigeot gen9_init_workarounds(ring); 1040477eb7f9SFrançois Tigeot 1041477eb7f9SFrançois Tigeot /* WaDisablePowerCompilerClockGating:skl */ 1042477eb7f9SFrançois Tigeot if (INTEL_REVID(dev) == SKL_REVID_B0) 1043477eb7f9SFrançois Tigeot WA_SET_BIT_MASKED(HIZ_CHICKEN, 1044477eb7f9SFrançois Tigeot BDW_HIZ_POWER_COMPILER_CLOCK_GATING_DISABLE); 1045477eb7f9SFrançois Tigeot 104619c468b4SFrançois Tigeot if (INTEL_REVID(dev) <= SKL_REVID_D0) { 104719c468b4SFrançois Tigeot /* 104819c468b4SFrançois Tigeot *Use Force Non-Coherent whenever executing a 3D context. This 104919c468b4SFrançois Tigeot * is a workaround for a possible hang in the unlikely event 105019c468b4SFrançois Tigeot * a TLB invalidation occurs during a PSD flush. 105119c468b4SFrançois Tigeot */ 105219c468b4SFrançois Tigeot /* WaForceEnableNonCoherent:skl */ 105319c468b4SFrançois Tigeot WA_SET_BIT_MASKED(HDC_CHICKEN0, 105419c468b4SFrançois Tigeot HDC_FORCE_NON_COHERENT); 105519c468b4SFrançois Tigeot } 105619c468b4SFrançois Tigeot 1057*a05eeebfSFrançois Tigeot if (INTEL_REVID(dev) == SKL_REVID_C0 || 1058*a05eeebfSFrançois Tigeot INTEL_REVID(dev) == SKL_REVID_D0) 1059*a05eeebfSFrançois Tigeot /* WaBarrierPerformanceFixDisable:skl */ 1060*a05eeebfSFrançois Tigeot WA_SET_BIT_MASKED(HDC_CHICKEN0, 1061*a05eeebfSFrançois Tigeot HDC_FENCE_DEST_SLM_DISABLE | 1062*a05eeebfSFrançois Tigeot HDC_BARRIER_PERFORMANCE_DISABLE); 1063*a05eeebfSFrançois Tigeot 1064*a05eeebfSFrançois Tigeot /* WaDisableSbeCacheDispatchPortSharing:skl */ 1065*a05eeebfSFrançois Tigeot if (INTEL_REVID(dev) <= SKL_REVID_F0) { 1066*a05eeebfSFrançois Tigeot WA_SET_BIT_MASKED( 1067*a05eeebfSFrançois Tigeot GEN7_HALF_SLICE_CHICKEN1, 1068*a05eeebfSFrançois Tigeot GEN7_SBE_SS_CACHE_DISPATCH_PORT_SHARING_DISABLE); 1069*a05eeebfSFrançois Tigeot } 1070*a05eeebfSFrançois Tigeot 1071477eb7f9SFrançois Tigeot return skl_tune_iz_hashing(ring); 1072477eb7f9SFrançois Tigeot } 1073477eb7f9SFrançois Tigeot 107419c468b4SFrançois Tigeot static int bxt_init_workarounds(struct intel_engine_cs *ring) 107519c468b4SFrançois Tigeot { 107619c468b4SFrançois Tigeot struct drm_device *dev = ring->dev; 107719c468b4SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 107819c468b4SFrançois Tigeot 107919c468b4SFrançois Tigeot gen9_init_workarounds(ring); 108019c468b4SFrançois Tigeot 108119c468b4SFrançois Tigeot /* WaDisableThreadStallDopClockGating:bxt */ 108219c468b4SFrançois Tigeot WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN, 108319c468b4SFrançois Tigeot STALL_DOP_GATING_DISABLE); 108419c468b4SFrançois Tigeot 108519c468b4SFrançois Tigeot /* WaDisableSbeCacheDispatchPortSharing:bxt */ 108619c468b4SFrançois Tigeot if (INTEL_REVID(dev) <= BXT_REVID_B0) { 108719c468b4SFrançois Tigeot WA_SET_BIT_MASKED( 108819c468b4SFrançois Tigeot GEN7_HALF_SLICE_CHICKEN1, 108919c468b4SFrançois Tigeot GEN7_SBE_SS_CACHE_DISPATCH_PORT_SHARING_DISABLE); 109019c468b4SFrançois Tigeot } 109119c468b4SFrançois Tigeot 109219c468b4SFrançois Tigeot return 0; 109319c468b4SFrançois Tigeot } 109419c468b4SFrançois Tigeot 10952c9916cdSFrançois Tigeot int init_workarounds_ring(struct intel_engine_cs *ring) 10962c9916cdSFrançois Tigeot { 10972c9916cdSFrançois Tigeot struct drm_device *dev = ring->dev; 10982c9916cdSFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 10992c9916cdSFrançois Tigeot 11002c9916cdSFrançois Tigeot WARN_ON(ring->id != RCS); 11012c9916cdSFrançois Tigeot 11022c9916cdSFrançois Tigeot dev_priv->workarounds.count = 0; 11032c9916cdSFrançois Tigeot 11042c9916cdSFrançois Tigeot if (IS_BROADWELL(dev)) 11052c9916cdSFrançois Tigeot return bdw_init_workarounds(ring); 11062c9916cdSFrançois Tigeot 11072c9916cdSFrançois Tigeot if (IS_CHERRYVIEW(dev)) 11082c9916cdSFrançois Tigeot return chv_init_workarounds(ring); 11091b13d190SFrançois Tigeot 1110477eb7f9SFrançois Tigeot if (IS_SKYLAKE(dev)) 1111477eb7f9SFrançois Tigeot return skl_init_workarounds(ring); 111219c468b4SFrançois Tigeot 111319c468b4SFrançois Tigeot if (IS_BROXTON(dev)) 111419c468b4SFrançois Tigeot return bxt_init_workarounds(ring); 1115477eb7f9SFrançois Tigeot 11161b13d190SFrançois Tigeot return 0; 11171b13d190SFrançois Tigeot } 11181b13d190SFrançois Tigeot 1119ba55f2f5SFrançois Tigeot static int init_render_ring(struct intel_engine_cs *ring) 1120e3adcf8fSFrançois Tigeot { 1121e3adcf8fSFrançois Tigeot struct drm_device *dev = ring->dev; 1122e3adcf8fSFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 1123e3adcf8fSFrançois Tigeot int ret = init_ring_common(ring); 112424edb884SFrançois Tigeot if (ret) 112524edb884SFrançois Tigeot return ret; 1126e3adcf8fSFrançois Tigeot 1127ba55f2f5SFrançois Tigeot /* WaTimedSingleVertexDispatch:cl,bw,ctg,elk,ilk,snb */ 1128ba55f2f5SFrançois Tigeot if (INTEL_INFO(dev)->gen >= 4 && INTEL_INFO(dev)->gen < 7) 1129f4e1c372SFrançois Tigeot I915_WRITE(MI_MODE, _MASKED_BIT_ENABLE(VS_TIMER_DISPATCH)); 1130f4e1c372SFrançois Tigeot 1131f4e1c372SFrançois Tigeot /* We need to disable the AsyncFlip performance optimisations in order 1132f4e1c372SFrançois Tigeot * to use MI_WAIT_FOR_EVENT within the CS. It should already be 1133f4e1c372SFrançois Tigeot * programmed to '1' on all products. 11345d0b1887SFrançois Tigeot * 1135*a05eeebfSFrançois Tigeot * WaDisableAsyncFlipPerfMode:snb,ivb,hsw,vlv 1136f4e1c372SFrançois Tigeot */ 1137*a05eeebfSFrançois Tigeot if (INTEL_INFO(dev)->gen >= 6 && INTEL_INFO(dev)->gen < 8) 1138f4e1c372SFrançois Tigeot I915_WRITE(MI_MODE, _MASKED_BIT_ENABLE(ASYNC_FLIP_PERF_DISABLE)); 1139f4e1c372SFrançois Tigeot 1140f4e1c372SFrançois Tigeot /* Required for the hardware to program scanline values for waiting */ 1141ba55f2f5SFrançois Tigeot /* WaEnableFlushTlbInvalidationMode:snb */ 1142f4e1c372SFrançois Tigeot if (INTEL_INFO(dev)->gen == 6) 1143f4e1c372SFrançois Tigeot I915_WRITE(GFX_MODE, 1144ba55f2f5SFrançois Tigeot _MASKED_BIT_ENABLE(GFX_TLB_INVALIDATE_EXPLICIT)); 1145f4e1c372SFrançois Tigeot 1146ba55f2f5SFrançois Tigeot /* WaBCSVCSTlbInvalidationMode:ivb,vlv,hsw */ 1147e3adcf8fSFrançois Tigeot if (IS_GEN7(dev)) 1148e3adcf8fSFrançois Tigeot I915_WRITE(GFX_MODE_GEN7, 1149ba55f2f5SFrançois Tigeot _MASKED_BIT_ENABLE(GFX_TLB_INVALIDATE_EXPLICIT) | 1150f4e1c372SFrançois Tigeot _MASKED_BIT_ENABLE(GFX_REPLAY_MODE)); 1151e3adcf8fSFrançois Tigeot 1152e3adcf8fSFrançois Tigeot if (IS_GEN6(dev)) { 1153e3adcf8fSFrançois Tigeot /* From the Sandybridge PRM, volume 1 part 3, page 24: 1154e3adcf8fSFrançois Tigeot * "If this bit is set, STCunit will have LRA as replacement 1155e3adcf8fSFrançois Tigeot * policy. [...] This bit must be reset. LRA replacement 1156e3adcf8fSFrançois Tigeot * policy is not supported." 1157e3adcf8fSFrançois Tigeot */ 1158e3adcf8fSFrançois Tigeot I915_WRITE(CACHE_MODE_0, 1159f4e1c372SFrançois Tigeot _MASKED_BIT_DISABLE(CM0_STC_EVICT_DISABLE_LRA_SNB)); 1160e3adcf8fSFrançois Tigeot } 1161e3adcf8fSFrançois Tigeot 1162*a05eeebfSFrançois Tigeot if (INTEL_INFO(dev)->gen >= 6 && INTEL_INFO(dev)->gen < 8) 1163f4e1c372SFrançois Tigeot I915_WRITE(INSTPM, _MASKED_BIT_ENABLE(INSTPM_FORCE_ORDERING)); 1164f4e1c372SFrançois Tigeot 11659edbd4a0SFrançois Tigeot if (HAS_L3_DPF(dev)) 11669edbd4a0SFrançois Tigeot I915_WRITE_IMR(ring, ~GT_PARITY_ERROR(dev)); 1167e3adcf8fSFrançois Tigeot 11682c9916cdSFrançois Tigeot return init_workarounds_ring(ring); 1169e3adcf8fSFrançois Tigeot } 1170e3adcf8fSFrançois Tigeot 1171ba55f2f5SFrançois Tigeot static void render_ring_cleanup(struct intel_engine_cs *ring) 1172e3adcf8fSFrançois Tigeot { 1173b5c29a34SFrançois Tigeot struct drm_device *dev = ring->dev; 117424edb884SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 117524edb884SFrançois Tigeot 117624edb884SFrançois Tigeot if (dev_priv->semaphore_obj) { 117724edb884SFrançois Tigeot i915_gem_object_ggtt_unpin(dev_priv->semaphore_obj); 117824edb884SFrançois Tigeot drm_gem_object_unreference(&dev_priv->semaphore_obj->base); 117924edb884SFrançois Tigeot dev_priv->semaphore_obj = NULL; 118024edb884SFrançois Tigeot } 1181b5c29a34SFrançois Tigeot 11821b13d190SFrançois Tigeot intel_fini_pipe_control(ring); 1183e3adcf8fSFrançois Tigeot } 1184e3adcf8fSFrançois Tigeot 1185*a05eeebfSFrançois Tigeot static int gen8_rcs_signal(struct drm_i915_gem_request *signaller_req, 118624edb884SFrançois Tigeot unsigned int num_dwords) 118724edb884SFrançois Tigeot { 118824edb884SFrançois Tigeot #define MBOX_UPDATE_DWORDS 8 1189*a05eeebfSFrançois Tigeot struct intel_engine_cs *signaller = signaller_req->ring; 119024edb884SFrançois Tigeot struct drm_device *dev = signaller->dev; 119124edb884SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 119224edb884SFrançois Tigeot struct intel_engine_cs *waiter; 119324edb884SFrançois Tigeot int i, ret, num_rings; 119424edb884SFrançois Tigeot 119524edb884SFrançois Tigeot num_rings = hweight32(INTEL_INFO(dev)->ring_mask); 119624edb884SFrançois Tigeot num_dwords += (num_rings-1) * MBOX_UPDATE_DWORDS; 119724edb884SFrançois Tigeot #undef MBOX_UPDATE_DWORDS 119824edb884SFrançois Tigeot 1199*a05eeebfSFrançois Tigeot ret = intel_ring_begin(signaller_req, num_dwords); 120024edb884SFrançois Tigeot if (ret) 120124edb884SFrançois Tigeot return ret; 120224edb884SFrançois Tigeot 120324edb884SFrançois Tigeot for_each_ring(waiter, dev_priv, i) { 12042c9916cdSFrançois Tigeot u32 seqno; 120524edb884SFrançois Tigeot u64 gtt_offset = signaller->semaphore.signal_ggtt[i]; 120624edb884SFrançois Tigeot if (gtt_offset == MI_SEMAPHORE_SYNC_INVALID) 120724edb884SFrançois Tigeot continue; 120824edb884SFrançois Tigeot 1209*a05eeebfSFrançois Tigeot seqno = i915_gem_request_get_seqno(signaller_req); 121024edb884SFrançois Tigeot intel_ring_emit(signaller, GFX_OP_PIPE_CONTROL(6)); 121124edb884SFrançois Tigeot intel_ring_emit(signaller, PIPE_CONTROL_GLOBAL_GTT_IVB | 121224edb884SFrançois Tigeot PIPE_CONTROL_QW_WRITE | 121324edb884SFrançois Tigeot PIPE_CONTROL_FLUSH_ENABLE); 121424edb884SFrançois Tigeot intel_ring_emit(signaller, lower_32_bits(gtt_offset)); 121524edb884SFrançois Tigeot intel_ring_emit(signaller, upper_32_bits(gtt_offset)); 12162c9916cdSFrançois Tigeot intel_ring_emit(signaller, seqno); 121724edb884SFrançois Tigeot intel_ring_emit(signaller, 0); 121824edb884SFrançois Tigeot intel_ring_emit(signaller, MI_SEMAPHORE_SIGNAL | 121924edb884SFrançois Tigeot MI_SEMAPHORE_TARGET(waiter->id)); 122024edb884SFrançois Tigeot intel_ring_emit(signaller, 0); 122124edb884SFrançois Tigeot } 122224edb884SFrançois Tigeot 122324edb884SFrançois Tigeot return 0; 122424edb884SFrançois Tigeot } 122524edb884SFrançois Tigeot 1226*a05eeebfSFrançois Tigeot static int gen8_xcs_signal(struct drm_i915_gem_request *signaller_req, 122724edb884SFrançois Tigeot unsigned int num_dwords) 122824edb884SFrançois Tigeot { 122924edb884SFrançois Tigeot #define MBOX_UPDATE_DWORDS 6 1230*a05eeebfSFrançois Tigeot struct intel_engine_cs *signaller = signaller_req->ring; 123124edb884SFrançois Tigeot struct drm_device *dev = signaller->dev; 123224edb884SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 123324edb884SFrançois Tigeot struct intel_engine_cs *waiter; 123424edb884SFrançois Tigeot int i, ret, num_rings; 123524edb884SFrançois Tigeot 123624edb884SFrançois Tigeot num_rings = hweight32(INTEL_INFO(dev)->ring_mask); 123724edb884SFrançois Tigeot num_dwords += (num_rings-1) * MBOX_UPDATE_DWORDS; 123824edb884SFrançois Tigeot #undef MBOX_UPDATE_DWORDS 123924edb884SFrançois Tigeot 1240*a05eeebfSFrançois Tigeot ret = intel_ring_begin(signaller_req, num_dwords); 124124edb884SFrançois Tigeot if (ret) 124224edb884SFrançois Tigeot return ret; 124324edb884SFrançois Tigeot 124424edb884SFrançois Tigeot for_each_ring(waiter, dev_priv, i) { 12452c9916cdSFrançois Tigeot u32 seqno; 124624edb884SFrançois Tigeot u64 gtt_offset = signaller->semaphore.signal_ggtt[i]; 124724edb884SFrançois Tigeot if (gtt_offset == MI_SEMAPHORE_SYNC_INVALID) 124824edb884SFrançois Tigeot continue; 124924edb884SFrançois Tigeot 1250*a05eeebfSFrançois Tigeot seqno = i915_gem_request_get_seqno(signaller_req); 125124edb884SFrançois Tigeot intel_ring_emit(signaller, (MI_FLUSH_DW + 1) | 125224edb884SFrançois Tigeot MI_FLUSH_DW_OP_STOREDW); 125324edb884SFrançois Tigeot intel_ring_emit(signaller, lower_32_bits(gtt_offset) | 125424edb884SFrançois Tigeot MI_FLUSH_DW_USE_GTT); 125524edb884SFrançois Tigeot intel_ring_emit(signaller, upper_32_bits(gtt_offset)); 12562c9916cdSFrançois Tigeot intel_ring_emit(signaller, seqno); 125724edb884SFrançois Tigeot intel_ring_emit(signaller, MI_SEMAPHORE_SIGNAL | 125824edb884SFrançois Tigeot MI_SEMAPHORE_TARGET(waiter->id)); 125924edb884SFrançois Tigeot intel_ring_emit(signaller, 0); 126024edb884SFrançois Tigeot } 126124edb884SFrançois Tigeot 126224edb884SFrançois Tigeot return 0; 126324edb884SFrançois Tigeot } 126424edb884SFrançois Tigeot 1265*a05eeebfSFrançois Tigeot static int gen6_signal(struct drm_i915_gem_request *signaller_req, 1266ba55f2f5SFrançois Tigeot unsigned int num_dwords) 1267e3adcf8fSFrançois Tigeot { 1268*a05eeebfSFrançois Tigeot struct intel_engine_cs *signaller = signaller_req->ring; 1269ba55f2f5SFrançois Tigeot struct drm_device *dev = signaller->dev; 1270ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 1271ba55f2f5SFrançois Tigeot struct intel_engine_cs *useless; 127224edb884SFrançois Tigeot int i, ret, num_rings; 1273ba55f2f5SFrançois Tigeot 127424edb884SFrançois Tigeot #define MBOX_UPDATE_DWORDS 3 127524edb884SFrançois Tigeot num_rings = hweight32(INTEL_INFO(dev)->ring_mask); 127624edb884SFrançois Tigeot num_dwords += round_up((num_rings-1) * MBOX_UPDATE_DWORDS, 2); 127724edb884SFrançois Tigeot #undef MBOX_UPDATE_DWORDS 1278ba55f2f5SFrançois Tigeot 1279*a05eeebfSFrançois Tigeot ret = intel_ring_begin(signaller_req, num_dwords); 1280ba55f2f5SFrançois Tigeot if (ret) 1281ba55f2f5SFrançois Tigeot return ret; 1282ba55f2f5SFrançois Tigeot 1283ba55f2f5SFrançois Tigeot for_each_ring(useless, dev_priv, i) { 1284ba55f2f5SFrançois Tigeot u32 mbox_reg = signaller->semaphore.mbox.signal[i]; 1285ba55f2f5SFrançois Tigeot if (mbox_reg != GEN6_NOSYNC) { 1286*a05eeebfSFrançois Tigeot u32 seqno = i915_gem_request_get_seqno(signaller_req); 1287ba55f2f5SFrançois Tigeot intel_ring_emit(signaller, MI_LOAD_REGISTER_IMM(1)); 1288ba55f2f5SFrançois Tigeot intel_ring_emit(signaller, mbox_reg); 12892c9916cdSFrançois Tigeot intel_ring_emit(signaller, seqno); 1290ba55f2f5SFrançois Tigeot } 1291ba55f2f5SFrançois Tigeot } 1292ba55f2f5SFrançois Tigeot 129324edb884SFrançois Tigeot /* If num_dwords was rounded, make sure the tail pointer is correct */ 129424edb884SFrançois Tigeot if (num_rings % 2 == 0) 129524edb884SFrançois Tigeot intel_ring_emit(signaller, MI_NOOP); 129624edb884SFrançois Tigeot 1297ba55f2f5SFrançois Tigeot return 0; 1298e3adcf8fSFrançois Tigeot } 1299e3adcf8fSFrançois Tigeot 1300e3adcf8fSFrançois Tigeot /** 1301e3adcf8fSFrançois Tigeot * gen6_add_request - Update the semaphore mailbox registers 1302e3adcf8fSFrançois Tigeot * 1303*a05eeebfSFrançois Tigeot * @request - request to write to the ring 1304e3adcf8fSFrançois Tigeot * 1305e3adcf8fSFrançois Tigeot * Update the mailbox registers in the *other* rings with the current seqno. 1306e3adcf8fSFrançois Tigeot * This acts like a signal in the canonical semaphore. 1307e3adcf8fSFrançois Tigeot */ 1308e3adcf8fSFrançois Tigeot static int 1309*a05eeebfSFrançois Tigeot gen6_add_request(struct drm_i915_gem_request *req) 1310e3adcf8fSFrançois Tigeot { 1311*a05eeebfSFrançois Tigeot struct intel_engine_cs *ring = req->ring; 1312ba55f2f5SFrançois Tigeot int ret; 1313e3adcf8fSFrançois Tigeot 131424edb884SFrançois Tigeot if (ring->semaphore.signal) 1315*a05eeebfSFrançois Tigeot ret = ring->semaphore.signal(req, 4); 131624edb884SFrançois Tigeot else 1317*a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 4); 131824edb884SFrançois Tigeot 13199edbd4a0SFrançois Tigeot if (ret) 13209edbd4a0SFrançois Tigeot return ret; 13219edbd4a0SFrançois Tigeot 1322e3adcf8fSFrançois Tigeot intel_ring_emit(ring, MI_STORE_DWORD_INDEX); 1323e3adcf8fSFrançois Tigeot intel_ring_emit(ring, I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT); 1324*a05eeebfSFrançois Tigeot intel_ring_emit(ring, i915_gem_request_get_seqno(req)); 1325e3adcf8fSFrançois Tigeot intel_ring_emit(ring, MI_USER_INTERRUPT); 13269edbd4a0SFrançois Tigeot __intel_ring_advance(ring); 1327e3adcf8fSFrançois Tigeot 1328e3adcf8fSFrançois Tigeot return 0; 1329e3adcf8fSFrançois Tigeot } 1330e3adcf8fSFrançois Tigeot 1331a2fdbec6SFrançois Tigeot static inline bool i915_gem_has_seqno_wrapped(struct drm_device *dev, 1332a2fdbec6SFrançois Tigeot u32 seqno) 1333a2fdbec6SFrançois Tigeot { 1334a2fdbec6SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 1335a2fdbec6SFrançois Tigeot return dev_priv->last_seqno < seqno; 1336a2fdbec6SFrançois Tigeot } 1337a2fdbec6SFrançois Tigeot 1338e3adcf8fSFrançois Tigeot /** 1339e3adcf8fSFrançois Tigeot * intel_ring_sync - sync the waiter to the signaller on seqno 1340e3adcf8fSFrançois Tigeot * 1341e3adcf8fSFrançois Tigeot * @waiter - ring that is waiting 1342e3adcf8fSFrançois Tigeot * @signaller - ring which has, or will signal 1343e3adcf8fSFrançois Tigeot * @seqno - seqno which the waiter will block on 1344e3adcf8fSFrançois Tigeot */ 134524edb884SFrançois Tigeot 134624edb884SFrançois Tigeot static int 1347*a05eeebfSFrançois Tigeot gen8_ring_sync(struct drm_i915_gem_request *waiter_req, 134824edb884SFrançois Tigeot struct intel_engine_cs *signaller, 134924edb884SFrançois Tigeot u32 seqno) 135024edb884SFrançois Tigeot { 1351*a05eeebfSFrançois Tigeot struct intel_engine_cs *waiter = waiter_req->ring; 135224edb884SFrançois Tigeot struct drm_i915_private *dev_priv = waiter->dev->dev_private; 135324edb884SFrançois Tigeot int ret; 135424edb884SFrançois Tigeot 1355*a05eeebfSFrançois Tigeot ret = intel_ring_begin(waiter_req, 4); 135624edb884SFrançois Tigeot if (ret) 135724edb884SFrançois Tigeot return ret; 135824edb884SFrançois Tigeot 135924edb884SFrançois Tigeot intel_ring_emit(waiter, MI_SEMAPHORE_WAIT | 136024edb884SFrançois Tigeot MI_SEMAPHORE_GLOBAL_GTT | 136124edb884SFrançois Tigeot MI_SEMAPHORE_POLL | 136224edb884SFrançois Tigeot MI_SEMAPHORE_SAD_GTE_SDD); 136324edb884SFrançois Tigeot intel_ring_emit(waiter, seqno); 136424edb884SFrançois Tigeot intel_ring_emit(waiter, 136524edb884SFrançois Tigeot lower_32_bits(GEN8_WAIT_OFFSET(waiter, signaller->id))); 136624edb884SFrançois Tigeot intel_ring_emit(waiter, 136724edb884SFrançois Tigeot upper_32_bits(GEN8_WAIT_OFFSET(waiter, signaller->id))); 136824edb884SFrançois Tigeot intel_ring_advance(waiter); 136924edb884SFrançois Tigeot return 0; 137024edb884SFrançois Tigeot } 137124edb884SFrançois Tigeot 1372e3adcf8fSFrançois Tigeot static int 1373*a05eeebfSFrançois Tigeot gen6_ring_sync(struct drm_i915_gem_request *waiter_req, 1374ba55f2f5SFrançois Tigeot struct intel_engine_cs *signaller, 1375e3adcf8fSFrançois Tigeot u32 seqno) 1376e3adcf8fSFrançois Tigeot { 1377*a05eeebfSFrançois Tigeot struct intel_engine_cs *waiter = waiter_req->ring; 1378e3adcf8fSFrançois Tigeot u32 dw1 = MI_SEMAPHORE_MBOX | 1379e3adcf8fSFrançois Tigeot MI_SEMAPHORE_COMPARE | 1380e3adcf8fSFrançois Tigeot MI_SEMAPHORE_REGISTER; 1381ba55f2f5SFrançois Tigeot u32 wait_mbox = signaller->semaphore.mbox.wait[waiter->id]; 1382ba55f2f5SFrançois Tigeot int ret; 1383e3adcf8fSFrançois Tigeot 1384686a02f1SFrançois Tigeot /* Throughout all of the GEM code, seqno passed implies our current 1385686a02f1SFrançois Tigeot * seqno is >= the last seqno executed. However for hardware the 1386686a02f1SFrançois Tigeot * comparison is strictly greater than. 1387686a02f1SFrançois Tigeot */ 1388686a02f1SFrançois Tigeot seqno -= 1; 1389686a02f1SFrançois Tigeot 1390ba55f2f5SFrançois Tigeot WARN_ON(wait_mbox == MI_SEMAPHORE_SYNC_INVALID); 1391686a02f1SFrançois Tigeot 1392*a05eeebfSFrançois Tigeot ret = intel_ring_begin(waiter_req, 4); 1393e3adcf8fSFrançois Tigeot if (ret) 1394e3adcf8fSFrançois Tigeot return ret; 1395e3adcf8fSFrançois Tigeot 1396a2fdbec6SFrançois Tigeot /* If seqno wrap happened, omit the wait with no-ops */ 1397a2fdbec6SFrançois Tigeot if (likely(!i915_gem_has_seqno_wrapped(waiter->dev, seqno))) { 1398ba55f2f5SFrançois Tigeot intel_ring_emit(waiter, dw1 | wait_mbox); 1399e3adcf8fSFrançois Tigeot intel_ring_emit(waiter, seqno); 1400e3adcf8fSFrançois Tigeot intel_ring_emit(waiter, 0); 1401e3adcf8fSFrançois Tigeot intel_ring_emit(waiter, MI_NOOP); 1402a2fdbec6SFrançois Tigeot } else { 1403a2fdbec6SFrançois Tigeot intel_ring_emit(waiter, MI_NOOP); 1404a2fdbec6SFrançois Tigeot intel_ring_emit(waiter, MI_NOOP); 1405a2fdbec6SFrançois Tigeot intel_ring_emit(waiter, MI_NOOP); 1406a2fdbec6SFrançois Tigeot intel_ring_emit(waiter, MI_NOOP); 1407a2fdbec6SFrançois Tigeot } 1408e3adcf8fSFrançois Tigeot intel_ring_advance(waiter); 1409e3adcf8fSFrançois Tigeot 1410e3adcf8fSFrançois Tigeot return 0; 1411e3adcf8fSFrançois Tigeot } 1412e3adcf8fSFrançois Tigeot 1413e3adcf8fSFrançois Tigeot #define PIPE_CONTROL_FLUSH(ring__, addr__) \ 1414e3adcf8fSFrançois Tigeot do { \ 1415e3adcf8fSFrançois Tigeot intel_ring_emit(ring__, GFX_OP_PIPE_CONTROL(4) | PIPE_CONTROL_QW_WRITE | \ 1416e3adcf8fSFrançois Tigeot PIPE_CONTROL_DEPTH_STALL); \ 1417e3adcf8fSFrançois Tigeot intel_ring_emit(ring__, (addr__) | PIPE_CONTROL_GLOBAL_GTT); \ 1418e3adcf8fSFrançois Tigeot intel_ring_emit(ring__, 0); \ 1419e3adcf8fSFrançois Tigeot intel_ring_emit(ring__, 0); \ 1420e3adcf8fSFrançois Tigeot } while (0) 1421e3adcf8fSFrançois Tigeot 1422e3adcf8fSFrançois Tigeot static int 1423*a05eeebfSFrançois Tigeot pc_render_add_request(struct drm_i915_gem_request *req) 1424e3adcf8fSFrançois Tigeot { 1425*a05eeebfSFrançois Tigeot struct intel_engine_cs *ring = req->ring; 1426ba55f2f5SFrançois Tigeot u32 scratch_addr = ring->scratch.gtt_offset + 2 * CACHELINE_BYTES; 1427e3adcf8fSFrançois Tigeot int ret; 1428e3adcf8fSFrançois Tigeot 1429e3adcf8fSFrançois Tigeot /* For Ironlake, MI_USER_INTERRUPT was deprecated and apparently 1430e3adcf8fSFrançois Tigeot * incoherent with writes to memory, i.e. completely fubar, 1431e3adcf8fSFrançois Tigeot * so we need to use PIPE_NOTIFY instead. 1432e3adcf8fSFrançois Tigeot * 1433e3adcf8fSFrançois Tigeot * However, we also need to workaround the qword write 1434e3adcf8fSFrançois Tigeot * incoherence by flushing the 6 PIPE_NOTIFY buffers out to 1435e3adcf8fSFrançois Tigeot * memory before requesting an interrupt. 1436e3adcf8fSFrançois Tigeot */ 1437*a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 32); 1438e3adcf8fSFrançois Tigeot if (ret) 1439e3adcf8fSFrançois Tigeot return ret; 1440e3adcf8fSFrançois Tigeot 1441e3adcf8fSFrançois Tigeot intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(4) | PIPE_CONTROL_QW_WRITE | 1442e3adcf8fSFrançois Tigeot PIPE_CONTROL_WRITE_FLUSH | 1443e3adcf8fSFrançois Tigeot PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE); 14449edbd4a0SFrançois Tigeot intel_ring_emit(ring, ring->scratch.gtt_offset | PIPE_CONTROL_GLOBAL_GTT); 1445*a05eeebfSFrançois Tigeot intel_ring_emit(ring, i915_gem_request_get_seqno(req)); 1446e3adcf8fSFrançois Tigeot intel_ring_emit(ring, 0); 1447e3adcf8fSFrançois Tigeot PIPE_CONTROL_FLUSH(ring, scratch_addr); 1448ba55f2f5SFrançois Tigeot scratch_addr += 2 * CACHELINE_BYTES; /* write to separate cachelines */ 1449e3adcf8fSFrançois Tigeot PIPE_CONTROL_FLUSH(ring, scratch_addr); 1450ba55f2f5SFrançois Tigeot scratch_addr += 2 * CACHELINE_BYTES; 1451e3adcf8fSFrançois Tigeot PIPE_CONTROL_FLUSH(ring, scratch_addr); 1452ba55f2f5SFrançois Tigeot scratch_addr += 2 * CACHELINE_BYTES; 1453e3adcf8fSFrançois Tigeot PIPE_CONTROL_FLUSH(ring, scratch_addr); 1454ba55f2f5SFrançois Tigeot scratch_addr += 2 * CACHELINE_BYTES; 1455e3adcf8fSFrançois Tigeot PIPE_CONTROL_FLUSH(ring, scratch_addr); 1456ba55f2f5SFrançois Tigeot scratch_addr += 2 * CACHELINE_BYTES; 1457e3adcf8fSFrançois Tigeot PIPE_CONTROL_FLUSH(ring, scratch_addr); 1458b5c29a34SFrançois Tigeot 1459e3adcf8fSFrançois Tigeot intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(4) | PIPE_CONTROL_QW_WRITE | 1460e3adcf8fSFrançois Tigeot PIPE_CONTROL_WRITE_FLUSH | 1461e3adcf8fSFrançois Tigeot PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE | 1462e3adcf8fSFrançois Tigeot PIPE_CONTROL_NOTIFY); 14639edbd4a0SFrançois Tigeot intel_ring_emit(ring, ring->scratch.gtt_offset | PIPE_CONTROL_GLOBAL_GTT); 1464*a05eeebfSFrançois Tigeot intel_ring_emit(ring, i915_gem_request_get_seqno(req)); 1465e3adcf8fSFrançois Tigeot intel_ring_emit(ring, 0); 14669edbd4a0SFrançois Tigeot __intel_ring_advance(ring); 1467e3adcf8fSFrançois Tigeot 1468e3adcf8fSFrançois Tigeot return 0; 1469e3adcf8fSFrançois Tigeot } 1470e3adcf8fSFrançois Tigeot 1471e3adcf8fSFrançois Tigeot static u32 1472ba55f2f5SFrançois Tigeot gen6_ring_get_seqno(struct intel_engine_cs *ring, bool lazy_coherency) 1473e3adcf8fSFrançois Tigeot { 1474e3adcf8fSFrançois Tigeot /* Workaround to force correct ordering between irq and seqno writes on 1475e3adcf8fSFrançois Tigeot * ivb (and maybe also on snb) by reading from a CS register (like 1476e3adcf8fSFrançois Tigeot * ACTHD) before reading the status page. */ 1477ba55f2f5SFrançois Tigeot if (!lazy_coherency) { 1478ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = ring->dev->dev_private; 1479ba55f2f5SFrançois Tigeot POSTING_READ(RING_ACTHD(ring->mmio_base)); 1480ba55f2f5SFrançois Tigeot } 1481ba55f2f5SFrançois Tigeot 1482e3adcf8fSFrançois Tigeot return intel_read_status_page(ring, I915_GEM_HWS_INDEX); 1483e3adcf8fSFrançois Tigeot } 1484e3adcf8fSFrançois Tigeot 1485b030f26bSFrançois Tigeot static u32 1486ba55f2f5SFrançois Tigeot ring_get_seqno(struct intel_engine_cs *ring, bool lazy_coherency) 1487e3adcf8fSFrançois Tigeot { 1488e3adcf8fSFrançois Tigeot return intel_read_status_page(ring, I915_GEM_HWS_INDEX); 1489e3adcf8fSFrançois Tigeot } 1490e3adcf8fSFrançois Tigeot 1491a2fdbec6SFrançois Tigeot static void 1492ba55f2f5SFrançois Tigeot ring_set_seqno(struct intel_engine_cs *ring, u32 seqno) 1493a2fdbec6SFrançois Tigeot { 1494a2fdbec6SFrançois Tigeot intel_write_status_page(ring, I915_GEM_HWS_INDEX, seqno); 1495a2fdbec6SFrançois Tigeot } 1496a2fdbec6SFrançois Tigeot 1497b030f26bSFrançois Tigeot static u32 1498ba55f2f5SFrançois Tigeot pc_render_get_seqno(struct intel_engine_cs *ring, bool lazy_coherency) 1499e3adcf8fSFrançois Tigeot { 15009edbd4a0SFrançois Tigeot return ring->scratch.cpu_page[0]; 1501e3adcf8fSFrançois Tigeot } 1502e3adcf8fSFrançois Tigeot 1503a2fdbec6SFrançois Tigeot static void 1504ba55f2f5SFrançois Tigeot pc_render_set_seqno(struct intel_engine_cs *ring, u32 seqno) 1505a2fdbec6SFrançois Tigeot { 15069edbd4a0SFrançois Tigeot ring->scratch.cpu_page[0] = seqno; 1507a2fdbec6SFrançois Tigeot } 1508a2fdbec6SFrançois Tigeot 1509e3adcf8fSFrançois Tigeot static bool 1510ba55f2f5SFrançois Tigeot gen5_ring_get_irq(struct intel_engine_cs *ring) 1511e3adcf8fSFrançois Tigeot { 1512e3adcf8fSFrançois Tigeot struct drm_device *dev = ring->dev; 1513ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 1514e3adcf8fSFrançois Tigeot 15152c9916cdSFrançois Tigeot if (WARN_ON(!intel_irqs_enabled(dev_priv))) 1516e3adcf8fSFrançois Tigeot return false; 1517e3adcf8fSFrançois Tigeot 151802727ecdSFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_EXCLUSIVE); 15199edbd4a0SFrançois Tigeot if (ring->irq_refcount++ == 0) 152024edb884SFrançois Tigeot gen5_enable_gt_irq(dev_priv, ring->irq_enable_mask); 152102727ecdSFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_RELEASE); 1522e3adcf8fSFrançois Tigeot 1523e3adcf8fSFrançois Tigeot return true; 1524e3adcf8fSFrançois Tigeot } 1525e3adcf8fSFrançois Tigeot 1526e3adcf8fSFrançois Tigeot static void 1527ba55f2f5SFrançois Tigeot gen5_ring_put_irq(struct intel_engine_cs *ring) 1528e3adcf8fSFrançois Tigeot { 1529e3adcf8fSFrançois Tigeot struct drm_device *dev = ring->dev; 1530ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 1531e3adcf8fSFrançois Tigeot 153202727ecdSFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_EXCLUSIVE); 15339edbd4a0SFrançois Tigeot if (--ring->irq_refcount == 0) 153424edb884SFrançois Tigeot gen5_disable_gt_irq(dev_priv, ring->irq_enable_mask); 1535686a02f1SFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_RELEASE); 1536686a02f1SFrançois Tigeot } 1537686a02f1SFrançois Tigeot 1538686a02f1SFrançois Tigeot static bool 1539ba55f2f5SFrançois Tigeot i9xx_ring_get_irq(struct intel_engine_cs *ring) 1540686a02f1SFrançois Tigeot { 1541686a02f1SFrançois Tigeot struct drm_device *dev = ring->dev; 1542ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 1543686a02f1SFrançois Tigeot 15442c9916cdSFrançois Tigeot if (!intel_irqs_enabled(dev_priv)) 1545686a02f1SFrançois Tigeot return false; 1546686a02f1SFrançois Tigeot 1547686a02f1SFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_EXCLUSIVE); 15489edbd4a0SFrançois Tigeot if (ring->irq_refcount++ == 0) { 1549686a02f1SFrançois Tigeot dev_priv->irq_mask &= ~ring->irq_enable_mask; 1550686a02f1SFrançois Tigeot I915_WRITE(IMR, dev_priv->irq_mask); 1551686a02f1SFrançois Tigeot POSTING_READ(IMR); 1552686a02f1SFrançois Tigeot } 1553686a02f1SFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_RELEASE); 1554686a02f1SFrançois Tigeot 1555686a02f1SFrançois Tigeot return true; 1556686a02f1SFrançois Tigeot } 1557686a02f1SFrançois Tigeot 1558686a02f1SFrançois Tigeot static void 1559ba55f2f5SFrançois Tigeot i9xx_ring_put_irq(struct intel_engine_cs *ring) 1560686a02f1SFrançois Tigeot { 1561686a02f1SFrançois Tigeot struct drm_device *dev = ring->dev; 1562ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 1563686a02f1SFrançois Tigeot 1564686a02f1SFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_EXCLUSIVE); 15659edbd4a0SFrançois Tigeot if (--ring->irq_refcount == 0) { 1566686a02f1SFrançois Tigeot dev_priv->irq_mask |= ring->irq_enable_mask; 1567686a02f1SFrançois Tigeot I915_WRITE(IMR, dev_priv->irq_mask); 1568686a02f1SFrançois Tigeot POSTING_READ(IMR); 1569686a02f1SFrançois Tigeot } 1570686a02f1SFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_RELEASE); 1571686a02f1SFrançois Tigeot } 1572686a02f1SFrançois Tigeot 1573686a02f1SFrançois Tigeot static bool 1574ba55f2f5SFrançois Tigeot i8xx_ring_get_irq(struct intel_engine_cs *ring) 1575686a02f1SFrançois Tigeot { 1576686a02f1SFrançois Tigeot struct drm_device *dev = ring->dev; 1577ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 1578686a02f1SFrançois Tigeot 15792c9916cdSFrançois Tigeot if (!intel_irqs_enabled(dev_priv)) 1580686a02f1SFrançois Tigeot return false; 1581686a02f1SFrançois Tigeot 1582686a02f1SFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_EXCLUSIVE); 15839edbd4a0SFrançois Tigeot if (ring->irq_refcount++ == 0) { 1584686a02f1SFrançois Tigeot dev_priv->irq_mask &= ~ring->irq_enable_mask; 1585686a02f1SFrançois Tigeot I915_WRITE16(IMR, dev_priv->irq_mask); 1586686a02f1SFrançois Tigeot POSTING_READ16(IMR); 1587686a02f1SFrançois Tigeot } 1588686a02f1SFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_RELEASE); 1589686a02f1SFrançois Tigeot 1590686a02f1SFrançois Tigeot return true; 1591686a02f1SFrançois Tigeot } 1592686a02f1SFrançois Tigeot 1593686a02f1SFrançois Tigeot static void 1594ba55f2f5SFrançois Tigeot i8xx_ring_put_irq(struct intel_engine_cs *ring) 1595686a02f1SFrançois Tigeot { 1596686a02f1SFrançois Tigeot struct drm_device *dev = ring->dev; 1597ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 1598686a02f1SFrançois Tigeot 1599686a02f1SFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_EXCLUSIVE); 16009edbd4a0SFrançois Tigeot if (--ring->irq_refcount == 0) { 1601686a02f1SFrançois Tigeot dev_priv->irq_mask |= ring->irq_enable_mask; 1602686a02f1SFrançois Tigeot I915_WRITE16(IMR, dev_priv->irq_mask); 1603686a02f1SFrançois Tigeot POSTING_READ16(IMR); 1604e3adcf8fSFrançois Tigeot } 160502727ecdSFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_RELEASE); 1606e3adcf8fSFrançois Tigeot } 1607e3adcf8fSFrançois Tigeot 1608e3adcf8fSFrançois Tigeot static int 1609*a05eeebfSFrançois Tigeot bsd_ring_flush(struct drm_i915_gem_request *req, 1610b5c29a34SFrançois Tigeot u32 invalidate_domains, 1611b5c29a34SFrançois Tigeot u32 flush_domains) 1612e3adcf8fSFrançois Tigeot { 1613*a05eeebfSFrançois Tigeot struct intel_engine_cs *ring = req->ring; 1614e3adcf8fSFrançois Tigeot int ret; 1615e3adcf8fSFrançois Tigeot 1616*a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 2); 1617e3adcf8fSFrançois Tigeot if (ret) 1618e3adcf8fSFrançois Tigeot return ret; 1619e3adcf8fSFrançois Tigeot 1620e3adcf8fSFrançois Tigeot intel_ring_emit(ring, MI_FLUSH); 1621e3adcf8fSFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 1622e3adcf8fSFrançois Tigeot intel_ring_advance(ring); 1623e3adcf8fSFrançois Tigeot return 0; 1624e3adcf8fSFrançois Tigeot } 1625e3adcf8fSFrançois Tigeot 1626e3adcf8fSFrançois Tigeot static int 1627*a05eeebfSFrançois Tigeot i9xx_add_request(struct drm_i915_gem_request *req) 1628e3adcf8fSFrançois Tigeot { 1629*a05eeebfSFrançois Tigeot struct intel_engine_cs *ring = req->ring; 1630e3adcf8fSFrançois Tigeot int ret; 1631e3adcf8fSFrançois Tigeot 1632*a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 4); 1633e3adcf8fSFrançois Tigeot if (ret) 1634e3adcf8fSFrançois Tigeot return ret; 1635e3adcf8fSFrançois Tigeot 1636e3adcf8fSFrançois Tigeot intel_ring_emit(ring, MI_STORE_DWORD_INDEX); 1637e3adcf8fSFrançois Tigeot intel_ring_emit(ring, I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT); 1638*a05eeebfSFrançois Tigeot intel_ring_emit(ring, i915_gem_request_get_seqno(req)); 1639e3adcf8fSFrançois Tigeot intel_ring_emit(ring, MI_USER_INTERRUPT); 16409edbd4a0SFrançois Tigeot __intel_ring_advance(ring); 1641e3adcf8fSFrançois Tigeot 1642e3adcf8fSFrançois Tigeot return 0; 1643e3adcf8fSFrançois Tigeot } 1644e3adcf8fSFrançois Tigeot 1645e3adcf8fSFrançois Tigeot static bool 1646ba55f2f5SFrançois Tigeot gen6_ring_get_irq(struct intel_engine_cs *ring) 1647e3adcf8fSFrançois Tigeot { 1648e3adcf8fSFrançois Tigeot struct drm_device *dev = ring->dev; 1649ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 1650e3adcf8fSFrançois Tigeot 16512c9916cdSFrançois Tigeot if (WARN_ON(!intel_irqs_enabled(dev_priv))) 1652e3adcf8fSFrançois Tigeot return false; 1653e3adcf8fSFrançois Tigeot 165402727ecdSFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_EXCLUSIVE); 16559edbd4a0SFrançois Tigeot if (ring->irq_refcount++ == 0) { 16569edbd4a0SFrançois Tigeot if (HAS_L3_DPF(dev) && ring->id == RCS) 16575d0b1887SFrançois Tigeot I915_WRITE_IMR(ring, 16585d0b1887SFrançois Tigeot ~(ring->irq_enable_mask | 16599edbd4a0SFrançois Tigeot GT_PARITY_ERROR(dev))); 1660686a02f1SFrançois Tigeot else 1661686a02f1SFrançois Tigeot I915_WRITE_IMR(ring, ~ring->irq_enable_mask); 166224edb884SFrançois Tigeot gen5_enable_gt_irq(dev_priv, ring->irq_enable_mask); 1663e3adcf8fSFrançois Tigeot } 166402727ecdSFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_RELEASE); 1665e3adcf8fSFrançois Tigeot 1666e3adcf8fSFrançois Tigeot return true; 1667e3adcf8fSFrançois Tigeot } 1668e3adcf8fSFrançois Tigeot 1669e3adcf8fSFrançois Tigeot static void 1670ba55f2f5SFrançois Tigeot gen6_ring_put_irq(struct intel_engine_cs *ring) 1671e3adcf8fSFrançois Tigeot { 1672e3adcf8fSFrançois Tigeot struct drm_device *dev = ring->dev; 1673ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 1674e3adcf8fSFrançois Tigeot 167502727ecdSFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_EXCLUSIVE); 16769edbd4a0SFrançois Tigeot if (--ring->irq_refcount == 0) { 16779edbd4a0SFrançois Tigeot if (HAS_L3_DPF(dev) && ring->id == RCS) 16789edbd4a0SFrançois Tigeot I915_WRITE_IMR(ring, ~GT_PARITY_ERROR(dev)); 1679686a02f1SFrançois Tigeot else 1680686a02f1SFrançois Tigeot I915_WRITE_IMR(ring, ~0); 168124edb884SFrançois Tigeot gen5_disable_gt_irq(dev_priv, ring->irq_enable_mask); 1682e3adcf8fSFrançois Tigeot } 168302727ecdSFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_RELEASE); 1684e3adcf8fSFrançois Tigeot } 1685e3adcf8fSFrançois Tigeot 16865d0b1887SFrançois Tigeot static bool 1687ba55f2f5SFrançois Tigeot hsw_vebox_get_irq(struct intel_engine_cs *ring) 16885d0b1887SFrançois Tigeot { 16895d0b1887SFrançois Tigeot struct drm_device *dev = ring->dev; 16905d0b1887SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 16915d0b1887SFrançois Tigeot 16922c9916cdSFrançois Tigeot if (WARN_ON(!intel_irqs_enabled(dev_priv))) 16935d0b1887SFrançois Tigeot return false; 16945d0b1887SFrançois Tigeot 16959edbd4a0SFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_EXCLUSIVE); 16969edbd4a0SFrançois Tigeot if (ring->irq_refcount++ == 0) { 16975d0b1887SFrançois Tigeot I915_WRITE_IMR(ring, ~ring->irq_enable_mask); 169824edb884SFrançois Tigeot gen6_enable_pm_irq(dev_priv, ring->irq_enable_mask); 16995d0b1887SFrançois Tigeot } 17009edbd4a0SFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_RELEASE); 17015d0b1887SFrançois Tigeot 17025d0b1887SFrançois Tigeot return true; 17035d0b1887SFrançois Tigeot } 17045d0b1887SFrançois Tigeot 17055d0b1887SFrançois Tigeot static void 1706ba55f2f5SFrançois Tigeot hsw_vebox_put_irq(struct intel_engine_cs *ring) 17075d0b1887SFrançois Tigeot { 17085d0b1887SFrançois Tigeot struct drm_device *dev = ring->dev; 17095d0b1887SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 17105d0b1887SFrançois Tigeot 17119edbd4a0SFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_EXCLUSIVE); 17129edbd4a0SFrançois Tigeot if (--ring->irq_refcount == 0) { 17135d0b1887SFrançois Tigeot I915_WRITE_IMR(ring, ~0); 171424edb884SFrançois Tigeot gen6_disable_pm_irq(dev_priv, ring->irq_enable_mask); 17155d0b1887SFrançois Tigeot } 17169edbd4a0SFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_RELEASE); 17179edbd4a0SFrançois Tigeot } 17189edbd4a0SFrançois Tigeot 17199edbd4a0SFrançois Tigeot static bool 1720ba55f2f5SFrançois Tigeot gen8_ring_get_irq(struct intel_engine_cs *ring) 17219edbd4a0SFrançois Tigeot { 17229edbd4a0SFrançois Tigeot struct drm_device *dev = ring->dev; 17239edbd4a0SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 17249edbd4a0SFrançois Tigeot 17252c9916cdSFrançois Tigeot if (WARN_ON(!intel_irqs_enabled(dev_priv))) 17269edbd4a0SFrançois Tigeot return false; 17279edbd4a0SFrançois Tigeot 17289edbd4a0SFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_EXCLUSIVE); 17299edbd4a0SFrançois Tigeot if (ring->irq_refcount++ == 0) { 17309edbd4a0SFrançois Tigeot if (HAS_L3_DPF(dev) && ring->id == RCS) { 17319edbd4a0SFrançois Tigeot I915_WRITE_IMR(ring, 17329edbd4a0SFrançois Tigeot ~(ring->irq_enable_mask | 17339edbd4a0SFrançois Tigeot GT_RENDER_L3_PARITY_ERROR_INTERRUPT)); 17349edbd4a0SFrançois Tigeot } else { 17359edbd4a0SFrançois Tigeot I915_WRITE_IMR(ring, ~ring->irq_enable_mask); 17369edbd4a0SFrançois Tigeot } 17379edbd4a0SFrançois Tigeot POSTING_READ(RING_IMR(ring->mmio_base)); 17389edbd4a0SFrançois Tigeot } 17399edbd4a0SFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_RELEASE); 17409edbd4a0SFrançois Tigeot 17419edbd4a0SFrançois Tigeot return true; 17429edbd4a0SFrançois Tigeot } 17439edbd4a0SFrançois Tigeot 17449edbd4a0SFrançois Tigeot static void 1745ba55f2f5SFrançois Tigeot gen8_ring_put_irq(struct intel_engine_cs *ring) 17469edbd4a0SFrançois Tigeot { 17479edbd4a0SFrançois Tigeot struct drm_device *dev = ring->dev; 17489edbd4a0SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 17499edbd4a0SFrançois Tigeot 17509edbd4a0SFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_EXCLUSIVE); 17519edbd4a0SFrançois Tigeot if (--ring->irq_refcount == 0) { 17529edbd4a0SFrançois Tigeot if (HAS_L3_DPF(dev) && ring->id == RCS) { 17539edbd4a0SFrançois Tigeot I915_WRITE_IMR(ring, 17549edbd4a0SFrançois Tigeot ~GT_RENDER_L3_PARITY_ERROR_INTERRUPT); 17559edbd4a0SFrançois Tigeot } else { 17569edbd4a0SFrançois Tigeot I915_WRITE_IMR(ring, ~0); 17579edbd4a0SFrançois Tigeot } 17589edbd4a0SFrançois Tigeot POSTING_READ(RING_IMR(ring->mmio_base)); 17599edbd4a0SFrançois Tigeot } 17609edbd4a0SFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_RELEASE); 17615d0b1887SFrançois Tigeot } 17625d0b1887SFrançois Tigeot 1763e3adcf8fSFrançois Tigeot static int 1764*a05eeebfSFrançois Tigeot i965_dispatch_execbuffer(struct drm_i915_gem_request *req, 1765ba55f2f5SFrançois Tigeot u64 offset, u32 length, 1766477eb7f9SFrançois Tigeot unsigned dispatch_flags) 1767e3adcf8fSFrançois Tigeot { 1768*a05eeebfSFrançois Tigeot struct intel_engine_cs *ring = req->ring; 1769e3adcf8fSFrançois Tigeot int ret; 1770e3adcf8fSFrançois Tigeot 1771*a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 2); 1772e3adcf8fSFrançois Tigeot if (ret) 1773e3adcf8fSFrançois Tigeot return ret; 1774e3adcf8fSFrançois Tigeot 1775e3adcf8fSFrançois Tigeot intel_ring_emit(ring, 1776686a02f1SFrançois Tigeot MI_BATCH_BUFFER_START | 1777b5c29a34SFrançois Tigeot MI_BATCH_GTT | 1778477eb7f9SFrançois Tigeot (dispatch_flags & I915_DISPATCH_SECURE ? 1779477eb7f9SFrançois Tigeot 0 : MI_BATCH_NON_SECURE_I965)); 1780e3adcf8fSFrançois Tigeot intel_ring_emit(ring, offset); 1781e3adcf8fSFrançois Tigeot intel_ring_advance(ring); 1782e3adcf8fSFrançois Tigeot 1783e3adcf8fSFrançois Tigeot return 0; 1784e3adcf8fSFrançois Tigeot } 1785e3adcf8fSFrançois Tigeot 1786b5c29a34SFrançois Tigeot /* Just userspace ABI convention to limit the wa batch bo to a resonable size */ 1787b5c29a34SFrançois Tigeot #define I830_BATCH_LIMIT (256*1024) 178824edb884SFrançois Tigeot #define I830_TLB_ENTRIES (2) 178924edb884SFrançois Tigeot #define I830_WA_SIZE max(I830_TLB_ENTRIES*4096, I830_BATCH_LIMIT) 1790e3adcf8fSFrançois Tigeot static int 1791*a05eeebfSFrançois Tigeot i830_dispatch_execbuffer(struct drm_i915_gem_request *req, 1792ba55f2f5SFrançois Tigeot u64 offset, u32 len, 1793477eb7f9SFrançois Tigeot unsigned dispatch_flags) 1794e3adcf8fSFrançois Tigeot { 1795*a05eeebfSFrançois Tigeot struct intel_engine_cs *ring = req->ring; 179624edb884SFrançois Tigeot u32 cs_offset = ring->scratch.gtt_offset; 1797e3adcf8fSFrançois Tigeot int ret; 1798e3adcf8fSFrançois Tigeot 1799*a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 6); 180024edb884SFrançois Tigeot if (ret) 180124edb884SFrançois Tigeot return ret; 180224edb884SFrançois Tigeot 180324edb884SFrançois Tigeot /* Evict the invalid PTE TLBs */ 180424edb884SFrançois Tigeot intel_ring_emit(ring, COLOR_BLT_CMD | BLT_WRITE_RGBA); 180524edb884SFrançois Tigeot intel_ring_emit(ring, BLT_DEPTH_32 | BLT_ROP_COLOR_COPY | 4096); 180624edb884SFrançois Tigeot intel_ring_emit(ring, I830_TLB_ENTRIES << 16 | 4); /* load each page */ 180724edb884SFrançois Tigeot intel_ring_emit(ring, cs_offset); 180824edb884SFrançois Tigeot intel_ring_emit(ring, 0xdeadbeef); 180924edb884SFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 181024edb884SFrançois Tigeot intel_ring_advance(ring); 181124edb884SFrançois Tigeot 1812477eb7f9SFrançois Tigeot if ((dispatch_flags & I915_DISPATCH_PINNED) == 0) { 181324edb884SFrançois Tigeot if (len > I830_BATCH_LIMIT) 181424edb884SFrançois Tigeot return -ENOSPC; 181524edb884SFrançois Tigeot 1816*a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 6 + 2); 181724edb884SFrançois Tigeot if (ret) 181824edb884SFrançois Tigeot return ret; 181924edb884SFrançois Tigeot 182024edb884SFrançois Tigeot /* Blit the batch (which has now all relocs applied) to the 182124edb884SFrançois Tigeot * stable batch scratch bo area (so that the CS never 182224edb884SFrançois Tigeot * stumbles over its tlb invalidation bug) ... 182324edb884SFrançois Tigeot */ 182424edb884SFrançois Tigeot intel_ring_emit(ring, SRC_COPY_BLT_CMD | BLT_WRITE_RGBA); 182524edb884SFrançois Tigeot intel_ring_emit(ring, BLT_DEPTH_32 | BLT_ROP_SRC_COPY | 4096); 182624edb884SFrançois Tigeot intel_ring_emit(ring, DIV_ROUND_UP(len, 4096) << 16 | 4096); 182724edb884SFrançois Tigeot intel_ring_emit(ring, cs_offset); 182824edb884SFrançois Tigeot intel_ring_emit(ring, 4096); 182924edb884SFrançois Tigeot intel_ring_emit(ring, offset); 183024edb884SFrançois Tigeot 183124edb884SFrançois Tigeot intel_ring_emit(ring, MI_FLUSH); 183224edb884SFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 183324edb884SFrançois Tigeot intel_ring_advance(ring); 183424edb884SFrançois Tigeot 183524edb884SFrançois Tigeot /* ... and execute it. */ 183624edb884SFrançois Tigeot offset = cs_offset; 183724edb884SFrançois Tigeot } 183824edb884SFrançois Tigeot 1839*a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 4); 1840e3adcf8fSFrançois Tigeot if (ret) 1841e3adcf8fSFrançois Tigeot return ret; 1842e3adcf8fSFrançois Tigeot 1843e3adcf8fSFrançois Tigeot intel_ring_emit(ring, MI_BATCH_BUFFER); 1844477eb7f9SFrançois Tigeot intel_ring_emit(ring, offset | (dispatch_flags & I915_DISPATCH_SECURE ? 1845477eb7f9SFrançois Tigeot 0 : MI_BATCH_NON_SECURE)); 1846e3adcf8fSFrançois Tigeot intel_ring_emit(ring, offset + len - 8); 1847b5c29a34SFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 1848686a02f1SFrançois Tigeot intel_ring_advance(ring); 1849686a02f1SFrançois Tigeot 1850686a02f1SFrançois Tigeot return 0; 1851686a02f1SFrançois Tigeot } 1852686a02f1SFrançois Tigeot 1853686a02f1SFrançois Tigeot static int 1854*a05eeebfSFrançois Tigeot i915_dispatch_execbuffer(struct drm_i915_gem_request *req, 1855ba55f2f5SFrançois Tigeot u64 offset, u32 len, 1856477eb7f9SFrançois Tigeot unsigned dispatch_flags) 1857686a02f1SFrançois Tigeot { 1858*a05eeebfSFrançois Tigeot struct intel_engine_cs *ring = req->ring; 1859686a02f1SFrançois Tigeot int ret; 1860686a02f1SFrançois Tigeot 1861*a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 2); 1862e3adcf8fSFrançois Tigeot if (ret) 1863e3adcf8fSFrançois Tigeot return ret; 1864e3adcf8fSFrançois Tigeot 1865686a02f1SFrançois Tigeot intel_ring_emit(ring, MI_BATCH_BUFFER_START | MI_BATCH_GTT); 1866477eb7f9SFrançois Tigeot intel_ring_emit(ring, offset | (dispatch_flags & I915_DISPATCH_SECURE ? 1867477eb7f9SFrançois Tigeot 0 : MI_BATCH_NON_SECURE)); 1868e3adcf8fSFrançois Tigeot intel_ring_advance(ring); 1869e3adcf8fSFrançois Tigeot 1870e3adcf8fSFrançois Tigeot return 0; 1871e3adcf8fSFrançois Tigeot } 1872e3adcf8fSFrançois Tigeot 1873ba55f2f5SFrançois Tigeot static void cleanup_status_page(struct intel_engine_cs *ring) 1874e3adcf8fSFrançois Tigeot { 1875e3adcf8fSFrançois Tigeot struct drm_i915_gem_object *obj; 1876e3adcf8fSFrançois Tigeot 1877e3adcf8fSFrançois Tigeot obj = ring->status_page.obj; 1878e3adcf8fSFrançois Tigeot if (obj == NULL) 1879e3adcf8fSFrançois Tigeot return; 1880e3adcf8fSFrançois Tigeot 18817ec9f8e5SFrançois Tigeot kunmap(sg_page(obj->pages->sgl)); 1882ba55f2f5SFrançois Tigeot i915_gem_object_ggtt_unpin(obj); 1883e3adcf8fSFrançois Tigeot drm_gem_object_unreference(&obj->base); 1884e3adcf8fSFrançois Tigeot ring->status_page.obj = NULL; 1885e3adcf8fSFrançois Tigeot } 1886e3adcf8fSFrançois Tigeot 1887ba55f2f5SFrançois Tigeot static int init_status_page(struct intel_engine_cs *ring) 1888e3adcf8fSFrançois Tigeot { 1889e3adcf8fSFrançois Tigeot struct drm_i915_gem_object *obj; 1890ba55f2f5SFrançois Tigeot 1891ba55f2f5SFrançois Tigeot if ((obj = ring->status_page.obj) == NULL) { 189224edb884SFrançois Tigeot unsigned flags; 1893e3adcf8fSFrançois Tigeot int ret; 1894e3adcf8fSFrançois Tigeot 1895ba55f2f5SFrançois Tigeot obj = i915_gem_alloc_object(ring->dev, 4096); 1896e3adcf8fSFrançois Tigeot if (obj == NULL) { 1897e3adcf8fSFrançois Tigeot DRM_ERROR("Failed to allocate status page\n"); 1898ba55f2f5SFrançois Tigeot return -ENOMEM; 1899e3adcf8fSFrançois Tigeot } 1900e3adcf8fSFrançois Tigeot 1901ba55f2f5SFrançois Tigeot ret = i915_gem_object_set_cache_level(obj, I915_CACHE_LLC); 1902ba55f2f5SFrançois Tigeot if (ret) 1903e3adcf8fSFrançois Tigeot goto err_unref; 1904ba55f2f5SFrançois Tigeot 190524edb884SFrançois Tigeot flags = 0; 190624edb884SFrançois Tigeot if (!HAS_LLC(ring->dev)) 190724edb884SFrançois Tigeot /* On g33, we cannot place HWS above 256MiB, so 190824edb884SFrançois Tigeot * restrict its pinning to the low mappable arena. 190924edb884SFrançois Tigeot * Though this restriction is not documented for 191024edb884SFrançois Tigeot * gen4, gen5, or byt, they also behave similarly 191124edb884SFrançois Tigeot * and hang if the HWS is placed at the top of the 191224edb884SFrançois Tigeot * GTT. To generalise, it appears that all !llc 191324edb884SFrançois Tigeot * platforms have issues with us placing the HWS 191424edb884SFrançois Tigeot * above the mappable region (even though we never 191524edb884SFrançois Tigeot * actualy map it). 191624edb884SFrançois Tigeot */ 191724edb884SFrançois Tigeot flags |= PIN_MAPPABLE; 191824edb884SFrançois Tigeot ret = i915_gem_obj_ggtt_pin(obj, 4096, flags); 1919ba55f2f5SFrançois Tigeot if (ret) { 1920ba55f2f5SFrançois Tigeot err_unref: 1921ba55f2f5SFrançois Tigeot drm_gem_object_unreference(&obj->base); 1922ba55f2f5SFrançois Tigeot return ret; 1923ba55f2f5SFrançois Tigeot } 1924ba55f2f5SFrançois Tigeot 1925ba55f2f5SFrançois Tigeot ring->status_page.obj = obj; 1926e3adcf8fSFrançois Tigeot } 1927e3adcf8fSFrançois Tigeot 19289edbd4a0SFrançois Tigeot ring->status_page.gfx_addr = i915_gem_obj_ggtt_offset(obj); 19297ec9f8e5SFrançois Tigeot ring->status_page.page_addr = kmap(sg_page(obj->pages->sgl)); 1930e3adcf8fSFrançois Tigeot memset(ring->status_page.page_addr, 0, PAGE_SIZE); 1931e3adcf8fSFrançois Tigeot 1932b5c29a34SFrançois Tigeot DRM_DEBUG_DRIVER("%s hws offset: 0x%08x\n", 1933e3adcf8fSFrançois Tigeot ring->name, ring->status_page.gfx_addr); 1934e3adcf8fSFrançois Tigeot 1935e3adcf8fSFrançois Tigeot return 0; 1936e3adcf8fSFrançois Tigeot } 1937e3adcf8fSFrançois Tigeot 1938ba55f2f5SFrançois Tigeot static int init_phys_status_page(struct intel_engine_cs *ring) 1939686a02f1SFrançois Tigeot { 1940686a02f1SFrançois Tigeot struct drm_i915_private *dev_priv = ring->dev->dev_private; 1941686a02f1SFrançois Tigeot 1942686a02f1SFrançois Tigeot if (!dev_priv->status_page_dmah) { 1943686a02f1SFrançois Tigeot dev_priv->status_page_dmah = 1944b31e9d59SFrançois Tigeot drm_pci_alloc(ring->dev, PAGE_SIZE, PAGE_SIZE); 1945686a02f1SFrançois Tigeot if (!dev_priv->status_page_dmah) 1946686a02f1SFrançois Tigeot return -ENOMEM; 1947686a02f1SFrançois Tigeot } 1948686a02f1SFrançois Tigeot 1949686a02f1SFrançois Tigeot ring->status_page.page_addr = dev_priv->status_page_dmah->vaddr; 1950686a02f1SFrançois Tigeot memset(ring->status_page.page_addr, 0, PAGE_SIZE); 1951686a02f1SFrançois Tigeot 1952686a02f1SFrançois Tigeot return 0; 1953686a02f1SFrançois Tigeot } 1954686a02f1SFrançois Tigeot 19552c9916cdSFrançois Tigeot void intel_unpin_ringbuffer_obj(struct intel_ringbuffer *ringbuf) 19562c9916cdSFrançois Tigeot { 195724409b39SFrançois Tigeot iounmap(ringbuf->virtual_start); 19582c9916cdSFrançois Tigeot ringbuf->virtual_start = NULL; 19592c9916cdSFrançois Tigeot i915_gem_object_ggtt_unpin(ringbuf->obj); 19602c9916cdSFrançois Tigeot } 19612c9916cdSFrançois Tigeot 19622c9916cdSFrançois Tigeot int intel_pin_and_map_ringbuffer_obj(struct drm_device *dev, 19632c9916cdSFrançois Tigeot struct intel_ringbuffer *ringbuf) 19642c9916cdSFrançois Tigeot { 19652c9916cdSFrançois Tigeot struct drm_i915_private *dev_priv = to_i915(dev); 19662c9916cdSFrançois Tigeot struct drm_i915_gem_object *obj = ringbuf->obj; 19672c9916cdSFrançois Tigeot int ret; 19682c9916cdSFrançois Tigeot 19692c9916cdSFrançois Tigeot ret = i915_gem_obj_ggtt_pin(obj, PAGE_SIZE, PIN_MAPPABLE); 19702c9916cdSFrançois Tigeot if (ret) 19712c9916cdSFrançois Tigeot return ret; 19722c9916cdSFrançois Tigeot 19732c9916cdSFrançois Tigeot ret = i915_gem_object_set_to_gtt_domain(obj, true); 19742c9916cdSFrançois Tigeot if (ret) { 19752c9916cdSFrançois Tigeot i915_gem_object_ggtt_unpin(obj); 19762c9916cdSFrançois Tigeot return ret; 19772c9916cdSFrançois Tigeot } 19782c9916cdSFrançois Tigeot 19792c9916cdSFrançois Tigeot ringbuf->virtual_start = ioremap_wc(dev_priv->gtt.mappable_base + 19802c9916cdSFrançois Tigeot i915_gem_obj_ggtt_offset(obj), ringbuf->size); 19812c9916cdSFrançois Tigeot if (ringbuf->virtual_start == NULL) { 19822c9916cdSFrançois Tigeot i915_gem_object_ggtt_unpin(obj); 19832c9916cdSFrançois Tigeot return -EINVAL; 19842c9916cdSFrançois Tigeot } 19852c9916cdSFrançois Tigeot 19862c9916cdSFrançois Tigeot return 0; 19872c9916cdSFrançois Tigeot } 19882c9916cdSFrançois Tigeot 19891b13d190SFrançois Tigeot void intel_destroy_ringbuffer_obj(struct intel_ringbuffer *ringbuf) 1990e3adcf8fSFrançois Tigeot { 199124edb884SFrançois Tigeot drm_gem_object_unreference(&ringbuf->obj->base); 199224edb884SFrançois Tigeot ringbuf->obj = NULL; 199324edb884SFrançois Tigeot } 199424edb884SFrançois Tigeot 19951b13d190SFrançois Tigeot int intel_alloc_ringbuffer_obj(struct drm_device *dev, 199624edb884SFrançois Tigeot struct intel_ringbuffer *ringbuf) 199724edb884SFrançois Tigeot { 1998e3adcf8fSFrançois Tigeot struct drm_i915_gem_object *obj; 1999e3adcf8fSFrançois Tigeot 2000a2fdbec6SFrançois Tigeot obj = NULL; 2001a2fdbec6SFrançois Tigeot if (!HAS_LLC(dev)) 2002ba55f2f5SFrançois Tigeot obj = i915_gem_object_create_stolen(dev, ringbuf->size); 2003a2fdbec6SFrançois Tigeot if (obj == NULL) 2004ba55f2f5SFrançois Tigeot obj = i915_gem_alloc_object(dev, ringbuf->size); 2005ba55f2f5SFrançois Tigeot if (obj == NULL) 2006ba55f2f5SFrançois Tigeot return -ENOMEM; 2007e3adcf8fSFrançois Tigeot 200824edb884SFrançois Tigeot /* mark ring buffers as read-only from GPU side by default */ 200924edb884SFrançois Tigeot obj->gt_ro = 1; 201024edb884SFrançois Tigeot 2011ba55f2f5SFrançois Tigeot ringbuf->obj = obj; 2012ba55f2f5SFrançois Tigeot 20132c9916cdSFrançois Tigeot return 0; 2014ba55f2f5SFrançois Tigeot } 2015ba55f2f5SFrançois Tigeot 2016ba55f2f5SFrançois Tigeot static int intel_init_ring_buffer(struct drm_device *dev, 2017ba55f2f5SFrançois Tigeot struct intel_engine_cs *ring) 2018ba55f2f5SFrançois Tigeot { 20192c9916cdSFrançois Tigeot struct intel_ringbuffer *ringbuf; 2020ba55f2f5SFrançois Tigeot int ret; 2021ba55f2f5SFrançois Tigeot 20222c9916cdSFrançois Tigeot WARN_ON(ring->buffer); 20232c9916cdSFrançois Tigeot 2024ba55f2f5SFrançois Tigeot ringbuf = kzalloc(sizeof(*ringbuf), GFP_KERNEL); 2025ba55f2f5SFrançois Tigeot if (!ringbuf) 2026ba55f2f5SFrançois Tigeot return -ENOMEM; 2027ba55f2f5SFrançois Tigeot ring->buffer = ringbuf; 2028ba55f2f5SFrançois Tigeot 2029ba55f2f5SFrançois Tigeot ring->dev = dev; 2030ba55f2f5SFrançois Tigeot INIT_LIST_HEAD(&ring->active_list); 2031ba55f2f5SFrançois Tigeot INIT_LIST_HEAD(&ring->request_list); 20321b13d190SFrançois Tigeot INIT_LIST_HEAD(&ring->execlist_queue); 203319c468b4SFrançois Tigeot i915_gem_batch_pool_init(dev, &ring->batch_pool); 2034ba55f2f5SFrançois Tigeot ringbuf->size = 32 * PAGE_SIZE; 20351b13d190SFrançois Tigeot ringbuf->ring = ring; 2036ba55f2f5SFrançois Tigeot memset(ring->semaphore.sync_seqno, 0, sizeof(ring->semaphore.sync_seqno)); 2037ba55f2f5SFrançois Tigeot 2038ba55f2f5SFrançois Tigeot init_waitqueue_head(&ring->irq_queue); 2039ba55f2f5SFrançois Tigeot 2040ba55f2f5SFrançois Tigeot if (I915_NEED_GFX_HWS(dev)) { 2041ba55f2f5SFrançois Tigeot ret = init_status_page(ring); 2042e3adcf8fSFrançois Tigeot if (ret) 2043ba55f2f5SFrançois Tigeot goto error; 2044ba55f2f5SFrançois Tigeot } else { 2045ba55f2f5SFrançois Tigeot BUG_ON(ring->id != RCS); 2046ba55f2f5SFrançois Tigeot ret = init_phys_status_page(ring); 2047ba55f2f5SFrançois Tigeot if (ret) 2048ba55f2f5SFrançois Tigeot goto error; 2049ba55f2f5SFrançois Tigeot } 2050ba55f2f5SFrançois Tigeot 20512c9916cdSFrançois Tigeot WARN_ON(ringbuf->obj); 20522c9916cdSFrançois Tigeot 205324edb884SFrançois Tigeot ret = intel_alloc_ringbuffer_obj(dev, ringbuf); 2054ba55f2f5SFrançois Tigeot if (ret) { 20552c9916cdSFrançois Tigeot DRM_ERROR("Failed to allocate ringbuffer %s: %d\n", 20562c9916cdSFrançois Tigeot ring->name, ret); 20572c9916cdSFrançois Tigeot goto error; 20582c9916cdSFrançois Tigeot } 20592c9916cdSFrançois Tigeot 20602c9916cdSFrançois Tigeot ret = intel_pin_and_map_ringbuffer_obj(dev, ringbuf); 20612c9916cdSFrançois Tigeot if (ret) { 20622c9916cdSFrançois Tigeot DRM_ERROR("Failed to pin and map ringbuffer %s: %d\n", 20632c9916cdSFrançois Tigeot ring->name, ret); 20642c9916cdSFrançois Tigeot intel_destroy_ringbuffer_obj(ringbuf); 2065ba55f2f5SFrançois Tigeot goto error; 2066ba55f2f5SFrançois Tigeot } 2067e3adcf8fSFrançois Tigeot 2068e3adcf8fSFrançois Tigeot /* Workaround an erratum on the i830 which causes a hang if 2069e3adcf8fSFrançois Tigeot * the TAIL pointer points to within the last 2 cachelines 2070e3adcf8fSFrançois Tigeot * of the buffer. 2071e3adcf8fSFrançois Tigeot */ 2072ba55f2f5SFrançois Tigeot ringbuf->effective_size = ringbuf->size; 2073ba55f2f5SFrançois Tigeot if (IS_I830(dev) || IS_845G(dev)) 2074ba55f2f5SFrançois Tigeot ringbuf->effective_size -= 2 * CACHELINE_BYTES; 2075ba55f2f5SFrançois Tigeot 2076ba55f2f5SFrançois Tigeot ret = i915_cmd_parser_init_ring(ring); 2077ba55f2f5SFrançois Tigeot if (ret) 2078ba55f2f5SFrançois Tigeot goto error; 2079ba55f2f5SFrançois Tigeot 2080e3adcf8fSFrançois Tigeot return 0; 2081e3adcf8fSFrançois Tigeot 2082ba55f2f5SFrançois Tigeot error: 2083ba55f2f5SFrançois Tigeot kfree(ringbuf); 2084ba55f2f5SFrançois Tigeot ring->buffer = NULL; 2085e3adcf8fSFrançois Tigeot return ret; 2086e3adcf8fSFrançois Tigeot } 2087e3adcf8fSFrançois Tigeot 2088ba55f2f5SFrançois Tigeot void intel_cleanup_ring_buffer(struct intel_engine_cs *ring) 2089e3adcf8fSFrançois Tigeot { 20902c9916cdSFrançois Tigeot struct drm_i915_private *dev_priv; 20912c9916cdSFrançois Tigeot struct intel_ringbuffer *ringbuf; 2092e3adcf8fSFrançois Tigeot 2093ba55f2f5SFrançois Tigeot if (!intel_ring_initialized(ring)) 2094e3adcf8fSFrançois Tigeot return; 2095e3adcf8fSFrançois Tigeot 20962c9916cdSFrançois Tigeot dev_priv = to_i915(ring->dev); 20972c9916cdSFrançois Tigeot ringbuf = ring->buffer; 20982c9916cdSFrançois Tigeot 2099ba55f2f5SFrançois Tigeot intel_stop_ring_buffer(ring); 2100ba55f2f5SFrançois Tigeot WARN_ON(!IS_GEN2(ring->dev) && (I915_READ_MODE(ring) & MODE_IDLE) == 0); 2101b030f26bSFrançois Tigeot 21022c9916cdSFrançois Tigeot intel_unpin_ringbuffer_obj(ringbuf); 210324edb884SFrançois Tigeot intel_destroy_ringbuffer_obj(ringbuf); 2104e3adcf8fSFrançois Tigeot 2105e3adcf8fSFrançois Tigeot if (ring->cleanup) 2106e3adcf8fSFrançois Tigeot ring->cleanup(ring); 2107e3adcf8fSFrançois Tigeot 2108e3adcf8fSFrançois Tigeot cleanup_status_page(ring); 2109ba55f2f5SFrançois Tigeot 2110ba55f2f5SFrançois Tigeot i915_cmd_parser_fini_ring(ring); 211119c468b4SFrançois Tigeot i915_gem_batch_pool_fini(&ring->batch_pool); 2112ba55f2f5SFrançois Tigeot 2113ba55f2f5SFrançois Tigeot kfree(ringbuf); 2114ba55f2f5SFrançois Tigeot ring->buffer = NULL; 2115e3adcf8fSFrançois Tigeot } 2116e3adcf8fSFrançois Tigeot 211719c468b4SFrançois Tigeot static int ring_wait_for_space(struct intel_engine_cs *ring, int n) 2118e3adcf8fSFrançois Tigeot { 2119ba55f2f5SFrançois Tigeot struct intel_ringbuffer *ringbuf = ring->buffer; 2120e3adcf8fSFrançois Tigeot struct drm_i915_gem_request *request; 212119c468b4SFrançois Tigeot unsigned space; 2122e3adcf8fSFrançois Tigeot int ret; 2123e3adcf8fSFrançois Tigeot 21242c9916cdSFrançois Tigeot if (intel_ring_space(ringbuf) >= n) 2125e3adcf8fSFrançois Tigeot return 0; 2126e3adcf8fSFrançois Tigeot 2127*a05eeebfSFrançois Tigeot /* The whole point of reserving space is to not wait! */ 2128*a05eeebfSFrançois Tigeot WARN_ON(ringbuf->reserved_in_use); 2129*a05eeebfSFrançois Tigeot 2130e3adcf8fSFrançois Tigeot list_for_each_entry(request, &ring->request_list, list) { 213119c468b4SFrançois Tigeot space = __intel_ring_space(request->postfix, ringbuf->tail, 213219c468b4SFrançois Tigeot ringbuf->size); 213319c468b4SFrançois Tigeot if (space >= n) 2134e3adcf8fSFrançois Tigeot break; 2135e3adcf8fSFrançois Tigeot } 2136e3adcf8fSFrançois Tigeot 213719c468b4SFrançois Tigeot if (WARN_ON(&request->list == &ring->request_list)) 2138e3adcf8fSFrançois Tigeot return -ENOSPC; 2139e3adcf8fSFrançois Tigeot 21402c9916cdSFrançois Tigeot ret = i915_wait_request(request); 2141e3adcf8fSFrançois Tigeot if (ret) 2142e3adcf8fSFrançois Tigeot return ret; 2143e3adcf8fSFrançois Tigeot 214419c468b4SFrançois Tigeot ringbuf->space = space; 2145e3adcf8fSFrançois Tigeot return 0; 2146e3adcf8fSFrançois Tigeot } 2147e3adcf8fSFrançois Tigeot 2148*a05eeebfSFrançois Tigeot static void __wrap_ring_buffer(struct intel_ringbuffer *ringbuf) 2149b030f26bSFrançois Tigeot { 2150b030f26bSFrançois Tigeot uint32_t __iomem *virt; 2151ba55f2f5SFrançois Tigeot int rem = ringbuf->size - ringbuf->tail; 2152b030f26bSFrançois Tigeot 2153ba55f2f5SFrançois Tigeot virt = (unsigned int *)((char *)ringbuf->virtual_start + ringbuf->tail); 2154b030f26bSFrançois Tigeot rem /= 4; 2155b030f26bSFrançois Tigeot while (rem--) 2156686a02f1SFrançois Tigeot iowrite32(MI_NOOP, virt++); 2157b030f26bSFrançois Tigeot 2158ba55f2f5SFrançois Tigeot ringbuf->tail = 0; 21592c9916cdSFrançois Tigeot intel_ring_update_space(ringbuf); 2160b030f26bSFrançois Tigeot } 2161b030f26bSFrançois Tigeot 2162ba55f2f5SFrançois Tigeot int intel_ring_idle(struct intel_engine_cs *ring) 2163b030f26bSFrançois Tigeot { 21642c9916cdSFrançois Tigeot struct drm_i915_gem_request *req; 2165b5c29a34SFrançois Tigeot 2166b5c29a34SFrançois Tigeot /* Wait upon the last request to be completed */ 2167b5c29a34SFrançois Tigeot if (list_empty(&ring->request_list)) 2168b5c29a34SFrançois Tigeot return 0; 2169b5c29a34SFrançois Tigeot 21702c9916cdSFrançois Tigeot req = list_entry(ring->request_list.prev, 2171b5c29a34SFrançois Tigeot struct drm_i915_gem_request, 21722c9916cdSFrançois Tigeot list); 2173b5c29a34SFrançois Tigeot 217419c468b4SFrançois Tigeot /* Make sure we do not trigger any retires */ 217519c468b4SFrançois Tigeot return __i915_wait_request(req, 217619c468b4SFrançois Tigeot atomic_read(&to_i915(ring->dev)->gpu_error.reset_counter), 217719c468b4SFrançois Tigeot to_i915(ring->dev)->mm.interruptible, 217819c468b4SFrançois Tigeot NULL, NULL); 2179b5c29a34SFrançois Tigeot } 2180b5c29a34SFrançois Tigeot 218119c468b4SFrançois Tigeot int intel_ring_alloc_request_extras(struct drm_i915_gem_request *request) 2182b5c29a34SFrançois Tigeot { 218319c468b4SFrançois Tigeot request->ringbuf = request->ring->buffer; 21842c9916cdSFrançois Tigeot return 0; 21859edbd4a0SFrançois Tigeot } 21869edbd4a0SFrançois Tigeot 2187*a05eeebfSFrançois Tigeot int intel_ring_reserve_space(struct drm_i915_gem_request *request) 2188a2fdbec6SFrançois Tigeot { 2189*a05eeebfSFrançois Tigeot /* 2190*a05eeebfSFrançois Tigeot * The first call merely notes the reserve request and is common for 2191*a05eeebfSFrançois Tigeot * all back ends. The subsequent localised _begin() call actually 2192*a05eeebfSFrançois Tigeot * ensures that the reservation is available. Without the begin, if 2193*a05eeebfSFrançois Tigeot * the request creator immediately submitted the request without 2194*a05eeebfSFrançois Tigeot * adding any commands to it then there might not actually be 2195*a05eeebfSFrançois Tigeot * sufficient room for the submission commands. 2196*a05eeebfSFrançois Tigeot */ 2197*a05eeebfSFrançois Tigeot intel_ring_reserved_space_reserve(request->ringbuf, MIN_SPACE_FOR_ADD_REQUEST); 2198a2fdbec6SFrançois Tigeot 2199*a05eeebfSFrançois Tigeot return intel_ring_begin(request, 0); 2200a2fdbec6SFrançois Tigeot } 2201a2fdbec6SFrançois Tigeot 2202*a05eeebfSFrançois Tigeot void intel_ring_reserved_space_reserve(struct intel_ringbuffer *ringbuf, int size) 2203*a05eeebfSFrançois Tigeot { 2204*a05eeebfSFrançois Tigeot WARN_ON(ringbuf->reserved_size); 2205*a05eeebfSFrançois Tigeot WARN_ON(ringbuf->reserved_in_use); 2206*a05eeebfSFrançois Tigeot 2207*a05eeebfSFrançois Tigeot ringbuf->reserved_size = size; 2208*a05eeebfSFrançois Tigeot } 2209*a05eeebfSFrançois Tigeot 2210*a05eeebfSFrançois Tigeot void intel_ring_reserved_space_cancel(struct intel_ringbuffer *ringbuf) 2211*a05eeebfSFrançois Tigeot { 2212*a05eeebfSFrançois Tigeot WARN_ON(ringbuf->reserved_in_use); 2213*a05eeebfSFrançois Tigeot 2214*a05eeebfSFrançois Tigeot ringbuf->reserved_size = 0; 2215*a05eeebfSFrançois Tigeot ringbuf->reserved_in_use = false; 2216*a05eeebfSFrançois Tigeot } 2217*a05eeebfSFrançois Tigeot 2218*a05eeebfSFrançois Tigeot void intel_ring_reserved_space_use(struct intel_ringbuffer *ringbuf) 2219*a05eeebfSFrançois Tigeot { 2220*a05eeebfSFrançois Tigeot WARN_ON(ringbuf->reserved_in_use); 2221*a05eeebfSFrançois Tigeot 2222*a05eeebfSFrançois Tigeot ringbuf->reserved_in_use = true; 2223*a05eeebfSFrançois Tigeot ringbuf->reserved_tail = ringbuf->tail; 2224*a05eeebfSFrançois Tigeot } 2225*a05eeebfSFrançois Tigeot 2226*a05eeebfSFrançois Tigeot void intel_ring_reserved_space_end(struct intel_ringbuffer *ringbuf) 2227*a05eeebfSFrançois Tigeot { 2228*a05eeebfSFrançois Tigeot WARN_ON(!ringbuf->reserved_in_use); 2229*a05eeebfSFrançois Tigeot if (ringbuf->tail > ringbuf->reserved_tail) { 2230*a05eeebfSFrançois Tigeot WARN(ringbuf->tail > ringbuf->reserved_tail + ringbuf->reserved_size, 2231*a05eeebfSFrançois Tigeot "request reserved size too small: %d vs %d!\n", 2232*a05eeebfSFrançois Tigeot ringbuf->tail - ringbuf->reserved_tail, ringbuf->reserved_size); 2233*a05eeebfSFrançois Tigeot } else { 2234*a05eeebfSFrançois Tigeot /* 2235*a05eeebfSFrançois Tigeot * The ring was wrapped while the reserved space was in use. 2236*a05eeebfSFrançois Tigeot * That means that some unknown amount of the ring tail was 2237*a05eeebfSFrançois Tigeot * no-op filled and skipped. Thus simply adding the ring size 2238*a05eeebfSFrançois Tigeot * to the tail and doing the above space check will not work. 2239*a05eeebfSFrançois Tigeot * Rather than attempt to track how much tail was skipped, 2240*a05eeebfSFrançois Tigeot * it is much simpler to say that also skipping the sanity 2241*a05eeebfSFrançois Tigeot * check every once in a while is not a big issue. 2242*a05eeebfSFrançois Tigeot */ 2243*a05eeebfSFrançois Tigeot } 2244*a05eeebfSFrançois Tigeot 2245*a05eeebfSFrançois Tigeot ringbuf->reserved_size = 0; 2246*a05eeebfSFrançois Tigeot ringbuf->reserved_in_use = false; 2247*a05eeebfSFrançois Tigeot } 2248*a05eeebfSFrançois Tigeot 2249*a05eeebfSFrançois Tigeot static int __intel_ring_prepare(struct intel_engine_cs *ring, int bytes) 2250*a05eeebfSFrançois Tigeot { 2251*a05eeebfSFrançois Tigeot struct intel_ringbuffer *ringbuf = ring->buffer; 2252*a05eeebfSFrançois Tigeot int remain_usable = ringbuf->effective_size - ringbuf->tail; 2253*a05eeebfSFrançois Tigeot int remain_actual = ringbuf->size - ringbuf->tail; 2254*a05eeebfSFrançois Tigeot int ret, total_bytes, wait_bytes = 0; 2255*a05eeebfSFrançois Tigeot bool need_wrap = false; 2256*a05eeebfSFrançois Tigeot 2257*a05eeebfSFrançois Tigeot if (ringbuf->reserved_in_use) 2258*a05eeebfSFrançois Tigeot total_bytes = bytes; 2259*a05eeebfSFrançois Tigeot else 2260*a05eeebfSFrançois Tigeot total_bytes = bytes + ringbuf->reserved_size; 2261*a05eeebfSFrançois Tigeot 2262*a05eeebfSFrançois Tigeot if (unlikely(bytes > remain_usable)) { 2263*a05eeebfSFrançois Tigeot /* 2264*a05eeebfSFrançois Tigeot * Not enough space for the basic request. So need to flush 2265*a05eeebfSFrançois Tigeot * out the remainder and then wait for base + reserved. 2266*a05eeebfSFrançois Tigeot */ 2267*a05eeebfSFrançois Tigeot wait_bytes = remain_actual + total_bytes; 2268*a05eeebfSFrançois Tigeot need_wrap = true; 2269*a05eeebfSFrançois Tigeot } else { 2270*a05eeebfSFrançois Tigeot if (unlikely(total_bytes > remain_usable)) { 2271*a05eeebfSFrançois Tigeot /* 2272*a05eeebfSFrançois Tigeot * The base request will fit but the reserved space 2273*a05eeebfSFrançois Tigeot * falls off the end. So only need to to wait for the 2274*a05eeebfSFrançois Tigeot * reserved size after flushing out the remainder. 2275*a05eeebfSFrançois Tigeot */ 2276*a05eeebfSFrançois Tigeot wait_bytes = remain_actual + ringbuf->reserved_size; 2277*a05eeebfSFrançois Tigeot need_wrap = true; 2278*a05eeebfSFrançois Tigeot } else if (total_bytes > ringbuf->space) { 2279*a05eeebfSFrançois Tigeot /* No wrapping required, just waiting. */ 2280*a05eeebfSFrançois Tigeot wait_bytes = total_bytes; 2281*a05eeebfSFrançois Tigeot } 2282*a05eeebfSFrançois Tigeot } 2283*a05eeebfSFrançois Tigeot 2284*a05eeebfSFrançois Tigeot if (wait_bytes) { 2285*a05eeebfSFrançois Tigeot ret = ring_wait_for_space(ring, wait_bytes); 2286a2fdbec6SFrançois Tigeot if (unlikely(ret)) 2287a2fdbec6SFrançois Tigeot return ret; 2288*a05eeebfSFrançois Tigeot 2289*a05eeebfSFrançois Tigeot if (need_wrap) 2290*a05eeebfSFrançois Tigeot __wrap_ring_buffer(ringbuf); 2291a2fdbec6SFrançois Tigeot } 2292a2fdbec6SFrançois Tigeot 2293a2fdbec6SFrançois Tigeot return 0; 2294a2fdbec6SFrançois Tigeot } 2295a2fdbec6SFrançois Tigeot 2296*a05eeebfSFrançois Tigeot int intel_ring_begin(struct drm_i915_gem_request *req, 2297e3adcf8fSFrançois Tigeot int num_dwords) 2298e3adcf8fSFrançois Tigeot { 2299*a05eeebfSFrançois Tigeot struct intel_engine_cs *ring; 2300*a05eeebfSFrançois Tigeot struct drm_i915_private *dev_priv; 2301e3adcf8fSFrançois Tigeot int ret; 2302e3adcf8fSFrançois Tigeot 2303*a05eeebfSFrançois Tigeot WARN_ON(req == NULL); 2304*a05eeebfSFrançois Tigeot ring = req->ring; 2305*a05eeebfSFrançois Tigeot dev_priv = ring->dev->dev_private; 2306*a05eeebfSFrançois Tigeot 2307a2fdbec6SFrançois Tigeot ret = i915_gem_check_wedge(&dev_priv->gpu_error, 2308a2fdbec6SFrançois Tigeot dev_priv->mm.interruptible); 2309245593daSFrançois Tigeot if (ret) 2310245593daSFrançois Tigeot return ret; 2311e3adcf8fSFrançois Tigeot 23129edbd4a0SFrançois Tigeot ret = __intel_ring_prepare(ring, num_dwords * sizeof(uint32_t)); 23139edbd4a0SFrançois Tigeot if (ret) 23149edbd4a0SFrançois Tigeot return ret; 23159edbd4a0SFrançois Tigeot 2316ba55f2f5SFrançois Tigeot ring->buffer->space -= num_dwords * sizeof(uint32_t); 23179edbd4a0SFrançois Tigeot return 0; 23189edbd4a0SFrançois Tigeot } 23199edbd4a0SFrançois Tigeot 23209edbd4a0SFrançois Tigeot /* Align the ring tail to a cacheline boundary */ 2321*a05eeebfSFrançois Tigeot int intel_ring_cacheline_align(struct drm_i915_gem_request *req) 23229edbd4a0SFrançois Tigeot { 2323*a05eeebfSFrançois Tigeot struct intel_engine_cs *ring = req->ring; 2324ba55f2f5SFrançois Tigeot int num_dwords = (ring->buffer->tail & (CACHELINE_BYTES - 1)) / sizeof(uint32_t); 23259edbd4a0SFrançois Tigeot int ret; 23269edbd4a0SFrançois Tigeot 23279edbd4a0SFrançois Tigeot if (num_dwords == 0) 23289edbd4a0SFrançois Tigeot return 0; 23299edbd4a0SFrançois Tigeot 2330ba55f2f5SFrançois Tigeot num_dwords = CACHELINE_BYTES / sizeof(uint32_t) - num_dwords; 2331*a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, num_dwords); 23329edbd4a0SFrançois Tigeot if (ret) 23339edbd4a0SFrançois Tigeot return ret; 23349edbd4a0SFrançois Tigeot 23359edbd4a0SFrançois Tigeot while (num_dwords--) 23369edbd4a0SFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 23379edbd4a0SFrançois Tigeot 23389edbd4a0SFrançois Tigeot intel_ring_advance(ring); 23399edbd4a0SFrançois Tigeot 23409edbd4a0SFrançois Tigeot return 0; 2341e3adcf8fSFrançois Tigeot } 2342e3adcf8fSFrançois Tigeot 2343ba55f2f5SFrançois Tigeot void intel_ring_init_seqno(struct intel_engine_cs *ring, u32 seqno) 2344a2fdbec6SFrançois Tigeot { 234524edb884SFrançois Tigeot struct drm_device *dev = ring->dev; 234624edb884SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 2347a2fdbec6SFrançois Tigeot 234824edb884SFrançois Tigeot if (INTEL_INFO(dev)->gen == 6 || INTEL_INFO(dev)->gen == 7) { 2349a2fdbec6SFrançois Tigeot I915_WRITE(RING_SYNC_0(ring->mmio_base), 0); 2350a2fdbec6SFrançois Tigeot I915_WRITE(RING_SYNC_1(ring->mmio_base), 0); 235124edb884SFrançois Tigeot if (HAS_VEBOX(dev)) 23529edbd4a0SFrançois Tigeot I915_WRITE(RING_SYNC_2(ring->mmio_base), 0); 2353e3adcf8fSFrançois Tigeot } 2354e3adcf8fSFrançois Tigeot 2355a2fdbec6SFrançois Tigeot ring->set_seqno(ring, seqno); 23565d0b1887SFrançois Tigeot ring->hangcheck.seqno = seqno; 2357e3adcf8fSFrançois Tigeot } 2358e3adcf8fSFrançois Tigeot 2359ba55f2f5SFrançois Tigeot static void gen6_bsd_ring_write_tail(struct intel_engine_cs *ring, 2360f4e1c372SFrançois Tigeot u32 value) 2361e3adcf8fSFrançois Tigeot { 2362ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = ring->dev->dev_private; 2363e3adcf8fSFrançois Tigeot 2364e3adcf8fSFrançois Tigeot /* Every tail move must follow the sequence below */ 2365f4e1c372SFrançois Tigeot 2366f4e1c372SFrançois Tigeot /* Disable notification that the ring is IDLE. The GT 2367f4e1c372SFrançois Tigeot * will then assume that it is busy and bring it out of rc6. 2368f4e1c372SFrançois Tigeot */ 2369e3adcf8fSFrançois Tigeot I915_WRITE(GEN6_BSD_SLEEP_PSMI_CONTROL, 2370f4e1c372SFrançois Tigeot _MASKED_BIT_ENABLE(GEN6_BSD_SLEEP_MSG_DISABLE)); 2371e3adcf8fSFrançois Tigeot 2372f4e1c372SFrançois Tigeot /* Clear the context id. Here be magic! */ 2373f4e1c372SFrançois Tigeot I915_WRITE64(GEN6_BSD_RNCID, 0x0); 2374e3adcf8fSFrançois Tigeot 2375f4e1c372SFrançois Tigeot /* Wait for the ring not to be idle, i.e. for it to wake up. */ 2376f4e1c372SFrançois Tigeot if (wait_for((I915_READ(GEN6_BSD_SLEEP_PSMI_CONTROL) & 2377f4e1c372SFrançois Tigeot GEN6_BSD_SLEEP_INDICATOR) == 0, 2378f4e1c372SFrançois Tigeot 50)) 2379f4e1c372SFrançois Tigeot DRM_ERROR("timed out waiting for the BSD ring to wake up\n"); 2380f4e1c372SFrançois Tigeot 2381f4e1c372SFrançois Tigeot /* Now that the ring is fully powered up, update the tail */ 2382e3adcf8fSFrançois Tigeot I915_WRITE_TAIL(ring, value); 2383f4e1c372SFrançois Tigeot POSTING_READ(RING_TAIL(ring->mmio_base)); 2384f4e1c372SFrançois Tigeot 2385f4e1c372SFrançois Tigeot /* Let the ring send IDLE messages to the GT again, 2386f4e1c372SFrançois Tigeot * and so let it sleep to conserve power when idle. 2387f4e1c372SFrançois Tigeot */ 2388e3adcf8fSFrançois Tigeot I915_WRITE(GEN6_BSD_SLEEP_PSMI_CONTROL, 2389f4e1c372SFrançois Tigeot _MASKED_BIT_DISABLE(GEN6_BSD_SLEEP_MSG_DISABLE)); 2390e3adcf8fSFrançois Tigeot } 2391e3adcf8fSFrançois Tigeot 2392*a05eeebfSFrançois Tigeot static int gen6_bsd_ring_flush(struct drm_i915_gem_request *req, 2393b5c29a34SFrançois Tigeot u32 invalidate, u32 flush) 2394e3adcf8fSFrançois Tigeot { 2395*a05eeebfSFrançois Tigeot struct intel_engine_cs *ring = req->ring; 2396e3adcf8fSFrançois Tigeot uint32_t cmd; 2397e3adcf8fSFrançois Tigeot int ret; 2398e3adcf8fSFrançois Tigeot 2399*a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 4); 2400e3adcf8fSFrançois Tigeot if (ret) 2401e3adcf8fSFrançois Tigeot return ret; 2402e3adcf8fSFrançois Tigeot 2403e3adcf8fSFrançois Tigeot cmd = MI_FLUSH_DW; 24049edbd4a0SFrançois Tigeot if (INTEL_INFO(ring->dev)->gen >= 8) 24059edbd4a0SFrançois Tigeot cmd += 1; 24062c9916cdSFrançois Tigeot 24072c9916cdSFrançois Tigeot /* We always require a command barrier so that subsequent 24082c9916cdSFrançois Tigeot * commands, such as breadcrumb interrupts, are strictly ordered 24092c9916cdSFrançois Tigeot * wrt the contents of the write cache being flushed to memory 24102c9916cdSFrançois Tigeot * (and thus being coherent from the CPU). 24112c9916cdSFrançois Tigeot */ 24122c9916cdSFrançois Tigeot cmd |= MI_FLUSH_DW_STORE_INDEX | MI_FLUSH_DW_OP_STOREDW; 24132c9916cdSFrançois Tigeot 2414b5c29a34SFrançois Tigeot /* 2415b5c29a34SFrançois Tigeot * Bspec vol 1c.5 - video engine command streamer: 2416b5c29a34SFrançois Tigeot * "If ENABLED, all TLBs will be invalidated once the flush 2417b5c29a34SFrançois Tigeot * operation is complete. This bit is only valid when the 2418b5c29a34SFrançois Tigeot * Post-Sync Operation field is a value of 1h or 3h." 2419b5c29a34SFrançois Tigeot */ 2420e3adcf8fSFrançois Tigeot if (invalidate & I915_GEM_GPU_DOMAINS) 24212c9916cdSFrançois Tigeot cmd |= MI_INVALIDATE_TLB | MI_INVALIDATE_BSD; 24222c9916cdSFrançois Tigeot 2423e3adcf8fSFrançois Tigeot intel_ring_emit(ring, cmd); 2424b5c29a34SFrançois Tigeot intel_ring_emit(ring, I915_GEM_HWS_SCRATCH_ADDR | MI_FLUSH_DW_USE_GTT); 24259edbd4a0SFrançois Tigeot if (INTEL_INFO(ring->dev)->gen >= 8) { 24269edbd4a0SFrançois Tigeot intel_ring_emit(ring, 0); /* upper addr */ 24279edbd4a0SFrançois Tigeot intel_ring_emit(ring, 0); /* value */ 24289edbd4a0SFrançois Tigeot } else { 24299edbd4a0SFrançois Tigeot intel_ring_emit(ring, 0); 24309edbd4a0SFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 24319edbd4a0SFrançois Tigeot } 24329edbd4a0SFrançois Tigeot intel_ring_advance(ring); 24339edbd4a0SFrançois Tigeot return 0; 24349edbd4a0SFrançois Tigeot } 24359edbd4a0SFrançois Tigeot 24369edbd4a0SFrançois Tigeot static int 2437*a05eeebfSFrançois Tigeot gen8_ring_dispatch_execbuffer(struct drm_i915_gem_request *req, 2438ba55f2f5SFrançois Tigeot u64 offset, u32 len, 2439477eb7f9SFrançois Tigeot unsigned dispatch_flags) 24409edbd4a0SFrançois Tigeot { 2441*a05eeebfSFrançois Tigeot struct intel_engine_cs *ring = req->ring; 2442477eb7f9SFrançois Tigeot bool ppgtt = USES_PPGTT(ring->dev) && 2443477eb7f9SFrançois Tigeot !(dispatch_flags & I915_DISPATCH_SECURE); 24449edbd4a0SFrançois Tigeot int ret; 24459edbd4a0SFrançois Tigeot 2446*a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 4); 24479edbd4a0SFrançois Tigeot if (ret) 24489edbd4a0SFrançois Tigeot return ret; 24499edbd4a0SFrançois Tigeot 24509edbd4a0SFrançois Tigeot /* FIXME(BDW): Address space and security selectors. */ 2451*a05eeebfSFrançois Tigeot intel_ring_emit(ring, MI_BATCH_BUFFER_START_GEN8 | (ppgtt<<8) | 2452*a05eeebfSFrançois Tigeot (dispatch_flags & I915_DISPATCH_RS ? 2453*a05eeebfSFrançois Tigeot MI_BATCH_RESOURCE_STREAMER : 0)); 2454ba55f2f5SFrançois Tigeot intel_ring_emit(ring, lower_32_bits(offset)); 2455ba55f2f5SFrançois Tigeot intel_ring_emit(ring, upper_32_bits(offset)); 2456e3adcf8fSFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 2457e3adcf8fSFrançois Tigeot intel_ring_advance(ring); 24589edbd4a0SFrançois Tigeot 2459e3adcf8fSFrançois Tigeot return 0; 2460e3adcf8fSFrançois Tigeot } 2461e3adcf8fSFrançois Tigeot 2462e3adcf8fSFrançois Tigeot static int 2463*a05eeebfSFrançois Tigeot hsw_ring_dispatch_execbuffer(struct drm_i915_gem_request *req, 2464ba55f2f5SFrançois Tigeot u64 offset, u32 len, 2465477eb7f9SFrançois Tigeot unsigned dispatch_flags) 2466e3adcf8fSFrançois Tigeot { 2467*a05eeebfSFrançois Tigeot struct intel_engine_cs *ring = req->ring; 2468e3adcf8fSFrançois Tigeot int ret; 2469e3adcf8fSFrançois Tigeot 2470*a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 2); 2471e3adcf8fSFrançois Tigeot if (ret) 2472e3adcf8fSFrançois Tigeot return ret; 2473e3adcf8fSFrançois Tigeot 2474b5c29a34SFrançois Tigeot intel_ring_emit(ring, 24751b13d190SFrançois Tigeot MI_BATCH_BUFFER_START | 2476477eb7f9SFrançois Tigeot (dispatch_flags & I915_DISPATCH_SECURE ? 2477*a05eeebfSFrançois Tigeot 0 : MI_BATCH_PPGTT_HSW | MI_BATCH_NON_SECURE_HSW) | 2478*a05eeebfSFrançois Tigeot (dispatch_flags & I915_DISPATCH_RS ? 2479*a05eeebfSFrançois Tigeot MI_BATCH_RESOURCE_STREAMER : 0)); 2480b5c29a34SFrançois Tigeot /* bit0-7 is the length on GEN6+ */ 2481b5c29a34SFrançois Tigeot intel_ring_emit(ring, offset); 2482b5c29a34SFrançois Tigeot intel_ring_advance(ring); 2483b5c29a34SFrançois Tigeot 2484b5c29a34SFrançois Tigeot return 0; 2485b5c29a34SFrançois Tigeot } 2486b5c29a34SFrançois Tigeot 2487b5c29a34SFrançois Tigeot static int 2488*a05eeebfSFrançois Tigeot gen6_ring_dispatch_execbuffer(struct drm_i915_gem_request *req, 2489ba55f2f5SFrançois Tigeot u64 offset, u32 len, 2490477eb7f9SFrançois Tigeot unsigned dispatch_flags) 2491b5c29a34SFrançois Tigeot { 2492*a05eeebfSFrançois Tigeot struct intel_engine_cs *ring = req->ring; 2493b5c29a34SFrançois Tigeot int ret; 2494b5c29a34SFrançois Tigeot 2495*a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 2); 2496b5c29a34SFrançois Tigeot if (ret) 2497b5c29a34SFrançois Tigeot return ret; 2498b5c29a34SFrançois Tigeot 2499b5c29a34SFrançois Tigeot intel_ring_emit(ring, 2500b5c29a34SFrançois Tigeot MI_BATCH_BUFFER_START | 2501477eb7f9SFrançois Tigeot (dispatch_flags & I915_DISPATCH_SECURE ? 2502477eb7f9SFrançois Tigeot 0 : MI_BATCH_NON_SECURE_I965)); 2503e3adcf8fSFrançois Tigeot /* bit0-7 is the length on GEN6+ */ 2504e3adcf8fSFrançois Tigeot intel_ring_emit(ring, offset); 2505e3adcf8fSFrançois Tigeot intel_ring_advance(ring); 2506e3adcf8fSFrançois Tigeot 2507e3adcf8fSFrançois Tigeot return 0; 2508e3adcf8fSFrançois Tigeot } 2509e3adcf8fSFrançois Tigeot 2510e3adcf8fSFrançois Tigeot /* Blitter support (SandyBridge+) */ 2511e3adcf8fSFrançois Tigeot 2512*a05eeebfSFrançois Tigeot static int gen6_ring_flush(struct drm_i915_gem_request *req, 2513b5c29a34SFrançois Tigeot u32 invalidate, u32 flush) 2514e3adcf8fSFrançois Tigeot { 2515*a05eeebfSFrançois Tigeot struct intel_engine_cs *ring = req->ring; 25165d0b1887SFrançois Tigeot struct drm_device *dev = ring->dev; 2517e3adcf8fSFrançois Tigeot uint32_t cmd; 2518e3adcf8fSFrançois Tigeot int ret; 2519e3adcf8fSFrançois Tigeot 2520*a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 4); 2521e3adcf8fSFrançois Tigeot if (ret) 2522e3adcf8fSFrançois Tigeot return ret; 2523e3adcf8fSFrançois Tigeot 2524e3adcf8fSFrançois Tigeot cmd = MI_FLUSH_DW; 2525477eb7f9SFrançois Tigeot if (INTEL_INFO(dev)->gen >= 8) 25269edbd4a0SFrançois Tigeot cmd += 1; 25272c9916cdSFrançois Tigeot 25282c9916cdSFrançois Tigeot /* We always require a command barrier so that subsequent 25292c9916cdSFrançois Tigeot * commands, such as breadcrumb interrupts, are strictly ordered 25302c9916cdSFrançois Tigeot * wrt the contents of the write cache being flushed to memory 25312c9916cdSFrançois Tigeot * (and thus being coherent from the CPU). 25322c9916cdSFrançois Tigeot */ 25332c9916cdSFrançois Tigeot cmd |= MI_FLUSH_DW_STORE_INDEX | MI_FLUSH_DW_OP_STOREDW; 25342c9916cdSFrançois Tigeot 2535b5c29a34SFrançois Tigeot /* 2536b5c29a34SFrançois Tigeot * Bspec vol 1c.3 - blitter engine command streamer: 2537b5c29a34SFrançois Tigeot * "If ENABLED, all TLBs will be invalidated once the flush 2538b5c29a34SFrançois Tigeot * operation is complete. This bit is only valid when the 2539b5c29a34SFrançois Tigeot * Post-Sync Operation field is a value of 1h or 3h." 2540b5c29a34SFrançois Tigeot */ 2541e3adcf8fSFrançois Tigeot if (invalidate & I915_GEM_DOMAIN_RENDER) 25422c9916cdSFrançois Tigeot cmd |= MI_INVALIDATE_TLB; 2543e3adcf8fSFrançois Tigeot intel_ring_emit(ring, cmd); 2544b5c29a34SFrançois Tigeot intel_ring_emit(ring, I915_GEM_HWS_SCRATCH_ADDR | MI_FLUSH_DW_USE_GTT); 2545477eb7f9SFrançois Tigeot if (INTEL_INFO(dev)->gen >= 8) { 25469edbd4a0SFrançois Tigeot intel_ring_emit(ring, 0); /* upper addr */ 25479edbd4a0SFrançois Tigeot intel_ring_emit(ring, 0); /* value */ 25489edbd4a0SFrançois Tigeot } else { 2549e3adcf8fSFrançois Tigeot intel_ring_emit(ring, 0); 2550e3adcf8fSFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 25519edbd4a0SFrançois Tigeot } 2552e3adcf8fSFrançois Tigeot intel_ring_advance(ring); 25535d0b1887SFrançois Tigeot 2554e3adcf8fSFrançois Tigeot return 0; 2555e3adcf8fSFrançois Tigeot } 2556e3adcf8fSFrançois Tigeot 2557e3adcf8fSFrançois Tigeot int intel_init_render_ring_buffer(struct drm_device *dev) 2558e3adcf8fSFrançois Tigeot { 2559ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 2560ba55f2f5SFrançois Tigeot struct intel_engine_cs *ring = &dev_priv->ring[RCS]; 256124edb884SFrançois Tigeot struct drm_i915_gem_object *obj; 256224edb884SFrançois Tigeot int ret; 2563e3adcf8fSFrançois Tigeot 2564686a02f1SFrançois Tigeot ring->name = "render ring"; 2565686a02f1SFrançois Tigeot ring->id = RCS; 2566686a02f1SFrançois Tigeot ring->mmio_base = RENDER_RING_BASE; 2567686a02f1SFrançois Tigeot 256824edb884SFrançois Tigeot if (INTEL_INFO(dev)->gen >= 8) { 256924edb884SFrançois Tigeot if (i915_semaphore_is_enabled(dev)) { 257024edb884SFrançois Tigeot obj = i915_gem_alloc_object(dev, 4096); 257124edb884SFrançois Tigeot if (obj == NULL) { 257224edb884SFrançois Tigeot DRM_ERROR("Failed to allocate semaphore bo. Disabling semaphores\n"); 257324edb884SFrançois Tigeot i915.semaphores = 0; 257424edb884SFrançois Tigeot } else { 257524edb884SFrançois Tigeot i915_gem_object_set_cache_level(obj, I915_CACHE_LLC); 257624edb884SFrançois Tigeot ret = i915_gem_obj_ggtt_pin(obj, 0, PIN_NONBLOCK); 257724edb884SFrançois Tigeot if (ret != 0) { 257824edb884SFrançois Tigeot drm_gem_object_unreference(&obj->base); 257924edb884SFrançois Tigeot DRM_ERROR("Failed to pin semaphore bo. Disabling semaphores\n"); 258024edb884SFrançois Tigeot i915.semaphores = 0; 258124edb884SFrançois Tigeot } else 258224edb884SFrançois Tigeot dev_priv->semaphore_obj = obj; 258324edb884SFrançois Tigeot } 258424edb884SFrançois Tigeot } 25852c9916cdSFrançois Tigeot 25862c9916cdSFrançois Tigeot ring->init_context = intel_rcs_ctx_init; 258724edb884SFrançois Tigeot ring->add_request = gen6_add_request; 258824edb884SFrançois Tigeot ring->flush = gen8_render_ring_flush; 258924edb884SFrançois Tigeot ring->irq_get = gen8_ring_get_irq; 259024edb884SFrançois Tigeot ring->irq_put = gen8_ring_put_irq; 259124edb884SFrançois Tigeot ring->irq_enable_mask = GT_RENDER_USER_INTERRUPT; 259224edb884SFrançois Tigeot ring->get_seqno = gen6_ring_get_seqno; 259324edb884SFrançois Tigeot ring->set_seqno = ring_set_seqno; 259424edb884SFrançois Tigeot if (i915_semaphore_is_enabled(dev)) { 259524edb884SFrançois Tigeot WARN_ON(!dev_priv->semaphore_obj); 259624edb884SFrançois Tigeot ring->semaphore.sync_to = gen8_ring_sync; 259724edb884SFrançois Tigeot ring->semaphore.signal = gen8_rcs_signal; 259824edb884SFrançois Tigeot GEN8_RING_SEMAPHORE_INIT; 259924edb884SFrançois Tigeot } 260024edb884SFrançois Tigeot } else if (INTEL_INFO(dev)->gen >= 6) { 2601e3adcf8fSFrançois Tigeot ring->add_request = gen6_add_request; 2602b5c29a34SFrançois Tigeot ring->flush = gen7_render_ring_flush; 2603b5c29a34SFrançois Tigeot if (INTEL_INFO(dev)->gen == 6) 2604e3adcf8fSFrançois Tigeot ring->flush = gen6_render_ring_flush; 2605686a02f1SFrançois Tigeot ring->irq_get = gen6_ring_get_irq; 2606686a02f1SFrançois Tigeot ring->irq_put = gen6_ring_put_irq; 26075d0b1887SFrançois Tigeot ring->irq_enable_mask = GT_RENDER_USER_INTERRUPT; 2608e3adcf8fSFrançois Tigeot ring->get_seqno = gen6_ring_get_seqno; 2609a2fdbec6SFrançois Tigeot ring->set_seqno = ring_set_seqno; 261024edb884SFrançois Tigeot if (i915_semaphore_is_enabled(dev)) { 2611ba55f2f5SFrançois Tigeot ring->semaphore.sync_to = gen6_ring_sync; 2612ba55f2f5SFrançois Tigeot ring->semaphore.signal = gen6_signal; 2613ba55f2f5SFrançois Tigeot /* 261424edb884SFrançois Tigeot * The current semaphore is only applied on pre-gen8 261524edb884SFrançois Tigeot * platform. And there is no VCS2 ring on the pre-gen8 261624edb884SFrançois Tigeot * platform. So the semaphore between RCS and VCS2 is 261724edb884SFrançois Tigeot * initialized as INVALID. Gen8 will initialize the 261824edb884SFrançois Tigeot * sema between VCS2 and RCS later. 2619ba55f2f5SFrançois Tigeot */ 2620ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[RCS] = MI_SEMAPHORE_SYNC_INVALID; 2621ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[VCS] = MI_SEMAPHORE_SYNC_RV; 2622ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[BCS] = MI_SEMAPHORE_SYNC_RB; 2623ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[VECS] = MI_SEMAPHORE_SYNC_RVE; 2624ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[VCS2] = MI_SEMAPHORE_SYNC_INVALID; 2625ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[RCS] = GEN6_NOSYNC; 2626ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[VCS] = GEN6_VRSYNC; 2627ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[BCS] = GEN6_BRSYNC; 2628ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[VECS] = GEN6_VERSYNC; 2629ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[VCS2] = GEN6_NOSYNC; 263024edb884SFrançois Tigeot } 2631e3adcf8fSFrançois Tigeot } else if (IS_GEN5(dev)) { 2632e3adcf8fSFrançois Tigeot ring->add_request = pc_render_add_request; 2633686a02f1SFrançois Tigeot ring->flush = gen4_render_ring_flush; 2634e3adcf8fSFrançois Tigeot ring->get_seqno = pc_render_get_seqno; 2635a2fdbec6SFrançois Tigeot ring->set_seqno = pc_render_set_seqno; 2636686a02f1SFrançois Tigeot ring->irq_get = gen5_ring_get_irq; 2637686a02f1SFrançois Tigeot ring->irq_put = gen5_ring_put_irq; 26385d0b1887SFrançois Tigeot ring->irq_enable_mask = GT_RENDER_USER_INTERRUPT | 26395d0b1887SFrançois Tigeot GT_RENDER_PIPECTL_NOTIFY_INTERRUPT; 2640686a02f1SFrançois Tigeot } else { 2641686a02f1SFrançois Tigeot ring->add_request = i9xx_add_request; 2642686a02f1SFrançois Tigeot if (INTEL_INFO(dev)->gen < 4) 2643686a02f1SFrançois Tigeot ring->flush = gen2_render_ring_flush; 2644686a02f1SFrançois Tigeot else 2645686a02f1SFrançois Tigeot ring->flush = gen4_render_ring_flush; 2646686a02f1SFrançois Tigeot ring->get_seqno = ring_get_seqno; 2647a2fdbec6SFrançois Tigeot ring->set_seqno = ring_set_seqno; 2648686a02f1SFrançois Tigeot if (IS_GEN2(dev)) { 2649686a02f1SFrançois Tigeot ring->irq_get = i8xx_ring_get_irq; 2650686a02f1SFrançois Tigeot ring->irq_put = i8xx_ring_put_irq; 2651686a02f1SFrançois Tigeot } else { 2652686a02f1SFrançois Tigeot ring->irq_get = i9xx_ring_get_irq; 2653686a02f1SFrançois Tigeot ring->irq_put = i9xx_ring_put_irq; 2654e3adcf8fSFrançois Tigeot } 2655686a02f1SFrançois Tigeot ring->irq_enable_mask = I915_USER_INTERRUPT; 2656686a02f1SFrançois Tigeot } 2657686a02f1SFrançois Tigeot ring->write_tail = ring_write_tail; 265824edb884SFrançois Tigeot 2659b5c29a34SFrançois Tigeot if (IS_HASWELL(dev)) 2660b5c29a34SFrançois Tigeot ring->dispatch_execbuffer = hsw_ring_dispatch_execbuffer; 26619edbd4a0SFrançois Tigeot else if (IS_GEN8(dev)) 26629edbd4a0SFrançois Tigeot ring->dispatch_execbuffer = gen8_ring_dispatch_execbuffer; 2663b5c29a34SFrançois Tigeot else if (INTEL_INFO(dev)->gen >= 6) 2664686a02f1SFrançois Tigeot ring->dispatch_execbuffer = gen6_ring_dispatch_execbuffer; 2665686a02f1SFrançois Tigeot else if (INTEL_INFO(dev)->gen >= 4) 2666686a02f1SFrançois Tigeot ring->dispatch_execbuffer = i965_dispatch_execbuffer; 2667686a02f1SFrançois Tigeot else if (IS_I830(dev) || IS_845G(dev)) 2668686a02f1SFrançois Tigeot ring->dispatch_execbuffer = i830_dispatch_execbuffer; 2669686a02f1SFrançois Tigeot else 2670686a02f1SFrançois Tigeot ring->dispatch_execbuffer = i915_dispatch_execbuffer; 26712c9916cdSFrançois Tigeot ring->init_hw = init_render_ring; 2672686a02f1SFrançois Tigeot ring->cleanup = render_ring_cleanup; 2673e3adcf8fSFrançois Tigeot 2674b5c29a34SFrançois Tigeot /* Workaround batchbuffer to combat CS tlb bug. */ 2675b5c29a34SFrançois Tigeot if (HAS_BROKEN_CS_TLB(dev)) { 267624edb884SFrançois Tigeot obj = i915_gem_alloc_object(dev, I830_WA_SIZE); 2677b5c29a34SFrançois Tigeot if (obj == NULL) { 2678b5c29a34SFrançois Tigeot DRM_ERROR("Failed to allocate batch bo\n"); 2679b5c29a34SFrançois Tigeot return -ENOMEM; 2680b5c29a34SFrançois Tigeot } 2681b5c29a34SFrançois Tigeot 2682ba55f2f5SFrançois Tigeot ret = i915_gem_obj_ggtt_pin(obj, 0, 0); 2683b5c29a34SFrançois Tigeot if (ret != 0) { 2684b5c29a34SFrançois Tigeot drm_gem_object_unreference(&obj->base); 2685b5c29a34SFrançois Tigeot DRM_ERROR("Failed to ping batch bo\n"); 2686b5c29a34SFrançois Tigeot return ret; 2687b5c29a34SFrançois Tigeot } 2688b5c29a34SFrançois Tigeot 26899edbd4a0SFrançois Tigeot ring->scratch.obj = obj; 26909edbd4a0SFrançois Tigeot ring->scratch.gtt_offset = i915_gem_obj_ggtt_offset(obj); 2691e3adcf8fSFrançois Tigeot } 2692e3adcf8fSFrançois Tigeot 26932c9916cdSFrançois Tigeot ret = intel_init_ring_buffer(dev, ring); 2694b5c29a34SFrançois Tigeot if (ret) 26952c9916cdSFrançois Tigeot return ret; 26962c9916cdSFrançois Tigeot 26972c9916cdSFrançois Tigeot if (INTEL_INFO(dev)->gen >= 5) { 26982c9916cdSFrançois Tigeot ret = intel_init_pipe_control(ring); 26992c9916cdSFrançois Tigeot if (ret) 27002c9916cdSFrançois Tigeot return ret; 2701b5c29a34SFrançois Tigeot } 2702b5c29a34SFrançois Tigeot 2703e3adcf8fSFrançois Tigeot return 0; 2704e3adcf8fSFrançois Tigeot } 2705e3adcf8fSFrançois Tigeot 2706e3adcf8fSFrançois Tigeot int intel_init_bsd_ring_buffer(struct drm_device *dev) 2707e3adcf8fSFrançois Tigeot { 2708ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 2709ba55f2f5SFrançois Tigeot struct intel_engine_cs *ring = &dev_priv->ring[VCS]; 2710e3adcf8fSFrançois Tigeot 2711686a02f1SFrançois Tigeot ring->name = "bsd ring"; 2712686a02f1SFrançois Tigeot ring->id = VCS; 2713686a02f1SFrançois Tigeot 2714686a02f1SFrançois Tigeot ring->write_tail = ring_write_tail; 27159edbd4a0SFrançois Tigeot if (INTEL_INFO(dev)->gen >= 6) { 2716686a02f1SFrançois Tigeot ring->mmio_base = GEN6_BSD_RING_BASE; 2717686a02f1SFrançois Tigeot /* gen6 bsd needs a special wa for tail updates */ 2718686a02f1SFrançois Tigeot if (IS_GEN6(dev)) 2719686a02f1SFrançois Tigeot ring->write_tail = gen6_bsd_ring_write_tail; 27205d0b1887SFrançois Tigeot ring->flush = gen6_bsd_ring_flush; 2721686a02f1SFrançois Tigeot ring->add_request = gen6_add_request; 2722686a02f1SFrançois Tigeot ring->get_seqno = gen6_ring_get_seqno; 2723a2fdbec6SFrançois Tigeot ring->set_seqno = ring_set_seqno; 27249edbd4a0SFrançois Tigeot if (INTEL_INFO(dev)->gen >= 8) { 27259edbd4a0SFrançois Tigeot ring->irq_enable_mask = 27269edbd4a0SFrançois Tigeot GT_RENDER_USER_INTERRUPT << GEN8_VCS1_IRQ_SHIFT; 27279edbd4a0SFrançois Tigeot ring->irq_get = gen8_ring_get_irq; 27289edbd4a0SFrançois Tigeot ring->irq_put = gen8_ring_put_irq; 27299edbd4a0SFrançois Tigeot ring->dispatch_execbuffer = 27309edbd4a0SFrançois Tigeot gen8_ring_dispatch_execbuffer; 273124edb884SFrançois Tigeot if (i915_semaphore_is_enabled(dev)) { 273224edb884SFrançois Tigeot ring->semaphore.sync_to = gen8_ring_sync; 273324edb884SFrançois Tigeot ring->semaphore.signal = gen8_xcs_signal; 273424edb884SFrançois Tigeot GEN8_RING_SEMAPHORE_INIT; 273524edb884SFrançois Tigeot } 27369edbd4a0SFrançois Tigeot } else { 27375d0b1887SFrançois Tigeot ring->irq_enable_mask = GT_BSD_USER_INTERRUPT; 2738686a02f1SFrançois Tigeot ring->irq_get = gen6_ring_get_irq; 2739686a02f1SFrançois Tigeot ring->irq_put = gen6_ring_put_irq; 27409edbd4a0SFrançois Tigeot ring->dispatch_execbuffer = 27419edbd4a0SFrançois Tigeot gen6_ring_dispatch_execbuffer; 274224edb884SFrançois Tigeot if (i915_semaphore_is_enabled(dev)) { 2743ba55f2f5SFrançois Tigeot ring->semaphore.sync_to = gen6_ring_sync; 2744ba55f2f5SFrançois Tigeot ring->semaphore.signal = gen6_signal; 2745ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[RCS] = MI_SEMAPHORE_SYNC_VR; 2746ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[VCS] = MI_SEMAPHORE_SYNC_INVALID; 2747ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[BCS] = MI_SEMAPHORE_SYNC_VB; 2748ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[VECS] = MI_SEMAPHORE_SYNC_VVE; 2749ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[VCS2] = MI_SEMAPHORE_SYNC_INVALID; 2750ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[RCS] = GEN6_RVSYNC; 2751ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[VCS] = GEN6_NOSYNC; 2752ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[BCS] = GEN6_BVSYNC; 2753ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[VECS] = GEN6_VEVSYNC; 2754ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[VCS2] = GEN6_NOSYNC; 275524edb884SFrançois Tigeot } 275624edb884SFrançois Tigeot } 2757686a02f1SFrançois Tigeot } else { 2758686a02f1SFrançois Tigeot ring->mmio_base = BSD_RING_BASE; 2759686a02f1SFrançois Tigeot ring->flush = bsd_ring_flush; 2760686a02f1SFrançois Tigeot ring->add_request = i9xx_add_request; 2761686a02f1SFrançois Tigeot ring->get_seqno = ring_get_seqno; 2762a2fdbec6SFrançois Tigeot ring->set_seqno = ring_set_seqno; 2763686a02f1SFrançois Tigeot if (IS_GEN5(dev)) { 27645d0b1887SFrançois Tigeot ring->irq_enable_mask = ILK_BSD_USER_INTERRUPT; 2765686a02f1SFrançois Tigeot ring->irq_get = gen5_ring_get_irq; 2766686a02f1SFrançois Tigeot ring->irq_put = gen5_ring_put_irq; 2767686a02f1SFrançois Tigeot } else { 2768686a02f1SFrançois Tigeot ring->irq_enable_mask = I915_BSD_USER_INTERRUPT; 2769686a02f1SFrançois Tigeot ring->irq_get = i9xx_ring_get_irq; 2770686a02f1SFrançois Tigeot ring->irq_put = i9xx_ring_put_irq; 2771686a02f1SFrançois Tigeot } 2772686a02f1SFrançois Tigeot ring->dispatch_execbuffer = i965_dispatch_execbuffer; 2773686a02f1SFrançois Tigeot } 27742c9916cdSFrançois Tigeot ring->init_hw = init_ring_common; 2775e3adcf8fSFrançois Tigeot 2776e3adcf8fSFrançois Tigeot return intel_init_ring_buffer(dev, ring); 2777e3adcf8fSFrançois Tigeot } 2778e3adcf8fSFrançois Tigeot 2779ba55f2f5SFrançois Tigeot /** 2780477eb7f9SFrançois Tigeot * Initialize the second BSD ring (eg. Broadwell GT3, Skylake GT3) 2781ba55f2f5SFrançois Tigeot */ 2782ba55f2f5SFrançois Tigeot int intel_init_bsd2_ring_buffer(struct drm_device *dev) 2783ba55f2f5SFrançois Tigeot { 2784ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 2785ba55f2f5SFrançois Tigeot struct intel_engine_cs *ring = &dev_priv->ring[VCS2]; 2786ba55f2f5SFrançois Tigeot 278724edb884SFrançois Tigeot ring->name = "bsd2 ring"; 2788ba55f2f5SFrançois Tigeot ring->id = VCS2; 2789ba55f2f5SFrançois Tigeot 2790ba55f2f5SFrançois Tigeot ring->write_tail = ring_write_tail; 2791ba55f2f5SFrançois Tigeot ring->mmio_base = GEN8_BSD2_RING_BASE; 2792ba55f2f5SFrançois Tigeot ring->flush = gen6_bsd_ring_flush; 2793ba55f2f5SFrançois Tigeot ring->add_request = gen6_add_request; 2794ba55f2f5SFrançois Tigeot ring->get_seqno = gen6_ring_get_seqno; 2795ba55f2f5SFrançois Tigeot ring->set_seqno = ring_set_seqno; 2796ba55f2f5SFrançois Tigeot ring->irq_enable_mask = 2797ba55f2f5SFrançois Tigeot GT_RENDER_USER_INTERRUPT << GEN8_VCS2_IRQ_SHIFT; 2798ba55f2f5SFrançois Tigeot ring->irq_get = gen8_ring_get_irq; 2799ba55f2f5SFrançois Tigeot ring->irq_put = gen8_ring_put_irq; 2800ba55f2f5SFrançois Tigeot ring->dispatch_execbuffer = 2801ba55f2f5SFrançois Tigeot gen8_ring_dispatch_execbuffer; 280224edb884SFrançois Tigeot if (i915_semaphore_is_enabled(dev)) { 280324edb884SFrançois Tigeot ring->semaphore.sync_to = gen8_ring_sync; 280424edb884SFrançois Tigeot ring->semaphore.signal = gen8_xcs_signal; 280524edb884SFrançois Tigeot GEN8_RING_SEMAPHORE_INIT; 280624edb884SFrançois Tigeot } 28072c9916cdSFrançois Tigeot ring->init_hw = init_ring_common; 2808ba55f2f5SFrançois Tigeot 2809ba55f2f5SFrançois Tigeot return intel_init_ring_buffer(dev, ring); 2810ba55f2f5SFrançois Tigeot } 2811ba55f2f5SFrançois Tigeot 2812e3adcf8fSFrançois Tigeot int intel_init_blt_ring_buffer(struct drm_device *dev) 2813e3adcf8fSFrançois Tigeot { 2814ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 2815ba55f2f5SFrançois Tigeot struct intel_engine_cs *ring = &dev_priv->ring[BCS]; 2816e3adcf8fSFrançois Tigeot 2817686a02f1SFrançois Tigeot ring->name = "blitter ring"; 2818686a02f1SFrançois Tigeot ring->id = BCS; 2819686a02f1SFrançois Tigeot 2820686a02f1SFrançois Tigeot ring->mmio_base = BLT_RING_BASE; 2821686a02f1SFrançois Tigeot ring->write_tail = ring_write_tail; 28225d0b1887SFrançois Tigeot ring->flush = gen6_ring_flush; 2823686a02f1SFrançois Tigeot ring->add_request = gen6_add_request; 2824686a02f1SFrançois Tigeot ring->get_seqno = gen6_ring_get_seqno; 2825a2fdbec6SFrançois Tigeot ring->set_seqno = ring_set_seqno; 28269edbd4a0SFrançois Tigeot if (INTEL_INFO(dev)->gen >= 8) { 28279edbd4a0SFrançois Tigeot ring->irq_enable_mask = 28289edbd4a0SFrançois Tigeot GT_RENDER_USER_INTERRUPT << GEN8_BCS_IRQ_SHIFT; 28299edbd4a0SFrançois Tigeot ring->irq_get = gen8_ring_get_irq; 28309edbd4a0SFrançois Tigeot ring->irq_put = gen8_ring_put_irq; 28319edbd4a0SFrançois Tigeot ring->dispatch_execbuffer = gen8_ring_dispatch_execbuffer; 283224edb884SFrançois Tigeot if (i915_semaphore_is_enabled(dev)) { 283324edb884SFrançois Tigeot ring->semaphore.sync_to = gen8_ring_sync; 283424edb884SFrançois Tigeot ring->semaphore.signal = gen8_xcs_signal; 283524edb884SFrançois Tigeot GEN8_RING_SEMAPHORE_INIT; 283624edb884SFrançois Tigeot } 28379edbd4a0SFrançois Tigeot } else { 28385d0b1887SFrançois Tigeot ring->irq_enable_mask = GT_BLT_USER_INTERRUPT; 2839686a02f1SFrançois Tigeot ring->irq_get = gen6_ring_get_irq; 2840686a02f1SFrançois Tigeot ring->irq_put = gen6_ring_put_irq; 2841686a02f1SFrançois Tigeot ring->dispatch_execbuffer = gen6_ring_dispatch_execbuffer; 284224edb884SFrançois Tigeot if (i915_semaphore_is_enabled(dev)) { 2843ba55f2f5SFrançois Tigeot ring->semaphore.signal = gen6_signal; 284424edb884SFrançois Tigeot ring->semaphore.sync_to = gen6_ring_sync; 2845ba55f2f5SFrançois Tigeot /* 284624edb884SFrançois Tigeot * The current semaphore is only applied on pre-gen8 284724edb884SFrançois Tigeot * platform. And there is no VCS2 ring on the pre-gen8 284824edb884SFrançois Tigeot * platform. So the semaphore between BCS and VCS2 is 284924edb884SFrançois Tigeot * initialized as INVALID. Gen8 will initialize the 285024edb884SFrançois Tigeot * sema between BCS and VCS2 later. 2851ba55f2f5SFrançois Tigeot */ 2852ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[RCS] = MI_SEMAPHORE_SYNC_BR; 2853ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[VCS] = MI_SEMAPHORE_SYNC_BV; 2854ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[BCS] = MI_SEMAPHORE_SYNC_INVALID; 2855ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[VECS] = MI_SEMAPHORE_SYNC_BVE; 2856ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[VCS2] = MI_SEMAPHORE_SYNC_INVALID; 2857ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[RCS] = GEN6_RBSYNC; 2858ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[VCS] = GEN6_VBSYNC; 2859ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[BCS] = GEN6_NOSYNC; 2860ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[VECS] = GEN6_VEBSYNC; 2861ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[VCS2] = GEN6_NOSYNC; 286224edb884SFrançois Tigeot } 286324edb884SFrançois Tigeot } 28642c9916cdSFrançois Tigeot ring->init_hw = init_ring_common; 28655d0b1887SFrançois Tigeot 28665d0b1887SFrançois Tigeot return intel_init_ring_buffer(dev, ring); 28675d0b1887SFrançois Tigeot } 28685d0b1887SFrançois Tigeot 28695d0b1887SFrançois Tigeot int intel_init_vebox_ring_buffer(struct drm_device *dev) 28705d0b1887SFrançois Tigeot { 2871ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 2872ba55f2f5SFrançois Tigeot struct intel_engine_cs *ring = &dev_priv->ring[VECS]; 28735d0b1887SFrançois Tigeot 28745d0b1887SFrançois Tigeot ring->name = "video enhancement ring"; 28755d0b1887SFrançois Tigeot ring->id = VECS; 28765d0b1887SFrançois Tigeot 28775d0b1887SFrançois Tigeot ring->mmio_base = VEBOX_RING_BASE; 28785d0b1887SFrançois Tigeot ring->write_tail = ring_write_tail; 28795d0b1887SFrançois Tigeot ring->flush = gen6_ring_flush; 28805d0b1887SFrançois Tigeot ring->add_request = gen6_add_request; 28815d0b1887SFrançois Tigeot ring->get_seqno = gen6_ring_get_seqno; 28825d0b1887SFrançois Tigeot ring->set_seqno = ring_set_seqno; 28839edbd4a0SFrançois Tigeot 28849edbd4a0SFrançois Tigeot if (INTEL_INFO(dev)->gen >= 8) { 28859edbd4a0SFrançois Tigeot ring->irq_enable_mask = 28869edbd4a0SFrançois Tigeot GT_RENDER_USER_INTERRUPT << GEN8_VECS_IRQ_SHIFT; 28879edbd4a0SFrançois Tigeot ring->irq_get = gen8_ring_get_irq; 28889edbd4a0SFrançois Tigeot ring->irq_put = gen8_ring_put_irq; 28899edbd4a0SFrançois Tigeot ring->dispatch_execbuffer = gen8_ring_dispatch_execbuffer; 289024edb884SFrançois Tigeot if (i915_semaphore_is_enabled(dev)) { 289124edb884SFrançois Tigeot ring->semaphore.sync_to = gen8_ring_sync; 289224edb884SFrançois Tigeot ring->semaphore.signal = gen8_xcs_signal; 289324edb884SFrançois Tigeot GEN8_RING_SEMAPHORE_INIT; 289424edb884SFrançois Tigeot } 28959edbd4a0SFrançois Tigeot } else { 28969edbd4a0SFrançois Tigeot ring->irq_enable_mask = PM_VEBOX_USER_INTERRUPT; 28975d0b1887SFrançois Tigeot ring->irq_get = hsw_vebox_get_irq; 28985d0b1887SFrançois Tigeot ring->irq_put = hsw_vebox_put_irq; 28995d0b1887SFrançois Tigeot ring->dispatch_execbuffer = gen6_ring_dispatch_execbuffer; 290024edb884SFrançois Tigeot if (i915_semaphore_is_enabled(dev)) { 2901ba55f2f5SFrançois Tigeot ring->semaphore.sync_to = gen6_ring_sync; 2902ba55f2f5SFrançois Tigeot ring->semaphore.signal = gen6_signal; 2903ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[RCS] = MI_SEMAPHORE_SYNC_VER; 2904ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[VCS] = MI_SEMAPHORE_SYNC_VEV; 2905ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[BCS] = MI_SEMAPHORE_SYNC_VEB; 2906ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[VECS] = MI_SEMAPHORE_SYNC_INVALID; 2907ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[VCS2] = MI_SEMAPHORE_SYNC_INVALID; 2908ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[RCS] = GEN6_RVESYNC; 2909ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[VCS] = GEN6_VVESYNC; 2910ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[BCS] = GEN6_BVESYNC; 2911ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[VECS] = GEN6_NOSYNC; 2912ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[VCS2] = GEN6_NOSYNC; 291324edb884SFrançois Tigeot } 291424edb884SFrançois Tigeot } 29152c9916cdSFrançois Tigeot ring->init_hw = init_ring_common; 2916e3adcf8fSFrançois Tigeot 2917e3adcf8fSFrançois Tigeot return intel_init_ring_buffer(dev, ring); 2918e3adcf8fSFrançois Tigeot } 2919b030f26bSFrançois Tigeot 2920b030f26bSFrançois Tigeot int 2921*a05eeebfSFrançois Tigeot intel_ring_flush_all_caches(struct drm_i915_gem_request *req) 2922b030f26bSFrançois Tigeot { 2923*a05eeebfSFrançois Tigeot struct intel_engine_cs *ring = req->ring; 2924b030f26bSFrançois Tigeot int ret; 2925b030f26bSFrançois Tigeot 2926b030f26bSFrançois Tigeot if (!ring->gpu_caches_dirty) 2927b030f26bSFrançois Tigeot return 0; 2928b030f26bSFrançois Tigeot 2929*a05eeebfSFrançois Tigeot ret = ring->flush(req, 0, I915_GEM_GPU_DOMAINS); 2930b030f26bSFrançois Tigeot if (ret) 2931b030f26bSFrançois Tigeot return ret; 2932b030f26bSFrançois Tigeot 2933*a05eeebfSFrançois Tigeot trace_i915_gem_ring_flush(req, 0, I915_GEM_GPU_DOMAINS); 2934a2fdbec6SFrançois Tigeot 2935b030f26bSFrançois Tigeot ring->gpu_caches_dirty = false; 2936b030f26bSFrançois Tigeot return 0; 2937b030f26bSFrançois Tigeot } 2938b030f26bSFrançois Tigeot 2939b030f26bSFrançois Tigeot int 2940*a05eeebfSFrançois Tigeot intel_ring_invalidate_all_caches(struct drm_i915_gem_request *req) 2941b030f26bSFrançois Tigeot { 2942*a05eeebfSFrançois Tigeot struct intel_engine_cs *ring = req->ring; 2943b030f26bSFrançois Tigeot uint32_t flush_domains; 2944b030f26bSFrançois Tigeot int ret; 2945b030f26bSFrançois Tigeot 2946b030f26bSFrançois Tigeot flush_domains = 0; 2947b030f26bSFrançois Tigeot if (ring->gpu_caches_dirty) 2948b030f26bSFrançois Tigeot flush_domains = I915_GEM_GPU_DOMAINS; 2949b030f26bSFrançois Tigeot 2950*a05eeebfSFrançois Tigeot ret = ring->flush(req, I915_GEM_GPU_DOMAINS, flush_domains); 2951b030f26bSFrançois Tigeot if (ret) 2952b030f26bSFrançois Tigeot return ret; 2953b030f26bSFrançois Tigeot 2954*a05eeebfSFrançois Tigeot trace_i915_gem_ring_flush(req, I915_GEM_GPU_DOMAINS, flush_domains); 2955a2fdbec6SFrançois Tigeot 2956b030f26bSFrançois Tigeot ring->gpu_caches_dirty = false; 2957b030f26bSFrançois Tigeot return 0; 2958b030f26bSFrançois Tigeot } 2959ba55f2f5SFrançois Tigeot 2960ba55f2f5SFrançois Tigeot void 2961ba55f2f5SFrançois Tigeot intel_stop_ring_buffer(struct intel_engine_cs *ring) 2962ba55f2f5SFrançois Tigeot { 2963ba55f2f5SFrançois Tigeot int ret; 2964ba55f2f5SFrançois Tigeot 2965ba55f2f5SFrançois Tigeot if (!intel_ring_initialized(ring)) 2966ba55f2f5SFrançois Tigeot return; 2967ba55f2f5SFrançois Tigeot 2968ba55f2f5SFrançois Tigeot ret = intel_ring_idle(ring); 2969ba55f2f5SFrançois Tigeot if (ret && !i915_reset_in_progress(&to_i915(ring->dev)->gpu_error)) 2970ba55f2f5SFrançois Tigeot DRM_ERROR("failed to quiesce %s whilst cleaning up: %d\n", 2971ba55f2f5SFrançois Tigeot ring->name, ret); 2972ba55f2f5SFrançois Tigeot 2973ba55f2f5SFrançois Tigeot stop_ring(ring); 2974ba55f2f5SFrançois Tigeot } 2975