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 371b13d190SFrançois Tigeot int __intel_ring_space(int head, int tail, int size) 38e3adcf8fSFrançois Tigeot { 392c9916cdSFrançois Tigeot int space = head - tail; 402c9916cdSFrançois Tigeot if (space <= 0) 41ba55f2f5SFrançois Tigeot space += size; 422c9916cdSFrançois Tigeot return space - I915_RING_FREE_SPACE; 432c9916cdSFrançois Tigeot } 442c9916cdSFrançois Tigeot 452c9916cdSFrançois Tigeot void intel_ring_update_space(struct intel_ringbuffer *ringbuf) 462c9916cdSFrançois Tigeot { 472c9916cdSFrançois Tigeot if (ringbuf->last_retired_head != -1) { 482c9916cdSFrançois Tigeot ringbuf->head = ringbuf->last_retired_head; 492c9916cdSFrançois Tigeot ringbuf->last_retired_head = -1; 502c9916cdSFrançois Tigeot } 512c9916cdSFrançois Tigeot 522c9916cdSFrançois Tigeot ringbuf->space = __intel_ring_space(ringbuf->head & HEAD_ADDR, 532c9916cdSFrançois Tigeot ringbuf->tail, ringbuf->size); 54e3adcf8fSFrançois Tigeot } 55e3adcf8fSFrançois Tigeot 568621f407SFrançois Tigeot bool intel_engine_stopped(struct intel_engine_cs *engine) 57ba55f2f5SFrançois Tigeot { 588621f407SFrançois Tigeot struct drm_i915_private *dev_priv = engine->dev->dev_private; 598621f407SFrançois Tigeot return dev_priv->gpu_error.stop_rings & intel_engine_flag(engine); 60ba55f2f5SFrançois Tigeot } 61ba55f2f5SFrançois Tigeot 628621f407SFrançois Tigeot static void __intel_ring_advance(struct intel_engine_cs *engine) 639edbd4a0SFrançois Tigeot { 648621f407SFrançois Tigeot struct intel_ringbuffer *ringbuf = engine->buffer; 65ba55f2f5SFrançois Tigeot ringbuf->tail &= ringbuf->size - 1; 668621f407SFrançois Tigeot if (intel_engine_stopped(engine)) 679edbd4a0SFrançois Tigeot return; 688621f407SFrançois Tigeot engine->write_tail(engine, ringbuf->tail); 699edbd4a0SFrançois Tigeot } 709edbd4a0SFrançois Tigeot 71e3adcf8fSFrançois Tigeot static int 72a05eeebfSFrançois Tigeot gen2_render_ring_flush(struct drm_i915_gem_request *req, 73686a02f1SFrançois Tigeot u32 invalidate_domains, 74686a02f1SFrançois Tigeot u32 flush_domains) 75686a02f1SFrançois Tigeot { 768621f407SFrançois Tigeot struct intel_engine_cs *engine = req->engine; 77686a02f1SFrançois Tigeot u32 cmd; 78686a02f1SFrançois Tigeot int ret; 79686a02f1SFrançois Tigeot 80686a02f1SFrançois Tigeot cmd = MI_FLUSH; 81686a02f1SFrançois Tigeot if (((invalidate_domains|flush_domains) & I915_GEM_DOMAIN_RENDER) == 0) 82686a02f1SFrançois Tigeot cmd |= MI_NO_WRITE_FLUSH; 83686a02f1SFrançois Tigeot 84686a02f1SFrançois Tigeot if (invalidate_domains & I915_GEM_DOMAIN_SAMPLER) 85686a02f1SFrançois Tigeot cmd |= MI_READ_FLUSH; 86686a02f1SFrançois Tigeot 87a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 2); 88686a02f1SFrançois Tigeot if (ret) 89686a02f1SFrançois Tigeot return ret; 90686a02f1SFrançois Tigeot 918621f407SFrançois Tigeot intel_ring_emit(engine, cmd); 928621f407SFrançois Tigeot intel_ring_emit(engine, MI_NOOP); 938621f407SFrançois Tigeot intel_ring_advance(engine); 94686a02f1SFrançois Tigeot 95686a02f1SFrançois Tigeot return 0; 96686a02f1SFrançois Tigeot } 97686a02f1SFrançois Tigeot 98686a02f1SFrançois Tigeot static int 99a05eeebfSFrançois Tigeot gen4_render_ring_flush(struct drm_i915_gem_request *req, 100686a02f1SFrançois Tigeot u32 invalidate_domains, 101686a02f1SFrançois Tigeot u32 flush_domains) 102e3adcf8fSFrançois Tigeot { 1038621f407SFrançois Tigeot struct intel_engine_cs *engine = req->engine; 1048621f407SFrançois Tigeot struct drm_device *dev = engine->dev; 105686a02f1SFrançois Tigeot u32 cmd; 106e3adcf8fSFrançois Tigeot int ret; 107e3adcf8fSFrançois Tigeot 108e3adcf8fSFrançois Tigeot /* 109e3adcf8fSFrançois Tigeot * read/write caches: 110e3adcf8fSFrançois Tigeot * 111e3adcf8fSFrançois Tigeot * I915_GEM_DOMAIN_RENDER is always invalidated, but is 112e3adcf8fSFrançois Tigeot * only flushed if MI_NO_WRITE_FLUSH is unset. On 965, it is 113e3adcf8fSFrançois Tigeot * also flushed at 2d versus 3d pipeline switches. 114e3adcf8fSFrançois Tigeot * 115e3adcf8fSFrançois Tigeot * read-only caches: 116e3adcf8fSFrançois Tigeot * 117e3adcf8fSFrançois Tigeot * I915_GEM_DOMAIN_SAMPLER is flushed on pre-965 if 118e3adcf8fSFrançois Tigeot * MI_READ_FLUSH is set, and is always flushed on 965. 119e3adcf8fSFrançois Tigeot * 120e3adcf8fSFrançois Tigeot * I915_GEM_DOMAIN_COMMAND may not exist? 121e3adcf8fSFrançois Tigeot * 122e3adcf8fSFrançois Tigeot * I915_GEM_DOMAIN_INSTRUCTION, which exists on 965, is 123e3adcf8fSFrançois Tigeot * invalidated when MI_EXE_FLUSH is set. 124e3adcf8fSFrançois Tigeot * 125e3adcf8fSFrançois Tigeot * I915_GEM_DOMAIN_VERTEX, which exists on 965, is 126e3adcf8fSFrançois Tigeot * invalidated with every MI_FLUSH. 127e3adcf8fSFrançois Tigeot * 128e3adcf8fSFrançois Tigeot * TLBs: 129e3adcf8fSFrançois Tigeot * 130e3adcf8fSFrançois Tigeot * On 965, TLBs associated with I915_GEM_DOMAIN_COMMAND 131e3adcf8fSFrançois Tigeot * and I915_GEM_DOMAIN_CPU in are invalidated at PTE write and 132e3adcf8fSFrançois Tigeot * I915_GEM_DOMAIN_RENDER and I915_GEM_DOMAIN_SAMPLER 133e3adcf8fSFrançois Tigeot * are flushed at any MI_FLUSH. 134e3adcf8fSFrançois Tigeot */ 135e3adcf8fSFrançois Tigeot 136e3adcf8fSFrançois Tigeot cmd = MI_FLUSH | MI_NO_WRITE_FLUSH; 137686a02f1SFrançois Tigeot if ((invalidate_domains|flush_domains) & I915_GEM_DOMAIN_RENDER) 138e3adcf8fSFrançois Tigeot cmd &= ~MI_NO_WRITE_FLUSH; 139e3adcf8fSFrançois Tigeot if (invalidate_domains & I915_GEM_DOMAIN_INSTRUCTION) 140e3adcf8fSFrançois Tigeot cmd |= MI_EXE_FLUSH; 141e3adcf8fSFrançois Tigeot 142e3adcf8fSFrançois Tigeot if (invalidate_domains & I915_GEM_DOMAIN_COMMAND && 143e3adcf8fSFrançois Tigeot (IS_G4X(dev) || IS_GEN5(dev))) 144e3adcf8fSFrançois Tigeot cmd |= MI_INVALIDATE_ISP; 145e3adcf8fSFrançois Tigeot 146a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 2); 147e3adcf8fSFrançois Tigeot if (ret) 148e3adcf8fSFrançois Tigeot return ret; 149e3adcf8fSFrançois Tigeot 1508621f407SFrançois Tigeot intel_ring_emit(engine, cmd); 1518621f407SFrançois Tigeot intel_ring_emit(engine, MI_NOOP); 1528621f407SFrançois Tigeot intel_ring_advance(engine); 153e3adcf8fSFrançois Tigeot 154e3adcf8fSFrançois Tigeot return 0; 155e3adcf8fSFrançois Tigeot } 156e3adcf8fSFrançois Tigeot 157e3adcf8fSFrançois Tigeot /** 158e3adcf8fSFrançois Tigeot * Emits a PIPE_CONTROL with a non-zero post-sync operation, for 159e3adcf8fSFrançois Tigeot * implementing two workarounds on gen6. From section 1.4.7.1 160e3adcf8fSFrançois Tigeot * "PIPE_CONTROL" of the Sandy Bridge PRM volume 2 part 1: 161e3adcf8fSFrançois Tigeot * 162e3adcf8fSFrançois Tigeot * [DevSNB-C+{W/A}] Before any depth stall flush (including those 163e3adcf8fSFrançois Tigeot * produced by non-pipelined state commands), software needs to first 164e3adcf8fSFrançois Tigeot * send a PIPE_CONTROL with no bits set except Post-Sync Operation != 165e3adcf8fSFrançois Tigeot * 0. 166e3adcf8fSFrançois Tigeot * 167e3adcf8fSFrançois Tigeot * [Dev-SNB{W/A}]: Before a PIPE_CONTROL with Write Cache Flush Enable 168e3adcf8fSFrançois Tigeot * =1, a PIPE_CONTROL with any non-zero post-sync-op is required. 169e3adcf8fSFrançois Tigeot * 170e3adcf8fSFrançois Tigeot * And the workaround for these two requires this workaround first: 171e3adcf8fSFrançois Tigeot * 172e3adcf8fSFrançois Tigeot * [Dev-SNB{W/A}]: Pipe-control with CS-stall bit set must be sent 173e3adcf8fSFrançois Tigeot * BEFORE the pipe-control with a post-sync op and no write-cache 174e3adcf8fSFrançois Tigeot * flushes. 175e3adcf8fSFrançois Tigeot * 176e3adcf8fSFrançois Tigeot * And this last workaround is tricky because of the requirements on 177e3adcf8fSFrançois Tigeot * that bit. From section 1.4.7.2.3 "Stall" of the Sandy Bridge PRM 178e3adcf8fSFrançois Tigeot * volume 2 part 1: 179e3adcf8fSFrançois Tigeot * 180e3adcf8fSFrançois Tigeot * "1 of the following must also be set: 181e3adcf8fSFrançois Tigeot * - Render Target Cache Flush Enable ([12] of DW1) 182e3adcf8fSFrançois Tigeot * - Depth Cache Flush Enable ([0] of DW1) 183e3adcf8fSFrançois Tigeot * - Stall at Pixel Scoreboard ([1] of DW1) 184e3adcf8fSFrançois Tigeot * - Depth Stall ([13] of DW1) 185e3adcf8fSFrançois Tigeot * - Post-Sync Operation ([13] of DW1) 186e3adcf8fSFrançois Tigeot * - Notify Enable ([8] of DW1)" 187e3adcf8fSFrançois Tigeot * 188e3adcf8fSFrançois Tigeot * The cache flushes require the workaround flush that triggered this 189e3adcf8fSFrançois Tigeot * one, so we can't use it. Depth stall would trigger the same. 190e3adcf8fSFrançois Tigeot * Post-sync nonzero is what triggered this second workaround, so we 191e3adcf8fSFrançois Tigeot * can't use that one either. Notify enable is IRQs, which aren't 192e3adcf8fSFrançois Tigeot * really our business. That leaves only stall at scoreboard. 193e3adcf8fSFrançois Tigeot */ 194e3adcf8fSFrançois Tigeot static int 195a05eeebfSFrançois Tigeot intel_emit_post_sync_nonzero_flush(struct drm_i915_gem_request *req) 196e3adcf8fSFrançois Tigeot { 1978621f407SFrançois Tigeot struct intel_engine_cs *engine = req->engine; 1988621f407SFrançois Tigeot u32 scratch_addr = engine->scratch.gtt_offset + 2 * CACHELINE_BYTES; 199e3adcf8fSFrançois Tigeot int ret; 200e3adcf8fSFrançois Tigeot 201a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 6); 202e3adcf8fSFrançois Tigeot if (ret) 203e3adcf8fSFrançois Tigeot return ret; 204e3adcf8fSFrançois Tigeot 2058621f407SFrançois Tigeot intel_ring_emit(engine, GFX_OP_PIPE_CONTROL(5)); 2068621f407SFrançois Tigeot intel_ring_emit(engine, PIPE_CONTROL_CS_STALL | 207e3adcf8fSFrançois Tigeot PIPE_CONTROL_STALL_AT_SCOREBOARD); 2088621f407SFrançois Tigeot intel_ring_emit(engine, scratch_addr | PIPE_CONTROL_GLOBAL_GTT); /* address */ 2098621f407SFrançois Tigeot intel_ring_emit(engine, 0); /* low dword */ 2108621f407SFrançois Tigeot intel_ring_emit(engine, 0); /* high dword */ 2118621f407SFrançois Tigeot intel_ring_emit(engine, MI_NOOP); 2128621f407SFrançois Tigeot intel_ring_advance(engine); 213e3adcf8fSFrançois Tigeot 214a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 6); 215e3adcf8fSFrançois Tigeot if (ret) 216e3adcf8fSFrançois Tigeot return ret; 217e3adcf8fSFrançois Tigeot 2188621f407SFrançois Tigeot intel_ring_emit(engine, GFX_OP_PIPE_CONTROL(5)); 2198621f407SFrançois Tigeot intel_ring_emit(engine, PIPE_CONTROL_QW_WRITE); 2208621f407SFrançois Tigeot intel_ring_emit(engine, scratch_addr | PIPE_CONTROL_GLOBAL_GTT); /* address */ 2218621f407SFrançois Tigeot intel_ring_emit(engine, 0); 2228621f407SFrançois Tigeot intel_ring_emit(engine, 0); 2238621f407SFrançois Tigeot intel_ring_emit(engine, MI_NOOP); 2248621f407SFrançois Tigeot intel_ring_advance(engine); 225e3adcf8fSFrançois Tigeot 226e3adcf8fSFrançois Tigeot return 0; 227e3adcf8fSFrançois Tigeot } 228e3adcf8fSFrançois Tigeot 229e3adcf8fSFrançois Tigeot static int 230a05eeebfSFrançois Tigeot gen6_render_ring_flush(struct drm_i915_gem_request *req, 231e3adcf8fSFrançois Tigeot u32 invalidate_domains, u32 flush_domains) 232e3adcf8fSFrançois Tigeot { 2338621f407SFrançois Tigeot struct intel_engine_cs *engine = req->engine; 234e3adcf8fSFrançois Tigeot u32 flags = 0; 2358621f407SFrançois Tigeot u32 scratch_addr = engine->scratch.gtt_offset + 2 * CACHELINE_BYTES; 236e3adcf8fSFrançois Tigeot int ret; 237e3adcf8fSFrançois Tigeot 238e3adcf8fSFrançois Tigeot /* Force SNB workarounds for PIPE_CONTROL flushes */ 239a05eeebfSFrançois Tigeot ret = intel_emit_post_sync_nonzero_flush(req); 240686a02f1SFrançois Tigeot if (ret) 241686a02f1SFrançois Tigeot return ret; 242e3adcf8fSFrançois Tigeot 243e3adcf8fSFrançois Tigeot /* Just flush everything. Experiments have shown that reducing the 244e3adcf8fSFrançois Tigeot * number of bits based on the write domains has little performance 245e3adcf8fSFrançois Tigeot * impact. 246e3adcf8fSFrançois Tigeot */ 247b5c29a34SFrançois Tigeot if (flush_domains) { 248e3adcf8fSFrançois Tigeot flags |= PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH; 249b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_DEPTH_CACHE_FLUSH; 250b5c29a34SFrançois Tigeot /* 251b5c29a34SFrançois Tigeot * Ensure that any following seqno writes only happen 252b5c29a34SFrançois Tigeot * when the render cache is indeed flushed. 253b5c29a34SFrançois Tigeot */ 254b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_CS_STALL; 255b5c29a34SFrançois Tigeot } 256b5c29a34SFrançois Tigeot if (invalidate_domains) { 257686a02f1SFrançois Tigeot flags |= PIPE_CONTROL_TLB_INVALIDATE; 258e3adcf8fSFrançois Tigeot flags |= PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE; 259e3adcf8fSFrançois Tigeot flags |= PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE; 260e3adcf8fSFrançois Tigeot flags |= PIPE_CONTROL_VF_CACHE_INVALIDATE; 261e3adcf8fSFrançois Tigeot flags |= PIPE_CONTROL_CONST_CACHE_INVALIDATE; 262e3adcf8fSFrançois Tigeot flags |= PIPE_CONTROL_STATE_CACHE_INVALIDATE; 263686a02f1SFrançois Tigeot /* 264b5c29a34SFrançois Tigeot * TLB invalidate requires a post-sync write. 265686a02f1SFrançois Tigeot */ 266b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_QW_WRITE | PIPE_CONTROL_CS_STALL; 267b5c29a34SFrançois Tigeot } 268e3adcf8fSFrançois Tigeot 269a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 4); 270e3adcf8fSFrançois Tigeot if (ret) 271e3adcf8fSFrançois Tigeot return ret; 272e3adcf8fSFrançois Tigeot 2738621f407SFrançois Tigeot intel_ring_emit(engine, GFX_OP_PIPE_CONTROL(4)); 2748621f407SFrançois Tigeot intel_ring_emit(engine, flags); 2758621f407SFrançois Tigeot intel_ring_emit(engine, scratch_addr | PIPE_CONTROL_GLOBAL_GTT); 2768621f407SFrançois Tigeot intel_ring_emit(engine, 0); 2778621f407SFrançois Tigeot intel_ring_advance(engine); 278b5c29a34SFrançois Tigeot 279b5c29a34SFrançois Tigeot return 0; 280b5c29a34SFrançois Tigeot } 281b5c29a34SFrançois Tigeot 282b5c29a34SFrançois Tigeot static int 283a05eeebfSFrançois Tigeot gen7_render_ring_cs_stall_wa(struct drm_i915_gem_request *req) 284b5c29a34SFrançois Tigeot { 2858621f407SFrançois Tigeot struct intel_engine_cs *engine = req->engine; 286b5c29a34SFrançois Tigeot int ret; 287b5c29a34SFrançois Tigeot 288a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 4); 289b5c29a34SFrançois Tigeot if (ret) 290b5c29a34SFrançois Tigeot return ret; 291b5c29a34SFrançois Tigeot 2928621f407SFrançois Tigeot intel_ring_emit(engine, GFX_OP_PIPE_CONTROL(4)); 2938621f407SFrançois Tigeot intel_ring_emit(engine, PIPE_CONTROL_CS_STALL | 294b5c29a34SFrançois Tigeot PIPE_CONTROL_STALL_AT_SCOREBOARD); 2958621f407SFrançois Tigeot intel_ring_emit(engine, 0); 2968621f407SFrançois Tigeot intel_ring_emit(engine, 0); 2978621f407SFrançois Tigeot intel_ring_advance(engine); 298b5c29a34SFrançois Tigeot 299b5c29a34SFrançois Tigeot return 0; 300b5c29a34SFrançois Tigeot } 301b5c29a34SFrançois Tigeot 302b5c29a34SFrançois Tigeot static int 303a05eeebfSFrançois Tigeot gen7_render_ring_flush(struct drm_i915_gem_request *req, 304b5c29a34SFrançois Tigeot u32 invalidate_domains, u32 flush_domains) 305b5c29a34SFrançois Tigeot { 3068621f407SFrançois Tigeot struct intel_engine_cs *engine = req->engine; 307b5c29a34SFrançois Tigeot u32 flags = 0; 3088621f407SFrançois Tigeot u32 scratch_addr = engine->scratch.gtt_offset + 2 * CACHELINE_BYTES; 309b5c29a34SFrançois Tigeot int ret; 310b5c29a34SFrançois Tigeot 311b5c29a34SFrançois Tigeot /* 312b5c29a34SFrançois Tigeot * Ensure that any following seqno writes only happen when the render 313b5c29a34SFrançois Tigeot * cache is indeed flushed. 314b5c29a34SFrançois Tigeot * 315b5c29a34SFrançois Tigeot * Workaround: 4th PIPE_CONTROL command (except the ones with only 316b5c29a34SFrançois Tigeot * read-cache invalidate bits set) must have the CS_STALL bit set. We 317b5c29a34SFrançois Tigeot * don't try to be clever and just set it unconditionally. 318b5c29a34SFrançois Tigeot */ 319b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_CS_STALL; 320b5c29a34SFrançois Tigeot 321b5c29a34SFrançois Tigeot /* Just flush everything. Experiments have shown that reducing the 322b5c29a34SFrançois Tigeot * number of bits based on the write domains has little performance 323b5c29a34SFrançois Tigeot * impact. 324b5c29a34SFrançois Tigeot */ 325b5c29a34SFrançois Tigeot if (flush_domains) { 326b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH; 327b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_DEPTH_CACHE_FLUSH; 328aee94f86SFrançois Tigeot flags |= PIPE_CONTROL_DC_FLUSH_ENABLE; 329b49c8cf9SFrançois Tigeot flags |= PIPE_CONTROL_FLUSH_ENABLE; 330b5c29a34SFrançois Tigeot } 331b5c29a34SFrançois Tigeot if (invalidate_domains) { 332b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_TLB_INVALIDATE; 333b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE; 334b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE; 335b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_VF_CACHE_INVALIDATE; 336b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_CONST_CACHE_INVALIDATE; 337b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_STATE_CACHE_INVALIDATE; 3382c9916cdSFrançois Tigeot flags |= PIPE_CONTROL_MEDIA_STATE_CLEAR; 339b5c29a34SFrançois Tigeot /* 340b5c29a34SFrançois Tigeot * TLB invalidate requires a post-sync write. 341b5c29a34SFrançois Tigeot */ 342b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_QW_WRITE; 343a2fdbec6SFrançois Tigeot flags |= PIPE_CONTROL_GLOBAL_GTT_IVB; 344b5c29a34SFrançois Tigeot 3450dbf0ea8SMatthew Dillon flags |= PIPE_CONTROL_STALL_AT_SCOREBOARD; 3460dbf0ea8SMatthew Dillon 347b5c29a34SFrançois Tigeot /* Workaround: we must issue a pipe_control with CS-stall bit 348b5c29a34SFrançois Tigeot * set before a pipe_control command that has the state cache 349b5c29a34SFrançois Tigeot * invalidate bit set. */ 350a05eeebfSFrançois Tigeot gen7_render_ring_cs_stall_wa(req); 351b5c29a34SFrançois Tigeot } 352b5c29a34SFrançois Tigeot 353a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 4); 354b5c29a34SFrançois Tigeot if (ret) 355b5c29a34SFrançois Tigeot return ret; 356b5c29a34SFrançois Tigeot 3578621f407SFrançois Tigeot intel_ring_emit(engine, GFX_OP_PIPE_CONTROL(4)); 3588621f407SFrançois Tigeot intel_ring_emit(engine, flags); 3598621f407SFrançois Tigeot intel_ring_emit(engine, scratch_addr); 3608621f407SFrançois Tigeot intel_ring_emit(engine, 0); 3618621f407SFrançois Tigeot intel_ring_advance(engine); 362e3adcf8fSFrançois Tigeot 363e3adcf8fSFrançois Tigeot return 0; 364e3adcf8fSFrançois Tigeot } 365e3adcf8fSFrançois Tigeot 3669edbd4a0SFrançois Tigeot static int 367a05eeebfSFrançois Tigeot gen8_emit_pipe_control(struct drm_i915_gem_request *req, 36824edb884SFrançois Tigeot u32 flags, u32 scratch_addr) 36924edb884SFrançois Tigeot { 3708621f407SFrançois Tigeot struct intel_engine_cs *engine = req->engine; 37124edb884SFrançois Tigeot int ret; 37224edb884SFrançois Tigeot 373a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 6); 37424edb884SFrançois Tigeot if (ret) 37524edb884SFrançois Tigeot return ret; 37624edb884SFrançois Tigeot 3778621f407SFrançois Tigeot intel_ring_emit(engine, GFX_OP_PIPE_CONTROL(6)); 3788621f407SFrançois Tigeot intel_ring_emit(engine, flags); 3798621f407SFrançois Tigeot intel_ring_emit(engine, scratch_addr); 3808621f407SFrançois Tigeot intel_ring_emit(engine, 0); 3818621f407SFrançois Tigeot intel_ring_emit(engine, 0); 3828621f407SFrançois Tigeot intel_ring_emit(engine, 0); 3838621f407SFrançois Tigeot intel_ring_advance(engine); 38424edb884SFrançois Tigeot 38524edb884SFrançois Tigeot return 0; 38624edb884SFrançois Tigeot } 38724edb884SFrançois Tigeot 38824edb884SFrançois Tigeot static int 389a05eeebfSFrançois Tigeot gen8_render_ring_flush(struct drm_i915_gem_request *req, 3909edbd4a0SFrançois Tigeot u32 invalidate_domains, u32 flush_domains) 3919edbd4a0SFrançois Tigeot { 3929edbd4a0SFrançois Tigeot u32 flags = 0; 3938621f407SFrançois Tigeot u32 scratch_addr = req->engine->scratch.gtt_offset + 2 * CACHELINE_BYTES; 3949edbd4a0SFrançois Tigeot int ret; 3959edbd4a0SFrançois Tigeot 3969edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_CS_STALL; 3979edbd4a0SFrançois Tigeot 3989edbd4a0SFrançois Tigeot if (flush_domains) { 3999edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH; 4009edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_DEPTH_CACHE_FLUSH; 401aee94f86SFrançois Tigeot flags |= PIPE_CONTROL_DC_FLUSH_ENABLE; 402b49c8cf9SFrançois Tigeot flags |= PIPE_CONTROL_FLUSH_ENABLE; 4039edbd4a0SFrançois Tigeot } 4049edbd4a0SFrançois Tigeot if (invalidate_domains) { 4059edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_TLB_INVALIDATE; 4069edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE; 4079edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE; 4089edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_VF_CACHE_INVALIDATE; 4099edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_CONST_CACHE_INVALIDATE; 4109edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_STATE_CACHE_INVALIDATE; 4119edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_QW_WRITE; 4129edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_GLOBAL_GTT_IVB; 4139edbd4a0SFrançois Tigeot 41424edb884SFrançois Tigeot /* WaCsStallBeforeStateCacheInvalidate:bdw,chv */ 415a05eeebfSFrançois Tigeot ret = gen8_emit_pipe_control(req, 41624edb884SFrançois Tigeot PIPE_CONTROL_CS_STALL | 41724edb884SFrançois Tigeot PIPE_CONTROL_STALL_AT_SCOREBOARD, 41824edb884SFrançois Tigeot 0); 4199edbd4a0SFrançois Tigeot if (ret) 4209edbd4a0SFrançois Tigeot return ret; 42124edb884SFrançois Tigeot } 4229edbd4a0SFrançois Tigeot 423a05eeebfSFrançois Tigeot return gen8_emit_pipe_control(req, flags, scratch_addr); 4249edbd4a0SFrançois Tigeot } 4259edbd4a0SFrançois Tigeot 4268621f407SFrançois Tigeot static void ring_write_tail(struct intel_engine_cs *engine, 427b5c29a34SFrançois Tigeot u32 value) 428e3adcf8fSFrançois Tigeot { 4298621f407SFrançois Tigeot struct drm_i915_private *dev_priv = engine->dev->dev_private; 4308621f407SFrançois Tigeot I915_WRITE_TAIL(engine, value); 431e3adcf8fSFrançois Tigeot } 432e3adcf8fSFrançois Tigeot 4338621f407SFrançois Tigeot u64 intel_ring_get_active_head(struct intel_engine_cs *engine) 434e3adcf8fSFrançois Tigeot { 4358621f407SFrançois Tigeot struct drm_i915_private *dev_priv = engine->dev->dev_private; 436ba55f2f5SFrançois Tigeot u64 acthd; 437e3adcf8fSFrançois Tigeot 4388621f407SFrançois Tigeot if (INTEL_INFO(engine->dev)->gen >= 8) 4398621f407SFrançois Tigeot acthd = I915_READ64_2x32(RING_ACTHD(engine->mmio_base), 4408621f407SFrançois Tigeot RING_ACTHD_UDW(engine->mmio_base)); 4418621f407SFrançois Tigeot else if (INTEL_INFO(engine->dev)->gen >= 4) 4428621f407SFrançois Tigeot acthd = I915_READ(RING_ACTHD(engine->mmio_base)); 443ba55f2f5SFrançois Tigeot else 444ba55f2f5SFrançois Tigeot acthd = I915_READ(ACTHD); 445ba55f2f5SFrançois Tigeot 446ba55f2f5SFrançois Tigeot return acthd; 447e3adcf8fSFrançois Tigeot } 448e3adcf8fSFrançois Tigeot 4498621f407SFrançois Tigeot static void ring_setup_phys_status_page(struct intel_engine_cs *engine) 4505d0b1887SFrançois Tigeot { 4518621f407SFrançois Tigeot struct drm_i915_private *dev_priv = engine->dev->dev_private; 4525d0b1887SFrançois Tigeot u32 addr; 4535d0b1887SFrançois Tigeot 4545d0b1887SFrançois Tigeot addr = dev_priv->status_page_dmah->busaddr; 4558621f407SFrançois Tigeot if (INTEL_INFO(engine->dev)->gen >= 4) 4565d0b1887SFrançois Tigeot addr |= (dev_priv->status_page_dmah->busaddr >> 28) & 0xf0; 4575d0b1887SFrançois Tigeot I915_WRITE(HWS_PGA, addr); 4585d0b1887SFrançois Tigeot } 4595d0b1887SFrançois Tigeot 4608621f407SFrançois Tigeot static void intel_ring_setup_status_page(struct intel_engine_cs *engine) 461477eb7f9SFrançois Tigeot { 4628621f407SFrançois Tigeot struct drm_device *dev = engine->dev; 4638621f407SFrançois Tigeot struct drm_i915_private *dev_priv = engine->dev->dev_private; 464aee94f86SFrançois Tigeot i915_reg_t mmio; 465477eb7f9SFrançois Tigeot 466477eb7f9SFrançois Tigeot /* The ring status page addresses are no longer next to the rest of 467477eb7f9SFrançois Tigeot * the ring registers as of gen7. 468477eb7f9SFrançois Tigeot */ 469477eb7f9SFrançois Tigeot if (IS_GEN7(dev)) { 4708621f407SFrançois Tigeot switch (engine->id) { 471477eb7f9SFrançois Tigeot case RCS: 472477eb7f9SFrançois Tigeot mmio = RENDER_HWS_PGA_GEN7; 473477eb7f9SFrançois Tigeot break; 474477eb7f9SFrançois Tigeot case BCS: 475477eb7f9SFrançois Tigeot mmio = BLT_HWS_PGA_GEN7; 476477eb7f9SFrançois Tigeot break; 477477eb7f9SFrançois Tigeot /* 478477eb7f9SFrançois Tigeot * VCS2 actually doesn't exist on Gen7. Only shut up 479477eb7f9SFrançois Tigeot * gcc switch check warning 480477eb7f9SFrançois Tigeot */ 481477eb7f9SFrançois Tigeot case VCS2: 482477eb7f9SFrançois Tigeot case VCS: 483477eb7f9SFrançois Tigeot mmio = BSD_HWS_PGA_GEN7; 484477eb7f9SFrançois Tigeot break; 485477eb7f9SFrançois Tigeot case VECS: 486477eb7f9SFrançois Tigeot mmio = VEBOX_HWS_PGA_GEN7; 487477eb7f9SFrançois Tigeot break; 488477eb7f9SFrançois Tigeot } 4898621f407SFrançois Tigeot } else if (IS_GEN6(engine->dev)) { 4908621f407SFrançois Tigeot mmio = RING_HWS_PGA_GEN6(engine->mmio_base); 491477eb7f9SFrançois Tigeot } else { 492477eb7f9SFrançois Tigeot /* XXX: gen8 returns to sanity */ 4938621f407SFrançois Tigeot mmio = RING_HWS_PGA(engine->mmio_base); 494477eb7f9SFrançois Tigeot } 495477eb7f9SFrançois Tigeot 4968621f407SFrançois Tigeot I915_WRITE(mmio, (u32)engine->status_page.gfx_addr); 497477eb7f9SFrançois Tigeot POSTING_READ(mmio); 498477eb7f9SFrançois Tigeot 499477eb7f9SFrançois Tigeot /* 500477eb7f9SFrançois Tigeot * Flush the TLB for this page 501477eb7f9SFrançois Tigeot * 502477eb7f9SFrançois Tigeot * FIXME: These two bits have disappeared on gen8, so a question 503477eb7f9SFrançois Tigeot * arises: do we still need this and if so how should we go about 504477eb7f9SFrançois Tigeot * invalidating the TLB? 505477eb7f9SFrançois Tigeot */ 506477eb7f9SFrançois Tigeot if (INTEL_INFO(dev)->gen >= 6 && INTEL_INFO(dev)->gen < 8) { 5078621f407SFrançois Tigeot i915_reg_t reg = RING_INSTPM(engine->mmio_base); 508477eb7f9SFrançois Tigeot 509477eb7f9SFrançois Tigeot /* ring should be idle before issuing a sync flush*/ 5108621f407SFrançois Tigeot WARN_ON((I915_READ_MODE(engine) & MODE_IDLE) == 0); 511477eb7f9SFrançois Tigeot 512477eb7f9SFrançois Tigeot I915_WRITE(reg, 513477eb7f9SFrançois Tigeot _MASKED_BIT_ENABLE(INSTPM_TLB_INVALIDATE | 514477eb7f9SFrançois Tigeot INSTPM_SYNC_FLUSH)); 515477eb7f9SFrançois Tigeot if (wait_for((I915_READ(reg) & INSTPM_SYNC_FLUSH) == 0, 516477eb7f9SFrançois Tigeot 1000)) 517477eb7f9SFrançois Tigeot DRM_ERROR("%s: wait for SyncFlush to complete for TLB invalidation timed out\n", 5188621f407SFrançois Tigeot engine->name); 519477eb7f9SFrançois Tigeot } 520477eb7f9SFrançois Tigeot } 521477eb7f9SFrançois Tigeot 5228621f407SFrançois Tigeot static bool stop_ring(struct intel_engine_cs *engine) 523e3adcf8fSFrançois Tigeot { 5248621f407SFrançois Tigeot struct drm_i915_private *dev_priv = to_i915(engine->dev); 525e3adcf8fSFrançois Tigeot 5268621f407SFrançois Tigeot if (!IS_GEN2(engine->dev)) { 5278621f407SFrançois Tigeot I915_WRITE_MODE(engine, _MASKED_BIT_ENABLE(STOP_RING)); 5288621f407SFrançois Tigeot if (wait_for((I915_READ_MODE(engine) & MODE_IDLE) != 0, 1000)) { 5298621f407SFrançois Tigeot DRM_ERROR("%s : timed out trying to stop ring\n", 5308621f407SFrançois Tigeot engine->name); 5311b13d190SFrançois Tigeot /* Sometimes we observe that the idle flag is not 5321b13d190SFrançois Tigeot * set even though the ring is empty. So double 5331b13d190SFrançois Tigeot * check before giving up. 5341b13d190SFrançois Tigeot */ 5358621f407SFrançois Tigeot if (I915_READ_HEAD(engine) != I915_READ_TAIL(engine)) 536ba55f2f5SFrançois Tigeot return false; 537ba55f2f5SFrançois Tigeot } 538ba55f2f5SFrançois Tigeot } 539686a02f1SFrançois Tigeot 5408621f407SFrançois Tigeot I915_WRITE_CTL(engine, 0); 5418621f407SFrançois Tigeot I915_WRITE_HEAD(engine, 0); 5428621f407SFrançois Tigeot engine->write_tail(engine, 0); 543e3adcf8fSFrançois Tigeot 5448621f407SFrançois Tigeot if (!IS_GEN2(engine->dev)) { 5458621f407SFrançois Tigeot (void)I915_READ_CTL(engine); 5468621f407SFrançois Tigeot I915_WRITE_MODE(engine, _MASKED_BIT_DISABLE(STOP_RING)); 547ba55f2f5SFrançois Tigeot } 548e3adcf8fSFrançois Tigeot 5498621f407SFrançois Tigeot return (I915_READ_HEAD(engine) & HEAD_ADDR) == 0; 550ba55f2f5SFrançois Tigeot } 551ba55f2f5SFrançois Tigeot 5528621f407SFrançois Tigeot void intel_engine_init_hangcheck(struct intel_engine_cs *engine) 553ba55f2f5SFrançois Tigeot { 5548621f407SFrançois Tigeot memset(&engine->hangcheck, 0, sizeof(engine->hangcheck)); 5558621f407SFrançois Tigeot } 5568621f407SFrançois Tigeot 5578621f407SFrançois Tigeot static int init_ring_common(struct intel_engine_cs *engine) 5588621f407SFrançois Tigeot { 5598621f407SFrançois Tigeot struct drm_device *dev = engine->dev; 560ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 5618621f407SFrançois Tigeot struct intel_ringbuffer *ringbuf = engine->buffer; 562ba55f2f5SFrançois Tigeot struct drm_i915_gem_object *obj = ringbuf->obj; 563ba55f2f5SFrançois Tigeot int ret = 0; 564ba55f2f5SFrançois Tigeot 5652c9916cdSFrançois Tigeot intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL); 566ba55f2f5SFrançois Tigeot 5678621f407SFrançois Tigeot if (!stop_ring(engine)) { 568ba55f2f5SFrançois Tigeot /* G45 ring initialization often fails to reset head to zero */ 569b5c29a34SFrançois Tigeot DRM_DEBUG_KMS("%s head not reset to zero " 570e3adcf8fSFrançois Tigeot "ctl %08x head %08x tail %08x start %08x\n", 5718621f407SFrançois Tigeot engine->name, 5728621f407SFrançois Tigeot I915_READ_CTL(engine), 5738621f407SFrançois Tigeot I915_READ_HEAD(engine), 5748621f407SFrançois Tigeot I915_READ_TAIL(engine), 5758621f407SFrançois Tigeot I915_READ_START(engine)); 576e3adcf8fSFrançois Tigeot 5778621f407SFrançois Tigeot if (!stop_ring(engine)) { 578e3adcf8fSFrançois Tigeot DRM_ERROR("failed to set %s head to zero " 579e3adcf8fSFrançois Tigeot "ctl %08x head %08x tail %08x start %08x\n", 5808621f407SFrançois Tigeot engine->name, 5818621f407SFrançois Tigeot I915_READ_CTL(engine), 5828621f407SFrançois Tigeot I915_READ_HEAD(engine), 5838621f407SFrançois Tigeot I915_READ_TAIL(engine), 5848621f407SFrançois Tigeot I915_READ_START(engine)); 585686a02f1SFrançois Tigeot ret = -EIO; 586686a02f1SFrançois Tigeot goto out; 587e3adcf8fSFrançois Tigeot } 588ba55f2f5SFrançois Tigeot } 589ba55f2f5SFrançois Tigeot 590ba55f2f5SFrançois Tigeot if (I915_NEED_GFX_HWS(dev)) 5918621f407SFrançois Tigeot intel_ring_setup_status_page(engine); 592ba55f2f5SFrançois Tigeot else 5938621f407SFrançois Tigeot ring_setup_phys_status_page(engine); 594ba55f2f5SFrançois Tigeot 5950f370975SMatthew Dillon /* Enforce ordering by reading HEAD register back */ 5968621f407SFrançois Tigeot I915_READ_HEAD(engine); 5970f370975SMatthew Dillon 598ba55f2f5SFrançois Tigeot /* Initialize the ring. This must happen _after_ we've cleared the ring 599ba55f2f5SFrançois Tigeot * registers with the above sequence (the readback of the HEAD registers 600ba55f2f5SFrançois Tigeot * also enforces ordering), otherwise the hw might lose the new ring 601ba55f2f5SFrançois Tigeot * register values. */ 6028621f407SFrançois Tigeot I915_WRITE_START(engine, i915_gem_obj_ggtt_offset(obj)); 6031b13d190SFrançois Tigeot 6041b13d190SFrançois Tigeot /* WaClearRingBufHeadRegAtInit:ctg,elk */ 6058621f407SFrançois Tigeot if (I915_READ_HEAD(engine)) 6061b13d190SFrançois Tigeot DRM_DEBUG("%s initialization failed [head=%08x], fudging\n", 6078621f407SFrançois Tigeot engine->name, I915_READ_HEAD(engine)); 6088621f407SFrançois Tigeot I915_WRITE_HEAD(engine, 0); 6098621f407SFrançois Tigeot (void)I915_READ_HEAD(engine); 6101b13d190SFrançois Tigeot 6118621f407SFrançois Tigeot I915_WRITE_CTL(engine, 612ba55f2f5SFrançois Tigeot ((ringbuf->size - PAGE_SIZE) & RING_NR_PAGES) 613ba55f2f5SFrançois Tigeot | RING_VALID); 614ba55f2f5SFrançois Tigeot 615ba55f2f5SFrançois Tigeot /* If the head is still not zero, the ring is dead */ 6168621f407SFrançois Tigeot if (wait_for((I915_READ_CTL(engine) & RING_VALID) != 0 && 6178621f407SFrançois Tigeot I915_READ_START(engine) == i915_gem_obj_ggtt_offset(obj) && 6188621f407SFrançois Tigeot (I915_READ_HEAD(engine) & HEAD_ADDR) == 0, 50)) { 619ba55f2f5SFrançois Tigeot DRM_ERROR("%s initialization failed " 620ba55f2f5SFrançois Tigeot "ctl %08x (valid? %d) head %08x tail %08x start %08x [expected %08lx]\n", 6218621f407SFrançois Tigeot engine->name, 6228621f407SFrançois Tigeot I915_READ_CTL(engine), 6238621f407SFrançois Tigeot I915_READ_CTL(engine) & RING_VALID, 6248621f407SFrançois Tigeot I915_READ_HEAD(engine), I915_READ_TAIL(engine), 6258621f407SFrançois Tigeot I915_READ_START(engine), 6268621f407SFrançois Tigeot (unsigned long)i915_gem_obj_ggtt_offset(obj)); 627ba55f2f5SFrançois Tigeot ret = -EIO; 628ba55f2f5SFrançois Tigeot goto out; 629ba55f2f5SFrançois Tigeot } 630e3adcf8fSFrançois Tigeot 6312c9916cdSFrançois Tigeot ringbuf->last_retired_head = -1; 6328621f407SFrançois Tigeot ringbuf->head = I915_READ_HEAD(engine); 6338621f407SFrançois Tigeot ringbuf->tail = I915_READ_TAIL(engine) & TAIL_ADDR; 6342c9916cdSFrançois Tigeot intel_ring_update_space(ringbuf); 635e3adcf8fSFrançois Tigeot 6368621f407SFrançois Tigeot intel_engine_init_hangcheck(engine); 6375d0b1887SFrançois Tigeot 638686a02f1SFrançois Tigeot out: 6392c9916cdSFrançois Tigeot intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL); 640686a02f1SFrançois Tigeot 641686a02f1SFrançois Tigeot return ret; 642e3adcf8fSFrançois Tigeot } 643e3adcf8fSFrançois Tigeot 6441b13d190SFrançois Tigeot void 6458621f407SFrançois Tigeot intel_fini_pipe_control(struct intel_engine_cs *engine) 6461b13d190SFrançois Tigeot { 6478621f407SFrançois Tigeot struct drm_device *dev = engine->dev; 6481b13d190SFrançois Tigeot 6498621f407SFrançois Tigeot if (engine->scratch.obj == NULL) 6501b13d190SFrançois Tigeot return; 6511b13d190SFrançois Tigeot 6521b13d190SFrançois Tigeot if (INTEL_INFO(dev)->gen >= 5) { 6538621f407SFrançois Tigeot kunmap(sg_page(engine->scratch.obj->pages->sgl)); 6548621f407SFrançois Tigeot i915_gem_object_ggtt_unpin(engine->scratch.obj); 6551b13d190SFrançois Tigeot } 6561b13d190SFrançois Tigeot 6578621f407SFrançois Tigeot drm_gem_object_unreference(&engine->scratch.obj->base); 6588621f407SFrançois Tigeot engine->scratch.obj = NULL; 6591b13d190SFrançois Tigeot } 6601b13d190SFrançois Tigeot 6611b13d190SFrançois Tigeot int 6628621f407SFrançois Tigeot intel_init_pipe_control(struct intel_engine_cs *engine) 663e3adcf8fSFrançois Tigeot { 664e3adcf8fSFrançois Tigeot int ret; 665e3adcf8fSFrançois Tigeot 6668621f407SFrançois Tigeot WARN_ON(engine->scratch.obj); 667e3adcf8fSFrançois Tigeot 6688621f407SFrançois Tigeot engine->scratch.obj = i915_gem_alloc_object(engine->dev, 4096); 6698621f407SFrançois Tigeot if (engine->scratch.obj == NULL) { 670e3adcf8fSFrançois Tigeot DRM_ERROR("Failed to allocate seqno page\n"); 671e3adcf8fSFrançois Tigeot ret = -ENOMEM; 672e3adcf8fSFrançois Tigeot goto err; 673e3adcf8fSFrançois Tigeot } 674e3adcf8fSFrançois Tigeot 6758621f407SFrançois Tigeot ret = i915_gem_object_set_cache_level(engine->scratch.obj, 6768621f407SFrançois Tigeot I915_CACHE_LLC); 677ba55f2f5SFrançois Tigeot if (ret) 678ba55f2f5SFrançois Tigeot goto err_unref; 679e3adcf8fSFrançois Tigeot 6808621f407SFrançois Tigeot ret = i915_gem_obj_ggtt_pin(engine->scratch.obj, 4096, 0); 681e3adcf8fSFrançois Tigeot if (ret) 682e3adcf8fSFrançois Tigeot goto err_unref; 683e3adcf8fSFrançois Tigeot 6848621f407SFrançois Tigeot engine->scratch.gtt_offset = i915_gem_obj_ggtt_offset(engine->scratch.obj); 6858621f407SFrançois Tigeot engine->scratch.cpu_page = kmap(sg_page(engine->scratch.obj->pages->sgl)); 6868621f407SFrançois Tigeot if (engine->scratch.cpu_page == NULL) { 6875d0b1887SFrançois Tigeot ret = -ENOMEM; 688e3adcf8fSFrançois Tigeot goto err_unpin; 6895d0b1887SFrançois Tigeot } 690a2fdbec6SFrançois Tigeot 691a2fdbec6SFrançois Tigeot DRM_DEBUG_DRIVER("%s pipe control offset: 0x%08x\n", 6928621f407SFrançois Tigeot engine->name, engine->scratch.gtt_offset); 693e3adcf8fSFrançois Tigeot return 0; 694e3adcf8fSFrançois Tigeot 695e3adcf8fSFrançois Tigeot err_unpin: 6968621f407SFrançois Tigeot i915_gem_object_ggtt_unpin(engine->scratch.obj); 697e3adcf8fSFrançois Tigeot err_unref: 6988621f407SFrançois Tigeot drm_gem_object_unreference(&engine->scratch.obj->base); 699e3adcf8fSFrançois Tigeot err: 700e3adcf8fSFrançois Tigeot return ret; 701e3adcf8fSFrançois Tigeot } 702e3adcf8fSFrançois Tigeot 703a05eeebfSFrançois Tigeot static int intel_ring_workarounds_emit(struct drm_i915_gem_request *req) 7041b13d190SFrançois Tigeot { 7052c9916cdSFrançois Tigeot int ret, i; 7068621f407SFrançois Tigeot struct intel_engine_cs *engine = req->engine; 7078621f407SFrançois Tigeot struct drm_device *dev = engine->dev; 7081b13d190SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 7092c9916cdSFrançois Tigeot struct i915_workarounds *w = &dev_priv->workarounds; 7101b13d190SFrançois Tigeot 711352ff8bdSFrançois Tigeot if (w->count == 0) 7122c9916cdSFrançois Tigeot return 0; 7131b13d190SFrançois Tigeot 7148621f407SFrançois Tigeot engine->gpu_caches_dirty = true; 715a05eeebfSFrançois Tigeot ret = intel_ring_flush_all_caches(req); 7161b13d190SFrançois Tigeot if (ret) 7171b13d190SFrançois Tigeot return ret; 7181b13d190SFrançois Tigeot 719a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, (w->count * 2 + 2)); 7202c9916cdSFrançois Tigeot if (ret) 7212c9916cdSFrançois Tigeot return ret; 7222c9916cdSFrançois Tigeot 7238621f407SFrançois Tigeot intel_ring_emit(engine, MI_LOAD_REGISTER_IMM(w->count)); 7242c9916cdSFrançois Tigeot for (i = 0; i < w->count; i++) { 7258621f407SFrançois Tigeot intel_ring_emit_reg(engine, w->reg[i].addr); 7268621f407SFrançois Tigeot intel_ring_emit(engine, w->reg[i].value); 7272c9916cdSFrançois Tigeot } 7288621f407SFrançois Tigeot intel_ring_emit(engine, MI_NOOP); 7292c9916cdSFrançois Tigeot 7308621f407SFrançois Tigeot intel_ring_advance(engine); 7312c9916cdSFrançois Tigeot 7328621f407SFrançois Tigeot engine->gpu_caches_dirty = true; 733a05eeebfSFrançois Tigeot ret = intel_ring_flush_all_caches(req); 7342c9916cdSFrançois Tigeot if (ret) 7352c9916cdSFrançois Tigeot return ret; 7362c9916cdSFrançois Tigeot 7372c9916cdSFrançois Tigeot DRM_DEBUG_DRIVER("Number of Workarounds emitted: %d\n", w->count); 7382c9916cdSFrançois Tigeot 7392c9916cdSFrançois Tigeot return 0; 7402c9916cdSFrançois Tigeot } 7412c9916cdSFrançois Tigeot 742a05eeebfSFrançois Tigeot static int intel_rcs_ctx_init(struct drm_i915_gem_request *req) 7432c9916cdSFrançois Tigeot { 7442c9916cdSFrançois Tigeot int ret; 7452c9916cdSFrançois Tigeot 746a05eeebfSFrançois Tigeot ret = intel_ring_workarounds_emit(req); 7472c9916cdSFrançois Tigeot if (ret != 0) 7482c9916cdSFrançois Tigeot return ret; 7492c9916cdSFrançois Tigeot 750a05eeebfSFrançois Tigeot ret = i915_gem_render_state_init(req); 7512c9916cdSFrançois Tigeot if (ret) 7522c9916cdSFrançois Tigeot return ret; 753c0e85e96SFrançois Tigeot 754c0e85e96SFrançois Tigeot return 0; 7552c9916cdSFrançois Tigeot } 7562c9916cdSFrançois Tigeot 7572c9916cdSFrançois Tigeot static int wa_add(struct drm_i915_private *dev_priv, 758aee94f86SFrançois Tigeot i915_reg_t addr, 759aee94f86SFrançois Tigeot const u32 mask, const u32 val) 7602c9916cdSFrançois Tigeot { 7612c9916cdSFrançois Tigeot const u32 idx = dev_priv->workarounds.count; 7622c9916cdSFrançois Tigeot 7632c9916cdSFrançois Tigeot if (WARN_ON(idx >= I915_MAX_WA_REGS)) 7642c9916cdSFrançois Tigeot return -ENOSPC; 7652c9916cdSFrançois Tigeot 7662c9916cdSFrançois Tigeot dev_priv->workarounds.reg[idx].addr = addr; 7672c9916cdSFrançois Tigeot dev_priv->workarounds.reg[idx].value = val; 7682c9916cdSFrançois Tigeot dev_priv->workarounds.reg[idx].mask = mask; 7692c9916cdSFrançois Tigeot 7702c9916cdSFrançois Tigeot dev_priv->workarounds.count++; 7712c9916cdSFrançois Tigeot 7722c9916cdSFrançois Tigeot return 0; 7732c9916cdSFrançois Tigeot } 7742c9916cdSFrançois Tigeot 775a05eeebfSFrançois Tigeot #define WA_REG(addr, mask, val) do { \ 7762c9916cdSFrançois Tigeot const int r = wa_add(dev_priv, (addr), (mask), (val)); \ 7772c9916cdSFrançois Tigeot if (r) \ 7782c9916cdSFrançois Tigeot return r; \ 779a05eeebfSFrançois Tigeot } while (0) 7802c9916cdSFrançois Tigeot 7812c9916cdSFrançois Tigeot #define WA_SET_BIT_MASKED(addr, mask) \ 7822c9916cdSFrançois Tigeot WA_REG(addr, (mask), _MASKED_BIT_ENABLE(mask)) 7832c9916cdSFrançois Tigeot 7842c9916cdSFrançois Tigeot #define WA_CLR_BIT_MASKED(addr, mask) \ 7852c9916cdSFrançois Tigeot WA_REG(addr, (mask), _MASKED_BIT_DISABLE(mask)) 7862c9916cdSFrançois Tigeot 7872c9916cdSFrançois Tigeot #define WA_SET_FIELD_MASKED(addr, mask, value) \ 7882c9916cdSFrançois Tigeot WA_REG(addr, mask, _MASKED_FIELD(mask, value)) 7892c9916cdSFrançois Tigeot 7902c9916cdSFrançois Tigeot #define WA_SET_BIT(addr, mask) WA_REG(addr, mask, I915_READ(addr) | (mask)) 7912c9916cdSFrançois Tigeot #define WA_CLR_BIT(addr, mask) WA_REG(addr, mask, I915_READ(addr) & ~(mask)) 7922c9916cdSFrançois Tigeot 7932c9916cdSFrançois Tigeot #define WA_WRITE(addr, val) WA_REG(addr, 0xffffffff, val) 7942c9916cdSFrançois Tigeot 7958621f407SFrançois Tigeot static int wa_ring_whitelist_reg(struct intel_engine_cs *engine, 7968621f407SFrançois Tigeot i915_reg_t reg) 797c0e85e96SFrançois Tigeot { 7988621f407SFrançois Tigeot struct drm_i915_private *dev_priv = engine->dev->dev_private; 799c0e85e96SFrançois Tigeot struct i915_workarounds *wa = &dev_priv->workarounds; 8008621f407SFrançois Tigeot const uint32_t index = wa->hw_whitelist_count[engine->id]; 801c0e85e96SFrançois Tigeot 802c0e85e96SFrançois Tigeot if (WARN_ON(index >= RING_MAX_NONPRIV_SLOTS)) 803c0e85e96SFrançois Tigeot return -EINVAL; 804c0e85e96SFrançois Tigeot 8058621f407SFrançois Tigeot WA_WRITE(RING_FORCE_TO_NONPRIV(engine->mmio_base, index), 806c0e85e96SFrançois Tigeot i915_mmio_reg_offset(reg)); 8078621f407SFrançois Tigeot wa->hw_whitelist_count[engine->id]++; 808c0e85e96SFrançois Tigeot 809c0e85e96SFrançois Tigeot return 0; 810c0e85e96SFrançois Tigeot } 811c0e85e96SFrançois Tigeot 8128621f407SFrançois Tigeot static int gen8_init_workarounds(struct intel_engine_cs *engine) 8132c9916cdSFrançois Tigeot { 8148621f407SFrançois Tigeot struct drm_device *dev = engine->dev; 8152c9916cdSFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 8162c9916cdSFrançois Tigeot 817a05eeebfSFrançois Tigeot WA_SET_BIT_MASKED(INSTPM, INSTPM_FORCE_ORDERING); 818a05eeebfSFrançois Tigeot 819352ff8bdSFrançois Tigeot /* WaDisableAsyncFlipPerfMode:bdw,chv */ 820a05eeebfSFrançois Tigeot WA_SET_BIT_MASKED(MI_MODE, ASYNC_FLIP_PERF_DISABLE); 821a05eeebfSFrançois Tigeot 822352ff8bdSFrançois Tigeot /* WaDisablePartialInstShootdown:bdw,chv */ 8232c9916cdSFrançois Tigeot WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN, 824352ff8bdSFrançois Tigeot PARTIAL_INSTRUCTION_SHOOTDOWN_DISABLE); 8251b13d190SFrançois Tigeot 8261b13d190SFrançois Tigeot /* Use Force Non-Coherent whenever executing a 3D context. This is a 8271b13d190SFrançois Tigeot * workaround for for a possible hang in the unlikely event a TLB 8281b13d190SFrançois Tigeot * invalidation occurs during a PSD flush. 8291b13d190SFrançois Tigeot */ 830352ff8bdSFrançois Tigeot /* WaForceEnableNonCoherent:bdw,chv */ 831352ff8bdSFrançois Tigeot /* WaHdcDisableFetchWhenMasked:bdw,chv */ 8322c9916cdSFrançois Tigeot WA_SET_BIT_MASKED(HDC_CHICKEN0, 8332c9916cdSFrançois Tigeot HDC_DONOT_FETCH_MEM_WHEN_MASKED | 834352ff8bdSFrançois Tigeot HDC_FORCE_NON_COHERENT); 8352c9916cdSFrançois Tigeot 8362c9916cdSFrançois Tigeot /* From the Haswell PRM, Command Reference: Registers, CACHE_MODE_0: 8372c9916cdSFrançois Tigeot * "The Hierarchical Z RAW Stall Optimization allows non-overlapping 8382c9916cdSFrançois Tigeot * polygons in the same 8x4 pixel/sample area to be processed without 8392c9916cdSFrançois Tigeot * stalling waiting for the earlier ones to write to Hierarchical Z 8402c9916cdSFrançois Tigeot * buffer." 8412c9916cdSFrançois Tigeot * 842352ff8bdSFrançois Tigeot * This optimization is off by default for BDW and CHV; turn it on. 8432c9916cdSFrançois Tigeot */ 8442c9916cdSFrançois Tigeot WA_CLR_BIT_MASKED(CACHE_MODE_0_GEN7, HIZ_RAW_STALL_OPT_DISABLE); 8451b13d190SFrançois Tigeot 846352ff8bdSFrançois Tigeot /* Wa4x4STCOptimizationDisable:bdw,chv */ 847352ff8bdSFrançois Tigeot WA_SET_BIT_MASKED(CACHE_MODE_1, GEN8_4x4_STC_OPTIMIZATION_DISABLE); 8481b13d190SFrançois Tigeot 8491b13d190SFrançois Tigeot /* 8501b13d190SFrançois Tigeot * BSpec recommends 8x4 when MSAA is used, 8511b13d190SFrançois Tigeot * however in practice 16x4 seems fastest. 8521b13d190SFrançois Tigeot * 8531b13d190SFrançois Tigeot * Note that PS/WM thread counts depend on the WIZ hashing 8541b13d190SFrançois Tigeot * disable bit, which we don't touch here, but it's good 8551b13d190SFrançois Tigeot * to keep in mind (see 3DSTATE_PS and 3DSTATE_WM). 8561b13d190SFrançois Tigeot */ 8572c9916cdSFrançois Tigeot WA_SET_FIELD_MASKED(GEN7_GT_MODE, 8582c9916cdSFrançois Tigeot GEN6_WIZ_HASHING_MASK, 8592c9916cdSFrançois Tigeot GEN6_WIZ_HASHING_16x4); 8601b13d190SFrançois Tigeot 8611b13d190SFrançois Tigeot return 0; 8621b13d190SFrançois Tigeot } 8631b13d190SFrançois Tigeot 8648621f407SFrançois Tigeot static int bdw_init_workarounds(struct intel_engine_cs *engine) 8651b13d190SFrançois Tigeot { 866352ff8bdSFrançois Tigeot int ret; 8678621f407SFrançois Tigeot struct drm_device *dev = engine->dev; 8681b13d190SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 8691b13d190SFrançois Tigeot 8708621f407SFrançois Tigeot ret = gen8_init_workarounds(engine); 871352ff8bdSFrançois Tigeot if (ret) 872352ff8bdSFrançois Tigeot return ret; 873a05eeebfSFrançois Tigeot 874352ff8bdSFrançois Tigeot /* WaDisableThreadStallDopClockGating:bdw (pre-production) */ 875352ff8bdSFrançois Tigeot WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN, STALL_DOP_GATING_DISABLE); 876a05eeebfSFrançois Tigeot 877352ff8bdSFrançois Tigeot /* WaDisableDopClockGating:bdw */ 878352ff8bdSFrançois Tigeot WA_SET_BIT_MASKED(GEN7_ROW_CHICKEN2, 879352ff8bdSFrançois Tigeot DOP_CLOCK_GATING_DISABLE); 8801b13d190SFrançois Tigeot 881352ff8bdSFrançois Tigeot WA_SET_BIT_MASKED(HALF_SLICE_CHICKEN3, 882352ff8bdSFrançois Tigeot GEN8_SAMPLER_POWER_BYPASS_DIS); 883352ff8bdSFrançois Tigeot 8842c9916cdSFrançois Tigeot WA_SET_BIT_MASKED(HDC_CHICKEN0, 885352ff8bdSFrançois Tigeot /* WaForceContextSaveRestoreNonCoherent:bdw */ 886352ff8bdSFrançois Tigeot HDC_FORCE_CONTEXT_SAVE_RESTORE_NON_COHERENT | 887352ff8bdSFrançois Tigeot /* WaDisableFenceDestinationToSLM:bdw (pre-prod) */ 888352ff8bdSFrançois Tigeot (IS_BDW_GT3(dev) ? HDC_FENCE_DEST_SLM_DISABLE : 0)); 8891b13d190SFrançois Tigeot 890352ff8bdSFrançois Tigeot return 0; 891352ff8bdSFrançois Tigeot } 8921b13d190SFrançois Tigeot 8938621f407SFrançois Tigeot static int chv_init_workarounds(struct intel_engine_cs *engine) 894352ff8bdSFrançois Tigeot { 895352ff8bdSFrançois Tigeot int ret; 8968621f407SFrançois Tigeot struct drm_device *dev = engine->dev; 897352ff8bdSFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 898352ff8bdSFrançois Tigeot 8998621f407SFrançois Tigeot ret = gen8_init_workarounds(engine); 900352ff8bdSFrançois Tigeot if (ret) 901352ff8bdSFrançois Tigeot return ret; 902352ff8bdSFrançois Tigeot 903352ff8bdSFrançois Tigeot /* WaDisableThreadStallDopClockGating:chv */ 904352ff8bdSFrançois Tigeot WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN, STALL_DOP_GATING_DISABLE); 9052c9916cdSFrançois Tigeot 9062c9916cdSFrançois Tigeot /* Improve HiZ throughput on CHV. */ 9072c9916cdSFrançois Tigeot WA_SET_BIT_MASKED(HIZ_CHICKEN, CHV_HZ_8X8_MODE_IN_1X); 9082c9916cdSFrançois Tigeot 9092c9916cdSFrançois Tigeot return 0; 9102c9916cdSFrançois Tigeot } 9112c9916cdSFrançois Tigeot 9128621f407SFrançois Tigeot static int gen9_init_workarounds(struct intel_engine_cs *engine) 913477eb7f9SFrançois Tigeot { 9148621f407SFrançois Tigeot struct drm_device *dev = engine->dev; 915477eb7f9SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 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 */ 940aee94f86SFrançois Tigeot if (IS_SKL_REVID(dev, 0, SKL_REVID_B0) || 941aee94f86SFrançois Tigeot IS_BXT_REVID(dev, 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 */ 946aee94f86SFrançois Tigeot if (IS_SKL_REVID(dev, 0, SKL_REVID_B0) || 947aee94f86SFrançois Tigeot IS_BXT_REVID(dev, 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 */ 973aee94f86SFrançois Tigeot if (IS_SKL_REVID(dev, SKL_REVID_C0, SKL_REVID_C0) || 974aee94f86SFrançois Tigeot IS_BXT_REVID(dev, 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 { 10388621f407SFrançois Tigeot struct drm_device *dev = engine->dev; 1039477eb7f9SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 1040477eb7f9SFrançois Tigeot u8 vals[3] = { 0, 0, 0 }; 1041477eb7f9SFrançois Tigeot unsigned int i; 1042477eb7f9SFrançois Tigeot 1043477eb7f9SFrançois Tigeot for (i = 0; i < 3; i++) { 1044477eb7f9SFrançois Tigeot u8 ss; 1045477eb7f9SFrançois Tigeot 1046477eb7f9SFrançois Tigeot /* 1047477eb7f9SFrançois Tigeot * Only consider slices where one, and only one, subslice has 7 1048477eb7f9SFrançois Tigeot * EUs 1049477eb7f9SFrançois Tigeot */ 1050aee94f86SFrançois Tigeot if (!is_power_of_2(dev_priv->info.subslice_7eu[i])) 1051477eb7f9SFrançois Tigeot continue; 1052477eb7f9SFrançois Tigeot 1053477eb7f9SFrançois Tigeot /* 1054477eb7f9SFrançois Tigeot * subslice_7eu[i] != 0 (because of the check above) and 1055477eb7f9SFrançois Tigeot * ss_max == 4 (maximum number of subslices possible per slice) 1056477eb7f9SFrançois Tigeot * 1057477eb7f9SFrançois Tigeot * -> 0 <= ss <= 3; 1058477eb7f9SFrançois Tigeot */ 1059477eb7f9SFrançois Tigeot ss = ffs(dev_priv->info.subslice_7eu[i]) - 1; 1060477eb7f9SFrançois Tigeot vals[i] = 3 - ss; 1061477eb7f9SFrançois Tigeot } 1062477eb7f9SFrançois Tigeot 1063477eb7f9SFrançois Tigeot if (vals[0] == 0 && vals[1] == 0 && vals[2] == 0) 1064477eb7f9SFrançois Tigeot return 0; 1065477eb7f9SFrançois Tigeot 1066477eb7f9SFrançois Tigeot /* Tune IZ hashing. See intel_device_info_runtime_init() */ 1067477eb7f9SFrançois Tigeot WA_SET_FIELD_MASKED(GEN7_GT_MODE, 1068477eb7f9SFrançois Tigeot GEN9_IZ_HASHING_MASK(2) | 1069477eb7f9SFrançois Tigeot GEN9_IZ_HASHING_MASK(1) | 1070477eb7f9SFrançois Tigeot GEN9_IZ_HASHING_MASK(0), 1071477eb7f9SFrançois Tigeot GEN9_IZ_HASHING(2, vals[2]) | 1072477eb7f9SFrançois Tigeot GEN9_IZ_HASHING(1, vals[1]) | 1073477eb7f9SFrançois Tigeot GEN9_IZ_HASHING(0, vals[0])); 1074477eb7f9SFrançois Tigeot 1075477eb7f9SFrançois Tigeot return 0; 1076477eb7f9SFrançois Tigeot } 1077477eb7f9SFrançois Tigeot 10788621f407SFrançois Tigeot static int skl_init_workarounds(struct intel_engine_cs *engine) 1079477eb7f9SFrançois Tigeot { 1080352ff8bdSFrançois Tigeot int ret; 10818621f407SFrançois Tigeot struct drm_device *dev = engine->dev; 1082477eb7f9SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 1083477eb7f9SFrançois Tigeot 10848621f407SFrançois Tigeot ret = gen9_init_workarounds(engine); 1085352ff8bdSFrançois Tigeot if (ret) 1086352ff8bdSFrançois Tigeot return ret; 1087352ff8bdSFrançois Tigeot 1088c0e85e96SFrançois Tigeot /* 1089c0e85e96SFrançois Tigeot * Actual WA is to disable percontext preemption granularity control 1090c0e85e96SFrançois Tigeot * until D0 which is the default case so this is equivalent to 1091c0e85e96SFrançois Tigeot * !WaDisablePerCtxtPreemptionGranularityControl:skl 1092c0e85e96SFrançois Tigeot */ 1093c0e85e96SFrançois Tigeot if (IS_SKL_REVID(dev, SKL_REVID_E0, REVID_FOREVER)) { 1094c0e85e96SFrançois Tigeot I915_WRITE(GEN7_FF_SLICE_CS_CHICKEN1, 1095c0e85e96SFrançois Tigeot _MASKED_BIT_ENABLE(GEN9_FFSC_PERCTX_PREEMPT_CTRL)); 1096c0e85e96SFrançois Tigeot } 1097c0e85e96SFrançois Tigeot 1098aee94f86SFrançois Tigeot if (IS_SKL_REVID(dev, 0, SKL_REVID_D0)) { 1099352ff8bdSFrançois Tigeot /* WaDisableChickenBitTSGBarrierAckForFFSliceCS:skl */ 1100352ff8bdSFrançois Tigeot I915_WRITE(FF_SLICE_CS_CHICKEN2, 1101352ff8bdSFrançois Tigeot _MASKED_BIT_ENABLE(GEN9_TSG_BARRIER_ACK_DISABLE)); 1102352ff8bdSFrançois Tigeot } 1103352ff8bdSFrançois Tigeot 1104352ff8bdSFrançois Tigeot /* GEN8_L3SQCREG4 has a dependency with WA batch so any new changes 1105352ff8bdSFrançois Tigeot * involving this register should also be added to WA batch as required. 1106352ff8bdSFrançois Tigeot */ 1107aee94f86SFrançois Tigeot if (IS_SKL_REVID(dev, 0, SKL_REVID_E0)) 1108352ff8bdSFrançois Tigeot /* WaDisableLSQCROPERFforOCL:skl */ 1109352ff8bdSFrançois Tigeot I915_WRITE(GEN8_L3SQCREG4, I915_READ(GEN8_L3SQCREG4) | 1110352ff8bdSFrançois Tigeot GEN8_LQSC_RO_PERF_DIS); 1111352ff8bdSFrançois Tigeot 1112352ff8bdSFrançois Tigeot /* WaEnableGapsTsvCreditFix:skl */ 1113aee94f86SFrançois Tigeot if (IS_SKL_REVID(dev, SKL_REVID_C0, REVID_FOREVER)) { 1114352ff8bdSFrançois Tigeot I915_WRITE(GEN8_GARBCNTL, (I915_READ(GEN8_GARBCNTL) | 1115352ff8bdSFrançois Tigeot GEN9_GAPS_TSV_CREDIT_DISABLE)); 1116352ff8bdSFrançois Tigeot } 1117477eb7f9SFrançois Tigeot 1118477eb7f9SFrançois Tigeot /* WaDisablePowerCompilerClockGating:skl */ 1119aee94f86SFrançois Tigeot if (IS_SKL_REVID(dev, SKL_REVID_B0, SKL_REVID_B0)) 1120477eb7f9SFrançois Tigeot WA_SET_BIT_MASKED(HIZ_CHICKEN, 1121477eb7f9SFrançois Tigeot BDW_HIZ_POWER_COMPILER_CLOCK_GATING_DISABLE); 1122477eb7f9SFrançois Tigeot 1123a05eeebfSFrançois Tigeot /* WaBarrierPerformanceFixDisable:skl */ 1124aee94f86SFrançois Tigeot if (IS_SKL_REVID(dev, SKL_REVID_C0, SKL_REVID_D0)) 1125a05eeebfSFrançois Tigeot WA_SET_BIT_MASKED(HDC_CHICKEN0, 1126a05eeebfSFrançois Tigeot HDC_FENCE_DEST_SLM_DISABLE | 1127a05eeebfSFrançois Tigeot HDC_BARRIER_PERFORMANCE_DISABLE); 1128a05eeebfSFrançois Tigeot 1129a05eeebfSFrançois Tigeot /* WaDisableSbeCacheDispatchPortSharing:skl */ 1130aee94f86SFrançois Tigeot if (IS_SKL_REVID(dev, 0, SKL_REVID_F0)) 1131a05eeebfSFrançois Tigeot WA_SET_BIT_MASKED( 1132a05eeebfSFrançois Tigeot GEN7_HALF_SLICE_CHICKEN1, 1133a05eeebfSFrançois Tigeot GEN7_SBE_SS_CACHE_DISPATCH_PORT_SHARING_DISABLE); 1134a05eeebfSFrançois Tigeot 11358621f407SFrançois Tigeot /* WaDisableGafsUnitClkGating:skl */ 11368621f407SFrançois Tigeot WA_SET_BIT(GEN7_UCGCTL4, GEN8_EU_GAUNIT_CLOCK_GATE_DISABLE); 11378621f407SFrançois Tigeot 11388621f407SFrançois Tigeot /* WaInPlaceDecompressionHang:skl */ 11398621f407SFrançois Tigeot if (IS_SKL_REVID(dev_priv, SKL_REVID_H0, REVID_FOREVER)) 11408621f407SFrançois Tigeot WA_SET_BIT(GEN9_GAMT_ECO_REG_RW_IA, 11418621f407SFrançois Tigeot GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS); 11428621f407SFrançois Tigeot 1143c0e85e96SFrançois Tigeot /* WaDisableLSQCROPERFforOCL:skl */ 11448621f407SFrançois Tigeot ret = wa_ring_whitelist_reg(engine, GEN8_L3SQCREG4); 1145c0e85e96SFrançois Tigeot if (ret) 1146c0e85e96SFrançois Tigeot return ret; 1147c0e85e96SFrançois Tigeot 11488621f407SFrançois Tigeot return skl_tune_iz_hashing(engine); 1149477eb7f9SFrançois Tigeot } 1150477eb7f9SFrançois Tigeot 11518621f407SFrançois Tigeot static int bxt_init_workarounds(struct intel_engine_cs *engine) 115219c468b4SFrançois Tigeot { 1153352ff8bdSFrançois Tigeot int ret; 11548621f407SFrançois Tigeot struct drm_device *dev = engine->dev; 115519c468b4SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 115619c468b4SFrançois Tigeot 11578621f407SFrançois Tigeot ret = gen9_init_workarounds(engine); 1158352ff8bdSFrançois Tigeot if (ret) 1159352ff8bdSFrançois Tigeot return ret; 1160352ff8bdSFrançois Tigeot 1161352ff8bdSFrançois Tigeot /* WaStoreMultiplePTEenable:bxt */ 1162352ff8bdSFrançois Tigeot /* This is a requirement according to Hardware specification */ 1163aee94f86SFrançois Tigeot if (IS_BXT_REVID(dev, 0, BXT_REVID_A1)) 1164352ff8bdSFrançois Tigeot I915_WRITE(TILECTL, I915_READ(TILECTL) | TILECTL_TLBPF); 1165352ff8bdSFrançois Tigeot 1166352ff8bdSFrançois Tigeot /* WaSetClckGatingDisableMedia:bxt */ 1167aee94f86SFrançois Tigeot if (IS_BXT_REVID(dev, 0, BXT_REVID_A1)) { 1168352ff8bdSFrançois Tigeot I915_WRITE(GEN7_MISCCPCTL, (I915_READ(GEN7_MISCCPCTL) & 1169352ff8bdSFrançois Tigeot ~GEN8_DOP_CLOCK_GATE_MEDIA_ENABLE)); 1170352ff8bdSFrançois Tigeot } 117119c468b4SFrançois Tigeot 117219c468b4SFrançois Tigeot /* WaDisableThreadStallDopClockGating:bxt */ 117319c468b4SFrançois Tigeot WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN, 117419c468b4SFrançois Tigeot STALL_DOP_GATING_DISABLE); 117519c468b4SFrançois Tigeot 117619c468b4SFrançois Tigeot /* WaDisableSbeCacheDispatchPortSharing:bxt */ 1177aee94f86SFrançois Tigeot if (IS_BXT_REVID(dev, 0, BXT_REVID_B0)) { 117819c468b4SFrançois Tigeot WA_SET_BIT_MASKED( 117919c468b4SFrançois Tigeot GEN7_HALF_SLICE_CHICKEN1, 118019c468b4SFrançois Tigeot GEN7_SBE_SS_CACHE_DISPATCH_PORT_SHARING_DISABLE); 118119c468b4SFrançois Tigeot } 118219c468b4SFrançois Tigeot 1183c0e85e96SFrançois Tigeot /* WaDisableObjectLevelPreemptionForTrifanOrPolygon:bxt */ 1184c0e85e96SFrançois Tigeot /* WaDisableObjectLevelPreemptionForInstancedDraw:bxt */ 1185c0e85e96SFrançois Tigeot /* WaDisableObjectLevelPreemtionForInstanceId:bxt */ 1186c0e85e96SFrançois Tigeot /* WaDisableLSQCROPERFforOCL:bxt */ 1187c0e85e96SFrançois Tigeot if (IS_BXT_REVID(dev, 0, BXT_REVID_A1)) { 11888621f407SFrançois Tigeot ret = wa_ring_whitelist_reg(engine, GEN9_CS_DEBUG_MODE1); 1189c0e85e96SFrançois Tigeot if (ret) 1190c0e85e96SFrançois Tigeot return ret; 1191c0e85e96SFrançois Tigeot 11928621f407SFrançois Tigeot ret = wa_ring_whitelist_reg(engine, GEN8_L3SQCREG4); 1193c0e85e96SFrançois Tigeot if (ret) 1194c0e85e96SFrançois Tigeot return ret; 1195c0e85e96SFrançois Tigeot } 1196c0e85e96SFrançois Tigeot 11978621f407SFrançois Tigeot /* WaInsertDummyPushConstPs:bxt */ 11988621f407SFrançois Tigeot if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_B0)) 11998621f407SFrançois Tigeot WA_SET_BIT_MASKED(COMMON_SLICE_CHICKEN2, 12008621f407SFrançois Tigeot GEN8_SBE_DISABLE_REPLAY_BUF_OPTIMIZATION); 12018621f407SFrançois Tigeot 12028621f407SFrançois Tigeot /* WaInPlaceDecompressionHang:bxt */ 12038621f407SFrançois Tigeot if (IS_BXT_REVID(dev_priv, BXT_REVID_C0, REVID_FOREVER)) 12048621f407SFrançois Tigeot WA_SET_BIT(GEN9_GAMT_ECO_REG_RW_IA, 12058621f407SFrançois Tigeot GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS); 12068621f407SFrançois Tigeot 120719c468b4SFrançois Tigeot return 0; 120819c468b4SFrançois Tigeot } 120919c468b4SFrançois Tigeot 12108621f407SFrançois Tigeot static int kbl_init_workarounds(struct intel_engine_cs *engine) 12112c9916cdSFrançois Tigeot { 12128621f407SFrançois Tigeot struct drm_i915_private *dev_priv = engine->dev->dev_private; 12138621f407SFrançois Tigeot int ret; 12148621f407SFrançois Tigeot 12158621f407SFrançois Tigeot ret = gen9_init_workarounds(engine); 12168621f407SFrançois Tigeot if (ret) 12178621f407SFrançois Tigeot return ret; 12188621f407SFrançois Tigeot 12198621f407SFrançois Tigeot /* WaEnableGapsTsvCreditFix:kbl */ 12208621f407SFrançois Tigeot I915_WRITE(GEN8_GARBCNTL, (I915_READ(GEN8_GARBCNTL) | 12218621f407SFrançois Tigeot GEN9_GAPS_TSV_CREDIT_DISABLE)); 12228621f407SFrançois Tigeot 12238621f407SFrançois Tigeot /* WaDisableDynamicCreditSharing:kbl */ 12248621f407SFrançois Tigeot if (IS_KBL_REVID(dev_priv, 0, KBL_REVID_B0)) 12258621f407SFrançois Tigeot WA_SET_BIT(GAMT_CHKN_BIT_REG, 12268621f407SFrançois Tigeot GAMT_CHKN_DISABLE_DYNAMIC_CREDIT_SHARING); 12278621f407SFrançois Tigeot 12288621f407SFrançois Tigeot /* WaDisableFenceDestinationToSLM:kbl (pre-prod) */ 12298621f407SFrançois Tigeot if (IS_KBL_REVID(dev_priv, KBL_REVID_A0, KBL_REVID_A0)) 12308621f407SFrançois Tigeot WA_SET_BIT_MASKED(HDC_CHICKEN0, 12318621f407SFrançois Tigeot HDC_FENCE_DEST_SLM_DISABLE); 12328621f407SFrançois Tigeot 12338621f407SFrançois Tigeot /* GEN8_L3SQCREG4 has a dependency with WA batch so any new changes 12348621f407SFrançois Tigeot * involving this register should also be added to WA batch as required. 12358621f407SFrançois Tigeot */ 12368621f407SFrançois Tigeot if (IS_KBL_REVID(dev_priv, 0, KBL_REVID_E0)) 12378621f407SFrançois Tigeot /* WaDisableLSQCROPERFforOCL:kbl */ 12388621f407SFrançois Tigeot I915_WRITE(GEN8_L3SQCREG4, I915_READ(GEN8_L3SQCREG4) | 12398621f407SFrançois Tigeot GEN8_LQSC_RO_PERF_DIS); 12408621f407SFrançois Tigeot 12418621f407SFrançois Tigeot /* WaInsertDummyPushConstPs:kbl */ 12428621f407SFrançois Tigeot if (IS_KBL_REVID(dev_priv, 0, KBL_REVID_B0)) 12438621f407SFrançois Tigeot WA_SET_BIT_MASKED(COMMON_SLICE_CHICKEN2, 12448621f407SFrançois Tigeot GEN8_SBE_DISABLE_REPLAY_BUF_OPTIMIZATION); 12458621f407SFrançois Tigeot 12468621f407SFrançois Tigeot /* WaDisableGafsUnitClkGating:kbl */ 12478621f407SFrançois Tigeot WA_SET_BIT(GEN7_UCGCTL4, GEN8_EU_GAUNIT_CLOCK_GATE_DISABLE); 12488621f407SFrançois Tigeot 12498621f407SFrançois Tigeot /* WaDisableSbeCacheDispatchPortSharing:kbl */ 12508621f407SFrançois Tigeot WA_SET_BIT_MASKED( 12518621f407SFrançois Tigeot GEN7_HALF_SLICE_CHICKEN1, 12528621f407SFrançois Tigeot GEN7_SBE_SS_CACHE_DISPATCH_PORT_SHARING_DISABLE); 12538621f407SFrançois Tigeot 12548621f407SFrançois Tigeot /* WaInPlaceDecompressionHang:kbl */ 12558621f407SFrançois Tigeot WA_SET_BIT(GEN9_GAMT_ECO_REG_RW_IA, 12568621f407SFrançois Tigeot GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS); 12578621f407SFrançois Tigeot 12588621f407SFrançois Tigeot /* WaDisableLSQCROPERFforOCL:kbl */ 12598621f407SFrançois Tigeot ret = wa_ring_whitelist_reg(engine, GEN8_L3SQCREG4); 12608621f407SFrançois Tigeot if (ret) 12618621f407SFrançois Tigeot return ret; 12628621f407SFrançois Tigeot 12638621f407SFrançois Tigeot return 0; 12648621f407SFrançois Tigeot } 12658621f407SFrançois Tigeot 12668621f407SFrançois Tigeot int init_workarounds_ring(struct intel_engine_cs *engine) 12678621f407SFrançois Tigeot { 12688621f407SFrançois Tigeot struct drm_device *dev = engine->dev; 12692c9916cdSFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 12702c9916cdSFrançois Tigeot 12718621f407SFrançois Tigeot WARN_ON(engine->id != RCS); 12722c9916cdSFrançois Tigeot 12732c9916cdSFrançois Tigeot dev_priv->workarounds.count = 0; 1274c0e85e96SFrançois Tigeot dev_priv->workarounds.hw_whitelist_count[RCS] = 0; 12752c9916cdSFrançois Tigeot 12762c9916cdSFrançois Tigeot if (IS_BROADWELL(dev)) 12778621f407SFrançois Tigeot return bdw_init_workarounds(engine); 12782c9916cdSFrançois Tigeot 12792c9916cdSFrançois Tigeot if (IS_CHERRYVIEW(dev)) 12808621f407SFrançois Tigeot return chv_init_workarounds(engine); 12811b13d190SFrançois Tigeot 1282477eb7f9SFrançois Tigeot if (IS_SKYLAKE(dev)) 12838621f407SFrançois Tigeot return skl_init_workarounds(engine); 128419c468b4SFrançois Tigeot 128519c468b4SFrançois Tigeot if (IS_BROXTON(dev)) 12868621f407SFrançois Tigeot return bxt_init_workarounds(engine); 12878621f407SFrançois Tigeot 12888621f407SFrançois Tigeot if (IS_KABYLAKE(dev_priv)) 12898621f407SFrançois Tigeot return kbl_init_workarounds(engine); 1290477eb7f9SFrançois Tigeot 12911b13d190SFrançois Tigeot return 0; 12921b13d190SFrançois Tigeot } 12931b13d190SFrançois Tigeot 12948621f407SFrançois Tigeot static int init_render_ring(struct intel_engine_cs *engine) 1295e3adcf8fSFrançois Tigeot { 12968621f407SFrançois Tigeot struct drm_device *dev = engine->dev; 1297e3adcf8fSFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 12988621f407SFrançois Tigeot int ret = init_ring_common(engine); 129924edb884SFrançois Tigeot if (ret) 130024edb884SFrançois Tigeot return ret; 1301e3adcf8fSFrançois Tigeot 1302ba55f2f5SFrançois Tigeot /* WaTimedSingleVertexDispatch:cl,bw,ctg,elk,ilk,snb */ 1303ba55f2f5SFrançois Tigeot if (INTEL_INFO(dev)->gen >= 4 && INTEL_INFO(dev)->gen < 7) 1304f4e1c372SFrançois Tigeot I915_WRITE(MI_MODE, _MASKED_BIT_ENABLE(VS_TIMER_DISPATCH)); 1305f4e1c372SFrançois Tigeot 1306f4e1c372SFrançois Tigeot /* We need to disable the AsyncFlip performance optimisations in order 1307f4e1c372SFrançois Tigeot * to use MI_WAIT_FOR_EVENT within the CS. It should already be 1308f4e1c372SFrançois Tigeot * programmed to '1' on all products. 13095d0b1887SFrançois Tigeot * 1310a05eeebfSFrançois Tigeot * WaDisableAsyncFlipPerfMode:snb,ivb,hsw,vlv 1311f4e1c372SFrançois Tigeot */ 1312a05eeebfSFrançois Tigeot if (INTEL_INFO(dev)->gen >= 6 && INTEL_INFO(dev)->gen < 8) 1313f4e1c372SFrançois Tigeot I915_WRITE(MI_MODE, _MASKED_BIT_ENABLE(ASYNC_FLIP_PERF_DISABLE)); 1314f4e1c372SFrançois Tigeot 1315f4e1c372SFrançois Tigeot /* Required for the hardware to program scanline values for waiting */ 1316ba55f2f5SFrançois Tigeot /* WaEnableFlushTlbInvalidationMode:snb */ 1317f4e1c372SFrançois Tigeot if (INTEL_INFO(dev)->gen == 6) 1318f4e1c372SFrançois Tigeot I915_WRITE(GFX_MODE, 1319ba55f2f5SFrançois Tigeot _MASKED_BIT_ENABLE(GFX_TLB_INVALIDATE_EXPLICIT)); 1320f4e1c372SFrançois Tigeot 1321ba55f2f5SFrançois Tigeot /* WaBCSVCSTlbInvalidationMode:ivb,vlv,hsw */ 1322e3adcf8fSFrançois Tigeot if (IS_GEN7(dev)) 1323e3adcf8fSFrançois Tigeot I915_WRITE(GFX_MODE_GEN7, 1324ba55f2f5SFrançois Tigeot _MASKED_BIT_ENABLE(GFX_TLB_INVALIDATE_EXPLICIT) | 1325f4e1c372SFrançois Tigeot _MASKED_BIT_ENABLE(GFX_REPLAY_MODE)); 1326e3adcf8fSFrançois Tigeot 1327e3adcf8fSFrançois Tigeot if (IS_GEN6(dev)) { 1328e3adcf8fSFrançois Tigeot /* From the Sandybridge PRM, volume 1 part 3, page 24: 1329e3adcf8fSFrançois Tigeot * "If this bit is set, STCunit will have LRA as replacement 1330e3adcf8fSFrançois Tigeot * policy. [...] This bit must be reset. LRA replacement 1331e3adcf8fSFrançois Tigeot * policy is not supported." 1332e3adcf8fSFrançois Tigeot */ 1333e3adcf8fSFrançois Tigeot I915_WRITE(CACHE_MODE_0, 1334f4e1c372SFrançois Tigeot _MASKED_BIT_DISABLE(CM0_STC_EVICT_DISABLE_LRA_SNB)); 1335e3adcf8fSFrançois Tigeot } 1336e3adcf8fSFrançois Tigeot 1337a05eeebfSFrançois Tigeot if (INTEL_INFO(dev)->gen >= 6 && INTEL_INFO(dev)->gen < 8) 1338f4e1c372SFrançois Tigeot I915_WRITE(INSTPM, _MASKED_BIT_ENABLE(INSTPM_FORCE_ORDERING)); 1339f4e1c372SFrançois Tigeot 13409edbd4a0SFrançois Tigeot if (HAS_L3_DPF(dev)) 13418621f407SFrançois Tigeot I915_WRITE_IMR(engine, ~GT_PARITY_ERROR(dev)); 1342e3adcf8fSFrançois Tigeot 13438621f407SFrançois Tigeot return init_workarounds_ring(engine); 1344e3adcf8fSFrançois Tigeot } 1345e3adcf8fSFrançois Tigeot 13468621f407SFrançois Tigeot static void render_ring_cleanup(struct intel_engine_cs *engine) 1347e3adcf8fSFrançois Tigeot { 13488621f407SFrançois Tigeot struct drm_device *dev = engine->dev; 134924edb884SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 135024edb884SFrançois Tigeot 135124edb884SFrançois Tigeot if (dev_priv->semaphore_obj) { 135224edb884SFrançois Tigeot i915_gem_object_ggtt_unpin(dev_priv->semaphore_obj); 135324edb884SFrançois Tigeot drm_gem_object_unreference(&dev_priv->semaphore_obj->base); 135424edb884SFrançois Tigeot dev_priv->semaphore_obj = NULL; 135524edb884SFrançois Tigeot } 1356b5c29a34SFrançois Tigeot 13578621f407SFrançois Tigeot intel_fini_pipe_control(engine); 1358e3adcf8fSFrançois Tigeot } 1359e3adcf8fSFrançois Tigeot 1360a05eeebfSFrançois Tigeot static int gen8_rcs_signal(struct drm_i915_gem_request *signaller_req, 136124edb884SFrançois Tigeot unsigned int num_dwords) 136224edb884SFrançois Tigeot { 136324edb884SFrançois Tigeot #define MBOX_UPDATE_DWORDS 8 13648621f407SFrançois Tigeot struct intel_engine_cs *signaller = signaller_req->engine; 136524edb884SFrançois Tigeot struct drm_device *dev = signaller->dev; 136624edb884SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 136724edb884SFrançois Tigeot struct intel_engine_cs *waiter; 13688621f407SFrançois Tigeot enum intel_engine_id id; 13698621f407SFrançois Tigeot int ret, num_rings; 137024edb884SFrançois Tigeot 137124edb884SFrançois Tigeot num_rings = hweight32(INTEL_INFO(dev)->ring_mask); 137224edb884SFrançois Tigeot num_dwords += (num_rings-1) * MBOX_UPDATE_DWORDS; 137324edb884SFrançois Tigeot #undef MBOX_UPDATE_DWORDS 137424edb884SFrançois Tigeot 1375a05eeebfSFrançois Tigeot ret = intel_ring_begin(signaller_req, num_dwords); 137624edb884SFrançois Tigeot if (ret) 137724edb884SFrançois Tigeot return ret; 137824edb884SFrançois Tigeot 13798621f407SFrançois Tigeot for_each_engine_id(waiter, dev_priv, id) { 13802c9916cdSFrançois Tigeot u32 seqno; 13818621f407SFrançois Tigeot u64 gtt_offset = signaller->semaphore.signal_ggtt[id]; 138224edb884SFrançois Tigeot if (gtt_offset == MI_SEMAPHORE_SYNC_INVALID) 138324edb884SFrançois Tigeot continue; 138424edb884SFrançois Tigeot 1385a05eeebfSFrançois Tigeot seqno = i915_gem_request_get_seqno(signaller_req); 138624edb884SFrançois Tigeot intel_ring_emit(signaller, GFX_OP_PIPE_CONTROL(6)); 138724edb884SFrançois Tigeot intel_ring_emit(signaller, PIPE_CONTROL_GLOBAL_GTT_IVB | 138824edb884SFrançois Tigeot PIPE_CONTROL_QW_WRITE | 138924edb884SFrançois Tigeot PIPE_CONTROL_FLUSH_ENABLE); 139024edb884SFrançois Tigeot intel_ring_emit(signaller, lower_32_bits(gtt_offset)); 139124edb884SFrançois Tigeot intel_ring_emit(signaller, upper_32_bits(gtt_offset)); 13922c9916cdSFrançois Tigeot intel_ring_emit(signaller, seqno); 139324edb884SFrançois Tigeot intel_ring_emit(signaller, 0); 139424edb884SFrançois Tigeot intel_ring_emit(signaller, MI_SEMAPHORE_SIGNAL | 13958621f407SFrançois Tigeot MI_SEMAPHORE_TARGET(waiter->hw_id)); 139624edb884SFrançois Tigeot intel_ring_emit(signaller, 0); 139724edb884SFrançois Tigeot } 139824edb884SFrançois Tigeot 139924edb884SFrançois Tigeot return 0; 140024edb884SFrançois Tigeot } 140124edb884SFrançois Tigeot 1402a05eeebfSFrançois Tigeot static int gen8_xcs_signal(struct drm_i915_gem_request *signaller_req, 140324edb884SFrançois Tigeot unsigned int num_dwords) 140424edb884SFrançois Tigeot { 140524edb884SFrançois Tigeot #define MBOX_UPDATE_DWORDS 6 14068621f407SFrançois Tigeot struct intel_engine_cs *signaller = signaller_req->engine; 140724edb884SFrançois Tigeot struct drm_device *dev = signaller->dev; 140824edb884SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 140924edb884SFrançois Tigeot struct intel_engine_cs *waiter; 14108621f407SFrançois Tigeot enum intel_engine_id id; 14118621f407SFrançois Tigeot int ret, num_rings; 141224edb884SFrançois Tigeot 141324edb884SFrançois Tigeot num_rings = hweight32(INTEL_INFO(dev)->ring_mask); 141424edb884SFrançois Tigeot num_dwords += (num_rings-1) * MBOX_UPDATE_DWORDS; 141524edb884SFrançois Tigeot #undef MBOX_UPDATE_DWORDS 141624edb884SFrançois Tigeot 1417a05eeebfSFrançois Tigeot ret = intel_ring_begin(signaller_req, num_dwords); 141824edb884SFrançois Tigeot if (ret) 141924edb884SFrançois Tigeot return ret; 142024edb884SFrançois Tigeot 14218621f407SFrançois Tigeot for_each_engine_id(waiter, dev_priv, id) { 14222c9916cdSFrançois Tigeot u32 seqno; 14238621f407SFrançois Tigeot u64 gtt_offset = signaller->semaphore.signal_ggtt[id]; 142424edb884SFrançois Tigeot if (gtt_offset == MI_SEMAPHORE_SYNC_INVALID) 142524edb884SFrançois Tigeot continue; 142624edb884SFrançois Tigeot 1427a05eeebfSFrançois Tigeot seqno = i915_gem_request_get_seqno(signaller_req); 142824edb884SFrançois Tigeot intel_ring_emit(signaller, (MI_FLUSH_DW + 1) | 142924edb884SFrançois Tigeot MI_FLUSH_DW_OP_STOREDW); 143024edb884SFrançois Tigeot intel_ring_emit(signaller, lower_32_bits(gtt_offset) | 143124edb884SFrançois Tigeot MI_FLUSH_DW_USE_GTT); 143224edb884SFrançois Tigeot intel_ring_emit(signaller, upper_32_bits(gtt_offset)); 14332c9916cdSFrançois Tigeot intel_ring_emit(signaller, seqno); 143424edb884SFrançois Tigeot intel_ring_emit(signaller, MI_SEMAPHORE_SIGNAL | 14358621f407SFrançois Tigeot MI_SEMAPHORE_TARGET(waiter->hw_id)); 143624edb884SFrançois Tigeot intel_ring_emit(signaller, 0); 143724edb884SFrançois Tigeot } 143824edb884SFrançois Tigeot 143924edb884SFrançois Tigeot return 0; 144024edb884SFrançois Tigeot } 144124edb884SFrançois Tigeot 1442a05eeebfSFrançois Tigeot static int gen6_signal(struct drm_i915_gem_request *signaller_req, 1443ba55f2f5SFrançois Tigeot unsigned int num_dwords) 1444e3adcf8fSFrançois Tigeot { 14458621f407SFrançois Tigeot struct intel_engine_cs *signaller = signaller_req->engine; 1446ba55f2f5SFrançois Tigeot struct drm_device *dev = signaller->dev; 1447ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 1448ba55f2f5SFrançois Tigeot struct intel_engine_cs *useless; 14498621f407SFrançois Tigeot enum intel_engine_id id; 14508621f407SFrançois Tigeot int ret, num_rings; 1451ba55f2f5SFrançois Tigeot 145224edb884SFrançois Tigeot #define MBOX_UPDATE_DWORDS 3 145324edb884SFrançois Tigeot num_rings = hweight32(INTEL_INFO(dev)->ring_mask); 145424edb884SFrançois Tigeot num_dwords += round_up((num_rings-1) * MBOX_UPDATE_DWORDS, 2); 145524edb884SFrançois Tigeot #undef MBOX_UPDATE_DWORDS 1456ba55f2f5SFrançois Tigeot 1457a05eeebfSFrançois Tigeot ret = intel_ring_begin(signaller_req, num_dwords); 1458ba55f2f5SFrançois Tigeot if (ret) 1459ba55f2f5SFrançois Tigeot return ret; 1460ba55f2f5SFrançois Tigeot 14618621f407SFrançois Tigeot for_each_engine_id(useless, dev_priv, id) { 14628621f407SFrançois Tigeot i915_reg_t mbox_reg = signaller->semaphore.mbox.signal[id]; 1463aee94f86SFrançois Tigeot 1464aee94f86SFrançois Tigeot if (i915_mmio_reg_valid(mbox_reg)) { 1465a05eeebfSFrançois Tigeot u32 seqno = i915_gem_request_get_seqno(signaller_req); 1466aee94f86SFrançois Tigeot 1467ba55f2f5SFrançois Tigeot intel_ring_emit(signaller, MI_LOAD_REGISTER_IMM(1)); 1468aee94f86SFrançois Tigeot intel_ring_emit_reg(signaller, mbox_reg); 14692c9916cdSFrançois Tigeot intel_ring_emit(signaller, seqno); 1470ba55f2f5SFrançois Tigeot } 1471ba55f2f5SFrançois Tigeot } 1472ba55f2f5SFrançois Tigeot 147324edb884SFrançois Tigeot /* If num_dwords was rounded, make sure the tail pointer is correct */ 147424edb884SFrançois Tigeot if (num_rings % 2 == 0) 147524edb884SFrançois Tigeot intel_ring_emit(signaller, MI_NOOP); 147624edb884SFrançois Tigeot 1477ba55f2f5SFrançois Tigeot return 0; 1478e3adcf8fSFrançois Tigeot } 1479e3adcf8fSFrançois Tigeot 1480e3adcf8fSFrançois Tigeot /** 1481e3adcf8fSFrançois Tigeot * gen6_add_request - Update the semaphore mailbox registers 1482e3adcf8fSFrançois Tigeot * 1483a05eeebfSFrançois Tigeot * @request - request to write to the ring 1484e3adcf8fSFrançois Tigeot * 1485e3adcf8fSFrançois Tigeot * Update the mailbox registers in the *other* rings with the current seqno. 1486e3adcf8fSFrançois Tigeot * This acts like a signal in the canonical semaphore. 1487e3adcf8fSFrançois Tigeot */ 1488e3adcf8fSFrançois Tigeot static int 1489a05eeebfSFrançois Tigeot gen6_add_request(struct drm_i915_gem_request *req) 1490e3adcf8fSFrançois Tigeot { 14918621f407SFrançois Tigeot struct intel_engine_cs *engine = req->engine; 1492ba55f2f5SFrançois Tigeot int ret; 1493e3adcf8fSFrançois Tigeot 14948621f407SFrançois Tigeot if (engine->semaphore.signal) 14958621f407SFrançois Tigeot ret = engine->semaphore.signal(req, 4); 149624edb884SFrançois Tigeot else 1497a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 4); 149824edb884SFrançois Tigeot 14999edbd4a0SFrançois Tigeot if (ret) 15009edbd4a0SFrançois Tigeot return ret; 15019edbd4a0SFrançois Tigeot 15028621f407SFrançois Tigeot intel_ring_emit(engine, MI_STORE_DWORD_INDEX); 15038621f407SFrançois Tigeot intel_ring_emit(engine, 15048621f407SFrançois Tigeot I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT); 15058621f407SFrançois Tigeot intel_ring_emit(engine, i915_gem_request_get_seqno(req)); 15068621f407SFrançois Tigeot intel_ring_emit(engine, MI_USER_INTERRUPT); 15078621f407SFrançois Tigeot __intel_ring_advance(engine); 1508e3adcf8fSFrançois Tigeot 1509e3adcf8fSFrançois Tigeot return 0; 1510e3adcf8fSFrançois Tigeot } 1511e3adcf8fSFrançois Tigeot 1512a2fdbec6SFrançois Tigeot static inline bool i915_gem_has_seqno_wrapped(struct drm_device *dev, 1513a2fdbec6SFrançois Tigeot u32 seqno) 1514a2fdbec6SFrançois Tigeot { 1515a2fdbec6SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 1516a2fdbec6SFrançois Tigeot return dev_priv->last_seqno < seqno; 1517a2fdbec6SFrançois Tigeot } 1518a2fdbec6SFrançois Tigeot 1519e3adcf8fSFrançois Tigeot /** 1520e3adcf8fSFrançois Tigeot * intel_ring_sync - sync the waiter to the signaller on seqno 1521e3adcf8fSFrançois Tigeot * 1522e3adcf8fSFrançois Tigeot * @waiter - ring that is waiting 1523e3adcf8fSFrançois Tigeot * @signaller - ring which has, or will signal 1524e3adcf8fSFrançois Tigeot * @seqno - seqno which the waiter will block on 1525e3adcf8fSFrançois Tigeot */ 152624edb884SFrançois Tigeot 152724edb884SFrançois Tigeot static int 1528a05eeebfSFrançois Tigeot gen8_ring_sync(struct drm_i915_gem_request *waiter_req, 152924edb884SFrançois Tigeot struct intel_engine_cs *signaller, 153024edb884SFrançois Tigeot u32 seqno) 153124edb884SFrançois Tigeot { 15328621f407SFrançois Tigeot struct intel_engine_cs *waiter = waiter_req->engine; 153324edb884SFrançois Tigeot struct drm_i915_private *dev_priv = waiter->dev->dev_private; 153424edb884SFrançois Tigeot int ret; 153524edb884SFrançois Tigeot 1536a05eeebfSFrançois Tigeot ret = intel_ring_begin(waiter_req, 4); 153724edb884SFrançois Tigeot if (ret) 153824edb884SFrançois Tigeot return ret; 153924edb884SFrançois Tigeot 154024edb884SFrançois Tigeot intel_ring_emit(waiter, MI_SEMAPHORE_WAIT | 154124edb884SFrançois Tigeot MI_SEMAPHORE_GLOBAL_GTT | 154224edb884SFrançois Tigeot MI_SEMAPHORE_POLL | 154324edb884SFrançois Tigeot MI_SEMAPHORE_SAD_GTE_SDD); 154424edb884SFrançois Tigeot intel_ring_emit(waiter, seqno); 154524edb884SFrançois Tigeot intel_ring_emit(waiter, 154624edb884SFrançois Tigeot lower_32_bits(GEN8_WAIT_OFFSET(waiter, signaller->id))); 154724edb884SFrançois Tigeot intel_ring_emit(waiter, 154824edb884SFrançois Tigeot upper_32_bits(GEN8_WAIT_OFFSET(waiter, signaller->id))); 154924edb884SFrançois Tigeot intel_ring_advance(waiter); 155024edb884SFrançois Tigeot return 0; 155124edb884SFrançois Tigeot } 155224edb884SFrançois Tigeot 1553e3adcf8fSFrançois Tigeot static int 1554a05eeebfSFrançois Tigeot gen6_ring_sync(struct drm_i915_gem_request *waiter_req, 1555ba55f2f5SFrançois Tigeot struct intel_engine_cs *signaller, 1556e3adcf8fSFrançois Tigeot u32 seqno) 1557e3adcf8fSFrançois Tigeot { 15588621f407SFrançois Tigeot struct intel_engine_cs *waiter = waiter_req->engine; 1559e3adcf8fSFrançois Tigeot u32 dw1 = MI_SEMAPHORE_MBOX | 1560e3adcf8fSFrançois Tigeot MI_SEMAPHORE_COMPARE | 1561e3adcf8fSFrançois Tigeot MI_SEMAPHORE_REGISTER; 1562ba55f2f5SFrançois Tigeot u32 wait_mbox = signaller->semaphore.mbox.wait[waiter->id]; 1563ba55f2f5SFrançois Tigeot int ret; 1564e3adcf8fSFrançois Tigeot 1565686a02f1SFrançois Tigeot /* Throughout all of the GEM code, seqno passed implies our current 1566686a02f1SFrançois Tigeot * seqno is >= the last seqno executed. However for hardware the 1567686a02f1SFrançois Tigeot * comparison is strictly greater than. 1568686a02f1SFrançois Tigeot */ 1569686a02f1SFrançois Tigeot seqno -= 1; 1570686a02f1SFrançois Tigeot 1571ba55f2f5SFrançois Tigeot WARN_ON(wait_mbox == MI_SEMAPHORE_SYNC_INVALID); 1572686a02f1SFrançois Tigeot 1573a05eeebfSFrançois Tigeot ret = intel_ring_begin(waiter_req, 4); 1574e3adcf8fSFrançois Tigeot if (ret) 1575e3adcf8fSFrançois Tigeot return ret; 1576e3adcf8fSFrançois Tigeot 1577a2fdbec6SFrançois Tigeot /* If seqno wrap happened, omit the wait with no-ops */ 1578a2fdbec6SFrançois Tigeot if (likely(!i915_gem_has_seqno_wrapped(waiter->dev, seqno))) { 1579ba55f2f5SFrançois Tigeot intel_ring_emit(waiter, dw1 | wait_mbox); 1580e3adcf8fSFrançois Tigeot intel_ring_emit(waiter, seqno); 1581e3adcf8fSFrançois Tigeot intel_ring_emit(waiter, 0); 1582e3adcf8fSFrançois Tigeot intel_ring_emit(waiter, MI_NOOP); 1583a2fdbec6SFrançois Tigeot } else { 1584a2fdbec6SFrançois Tigeot intel_ring_emit(waiter, MI_NOOP); 1585a2fdbec6SFrançois Tigeot intel_ring_emit(waiter, MI_NOOP); 1586a2fdbec6SFrançois Tigeot intel_ring_emit(waiter, MI_NOOP); 1587a2fdbec6SFrançois Tigeot intel_ring_emit(waiter, MI_NOOP); 1588a2fdbec6SFrançois Tigeot } 1589e3adcf8fSFrançois Tigeot intel_ring_advance(waiter); 1590e3adcf8fSFrançois Tigeot 1591e3adcf8fSFrançois Tigeot return 0; 1592e3adcf8fSFrançois Tigeot } 1593e3adcf8fSFrançois Tigeot 1594e3adcf8fSFrançois Tigeot #define PIPE_CONTROL_FLUSH(ring__, addr__) \ 1595e3adcf8fSFrançois Tigeot do { \ 1596e3adcf8fSFrançois Tigeot intel_ring_emit(ring__, GFX_OP_PIPE_CONTROL(4) | PIPE_CONTROL_QW_WRITE | \ 1597e3adcf8fSFrançois Tigeot PIPE_CONTROL_DEPTH_STALL); \ 1598e3adcf8fSFrançois Tigeot intel_ring_emit(ring__, (addr__) | PIPE_CONTROL_GLOBAL_GTT); \ 1599e3adcf8fSFrançois Tigeot intel_ring_emit(ring__, 0); \ 1600e3adcf8fSFrançois Tigeot intel_ring_emit(ring__, 0); \ 1601e3adcf8fSFrançois Tigeot } while (0) 1602e3adcf8fSFrançois Tigeot 1603e3adcf8fSFrançois Tigeot static int 1604a05eeebfSFrançois Tigeot pc_render_add_request(struct drm_i915_gem_request *req) 1605e3adcf8fSFrançois Tigeot { 16068621f407SFrançois Tigeot struct intel_engine_cs *engine = req->engine; 16078621f407SFrançois Tigeot u32 scratch_addr = engine->scratch.gtt_offset + 2 * CACHELINE_BYTES; 1608e3adcf8fSFrançois Tigeot int ret; 1609e3adcf8fSFrançois Tigeot 1610e3adcf8fSFrançois Tigeot /* For Ironlake, MI_USER_INTERRUPT was deprecated and apparently 1611e3adcf8fSFrançois Tigeot * incoherent with writes to memory, i.e. completely fubar, 1612e3adcf8fSFrançois Tigeot * so we need to use PIPE_NOTIFY instead. 1613e3adcf8fSFrançois Tigeot * 1614e3adcf8fSFrançois Tigeot * However, we also need to workaround the qword write 1615e3adcf8fSFrançois Tigeot * incoherence by flushing the 6 PIPE_NOTIFY buffers out to 1616e3adcf8fSFrançois Tigeot * memory before requesting an interrupt. 1617e3adcf8fSFrançois Tigeot */ 1618a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 32); 1619e3adcf8fSFrançois Tigeot if (ret) 1620e3adcf8fSFrançois Tigeot return ret; 1621e3adcf8fSFrançois Tigeot 16228621f407SFrançois Tigeot intel_ring_emit(engine, 16238621f407SFrançois Tigeot GFX_OP_PIPE_CONTROL(4) | PIPE_CONTROL_QW_WRITE | 1624e3adcf8fSFrançois Tigeot PIPE_CONTROL_WRITE_FLUSH | 1625e3adcf8fSFrançois Tigeot PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE); 16268621f407SFrançois Tigeot intel_ring_emit(engine, 16278621f407SFrançois Tigeot engine->scratch.gtt_offset | PIPE_CONTROL_GLOBAL_GTT); 16288621f407SFrançois Tigeot intel_ring_emit(engine, i915_gem_request_get_seqno(req)); 16298621f407SFrançois Tigeot intel_ring_emit(engine, 0); 16308621f407SFrançois Tigeot PIPE_CONTROL_FLUSH(engine, scratch_addr); 1631ba55f2f5SFrançois Tigeot scratch_addr += 2 * CACHELINE_BYTES; /* write to separate cachelines */ 16328621f407SFrançois Tigeot PIPE_CONTROL_FLUSH(engine, scratch_addr); 1633ba55f2f5SFrançois Tigeot scratch_addr += 2 * CACHELINE_BYTES; 16348621f407SFrançois Tigeot PIPE_CONTROL_FLUSH(engine, scratch_addr); 1635ba55f2f5SFrançois Tigeot scratch_addr += 2 * CACHELINE_BYTES; 16368621f407SFrançois Tigeot PIPE_CONTROL_FLUSH(engine, scratch_addr); 1637ba55f2f5SFrançois Tigeot scratch_addr += 2 * CACHELINE_BYTES; 16388621f407SFrançois Tigeot PIPE_CONTROL_FLUSH(engine, scratch_addr); 1639ba55f2f5SFrançois Tigeot scratch_addr += 2 * CACHELINE_BYTES; 16408621f407SFrançois Tigeot PIPE_CONTROL_FLUSH(engine, scratch_addr); 1641b5c29a34SFrançois Tigeot 16428621f407SFrançois Tigeot intel_ring_emit(engine, 16438621f407SFrançois Tigeot GFX_OP_PIPE_CONTROL(4) | PIPE_CONTROL_QW_WRITE | 1644e3adcf8fSFrançois Tigeot PIPE_CONTROL_WRITE_FLUSH | 1645e3adcf8fSFrançois Tigeot PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE | 1646e3adcf8fSFrançois Tigeot PIPE_CONTROL_NOTIFY); 16478621f407SFrançois Tigeot intel_ring_emit(engine, 16488621f407SFrançois Tigeot engine->scratch.gtt_offset | PIPE_CONTROL_GLOBAL_GTT); 16498621f407SFrançois Tigeot intel_ring_emit(engine, i915_gem_request_get_seqno(req)); 16508621f407SFrançois Tigeot intel_ring_emit(engine, 0); 16518621f407SFrançois Tigeot __intel_ring_advance(engine); 1652e3adcf8fSFrançois Tigeot 1653e3adcf8fSFrançois Tigeot return 0; 1654e3adcf8fSFrançois Tigeot } 1655e3adcf8fSFrançois Tigeot 16568621f407SFrançois Tigeot static void 16578621f407SFrançois Tigeot gen6_seqno_barrier(struct intel_engine_cs *engine) 1658e3adcf8fSFrançois Tigeot { 16598621f407SFrançois Tigeot struct drm_i915_private *dev_priv = engine->dev->dev_private; 16608621f407SFrançois Tigeot 1661e3adcf8fSFrançois Tigeot /* Workaround to force correct ordering between irq and seqno writes on 1662e3adcf8fSFrançois Tigeot * ivb (and maybe also on snb) by reading from a CS register (like 16638621f407SFrançois Tigeot * ACTHD) before reading the status page. 16648621f407SFrançois Tigeot * 16658621f407SFrançois Tigeot * Note that this effectively stalls the read by the time it takes to 16668621f407SFrançois Tigeot * do a memory transaction, which more or less ensures that the write 16678621f407SFrançois Tigeot * from the GPU has sufficient time to invalidate the CPU cacheline. 16688621f407SFrançois Tigeot * Alternatively we could delay the interrupt from the CS ring to give 16698621f407SFrançois Tigeot * the write time to land, but that would incur a delay after every 16708621f407SFrançois Tigeot * batch i.e. much more frequent than a delay when waiting for the 16718621f407SFrançois Tigeot * interrupt (with the same net latency). 16728621f407SFrançois Tigeot * 16738621f407SFrançois Tigeot * Also note that to prevent whole machine hangs on gen7, we have to 16748621f407SFrançois Tigeot * take the spinlock to guard against concurrent cacheline access. 16758621f407SFrançois Tigeot */ 16768621f407SFrançois Tigeot spin_lock_irq(&dev_priv->uncore.lock); 16778621f407SFrançois Tigeot POSTING_READ_FW(RING_ACTHD(engine->mmio_base)); 16788621f407SFrançois Tigeot spin_unlock_irq(&dev_priv->uncore.lock); 1679e3adcf8fSFrançois Tigeot } 1680e3adcf8fSFrançois Tigeot 1681b030f26bSFrançois Tigeot static u32 16828621f407SFrançois Tigeot ring_get_seqno(struct intel_engine_cs *engine) 1683e3adcf8fSFrançois Tigeot { 16848621f407SFrançois Tigeot return intel_read_status_page(engine, I915_GEM_HWS_INDEX); 1685e3adcf8fSFrançois Tigeot } 1686e3adcf8fSFrançois Tigeot 1687a2fdbec6SFrançois Tigeot static void 16888621f407SFrançois Tigeot ring_set_seqno(struct intel_engine_cs *engine, u32 seqno) 1689a2fdbec6SFrançois Tigeot { 16908621f407SFrançois Tigeot intel_write_status_page(engine, I915_GEM_HWS_INDEX, seqno); 1691a2fdbec6SFrançois Tigeot } 1692a2fdbec6SFrançois Tigeot 1693b030f26bSFrançois Tigeot static u32 16948621f407SFrançois Tigeot pc_render_get_seqno(struct intel_engine_cs *engine) 1695e3adcf8fSFrançois Tigeot { 16968621f407SFrançois Tigeot return engine->scratch.cpu_page[0]; 1697e3adcf8fSFrançois Tigeot } 1698e3adcf8fSFrançois Tigeot 1699a2fdbec6SFrançois Tigeot static void 17008621f407SFrançois Tigeot pc_render_set_seqno(struct intel_engine_cs *engine, u32 seqno) 1701a2fdbec6SFrançois Tigeot { 17028621f407SFrançois Tigeot engine->scratch.cpu_page[0] = seqno; 1703a2fdbec6SFrançois Tigeot } 1704a2fdbec6SFrançois Tigeot 1705e3adcf8fSFrançois Tigeot static bool 17068621f407SFrançois Tigeot gen5_ring_get_irq(struct intel_engine_cs *engine) 1707e3adcf8fSFrançois Tigeot { 17088621f407SFrançois Tigeot struct drm_device *dev = engine->dev; 1709ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 17105e269720SFrançois Tigeot unsigned long flags; 1711e3adcf8fSFrançois Tigeot 17122c9916cdSFrançois Tigeot if (WARN_ON(!intel_irqs_enabled(dev_priv))) 1713e3adcf8fSFrançois Tigeot return false; 1714e3adcf8fSFrançois Tigeot 17155e269720SFrançois Tigeot spin_lock_irqsave(&dev_priv->irq_lock, flags); 17168621f407SFrançois Tigeot if (engine->irq_refcount++ == 0) 17178621f407SFrançois Tigeot gen5_enable_gt_irq(dev_priv, engine->irq_enable_mask); 17185e269720SFrançois Tigeot spin_unlock_irqrestore(&dev_priv->irq_lock, flags); 1719e3adcf8fSFrançois Tigeot 1720e3adcf8fSFrançois Tigeot return true; 1721e3adcf8fSFrançois Tigeot } 1722e3adcf8fSFrançois Tigeot 1723e3adcf8fSFrançois Tigeot static void 17248621f407SFrançois Tigeot gen5_ring_put_irq(struct intel_engine_cs *engine) 1725e3adcf8fSFrançois Tigeot { 17268621f407SFrançois Tigeot struct drm_device *dev = engine->dev; 1727ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 17285e269720SFrançois Tigeot unsigned long flags; 1729e3adcf8fSFrançois Tigeot 17305e269720SFrançois Tigeot spin_lock_irqsave(&dev_priv->irq_lock, flags); 17318621f407SFrançois Tigeot if (--engine->irq_refcount == 0) 17328621f407SFrançois Tigeot gen5_disable_gt_irq(dev_priv, engine->irq_enable_mask); 17335e269720SFrançois Tigeot spin_unlock_irqrestore(&dev_priv->irq_lock, flags); 1734686a02f1SFrançois Tigeot } 1735686a02f1SFrançois Tigeot 1736686a02f1SFrançois Tigeot static bool 17378621f407SFrançois Tigeot i9xx_ring_get_irq(struct intel_engine_cs *engine) 1738686a02f1SFrançois Tigeot { 17398621f407SFrançois Tigeot struct drm_device *dev = engine->dev; 1740ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 17415e269720SFrançois Tigeot unsigned long flags; 1742686a02f1SFrançois Tigeot 17432c9916cdSFrançois Tigeot if (!intel_irqs_enabled(dev_priv)) 1744686a02f1SFrançois Tigeot return false; 1745686a02f1SFrançois Tigeot 17465e269720SFrançois Tigeot spin_lock_irqsave(&dev_priv->irq_lock, flags); 17478621f407SFrançois Tigeot if (engine->irq_refcount++ == 0) { 17488621f407SFrançois Tigeot dev_priv->irq_mask &= ~engine->irq_enable_mask; 1749686a02f1SFrançois Tigeot I915_WRITE(IMR, dev_priv->irq_mask); 1750686a02f1SFrançois Tigeot POSTING_READ(IMR); 1751686a02f1SFrançois Tigeot } 17525e269720SFrançois Tigeot spin_unlock_irqrestore(&dev_priv->irq_lock, flags); 1753686a02f1SFrançois Tigeot 1754686a02f1SFrançois Tigeot return true; 1755686a02f1SFrançois Tigeot } 1756686a02f1SFrançois Tigeot 1757686a02f1SFrançois Tigeot static void 17588621f407SFrançois Tigeot i9xx_ring_put_irq(struct intel_engine_cs *engine) 1759686a02f1SFrançois Tigeot { 17608621f407SFrançois Tigeot struct drm_device *dev = engine->dev; 1761ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 17625e269720SFrançois Tigeot unsigned long flags; 1763686a02f1SFrançois Tigeot 17645e269720SFrançois Tigeot spin_lock_irqsave(&dev_priv->irq_lock, flags); 17658621f407SFrançois Tigeot if (--engine->irq_refcount == 0) { 17668621f407SFrançois Tigeot dev_priv->irq_mask |= engine->irq_enable_mask; 1767686a02f1SFrançois Tigeot I915_WRITE(IMR, dev_priv->irq_mask); 1768686a02f1SFrançois Tigeot POSTING_READ(IMR); 1769686a02f1SFrançois Tigeot } 17705e269720SFrançois Tigeot spin_unlock_irqrestore(&dev_priv->irq_lock, flags); 1771686a02f1SFrançois Tigeot } 1772686a02f1SFrançois Tigeot 1773686a02f1SFrançois Tigeot static bool 17748621f407SFrançois Tigeot i8xx_ring_get_irq(struct intel_engine_cs *engine) 1775686a02f1SFrançois Tigeot { 17768621f407SFrançois Tigeot struct drm_device *dev = engine->dev; 1777ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 17785e269720SFrançois Tigeot unsigned long flags; 1779686a02f1SFrançois Tigeot 17802c9916cdSFrançois Tigeot if (!intel_irqs_enabled(dev_priv)) 1781686a02f1SFrançois Tigeot return false; 1782686a02f1SFrançois Tigeot 17835e269720SFrançois Tigeot spin_lock_irqsave(&dev_priv->irq_lock, flags); 17848621f407SFrançois Tigeot if (engine->irq_refcount++ == 0) { 17858621f407SFrançois Tigeot dev_priv->irq_mask &= ~engine->irq_enable_mask; 1786686a02f1SFrançois Tigeot I915_WRITE16(IMR, dev_priv->irq_mask); 1787686a02f1SFrançois Tigeot POSTING_READ16(IMR); 1788686a02f1SFrançois Tigeot } 17895e269720SFrançois Tigeot spin_unlock_irqrestore(&dev_priv->irq_lock, flags); 1790686a02f1SFrançois Tigeot 1791686a02f1SFrançois Tigeot return true; 1792686a02f1SFrançois Tigeot } 1793686a02f1SFrançois Tigeot 1794686a02f1SFrançois Tigeot static void 17958621f407SFrançois Tigeot i8xx_ring_put_irq(struct intel_engine_cs *engine) 1796686a02f1SFrançois Tigeot { 17978621f407SFrançois Tigeot struct drm_device *dev = engine->dev; 1798ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 17995e269720SFrançois Tigeot unsigned long flags; 1800686a02f1SFrançois Tigeot 18015e269720SFrançois Tigeot spin_lock_irqsave(&dev_priv->irq_lock, flags); 18028621f407SFrançois Tigeot if (--engine->irq_refcount == 0) { 18038621f407SFrançois Tigeot dev_priv->irq_mask |= engine->irq_enable_mask; 1804686a02f1SFrançois Tigeot I915_WRITE16(IMR, dev_priv->irq_mask); 1805686a02f1SFrançois Tigeot POSTING_READ16(IMR); 1806e3adcf8fSFrançois Tigeot } 18075e269720SFrançois Tigeot spin_unlock_irqrestore(&dev_priv->irq_lock, flags); 1808e3adcf8fSFrançois Tigeot } 1809e3adcf8fSFrançois Tigeot 1810e3adcf8fSFrançois Tigeot static int 1811a05eeebfSFrançois Tigeot bsd_ring_flush(struct drm_i915_gem_request *req, 1812b5c29a34SFrançois Tigeot u32 invalidate_domains, 1813b5c29a34SFrançois Tigeot u32 flush_domains) 1814e3adcf8fSFrançois Tigeot { 18158621f407SFrançois Tigeot struct intel_engine_cs *engine = req->engine; 1816e3adcf8fSFrançois Tigeot int ret; 1817e3adcf8fSFrançois Tigeot 1818a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 2); 1819e3adcf8fSFrançois Tigeot if (ret) 1820e3adcf8fSFrançois Tigeot return ret; 1821e3adcf8fSFrançois Tigeot 18228621f407SFrançois Tigeot intel_ring_emit(engine, MI_FLUSH); 18238621f407SFrançois Tigeot intel_ring_emit(engine, MI_NOOP); 18248621f407SFrançois Tigeot intel_ring_advance(engine); 1825e3adcf8fSFrançois Tigeot return 0; 1826e3adcf8fSFrançois Tigeot } 1827e3adcf8fSFrançois Tigeot 1828e3adcf8fSFrançois Tigeot static int 1829a05eeebfSFrançois Tigeot i9xx_add_request(struct drm_i915_gem_request *req) 1830e3adcf8fSFrançois Tigeot { 18318621f407SFrançois Tigeot struct intel_engine_cs *engine = req->engine; 1832e3adcf8fSFrançois Tigeot int ret; 1833e3adcf8fSFrançois Tigeot 1834a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 4); 1835e3adcf8fSFrançois Tigeot if (ret) 1836e3adcf8fSFrançois Tigeot return ret; 1837e3adcf8fSFrançois Tigeot 18388621f407SFrançois Tigeot intel_ring_emit(engine, MI_STORE_DWORD_INDEX); 18398621f407SFrançois Tigeot intel_ring_emit(engine, 18408621f407SFrançois Tigeot I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT); 18418621f407SFrançois Tigeot intel_ring_emit(engine, i915_gem_request_get_seqno(req)); 18428621f407SFrançois Tigeot intel_ring_emit(engine, MI_USER_INTERRUPT); 18438621f407SFrançois Tigeot __intel_ring_advance(engine); 1844e3adcf8fSFrançois Tigeot 1845e3adcf8fSFrançois Tigeot return 0; 1846e3adcf8fSFrançois Tigeot } 1847e3adcf8fSFrançois Tigeot 1848e3adcf8fSFrançois Tigeot static bool 18498621f407SFrançois Tigeot gen6_ring_get_irq(struct intel_engine_cs *engine) 1850e3adcf8fSFrançois Tigeot { 18518621f407SFrançois Tigeot struct drm_device *dev = engine->dev; 1852ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 18535e269720SFrançois Tigeot unsigned long flags; 1854e3adcf8fSFrançois Tigeot 18552c9916cdSFrançois Tigeot if (WARN_ON(!intel_irqs_enabled(dev_priv))) 1856e3adcf8fSFrançois Tigeot return false; 1857e3adcf8fSFrançois Tigeot 18585e269720SFrançois Tigeot spin_lock_irqsave(&dev_priv->irq_lock, flags); 18598621f407SFrançois Tigeot if (engine->irq_refcount++ == 0) { 18608621f407SFrançois Tigeot if (HAS_L3_DPF(dev) && engine->id == RCS) 18618621f407SFrançois Tigeot I915_WRITE_IMR(engine, 18628621f407SFrançois Tigeot ~(engine->irq_enable_mask | 18639edbd4a0SFrançois Tigeot GT_PARITY_ERROR(dev))); 1864686a02f1SFrançois Tigeot else 18658621f407SFrançois Tigeot I915_WRITE_IMR(engine, ~engine->irq_enable_mask); 18668621f407SFrançois Tigeot gen5_enable_gt_irq(dev_priv, engine->irq_enable_mask); 1867e3adcf8fSFrançois Tigeot } 18685e269720SFrançois Tigeot spin_unlock_irqrestore(&dev_priv->irq_lock, flags); 1869e3adcf8fSFrançois Tigeot 1870e3adcf8fSFrançois Tigeot return true; 1871e3adcf8fSFrançois Tigeot } 1872e3adcf8fSFrançois Tigeot 1873e3adcf8fSFrançois Tigeot static void 18748621f407SFrançois Tigeot gen6_ring_put_irq(struct intel_engine_cs *engine) 1875e3adcf8fSFrançois Tigeot { 18768621f407SFrançois Tigeot struct drm_device *dev = engine->dev; 1877ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 18785e269720SFrançois Tigeot unsigned long flags; 1879e3adcf8fSFrançois Tigeot 18805e269720SFrançois Tigeot spin_lock_irqsave(&dev_priv->irq_lock, flags); 18818621f407SFrançois Tigeot if (--engine->irq_refcount == 0) { 18828621f407SFrançois Tigeot if (HAS_L3_DPF(dev) && engine->id == RCS) 18838621f407SFrançois Tigeot I915_WRITE_IMR(engine, ~GT_PARITY_ERROR(dev)); 1884686a02f1SFrançois Tigeot else 18858621f407SFrançois Tigeot I915_WRITE_IMR(engine, ~0); 18868621f407SFrançois Tigeot gen5_disable_gt_irq(dev_priv, engine->irq_enable_mask); 1887e3adcf8fSFrançois Tigeot } 18885e269720SFrançois Tigeot spin_unlock_irqrestore(&dev_priv->irq_lock, flags); 1889e3adcf8fSFrançois Tigeot } 1890e3adcf8fSFrançois Tigeot 18915d0b1887SFrançois Tigeot static bool 18928621f407SFrançois Tigeot hsw_vebox_get_irq(struct intel_engine_cs *engine) 18935d0b1887SFrançois Tigeot { 18948621f407SFrançois Tigeot struct drm_device *dev = engine->dev; 18955d0b1887SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 18965e269720SFrançois Tigeot unsigned long flags; 18975d0b1887SFrançois Tigeot 18982c9916cdSFrançois Tigeot if (WARN_ON(!intel_irqs_enabled(dev_priv))) 18995d0b1887SFrançois Tigeot return false; 19005d0b1887SFrançois Tigeot 19015e269720SFrançois Tigeot spin_lock_irqsave(&dev_priv->irq_lock, flags); 19028621f407SFrançois Tigeot if (engine->irq_refcount++ == 0) { 19038621f407SFrançois Tigeot I915_WRITE_IMR(engine, ~engine->irq_enable_mask); 19048621f407SFrançois Tigeot gen6_enable_pm_irq(dev_priv, engine->irq_enable_mask); 19055d0b1887SFrançois Tigeot } 19065e269720SFrançois Tigeot spin_unlock_irqrestore(&dev_priv->irq_lock, flags); 19075d0b1887SFrançois Tigeot 19085d0b1887SFrançois Tigeot return true; 19095d0b1887SFrançois Tigeot } 19105d0b1887SFrançois Tigeot 19115d0b1887SFrançois Tigeot static void 19128621f407SFrançois Tigeot hsw_vebox_put_irq(struct intel_engine_cs *engine) 19135d0b1887SFrançois Tigeot { 19148621f407SFrançois Tigeot struct drm_device *dev = engine->dev; 19155d0b1887SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 19165e269720SFrançois Tigeot unsigned long flags; 19175d0b1887SFrançois Tigeot 19185e269720SFrançois Tigeot spin_lock_irqsave(&dev_priv->irq_lock, flags); 19198621f407SFrançois Tigeot if (--engine->irq_refcount == 0) { 19208621f407SFrançois Tigeot I915_WRITE_IMR(engine, ~0); 19218621f407SFrançois Tigeot gen6_disable_pm_irq(dev_priv, engine->irq_enable_mask); 19225d0b1887SFrançois Tigeot } 19235e269720SFrançois Tigeot spin_unlock_irqrestore(&dev_priv->irq_lock, flags); 19249edbd4a0SFrançois Tigeot } 19259edbd4a0SFrançois Tigeot 19269edbd4a0SFrançois Tigeot static bool 19278621f407SFrançois Tigeot gen8_ring_get_irq(struct intel_engine_cs *engine) 19289edbd4a0SFrançois Tigeot { 19298621f407SFrançois Tigeot struct drm_device *dev = engine->dev; 19309edbd4a0SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 19315e269720SFrançois Tigeot unsigned long flags; 19329edbd4a0SFrançois Tigeot 19332c9916cdSFrançois Tigeot if (WARN_ON(!intel_irqs_enabled(dev_priv))) 19349edbd4a0SFrançois Tigeot return false; 19359edbd4a0SFrançois Tigeot 19365e269720SFrançois Tigeot spin_lock_irqsave(&dev_priv->irq_lock, flags); 19378621f407SFrançois Tigeot if (engine->irq_refcount++ == 0) { 19388621f407SFrançois Tigeot if (HAS_L3_DPF(dev) && engine->id == RCS) { 19398621f407SFrançois Tigeot I915_WRITE_IMR(engine, 19408621f407SFrançois Tigeot ~(engine->irq_enable_mask | 19419edbd4a0SFrançois Tigeot GT_RENDER_L3_PARITY_ERROR_INTERRUPT)); 19429edbd4a0SFrançois Tigeot } else { 19438621f407SFrançois Tigeot I915_WRITE_IMR(engine, ~engine->irq_enable_mask); 19449edbd4a0SFrançois Tigeot } 19458621f407SFrançois Tigeot POSTING_READ(RING_IMR(engine->mmio_base)); 19469edbd4a0SFrançois Tigeot } 19475e269720SFrançois Tigeot spin_unlock_irqrestore(&dev_priv->irq_lock, flags); 19489edbd4a0SFrançois Tigeot 19499edbd4a0SFrançois Tigeot return true; 19509edbd4a0SFrançois Tigeot } 19519edbd4a0SFrançois Tigeot 19529edbd4a0SFrançois Tigeot static void 19538621f407SFrançois Tigeot gen8_ring_put_irq(struct intel_engine_cs *engine) 19549edbd4a0SFrançois Tigeot { 19558621f407SFrançois Tigeot struct drm_device *dev = engine->dev; 19569edbd4a0SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 19575e269720SFrançois Tigeot unsigned long flags; 19589edbd4a0SFrançois Tigeot 19595e269720SFrançois Tigeot spin_lock_irqsave(&dev_priv->irq_lock, flags); 19608621f407SFrançois Tigeot if (--engine->irq_refcount == 0) { 19618621f407SFrançois Tigeot if (HAS_L3_DPF(dev) && engine->id == RCS) { 19628621f407SFrançois Tigeot I915_WRITE_IMR(engine, 19639edbd4a0SFrançois Tigeot ~GT_RENDER_L3_PARITY_ERROR_INTERRUPT); 19649edbd4a0SFrançois Tigeot } else { 19658621f407SFrançois Tigeot I915_WRITE_IMR(engine, ~0); 19669edbd4a0SFrançois Tigeot } 19678621f407SFrançois Tigeot POSTING_READ(RING_IMR(engine->mmio_base)); 19689edbd4a0SFrançois Tigeot } 19695e269720SFrançois Tigeot spin_unlock_irqrestore(&dev_priv->irq_lock, flags); 19705d0b1887SFrançois Tigeot } 19715d0b1887SFrançois Tigeot 1972e3adcf8fSFrançois Tigeot static int 1973a05eeebfSFrançois Tigeot i965_dispatch_execbuffer(struct drm_i915_gem_request *req, 1974ba55f2f5SFrançois Tigeot u64 offset, u32 length, 1975477eb7f9SFrançois Tigeot unsigned dispatch_flags) 1976e3adcf8fSFrançois Tigeot { 19778621f407SFrançois Tigeot struct intel_engine_cs *engine = req->engine; 1978e3adcf8fSFrançois Tigeot int ret; 1979e3adcf8fSFrançois Tigeot 1980a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 2); 1981e3adcf8fSFrançois Tigeot if (ret) 1982e3adcf8fSFrançois Tigeot return ret; 1983e3adcf8fSFrançois Tigeot 19848621f407SFrançois Tigeot intel_ring_emit(engine, 1985686a02f1SFrançois Tigeot MI_BATCH_BUFFER_START | 1986b5c29a34SFrançois Tigeot MI_BATCH_GTT | 1987477eb7f9SFrançois Tigeot (dispatch_flags & I915_DISPATCH_SECURE ? 1988477eb7f9SFrançois Tigeot 0 : MI_BATCH_NON_SECURE_I965)); 19898621f407SFrançois Tigeot intel_ring_emit(engine, offset); 19908621f407SFrançois Tigeot intel_ring_advance(engine); 1991e3adcf8fSFrançois Tigeot 1992e3adcf8fSFrançois Tigeot return 0; 1993e3adcf8fSFrançois Tigeot } 1994e3adcf8fSFrançois Tigeot 1995b5c29a34SFrançois Tigeot /* Just userspace ABI convention to limit the wa batch bo to a resonable size */ 1996b5c29a34SFrançois Tigeot #define I830_BATCH_LIMIT (256*1024) 199724edb884SFrançois Tigeot #define I830_TLB_ENTRIES (2) 199824edb884SFrançois Tigeot #define I830_WA_SIZE max(I830_TLB_ENTRIES*4096, I830_BATCH_LIMIT) 1999e3adcf8fSFrançois Tigeot static int 2000a05eeebfSFrançois Tigeot i830_dispatch_execbuffer(struct drm_i915_gem_request *req, 2001ba55f2f5SFrançois Tigeot u64 offset, u32 len, 2002477eb7f9SFrançois Tigeot unsigned dispatch_flags) 2003e3adcf8fSFrançois Tigeot { 20048621f407SFrançois Tigeot struct intel_engine_cs *engine = req->engine; 20058621f407SFrançois Tigeot u32 cs_offset = engine->scratch.gtt_offset; 2006e3adcf8fSFrançois Tigeot int ret; 2007e3adcf8fSFrançois Tigeot 2008a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 6); 200924edb884SFrançois Tigeot if (ret) 201024edb884SFrançois Tigeot return ret; 201124edb884SFrançois Tigeot 201224edb884SFrançois Tigeot /* Evict the invalid PTE TLBs */ 20138621f407SFrançois Tigeot intel_ring_emit(engine, COLOR_BLT_CMD | BLT_WRITE_RGBA); 20148621f407SFrançois Tigeot intel_ring_emit(engine, BLT_DEPTH_32 | BLT_ROP_COLOR_COPY | 4096); 20158621f407SFrançois Tigeot intel_ring_emit(engine, I830_TLB_ENTRIES << 16 | 4); /* load each page */ 20168621f407SFrançois Tigeot intel_ring_emit(engine, cs_offset); 20178621f407SFrançois Tigeot intel_ring_emit(engine, 0xdeadbeef); 20188621f407SFrançois Tigeot intel_ring_emit(engine, MI_NOOP); 20198621f407SFrançois Tigeot intel_ring_advance(engine); 202024edb884SFrançois Tigeot 2021477eb7f9SFrançois Tigeot if ((dispatch_flags & I915_DISPATCH_PINNED) == 0) { 202224edb884SFrançois Tigeot if (len > I830_BATCH_LIMIT) 202324edb884SFrançois Tigeot return -ENOSPC; 202424edb884SFrançois Tigeot 2025a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 6 + 2); 202624edb884SFrançois Tigeot if (ret) 202724edb884SFrançois Tigeot return ret; 202824edb884SFrançois Tigeot 202924edb884SFrançois Tigeot /* Blit the batch (which has now all relocs applied) to the 203024edb884SFrançois Tigeot * stable batch scratch bo area (so that the CS never 203124edb884SFrançois Tigeot * stumbles over its tlb invalidation bug) ... 203224edb884SFrançois Tigeot */ 20338621f407SFrançois Tigeot intel_ring_emit(engine, SRC_COPY_BLT_CMD | BLT_WRITE_RGBA); 20348621f407SFrançois Tigeot intel_ring_emit(engine, 20358621f407SFrançois Tigeot BLT_DEPTH_32 | BLT_ROP_SRC_COPY | 4096); 20368621f407SFrançois Tigeot intel_ring_emit(engine, DIV_ROUND_UP(len, 4096) << 16 | 4096); 20378621f407SFrançois Tigeot intel_ring_emit(engine, cs_offset); 20388621f407SFrançois Tigeot intel_ring_emit(engine, 4096); 20398621f407SFrançois Tigeot intel_ring_emit(engine, offset); 204024edb884SFrançois Tigeot 20418621f407SFrançois Tigeot intel_ring_emit(engine, MI_FLUSH); 20428621f407SFrançois Tigeot intel_ring_emit(engine, MI_NOOP); 20438621f407SFrançois Tigeot intel_ring_advance(engine); 204424edb884SFrançois Tigeot 204524edb884SFrançois Tigeot /* ... and execute it. */ 204624edb884SFrançois Tigeot offset = cs_offset; 204724edb884SFrançois Tigeot } 204824edb884SFrançois Tigeot 2049c0e85e96SFrançois Tigeot ret = intel_ring_begin(req, 2); 2050e3adcf8fSFrançois Tigeot if (ret) 2051e3adcf8fSFrançois Tigeot return ret; 2052e3adcf8fSFrançois Tigeot 20538621f407SFrançois Tigeot intel_ring_emit(engine, MI_BATCH_BUFFER_START | MI_BATCH_GTT); 20548621f407SFrançois Tigeot intel_ring_emit(engine, offset | (dispatch_flags & I915_DISPATCH_SECURE ? 2055477eb7f9SFrançois Tigeot 0 : MI_BATCH_NON_SECURE)); 20568621f407SFrançois Tigeot intel_ring_advance(engine); 2057686a02f1SFrançois Tigeot 2058686a02f1SFrançois Tigeot return 0; 2059686a02f1SFrançois Tigeot } 2060686a02f1SFrançois Tigeot 2061686a02f1SFrançois Tigeot static int 2062a05eeebfSFrançois Tigeot i915_dispatch_execbuffer(struct drm_i915_gem_request *req, 2063ba55f2f5SFrançois Tigeot u64 offset, u32 len, 2064477eb7f9SFrançois Tigeot unsigned dispatch_flags) 2065686a02f1SFrançois Tigeot { 20668621f407SFrançois Tigeot struct intel_engine_cs *engine = req->engine; 2067686a02f1SFrançois Tigeot int ret; 2068686a02f1SFrançois Tigeot 2069a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 2); 2070e3adcf8fSFrançois Tigeot if (ret) 2071e3adcf8fSFrançois Tigeot return ret; 2072e3adcf8fSFrançois Tigeot 20738621f407SFrançois Tigeot intel_ring_emit(engine, MI_BATCH_BUFFER_START | MI_BATCH_GTT); 20748621f407SFrançois Tigeot intel_ring_emit(engine, offset | (dispatch_flags & I915_DISPATCH_SECURE ? 2075477eb7f9SFrançois Tigeot 0 : MI_BATCH_NON_SECURE)); 20768621f407SFrançois Tigeot intel_ring_advance(engine); 2077e3adcf8fSFrançois Tigeot 2078e3adcf8fSFrançois Tigeot return 0; 2079e3adcf8fSFrançois Tigeot } 2080e3adcf8fSFrançois Tigeot 20818621f407SFrançois Tigeot static void cleanup_phys_status_page(struct intel_engine_cs *engine) 2082c0e85e96SFrançois Tigeot { 20838621f407SFrançois Tigeot struct drm_i915_private *dev_priv = to_i915(engine->dev); 2084c0e85e96SFrançois Tigeot 2085c0e85e96SFrançois Tigeot if (!dev_priv->status_page_dmah) 2086c0e85e96SFrançois Tigeot return; 2087c0e85e96SFrançois Tigeot 20888621f407SFrançois Tigeot drm_pci_free(engine->dev, dev_priv->status_page_dmah); 20898621f407SFrançois Tigeot engine->status_page.page_addr = NULL; 2090c0e85e96SFrançois Tigeot } 2091c0e85e96SFrançois Tigeot 20928621f407SFrançois Tigeot static void cleanup_status_page(struct intel_engine_cs *engine) 2093e3adcf8fSFrançois Tigeot { 2094e3adcf8fSFrançois Tigeot struct drm_i915_gem_object *obj; 2095e3adcf8fSFrançois Tigeot 20968621f407SFrançois Tigeot obj = engine->status_page.obj; 2097e3adcf8fSFrançois Tigeot if (obj == NULL) 2098e3adcf8fSFrançois Tigeot return; 2099e3adcf8fSFrançois Tigeot 21007ec9f8e5SFrançois Tigeot kunmap(sg_page(obj->pages->sgl)); 2101ba55f2f5SFrançois Tigeot i915_gem_object_ggtt_unpin(obj); 2102e3adcf8fSFrançois Tigeot drm_gem_object_unreference(&obj->base); 21038621f407SFrançois Tigeot engine->status_page.obj = NULL; 2104e3adcf8fSFrançois Tigeot } 2105e3adcf8fSFrançois Tigeot 21068621f407SFrançois Tigeot static int init_status_page(struct intel_engine_cs *engine) 2107e3adcf8fSFrançois Tigeot { 21088621f407SFrançois Tigeot struct drm_i915_gem_object *obj = engine->status_page.obj; 2109ba55f2f5SFrançois Tigeot 2110c0e85e96SFrançois Tigeot if (obj == NULL) { 211124edb884SFrançois Tigeot unsigned flags; 2112e3adcf8fSFrançois Tigeot int ret; 2113e3adcf8fSFrançois Tigeot 21148621f407SFrançois Tigeot obj = i915_gem_alloc_object(engine->dev, 4096); 2115e3adcf8fSFrançois Tigeot if (obj == NULL) { 2116e3adcf8fSFrançois Tigeot DRM_ERROR("Failed to allocate status page\n"); 2117ba55f2f5SFrançois Tigeot return -ENOMEM; 2118e3adcf8fSFrançois Tigeot } 2119e3adcf8fSFrançois Tigeot 2120ba55f2f5SFrançois Tigeot ret = i915_gem_object_set_cache_level(obj, I915_CACHE_LLC); 2121ba55f2f5SFrançois Tigeot if (ret) 2122e3adcf8fSFrançois Tigeot goto err_unref; 2123ba55f2f5SFrançois Tigeot 212424edb884SFrançois Tigeot flags = 0; 21258621f407SFrançois Tigeot if (!HAS_LLC(engine->dev)) 212624edb884SFrançois Tigeot /* On g33, we cannot place HWS above 256MiB, so 212724edb884SFrançois Tigeot * restrict its pinning to the low mappable arena. 212824edb884SFrançois Tigeot * Though this restriction is not documented for 212924edb884SFrançois Tigeot * gen4, gen5, or byt, they also behave similarly 213024edb884SFrançois Tigeot * and hang if the HWS is placed at the top of the 213124edb884SFrançois Tigeot * GTT. To generalise, it appears that all !llc 213224edb884SFrançois Tigeot * platforms have issues with us placing the HWS 213324edb884SFrançois Tigeot * above the mappable region (even though we never 213424edb884SFrançois Tigeot * actualy map it). 213524edb884SFrançois Tigeot */ 213624edb884SFrançois Tigeot flags |= PIN_MAPPABLE; 213724edb884SFrançois Tigeot ret = i915_gem_obj_ggtt_pin(obj, 4096, flags); 2138ba55f2f5SFrançois Tigeot if (ret) { 2139ba55f2f5SFrançois Tigeot err_unref: 2140ba55f2f5SFrançois Tigeot drm_gem_object_unreference(&obj->base); 2141ba55f2f5SFrançois Tigeot return ret; 2142ba55f2f5SFrançois Tigeot } 2143ba55f2f5SFrançois Tigeot 21448621f407SFrançois Tigeot engine->status_page.obj = obj; 2145e3adcf8fSFrançois Tigeot } 2146e3adcf8fSFrançois Tigeot 21478621f407SFrançois Tigeot engine->status_page.gfx_addr = i915_gem_obj_ggtt_offset(obj); 21488621f407SFrançois Tigeot engine->status_page.page_addr = kmap(sg_page(obj->pages->sgl)); 21498621f407SFrançois Tigeot memset(engine->status_page.page_addr, 0, PAGE_SIZE); 2150e3adcf8fSFrançois Tigeot 2151b5c29a34SFrançois Tigeot DRM_DEBUG_DRIVER("%s hws offset: 0x%08x\n", 21528621f407SFrançois Tigeot engine->name, engine->status_page.gfx_addr); 2153e3adcf8fSFrançois Tigeot 2154e3adcf8fSFrançois Tigeot return 0; 2155e3adcf8fSFrançois Tigeot } 2156e3adcf8fSFrançois Tigeot 21578621f407SFrançois Tigeot static int init_phys_status_page(struct intel_engine_cs *engine) 2158686a02f1SFrançois Tigeot { 21598621f407SFrançois Tigeot struct drm_i915_private *dev_priv = engine->dev->dev_private; 2160686a02f1SFrançois Tigeot 2161686a02f1SFrançois Tigeot if (!dev_priv->status_page_dmah) { 2162686a02f1SFrançois Tigeot dev_priv->status_page_dmah = 21638621f407SFrançois Tigeot drm_pci_alloc(engine->dev, PAGE_SIZE, PAGE_SIZE); 2164686a02f1SFrançois Tigeot if (!dev_priv->status_page_dmah) 2165686a02f1SFrançois Tigeot return -ENOMEM; 2166686a02f1SFrançois Tigeot } 2167686a02f1SFrançois Tigeot 21688621f407SFrançois Tigeot engine->status_page.page_addr = dev_priv->status_page_dmah->vaddr; 21698621f407SFrançois Tigeot memset(engine->status_page.page_addr, 0, PAGE_SIZE); 2170686a02f1SFrançois Tigeot 2171686a02f1SFrançois Tigeot return 0; 2172686a02f1SFrançois Tigeot } 2173686a02f1SFrançois Tigeot 21742c9916cdSFrançois Tigeot void intel_unpin_ringbuffer_obj(struct intel_ringbuffer *ringbuf) 21752c9916cdSFrançois Tigeot { 2176aee94f86SFrançois Tigeot if (HAS_LLC(ringbuf->obj->base.dev) && !ringbuf->obj->stolen) 21778621f407SFrançois Tigeot i915_gem_object_unpin_map(ringbuf->obj); 2178aee94f86SFrançois Tigeot else 217924409b39SFrançois Tigeot iounmap(ringbuf->virtual_start); 21802c9916cdSFrançois Tigeot ringbuf->virtual_start = NULL; 2181c0e85e96SFrançois Tigeot ringbuf->vma = NULL; 21822c9916cdSFrançois Tigeot i915_gem_object_ggtt_unpin(ringbuf->obj); 21832c9916cdSFrançois Tigeot } 21842c9916cdSFrançois Tigeot 21852c9916cdSFrançois Tigeot int intel_pin_and_map_ringbuffer_obj(struct drm_device *dev, 21862c9916cdSFrançois Tigeot struct intel_ringbuffer *ringbuf) 21872c9916cdSFrançois Tigeot { 21882c9916cdSFrançois Tigeot struct drm_i915_private *dev_priv = to_i915(dev); 21898621f407SFrançois Tigeot struct i915_ggtt *ggtt = &dev_priv->ggtt; 21902c9916cdSFrançois Tigeot struct drm_i915_gem_object *obj = ringbuf->obj; 2191c0e85e96SFrançois Tigeot /* Ring wraparound at offset 0 sometimes hangs. No idea why. */ 2192c0e85e96SFrançois Tigeot unsigned flags = PIN_OFFSET_BIAS | 4096; 21938621f407SFrançois Tigeot void *addr; 21942c9916cdSFrançois Tigeot int ret; 21952c9916cdSFrançois Tigeot 2196aee94f86SFrançois Tigeot if (HAS_LLC(dev_priv) && !obj->stolen) { 2197c0e85e96SFrançois Tigeot ret = i915_gem_obj_ggtt_pin(obj, PAGE_SIZE, flags); 2198aee94f86SFrançois Tigeot if (ret) 2199aee94f86SFrançois Tigeot return ret; 2200aee94f86SFrançois Tigeot 2201aee94f86SFrançois Tigeot ret = i915_gem_object_set_to_cpu_domain(obj, true); 22028621f407SFrançois Tigeot if (ret) 22038621f407SFrançois Tigeot goto err_unpin; 2204aee94f86SFrançois Tigeot 22058621f407SFrançois Tigeot addr = i915_gem_object_pin_map(obj); 22068621f407SFrançois Tigeot if (IS_ERR(addr)) { 22078621f407SFrançois Tigeot ret = PTR_ERR(addr); 22088621f407SFrançois Tigeot goto err_unpin; 2209aee94f86SFrançois Tigeot } 2210aee94f86SFrançois Tigeot } else { 2211c0e85e96SFrançois Tigeot ret = i915_gem_obj_ggtt_pin(obj, PAGE_SIZE, 2212c0e85e96SFrançois Tigeot flags | PIN_MAPPABLE); 22132c9916cdSFrançois Tigeot if (ret) 22142c9916cdSFrançois Tigeot return ret; 22152c9916cdSFrançois Tigeot 22162c9916cdSFrançois Tigeot ret = i915_gem_object_set_to_gtt_domain(obj, true); 22178621f407SFrançois Tigeot if (ret) 22188621f407SFrançois Tigeot goto err_unpin; 22192c9916cdSFrançois Tigeot 2220c0e85e96SFrançois Tigeot /* Access through the GTT requires the device to be awake. */ 2221c0e85e96SFrançois Tigeot assert_rpm_wakelock_held(dev_priv); 2222c0e85e96SFrançois Tigeot 22238621f407SFrançois Tigeot addr = ioremap_wc(ggtt->mappable_base + 22242c9916cdSFrançois Tigeot i915_gem_obj_ggtt_offset(obj), ringbuf->size); 22258621f407SFrançois Tigeot if (addr == NULL) { 22268621f407SFrançois Tigeot ret = -ENOMEM; 22278621f407SFrançois Tigeot goto err_unpin; 22282c9916cdSFrançois Tigeot } 2229aee94f86SFrançois Tigeot } 22302c9916cdSFrançois Tigeot 22318621f407SFrançois Tigeot ringbuf->virtual_start = addr; 2232c0e85e96SFrançois Tigeot ringbuf->vma = i915_gem_obj_to_ggtt(obj); 22332c9916cdSFrançois Tigeot return 0; 22348621f407SFrançois Tigeot 22358621f407SFrançois Tigeot err_unpin: 22368621f407SFrançois Tigeot i915_gem_object_ggtt_unpin(obj); 22378621f407SFrançois Tigeot return ret; 22382c9916cdSFrançois Tigeot } 22392c9916cdSFrançois Tigeot 2240352ff8bdSFrançois Tigeot static void intel_destroy_ringbuffer_obj(struct intel_ringbuffer *ringbuf) 2241e3adcf8fSFrançois Tigeot { 224224edb884SFrançois Tigeot drm_gem_object_unreference(&ringbuf->obj->base); 224324edb884SFrançois Tigeot ringbuf->obj = NULL; 224424edb884SFrançois Tigeot } 224524edb884SFrançois Tigeot 2246352ff8bdSFrançois Tigeot static int intel_alloc_ringbuffer_obj(struct drm_device *dev, 224724edb884SFrançois Tigeot struct intel_ringbuffer *ringbuf) 224824edb884SFrançois Tigeot { 2249e3adcf8fSFrançois Tigeot struct drm_i915_gem_object *obj; 2250e3adcf8fSFrançois Tigeot 2251a2fdbec6SFrançois Tigeot obj = NULL; 2252a2fdbec6SFrançois Tigeot if (!HAS_LLC(dev)) 2253ba55f2f5SFrançois Tigeot obj = i915_gem_object_create_stolen(dev, ringbuf->size); 2254a2fdbec6SFrançois Tigeot if (obj == NULL) 2255ba55f2f5SFrançois Tigeot obj = i915_gem_alloc_object(dev, ringbuf->size); 2256ba55f2f5SFrançois Tigeot if (obj == NULL) 2257ba55f2f5SFrançois Tigeot return -ENOMEM; 2258e3adcf8fSFrançois Tigeot 225924edb884SFrançois Tigeot /* mark ring buffers as read-only from GPU side by default */ 226024edb884SFrançois Tigeot obj->gt_ro = 1; 226124edb884SFrançois Tigeot 2262ba55f2f5SFrançois Tigeot ringbuf->obj = obj; 2263ba55f2f5SFrançois Tigeot 22642c9916cdSFrançois Tigeot return 0; 2265ba55f2f5SFrançois Tigeot } 2266ba55f2f5SFrançois Tigeot 2267352ff8bdSFrançois Tigeot struct intel_ringbuffer * 2268352ff8bdSFrançois Tigeot intel_engine_create_ringbuffer(struct intel_engine_cs *engine, int size) 2269352ff8bdSFrançois Tigeot { 2270352ff8bdSFrançois Tigeot struct intel_ringbuffer *ring; 2271352ff8bdSFrançois Tigeot int ret; 2272352ff8bdSFrançois Tigeot 2273352ff8bdSFrançois Tigeot ring = kzalloc(sizeof(*ring), GFP_KERNEL); 2274aee94f86SFrançois Tigeot if (ring == NULL) { 2275aee94f86SFrançois Tigeot DRM_DEBUG_DRIVER("Failed to allocate ringbuffer %s\n", 2276aee94f86SFrançois Tigeot engine->name); 2277352ff8bdSFrançois Tigeot return ERR_PTR(-ENOMEM); 2278aee94f86SFrançois Tigeot } 2279352ff8bdSFrançois Tigeot 22808621f407SFrançois Tigeot ring->engine = engine; 2281aee94f86SFrançois Tigeot list_add(&ring->link, &engine->buffers); 2282352ff8bdSFrançois Tigeot 2283352ff8bdSFrançois Tigeot ring->size = size; 2284352ff8bdSFrançois Tigeot /* Workaround an erratum on the i830 which causes a hang if 2285352ff8bdSFrançois Tigeot * the TAIL pointer points to within the last 2 cachelines 2286352ff8bdSFrançois Tigeot * of the buffer. 2287352ff8bdSFrançois Tigeot */ 2288352ff8bdSFrançois Tigeot ring->effective_size = size; 2289352ff8bdSFrançois Tigeot if (IS_I830(engine->dev) || IS_845G(engine->dev)) 2290352ff8bdSFrançois Tigeot ring->effective_size -= 2 * CACHELINE_BYTES; 2291352ff8bdSFrançois Tigeot 2292352ff8bdSFrançois Tigeot ring->last_retired_head = -1; 2293352ff8bdSFrançois Tigeot intel_ring_update_space(ring); 2294352ff8bdSFrançois Tigeot 2295352ff8bdSFrançois Tigeot ret = intel_alloc_ringbuffer_obj(engine->dev, ring); 2296352ff8bdSFrançois Tigeot if (ret) { 2297aee94f86SFrançois Tigeot DRM_DEBUG_DRIVER("Failed to allocate ringbuffer %s: %d\n", 2298352ff8bdSFrançois Tigeot engine->name, ret); 2299aee94f86SFrançois Tigeot list_del(&ring->link); 2300352ff8bdSFrançois Tigeot kfree(ring); 2301352ff8bdSFrançois Tigeot return ERR_PTR(ret); 2302352ff8bdSFrançois Tigeot } 2303352ff8bdSFrançois Tigeot 2304352ff8bdSFrançois Tigeot return ring; 2305352ff8bdSFrançois Tigeot } 2306352ff8bdSFrançois Tigeot 2307352ff8bdSFrançois Tigeot void 2308352ff8bdSFrançois Tigeot intel_ringbuffer_free(struct intel_ringbuffer *ring) 2309352ff8bdSFrançois Tigeot { 2310352ff8bdSFrançois Tigeot intel_destroy_ringbuffer_obj(ring); 2311aee94f86SFrançois Tigeot list_del(&ring->link); 2312352ff8bdSFrançois Tigeot kfree(ring); 2313352ff8bdSFrançois Tigeot } 2314352ff8bdSFrançois Tigeot 2315ba55f2f5SFrançois Tigeot static int intel_init_ring_buffer(struct drm_device *dev, 23168621f407SFrançois Tigeot struct intel_engine_cs *engine) 2317ba55f2f5SFrançois Tigeot { 23182c9916cdSFrançois Tigeot struct intel_ringbuffer *ringbuf; 2319ba55f2f5SFrançois Tigeot int ret; 2320ba55f2f5SFrançois Tigeot 23218621f407SFrançois Tigeot WARN_ON(engine->buffer); 23222c9916cdSFrançois Tigeot 23238621f407SFrançois Tigeot engine->dev = dev; 23248621f407SFrançois Tigeot INIT_LIST_HEAD(&engine->active_list); 23258621f407SFrançois Tigeot INIT_LIST_HEAD(&engine->request_list); 23268621f407SFrançois Tigeot INIT_LIST_HEAD(&engine->execlist_queue); 23278621f407SFrançois Tigeot INIT_LIST_HEAD(&engine->buffers); 23288621f407SFrançois Tigeot i915_gem_batch_pool_init(dev, &engine->batch_pool); 23298621f407SFrançois Tigeot memset(engine->semaphore.sync_seqno, 0, 23308621f407SFrançois Tigeot sizeof(engine->semaphore.sync_seqno)); 2331ba55f2f5SFrançois Tigeot 23328621f407SFrançois Tigeot init_waitqueue_head(&engine->irq_queue); 2333ba55f2f5SFrançois Tigeot 23348621f407SFrançois Tigeot ringbuf = intel_engine_create_ringbuffer(engine, 32 * PAGE_SIZE); 2335aee94f86SFrançois Tigeot if (IS_ERR(ringbuf)) { 2336aee94f86SFrançois Tigeot ret = PTR_ERR(ringbuf); 2337aee94f86SFrançois Tigeot goto error; 2338aee94f86SFrançois Tigeot } 23398621f407SFrançois Tigeot engine->buffer = ringbuf; 2340352ff8bdSFrançois Tigeot 2341ba55f2f5SFrançois Tigeot if (I915_NEED_GFX_HWS(dev)) { 23428621f407SFrançois Tigeot ret = init_status_page(engine); 2343e3adcf8fSFrançois Tigeot if (ret) 2344ba55f2f5SFrançois Tigeot goto error; 2345ba55f2f5SFrançois Tigeot } else { 23468621f407SFrançois Tigeot WARN_ON(engine->id != RCS); 23478621f407SFrançois Tigeot ret = init_phys_status_page(engine); 2348ba55f2f5SFrançois Tigeot if (ret) 2349ba55f2f5SFrançois Tigeot goto error; 2350ba55f2f5SFrançois Tigeot } 2351ba55f2f5SFrançois Tigeot 23522c9916cdSFrançois Tigeot ret = intel_pin_and_map_ringbuffer_obj(dev, ringbuf); 23532c9916cdSFrançois Tigeot if (ret) { 23542c9916cdSFrançois Tigeot DRM_ERROR("Failed to pin and map ringbuffer %s: %d\n", 23558621f407SFrançois Tigeot engine->name, ret); 23562c9916cdSFrançois Tigeot intel_destroy_ringbuffer_obj(ringbuf); 2357ba55f2f5SFrançois Tigeot goto error; 2358ba55f2f5SFrançois Tigeot } 2359e3adcf8fSFrançois Tigeot 23608621f407SFrançois Tigeot ret = i915_cmd_parser_init_ring(engine); 2361ba55f2f5SFrançois Tigeot if (ret) 2362ba55f2f5SFrançois Tigeot goto error; 2363ba55f2f5SFrançois Tigeot 2364e3adcf8fSFrançois Tigeot return 0; 2365e3adcf8fSFrançois Tigeot 2366ba55f2f5SFrançois Tigeot error: 23678621f407SFrançois Tigeot intel_cleanup_engine(engine); 2368e3adcf8fSFrançois Tigeot return ret; 2369e3adcf8fSFrançois Tigeot } 2370e3adcf8fSFrançois Tigeot 23718621f407SFrançois Tigeot void intel_cleanup_engine(struct intel_engine_cs *engine) 2372e3adcf8fSFrançois Tigeot { 23732c9916cdSFrançois Tigeot struct drm_i915_private *dev_priv; 2374e3adcf8fSFrançois Tigeot 23758621f407SFrançois Tigeot if (!intel_engine_initialized(engine)) 2376e3adcf8fSFrançois Tigeot return; 2377e3adcf8fSFrançois Tigeot 23788621f407SFrançois Tigeot dev_priv = to_i915(engine->dev); 23792c9916cdSFrançois Tigeot 23808621f407SFrançois Tigeot if (engine->buffer) { 23818621f407SFrançois Tigeot intel_stop_engine(engine); 23828621f407SFrançois Tigeot WARN_ON(!IS_GEN2(engine->dev) && (I915_READ_MODE(engine) & MODE_IDLE) == 0); 2383b030f26bSFrançois Tigeot 23848621f407SFrançois Tigeot intel_unpin_ringbuffer_obj(engine->buffer); 23858621f407SFrançois Tigeot intel_ringbuffer_free(engine->buffer); 23868621f407SFrançois Tigeot engine->buffer = NULL; 2387aee94f86SFrançois Tigeot } 2388e3adcf8fSFrançois Tigeot 23898621f407SFrançois Tigeot if (engine->cleanup) 23908621f407SFrançois Tigeot engine->cleanup(engine); 2391e3adcf8fSFrançois Tigeot 23928621f407SFrançois Tigeot if (I915_NEED_GFX_HWS(engine->dev)) { 23938621f407SFrançois Tigeot cleanup_status_page(engine); 2394c0e85e96SFrançois Tigeot } else { 23958621f407SFrançois Tigeot WARN_ON(engine->id != RCS); 23968621f407SFrançois Tigeot cleanup_phys_status_page(engine); 2397c0e85e96SFrançois Tigeot } 2398ba55f2f5SFrançois Tigeot 23998621f407SFrançois Tigeot i915_cmd_parser_fini_ring(engine); 24008621f407SFrançois Tigeot i915_gem_batch_pool_fini(&engine->batch_pool); 24018621f407SFrançois Tigeot engine->dev = NULL; 2402e3adcf8fSFrançois Tigeot } 2403e3adcf8fSFrançois Tigeot 24048621f407SFrançois Tigeot int intel_engine_idle(struct intel_engine_cs *engine) 2405b030f26bSFrançois Tigeot { 24062c9916cdSFrançois Tigeot struct drm_i915_gem_request *req; 2407b5c29a34SFrançois Tigeot 2408b5c29a34SFrançois Tigeot /* Wait upon the last request to be completed */ 24098621f407SFrançois Tigeot if (list_empty(&engine->request_list)) 2410b5c29a34SFrançois Tigeot return 0; 2411b5c29a34SFrançois Tigeot 24128621f407SFrançois Tigeot req = list_entry(engine->request_list.prev, 2413b5c29a34SFrançois Tigeot struct drm_i915_gem_request, 24142c9916cdSFrançois Tigeot list); 2415b5c29a34SFrançois Tigeot 241619c468b4SFrançois Tigeot /* Make sure we do not trigger any retires */ 241719c468b4SFrançois Tigeot return __i915_wait_request(req, 24188621f407SFrançois Tigeot req->i915->mm.interruptible, 241919c468b4SFrançois Tigeot NULL, NULL); 2420b5c29a34SFrançois Tigeot } 2421b5c29a34SFrançois Tigeot 242219c468b4SFrançois Tigeot int intel_ring_alloc_request_extras(struct drm_i915_gem_request *request) 2423b5c29a34SFrançois Tigeot { 24248621f407SFrançois Tigeot request->ringbuf = request->engine->buffer; 24252c9916cdSFrançois Tigeot return 0; 24269edbd4a0SFrançois Tigeot } 24279edbd4a0SFrançois Tigeot 2428a05eeebfSFrançois Tigeot int intel_ring_reserve_space(struct drm_i915_gem_request *request) 2429a2fdbec6SFrançois Tigeot { 2430a05eeebfSFrançois Tigeot /* 2431a05eeebfSFrançois Tigeot * The first call merely notes the reserve request and is common for 2432a05eeebfSFrançois Tigeot * all back ends. The subsequent localised _begin() call actually 2433a05eeebfSFrançois Tigeot * ensures that the reservation is available. Without the begin, if 2434a05eeebfSFrançois Tigeot * the request creator immediately submitted the request without 2435a05eeebfSFrançois Tigeot * adding any commands to it then there might not actually be 2436a05eeebfSFrançois Tigeot * sufficient room for the submission commands. 2437a05eeebfSFrançois Tigeot */ 2438a05eeebfSFrançois Tigeot intel_ring_reserved_space_reserve(request->ringbuf, MIN_SPACE_FOR_ADD_REQUEST); 2439a2fdbec6SFrançois Tigeot 2440a05eeebfSFrançois Tigeot return intel_ring_begin(request, 0); 2441a2fdbec6SFrançois Tigeot } 2442a2fdbec6SFrançois Tigeot 2443a05eeebfSFrançois Tigeot void intel_ring_reserved_space_reserve(struct intel_ringbuffer *ringbuf, int size) 2444a05eeebfSFrançois Tigeot { 24458621f407SFrançois Tigeot GEM_BUG_ON(ringbuf->reserved_size); 2446a05eeebfSFrançois Tigeot ringbuf->reserved_size = size; 2447a05eeebfSFrançois Tigeot } 2448a05eeebfSFrançois Tigeot 2449a05eeebfSFrançois Tigeot void intel_ring_reserved_space_cancel(struct intel_ringbuffer *ringbuf) 2450a05eeebfSFrançois Tigeot { 24518621f407SFrançois Tigeot GEM_BUG_ON(!ringbuf->reserved_size); 2452a05eeebfSFrançois Tigeot ringbuf->reserved_size = 0; 2453a05eeebfSFrançois Tigeot } 2454a05eeebfSFrançois Tigeot 2455a05eeebfSFrançois Tigeot void intel_ring_reserved_space_use(struct intel_ringbuffer *ringbuf) 2456a05eeebfSFrançois Tigeot { 24578621f407SFrançois Tigeot GEM_BUG_ON(!ringbuf->reserved_size); 24588621f407SFrançois Tigeot ringbuf->reserved_size = 0; 2459a05eeebfSFrançois Tigeot } 2460a05eeebfSFrançois Tigeot 2461a05eeebfSFrançois Tigeot void intel_ring_reserved_space_end(struct intel_ringbuffer *ringbuf) 2462a05eeebfSFrançois Tigeot { 24638621f407SFrançois Tigeot GEM_BUG_ON(ringbuf->reserved_size); 2464a05eeebfSFrançois Tigeot } 2465a05eeebfSFrançois Tigeot 24668621f407SFrançois Tigeot static int wait_for_space(struct drm_i915_gem_request *req, int bytes) 2467a05eeebfSFrançois Tigeot { 24688621f407SFrançois Tigeot struct intel_ringbuffer *ringbuf = req->ringbuf; 24698621f407SFrançois Tigeot struct intel_engine_cs *engine = req->engine; 24708621f407SFrançois Tigeot struct drm_i915_gem_request *target; 24718621f407SFrançois Tigeot 24728621f407SFrançois Tigeot intel_ring_update_space(ringbuf); 24738621f407SFrançois Tigeot if (ringbuf->space >= bytes) 24748621f407SFrançois Tigeot return 0; 24758621f407SFrançois Tigeot 24768621f407SFrançois Tigeot /* 24778621f407SFrançois Tigeot * Space is reserved in the ringbuffer for finalising the request, 24788621f407SFrançois Tigeot * as that cannot be allowed to fail. During request finalisation, 24798621f407SFrançois Tigeot * reserved_space is set to 0 to stop the overallocation and the 24808621f407SFrançois Tigeot * assumption is that then we never need to wait (which has the 24818621f407SFrançois Tigeot * risk of failing with EINTR). 24828621f407SFrançois Tigeot * 24838621f407SFrançois Tigeot * See also i915_gem_request_alloc() and i915_add_request(). 24848621f407SFrançois Tigeot */ 24858621f407SFrançois Tigeot GEM_BUG_ON(!ringbuf->reserved_size); 24868621f407SFrançois Tigeot 24878621f407SFrançois Tigeot list_for_each_entry(target, &engine->request_list, list) { 24888621f407SFrançois Tigeot unsigned space; 24898621f407SFrançois Tigeot 24908621f407SFrançois Tigeot /* 24918621f407SFrançois Tigeot * The request queue is per-engine, so can contain requests 24928621f407SFrançois Tigeot * from multiple ringbuffers. Here, we must ignore any that 24938621f407SFrançois Tigeot * aren't from the ringbuffer we're considering. 24948621f407SFrançois Tigeot */ 24958621f407SFrançois Tigeot if (target->ringbuf != ringbuf) 24968621f407SFrançois Tigeot continue; 24978621f407SFrançois Tigeot 24988621f407SFrançois Tigeot /* Would completion of this request free enough space? */ 24998621f407SFrançois Tigeot space = __intel_ring_space(target->postfix, ringbuf->tail, 25008621f407SFrançois Tigeot ringbuf->size); 25018621f407SFrançois Tigeot if (space >= bytes) 25028621f407SFrançois Tigeot break; 25038621f407SFrançois Tigeot } 25048621f407SFrançois Tigeot 25058621f407SFrançois Tigeot if (WARN_ON(&target->list == &engine->request_list)) 25068621f407SFrançois Tigeot return -ENOSPC; 25078621f407SFrançois Tigeot 25088621f407SFrançois Tigeot return i915_wait_request(target); 25098621f407SFrançois Tigeot } 25108621f407SFrançois Tigeot 25118621f407SFrançois Tigeot int intel_ring_begin(struct drm_i915_gem_request *req, int num_dwords) 25128621f407SFrançois Tigeot { 25138621f407SFrançois Tigeot struct intel_ringbuffer *ringbuf = req->ringbuf; 2514a05eeebfSFrançois Tigeot int remain_actual = ringbuf->size - ringbuf->tail; 25158621f407SFrançois Tigeot int remain_usable = ringbuf->effective_size - ringbuf->tail; 25168621f407SFrançois Tigeot int bytes = num_dwords * sizeof(u32); 25178621f407SFrançois Tigeot int total_bytes, wait_bytes; 2518a05eeebfSFrançois Tigeot bool need_wrap = false; 2519a05eeebfSFrançois Tigeot 2520a05eeebfSFrançois Tigeot total_bytes = bytes + ringbuf->reserved_size; 2521a05eeebfSFrançois Tigeot 2522a05eeebfSFrançois Tigeot if (unlikely(bytes > remain_usable)) { 2523a05eeebfSFrançois Tigeot /* 2524a05eeebfSFrançois Tigeot * Not enough space for the basic request. So need to flush 2525a05eeebfSFrançois Tigeot * out the remainder and then wait for base + reserved. 2526a05eeebfSFrançois Tigeot */ 2527a05eeebfSFrançois Tigeot wait_bytes = remain_actual + total_bytes; 2528a05eeebfSFrançois Tigeot need_wrap = true; 25298621f407SFrançois Tigeot } else if (unlikely(total_bytes > remain_usable)) { 2530a05eeebfSFrançois Tigeot /* 2531a05eeebfSFrançois Tigeot * The base request will fit but the reserved space 25328621f407SFrançois Tigeot * falls off the end. So we don't need an immediate wrap 2533c0e85e96SFrançois Tigeot * and only need to effectively wait for the reserved 2534c0e85e96SFrançois Tigeot * size space from the start of ringbuffer. 2535a05eeebfSFrançois Tigeot */ 2536a05eeebfSFrançois Tigeot wait_bytes = remain_actual + ringbuf->reserved_size; 25378621f407SFrançois Tigeot } else { 2538a05eeebfSFrançois Tigeot /* No wrapping required, just waiting. */ 2539a05eeebfSFrançois Tigeot wait_bytes = total_bytes; 2540a05eeebfSFrançois Tigeot } 2541a05eeebfSFrançois Tigeot 25428621f407SFrançois Tigeot if (wait_bytes > ringbuf->space) { 25438621f407SFrançois Tigeot int ret = wait_for_space(req, wait_bytes); 2544a2fdbec6SFrançois Tigeot if (unlikely(ret)) 2545a2fdbec6SFrançois Tigeot return ret; 2546a05eeebfSFrançois Tigeot 25478621f407SFrançois Tigeot intel_ring_update_space(ringbuf); 25488621f407SFrançois Tigeot if (unlikely(ringbuf->space < wait_bytes)) 25498621f407SFrançois Tigeot return -EAGAIN; 2550a2fdbec6SFrançois Tigeot } 2551a2fdbec6SFrançois Tigeot 25528621f407SFrançois Tigeot if (unlikely(need_wrap)) { 25538621f407SFrançois Tigeot GEM_BUG_ON(remain_actual > ringbuf->space); 25548621f407SFrançois Tigeot GEM_BUG_ON(ringbuf->tail + remain_actual > ringbuf->size); 25558621f407SFrançois Tigeot 25568621f407SFrançois Tigeot /* Fill the tail with MI_NOOP */ 25578621f407SFrançois Tigeot memset(ringbuf->virtual_start + ringbuf->tail, 25588621f407SFrançois Tigeot 0, remain_actual); 25598621f407SFrançois Tigeot ringbuf->tail = 0; 25608621f407SFrançois Tigeot ringbuf->space -= remain_actual; 2561a2fdbec6SFrançois Tigeot } 2562a2fdbec6SFrançois Tigeot 25638621f407SFrançois Tigeot ringbuf->space -= bytes; 25648621f407SFrançois Tigeot GEM_BUG_ON(ringbuf->space < 0); 25659edbd4a0SFrançois Tigeot return 0; 25669edbd4a0SFrançois Tigeot } 25679edbd4a0SFrançois Tigeot 25689edbd4a0SFrançois Tigeot /* Align the ring tail to a cacheline boundary */ 2569a05eeebfSFrançois Tigeot int intel_ring_cacheline_align(struct drm_i915_gem_request *req) 25709edbd4a0SFrançois Tigeot { 25718621f407SFrançois Tigeot struct intel_engine_cs *engine = req->engine; 25728621f407SFrançois Tigeot int num_dwords = (engine->buffer->tail & (CACHELINE_BYTES - 1)) / sizeof(uint32_t); 25739edbd4a0SFrançois Tigeot int ret; 25749edbd4a0SFrançois Tigeot 25759edbd4a0SFrançois Tigeot if (num_dwords == 0) 25769edbd4a0SFrançois Tigeot return 0; 25779edbd4a0SFrançois Tigeot 2578ba55f2f5SFrançois Tigeot num_dwords = CACHELINE_BYTES / sizeof(uint32_t) - num_dwords; 2579a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, num_dwords); 25809edbd4a0SFrançois Tigeot if (ret) 25819edbd4a0SFrançois Tigeot return ret; 25829edbd4a0SFrançois Tigeot 25839edbd4a0SFrançois Tigeot while (num_dwords--) 25848621f407SFrançois Tigeot intel_ring_emit(engine, MI_NOOP); 25859edbd4a0SFrançois Tigeot 25868621f407SFrançois Tigeot intel_ring_advance(engine); 25879edbd4a0SFrançois Tigeot 25889edbd4a0SFrançois Tigeot return 0; 2589e3adcf8fSFrançois Tigeot } 2590e3adcf8fSFrançois Tigeot 25918621f407SFrançois Tigeot void intel_ring_init_seqno(struct intel_engine_cs *engine, u32 seqno) 2592a2fdbec6SFrançois Tigeot { 25938621f407SFrançois Tigeot struct drm_i915_private *dev_priv = to_i915(engine->dev); 2594a2fdbec6SFrançois Tigeot 25958621f407SFrançois Tigeot /* Our semaphore implementation is strictly monotonic (i.e. we proceed 25968621f407SFrançois Tigeot * so long as the semaphore value in the register/page is greater 25978621f407SFrançois Tigeot * than the sync value), so whenever we reset the seqno, 25988621f407SFrançois Tigeot * so long as we reset the tracking semaphore value to 0, it will 25998621f407SFrançois Tigeot * always be before the next request's seqno. If we don't reset 26008621f407SFrançois Tigeot * the semaphore value, then when the seqno moves backwards all 26018621f407SFrançois Tigeot * future waits will complete instantly (causing rendering corruption). 26028621f407SFrançois Tigeot */ 26038621f407SFrançois Tigeot if (INTEL_INFO(dev_priv)->gen == 6 || INTEL_INFO(dev_priv)->gen == 7) { 26048621f407SFrançois Tigeot I915_WRITE(RING_SYNC_0(engine->mmio_base), 0); 26058621f407SFrançois Tigeot I915_WRITE(RING_SYNC_1(engine->mmio_base), 0); 26068621f407SFrançois Tigeot if (HAS_VEBOX(dev_priv)) 26078621f407SFrançois Tigeot I915_WRITE(RING_SYNC_2(engine->mmio_base), 0); 26088621f407SFrançois Tigeot } 26098621f407SFrançois Tigeot if (dev_priv->semaphore_obj) { 26108621f407SFrançois Tigeot struct drm_i915_gem_object *obj = dev_priv->semaphore_obj; 2611*f0bba3d1SFrançois Tigeot struct page *page = i915_gem_object_get_dirty_page(obj, 0); 26128621f407SFrançois Tigeot char *semaphores = kmap(page); 26138621f407SFrançois Tigeot memset(semaphores + GEN8_SEMAPHORE_OFFSET(engine->id, 0), 26148621f407SFrançois Tigeot 0, I915_NUM_ENGINES * gen8_semaphore_seqno_size); 26158621f407SFrançois Tigeot kunmap(page); 26168621f407SFrançois Tigeot } 26178621f407SFrançois Tigeot memset(engine->semaphore.sync_seqno, 0, 26188621f407SFrançois Tigeot sizeof(engine->semaphore.sync_seqno)); 26198621f407SFrançois Tigeot 26208621f407SFrançois Tigeot engine->set_seqno(engine, seqno); 26218621f407SFrançois Tigeot engine->last_submitted_seqno = seqno; 26228621f407SFrançois Tigeot 26238621f407SFrançois Tigeot engine->hangcheck.seqno = seqno; 2624e3adcf8fSFrançois Tigeot } 2625e3adcf8fSFrançois Tigeot 26268621f407SFrançois Tigeot static void gen6_bsd_ring_write_tail(struct intel_engine_cs *engine, 2627f4e1c372SFrançois Tigeot u32 value) 2628e3adcf8fSFrançois Tigeot { 26298621f407SFrançois Tigeot struct drm_i915_private *dev_priv = engine->dev->dev_private; 2630e3adcf8fSFrançois Tigeot 2631e3adcf8fSFrançois Tigeot /* Every tail move must follow the sequence below */ 2632f4e1c372SFrançois Tigeot 2633f4e1c372SFrançois Tigeot /* Disable notification that the ring is IDLE. The GT 2634f4e1c372SFrançois Tigeot * will then assume that it is busy and bring it out of rc6. 2635f4e1c372SFrançois Tigeot */ 2636e3adcf8fSFrançois Tigeot I915_WRITE(GEN6_BSD_SLEEP_PSMI_CONTROL, 2637f4e1c372SFrançois Tigeot _MASKED_BIT_ENABLE(GEN6_BSD_SLEEP_MSG_DISABLE)); 2638e3adcf8fSFrançois Tigeot 2639f4e1c372SFrançois Tigeot /* Clear the context id. Here be magic! */ 2640f4e1c372SFrançois Tigeot I915_WRITE64(GEN6_BSD_RNCID, 0x0); 2641e3adcf8fSFrançois Tigeot 2642f4e1c372SFrançois Tigeot /* Wait for the ring not to be idle, i.e. for it to wake up. */ 2643f4e1c372SFrançois Tigeot if (wait_for((I915_READ(GEN6_BSD_SLEEP_PSMI_CONTROL) & 2644f4e1c372SFrançois Tigeot GEN6_BSD_SLEEP_INDICATOR) == 0, 2645f4e1c372SFrançois Tigeot 50)) 2646f4e1c372SFrançois Tigeot DRM_ERROR("timed out waiting for the BSD ring to wake up\n"); 2647f4e1c372SFrançois Tigeot 2648f4e1c372SFrançois Tigeot /* Now that the ring is fully powered up, update the tail */ 26498621f407SFrançois Tigeot I915_WRITE_TAIL(engine, value); 26508621f407SFrançois Tigeot POSTING_READ(RING_TAIL(engine->mmio_base)); 2651f4e1c372SFrançois Tigeot 2652f4e1c372SFrançois Tigeot /* Let the ring send IDLE messages to the GT again, 2653f4e1c372SFrançois Tigeot * and so let it sleep to conserve power when idle. 2654f4e1c372SFrançois Tigeot */ 2655e3adcf8fSFrançois Tigeot I915_WRITE(GEN6_BSD_SLEEP_PSMI_CONTROL, 2656f4e1c372SFrançois Tigeot _MASKED_BIT_DISABLE(GEN6_BSD_SLEEP_MSG_DISABLE)); 2657e3adcf8fSFrançois Tigeot } 2658e3adcf8fSFrançois Tigeot 2659a05eeebfSFrançois Tigeot static int gen6_bsd_ring_flush(struct drm_i915_gem_request *req, 2660b5c29a34SFrançois Tigeot u32 invalidate, u32 flush) 2661e3adcf8fSFrançois Tigeot { 26628621f407SFrançois Tigeot struct intel_engine_cs *engine = req->engine; 2663e3adcf8fSFrançois Tigeot uint32_t cmd; 2664e3adcf8fSFrançois Tigeot int ret; 2665e3adcf8fSFrançois Tigeot 2666a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 4); 2667e3adcf8fSFrançois Tigeot if (ret) 2668e3adcf8fSFrançois Tigeot return ret; 2669e3adcf8fSFrançois Tigeot 2670e3adcf8fSFrançois Tigeot cmd = MI_FLUSH_DW; 26718621f407SFrançois Tigeot if (INTEL_INFO(engine->dev)->gen >= 8) 26729edbd4a0SFrançois Tigeot cmd += 1; 26732c9916cdSFrançois Tigeot 26742c9916cdSFrançois Tigeot /* We always require a command barrier so that subsequent 26752c9916cdSFrançois Tigeot * commands, such as breadcrumb interrupts, are strictly ordered 26762c9916cdSFrançois Tigeot * wrt the contents of the write cache being flushed to memory 26772c9916cdSFrançois Tigeot * (and thus being coherent from the CPU). 26782c9916cdSFrançois Tigeot */ 26792c9916cdSFrançois Tigeot cmd |= MI_FLUSH_DW_STORE_INDEX | MI_FLUSH_DW_OP_STOREDW; 26802c9916cdSFrançois Tigeot 2681b5c29a34SFrançois Tigeot /* 2682b5c29a34SFrançois Tigeot * Bspec vol 1c.5 - video engine command streamer: 2683b5c29a34SFrançois Tigeot * "If ENABLED, all TLBs will be invalidated once the flush 2684b5c29a34SFrançois Tigeot * operation is complete. This bit is only valid when the 2685b5c29a34SFrançois Tigeot * Post-Sync Operation field is a value of 1h or 3h." 2686b5c29a34SFrançois Tigeot */ 2687e3adcf8fSFrançois Tigeot if (invalidate & I915_GEM_GPU_DOMAINS) 26882c9916cdSFrançois Tigeot cmd |= MI_INVALIDATE_TLB | MI_INVALIDATE_BSD; 26892c9916cdSFrançois Tigeot 26908621f407SFrançois Tigeot intel_ring_emit(engine, cmd); 26918621f407SFrançois Tigeot intel_ring_emit(engine, 26928621f407SFrançois Tigeot I915_GEM_HWS_SCRATCH_ADDR | MI_FLUSH_DW_USE_GTT); 26938621f407SFrançois Tigeot if (INTEL_INFO(engine->dev)->gen >= 8) { 26948621f407SFrançois Tigeot intel_ring_emit(engine, 0); /* upper addr */ 26958621f407SFrançois Tigeot intel_ring_emit(engine, 0); /* value */ 26969edbd4a0SFrançois Tigeot } else { 26978621f407SFrançois Tigeot intel_ring_emit(engine, 0); 26988621f407SFrançois Tigeot intel_ring_emit(engine, MI_NOOP); 26999edbd4a0SFrançois Tigeot } 27008621f407SFrançois Tigeot intel_ring_advance(engine); 27019edbd4a0SFrançois Tigeot return 0; 27029edbd4a0SFrançois Tigeot } 27039edbd4a0SFrançois Tigeot 27049edbd4a0SFrançois Tigeot static int 2705a05eeebfSFrançois Tigeot gen8_ring_dispatch_execbuffer(struct drm_i915_gem_request *req, 2706ba55f2f5SFrançois Tigeot u64 offset, u32 len, 2707477eb7f9SFrançois Tigeot unsigned dispatch_flags) 27089edbd4a0SFrançois Tigeot { 27098621f407SFrançois Tigeot struct intel_engine_cs *engine = req->engine; 27108621f407SFrançois Tigeot bool ppgtt = USES_PPGTT(engine->dev) && 2711477eb7f9SFrançois Tigeot !(dispatch_flags & I915_DISPATCH_SECURE); 27129edbd4a0SFrançois Tigeot int ret; 27139edbd4a0SFrançois Tigeot 2714a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 4); 27159edbd4a0SFrançois Tigeot if (ret) 27169edbd4a0SFrançois Tigeot return ret; 27179edbd4a0SFrançois Tigeot 27189edbd4a0SFrançois Tigeot /* FIXME(BDW): Address space and security selectors. */ 27198621f407SFrançois Tigeot intel_ring_emit(engine, MI_BATCH_BUFFER_START_GEN8 | (ppgtt<<8) | 2720a05eeebfSFrançois Tigeot (dispatch_flags & I915_DISPATCH_RS ? 2721a05eeebfSFrançois Tigeot MI_BATCH_RESOURCE_STREAMER : 0)); 27228621f407SFrançois Tigeot intel_ring_emit(engine, lower_32_bits(offset)); 27238621f407SFrançois Tigeot intel_ring_emit(engine, upper_32_bits(offset)); 27248621f407SFrançois Tigeot intel_ring_emit(engine, MI_NOOP); 27258621f407SFrançois Tigeot intel_ring_advance(engine); 27269edbd4a0SFrançois Tigeot 2727e3adcf8fSFrançois Tigeot return 0; 2728e3adcf8fSFrançois Tigeot } 2729e3adcf8fSFrançois Tigeot 2730e3adcf8fSFrançois Tigeot static int 2731a05eeebfSFrançois Tigeot hsw_ring_dispatch_execbuffer(struct drm_i915_gem_request *req, 2732ba55f2f5SFrançois Tigeot u64 offset, u32 len, 2733477eb7f9SFrançois Tigeot unsigned dispatch_flags) 2734e3adcf8fSFrançois Tigeot { 27358621f407SFrançois Tigeot struct intel_engine_cs *engine = req->engine; 2736e3adcf8fSFrançois Tigeot int ret; 2737e3adcf8fSFrançois Tigeot 2738a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 2); 2739e3adcf8fSFrançois Tigeot if (ret) 2740e3adcf8fSFrançois Tigeot return ret; 2741e3adcf8fSFrançois Tigeot 27428621f407SFrançois Tigeot intel_ring_emit(engine, 27431b13d190SFrançois Tigeot MI_BATCH_BUFFER_START | 2744477eb7f9SFrançois Tigeot (dispatch_flags & I915_DISPATCH_SECURE ? 2745a05eeebfSFrançois Tigeot 0 : MI_BATCH_PPGTT_HSW | MI_BATCH_NON_SECURE_HSW) | 2746a05eeebfSFrançois Tigeot (dispatch_flags & I915_DISPATCH_RS ? 2747a05eeebfSFrançois Tigeot MI_BATCH_RESOURCE_STREAMER : 0)); 2748b5c29a34SFrançois Tigeot /* bit0-7 is the length on GEN6+ */ 27498621f407SFrançois Tigeot intel_ring_emit(engine, offset); 27508621f407SFrançois Tigeot intel_ring_advance(engine); 2751b5c29a34SFrançois Tigeot 2752b5c29a34SFrançois Tigeot return 0; 2753b5c29a34SFrançois Tigeot } 2754b5c29a34SFrançois Tigeot 2755b5c29a34SFrançois Tigeot static int 2756a05eeebfSFrançois Tigeot gen6_ring_dispatch_execbuffer(struct drm_i915_gem_request *req, 2757ba55f2f5SFrançois Tigeot u64 offset, u32 len, 2758477eb7f9SFrançois Tigeot unsigned dispatch_flags) 2759b5c29a34SFrançois Tigeot { 27608621f407SFrançois Tigeot struct intel_engine_cs *engine = req->engine; 2761b5c29a34SFrançois Tigeot int ret; 2762b5c29a34SFrançois Tigeot 2763a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 2); 2764b5c29a34SFrançois Tigeot if (ret) 2765b5c29a34SFrançois Tigeot return ret; 2766b5c29a34SFrançois Tigeot 27678621f407SFrançois Tigeot intel_ring_emit(engine, 2768b5c29a34SFrançois Tigeot MI_BATCH_BUFFER_START | 2769477eb7f9SFrançois Tigeot (dispatch_flags & I915_DISPATCH_SECURE ? 2770477eb7f9SFrançois Tigeot 0 : MI_BATCH_NON_SECURE_I965)); 2771e3adcf8fSFrançois Tigeot /* bit0-7 is the length on GEN6+ */ 27728621f407SFrançois Tigeot intel_ring_emit(engine, offset); 27738621f407SFrançois Tigeot intel_ring_advance(engine); 2774e3adcf8fSFrançois Tigeot 2775e3adcf8fSFrançois Tigeot return 0; 2776e3adcf8fSFrançois Tigeot } 2777e3adcf8fSFrançois Tigeot 2778e3adcf8fSFrançois Tigeot /* Blitter support (SandyBridge+) */ 2779e3adcf8fSFrançois Tigeot 2780a05eeebfSFrançois Tigeot static int gen6_ring_flush(struct drm_i915_gem_request *req, 2781b5c29a34SFrançois Tigeot u32 invalidate, u32 flush) 2782e3adcf8fSFrançois Tigeot { 27838621f407SFrançois Tigeot struct intel_engine_cs *engine = req->engine; 27848621f407SFrançois Tigeot struct drm_device *dev = engine->dev; 2785e3adcf8fSFrançois Tigeot uint32_t cmd; 2786e3adcf8fSFrançois Tigeot int ret; 2787e3adcf8fSFrançois Tigeot 2788a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 4); 2789e3adcf8fSFrançois Tigeot if (ret) 2790e3adcf8fSFrançois Tigeot return ret; 2791e3adcf8fSFrançois Tigeot 2792e3adcf8fSFrançois Tigeot cmd = MI_FLUSH_DW; 2793477eb7f9SFrançois Tigeot if (INTEL_INFO(dev)->gen >= 8) 27949edbd4a0SFrançois Tigeot cmd += 1; 27952c9916cdSFrançois Tigeot 27962c9916cdSFrançois Tigeot /* We always require a command barrier so that subsequent 27972c9916cdSFrançois Tigeot * commands, such as breadcrumb interrupts, are strictly ordered 27982c9916cdSFrançois Tigeot * wrt the contents of the write cache being flushed to memory 27992c9916cdSFrançois Tigeot * (and thus being coherent from the CPU). 28002c9916cdSFrançois Tigeot */ 28012c9916cdSFrançois Tigeot cmd |= MI_FLUSH_DW_STORE_INDEX | MI_FLUSH_DW_OP_STOREDW; 28022c9916cdSFrançois Tigeot 2803b5c29a34SFrançois Tigeot /* 2804b5c29a34SFrançois Tigeot * Bspec vol 1c.3 - blitter engine command streamer: 2805b5c29a34SFrançois Tigeot * "If ENABLED, all TLBs will be invalidated once the flush 2806b5c29a34SFrançois Tigeot * operation is complete. This bit is only valid when the 2807b5c29a34SFrançois Tigeot * Post-Sync Operation field is a value of 1h or 3h." 2808b5c29a34SFrançois Tigeot */ 2809e3adcf8fSFrançois Tigeot if (invalidate & I915_GEM_DOMAIN_RENDER) 28102c9916cdSFrançois Tigeot cmd |= MI_INVALIDATE_TLB; 28118621f407SFrançois Tigeot intel_ring_emit(engine, cmd); 28128621f407SFrançois Tigeot intel_ring_emit(engine, 28138621f407SFrançois Tigeot I915_GEM_HWS_SCRATCH_ADDR | MI_FLUSH_DW_USE_GTT); 2814477eb7f9SFrançois Tigeot if (INTEL_INFO(dev)->gen >= 8) { 28158621f407SFrançois Tigeot intel_ring_emit(engine, 0); /* upper addr */ 28168621f407SFrançois Tigeot intel_ring_emit(engine, 0); /* value */ 28179edbd4a0SFrançois Tigeot } else { 28188621f407SFrançois Tigeot intel_ring_emit(engine, 0); 28198621f407SFrançois Tigeot intel_ring_emit(engine, MI_NOOP); 28209edbd4a0SFrançois Tigeot } 28218621f407SFrançois Tigeot intel_ring_advance(engine); 28225d0b1887SFrançois Tigeot 2823e3adcf8fSFrançois Tigeot return 0; 2824e3adcf8fSFrançois Tigeot } 2825e3adcf8fSFrançois Tigeot 2826e3adcf8fSFrançois Tigeot int intel_init_render_ring_buffer(struct drm_device *dev) 2827e3adcf8fSFrançois Tigeot { 2828ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 28298621f407SFrançois Tigeot struct intel_engine_cs *engine = &dev_priv->engine[RCS]; 283024edb884SFrançois Tigeot struct drm_i915_gem_object *obj; 283124edb884SFrançois Tigeot int ret; 2832e3adcf8fSFrançois Tigeot 28338621f407SFrançois Tigeot engine->name = "render ring"; 28348621f407SFrançois Tigeot engine->id = RCS; 28358621f407SFrançois Tigeot engine->exec_id = I915_EXEC_RENDER; 28368621f407SFrançois Tigeot engine->hw_id = 0; 28378621f407SFrançois Tigeot engine->mmio_base = RENDER_RING_BASE; 2838686a02f1SFrançois Tigeot 283924edb884SFrançois Tigeot if (INTEL_INFO(dev)->gen >= 8) { 284024edb884SFrançois Tigeot if (i915_semaphore_is_enabled(dev)) { 284124edb884SFrançois Tigeot obj = i915_gem_alloc_object(dev, 4096); 284224edb884SFrançois Tigeot if (obj == NULL) { 284324edb884SFrançois Tigeot DRM_ERROR("Failed to allocate semaphore bo. Disabling semaphores\n"); 284424edb884SFrançois Tigeot i915.semaphores = 0; 284524edb884SFrançois Tigeot } else { 284624edb884SFrançois Tigeot i915_gem_object_set_cache_level(obj, I915_CACHE_LLC); 284724edb884SFrançois Tigeot ret = i915_gem_obj_ggtt_pin(obj, 0, PIN_NONBLOCK); 284824edb884SFrançois Tigeot if (ret != 0) { 284924edb884SFrançois Tigeot drm_gem_object_unreference(&obj->base); 285024edb884SFrançois Tigeot DRM_ERROR("Failed to pin semaphore bo. Disabling semaphores\n"); 285124edb884SFrançois Tigeot i915.semaphores = 0; 285224edb884SFrançois Tigeot } else 285324edb884SFrançois Tigeot dev_priv->semaphore_obj = obj; 285424edb884SFrançois Tigeot } 285524edb884SFrançois Tigeot } 28562c9916cdSFrançois Tigeot 28578621f407SFrançois Tigeot engine->init_context = intel_rcs_ctx_init; 28588621f407SFrançois Tigeot engine->add_request = gen6_add_request; 28598621f407SFrançois Tigeot engine->flush = gen8_render_ring_flush; 28608621f407SFrançois Tigeot engine->irq_get = gen8_ring_get_irq; 28618621f407SFrançois Tigeot engine->irq_put = gen8_ring_put_irq; 28628621f407SFrançois Tigeot engine->irq_enable_mask = GT_RENDER_USER_INTERRUPT; 28638621f407SFrançois Tigeot engine->irq_seqno_barrier = gen6_seqno_barrier; 28648621f407SFrançois Tigeot engine->get_seqno = ring_get_seqno; 28658621f407SFrançois Tigeot engine->set_seqno = ring_set_seqno; 286624edb884SFrançois Tigeot if (i915_semaphore_is_enabled(dev)) { 286724edb884SFrançois Tigeot WARN_ON(!dev_priv->semaphore_obj); 28688621f407SFrançois Tigeot engine->semaphore.sync_to = gen8_ring_sync; 28698621f407SFrançois Tigeot engine->semaphore.signal = gen8_rcs_signal; 28708621f407SFrançois Tigeot GEN8_RING_SEMAPHORE_INIT(engine); 287124edb884SFrançois Tigeot } 287224edb884SFrançois Tigeot } else if (INTEL_INFO(dev)->gen >= 6) { 28738621f407SFrançois Tigeot engine->init_context = intel_rcs_ctx_init; 28748621f407SFrançois Tigeot engine->add_request = gen6_add_request; 28758621f407SFrançois Tigeot engine->flush = gen7_render_ring_flush; 2876b5c29a34SFrançois Tigeot if (INTEL_INFO(dev)->gen == 6) 28778621f407SFrançois Tigeot engine->flush = gen6_render_ring_flush; 28788621f407SFrançois Tigeot engine->irq_get = gen6_ring_get_irq; 28798621f407SFrançois Tigeot engine->irq_put = gen6_ring_put_irq; 28808621f407SFrançois Tigeot engine->irq_enable_mask = GT_RENDER_USER_INTERRUPT; 28818621f407SFrançois Tigeot engine->irq_seqno_barrier = gen6_seqno_barrier; 28828621f407SFrançois Tigeot engine->get_seqno = ring_get_seqno; 28838621f407SFrançois Tigeot engine->set_seqno = ring_set_seqno; 288424edb884SFrançois Tigeot if (i915_semaphore_is_enabled(dev)) { 28858621f407SFrançois Tigeot engine->semaphore.sync_to = gen6_ring_sync; 28868621f407SFrançois Tigeot engine->semaphore.signal = gen6_signal; 2887ba55f2f5SFrançois Tigeot /* 288824edb884SFrançois Tigeot * The current semaphore is only applied on pre-gen8 288924edb884SFrançois Tigeot * platform. And there is no VCS2 ring on the pre-gen8 289024edb884SFrançois Tigeot * platform. So the semaphore between RCS and VCS2 is 289124edb884SFrançois Tigeot * initialized as INVALID. Gen8 will initialize the 289224edb884SFrançois Tigeot * sema between VCS2 and RCS later. 2893ba55f2f5SFrançois Tigeot */ 28948621f407SFrançois Tigeot engine->semaphore.mbox.wait[RCS] = MI_SEMAPHORE_SYNC_INVALID; 28958621f407SFrançois Tigeot engine->semaphore.mbox.wait[VCS] = MI_SEMAPHORE_SYNC_RV; 28968621f407SFrançois Tigeot engine->semaphore.mbox.wait[BCS] = MI_SEMAPHORE_SYNC_RB; 28978621f407SFrançois Tigeot engine->semaphore.mbox.wait[VECS] = MI_SEMAPHORE_SYNC_RVE; 28988621f407SFrançois Tigeot engine->semaphore.mbox.wait[VCS2] = MI_SEMAPHORE_SYNC_INVALID; 28998621f407SFrançois Tigeot engine->semaphore.mbox.signal[RCS] = GEN6_NOSYNC; 29008621f407SFrançois Tigeot engine->semaphore.mbox.signal[VCS] = GEN6_VRSYNC; 29018621f407SFrançois Tigeot engine->semaphore.mbox.signal[BCS] = GEN6_BRSYNC; 29028621f407SFrançois Tigeot engine->semaphore.mbox.signal[VECS] = GEN6_VERSYNC; 29038621f407SFrançois Tigeot engine->semaphore.mbox.signal[VCS2] = GEN6_NOSYNC; 290424edb884SFrançois Tigeot } 2905e3adcf8fSFrançois Tigeot } else if (IS_GEN5(dev)) { 29068621f407SFrançois Tigeot engine->add_request = pc_render_add_request; 29078621f407SFrançois Tigeot engine->flush = gen4_render_ring_flush; 29088621f407SFrançois Tigeot engine->get_seqno = pc_render_get_seqno; 29098621f407SFrançois Tigeot engine->set_seqno = pc_render_set_seqno; 29108621f407SFrançois Tigeot engine->irq_get = gen5_ring_get_irq; 29118621f407SFrançois Tigeot engine->irq_put = gen5_ring_put_irq; 29128621f407SFrançois Tigeot engine->irq_enable_mask = GT_RENDER_USER_INTERRUPT | 29135d0b1887SFrançois Tigeot GT_RENDER_PIPECTL_NOTIFY_INTERRUPT; 2914686a02f1SFrançois Tigeot } else { 29158621f407SFrançois Tigeot engine->add_request = i9xx_add_request; 2916686a02f1SFrançois Tigeot if (INTEL_INFO(dev)->gen < 4) 29178621f407SFrançois Tigeot engine->flush = gen2_render_ring_flush; 2918686a02f1SFrançois Tigeot else 29198621f407SFrançois Tigeot engine->flush = gen4_render_ring_flush; 29208621f407SFrançois Tigeot engine->get_seqno = ring_get_seqno; 29218621f407SFrançois Tigeot engine->set_seqno = ring_set_seqno; 2922686a02f1SFrançois Tigeot if (IS_GEN2(dev)) { 29238621f407SFrançois Tigeot engine->irq_get = i8xx_ring_get_irq; 29248621f407SFrançois Tigeot engine->irq_put = i8xx_ring_put_irq; 2925686a02f1SFrançois Tigeot } else { 29268621f407SFrançois Tigeot engine->irq_get = i9xx_ring_get_irq; 29278621f407SFrançois Tigeot engine->irq_put = i9xx_ring_put_irq; 2928e3adcf8fSFrançois Tigeot } 29298621f407SFrançois Tigeot engine->irq_enable_mask = I915_USER_INTERRUPT; 2930686a02f1SFrançois Tigeot } 29318621f407SFrançois Tigeot engine->write_tail = ring_write_tail; 293224edb884SFrançois Tigeot 2933b5c29a34SFrançois Tigeot if (IS_HASWELL(dev)) 29348621f407SFrançois Tigeot engine->dispatch_execbuffer = hsw_ring_dispatch_execbuffer; 29359edbd4a0SFrançois Tigeot else if (IS_GEN8(dev)) 29368621f407SFrançois Tigeot engine->dispatch_execbuffer = gen8_ring_dispatch_execbuffer; 2937b5c29a34SFrançois Tigeot else if (INTEL_INFO(dev)->gen >= 6) 29388621f407SFrançois Tigeot engine->dispatch_execbuffer = gen6_ring_dispatch_execbuffer; 2939686a02f1SFrançois Tigeot else if (INTEL_INFO(dev)->gen >= 4) 29408621f407SFrançois Tigeot engine->dispatch_execbuffer = i965_dispatch_execbuffer; 2941686a02f1SFrançois Tigeot else if (IS_I830(dev) || IS_845G(dev)) 29428621f407SFrançois Tigeot engine->dispatch_execbuffer = i830_dispatch_execbuffer; 2943686a02f1SFrançois Tigeot else 29448621f407SFrançois Tigeot engine->dispatch_execbuffer = i915_dispatch_execbuffer; 29458621f407SFrançois Tigeot engine->init_hw = init_render_ring; 29468621f407SFrançois Tigeot engine->cleanup = render_ring_cleanup; 2947e3adcf8fSFrançois Tigeot 2948b5c29a34SFrançois Tigeot /* Workaround batchbuffer to combat CS tlb bug. */ 2949b5c29a34SFrançois Tigeot if (HAS_BROKEN_CS_TLB(dev)) { 295024edb884SFrançois Tigeot obj = i915_gem_alloc_object(dev, I830_WA_SIZE); 2951b5c29a34SFrançois Tigeot if (obj == NULL) { 2952b5c29a34SFrançois Tigeot DRM_ERROR("Failed to allocate batch bo\n"); 2953b5c29a34SFrançois Tigeot return -ENOMEM; 2954b5c29a34SFrançois Tigeot } 2955b5c29a34SFrançois Tigeot 2956ba55f2f5SFrançois Tigeot ret = i915_gem_obj_ggtt_pin(obj, 0, 0); 2957b5c29a34SFrançois Tigeot if (ret != 0) { 2958b5c29a34SFrançois Tigeot drm_gem_object_unreference(&obj->base); 2959b5c29a34SFrançois Tigeot DRM_ERROR("Failed to ping batch bo\n"); 2960b5c29a34SFrançois Tigeot return ret; 2961b5c29a34SFrançois Tigeot } 2962b5c29a34SFrançois Tigeot 29638621f407SFrançois Tigeot engine->scratch.obj = obj; 29648621f407SFrançois Tigeot engine->scratch.gtt_offset = i915_gem_obj_ggtt_offset(obj); 2965e3adcf8fSFrançois Tigeot } 2966e3adcf8fSFrançois Tigeot 29678621f407SFrançois Tigeot ret = intel_init_ring_buffer(dev, engine); 2968b5c29a34SFrançois Tigeot if (ret) 29692c9916cdSFrançois Tigeot return ret; 29702c9916cdSFrançois Tigeot 29712c9916cdSFrançois Tigeot if (INTEL_INFO(dev)->gen >= 5) { 29728621f407SFrançois Tigeot ret = intel_init_pipe_control(engine); 29732c9916cdSFrançois Tigeot if (ret) 29742c9916cdSFrançois Tigeot return ret; 2975b5c29a34SFrançois Tigeot } 2976b5c29a34SFrançois Tigeot 2977e3adcf8fSFrançois Tigeot return 0; 2978e3adcf8fSFrançois Tigeot } 2979e3adcf8fSFrançois Tigeot 2980e3adcf8fSFrançois Tigeot int intel_init_bsd_ring_buffer(struct drm_device *dev) 2981e3adcf8fSFrançois Tigeot { 2982ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 29838621f407SFrançois Tigeot struct intel_engine_cs *engine = &dev_priv->engine[VCS]; 2984e3adcf8fSFrançois Tigeot 29858621f407SFrançois Tigeot engine->name = "bsd ring"; 29868621f407SFrançois Tigeot engine->id = VCS; 29878621f407SFrançois Tigeot engine->exec_id = I915_EXEC_BSD; 29888621f407SFrançois Tigeot engine->hw_id = 1; 2989686a02f1SFrançois Tigeot 29908621f407SFrançois Tigeot engine->write_tail = ring_write_tail; 29919edbd4a0SFrançois Tigeot if (INTEL_INFO(dev)->gen >= 6) { 29928621f407SFrançois Tigeot engine->mmio_base = GEN6_BSD_RING_BASE; 2993686a02f1SFrançois Tigeot /* gen6 bsd needs a special wa for tail updates */ 2994686a02f1SFrançois Tigeot if (IS_GEN6(dev)) 29958621f407SFrançois Tigeot engine->write_tail = gen6_bsd_ring_write_tail; 29968621f407SFrançois Tigeot engine->flush = gen6_bsd_ring_flush; 29978621f407SFrançois Tigeot engine->add_request = gen6_add_request; 29988621f407SFrançois Tigeot engine->irq_seqno_barrier = gen6_seqno_barrier; 29998621f407SFrançois Tigeot engine->get_seqno = ring_get_seqno; 30008621f407SFrançois Tigeot engine->set_seqno = ring_set_seqno; 30019edbd4a0SFrançois Tigeot if (INTEL_INFO(dev)->gen >= 8) { 30028621f407SFrançois Tigeot engine->irq_enable_mask = 30039edbd4a0SFrançois Tigeot GT_RENDER_USER_INTERRUPT << GEN8_VCS1_IRQ_SHIFT; 30048621f407SFrançois Tigeot engine->irq_get = gen8_ring_get_irq; 30058621f407SFrançois Tigeot engine->irq_put = gen8_ring_put_irq; 30068621f407SFrançois Tigeot engine->dispatch_execbuffer = 30079edbd4a0SFrançois Tigeot gen8_ring_dispatch_execbuffer; 300824edb884SFrançois Tigeot if (i915_semaphore_is_enabled(dev)) { 30098621f407SFrançois Tigeot engine->semaphore.sync_to = gen8_ring_sync; 30108621f407SFrançois Tigeot engine->semaphore.signal = gen8_xcs_signal; 30118621f407SFrançois Tigeot GEN8_RING_SEMAPHORE_INIT(engine); 301224edb884SFrançois Tigeot } 30139edbd4a0SFrançois Tigeot } else { 30148621f407SFrançois Tigeot engine->irq_enable_mask = GT_BSD_USER_INTERRUPT; 30158621f407SFrançois Tigeot engine->irq_get = gen6_ring_get_irq; 30168621f407SFrançois Tigeot engine->irq_put = gen6_ring_put_irq; 30178621f407SFrançois Tigeot engine->dispatch_execbuffer = 30189edbd4a0SFrançois Tigeot gen6_ring_dispatch_execbuffer; 301924edb884SFrançois Tigeot if (i915_semaphore_is_enabled(dev)) { 30208621f407SFrançois Tigeot engine->semaphore.sync_to = gen6_ring_sync; 30218621f407SFrançois Tigeot engine->semaphore.signal = gen6_signal; 30228621f407SFrançois Tigeot engine->semaphore.mbox.wait[RCS] = MI_SEMAPHORE_SYNC_VR; 30238621f407SFrançois Tigeot engine->semaphore.mbox.wait[VCS] = MI_SEMAPHORE_SYNC_INVALID; 30248621f407SFrançois Tigeot engine->semaphore.mbox.wait[BCS] = MI_SEMAPHORE_SYNC_VB; 30258621f407SFrançois Tigeot engine->semaphore.mbox.wait[VECS] = MI_SEMAPHORE_SYNC_VVE; 30268621f407SFrançois Tigeot engine->semaphore.mbox.wait[VCS2] = MI_SEMAPHORE_SYNC_INVALID; 30278621f407SFrançois Tigeot engine->semaphore.mbox.signal[RCS] = GEN6_RVSYNC; 30288621f407SFrançois Tigeot engine->semaphore.mbox.signal[VCS] = GEN6_NOSYNC; 30298621f407SFrançois Tigeot engine->semaphore.mbox.signal[BCS] = GEN6_BVSYNC; 30308621f407SFrançois Tigeot engine->semaphore.mbox.signal[VECS] = GEN6_VEVSYNC; 30318621f407SFrançois Tigeot engine->semaphore.mbox.signal[VCS2] = GEN6_NOSYNC; 303224edb884SFrançois Tigeot } 303324edb884SFrançois Tigeot } 3034686a02f1SFrançois Tigeot } else { 30358621f407SFrançois Tigeot engine->mmio_base = BSD_RING_BASE; 30368621f407SFrançois Tigeot engine->flush = bsd_ring_flush; 30378621f407SFrançois Tigeot engine->add_request = i9xx_add_request; 30388621f407SFrançois Tigeot engine->get_seqno = ring_get_seqno; 30398621f407SFrançois Tigeot engine->set_seqno = ring_set_seqno; 3040686a02f1SFrançois Tigeot if (IS_GEN5(dev)) { 30418621f407SFrançois Tigeot engine->irq_enable_mask = ILK_BSD_USER_INTERRUPT; 30428621f407SFrançois Tigeot engine->irq_get = gen5_ring_get_irq; 30438621f407SFrançois Tigeot engine->irq_put = gen5_ring_put_irq; 3044686a02f1SFrançois Tigeot } else { 30458621f407SFrançois Tigeot engine->irq_enable_mask = I915_BSD_USER_INTERRUPT; 30468621f407SFrançois Tigeot engine->irq_get = i9xx_ring_get_irq; 30478621f407SFrançois Tigeot engine->irq_put = i9xx_ring_put_irq; 3048686a02f1SFrançois Tigeot } 30498621f407SFrançois Tigeot engine->dispatch_execbuffer = i965_dispatch_execbuffer; 3050686a02f1SFrançois Tigeot } 30518621f407SFrançois Tigeot engine->init_hw = init_ring_common; 3052e3adcf8fSFrançois Tigeot 30538621f407SFrançois Tigeot return intel_init_ring_buffer(dev, engine); 3054e3adcf8fSFrançois Tigeot } 3055e3adcf8fSFrançois Tigeot 3056ba55f2f5SFrançois Tigeot /** 3057477eb7f9SFrançois Tigeot * Initialize the second BSD ring (eg. Broadwell GT3, Skylake GT3) 3058ba55f2f5SFrançois Tigeot */ 3059ba55f2f5SFrançois Tigeot int intel_init_bsd2_ring_buffer(struct drm_device *dev) 3060ba55f2f5SFrançois Tigeot { 3061ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 30628621f407SFrançois Tigeot struct intel_engine_cs *engine = &dev_priv->engine[VCS2]; 3063ba55f2f5SFrançois Tigeot 30648621f407SFrançois Tigeot engine->name = "bsd2 ring"; 30658621f407SFrançois Tigeot engine->id = VCS2; 30668621f407SFrançois Tigeot engine->exec_id = I915_EXEC_BSD; 30678621f407SFrançois Tigeot engine->hw_id = 4; 3068ba55f2f5SFrançois Tigeot 30698621f407SFrançois Tigeot engine->write_tail = ring_write_tail; 30708621f407SFrançois Tigeot engine->mmio_base = GEN8_BSD2_RING_BASE; 30718621f407SFrançois Tigeot engine->flush = gen6_bsd_ring_flush; 30728621f407SFrançois Tigeot engine->add_request = gen6_add_request; 30738621f407SFrançois Tigeot engine->irq_seqno_barrier = gen6_seqno_barrier; 30748621f407SFrançois Tigeot engine->get_seqno = ring_get_seqno; 30758621f407SFrançois Tigeot engine->set_seqno = ring_set_seqno; 30768621f407SFrançois Tigeot engine->irq_enable_mask = 3077ba55f2f5SFrançois Tigeot GT_RENDER_USER_INTERRUPT << GEN8_VCS2_IRQ_SHIFT; 30788621f407SFrançois Tigeot engine->irq_get = gen8_ring_get_irq; 30798621f407SFrançois Tigeot engine->irq_put = gen8_ring_put_irq; 30808621f407SFrançois Tigeot engine->dispatch_execbuffer = 3081ba55f2f5SFrançois Tigeot gen8_ring_dispatch_execbuffer; 308224edb884SFrançois Tigeot if (i915_semaphore_is_enabled(dev)) { 30838621f407SFrançois Tigeot engine->semaphore.sync_to = gen8_ring_sync; 30848621f407SFrançois Tigeot engine->semaphore.signal = gen8_xcs_signal; 30858621f407SFrançois Tigeot GEN8_RING_SEMAPHORE_INIT(engine); 308624edb884SFrançois Tigeot } 30878621f407SFrançois Tigeot engine->init_hw = init_ring_common; 3088ba55f2f5SFrançois Tigeot 30898621f407SFrançois Tigeot return intel_init_ring_buffer(dev, engine); 3090ba55f2f5SFrançois Tigeot } 3091ba55f2f5SFrançois Tigeot 3092e3adcf8fSFrançois Tigeot int intel_init_blt_ring_buffer(struct drm_device *dev) 3093e3adcf8fSFrançois Tigeot { 3094ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 30958621f407SFrançois Tigeot struct intel_engine_cs *engine = &dev_priv->engine[BCS]; 3096e3adcf8fSFrançois Tigeot 30978621f407SFrançois Tigeot engine->name = "blitter ring"; 30988621f407SFrançois Tigeot engine->id = BCS; 30998621f407SFrançois Tigeot engine->exec_id = I915_EXEC_BLT; 31008621f407SFrançois Tigeot engine->hw_id = 2; 3101686a02f1SFrançois Tigeot 31028621f407SFrançois Tigeot engine->mmio_base = BLT_RING_BASE; 31038621f407SFrançois Tigeot engine->write_tail = ring_write_tail; 31048621f407SFrançois Tigeot engine->flush = gen6_ring_flush; 31058621f407SFrançois Tigeot engine->add_request = gen6_add_request; 31068621f407SFrançois Tigeot engine->irq_seqno_barrier = gen6_seqno_barrier; 31078621f407SFrançois Tigeot engine->get_seqno = ring_get_seqno; 31088621f407SFrançois Tigeot engine->set_seqno = ring_set_seqno; 31099edbd4a0SFrançois Tigeot if (INTEL_INFO(dev)->gen >= 8) { 31108621f407SFrançois Tigeot engine->irq_enable_mask = 31119edbd4a0SFrançois Tigeot GT_RENDER_USER_INTERRUPT << GEN8_BCS_IRQ_SHIFT; 31128621f407SFrançois Tigeot engine->irq_get = gen8_ring_get_irq; 31138621f407SFrançois Tigeot engine->irq_put = gen8_ring_put_irq; 31148621f407SFrançois Tigeot engine->dispatch_execbuffer = gen8_ring_dispatch_execbuffer; 311524edb884SFrançois Tigeot if (i915_semaphore_is_enabled(dev)) { 31168621f407SFrançois Tigeot engine->semaphore.sync_to = gen8_ring_sync; 31178621f407SFrançois Tigeot engine->semaphore.signal = gen8_xcs_signal; 31188621f407SFrançois Tigeot GEN8_RING_SEMAPHORE_INIT(engine); 311924edb884SFrançois Tigeot } 31209edbd4a0SFrançois Tigeot } else { 31218621f407SFrançois Tigeot engine->irq_enable_mask = GT_BLT_USER_INTERRUPT; 31228621f407SFrançois Tigeot engine->irq_get = gen6_ring_get_irq; 31238621f407SFrançois Tigeot engine->irq_put = gen6_ring_put_irq; 31248621f407SFrançois Tigeot engine->dispatch_execbuffer = gen6_ring_dispatch_execbuffer; 312524edb884SFrançois Tigeot if (i915_semaphore_is_enabled(dev)) { 31268621f407SFrançois Tigeot engine->semaphore.signal = gen6_signal; 31278621f407SFrançois Tigeot engine->semaphore.sync_to = gen6_ring_sync; 3128ba55f2f5SFrançois Tigeot /* 312924edb884SFrançois Tigeot * The current semaphore is only applied on pre-gen8 313024edb884SFrançois Tigeot * platform. And there is no VCS2 ring on the pre-gen8 313124edb884SFrançois Tigeot * platform. So the semaphore between BCS and VCS2 is 313224edb884SFrançois Tigeot * initialized as INVALID. Gen8 will initialize the 313324edb884SFrançois Tigeot * sema between BCS and VCS2 later. 3134ba55f2f5SFrançois Tigeot */ 31358621f407SFrançois Tigeot engine->semaphore.mbox.wait[RCS] = MI_SEMAPHORE_SYNC_BR; 31368621f407SFrançois Tigeot engine->semaphore.mbox.wait[VCS] = MI_SEMAPHORE_SYNC_BV; 31378621f407SFrançois Tigeot engine->semaphore.mbox.wait[BCS] = MI_SEMAPHORE_SYNC_INVALID; 31388621f407SFrançois Tigeot engine->semaphore.mbox.wait[VECS] = MI_SEMAPHORE_SYNC_BVE; 31398621f407SFrançois Tigeot engine->semaphore.mbox.wait[VCS2] = MI_SEMAPHORE_SYNC_INVALID; 31408621f407SFrançois Tigeot engine->semaphore.mbox.signal[RCS] = GEN6_RBSYNC; 31418621f407SFrançois Tigeot engine->semaphore.mbox.signal[VCS] = GEN6_VBSYNC; 31428621f407SFrançois Tigeot engine->semaphore.mbox.signal[BCS] = GEN6_NOSYNC; 31438621f407SFrançois Tigeot engine->semaphore.mbox.signal[VECS] = GEN6_VEBSYNC; 31448621f407SFrançois Tigeot engine->semaphore.mbox.signal[VCS2] = GEN6_NOSYNC; 314524edb884SFrançois Tigeot } 314624edb884SFrançois Tigeot } 31478621f407SFrançois Tigeot engine->init_hw = init_ring_common; 31485d0b1887SFrançois Tigeot 31498621f407SFrançois Tigeot return intel_init_ring_buffer(dev, engine); 31505d0b1887SFrançois Tigeot } 31515d0b1887SFrançois Tigeot 31525d0b1887SFrançois Tigeot int intel_init_vebox_ring_buffer(struct drm_device *dev) 31535d0b1887SFrançois Tigeot { 3154ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 31558621f407SFrançois Tigeot struct intel_engine_cs *engine = &dev_priv->engine[VECS]; 31565d0b1887SFrançois Tigeot 31578621f407SFrançois Tigeot engine->name = "video enhancement ring"; 31588621f407SFrançois Tigeot engine->id = VECS; 31598621f407SFrançois Tigeot engine->exec_id = I915_EXEC_VEBOX; 31608621f407SFrançois Tigeot engine->hw_id = 3; 31615d0b1887SFrançois Tigeot 31628621f407SFrançois Tigeot engine->mmio_base = VEBOX_RING_BASE; 31638621f407SFrançois Tigeot engine->write_tail = ring_write_tail; 31648621f407SFrançois Tigeot engine->flush = gen6_ring_flush; 31658621f407SFrançois Tigeot engine->add_request = gen6_add_request; 31668621f407SFrançois Tigeot engine->irq_seqno_barrier = gen6_seqno_barrier; 31678621f407SFrançois Tigeot engine->get_seqno = ring_get_seqno; 31688621f407SFrançois Tigeot engine->set_seqno = ring_set_seqno; 31699edbd4a0SFrançois Tigeot 31709edbd4a0SFrançois Tigeot if (INTEL_INFO(dev)->gen >= 8) { 31718621f407SFrançois Tigeot engine->irq_enable_mask = 31729edbd4a0SFrançois Tigeot GT_RENDER_USER_INTERRUPT << GEN8_VECS_IRQ_SHIFT; 31738621f407SFrançois Tigeot engine->irq_get = gen8_ring_get_irq; 31748621f407SFrançois Tigeot engine->irq_put = gen8_ring_put_irq; 31758621f407SFrançois Tigeot engine->dispatch_execbuffer = gen8_ring_dispatch_execbuffer; 317624edb884SFrançois Tigeot if (i915_semaphore_is_enabled(dev)) { 31778621f407SFrançois Tigeot engine->semaphore.sync_to = gen8_ring_sync; 31788621f407SFrançois Tigeot engine->semaphore.signal = gen8_xcs_signal; 31798621f407SFrançois Tigeot GEN8_RING_SEMAPHORE_INIT(engine); 318024edb884SFrançois Tigeot } 31819edbd4a0SFrançois Tigeot } else { 31828621f407SFrançois Tigeot engine->irq_enable_mask = PM_VEBOX_USER_INTERRUPT; 31838621f407SFrançois Tigeot engine->irq_get = hsw_vebox_get_irq; 31848621f407SFrançois Tigeot engine->irq_put = hsw_vebox_put_irq; 31858621f407SFrançois Tigeot engine->dispatch_execbuffer = gen6_ring_dispatch_execbuffer; 318624edb884SFrançois Tigeot if (i915_semaphore_is_enabled(dev)) { 31878621f407SFrançois Tigeot engine->semaphore.sync_to = gen6_ring_sync; 31888621f407SFrançois Tigeot engine->semaphore.signal = gen6_signal; 31898621f407SFrançois Tigeot engine->semaphore.mbox.wait[RCS] = MI_SEMAPHORE_SYNC_VER; 31908621f407SFrançois Tigeot engine->semaphore.mbox.wait[VCS] = MI_SEMAPHORE_SYNC_VEV; 31918621f407SFrançois Tigeot engine->semaphore.mbox.wait[BCS] = MI_SEMAPHORE_SYNC_VEB; 31928621f407SFrançois Tigeot engine->semaphore.mbox.wait[VECS] = MI_SEMAPHORE_SYNC_INVALID; 31938621f407SFrançois Tigeot engine->semaphore.mbox.wait[VCS2] = MI_SEMAPHORE_SYNC_INVALID; 31948621f407SFrançois Tigeot engine->semaphore.mbox.signal[RCS] = GEN6_RVESYNC; 31958621f407SFrançois Tigeot engine->semaphore.mbox.signal[VCS] = GEN6_VVESYNC; 31968621f407SFrançois Tigeot engine->semaphore.mbox.signal[BCS] = GEN6_BVESYNC; 31978621f407SFrançois Tigeot engine->semaphore.mbox.signal[VECS] = GEN6_NOSYNC; 31988621f407SFrançois Tigeot engine->semaphore.mbox.signal[VCS2] = GEN6_NOSYNC; 319924edb884SFrançois Tigeot } 320024edb884SFrançois Tigeot } 32018621f407SFrançois Tigeot engine->init_hw = init_ring_common; 3202e3adcf8fSFrançois Tigeot 32038621f407SFrançois Tigeot return intel_init_ring_buffer(dev, engine); 3204e3adcf8fSFrançois Tigeot } 3205b030f26bSFrançois Tigeot 3206b030f26bSFrançois Tigeot int 3207a05eeebfSFrançois Tigeot intel_ring_flush_all_caches(struct drm_i915_gem_request *req) 3208b030f26bSFrançois Tigeot { 32098621f407SFrançois Tigeot struct intel_engine_cs *engine = req->engine; 3210b030f26bSFrançois Tigeot int ret; 3211b030f26bSFrançois Tigeot 32128621f407SFrançois Tigeot if (!engine->gpu_caches_dirty) 3213b030f26bSFrançois Tigeot return 0; 3214b030f26bSFrançois Tigeot 32158621f407SFrançois Tigeot ret = engine->flush(req, 0, I915_GEM_GPU_DOMAINS); 3216b030f26bSFrançois Tigeot if (ret) 3217b030f26bSFrançois Tigeot return ret; 3218b030f26bSFrançois Tigeot 3219a05eeebfSFrançois Tigeot trace_i915_gem_ring_flush(req, 0, I915_GEM_GPU_DOMAINS); 3220a2fdbec6SFrançois Tigeot 32218621f407SFrançois Tigeot engine->gpu_caches_dirty = false; 3222b030f26bSFrançois Tigeot return 0; 3223b030f26bSFrançois Tigeot } 3224b030f26bSFrançois Tigeot 3225b030f26bSFrançois Tigeot int 3226a05eeebfSFrançois Tigeot intel_ring_invalidate_all_caches(struct drm_i915_gem_request *req) 3227b030f26bSFrançois Tigeot { 32288621f407SFrançois Tigeot struct intel_engine_cs *engine = req->engine; 3229b030f26bSFrançois Tigeot uint32_t flush_domains; 3230b030f26bSFrançois Tigeot int ret; 3231b030f26bSFrançois Tigeot 3232b030f26bSFrançois Tigeot flush_domains = 0; 32338621f407SFrançois Tigeot if (engine->gpu_caches_dirty) 3234b030f26bSFrançois Tigeot flush_domains = I915_GEM_GPU_DOMAINS; 3235b030f26bSFrançois Tigeot 32368621f407SFrançois Tigeot ret = engine->flush(req, I915_GEM_GPU_DOMAINS, flush_domains); 3237b030f26bSFrançois Tigeot if (ret) 3238b030f26bSFrançois Tigeot return ret; 3239b030f26bSFrançois Tigeot 3240a05eeebfSFrançois Tigeot trace_i915_gem_ring_flush(req, I915_GEM_GPU_DOMAINS, flush_domains); 3241a2fdbec6SFrançois Tigeot 32428621f407SFrançois Tigeot engine->gpu_caches_dirty = false; 3243b030f26bSFrançois Tigeot return 0; 3244b030f26bSFrançois Tigeot } 3245ba55f2f5SFrançois Tigeot 3246ba55f2f5SFrançois Tigeot void 32478621f407SFrançois Tigeot intel_stop_engine(struct intel_engine_cs *engine) 3248ba55f2f5SFrançois Tigeot { 3249ba55f2f5SFrançois Tigeot int ret; 3250ba55f2f5SFrançois Tigeot 32518621f407SFrançois Tigeot if (!intel_engine_initialized(engine)) 3252ba55f2f5SFrançois Tigeot return; 3253ba55f2f5SFrançois Tigeot 32548621f407SFrançois Tigeot ret = intel_engine_idle(engine); 32558621f407SFrançois Tigeot if (ret) 3256ba55f2f5SFrançois Tigeot DRM_ERROR("failed to quiesce %s whilst cleaning up: %d\n", 32578621f407SFrançois Tigeot engine->name, ret); 3258ba55f2f5SFrançois Tigeot 32598621f407SFrançois Tigeot stop_ring(engine); 3260ba55f2f5SFrançois Tigeot } 3261