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 30aee94f86SFrançois Tigeot #include <linux/log2.h> 3118e26a6dSFrançois Tigeot #include <drm/drmP.h> 32e3adcf8fSFrançois Tigeot #include "i915_drv.h" 33a2fdbec6SFrançois Tigeot #include <drm/i915_drm.h> 34a2fdbec6SFrançois Tigeot #include "i915_trace.h" 35e3adcf8fSFrançois Tigeot #include "intel_drv.h" 36e3adcf8fSFrançois Tigeot 371487f786SFrançois Tigeot /* Rough estimate of the typical request size, performing a flush, 381487f786SFrançois Tigeot * set-context and then emitting the batch. 391487f786SFrançois Tigeot */ 401487f786SFrançois Tigeot #define LEGACY_REQUEST_SIZE 200 411487f786SFrançois Tigeot 421b13d190SFrançois Tigeot int __intel_ring_space(int head, int tail, int size) 43e3adcf8fSFrançois Tigeot { 442c9916cdSFrançois Tigeot int space = head - tail; 452c9916cdSFrançois Tigeot if (space <= 0) 46ba55f2f5SFrançois Tigeot space += size; 472c9916cdSFrançois Tigeot return space - I915_RING_FREE_SPACE; 482c9916cdSFrançois Tigeot } 492c9916cdSFrançois Tigeot 5071f41f3eSFrançois Tigeot void intel_ring_update_space(struct intel_ring *ring) 512c9916cdSFrançois Tigeot { 5271f41f3eSFrançois Tigeot if (ring->last_retired_head != -1) { 5371f41f3eSFrançois Tigeot ring->head = ring->last_retired_head; 5471f41f3eSFrançois Tigeot ring->last_retired_head = -1; 552c9916cdSFrançois Tigeot } 562c9916cdSFrançois Tigeot 5771f41f3eSFrançois Tigeot ring->space = __intel_ring_space(ring->head & HEAD_ADDR, 5871f41f3eSFrançois Tigeot ring->tail, ring->size); 599edbd4a0SFrançois Tigeot } 609edbd4a0SFrançois Tigeot 61e3adcf8fSFrançois Tigeot static int 6271f41f3eSFrançois Tigeot gen2_render_ring_flush(struct drm_i915_gem_request *req, u32 mode) 63686a02f1SFrançois Tigeot { 6471f41f3eSFrançois Tigeot struct intel_ring *ring = req->ring; 65686a02f1SFrançois Tigeot u32 cmd; 66686a02f1SFrançois Tigeot int ret; 67686a02f1SFrançois Tigeot 68686a02f1SFrançois Tigeot cmd = MI_FLUSH; 69686a02f1SFrançois Tigeot 7071f41f3eSFrançois Tigeot if (mode & EMIT_INVALIDATE) 71686a02f1SFrançois Tigeot cmd |= MI_READ_FLUSH; 72686a02f1SFrançois Tigeot 73a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 2); 74686a02f1SFrançois Tigeot if (ret) 75686a02f1SFrançois Tigeot return ret; 76686a02f1SFrançois Tigeot 7771f41f3eSFrançois Tigeot intel_ring_emit(ring, cmd); 7871f41f3eSFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 7971f41f3eSFrançois Tigeot intel_ring_advance(ring); 80686a02f1SFrançois Tigeot 81686a02f1SFrançois Tigeot return 0; 82686a02f1SFrançois Tigeot } 83686a02f1SFrançois Tigeot 84686a02f1SFrançois Tigeot static int 8571f41f3eSFrançois Tigeot gen4_render_ring_flush(struct drm_i915_gem_request *req, u32 mode) 86e3adcf8fSFrançois Tigeot { 8771f41f3eSFrançois Tigeot struct intel_ring *ring = req->ring; 88686a02f1SFrançois Tigeot u32 cmd; 89e3adcf8fSFrançois Tigeot int ret; 90e3adcf8fSFrançois Tigeot 91e3adcf8fSFrançois Tigeot /* 92e3adcf8fSFrançois Tigeot * read/write caches: 93e3adcf8fSFrançois Tigeot * 94e3adcf8fSFrançois Tigeot * I915_GEM_DOMAIN_RENDER is always invalidated, but is 95e3adcf8fSFrançois Tigeot * only flushed if MI_NO_WRITE_FLUSH is unset. On 965, it is 96e3adcf8fSFrançois Tigeot * also flushed at 2d versus 3d pipeline switches. 97e3adcf8fSFrançois Tigeot * 98e3adcf8fSFrançois Tigeot * read-only caches: 99e3adcf8fSFrançois Tigeot * 100e3adcf8fSFrançois Tigeot * I915_GEM_DOMAIN_SAMPLER is flushed on pre-965 if 101e3adcf8fSFrançois Tigeot * MI_READ_FLUSH is set, and is always flushed on 965. 102e3adcf8fSFrançois Tigeot * 103e3adcf8fSFrançois Tigeot * I915_GEM_DOMAIN_COMMAND may not exist? 104e3adcf8fSFrançois Tigeot * 105e3adcf8fSFrançois Tigeot * I915_GEM_DOMAIN_INSTRUCTION, which exists on 965, is 106e3adcf8fSFrançois Tigeot * invalidated when MI_EXE_FLUSH is set. 107e3adcf8fSFrançois Tigeot * 108e3adcf8fSFrançois Tigeot * I915_GEM_DOMAIN_VERTEX, which exists on 965, is 109e3adcf8fSFrançois Tigeot * invalidated with every MI_FLUSH. 110e3adcf8fSFrançois Tigeot * 111e3adcf8fSFrançois Tigeot * TLBs: 112e3adcf8fSFrançois Tigeot * 113e3adcf8fSFrançois Tigeot * On 965, TLBs associated with I915_GEM_DOMAIN_COMMAND 114e3adcf8fSFrançois Tigeot * and I915_GEM_DOMAIN_CPU in are invalidated at PTE write and 115e3adcf8fSFrançois Tigeot * I915_GEM_DOMAIN_RENDER and I915_GEM_DOMAIN_SAMPLER 116e3adcf8fSFrançois Tigeot * are flushed at any MI_FLUSH. 117e3adcf8fSFrançois Tigeot */ 118e3adcf8fSFrançois Tigeot 11971f41f3eSFrançois Tigeot cmd = MI_FLUSH; 12071f41f3eSFrançois Tigeot if (mode & EMIT_INVALIDATE) { 121e3adcf8fSFrançois Tigeot cmd |= MI_EXE_FLUSH; 12271f41f3eSFrançois Tigeot if (IS_G4X(req->i915) || IS_GEN5(req->i915)) 123e3adcf8fSFrançois Tigeot cmd |= MI_INVALIDATE_ISP; 12471f41f3eSFrançois Tigeot } 125e3adcf8fSFrançois Tigeot 126a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 2); 127e3adcf8fSFrançois Tigeot if (ret) 128e3adcf8fSFrançois Tigeot return ret; 129e3adcf8fSFrançois Tigeot 13071f41f3eSFrançois Tigeot intel_ring_emit(ring, cmd); 13171f41f3eSFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 13271f41f3eSFrançois Tigeot intel_ring_advance(ring); 133e3adcf8fSFrançois Tigeot 134e3adcf8fSFrançois Tigeot return 0; 135e3adcf8fSFrançois Tigeot } 136e3adcf8fSFrançois Tigeot 137e3adcf8fSFrançois Tigeot /** 138e3adcf8fSFrançois Tigeot * Emits a PIPE_CONTROL with a non-zero post-sync operation, for 139e3adcf8fSFrançois Tigeot * implementing two workarounds on gen6. From section 1.4.7.1 140e3adcf8fSFrançois Tigeot * "PIPE_CONTROL" of the Sandy Bridge PRM volume 2 part 1: 141e3adcf8fSFrançois Tigeot * 142e3adcf8fSFrançois Tigeot * [DevSNB-C+{W/A}] Before any depth stall flush (including those 143e3adcf8fSFrançois Tigeot * produced by non-pipelined state commands), software needs to first 144e3adcf8fSFrançois Tigeot * send a PIPE_CONTROL with no bits set except Post-Sync Operation != 145e3adcf8fSFrançois Tigeot * 0. 146e3adcf8fSFrançois Tigeot * 147e3adcf8fSFrançois Tigeot * [Dev-SNB{W/A}]: Before a PIPE_CONTROL with Write Cache Flush Enable 148e3adcf8fSFrançois Tigeot * =1, a PIPE_CONTROL with any non-zero post-sync-op is required. 149e3adcf8fSFrançois Tigeot * 150e3adcf8fSFrançois Tigeot * And the workaround for these two requires this workaround first: 151e3adcf8fSFrançois Tigeot * 152e3adcf8fSFrançois Tigeot * [Dev-SNB{W/A}]: Pipe-control with CS-stall bit set must be sent 153e3adcf8fSFrançois Tigeot * BEFORE the pipe-control with a post-sync op and no write-cache 154e3adcf8fSFrançois Tigeot * flushes. 155e3adcf8fSFrançois Tigeot * 156e3adcf8fSFrançois Tigeot * And this last workaround is tricky because of the requirements on 157e3adcf8fSFrançois Tigeot * that bit. From section 1.4.7.2.3 "Stall" of the Sandy Bridge PRM 158e3adcf8fSFrançois Tigeot * volume 2 part 1: 159e3adcf8fSFrançois Tigeot * 160e3adcf8fSFrançois Tigeot * "1 of the following must also be set: 161e3adcf8fSFrançois Tigeot * - Render Target Cache Flush Enable ([12] of DW1) 162e3adcf8fSFrançois Tigeot * - Depth Cache Flush Enable ([0] of DW1) 163e3adcf8fSFrançois Tigeot * - Stall at Pixel Scoreboard ([1] of DW1) 164e3adcf8fSFrançois Tigeot * - Depth Stall ([13] of DW1) 165e3adcf8fSFrançois Tigeot * - Post-Sync Operation ([13] of DW1) 166e3adcf8fSFrançois Tigeot * - Notify Enable ([8] of DW1)" 167e3adcf8fSFrançois Tigeot * 168e3adcf8fSFrançois Tigeot * The cache flushes require the workaround flush that triggered this 169e3adcf8fSFrançois Tigeot * one, so we can't use it. Depth stall would trigger the same. 170e3adcf8fSFrançois Tigeot * Post-sync nonzero is what triggered this second workaround, so we 171e3adcf8fSFrançois Tigeot * can't use that one either. Notify enable is IRQs, which aren't 172e3adcf8fSFrançois Tigeot * really our business. That leaves only stall at scoreboard. 173e3adcf8fSFrançois Tigeot */ 174e3adcf8fSFrançois Tigeot static int 175a05eeebfSFrançois Tigeot intel_emit_post_sync_nonzero_flush(struct drm_i915_gem_request *req) 176e3adcf8fSFrançois Tigeot { 17771f41f3eSFrançois Tigeot struct intel_ring *ring = req->ring; 17871f41f3eSFrançois Tigeot u32 scratch_addr = 179*1e12ee3bSFrançois Tigeot i915_ggtt_offset(req->engine->scratch) + 2 * CACHELINE_BYTES; 180e3adcf8fSFrançois Tigeot int ret; 181e3adcf8fSFrançois Tigeot 182a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 6); 183e3adcf8fSFrançois Tigeot if (ret) 184e3adcf8fSFrançois Tigeot return ret; 185e3adcf8fSFrançois Tigeot 18671f41f3eSFrançois Tigeot intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(5)); 18771f41f3eSFrançois Tigeot intel_ring_emit(ring, PIPE_CONTROL_CS_STALL | 188e3adcf8fSFrançois Tigeot PIPE_CONTROL_STALL_AT_SCOREBOARD); 18971f41f3eSFrançois Tigeot intel_ring_emit(ring, scratch_addr | PIPE_CONTROL_GLOBAL_GTT); 19071f41f3eSFrançois Tigeot intel_ring_emit(ring, 0); /* low dword */ 19171f41f3eSFrançois Tigeot intel_ring_emit(ring, 0); /* high dword */ 19271f41f3eSFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 19371f41f3eSFrançois Tigeot intel_ring_advance(ring); 194e3adcf8fSFrançois Tigeot 195a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 6); 196e3adcf8fSFrançois Tigeot if (ret) 197e3adcf8fSFrançois Tigeot return ret; 198e3adcf8fSFrançois Tigeot 19971f41f3eSFrançois Tigeot intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(5)); 20071f41f3eSFrançois Tigeot intel_ring_emit(ring, PIPE_CONTROL_QW_WRITE); 20171f41f3eSFrançois Tigeot intel_ring_emit(ring, scratch_addr | PIPE_CONTROL_GLOBAL_GTT); 20271f41f3eSFrançois Tigeot intel_ring_emit(ring, 0); 20371f41f3eSFrançois Tigeot intel_ring_emit(ring, 0); 20471f41f3eSFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 20571f41f3eSFrançois Tigeot intel_ring_advance(ring); 206e3adcf8fSFrançois Tigeot 207e3adcf8fSFrançois Tigeot return 0; 208e3adcf8fSFrançois Tigeot } 209e3adcf8fSFrançois Tigeot 210e3adcf8fSFrançois Tigeot static int 21171f41f3eSFrançois Tigeot gen6_render_ring_flush(struct drm_i915_gem_request *req, u32 mode) 212e3adcf8fSFrançois Tigeot { 21371f41f3eSFrançois Tigeot struct intel_ring *ring = req->ring; 21471f41f3eSFrançois Tigeot u32 scratch_addr = 215*1e12ee3bSFrançois Tigeot i915_ggtt_offset(req->engine->scratch) + 2 * CACHELINE_BYTES; 216e3adcf8fSFrançois Tigeot u32 flags = 0; 217e3adcf8fSFrançois Tigeot int ret; 218e3adcf8fSFrançois Tigeot 219e3adcf8fSFrançois Tigeot /* Force SNB workarounds for PIPE_CONTROL flushes */ 220a05eeebfSFrançois Tigeot ret = intel_emit_post_sync_nonzero_flush(req); 221686a02f1SFrançois Tigeot if (ret) 222686a02f1SFrançois Tigeot return ret; 223e3adcf8fSFrançois Tigeot 224e3adcf8fSFrançois Tigeot /* Just flush everything. Experiments have shown that reducing the 225e3adcf8fSFrançois Tigeot * number of bits based on the write domains has little performance 226e3adcf8fSFrançois Tigeot * impact. 227e3adcf8fSFrançois Tigeot */ 22871f41f3eSFrançois Tigeot if (mode & EMIT_FLUSH) { 229e3adcf8fSFrançois Tigeot flags |= PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH; 230b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_DEPTH_CACHE_FLUSH; 231b5c29a34SFrançois Tigeot /* 232b5c29a34SFrançois Tigeot * Ensure that any following seqno writes only happen 233b5c29a34SFrançois Tigeot * when the render cache is indeed flushed. 234b5c29a34SFrançois Tigeot */ 235b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_CS_STALL; 236b5c29a34SFrançois Tigeot } 23771f41f3eSFrançois Tigeot if (mode & EMIT_INVALIDATE) { 238686a02f1SFrançois Tigeot flags |= PIPE_CONTROL_TLB_INVALIDATE; 239e3adcf8fSFrançois Tigeot flags |= PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE; 240e3adcf8fSFrançois Tigeot flags |= PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE; 241e3adcf8fSFrançois Tigeot flags |= PIPE_CONTROL_VF_CACHE_INVALIDATE; 242e3adcf8fSFrançois Tigeot flags |= PIPE_CONTROL_CONST_CACHE_INVALIDATE; 243e3adcf8fSFrançois Tigeot flags |= PIPE_CONTROL_STATE_CACHE_INVALIDATE; 244686a02f1SFrançois Tigeot /* 245b5c29a34SFrançois Tigeot * TLB invalidate requires a post-sync write. 246686a02f1SFrançois Tigeot */ 247b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_QW_WRITE | PIPE_CONTROL_CS_STALL; 248b5c29a34SFrançois Tigeot } 249e3adcf8fSFrançois Tigeot 250a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 4); 251e3adcf8fSFrançois Tigeot if (ret) 252e3adcf8fSFrançois Tigeot return ret; 253e3adcf8fSFrançois Tigeot 25471f41f3eSFrançois Tigeot intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(4)); 25571f41f3eSFrançois Tigeot intel_ring_emit(ring, flags); 25671f41f3eSFrançois Tigeot intel_ring_emit(ring, scratch_addr | PIPE_CONTROL_GLOBAL_GTT); 25771f41f3eSFrançois Tigeot intel_ring_emit(ring, 0); 25871f41f3eSFrançois Tigeot intel_ring_advance(ring); 259b5c29a34SFrançois Tigeot 260b5c29a34SFrançois Tigeot return 0; 261b5c29a34SFrançois Tigeot } 262b5c29a34SFrançois Tigeot 263b5c29a34SFrançois Tigeot static int 264a05eeebfSFrançois Tigeot gen7_render_ring_cs_stall_wa(struct drm_i915_gem_request *req) 265b5c29a34SFrançois Tigeot { 26671f41f3eSFrançois Tigeot struct intel_ring *ring = req->ring; 267b5c29a34SFrançois Tigeot int ret; 268b5c29a34SFrançois Tigeot 269a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 4); 270b5c29a34SFrançois Tigeot if (ret) 271b5c29a34SFrançois Tigeot return ret; 272b5c29a34SFrançois Tigeot 27371f41f3eSFrançois Tigeot intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(4)); 27471f41f3eSFrançois Tigeot intel_ring_emit(ring, 27571f41f3eSFrançois Tigeot PIPE_CONTROL_CS_STALL | 276b5c29a34SFrançois Tigeot PIPE_CONTROL_STALL_AT_SCOREBOARD); 27771f41f3eSFrançois Tigeot intel_ring_emit(ring, 0); 27871f41f3eSFrançois Tigeot intel_ring_emit(ring, 0); 27971f41f3eSFrançois Tigeot intel_ring_advance(ring); 280b5c29a34SFrançois Tigeot 281b5c29a34SFrançois Tigeot return 0; 282b5c29a34SFrançois Tigeot } 283b5c29a34SFrançois Tigeot 284b5c29a34SFrançois Tigeot static int 28571f41f3eSFrançois Tigeot gen7_render_ring_flush(struct drm_i915_gem_request *req, u32 mode) 286b5c29a34SFrançois Tigeot { 28771f41f3eSFrançois Tigeot struct intel_ring *ring = req->ring; 28871f41f3eSFrançois Tigeot u32 scratch_addr = 289*1e12ee3bSFrançois Tigeot i915_ggtt_offset(req->engine->scratch) + 2 * CACHELINE_BYTES; 290b5c29a34SFrançois Tigeot u32 flags = 0; 291b5c29a34SFrançois Tigeot int ret; 292b5c29a34SFrançois Tigeot 293b5c29a34SFrançois Tigeot /* 294b5c29a34SFrançois Tigeot * Ensure that any following seqno writes only happen when the render 295b5c29a34SFrançois Tigeot * cache is indeed flushed. 296b5c29a34SFrançois Tigeot * 297b5c29a34SFrançois Tigeot * Workaround: 4th PIPE_CONTROL command (except the ones with only 298b5c29a34SFrançois Tigeot * read-cache invalidate bits set) must have the CS_STALL bit set. We 299b5c29a34SFrançois Tigeot * don't try to be clever and just set it unconditionally. 300b5c29a34SFrançois Tigeot */ 301b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_CS_STALL; 302b5c29a34SFrançois Tigeot 303b5c29a34SFrançois Tigeot /* Just flush everything. Experiments have shown that reducing the 304b5c29a34SFrançois Tigeot * number of bits based on the write domains has little performance 305b5c29a34SFrançois Tigeot * impact. 306b5c29a34SFrançois Tigeot */ 30771f41f3eSFrançois Tigeot if (mode & EMIT_FLUSH) { 308b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH; 309b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_DEPTH_CACHE_FLUSH; 310aee94f86SFrançois Tigeot flags |= PIPE_CONTROL_DC_FLUSH_ENABLE; 311b49c8cf9SFrançois Tigeot flags |= PIPE_CONTROL_FLUSH_ENABLE; 312b5c29a34SFrançois Tigeot } 31371f41f3eSFrançois Tigeot if (mode & EMIT_INVALIDATE) { 314b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_TLB_INVALIDATE; 315b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE; 316b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE; 317b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_VF_CACHE_INVALIDATE; 318b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_CONST_CACHE_INVALIDATE; 319b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_STATE_CACHE_INVALIDATE; 3202c9916cdSFrançois Tigeot flags |= PIPE_CONTROL_MEDIA_STATE_CLEAR; 321b5c29a34SFrançois Tigeot /* 322b5c29a34SFrançois Tigeot * TLB invalidate requires a post-sync write. 323b5c29a34SFrançois Tigeot */ 324b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_QW_WRITE; 325a2fdbec6SFrançois Tigeot flags |= PIPE_CONTROL_GLOBAL_GTT_IVB; 326b5c29a34SFrançois Tigeot 3270dbf0ea8SMatthew Dillon flags |= PIPE_CONTROL_STALL_AT_SCOREBOARD; 3280dbf0ea8SMatthew Dillon 329b5c29a34SFrançois Tigeot /* Workaround: we must issue a pipe_control with CS-stall bit 330b5c29a34SFrançois Tigeot * set before a pipe_control command that has the state cache 331b5c29a34SFrançois Tigeot * invalidate bit set. */ 332a05eeebfSFrançois Tigeot gen7_render_ring_cs_stall_wa(req); 333b5c29a34SFrançois Tigeot } 334b5c29a34SFrançois Tigeot 335a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 4); 336b5c29a34SFrançois Tigeot if (ret) 337b5c29a34SFrançois Tigeot return ret; 338b5c29a34SFrançois Tigeot 33971f41f3eSFrançois Tigeot intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(4)); 34071f41f3eSFrançois Tigeot intel_ring_emit(ring, flags); 34171f41f3eSFrançois Tigeot intel_ring_emit(ring, scratch_addr); 34271f41f3eSFrançois Tigeot intel_ring_emit(ring, 0); 34371f41f3eSFrançois Tigeot intel_ring_advance(ring); 344e3adcf8fSFrançois Tigeot 345e3adcf8fSFrançois Tigeot return 0; 346e3adcf8fSFrançois Tigeot } 347e3adcf8fSFrançois Tigeot 3489edbd4a0SFrançois Tigeot static int 349a05eeebfSFrançois Tigeot gen8_emit_pipe_control(struct drm_i915_gem_request *req, 35024edb884SFrançois Tigeot u32 flags, u32 scratch_addr) 35124edb884SFrançois Tigeot { 35271f41f3eSFrançois Tigeot struct intel_ring *ring = req->ring; 35324edb884SFrançois Tigeot int ret; 35424edb884SFrançois Tigeot 355a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 6); 35624edb884SFrançois Tigeot if (ret) 35724edb884SFrançois Tigeot return ret; 35824edb884SFrançois Tigeot 35971f41f3eSFrançois Tigeot intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(6)); 36071f41f3eSFrançois Tigeot intel_ring_emit(ring, flags); 36171f41f3eSFrançois Tigeot intel_ring_emit(ring, scratch_addr); 36271f41f3eSFrançois Tigeot intel_ring_emit(ring, 0); 36371f41f3eSFrançois Tigeot intel_ring_emit(ring, 0); 36471f41f3eSFrançois Tigeot intel_ring_emit(ring, 0); 36571f41f3eSFrançois Tigeot intel_ring_advance(ring); 36624edb884SFrançois Tigeot 36724edb884SFrançois Tigeot return 0; 36824edb884SFrançois Tigeot } 36924edb884SFrançois Tigeot 37024edb884SFrançois Tigeot static int 37171f41f3eSFrançois Tigeot gen8_render_ring_flush(struct drm_i915_gem_request *req, u32 mode) 3729edbd4a0SFrançois Tigeot { 373*1e12ee3bSFrançois Tigeot u32 scratch_addr = 374*1e12ee3bSFrançois Tigeot i915_ggtt_offset(req->engine->scratch) + 2 * CACHELINE_BYTES; 37571f41f3eSFrançois Tigeot u32 flags = 0; 3769edbd4a0SFrançois Tigeot int ret; 3779edbd4a0SFrançois Tigeot 3789edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_CS_STALL; 3799edbd4a0SFrançois Tigeot 38071f41f3eSFrançois Tigeot if (mode & EMIT_FLUSH) { 3819edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH; 3829edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_DEPTH_CACHE_FLUSH; 383aee94f86SFrançois Tigeot flags |= PIPE_CONTROL_DC_FLUSH_ENABLE; 384b49c8cf9SFrançois Tigeot flags |= PIPE_CONTROL_FLUSH_ENABLE; 3859edbd4a0SFrançois Tigeot } 38671f41f3eSFrançois Tigeot if (mode & EMIT_INVALIDATE) { 3879edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_TLB_INVALIDATE; 3889edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE; 3899edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE; 3909edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_VF_CACHE_INVALIDATE; 3919edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_CONST_CACHE_INVALIDATE; 3929edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_STATE_CACHE_INVALIDATE; 3939edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_QW_WRITE; 3949edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_GLOBAL_GTT_IVB; 3959edbd4a0SFrançois Tigeot 39624edb884SFrançois Tigeot /* WaCsStallBeforeStateCacheInvalidate:bdw,chv */ 397a05eeebfSFrançois Tigeot ret = gen8_emit_pipe_control(req, 39824edb884SFrançois Tigeot PIPE_CONTROL_CS_STALL | 39924edb884SFrançois Tigeot PIPE_CONTROL_STALL_AT_SCOREBOARD, 40024edb884SFrançois Tigeot 0); 4019edbd4a0SFrançois Tigeot if (ret) 4029edbd4a0SFrançois Tigeot return ret; 40324edb884SFrançois Tigeot } 4049edbd4a0SFrançois Tigeot 405a05eeebfSFrançois Tigeot return gen8_emit_pipe_control(req, flags, scratch_addr); 4069edbd4a0SFrançois Tigeot } 4079edbd4a0SFrançois Tigeot 4088621f407SFrançois Tigeot static void ring_setup_phys_status_page(struct intel_engine_cs *engine) 4095d0b1887SFrançois Tigeot { 4101487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 4115d0b1887SFrançois Tigeot u32 addr; 4125d0b1887SFrançois Tigeot 4135d0b1887SFrançois Tigeot addr = dev_priv->status_page_dmah->busaddr; 4141487f786SFrançois Tigeot if (INTEL_GEN(dev_priv) >= 4) 4155d0b1887SFrançois Tigeot addr |= (dev_priv->status_page_dmah->busaddr >> 28) & 0xf0; 4165d0b1887SFrançois Tigeot I915_WRITE(HWS_PGA, addr); 4175d0b1887SFrançois Tigeot } 4185d0b1887SFrançois Tigeot 4198621f407SFrançois Tigeot static void intel_ring_setup_status_page(struct intel_engine_cs *engine) 420477eb7f9SFrançois Tigeot { 4211487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 422aee94f86SFrançois Tigeot i915_reg_t mmio; 423477eb7f9SFrançois Tigeot 424477eb7f9SFrançois Tigeot /* The ring status page addresses are no longer next to the rest of 425477eb7f9SFrançois Tigeot * the ring registers as of gen7. 426477eb7f9SFrançois Tigeot */ 4271487f786SFrançois Tigeot if (IS_GEN7(dev_priv)) { 4288621f407SFrançois Tigeot switch (engine->id) { 429477eb7f9SFrançois Tigeot case RCS: 430477eb7f9SFrançois Tigeot mmio = RENDER_HWS_PGA_GEN7; 431477eb7f9SFrançois Tigeot break; 432477eb7f9SFrançois Tigeot case BCS: 433477eb7f9SFrançois Tigeot mmio = BLT_HWS_PGA_GEN7; 434477eb7f9SFrançois Tigeot break; 435477eb7f9SFrançois Tigeot /* 436477eb7f9SFrançois Tigeot * VCS2 actually doesn't exist on Gen7. Only shut up 437477eb7f9SFrançois Tigeot * gcc switch check warning 438477eb7f9SFrançois Tigeot */ 439477eb7f9SFrançois Tigeot case VCS2: 440477eb7f9SFrançois Tigeot case VCS: 441477eb7f9SFrançois Tigeot mmio = BSD_HWS_PGA_GEN7; 442477eb7f9SFrançois Tigeot break; 443477eb7f9SFrançois Tigeot case VECS: 444477eb7f9SFrançois Tigeot mmio = VEBOX_HWS_PGA_GEN7; 445477eb7f9SFrançois Tigeot break; 446477eb7f9SFrançois Tigeot } 4471487f786SFrançois Tigeot } else if (IS_GEN6(dev_priv)) { 4488621f407SFrançois Tigeot mmio = RING_HWS_PGA_GEN6(engine->mmio_base); 449477eb7f9SFrançois Tigeot } else { 450477eb7f9SFrançois Tigeot /* XXX: gen8 returns to sanity */ 4518621f407SFrançois Tigeot mmio = RING_HWS_PGA(engine->mmio_base); 452477eb7f9SFrançois Tigeot } 453477eb7f9SFrançois Tigeot 454*1e12ee3bSFrançois Tigeot I915_WRITE(mmio, engine->status_page.ggtt_offset); 455477eb7f9SFrançois Tigeot POSTING_READ(mmio); 456477eb7f9SFrançois Tigeot 457477eb7f9SFrançois Tigeot /* 458477eb7f9SFrançois Tigeot * Flush the TLB for this page 459477eb7f9SFrançois Tigeot * 460477eb7f9SFrançois Tigeot * FIXME: These two bits have disappeared on gen8, so a question 461477eb7f9SFrançois Tigeot * arises: do we still need this and if so how should we go about 462477eb7f9SFrançois Tigeot * invalidating the TLB? 463477eb7f9SFrançois Tigeot */ 4641487f786SFrançois Tigeot if (IS_GEN(dev_priv, 6, 7)) { 4658621f407SFrançois Tigeot i915_reg_t reg = RING_INSTPM(engine->mmio_base); 466477eb7f9SFrançois Tigeot 467477eb7f9SFrançois Tigeot /* ring should be idle before issuing a sync flush*/ 4688621f407SFrançois Tigeot WARN_ON((I915_READ_MODE(engine) & MODE_IDLE) == 0); 469477eb7f9SFrançois Tigeot 470477eb7f9SFrançois Tigeot I915_WRITE(reg, 471477eb7f9SFrançois Tigeot _MASKED_BIT_ENABLE(INSTPM_TLB_INVALIDATE | 472477eb7f9SFrançois Tigeot INSTPM_SYNC_FLUSH)); 4731487f786SFrançois Tigeot if (intel_wait_for_register(dev_priv, 4741487f786SFrançois Tigeot reg, INSTPM_SYNC_FLUSH, 0, 475477eb7f9SFrançois Tigeot 1000)) 476477eb7f9SFrançois Tigeot DRM_ERROR("%s: wait for SyncFlush to complete for TLB invalidation timed out\n", 4778621f407SFrançois Tigeot engine->name); 478477eb7f9SFrançois Tigeot } 479477eb7f9SFrançois Tigeot } 480477eb7f9SFrançois Tigeot 4818621f407SFrançois Tigeot static bool stop_ring(struct intel_engine_cs *engine) 482e3adcf8fSFrançois Tigeot { 4831487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 484e3adcf8fSFrançois Tigeot 485*1e12ee3bSFrançois Tigeot if (INTEL_GEN(dev_priv) > 2) { 4868621f407SFrançois Tigeot I915_WRITE_MODE(engine, _MASKED_BIT_ENABLE(STOP_RING)); 4871487f786SFrançois Tigeot if (intel_wait_for_register(dev_priv, 4881487f786SFrançois Tigeot RING_MI_MODE(engine->mmio_base), 4891487f786SFrançois Tigeot MODE_IDLE, 4901487f786SFrançois Tigeot MODE_IDLE, 4911487f786SFrançois Tigeot 1000)) { 4928621f407SFrançois Tigeot DRM_ERROR("%s : timed out trying to stop ring\n", 4938621f407SFrançois Tigeot engine->name); 4941b13d190SFrançois Tigeot /* Sometimes we observe that the idle flag is not 4951b13d190SFrançois Tigeot * set even though the ring is empty. So double 4961b13d190SFrançois Tigeot * check before giving up. 4971b13d190SFrançois Tigeot */ 4988621f407SFrançois Tigeot if (I915_READ_HEAD(engine) != I915_READ_TAIL(engine)) 499ba55f2f5SFrançois Tigeot return false; 500ba55f2f5SFrançois Tigeot } 501ba55f2f5SFrançois Tigeot } 502686a02f1SFrançois Tigeot 5038621f407SFrançois Tigeot I915_WRITE_CTL(engine, 0); 5048621f407SFrançois Tigeot I915_WRITE_HEAD(engine, 0); 50571f41f3eSFrançois Tigeot I915_WRITE_TAIL(engine, 0); 506e3adcf8fSFrançois Tigeot 507*1e12ee3bSFrançois Tigeot if (INTEL_GEN(dev_priv) > 2) { 5088621f407SFrançois Tigeot (void)I915_READ_CTL(engine); 5098621f407SFrançois Tigeot I915_WRITE_MODE(engine, _MASKED_BIT_DISABLE(STOP_RING)); 510ba55f2f5SFrançois Tigeot } 511e3adcf8fSFrançois Tigeot 5128621f407SFrançois Tigeot return (I915_READ_HEAD(engine) & HEAD_ADDR) == 0; 513ba55f2f5SFrançois Tigeot } 514ba55f2f5SFrançois Tigeot 5158621f407SFrançois Tigeot static int init_ring_common(struct intel_engine_cs *engine) 5168621f407SFrançois Tigeot { 5171487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 51871f41f3eSFrançois Tigeot struct intel_ring *ring = engine->buffer; 519ba55f2f5SFrançois Tigeot int ret = 0; 520ba55f2f5SFrançois Tigeot 5212c9916cdSFrançois Tigeot intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL); 522ba55f2f5SFrançois Tigeot 5238621f407SFrançois Tigeot if (!stop_ring(engine)) { 524ba55f2f5SFrançois Tigeot /* G45 ring initialization often fails to reset head to zero */ 525b5c29a34SFrançois Tigeot DRM_DEBUG_KMS("%s head not reset to zero " 526e3adcf8fSFrançois Tigeot "ctl %08x head %08x tail %08x start %08x\n", 5278621f407SFrançois Tigeot engine->name, 5288621f407SFrançois Tigeot I915_READ_CTL(engine), 5298621f407SFrançois Tigeot I915_READ_HEAD(engine), 5308621f407SFrançois Tigeot I915_READ_TAIL(engine), 5318621f407SFrançois Tigeot I915_READ_START(engine)); 532e3adcf8fSFrançois Tigeot 5338621f407SFrançois Tigeot if (!stop_ring(engine)) { 534e3adcf8fSFrançois Tigeot DRM_ERROR("failed to set %s head to zero " 535e3adcf8fSFrançois Tigeot "ctl %08x head %08x tail %08x start %08x\n", 5368621f407SFrançois Tigeot engine->name, 5378621f407SFrançois Tigeot I915_READ_CTL(engine), 5388621f407SFrançois Tigeot I915_READ_HEAD(engine), 5398621f407SFrançois Tigeot I915_READ_TAIL(engine), 5408621f407SFrançois Tigeot I915_READ_START(engine)); 541686a02f1SFrançois Tigeot ret = -EIO; 542686a02f1SFrançois Tigeot goto out; 543e3adcf8fSFrançois Tigeot } 544ba55f2f5SFrançois Tigeot } 545ba55f2f5SFrançois Tigeot 546*1e12ee3bSFrançois Tigeot if (HWS_NEEDS_PHYSICAL(dev_priv)) 5478621f407SFrançois Tigeot ring_setup_phys_status_page(engine); 548*1e12ee3bSFrançois Tigeot else 549*1e12ee3bSFrançois Tigeot intel_ring_setup_status_page(engine); 550*1e12ee3bSFrançois Tigeot 551*1e12ee3bSFrançois Tigeot intel_engine_reset_breadcrumbs(engine); 552ba55f2f5SFrançois Tigeot 5530f370975SMatthew Dillon /* Enforce ordering by reading HEAD register back */ 5548621f407SFrançois Tigeot I915_READ_HEAD(engine); 5550f370975SMatthew Dillon 556ba55f2f5SFrançois Tigeot /* Initialize the ring. This must happen _after_ we've cleared the ring 557ba55f2f5SFrançois Tigeot * registers with the above sequence (the readback of the HEAD registers 558ba55f2f5SFrançois Tigeot * also enforces ordering), otherwise the hw might lose the new ring 559ba55f2f5SFrançois Tigeot * register values. */ 560*1e12ee3bSFrançois Tigeot I915_WRITE_START(engine, i915_ggtt_offset(ring->vma)); 5611b13d190SFrançois Tigeot 5621b13d190SFrançois Tigeot /* WaClearRingBufHeadRegAtInit:ctg,elk */ 5638621f407SFrançois Tigeot if (I915_READ_HEAD(engine)) 5641b13d190SFrançois Tigeot DRM_DEBUG("%s initialization failed [head=%08x], fudging\n", 5658621f407SFrançois Tigeot engine->name, I915_READ_HEAD(engine)); 5661b13d190SFrançois Tigeot 567*1e12ee3bSFrançois Tigeot intel_ring_update_space(ring); 568*1e12ee3bSFrançois Tigeot I915_WRITE_HEAD(engine, ring->head); 569*1e12ee3bSFrançois Tigeot I915_WRITE_TAIL(engine, ring->tail); 570*1e12ee3bSFrançois Tigeot (void)I915_READ_TAIL(engine); 571*1e12ee3bSFrançois Tigeot 572*1e12ee3bSFrançois Tigeot I915_WRITE_CTL(engine, RING_CTL_SIZE(ring->size) | RING_VALID); 573ba55f2f5SFrançois Tigeot 574ba55f2f5SFrançois Tigeot /* If the head is still not zero, the ring is dead */ 575*1e12ee3bSFrançois Tigeot if (intel_wait_for_register_fw(dev_priv, RING_CTL(engine->mmio_base), 576*1e12ee3bSFrançois Tigeot RING_VALID, RING_VALID, 577*1e12ee3bSFrançois Tigeot 50)) { 578ba55f2f5SFrançois Tigeot DRM_ERROR("%s initialization failed " 579*1e12ee3bSFrançois Tigeot "ctl %08x (valid? %d) head %08x [%08x] tail %08x [%08x] start %08x [expected %08x]\n", 5808621f407SFrançois Tigeot engine->name, 5818621f407SFrançois Tigeot I915_READ_CTL(engine), 5828621f407SFrançois Tigeot I915_READ_CTL(engine) & RING_VALID, 583*1e12ee3bSFrançois Tigeot I915_READ_HEAD(engine), ring->head, 584*1e12ee3bSFrançois Tigeot I915_READ_TAIL(engine), ring->tail, 5858621f407SFrançois Tigeot I915_READ_START(engine), 586*1e12ee3bSFrançois Tigeot i915_ggtt_offset(ring->vma)); 587ba55f2f5SFrançois Tigeot ret = -EIO; 588ba55f2f5SFrançois Tigeot goto out; 589ba55f2f5SFrançois Tigeot } 590e3adcf8fSFrançois Tigeot 5918621f407SFrançois Tigeot intel_engine_init_hangcheck(engine); 5925d0b1887SFrançois Tigeot 593686a02f1SFrançois Tigeot out: 5942c9916cdSFrançois Tigeot intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL); 595686a02f1SFrançois Tigeot 596686a02f1SFrançois Tigeot return ret; 597e3adcf8fSFrançois Tigeot } 598e3adcf8fSFrançois Tigeot 599*1e12ee3bSFrançois Tigeot static void reset_ring_common(struct intel_engine_cs *engine, 600*1e12ee3bSFrançois Tigeot struct drm_i915_gem_request *request) 6011b13d190SFrançois Tigeot { 602*1e12ee3bSFrançois Tigeot struct intel_ring *ring = request->ring; 6031b13d190SFrançois Tigeot 604*1e12ee3bSFrançois Tigeot ring->head = request->postfix; 605*1e12ee3bSFrançois Tigeot ring->last_retired_head = -1; 606e3adcf8fSFrançois Tigeot } 607e3adcf8fSFrançois Tigeot 608a05eeebfSFrançois Tigeot static int intel_ring_workarounds_emit(struct drm_i915_gem_request *req) 6091b13d190SFrançois Tigeot { 61071f41f3eSFrançois Tigeot struct intel_ring *ring = req->ring; 6111487f786SFrançois Tigeot struct i915_workarounds *w = &req->i915->workarounds; 6121487f786SFrançois Tigeot int ret, i; 6131b13d190SFrançois Tigeot 614352ff8bdSFrançois Tigeot if (w->count == 0) 6152c9916cdSFrançois Tigeot return 0; 6161b13d190SFrançois Tigeot 61771f41f3eSFrançois Tigeot ret = req->engine->emit_flush(req, EMIT_BARRIER); 6181b13d190SFrançois Tigeot if (ret) 6191b13d190SFrançois Tigeot return ret; 6201b13d190SFrançois Tigeot 621a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, (w->count * 2 + 2)); 6222c9916cdSFrançois Tigeot if (ret) 6232c9916cdSFrançois Tigeot return ret; 6242c9916cdSFrançois Tigeot 62571f41f3eSFrançois Tigeot intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(w->count)); 6262c9916cdSFrançois Tigeot for (i = 0; i < w->count; i++) { 62771f41f3eSFrançois Tigeot intel_ring_emit_reg(ring, w->reg[i].addr); 62871f41f3eSFrançois Tigeot intel_ring_emit(ring, w->reg[i].value); 6292c9916cdSFrançois Tigeot } 63071f41f3eSFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 6312c9916cdSFrançois Tigeot 63271f41f3eSFrançois Tigeot intel_ring_advance(ring); 6332c9916cdSFrançois Tigeot 63471f41f3eSFrançois Tigeot ret = req->engine->emit_flush(req, EMIT_BARRIER); 6352c9916cdSFrançois Tigeot if (ret) 6362c9916cdSFrançois Tigeot return ret; 6372c9916cdSFrançois Tigeot 6382c9916cdSFrançois Tigeot DRM_DEBUG_DRIVER("Number of Workarounds emitted: %d\n", w->count); 6392c9916cdSFrançois Tigeot 6402c9916cdSFrançois Tigeot return 0; 6412c9916cdSFrançois Tigeot } 6422c9916cdSFrançois Tigeot 643a05eeebfSFrançois Tigeot static int intel_rcs_ctx_init(struct drm_i915_gem_request *req) 6442c9916cdSFrançois Tigeot { 6452c9916cdSFrançois Tigeot int ret; 6462c9916cdSFrançois Tigeot 647a05eeebfSFrançois Tigeot ret = intel_ring_workarounds_emit(req); 6482c9916cdSFrançois Tigeot if (ret != 0) 6492c9916cdSFrançois Tigeot return ret; 6502c9916cdSFrançois Tigeot 651a05eeebfSFrançois Tigeot ret = i915_gem_render_state_init(req); 6522c9916cdSFrançois Tigeot if (ret) 6532c9916cdSFrançois Tigeot return ret; 654c0e85e96SFrançois Tigeot 655c0e85e96SFrançois Tigeot return 0; 6562c9916cdSFrançois Tigeot } 6572c9916cdSFrançois Tigeot 6582c9916cdSFrançois Tigeot static int wa_add(struct drm_i915_private *dev_priv, 659aee94f86SFrançois Tigeot i915_reg_t addr, 660aee94f86SFrançois Tigeot const u32 mask, const u32 val) 6612c9916cdSFrançois Tigeot { 6622c9916cdSFrançois Tigeot const u32 idx = dev_priv->workarounds.count; 6632c9916cdSFrançois Tigeot 6642c9916cdSFrançois Tigeot if (WARN_ON(idx >= I915_MAX_WA_REGS)) 6652c9916cdSFrançois Tigeot return -ENOSPC; 6662c9916cdSFrançois Tigeot 6672c9916cdSFrançois Tigeot dev_priv->workarounds.reg[idx].addr = addr; 6682c9916cdSFrançois Tigeot dev_priv->workarounds.reg[idx].value = val; 6692c9916cdSFrançois Tigeot dev_priv->workarounds.reg[idx].mask = mask; 6702c9916cdSFrançois Tigeot 6712c9916cdSFrançois Tigeot dev_priv->workarounds.count++; 6722c9916cdSFrançois Tigeot 6732c9916cdSFrançois Tigeot return 0; 6742c9916cdSFrançois Tigeot } 6752c9916cdSFrançois Tigeot 676a05eeebfSFrançois Tigeot #define WA_REG(addr, mask, val) do { \ 6772c9916cdSFrançois Tigeot const int r = wa_add(dev_priv, (addr), (mask), (val)); \ 6782c9916cdSFrançois Tigeot if (r) \ 6792c9916cdSFrançois Tigeot return r; \ 680a05eeebfSFrançois Tigeot } while (0) 6812c9916cdSFrançois Tigeot 6822c9916cdSFrançois Tigeot #define WA_SET_BIT_MASKED(addr, mask) \ 6832c9916cdSFrançois Tigeot WA_REG(addr, (mask), _MASKED_BIT_ENABLE(mask)) 6842c9916cdSFrançois Tigeot 6852c9916cdSFrançois Tigeot #define WA_CLR_BIT_MASKED(addr, mask) \ 6862c9916cdSFrançois Tigeot WA_REG(addr, (mask), _MASKED_BIT_DISABLE(mask)) 6872c9916cdSFrançois Tigeot 6882c9916cdSFrançois Tigeot #define WA_SET_FIELD_MASKED(addr, mask, value) \ 6892c9916cdSFrançois Tigeot WA_REG(addr, mask, _MASKED_FIELD(mask, value)) 6902c9916cdSFrançois Tigeot 6912c9916cdSFrançois Tigeot #define WA_SET_BIT(addr, mask) WA_REG(addr, mask, I915_READ(addr) | (mask)) 6922c9916cdSFrançois Tigeot #define WA_CLR_BIT(addr, mask) WA_REG(addr, mask, I915_READ(addr) & ~(mask)) 6932c9916cdSFrançois Tigeot 6942c9916cdSFrançois Tigeot #define WA_WRITE(addr, val) WA_REG(addr, 0xffffffff, val) 6952c9916cdSFrançois Tigeot 6968621f407SFrançois Tigeot static int wa_ring_whitelist_reg(struct intel_engine_cs *engine, 6978621f407SFrançois Tigeot i915_reg_t reg) 698c0e85e96SFrançois Tigeot { 6991487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 700c0e85e96SFrançois Tigeot struct i915_workarounds *wa = &dev_priv->workarounds; 7018621f407SFrançois Tigeot const uint32_t index = wa->hw_whitelist_count[engine->id]; 702c0e85e96SFrançois Tigeot 703c0e85e96SFrançois Tigeot if (WARN_ON(index >= RING_MAX_NONPRIV_SLOTS)) 704c0e85e96SFrançois Tigeot return -EINVAL; 705c0e85e96SFrançois Tigeot 7068621f407SFrançois Tigeot WA_WRITE(RING_FORCE_TO_NONPRIV(engine->mmio_base, index), 707c0e85e96SFrançois Tigeot i915_mmio_reg_offset(reg)); 7088621f407SFrançois Tigeot wa->hw_whitelist_count[engine->id]++; 709c0e85e96SFrançois Tigeot 710c0e85e96SFrançois Tigeot return 0; 711c0e85e96SFrançois Tigeot } 712c0e85e96SFrançois Tigeot 7138621f407SFrançois Tigeot static int gen8_init_workarounds(struct intel_engine_cs *engine) 7142c9916cdSFrançois Tigeot { 7151487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 7162c9916cdSFrançois Tigeot 717a05eeebfSFrançois Tigeot WA_SET_BIT_MASKED(INSTPM, INSTPM_FORCE_ORDERING); 718a05eeebfSFrançois Tigeot 719352ff8bdSFrançois Tigeot /* WaDisableAsyncFlipPerfMode:bdw,chv */ 720a05eeebfSFrançois Tigeot WA_SET_BIT_MASKED(MI_MODE, ASYNC_FLIP_PERF_DISABLE); 721a05eeebfSFrançois Tigeot 722352ff8bdSFrançois Tigeot /* WaDisablePartialInstShootdown:bdw,chv */ 7232c9916cdSFrançois Tigeot WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN, 724352ff8bdSFrançois Tigeot PARTIAL_INSTRUCTION_SHOOTDOWN_DISABLE); 7251b13d190SFrançois Tigeot 7261b13d190SFrançois Tigeot /* Use Force Non-Coherent whenever executing a 3D context. This is a 7271b13d190SFrançois Tigeot * workaround for for a possible hang in the unlikely event a TLB 7281b13d190SFrançois Tigeot * invalidation occurs during a PSD flush. 7291b13d190SFrançois Tigeot */ 730352ff8bdSFrançois Tigeot /* WaForceEnableNonCoherent:bdw,chv */ 731352ff8bdSFrançois Tigeot /* WaHdcDisableFetchWhenMasked:bdw,chv */ 7322c9916cdSFrançois Tigeot WA_SET_BIT_MASKED(HDC_CHICKEN0, 7332c9916cdSFrançois Tigeot HDC_DONOT_FETCH_MEM_WHEN_MASKED | 734352ff8bdSFrançois Tigeot HDC_FORCE_NON_COHERENT); 7352c9916cdSFrançois Tigeot 7362c9916cdSFrançois Tigeot /* From the Haswell PRM, Command Reference: Registers, CACHE_MODE_0: 7372c9916cdSFrançois Tigeot * "The Hierarchical Z RAW Stall Optimization allows non-overlapping 7382c9916cdSFrançois Tigeot * polygons in the same 8x4 pixel/sample area to be processed without 7392c9916cdSFrançois Tigeot * stalling waiting for the earlier ones to write to Hierarchical Z 7402c9916cdSFrançois Tigeot * buffer." 7412c9916cdSFrançois Tigeot * 742352ff8bdSFrançois Tigeot * This optimization is off by default for BDW and CHV; turn it on. 7432c9916cdSFrançois Tigeot */ 7442c9916cdSFrançois Tigeot WA_CLR_BIT_MASKED(CACHE_MODE_0_GEN7, HIZ_RAW_STALL_OPT_DISABLE); 7451b13d190SFrançois Tigeot 746352ff8bdSFrançois Tigeot /* Wa4x4STCOptimizationDisable:bdw,chv */ 747352ff8bdSFrançois Tigeot WA_SET_BIT_MASKED(CACHE_MODE_1, GEN8_4x4_STC_OPTIMIZATION_DISABLE); 7481b13d190SFrançois Tigeot 7491b13d190SFrançois Tigeot /* 7501b13d190SFrançois Tigeot * BSpec recommends 8x4 when MSAA is used, 7511b13d190SFrançois Tigeot * however in practice 16x4 seems fastest. 7521b13d190SFrançois Tigeot * 7531b13d190SFrançois Tigeot * Note that PS/WM thread counts depend on the WIZ hashing 7541b13d190SFrançois Tigeot * disable bit, which we don't touch here, but it's good 7551b13d190SFrançois Tigeot * to keep in mind (see 3DSTATE_PS and 3DSTATE_WM). 7561b13d190SFrançois Tigeot */ 7572c9916cdSFrançois Tigeot WA_SET_FIELD_MASKED(GEN7_GT_MODE, 7582c9916cdSFrançois Tigeot GEN6_WIZ_HASHING_MASK, 7592c9916cdSFrançois Tigeot GEN6_WIZ_HASHING_16x4); 7601b13d190SFrançois Tigeot 7611b13d190SFrançois Tigeot return 0; 7621b13d190SFrançois Tigeot } 7631b13d190SFrançois Tigeot 7648621f407SFrançois Tigeot static int bdw_init_workarounds(struct intel_engine_cs *engine) 7651b13d190SFrançois Tigeot { 7661487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 767352ff8bdSFrançois Tigeot int ret; 7681b13d190SFrançois Tigeot 7698621f407SFrançois Tigeot ret = gen8_init_workarounds(engine); 770352ff8bdSFrançois Tigeot if (ret) 771352ff8bdSFrançois Tigeot return ret; 772a05eeebfSFrançois Tigeot 773352ff8bdSFrançois Tigeot /* WaDisableThreadStallDopClockGating:bdw (pre-production) */ 774352ff8bdSFrançois Tigeot WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN, STALL_DOP_GATING_DISABLE); 775a05eeebfSFrançois Tigeot 776352ff8bdSFrançois Tigeot /* WaDisableDopClockGating:bdw */ 777352ff8bdSFrançois Tigeot WA_SET_BIT_MASKED(GEN7_ROW_CHICKEN2, 778352ff8bdSFrançois Tigeot DOP_CLOCK_GATING_DISABLE); 7791b13d190SFrançois Tigeot 780352ff8bdSFrançois Tigeot WA_SET_BIT_MASKED(HALF_SLICE_CHICKEN3, 781352ff8bdSFrançois Tigeot GEN8_SAMPLER_POWER_BYPASS_DIS); 782352ff8bdSFrançois Tigeot 7832c9916cdSFrançois Tigeot WA_SET_BIT_MASKED(HDC_CHICKEN0, 784352ff8bdSFrançois Tigeot /* WaForceContextSaveRestoreNonCoherent:bdw */ 785352ff8bdSFrançois Tigeot HDC_FORCE_CONTEXT_SAVE_RESTORE_NON_COHERENT | 786352ff8bdSFrançois Tigeot /* WaDisableFenceDestinationToSLM:bdw (pre-prod) */ 7871487f786SFrançois Tigeot (IS_BDW_GT3(dev_priv) ? HDC_FENCE_DEST_SLM_DISABLE : 0)); 7881b13d190SFrançois Tigeot 789352ff8bdSFrançois Tigeot return 0; 790352ff8bdSFrançois Tigeot } 7911b13d190SFrançois Tigeot 7928621f407SFrançois Tigeot static int chv_init_workarounds(struct intel_engine_cs *engine) 793352ff8bdSFrançois Tigeot { 7941487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 795352ff8bdSFrançois Tigeot int ret; 796352ff8bdSFrançois Tigeot 7978621f407SFrançois Tigeot ret = gen8_init_workarounds(engine); 798352ff8bdSFrançois Tigeot if (ret) 799352ff8bdSFrançois Tigeot return ret; 800352ff8bdSFrançois Tigeot 801352ff8bdSFrançois Tigeot /* WaDisableThreadStallDopClockGating:chv */ 802352ff8bdSFrançois Tigeot WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN, STALL_DOP_GATING_DISABLE); 8032c9916cdSFrançois Tigeot 8042c9916cdSFrançois Tigeot /* Improve HiZ throughput on CHV. */ 8052c9916cdSFrançois Tigeot WA_SET_BIT_MASKED(HIZ_CHICKEN, CHV_HZ_8X8_MODE_IN_1X); 8062c9916cdSFrançois Tigeot 8072c9916cdSFrançois Tigeot return 0; 8082c9916cdSFrançois Tigeot } 8092c9916cdSFrançois Tigeot 8108621f407SFrançois Tigeot static int gen9_init_workarounds(struct intel_engine_cs *engine) 811477eb7f9SFrançois Tigeot { 8121487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 813c0e85e96SFrançois Tigeot int ret; 814477eb7f9SFrançois Tigeot 8158621f407SFrançois Tigeot /* WaConextSwitchWithConcurrentTLBInvalidate:skl,bxt,kbl */ 8168621f407SFrançois Tigeot I915_WRITE(GEN9_CSFE_CHICKEN1_RCS, _MASKED_BIT_ENABLE(GEN9_PREEMPT_GPGPU_SYNC_SWITCH_DISABLE)); 8178621f407SFrançois Tigeot 8188621f407SFrançois Tigeot /* WaEnableLbsSlaRetryTimerDecrement:skl,bxt,kbl */ 819352ff8bdSFrançois Tigeot I915_WRITE(BDW_SCRATCH1, I915_READ(BDW_SCRATCH1) | 820352ff8bdSFrançois Tigeot GEN9_LBS_SLA_RETRY_TIMER_DECREMENT_ENABLE); 821352ff8bdSFrançois Tigeot 8228621f407SFrançois Tigeot /* WaDisableKillLogic:bxt,skl,kbl */ 823352ff8bdSFrançois Tigeot I915_WRITE(GAM_ECOCHK, I915_READ(GAM_ECOCHK) | 824352ff8bdSFrançois Tigeot ECOCHK_DIS_TLB); 825352ff8bdSFrançois Tigeot 8268621f407SFrançois Tigeot /* WaClearFlowControlGpgpuContextSave:skl,bxt,kbl */ 8278621f407SFrançois Tigeot /* WaDisablePartialInstShootdown:skl,bxt,kbl */ 828477eb7f9SFrançois Tigeot WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN, 8298621f407SFrançois Tigeot FLOW_CONTROL_ENABLE | 830477eb7f9SFrançois Tigeot PARTIAL_INSTRUCTION_SHOOTDOWN_DISABLE); 831477eb7f9SFrançois Tigeot 8328621f407SFrançois Tigeot /* Syncing dependencies between camera and graphics:skl,bxt,kbl */ 833477eb7f9SFrançois Tigeot WA_SET_BIT_MASKED(HALF_SLICE_CHICKEN3, 834477eb7f9SFrançois Tigeot GEN9_DISABLE_OCL_OOB_SUPPRESS_LOGIC); 835477eb7f9SFrançois Tigeot 836*1e12ee3bSFrançois Tigeot /* WaDisableDgMirrorFixInHalfSliceChicken5:bxt */ 837*1e12ee3bSFrançois Tigeot if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1)) 838477eb7f9SFrançois Tigeot WA_CLR_BIT_MASKED(GEN9_HALF_SLICE_CHICKEN5, 839477eb7f9SFrançois Tigeot GEN9_DG_MIRROR_FIX_ENABLE); 840477eb7f9SFrançois Tigeot 841*1e12ee3bSFrançois Tigeot /* WaSetDisablePixMaskCammingAndRhwoInCommonSliceChicken:bxt */ 842*1e12ee3bSFrançois Tigeot if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1)) { 843477eb7f9SFrançois Tigeot WA_SET_BIT_MASKED(GEN7_COMMON_SLICE_CHICKEN1, 844477eb7f9SFrançois Tigeot GEN9_RHWO_OPTIMIZATION_DISABLE); 845a05eeebfSFrançois Tigeot /* 846a05eeebfSFrançois Tigeot * WA also requires GEN9_SLICE_COMMON_ECO_CHICKEN0[14:14] to be set 847a05eeebfSFrançois Tigeot * but we do that in per ctx batchbuffer as there is an issue 848a05eeebfSFrançois Tigeot * with this register not getting restored on ctx restore 849a05eeebfSFrançois Tigeot */ 850477eb7f9SFrançois Tigeot } 851477eb7f9SFrançois Tigeot 8528621f407SFrançois Tigeot /* WaEnableSamplerGPGPUPreemptionSupport:skl,bxt,kbl */ 853477eb7f9SFrançois Tigeot WA_SET_BIT_MASKED(GEN9_HALF_SLICE_CHICKEN7, 8548621f407SFrançois Tigeot GEN9_ENABLE_GPGPU_PREEMPTION); 855477eb7f9SFrançois Tigeot 8568621f407SFrançois Tigeot /* Wa4x4STCOptimizationDisable:skl,bxt,kbl */ 8578621f407SFrançois Tigeot /* WaDisablePartialResolveInVc:skl,bxt,kbl */ 858352ff8bdSFrançois Tigeot WA_SET_BIT_MASKED(CACHE_MODE_1, (GEN8_4x4_STC_OPTIMIZATION_DISABLE | 859352ff8bdSFrançois Tigeot GEN9_PARTIAL_RESOLVE_IN_VC_DISABLE)); 860477eb7f9SFrançois Tigeot 8618621f407SFrançois Tigeot /* WaCcsTlbPrefetchDisable:skl,bxt,kbl */ 862477eb7f9SFrançois Tigeot WA_CLR_BIT_MASKED(GEN9_HALF_SLICE_CHICKEN5, 863477eb7f9SFrançois Tigeot GEN9_CCS_TLB_PREFETCH_ENABLE); 864477eb7f9SFrançois Tigeot 865*1e12ee3bSFrançois Tigeot /* WaDisableMaskBasedCammingInRCC:bxt */ 866*1e12ee3bSFrançois Tigeot if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1)) 86719c468b4SFrançois Tigeot WA_SET_BIT_MASKED(SLICE_ECO_CHICKEN0, 86819c468b4SFrançois Tigeot PIXEL_MASK_CAMMING_DISABLE); 86919c468b4SFrançois Tigeot 8708621f407SFrançois Tigeot /* WaForceContextSaveRestoreNonCoherent:skl,bxt,kbl */ 8718621f407SFrançois Tigeot WA_SET_BIT_MASKED(HDC_CHICKEN0, 8728621f407SFrançois Tigeot HDC_FORCE_CONTEXT_SAVE_RESTORE_NON_COHERENT | 8738621f407SFrançois Tigeot HDC_FORCE_CSR_NON_COHERENT_OVR_DISABLE); 87419c468b4SFrançois Tigeot 8758621f407SFrançois Tigeot /* WaForceEnableNonCoherent and WaDisableHDCInvalidation are 8768621f407SFrançois Tigeot * both tied to WaForceContextSaveRestoreNonCoherent 8778621f407SFrançois Tigeot * in some hsds for skl. We keep the tie for all gen9. The 8788621f407SFrançois Tigeot * documentation is a bit hazy and so we want to get common behaviour, 8798621f407SFrançois Tigeot * even though there is no clear evidence we would need both on kbl/bxt. 8808621f407SFrançois Tigeot * This area has been source of system hangs so we play it safe 8818621f407SFrançois Tigeot * and mimic the skl regardless of what bspec says. 8828621f407SFrançois Tigeot * 8838621f407SFrançois Tigeot * Use Force Non-Coherent whenever executing a 3D context. This 8848621f407SFrançois Tigeot * is a workaround for a possible hang in the unlikely event 8858621f407SFrançois Tigeot * a TLB invalidation occurs during a PSD flush. 8868621f407SFrançois Tigeot */ 8878621f407SFrançois Tigeot 8888621f407SFrançois Tigeot /* WaForceEnableNonCoherent:skl,bxt,kbl */ 8898621f407SFrançois Tigeot WA_SET_BIT_MASKED(HDC_CHICKEN0, 8908621f407SFrançois Tigeot HDC_FORCE_NON_COHERENT); 8918621f407SFrançois Tigeot 8928621f407SFrançois Tigeot /* WaDisableHDCInvalidation:skl,bxt,kbl */ 8938621f407SFrançois Tigeot I915_WRITE(GAM_ECOCHK, I915_READ(GAM_ECOCHK) | 8948621f407SFrançois Tigeot BDW_DISABLE_HDC_INVALIDATION); 8958621f407SFrançois Tigeot 8968621f407SFrançois Tigeot /* WaDisableSamplerPowerBypassForSOPingPong:skl,bxt,kbl */ 8978621f407SFrançois Tigeot if (IS_SKYLAKE(dev_priv) || 8988621f407SFrançois Tigeot IS_KABYLAKE(dev_priv) || 8998621f407SFrançois Tigeot IS_BXT_REVID(dev_priv, 0, BXT_REVID_B0)) 900352ff8bdSFrançois Tigeot WA_SET_BIT_MASKED(HALF_SLICE_CHICKEN3, 901352ff8bdSFrançois Tigeot GEN8_SAMPLER_POWER_BYPASS_DIS); 902352ff8bdSFrançois Tigeot 9038621f407SFrançois Tigeot /* WaDisableSTUnitPowerOptimization:skl,bxt,kbl */ 904352ff8bdSFrançois Tigeot WA_SET_BIT_MASKED(HALF_SLICE_CHICKEN2, GEN8_ST_PO_DISABLE); 905352ff8bdSFrançois Tigeot 9068621f407SFrançois Tigeot /* WaOCLCoherentLineFlush:skl,bxt,kbl */ 907c0e85e96SFrançois Tigeot I915_WRITE(GEN8_L3SQCREG4, (I915_READ(GEN8_L3SQCREG4) | 908c0e85e96SFrançois Tigeot GEN8_LQSC_FLUSH_COHERENT_LINES)); 909c0e85e96SFrançois Tigeot 9108621f407SFrançois Tigeot /* WaVFEStateAfterPipeControlwithMediaStateClear:skl,bxt */ 9118621f407SFrançois Tigeot ret = wa_ring_whitelist_reg(engine, GEN9_CTX_PREEMPT_REG); 912c0e85e96SFrançois Tigeot if (ret) 913c0e85e96SFrançois Tigeot return ret; 914c0e85e96SFrançois Tigeot 9158621f407SFrançois Tigeot /* WaEnablePreemptionGranularityControlByUMD:skl,bxt,kbl */ 9168621f407SFrançois Tigeot ret= wa_ring_whitelist_reg(engine, GEN8_CS_CHICKEN1); 9178621f407SFrançois Tigeot if (ret) 9188621f407SFrançois Tigeot return ret; 9198621f407SFrançois Tigeot 9208621f407SFrançois Tigeot /* WaAllowUMDToModifyHDCChicken1:skl,bxt,kbl */ 9218621f407SFrançois Tigeot ret = wa_ring_whitelist_reg(engine, GEN8_HDC_CHICKEN1); 922c0e85e96SFrançois Tigeot if (ret) 923c0e85e96SFrançois Tigeot return ret; 924c0e85e96SFrançois Tigeot 925477eb7f9SFrançois Tigeot return 0; 926477eb7f9SFrançois Tigeot } 927477eb7f9SFrançois Tigeot 9288621f407SFrançois Tigeot static int skl_tune_iz_hashing(struct intel_engine_cs *engine) 929477eb7f9SFrançois Tigeot { 9301487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 931477eb7f9SFrançois Tigeot u8 vals[3] = { 0, 0, 0 }; 932477eb7f9SFrançois Tigeot unsigned int i; 933477eb7f9SFrançois Tigeot 934477eb7f9SFrançois Tigeot for (i = 0; i < 3; i++) { 935477eb7f9SFrançois Tigeot u8 ss; 936477eb7f9SFrançois Tigeot 937477eb7f9SFrançois Tigeot /* 938477eb7f9SFrançois Tigeot * Only consider slices where one, and only one, subslice has 7 939477eb7f9SFrançois Tigeot * EUs 940477eb7f9SFrançois Tigeot */ 941*1e12ee3bSFrançois Tigeot if (!is_power_of_2(INTEL_INFO(dev_priv)->sseu.subslice_7eu[i])) 942477eb7f9SFrançois Tigeot continue; 943477eb7f9SFrançois Tigeot 944477eb7f9SFrançois Tigeot /* 945477eb7f9SFrançois Tigeot * subslice_7eu[i] != 0 (because of the check above) and 946477eb7f9SFrançois Tigeot * ss_max == 4 (maximum number of subslices possible per slice) 947477eb7f9SFrançois Tigeot * 948477eb7f9SFrançois Tigeot * -> 0 <= ss <= 3; 949477eb7f9SFrançois Tigeot */ 950*1e12ee3bSFrançois Tigeot ss = ffs(INTEL_INFO(dev_priv)->sseu.subslice_7eu[i]) - 1; 951477eb7f9SFrançois Tigeot vals[i] = 3 - ss; 952477eb7f9SFrançois Tigeot } 953477eb7f9SFrançois Tigeot 954477eb7f9SFrançois Tigeot if (vals[0] == 0 && vals[1] == 0 && vals[2] == 0) 955477eb7f9SFrançois Tigeot return 0; 956477eb7f9SFrançois Tigeot 957477eb7f9SFrançois Tigeot /* Tune IZ hashing. See intel_device_info_runtime_init() */ 958477eb7f9SFrançois Tigeot WA_SET_FIELD_MASKED(GEN7_GT_MODE, 959477eb7f9SFrançois Tigeot GEN9_IZ_HASHING_MASK(2) | 960477eb7f9SFrançois Tigeot GEN9_IZ_HASHING_MASK(1) | 961477eb7f9SFrançois Tigeot GEN9_IZ_HASHING_MASK(0), 962477eb7f9SFrançois Tigeot GEN9_IZ_HASHING(2, vals[2]) | 963477eb7f9SFrançois Tigeot GEN9_IZ_HASHING(1, vals[1]) | 964477eb7f9SFrançois Tigeot GEN9_IZ_HASHING(0, vals[0])); 965477eb7f9SFrançois Tigeot 966477eb7f9SFrançois Tigeot return 0; 967477eb7f9SFrançois Tigeot } 968477eb7f9SFrançois Tigeot 9698621f407SFrançois Tigeot static int skl_init_workarounds(struct intel_engine_cs *engine) 970477eb7f9SFrançois Tigeot { 9711487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 972352ff8bdSFrançois Tigeot int ret; 973477eb7f9SFrançois Tigeot 9748621f407SFrançois Tigeot ret = gen9_init_workarounds(engine); 975352ff8bdSFrançois Tigeot if (ret) 976352ff8bdSFrançois Tigeot return ret; 977352ff8bdSFrançois Tigeot 978c0e85e96SFrançois Tigeot /* 979c0e85e96SFrançois Tigeot * Actual WA is to disable percontext preemption granularity control 980c0e85e96SFrançois Tigeot * until D0 which is the default case so this is equivalent to 981c0e85e96SFrançois Tigeot * !WaDisablePerCtxtPreemptionGranularityControl:skl 982c0e85e96SFrançois Tigeot */ 983c0e85e96SFrançois Tigeot I915_WRITE(GEN7_FF_SLICE_CS_CHICKEN1, 984c0e85e96SFrançois Tigeot _MASKED_BIT_ENABLE(GEN9_FFSC_PERCTX_PREEMPT_CTRL)); 985352ff8bdSFrançois Tigeot 986352ff8bdSFrançois Tigeot /* WaEnableGapsTsvCreditFix:skl */ 987352ff8bdSFrançois Tigeot I915_WRITE(GEN8_GARBCNTL, (I915_READ(GEN8_GARBCNTL) | 988352ff8bdSFrançois Tigeot GEN9_GAPS_TSV_CREDIT_DISABLE)); 989a05eeebfSFrançois Tigeot 9908621f407SFrançois Tigeot /* WaDisableGafsUnitClkGating:skl */ 9918621f407SFrançois Tigeot WA_SET_BIT(GEN7_UCGCTL4, GEN8_EU_GAUNIT_CLOCK_GATE_DISABLE); 9928621f407SFrançois Tigeot 993bf017597SFrançois Tigeot /* WaInPlaceDecompressionHang:skl */ 994bf017597SFrançois Tigeot if (IS_SKL_REVID(dev_priv, SKL_REVID_H0, REVID_FOREVER)) 995bf017597SFrançois Tigeot WA_SET_BIT(GEN9_GAMT_ECO_REG_RW_IA, 996bf017597SFrançois Tigeot GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS); 997bf017597SFrançois Tigeot 998c0e85e96SFrançois Tigeot /* WaDisableLSQCROPERFforOCL:skl */ 9998621f407SFrançois Tigeot ret = wa_ring_whitelist_reg(engine, GEN8_L3SQCREG4); 1000c0e85e96SFrançois Tigeot if (ret) 1001c0e85e96SFrançois Tigeot return ret; 1002c0e85e96SFrançois Tigeot 10038621f407SFrançois Tigeot return skl_tune_iz_hashing(engine); 1004477eb7f9SFrançois Tigeot } 1005477eb7f9SFrançois Tigeot 10068621f407SFrançois Tigeot static int bxt_init_workarounds(struct intel_engine_cs *engine) 100719c468b4SFrançois Tigeot { 10081487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 1009352ff8bdSFrançois Tigeot int ret; 101019c468b4SFrançois Tigeot 10118621f407SFrançois Tigeot ret = gen9_init_workarounds(engine); 1012352ff8bdSFrançois Tigeot if (ret) 1013352ff8bdSFrançois Tigeot return ret; 1014352ff8bdSFrançois Tigeot 1015352ff8bdSFrançois Tigeot /* WaStoreMultiplePTEenable:bxt */ 1016352ff8bdSFrançois Tigeot /* This is a requirement according to Hardware specification */ 10171487f786SFrançois Tigeot if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1)) 1018352ff8bdSFrançois Tigeot I915_WRITE(TILECTL, I915_READ(TILECTL) | TILECTL_TLBPF); 1019352ff8bdSFrançois Tigeot 1020352ff8bdSFrançois Tigeot /* WaSetClckGatingDisableMedia:bxt */ 10211487f786SFrançois Tigeot if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1)) { 1022352ff8bdSFrançois Tigeot I915_WRITE(GEN7_MISCCPCTL, (I915_READ(GEN7_MISCCPCTL) & 1023352ff8bdSFrançois Tigeot ~GEN8_DOP_CLOCK_GATE_MEDIA_ENABLE)); 1024352ff8bdSFrançois Tigeot } 102519c468b4SFrançois Tigeot 102619c468b4SFrançois Tigeot /* WaDisableThreadStallDopClockGating:bxt */ 102719c468b4SFrançois Tigeot WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN, 102819c468b4SFrançois Tigeot STALL_DOP_GATING_DISABLE); 102919c468b4SFrançois Tigeot 10301487f786SFrançois Tigeot /* WaDisablePooledEuLoadBalancingFix:bxt */ 10311487f786SFrançois Tigeot if (IS_BXT_REVID(dev_priv, BXT_REVID_B0, REVID_FOREVER)) { 10321487f786SFrançois Tigeot WA_SET_BIT_MASKED(FF_SLICE_CS_CHICKEN2, 10331487f786SFrançois Tigeot GEN9_POOLED_EU_LOAD_BALANCING_FIX_DISABLE); 10341487f786SFrançois Tigeot } 10351487f786SFrançois Tigeot 103619c468b4SFrançois Tigeot /* WaDisableSbeCacheDispatchPortSharing:bxt */ 10371487f786SFrançois Tigeot if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_B0)) { 103819c468b4SFrançois Tigeot WA_SET_BIT_MASKED( 103919c468b4SFrançois Tigeot GEN7_HALF_SLICE_CHICKEN1, 104019c468b4SFrançois Tigeot GEN7_SBE_SS_CACHE_DISPATCH_PORT_SHARING_DISABLE); 104119c468b4SFrançois Tigeot } 104219c468b4SFrançois Tigeot 1043c0e85e96SFrançois Tigeot /* WaDisableObjectLevelPreemptionForTrifanOrPolygon:bxt */ 1044c0e85e96SFrançois Tigeot /* WaDisableObjectLevelPreemptionForInstancedDraw:bxt */ 1045c0e85e96SFrançois Tigeot /* WaDisableObjectLevelPreemtionForInstanceId:bxt */ 1046c0e85e96SFrançois Tigeot /* WaDisableLSQCROPERFforOCL:bxt */ 10471487f786SFrançois Tigeot if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1)) { 10488621f407SFrançois Tigeot ret = wa_ring_whitelist_reg(engine, GEN9_CS_DEBUG_MODE1); 1049c0e85e96SFrançois Tigeot if (ret) 1050c0e85e96SFrançois Tigeot return ret; 1051c0e85e96SFrançois Tigeot 10528621f407SFrançois Tigeot ret = wa_ring_whitelist_reg(engine, GEN8_L3SQCREG4); 1053c0e85e96SFrançois Tigeot if (ret) 1054c0e85e96SFrançois Tigeot return ret; 1055c0e85e96SFrançois Tigeot } 1056c0e85e96SFrançois Tigeot 10571487f786SFrançois Tigeot /* WaProgramL3SqcReg1DefaultForPerf:bxt */ 10581487f786SFrançois Tigeot if (IS_BXT_REVID(dev_priv, BXT_REVID_B0, REVID_FOREVER)) 10591487f786SFrançois Tigeot I915_WRITE(GEN8_L3SQCREG1, L3_GENERAL_PRIO_CREDITS(62) | 10601487f786SFrançois Tigeot L3_HIGH_PRIO_CREDITS(2)); 10611487f786SFrançois Tigeot 1062bf017597SFrançois Tigeot /* WaToEnableHwFixForPushConstHWBug:bxt */ 1063bf017597SFrançois Tigeot if (IS_BXT_REVID(dev_priv, BXT_REVID_C0, REVID_FOREVER)) 10648621f407SFrançois Tigeot WA_SET_BIT_MASKED(COMMON_SLICE_CHICKEN2, 10658621f407SFrançois Tigeot GEN8_SBE_DISABLE_REPLAY_BUF_OPTIMIZATION); 10668621f407SFrançois Tigeot 1067bf017597SFrançois Tigeot /* WaInPlaceDecompressionHang:bxt */ 1068bf017597SFrançois Tigeot if (IS_BXT_REVID(dev_priv, BXT_REVID_C0, REVID_FOREVER)) 1069bf017597SFrançois Tigeot WA_SET_BIT(GEN9_GAMT_ECO_REG_RW_IA, 1070bf017597SFrançois Tigeot GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS); 1071bf017597SFrançois Tigeot 107219c468b4SFrançois Tigeot return 0; 107319c468b4SFrançois Tigeot } 107419c468b4SFrançois Tigeot 10758621f407SFrançois Tigeot static int kbl_init_workarounds(struct intel_engine_cs *engine) 10762c9916cdSFrançois Tigeot { 10771487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 10788621f407SFrançois Tigeot int ret; 10798621f407SFrançois Tigeot 10808621f407SFrançois Tigeot ret = gen9_init_workarounds(engine); 10818621f407SFrançois Tigeot if (ret) 10828621f407SFrançois Tigeot return ret; 10838621f407SFrançois Tigeot 10848621f407SFrançois Tigeot /* WaEnableGapsTsvCreditFix:kbl */ 10858621f407SFrançois Tigeot I915_WRITE(GEN8_GARBCNTL, (I915_READ(GEN8_GARBCNTL) | 10868621f407SFrançois Tigeot GEN9_GAPS_TSV_CREDIT_DISABLE)); 10878621f407SFrançois Tigeot 10888621f407SFrançois Tigeot /* WaDisableDynamicCreditSharing:kbl */ 10898621f407SFrançois Tigeot if (IS_KBL_REVID(dev_priv, 0, KBL_REVID_B0)) 10908621f407SFrançois Tigeot WA_SET_BIT(GAMT_CHKN_BIT_REG, 10918621f407SFrançois Tigeot GAMT_CHKN_DISABLE_DYNAMIC_CREDIT_SHARING); 10928621f407SFrançois Tigeot 10938621f407SFrançois Tigeot /* WaDisableFenceDestinationToSLM:kbl (pre-prod) */ 10948621f407SFrançois Tigeot if (IS_KBL_REVID(dev_priv, KBL_REVID_A0, KBL_REVID_A0)) 10958621f407SFrançois Tigeot WA_SET_BIT_MASKED(HDC_CHICKEN0, 10968621f407SFrançois Tigeot HDC_FENCE_DEST_SLM_DISABLE); 10978621f407SFrançois Tigeot 10988621f407SFrançois Tigeot /* GEN8_L3SQCREG4 has a dependency with WA batch so any new changes 10998621f407SFrançois Tigeot * involving this register should also be added to WA batch as required. 11008621f407SFrançois Tigeot */ 11018621f407SFrançois Tigeot if (IS_KBL_REVID(dev_priv, 0, KBL_REVID_E0)) 11028621f407SFrançois Tigeot /* WaDisableLSQCROPERFforOCL:kbl */ 11038621f407SFrançois Tigeot I915_WRITE(GEN8_L3SQCREG4, I915_READ(GEN8_L3SQCREG4) | 11048621f407SFrançois Tigeot GEN8_LQSC_RO_PERF_DIS); 11058621f407SFrançois Tigeot 1106bf017597SFrançois Tigeot /* WaToEnableHwFixForPushConstHWBug:kbl */ 1107bf017597SFrançois Tigeot if (IS_KBL_REVID(dev_priv, KBL_REVID_C0, REVID_FOREVER)) 11088621f407SFrançois Tigeot WA_SET_BIT_MASKED(COMMON_SLICE_CHICKEN2, 11098621f407SFrançois Tigeot GEN8_SBE_DISABLE_REPLAY_BUF_OPTIMIZATION); 11108621f407SFrançois Tigeot 11118621f407SFrançois Tigeot /* WaDisableGafsUnitClkGating:kbl */ 11128621f407SFrançois Tigeot WA_SET_BIT(GEN7_UCGCTL4, GEN8_EU_GAUNIT_CLOCK_GATE_DISABLE); 11138621f407SFrançois Tigeot 11148621f407SFrançois Tigeot /* WaDisableSbeCacheDispatchPortSharing:kbl */ 11158621f407SFrançois Tigeot WA_SET_BIT_MASKED( 11168621f407SFrançois Tigeot GEN7_HALF_SLICE_CHICKEN1, 11178621f407SFrançois Tigeot GEN7_SBE_SS_CACHE_DISPATCH_PORT_SHARING_DISABLE); 11188621f407SFrançois Tigeot 1119bf017597SFrançois Tigeot /* WaInPlaceDecompressionHang:kbl */ 1120bf017597SFrançois Tigeot WA_SET_BIT(GEN9_GAMT_ECO_REG_RW_IA, 1121bf017597SFrançois Tigeot GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS); 1122bf017597SFrançois Tigeot 11238621f407SFrançois Tigeot /* WaDisableLSQCROPERFforOCL:kbl */ 11248621f407SFrançois Tigeot ret = wa_ring_whitelist_reg(engine, GEN8_L3SQCREG4); 11258621f407SFrançois Tigeot if (ret) 11268621f407SFrançois Tigeot return ret; 11278621f407SFrançois Tigeot 11288621f407SFrançois Tigeot return 0; 11298621f407SFrançois Tigeot } 11308621f407SFrançois Tigeot 11318621f407SFrançois Tigeot int init_workarounds_ring(struct intel_engine_cs *engine) 11328621f407SFrançois Tigeot { 11331487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 11342c9916cdSFrançois Tigeot 11358621f407SFrançois Tigeot WARN_ON(engine->id != RCS); 11362c9916cdSFrançois Tigeot 11372c9916cdSFrançois Tigeot dev_priv->workarounds.count = 0; 1138c0e85e96SFrançois Tigeot dev_priv->workarounds.hw_whitelist_count[RCS] = 0; 11392c9916cdSFrançois Tigeot 11401487f786SFrançois Tigeot if (IS_BROADWELL(dev_priv)) 11418621f407SFrançois Tigeot return bdw_init_workarounds(engine); 11422c9916cdSFrançois Tigeot 11431487f786SFrançois Tigeot if (IS_CHERRYVIEW(dev_priv)) 11448621f407SFrançois Tigeot return chv_init_workarounds(engine); 11451b13d190SFrançois Tigeot 11461487f786SFrançois Tigeot if (IS_SKYLAKE(dev_priv)) 11478621f407SFrançois Tigeot return skl_init_workarounds(engine); 114819c468b4SFrançois Tigeot 11491487f786SFrançois Tigeot if (IS_BROXTON(dev_priv)) 11508621f407SFrançois Tigeot return bxt_init_workarounds(engine); 11518621f407SFrançois Tigeot 11528621f407SFrançois Tigeot if (IS_KABYLAKE(dev_priv)) 11538621f407SFrançois Tigeot return kbl_init_workarounds(engine); 1154477eb7f9SFrançois Tigeot 11551b13d190SFrançois Tigeot return 0; 11561b13d190SFrançois Tigeot } 11571b13d190SFrançois Tigeot 11588621f407SFrançois Tigeot static int init_render_ring(struct intel_engine_cs *engine) 1159e3adcf8fSFrançois Tigeot { 11601487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 11618621f407SFrançois Tigeot int ret = init_ring_common(engine); 116224edb884SFrançois Tigeot if (ret) 116324edb884SFrançois Tigeot return ret; 1164e3adcf8fSFrançois Tigeot 1165ba55f2f5SFrançois Tigeot /* WaTimedSingleVertexDispatch:cl,bw,ctg,elk,ilk,snb */ 11661487f786SFrançois Tigeot if (IS_GEN(dev_priv, 4, 6)) 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 */ 11751487f786SFrançois Tigeot if (IS_GEN(dev_priv, 6, 7)) 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 */ 11801487f786SFrançois Tigeot if (IS_GEN6(dev_priv)) 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 */ 11851487f786SFrançois Tigeot if (IS_GEN7(dev_priv)) 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 11901487f786SFrançois Tigeot if (IS_GEN6(dev_priv)) { 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 12001487f786SFrançois Tigeot if (IS_GEN(dev_priv, 6, 7)) 1201f4e1c372SFrançois Tigeot I915_WRITE(INSTPM, _MASKED_BIT_ENABLE(INSTPM_FORCE_ORDERING)); 1202f4e1c372SFrançois Tigeot 1203303bf270SFrançois Tigeot if (INTEL_INFO(dev_priv)->gen >= 6) 1204303bf270SFrançois Tigeot I915_WRITE_IMR(engine, ~engine->irq_keep_mask); 1205e3adcf8fSFrançois Tigeot 12068621f407SFrançois Tigeot return init_workarounds_ring(engine); 1207e3adcf8fSFrançois Tigeot } 1208e3adcf8fSFrançois Tigeot 12098621f407SFrançois Tigeot static void render_ring_cleanup(struct intel_engine_cs *engine) 1210e3adcf8fSFrançois Tigeot { 12111487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 121224edb884SFrançois Tigeot 1213*1e12ee3bSFrançois Tigeot i915_vma_unpin_and_release(&dev_priv->semaphore); 1214e3adcf8fSFrançois Tigeot } 1215e3adcf8fSFrançois Tigeot 121671f41f3eSFrançois Tigeot static int gen8_rcs_signal(struct drm_i915_gem_request *req) 121724edb884SFrançois Tigeot { 121871f41f3eSFrançois Tigeot struct intel_ring *ring = req->ring; 121971f41f3eSFrançois Tigeot struct drm_i915_private *dev_priv = req->i915; 122024edb884SFrançois Tigeot struct intel_engine_cs *waiter; 12218621f407SFrançois Tigeot enum intel_engine_id id; 12228621f407SFrançois Tigeot int ret, num_rings; 122324edb884SFrançois Tigeot 1224*1e12ee3bSFrançois Tigeot num_rings = INTEL_INFO(dev_priv)->num_rings; 122571f41f3eSFrançois Tigeot ret = intel_ring_begin(req, (num_rings-1) * 8); 122624edb884SFrançois Tigeot if (ret) 122724edb884SFrançois Tigeot return ret; 122824edb884SFrançois Tigeot 1229*1e12ee3bSFrançois Tigeot for_each_engine(waiter, dev_priv, id) { 123071f41f3eSFrançois Tigeot u64 gtt_offset = req->engine->semaphore.signal_ggtt[id]; 123124edb884SFrançois Tigeot if (gtt_offset == MI_SEMAPHORE_SYNC_INVALID) 123224edb884SFrançois Tigeot continue; 123324edb884SFrançois Tigeot 123471f41f3eSFrançois Tigeot intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(6)); 123571f41f3eSFrançois Tigeot intel_ring_emit(ring, 123671f41f3eSFrançois Tigeot PIPE_CONTROL_GLOBAL_GTT_IVB | 123724edb884SFrançois Tigeot PIPE_CONTROL_QW_WRITE | 12381487f786SFrançois Tigeot PIPE_CONTROL_CS_STALL); 123971f41f3eSFrançois Tigeot intel_ring_emit(ring, lower_32_bits(gtt_offset)); 124071f41f3eSFrançois Tigeot intel_ring_emit(ring, upper_32_bits(gtt_offset)); 124171f41f3eSFrançois Tigeot intel_ring_emit(ring, req->fence.seqno); 124271f41f3eSFrançois Tigeot intel_ring_emit(ring, 0); 124371f41f3eSFrançois Tigeot intel_ring_emit(ring, 124471f41f3eSFrançois Tigeot MI_SEMAPHORE_SIGNAL | 12458621f407SFrançois Tigeot MI_SEMAPHORE_TARGET(waiter->hw_id)); 124671f41f3eSFrançois Tigeot intel_ring_emit(ring, 0); 124724edb884SFrançois Tigeot } 124871f41f3eSFrançois Tigeot intel_ring_advance(ring); 124924edb884SFrançois Tigeot 125024edb884SFrançois Tigeot return 0; 125124edb884SFrançois Tigeot } 125224edb884SFrançois Tigeot 125371f41f3eSFrançois Tigeot static int gen8_xcs_signal(struct drm_i915_gem_request *req) 125424edb884SFrançois Tigeot { 125571f41f3eSFrançois Tigeot struct intel_ring *ring = req->ring; 125671f41f3eSFrançois Tigeot struct drm_i915_private *dev_priv = req->i915; 125724edb884SFrançois Tigeot struct intel_engine_cs *waiter; 12588621f407SFrançois Tigeot enum intel_engine_id id; 12598621f407SFrançois Tigeot int ret, num_rings; 126024edb884SFrançois Tigeot 1261*1e12ee3bSFrançois Tigeot num_rings = INTEL_INFO(dev_priv)->num_rings; 126271f41f3eSFrançois Tigeot ret = intel_ring_begin(req, (num_rings-1) * 6); 126324edb884SFrançois Tigeot if (ret) 126424edb884SFrançois Tigeot return ret; 126524edb884SFrançois Tigeot 1266*1e12ee3bSFrançois Tigeot for_each_engine(waiter, dev_priv, id) { 126771f41f3eSFrançois Tigeot u64 gtt_offset = req->engine->semaphore.signal_ggtt[id]; 126824edb884SFrançois Tigeot if (gtt_offset == MI_SEMAPHORE_SYNC_INVALID) 126924edb884SFrançois Tigeot continue; 127024edb884SFrançois Tigeot 127171f41f3eSFrançois Tigeot intel_ring_emit(ring, 127271f41f3eSFrançois Tigeot (MI_FLUSH_DW + 1) | MI_FLUSH_DW_OP_STOREDW); 127371f41f3eSFrançois Tigeot intel_ring_emit(ring, 127471f41f3eSFrançois Tigeot lower_32_bits(gtt_offset) | 127524edb884SFrançois Tigeot MI_FLUSH_DW_USE_GTT); 127671f41f3eSFrançois Tigeot intel_ring_emit(ring, upper_32_bits(gtt_offset)); 127771f41f3eSFrançois Tigeot intel_ring_emit(ring, req->fence.seqno); 127871f41f3eSFrançois Tigeot intel_ring_emit(ring, 127971f41f3eSFrançois Tigeot MI_SEMAPHORE_SIGNAL | 12808621f407SFrançois Tigeot MI_SEMAPHORE_TARGET(waiter->hw_id)); 128171f41f3eSFrançois Tigeot intel_ring_emit(ring, 0); 128224edb884SFrançois Tigeot } 128371f41f3eSFrançois Tigeot intel_ring_advance(ring); 128424edb884SFrançois Tigeot 128524edb884SFrançois Tigeot return 0; 128624edb884SFrançois Tigeot } 128724edb884SFrançois Tigeot 128871f41f3eSFrançois Tigeot static int gen6_signal(struct drm_i915_gem_request *req) 1289e3adcf8fSFrançois Tigeot { 129071f41f3eSFrançois Tigeot struct intel_ring *ring = req->ring; 129171f41f3eSFrançois Tigeot struct drm_i915_private *dev_priv = req->i915; 1292*1e12ee3bSFrançois Tigeot struct intel_engine_cs *engine; 12938621f407SFrançois Tigeot enum intel_engine_id id; 12948621f407SFrançois Tigeot int ret, num_rings; 1295ba55f2f5SFrançois Tigeot 1296*1e12ee3bSFrançois Tigeot num_rings = INTEL_INFO(dev_priv)->num_rings; 129771f41f3eSFrançois Tigeot ret = intel_ring_begin(req, round_up((num_rings-1) * 3, 2)); 1298ba55f2f5SFrançois Tigeot if (ret) 1299ba55f2f5SFrançois Tigeot return ret; 1300ba55f2f5SFrançois Tigeot 1301*1e12ee3bSFrançois Tigeot for_each_engine(engine, dev_priv, id) { 1302*1e12ee3bSFrançois Tigeot i915_reg_t mbox_reg; 1303aee94f86SFrançois Tigeot 1304*1e12ee3bSFrançois Tigeot if (!(BIT(engine->hw_id) & GEN6_SEMAPHORES_MASK)) 1305*1e12ee3bSFrançois Tigeot continue; 1306*1e12ee3bSFrançois Tigeot 1307*1e12ee3bSFrançois Tigeot mbox_reg = req->engine->semaphore.mbox.signal[engine->hw_id]; 1308aee94f86SFrançois Tigeot if (i915_mmio_reg_valid(mbox_reg)) { 130971f41f3eSFrançois Tigeot intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1)); 131071f41f3eSFrançois Tigeot intel_ring_emit_reg(ring, mbox_reg); 131171f41f3eSFrançois Tigeot intel_ring_emit(ring, req->fence.seqno); 1312ba55f2f5SFrançois Tigeot } 1313ba55f2f5SFrançois Tigeot } 1314ba55f2f5SFrançois Tigeot 131524edb884SFrançois Tigeot /* If num_dwords was rounded, make sure the tail pointer is correct */ 131624edb884SFrançois Tigeot if (num_rings % 2 == 0) 131771f41f3eSFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 131871f41f3eSFrançois Tigeot intel_ring_advance(ring); 131971f41f3eSFrançois Tigeot 132071f41f3eSFrançois Tigeot return 0; 132171f41f3eSFrançois Tigeot } 132271f41f3eSFrançois Tigeot 132371f41f3eSFrançois Tigeot static void i9xx_submit_request(struct drm_i915_gem_request *request) 132471f41f3eSFrançois Tigeot { 132571f41f3eSFrançois Tigeot struct drm_i915_private *dev_priv = request->i915; 132671f41f3eSFrançois Tigeot 132771f41f3eSFrançois Tigeot I915_WRITE_TAIL(request->engine, 132871f41f3eSFrançois Tigeot intel_ring_offset(request->ring, request->tail)); 132971f41f3eSFrançois Tigeot } 133071f41f3eSFrançois Tigeot 133171f41f3eSFrançois Tigeot static int i9xx_emit_request(struct drm_i915_gem_request *req) 133271f41f3eSFrançois Tigeot { 133371f41f3eSFrançois Tigeot struct intel_ring *ring = req->ring; 133471f41f3eSFrançois Tigeot int ret; 133571f41f3eSFrançois Tigeot 133671f41f3eSFrançois Tigeot ret = intel_ring_begin(req, 4); 133771f41f3eSFrançois Tigeot if (ret) 133871f41f3eSFrançois Tigeot return ret; 133971f41f3eSFrançois Tigeot 134071f41f3eSFrançois Tigeot intel_ring_emit(ring, MI_STORE_DWORD_INDEX); 134171f41f3eSFrançois Tigeot intel_ring_emit(ring, I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT); 134271f41f3eSFrançois Tigeot intel_ring_emit(ring, req->fence.seqno); 134371f41f3eSFrançois Tigeot intel_ring_emit(ring, MI_USER_INTERRUPT); 134471f41f3eSFrançois Tigeot intel_ring_advance(ring); 134571f41f3eSFrançois Tigeot 134671f41f3eSFrançois Tigeot req->tail = ring->tail; 134724edb884SFrançois Tigeot 1348ba55f2f5SFrançois Tigeot return 0; 1349e3adcf8fSFrançois Tigeot } 1350e3adcf8fSFrançois Tigeot 1351e3adcf8fSFrançois Tigeot /** 135271f41f3eSFrançois Tigeot * gen6_sema_emit_request - Update the semaphore mailbox registers 1353e3adcf8fSFrançois Tigeot * 1354a05eeebfSFrançois Tigeot * @request - request to write to the ring 1355e3adcf8fSFrançois Tigeot * 1356e3adcf8fSFrançois Tigeot * Update the mailbox registers in the *other* rings with the current seqno. 1357e3adcf8fSFrançois Tigeot * This acts like a signal in the canonical semaphore. 1358e3adcf8fSFrançois Tigeot */ 135971f41f3eSFrançois Tigeot static int gen6_sema_emit_request(struct drm_i915_gem_request *req) 1360e3adcf8fSFrançois Tigeot { 1361ba55f2f5SFrançois Tigeot int ret; 1362e3adcf8fSFrançois Tigeot 136371f41f3eSFrançois Tigeot ret = req->engine->semaphore.signal(req); 13649edbd4a0SFrançois Tigeot if (ret) 13659edbd4a0SFrançois Tigeot return ret; 13669edbd4a0SFrançois Tigeot 136771f41f3eSFrançois Tigeot return i9xx_emit_request(req); 1368e3adcf8fSFrançois Tigeot } 1369e3adcf8fSFrançois Tigeot 137071f41f3eSFrançois Tigeot static int gen8_render_emit_request(struct drm_i915_gem_request *req) 13711487f786SFrançois Tigeot { 13721487f786SFrançois Tigeot struct intel_engine_cs *engine = req->engine; 137371f41f3eSFrançois Tigeot struct intel_ring *ring = req->ring; 13741487f786SFrançois Tigeot int ret; 13751487f786SFrançois Tigeot 137671f41f3eSFrançois Tigeot if (engine->semaphore.signal) { 137771f41f3eSFrançois Tigeot ret = engine->semaphore.signal(req); 137871f41f3eSFrançois Tigeot if (ret) 137971f41f3eSFrançois Tigeot return ret; 138071f41f3eSFrançois Tigeot } 138171f41f3eSFrançois Tigeot 13821487f786SFrançois Tigeot ret = intel_ring_begin(req, 8); 13831487f786SFrançois Tigeot if (ret) 13841487f786SFrançois Tigeot return ret; 13851487f786SFrançois Tigeot 138671f41f3eSFrançois Tigeot intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(6)); 138771f41f3eSFrançois Tigeot intel_ring_emit(ring, (PIPE_CONTROL_GLOBAL_GTT_IVB | 13881487f786SFrançois Tigeot PIPE_CONTROL_CS_STALL | 13891487f786SFrançois Tigeot PIPE_CONTROL_QW_WRITE)); 139071f41f3eSFrançois Tigeot intel_ring_emit(ring, intel_hws_seqno_address(engine)); 139171f41f3eSFrançois Tigeot intel_ring_emit(ring, 0); 139271f41f3eSFrançois Tigeot intel_ring_emit(ring, i915_gem_request_get_seqno(req)); 13931487f786SFrançois Tigeot /* We're thrashing one dword of HWS. */ 139471f41f3eSFrançois Tigeot intel_ring_emit(ring, 0); 139571f41f3eSFrançois Tigeot intel_ring_emit(ring, MI_USER_INTERRUPT); 139671f41f3eSFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 139771f41f3eSFrançois Tigeot intel_ring_advance(ring); 139871f41f3eSFrançois Tigeot 139971f41f3eSFrançois Tigeot req->tail = ring->tail; 14001487f786SFrançois Tigeot 14011487f786SFrançois Tigeot return 0; 14021487f786SFrançois Tigeot } 14031487f786SFrançois Tigeot 1404e3adcf8fSFrançois Tigeot /** 1405e3adcf8fSFrançois Tigeot * intel_ring_sync - sync the waiter to the signaller on seqno 1406e3adcf8fSFrançois Tigeot * 1407e3adcf8fSFrançois Tigeot * @waiter - ring that is waiting 1408e3adcf8fSFrançois Tigeot * @signaller - ring which has, or will signal 1409e3adcf8fSFrançois Tigeot * @seqno - seqno which the waiter will block on 1410e3adcf8fSFrançois Tigeot */ 141124edb884SFrançois Tigeot 141224edb884SFrançois Tigeot static int 141371f41f3eSFrançois Tigeot gen8_ring_sync_to(struct drm_i915_gem_request *req, 141471f41f3eSFrançois Tigeot struct drm_i915_gem_request *signal) 141524edb884SFrançois Tigeot { 141671f41f3eSFrançois Tigeot struct intel_ring *ring = req->ring; 141771f41f3eSFrançois Tigeot struct drm_i915_private *dev_priv = req->i915; 141871f41f3eSFrançois Tigeot u64 offset = GEN8_WAIT_OFFSET(req->engine, signal->engine->id); 14191487f786SFrançois Tigeot struct i915_hw_ppgtt *ppgtt; 142024edb884SFrançois Tigeot int ret; 142124edb884SFrançois Tigeot 142271f41f3eSFrançois Tigeot ret = intel_ring_begin(req, 4); 142324edb884SFrançois Tigeot if (ret) 142424edb884SFrançois Tigeot return ret; 142524edb884SFrançois Tigeot 142671f41f3eSFrançois Tigeot intel_ring_emit(ring, 142771f41f3eSFrançois Tigeot MI_SEMAPHORE_WAIT | 142824edb884SFrançois Tigeot MI_SEMAPHORE_GLOBAL_GTT | 142924edb884SFrançois Tigeot MI_SEMAPHORE_SAD_GTE_SDD); 143071f41f3eSFrançois Tigeot intel_ring_emit(ring, signal->fence.seqno); 143171f41f3eSFrançois Tigeot intel_ring_emit(ring, lower_32_bits(offset)); 143271f41f3eSFrançois Tigeot intel_ring_emit(ring, upper_32_bits(offset)); 143371f41f3eSFrançois Tigeot intel_ring_advance(ring); 14341487f786SFrançois Tigeot 14351487f786SFrançois Tigeot /* When the !RCS engines idle waiting upon a semaphore, they lose their 14361487f786SFrançois Tigeot * pagetables and we must reload them before executing the batch. 14371487f786SFrançois Tigeot * We do this on the i915_switch_context() following the wait and 14381487f786SFrançois Tigeot * before the dispatch. 14391487f786SFrançois Tigeot */ 144071f41f3eSFrançois Tigeot ppgtt = req->ctx->ppgtt; 144171f41f3eSFrançois Tigeot if (ppgtt && req->engine->id != RCS) 144271f41f3eSFrançois Tigeot ppgtt->pd_dirty_rings |= intel_engine_flag(req->engine); 144324edb884SFrançois Tigeot return 0; 144424edb884SFrançois Tigeot } 144524edb884SFrançois Tigeot 1446e3adcf8fSFrançois Tigeot static int 144771f41f3eSFrançois Tigeot gen6_ring_sync_to(struct drm_i915_gem_request *req, 144871f41f3eSFrançois Tigeot struct drm_i915_gem_request *signal) 1449e3adcf8fSFrançois Tigeot { 145071f41f3eSFrançois Tigeot struct intel_ring *ring = req->ring; 1451e3adcf8fSFrançois Tigeot u32 dw1 = MI_SEMAPHORE_MBOX | 1452e3adcf8fSFrançois Tigeot MI_SEMAPHORE_COMPARE | 1453e3adcf8fSFrançois Tigeot MI_SEMAPHORE_REGISTER; 1454*1e12ee3bSFrançois Tigeot u32 wait_mbox = signal->engine->semaphore.mbox.wait[req->engine->hw_id]; 1455ba55f2f5SFrançois Tigeot int ret; 1456e3adcf8fSFrançois Tigeot 145771f41f3eSFrançois Tigeot WARN_ON(wait_mbox == MI_SEMAPHORE_SYNC_INVALID); 145871f41f3eSFrançois Tigeot 145971f41f3eSFrançois Tigeot ret = intel_ring_begin(req, 4); 146071f41f3eSFrançois Tigeot if (ret) 146171f41f3eSFrançois Tigeot return ret; 146271f41f3eSFrançois Tigeot 146371f41f3eSFrançois Tigeot intel_ring_emit(ring, dw1 | wait_mbox); 1464686a02f1SFrançois Tigeot /* Throughout all of the GEM code, seqno passed implies our current 1465686a02f1SFrançois Tigeot * seqno is >= the last seqno executed. However for hardware the 1466686a02f1SFrançois Tigeot * comparison is strictly greater than. 1467686a02f1SFrançois Tigeot */ 146871f41f3eSFrançois Tigeot intel_ring_emit(ring, signal->fence.seqno - 1); 146971f41f3eSFrançois Tigeot intel_ring_emit(ring, 0); 147071f41f3eSFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 147171f41f3eSFrançois Tigeot intel_ring_advance(ring); 1472e3adcf8fSFrançois Tigeot 1473e3adcf8fSFrançois Tigeot return 0; 1474e3adcf8fSFrançois Tigeot } 1475e3adcf8fSFrançois Tigeot 1476303bf270SFrançois Tigeot static void 147787df8fc6SFrançois Tigeot gen5_seqno_barrier(struct intel_engine_cs *engine) 1478e3adcf8fSFrançois Tigeot { 1479303bf270SFrançois Tigeot /* MI_STORE are internally buffered by the GPU and not flushed 1480303bf270SFrançois Tigeot * either by MI_FLUSH or SyncFlush or any other combination of 1481303bf270SFrançois Tigeot * MI commands. 1482e3adcf8fSFrançois Tigeot * 1483303bf270SFrançois Tigeot * "Only the submission of the store operation is guaranteed. 1484303bf270SFrançois Tigeot * The write result will be complete (coherent) some time later 1485303bf270SFrançois Tigeot * (this is practically a finite period but there is no guaranteed 1486303bf270SFrançois Tigeot * latency)." 1487303bf270SFrançois Tigeot * 1488303bf270SFrançois Tigeot * Empirically, we observe that we need a delay of at least 75us to 1489303bf270SFrançois Tigeot * be sure that the seqno write is visible by the CPU. 1490e3adcf8fSFrançois Tigeot */ 1491303bf270SFrançois Tigeot usleep_range(125, 250); 1492e3adcf8fSFrançois Tigeot } 1493e3adcf8fSFrançois Tigeot 14948621f407SFrançois Tigeot static void 14958621f407SFrançois Tigeot gen6_seqno_barrier(struct intel_engine_cs *engine) 1496e3adcf8fSFrançois Tigeot { 14971487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 14988621f407SFrançois Tigeot 1499e3adcf8fSFrançois Tigeot /* Workaround to force correct ordering between irq and seqno writes on 1500e3adcf8fSFrançois Tigeot * ivb (and maybe also on snb) by reading from a CS register (like 15018621f407SFrançois Tigeot * ACTHD) before reading the status page. 15028621f407SFrançois Tigeot * 15038621f407SFrançois Tigeot * Note that this effectively stalls the read by the time it takes to 15048621f407SFrançois Tigeot * do a memory transaction, which more or less ensures that the write 15058621f407SFrançois Tigeot * from the GPU has sufficient time to invalidate the CPU cacheline. 15068621f407SFrançois Tigeot * Alternatively we could delay the interrupt from the CS ring to give 15078621f407SFrançois Tigeot * the write time to land, but that would incur a delay after every 15088621f407SFrançois Tigeot * batch i.e. much more frequent than a delay when waiting for the 15098621f407SFrançois Tigeot * interrupt (with the same net latency). 15108621f407SFrançois Tigeot * 15118621f407SFrançois Tigeot * Also note that to prevent whole machine hangs on gen7, we have to 15128621f407SFrançois Tigeot * take the spinlock to guard against concurrent cacheline access. 15138621f407SFrançois Tigeot */ 15148621f407SFrançois Tigeot spin_lock_irq(&dev_priv->uncore.lock); 15158621f407SFrançois Tigeot POSTING_READ_FW(RING_ACTHD(engine->mmio_base)); 15168621f407SFrançois Tigeot spin_unlock_irq(&dev_priv->uncore.lock); 1517e3adcf8fSFrançois Tigeot } 1518e3adcf8fSFrançois Tigeot 1519303bf270SFrançois Tigeot static void 1520303bf270SFrançois Tigeot gen5_irq_enable(struct intel_engine_cs *engine) 1521e3adcf8fSFrançois Tigeot { 1522303bf270SFrançois Tigeot gen5_enable_gt_irq(engine->i915, engine->irq_enable_mask); 1523e3adcf8fSFrançois Tigeot } 1524e3adcf8fSFrançois Tigeot 1525a2fdbec6SFrançois Tigeot static void 1526303bf270SFrançois Tigeot gen5_irq_disable(struct intel_engine_cs *engine) 1527a2fdbec6SFrançois Tigeot { 1528303bf270SFrançois Tigeot gen5_disable_gt_irq(engine->i915, engine->irq_enable_mask); 1529e3adcf8fSFrançois Tigeot } 1530e3adcf8fSFrançois Tigeot 1531a2fdbec6SFrançois Tigeot static void 1532303bf270SFrançois Tigeot i9xx_irq_enable(struct intel_engine_cs *engine) 1533e3adcf8fSFrançois Tigeot { 15341487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 1535e3adcf8fSFrançois Tigeot 15368621f407SFrançois Tigeot dev_priv->irq_mask &= ~engine->irq_enable_mask; 1537686a02f1SFrançois Tigeot I915_WRITE(IMR, dev_priv->irq_mask); 1538303bf270SFrançois Tigeot POSTING_READ_FW(RING_IMR(engine->mmio_base)); 1539686a02f1SFrançois Tigeot } 1540686a02f1SFrançois Tigeot 1541686a02f1SFrançois Tigeot static void 1542303bf270SFrançois Tigeot i9xx_irq_disable(struct intel_engine_cs *engine) 1543686a02f1SFrançois Tigeot { 15441487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 1545686a02f1SFrançois Tigeot 15468621f407SFrançois Tigeot dev_priv->irq_mask |= engine->irq_enable_mask; 1547686a02f1SFrançois Tigeot I915_WRITE(IMR, dev_priv->irq_mask); 1548686a02f1SFrançois Tigeot } 1549686a02f1SFrançois Tigeot 1550686a02f1SFrançois Tigeot static void 1551303bf270SFrançois Tigeot i8xx_irq_enable(struct intel_engine_cs *engine) 1552686a02f1SFrançois Tigeot { 15531487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 1554686a02f1SFrançois Tigeot 1555303bf270SFrançois Tigeot dev_priv->irq_mask &= ~engine->irq_enable_mask; 1556303bf270SFrançois Tigeot I915_WRITE16(IMR, dev_priv->irq_mask); 1557303bf270SFrançois Tigeot POSTING_READ16(RING_IMR(engine->mmio_base)); 1558303bf270SFrançois Tigeot } 1559303bf270SFrançois Tigeot 1560303bf270SFrançois Tigeot static void 1561303bf270SFrançois Tigeot i8xx_irq_disable(struct intel_engine_cs *engine) 1562303bf270SFrançois Tigeot { 1563303bf270SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 1564303bf270SFrançois Tigeot 15658621f407SFrançois Tigeot dev_priv->irq_mask |= engine->irq_enable_mask; 1566686a02f1SFrançois Tigeot I915_WRITE16(IMR, dev_priv->irq_mask); 1567e3adcf8fSFrançois Tigeot } 1568e3adcf8fSFrançois Tigeot 1569e3adcf8fSFrançois Tigeot static int 157071f41f3eSFrançois Tigeot bsd_ring_flush(struct drm_i915_gem_request *req, u32 mode) 1571e3adcf8fSFrançois Tigeot { 157271f41f3eSFrançois Tigeot struct intel_ring *ring = req->ring; 1573e3adcf8fSFrançois Tigeot int ret; 1574e3adcf8fSFrançois Tigeot 1575a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 2); 1576e3adcf8fSFrançois Tigeot if (ret) 1577e3adcf8fSFrançois Tigeot return ret; 1578e3adcf8fSFrançois Tigeot 157971f41f3eSFrançois Tigeot intel_ring_emit(ring, MI_FLUSH); 158071f41f3eSFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 158171f41f3eSFrançois Tigeot intel_ring_advance(ring); 1582e3adcf8fSFrançois Tigeot return 0; 1583e3adcf8fSFrançois Tigeot } 1584e3adcf8fSFrançois Tigeot 1585303bf270SFrançois Tigeot static void 1586303bf270SFrançois Tigeot gen6_irq_enable(struct intel_engine_cs *engine) 1587e3adcf8fSFrançois Tigeot { 15881487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 1589e3adcf8fSFrançois Tigeot 15908621f407SFrançois Tigeot I915_WRITE_IMR(engine, 15918621f407SFrançois Tigeot ~(engine->irq_enable_mask | 1592303bf270SFrançois Tigeot engine->irq_keep_mask)); 15938621f407SFrançois Tigeot gen5_enable_gt_irq(dev_priv, engine->irq_enable_mask); 1594e3adcf8fSFrançois Tigeot } 1595e3adcf8fSFrançois Tigeot 1596e3adcf8fSFrançois Tigeot static void 1597303bf270SFrançois Tigeot gen6_irq_disable(struct intel_engine_cs *engine) 1598e3adcf8fSFrançois Tigeot { 15991487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 1600e3adcf8fSFrançois Tigeot 1601303bf270SFrançois Tigeot I915_WRITE_IMR(engine, ~engine->irq_keep_mask); 16028621f407SFrançois Tigeot gen5_disable_gt_irq(dev_priv, engine->irq_enable_mask); 1603e3adcf8fSFrançois Tigeot } 1604e3adcf8fSFrançois Tigeot 1605303bf270SFrançois Tigeot static void 1606303bf270SFrançois Tigeot hsw_vebox_irq_enable(struct intel_engine_cs *engine) 16075d0b1887SFrançois Tigeot { 16081487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 16095d0b1887SFrançois Tigeot 16108621f407SFrançois Tigeot I915_WRITE_IMR(engine, ~engine->irq_enable_mask); 16118621f407SFrançois Tigeot gen6_enable_pm_irq(dev_priv, engine->irq_enable_mask); 16125d0b1887SFrançois Tigeot } 16135d0b1887SFrançois Tigeot 16145d0b1887SFrançois Tigeot static void 1615303bf270SFrançois Tigeot hsw_vebox_irq_disable(struct intel_engine_cs *engine) 16165d0b1887SFrançois Tigeot { 16171487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 16185d0b1887SFrançois Tigeot 16198621f407SFrançois Tigeot I915_WRITE_IMR(engine, ~0); 16208621f407SFrançois Tigeot gen6_disable_pm_irq(dev_priv, engine->irq_enable_mask); 16215d0b1887SFrançois Tigeot } 16229edbd4a0SFrançois Tigeot 1623303bf270SFrançois Tigeot static void 1624303bf270SFrançois Tigeot gen8_irq_enable(struct intel_engine_cs *engine) 16259edbd4a0SFrançois Tigeot { 16261487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 16279edbd4a0SFrançois Tigeot 16288621f407SFrançois Tigeot I915_WRITE_IMR(engine, 16298621f407SFrançois Tigeot ~(engine->irq_enable_mask | 1630303bf270SFrançois Tigeot engine->irq_keep_mask)); 1631303bf270SFrançois Tigeot POSTING_READ_FW(RING_IMR(engine->mmio_base)); 16329edbd4a0SFrançois Tigeot } 16339edbd4a0SFrançois Tigeot 16349edbd4a0SFrançois Tigeot static void 1635303bf270SFrançois Tigeot gen8_irq_disable(struct intel_engine_cs *engine) 16369edbd4a0SFrançois Tigeot { 16371487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 16389edbd4a0SFrançois Tigeot 1639303bf270SFrançois Tigeot I915_WRITE_IMR(engine, ~engine->irq_keep_mask); 16405d0b1887SFrançois Tigeot } 16415d0b1887SFrançois Tigeot 1642e3adcf8fSFrançois Tigeot static int 164371f41f3eSFrançois Tigeot i965_emit_bb_start(struct drm_i915_gem_request *req, 1644ba55f2f5SFrançois Tigeot u64 offset, u32 length, 164571f41f3eSFrançois Tigeot unsigned int dispatch_flags) 1646e3adcf8fSFrançois Tigeot { 164771f41f3eSFrançois Tigeot struct intel_ring *ring = req->ring; 1648e3adcf8fSFrançois Tigeot int ret; 1649e3adcf8fSFrançois Tigeot 1650a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 2); 1651e3adcf8fSFrançois Tigeot if (ret) 1652e3adcf8fSFrançois Tigeot return ret; 1653e3adcf8fSFrançois Tigeot 165471f41f3eSFrançois Tigeot intel_ring_emit(ring, 1655686a02f1SFrançois Tigeot MI_BATCH_BUFFER_START | 1656b5c29a34SFrançois Tigeot MI_BATCH_GTT | 1657477eb7f9SFrançois Tigeot (dispatch_flags & I915_DISPATCH_SECURE ? 1658477eb7f9SFrançois Tigeot 0 : MI_BATCH_NON_SECURE_I965)); 165971f41f3eSFrançois Tigeot intel_ring_emit(ring, offset); 166071f41f3eSFrançois Tigeot intel_ring_advance(ring); 1661e3adcf8fSFrançois Tigeot 1662e3adcf8fSFrançois Tigeot return 0; 1663e3adcf8fSFrançois Tigeot } 1664e3adcf8fSFrançois Tigeot 1665b5c29a34SFrançois Tigeot /* Just userspace ABI convention to limit the wa batch bo to a resonable size */ 1666b5c29a34SFrançois Tigeot #define I830_BATCH_LIMIT (256*1024) 166724edb884SFrançois Tigeot #define I830_TLB_ENTRIES (2) 166824edb884SFrançois Tigeot #define I830_WA_SIZE max(I830_TLB_ENTRIES*4096, I830_BATCH_LIMIT) 1669e3adcf8fSFrançois Tigeot static int 167071f41f3eSFrançois Tigeot i830_emit_bb_start(struct drm_i915_gem_request *req, 1671ba55f2f5SFrançois Tigeot u64 offset, u32 len, 167271f41f3eSFrançois Tigeot unsigned int dispatch_flags) 1673e3adcf8fSFrançois Tigeot { 167471f41f3eSFrançois Tigeot struct intel_ring *ring = req->ring; 1675*1e12ee3bSFrançois Tigeot u32 cs_offset = i915_ggtt_offset(req->engine->scratch); 1676e3adcf8fSFrançois Tigeot int ret; 1677e3adcf8fSFrançois Tigeot 1678a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 6); 167924edb884SFrançois Tigeot if (ret) 168024edb884SFrançois Tigeot return ret; 168124edb884SFrançois Tigeot 168224edb884SFrançois Tigeot /* Evict the invalid PTE TLBs */ 168371f41f3eSFrançois Tigeot intel_ring_emit(ring, COLOR_BLT_CMD | BLT_WRITE_RGBA); 168471f41f3eSFrançois Tigeot intel_ring_emit(ring, BLT_DEPTH_32 | BLT_ROP_COLOR_COPY | 4096); 168571f41f3eSFrançois Tigeot intel_ring_emit(ring, I830_TLB_ENTRIES << 16 | 4); /* load each page */ 168671f41f3eSFrançois Tigeot intel_ring_emit(ring, cs_offset); 168771f41f3eSFrançois Tigeot intel_ring_emit(ring, 0xdeadbeef); 168871f41f3eSFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 168971f41f3eSFrançois Tigeot intel_ring_advance(ring); 169024edb884SFrançois Tigeot 1691477eb7f9SFrançois Tigeot if ((dispatch_flags & I915_DISPATCH_PINNED) == 0) { 169224edb884SFrançois Tigeot if (len > I830_BATCH_LIMIT) 169324edb884SFrançois Tigeot return -ENOSPC; 169424edb884SFrançois Tigeot 1695a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 6 + 2); 169624edb884SFrançois Tigeot if (ret) 169724edb884SFrançois Tigeot return ret; 169824edb884SFrançois Tigeot 169924edb884SFrançois Tigeot /* Blit the batch (which has now all relocs applied) to the 170024edb884SFrançois Tigeot * stable batch scratch bo area (so that the CS never 170124edb884SFrançois Tigeot * stumbles over its tlb invalidation bug) ... 170224edb884SFrançois Tigeot */ 170371f41f3eSFrançois Tigeot intel_ring_emit(ring, SRC_COPY_BLT_CMD | BLT_WRITE_RGBA); 170471f41f3eSFrançois Tigeot intel_ring_emit(ring, 17058621f407SFrançois Tigeot BLT_DEPTH_32 | BLT_ROP_SRC_COPY | 4096); 170671f41f3eSFrançois Tigeot intel_ring_emit(ring, DIV_ROUND_UP(len, 4096) << 16 | 4096); 170771f41f3eSFrançois Tigeot intel_ring_emit(ring, cs_offset); 170871f41f3eSFrançois Tigeot intel_ring_emit(ring, 4096); 170971f41f3eSFrançois Tigeot intel_ring_emit(ring, offset); 171024edb884SFrançois Tigeot 171171f41f3eSFrançois Tigeot intel_ring_emit(ring, MI_FLUSH); 171271f41f3eSFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 171371f41f3eSFrançois Tigeot intel_ring_advance(ring); 171424edb884SFrançois Tigeot 171524edb884SFrançois Tigeot /* ... and execute it. */ 171624edb884SFrançois Tigeot offset = cs_offset; 171724edb884SFrançois Tigeot } 171824edb884SFrançois Tigeot 1719c0e85e96SFrançois Tigeot ret = intel_ring_begin(req, 2); 1720e3adcf8fSFrançois Tigeot if (ret) 1721e3adcf8fSFrançois Tigeot return ret; 1722e3adcf8fSFrançois Tigeot 172371f41f3eSFrançois Tigeot intel_ring_emit(ring, MI_BATCH_BUFFER_START | MI_BATCH_GTT); 172471f41f3eSFrançois Tigeot intel_ring_emit(ring, offset | (dispatch_flags & I915_DISPATCH_SECURE ? 1725477eb7f9SFrançois Tigeot 0 : MI_BATCH_NON_SECURE)); 172671f41f3eSFrançois Tigeot intel_ring_advance(ring); 1727686a02f1SFrançois Tigeot 1728686a02f1SFrançois Tigeot return 0; 1729686a02f1SFrançois Tigeot } 1730686a02f1SFrançois Tigeot 1731686a02f1SFrançois Tigeot static int 173271f41f3eSFrançois Tigeot i915_emit_bb_start(struct drm_i915_gem_request *req, 1733ba55f2f5SFrançois Tigeot u64 offset, u32 len, 173471f41f3eSFrançois Tigeot unsigned int dispatch_flags) 1735686a02f1SFrançois Tigeot { 173671f41f3eSFrançois Tigeot struct intel_ring *ring = req->ring; 1737686a02f1SFrançois Tigeot int ret; 1738686a02f1SFrançois Tigeot 1739a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 2); 1740e3adcf8fSFrançois Tigeot if (ret) 1741e3adcf8fSFrançois Tigeot return ret; 1742e3adcf8fSFrançois Tigeot 174371f41f3eSFrançois Tigeot intel_ring_emit(ring, MI_BATCH_BUFFER_START | MI_BATCH_GTT); 174471f41f3eSFrançois Tigeot intel_ring_emit(ring, offset | (dispatch_flags & I915_DISPATCH_SECURE ? 1745477eb7f9SFrançois Tigeot 0 : MI_BATCH_NON_SECURE)); 174671f41f3eSFrançois Tigeot intel_ring_advance(ring); 1747e3adcf8fSFrançois Tigeot 1748e3adcf8fSFrançois Tigeot return 0; 1749e3adcf8fSFrançois Tigeot } 1750e3adcf8fSFrançois Tigeot 17518621f407SFrançois Tigeot static void cleanup_phys_status_page(struct intel_engine_cs *engine) 1752c0e85e96SFrançois Tigeot { 17531487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 1754c0e85e96SFrançois Tigeot 1755c0e85e96SFrançois Tigeot if (!dev_priv->status_page_dmah) 1756c0e85e96SFrançois Tigeot return; 1757c0e85e96SFrançois Tigeot 1758303bf270SFrançois Tigeot drm_pci_free(&dev_priv->drm, dev_priv->status_page_dmah); 17598621f407SFrançois Tigeot engine->status_page.page_addr = NULL; 1760c0e85e96SFrançois Tigeot } 1761c0e85e96SFrançois Tigeot 17628621f407SFrançois Tigeot static void cleanup_status_page(struct intel_engine_cs *engine) 1763e3adcf8fSFrançois Tigeot { 1764*1e12ee3bSFrançois Tigeot struct i915_vma *vma; 1765e3adcf8fSFrançois Tigeot 1766*1e12ee3bSFrançois Tigeot vma = fetch_and_zero(&engine->status_page.vma); 1767*1e12ee3bSFrançois Tigeot if (!vma) 1768e3adcf8fSFrançois Tigeot return; 1769e3adcf8fSFrançois Tigeot 1770*1e12ee3bSFrançois Tigeot i915_vma_unpin(vma); 1771*1e12ee3bSFrançois Tigeot i915_gem_object_unpin_map(vma->obj); 1772*1e12ee3bSFrançois Tigeot i915_vma_put(vma); 1773e3adcf8fSFrançois Tigeot } 1774e3adcf8fSFrançois Tigeot 17758621f407SFrançois Tigeot static int init_status_page(struct intel_engine_cs *engine) 1776e3adcf8fSFrançois Tigeot { 1777*1e12ee3bSFrançois Tigeot struct drm_i915_gem_object *obj; 1778*1e12ee3bSFrançois Tigeot struct i915_vma *vma; 1779*1e12ee3bSFrançois Tigeot unsigned int flags; 1780e3adcf8fSFrançois Tigeot int ret; 1781e3adcf8fSFrançois Tigeot 1782303bf270SFrançois Tigeot obj = i915_gem_object_create(&engine->i915->drm, 4096); 17831487f786SFrançois Tigeot if (IS_ERR(obj)) { 1784e3adcf8fSFrançois Tigeot DRM_ERROR("Failed to allocate status page\n"); 17851487f786SFrançois Tigeot return PTR_ERR(obj); 1786e3adcf8fSFrançois Tigeot } 1787e3adcf8fSFrançois Tigeot 1788ba55f2f5SFrançois Tigeot ret = i915_gem_object_set_cache_level(obj, I915_CACHE_LLC); 1789ba55f2f5SFrançois Tigeot if (ret) 1790*1e12ee3bSFrançois Tigeot goto err; 1791ba55f2f5SFrançois Tigeot 1792*1e12ee3bSFrançois Tigeot vma = i915_vma_create(obj, &engine->i915->ggtt.base, NULL); 1793*1e12ee3bSFrançois Tigeot if (IS_ERR(vma)) { 1794*1e12ee3bSFrançois Tigeot ret = PTR_ERR(vma); 1795*1e12ee3bSFrançois Tigeot goto err; 1796*1e12ee3bSFrançois Tigeot } 1797*1e12ee3bSFrançois Tigeot 1798*1e12ee3bSFrançois Tigeot flags = PIN_GLOBAL; 17991487f786SFrançois Tigeot if (!HAS_LLC(engine->i915)) 180024edb884SFrançois Tigeot /* On g33, we cannot place HWS above 256MiB, so 180124edb884SFrançois Tigeot * restrict its pinning to the low mappable arena. 180224edb884SFrançois Tigeot * Though this restriction is not documented for 180324edb884SFrançois Tigeot * gen4, gen5, or byt, they also behave similarly 180424edb884SFrançois Tigeot * and hang if the HWS is placed at the top of the 180524edb884SFrançois Tigeot * GTT. To generalise, it appears that all !llc 180624edb884SFrançois Tigeot * platforms have issues with us placing the HWS 180724edb884SFrançois Tigeot * above the mappable region (even though we never 180824edb884SFrançois Tigeot * actualy map it). 180924edb884SFrançois Tigeot */ 181024edb884SFrançois Tigeot flags |= PIN_MAPPABLE; 1811*1e12ee3bSFrançois Tigeot ret = i915_vma_pin(vma, 0, 4096, flags); 1812*1e12ee3bSFrançois Tigeot if (ret) 1813*1e12ee3bSFrançois Tigeot goto err; 1814ba55f2f5SFrançois Tigeot 1815*1e12ee3bSFrançois Tigeot engine->status_page.vma = vma; 1816*1e12ee3bSFrançois Tigeot engine->status_page.ggtt_offset = i915_ggtt_offset(vma); 1817*1e12ee3bSFrançois Tigeot engine->status_page.page_addr = 1818*1e12ee3bSFrançois Tigeot i915_gem_object_pin_map(obj, I915_MAP_WB); 1819e3adcf8fSFrançois Tigeot 1820b5c29a34SFrançois Tigeot DRM_DEBUG_DRIVER("%s hws offset: 0x%08x\n", 1821*1e12ee3bSFrançois Tigeot engine->name, i915_ggtt_offset(vma)); 1822e3adcf8fSFrançois Tigeot return 0; 1823*1e12ee3bSFrançois Tigeot 1824*1e12ee3bSFrançois Tigeot err: 1825*1e12ee3bSFrançois Tigeot i915_gem_object_put(obj); 1826*1e12ee3bSFrançois Tigeot return ret; 1827e3adcf8fSFrançois Tigeot } 1828e3adcf8fSFrançois Tigeot 18298621f407SFrançois Tigeot static int init_phys_status_page(struct intel_engine_cs *engine) 1830686a02f1SFrançois Tigeot { 18311487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 1832686a02f1SFrançois Tigeot 1833686a02f1SFrançois Tigeot dev_priv->status_page_dmah = 1834303bf270SFrançois Tigeot drm_pci_alloc(&dev_priv->drm, PAGE_SIZE, PAGE_SIZE); 1835686a02f1SFrançois Tigeot if (!dev_priv->status_page_dmah) 1836686a02f1SFrançois Tigeot return -ENOMEM; 1837686a02f1SFrançois Tigeot 18388621f407SFrançois Tigeot engine->status_page.page_addr = dev_priv->status_page_dmah->vaddr; 18398621f407SFrançois Tigeot memset(engine->status_page.page_addr, 0, PAGE_SIZE); 1840686a02f1SFrançois Tigeot 1841686a02f1SFrançois Tigeot return 0; 1842686a02f1SFrançois Tigeot } 1843686a02f1SFrançois Tigeot 184471f41f3eSFrançois Tigeot int intel_ring_pin(struct intel_ring *ring) 18452c9916cdSFrançois Tigeot { 1846c0e85e96SFrançois Tigeot /* Ring wraparound at offset 0 sometimes hangs. No idea why. */ 1847*1e12ee3bSFrançois Tigeot unsigned int flags = PIN_GLOBAL | PIN_OFFSET_BIAS | 4096; 1848*1e12ee3bSFrançois Tigeot enum i915_map_type map; 1849*1e12ee3bSFrançois Tigeot struct i915_vma *vma = ring->vma; 18508621f407SFrançois Tigeot void *addr; 18512c9916cdSFrançois Tigeot int ret; 18522c9916cdSFrançois Tigeot 1853*1e12ee3bSFrançois Tigeot GEM_BUG_ON(ring->vaddr); 1854*1e12ee3bSFrançois Tigeot 1855*1e12ee3bSFrançois Tigeot map = HAS_LLC(ring->engine->i915) ? I915_MAP_WB : I915_MAP_WC; 1856*1e12ee3bSFrançois Tigeot 1857*1e12ee3bSFrançois Tigeot if (vma->obj->stolen) 1858*1e12ee3bSFrançois Tigeot flags |= PIN_MAPPABLE; 1859*1e12ee3bSFrançois Tigeot 1860*1e12ee3bSFrançois Tigeot if (!(vma->flags & I915_VMA_GLOBAL_BIND)) { 1861*1e12ee3bSFrançois Tigeot if (flags & PIN_MAPPABLE || map == I915_MAP_WC) 1862*1e12ee3bSFrançois Tigeot ret = i915_gem_object_set_to_gtt_domain(vma->obj, true); 1863*1e12ee3bSFrançois Tigeot else 1864*1e12ee3bSFrançois Tigeot ret = i915_gem_object_set_to_cpu_domain(vma->obj, true); 1865*1e12ee3bSFrançois Tigeot if (unlikely(ret)) 1866*1e12ee3bSFrançois Tigeot return ret; 1867*1e12ee3bSFrançois Tigeot } 1868*1e12ee3bSFrançois Tigeot 1869*1e12ee3bSFrançois Tigeot ret = i915_vma_pin(vma, 0, PAGE_SIZE, flags); 1870*1e12ee3bSFrançois Tigeot if (unlikely(ret)) 1871aee94f86SFrançois Tigeot return ret; 1872aee94f86SFrançois Tigeot 1873*1e12ee3bSFrançois Tigeot if (i915_vma_is_map_and_fenceable(vma)) 1874*1e12ee3bSFrançois Tigeot addr = (void __force *)i915_vma_pin_iomap(vma); 1875*1e12ee3bSFrançois Tigeot else 1876*1e12ee3bSFrançois Tigeot addr = i915_gem_object_pin_map(vma->obj, map); 1877*1e12ee3bSFrançois Tigeot if (IS_ERR(addr)) 1878*1e12ee3bSFrançois Tigeot goto err; 18792c9916cdSFrançois Tigeot 188071f41f3eSFrançois Tigeot ring->vaddr = addr; 18812c9916cdSFrançois Tigeot return 0; 18828621f407SFrançois Tigeot 1883*1e12ee3bSFrançois Tigeot err: 1884*1e12ee3bSFrançois Tigeot i915_vma_unpin(vma); 1885*1e12ee3bSFrançois Tigeot return PTR_ERR(addr); 18862c9916cdSFrançois Tigeot } 18872c9916cdSFrançois Tigeot 188871f41f3eSFrançois Tigeot void intel_ring_unpin(struct intel_ring *ring) 1889e3adcf8fSFrançois Tigeot { 189071f41f3eSFrançois Tigeot GEM_BUG_ON(!ring->vma); 189171f41f3eSFrançois Tigeot GEM_BUG_ON(!ring->vaddr); 189271f41f3eSFrançois Tigeot 1893*1e12ee3bSFrançois Tigeot if (i915_vma_is_map_and_fenceable(ring->vma)) 189471f41f3eSFrançois Tigeot i915_vma_unpin_iomap(ring->vma); 1895*1e12ee3bSFrançois Tigeot else 1896*1e12ee3bSFrançois Tigeot i915_gem_object_unpin_map(ring->vma->obj); 189771f41f3eSFrançois Tigeot ring->vaddr = NULL; 189871f41f3eSFrançois Tigeot 1899*1e12ee3bSFrançois Tigeot i915_vma_unpin(ring->vma); 190071f41f3eSFrançois Tigeot } 190171f41f3eSFrançois Tigeot 1902*1e12ee3bSFrançois Tigeot static struct i915_vma * 1903*1e12ee3bSFrançois Tigeot intel_ring_create_vma(struct drm_i915_private *dev_priv, int size) 190424edb884SFrançois Tigeot { 1905e3adcf8fSFrançois Tigeot struct drm_i915_gem_object *obj; 1906*1e12ee3bSFrançois Tigeot struct i915_vma *vma; 1907e3adcf8fSFrançois Tigeot 1908*1e12ee3bSFrançois Tigeot obj = i915_gem_object_create_stolen(&dev_priv->drm, size); 1909*1e12ee3bSFrançois Tigeot if (!obj) 1910*1e12ee3bSFrançois Tigeot obj = i915_gem_object_create(&dev_priv->drm, size); 19111487f786SFrançois Tigeot if (IS_ERR(obj)) 1912*1e12ee3bSFrançois Tigeot return ERR_CAST(obj); 1913e3adcf8fSFrançois Tigeot 191424edb884SFrançois Tigeot /* mark ring buffers as read-only from GPU side by default */ 191524edb884SFrançois Tigeot obj->gt_ro = 1; 191624edb884SFrançois Tigeot 1917*1e12ee3bSFrançois Tigeot vma = i915_vma_create(obj, &dev_priv->ggtt.base, NULL); 1918*1e12ee3bSFrançois Tigeot if (IS_ERR(vma)) 1919*1e12ee3bSFrançois Tigeot goto err; 1920ba55f2f5SFrançois Tigeot 1921*1e12ee3bSFrançois Tigeot return vma; 1922*1e12ee3bSFrançois Tigeot 1923*1e12ee3bSFrançois Tigeot err: 1924*1e12ee3bSFrançois Tigeot i915_gem_object_put(obj); 1925*1e12ee3bSFrançois Tigeot return vma; 1926ba55f2f5SFrançois Tigeot } 1927ba55f2f5SFrançois Tigeot 192871f41f3eSFrançois Tigeot struct intel_ring * 192971f41f3eSFrançois Tigeot intel_engine_create_ring(struct intel_engine_cs *engine, int size) 1930352ff8bdSFrançois Tigeot { 193171f41f3eSFrançois Tigeot struct intel_ring *ring; 1932*1e12ee3bSFrançois Tigeot struct i915_vma *vma; 1933352ff8bdSFrançois Tigeot 193471f41f3eSFrançois Tigeot GEM_BUG_ON(!is_power_of_2(size)); 1935*1e12ee3bSFrançois Tigeot GEM_BUG_ON(RING_CTL_SIZE(size) & ~RING_NR_PAGES); 193671f41f3eSFrançois Tigeot 1937352ff8bdSFrançois Tigeot ring = kzalloc(sizeof(*ring), GFP_KERNEL); 1938*1e12ee3bSFrançois Tigeot if (!ring) 1939352ff8bdSFrançois Tigeot return ERR_PTR(-ENOMEM); 1940352ff8bdSFrançois Tigeot 19418621f407SFrançois Tigeot ring->engine = engine; 1942352ff8bdSFrançois Tigeot 194371f41f3eSFrançois Tigeot INIT_LIST_HEAD(&ring->request_list); 194471f41f3eSFrançois Tigeot 1945352ff8bdSFrançois Tigeot ring->size = size; 1946352ff8bdSFrançois Tigeot /* Workaround an erratum on the i830 which causes a hang if 1947352ff8bdSFrançois Tigeot * the TAIL pointer points to within the last 2 cachelines 1948352ff8bdSFrançois Tigeot * of the buffer. 1949352ff8bdSFrançois Tigeot */ 1950352ff8bdSFrançois Tigeot ring->effective_size = size; 19511487f786SFrançois Tigeot if (IS_I830(engine->i915) || IS_845G(engine->i915)) 1952352ff8bdSFrançois Tigeot ring->effective_size -= 2 * CACHELINE_BYTES; 1953352ff8bdSFrançois Tigeot 1954352ff8bdSFrançois Tigeot ring->last_retired_head = -1; 1955352ff8bdSFrançois Tigeot intel_ring_update_space(ring); 1956352ff8bdSFrançois Tigeot 1957*1e12ee3bSFrançois Tigeot vma = intel_ring_create_vma(engine->i915, size); 1958*1e12ee3bSFrançois Tigeot if (IS_ERR(vma)) { 1959352ff8bdSFrançois Tigeot kfree(ring); 1960*1e12ee3bSFrançois Tigeot return ERR_CAST(vma); 1961352ff8bdSFrançois Tigeot } 1962*1e12ee3bSFrançois Tigeot ring->vma = vma; 1963352ff8bdSFrançois Tigeot 1964352ff8bdSFrançois Tigeot return ring; 1965352ff8bdSFrançois Tigeot } 1966352ff8bdSFrançois Tigeot 1967352ff8bdSFrançois Tigeot void 196871f41f3eSFrançois Tigeot intel_ring_free(struct intel_ring *ring) 1969352ff8bdSFrançois Tigeot { 1970*1e12ee3bSFrançois Tigeot i915_vma_put(ring->vma); 1971352ff8bdSFrançois Tigeot kfree(ring); 1972352ff8bdSFrançois Tigeot } 1973352ff8bdSFrançois Tigeot 19741487f786SFrançois Tigeot static int intel_ring_context_pin(struct i915_gem_context *ctx, 19751487f786SFrançois Tigeot struct intel_engine_cs *engine) 19761487f786SFrançois Tigeot { 19771487f786SFrançois Tigeot struct intel_context *ce = &ctx->engine[engine->id]; 19781487f786SFrançois Tigeot int ret; 19791487f786SFrançois Tigeot 1980303bf270SFrançois Tigeot lockdep_assert_held(&ctx->i915->drm.struct_mutex); 19811487f786SFrançois Tigeot 19821487f786SFrançois Tigeot if (ce->pin_count++) 19831487f786SFrançois Tigeot return 0; 19841487f786SFrançois Tigeot 19851487f786SFrançois Tigeot if (ce->state) { 1986*1e12ee3bSFrançois Tigeot ret = i915_gem_object_set_to_gtt_domain(ce->state->obj, false); 1987*1e12ee3bSFrançois Tigeot if (ret) 1988*1e12ee3bSFrançois Tigeot goto error; 1989*1e12ee3bSFrançois Tigeot 1990*1e12ee3bSFrançois Tigeot ret = i915_vma_pin(ce->state, 0, ctx->ggtt_alignment, 1991*1e12ee3bSFrançois Tigeot PIN_GLOBAL | PIN_HIGH); 19921487f786SFrançois Tigeot if (ret) 19931487f786SFrançois Tigeot goto error; 19941487f786SFrançois Tigeot } 19951487f786SFrançois Tigeot 19961487f786SFrançois Tigeot /* The kernel context is only used as a placeholder for flushing the 19971487f786SFrançois Tigeot * active context. It is never used for submitting user rendering and 19981487f786SFrançois Tigeot * as such never requires the golden render context, and so we can skip 19991487f786SFrançois Tigeot * emitting it when we switch to the kernel context. This is required 20001487f786SFrançois Tigeot * as during eviction we cannot allocate and pin the renderstate in 20011487f786SFrançois Tigeot * order to initialise the context. 20021487f786SFrançois Tigeot */ 20031487f786SFrançois Tigeot if (ctx == ctx->i915->kernel_context) 20041487f786SFrançois Tigeot ce->initialised = true; 20051487f786SFrançois Tigeot 200687df8fc6SFrançois Tigeot i915_gem_context_get(ctx); 20071487f786SFrançois Tigeot return 0; 20081487f786SFrançois Tigeot 20091487f786SFrançois Tigeot error: 20101487f786SFrançois Tigeot ce->pin_count = 0; 20111487f786SFrançois Tigeot return ret; 20121487f786SFrançois Tigeot } 20131487f786SFrançois Tigeot 20141487f786SFrançois Tigeot static void intel_ring_context_unpin(struct i915_gem_context *ctx, 20151487f786SFrançois Tigeot struct intel_engine_cs *engine) 20161487f786SFrançois Tigeot { 20171487f786SFrançois Tigeot struct intel_context *ce = &ctx->engine[engine->id]; 20181487f786SFrançois Tigeot 2019303bf270SFrançois Tigeot lockdep_assert_held(&ctx->i915->drm.struct_mutex); 20201487f786SFrançois Tigeot 20211487f786SFrançois Tigeot if (--ce->pin_count) 20221487f786SFrançois Tigeot return; 20231487f786SFrançois Tigeot 20241487f786SFrançois Tigeot if (ce->state) 2025*1e12ee3bSFrançois Tigeot i915_vma_unpin(ce->state); 20261487f786SFrançois Tigeot 202787df8fc6SFrançois Tigeot i915_gem_context_put(ctx); 20281487f786SFrançois Tigeot } 20291487f786SFrançois Tigeot 203087df8fc6SFrançois Tigeot static int intel_init_ring_buffer(struct intel_engine_cs *engine) 2031ba55f2f5SFrançois Tigeot { 203287df8fc6SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 203371f41f3eSFrançois Tigeot struct intel_ring *ring; 2034ba55f2f5SFrançois Tigeot int ret; 2035ba55f2f5SFrançois Tigeot 20368621f407SFrançois Tigeot WARN_ON(engine->buffer); 20372c9916cdSFrançois Tigeot 203887df8fc6SFrançois Tigeot intel_engine_setup_common(engine); 203987df8fc6SFrançois Tigeot 20408621f407SFrançois Tigeot memset(engine->semaphore.sync_seqno, 0, 20418621f407SFrançois Tigeot sizeof(engine->semaphore.sync_seqno)); 2042ba55f2f5SFrançois Tigeot 204387df8fc6SFrançois Tigeot ret = intel_engine_init_common(engine); 2044303bf270SFrançois Tigeot if (ret) 2045303bf270SFrançois Tigeot goto error; 2046ba55f2f5SFrançois Tigeot 20471487f786SFrançois Tigeot /* We may need to do things with the shrinker which 20481487f786SFrançois Tigeot * require us to immediately switch back to the default 20491487f786SFrançois Tigeot * context. This can cause a problem as pinning the 20501487f786SFrançois Tigeot * default context also requires GTT space which may not 20511487f786SFrançois Tigeot * be available. To avoid this we always pin the default 20521487f786SFrançois Tigeot * context. 20531487f786SFrançois Tigeot */ 20541487f786SFrançois Tigeot ret = intel_ring_context_pin(dev_priv->kernel_context, engine); 20551487f786SFrançois Tigeot if (ret) 20561487f786SFrançois Tigeot goto error; 20571487f786SFrançois Tigeot 205871f41f3eSFrançois Tigeot ring = intel_engine_create_ring(engine, 32 * PAGE_SIZE); 205971f41f3eSFrançois Tigeot if (IS_ERR(ring)) { 206071f41f3eSFrançois Tigeot ret = PTR_ERR(ring); 2061aee94f86SFrançois Tigeot goto error; 2062aee94f86SFrançois Tigeot } 2063352ff8bdSFrançois Tigeot 2064*1e12ee3bSFrançois Tigeot if (HWS_NEEDS_PHYSICAL(dev_priv)) { 2065*1e12ee3bSFrançois Tigeot WARN_ON(engine->id != RCS); 2066*1e12ee3bSFrançois Tigeot ret = init_phys_status_page(engine); 2067e3adcf8fSFrançois Tigeot if (ret) 2068ba55f2f5SFrançois Tigeot goto error; 2069ba55f2f5SFrançois Tigeot } else { 2070*1e12ee3bSFrançois Tigeot ret = init_status_page(engine); 2071ba55f2f5SFrançois Tigeot if (ret) 2072ba55f2f5SFrançois Tigeot goto error; 2073ba55f2f5SFrançois Tigeot } 2074ba55f2f5SFrançois Tigeot 207571f41f3eSFrançois Tigeot ret = intel_ring_pin(ring); 20762c9916cdSFrançois Tigeot if (ret) { 2077*1e12ee3bSFrançois Tigeot intel_ring_free(ring); 2078ba55f2f5SFrançois Tigeot goto error; 2079ba55f2f5SFrançois Tigeot } 2080*1e12ee3bSFrançois Tigeot engine->buffer = ring; 2081e3adcf8fSFrançois Tigeot 2082e3adcf8fSFrançois Tigeot return 0; 2083e3adcf8fSFrançois Tigeot 2084ba55f2f5SFrançois Tigeot error: 208571f41f3eSFrançois Tigeot intel_engine_cleanup(engine); 2086e3adcf8fSFrançois Tigeot return ret; 2087e3adcf8fSFrançois Tigeot } 2088e3adcf8fSFrançois Tigeot 208971f41f3eSFrançois Tigeot void intel_engine_cleanup(struct intel_engine_cs *engine) 2090e3adcf8fSFrançois Tigeot { 20912c9916cdSFrançois Tigeot struct drm_i915_private *dev_priv; 2092e3adcf8fSFrançois Tigeot 20931487f786SFrançois Tigeot dev_priv = engine->i915; 20942c9916cdSFrançois Tigeot 20958621f407SFrançois Tigeot if (engine->buffer) { 2096*1e12ee3bSFrançois Tigeot WARN_ON(INTEL_GEN(dev_priv) > 2 && 2097*1e12ee3bSFrançois Tigeot (I915_READ_MODE(engine) & MODE_IDLE) == 0); 2098b030f26bSFrançois Tigeot 209971f41f3eSFrançois Tigeot intel_ring_unpin(engine->buffer); 210071f41f3eSFrançois Tigeot intel_ring_free(engine->buffer); 21018621f407SFrançois Tigeot engine->buffer = NULL; 2102aee94f86SFrançois Tigeot } 2103e3adcf8fSFrançois Tigeot 21048621f407SFrançois Tigeot if (engine->cleanup) 21058621f407SFrançois Tigeot engine->cleanup(engine); 2106e3adcf8fSFrançois Tigeot 2107*1e12ee3bSFrançois Tigeot if (HWS_NEEDS_PHYSICAL(dev_priv)) { 21088621f407SFrançois Tigeot WARN_ON(engine->id != RCS); 21098621f407SFrançois Tigeot cleanup_phys_status_page(engine); 2110*1e12ee3bSFrançois Tigeot } else { 2111*1e12ee3bSFrançois Tigeot cleanup_status_page(engine); 2112c0e85e96SFrançois Tigeot } 2113ba55f2f5SFrançois Tigeot 211471f41f3eSFrançois Tigeot intel_engine_cleanup_common(engine); 21151487f786SFrançois Tigeot 21161487f786SFrançois Tigeot intel_ring_context_unpin(dev_priv->kernel_context, engine); 21171487f786SFrançois Tigeot 21181487f786SFrançois Tigeot engine->i915 = NULL; 2119*1e12ee3bSFrançois Tigeot dev_priv->engine[engine->id] = NULL; 2120*1e12ee3bSFrançois Tigeot kfree(engine); 2121*1e12ee3bSFrançois Tigeot } 2122*1e12ee3bSFrançois Tigeot 2123*1e12ee3bSFrançois Tigeot void intel_legacy_submission_resume(struct drm_i915_private *dev_priv) 2124*1e12ee3bSFrançois Tigeot { 2125*1e12ee3bSFrançois Tigeot struct intel_engine_cs *engine; 2126*1e12ee3bSFrançois Tigeot enum intel_engine_id id; 2127*1e12ee3bSFrançois Tigeot 2128*1e12ee3bSFrançois Tigeot for_each_engine(engine, dev_priv, id) { 2129*1e12ee3bSFrançois Tigeot engine->buffer->head = engine->buffer->tail; 2130*1e12ee3bSFrançois Tigeot engine->buffer->last_retired_head = -1; 2131*1e12ee3bSFrançois Tigeot } 2132e3adcf8fSFrançois Tigeot } 2133e3adcf8fSFrançois Tigeot 213419c468b4SFrançois Tigeot int intel_ring_alloc_request_extras(struct drm_i915_gem_request *request) 2135b5c29a34SFrançois Tigeot { 21361487f786SFrançois Tigeot int ret; 21379edbd4a0SFrançois Tigeot 21381487f786SFrançois Tigeot /* Flush enough space to reduce the likelihood of waiting after 21391487f786SFrançois Tigeot * we start building the request - in which case we will just 21401487f786SFrançois Tigeot * have to repeat work. 2141a05eeebfSFrançois Tigeot */ 21421487f786SFrançois Tigeot request->reserved_space += LEGACY_REQUEST_SIZE; 2143a2fdbec6SFrançois Tigeot 214471f41f3eSFrançois Tigeot request->ring = request->engine->buffer; 2145a2fdbec6SFrançois Tigeot 21461487f786SFrançois Tigeot ret = intel_ring_begin(request, 0); 21471487f786SFrançois Tigeot if (ret) 21481487f786SFrançois Tigeot return ret; 2149a05eeebfSFrançois Tigeot 21501487f786SFrançois Tigeot request->reserved_space -= LEGACY_REQUEST_SIZE; 21511487f786SFrançois Tigeot return 0; 2152a05eeebfSFrançois Tigeot } 2153a05eeebfSFrançois Tigeot 21548621f407SFrançois Tigeot static int wait_for_space(struct drm_i915_gem_request *req, int bytes) 2155a05eeebfSFrançois Tigeot { 215671f41f3eSFrançois Tigeot struct intel_ring *ring = req->ring; 21578621f407SFrançois Tigeot struct drm_i915_gem_request *target; 215871f41f3eSFrançois Tigeot int ret; 21598621f407SFrançois Tigeot 216071f41f3eSFrançois Tigeot intel_ring_update_space(ring); 216171f41f3eSFrançois Tigeot if (ring->space >= bytes) 21628621f407SFrançois Tigeot return 0; 21638621f407SFrançois Tigeot 21648621f407SFrançois Tigeot /* 21658621f407SFrançois Tigeot * Space is reserved in the ringbuffer for finalising the request, 21668621f407SFrançois Tigeot * as that cannot be allowed to fail. During request finalisation, 21678621f407SFrançois Tigeot * reserved_space is set to 0 to stop the overallocation and the 21688621f407SFrançois Tigeot * assumption is that then we never need to wait (which has the 21698621f407SFrançois Tigeot * risk of failing with EINTR). 21708621f407SFrançois Tigeot * 21718621f407SFrançois Tigeot * See also i915_gem_request_alloc() and i915_add_request(). 21728621f407SFrançois Tigeot */ 21731487f786SFrançois Tigeot GEM_BUG_ON(!req->reserved_space); 21748621f407SFrançois Tigeot 217571f41f3eSFrançois Tigeot list_for_each_entry(target, &ring->request_list, ring_link) { 21768621f407SFrançois Tigeot unsigned space; 21778621f407SFrançois Tigeot 21788621f407SFrançois Tigeot /* Would completion of this request free enough space? */ 217971f41f3eSFrançois Tigeot space = __intel_ring_space(target->postfix, ring->tail, 218071f41f3eSFrançois Tigeot ring->size); 21818621f407SFrançois Tigeot if (space >= bytes) 21828621f407SFrançois Tigeot break; 21838621f407SFrançois Tigeot } 21848621f407SFrançois Tigeot 218571f41f3eSFrançois Tigeot if (WARN_ON(&target->ring_link == &ring->request_list)) 21868621f407SFrançois Tigeot return -ENOSPC; 21878621f407SFrançois Tigeot 2188*1e12ee3bSFrançois Tigeot ret = i915_wait_request(target, 2189*1e12ee3bSFrançois Tigeot I915_WAIT_INTERRUPTIBLE | I915_WAIT_LOCKED, 2190*1e12ee3bSFrançois Tigeot NULL, NO_WAITBOOST); 219171f41f3eSFrançois Tigeot if (ret) 219271f41f3eSFrançois Tigeot return ret; 219371f41f3eSFrançois Tigeot 219471f41f3eSFrançois Tigeot i915_gem_request_retire_upto(target); 219571f41f3eSFrançois Tigeot 219671f41f3eSFrançois Tigeot intel_ring_update_space(ring); 219771f41f3eSFrançois Tigeot GEM_BUG_ON(ring->space < bytes); 219871f41f3eSFrançois Tigeot return 0; 21998621f407SFrançois Tigeot } 22008621f407SFrançois Tigeot 22018621f407SFrançois Tigeot int intel_ring_begin(struct drm_i915_gem_request *req, int num_dwords) 22028621f407SFrançois Tigeot { 220371f41f3eSFrançois Tigeot struct intel_ring *ring = req->ring; 220471f41f3eSFrançois Tigeot int remain_actual = ring->size - ring->tail; 220571f41f3eSFrançois Tigeot int remain_usable = ring->effective_size - ring->tail; 22068621f407SFrançois Tigeot int bytes = num_dwords * sizeof(u32); 22078621f407SFrançois Tigeot int total_bytes, wait_bytes; 2208a05eeebfSFrançois Tigeot bool need_wrap = false; 2209a05eeebfSFrançois Tigeot 22101487f786SFrançois Tigeot total_bytes = bytes + req->reserved_space; 2211a05eeebfSFrançois Tigeot 2212a05eeebfSFrançois Tigeot if (unlikely(bytes > remain_usable)) { 2213a05eeebfSFrançois Tigeot /* 2214a05eeebfSFrançois Tigeot * Not enough space for the basic request. So need to flush 2215a05eeebfSFrançois Tigeot * out the remainder and then wait for base + reserved. 2216a05eeebfSFrançois Tigeot */ 2217a05eeebfSFrançois Tigeot wait_bytes = remain_actual + total_bytes; 2218a05eeebfSFrançois Tigeot need_wrap = true; 22198621f407SFrançois Tigeot } else if (unlikely(total_bytes > remain_usable)) { 2220a05eeebfSFrançois Tigeot /* 2221a05eeebfSFrançois Tigeot * The base request will fit but the reserved space 22228621f407SFrançois Tigeot * falls off the end. So we don't need an immediate wrap 2223c0e85e96SFrançois Tigeot * and only need to effectively wait for the reserved 2224c0e85e96SFrançois Tigeot * size space from the start of ringbuffer. 2225a05eeebfSFrançois Tigeot */ 22261487f786SFrançois Tigeot wait_bytes = remain_actual + req->reserved_space; 22278621f407SFrançois Tigeot } else { 2228a05eeebfSFrançois Tigeot /* No wrapping required, just waiting. */ 2229a05eeebfSFrançois Tigeot wait_bytes = total_bytes; 2230a05eeebfSFrançois Tigeot } 2231a05eeebfSFrançois Tigeot 223271f41f3eSFrançois Tigeot if (wait_bytes > ring->space) { 22338621f407SFrançois Tigeot int ret = wait_for_space(req, wait_bytes); 2234a2fdbec6SFrançois Tigeot if (unlikely(ret)) 2235a2fdbec6SFrançois Tigeot return ret; 2236a2fdbec6SFrançois Tigeot } 2237a2fdbec6SFrançois Tigeot 22388621f407SFrançois Tigeot if (unlikely(need_wrap)) { 223971f41f3eSFrançois Tigeot GEM_BUG_ON(remain_actual > ring->space); 224071f41f3eSFrançois Tigeot GEM_BUG_ON(ring->tail + remain_actual > ring->size); 22418621f407SFrançois Tigeot 22428621f407SFrançois Tigeot /* Fill the tail with MI_NOOP */ 224371f41f3eSFrançois Tigeot memset(ring->vaddr + ring->tail, 0, remain_actual); 224471f41f3eSFrançois Tigeot ring->tail = 0; 224571f41f3eSFrançois Tigeot ring->space -= remain_actual; 2246a2fdbec6SFrançois Tigeot } 2247a2fdbec6SFrançois Tigeot 224871f41f3eSFrançois Tigeot ring->space -= bytes; 224971f41f3eSFrançois Tigeot GEM_BUG_ON(ring->space < 0); 22509edbd4a0SFrançois Tigeot return 0; 22519edbd4a0SFrançois Tigeot } 22529edbd4a0SFrançois Tigeot 22539edbd4a0SFrançois Tigeot /* Align the ring tail to a cacheline boundary */ 2254a05eeebfSFrançois Tigeot int intel_ring_cacheline_align(struct drm_i915_gem_request *req) 22559edbd4a0SFrançois Tigeot { 225671f41f3eSFrançois Tigeot struct intel_ring *ring = req->ring; 225771f41f3eSFrançois Tigeot int num_dwords = 225871f41f3eSFrançois Tigeot (ring->tail & (CACHELINE_BYTES - 1)) / sizeof(uint32_t); 22599edbd4a0SFrançois Tigeot int ret; 22609edbd4a0SFrançois Tigeot 22619edbd4a0SFrançois Tigeot if (num_dwords == 0) 22629edbd4a0SFrançois Tigeot return 0; 22639edbd4a0SFrançois Tigeot 2264ba55f2f5SFrançois Tigeot num_dwords = CACHELINE_BYTES / sizeof(uint32_t) - num_dwords; 2265a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, num_dwords); 22669edbd4a0SFrançois Tigeot if (ret) 22679edbd4a0SFrançois Tigeot return ret; 22689edbd4a0SFrançois Tigeot 22699edbd4a0SFrançois Tigeot while (num_dwords--) 227071f41f3eSFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 22719edbd4a0SFrançois Tigeot 227271f41f3eSFrançois Tigeot intel_ring_advance(ring); 22739edbd4a0SFrançois Tigeot 22749edbd4a0SFrançois Tigeot return 0; 2275e3adcf8fSFrançois Tigeot } 2276e3adcf8fSFrançois Tigeot 227771f41f3eSFrançois Tigeot static void gen6_bsd_submit_request(struct drm_i915_gem_request *request) 2278e3adcf8fSFrançois Tigeot { 227971f41f3eSFrançois Tigeot struct drm_i915_private *dev_priv = request->i915; 22801487f786SFrançois Tigeot 22811487f786SFrançois Tigeot intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL); 2282e3adcf8fSFrançois Tigeot 2283e3adcf8fSFrançois Tigeot /* Every tail move must follow the sequence below */ 2284f4e1c372SFrançois Tigeot 2285f4e1c372SFrançois Tigeot /* Disable notification that the ring is IDLE. The GT 2286f4e1c372SFrançois Tigeot * will then assume that it is busy and bring it out of rc6. 2287f4e1c372SFrançois Tigeot */ 22881487f786SFrançois Tigeot I915_WRITE_FW(GEN6_BSD_SLEEP_PSMI_CONTROL, 2289f4e1c372SFrançois Tigeot _MASKED_BIT_ENABLE(GEN6_BSD_SLEEP_MSG_DISABLE)); 2290e3adcf8fSFrançois Tigeot 2291f4e1c372SFrançois Tigeot /* Clear the context id. Here be magic! */ 22921487f786SFrançois Tigeot I915_WRITE64_FW(GEN6_BSD_RNCID, 0x0); 2293e3adcf8fSFrançois Tigeot 2294f4e1c372SFrançois Tigeot /* Wait for the ring not to be idle, i.e. for it to wake up. */ 22951487f786SFrançois Tigeot if (intel_wait_for_register_fw(dev_priv, 22961487f786SFrançois Tigeot GEN6_BSD_SLEEP_PSMI_CONTROL, 22971487f786SFrançois Tigeot GEN6_BSD_SLEEP_INDICATOR, 22981487f786SFrançois Tigeot 0, 2299f4e1c372SFrançois Tigeot 50)) 2300f4e1c372SFrançois Tigeot DRM_ERROR("timed out waiting for the BSD ring to wake up\n"); 2301f4e1c372SFrançois Tigeot 2302f4e1c372SFrançois Tigeot /* Now that the ring is fully powered up, update the tail */ 230371f41f3eSFrançois Tigeot i9xx_submit_request(request); 2304f4e1c372SFrançois Tigeot 2305f4e1c372SFrançois Tigeot /* Let the ring send IDLE messages to the GT again, 2306f4e1c372SFrançois Tigeot * and so let it sleep to conserve power when idle. 2307f4e1c372SFrançois Tigeot */ 23081487f786SFrançois Tigeot I915_WRITE_FW(GEN6_BSD_SLEEP_PSMI_CONTROL, 2309f4e1c372SFrançois Tigeot _MASKED_BIT_DISABLE(GEN6_BSD_SLEEP_MSG_DISABLE)); 23101487f786SFrançois Tigeot 23111487f786SFrançois Tigeot intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL); 2312e3adcf8fSFrançois Tigeot } 2313e3adcf8fSFrançois Tigeot 231471f41f3eSFrançois Tigeot static int gen6_bsd_ring_flush(struct drm_i915_gem_request *req, u32 mode) 2315e3adcf8fSFrançois Tigeot { 231671f41f3eSFrançois Tigeot struct intel_ring *ring = req->ring; 2317e3adcf8fSFrançois Tigeot uint32_t cmd; 2318e3adcf8fSFrançois Tigeot int ret; 2319e3adcf8fSFrançois Tigeot 2320a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 4); 2321e3adcf8fSFrançois Tigeot if (ret) 2322e3adcf8fSFrançois Tigeot return ret; 2323e3adcf8fSFrançois Tigeot 2324e3adcf8fSFrançois Tigeot cmd = MI_FLUSH_DW; 23251487f786SFrançois Tigeot if (INTEL_GEN(req->i915) >= 8) 23269edbd4a0SFrançois Tigeot cmd += 1; 23272c9916cdSFrançois Tigeot 23282c9916cdSFrançois Tigeot /* We always require a command barrier so that subsequent 23292c9916cdSFrançois Tigeot * commands, such as breadcrumb interrupts, are strictly ordered 23302c9916cdSFrançois Tigeot * wrt the contents of the write cache being flushed to memory 23312c9916cdSFrançois Tigeot * (and thus being coherent from the CPU). 23322c9916cdSFrançois Tigeot */ 23332c9916cdSFrançois Tigeot cmd |= MI_FLUSH_DW_STORE_INDEX | MI_FLUSH_DW_OP_STOREDW; 23342c9916cdSFrançois Tigeot 2335b5c29a34SFrançois Tigeot /* 2336b5c29a34SFrançois Tigeot * Bspec vol 1c.5 - video engine command streamer: 2337b5c29a34SFrançois Tigeot * "If ENABLED, all TLBs will be invalidated once the flush 2338b5c29a34SFrançois Tigeot * operation is complete. This bit is only valid when the 2339b5c29a34SFrançois Tigeot * Post-Sync Operation field is a value of 1h or 3h." 2340b5c29a34SFrançois Tigeot */ 234171f41f3eSFrançois Tigeot if (mode & EMIT_INVALIDATE) 23422c9916cdSFrançois Tigeot cmd |= MI_INVALIDATE_TLB | MI_INVALIDATE_BSD; 23432c9916cdSFrançois Tigeot 234471f41f3eSFrançois Tigeot intel_ring_emit(ring, cmd); 234571f41f3eSFrançois Tigeot intel_ring_emit(ring, I915_GEM_HWS_SCRATCH_ADDR | MI_FLUSH_DW_USE_GTT); 23461487f786SFrançois Tigeot if (INTEL_GEN(req->i915) >= 8) { 234771f41f3eSFrançois Tigeot intel_ring_emit(ring, 0); /* upper addr */ 234871f41f3eSFrançois Tigeot intel_ring_emit(ring, 0); /* value */ 23499edbd4a0SFrançois Tigeot } else { 235071f41f3eSFrançois Tigeot intel_ring_emit(ring, 0); 235171f41f3eSFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 23529edbd4a0SFrançois Tigeot } 235371f41f3eSFrançois Tigeot intel_ring_advance(ring); 23549edbd4a0SFrançois Tigeot return 0; 23559edbd4a0SFrançois Tigeot } 23569edbd4a0SFrançois Tigeot 23579edbd4a0SFrançois Tigeot static int 235871f41f3eSFrançois Tigeot gen8_emit_bb_start(struct drm_i915_gem_request *req, 2359ba55f2f5SFrançois Tigeot u64 offset, u32 len, 236071f41f3eSFrançois Tigeot unsigned int dispatch_flags) 23619edbd4a0SFrançois Tigeot { 236271f41f3eSFrançois Tigeot struct intel_ring *ring = req->ring; 236371f41f3eSFrançois Tigeot bool ppgtt = USES_PPGTT(req->i915) && 2364477eb7f9SFrançois Tigeot !(dispatch_flags & I915_DISPATCH_SECURE); 23659edbd4a0SFrançois Tigeot int ret; 23669edbd4a0SFrançois Tigeot 2367a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 4); 23689edbd4a0SFrançois Tigeot if (ret) 23699edbd4a0SFrançois Tigeot return ret; 23709edbd4a0SFrançois Tigeot 23719edbd4a0SFrançois Tigeot /* FIXME(BDW): Address space and security selectors. */ 237271f41f3eSFrançois Tigeot intel_ring_emit(ring, MI_BATCH_BUFFER_START_GEN8 | (ppgtt<<8) | 2373a05eeebfSFrançois Tigeot (dispatch_flags & I915_DISPATCH_RS ? 2374a05eeebfSFrançois Tigeot MI_BATCH_RESOURCE_STREAMER : 0)); 237571f41f3eSFrançois Tigeot intel_ring_emit(ring, lower_32_bits(offset)); 237671f41f3eSFrançois Tigeot intel_ring_emit(ring, upper_32_bits(offset)); 237771f41f3eSFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 237871f41f3eSFrançois Tigeot intel_ring_advance(ring); 23799edbd4a0SFrançois Tigeot 2380e3adcf8fSFrançois Tigeot return 0; 2381e3adcf8fSFrançois Tigeot } 2382e3adcf8fSFrançois Tigeot 2383e3adcf8fSFrançois Tigeot static int 238471f41f3eSFrançois Tigeot hsw_emit_bb_start(struct drm_i915_gem_request *req, 2385ba55f2f5SFrançois Tigeot u64 offset, u32 len, 238671f41f3eSFrançois Tigeot unsigned int dispatch_flags) 2387e3adcf8fSFrançois Tigeot { 238871f41f3eSFrançois Tigeot struct intel_ring *ring = req->ring; 2389e3adcf8fSFrançois Tigeot int ret; 2390e3adcf8fSFrançois Tigeot 2391a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 2); 2392e3adcf8fSFrançois Tigeot if (ret) 2393e3adcf8fSFrançois Tigeot return ret; 2394e3adcf8fSFrançois Tigeot 239571f41f3eSFrançois Tigeot intel_ring_emit(ring, 23961b13d190SFrançois Tigeot MI_BATCH_BUFFER_START | 2397477eb7f9SFrançois Tigeot (dispatch_flags & I915_DISPATCH_SECURE ? 2398a05eeebfSFrançois Tigeot 0 : MI_BATCH_PPGTT_HSW | MI_BATCH_NON_SECURE_HSW) | 2399a05eeebfSFrançois Tigeot (dispatch_flags & I915_DISPATCH_RS ? 2400a05eeebfSFrançois Tigeot MI_BATCH_RESOURCE_STREAMER : 0)); 2401b5c29a34SFrançois Tigeot /* bit0-7 is the length on GEN6+ */ 240271f41f3eSFrançois Tigeot intel_ring_emit(ring, offset); 240371f41f3eSFrançois Tigeot intel_ring_advance(ring); 2404b5c29a34SFrançois Tigeot 2405b5c29a34SFrançois Tigeot return 0; 2406b5c29a34SFrançois Tigeot } 2407b5c29a34SFrançois Tigeot 2408b5c29a34SFrançois Tigeot static int 240971f41f3eSFrançois Tigeot gen6_emit_bb_start(struct drm_i915_gem_request *req, 2410ba55f2f5SFrançois Tigeot u64 offset, u32 len, 241171f41f3eSFrançois Tigeot unsigned int dispatch_flags) 2412b5c29a34SFrançois Tigeot { 241371f41f3eSFrançois Tigeot struct intel_ring *ring = req->ring; 2414b5c29a34SFrançois Tigeot int ret; 2415b5c29a34SFrançois Tigeot 2416a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 2); 2417b5c29a34SFrançois Tigeot if (ret) 2418b5c29a34SFrançois Tigeot return ret; 2419b5c29a34SFrançois Tigeot 242071f41f3eSFrançois Tigeot intel_ring_emit(ring, 2421b5c29a34SFrançois Tigeot MI_BATCH_BUFFER_START | 2422477eb7f9SFrançois Tigeot (dispatch_flags & I915_DISPATCH_SECURE ? 2423477eb7f9SFrançois Tigeot 0 : MI_BATCH_NON_SECURE_I965)); 2424e3adcf8fSFrançois Tigeot /* bit0-7 is the length on GEN6+ */ 242571f41f3eSFrançois Tigeot intel_ring_emit(ring, offset); 242671f41f3eSFrançois Tigeot intel_ring_advance(ring); 2427e3adcf8fSFrançois Tigeot 2428e3adcf8fSFrançois Tigeot return 0; 2429e3adcf8fSFrançois Tigeot } 2430e3adcf8fSFrançois Tigeot 2431e3adcf8fSFrançois Tigeot /* Blitter support (SandyBridge+) */ 2432e3adcf8fSFrançois Tigeot 243371f41f3eSFrançois Tigeot static int gen6_ring_flush(struct drm_i915_gem_request *req, u32 mode) 2434e3adcf8fSFrançois Tigeot { 243571f41f3eSFrançois Tigeot struct intel_ring *ring = req->ring; 2436e3adcf8fSFrançois Tigeot uint32_t cmd; 2437e3adcf8fSFrançois Tigeot int ret; 2438e3adcf8fSFrançois Tigeot 2439a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 4); 2440e3adcf8fSFrançois Tigeot if (ret) 2441e3adcf8fSFrançois Tigeot return ret; 2442e3adcf8fSFrançois Tigeot 2443e3adcf8fSFrançois Tigeot cmd = MI_FLUSH_DW; 24441487f786SFrançois Tigeot if (INTEL_GEN(req->i915) >= 8) 24459edbd4a0SFrançois Tigeot cmd += 1; 24462c9916cdSFrançois Tigeot 24472c9916cdSFrançois Tigeot /* We always require a command barrier so that subsequent 24482c9916cdSFrançois Tigeot * commands, such as breadcrumb interrupts, are strictly ordered 24492c9916cdSFrançois Tigeot * wrt the contents of the write cache being flushed to memory 24502c9916cdSFrançois Tigeot * (and thus being coherent from the CPU). 24512c9916cdSFrançois Tigeot */ 24522c9916cdSFrançois Tigeot cmd |= MI_FLUSH_DW_STORE_INDEX | MI_FLUSH_DW_OP_STOREDW; 24532c9916cdSFrançois Tigeot 2454b5c29a34SFrançois Tigeot /* 2455b5c29a34SFrançois Tigeot * Bspec vol 1c.3 - blitter engine command streamer: 2456b5c29a34SFrançois Tigeot * "If ENABLED, all TLBs will be invalidated once the flush 2457b5c29a34SFrançois Tigeot * operation is complete. This bit is only valid when the 2458b5c29a34SFrançois Tigeot * Post-Sync Operation field is a value of 1h or 3h." 2459b5c29a34SFrançois Tigeot */ 246071f41f3eSFrançois Tigeot if (mode & EMIT_INVALIDATE) 24612c9916cdSFrançois Tigeot cmd |= MI_INVALIDATE_TLB; 246271f41f3eSFrançois Tigeot intel_ring_emit(ring, cmd); 246371f41f3eSFrançois Tigeot intel_ring_emit(ring, 24648621f407SFrançois Tigeot I915_GEM_HWS_SCRATCH_ADDR | MI_FLUSH_DW_USE_GTT); 24651487f786SFrançois Tigeot if (INTEL_GEN(req->i915) >= 8) { 246671f41f3eSFrançois Tigeot intel_ring_emit(ring, 0); /* upper addr */ 246771f41f3eSFrançois Tigeot intel_ring_emit(ring, 0); /* value */ 24689edbd4a0SFrançois Tigeot } else { 246971f41f3eSFrançois Tigeot intel_ring_emit(ring, 0); 247071f41f3eSFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 24719edbd4a0SFrançois Tigeot } 247271f41f3eSFrançois Tigeot intel_ring_advance(ring); 24735d0b1887SFrançois Tigeot 2474e3adcf8fSFrançois Tigeot return 0; 2475e3adcf8fSFrançois Tigeot } 2476e3adcf8fSFrançois Tigeot 24771487f786SFrançois Tigeot static void intel_ring_init_semaphores(struct drm_i915_private *dev_priv, 24781487f786SFrançois Tigeot struct intel_engine_cs *engine) 24791487f786SFrançois Tigeot { 24801487f786SFrançois Tigeot struct drm_i915_gem_object *obj; 24811487f786SFrançois Tigeot int ret, i; 24821487f786SFrançois Tigeot 248387df8fc6SFrançois Tigeot if (!i915.semaphores) 24841487f786SFrançois Tigeot return; 24851487f786SFrançois Tigeot 2486*1e12ee3bSFrançois Tigeot if (INTEL_GEN(dev_priv) >= 8 && !dev_priv->semaphore) { 2487*1e12ee3bSFrançois Tigeot struct i915_vma *vma; 24881487f786SFrançois Tigeot 2489*1e12ee3bSFrançois Tigeot obj = i915_gem_object_create(&dev_priv->drm, 4096); 2490*1e12ee3bSFrançois Tigeot if (IS_ERR(obj)) 2491*1e12ee3bSFrançois Tigeot goto err; 2492*1e12ee3bSFrançois Tigeot 2493*1e12ee3bSFrançois Tigeot vma = i915_vma_create(obj, &dev_priv->ggtt.base, NULL); 2494*1e12ee3bSFrançois Tigeot if (IS_ERR(vma)) 2495*1e12ee3bSFrançois Tigeot goto err_obj; 2496*1e12ee3bSFrançois Tigeot 2497*1e12ee3bSFrançois Tigeot ret = i915_gem_object_set_to_gtt_domain(obj, false); 2498*1e12ee3bSFrançois Tigeot if (ret) 2499*1e12ee3bSFrançois Tigeot goto err_obj; 2500*1e12ee3bSFrançois Tigeot 2501*1e12ee3bSFrançois Tigeot ret = i915_vma_pin(vma, 0, 0, PIN_GLOBAL | PIN_HIGH); 2502*1e12ee3bSFrançois Tigeot if (ret) 2503*1e12ee3bSFrançois Tigeot goto err_obj; 2504*1e12ee3bSFrançois Tigeot 2505*1e12ee3bSFrançois Tigeot dev_priv->semaphore = vma; 2506*1e12ee3bSFrançois Tigeot } 25071487f786SFrançois Tigeot 25081487f786SFrançois Tigeot if (INTEL_GEN(dev_priv) >= 8) { 2509*1e12ee3bSFrançois Tigeot u32 offset = i915_ggtt_offset(dev_priv->semaphore); 25101487f786SFrançois Tigeot 251171f41f3eSFrançois Tigeot engine->semaphore.sync_to = gen8_ring_sync_to; 25121487f786SFrançois Tigeot engine->semaphore.signal = gen8_xcs_signal; 25131487f786SFrançois Tigeot 25141487f786SFrançois Tigeot for (i = 0; i < I915_NUM_ENGINES; i++) { 2515*1e12ee3bSFrançois Tigeot u32 ring_offset; 25161487f786SFrançois Tigeot 25171487f786SFrançois Tigeot if (i != engine->id) 25181487f786SFrançois Tigeot ring_offset = offset + GEN8_SEMAPHORE_OFFSET(engine->id, i); 25191487f786SFrançois Tigeot else 25201487f786SFrançois Tigeot ring_offset = MI_SEMAPHORE_SYNC_INVALID; 25211487f786SFrançois Tigeot 25221487f786SFrançois Tigeot engine->semaphore.signal_ggtt[i] = ring_offset; 25231487f786SFrançois Tigeot } 25241487f786SFrançois Tigeot } else if (INTEL_GEN(dev_priv) >= 6) { 252571f41f3eSFrançois Tigeot engine->semaphore.sync_to = gen6_ring_sync_to; 25261487f786SFrançois Tigeot engine->semaphore.signal = gen6_signal; 25271487f786SFrançois Tigeot 25281487f786SFrançois Tigeot /* 25291487f786SFrançois Tigeot * The current semaphore is only applied on pre-gen8 25301487f786SFrançois Tigeot * platform. And there is no VCS2 ring on the pre-gen8 25311487f786SFrançois Tigeot * platform. So the semaphore between RCS and VCS2 is 25321487f786SFrançois Tigeot * initialized as INVALID. Gen8 will initialize the 25331487f786SFrançois Tigeot * sema between VCS2 and RCS later. 25341487f786SFrançois Tigeot */ 2535*1e12ee3bSFrançois Tigeot for (i = 0; i < GEN6_NUM_SEMAPHORES; i++) { 25361487f786SFrançois Tigeot static const struct { 25371487f786SFrançois Tigeot u32 wait_mbox; 25381487f786SFrançois Tigeot i915_reg_t mbox_reg; 2539*1e12ee3bSFrançois Tigeot } sem_data[GEN6_NUM_SEMAPHORES][GEN6_NUM_SEMAPHORES] = { 2540*1e12ee3bSFrançois Tigeot [RCS_HW] = { 2541*1e12ee3bSFrançois Tigeot [VCS_HW] = { .wait_mbox = MI_SEMAPHORE_SYNC_RV, .mbox_reg = GEN6_VRSYNC }, 2542*1e12ee3bSFrançois Tigeot [BCS_HW] = { .wait_mbox = MI_SEMAPHORE_SYNC_RB, .mbox_reg = GEN6_BRSYNC }, 2543*1e12ee3bSFrançois Tigeot [VECS_HW] = { .wait_mbox = MI_SEMAPHORE_SYNC_RVE, .mbox_reg = GEN6_VERSYNC }, 25441487f786SFrançois Tigeot }, 2545*1e12ee3bSFrançois Tigeot [VCS_HW] = { 2546*1e12ee3bSFrançois Tigeot [RCS_HW] = { .wait_mbox = MI_SEMAPHORE_SYNC_VR, .mbox_reg = GEN6_RVSYNC }, 2547*1e12ee3bSFrançois Tigeot [BCS_HW] = { .wait_mbox = MI_SEMAPHORE_SYNC_VB, .mbox_reg = GEN6_BVSYNC }, 2548*1e12ee3bSFrançois Tigeot [VECS_HW] = { .wait_mbox = MI_SEMAPHORE_SYNC_VVE, .mbox_reg = GEN6_VEVSYNC }, 25491487f786SFrançois Tigeot }, 2550*1e12ee3bSFrançois Tigeot [BCS_HW] = { 2551*1e12ee3bSFrançois Tigeot [RCS_HW] = { .wait_mbox = MI_SEMAPHORE_SYNC_BR, .mbox_reg = GEN6_RBSYNC }, 2552*1e12ee3bSFrançois Tigeot [VCS_HW] = { .wait_mbox = MI_SEMAPHORE_SYNC_BV, .mbox_reg = GEN6_VBSYNC }, 2553*1e12ee3bSFrançois Tigeot [VECS_HW] = { .wait_mbox = MI_SEMAPHORE_SYNC_BVE, .mbox_reg = GEN6_VEBSYNC }, 25541487f786SFrançois Tigeot }, 2555*1e12ee3bSFrançois Tigeot [VECS_HW] = { 2556*1e12ee3bSFrançois Tigeot [RCS_HW] = { .wait_mbox = MI_SEMAPHORE_SYNC_VER, .mbox_reg = GEN6_RVESYNC }, 2557*1e12ee3bSFrançois Tigeot [VCS_HW] = { .wait_mbox = MI_SEMAPHORE_SYNC_VEV, .mbox_reg = GEN6_VVESYNC }, 2558*1e12ee3bSFrançois Tigeot [BCS_HW] = { .wait_mbox = MI_SEMAPHORE_SYNC_VEB, .mbox_reg = GEN6_BVESYNC }, 25591487f786SFrançois Tigeot }, 25601487f786SFrançois Tigeot }; 25611487f786SFrançois Tigeot u32 wait_mbox; 25621487f786SFrançois Tigeot i915_reg_t mbox_reg; 25631487f786SFrançois Tigeot 2564*1e12ee3bSFrançois Tigeot if (i == engine->hw_id) { 25651487f786SFrançois Tigeot wait_mbox = MI_SEMAPHORE_SYNC_INVALID; 25661487f786SFrançois Tigeot mbox_reg = GEN6_NOSYNC; 25671487f786SFrançois Tigeot } else { 2568*1e12ee3bSFrançois Tigeot wait_mbox = sem_data[engine->hw_id][i].wait_mbox; 2569*1e12ee3bSFrançois Tigeot mbox_reg = sem_data[engine->hw_id][i].mbox_reg; 25701487f786SFrançois Tigeot } 25711487f786SFrançois Tigeot 25721487f786SFrançois Tigeot engine->semaphore.mbox.wait[i] = wait_mbox; 25731487f786SFrançois Tigeot engine->semaphore.mbox.signal[i] = mbox_reg; 25741487f786SFrançois Tigeot } 25751487f786SFrançois Tigeot } 2576*1e12ee3bSFrançois Tigeot 2577*1e12ee3bSFrançois Tigeot return; 2578*1e12ee3bSFrançois Tigeot 2579*1e12ee3bSFrançois Tigeot err_obj: 2580*1e12ee3bSFrançois Tigeot i915_gem_object_put(obj); 2581*1e12ee3bSFrançois Tigeot err: 2582*1e12ee3bSFrançois Tigeot DRM_DEBUG_DRIVER("Failed to allocate space for semaphores, disabling\n"); 2583*1e12ee3bSFrançois Tigeot i915.semaphores = 0; 25841487f786SFrançois Tigeot } 25851487f786SFrançois Tigeot 25861487f786SFrançois Tigeot static void intel_ring_init_irq(struct drm_i915_private *dev_priv, 25871487f786SFrançois Tigeot struct intel_engine_cs *engine) 25881487f786SFrançois Tigeot { 258987df8fc6SFrançois Tigeot engine->irq_enable_mask = GT_RENDER_USER_INTERRUPT << engine->irq_shift; 259087df8fc6SFrançois Tigeot 25911487f786SFrançois Tigeot if (INTEL_GEN(dev_priv) >= 8) { 2592303bf270SFrançois Tigeot engine->irq_enable = gen8_irq_enable; 2593303bf270SFrançois Tigeot engine->irq_disable = gen8_irq_disable; 25941487f786SFrançois Tigeot engine->irq_seqno_barrier = gen6_seqno_barrier; 25951487f786SFrançois Tigeot } else if (INTEL_GEN(dev_priv) >= 6) { 2596303bf270SFrançois Tigeot engine->irq_enable = gen6_irq_enable; 2597303bf270SFrançois Tigeot engine->irq_disable = gen6_irq_disable; 25981487f786SFrançois Tigeot engine->irq_seqno_barrier = gen6_seqno_barrier; 25991487f786SFrançois Tigeot } else if (INTEL_GEN(dev_priv) >= 5) { 2600303bf270SFrançois Tigeot engine->irq_enable = gen5_irq_enable; 2601303bf270SFrançois Tigeot engine->irq_disable = gen5_irq_disable; 2602303bf270SFrançois Tigeot engine->irq_seqno_barrier = gen5_seqno_barrier; 26031487f786SFrançois Tigeot } else if (INTEL_GEN(dev_priv) >= 3) { 2604303bf270SFrançois Tigeot engine->irq_enable = i9xx_irq_enable; 2605303bf270SFrançois Tigeot engine->irq_disable = i9xx_irq_disable; 26061487f786SFrançois Tigeot } else { 2607303bf270SFrançois Tigeot engine->irq_enable = i8xx_irq_enable; 2608303bf270SFrançois Tigeot engine->irq_disable = i8xx_irq_disable; 26091487f786SFrançois Tigeot } 26101487f786SFrançois Tigeot } 26111487f786SFrançois Tigeot 26121487f786SFrançois Tigeot static void intel_ring_default_vfuncs(struct drm_i915_private *dev_priv, 26131487f786SFrançois Tigeot struct intel_engine_cs *engine) 26141487f786SFrançois Tigeot { 26151487f786SFrançois Tigeot intel_ring_init_irq(dev_priv, engine); 26161487f786SFrançois Tigeot intel_ring_init_semaphores(dev_priv, engine); 261771f41f3eSFrançois Tigeot 261871f41f3eSFrançois Tigeot engine->init_hw = init_ring_common; 2619*1e12ee3bSFrançois Tigeot engine->reset_hw = reset_ring_common; 262071f41f3eSFrançois Tigeot 262171f41f3eSFrançois Tigeot engine->emit_request = i9xx_emit_request; 262271f41f3eSFrançois Tigeot if (i915.semaphores) 262371f41f3eSFrançois Tigeot engine->emit_request = gen6_sema_emit_request; 262471f41f3eSFrançois Tigeot engine->submit_request = i9xx_submit_request; 262571f41f3eSFrançois Tigeot 262671f41f3eSFrançois Tigeot if (INTEL_GEN(dev_priv) >= 8) 262771f41f3eSFrançois Tigeot engine->emit_bb_start = gen8_emit_bb_start; 262871f41f3eSFrançois Tigeot else if (INTEL_GEN(dev_priv) >= 6) 262971f41f3eSFrançois Tigeot engine->emit_bb_start = gen6_emit_bb_start; 263071f41f3eSFrançois Tigeot else if (INTEL_GEN(dev_priv) >= 4) 263171f41f3eSFrançois Tigeot engine->emit_bb_start = i965_emit_bb_start; 263271f41f3eSFrançois Tigeot else if (IS_I830(dev_priv) || IS_845G(dev_priv)) 263371f41f3eSFrançois Tigeot engine->emit_bb_start = i830_emit_bb_start; 263471f41f3eSFrançois Tigeot else 263571f41f3eSFrançois Tigeot engine->emit_bb_start = i915_emit_bb_start; 26361487f786SFrançois Tigeot } 26371487f786SFrançois Tigeot 263887df8fc6SFrançois Tigeot int intel_init_render_ring_buffer(struct intel_engine_cs *engine) 2639e3adcf8fSFrançois Tigeot { 264087df8fc6SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 264124edb884SFrançois Tigeot int ret; 2642e3adcf8fSFrançois Tigeot 26431487f786SFrançois Tigeot intel_ring_default_vfuncs(dev_priv, engine); 26442c9916cdSFrançois Tigeot 2645303bf270SFrançois Tigeot if (HAS_L3_DPF(dev_priv)) 2646303bf270SFrançois Tigeot engine->irq_keep_mask = GT_RENDER_L3_PARITY_ERROR_INTERRUPT; 2647303bf270SFrançois Tigeot 26481487f786SFrançois Tigeot if (INTEL_GEN(dev_priv) >= 8) { 26498621f407SFrançois Tigeot engine->init_context = intel_rcs_ctx_init; 265071f41f3eSFrançois Tigeot engine->emit_request = gen8_render_emit_request; 265171f41f3eSFrançois Tigeot engine->emit_flush = gen8_render_ring_flush; 265287df8fc6SFrançois Tigeot if (i915.semaphores) 26538621f407SFrançois Tigeot engine->semaphore.signal = gen8_rcs_signal; 26541487f786SFrançois Tigeot } else if (INTEL_GEN(dev_priv) >= 6) { 26558621f407SFrançois Tigeot engine->init_context = intel_rcs_ctx_init; 265671f41f3eSFrançois Tigeot engine->emit_flush = gen7_render_ring_flush; 26571487f786SFrançois Tigeot if (IS_GEN6(dev_priv)) 265871f41f3eSFrançois Tigeot engine->emit_flush = gen6_render_ring_flush; 26591487f786SFrançois Tigeot } else if (IS_GEN5(dev_priv)) { 266071f41f3eSFrançois Tigeot engine->emit_flush = gen4_render_ring_flush; 2661686a02f1SFrançois Tigeot } else { 26621487f786SFrançois Tigeot if (INTEL_GEN(dev_priv) < 4) 266371f41f3eSFrançois Tigeot engine->emit_flush = gen2_render_ring_flush; 2664686a02f1SFrançois Tigeot else 266571f41f3eSFrançois Tigeot engine->emit_flush = gen4_render_ring_flush; 26668621f407SFrançois Tigeot engine->irq_enable_mask = I915_USER_INTERRUPT; 2667686a02f1SFrançois Tigeot } 266824edb884SFrançois Tigeot 26691487f786SFrançois Tigeot if (IS_HASWELL(dev_priv)) 267071f41f3eSFrançois Tigeot engine->emit_bb_start = hsw_emit_bb_start; 26711487f786SFrançois Tigeot 26728621f407SFrançois Tigeot engine->init_hw = init_render_ring; 26738621f407SFrançois Tigeot engine->cleanup = render_ring_cleanup; 2674e3adcf8fSFrançois Tigeot 267587df8fc6SFrançois Tigeot ret = intel_init_ring_buffer(engine); 2676b5c29a34SFrançois Tigeot if (ret) 26772c9916cdSFrançois Tigeot return ret; 26782c9916cdSFrançois Tigeot 2679303bf270SFrançois Tigeot if (INTEL_GEN(dev_priv) >= 6) { 2680*1e12ee3bSFrançois Tigeot ret = intel_engine_create_scratch(engine, 4096); 2681303bf270SFrançois Tigeot if (ret) 2682303bf270SFrançois Tigeot return ret; 2683303bf270SFrançois Tigeot } else if (HAS_BROKEN_CS_TLB(dev_priv)) { 2684*1e12ee3bSFrançois Tigeot ret = intel_engine_create_scratch(engine, I830_WA_SIZE); 26852c9916cdSFrançois Tigeot if (ret) 26862c9916cdSFrançois Tigeot return ret; 2687b5c29a34SFrançois Tigeot } 2688b5c29a34SFrançois Tigeot 2689e3adcf8fSFrançois Tigeot return 0; 2690e3adcf8fSFrançois Tigeot } 2691e3adcf8fSFrançois Tigeot 269287df8fc6SFrançois Tigeot int intel_init_bsd_ring_buffer(struct intel_engine_cs *engine) 2693e3adcf8fSFrançois Tigeot { 269487df8fc6SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 2695686a02f1SFrançois Tigeot 26961487f786SFrançois Tigeot intel_ring_default_vfuncs(dev_priv, engine); 26971487f786SFrançois Tigeot 26981487f786SFrançois Tigeot if (INTEL_GEN(dev_priv) >= 6) { 2699686a02f1SFrançois Tigeot /* gen6 bsd needs a special wa for tail updates */ 27001487f786SFrançois Tigeot if (IS_GEN6(dev_priv)) 270171f41f3eSFrançois Tigeot engine->submit_request = gen6_bsd_submit_request; 270271f41f3eSFrançois Tigeot engine->emit_flush = gen6_bsd_ring_flush; 270387df8fc6SFrançois Tigeot if (INTEL_GEN(dev_priv) < 8) 27048621f407SFrançois Tigeot engine->irq_enable_mask = GT_BSD_USER_INTERRUPT; 2705686a02f1SFrançois Tigeot } else { 27068621f407SFrançois Tigeot engine->mmio_base = BSD_RING_BASE; 270771f41f3eSFrançois Tigeot engine->emit_flush = bsd_ring_flush; 27081487f786SFrançois Tigeot if (IS_GEN5(dev_priv)) 27098621f407SFrançois Tigeot engine->irq_enable_mask = ILK_BSD_USER_INTERRUPT; 27101487f786SFrançois Tigeot else 27118621f407SFrançois Tigeot engine->irq_enable_mask = I915_BSD_USER_INTERRUPT; 2712686a02f1SFrançois Tigeot } 2713e3adcf8fSFrançois Tigeot 271487df8fc6SFrançois Tigeot return intel_init_ring_buffer(engine); 2715e3adcf8fSFrançois Tigeot } 2716e3adcf8fSFrançois Tigeot 2717ba55f2f5SFrançois Tigeot /** 2718477eb7f9SFrançois Tigeot * Initialize the second BSD ring (eg. Broadwell GT3, Skylake GT3) 2719ba55f2f5SFrançois Tigeot */ 272087df8fc6SFrançois Tigeot int intel_init_bsd2_ring_buffer(struct intel_engine_cs *engine) 2721ba55f2f5SFrançois Tigeot { 272287df8fc6SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 27231487f786SFrançois Tigeot 27241487f786SFrançois Tigeot intel_ring_default_vfuncs(dev_priv, engine); 27251487f786SFrançois Tigeot 272671f41f3eSFrançois Tigeot engine->emit_flush = gen6_bsd_ring_flush; 2727ba55f2f5SFrançois Tigeot 272887df8fc6SFrançois Tigeot return intel_init_ring_buffer(engine); 2729ba55f2f5SFrançois Tigeot } 2730ba55f2f5SFrançois Tigeot 273187df8fc6SFrançois Tigeot int intel_init_blt_ring_buffer(struct intel_engine_cs *engine) 2732e3adcf8fSFrançois Tigeot { 273387df8fc6SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 27341487f786SFrançois Tigeot 27351487f786SFrançois Tigeot intel_ring_default_vfuncs(dev_priv, engine); 27361487f786SFrançois Tigeot 273771f41f3eSFrançois Tigeot engine->emit_flush = gen6_ring_flush; 273887df8fc6SFrançois Tigeot if (INTEL_GEN(dev_priv) < 8) 27398621f407SFrançois Tigeot engine->irq_enable_mask = GT_BLT_USER_INTERRUPT; 27405d0b1887SFrançois Tigeot 274187df8fc6SFrançois Tigeot return intel_init_ring_buffer(engine); 27425d0b1887SFrançois Tigeot } 27435d0b1887SFrançois Tigeot 274487df8fc6SFrançois Tigeot int intel_init_vebox_ring_buffer(struct intel_engine_cs *engine) 27455d0b1887SFrançois Tigeot { 274687df8fc6SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 27479edbd4a0SFrançois Tigeot 27481487f786SFrançois Tigeot intel_ring_default_vfuncs(dev_priv, engine); 27491487f786SFrançois Tigeot 275071f41f3eSFrançois Tigeot engine->emit_flush = gen6_ring_flush; 27511487f786SFrançois Tigeot 275287df8fc6SFrançois Tigeot if (INTEL_GEN(dev_priv) < 8) { 27538621f407SFrançois Tigeot engine->irq_enable_mask = PM_VEBOX_USER_INTERRUPT; 2754303bf270SFrançois Tigeot engine->irq_enable = hsw_vebox_irq_enable; 2755303bf270SFrançois Tigeot engine->irq_disable = hsw_vebox_irq_disable; 275624edb884SFrançois Tigeot } 2757e3adcf8fSFrançois Tigeot 275887df8fc6SFrançois Tigeot return intel_init_ring_buffer(engine); 2759e3adcf8fSFrançois Tigeot } 2760