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 37*1487f786SFrançois Tigeot /* Rough estimate of the typical request size, performing a flush, 38*1487f786SFrançois Tigeot * set-context and then emitting the batch. 39*1487f786SFrançois Tigeot */ 40*1487f786SFrançois Tigeot #define LEGACY_REQUEST_SIZE 200 41*1487f786SFrançois Tigeot 421b13d190SFrançois Tigeot int __intel_ring_space(int head, int tail, int size) 43e3adcf8fSFrançois Tigeot { 442c9916cdSFrançois Tigeot int space = head - tail; 452c9916cdSFrançois Tigeot if (space <= 0) 46ba55f2f5SFrançois Tigeot space += size; 472c9916cdSFrançois Tigeot return space - I915_RING_FREE_SPACE; 482c9916cdSFrançois Tigeot } 492c9916cdSFrançois Tigeot 502c9916cdSFrançois Tigeot void intel_ring_update_space(struct intel_ringbuffer *ringbuf) 512c9916cdSFrançois Tigeot { 522c9916cdSFrançois Tigeot if (ringbuf->last_retired_head != -1) { 532c9916cdSFrançois Tigeot ringbuf->head = ringbuf->last_retired_head; 542c9916cdSFrançois Tigeot ringbuf->last_retired_head = -1; 552c9916cdSFrançois Tigeot } 562c9916cdSFrançois Tigeot 572c9916cdSFrançois Tigeot ringbuf->space = __intel_ring_space(ringbuf->head & HEAD_ADDR, 582c9916cdSFrançois Tigeot ringbuf->tail, ringbuf->size); 59e3adcf8fSFrançois Tigeot } 60e3adcf8fSFrançois Tigeot 618621f407SFrançois Tigeot bool intel_engine_stopped(struct intel_engine_cs *engine) 62ba55f2f5SFrançois Tigeot { 63*1487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 648621f407SFrançois Tigeot return dev_priv->gpu_error.stop_rings & intel_engine_flag(engine); 65ba55f2f5SFrançois Tigeot } 66ba55f2f5SFrançois Tigeot 678621f407SFrançois Tigeot static void __intel_ring_advance(struct intel_engine_cs *engine) 689edbd4a0SFrançois Tigeot { 698621f407SFrançois Tigeot struct intel_ringbuffer *ringbuf = engine->buffer; 70ba55f2f5SFrançois Tigeot ringbuf->tail &= ringbuf->size - 1; 718621f407SFrançois Tigeot if (intel_engine_stopped(engine)) 729edbd4a0SFrançois Tigeot return; 738621f407SFrançois Tigeot engine->write_tail(engine, ringbuf->tail); 749edbd4a0SFrançois Tigeot } 759edbd4a0SFrançois Tigeot 76e3adcf8fSFrançois Tigeot static int 77a05eeebfSFrançois Tigeot gen2_render_ring_flush(struct drm_i915_gem_request *req, 78686a02f1SFrançois Tigeot u32 invalidate_domains, 79686a02f1SFrançois Tigeot u32 flush_domains) 80686a02f1SFrançois Tigeot { 818621f407SFrançois Tigeot struct intel_engine_cs *engine = req->engine; 82686a02f1SFrançois Tigeot u32 cmd; 83686a02f1SFrançois Tigeot int ret; 84686a02f1SFrançois Tigeot 85686a02f1SFrançois Tigeot cmd = MI_FLUSH; 86686a02f1SFrançois Tigeot if (((invalidate_domains|flush_domains) & I915_GEM_DOMAIN_RENDER) == 0) 87686a02f1SFrançois Tigeot cmd |= MI_NO_WRITE_FLUSH; 88686a02f1SFrançois Tigeot 89686a02f1SFrançois Tigeot if (invalidate_domains & I915_GEM_DOMAIN_SAMPLER) 90686a02f1SFrançois Tigeot cmd |= MI_READ_FLUSH; 91686a02f1SFrançois Tigeot 92a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 2); 93686a02f1SFrançois Tigeot if (ret) 94686a02f1SFrançois Tigeot return ret; 95686a02f1SFrançois Tigeot 968621f407SFrançois Tigeot intel_ring_emit(engine, cmd); 978621f407SFrançois Tigeot intel_ring_emit(engine, MI_NOOP); 988621f407SFrançois Tigeot intel_ring_advance(engine); 99686a02f1SFrançois Tigeot 100686a02f1SFrançois Tigeot return 0; 101686a02f1SFrançois Tigeot } 102686a02f1SFrançois Tigeot 103686a02f1SFrançois Tigeot static int 104a05eeebfSFrançois Tigeot gen4_render_ring_flush(struct drm_i915_gem_request *req, 105686a02f1SFrançois Tigeot u32 invalidate_domains, 106686a02f1SFrançois Tigeot u32 flush_domains) 107e3adcf8fSFrançois Tigeot { 1088621f407SFrançois Tigeot struct intel_engine_cs *engine = req->engine; 109686a02f1SFrançois Tigeot u32 cmd; 110e3adcf8fSFrançois Tigeot int ret; 111e3adcf8fSFrançois Tigeot 112e3adcf8fSFrançois Tigeot /* 113e3adcf8fSFrançois Tigeot * read/write caches: 114e3adcf8fSFrançois Tigeot * 115e3adcf8fSFrançois Tigeot * I915_GEM_DOMAIN_RENDER is always invalidated, but is 116e3adcf8fSFrançois Tigeot * only flushed if MI_NO_WRITE_FLUSH is unset. On 965, it is 117e3adcf8fSFrançois Tigeot * also flushed at 2d versus 3d pipeline switches. 118e3adcf8fSFrançois Tigeot * 119e3adcf8fSFrançois Tigeot * read-only caches: 120e3adcf8fSFrançois Tigeot * 121e3adcf8fSFrançois Tigeot * I915_GEM_DOMAIN_SAMPLER is flushed on pre-965 if 122e3adcf8fSFrançois Tigeot * MI_READ_FLUSH is set, and is always flushed on 965. 123e3adcf8fSFrançois Tigeot * 124e3adcf8fSFrançois Tigeot * I915_GEM_DOMAIN_COMMAND may not exist? 125e3adcf8fSFrançois Tigeot * 126e3adcf8fSFrançois Tigeot * I915_GEM_DOMAIN_INSTRUCTION, which exists on 965, is 127e3adcf8fSFrançois Tigeot * invalidated when MI_EXE_FLUSH is set. 128e3adcf8fSFrançois Tigeot * 129e3adcf8fSFrançois Tigeot * I915_GEM_DOMAIN_VERTEX, which exists on 965, is 130e3adcf8fSFrançois Tigeot * invalidated with every MI_FLUSH. 131e3adcf8fSFrançois Tigeot * 132e3adcf8fSFrançois Tigeot * TLBs: 133e3adcf8fSFrançois Tigeot * 134e3adcf8fSFrançois Tigeot * On 965, TLBs associated with I915_GEM_DOMAIN_COMMAND 135e3adcf8fSFrançois Tigeot * and I915_GEM_DOMAIN_CPU in are invalidated at PTE write and 136e3adcf8fSFrançois Tigeot * I915_GEM_DOMAIN_RENDER and I915_GEM_DOMAIN_SAMPLER 137e3adcf8fSFrançois Tigeot * are flushed at any MI_FLUSH. 138e3adcf8fSFrançois Tigeot */ 139e3adcf8fSFrançois Tigeot 140e3adcf8fSFrançois Tigeot cmd = MI_FLUSH | MI_NO_WRITE_FLUSH; 141686a02f1SFrançois Tigeot if ((invalidate_domains|flush_domains) & I915_GEM_DOMAIN_RENDER) 142e3adcf8fSFrançois Tigeot cmd &= ~MI_NO_WRITE_FLUSH; 143e3adcf8fSFrançois Tigeot if (invalidate_domains & I915_GEM_DOMAIN_INSTRUCTION) 144e3adcf8fSFrançois Tigeot cmd |= MI_EXE_FLUSH; 145e3adcf8fSFrançois Tigeot 146e3adcf8fSFrançois Tigeot if (invalidate_domains & I915_GEM_DOMAIN_COMMAND && 147*1487f786SFrançois Tigeot (IS_G4X(req->i915) || IS_GEN5(req->i915))) 148e3adcf8fSFrançois Tigeot cmd |= MI_INVALIDATE_ISP; 149e3adcf8fSFrançois Tigeot 150a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 2); 151e3adcf8fSFrançois Tigeot if (ret) 152e3adcf8fSFrançois Tigeot return ret; 153e3adcf8fSFrançois Tigeot 1548621f407SFrançois Tigeot intel_ring_emit(engine, cmd); 1558621f407SFrançois Tigeot intel_ring_emit(engine, MI_NOOP); 1568621f407SFrançois Tigeot intel_ring_advance(engine); 157e3adcf8fSFrançois Tigeot 158e3adcf8fSFrançois Tigeot return 0; 159e3adcf8fSFrançois Tigeot } 160e3adcf8fSFrançois Tigeot 161e3adcf8fSFrançois Tigeot /** 162e3adcf8fSFrançois Tigeot * Emits a PIPE_CONTROL with a non-zero post-sync operation, for 163e3adcf8fSFrançois Tigeot * implementing two workarounds on gen6. From section 1.4.7.1 164e3adcf8fSFrançois Tigeot * "PIPE_CONTROL" of the Sandy Bridge PRM volume 2 part 1: 165e3adcf8fSFrançois Tigeot * 166e3adcf8fSFrançois Tigeot * [DevSNB-C+{W/A}] Before any depth stall flush (including those 167e3adcf8fSFrançois Tigeot * produced by non-pipelined state commands), software needs to first 168e3adcf8fSFrançois Tigeot * send a PIPE_CONTROL with no bits set except Post-Sync Operation != 169e3adcf8fSFrançois Tigeot * 0. 170e3adcf8fSFrançois Tigeot * 171e3adcf8fSFrançois Tigeot * [Dev-SNB{W/A}]: Before a PIPE_CONTROL with Write Cache Flush Enable 172e3adcf8fSFrançois Tigeot * =1, a PIPE_CONTROL with any non-zero post-sync-op is required. 173e3adcf8fSFrançois Tigeot * 174e3adcf8fSFrançois Tigeot * And the workaround for these two requires this workaround first: 175e3adcf8fSFrançois Tigeot * 176e3adcf8fSFrançois Tigeot * [Dev-SNB{W/A}]: Pipe-control with CS-stall bit set must be sent 177e3adcf8fSFrançois Tigeot * BEFORE the pipe-control with a post-sync op and no write-cache 178e3adcf8fSFrançois Tigeot * flushes. 179e3adcf8fSFrançois Tigeot * 180e3adcf8fSFrançois Tigeot * And this last workaround is tricky because of the requirements on 181e3adcf8fSFrançois Tigeot * that bit. From section 1.4.7.2.3 "Stall" of the Sandy Bridge PRM 182e3adcf8fSFrançois Tigeot * volume 2 part 1: 183e3adcf8fSFrançois Tigeot * 184e3adcf8fSFrançois Tigeot * "1 of the following must also be set: 185e3adcf8fSFrançois Tigeot * - Render Target Cache Flush Enable ([12] of DW1) 186e3adcf8fSFrançois Tigeot * - Depth Cache Flush Enable ([0] of DW1) 187e3adcf8fSFrançois Tigeot * - Stall at Pixel Scoreboard ([1] of DW1) 188e3adcf8fSFrançois Tigeot * - Depth Stall ([13] of DW1) 189e3adcf8fSFrançois Tigeot * - Post-Sync Operation ([13] of DW1) 190e3adcf8fSFrançois Tigeot * - Notify Enable ([8] of DW1)" 191e3adcf8fSFrançois Tigeot * 192e3adcf8fSFrançois Tigeot * The cache flushes require the workaround flush that triggered this 193e3adcf8fSFrançois Tigeot * one, so we can't use it. Depth stall would trigger the same. 194e3adcf8fSFrançois Tigeot * Post-sync nonzero is what triggered this second workaround, so we 195e3adcf8fSFrançois Tigeot * can't use that one either. Notify enable is IRQs, which aren't 196e3adcf8fSFrançois Tigeot * really our business. That leaves only stall at scoreboard. 197e3adcf8fSFrançois Tigeot */ 198e3adcf8fSFrançois Tigeot static int 199a05eeebfSFrançois Tigeot intel_emit_post_sync_nonzero_flush(struct drm_i915_gem_request *req) 200e3adcf8fSFrançois Tigeot { 2018621f407SFrançois Tigeot struct intel_engine_cs *engine = req->engine; 2028621f407SFrançois Tigeot u32 scratch_addr = engine->scratch.gtt_offset + 2 * CACHELINE_BYTES; 203e3adcf8fSFrançois Tigeot int ret; 204e3adcf8fSFrançois Tigeot 205a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 6); 206e3adcf8fSFrançois Tigeot if (ret) 207e3adcf8fSFrançois Tigeot return ret; 208e3adcf8fSFrançois Tigeot 2098621f407SFrançois Tigeot intel_ring_emit(engine, GFX_OP_PIPE_CONTROL(5)); 2108621f407SFrançois Tigeot intel_ring_emit(engine, PIPE_CONTROL_CS_STALL | 211e3adcf8fSFrançois Tigeot PIPE_CONTROL_STALL_AT_SCOREBOARD); 2128621f407SFrançois Tigeot intel_ring_emit(engine, scratch_addr | PIPE_CONTROL_GLOBAL_GTT); /* address */ 2138621f407SFrançois Tigeot intel_ring_emit(engine, 0); /* low dword */ 2148621f407SFrançois Tigeot intel_ring_emit(engine, 0); /* high dword */ 2158621f407SFrançois Tigeot intel_ring_emit(engine, MI_NOOP); 2168621f407SFrançois Tigeot intel_ring_advance(engine); 217e3adcf8fSFrançois Tigeot 218a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 6); 219e3adcf8fSFrançois Tigeot if (ret) 220e3adcf8fSFrançois Tigeot return ret; 221e3adcf8fSFrançois Tigeot 2228621f407SFrançois Tigeot intel_ring_emit(engine, GFX_OP_PIPE_CONTROL(5)); 2238621f407SFrançois Tigeot intel_ring_emit(engine, PIPE_CONTROL_QW_WRITE); 2248621f407SFrançois Tigeot intel_ring_emit(engine, scratch_addr | PIPE_CONTROL_GLOBAL_GTT); /* address */ 2258621f407SFrançois Tigeot intel_ring_emit(engine, 0); 2268621f407SFrançois Tigeot intel_ring_emit(engine, 0); 2278621f407SFrançois Tigeot intel_ring_emit(engine, MI_NOOP); 2288621f407SFrançois Tigeot intel_ring_advance(engine); 229e3adcf8fSFrançois Tigeot 230e3adcf8fSFrançois Tigeot return 0; 231e3adcf8fSFrançois Tigeot } 232e3adcf8fSFrançois Tigeot 233e3adcf8fSFrançois Tigeot static int 234a05eeebfSFrançois Tigeot gen6_render_ring_flush(struct drm_i915_gem_request *req, 235e3adcf8fSFrançois Tigeot u32 invalidate_domains, u32 flush_domains) 236e3adcf8fSFrançois Tigeot { 2378621f407SFrançois Tigeot struct intel_engine_cs *engine = req->engine; 238e3adcf8fSFrançois Tigeot u32 flags = 0; 2398621f407SFrançois Tigeot u32 scratch_addr = engine->scratch.gtt_offset + 2 * CACHELINE_BYTES; 240e3adcf8fSFrançois Tigeot int ret; 241e3adcf8fSFrançois Tigeot 242e3adcf8fSFrançois Tigeot /* Force SNB workarounds for PIPE_CONTROL flushes */ 243a05eeebfSFrançois Tigeot ret = intel_emit_post_sync_nonzero_flush(req); 244686a02f1SFrançois Tigeot if (ret) 245686a02f1SFrançois Tigeot return ret; 246e3adcf8fSFrançois Tigeot 247e3adcf8fSFrançois Tigeot /* Just flush everything. Experiments have shown that reducing the 248e3adcf8fSFrançois Tigeot * number of bits based on the write domains has little performance 249e3adcf8fSFrançois Tigeot * impact. 250e3adcf8fSFrançois Tigeot */ 251b5c29a34SFrançois Tigeot if (flush_domains) { 252e3adcf8fSFrançois Tigeot flags |= PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH; 253b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_DEPTH_CACHE_FLUSH; 254b5c29a34SFrançois Tigeot /* 255b5c29a34SFrançois Tigeot * Ensure that any following seqno writes only happen 256b5c29a34SFrançois Tigeot * when the render cache is indeed flushed. 257b5c29a34SFrançois Tigeot */ 258b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_CS_STALL; 259b5c29a34SFrançois Tigeot } 260b5c29a34SFrançois Tigeot if (invalidate_domains) { 261686a02f1SFrançois Tigeot flags |= PIPE_CONTROL_TLB_INVALIDATE; 262e3adcf8fSFrançois Tigeot flags |= PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE; 263e3adcf8fSFrançois Tigeot flags |= PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE; 264e3adcf8fSFrançois Tigeot flags |= PIPE_CONTROL_VF_CACHE_INVALIDATE; 265e3adcf8fSFrançois Tigeot flags |= PIPE_CONTROL_CONST_CACHE_INVALIDATE; 266e3adcf8fSFrançois Tigeot flags |= PIPE_CONTROL_STATE_CACHE_INVALIDATE; 267686a02f1SFrançois Tigeot /* 268b5c29a34SFrançois Tigeot * TLB invalidate requires a post-sync write. 269686a02f1SFrançois Tigeot */ 270b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_QW_WRITE | PIPE_CONTROL_CS_STALL; 271b5c29a34SFrançois Tigeot } 272e3adcf8fSFrançois Tigeot 273a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 4); 274e3adcf8fSFrançois Tigeot if (ret) 275e3adcf8fSFrançois Tigeot return ret; 276e3adcf8fSFrançois Tigeot 2778621f407SFrançois Tigeot intel_ring_emit(engine, GFX_OP_PIPE_CONTROL(4)); 2788621f407SFrançois Tigeot intel_ring_emit(engine, flags); 2798621f407SFrançois Tigeot intel_ring_emit(engine, scratch_addr | PIPE_CONTROL_GLOBAL_GTT); 2808621f407SFrançois Tigeot intel_ring_emit(engine, 0); 2818621f407SFrançois Tigeot intel_ring_advance(engine); 282b5c29a34SFrançois Tigeot 283b5c29a34SFrançois Tigeot return 0; 284b5c29a34SFrançois Tigeot } 285b5c29a34SFrançois Tigeot 286b5c29a34SFrançois Tigeot static int 287a05eeebfSFrançois Tigeot gen7_render_ring_cs_stall_wa(struct drm_i915_gem_request *req) 288b5c29a34SFrançois Tigeot { 2898621f407SFrançois Tigeot struct intel_engine_cs *engine = req->engine; 290b5c29a34SFrançois Tigeot int ret; 291b5c29a34SFrançois Tigeot 292a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 4); 293b5c29a34SFrançois Tigeot if (ret) 294b5c29a34SFrançois Tigeot return ret; 295b5c29a34SFrançois Tigeot 2968621f407SFrançois Tigeot intel_ring_emit(engine, GFX_OP_PIPE_CONTROL(4)); 2978621f407SFrançois Tigeot intel_ring_emit(engine, PIPE_CONTROL_CS_STALL | 298b5c29a34SFrançois Tigeot PIPE_CONTROL_STALL_AT_SCOREBOARD); 2998621f407SFrançois Tigeot intel_ring_emit(engine, 0); 3008621f407SFrançois Tigeot intel_ring_emit(engine, 0); 3018621f407SFrançois Tigeot intel_ring_advance(engine); 302b5c29a34SFrançois Tigeot 303b5c29a34SFrançois Tigeot return 0; 304b5c29a34SFrançois Tigeot } 305b5c29a34SFrançois Tigeot 306b5c29a34SFrançois Tigeot static int 307a05eeebfSFrançois Tigeot gen7_render_ring_flush(struct drm_i915_gem_request *req, 308b5c29a34SFrançois Tigeot u32 invalidate_domains, u32 flush_domains) 309b5c29a34SFrançois Tigeot { 3108621f407SFrançois Tigeot struct intel_engine_cs *engine = req->engine; 311b5c29a34SFrançois Tigeot u32 flags = 0; 3128621f407SFrançois Tigeot u32 scratch_addr = engine->scratch.gtt_offset + 2 * CACHELINE_BYTES; 313b5c29a34SFrançois Tigeot int ret; 314b5c29a34SFrançois Tigeot 315b5c29a34SFrançois Tigeot /* 316b5c29a34SFrançois Tigeot * Ensure that any following seqno writes only happen when the render 317b5c29a34SFrançois Tigeot * cache is indeed flushed. 318b5c29a34SFrançois Tigeot * 319b5c29a34SFrançois Tigeot * Workaround: 4th PIPE_CONTROL command (except the ones with only 320b5c29a34SFrançois Tigeot * read-cache invalidate bits set) must have the CS_STALL bit set. We 321b5c29a34SFrançois Tigeot * don't try to be clever and just set it unconditionally. 322b5c29a34SFrançois Tigeot */ 323b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_CS_STALL; 324b5c29a34SFrançois Tigeot 325b5c29a34SFrançois Tigeot /* Just flush everything. Experiments have shown that reducing the 326b5c29a34SFrançois Tigeot * number of bits based on the write domains has little performance 327b5c29a34SFrançois Tigeot * impact. 328b5c29a34SFrançois Tigeot */ 329b5c29a34SFrançois Tigeot if (flush_domains) { 330b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH; 331b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_DEPTH_CACHE_FLUSH; 332aee94f86SFrançois Tigeot flags |= PIPE_CONTROL_DC_FLUSH_ENABLE; 333b49c8cf9SFrançois Tigeot flags |= PIPE_CONTROL_FLUSH_ENABLE; 334b5c29a34SFrançois Tigeot } 335b5c29a34SFrançois Tigeot if (invalidate_domains) { 336b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_TLB_INVALIDATE; 337b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE; 338b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE; 339b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_VF_CACHE_INVALIDATE; 340b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_CONST_CACHE_INVALIDATE; 341b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_STATE_CACHE_INVALIDATE; 3422c9916cdSFrançois Tigeot flags |= PIPE_CONTROL_MEDIA_STATE_CLEAR; 343b5c29a34SFrançois Tigeot /* 344b5c29a34SFrançois Tigeot * TLB invalidate requires a post-sync write. 345b5c29a34SFrançois Tigeot */ 346b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_QW_WRITE; 347a2fdbec6SFrançois Tigeot flags |= PIPE_CONTROL_GLOBAL_GTT_IVB; 348b5c29a34SFrançois Tigeot 3490dbf0ea8SMatthew Dillon flags |= PIPE_CONTROL_STALL_AT_SCOREBOARD; 3500dbf0ea8SMatthew Dillon 351b5c29a34SFrançois Tigeot /* Workaround: we must issue a pipe_control with CS-stall bit 352b5c29a34SFrançois Tigeot * set before a pipe_control command that has the state cache 353b5c29a34SFrançois Tigeot * invalidate bit set. */ 354a05eeebfSFrançois Tigeot gen7_render_ring_cs_stall_wa(req); 355b5c29a34SFrançois Tigeot } 356b5c29a34SFrançois Tigeot 357a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 4); 358b5c29a34SFrançois Tigeot if (ret) 359b5c29a34SFrançois Tigeot return ret; 360b5c29a34SFrançois Tigeot 3618621f407SFrançois Tigeot intel_ring_emit(engine, GFX_OP_PIPE_CONTROL(4)); 3628621f407SFrançois Tigeot intel_ring_emit(engine, flags); 3638621f407SFrançois Tigeot intel_ring_emit(engine, scratch_addr); 3648621f407SFrançois Tigeot intel_ring_emit(engine, 0); 3658621f407SFrançois Tigeot intel_ring_advance(engine); 366e3adcf8fSFrançois Tigeot 367e3adcf8fSFrançois Tigeot return 0; 368e3adcf8fSFrançois Tigeot } 369e3adcf8fSFrançois Tigeot 3709edbd4a0SFrançois Tigeot static int 371a05eeebfSFrançois Tigeot gen8_emit_pipe_control(struct drm_i915_gem_request *req, 37224edb884SFrançois Tigeot u32 flags, u32 scratch_addr) 37324edb884SFrançois Tigeot { 3748621f407SFrançois Tigeot struct intel_engine_cs *engine = req->engine; 37524edb884SFrançois Tigeot int ret; 37624edb884SFrançois Tigeot 377a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 6); 37824edb884SFrançois Tigeot if (ret) 37924edb884SFrançois Tigeot return ret; 38024edb884SFrançois Tigeot 3818621f407SFrançois Tigeot intel_ring_emit(engine, GFX_OP_PIPE_CONTROL(6)); 3828621f407SFrançois Tigeot intel_ring_emit(engine, flags); 3838621f407SFrançois Tigeot intel_ring_emit(engine, scratch_addr); 3848621f407SFrançois Tigeot intel_ring_emit(engine, 0); 3858621f407SFrançois Tigeot intel_ring_emit(engine, 0); 3868621f407SFrançois Tigeot intel_ring_emit(engine, 0); 3878621f407SFrançois Tigeot intel_ring_advance(engine); 38824edb884SFrançois Tigeot 38924edb884SFrançois Tigeot return 0; 39024edb884SFrançois Tigeot } 39124edb884SFrançois Tigeot 39224edb884SFrançois Tigeot static int 393a05eeebfSFrançois Tigeot gen8_render_ring_flush(struct drm_i915_gem_request *req, 3949edbd4a0SFrançois Tigeot u32 invalidate_domains, u32 flush_domains) 3959edbd4a0SFrançois Tigeot { 3969edbd4a0SFrançois Tigeot u32 flags = 0; 3978621f407SFrançois Tigeot u32 scratch_addr = req->engine->scratch.gtt_offset + 2 * CACHELINE_BYTES; 3989edbd4a0SFrançois Tigeot int ret; 3999edbd4a0SFrançois Tigeot 4009edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_CS_STALL; 4019edbd4a0SFrançois Tigeot 4029edbd4a0SFrançois Tigeot if (flush_domains) { 4039edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH; 4049edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_DEPTH_CACHE_FLUSH; 405aee94f86SFrançois Tigeot flags |= PIPE_CONTROL_DC_FLUSH_ENABLE; 406b49c8cf9SFrançois Tigeot flags |= PIPE_CONTROL_FLUSH_ENABLE; 4079edbd4a0SFrançois Tigeot } 4089edbd4a0SFrançois Tigeot if (invalidate_domains) { 4099edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_TLB_INVALIDATE; 4109edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE; 4119edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE; 4129edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_VF_CACHE_INVALIDATE; 4139edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_CONST_CACHE_INVALIDATE; 4149edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_STATE_CACHE_INVALIDATE; 4159edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_QW_WRITE; 4169edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_GLOBAL_GTT_IVB; 4179edbd4a0SFrançois Tigeot 41824edb884SFrançois Tigeot /* WaCsStallBeforeStateCacheInvalidate:bdw,chv */ 419a05eeebfSFrançois Tigeot ret = gen8_emit_pipe_control(req, 42024edb884SFrançois Tigeot PIPE_CONTROL_CS_STALL | 42124edb884SFrançois Tigeot PIPE_CONTROL_STALL_AT_SCOREBOARD, 42224edb884SFrançois Tigeot 0); 4239edbd4a0SFrançois Tigeot if (ret) 4249edbd4a0SFrançois Tigeot return ret; 42524edb884SFrançois Tigeot } 4269edbd4a0SFrançois Tigeot 427a05eeebfSFrançois Tigeot return gen8_emit_pipe_control(req, flags, scratch_addr); 4289edbd4a0SFrançois Tigeot } 4299edbd4a0SFrançois Tigeot 4308621f407SFrançois Tigeot static void ring_write_tail(struct intel_engine_cs *engine, 431b5c29a34SFrançois Tigeot u32 value) 432e3adcf8fSFrançois Tigeot { 433*1487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 4348621f407SFrançois Tigeot I915_WRITE_TAIL(engine, value); 435e3adcf8fSFrançois Tigeot } 436e3adcf8fSFrançois Tigeot 4378621f407SFrançois Tigeot u64 intel_ring_get_active_head(struct intel_engine_cs *engine) 438e3adcf8fSFrançois Tigeot { 439*1487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 440ba55f2f5SFrançois Tigeot u64 acthd; 441e3adcf8fSFrançois Tigeot 442*1487f786SFrançois Tigeot if (INTEL_GEN(dev_priv) >= 8) 4438621f407SFrançois Tigeot acthd = I915_READ64_2x32(RING_ACTHD(engine->mmio_base), 4448621f407SFrançois Tigeot RING_ACTHD_UDW(engine->mmio_base)); 445*1487f786SFrançois Tigeot else if (INTEL_GEN(dev_priv) >= 4) 4468621f407SFrançois Tigeot acthd = I915_READ(RING_ACTHD(engine->mmio_base)); 447ba55f2f5SFrançois Tigeot else 448ba55f2f5SFrançois Tigeot acthd = I915_READ(ACTHD); 449ba55f2f5SFrançois Tigeot 450ba55f2f5SFrançois Tigeot return acthd; 451e3adcf8fSFrançois Tigeot } 452e3adcf8fSFrançois Tigeot 4538621f407SFrançois Tigeot static void ring_setup_phys_status_page(struct intel_engine_cs *engine) 4545d0b1887SFrançois Tigeot { 455*1487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 4565d0b1887SFrançois Tigeot u32 addr; 4575d0b1887SFrançois Tigeot 4585d0b1887SFrançois Tigeot addr = dev_priv->status_page_dmah->busaddr; 459*1487f786SFrançois Tigeot if (INTEL_GEN(dev_priv) >= 4) 4605d0b1887SFrançois Tigeot addr |= (dev_priv->status_page_dmah->busaddr >> 28) & 0xf0; 4615d0b1887SFrançois Tigeot I915_WRITE(HWS_PGA, addr); 4625d0b1887SFrançois Tigeot } 4635d0b1887SFrançois Tigeot 4648621f407SFrançois Tigeot static void intel_ring_setup_status_page(struct intel_engine_cs *engine) 465477eb7f9SFrançois Tigeot { 466*1487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 467aee94f86SFrançois Tigeot i915_reg_t mmio; 468477eb7f9SFrançois Tigeot 469477eb7f9SFrançois Tigeot /* The ring status page addresses are no longer next to the rest of 470477eb7f9SFrançois Tigeot * the ring registers as of gen7. 471477eb7f9SFrançois Tigeot */ 472*1487f786SFrançois Tigeot if (IS_GEN7(dev_priv)) { 4738621f407SFrançois Tigeot switch (engine->id) { 474477eb7f9SFrançois Tigeot case RCS: 475477eb7f9SFrançois Tigeot mmio = RENDER_HWS_PGA_GEN7; 476477eb7f9SFrançois Tigeot break; 477477eb7f9SFrançois Tigeot case BCS: 478477eb7f9SFrançois Tigeot mmio = BLT_HWS_PGA_GEN7; 479477eb7f9SFrançois Tigeot break; 480477eb7f9SFrançois Tigeot /* 481477eb7f9SFrançois Tigeot * VCS2 actually doesn't exist on Gen7. Only shut up 482477eb7f9SFrançois Tigeot * gcc switch check warning 483477eb7f9SFrançois Tigeot */ 484477eb7f9SFrançois Tigeot case VCS2: 485477eb7f9SFrançois Tigeot case VCS: 486477eb7f9SFrançois Tigeot mmio = BSD_HWS_PGA_GEN7; 487477eb7f9SFrançois Tigeot break; 488477eb7f9SFrançois Tigeot case VECS: 489477eb7f9SFrançois Tigeot mmio = VEBOX_HWS_PGA_GEN7; 490477eb7f9SFrançois Tigeot break; 491477eb7f9SFrançois Tigeot } 492*1487f786SFrançois Tigeot } else if (IS_GEN6(dev_priv)) { 4938621f407SFrançois Tigeot mmio = RING_HWS_PGA_GEN6(engine->mmio_base); 494477eb7f9SFrançois Tigeot } else { 495477eb7f9SFrançois Tigeot /* XXX: gen8 returns to sanity */ 4968621f407SFrançois Tigeot mmio = RING_HWS_PGA(engine->mmio_base); 497477eb7f9SFrançois Tigeot } 498477eb7f9SFrançois Tigeot 4998621f407SFrançois Tigeot I915_WRITE(mmio, (u32)engine->status_page.gfx_addr); 500477eb7f9SFrançois Tigeot POSTING_READ(mmio); 501477eb7f9SFrançois Tigeot 502477eb7f9SFrançois Tigeot /* 503477eb7f9SFrançois Tigeot * Flush the TLB for this page 504477eb7f9SFrançois Tigeot * 505477eb7f9SFrançois Tigeot * FIXME: These two bits have disappeared on gen8, so a question 506477eb7f9SFrançois Tigeot * arises: do we still need this and if so how should we go about 507477eb7f9SFrançois Tigeot * invalidating the TLB? 508477eb7f9SFrançois Tigeot */ 509*1487f786SFrançois Tigeot if (IS_GEN(dev_priv, 6, 7)) { 5108621f407SFrançois Tigeot i915_reg_t reg = RING_INSTPM(engine->mmio_base); 511477eb7f9SFrançois Tigeot 512477eb7f9SFrançois Tigeot /* ring should be idle before issuing a sync flush*/ 5138621f407SFrançois Tigeot WARN_ON((I915_READ_MODE(engine) & MODE_IDLE) == 0); 514477eb7f9SFrançois Tigeot 515477eb7f9SFrançois Tigeot I915_WRITE(reg, 516477eb7f9SFrançois Tigeot _MASKED_BIT_ENABLE(INSTPM_TLB_INVALIDATE | 517477eb7f9SFrançois Tigeot INSTPM_SYNC_FLUSH)); 518*1487f786SFrançois Tigeot if (intel_wait_for_register(dev_priv, 519*1487f786SFrançois Tigeot reg, INSTPM_SYNC_FLUSH, 0, 520477eb7f9SFrançois Tigeot 1000)) 521477eb7f9SFrançois Tigeot DRM_ERROR("%s: wait for SyncFlush to complete for TLB invalidation timed out\n", 5228621f407SFrançois Tigeot engine->name); 523477eb7f9SFrançois Tigeot } 524477eb7f9SFrançois Tigeot } 525477eb7f9SFrançois Tigeot 5268621f407SFrançois Tigeot static bool stop_ring(struct intel_engine_cs *engine) 527e3adcf8fSFrançois Tigeot { 528*1487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 529e3adcf8fSFrançois Tigeot 530*1487f786SFrançois Tigeot if (!IS_GEN2(dev_priv)) { 5318621f407SFrançois Tigeot I915_WRITE_MODE(engine, _MASKED_BIT_ENABLE(STOP_RING)); 532*1487f786SFrançois Tigeot if (intel_wait_for_register(dev_priv, 533*1487f786SFrançois Tigeot RING_MI_MODE(engine->mmio_base), 534*1487f786SFrançois Tigeot MODE_IDLE, 535*1487f786SFrançois Tigeot MODE_IDLE, 536*1487f786SFrançois Tigeot 1000)) { 5378621f407SFrançois Tigeot DRM_ERROR("%s : timed out trying to stop ring\n", 5388621f407SFrançois Tigeot engine->name); 5391b13d190SFrançois Tigeot /* Sometimes we observe that the idle flag is not 5401b13d190SFrançois Tigeot * set even though the ring is empty. So double 5411b13d190SFrançois Tigeot * check before giving up. 5421b13d190SFrançois Tigeot */ 5438621f407SFrançois Tigeot if (I915_READ_HEAD(engine) != I915_READ_TAIL(engine)) 544ba55f2f5SFrançois Tigeot return false; 545ba55f2f5SFrançois Tigeot } 546ba55f2f5SFrançois Tigeot } 547686a02f1SFrançois Tigeot 5488621f407SFrançois Tigeot I915_WRITE_CTL(engine, 0); 5498621f407SFrançois Tigeot I915_WRITE_HEAD(engine, 0); 5508621f407SFrançois Tigeot engine->write_tail(engine, 0); 551e3adcf8fSFrançois Tigeot 552*1487f786SFrançois Tigeot if (!IS_GEN2(dev_priv)) { 5538621f407SFrançois Tigeot (void)I915_READ_CTL(engine); 5548621f407SFrançois Tigeot I915_WRITE_MODE(engine, _MASKED_BIT_DISABLE(STOP_RING)); 555ba55f2f5SFrançois Tigeot } 556e3adcf8fSFrançois Tigeot 5578621f407SFrançois Tigeot return (I915_READ_HEAD(engine) & HEAD_ADDR) == 0; 558ba55f2f5SFrançois Tigeot } 559ba55f2f5SFrançois Tigeot 5608621f407SFrançois Tigeot void intel_engine_init_hangcheck(struct intel_engine_cs *engine) 561ba55f2f5SFrançois Tigeot { 5628621f407SFrançois Tigeot memset(&engine->hangcheck, 0, sizeof(engine->hangcheck)); 5638621f407SFrançois Tigeot } 5648621f407SFrançois Tigeot 5658621f407SFrançois Tigeot static int init_ring_common(struct intel_engine_cs *engine) 5668621f407SFrançois Tigeot { 567*1487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 5688621f407SFrançois Tigeot struct intel_ringbuffer *ringbuf = engine->buffer; 569ba55f2f5SFrançois Tigeot struct drm_i915_gem_object *obj = ringbuf->obj; 570ba55f2f5SFrançois Tigeot int ret = 0; 571ba55f2f5SFrançois Tigeot 5722c9916cdSFrançois Tigeot intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL); 573ba55f2f5SFrançois Tigeot 5748621f407SFrançois Tigeot if (!stop_ring(engine)) { 575ba55f2f5SFrançois Tigeot /* G45 ring initialization often fails to reset head to zero */ 576b5c29a34SFrançois Tigeot DRM_DEBUG_KMS("%s head not reset to zero " 577e3adcf8fSFrançois Tigeot "ctl %08x head %08x tail %08x start %08x\n", 5788621f407SFrançois Tigeot engine->name, 5798621f407SFrançois Tigeot I915_READ_CTL(engine), 5808621f407SFrançois Tigeot I915_READ_HEAD(engine), 5818621f407SFrançois Tigeot I915_READ_TAIL(engine), 5828621f407SFrançois Tigeot I915_READ_START(engine)); 583e3adcf8fSFrançois Tigeot 5848621f407SFrançois Tigeot if (!stop_ring(engine)) { 585e3adcf8fSFrançois Tigeot DRM_ERROR("failed to set %s head to zero " 586e3adcf8fSFrançois Tigeot "ctl %08x head %08x tail %08x start %08x\n", 5878621f407SFrançois Tigeot engine->name, 5888621f407SFrançois Tigeot I915_READ_CTL(engine), 5898621f407SFrançois Tigeot I915_READ_HEAD(engine), 5908621f407SFrançois Tigeot I915_READ_TAIL(engine), 5918621f407SFrançois Tigeot I915_READ_START(engine)); 592686a02f1SFrançois Tigeot ret = -EIO; 593686a02f1SFrançois Tigeot goto out; 594e3adcf8fSFrançois Tigeot } 595ba55f2f5SFrançois Tigeot } 596ba55f2f5SFrançois Tigeot 597*1487f786SFrançois Tigeot if (I915_NEED_GFX_HWS(dev_priv)) 5988621f407SFrançois Tigeot intel_ring_setup_status_page(engine); 599ba55f2f5SFrançois Tigeot else 6008621f407SFrançois Tigeot ring_setup_phys_status_page(engine); 601ba55f2f5SFrançois Tigeot 6020f370975SMatthew Dillon /* Enforce ordering by reading HEAD register back */ 6038621f407SFrançois Tigeot I915_READ_HEAD(engine); 6040f370975SMatthew Dillon 605ba55f2f5SFrançois Tigeot /* Initialize the ring. This must happen _after_ we've cleared the ring 606ba55f2f5SFrançois Tigeot * registers with the above sequence (the readback of the HEAD registers 607ba55f2f5SFrançois Tigeot * also enforces ordering), otherwise the hw might lose the new ring 608ba55f2f5SFrançois Tigeot * register values. */ 6098621f407SFrançois Tigeot I915_WRITE_START(engine, i915_gem_obj_ggtt_offset(obj)); 6101b13d190SFrançois Tigeot 6111b13d190SFrançois Tigeot /* WaClearRingBufHeadRegAtInit:ctg,elk */ 6128621f407SFrançois Tigeot if (I915_READ_HEAD(engine)) 6131b13d190SFrançois Tigeot DRM_DEBUG("%s initialization failed [head=%08x], fudging\n", 6148621f407SFrançois Tigeot engine->name, I915_READ_HEAD(engine)); 6158621f407SFrançois Tigeot I915_WRITE_HEAD(engine, 0); 6168621f407SFrançois Tigeot (void)I915_READ_HEAD(engine); 6171b13d190SFrançois Tigeot 6188621f407SFrançois Tigeot I915_WRITE_CTL(engine, 619ba55f2f5SFrançois Tigeot ((ringbuf->size - PAGE_SIZE) & RING_NR_PAGES) 620ba55f2f5SFrançois Tigeot | RING_VALID); 621ba55f2f5SFrançois Tigeot 622ba55f2f5SFrançois Tigeot /* If the head is still not zero, the ring is dead */ 6238621f407SFrançois Tigeot if (wait_for((I915_READ_CTL(engine) & RING_VALID) != 0 && 6248621f407SFrançois Tigeot I915_READ_START(engine) == i915_gem_obj_ggtt_offset(obj) && 6258621f407SFrançois Tigeot (I915_READ_HEAD(engine) & HEAD_ADDR) == 0, 50)) { 626ba55f2f5SFrançois Tigeot DRM_ERROR("%s initialization failed " 627ba55f2f5SFrançois Tigeot "ctl %08x (valid? %d) head %08x tail %08x start %08x [expected %08lx]\n", 6288621f407SFrançois Tigeot engine->name, 6298621f407SFrançois Tigeot I915_READ_CTL(engine), 6308621f407SFrançois Tigeot I915_READ_CTL(engine) & RING_VALID, 6318621f407SFrançois Tigeot I915_READ_HEAD(engine), I915_READ_TAIL(engine), 6328621f407SFrançois Tigeot I915_READ_START(engine), 6338621f407SFrançois Tigeot (unsigned long)i915_gem_obj_ggtt_offset(obj)); 634ba55f2f5SFrançois Tigeot ret = -EIO; 635ba55f2f5SFrançois Tigeot goto out; 636ba55f2f5SFrançois Tigeot } 637e3adcf8fSFrançois Tigeot 6382c9916cdSFrançois Tigeot ringbuf->last_retired_head = -1; 6398621f407SFrançois Tigeot ringbuf->head = I915_READ_HEAD(engine); 6408621f407SFrançois Tigeot ringbuf->tail = I915_READ_TAIL(engine) & TAIL_ADDR; 6412c9916cdSFrançois Tigeot intel_ring_update_space(ringbuf); 642e3adcf8fSFrançois Tigeot 6438621f407SFrançois Tigeot intel_engine_init_hangcheck(engine); 6445d0b1887SFrançois Tigeot 645686a02f1SFrançois Tigeot out: 6462c9916cdSFrançois Tigeot intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL); 647686a02f1SFrançois Tigeot 648686a02f1SFrançois Tigeot return ret; 649e3adcf8fSFrançois Tigeot } 650e3adcf8fSFrançois Tigeot 6511b13d190SFrançois Tigeot void 6528621f407SFrançois Tigeot intel_fini_pipe_control(struct intel_engine_cs *engine) 6531b13d190SFrançois Tigeot { 6548621f407SFrançois Tigeot if (engine->scratch.obj == NULL) 6551b13d190SFrançois Tigeot return; 6561b13d190SFrançois Tigeot 657*1487f786SFrançois Tigeot if (INTEL_GEN(engine->i915) >= 5) { 6588621f407SFrançois Tigeot kunmap(sg_page(engine->scratch.obj->pages->sgl)); 6598621f407SFrançois Tigeot i915_gem_object_ggtt_unpin(engine->scratch.obj); 6601b13d190SFrançois Tigeot } 6611b13d190SFrançois Tigeot 6628621f407SFrançois Tigeot drm_gem_object_unreference(&engine->scratch.obj->base); 6638621f407SFrançois Tigeot engine->scratch.obj = NULL; 6641b13d190SFrançois Tigeot } 6651b13d190SFrançois Tigeot 6661b13d190SFrançois Tigeot int 6678621f407SFrançois Tigeot intel_init_pipe_control(struct intel_engine_cs *engine) 668e3adcf8fSFrançois Tigeot { 669e3adcf8fSFrançois Tigeot int ret; 670e3adcf8fSFrançois Tigeot 6718621f407SFrançois Tigeot WARN_ON(engine->scratch.obj); 672e3adcf8fSFrançois Tigeot 673*1487f786SFrançois Tigeot engine->scratch.obj = i915_gem_object_create(engine->i915->dev, 4096); 674*1487f786SFrançois Tigeot if (IS_ERR(engine->scratch.obj)) { 675e3adcf8fSFrançois Tigeot DRM_ERROR("Failed to allocate seqno page\n"); 676*1487f786SFrançois Tigeot ret = PTR_ERR(engine->scratch.obj); 677*1487f786SFrançois Tigeot engine->scratch.obj = NULL; 678e3adcf8fSFrançois Tigeot goto err; 679e3adcf8fSFrançois Tigeot } 680e3adcf8fSFrançois Tigeot 6818621f407SFrançois Tigeot ret = i915_gem_object_set_cache_level(engine->scratch.obj, 6828621f407SFrançois Tigeot I915_CACHE_LLC); 683ba55f2f5SFrançois Tigeot if (ret) 684ba55f2f5SFrançois Tigeot goto err_unref; 685e3adcf8fSFrançois Tigeot 6868621f407SFrançois Tigeot ret = i915_gem_obj_ggtt_pin(engine->scratch.obj, 4096, 0); 687e3adcf8fSFrançois Tigeot if (ret) 688e3adcf8fSFrançois Tigeot goto err_unref; 689e3adcf8fSFrançois Tigeot 6908621f407SFrançois Tigeot engine->scratch.gtt_offset = i915_gem_obj_ggtt_offset(engine->scratch.obj); 6918621f407SFrançois Tigeot engine->scratch.cpu_page = kmap(sg_page(engine->scratch.obj->pages->sgl)); 6928621f407SFrançois Tigeot if (engine->scratch.cpu_page == NULL) { 6935d0b1887SFrançois Tigeot ret = -ENOMEM; 694e3adcf8fSFrançois Tigeot goto err_unpin; 6955d0b1887SFrançois Tigeot } 696a2fdbec6SFrançois Tigeot 697a2fdbec6SFrançois Tigeot DRM_DEBUG_DRIVER("%s pipe control offset: 0x%08x\n", 6988621f407SFrançois Tigeot engine->name, engine->scratch.gtt_offset); 699e3adcf8fSFrançois Tigeot return 0; 700e3adcf8fSFrançois Tigeot 701e3adcf8fSFrançois Tigeot err_unpin: 7028621f407SFrançois Tigeot i915_gem_object_ggtt_unpin(engine->scratch.obj); 703e3adcf8fSFrançois Tigeot err_unref: 7048621f407SFrançois Tigeot drm_gem_object_unreference(&engine->scratch.obj->base); 705e3adcf8fSFrançois Tigeot err: 706e3adcf8fSFrançois Tigeot return ret; 707e3adcf8fSFrançois Tigeot } 708e3adcf8fSFrançois Tigeot 709a05eeebfSFrançois Tigeot static int intel_ring_workarounds_emit(struct drm_i915_gem_request *req) 7101b13d190SFrançois Tigeot { 7118621f407SFrançois Tigeot struct intel_engine_cs *engine = req->engine; 712*1487f786SFrançois Tigeot struct i915_workarounds *w = &req->i915->workarounds; 713*1487f786SFrançois Tigeot int ret, i; 7141b13d190SFrançois Tigeot 715352ff8bdSFrançois Tigeot if (w->count == 0) 7162c9916cdSFrançois Tigeot return 0; 7171b13d190SFrançois Tigeot 7188621f407SFrançois Tigeot engine->gpu_caches_dirty = true; 719a05eeebfSFrançois Tigeot ret = intel_ring_flush_all_caches(req); 7201b13d190SFrançois Tigeot if (ret) 7211b13d190SFrançois Tigeot return ret; 7221b13d190SFrançois Tigeot 723a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, (w->count * 2 + 2)); 7242c9916cdSFrançois Tigeot if (ret) 7252c9916cdSFrançois Tigeot return ret; 7262c9916cdSFrançois Tigeot 7278621f407SFrançois Tigeot intel_ring_emit(engine, MI_LOAD_REGISTER_IMM(w->count)); 7282c9916cdSFrançois Tigeot for (i = 0; i < w->count; i++) { 7298621f407SFrançois Tigeot intel_ring_emit_reg(engine, w->reg[i].addr); 7308621f407SFrançois Tigeot intel_ring_emit(engine, w->reg[i].value); 7312c9916cdSFrançois Tigeot } 7328621f407SFrançois Tigeot intel_ring_emit(engine, MI_NOOP); 7332c9916cdSFrançois Tigeot 7348621f407SFrançois Tigeot intel_ring_advance(engine); 7352c9916cdSFrançois Tigeot 7368621f407SFrançois Tigeot engine->gpu_caches_dirty = true; 737a05eeebfSFrançois Tigeot ret = intel_ring_flush_all_caches(req); 7382c9916cdSFrançois Tigeot if (ret) 7392c9916cdSFrançois Tigeot return ret; 7402c9916cdSFrançois Tigeot 7412c9916cdSFrançois Tigeot DRM_DEBUG_DRIVER("Number of Workarounds emitted: %d\n", w->count); 7422c9916cdSFrançois Tigeot 7432c9916cdSFrançois Tigeot return 0; 7442c9916cdSFrançois Tigeot } 7452c9916cdSFrançois Tigeot 746a05eeebfSFrançois Tigeot static int intel_rcs_ctx_init(struct drm_i915_gem_request *req) 7472c9916cdSFrançois Tigeot { 7482c9916cdSFrançois Tigeot int ret; 7492c9916cdSFrançois Tigeot 750a05eeebfSFrançois Tigeot ret = intel_ring_workarounds_emit(req); 7512c9916cdSFrançois Tigeot if (ret != 0) 7522c9916cdSFrançois Tigeot return ret; 7532c9916cdSFrançois Tigeot 754a05eeebfSFrançois Tigeot ret = i915_gem_render_state_init(req); 7552c9916cdSFrançois Tigeot if (ret) 7562c9916cdSFrançois Tigeot return ret; 757c0e85e96SFrançois Tigeot 758c0e85e96SFrançois Tigeot return 0; 7592c9916cdSFrançois Tigeot } 7602c9916cdSFrançois Tigeot 7612c9916cdSFrançois Tigeot static int wa_add(struct drm_i915_private *dev_priv, 762aee94f86SFrançois Tigeot i915_reg_t addr, 763aee94f86SFrançois Tigeot const u32 mask, const u32 val) 7642c9916cdSFrançois Tigeot { 7652c9916cdSFrançois Tigeot const u32 idx = dev_priv->workarounds.count; 7662c9916cdSFrançois Tigeot 7672c9916cdSFrançois Tigeot if (WARN_ON(idx >= I915_MAX_WA_REGS)) 7682c9916cdSFrançois Tigeot return -ENOSPC; 7692c9916cdSFrançois Tigeot 7702c9916cdSFrançois Tigeot dev_priv->workarounds.reg[idx].addr = addr; 7712c9916cdSFrançois Tigeot dev_priv->workarounds.reg[idx].value = val; 7722c9916cdSFrançois Tigeot dev_priv->workarounds.reg[idx].mask = mask; 7732c9916cdSFrançois Tigeot 7742c9916cdSFrançois Tigeot dev_priv->workarounds.count++; 7752c9916cdSFrançois Tigeot 7762c9916cdSFrançois Tigeot return 0; 7772c9916cdSFrançois Tigeot } 7782c9916cdSFrançois Tigeot 779a05eeebfSFrançois Tigeot #define WA_REG(addr, mask, val) do { \ 7802c9916cdSFrançois Tigeot const int r = wa_add(dev_priv, (addr), (mask), (val)); \ 7812c9916cdSFrançois Tigeot if (r) \ 7822c9916cdSFrançois Tigeot return r; \ 783a05eeebfSFrançois Tigeot } while (0) 7842c9916cdSFrançois Tigeot 7852c9916cdSFrançois Tigeot #define WA_SET_BIT_MASKED(addr, mask) \ 7862c9916cdSFrançois Tigeot WA_REG(addr, (mask), _MASKED_BIT_ENABLE(mask)) 7872c9916cdSFrançois Tigeot 7882c9916cdSFrançois Tigeot #define WA_CLR_BIT_MASKED(addr, mask) \ 7892c9916cdSFrançois Tigeot WA_REG(addr, (mask), _MASKED_BIT_DISABLE(mask)) 7902c9916cdSFrançois Tigeot 7912c9916cdSFrançois Tigeot #define WA_SET_FIELD_MASKED(addr, mask, value) \ 7922c9916cdSFrançois Tigeot WA_REG(addr, mask, _MASKED_FIELD(mask, value)) 7932c9916cdSFrançois Tigeot 7942c9916cdSFrançois Tigeot #define WA_SET_BIT(addr, mask) WA_REG(addr, mask, I915_READ(addr) | (mask)) 7952c9916cdSFrançois Tigeot #define WA_CLR_BIT(addr, mask) WA_REG(addr, mask, I915_READ(addr) & ~(mask)) 7962c9916cdSFrançois Tigeot 7972c9916cdSFrançois Tigeot #define WA_WRITE(addr, val) WA_REG(addr, 0xffffffff, val) 7982c9916cdSFrançois Tigeot 7998621f407SFrançois Tigeot static int wa_ring_whitelist_reg(struct intel_engine_cs *engine, 8008621f407SFrançois Tigeot i915_reg_t reg) 801c0e85e96SFrançois Tigeot { 802*1487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 803c0e85e96SFrançois Tigeot struct i915_workarounds *wa = &dev_priv->workarounds; 8048621f407SFrançois Tigeot const uint32_t index = wa->hw_whitelist_count[engine->id]; 805c0e85e96SFrançois Tigeot 806c0e85e96SFrançois Tigeot if (WARN_ON(index >= RING_MAX_NONPRIV_SLOTS)) 807c0e85e96SFrançois Tigeot return -EINVAL; 808c0e85e96SFrançois Tigeot 8098621f407SFrançois Tigeot WA_WRITE(RING_FORCE_TO_NONPRIV(engine->mmio_base, index), 810c0e85e96SFrançois Tigeot i915_mmio_reg_offset(reg)); 8118621f407SFrançois Tigeot wa->hw_whitelist_count[engine->id]++; 812c0e85e96SFrançois Tigeot 813c0e85e96SFrançois Tigeot return 0; 814c0e85e96SFrançois Tigeot } 815c0e85e96SFrançois Tigeot 8168621f407SFrançois Tigeot static int gen8_init_workarounds(struct intel_engine_cs *engine) 8172c9916cdSFrançois Tigeot { 818*1487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 8192c9916cdSFrançois Tigeot 820a05eeebfSFrançois Tigeot WA_SET_BIT_MASKED(INSTPM, INSTPM_FORCE_ORDERING); 821a05eeebfSFrançois Tigeot 822352ff8bdSFrançois Tigeot /* WaDisableAsyncFlipPerfMode:bdw,chv */ 823a05eeebfSFrançois Tigeot WA_SET_BIT_MASKED(MI_MODE, ASYNC_FLIP_PERF_DISABLE); 824a05eeebfSFrançois Tigeot 825352ff8bdSFrançois Tigeot /* WaDisablePartialInstShootdown:bdw,chv */ 8262c9916cdSFrançois Tigeot WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN, 827352ff8bdSFrançois Tigeot PARTIAL_INSTRUCTION_SHOOTDOWN_DISABLE); 8281b13d190SFrançois Tigeot 8291b13d190SFrançois Tigeot /* Use Force Non-Coherent whenever executing a 3D context. This is a 8301b13d190SFrançois Tigeot * workaround for for a possible hang in the unlikely event a TLB 8311b13d190SFrançois Tigeot * invalidation occurs during a PSD flush. 8321b13d190SFrançois Tigeot */ 833352ff8bdSFrançois Tigeot /* WaForceEnableNonCoherent:bdw,chv */ 834352ff8bdSFrançois Tigeot /* WaHdcDisableFetchWhenMasked:bdw,chv */ 8352c9916cdSFrançois Tigeot WA_SET_BIT_MASKED(HDC_CHICKEN0, 8362c9916cdSFrançois Tigeot HDC_DONOT_FETCH_MEM_WHEN_MASKED | 837352ff8bdSFrançois Tigeot HDC_FORCE_NON_COHERENT); 8382c9916cdSFrançois Tigeot 8392c9916cdSFrançois Tigeot /* From the Haswell PRM, Command Reference: Registers, CACHE_MODE_0: 8402c9916cdSFrançois Tigeot * "The Hierarchical Z RAW Stall Optimization allows non-overlapping 8412c9916cdSFrançois Tigeot * polygons in the same 8x4 pixel/sample area to be processed without 8422c9916cdSFrançois Tigeot * stalling waiting for the earlier ones to write to Hierarchical Z 8432c9916cdSFrançois Tigeot * buffer." 8442c9916cdSFrançois Tigeot * 845352ff8bdSFrançois Tigeot * This optimization is off by default for BDW and CHV; turn it on. 8462c9916cdSFrançois Tigeot */ 8472c9916cdSFrançois Tigeot WA_CLR_BIT_MASKED(CACHE_MODE_0_GEN7, HIZ_RAW_STALL_OPT_DISABLE); 8481b13d190SFrançois Tigeot 849352ff8bdSFrançois Tigeot /* Wa4x4STCOptimizationDisable:bdw,chv */ 850352ff8bdSFrançois Tigeot WA_SET_BIT_MASKED(CACHE_MODE_1, GEN8_4x4_STC_OPTIMIZATION_DISABLE); 8511b13d190SFrançois Tigeot 8521b13d190SFrançois Tigeot /* 8531b13d190SFrançois Tigeot * BSpec recommends 8x4 when MSAA is used, 8541b13d190SFrançois Tigeot * however in practice 16x4 seems fastest. 8551b13d190SFrançois Tigeot * 8561b13d190SFrançois Tigeot * Note that PS/WM thread counts depend on the WIZ hashing 8571b13d190SFrançois Tigeot * disable bit, which we don't touch here, but it's good 8581b13d190SFrançois Tigeot * to keep in mind (see 3DSTATE_PS and 3DSTATE_WM). 8591b13d190SFrançois Tigeot */ 8602c9916cdSFrançois Tigeot WA_SET_FIELD_MASKED(GEN7_GT_MODE, 8612c9916cdSFrançois Tigeot GEN6_WIZ_HASHING_MASK, 8622c9916cdSFrançois Tigeot GEN6_WIZ_HASHING_16x4); 8631b13d190SFrançois Tigeot 8641b13d190SFrançois Tigeot return 0; 8651b13d190SFrançois Tigeot } 8661b13d190SFrançois Tigeot 8678621f407SFrançois Tigeot static int bdw_init_workarounds(struct intel_engine_cs *engine) 8681b13d190SFrançois Tigeot { 869*1487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 870352ff8bdSFrançois Tigeot int ret; 8711b13d190SFrançois Tigeot 8728621f407SFrançois Tigeot ret = gen8_init_workarounds(engine); 873352ff8bdSFrançois Tigeot if (ret) 874352ff8bdSFrançois Tigeot return ret; 875a05eeebfSFrançois Tigeot 876352ff8bdSFrançois Tigeot /* WaDisableThreadStallDopClockGating:bdw (pre-production) */ 877352ff8bdSFrançois Tigeot WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN, STALL_DOP_GATING_DISABLE); 878a05eeebfSFrançois Tigeot 879352ff8bdSFrançois Tigeot /* WaDisableDopClockGating:bdw */ 880352ff8bdSFrançois Tigeot WA_SET_BIT_MASKED(GEN7_ROW_CHICKEN2, 881352ff8bdSFrançois Tigeot DOP_CLOCK_GATING_DISABLE); 8821b13d190SFrançois Tigeot 883352ff8bdSFrançois Tigeot WA_SET_BIT_MASKED(HALF_SLICE_CHICKEN3, 884352ff8bdSFrançois Tigeot GEN8_SAMPLER_POWER_BYPASS_DIS); 885352ff8bdSFrançois Tigeot 8862c9916cdSFrançois Tigeot WA_SET_BIT_MASKED(HDC_CHICKEN0, 887352ff8bdSFrançois Tigeot /* WaForceContextSaveRestoreNonCoherent:bdw */ 888352ff8bdSFrançois Tigeot HDC_FORCE_CONTEXT_SAVE_RESTORE_NON_COHERENT | 889352ff8bdSFrançois Tigeot /* WaDisableFenceDestinationToSLM:bdw (pre-prod) */ 890*1487f786SFrançois Tigeot (IS_BDW_GT3(dev_priv) ? HDC_FENCE_DEST_SLM_DISABLE : 0)); 8911b13d190SFrançois Tigeot 892352ff8bdSFrançois Tigeot return 0; 893352ff8bdSFrançois Tigeot } 8941b13d190SFrançois Tigeot 8958621f407SFrançois Tigeot static int chv_init_workarounds(struct intel_engine_cs *engine) 896352ff8bdSFrançois Tigeot { 897*1487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 898352ff8bdSFrançois Tigeot int ret; 899352ff8bdSFrançois Tigeot 9008621f407SFrançois Tigeot ret = gen8_init_workarounds(engine); 901352ff8bdSFrançois Tigeot if (ret) 902352ff8bdSFrançois Tigeot return ret; 903352ff8bdSFrançois Tigeot 904352ff8bdSFrançois Tigeot /* WaDisableThreadStallDopClockGating:chv */ 905352ff8bdSFrançois Tigeot WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN, STALL_DOP_GATING_DISABLE); 9062c9916cdSFrançois Tigeot 9072c9916cdSFrançois Tigeot /* Improve HiZ throughput on CHV. */ 9082c9916cdSFrançois Tigeot WA_SET_BIT_MASKED(HIZ_CHICKEN, CHV_HZ_8X8_MODE_IN_1X); 9092c9916cdSFrançois Tigeot 9102c9916cdSFrançois Tigeot return 0; 9112c9916cdSFrançois Tigeot } 9122c9916cdSFrançois Tigeot 9138621f407SFrançois Tigeot static int gen9_init_workarounds(struct intel_engine_cs *engine) 914477eb7f9SFrançois Tigeot { 915*1487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 916c0e85e96SFrançois Tigeot int ret; 917477eb7f9SFrançois Tigeot 9188621f407SFrançois Tigeot /* WaConextSwitchWithConcurrentTLBInvalidate:skl,bxt,kbl */ 9198621f407SFrançois Tigeot I915_WRITE(GEN9_CSFE_CHICKEN1_RCS, _MASKED_BIT_ENABLE(GEN9_PREEMPT_GPGPU_SYNC_SWITCH_DISABLE)); 9208621f407SFrançois Tigeot 9218621f407SFrançois Tigeot /* WaEnableLbsSlaRetryTimerDecrement:skl,bxt,kbl */ 922352ff8bdSFrançois Tigeot I915_WRITE(BDW_SCRATCH1, I915_READ(BDW_SCRATCH1) | 923352ff8bdSFrançois Tigeot GEN9_LBS_SLA_RETRY_TIMER_DECREMENT_ENABLE); 924352ff8bdSFrançois Tigeot 9258621f407SFrançois Tigeot /* WaDisableKillLogic:bxt,skl,kbl */ 926352ff8bdSFrançois Tigeot I915_WRITE(GAM_ECOCHK, I915_READ(GAM_ECOCHK) | 927352ff8bdSFrançois Tigeot ECOCHK_DIS_TLB); 928352ff8bdSFrançois Tigeot 9298621f407SFrançois Tigeot /* WaClearFlowControlGpgpuContextSave:skl,bxt,kbl */ 9308621f407SFrançois Tigeot /* WaDisablePartialInstShootdown:skl,bxt,kbl */ 931477eb7f9SFrançois Tigeot WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN, 9328621f407SFrançois Tigeot FLOW_CONTROL_ENABLE | 933477eb7f9SFrançois Tigeot PARTIAL_INSTRUCTION_SHOOTDOWN_DISABLE); 934477eb7f9SFrançois Tigeot 9358621f407SFrançois Tigeot /* Syncing dependencies between camera and graphics:skl,bxt,kbl */ 936477eb7f9SFrançois Tigeot WA_SET_BIT_MASKED(HALF_SLICE_CHICKEN3, 937477eb7f9SFrançois Tigeot GEN9_DISABLE_OCL_OOB_SUPPRESS_LOGIC); 938477eb7f9SFrançois Tigeot 93919c468b4SFrançois Tigeot /* WaDisableDgMirrorFixInHalfSliceChicken5:skl,bxt */ 940*1487f786SFrançois Tigeot if (IS_SKL_REVID(dev_priv, 0, SKL_REVID_B0) || 941*1487f786SFrançois Tigeot IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1)) 942477eb7f9SFrançois Tigeot WA_CLR_BIT_MASKED(GEN9_HALF_SLICE_CHICKEN5, 943477eb7f9SFrançois Tigeot GEN9_DG_MIRROR_FIX_ENABLE); 944477eb7f9SFrançois Tigeot 94519c468b4SFrançois Tigeot /* WaSetDisablePixMaskCammingAndRhwoInCommonSliceChicken:skl,bxt */ 946*1487f786SFrançois Tigeot if (IS_SKL_REVID(dev_priv, 0, SKL_REVID_B0) || 947*1487f786SFrançois Tigeot IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1)) { 948477eb7f9SFrançois Tigeot WA_SET_BIT_MASKED(GEN7_COMMON_SLICE_CHICKEN1, 949477eb7f9SFrançois Tigeot GEN9_RHWO_OPTIMIZATION_DISABLE); 950a05eeebfSFrançois Tigeot /* 951a05eeebfSFrançois Tigeot * WA also requires GEN9_SLICE_COMMON_ECO_CHICKEN0[14:14] to be set 952a05eeebfSFrançois Tigeot * but we do that in per ctx batchbuffer as there is an issue 953a05eeebfSFrançois Tigeot * with this register not getting restored on ctx restore 954a05eeebfSFrançois Tigeot */ 955477eb7f9SFrançois Tigeot } 956477eb7f9SFrançois Tigeot 9578621f407SFrançois Tigeot /* WaEnableYV12BugFixInHalfSliceChicken7:skl,bxt,kbl */ 9588621f407SFrançois Tigeot /* WaEnableSamplerGPGPUPreemptionSupport:skl,bxt,kbl */ 959477eb7f9SFrançois Tigeot WA_SET_BIT_MASKED(GEN9_HALF_SLICE_CHICKEN7, 9608621f407SFrançois Tigeot GEN9_ENABLE_YV12_BUGFIX | 9618621f407SFrançois Tigeot GEN9_ENABLE_GPGPU_PREEMPTION); 962477eb7f9SFrançois Tigeot 9638621f407SFrançois Tigeot /* Wa4x4STCOptimizationDisable:skl,bxt,kbl */ 9648621f407SFrançois Tigeot /* WaDisablePartialResolveInVc:skl,bxt,kbl */ 965352ff8bdSFrançois Tigeot WA_SET_BIT_MASKED(CACHE_MODE_1, (GEN8_4x4_STC_OPTIMIZATION_DISABLE | 966352ff8bdSFrançois Tigeot GEN9_PARTIAL_RESOLVE_IN_VC_DISABLE)); 967477eb7f9SFrançois Tigeot 9688621f407SFrançois Tigeot /* WaCcsTlbPrefetchDisable:skl,bxt,kbl */ 969477eb7f9SFrançois Tigeot WA_CLR_BIT_MASKED(GEN9_HALF_SLICE_CHICKEN5, 970477eb7f9SFrançois Tigeot GEN9_CCS_TLB_PREFETCH_ENABLE); 971477eb7f9SFrançois Tigeot 97219c468b4SFrançois Tigeot /* WaDisableMaskBasedCammingInRCC:skl,bxt */ 973*1487f786SFrançois Tigeot if (IS_SKL_REVID(dev_priv, SKL_REVID_C0, SKL_REVID_C0) || 974*1487f786SFrançois Tigeot IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1)) 97519c468b4SFrançois Tigeot WA_SET_BIT_MASKED(SLICE_ECO_CHICKEN0, 97619c468b4SFrançois Tigeot PIXEL_MASK_CAMMING_DISABLE); 97719c468b4SFrançois Tigeot 9788621f407SFrançois Tigeot /* WaForceContextSaveRestoreNonCoherent:skl,bxt,kbl */ 9798621f407SFrançois Tigeot WA_SET_BIT_MASKED(HDC_CHICKEN0, 9808621f407SFrançois Tigeot HDC_FORCE_CONTEXT_SAVE_RESTORE_NON_COHERENT | 9818621f407SFrançois Tigeot HDC_FORCE_CSR_NON_COHERENT_OVR_DISABLE); 98219c468b4SFrançois Tigeot 9838621f407SFrançois Tigeot /* WaForceEnableNonCoherent and WaDisableHDCInvalidation are 9848621f407SFrançois Tigeot * both tied to WaForceContextSaveRestoreNonCoherent 9858621f407SFrançois Tigeot * in some hsds for skl. We keep the tie for all gen9. The 9868621f407SFrançois Tigeot * documentation is a bit hazy and so we want to get common behaviour, 9878621f407SFrançois Tigeot * even though there is no clear evidence we would need both on kbl/bxt. 9888621f407SFrançois Tigeot * This area has been source of system hangs so we play it safe 9898621f407SFrançois Tigeot * and mimic the skl regardless of what bspec says. 9908621f407SFrançois Tigeot * 9918621f407SFrançois Tigeot * Use Force Non-Coherent whenever executing a 3D context. This 9928621f407SFrançois Tigeot * is a workaround for a possible hang in the unlikely event 9938621f407SFrançois Tigeot * a TLB invalidation occurs during a PSD flush. 9948621f407SFrançois Tigeot */ 9958621f407SFrançois Tigeot 9968621f407SFrançois Tigeot /* WaForceEnableNonCoherent:skl,bxt,kbl */ 9978621f407SFrançois Tigeot WA_SET_BIT_MASKED(HDC_CHICKEN0, 9988621f407SFrançois Tigeot HDC_FORCE_NON_COHERENT); 9998621f407SFrançois Tigeot 10008621f407SFrançois Tigeot /* WaDisableHDCInvalidation:skl,bxt,kbl */ 10018621f407SFrançois Tigeot I915_WRITE(GAM_ECOCHK, I915_READ(GAM_ECOCHK) | 10028621f407SFrançois Tigeot BDW_DISABLE_HDC_INVALIDATION); 10038621f407SFrançois Tigeot 10048621f407SFrançois Tigeot /* WaDisableSamplerPowerBypassForSOPingPong:skl,bxt,kbl */ 10058621f407SFrançois Tigeot if (IS_SKYLAKE(dev_priv) || 10068621f407SFrançois Tigeot IS_KABYLAKE(dev_priv) || 10078621f407SFrançois Tigeot IS_BXT_REVID(dev_priv, 0, BXT_REVID_B0)) 1008352ff8bdSFrançois Tigeot WA_SET_BIT_MASKED(HALF_SLICE_CHICKEN3, 1009352ff8bdSFrançois Tigeot GEN8_SAMPLER_POWER_BYPASS_DIS); 1010352ff8bdSFrançois Tigeot 10118621f407SFrançois Tigeot /* WaDisableSTUnitPowerOptimization:skl,bxt,kbl */ 1012352ff8bdSFrançois Tigeot WA_SET_BIT_MASKED(HALF_SLICE_CHICKEN2, GEN8_ST_PO_DISABLE); 1013352ff8bdSFrançois Tigeot 10148621f407SFrançois Tigeot /* WaOCLCoherentLineFlush:skl,bxt,kbl */ 1015c0e85e96SFrançois Tigeot I915_WRITE(GEN8_L3SQCREG4, (I915_READ(GEN8_L3SQCREG4) | 1016c0e85e96SFrançois Tigeot GEN8_LQSC_FLUSH_COHERENT_LINES)); 1017c0e85e96SFrançois Tigeot 10188621f407SFrançois Tigeot /* WaVFEStateAfterPipeControlwithMediaStateClear:skl,bxt */ 10198621f407SFrançois Tigeot ret = wa_ring_whitelist_reg(engine, GEN9_CTX_PREEMPT_REG); 1020c0e85e96SFrançois Tigeot if (ret) 1021c0e85e96SFrançois Tigeot return ret; 1022c0e85e96SFrançois Tigeot 10238621f407SFrançois Tigeot /* WaEnablePreemptionGranularityControlByUMD:skl,bxt,kbl */ 10248621f407SFrançois Tigeot ret= wa_ring_whitelist_reg(engine, GEN8_CS_CHICKEN1); 10258621f407SFrançois Tigeot if (ret) 10268621f407SFrançois Tigeot return ret; 10278621f407SFrançois Tigeot 10288621f407SFrançois Tigeot /* WaAllowUMDToModifyHDCChicken1:skl,bxt,kbl */ 10298621f407SFrançois Tigeot ret = wa_ring_whitelist_reg(engine, GEN8_HDC_CHICKEN1); 1030c0e85e96SFrançois Tigeot if (ret) 1031c0e85e96SFrançois Tigeot return ret; 1032c0e85e96SFrançois Tigeot 1033477eb7f9SFrançois Tigeot return 0; 1034477eb7f9SFrançois Tigeot } 1035477eb7f9SFrançois Tigeot 10368621f407SFrançois Tigeot static int skl_tune_iz_hashing(struct intel_engine_cs *engine) 1037477eb7f9SFrançois Tigeot { 1038*1487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 1039477eb7f9SFrançois Tigeot u8 vals[3] = { 0, 0, 0 }; 1040477eb7f9SFrançois Tigeot unsigned int i; 1041477eb7f9SFrançois Tigeot 1042477eb7f9SFrançois Tigeot for (i = 0; i < 3; i++) { 1043477eb7f9SFrançois Tigeot u8 ss; 1044477eb7f9SFrançois Tigeot 1045477eb7f9SFrançois Tigeot /* 1046477eb7f9SFrançois Tigeot * Only consider slices where one, and only one, subslice has 7 1047477eb7f9SFrançois Tigeot * EUs 1048477eb7f9SFrançois Tigeot */ 1049aee94f86SFrançois Tigeot if (!is_power_of_2(dev_priv->info.subslice_7eu[i])) 1050477eb7f9SFrançois Tigeot continue; 1051477eb7f9SFrançois Tigeot 1052477eb7f9SFrançois Tigeot /* 1053477eb7f9SFrançois Tigeot * subslice_7eu[i] != 0 (because of the check above) and 1054477eb7f9SFrançois Tigeot * ss_max == 4 (maximum number of subslices possible per slice) 1055477eb7f9SFrançois Tigeot * 1056477eb7f9SFrançois Tigeot * -> 0 <= ss <= 3; 1057477eb7f9SFrançois Tigeot */ 1058477eb7f9SFrançois Tigeot ss = ffs(dev_priv->info.subslice_7eu[i]) - 1; 1059477eb7f9SFrançois Tigeot vals[i] = 3 - ss; 1060477eb7f9SFrançois Tigeot } 1061477eb7f9SFrançois Tigeot 1062477eb7f9SFrançois Tigeot if (vals[0] == 0 && vals[1] == 0 && vals[2] == 0) 1063477eb7f9SFrançois Tigeot return 0; 1064477eb7f9SFrançois Tigeot 1065477eb7f9SFrançois Tigeot /* Tune IZ hashing. See intel_device_info_runtime_init() */ 1066477eb7f9SFrançois Tigeot WA_SET_FIELD_MASKED(GEN7_GT_MODE, 1067477eb7f9SFrançois Tigeot GEN9_IZ_HASHING_MASK(2) | 1068477eb7f9SFrançois Tigeot GEN9_IZ_HASHING_MASK(1) | 1069477eb7f9SFrançois Tigeot GEN9_IZ_HASHING_MASK(0), 1070477eb7f9SFrançois Tigeot GEN9_IZ_HASHING(2, vals[2]) | 1071477eb7f9SFrançois Tigeot GEN9_IZ_HASHING(1, vals[1]) | 1072477eb7f9SFrançois Tigeot GEN9_IZ_HASHING(0, vals[0])); 1073477eb7f9SFrançois Tigeot 1074477eb7f9SFrançois Tigeot return 0; 1075477eb7f9SFrançois Tigeot } 1076477eb7f9SFrançois Tigeot 10778621f407SFrançois Tigeot static int skl_init_workarounds(struct intel_engine_cs *engine) 1078477eb7f9SFrançois Tigeot { 1079*1487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 1080352ff8bdSFrançois Tigeot int ret; 1081477eb7f9SFrançois Tigeot 10828621f407SFrançois Tigeot ret = gen9_init_workarounds(engine); 1083352ff8bdSFrançois Tigeot if (ret) 1084352ff8bdSFrançois Tigeot return ret; 1085352ff8bdSFrançois Tigeot 1086c0e85e96SFrançois Tigeot /* 1087c0e85e96SFrançois Tigeot * Actual WA is to disable percontext preemption granularity control 1088c0e85e96SFrançois Tigeot * until D0 which is the default case so this is equivalent to 1089c0e85e96SFrançois Tigeot * !WaDisablePerCtxtPreemptionGranularityControl:skl 1090c0e85e96SFrançois Tigeot */ 1091*1487f786SFrançois Tigeot if (IS_SKL_REVID(dev_priv, SKL_REVID_E0, REVID_FOREVER)) { 1092c0e85e96SFrançois Tigeot I915_WRITE(GEN7_FF_SLICE_CS_CHICKEN1, 1093c0e85e96SFrançois Tigeot _MASKED_BIT_ENABLE(GEN9_FFSC_PERCTX_PREEMPT_CTRL)); 1094c0e85e96SFrançois Tigeot } 1095c0e85e96SFrançois Tigeot 1096*1487f786SFrançois Tigeot if (IS_SKL_REVID(dev_priv, 0, SKL_REVID_E0)) { 1097352ff8bdSFrançois Tigeot /* WaDisableChickenBitTSGBarrierAckForFFSliceCS:skl */ 1098352ff8bdSFrançois Tigeot I915_WRITE(FF_SLICE_CS_CHICKEN2, 1099352ff8bdSFrançois Tigeot _MASKED_BIT_ENABLE(GEN9_TSG_BARRIER_ACK_DISABLE)); 1100352ff8bdSFrançois Tigeot } 1101352ff8bdSFrançois Tigeot 1102352ff8bdSFrançois Tigeot /* GEN8_L3SQCREG4 has a dependency with WA batch so any new changes 1103352ff8bdSFrançois Tigeot * involving this register should also be added to WA batch as required. 1104352ff8bdSFrançois Tigeot */ 1105*1487f786SFrançois Tigeot if (IS_SKL_REVID(dev_priv, 0, SKL_REVID_E0)) 1106352ff8bdSFrançois Tigeot /* WaDisableLSQCROPERFforOCL:skl */ 1107352ff8bdSFrançois Tigeot I915_WRITE(GEN8_L3SQCREG4, I915_READ(GEN8_L3SQCREG4) | 1108352ff8bdSFrançois Tigeot GEN8_LQSC_RO_PERF_DIS); 1109352ff8bdSFrançois Tigeot 1110352ff8bdSFrançois Tigeot /* WaEnableGapsTsvCreditFix:skl */ 1111*1487f786SFrançois Tigeot if (IS_SKL_REVID(dev_priv, SKL_REVID_C0, REVID_FOREVER)) { 1112352ff8bdSFrançois Tigeot I915_WRITE(GEN8_GARBCNTL, (I915_READ(GEN8_GARBCNTL) | 1113352ff8bdSFrançois Tigeot GEN9_GAPS_TSV_CREDIT_DISABLE)); 1114352ff8bdSFrançois Tigeot } 1115477eb7f9SFrançois Tigeot 1116477eb7f9SFrançois Tigeot /* WaDisablePowerCompilerClockGating:skl */ 1117*1487f786SFrançois Tigeot if (IS_SKL_REVID(dev_priv, SKL_REVID_B0, SKL_REVID_B0)) 1118477eb7f9SFrançois Tigeot WA_SET_BIT_MASKED(HIZ_CHICKEN, 1119477eb7f9SFrançois Tigeot BDW_HIZ_POWER_COMPILER_CLOCK_GATING_DISABLE); 1120477eb7f9SFrançois Tigeot 1121a05eeebfSFrançois Tigeot /* WaBarrierPerformanceFixDisable:skl */ 1122*1487f786SFrançois Tigeot if (IS_SKL_REVID(dev_priv, SKL_REVID_C0, SKL_REVID_D0)) 1123a05eeebfSFrançois Tigeot WA_SET_BIT_MASKED(HDC_CHICKEN0, 1124a05eeebfSFrançois Tigeot HDC_FENCE_DEST_SLM_DISABLE | 1125a05eeebfSFrançois Tigeot HDC_BARRIER_PERFORMANCE_DISABLE); 1126a05eeebfSFrançois Tigeot 1127a05eeebfSFrançois Tigeot /* WaDisableSbeCacheDispatchPortSharing:skl */ 1128*1487f786SFrançois Tigeot if (IS_SKL_REVID(dev_priv, 0, SKL_REVID_F0)) 1129a05eeebfSFrançois Tigeot WA_SET_BIT_MASKED( 1130a05eeebfSFrançois Tigeot GEN7_HALF_SLICE_CHICKEN1, 1131a05eeebfSFrançois Tigeot GEN7_SBE_SS_CACHE_DISPATCH_PORT_SHARING_DISABLE); 1132a05eeebfSFrançois Tigeot 11338621f407SFrançois Tigeot /* WaDisableGafsUnitClkGating:skl */ 11348621f407SFrançois Tigeot WA_SET_BIT(GEN7_UCGCTL4, GEN8_EU_GAUNIT_CLOCK_GATE_DISABLE); 11358621f407SFrançois Tigeot 1136c0e85e96SFrançois Tigeot /* WaDisableLSQCROPERFforOCL:skl */ 11378621f407SFrançois Tigeot ret = wa_ring_whitelist_reg(engine, GEN8_L3SQCREG4); 1138c0e85e96SFrançois Tigeot if (ret) 1139c0e85e96SFrançois Tigeot return ret; 1140c0e85e96SFrançois Tigeot 11418621f407SFrançois Tigeot return skl_tune_iz_hashing(engine); 1142477eb7f9SFrançois Tigeot } 1143477eb7f9SFrançois Tigeot 11448621f407SFrançois Tigeot static int bxt_init_workarounds(struct intel_engine_cs *engine) 114519c468b4SFrançois Tigeot { 1146*1487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 1147352ff8bdSFrançois Tigeot int ret; 114819c468b4SFrançois Tigeot 11498621f407SFrançois Tigeot ret = gen9_init_workarounds(engine); 1150352ff8bdSFrançois Tigeot if (ret) 1151352ff8bdSFrançois Tigeot return ret; 1152352ff8bdSFrançois Tigeot 1153352ff8bdSFrançois Tigeot /* WaStoreMultiplePTEenable:bxt */ 1154352ff8bdSFrançois Tigeot /* This is a requirement according to Hardware specification */ 1155*1487f786SFrançois Tigeot if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1)) 1156352ff8bdSFrançois Tigeot I915_WRITE(TILECTL, I915_READ(TILECTL) | TILECTL_TLBPF); 1157352ff8bdSFrançois Tigeot 1158352ff8bdSFrançois Tigeot /* WaSetClckGatingDisableMedia:bxt */ 1159*1487f786SFrançois Tigeot if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1)) { 1160352ff8bdSFrançois Tigeot I915_WRITE(GEN7_MISCCPCTL, (I915_READ(GEN7_MISCCPCTL) & 1161352ff8bdSFrançois Tigeot ~GEN8_DOP_CLOCK_GATE_MEDIA_ENABLE)); 1162352ff8bdSFrançois Tigeot } 116319c468b4SFrançois Tigeot 116419c468b4SFrançois Tigeot /* WaDisableThreadStallDopClockGating:bxt */ 116519c468b4SFrançois Tigeot WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN, 116619c468b4SFrançois Tigeot STALL_DOP_GATING_DISABLE); 116719c468b4SFrançois Tigeot 1168*1487f786SFrançois Tigeot /* WaDisablePooledEuLoadBalancingFix:bxt */ 1169*1487f786SFrançois Tigeot if (IS_BXT_REVID(dev_priv, BXT_REVID_B0, REVID_FOREVER)) { 1170*1487f786SFrançois Tigeot WA_SET_BIT_MASKED(FF_SLICE_CS_CHICKEN2, 1171*1487f786SFrançois Tigeot GEN9_POOLED_EU_LOAD_BALANCING_FIX_DISABLE); 1172*1487f786SFrançois Tigeot } 1173*1487f786SFrançois Tigeot 117419c468b4SFrançois Tigeot /* WaDisableSbeCacheDispatchPortSharing:bxt */ 1175*1487f786SFrançois Tigeot if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_B0)) { 117619c468b4SFrançois Tigeot WA_SET_BIT_MASKED( 117719c468b4SFrançois Tigeot GEN7_HALF_SLICE_CHICKEN1, 117819c468b4SFrançois Tigeot GEN7_SBE_SS_CACHE_DISPATCH_PORT_SHARING_DISABLE); 117919c468b4SFrançois Tigeot } 118019c468b4SFrançois Tigeot 1181c0e85e96SFrançois Tigeot /* WaDisableObjectLevelPreemptionForTrifanOrPolygon:bxt */ 1182c0e85e96SFrançois Tigeot /* WaDisableObjectLevelPreemptionForInstancedDraw:bxt */ 1183c0e85e96SFrançois Tigeot /* WaDisableObjectLevelPreemtionForInstanceId:bxt */ 1184c0e85e96SFrançois Tigeot /* WaDisableLSQCROPERFforOCL:bxt */ 1185*1487f786SFrançois Tigeot if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1)) { 11868621f407SFrançois Tigeot ret = wa_ring_whitelist_reg(engine, GEN9_CS_DEBUG_MODE1); 1187c0e85e96SFrançois Tigeot if (ret) 1188c0e85e96SFrançois Tigeot return ret; 1189c0e85e96SFrançois Tigeot 11908621f407SFrançois Tigeot ret = wa_ring_whitelist_reg(engine, GEN8_L3SQCREG4); 1191c0e85e96SFrançois Tigeot if (ret) 1192c0e85e96SFrançois Tigeot return ret; 1193c0e85e96SFrançois Tigeot } 1194c0e85e96SFrançois Tigeot 1195*1487f786SFrançois Tigeot /* WaProgramL3SqcReg1DefaultForPerf:bxt */ 1196*1487f786SFrançois Tigeot if (IS_BXT_REVID(dev_priv, BXT_REVID_B0, REVID_FOREVER)) 1197*1487f786SFrançois Tigeot I915_WRITE(GEN8_L3SQCREG1, L3_GENERAL_PRIO_CREDITS(62) | 1198*1487f786SFrançois Tigeot L3_HIGH_PRIO_CREDITS(2)); 1199*1487f786SFrançois Tigeot 12008621f407SFrançois Tigeot /* WaInsertDummyPushConstPs:bxt */ 12018621f407SFrançois Tigeot if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_B0)) 12028621f407SFrançois Tigeot WA_SET_BIT_MASKED(COMMON_SLICE_CHICKEN2, 12038621f407SFrançois Tigeot GEN8_SBE_DISABLE_REPLAY_BUF_OPTIMIZATION); 12048621f407SFrançois Tigeot 120519c468b4SFrançois Tigeot return 0; 120619c468b4SFrançois Tigeot } 120719c468b4SFrançois Tigeot 12088621f407SFrançois Tigeot static int kbl_init_workarounds(struct intel_engine_cs *engine) 12092c9916cdSFrançois Tigeot { 1210*1487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 12118621f407SFrançois Tigeot int ret; 12128621f407SFrançois Tigeot 12138621f407SFrançois Tigeot ret = gen9_init_workarounds(engine); 12148621f407SFrançois Tigeot if (ret) 12158621f407SFrançois Tigeot return ret; 12168621f407SFrançois Tigeot 12178621f407SFrançois Tigeot /* WaEnableGapsTsvCreditFix:kbl */ 12188621f407SFrançois Tigeot I915_WRITE(GEN8_GARBCNTL, (I915_READ(GEN8_GARBCNTL) | 12198621f407SFrançois Tigeot GEN9_GAPS_TSV_CREDIT_DISABLE)); 12208621f407SFrançois Tigeot 12218621f407SFrançois Tigeot /* WaDisableDynamicCreditSharing:kbl */ 12228621f407SFrançois Tigeot if (IS_KBL_REVID(dev_priv, 0, KBL_REVID_B0)) 12238621f407SFrançois Tigeot WA_SET_BIT(GAMT_CHKN_BIT_REG, 12248621f407SFrançois Tigeot GAMT_CHKN_DISABLE_DYNAMIC_CREDIT_SHARING); 12258621f407SFrançois Tigeot 12268621f407SFrançois Tigeot /* WaDisableFenceDestinationToSLM:kbl (pre-prod) */ 12278621f407SFrançois Tigeot if (IS_KBL_REVID(dev_priv, KBL_REVID_A0, KBL_REVID_A0)) 12288621f407SFrançois Tigeot WA_SET_BIT_MASKED(HDC_CHICKEN0, 12298621f407SFrançois Tigeot HDC_FENCE_DEST_SLM_DISABLE); 12308621f407SFrançois Tigeot 12318621f407SFrançois Tigeot /* GEN8_L3SQCREG4 has a dependency with WA batch so any new changes 12328621f407SFrançois Tigeot * involving this register should also be added to WA batch as required. 12338621f407SFrançois Tigeot */ 12348621f407SFrançois Tigeot if (IS_KBL_REVID(dev_priv, 0, KBL_REVID_E0)) 12358621f407SFrançois Tigeot /* WaDisableLSQCROPERFforOCL:kbl */ 12368621f407SFrançois Tigeot I915_WRITE(GEN8_L3SQCREG4, I915_READ(GEN8_L3SQCREG4) | 12378621f407SFrançois Tigeot GEN8_LQSC_RO_PERF_DIS); 12388621f407SFrançois Tigeot 12398621f407SFrançois Tigeot /* WaInsertDummyPushConstPs:kbl */ 12408621f407SFrançois Tigeot if (IS_KBL_REVID(dev_priv, 0, KBL_REVID_B0)) 12418621f407SFrançois Tigeot WA_SET_BIT_MASKED(COMMON_SLICE_CHICKEN2, 12428621f407SFrançois Tigeot GEN8_SBE_DISABLE_REPLAY_BUF_OPTIMIZATION); 12438621f407SFrançois Tigeot 12448621f407SFrançois Tigeot /* WaDisableGafsUnitClkGating:kbl */ 12458621f407SFrançois Tigeot WA_SET_BIT(GEN7_UCGCTL4, GEN8_EU_GAUNIT_CLOCK_GATE_DISABLE); 12468621f407SFrançois Tigeot 12478621f407SFrançois Tigeot /* WaDisableSbeCacheDispatchPortSharing:kbl */ 12488621f407SFrançois Tigeot WA_SET_BIT_MASKED( 12498621f407SFrançois Tigeot GEN7_HALF_SLICE_CHICKEN1, 12508621f407SFrançois Tigeot GEN7_SBE_SS_CACHE_DISPATCH_PORT_SHARING_DISABLE); 12518621f407SFrançois Tigeot 12528621f407SFrançois Tigeot /* WaDisableLSQCROPERFforOCL:kbl */ 12538621f407SFrançois Tigeot ret = wa_ring_whitelist_reg(engine, GEN8_L3SQCREG4); 12548621f407SFrançois Tigeot if (ret) 12558621f407SFrançois Tigeot return ret; 12568621f407SFrançois Tigeot 12578621f407SFrançois Tigeot return 0; 12588621f407SFrançois Tigeot } 12598621f407SFrançois Tigeot 12608621f407SFrançois Tigeot int init_workarounds_ring(struct intel_engine_cs *engine) 12618621f407SFrançois Tigeot { 1262*1487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 12632c9916cdSFrançois Tigeot 12648621f407SFrançois Tigeot WARN_ON(engine->id != RCS); 12652c9916cdSFrançois Tigeot 12662c9916cdSFrançois Tigeot dev_priv->workarounds.count = 0; 1267c0e85e96SFrançois Tigeot dev_priv->workarounds.hw_whitelist_count[RCS] = 0; 12682c9916cdSFrançois Tigeot 1269*1487f786SFrançois Tigeot if (IS_BROADWELL(dev_priv)) 12708621f407SFrançois Tigeot return bdw_init_workarounds(engine); 12712c9916cdSFrançois Tigeot 1272*1487f786SFrançois Tigeot if (IS_CHERRYVIEW(dev_priv)) 12738621f407SFrançois Tigeot return chv_init_workarounds(engine); 12741b13d190SFrançois Tigeot 1275*1487f786SFrançois Tigeot if (IS_SKYLAKE(dev_priv)) 12768621f407SFrançois Tigeot return skl_init_workarounds(engine); 127719c468b4SFrançois Tigeot 1278*1487f786SFrançois Tigeot if (IS_BROXTON(dev_priv)) 12798621f407SFrançois Tigeot return bxt_init_workarounds(engine); 12808621f407SFrançois Tigeot 12818621f407SFrançois Tigeot if (IS_KABYLAKE(dev_priv)) 12828621f407SFrançois Tigeot return kbl_init_workarounds(engine); 1283477eb7f9SFrançois Tigeot 12841b13d190SFrançois Tigeot return 0; 12851b13d190SFrançois Tigeot } 12861b13d190SFrançois Tigeot 12878621f407SFrançois Tigeot static int init_render_ring(struct intel_engine_cs *engine) 1288e3adcf8fSFrançois Tigeot { 1289*1487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 12908621f407SFrançois Tigeot int ret = init_ring_common(engine); 129124edb884SFrançois Tigeot if (ret) 129224edb884SFrançois Tigeot return ret; 1293e3adcf8fSFrançois Tigeot 1294ba55f2f5SFrançois Tigeot /* WaTimedSingleVertexDispatch:cl,bw,ctg,elk,ilk,snb */ 1295*1487f786SFrançois Tigeot if (IS_GEN(dev_priv, 4, 6)) 1296f4e1c372SFrançois Tigeot I915_WRITE(MI_MODE, _MASKED_BIT_ENABLE(VS_TIMER_DISPATCH)); 1297f4e1c372SFrançois Tigeot 1298f4e1c372SFrançois Tigeot /* We need to disable the AsyncFlip performance optimisations in order 1299f4e1c372SFrançois Tigeot * to use MI_WAIT_FOR_EVENT within the CS. It should already be 1300f4e1c372SFrançois Tigeot * programmed to '1' on all products. 13015d0b1887SFrançois Tigeot * 1302a05eeebfSFrançois Tigeot * WaDisableAsyncFlipPerfMode:snb,ivb,hsw,vlv 1303f4e1c372SFrançois Tigeot */ 1304*1487f786SFrançois Tigeot if (IS_GEN(dev_priv, 6, 7)) 1305f4e1c372SFrançois Tigeot I915_WRITE(MI_MODE, _MASKED_BIT_ENABLE(ASYNC_FLIP_PERF_DISABLE)); 1306f4e1c372SFrançois Tigeot 1307f4e1c372SFrançois Tigeot /* Required for the hardware to program scanline values for waiting */ 1308ba55f2f5SFrançois Tigeot /* WaEnableFlushTlbInvalidationMode:snb */ 1309*1487f786SFrançois Tigeot if (IS_GEN6(dev_priv)) 1310f4e1c372SFrançois Tigeot I915_WRITE(GFX_MODE, 1311ba55f2f5SFrançois Tigeot _MASKED_BIT_ENABLE(GFX_TLB_INVALIDATE_EXPLICIT)); 1312f4e1c372SFrançois Tigeot 1313ba55f2f5SFrançois Tigeot /* WaBCSVCSTlbInvalidationMode:ivb,vlv,hsw */ 1314*1487f786SFrançois Tigeot if (IS_GEN7(dev_priv)) 1315e3adcf8fSFrançois Tigeot I915_WRITE(GFX_MODE_GEN7, 1316ba55f2f5SFrançois Tigeot _MASKED_BIT_ENABLE(GFX_TLB_INVALIDATE_EXPLICIT) | 1317f4e1c372SFrançois Tigeot _MASKED_BIT_ENABLE(GFX_REPLAY_MODE)); 1318e3adcf8fSFrançois Tigeot 1319*1487f786SFrançois Tigeot if (IS_GEN6(dev_priv)) { 1320e3adcf8fSFrançois Tigeot /* From the Sandybridge PRM, volume 1 part 3, page 24: 1321e3adcf8fSFrançois Tigeot * "If this bit is set, STCunit will have LRA as replacement 1322e3adcf8fSFrançois Tigeot * policy. [...] This bit must be reset. LRA replacement 1323e3adcf8fSFrançois Tigeot * policy is not supported." 1324e3adcf8fSFrançois Tigeot */ 1325e3adcf8fSFrançois Tigeot I915_WRITE(CACHE_MODE_0, 1326f4e1c372SFrançois Tigeot _MASKED_BIT_DISABLE(CM0_STC_EVICT_DISABLE_LRA_SNB)); 1327e3adcf8fSFrançois Tigeot } 1328e3adcf8fSFrançois Tigeot 1329*1487f786SFrançois Tigeot if (IS_GEN(dev_priv, 6, 7)) 1330f4e1c372SFrançois Tigeot I915_WRITE(INSTPM, _MASKED_BIT_ENABLE(INSTPM_FORCE_ORDERING)); 1331f4e1c372SFrançois Tigeot 1332*1487f786SFrançois Tigeot if (HAS_L3_DPF(dev_priv)) 1333*1487f786SFrançois Tigeot I915_WRITE_IMR(engine, ~GT_PARITY_ERROR(dev_priv)); 1334e3adcf8fSFrançois Tigeot 13358621f407SFrançois Tigeot return init_workarounds_ring(engine); 1336e3adcf8fSFrançois Tigeot } 1337e3adcf8fSFrançois Tigeot 13388621f407SFrançois Tigeot static void render_ring_cleanup(struct intel_engine_cs *engine) 1339e3adcf8fSFrançois Tigeot { 1340*1487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 134124edb884SFrançois Tigeot 134224edb884SFrançois Tigeot if (dev_priv->semaphore_obj) { 134324edb884SFrançois Tigeot i915_gem_object_ggtt_unpin(dev_priv->semaphore_obj); 134424edb884SFrançois Tigeot drm_gem_object_unreference(&dev_priv->semaphore_obj->base); 134524edb884SFrançois Tigeot dev_priv->semaphore_obj = NULL; 134624edb884SFrançois Tigeot } 1347b5c29a34SFrançois Tigeot 13488621f407SFrançois Tigeot intel_fini_pipe_control(engine); 1349e3adcf8fSFrançois Tigeot } 1350e3adcf8fSFrançois Tigeot 1351a05eeebfSFrançois Tigeot static int gen8_rcs_signal(struct drm_i915_gem_request *signaller_req, 135224edb884SFrançois Tigeot unsigned int num_dwords) 135324edb884SFrançois Tigeot { 135424edb884SFrançois Tigeot #define MBOX_UPDATE_DWORDS 8 13558621f407SFrançois Tigeot struct intel_engine_cs *signaller = signaller_req->engine; 1356*1487f786SFrançois Tigeot struct drm_i915_private *dev_priv = signaller_req->i915; 135724edb884SFrançois Tigeot struct intel_engine_cs *waiter; 13588621f407SFrançois Tigeot enum intel_engine_id id; 13598621f407SFrançois Tigeot int ret, num_rings; 136024edb884SFrançois Tigeot 1361*1487f786SFrançois Tigeot num_rings = hweight32(INTEL_INFO(dev_priv)->ring_mask); 136224edb884SFrançois Tigeot num_dwords += (num_rings-1) * MBOX_UPDATE_DWORDS; 136324edb884SFrançois Tigeot #undef MBOX_UPDATE_DWORDS 136424edb884SFrançois Tigeot 1365a05eeebfSFrançois Tigeot ret = intel_ring_begin(signaller_req, num_dwords); 136624edb884SFrançois Tigeot if (ret) 136724edb884SFrançois Tigeot return ret; 136824edb884SFrançois Tigeot 13698621f407SFrançois Tigeot for_each_engine_id(waiter, dev_priv, id) { 13702c9916cdSFrançois Tigeot u32 seqno; 13718621f407SFrançois Tigeot u64 gtt_offset = signaller->semaphore.signal_ggtt[id]; 137224edb884SFrançois Tigeot if (gtt_offset == MI_SEMAPHORE_SYNC_INVALID) 137324edb884SFrançois Tigeot continue; 137424edb884SFrançois Tigeot 1375a05eeebfSFrançois Tigeot seqno = i915_gem_request_get_seqno(signaller_req); 137624edb884SFrançois Tigeot intel_ring_emit(signaller, GFX_OP_PIPE_CONTROL(6)); 137724edb884SFrançois Tigeot intel_ring_emit(signaller, PIPE_CONTROL_GLOBAL_GTT_IVB | 137824edb884SFrançois Tigeot PIPE_CONTROL_QW_WRITE | 1379*1487f786SFrançois Tigeot PIPE_CONTROL_CS_STALL); 138024edb884SFrançois Tigeot intel_ring_emit(signaller, lower_32_bits(gtt_offset)); 138124edb884SFrançois Tigeot intel_ring_emit(signaller, upper_32_bits(gtt_offset)); 13822c9916cdSFrançois Tigeot intel_ring_emit(signaller, seqno); 138324edb884SFrançois Tigeot intel_ring_emit(signaller, 0); 138424edb884SFrançois Tigeot intel_ring_emit(signaller, MI_SEMAPHORE_SIGNAL | 13858621f407SFrançois Tigeot MI_SEMAPHORE_TARGET(waiter->hw_id)); 138624edb884SFrançois Tigeot intel_ring_emit(signaller, 0); 138724edb884SFrançois Tigeot } 138824edb884SFrançois Tigeot 138924edb884SFrançois Tigeot return 0; 139024edb884SFrançois Tigeot } 139124edb884SFrançois Tigeot 1392a05eeebfSFrançois Tigeot static int gen8_xcs_signal(struct drm_i915_gem_request *signaller_req, 139324edb884SFrançois Tigeot unsigned int num_dwords) 139424edb884SFrançois Tigeot { 139524edb884SFrançois Tigeot #define MBOX_UPDATE_DWORDS 6 13968621f407SFrançois Tigeot struct intel_engine_cs *signaller = signaller_req->engine; 1397*1487f786SFrançois Tigeot struct drm_i915_private *dev_priv = signaller_req->i915; 139824edb884SFrançois Tigeot struct intel_engine_cs *waiter; 13998621f407SFrançois Tigeot enum intel_engine_id id; 14008621f407SFrançois Tigeot int ret, num_rings; 140124edb884SFrançois Tigeot 1402*1487f786SFrançois Tigeot num_rings = hweight32(INTEL_INFO(dev_priv)->ring_mask); 140324edb884SFrançois Tigeot num_dwords += (num_rings-1) * MBOX_UPDATE_DWORDS; 140424edb884SFrançois Tigeot #undef MBOX_UPDATE_DWORDS 140524edb884SFrançois Tigeot 1406a05eeebfSFrançois Tigeot ret = intel_ring_begin(signaller_req, num_dwords); 140724edb884SFrançois Tigeot if (ret) 140824edb884SFrançois Tigeot return ret; 140924edb884SFrançois Tigeot 14108621f407SFrançois Tigeot for_each_engine_id(waiter, dev_priv, id) { 14112c9916cdSFrançois Tigeot u32 seqno; 14128621f407SFrançois Tigeot u64 gtt_offset = signaller->semaphore.signal_ggtt[id]; 141324edb884SFrançois Tigeot if (gtt_offset == MI_SEMAPHORE_SYNC_INVALID) 141424edb884SFrançois Tigeot continue; 141524edb884SFrançois Tigeot 1416a05eeebfSFrançois Tigeot seqno = i915_gem_request_get_seqno(signaller_req); 141724edb884SFrançois Tigeot intel_ring_emit(signaller, (MI_FLUSH_DW + 1) | 141824edb884SFrançois Tigeot MI_FLUSH_DW_OP_STOREDW); 141924edb884SFrançois Tigeot intel_ring_emit(signaller, lower_32_bits(gtt_offset) | 142024edb884SFrançois Tigeot MI_FLUSH_DW_USE_GTT); 142124edb884SFrançois Tigeot intel_ring_emit(signaller, upper_32_bits(gtt_offset)); 14222c9916cdSFrançois Tigeot intel_ring_emit(signaller, seqno); 142324edb884SFrançois Tigeot intel_ring_emit(signaller, MI_SEMAPHORE_SIGNAL | 14248621f407SFrançois Tigeot MI_SEMAPHORE_TARGET(waiter->hw_id)); 142524edb884SFrançois Tigeot intel_ring_emit(signaller, 0); 142624edb884SFrançois Tigeot } 142724edb884SFrançois Tigeot 142824edb884SFrançois Tigeot return 0; 142924edb884SFrançois Tigeot } 143024edb884SFrançois Tigeot 1431a05eeebfSFrançois Tigeot static int gen6_signal(struct drm_i915_gem_request *signaller_req, 1432ba55f2f5SFrançois Tigeot unsigned int num_dwords) 1433e3adcf8fSFrançois Tigeot { 14348621f407SFrançois Tigeot struct intel_engine_cs *signaller = signaller_req->engine; 1435*1487f786SFrançois Tigeot struct drm_i915_private *dev_priv = signaller_req->i915; 1436ba55f2f5SFrançois Tigeot struct intel_engine_cs *useless; 14378621f407SFrançois Tigeot enum intel_engine_id id; 14388621f407SFrançois Tigeot int ret, num_rings; 1439ba55f2f5SFrançois Tigeot 144024edb884SFrançois Tigeot #define MBOX_UPDATE_DWORDS 3 1441*1487f786SFrançois Tigeot num_rings = hweight32(INTEL_INFO(dev_priv)->ring_mask); 144224edb884SFrançois Tigeot num_dwords += round_up((num_rings-1) * MBOX_UPDATE_DWORDS, 2); 144324edb884SFrançois Tigeot #undef MBOX_UPDATE_DWORDS 1444ba55f2f5SFrançois Tigeot 1445a05eeebfSFrançois Tigeot ret = intel_ring_begin(signaller_req, num_dwords); 1446ba55f2f5SFrançois Tigeot if (ret) 1447ba55f2f5SFrançois Tigeot return ret; 1448ba55f2f5SFrançois Tigeot 14498621f407SFrançois Tigeot for_each_engine_id(useless, dev_priv, id) { 14508621f407SFrançois Tigeot i915_reg_t mbox_reg = signaller->semaphore.mbox.signal[id]; 1451aee94f86SFrançois Tigeot 1452aee94f86SFrançois Tigeot if (i915_mmio_reg_valid(mbox_reg)) { 1453a05eeebfSFrançois Tigeot u32 seqno = i915_gem_request_get_seqno(signaller_req); 1454aee94f86SFrançois Tigeot 1455ba55f2f5SFrançois Tigeot intel_ring_emit(signaller, MI_LOAD_REGISTER_IMM(1)); 1456aee94f86SFrançois Tigeot intel_ring_emit_reg(signaller, mbox_reg); 14572c9916cdSFrançois Tigeot intel_ring_emit(signaller, seqno); 1458ba55f2f5SFrançois Tigeot } 1459ba55f2f5SFrançois Tigeot } 1460ba55f2f5SFrançois Tigeot 146124edb884SFrançois Tigeot /* If num_dwords was rounded, make sure the tail pointer is correct */ 146224edb884SFrançois Tigeot if (num_rings % 2 == 0) 146324edb884SFrançois Tigeot intel_ring_emit(signaller, MI_NOOP); 146424edb884SFrançois Tigeot 1465ba55f2f5SFrançois Tigeot return 0; 1466e3adcf8fSFrançois Tigeot } 1467e3adcf8fSFrançois Tigeot 1468e3adcf8fSFrançois Tigeot /** 1469e3adcf8fSFrançois Tigeot * gen6_add_request - Update the semaphore mailbox registers 1470e3adcf8fSFrançois Tigeot * 1471a05eeebfSFrançois Tigeot * @request - request to write to the ring 1472e3adcf8fSFrançois Tigeot * 1473e3adcf8fSFrançois Tigeot * Update the mailbox registers in the *other* rings with the current seqno. 1474e3adcf8fSFrançois Tigeot * This acts like a signal in the canonical semaphore. 1475e3adcf8fSFrançois Tigeot */ 1476e3adcf8fSFrançois Tigeot static int 1477a05eeebfSFrançois Tigeot gen6_add_request(struct drm_i915_gem_request *req) 1478e3adcf8fSFrançois Tigeot { 14798621f407SFrançois Tigeot struct intel_engine_cs *engine = req->engine; 1480ba55f2f5SFrançois Tigeot int ret; 1481e3adcf8fSFrançois Tigeot 14828621f407SFrançois Tigeot if (engine->semaphore.signal) 14838621f407SFrançois Tigeot ret = engine->semaphore.signal(req, 4); 148424edb884SFrançois Tigeot else 1485a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 4); 148624edb884SFrançois Tigeot 14879edbd4a0SFrançois Tigeot if (ret) 14889edbd4a0SFrançois Tigeot return ret; 14899edbd4a0SFrançois Tigeot 14908621f407SFrançois Tigeot intel_ring_emit(engine, MI_STORE_DWORD_INDEX); 14918621f407SFrançois Tigeot intel_ring_emit(engine, 14928621f407SFrançois Tigeot I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT); 14938621f407SFrançois Tigeot intel_ring_emit(engine, i915_gem_request_get_seqno(req)); 14948621f407SFrançois Tigeot intel_ring_emit(engine, MI_USER_INTERRUPT); 14958621f407SFrançois Tigeot __intel_ring_advance(engine); 1496e3adcf8fSFrançois Tigeot 1497e3adcf8fSFrançois Tigeot return 0; 1498e3adcf8fSFrançois Tigeot } 1499e3adcf8fSFrançois Tigeot 1500*1487f786SFrançois Tigeot static int 1501*1487f786SFrançois Tigeot gen8_render_add_request(struct drm_i915_gem_request *req) 1502*1487f786SFrançois Tigeot { 1503*1487f786SFrançois Tigeot struct intel_engine_cs *engine = req->engine; 1504*1487f786SFrançois Tigeot int ret; 1505*1487f786SFrançois Tigeot 1506*1487f786SFrançois Tigeot if (engine->semaphore.signal) 1507*1487f786SFrançois Tigeot ret = engine->semaphore.signal(req, 8); 1508*1487f786SFrançois Tigeot else 1509*1487f786SFrançois Tigeot ret = intel_ring_begin(req, 8); 1510*1487f786SFrançois Tigeot if (ret) 1511*1487f786SFrançois Tigeot return ret; 1512*1487f786SFrançois Tigeot 1513*1487f786SFrançois Tigeot intel_ring_emit(engine, GFX_OP_PIPE_CONTROL(6)); 1514*1487f786SFrançois Tigeot intel_ring_emit(engine, (PIPE_CONTROL_GLOBAL_GTT_IVB | 1515*1487f786SFrançois Tigeot PIPE_CONTROL_CS_STALL | 1516*1487f786SFrançois Tigeot PIPE_CONTROL_QW_WRITE)); 1517*1487f786SFrançois Tigeot intel_ring_emit(engine, intel_hws_seqno_address(req->engine)); 1518*1487f786SFrançois Tigeot intel_ring_emit(engine, 0); 1519*1487f786SFrançois Tigeot intel_ring_emit(engine, i915_gem_request_get_seqno(req)); 1520*1487f786SFrançois Tigeot /* We're thrashing one dword of HWS. */ 1521*1487f786SFrançois Tigeot intel_ring_emit(engine, 0); 1522*1487f786SFrançois Tigeot intel_ring_emit(engine, MI_USER_INTERRUPT); 1523*1487f786SFrançois Tigeot intel_ring_emit(engine, MI_NOOP); 1524*1487f786SFrançois Tigeot __intel_ring_advance(engine); 1525*1487f786SFrançois Tigeot 1526*1487f786SFrançois Tigeot return 0; 1527*1487f786SFrançois Tigeot } 1528*1487f786SFrançois Tigeot 1529*1487f786SFrançois Tigeot static inline bool i915_gem_has_seqno_wrapped(struct drm_i915_private *dev_priv, 1530a2fdbec6SFrançois Tigeot u32 seqno) 1531a2fdbec6SFrançois Tigeot { 1532a2fdbec6SFrançois Tigeot return dev_priv->last_seqno < seqno; 1533a2fdbec6SFrançois Tigeot } 1534a2fdbec6SFrançois Tigeot 1535e3adcf8fSFrançois Tigeot /** 1536e3adcf8fSFrançois Tigeot * intel_ring_sync - sync the waiter to the signaller on seqno 1537e3adcf8fSFrançois Tigeot * 1538e3adcf8fSFrançois Tigeot * @waiter - ring that is waiting 1539e3adcf8fSFrançois Tigeot * @signaller - ring which has, or will signal 1540e3adcf8fSFrançois Tigeot * @seqno - seqno which the waiter will block on 1541e3adcf8fSFrançois Tigeot */ 154224edb884SFrançois Tigeot 154324edb884SFrançois Tigeot static int 1544a05eeebfSFrançois Tigeot gen8_ring_sync(struct drm_i915_gem_request *waiter_req, 154524edb884SFrançois Tigeot struct intel_engine_cs *signaller, 154624edb884SFrançois Tigeot u32 seqno) 154724edb884SFrançois Tigeot { 15488621f407SFrançois Tigeot struct intel_engine_cs *waiter = waiter_req->engine; 1549*1487f786SFrançois Tigeot struct drm_i915_private *dev_priv = waiter_req->i915; 1550*1487f786SFrançois Tigeot u64 offset = GEN8_WAIT_OFFSET(waiter, signaller->id); 1551*1487f786SFrançois Tigeot struct i915_hw_ppgtt *ppgtt; 155224edb884SFrançois Tigeot int ret; 155324edb884SFrançois Tigeot 1554a05eeebfSFrançois Tigeot ret = intel_ring_begin(waiter_req, 4); 155524edb884SFrançois Tigeot if (ret) 155624edb884SFrançois Tigeot return ret; 155724edb884SFrançois Tigeot 155824edb884SFrançois Tigeot intel_ring_emit(waiter, MI_SEMAPHORE_WAIT | 155924edb884SFrançois Tigeot MI_SEMAPHORE_GLOBAL_GTT | 156024edb884SFrançois Tigeot MI_SEMAPHORE_SAD_GTE_SDD); 156124edb884SFrançois Tigeot intel_ring_emit(waiter, seqno); 1562*1487f786SFrançois Tigeot intel_ring_emit(waiter, lower_32_bits(offset)); 1563*1487f786SFrançois Tigeot intel_ring_emit(waiter, upper_32_bits(offset)); 156424edb884SFrançois Tigeot intel_ring_advance(waiter); 1565*1487f786SFrançois Tigeot 1566*1487f786SFrançois Tigeot /* When the !RCS engines idle waiting upon a semaphore, they lose their 1567*1487f786SFrançois Tigeot * pagetables and we must reload them before executing the batch. 1568*1487f786SFrançois Tigeot * We do this on the i915_switch_context() following the wait and 1569*1487f786SFrançois Tigeot * before the dispatch. 1570*1487f786SFrançois Tigeot */ 1571*1487f786SFrançois Tigeot ppgtt = waiter_req->ctx->ppgtt; 1572*1487f786SFrançois Tigeot if (ppgtt && waiter_req->engine->id != RCS) 1573*1487f786SFrançois Tigeot ppgtt->pd_dirty_rings |= intel_engine_flag(waiter_req->engine); 157424edb884SFrançois Tigeot return 0; 157524edb884SFrançois Tigeot } 157624edb884SFrançois Tigeot 1577e3adcf8fSFrançois Tigeot static int 1578a05eeebfSFrançois Tigeot gen6_ring_sync(struct drm_i915_gem_request *waiter_req, 1579ba55f2f5SFrançois Tigeot struct intel_engine_cs *signaller, 1580e3adcf8fSFrançois Tigeot u32 seqno) 1581e3adcf8fSFrançois Tigeot { 15828621f407SFrançois Tigeot struct intel_engine_cs *waiter = waiter_req->engine; 1583e3adcf8fSFrançois Tigeot u32 dw1 = MI_SEMAPHORE_MBOX | 1584e3adcf8fSFrançois Tigeot MI_SEMAPHORE_COMPARE | 1585e3adcf8fSFrançois Tigeot MI_SEMAPHORE_REGISTER; 1586ba55f2f5SFrançois Tigeot u32 wait_mbox = signaller->semaphore.mbox.wait[waiter->id]; 1587ba55f2f5SFrançois Tigeot int ret; 1588e3adcf8fSFrançois Tigeot 1589686a02f1SFrançois Tigeot /* Throughout all of the GEM code, seqno passed implies our current 1590686a02f1SFrançois Tigeot * seqno is >= the last seqno executed. However for hardware the 1591686a02f1SFrançois Tigeot * comparison is strictly greater than. 1592686a02f1SFrançois Tigeot */ 1593686a02f1SFrançois Tigeot seqno -= 1; 1594686a02f1SFrançois Tigeot 1595ba55f2f5SFrançois Tigeot WARN_ON(wait_mbox == MI_SEMAPHORE_SYNC_INVALID); 1596686a02f1SFrançois Tigeot 1597a05eeebfSFrançois Tigeot ret = intel_ring_begin(waiter_req, 4); 1598e3adcf8fSFrançois Tigeot if (ret) 1599e3adcf8fSFrançois Tigeot return ret; 1600e3adcf8fSFrançois Tigeot 1601a2fdbec6SFrançois Tigeot /* If seqno wrap happened, omit the wait with no-ops */ 1602*1487f786SFrançois Tigeot if (likely(!i915_gem_has_seqno_wrapped(waiter_req->i915, seqno))) { 1603ba55f2f5SFrançois Tigeot intel_ring_emit(waiter, dw1 | wait_mbox); 1604e3adcf8fSFrançois Tigeot intel_ring_emit(waiter, seqno); 1605e3adcf8fSFrançois Tigeot intel_ring_emit(waiter, 0); 1606e3adcf8fSFrançois Tigeot intel_ring_emit(waiter, MI_NOOP); 1607a2fdbec6SFrançois Tigeot } else { 1608a2fdbec6SFrançois Tigeot intel_ring_emit(waiter, MI_NOOP); 1609a2fdbec6SFrançois Tigeot intel_ring_emit(waiter, MI_NOOP); 1610a2fdbec6SFrançois Tigeot intel_ring_emit(waiter, MI_NOOP); 1611a2fdbec6SFrançois Tigeot intel_ring_emit(waiter, MI_NOOP); 1612a2fdbec6SFrançois Tigeot } 1613e3adcf8fSFrançois Tigeot intel_ring_advance(waiter); 1614e3adcf8fSFrançois Tigeot 1615e3adcf8fSFrançois Tigeot return 0; 1616e3adcf8fSFrançois Tigeot } 1617e3adcf8fSFrançois Tigeot 1618e3adcf8fSFrançois Tigeot #define PIPE_CONTROL_FLUSH(ring__, addr__) \ 1619e3adcf8fSFrançois Tigeot do { \ 1620e3adcf8fSFrançois Tigeot intel_ring_emit(ring__, GFX_OP_PIPE_CONTROL(4) | PIPE_CONTROL_QW_WRITE | \ 1621e3adcf8fSFrançois Tigeot PIPE_CONTROL_DEPTH_STALL); \ 1622e3adcf8fSFrançois Tigeot intel_ring_emit(ring__, (addr__) | PIPE_CONTROL_GLOBAL_GTT); \ 1623e3adcf8fSFrançois Tigeot intel_ring_emit(ring__, 0); \ 1624e3adcf8fSFrançois Tigeot intel_ring_emit(ring__, 0); \ 1625e3adcf8fSFrançois Tigeot } while (0) 1626e3adcf8fSFrançois Tigeot 1627e3adcf8fSFrançois Tigeot static int 1628a05eeebfSFrançois Tigeot pc_render_add_request(struct drm_i915_gem_request *req) 1629e3adcf8fSFrançois Tigeot { 16308621f407SFrançois Tigeot struct intel_engine_cs *engine = req->engine; 16318621f407SFrançois Tigeot u32 scratch_addr = engine->scratch.gtt_offset + 2 * CACHELINE_BYTES; 1632e3adcf8fSFrançois Tigeot int ret; 1633e3adcf8fSFrançois Tigeot 1634e3adcf8fSFrançois Tigeot /* For Ironlake, MI_USER_INTERRUPT was deprecated and apparently 1635e3adcf8fSFrançois Tigeot * incoherent with writes to memory, i.e. completely fubar, 1636e3adcf8fSFrançois Tigeot * so we need to use PIPE_NOTIFY instead. 1637e3adcf8fSFrançois Tigeot * 1638e3adcf8fSFrançois Tigeot * However, we also need to workaround the qword write 1639e3adcf8fSFrançois Tigeot * incoherence by flushing the 6 PIPE_NOTIFY buffers out to 1640e3adcf8fSFrançois Tigeot * memory before requesting an interrupt. 1641e3adcf8fSFrançois Tigeot */ 1642a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 32); 1643e3adcf8fSFrançois Tigeot if (ret) 1644e3adcf8fSFrançois Tigeot return ret; 1645e3adcf8fSFrançois Tigeot 16468621f407SFrançois Tigeot intel_ring_emit(engine, 16478621f407SFrançois Tigeot GFX_OP_PIPE_CONTROL(4) | PIPE_CONTROL_QW_WRITE | 1648e3adcf8fSFrançois Tigeot PIPE_CONTROL_WRITE_FLUSH | 1649e3adcf8fSFrançois Tigeot PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE); 16508621f407SFrançois Tigeot intel_ring_emit(engine, 16518621f407SFrançois Tigeot engine->scratch.gtt_offset | PIPE_CONTROL_GLOBAL_GTT); 16528621f407SFrançois Tigeot intel_ring_emit(engine, i915_gem_request_get_seqno(req)); 16538621f407SFrançois Tigeot intel_ring_emit(engine, 0); 16548621f407SFrançois Tigeot PIPE_CONTROL_FLUSH(engine, scratch_addr); 1655ba55f2f5SFrançois Tigeot scratch_addr += 2 * CACHELINE_BYTES; /* write to separate cachelines */ 16568621f407SFrançois Tigeot PIPE_CONTROL_FLUSH(engine, scratch_addr); 1657ba55f2f5SFrançois Tigeot scratch_addr += 2 * CACHELINE_BYTES; 16588621f407SFrançois Tigeot PIPE_CONTROL_FLUSH(engine, scratch_addr); 1659ba55f2f5SFrançois Tigeot scratch_addr += 2 * CACHELINE_BYTES; 16608621f407SFrançois Tigeot PIPE_CONTROL_FLUSH(engine, scratch_addr); 1661ba55f2f5SFrançois Tigeot scratch_addr += 2 * CACHELINE_BYTES; 16628621f407SFrançois Tigeot PIPE_CONTROL_FLUSH(engine, scratch_addr); 1663ba55f2f5SFrançois Tigeot scratch_addr += 2 * CACHELINE_BYTES; 16648621f407SFrançois Tigeot PIPE_CONTROL_FLUSH(engine, scratch_addr); 1665b5c29a34SFrançois Tigeot 16668621f407SFrançois Tigeot intel_ring_emit(engine, 16678621f407SFrançois Tigeot GFX_OP_PIPE_CONTROL(4) | PIPE_CONTROL_QW_WRITE | 1668e3adcf8fSFrançois Tigeot PIPE_CONTROL_WRITE_FLUSH | 1669e3adcf8fSFrançois Tigeot PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE | 1670e3adcf8fSFrançois Tigeot PIPE_CONTROL_NOTIFY); 16718621f407SFrançois Tigeot intel_ring_emit(engine, 16728621f407SFrançois Tigeot engine->scratch.gtt_offset | PIPE_CONTROL_GLOBAL_GTT); 16738621f407SFrançois Tigeot intel_ring_emit(engine, i915_gem_request_get_seqno(req)); 16748621f407SFrançois Tigeot intel_ring_emit(engine, 0); 16758621f407SFrançois Tigeot __intel_ring_advance(engine); 1676e3adcf8fSFrançois Tigeot 1677e3adcf8fSFrançois Tigeot return 0; 1678e3adcf8fSFrançois Tigeot } 1679e3adcf8fSFrançois Tigeot 16808621f407SFrançois Tigeot static void 16818621f407SFrançois Tigeot gen6_seqno_barrier(struct intel_engine_cs *engine) 1682e3adcf8fSFrançois Tigeot { 1683*1487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 16848621f407SFrançois Tigeot 1685e3adcf8fSFrançois Tigeot /* Workaround to force correct ordering between irq and seqno writes on 1686e3adcf8fSFrançois Tigeot * ivb (and maybe also on snb) by reading from a CS register (like 16878621f407SFrançois Tigeot * ACTHD) before reading the status page. 16888621f407SFrançois Tigeot * 16898621f407SFrançois Tigeot * Note that this effectively stalls the read by the time it takes to 16908621f407SFrançois Tigeot * do a memory transaction, which more or less ensures that the write 16918621f407SFrançois Tigeot * from the GPU has sufficient time to invalidate the CPU cacheline. 16928621f407SFrançois Tigeot * Alternatively we could delay the interrupt from the CS ring to give 16938621f407SFrançois Tigeot * the write time to land, but that would incur a delay after every 16948621f407SFrançois Tigeot * batch i.e. much more frequent than a delay when waiting for the 16958621f407SFrançois Tigeot * interrupt (with the same net latency). 16968621f407SFrançois Tigeot * 16978621f407SFrançois Tigeot * Also note that to prevent whole machine hangs on gen7, we have to 16988621f407SFrançois Tigeot * take the spinlock to guard against concurrent cacheline access. 16998621f407SFrançois Tigeot */ 17008621f407SFrançois Tigeot spin_lock_irq(&dev_priv->uncore.lock); 17018621f407SFrançois Tigeot POSTING_READ_FW(RING_ACTHD(engine->mmio_base)); 17028621f407SFrançois Tigeot spin_unlock_irq(&dev_priv->uncore.lock); 1703e3adcf8fSFrançois Tigeot } 1704e3adcf8fSFrançois Tigeot 1705b030f26bSFrançois Tigeot static u32 17068621f407SFrançois Tigeot ring_get_seqno(struct intel_engine_cs *engine) 1707e3adcf8fSFrançois Tigeot { 17088621f407SFrançois Tigeot return intel_read_status_page(engine, I915_GEM_HWS_INDEX); 1709e3adcf8fSFrançois Tigeot } 1710e3adcf8fSFrançois Tigeot 1711a2fdbec6SFrançois Tigeot static void 17128621f407SFrançois Tigeot ring_set_seqno(struct intel_engine_cs *engine, u32 seqno) 1713a2fdbec6SFrançois Tigeot { 17148621f407SFrançois Tigeot intel_write_status_page(engine, I915_GEM_HWS_INDEX, seqno); 1715a2fdbec6SFrançois Tigeot } 1716a2fdbec6SFrançois Tigeot 1717b030f26bSFrançois Tigeot static u32 17188621f407SFrançois Tigeot pc_render_get_seqno(struct intel_engine_cs *engine) 1719e3adcf8fSFrançois Tigeot { 17208621f407SFrançois Tigeot return engine->scratch.cpu_page[0]; 1721e3adcf8fSFrançois Tigeot } 1722e3adcf8fSFrançois Tigeot 1723a2fdbec6SFrançois Tigeot static void 17248621f407SFrançois Tigeot pc_render_set_seqno(struct intel_engine_cs *engine, u32 seqno) 1725a2fdbec6SFrançois Tigeot { 17268621f407SFrançois Tigeot engine->scratch.cpu_page[0] = seqno; 1727a2fdbec6SFrançois Tigeot } 1728a2fdbec6SFrançois Tigeot 1729e3adcf8fSFrançois Tigeot static bool 17308621f407SFrançois Tigeot gen5_ring_get_irq(struct intel_engine_cs *engine) 1731e3adcf8fSFrançois Tigeot { 1732*1487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 17335e269720SFrançois Tigeot unsigned long flags; 1734e3adcf8fSFrançois Tigeot 17352c9916cdSFrançois Tigeot if (WARN_ON(!intel_irqs_enabled(dev_priv))) 1736e3adcf8fSFrançois Tigeot return false; 1737e3adcf8fSFrançois Tigeot 17385e269720SFrançois Tigeot spin_lock_irqsave(&dev_priv->irq_lock, flags); 17398621f407SFrançois Tigeot if (engine->irq_refcount++ == 0) 17408621f407SFrançois Tigeot gen5_enable_gt_irq(dev_priv, engine->irq_enable_mask); 17415e269720SFrançois Tigeot spin_unlock_irqrestore(&dev_priv->irq_lock, flags); 1742e3adcf8fSFrançois Tigeot 1743e3adcf8fSFrançois Tigeot return true; 1744e3adcf8fSFrançois Tigeot } 1745e3adcf8fSFrançois Tigeot 1746e3adcf8fSFrançois Tigeot static void 17478621f407SFrançois Tigeot gen5_ring_put_irq(struct intel_engine_cs *engine) 1748e3adcf8fSFrançois Tigeot { 1749*1487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 17505e269720SFrançois Tigeot unsigned long flags; 1751e3adcf8fSFrançois Tigeot 17525e269720SFrançois Tigeot spin_lock_irqsave(&dev_priv->irq_lock, flags); 17538621f407SFrançois Tigeot if (--engine->irq_refcount == 0) 17548621f407SFrançois Tigeot gen5_disable_gt_irq(dev_priv, engine->irq_enable_mask); 17555e269720SFrançois Tigeot spin_unlock_irqrestore(&dev_priv->irq_lock, flags); 1756686a02f1SFrançois Tigeot } 1757686a02f1SFrançois Tigeot 1758686a02f1SFrançois Tigeot static bool 17598621f407SFrançois Tigeot i9xx_ring_get_irq(struct intel_engine_cs *engine) 1760686a02f1SFrançois Tigeot { 1761*1487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 17625e269720SFrançois Tigeot unsigned long flags; 1763686a02f1SFrançois Tigeot 17642c9916cdSFrançois Tigeot if (!intel_irqs_enabled(dev_priv)) 1765686a02f1SFrançois Tigeot return false; 1766686a02f1SFrançois Tigeot 17675e269720SFrançois Tigeot spin_lock_irqsave(&dev_priv->irq_lock, flags); 17688621f407SFrançois Tigeot if (engine->irq_refcount++ == 0) { 17698621f407SFrançois Tigeot dev_priv->irq_mask &= ~engine->irq_enable_mask; 1770686a02f1SFrançois Tigeot I915_WRITE(IMR, dev_priv->irq_mask); 1771686a02f1SFrançois Tigeot POSTING_READ(IMR); 1772686a02f1SFrançois Tigeot } 17735e269720SFrançois Tigeot spin_unlock_irqrestore(&dev_priv->irq_lock, flags); 1774686a02f1SFrançois Tigeot 1775686a02f1SFrançois Tigeot return true; 1776686a02f1SFrançois Tigeot } 1777686a02f1SFrançois Tigeot 1778686a02f1SFrançois Tigeot static void 17798621f407SFrançois Tigeot i9xx_ring_put_irq(struct intel_engine_cs *engine) 1780686a02f1SFrançois Tigeot { 1781*1487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 17825e269720SFrançois Tigeot unsigned long flags; 1783686a02f1SFrançois Tigeot 17845e269720SFrançois Tigeot spin_lock_irqsave(&dev_priv->irq_lock, flags); 17858621f407SFrançois Tigeot if (--engine->irq_refcount == 0) { 17868621f407SFrançois Tigeot dev_priv->irq_mask |= engine->irq_enable_mask; 1787686a02f1SFrançois Tigeot I915_WRITE(IMR, dev_priv->irq_mask); 1788686a02f1SFrançois Tigeot POSTING_READ(IMR); 1789686a02f1SFrançois Tigeot } 17905e269720SFrançois Tigeot spin_unlock_irqrestore(&dev_priv->irq_lock, flags); 1791686a02f1SFrançois Tigeot } 1792686a02f1SFrançois Tigeot 1793686a02f1SFrançois Tigeot static bool 17948621f407SFrançois Tigeot i8xx_ring_get_irq(struct intel_engine_cs *engine) 1795686a02f1SFrançois Tigeot { 1796*1487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 17975e269720SFrançois Tigeot unsigned long flags; 1798686a02f1SFrançois Tigeot 17992c9916cdSFrançois Tigeot if (!intel_irqs_enabled(dev_priv)) 1800686a02f1SFrançois Tigeot return false; 1801686a02f1SFrançois Tigeot 18025e269720SFrançois Tigeot spin_lock_irqsave(&dev_priv->irq_lock, flags); 18038621f407SFrançois Tigeot if (engine->irq_refcount++ == 0) { 18048621f407SFrançois Tigeot dev_priv->irq_mask &= ~engine->irq_enable_mask; 1805686a02f1SFrançois Tigeot I915_WRITE16(IMR, dev_priv->irq_mask); 1806686a02f1SFrançois Tigeot POSTING_READ16(IMR); 1807686a02f1SFrançois Tigeot } 18085e269720SFrançois Tigeot spin_unlock_irqrestore(&dev_priv->irq_lock, flags); 1809686a02f1SFrançois Tigeot 1810686a02f1SFrançois Tigeot return true; 1811686a02f1SFrançois Tigeot } 1812686a02f1SFrançois Tigeot 1813686a02f1SFrançois Tigeot static void 18148621f407SFrançois Tigeot i8xx_ring_put_irq(struct intel_engine_cs *engine) 1815686a02f1SFrançois Tigeot { 1816*1487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 18175e269720SFrançois Tigeot unsigned long flags; 1818686a02f1SFrançois Tigeot 18195e269720SFrançois Tigeot spin_lock_irqsave(&dev_priv->irq_lock, flags); 18208621f407SFrançois Tigeot if (--engine->irq_refcount == 0) { 18218621f407SFrançois Tigeot dev_priv->irq_mask |= engine->irq_enable_mask; 1822686a02f1SFrançois Tigeot I915_WRITE16(IMR, dev_priv->irq_mask); 1823686a02f1SFrançois Tigeot POSTING_READ16(IMR); 1824e3adcf8fSFrançois Tigeot } 18255e269720SFrançois Tigeot spin_unlock_irqrestore(&dev_priv->irq_lock, flags); 1826e3adcf8fSFrançois Tigeot } 1827e3adcf8fSFrançois Tigeot 1828e3adcf8fSFrançois Tigeot static int 1829a05eeebfSFrançois Tigeot bsd_ring_flush(struct drm_i915_gem_request *req, 1830b5c29a34SFrançois Tigeot u32 invalidate_domains, 1831b5c29a34SFrançois Tigeot u32 flush_domains) 1832e3adcf8fSFrançois Tigeot { 18338621f407SFrançois Tigeot struct intel_engine_cs *engine = req->engine; 1834e3adcf8fSFrançois Tigeot int ret; 1835e3adcf8fSFrançois Tigeot 1836a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 2); 1837e3adcf8fSFrançois Tigeot if (ret) 1838e3adcf8fSFrançois Tigeot return ret; 1839e3adcf8fSFrançois Tigeot 18408621f407SFrançois Tigeot intel_ring_emit(engine, MI_FLUSH); 18418621f407SFrançois Tigeot intel_ring_emit(engine, MI_NOOP); 18428621f407SFrançois Tigeot intel_ring_advance(engine); 1843e3adcf8fSFrançois Tigeot return 0; 1844e3adcf8fSFrançois Tigeot } 1845e3adcf8fSFrançois Tigeot 1846e3adcf8fSFrançois Tigeot static int 1847a05eeebfSFrançois Tigeot i9xx_add_request(struct drm_i915_gem_request *req) 1848e3adcf8fSFrançois Tigeot { 18498621f407SFrançois Tigeot struct intel_engine_cs *engine = req->engine; 1850e3adcf8fSFrançois Tigeot int ret; 1851e3adcf8fSFrançois Tigeot 1852a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 4); 1853e3adcf8fSFrançois Tigeot if (ret) 1854e3adcf8fSFrançois Tigeot return ret; 1855e3adcf8fSFrançois Tigeot 18568621f407SFrançois Tigeot intel_ring_emit(engine, MI_STORE_DWORD_INDEX); 18578621f407SFrançois Tigeot intel_ring_emit(engine, 18588621f407SFrançois Tigeot I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT); 18598621f407SFrançois Tigeot intel_ring_emit(engine, i915_gem_request_get_seqno(req)); 18608621f407SFrançois Tigeot intel_ring_emit(engine, MI_USER_INTERRUPT); 18618621f407SFrançois Tigeot __intel_ring_advance(engine); 1862e3adcf8fSFrançois Tigeot 1863e3adcf8fSFrançois Tigeot return 0; 1864e3adcf8fSFrançois Tigeot } 1865e3adcf8fSFrançois Tigeot 1866e3adcf8fSFrançois Tigeot static bool 18678621f407SFrançois Tigeot gen6_ring_get_irq(struct intel_engine_cs *engine) 1868e3adcf8fSFrançois Tigeot { 1869*1487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 18705e269720SFrançois Tigeot unsigned long flags; 1871e3adcf8fSFrançois Tigeot 18722c9916cdSFrançois Tigeot if (WARN_ON(!intel_irqs_enabled(dev_priv))) 1873e3adcf8fSFrançois Tigeot return false; 1874e3adcf8fSFrançois Tigeot 18755e269720SFrançois Tigeot spin_lock_irqsave(&dev_priv->irq_lock, flags); 18768621f407SFrançois Tigeot if (engine->irq_refcount++ == 0) { 1877*1487f786SFrançois Tigeot if (HAS_L3_DPF(dev_priv) && engine->id == RCS) 18788621f407SFrançois Tigeot I915_WRITE_IMR(engine, 18798621f407SFrançois Tigeot ~(engine->irq_enable_mask | 1880*1487f786SFrançois Tigeot GT_PARITY_ERROR(dev_priv))); 1881686a02f1SFrançois Tigeot else 18828621f407SFrançois Tigeot I915_WRITE_IMR(engine, ~engine->irq_enable_mask); 18838621f407SFrançois Tigeot gen5_enable_gt_irq(dev_priv, engine->irq_enable_mask); 1884e3adcf8fSFrançois Tigeot } 18855e269720SFrançois Tigeot spin_unlock_irqrestore(&dev_priv->irq_lock, flags); 1886e3adcf8fSFrançois Tigeot 1887e3adcf8fSFrançois Tigeot return true; 1888e3adcf8fSFrançois Tigeot } 1889e3adcf8fSFrançois Tigeot 1890e3adcf8fSFrançois Tigeot static void 18918621f407SFrançois Tigeot gen6_ring_put_irq(struct intel_engine_cs *engine) 1892e3adcf8fSFrançois Tigeot { 1893*1487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 18945e269720SFrançois Tigeot unsigned long flags; 1895e3adcf8fSFrançois Tigeot 18965e269720SFrançois Tigeot spin_lock_irqsave(&dev_priv->irq_lock, flags); 18978621f407SFrançois Tigeot if (--engine->irq_refcount == 0) { 1898*1487f786SFrançois Tigeot if (HAS_L3_DPF(dev_priv) && engine->id == RCS) 1899*1487f786SFrançois Tigeot I915_WRITE_IMR(engine, ~GT_PARITY_ERROR(dev_priv)); 1900686a02f1SFrançois Tigeot else 19018621f407SFrançois Tigeot I915_WRITE_IMR(engine, ~0); 19028621f407SFrançois Tigeot gen5_disable_gt_irq(dev_priv, engine->irq_enable_mask); 1903e3adcf8fSFrançois Tigeot } 19045e269720SFrançois Tigeot spin_unlock_irqrestore(&dev_priv->irq_lock, flags); 1905e3adcf8fSFrançois Tigeot } 1906e3adcf8fSFrançois Tigeot 19075d0b1887SFrançois Tigeot static bool 19088621f407SFrançois Tigeot hsw_vebox_get_irq(struct intel_engine_cs *engine) 19095d0b1887SFrançois Tigeot { 1910*1487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 19115e269720SFrançois Tigeot unsigned long flags; 19125d0b1887SFrançois Tigeot 19132c9916cdSFrançois Tigeot if (WARN_ON(!intel_irqs_enabled(dev_priv))) 19145d0b1887SFrançois Tigeot return false; 19155d0b1887SFrançois Tigeot 19165e269720SFrançois Tigeot spin_lock_irqsave(&dev_priv->irq_lock, flags); 19178621f407SFrançois Tigeot if (engine->irq_refcount++ == 0) { 19188621f407SFrançois Tigeot I915_WRITE_IMR(engine, ~engine->irq_enable_mask); 19198621f407SFrançois Tigeot gen6_enable_pm_irq(dev_priv, engine->irq_enable_mask); 19205d0b1887SFrançois Tigeot } 19215e269720SFrançois Tigeot spin_unlock_irqrestore(&dev_priv->irq_lock, flags); 19225d0b1887SFrançois Tigeot 19235d0b1887SFrançois Tigeot return true; 19245d0b1887SFrançois Tigeot } 19255d0b1887SFrançois Tigeot 19265d0b1887SFrançois Tigeot static void 19278621f407SFrançois Tigeot hsw_vebox_put_irq(struct intel_engine_cs *engine) 19285d0b1887SFrançois Tigeot { 1929*1487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 19305e269720SFrançois Tigeot unsigned long flags; 19315d0b1887SFrançois Tigeot 19325e269720SFrançois Tigeot spin_lock_irqsave(&dev_priv->irq_lock, flags); 19338621f407SFrançois Tigeot if (--engine->irq_refcount == 0) { 19348621f407SFrançois Tigeot I915_WRITE_IMR(engine, ~0); 19358621f407SFrançois Tigeot gen6_disable_pm_irq(dev_priv, engine->irq_enable_mask); 19365d0b1887SFrançois Tigeot } 19375e269720SFrançois Tigeot spin_unlock_irqrestore(&dev_priv->irq_lock, flags); 19389edbd4a0SFrançois Tigeot } 19399edbd4a0SFrançois Tigeot 19409edbd4a0SFrançois Tigeot static bool 19418621f407SFrançois Tigeot gen8_ring_get_irq(struct intel_engine_cs *engine) 19429edbd4a0SFrançois Tigeot { 1943*1487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 19445e269720SFrançois Tigeot unsigned long flags; 19459edbd4a0SFrançois Tigeot 19462c9916cdSFrançois Tigeot if (WARN_ON(!intel_irqs_enabled(dev_priv))) 19479edbd4a0SFrançois Tigeot return false; 19489edbd4a0SFrançois Tigeot 19495e269720SFrançois Tigeot spin_lock_irqsave(&dev_priv->irq_lock, flags); 19508621f407SFrançois Tigeot if (engine->irq_refcount++ == 0) { 1951*1487f786SFrançois Tigeot if (HAS_L3_DPF(dev_priv) && engine->id == RCS) { 19528621f407SFrançois Tigeot I915_WRITE_IMR(engine, 19538621f407SFrançois Tigeot ~(engine->irq_enable_mask | 19549edbd4a0SFrançois Tigeot GT_RENDER_L3_PARITY_ERROR_INTERRUPT)); 19559edbd4a0SFrançois Tigeot } else { 19568621f407SFrançois Tigeot I915_WRITE_IMR(engine, ~engine->irq_enable_mask); 19579edbd4a0SFrançois Tigeot } 19588621f407SFrançois Tigeot POSTING_READ(RING_IMR(engine->mmio_base)); 19599edbd4a0SFrançois Tigeot } 19605e269720SFrançois Tigeot spin_unlock_irqrestore(&dev_priv->irq_lock, flags); 19619edbd4a0SFrançois Tigeot 19629edbd4a0SFrançois Tigeot return true; 19639edbd4a0SFrançois Tigeot } 19649edbd4a0SFrançois Tigeot 19659edbd4a0SFrançois Tigeot static void 19668621f407SFrançois Tigeot gen8_ring_put_irq(struct intel_engine_cs *engine) 19679edbd4a0SFrançois Tigeot { 1968*1487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 19695e269720SFrançois Tigeot unsigned long flags; 19709edbd4a0SFrançois Tigeot 19715e269720SFrançois Tigeot spin_lock_irqsave(&dev_priv->irq_lock, flags); 19728621f407SFrançois Tigeot if (--engine->irq_refcount == 0) { 1973*1487f786SFrançois Tigeot if (HAS_L3_DPF(dev_priv) && engine->id == RCS) { 19748621f407SFrançois Tigeot I915_WRITE_IMR(engine, 19759edbd4a0SFrançois Tigeot ~GT_RENDER_L3_PARITY_ERROR_INTERRUPT); 19769edbd4a0SFrançois Tigeot } else { 19778621f407SFrançois Tigeot I915_WRITE_IMR(engine, ~0); 19789edbd4a0SFrançois Tigeot } 19798621f407SFrançois Tigeot POSTING_READ(RING_IMR(engine->mmio_base)); 19809edbd4a0SFrançois Tigeot } 19815e269720SFrançois Tigeot spin_unlock_irqrestore(&dev_priv->irq_lock, flags); 19825d0b1887SFrançois Tigeot } 19835d0b1887SFrançois Tigeot 1984e3adcf8fSFrançois Tigeot static int 1985a05eeebfSFrançois Tigeot i965_dispatch_execbuffer(struct drm_i915_gem_request *req, 1986ba55f2f5SFrançois Tigeot u64 offset, u32 length, 1987477eb7f9SFrançois Tigeot unsigned dispatch_flags) 1988e3adcf8fSFrançois Tigeot { 19898621f407SFrançois Tigeot struct intel_engine_cs *engine = req->engine; 1990e3adcf8fSFrançois Tigeot int ret; 1991e3adcf8fSFrançois Tigeot 1992a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 2); 1993e3adcf8fSFrançois Tigeot if (ret) 1994e3adcf8fSFrançois Tigeot return ret; 1995e3adcf8fSFrançois Tigeot 19968621f407SFrançois Tigeot intel_ring_emit(engine, 1997686a02f1SFrançois Tigeot MI_BATCH_BUFFER_START | 1998b5c29a34SFrançois Tigeot MI_BATCH_GTT | 1999477eb7f9SFrançois Tigeot (dispatch_flags & I915_DISPATCH_SECURE ? 2000477eb7f9SFrançois Tigeot 0 : MI_BATCH_NON_SECURE_I965)); 20018621f407SFrançois Tigeot intel_ring_emit(engine, offset); 20028621f407SFrançois Tigeot intel_ring_advance(engine); 2003e3adcf8fSFrançois Tigeot 2004e3adcf8fSFrançois Tigeot return 0; 2005e3adcf8fSFrançois Tigeot } 2006e3adcf8fSFrançois Tigeot 2007b5c29a34SFrançois Tigeot /* Just userspace ABI convention to limit the wa batch bo to a resonable size */ 2008b5c29a34SFrançois Tigeot #define I830_BATCH_LIMIT (256*1024) 200924edb884SFrançois Tigeot #define I830_TLB_ENTRIES (2) 201024edb884SFrançois Tigeot #define I830_WA_SIZE max(I830_TLB_ENTRIES*4096, I830_BATCH_LIMIT) 2011e3adcf8fSFrançois Tigeot static int 2012a05eeebfSFrançois Tigeot i830_dispatch_execbuffer(struct drm_i915_gem_request *req, 2013ba55f2f5SFrançois Tigeot u64 offset, u32 len, 2014477eb7f9SFrançois Tigeot unsigned dispatch_flags) 2015e3adcf8fSFrançois Tigeot { 20168621f407SFrançois Tigeot struct intel_engine_cs *engine = req->engine; 20178621f407SFrançois Tigeot u32 cs_offset = engine->scratch.gtt_offset; 2018e3adcf8fSFrançois Tigeot int ret; 2019e3adcf8fSFrançois Tigeot 2020a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 6); 202124edb884SFrançois Tigeot if (ret) 202224edb884SFrançois Tigeot return ret; 202324edb884SFrançois Tigeot 202424edb884SFrançois Tigeot /* Evict the invalid PTE TLBs */ 20258621f407SFrançois Tigeot intel_ring_emit(engine, COLOR_BLT_CMD | BLT_WRITE_RGBA); 20268621f407SFrançois Tigeot intel_ring_emit(engine, BLT_DEPTH_32 | BLT_ROP_COLOR_COPY | 4096); 20278621f407SFrançois Tigeot intel_ring_emit(engine, I830_TLB_ENTRIES << 16 | 4); /* load each page */ 20288621f407SFrançois Tigeot intel_ring_emit(engine, cs_offset); 20298621f407SFrançois Tigeot intel_ring_emit(engine, 0xdeadbeef); 20308621f407SFrançois Tigeot intel_ring_emit(engine, MI_NOOP); 20318621f407SFrançois Tigeot intel_ring_advance(engine); 203224edb884SFrançois Tigeot 2033477eb7f9SFrançois Tigeot if ((dispatch_flags & I915_DISPATCH_PINNED) == 0) { 203424edb884SFrançois Tigeot if (len > I830_BATCH_LIMIT) 203524edb884SFrançois Tigeot return -ENOSPC; 203624edb884SFrançois Tigeot 2037a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 6 + 2); 203824edb884SFrançois Tigeot if (ret) 203924edb884SFrançois Tigeot return ret; 204024edb884SFrançois Tigeot 204124edb884SFrançois Tigeot /* Blit the batch (which has now all relocs applied) to the 204224edb884SFrançois Tigeot * stable batch scratch bo area (so that the CS never 204324edb884SFrançois Tigeot * stumbles over its tlb invalidation bug) ... 204424edb884SFrançois Tigeot */ 20458621f407SFrançois Tigeot intel_ring_emit(engine, SRC_COPY_BLT_CMD | BLT_WRITE_RGBA); 20468621f407SFrançois Tigeot intel_ring_emit(engine, 20478621f407SFrançois Tigeot BLT_DEPTH_32 | BLT_ROP_SRC_COPY | 4096); 20488621f407SFrançois Tigeot intel_ring_emit(engine, DIV_ROUND_UP(len, 4096) << 16 | 4096); 20498621f407SFrançois Tigeot intel_ring_emit(engine, cs_offset); 20508621f407SFrançois Tigeot intel_ring_emit(engine, 4096); 20518621f407SFrançois Tigeot intel_ring_emit(engine, offset); 205224edb884SFrançois Tigeot 20538621f407SFrançois Tigeot intel_ring_emit(engine, MI_FLUSH); 20548621f407SFrançois Tigeot intel_ring_emit(engine, MI_NOOP); 20558621f407SFrançois Tigeot intel_ring_advance(engine); 205624edb884SFrançois Tigeot 205724edb884SFrançois Tigeot /* ... and execute it. */ 205824edb884SFrançois Tigeot offset = cs_offset; 205924edb884SFrançois Tigeot } 206024edb884SFrançois Tigeot 2061c0e85e96SFrançois Tigeot ret = intel_ring_begin(req, 2); 2062e3adcf8fSFrançois Tigeot if (ret) 2063e3adcf8fSFrançois Tigeot return ret; 2064e3adcf8fSFrançois Tigeot 20658621f407SFrançois Tigeot intel_ring_emit(engine, MI_BATCH_BUFFER_START | MI_BATCH_GTT); 20668621f407SFrançois Tigeot intel_ring_emit(engine, offset | (dispatch_flags & I915_DISPATCH_SECURE ? 2067477eb7f9SFrançois Tigeot 0 : MI_BATCH_NON_SECURE)); 20688621f407SFrançois Tigeot intel_ring_advance(engine); 2069686a02f1SFrançois Tigeot 2070686a02f1SFrançois Tigeot return 0; 2071686a02f1SFrançois Tigeot } 2072686a02f1SFrançois Tigeot 2073686a02f1SFrançois Tigeot static int 2074a05eeebfSFrançois Tigeot i915_dispatch_execbuffer(struct drm_i915_gem_request *req, 2075ba55f2f5SFrançois Tigeot u64 offset, u32 len, 2076477eb7f9SFrançois Tigeot unsigned dispatch_flags) 2077686a02f1SFrançois Tigeot { 20788621f407SFrançois Tigeot struct intel_engine_cs *engine = req->engine; 2079686a02f1SFrançois Tigeot int ret; 2080686a02f1SFrançois Tigeot 2081a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 2); 2082e3adcf8fSFrançois Tigeot if (ret) 2083e3adcf8fSFrançois Tigeot return ret; 2084e3adcf8fSFrançois Tigeot 20858621f407SFrançois Tigeot intel_ring_emit(engine, MI_BATCH_BUFFER_START | MI_BATCH_GTT); 20868621f407SFrançois Tigeot intel_ring_emit(engine, offset | (dispatch_flags & I915_DISPATCH_SECURE ? 2087477eb7f9SFrançois Tigeot 0 : MI_BATCH_NON_SECURE)); 20888621f407SFrançois Tigeot intel_ring_advance(engine); 2089e3adcf8fSFrançois Tigeot 2090e3adcf8fSFrançois Tigeot return 0; 2091e3adcf8fSFrançois Tigeot } 2092e3adcf8fSFrançois Tigeot 20938621f407SFrançois Tigeot static void cleanup_phys_status_page(struct intel_engine_cs *engine) 2094c0e85e96SFrançois Tigeot { 2095*1487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 2096c0e85e96SFrançois Tigeot 2097c0e85e96SFrançois Tigeot if (!dev_priv->status_page_dmah) 2098c0e85e96SFrançois Tigeot return; 2099c0e85e96SFrançois Tigeot 2100*1487f786SFrançois Tigeot drm_pci_free(dev_priv->dev, dev_priv->status_page_dmah); 21018621f407SFrançois Tigeot engine->status_page.page_addr = NULL; 2102c0e85e96SFrançois Tigeot } 2103c0e85e96SFrançois Tigeot 21048621f407SFrançois Tigeot static void cleanup_status_page(struct intel_engine_cs *engine) 2105e3adcf8fSFrançois Tigeot { 2106e3adcf8fSFrançois Tigeot struct drm_i915_gem_object *obj; 2107e3adcf8fSFrançois Tigeot 21088621f407SFrançois Tigeot obj = engine->status_page.obj; 2109e3adcf8fSFrançois Tigeot if (obj == NULL) 2110e3adcf8fSFrançois Tigeot return; 2111e3adcf8fSFrançois Tigeot 21127ec9f8e5SFrançois Tigeot kunmap(sg_page(obj->pages->sgl)); 2113ba55f2f5SFrançois Tigeot i915_gem_object_ggtt_unpin(obj); 2114e3adcf8fSFrançois Tigeot drm_gem_object_unreference(&obj->base); 21158621f407SFrançois Tigeot engine->status_page.obj = NULL; 2116e3adcf8fSFrançois Tigeot } 2117e3adcf8fSFrançois Tigeot 21188621f407SFrançois Tigeot static int init_status_page(struct intel_engine_cs *engine) 2119e3adcf8fSFrançois Tigeot { 21208621f407SFrançois Tigeot struct drm_i915_gem_object *obj = engine->status_page.obj; 2121ba55f2f5SFrançois Tigeot 2122c0e85e96SFrançois Tigeot if (obj == NULL) { 212324edb884SFrançois Tigeot unsigned flags; 2124e3adcf8fSFrançois Tigeot int ret; 2125e3adcf8fSFrançois Tigeot 2126*1487f786SFrançois Tigeot obj = i915_gem_object_create(engine->i915->dev, 4096); 2127*1487f786SFrançois Tigeot if (IS_ERR(obj)) { 2128e3adcf8fSFrançois Tigeot DRM_ERROR("Failed to allocate status page\n"); 2129*1487f786SFrançois Tigeot return PTR_ERR(obj); 2130e3adcf8fSFrançois Tigeot } 2131e3adcf8fSFrançois Tigeot 2132ba55f2f5SFrançois Tigeot ret = i915_gem_object_set_cache_level(obj, I915_CACHE_LLC); 2133ba55f2f5SFrançois Tigeot if (ret) 2134e3adcf8fSFrançois Tigeot goto err_unref; 2135ba55f2f5SFrançois Tigeot 213624edb884SFrançois Tigeot flags = 0; 2137*1487f786SFrançois Tigeot if (!HAS_LLC(engine->i915)) 213824edb884SFrançois Tigeot /* On g33, we cannot place HWS above 256MiB, so 213924edb884SFrançois Tigeot * restrict its pinning to the low mappable arena. 214024edb884SFrançois Tigeot * Though this restriction is not documented for 214124edb884SFrançois Tigeot * gen4, gen5, or byt, they also behave similarly 214224edb884SFrançois Tigeot * and hang if the HWS is placed at the top of the 214324edb884SFrançois Tigeot * GTT. To generalise, it appears that all !llc 214424edb884SFrançois Tigeot * platforms have issues with us placing the HWS 214524edb884SFrançois Tigeot * above the mappable region (even though we never 214624edb884SFrançois Tigeot * actualy map it). 214724edb884SFrançois Tigeot */ 214824edb884SFrançois Tigeot flags |= PIN_MAPPABLE; 214924edb884SFrançois Tigeot ret = i915_gem_obj_ggtt_pin(obj, 4096, flags); 2150ba55f2f5SFrançois Tigeot if (ret) { 2151ba55f2f5SFrançois Tigeot err_unref: 2152ba55f2f5SFrançois Tigeot drm_gem_object_unreference(&obj->base); 2153ba55f2f5SFrançois Tigeot return ret; 2154ba55f2f5SFrançois Tigeot } 2155ba55f2f5SFrançois Tigeot 21568621f407SFrançois Tigeot engine->status_page.obj = obj; 2157e3adcf8fSFrançois Tigeot } 2158e3adcf8fSFrançois Tigeot 21598621f407SFrançois Tigeot engine->status_page.gfx_addr = i915_gem_obj_ggtt_offset(obj); 21608621f407SFrançois Tigeot engine->status_page.page_addr = kmap(sg_page(obj->pages->sgl)); 21618621f407SFrançois Tigeot memset(engine->status_page.page_addr, 0, PAGE_SIZE); 2162e3adcf8fSFrançois Tigeot 2163b5c29a34SFrançois Tigeot DRM_DEBUG_DRIVER("%s hws offset: 0x%08x\n", 21648621f407SFrançois Tigeot engine->name, engine->status_page.gfx_addr); 2165e3adcf8fSFrançois Tigeot 2166e3adcf8fSFrançois Tigeot return 0; 2167e3adcf8fSFrançois Tigeot } 2168e3adcf8fSFrançois Tigeot 21698621f407SFrançois Tigeot static int init_phys_status_page(struct intel_engine_cs *engine) 2170686a02f1SFrançois Tigeot { 2171*1487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 2172686a02f1SFrançois Tigeot 2173686a02f1SFrançois Tigeot if (!dev_priv->status_page_dmah) { 2174686a02f1SFrançois Tigeot dev_priv->status_page_dmah = 2175*1487f786SFrançois Tigeot drm_pci_alloc(dev_priv->dev, PAGE_SIZE, PAGE_SIZE); 2176686a02f1SFrançois Tigeot if (!dev_priv->status_page_dmah) 2177686a02f1SFrançois Tigeot return -ENOMEM; 2178686a02f1SFrançois Tigeot } 2179686a02f1SFrançois Tigeot 21808621f407SFrançois Tigeot engine->status_page.page_addr = dev_priv->status_page_dmah->vaddr; 21818621f407SFrançois Tigeot memset(engine->status_page.page_addr, 0, PAGE_SIZE); 2182686a02f1SFrançois Tigeot 2183686a02f1SFrançois Tigeot return 0; 2184686a02f1SFrançois Tigeot } 2185686a02f1SFrançois Tigeot 21862c9916cdSFrançois Tigeot void intel_unpin_ringbuffer_obj(struct intel_ringbuffer *ringbuf) 21872c9916cdSFrançois Tigeot { 2188*1487f786SFrançois Tigeot GEM_BUG_ON(ringbuf->vma == NULL); 2189*1487f786SFrançois Tigeot GEM_BUG_ON(ringbuf->virtual_start == NULL); 2190*1487f786SFrançois Tigeot 2191aee94f86SFrançois Tigeot if (HAS_LLC(ringbuf->obj->base.dev) && !ringbuf->obj->stolen) 21928621f407SFrançois Tigeot i915_gem_object_unpin_map(ringbuf->obj); 2193aee94f86SFrançois Tigeot else 2194*1487f786SFrançois Tigeot i915_vma_unpin_iomap(ringbuf->vma); 21952c9916cdSFrançois Tigeot ringbuf->virtual_start = NULL; 2196*1487f786SFrançois Tigeot 21972c9916cdSFrançois Tigeot i915_gem_object_ggtt_unpin(ringbuf->obj); 2198*1487f786SFrançois Tigeot ringbuf->vma = NULL; 21992c9916cdSFrançois Tigeot } 22002c9916cdSFrançois Tigeot 2201*1487f786SFrançois Tigeot int intel_pin_and_map_ringbuffer_obj(struct drm_i915_private *dev_priv, 22022c9916cdSFrançois Tigeot struct intel_ringbuffer *ringbuf) 22032c9916cdSFrançois Tigeot { 22042c9916cdSFrançois Tigeot struct drm_i915_gem_object *obj = ringbuf->obj; 2205c0e85e96SFrançois Tigeot /* Ring wraparound at offset 0 sometimes hangs. No idea why. */ 2206c0e85e96SFrançois Tigeot unsigned flags = PIN_OFFSET_BIAS | 4096; 22078621f407SFrançois Tigeot void *addr; 22082c9916cdSFrançois Tigeot int ret; 22092c9916cdSFrançois Tigeot 2210aee94f86SFrançois Tigeot if (HAS_LLC(dev_priv) && !obj->stolen) { 2211c0e85e96SFrançois Tigeot ret = i915_gem_obj_ggtt_pin(obj, PAGE_SIZE, flags); 2212aee94f86SFrançois Tigeot if (ret) 2213aee94f86SFrançois Tigeot return ret; 2214aee94f86SFrançois Tigeot 2215aee94f86SFrançois Tigeot ret = i915_gem_object_set_to_cpu_domain(obj, true); 22168621f407SFrançois Tigeot if (ret) 22178621f407SFrançois Tigeot goto err_unpin; 2218aee94f86SFrançois Tigeot 22198621f407SFrançois Tigeot addr = i915_gem_object_pin_map(obj); 22208621f407SFrançois Tigeot if (IS_ERR(addr)) { 22218621f407SFrançois Tigeot ret = PTR_ERR(addr); 22228621f407SFrançois Tigeot goto err_unpin; 2223aee94f86SFrançois Tigeot } 2224aee94f86SFrançois Tigeot } else { 2225c0e85e96SFrançois Tigeot ret = i915_gem_obj_ggtt_pin(obj, PAGE_SIZE, 2226c0e85e96SFrançois Tigeot flags | PIN_MAPPABLE); 22272c9916cdSFrançois Tigeot if (ret) 22282c9916cdSFrançois Tigeot return ret; 22292c9916cdSFrançois Tigeot 22302c9916cdSFrançois Tigeot ret = i915_gem_object_set_to_gtt_domain(obj, true); 22318621f407SFrançois Tigeot if (ret) 22328621f407SFrançois Tigeot goto err_unpin; 22332c9916cdSFrançois Tigeot 2234c0e85e96SFrançois Tigeot /* Access through the GTT requires the device to be awake. */ 2235c0e85e96SFrançois Tigeot assert_rpm_wakelock_held(dev_priv); 2236c0e85e96SFrançois Tigeot 2237*1487f786SFrançois Tigeot addr = i915_vma_pin_iomap(i915_gem_obj_to_ggtt(obj)); 2238*1487f786SFrançois Tigeot if (IS_ERR(addr)) { 2239*1487f786SFrançois Tigeot ret = PTR_ERR(addr); 22408621f407SFrançois Tigeot goto err_unpin; 22412c9916cdSFrançois Tigeot } 2242aee94f86SFrançois Tigeot } 22432c9916cdSFrançois Tigeot 22448621f407SFrançois Tigeot ringbuf->virtual_start = addr; 2245c0e85e96SFrançois Tigeot ringbuf->vma = i915_gem_obj_to_ggtt(obj); 22462c9916cdSFrançois Tigeot return 0; 22478621f407SFrançois Tigeot 22488621f407SFrançois Tigeot err_unpin: 22498621f407SFrançois Tigeot i915_gem_object_ggtt_unpin(obj); 22508621f407SFrançois Tigeot return ret; 22512c9916cdSFrançois Tigeot } 22522c9916cdSFrançois Tigeot 2253352ff8bdSFrançois Tigeot static void intel_destroy_ringbuffer_obj(struct intel_ringbuffer *ringbuf) 2254e3adcf8fSFrançois Tigeot { 225524edb884SFrançois Tigeot drm_gem_object_unreference(&ringbuf->obj->base); 225624edb884SFrançois Tigeot ringbuf->obj = NULL; 225724edb884SFrançois Tigeot } 225824edb884SFrançois Tigeot 2259352ff8bdSFrançois Tigeot static int intel_alloc_ringbuffer_obj(struct drm_device *dev, 226024edb884SFrançois Tigeot struct intel_ringbuffer *ringbuf) 226124edb884SFrançois Tigeot { 2262e3adcf8fSFrançois Tigeot struct drm_i915_gem_object *obj; 2263e3adcf8fSFrançois Tigeot 2264a2fdbec6SFrançois Tigeot obj = NULL; 2265a2fdbec6SFrançois Tigeot if (!HAS_LLC(dev)) 2266ba55f2f5SFrançois Tigeot obj = i915_gem_object_create_stolen(dev, ringbuf->size); 2267a2fdbec6SFrançois Tigeot if (obj == NULL) 2268*1487f786SFrançois Tigeot obj = i915_gem_object_create(dev, ringbuf->size); 2269*1487f786SFrançois Tigeot if (IS_ERR(obj)) 2270*1487f786SFrançois Tigeot return PTR_ERR(obj); 2271e3adcf8fSFrançois Tigeot 227224edb884SFrançois Tigeot /* mark ring buffers as read-only from GPU side by default */ 227324edb884SFrançois Tigeot obj->gt_ro = 1; 227424edb884SFrançois Tigeot 2275ba55f2f5SFrançois Tigeot ringbuf->obj = obj; 2276ba55f2f5SFrançois Tigeot 22772c9916cdSFrançois Tigeot return 0; 2278ba55f2f5SFrançois Tigeot } 2279ba55f2f5SFrançois Tigeot 2280352ff8bdSFrançois Tigeot struct intel_ringbuffer * 2281352ff8bdSFrançois Tigeot intel_engine_create_ringbuffer(struct intel_engine_cs *engine, int size) 2282352ff8bdSFrançois Tigeot { 2283352ff8bdSFrançois Tigeot struct intel_ringbuffer *ring; 2284352ff8bdSFrançois Tigeot int ret; 2285352ff8bdSFrançois Tigeot 2286352ff8bdSFrançois Tigeot ring = kzalloc(sizeof(*ring), GFP_KERNEL); 2287aee94f86SFrançois Tigeot if (ring == NULL) { 2288aee94f86SFrançois Tigeot DRM_DEBUG_DRIVER("Failed to allocate ringbuffer %s\n", 2289aee94f86SFrançois Tigeot engine->name); 2290352ff8bdSFrançois Tigeot return ERR_PTR(-ENOMEM); 2291aee94f86SFrançois Tigeot } 2292352ff8bdSFrançois Tigeot 22938621f407SFrançois Tigeot ring->engine = engine; 2294aee94f86SFrançois Tigeot list_add(&ring->link, &engine->buffers); 2295352ff8bdSFrançois Tigeot 2296352ff8bdSFrançois Tigeot ring->size = size; 2297352ff8bdSFrançois Tigeot /* Workaround an erratum on the i830 which causes a hang if 2298352ff8bdSFrançois Tigeot * the TAIL pointer points to within the last 2 cachelines 2299352ff8bdSFrançois Tigeot * of the buffer. 2300352ff8bdSFrançois Tigeot */ 2301352ff8bdSFrançois Tigeot ring->effective_size = size; 2302*1487f786SFrançois Tigeot if (IS_I830(engine->i915) || IS_845G(engine->i915)) 2303352ff8bdSFrançois Tigeot ring->effective_size -= 2 * CACHELINE_BYTES; 2304352ff8bdSFrançois Tigeot 2305352ff8bdSFrançois Tigeot ring->last_retired_head = -1; 2306352ff8bdSFrançois Tigeot intel_ring_update_space(ring); 2307352ff8bdSFrançois Tigeot 2308*1487f786SFrançois Tigeot ret = intel_alloc_ringbuffer_obj(engine->i915->dev, ring); 2309352ff8bdSFrançois Tigeot if (ret) { 2310aee94f86SFrançois Tigeot DRM_DEBUG_DRIVER("Failed to allocate ringbuffer %s: %d\n", 2311352ff8bdSFrançois Tigeot engine->name, ret); 2312aee94f86SFrançois Tigeot list_del(&ring->link); 2313352ff8bdSFrançois Tigeot kfree(ring); 2314352ff8bdSFrançois Tigeot return ERR_PTR(ret); 2315352ff8bdSFrançois Tigeot } 2316352ff8bdSFrançois Tigeot 2317352ff8bdSFrançois Tigeot return ring; 2318352ff8bdSFrançois Tigeot } 2319352ff8bdSFrançois Tigeot 2320352ff8bdSFrançois Tigeot void 2321352ff8bdSFrançois Tigeot intel_ringbuffer_free(struct intel_ringbuffer *ring) 2322352ff8bdSFrançois Tigeot { 2323352ff8bdSFrançois Tigeot intel_destroy_ringbuffer_obj(ring); 2324aee94f86SFrançois Tigeot list_del(&ring->link); 2325352ff8bdSFrançois Tigeot kfree(ring); 2326352ff8bdSFrançois Tigeot } 2327352ff8bdSFrançois Tigeot 2328*1487f786SFrançois Tigeot static int intel_ring_context_pin(struct i915_gem_context *ctx, 2329*1487f786SFrançois Tigeot struct intel_engine_cs *engine) 2330*1487f786SFrançois Tigeot { 2331*1487f786SFrançois Tigeot struct intel_context *ce = &ctx->engine[engine->id]; 2332*1487f786SFrançois Tigeot int ret; 2333*1487f786SFrançois Tigeot 2334*1487f786SFrançois Tigeot lockdep_assert_held(&ctx->i915->dev->struct_mutex); 2335*1487f786SFrançois Tigeot 2336*1487f786SFrançois Tigeot if (ce->pin_count++) 2337*1487f786SFrançois Tigeot return 0; 2338*1487f786SFrançois Tigeot 2339*1487f786SFrançois Tigeot if (ce->state) { 2340*1487f786SFrançois Tigeot ret = i915_gem_obj_ggtt_pin(ce->state, ctx->ggtt_alignment, 0); 2341*1487f786SFrançois Tigeot if (ret) 2342*1487f786SFrançois Tigeot goto error; 2343*1487f786SFrançois Tigeot } 2344*1487f786SFrançois Tigeot 2345*1487f786SFrançois Tigeot /* The kernel context is only used as a placeholder for flushing the 2346*1487f786SFrançois Tigeot * active context. It is never used for submitting user rendering and 2347*1487f786SFrançois Tigeot * as such never requires the golden render context, and so we can skip 2348*1487f786SFrançois Tigeot * emitting it when we switch to the kernel context. This is required 2349*1487f786SFrançois Tigeot * as during eviction we cannot allocate and pin the renderstate in 2350*1487f786SFrançois Tigeot * order to initialise the context. 2351*1487f786SFrançois Tigeot */ 2352*1487f786SFrançois Tigeot if (ctx == ctx->i915->kernel_context) 2353*1487f786SFrançois Tigeot ce->initialised = true; 2354*1487f786SFrançois Tigeot 2355*1487f786SFrançois Tigeot i915_gem_context_reference(ctx); 2356*1487f786SFrançois Tigeot return 0; 2357*1487f786SFrançois Tigeot 2358*1487f786SFrançois Tigeot error: 2359*1487f786SFrançois Tigeot ce->pin_count = 0; 2360*1487f786SFrançois Tigeot return ret; 2361*1487f786SFrançois Tigeot } 2362*1487f786SFrançois Tigeot 2363*1487f786SFrançois Tigeot static void intel_ring_context_unpin(struct i915_gem_context *ctx, 2364*1487f786SFrançois Tigeot struct intel_engine_cs *engine) 2365*1487f786SFrançois Tigeot { 2366*1487f786SFrançois Tigeot struct intel_context *ce = &ctx->engine[engine->id]; 2367*1487f786SFrançois Tigeot 2368*1487f786SFrançois Tigeot lockdep_assert_held(&ctx->i915->dev->struct_mutex); 2369*1487f786SFrançois Tigeot 2370*1487f786SFrançois Tigeot if (--ce->pin_count) 2371*1487f786SFrançois Tigeot return; 2372*1487f786SFrançois Tigeot 2373*1487f786SFrançois Tigeot if (ce->state) 2374*1487f786SFrançois Tigeot i915_gem_object_ggtt_unpin(ce->state); 2375*1487f786SFrançois Tigeot 2376*1487f786SFrançois Tigeot i915_gem_context_unreference(ctx); 2377*1487f786SFrançois Tigeot } 2378*1487f786SFrançois Tigeot 2379ba55f2f5SFrançois Tigeot static int intel_init_ring_buffer(struct drm_device *dev, 23808621f407SFrançois Tigeot struct intel_engine_cs *engine) 2381ba55f2f5SFrançois Tigeot { 2382*1487f786SFrançois Tigeot struct drm_i915_private *dev_priv = to_i915(dev); 23832c9916cdSFrançois Tigeot struct intel_ringbuffer *ringbuf; 2384ba55f2f5SFrançois Tigeot int ret; 2385ba55f2f5SFrançois Tigeot 23868621f407SFrançois Tigeot WARN_ON(engine->buffer); 23872c9916cdSFrançois Tigeot 2388*1487f786SFrançois Tigeot engine->i915 = dev_priv; 23898621f407SFrançois Tigeot INIT_LIST_HEAD(&engine->active_list); 23908621f407SFrançois Tigeot INIT_LIST_HEAD(&engine->request_list); 23918621f407SFrançois Tigeot INIT_LIST_HEAD(&engine->execlist_queue); 23928621f407SFrançois Tigeot INIT_LIST_HEAD(&engine->buffers); 23938621f407SFrançois Tigeot i915_gem_batch_pool_init(dev, &engine->batch_pool); 23948621f407SFrançois Tigeot memset(engine->semaphore.sync_seqno, 0, 23958621f407SFrançois Tigeot sizeof(engine->semaphore.sync_seqno)); 2396ba55f2f5SFrançois Tigeot 23978621f407SFrançois Tigeot init_waitqueue_head(&engine->irq_queue); 2398ba55f2f5SFrançois Tigeot 2399*1487f786SFrançois Tigeot /* We may need to do things with the shrinker which 2400*1487f786SFrançois Tigeot * require us to immediately switch back to the default 2401*1487f786SFrançois Tigeot * context. This can cause a problem as pinning the 2402*1487f786SFrançois Tigeot * default context also requires GTT space which may not 2403*1487f786SFrançois Tigeot * be available. To avoid this we always pin the default 2404*1487f786SFrançois Tigeot * context. 2405*1487f786SFrançois Tigeot */ 2406*1487f786SFrançois Tigeot ret = intel_ring_context_pin(dev_priv->kernel_context, engine); 2407*1487f786SFrançois Tigeot if (ret) 2408*1487f786SFrançois Tigeot goto error; 2409*1487f786SFrançois Tigeot 24108621f407SFrançois Tigeot ringbuf = intel_engine_create_ringbuffer(engine, 32 * PAGE_SIZE); 2411aee94f86SFrançois Tigeot if (IS_ERR(ringbuf)) { 2412aee94f86SFrançois Tigeot ret = PTR_ERR(ringbuf); 2413aee94f86SFrançois Tigeot goto error; 2414aee94f86SFrançois Tigeot } 24158621f407SFrançois Tigeot engine->buffer = ringbuf; 2416352ff8bdSFrançois Tigeot 2417*1487f786SFrançois Tigeot if (I915_NEED_GFX_HWS(dev_priv)) { 24188621f407SFrançois Tigeot ret = init_status_page(engine); 2419e3adcf8fSFrançois Tigeot if (ret) 2420ba55f2f5SFrançois Tigeot goto error; 2421ba55f2f5SFrançois Tigeot } else { 24228621f407SFrançois Tigeot WARN_ON(engine->id != RCS); 24238621f407SFrançois Tigeot ret = init_phys_status_page(engine); 2424ba55f2f5SFrançois Tigeot if (ret) 2425ba55f2f5SFrançois Tigeot goto error; 2426ba55f2f5SFrançois Tigeot } 2427ba55f2f5SFrançois Tigeot 2428*1487f786SFrançois Tigeot ret = intel_pin_and_map_ringbuffer_obj(dev_priv, ringbuf); 24292c9916cdSFrançois Tigeot if (ret) { 24302c9916cdSFrançois Tigeot DRM_ERROR("Failed to pin and map ringbuffer %s: %d\n", 24318621f407SFrançois Tigeot engine->name, ret); 24322c9916cdSFrançois Tigeot intel_destroy_ringbuffer_obj(ringbuf); 2433ba55f2f5SFrançois Tigeot goto error; 2434ba55f2f5SFrançois Tigeot } 2435e3adcf8fSFrançois Tigeot 24368621f407SFrançois Tigeot ret = i915_cmd_parser_init_ring(engine); 2437ba55f2f5SFrançois Tigeot if (ret) 2438ba55f2f5SFrançois Tigeot goto error; 2439ba55f2f5SFrançois Tigeot 2440e3adcf8fSFrançois Tigeot return 0; 2441e3adcf8fSFrançois Tigeot 2442ba55f2f5SFrançois Tigeot error: 24438621f407SFrançois Tigeot intel_cleanup_engine(engine); 2444e3adcf8fSFrançois Tigeot return ret; 2445e3adcf8fSFrançois Tigeot } 2446e3adcf8fSFrançois Tigeot 24478621f407SFrançois Tigeot void intel_cleanup_engine(struct intel_engine_cs *engine) 2448e3adcf8fSFrançois Tigeot { 24492c9916cdSFrançois Tigeot struct drm_i915_private *dev_priv; 2450e3adcf8fSFrançois Tigeot 24518621f407SFrançois Tigeot if (!intel_engine_initialized(engine)) 2452e3adcf8fSFrançois Tigeot return; 2453e3adcf8fSFrançois Tigeot 2454*1487f786SFrançois Tigeot dev_priv = engine->i915; 24552c9916cdSFrançois Tigeot 24568621f407SFrançois Tigeot if (engine->buffer) { 24578621f407SFrançois Tigeot intel_stop_engine(engine); 2458*1487f786SFrançois Tigeot WARN_ON(!IS_GEN2(dev_priv) && (I915_READ_MODE(engine) & MODE_IDLE) == 0); 2459b030f26bSFrançois Tigeot 24608621f407SFrançois Tigeot intel_unpin_ringbuffer_obj(engine->buffer); 24618621f407SFrançois Tigeot intel_ringbuffer_free(engine->buffer); 24628621f407SFrançois Tigeot engine->buffer = NULL; 2463aee94f86SFrançois Tigeot } 2464e3adcf8fSFrançois Tigeot 24658621f407SFrançois Tigeot if (engine->cleanup) 24668621f407SFrançois Tigeot engine->cleanup(engine); 2467e3adcf8fSFrançois Tigeot 2468*1487f786SFrançois Tigeot if (I915_NEED_GFX_HWS(dev_priv)) { 24698621f407SFrançois Tigeot cleanup_status_page(engine); 2470c0e85e96SFrançois Tigeot } else { 24718621f407SFrançois Tigeot WARN_ON(engine->id != RCS); 24728621f407SFrançois Tigeot cleanup_phys_status_page(engine); 2473c0e85e96SFrançois Tigeot } 2474ba55f2f5SFrançois Tigeot 24758621f407SFrançois Tigeot i915_cmd_parser_fini_ring(engine); 24768621f407SFrançois Tigeot i915_gem_batch_pool_fini(&engine->batch_pool); 2477*1487f786SFrançois Tigeot 2478*1487f786SFrançois Tigeot intel_ring_context_unpin(dev_priv->kernel_context, engine); 2479*1487f786SFrançois Tigeot 2480*1487f786SFrançois Tigeot engine->i915 = NULL; 2481e3adcf8fSFrançois Tigeot } 2482e3adcf8fSFrançois Tigeot 24838621f407SFrançois Tigeot int intel_engine_idle(struct intel_engine_cs *engine) 2484b030f26bSFrançois Tigeot { 24852c9916cdSFrançois Tigeot struct drm_i915_gem_request *req; 2486b5c29a34SFrançois Tigeot 2487b5c29a34SFrançois Tigeot /* Wait upon the last request to be completed */ 24888621f407SFrançois Tigeot if (list_empty(&engine->request_list)) 2489b5c29a34SFrançois Tigeot return 0; 2490b5c29a34SFrançois Tigeot 24918621f407SFrançois Tigeot req = list_entry(engine->request_list.prev, 2492b5c29a34SFrançois Tigeot struct drm_i915_gem_request, 24932c9916cdSFrançois Tigeot list); 2494b5c29a34SFrançois Tigeot 249519c468b4SFrançois Tigeot /* Make sure we do not trigger any retires */ 249619c468b4SFrançois Tigeot return __i915_wait_request(req, 24978621f407SFrançois Tigeot req->i915->mm.interruptible, 249819c468b4SFrançois Tigeot NULL, NULL); 2499b5c29a34SFrançois Tigeot } 2500b5c29a34SFrançois Tigeot 250119c468b4SFrançois Tigeot int intel_ring_alloc_request_extras(struct drm_i915_gem_request *request) 2502b5c29a34SFrançois Tigeot { 2503*1487f786SFrançois Tigeot int ret; 25049edbd4a0SFrançois Tigeot 2505*1487f786SFrançois Tigeot /* Flush enough space to reduce the likelihood of waiting after 2506*1487f786SFrançois Tigeot * we start building the request - in which case we will just 2507*1487f786SFrançois Tigeot * have to repeat work. 2508a05eeebfSFrançois Tigeot */ 2509*1487f786SFrançois Tigeot request->reserved_space += LEGACY_REQUEST_SIZE; 2510a2fdbec6SFrançois Tigeot 2511*1487f786SFrançois Tigeot request->ringbuf = request->engine->buffer; 2512a2fdbec6SFrançois Tigeot 2513*1487f786SFrançois Tigeot ret = intel_ring_begin(request, 0); 2514*1487f786SFrançois Tigeot if (ret) 2515*1487f786SFrançois Tigeot return ret; 2516a05eeebfSFrançois Tigeot 2517*1487f786SFrançois Tigeot request->reserved_space -= LEGACY_REQUEST_SIZE; 2518*1487f786SFrançois Tigeot return 0; 2519a05eeebfSFrançois Tigeot } 2520a05eeebfSFrançois Tigeot 25218621f407SFrançois Tigeot static int wait_for_space(struct drm_i915_gem_request *req, int bytes) 2522a05eeebfSFrançois Tigeot { 25238621f407SFrançois Tigeot struct intel_ringbuffer *ringbuf = req->ringbuf; 25248621f407SFrançois Tigeot struct intel_engine_cs *engine = req->engine; 25258621f407SFrançois Tigeot struct drm_i915_gem_request *target; 25268621f407SFrançois Tigeot 25278621f407SFrançois Tigeot intel_ring_update_space(ringbuf); 25288621f407SFrançois Tigeot if (ringbuf->space >= bytes) 25298621f407SFrançois Tigeot return 0; 25308621f407SFrançois Tigeot 25318621f407SFrançois Tigeot /* 25328621f407SFrançois Tigeot * Space is reserved in the ringbuffer for finalising the request, 25338621f407SFrançois Tigeot * as that cannot be allowed to fail. During request finalisation, 25348621f407SFrançois Tigeot * reserved_space is set to 0 to stop the overallocation and the 25358621f407SFrançois Tigeot * assumption is that then we never need to wait (which has the 25368621f407SFrançois Tigeot * risk of failing with EINTR). 25378621f407SFrançois Tigeot * 25388621f407SFrançois Tigeot * See also i915_gem_request_alloc() and i915_add_request(). 25398621f407SFrançois Tigeot */ 2540*1487f786SFrançois Tigeot GEM_BUG_ON(!req->reserved_space); 25418621f407SFrançois Tigeot 25428621f407SFrançois Tigeot list_for_each_entry(target, &engine->request_list, list) { 25438621f407SFrançois Tigeot unsigned space; 25448621f407SFrançois Tigeot 25458621f407SFrançois Tigeot /* 25468621f407SFrançois Tigeot * The request queue is per-engine, so can contain requests 25478621f407SFrançois Tigeot * from multiple ringbuffers. Here, we must ignore any that 25488621f407SFrançois Tigeot * aren't from the ringbuffer we're considering. 25498621f407SFrançois Tigeot */ 25508621f407SFrançois Tigeot if (target->ringbuf != ringbuf) 25518621f407SFrançois Tigeot continue; 25528621f407SFrançois Tigeot 25538621f407SFrançois Tigeot /* Would completion of this request free enough space? */ 25548621f407SFrançois Tigeot space = __intel_ring_space(target->postfix, ringbuf->tail, 25558621f407SFrançois Tigeot ringbuf->size); 25568621f407SFrançois Tigeot if (space >= bytes) 25578621f407SFrançois Tigeot break; 25588621f407SFrançois Tigeot } 25598621f407SFrançois Tigeot 25608621f407SFrançois Tigeot if (WARN_ON(&target->list == &engine->request_list)) 25618621f407SFrançois Tigeot return -ENOSPC; 25628621f407SFrançois Tigeot 25638621f407SFrançois Tigeot return i915_wait_request(target); 25648621f407SFrançois Tigeot } 25658621f407SFrançois Tigeot 25668621f407SFrançois Tigeot int intel_ring_begin(struct drm_i915_gem_request *req, int num_dwords) 25678621f407SFrançois Tigeot { 25688621f407SFrançois Tigeot struct intel_ringbuffer *ringbuf = req->ringbuf; 2569a05eeebfSFrançois Tigeot int remain_actual = ringbuf->size - ringbuf->tail; 25708621f407SFrançois Tigeot int remain_usable = ringbuf->effective_size - ringbuf->tail; 25718621f407SFrançois Tigeot int bytes = num_dwords * sizeof(u32); 25728621f407SFrançois Tigeot int total_bytes, wait_bytes; 2573a05eeebfSFrançois Tigeot bool need_wrap = false; 2574a05eeebfSFrançois Tigeot 2575*1487f786SFrançois Tigeot total_bytes = bytes + req->reserved_space; 2576a05eeebfSFrançois Tigeot 2577a05eeebfSFrançois Tigeot if (unlikely(bytes > remain_usable)) { 2578a05eeebfSFrançois Tigeot /* 2579a05eeebfSFrançois Tigeot * Not enough space for the basic request. So need to flush 2580a05eeebfSFrançois Tigeot * out the remainder and then wait for base + reserved. 2581a05eeebfSFrançois Tigeot */ 2582a05eeebfSFrançois Tigeot wait_bytes = remain_actual + total_bytes; 2583a05eeebfSFrançois Tigeot need_wrap = true; 25848621f407SFrançois Tigeot } else if (unlikely(total_bytes > remain_usable)) { 2585a05eeebfSFrançois Tigeot /* 2586a05eeebfSFrançois Tigeot * The base request will fit but the reserved space 25878621f407SFrançois Tigeot * falls off the end. So we don't need an immediate wrap 2588c0e85e96SFrançois Tigeot * and only need to effectively wait for the reserved 2589c0e85e96SFrançois Tigeot * size space from the start of ringbuffer. 2590a05eeebfSFrançois Tigeot */ 2591*1487f786SFrançois Tigeot wait_bytes = remain_actual + req->reserved_space; 25928621f407SFrançois Tigeot } else { 2593a05eeebfSFrançois Tigeot /* No wrapping required, just waiting. */ 2594a05eeebfSFrançois Tigeot wait_bytes = total_bytes; 2595a05eeebfSFrançois Tigeot } 2596a05eeebfSFrançois Tigeot 25978621f407SFrançois Tigeot if (wait_bytes > ringbuf->space) { 25988621f407SFrançois Tigeot int ret = wait_for_space(req, wait_bytes); 2599a2fdbec6SFrançois Tigeot if (unlikely(ret)) 2600a2fdbec6SFrançois Tigeot return ret; 2601a05eeebfSFrançois Tigeot 26028621f407SFrançois Tigeot intel_ring_update_space(ringbuf); 26038621f407SFrançois Tigeot if (unlikely(ringbuf->space < wait_bytes)) 26048621f407SFrançois Tigeot return -EAGAIN; 2605a2fdbec6SFrançois Tigeot } 2606a2fdbec6SFrançois Tigeot 26078621f407SFrançois Tigeot if (unlikely(need_wrap)) { 26088621f407SFrançois Tigeot GEM_BUG_ON(remain_actual > ringbuf->space); 26098621f407SFrançois Tigeot GEM_BUG_ON(ringbuf->tail + remain_actual > ringbuf->size); 26108621f407SFrançois Tigeot 26118621f407SFrançois Tigeot /* Fill the tail with MI_NOOP */ 26128621f407SFrançois Tigeot memset(ringbuf->virtual_start + ringbuf->tail, 26138621f407SFrançois Tigeot 0, remain_actual); 26148621f407SFrançois Tigeot ringbuf->tail = 0; 26158621f407SFrançois Tigeot ringbuf->space -= remain_actual; 2616a2fdbec6SFrançois Tigeot } 2617a2fdbec6SFrançois Tigeot 26188621f407SFrançois Tigeot ringbuf->space -= bytes; 26198621f407SFrançois Tigeot GEM_BUG_ON(ringbuf->space < 0); 26209edbd4a0SFrançois Tigeot return 0; 26219edbd4a0SFrançois Tigeot } 26229edbd4a0SFrançois Tigeot 26239edbd4a0SFrançois Tigeot /* Align the ring tail to a cacheline boundary */ 2624a05eeebfSFrançois Tigeot int intel_ring_cacheline_align(struct drm_i915_gem_request *req) 26259edbd4a0SFrançois Tigeot { 26268621f407SFrançois Tigeot struct intel_engine_cs *engine = req->engine; 26278621f407SFrançois Tigeot int num_dwords = (engine->buffer->tail & (CACHELINE_BYTES - 1)) / sizeof(uint32_t); 26289edbd4a0SFrançois Tigeot int ret; 26299edbd4a0SFrançois Tigeot 26309edbd4a0SFrançois Tigeot if (num_dwords == 0) 26319edbd4a0SFrançois Tigeot return 0; 26329edbd4a0SFrançois Tigeot 2633ba55f2f5SFrançois Tigeot num_dwords = CACHELINE_BYTES / sizeof(uint32_t) - num_dwords; 2634a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, num_dwords); 26359edbd4a0SFrançois Tigeot if (ret) 26369edbd4a0SFrançois Tigeot return ret; 26379edbd4a0SFrançois Tigeot 26389edbd4a0SFrançois Tigeot while (num_dwords--) 26398621f407SFrançois Tigeot intel_ring_emit(engine, MI_NOOP); 26409edbd4a0SFrançois Tigeot 26418621f407SFrançois Tigeot intel_ring_advance(engine); 26429edbd4a0SFrançois Tigeot 26439edbd4a0SFrançois Tigeot return 0; 2644e3adcf8fSFrançois Tigeot } 2645e3adcf8fSFrançois Tigeot 26468621f407SFrançois Tigeot void intel_ring_init_seqno(struct intel_engine_cs *engine, u32 seqno) 2647a2fdbec6SFrançois Tigeot { 2648*1487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 2649a2fdbec6SFrançois Tigeot 26508621f407SFrançois Tigeot /* Our semaphore implementation is strictly monotonic (i.e. we proceed 26518621f407SFrançois Tigeot * so long as the semaphore value in the register/page is greater 26528621f407SFrançois Tigeot * than the sync value), so whenever we reset the seqno, 26538621f407SFrançois Tigeot * so long as we reset the tracking semaphore value to 0, it will 26548621f407SFrançois Tigeot * always be before the next request's seqno. If we don't reset 26558621f407SFrançois Tigeot * the semaphore value, then when the seqno moves backwards all 26568621f407SFrançois Tigeot * future waits will complete instantly (causing rendering corruption). 26578621f407SFrançois Tigeot */ 2658*1487f786SFrançois Tigeot if (IS_GEN6(dev_priv) || IS_GEN7(dev_priv)) { 26598621f407SFrançois Tigeot I915_WRITE(RING_SYNC_0(engine->mmio_base), 0); 26608621f407SFrançois Tigeot I915_WRITE(RING_SYNC_1(engine->mmio_base), 0); 26618621f407SFrançois Tigeot if (HAS_VEBOX(dev_priv)) 26628621f407SFrançois Tigeot I915_WRITE(RING_SYNC_2(engine->mmio_base), 0); 26638621f407SFrançois Tigeot } 26648621f407SFrançois Tigeot if (dev_priv->semaphore_obj) { 26658621f407SFrançois Tigeot struct drm_i915_gem_object *obj = dev_priv->semaphore_obj; 2666f0bba3d1SFrançois Tigeot struct page *page = i915_gem_object_get_dirty_page(obj, 0); 2667*1487f786SFrançois Tigeot void *semaphores = kmap(page); 26688621f407SFrançois Tigeot memset(semaphores + GEN8_SEMAPHORE_OFFSET(engine->id, 0), 26698621f407SFrançois Tigeot 0, I915_NUM_ENGINES * gen8_semaphore_seqno_size); 26708621f407SFrançois Tigeot kunmap(page); 26718621f407SFrançois Tigeot } 26728621f407SFrançois Tigeot memset(engine->semaphore.sync_seqno, 0, 26738621f407SFrançois Tigeot sizeof(engine->semaphore.sync_seqno)); 26748621f407SFrançois Tigeot 26758621f407SFrançois Tigeot engine->set_seqno(engine, seqno); 26768621f407SFrançois Tigeot engine->last_submitted_seqno = seqno; 26778621f407SFrançois Tigeot 26788621f407SFrançois Tigeot engine->hangcheck.seqno = seqno; 2679e3adcf8fSFrançois Tigeot } 2680e3adcf8fSFrançois Tigeot 26818621f407SFrançois Tigeot static void gen6_bsd_ring_write_tail(struct intel_engine_cs *engine, 2682f4e1c372SFrançois Tigeot u32 value) 2683e3adcf8fSFrançois Tigeot { 2684*1487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 2685*1487f786SFrançois Tigeot 2686*1487f786SFrançois Tigeot intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL); 2687e3adcf8fSFrançois Tigeot 2688e3adcf8fSFrançois Tigeot /* Every tail move must follow the sequence below */ 2689f4e1c372SFrançois Tigeot 2690f4e1c372SFrançois Tigeot /* Disable notification that the ring is IDLE. The GT 2691f4e1c372SFrançois Tigeot * will then assume that it is busy and bring it out of rc6. 2692f4e1c372SFrançois Tigeot */ 2693*1487f786SFrançois Tigeot I915_WRITE_FW(GEN6_BSD_SLEEP_PSMI_CONTROL, 2694f4e1c372SFrançois Tigeot _MASKED_BIT_ENABLE(GEN6_BSD_SLEEP_MSG_DISABLE)); 2695e3adcf8fSFrançois Tigeot 2696f4e1c372SFrançois Tigeot /* Clear the context id. Here be magic! */ 2697*1487f786SFrançois Tigeot I915_WRITE64_FW(GEN6_BSD_RNCID, 0x0); 2698e3adcf8fSFrançois Tigeot 2699f4e1c372SFrançois Tigeot /* Wait for the ring not to be idle, i.e. for it to wake up. */ 2700*1487f786SFrançois Tigeot if (intel_wait_for_register_fw(dev_priv, 2701*1487f786SFrançois Tigeot GEN6_BSD_SLEEP_PSMI_CONTROL, 2702*1487f786SFrançois Tigeot GEN6_BSD_SLEEP_INDICATOR, 2703*1487f786SFrançois Tigeot 0, 2704f4e1c372SFrançois Tigeot 50)) 2705f4e1c372SFrançois Tigeot DRM_ERROR("timed out waiting for the BSD ring to wake up\n"); 2706f4e1c372SFrançois Tigeot 2707f4e1c372SFrançois Tigeot /* Now that the ring is fully powered up, update the tail */ 2708*1487f786SFrançois Tigeot I915_WRITE_FW(RING_TAIL(engine->mmio_base), value); 2709*1487f786SFrançois Tigeot POSTING_READ_FW(RING_TAIL(engine->mmio_base)); 2710f4e1c372SFrançois Tigeot 2711f4e1c372SFrançois Tigeot /* Let the ring send IDLE messages to the GT again, 2712f4e1c372SFrançois Tigeot * and so let it sleep to conserve power when idle. 2713f4e1c372SFrançois Tigeot */ 2714*1487f786SFrançois Tigeot I915_WRITE_FW(GEN6_BSD_SLEEP_PSMI_CONTROL, 2715f4e1c372SFrançois Tigeot _MASKED_BIT_DISABLE(GEN6_BSD_SLEEP_MSG_DISABLE)); 2716*1487f786SFrançois Tigeot 2717*1487f786SFrançois Tigeot intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL); 2718e3adcf8fSFrançois Tigeot } 2719e3adcf8fSFrançois Tigeot 2720a05eeebfSFrançois Tigeot static int gen6_bsd_ring_flush(struct drm_i915_gem_request *req, 2721b5c29a34SFrançois Tigeot u32 invalidate, u32 flush) 2722e3adcf8fSFrançois Tigeot { 27238621f407SFrançois Tigeot struct intel_engine_cs *engine = req->engine; 2724e3adcf8fSFrançois Tigeot uint32_t cmd; 2725e3adcf8fSFrançois Tigeot int ret; 2726e3adcf8fSFrançois Tigeot 2727a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 4); 2728e3adcf8fSFrançois Tigeot if (ret) 2729e3adcf8fSFrançois Tigeot return ret; 2730e3adcf8fSFrançois Tigeot 2731e3adcf8fSFrançois Tigeot cmd = MI_FLUSH_DW; 2732*1487f786SFrançois Tigeot if (INTEL_GEN(req->i915) >= 8) 27339edbd4a0SFrançois Tigeot cmd += 1; 27342c9916cdSFrançois Tigeot 27352c9916cdSFrançois Tigeot /* We always require a command barrier so that subsequent 27362c9916cdSFrançois Tigeot * commands, such as breadcrumb interrupts, are strictly ordered 27372c9916cdSFrançois Tigeot * wrt the contents of the write cache being flushed to memory 27382c9916cdSFrançois Tigeot * (and thus being coherent from the CPU). 27392c9916cdSFrançois Tigeot */ 27402c9916cdSFrançois Tigeot cmd |= MI_FLUSH_DW_STORE_INDEX | MI_FLUSH_DW_OP_STOREDW; 27412c9916cdSFrançois Tigeot 2742b5c29a34SFrançois Tigeot /* 2743b5c29a34SFrançois Tigeot * Bspec vol 1c.5 - video engine command streamer: 2744b5c29a34SFrançois Tigeot * "If ENABLED, all TLBs will be invalidated once the flush 2745b5c29a34SFrançois Tigeot * operation is complete. This bit is only valid when the 2746b5c29a34SFrançois Tigeot * Post-Sync Operation field is a value of 1h or 3h." 2747b5c29a34SFrançois Tigeot */ 2748e3adcf8fSFrançois Tigeot if (invalidate & I915_GEM_GPU_DOMAINS) 27492c9916cdSFrançois Tigeot cmd |= MI_INVALIDATE_TLB | MI_INVALIDATE_BSD; 27502c9916cdSFrançois Tigeot 27518621f407SFrançois Tigeot intel_ring_emit(engine, cmd); 27528621f407SFrançois Tigeot intel_ring_emit(engine, 27538621f407SFrançois Tigeot I915_GEM_HWS_SCRATCH_ADDR | MI_FLUSH_DW_USE_GTT); 2754*1487f786SFrançois Tigeot if (INTEL_GEN(req->i915) >= 8) { 27558621f407SFrançois Tigeot intel_ring_emit(engine, 0); /* upper addr */ 27568621f407SFrançois Tigeot intel_ring_emit(engine, 0); /* value */ 27579edbd4a0SFrançois Tigeot } else { 27588621f407SFrançois Tigeot intel_ring_emit(engine, 0); 27598621f407SFrançois Tigeot intel_ring_emit(engine, MI_NOOP); 27609edbd4a0SFrançois Tigeot } 27618621f407SFrançois Tigeot intel_ring_advance(engine); 27629edbd4a0SFrançois Tigeot return 0; 27639edbd4a0SFrançois Tigeot } 27649edbd4a0SFrançois Tigeot 27659edbd4a0SFrançois Tigeot static int 2766a05eeebfSFrançois Tigeot gen8_ring_dispatch_execbuffer(struct drm_i915_gem_request *req, 2767ba55f2f5SFrançois Tigeot u64 offset, u32 len, 2768477eb7f9SFrançois Tigeot unsigned dispatch_flags) 27699edbd4a0SFrançois Tigeot { 27708621f407SFrançois Tigeot struct intel_engine_cs *engine = req->engine; 27718621f407SFrançois Tigeot bool ppgtt = USES_PPGTT(engine->dev) && 2772477eb7f9SFrançois Tigeot !(dispatch_flags & I915_DISPATCH_SECURE); 27739edbd4a0SFrançois Tigeot int ret; 27749edbd4a0SFrançois Tigeot 2775a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 4); 27769edbd4a0SFrançois Tigeot if (ret) 27779edbd4a0SFrançois Tigeot return ret; 27789edbd4a0SFrançois Tigeot 27799edbd4a0SFrançois Tigeot /* FIXME(BDW): Address space and security selectors. */ 27808621f407SFrançois Tigeot intel_ring_emit(engine, MI_BATCH_BUFFER_START_GEN8 | (ppgtt<<8) | 2781a05eeebfSFrançois Tigeot (dispatch_flags & I915_DISPATCH_RS ? 2782a05eeebfSFrançois Tigeot MI_BATCH_RESOURCE_STREAMER : 0)); 27838621f407SFrançois Tigeot intel_ring_emit(engine, lower_32_bits(offset)); 27848621f407SFrançois Tigeot intel_ring_emit(engine, upper_32_bits(offset)); 27858621f407SFrançois Tigeot intel_ring_emit(engine, MI_NOOP); 27868621f407SFrançois Tigeot intel_ring_advance(engine); 27879edbd4a0SFrançois Tigeot 2788e3adcf8fSFrançois Tigeot return 0; 2789e3adcf8fSFrançois Tigeot } 2790e3adcf8fSFrançois Tigeot 2791e3adcf8fSFrançois Tigeot static int 2792a05eeebfSFrançois Tigeot hsw_ring_dispatch_execbuffer(struct drm_i915_gem_request *req, 2793ba55f2f5SFrançois Tigeot u64 offset, u32 len, 2794477eb7f9SFrançois Tigeot unsigned dispatch_flags) 2795e3adcf8fSFrançois Tigeot { 27968621f407SFrançois Tigeot struct intel_engine_cs *engine = req->engine; 2797e3adcf8fSFrançois Tigeot int ret; 2798e3adcf8fSFrançois Tigeot 2799a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 2); 2800e3adcf8fSFrançois Tigeot if (ret) 2801e3adcf8fSFrançois Tigeot return ret; 2802e3adcf8fSFrançois Tigeot 28038621f407SFrançois Tigeot intel_ring_emit(engine, 28041b13d190SFrançois Tigeot MI_BATCH_BUFFER_START | 2805477eb7f9SFrançois Tigeot (dispatch_flags & I915_DISPATCH_SECURE ? 2806a05eeebfSFrançois Tigeot 0 : MI_BATCH_PPGTT_HSW | MI_BATCH_NON_SECURE_HSW) | 2807a05eeebfSFrançois Tigeot (dispatch_flags & I915_DISPATCH_RS ? 2808a05eeebfSFrançois Tigeot MI_BATCH_RESOURCE_STREAMER : 0)); 2809b5c29a34SFrançois Tigeot /* bit0-7 is the length on GEN6+ */ 28108621f407SFrançois Tigeot intel_ring_emit(engine, offset); 28118621f407SFrançois Tigeot intel_ring_advance(engine); 2812b5c29a34SFrançois Tigeot 2813b5c29a34SFrançois Tigeot return 0; 2814b5c29a34SFrançois Tigeot } 2815b5c29a34SFrançois Tigeot 2816b5c29a34SFrançois Tigeot static int 2817a05eeebfSFrançois Tigeot gen6_ring_dispatch_execbuffer(struct drm_i915_gem_request *req, 2818ba55f2f5SFrançois Tigeot u64 offset, u32 len, 2819477eb7f9SFrançois Tigeot unsigned dispatch_flags) 2820b5c29a34SFrançois Tigeot { 28218621f407SFrançois Tigeot struct intel_engine_cs *engine = req->engine; 2822b5c29a34SFrançois Tigeot int ret; 2823b5c29a34SFrançois Tigeot 2824a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 2); 2825b5c29a34SFrançois Tigeot if (ret) 2826b5c29a34SFrançois Tigeot return ret; 2827b5c29a34SFrançois Tigeot 28288621f407SFrançois Tigeot intel_ring_emit(engine, 2829b5c29a34SFrançois Tigeot MI_BATCH_BUFFER_START | 2830477eb7f9SFrançois Tigeot (dispatch_flags & I915_DISPATCH_SECURE ? 2831477eb7f9SFrançois Tigeot 0 : MI_BATCH_NON_SECURE_I965)); 2832e3adcf8fSFrançois Tigeot /* bit0-7 is the length on GEN6+ */ 28338621f407SFrançois Tigeot intel_ring_emit(engine, offset); 28348621f407SFrançois Tigeot intel_ring_advance(engine); 2835e3adcf8fSFrançois Tigeot 2836e3adcf8fSFrançois Tigeot return 0; 2837e3adcf8fSFrançois Tigeot } 2838e3adcf8fSFrançois Tigeot 2839e3adcf8fSFrançois Tigeot /* Blitter support (SandyBridge+) */ 2840e3adcf8fSFrançois Tigeot 2841a05eeebfSFrançois Tigeot static int gen6_ring_flush(struct drm_i915_gem_request *req, 2842b5c29a34SFrançois Tigeot u32 invalidate, u32 flush) 2843e3adcf8fSFrançois Tigeot { 28448621f407SFrançois Tigeot struct intel_engine_cs *engine = req->engine; 2845e3adcf8fSFrançois Tigeot uint32_t cmd; 2846e3adcf8fSFrançois Tigeot int ret; 2847e3adcf8fSFrançois Tigeot 2848a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 4); 2849e3adcf8fSFrançois Tigeot if (ret) 2850e3adcf8fSFrançois Tigeot return ret; 2851e3adcf8fSFrançois Tigeot 2852e3adcf8fSFrançois Tigeot cmd = MI_FLUSH_DW; 2853*1487f786SFrançois Tigeot if (INTEL_GEN(req->i915) >= 8) 28549edbd4a0SFrançois Tigeot cmd += 1; 28552c9916cdSFrançois Tigeot 28562c9916cdSFrançois Tigeot /* We always require a command barrier so that subsequent 28572c9916cdSFrançois Tigeot * commands, such as breadcrumb interrupts, are strictly ordered 28582c9916cdSFrançois Tigeot * wrt the contents of the write cache being flushed to memory 28592c9916cdSFrançois Tigeot * (and thus being coherent from the CPU). 28602c9916cdSFrançois Tigeot */ 28612c9916cdSFrançois Tigeot cmd |= MI_FLUSH_DW_STORE_INDEX | MI_FLUSH_DW_OP_STOREDW; 28622c9916cdSFrançois Tigeot 2863b5c29a34SFrançois Tigeot /* 2864b5c29a34SFrançois Tigeot * Bspec vol 1c.3 - blitter engine command streamer: 2865b5c29a34SFrançois Tigeot * "If ENABLED, all TLBs will be invalidated once the flush 2866b5c29a34SFrançois Tigeot * operation is complete. This bit is only valid when the 2867b5c29a34SFrançois Tigeot * Post-Sync Operation field is a value of 1h or 3h." 2868b5c29a34SFrançois Tigeot */ 2869e3adcf8fSFrançois Tigeot if (invalidate & I915_GEM_DOMAIN_RENDER) 28702c9916cdSFrançois Tigeot cmd |= MI_INVALIDATE_TLB; 28718621f407SFrançois Tigeot intel_ring_emit(engine, cmd); 28728621f407SFrançois Tigeot intel_ring_emit(engine, 28738621f407SFrançois Tigeot I915_GEM_HWS_SCRATCH_ADDR | MI_FLUSH_DW_USE_GTT); 2874*1487f786SFrançois Tigeot if (INTEL_GEN(req->i915) >= 8) { 28758621f407SFrançois Tigeot intel_ring_emit(engine, 0); /* upper addr */ 28768621f407SFrançois Tigeot intel_ring_emit(engine, 0); /* value */ 28779edbd4a0SFrançois Tigeot } else { 28788621f407SFrançois Tigeot intel_ring_emit(engine, 0); 28798621f407SFrançois Tigeot intel_ring_emit(engine, MI_NOOP); 28809edbd4a0SFrançois Tigeot } 28818621f407SFrançois Tigeot intel_ring_advance(engine); 28825d0b1887SFrançois Tigeot 2883e3adcf8fSFrançois Tigeot return 0; 2884e3adcf8fSFrançois Tigeot } 2885e3adcf8fSFrançois Tigeot 2886*1487f786SFrançois Tigeot static void intel_ring_init_semaphores(struct drm_i915_private *dev_priv, 2887*1487f786SFrançois Tigeot struct intel_engine_cs *engine) 2888*1487f786SFrançois Tigeot { 2889*1487f786SFrançois Tigeot struct drm_i915_gem_object *obj; 2890*1487f786SFrançois Tigeot int ret, i; 2891*1487f786SFrançois Tigeot 2892*1487f786SFrançois Tigeot if (!i915_semaphore_is_enabled(dev_priv)) 2893*1487f786SFrançois Tigeot return; 2894*1487f786SFrançois Tigeot 2895*1487f786SFrançois Tigeot if (INTEL_GEN(dev_priv) >= 8 && !dev_priv->semaphore_obj) { 2896*1487f786SFrançois Tigeot obj = i915_gem_object_create(dev_priv->dev, 4096); 2897*1487f786SFrançois Tigeot if (IS_ERR(obj)) { 2898*1487f786SFrançois Tigeot DRM_ERROR("Failed to allocate semaphore bo. Disabling semaphores\n"); 2899*1487f786SFrançois Tigeot i915.semaphores = 0; 2900*1487f786SFrançois Tigeot } else { 2901*1487f786SFrançois Tigeot i915_gem_object_set_cache_level(obj, I915_CACHE_LLC); 2902*1487f786SFrançois Tigeot ret = i915_gem_obj_ggtt_pin(obj, 0, PIN_NONBLOCK); 2903*1487f786SFrançois Tigeot if (ret != 0) { 2904*1487f786SFrançois Tigeot drm_gem_object_unreference(&obj->base); 2905*1487f786SFrançois Tigeot DRM_ERROR("Failed to pin semaphore bo. Disabling semaphores\n"); 2906*1487f786SFrançois Tigeot i915.semaphores = 0; 2907*1487f786SFrançois Tigeot } else { 2908*1487f786SFrançois Tigeot dev_priv->semaphore_obj = obj; 2909*1487f786SFrançois Tigeot } 2910*1487f786SFrançois Tigeot } 2911*1487f786SFrançois Tigeot } 2912*1487f786SFrançois Tigeot 2913*1487f786SFrançois Tigeot if (!i915_semaphore_is_enabled(dev_priv)) 2914*1487f786SFrançois Tigeot return; 2915*1487f786SFrançois Tigeot 2916*1487f786SFrançois Tigeot if (INTEL_GEN(dev_priv) >= 8) { 2917*1487f786SFrançois Tigeot u64 offset = i915_gem_obj_ggtt_offset(dev_priv->semaphore_obj); 2918*1487f786SFrançois Tigeot 2919*1487f786SFrançois Tigeot engine->semaphore.sync_to = gen8_ring_sync; 2920*1487f786SFrançois Tigeot engine->semaphore.signal = gen8_xcs_signal; 2921*1487f786SFrançois Tigeot 2922*1487f786SFrançois Tigeot for (i = 0; i < I915_NUM_ENGINES; i++) { 2923*1487f786SFrançois Tigeot u64 ring_offset; 2924*1487f786SFrançois Tigeot 2925*1487f786SFrançois Tigeot if (i != engine->id) 2926*1487f786SFrançois Tigeot ring_offset = offset + GEN8_SEMAPHORE_OFFSET(engine->id, i); 2927*1487f786SFrançois Tigeot else 2928*1487f786SFrançois Tigeot ring_offset = MI_SEMAPHORE_SYNC_INVALID; 2929*1487f786SFrançois Tigeot 2930*1487f786SFrançois Tigeot engine->semaphore.signal_ggtt[i] = ring_offset; 2931*1487f786SFrançois Tigeot } 2932*1487f786SFrançois Tigeot } else if (INTEL_GEN(dev_priv) >= 6) { 2933*1487f786SFrançois Tigeot engine->semaphore.sync_to = gen6_ring_sync; 2934*1487f786SFrançois Tigeot engine->semaphore.signal = gen6_signal; 2935*1487f786SFrançois Tigeot 2936*1487f786SFrançois Tigeot /* 2937*1487f786SFrançois Tigeot * The current semaphore is only applied on pre-gen8 2938*1487f786SFrançois Tigeot * platform. And there is no VCS2 ring on the pre-gen8 2939*1487f786SFrançois Tigeot * platform. So the semaphore between RCS and VCS2 is 2940*1487f786SFrançois Tigeot * initialized as INVALID. Gen8 will initialize the 2941*1487f786SFrançois Tigeot * sema between VCS2 and RCS later. 2942*1487f786SFrançois Tigeot */ 2943*1487f786SFrançois Tigeot for (i = 0; i < I915_NUM_ENGINES; i++) { 2944*1487f786SFrançois Tigeot static const struct { 2945*1487f786SFrançois Tigeot u32 wait_mbox; 2946*1487f786SFrançois Tigeot i915_reg_t mbox_reg; 2947*1487f786SFrançois Tigeot } sem_data[I915_NUM_ENGINES][I915_NUM_ENGINES] = { 2948*1487f786SFrançois Tigeot [RCS] = { 2949*1487f786SFrançois Tigeot [VCS] = { .wait_mbox = MI_SEMAPHORE_SYNC_RV, .mbox_reg = GEN6_VRSYNC }, 2950*1487f786SFrançois Tigeot [BCS] = { .wait_mbox = MI_SEMAPHORE_SYNC_RB, .mbox_reg = GEN6_BRSYNC }, 2951*1487f786SFrançois Tigeot [VECS] = { .wait_mbox = MI_SEMAPHORE_SYNC_RVE, .mbox_reg = GEN6_VERSYNC }, 2952*1487f786SFrançois Tigeot }, 2953*1487f786SFrançois Tigeot [VCS] = { 2954*1487f786SFrançois Tigeot [RCS] = { .wait_mbox = MI_SEMAPHORE_SYNC_VR, .mbox_reg = GEN6_RVSYNC }, 2955*1487f786SFrançois Tigeot [BCS] = { .wait_mbox = MI_SEMAPHORE_SYNC_VB, .mbox_reg = GEN6_BVSYNC }, 2956*1487f786SFrançois Tigeot [VECS] = { .wait_mbox = MI_SEMAPHORE_SYNC_VVE, .mbox_reg = GEN6_VEVSYNC }, 2957*1487f786SFrançois Tigeot }, 2958*1487f786SFrançois Tigeot [BCS] = { 2959*1487f786SFrançois Tigeot [RCS] = { .wait_mbox = MI_SEMAPHORE_SYNC_BR, .mbox_reg = GEN6_RBSYNC }, 2960*1487f786SFrançois Tigeot [VCS] = { .wait_mbox = MI_SEMAPHORE_SYNC_BV, .mbox_reg = GEN6_VBSYNC }, 2961*1487f786SFrançois Tigeot [VECS] = { .wait_mbox = MI_SEMAPHORE_SYNC_BVE, .mbox_reg = GEN6_VEBSYNC }, 2962*1487f786SFrançois Tigeot }, 2963*1487f786SFrançois Tigeot [VECS] = { 2964*1487f786SFrançois Tigeot [RCS] = { .wait_mbox = MI_SEMAPHORE_SYNC_VER, .mbox_reg = GEN6_RVESYNC }, 2965*1487f786SFrançois Tigeot [VCS] = { .wait_mbox = MI_SEMAPHORE_SYNC_VEV, .mbox_reg = GEN6_VVESYNC }, 2966*1487f786SFrançois Tigeot [BCS] = { .wait_mbox = MI_SEMAPHORE_SYNC_VEB, .mbox_reg = GEN6_BVESYNC }, 2967*1487f786SFrançois Tigeot }, 2968*1487f786SFrançois Tigeot }; 2969*1487f786SFrançois Tigeot u32 wait_mbox; 2970*1487f786SFrançois Tigeot i915_reg_t mbox_reg; 2971*1487f786SFrançois Tigeot 2972*1487f786SFrançois Tigeot if (i == engine->id || i == VCS2) { 2973*1487f786SFrançois Tigeot wait_mbox = MI_SEMAPHORE_SYNC_INVALID; 2974*1487f786SFrançois Tigeot mbox_reg = GEN6_NOSYNC; 2975*1487f786SFrançois Tigeot } else { 2976*1487f786SFrançois Tigeot wait_mbox = sem_data[engine->id][i].wait_mbox; 2977*1487f786SFrançois Tigeot mbox_reg = sem_data[engine->id][i].mbox_reg; 2978*1487f786SFrançois Tigeot } 2979*1487f786SFrançois Tigeot 2980*1487f786SFrançois Tigeot engine->semaphore.mbox.wait[i] = wait_mbox; 2981*1487f786SFrançois Tigeot engine->semaphore.mbox.signal[i] = mbox_reg; 2982*1487f786SFrançois Tigeot } 2983*1487f786SFrançois Tigeot } 2984*1487f786SFrançois Tigeot } 2985*1487f786SFrançois Tigeot 2986*1487f786SFrançois Tigeot static void intel_ring_init_irq(struct drm_i915_private *dev_priv, 2987*1487f786SFrançois Tigeot struct intel_engine_cs *engine) 2988*1487f786SFrançois Tigeot { 2989*1487f786SFrançois Tigeot if (INTEL_GEN(dev_priv) >= 8) { 2990*1487f786SFrançois Tigeot engine->irq_get = gen8_ring_get_irq; 2991*1487f786SFrançois Tigeot engine->irq_put = gen8_ring_put_irq; 2992*1487f786SFrançois Tigeot engine->irq_seqno_barrier = gen6_seqno_barrier; 2993*1487f786SFrançois Tigeot } else if (INTEL_GEN(dev_priv) >= 6) { 2994*1487f786SFrançois Tigeot engine->irq_get = gen6_ring_get_irq; 2995*1487f786SFrançois Tigeot engine->irq_put = gen6_ring_put_irq; 2996*1487f786SFrançois Tigeot engine->irq_seqno_barrier = gen6_seqno_barrier; 2997*1487f786SFrançois Tigeot } else if (INTEL_GEN(dev_priv) >= 5) { 2998*1487f786SFrançois Tigeot engine->irq_get = gen5_ring_get_irq; 2999*1487f786SFrançois Tigeot engine->irq_put = gen5_ring_put_irq; 3000*1487f786SFrançois Tigeot } else if (INTEL_GEN(dev_priv) >= 3) { 3001*1487f786SFrançois Tigeot engine->irq_get = i9xx_ring_get_irq; 3002*1487f786SFrançois Tigeot engine->irq_put = i9xx_ring_put_irq; 3003*1487f786SFrançois Tigeot } else { 3004*1487f786SFrançois Tigeot engine->irq_get = i8xx_ring_get_irq; 3005*1487f786SFrançois Tigeot engine->irq_put = i8xx_ring_put_irq; 3006*1487f786SFrançois Tigeot } 3007*1487f786SFrançois Tigeot } 3008*1487f786SFrançois Tigeot 3009*1487f786SFrançois Tigeot static void intel_ring_default_vfuncs(struct drm_i915_private *dev_priv, 3010*1487f786SFrançois Tigeot struct intel_engine_cs *engine) 3011*1487f786SFrançois Tigeot { 3012*1487f786SFrançois Tigeot engine->init_hw = init_ring_common; 3013*1487f786SFrançois Tigeot engine->write_tail = ring_write_tail; 3014*1487f786SFrançois Tigeot engine->get_seqno = ring_get_seqno; 3015*1487f786SFrançois Tigeot engine->set_seqno = ring_set_seqno; 3016*1487f786SFrançois Tigeot 3017*1487f786SFrançois Tigeot engine->add_request = i9xx_add_request; 3018*1487f786SFrançois Tigeot if (INTEL_GEN(dev_priv) >= 6) 3019*1487f786SFrançois Tigeot engine->add_request = gen6_add_request; 3020*1487f786SFrançois Tigeot 3021*1487f786SFrançois Tigeot if (INTEL_GEN(dev_priv) >= 8) 3022*1487f786SFrançois Tigeot engine->dispatch_execbuffer = gen8_ring_dispatch_execbuffer; 3023*1487f786SFrançois Tigeot else if (INTEL_GEN(dev_priv) >= 6) 3024*1487f786SFrançois Tigeot engine->dispatch_execbuffer = gen6_ring_dispatch_execbuffer; 3025*1487f786SFrançois Tigeot else if (INTEL_GEN(dev_priv) >= 4) 3026*1487f786SFrançois Tigeot engine->dispatch_execbuffer = i965_dispatch_execbuffer; 3027*1487f786SFrançois Tigeot else if (IS_I830(dev_priv) || IS_845G(dev_priv)) 3028*1487f786SFrançois Tigeot engine->dispatch_execbuffer = i830_dispatch_execbuffer; 3029*1487f786SFrançois Tigeot else 3030*1487f786SFrançois Tigeot engine->dispatch_execbuffer = i915_dispatch_execbuffer; 3031*1487f786SFrançois Tigeot 3032*1487f786SFrançois Tigeot intel_ring_init_irq(dev_priv, engine); 3033*1487f786SFrançois Tigeot intel_ring_init_semaphores(dev_priv, engine); 3034*1487f786SFrançois Tigeot } 3035*1487f786SFrançois Tigeot 3036e3adcf8fSFrançois Tigeot int intel_init_render_ring_buffer(struct drm_device *dev) 3037e3adcf8fSFrançois Tigeot { 3038ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 30398621f407SFrançois Tigeot struct intel_engine_cs *engine = &dev_priv->engine[RCS]; 304024edb884SFrançois Tigeot struct drm_i915_gem_object *obj; 304124edb884SFrançois Tigeot int ret; 3042e3adcf8fSFrançois Tigeot 30438621f407SFrançois Tigeot engine->name = "render ring"; 30448621f407SFrançois Tigeot engine->id = RCS; 30458621f407SFrançois Tigeot engine->exec_id = I915_EXEC_RENDER; 30468621f407SFrançois Tigeot engine->hw_id = 0; 30478621f407SFrançois Tigeot engine->mmio_base = RENDER_RING_BASE; 3048686a02f1SFrançois Tigeot 3049*1487f786SFrançois Tigeot intel_ring_default_vfuncs(dev_priv, engine); 30502c9916cdSFrançois Tigeot 3051*1487f786SFrançois Tigeot if (INTEL_GEN(dev_priv) >= 8) { 30528621f407SFrançois Tigeot engine->init_context = intel_rcs_ctx_init; 3053*1487f786SFrançois Tigeot engine->add_request = gen8_render_add_request; 30548621f407SFrançois Tigeot engine->flush = gen8_render_ring_flush; 30558621f407SFrançois Tigeot engine->irq_enable_mask = GT_RENDER_USER_INTERRUPT; 3056*1487f786SFrançois Tigeot if (i915_semaphore_is_enabled(dev_priv)) 30578621f407SFrançois Tigeot engine->semaphore.signal = gen8_rcs_signal; 3058*1487f786SFrançois Tigeot } else if (INTEL_GEN(dev_priv) >= 6) { 30598621f407SFrançois Tigeot engine->init_context = intel_rcs_ctx_init; 30608621f407SFrançois Tigeot engine->flush = gen7_render_ring_flush; 3061*1487f786SFrançois Tigeot if (IS_GEN6(dev_priv)) 30628621f407SFrançois Tigeot engine->flush = gen6_render_ring_flush; 30638621f407SFrançois Tigeot engine->irq_enable_mask = GT_RENDER_USER_INTERRUPT; 3064*1487f786SFrançois Tigeot } else if (IS_GEN5(dev_priv)) { 30658621f407SFrançois Tigeot engine->add_request = pc_render_add_request; 30668621f407SFrançois Tigeot engine->flush = gen4_render_ring_flush; 30678621f407SFrançois Tigeot engine->get_seqno = pc_render_get_seqno; 30688621f407SFrançois Tigeot engine->set_seqno = pc_render_set_seqno; 30698621f407SFrançois Tigeot engine->irq_enable_mask = GT_RENDER_USER_INTERRUPT | 30705d0b1887SFrançois Tigeot GT_RENDER_PIPECTL_NOTIFY_INTERRUPT; 3071686a02f1SFrançois Tigeot } else { 3072*1487f786SFrançois Tigeot if (INTEL_GEN(dev_priv) < 4) 30738621f407SFrançois Tigeot engine->flush = gen2_render_ring_flush; 3074686a02f1SFrançois Tigeot else 30758621f407SFrançois Tigeot engine->flush = gen4_render_ring_flush; 30768621f407SFrançois Tigeot engine->irq_enable_mask = I915_USER_INTERRUPT; 3077686a02f1SFrançois Tigeot } 307824edb884SFrançois Tigeot 3079*1487f786SFrançois Tigeot if (IS_HASWELL(dev_priv)) 30808621f407SFrançois Tigeot engine->dispatch_execbuffer = hsw_ring_dispatch_execbuffer; 3081*1487f786SFrançois Tigeot 30828621f407SFrançois Tigeot engine->init_hw = init_render_ring; 30838621f407SFrançois Tigeot engine->cleanup = render_ring_cleanup; 3084e3adcf8fSFrançois Tigeot 3085b5c29a34SFrançois Tigeot /* Workaround batchbuffer to combat CS tlb bug. */ 3086*1487f786SFrançois Tigeot if (HAS_BROKEN_CS_TLB(dev_priv)) { 3087*1487f786SFrançois Tigeot obj = i915_gem_object_create(dev, I830_WA_SIZE); 3088*1487f786SFrançois Tigeot if (IS_ERR(obj)) { 3089b5c29a34SFrançois Tigeot DRM_ERROR("Failed to allocate batch bo\n"); 3090*1487f786SFrançois Tigeot return PTR_ERR(obj); 3091b5c29a34SFrançois Tigeot } 3092b5c29a34SFrançois Tigeot 3093ba55f2f5SFrançois Tigeot ret = i915_gem_obj_ggtt_pin(obj, 0, 0); 3094b5c29a34SFrançois Tigeot if (ret != 0) { 3095b5c29a34SFrançois Tigeot drm_gem_object_unreference(&obj->base); 3096b5c29a34SFrançois Tigeot DRM_ERROR("Failed to ping batch bo\n"); 3097b5c29a34SFrançois Tigeot return ret; 3098b5c29a34SFrançois Tigeot } 3099b5c29a34SFrançois Tigeot 31008621f407SFrançois Tigeot engine->scratch.obj = obj; 31018621f407SFrançois Tigeot engine->scratch.gtt_offset = i915_gem_obj_ggtt_offset(obj); 3102e3adcf8fSFrançois Tigeot } 3103e3adcf8fSFrançois Tigeot 31048621f407SFrançois Tigeot ret = intel_init_ring_buffer(dev, engine); 3105b5c29a34SFrançois Tigeot if (ret) 31062c9916cdSFrançois Tigeot return ret; 31072c9916cdSFrançois Tigeot 3108*1487f786SFrançois Tigeot if (INTEL_GEN(dev_priv) >= 5) { 31098621f407SFrançois Tigeot ret = intel_init_pipe_control(engine); 31102c9916cdSFrançois Tigeot if (ret) 31112c9916cdSFrançois Tigeot return ret; 3112b5c29a34SFrançois Tigeot } 3113b5c29a34SFrançois Tigeot 3114e3adcf8fSFrançois Tigeot return 0; 3115e3adcf8fSFrançois Tigeot } 3116e3adcf8fSFrançois Tigeot 3117e3adcf8fSFrançois Tigeot int intel_init_bsd_ring_buffer(struct drm_device *dev) 3118e3adcf8fSFrançois Tigeot { 3119ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 31208621f407SFrançois Tigeot struct intel_engine_cs *engine = &dev_priv->engine[VCS]; 3121e3adcf8fSFrançois Tigeot 31228621f407SFrançois Tigeot engine->name = "bsd ring"; 31238621f407SFrançois Tigeot engine->id = VCS; 31248621f407SFrançois Tigeot engine->exec_id = I915_EXEC_BSD; 31258621f407SFrançois Tigeot engine->hw_id = 1; 3126686a02f1SFrançois Tigeot 3127*1487f786SFrançois Tigeot intel_ring_default_vfuncs(dev_priv, engine); 3128*1487f786SFrançois Tigeot 3129*1487f786SFrançois Tigeot if (INTEL_GEN(dev_priv) >= 6) { 31308621f407SFrançois Tigeot engine->mmio_base = GEN6_BSD_RING_BASE; 3131686a02f1SFrançois Tigeot /* gen6 bsd needs a special wa for tail updates */ 3132*1487f786SFrançois Tigeot if (IS_GEN6(dev_priv)) 31338621f407SFrançois Tigeot engine->write_tail = gen6_bsd_ring_write_tail; 31348621f407SFrançois Tigeot engine->flush = gen6_bsd_ring_flush; 3135*1487f786SFrançois Tigeot if (INTEL_GEN(dev_priv) >= 8) 31368621f407SFrançois Tigeot engine->irq_enable_mask = 31379edbd4a0SFrançois Tigeot GT_RENDER_USER_INTERRUPT << GEN8_VCS1_IRQ_SHIFT; 3138*1487f786SFrançois Tigeot else 31398621f407SFrançois Tigeot engine->irq_enable_mask = GT_BSD_USER_INTERRUPT; 3140686a02f1SFrançois Tigeot } else { 31418621f407SFrançois Tigeot engine->mmio_base = BSD_RING_BASE; 31428621f407SFrançois Tigeot engine->flush = bsd_ring_flush; 3143*1487f786SFrançois Tigeot if (IS_GEN5(dev_priv)) 31448621f407SFrançois Tigeot engine->irq_enable_mask = ILK_BSD_USER_INTERRUPT; 3145*1487f786SFrançois Tigeot else 31468621f407SFrançois Tigeot engine->irq_enable_mask = I915_BSD_USER_INTERRUPT; 3147686a02f1SFrançois Tigeot } 3148e3adcf8fSFrançois Tigeot 31498621f407SFrançois Tigeot return intel_init_ring_buffer(dev, engine); 3150e3adcf8fSFrançois Tigeot } 3151e3adcf8fSFrançois Tigeot 3152ba55f2f5SFrançois Tigeot /** 3153477eb7f9SFrançois Tigeot * Initialize the second BSD ring (eg. Broadwell GT3, Skylake GT3) 3154ba55f2f5SFrançois Tigeot */ 3155ba55f2f5SFrançois Tigeot int intel_init_bsd2_ring_buffer(struct drm_device *dev) 3156ba55f2f5SFrançois Tigeot { 3157ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 31588621f407SFrançois Tigeot struct intel_engine_cs *engine = &dev_priv->engine[VCS2]; 3159ba55f2f5SFrançois Tigeot 31608621f407SFrançois Tigeot engine->name = "bsd2 ring"; 31618621f407SFrançois Tigeot engine->id = VCS2; 31628621f407SFrançois Tigeot engine->exec_id = I915_EXEC_BSD; 31638621f407SFrançois Tigeot engine->hw_id = 4; 31648621f407SFrançois Tigeot engine->mmio_base = GEN8_BSD2_RING_BASE; 3165*1487f786SFrançois Tigeot 3166*1487f786SFrançois Tigeot intel_ring_default_vfuncs(dev_priv, engine); 3167*1487f786SFrançois Tigeot 31688621f407SFrançois Tigeot engine->flush = gen6_bsd_ring_flush; 31698621f407SFrançois Tigeot engine->irq_enable_mask = 3170ba55f2f5SFrançois Tigeot GT_RENDER_USER_INTERRUPT << GEN8_VCS2_IRQ_SHIFT; 3171ba55f2f5SFrançois Tigeot 31728621f407SFrançois Tigeot return intel_init_ring_buffer(dev, engine); 3173ba55f2f5SFrançois Tigeot } 3174ba55f2f5SFrançois Tigeot 3175e3adcf8fSFrançois Tigeot int intel_init_blt_ring_buffer(struct drm_device *dev) 3176e3adcf8fSFrançois Tigeot { 3177ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 31788621f407SFrançois Tigeot struct intel_engine_cs *engine = &dev_priv->engine[BCS]; 3179e3adcf8fSFrançois Tigeot 31808621f407SFrançois Tigeot engine->name = "blitter ring"; 31818621f407SFrançois Tigeot engine->id = BCS; 31828621f407SFrançois Tigeot engine->exec_id = I915_EXEC_BLT; 31838621f407SFrançois Tigeot engine->hw_id = 2; 31848621f407SFrançois Tigeot engine->mmio_base = BLT_RING_BASE; 3185*1487f786SFrançois Tigeot 3186*1487f786SFrançois Tigeot intel_ring_default_vfuncs(dev_priv, engine); 3187*1487f786SFrançois Tigeot 31888621f407SFrançois Tigeot engine->flush = gen6_ring_flush; 3189*1487f786SFrançois Tigeot if (INTEL_GEN(dev_priv) >= 8) 31908621f407SFrançois Tigeot engine->irq_enable_mask = 31919edbd4a0SFrançois Tigeot GT_RENDER_USER_INTERRUPT << GEN8_BCS_IRQ_SHIFT; 3192*1487f786SFrançois Tigeot else 31938621f407SFrançois Tigeot engine->irq_enable_mask = GT_BLT_USER_INTERRUPT; 31945d0b1887SFrançois Tigeot 31958621f407SFrançois Tigeot return intel_init_ring_buffer(dev, engine); 31965d0b1887SFrançois Tigeot } 31975d0b1887SFrançois Tigeot 31985d0b1887SFrançois Tigeot int intel_init_vebox_ring_buffer(struct drm_device *dev) 31995d0b1887SFrançois Tigeot { 3200ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 32018621f407SFrançois Tigeot struct intel_engine_cs *engine = &dev_priv->engine[VECS]; 32025d0b1887SFrançois Tigeot 32038621f407SFrançois Tigeot engine->name = "video enhancement ring"; 32048621f407SFrançois Tigeot engine->id = VECS; 32058621f407SFrançois Tigeot engine->exec_id = I915_EXEC_VEBOX; 32068621f407SFrançois Tigeot engine->hw_id = 3; 32078621f407SFrançois Tigeot engine->mmio_base = VEBOX_RING_BASE; 32089edbd4a0SFrançois Tigeot 3209*1487f786SFrançois Tigeot intel_ring_default_vfuncs(dev_priv, engine); 3210*1487f786SFrançois Tigeot 3211*1487f786SFrançois Tigeot engine->flush = gen6_ring_flush; 3212*1487f786SFrançois Tigeot 3213*1487f786SFrançois Tigeot if (INTEL_GEN(dev_priv) >= 8) { 32148621f407SFrançois Tigeot engine->irq_enable_mask = 32159edbd4a0SFrançois Tigeot GT_RENDER_USER_INTERRUPT << GEN8_VECS_IRQ_SHIFT; 32169edbd4a0SFrançois Tigeot } else { 32178621f407SFrançois Tigeot engine->irq_enable_mask = PM_VEBOX_USER_INTERRUPT; 32188621f407SFrançois Tigeot engine->irq_get = hsw_vebox_get_irq; 32198621f407SFrançois Tigeot engine->irq_put = hsw_vebox_put_irq; 322024edb884SFrançois Tigeot } 3221e3adcf8fSFrançois Tigeot 32228621f407SFrançois Tigeot return intel_init_ring_buffer(dev, engine); 3223e3adcf8fSFrançois Tigeot } 3224b030f26bSFrançois Tigeot 3225b030f26bSFrançois Tigeot int 3226a05eeebfSFrançois Tigeot intel_ring_flush_all_caches(struct drm_i915_gem_request *req) 3227b030f26bSFrançois Tigeot { 32288621f407SFrançois Tigeot struct intel_engine_cs *engine = req->engine; 3229b030f26bSFrançois Tigeot int ret; 3230b030f26bSFrançois Tigeot 32318621f407SFrançois Tigeot if (!engine->gpu_caches_dirty) 3232b030f26bSFrançois Tigeot return 0; 3233b030f26bSFrançois Tigeot 32348621f407SFrançois Tigeot ret = engine->flush(req, 0, I915_GEM_GPU_DOMAINS); 3235b030f26bSFrançois Tigeot if (ret) 3236b030f26bSFrançois Tigeot return ret; 3237b030f26bSFrançois Tigeot 3238a05eeebfSFrançois Tigeot trace_i915_gem_ring_flush(req, 0, I915_GEM_GPU_DOMAINS); 3239a2fdbec6SFrançois Tigeot 32408621f407SFrançois Tigeot engine->gpu_caches_dirty = false; 3241b030f26bSFrançois Tigeot return 0; 3242b030f26bSFrançois Tigeot } 3243b030f26bSFrançois Tigeot 3244b030f26bSFrançois Tigeot int 3245a05eeebfSFrançois Tigeot intel_ring_invalidate_all_caches(struct drm_i915_gem_request *req) 3246b030f26bSFrançois Tigeot { 32478621f407SFrançois Tigeot struct intel_engine_cs *engine = req->engine; 3248b030f26bSFrançois Tigeot uint32_t flush_domains; 3249b030f26bSFrançois Tigeot int ret; 3250b030f26bSFrançois Tigeot 3251b030f26bSFrançois Tigeot flush_domains = 0; 32528621f407SFrançois Tigeot if (engine->gpu_caches_dirty) 3253b030f26bSFrançois Tigeot flush_domains = I915_GEM_GPU_DOMAINS; 3254b030f26bSFrançois Tigeot 32558621f407SFrançois Tigeot ret = engine->flush(req, I915_GEM_GPU_DOMAINS, flush_domains); 3256b030f26bSFrançois Tigeot if (ret) 3257b030f26bSFrançois Tigeot return ret; 3258b030f26bSFrançois Tigeot 3259a05eeebfSFrançois Tigeot trace_i915_gem_ring_flush(req, I915_GEM_GPU_DOMAINS, flush_domains); 3260a2fdbec6SFrançois Tigeot 32618621f407SFrançois Tigeot engine->gpu_caches_dirty = false; 3262b030f26bSFrançois Tigeot return 0; 3263b030f26bSFrançois Tigeot } 3264ba55f2f5SFrançois Tigeot 3265ba55f2f5SFrançois Tigeot void 32668621f407SFrançois Tigeot intel_stop_engine(struct intel_engine_cs *engine) 3267ba55f2f5SFrançois Tigeot { 3268ba55f2f5SFrançois Tigeot int ret; 3269ba55f2f5SFrançois Tigeot 32708621f407SFrançois Tigeot if (!intel_engine_initialized(engine)) 3271ba55f2f5SFrançois Tigeot return; 3272ba55f2f5SFrançois Tigeot 32738621f407SFrançois Tigeot ret = intel_engine_idle(engine); 32748621f407SFrançois Tigeot if (ret) 3275ba55f2f5SFrançois Tigeot DRM_ERROR("failed to quiesce %s whilst cleaning up: %d\n", 32768621f407SFrançois Tigeot engine->name, ret); 3277ba55f2f5SFrançois Tigeot 32788621f407SFrançois Tigeot stop_ring(engine); 3279ba55f2f5SFrançois Tigeot } 3280