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 42*a85cb24fSFrançois Tigeot static int __intel_ring_space(int head, int tail, int size) 43e3adcf8fSFrançois Tigeot { 442c9916cdSFrançois Tigeot int space = head - tail; 452c9916cdSFrançois Tigeot if (space <= 0) 46ba55f2f5SFrançois Tigeot space += size; 472c9916cdSFrançois Tigeot return space - I915_RING_FREE_SPACE; 482c9916cdSFrançois Tigeot } 492c9916cdSFrançois Tigeot 5071f41f3eSFrançois Tigeot void intel_ring_update_space(struct intel_ring *ring) 512c9916cdSFrançois Tigeot { 52*a85cb24fSFrançois Tigeot ring->space = __intel_ring_space(ring->head, ring->emit, ring->size); 539edbd4a0SFrançois Tigeot } 549edbd4a0SFrançois Tigeot 55e3adcf8fSFrançois Tigeot static int 5671f41f3eSFrançois Tigeot gen2_render_ring_flush(struct drm_i915_gem_request *req, u32 mode) 57686a02f1SFrançois Tigeot { 58*a85cb24fSFrançois Tigeot u32 cmd, *cs; 59686a02f1SFrançois Tigeot 60686a02f1SFrançois Tigeot cmd = MI_FLUSH; 61686a02f1SFrançois Tigeot 6271f41f3eSFrançois Tigeot if (mode & EMIT_INVALIDATE) 63686a02f1SFrançois Tigeot cmd |= MI_READ_FLUSH; 64686a02f1SFrançois Tigeot 65*a85cb24fSFrançois Tigeot cs = intel_ring_begin(req, 2); 66*a85cb24fSFrançois Tigeot if (IS_ERR(cs)) 67*a85cb24fSFrançois Tigeot return PTR_ERR(cs); 68686a02f1SFrançois Tigeot 69*a85cb24fSFrançois Tigeot *cs++ = cmd; 70*a85cb24fSFrançois Tigeot *cs++ = MI_NOOP; 71*a85cb24fSFrançois Tigeot intel_ring_advance(req, cs); 72686a02f1SFrançois Tigeot 73686a02f1SFrançois Tigeot return 0; 74686a02f1SFrançois Tigeot } 75686a02f1SFrançois Tigeot 76686a02f1SFrançois Tigeot static int 7771f41f3eSFrançois Tigeot gen4_render_ring_flush(struct drm_i915_gem_request *req, u32 mode) 78e3adcf8fSFrançois Tigeot { 79*a85cb24fSFrançois Tigeot u32 cmd, *cs; 80e3adcf8fSFrançois Tigeot 81e3adcf8fSFrançois Tigeot /* 82e3adcf8fSFrançois Tigeot * read/write caches: 83e3adcf8fSFrançois Tigeot * 84e3adcf8fSFrançois Tigeot * I915_GEM_DOMAIN_RENDER is always invalidated, but is 85e3adcf8fSFrançois Tigeot * only flushed if MI_NO_WRITE_FLUSH is unset. On 965, it is 86e3adcf8fSFrançois Tigeot * also flushed at 2d versus 3d pipeline switches. 87e3adcf8fSFrançois Tigeot * 88e3adcf8fSFrançois Tigeot * read-only caches: 89e3adcf8fSFrançois Tigeot * 90e3adcf8fSFrançois Tigeot * I915_GEM_DOMAIN_SAMPLER is flushed on pre-965 if 91e3adcf8fSFrançois Tigeot * MI_READ_FLUSH is set, and is always flushed on 965. 92e3adcf8fSFrançois Tigeot * 93e3adcf8fSFrançois Tigeot * I915_GEM_DOMAIN_COMMAND may not exist? 94e3adcf8fSFrançois Tigeot * 95e3adcf8fSFrançois Tigeot * I915_GEM_DOMAIN_INSTRUCTION, which exists on 965, is 96e3adcf8fSFrançois Tigeot * invalidated when MI_EXE_FLUSH is set. 97e3adcf8fSFrançois Tigeot * 98e3adcf8fSFrançois Tigeot * I915_GEM_DOMAIN_VERTEX, which exists on 965, is 99e3adcf8fSFrançois Tigeot * invalidated with every MI_FLUSH. 100e3adcf8fSFrançois Tigeot * 101e3adcf8fSFrançois Tigeot * TLBs: 102e3adcf8fSFrançois Tigeot * 103e3adcf8fSFrançois Tigeot * On 965, TLBs associated with I915_GEM_DOMAIN_COMMAND 104e3adcf8fSFrançois Tigeot * and I915_GEM_DOMAIN_CPU in are invalidated at PTE write and 105e3adcf8fSFrançois Tigeot * I915_GEM_DOMAIN_RENDER and I915_GEM_DOMAIN_SAMPLER 106e3adcf8fSFrançois Tigeot * are flushed at any MI_FLUSH. 107e3adcf8fSFrançois Tigeot */ 108e3adcf8fSFrançois Tigeot 10971f41f3eSFrançois Tigeot cmd = MI_FLUSH; 11071f41f3eSFrançois Tigeot if (mode & EMIT_INVALIDATE) { 111e3adcf8fSFrançois Tigeot cmd |= MI_EXE_FLUSH; 11271f41f3eSFrançois Tigeot if (IS_G4X(req->i915) || IS_GEN5(req->i915)) 113e3adcf8fSFrançois Tigeot cmd |= MI_INVALIDATE_ISP; 11471f41f3eSFrançois Tigeot } 115e3adcf8fSFrançois Tigeot 116*a85cb24fSFrançois Tigeot cs = intel_ring_begin(req, 2); 117*a85cb24fSFrançois Tigeot if (IS_ERR(cs)) 118*a85cb24fSFrançois Tigeot return PTR_ERR(cs); 119e3adcf8fSFrançois Tigeot 120*a85cb24fSFrançois Tigeot *cs++ = cmd; 121*a85cb24fSFrançois Tigeot *cs++ = MI_NOOP; 122*a85cb24fSFrançois Tigeot intel_ring_advance(req, cs); 123e3adcf8fSFrançois Tigeot 124e3adcf8fSFrançois Tigeot return 0; 125e3adcf8fSFrançois Tigeot } 126e3adcf8fSFrançois Tigeot 127e3adcf8fSFrançois Tigeot /** 128e3adcf8fSFrançois Tigeot * Emits a PIPE_CONTROL with a non-zero post-sync operation, for 129e3adcf8fSFrançois Tigeot * implementing two workarounds on gen6. From section 1.4.7.1 130e3adcf8fSFrançois Tigeot * "PIPE_CONTROL" of the Sandy Bridge PRM volume 2 part 1: 131e3adcf8fSFrançois Tigeot * 132e3adcf8fSFrançois Tigeot * [DevSNB-C+{W/A}] Before any depth stall flush (including those 133e3adcf8fSFrançois Tigeot * produced by non-pipelined state commands), software needs to first 134e3adcf8fSFrançois Tigeot * send a PIPE_CONTROL with no bits set except Post-Sync Operation != 135e3adcf8fSFrançois Tigeot * 0. 136e3adcf8fSFrançois Tigeot * 137e3adcf8fSFrançois Tigeot * [Dev-SNB{W/A}]: Before a PIPE_CONTROL with Write Cache Flush Enable 138e3adcf8fSFrançois Tigeot * =1, a PIPE_CONTROL with any non-zero post-sync-op is required. 139e3adcf8fSFrançois Tigeot * 140e3adcf8fSFrançois Tigeot * And the workaround for these two requires this workaround first: 141e3adcf8fSFrançois Tigeot * 142e3adcf8fSFrançois Tigeot * [Dev-SNB{W/A}]: Pipe-control with CS-stall bit set must be sent 143e3adcf8fSFrançois Tigeot * BEFORE the pipe-control with a post-sync op and no write-cache 144e3adcf8fSFrançois Tigeot * flushes. 145e3adcf8fSFrançois Tigeot * 146e3adcf8fSFrançois Tigeot * And this last workaround is tricky because of the requirements on 147e3adcf8fSFrançois Tigeot * that bit. From section 1.4.7.2.3 "Stall" of the Sandy Bridge PRM 148e3adcf8fSFrançois Tigeot * volume 2 part 1: 149e3adcf8fSFrançois Tigeot * 150e3adcf8fSFrançois Tigeot * "1 of the following must also be set: 151e3adcf8fSFrançois Tigeot * - Render Target Cache Flush Enable ([12] of DW1) 152e3adcf8fSFrançois Tigeot * - Depth Cache Flush Enable ([0] of DW1) 153e3adcf8fSFrançois Tigeot * - Stall at Pixel Scoreboard ([1] of DW1) 154e3adcf8fSFrançois Tigeot * - Depth Stall ([13] of DW1) 155e3adcf8fSFrançois Tigeot * - Post-Sync Operation ([13] of DW1) 156e3adcf8fSFrançois Tigeot * - Notify Enable ([8] of DW1)" 157e3adcf8fSFrançois Tigeot * 158e3adcf8fSFrançois Tigeot * The cache flushes require the workaround flush that triggered this 159e3adcf8fSFrançois Tigeot * one, so we can't use it. Depth stall would trigger the same. 160e3adcf8fSFrançois Tigeot * Post-sync nonzero is what triggered this second workaround, so we 161e3adcf8fSFrançois Tigeot * can't use that one either. Notify enable is IRQs, which aren't 162e3adcf8fSFrançois Tigeot * really our business. That leaves only stall at scoreboard. 163e3adcf8fSFrançois Tigeot */ 164e3adcf8fSFrançois Tigeot static int 165a05eeebfSFrançois Tigeot intel_emit_post_sync_nonzero_flush(struct drm_i915_gem_request *req) 166e3adcf8fSFrançois Tigeot { 16771f41f3eSFrançois Tigeot u32 scratch_addr = 1681e12ee3bSFrançois Tigeot i915_ggtt_offset(req->engine->scratch) + 2 * CACHELINE_BYTES; 169*a85cb24fSFrançois Tigeot u32 *cs; 170e3adcf8fSFrançois Tigeot 171*a85cb24fSFrançois Tigeot cs = intel_ring_begin(req, 6); 172*a85cb24fSFrançois Tigeot if (IS_ERR(cs)) 173*a85cb24fSFrançois Tigeot return PTR_ERR(cs); 174e3adcf8fSFrançois Tigeot 175*a85cb24fSFrançois Tigeot *cs++ = GFX_OP_PIPE_CONTROL(5); 176*a85cb24fSFrançois Tigeot *cs++ = PIPE_CONTROL_CS_STALL | PIPE_CONTROL_STALL_AT_SCOREBOARD; 177*a85cb24fSFrançois Tigeot *cs++ = scratch_addr | PIPE_CONTROL_GLOBAL_GTT; 178*a85cb24fSFrançois Tigeot *cs++ = 0; /* low dword */ 179*a85cb24fSFrançois Tigeot *cs++ = 0; /* high dword */ 180*a85cb24fSFrançois Tigeot *cs++ = MI_NOOP; 181*a85cb24fSFrançois Tigeot intel_ring_advance(req, cs); 182e3adcf8fSFrançois Tigeot 183*a85cb24fSFrançois Tigeot cs = intel_ring_begin(req, 6); 184*a85cb24fSFrançois Tigeot if (IS_ERR(cs)) 185*a85cb24fSFrançois Tigeot return PTR_ERR(cs); 186e3adcf8fSFrançois Tigeot 187*a85cb24fSFrançois Tigeot *cs++ = GFX_OP_PIPE_CONTROL(5); 188*a85cb24fSFrançois Tigeot *cs++ = PIPE_CONTROL_QW_WRITE; 189*a85cb24fSFrançois Tigeot *cs++ = scratch_addr | PIPE_CONTROL_GLOBAL_GTT; 190*a85cb24fSFrançois Tigeot *cs++ = 0; 191*a85cb24fSFrançois Tigeot *cs++ = 0; 192*a85cb24fSFrançois Tigeot *cs++ = MI_NOOP; 193*a85cb24fSFrançois Tigeot intel_ring_advance(req, cs); 194e3adcf8fSFrançois Tigeot 195e3adcf8fSFrançois Tigeot return 0; 196e3adcf8fSFrançois Tigeot } 197e3adcf8fSFrançois Tigeot 198e3adcf8fSFrançois Tigeot static int 19971f41f3eSFrançois Tigeot gen6_render_ring_flush(struct drm_i915_gem_request *req, u32 mode) 200e3adcf8fSFrançois Tigeot { 20171f41f3eSFrançois Tigeot u32 scratch_addr = 2021e12ee3bSFrançois Tigeot i915_ggtt_offset(req->engine->scratch) + 2 * CACHELINE_BYTES; 203*a85cb24fSFrançois Tigeot u32 *cs, flags = 0; 204e3adcf8fSFrançois Tigeot int ret; 205e3adcf8fSFrançois Tigeot 206e3adcf8fSFrançois Tigeot /* Force SNB workarounds for PIPE_CONTROL flushes */ 207a05eeebfSFrançois Tigeot ret = intel_emit_post_sync_nonzero_flush(req); 208686a02f1SFrançois Tigeot if (ret) 209686a02f1SFrançois Tigeot return ret; 210e3adcf8fSFrançois Tigeot 211e3adcf8fSFrançois Tigeot /* Just flush everything. Experiments have shown that reducing the 212e3adcf8fSFrançois Tigeot * number of bits based on the write domains has little performance 213e3adcf8fSFrançois Tigeot * impact. 214e3adcf8fSFrançois Tigeot */ 21571f41f3eSFrançois Tigeot if (mode & EMIT_FLUSH) { 216e3adcf8fSFrançois Tigeot flags |= PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH; 217b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_DEPTH_CACHE_FLUSH; 218b5c29a34SFrançois Tigeot /* 219b5c29a34SFrançois Tigeot * Ensure that any following seqno writes only happen 220b5c29a34SFrançois Tigeot * when the render cache is indeed flushed. 221b5c29a34SFrançois Tigeot */ 222b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_CS_STALL; 223b5c29a34SFrançois Tigeot } 22471f41f3eSFrançois Tigeot if (mode & EMIT_INVALIDATE) { 225686a02f1SFrançois Tigeot flags |= PIPE_CONTROL_TLB_INVALIDATE; 226e3adcf8fSFrançois Tigeot flags |= PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE; 227e3adcf8fSFrançois Tigeot flags |= PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE; 228e3adcf8fSFrançois Tigeot flags |= PIPE_CONTROL_VF_CACHE_INVALIDATE; 229e3adcf8fSFrançois Tigeot flags |= PIPE_CONTROL_CONST_CACHE_INVALIDATE; 230e3adcf8fSFrançois Tigeot flags |= PIPE_CONTROL_STATE_CACHE_INVALIDATE; 231686a02f1SFrançois Tigeot /* 232b5c29a34SFrançois Tigeot * TLB invalidate requires a post-sync write. 233686a02f1SFrançois Tigeot */ 234b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_QW_WRITE | PIPE_CONTROL_CS_STALL; 235b5c29a34SFrançois Tigeot } 236e3adcf8fSFrançois Tigeot 237*a85cb24fSFrançois Tigeot cs = intel_ring_begin(req, 4); 238*a85cb24fSFrançois Tigeot if (IS_ERR(cs)) 239*a85cb24fSFrançois Tigeot return PTR_ERR(cs); 240e3adcf8fSFrançois Tigeot 241*a85cb24fSFrançois Tigeot *cs++ = GFX_OP_PIPE_CONTROL(4); 242*a85cb24fSFrançois Tigeot *cs++ = flags; 243*a85cb24fSFrançois Tigeot *cs++ = scratch_addr | PIPE_CONTROL_GLOBAL_GTT; 244*a85cb24fSFrançois Tigeot *cs++ = 0; 245*a85cb24fSFrançois Tigeot intel_ring_advance(req, cs); 246b5c29a34SFrançois Tigeot 247b5c29a34SFrançois Tigeot return 0; 248b5c29a34SFrançois Tigeot } 249b5c29a34SFrançois Tigeot 250b5c29a34SFrançois Tigeot static int 251a05eeebfSFrançois Tigeot gen7_render_ring_cs_stall_wa(struct drm_i915_gem_request *req) 252b5c29a34SFrançois Tigeot { 253*a85cb24fSFrançois Tigeot u32 *cs; 254b5c29a34SFrançois Tigeot 255*a85cb24fSFrançois Tigeot cs = intel_ring_begin(req, 4); 256*a85cb24fSFrançois Tigeot if (IS_ERR(cs)) 257*a85cb24fSFrançois Tigeot return PTR_ERR(cs); 258b5c29a34SFrançois Tigeot 259*a85cb24fSFrançois Tigeot *cs++ = GFX_OP_PIPE_CONTROL(4); 260*a85cb24fSFrançois Tigeot *cs++ = PIPE_CONTROL_CS_STALL | PIPE_CONTROL_STALL_AT_SCOREBOARD; 261*a85cb24fSFrançois Tigeot *cs++ = 0; 262*a85cb24fSFrançois Tigeot *cs++ = 0; 263*a85cb24fSFrançois Tigeot intel_ring_advance(req, cs); 264b5c29a34SFrançois Tigeot 265b5c29a34SFrançois Tigeot return 0; 266b5c29a34SFrançois Tigeot } 267b5c29a34SFrançois Tigeot 268b5c29a34SFrançois Tigeot static int 26971f41f3eSFrançois Tigeot gen7_render_ring_flush(struct drm_i915_gem_request *req, u32 mode) 270b5c29a34SFrançois Tigeot { 27171f41f3eSFrançois Tigeot u32 scratch_addr = 2721e12ee3bSFrançois Tigeot i915_ggtt_offset(req->engine->scratch) + 2 * CACHELINE_BYTES; 273*a85cb24fSFrançois Tigeot u32 *cs, flags = 0; 274b5c29a34SFrançois Tigeot 275b5c29a34SFrançois Tigeot /* 276b5c29a34SFrançois Tigeot * Ensure that any following seqno writes only happen when the render 277b5c29a34SFrançois Tigeot * cache is indeed flushed. 278b5c29a34SFrançois Tigeot * 279b5c29a34SFrançois Tigeot * Workaround: 4th PIPE_CONTROL command (except the ones with only 280b5c29a34SFrançois Tigeot * read-cache invalidate bits set) must have the CS_STALL bit set. We 281b5c29a34SFrançois Tigeot * don't try to be clever and just set it unconditionally. 282b5c29a34SFrançois Tigeot */ 283b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_CS_STALL; 284b5c29a34SFrançois Tigeot 285b5c29a34SFrançois Tigeot /* Just flush everything. Experiments have shown that reducing the 286b5c29a34SFrançois Tigeot * number of bits based on the write domains has little performance 287b5c29a34SFrançois Tigeot * impact. 288b5c29a34SFrançois Tigeot */ 28971f41f3eSFrançois Tigeot if (mode & EMIT_FLUSH) { 290b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH; 291b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_DEPTH_CACHE_FLUSH; 292aee94f86SFrançois Tigeot flags |= PIPE_CONTROL_DC_FLUSH_ENABLE; 293b49c8cf9SFrançois Tigeot flags |= PIPE_CONTROL_FLUSH_ENABLE; 294b5c29a34SFrançois Tigeot } 29571f41f3eSFrançois Tigeot if (mode & EMIT_INVALIDATE) { 296b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_TLB_INVALIDATE; 297b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE; 298b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE; 299b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_VF_CACHE_INVALIDATE; 300b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_CONST_CACHE_INVALIDATE; 301b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_STATE_CACHE_INVALIDATE; 3022c9916cdSFrançois Tigeot flags |= PIPE_CONTROL_MEDIA_STATE_CLEAR; 303b5c29a34SFrançois Tigeot /* 304b5c29a34SFrançois Tigeot * TLB invalidate requires a post-sync write. 305b5c29a34SFrançois Tigeot */ 306b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_QW_WRITE; 307a2fdbec6SFrançois Tigeot flags |= PIPE_CONTROL_GLOBAL_GTT_IVB; 308b5c29a34SFrançois Tigeot 3090dbf0ea8SMatthew Dillon flags |= PIPE_CONTROL_STALL_AT_SCOREBOARD; 3100dbf0ea8SMatthew Dillon 311b5c29a34SFrançois Tigeot /* Workaround: we must issue a pipe_control with CS-stall bit 312b5c29a34SFrançois Tigeot * set before a pipe_control command that has the state cache 313b5c29a34SFrançois Tigeot * invalidate bit set. */ 314a05eeebfSFrançois Tigeot gen7_render_ring_cs_stall_wa(req); 315b5c29a34SFrançois Tigeot } 316b5c29a34SFrançois Tigeot 317*a85cb24fSFrançois Tigeot cs = intel_ring_begin(req, 4); 318*a85cb24fSFrançois Tigeot if (IS_ERR(cs)) 319*a85cb24fSFrançois Tigeot return PTR_ERR(cs); 320b5c29a34SFrançois Tigeot 321*a85cb24fSFrançois Tigeot *cs++ = GFX_OP_PIPE_CONTROL(4); 322*a85cb24fSFrançois Tigeot *cs++ = flags; 323*a85cb24fSFrançois Tigeot *cs++ = scratch_addr; 324*a85cb24fSFrançois Tigeot *cs++ = 0; 325*a85cb24fSFrançois Tigeot intel_ring_advance(req, cs); 32624edb884SFrançois Tigeot 32724edb884SFrançois Tigeot return 0; 32824edb884SFrançois Tigeot } 32924edb884SFrançois Tigeot 33024edb884SFrançois Tigeot static int 33171f41f3eSFrançois Tigeot gen8_render_ring_flush(struct drm_i915_gem_request *req, u32 mode) 3329edbd4a0SFrançois Tigeot { 333*a85cb24fSFrançois Tigeot u32 flags; 334*a85cb24fSFrançois Tigeot u32 *cs; 3359edbd4a0SFrançois Tigeot 336*a85cb24fSFrançois Tigeot cs = intel_ring_begin(req, mode & EMIT_INVALIDATE ? 12 : 6); 337*a85cb24fSFrançois Tigeot if (IS_ERR(cs)) 338*a85cb24fSFrançois Tigeot return PTR_ERR(cs); 339*a85cb24fSFrançois Tigeot 340*a85cb24fSFrançois Tigeot flags = PIPE_CONTROL_CS_STALL; 3419edbd4a0SFrançois Tigeot 34271f41f3eSFrançois Tigeot if (mode & EMIT_FLUSH) { 3439edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH; 3449edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_DEPTH_CACHE_FLUSH; 345aee94f86SFrançois Tigeot flags |= PIPE_CONTROL_DC_FLUSH_ENABLE; 346b49c8cf9SFrançois Tigeot flags |= PIPE_CONTROL_FLUSH_ENABLE; 3479edbd4a0SFrançois Tigeot } 34871f41f3eSFrançois Tigeot if (mode & EMIT_INVALIDATE) { 3499edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_TLB_INVALIDATE; 3509edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE; 3519edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE; 3529edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_VF_CACHE_INVALIDATE; 3539edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_CONST_CACHE_INVALIDATE; 3549edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_STATE_CACHE_INVALIDATE; 3559edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_QW_WRITE; 3569edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_GLOBAL_GTT_IVB; 3579edbd4a0SFrançois Tigeot 35824edb884SFrançois Tigeot /* WaCsStallBeforeStateCacheInvalidate:bdw,chv */ 359*a85cb24fSFrançois Tigeot cs = gen8_emit_pipe_control(cs, 36024edb884SFrançois Tigeot PIPE_CONTROL_CS_STALL | 36124edb884SFrançois Tigeot PIPE_CONTROL_STALL_AT_SCOREBOARD, 36224edb884SFrançois Tigeot 0); 36324edb884SFrançois Tigeot } 3649edbd4a0SFrançois Tigeot 365*a85cb24fSFrançois Tigeot cs = gen8_emit_pipe_control(cs, flags, 366*a85cb24fSFrançois Tigeot i915_ggtt_offset(req->engine->scratch) + 367*a85cb24fSFrançois Tigeot 2 * CACHELINE_BYTES); 368*a85cb24fSFrançois Tigeot 369*a85cb24fSFrançois Tigeot intel_ring_advance(req, cs); 370*a85cb24fSFrançois Tigeot 371*a85cb24fSFrançois Tigeot return 0; 3729edbd4a0SFrançois Tigeot } 3739edbd4a0SFrançois Tigeot 3748621f407SFrançois Tigeot static void ring_setup_phys_status_page(struct intel_engine_cs *engine) 3755d0b1887SFrançois Tigeot { 3761487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 3775d0b1887SFrançois Tigeot u32 addr; 3785d0b1887SFrançois Tigeot 3795d0b1887SFrançois Tigeot addr = dev_priv->status_page_dmah->busaddr; 3801487f786SFrançois Tigeot if (INTEL_GEN(dev_priv) >= 4) 3815d0b1887SFrançois Tigeot addr |= (dev_priv->status_page_dmah->busaddr >> 28) & 0xf0; 3825d0b1887SFrançois Tigeot I915_WRITE(HWS_PGA, addr); 3835d0b1887SFrançois Tigeot } 3845d0b1887SFrançois Tigeot 3858621f407SFrançois Tigeot static void intel_ring_setup_status_page(struct intel_engine_cs *engine) 386477eb7f9SFrançois Tigeot { 3871487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 388aee94f86SFrançois Tigeot i915_reg_t mmio; 389477eb7f9SFrançois Tigeot 390477eb7f9SFrançois Tigeot /* The ring status page addresses are no longer next to the rest of 391477eb7f9SFrançois Tigeot * the ring registers as of gen7. 392477eb7f9SFrançois Tigeot */ 3931487f786SFrançois Tigeot if (IS_GEN7(dev_priv)) { 3948621f407SFrançois Tigeot switch (engine->id) { 395477eb7f9SFrançois Tigeot case RCS: 396477eb7f9SFrançois Tigeot mmio = RENDER_HWS_PGA_GEN7; 397477eb7f9SFrançois Tigeot break; 398477eb7f9SFrançois Tigeot case BCS: 399477eb7f9SFrançois Tigeot mmio = BLT_HWS_PGA_GEN7; 400477eb7f9SFrançois Tigeot break; 401477eb7f9SFrançois Tigeot /* 402477eb7f9SFrançois Tigeot * VCS2 actually doesn't exist on Gen7. Only shut up 403477eb7f9SFrançois Tigeot * gcc switch check warning 404477eb7f9SFrançois Tigeot */ 405477eb7f9SFrançois Tigeot case VCS2: 406477eb7f9SFrançois Tigeot case VCS: 407477eb7f9SFrançois Tigeot mmio = BSD_HWS_PGA_GEN7; 408477eb7f9SFrançois Tigeot break; 409477eb7f9SFrançois Tigeot case VECS: 410477eb7f9SFrançois Tigeot mmio = VEBOX_HWS_PGA_GEN7; 411477eb7f9SFrançois Tigeot break; 412477eb7f9SFrançois Tigeot } 4131487f786SFrançois Tigeot } else if (IS_GEN6(dev_priv)) { 4148621f407SFrançois Tigeot mmio = RING_HWS_PGA_GEN6(engine->mmio_base); 415477eb7f9SFrançois Tigeot } else { 416477eb7f9SFrançois Tigeot /* XXX: gen8 returns to sanity */ 4178621f407SFrançois Tigeot mmio = RING_HWS_PGA(engine->mmio_base); 418477eb7f9SFrançois Tigeot } 419477eb7f9SFrançois Tigeot 4201e12ee3bSFrançois Tigeot I915_WRITE(mmio, engine->status_page.ggtt_offset); 421477eb7f9SFrançois Tigeot POSTING_READ(mmio); 422477eb7f9SFrançois Tigeot 423477eb7f9SFrançois Tigeot /* 424477eb7f9SFrançois Tigeot * Flush the TLB for this page 425477eb7f9SFrançois Tigeot * 426477eb7f9SFrançois Tigeot * FIXME: These two bits have disappeared on gen8, so a question 427477eb7f9SFrançois Tigeot * arises: do we still need this and if so how should we go about 428477eb7f9SFrançois Tigeot * invalidating the TLB? 429477eb7f9SFrançois Tigeot */ 4301487f786SFrançois Tigeot if (IS_GEN(dev_priv, 6, 7)) { 4318621f407SFrançois Tigeot i915_reg_t reg = RING_INSTPM(engine->mmio_base); 432477eb7f9SFrançois Tigeot 433477eb7f9SFrançois Tigeot /* ring should be idle before issuing a sync flush*/ 4348621f407SFrançois Tigeot WARN_ON((I915_READ_MODE(engine) & MODE_IDLE) == 0); 435477eb7f9SFrançois Tigeot 436477eb7f9SFrançois Tigeot I915_WRITE(reg, 437477eb7f9SFrançois Tigeot _MASKED_BIT_ENABLE(INSTPM_TLB_INVALIDATE | 438477eb7f9SFrançois Tigeot INSTPM_SYNC_FLUSH)); 4391487f786SFrançois Tigeot if (intel_wait_for_register(dev_priv, 4401487f786SFrançois Tigeot reg, INSTPM_SYNC_FLUSH, 0, 441477eb7f9SFrançois Tigeot 1000)) 442477eb7f9SFrançois Tigeot DRM_ERROR("%s: wait for SyncFlush to complete for TLB invalidation timed out\n", 4438621f407SFrançois Tigeot engine->name); 444477eb7f9SFrançois Tigeot } 445477eb7f9SFrançois Tigeot } 446477eb7f9SFrançois Tigeot 4478621f407SFrançois Tigeot static bool stop_ring(struct intel_engine_cs *engine) 448e3adcf8fSFrançois Tigeot { 4491487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 450e3adcf8fSFrançois Tigeot 4511e12ee3bSFrançois Tigeot if (INTEL_GEN(dev_priv) > 2) { 4528621f407SFrançois Tigeot I915_WRITE_MODE(engine, _MASKED_BIT_ENABLE(STOP_RING)); 4531487f786SFrançois Tigeot if (intel_wait_for_register(dev_priv, 4541487f786SFrançois Tigeot RING_MI_MODE(engine->mmio_base), 4551487f786SFrançois Tigeot MODE_IDLE, 4561487f786SFrançois Tigeot MODE_IDLE, 4571487f786SFrançois Tigeot 1000)) { 4588621f407SFrançois Tigeot DRM_ERROR("%s : timed out trying to stop ring\n", 4598621f407SFrançois Tigeot engine->name); 4601b13d190SFrançois Tigeot /* Sometimes we observe that the idle flag is not 4611b13d190SFrançois Tigeot * set even though the ring is empty. So double 4621b13d190SFrançois Tigeot * check before giving up. 4631b13d190SFrançois Tigeot */ 4648621f407SFrançois Tigeot if (I915_READ_HEAD(engine) != I915_READ_TAIL(engine)) 465ba55f2f5SFrançois Tigeot return false; 466ba55f2f5SFrançois Tigeot } 467ba55f2f5SFrançois Tigeot } 468686a02f1SFrançois Tigeot 4698621f407SFrançois Tigeot I915_WRITE_CTL(engine, 0); 4708621f407SFrançois Tigeot I915_WRITE_HEAD(engine, 0); 47171f41f3eSFrançois Tigeot I915_WRITE_TAIL(engine, 0); 472e3adcf8fSFrançois Tigeot 4731e12ee3bSFrançois Tigeot if (INTEL_GEN(dev_priv) > 2) { 4748621f407SFrançois Tigeot (void)I915_READ_CTL(engine); 4758621f407SFrançois Tigeot I915_WRITE_MODE(engine, _MASKED_BIT_DISABLE(STOP_RING)); 476ba55f2f5SFrançois Tigeot } 477e3adcf8fSFrançois Tigeot 4788621f407SFrançois Tigeot return (I915_READ_HEAD(engine) & HEAD_ADDR) == 0; 479ba55f2f5SFrançois Tigeot } 480ba55f2f5SFrançois Tigeot 4818621f407SFrançois Tigeot static int init_ring_common(struct intel_engine_cs *engine) 4828621f407SFrançois Tigeot { 4831487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 48471f41f3eSFrançois Tigeot struct intel_ring *ring = engine->buffer; 485ba55f2f5SFrançois Tigeot int ret = 0; 486ba55f2f5SFrançois Tigeot 4872c9916cdSFrançois Tigeot intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL); 488ba55f2f5SFrançois Tigeot 4898621f407SFrançois Tigeot if (!stop_ring(engine)) { 490ba55f2f5SFrançois Tigeot /* G45 ring initialization often fails to reset head to zero */ 491b5c29a34SFrançois Tigeot DRM_DEBUG_KMS("%s head not reset to zero " 492e3adcf8fSFrançois Tigeot "ctl %08x head %08x tail %08x start %08x\n", 4938621f407SFrançois Tigeot engine->name, 4948621f407SFrançois Tigeot I915_READ_CTL(engine), 4958621f407SFrançois Tigeot I915_READ_HEAD(engine), 4968621f407SFrançois Tigeot I915_READ_TAIL(engine), 4978621f407SFrançois Tigeot I915_READ_START(engine)); 498e3adcf8fSFrançois Tigeot 4998621f407SFrançois Tigeot if (!stop_ring(engine)) { 500e3adcf8fSFrançois Tigeot DRM_ERROR("failed to set %s head to zero " 501e3adcf8fSFrançois Tigeot "ctl %08x head %08x tail %08x start %08x\n", 5028621f407SFrançois Tigeot engine->name, 5038621f407SFrançois Tigeot I915_READ_CTL(engine), 5048621f407SFrançois Tigeot I915_READ_HEAD(engine), 5058621f407SFrançois Tigeot I915_READ_TAIL(engine), 5068621f407SFrançois Tigeot I915_READ_START(engine)); 507686a02f1SFrançois Tigeot ret = -EIO; 508686a02f1SFrançois Tigeot goto out; 509e3adcf8fSFrançois Tigeot } 510ba55f2f5SFrançois Tigeot } 511ba55f2f5SFrançois Tigeot 5121e12ee3bSFrançois Tigeot if (HWS_NEEDS_PHYSICAL(dev_priv)) 5138621f407SFrançois Tigeot ring_setup_phys_status_page(engine); 5141e12ee3bSFrançois Tigeot else 5151e12ee3bSFrançois Tigeot intel_ring_setup_status_page(engine); 5161e12ee3bSFrançois Tigeot 5171e12ee3bSFrançois Tigeot intel_engine_reset_breadcrumbs(engine); 518ba55f2f5SFrançois Tigeot 5190f370975SMatthew Dillon /* Enforce ordering by reading HEAD register back */ 5208621f407SFrançois Tigeot I915_READ_HEAD(engine); 5210f370975SMatthew Dillon 522ba55f2f5SFrançois Tigeot /* Initialize the ring. This must happen _after_ we've cleared the ring 523ba55f2f5SFrançois Tigeot * registers with the above sequence (the readback of the HEAD registers 524ba55f2f5SFrançois Tigeot * also enforces ordering), otherwise the hw might lose the new ring 525ba55f2f5SFrançois Tigeot * register values. */ 5261e12ee3bSFrançois Tigeot I915_WRITE_START(engine, i915_ggtt_offset(ring->vma)); 5271b13d190SFrançois Tigeot 5281b13d190SFrançois Tigeot /* WaClearRingBufHeadRegAtInit:ctg,elk */ 5298621f407SFrançois Tigeot if (I915_READ_HEAD(engine)) 5301b13d190SFrançois Tigeot DRM_DEBUG("%s initialization failed [head=%08x], fudging\n", 5318621f407SFrançois Tigeot engine->name, I915_READ_HEAD(engine)); 5321b13d190SFrançois Tigeot 5331e12ee3bSFrançois Tigeot intel_ring_update_space(ring); 5341e12ee3bSFrançois Tigeot I915_WRITE_HEAD(engine, ring->head); 5351e12ee3bSFrançois Tigeot I915_WRITE_TAIL(engine, ring->tail); 5361e12ee3bSFrançois Tigeot (void)I915_READ_TAIL(engine); 5371e12ee3bSFrançois Tigeot 5381e12ee3bSFrançois Tigeot I915_WRITE_CTL(engine, RING_CTL_SIZE(ring->size) | RING_VALID); 539ba55f2f5SFrançois Tigeot 540ba55f2f5SFrançois Tigeot /* If the head is still not zero, the ring is dead */ 5411e12ee3bSFrançois Tigeot if (intel_wait_for_register_fw(dev_priv, RING_CTL(engine->mmio_base), 5421e12ee3bSFrançois Tigeot RING_VALID, RING_VALID, 5431e12ee3bSFrançois Tigeot 50)) { 544ba55f2f5SFrançois Tigeot DRM_ERROR("%s initialization failed " 5451e12ee3bSFrançois Tigeot "ctl %08x (valid? %d) head %08x [%08x] tail %08x [%08x] start %08x [expected %08x]\n", 5468621f407SFrançois Tigeot engine->name, 5478621f407SFrançois Tigeot I915_READ_CTL(engine), 5488621f407SFrançois Tigeot I915_READ_CTL(engine) & RING_VALID, 5491e12ee3bSFrançois Tigeot I915_READ_HEAD(engine), ring->head, 5501e12ee3bSFrançois Tigeot I915_READ_TAIL(engine), ring->tail, 5518621f407SFrançois Tigeot I915_READ_START(engine), 5521e12ee3bSFrançois Tigeot i915_ggtt_offset(ring->vma)); 553ba55f2f5SFrançois Tigeot ret = -EIO; 554ba55f2f5SFrançois Tigeot goto out; 555ba55f2f5SFrançois Tigeot } 556e3adcf8fSFrançois Tigeot 5578621f407SFrançois Tigeot intel_engine_init_hangcheck(engine); 5585d0b1887SFrançois Tigeot 559686a02f1SFrançois Tigeot out: 5602c9916cdSFrançois Tigeot intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL); 561686a02f1SFrançois Tigeot 562686a02f1SFrançois Tigeot return ret; 563e3adcf8fSFrançois Tigeot } 564e3adcf8fSFrançois Tigeot 5651e12ee3bSFrançois Tigeot static void reset_ring_common(struct intel_engine_cs *engine, 5661e12ee3bSFrançois Tigeot struct drm_i915_gem_request *request) 5671b13d190SFrançois Tigeot { 568*a85cb24fSFrançois Tigeot /* Try to restore the logical GPU state to match the continuation 569*a85cb24fSFrançois Tigeot * of the request queue. If we skip the context/PD restore, then 570*a85cb24fSFrançois Tigeot * the next request may try to execute assuming that its context 571*a85cb24fSFrançois Tigeot * is valid and loaded on the GPU and so may try to access invalid 572*a85cb24fSFrançois Tigeot * memory, prompting repeated GPU hangs. 573*a85cb24fSFrançois Tigeot * 574*a85cb24fSFrançois Tigeot * If the request was guilty, we still restore the logical state 575*a85cb24fSFrançois Tigeot * in case the next request requires it (e.g. the aliasing ppgtt), 576*a85cb24fSFrançois Tigeot * but skip over the hung batch. 577*a85cb24fSFrançois Tigeot * 578*a85cb24fSFrançois Tigeot * If the request was innocent, we try to replay the request with 579*a85cb24fSFrançois Tigeot * the restored context. 580*a85cb24fSFrançois Tigeot */ 581*a85cb24fSFrançois Tigeot if (request) { 582*a85cb24fSFrançois Tigeot struct drm_i915_private *dev_priv = request->i915; 583*a85cb24fSFrançois Tigeot struct intel_context *ce = &request->ctx->engine[engine->id]; 584*a85cb24fSFrançois Tigeot struct i915_hw_ppgtt *ppgtt; 5851b13d190SFrançois Tigeot 586*a85cb24fSFrançois Tigeot /* FIXME consider gen8 reset */ 587*a85cb24fSFrançois Tigeot 588*a85cb24fSFrançois Tigeot if (ce->state) { 589*a85cb24fSFrançois Tigeot I915_WRITE(CCID, 590*a85cb24fSFrançois Tigeot i915_ggtt_offset(ce->state) | 591*a85cb24fSFrançois Tigeot BIT(8) /* must be set! */ | 592*a85cb24fSFrançois Tigeot CCID_EXTENDED_STATE_SAVE | 593*a85cb24fSFrançois Tigeot CCID_EXTENDED_STATE_RESTORE | 594*a85cb24fSFrançois Tigeot CCID_EN); 595e3adcf8fSFrançois Tigeot } 596e3adcf8fSFrançois Tigeot 597*a85cb24fSFrançois Tigeot ppgtt = request->ctx->ppgtt ?: engine->i915->mm.aliasing_ppgtt; 598*a85cb24fSFrançois Tigeot if (ppgtt) { 599*a85cb24fSFrançois Tigeot u32 pd_offset = ppgtt->pd.base.ggtt_offset << 10; 6001b13d190SFrançois Tigeot 601*a85cb24fSFrançois Tigeot I915_WRITE(RING_PP_DIR_DCLV(engine), PP_DIR_DCLV_2G); 602*a85cb24fSFrançois Tigeot I915_WRITE(RING_PP_DIR_BASE(engine), pd_offset); 6031b13d190SFrançois Tigeot 604*a85cb24fSFrançois Tigeot /* Wait for the PD reload to complete */ 605*a85cb24fSFrançois Tigeot if (intel_wait_for_register(dev_priv, 606*a85cb24fSFrançois Tigeot RING_PP_DIR_BASE(engine), 607*a85cb24fSFrançois Tigeot BIT(0), 0, 608*a85cb24fSFrançois Tigeot 10)) 609*a85cb24fSFrançois Tigeot DRM_ERROR("Wait for reload of ppgtt page-directory timed out\n"); 6101b13d190SFrançois Tigeot 611*a85cb24fSFrançois Tigeot ppgtt->pd_dirty_rings &= ~intel_engine_flag(engine); 6122c9916cdSFrançois Tigeot } 6132c9916cdSFrançois Tigeot 614*a85cb24fSFrançois Tigeot /* If the rq hung, jump to its breadcrumb and skip the batch */ 615*a85cb24fSFrançois Tigeot if (request->fence.error == -EIO) 616*a85cb24fSFrançois Tigeot request->ring->head = request->postfix; 617*a85cb24fSFrançois Tigeot } else { 618*a85cb24fSFrançois Tigeot engine->legacy_active_context = NULL; 619*a85cb24fSFrançois Tigeot } 6202c9916cdSFrançois Tigeot } 6212c9916cdSFrançois Tigeot 622a05eeebfSFrançois Tigeot static int intel_rcs_ctx_init(struct drm_i915_gem_request *req) 6232c9916cdSFrançois Tigeot { 6242c9916cdSFrançois Tigeot int ret; 6252c9916cdSFrançois Tigeot 626a05eeebfSFrançois Tigeot ret = intel_ring_workarounds_emit(req); 6272c9916cdSFrançois Tigeot if (ret != 0) 6282c9916cdSFrançois Tigeot return ret; 6292c9916cdSFrançois Tigeot 6304be47400SFrançois Tigeot ret = i915_gem_render_state_emit(req); 6312c9916cdSFrançois Tigeot if (ret) 6322c9916cdSFrançois Tigeot return ret; 633c0e85e96SFrançois Tigeot 634c0e85e96SFrançois Tigeot return 0; 6352c9916cdSFrançois Tigeot } 6362c9916cdSFrançois Tigeot 6378621f407SFrançois Tigeot static int init_render_ring(struct intel_engine_cs *engine) 638e3adcf8fSFrançois Tigeot { 6391487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 6408621f407SFrançois Tigeot int ret = init_ring_common(engine); 64124edb884SFrançois Tigeot if (ret) 64224edb884SFrançois Tigeot return ret; 643e3adcf8fSFrançois Tigeot 644ba55f2f5SFrançois Tigeot /* WaTimedSingleVertexDispatch:cl,bw,ctg,elk,ilk,snb */ 6451487f786SFrançois Tigeot if (IS_GEN(dev_priv, 4, 6)) 646f4e1c372SFrançois Tigeot I915_WRITE(MI_MODE, _MASKED_BIT_ENABLE(VS_TIMER_DISPATCH)); 647f4e1c372SFrançois Tigeot 648f4e1c372SFrançois Tigeot /* We need to disable the AsyncFlip performance optimisations in order 649f4e1c372SFrançois Tigeot * to use MI_WAIT_FOR_EVENT within the CS. It should already be 650f4e1c372SFrançois Tigeot * programmed to '1' on all products. 6515d0b1887SFrançois Tigeot * 652a05eeebfSFrançois Tigeot * WaDisableAsyncFlipPerfMode:snb,ivb,hsw,vlv 653f4e1c372SFrançois Tigeot */ 6541487f786SFrançois Tigeot if (IS_GEN(dev_priv, 6, 7)) 655f4e1c372SFrançois Tigeot I915_WRITE(MI_MODE, _MASKED_BIT_ENABLE(ASYNC_FLIP_PERF_DISABLE)); 656f4e1c372SFrançois Tigeot 657f4e1c372SFrançois Tigeot /* Required for the hardware to program scanline values for waiting */ 658ba55f2f5SFrançois Tigeot /* WaEnableFlushTlbInvalidationMode:snb */ 6591487f786SFrançois Tigeot if (IS_GEN6(dev_priv)) 660f4e1c372SFrançois Tigeot I915_WRITE(GFX_MODE, 661ba55f2f5SFrançois Tigeot _MASKED_BIT_ENABLE(GFX_TLB_INVALIDATE_EXPLICIT)); 662f4e1c372SFrançois Tigeot 663ba55f2f5SFrançois Tigeot /* WaBCSVCSTlbInvalidationMode:ivb,vlv,hsw */ 6641487f786SFrançois Tigeot if (IS_GEN7(dev_priv)) 665e3adcf8fSFrançois Tigeot I915_WRITE(GFX_MODE_GEN7, 666ba55f2f5SFrançois Tigeot _MASKED_BIT_ENABLE(GFX_TLB_INVALIDATE_EXPLICIT) | 667f4e1c372SFrançois Tigeot _MASKED_BIT_ENABLE(GFX_REPLAY_MODE)); 668e3adcf8fSFrançois Tigeot 6691487f786SFrançois Tigeot if (IS_GEN6(dev_priv)) { 670e3adcf8fSFrançois Tigeot /* From the Sandybridge PRM, volume 1 part 3, page 24: 671e3adcf8fSFrançois Tigeot * "If this bit is set, STCunit will have LRA as replacement 672e3adcf8fSFrançois Tigeot * policy. [...] This bit must be reset. LRA replacement 673e3adcf8fSFrançois Tigeot * policy is not supported." 674e3adcf8fSFrançois Tigeot */ 675e3adcf8fSFrançois Tigeot I915_WRITE(CACHE_MODE_0, 676f4e1c372SFrançois Tigeot _MASKED_BIT_DISABLE(CM0_STC_EVICT_DISABLE_LRA_SNB)); 677e3adcf8fSFrançois Tigeot } 678e3adcf8fSFrançois Tigeot 6791487f786SFrançois Tigeot if (IS_GEN(dev_priv, 6, 7)) 680f4e1c372SFrançois Tigeot I915_WRITE(INSTPM, _MASKED_BIT_ENABLE(INSTPM_FORCE_ORDERING)); 681f4e1c372SFrançois Tigeot 682303bf270SFrançois Tigeot if (INTEL_INFO(dev_priv)->gen >= 6) 683303bf270SFrançois Tigeot I915_WRITE_IMR(engine, ~engine->irq_keep_mask); 684e3adcf8fSFrançois Tigeot 6858621f407SFrançois Tigeot return init_workarounds_ring(engine); 686e3adcf8fSFrançois Tigeot } 687e3adcf8fSFrançois Tigeot 6888621f407SFrançois Tigeot static void render_ring_cleanup(struct intel_engine_cs *engine) 689e3adcf8fSFrançois Tigeot { 6901487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 69124edb884SFrançois Tigeot 6921e12ee3bSFrançois Tigeot i915_vma_unpin_and_release(&dev_priv->semaphore); 693e3adcf8fSFrançois Tigeot } 694e3adcf8fSFrançois Tigeot 695*a85cb24fSFrançois Tigeot static u32 *gen8_rcs_signal(struct drm_i915_gem_request *req, u32 *cs) 69624edb884SFrançois Tigeot { 69771f41f3eSFrançois Tigeot struct drm_i915_private *dev_priv = req->i915; 69824edb884SFrançois Tigeot struct intel_engine_cs *waiter; 6998621f407SFrançois Tigeot enum intel_engine_id id; 70024edb884SFrançois Tigeot 7011e12ee3bSFrançois Tigeot for_each_engine(waiter, dev_priv, id) { 70271f41f3eSFrançois Tigeot u64 gtt_offset = req->engine->semaphore.signal_ggtt[id]; 70324edb884SFrançois Tigeot if (gtt_offset == MI_SEMAPHORE_SYNC_INVALID) 70424edb884SFrançois Tigeot continue; 70524edb884SFrançois Tigeot 706*a85cb24fSFrançois Tigeot *cs++ = GFX_OP_PIPE_CONTROL(6); 707*a85cb24fSFrançois Tigeot *cs++ = PIPE_CONTROL_GLOBAL_GTT_IVB | PIPE_CONTROL_QW_WRITE | 708*a85cb24fSFrançois Tigeot PIPE_CONTROL_CS_STALL; 709*a85cb24fSFrançois Tigeot *cs++ = lower_32_bits(gtt_offset); 710*a85cb24fSFrançois Tigeot *cs++ = upper_32_bits(gtt_offset); 711*a85cb24fSFrançois Tigeot *cs++ = req->global_seqno; 712*a85cb24fSFrançois Tigeot *cs++ = 0; 713*a85cb24fSFrançois Tigeot *cs++ = MI_SEMAPHORE_SIGNAL | 714*a85cb24fSFrançois Tigeot MI_SEMAPHORE_TARGET(waiter->hw_id); 715*a85cb24fSFrançois Tigeot *cs++ = 0; 71624edb884SFrançois Tigeot } 71724edb884SFrançois Tigeot 718*a85cb24fSFrançois Tigeot return cs; 7194be47400SFrançois Tigeot } 7204be47400SFrançois Tigeot 721*a85cb24fSFrançois Tigeot static u32 *gen8_xcs_signal(struct drm_i915_gem_request *req, u32 *cs) 72224edb884SFrançois Tigeot { 72371f41f3eSFrançois Tigeot struct drm_i915_private *dev_priv = req->i915; 72424edb884SFrançois Tigeot struct intel_engine_cs *waiter; 7258621f407SFrançois Tigeot enum intel_engine_id id; 72624edb884SFrançois Tigeot 7271e12ee3bSFrançois Tigeot for_each_engine(waiter, dev_priv, id) { 72871f41f3eSFrançois Tigeot u64 gtt_offset = req->engine->semaphore.signal_ggtt[id]; 72924edb884SFrançois Tigeot if (gtt_offset == MI_SEMAPHORE_SYNC_INVALID) 73024edb884SFrançois Tigeot continue; 73124edb884SFrançois Tigeot 732*a85cb24fSFrançois Tigeot *cs++ = (MI_FLUSH_DW + 1) | MI_FLUSH_DW_OP_STOREDW; 733*a85cb24fSFrançois Tigeot *cs++ = lower_32_bits(gtt_offset) | MI_FLUSH_DW_USE_GTT; 734*a85cb24fSFrançois Tigeot *cs++ = upper_32_bits(gtt_offset); 735*a85cb24fSFrançois Tigeot *cs++ = req->global_seqno; 736*a85cb24fSFrançois Tigeot *cs++ = MI_SEMAPHORE_SIGNAL | 737*a85cb24fSFrançois Tigeot MI_SEMAPHORE_TARGET(waiter->hw_id); 738*a85cb24fSFrançois Tigeot *cs++ = 0; 73924edb884SFrançois Tigeot } 74024edb884SFrançois Tigeot 741*a85cb24fSFrançois Tigeot return cs; 7424be47400SFrançois Tigeot } 7434be47400SFrançois Tigeot 744*a85cb24fSFrançois Tigeot static u32 *gen6_signal(struct drm_i915_gem_request *req, u32 *cs) 745e3adcf8fSFrançois Tigeot { 74671f41f3eSFrançois Tigeot struct drm_i915_private *dev_priv = req->i915; 7471e12ee3bSFrançois Tigeot struct intel_engine_cs *engine; 7488621f407SFrançois Tigeot enum intel_engine_id id; 7494be47400SFrançois Tigeot int num_rings = 0; 750ba55f2f5SFrançois Tigeot 7511e12ee3bSFrançois Tigeot for_each_engine(engine, dev_priv, id) { 7521e12ee3bSFrançois Tigeot i915_reg_t mbox_reg; 753aee94f86SFrançois Tigeot 7541e12ee3bSFrançois Tigeot if (!(BIT(engine->hw_id) & GEN6_SEMAPHORES_MASK)) 7551e12ee3bSFrançois Tigeot continue; 7561e12ee3bSFrançois Tigeot 7571e12ee3bSFrançois Tigeot mbox_reg = req->engine->semaphore.mbox.signal[engine->hw_id]; 758aee94f86SFrançois Tigeot if (i915_mmio_reg_valid(mbox_reg)) { 759*a85cb24fSFrançois Tigeot *cs++ = MI_LOAD_REGISTER_IMM(1); 760*a85cb24fSFrançois Tigeot *cs++ = i915_mmio_reg_offset(mbox_reg); 761*a85cb24fSFrançois Tigeot *cs++ = req->global_seqno; 7624be47400SFrançois Tigeot num_rings++; 763ba55f2f5SFrançois Tigeot } 764ba55f2f5SFrançois Tigeot } 7654be47400SFrançois Tigeot if (num_rings & 1) 766*a85cb24fSFrançois Tigeot *cs++ = MI_NOOP; 767ba55f2f5SFrançois Tigeot 768*a85cb24fSFrançois Tigeot return cs; 76971f41f3eSFrançois Tigeot } 77071f41f3eSFrançois Tigeot 77171f41f3eSFrançois Tigeot static void i9xx_submit_request(struct drm_i915_gem_request *request) 77271f41f3eSFrançois Tigeot { 77371f41f3eSFrançois Tigeot struct drm_i915_private *dev_priv = request->i915; 77471f41f3eSFrançois Tigeot 7754be47400SFrançois Tigeot i915_gem_request_submit(request); 7764be47400SFrançois Tigeot 777*a85cb24fSFrançois Tigeot I915_WRITE_TAIL(request->engine, 778*a85cb24fSFrançois Tigeot intel_ring_set_tail(request->ring, request->tail)); 77971f41f3eSFrançois Tigeot } 78071f41f3eSFrançois Tigeot 781*a85cb24fSFrançois Tigeot static void i9xx_emit_breadcrumb(struct drm_i915_gem_request *req, u32 *cs) 78271f41f3eSFrançois Tigeot { 783*a85cb24fSFrançois Tigeot *cs++ = MI_STORE_DWORD_INDEX; 784*a85cb24fSFrançois Tigeot *cs++ = I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT; 785*a85cb24fSFrançois Tigeot *cs++ = req->global_seqno; 786*a85cb24fSFrançois Tigeot *cs++ = MI_USER_INTERRUPT; 78771f41f3eSFrançois Tigeot 788*a85cb24fSFrançois Tigeot req->tail = intel_ring_offset(req, cs); 789*a85cb24fSFrançois Tigeot assert_ring_tail_valid(req->ring, req->tail); 790e3adcf8fSFrançois Tigeot } 791e3adcf8fSFrançois Tigeot 7924be47400SFrançois Tigeot static const int i9xx_emit_breadcrumb_sz = 4; 7934be47400SFrançois Tigeot 794e3adcf8fSFrançois Tigeot /** 7954be47400SFrançois Tigeot * gen6_sema_emit_breadcrumb - Update the semaphore mailbox registers 796e3adcf8fSFrançois Tigeot * 797a05eeebfSFrançois Tigeot * @request - request to write to the ring 798e3adcf8fSFrançois Tigeot * 799e3adcf8fSFrançois Tigeot * Update the mailbox registers in the *other* rings with the current seqno. 800e3adcf8fSFrançois Tigeot * This acts like a signal in the canonical semaphore. 801e3adcf8fSFrançois Tigeot */ 802*a85cb24fSFrançois Tigeot static void gen6_sema_emit_breadcrumb(struct drm_i915_gem_request *req, u32 *cs) 803e3adcf8fSFrançois Tigeot { 8044be47400SFrançois Tigeot return i9xx_emit_breadcrumb(req, 805*a85cb24fSFrançois Tigeot req->engine->semaphore.signal(req, cs)); 806e3adcf8fSFrançois Tigeot } 807e3adcf8fSFrançois Tigeot 8084be47400SFrançois Tigeot static void gen8_render_emit_breadcrumb(struct drm_i915_gem_request *req, 809*a85cb24fSFrançois Tigeot u32 *cs) 8101487f786SFrançois Tigeot { 8111487f786SFrançois Tigeot struct intel_engine_cs *engine = req->engine; 8121487f786SFrançois Tigeot 8134be47400SFrançois Tigeot if (engine->semaphore.signal) 814*a85cb24fSFrançois Tigeot cs = engine->semaphore.signal(req, cs); 81571f41f3eSFrançois Tigeot 816*a85cb24fSFrançois Tigeot *cs++ = GFX_OP_PIPE_CONTROL(6); 817*a85cb24fSFrançois Tigeot *cs++ = PIPE_CONTROL_GLOBAL_GTT_IVB | PIPE_CONTROL_CS_STALL | 818*a85cb24fSFrançois Tigeot PIPE_CONTROL_QW_WRITE; 819*a85cb24fSFrançois Tigeot *cs++ = intel_hws_seqno_address(engine); 820*a85cb24fSFrançois Tigeot *cs++ = 0; 821*a85cb24fSFrançois Tigeot *cs++ = req->global_seqno; 8221487f786SFrançois Tigeot /* We're thrashing one dword of HWS. */ 823*a85cb24fSFrançois Tigeot *cs++ = 0; 824*a85cb24fSFrançois Tigeot *cs++ = MI_USER_INTERRUPT; 825*a85cb24fSFrançois Tigeot *cs++ = MI_NOOP; 82671f41f3eSFrançois Tigeot 827*a85cb24fSFrançois Tigeot req->tail = intel_ring_offset(req, cs); 828*a85cb24fSFrançois Tigeot assert_ring_tail_valid(req->ring, req->tail); 8291487f786SFrançois Tigeot } 8301487f786SFrançois Tigeot 8314be47400SFrançois Tigeot static const int gen8_render_emit_breadcrumb_sz = 8; 8324be47400SFrançois Tigeot 833e3adcf8fSFrançois Tigeot /** 834e3adcf8fSFrançois Tigeot * intel_ring_sync - sync the waiter to the signaller on seqno 835e3adcf8fSFrançois Tigeot * 836e3adcf8fSFrançois Tigeot * @waiter - ring that is waiting 837e3adcf8fSFrançois Tigeot * @signaller - ring which has, or will signal 838e3adcf8fSFrançois Tigeot * @seqno - seqno which the waiter will block on 839e3adcf8fSFrançois Tigeot */ 84024edb884SFrançois Tigeot 84124edb884SFrançois Tigeot static int 84271f41f3eSFrançois Tigeot gen8_ring_sync_to(struct drm_i915_gem_request *req, 84371f41f3eSFrançois Tigeot struct drm_i915_gem_request *signal) 84424edb884SFrançois Tigeot { 84571f41f3eSFrançois Tigeot struct drm_i915_private *dev_priv = req->i915; 84671f41f3eSFrançois Tigeot u64 offset = GEN8_WAIT_OFFSET(req->engine, signal->engine->id); 8471487f786SFrançois Tigeot struct i915_hw_ppgtt *ppgtt; 848*a85cb24fSFrançois Tigeot u32 *cs; 84924edb884SFrançois Tigeot 850*a85cb24fSFrançois Tigeot cs = intel_ring_begin(req, 4); 851*a85cb24fSFrançois Tigeot if (IS_ERR(cs)) 852*a85cb24fSFrançois Tigeot return PTR_ERR(cs); 85324edb884SFrançois Tigeot 854*a85cb24fSFrançois Tigeot *cs++ = MI_SEMAPHORE_WAIT | MI_SEMAPHORE_GLOBAL_GTT | 855*a85cb24fSFrançois Tigeot MI_SEMAPHORE_SAD_GTE_SDD; 856*a85cb24fSFrançois Tigeot *cs++ = signal->global_seqno; 857*a85cb24fSFrançois Tigeot *cs++ = lower_32_bits(offset); 858*a85cb24fSFrançois Tigeot *cs++ = upper_32_bits(offset); 859*a85cb24fSFrançois Tigeot intel_ring_advance(req, cs); 8601487f786SFrançois Tigeot 8611487f786SFrançois Tigeot /* When the !RCS engines idle waiting upon a semaphore, they lose their 8621487f786SFrançois Tigeot * pagetables and we must reload them before executing the batch. 8631487f786SFrançois Tigeot * We do this on the i915_switch_context() following the wait and 8641487f786SFrançois Tigeot * before the dispatch. 8651487f786SFrançois Tigeot */ 86671f41f3eSFrançois Tigeot ppgtt = req->ctx->ppgtt; 86771f41f3eSFrançois Tigeot if (ppgtt && req->engine->id != RCS) 86871f41f3eSFrançois Tigeot ppgtt->pd_dirty_rings |= intel_engine_flag(req->engine); 86924edb884SFrançois Tigeot return 0; 87024edb884SFrançois Tigeot } 87124edb884SFrançois Tigeot 872e3adcf8fSFrançois Tigeot static int 87371f41f3eSFrançois Tigeot gen6_ring_sync_to(struct drm_i915_gem_request *req, 87471f41f3eSFrançois Tigeot struct drm_i915_gem_request *signal) 875e3adcf8fSFrançois Tigeot { 876e3adcf8fSFrançois Tigeot u32 dw1 = MI_SEMAPHORE_MBOX | 877e3adcf8fSFrançois Tigeot MI_SEMAPHORE_COMPARE | 878e3adcf8fSFrançois Tigeot MI_SEMAPHORE_REGISTER; 8791e12ee3bSFrançois Tigeot u32 wait_mbox = signal->engine->semaphore.mbox.wait[req->engine->hw_id]; 880*a85cb24fSFrançois Tigeot u32 *cs; 881e3adcf8fSFrançois Tigeot 88271f41f3eSFrançois Tigeot WARN_ON(wait_mbox == MI_SEMAPHORE_SYNC_INVALID); 88371f41f3eSFrançois Tigeot 884*a85cb24fSFrançois Tigeot cs = intel_ring_begin(req, 4); 885*a85cb24fSFrançois Tigeot if (IS_ERR(cs)) 886*a85cb24fSFrançois Tigeot return PTR_ERR(cs); 88771f41f3eSFrançois Tigeot 888*a85cb24fSFrançois Tigeot *cs++ = dw1 | wait_mbox; 889686a02f1SFrançois Tigeot /* Throughout all of the GEM code, seqno passed implies our current 890686a02f1SFrançois Tigeot * seqno is >= the last seqno executed. However for hardware the 891686a02f1SFrançois Tigeot * comparison is strictly greater than. 892686a02f1SFrançois Tigeot */ 893*a85cb24fSFrançois Tigeot *cs++ = signal->global_seqno - 1; 894*a85cb24fSFrançois Tigeot *cs++ = 0; 895*a85cb24fSFrançois Tigeot *cs++ = MI_NOOP; 896*a85cb24fSFrançois Tigeot intel_ring_advance(req, cs); 897e3adcf8fSFrançois Tigeot 898e3adcf8fSFrançois Tigeot return 0; 899e3adcf8fSFrançois Tigeot } 900e3adcf8fSFrançois Tigeot 901303bf270SFrançois Tigeot static void 90287df8fc6SFrançois Tigeot gen5_seqno_barrier(struct intel_engine_cs *engine) 903e3adcf8fSFrançois Tigeot { 904303bf270SFrançois Tigeot /* MI_STORE are internally buffered by the GPU and not flushed 905303bf270SFrançois Tigeot * either by MI_FLUSH or SyncFlush or any other combination of 906303bf270SFrançois Tigeot * MI commands. 907e3adcf8fSFrançois Tigeot * 908303bf270SFrançois Tigeot * "Only the submission of the store operation is guaranteed. 909303bf270SFrançois Tigeot * The write result will be complete (coherent) some time later 910303bf270SFrançois Tigeot * (this is practically a finite period but there is no guaranteed 911303bf270SFrançois Tigeot * latency)." 912303bf270SFrançois Tigeot * 913303bf270SFrançois Tigeot * Empirically, we observe that we need a delay of at least 75us to 914303bf270SFrançois Tigeot * be sure that the seqno write is visible by the CPU. 915e3adcf8fSFrançois Tigeot */ 916303bf270SFrançois Tigeot usleep_range(125, 250); 917e3adcf8fSFrançois Tigeot } 918e3adcf8fSFrançois Tigeot 9198621f407SFrançois Tigeot static void 9208621f407SFrançois Tigeot gen6_seqno_barrier(struct intel_engine_cs *engine) 921e3adcf8fSFrançois Tigeot { 9221487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 9238621f407SFrançois Tigeot 924e3adcf8fSFrançois Tigeot /* Workaround to force correct ordering between irq and seqno writes on 925e3adcf8fSFrançois Tigeot * ivb (and maybe also on snb) by reading from a CS register (like 9268621f407SFrançois Tigeot * ACTHD) before reading the status page. 9278621f407SFrançois Tigeot * 9288621f407SFrançois Tigeot * Note that this effectively stalls the read by the time it takes to 9298621f407SFrançois Tigeot * do a memory transaction, which more or less ensures that the write 9308621f407SFrançois Tigeot * from the GPU has sufficient time to invalidate the CPU cacheline. 9318621f407SFrançois Tigeot * Alternatively we could delay the interrupt from the CS ring to give 9328621f407SFrançois Tigeot * the write time to land, but that would incur a delay after every 9338621f407SFrançois Tigeot * batch i.e. much more frequent than a delay when waiting for the 9348621f407SFrançois Tigeot * interrupt (with the same net latency). 9358621f407SFrançois Tigeot * 9368621f407SFrançois Tigeot * Also note that to prevent whole machine hangs on gen7, we have to 9378621f407SFrançois Tigeot * take the spinlock to guard against concurrent cacheline access. 9388621f407SFrançois Tigeot */ 9398621f407SFrançois Tigeot spin_lock_irq(&dev_priv->uncore.lock); 9408621f407SFrançois Tigeot POSTING_READ_FW(RING_ACTHD(engine->mmio_base)); 9418621f407SFrançois Tigeot spin_unlock_irq(&dev_priv->uncore.lock); 942e3adcf8fSFrançois Tigeot } 943e3adcf8fSFrançois Tigeot 944303bf270SFrançois Tigeot static void 945303bf270SFrançois Tigeot gen5_irq_enable(struct intel_engine_cs *engine) 946e3adcf8fSFrançois Tigeot { 947303bf270SFrançois Tigeot gen5_enable_gt_irq(engine->i915, engine->irq_enable_mask); 948e3adcf8fSFrançois Tigeot } 949e3adcf8fSFrançois Tigeot 950a2fdbec6SFrançois Tigeot static void 951303bf270SFrançois Tigeot gen5_irq_disable(struct intel_engine_cs *engine) 952a2fdbec6SFrançois Tigeot { 953303bf270SFrançois Tigeot gen5_disable_gt_irq(engine->i915, engine->irq_enable_mask); 954e3adcf8fSFrançois Tigeot } 955e3adcf8fSFrançois Tigeot 956a2fdbec6SFrançois Tigeot static void 957303bf270SFrançois Tigeot i9xx_irq_enable(struct intel_engine_cs *engine) 958e3adcf8fSFrançois Tigeot { 9591487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 960e3adcf8fSFrançois Tigeot 9618621f407SFrançois Tigeot dev_priv->irq_mask &= ~engine->irq_enable_mask; 962686a02f1SFrançois Tigeot I915_WRITE(IMR, dev_priv->irq_mask); 963303bf270SFrançois Tigeot POSTING_READ_FW(RING_IMR(engine->mmio_base)); 964686a02f1SFrançois Tigeot } 965686a02f1SFrançois Tigeot 966686a02f1SFrançois Tigeot static void 967303bf270SFrançois Tigeot i9xx_irq_disable(struct intel_engine_cs *engine) 968686a02f1SFrançois Tigeot { 9691487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 970686a02f1SFrançois Tigeot 9718621f407SFrançois Tigeot dev_priv->irq_mask |= engine->irq_enable_mask; 972686a02f1SFrançois Tigeot I915_WRITE(IMR, dev_priv->irq_mask); 973686a02f1SFrançois Tigeot } 974686a02f1SFrançois Tigeot 975686a02f1SFrançois Tigeot static void 976303bf270SFrançois Tigeot i8xx_irq_enable(struct intel_engine_cs *engine) 977686a02f1SFrançois Tigeot { 9781487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 979686a02f1SFrançois Tigeot 980303bf270SFrançois Tigeot dev_priv->irq_mask &= ~engine->irq_enable_mask; 981303bf270SFrançois Tigeot I915_WRITE16(IMR, dev_priv->irq_mask); 982303bf270SFrançois Tigeot POSTING_READ16(RING_IMR(engine->mmio_base)); 983303bf270SFrançois Tigeot } 984303bf270SFrançois Tigeot 985303bf270SFrançois Tigeot static void 986303bf270SFrançois Tigeot i8xx_irq_disable(struct intel_engine_cs *engine) 987303bf270SFrançois Tigeot { 988303bf270SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 989303bf270SFrançois Tigeot 9908621f407SFrançois Tigeot dev_priv->irq_mask |= engine->irq_enable_mask; 991686a02f1SFrançois Tigeot I915_WRITE16(IMR, dev_priv->irq_mask); 992e3adcf8fSFrançois Tigeot } 993e3adcf8fSFrançois Tigeot 994e3adcf8fSFrançois Tigeot static int 99571f41f3eSFrançois Tigeot bsd_ring_flush(struct drm_i915_gem_request *req, u32 mode) 996e3adcf8fSFrançois Tigeot { 997*a85cb24fSFrançois Tigeot u32 *cs; 998e3adcf8fSFrançois Tigeot 999*a85cb24fSFrançois Tigeot cs = intel_ring_begin(req, 2); 1000*a85cb24fSFrançois Tigeot if (IS_ERR(cs)) 1001*a85cb24fSFrançois Tigeot return PTR_ERR(cs); 1002e3adcf8fSFrançois Tigeot 1003*a85cb24fSFrançois Tigeot *cs++ = MI_FLUSH; 1004*a85cb24fSFrançois Tigeot *cs++ = MI_NOOP; 1005*a85cb24fSFrançois Tigeot intel_ring_advance(req, cs); 1006e3adcf8fSFrançois Tigeot return 0; 1007e3adcf8fSFrançois Tigeot } 1008e3adcf8fSFrançois Tigeot 1009303bf270SFrançois Tigeot static void 1010303bf270SFrançois Tigeot gen6_irq_enable(struct intel_engine_cs *engine) 1011e3adcf8fSFrançois Tigeot { 10121487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 1013e3adcf8fSFrançois Tigeot 10148621f407SFrançois Tigeot I915_WRITE_IMR(engine, 10158621f407SFrançois Tigeot ~(engine->irq_enable_mask | 1016303bf270SFrançois Tigeot engine->irq_keep_mask)); 10178621f407SFrançois Tigeot gen5_enable_gt_irq(dev_priv, engine->irq_enable_mask); 1018e3adcf8fSFrançois Tigeot } 1019e3adcf8fSFrançois Tigeot 1020e3adcf8fSFrançois Tigeot static void 1021303bf270SFrançois Tigeot gen6_irq_disable(struct intel_engine_cs *engine) 1022e3adcf8fSFrançois Tigeot { 10231487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 1024e3adcf8fSFrançois Tigeot 1025303bf270SFrançois Tigeot I915_WRITE_IMR(engine, ~engine->irq_keep_mask); 10268621f407SFrançois Tigeot gen5_disable_gt_irq(dev_priv, engine->irq_enable_mask); 1027e3adcf8fSFrançois Tigeot } 1028e3adcf8fSFrançois Tigeot 1029303bf270SFrançois Tigeot static void 1030303bf270SFrançois Tigeot hsw_vebox_irq_enable(struct intel_engine_cs *engine) 10315d0b1887SFrançois Tigeot { 10321487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 10335d0b1887SFrançois Tigeot 10348621f407SFrançois Tigeot I915_WRITE_IMR(engine, ~engine->irq_enable_mask); 10354be47400SFrançois Tigeot gen6_unmask_pm_irq(dev_priv, engine->irq_enable_mask); 10365d0b1887SFrançois Tigeot } 10375d0b1887SFrançois Tigeot 10385d0b1887SFrançois Tigeot static void 1039303bf270SFrançois Tigeot hsw_vebox_irq_disable(struct intel_engine_cs *engine) 10405d0b1887SFrançois Tigeot { 10411487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 10425d0b1887SFrançois Tigeot 10438621f407SFrançois Tigeot I915_WRITE_IMR(engine, ~0); 10444be47400SFrançois Tigeot gen6_mask_pm_irq(dev_priv, engine->irq_enable_mask); 10455d0b1887SFrançois Tigeot } 10469edbd4a0SFrançois Tigeot 1047303bf270SFrançois Tigeot static void 1048303bf270SFrançois Tigeot gen8_irq_enable(struct intel_engine_cs *engine) 10499edbd4a0SFrançois Tigeot { 10501487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 10519edbd4a0SFrançois Tigeot 10528621f407SFrançois Tigeot I915_WRITE_IMR(engine, 10538621f407SFrançois Tigeot ~(engine->irq_enable_mask | 1054303bf270SFrançois Tigeot engine->irq_keep_mask)); 1055303bf270SFrançois Tigeot POSTING_READ_FW(RING_IMR(engine->mmio_base)); 10569edbd4a0SFrançois Tigeot } 10579edbd4a0SFrançois Tigeot 10589edbd4a0SFrançois Tigeot static void 1059303bf270SFrançois Tigeot gen8_irq_disable(struct intel_engine_cs *engine) 10609edbd4a0SFrançois Tigeot { 10611487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 10629edbd4a0SFrançois Tigeot 1063303bf270SFrançois Tigeot I915_WRITE_IMR(engine, ~engine->irq_keep_mask); 10645d0b1887SFrançois Tigeot } 10655d0b1887SFrançois Tigeot 1066e3adcf8fSFrançois Tigeot static int 106771f41f3eSFrançois Tigeot i965_emit_bb_start(struct drm_i915_gem_request *req, 1068ba55f2f5SFrançois Tigeot u64 offset, u32 length, 106971f41f3eSFrançois Tigeot unsigned int dispatch_flags) 1070e3adcf8fSFrançois Tigeot { 1071*a85cb24fSFrançois Tigeot u32 *cs; 1072e3adcf8fSFrançois Tigeot 1073*a85cb24fSFrançois Tigeot cs = intel_ring_begin(req, 2); 1074*a85cb24fSFrançois Tigeot if (IS_ERR(cs)) 1075*a85cb24fSFrançois Tigeot return PTR_ERR(cs); 1076e3adcf8fSFrançois Tigeot 1077*a85cb24fSFrançois Tigeot *cs++ = MI_BATCH_BUFFER_START | MI_BATCH_GTT | (dispatch_flags & 1078*a85cb24fSFrançois Tigeot I915_DISPATCH_SECURE ? 0 : MI_BATCH_NON_SECURE_I965); 1079*a85cb24fSFrançois Tigeot *cs++ = offset; 1080*a85cb24fSFrançois Tigeot intel_ring_advance(req, cs); 1081e3adcf8fSFrançois Tigeot 1082e3adcf8fSFrançois Tigeot return 0; 1083e3adcf8fSFrançois Tigeot } 1084e3adcf8fSFrançois Tigeot 1085b5c29a34SFrançois Tigeot /* Just userspace ABI convention to limit the wa batch bo to a resonable size */ 1086b5c29a34SFrançois Tigeot #define I830_BATCH_LIMIT (256*1024) 108724edb884SFrançois Tigeot #define I830_TLB_ENTRIES (2) 108824edb884SFrançois Tigeot #define I830_WA_SIZE max(I830_TLB_ENTRIES*4096, I830_BATCH_LIMIT) 1089e3adcf8fSFrançois Tigeot static int 109071f41f3eSFrançois Tigeot i830_emit_bb_start(struct drm_i915_gem_request *req, 1091ba55f2f5SFrançois Tigeot u64 offset, u32 len, 109271f41f3eSFrançois Tigeot unsigned int dispatch_flags) 1093e3adcf8fSFrançois Tigeot { 1094*a85cb24fSFrançois Tigeot u32 *cs, cs_offset = i915_ggtt_offset(req->engine->scratch); 1095e3adcf8fSFrançois Tigeot 1096*a85cb24fSFrançois Tigeot cs = intel_ring_begin(req, 6); 1097*a85cb24fSFrançois Tigeot if (IS_ERR(cs)) 1098*a85cb24fSFrançois Tigeot return PTR_ERR(cs); 109924edb884SFrançois Tigeot 110024edb884SFrançois Tigeot /* Evict the invalid PTE TLBs */ 1101*a85cb24fSFrançois Tigeot *cs++ = COLOR_BLT_CMD | BLT_WRITE_RGBA; 1102*a85cb24fSFrançois Tigeot *cs++ = BLT_DEPTH_32 | BLT_ROP_COLOR_COPY | 4096; 1103*a85cb24fSFrançois Tigeot *cs++ = I830_TLB_ENTRIES << 16 | 4; /* load each page */ 1104*a85cb24fSFrançois Tigeot *cs++ = cs_offset; 1105*a85cb24fSFrançois Tigeot *cs++ = 0xdeadbeef; 1106*a85cb24fSFrançois Tigeot *cs++ = MI_NOOP; 1107*a85cb24fSFrançois Tigeot intel_ring_advance(req, cs); 110824edb884SFrançois Tigeot 1109477eb7f9SFrançois Tigeot if ((dispatch_flags & I915_DISPATCH_PINNED) == 0) { 111024edb884SFrançois Tigeot if (len > I830_BATCH_LIMIT) 111124edb884SFrançois Tigeot return -ENOSPC; 111224edb884SFrançois Tigeot 1113*a85cb24fSFrançois Tigeot cs = intel_ring_begin(req, 6 + 2); 1114*a85cb24fSFrançois Tigeot if (IS_ERR(cs)) 1115*a85cb24fSFrançois Tigeot return PTR_ERR(cs); 111624edb884SFrançois Tigeot 111724edb884SFrançois Tigeot /* Blit the batch (which has now all relocs applied) to the 111824edb884SFrançois Tigeot * stable batch scratch bo area (so that the CS never 111924edb884SFrançois Tigeot * stumbles over its tlb invalidation bug) ... 112024edb884SFrançois Tigeot */ 1121*a85cb24fSFrançois Tigeot *cs++ = SRC_COPY_BLT_CMD | BLT_WRITE_RGBA; 1122*a85cb24fSFrançois Tigeot *cs++ = BLT_DEPTH_32 | BLT_ROP_SRC_COPY | 4096; 1123*a85cb24fSFrançois Tigeot *cs++ = DIV_ROUND_UP(len, 4096) << 16 | 4096; 1124*a85cb24fSFrançois Tigeot *cs++ = cs_offset; 1125*a85cb24fSFrançois Tigeot *cs++ = 4096; 1126*a85cb24fSFrançois Tigeot *cs++ = offset; 112724edb884SFrançois Tigeot 1128*a85cb24fSFrançois Tigeot *cs++ = MI_FLUSH; 1129*a85cb24fSFrançois Tigeot *cs++ = MI_NOOP; 1130*a85cb24fSFrançois Tigeot intel_ring_advance(req, cs); 113124edb884SFrançois Tigeot 113224edb884SFrançois Tigeot /* ... and execute it. */ 113324edb884SFrançois Tigeot offset = cs_offset; 113424edb884SFrançois Tigeot } 113524edb884SFrançois Tigeot 1136*a85cb24fSFrançois Tigeot cs = intel_ring_begin(req, 2); 1137*a85cb24fSFrançois Tigeot if (IS_ERR(cs)) 1138*a85cb24fSFrançois Tigeot return PTR_ERR(cs); 1139e3adcf8fSFrançois Tigeot 1140*a85cb24fSFrançois Tigeot *cs++ = MI_BATCH_BUFFER_START | MI_BATCH_GTT; 1141*a85cb24fSFrançois Tigeot *cs++ = offset | (dispatch_flags & I915_DISPATCH_SECURE ? 0 : 1142*a85cb24fSFrançois Tigeot MI_BATCH_NON_SECURE); 1143*a85cb24fSFrançois Tigeot intel_ring_advance(req, cs); 1144686a02f1SFrançois Tigeot 1145686a02f1SFrançois Tigeot return 0; 1146686a02f1SFrançois Tigeot } 1147686a02f1SFrançois Tigeot 1148686a02f1SFrançois Tigeot static int 114971f41f3eSFrançois Tigeot i915_emit_bb_start(struct drm_i915_gem_request *req, 1150ba55f2f5SFrançois Tigeot u64 offset, u32 len, 115171f41f3eSFrançois Tigeot unsigned int dispatch_flags) 1152686a02f1SFrançois Tigeot { 1153*a85cb24fSFrançois Tigeot u32 *cs; 1154686a02f1SFrançois Tigeot 1155*a85cb24fSFrançois Tigeot cs = intel_ring_begin(req, 2); 1156*a85cb24fSFrançois Tigeot if (IS_ERR(cs)) 1157*a85cb24fSFrançois Tigeot return PTR_ERR(cs); 1158e3adcf8fSFrançois Tigeot 1159*a85cb24fSFrançois Tigeot *cs++ = MI_BATCH_BUFFER_START | MI_BATCH_GTT; 1160*a85cb24fSFrançois Tigeot *cs++ = offset | (dispatch_flags & I915_DISPATCH_SECURE ? 0 : 1161*a85cb24fSFrançois Tigeot MI_BATCH_NON_SECURE); 1162*a85cb24fSFrançois Tigeot intel_ring_advance(req, cs); 1163e3adcf8fSFrançois Tigeot 1164e3adcf8fSFrançois Tigeot return 0; 1165e3adcf8fSFrançois Tigeot } 1166e3adcf8fSFrançois Tigeot 11678621f407SFrançois Tigeot static void cleanup_phys_status_page(struct intel_engine_cs *engine) 1168c0e85e96SFrançois Tigeot { 11691487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 1170c0e85e96SFrançois Tigeot 1171c0e85e96SFrançois Tigeot if (!dev_priv->status_page_dmah) 1172c0e85e96SFrançois Tigeot return; 1173c0e85e96SFrançois Tigeot 1174303bf270SFrançois Tigeot drm_pci_free(&dev_priv->drm, dev_priv->status_page_dmah); 11758621f407SFrançois Tigeot engine->status_page.page_addr = NULL; 1176c0e85e96SFrançois Tigeot } 1177c0e85e96SFrançois Tigeot 11788621f407SFrançois Tigeot static void cleanup_status_page(struct intel_engine_cs *engine) 1179e3adcf8fSFrançois Tigeot { 11801e12ee3bSFrançois Tigeot struct i915_vma *vma; 11814be47400SFrançois Tigeot struct drm_i915_gem_object *obj; 1182e3adcf8fSFrançois Tigeot 11831e12ee3bSFrançois Tigeot vma = fetch_and_zero(&engine->status_page.vma); 11841e12ee3bSFrançois Tigeot if (!vma) 1185e3adcf8fSFrançois Tigeot return; 1186e3adcf8fSFrançois Tigeot 11874be47400SFrançois Tigeot obj = vma->obj; 11884be47400SFrançois Tigeot 11891e12ee3bSFrançois Tigeot i915_vma_unpin(vma); 11904be47400SFrançois Tigeot i915_vma_close(vma); 11914be47400SFrançois Tigeot 11924be47400SFrançois Tigeot i915_gem_object_unpin_map(obj); 11934be47400SFrançois Tigeot __i915_gem_object_release_unless_active(obj); 1194e3adcf8fSFrançois Tigeot } 1195e3adcf8fSFrançois Tigeot 11968621f407SFrançois Tigeot static int init_status_page(struct intel_engine_cs *engine) 1197e3adcf8fSFrançois Tigeot { 11981e12ee3bSFrançois Tigeot struct drm_i915_gem_object *obj; 11991e12ee3bSFrançois Tigeot struct i915_vma *vma; 12001e12ee3bSFrançois Tigeot unsigned int flags; 12014be47400SFrançois Tigeot void *vaddr; 1202e3adcf8fSFrançois Tigeot int ret; 1203e3adcf8fSFrançois Tigeot 1204*a85cb24fSFrançois Tigeot obj = i915_gem_object_create_internal(engine->i915, PAGE_SIZE); 12051487f786SFrançois Tigeot if (IS_ERR(obj)) { 1206e3adcf8fSFrançois Tigeot DRM_ERROR("Failed to allocate status page\n"); 12071487f786SFrançois Tigeot return PTR_ERR(obj); 1208e3adcf8fSFrançois Tigeot } 1209e3adcf8fSFrançois Tigeot 1210ba55f2f5SFrançois Tigeot ret = i915_gem_object_set_cache_level(obj, I915_CACHE_LLC); 1211ba55f2f5SFrançois Tigeot if (ret) 12121e12ee3bSFrançois Tigeot goto err; 1213ba55f2f5SFrançois Tigeot 1214*a85cb24fSFrançois Tigeot vma = i915_vma_instance(obj, &engine->i915->ggtt.base, NULL); 12151e12ee3bSFrançois Tigeot if (IS_ERR(vma)) { 12161e12ee3bSFrançois Tigeot ret = PTR_ERR(vma); 12171e12ee3bSFrançois Tigeot goto err; 12181e12ee3bSFrançois Tigeot } 12191e12ee3bSFrançois Tigeot 12201e12ee3bSFrançois Tigeot flags = PIN_GLOBAL; 12211487f786SFrançois Tigeot if (!HAS_LLC(engine->i915)) 122224edb884SFrançois Tigeot /* On g33, we cannot place HWS above 256MiB, so 122324edb884SFrançois Tigeot * restrict its pinning to the low mappable arena. 122424edb884SFrançois Tigeot * Though this restriction is not documented for 122524edb884SFrançois Tigeot * gen4, gen5, or byt, they also behave similarly 122624edb884SFrançois Tigeot * and hang if the HWS is placed at the top of the 122724edb884SFrançois Tigeot * GTT. To generalise, it appears that all !llc 122824edb884SFrançois Tigeot * platforms have issues with us placing the HWS 122924edb884SFrançois Tigeot * above the mappable region (even though we never 123024edb884SFrançois Tigeot * actualy map it). 123124edb884SFrançois Tigeot */ 123224edb884SFrançois Tigeot flags |= PIN_MAPPABLE; 12331e12ee3bSFrançois Tigeot ret = i915_vma_pin(vma, 0, 4096, flags); 12341e12ee3bSFrançois Tigeot if (ret) 12351e12ee3bSFrançois Tigeot goto err; 1236ba55f2f5SFrançois Tigeot 12374be47400SFrançois Tigeot vaddr = i915_gem_object_pin_map(obj, I915_MAP_WB); 12384be47400SFrançois Tigeot if (IS_ERR(vaddr)) { 12394be47400SFrançois Tigeot ret = PTR_ERR(vaddr); 12404be47400SFrançois Tigeot goto err_unpin; 12414be47400SFrançois Tigeot } 12424be47400SFrançois Tigeot 12431e12ee3bSFrançois Tigeot engine->status_page.vma = vma; 12441e12ee3bSFrançois Tigeot engine->status_page.ggtt_offset = i915_ggtt_offset(vma); 1245*a85cb24fSFrançois Tigeot engine->status_page.page_addr = memset(vaddr, 0, PAGE_SIZE); 1246e3adcf8fSFrançois Tigeot 1247b5c29a34SFrançois Tigeot DRM_DEBUG_DRIVER("%s hws offset: 0x%08x\n", 12481e12ee3bSFrançois Tigeot engine->name, i915_ggtt_offset(vma)); 1249e3adcf8fSFrançois Tigeot return 0; 12501e12ee3bSFrançois Tigeot 12514be47400SFrançois Tigeot err_unpin: 12524be47400SFrançois Tigeot i915_vma_unpin(vma); 12531e12ee3bSFrançois Tigeot err: 12541e12ee3bSFrançois Tigeot i915_gem_object_put(obj); 12551e12ee3bSFrançois Tigeot return ret; 1256e3adcf8fSFrançois Tigeot } 1257e3adcf8fSFrançois Tigeot 12588621f407SFrançois Tigeot static int init_phys_status_page(struct intel_engine_cs *engine) 1259686a02f1SFrançois Tigeot { 12601487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 1261686a02f1SFrançois Tigeot 1262686a02f1SFrançois Tigeot dev_priv->status_page_dmah = 1263303bf270SFrançois Tigeot drm_pci_alloc(&dev_priv->drm, PAGE_SIZE, PAGE_SIZE); 1264686a02f1SFrançois Tigeot if (!dev_priv->status_page_dmah) 1265686a02f1SFrançois Tigeot return -ENOMEM; 1266686a02f1SFrançois Tigeot 12678621f407SFrançois Tigeot engine->status_page.page_addr = dev_priv->status_page_dmah->vaddr; 12688621f407SFrançois Tigeot memset(engine->status_page.page_addr, 0, PAGE_SIZE); 1269686a02f1SFrançois Tigeot 1270686a02f1SFrançois Tigeot return 0; 1271686a02f1SFrançois Tigeot } 1272686a02f1SFrançois Tigeot 1273*a85cb24fSFrançois Tigeot int intel_ring_pin(struct intel_ring *ring, unsigned int offset_bias) 12742c9916cdSFrançois Tigeot { 1275*a85cb24fSFrançois Tigeot unsigned int flags; 12761e12ee3bSFrançois Tigeot enum i915_map_type map; 12771e12ee3bSFrançois Tigeot struct i915_vma *vma = ring->vma; 12788621f407SFrançois Tigeot void *addr; 12792c9916cdSFrançois Tigeot int ret; 12802c9916cdSFrançois Tigeot 12811e12ee3bSFrançois Tigeot GEM_BUG_ON(ring->vaddr); 12821e12ee3bSFrançois Tigeot 12831e12ee3bSFrançois Tigeot map = HAS_LLC(ring->engine->i915) ? I915_MAP_WB : I915_MAP_WC; 12841e12ee3bSFrançois Tigeot 1285*a85cb24fSFrançois Tigeot flags = PIN_GLOBAL; 1286*a85cb24fSFrançois Tigeot if (offset_bias) 1287*a85cb24fSFrançois Tigeot flags |= PIN_OFFSET_BIAS | offset_bias; 12881e12ee3bSFrançois Tigeot if (vma->obj->stolen) 12891e12ee3bSFrançois Tigeot flags |= PIN_MAPPABLE; 12901e12ee3bSFrançois Tigeot 12911e12ee3bSFrançois Tigeot if (!(vma->flags & I915_VMA_GLOBAL_BIND)) { 12921e12ee3bSFrançois Tigeot if (flags & PIN_MAPPABLE || map == I915_MAP_WC) 12931e12ee3bSFrançois Tigeot ret = i915_gem_object_set_to_gtt_domain(vma->obj, true); 12941e12ee3bSFrançois Tigeot else 12951e12ee3bSFrançois Tigeot ret = i915_gem_object_set_to_cpu_domain(vma->obj, true); 12961e12ee3bSFrançois Tigeot if (unlikely(ret)) 12971e12ee3bSFrançois Tigeot return ret; 12981e12ee3bSFrançois Tigeot } 12991e12ee3bSFrançois Tigeot 13001e12ee3bSFrançois Tigeot ret = i915_vma_pin(vma, 0, PAGE_SIZE, flags); 13011e12ee3bSFrançois Tigeot if (unlikely(ret)) 1302aee94f86SFrançois Tigeot return ret; 1303aee94f86SFrançois Tigeot 13041e12ee3bSFrançois Tigeot if (i915_vma_is_map_and_fenceable(vma)) 13051e12ee3bSFrançois Tigeot addr = (void __force *)i915_vma_pin_iomap(vma); 13061e12ee3bSFrançois Tigeot else 13071e12ee3bSFrançois Tigeot addr = i915_gem_object_pin_map(vma->obj, map); 13081e12ee3bSFrançois Tigeot if (IS_ERR(addr)) 13091e12ee3bSFrançois Tigeot goto err; 13102c9916cdSFrançois Tigeot 131171f41f3eSFrançois Tigeot ring->vaddr = addr; 13122c9916cdSFrançois Tigeot return 0; 13138621f407SFrançois Tigeot 13141e12ee3bSFrançois Tigeot err: 13151e12ee3bSFrançois Tigeot i915_vma_unpin(vma); 13161e12ee3bSFrançois Tigeot return PTR_ERR(addr); 13172c9916cdSFrançois Tigeot } 13182c9916cdSFrançois Tigeot 1319*a85cb24fSFrançois Tigeot void intel_ring_reset(struct intel_ring *ring, u32 tail) 1320*a85cb24fSFrançois Tigeot { 1321*a85cb24fSFrançois Tigeot GEM_BUG_ON(!list_empty(&ring->request_list)); 1322*a85cb24fSFrançois Tigeot ring->tail = tail; 1323*a85cb24fSFrançois Tigeot ring->head = tail; 1324*a85cb24fSFrançois Tigeot ring->emit = tail; 1325*a85cb24fSFrançois Tigeot intel_ring_update_space(ring); 1326*a85cb24fSFrançois Tigeot } 1327*a85cb24fSFrançois Tigeot 132871f41f3eSFrançois Tigeot void intel_ring_unpin(struct intel_ring *ring) 1329e3adcf8fSFrançois Tigeot { 133071f41f3eSFrançois Tigeot GEM_BUG_ON(!ring->vma); 133171f41f3eSFrançois Tigeot GEM_BUG_ON(!ring->vaddr); 133271f41f3eSFrançois Tigeot 1333*a85cb24fSFrançois Tigeot /* Discard any unused bytes beyond that submitted to hw. */ 1334*a85cb24fSFrançois Tigeot intel_ring_reset(ring, ring->tail); 1335*a85cb24fSFrançois Tigeot 13361e12ee3bSFrançois Tigeot if (i915_vma_is_map_and_fenceable(ring->vma)) 133771f41f3eSFrançois Tigeot i915_vma_unpin_iomap(ring->vma); 13381e12ee3bSFrançois Tigeot else 13391e12ee3bSFrançois Tigeot i915_gem_object_unpin_map(ring->vma->obj); 134071f41f3eSFrançois Tigeot ring->vaddr = NULL; 134171f41f3eSFrançois Tigeot 13421e12ee3bSFrançois Tigeot i915_vma_unpin(ring->vma); 134371f41f3eSFrançois Tigeot } 134471f41f3eSFrançois Tigeot 13451e12ee3bSFrançois Tigeot static struct i915_vma * 13461e12ee3bSFrançois Tigeot intel_ring_create_vma(struct drm_i915_private *dev_priv, int size) 134724edb884SFrançois Tigeot { 1348e3adcf8fSFrançois Tigeot struct drm_i915_gem_object *obj; 13491e12ee3bSFrançois Tigeot struct i915_vma *vma; 1350e3adcf8fSFrançois Tigeot 1351*a85cb24fSFrançois Tigeot obj = i915_gem_object_create_stolen(dev_priv, size); 13521e12ee3bSFrançois Tigeot if (!obj) 1353*a85cb24fSFrançois Tigeot obj = i915_gem_object_create(dev_priv, size); 13541487f786SFrançois Tigeot if (IS_ERR(obj)) 13551e12ee3bSFrançois Tigeot return ERR_CAST(obj); 1356e3adcf8fSFrançois Tigeot 135724edb884SFrançois Tigeot /* mark ring buffers as read-only from GPU side by default */ 135824edb884SFrançois Tigeot obj->gt_ro = 1; 135924edb884SFrançois Tigeot 1360*a85cb24fSFrançois Tigeot vma = i915_vma_instance(obj, &dev_priv->ggtt.base, NULL); 13611e12ee3bSFrançois Tigeot if (IS_ERR(vma)) 13621e12ee3bSFrançois Tigeot goto err; 1363ba55f2f5SFrançois Tigeot 13641e12ee3bSFrançois Tigeot return vma; 13651e12ee3bSFrançois Tigeot 13661e12ee3bSFrançois Tigeot err: 13671e12ee3bSFrançois Tigeot i915_gem_object_put(obj); 13681e12ee3bSFrançois Tigeot return vma; 1369ba55f2f5SFrançois Tigeot } 1370ba55f2f5SFrançois Tigeot 137171f41f3eSFrançois Tigeot struct intel_ring * 137271f41f3eSFrançois Tigeot intel_engine_create_ring(struct intel_engine_cs *engine, int size) 1373352ff8bdSFrançois Tigeot { 137471f41f3eSFrançois Tigeot struct intel_ring *ring; 13751e12ee3bSFrançois Tigeot struct i915_vma *vma; 1376352ff8bdSFrançois Tigeot 137771f41f3eSFrançois Tigeot GEM_BUG_ON(!is_power_of_2(size)); 13781e12ee3bSFrançois Tigeot GEM_BUG_ON(RING_CTL_SIZE(size) & ~RING_NR_PAGES); 137971f41f3eSFrançois Tigeot 1380352ff8bdSFrançois Tigeot ring = kzalloc(sizeof(*ring), GFP_KERNEL); 13811e12ee3bSFrançois Tigeot if (!ring) 1382352ff8bdSFrançois Tigeot return ERR_PTR(-ENOMEM); 1383352ff8bdSFrançois Tigeot 13848621f407SFrançois Tigeot ring->engine = engine; 1385352ff8bdSFrançois Tigeot 138671f41f3eSFrançois Tigeot INIT_LIST_HEAD(&ring->request_list); 138771f41f3eSFrançois Tigeot 1388352ff8bdSFrançois Tigeot ring->size = size; 1389352ff8bdSFrançois Tigeot /* Workaround an erratum on the i830 which causes a hang if 1390352ff8bdSFrançois Tigeot * the TAIL pointer points to within the last 2 cachelines 1391352ff8bdSFrançois Tigeot * of the buffer. 1392352ff8bdSFrançois Tigeot */ 1393352ff8bdSFrançois Tigeot ring->effective_size = size; 1394*a85cb24fSFrançois Tigeot if (IS_I830(engine->i915) || IS_I845G(engine->i915)) 1395352ff8bdSFrançois Tigeot ring->effective_size -= 2 * CACHELINE_BYTES; 1396352ff8bdSFrançois Tigeot 1397352ff8bdSFrançois Tigeot intel_ring_update_space(ring); 1398352ff8bdSFrançois Tigeot 13991e12ee3bSFrançois Tigeot vma = intel_ring_create_vma(engine->i915, size); 14001e12ee3bSFrançois Tigeot if (IS_ERR(vma)) { 1401352ff8bdSFrançois Tigeot kfree(ring); 14021e12ee3bSFrançois Tigeot return ERR_CAST(vma); 1403352ff8bdSFrançois Tigeot } 14041e12ee3bSFrançois Tigeot ring->vma = vma; 1405352ff8bdSFrançois Tigeot 1406352ff8bdSFrançois Tigeot return ring; 1407352ff8bdSFrançois Tigeot } 1408352ff8bdSFrançois Tigeot 1409352ff8bdSFrançois Tigeot void 141071f41f3eSFrançois Tigeot intel_ring_free(struct intel_ring *ring) 1411352ff8bdSFrançois Tigeot { 14124be47400SFrançois Tigeot struct drm_i915_gem_object *obj = ring->vma->obj; 14134be47400SFrançois Tigeot 14144be47400SFrançois Tigeot i915_vma_close(ring->vma); 14154be47400SFrançois Tigeot __i915_gem_object_release_unless_active(obj); 14164be47400SFrançois Tigeot 1417352ff8bdSFrançois Tigeot kfree(ring); 1418352ff8bdSFrançois Tigeot } 1419352ff8bdSFrançois Tigeot 1420*a85cb24fSFrançois Tigeot static int context_pin(struct i915_gem_context *ctx) 1421*a85cb24fSFrançois Tigeot { 1422*a85cb24fSFrançois Tigeot struct i915_vma *vma = ctx->engine[RCS].state; 1423*a85cb24fSFrançois Tigeot int ret; 1424*a85cb24fSFrançois Tigeot 1425*a85cb24fSFrançois Tigeot /* Clear this page out of any CPU caches for coherent swap-in/out. 1426*a85cb24fSFrançois Tigeot * We only want to do this on the first bind so that we do not stall 1427*a85cb24fSFrançois Tigeot * on an active context (which by nature is already on the GPU). 1428*a85cb24fSFrançois Tigeot */ 1429*a85cb24fSFrançois Tigeot if (!(vma->flags & I915_VMA_GLOBAL_BIND)) { 1430*a85cb24fSFrançois Tigeot ret = i915_gem_object_set_to_gtt_domain(vma->obj, false); 1431*a85cb24fSFrançois Tigeot if (ret) 1432*a85cb24fSFrançois Tigeot return ret; 1433*a85cb24fSFrançois Tigeot } 1434*a85cb24fSFrançois Tigeot 1435*a85cb24fSFrançois Tigeot return i915_vma_pin(vma, 0, I915_GTT_MIN_ALIGNMENT, 1436*a85cb24fSFrançois Tigeot PIN_GLOBAL | PIN_HIGH); 1437*a85cb24fSFrançois Tigeot } 1438*a85cb24fSFrançois Tigeot 1439*a85cb24fSFrançois Tigeot static int intel_ring_context_pin(struct intel_engine_cs *engine, 1440*a85cb24fSFrançois Tigeot struct i915_gem_context *ctx) 14411487f786SFrançois Tigeot { 14421487f786SFrançois Tigeot struct intel_context *ce = &ctx->engine[engine->id]; 14431487f786SFrançois Tigeot int ret; 14441487f786SFrançois Tigeot 1445303bf270SFrançois Tigeot lockdep_assert_held(&ctx->i915->drm.struct_mutex); 14461487f786SFrançois Tigeot 14471487f786SFrançois Tigeot if (ce->pin_count++) 14481487f786SFrançois Tigeot return 0; 1449*a85cb24fSFrançois Tigeot GEM_BUG_ON(!ce->pin_count); /* no overflow please! */ 14501487f786SFrançois Tigeot 14511487f786SFrançois Tigeot if (ce->state) { 1452*a85cb24fSFrançois Tigeot ret = context_pin(ctx); 1453*a85cb24fSFrançois Tigeot if (ret) 14541487f786SFrançois Tigeot goto error; 1455*a85cb24fSFrançois Tigeot 1456*a85cb24fSFrançois Tigeot ce->state->obj->mm.dirty = true; 14574be47400SFrançois Tigeot } 14581487f786SFrançois Tigeot 14591487f786SFrançois Tigeot /* The kernel context is only used as a placeholder for flushing the 14601487f786SFrançois Tigeot * active context. It is never used for submitting user rendering and 14611487f786SFrançois Tigeot * as such never requires the golden render context, and so we can skip 14621487f786SFrançois Tigeot * emitting it when we switch to the kernel context. This is required 14631487f786SFrançois Tigeot * as during eviction we cannot allocate and pin the renderstate in 14641487f786SFrançois Tigeot * order to initialise the context. 14651487f786SFrançois Tigeot */ 1466*a85cb24fSFrançois Tigeot if (i915_gem_context_is_kernel(ctx)) 14671487f786SFrançois Tigeot ce->initialised = true; 14681487f786SFrançois Tigeot 146987df8fc6SFrançois Tigeot i915_gem_context_get(ctx); 14701487f786SFrançois Tigeot return 0; 14711487f786SFrançois Tigeot 14721487f786SFrançois Tigeot error: 14731487f786SFrançois Tigeot ce->pin_count = 0; 14741487f786SFrançois Tigeot return ret; 14751487f786SFrançois Tigeot } 14761487f786SFrançois Tigeot 1477*a85cb24fSFrançois Tigeot static void intel_ring_context_unpin(struct intel_engine_cs *engine, 1478*a85cb24fSFrançois Tigeot struct i915_gem_context *ctx) 14791487f786SFrançois Tigeot { 14801487f786SFrançois Tigeot struct intel_context *ce = &ctx->engine[engine->id]; 14811487f786SFrançois Tigeot 1482303bf270SFrançois Tigeot lockdep_assert_held(&ctx->i915->drm.struct_mutex); 1483*a85cb24fSFrançois Tigeot GEM_BUG_ON(ce->pin_count == 0); 14841487f786SFrançois Tigeot 14851487f786SFrançois Tigeot if (--ce->pin_count) 14861487f786SFrançois Tigeot return; 14871487f786SFrançois Tigeot 14881487f786SFrançois Tigeot if (ce->state) 14891e12ee3bSFrançois Tigeot i915_vma_unpin(ce->state); 14901487f786SFrançois Tigeot 149187df8fc6SFrançois Tigeot i915_gem_context_put(ctx); 14921487f786SFrançois Tigeot } 14931487f786SFrançois Tigeot 149487df8fc6SFrançois Tigeot static int intel_init_ring_buffer(struct intel_engine_cs *engine) 1495ba55f2f5SFrançois Tigeot { 149687df8fc6SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 149771f41f3eSFrançois Tigeot struct intel_ring *ring; 1498ba55f2f5SFrançois Tigeot int ret; 1499ba55f2f5SFrançois Tigeot 15008621f407SFrançois Tigeot WARN_ON(engine->buffer); 15012c9916cdSFrançois Tigeot 150287df8fc6SFrançois Tigeot intel_engine_setup_common(engine); 150387df8fc6SFrançois Tigeot 150487df8fc6SFrançois Tigeot ret = intel_engine_init_common(engine); 1505303bf270SFrançois Tigeot if (ret) 1506303bf270SFrançois Tigeot goto error; 1507ba55f2f5SFrançois Tigeot 150871f41f3eSFrançois Tigeot ring = intel_engine_create_ring(engine, 32 * PAGE_SIZE); 150971f41f3eSFrançois Tigeot if (IS_ERR(ring)) { 151071f41f3eSFrançois Tigeot ret = PTR_ERR(ring); 1511aee94f86SFrançois Tigeot goto error; 1512aee94f86SFrançois Tigeot } 1513352ff8bdSFrançois Tigeot 15141e12ee3bSFrançois Tigeot if (HWS_NEEDS_PHYSICAL(dev_priv)) { 15151e12ee3bSFrançois Tigeot WARN_ON(engine->id != RCS); 15161e12ee3bSFrançois Tigeot ret = init_phys_status_page(engine); 1517e3adcf8fSFrançois Tigeot if (ret) 1518ba55f2f5SFrançois Tigeot goto error; 1519ba55f2f5SFrançois Tigeot } else { 15201e12ee3bSFrançois Tigeot ret = init_status_page(engine); 1521ba55f2f5SFrançois Tigeot if (ret) 1522ba55f2f5SFrançois Tigeot goto error; 1523ba55f2f5SFrançois Tigeot } 1524ba55f2f5SFrançois Tigeot 1525*a85cb24fSFrançois Tigeot /* Ring wraparound at offset 0 sometimes hangs. No idea why. */ 1526*a85cb24fSFrançois Tigeot ret = intel_ring_pin(ring, I915_GTT_PAGE_SIZE); 15272c9916cdSFrançois Tigeot if (ret) { 15281e12ee3bSFrançois Tigeot intel_ring_free(ring); 1529ba55f2f5SFrançois Tigeot goto error; 1530ba55f2f5SFrançois Tigeot } 15311e12ee3bSFrançois Tigeot engine->buffer = ring; 1532e3adcf8fSFrançois Tigeot 1533e3adcf8fSFrançois Tigeot return 0; 1534e3adcf8fSFrançois Tigeot 1535ba55f2f5SFrançois Tigeot error: 153671f41f3eSFrançois Tigeot intel_engine_cleanup(engine); 1537e3adcf8fSFrançois Tigeot return ret; 1538e3adcf8fSFrançois Tigeot } 1539e3adcf8fSFrançois Tigeot 154071f41f3eSFrançois Tigeot void intel_engine_cleanup(struct intel_engine_cs *engine) 1541e3adcf8fSFrançois Tigeot { 15422c9916cdSFrançois Tigeot struct drm_i915_private *dev_priv; 1543e3adcf8fSFrançois Tigeot 15441487f786SFrançois Tigeot dev_priv = engine->i915; 15452c9916cdSFrançois Tigeot 15468621f407SFrançois Tigeot if (engine->buffer) { 15471e12ee3bSFrançois Tigeot WARN_ON(INTEL_GEN(dev_priv) > 2 && 15481e12ee3bSFrançois Tigeot (I915_READ_MODE(engine) & MODE_IDLE) == 0); 1549b030f26bSFrançois Tigeot 155071f41f3eSFrançois Tigeot intel_ring_unpin(engine->buffer); 155171f41f3eSFrançois Tigeot intel_ring_free(engine->buffer); 15528621f407SFrançois Tigeot engine->buffer = NULL; 1553aee94f86SFrançois Tigeot } 1554e3adcf8fSFrançois Tigeot 15558621f407SFrançois Tigeot if (engine->cleanup) 15568621f407SFrançois Tigeot engine->cleanup(engine); 1557e3adcf8fSFrançois Tigeot 15581e12ee3bSFrançois Tigeot if (HWS_NEEDS_PHYSICAL(dev_priv)) { 15598621f407SFrançois Tigeot WARN_ON(engine->id != RCS); 15608621f407SFrançois Tigeot cleanup_phys_status_page(engine); 15611e12ee3bSFrançois Tigeot } else { 15621e12ee3bSFrançois Tigeot cleanup_status_page(engine); 1563c0e85e96SFrançois Tigeot } 1564ba55f2f5SFrançois Tigeot 156571f41f3eSFrançois Tigeot intel_engine_cleanup_common(engine); 15661487f786SFrançois Tigeot 15671487f786SFrançois Tigeot engine->i915 = NULL; 15681e12ee3bSFrançois Tigeot dev_priv->engine[engine->id] = NULL; 15691e12ee3bSFrançois Tigeot kfree(engine); 15701e12ee3bSFrançois Tigeot } 15711e12ee3bSFrançois Tigeot 15721e12ee3bSFrançois Tigeot void intel_legacy_submission_resume(struct drm_i915_private *dev_priv) 15731e12ee3bSFrançois Tigeot { 15741e12ee3bSFrançois Tigeot struct intel_engine_cs *engine; 15751e12ee3bSFrançois Tigeot enum intel_engine_id id; 15761e12ee3bSFrançois Tigeot 1577*a85cb24fSFrançois Tigeot /* Restart from the beginning of the rings for convenience */ 1578*a85cb24fSFrançois Tigeot for_each_engine(engine, dev_priv, id) 1579*a85cb24fSFrançois Tigeot intel_ring_reset(engine->buffer, 0); 1580e3adcf8fSFrançois Tigeot } 1581e3adcf8fSFrançois Tigeot 1582*a85cb24fSFrançois Tigeot static int ring_request_alloc(struct drm_i915_gem_request *request) 1583b5c29a34SFrançois Tigeot { 1584*a85cb24fSFrançois Tigeot u32 *cs; 1585*a85cb24fSFrançois Tigeot 1586*a85cb24fSFrançois Tigeot GEM_BUG_ON(!request->ctx->engine[request->engine->id].pin_count); 15879edbd4a0SFrançois Tigeot 15881487f786SFrançois Tigeot /* Flush enough space to reduce the likelihood of waiting after 15891487f786SFrançois Tigeot * we start building the request - in which case we will just 15901487f786SFrançois Tigeot * have to repeat work. 1591a05eeebfSFrançois Tigeot */ 15921487f786SFrançois Tigeot request->reserved_space += LEGACY_REQUEST_SIZE; 1593a2fdbec6SFrançois Tigeot 1594*a85cb24fSFrançois Tigeot GEM_BUG_ON(!request->engine->buffer); 159571f41f3eSFrançois Tigeot request->ring = request->engine->buffer; 1596a2fdbec6SFrançois Tigeot 1597*a85cb24fSFrançois Tigeot cs = intel_ring_begin(request, 0); 1598*a85cb24fSFrançois Tigeot if (IS_ERR(cs)) 1599*a85cb24fSFrançois Tigeot return PTR_ERR(cs); 1600a05eeebfSFrançois Tigeot 16011487f786SFrançois Tigeot request->reserved_space -= LEGACY_REQUEST_SIZE; 16021487f786SFrançois Tigeot return 0; 1603a05eeebfSFrançois Tigeot } 1604a05eeebfSFrançois Tigeot 16058621f407SFrançois Tigeot static int wait_for_space(struct drm_i915_gem_request *req, int bytes) 1606a05eeebfSFrançois Tigeot { 160771f41f3eSFrançois Tigeot struct intel_ring *ring = req->ring; 16088621f407SFrançois Tigeot struct drm_i915_gem_request *target; 16094be47400SFrançois Tigeot long timeout; 16104be47400SFrançois Tigeot 16114be47400SFrançois Tigeot lockdep_assert_held(&req->i915->drm.struct_mutex); 16128621f407SFrançois Tigeot 161371f41f3eSFrançois Tigeot intel_ring_update_space(ring); 161471f41f3eSFrançois Tigeot if (ring->space >= bytes) 16158621f407SFrançois Tigeot return 0; 16168621f407SFrançois Tigeot 16178621f407SFrançois Tigeot /* 16188621f407SFrançois Tigeot * Space is reserved in the ringbuffer for finalising the request, 16198621f407SFrançois Tigeot * as that cannot be allowed to fail. During request finalisation, 16208621f407SFrançois Tigeot * reserved_space is set to 0 to stop the overallocation and the 16218621f407SFrançois Tigeot * assumption is that then we never need to wait (which has the 16228621f407SFrançois Tigeot * risk of failing with EINTR). 16238621f407SFrançois Tigeot * 16248621f407SFrançois Tigeot * See also i915_gem_request_alloc() and i915_add_request(). 16258621f407SFrançois Tigeot */ 16261487f786SFrançois Tigeot GEM_BUG_ON(!req->reserved_space); 16278621f407SFrançois Tigeot 162871f41f3eSFrançois Tigeot list_for_each_entry(target, &ring->request_list, ring_link) { 16298621f407SFrançois Tigeot unsigned space; 16308621f407SFrançois Tigeot 16318621f407SFrançois Tigeot /* Would completion of this request free enough space? */ 1632*a85cb24fSFrançois Tigeot space = __intel_ring_space(target->postfix, ring->emit, 163371f41f3eSFrançois Tigeot ring->size); 16348621f407SFrançois Tigeot if (space >= bytes) 16358621f407SFrançois Tigeot break; 16368621f407SFrançois Tigeot } 16378621f407SFrançois Tigeot 163871f41f3eSFrançois Tigeot if (WARN_ON(&target->ring_link == &ring->request_list)) 16398621f407SFrançois Tigeot return -ENOSPC; 16408621f407SFrançois Tigeot 16414be47400SFrançois Tigeot timeout = i915_wait_request(target, 16421e12ee3bSFrançois Tigeot I915_WAIT_INTERRUPTIBLE | I915_WAIT_LOCKED, 16434be47400SFrançois Tigeot MAX_SCHEDULE_TIMEOUT); 16444be47400SFrançois Tigeot if (timeout < 0) 16454be47400SFrançois Tigeot return timeout; 164671f41f3eSFrançois Tigeot 164771f41f3eSFrançois Tigeot i915_gem_request_retire_upto(target); 164871f41f3eSFrançois Tigeot 164971f41f3eSFrançois Tigeot intel_ring_update_space(ring); 165071f41f3eSFrançois Tigeot GEM_BUG_ON(ring->space < bytes); 165171f41f3eSFrançois Tigeot return 0; 16528621f407SFrançois Tigeot } 16538621f407SFrançois Tigeot 1654*a85cb24fSFrançois Tigeot u32 *intel_ring_begin(struct drm_i915_gem_request *req, int num_dwords) 16558621f407SFrançois Tigeot { 165671f41f3eSFrançois Tigeot struct intel_ring *ring = req->ring; 1657*a85cb24fSFrançois Tigeot int remain_actual = ring->size - ring->emit; 1658*a85cb24fSFrançois Tigeot int remain_usable = ring->effective_size - ring->emit; 16598621f407SFrançois Tigeot int bytes = num_dwords * sizeof(u32); 16608621f407SFrançois Tigeot int total_bytes, wait_bytes; 1661a05eeebfSFrançois Tigeot bool need_wrap = false; 1662*a85cb24fSFrançois Tigeot u32 *cs; 1663a05eeebfSFrançois Tigeot 16641487f786SFrançois Tigeot total_bytes = bytes + req->reserved_space; 1665a05eeebfSFrançois Tigeot 1666a05eeebfSFrançois Tigeot if (unlikely(bytes > remain_usable)) { 1667a05eeebfSFrançois Tigeot /* 1668a05eeebfSFrançois Tigeot * Not enough space for the basic request. So need to flush 1669a05eeebfSFrançois Tigeot * out the remainder and then wait for base + reserved. 1670a05eeebfSFrançois Tigeot */ 1671a05eeebfSFrançois Tigeot wait_bytes = remain_actual + total_bytes; 1672a05eeebfSFrançois Tigeot need_wrap = true; 16738621f407SFrançois Tigeot } else if (unlikely(total_bytes > remain_usable)) { 1674a05eeebfSFrançois Tigeot /* 1675a05eeebfSFrançois Tigeot * The base request will fit but the reserved space 16768621f407SFrançois Tigeot * falls off the end. So we don't need an immediate wrap 1677c0e85e96SFrançois Tigeot * and only need to effectively wait for the reserved 1678c0e85e96SFrançois Tigeot * size space from the start of ringbuffer. 1679a05eeebfSFrançois Tigeot */ 16801487f786SFrançois Tigeot wait_bytes = remain_actual + req->reserved_space; 16818621f407SFrançois Tigeot } else { 1682a05eeebfSFrançois Tigeot /* No wrapping required, just waiting. */ 1683a05eeebfSFrançois Tigeot wait_bytes = total_bytes; 1684a05eeebfSFrançois Tigeot } 1685a05eeebfSFrançois Tigeot 168671f41f3eSFrançois Tigeot if (wait_bytes > ring->space) { 16878621f407SFrançois Tigeot int ret = wait_for_space(req, wait_bytes); 1688a2fdbec6SFrançois Tigeot if (unlikely(ret)) 1689*a85cb24fSFrançois Tigeot return ERR_PTR(ret); 1690a2fdbec6SFrançois Tigeot } 1691a2fdbec6SFrançois Tigeot 16928621f407SFrançois Tigeot if (unlikely(need_wrap)) { 169371f41f3eSFrançois Tigeot GEM_BUG_ON(remain_actual > ring->space); 1694*a85cb24fSFrançois Tigeot GEM_BUG_ON(ring->emit + remain_actual > ring->size); 16958621f407SFrançois Tigeot 16968621f407SFrançois Tigeot /* Fill the tail with MI_NOOP */ 1697*a85cb24fSFrançois Tigeot memset(ring->vaddr + ring->emit, 0, remain_actual); 1698*a85cb24fSFrançois Tigeot ring->emit = 0; 169971f41f3eSFrançois Tigeot ring->space -= remain_actual; 1700a2fdbec6SFrançois Tigeot } 1701a2fdbec6SFrançois Tigeot 1702*a85cb24fSFrançois Tigeot GEM_BUG_ON(ring->emit > ring->size - bytes); 1703*a85cb24fSFrançois Tigeot cs = ring->vaddr + ring->emit; 1704*a85cb24fSFrançois Tigeot ring->emit += bytes; 170571f41f3eSFrançois Tigeot ring->space -= bytes; 170671f41f3eSFrançois Tigeot GEM_BUG_ON(ring->space < 0); 1707*a85cb24fSFrançois Tigeot 1708*a85cb24fSFrançois Tigeot return cs; 17099edbd4a0SFrançois Tigeot } 17109edbd4a0SFrançois Tigeot 17119edbd4a0SFrançois Tigeot /* Align the ring tail to a cacheline boundary */ 1712a05eeebfSFrançois Tigeot int intel_ring_cacheline_align(struct drm_i915_gem_request *req) 17139edbd4a0SFrançois Tigeot { 171471f41f3eSFrançois Tigeot int num_dwords = 1715*a85cb24fSFrançois Tigeot (req->ring->emit & (CACHELINE_BYTES - 1)) / sizeof(uint32_t); 1716*a85cb24fSFrançois Tigeot u32 *cs; 17179edbd4a0SFrançois Tigeot 17189edbd4a0SFrançois Tigeot if (num_dwords == 0) 17199edbd4a0SFrançois Tigeot return 0; 17209edbd4a0SFrançois Tigeot 1721ba55f2f5SFrançois Tigeot num_dwords = CACHELINE_BYTES / sizeof(uint32_t) - num_dwords; 1722*a85cb24fSFrançois Tigeot cs = intel_ring_begin(req, num_dwords); 1723*a85cb24fSFrançois Tigeot if (IS_ERR(cs)) 1724*a85cb24fSFrançois Tigeot return PTR_ERR(cs); 17259edbd4a0SFrançois Tigeot 17269edbd4a0SFrançois Tigeot while (num_dwords--) 1727*a85cb24fSFrançois Tigeot *cs++ = MI_NOOP; 17289edbd4a0SFrançois Tigeot 1729*a85cb24fSFrançois Tigeot intel_ring_advance(req, cs); 17309edbd4a0SFrançois Tigeot 17319edbd4a0SFrançois Tigeot return 0; 1732e3adcf8fSFrançois Tigeot } 1733e3adcf8fSFrançois Tigeot 173471f41f3eSFrançois Tigeot static void gen6_bsd_submit_request(struct drm_i915_gem_request *request) 1735e3adcf8fSFrançois Tigeot { 173671f41f3eSFrançois Tigeot struct drm_i915_private *dev_priv = request->i915; 17371487f786SFrançois Tigeot 17381487f786SFrançois Tigeot intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL); 1739e3adcf8fSFrançois Tigeot 1740e3adcf8fSFrançois Tigeot /* Every tail move must follow the sequence below */ 1741f4e1c372SFrançois Tigeot 1742f4e1c372SFrançois Tigeot /* Disable notification that the ring is IDLE. The GT 1743f4e1c372SFrançois Tigeot * will then assume that it is busy and bring it out of rc6. 1744f4e1c372SFrançois Tigeot */ 17451487f786SFrançois Tigeot I915_WRITE_FW(GEN6_BSD_SLEEP_PSMI_CONTROL, 1746f4e1c372SFrançois Tigeot _MASKED_BIT_ENABLE(GEN6_BSD_SLEEP_MSG_DISABLE)); 1747e3adcf8fSFrançois Tigeot 1748f4e1c372SFrançois Tigeot /* Clear the context id. Here be magic! */ 17491487f786SFrançois Tigeot I915_WRITE64_FW(GEN6_BSD_RNCID, 0x0); 1750e3adcf8fSFrançois Tigeot 1751f4e1c372SFrançois Tigeot /* Wait for the ring not to be idle, i.e. for it to wake up. */ 17521487f786SFrançois Tigeot if (intel_wait_for_register_fw(dev_priv, 17531487f786SFrançois Tigeot GEN6_BSD_SLEEP_PSMI_CONTROL, 17541487f786SFrançois Tigeot GEN6_BSD_SLEEP_INDICATOR, 17551487f786SFrançois Tigeot 0, 1756f4e1c372SFrançois Tigeot 50)) 1757f4e1c372SFrançois Tigeot DRM_ERROR("timed out waiting for the BSD ring to wake up\n"); 1758f4e1c372SFrançois Tigeot 1759f4e1c372SFrançois Tigeot /* Now that the ring is fully powered up, update the tail */ 176071f41f3eSFrançois Tigeot i9xx_submit_request(request); 1761f4e1c372SFrançois Tigeot 1762f4e1c372SFrançois Tigeot /* Let the ring send IDLE messages to the GT again, 1763f4e1c372SFrançois Tigeot * and so let it sleep to conserve power when idle. 1764f4e1c372SFrançois Tigeot */ 17651487f786SFrançois Tigeot I915_WRITE_FW(GEN6_BSD_SLEEP_PSMI_CONTROL, 1766f4e1c372SFrançois Tigeot _MASKED_BIT_DISABLE(GEN6_BSD_SLEEP_MSG_DISABLE)); 17671487f786SFrançois Tigeot 17681487f786SFrançois Tigeot intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL); 1769e3adcf8fSFrançois Tigeot } 1770e3adcf8fSFrançois Tigeot 177171f41f3eSFrançois Tigeot static int gen6_bsd_ring_flush(struct drm_i915_gem_request *req, u32 mode) 1772e3adcf8fSFrançois Tigeot { 1773*a85cb24fSFrançois Tigeot u32 cmd, *cs; 1774e3adcf8fSFrançois Tigeot 1775*a85cb24fSFrançois Tigeot cs = intel_ring_begin(req, 4); 1776*a85cb24fSFrançois Tigeot if (IS_ERR(cs)) 1777*a85cb24fSFrançois Tigeot return PTR_ERR(cs); 1778e3adcf8fSFrançois Tigeot 1779e3adcf8fSFrançois Tigeot cmd = MI_FLUSH_DW; 17801487f786SFrançois Tigeot if (INTEL_GEN(req->i915) >= 8) 17819edbd4a0SFrançois Tigeot cmd += 1; 17822c9916cdSFrançois Tigeot 17832c9916cdSFrançois Tigeot /* We always require a command barrier so that subsequent 17842c9916cdSFrançois Tigeot * commands, such as breadcrumb interrupts, are strictly ordered 17852c9916cdSFrançois Tigeot * wrt the contents of the write cache being flushed to memory 17862c9916cdSFrançois Tigeot * (and thus being coherent from the CPU). 17872c9916cdSFrançois Tigeot */ 17882c9916cdSFrançois Tigeot cmd |= MI_FLUSH_DW_STORE_INDEX | MI_FLUSH_DW_OP_STOREDW; 17892c9916cdSFrançois Tigeot 1790b5c29a34SFrançois Tigeot /* 1791b5c29a34SFrançois Tigeot * Bspec vol 1c.5 - video engine command streamer: 1792b5c29a34SFrançois Tigeot * "If ENABLED, all TLBs will be invalidated once the flush 1793b5c29a34SFrançois Tigeot * operation is complete. This bit is only valid when the 1794b5c29a34SFrançois Tigeot * Post-Sync Operation field is a value of 1h or 3h." 1795b5c29a34SFrançois Tigeot */ 179671f41f3eSFrançois Tigeot if (mode & EMIT_INVALIDATE) 17972c9916cdSFrançois Tigeot cmd |= MI_INVALIDATE_TLB | MI_INVALIDATE_BSD; 17982c9916cdSFrançois Tigeot 1799*a85cb24fSFrançois Tigeot *cs++ = cmd; 1800*a85cb24fSFrançois Tigeot *cs++ = I915_GEM_HWS_SCRATCH_ADDR | MI_FLUSH_DW_USE_GTT; 18011487f786SFrançois Tigeot if (INTEL_GEN(req->i915) >= 8) { 1802*a85cb24fSFrançois Tigeot *cs++ = 0; /* upper addr */ 1803*a85cb24fSFrançois Tigeot *cs++ = 0; /* value */ 18049edbd4a0SFrançois Tigeot } else { 1805*a85cb24fSFrançois Tigeot *cs++ = 0; 1806*a85cb24fSFrançois Tigeot *cs++ = MI_NOOP; 18079edbd4a0SFrançois Tigeot } 1808*a85cb24fSFrançois Tigeot intel_ring_advance(req, cs); 18099edbd4a0SFrançois Tigeot return 0; 18109edbd4a0SFrançois Tigeot } 18119edbd4a0SFrançois Tigeot 18129edbd4a0SFrançois Tigeot static int 181371f41f3eSFrançois Tigeot gen8_emit_bb_start(struct drm_i915_gem_request *req, 1814ba55f2f5SFrançois Tigeot u64 offset, u32 len, 181571f41f3eSFrançois Tigeot unsigned int dispatch_flags) 18169edbd4a0SFrançois Tigeot { 181771f41f3eSFrançois Tigeot bool ppgtt = USES_PPGTT(req->i915) && 1818477eb7f9SFrançois Tigeot !(dispatch_flags & I915_DISPATCH_SECURE); 1819*a85cb24fSFrançois Tigeot u32 *cs; 18209edbd4a0SFrançois Tigeot 1821*a85cb24fSFrançois Tigeot cs = intel_ring_begin(req, 4); 1822*a85cb24fSFrançois Tigeot if (IS_ERR(cs)) 1823*a85cb24fSFrançois Tigeot return PTR_ERR(cs); 18249edbd4a0SFrançois Tigeot 18259edbd4a0SFrançois Tigeot /* FIXME(BDW): Address space and security selectors. */ 1826*a85cb24fSFrançois Tigeot *cs++ = MI_BATCH_BUFFER_START_GEN8 | (ppgtt << 8) | (dispatch_flags & 1827*a85cb24fSFrançois Tigeot I915_DISPATCH_RS ? MI_BATCH_RESOURCE_STREAMER : 0); 1828*a85cb24fSFrançois Tigeot *cs++ = lower_32_bits(offset); 1829*a85cb24fSFrançois Tigeot *cs++ = upper_32_bits(offset); 1830*a85cb24fSFrançois Tigeot *cs++ = MI_NOOP; 1831*a85cb24fSFrançois Tigeot intel_ring_advance(req, cs); 18329edbd4a0SFrançois Tigeot 1833e3adcf8fSFrançois Tigeot return 0; 1834e3adcf8fSFrançois Tigeot } 1835e3adcf8fSFrançois Tigeot 1836e3adcf8fSFrançois Tigeot static int 183771f41f3eSFrançois Tigeot hsw_emit_bb_start(struct drm_i915_gem_request *req, 1838ba55f2f5SFrançois Tigeot u64 offset, u32 len, 183971f41f3eSFrançois Tigeot unsigned int dispatch_flags) 1840e3adcf8fSFrançois Tigeot { 1841*a85cb24fSFrançois Tigeot u32 *cs; 1842e3adcf8fSFrançois Tigeot 1843*a85cb24fSFrançois Tigeot cs = intel_ring_begin(req, 2); 1844*a85cb24fSFrançois Tigeot if (IS_ERR(cs)) 1845*a85cb24fSFrançois Tigeot return PTR_ERR(cs); 1846e3adcf8fSFrançois Tigeot 1847*a85cb24fSFrançois Tigeot *cs++ = MI_BATCH_BUFFER_START | (dispatch_flags & I915_DISPATCH_SECURE ? 1848a05eeebfSFrançois Tigeot 0 : MI_BATCH_PPGTT_HSW | MI_BATCH_NON_SECURE_HSW) | 1849a05eeebfSFrançois Tigeot (dispatch_flags & I915_DISPATCH_RS ? 1850*a85cb24fSFrançois Tigeot MI_BATCH_RESOURCE_STREAMER : 0); 1851b5c29a34SFrançois Tigeot /* bit0-7 is the length on GEN6+ */ 1852*a85cb24fSFrançois Tigeot *cs++ = offset; 1853*a85cb24fSFrançois Tigeot intel_ring_advance(req, cs); 1854b5c29a34SFrançois Tigeot 1855b5c29a34SFrançois Tigeot return 0; 1856b5c29a34SFrançois Tigeot } 1857b5c29a34SFrançois Tigeot 1858b5c29a34SFrançois Tigeot static int 185971f41f3eSFrançois Tigeot gen6_emit_bb_start(struct drm_i915_gem_request *req, 1860ba55f2f5SFrançois Tigeot u64 offset, u32 len, 186171f41f3eSFrançois Tigeot unsigned int dispatch_flags) 1862b5c29a34SFrançois Tigeot { 1863*a85cb24fSFrançois Tigeot u32 *cs; 1864b5c29a34SFrançois Tigeot 1865*a85cb24fSFrançois Tigeot cs = intel_ring_begin(req, 2); 1866*a85cb24fSFrançois Tigeot if (IS_ERR(cs)) 1867*a85cb24fSFrançois Tigeot return PTR_ERR(cs); 1868b5c29a34SFrançois Tigeot 1869*a85cb24fSFrançois Tigeot *cs++ = MI_BATCH_BUFFER_START | (dispatch_flags & I915_DISPATCH_SECURE ? 1870*a85cb24fSFrançois Tigeot 0 : MI_BATCH_NON_SECURE_I965); 1871e3adcf8fSFrançois Tigeot /* bit0-7 is the length on GEN6+ */ 1872*a85cb24fSFrançois Tigeot *cs++ = offset; 1873*a85cb24fSFrançois Tigeot intel_ring_advance(req, cs); 1874e3adcf8fSFrançois Tigeot 1875e3adcf8fSFrançois Tigeot return 0; 1876e3adcf8fSFrançois Tigeot } 1877e3adcf8fSFrançois Tigeot 1878e3adcf8fSFrançois Tigeot /* Blitter support (SandyBridge+) */ 1879e3adcf8fSFrançois Tigeot 188071f41f3eSFrançois Tigeot static int gen6_ring_flush(struct drm_i915_gem_request *req, u32 mode) 1881e3adcf8fSFrançois Tigeot { 1882*a85cb24fSFrançois Tigeot u32 cmd, *cs; 1883e3adcf8fSFrançois Tigeot 1884*a85cb24fSFrançois Tigeot cs = intel_ring_begin(req, 4); 1885*a85cb24fSFrançois Tigeot if (IS_ERR(cs)) 1886*a85cb24fSFrançois Tigeot return PTR_ERR(cs); 1887e3adcf8fSFrançois Tigeot 1888e3adcf8fSFrançois Tigeot cmd = MI_FLUSH_DW; 18891487f786SFrançois Tigeot if (INTEL_GEN(req->i915) >= 8) 18909edbd4a0SFrançois Tigeot cmd += 1; 18912c9916cdSFrançois Tigeot 18922c9916cdSFrançois Tigeot /* We always require a command barrier so that subsequent 18932c9916cdSFrançois Tigeot * commands, such as breadcrumb interrupts, are strictly ordered 18942c9916cdSFrançois Tigeot * wrt the contents of the write cache being flushed to memory 18952c9916cdSFrançois Tigeot * (and thus being coherent from the CPU). 18962c9916cdSFrançois Tigeot */ 18972c9916cdSFrançois Tigeot cmd |= MI_FLUSH_DW_STORE_INDEX | MI_FLUSH_DW_OP_STOREDW; 18982c9916cdSFrançois Tigeot 1899b5c29a34SFrançois Tigeot /* 1900b5c29a34SFrançois Tigeot * Bspec vol 1c.3 - blitter engine command streamer: 1901b5c29a34SFrançois Tigeot * "If ENABLED, all TLBs will be invalidated once the flush 1902b5c29a34SFrançois Tigeot * operation is complete. This bit is only valid when the 1903b5c29a34SFrançois Tigeot * Post-Sync Operation field is a value of 1h or 3h." 1904b5c29a34SFrançois Tigeot */ 190571f41f3eSFrançois Tigeot if (mode & EMIT_INVALIDATE) 19062c9916cdSFrançois Tigeot cmd |= MI_INVALIDATE_TLB; 1907*a85cb24fSFrançois Tigeot *cs++ = cmd; 1908*a85cb24fSFrançois Tigeot *cs++ = I915_GEM_HWS_SCRATCH_ADDR | MI_FLUSH_DW_USE_GTT; 19091487f786SFrançois Tigeot if (INTEL_GEN(req->i915) >= 8) { 1910*a85cb24fSFrançois Tigeot *cs++ = 0; /* upper addr */ 1911*a85cb24fSFrançois Tigeot *cs++ = 0; /* value */ 19129edbd4a0SFrançois Tigeot } else { 1913*a85cb24fSFrançois Tigeot *cs++ = 0; 1914*a85cb24fSFrançois Tigeot *cs++ = MI_NOOP; 19159edbd4a0SFrançois Tigeot } 1916*a85cb24fSFrançois Tigeot intel_ring_advance(req, cs); 19175d0b1887SFrançois Tigeot 1918e3adcf8fSFrançois Tigeot return 0; 1919e3adcf8fSFrançois Tigeot } 1920e3adcf8fSFrançois Tigeot 19211487f786SFrançois Tigeot static void intel_ring_init_semaphores(struct drm_i915_private *dev_priv, 19221487f786SFrançois Tigeot struct intel_engine_cs *engine) 19231487f786SFrançois Tigeot { 19241487f786SFrançois Tigeot struct drm_i915_gem_object *obj; 19251487f786SFrançois Tigeot int ret, i; 19261487f786SFrançois Tigeot 192787df8fc6SFrançois Tigeot if (!i915.semaphores) 19281487f786SFrançois Tigeot return; 19291487f786SFrançois Tigeot 19301e12ee3bSFrançois Tigeot if (INTEL_GEN(dev_priv) >= 8 && !dev_priv->semaphore) { 19311e12ee3bSFrançois Tigeot struct i915_vma *vma; 19321487f786SFrançois Tigeot 1933*a85cb24fSFrançois Tigeot obj = i915_gem_object_create(dev_priv, PAGE_SIZE); 19341e12ee3bSFrançois Tigeot if (IS_ERR(obj)) 19351e12ee3bSFrançois Tigeot goto err; 19361e12ee3bSFrançois Tigeot 1937*a85cb24fSFrançois Tigeot vma = i915_vma_instance(obj, &dev_priv->ggtt.base, NULL); 19381e12ee3bSFrançois Tigeot if (IS_ERR(vma)) 19391e12ee3bSFrançois Tigeot goto err_obj; 19401e12ee3bSFrançois Tigeot 19411e12ee3bSFrançois Tigeot ret = i915_gem_object_set_to_gtt_domain(obj, false); 19421e12ee3bSFrançois Tigeot if (ret) 19431e12ee3bSFrançois Tigeot goto err_obj; 19441e12ee3bSFrançois Tigeot 19451e12ee3bSFrançois Tigeot ret = i915_vma_pin(vma, 0, 0, PIN_GLOBAL | PIN_HIGH); 19461e12ee3bSFrançois Tigeot if (ret) 19471e12ee3bSFrançois Tigeot goto err_obj; 19481e12ee3bSFrançois Tigeot 19491e12ee3bSFrançois Tigeot dev_priv->semaphore = vma; 19501e12ee3bSFrançois Tigeot } 19511487f786SFrançois Tigeot 19521487f786SFrançois Tigeot if (INTEL_GEN(dev_priv) >= 8) { 19531e12ee3bSFrançois Tigeot u32 offset = i915_ggtt_offset(dev_priv->semaphore); 19541487f786SFrançois Tigeot 195571f41f3eSFrançois Tigeot engine->semaphore.sync_to = gen8_ring_sync_to; 19561487f786SFrançois Tigeot engine->semaphore.signal = gen8_xcs_signal; 19571487f786SFrançois Tigeot 19581487f786SFrançois Tigeot for (i = 0; i < I915_NUM_ENGINES; i++) { 19591e12ee3bSFrançois Tigeot u32 ring_offset; 19601487f786SFrançois Tigeot 19611487f786SFrançois Tigeot if (i != engine->id) 19621487f786SFrançois Tigeot ring_offset = offset + GEN8_SEMAPHORE_OFFSET(engine->id, i); 19631487f786SFrançois Tigeot else 19641487f786SFrançois Tigeot ring_offset = MI_SEMAPHORE_SYNC_INVALID; 19651487f786SFrançois Tigeot 19661487f786SFrançois Tigeot engine->semaphore.signal_ggtt[i] = ring_offset; 19671487f786SFrançois Tigeot } 19681487f786SFrançois Tigeot } else if (INTEL_GEN(dev_priv) >= 6) { 196971f41f3eSFrançois Tigeot engine->semaphore.sync_to = gen6_ring_sync_to; 19701487f786SFrançois Tigeot engine->semaphore.signal = gen6_signal; 19711487f786SFrançois Tigeot 19721487f786SFrançois Tigeot /* 19731487f786SFrançois Tigeot * The current semaphore is only applied on pre-gen8 19741487f786SFrançois Tigeot * platform. And there is no VCS2 ring on the pre-gen8 19751487f786SFrançois Tigeot * platform. So the semaphore between RCS and VCS2 is 19761487f786SFrançois Tigeot * initialized as INVALID. Gen8 will initialize the 19771487f786SFrançois Tigeot * sema between VCS2 and RCS later. 19781487f786SFrançois Tigeot */ 19791e12ee3bSFrançois Tigeot for (i = 0; i < GEN6_NUM_SEMAPHORES; i++) { 19801487f786SFrançois Tigeot static const struct { 19811487f786SFrançois Tigeot u32 wait_mbox; 19821487f786SFrançois Tigeot i915_reg_t mbox_reg; 19831e12ee3bSFrançois Tigeot } sem_data[GEN6_NUM_SEMAPHORES][GEN6_NUM_SEMAPHORES] = { 19841e12ee3bSFrançois Tigeot [RCS_HW] = { 19851e12ee3bSFrançois Tigeot [VCS_HW] = { .wait_mbox = MI_SEMAPHORE_SYNC_RV, .mbox_reg = GEN6_VRSYNC }, 19861e12ee3bSFrançois Tigeot [BCS_HW] = { .wait_mbox = MI_SEMAPHORE_SYNC_RB, .mbox_reg = GEN6_BRSYNC }, 19871e12ee3bSFrançois Tigeot [VECS_HW] = { .wait_mbox = MI_SEMAPHORE_SYNC_RVE, .mbox_reg = GEN6_VERSYNC }, 19881487f786SFrançois Tigeot }, 19891e12ee3bSFrançois Tigeot [VCS_HW] = { 19901e12ee3bSFrançois Tigeot [RCS_HW] = { .wait_mbox = MI_SEMAPHORE_SYNC_VR, .mbox_reg = GEN6_RVSYNC }, 19911e12ee3bSFrançois Tigeot [BCS_HW] = { .wait_mbox = MI_SEMAPHORE_SYNC_VB, .mbox_reg = GEN6_BVSYNC }, 19921e12ee3bSFrançois Tigeot [VECS_HW] = { .wait_mbox = MI_SEMAPHORE_SYNC_VVE, .mbox_reg = GEN6_VEVSYNC }, 19931487f786SFrançois Tigeot }, 19941e12ee3bSFrançois Tigeot [BCS_HW] = { 19951e12ee3bSFrançois Tigeot [RCS_HW] = { .wait_mbox = MI_SEMAPHORE_SYNC_BR, .mbox_reg = GEN6_RBSYNC }, 19961e12ee3bSFrançois Tigeot [VCS_HW] = { .wait_mbox = MI_SEMAPHORE_SYNC_BV, .mbox_reg = GEN6_VBSYNC }, 19971e12ee3bSFrançois Tigeot [VECS_HW] = { .wait_mbox = MI_SEMAPHORE_SYNC_BVE, .mbox_reg = GEN6_VEBSYNC }, 19981487f786SFrançois Tigeot }, 19991e12ee3bSFrançois Tigeot [VECS_HW] = { 20001e12ee3bSFrançois Tigeot [RCS_HW] = { .wait_mbox = MI_SEMAPHORE_SYNC_VER, .mbox_reg = GEN6_RVESYNC }, 20011e12ee3bSFrançois Tigeot [VCS_HW] = { .wait_mbox = MI_SEMAPHORE_SYNC_VEV, .mbox_reg = GEN6_VVESYNC }, 20021e12ee3bSFrançois Tigeot [BCS_HW] = { .wait_mbox = MI_SEMAPHORE_SYNC_VEB, .mbox_reg = GEN6_BVESYNC }, 20031487f786SFrançois Tigeot }, 20041487f786SFrançois Tigeot }; 20051487f786SFrançois Tigeot u32 wait_mbox; 20061487f786SFrançois Tigeot i915_reg_t mbox_reg; 20071487f786SFrançois Tigeot 20081e12ee3bSFrançois Tigeot if (i == engine->hw_id) { 20091487f786SFrançois Tigeot wait_mbox = MI_SEMAPHORE_SYNC_INVALID; 20101487f786SFrançois Tigeot mbox_reg = GEN6_NOSYNC; 20111487f786SFrançois Tigeot } else { 20121e12ee3bSFrançois Tigeot wait_mbox = sem_data[engine->hw_id][i].wait_mbox; 20131e12ee3bSFrançois Tigeot mbox_reg = sem_data[engine->hw_id][i].mbox_reg; 20141487f786SFrançois Tigeot } 20151487f786SFrançois Tigeot 20161487f786SFrançois Tigeot engine->semaphore.mbox.wait[i] = wait_mbox; 20171487f786SFrançois Tigeot engine->semaphore.mbox.signal[i] = mbox_reg; 20181487f786SFrançois Tigeot } 20191487f786SFrançois Tigeot } 20201e12ee3bSFrançois Tigeot 20211e12ee3bSFrançois Tigeot return; 20221e12ee3bSFrançois Tigeot 20231e12ee3bSFrançois Tigeot err_obj: 20241e12ee3bSFrançois Tigeot i915_gem_object_put(obj); 20251e12ee3bSFrançois Tigeot err: 20261e12ee3bSFrançois Tigeot DRM_DEBUG_DRIVER("Failed to allocate space for semaphores, disabling\n"); 20271e12ee3bSFrançois Tigeot i915.semaphores = 0; 20281487f786SFrançois Tigeot } 20291487f786SFrançois Tigeot 20301487f786SFrançois Tigeot static void intel_ring_init_irq(struct drm_i915_private *dev_priv, 20311487f786SFrançois Tigeot struct intel_engine_cs *engine) 20321487f786SFrançois Tigeot { 203387df8fc6SFrançois Tigeot engine->irq_enable_mask = GT_RENDER_USER_INTERRUPT << engine->irq_shift; 203487df8fc6SFrançois Tigeot 20351487f786SFrançois Tigeot if (INTEL_GEN(dev_priv) >= 8) { 2036303bf270SFrançois Tigeot engine->irq_enable = gen8_irq_enable; 2037303bf270SFrançois Tigeot engine->irq_disable = gen8_irq_disable; 20381487f786SFrançois Tigeot engine->irq_seqno_barrier = gen6_seqno_barrier; 20391487f786SFrançois Tigeot } else if (INTEL_GEN(dev_priv) >= 6) { 2040303bf270SFrançois Tigeot engine->irq_enable = gen6_irq_enable; 2041303bf270SFrançois Tigeot engine->irq_disable = gen6_irq_disable; 20421487f786SFrançois Tigeot engine->irq_seqno_barrier = gen6_seqno_barrier; 20431487f786SFrançois Tigeot } else if (INTEL_GEN(dev_priv) >= 5) { 2044303bf270SFrançois Tigeot engine->irq_enable = gen5_irq_enable; 2045303bf270SFrançois Tigeot engine->irq_disable = gen5_irq_disable; 2046303bf270SFrançois Tigeot engine->irq_seqno_barrier = gen5_seqno_barrier; 20471487f786SFrançois Tigeot } else if (INTEL_GEN(dev_priv) >= 3) { 2048303bf270SFrançois Tigeot engine->irq_enable = i9xx_irq_enable; 2049303bf270SFrançois Tigeot engine->irq_disable = i9xx_irq_disable; 20501487f786SFrançois Tigeot } else { 2051303bf270SFrançois Tigeot engine->irq_enable = i8xx_irq_enable; 2052303bf270SFrançois Tigeot engine->irq_disable = i8xx_irq_disable; 20531487f786SFrançois Tigeot } 20541487f786SFrançois Tigeot } 20551487f786SFrançois Tigeot 2056*a85cb24fSFrançois Tigeot static void i9xx_set_default_submission(struct intel_engine_cs *engine) 2057*a85cb24fSFrançois Tigeot { 2058*a85cb24fSFrançois Tigeot engine->submit_request = i9xx_submit_request; 2059*a85cb24fSFrançois Tigeot } 2060*a85cb24fSFrançois Tigeot 2061*a85cb24fSFrançois Tigeot static void gen6_bsd_set_default_submission(struct intel_engine_cs *engine) 2062*a85cb24fSFrançois Tigeot { 2063*a85cb24fSFrançois Tigeot engine->submit_request = gen6_bsd_submit_request; 2064*a85cb24fSFrançois Tigeot } 2065*a85cb24fSFrançois Tigeot 20661487f786SFrançois Tigeot static void intel_ring_default_vfuncs(struct drm_i915_private *dev_priv, 20671487f786SFrançois Tigeot struct intel_engine_cs *engine) 20681487f786SFrançois Tigeot { 20691487f786SFrançois Tigeot intel_ring_init_irq(dev_priv, engine); 20701487f786SFrançois Tigeot intel_ring_init_semaphores(dev_priv, engine); 207171f41f3eSFrançois Tigeot 207271f41f3eSFrançois Tigeot engine->init_hw = init_ring_common; 20731e12ee3bSFrançois Tigeot engine->reset_hw = reset_ring_common; 207471f41f3eSFrançois Tigeot 2075*a85cb24fSFrançois Tigeot engine->context_pin = intel_ring_context_pin; 2076*a85cb24fSFrançois Tigeot engine->context_unpin = intel_ring_context_unpin; 2077*a85cb24fSFrançois Tigeot 2078*a85cb24fSFrançois Tigeot engine->request_alloc = ring_request_alloc; 2079*a85cb24fSFrançois Tigeot 20804be47400SFrançois Tigeot engine->emit_breadcrumb = i9xx_emit_breadcrumb; 20814be47400SFrançois Tigeot engine->emit_breadcrumb_sz = i9xx_emit_breadcrumb_sz; 20824be47400SFrançois Tigeot if (i915.semaphores) { 20834be47400SFrançois Tigeot int num_rings; 20844be47400SFrançois Tigeot 20854be47400SFrançois Tigeot engine->emit_breadcrumb = gen6_sema_emit_breadcrumb; 20864be47400SFrançois Tigeot 20874be47400SFrançois Tigeot num_rings = hweight32(INTEL_INFO(dev_priv)->ring_mask) - 1; 20884be47400SFrançois Tigeot if (INTEL_GEN(dev_priv) >= 8) { 20894be47400SFrançois Tigeot engine->emit_breadcrumb_sz += num_rings * 6; 20904be47400SFrançois Tigeot } else { 20914be47400SFrançois Tigeot engine->emit_breadcrumb_sz += num_rings * 3; 20924be47400SFrançois Tigeot if (num_rings & 1) 20934be47400SFrançois Tigeot engine->emit_breadcrumb_sz++; 20944be47400SFrançois Tigeot } 20954be47400SFrançois Tigeot } 2096*a85cb24fSFrançois Tigeot 2097*a85cb24fSFrançois Tigeot engine->set_default_submission = i9xx_set_default_submission; 209871f41f3eSFrançois Tigeot 209971f41f3eSFrançois Tigeot if (INTEL_GEN(dev_priv) >= 8) 210071f41f3eSFrançois Tigeot engine->emit_bb_start = gen8_emit_bb_start; 210171f41f3eSFrançois Tigeot else if (INTEL_GEN(dev_priv) >= 6) 210271f41f3eSFrançois Tigeot engine->emit_bb_start = gen6_emit_bb_start; 210371f41f3eSFrançois Tigeot else if (INTEL_GEN(dev_priv) >= 4) 210471f41f3eSFrançois Tigeot engine->emit_bb_start = i965_emit_bb_start; 2105*a85cb24fSFrançois Tigeot else if (IS_I830(dev_priv) || IS_I845G(dev_priv)) 210671f41f3eSFrançois Tigeot engine->emit_bb_start = i830_emit_bb_start; 210771f41f3eSFrançois Tigeot else 210871f41f3eSFrançois Tigeot engine->emit_bb_start = i915_emit_bb_start; 21091487f786SFrançois Tigeot } 21101487f786SFrançois Tigeot 211187df8fc6SFrançois Tigeot int intel_init_render_ring_buffer(struct intel_engine_cs *engine) 2112e3adcf8fSFrançois Tigeot { 211387df8fc6SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 211424edb884SFrançois Tigeot int ret; 2115e3adcf8fSFrançois Tigeot 21161487f786SFrançois Tigeot intel_ring_default_vfuncs(dev_priv, engine); 21172c9916cdSFrançois Tigeot 2118303bf270SFrançois Tigeot if (HAS_L3_DPF(dev_priv)) 2119303bf270SFrançois Tigeot engine->irq_keep_mask = GT_RENDER_L3_PARITY_ERROR_INTERRUPT; 2120303bf270SFrançois Tigeot 21211487f786SFrançois Tigeot if (INTEL_GEN(dev_priv) >= 8) { 21228621f407SFrançois Tigeot engine->init_context = intel_rcs_ctx_init; 21234be47400SFrançois Tigeot engine->emit_breadcrumb = gen8_render_emit_breadcrumb; 21244be47400SFrançois Tigeot engine->emit_breadcrumb_sz = gen8_render_emit_breadcrumb_sz; 212571f41f3eSFrançois Tigeot engine->emit_flush = gen8_render_ring_flush; 21264be47400SFrançois Tigeot if (i915.semaphores) { 21274be47400SFrançois Tigeot int num_rings; 21284be47400SFrançois Tigeot 21298621f407SFrançois Tigeot engine->semaphore.signal = gen8_rcs_signal; 21304be47400SFrançois Tigeot 21314be47400SFrançois Tigeot num_rings = 21324be47400SFrançois Tigeot hweight32(INTEL_INFO(dev_priv)->ring_mask) - 1; 2133*a85cb24fSFrançois Tigeot engine->emit_breadcrumb_sz += num_rings * 8; 21344be47400SFrançois Tigeot } 21351487f786SFrançois Tigeot } else if (INTEL_GEN(dev_priv) >= 6) { 21368621f407SFrançois Tigeot engine->init_context = intel_rcs_ctx_init; 213771f41f3eSFrançois Tigeot engine->emit_flush = gen7_render_ring_flush; 21381487f786SFrançois Tigeot if (IS_GEN6(dev_priv)) 213971f41f3eSFrançois Tigeot engine->emit_flush = gen6_render_ring_flush; 21401487f786SFrançois Tigeot } else if (IS_GEN5(dev_priv)) { 214171f41f3eSFrançois Tigeot engine->emit_flush = gen4_render_ring_flush; 2142686a02f1SFrançois Tigeot } else { 21431487f786SFrançois Tigeot if (INTEL_GEN(dev_priv) < 4) 214471f41f3eSFrançois Tigeot engine->emit_flush = gen2_render_ring_flush; 2145686a02f1SFrançois Tigeot else 214671f41f3eSFrançois Tigeot engine->emit_flush = gen4_render_ring_flush; 21478621f407SFrançois Tigeot engine->irq_enable_mask = I915_USER_INTERRUPT; 2148686a02f1SFrançois Tigeot } 214924edb884SFrançois Tigeot 21501487f786SFrançois Tigeot if (IS_HASWELL(dev_priv)) 215171f41f3eSFrançois Tigeot engine->emit_bb_start = hsw_emit_bb_start; 21521487f786SFrançois Tigeot 21538621f407SFrançois Tigeot engine->init_hw = init_render_ring; 21548621f407SFrançois Tigeot engine->cleanup = render_ring_cleanup; 2155e3adcf8fSFrançois Tigeot 215687df8fc6SFrançois Tigeot ret = intel_init_ring_buffer(engine); 2157b5c29a34SFrançois Tigeot if (ret) 21582c9916cdSFrançois Tigeot return ret; 21592c9916cdSFrançois Tigeot 2160303bf270SFrançois Tigeot if (INTEL_GEN(dev_priv) >= 6) { 2161*a85cb24fSFrançois Tigeot ret = intel_engine_create_scratch(engine, PAGE_SIZE); 2162303bf270SFrançois Tigeot if (ret) 2163303bf270SFrançois Tigeot return ret; 2164303bf270SFrançois Tigeot } else if (HAS_BROKEN_CS_TLB(dev_priv)) { 21651e12ee3bSFrançois Tigeot ret = intel_engine_create_scratch(engine, I830_WA_SIZE); 21662c9916cdSFrançois Tigeot if (ret) 21672c9916cdSFrançois Tigeot return ret; 2168b5c29a34SFrançois Tigeot } 2169b5c29a34SFrançois Tigeot 2170e3adcf8fSFrançois Tigeot return 0; 2171e3adcf8fSFrançois Tigeot } 2172e3adcf8fSFrançois Tigeot 217387df8fc6SFrançois Tigeot int intel_init_bsd_ring_buffer(struct intel_engine_cs *engine) 2174e3adcf8fSFrançois Tigeot { 217587df8fc6SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 2176686a02f1SFrançois Tigeot 21771487f786SFrançois Tigeot intel_ring_default_vfuncs(dev_priv, engine); 21781487f786SFrançois Tigeot 21791487f786SFrançois Tigeot if (INTEL_GEN(dev_priv) >= 6) { 2180686a02f1SFrançois Tigeot /* gen6 bsd needs a special wa for tail updates */ 21811487f786SFrançois Tigeot if (IS_GEN6(dev_priv)) 2182*a85cb24fSFrançois Tigeot engine->set_default_submission = gen6_bsd_set_default_submission; 218371f41f3eSFrançois Tigeot engine->emit_flush = gen6_bsd_ring_flush; 218487df8fc6SFrançois Tigeot if (INTEL_GEN(dev_priv) < 8) 21858621f407SFrançois Tigeot engine->irq_enable_mask = GT_BSD_USER_INTERRUPT; 2186686a02f1SFrançois Tigeot } else { 21878621f407SFrançois Tigeot engine->mmio_base = BSD_RING_BASE; 218871f41f3eSFrançois Tigeot engine->emit_flush = bsd_ring_flush; 21891487f786SFrançois Tigeot if (IS_GEN5(dev_priv)) 21908621f407SFrançois Tigeot engine->irq_enable_mask = ILK_BSD_USER_INTERRUPT; 21911487f786SFrançois Tigeot else 21928621f407SFrançois Tigeot engine->irq_enable_mask = I915_BSD_USER_INTERRUPT; 2193686a02f1SFrançois Tigeot } 2194e3adcf8fSFrançois Tigeot 219587df8fc6SFrançois Tigeot return intel_init_ring_buffer(engine); 2196e3adcf8fSFrançois Tigeot } 2197e3adcf8fSFrançois Tigeot 2198ba55f2f5SFrançois Tigeot /** 2199477eb7f9SFrançois Tigeot * Initialize the second BSD ring (eg. Broadwell GT3, Skylake GT3) 2200ba55f2f5SFrançois Tigeot */ 220187df8fc6SFrançois Tigeot int intel_init_bsd2_ring_buffer(struct intel_engine_cs *engine) 2202ba55f2f5SFrançois Tigeot { 220387df8fc6SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 22041487f786SFrançois Tigeot 22051487f786SFrançois Tigeot intel_ring_default_vfuncs(dev_priv, engine); 22061487f786SFrançois Tigeot 220771f41f3eSFrançois Tigeot engine->emit_flush = gen6_bsd_ring_flush; 2208ba55f2f5SFrançois Tigeot 220987df8fc6SFrançois Tigeot return intel_init_ring_buffer(engine); 2210ba55f2f5SFrançois Tigeot } 2211ba55f2f5SFrançois Tigeot 221287df8fc6SFrançois Tigeot int intel_init_blt_ring_buffer(struct intel_engine_cs *engine) 2213e3adcf8fSFrançois Tigeot { 221487df8fc6SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 22151487f786SFrançois Tigeot 22161487f786SFrançois Tigeot intel_ring_default_vfuncs(dev_priv, engine); 22171487f786SFrançois Tigeot 221871f41f3eSFrançois Tigeot engine->emit_flush = gen6_ring_flush; 221987df8fc6SFrançois Tigeot if (INTEL_GEN(dev_priv) < 8) 22208621f407SFrançois Tigeot engine->irq_enable_mask = GT_BLT_USER_INTERRUPT; 22215d0b1887SFrançois Tigeot 222287df8fc6SFrançois Tigeot return intel_init_ring_buffer(engine); 22235d0b1887SFrançois Tigeot } 22245d0b1887SFrançois Tigeot 222587df8fc6SFrançois Tigeot int intel_init_vebox_ring_buffer(struct intel_engine_cs *engine) 22265d0b1887SFrançois Tigeot { 222787df8fc6SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 22289edbd4a0SFrançois Tigeot 22291487f786SFrançois Tigeot intel_ring_default_vfuncs(dev_priv, engine); 22301487f786SFrançois Tigeot 223171f41f3eSFrançois Tigeot engine->emit_flush = gen6_ring_flush; 22321487f786SFrançois Tigeot 223387df8fc6SFrançois Tigeot if (INTEL_GEN(dev_priv) < 8) { 22348621f407SFrançois Tigeot engine->irq_enable_mask = PM_VEBOX_USER_INTERRUPT; 2235303bf270SFrançois Tigeot engine->irq_enable = hsw_vebox_irq_enable; 2236303bf270SFrançois Tigeot engine->irq_disable = hsw_vebox_irq_disable; 223724edb884SFrançois Tigeot } 2238e3adcf8fSFrançois Tigeot 223987df8fc6SFrançois Tigeot return intel_init_ring_buffer(engine); 2240e3adcf8fSFrançois Tigeot } 2241