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 84a05eeebfSFranç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 94a05eeebfSFranç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 { 98a05eeebfSFranç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 109a05eeebfSFranç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 121a05eeebfSFranç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 { 125a05eeebfSFranç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 168a05eeebfSFranç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 217a05eeebfSFrançois Tigeot intel_emit_post_sync_nonzero_flush(struct drm_i915_gem_request *req) 218e3adcf8fSFrançois Tigeot { 219a05eeebfSFranç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 223a05eeebfSFranç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 236a05eeebfSFranç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 252a05eeebfSFrançois Tigeot gen6_render_ring_flush(struct drm_i915_gem_request *req, 253e3adcf8fSFrançois Tigeot u32 invalidate_domains, u32 flush_domains) 254e3adcf8fSFrançois Tigeot { 255a05eeebfSFranç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 */ 261a05eeebfSFranç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 291a05eeebfSFranç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 305a05eeebfSFrançois Tigeot gen7_render_ring_cs_stall_wa(struct drm_i915_gem_request *req) 306b5c29a34SFrançois Tigeot { 307a05eeebfSFrançois Tigeot struct intel_engine_cs *ring = req->ring; 308b5c29a34SFrançois Tigeot int ret; 309b5c29a34SFrançois Tigeot 310a05eeebfSFranç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 325a05eeebfSFrançois Tigeot gen7_render_ring_flush(struct drm_i915_gem_request *req, 326b5c29a34SFrançois Tigeot u32 invalidate_domains, u32 flush_domains) 327b5c29a34SFrançois Tigeot { 328a05eeebfSFranç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. */ 371a05eeebfSFrançois Tigeot gen7_render_ring_cs_stall_wa(req); 372b5c29a34SFrançois Tigeot } 373b5c29a34SFrançois Tigeot 374a05eeebfSFranç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 388a05eeebfSFrançois Tigeot gen8_emit_pipe_control(struct drm_i915_gem_request *req, 38924edb884SFrançois Tigeot u32 flags, u32 scratch_addr) 39024edb884SFrançois Tigeot { 391a05eeebfSFrançois Tigeot struct intel_engine_cs *ring = req->ring; 39224edb884SFrançois Tigeot int ret; 39324edb884SFrançois Tigeot 394a05eeebfSFranç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 410a05eeebfSFranç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; 414a05eeebfSFranç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 */ 435a05eeebfSFranç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 443a05eeebfSFranç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 714a05eeebfSFrançois Tigeot static int intel_ring_workarounds_emit(struct drm_i915_gem_request *req) 7151b13d190SFrançois Tigeot { 7162c9916cdSFrançois Tigeot int ret, i; 717a05eeebfSFranç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 722*352ff8bdSFrançois Tigeot if (w->count == 0) 7232c9916cdSFrançois Tigeot return 0; 7241b13d190SFrançois Tigeot 7252c9916cdSFrançois Tigeot ring->gpu_caches_dirty = true; 726a05eeebfSFrançois Tigeot ret = intel_ring_flush_all_caches(req); 7271b13d190SFrançois Tigeot if (ret) 7281b13d190SFrançois Tigeot return ret; 7291b13d190SFrançois Tigeot 730a05eeebfSFranç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; 744a05eeebfSFranç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 753a05eeebfSFranç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 757a05eeebfSFrançois Tigeot ret = intel_ring_workarounds_emit(req); 7582c9916cdSFrançois Tigeot if (ret != 0) 7592c9916cdSFrançois Tigeot return ret; 7602c9916cdSFrançois Tigeot 761a05eeebfSFranç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 785a05eeebfSFranç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; \ 789a05eeebfSFranç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 805*352ff8bdSFrançois Tigeot static int gen8_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 810a05eeebfSFrançois Tigeot WA_SET_BIT_MASKED(INSTPM, INSTPM_FORCE_ORDERING); 811a05eeebfSFrançois Tigeot 812*352ff8bdSFrançois Tigeot /* WaDisableAsyncFlipPerfMode:bdw,chv */ 813a05eeebfSFrançois Tigeot WA_SET_BIT_MASKED(MI_MODE, ASYNC_FLIP_PERF_DISABLE); 814a05eeebfSFrançois Tigeot 815*352ff8bdSFrançois Tigeot /* WaDisablePartialInstShootdown:bdw,chv */ 8162c9916cdSFrançois Tigeot WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN, 817*352ff8bdSFrançois Tigeot PARTIAL_INSTRUCTION_SHOOTDOWN_DISABLE); 8181b13d190SFrançois Tigeot 8191b13d190SFrançois Tigeot /* Use Force Non-Coherent whenever executing a 3D context. This is a 8201b13d190SFrançois Tigeot * workaround for for a possible hang in the unlikely event a TLB 8211b13d190SFrançois Tigeot * invalidation occurs during a PSD flush. 8221b13d190SFrançois Tigeot */ 823*352ff8bdSFrançois Tigeot /* WaForceEnableNonCoherent:bdw,chv */ 824*352ff8bdSFrançois Tigeot /* WaHdcDisableFetchWhenMasked:bdw,chv */ 8252c9916cdSFrançois Tigeot WA_SET_BIT_MASKED(HDC_CHICKEN0, 8262c9916cdSFrançois Tigeot HDC_DONOT_FETCH_MEM_WHEN_MASKED | 827*352ff8bdSFrançois Tigeot HDC_FORCE_NON_COHERENT); 8282c9916cdSFrançois Tigeot 8292c9916cdSFrançois Tigeot /* From the Haswell PRM, Command Reference: Registers, CACHE_MODE_0: 8302c9916cdSFrançois Tigeot * "The Hierarchical Z RAW Stall Optimization allows non-overlapping 8312c9916cdSFrançois Tigeot * polygons in the same 8x4 pixel/sample area to be processed without 8322c9916cdSFrançois Tigeot * stalling waiting for the earlier ones to write to Hierarchical Z 8332c9916cdSFrançois Tigeot * buffer." 8342c9916cdSFrançois Tigeot * 835*352ff8bdSFrançois Tigeot * This optimization is off by default for BDW and CHV; turn it on. 8362c9916cdSFrançois Tigeot */ 8372c9916cdSFrançois Tigeot WA_CLR_BIT_MASKED(CACHE_MODE_0_GEN7, HIZ_RAW_STALL_OPT_DISABLE); 8381b13d190SFrançois Tigeot 839*352ff8bdSFrançois Tigeot /* Wa4x4STCOptimizationDisable:bdw,chv */ 840*352ff8bdSFrançois Tigeot WA_SET_BIT_MASKED(CACHE_MODE_1, GEN8_4x4_STC_OPTIMIZATION_DISABLE); 8411b13d190SFrançois Tigeot 8421b13d190SFrançois Tigeot /* 8431b13d190SFrançois Tigeot * BSpec recommends 8x4 when MSAA is used, 8441b13d190SFrançois Tigeot * however in practice 16x4 seems fastest. 8451b13d190SFrançois Tigeot * 8461b13d190SFrançois Tigeot * Note that PS/WM thread counts depend on the WIZ hashing 8471b13d190SFrançois Tigeot * disable bit, which we don't touch here, but it's good 8481b13d190SFrançois Tigeot * to keep in mind (see 3DSTATE_PS and 3DSTATE_WM). 8491b13d190SFrançois Tigeot */ 8502c9916cdSFrançois Tigeot WA_SET_FIELD_MASKED(GEN7_GT_MODE, 8512c9916cdSFrançois Tigeot GEN6_WIZ_HASHING_MASK, 8522c9916cdSFrançois Tigeot GEN6_WIZ_HASHING_16x4); 8531b13d190SFrançois Tigeot 8541b13d190SFrançois Tigeot return 0; 8551b13d190SFrançois Tigeot } 8561b13d190SFrançois Tigeot 857*352ff8bdSFrançois Tigeot static int bdw_init_workarounds(struct intel_engine_cs *ring) 8581b13d190SFrançois Tigeot { 859*352ff8bdSFrançois Tigeot int ret; 8601b13d190SFrançois Tigeot struct drm_device *dev = ring->dev; 8611b13d190SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 8621b13d190SFrançois Tigeot 863*352ff8bdSFrançois Tigeot ret = gen8_init_workarounds(ring); 864*352ff8bdSFrançois Tigeot if (ret) 865*352ff8bdSFrançois Tigeot return ret; 866a05eeebfSFrançois Tigeot 867*352ff8bdSFrançois Tigeot /* WaDisableThreadStallDopClockGating:bdw (pre-production) */ 868*352ff8bdSFrançois Tigeot WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN, STALL_DOP_GATING_DISABLE); 869a05eeebfSFrançois Tigeot 870*352ff8bdSFrançois Tigeot /* WaDisableDopClockGating:bdw */ 871*352ff8bdSFrançois Tigeot WA_SET_BIT_MASKED(GEN7_ROW_CHICKEN2, 872*352ff8bdSFrançois Tigeot DOP_CLOCK_GATING_DISABLE); 8731b13d190SFrançois Tigeot 874*352ff8bdSFrançois Tigeot WA_SET_BIT_MASKED(HALF_SLICE_CHICKEN3, 875*352ff8bdSFrançois Tigeot GEN8_SAMPLER_POWER_BYPASS_DIS); 876*352ff8bdSFrançois Tigeot 8772c9916cdSFrançois Tigeot WA_SET_BIT_MASKED(HDC_CHICKEN0, 878*352ff8bdSFrançois Tigeot /* WaForceContextSaveRestoreNonCoherent:bdw */ 879*352ff8bdSFrançois Tigeot HDC_FORCE_CONTEXT_SAVE_RESTORE_NON_COHERENT | 880*352ff8bdSFrançois Tigeot /* WaDisableFenceDestinationToSLM:bdw (pre-prod) */ 881*352ff8bdSFrançois Tigeot (IS_BDW_GT3(dev) ? HDC_FENCE_DEST_SLM_DISABLE : 0)); 8821b13d190SFrançois Tigeot 883*352ff8bdSFrançois Tigeot return 0; 884*352ff8bdSFrançois Tigeot } 8851b13d190SFrançois Tigeot 886*352ff8bdSFrançois Tigeot static int chv_init_workarounds(struct intel_engine_cs *ring) 887*352ff8bdSFrançois Tigeot { 888*352ff8bdSFrançois Tigeot int ret; 889*352ff8bdSFrançois Tigeot struct drm_device *dev = ring->dev; 890*352ff8bdSFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 891*352ff8bdSFrançois Tigeot 892*352ff8bdSFrançois Tigeot ret = gen8_init_workarounds(ring); 893*352ff8bdSFrançois Tigeot if (ret) 894*352ff8bdSFrançois Tigeot return ret; 895*352ff8bdSFrançois Tigeot 896*352ff8bdSFrançois Tigeot /* WaDisableThreadStallDopClockGating:chv */ 897*352ff8bdSFrançois Tigeot WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN, STALL_DOP_GATING_DISABLE); 8982c9916cdSFrançois Tigeot 8992c9916cdSFrançois Tigeot /* Improve HiZ throughput on CHV. */ 9002c9916cdSFrançois Tigeot WA_SET_BIT_MASKED(HIZ_CHICKEN, CHV_HZ_8X8_MODE_IN_1X); 9012c9916cdSFrançois Tigeot 9022c9916cdSFrançois Tigeot return 0; 9032c9916cdSFrançois Tigeot } 9042c9916cdSFrançois Tigeot 905477eb7f9SFrançois Tigeot static int gen9_init_workarounds(struct intel_engine_cs *ring) 906477eb7f9SFrançois Tigeot { 907477eb7f9SFrançois Tigeot struct drm_device *dev = ring->dev; 908477eb7f9SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 90919c468b4SFrançois Tigeot uint32_t tmp; 910477eb7f9SFrançois Tigeot 911*352ff8bdSFrançois Tigeot /* WaEnableLbsSlaRetryTimerDecrement:skl */ 912*352ff8bdSFrançois Tigeot I915_WRITE(BDW_SCRATCH1, I915_READ(BDW_SCRATCH1) | 913*352ff8bdSFrançois Tigeot GEN9_LBS_SLA_RETRY_TIMER_DECREMENT_ENABLE); 914*352ff8bdSFrançois Tigeot 915*352ff8bdSFrançois Tigeot /* WaDisableKillLogic:bxt,skl */ 916*352ff8bdSFrançois Tigeot I915_WRITE(GAM_ECOCHK, I915_READ(GAM_ECOCHK) | 917*352ff8bdSFrançois Tigeot ECOCHK_DIS_TLB); 918*352ff8bdSFrançois Tigeot 91919c468b4SFrançois Tigeot /* WaDisablePartialInstShootdown:skl,bxt */ 920477eb7f9SFrançois Tigeot WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN, 921477eb7f9SFrançois Tigeot PARTIAL_INSTRUCTION_SHOOTDOWN_DISABLE); 922477eb7f9SFrançois Tigeot 92319c468b4SFrançois Tigeot /* Syncing dependencies between camera and graphics:skl,bxt */ 924477eb7f9SFrançois Tigeot WA_SET_BIT_MASKED(HALF_SLICE_CHICKEN3, 925477eb7f9SFrançois Tigeot GEN9_DISABLE_OCL_OOB_SUPPRESS_LOGIC); 926477eb7f9SFrançois Tigeot 92719c468b4SFrançois Tigeot if ((IS_SKYLAKE(dev) && (INTEL_REVID(dev) == SKL_REVID_A0 || 92819c468b4SFrançois Tigeot INTEL_REVID(dev) == SKL_REVID_B0)) || 92919c468b4SFrançois Tigeot (IS_BROXTON(dev) && INTEL_REVID(dev) < BXT_REVID_B0)) { 93019c468b4SFrançois Tigeot /* WaDisableDgMirrorFixInHalfSliceChicken5:skl,bxt */ 931477eb7f9SFrançois Tigeot WA_CLR_BIT_MASKED(GEN9_HALF_SLICE_CHICKEN5, 932477eb7f9SFrançois Tigeot GEN9_DG_MIRROR_FIX_ENABLE); 933477eb7f9SFrançois Tigeot } 934477eb7f9SFrançois Tigeot 93519c468b4SFrançois Tigeot if ((IS_SKYLAKE(dev) && INTEL_REVID(dev) <= SKL_REVID_B0) || 93619c468b4SFrançois Tigeot (IS_BROXTON(dev) && INTEL_REVID(dev) < BXT_REVID_B0)) { 93719c468b4SFrançois Tigeot /* WaSetDisablePixMaskCammingAndRhwoInCommonSliceChicken:skl,bxt */ 938477eb7f9SFrançois Tigeot WA_SET_BIT_MASKED(GEN7_COMMON_SLICE_CHICKEN1, 939477eb7f9SFrançois Tigeot GEN9_RHWO_OPTIMIZATION_DISABLE); 940a05eeebfSFrançois Tigeot /* 941a05eeebfSFrançois Tigeot * WA also requires GEN9_SLICE_COMMON_ECO_CHICKEN0[14:14] to be set 942a05eeebfSFrançois Tigeot * but we do that in per ctx batchbuffer as there is an issue 943a05eeebfSFrançois Tigeot * with this register not getting restored on ctx restore 944a05eeebfSFrançois Tigeot */ 945477eb7f9SFrançois Tigeot } 946477eb7f9SFrançois Tigeot 94719c468b4SFrançois Tigeot if ((IS_SKYLAKE(dev) && INTEL_REVID(dev) >= SKL_REVID_C0) || 94819c468b4SFrançois Tigeot IS_BROXTON(dev)) { 94919c468b4SFrançois Tigeot /* WaEnableYV12BugFixInHalfSliceChicken7:skl,bxt */ 950477eb7f9SFrançois Tigeot WA_SET_BIT_MASKED(GEN9_HALF_SLICE_CHICKEN7, 951477eb7f9SFrançois Tigeot GEN9_ENABLE_YV12_BUGFIX); 952477eb7f9SFrançois Tigeot } 953477eb7f9SFrançois Tigeot 95419c468b4SFrançois Tigeot /* Wa4x4STCOptimizationDisable:skl,bxt */ 95519c468b4SFrançois Tigeot /* WaDisablePartialResolveInVc:skl,bxt */ 956*352ff8bdSFrançois Tigeot WA_SET_BIT_MASKED(CACHE_MODE_1, (GEN8_4x4_STC_OPTIMIZATION_DISABLE | 957*352ff8bdSFrançois Tigeot GEN9_PARTIAL_RESOLVE_IN_VC_DISABLE)); 958477eb7f9SFrançois Tigeot 95919c468b4SFrançois Tigeot /* WaCcsTlbPrefetchDisable:skl,bxt */ 960477eb7f9SFrançois Tigeot WA_CLR_BIT_MASKED(GEN9_HALF_SLICE_CHICKEN5, 961477eb7f9SFrançois Tigeot GEN9_CCS_TLB_PREFETCH_ENABLE); 962477eb7f9SFrançois Tigeot 96319c468b4SFrançois Tigeot /* WaDisableMaskBasedCammingInRCC:skl,bxt */ 96419c468b4SFrançois Tigeot if ((IS_SKYLAKE(dev) && INTEL_REVID(dev) == SKL_REVID_C0) || 96519c468b4SFrançois Tigeot (IS_BROXTON(dev) && INTEL_REVID(dev) < BXT_REVID_B0)) 96619c468b4SFrançois Tigeot WA_SET_BIT_MASKED(SLICE_ECO_CHICKEN0, 96719c468b4SFrançois Tigeot PIXEL_MASK_CAMMING_DISABLE); 96819c468b4SFrançois Tigeot 96919c468b4SFrançois Tigeot /* WaForceContextSaveRestoreNonCoherent:skl,bxt */ 97019c468b4SFrançois Tigeot tmp = HDC_FORCE_CONTEXT_SAVE_RESTORE_NON_COHERENT; 97119c468b4SFrançois Tigeot if ((IS_SKYLAKE(dev) && INTEL_REVID(dev) == SKL_REVID_F0) || 97219c468b4SFrançois Tigeot (IS_BROXTON(dev) && INTEL_REVID(dev) >= BXT_REVID_B0)) 97319c468b4SFrançois Tigeot tmp |= HDC_FORCE_CSR_NON_COHERENT_OVR_DISABLE; 97419c468b4SFrançois Tigeot WA_SET_BIT_MASKED(HDC_CHICKEN0, tmp); 97519c468b4SFrançois Tigeot 976*352ff8bdSFrançois Tigeot /* WaDisableSamplerPowerBypassForSOPingPong:skl,bxt */ 977*352ff8bdSFrançois Tigeot if (IS_SKYLAKE(dev) || 978*352ff8bdSFrançois Tigeot (IS_BROXTON(dev) && INTEL_REVID(dev) <= BXT_REVID_B0)) { 979*352ff8bdSFrançois Tigeot WA_SET_BIT_MASKED(HALF_SLICE_CHICKEN3, 980*352ff8bdSFrançois Tigeot GEN8_SAMPLER_POWER_BYPASS_DIS); 981*352ff8bdSFrançois Tigeot } 982*352ff8bdSFrançois Tigeot 983*352ff8bdSFrançois Tigeot /* WaDisableSTUnitPowerOptimization:skl,bxt */ 984*352ff8bdSFrançois Tigeot WA_SET_BIT_MASKED(HALF_SLICE_CHICKEN2, GEN8_ST_PO_DISABLE); 985*352ff8bdSFrançois Tigeot 986477eb7f9SFrançois Tigeot return 0; 987477eb7f9SFrançois Tigeot } 988477eb7f9SFrançois Tigeot 989477eb7f9SFrançois Tigeot static int skl_tune_iz_hashing(struct intel_engine_cs *ring) 990477eb7f9SFrançois Tigeot { 991477eb7f9SFrançois Tigeot struct drm_device *dev = ring->dev; 992477eb7f9SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 993477eb7f9SFrançois Tigeot u8 vals[3] = { 0, 0, 0 }; 994477eb7f9SFrançois Tigeot unsigned int i; 995477eb7f9SFrançois Tigeot 996477eb7f9SFrançois Tigeot for (i = 0; i < 3; i++) { 997477eb7f9SFrançois Tigeot u8 ss; 998477eb7f9SFrançois Tigeot 999477eb7f9SFrançois Tigeot /* 1000477eb7f9SFrançois Tigeot * Only consider slices where one, and only one, subslice has 7 1001477eb7f9SFrançois Tigeot * EUs 1002477eb7f9SFrançois Tigeot */ 1003477eb7f9SFrançois Tigeot if (hweight8(dev_priv->info.subslice_7eu[i]) != 1) 1004477eb7f9SFrançois Tigeot continue; 1005477eb7f9SFrançois Tigeot 1006477eb7f9SFrançois Tigeot /* 1007477eb7f9SFrançois Tigeot * subslice_7eu[i] != 0 (because of the check above) and 1008477eb7f9SFrançois Tigeot * ss_max == 4 (maximum number of subslices possible per slice) 1009477eb7f9SFrançois Tigeot * 1010477eb7f9SFrançois Tigeot * -> 0 <= ss <= 3; 1011477eb7f9SFrançois Tigeot */ 1012477eb7f9SFrançois Tigeot ss = ffs(dev_priv->info.subslice_7eu[i]) - 1; 1013477eb7f9SFrançois Tigeot vals[i] = 3 - ss; 1014477eb7f9SFrançois Tigeot } 1015477eb7f9SFrançois Tigeot 1016477eb7f9SFrançois Tigeot if (vals[0] == 0 && vals[1] == 0 && vals[2] == 0) 1017477eb7f9SFrançois Tigeot return 0; 1018477eb7f9SFrançois Tigeot 1019477eb7f9SFrançois Tigeot /* Tune IZ hashing. See intel_device_info_runtime_init() */ 1020477eb7f9SFrançois Tigeot WA_SET_FIELD_MASKED(GEN7_GT_MODE, 1021477eb7f9SFrançois Tigeot GEN9_IZ_HASHING_MASK(2) | 1022477eb7f9SFrançois Tigeot GEN9_IZ_HASHING_MASK(1) | 1023477eb7f9SFrançois Tigeot GEN9_IZ_HASHING_MASK(0), 1024477eb7f9SFrançois Tigeot GEN9_IZ_HASHING(2, vals[2]) | 1025477eb7f9SFrançois Tigeot GEN9_IZ_HASHING(1, vals[1]) | 1026477eb7f9SFrançois Tigeot GEN9_IZ_HASHING(0, vals[0])); 1027477eb7f9SFrançois Tigeot 1028477eb7f9SFrançois Tigeot return 0; 1029477eb7f9SFrançois Tigeot } 1030477eb7f9SFrançois Tigeot 1031477eb7f9SFrançois Tigeot static int skl_init_workarounds(struct intel_engine_cs *ring) 1032477eb7f9SFrançois Tigeot { 1033*352ff8bdSFrançois Tigeot int ret; 1034477eb7f9SFrançois Tigeot struct drm_device *dev = ring->dev; 1035477eb7f9SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 1036477eb7f9SFrançois Tigeot 1037*352ff8bdSFrançois Tigeot ret = gen9_init_workarounds(ring); 1038*352ff8bdSFrançois Tigeot if (ret) 1039*352ff8bdSFrançois Tigeot return ret; 1040*352ff8bdSFrançois Tigeot 1041*352ff8bdSFrançois Tigeot if (INTEL_REVID(dev) <= SKL_REVID_D0) { 1042*352ff8bdSFrançois Tigeot /* WaDisableHDCInvalidation:skl */ 1043*352ff8bdSFrançois Tigeot I915_WRITE(GAM_ECOCHK, I915_READ(GAM_ECOCHK) | 1044*352ff8bdSFrançois Tigeot BDW_DISABLE_HDC_INVALIDATION); 1045*352ff8bdSFrançois Tigeot 1046*352ff8bdSFrançois Tigeot /* WaDisableChickenBitTSGBarrierAckForFFSliceCS:skl */ 1047*352ff8bdSFrançois Tigeot I915_WRITE(FF_SLICE_CS_CHICKEN2, 1048*352ff8bdSFrançois Tigeot _MASKED_BIT_ENABLE(GEN9_TSG_BARRIER_ACK_DISABLE)); 1049*352ff8bdSFrançois Tigeot } 1050*352ff8bdSFrançois Tigeot 1051*352ff8bdSFrançois Tigeot /* GEN8_L3SQCREG4 has a dependency with WA batch so any new changes 1052*352ff8bdSFrançois Tigeot * involving this register should also be added to WA batch as required. 1053*352ff8bdSFrançois Tigeot */ 1054*352ff8bdSFrançois Tigeot if (INTEL_REVID(dev) <= SKL_REVID_E0) 1055*352ff8bdSFrançois Tigeot /* WaDisableLSQCROPERFforOCL:skl */ 1056*352ff8bdSFrançois Tigeot I915_WRITE(GEN8_L3SQCREG4, I915_READ(GEN8_L3SQCREG4) | 1057*352ff8bdSFrançois Tigeot GEN8_LQSC_RO_PERF_DIS); 1058*352ff8bdSFrançois Tigeot 1059*352ff8bdSFrançois Tigeot /* WaEnableGapsTsvCreditFix:skl */ 1060*352ff8bdSFrançois Tigeot if (IS_SKYLAKE(dev) && (INTEL_REVID(dev) >= SKL_REVID_C0)) { 1061*352ff8bdSFrançois Tigeot I915_WRITE(GEN8_GARBCNTL, (I915_READ(GEN8_GARBCNTL) | 1062*352ff8bdSFrançois Tigeot GEN9_GAPS_TSV_CREDIT_DISABLE)); 1063*352ff8bdSFrançois Tigeot } 1064477eb7f9SFrançois Tigeot 1065477eb7f9SFrançois Tigeot /* WaDisablePowerCompilerClockGating:skl */ 1066477eb7f9SFrançois Tigeot if (INTEL_REVID(dev) == SKL_REVID_B0) 1067477eb7f9SFrançois Tigeot WA_SET_BIT_MASKED(HIZ_CHICKEN, 1068477eb7f9SFrançois Tigeot BDW_HIZ_POWER_COMPILER_CLOCK_GATING_DISABLE); 1069477eb7f9SFrançois Tigeot 107019c468b4SFrançois Tigeot if (INTEL_REVID(dev) <= SKL_REVID_D0) { 107119c468b4SFrançois Tigeot /* 107219c468b4SFrançois Tigeot *Use Force Non-Coherent whenever executing a 3D context. This 107319c468b4SFrançois Tigeot * is a workaround for a possible hang in the unlikely event 107419c468b4SFrançois Tigeot * a TLB invalidation occurs during a PSD flush. 107519c468b4SFrançois Tigeot */ 107619c468b4SFrançois Tigeot /* WaForceEnableNonCoherent:skl */ 107719c468b4SFrançois Tigeot WA_SET_BIT_MASKED(HDC_CHICKEN0, 107819c468b4SFrançois Tigeot HDC_FORCE_NON_COHERENT); 107919c468b4SFrançois Tigeot } 108019c468b4SFrançois Tigeot 1081a05eeebfSFrançois Tigeot if (INTEL_REVID(dev) == SKL_REVID_C0 || 1082a05eeebfSFrançois Tigeot INTEL_REVID(dev) == SKL_REVID_D0) 1083a05eeebfSFrançois Tigeot /* WaBarrierPerformanceFixDisable:skl */ 1084a05eeebfSFrançois Tigeot WA_SET_BIT_MASKED(HDC_CHICKEN0, 1085a05eeebfSFrançois Tigeot HDC_FENCE_DEST_SLM_DISABLE | 1086a05eeebfSFrançois Tigeot HDC_BARRIER_PERFORMANCE_DISABLE); 1087a05eeebfSFrançois Tigeot 1088a05eeebfSFrançois Tigeot /* WaDisableSbeCacheDispatchPortSharing:skl */ 1089a05eeebfSFrançois Tigeot if (INTEL_REVID(dev) <= SKL_REVID_F0) { 1090a05eeebfSFrançois Tigeot WA_SET_BIT_MASKED( 1091a05eeebfSFrançois Tigeot GEN7_HALF_SLICE_CHICKEN1, 1092a05eeebfSFrançois Tigeot GEN7_SBE_SS_CACHE_DISPATCH_PORT_SHARING_DISABLE); 1093a05eeebfSFrançois Tigeot } 1094a05eeebfSFrançois Tigeot 1095477eb7f9SFrançois Tigeot return skl_tune_iz_hashing(ring); 1096477eb7f9SFrançois Tigeot } 1097477eb7f9SFrançois Tigeot 109819c468b4SFrançois Tigeot static int bxt_init_workarounds(struct intel_engine_cs *ring) 109919c468b4SFrançois Tigeot { 1100*352ff8bdSFrançois Tigeot int ret; 110119c468b4SFrançois Tigeot struct drm_device *dev = ring->dev; 110219c468b4SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 110319c468b4SFrançois Tigeot 1104*352ff8bdSFrançois Tigeot ret = gen9_init_workarounds(ring); 1105*352ff8bdSFrançois Tigeot if (ret) 1106*352ff8bdSFrançois Tigeot return ret; 1107*352ff8bdSFrançois Tigeot 1108*352ff8bdSFrançois Tigeot /* WaStoreMultiplePTEenable:bxt */ 1109*352ff8bdSFrançois Tigeot /* This is a requirement according to Hardware specification */ 1110*352ff8bdSFrançois Tigeot if (INTEL_REVID(dev) == BXT_REVID_A0) 1111*352ff8bdSFrançois Tigeot I915_WRITE(TILECTL, I915_READ(TILECTL) | TILECTL_TLBPF); 1112*352ff8bdSFrançois Tigeot 1113*352ff8bdSFrançois Tigeot /* WaSetClckGatingDisableMedia:bxt */ 1114*352ff8bdSFrançois Tigeot if (INTEL_REVID(dev) == BXT_REVID_A0) { 1115*352ff8bdSFrançois Tigeot I915_WRITE(GEN7_MISCCPCTL, (I915_READ(GEN7_MISCCPCTL) & 1116*352ff8bdSFrançois Tigeot ~GEN8_DOP_CLOCK_GATE_MEDIA_ENABLE)); 1117*352ff8bdSFrançois Tigeot } 111819c468b4SFrançois Tigeot 111919c468b4SFrançois Tigeot /* WaDisableThreadStallDopClockGating:bxt */ 112019c468b4SFrançois Tigeot WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN, 112119c468b4SFrançois Tigeot STALL_DOP_GATING_DISABLE); 112219c468b4SFrançois Tigeot 112319c468b4SFrançois Tigeot /* WaDisableSbeCacheDispatchPortSharing:bxt */ 112419c468b4SFrançois Tigeot if (INTEL_REVID(dev) <= BXT_REVID_B0) { 112519c468b4SFrançois Tigeot WA_SET_BIT_MASKED( 112619c468b4SFrançois Tigeot GEN7_HALF_SLICE_CHICKEN1, 112719c468b4SFrançois Tigeot GEN7_SBE_SS_CACHE_DISPATCH_PORT_SHARING_DISABLE); 112819c468b4SFrançois Tigeot } 112919c468b4SFrançois Tigeot 113019c468b4SFrançois Tigeot return 0; 113119c468b4SFrançois Tigeot } 113219c468b4SFrançois Tigeot 11332c9916cdSFrançois Tigeot int init_workarounds_ring(struct intel_engine_cs *ring) 11342c9916cdSFrançois Tigeot { 11352c9916cdSFrançois Tigeot struct drm_device *dev = ring->dev; 11362c9916cdSFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 11372c9916cdSFrançois Tigeot 11382c9916cdSFrançois Tigeot WARN_ON(ring->id != RCS); 11392c9916cdSFrançois Tigeot 11402c9916cdSFrançois Tigeot dev_priv->workarounds.count = 0; 11412c9916cdSFrançois Tigeot 11422c9916cdSFrançois Tigeot if (IS_BROADWELL(dev)) 11432c9916cdSFrançois Tigeot return bdw_init_workarounds(ring); 11442c9916cdSFrançois Tigeot 11452c9916cdSFrançois Tigeot if (IS_CHERRYVIEW(dev)) 11462c9916cdSFrançois Tigeot return chv_init_workarounds(ring); 11471b13d190SFrançois Tigeot 1148477eb7f9SFrançois Tigeot if (IS_SKYLAKE(dev)) 1149477eb7f9SFrançois Tigeot return skl_init_workarounds(ring); 115019c468b4SFrançois Tigeot 115119c468b4SFrançois Tigeot if (IS_BROXTON(dev)) 115219c468b4SFrançois Tigeot return bxt_init_workarounds(ring); 1153477eb7f9SFrançois Tigeot 11541b13d190SFrançois Tigeot return 0; 11551b13d190SFrançois Tigeot } 11561b13d190SFrançois Tigeot 1157ba55f2f5SFrançois Tigeot static int init_render_ring(struct intel_engine_cs *ring) 1158e3adcf8fSFrançois Tigeot { 1159e3adcf8fSFrançois Tigeot struct drm_device *dev = ring->dev; 1160e3adcf8fSFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 1161e3adcf8fSFrançois Tigeot int ret = init_ring_common(ring); 116224edb884SFrançois Tigeot if (ret) 116324edb884SFrançois Tigeot return ret; 1164e3adcf8fSFrançois Tigeot 1165ba55f2f5SFrançois Tigeot /* WaTimedSingleVertexDispatch:cl,bw,ctg,elk,ilk,snb */ 1166ba55f2f5SFrançois Tigeot if (INTEL_INFO(dev)->gen >= 4 && INTEL_INFO(dev)->gen < 7) 1167f4e1c372SFrançois Tigeot I915_WRITE(MI_MODE, _MASKED_BIT_ENABLE(VS_TIMER_DISPATCH)); 1168f4e1c372SFrançois Tigeot 1169f4e1c372SFrançois Tigeot /* We need to disable the AsyncFlip performance optimisations in order 1170f4e1c372SFrançois Tigeot * to use MI_WAIT_FOR_EVENT within the CS. It should already be 1171f4e1c372SFrançois Tigeot * programmed to '1' on all products. 11725d0b1887SFrançois Tigeot * 1173a05eeebfSFrançois Tigeot * WaDisableAsyncFlipPerfMode:snb,ivb,hsw,vlv 1174f4e1c372SFrançois Tigeot */ 1175a05eeebfSFrançois Tigeot if (INTEL_INFO(dev)->gen >= 6 && INTEL_INFO(dev)->gen < 8) 1176f4e1c372SFrançois Tigeot I915_WRITE(MI_MODE, _MASKED_BIT_ENABLE(ASYNC_FLIP_PERF_DISABLE)); 1177f4e1c372SFrançois Tigeot 1178f4e1c372SFrançois Tigeot /* Required for the hardware to program scanline values for waiting */ 1179ba55f2f5SFrançois Tigeot /* WaEnableFlushTlbInvalidationMode:snb */ 1180f4e1c372SFrançois Tigeot if (INTEL_INFO(dev)->gen == 6) 1181f4e1c372SFrançois Tigeot I915_WRITE(GFX_MODE, 1182ba55f2f5SFrançois Tigeot _MASKED_BIT_ENABLE(GFX_TLB_INVALIDATE_EXPLICIT)); 1183f4e1c372SFrançois Tigeot 1184ba55f2f5SFrançois Tigeot /* WaBCSVCSTlbInvalidationMode:ivb,vlv,hsw */ 1185e3adcf8fSFrançois Tigeot if (IS_GEN7(dev)) 1186e3adcf8fSFrançois Tigeot I915_WRITE(GFX_MODE_GEN7, 1187ba55f2f5SFrançois Tigeot _MASKED_BIT_ENABLE(GFX_TLB_INVALIDATE_EXPLICIT) | 1188f4e1c372SFrançois Tigeot _MASKED_BIT_ENABLE(GFX_REPLAY_MODE)); 1189e3adcf8fSFrançois Tigeot 1190e3adcf8fSFrançois Tigeot if (IS_GEN6(dev)) { 1191e3adcf8fSFrançois Tigeot /* From the Sandybridge PRM, volume 1 part 3, page 24: 1192e3adcf8fSFrançois Tigeot * "If this bit is set, STCunit will have LRA as replacement 1193e3adcf8fSFrançois Tigeot * policy. [...] This bit must be reset. LRA replacement 1194e3adcf8fSFrançois Tigeot * policy is not supported." 1195e3adcf8fSFrançois Tigeot */ 1196e3adcf8fSFrançois Tigeot I915_WRITE(CACHE_MODE_0, 1197f4e1c372SFrançois Tigeot _MASKED_BIT_DISABLE(CM0_STC_EVICT_DISABLE_LRA_SNB)); 1198e3adcf8fSFrançois Tigeot } 1199e3adcf8fSFrançois Tigeot 1200a05eeebfSFrançois Tigeot if (INTEL_INFO(dev)->gen >= 6 && INTEL_INFO(dev)->gen < 8) 1201f4e1c372SFrançois Tigeot I915_WRITE(INSTPM, _MASKED_BIT_ENABLE(INSTPM_FORCE_ORDERING)); 1202f4e1c372SFrançois Tigeot 12039edbd4a0SFrançois Tigeot if (HAS_L3_DPF(dev)) 12049edbd4a0SFrançois Tigeot I915_WRITE_IMR(ring, ~GT_PARITY_ERROR(dev)); 1205e3adcf8fSFrançois Tigeot 12062c9916cdSFrançois Tigeot return init_workarounds_ring(ring); 1207e3adcf8fSFrançois Tigeot } 1208e3adcf8fSFrançois Tigeot 1209ba55f2f5SFrançois Tigeot static void render_ring_cleanup(struct intel_engine_cs *ring) 1210e3adcf8fSFrançois Tigeot { 1211b5c29a34SFrançois Tigeot struct drm_device *dev = ring->dev; 121224edb884SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 121324edb884SFrançois Tigeot 121424edb884SFrançois Tigeot if (dev_priv->semaphore_obj) { 121524edb884SFrançois Tigeot i915_gem_object_ggtt_unpin(dev_priv->semaphore_obj); 121624edb884SFrançois Tigeot drm_gem_object_unreference(&dev_priv->semaphore_obj->base); 121724edb884SFrançois Tigeot dev_priv->semaphore_obj = NULL; 121824edb884SFrançois Tigeot } 1219b5c29a34SFrançois Tigeot 12201b13d190SFrançois Tigeot intel_fini_pipe_control(ring); 1221e3adcf8fSFrançois Tigeot } 1222e3adcf8fSFrançois Tigeot 1223a05eeebfSFrançois Tigeot static int gen8_rcs_signal(struct drm_i915_gem_request *signaller_req, 122424edb884SFrançois Tigeot unsigned int num_dwords) 122524edb884SFrançois Tigeot { 122624edb884SFrançois Tigeot #define MBOX_UPDATE_DWORDS 8 1227a05eeebfSFrançois Tigeot struct intel_engine_cs *signaller = signaller_req->ring; 122824edb884SFrançois Tigeot struct drm_device *dev = signaller->dev; 122924edb884SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 123024edb884SFrançois Tigeot struct intel_engine_cs *waiter; 123124edb884SFrançois Tigeot int i, ret, num_rings; 123224edb884SFrançois Tigeot 123324edb884SFrançois Tigeot num_rings = hweight32(INTEL_INFO(dev)->ring_mask); 123424edb884SFrançois Tigeot num_dwords += (num_rings-1) * MBOX_UPDATE_DWORDS; 123524edb884SFrançois Tigeot #undef MBOX_UPDATE_DWORDS 123624edb884SFrançois Tigeot 1237a05eeebfSFrançois Tigeot ret = intel_ring_begin(signaller_req, num_dwords); 123824edb884SFrançois Tigeot if (ret) 123924edb884SFrançois Tigeot return ret; 124024edb884SFrançois Tigeot 124124edb884SFrançois Tigeot for_each_ring(waiter, dev_priv, i) { 12422c9916cdSFrançois Tigeot u32 seqno; 124324edb884SFrançois Tigeot u64 gtt_offset = signaller->semaphore.signal_ggtt[i]; 124424edb884SFrançois Tigeot if (gtt_offset == MI_SEMAPHORE_SYNC_INVALID) 124524edb884SFrançois Tigeot continue; 124624edb884SFrançois Tigeot 1247a05eeebfSFrançois Tigeot seqno = i915_gem_request_get_seqno(signaller_req); 124824edb884SFrançois Tigeot intel_ring_emit(signaller, GFX_OP_PIPE_CONTROL(6)); 124924edb884SFrançois Tigeot intel_ring_emit(signaller, PIPE_CONTROL_GLOBAL_GTT_IVB | 125024edb884SFrançois Tigeot PIPE_CONTROL_QW_WRITE | 125124edb884SFrançois Tigeot PIPE_CONTROL_FLUSH_ENABLE); 125224edb884SFrançois Tigeot intel_ring_emit(signaller, lower_32_bits(gtt_offset)); 125324edb884SFrançois Tigeot intel_ring_emit(signaller, upper_32_bits(gtt_offset)); 12542c9916cdSFrançois Tigeot intel_ring_emit(signaller, seqno); 125524edb884SFrançois Tigeot intel_ring_emit(signaller, 0); 125624edb884SFrançois Tigeot intel_ring_emit(signaller, MI_SEMAPHORE_SIGNAL | 125724edb884SFrançois Tigeot MI_SEMAPHORE_TARGET(waiter->id)); 125824edb884SFrançois Tigeot intel_ring_emit(signaller, 0); 125924edb884SFrançois Tigeot } 126024edb884SFrançois Tigeot 126124edb884SFrançois Tigeot return 0; 126224edb884SFrançois Tigeot } 126324edb884SFrançois Tigeot 1264a05eeebfSFrançois Tigeot static int gen8_xcs_signal(struct drm_i915_gem_request *signaller_req, 126524edb884SFrançois Tigeot unsigned int num_dwords) 126624edb884SFrançois Tigeot { 126724edb884SFrançois Tigeot #define MBOX_UPDATE_DWORDS 6 1268a05eeebfSFrançois Tigeot struct intel_engine_cs *signaller = signaller_req->ring; 126924edb884SFrançois Tigeot struct drm_device *dev = signaller->dev; 127024edb884SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 127124edb884SFrançois Tigeot struct intel_engine_cs *waiter; 127224edb884SFrançois Tigeot int i, ret, num_rings; 127324edb884SFrançois Tigeot 127424edb884SFrançois Tigeot num_rings = hweight32(INTEL_INFO(dev)->ring_mask); 127524edb884SFrançois Tigeot num_dwords += (num_rings-1) * MBOX_UPDATE_DWORDS; 127624edb884SFrançois Tigeot #undef MBOX_UPDATE_DWORDS 127724edb884SFrançois Tigeot 1278a05eeebfSFrançois Tigeot ret = intel_ring_begin(signaller_req, num_dwords); 127924edb884SFrançois Tigeot if (ret) 128024edb884SFrançois Tigeot return ret; 128124edb884SFrançois Tigeot 128224edb884SFrançois Tigeot for_each_ring(waiter, dev_priv, i) { 12832c9916cdSFrançois Tigeot u32 seqno; 128424edb884SFrançois Tigeot u64 gtt_offset = signaller->semaphore.signal_ggtt[i]; 128524edb884SFrançois Tigeot if (gtt_offset == MI_SEMAPHORE_SYNC_INVALID) 128624edb884SFrançois Tigeot continue; 128724edb884SFrançois Tigeot 1288a05eeebfSFrançois Tigeot seqno = i915_gem_request_get_seqno(signaller_req); 128924edb884SFrançois Tigeot intel_ring_emit(signaller, (MI_FLUSH_DW + 1) | 129024edb884SFrançois Tigeot MI_FLUSH_DW_OP_STOREDW); 129124edb884SFrançois Tigeot intel_ring_emit(signaller, lower_32_bits(gtt_offset) | 129224edb884SFrançois Tigeot MI_FLUSH_DW_USE_GTT); 129324edb884SFrançois Tigeot intel_ring_emit(signaller, upper_32_bits(gtt_offset)); 12942c9916cdSFrançois Tigeot intel_ring_emit(signaller, seqno); 129524edb884SFrançois Tigeot intel_ring_emit(signaller, MI_SEMAPHORE_SIGNAL | 129624edb884SFrançois Tigeot MI_SEMAPHORE_TARGET(waiter->id)); 129724edb884SFrançois Tigeot intel_ring_emit(signaller, 0); 129824edb884SFrançois Tigeot } 129924edb884SFrançois Tigeot 130024edb884SFrançois Tigeot return 0; 130124edb884SFrançois Tigeot } 130224edb884SFrançois Tigeot 1303a05eeebfSFrançois Tigeot static int gen6_signal(struct drm_i915_gem_request *signaller_req, 1304ba55f2f5SFrançois Tigeot unsigned int num_dwords) 1305e3adcf8fSFrançois Tigeot { 1306a05eeebfSFrançois Tigeot struct intel_engine_cs *signaller = signaller_req->ring; 1307ba55f2f5SFrançois Tigeot struct drm_device *dev = signaller->dev; 1308ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 1309ba55f2f5SFrançois Tigeot struct intel_engine_cs *useless; 131024edb884SFrançois Tigeot int i, ret, num_rings; 1311ba55f2f5SFrançois Tigeot 131224edb884SFrançois Tigeot #define MBOX_UPDATE_DWORDS 3 131324edb884SFrançois Tigeot num_rings = hweight32(INTEL_INFO(dev)->ring_mask); 131424edb884SFrançois Tigeot num_dwords += round_up((num_rings-1) * MBOX_UPDATE_DWORDS, 2); 131524edb884SFrançois Tigeot #undef MBOX_UPDATE_DWORDS 1316ba55f2f5SFrançois Tigeot 1317a05eeebfSFrançois Tigeot ret = intel_ring_begin(signaller_req, num_dwords); 1318ba55f2f5SFrançois Tigeot if (ret) 1319ba55f2f5SFrançois Tigeot return ret; 1320ba55f2f5SFrançois Tigeot 1321ba55f2f5SFrançois Tigeot for_each_ring(useless, dev_priv, i) { 1322ba55f2f5SFrançois Tigeot u32 mbox_reg = signaller->semaphore.mbox.signal[i]; 1323ba55f2f5SFrançois Tigeot if (mbox_reg != GEN6_NOSYNC) { 1324a05eeebfSFrançois Tigeot u32 seqno = i915_gem_request_get_seqno(signaller_req); 1325ba55f2f5SFrançois Tigeot intel_ring_emit(signaller, MI_LOAD_REGISTER_IMM(1)); 1326ba55f2f5SFrançois Tigeot intel_ring_emit(signaller, mbox_reg); 13272c9916cdSFrançois Tigeot intel_ring_emit(signaller, seqno); 1328ba55f2f5SFrançois Tigeot } 1329ba55f2f5SFrançois Tigeot } 1330ba55f2f5SFrançois Tigeot 133124edb884SFrançois Tigeot /* If num_dwords was rounded, make sure the tail pointer is correct */ 133224edb884SFrançois Tigeot if (num_rings % 2 == 0) 133324edb884SFrançois Tigeot intel_ring_emit(signaller, MI_NOOP); 133424edb884SFrançois Tigeot 1335ba55f2f5SFrançois Tigeot return 0; 1336e3adcf8fSFrançois Tigeot } 1337e3adcf8fSFrançois Tigeot 1338e3adcf8fSFrançois Tigeot /** 1339e3adcf8fSFrançois Tigeot * gen6_add_request - Update the semaphore mailbox registers 1340e3adcf8fSFrançois Tigeot * 1341a05eeebfSFrançois Tigeot * @request - request to write to the ring 1342e3adcf8fSFrançois Tigeot * 1343e3adcf8fSFrançois Tigeot * Update the mailbox registers in the *other* rings with the current seqno. 1344e3adcf8fSFrançois Tigeot * This acts like a signal in the canonical semaphore. 1345e3adcf8fSFrançois Tigeot */ 1346e3adcf8fSFrançois Tigeot static int 1347a05eeebfSFrançois Tigeot gen6_add_request(struct drm_i915_gem_request *req) 1348e3adcf8fSFrançois Tigeot { 1349a05eeebfSFrançois Tigeot struct intel_engine_cs *ring = req->ring; 1350ba55f2f5SFrançois Tigeot int ret; 1351e3adcf8fSFrançois Tigeot 135224edb884SFrançois Tigeot if (ring->semaphore.signal) 1353a05eeebfSFrançois Tigeot ret = ring->semaphore.signal(req, 4); 135424edb884SFrançois Tigeot else 1355a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 4); 135624edb884SFrançois Tigeot 13579edbd4a0SFrançois Tigeot if (ret) 13589edbd4a0SFrançois Tigeot return ret; 13599edbd4a0SFrançois Tigeot 1360e3adcf8fSFrançois Tigeot intel_ring_emit(ring, MI_STORE_DWORD_INDEX); 1361e3adcf8fSFrançois Tigeot intel_ring_emit(ring, I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT); 1362a05eeebfSFrançois Tigeot intel_ring_emit(ring, i915_gem_request_get_seqno(req)); 1363e3adcf8fSFrançois Tigeot intel_ring_emit(ring, MI_USER_INTERRUPT); 13649edbd4a0SFrançois Tigeot __intel_ring_advance(ring); 1365e3adcf8fSFrançois Tigeot 1366e3adcf8fSFrançois Tigeot return 0; 1367e3adcf8fSFrançois Tigeot } 1368e3adcf8fSFrançois Tigeot 1369a2fdbec6SFrançois Tigeot static inline bool i915_gem_has_seqno_wrapped(struct drm_device *dev, 1370a2fdbec6SFrançois Tigeot u32 seqno) 1371a2fdbec6SFrançois Tigeot { 1372a2fdbec6SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 1373a2fdbec6SFrançois Tigeot return dev_priv->last_seqno < seqno; 1374a2fdbec6SFrançois Tigeot } 1375a2fdbec6SFrançois Tigeot 1376e3adcf8fSFrançois Tigeot /** 1377e3adcf8fSFrançois Tigeot * intel_ring_sync - sync the waiter to the signaller on seqno 1378e3adcf8fSFrançois Tigeot * 1379e3adcf8fSFrançois Tigeot * @waiter - ring that is waiting 1380e3adcf8fSFrançois Tigeot * @signaller - ring which has, or will signal 1381e3adcf8fSFrançois Tigeot * @seqno - seqno which the waiter will block on 1382e3adcf8fSFrançois Tigeot */ 138324edb884SFrançois Tigeot 138424edb884SFrançois Tigeot static int 1385a05eeebfSFrançois Tigeot gen8_ring_sync(struct drm_i915_gem_request *waiter_req, 138624edb884SFrançois Tigeot struct intel_engine_cs *signaller, 138724edb884SFrançois Tigeot u32 seqno) 138824edb884SFrançois Tigeot { 1389a05eeebfSFrançois Tigeot struct intel_engine_cs *waiter = waiter_req->ring; 139024edb884SFrançois Tigeot struct drm_i915_private *dev_priv = waiter->dev->dev_private; 139124edb884SFrançois Tigeot int ret; 139224edb884SFrançois Tigeot 1393a05eeebfSFrançois Tigeot ret = intel_ring_begin(waiter_req, 4); 139424edb884SFrançois Tigeot if (ret) 139524edb884SFrançois Tigeot return ret; 139624edb884SFrançois Tigeot 139724edb884SFrançois Tigeot intel_ring_emit(waiter, MI_SEMAPHORE_WAIT | 139824edb884SFrançois Tigeot MI_SEMAPHORE_GLOBAL_GTT | 139924edb884SFrançois Tigeot MI_SEMAPHORE_POLL | 140024edb884SFrançois Tigeot MI_SEMAPHORE_SAD_GTE_SDD); 140124edb884SFrançois Tigeot intel_ring_emit(waiter, seqno); 140224edb884SFrançois Tigeot intel_ring_emit(waiter, 140324edb884SFrançois Tigeot lower_32_bits(GEN8_WAIT_OFFSET(waiter, signaller->id))); 140424edb884SFrançois Tigeot intel_ring_emit(waiter, 140524edb884SFrançois Tigeot upper_32_bits(GEN8_WAIT_OFFSET(waiter, signaller->id))); 140624edb884SFrançois Tigeot intel_ring_advance(waiter); 140724edb884SFrançois Tigeot return 0; 140824edb884SFrançois Tigeot } 140924edb884SFrançois Tigeot 1410e3adcf8fSFrançois Tigeot static int 1411a05eeebfSFrançois Tigeot gen6_ring_sync(struct drm_i915_gem_request *waiter_req, 1412ba55f2f5SFrançois Tigeot struct intel_engine_cs *signaller, 1413e3adcf8fSFrançois Tigeot u32 seqno) 1414e3adcf8fSFrançois Tigeot { 1415a05eeebfSFrançois Tigeot struct intel_engine_cs *waiter = waiter_req->ring; 1416e3adcf8fSFrançois Tigeot u32 dw1 = MI_SEMAPHORE_MBOX | 1417e3adcf8fSFrançois Tigeot MI_SEMAPHORE_COMPARE | 1418e3adcf8fSFrançois Tigeot MI_SEMAPHORE_REGISTER; 1419ba55f2f5SFrançois Tigeot u32 wait_mbox = signaller->semaphore.mbox.wait[waiter->id]; 1420ba55f2f5SFrançois Tigeot int ret; 1421e3adcf8fSFrançois Tigeot 1422686a02f1SFrançois Tigeot /* Throughout all of the GEM code, seqno passed implies our current 1423686a02f1SFrançois Tigeot * seqno is >= the last seqno executed. However for hardware the 1424686a02f1SFrançois Tigeot * comparison is strictly greater than. 1425686a02f1SFrançois Tigeot */ 1426686a02f1SFrançois Tigeot seqno -= 1; 1427686a02f1SFrançois Tigeot 1428ba55f2f5SFrançois Tigeot WARN_ON(wait_mbox == MI_SEMAPHORE_SYNC_INVALID); 1429686a02f1SFrançois Tigeot 1430a05eeebfSFrançois Tigeot ret = intel_ring_begin(waiter_req, 4); 1431e3adcf8fSFrançois Tigeot if (ret) 1432e3adcf8fSFrançois Tigeot return ret; 1433e3adcf8fSFrançois Tigeot 1434a2fdbec6SFrançois Tigeot /* If seqno wrap happened, omit the wait with no-ops */ 1435a2fdbec6SFrançois Tigeot if (likely(!i915_gem_has_seqno_wrapped(waiter->dev, seqno))) { 1436ba55f2f5SFrançois Tigeot intel_ring_emit(waiter, dw1 | wait_mbox); 1437e3adcf8fSFrançois Tigeot intel_ring_emit(waiter, seqno); 1438e3adcf8fSFrançois Tigeot intel_ring_emit(waiter, 0); 1439e3adcf8fSFrançois Tigeot intel_ring_emit(waiter, MI_NOOP); 1440a2fdbec6SFrançois Tigeot } else { 1441a2fdbec6SFrançois Tigeot intel_ring_emit(waiter, MI_NOOP); 1442a2fdbec6SFrançois Tigeot intel_ring_emit(waiter, MI_NOOP); 1443a2fdbec6SFrançois Tigeot intel_ring_emit(waiter, MI_NOOP); 1444a2fdbec6SFrançois Tigeot intel_ring_emit(waiter, MI_NOOP); 1445a2fdbec6SFrançois Tigeot } 1446e3adcf8fSFrançois Tigeot intel_ring_advance(waiter); 1447e3adcf8fSFrançois Tigeot 1448e3adcf8fSFrançois Tigeot return 0; 1449e3adcf8fSFrançois Tigeot } 1450e3adcf8fSFrançois Tigeot 1451e3adcf8fSFrançois Tigeot #define PIPE_CONTROL_FLUSH(ring__, addr__) \ 1452e3adcf8fSFrançois Tigeot do { \ 1453e3adcf8fSFrançois Tigeot intel_ring_emit(ring__, GFX_OP_PIPE_CONTROL(4) | PIPE_CONTROL_QW_WRITE | \ 1454e3adcf8fSFrançois Tigeot PIPE_CONTROL_DEPTH_STALL); \ 1455e3adcf8fSFrançois Tigeot intel_ring_emit(ring__, (addr__) | PIPE_CONTROL_GLOBAL_GTT); \ 1456e3adcf8fSFrançois Tigeot intel_ring_emit(ring__, 0); \ 1457e3adcf8fSFrançois Tigeot intel_ring_emit(ring__, 0); \ 1458e3adcf8fSFrançois Tigeot } while (0) 1459e3adcf8fSFrançois Tigeot 1460e3adcf8fSFrançois Tigeot static int 1461a05eeebfSFrançois Tigeot pc_render_add_request(struct drm_i915_gem_request *req) 1462e3adcf8fSFrançois Tigeot { 1463a05eeebfSFrançois Tigeot struct intel_engine_cs *ring = req->ring; 1464ba55f2f5SFrançois Tigeot u32 scratch_addr = ring->scratch.gtt_offset + 2 * CACHELINE_BYTES; 1465e3adcf8fSFrançois Tigeot int ret; 1466e3adcf8fSFrançois Tigeot 1467e3adcf8fSFrançois Tigeot /* For Ironlake, MI_USER_INTERRUPT was deprecated and apparently 1468e3adcf8fSFrançois Tigeot * incoherent with writes to memory, i.e. completely fubar, 1469e3adcf8fSFrançois Tigeot * so we need to use PIPE_NOTIFY instead. 1470e3adcf8fSFrançois Tigeot * 1471e3adcf8fSFrançois Tigeot * However, we also need to workaround the qword write 1472e3adcf8fSFrançois Tigeot * incoherence by flushing the 6 PIPE_NOTIFY buffers out to 1473e3adcf8fSFrançois Tigeot * memory before requesting an interrupt. 1474e3adcf8fSFrançois Tigeot */ 1475a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 32); 1476e3adcf8fSFrançois Tigeot if (ret) 1477e3adcf8fSFrançois Tigeot return ret; 1478e3adcf8fSFrançois Tigeot 1479e3adcf8fSFrançois Tigeot intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(4) | PIPE_CONTROL_QW_WRITE | 1480e3adcf8fSFrançois Tigeot PIPE_CONTROL_WRITE_FLUSH | 1481e3adcf8fSFrançois Tigeot PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE); 14829edbd4a0SFrançois Tigeot intel_ring_emit(ring, ring->scratch.gtt_offset | PIPE_CONTROL_GLOBAL_GTT); 1483a05eeebfSFrançois Tigeot intel_ring_emit(ring, i915_gem_request_get_seqno(req)); 1484e3adcf8fSFrançois Tigeot intel_ring_emit(ring, 0); 1485e3adcf8fSFrançois Tigeot PIPE_CONTROL_FLUSH(ring, scratch_addr); 1486ba55f2f5SFrançois Tigeot scratch_addr += 2 * CACHELINE_BYTES; /* write to separate cachelines */ 1487e3adcf8fSFrançois Tigeot PIPE_CONTROL_FLUSH(ring, scratch_addr); 1488ba55f2f5SFrançois Tigeot scratch_addr += 2 * CACHELINE_BYTES; 1489e3adcf8fSFrançois Tigeot PIPE_CONTROL_FLUSH(ring, scratch_addr); 1490ba55f2f5SFrançois Tigeot scratch_addr += 2 * CACHELINE_BYTES; 1491e3adcf8fSFrançois Tigeot PIPE_CONTROL_FLUSH(ring, scratch_addr); 1492ba55f2f5SFrançois Tigeot scratch_addr += 2 * CACHELINE_BYTES; 1493e3adcf8fSFrançois Tigeot PIPE_CONTROL_FLUSH(ring, scratch_addr); 1494ba55f2f5SFrançois Tigeot scratch_addr += 2 * CACHELINE_BYTES; 1495e3adcf8fSFrançois Tigeot PIPE_CONTROL_FLUSH(ring, scratch_addr); 1496b5c29a34SFrançois Tigeot 1497e3adcf8fSFrançois Tigeot intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(4) | PIPE_CONTROL_QW_WRITE | 1498e3adcf8fSFrançois Tigeot PIPE_CONTROL_WRITE_FLUSH | 1499e3adcf8fSFrançois Tigeot PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE | 1500e3adcf8fSFrançois Tigeot PIPE_CONTROL_NOTIFY); 15019edbd4a0SFrançois Tigeot intel_ring_emit(ring, ring->scratch.gtt_offset | PIPE_CONTROL_GLOBAL_GTT); 1502a05eeebfSFrançois Tigeot intel_ring_emit(ring, i915_gem_request_get_seqno(req)); 1503e3adcf8fSFrançois Tigeot intel_ring_emit(ring, 0); 15049edbd4a0SFrançois Tigeot __intel_ring_advance(ring); 1505e3adcf8fSFrançois Tigeot 1506e3adcf8fSFrançois Tigeot return 0; 1507e3adcf8fSFrançois Tigeot } 1508e3adcf8fSFrançois Tigeot 1509e3adcf8fSFrançois Tigeot static u32 1510ba55f2f5SFrançois Tigeot gen6_ring_get_seqno(struct intel_engine_cs *ring, bool lazy_coherency) 1511e3adcf8fSFrançois Tigeot { 1512e3adcf8fSFrançois Tigeot /* Workaround to force correct ordering between irq and seqno writes on 1513e3adcf8fSFrançois Tigeot * ivb (and maybe also on snb) by reading from a CS register (like 1514e3adcf8fSFrançois Tigeot * ACTHD) before reading the status page. */ 1515ba55f2f5SFrançois Tigeot if (!lazy_coherency) { 1516ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = ring->dev->dev_private; 1517ba55f2f5SFrançois Tigeot POSTING_READ(RING_ACTHD(ring->mmio_base)); 1518ba55f2f5SFrançois Tigeot } 1519ba55f2f5SFrançois Tigeot 1520e3adcf8fSFrançois Tigeot return intel_read_status_page(ring, I915_GEM_HWS_INDEX); 1521e3adcf8fSFrançois Tigeot } 1522e3adcf8fSFrançois Tigeot 1523b030f26bSFrançois Tigeot static u32 1524ba55f2f5SFrançois Tigeot ring_get_seqno(struct intel_engine_cs *ring, bool lazy_coherency) 1525e3adcf8fSFrançois Tigeot { 1526e3adcf8fSFrançois Tigeot return intel_read_status_page(ring, I915_GEM_HWS_INDEX); 1527e3adcf8fSFrançois Tigeot } 1528e3adcf8fSFrançois Tigeot 1529a2fdbec6SFrançois Tigeot static void 1530ba55f2f5SFrançois Tigeot ring_set_seqno(struct intel_engine_cs *ring, u32 seqno) 1531a2fdbec6SFrançois Tigeot { 1532a2fdbec6SFrançois Tigeot intel_write_status_page(ring, I915_GEM_HWS_INDEX, seqno); 1533a2fdbec6SFrançois Tigeot } 1534a2fdbec6SFrançois Tigeot 1535b030f26bSFrançois Tigeot static u32 1536ba55f2f5SFrançois Tigeot pc_render_get_seqno(struct intel_engine_cs *ring, bool lazy_coherency) 1537e3adcf8fSFrançois Tigeot { 15389edbd4a0SFrançois Tigeot return ring->scratch.cpu_page[0]; 1539e3adcf8fSFrançois Tigeot } 1540e3adcf8fSFrançois Tigeot 1541a2fdbec6SFrançois Tigeot static void 1542ba55f2f5SFrançois Tigeot pc_render_set_seqno(struct intel_engine_cs *ring, u32 seqno) 1543a2fdbec6SFrançois Tigeot { 15449edbd4a0SFrançois Tigeot ring->scratch.cpu_page[0] = seqno; 1545a2fdbec6SFrançois Tigeot } 1546a2fdbec6SFrançois Tigeot 1547e3adcf8fSFrançois Tigeot static bool 1548ba55f2f5SFrançois Tigeot gen5_ring_get_irq(struct intel_engine_cs *ring) 1549e3adcf8fSFrançois Tigeot { 1550e3adcf8fSFrançois Tigeot struct drm_device *dev = ring->dev; 1551ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 15525e269720SFrançois Tigeot unsigned long flags; 1553e3adcf8fSFrançois Tigeot 15542c9916cdSFrançois Tigeot if (WARN_ON(!intel_irqs_enabled(dev_priv))) 1555e3adcf8fSFrançois Tigeot return false; 1556e3adcf8fSFrançois Tigeot 15575e269720SFrançois Tigeot spin_lock_irqsave(&dev_priv->irq_lock, flags); 15589edbd4a0SFrançois Tigeot if (ring->irq_refcount++ == 0) 155924edb884SFrançois Tigeot gen5_enable_gt_irq(dev_priv, ring->irq_enable_mask); 15605e269720SFrançois Tigeot spin_unlock_irqrestore(&dev_priv->irq_lock, flags); 1561e3adcf8fSFrançois Tigeot 1562e3adcf8fSFrançois Tigeot return true; 1563e3adcf8fSFrançois Tigeot } 1564e3adcf8fSFrançois Tigeot 1565e3adcf8fSFrançois Tigeot static void 1566ba55f2f5SFrançois Tigeot gen5_ring_put_irq(struct intel_engine_cs *ring) 1567e3adcf8fSFrançois Tigeot { 1568e3adcf8fSFrançois Tigeot struct drm_device *dev = ring->dev; 1569ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 15705e269720SFrançois Tigeot unsigned long flags; 1571e3adcf8fSFrançois Tigeot 15725e269720SFrançois Tigeot spin_lock_irqsave(&dev_priv->irq_lock, flags); 15739edbd4a0SFrançois Tigeot if (--ring->irq_refcount == 0) 157424edb884SFrançois Tigeot gen5_disable_gt_irq(dev_priv, ring->irq_enable_mask); 15755e269720SFrançois Tigeot spin_unlock_irqrestore(&dev_priv->irq_lock, flags); 1576686a02f1SFrançois Tigeot } 1577686a02f1SFrançois Tigeot 1578686a02f1SFrançois Tigeot static bool 1579ba55f2f5SFrançois Tigeot i9xx_ring_get_irq(struct intel_engine_cs *ring) 1580686a02f1SFrançois Tigeot { 1581686a02f1SFrançois Tigeot struct drm_device *dev = ring->dev; 1582ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 15835e269720SFrançois Tigeot unsigned long flags; 1584686a02f1SFrançois Tigeot 15852c9916cdSFrançois Tigeot if (!intel_irqs_enabled(dev_priv)) 1586686a02f1SFrançois Tigeot return false; 1587686a02f1SFrançois Tigeot 15885e269720SFrançois Tigeot spin_lock_irqsave(&dev_priv->irq_lock, flags); 15899edbd4a0SFrançois Tigeot if (ring->irq_refcount++ == 0) { 1590686a02f1SFrançois Tigeot dev_priv->irq_mask &= ~ring->irq_enable_mask; 1591686a02f1SFrançois Tigeot I915_WRITE(IMR, dev_priv->irq_mask); 1592686a02f1SFrançois Tigeot POSTING_READ(IMR); 1593686a02f1SFrançois Tigeot } 15945e269720SFrançois Tigeot spin_unlock_irqrestore(&dev_priv->irq_lock, flags); 1595686a02f1SFrançois Tigeot 1596686a02f1SFrançois Tigeot return true; 1597686a02f1SFrançois Tigeot } 1598686a02f1SFrançois Tigeot 1599686a02f1SFrançois Tigeot static void 1600ba55f2f5SFrançois Tigeot i9xx_ring_put_irq(struct intel_engine_cs *ring) 1601686a02f1SFrançois Tigeot { 1602686a02f1SFrançois Tigeot struct drm_device *dev = ring->dev; 1603ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 16045e269720SFrançois Tigeot unsigned long flags; 1605686a02f1SFrançois Tigeot 16065e269720SFrançois Tigeot spin_lock_irqsave(&dev_priv->irq_lock, flags); 16079edbd4a0SFrançois Tigeot if (--ring->irq_refcount == 0) { 1608686a02f1SFrançois Tigeot dev_priv->irq_mask |= ring->irq_enable_mask; 1609686a02f1SFrançois Tigeot I915_WRITE(IMR, dev_priv->irq_mask); 1610686a02f1SFrançois Tigeot POSTING_READ(IMR); 1611686a02f1SFrançois Tigeot } 16125e269720SFrançois Tigeot spin_unlock_irqrestore(&dev_priv->irq_lock, flags); 1613686a02f1SFrançois Tigeot } 1614686a02f1SFrançois Tigeot 1615686a02f1SFrançois Tigeot static bool 1616ba55f2f5SFrançois Tigeot i8xx_ring_get_irq(struct intel_engine_cs *ring) 1617686a02f1SFrançois Tigeot { 1618686a02f1SFrançois Tigeot struct drm_device *dev = ring->dev; 1619ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 16205e269720SFrançois Tigeot unsigned long flags; 1621686a02f1SFrançois Tigeot 16222c9916cdSFrançois Tigeot if (!intel_irqs_enabled(dev_priv)) 1623686a02f1SFrançois Tigeot return false; 1624686a02f1SFrançois Tigeot 16255e269720SFrançois Tigeot spin_lock_irqsave(&dev_priv->irq_lock, flags); 16269edbd4a0SFrançois Tigeot if (ring->irq_refcount++ == 0) { 1627686a02f1SFrançois Tigeot dev_priv->irq_mask &= ~ring->irq_enable_mask; 1628686a02f1SFrançois Tigeot I915_WRITE16(IMR, dev_priv->irq_mask); 1629686a02f1SFrançois Tigeot POSTING_READ16(IMR); 1630686a02f1SFrançois Tigeot } 16315e269720SFrançois Tigeot spin_unlock_irqrestore(&dev_priv->irq_lock, flags); 1632686a02f1SFrançois Tigeot 1633686a02f1SFrançois Tigeot return true; 1634686a02f1SFrançois Tigeot } 1635686a02f1SFrançois Tigeot 1636686a02f1SFrançois Tigeot static void 1637ba55f2f5SFrançois Tigeot i8xx_ring_put_irq(struct intel_engine_cs *ring) 1638686a02f1SFrançois Tigeot { 1639686a02f1SFrançois Tigeot struct drm_device *dev = ring->dev; 1640ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 16415e269720SFrançois Tigeot unsigned long flags; 1642686a02f1SFrançois Tigeot 16435e269720SFrançois Tigeot spin_lock_irqsave(&dev_priv->irq_lock, flags); 16449edbd4a0SFrançois Tigeot if (--ring->irq_refcount == 0) { 1645686a02f1SFrançois Tigeot dev_priv->irq_mask |= ring->irq_enable_mask; 1646686a02f1SFrançois Tigeot I915_WRITE16(IMR, dev_priv->irq_mask); 1647686a02f1SFrançois Tigeot POSTING_READ16(IMR); 1648e3adcf8fSFrançois Tigeot } 16495e269720SFrançois Tigeot spin_unlock_irqrestore(&dev_priv->irq_lock, flags); 1650e3adcf8fSFrançois Tigeot } 1651e3adcf8fSFrançois Tigeot 1652e3adcf8fSFrançois Tigeot static int 1653a05eeebfSFrançois Tigeot bsd_ring_flush(struct drm_i915_gem_request *req, 1654b5c29a34SFrançois Tigeot u32 invalidate_domains, 1655b5c29a34SFrançois Tigeot u32 flush_domains) 1656e3adcf8fSFrançois Tigeot { 1657a05eeebfSFrançois Tigeot struct intel_engine_cs *ring = req->ring; 1658e3adcf8fSFrançois Tigeot int ret; 1659e3adcf8fSFrançois Tigeot 1660a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 2); 1661e3adcf8fSFrançois Tigeot if (ret) 1662e3adcf8fSFrançois Tigeot return ret; 1663e3adcf8fSFrançois Tigeot 1664e3adcf8fSFrançois Tigeot intel_ring_emit(ring, MI_FLUSH); 1665e3adcf8fSFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 1666e3adcf8fSFrançois Tigeot intel_ring_advance(ring); 1667e3adcf8fSFrançois Tigeot return 0; 1668e3adcf8fSFrançois Tigeot } 1669e3adcf8fSFrançois Tigeot 1670e3adcf8fSFrançois Tigeot static int 1671a05eeebfSFrançois Tigeot i9xx_add_request(struct drm_i915_gem_request *req) 1672e3adcf8fSFrançois Tigeot { 1673a05eeebfSFrançois Tigeot struct intel_engine_cs *ring = req->ring; 1674e3adcf8fSFrançois Tigeot int ret; 1675e3adcf8fSFrançois Tigeot 1676a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 4); 1677e3adcf8fSFrançois Tigeot if (ret) 1678e3adcf8fSFrançois Tigeot return ret; 1679e3adcf8fSFrançois Tigeot 1680e3adcf8fSFrançois Tigeot intel_ring_emit(ring, MI_STORE_DWORD_INDEX); 1681e3adcf8fSFrançois Tigeot intel_ring_emit(ring, I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT); 1682a05eeebfSFrançois Tigeot intel_ring_emit(ring, i915_gem_request_get_seqno(req)); 1683e3adcf8fSFrançois Tigeot intel_ring_emit(ring, MI_USER_INTERRUPT); 16849edbd4a0SFrançois Tigeot __intel_ring_advance(ring); 1685e3adcf8fSFrançois Tigeot 1686e3adcf8fSFrançois Tigeot return 0; 1687e3adcf8fSFrançois Tigeot } 1688e3adcf8fSFrançois Tigeot 1689e3adcf8fSFrançois Tigeot static bool 1690ba55f2f5SFrançois Tigeot gen6_ring_get_irq(struct intel_engine_cs *ring) 1691e3adcf8fSFrançois Tigeot { 1692e3adcf8fSFrançois Tigeot struct drm_device *dev = ring->dev; 1693ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 16945e269720SFrançois Tigeot unsigned long flags; 1695e3adcf8fSFrançois Tigeot 16962c9916cdSFrançois Tigeot if (WARN_ON(!intel_irqs_enabled(dev_priv))) 1697e3adcf8fSFrançois Tigeot return false; 1698e3adcf8fSFrançois Tigeot 16995e269720SFrançois Tigeot spin_lock_irqsave(&dev_priv->irq_lock, flags); 17009edbd4a0SFrançois Tigeot if (ring->irq_refcount++ == 0) { 17019edbd4a0SFrançois Tigeot if (HAS_L3_DPF(dev) && ring->id == RCS) 17025d0b1887SFrançois Tigeot I915_WRITE_IMR(ring, 17035d0b1887SFrançois Tigeot ~(ring->irq_enable_mask | 17049edbd4a0SFrançois Tigeot GT_PARITY_ERROR(dev))); 1705686a02f1SFrançois Tigeot else 1706686a02f1SFrançois Tigeot I915_WRITE_IMR(ring, ~ring->irq_enable_mask); 170724edb884SFrançois Tigeot gen5_enable_gt_irq(dev_priv, ring->irq_enable_mask); 1708e3adcf8fSFrançois Tigeot } 17095e269720SFrançois Tigeot spin_unlock_irqrestore(&dev_priv->irq_lock, flags); 1710e3adcf8fSFrançois Tigeot 1711e3adcf8fSFrançois Tigeot return true; 1712e3adcf8fSFrançois Tigeot } 1713e3adcf8fSFrançois Tigeot 1714e3adcf8fSFrançois Tigeot static void 1715ba55f2f5SFrançois Tigeot gen6_ring_put_irq(struct intel_engine_cs *ring) 1716e3adcf8fSFrançois Tigeot { 1717e3adcf8fSFrançois Tigeot struct drm_device *dev = ring->dev; 1718ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 17195e269720SFrançois Tigeot unsigned long flags; 1720e3adcf8fSFrançois Tigeot 17215e269720SFrançois Tigeot spin_lock_irqsave(&dev_priv->irq_lock, flags); 17229edbd4a0SFrançois Tigeot if (--ring->irq_refcount == 0) { 17239edbd4a0SFrançois Tigeot if (HAS_L3_DPF(dev) && ring->id == RCS) 17249edbd4a0SFrançois Tigeot I915_WRITE_IMR(ring, ~GT_PARITY_ERROR(dev)); 1725686a02f1SFrançois Tigeot else 1726686a02f1SFrançois Tigeot I915_WRITE_IMR(ring, ~0); 172724edb884SFrançois Tigeot gen5_disable_gt_irq(dev_priv, ring->irq_enable_mask); 1728e3adcf8fSFrançois Tigeot } 17295e269720SFrançois Tigeot spin_unlock_irqrestore(&dev_priv->irq_lock, flags); 1730e3adcf8fSFrançois Tigeot } 1731e3adcf8fSFrançois Tigeot 17325d0b1887SFrançois Tigeot static bool 1733ba55f2f5SFrançois Tigeot hsw_vebox_get_irq(struct intel_engine_cs *ring) 17345d0b1887SFrançois Tigeot { 17355d0b1887SFrançois Tigeot struct drm_device *dev = ring->dev; 17365d0b1887SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 17375e269720SFrançois Tigeot unsigned long flags; 17385d0b1887SFrançois Tigeot 17392c9916cdSFrançois Tigeot if (WARN_ON(!intel_irqs_enabled(dev_priv))) 17405d0b1887SFrançois Tigeot return false; 17415d0b1887SFrançois Tigeot 17425e269720SFrançois Tigeot spin_lock_irqsave(&dev_priv->irq_lock, flags); 17439edbd4a0SFrançois Tigeot if (ring->irq_refcount++ == 0) { 17445d0b1887SFrançois Tigeot I915_WRITE_IMR(ring, ~ring->irq_enable_mask); 174524edb884SFrançois Tigeot gen6_enable_pm_irq(dev_priv, ring->irq_enable_mask); 17465d0b1887SFrançois Tigeot } 17475e269720SFrançois Tigeot spin_unlock_irqrestore(&dev_priv->irq_lock, flags); 17485d0b1887SFrançois Tigeot 17495d0b1887SFrançois Tigeot return true; 17505d0b1887SFrançois Tigeot } 17515d0b1887SFrançois Tigeot 17525d0b1887SFrançois Tigeot static void 1753ba55f2f5SFrançois Tigeot hsw_vebox_put_irq(struct intel_engine_cs *ring) 17545d0b1887SFrançois Tigeot { 17555d0b1887SFrançois Tigeot struct drm_device *dev = ring->dev; 17565d0b1887SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 17575e269720SFrançois Tigeot unsigned long flags; 17585d0b1887SFrançois Tigeot 17595e269720SFrançois Tigeot spin_lock_irqsave(&dev_priv->irq_lock, flags); 17609edbd4a0SFrançois Tigeot if (--ring->irq_refcount == 0) { 17615d0b1887SFrançois Tigeot I915_WRITE_IMR(ring, ~0); 176224edb884SFrançois Tigeot gen6_disable_pm_irq(dev_priv, ring->irq_enable_mask); 17635d0b1887SFrançois Tigeot } 17645e269720SFrançois Tigeot spin_unlock_irqrestore(&dev_priv->irq_lock, flags); 17659edbd4a0SFrançois Tigeot } 17669edbd4a0SFrançois Tigeot 17679edbd4a0SFrançois Tigeot static bool 1768ba55f2f5SFrançois Tigeot gen8_ring_get_irq(struct intel_engine_cs *ring) 17699edbd4a0SFrançois Tigeot { 17709edbd4a0SFrançois Tigeot struct drm_device *dev = ring->dev; 17719edbd4a0SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 17725e269720SFrançois Tigeot unsigned long flags; 17739edbd4a0SFrançois Tigeot 17742c9916cdSFrançois Tigeot if (WARN_ON(!intel_irqs_enabled(dev_priv))) 17759edbd4a0SFrançois Tigeot return false; 17769edbd4a0SFrançois Tigeot 17775e269720SFrançois Tigeot spin_lock_irqsave(&dev_priv->irq_lock, flags); 17789edbd4a0SFrançois Tigeot if (ring->irq_refcount++ == 0) { 17799edbd4a0SFrançois Tigeot if (HAS_L3_DPF(dev) && ring->id == RCS) { 17809edbd4a0SFrançois Tigeot I915_WRITE_IMR(ring, 17819edbd4a0SFrançois Tigeot ~(ring->irq_enable_mask | 17829edbd4a0SFrançois Tigeot GT_RENDER_L3_PARITY_ERROR_INTERRUPT)); 17839edbd4a0SFrançois Tigeot } else { 17849edbd4a0SFrançois Tigeot I915_WRITE_IMR(ring, ~ring->irq_enable_mask); 17859edbd4a0SFrançois Tigeot } 17869edbd4a0SFrançois Tigeot POSTING_READ(RING_IMR(ring->mmio_base)); 17879edbd4a0SFrançois Tigeot } 17885e269720SFrançois Tigeot spin_unlock_irqrestore(&dev_priv->irq_lock, flags); 17899edbd4a0SFrançois Tigeot 17909edbd4a0SFrançois Tigeot return true; 17919edbd4a0SFrançois Tigeot } 17929edbd4a0SFrançois Tigeot 17939edbd4a0SFrançois Tigeot static void 1794ba55f2f5SFrançois Tigeot gen8_ring_put_irq(struct intel_engine_cs *ring) 17959edbd4a0SFrançois Tigeot { 17969edbd4a0SFrançois Tigeot struct drm_device *dev = ring->dev; 17979edbd4a0SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 17985e269720SFrançois Tigeot unsigned long flags; 17999edbd4a0SFrançois Tigeot 18005e269720SFrançois Tigeot spin_lock_irqsave(&dev_priv->irq_lock, flags); 18019edbd4a0SFrançois Tigeot if (--ring->irq_refcount == 0) { 18029edbd4a0SFrançois Tigeot if (HAS_L3_DPF(dev) && ring->id == RCS) { 18039edbd4a0SFrançois Tigeot I915_WRITE_IMR(ring, 18049edbd4a0SFrançois Tigeot ~GT_RENDER_L3_PARITY_ERROR_INTERRUPT); 18059edbd4a0SFrançois Tigeot } else { 18069edbd4a0SFrançois Tigeot I915_WRITE_IMR(ring, ~0); 18079edbd4a0SFrançois Tigeot } 18089edbd4a0SFrançois Tigeot POSTING_READ(RING_IMR(ring->mmio_base)); 18099edbd4a0SFrançois Tigeot } 18105e269720SFrançois Tigeot spin_unlock_irqrestore(&dev_priv->irq_lock, flags); 18115d0b1887SFrançois Tigeot } 18125d0b1887SFrançois Tigeot 1813e3adcf8fSFrançois Tigeot static int 1814a05eeebfSFrançois Tigeot i965_dispatch_execbuffer(struct drm_i915_gem_request *req, 1815ba55f2f5SFrançois Tigeot u64 offset, u32 length, 1816477eb7f9SFrançois Tigeot unsigned dispatch_flags) 1817e3adcf8fSFrançois Tigeot { 1818a05eeebfSFrançois Tigeot struct intel_engine_cs *ring = req->ring; 1819e3adcf8fSFrançois Tigeot int ret; 1820e3adcf8fSFrançois Tigeot 1821a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 2); 1822e3adcf8fSFrançois Tigeot if (ret) 1823e3adcf8fSFrançois Tigeot return ret; 1824e3adcf8fSFrançois Tigeot 1825e3adcf8fSFrançois Tigeot intel_ring_emit(ring, 1826686a02f1SFrançois Tigeot MI_BATCH_BUFFER_START | 1827b5c29a34SFrançois Tigeot MI_BATCH_GTT | 1828477eb7f9SFrançois Tigeot (dispatch_flags & I915_DISPATCH_SECURE ? 1829477eb7f9SFrançois Tigeot 0 : MI_BATCH_NON_SECURE_I965)); 1830e3adcf8fSFrançois Tigeot intel_ring_emit(ring, offset); 1831e3adcf8fSFrançois Tigeot intel_ring_advance(ring); 1832e3adcf8fSFrançois Tigeot 1833e3adcf8fSFrançois Tigeot return 0; 1834e3adcf8fSFrançois Tigeot } 1835e3adcf8fSFrançois Tigeot 1836b5c29a34SFrançois Tigeot /* Just userspace ABI convention to limit the wa batch bo to a resonable size */ 1837b5c29a34SFrançois Tigeot #define I830_BATCH_LIMIT (256*1024) 183824edb884SFrançois Tigeot #define I830_TLB_ENTRIES (2) 183924edb884SFrançois Tigeot #define I830_WA_SIZE max(I830_TLB_ENTRIES*4096, I830_BATCH_LIMIT) 1840e3adcf8fSFrançois Tigeot static int 1841a05eeebfSFrançois Tigeot i830_dispatch_execbuffer(struct drm_i915_gem_request *req, 1842ba55f2f5SFrançois Tigeot u64 offset, u32 len, 1843477eb7f9SFrançois Tigeot unsigned dispatch_flags) 1844e3adcf8fSFrançois Tigeot { 1845a05eeebfSFrançois Tigeot struct intel_engine_cs *ring = req->ring; 184624edb884SFrançois Tigeot u32 cs_offset = ring->scratch.gtt_offset; 1847e3adcf8fSFrançois Tigeot int ret; 1848e3adcf8fSFrançois Tigeot 1849a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 6); 185024edb884SFrançois Tigeot if (ret) 185124edb884SFrançois Tigeot return ret; 185224edb884SFrançois Tigeot 185324edb884SFrançois Tigeot /* Evict the invalid PTE TLBs */ 185424edb884SFrançois Tigeot intel_ring_emit(ring, COLOR_BLT_CMD | BLT_WRITE_RGBA); 185524edb884SFrançois Tigeot intel_ring_emit(ring, BLT_DEPTH_32 | BLT_ROP_COLOR_COPY | 4096); 185624edb884SFrançois Tigeot intel_ring_emit(ring, I830_TLB_ENTRIES << 16 | 4); /* load each page */ 185724edb884SFrançois Tigeot intel_ring_emit(ring, cs_offset); 185824edb884SFrançois Tigeot intel_ring_emit(ring, 0xdeadbeef); 185924edb884SFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 186024edb884SFrançois Tigeot intel_ring_advance(ring); 186124edb884SFrançois Tigeot 1862477eb7f9SFrançois Tigeot if ((dispatch_flags & I915_DISPATCH_PINNED) == 0) { 186324edb884SFrançois Tigeot if (len > I830_BATCH_LIMIT) 186424edb884SFrançois Tigeot return -ENOSPC; 186524edb884SFrançois Tigeot 1866a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 6 + 2); 186724edb884SFrançois Tigeot if (ret) 186824edb884SFrançois Tigeot return ret; 186924edb884SFrançois Tigeot 187024edb884SFrançois Tigeot /* Blit the batch (which has now all relocs applied) to the 187124edb884SFrançois Tigeot * stable batch scratch bo area (so that the CS never 187224edb884SFrançois Tigeot * stumbles over its tlb invalidation bug) ... 187324edb884SFrançois Tigeot */ 187424edb884SFrançois Tigeot intel_ring_emit(ring, SRC_COPY_BLT_CMD | BLT_WRITE_RGBA); 187524edb884SFrançois Tigeot intel_ring_emit(ring, BLT_DEPTH_32 | BLT_ROP_SRC_COPY | 4096); 187624edb884SFrançois Tigeot intel_ring_emit(ring, DIV_ROUND_UP(len, 4096) << 16 | 4096); 187724edb884SFrançois Tigeot intel_ring_emit(ring, cs_offset); 187824edb884SFrançois Tigeot intel_ring_emit(ring, 4096); 187924edb884SFrançois Tigeot intel_ring_emit(ring, offset); 188024edb884SFrançois Tigeot 188124edb884SFrançois Tigeot intel_ring_emit(ring, MI_FLUSH); 188224edb884SFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 188324edb884SFrançois Tigeot intel_ring_advance(ring); 188424edb884SFrançois Tigeot 188524edb884SFrançois Tigeot /* ... and execute it. */ 188624edb884SFrançois Tigeot offset = cs_offset; 188724edb884SFrançois Tigeot } 188824edb884SFrançois Tigeot 1889a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 4); 1890e3adcf8fSFrançois Tigeot if (ret) 1891e3adcf8fSFrançois Tigeot return ret; 1892e3adcf8fSFrançois Tigeot 1893e3adcf8fSFrançois Tigeot intel_ring_emit(ring, MI_BATCH_BUFFER); 1894477eb7f9SFrançois Tigeot intel_ring_emit(ring, offset | (dispatch_flags & I915_DISPATCH_SECURE ? 1895477eb7f9SFrançois Tigeot 0 : MI_BATCH_NON_SECURE)); 1896e3adcf8fSFrançois Tigeot intel_ring_emit(ring, offset + len - 8); 1897b5c29a34SFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 1898686a02f1SFrançois Tigeot intel_ring_advance(ring); 1899686a02f1SFrançois Tigeot 1900686a02f1SFrançois Tigeot return 0; 1901686a02f1SFrançois Tigeot } 1902686a02f1SFrançois Tigeot 1903686a02f1SFrançois Tigeot static int 1904a05eeebfSFrançois Tigeot i915_dispatch_execbuffer(struct drm_i915_gem_request *req, 1905ba55f2f5SFrançois Tigeot u64 offset, u32 len, 1906477eb7f9SFrançois Tigeot unsigned dispatch_flags) 1907686a02f1SFrançois Tigeot { 1908a05eeebfSFrançois Tigeot struct intel_engine_cs *ring = req->ring; 1909686a02f1SFrançois Tigeot int ret; 1910686a02f1SFrançois Tigeot 1911a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 2); 1912e3adcf8fSFrançois Tigeot if (ret) 1913e3adcf8fSFrançois Tigeot return ret; 1914e3adcf8fSFrançois Tigeot 1915686a02f1SFrançois Tigeot intel_ring_emit(ring, MI_BATCH_BUFFER_START | MI_BATCH_GTT); 1916477eb7f9SFrançois Tigeot intel_ring_emit(ring, offset | (dispatch_flags & I915_DISPATCH_SECURE ? 1917477eb7f9SFrançois Tigeot 0 : MI_BATCH_NON_SECURE)); 1918e3adcf8fSFrançois Tigeot intel_ring_advance(ring); 1919e3adcf8fSFrançois Tigeot 1920e3adcf8fSFrançois Tigeot return 0; 1921e3adcf8fSFrançois Tigeot } 1922e3adcf8fSFrançois Tigeot 1923ba55f2f5SFrançois Tigeot static void cleanup_status_page(struct intel_engine_cs *ring) 1924e3adcf8fSFrançois Tigeot { 1925e3adcf8fSFrançois Tigeot struct drm_i915_gem_object *obj; 1926e3adcf8fSFrançois Tigeot 1927e3adcf8fSFrançois Tigeot obj = ring->status_page.obj; 1928e3adcf8fSFrançois Tigeot if (obj == NULL) 1929e3adcf8fSFrançois Tigeot return; 1930e3adcf8fSFrançois Tigeot 19317ec9f8e5SFrançois Tigeot kunmap(sg_page(obj->pages->sgl)); 1932ba55f2f5SFrançois Tigeot i915_gem_object_ggtt_unpin(obj); 1933e3adcf8fSFrançois Tigeot drm_gem_object_unreference(&obj->base); 1934e3adcf8fSFrançois Tigeot ring->status_page.obj = NULL; 1935e3adcf8fSFrançois Tigeot } 1936e3adcf8fSFrançois Tigeot 1937ba55f2f5SFrançois Tigeot static int init_status_page(struct intel_engine_cs *ring) 1938e3adcf8fSFrançois Tigeot { 1939e3adcf8fSFrançois Tigeot struct drm_i915_gem_object *obj; 1940ba55f2f5SFrançois Tigeot 1941ba55f2f5SFrançois Tigeot if ((obj = ring->status_page.obj) == NULL) { 194224edb884SFrançois Tigeot unsigned flags; 1943e3adcf8fSFrançois Tigeot int ret; 1944e3adcf8fSFrançois Tigeot 1945ba55f2f5SFrançois Tigeot obj = i915_gem_alloc_object(ring->dev, 4096); 1946e3adcf8fSFrançois Tigeot if (obj == NULL) { 1947e3adcf8fSFrançois Tigeot DRM_ERROR("Failed to allocate status page\n"); 1948ba55f2f5SFrançois Tigeot return -ENOMEM; 1949e3adcf8fSFrançois Tigeot } 1950e3adcf8fSFrançois Tigeot 1951ba55f2f5SFrançois Tigeot ret = i915_gem_object_set_cache_level(obj, I915_CACHE_LLC); 1952ba55f2f5SFrançois Tigeot if (ret) 1953e3adcf8fSFrançois Tigeot goto err_unref; 1954ba55f2f5SFrançois Tigeot 195524edb884SFrançois Tigeot flags = 0; 195624edb884SFrançois Tigeot if (!HAS_LLC(ring->dev)) 195724edb884SFrançois Tigeot /* On g33, we cannot place HWS above 256MiB, so 195824edb884SFrançois Tigeot * restrict its pinning to the low mappable arena. 195924edb884SFrançois Tigeot * Though this restriction is not documented for 196024edb884SFrançois Tigeot * gen4, gen5, or byt, they also behave similarly 196124edb884SFrançois Tigeot * and hang if the HWS is placed at the top of the 196224edb884SFrançois Tigeot * GTT. To generalise, it appears that all !llc 196324edb884SFrançois Tigeot * platforms have issues with us placing the HWS 196424edb884SFrançois Tigeot * above the mappable region (even though we never 196524edb884SFrançois Tigeot * actualy map it). 196624edb884SFrançois Tigeot */ 196724edb884SFrançois Tigeot flags |= PIN_MAPPABLE; 196824edb884SFrançois Tigeot ret = i915_gem_obj_ggtt_pin(obj, 4096, flags); 1969ba55f2f5SFrançois Tigeot if (ret) { 1970ba55f2f5SFrançois Tigeot err_unref: 1971ba55f2f5SFrançois Tigeot drm_gem_object_unreference(&obj->base); 1972ba55f2f5SFrançois Tigeot return ret; 1973ba55f2f5SFrançois Tigeot } 1974ba55f2f5SFrançois Tigeot 1975ba55f2f5SFrançois Tigeot ring->status_page.obj = obj; 1976e3adcf8fSFrançois Tigeot } 1977e3adcf8fSFrançois Tigeot 19789edbd4a0SFrançois Tigeot ring->status_page.gfx_addr = i915_gem_obj_ggtt_offset(obj); 19797ec9f8e5SFrançois Tigeot ring->status_page.page_addr = kmap(sg_page(obj->pages->sgl)); 1980e3adcf8fSFrançois Tigeot memset(ring->status_page.page_addr, 0, PAGE_SIZE); 1981e3adcf8fSFrançois Tigeot 1982b5c29a34SFrançois Tigeot DRM_DEBUG_DRIVER("%s hws offset: 0x%08x\n", 1983e3adcf8fSFrançois Tigeot ring->name, ring->status_page.gfx_addr); 1984e3adcf8fSFrançois Tigeot 1985e3adcf8fSFrançois Tigeot return 0; 1986e3adcf8fSFrançois Tigeot } 1987e3adcf8fSFrançois Tigeot 1988ba55f2f5SFrançois Tigeot static int init_phys_status_page(struct intel_engine_cs *ring) 1989686a02f1SFrançois Tigeot { 1990686a02f1SFrançois Tigeot struct drm_i915_private *dev_priv = ring->dev->dev_private; 1991686a02f1SFrançois Tigeot 1992686a02f1SFrançois Tigeot if (!dev_priv->status_page_dmah) { 1993686a02f1SFrançois Tigeot dev_priv->status_page_dmah = 1994b31e9d59SFrançois Tigeot drm_pci_alloc(ring->dev, PAGE_SIZE, PAGE_SIZE); 1995686a02f1SFrançois Tigeot if (!dev_priv->status_page_dmah) 1996686a02f1SFrançois Tigeot return -ENOMEM; 1997686a02f1SFrançois Tigeot } 1998686a02f1SFrançois Tigeot 1999686a02f1SFrançois Tigeot ring->status_page.page_addr = dev_priv->status_page_dmah->vaddr; 2000686a02f1SFrançois Tigeot memset(ring->status_page.page_addr, 0, PAGE_SIZE); 2001686a02f1SFrançois Tigeot 2002686a02f1SFrançois Tigeot return 0; 2003686a02f1SFrançois Tigeot } 2004686a02f1SFrançois Tigeot 20052c9916cdSFrançois Tigeot void intel_unpin_ringbuffer_obj(struct intel_ringbuffer *ringbuf) 20062c9916cdSFrançois Tigeot { 200724409b39SFrançois Tigeot iounmap(ringbuf->virtual_start); 20082c9916cdSFrançois Tigeot ringbuf->virtual_start = NULL; 20092c9916cdSFrançois Tigeot i915_gem_object_ggtt_unpin(ringbuf->obj); 20102c9916cdSFrançois Tigeot } 20112c9916cdSFrançois Tigeot 20122c9916cdSFrançois Tigeot int intel_pin_and_map_ringbuffer_obj(struct drm_device *dev, 20132c9916cdSFrançois Tigeot struct intel_ringbuffer *ringbuf) 20142c9916cdSFrançois Tigeot { 20152c9916cdSFrançois Tigeot struct drm_i915_private *dev_priv = to_i915(dev); 20162c9916cdSFrançois Tigeot struct drm_i915_gem_object *obj = ringbuf->obj; 20172c9916cdSFrançois Tigeot int ret; 20182c9916cdSFrançois Tigeot 20192c9916cdSFrançois Tigeot ret = i915_gem_obj_ggtt_pin(obj, PAGE_SIZE, PIN_MAPPABLE); 20202c9916cdSFrançois Tigeot if (ret) 20212c9916cdSFrançois Tigeot return ret; 20222c9916cdSFrançois Tigeot 20232c9916cdSFrançois Tigeot ret = i915_gem_object_set_to_gtt_domain(obj, true); 20242c9916cdSFrançois Tigeot if (ret) { 20252c9916cdSFrançois Tigeot i915_gem_object_ggtt_unpin(obj); 20262c9916cdSFrançois Tigeot return ret; 20272c9916cdSFrançois Tigeot } 20282c9916cdSFrançois Tigeot 20292c9916cdSFrançois Tigeot ringbuf->virtual_start = ioremap_wc(dev_priv->gtt.mappable_base + 20302c9916cdSFrançois Tigeot i915_gem_obj_ggtt_offset(obj), ringbuf->size); 20312c9916cdSFrançois Tigeot if (ringbuf->virtual_start == NULL) { 20322c9916cdSFrançois Tigeot i915_gem_object_ggtt_unpin(obj); 20332c9916cdSFrançois Tigeot return -EINVAL; 20342c9916cdSFrançois Tigeot } 20352c9916cdSFrançois Tigeot 20362c9916cdSFrançois Tigeot return 0; 20372c9916cdSFrançois Tigeot } 20382c9916cdSFrançois Tigeot 2039*352ff8bdSFrançois Tigeot static void intel_destroy_ringbuffer_obj(struct intel_ringbuffer *ringbuf) 2040e3adcf8fSFrançois Tigeot { 204124edb884SFrançois Tigeot drm_gem_object_unreference(&ringbuf->obj->base); 204224edb884SFrançois Tigeot ringbuf->obj = NULL; 204324edb884SFrançois Tigeot } 204424edb884SFrançois Tigeot 2045*352ff8bdSFrançois Tigeot static int intel_alloc_ringbuffer_obj(struct drm_device *dev, 204624edb884SFrançois Tigeot struct intel_ringbuffer *ringbuf) 204724edb884SFrançois Tigeot { 2048e3adcf8fSFrançois Tigeot struct drm_i915_gem_object *obj; 2049e3adcf8fSFrançois Tigeot 2050a2fdbec6SFrançois Tigeot obj = NULL; 2051a2fdbec6SFrançois Tigeot if (!HAS_LLC(dev)) 2052ba55f2f5SFrançois Tigeot obj = i915_gem_object_create_stolen(dev, ringbuf->size); 2053a2fdbec6SFrançois Tigeot if (obj == NULL) 2054ba55f2f5SFrançois Tigeot obj = i915_gem_alloc_object(dev, ringbuf->size); 2055ba55f2f5SFrançois Tigeot if (obj == NULL) 2056ba55f2f5SFrançois Tigeot return -ENOMEM; 2057e3adcf8fSFrançois Tigeot 205824edb884SFrançois Tigeot /* mark ring buffers as read-only from GPU side by default */ 205924edb884SFrançois Tigeot obj->gt_ro = 1; 206024edb884SFrançois Tigeot 2061ba55f2f5SFrançois Tigeot ringbuf->obj = obj; 2062ba55f2f5SFrançois Tigeot 20632c9916cdSFrançois Tigeot return 0; 2064ba55f2f5SFrançois Tigeot } 2065ba55f2f5SFrançois Tigeot 2066*352ff8bdSFrançois Tigeot struct intel_ringbuffer * 2067*352ff8bdSFrançois Tigeot intel_engine_create_ringbuffer(struct intel_engine_cs *engine, int size) 2068*352ff8bdSFrançois Tigeot { 2069*352ff8bdSFrançois Tigeot struct intel_ringbuffer *ring; 2070*352ff8bdSFrançois Tigeot int ret; 2071*352ff8bdSFrançois Tigeot 2072*352ff8bdSFrançois Tigeot ring = kzalloc(sizeof(*ring), GFP_KERNEL); 2073*352ff8bdSFrançois Tigeot if (ring == NULL) 2074*352ff8bdSFrançois Tigeot return ERR_PTR(-ENOMEM); 2075*352ff8bdSFrançois Tigeot 2076*352ff8bdSFrançois Tigeot ring->ring = engine; 2077*352ff8bdSFrançois Tigeot 2078*352ff8bdSFrançois Tigeot ring->size = size; 2079*352ff8bdSFrançois Tigeot /* Workaround an erratum on the i830 which causes a hang if 2080*352ff8bdSFrançois Tigeot * the TAIL pointer points to within the last 2 cachelines 2081*352ff8bdSFrançois Tigeot * of the buffer. 2082*352ff8bdSFrançois Tigeot */ 2083*352ff8bdSFrançois Tigeot ring->effective_size = size; 2084*352ff8bdSFrançois Tigeot if (IS_I830(engine->dev) || IS_845G(engine->dev)) 2085*352ff8bdSFrançois Tigeot ring->effective_size -= 2 * CACHELINE_BYTES; 2086*352ff8bdSFrançois Tigeot 2087*352ff8bdSFrançois Tigeot ring->last_retired_head = -1; 2088*352ff8bdSFrançois Tigeot intel_ring_update_space(ring); 2089*352ff8bdSFrançois Tigeot 2090*352ff8bdSFrançois Tigeot ret = intel_alloc_ringbuffer_obj(engine->dev, ring); 2091*352ff8bdSFrançois Tigeot if (ret) { 2092*352ff8bdSFrançois Tigeot DRM_ERROR("Failed to allocate ringbuffer %s: %d\n", 2093*352ff8bdSFrançois Tigeot engine->name, ret); 2094*352ff8bdSFrançois Tigeot kfree(ring); 2095*352ff8bdSFrançois Tigeot return ERR_PTR(ret); 2096*352ff8bdSFrançois Tigeot } 2097*352ff8bdSFrançois Tigeot 2098*352ff8bdSFrançois Tigeot return ring; 2099*352ff8bdSFrançois Tigeot } 2100*352ff8bdSFrançois Tigeot 2101*352ff8bdSFrançois Tigeot void 2102*352ff8bdSFrançois Tigeot intel_ringbuffer_free(struct intel_ringbuffer *ring) 2103*352ff8bdSFrançois Tigeot { 2104*352ff8bdSFrançois Tigeot intel_destroy_ringbuffer_obj(ring); 2105*352ff8bdSFrançois Tigeot kfree(ring); 2106*352ff8bdSFrançois Tigeot } 2107*352ff8bdSFrançois Tigeot 2108ba55f2f5SFrançois Tigeot static int intel_init_ring_buffer(struct drm_device *dev, 2109ba55f2f5SFrançois Tigeot struct intel_engine_cs *ring) 2110ba55f2f5SFrançois Tigeot { 21112c9916cdSFrançois Tigeot struct intel_ringbuffer *ringbuf; 2112ba55f2f5SFrançois Tigeot int ret; 2113ba55f2f5SFrançois Tigeot 21142c9916cdSFrançois Tigeot WARN_ON(ring->buffer); 21152c9916cdSFrançois Tigeot 2116ba55f2f5SFrançois Tigeot ring->dev = dev; 2117ba55f2f5SFrançois Tigeot INIT_LIST_HEAD(&ring->active_list); 2118ba55f2f5SFrançois Tigeot INIT_LIST_HEAD(&ring->request_list); 21191b13d190SFrançois Tigeot INIT_LIST_HEAD(&ring->execlist_queue); 212019c468b4SFrançois Tigeot i915_gem_batch_pool_init(dev, &ring->batch_pool); 2121ba55f2f5SFrançois Tigeot memset(ring->semaphore.sync_seqno, 0, sizeof(ring->semaphore.sync_seqno)); 2122ba55f2f5SFrançois Tigeot 2123ba55f2f5SFrançois Tigeot init_waitqueue_head(&ring->irq_queue); 2124ba55f2f5SFrançois Tigeot 2125*352ff8bdSFrançois Tigeot ringbuf = intel_engine_create_ringbuffer(ring, 32 * PAGE_SIZE); 2126*352ff8bdSFrançois Tigeot if (IS_ERR(ringbuf)) 2127*352ff8bdSFrançois Tigeot return PTR_ERR(ringbuf); 2128*352ff8bdSFrançois Tigeot ring->buffer = ringbuf; 2129*352ff8bdSFrançois Tigeot 2130ba55f2f5SFrançois Tigeot if (I915_NEED_GFX_HWS(dev)) { 2131ba55f2f5SFrançois Tigeot ret = init_status_page(ring); 2132e3adcf8fSFrançois Tigeot if (ret) 2133ba55f2f5SFrançois Tigeot goto error; 2134ba55f2f5SFrançois Tigeot } else { 2135ba55f2f5SFrançois Tigeot BUG_ON(ring->id != RCS); 2136ba55f2f5SFrançois Tigeot ret = init_phys_status_page(ring); 2137ba55f2f5SFrançois Tigeot if (ret) 2138ba55f2f5SFrançois Tigeot goto error; 2139ba55f2f5SFrançois Tigeot } 2140ba55f2f5SFrançois Tigeot 21412c9916cdSFrançois Tigeot ret = intel_pin_and_map_ringbuffer_obj(dev, ringbuf); 21422c9916cdSFrançois Tigeot if (ret) { 21432c9916cdSFrançois Tigeot DRM_ERROR("Failed to pin and map ringbuffer %s: %d\n", 21442c9916cdSFrançois Tigeot ring->name, ret); 21452c9916cdSFrançois Tigeot intel_destroy_ringbuffer_obj(ringbuf); 2146ba55f2f5SFrançois Tigeot goto error; 2147ba55f2f5SFrançois Tigeot } 2148e3adcf8fSFrançois Tigeot 2149ba55f2f5SFrançois Tigeot ret = i915_cmd_parser_init_ring(ring); 2150ba55f2f5SFrançois Tigeot if (ret) 2151ba55f2f5SFrançois Tigeot goto error; 2152ba55f2f5SFrançois Tigeot 2153e3adcf8fSFrançois Tigeot return 0; 2154e3adcf8fSFrançois Tigeot 2155ba55f2f5SFrançois Tigeot error: 2156*352ff8bdSFrançois Tigeot intel_ringbuffer_free(ringbuf); 2157ba55f2f5SFrançois Tigeot ring->buffer = NULL; 2158e3adcf8fSFrançois Tigeot return ret; 2159e3adcf8fSFrançois Tigeot } 2160e3adcf8fSFrançois Tigeot 2161ba55f2f5SFrançois Tigeot void intel_cleanup_ring_buffer(struct intel_engine_cs *ring) 2162e3adcf8fSFrançois Tigeot { 21632c9916cdSFrançois Tigeot struct drm_i915_private *dev_priv; 2164e3adcf8fSFrançois Tigeot 2165ba55f2f5SFrançois Tigeot if (!intel_ring_initialized(ring)) 2166e3adcf8fSFrançois Tigeot return; 2167e3adcf8fSFrançois Tigeot 21682c9916cdSFrançois Tigeot dev_priv = to_i915(ring->dev); 21692c9916cdSFrançois Tigeot 2170ba55f2f5SFrançois Tigeot intel_stop_ring_buffer(ring); 2171ba55f2f5SFrançois Tigeot WARN_ON(!IS_GEN2(ring->dev) && (I915_READ_MODE(ring) & MODE_IDLE) == 0); 2172b030f26bSFrançois Tigeot 2173*352ff8bdSFrançois Tigeot intel_unpin_ringbuffer_obj(ring->buffer); 2174*352ff8bdSFrançois Tigeot intel_ringbuffer_free(ring->buffer); 2175*352ff8bdSFrançois Tigeot ring->buffer = NULL; 2176e3adcf8fSFrançois Tigeot 2177e3adcf8fSFrançois Tigeot if (ring->cleanup) 2178e3adcf8fSFrançois Tigeot ring->cleanup(ring); 2179e3adcf8fSFrançois Tigeot 2180e3adcf8fSFrançois Tigeot cleanup_status_page(ring); 2181ba55f2f5SFrançois Tigeot 2182ba55f2f5SFrançois Tigeot i915_cmd_parser_fini_ring(ring); 218319c468b4SFrançois Tigeot i915_gem_batch_pool_fini(&ring->batch_pool); 2184e3adcf8fSFrançois Tigeot } 2185e3adcf8fSFrançois Tigeot 218619c468b4SFrançois Tigeot static int ring_wait_for_space(struct intel_engine_cs *ring, int n) 2187e3adcf8fSFrançois Tigeot { 2188ba55f2f5SFrançois Tigeot struct intel_ringbuffer *ringbuf = ring->buffer; 2189e3adcf8fSFrançois Tigeot struct drm_i915_gem_request *request; 219019c468b4SFrançois Tigeot unsigned space; 2191e3adcf8fSFrançois Tigeot int ret; 2192e3adcf8fSFrançois Tigeot 21932c9916cdSFrançois Tigeot if (intel_ring_space(ringbuf) >= n) 2194e3adcf8fSFrançois Tigeot return 0; 2195e3adcf8fSFrançois Tigeot 2196a05eeebfSFrançois Tigeot /* The whole point of reserving space is to not wait! */ 2197a05eeebfSFrançois Tigeot WARN_ON(ringbuf->reserved_in_use); 2198a05eeebfSFrançois Tigeot 2199e3adcf8fSFrançois Tigeot list_for_each_entry(request, &ring->request_list, list) { 220019c468b4SFrançois Tigeot space = __intel_ring_space(request->postfix, ringbuf->tail, 220119c468b4SFrançois Tigeot ringbuf->size); 220219c468b4SFrançois Tigeot if (space >= n) 2203e3adcf8fSFrançois Tigeot break; 2204e3adcf8fSFrançois Tigeot } 2205e3adcf8fSFrançois Tigeot 220619c468b4SFrançois Tigeot if (WARN_ON(&request->list == &ring->request_list)) 2207e3adcf8fSFrançois Tigeot return -ENOSPC; 2208e3adcf8fSFrançois Tigeot 22092c9916cdSFrançois Tigeot ret = i915_wait_request(request); 2210e3adcf8fSFrançois Tigeot if (ret) 2211e3adcf8fSFrançois Tigeot return ret; 2212e3adcf8fSFrançois Tigeot 221319c468b4SFrançois Tigeot ringbuf->space = space; 2214e3adcf8fSFrançois Tigeot return 0; 2215e3adcf8fSFrançois Tigeot } 2216e3adcf8fSFrançois Tigeot 2217a05eeebfSFrançois Tigeot static void __wrap_ring_buffer(struct intel_ringbuffer *ringbuf) 2218b030f26bSFrançois Tigeot { 2219b030f26bSFrançois Tigeot uint32_t __iomem *virt; 2220ba55f2f5SFrançois Tigeot int rem = ringbuf->size - ringbuf->tail; 2221b030f26bSFrançois Tigeot 2222ba55f2f5SFrançois Tigeot virt = (unsigned int *)((char *)ringbuf->virtual_start + ringbuf->tail); 2223b030f26bSFrançois Tigeot rem /= 4; 2224b030f26bSFrançois Tigeot while (rem--) 2225686a02f1SFrançois Tigeot iowrite32(MI_NOOP, virt++); 2226b030f26bSFrançois Tigeot 2227ba55f2f5SFrançois Tigeot ringbuf->tail = 0; 22282c9916cdSFrançois Tigeot intel_ring_update_space(ringbuf); 2229b030f26bSFrançois Tigeot } 2230b030f26bSFrançois Tigeot 2231ba55f2f5SFrançois Tigeot int intel_ring_idle(struct intel_engine_cs *ring) 2232b030f26bSFrançois Tigeot { 22332c9916cdSFrançois Tigeot struct drm_i915_gem_request *req; 2234b5c29a34SFrançois Tigeot 2235b5c29a34SFrançois Tigeot /* Wait upon the last request to be completed */ 2236b5c29a34SFrançois Tigeot if (list_empty(&ring->request_list)) 2237b5c29a34SFrançois Tigeot return 0; 2238b5c29a34SFrançois Tigeot 22392c9916cdSFrançois Tigeot req = list_entry(ring->request_list.prev, 2240b5c29a34SFrançois Tigeot struct drm_i915_gem_request, 22412c9916cdSFrançois Tigeot list); 2242b5c29a34SFrançois Tigeot 224319c468b4SFrançois Tigeot /* Make sure we do not trigger any retires */ 224419c468b4SFrançois Tigeot return __i915_wait_request(req, 224519c468b4SFrançois Tigeot atomic_read(&to_i915(ring->dev)->gpu_error.reset_counter), 224619c468b4SFrançois Tigeot to_i915(ring->dev)->mm.interruptible, 224719c468b4SFrançois Tigeot NULL, NULL); 2248b5c29a34SFrançois Tigeot } 2249b5c29a34SFrançois Tigeot 225019c468b4SFrançois Tigeot int intel_ring_alloc_request_extras(struct drm_i915_gem_request *request) 2251b5c29a34SFrançois Tigeot { 225219c468b4SFrançois Tigeot request->ringbuf = request->ring->buffer; 22532c9916cdSFrançois Tigeot return 0; 22549edbd4a0SFrançois Tigeot } 22559edbd4a0SFrançois Tigeot 2256a05eeebfSFrançois Tigeot int intel_ring_reserve_space(struct drm_i915_gem_request *request) 2257a2fdbec6SFrançois Tigeot { 2258a05eeebfSFrançois Tigeot /* 2259a05eeebfSFrançois Tigeot * The first call merely notes the reserve request and is common for 2260a05eeebfSFrançois Tigeot * all back ends. The subsequent localised _begin() call actually 2261a05eeebfSFrançois Tigeot * ensures that the reservation is available. Without the begin, if 2262a05eeebfSFrançois Tigeot * the request creator immediately submitted the request without 2263a05eeebfSFrançois Tigeot * adding any commands to it then there might not actually be 2264a05eeebfSFrançois Tigeot * sufficient room for the submission commands. 2265a05eeebfSFrançois Tigeot */ 2266a05eeebfSFrançois Tigeot intel_ring_reserved_space_reserve(request->ringbuf, MIN_SPACE_FOR_ADD_REQUEST); 2267a2fdbec6SFrançois Tigeot 2268a05eeebfSFrançois Tigeot return intel_ring_begin(request, 0); 2269a2fdbec6SFrançois Tigeot } 2270a2fdbec6SFrançois Tigeot 2271a05eeebfSFrançois Tigeot void intel_ring_reserved_space_reserve(struct intel_ringbuffer *ringbuf, int size) 2272a05eeebfSFrançois Tigeot { 2273a05eeebfSFrançois Tigeot WARN_ON(ringbuf->reserved_size); 2274a05eeebfSFrançois Tigeot WARN_ON(ringbuf->reserved_in_use); 2275a05eeebfSFrançois Tigeot 2276a05eeebfSFrançois Tigeot ringbuf->reserved_size = size; 2277a05eeebfSFrançois Tigeot } 2278a05eeebfSFrançois Tigeot 2279a05eeebfSFrançois Tigeot void intel_ring_reserved_space_cancel(struct intel_ringbuffer *ringbuf) 2280a05eeebfSFrançois Tigeot { 2281a05eeebfSFrançois Tigeot WARN_ON(ringbuf->reserved_in_use); 2282a05eeebfSFrançois Tigeot 2283a05eeebfSFrançois Tigeot ringbuf->reserved_size = 0; 2284a05eeebfSFrançois Tigeot ringbuf->reserved_in_use = false; 2285a05eeebfSFrançois Tigeot } 2286a05eeebfSFrançois Tigeot 2287a05eeebfSFrançois Tigeot void intel_ring_reserved_space_use(struct intel_ringbuffer *ringbuf) 2288a05eeebfSFrançois Tigeot { 2289a05eeebfSFrançois Tigeot WARN_ON(ringbuf->reserved_in_use); 2290a05eeebfSFrançois Tigeot 2291a05eeebfSFrançois Tigeot ringbuf->reserved_in_use = true; 2292a05eeebfSFrançois Tigeot ringbuf->reserved_tail = ringbuf->tail; 2293a05eeebfSFrançois Tigeot } 2294a05eeebfSFrançois Tigeot 2295a05eeebfSFrançois Tigeot void intel_ring_reserved_space_end(struct intel_ringbuffer *ringbuf) 2296a05eeebfSFrançois Tigeot { 2297a05eeebfSFrançois Tigeot WARN_ON(!ringbuf->reserved_in_use); 2298a05eeebfSFrançois Tigeot if (ringbuf->tail > ringbuf->reserved_tail) { 2299a05eeebfSFrançois Tigeot WARN(ringbuf->tail > ringbuf->reserved_tail + ringbuf->reserved_size, 2300a05eeebfSFrançois Tigeot "request reserved size too small: %d vs %d!\n", 2301a05eeebfSFrançois Tigeot ringbuf->tail - ringbuf->reserved_tail, ringbuf->reserved_size); 2302a05eeebfSFrançois Tigeot } else { 2303a05eeebfSFrançois Tigeot /* 2304a05eeebfSFrançois Tigeot * The ring was wrapped while the reserved space was in use. 2305a05eeebfSFrançois Tigeot * That means that some unknown amount of the ring tail was 2306a05eeebfSFrançois Tigeot * no-op filled and skipped. Thus simply adding the ring size 2307a05eeebfSFrançois Tigeot * to the tail and doing the above space check will not work. 2308a05eeebfSFrançois Tigeot * Rather than attempt to track how much tail was skipped, 2309a05eeebfSFrançois Tigeot * it is much simpler to say that also skipping the sanity 2310a05eeebfSFrançois Tigeot * check every once in a while is not a big issue. 2311a05eeebfSFrançois Tigeot */ 2312a05eeebfSFrançois Tigeot } 2313a05eeebfSFrançois Tigeot 2314a05eeebfSFrançois Tigeot ringbuf->reserved_size = 0; 2315a05eeebfSFrançois Tigeot ringbuf->reserved_in_use = false; 2316a05eeebfSFrançois Tigeot } 2317a05eeebfSFrançois Tigeot 2318a05eeebfSFrançois Tigeot static int __intel_ring_prepare(struct intel_engine_cs *ring, int bytes) 2319a05eeebfSFrançois Tigeot { 2320a05eeebfSFrançois Tigeot struct intel_ringbuffer *ringbuf = ring->buffer; 2321a05eeebfSFrançois Tigeot int remain_usable = ringbuf->effective_size - ringbuf->tail; 2322a05eeebfSFrançois Tigeot int remain_actual = ringbuf->size - ringbuf->tail; 2323a05eeebfSFrançois Tigeot int ret, total_bytes, wait_bytes = 0; 2324a05eeebfSFrançois Tigeot bool need_wrap = false; 2325a05eeebfSFrançois Tigeot 2326a05eeebfSFrançois Tigeot if (ringbuf->reserved_in_use) 2327a05eeebfSFrançois Tigeot total_bytes = bytes; 2328a05eeebfSFrançois Tigeot else 2329a05eeebfSFrançois Tigeot total_bytes = bytes + ringbuf->reserved_size; 2330a05eeebfSFrançois Tigeot 2331a05eeebfSFrançois Tigeot if (unlikely(bytes > remain_usable)) { 2332a05eeebfSFrançois Tigeot /* 2333a05eeebfSFrançois Tigeot * Not enough space for the basic request. So need to flush 2334a05eeebfSFrançois Tigeot * out the remainder and then wait for base + reserved. 2335a05eeebfSFrançois Tigeot */ 2336a05eeebfSFrançois Tigeot wait_bytes = remain_actual + total_bytes; 2337a05eeebfSFrançois Tigeot need_wrap = true; 2338a05eeebfSFrançois Tigeot } else { 2339a05eeebfSFrançois Tigeot if (unlikely(total_bytes > remain_usable)) { 2340a05eeebfSFrançois Tigeot /* 2341a05eeebfSFrançois Tigeot * The base request will fit but the reserved space 2342a05eeebfSFrançois Tigeot * falls off the end. So only need to to wait for the 2343a05eeebfSFrançois Tigeot * reserved size after flushing out the remainder. 2344a05eeebfSFrançois Tigeot */ 2345a05eeebfSFrançois Tigeot wait_bytes = remain_actual + ringbuf->reserved_size; 2346a05eeebfSFrançois Tigeot need_wrap = true; 2347a05eeebfSFrançois Tigeot } else if (total_bytes > ringbuf->space) { 2348a05eeebfSFrançois Tigeot /* No wrapping required, just waiting. */ 2349a05eeebfSFrançois Tigeot wait_bytes = total_bytes; 2350a05eeebfSFrançois Tigeot } 2351a05eeebfSFrançois Tigeot } 2352a05eeebfSFrançois Tigeot 2353a05eeebfSFrançois Tigeot if (wait_bytes) { 2354a05eeebfSFrançois Tigeot ret = ring_wait_for_space(ring, wait_bytes); 2355a2fdbec6SFrançois Tigeot if (unlikely(ret)) 2356a2fdbec6SFrançois Tigeot return ret; 2357a05eeebfSFrançois Tigeot 2358a05eeebfSFrançois Tigeot if (need_wrap) 2359a05eeebfSFrançois Tigeot __wrap_ring_buffer(ringbuf); 2360a2fdbec6SFrançois Tigeot } 2361a2fdbec6SFrançois Tigeot 2362a2fdbec6SFrançois Tigeot return 0; 2363a2fdbec6SFrançois Tigeot } 2364a2fdbec6SFrançois Tigeot 2365a05eeebfSFrançois Tigeot int intel_ring_begin(struct drm_i915_gem_request *req, 2366e3adcf8fSFrançois Tigeot int num_dwords) 2367e3adcf8fSFrançois Tigeot { 2368a05eeebfSFrançois Tigeot struct intel_engine_cs *ring; 2369a05eeebfSFrançois Tigeot struct drm_i915_private *dev_priv; 2370e3adcf8fSFrançois Tigeot int ret; 2371e3adcf8fSFrançois Tigeot 2372a05eeebfSFrançois Tigeot WARN_ON(req == NULL); 2373a05eeebfSFrançois Tigeot ring = req->ring; 2374a05eeebfSFrançois Tigeot dev_priv = ring->dev->dev_private; 2375a05eeebfSFrançois Tigeot 2376a2fdbec6SFrançois Tigeot ret = i915_gem_check_wedge(&dev_priv->gpu_error, 2377a2fdbec6SFrançois Tigeot dev_priv->mm.interruptible); 2378245593daSFrançois Tigeot if (ret) 2379245593daSFrançois Tigeot return ret; 2380e3adcf8fSFrançois Tigeot 23819edbd4a0SFrançois Tigeot ret = __intel_ring_prepare(ring, num_dwords * sizeof(uint32_t)); 23829edbd4a0SFrançois Tigeot if (ret) 23839edbd4a0SFrançois Tigeot return ret; 23849edbd4a0SFrançois Tigeot 2385ba55f2f5SFrançois Tigeot ring->buffer->space -= num_dwords * sizeof(uint32_t); 23869edbd4a0SFrançois Tigeot return 0; 23879edbd4a0SFrançois Tigeot } 23889edbd4a0SFrançois Tigeot 23899edbd4a0SFrançois Tigeot /* Align the ring tail to a cacheline boundary */ 2390a05eeebfSFrançois Tigeot int intel_ring_cacheline_align(struct drm_i915_gem_request *req) 23919edbd4a0SFrançois Tigeot { 2392a05eeebfSFrançois Tigeot struct intel_engine_cs *ring = req->ring; 2393ba55f2f5SFrançois Tigeot int num_dwords = (ring->buffer->tail & (CACHELINE_BYTES - 1)) / sizeof(uint32_t); 23949edbd4a0SFrançois Tigeot int ret; 23959edbd4a0SFrançois Tigeot 23969edbd4a0SFrançois Tigeot if (num_dwords == 0) 23979edbd4a0SFrançois Tigeot return 0; 23989edbd4a0SFrançois Tigeot 2399ba55f2f5SFrançois Tigeot num_dwords = CACHELINE_BYTES / sizeof(uint32_t) - num_dwords; 2400a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, num_dwords); 24019edbd4a0SFrançois Tigeot if (ret) 24029edbd4a0SFrançois Tigeot return ret; 24039edbd4a0SFrançois Tigeot 24049edbd4a0SFrançois Tigeot while (num_dwords--) 24059edbd4a0SFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 24069edbd4a0SFrançois Tigeot 24079edbd4a0SFrançois Tigeot intel_ring_advance(ring); 24089edbd4a0SFrançois Tigeot 24099edbd4a0SFrançois Tigeot return 0; 2410e3adcf8fSFrançois Tigeot } 2411e3adcf8fSFrançois Tigeot 2412ba55f2f5SFrançois Tigeot void intel_ring_init_seqno(struct intel_engine_cs *ring, u32 seqno) 2413a2fdbec6SFrançois Tigeot { 241424edb884SFrançois Tigeot struct drm_device *dev = ring->dev; 241524edb884SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 2416a2fdbec6SFrançois Tigeot 241724edb884SFrançois Tigeot if (INTEL_INFO(dev)->gen == 6 || INTEL_INFO(dev)->gen == 7) { 2418a2fdbec6SFrançois Tigeot I915_WRITE(RING_SYNC_0(ring->mmio_base), 0); 2419a2fdbec6SFrançois Tigeot I915_WRITE(RING_SYNC_1(ring->mmio_base), 0); 242024edb884SFrançois Tigeot if (HAS_VEBOX(dev)) 24219edbd4a0SFrançois Tigeot I915_WRITE(RING_SYNC_2(ring->mmio_base), 0); 2422e3adcf8fSFrançois Tigeot } 2423e3adcf8fSFrançois Tigeot 2424a2fdbec6SFrançois Tigeot ring->set_seqno(ring, seqno); 24255d0b1887SFrançois Tigeot ring->hangcheck.seqno = seqno; 2426e3adcf8fSFrançois Tigeot } 2427e3adcf8fSFrançois Tigeot 2428ba55f2f5SFrançois Tigeot static void gen6_bsd_ring_write_tail(struct intel_engine_cs *ring, 2429f4e1c372SFrançois Tigeot u32 value) 2430e3adcf8fSFrançois Tigeot { 2431ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = ring->dev->dev_private; 2432e3adcf8fSFrançois Tigeot 2433e3adcf8fSFrançois Tigeot /* Every tail move must follow the sequence below */ 2434f4e1c372SFrançois Tigeot 2435f4e1c372SFrançois Tigeot /* Disable notification that the ring is IDLE. The GT 2436f4e1c372SFrançois Tigeot * will then assume that it is busy and bring it out of rc6. 2437f4e1c372SFrançois Tigeot */ 2438e3adcf8fSFrançois Tigeot I915_WRITE(GEN6_BSD_SLEEP_PSMI_CONTROL, 2439f4e1c372SFrançois Tigeot _MASKED_BIT_ENABLE(GEN6_BSD_SLEEP_MSG_DISABLE)); 2440e3adcf8fSFrançois Tigeot 2441f4e1c372SFrançois Tigeot /* Clear the context id. Here be magic! */ 2442f4e1c372SFrançois Tigeot I915_WRITE64(GEN6_BSD_RNCID, 0x0); 2443e3adcf8fSFrançois Tigeot 2444f4e1c372SFrançois Tigeot /* Wait for the ring not to be idle, i.e. for it to wake up. */ 2445f4e1c372SFrançois Tigeot if (wait_for((I915_READ(GEN6_BSD_SLEEP_PSMI_CONTROL) & 2446f4e1c372SFrançois Tigeot GEN6_BSD_SLEEP_INDICATOR) == 0, 2447f4e1c372SFrançois Tigeot 50)) 2448f4e1c372SFrançois Tigeot DRM_ERROR("timed out waiting for the BSD ring to wake up\n"); 2449f4e1c372SFrançois Tigeot 2450f4e1c372SFrançois Tigeot /* Now that the ring is fully powered up, update the tail */ 2451e3adcf8fSFrançois Tigeot I915_WRITE_TAIL(ring, value); 2452f4e1c372SFrançois Tigeot POSTING_READ(RING_TAIL(ring->mmio_base)); 2453f4e1c372SFrançois Tigeot 2454f4e1c372SFrançois Tigeot /* Let the ring send IDLE messages to the GT again, 2455f4e1c372SFrançois Tigeot * and so let it sleep to conserve power when idle. 2456f4e1c372SFrançois Tigeot */ 2457e3adcf8fSFrançois Tigeot I915_WRITE(GEN6_BSD_SLEEP_PSMI_CONTROL, 2458f4e1c372SFrançois Tigeot _MASKED_BIT_DISABLE(GEN6_BSD_SLEEP_MSG_DISABLE)); 2459e3adcf8fSFrançois Tigeot } 2460e3adcf8fSFrançois Tigeot 2461a05eeebfSFrançois Tigeot static int gen6_bsd_ring_flush(struct drm_i915_gem_request *req, 2462b5c29a34SFrançois Tigeot u32 invalidate, u32 flush) 2463e3adcf8fSFrançois Tigeot { 2464a05eeebfSFrançois Tigeot struct intel_engine_cs *ring = req->ring; 2465e3adcf8fSFrançois Tigeot uint32_t cmd; 2466e3adcf8fSFrançois Tigeot int ret; 2467e3adcf8fSFrançois Tigeot 2468a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 4); 2469e3adcf8fSFrançois Tigeot if (ret) 2470e3adcf8fSFrançois Tigeot return ret; 2471e3adcf8fSFrançois Tigeot 2472e3adcf8fSFrançois Tigeot cmd = MI_FLUSH_DW; 24739edbd4a0SFrançois Tigeot if (INTEL_INFO(ring->dev)->gen >= 8) 24749edbd4a0SFrançois Tigeot cmd += 1; 24752c9916cdSFrançois Tigeot 24762c9916cdSFrançois Tigeot /* We always require a command barrier so that subsequent 24772c9916cdSFrançois Tigeot * commands, such as breadcrumb interrupts, are strictly ordered 24782c9916cdSFrançois Tigeot * wrt the contents of the write cache being flushed to memory 24792c9916cdSFrançois Tigeot * (and thus being coherent from the CPU). 24802c9916cdSFrançois Tigeot */ 24812c9916cdSFrançois Tigeot cmd |= MI_FLUSH_DW_STORE_INDEX | MI_FLUSH_DW_OP_STOREDW; 24822c9916cdSFrançois Tigeot 2483b5c29a34SFrançois Tigeot /* 2484b5c29a34SFrançois Tigeot * Bspec vol 1c.5 - video engine command streamer: 2485b5c29a34SFrançois Tigeot * "If ENABLED, all TLBs will be invalidated once the flush 2486b5c29a34SFrançois Tigeot * operation is complete. This bit is only valid when the 2487b5c29a34SFrançois Tigeot * Post-Sync Operation field is a value of 1h or 3h." 2488b5c29a34SFrançois Tigeot */ 2489e3adcf8fSFrançois Tigeot if (invalidate & I915_GEM_GPU_DOMAINS) 24902c9916cdSFrançois Tigeot cmd |= MI_INVALIDATE_TLB | MI_INVALIDATE_BSD; 24912c9916cdSFrançois Tigeot 2492e3adcf8fSFrançois Tigeot intel_ring_emit(ring, cmd); 2493b5c29a34SFrançois Tigeot intel_ring_emit(ring, I915_GEM_HWS_SCRATCH_ADDR | MI_FLUSH_DW_USE_GTT); 24949edbd4a0SFrançois Tigeot if (INTEL_INFO(ring->dev)->gen >= 8) { 24959edbd4a0SFrançois Tigeot intel_ring_emit(ring, 0); /* upper addr */ 24969edbd4a0SFrançois Tigeot intel_ring_emit(ring, 0); /* value */ 24979edbd4a0SFrançois Tigeot } else { 24989edbd4a0SFrançois Tigeot intel_ring_emit(ring, 0); 24999edbd4a0SFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 25009edbd4a0SFrançois Tigeot } 25019edbd4a0SFrançois Tigeot intel_ring_advance(ring); 25029edbd4a0SFrançois Tigeot return 0; 25039edbd4a0SFrançois Tigeot } 25049edbd4a0SFrançois Tigeot 25059edbd4a0SFrançois Tigeot static int 2506a05eeebfSFrançois Tigeot gen8_ring_dispatch_execbuffer(struct drm_i915_gem_request *req, 2507ba55f2f5SFrançois Tigeot u64 offset, u32 len, 2508477eb7f9SFrançois Tigeot unsigned dispatch_flags) 25099edbd4a0SFrançois Tigeot { 2510a05eeebfSFrançois Tigeot struct intel_engine_cs *ring = req->ring; 2511477eb7f9SFrançois Tigeot bool ppgtt = USES_PPGTT(ring->dev) && 2512477eb7f9SFrançois Tigeot !(dispatch_flags & I915_DISPATCH_SECURE); 25139edbd4a0SFrançois Tigeot int ret; 25149edbd4a0SFrançois Tigeot 2515a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 4); 25169edbd4a0SFrançois Tigeot if (ret) 25179edbd4a0SFrançois Tigeot return ret; 25189edbd4a0SFrançois Tigeot 25199edbd4a0SFrançois Tigeot /* FIXME(BDW): Address space and security selectors. */ 2520a05eeebfSFrançois Tigeot intel_ring_emit(ring, MI_BATCH_BUFFER_START_GEN8 | (ppgtt<<8) | 2521a05eeebfSFrançois Tigeot (dispatch_flags & I915_DISPATCH_RS ? 2522a05eeebfSFrançois Tigeot MI_BATCH_RESOURCE_STREAMER : 0)); 2523ba55f2f5SFrançois Tigeot intel_ring_emit(ring, lower_32_bits(offset)); 2524ba55f2f5SFrançois Tigeot intel_ring_emit(ring, upper_32_bits(offset)); 2525e3adcf8fSFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 2526e3adcf8fSFrançois Tigeot intel_ring_advance(ring); 25279edbd4a0SFrançois Tigeot 2528e3adcf8fSFrançois Tigeot return 0; 2529e3adcf8fSFrançois Tigeot } 2530e3adcf8fSFrançois Tigeot 2531e3adcf8fSFrançois Tigeot static int 2532a05eeebfSFrançois Tigeot hsw_ring_dispatch_execbuffer(struct drm_i915_gem_request *req, 2533ba55f2f5SFrançois Tigeot u64 offset, u32 len, 2534477eb7f9SFrançois Tigeot unsigned dispatch_flags) 2535e3adcf8fSFrançois Tigeot { 2536a05eeebfSFrançois Tigeot struct intel_engine_cs *ring = req->ring; 2537e3adcf8fSFrançois Tigeot int ret; 2538e3adcf8fSFrançois Tigeot 2539a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 2); 2540e3adcf8fSFrançois Tigeot if (ret) 2541e3adcf8fSFrançois Tigeot return ret; 2542e3adcf8fSFrançois Tigeot 2543b5c29a34SFrançois Tigeot intel_ring_emit(ring, 25441b13d190SFrançois Tigeot MI_BATCH_BUFFER_START | 2545477eb7f9SFrançois Tigeot (dispatch_flags & I915_DISPATCH_SECURE ? 2546a05eeebfSFrançois Tigeot 0 : MI_BATCH_PPGTT_HSW | MI_BATCH_NON_SECURE_HSW) | 2547a05eeebfSFrançois Tigeot (dispatch_flags & I915_DISPATCH_RS ? 2548a05eeebfSFrançois Tigeot MI_BATCH_RESOURCE_STREAMER : 0)); 2549b5c29a34SFrançois Tigeot /* bit0-7 is the length on GEN6+ */ 2550b5c29a34SFrançois Tigeot intel_ring_emit(ring, offset); 2551b5c29a34SFrançois Tigeot intel_ring_advance(ring); 2552b5c29a34SFrançois Tigeot 2553b5c29a34SFrançois Tigeot return 0; 2554b5c29a34SFrançois Tigeot } 2555b5c29a34SFrançois Tigeot 2556b5c29a34SFrançois Tigeot static int 2557a05eeebfSFrançois Tigeot gen6_ring_dispatch_execbuffer(struct drm_i915_gem_request *req, 2558ba55f2f5SFrançois Tigeot u64 offset, u32 len, 2559477eb7f9SFrançois Tigeot unsigned dispatch_flags) 2560b5c29a34SFrançois Tigeot { 2561a05eeebfSFrançois Tigeot struct intel_engine_cs *ring = req->ring; 2562b5c29a34SFrançois Tigeot int ret; 2563b5c29a34SFrançois Tigeot 2564a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 2); 2565b5c29a34SFrançois Tigeot if (ret) 2566b5c29a34SFrançois Tigeot return ret; 2567b5c29a34SFrançois Tigeot 2568b5c29a34SFrançois Tigeot intel_ring_emit(ring, 2569b5c29a34SFrançois Tigeot MI_BATCH_BUFFER_START | 2570477eb7f9SFrançois Tigeot (dispatch_flags & I915_DISPATCH_SECURE ? 2571477eb7f9SFrançois Tigeot 0 : MI_BATCH_NON_SECURE_I965)); 2572e3adcf8fSFrançois Tigeot /* bit0-7 is the length on GEN6+ */ 2573e3adcf8fSFrançois Tigeot intel_ring_emit(ring, offset); 2574e3adcf8fSFrançois Tigeot intel_ring_advance(ring); 2575e3adcf8fSFrançois Tigeot 2576e3adcf8fSFrançois Tigeot return 0; 2577e3adcf8fSFrançois Tigeot } 2578e3adcf8fSFrançois Tigeot 2579e3adcf8fSFrançois Tigeot /* Blitter support (SandyBridge+) */ 2580e3adcf8fSFrançois Tigeot 2581a05eeebfSFrançois Tigeot static int gen6_ring_flush(struct drm_i915_gem_request *req, 2582b5c29a34SFrançois Tigeot u32 invalidate, u32 flush) 2583e3adcf8fSFrançois Tigeot { 2584a05eeebfSFrançois Tigeot struct intel_engine_cs *ring = req->ring; 25855d0b1887SFrançois Tigeot struct drm_device *dev = ring->dev; 2586e3adcf8fSFrançois Tigeot uint32_t cmd; 2587e3adcf8fSFrançois Tigeot int ret; 2588e3adcf8fSFrançois Tigeot 2589a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 4); 2590e3adcf8fSFrançois Tigeot if (ret) 2591e3adcf8fSFrançois Tigeot return ret; 2592e3adcf8fSFrançois Tigeot 2593e3adcf8fSFrançois Tigeot cmd = MI_FLUSH_DW; 2594477eb7f9SFrançois Tigeot if (INTEL_INFO(dev)->gen >= 8) 25959edbd4a0SFrançois Tigeot cmd += 1; 25962c9916cdSFrançois Tigeot 25972c9916cdSFrançois Tigeot /* We always require a command barrier so that subsequent 25982c9916cdSFrançois Tigeot * commands, such as breadcrumb interrupts, are strictly ordered 25992c9916cdSFrançois Tigeot * wrt the contents of the write cache being flushed to memory 26002c9916cdSFrançois Tigeot * (and thus being coherent from the CPU). 26012c9916cdSFrançois Tigeot */ 26022c9916cdSFrançois Tigeot cmd |= MI_FLUSH_DW_STORE_INDEX | MI_FLUSH_DW_OP_STOREDW; 26032c9916cdSFrançois Tigeot 2604b5c29a34SFrançois Tigeot /* 2605b5c29a34SFrançois Tigeot * Bspec vol 1c.3 - blitter engine command streamer: 2606b5c29a34SFrançois Tigeot * "If ENABLED, all TLBs will be invalidated once the flush 2607b5c29a34SFrançois Tigeot * operation is complete. This bit is only valid when the 2608b5c29a34SFrançois Tigeot * Post-Sync Operation field is a value of 1h or 3h." 2609b5c29a34SFrançois Tigeot */ 2610e3adcf8fSFrançois Tigeot if (invalidate & I915_GEM_DOMAIN_RENDER) 26112c9916cdSFrançois Tigeot cmd |= MI_INVALIDATE_TLB; 2612e3adcf8fSFrançois Tigeot intel_ring_emit(ring, cmd); 2613b5c29a34SFrançois Tigeot intel_ring_emit(ring, I915_GEM_HWS_SCRATCH_ADDR | MI_FLUSH_DW_USE_GTT); 2614477eb7f9SFrançois Tigeot if (INTEL_INFO(dev)->gen >= 8) { 26159edbd4a0SFrançois Tigeot intel_ring_emit(ring, 0); /* upper addr */ 26169edbd4a0SFrançois Tigeot intel_ring_emit(ring, 0); /* value */ 26179edbd4a0SFrançois Tigeot } else { 2618e3adcf8fSFrançois Tigeot intel_ring_emit(ring, 0); 2619e3adcf8fSFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 26209edbd4a0SFrançois Tigeot } 2621e3adcf8fSFrançois Tigeot intel_ring_advance(ring); 26225d0b1887SFrançois Tigeot 2623e3adcf8fSFrançois Tigeot return 0; 2624e3adcf8fSFrançois Tigeot } 2625e3adcf8fSFrançois Tigeot 2626e3adcf8fSFrançois Tigeot int intel_init_render_ring_buffer(struct drm_device *dev) 2627e3adcf8fSFrançois Tigeot { 2628ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 2629ba55f2f5SFrançois Tigeot struct intel_engine_cs *ring = &dev_priv->ring[RCS]; 263024edb884SFrançois Tigeot struct drm_i915_gem_object *obj; 263124edb884SFrançois Tigeot int ret; 2632e3adcf8fSFrançois Tigeot 2633686a02f1SFrançois Tigeot ring->name = "render ring"; 2634686a02f1SFrançois Tigeot ring->id = RCS; 2635686a02f1SFrançois Tigeot ring->mmio_base = RENDER_RING_BASE; 2636686a02f1SFrançois Tigeot 263724edb884SFrançois Tigeot if (INTEL_INFO(dev)->gen >= 8) { 263824edb884SFrançois Tigeot if (i915_semaphore_is_enabled(dev)) { 263924edb884SFrançois Tigeot obj = i915_gem_alloc_object(dev, 4096); 264024edb884SFrançois Tigeot if (obj == NULL) { 264124edb884SFrançois Tigeot DRM_ERROR("Failed to allocate semaphore bo. Disabling semaphores\n"); 264224edb884SFrançois Tigeot i915.semaphores = 0; 264324edb884SFrançois Tigeot } else { 264424edb884SFrançois Tigeot i915_gem_object_set_cache_level(obj, I915_CACHE_LLC); 264524edb884SFrançois Tigeot ret = i915_gem_obj_ggtt_pin(obj, 0, PIN_NONBLOCK); 264624edb884SFrançois Tigeot if (ret != 0) { 264724edb884SFrançois Tigeot drm_gem_object_unreference(&obj->base); 264824edb884SFrançois Tigeot DRM_ERROR("Failed to pin semaphore bo. Disabling semaphores\n"); 264924edb884SFrançois Tigeot i915.semaphores = 0; 265024edb884SFrançois Tigeot } else 265124edb884SFrançois Tigeot dev_priv->semaphore_obj = obj; 265224edb884SFrançois Tigeot } 265324edb884SFrançois Tigeot } 26542c9916cdSFrançois Tigeot 26552c9916cdSFrançois Tigeot ring->init_context = intel_rcs_ctx_init; 265624edb884SFrançois Tigeot ring->add_request = gen6_add_request; 265724edb884SFrançois Tigeot ring->flush = gen8_render_ring_flush; 265824edb884SFrançois Tigeot ring->irq_get = gen8_ring_get_irq; 265924edb884SFrançois Tigeot ring->irq_put = gen8_ring_put_irq; 266024edb884SFrançois Tigeot ring->irq_enable_mask = GT_RENDER_USER_INTERRUPT; 266124edb884SFrançois Tigeot ring->get_seqno = gen6_ring_get_seqno; 266224edb884SFrançois Tigeot ring->set_seqno = ring_set_seqno; 266324edb884SFrançois Tigeot if (i915_semaphore_is_enabled(dev)) { 266424edb884SFrançois Tigeot WARN_ON(!dev_priv->semaphore_obj); 266524edb884SFrançois Tigeot ring->semaphore.sync_to = gen8_ring_sync; 266624edb884SFrançois Tigeot ring->semaphore.signal = gen8_rcs_signal; 266724edb884SFrançois Tigeot GEN8_RING_SEMAPHORE_INIT; 266824edb884SFrançois Tigeot } 266924edb884SFrançois Tigeot } else if (INTEL_INFO(dev)->gen >= 6) { 2670*352ff8bdSFrançois Tigeot ring->init_context = intel_rcs_ctx_init; 2671e3adcf8fSFrançois Tigeot ring->add_request = gen6_add_request; 2672b5c29a34SFrançois Tigeot ring->flush = gen7_render_ring_flush; 2673b5c29a34SFrançois Tigeot if (INTEL_INFO(dev)->gen == 6) 2674e3adcf8fSFrançois Tigeot ring->flush = gen6_render_ring_flush; 2675686a02f1SFrançois Tigeot ring->irq_get = gen6_ring_get_irq; 2676686a02f1SFrançois Tigeot ring->irq_put = gen6_ring_put_irq; 26775d0b1887SFrançois Tigeot ring->irq_enable_mask = GT_RENDER_USER_INTERRUPT; 2678e3adcf8fSFrançois Tigeot ring->get_seqno = gen6_ring_get_seqno; 2679a2fdbec6SFrançois Tigeot ring->set_seqno = ring_set_seqno; 268024edb884SFrançois Tigeot if (i915_semaphore_is_enabled(dev)) { 2681ba55f2f5SFrançois Tigeot ring->semaphore.sync_to = gen6_ring_sync; 2682ba55f2f5SFrançois Tigeot ring->semaphore.signal = gen6_signal; 2683ba55f2f5SFrançois Tigeot /* 268424edb884SFrançois Tigeot * The current semaphore is only applied on pre-gen8 268524edb884SFrançois Tigeot * platform. And there is no VCS2 ring on the pre-gen8 268624edb884SFrançois Tigeot * platform. So the semaphore between RCS and VCS2 is 268724edb884SFrançois Tigeot * initialized as INVALID. Gen8 will initialize the 268824edb884SFrançois Tigeot * sema between VCS2 and RCS later. 2689ba55f2f5SFrançois Tigeot */ 2690ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[RCS] = MI_SEMAPHORE_SYNC_INVALID; 2691ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[VCS] = MI_SEMAPHORE_SYNC_RV; 2692ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[BCS] = MI_SEMAPHORE_SYNC_RB; 2693ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[VECS] = MI_SEMAPHORE_SYNC_RVE; 2694ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[VCS2] = MI_SEMAPHORE_SYNC_INVALID; 2695ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[RCS] = GEN6_NOSYNC; 2696ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[VCS] = GEN6_VRSYNC; 2697ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[BCS] = GEN6_BRSYNC; 2698ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[VECS] = GEN6_VERSYNC; 2699ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[VCS2] = GEN6_NOSYNC; 270024edb884SFrançois Tigeot } 2701e3adcf8fSFrançois Tigeot } else if (IS_GEN5(dev)) { 2702e3adcf8fSFrançois Tigeot ring->add_request = pc_render_add_request; 2703686a02f1SFrançois Tigeot ring->flush = gen4_render_ring_flush; 2704e3adcf8fSFrançois Tigeot ring->get_seqno = pc_render_get_seqno; 2705a2fdbec6SFrançois Tigeot ring->set_seqno = pc_render_set_seqno; 2706686a02f1SFrançois Tigeot ring->irq_get = gen5_ring_get_irq; 2707686a02f1SFrançois Tigeot ring->irq_put = gen5_ring_put_irq; 27085d0b1887SFrançois Tigeot ring->irq_enable_mask = GT_RENDER_USER_INTERRUPT | 27095d0b1887SFrançois Tigeot GT_RENDER_PIPECTL_NOTIFY_INTERRUPT; 2710686a02f1SFrançois Tigeot } else { 2711686a02f1SFrançois Tigeot ring->add_request = i9xx_add_request; 2712686a02f1SFrançois Tigeot if (INTEL_INFO(dev)->gen < 4) 2713686a02f1SFrançois Tigeot ring->flush = gen2_render_ring_flush; 2714686a02f1SFrançois Tigeot else 2715686a02f1SFrançois Tigeot ring->flush = gen4_render_ring_flush; 2716686a02f1SFrançois Tigeot ring->get_seqno = ring_get_seqno; 2717a2fdbec6SFrançois Tigeot ring->set_seqno = ring_set_seqno; 2718686a02f1SFrançois Tigeot if (IS_GEN2(dev)) { 2719686a02f1SFrançois Tigeot ring->irq_get = i8xx_ring_get_irq; 2720686a02f1SFrançois Tigeot ring->irq_put = i8xx_ring_put_irq; 2721686a02f1SFrançois Tigeot } else { 2722686a02f1SFrançois Tigeot ring->irq_get = i9xx_ring_get_irq; 2723686a02f1SFrançois Tigeot ring->irq_put = i9xx_ring_put_irq; 2724e3adcf8fSFrançois Tigeot } 2725686a02f1SFrançois Tigeot ring->irq_enable_mask = I915_USER_INTERRUPT; 2726686a02f1SFrançois Tigeot } 2727686a02f1SFrançois Tigeot ring->write_tail = ring_write_tail; 272824edb884SFrançois Tigeot 2729b5c29a34SFrançois Tigeot if (IS_HASWELL(dev)) 2730b5c29a34SFrançois Tigeot ring->dispatch_execbuffer = hsw_ring_dispatch_execbuffer; 27319edbd4a0SFrançois Tigeot else if (IS_GEN8(dev)) 27329edbd4a0SFrançois Tigeot ring->dispatch_execbuffer = gen8_ring_dispatch_execbuffer; 2733b5c29a34SFrançois Tigeot else if (INTEL_INFO(dev)->gen >= 6) 2734686a02f1SFrançois Tigeot ring->dispatch_execbuffer = gen6_ring_dispatch_execbuffer; 2735686a02f1SFrançois Tigeot else if (INTEL_INFO(dev)->gen >= 4) 2736686a02f1SFrançois Tigeot ring->dispatch_execbuffer = i965_dispatch_execbuffer; 2737686a02f1SFrançois Tigeot else if (IS_I830(dev) || IS_845G(dev)) 2738686a02f1SFrançois Tigeot ring->dispatch_execbuffer = i830_dispatch_execbuffer; 2739686a02f1SFrançois Tigeot else 2740686a02f1SFrançois Tigeot ring->dispatch_execbuffer = i915_dispatch_execbuffer; 27412c9916cdSFrançois Tigeot ring->init_hw = init_render_ring; 2742686a02f1SFrançois Tigeot ring->cleanup = render_ring_cleanup; 2743e3adcf8fSFrançois Tigeot 2744b5c29a34SFrançois Tigeot /* Workaround batchbuffer to combat CS tlb bug. */ 2745b5c29a34SFrançois Tigeot if (HAS_BROKEN_CS_TLB(dev)) { 274624edb884SFrançois Tigeot obj = i915_gem_alloc_object(dev, I830_WA_SIZE); 2747b5c29a34SFrançois Tigeot if (obj == NULL) { 2748b5c29a34SFrançois Tigeot DRM_ERROR("Failed to allocate batch bo\n"); 2749b5c29a34SFrançois Tigeot return -ENOMEM; 2750b5c29a34SFrançois Tigeot } 2751b5c29a34SFrançois Tigeot 2752ba55f2f5SFrançois Tigeot ret = i915_gem_obj_ggtt_pin(obj, 0, 0); 2753b5c29a34SFrançois Tigeot if (ret != 0) { 2754b5c29a34SFrançois Tigeot drm_gem_object_unreference(&obj->base); 2755b5c29a34SFrançois Tigeot DRM_ERROR("Failed to ping batch bo\n"); 2756b5c29a34SFrançois Tigeot return ret; 2757b5c29a34SFrançois Tigeot } 2758b5c29a34SFrançois Tigeot 27599edbd4a0SFrançois Tigeot ring->scratch.obj = obj; 27609edbd4a0SFrançois Tigeot ring->scratch.gtt_offset = i915_gem_obj_ggtt_offset(obj); 2761e3adcf8fSFrançois Tigeot } 2762e3adcf8fSFrançois Tigeot 27632c9916cdSFrançois Tigeot ret = intel_init_ring_buffer(dev, ring); 2764b5c29a34SFrançois Tigeot if (ret) 27652c9916cdSFrançois Tigeot return ret; 27662c9916cdSFrançois Tigeot 27672c9916cdSFrançois Tigeot if (INTEL_INFO(dev)->gen >= 5) { 27682c9916cdSFrançois Tigeot ret = intel_init_pipe_control(ring); 27692c9916cdSFrançois Tigeot if (ret) 27702c9916cdSFrançois Tigeot return ret; 2771b5c29a34SFrançois Tigeot } 2772b5c29a34SFrançois Tigeot 2773e3adcf8fSFrançois Tigeot return 0; 2774e3adcf8fSFrançois Tigeot } 2775e3adcf8fSFrançois Tigeot 2776e3adcf8fSFrançois Tigeot int intel_init_bsd_ring_buffer(struct drm_device *dev) 2777e3adcf8fSFrançois Tigeot { 2778ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 2779ba55f2f5SFrançois Tigeot struct intel_engine_cs *ring = &dev_priv->ring[VCS]; 2780e3adcf8fSFrançois Tigeot 2781686a02f1SFrançois Tigeot ring->name = "bsd ring"; 2782686a02f1SFrançois Tigeot ring->id = VCS; 2783686a02f1SFrançois Tigeot 2784686a02f1SFrançois Tigeot ring->write_tail = ring_write_tail; 27859edbd4a0SFrançois Tigeot if (INTEL_INFO(dev)->gen >= 6) { 2786686a02f1SFrançois Tigeot ring->mmio_base = GEN6_BSD_RING_BASE; 2787686a02f1SFrançois Tigeot /* gen6 bsd needs a special wa for tail updates */ 2788686a02f1SFrançois Tigeot if (IS_GEN6(dev)) 2789686a02f1SFrançois Tigeot ring->write_tail = gen6_bsd_ring_write_tail; 27905d0b1887SFrançois Tigeot ring->flush = gen6_bsd_ring_flush; 2791686a02f1SFrançois Tigeot ring->add_request = gen6_add_request; 2792686a02f1SFrançois Tigeot ring->get_seqno = gen6_ring_get_seqno; 2793a2fdbec6SFrançois Tigeot ring->set_seqno = ring_set_seqno; 27949edbd4a0SFrançois Tigeot if (INTEL_INFO(dev)->gen >= 8) { 27959edbd4a0SFrançois Tigeot ring->irq_enable_mask = 27969edbd4a0SFrançois Tigeot GT_RENDER_USER_INTERRUPT << GEN8_VCS1_IRQ_SHIFT; 27979edbd4a0SFrançois Tigeot ring->irq_get = gen8_ring_get_irq; 27989edbd4a0SFrançois Tigeot ring->irq_put = gen8_ring_put_irq; 27999edbd4a0SFrançois Tigeot ring->dispatch_execbuffer = 28009edbd4a0SFrançois Tigeot gen8_ring_dispatch_execbuffer; 280124edb884SFrançois Tigeot if (i915_semaphore_is_enabled(dev)) { 280224edb884SFrançois Tigeot ring->semaphore.sync_to = gen8_ring_sync; 280324edb884SFrançois Tigeot ring->semaphore.signal = gen8_xcs_signal; 280424edb884SFrançois Tigeot GEN8_RING_SEMAPHORE_INIT; 280524edb884SFrançois Tigeot } 28069edbd4a0SFrançois Tigeot } else { 28075d0b1887SFrançois Tigeot ring->irq_enable_mask = GT_BSD_USER_INTERRUPT; 2808686a02f1SFrançois Tigeot ring->irq_get = gen6_ring_get_irq; 2809686a02f1SFrançois Tigeot ring->irq_put = gen6_ring_put_irq; 28109edbd4a0SFrançois Tigeot ring->dispatch_execbuffer = 28119edbd4a0SFrançois Tigeot gen6_ring_dispatch_execbuffer; 281224edb884SFrançois Tigeot if (i915_semaphore_is_enabled(dev)) { 2813ba55f2f5SFrançois Tigeot ring->semaphore.sync_to = gen6_ring_sync; 2814ba55f2f5SFrançois Tigeot ring->semaphore.signal = gen6_signal; 2815ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[RCS] = MI_SEMAPHORE_SYNC_VR; 2816ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[VCS] = MI_SEMAPHORE_SYNC_INVALID; 2817ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[BCS] = MI_SEMAPHORE_SYNC_VB; 2818ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[VECS] = MI_SEMAPHORE_SYNC_VVE; 2819ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[VCS2] = MI_SEMAPHORE_SYNC_INVALID; 2820ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[RCS] = GEN6_RVSYNC; 2821ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[VCS] = GEN6_NOSYNC; 2822ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[BCS] = GEN6_BVSYNC; 2823ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[VECS] = GEN6_VEVSYNC; 2824ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[VCS2] = GEN6_NOSYNC; 282524edb884SFrançois Tigeot } 282624edb884SFrançois Tigeot } 2827686a02f1SFrançois Tigeot } else { 2828686a02f1SFrançois Tigeot ring->mmio_base = BSD_RING_BASE; 2829686a02f1SFrançois Tigeot ring->flush = bsd_ring_flush; 2830686a02f1SFrançois Tigeot ring->add_request = i9xx_add_request; 2831686a02f1SFrançois Tigeot ring->get_seqno = ring_get_seqno; 2832a2fdbec6SFrançois Tigeot ring->set_seqno = ring_set_seqno; 2833686a02f1SFrançois Tigeot if (IS_GEN5(dev)) { 28345d0b1887SFrançois Tigeot ring->irq_enable_mask = ILK_BSD_USER_INTERRUPT; 2835686a02f1SFrançois Tigeot ring->irq_get = gen5_ring_get_irq; 2836686a02f1SFrançois Tigeot ring->irq_put = gen5_ring_put_irq; 2837686a02f1SFrançois Tigeot } else { 2838686a02f1SFrançois Tigeot ring->irq_enable_mask = I915_BSD_USER_INTERRUPT; 2839686a02f1SFrançois Tigeot ring->irq_get = i9xx_ring_get_irq; 2840686a02f1SFrançois Tigeot ring->irq_put = i9xx_ring_put_irq; 2841686a02f1SFrançois Tigeot } 2842686a02f1SFrançois Tigeot ring->dispatch_execbuffer = i965_dispatch_execbuffer; 2843686a02f1SFrançois Tigeot } 28442c9916cdSFrançois Tigeot ring->init_hw = init_ring_common; 2845e3adcf8fSFrançois Tigeot 2846e3adcf8fSFrançois Tigeot return intel_init_ring_buffer(dev, ring); 2847e3adcf8fSFrançois Tigeot } 2848e3adcf8fSFrançois Tigeot 2849ba55f2f5SFrançois Tigeot /** 2850477eb7f9SFrançois Tigeot * Initialize the second BSD ring (eg. Broadwell GT3, Skylake GT3) 2851ba55f2f5SFrançois Tigeot */ 2852ba55f2f5SFrançois Tigeot int intel_init_bsd2_ring_buffer(struct drm_device *dev) 2853ba55f2f5SFrançois Tigeot { 2854ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 2855ba55f2f5SFrançois Tigeot struct intel_engine_cs *ring = &dev_priv->ring[VCS2]; 2856ba55f2f5SFrançois Tigeot 285724edb884SFrançois Tigeot ring->name = "bsd2 ring"; 2858ba55f2f5SFrançois Tigeot ring->id = VCS2; 2859ba55f2f5SFrançois Tigeot 2860ba55f2f5SFrançois Tigeot ring->write_tail = ring_write_tail; 2861ba55f2f5SFrançois Tigeot ring->mmio_base = GEN8_BSD2_RING_BASE; 2862ba55f2f5SFrançois Tigeot ring->flush = gen6_bsd_ring_flush; 2863ba55f2f5SFrançois Tigeot ring->add_request = gen6_add_request; 2864ba55f2f5SFrançois Tigeot ring->get_seqno = gen6_ring_get_seqno; 2865ba55f2f5SFrançois Tigeot ring->set_seqno = ring_set_seqno; 2866ba55f2f5SFrançois Tigeot ring->irq_enable_mask = 2867ba55f2f5SFrançois Tigeot GT_RENDER_USER_INTERRUPT << GEN8_VCS2_IRQ_SHIFT; 2868ba55f2f5SFrançois Tigeot ring->irq_get = gen8_ring_get_irq; 2869ba55f2f5SFrançois Tigeot ring->irq_put = gen8_ring_put_irq; 2870ba55f2f5SFrançois Tigeot ring->dispatch_execbuffer = 2871ba55f2f5SFrançois Tigeot gen8_ring_dispatch_execbuffer; 287224edb884SFrançois Tigeot if (i915_semaphore_is_enabled(dev)) { 287324edb884SFrançois Tigeot ring->semaphore.sync_to = gen8_ring_sync; 287424edb884SFrançois Tigeot ring->semaphore.signal = gen8_xcs_signal; 287524edb884SFrançois Tigeot GEN8_RING_SEMAPHORE_INIT; 287624edb884SFrançois Tigeot } 28772c9916cdSFrançois Tigeot ring->init_hw = init_ring_common; 2878ba55f2f5SFrançois Tigeot 2879ba55f2f5SFrançois Tigeot return intel_init_ring_buffer(dev, ring); 2880ba55f2f5SFrançois Tigeot } 2881ba55f2f5SFrançois Tigeot 2882e3adcf8fSFrançois Tigeot int intel_init_blt_ring_buffer(struct drm_device *dev) 2883e3adcf8fSFrançois Tigeot { 2884ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 2885ba55f2f5SFrançois Tigeot struct intel_engine_cs *ring = &dev_priv->ring[BCS]; 2886e3adcf8fSFrançois Tigeot 2887686a02f1SFrançois Tigeot ring->name = "blitter ring"; 2888686a02f1SFrançois Tigeot ring->id = BCS; 2889686a02f1SFrançois Tigeot 2890686a02f1SFrançois Tigeot ring->mmio_base = BLT_RING_BASE; 2891686a02f1SFrançois Tigeot ring->write_tail = ring_write_tail; 28925d0b1887SFrançois Tigeot ring->flush = gen6_ring_flush; 2893686a02f1SFrançois Tigeot ring->add_request = gen6_add_request; 2894686a02f1SFrançois Tigeot ring->get_seqno = gen6_ring_get_seqno; 2895a2fdbec6SFrançois Tigeot ring->set_seqno = ring_set_seqno; 28969edbd4a0SFrançois Tigeot if (INTEL_INFO(dev)->gen >= 8) { 28979edbd4a0SFrançois Tigeot ring->irq_enable_mask = 28989edbd4a0SFrançois Tigeot GT_RENDER_USER_INTERRUPT << GEN8_BCS_IRQ_SHIFT; 28999edbd4a0SFrançois Tigeot ring->irq_get = gen8_ring_get_irq; 29009edbd4a0SFrançois Tigeot ring->irq_put = gen8_ring_put_irq; 29019edbd4a0SFrançois Tigeot ring->dispatch_execbuffer = gen8_ring_dispatch_execbuffer; 290224edb884SFrançois Tigeot if (i915_semaphore_is_enabled(dev)) { 290324edb884SFrançois Tigeot ring->semaphore.sync_to = gen8_ring_sync; 290424edb884SFrançois Tigeot ring->semaphore.signal = gen8_xcs_signal; 290524edb884SFrançois Tigeot GEN8_RING_SEMAPHORE_INIT; 290624edb884SFrançois Tigeot } 29079edbd4a0SFrançois Tigeot } else { 29085d0b1887SFrançois Tigeot ring->irq_enable_mask = GT_BLT_USER_INTERRUPT; 2909686a02f1SFrançois Tigeot ring->irq_get = gen6_ring_get_irq; 2910686a02f1SFrançois Tigeot ring->irq_put = gen6_ring_put_irq; 2911686a02f1SFrançois Tigeot ring->dispatch_execbuffer = gen6_ring_dispatch_execbuffer; 291224edb884SFrançois Tigeot if (i915_semaphore_is_enabled(dev)) { 2913ba55f2f5SFrançois Tigeot ring->semaphore.signal = gen6_signal; 291424edb884SFrançois Tigeot ring->semaphore.sync_to = gen6_ring_sync; 2915ba55f2f5SFrançois Tigeot /* 291624edb884SFrançois Tigeot * The current semaphore is only applied on pre-gen8 291724edb884SFrançois Tigeot * platform. And there is no VCS2 ring on the pre-gen8 291824edb884SFrançois Tigeot * platform. So the semaphore between BCS and VCS2 is 291924edb884SFrançois Tigeot * initialized as INVALID. Gen8 will initialize the 292024edb884SFrançois Tigeot * sema between BCS and VCS2 later. 2921ba55f2f5SFrançois Tigeot */ 2922ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[RCS] = MI_SEMAPHORE_SYNC_BR; 2923ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[VCS] = MI_SEMAPHORE_SYNC_BV; 2924ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[BCS] = MI_SEMAPHORE_SYNC_INVALID; 2925ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[VECS] = MI_SEMAPHORE_SYNC_BVE; 2926ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[VCS2] = MI_SEMAPHORE_SYNC_INVALID; 2927ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[RCS] = GEN6_RBSYNC; 2928ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[VCS] = GEN6_VBSYNC; 2929ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[BCS] = GEN6_NOSYNC; 2930ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[VECS] = GEN6_VEBSYNC; 2931ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[VCS2] = GEN6_NOSYNC; 293224edb884SFrançois Tigeot } 293324edb884SFrançois Tigeot } 29342c9916cdSFrançois Tigeot ring->init_hw = init_ring_common; 29355d0b1887SFrançois Tigeot 29365d0b1887SFrançois Tigeot return intel_init_ring_buffer(dev, ring); 29375d0b1887SFrançois Tigeot } 29385d0b1887SFrançois Tigeot 29395d0b1887SFrançois Tigeot int intel_init_vebox_ring_buffer(struct drm_device *dev) 29405d0b1887SFrançois Tigeot { 2941ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 2942ba55f2f5SFrançois Tigeot struct intel_engine_cs *ring = &dev_priv->ring[VECS]; 29435d0b1887SFrançois Tigeot 29445d0b1887SFrançois Tigeot ring->name = "video enhancement ring"; 29455d0b1887SFrançois Tigeot ring->id = VECS; 29465d0b1887SFrançois Tigeot 29475d0b1887SFrançois Tigeot ring->mmio_base = VEBOX_RING_BASE; 29485d0b1887SFrançois Tigeot ring->write_tail = ring_write_tail; 29495d0b1887SFrançois Tigeot ring->flush = gen6_ring_flush; 29505d0b1887SFrançois Tigeot ring->add_request = gen6_add_request; 29515d0b1887SFrançois Tigeot ring->get_seqno = gen6_ring_get_seqno; 29525d0b1887SFrançois Tigeot ring->set_seqno = ring_set_seqno; 29539edbd4a0SFrançois Tigeot 29549edbd4a0SFrançois Tigeot if (INTEL_INFO(dev)->gen >= 8) { 29559edbd4a0SFrançois Tigeot ring->irq_enable_mask = 29569edbd4a0SFrançois Tigeot GT_RENDER_USER_INTERRUPT << GEN8_VECS_IRQ_SHIFT; 29579edbd4a0SFrançois Tigeot ring->irq_get = gen8_ring_get_irq; 29589edbd4a0SFrançois Tigeot ring->irq_put = gen8_ring_put_irq; 29599edbd4a0SFrançois Tigeot ring->dispatch_execbuffer = gen8_ring_dispatch_execbuffer; 296024edb884SFrançois Tigeot if (i915_semaphore_is_enabled(dev)) { 296124edb884SFrançois Tigeot ring->semaphore.sync_to = gen8_ring_sync; 296224edb884SFrançois Tigeot ring->semaphore.signal = gen8_xcs_signal; 296324edb884SFrançois Tigeot GEN8_RING_SEMAPHORE_INIT; 296424edb884SFrançois Tigeot } 29659edbd4a0SFrançois Tigeot } else { 29669edbd4a0SFrançois Tigeot ring->irq_enable_mask = PM_VEBOX_USER_INTERRUPT; 29675d0b1887SFrançois Tigeot ring->irq_get = hsw_vebox_get_irq; 29685d0b1887SFrançois Tigeot ring->irq_put = hsw_vebox_put_irq; 29695d0b1887SFrançois Tigeot ring->dispatch_execbuffer = gen6_ring_dispatch_execbuffer; 297024edb884SFrançois Tigeot if (i915_semaphore_is_enabled(dev)) { 2971ba55f2f5SFrançois Tigeot ring->semaphore.sync_to = gen6_ring_sync; 2972ba55f2f5SFrançois Tigeot ring->semaphore.signal = gen6_signal; 2973ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[RCS] = MI_SEMAPHORE_SYNC_VER; 2974ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[VCS] = MI_SEMAPHORE_SYNC_VEV; 2975ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[BCS] = MI_SEMAPHORE_SYNC_VEB; 2976ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[VECS] = MI_SEMAPHORE_SYNC_INVALID; 2977ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[VCS2] = MI_SEMAPHORE_SYNC_INVALID; 2978ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[RCS] = GEN6_RVESYNC; 2979ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[VCS] = GEN6_VVESYNC; 2980ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[BCS] = GEN6_BVESYNC; 2981ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[VECS] = GEN6_NOSYNC; 2982ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[VCS2] = GEN6_NOSYNC; 298324edb884SFrançois Tigeot } 298424edb884SFrançois Tigeot } 29852c9916cdSFrançois Tigeot ring->init_hw = init_ring_common; 2986e3adcf8fSFrançois Tigeot 2987e3adcf8fSFrançois Tigeot return intel_init_ring_buffer(dev, ring); 2988e3adcf8fSFrançois Tigeot } 2989b030f26bSFrançois Tigeot 2990b030f26bSFrançois Tigeot int 2991a05eeebfSFrançois Tigeot intel_ring_flush_all_caches(struct drm_i915_gem_request *req) 2992b030f26bSFrançois Tigeot { 2993a05eeebfSFrançois Tigeot struct intel_engine_cs *ring = req->ring; 2994b030f26bSFrançois Tigeot int ret; 2995b030f26bSFrançois Tigeot 2996b030f26bSFrançois Tigeot if (!ring->gpu_caches_dirty) 2997b030f26bSFrançois Tigeot return 0; 2998b030f26bSFrançois Tigeot 2999a05eeebfSFrançois Tigeot ret = ring->flush(req, 0, I915_GEM_GPU_DOMAINS); 3000b030f26bSFrançois Tigeot if (ret) 3001b030f26bSFrançois Tigeot return ret; 3002b030f26bSFrançois Tigeot 3003a05eeebfSFrançois Tigeot trace_i915_gem_ring_flush(req, 0, I915_GEM_GPU_DOMAINS); 3004a2fdbec6SFrançois Tigeot 3005b030f26bSFrançois Tigeot ring->gpu_caches_dirty = false; 3006b030f26bSFrançois Tigeot return 0; 3007b030f26bSFrançois Tigeot } 3008b030f26bSFrançois Tigeot 3009b030f26bSFrançois Tigeot int 3010a05eeebfSFrançois Tigeot intel_ring_invalidate_all_caches(struct drm_i915_gem_request *req) 3011b030f26bSFrançois Tigeot { 3012a05eeebfSFrançois Tigeot struct intel_engine_cs *ring = req->ring; 3013b030f26bSFrançois Tigeot uint32_t flush_domains; 3014b030f26bSFrançois Tigeot int ret; 3015b030f26bSFrançois Tigeot 3016b030f26bSFrançois Tigeot flush_domains = 0; 3017b030f26bSFrançois Tigeot if (ring->gpu_caches_dirty) 3018b030f26bSFrançois Tigeot flush_domains = I915_GEM_GPU_DOMAINS; 3019b030f26bSFrançois Tigeot 3020a05eeebfSFrançois Tigeot ret = ring->flush(req, I915_GEM_GPU_DOMAINS, flush_domains); 3021b030f26bSFrançois Tigeot if (ret) 3022b030f26bSFrançois Tigeot return ret; 3023b030f26bSFrançois Tigeot 3024a05eeebfSFrançois Tigeot trace_i915_gem_ring_flush(req, I915_GEM_GPU_DOMAINS, flush_domains); 3025a2fdbec6SFrançois Tigeot 3026b030f26bSFrançois Tigeot ring->gpu_caches_dirty = false; 3027b030f26bSFrançois Tigeot return 0; 3028b030f26bSFrançois Tigeot } 3029ba55f2f5SFrançois Tigeot 3030ba55f2f5SFrançois Tigeot void 3031ba55f2f5SFrançois Tigeot intel_stop_ring_buffer(struct intel_engine_cs *ring) 3032ba55f2f5SFrançois Tigeot { 3033ba55f2f5SFrançois Tigeot int ret; 3034ba55f2f5SFrançois Tigeot 3035ba55f2f5SFrançois Tigeot if (!intel_ring_initialized(ring)) 3036ba55f2f5SFrançois Tigeot return; 3037ba55f2f5SFrançois Tigeot 3038ba55f2f5SFrançois Tigeot ret = intel_ring_idle(ring); 3039ba55f2f5SFrançois Tigeot if (ret && !i915_reset_in_progress(&to_i915(ring->dev)->gpu_error)) 3040ba55f2f5SFrançois Tigeot DRM_ERROR("failed to quiesce %s whilst cleaning up: %d\n", 3041ba55f2f5SFrançois Tigeot ring->name, ret); 3042ba55f2f5SFrançois Tigeot 3043ba55f2f5SFrançois Tigeot stop_ring(ring); 3044ba55f2f5SFrançois Tigeot } 3045