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 50*71f41f3eSFrançois Tigeot void intel_ring_update_space(struct intel_ring *ring) 512c9916cdSFrançois Tigeot { 52*71f41f3eSFrançois Tigeot if (ring->last_retired_head != -1) { 53*71f41f3eSFrançois Tigeot ring->head = ring->last_retired_head; 54*71f41f3eSFrançois Tigeot ring->last_retired_head = -1; 552c9916cdSFrançois Tigeot } 562c9916cdSFrançois Tigeot 57*71f41f3eSFrançois Tigeot ring->space = __intel_ring_space(ring->head & HEAD_ADDR, 58*71f41f3eSFrançois Tigeot ring->tail, ring->size); 599edbd4a0SFrançois Tigeot } 609edbd4a0SFrançois Tigeot 61e3adcf8fSFrançois Tigeot static int 62*71f41f3eSFrançois Tigeot gen2_render_ring_flush(struct drm_i915_gem_request *req, u32 mode) 63686a02f1SFrançois Tigeot { 64*71f41f3eSFranç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 70*71f41f3eSFranç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 77*71f41f3eSFrançois Tigeot intel_ring_emit(ring, cmd); 78*71f41f3eSFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 79*71f41f3eSFranç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 85*71f41f3eSFrançois Tigeot gen4_render_ring_flush(struct drm_i915_gem_request *req, u32 mode) 86e3adcf8fSFrançois Tigeot { 87*71f41f3eSFranç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 119*71f41f3eSFrançois Tigeot cmd = MI_FLUSH; 120*71f41f3eSFrançois Tigeot if (mode & EMIT_INVALIDATE) { 121e3adcf8fSFrançois Tigeot cmd |= MI_EXE_FLUSH; 122*71f41f3eSFrançois Tigeot if (IS_G4X(req->i915) || IS_GEN5(req->i915)) 123e3adcf8fSFrançois Tigeot cmd |= MI_INVALIDATE_ISP; 124*71f41f3eSFranç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 130*71f41f3eSFrançois Tigeot intel_ring_emit(ring, cmd); 131*71f41f3eSFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 132*71f41f3eSFranç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 { 177*71f41f3eSFrançois Tigeot struct intel_ring *ring = req->ring; 178*71f41f3eSFrançois Tigeot u32 scratch_addr = 179*71f41f3eSFrançois Tigeot req->engine->scratch.gtt_offset + 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 186*71f41f3eSFrançois Tigeot intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(5)); 187*71f41f3eSFrançois Tigeot intel_ring_emit(ring, PIPE_CONTROL_CS_STALL | 188e3adcf8fSFrançois Tigeot PIPE_CONTROL_STALL_AT_SCOREBOARD); 189*71f41f3eSFrançois Tigeot intel_ring_emit(ring, scratch_addr | PIPE_CONTROL_GLOBAL_GTT); 190*71f41f3eSFrançois Tigeot intel_ring_emit(ring, 0); /* low dword */ 191*71f41f3eSFrançois Tigeot intel_ring_emit(ring, 0); /* high dword */ 192*71f41f3eSFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 193*71f41f3eSFranç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 199*71f41f3eSFrançois Tigeot intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(5)); 200*71f41f3eSFrançois Tigeot intel_ring_emit(ring, PIPE_CONTROL_QW_WRITE); 201*71f41f3eSFrançois Tigeot intel_ring_emit(ring, scratch_addr | PIPE_CONTROL_GLOBAL_GTT); 202*71f41f3eSFrançois Tigeot intel_ring_emit(ring, 0); 203*71f41f3eSFrançois Tigeot intel_ring_emit(ring, 0); 204*71f41f3eSFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 205*71f41f3eSFranç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 211*71f41f3eSFrançois Tigeot gen6_render_ring_flush(struct drm_i915_gem_request *req, u32 mode) 212e3adcf8fSFrançois Tigeot { 213*71f41f3eSFrançois Tigeot struct intel_ring *ring = req->ring; 214*71f41f3eSFrançois Tigeot u32 scratch_addr = 215*71f41f3eSFrançois Tigeot req->engine->scratch.gtt_offset + 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 */ 228*71f41f3eSFranç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 } 237*71f41f3eSFranç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 254*71f41f3eSFrançois Tigeot intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(4)); 255*71f41f3eSFrançois Tigeot intel_ring_emit(ring, flags); 256*71f41f3eSFrançois Tigeot intel_ring_emit(ring, scratch_addr | PIPE_CONTROL_GLOBAL_GTT); 257*71f41f3eSFrançois Tigeot intel_ring_emit(ring, 0); 258*71f41f3eSFranç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 { 266*71f41f3eSFranç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 273*71f41f3eSFrançois Tigeot intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(4)); 274*71f41f3eSFrançois Tigeot intel_ring_emit(ring, 275*71f41f3eSFrançois Tigeot PIPE_CONTROL_CS_STALL | 276b5c29a34SFrançois Tigeot PIPE_CONTROL_STALL_AT_SCOREBOARD); 277*71f41f3eSFrançois Tigeot intel_ring_emit(ring, 0); 278*71f41f3eSFrançois Tigeot intel_ring_emit(ring, 0); 279*71f41f3eSFranç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 285*71f41f3eSFrançois Tigeot gen7_render_ring_flush(struct drm_i915_gem_request *req, u32 mode) 286b5c29a34SFrançois Tigeot { 287*71f41f3eSFrançois Tigeot struct intel_ring *ring = req->ring; 288*71f41f3eSFrançois Tigeot u32 scratch_addr = 289*71f41f3eSFrançois Tigeot req->engine->scratch.gtt_offset + 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 */ 307*71f41f3eSFranç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 } 313*71f41f3eSFranç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 339*71f41f3eSFrançois Tigeot intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(4)); 340*71f41f3eSFrançois Tigeot intel_ring_emit(ring, flags); 341*71f41f3eSFrançois Tigeot intel_ring_emit(ring, scratch_addr); 342*71f41f3eSFrançois Tigeot intel_ring_emit(ring, 0); 343*71f41f3eSFranç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 { 352*71f41f3eSFranç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 359*71f41f3eSFrançois Tigeot intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(6)); 360*71f41f3eSFrançois Tigeot intel_ring_emit(ring, flags); 361*71f41f3eSFrançois Tigeot intel_ring_emit(ring, scratch_addr); 362*71f41f3eSFrançois Tigeot intel_ring_emit(ring, 0); 363*71f41f3eSFrançois Tigeot intel_ring_emit(ring, 0); 364*71f41f3eSFrançois Tigeot intel_ring_emit(ring, 0); 365*71f41f3eSFranç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 371*71f41f3eSFrançois Tigeot gen8_render_ring_flush(struct drm_i915_gem_request *req, u32 mode) 3729edbd4a0SFrançois Tigeot { 3738621f407SFrançois Tigeot u32 scratch_addr = req->engine->scratch.gtt_offset + 2 * CACHELINE_BYTES; 374*71f41f3eSFrançois Tigeot u32 flags = 0; 3759edbd4a0SFrançois Tigeot int ret; 3769edbd4a0SFrançois Tigeot 3779edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_CS_STALL; 3789edbd4a0SFrançois Tigeot 379*71f41f3eSFrançois Tigeot if (mode & EMIT_FLUSH) { 3809edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH; 3819edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_DEPTH_CACHE_FLUSH; 382aee94f86SFrançois Tigeot flags |= PIPE_CONTROL_DC_FLUSH_ENABLE; 383b49c8cf9SFrançois Tigeot flags |= PIPE_CONTROL_FLUSH_ENABLE; 3849edbd4a0SFrançois Tigeot } 385*71f41f3eSFrançois Tigeot if (mode & EMIT_INVALIDATE) { 3869edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_TLB_INVALIDATE; 3879edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE; 3889edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE; 3899edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_VF_CACHE_INVALIDATE; 3909edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_CONST_CACHE_INVALIDATE; 3919edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_STATE_CACHE_INVALIDATE; 3929edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_QW_WRITE; 3939edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_GLOBAL_GTT_IVB; 3949edbd4a0SFrançois Tigeot 39524edb884SFrançois Tigeot /* WaCsStallBeforeStateCacheInvalidate:bdw,chv */ 396a05eeebfSFrançois Tigeot ret = gen8_emit_pipe_control(req, 39724edb884SFrançois Tigeot PIPE_CONTROL_CS_STALL | 39824edb884SFrançois Tigeot PIPE_CONTROL_STALL_AT_SCOREBOARD, 39924edb884SFrançois Tigeot 0); 4009edbd4a0SFrançois Tigeot if (ret) 4019edbd4a0SFrançois Tigeot return ret; 40224edb884SFrançois Tigeot } 4039edbd4a0SFrançois Tigeot 404a05eeebfSFrançois Tigeot return gen8_emit_pipe_control(req, flags, scratch_addr); 4059edbd4a0SFrançois Tigeot } 4069edbd4a0SFrançois Tigeot 407*71f41f3eSFrançois Tigeot u64 intel_engine_get_active_head(struct intel_engine_cs *engine) 408e3adcf8fSFrançois Tigeot { 4091487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 410ba55f2f5SFrançois Tigeot u64 acthd; 411e3adcf8fSFrançois Tigeot 4121487f786SFrançois Tigeot if (INTEL_GEN(dev_priv) >= 8) 4138621f407SFrançois Tigeot acthd = I915_READ64_2x32(RING_ACTHD(engine->mmio_base), 4148621f407SFrançois Tigeot RING_ACTHD_UDW(engine->mmio_base)); 4151487f786SFrançois Tigeot else if (INTEL_GEN(dev_priv) >= 4) 4168621f407SFrançois Tigeot acthd = I915_READ(RING_ACTHD(engine->mmio_base)); 417ba55f2f5SFrançois Tigeot else 418ba55f2f5SFrançois Tigeot acthd = I915_READ(ACTHD); 419ba55f2f5SFrançois Tigeot 420ba55f2f5SFrançois Tigeot return acthd; 421e3adcf8fSFrançois Tigeot } 422e3adcf8fSFrançois Tigeot 4238621f407SFrançois Tigeot static void ring_setup_phys_status_page(struct intel_engine_cs *engine) 4245d0b1887SFrançois Tigeot { 4251487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 4265d0b1887SFrançois Tigeot u32 addr; 4275d0b1887SFrançois Tigeot 4285d0b1887SFrançois Tigeot addr = dev_priv->status_page_dmah->busaddr; 4291487f786SFrançois Tigeot if (INTEL_GEN(dev_priv) >= 4) 4305d0b1887SFrançois Tigeot addr |= (dev_priv->status_page_dmah->busaddr >> 28) & 0xf0; 4315d0b1887SFrançois Tigeot I915_WRITE(HWS_PGA, addr); 4325d0b1887SFrançois Tigeot } 4335d0b1887SFrançois Tigeot 4348621f407SFrançois Tigeot static void intel_ring_setup_status_page(struct intel_engine_cs *engine) 435477eb7f9SFrançois Tigeot { 4361487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 437aee94f86SFrançois Tigeot i915_reg_t mmio; 438477eb7f9SFrançois Tigeot 439477eb7f9SFrançois Tigeot /* The ring status page addresses are no longer next to the rest of 440477eb7f9SFrançois Tigeot * the ring registers as of gen7. 441477eb7f9SFrançois Tigeot */ 4421487f786SFrançois Tigeot if (IS_GEN7(dev_priv)) { 4438621f407SFrançois Tigeot switch (engine->id) { 444477eb7f9SFrançois Tigeot case RCS: 445477eb7f9SFrançois Tigeot mmio = RENDER_HWS_PGA_GEN7; 446477eb7f9SFrançois Tigeot break; 447477eb7f9SFrançois Tigeot case BCS: 448477eb7f9SFrançois Tigeot mmio = BLT_HWS_PGA_GEN7; 449477eb7f9SFrançois Tigeot break; 450477eb7f9SFrançois Tigeot /* 451477eb7f9SFrançois Tigeot * VCS2 actually doesn't exist on Gen7. Only shut up 452477eb7f9SFrançois Tigeot * gcc switch check warning 453477eb7f9SFrançois Tigeot */ 454477eb7f9SFrançois Tigeot case VCS2: 455477eb7f9SFrançois Tigeot case VCS: 456477eb7f9SFrançois Tigeot mmio = BSD_HWS_PGA_GEN7; 457477eb7f9SFrançois Tigeot break; 458477eb7f9SFrançois Tigeot case VECS: 459477eb7f9SFrançois Tigeot mmio = VEBOX_HWS_PGA_GEN7; 460477eb7f9SFrançois Tigeot break; 461477eb7f9SFrançois Tigeot } 4621487f786SFrançois Tigeot } else if (IS_GEN6(dev_priv)) { 4638621f407SFrançois Tigeot mmio = RING_HWS_PGA_GEN6(engine->mmio_base); 464477eb7f9SFrançois Tigeot } else { 465477eb7f9SFrançois Tigeot /* XXX: gen8 returns to sanity */ 4668621f407SFrançois Tigeot mmio = RING_HWS_PGA(engine->mmio_base); 467477eb7f9SFrançois Tigeot } 468477eb7f9SFrançois Tigeot 4698621f407SFrançois Tigeot I915_WRITE(mmio, (u32)engine->status_page.gfx_addr); 470477eb7f9SFrançois Tigeot POSTING_READ(mmio); 471477eb7f9SFrançois Tigeot 472477eb7f9SFrançois Tigeot /* 473477eb7f9SFrançois Tigeot * Flush the TLB for this page 474477eb7f9SFrançois Tigeot * 475477eb7f9SFrançois Tigeot * FIXME: These two bits have disappeared on gen8, so a question 476477eb7f9SFrançois Tigeot * arises: do we still need this and if so how should we go about 477477eb7f9SFrançois Tigeot * invalidating the TLB? 478477eb7f9SFrançois Tigeot */ 4791487f786SFrançois Tigeot if (IS_GEN(dev_priv, 6, 7)) { 4808621f407SFrançois Tigeot i915_reg_t reg = RING_INSTPM(engine->mmio_base); 481477eb7f9SFrançois Tigeot 482477eb7f9SFrançois Tigeot /* ring should be idle before issuing a sync flush*/ 4838621f407SFrançois Tigeot WARN_ON((I915_READ_MODE(engine) & MODE_IDLE) == 0); 484477eb7f9SFrançois Tigeot 485477eb7f9SFrançois Tigeot I915_WRITE(reg, 486477eb7f9SFrançois Tigeot _MASKED_BIT_ENABLE(INSTPM_TLB_INVALIDATE | 487477eb7f9SFrançois Tigeot INSTPM_SYNC_FLUSH)); 4881487f786SFrançois Tigeot if (intel_wait_for_register(dev_priv, 4891487f786SFrançois Tigeot reg, INSTPM_SYNC_FLUSH, 0, 490477eb7f9SFrançois Tigeot 1000)) 491477eb7f9SFrançois Tigeot DRM_ERROR("%s: wait for SyncFlush to complete for TLB invalidation timed out\n", 4928621f407SFrançois Tigeot engine->name); 493477eb7f9SFrançois Tigeot } 494477eb7f9SFrançois Tigeot } 495477eb7f9SFrançois Tigeot 4968621f407SFrançois Tigeot static bool stop_ring(struct intel_engine_cs *engine) 497e3adcf8fSFrançois Tigeot { 4981487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 499e3adcf8fSFrançois Tigeot 5001487f786SFrançois Tigeot if (!IS_GEN2(dev_priv)) { 5018621f407SFrançois Tigeot I915_WRITE_MODE(engine, _MASKED_BIT_ENABLE(STOP_RING)); 5021487f786SFrançois Tigeot if (intel_wait_for_register(dev_priv, 5031487f786SFrançois Tigeot RING_MI_MODE(engine->mmio_base), 5041487f786SFrançois Tigeot MODE_IDLE, 5051487f786SFrançois Tigeot MODE_IDLE, 5061487f786SFrançois Tigeot 1000)) { 5078621f407SFrançois Tigeot DRM_ERROR("%s : timed out trying to stop ring\n", 5088621f407SFrançois Tigeot engine->name); 5091b13d190SFrançois Tigeot /* Sometimes we observe that the idle flag is not 5101b13d190SFrançois Tigeot * set even though the ring is empty. So double 5111b13d190SFrançois Tigeot * check before giving up. 5121b13d190SFrançois Tigeot */ 5138621f407SFrançois Tigeot if (I915_READ_HEAD(engine) != I915_READ_TAIL(engine)) 514ba55f2f5SFrançois Tigeot return false; 515ba55f2f5SFrançois Tigeot } 516ba55f2f5SFrançois Tigeot } 517686a02f1SFrançois Tigeot 5188621f407SFrançois Tigeot I915_WRITE_CTL(engine, 0); 5198621f407SFrançois Tigeot I915_WRITE_HEAD(engine, 0); 520*71f41f3eSFrançois Tigeot I915_WRITE_TAIL(engine, 0); 521e3adcf8fSFrançois Tigeot 5221487f786SFrançois Tigeot if (!IS_GEN2(dev_priv)) { 5238621f407SFrançois Tigeot (void)I915_READ_CTL(engine); 5248621f407SFrançois Tigeot I915_WRITE_MODE(engine, _MASKED_BIT_DISABLE(STOP_RING)); 525ba55f2f5SFrançois Tigeot } 526e3adcf8fSFrançois Tigeot 5278621f407SFrançois Tigeot return (I915_READ_HEAD(engine) & HEAD_ADDR) == 0; 528ba55f2f5SFrançois Tigeot } 529ba55f2f5SFrançois Tigeot 5308621f407SFrançois Tigeot static int init_ring_common(struct intel_engine_cs *engine) 5318621f407SFrançois Tigeot { 5321487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 533*71f41f3eSFrançois Tigeot struct intel_ring *ring = engine->buffer; 534*71f41f3eSFrançois Tigeot struct drm_i915_gem_object *obj = ring->obj; 535ba55f2f5SFrançois Tigeot int ret = 0; 536ba55f2f5SFrançois Tigeot 5372c9916cdSFrançois Tigeot intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL); 538ba55f2f5SFrançois Tigeot 5398621f407SFrançois Tigeot if (!stop_ring(engine)) { 540ba55f2f5SFrançois Tigeot /* G45 ring initialization often fails to reset head to zero */ 541b5c29a34SFrançois Tigeot DRM_DEBUG_KMS("%s head not reset to zero " 542e3adcf8fSFrançois Tigeot "ctl %08x head %08x tail %08x start %08x\n", 5438621f407SFrançois Tigeot engine->name, 5448621f407SFrançois Tigeot I915_READ_CTL(engine), 5458621f407SFrançois Tigeot I915_READ_HEAD(engine), 5468621f407SFrançois Tigeot I915_READ_TAIL(engine), 5478621f407SFrançois Tigeot I915_READ_START(engine)); 548e3adcf8fSFrançois Tigeot 5498621f407SFrançois Tigeot if (!stop_ring(engine)) { 550e3adcf8fSFrançois Tigeot DRM_ERROR("failed to set %s head to zero " 551e3adcf8fSFrançois Tigeot "ctl %08x head %08x tail %08x start %08x\n", 5528621f407SFrançois Tigeot engine->name, 5538621f407SFrançois Tigeot I915_READ_CTL(engine), 5548621f407SFrançois Tigeot I915_READ_HEAD(engine), 5558621f407SFrançois Tigeot I915_READ_TAIL(engine), 5568621f407SFrançois Tigeot I915_READ_START(engine)); 557686a02f1SFrançois Tigeot ret = -EIO; 558686a02f1SFrançois Tigeot goto out; 559e3adcf8fSFrançois Tigeot } 560ba55f2f5SFrançois Tigeot } 561ba55f2f5SFrançois Tigeot 5621487f786SFrançois Tigeot if (I915_NEED_GFX_HWS(dev_priv)) 5638621f407SFrançois Tigeot intel_ring_setup_status_page(engine); 564ba55f2f5SFrançois Tigeot else 5658621f407SFrançois Tigeot ring_setup_phys_status_page(engine); 566ba55f2f5SFrançois Tigeot 5670f370975SMatthew Dillon /* Enforce ordering by reading HEAD register back */ 5688621f407SFrançois Tigeot I915_READ_HEAD(engine); 5690f370975SMatthew Dillon 570ba55f2f5SFrançois Tigeot /* Initialize the ring. This must happen _after_ we've cleared the ring 571ba55f2f5SFrançois Tigeot * registers with the above sequence (the readback of the HEAD registers 572ba55f2f5SFrançois Tigeot * also enforces ordering), otherwise the hw might lose the new ring 573ba55f2f5SFrançois Tigeot * register values. */ 5748621f407SFrançois Tigeot I915_WRITE_START(engine, i915_gem_obj_ggtt_offset(obj)); 5751b13d190SFrançois Tigeot 5761b13d190SFrançois Tigeot /* WaClearRingBufHeadRegAtInit:ctg,elk */ 5778621f407SFrançois Tigeot if (I915_READ_HEAD(engine)) 5781b13d190SFrançois Tigeot DRM_DEBUG("%s initialization failed [head=%08x], fudging\n", 5798621f407SFrançois Tigeot engine->name, I915_READ_HEAD(engine)); 5808621f407SFrançois Tigeot I915_WRITE_HEAD(engine, 0); 5818621f407SFrançois Tigeot (void)I915_READ_HEAD(engine); 5821b13d190SFrançois Tigeot 5838621f407SFrançois Tigeot I915_WRITE_CTL(engine, 584*71f41f3eSFrançois Tigeot ((ring->size - PAGE_SIZE) & RING_NR_PAGES) 585ba55f2f5SFrançois Tigeot | RING_VALID); 586ba55f2f5SFrançois Tigeot 587ba55f2f5SFrançois Tigeot /* If the head is still not zero, the ring is dead */ 5888621f407SFrançois Tigeot if (wait_for((I915_READ_CTL(engine) & RING_VALID) != 0 && 5898621f407SFrançois Tigeot I915_READ_START(engine) == i915_gem_obj_ggtt_offset(obj) && 5908621f407SFrançois Tigeot (I915_READ_HEAD(engine) & HEAD_ADDR) == 0, 50)) { 591ba55f2f5SFrançois Tigeot DRM_ERROR("%s initialization failed " 592ba55f2f5SFrançois Tigeot "ctl %08x (valid? %d) head %08x tail %08x start %08x [expected %08lx]\n", 5938621f407SFrançois Tigeot engine->name, 5948621f407SFrançois Tigeot I915_READ_CTL(engine), 5958621f407SFrançois Tigeot I915_READ_CTL(engine) & RING_VALID, 5968621f407SFrançois Tigeot I915_READ_HEAD(engine), I915_READ_TAIL(engine), 5978621f407SFrançois Tigeot I915_READ_START(engine), 5988621f407SFrançois Tigeot (unsigned long)i915_gem_obj_ggtt_offset(obj)); 599ba55f2f5SFrançois Tigeot ret = -EIO; 600ba55f2f5SFrançois Tigeot goto out; 601ba55f2f5SFrançois Tigeot } 602e3adcf8fSFrançois Tigeot 603*71f41f3eSFrançois Tigeot ring->last_retired_head = -1; 604*71f41f3eSFrançois Tigeot ring->head = I915_READ_HEAD(engine); 605*71f41f3eSFrançois Tigeot ring->tail = I915_READ_TAIL(engine) & TAIL_ADDR; 606*71f41f3eSFrançois Tigeot intel_ring_update_space(ring); 607e3adcf8fSFrançois Tigeot 6088621f407SFrançois Tigeot intel_engine_init_hangcheck(engine); 6095d0b1887SFrançois Tigeot 610686a02f1SFrançois Tigeot out: 6112c9916cdSFrançois Tigeot intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL); 612686a02f1SFrançois Tigeot 613686a02f1SFrançois Tigeot return ret; 614e3adcf8fSFrançois Tigeot } 615e3adcf8fSFrançois Tigeot 616303bf270SFrançois Tigeot void intel_fini_pipe_control(struct intel_engine_cs *engine) 6171b13d190SFrançois Tigeot { 6188621f407SFrançois Tigeot if (engine->scratch.obj == NULL) 6191b13d190SFrançois Tigeot return; 6201b13d190SFrançois Tigeot 6218621f407SFrançois Tigeot i915_gem_object_ggtt_unpin(engine->scratch.obj); 62287df8fc6SFrançois Tigeot i915_gem_object_put(engine->scratch.obj); 6238621f407SFrançois Tigeot engine->scratch.obj = NULL; 6241b13d190SFrançois Tigeot } 6251b13d190SFrançois Tigeot 626303bf270SFrançois Tigeot int intel_init_pipe_control(struct intel_engine_cs *engine, int size) 627e3adcf8fSFrançois Tigeot { 628303bf270SFrançois Tigeot struct drm_i915_gem_object *obj; 629e3adcf8fSFrançois Tigeot int ret; 630e3adcf8fSFrançois Tigeot 6318621f407SFrançois Tigeot WARN_ON(engine->scratch.obj); 632e3adcf8fSFrançois Tigeot 633303bf270SFrançois Tigeot obj = i915_gem_object_create_stolen(&engine->i915->drm, size); 634303bf270SFrançois Tigeot if (!obj) 635303bf270SFrançois Tigeot obj = i915_gem_object_create(&engine->i915->drm, size); 636303bf270SFrançois Tigeot if (IS_ERR(obj)) { 637303bf270SFrançois Tigeot DRM_ERROR("Failed to allocate scratch page\n"); 638303bf270SFrançois Tigeot ret = PTR_ERR(obj); 639e3adcf8fSFrançois Tigeot goto err; 640e3adcf8fSFrançois Tigeot } 641e3adcf8fSFrançois Tigeot 642*71f41f3eSFrançois Tigeot ret = i915_gem_object_ggtt_pin(obj, NULL, 0, 4096, PIN_HIGH); 643ba55f2f5SFrançois Tigeot if (ret) 644ba55f2f5SFrançois Tigeot goto err_unref; 645e3adcf8fSFrançois Tigeot 646303bf270SFrançois Tigeot engine->scratch.obj = obj; 647303bf270SFrançois Tigeot engine->scratch.gtt_offset = i915_gem_obj_ggtt_offset(obj); 648a2fdbec6SFrançois Tigeot DRM_DEBUG_DRIVER("%s pipe control offset: 0x%08x\n", 6498621f407SFrançois Tigeot engine->name, engine->scratch.gtt_offset); 650e3adcf8fSFrançois Tigeot return 0; 651e3adcf8fSFrançois Tigeot 652e3adcf8fSFrançois Tigeot err_unref: 65387df8fc6SFrançois Tigeot i915_gem_object_put(engine->scratch.obj); 654e3adcf8fSFrançois Tigeot err: 655e3adcf8fSFrançois Tigeot return ret; 656e3adcf8fSFrançois Tigeot } 657e3adcf8fSFrançois Tigeot 658a05eeebfSFrançois Tigeot static int intel_ring_workarounds_emit(struct drm_i915_gem_request *req) 6591b13d190SFrançois Tigeot { 660*71f41f3eSFrançois Tigeot struct intel_ring *ring = req->ring; 6611487f786SFrançois Tigeot struct i915_workarounds *w = &req->i915->workarounds; 6621487f786SFrançois Tigeot int ret, i; 6631b13d190SFrançois Tigeot 664352ff8bdSFrançois Tigeot if (w->count == 0) 6652c9916cdSFrançois Tigeot return 0; 6661b13d190SFrançois Tigeot 667*71f41f3eSFrançois Tigeot ret = req->engine->emit_flush(req, EMIT_BARRIER); 6681b13d190SFrançois Tigeot if (ret) 6691b13d190SFrançois Tigeot return ret; 6701b13d190SFrançois Tigeot 671a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, (w->count * 2 + 2)); 6722c9916cdSFrançois Tigeot if (ret) 6732c9916cdSFrançois Tigeot return ret; 6742c9916cdSFrançois Tigeot 675*71f41f3eSFrançois Tigeot intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(w->count)); 6762c9916cdSFrançois Tigeot for (i = 0; i < w->count; i++) { 677*71f41f3eSFrançois Tigeot intel_ring_emit_reg(ring, w->reg[i].addr); 678*71f41f3eSFrançois Tigeot intel_ring_emit(ring, w->reg[i].value); 6792c9916cdSFrançois Tigeot } 680*71f41f3eSFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 6812c9916cdSFrançois Tigeot 682*71f41f3eSFrançois Tigeot intel_ring_advance(ring); 6832c9916cdSFrançois Tigeot 684*71f41f3eSFrançois Tigeot ret = req->engine->emit_flush(req, EMIT_BARRIER); 6852c9916cdSFrançois Tigeot if (ret) 6862c9916cdSFrançois Tigeot return ret; 6872c9916cdSFrançois Tigeot 6882c9916cdSFrançois Tigeot DRM_DEBUG_DRIVER("Number of Workarounds emitted: %d\n", w->count); 6892c9916cdSFrançois Tigeot 6902c9916cdSFrançois Tigeot return 0; 6912c9916cdSFrançois Tigeot } 6922c9916cdSFrançois Tigeot 693a05eeebfSFrançois Tigeot static int intel_rcs_ctx_init(struct drm_i915_gem_request *req) 6942c9916cdSFrançois Tigeot { 6952c9916cdSFrançois Tigeot int ret; 6962c9916cdSFrançois Tigeot 697a05eeebfSFrançois Tigeot ret = intel_ring_workarounds_emit(req); 6982c9916cdSFrançois Tigeot if (ret != 0) 6992c9916cdSFrançois Tigeot return ret; 7002c9916cdSFrançois Tigeot 701a05eeebfSFrançois Tigeot ret = i915_gem_render_state_init(req); 7022c9916cdSFrançois Tigeot if (ret) 7032c9916cdSFrançois Tigeot return ret; 704c0e85e96SFrançois Tigeot 705c0e85e96SFrançois Tigeot return 0; 7062c9916cdSFrançois Tigeot } 7072c9916cdSFrançois Tigeot 7082c9916cdSFrançois Tigeot static int wa_add(struct drm_i915_private *dev_priv, 709aee94f86SFrançois Tigeot i915_reg_t addr, 710aee94f86SFrançois Tigeot const u32 mask, const u32 val) 7112c9916cdSFrançois Tigeot { 7122c9916cdSFrançois Tigeot const u32 idx = dev_priv->workarounds.count; 7132c9916cdSFrançois Tigeot 7142c9916cdSFrançois Tigeot if (WARN_ON(idx >= I915_MAX_WA_REGS)) 7152c9916cdSFrançois Tigeot return -ENOSPC; 7162c9916cdSFrançois Tigeot 7172c9916cdSFrançois Tigeot dev_priv->workarounds.reg[idx].addr = addr; 7182c9916cdSFrançois Tigeot dev_priv->workarounds.reg[idx].value = val; 7192c9916cdSFrançois Tigeot dev_priv->workarounds.reg[idx].mask = mask; 7202c9916cdSFrançois Tigeot 7212c9916cdSFrançois Tigeot dev_priv->workarounds.count++; 7222c9916cdSFrançois Tigeot 7232c9916cdSFrançois Tigeot return 0; 7242c9916cdSFrançois Tigeot } 7252c9916cdSFrançois Tigeot 726a05eeebfSFrançois Tigeot #define WA_REG(addr, mask, val) do { \ 7272c9916cdSFrançois Tigeot const int r = wa_add(dev_priv, (addr), (mask), (val)); \ 7282c9916cdSFrançois Tigeot if (r) \ 7292c9916cdSFrançois Tigeot return r; \ 730a05eeebfSFrançois Tigeot } while (0) 7312c9916cdSFrançois Tigeot 7322c9916cdSFrançois Tigeot #define WA_SET_BIT_MASKED(addr, mask) \ 7332c9916cdSFrançois Tigeot WA_REG(addr, (mask), _MASKED_BIT_ENABLE(mask)) 7342c9916cdSFrançois Tigeot 7352c9916cdSFrançois Tigeot #define WA_CLR_BIT_MASKED(addr, mask) \ 7362c9916cdSFrançois Tigeot WA_REG(addr, (mask), _MASKED_BIT_DISABLE(mask)) 7372c9916cdSFrançois Tigeot 7382c9916cdSFrançois Tigeot #define WA_SET_FIELD_MASKED(addr, mask, value) \ 7392c9916cdSFrançois Tigeot WA_REG(addr, mask, _MASKED_FIELD(mask, value)) 7402c9916cdSFrançois Tigeot 7412c9916cdSFrançois Tigeot #define WA_SET_BIT(addr, mask) WA_REG(addr, mask, I915_READ(addr) | (mask)) 7422c9916cdSFrançois Tigeot #define WA_CLR_BIT(addr, mask) WA_REG(addr, mask, I915_READ(addr) & ~(mask)) 7432c9916cdSFrançois Tigeot 7442c9916cdSFrançois Tigeot #define WA_WRITE(addr, val) WA_REG(addr, 0xffffffff, val) 7452c9916cdSFrançois Tigeot 7468621f407SFrançois Tigeot static int wa_ring_whitelist_reg(struct intel_engine_cs *engine, 7478621f407SFrançois Tigeot i915_reg_t reg) 748c0e85e96SFrançois Tigeot { 7491487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 750c0e85e96SFrançois Tigeot struct i915_workarounds *wa = &dev_priv->workarounds; 7518621f407SFrançois Tigeot const uint32_t index = wa->hw_whitelist_count[engine->id]; 752c0e85e96SFrançois Tigeot 753c0e85e96SFrançois Tigeot if (WARN_ON(index >= RING_MAX_NONPRIV_SLOTS)) 754c0e85e96SFrançois Tigeot return -EINVAL; 755c0e85e96SFrançois Tigeot 7568621f407SFrançois Tigeot WA_WRITE(RING_FORCE_TO_NONPRIV(engine->mmio_base, index), 757c0e85e96SFrançois Tigeot i915_mmio_reg_offset(reg)); 7588621f407SFrançois Tigeot wa->hw_whitelist_count[engine->id]++; 759c0e85e96SFrançois Tigeot 760c0e85e96SFrançois Tigeot return 0; 761c0e85e96SFrançois Tigeot } 762c0e85e96SFrançois Tigeot 7638621f407SFrançois Tigeot static int gen8_init_workarounds(struct intel_engine_cs *engine) 7642c9916cdSFrançois Tigeot { 7651487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 7662c9916cdSFrançois Tigeot 767a05eeebfSFrançois Tigeot WA_SET_BIT_MASKED(INSTPM, INSTPM_FORCE_ORDERING); 768a05eeebfSFrançois Tigeot 769352ff8bdSFrançois Tigeot /* WaDisableAsyncFlipPerfMode:bdw,chv */ 770a05eeebfSFrançois Tigeot WA_SET_BIT_MASKED(MI_MODE, ASYNC_FLIP_PERF_DISABLE); 771a05eeebfSFrançois Tigeot 772352ff8bdSFrançois Tigeot /* WaDisablePartialInstShootdown:bdw,chv */ 7732c9916cdSFrançois Tigeot WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN, 774352ff8bdSFrançois Tigeot PARTIAL_INSTRUCTION_SHOOTDOWN_DISABLE); 7751b13d190SFrançois Tigeot 7761b13d190SFrançois Tigeot /* Use Force Non-Coherent whenever executing a 3D context. This is a 7771b13d190SFrançois Tigeot * workaround for for a possible hang in the unlikely event a TLB 7781b13d190SFrançois Tigeot * invalidation occurs during a PSD flush. 7791b13d190SFrançois Tigeot */ 780352ff8bdSFrançois Tigeot /* WaForceEnableNonCoherent:bdw,chv */ 781352ff8bdSFrançois Tigeot /* WaHdcDisableFetchWhenMasked:bdw,chv */ 7822c9916cdSFrançois Tigeot WA_SET_BIT_MASKED(HDC_CHICKEN0, 7832c9916cdSFrançois Tigeot HDC_DONOT_FETCH_MEM_WHEN_MASKED | 784352ff8bdSFrançois Tigeot HDC_FORCE_NON_COHERENT); 7852c9916cdSFrançois Tigeot 7862c9916cdSFrançois Tigeot /* From the Haswell PRM, Command Reference: Registers, CACHE_MODE_0: 7872c9916cdSFrançois Tigeot * "The Hierarchical Z RAW Stall Optimization allows non-overlapping 7882c9916cdSFrançois Tigeot * polygons in the same 8x4 pixel/sample area to be processed without 7892c9916cdSFrançois Tigeot * stalling waiting for the earlier ones to write to Hierarchical Z 7902c9916cdSFrançois Tigeot * buffer." 7912c9916cdSFrançois Tigeot * 792352ff8bdSFrançois Tigeot * This optimization is off by default for BDW and CHV; turn it on. 7932c9916cdSFrançois Tigeot */ 7942c9916cdSFrançois Tigeot WA_CLR_BIT_MASKED(CACHE_MODE_0_GEN7, HIZ_RAW_STALL_OPT_DISABLE); 7951b13d190SFrançois Tigeot 796352ff8bdSFrançois Tigeot /* Wa4x4STCOptimizationDisable:bdw,chv */ 797352ff8bdSFrançois Tigeot WA_SET_BIT_MASKED(CACHE_MODE_1, GEN8_4x4_STC_OPTIMIZATION_DISABLE); 7981b13d190SFrançois Tigeot 7991b13d190SFrançois Tigeot /* 8001b13d190SFrançois Tigeot * BSpec recommends 8x4 when MSAA is used, 8011b13d190SFrançois Tigeot * however in practice 16x4 seems fastest. 8021b13d190SFrançois Tigeot * 8031b13d190SFrançois Tigeot * Note that PS/WM thread counts depend on the WIZ hashing 8041b13d190SFrançois Tigeot * disable bit, which we don't touch here, but it's good 8051b13d190SFrançois Tigeot * to keep in mind (see 3DSTATE_PS and 3DSTATE_WM). 8061b13d190SFrançois Tigeot */ 8072c9916cdSFrançois Tigeot WA_SET_FIELD_MASKED(GEN7_GT_MODE, 8082c9916cdSFrançois Tigeot GEN6_WIZ_HASHING_MASK, 8092c9916cdSFrançois Tigeot GEN6_WIZ_HASHING_16x4); 8101b13d190SFrançois Tigeot 8111b13d190SFrançois Tigeot return 0; 8121b13d190SFrançois Tigeot } 8131b13d190SFrançois Tigeot 8148621f407SFrançois Tigeot static int bdw_init_workarounds(struct intel_engine_cs *engine) 8151b13d190SFrançois Tigeot { 8161487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 817352ff8bdSFrançois Tigeot int ret; 8181b13d190SFrançois Tigeot 8198621f407SFrançois Tigeot ret = gen8_init_workarounds(engine); 820352ff8bdSFrançois Tigeot if (ret) 821352ff8bdSFrançois Tigeot return ret; 822a05eeebfSFrançois Tigeot 823352ff8bdSFrançois Tigeot /* WaDisableThreadStallDopClockGating:bdw (pre-production) */ 824352ff8bdSFrançois Tigeot WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN, STALL_DOP_GATING_DISABLE); 825a05eeebfSFrançois Tigeot 826352ff8bdSFrançois Tigeot /* WaDisableDopClockGating:bdw */ 827352ff8bdSFrançois Tigeot WA_SET_BIT_MASKED(GEN7_ROW_CHICKEN2, 828352ff8bdSFrançois Tigeot DOP_CLOCK_GATING_DISABLE); 8291b13d190SFrançois Tigeot 830352ff8bdSFrançois Tigeot WA_SET_BIT_MASKED(HALF_SLICE_CHICKEN3, 831352ff8bdSFrançois Tigeot GEN8_SAMPLER_POWER_BYPASS_DIS); 832352ff8bdSFrançois Tigeot 8332c9916cdSFrançois Tigeot WA_SET_BIT_MASKED(HDC_CHICKEN0, 834352ff8bdSFrançois Tigeot /* WaForceContextSaveRestoreNonCoherent:bdw */ 835352ff8bdSFrançois Tigeot HDC_FORCE_CONTEXT_SAVE_RESTORE_NON_COHERENT | 836352ff8bdSFrançois Tigeot /* WaDisableFenceDestinationToSLM:bdw (pre-prod) */ 8371487f786SFrançois Tigeot (IS_BDW_GT3(dev_priv) ? HDC_FENCE_DEST_SLM_DISABLE : 0)); 8381b13d190SFrançois Tigeot 839352ff8bdSFrançois Tigeot return 0; 840352ff8bdSFrançois Tigeot } 8411b13d190SFrançois Tigeot 8428621f407SFrançois Tigeot static int chv_init_workarounds(struct intel_engine_cs *engine) 843352ff8bdSFrançois Tigeot { 8441487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 845352ff8bdSFrançois Tigeot int ret; 846352ff8bdSFrançois Tigeot 8478621f407SFrançois Tigeot ret = gen8_init_workarounds(engine); 848352ff8bdSFrançois Tigeot if (ret) 849352ff8bdSFrançois Tigeot return ret; 850352ff8bdSFrançois Tigeot 851352ff8bdSFrançois Tigeot /* WaDisableThreadStallDopClockGating:chv */ 852352ff8bdSFrançois Tigeot WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN, STALL_DOP_GATING_DISABLE); 8532c9916cdSFrançois Tigeot 8542c9916cdSFrançois Tigeot /* Improve HiZ throughput on CHV. */ 8552c9916cdSFrançois Tigeot WA_SET_BIT_MASKED(HIZ_CHICKEN, CHV_HZ_8X8_MODE_IN_1X); 8562c9916cdSFrançois Tigeot 8572c9916cdSFrançois Tigeot return 0; 8582c9916cdSFrançois Tigeot } 8592c9916cdSFrançois Tigeot 8608621f407SFrançois Tigeot static int gen9_init_workarounds(struct intel_engine_cs *engine) 861477eb7f9SFrançois Tigeot { 8621487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 863c0e85e96SFrançois Tigeot int ret; 864477eb7f9SFrançois Tigeot 8658621f407SFrançois Tigeot /* WaConextSwitchWithConcurrentTLBInvalidate:skl,bxt,kbl */ 8668621f407SFrançois Tigeot I915_WRITE(GEN9_CSFE_CHICKEN1_RCS, _MASKED_BIT_ENABLE(GEN9_PREEMPT_GPGPU_SYNC_SWITCH_DISABLE)); 8678621f407SFrançois Tigeot 8688621f407SFrançois Tigeot /* WaEnableLbsSlaRetryTimerDecrement:skl,bxt,kbl */ 869352ff8bdSFrançois Tigeot I915_WRITE(BDW_SCRATCH1, I915_READ(BDW_SCRATCH1) | 870352ff8bdSFrançois Tigeot GEN9_LBS_SLA_RETRY_TIMER_DECREMENT_ENABLE); 871352ff8bdSFrançois Tigeot 8728621f407SFrançois Tigeot /* WaDisableKillLogic:bxt,skl,kbl */ 873352ff8bdSFrançois Tigeot I915_WRITE(GAM_ECOCHK, I915_READ(GAM_ECOCHK) | 874352ff8bdSFrançois Tigeot ECOCHK_DIS_TLB); 875352ff8bdSFrançois Tigeot 8768621f407SFrançois Tigeot /* WaClearFlowControlGpgpuContextSave:skl,bxt,kbl */ 8778621f407SFrançois Tigeot /* WaDisablePartialInstShootdown:skl,bxt,kbl */ 878477eb7f9SFrançois Tigeot WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN, 8798621f407SFrançois Tigeot FLOW_CONTROL_ENABLE | 880477eb7f9SFrançois Tigeot PARTIAL_INSTRUCTION_SHOOTDOWN_DISABLE); 881477eb7f9SFrançois Tigeot 8828621f407SFrançois Tigeot /* Syncing dependencies between camera and graphics:skl,bxt,kbl */ 883477eb7f9SFrançois Tigeot WA_SET_BIT_MASKED(HALF_SLICE_CHICKEN3, 884477eb7f9SFrançois Tigeot GEN9_DISABLE_OCL_OOB_SUPPRESS_LOGIC); 885477eb7f9SFrançois Tigeot 88619c468b4SFrançois Tigeot /* WaDisableDgMirrorFixInHalfSliceChicken5:skl,bxt */ 8871487f786SFrançois Tigeot if (IS_SKL_REVID(dev_priv, 0, SKL_REVID_B0) || 8881487f786SFrançois Tigeot IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1)) 889477eb7f9SFrançois Tigeot WA_CLR_BIT_MASKED(GEN9_HALF_SLICE_CHICKEN5, 890477eb7f9SFrançois Tigeot GEN9_DG_MIRROR_FIX_ENABLE); 891477eb7f9SFrançois Tigeot 89219c468b4SFrançois Tigeot /* WaSetDisablePixMaskCammingAndRhwoInCommonSliceChicken:skl,bxt */ 8931487f786SFrançois Tigeot if (IS_SKL_REVID(dev_priv, 0, SKL_REVID_B0) || 8941487f786SFrançois Tigeot IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1)) { 895477eb7f9SFrançois Tigeot WA_SET_BIT_MASKED(GEN7_COMMON_SLICE_CHICKEN1, 896477eb7f9SFrançois Tigeot GEN9_RHWO_OPTIMIZATION_DISABLE); 897a05eeebfSFrançois Tigeot /* 898a05eeebfSFrançois Tigeot * WA also requires GEN9_SLICE_COMMON_ECO_CHICKEN0[14:14] to be set 899a05eeebfSFrançois Tigeot * but we do that in per ctx batchbuffer as there is an issue 900a05eeebfSFrançois Tigeot * with this register not getting restored on ctx restore 901a05eeebfSFrançois Tigeot */ 902477eb7f9SFrançois Tigeot } 903477eb7f9SFrançois Tigeot 9048621f407SFrançois Tigeot /* WaEnableYV12BugFixInHalfSliceChicken7:skl,bxt,kbl */ 9058621f407SFrançois Tigeot /* WaEnableSamplerGPGPUPreemptionSupport:skl,bxt,kbl */ 906477eb7f9SFrançois Tigeot WA_SET_BIT_MASKED(GEN9_HALF_SLICE_CHICKEN7, 9078621f407SFrançois Tigeot GEN9_ENABLE_YV12_BUGFIX | 9088621f407SFrançois Tigeot GEN9_ENABLE_GPGPU_PREEMPTION); 909477eb7f9SFrançois Tigeot 9108621f407SFrançois Tigeot /* Wa4x4STCOptimizationDisable:skl,bxt,kbl */ 9118621f407SFrançois Tigeot /* WaDisablePartialResolveInVc:skl,bxt,kbl */ 912352ff8bdSFrançois Tigeot WA_SET_BIT_MASKED(CACHE_MODE_1, (GEN8_4x4_STC_OPTIMIZATION_DISABLE | 913352ff8bdSFrançois Tigeot GEN9_PARTIAL_RESOLVE_IN_VC_DISABLE)); 914477eb7f9SFrançois Tigeot 9158621f407SFrançois Tigeot /* WaCcsTlbPrefetchDisable:skl,bxt,kbl */ 916477eb7f9SFrançois Tigeot WA_CLR_BIT_MASKED(GEN9_HALF_SLICE_CHICKEN5, 917477eb7f9SFrançois Tigeot GEN9_CCS_TLB_PREFETCH_ENABLE); 918477eb7f9SFrançois Tigeot 91919c468b4SFrançois Tigeot /* WaDisableMaskBasedCammingInRCC:skl,bxt */ 9201487f786SFrançois Tigeot if (IS_SKL_REVID(dev_priv, SKL_REVID_C0, SKL_REVID_C0) || 9211487f786SFrançois Tigeot IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1)) 92219c468b4SFrançois Tigeot WA_SET_BIT_MASKED(SLICE_ECO_CHICKEN0, 92319c468b4SFrançois Tigeot PIXEL_MASK_CAMMING_DISABLE); 92419c468b4SFrançois Tigeot 9258621f407SFrançois Tigeot /* WaForceContextSaveRestoreNonCoherent:skl,bxt,kbl */ 9268621f407SFrançois Tigeot WA_SET_BIT_MASKED(HDC_CHICKEN0, 9278621f407SFrançois Tigeot HDC_FORCE_CONTEXT_SAVE_RESTORE_NON_COHERENT | 9288621f407SFrançois Tigeot HDC_FORCE_CSR_NON_COHERENT_OVR_DISABLE); 92919c468b4SFrançois Tigeot 9308621f407SFrançois Tigeot /* WaForceEnableNonCoherent and WaDisableHDCInvalidation are 9318621f407SFrançois Tigeot * both tied to WaForceContextSaveRestoreNonCoherent 9328621f407SFrançois Tigeot * in some hsds for skl. We keep the tie for all gen9. The 9338621f407SFrançois Tigeot * documentation is a bit hazy and so we want to get common behaviour, 9348621f407SFrançois Tigeot * even though there is no clear evidence we would need both on kbl/bxt. 9358621f407SFrançois Tigeot * This area has been source of system hangs so we play it safe 9368621f407SFrançois Tigeot * and mimic the skl regardless of what bspec says. 9378621f407SFrançois Tigeot * 9388621f407SFrançois Tigeot * Use Force Non-Coherent whenever executing a 3D context. This 9398621f407SFrançois Tigeot * is a workaround for a possible hang in the unlikely event 9408621f407SFrançois Tigeot * a TLB invalidation occurs during a PSD flush. 9418621f407SFrançois Tigeot */ 9428621f407SFrançois Tigeot 9438621f407SFrançois Tigeot /* WaForceEnableNonCoherent:skl,bxt,kbl */ 9448621f407SFrançois Tigeot WA_SET_BIT_MASKED(HDC_CHICKEN0, 9458621f407SFrançois Tigeot HDC_FORCE_NON_COHERENT); 9468621f407SFrançois Tigeot 9478621f407SFrançois Tigeot /* WaDisableHDCInvalidation:skl,bxt,kbl */ 9488621f407SFrançois Tigeot I915_WRITE(GAM_ECOCHK, I915_READ(GAM_ECOCHK) | 9498621f407SFrançois Tigeot BDW_DISABLE_HDC_INVALIDATION); 9508621f407SFrançois Tigeot 9518621f407SFrançois Tigeot /* WaDisableSamplerPowerBypassForSOPingPong:skl,bxt,kbl */ 9528621f407SFrançois Tigeot if (IS_SKYLAKE(dev_priv) || 9538621f407SFrançois Tigeot IS_KABYLAKE(dev_priv) || 9548621f407SFrançois Tigeot IS_BXT_REVID(dev_priv, 0, BXT_REVID_B0)) 955352ff8bdSFrançois Tigeot WA_SET_BIT_MASKED(HALF_SLICE_CHICKEN3, 956352ff8bdSFrançois Tigeot GEN8_SAMPLER_POWER_BYPASS_DIS); 957352ff8bdSFrançois Tigeot 9588621f407SFrançois Tigeot /* WaDisableSTUnitPowerOptimization:skl,bxt,kbl */ 959352ff8bdSFrançois Tigeot WA_SET_BIT_MASKED(HALF_SLICE_CHICKEN2, GEN8_ST_PO_DISABLE); 960352ff8bdSFrançois Tigeot 9618621f407SFrançois Tigeot /* WaOCLCoherentLineFlush:skl,bxt,kbl */ 962c0e85e96SFrançois Tigeot I915_WRITE(GEN8_L3SQCREG4, (I915_READ(GEN8_L3SQCREG4) | 963c0e85e96SFrançois Tigeot GEN8_LQSC_FLUSH_COHERENT_LINES)); 964c0e85e96SFrançois Tigeot 9658621f407SFrançois Tigeot /* WaVFEStateAfterPipeControlwithMediaStateClear:skl,bxt */ 9668621f407SFrançois Tigeot ret = wa_ring_whitelist_reg(engine, GEN9_CTX_PREEMPT_REG); 967c0e85e96SFrançois Tigeot if (ret) 968c0e85e96SFrançois Tigeot return ret; 969c0e85e96SFrançois Tigeot 9708621f407SFrançois Tigeot /* WaEnablePreemptionGranularityControlByUMD:skl,bxt,kbl */ 9718621f407SFrançois Tigeot ret= wa_ring_whitelist_reg(engine, GEN8_CS_CHICKEN1); 9728621f407SFrançois Tigeot if (ret) 9738621f407SFrançois Tigeot return ret; 9748621f407SFrançois Tigeot 9758621f407SFrançois Tigeot /* WaAllowUMDToModifyHDCChicken1:skl,bxt,kbl */ 9768621f407SFrançois Tigeot ret = wa_ring_whitelist_reg(engine, GEN8_HDC_CHICKEN1); 977c0e85e96SFrançois Tigeot if (ret) 978c0e85e96SFrançois Tigeot return ret; 979c0e85e96SFrançois Tigeot 980477eb7f9SFrançois Tigeot return 0; 981477eb7f9SFrançois Tigeot } 982477eb7f9SFrançois Tigeot 9838621f407SFrançois Tigeot static int skl_tune_iz_hashing(struct intel_engine_cs *engine) 984477eb7f9SFrançois Tigeot { 9851487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 986477eb7f9SFrançois Tigeot u8 vals[3] = { 0, 0, 0 }; 987477eb7f9SFrançois Tigeot unsigned int i; 988477eb7f9SFrançois Tigeot 989477eb7f9SFrançois Tigeot for (i = 0; i < 3; i++) { 990477eb7f9SFrançois Tigeot u8 ss; 991477eb7f9SFrançois Tigeot 992477eb7f9SFrançois Tigeot /* 993477eb7f9SFrançois Tigeot * Only consider slices where one, and only one, subslice has 7 994477eb7f9SFrançois Tigeot * EUs 995477eb7f9SFrançois Tigeot */ 996aee94f86SFrançois Tigeot if (!is_power_of_2(dev_priv->info.subslice_7eu[i])) 997477eb7f9SFrançois Tigeot continue; 998477eb7f9SFrançois Tigeot 999477eb7f9SFrançois Tigeot /* 1000477eb7f9SFrançois Tigeot * subslice_7eu[i] != 0 (because of the check above) and 1001477eb7f9SFrançois Tigeot * ss_max == 4 (maximum number of subslices possible per slice) 1002477eb7f9SFrançois Tigeot * 1003477eb7f9SFrançois Tigeot * -> 0 <= ss <= 3; 1004477eb7f9SFrançois Tigeot */ 1005477eb7f9SFrançois Tigeot ss = ffs(dev_priv->info.subslice_7eu[i]) - 1; 1006477eb7f9SFrançois Tigeot vals[i] = 3 - ss; 1007477eb7f9SFrançois Tigeot } 1008477eb7f9SFrançois Tigeot 1009477eb7f9SFrançois Tigeot if (vals[0] == 0 && vals[1] == 0 && vals[2] == 0) 1010477eb7f9SFrançois Tigeot return 0; 1011477eb7f9SFrançois Tigeot 1012477eb7f9SFrançois Tigeot /* Tune IZ hashing. See intel_device_info_runtime_init() */ 1013477eb7f9SFrançois Tigeot WA_SET_FIELD_MASKED(GEN7_GT_MODE, 1014477eb7f9SFrançois Tigeot GEN9_IZ_HASHING_MASK(2) | 1015477eb7f9SFrançois Tigeot GEN9_IZ_HASHING_MASK(1) | 1016477eb7f9SFrançois Tigeot GEN9_IZ_HASHING_MASK(0), 1017477eb7f9SFrançois Tigeot GEN9_IZ_HASHING(2, vals[2]) | 1018477eb7f9SFrançois Tigeot GEN9_IZ_HASHING(1, vals[1]) | 1019477eb7f9SFrançois Tigeot GEN9_IZ_HASHING(0, vals[0])); 1020477eb7f9SFrançois Tigeot 1021477eb7f9SFrançois Tigeot return 0; 1022477eb7f9SFrançois Tigeot } 1023477eb7f9SFrançois Tigeot 10248621f407SFrançois Tigeot static int skl_init_workarounds(struct intel_engine_cs *engine) 1025477eb7f9SFrançois Tigeot { 10261487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 1027352ff8bdSFrançois Tigeot int ret; 1028477eb7f9SFrançois Tigeot 10298621f407SFrançois Tigeot ret = gen9_init_workarounds(engine); 1030352ff8bdSFrançois Tigeot if (ret) 1031352ff8bdSFrançois Tigeot return ret; 1032352ff8bdSFrançois Tigeot 1033c0e85e96SFrançois Tigeot /* 1034c0e85e96SFrançois Tigeot * Actual WA is to disable percontext preemption granularity control 1035c0e85e96SFrançois Tigeot * until D0 which is the default case so this is equivalent to 1036c0e85e96SFrançois Tigeot * !WaDisablePerCtxtPreemptionGranularityControl:skl 1037c0e85e96SFrançois Tigeot */ 10381487f786SFrançois Tigeot if (IS_SKL_REVID(dev_priv, SKL_REVID_E0, REVID_FOREVER)) { 1039c0e85e96SFrançois Tigeot I915_WRITE(GEN7_FF_SLICE_CS_CHICKEN1, 1040c0e85e96SFrançois Tigeot _MASKED_BIT_ENABLE(GEN9_FFSC_PERCTX_PREEMPT_CTRL)); 1041c0e85e96SFrançois Tigeot } 1042c0e85e96SFrançois Tigeot 10431487f786SFrançois Tigeot if (IS_SKL_REVID(dev_priv, 0, SKL_REVID_E0)) { 1044352ff8bdSFrançois Tigeot /* WaDisableChickenBitTSGBarrierAckForFFSliceCS:skl */ 1045352ff8bdSFrançois Tigeot I915_WRITE(FF_SLICE_CS_CHICKEN2, 1046352ff8bdSFrançois Tigeot _MASKED_BIT_ENABLE(GEN9_TSG_BARRIER_ACK_DISABLE)); 1047352ff8bdSFrançois Tigeot } 1048352ff8bdSFrançois Tigeot 1049352ff8bdSFrançois Tigeot /* GEN8_L3SQCREG4 has a dependency with WA batch so any new changes 1050352ff8bdSFrançois Tigeot * involving this register should also be added to WA batch as required. 1051352ff8bdSFrançois Tigeot */ 10521487f786SFrançois Tigeot if (IS_SKL_REVID(dev_priv, 0, SKL_REVID_E0)) 1053352ff8bdSFrançois Tigeot /* WaDisableLSQCROPERFforOCL:skl */ 1054352ff8bdSFrançois Tigeot I915_WRITE(GEN8_L3SQCREG4, I915_READ(GEN8_L3SQCREG4) | 1055352ff8bdSFrançois Tigeot GEN8_LQSC_RO_PERF_DIS); 1056352ff8bdSFrançois Tigeot 1057352ff8bdSFrançois Tigeot /* WaEnableGapsTsvCreditFix:skl */ 10581487f786SFrançois Tigeot if (IS_SKL_REVID(dev_priv, SKL_REVID_C0, REVID_FOREVER)) { 1059352ff8bdSFrançois Tigeot I915_WRITE(GEN8_GARBCNTL, (I915_READ(GEN8_GARBCNTL) | 1060352ff8bdSFrançois Tigeot GEN9_GAPS_TSV_CREDIT_DISABLE)); 1061352ff8bdSFrançois Tigeot } 1062477eb7f9SFrançois Tigeot 1063477eb7f9SFrançois Tigeot /* WaDisablePowerCompilerClockGating:skl */ 10641487f786SFrançois Tigeot if (IS_SKL_REVID(dev_priv, SKL_REVID_B0, SKL_REVID_B0)) 1065477eb7f9SFrançois Tigeot WA_SET_BIT_MASKED(HIZ_CHICKEN, 1066477eb7f9SFrançois Tigeot BDW_HIZ_POWER_COMPILER_CLOCK_GATING_DISABLE); 1067477eb7f9SFrançois Tigeot 1068a05eeebfSFrançois Tigeot /* WaBarrierPerformanceFixDisable:skl */ 10691487f786SFrançois Tigeot if (IS_SKL_REVID(dev_priv, SKL_REVID_C0, SKL_REVID_D0)) 1070a05eeebfSFrançois Tigeot WA_SET_BIT_MASKED(HDC_CHICKEN0, 1071a05eeebfSFrançois Tigeot HDC_FENCE_DEST_SLM_DISABLE | 1072a05eeebfSFrançois Tigeot HDC_BARRIER_PERFORMANCE_DISABLE); 1073a05eeebfSFrançois Tigeot 1074a05eeebfSFrançois Tigeot /* WaDisableSbeCacheDispatchPortSharing:skl */ 10751487f786SFrançois Tigeot if (IS_SKL_REVID(dev_priv, 0, SKL_REVID_F0)) 1076a05eeebfSFrançois Tigeot WA_SET_BIT_MASKED( 1077a05eeebfSFrançois Tigeot GEN7_HALF_SLICE_CHICKEN1, 1078a05eeebfSFrançois Tigeot GEN7_SBE_SS_CACHE_DISPATCH_PORT_SHARING_DISABLE); 1079a05eeebfSFrançois Tigeot 10808621f407SFrançois Tigeot /* WaDisableGafsUnitClkGating:skl */ 10818621f407SFrançois Tigeot WA_SET_BIT(GEN7_UCGCTL4, GEN8_EU_GAUNIT_CLOCK_GATE_DISABLE); 10828621f407SFrançois Tigeot 1083bf017597SFrançois Tigeot /* WaInPlaceDecompressionHang:skl */ 1084bf017597SFrançois Tigeot if (IS_SKL_REVID(dev_priv, SKL_REVID_H0, REVID_FOREVER)) 1085bf017597SFrançois Tigeot WA_SET_BIT(GEN9_GAMT_ECO_REG_RW_IA, 1086bf017597SFrançois Tigeot GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS); 1087bf017597SFrançois Tigeot 1088c0e85e96SFrançois Tigeot /* WaDisableLSQCROPERFforOCL:skl */ 10898621f407SFrançois Tigeot ret = wa_ring_whitelist_reg(engine, GEN8_L3SQCREG4); 1090c0e85e96SFrançois Tigeot if (ret) 1091c0e85e96SFrançois Tigeot return ret; 1092c0e85e96SFrançois Tigeot 10938621f407SFrançois Tigeot return skl_tune_iz_hashing(engine); 1094477eb7f9SFrançois Tigeot } 1095477eb7f9SFrançois Tigeot 10968621f407SFrançois Tigeot static int bxt_init_workarounds(struct intel_engine_cs *engine) 109719c468b4SFrançois Tigeot { 10981487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 1099352ff8bdSFrançois Tigeot int ret; 110019c468b4SFrançois Tigeot 11018621f407SFrançois Tigeot ret = gen9_init_workarounds(engine); 1102352ff8bdSFrançois Tigeot if (ret) 1103352ff8bdSFrançois Tigeot return ret; 1104352ff8bdSFrançois Tigeot 1105352ff8bdSFrançois Tigeot /* WaStoreMultiplePTEenable:bxt */ 1106352ff8bdSFrançois Tigeot /* This is a requirement according to Hardware specification */ 11071487f786SFrançois Tigeot if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1)) 1108352ff8bdSFrançois Tigeot I915_WRITE(TILECTL, I915_READ(TILECTL) | TILECTL_TLBPF); 1109352ff8bdSFrançois Tigeot 1110352ff8bdSFrançois Tigeot /* WaSetClckGatingDisableMedia:bxt */ 11111487f786SFrançois Tigeot if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1)) { 1112352ff8bdSFrançois Tigeot I915_WRITE(GEN7_MISCCPCTL, (I915_READ(GEN7_MISCCPCTL) & 1113352ff8bdSFrançois Tigeot ~GEN8_DOP_CLOCK_GATE_MEDIA_ENABLE)); 1114352ff8bdSFrançois Tigeot } 111519c468b4SFrançois Tigeot 111619c468b4SFrançois Tigeot /* WaDisableThreadStallDopClockGating:bxt */ 111719c468b4SFrançois Tigeot WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN, 111819c468b4SFrançois Tigeot STALL_DOP_GATING_DISABLE); 111919c468b4SFrançois Tigeot 11201487f786SFrançois Tigeot /* WaDisablePooledEuLoadBalancingFix:bxt */ 11211487f786SFrançois Tigeot if (IS_BXT_REVID(dev_priv, BXT_REVID_B0, REVID_FOREVER)) { 11221487f786SFrançois Tigeot WA_SET_BIT_MASKED(FF_SLICE_CS_CHICKEN2, 11231487f786SFrançois Tigeot GEN9_POOLED_EU_LOAD_BALANCING_FIX_DISABLE); 11241487f786SFrançois Tigeot } 11251487f786SFrançois Tigeot 112619c468b4SFrançois Tigeot /* WaDisableSbeCacheDispatchPortSharing:bxt */ 11271487f786SFrançois Tigeot if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_B0)) { 112819c468b4SFrançois Tigeot WA_SET_BIT_MASKED( 112919c468b4SFrançois Tigeot GEN7_HALF_SLICE_CHICKEN1, 113019c468b4SFrançois Tigeot GEN7_SBE_SS_CACHE_DISPATCH_PORT_SHARING_DISABLE); 113119c468b4SFrançois Tigeot } 113219c468b4SFrançois Tigeot 1133c0e85e96SFrançois Tigeot /* WaDisableObjectLevelPreemptionForTrifanOrPolygon:bxt */ 1134c0e85e96SFrançois Tigeot /* WaDisableObjectLevelPreemptionForInstancedDraw:bxt */ 1135c0e85e96SFrançois Tigeot /* WaDisableObjectLevelPreemtionForInstanceId:bxt */ 1136c0e85e96SFrançois Tigeot /* WaDisableLSQCROPERFforOCL:bxt */ 11371487f786SFrançois Tigeot if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1)) { 11388621f407SFrançois Tigeot ret = wa_ring_whitelist_reg(engine, GEN9_CS_DEBUG_MODE1); 1139c0e85e96SFrançois Tigeot if (ret) 1140c0e85e96SFrançois Tigeot return ret; 1141c0e85e96SFrançois Tigeot 11428621f407SFrançois Tigeot ret = wa_ring_whitelist_reg(engine, GEN8_L3SQCREG4); 1143c0e85e96SFrançois Tigeot if (ret) 1144c0e85e96SFrançois Tigeot return ret; 1145c0e85e96SFrançois Tigeot } 1146c0e85e96SFrançois Tigeot 11471487f786SFrançois Tigeot /* WaProgramL3SqcReg1DefaultForPerf:bxt */ 11481487f786SFrançois Tigeot if (IS_BXT_REVID(dev_priv, BXT_REVID_B0, REVID_FOREVER)) 11491487f786SFrançois Tigeot I915_WRITE(GEN8_L3SQCREG1, L3_GENERAL_PRIO_CREDITS(62) | 11501487f786SFrançois Tigeot L3_HIGH_PRIO_CREDITS(2)); 11511487f786SFrançois Tigeot 1152bf017597SFrançois Tigeot /* WaToEnableHwFixForPushConstHWBug:bxt */ 1153bf017597SFrançois Tigeot if (IS_BXT_REVID(dev_priv, BXT_REVID_C0, REVID_FOREVER)) 11548621f407SFrançois Tigeot WA_SET_BIT_MASKED(COMMON_SLICE_CHICKEN2, 11558621f407SFrançois Tigeot GEN8_SBE_DISABLE_REPLAY_BUF_OPTIMIZATION); 11568621f407SFrançois Tigeot 1157bf017597SFrançois Tigeot /* WaInPlaceDecompressionHang:bxt */ 1158bf017597SFrançois Tigeot if (IS_BXT_REVID(dev_priv, BXT_REVID_C0, REVID_FOREVER)) 1159bf017597SFrançois Tigeot WA_SET_BIT(GEN9_GAMT_ECO_REG_RW_IA, 1160bf017597SFrançois Tigeot GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS); 1161bf017597SFrançois Tigeot 116219c468b4SFrançois Tigeot return 0; 116319c468b4SFrançois Tigeot } 116419c468b4SFrançois Tigeot 11658621f407SFrançois Tigeot static int kbl_init_workarounds(struct intel_engine_cs *engine) 11662c9916cdSFrançois Tigeot { 11671487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 11688621f407SFrançois Tigeot int ret; 11698621f407SFrançois Tigeot 11708621f407SFrançois Tigeot ret = gen9_init_workarounds(engine); 11718621f407SFrançois Tigeot if (ret) 11728621f407SFrançois Tigeot return ret; 11738621f407SFrançois Tigeot 11748621f407SFrançois Tigeot /* WaEnableGapsTsvCreditFix:kbl */ 11758621f407SFrançois Tigeot I915_WRITE(GEN8_GARBCNTL, (I915_READ(GEN8_GARBCNTL) | 11768621f407SFrançois Tigeot GEN9_GAPS_TSV_CREDIT_DISABLE)); 11778621f407SFrançois Tigeot 11788621f407SFrançois Tigeot /* WaDisableDynamicCreditSharing:kbl */ 11798621f407SFrançois Tigeot if (IS_KBL_REVID(dev_priv, 0, KBL_REVID_B0)) 11808621f407SFrançois Tigeot WA_SET_BIT(GAMT_CHKN_BIT_REG, 11818621f407SFrançois Tigeot GAMT_CHKN_DISABLE_DYNAMIC_CREDIT_SHARING); 11828621f407SFrançois Tigeot 11838621f407SFrançois Tigeot /* WaDisableFenceDestinationToSLM:kbl (pre-prod) */ 11848621f407SFrançois Tigeot if (IS_KBL_REVID(dev_priv, KBL_REVID_A0, KBL_REVID_A0)) 11858621f407SFrançois Tigeot WA_SET_BIT_MASKED(HDC_CHICKEN0, 11868621f407SFrançois Tigeot HDC_FENCE_DEST_SLM_DISABLE); 11878621f407SFrançois Tigeot 11888621f407SFrançois Tigeot /* GEN8_L3SQCREG4 has a dependency with WA batch so any new changes 11898621f407SFrançois Tigeot * involving this register should also be added to WA batch as required. 11908621f407SFrançois Tigeot */ 11918621f407SFrançois Tigeot if (IS_KBL_REVID(dev_priv, 0, KBL_REVID_E0)) 11928621f407SFrançois Tigeot /* WaDisableLSQCROPERFforOCL:kbl */ 11938621f407SFrançois Tigeot I915_WRITE(GEN8_L3SQCREG4, I915_READ(GEN8_L3SQCREG4) | 11948621f407SFrançois Tigeot GEN8_LQSC_RO_PERF_DIS); 11958621f407SFrançois Tigeot 1196bf017597SFrançois Tigeot /* WaToEnableHwFixForPushConstHWBug:kbl */ 1197bf017597SFrançois Tigeot if (IS_KBL_REVID(dev_priv, KBL_REVID_C0, REVID_FOREVER)) 11988621f407SFrançois Tigeot WA_SET_BIT_MASKED(COMMON_SLICE_CHICKEN2, 11998621f407SFrançois Tigeot GEN8_SBE_DISABLE_REPLAY_BUF_OPTIMIZATION); 12008621f407SFrançois Tigeot 12018621f407SFrançois Tigeot /* WaDisableGafsUnitClkGating:kbl */ 12028621f407SFrançois Tigeot WA_SET_BIT(GEN7_UCGCTL4, GEN8_EU_GAUNIT_CLOCK_GATE_DISABLE); 12038621f407SFrançois Tigeot 12048621f407SFrançois Tigeot /* WaDisableSbeCacheDispatchPortSharing:kbl */ 12058621f407SFrançois Tigeot WA_SET_BIT_MASKED( 12068621f407SFrançois Tigeot GEN7_HALF_SLICE_CHICKEN1, 12078621f407SFrançois Tigeot GEN7_SBE_SS_CACHE_DISPATCH_PORT_SHARING_DISABLE); 12088621f407SFrançois Tigeot 1209bf017597SFrançois Tigeot /* WaInPlaceDecompressionHang:kbl */ 1210bf017597SFrançois Tigeot WA_SET_BIT(GEN9_GAMT_ECO_REG_RW_IA, 1211bf017597SFrançois Tigeot GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS); 1212bf017597SFrançois Tigeot 12138621f407SFrançois Tigeot /* WaDisableLSQCROPERFforOCL:kbl */ 12148621f407SFrançois Tigeot ret = wa_ring_whitelist_reg(engine, GEN8_L3SQCREG4); 12158621f407SFrançois Tigeot if (ret) 12168621f407SFrançois Tigeot return ret; 12178621f407SFrançois Tigeot 12188621f407SFrançois Tigeot return 0; 12198621f407SFrançois Tigeot } 12208621f407SFrançois Tigeot 12218621f407SFrançois Tigeot int init_workarounds_ring(struct intel_engine_cs *engine) 12228621f407SFrançois Tigeot { 12231487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 12242c9916cdSFrançois Tigeot 12258621f407SFrançois Tigeot WARN_ON(engine->id != RCS); 12262c9916cdSFrançois Tigeot 12272c9916cdSFrançois Tigeot dev_priv->workarounds.count = 0; 1228c0e85e96SFrançois Tigeot dev_priv->workarounds.hw_whitelist_count[RCS] = 0; 12292c9916cdSFrançois Tigeot 12301487f786SFrançois Tigeot if (IS_BROADWELL(dev_priv)) 12318621f407SFrançois Tigeot return bdw_init_workarounds(engine); 12322c9916cdSFrançois Tigeot 12331487f786SFrançois Tigeot if (IS_CHERRYVIEW(dev_priv)) 12348621f407SFrançois Tigeot return chv_init_workarounds(engine); 12351b13d190SFrançois Tigeot 12361487f786SFrançois Tigeot if (IS_SKYLAKE(dev_priv)) 12378621f407SFrançois Tigeot return skl_init_workarounds(engine); 123819c468b4SFrançois Tigeot 12391487f786SFrançois Tigeot if (IS_BROXTON(dev_priv)) 12408621f407SFrançois Tigeot return bxt_init_workarounds(engine); 12418621f407SFrançois Tigeot 12428621f407SFrançois Tigeot if (IS_KABYLAKE(dev_priv)) 12438621f407SFrançois Tigeot return kbl_init_workarounds(engine); 1244477eb7f9SFrançois Tigeot 12451b13d190SFrançois Tigeot return 0; 12461b13d190SFrançois Tigeot } 12471b13d190SFrançois Tigeot 12488621f407SFrançois Tigeot static int init_render_ring(struct intel_engine_cs *engine) 1249e3adcf8fSFrançois Tigeot { 12501487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 12518621f407SFrançois Tigeot int ret = init_ring_common(engine); 125224edb884SFrançois Tigeot if (ret) 125324edb884SFrançois Tigeot return ret; 1254e3adcf8fSFrançois Tigeot 1255ba55f2f5SFrançois Tigeot /* WaTimedSingleVertexDispatch:cl,bw,ctg,elk,ilk,snb */ 12561487f786SFrançois Tigeot if (IS_GEN(dev_priv, 4, 6)) 1257f4e1c372SFrançois Tigeot I915_WRITE(MI_MODE, _MASKED_BIT_ENABLE(VS_TIMER_DISPATCH)); 1258f4e1c372SFrançois Tigeot 1259f4e1c372SFrançois Tigeot /* We need to disable the AsyncFlip performance optimisations in order 1260f4e1c372SFrançois Tigeot * to use MI_WAIT_FOR_EVENT within the CS. It should already be 1261f4e1c372SFrançois Tigeot * programmed to '1' on all products. 12625d0b1887SFrançois Tigeot * 1263a05eeebfSFrançois Tigeot * WaDisableAsyncFlipPerfMode:snb,ivb,hsw,vlv 1264f4e1c372SFrançois Tigeot */ 12651487f786SFrançois Tigeot if (IS_GEN(dev_priv, 6, 7)) 1266f4e1c372SFrançois Tigeot I915_WRITE(MI_MODE, _MASKED_BIT_ENABLE(ASYNC_FLIP_PERF_DISABLE)); 1267f4e1c372SFrançois Tigeot 1268f4e1c372SFrançois Tigeot /* Required for the hardware to program scanline values for waiting */ 1269ba55f2f5SFrançois Tigeot /* WaEnableFlushTlbInvalidationMode:snb */ 12701487f786SFrançois Tigeot if (IS_GEN6(dev_priv)) 1271f4e1c372SFrançois Tigeot I915_WRITE(GFX_MODE, 1272ba55f2f5SFrançois Tigeot _MASKED_BIT_ENABLE(GFX_TLB_INVALIDATE_EXPLICIT)); 1273f4e1c372SFrançois Tigeot 1274ba55f2f5SFrançois Tigeot /* WaBCSVCSTlbInvalidationMode:ivb,vlv,hsw */ 12751487f786SFrançois Tigeot if (IS_GEN7(dev_priv)) 1276e3adcf8fSFrançois Tigeot I915_WRITE(GFX_MODE_GEN7, 1277ba55f2f5SFrançois Tigeot _MASKED_BIT_ENABLE(GFX_TLB_INVALIDATE_EXPLICIT) | 1278f4e1c372SFrançois Tigeot _MASKED_BIT_ENABLE(GFX_REPLAY_MODE)); 1279e3adcf8fSFrançois Tigeot 12801487f786SFrançois Tigeot if (IS_GEN6(dev_priv)) { 1281e3adcf8fSFrançois Tigeot /* From the Sandybridge PRM, volume 1 part 3, page 24: 1282e3adcf8fSFrançois Tigeot * "If this bit is set, STCunit will have LRA as replacement 1283e3adcf8fSFrançois Tigeot * policy. [...] This bit must be reset. LRA replacement 1284e3adcf8fSFrançois Tigeot * policy is not supported." 1285e3adcf8fSFrançois Tigeot */ 1286e3adcf8fSFrançois Tigeot I915_WRITE(CACHE_MODE_0, 1287f4e1c372SFrançois Tigeot _MASKED_BIT_DISABLE(CM0_STC_EVICT_DISABLE_LRA_SNB)); 1288e3adcf8fSFrançois Tigeot } 1289e3adcf8fSFrançois Tigeot 12901487f786SFrançois Tigeot if (IS_GEN(dev_priv, 6, 7)) 1291f4e1c372SFrançois Tigeot I915_WRITE(INSTPM, _MASKED_BIT_ENABLE(INSTPM_FORCE_ORDERING)); 1292f4e1c372SFrançois Tigeot 1293303bf270SFrançois Tigeot if (INTEL_INFO(dev_priv)->gen >= 6) 1294303bf270SFrançois Tigeot I915_WRITE_IMR(engine, ~engine->irq_keep_mask); 1295e3adcf8fSFrançois Tigeot 12968621f407SFrançois Tigeot return init_workarounds_ring(engine); 1297e3adcf8fSFrançois Tigeot } 1298e3adcf8fSFrançois Tigeot 12998621f407SFrançois Tigeot static void render_ring_cleanup(struct intel_engine_cs *engine) 1300e3adcf8fSFrançois Tigeot { 13011487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 130224edb884SFrançois Tigeot 130324edb884SFrançois Tigeot if (dev_priv->semaphore_obj) { 130424edb884SFrançois Tigeot i915_gem_object_ggtt_unpin(dev_priv->semaphore_obj); 130587df8fc6SFrançois Tigeot i915_gem_object_put(dev_priv->semaphore_obj); 130624edb884SFrançois Tigeot dev_priv->semaphore_obj = NULL; 130724edb884SFrançois Tigeot } 1308b5c29a34SFrançois Tigeot 13098621f407SFrançois Tigeot intel_fini_pipe_control(engine); 1310e3adcf8fSFrançois Tigeot } 1311e3adcf8fSFrançois Tigeot 1312*71f41f3eSFrançois Tigeot static int gen8_rcs_signal(struct drm_i915_gem_request *req) 131324edb884SFrançois Tigeot { 1314*71f41f3eSFrançois Tigeot struct intel_ring *ring = req->ring; 1315*71f41f3eSFrançois Tigeot struct drm_i915_private *dev_priv = req->i915; 131624edb884SFrançois Tigeot struct intel_engine_cs *waiter; 13178621f407SFrançois Tigeot enum intel_engine_id id; 13188621f407SFrançois Tigeot int ret, num_rings; 131924edb884SFrançois Tigeot 13201487f786SFrançois Tigeot num_rings = hweight32(INTEL_INFO(dev_priv)->ring_mask); 1321*71f41f3eSFrançois Tigeot ret = intel_ring_begin(req, (num_rings-1) * 8); 132224edb884SFrançois Tigeot if (ret) 132324edb884SFrançois Tigeot return ret; 132424edb884SFrançois Tigeot 13258621f407SFrançois Tigeot for_each_engine_id(waiter, dev_priv, id) { 1326*71f41f3eSFrançois Tigeot u64 gtt_offset = req->engine->semaphore.signal_ggtt[id]; 132724edb884SFrançois Tigeot if (gtt_offset == MI_SEMAPHORE_SYNC_INVALID) 132824edb884SFrançois Tigeot continue; 132924edb884SFrançois Tigeot 1330*71f41f3eSFrançois Tigeot intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(6)); 1331*71f41f3eSFrançois Tigeot intel_ring_emit(ring, 1332*71f41f3eSFrançois Tigeot PIPE_CONTROL_GLOBAL_GTT_IVB | 133324edb884SFrançois Tigeot PIPE_CONTROL_QW_WRITE | 13341487f786SFrançois Tigeot PIPE_CONTROL_CS_STALL); 1335*71f41f3eSFrançois Tigeot intel_ring_emit(ring, lower_32_bits(gtt_offset)); 1336*71f41f3eSFrançois Tigeot intel_ring_emit(ring, upper_32_bits(gtt_offset)); 1337*71f41f3eSFrançois Tigeot intel_ring_emit(ring, req->fence.seqno); 1338*71f41f3eSFrançois Tigeot intel_ring_emit(ring, 0); 1339*71f41f3eSFrançois Tigeot intel_ring_emit(ring, 1340*71f41f3eSFrançois Tigeot MI_SEMAPHORE_SIGNAL | 13418621f407SFrançois Tigeot MI_SEMAPHORE_TARGET(waiter->hw_id)); 1342*71f41f3eSFrançois Tigeot intel_ring_emit(ring, 0); 134324edb884SFrançois Tigeot } 1344*71f41f3eSFrançois Tigeot intel_ring_advance(ring); 134524edb884SFrançois Tigeot 134624edb884SFrançois Tigeot return 0; 134724edb884SFrançois Tigeot } 134824edb884SFrançois Tigeot 1349*71f41f3eSFrançois Tigeot static int gen8_xcs_signal(struct drm_i915_gem_request *req) 135024edb884SFrançois Tigeot { 1351*71f41f3eSFrançois Tigeot struct intel_ring *ring = req->ring; 1352*71f41f3eSFrançois Tigeot struct drm_i915_private *dev_priv = req->i915; 135324edb884SFrançois Tigeot struct intel_engine_cs *waiter; 13548621f407SFrançois Tigeot enum intel_engine_id id; 13558621f407SFrançois Tigeot int ret, num_rings; 135624edb884SFrançois Tigeot 13571487f786SFrançois Tigeot num_rings = hweight32(INTEL_INFO(dev_priv)->ring_mask); 1358*71f41f3eSFrançois Tigeot ret = intel_ring_begin(req, (num_rings-1) * 6); 135924edb884SFrançois Tigeot if (ret) 136024edb884SFrançois Tigeot return ret; 136124edb884SFrançois Tigeot 13628621f407SFrançois Tigeot for_each_engine_id(waiter, dev_priv, id) { 1363*71f41f3eSFrançois Tigeot u64 gtt_offset = req->engine->semaphore.signal_ggtt[id]; 136424edb884SFrançois Tigeot if (gtt_offset == MI_SEMAPHORE_SYNC_INVALID) 136524edb884SFrançois Tigeot continue; 136624edb884SFrançois Tigeot 1367*71f41f3eSFrançois Tigeot intel_ring_emit(ring, 1368*71f41f3eSFrançois Tigeot (MI_FLUSH_DW + 1) | MI_FLUSH_DW_OP_STOREDW); 1369*71f41f3eSFrançois Tigeot intel_ring_emit(ring, 1370*71f41f3eSFrançois Tigeot lower_32_bits(gtt_offset) | 137124edb884SFrançois Tigeot MI_FLUSH_DW_USE_GTT); 1372*71f41f3eSFrançois Tigeot intel_ring_emit(ring, upper_32_bits(gtt_offset)); 1373*71f41f3eSFrançois Tigeot intel_ring_emit(ring, req->fence.seqno); 1374*71f41f3eSFrançois Tigeot intel_ring_emit(ring, 1375*71f41f3eSFrançois Tigeot MI_SEMAPHORE_SIGNAL | 13768621f407SFrançois Tigeot MI_SEMAPHORE_TARGET(waiter->hw_id)); 1377*71f41f3eSFrançois Tigeot intel_ring_emit(ring, 0); 137824edb884SFrançois Tigeot } 1379*71f41f3eSFrançois Tigeot intel_ring_advance(ring); 138024edb884SFrançois Tigeot 138124edb884SFrançois Tigeot return 0; 138224edb884SFrançois Tigeot } 138324edb884SFrançois Tigeot 1384*71f41f3eSFrançois Tigeot static int gen6_signal(struct drm_i915_gem_request *req) 1385e3adcf8fSFrançois Tigeot { 1386*71f41f3eSFrançois Tigeot struct intel_ring *ring = req->ring; 1387*71f41f3eSFrançois Tigeot struct drm_i915_private *dev_priv = req->i915; 1388ba55f2f5SFrançois Tigeot struct intel_engine_cs *useless; 13898621f407SFrançois Tigeot enum intel_engine_id id; 13908621f407SFrançois Tigeot int ret, num_rings; 1391ba55f2f5SFrançois Tigeot 13921487f786SFrançois Tigeot num_rings = hweight32(INTEL_INFO(dev_priv)->ring_mask); 1393*71f41f3eSFrançois Tigeot ret = intel_ring_begin(req, round_up((num_rings-1) * 3, 2)); 1394ba55f2f5SFrançois Tigeot if (ret) 1395ba55f2f5SFrançois Tigeot return ret; 1396ba55f2f5SFrançois Tigeot 13978621f407SFrançois Tigeot for_each_engine_id(useless, dev_priv, id) { 1398*71f41f3eSFrançois Tigeot i915_reg_t mbox_reg = req->engine->semaphore.mbox.signal[id]; 1399aee94f86SFrançois Tigeot 1400aee94f86SFrançois Tigeot if (i915_mmio_reg_valid(mbox_reg)) { 1401*71f41f3eSFrançois Tigeot intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1)); 1402*71f41f3eSFrançois Tigeot intel_ring_emit_reg(ring, mbox_reg); 1403*71f41f3eSFrançois Tigeot intel_ring_emit(ring, req->fence.seqno); 1404ba55f2f5SFrançois Tigeot } 1405ba55f2f5SFrançois Tigeot } 1406ba55f2f5SFrançois Tigeot 140724edb884SFrançois Tigeot /* If num_dwords was rounded, make sure the tail pointer is correct */ 140824edb884SFrançois Tigeot if (num_rings % 2 == 0) 1409*71f41f3eSFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 1410*71f41f3eSFrançois Tigeot intel_ring_advance(ring); 1411*71f41f3eSFrançois Tigeot 1412*71f41f3eSFrançois Tigeot return 0; 1413*71f41f3eSFrançois Tigeot } 1414*71f41f3eSFrançois Tigeot 1415*71f41f3eSFrançois Tigeot static void i9xx_submit_request(struct drm_i915_gem_request *request) 1416*71f41f3eSFrançois Tigeot { 1417*71f41f3eSFrançois Tigeot struct drm_i915_private *dev_priv = request->i915; 1418*71f41f3eSFrançois Tigeot 1419*71f41f3eSFrançois Tigeot I915_WRITE_TAIL(request->engine, 1420*71f41f3eSFrançois Tigeot intel_ring_offset(request->ring, request->tail)); 1421*71f41f3eSFrançois Tigeot } 1422*71f41f3eSFrançois Tigeot 1423*71f41f3eSFrançois Tigeot static int i9xx_emit_request(struct drm_i915_gem_request *req) 1424*71f41f3eSFrançois Tigeot { 1425*71f41f3eSFrançois Tigeot struct intel_ring *ring = req->ring; 1426*71f41f3eSFrançois Tigeot int ret; 1427*71f41f3eSFrançois Tigeot 1428*71f41f3eSFrançois Tigeot ret = intel_ring_begin(req, 4); 1429*71f41f3eSFrançois Tigeot if (ret) 1430*71f41f3eSFrançois Tigeot return ret; 1431*71f41f3eSFrançois Tigeot 1432*71f41f3eSFrançois Tigeot intel_ring_emit(ring, MI_STORE_DWORD_INDEX); 1433*71f41f3eSFrançois Tigeot intel_ring_emit(ring, I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT); 1434*71f41f3eSFrançois Tigeot intel_ring_emit(ring, req->fence.seqno); 1435*71f41f3eSFrançois Tigeot intel_ring_emit(ring, MI_USER_INTERRUPT); 1436*71f41f3eSFrançois Tigeot intel_ring_advance(ring); 1437*71f41f3eSFrançois Tigeot 1438*71f41f3eSFrançois Tigeot req->tail = ring->tail; 143924edb884SFrançois Tigeot 1440ba55f2f5SFrançois Tigeot return 0; 1441e3adcf8fSFrançois Tigeot } 1442e3adcf8fSFrançois Tigeot 1443e3adcf8fSFrançois Tigeot /** 1444*71f41f3eSFrançois Tigeot * gen6_sema_emit_request - Update the semaphore mailbox registers 1445e3adcf8fSFrançois Tigeot * 1446a05eeebfSFrançois Tigeot * @request - request to write to the ring 1447e3adcf8fSFrançois Tigeot * 1448e3adcf8fSFrançois Tigeot * Update the mailbox registers in the *other* rings with the current seqno. 1449e3adcf8fSFrançois Tigeot * This acts like a signal in the canonical semaphore. 1450e3adcf8fSFrançois Tigeot */ 1451*71f41f3eSFrançois Tigeot static int gen6_sema_emit_request(struct drm_i915_gem_request *req) 1452e3adcf8fSFrançois Tigeot { 1453ba55f2f5SFrançois Tigeot int ret; 1454e3adcf8fSFrançois Tigeot 1455*71f41f3eSFrançois Tigeot ret = req->engine->semaphore.signal(req); 14569edbd4a0SFrançois Tigeot if (ret) 14579edbd4a0SFrançois Tigeot return ret; 14589edbd4a0SFrançois Tigeot 1459*71f41f3eSFrançois Tigeot return i9xx_emit_request(req); 1460e3adcf8fSFrançois Tigeot } 1461e3adcf8fSFrançois Tigeot 1462*71f41f3eSFrançois Tigeot static int gen8_render_emit_request(struct drm_i915_gem_request *req) 14631487f786SFrançois Tigeot { 14641487f786SFrançois Tigeot struct intel_engine_cs *engine = req->engine; 1465*71f41f3eSFrançois Tigeot struct intel_ring *ring = req->ring; 14661487f786SFrançois Tigeot int ret; 14671487f786SFrançois Tigeot 1468*71f41f3eSFrançois Tigeot if (engine->semaphore.signal) { 1469*71f41f3eSFrançois Tigeot ret = engine->semaphore.signal(req); 1470*71f41f3eSFrançois Tigeot if (ret) 1471*71f41f3eSFrançois Tigeot return ret; 1472*71f41f3eSFrançois Tigeot } 1473*71f41f3eSFrançois Tigeot 14741487f786SFrançois Tigeot ret = intel_ring_begin(req, 8); 14751487f786SFrançois Tigeot if (ret) 14761487f786SFrançois Tigeot return ret; 14771487f786SFrançois Tigeot 1478*71f41f3eSFrançois Tigeot intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(6)); 1479*71f41f3eSFrançois Tigeot intel_ring_emit(ring, (PIPE_CONTROL_GLOBAL_GTT_IVB | 14801487f786SFrançois Tigeot PIPE_CONTROL_CS_STALL | 14811487f786SFrançois Tigeot PIPE_CONTROL_QW_WRITE)); 1482*71f41f3eSFrançois Tigeot intel_ring_emit(ring, intel_hws_seqno_address(engine)); 1483*71f41f3eSFrançois Tigeot intel_ring_emit(ring, 0); 1484*71f41f3eSFrançois Tigeot intel_ring_emit(ring, i915_gem_request_get_seqno(req)); 14851487f786SFrançois Tigeot /* We're thrashing one dword of HWS. */ 1486*71f41f3eSFrançois Tigeot intel_ring_emit(ring, 0); 1487*71f41f3eSFrançois Tigeot intel_ring_emit(ring, MI_USER_INTERRUPT); 1488*71f41f3eSFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 1489*71f41f3eSFrançois Tigeot intel_ring_advance(ring); 1490*71f41f3eSFrançois Tigeot 1491*71f41f3eSFrançois Tigeot req->tail = ring->tail; 14921487f786SFrançois Tigeot 14931487f786SFrançois Tigeot return 0; 14941487f786SFrançois Tigeot } 14951487f786SFrançois Tigeot 1496e3adcf8fSFrançois Tigeot /** 1497e3adcf8fSFrançois Tigeot * intel_ring_sync - sync the waiter to the signaller on seqno 1498e3adcf8fSFrançois Tigeot * 1499e3adcf8fSFrançois Tigeot * @waiter - ring that is waiting 1500e3adcf8fSFrançois Tigeot * @signaller - ring which has, or will signal 1501e3adcf8fSFrançois Tigeot * @seqno - seqno which the waiter will block on 1502e3adcf8fSFrançois Tigeot */ 150324edb884SFrançois Tigeot 150424edb884SFrançois Tigeot static int 1505*71f41f3eSFrançois Tigeot gen8_ring_sync_to(struct drm_i915_gem_request *req, 1506*71f41f3eSFrançois Tigeot struct drm_i915_gem_request *signal) 150724edb884SFrançois Tigeot { 1508*71f41f3eSFrançois Tigeot struct intel_ring *ring = req->ring; 1509*71f41f3eSFrançois Tigeot struct drm_i915_private *dev_priv = req->i915; 1510*71f41f3eSFrançois Tigeot u64 offset = GEN8_WAIT_OFFSET(req->engine, signal->engine->id); 15111487f786SFrançois Tigeot struct i915_hw_ppgtt *ppgtt; 151224edb884SFrançois Tigeot int ret; 151324edb884SFrançois Tigeot 1514*71f41f3eSFrançois Tigeot ret = intel_ring_begin(req, 4); 151524edb884SFrançois Tigeot if (ret) 151624edb884SFrançois Tigeot return ret; 151724edb884SFrançois Tigeot 1518*71f41f3eSFrançois Tigeot intel_ring_emit(ring, 1519*71f41f3eSFrançois Tigeot MI_SEMAPHORE_WAIT | 152024edb884SFrançois Tigeot MI_SEMAPHORE_GLOBAL_GTT | 152124edb884SFrançois Tigeot MI_SEMAPHORE_SAD_GTE_SDD); 1522*71f41f3eSFrançois Tigeot intel_ring_emit(ring, signal->fence.seqno); 1523*71f41f3eSFrançois Tigeot intel_ring_emit(ring, lower_32_bits(offset)); 1524*71f41f3eSFrançois Tigeot intel_ring_emit(ring, upper_32_bits(offset)); 1525*71f41f3eSFrançois Tigeot intel_ring_advance(ring); 15261487f786SFrançois Tigeot 15271487f786SFrançois Tigeot /* When the !RCS engines idle waiting upon a semaphore, they lose their 15281487f786SFrançois Tigeot * pagetables and we must reload them before executing the batch. 15291487f786SFrançois Tigeot * We do this on the i915_switch_context() following the wait and 15301487f786SFrançois Tigeot * before the dispatch. 15311487f786SFrançois Tigeot */ 1532*71f41f3eSFrançois Tigeot ppgtt = req->ctx->ppgtt; 1533*71f41f3eSFrançois Tigeot if (ppgtt && req->engine->id != RCS) 1534*71f41f3eSFrançois Tigeot ppgtt->pd_dirty_rings |= intel_engine_flag(req->engine); 153524edb884SFrançois Tigeot return 0; 153624edb884SFrançois Tigeot } 153724edb884SFrançois Tigeot 1538e3adcf8fSFrançois Tigeot static int 1539*71f41f3eSFrançois Tigeot gen6_ring_sync_to(struct drm_i915_gem_request *req, 1540*71f41f3eSFrançois Tigeot struct drm_i915_gem_request *signal) 1541e3adcf8fSFrançois Tigeot { 1542*71f41f3eSFrançois Tigeot struct intel_ring *ring = req->ring; 1543e3adcf8fSFrançois Tigeot u32 dw1 = MI_SEMAPHORE_MBOX | 1544e3adcf8fSFrançois Tigeot MI_SEMAPHORE_COMPARE | 1545e3adcf8fSFrançois Tigeot MI_SEMAPHORE_REGISTER; 1546*71f41f3eSFrançois Tigeot u32 wait_mbox = signal->engine->semaphore.mbox.wait[req->engine->id]; 1547ba55f2f5SFrançois Tigeot int ret; 1548e3adcf8fSFrançois Tigeot 1549*71f41f3eSFrançois Tigeot WARN_ON(wait_mbox == MI_SEMAPHORE_SYNC_INVALID); 1550*71f41f3eSFrançois Tigeot 1551*71f41f3eSFrançois Tigeot ret = intel_ring_begin(req, 4); 1552*71f41f3eSFrançois Tigeot if (ret) 1553*71f41f3eSFrançois Tigeot return ret; 1554*71f41f3eSFrançois Tigeot 1555*71f41f3eSFrançois Tigeot intel_ring_emit(ring, dw1 | wait_mbox); 1556686a02f1SFrançois Tigeot /* Throughout all of the GEM code, seqno passed implies our current 1557686a02f1SFrançois Tigeot * seqno is >= the last seqno executed. However for hardware the 1558686a02f1SFrançois Tigeot * comparison is strictly greater than. 1559686a02f1SFrançois Tigeot */ 1560*71f41f3eSFrançois Tigeot intel_ring_emit(ring, signal->fence.seqno - 1); 1561*71f41f3eSFrançois Tigeot intel_ring_emit(ring, 0); 1562*71f41f3eSFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 1563*71f41f3eSFrançois Tigeot intel_ring_advance(ring); 1564e3adcf8fSFrançois Tigeot 1565e3adcf8fSFrançois Tigeot return 0; 1566e3adcf8fSFrançois Tigeot } 1567e3adcf8fSFrançois Tigeot 1568303bf270SFrançois Tigeot static void 156987df8fc6SFrançois Tigeot gen5_seqno_barrier(struct intel_engine_cs *engine) 1570e3adcf8fSFrançois Tigeot { 1571303bf270SFrançois Tigeot /* MI_STORE are internally buffered by the GPU and not flushed 1572303bf270SFrançois Tigeot * either by MI_FLUSH or SyncFlush or any other combination of 1573303bf270SFrançois Tigeot * MI commands. 1574e3adcf8fSFrançois Tigeot * 1575303bf270SFrançois Tigeot * "Only the submission of the store operation is guaranteed. 1576303bf270SFrançois Tigeot * The write result will be complete (coherent) some time later 1577303bf270SFrançois Tigeot * (this is practically a finite period but there is no guaranteed 1578303bf270SFrançois Tigeot * latency)." 1579303bf270SFrançois Tigeot * 1580303bf270SFrançois Tigeot * Empirically, we observe that we need a delay of at least 75us to 1581303bf270SFrançois Tigeot * be sure that the seqno write is visible by the CPU. 1582e3adcf8fSFrançois Tigeot */ 1583303bf270SFrançois Tigeot usleep_range(125, 250); 1584e3adcf8fSFrançois Tigeot } 1585e3adcf8fSFrançois Tigeot 15868621f407SFrançois Tigeot static void 15878621f407SFrançois Tigeot gen6_seqno_barrier(struct intel_engine_cs *engine) 1588e3adcf8fSFrançois Tigeot { 15891487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 15908621f407SFrançois Tigeot 1591e3adcf8fSFrançois Tigeot /* Workaround to force correct ordering between irq and seqno writes on 1592e3adcf8fSFrançois Tigeot * ivb (and maybe also on snb) by reading from a CS register (like 15938621f407SFrançois Tigeot * ACTHD) before reading the status page. 15948621f407SFrançois Tigeot * 15958621f407SFrançois Tigeot * Note that this effectively stalls the read by the time it takes to 15968621f407SFrançois Tigeot * do a memory transaction, which more or less ensures that the write 15978621f407SFrançois Tigeot * from the GPU has sufficient time to invalidate the CPU cacheline. 15988621f407SFrançois Tigeot * Alternatively we could delay the interrupt from the CS ring to give 15998621f407SFrançois Tigeot * the write time to land, but that would incur a delay after every 16008621f407SFrançois Tigeot * batch i.e. much more frequent than a delay when waiting for the 16018621f407SFrançois Tigeot * interrupt (with the same net latency). 16028621f407SFrançois Tigeot * 16038621f407SFrançois Tigeot * Also note that to prevent whole machine hangs on gen7, we have to 16048621f407SFrançois Tigeot * take the spinlock to guard against concurrent cacheline access. 16058621f407SFrançois Tigeot */ 16068621f407SFrançois Tigeot spin_lock_irq(&dev_priv->uncore.lock); 16078621f407SFrançois Tigeot POSTING_READ_FW(RING_ACTHD(engine->mmio_base)); 16088621f407SFrançois Tigeot spin_unlock_irq(&dev_priv->uncore.lock); 1609e3adcf8fSFrançois Tigeot } 1610e3adcf8fSFrançois Tigeot 1611303bf270SFrançois Tigeot static void 1612303bf270SFrançois Tigeot gen5_irq_enable(struct intel_engine_cs *engine) 1613e3adcf8fSFrançois Tigeot { 1614303bf270SFrançois Tigeot gen5_enable_gt_irq(engine->i915, engine->irq_enable_mask); 1615e3adcf8fSFrançois Tigeot } 1616e3adcf8fSFrançois Tigeot 1617a2fdbec6SFrançois Tigeot static void 1618303bf270SFrançois Tigeot gen5_irq_disable(struct intel_engine_cs *engine) 1619a2fdbec6SFrançois Tigeot { 1620303bf270SFrançois Tigeot gen5_disable_gt_irq(engine->i915, engine->irq_enable_mask); 1621e3adcf8fSFrançois Tigeot } 1622e3adcf8fSFrançois Tigeot 1623a2fdbec6SFrançois Tigeot static void 1624303bf270SFrançois Tigeot i9xx_irq_enable(struct intel_engine_cs *engine) 1625e3adcf8fSFrançois Tigeot { 16261487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 1627e3adcf8fSFrançois Tigeot 16288621f407SFrançois Tigeot dev_priv->irq_mask &= ~engine->irq_enable_mask; 1629686a02f1SFrançois Tigeot I915_WRITE(IMR, dev_priv->irq_mask); 1630303bf270SFrançois Tigeot POSTING_READ_FW(RING_IMR(engine->mmio_base)); 1631686a02f1SFrançois Tigeot } 1632686a02f1SFrançois Tigeot 1633686a02f1SFrançois Tigeot static void 1634303bf270SFrançois Tigeot i9xx_irq_disable(struct intel_engine_cs *engine) 1635686a02f1SFrançois Tigeot { 16361487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 1637686a02f1SFrançois Tigeot 16388621f407SFrançois Tigeot dev_priv->irq_mask |= engine->irq_enable_mask; 1639686a02f1SFrançois Tigeot I915_WRITE(IMR, dev_priv->irq_mask); 1640686a02f1SFrançois Tigeot } 1641686a02f1SFrançois Tigeot 1642686a02f1SFrançois Tigeot static void 1643303bf270SFrançois Tigeot i8xx_irq_enable(struct intel_engine_cs *engine) 1644686a02f1SFrançois Tigeot { 16451487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 1646686a02f1SFrançois Tigeot 1647303bf270SFrançois Tigeot dev_priv->irq_mask &= ~engine->irq_enable_mask; 1648303bf270SFrançois Tigeot I915_WRITE16(IMR, dev_priv->irq_mask); 1649303bf270SFrançois Tigeot POSTING_READ16(RING_IMR(engine->mmio_base)); 1650303bf270SFrançois Tigeot } 1651303bf270SFrançois Tigeot 1652303bf270SFrançois Tigeot static void 1653303bf270SFrançois Tigeot i8xx_irq_disable(struct intel_engine_cs *engine) 1654303bf270SFrançois Tigeot { 1655303bf270SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 1656303bf270SFrançois Tigeot 16578621f407SFrançois Tigeot dev_priv->irq_mask |= engine->irq_enable_mask; 1658686a02f1SFrançois Tigeot I915_WRITE16(IMR, dev_priv->irq_mask); 1659e3adcf8fSFrançois Tigeot } 1660e3adcf8fSFrançois Tigeot 1661e3adcf8fSFrançois Tigeot static int 1662*71f41f3eSFrançois Tigeot bsd_ring_flush(struct drm_i915_gem_request *req, u32 mode) 1663e3adcf8fSFrançois Tigeot { 1664*71f41f3eSFrançois Tigeot struct intel_ring *ring = req->ring; 1665e3adcf8fSFrançois Tigeot int ret; 1666e3adcf8fSFrançois Tigeot 1667a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 2); 1668e3adcf8fSFrançois Tigeot if (ret) 1669e3adcf8fSFrançois Tigeot return ret; 1670e3adcf8fSFrançois Tigeot 1671*71f41f3eSFrançois Tigeot intel_ring_emit(ring, MI_FLUSH); 1672*71f41f3eSFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 1673*71f41f3eSFrançois Tigeot intel_ring_advance(ring); 1674e3adcf8fSFrançois Tigeot return 0; 1675e3adcf8fSFrançois Tigeot } 1676e3adcf8fSFrançois Tigeot 1677303bf270SFrançois Tigeot static void 1678303bf270SFrançois Tigeot gen6_irq_enable(struct intel_engine_cs *engine) 1679e3adcf8fSFrançois Tigeot { 16801487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 1681e3adcf8fSFrançois Tigeot 16828621f407SFrançois Tigeot I915_WRITE_IMR(engine, 16838621f407SFrançois Tigeot ~(engine->irq_enable_mask | 1684303bf270SFrançois Tigeot engine->irq_keep_mask)); 16858621f407SFrançois Tigeot gen5_enable_gt_irq(dev_priv, engine->irq_enable_mask); 1686e3adcf8fSFrançois Tigeot } 1687e3adcf8fSFrançois Tigeot 1688e3adcf8fSFrançois Tigeot static void 1689303bf270SFrançois Tigeot gen6_irq_disable(struct intel_engine_cs *engine) 1690e3adcf8fSFrançois Tigeot { 16911487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 1692e3adcf8fSFrançois Tigeot 1693303bf270SFrançois Tigeot I915_WRITE_IMR(engine, ~engine->irq_keep_mask); 16948621f407SFrançois Tigeot gen5_disable_gt_irq(dev_priv, engine->irq_enable_mask); 1695e3adcf8fSFrançois Tigeot } 1696e3adcf8fSFrançois Tigeot 1697303bf270SFrançois Tigeot static void 1698303bf270SFrançois Tigeot hsw_vebox_irq_enable(struct intel_engine_cs *engine) 16995d0b1887SFrançois Tigeot { 17001487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 17015d0b1887SFrançois Tigeot 17028621f407SFrançois Tigeot I915_WRITE_IMR(engine, ~engine->irq_enable_mask); 17038621f407SFrançois Tigeot gen6_enable_pm_irq(dev_priv, engine->irq_enable_mask); 17045d0b1887SFrançois Tigeot } 17055d0b1887SFrançois Tigeot 17065d0b1887SFrançois Tigeot static void 1707303bf270SFrançois Tigeot hsw_vebox_irq_disable(struct intel_engine_cs *engine) 17085d0b1887SFrançois Tigeot { 17091487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 17105d0b1887SFrançois Tigeot 17118621f407SFrançois Tigeot I915_WRITE_IMR(engine, ~0); 17128621f407SFrançois Tigeot gen6_disable_pm_irq(dev_priv, engine->irq_enable_mask); 17135d0b1887SFrançois Tigeot } 17149edbd4a0SFrançois Tigeot 1715303bf270SFrançois Tigeot static void 1716303bf270SFrançois Tigeot gen8_irq_enable(struct intel_engine_cs *engine) 17179edbd4a0SFrançois Tigeot { 17181487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 17199edbd4a0SFrançois Tigeot 17208621f407SFrançois Tigeot I915_WRITE_IMR(engine, 17218621f407SFrançois Tigeot ~(engine->irq_enable_mask | 1722303bf270SFrançois Tigeot engine->irq_keep_mask)); 1723303bf270SFrançois Tigeot POSTING_READ_FW(RING_IMR(engine->mmio_base)); 17249edbd4a0SFrançois Tigeot } 17259edbd4a0SFrançois Tigeot 17269edbd4a0SFrançois Tigeot static void 1727303bf270SFrançois Tigeot gen8_irq_disable(struct intel_engine_cs *engine) 17289edbd4a0SFrançois Tigeot { 17291487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 17309edbd4a0SFrançois Tigeot 1731303bf270SFrançois Tigeot I915_WRITE_IMR(engine, ~engine->irq_keep_mask); 17325d0b1887SFrançois Tigeot } 17335d0b1887SFrançois Tigeot 1734e3adcf8fSFrançois Tigeot static int 1735*71f41f3eSFrançois Tigeot i965_emit_bb_start(struct drm_i915_gem_request *req, 1736ba55f2f5SFrançois Tigeot u64 offset, u32 length, 1737*71f41f3eSFrançois Tigeot unsigned int dispatch_flags) 1738e3adcf8fSFrançois Tigeot { 1739*71f41f3eSFrançois Tigeot struct intel_ring *ring = req->ring; 1740e3adcf8fSFrançois Tigeot int ret; 1741e3adcf8fSFrançois Tigeot 1742a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 2); 1743e3adcf8fSFrançois Tigeot if (ret) 1744e3adcf8fSFrançois Tigeot return ret; 1745e3adcf8fSFrançois Tigeot 1746*71f41f3eSFrançois Tigeot intel_ring_emit(ring, 1747686a02f1SFrançois Tigeot MI_BATCH_BUFFER_START | 1748b5c29a34SFrançois Tigeot MI_BATCH_GTT | 1749477eb7f9SFrançois Tigeot (dispatch_flags & I915_DISPATCH_SECURE ? 1750477eb7f9SFrançois Tigeot 0 : MI_BATCH_NON_SECURE_I965)); 1751*71f41f3eSFrançois Tigeot intel_ring_emit(ring, offset); 1752*71f41f3eSFrançois Tigeot intel_ring_advance(ring); 1753e3adcf8fSFrançois Tigeot 1754e3adcf8fSFrançois Tigeot return 0; 1755e3adcf8fSFrançois Tigeot } 1756e3adcf8fSFrançois Tigeot 1757b5c29a34SFrançois Tigeot /* Just userspace ABI convention to limit the wa batch bo to a resonable size */ 1758b5c29a34SFrançois Tigeot #define I830_BATCH_LIMIT (256*1024) 175924edb884SFrançois Tigeot #define I830_TLB_ENTRIES (2) 176024edb884SFrançois Tigeot #define I830_WA_SIZE max(I830_TLB_ENTRIES*4096, I830_BATCH_LIMIT) 1761e3adcf8fSFrançois Tigeot static int 1762*71f41f3eSFrançois Tigeot i830_emit_bb_start(struct drm_i915_gem_request *req, 1763ba55f2f5SFrançois Tigeot u64 offset, u32 len, 1764*71f41f3eSFrançois Tigeot unsigned int dispatch_flags) 1765e3adcf8fSFrançois Tigeot { 1766*71f41f3eSFrançois Tigeot struct intel_ring *ring = req->ring; 1767*71f41f3eSFrançois Tigeot u32 cs_offset = req->engine->scratch.gtt_offset; 1768e3adcf8fSFrançois Tigeot int ret; 1769e3adcf8fSFrançois Tigeot 1770a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 6); 177124edb884SFrançois Tigeot if (ret) 177224edb884SFrançois Tigeot return ret; 177324edb884SFrançois Tigeot 177424edb884SFrançois Tigeot /* Evict the invalid PTE TLBs */ 1775*71f41f3eSFrançois Tigeot intel_ring_emit(ring, COLOR_BLT_CMD | BLT_WRITE_RGBA); 1776*71f41f3eSFrançois Tigeot intel_ring_emit(ring, BLT_DEPTH_32 | BLT_ROP_COLOR_COPY | 4096); 1777*71f41f3eSFrançois Tigeot intel_ring_emit(ring, I830_TLB_ENTRIES << 16 | 4); /* load each page */ 1778*71f41f3eSFrançois Tigeot intel_ring_emit(ring, cs_offset); 1779*71f41f3eSFrançois Tigeot intel_ring_emit(ring, 0xdeadbeef); 1780*71f41f3eSFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 1781*71f41f3eSFrançois Tigeot intel_ring_advance(ring); 178224edb884SFrançois Tigeot 1783477eb7f9SFrançois Tigeot if ((dispatch_flags & I915_DISPATCH_PINNED) == 0) { 178424edb884SFrançois Tigeot if (len > I830_BATCH_LIMIT) 178524edb884SFrançois Tigeot return -ENOSPC; 178624edb884SFrançois Tigeot 1787a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 6 + 2); 178824edb884SFrançois Tigeot if (ret) 178924edb884SFrançois Tigeot return ret; 179024edb884SFrançois Tigeot 179124edb884SFrançois Tigeot /* Blit the batch (which has now all relocs applied) to the 179224edb884SFrançois Tigeot * stable batch scratch bo area (so that the CS never 179324edb884SFrançois Tigeot * stumbles over its tlb invalidation bug) ... 179424edb884SFrançois Tigeot */ 1795*71f41f3eSFrançois Tigeot intel_ring_emit(ring, SRC_COPY_BLT_CMD | BLT_WRITE_RGBA); 1796*71f41f3eSFrançois Tigeot intel_ring_emit(ring, 17978621f407SFrançois Tigeot BLT_DEPTH_32 | BLT_ROP_SRC_COPY | 4096); 1798*71f41f3eSFrançois Tigeot intel_ring_emit(ring, DIV_ROUND_UP(len, 4096) << 16 | 4096); 1799*71f41f3eSFrançois Tigeot intel_ring_emit(ring, cs_offset); 1800*71f41f3eSFrançois Tigeot intel_ring_emit(ring, 4096); 1801*71f41f3eSFrançois Tigeot intel_ring_emit(ring, offset); 180224edb884SFrançois Tigeot 1803*71f41f3eSFrançois Tigeot intel_ring_emit(ring, MI_FLUSH); 1804*71f41f3eSFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 1805*71f41f3eSFrançois Tigeot intel_ring_advance(ring); 180624edb884SFrançois Tigeot 180724edb884SFrançois Tigeot /* ... and execute it. */ 180824edb884SFrançois Tigeot offset = cs_offset; 180924edb884SFrançois Tigeot } 181024edb884SFrançois Tigeot 1811c0e85e96SFrançois Tigeot ret = intel_ring_begin(req, 2); 1812e3adcf8fSFrançois Tigeot if (ret) 1813e3adcf8fSFrançois Tigeot return ret; 1814e3adcf8fSFrançois Tigeot 1815*71f41f3eSFrançois Tigeot intel_ring_emit(ring, MI_BATCH_BUFFER_START | MI_BATCH_GTT); 1816*71f41f3eSFrançois Tigeot intel_ring_emit(ring, offset | (dispatch_flags & I915_DISPATCH_SECURE ? 1817477eb7f9SFrançois Tigeot 0 : MI_BATCH_NON_SECURE)); 1818*71f41f3eSFrançois Tigeot intel_ring_advance(ring); 1819686a02f1SFrançois Tigeot 1820686a02f1SFrançois Tigeot return 0; 1821686a02f1SFrançois Tigeot } 1822686a02f1SFrançois Tigeot 1823686a02f1SFrançois Tigeot static int 1824*71f41f3eSFrançois Tigeot i915_emit_bb_start(struct drm_i915_gem_request *req, 1825ba55f2f5SFrançois Tigeot u64 offset, u32 len, 1826*71f41f3eSFrançois Tigeot unsigned int dispatch_flags) 1827686a02f1SFrançois Tigeot { 1828*71f41f3eSFrançois Tigeot struct intel_ring *ring = req->ring; 1829686a02f1SFrançois Tigeot int ret; 1830686a02f1SFrançois Tigeot 1831a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 2); 1832e3adcf8fSFrançois Tigeot if (ret) 1833e3adcf8fSFrançois Tigeot return ret; 1834e3adcf8fSFrançois Tigeot 1835*71f41f3eSFrançois Tigeot intel_ring_emit(ring, MI_BATCH_BUFFER_START | MI_BATCH_GTT); 1836*71f41f3eSFrançois Tigeot intel_ring_emit(ring, offset | (dispatch_flags & I915_DISPATCH_SECURE ? 1837477eb7f9SFrançois Tigeot 0 : MI_BATCH_NON_SECURE)); 1838*71f41f3eSFrançois Tigeot intel_ring_advance(ring); 1839e3adcf8fSFrançois Tigeot 1840e3adcf8fSFrançois Tigeot return 0; 1841e3adcf8fSFrançois Tigeot } 1842e3adcf8fSFrançois Tigeot 18438621f407SFrançois Tigeot static void cleanup_phys_status_page(struct intel_engine_cs *engine) 1844c0e85e96SFrançois Tigeot { 18451487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 1846c0e85e96SFrançois Tigeot 1847c0e85e96SFrançois Tigeot if (!dev_priv->status_page_dmah) 1848c0e85e96SFrançois Tigeot return; 1849c0e85e96SFrançois Tigeot 1850303bf270SFrançois Tigeot drm_pci_free(&dev_priv->drm, dev_priv->status_page_dmah); 18518621f407SFrançois Tigeot engine->status_page.page_addr = NULL; 1852c0e85e96SFrançois Tigeot } 1853c0e85e96SFrançois Tigeot 18548621f407SFrançois Tigeot static void cleanup_status_page(struct intel_engine_cs *engine) 1855e3adcf8fSFrançois Tigeot { 1856e3adcf8fSFrançois Tigeot struct drm_i915_gem_object *obj; 1857e3adcf8fSFrançois Tigeot 18588621f407SFrançois Tigeot obj = engine->status_page.obj; 1859e3adcf8fSFrançois Tigeot if (obj == NULL) 1860e3adcf8fSFrançois Tigeot return; 1861e3adcf8fSFrançois Tigeot 18627ec9f8e5SFrançois Tigeot kunmap(sg_page(obj->pages->sgl)); 1863ba55f2f5SFrançois Tigeot i915_gem_object_ggtt_unpin(obj); 186487df8fc6SFrançois Tigeot i915_gem_object_put(obj); 18658621f407SFrançois Tigeot engine->status_page.obj = NULL; 1866e3adcf8fSFrançois Tigeot } 1867e3adcf8fSFrançois Tigeot 18688621f407SFrançois Tigeot static int init_status_page(struct intel_engine_cs *engine) 1869e3adcf8fSFrançois Tigeot { 18708621f407SFrançois Tigeot struct drm_i915_gem_object *obj = engine->status_page.obj; 1871ba55f2f5SFrançois Tigeot 1872c0e85e96SFrançois Tigeot if (obj == NULL) { 187324edb884SFrançois Tigeot unsigned flags; 1874e3adcf8fSFrançois Tigeot int ret; 1875e3adcf8fSFrançois Tigeot 1876303bf270SFrançois Tigeot obj = i915_gem_object_create(&engine->i915->drm, 4096); 18771487f786SFrançois Tigeot if (IS_ERR(obj)) { 1878e3adcf8fSFrançois Tigeot DRM_ERROR("Failed to allocate status page\n"); 18791487f786SFrançois Tigeot return PTR_ERR(obj); 1880e3adcf8fSFrançois Tigeot } 1881e3adcf8fSFrançois Tigeot 1882ba55f2f5SFrançois Tigeot ret = i915_gem_object_set_cache_level(obj, I915_CACHE_LLC); 1883ba55f2f5SFrançois Tigeot if (ret) 1884e3adcf8fSFrançois Tigeot goto err_unref; 1885ba55f2f5SFrançois Tigeot 188624edb884SFrançois Tigeot flags = 0; 18871487f786SFrançois Tigeot if (!HAS_LLC(engine->i915)) 188824edb884SFrançois Tigeot /* On g33, we cannot place HWS above 256MiB, so 188924edb884SFrançois Tigeot * restrict its pinning to the low mappable arena. 189024edb884SFrançois Tigeot * Though this restriction is not documented for 189124edb884SFrançois Tigeot * gen4, gen5, or byt, they also behave similarly 189224edb884SFrançois Tigeot * and hang if the HWS is placed at the top of the 189324edb884SFrançois Tigeot * GTT. To generalise, it appears that all !llc 189424edb884SFrançois Tigeot * platforms have issues with us placing the HWS 189524edb884SFrançois Tigeot * above the mappable region (even though we never 189624edb884SFrançois Tigeot * actualy map it). 189724edb884SFrançois Tigeot */ 189824edb884SFrançois Tigeot flags |= PIN_MAPPABLE; 1899*71f41f3eSFrançois Tigeot ret = i915_gem_object_ggtt_pin(obj, NULL, 0, 4096, flags); 1900ba55f2f5SFrançois Tigeot if (ret) { 1901ba55f2f5SFrançois Tigeot err_unref: 190287df8fc6SFrançois Tigeot i915_gem_object_put(obj); 1903ba55f2f5SFrançois Tigeot return ret; 1904ba55f2f5SFrançois Tigeot } 1905ba55f2f5SFrançois Tigeot 19068621f407SFrançois Tigeot engine->status_page.obj = obj; 1907e3adcf8fSFrançois Tigeot } 1908e3adcf8fSFrançois Tigeot 19098621f407SFrançois Tigeot engine->status_page.gfx_addr = i915_gem_obj_ggtt_offset(obj); 19108621f407SFrançois Tigeot engine->status_page.page_addr = kmap(sg_page(obj->pages->sgl)); 19118621f407SFrançois Tigeot memset(engine->status_page.page_addr, 0, PAGE_SIZE); 1912e3adcf8fSFrançois Tigeot 1913b5c29a34SFrançois Tigeot DRM_DEBUG_DRIVER("%s hws offset: 0x%08x\n", 19148621f407SFrançois Tigeot engine->name, engine->status_page.gfx_addr); 1915e3adcf8fSFrançois Tigeot 1916e3adcf8fSFrançois Tigeot return 0; 1917e3adcf8fSFrançois Tigeot } 1918e3adcf8fSFrançois Tigeot 19198621f407SFrançois Tigeot static int init_phys_status_page(struct intel_engine_cs *engine) 1920686a02f1SFrançois Tigeot { 19211487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 1922686a02f1SFrançois Tigeot 1923686a02f1SFrançois Tigeot if (!dev_priv->status_page_dmah) { 1924686a02f1SFrançois Tigeot dev_priv->status_page_dmah = 1925303bf270SFrançois Tigeot drm_pci_alloc(&dev_priv->drm, PAGE_SIZE, PAGE_SIZE); 1926686a02f1SFrançois Tigeot if (!dev_priv->status_page_dmah) 1927686a02f1SFrançois Tigeot return -ENOMEM; 1928686a02f1SFrançois Tigeot } 1929686a02f1SFrançois Tigeot 19308621f407SFrançois Tigeot engine->status_page.page_addr = dev_priv->status_page_dmah->vaddr; 19318621f407SFrançois Tigeot memset(engine->status_page.page_addr, 0, PAGE_SIZE); 1932686a02f1SFrançois Tigeot 1933686a02f1SFrançois Tigeot return 0; 1934686a02f1SFrançois Tigeot } 1935686a02f1SFrançois Tigeot 1936*71f41f3eSFrançois Tigeot int intel_ring_pin(struct intel_ring *ring) 19372c9916cdSFrançois Tigeot { 1938*71f41f3eSFrançois Tigeot struct drm_i915_private *dev_priv = ring->engine->i915; 1939*71f41f3eSFrançois Tigeot struct drm_i915_gem_object *obj = ring->obj; 1940c0e85e96SFrançois Tigeot /* Ring wraparound at offset 0 sometimes hangs. No idea why. */ 1941c0e85e96SFrançois Tigeot unsigned flags = PIN_OFFSET_BIAS | 4096; 19428621f407SFrançois Tigeot void *addr; 19432c9916cdSFrançois Tigeot int ret; 19442c9916cdSFrançois Tigeot 1945aee94f86SFrançois Tigeot if (HAS_LLC(dev_priv) && !obj->stolen) { 1946*71f41f3eSFrançois Tigeot ret = i915_gem_object_ggtt_pin(obj, NULL, 0, PAGE_SIZE, flags); 1947aee94f86SFrançois Tigeot if (ret) 1948aee94f86SFrançois Tigeot return ret; 1949aee94f86SFrançois Tigeot 1950aee94f86SFrançois Tigeot ret = i915_gem_object_set_to_cpu_domain(obj, true); 19518621f407SFrançois Tigeot if (ret) 19528621f407SFrançois Tigeot goto err_unpin; 1953aee94f86SFrançois Tigeot 19548621f407SFrançois Tigeot addr = i915_gem_object_pin_map(obj); 19558621f407SFrançois Tigeot if (IS_ERR(addr)) { 19568621f407SFrançois Tigeot ret = PTR_ERR(addr); 19578621f407SFrançois Tigeot goto err_unpin; 1958aee94f86SFrançois Tigeot } 1959aee94f86SFrançois Tigeot } else { 1960*71f41f3eSFrançois Tigeot ret = i915_gem_object_ggtt_pin(obj, NULL, 0, PAGE_SIZE, 1961c0e85e96SFrançois Tigeot flags | PIN_MAPPABLE); 19622c9916cdSFrançois Tigeot if (ret) 19632c9916cdSFrançois Tigeot return ret; 19642c9916cdSFrançois Tigeot 19652c9916cdSFrançois Tigeot ret = i915_gem_object_set_to_gtt_domain(obj, true); 19668621f407SFrançois Tigeot if (ret) 19678621f407SFrançois Tigeot goto err_unpin; 19682c9916cdSFrançois Tigeot 1969c0e85e96SFrançois Tigeot /* Access through the GTT requires the device to be awake. */ 1970c0e85e96SFrançois Tigeot assert_rpm_wakelock_held(dev_priv); 1971c0e85e96SFrançois Tigeot 197287df8fc6SFrançois Tigeot addr = (void __force *) 197387df8fc6SFrançois Tigeot i915_vma_pin_iomap(i915_gem_obj_to_ggtt(obj)); 19741487f786SFrançois Tigeot if (IS_ERR(addr)) { 19751487f786SFrançois Tigeot ret = PTR_ERR(addr); 19768621f407SFrançois Tigeot goto err_unpin; 19772c9916cdSFrançois Tigeot } 1978aee94f86SFrançois Tigeot } 19792c9916cdSFrançois Tigeot 1980*71f41f3eSFrançois Tigeot ring->vaddr = addr; 1981*71f41f3eSFrançois Tigeot ring->vma = i915_gem_obj_to_ggtt(obj); 19822c9916cdSFrançois Tigeot return 0; 19838621f407SFrançois Tigeot 19848621f407SFrançois Tigeot err_unpin: 19858621f407SFrançois Tigeot i915_gem_object_ggtt_unpin(obj); 19868621f407SFrançois Tigeot return ret; 19872c9916cdSFrançois Tigeot } 19882c9916cdSFrançois Tigeot 1989*71f41f3eSFrançois Tigeot void intel_ring_unpin(struct intel_ring *ring) 1990e3adcf8fSFrançois Tigeot { 1991*71f41f3eSFrançois Tigeot GEM_BUG_ON(!ring->vma); 1992*71f41f3eSFrançois Tigeot GEM_BUG_ON(!ring->vaddr); 1993*71f41f3eSFrançois Tigeot 1994*71f41f3eSFrançois Tigeot if (HAS_LLC(ring->engine->i915) && !ring->obj->stolen) 1995*71f41f3eSFrançois Tigeot i915_gem_object_unpin_map(ring->obj); 1996*71f41f3eSFrançois Tigeot else 1997*71f41f3eSFrançois Tigeot i915_vma_unpin_iomap(ring->vma); 1998*71f41f3eSFrançois Tigeot ring->vaddr = NULL; 1999*71f41f3eSFrançois Tigeot 2000*71f41f3eSFrançois Tigeot i915_gem_object_ggtt_unpin(ring->obj); 2001*71f41f3eSFrançois Tigeot ring->vma = NULL; 2002*71f41f3eSFrançois Tigeot } 2003*71f41f3eSFrançois Tigeot 2004*71f41f3eSFrançois Tigeot static void intel_destroy_ringbuffer_obj(struct intel_ring *ring) 2005*71f41f3eSFrançois Tigeot { 2006*71f41f3eSFrançois Tigeot i915_gem_object_put(ring->obj); 2007*71f41f3eSFrançois Tigeot ring->obj = NULL; 200824edb884SFrançois Tigeot } 200924edb884SFrançois Tigeot 2010352ff8bdSFrançois Tigeot static int intel_alloc_ringbuffer_obj(struct drm_device *dev, 2011*71f41f3eSFrançois Tigeot struct intel_ring *ring) 201224edb884SFrançois Tigeot { 2013e3adcf8fSFrançois Tigeot struct drm_i915_gem_object *obj; 2014e3adcf8fSFrançois Tigeot 2015a2fdbec6SFrançois Tigeot obj = NULL; 2016a2fdbec6SFrançois Tigeot if (!HAS_LLC(dev)) 2017*71f41f3eSFrançois Tigeot obj = i915_gem_object_create_stolen(dev, ring->size); 2018a2fdbec6SFrançois Tigeot if (obj == NULL) 2019*71f41f3eSFrançois Tigeot obj = i915_gem_object_create(dev, ring->size); 20201487f786SFrançois Tigeot if (IS_ERR(obj)) 20211487f786SFrançois Tigeot return PTR_ERR(obj); 2022e3adcf8fSFrançois Tigeot 202324edb884SFrançois Tigeot /* mark ring buffers as read-only from GPU side by default */ 202424edb884SFrançois Tigeot obj->gt_ro = 1; 202524edb884SFrançois Tigeot 2026*71f41f3eSFrançois Tigeot ring->obj = obj; 2027ba55f2f5SFrançois Tigeot 20282c9916cdSFrançois Tigeot return 0; 2029ba55f2f5SFrançois Tigeot } 2030ba55f2f5SFrançois Tigeot 2031*71f41f3eSFrançois Tigeot struct intel_ring * 2032*71f41f3eSFrançois Tigeot intel_engine_create_ring(struct intel_engine_cs *engine, int size) 2033352ff8bdSFrançois Tigeot { 2034*71f41f3eSFrançois Tigeot struct intel_ring *ring; 2035352ff8bdSFrançois Tigeot int ret; 2036352ff8bdSFrançois Tigeot 2037*71f41f3eSFrançois Tigeot GEM_BUG_ON(!is_power_of_2(size)); 2038*71f41f3eSFrançois Tigeot 2039352ff8bdSFrançois Tigeot ring = kzalloc(sizeof(*ring), GFP_KERNEL); 2040aee94f86SFrançois Tigeot if (ring == NULL) { 2041aee94f86SFrançois Tigeot DRM_DEBUG_DRIVER("Failed to allocate ringbuffer %s\n", 2042aee94f86SFrançois Tigeot engine->name); 2043352ff8bdSFrançois Tigeot return ERR_PTR(-ENOMEM); 2044aee94f86SFrançois Tigeot } 2045352ff8bdSFrançois Tigeot 20468621f407SFrançois Tigeot ring->engine = engine; 2047aee94f86SFrançois Tigeot list_add(&ring->link, &engine->buffers); 2048352ff8bdSFrançois Tigeot 2049*71f41f3eSFrançois Tigeot INIT_LIST_HEAD(&ring->request_list); 2050*71f41f3eSFrançois Tigeot 2051352ff8bdSFrançois Tigeot ring->size = size; 2052352ff8bdSFrançois Tigeot /* Workaround an erratum on the i830 which causes a hang if 2053352ff8bdSFrançois Tigeot * the TAIL pointer points to within the last 2 cachelines 2054352ff8bdSFrançois Tigeot * of the buffer. 2055352ff8bdSFrançois Tigeot */ 2056352ff8bdSFrançois Tigeot ring->effective_size = size; 20571487f786SFrançois Tigeot if (IS_I830(engine->i915) || IS_845G(engine->i915)) 2058352ff8bdSFrançois Tigeot ring->effective_size -= 2 * CACHELINE_BYTES; 2059352ff8bdSFrançois Tigeot 2060352ff8bdSFrançois Tigeot ring->last_retired_head = -1; 2061352ff8bdSFrançois Tigeot intel_ring_update_space(ring); 2062352ff8bdSFrançois Tigeot 2063303bf270SFrançois Tigeot ret = intel_alloc_ringbuffer_obj(&engine->i915->drm, ring); 2064352ff8bdSFrançois Tigeot if (ret) { 2065aee94f86SFrançois Tigeot DRM_DEBUG_DRIVER("Failed to allocate ringbuffer %s: %d\n", 2066352ff8bdSFrançois Tigeot engine->name, ret); 2067aee94f86SFrançois Tigeot list_del(&ring->link); 2068352ff8bdSFrançois Tigeot kfree(ring); 2069352ff8bdSFrançois Tigeot return ERR_PTR(ret); 2070352ff8bdSFrançois Tigeot } 2071352ff8bdSFrançois Tigeot 2072352ff8bdSFrançois Tigeot return ring; 2073352ff8bdSFrançois Tigeot } 2074352ff8bdSFrançois Tigeot 2075352ff8bdSFrançois Tigeot void 2076*71f41f3eSFrançois Tigeot intel_ring_free(struct intel_ring *ring) 2077352ff8bdSFrançois Tigeot { 2078352ff8bdSFrançois Tigeot intel_destroy_ringbuffer_obj(ring); 2079aee94f86SFrançois Tigeot list_del(&ring->link); 2080352ff8bdSFrançois Tigeot kfree(ring); 2081352ff8bdSFrançois Tigeot } 2082352ff8bdSFrançois Tigeot 20831487f786SFrançois Tigeot static int intel_ring_context_pin(struct i915_gem_context *ctx, 20841487f786SFrançois Tigeot struct intel_engine_cs *engine) 20851487f786SFrançois Tigeot { 20861487f786SFrançois Tigeot struct intel_context *ce = &ctx->engine[engine->id]; 20871487f786SFrançois Tigeot int ret; 20881487f786SFrançois Tigeot 2089303bf270SFrançois Tigeot lockdep_assert_held(&ctx->i915->drm.struct_mutex); 20901487f786SFrançois Tigeot 20911487f786SFrançois Tigeot if (ce->pin_count++) 20921487f786SFrançois Tigeot return 0; 20931487f786SFrançois Tigeot 20941487f786SFrançois Tigeot if (ce->state) { 2095*71f41f3eSFrançois Tigeot ret = i915_gem_object_ggtt_pin(ce->state, NULL, 0, 2096*71f41f3eSFrançois Tigeot ctx->ggtt_alignment, 0); 20971487f786SFrançois Tigeot if (ret) 20981487f786SFrançois Tigeot goto error; 20991487f786SFrançois Tigeot } 21001487f786SFrançois Tigeot 21011487f786SFrançois Tigeot /* The kernel context is only used as a placeholder for flushing the 21021487f786SFrançois Tigeot * active context. It is never used for submitting user rendering and 21031487f786SFrançois Tigeot * as such never requires the golden render context, and so we can skip 21041487f786SFrançois Tigeot * emitting it when we switch to the kernel context. This is required 21051487f786SFrançois Tigeot * as during eviction we cannot allocate and pin the renderstate in 21061487f786SFrançois Tigeot * order to initialise the context. 21071487f786SFrançois Tigeot */ 21081487f786SFrançois Tigeot if (ctx == ctx->i915->kernel_context) 21091487f786SFrançois Tigeot ce->initialised = true; 21101487f786SFrançois Tigeot 211187df8fc6SFrançois Tigeot i915_gem_context_get(ctx); 21121487f786SFrançois Tigeot return 0; 21131487f786SFrançois Tigeot 21141487f786SFrançois Tigeot error: 21151487f786SFrançois Tigeot ce->pin_count = 0; 21161487f786SFrançois Tigeot return ret; 21171487f786SFrançois Tigeot } 21181487f786SFrançois Tigeot 21191487f786SFrançois Tigeot static void intel_ring_context_unpin(struct i915_gem_context *ctx, 21201487f786SFrançois Tigeot struct intel_engine_cs *engine) 21211487f786SFrançois Tigeot { 21221487f786SFrançois Tigeot struct intel_context *ce = &ctx->engine[engine->id]; 21231487f786SFrançois Tigeot 2124303bf270SFrançois Tigeot lockdep_assert_held(&ctx->i915->drm.struct_mutex); 21251487f786SFrançois Tigeot 21261487f786SFrançois Tigeot if (--ce->pin_count) 21271487f786SFrançois Tigeot return; 21281487f786SFrançois Tigeot 21291487f786SFrançois Tigeot if (ce->state) 21301487f786SFrançois Tigeot i915_gem_object_ggtt_unpin(ce->state); 21311487f786SFrançois Tigeot 213287df8fc6SFrançois Tigeot i915_gem_context_put(ctx); 21331487f786SFrançois Tigeot } 21341487f786SFrançois Tigeot 213587df8fc6SFrançois Tigeot static int intel_init_ring_buffer(struct intel_engine_cs *engine) 2136ba55f2f5SFrançois Tigeot { 213787df8fc6SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 2138*71f41f3eSFrançois Tigeot struct intel_ring *ring; 2139ba55f2f5SFrançois Tigeot int ret; 2140ba55f2f5SFrançois Tigeot 21418621f407SFrançois Tigeot WARN_ON(engine->buffer); 21422c9916cdSFrançois Tigeot 214387df8fc6SFrançois Tigeot intel_engine_setup_common(engine); 214487df8fc6SFrançois Tigeot 21458621f407SFrançois Tigeot memset(engine->semaphore.sync_seqno, 0, 21468621f407SFrançois Tigeot sizeof(engine->semaphore.sync_seqno)); 2147ba55f2f5SFrançois Tigeot 214887df8fc6SFrançois Tigeot ret = intel_engine_init_common(engine); 2149303bf270SFrançois Tigeot if (ret) 2150303bf270SFrançois Tigeot goto error; 2151ba55f2f5SFrançois Tigeot 21521487f786SFrançois Tigeot /* We may need to do things with the shrinker which 21531487f786SFrançois Tigeot * require us to immediately switch back to the default 21541487f786SFrançois Tigeot * context. This can cause a problem as pinning the 21551487f786SFrançois Tigeot * default context also requires GTT space which may not 21561487f786SFrançois Tigeot * be available. To avoid this we always pin the default 21571487f786SFrançois Tigeot * context. 21581487f786SFrançois Tigeot */ 21591487f786SFrançois Tigeot ret = intel_ring_context_pin(dev_priv->kernel_context, engine); 21601487f786SFrançois Tigeot if (ret) 21611487f786SFrançois Tigeot goto error; 21621487f786SFrançois Tigeot 2163*71f41f3eSFrançois Tigeot ring = intel_engine_create_ring(engine, 32 * PAGE_SIZE); 2164*71f41f3eSFrançois Tigeot if (IS_ERR(ring)) { 2165*71f41f3eSFrançois Tigeot ret = PTR_ERR(ring); 2166aee94f86SFrançois Tigeot goto error; 2167aee94f86SFrançois Tigeot } 2168*71f41f3eSFrançois Tigeot engine->buffer = ring; 2169352ff8bdSFrançois Tigeot 21701487f786SFrançois Tigeot if (I915_NEED_GFX_HWS(dev_priv)) { 21718621f407SFrançois Tigeot ret = init_status_page(engine); 2172e3adcf8fSFrançois Tigeot if (ret) 2173ba55f2f5SFrançois Tigeot goto error; 2174ba55f2f5SFrançois Tigeot } else { 21758621f407SFrançois Tigeot WARN_ON(engine->id != RCS); 21768621f407SFrançois Tigeot ret = init_phys_status_page(engine); 2177ba55f2f5SFrançois Tigeot if (ret) 2178ba55f2f5SFrançois Tigeot goto error; 2179ba55f2f5SFrançois Tigeot } 2180ba55f2f5SFrançois Tigeot 2181*71f41f3eSFrançois Tigeot ret = intel_ring_pin(ring); 21822c9916cdSFrançois Tigeot if (ret) { 21832c9916cdSFrançois Tigeot DRM_ERROR("Failed to pin and map ringbuffer %s: %d\n", 21848621f407SFrançois Tigeot engine->name, ret); 2185*71f41f3eSFrançois Tigeot intel_destroy_ringbuffer_obj(ring); 2186ba55f2f5SFrançois Tigeot goto error; 2187ba55f2f5SFrançois Tigeot } 2188e3adcf8fSFrançois Tigeot 2189e3adcf8fSFrançois Tigeot return 0; 2190e3adcf8fSFrançois Tigeot 2191ba55f2f5SFrançois Tigeot error: 2192*71f41f3eSFrançois Tigeot intel_engine_cleanup(engine); 2193e3adcf8fSFrançois Tigeot return ret; 2194e3adcf8fSFrançois Tigeot } 2195e3adcf8fSFrançois Tigeot 2196*71f41f3eSFrançois Tigeot void intel_engine_cleanup(struct intel_engine_cs *engine) 2197e3adcf8fSFrançois Tigeot { 21982c9916cdSFrançois Tigeot struct drm_i915_private *dev_priv; 2199e3adcf8fSFrançois Tigeot 22008621f407SFrançois Tigeot if (!intel_engine_initialized(engine)) 2201e3adcf8fSFrançois Tigeot return; 2202e3adcf8fSFrançois Tigeot 22031487f786SFrançois Tigeot dev_priv = engine->i915; 22042c9916cdSFrançois Tigeot 22058621f407SFrançois Tigeot if (engine->buffer) { 22061487f786SFrançois Tigeot WARN_ON(!IS_GEN2(dev_priv) && (I915_READ_MODE(engine) & MODE_IDLE) == 0); 2207b030f26bSFrançois Tigeot 2208*71f41f3eSFrançois Tigeot intel_ring_unpin(engine->buffer); 2209*71f41f3eSFrançois Tigeot intel_ring_free(engine->buffer); 22108621f407SFrançois Tigeot engine->buffer = NULL; 2211aee94f86SFrançois Tigeot } 2212e3adcf8fSFrançois Tigeot 22138621f407SFrançois Tigeot if (engine->cleanup) 22148621f407SFrançois Tigeot engine->cleanup(engine); 2215e3adcf8fSFrançois Tigeot 22161487f786SFrançois Tigeot if (I915_NEED_GFX_HWS(dev_priv)) { 22178621f407SFrançois Tigeot cleanup_status_page(engine); 2218c0e85e96SFrançois Tigeot } else { 22198621f407SFrançois Tigeot WARN_ON(engine->id != RCS); 22208621f407SFrançois Tigeot cleanup_phys_status_page(engine); 2221c0e85e96SFrançois Tigeot } 2222ba55f2f5SFrançois Tigeot 2223*71f41f3eSFrançois Tigeot intel_engine_cleanup_common(engine); 22241487f786SFrançois Tigeot 22251487f786SFrançois Tigeot intel_ring_context_unpin(dev_priv->kernel_context, engine); 22261487f786SFrançois Tigeot 22271487f786SFrançois Tigeot engine->i915 = NULL; 2228e3adcf8fSFrançois Tigeot } 2229e3adcf8fSFrançois Tigeot 223019c468b4SFrançois Tigeot int intel_ring_alloc_request_extras(struct drm_i915_gem_request *request) 2231b5c29a34SFrançois Tigeot { 22321487f786SFrançois Tigeot int ret; 22339edbd4a0SFrançois Tigeot 22341487f786SFrançois Tigeot /* Flush enough space to reduce the likelihood of waiting after 22351487f786SFrançois Tigeot * we start building the request - in which case we will just 22361487f786SFrançois Tigeot * have to repeat work. 2237a05eeebfSFrançois Tigeot */ 22381487f786SFrançois Tigeot request->reserved_space += LEGACY_REQUEST_SIZE; 2239a2fdbec6SFrançois Tigeot 2240*71f41f3eSFrançois Tigeot request->ring = request->engine->buffer; 2241a2fdbec6SFrançois Tigeot 22421487f786SFrançois Tigeot ret = intel_ring_begin(request, 0); 22431487f786SFrançois Tigeot if (ret) 22441487f786SFrançois Tigeot return ret; 2245a05eeebfSFrançois Tigeot 22461487f786SFrançois Tigeot request->reserved_space -= LEGACY_REQUEST_SIZE; 22471487f786SFrançois Tigeot return 0; 2248a05eeebfSFrançois Tigeot } 2249a05eeebfSFrançois Tigeot 22508621f407SFrançois Tigeot static int wait_for_space(struct drm_i915_gem_request *req, int bytes) 2251a05eeebfSFrançois Tigeot { 2252*71f41f3eSFrançois Tigeot struct intel_ring *ring = req->ring; 22538621f407SFrançois Tigeot struct drm_i915_gem_request *target; 2254*71f41f3eSFrançois Tigeot int ret; 22558621f407SFrançois Tigeot 2256*71f41f3eSFrançois Tigeot intel_ring_update_space(ring); 2257*71f41f3eSFrançois Tigeot if (ring->space >= bytes) 22588621f407SFrançois Tigeot return 0; 22598621f407SFrançois Tigeot 22608621f407SFrançois Tigeot /* 22618621f407SFrançois Tigeot * Space is reserved in the ringbuffer for finalising the request, 22628621f407SFrançois Tigeot * as that cannot be allowed to fail. During request finalisation, 22638621f407SFrançois Tigeot * reserved_space is set to 0 to stop the overallocation and the 22648621f407SFrançois Tigeot * assumption is that then we never need to wait (which has the 22658621f407SFrançois Tigeot * risk of failing with EINTR). 22668621f407SFrançois Tigeot * 22678621f407SFrançois Tigeot * See also i915_gem_request_alloc() and i915_add_request(). 22688621f407SFrançois Tigeot */ 22691487f786SFrançois Tigeot GEM_BUG_ON(!req->reserved_space); 22708621f407SFrançois Tigeot 2271*71f41f3eSFrançois Tigeot list_for_each_entry(target, &ring->request_list, ring_link) { 22728621f407SFrançois Tigeot unsigned space; 22738621f407SFrançois Tigeot 22748621f407SFrançois Tigeot /* Would completion of this request free enough space? */ 2275*71f41f3eSFrançois Tigeot space = __intel_ring_space(target->postfix, ring->tail, 2276*71f41f3eSFrançois Tigeot ring->size); 22778621f407SFrançois Tigeot if (space >= bytes) 22788621f407SFrançois Tigeot break; 22798621f407SFrançois Tigeot } 22808621f407SFrançois Tigeot 2281*71f41f3eSFrançois Tigeot if (WARN_ON(&target->ring_link == &ring->request_list)) 22828621f407SFrançois Tigeot return -ENOSPC; 22838621f407SFrançois Tigeot 2284*71f41f3eSFrançois Tigeot ret = i915_wait_request(target, true, NULL, NO_WAITBOOST); 2285*71f41f3eSFrançois Tigeot if (ret) 2286*71f41f3eSFrançois Tigeot return ret; 2287*71f41f3eSFrançois Tigeot 2288*71f41f3eSFrançois Tigeot if (i915_reset_in_progress(&target->i915->gpu_error)) 2289*71f41f3eSFrançois Tigeot return -EAGAIN; 2290*71f41f3eSFrançois Tigeot 2291*71f41f3eSFrançois Tigeot i915_gem_request_retire_upto(target); 2292*71f41f3eSFrançois Tigeot 2293*71f41f3eSFrançois Tigeot intel_ring_update_space(ring); 2294*71f41f3eSFrançois Tigeot GEM_BUG_ON(ring->space < bytes); 2295*71f41f3eSFrançois Tigeot return 0; 22968621f407SFrançois Tigeot } 22978621f407SFrançois Tigeot 22988621f407SFrançois Tigeot int intel_ring_begin(struct drm_i915_gem_request *req, int num_dwords) 22998621f407SFrançois Tigeot { 2300*71f41f3eSFrançois Tigeot struct intel_ring *ring = req->ring; 2301*71f41f3eSFrançois Tigeot int remain_actual = ring->size - ring->tail; 2302*71f41f3eSFrançois Tigeot int remain_usable = ring->effective_size - ring->tail; 23038621f407SFrançois Tigeot int bytes = num_dwords * sizeof(u32); 23048621f407SFrançois Tigeot int total_bytes, wait_bytes; 2305a05eeebfSFrançois Tigeot bool need_wrap = false; 2306a05eeebfSFrançois Tigeot 23071487f786SFrançois Tigeot total_bytes = bytes + req->reserved_space; 2308a05eeebfSFrançois Tigeot 2309a05eeebfSFrançois Tigeot if (unlikely(bytes > remain_usable)) { 2310a05eeebfSFrançois Tigeot /* 2311a05eeebfSFrançois Tigeot * Not enough space for the basic request. So need to flush 2312a05eeebfSFrançois Tigeot * out the remainder and then wait for base + reserved. 2313a05eeebfSFrançois Tigeot */ 2314a05eeebfSFrançois Tigeot wait_bytes = remain_actual + total_bytes; 2315a05eeebfSFrançois Tigeot need_wrap = true; 23168621f407SFrançois Tigeot } else if (unlikely(total_bytes > remain_usable)) { 2317a05eeebfSFrançois Tigeot /* 2318a05eeebfSFrançois Tigeot * The base request will fit but the reserved space 23198621f407SFrançois Tigeot * falls off the end. So we don't need an immediate wrap 2320c0e85e96SFrançois Tigeot * and only need to effectively wait for the reserved 2321c0e85e96SFrançois Tigeot * size space from the start of ringbuffer. 2322a05eeebfSFrançois Tigeot */ 23231487f786SFrançois Tigeot wait_bytes = remain_actual + req->reserved_space; 23248621f407SFrançois Tigeot } else { 2325a05eeebfSFrançois Tigeot /* No wrapping required, just waiting. */ 2326a05eeebfSFrançois Tigeot wait_bytes = total_bytes; 2327a05eeebfSFrançois Tigeot } 2328a05eeebfSFrançois Tigeot 2329*71f41f3eSFrançois Tigeot if (wait_bytes > ring->space) { 23308621f407SFrançois Tigeot int ret = wait_for_space(req, wait_bytes); 2331a2fdbec6SFrançois Tigeot if (unlikely(ret)) 2332a2fdbec6SFrançois Tigeot return ret; 2333a2fdbec6SFrançois Tigeot } 2334a2fdbec6SFrançois Tigeot 23358621f407SFrançois Tigeot if (unlikely(need_wrap)) { 2336*71f41f3eSFrançois Tigeot GEM_BUG_ON(remain_actual > ring->space); 2337*71f41f3eSFrançois Tigeot GEM_BUG_ON(ring->tail + remain_actual > ring->size); 23388621f407SFrançois Tigeot 23398621f407SFrançois Tigeot /* Fill the tail with MI_NOOP */ 2340*71f41f3eSFrançois Tigeot memset(ring->vaddr + ring->tail, 0, remain_actual); 2341*71f41f3eSFrançois Tigeot ring->tail = 0; 2342*71f41f3eSFrançois Tigeot ring->space -= remain_actual; 2343a2fdbec6SFrançois Tigeot } 2344a2fdbec6SFrançois Tigeot 2345*71f41f3eSFrançois Tigeot ring->space -= bytes; 2346*71f41f3eSFrançois Tigeot GEM_BUG_ON(ring->space < 0); 23479edbd4a0SFrançois Tigeot return 0; 23489edbd4a0SFrançois Tigeot } 23499edbd4a0SFrançois Tigeot 23509edbd4a0SFrançois Tigeot /* Align the ring tail to a cacheline boundary */ 2351a05eeebfSFrançois Tigeot int intel_ring_cacheline_align(struct drm_i915_gem_request *req) 23529edbd4a0SFrançois Tigeot { 2353*71f41f3eSFrançois Tigeot struct intel_ring *ring = req->ring; 2354*71f41f3eSFrançois Tigeot int num_dwords = 2355*71f41f3eSFrançois Tigeot (ring->tail & (CACHELINE_BYTES - 1)) / sizeof(uint32_t); 23569edbd4a0SFrançois Tigeot int ret; 23579edbd4a0SFrançois Tigeot 23589edbd4a0SFrançois Tigeot if (num_dwords == 0) 23599edbd4a0SFrançois Tigeot return 0; 23609edbd4a0SFrançois Tigeot 2361ba55f2f5SFrançois Tigeot num_dwords = CACHELINE_BYTES / sizeof(uint32_t) - num_dwords; 2362a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, num_dwords); 23639edbd4a0SFrançois Tigeot if (ret) 23649edbd4a0SFrançois Tigeot return ret; 23659edbd4a0SFrançois Tigeot 23669edbd4a0SFrançois Tigeot while (num_dwords--) 2367*71f41f3eSFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 23689edbd4a0SFrançois Tigeot 2369*71f41f3eSFrançois Tigeot intel_ring_advance(ring); 23709edbd4a0SFrançois Tigeot 23719edbd4a0SFrançois Tigeot return 0; 2372e3adcf8fSFrançois Tigeot } 2373e3adcf8fSFrançois Tigeot 2374*71f41f3eSFrançois Tigeot void intel_engine_init_seqno(struct intel_engine_cs *engine, u32 seqno) 2375a2fdbec6SFrançois Tigeot { 23761487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 2377a2fdbec6SFrançois Tigeot 23788621f407SFrançois Tigeot /* Our semaphore implementation is strictly monotonic (i.e. we proceed 23798621f407SFrançois Tigeot * so long as the semaphore value in the register/page is greater 23808621f407SFrançois Tigeot * than the sync value), so whenever we reset the seqno, 23818621f407SFrançois Tigeot * so long as we reset the tracking semaphore value to 0, it will 23828621f407SFrançois Tigeot * always be before the next request's seqno. If we don't reset 23838621f407SFrançois Tigeot * the semaphore value, then when the seqno moves backwards all 23848621f407SFrançois Tigeot * future waits will complete instantly (causing rendering corruption). 23858621f407SFrançois Tigeot */ 23861487f786SFrançois Tigeot if (IS_GEN6(dev_priv) || IS_GEN7(dev_priv)) { 23878621f407SFrançois Tigeot I915_WRITE(RING_SYNC_0(engine->mmio_base), 0); 23888621f407SFrançois Tigeot I915_WRITE(RING_SYNC_1(engine->mmio_base), 0); 23898621f407SFrançois Tigeot if (HAS_VEBOX(dev_priv)) 23908621f407SFrançois Tigeot I915_WRITE(RING_SYNC_2(engine->mmio_base), 0); 23918621f407SFrançois Tigeot } 23928621f407SFrançois Tigeot if (dev_priv->semaphore_obj) { 23938621f407SFrançois Tigeot struct drm_i915_gem_object *obj = dev_priv->semaphore_obj; 2394f0bba3d1SFrançois Tigeot struct page *page = i915_gem_object_get_dirty_page(obj, 0); 23951487f786SFrançois Tigeot void *semaphores = kmap(page); 23968621f407SFrançois Tigeot memset(semaphores + GEN8_SEMAPHORE_OFFSET(engine->id, 0), 23978621f407SFrançois Tigeot 0, I915_NUM_ENGINES * gen8_semaphore_seqno_size); 23988621f407SFrançois Tigeot kunmap(page); 23998621f407SFrançois Tigeot } 24008621f407SFrançois Tigeot memset(engine->semaphore.sync_seqno, 0, 24018621f407SFrançois Tigeot sizeof(engine->semaphore.sync_seqno)); 24028621f407SFrançois Tigeot 2403303bf270SFrançois Tigeot intel_write_status_page(engine, I915_GEM_HWS_INDEX, seqno); 2404303bf270SFrançois Tigeot if (engine->irq_seqno_barrier) 2405303bf270SFrançois Tigeot engine->irq_seqno_barrier(engine); 24068621f407SFrançois Tigeot engine->last_submitted_seqno = seqno; 24078621f407SFrançois Tigeot 24088621f407SFrançois Tigeot engine->hangcheck.seqno = seqno; 2409303bf270SFrançois Tigeot 2410303bf270SFrançois Tigeot /* After manually advancing the seqno, fake the interrupt in case 2411303bf270SFrançois Tigeot * there are any waiters for that seqno. 2412303bf270SFrançois Tigeot */ 2413303bf270SFrançois Tigeot rcu_read_lock(); 2414303bf270SFrançois Tigeot intel_engine_wakeup(engine); 2415303bf270SFrançois Tigeot rcu_read_unlock(); 2416e3adcf8fSFrançois Tigeot } 2417e3adcf8fSFrançois Tigeot 2418*71f41f3eSFrançois Tigeot static void gen6_bsd_submit_request(struct drm_i915_gem_request *request) 2419e3adcf8fSFrançois Tigeot { 2420*71f41f3eSFrançois Tigeot struct drm_i915_private *dev_priv = request->i915; 24211487f786SFrançois Tigeot 24221487f786SFrançois Tigeot intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL); 2423e3adcf8fSFrançois Tigeot 2424e3adcf8fSFrançois Tigeot /* Every tail move must follow the sequence below */ 2425f4e1c372SFrançois Tigeot 2426f4e1c372SFrançois Tigeot /* Disable notification that the ring is IDLE. The GT 2427f4e1c372SFrançois Tigeot * will then assume that it is busy and bring it out of rc6. 2428f4e1c372SFrançois Tigeot */ 24291487f786SFrançois Tigeot I915_WRITE_FW(GEN6_BSD_SLEEP_PSMI_CONTROL, 2430f4e1c372SFrançois Tigeot _MASKED_BIT_ENABLE(GEN6_BSD_SLEEP_MSG_DISABLE)); 2431e3adcf8fSFrançois Tigeot 2432f4e1c372SFrançois Tigeot /* Clear the context id. Here be magic! */ 24331487f786SFrançois Tigeot I915_WRITE64_FW(GEN6_BSD_RNCID, 0x0); 2434e3adcf8fSFrançois Tigeot 2435f4e1c372SFrançois Tigeot /* Wait for the ring not to be idle, i.e. for it to wake up. */ 24361487f786SFrançois Tigeot if (intel_wait_for_register_fw(dev_priv, 24371487f786SFrançois Tigeot GEN6_BSD_SLEEP_PSMI_CONTROL, 24381487f786SFrançois Tigeot GEN6_BSD_SLEEP_INDICATOR, 24391487f786SFrançois Tigeot 0, 2440f4e1c372SFrançois Tigeot 50)) 2441f4e1c372SFrançois Tigeot DRM_ERROR("timed out waiting for the BSD ring to wake up\n"); 2442f4e1c372SFrançois Tigeot 2443f4e1c372SFrançois Tigeot /* Now that the ring is fully powered up, update the tail */ 2444*71f41f3eSFrançois Tigeot i9xx_submit_request(request); 2445f4e1c372SFrançois Tigeot 2446f4e1c372SFrançois Tigeot /* Let the ring send IDLE messages to the GT again, 2447f4e1c372SFrançois Tigeot * and so let it sleep to conserve power when idle. 2448f4e1c372SFrançois Tigeot */ 24491487f786SFrançois Tigeot I915_WRITE_FW(GEN6_BSD_SLEEP_PSMI_CONTROL, 2450f4e1c372SFrançois Tigeot _MASKED_BIT_DISABLE(GEN6_BSD_SLEEP_MSG_DISABLE)); 24511487f786SFrançois Tigeot 24521487f786SFrançois Tigeot intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL); 2453e3adcf8fSFrançois Tigeot } 2454e3adcf8fSFrançois Tigeot 2455*71f41f3eSFrançois Tigeot static int gen6_bsd_ring_flush(struct drm_i915_gem_request *req, u32 mode) 2456e3adcf8fSFrançois Tigeot { 2457*71f41f3eSFrançois Tigeot struct intel_ring *ring = req->ring; 2458e3adcf8fSFrançois Tigeot uint32_t cmd; 2459e3adcf8fSFrançois Tigeot int ret; 2460e3adcf8fSFrançois Tigeot 2461a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 4); 2462e3adcf8fSFrançois Tigeot if (ret) 2463e3adcf8fSFrançois Tigeot return ret; 2464e3adcf8fSFrançois Tigeot 2465e3adcf8fSFrançois Tigeot cmd = MI_FLUSH_DW; 24661487f786SFrançois Tigeot if (INTEL_GEN(req->i915) >= 8) 24679edbd4a0SFrançois Tigeot cmd += 1; 24682c9916cdSFrançois Tigeot 24692c9916cdSFrançois Tigeot /* We always require a command barrier so that subsequent 24702c9916cdSFrançois Tigeot * commands, such as breadcrumb interrupts, are strictly ordered 24712c9916cdSFrançois Tigeot * wrt the contents of the write cache being flushed to memory 24722c9916cdSFrançois Tigeot * (and thus being coherent from the CPU). 24732c9916cdSFrançois Tigeot */ 24742c9916cdSFrançois Tigeot cmd |= MI_FLUSH_DW_STORE_INDEX | MI_FLUSH_DW_OP_STOREDW; 24752c9916cdSFrançois Tigeot 2476b5c29a34SFrançois Tigeot /* 2477b5c29a34SFrançois Tigeot * Bspec vol 1c.5 - video engine command streamer: 2478b5c29a34SFrançois Tigeot * "If ENABLED, all TLBs will be invalidated once the flush 2479b5c29a34SFrançois Tigeot * operation is complete. This bit is only valid when the 2480b5c29a34SFrançois Tigeot * Post-Sync Operation field is a value of 1h or 3h." 2481b5c29a34SFrançois Tigeot */ 2482*71f41f3eSFrançois Tigeot if (mode & EMIT_INVALIDATE) 24832c9916cdSFrançois Tigeot cmd |= MI_INVALIDATE_TLB | MI_INVALIDATE_BSD; 24842c9916cdSFrançois Tigeot 2485*71f41f3eSFrançois Tigeot intel_ring_emit(ring, cmd); 2486*71f41f3eSFrançois Tigeot intel_ring_emit(ring, I915_GEM_HWS_SCRATCH_ADDR | MI_FLUSH_DW_USE_GTT); 24871487f786SFrançois Tigeot if (INTEL_GEN(req->i915) >= 8) { 2488*71f41f3eSFrançois Tigeot intel_ring_emit(ring, 0); /* upper addr */ 2489*71f41f3eSFrançois Tigeot intel_ring_emit(ring, 0); /* value */ 24909edbd4a0SFrançois Tigeot } else { 2491*71f41f3eSFrançois Tigeot intel_ring_emit(ring, 0); 2492*71f41f3eSFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 24939edbd4a0SFrançois Tigeot } 2494*71f41f3eSFrançois Tigeot intel_ring_advance(ring); 24959edbd4a0SFrançois Tigeot return 0; 24969edbd4a0SFrançois Tigeot } 24979edbd4a0SFrançois Tigeot 24989edbd4a0SFrançois Tigeot static int 2499*71f41f3eSFrançois Tigeot gen8_emit_bb_start(struct drm_i915_gem_request *req, 2500ba55f2f5SFrançois Tigeot u64 offset, u32 len, 2501*71f41f3eSFrançois Tigeot unsigned int dispatch_flags) 25029edbd4a0SFrançois Tigeot { 2503*71f41f3eSFrançois Tigeot struct intel_ring *ring = req->ring; 2504*71f41f3eSFrançois Tigeot bool ppgtt = USES_PPGTT(req->i915) && 2505477eb7f9SFrançois Tigeot !(dispatch_flags & I915_DISPATCH_SECURE); 25069edbd4a0SFrançois Tigeot int ret; 25079edbd4a0SFrançois Tigeot 2508a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 4); 25099edbd4a0SFrançois Tigeot if (ret) 25109edbd4a0SFrançois Tigeot return ret; 25119edbd4a0SFrançois Tigeot 25129edbd4a0SFrançois Tigeot /* FIXME(BDW): Address space and security selectors. */ 2513*71f41f3eSFrançois Tigeot intel_ring_emit(ring, MI_BATCH_BUFFER_START_GEN8 | (ppgtt<<8) | 2514a05eeebfSFrançois Tigeot (dispatch_flags & I915_DISPATCH_RS ? 2515a05eeebfSFrançois Tigeot MI_BATCH_RESOURCE_STREAMER : 0)); 2516*71f41f3eSFrançois Tigeot intel_ring_emit(ring, lower_32_bits(offset)); 2517*71f41f3eSFrançois Tigeot intel_ring_emit(ring, upper_32_bits(offset)); 2518*71f41f3eSFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 2519*71f41f3eSFrançois Tigeot intel_ring_advance(ring); 25209edbd4a0SFrançois Tigeot 2521e3adcf8fSFrançois Tigeot return 0; 2522e3adcf8fSFrançois Tigeot } 2523e3adcf8fSFrançois Tigeot 2524e3adcf8fSFrançois Tigeot static int 2525*71f41f3eSFrançois Tigeot hsw_emit_bb_start(struct drm_i915_gem_request *req, 2526ba55f2f5SFrançois Tigeot u64 offset, u32 len, 2527*71f41f3eSFrançois Tigeot unsigned int dispatch_flags) 2528e3adcf8fSFrançois Tigeot { 2529*71f41f3eSFrançois Tigeot struct intel_ring *ring = req->ring; 2530e3adcf8fSFrançois Tigeot int ret; 2531e3adcf8fSFrançois Tigeot 2532a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 2); 2533e3adcf8fSFrançois Tigeot if (ret) 2534e3adcf8fSFrançois Tigeot return ret; 2535e3adcf8fSFrançois Tigeot 2536*71f41f3eSFrançois Tigeot intel_ring_emit(ring, 25371b13d190SFrançois Tigeot MI_BATCH_BUFFER_START | 2538477eb7f9SFrançois Tigeot (dispatch_flags & I915_DISPATCH_SECURE ? 2539a05eeebfSFrançois Tigeot 0 : MI_BATCH_PPGTT_HSW | MI_BATCH_NON_SECURE_HSW) | 2540a05eeebfSFrançois Tigeot (dispatch_flags & I915_DISPATCH_RS ? 2541a05eeebfSFrançois Tigeot MI_BATCH_RESOURCE_STREAMER : 0)); 2542b5c29a34SFrançois Tigeot /* bit0-7 is the length on GEN6+ */ 2543*71f41f3eSFrançois Tigeot intel_ring_emit(ring, offset); 2544*71f41f3eSFrançois Tigeot intel_ring_advance(ring); 2545b5c29a34SFrançois Tigeot 2546b5c29a34SFrançois Tigeot return 0; 2547b5c29a34SFrançois Tigeot } 2548b5c29a34SFrançois Tigeot 2549b5c29a34SFrançois Tigeot static int 2550*71f41f3eSFrançois Tigeot gen6_emit_bb_start(struct drm_i915_gem_request *req, 2551ba55f2f5SFrançois Tigeot u64 offset, u32 len, 2552*71f41f3eSFrançois Tigeot unsigned int dispatch_flags) 2553b5c29a34SFrançois Tigeot { 2554*71f41f3eSFrançois Tigeot struct intel_ring *ring = req->ring; 2555b5c29a34SFrançois Tigeot int ret; 2556b5c29a34SFrançois Tigeot 2557a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 2); 2558b5c29a34SFrançois Tigeot if (ret) 2559b5c29a34SFrançois Tigeot return ret; 2560b5c29a34SFrançois Tigeot 2561*71f41f3eSFrançois Tigeot intel_ring_emit(ring, 2562b5c29a34SFrançois Tigeot MI_BATCH_BUFFER_START | 2563477eb7f9SFrançois Tigeot (dispatch_flags & I915_DISPATCH_SECURE ? 2564477eb7f9SFrançois Tigeot 0 : MI_BATCH_NON_SECURE_I965)); 2565e3adcf8fSFrançois Tigeot /* bit0-7 is the length on GEN6+ */ 2566*71f41f3eSFrançois Tigeot intel_ring_emit(ring, offset); 2567*71f41f3eSFrançois Tigeot intel_ring_advance(ring); 2568e3adcf8fSFrançois Tigeot 2569e3adcf8fSFrançois Tigeot return 0; 2570e3adcf8fSFrançois Tigeot } 2571e3adcf8fSFrançois Tigeot 2572e3adcf8fSFrançois Tigeot /* Blitter support (SandyBridge+) */ 2573e3adcf8fSFrançois Tigeot 2574*71f41f3eSFrançois Tigeot static int gen6_ring_flush(struct drm_i915_gem_request *req, u32 mode) 2575e3adcf8fSFrançois Tigeot { 2576*71f41f3eSFrançois Tigeot struct intel_ring *ring = req->ring; 2577e3adcf8fSFrançois Tigeot uint32_t cmd; 2578e3adcf8fSFrançois Tigeot int ret; 2579e3adcf8fSFrançois Tigeot 2580a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 4); 2581e3adcf8fSFrançois Tigeot if (ret) 2582e3adcf8fSFrançois Tigeot return ret; 2583e3adcf8fSFrançois Tigeot 2584e3adcf8fSFrançois Tigeot cmd = MI_FLUSH_DW; 25851487f786SFrançois Tigeot if (INTEL_GEN(req->i915) >= 8) 25869edbd4a0SFrançois Tigeot cmd += 1; 25872c9916cdSFrançois Tigeot 25882c9916cdSFrançois Tigeot /* We always require a command barrier so that subsequent 25892c9916cdSFrançois Tigeot * commands, such as breadcrumb interrupts, are strictly ordered 25902c9916cdSFrançois Tigeot * wrt the contents of the write cache being flushed to memory 25912c9916cdSFrançois Tigeot * (and thus being coherent from the CPU). 25922c9916cdSFrançois Tigeot */ 25932c9916cdSFrançois Tigeot cmd |= MI_FLUSH_DW_STORE_INDEX | MI_FLUSH_DW_OP_STOREDW; 25942c9916cdSFrançois Tigeot 2595b5c29a34SFrançois Tigeot /* 2596b5c29a34SFrançois Tigeot * Bspec vol 1c.3 - blitter engine command streamer: 2597b5c29a34SFrançois Tigeot * "If ENABLED, all TLBs will be invalidated once the flush 2598b5c29a34SFrançois Tigeot * operation is complete. This bit is only valid when the 2599b5c29a34SFrançois Tigeot * Post-Sync Operation field is a value of 1h or 3h." 2600b5c29a34SFrançois Tigeot */ 2601*71f41f3eSFrançois Tigeot if (mode & EMIT_INVALIDATE) 26022c9916cdSFrançois Tigeot cmd |= MI_INVALIDATE_TLB; 2603*71f41f3eSFrançois Tigeot intel_ring_emit(ring, cmd); 2604*71f41f3eSFrançois Tigeot intel_ring_emit(ring, 26058621f407SFrançois Tigeot I915_GEM_HWS_SCRATCH_ADDR | MI_FLUSH_DW_USE_GTT); 26061487f786SFrançois Tigeot if (INTEL_GEN(req->i915) >= 8) { 2607*71f41f3eSFrançois Tigeot intel_ring_emit(ring, 0); /* upper addr */ 2608*71f41f3eSFrançois Tigeot intel_ring_emit(ring, 0); /* value */ 26099edbd4a0SFrançois Tigeot } else { 2610*71f41f3eSFrançois Tigeot intel_ring_emit(ring, 0); 2611*71f41f3eSFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 26129edbd4a0SFrançois Tigeot } 2613*71f41f3eSFrançois Tigeot intel_ring_advance(ring); 26145d0b1887SFrançois Tigeot 2615e3adcf8fSFrançois Tigeot return 0; 2616e3adcf8fSFrançois Tigeot } 2617e3adcf8fSFrançois Tigeot 26181487f786SFrançois Tigeot static void intel_ring_init_semaphores(struct drm_i915_private *dev_priv, 26191487f786SFrançois Tigeot struct intel_engine_cs *engine) 26201487f786SFrançois Tigeot { 26211487f786SFrançois Tigeot struct drm_i915_gem_object *obj; 26221487f786SFrançois Tigeot int ret, i; 26231487f786SFrançois Tigeot 262487df8fc6SFrançois Tigeot if (!i915.semaphores) 26251487f786SFrançois Tigeot return; 26261487f786SFrançois Tigeot 26271487f786SFrançois Tigeot if (INTEL_GEN(dev_priv) >= 8 && !dev_priv->semaphore_obj) { 2628303bf270SFrançois Tigeot obj = i915_gem_object_create(&dev_priv->drm, 4096); 26291487f786SFrançois Tigeot if (IS_ERR(obj)) { 26301487f786SFrançois Tigeot DRM_ERROR("Failed to allocate semaphore bo. Disabling semaphores\n"); 26311487f786SFrançois Tigeot i915.semaphores = 0; 26321487f786SFrançois Tigeot } else { 26331487f786SFrançois Tigeot i915_gem_object_set_cache_level(obj, I915_CACHE_LLC); 2634*71f41f3eSFrançois Tigeot ret = i915_gem_object_ggtt_pin(obj, NULL, 0, 0, 0); 26351487f786SFrançois Tigeot if (ret != 0) { 263687df8fc6SFrançois Tigeot i915_gem_object_put(obj); 26371487f786SFrançois Tigeot DRM_ERROR("Failed to pin semaphore bo. Disabling semaphores\n"); 26381487f786SFrançois Tigeot i915.semaphores = 0; 26391487f786SFrançois Tigeot } else { 26401487f786SFrançois Tigeot dev_priv->semaphore_obj = obj; 26411487f786SFrançois Tigeot } 26421487f786SFrançois Tigeot } 26431487f786SFrançois Tigeot } 26441487f786SFrançois Tigeot 264587df8fc6SFrançois Tigeot if (!i915.semaphores) 26461487f786SFrançois Tigeot return; 26471487f786SFrançois Tigeot 26481487f786SFrançois Tigeot if (INTEL_GEN(dev_priv) >= 8) { 26491487f786SFrançois Tigeot u64 offset = i915_gem_obj_ggtt_offset(dev_priv->semaphore_obj); 26501487f786SFrançois Tigeot 2651*71f41f3eSFrançois Tigeot engine->semaphore.sync_to = gen8_ring_sync_to; 26521487f786SFrançois Tigeot engine->semaphore.signal = gen8_xcs_signal; 26531487f786SFrançois Tigeot 26541487f786SFrançois Tigeot for (i = 0; i < I915_NUM_ENGINES; i++) { 26551487f786SFrançois Tigeot u64 ring_offset; 26561487f786SFrançois Tigeot 26571487f786SFrançois Tigeot if (i != engine->id) 26581487f786SFrançois Tigeot ring_offset = offset + GEN8_SEMAPHORE_OFFSET(engine->id, i); 26591487f786SFrançois Tigeot else 26601487f786SFrançois Tigeot ring_offset = MI_SEMAPHORE_SYNC_INVALID; 26611487f786SFrançois Tigeot 26621487f786SFrançois Tigeot engine->semaphore.signal_ggtt[i] = ring_offset; 26631487f786SFrançois Tigeot } 26641487f786SFrançois Tigeot } else if (INTEL_GEN(dev_priv) >= 6) { 2665*71f41f3eSFrançois Tigeot engine->semaphore.sync_to = gen6_ring_sync_to; 26661487f786SFrançois Tigeot engine->semaphore.signal = gen6_signal; 26671487f786SFrançois Tigeot 26681487f786SFrançois Tigeot /* 26691487f786SFrançois Tigeot * The current semaphore is only applied on pre-gen8 26701487f786SFrançois Tigeot * platform. And there is no VCS2 ring on the pre-gen8 26711487f786SFrançois Tigeot * platform. So the semaphore between RCS and VCS2 is 26721487f786SFrançois Tigeot * initialized as INVALID. Gen8 will initialize the 26731487f786SFrançois Tigeot * sema between VCS2 and RCS later. 26741487f786SFrançois Tigeot */ 26751487f786SFrançois Tigeot for (i = 0; i < I915_NUM_ENGINES; i++) { 26761487f786SFrançois Tigeot static const struct { 26771487f786SFrançois Tigeot u32 wait_mbox; 26781487f786SFrançois Tigeot i915_reg_t mbox_reg; 26791487f786SFrançois Tigeot } sem_data[I915_NUM_ENGINES][I915_NUM_ENGINES] = { 26801487f786SFrançois Tigeot [RCS] = { 26811487f786SFrançois Tigeot [VCS] = { .wait_mbox = MI_SEMAPHORE_SYNC_RV, .mbox_reg = GEN6_VRSYNC }, 26821487f786SFrançois Tigeot [BCS] = { .wait_mbox = MI_SEMAPHORE_SYNC_RB, .mbox_reg = GEN6_BRSYNC }, 26831487f786SFrançois Tigeot [VECS] = { .wait_mbox = MI_SEMAPHORE_SYNC_RVE, .mbox_reg = GEN6_VERSYNC }, 26841487f786SFrançois Tigeot }, 26851487f786SFrançois Tigeot [VCS] = { 26861487f786SFrançois Tigeot [RCS] = { .wait_mbox = MI_SEMAPHORE_SYNC_VR, .mbox_reg = GEN6_RVSYNC }, 26871487f786SFrançois Tigeot [BCS] = { .wait_mbox = MI_SEMAPHORE_SYNC_VB, .mbox_reg = GEN6_BVSYNC }, 26881487f786SFrançois Tigeot [VECS] = { .wait_mbox = MI_SEMAPHORE_SYNC_VVE, .mbox_reg = GEN6_VEVSYNC }, 26891487f786SFrançois Tigeot }, 26901487f786SFrançois Tigeot [BCS] = { 26911487f786SFrançois Tigeot [RCS] = { .wait_mbox = MI_SEMAPHORE_SYNC_BR, .mbox_reg = GEN6_RBSYNC }, 26921487f786SFrançois Tigeot [VCS] = { .wait_mbox = MI_SEMAPHORE_SYNC_BV, .mbox_reg = GEN6_VBSYNC }, 26931487f786SFrançois Tigeot [VECS] = { .wait_mbox = MI_SEMAPHORE_SYNC_BVE, .mbox_reg = GEN6_VEBSYNC }, 26941487f786SFrançois Tigeot }, 26951487f786SFrançois Tigeot [VECS] = { 26961487f786SFrançois Tigeot [RCS] = { .wait_mbox = MI_SEMAPHORE_SYNC_VER, .mbox_reg = GEN6_RVESYNC }, 26971487f786SFrançois Tigeot [VCS] = { .wait_mbox = MI_SEMAPHORE_SYNC_VEV, .mbox_reg = GEN6_VVESYNC }, 26981487f786SFrançois Tigeot [BCS] = { .wait_mbox = MI_SEMAPHORE_SYNC_VEB, .mbox_reg = GEN6_BVESYNC }, 26991487f786SFrançois Tigeot }, 27001487f786SFrançois Tigeot }; 27011487f786SFrançois Tigeot u32 wait_mbox; 27021487f786SFrançois Tigeot i915_reg_t mbox_reg; 27031487f786SFrançois Tigeot 27041487f786SFrançois Tigeot if (i == engine->id || i == VCS2) { 27051487f786SFrançois Tigeot wait_mbox = MI_SEMAPHORE_SYNC_INVALID; 27061487f786SFrançois Tigeot mbox_reg = GEN6_NOSYNC; 27071487f786SFrançois Tigeot } else { 27081487f786SFrançois Tigeot wait_mbox = sem_data[engine->id][i].wait_mbox; 27091487f786SFrançois Tigeot mbox_reg = sem_data[engine->id][i].mbox_reg; 27101487f786SFrançois Tigeot } 27111487f786SFrançois Tigeot 27121487f786SFrançois Tigeot engine->semaphore.mbox.wait[i] = wait_mbox; 27131487f786SFrançois Tigeot engine->semaphore.mbox.signal[i] = mbox_reg; 27141487f786SFrançois Tigeot } 27151487f786SFrançois Tigeot } 27161487f786SFrançois Tigeot } 27171487f786SFrançois Tigeot 27181487f786SFrançois Tigeot static void intel_ring_init_irq(struct drm_i915_private *dev_priv, 27191487f786SFrançois Tigeot struct intel_engine_cs *engine) 27201487f786SFrançois Tigeot { 272187df8fc6SFrançois Tigeot engine->irq_enable_mask = GT_RENDER_USER_INTERRUPT << engine->irq_shift; 272287df8fc6SFrançois Tigeot 27231487f786SFrançois Tigeot if (INTEL_GEN(dev_priv) >= 8) { 2724303bf270SFrançois Tigeot engine->irq_enable = gen8_irq_enable; 2725303bf270SFrançois Tigeot engine->irq_disable = gen8_irq_disable; 27261487f786SFrançois Tigeot engine->irq_seqno_barrier = gen6_seqno_barrier; 27271487f786SFrançois Tigeot } else if (INTEL_GEN(dev_priv) >= 6) { 2728303bf270SFrançois Tigeot engine->irq_enable = gen6_irq_enable; 2729303bf270SFrançois Tigeot engine->irq_disable = gen6_irq_disable; 27301487f786SFrançois Tigeot engine->irq_seqno_barrier = gen6_seqno_barrier; 27311487f786SFrançois Tigeot } else if (INTEL_GEN(dev_priv) >= 5) { 2732303bf270SFrançois Tigeot engine->irq_enable = gen5_irq_enable; 2733303bf270SFrançois Tigeot engine->irq_disable = gen5_irq_disable; 2734303bf270SFrançois Tigeot engine->irq_seqno_barrier = gen5_seqno_barrier; 27351487f786SFrançois Tigeot } else if (INTEL_GEN(dev_priv) >= 3) { 2736303bf270SFrançois Tigeot engine->irq_enable = i9xx_irq_enable; 2737303bf270SFrançois Tigeot engine->irq_disable = i9xx_irq_disable; 27381487f786SFrançois Tigeot } else { 2739303bf270SFrançois Tigeot engine->irq_enable = i8xx_irq_enable; 2740303bf270SFrançois Tigeot engine->irq_disable = i8xx_irq_disable; 27411487f786SFrançois Tigeot } 27421487f786SFrançois Tigeot } 27431487f786SFrançois Tigeot 27441487f786SFrançois Tigeot static void intel_ring_default_vfuncs(struct drm_i915_private *dev_priv, 27451487f786SFrançois Tigeot struct intel_engine_cs *engine) 27461487f786SFrançois Tigeot { 27471487f786SFrançois Tigeot intel_ring_init_irq(dev_priv, engine); 27481487f786SFrançois Tigeot intel_ring_init_semaphores(dev_priv, engine); 2749*71f41f3eSFrançois Tigeot 2750*71f41f3eSFrançois Tigeot engine->init_hw = init_ring_common; 2751*71f41f3eSFrançois Tigeot 2752*71f41f3eSFrançois Tigeot engine->emit_request = i9xx_emit_request; 2753*71f41f3eSFrançois Tigeot if (i915.semaphores) 2754*71f41f3eSFrançois Tigeot engine->emit_request = gen6_sema_emit_request; 2755*71f41f3eSFrançois Tigeot engine->submit_request = i9xx_submit_request; 2756*71f41f3eSFrançois Tigeot 2757*71f41f3eSFrançois Tigeot if (INTEL_GEN(dev_priv) >= 8) 2758*71f41f3eSFrançois Tigeot engine->emit_bb_start = gen8_emit_bb_start; 2759*71f41f3eSFrançois Tigeot else if (INTEL_GEN(dev_priv) >= 6) 2760*71f41f3eSFrançois Tigeot engine->emit_bb_start = gen6_emit_bb_start; 2761*71f41f3eSFrançois Tigeot else if (INTEL_GEN(dev_priv) >= 4) 2762*71f41f3eSFrançois Tigeot engine->emit_bb_start = i965_emit_bb_start; 2763*71f41f3eSFrançois Tigeot else if (IS_I830(dev_priv) || IS_845G(dev_priv)) 2764*71f41f3eSFrançois Tigeot engine->emit_bb_start = i830_emit_bb_start; 2765*71f41f3eSFrançois Tigeot else 2766*71f41f3eSFrançois Tigeot engine->emit_bb_start = i915_emit_bb_start; 27671487f786SFrançois Tigeot } 27681487f786SFrançois Tigeot 276987df8fc6SFrançois Tigeot int intel_init_render_ring_buffer(struct intel_engine_cs *engine) 2770e3adcf8fSFrançois Tigeot { 277187df8fc6SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 277224edb884SFrançois Tigeot int ret; 2773e3adcf8fSFrançois Tigeot 27741487f786SFrançois Tigeot intel_ring_default_vfuncs(dev_priv, engine); 27752c9916cdSFrançois Tigeot 2776303bf270SFrançois Tigeot if (HAS_L3_DPF(dev_priv)) 2777303bf270SFrançois Tigeot engine->irq_keep_mask = GT_RENDER_L3_PARITY_ERROR_INTERRUPT; 2778303bf270SFrançois Tigeot 27791487f786SFrançois Tigeot if (INTEL_GEN(dev_priv) >= 8) { 27808621f407SFrançois Tigeot engine->init_context = intel_rcs_ctx_init; 2781*71f41f3eSFrançois Tigeot engine->emit_request = gen8_render_emit_request; 2782*71f41f3eSFrançois Tigeot engine->emit_flush = gen8_render_ring_flush; 278387df8fc6SFrançois Tigeot if (i915.semaphores) 27848621f407SFrançois Tigeot engine->semaphore.signal = gen8_rcs_signal; 27851487f786SFrançois Tigeot } else if (INTEL_GEN(dev_priv) >= 6) { 27868621f407SFrançois Tigeot engine->init_context = intel_rcs_ctx_init; 2787*71f41f3eSFrançois Tigeot engine->emit_flush = gen7_render_ring_flush; 27881487f786SFrançois Tigeot if (IS_GEN6(dev_priv)) 2789*71f41f3eSFrançois Tigeot engine->emit_flush = gen6_render_ring_flush; 27901487f786SFrançois Tigeot } else if (IS_GEN5(dev_priv)) { 2791*71f41f3eSFrançois Tigeot engine->emit_flush = gen4_render_ring_flush; 2792686a02f1SFrançois Tigeot } else { 27931487f786SFrançois Tigeot if (INTEL_GEN(dev_priv) < 4) 2794*71f41f3eSFrançois Tigeot engine->emit_flush = gen2_render_ring_flush; 2795686a02f1SFrançois Tigeot else 2796*71f41f3eSFrançois Tigeot engine->emit_flush = gen4_render_ring_flush; 27978621f407SFrançois Tigeot engine->irq_enable_mask = I915_USER_INTERRUPT; 2798686a02f1SFrançois Tigeot } 279924edb884SFrançois Tigeot 28001487f786SFrançois Tigeot if (IS_HASWELL(dev_priv)) 2801*71f41f3eSFrançois Tigeot engine->emit_bb_start = hsw_emit_bb_start; 28021487f786SFrançois Tigeot 28038621f407SFrançois Tigeot engine->init_hw = init_render_ring; 28048621f407SFrançois Tigeot engine->cleanup = render_ring_cleanup; 2805e3adcf8fSFrançois Tigeot 280687df8fc6SFrançois Tigeot ret = intel_init_ring_buffer(engine); 2807b5c29a34SFrançois Tigeot if (ret) 28082c9916cdSFrançois Tigeot return ret; 28092c9916cdSFrançois Tigeot 2810303bf270SFrançois Tigeot if (INTEL_GEN(dev_priv) >= 6) { 2811303bf270SFrançois Tigeot ret = intel_init_pipe_control(engine, 4096); 2812303bf270SFrançois Tigeot if (ret) 2813303bf270SFrançois Tigeot return ret; 2814303bf270SFrançois Tigeot } else if (HAS_BROKEN_CS_TLB(dev_priv)) { 2815303bf270SFrançois Tigeot ret = intel_init_pipe_control(engine, I830_WA_SIZE); 28162c9916cdSFrançois Tigeot if (ret) 28172c9916cdSFrançois Tigeot return ret; 2818b5c29a34SFrançois Tigeot } 2819b5c29a34SFrançois Tigeot 2820e3adcf8fSFrançois Tigeot return 0; 2821e3adcf8fSFrançois Tigeot } 2822e3adcf8fSFrançois Tigeot 282387df8fc6SFrançois Tigeot int intel_init_bsd_ring_buffer(struct intel_engine_cs *engine) 2824e3adcf8fSFrançois Tigeot { 282587df8fc6SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 2826686a02f1SFrançois Tigeot 28271487f786SFrançois Tigeot intel_ring_default_vfuncs(dev_priv, engine); 28281487f786SFrançois Tigeot 28291487f786SFrançois Tigeot if (INTEL_GEN(dev_priv) >= 6) { 2830686a02f1SFrançois Tigeot /* gen6 bsd needs a special wa for tail updates */ 28311487f786SFrançois Tigeot if (IS_GEN6(dev_priv)) 2832*71f41f3eSFrançois Tigeot engine->submit_request = gen6_bsd_submit_request; 2833*71f41f3eSFrançois Tigeot engine->emit_flush = gen6_bsd_ring_flush; 283487df8fc6SFrançois Tigeot if (INTEL_GEN(dev_priv) < 8) 28358621f407SFrançois Tigeot engine->irq_enable_mask = GT_BSD_USER_INTERRUPT; 2836686a02f1SFrançois Tigeot } else { 28378621f407SFrançois Tigeot engine->mmio_base = BSD_RING_BASE; 2838*71f41f3eSFrançois Tigeot engine->emit_flush = bsd_ring_flush; 28391487f786SFrançois Tigeot if (IS_GEN5(dev_priv)) 28408621f407SFrançois Tigeot engine->irq_enable_mask = ILK_BSD_USER_INTERRUPT; 28411487f786SFrançois Tigeot else 28428621f407SFrançois Tigeot engine->irq_enable_mask = I915_BSD_USER_INTERRUPT; 2843686a02f1SFrançois Tigeot } 2844e3adcf8fSFrançois Tigeot 284587df8fc6SFrançois Tigeot return intel_init_ring_buffer(engine); 2846e3adcf8fSFrançois Tigeot } 2847e3adcf8fSFrançois Tigeot 2848ba55f2f5SFrançois Tigeot /** 2849477eb7f9SFrançois Tigeot * Initialize the second BSD ring (eg. Broadwell GT3, Skylake GT3) 2850ba55f2f5SFrançois Tigeot */ 285187df8fc6SFrançois Tigeot int intel_init_bsd2_ring_buffer(struct intel_engine_cs *engine) 2852ba55f2f5SFrançois Tigeot { 285387df8fc6SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 28541487f786SFrançois Tigeot 28551487f786SFrançois Tigeot intel_ring_default_vfuncs(dev_priv, engine); 28561487f786SFrançois Tigeot 2857*71f41f3eSFrançois Tigeot engine->emit_flush = gen6_bsd_ring_flush; 2858ba55f2f5SFrançois Tigeot 285987df8fc6SFrançois Tigeot return intel_init_ring_buffer(engine); 2860ba55f2f5SFrançois Tigeot } 2861ba55f2f5SFrançois Tigeot 286287df8fc6SFrançois Tigeot int intel_init_blt_ring_buffer(struct intel_engine_cs *engine) 2863e3adcf8fSFrançois Tigeot { 286487df8fc6SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 28651487f786SFrançois Tigeot 28661487f786SFrançois Tigeot intel_ring_default_vfuncs(dev_priv, engine); 28671487f786SFrançois Tigeot 2868*71f41f3eSFrançois Tigeot engine->emit_flush = gen6_ring_flush; 286987df8fc6SFrançois Tigeot if (INTEL_GEN(dev_priv) < 8) 28708621f407SFrançois Tigeot engine->irq_enable_mask = GT_BLT_USER_INTERRUPT; 28715d0b1887SFrançois Tigeot 287287df8fc6SFrançois Tigeot return intel_init_ring_buffer(engine); 28735d0b1887SFrançois Tigeot } 28745d0b1887SFrançois Tigeot 287587df8fc6SFrançois Tigeot int intel_init_vebox_ring_buffer(struct intel_engine_cs *engine) 28765d0b1887SFrançois Tigeot { 287787df8fc6SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 28789edbd4a0SFrançois Tigeot 28791487f786SFrançois Tigeot intel_ring_default_vfuncs(dev_priv, engine); 28801487f786SFrançois Tigeot 2881*71f41f3eSFrançois Tigeot engine->emit_flush = gen6_ring_flush; 28821487f786SFrançois Tigeot 288387df8fc6SFrançois Tigeot if (INTEL_GEN(dev_priv) < 8) { 28848621f407SFrançois Tigeot engine->irq_enable_mask = PM_VEBOX_USER_INTERRUPT; 2885303bf270SFrançois Tigeot engine->irq_enable = hsw_vebox_irq_enable; 2886303bf270SFrançois Tigeot engine->irq_disable = hsw_vebox_irq_disable; 288724edb884SFrançois Tigeot } 2888e3adcf8fSFrançois Tigeot 288987df8fc6SFrançois Tigeot return intel_init_ring_buffer(engine); 2890e3adcf8fSFrançois Tigeot } 2891