1e3adcf8fSFrançois Tigeot /* 2e3adcf8fSFrançois Tigeot * Copyright © 2008-2010 Intel Corporation 3e3adcf8fSFrançois Tigeot * 4e3adcf8fSFrançois Tigeot * Permission is hereby granted, free of charge, to any person obtaining a 5e3adcf8fSFrançois Tigeot * copy of this software and associated documentation files (the "Software"), 6e3adcf8fSFrançois Tigeot * to deal in the Software without restriction, including without limitation 7e3adcf8fSFrançois Tigeot * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8e3adcf8fSFrançois Tigeot * and/or sell copies of the Software, and to permit persons to whom the 9e3adcf8fSFrançois Tigeot * Software is furnished to do so, subject to the following conditions: 10e3adcf8fSFrançois Tigeot * 11e3adcf8fSFrançois Tigeot * The above copyright notice and this permission notice (including the next 12e3adcf8fSFrançois Tigeot * paragraph) shall be included in all copies or substantial portions of the 13e3adcf8fSFrançois Tigeot * Software. 14e3adcf8fSFrançois Tigeot * 15e3adcf8fSFrançois Tigeot * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16e3adcf8fSFrançois Tigeot * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17e3adcf8fSFrançois Tigeot * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18e3adcf8fSFrançois Tigeot * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19e3adcf8fSFrançois Tigeot * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20e3adcf8fSFrançois Tigeot * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21e3adcf8fSFrançois Tigeot * IN THE SOFTWARE. 22e3adcf8fSFrançois Tigeot * 23e3adcf8fSFrançois Tigeot * Authors: 24e3adcf8fSFrançois Tigeot * Eric Anholt <eric@anholt.net> 25e3adcf8fSFrançois Tigeot * Zou Nan hai <nanhai.zou@intel.com> 26e3adcf8fSFrançois Tigeot * Xiang Hai hao<haihao.xiang@intel.com> 27e3adcf8fSFrançois Tigeot * 28e3adcf8fSFrançois Tigeot */ 29e3adcf8fSFrançois Tigeot 30aee94f86SFrançois Tigeot #include <linux/log2.h> 3118e26a6dSFrançois Tigeot #include <drm/drmP.h> 32e3adcf8fSFrançois Tigeot #include "i915_drv.h" 33a2fdbec6SFrançois Tigeot #include <drm/i915_drm.h> 34a2fdbec6SFrançois Tigeot #include "i915_trace.h" 35e3adcf8fSFrançois Tigeot #include "intel_drv.h" 36e3adcf8fSFrançois Tigeot 371487f786SFrançois Tigeot /* Rough estimate of the typical request size, performing a flush, 381487f786SFrançois Tigeot * set-context and then emitting the batch. 391487f786SFrançois Tigeot */ 401487f786SFrançois Tigeot #define LEGACY_REQUEST_SIZE 200 411487f786SFrançois Tigeot 421b13d190SFrançois Tigeot int __intel_ring_space(int head, int tail, int size) 43e3adcf8fSFrançois Tigeot { 442c9916cdSFrançois Tigeot int space = head - tail; 452c9916cdSFrançois Tigeot if (space <= 0) 46ba55f2f5SFrançois Tigeot space += size; 472c9916cdSFrançois Tigeot return space - I915_RING_FREE_SPACE; 482c9916cdSFrançois Tigeot } 492c9916cdSFrançois Tigeot 502c9916cdSFrançois Tigeot void intel_ring_update_space(struct intel_ringbuffer *ringbuf) 512c9916cdSFrançois Tigeot { 522c9916cdSFrançois Tigeot if (ringbuf->last_retired_head != -1) { 532c9916cdSFrançois Tigeot ringbuf->head = ringbuf->last_retired_head; 542c9916cdSFrançois Tigeot ringbuf->last_retired_head = -1; 552c9916cdSFrançois Tigeot } 562c9916cdSFrançois Tigeot 572c9916cdSFrançois Tigeot ringbuf->space = __intel_ring_space(ringbuf->head & HEAD_ADDR, 582c9916cdSFrançois Tigeot ringbuf->tail, ringbuf->size); 59e3adcf8fSFrançois Tigeot } 60e3adcf8fSFrançois Tigeot 618621f407SFrançois Tigeot static void __intel_ring_advance(struct intel_engine_cs *engine) 629edbd4a0SFrançois Tigeot { 638621f407SFrançois Tigeot struct intel_ringbuffer *ringbuf = engine->buffer; 64ba55f2f5SFrançois Tigeot ringbuf->tail &= ringbuf->size - 1; 658621f407SFrançois Tigeot engine->write_tail(engine, ringbuf->tail); 669edbd4a0SFrançois Tigeot } 679edbd4a0SFrançois Tigeot 68e3adcf8fSFrançois Tigeot static int 69a05eeebfSFrançois Tigeot gen2_render_ring_flush(struct drm_i915_gem_request *req, 70686a02f1SFrançois Tigeot u32 invalidate_domains, 71686a02f1SFrançois Tigeot u32 flush_domains) 72686a02f1SFrançois Tigeot { 738621f407SFrançois Tigeot struct intel_engine_cs *engine = req->engine; 74686a02f1SFrançois Tigeot u32 cmd; 75686a02f1SFrançois Tigeot int ret; 76686a02f1SFrançois Tigeot 77686a02f1SFrançois Tigeot cmd = MI_FLUSH; 78686a02f1SFrançois Tigeot if (((invalidate_domains|flush_domains) & I915_GEM_DOMAIN_RENDER) == 0) 79686a02f1SFrançois Tigeot cmd |= MI_NO_WRITE_FLUSH; 80686a02f1SFrançois Tigeot 81686a02f1SFrançois Tigeot if (invalidate_domains & I915_GEM_DOMAIN_SAMPLER) 82686a02f1SFrançois Tigeot cmd |= MI_READ_FLUSH; 83686a02f1SFrançois Tigeot 84a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 2); 85686a02f1SFrançois Tigeot if (ret) 86686a02f1SFrançois Tigeot return ret; 87686a02f1SFrançois Tigeot 888621f407SFrançois Tigeot intel_ring_emit(engine, cmd); 898621f407SFrançois Tigeot intel_ring_emit(engine, MI_NOOP); 908621f407SFrançois Tigeot intel_ring_advance(engine); 91686a02f1SFrançois Tigeot 92686a02f1SFrançois Tigeot return 0; 93686a02f1SFrançois Tigeot } 94686a02f1SFrançois Tigeot 95686a02f1SFrançois Tigeot static int 96a05eeebfSFrançois Tigeot gen4_render_ring_flush(struct drm_i915_gem_request *req, 97686a02f1SFrançois Tigeot u32 invalidate_domains, 98686a02f1SFrançois Tigeot u32 flush_domains) 99e3adcf8fSFrançois Tigeot { 1008621f407SFrançois Tigeot struct intel_engine_cs *engine = req->engine; 101686a02f1SFrançois Tigeot u32 cmd; 102e3adcf8fSFrançois Tigeot int ret; 103e3adcf8fSFrançois Tigeot 104e3adcf8fSFrançois Tigeot /* 105e3adcf8fSFrançois Tigeot * read/write caches: 106e3adcf8fSFrançois Tigeot * 107e3adcf8fSFrançois Tigeot * I915_GEM_DOMAIN_RENDER is always invalidated, but is 108e3adcf8fSFrançois Tigeot * only flushed if MI_NO_WRITE_FLUSH is unset. On 965, it is 109e3adcf8fSFrançois Tigeot * also flushed at 2d versus 3d pipeline switches. 110e3adcf8fSFrançois Tigeot * 111e3adcf8fSFrançois Tigeot * read-only caches: 112e3adcf8fSFrançois Tigeot * 113e3adcf8fSFrançois Tigeot * I915_GEM_DOMAIN_SAMPLER is flushed on pre-965 if 114e3adcf8fSFrançois Tigeot * MI_READ_FLUSH is set, and is always flushed on 965. 115e3adcf8fSFrançois Tigeot * 116e3adcf8fSFrançois Tigeot * I915_GEM_DOMAIN_COMMAND may not exist? 117e3adcf8fSFrançois Tigeot * 118e3adcf8fSFrançois Tigeot * I915_GEM_DOMAIN_INSTRUCTION, which exists on 965, is 119e3adcf8fSFrançois Tigeot * invalidated when MI_EXE_FLUSH is set. 120e3adcf8fSFrançois Tigeot * 121e3adcf8fSFrançois Tigeot * I915_GEM_DOMAIN_VERTEX, which exists on 965, is 122e3adcf8fSFrançois Tigeot * invalidated with every MI_FLUSH. 123e3adcf8fSFrançois Tigeot * 124e3adcf8fSFrançois Tigeot * TLBs: 125e3adcf8fSFrançois Tigeot * 126e3adcf8fSFrançois Tigeot * On 965, TLBs associated with I915_GEM_DOMAIN_COMMAND 127e3adcf8fSFrançois Tigeot * and I915_GEM_DOMAIN_CPU in are invalidated at PTE write and 128e3adcf8fSFrançois Tigeot * I915_GEM_DOMAIN_RENDER and I915_GEM_DOMAIN_SAMPLER 129e3adcf8fSFrançois Tigeot * are flushed at any MI_FLUSH. 130e3adcf8fSFrançois Tigeot */ 131e3adcf8fSFrançois Tigeot 132e3adcf8fSFrançois Tigeot cmd = MI_FLUSH | MI_NO_WRITE_FLUSH; 133686a02f1SFrançois Tigeot if ((invalidate_domains|flush_domains) & I915_GEM_DOMAIN_RENDER) 134e3adcf8fSFrançois Tigeot cmd &= ~MI_NO_WRITE_FLUSH; 135e3adcf8fSFrançois Tigeot if (invalidate_domains & I915_GEM_DOMAIN_INSTRUCTION) 136e3adcf8fSFrançois Tigeot cmd |= MI_EXE_FLUSH; 137e3adcf8fSFrançois Tigeot 138e3adcf8fSFrançois Tigeot if (invalidate_domains & I915_GEM_DOMAIN_COMMAND && 1391487f786SFrançois Tigeot (IS_G4X(req->i915) || IS_GEN5(req->i915))) 140e3adcf8fSFrançois Tigeot cmd |= MI_INVALIDATE_ISP; 141e3adcf8fSFrançois Tigeot 142a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 2); 143e3adcf8fSFrançois Tigeot if (ret) 144e3adcf8fSFrançois Tigeot return ret; 145e3adcf8fSFrançois Tigeot 1468621f407SFrançois Tigeot intel_ring_emit(engine, cmd); 1478621f407SFrançois Tigeot intel_ring_emit(engine, MI_NOOP); 1488621f407SFrançois Tigeot intel_ring_advance(engine); 149e3adcf8fSFrançois Tigeot 150e3adcf8fSFrançois Tigeot return 0; 151e3adcf8fSFrançois Tigeot } 152e3adcf8fSFrançois Tigeot 153e3adcf8fSFrançois Tigeot /** 154e3adcf8fSFrançois Tigeot * Emits a PIPE_CONTROL with a non-zero post-sync operation, for 155e3adcf8fSFrançois Tigeot * implementing two workarounds on gen6. From section 1.4.7.1 156e3adcf8fSFrançois Tigeot * "PIPE_CONTROL" of the Sandy Bridge PRM volume 2 part 1: 157e3adcf8fSFrançois Tigeot * 158e3adcf8fSFrançois Tigeot * [DevSNB-C+{W/A}] Before any depth stall flush (including those 159e3adcf8fSFrançois Tigeot * produced by non-pipelined state commands), software needs to first 160e3adcf8fSFrançois Tigeot * send a PIPE_CONTROL with no bits set except Post-Sync Operation != 161e3adcf8fSFrançois Tigeot * 0. 162e3adcf8fSFrançois Tigeot * 163e3adcf8fSFrançois Tigeot * [Dev-SNB{W/A}]: Before a PIPE_CONTROL with Write Cache Flush Enable 164e3adcf8fSFrançois Tigeot * =1, a PIPE_CONTROL with any non-zero post-sync-op is required. 165e3adcf8fSFrançois Tigeot * 166e3adcf8fSFrançois Tigeot * And the workaround for these two requires this workaround first: 167e3adcf8fSFrançois Tigeot * 168e3adcf8fSFrançois Tigeot * [Dev-SNB{W/A}]: Pipe-control with CS-stall bit set must be sent 169e3adcf8fSFrançois Tigeot * BEFORE the pipe-control with a post-sync op and no write-cache 170e3adcf8fSFrançois Tigeot * flushes. 171e3adcf8fSFrançois Tigeot * 172e3adcf8fSFrançois Tigeot * And this last workaround is tricky because of the requirements on 173e3adcf8fSFrançois Tigeot * that bit. From section 1.4.7.2.3 "Stall" of the Sandy Bridge PRM 174e3adcf8fSFrançois Tigeot * volume 2 part 1: 175e3adcf8fSFrançois Tigeot * 176e3adcf8fSFrançois Tigeot * "1 of the following must also be set: 177e3adcf8fSFrançois Tigeot * - Render Target Cache Flush Enable ([12] of DW1) 178e3adcf8fSFrançois Tigeot * - Depth Cache Flush Enable ([0] of DW1) 179e3adcf8fSFrançois Tigeot * - Stall at Pixel Scoreboard ([1] of DW1) 180e3adcf8fSFrançois Tigeot * - Depth Stall ([13] of DW1) 181e3adcf8fSFrançois Tigeot * - Post-Sync Operation ([13] of DW1) 182e3adcf8fSFrançois Tigeot * - Notify Enable ([8] of DW1)" 183e3adcf8fSFrançois Tigeot * 184e3adcf8fSFrançois Tigeot * The cache flushes require the workaround flush that triggered this 185e3adcf8fSFrançois Tigeot * one, so we can't use it. Depth stall would trigger the same. 186e3adcf8fSFrançois Tigeot * Post-sync nonzero is what triggered this second workaround, so we 187e3adcf8fSFrançois Tigeot * can't use that one either. Notify enable is IRQs, which aren't 188e3adcf8fSFrançois Tigeot * really our business. That leaves only stall at scoreboard. 189e3adcf8fSFrançois Tigeot */ 190e3adcf8fSFrançois Tigeot static int 191a05eeebfSFrançois Tigeot intel_emit_post_sync_nonzero_flush(struct drm_i915_gem_request *req) 192e3adcf8fSFrançois Tigeot { 1938621f407SFrançois Tigeot struct intel_engine_cs *engine = req->engine; 1948621f407SFrançois Tigeot u32 scratch_addr = engine->scratch.gtt_offset + 2 * CACHELINE_BYTES; 195e3adcf8fSFrançois Tigeot int ret; 196e3adcf8fSFrançois Tigeot 197a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 6); 198e3adcf8fSFrançois Tigeot if (ret) 199e3adcf8fSFrançois Tigeot return ret; 200e3adcf8fSFrançois Tigeot 2018621f407SFrançois Tigeot intel_ring_emit(engine, GFX_OP_PIPE_CONTROL(5)); 2028621f407SFrançois Tigeot intel_ring_emit(engine, PIPE_CONTROL_CS_STALL | 203e3adcf8fSFrançois Tigeot PIPE_CONTROL_STALL_AT_SCOREBOARD); 2048621f407SFrançois Tigeot intel_ring_emit(engine, scratch_addr | PIPE_CONTROL_GLOBAL_GTT); /* address */ 2058621f407SFrançois Tigeot intel_ring_emit(engine, 0); /* low dword */ 2068621f407SFrançois Tigeot intel_ring_emit(engine, 0); /* high dword */ 2078621f407SFrançois Tigeot intel_ring_emit(engine, MI_NOOP); 2088621f407SFrançois Tigeot intel_ring_advance(engine); 209e3adcf8fSFrançois Tigeot 210a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 6); 211e3adcf8fSFrançois Tigeot if (ret) 212e3adcf8fSFrançois Tigeot return ret; 213e3adcf8fSFrançois Tigeot 2148621f407SFrançois Tigeot intel_ring_emit(engine, GFX_OP_PIPE_CONTROL(5)); 2158621f407SFrançois Tigeot intel_ring_emit(engine, PIPE_CONTROL_QW_WRITE); 2168621f407SFrançois Tigeot intel_ring_emit(engine, scratch_addr | PIPE_CONTROL_GLOBAL_GTT); /* address */ 2178621f407SFrançois Tigeot intel_ring_emit(engine, 0); 2188621f407SFrançois Tigeot intel_ring_emit(engine, 0); 2198621f407SFrançois Tigeot intel_ring_emit(engine, MI_NOOP); 2208621f407SFrançois Tigeot intel_ring_advance(engine); 221e3adcf8fSFrançois Tigeot 222e3adcf8fSFrançois Tigeot return 0; 223e3adcf8fSFrançois Tigeot } 224e3adcf8fSFrançois Tigeot 225e3adcf8fSFrançois Tigeot static int 226a05eeebfSFrançois Tigeot gen6_render_ring_flush(struct drm_i915_gem_request *req, 227e3adcf8fSFrançois Tigeot u32 invalidate_domains, u32 flush_domains) 228e3adcf8fSFrançois Tigeot { 2298621f407SFrançois Tigeot struct intel_engine_cs *engine = req->engine; 230e3adcf8fSFrançois Tigeot u32 flags = 0; 2318621f407SFrançois Tigeot u32 scratch_addr = engine->scratch.gtt_offset + 2 * CACHELINE_BYTES; 232e3adcf8fSFrançois Tigeot int ret; 233e3adcf8fSFrançois Tigeot 234e3adcf8fSFrançois Tigeot /* Force SNB workarounds for PIPE_CONTROL flushes */ 235a05eeebfSFrançois Tigeot ret = intel_emit_post_sync_nonzero_flush(req); 236686a02f1SFrançois Tigeot if (ret) 237686a02f1SFrançois Tigeot return ret; 238e3adcf8fSFrançois Tigeot 239e3adcf8fSFrançois Tigeot /* Just flush everything. Experiments have shown that reducing the 240e3adcf8fSFrançois Tigeot * number of bits based on the write domains has little performance 241e3adcf8fSFrançois Tigeot * impact. 242e3adcf8fSFrançois Tigeot */ 243b5c29a34SFrançois Tigeot if (flush_domains) { 244e3adcf8fSFrançois Tigeot flags |= PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH; 245b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_DEPTH_CACHE_FLUSH; 246b5c29a34SFrançois Tigeot /* 247b5c29a34SFrançois Tigeot * Ensure that any following seqno writes only happen 248b5c29a34SFrançois Tigeot * when the render cache is indeed flushed. 249b5c29a34SFrançois Tigeot */ 250b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_CS_STALL; 251b5c29a34SFrançois Tigeot } 252b5c29a34SFrançois Tigeot if (invalidate_domains) { 253686a02f1SFrançois Tigeot flags |= PIPE_CONTROL_TLB_INVALIDATE; 254e3adcf8fSFrançois Tigeot flags |= PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE; 255e3adcf8fSFrançois Tigeot flags |= PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE; 256e3adcf8fSFrançois Tigeot flags |= PIPE_CONTROL_VF_CACHE_INVALIDATE; 257e3adcf8fSFrançois Tigeot flags |= PIPE_CONTROL_CONST_CACHE_INVALIDATE; 258e3adcf8fSFrançois Tigeot flags |= PIPE_CONTROL_STATE_CACHE_INVALIDATE; 259686a02f1SFrançois Tigeot /* 260b5c29a34SFrançois Tigeot * TLB invalidate requires a post-sync write. 261686a02f1SFrançois Tigeot */ 262b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_QW_WRITE | PIPE_CONTROL_CS_STALL; 263b5c29a34SFrançois Tigeot } 264e3adcf8fSFrançois Tigeot 265a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 4); 266e3adcf8fSFrançois Tigeot if (ret) 267e3adcf8fSFrançois Tigeot return ret; 268e3adcf8fSFrançois Tigeot 2698621f407SFrançois Tigeot intel_ring_emit(engine, GFX_OP_PIPE_CONTROL(4)); 2708621f407SFrançois Tigeot intel_ring_emit(engine, flags); 2718621f407SFrançois Tigeot intel_ring_emit(engine, scratch_addr | PIPE_CONTROL_GLOBAL_GTT); 2728621f407SFrançois Tigeot intel_ring_emit(engine, 0); 2738621f407SFrançois Tigeot intel_ring_advance(engine); 274b5c29a34SFrançois Tigeot 275b5c29a34SFrançois Tigeot return 0; 276b5c29a34SFrançois Tigeot } 277b5c29a34SFrançois Tigeot 278b5c29a34SFrançois Tigeot static int 279a05eeebfSFrançois Tigeot gen7_render_ring_cs_stall_wa(struct drm_i915_gem_request *req) 280b5c29a34SFrançois Tigeot { 2818621f407SFrançois Tigeot struct intel_engine_cs *engine = req->engine; 282b5c29a34SFrançois Tigeot int ret; 283b5c29a34SFrançois Tigeot 284a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 4); 285b5c29a34SFrançois Tigeot if (ret) 286b5c29a34SFrançois Tigeot return ret; 287b5c29a34SFrançois Tigeot 2888621f407SFrançois Tigeot intel_ring_emit(engine, GFX_OP_PIPE_CONTROL(4)); 2898621f407SFrançois Tigeot intel_ring_emit(engine, PIPE_CONTROL_CS_STALL | 290b5c29a34SFrançois Tigeot PIPE_CONTROL_STALL_AT_SCOREBOARD); 2918621f407SFrançois Tigeot intel_ring_emit(engine, 0); 2928621f407SFrançois Tigeot intel_ring_emit(engine, 0); 2938621f407SFrançois Tigeot intel_ring_advance(engine); 294b5c29a34SFrançois Tigeot 295b5c29a34SFrançois Tigeot return 0; 296b5c29a34SFrançois Tigeot } 297b5c29a34SFrançois Tigeot 298b5c29a34SFrançois Tigeot static int 299a05eeebfSFrançois Tigeot gen7_render_ring_flush(struct drm_i915_gem_request *req, 300b5c29a34SFrançois Tigeot u32 invalidate_domains, u32 flush_domains) 301b5c29a34SFrançois Tigeot { 3028621f407SFrançois Tigeot struct intel_engine_cs *engine = req->engine; 303b5c29a34SFrançois Tigeot u32 flags = 0; 3048621f407SFrançois Tigeot u32 scratch_addr = engine->scratch.gtt_offset + 2 * CACHELINE_BYTES; 305b5c29a34SFrançois Tigeot int ret; 306b5c29a34SFrançois Tigeot 307b5c29a34SFrançois Tigeot /* 308b5c29a34SFrançois Tigeot * Ensure that any following seqno writes only happen when the render 309b5c29a34SFrançois Tigeot * cache is indeed flushed. 310b5c29a34SFrançois Tigeot * 311b5c29a34SFrançois Tigeot * Workaround: 4th PIPE_CONTROL command (except the ones with only 312b5c29a34SFrançois Tigeot * read-cache invalidate bits set) must have the CS_STALL bit set. We 313b5c29a34SFrançois Tigeot * don't try to be clever and just set it unconditionally. 314b5c29a34SFrançois Tigeot */ 315b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_CS_STALL; 316b5c29a34SFrançois Tigeot 317b5c29a34SFrançois Tigeot /* Just flush everything. Experiments have shown that reducing the 318b5c29a34SFrançois Tigeot * number of bits based on the write domains has little performance 319b5c29a34SFrançois Tigeot * impact. 320b5c29a34SFrançois Tigeot */ 321b5c29a34SFrançois Tigeot if (flush_domains) { 322b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH; 323b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_DEPTH_CACHE_FLUSH; 324aee94f86SFrançois Tigeot flags |= PIPE_CONTROL_DC_FLUSH_ENABLE; 325b49c8cf9SFrançois Tigeot flags |= PIPE_CONTROL_FLUSH_ENABLE; 326b5c29a34SFrançois Tigeot } 327b5c29a34SFrançois Tigeot if (invalidate_domains) { 328b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_TLB_INVALIDATE; 329b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE; 330b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE; 331b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_VF_CACHE_INVALIDATE; 332b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_CONST_CACHE_INVALIDATE; 333b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_STATE_CACHE_INVALIDATE; 3342c9916cdSFrançois Tigeot flags |= PIPE_CONTROL_MEDIA_STATE_CLEAR; 335b5c29a34SFrançois Tigeot /* 336b5c29a34SFrançois Tigeot * TLB invalidate requires a post-sync write. 337b5c29a34SFrançois Tigeot */ 338b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_QW_WRITE; 339a2fdbec6SFrançois Tigeot flags |= PIPE_CONTROL_GLOBAL_GTT_IVB; 340b5c29a34SFrançois Tigeot 3410dbf0ea8SMatthew Dillon flags |= PIPE_CONTROL_STALL_AT_SCOREBOARD; 3420dbf0ea8SMatthew Dillon 343b5c29a34SFrançois Tigeot /* Workaround: we must issue a pipe_control with CS-stall bit 344b5c29a34SFrançois Tigeot * set before a pipe_control command that has the state cache 345b5c29a34SFrançois Tigeot * invalidate bit set. */ 346a05eeebfSFrançois Tigeot gen7_render_ring_cs_stall_wa(req); 347b5c29a34SFrançois Tigeot } 348b5c29a34SFrançois Tigeot 349a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 4); 350b5c29a34SFrançois Tigeot if (ret) 351b5c29a34SFrançois Tigeot return ret; 352b5c29a34SFrançois Tigeot 3538621f407SFrançois Tigeot intel_ring_emit(engine, GFX_OP_PIPE_CONTROL(4)); 3548621f407SFrançois Tigeot intel_ring_emit(engine, flags); 3558621f407SFrançois Tigeot intel_ring_emit(engine, scratch_addr); 3568621f407SFrançois Tigeot intel_ring_emit(engine, 0); 3578621f407SFrançois Tigeot intel_ring_advance(engine); 358e3adcf8fSFrançois Tigeot 359e3adcf8fSFrançois Tigeot return 0; 360e3adcf8fSFrançois Tigeot } 361e3adcf8fSFrançois Tigeot 3629edbd4a0SFrançois Tigeot static int 363a05eeebfSFrançois Tigeot gen8_emit_pipe_control(struct drm_i915_gem_request *req, 36424edb884SFrançois Tigeot u32 flags, u32 scratch_addr) 36524edb884SFrançois Tigeot { 3668621f407SFrançois Tigeot struct intel_engine_cs *engine = req->engine; 36724edb884SFrançois Tigeot int ret; 36824edb884SFrançois Tigeot 369a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 6); 37024edb884SFrançois Tigeot if (ret) 37124edb884SFrançois Tigeot return ret; 37224edb884SFrançois Tigeot 3738621f407SFrançois Tigeot intel_ring_emit(engine, GFX_OP_PIPE_CONTROL(6)); 3748621f407SFrançois Tigeot intel_ring_emit(engine, flags); 3758621f407SFrançois Tigeot intel_ring_emit(engine, scratch_addr); 3768621f407SFrançois Tigeot intel_ring_emit(engine, 0); 3778621f407SFrançois Tigeot intel_ring_emit(engine, 0); 3788621f407SFrançois Tigeot intel_ring_emit(engine, 0); 3798621f407SFrançois Tigeot intel_ring_advance(engine); 38024edb884SFrançois Tigeot 38124edb884SFrançois Tigeot return 0; 38224edb884SFrançois Tigeot } 38324edb884SFrançois Tigeot 38424edb884SFrançois Tigeot static int 385a05eeebfSFrançois Tigeot gen8_render_ring_flush(struct drm_i915_gem_request *req, 3869edbd4a0SFrançois Tigeot u32 invalidate_domains, u32 flush_domains) 3879edbd4a0SFrançois Tigeot { 3889edbd4a0SFrançois Tigeot u32 flags = 0; 3898621f407SFrançois Tigeot u32 scratch_addr = req->engine->scratch.gtt_offset + 2 * CACHELINE_BYTES; 3909edbd4a0SFrançois Tigeot int ret; 3919edbd4a0SFrançois Tigeot 3929edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_CS_STALL; 3939edbd4a0SFrançois Tigeot 3949edbd4a0SFrançois Tigeot if (flush_domains) { 3959edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH; 3969edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_DEPTH_CACHE_FLUSH; 397aee94f86SFrançois Tigeot flags |= PIPE_CONTROL_DC_FLUSH_ENABLE; 398b49c8cf9SFrançois Tigeot flags |= PIPE_CONTROL_FLUSH_ENABLE; 3999edbd4a0SFrançois Tigeot } 4009edbd4a0SFrançois Tigeot if (invalidate_domains) { 4019edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_TLB_INVALIDATE; 4029edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE; 4039edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE; 4049edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_VF_CACHE_INVALIDATE; 4059edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_CONST_CACHE_INVALIDATE; 4069edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_STATE_CACHE_INVALIDATE; 4079edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_QW_WRITE; 4089edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_GLOBAL_GTT_IVB; 4099edbd4a0SFrançois Tigeot 41024edb884SFrançois Tigeot /* WaCsStallBeforeStateCacheInvalidate:bdw,chv */ 411a05eeebfSFrançois Tigeot ret = gen8_emit_pipe_control(req, 41224edb884SFrançois Tigeot PIPE_CONTROL_CS_STALL | 41324edb884SFrançois Tigeot PIPE_CONTROL_STALL_AT_SCOREBOARD, 41424edb884SFrançois Tigeot 0); 4159edbd4a0SFrançois Tigeot if (ret) 4169edbd4a0SFrançois Tigeot return ret; 41724edb884SFrançois Tigeot } 4189edbd4a0SFrançois Tigeot 419a05eeebfSFrançois Tigeot return gen8_emit_pipe_control(req, flags, scratch_addr); 4209edbd4a0SFrançois Tigeot } 4219edbd4a0SFrançois Tigeot 4228621f407SFrançois Tigeot static void ring_write_tail(struct intel_engine_cs *engine, 423b5c29a34SFrançois Tigeot u32 value) 424e3adcf8fSFrançois Tigeot { 4251487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 4268621f407SFrançois Tigeot I915_WRITE_TAIL(engine, value); 427e3adcf8fSFrançois Tigeot } 428e3adcf8fSFrançois Tigeot 4298621f407SFrançois Tigeot u64 intel_ring_get_active_head(struct intel_engine_cs *engine) 430e3adcf8fSFrançois Tigeot { 4311487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 432ba55f2f5SFrançois Tigeot u64 acthd; 433e3adcf8fSFrançois Tigeot 4341487f786SFrançois Tigeot if (INTEL_GEN(dev_priv) >= 8) 4358621f407SFrançois Tigeot acthd = I915_READ64_2x32(RING_ACTHD(engine->mmio_base), 4368621f407SFrançois Tigeot RING_ACTHD_UDW(engine->mmio_base)); 4371487f786SFrançois Tigeot else if (INTEL_GEN(dev_priv) >= 4) 4388621f407SFrançois Tigeot acthd = I915_READ(RING_ACTHD(engine->mmio_base)); 439ba55f2f5SFrançois Tigeot else 440ba55f2f5SFrançois Tigeot acthd = I915_READ(ACTHD); 441ba55f2f5SFrançois Tigeot 442ba55f2f5SFrançois Tigeot return acthd; 443e3adcf8fSFrançois Tigeot } 444e3adcf8fSFrançois Tigeot 4458621f407SFrançois Tigeot static void ring_setup_phys_status_page(struct intel_engine_cs *engine) 4465d0b1887SFrançois Tigeot { 4471487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 4485d0b1887SFrançois Tigeot u32 addr; 4495d0b1887SFrançois Tigeot 4505d0b1887SFrançois Tigeot addr = dev_priv->status_page_dmah->busaddr; 4511487f786SFrançois Tigeot if (INTEL_GEN(dev_priv) >= 4) 4525d0b1887SFrançois Tigeot addr |= (dev_priv->status_page_dmah->busaddr >> 28) & 0xf0; 4535d0b1887SFrançois Tigeot I915_WRITE(HWS_PGA, addr); 4545d0b1887SFrançois Tigeot } 4555d0b1887SFrançois Tigeot 4568621f407SFrançois Tigeot static void intel_ring_setup_status_page(struct intel_engine_cs *engine) 457477eb7f9SFrançois Tigeot { 4581487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 459aee94f86SFrançois Tigeot i915_reg_t mmio; 460477eb7f9SFrançois Tigeot 461477eb7f9SFrançois Tigeot /* The ring status page addresses are no longer next to the rest of 462477eb7f9SFrançois Tigeot * the ring registers as of gen7. 463477eb7f9SFrançois Tigeot */ 4641487f786SFrançois Tigeot if (IS_GEN7(dev_priv)) { 4658621f407SFrançois Tigeot switch (engine->id) { 466477eb7f9SFrançois Tigeot case RCS: 467477eb7f9SFrançois Tigeot mmio = RENDER_HWS_PGA_GEN7; 468477eb7f9SFrançois Tigeot break; 469477eb7f9SFrançois Tigeot case BCS: 470477eb7f9SFrançois Tigeot mmio = BLT_HWS_PGA_GEN7; 471477eb7f9SFrançois Tigeot break; 472477eb7f9SFrançois Tigeot /* 473477eb7f9SFrançois Tigeot * VCS2 actually doesn't exist on Gen7. Only shut up 474477eb7f9SFrançois Tigeot * gcc switch check warning 475477eb7f9SFrançois Tigeot */ 476477eb7f9SFrançois Tigeot case VCS2: 477477eb7f9SFrançois Tigeot case VCS: 478477eb7f9SFrançois Tigeot mmio = BSD_HWS_PGA_GEN7; 479477eb7f9SFrançois Tigeot break; 480477eb7f9SFrançois Tigeot case VECS: 481477eb7f9SFrançois Tigeot mmio = VEBOX_HWS_PGA_GEN7; 482477eb7f9SFrançois Tigeot break; 483477eb7f9SFrançois Tigeot } 4841487f786SFrançois Tigeot } else if (IS_GEN6(dev_priv)) { 4858621f407SFrançois Tigeot mmio = RING_HWS_PGA_GEN6(engine->mmio_base); 486477eb7f9SFrançois Tigeot } else { 487477eb7f9SFrançois Tigeot /* XXX: gen8 returns to sanity */ 4888621f407SFrançois Tigeot mmio = RING_HWS_PGA(engine->mmio_base); 489477eb7f9SFrançois Tigeot } 490477eb7f9SFrançois Tigeot 4918621f407SFrançois Tigeot I915_WRITE(mmio, (u32)engine->status_page.gfx_addr); 492477eb7f9SFrançois Tigeot POSTING_READ(mmio); 493477eb7f9SFrançois Tigeot 494477eb7f9SFrançois Tigeot /* 495477eb7f9SFrançois Tigeot * Flush the TLB for this page 496477eb7f9SFrançois Tigeot * 497477eb7f9SFrançois Tigeot * FIXME: These two bits have disappeared on gen8, so a question 498477eb7f9SFrançois Tigeot * arises: do we still need this and if so how should we go about 499477eb7f9SFrançois Tigeot * invalidating the TLB? 500477eb7f9SFrançois Tigeot */ 5011487f786SFrançois Tigeot if (IS_GEN(dev_priv, 6, 7)) { 5028621f407SFrançois Tigeot i915_reg_t reg = RING_INSTPM(engine->mmio_base); 503477eb7f9SFrançois Tigeot 504477eb7f9SFrançois Tigeot /* ring should be idle before issuing a sync flush*/ 5058621f407SFrançois Tigeot WARN_ON((I915_READ_MODE(engine) & MODE_IDLE) == 0); 506477eb7f9SFrançois Tigeot 507477eb7f9SFrançois Tigeot I915_WRITE(reg, 508477eb7f9SFrançois Tigeot _MASKED_BIT_ENABLE(INSTPM_TLB_INVALIDATE | 509477eb7f9SFrançois Tigeot INSTPM_SYNC_FLUSH)); 5101487f786SFrançois Tigeot if (intel_wait_for_register(dev_priv, 5111487f786SFrançois Tigeot reg, INSTPM_SYNC_FLUSH, 0, 512477eb7f9SFrançois Tigeot 1000)) 513477eb7f9SFrançois Tigeot DRM_ERROR("%s: wait for SyncFlush to complete for TLB invalidation timed out\n", 5148621f407SFrançois Tigeot engine->name); 515477eb7f9SFrançois Tigeot } 516477eb7f9SFrançois Tigeot } 517477eb7f9SFrançois Tigeot 5188621f407SFrançois Tigeot static bool stop_ring(struct intel_engine_cs *engine) 519e3adcf8fSFrançois Tigeot { 5201487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 521e3adcf8fSFrançois Tigeot 5221487f786SFrançois Tigeot if (!IS_GEN2(dev_priv)) { 5238621f407SFrançois Tigeot I915_WRITE_MODE(engine, _MASKED_BIT_ENABLE(STOP_RING)); 5241487f786SFrançois Tigeot if (intel_wait_for_register(dev_priv, 5251487f786SFrançois Tigeot RING_MI_MODE(engine->mmio_base), 5261487f786SFrançois Tigeot MODE_IDLE, 5271487f786SFrançois Tigeot MODE_IDLE, 5281487f786SFrançois Tigeot 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 5441487f786SFrançois Tigeot if (!IS_GEN2(dev_priv)) { 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 { 5591487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 5608621f407SFrançois Tigeot struct intel_ringbuffer *ringbuf = engine->buffer; 561ba55f2f5SFrançois Tigeot struct drm_i915_gem_object *obj = ringbuf->obj; 562ba55f2f5SFrançois Tigeot int ret = 0; 563ba55f2f5SFrançois Tigeot 5642c9916cdSFrançois Tigeot intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL); 565ba55f2f5SFrançois Tigeot 5668621f407SFrançois Tigeot if (!stop_ring(engine)) { 567ba55f2f5SFrançois Tigeot /* G45 ring initialization often fails to reset head to zero */ 568b5c29a34SFrançois Tigeot DRM_DEBUG_KMS("%s head not reset to zero " 569e3adcf8fSFrançois Tigeot "ctl %08x head %08x tail %08x start %08x\n", 5708621f407SFrançois Tigeot engine->name, 5718621f407SFrançois Tigeot I915_READ_CTL(engine), 5728621f407SFrançois Tigeot I915_READ_HEAD(engine), 5738621f407SFrançois Tigeot I915_READ_TAIL(engine), 5748621f407SFrançois Tigeot I915_READ_START(engine)); 575e3adcf8fSFrançois Tigeot 5768621f407SFrançois Tigeot if (!stop_ring(engine)) { 577e3adcf8fSFrançois Tigeot DRM_ERROR("failed to set %s head to zero " 578e3adcf8fSFrançois Tigeot "ctl %08x head %08x tail %08x start %08x\n", 5798621f407SFrançois Tigeot engine->name, 5808621f407SFrançois Tigeot I915_READ_CTL(engine), 5818621f407SFrançois Tigeot I915_READ_HEAD(engine), 5828621f407SFrançois Tigeot I915_READ_TAIL(engine), 5838621f407SFrançois Tigeot I915_READ_START(engine)); 584686a02f1SFrançois Tigeot ret = -EIO; 585686a02f1SFrançois Tigeot goto out; 586e3adcf8fSFrançois Tigeot } 587ba55f2f5SFrançois Tigeot } 588ba55f2f5SFrançois Tigeot 5891487f786SFrançois Tigeot if (I915_NEED_GFX_HWS(dev_priv)) 5908621f407SFrançois Tigeot intel_ring_setup_status_page(engine); 591ba55f2f5SFrançois Tigeot else 5928621f407SFrançois Tigeot ring_setup_phys_status_page(engine); 593ba55f2f5SFrançois Tigeot 5940f370975SMatthew Dillon /* Enforce ordering by reading HEAD register back */ 5958621f407SFrançois Tigeot I915_READ_HEAD(engine); 5960f370975SMatthew Dillon 597ba55f2f5SFrançois Tigeot /* Initialize the ring. This must happen _after_ we've cleared the ring 598ba55f2f5SFrançois Tigeot * registers with the above sequence (the readback of the HEAD registers 599ba55f2f5SFrançois Tigeot * also enforces ordering), otherwise the hw might lose the new ring 600ba55f2f5SFrançois Tigeot * register values. */ 6018621f407SFrançois Tigeot I915_WRITE_START(engine, i915_gem_obj_ggtt_offset(obj)); 6021b13d190SFrançois Tigeot 6031b13d190SFrançois Tigeot /* WaClearRingBufHeadRegAtInit:ctg,elk */ 6048621f407SFrançois Tigeot if (I915_READ_HEAD(engine)) 6051b13d190SFrançois Tigeot DRM_DEBUG("%s initialization failed [head=%08x], fudging\n", 6068621f407SFrançois Tigeot engine->name, I915_READ_HEAD(engine)); 6078621f407SFrançois Tigeot I915_WRITE_HEAD(engine, 0); 6088621f407SFrançois Tigeot (void)I915_READ_HEAD(engine); 6091b13d190SFrançois Tigeot 6108621f407SFrançois Tigeot I915_WRITE_CTL(engine, 611ba55f2f5SFrançois Tigeot ((ringbuf->size - PAGE_SIZE) & RING_NR_PAGES) 612ba55f2f5SFrançois Tigeot | RING_VALID); 613ba55f2f5SFrançois Tigeot 614ba55f2f5SFrançois Tigeot /* If the head is still not zero, the ring is dead */ 6158621f407SFrançois Tigeot if (wait_for((I915_READ_CTL(engine) & RING_VALID) != 0 && 6168621f407SFrançois Tigeot I915_READ_START(engine) == i915_gem_obj_ggtt_offset(obj) && 6178621f407SFrançois Tigeot (I915_READ_HEAD(engine) & HEAD_ADDR) == 0, 50)) { 618ba55f2f5SFrançois Tigeot DRM_ERROR("%s initialization failed " 619ba55f2f5SFrançois Tigeot "ctl %08x (valid? %d) head %08x tail %08x start %08x [expected %08lx]\n", 6208621f407SFrançois Tigeot engine->name, 6218621f407SFrançois Tigeot I915_READ_CTL(engine), 6228621f407SFrançois Tigeot I915_READ_CTL(engine) & RING_VALID, 6238621f407SFrançois Tigeot I915_READ_HEAD(engine), I915_READ_TAIL(engine), 6248621f407SFrançois Tigeot I915_READ_START(engine), 6258621f407SFrançois Tigeot (unsigned long)i915_gem_obj_ggtt_offset(obj)); 626ba55f2f5SFrançois Tigeot ret = -EIO; 627ba55f2f5SFrançois Tigeot goto out; 628ba55f2f5SFrançois Tigeot } 629e3adcf8fSFrançois Tigeot 6302c9916cdSFrançois Tigeot ringbuf->last_retired_head = -1; 6318621f407SFrançois Tigeot ringbuf->head = I915_READ_HEAD(engine); 6328621f407SFrançois Tigeot ringbuf->tail = I915_READ_TAIL(engine) & TAIL_ADDR; 6332c9916cdSFrançois Tigeot intel_ring_update_space(ringbuf); 634e3adcf8fSFrançois Tigeot 6358621f407SFrançois Tigeot intel_engine_init_hangcheck(engine); 6365d0b1887SFrançois Tigeot 637686a02f1SFrançois Tigeot out: 6382c9916cdSFrançois Tigeot intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL); 639686a02f1SFrançois Tigeot 640686a02f1SFrançois Tigeot return ret; 641e3adcf8fSFrançois Tigeot } 642e3adcf8fSFrançois Tigeot 643*303bf270SFrançois Tigeot void intel_fini_pipe_control(struct intel_engine_cs *engine) 6441b13d190SFrançois Tigeot { 6458621f407SFrançois Tigeot if (engine->scratch.obj == NULL) 6461b13d190SFrançois Tigeot return; 6471b13d190SFrançois Tigeot 6488621f407SFrançois Tigeot i915_gem_object_ggtt_unpin(engine->scratch.obj); 6498621f407SFrançois Tigeot drm_gem_object_unreference(&engine->scratch.obj->base); 6508621f407SFrançois Tigeot engine->scratch.obj = NULL; 6511b13d190SFrançois Tigeot } 6521b13d190SFrançois Tigeot 653*303bf270SFrançois Tigeot int intel_init_pipe_control(struct intel_engine_cs *engine, int size) 654e3adcf8fSFrançois Tigeot { 655*303bf270SFrançois Tigeot struct drm_i915_gem_object *obj; 656e3adcf8fSFrançois Tigeot int ret; 657e3adcf8fSFrançois Tigeot 6588621f407SFrançois Tigeot WARN_ON(engine->scratch.obj); 659e3adcf8fSFrançois Tigeot 660*303bf270SFrançois Tigeot obj = i915_gem_object_create_stolen(&engine->i915->drm, size); 661*303bf270SFrançois Tigeot if (!obj) 662*303bf270SFrançois Tigeot obj = i915_gem_object_create(&engine->i915->drm, size); 663*303bf270SFrançois Tigeot if (IS_ERR(obj)) { 664*303bf270SFrançois Tigeot DRM_ERROR("Failed to allocate scratch page\n"); 665*303bf270SFrançois Tigeot ret = PTR_ERR(obj); 666e3adcf8fSFrançois Tigeot goto err; 667e3adcf8fSFrançois Tigeot } 668e3adcf8fSFrançois Tigeot 669*303bf270SFrançois Tigeot ret = i915_gem_obj_ggtt_pin(obj, 4096, PIN_HIGH); 670ba55f2f5SFrançois Tigeot if (ret) 671ba55f2f5SFrançois Tigeot goto err_unref; 672e3adcf8fSFrançois Tigeot 673*303bf270SFrançois Tigeot engine->scratch.obj = obj; 674*303bf270SFrançois Tigeot engine->scratch.gtt_offset = i915_gem_obj_ggtt_offset(obj); 675a2fdbec6SFrançois Tigeot DRM_DEBUG_DRIVER("%s pipe control offset: 0x%08x\n", 6768621f407SFrançois Tigeot engine->name, engine->scratch.gtt_offset); 677e3adcf8fSFrançois Tigeot return 0; 678e3adcf8fSFrançois Tigeot 679e3adcf8fSFrançois Tigeot err_unref: 6808621f407SFrançois Tigeot drm_gem_object_unreference(&engine->scratch.obj->base); 681e3adcf8fSFrançois Tigeot err: 682e3adcf8fSFrançois Tigeot return ret; 683e3adcf8fSFrançois Tigeot } 684e3adcf8fSFrançois Tigeot 685a05eeebfSFrançois Tigeot static int intel_ring_workarounds_emit(struct drm_i915_gem_request *req) 6861b13d190SFrançois Tigeot { 6878621f407SFrançois Tigeot struct intel_engine_cs *engine = req->engine; 6881487f786SFrançois Tigeot struct i915_workarounds *w = &req->i915->workarounds; 6891487f786SFrançois Tigeot int ret, i; 6901b13d190SFrançois Tigeot 691352ff8bdSFrançois Tigeot if (w->count == 0) 6922c9916cdSFrançois Tigeot return 0; 6931b13d190SFrançois Tigeot 6948621f407SFrançois Tigeot engine->gpu_caches_dirty = true; 695a05eeebfSFrançois Tigeot ret = intel_ring_flush_all_caches(req); 6961b13d190SFrançois Tigeot if (ret) 6971b13d190SFrançois Tigeot return ret; 6981b13d190SFrançois Tigeot 699a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, (w->count * 2 + 2)); 7002c9916cdSFrançois Tigeot if (ret) 7012c9916cdSFrançois Tigeot return ret; 7022c9916cdSFrançois Tigeot 7038621f407SFrançois Tigeot intel_ring_emit(engine, MI_LOAD_REGISTER_IMM(w->count)); 7042c9916cdSFrançois Tigeot for (i = 0; i < w->count; i++) { 7058621f407SFrançois Tigeot intel_ring_emit_reg(engine, w->reg[i].addr); 7068621f407SFrançois Tigeot intel_ring_emit(engine, w->reg[i].value); 7072c9916cdSFrançois Tigeot } 7088621f407SFrançois Tigeot intel_ring_emit(engine, MI_NOOP); 7092c9916cdSFrançois Tigeot 7108621f407SFrançois Tigeot intel_ring_advance(engine); 7112c9916cdSFrançois Tigeot 7128621f407SFrançois Tigeot engine->gpu_caches_dirty = true; 713a05eeebfSFrançois Tigeot ret = intel_ring_flush_all_caches(req); 7142c9916cdSFrançois Tigeot if (ret) 7152c9916cdSFrançois Tigeot return ret; 7162c9916cdSFrançois Tigeot 7172c9916cdSFrançois Tigeot DRM_DEBUG_DRIVER("Number of Workarounds emitted: %d\n", w->count); 7182c9916cdSFrançois Tigeot 7192c9916cdSFrançois Tigeot return 0; 7202c9916cdSFrançois Tigeot } 7212c9916cdSFrançois Tigeot 722a05eeebfSFrançois Tigeot static int intel_rcs_ctx_init(struct drm_i915_gem_request *req) 7232c9916cdSFrançois Tigeot { 7242c9916cdSFrançois Tigeot int ret; 7252c9916cdSFrançois Tigeot 726a05eeebfSFrançois Tigeot ret = intel_ring_workarounds_emit(req); 7272c9916cdSFrançois Tigeot if (ret != 0) 7282c9916cdSFrançois Tigeot return ret; 7292c9916cdSFrançois Tigeot 730a05eeebfSFrançois Tigeot ret = i915_gem_render_state_init(req); 7312c9916cdSFrançois Tigeot if (ret) 7322c9916cdSFrançois Tigeot return ret; 733c0e85e96SFrançois Tigeot 734c0e85e96SFrançois Tigeot return 0; 7352c9916cdSFrançois Tigeot } 7362c9916cdSFrançois Tigeot 7372c9916cdSFrançois Tigeot static int wa_add(struct drm_i915_private *dev_priv, 738aee94f86SFrançois Tigeot i915_reg_t addr, 739aee94f86SFrançois Tigeot const u32 mask, const u32 val) 7402c9916cdSFrançois Tigeot { 7412c9916cdSFrançois Tigeot const u32 idx = dev_priv->workarounds.count; 7422c9916cdSFrançois Tigeot 7432c9916cdSFrançois Tigeot if (WARN_ON(idx >= I915_MAX_WA_REGS)) 7442c9916cdSFrançois Tigeot return -ENOSPC; 7452c9916cdSFrançois Tigeot 7462c9916cdSFrançois Tigeot dev_priv->workarounds.reg[idx].addr = addr; 7472c9916cdSFrançois Tigeot dev_priv->workarounds.reg[idx].value = val; 7482c9916cdSFrançois Tigeot dev_priv->workarounds.reg[idx].mask = mask; 7492c9916cdSFrançois Tigeot 7502c9916cdSFrançois Tigeot dev_priv->workarounds.count++; 7512c9916cdSFrançois Tigeot 7522c9916cdSFrançois Tigeot return 0; 7532c9916cdSFrançois Tigeot } 7542c9916cdSFrançois Tigeot 755a05eeebfSFrançois Tigeot #define WA_REG(addr, mask, val) do { \ 7562c9916cdSFrançois Tigeot const int r = wa_add(dev_priv, (addr), (mask), (val)); \ 7572c9916cdSFrançois Tigeot if (r) \ 7582c9916cdSFrançois Tigeot return r; \ 759a05eeebfSFrançois Tigeot } while (0) 7602c9916cdSFrançois Tigeot 7612c9916cdSFrançois Tigeot #define WA_SET_BIT_MASKED(addr, mask) \ 7622c9916cdSFrançois Tigeot WA_REG(addr, (mask), _MASKED_BIT_ENABLE(mask)) 7632c9916cdSFrançois Tigeot 7642c9916cdSFrançois Tigeot #define WA_CLR_BIT_MASKED(addr, mask) \ 7652c9916cdSFrançois Tigeot WA_REG(addr, (mask), _MASKED_BIT_DISABLE(mask)) 7662c9916cdSFrançois Tigeot 7672c9916cdSFrançois Tigeot #define WA_SET_FIELD_MASKED(addr, mask, value) \ 7682c9916cdSFrançois Tigeot WA_REG(addr, mask, _MASKED_FIELD(mask, value)) 7692c9916cdSFrançois Tigeot 7702c9916cdSFrançois Tigeot #define WA_SET_BIT(addr, mask) WA_REG(addr, mask, I915_READ(addr) | (mask)) 7712c9916cdSFrançois Tigeot #define WA_CLR_BIT(addr, mask) WA_REG(addr, mask, I915_READ(addr) & ~(mask)) 7722c9916cdSFrançois Tigeot 7732c9916cdSFrançois Tigeot #define WA_WRITE(addr, val) WA_REG(addr, 0xffffffff, val) 7742c9916cdSFrançois Tigeot 7758621f407SFrançois Tigeot static int wa_ring_whitelist_reg(struct intel_engine_cs *engine, 7768621f407SFrançois Tigeot i915_reg_t reg) 777c0e85e96SFrançois Tigeot { 7781487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 779c0e85e96SFrançois Tigeot struct i915_workarounds *wa = &dev_priv->workarounds; 7808621f407SFrançois Tigeot const uint32_t index = wa->hw_whitelist_count[engine->id]; 781c0e85e96SFrançois Tigeot 782c0e85e96SFrançois Tigeot if (WARN_ON(index >= RING_MAX_NONPRIV_SLOTS)) 783c0e85e96SFrançois Tigeot return -EINVAL; 784c0e85e96SFrançois Tigeot 7858621f407SFrançois Tigeot WA_WRITE(RING_FORCE_TO_NONPRIV(engine->mmio_base, index), 786c0e85e96SFrançois Tigeot i915_mmio_reg_offset(reg)); 7878621f407SFrançois Tigeot wa->hw_whitelist_count[engine->id]++; 788c0e85e96SFrançois Tigeot 789c0e85e96SFrançois Tigeot return 0; 790c0e85e96SFrançois Tigeot } 791c0e85e96SFrançois Tigeot 7928621f407SFrançois Tigeot static int gen8_init_workarounds(struct intel_engine_cs *engine) 7932c9916cdSFrançois Tigeot { 7941487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 7952c9916cdSFrançois Tigeot 796a05eeebfSFrançois Tigeot WA_SET_BIT_MASKED(INSTPM, INSTPM_FORCE_ORDERING); 797a05eeebfSFrançois Tigeot 798352ff8bdSFrançois Tigeot /* WaDisableAsyncFlipPerfMode:bdw,chv */ 799a05eeebfSFrançois Tigeot WA_SET_BIT_MASKED(MI_MODE, ASYNC_FLIP_PERF_DISABLE); 800a05eeebfSFrançois Tigeot 801352ff8bdSFrançois Tigeot /* WaDisablePartialInstShootdown:bdw,chv */ 8022c9916cdSFrançois Tigeot WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN, 803352ff8bdSFrançois Tigeot PARTIAL_INSTRUCTION_SHOOTDOWN_DISABLE); 8041b13d190SFrançois Tigeot 8051b13d190SFrançois Tigeot /* Use Force Non-Coherent whenever executing a 3D context. This is a 8061b13d190SFrançois Tigeot * workaround for for a possible hang in the unlikely event a TLB 8071b13d190SFrançois Tigeot * invalidation occurs during a PSD flush. 8081b13d190SFrançois Tigeot */ 809352ff8bdSFrançois Tigeot /* WaForceEnableNonCoherent:bdw,chv */ 810352ff8bdSFrançois Tigeot /* WaHdcDisableFetchWhenMasked:bdw,chv */ 8112c9916cdSFrançois Tigeot WA_SET_BIT_MASKED(HDC_CHICKEN0, 8122c9916cdSFrançois Tigeot HDC_DONOT_FETCH_MEM_WHEN_MASKED | 813352ff8bdSFrançois Tigeot HDC_FORCE_NON_COHERENT); 8142c9916cdSFrançois Tigeot 8152c9916cdSFrançois Tigeot /* From the Haswell PRM, Command Reference: Registers, CACHE_MODE_0: 8162c9916cdSFrançois Tigeot * "The Hierarchical Z RAW Stall Optimization allows non-overlapping 8172c9916cdSFrançois Tigeot * polygons in the same 8x4 pixel/sample area to be processed without 8182c9916cdSFrançois Tigeot * stalling waiting for the earlier ones to write to Hierarchical Z 8192c9916cdSFrançois Tigeot * buffer." 8202c9916cdSFrançois Tigeot * 821352ff8bdSFrançois Tigeot * This optimization is off by default for BDW and CHV; turn it on. 8222c9916cdSFrançois Tigeot */ 8232c9916cdSFrançois Tigeot WA_CLR_BIT_MASKED(CACHE_MODE_0_GEN7, HIZ_RAW_STALL_OPT_DISABLE); 8241b13d190SFrançois Tigeot 825352ff8bdSFrançois Tigeot /* Wa4x4STCOptimizationDisable:bdw,chv */ 826352ff8bdSFrançois Tigeot WA_SET_BIT_MASKED(CACHE_MODE_1, GEN8_4x4_STC_OPTIMIZATION_DISABLE); 8271b13d190SFrançois Tigeot 8281b13d190SFrançois Tigeot /* 8291b13d190SFrançois Tigeot * BSpec recommends 8x4 when MSAA is used, 8301b13d190SFrançois Tigeot * however in practice 16x4 seems fastest. 8311b13d190SFrançois Tigeot * 8321b13d190SFrançois Tigeot * Note that PS/WM thread counts depend on the WIZ hashing 8331b13d190SFrançois Tigeot * disable bit, which we don't touch here, but it's good 8341b13d190SFrançois Tigeot * to keep in mind (see 3DSTATE_PS and 3DSTATE_WM). 8351b13d190SFrançois Tigeot */ 8362c9916cdSFrançois Tigeot WA_SET_FIELD_MASKED(GEN7_GT_MODE, 8372c9916cdSFrançois Tigeot GEN6_WIZ_HASHING_MASK, 8382c9916cdSFrançois Tigeot GEN6_WIZ_HASHING_16x4); 8391b13d190SFrançois Tigeot 8401b13d190SFrançois Tigeot return 0; 8411b13d190SFrançois Tigeot } 8421b13d190SFrançois Tigeot 8438621f407SFrançois Tigeot static int bdw_init_workarounds(struct intel_engine_cs *engine) 8441b13d190SFrançois Tigeot { 8451487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 846352ff8bdSFrançois Tigeot int ret; 8471b13d190SFrançois Tigeot 8488621f407SFrançois Tigeot ret = gen8_init_workarounds(engine); 849352ff8bdSFrançois Tigeot if (ret) 850352ff8bdSFrançois Tigeot return ret; 851a05eeebfSFrançois Tigeot 852352ff8bdSFrançois Tigeot /* WaDisableThreadStallDopClockGating:bdw (pre-production) */ 853352ff8bdSFrançois Tigeot WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN, STALL_DOP_GATING_DISABLE); 854a05eeebfSFrançois Tigeot 855352ff8bdSFrançois Tigeot /* WaDisableDopClockGating:bdw */ 856352ff8bdSFrançois Tigeot WA_SET_BIT_MASKED(GEN7_ROW_CHICKEN2, 857352ff8bdSFrançois Tigeot DOP_CLOCK_GATING_DISABLE); 8581b13d190SFrançois Tigeot 859352ff8bdSFrançois Tigeot WA_SET_BIT_MASKED(HALF_SLICE_CHICKEN3, 860352ff8bdSFrançois Tigeot GEN8_SAMPLER_POWER_BYPASS_DIS); 861352ff8bdSFrançois Tigeot 8622c9916cdSFrançois Tigeot WA_SET_BIT_MASKED(HDC_CHICKEN0, 863352ff8bdSFrançois Tigeot /* WaForceContextSaveRestoreNonCoherent:bdw */ 864352ff8bdSFrançois Tigeot HDC_FORCE_CONTEXT_SAVE_RESTORE_NON_COHERENT | 865352ff8bdSFrançois Tigeot /* WaDisableFenceDestinationToSLM:bdw (pre-prod) */ 8661487f786SFrançois Tigeot (IS_BDW_GT3(dev_priv) ? HDC_FENCE_DEST_SLM_DISABLE : 0)); 8671b13d190SFrançois Tigeot 868352ff8bdSFrançois Tigeot return 0; 869352ff8bdSFrançois Tigeot } 8701b13d190SFrançois Tigeot 8718621f407SFrançois Tigeot static int chv_init_workarounds(struct intel_engine_cs *engine) 872352ff8bdSFrançois Tigeot { 8731487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 874352ff8bdSFrançois Tigeot int ret; 875352ff8bdSFrançois Tigeot 8768621f407SFrançois Tigeot ret = gen8_init_workarounds(engine); 877352ff8bdSFrançois Tigeot if (ret) 878352ff8bdSFrançois Tigeot return ret; 879352ff8bdSFrançois Tigeot 880352ff8bdSFrançois Tigeot /* WaDisableThreadStallDopClockGating:chv */ 881352ff8bdSFrançois Tigeot WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN, STALL_DOP_GATING_DISABLE); 8822c9916cdSFrançois Tigeot 8832c9916cdSFrançois Tigeot /* Improve HiZ throughput on CHV. */ 8842c9916cdSFrançois Tigeot WA_SET_BIT_MASKED(HIZ_CHICKEN, CHV_HZ_8X8_MODE_IN_1X); 8852c9916cdSFrançois Tigeot 8862c9916cdSFrançois Tigeot return 0; 8872c9916cdSFrançois Tigeot } 8882c9916cdSFrançois Tigeot 8898621f407SFrançois Tigeot static int gen9_init_workarounds(struct intel_engine_cs *engine) 890477eb7f9SFrançois Tigeot { 8911487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 892c0e85e96SFrançois Tigeot int ret; 893477eb7f9SFrançois Tigeot 8948621f407SFrançois Tigeot /* WaConextSwitchWithConcurrentTLBInvalidate:skl,bxt,kbl */ 8958621f407SFrançois Tigeot I915_WRITE(GEN9_CSFE_CHICKEN1_RCS, _MASKED_BIT_ENABLE(GEN9_PREEMPT_GPGPU_SYNC_SWITCH_DISABLE)); 8968621f407SFrançois Tigeot 8978621f407SFrançois Tigeot /* WaEnableLbsSlaRetryTimerDecrement:skl,bxt,kbl */ 898352ff8bdSFrançois Tigeot I915_WRITE(BDW_SCRATCH1, I915_READ(BDW_SCRATCH1) | 899352ff8bdSFrançois Tigeot GEN9_LBS_SLA_RETRY_TIMER_DECREMENT_ENABLE); 900352ff8bdSFrançois Tigeot 9018621f407SFrançois Tigeot /* WaDisableKillLogic:bxt,skl,kbl */ 902352ff8bdSFrançois Tigeot I915_WRITE(GAM_ECOCHK, I915_READ(GAM_ECOCHK) | 903352ff8bdSFrançois Tigeot ECOCHK_DIS_TLB); 904352ff8bdSFrançois Tigeot 9058621f407SFrançois Tigeot /* WaClearFlowControlGpgpuContextSave:skl,bxt,kbl */ 9068621f407SFrançois Tigeot /* WaDisablePartialInstShootdown:skl,bxt,kbl */ 907477eb7f9SFrançois Tigeot WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN, 9088621f407SFrançois Tigeot FLOW_CONTROL_ENABLE | 909477eb7f9SFrançois Tigeot PARTIAL_INSTRUCTION_SHOOTDOWN_DISABLE); 910477eb7f9SFrançois Tigeot 9118621f407SFrançois Tigeot /* Syncing dependencies between camera and graphics:skl,bxt,kbl */ 912477eb7f9SFrançois Tigeot WA_SET_BIT_MASKED(HALF_SLICE_CHICKEN3, 913477eb7f9SFrançois Tigeot GEN9_DISABLE_OCL_OOB_SUPPRESS_LOGIC); 914477eb7f9SFrançois Tigeot 91519c468b4SFrançois Tigeot /* WaDisableDgMirrorFixInHalfSliceChicken5:skl,bxt */ 9161487f786SFrançois Tigeot if (IS_SKL_REVID(dev_priv, 0, SKL_REVID_B0) || 9171487f786SFrançois Tigeot IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1)) 918477eb7f9SFrançois Tigeot WA_CLR_BIT_MASKED(GEN9_HALF_SLICE_CHICKEN5, 919477eb7f9SFrançois Tigeot GEN9_DG_MIRROR_FIX_ENABLE); 920477eb7f9SFrançois Tigeot 92119c468b4SFrançois Tigeot /* WaSetDisablePixMaskCammingAndRhwoInCommonSliceChicken:skl,bxt */ 9221487f786SFrançois Tigeot if (IS_SKL_REVID(dev_priv, 0, SKL_REVID_B0) || 9231487f786SFrançois Tigeot IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1)) { 924477eb7f9SFrançois Tigeot WA_SET_BIT_MASKED(GEN7_COMMON_SLICE_CHICKEN1, 925477eb7f9SFrançois Tigeot GEN9_RHWO_OPTIMIZATION_DISABLE); 926a05eeebfSFrançois Tigeot /* 927a05eeebfSFrançois Tigeot * WA also requires GEN9_SLICE_COMMON_ECO_CHICKEN0[14:14] to be set 928a05eeebfSFrançois Tigeot * but we do that in per ctx batchbuffer as there is an issue 929a05eeebfSFrançois Tigeot * with this register not getting restored on ctx restore 930a05eeebfSFrançois Tigeot */ 931477eb7f9SFrançois Tigeot } 932477eb7f9SFrançois Tigeot 9338621f407SFrançois Tigeot /* WaEnableYV12BugFixInHalfSliceChicken7:skl,bxt,kbl */ 9348621f407SFrançois Tigeot /* WaEnableSamplerGPGPUPreemptionSupport:skl,bxt,kbl */ 935477eb7f9SFrançois Tigeot WA_SET_BIT_MASKED(GEN9_HALF_SLICE_CHICKEN7, 9368621f407SFrançois Tigeot GEN9_ENABLE_YV12_BUGFIX | 9378621f407SFrançois Tigeot GEN9_ENABLE_GPGPU_PREEMPTION); 938477eb7f9SFrançois Tigeot 9398621f407SFrançois Tigeot /* Wa4x4STCOptimizationDisable:skl,bxt,kbl */ 9408621f407SFrançois Tigeot /* WaDisablePartialResolveInVc:skl,bxt,kbl */ 941352ff8bdSFrançois Tigeot WA_SET_BIT_MASKED(CACHE_MODE_1, (GEN8_4x4_STC_OPTIMIZATION_DISABLE | 942352ff8bdSFrançois Tigeot GEN9_PARTIAL_RESOLVE_IN_VC_DISABLE)); 943477eb7f9SFrançois Tigeot 9448621f407SFrançois Tigeot /* WaCcsTlbPrefetchDisable:skl,bxt,kbl */ 945477eb7f9SFrançois Tigeot WA_CLR_BIT_MASKED(GEN9_HALF_SLICE_CHICKEN5, 946477eb7f9SFrançois Tigeot GEN9_CCS_TLB_PREFETCH_ENABLE); 947477eb7f9SFrançois Tigeot 94819c468b4SFrançois Tigeot /* WaDisableMaskBasedCammingInRCC:skl,bxt */ 9491487f786SFrançois Tigeot if (IS_SKL_REVID(dev_priv, SKL_REVID_C0, SKL_REVID_C0) || 9501487f786SFrançois Tigeot IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1)) 95119c468b4SFrançois Tigeot WA_SET_BIT_MASKED(SLICE_ECO_CHICKEN0, 95219c468b4SFrançois Tigeot PIXEL_MASK_CAMMING_DISABLE); 95319c468b4SFrançois Tigeot 9548621f407SFrançois Tigeot /* WaForceContextSaveRestoreNonCoherent:skl,bxt,kbl */ 9558621f407SFrançois Tigeot WA_SET_BIT_MASKED(HDC_CHICKEN0, 9568621f407SFrançois Tigeot HDC_FORCE_CONTEXT_SAVE_RESTORE_NON_COHERENT | 9578621f407SFrançois Tigeot HDC_FORCE_CSR_NON_COHERENT_OVR_DISABLE); 95819c468b4SFrançois Tigeot 9598621f407SFrançois Tigeot /* WaForceEnableNonCoherent and WaDisableHDCInvalidation are 9608621f407SFrançois Tigeot * both tied to WaForceContextSaveRestoreNonCoherent 9618621f407SFrançois Tigeot * in some hsds for skl. We keep the tie for all gen9. The 9628621f407SFrançois Tigeot * documentation is a bit hazy and so we want to get common behaviour, 9638621f407SFrançois Tigeot * even though there is no clear evidence we would need both on kbl/bxt. 9648621f407SFrançois Tigeot * This area has been source of system hangs so we play it safe 9658621f407SFrançois Tigeot * and mimic the skl regardless of what bspec says. 9668621f407SFrançois Tigeot * 9678621f407SFrançois Tigeot * Use Force Non-Coherent whenever executing a 3D context. This 9688621f407SFrançois Tigeot * is a workaround for a possible hang in the unlikely event 9698621f407SFrançois Tigeot * a TLB invalidation occurs during a PSD flush. 9708621f407SFrançois Tigeot */ 9718621f407SFrançois Tigeot 9728621f407SFrançois Tigeot /* WaForceEnableNonCoherent:skl,bxt,kbl */ 9738621f407SFrançois Tigeot WA_SET_BIT_MASKED(HDC_CHICKEN0, 9748621f407SFrançois Tigeot HDC_FORCE_NON_COHERENT); 9758621f407SFrançois Tigeot 9768621f407SFrançois Tigeot /* WaDisableHDCInvalidation:skl,bxt,kbl */ 9778621f407SFrançois Tigeot I915_WRITE(GAM_ECOCHK, I915_READ(GAM_ECOCHK) | 9788621f407SFrançois Tigeot BDW_DISABLE_HDC_INVALIDATION); 9798621f407SFrançois Tigeot 9808621f407SFrançois Tigeot /* WaDisableSamplerPowerBypassForSOPingPong:skl,bxt,kbl */ 9818621f407SFrançois Tigeot if (IS_SKYLAKE(dev_priv) || 9828621f407SFrançois Tigeot IS_KABYLAKE(dev_priv) || 9838621f407SFrançois Tigeot IS_BXT_REVID(dev_priv, 0, BXT_REVID_B0)) 984352ff8bdSFrançois Tigeot WA_SET_BIT_MASKED(HALF_SLICE_CHICKEN3, 985352ff8bdSFrançois Tigeot GEN8_SAMPLER_POWER_BYPASS_DIS); 986352ff8bdSFrançois Tigeot 9878621f407SFrançois Tigeot /* WaDisableSTUnitPowerOptimization:skl,bxt,kbl */ 988352ff8bdSFrançois Tigeot WA_SET_BIT_MASKED(HALF_SLICE_CHICKEN2, GEN8_ST_PO_DISABLE); 989352ff8bdSFrançois Tigeot 9908621f407SFrançois Tigeot /* WaOCLCoherentLineFlush:skl,bxt,kbl */ 991c0e85e96SFrançois Tigeot I915_WRITE(GEN8_L3SQCREG4, (I915_READ(GEN8_L3SQCREG4) | 992c0e85e96SFrançois Tigeot GEN8_LQSC_FLUSH_COHERENT_LINES)); 993c0e85e96SFrançois Tigeot 9948621f407SFrançois Tigeot /* WaVFEStateAfterPipeControlwithMediaStateClear:skl,bxt */ 9958621f407SFrançois Tigeot ret = wa_ring_whitelist_reg(engine, GEN9_CTX_PREEMPT_REG); 996c0e85e96SFrançois Tigeot if (ret) 997c0e85e96SFrançois Tigeot return ret; 998c0e85e96SFrançois Tigeot 9998621f407SFrançois Tigeot /* WaEnablePreemptionGranularityControlByUMD:skl,bxt,kbl */ 10008621f407SFrançois Tigeot ret= wa_ring_whitelist_reg(engine, GEN8_CS_CHICKEN1); 10018621f407SFrançois Tigeot if (ret) 10028621f407SFrançois Tigeot return ret; 10038621f407SFrançois Tigeot 10048621f407SFrançois Tigeot /* WaAllowUMDToModifyHDCChicken1:skl,bxt,kbl */ 10058621f407SFrançois Tigeot ret = wa_ring_whitelist_reg(engine, GEN8_HDC_CHICKEN1); 1006c0e85e96SFrançois Tigeot if (ret) 1007c0e85e96SFrançois Tigeot return ret; 1008c0e85e96SFrançois Tigeot 1009477eb7f9SFrançois Tigeot return 0; 1010477eb7f9SFrançois Tigeot } 1011477eb7f9SFrançois Tigeot 10128621f407SFrançois Tigeot static int skl_tune_iz_hashing(struct intel_engine_cs *engine) 1013477eb7f9SFrançois Tigeot { 10141487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 1015477eb7f9SFrançois Tigeot u8 vals[3] = { 0, 0, 0 }; 1016477eb7f9SFrançois Tigeot unsigned int i; 1017477eb7f9SFrançois Tigeot 1018477eb7f9SFrançois Tigeot for (i = 0; i < 3; i++) { 1019477eb7f9SFrançois Tigeot u8 ss; 1020477eb7f9SFrançois Tigeot 1021477eb7f9SFrançois Tigeot /* 1022477eb7f9SFrançois Tigeot * Only consider slices where one, and only one, subslice has 7 1023477eb7f9SFrançois Tigeot * EUs 1024477eb7f9SFrançois Tigeot */ 1025aee94f86SFrançois Tigeot if (!is_power_of_2(dev_priv->info.subslice_7eu[i])) 1026477eb7f9SFrançois Tigeot continue; 1027477eb7f9SFrançois Tigeot 1028477eb7f9SFrançois Tigeot /* 1029477eb7f9SFrançois Tigeot * subslice_7eu[i] != 0 (because of the check above) and 1030477eb7f9SFrançois Tigeot * ss_max == 4 (maximum number of subslices possible per slice) 1031477eb7f9SFrançois Tigeot * 1032477eb7f9SFrançois Tigeot * -> 0 <= ss <= 3; 1033477eb7f9SFrançois Tigeot */ 1034477eb7f9SFrançois Tigeot ss = ffs(dev_priv->info.subslice_7eu[i]) - 1; 1035477eb7f9SFrançois Tigeot vals[i] = 3 - ss; 1036477eb7f9SFrançois Tigeot } 1037477eb7f9SFrançois Tigeot 1038477eb7f9SFrançois Tigeot if (vals[0] == 0 && vals[1] == 0 && vals[2] == 0) 1039477eb7f9SFrançois Tigeot return 0; 1040477eb7f9SFrançois Tigeot 1041477eb7f9SFrançois Tigeot /* Tune IZ hashing. See intel_device_info_runtime_init() */ 1042477eb7f9SFrançois Tigeot WA_SET_FIELD_MASKED(GEN7_GT_MODE, 1043477eb7f9SFrançois Tigeot GEN9_IZ_HASHING_MASK(2) | 1044477eb7f9SFrançois Tigeot GEN9_IZ_HASHING_MASK(1) | 1045477eb7f9SFrançois Tigeot GEN9_IZ_HASHING_MASK(0), 1046477eb7f9SFrançois Tigeot GEN9_IZ_HASHING(2, vals[2]) | 1047477eb7f9SFrançois Tigeot GEN9_IZ_HASHING(1, vals[1]) | 1048477eb7f9SFrançois Tigeot GEN9_IZ_HASHING(0, vals[0])); 1049477eb7f9SFrançois Tigeot 1050477eb7f9SFrançois Tigeot return 0; 1051477eb7f9SFrançois Tigeot } 1052477eb7f9SFrançois Tigeot 10538621f407SFrançois Tigeot static int skl_init_workarounds(struct intel_engine_cs *engine) 1054477eb7f9SFrançois Tigeot { 10551487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 1056352ff8bdSFrançois Tigeot int ret; 1057477eb7f9SFrançois Tigeot 10588621f407SFrançois Tigeot ret = gen9_init_workarounds(engine); 1059352ff8bdSFrançois Tigeot if (ret) 1060352ff8bdSFrançois Tigeot return ret; 1061352ff8bdSFrançois Tigeot 1062c0e85e96SFrançois Tigeot /* 1063c0e85e96SFrançois Tigeot * Actual WA is to disable percontext preemption granularity control 1064c0e85e96SFrançois Tigeot * until D0 which is the default case so this is equivalent to 1065c0e85e96SFrançois Tigeot * !WaDisablePerCtxtPreemptionGranularityControl:skl 1066c0e85e96SFrançois Tigeot */ 10671487f786SFrançois Tigeot if (IS_SKL_REVID(dev_priv, SKL_REVID_E0, REVID_FOREVER)) { 1068c0e85e96SFrançois Tigeot I915_WRITE(GEN7_FF_SLICE_CS_CHICKEN1, 1069c0e85e96SFrançois Tigeot _MASKED_BIT_ENABLE(GEN9_FFSC_PERCTX_PREEMPT_CTRL)); 1070c0e85e96SFrançois Tigeot } 1071c0e85e96SFrançois Tigeot 10721487f786SFrançois Tigeot if (IS_SKL_REVID(dev_priv, 0, SKL_REVID_E0)) { 1073352ff8bdSFrançois Tigeot /* WaDisableChickenBitTSGBarrierAckForFFSliceCS:skl */ 1074352ff8bdSFrançois Tigeot I915_WRITE(FF_SLICE_CS_CHICKEN2, 1075352ff8bdSFrançois Tigeot _MASKED_BIT_ENABLE(GEN9_TSG_BARRIER_ACK_DISABLE)); 1076352ff8bdSFrançois Tigeot } 1077352ff8bdSFrançois Tigeot 1078352ff8bdSFrançois Tigeot /* GEN8_L3SQCREG4 has a dependency with WA batch so any new changes 1079352ff8bdSFrançois Tigeot * involving this register should also be added to WA batch as required. 1080352ff8bdSFrançois Tigeot */ 10811487f786SFrançois Tigeot if (IS_SKL_REVID(dev_priv, 0, SKL_REVID_E0)) 1082352ff8bdSFrançois Tigeot /* WaDisableLSQCROPERFforOCL:skl */ 1083352ff8bdSFrançois Tigeot I915_WRITE(GEN8_L3SQCREG4, I915_READ(GEN8_L3SQCREG4) | 1084352ff8bdSFrançois Tigeot GEN8_LQSC_RO_PERF_DIS); 1085352ff8bdSFrançois Tigeot 1086352ff8bdSFrançois Tigeot /* WaEnableGapsTsvCreditFix:skl */ 10871487f786SFrançois Tigeot if (IS_SKL_REVID(dev_priv, SKL_REVID_C0, REVID_FOREVER)) { 1088352ff8bdSFrançois Tigeot I915_WRITE(GEN8_GARBCNTL, (I915_READ(GEN8_GARBCNTL) | 1089352ff8bdSFrançois Tigeot GEN9_GAPS_TSV_CREDIT_DISABLE)); 1090352ff8bdSFrançois Tigeot } 1091477eb7f9SFrançois Tigeot 1092477eb7f9SFrançois Tigeot /* WaDisablePowerCompilerClockGating:skl */ 10931487f786SFrançois Tigeot if (IS_SKL_REVID(dev_priv, SKL_REVID_B0, SKL_REVID_B0)) 1094477eb7f9SFrançois Tigeot WA_SET_BIT_MASKED(HIZ_CHICKEN, 1095477eb7f9SFrançois Tigeot BDW_HIZ_POWER_COMPILER_CLOCK_GATING_DISABLE); 1096477eb7f9SFrançois Tigeot 1097a05eeebfSFrançois Tigeot /* WaBarrierPerformanceFixDisable:skl */ 10981487f786SFrançois Tigeot if (IS_SKL_REVID(dev_priv, SKL_REVID_C0, SKL_REVID_D0)) 1099a05eeebfSFrançois Tigeot WA_SET_BIT_MASKED(HDC_CHICKEN0, 1100a05eeebfSFrançois Tigeot HDC_FENCE_DEST_SLM_DISABLE | 1101a05eeebfSFrançois Tigeot HDC_BARRIER_PERFORMANCE_DISABLE); 1102a05eeebfSFrançois Tigeot 1103a05eeebfSFrançois Tigeot /* WaDisableSbeCacheDispatchPortSharing:skl */ 11041487f786SFrançois Tigeot if (IS_SKL_REVID(dev_priv, 0, SKL_REVID_F0)) 1105a05eeebfSFrançois Tigeot WA_SET_BIT_MASKED( 1106a05eeebfSFrançois Tigeot GEN7_HALF_SLICE_CHICKEN1, 1107a05eeebfSFrançois Tigeot GEN7_SBE_SS_CACHE_DISPATCH_PORT_SHARING_DISABLE); 1108a05eeebfSFrançois Tigeot 11098621f407SFrançois Tigeot /* WaDisableGafsUnitClkGating:skl */ 11108621f407SFrançois Tigeot WA_SET_BIT(GEN7_UCGCTL4, GEN8_EU_GAUNIT_CLOCK_GATE_DISABLE); 11118621f407SFrançois Tigeot 1112c0e85e96SFrançois Tigeot /* WaDisableLSQCROPERFforOCL:skl */ 11138621f407SFrançois Tigeot ret = wa_ring_whitelist_reg(engine, GEN8_L3SQCREG4); 1114c0e85e96SFrançois Tigeot if (ret) 1115c0e85e96SFrançois Tigeot return ret; 1116c0e85e96SFrançois Tigeot 11178621f407SFrançois Tigeot return skl_tune_iz_hashing(engine); 1118477eb7f9SFrançois Tigeot } 1119477eb7f9SFrançois Tigeot 11208621f407SFrançois Tigeot static int bxt_init_workarounds(struct intel_engine_cs *engine) 112119c468b4SFrançois Tigeot { 11221487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 1123352ff8bdSFrançois Tigeot int ret; 112419c468b4SFrançois Tigeot 11258621f407SFrançois Tigeot ret = gen9_init_workarounds(engine); 1126352ff8bdSFrançois Tigeot if (ret) 1127352ff8bdSFrançois Tigeot return ret; 1128352ff8bdSFrançois Tigeot 1129352ff8bdSFrançois Tigeot /* WaStoreMultiplePTEenable:bxt */ 1130352ff8bdSFrançois Tigeot /* This is a requirement according to Hardware specification */ 11311487f786SFrançois Tigeot if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1)) 1132352ff8bdSFrançois Tigeot I915_WRITE(TILECTL, I915_READ(TILECTL) | TILECTL_TLBPF); 1133352ff8bdSFrançois Tigeot 1134352ff8bdSFrançois Tigeot /* WaSetClckGatingDisableMedia:bxt */ 11351487f786SFrançois Tigeot if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1)) { 1136352ff8bdSFrançois Tigeot I915_WRITE(GEN7_MISCCPCTL, (I915_READ(GEN7_MISCCPCTL) & 1137352ff8bdSFrançois Tigeot ~GEN8_DOP_CLOCK_GATE_MEDIA_ENABLE)); 1138352ff8bdSFrançois Tigeot } 113919c468b4SFrançois Tigeot 114019c468b4SFrançois Tigeot /* WaDisableThreadStallDopClockGating:bxt */ 114119c468b4SFrançois Tigeot WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN, 114219c468b4SFrançois Tigeot STALL_DOP_GATING_DISABLE); 114319c468b4SFrançois Tigeot 11441487f786SFrançois Tigeot /* WaDisablePooledEuLoadBalancingFix:bxt */ 11451487f786SFrançois Tigeot if (IS_BXT_REVID(dev_priv, BXT_REVID_B0, REVID_FOREVER)) { 11461487f786SFrançois Tigeot WA_SET_BIT_MASKED(FF_SLICE_CS_CHICKEN2, 11471487f786SFrançois Tigeot GEN9_POOLED_EU_LOAD_BALANCING_FIX_DISABLE); 11481487f786SFrançois Tigeot } 11491487f786SFrançois Tigeot 115019c468b4SFrançois Tigeot /* WaDisableSbeCacheDispatchPortSharing:bxt */ 11511487f786SFrançois Tigeot if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_B0)) { 115219c468b4SFrançois Tigeot WA_SET_BIT_MASKED( 115319c468b4SFrançois Tigeot GEN7_HALF_SLICE_CHICKEN1, 115419c468b4SFrançois Tigeot GEN7_SBE_SS_CACHE_DISPATCH_PORT_SHARING_DISABLE); 115519c468b4SFrançois Tigeot } 115619c468b4SFrançois Tigeot 1157c0e85e96SFrançois Tigeot /* WaDisableObjectLevelPreemptionForTrifanOrPolygon:bxt */ 1158c0e85e96SFrançois Tigeot /* WaDisableObjectLevelPreemptionForInstancedDraw:bxt */ 1159c0e85e96SFrançois Tigeot /* WaDisableObjectLevelPreemtionForInstanceId:bxt */ 1160c0e85e96SFrançois Tigeot /* WaDisableLSQCROPERFforOCL:bxt */ 11611487f786SFrançois Tigeot if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1)) { 11628621f407SFrançois Tigeot ret = wa_ring_whitelist_reg(engine, GEN9_CS_DEBUG_MODE1); 1163c0e85e96SFrançois Tigeot if (ret) 1164c0e85e96SFrançois Tigeot return ret; 1165c0e85e96SFrançois Tigeot 11668621f407SFrançois Tigeot ret = wa_ring_whitelist_reg(engine, GEN8_L3SQCREG4); 1167c0e85e96SFrançois Tigeot if (ret) 1168c0e85e96SFrançois Tigeot return ret; 1169c0e85e96SFrançois Tigeot } 1170c0e85e96SFrançois Tigeot 11711487f786SFrançois Tigeot /* WaProgramL3SqcReg1DefaultForPerf:bxt */ 11721487f786SFrançois Tigeot if (IS_BXT_REVID(dev_priv, BXT_REVID_B0, REVID_FOREVER)) 11731487f786SFrançois Tigeot I915_WRITE(GEN8_L3SQCREG1, L3_GENERAL_PRIO_CREDITS(62) | 11741487f786SFrançois Tigeot L3_HIGH_PRIO_CREDITS(2)); 11751487f786SFrançois Tigeot 11768621f407SFrançois Tigeot /* WaInsertDummyPushConstPs:bxt */ 11778621f407SFrançois Tigeot if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_B0)) 11788621f407SFrançois Tigeot WA_SET_BIT_MASKED(COMMON_SLICE_CHICKEN2, 11798621f407SFrançois Tigeot GEN8_SBE_DISABLE_REPLAY_BUF_OPTIMIZATION); 11808621f407SFrançois Tigeot 118119c468b4SFrançois Tigeot return 0; 118219c468b4SFrançois Tigeot } 118319c468b4SFrançois Tigeot 11848621f407SFrançois Tigeot static int kbl_init_workarounds(struct intel_engine_cs *engine) 11852c9916cdSFrançois Tigeot { 11861487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 11878621f407SFrançois Tigeot int ret; 11888621f407SFrançois Tigeot 11898621f407SFrançois Tigeot ret = gen9_init_workarounds(engine); 11908621f407SFrançois Tigeot if (ret) 11918621f407SFrançois Tigeot return ret; 11928621f407SFrançois Tigeot 11938621f407SFrançois Tigeot /* WaEnableGapsTsvCreditFix:kbl */ 11948621f407SFrançois Tigeot I915_WRITE(GEN8_GARBCNTL, (I915_READ(GEN8_GARBCNTL) | 11958621f407SFrançois Tigeot GEN9_GAPS_TSV_CREDIT_DISABLE)); 11968621f407SFrançois Tigeot 11978621f407SFrançois Tigeot /* WaDisableDynamicCreditSharing:kbl */ 11988621f407SFrançois Tigeot if (IS_KBL_REVID(dev_priv, 0, KBL_REVID_B0)) 11998621f407SFrançois Tigeot WA_SET_BIT(GAMT_CHKN_BIT_REG, 12008621f407SFrançois Tigeot GAMT_CHKN_DISABLE_DYNAMIC_CREDIT_SHARING); 12018621f407SFrançois Tigeot 12028621f407SFrançois Tigeot /* WaDisableFenceDestinationToSLM:kbl (pre-prod) */ 12038621f407SFrançois Tigeot if (IS_KBL_REVID(dev_priv, KBL_REVID_A0, KBL_REVID_A0)) 12048621f407SFrançois Tigeot WA_SET_BIT_MASKED(HDC_CHICKEN0, 12058621f407SFrançois Tigeot HDC_FENCE_DEST_SLM_DISABLE); 12068621f407SFrançois Tigeot 12078621f407SFrançois Tigeot /* GEN8_L3SQCREG4 has a dependency with WA batch so any new changes 12088621f407SFrançois Tigeot * involving this register should also be added to WA batch as required. 12098621f407SFrançois Tigeot */ 12108621f407SFrançois Tigeot if (IS_KBL_REVID(dev_priv, 0, KBL_REVID_E0)) 12118621f407SFrançois Tigeot /* WaDisableLSQCROPERFforOCL:kbl */ 12128621f407SFrançois Tigeot I915_WRITE(GEN8_L3SQCREG4, I915_READ(GEN8_L3SQCREG4) | 12138621f407SFrançois Tigeot GEN8_LQSC_RO_PERF_DIS); 12148621f407SFrançois Tigeot 12158621f407SFrançois Tigeot /* WaInsertDummyPushConstPs:kbl */ 12168621f407SFrançois Tigeot if (IS_KBL_REVID(dev_priv, 0, KBL_REVID_B0)) 12178621f407SFrançois Tigeot WA_SET_BIT_MASKED(COMMON_SLICE_CHICKEN2, 12188621f407SFrançois Tigeot GEN8_SBE_DISABLE_REPLAY_BUF_OPTIMIZATION); 12198621f407SFrançois Tigeot 12208621f407SFrançois Tigeot /* WaDisableGafsUnitClkGating:kbl */ 12218621f407SFrançois Tigeot WA_SET_BIT(GEN7_UCGCTL4, GEN8_EU_GAUNIT_CLOCK_GATE_DISABLE); 12228621f407SFrançois Tigeot 12238621f407SFrançois Tigeot /* WaDisableSbeCacheDispatchPortSharing:kbl */ 12248621f407SFrançois Tigeot WA_SET_BIT_MASKED( 12258621f407SFrançois Tigeot GEN7_HALF_SLICE_CHICKEN1, 12268621f407SFrançois Tigeot GEN7_SBE_SS_CACHE_DISPATCH_PORT_SHARING_DISABLE); 12278621f407SFrançois Tigeot 12288621f407SFrançois Tigeot /* WaDisableLSQCROPERFforOCL:kbl */ 12298621f407SFrançois Tigeot ret = wa_ring_whitelist_reg(engine, GEN8_L3SQCREG4); 12308621f407SFrançois Tigeot if (ret) 12318621f407SFrançois Tigeot return ret; 12328621f407SFrançois Tigeot 12338621f407SFrançois Tigeot return 0; 12348621f407SFrançois Tigeot } 12358621f407SFrançois Tigeot 12368621f407SFrançois Tigeot int init_workarounds_ring(struct intel_engine_cs *engine) 12378621f407SFrançois Tigeot { 12381487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 12392c9916cdSFrançois Tigeot 12408621f407SFrançois Tigeot WARN_ON(engine->id != RCS); 12412c9916cdSFrançois Tigeot 12422c9916cdSFrançois Tigeot dev_priv->workarounds.count = 0; 1243c0e85e96SFrançois Tigeot dev_priv->workarounds.hw_whitelist_count[RCS] = 0; 12442c9916cdSFrançois Tigeot 12451487f786SFrançois Tigeot if (IS_BROADWELL(dev_priv)) 12468621f407SFrançois Tigeot return bdw_init_workarounds(engine); 12472c9916cdSFrançois Tigeot 12481487f786SFrançois Tigeot if (IS_CHERRYVIEW(dev_priv)) 12498621f407SFrançois Tigeot return chv_init_workarounds(engine); 12501b13d190SFrançois Tigeot 12511487f786SFrançois Tigeot if (IS_SKYLAKE(dev_priv)) 12528621f407SFrançois Tigeot return skl_init_workarounds(engine); 125319c468b4SFrançois Tigeot 12541487f786SFrançois Tigeot if (IS_BROXTON(dev_priv)) 12558621f407SFrançois Tigeot return bxt_init_workarounds(engine); 12568621f407SFrançois Tigeot 12578621f407SFrançois Tigeot if (IS_KABYLAKE(dev_priv)) 12588621f407SFrançois Tigeot return kbl_init_workarounds(engine); 1259477eb7f9SFrançois Tigeot 12601b13d190SFrançois Tigeot return 0; 12611b13d190SFrançois Tigeot } 12621b13d190SFrançois Tigeot 12638621f407SFrançois Tigeot static int init_render_ring(struct intel_engine_cs *engine) 1264e3adcf8fSFrançois Tigeot { 12651487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 12668621f407SFrançois Tigeot int ret = init_ring_common(engine); 126724edb884SFrançois Tigeot if (ret) 126824edb884SFrançois Tigeot return ret; 1269e3adcf8fSFrançois Tigeot 1270ba55f2f5SFrançois Tigeot /* WaTimedSingleVertexDispatch:cl,bw,ctg,elk,ilk,snb */ 12711487f786SFrançois Tigeot if (IS_GEN(dev_priv, 4, 6)) 1272f4e1c372SFrançois Tigeot I915_WRITE(MI_MODE, _MASKED_BIT_ENABLE(VS_TIMER_DISPATCH)); 1273f4e1c372SFrançois Tigeot 1274f4e1c372SFrançois Tigeot /* We need to disable the AsyncFlip performance optimisations in order 1275f4e1c372SFrançois Tigeot * to use MI_WAIT_FOR_EVENT within the CS. It should already be 1276f4e1c372SFrançois Tigeot * programmed to '1' on all products. 12775d0b1887SFrançois Tigeot * 1278a05eeebfSFrançois Tigeot * WaDisableAsyncFlipPerfMode:snb,ivb,hsw,vlv 1279f4e1c372SFrançois Tigeot */ 12801487f786SFrançois Tigeot if (IS_GEN(dev_priv, 6, 7)) 1281f4e1c372SFrançois Tigeot I915_WRITE(MI_MODE, _MASKED_BIT_ENABLE(ASYNC_FLIP_PERF_DISABLE)); 1282f4e1c372SFrançois Tigeot 1283f4e1c372SFrançois Tigeot /* Required for the hardware to program scanline values for waiting */ 1284ba55f2f5SFrançois Tigeot /* WaEnableFlushTlbInvalidationMode:snb */ 12851487f786SFrançois Tigeot if (IS_GEN6(dev_priv)) 1286f4e1c372SFrançois Tigeot I915_WRITE(GFX_MODE, 1287ba55f2f5SFrançois Tigeot _MASKED_BIT_ENABLE(GFX_TLB_INVALIDATE_EXPLICIT)); 1288f4e1c372SFrançois Tigeot 1289ba55f2f5SFrançois Tigeot /* WaBCSVCSTlbInvalidationMode:ivb,vlv,hsw */ 12901487f786SFrançois Tigeot if (IS_GEN7(dev_priv)) 1291e3adcf8fSFrançois Tigeot I915_WRITE(GFX_MODE_GEN7, 1292ba55f2f5SFrançois Tigeot _MASKED_BIT_ENABLE(GFX_TLB_INVALIDATE_EXPLICIT) | 1293f4e1c372SFrançois Tigeot _MASKED_BIT_ENABLE(GFX_REPLAY_MODE)); 1294e3adcf8fSFrançois Tigeot 12951487f786SFrançois Tigeot if (IS_GEN6(dev_priv)) { 1296e3adcf8fSFrançois Tigeot /* From the Sandybridge PRM, volume 1 part 3, page 24: 1297e3adcf8fSFrançois Tigeot * "If this bit is set, STCunit will have LRA as replacement 1298e3adcf8fSFrançois Tigeot * policy. [...] This bit must be reset. LRA replacement 1299e3adcf8fSFrançois Tigeot * policy is not supported." 1300e3adcf8fSFrançois Tigeot */ 1301e3adcf8fSFrançois Tigeot I915_WRITE(CACHE_MODE_0, 1302f4e1c372SFrançois Tigeot _MASKED_BIT_DISABLE(CM0_STC_EVICT_DISABLE_LRA_SNB)); 1303e3adcf8fSFrançois Tigeot } 1304e3adcf8fSFrançois Tigeot 13051487f786SFrançois Tigeot if (IS_GEN(dev_priv, 6, 7)) 1306f4e1c372SFrançois Tigeot I915_WRITE(INSTPM, _MASKED_BIT_ENABLE(INSTPM_FORCE_ORDERING)); 1307f4e1c372SFrançois Tigeot 1308*303bf270SFrançois Tigeot if (INTEL_INFO(dev_priv)->gen >= 6) 1309*303bf270SFrançois Tigeot I915_WRITE_IMR(engine, ~engine->irq_keep_mask); 1310e3adcf8fSFrançois Tigeot 13118621f407SFrançois Tigeot return init_workarounds_ring(engine); 1312e3adcf8fSFrançois Tigeot } 1313e3adcf8fSFrançois Tigeot 13148621f407SFrançois Tigeot static void render_ring_cleanup(struct intel_engine_cs *engine) 1315e3adcf8fSFrançois Tigeot { 13161487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 131724edb884SFrançois Tigeot 131824edb884SFrançois Tigeot if (dev_priv->semaphore_obj) { 131924edb884SFrançois Tigeot i915_gem_object_ggtt_unpin(dev_priv->semaphore_obj); 132024edb884SFrançois Tigeot drm_gem_object_unreference(&dev_priv->semaphore_obj->base); 132124edb884SFrançois Tigeot dev_priv->semaphore_obj = NULL; 132224edb884SFrançois Tigeot } 1323b5c29a34SFrançois Tigeot 13248621f407SFrançois Tigeot intel_fini_pipe_control(engine); 1325e3adcf8fSFrançois Tigeot } 1326e3adcf8fSFrançois Tigeot 1327a05eeebfSFrançois Tigeot static int gen8_rcs_signal(struct drm_i915_gem_request *signaller_req, 132824edb884SFrançois Tigeot unsigned int num_dwords) 132924edb884SFrançois Tigeot { 133024edb884SFrançois Tigeot #define MBOX_UPDATE_DWORDS 8 13318621f407SFrançois Tigeot struct intel_engine_cs *signaller = signaller_req->engine; 13321487f786SFrançois Tigeot struct drm_i915_private *dev_priv = signaller_req->i915; 133324edb884SFrançois Tigeot struct intel_engine_cs *waiter; 13348621f407SFrançois Tigeot enum intel_engine_id id; 13358621f407SFrançois Tigeot int ret, num_rings; 133624edb884SFrançois Tigeot 13371487f786SFrançois Tigeot num_rings = hweight32(INTEL_INFO(dev_priv)->ring_mask); 133824edb884SFrançois Tigeot num_dwords += (num_rings-1) * MBOX_UPDATE_DWORDS; 133924edb884SFrançois Tigeot #undef MBOX_UPDATE_DWORDS 134024edb884SFrançois Tigeot 1341a05eeebfSFrançois Tigeot ret = intel_ring_begin(signaller_req, num_dwords); 134224edb884SFrançois Tigeot if (ret) 134324edb884SFrançois Tigeot return ret; 134424edb884SFrançois Tigeot 13458621f407SFrançois Tigeot for_each_engine_id(waiter, dev_priv, id) { 13468621f407SFrançois Tigeot u64 gtt_offset = signaller->semaphore.signal_ggtt[id]; 134724edb884SFrançois Tigeot if (gtt_offset == MI_SEMAPHORE_SYNC_INVALID) 134824edb884SFrançois Tigeot continue; 134924edb884SFrançois Tigeot 135024edb884SFrançois Tigeot intel_ring_emit(signaller, GFX_OP_PIPE_CONTROL(6)); 135124edb884SFrançois Tigeot intel_ring_emit(signaller, PIPE_CONTROL_GLOBAL_GTT_IVB | 135224edb884SFrançois Tigeot PIPE_CONTROL_QW_WRITE | 13531487f786SFrançois Tigeot PIPE_CONTROL_CS_STALL); 135424edb884SFrançois Tigeot intel_ring_emit(signaller, lower_32_bits(gtt_offset)); 135524edb884SFrançois Tigeot intel_ring_emit(signaller, upper_32_bits(gtt_offset)); 1356*303bf270SFrançois Tigeot intel_ring_emit(signaller, signaller_req->seqno); 135724edb884SFrançois Tigeot intel_ring_emit(signaller, 0); 135824edb884SFrançois Tigeot intel_ring_emit(signaller, MI_SEMAPHORE_SIGNAL | 13598621f407SFrançois Tigeot MI_SEMAPHORE_TARGET(waiter->hw_id)); 136024edb884SFrançois Tigeot intel_ring_emit(signaller, 0); 136124edb884SFrançois Tigeot } 136224edb884SFrançois Tigeot 136324edb884SFrançois Tigeot return 0; 136424edb884SFrançois Tigeot } 136524edb884SFrançois Tigeot 1366a05eeebfSFrançois Tigeot static int gen8_xcs_signal(struct drm_i915_gem_request *signaller_req, 136724edb884SFrançois Tigeot unsigned int num_dwords) 136824edb884SFrançois Tigeot { 136924edb884SFrançois Tigeot #define MBOX_UPDATE_DWORDS 6 13708621f407SFrançois Tigeot struct intel_engine_cs *signaller = signaller_req->engine; 13711487f786SFrançois Tigeot struct drm_i915_private *dev_priv = signaller_req->i915; 137224edb884SFrançois Tigeot struct intel_engine_cs *waiter; 13738621f407SFrançois Tigeot enum intel_engine_id id; 13748621f407SFrançois Tigeot int ret, num_rings; 137524edb884SFrançois Tigeot 13761487f786SFrançois Tigeot num_rings = hweight32(INTEL_INFO(dev_priv)->ring_mask); 137724edb884SFrançois Tigeot num_dwords += (num_rings-1) * MBOX_UPDATE_DWORDS; 137824edb884SFrançois Tigeot #undef MBOX_UPDATE_DWORDS 137924edb884SFrançois Tigeot 1380a05eeebfSFrançois Tigeot ret = intel_ring_begin(signaller_req, num_dwords); 138124edb884SFrançois Tigeot if (ret) 138224edb884SFrançois Tigeot return ret; 138324edb884SFrançois Tigeot 13848621f407SFrançois Tigeot for_each_engine_id(waiter, dev_priv, id) { 13858621f407SFrançois Tigeot u64 gtt_offset = signaller->semaphore.signal_ggtt[id]; 138624edb884SFrançois Tigeot if (gtt_offset == MI_SEMAPHORE_SYNC_INVALID) 138724edb884SFrançois Tigeot continue; 138824edb884SFrançois Tigeot 138924edb884SFrançois Tigeot intel_ring_emit(signaller, (MI_FLUSH_DW + 1) | 139024edb884SFrançois Tigeot MI_FLUSH_DW_OP_STOREDW); 139124edb884SFrançois Tigeot intel_ring_emit(signaller, lower_32_bits(gtt_offset) | 139224edb884SFrançois Tigeot MI_FLUSH_DW_USE_GTT); 139324edb884SFrançois Tigeot intel_ring_emit(signaller, upper_32_bits(gtt_offset)); 1394*303bf270SFrançois Tigeot intel_ring_emit(signaller, signaller_req->seqno); 139524edb884SFrançois Tigeot intel_ring_emit(signaller, MI_SEMAPHORE_SIGNAL | 13968621f407SFrançois Tigeot MI_SEMAPHORE_TARGET(waiter->hw_id)); 139724edb884SFrançois Tigeot intel_ring_emit(signaller, 0); 139824edb884SFrançois Tigeot } 139924edb884SFrançois Tigeot 140024edb884SFrançois Tigeot return 0; 140124edb884SFrançois Tigeot } 140224edb884SFrançois Tigeot 1403a05eeebfSFrançois Tigeot static int gen6_signal(struct drm_i915_gem_request *signaller_req, 1404ba55f2f5SFrançois Tigeot unsigned int num_dwords) 1405e3adcf8fSFrançois Tigeot { 14068621f407SFrançois Tigeot struct intel_engine_cs *signaller = signaller_req->engine; 14071487f786SFrançois Tigeot struct drm_i915_private *dev_priv = signaller_req->i915; 1408ba55f2f5SFrançois Tigeot struct intel_engine_cs *useless; 14098621f407SFrançois Tigeot enum intel_engine_id id; 14108621f407SFrançois Tigeot int ret, num_rings; 1411ba55f2f5SFrançois Tigeot 141224edb884SFrançois Tigeot #define MBOX_UPDATE_DWORDS 3 14131487f786SFrançois Tigeot num_rings = hweight32(INTEL_INFO(dev_priv)->ring_mask); 141424edb884SFrançois Tigeot num_dwords += round_up((num_rings-1) * MBOX_UPDATE_DWORDS, 2); 141524edb884SFrançois Tigeot #undef MBOX_UPDATE_DWORDS 1416ba55f2f5SFrançois Tigeot 1417a05eeebfSFrançois Tigeot ret = intel_ring_begin(signaller_req, num_dwords); 1418ba55f2f5SFrançois Tigeot if (ret) 1419ba55f2f5SFrançois Tigeot return ret; 1420ba55f2f5SFrançois Tigeot 14218621f407SFrançois Tigeot for_each_engine_id(useless, dev_priv, id) { 14228621f407SFrançois Tigeot i915_reg_t mbox_reg = signaller->semaphore.mbox.signal[id]; 1423aee94f86SFrançois Tigeot 1424aee94f86SFrançois Tigeot if (i915_mmio_reg_valid(mbox_reg)) { 1425ba55f2f5SFrançois Tigeot intel_ring_emit(signaller, MI_LOAD_REGISTER_IMM(1)); 1426aee94f86SFrançois Tigeot intel_ring_emit_reg(signaller, mbox_reg); 1427*303bf270SFrançois Tigeot intel_ring_emit(signaller, signaller_req->seqno); 1428ba55f2f5SFrançois Tigeot } 1429ba55f2f5SFrançois Tigeot } 1430ba55f2f5SFrançois Tigeot 143124edb884SFrançois Tigeot /* If num_dwords was rounded, make sure the tail pointer is correct */ 143224edb884SFrançois Tigeot if (num_rings % 2 == 0) 143324edb884SFrançois Tigeot intel_ring_emit(signaller, MI_NOOP); 143424edb884SFrançois Tigeot 1435ba55f2f5SFrançois Tigeot return 0; 1436e3adcf8fSFrançois Tigeot } 1437e3adcf8fSFrançois Tigeot 1438e3adcf8fSFrançois Tigeot /** 1439e3adcf8fSFrançois Tigeot * gen6_add_request - Update the semaphore mailbox registers 1440e3adcf8fSFrançois Tigeot * 1441a05eeebfSFrançois Tigeot * @request - request to write to the ring 1442e3adcf8fSFrançois Tigeot * 1443e3adcf8fSFrançois Tigeot * Update the mailbox registers in the *other* rings with the current seqno. 1444e3adcf8fSFrançois Tigeot * This acts like a signal in the canonical semaphore. 1445e3adcf8fSFrançois Tigeot */ 1446e3adcf8fSFrançois Tigeot static int 1447a05eeebfSFrançois Tigeot gen6_add_request(struct drm_i915_gem_request *req) 1448e3adcf8fSFrançois Tigeot { 14498621f407SFrançois Tigeot struct intel_engine_cs *engine = req->engine; 1450ba55f2f5SFrançois Tigeot int ret; 1451e3adcf8fSFrançois Tigeot 14528621f407SFrançois Tigeot if (engine->semaphore.signal) 14538621f407SFrançois Tigeot ret = engine->semaphore.signal(req, 4); 145424edb884SFrançois Tigeot else 1455a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 4); 145624edb884SFrançois Tigeot 14579edbd4a0SFrançois Tigeot if (ret) 14589edbd4a0SFrançois Tigeot return ret; 14599edbd4a0SFrançois Tigeot 14608621f407SFrançois Tigeot intel_ring_emit(engine, MI_STORE_DWORD_INDEX); 14618621f407SFrançois Tigeot intel_ring_emit(engine, 14628621f407SFrançois Tigeot I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT); 1463*303bf270SFrançois Tigeot intel_ring_emit(engine, req->seqno); 14648621f407SFrançois Tigeot intel_ring_emit(engine, MI_USER_INTERRUPT); 14658621f407SFrançois Tigeot __intel_ring_advance(engine); 1466e3adcf8fSFrançois Tigeot 1467e3adcf8fSFrançois Tigeot return 0; 1468e3adcf8fSFrançois Tigeot } 1469e3adcf8fSFrançois Tigeot 14701487f786SFrançois Tigeot static int 14711487f786SFrançois Tigeot gen8_render_add_request(struct drm_i915_gem_request *req) 14721487f786SFrançois Tigeot { 14731487f786SFrançois Tigeot struct intel_engine_cs *engine = req->engine; 14741487f786SFrançois Tigeot int ret; 14751487f786SFrançois Tigeot 14761487f786SFrançois Tigeot if (engine->semaphore.signal) 14771487f786SFrançois Tigeot ret = engine->semaphore.signal(req, 8); 14781487f786SFrançois Tigeot else 14791487f786SFrançois Tigeot ret = intel_ring_begin(req, 8); 14801487f786SFrançois Tigeot if (ret) 14811487f786SFrançois Tigeot return ret; 14821487f786SFrançois Tigeot 14831487f786SFrançois Tigeot intel_ring_emit(engine, GFX_OP_PIPE_CONTROL(6)); 14841487f786SFrançois Tigeot intel_ring_emit(engine, (PIPE_CONTROL_GLOBAL_GTT_IVB | 14851487f786SFrançois Tigeot PIPE_CONTROL_CS_STALL | 14861487f786SFrançois Tigeot PIPE_CONTROL_QW_WRITE)); 14871487f786SFrançois Tigeot intel_ring_emit(engine, intel_hws_seqno_address(req->engine)); 14881487f786SFrançois Tigeot intel_ring_emit(engine, 0); 14891487f786SFrançois Tigeot intel_ring_emit(engine, i915_gem_request_get_seqno(req)); 14901487f786SFrançois Tigeot /* We're thrashing one dword of HWS. */ 14911487f786SFrançois Tigeot intel_ring_emit(engine, 0); 14921487f786SFrançois Tigeot intel_ring_emit(engine, MI_USER_INTERRUPT); 14931487f786SFrançois Tigeot intel_ring_emit(engine, MI_NOOP); 14941487f786SFrançois Tigeot __intel_ring_advance(engine); 14951487f786SFrançois Tigeot 14961487f786SFrançois Tigeot return 0; 14971487f786SFrançois Tigeot } 14981487f786SFrançois Tigeot 14991487f786SFrançois Tigeot static inline bool i915_gem_has_seqno_wrapped(struct drm_i915_private *dev_priv, 1500a2fdbec6SFrançois Tigeot u32 seqno) 1501a2fdbec6SFrançois Tigeot { 1502a2fdbec6SFrançois Tigeot return dev_priv->last_seqno < seqno; 1503a2fdbec6SFrançois Tigeot } 1504a2fdbec6SFrançois Tigeot 1505e3adcf8fSFrançois Tigeot /** 1506e3adcf8fSFrançois Tigeot * intel_ring_sync - sync the waiter to the signaller on seqno 1507e3adcf8fSFrançois Tigeot * 1508e3adcf8fSFrançois Tigeot * @waiter - ring that is waiting 1509e3adcf8fSFrançois Tigeot * @signaller - ring which has, or will signal 1510e3adcf8fSFrançois Tigeot * @seqno - seqno which the waiter will block on 1511e3adcf8fSFrançois Tigeot */ 151224edb884SFrançois Tigeot 151324edb884SFrançois Tigeot static int 1514a05eeebfSFrançois Tigeot gen8_ring_sync(struct drm_i915_gem_request *waiter_req, 151524edb884SFrançois Tigeot struct intel_engine_cs *signaller, 151624edb884SFrançois Tigeot u32 seqno) 151724edb884SFrançois Tigeot { 15188621f407SFrançois Tigeot struct intel_engine_cs *waiter = waiter_req->engine; 15191487f786SFrançois Tigeot struct drm_i915_private *dev_priv = waiter_req->i915; 15201487f786SFrançois Tigeot u64 offset = GEN8_WAIT_OFFSET(waiter, signaller->id); 15211487f786SFrançois Tigeot struct i915_hw_ppgtt *ppgtt; 152224edb884SFrançois Tigeot int ret; 152324edb884SFrançois Tigeot 1524a05eeebfSFrançois Tigeot ret = intel_ring_begin(waiter_req, 4); 152524edb884SFrançois Tigeot if (ret) 152624edb884SFrançois Tigeot return ret; 152724edb884SFrançois Tigeot 152824edb884SFrançois Tigeot intel_ring_emit(waiter, MI_SEMAPHORE_WAIT | 152924edb884SFrançois Tigeot MI_SEMAPHORE_GLOBAL_GTT | 153024edb884SFrançois Tigeot MI_SEMAPHORE_SAD_GTE_SDD); 153124edb884SFrançois Tigeot intel_ring_emit(waiter, seqno); 15321487f786SFrançois Tigeot intel_ring_emit(waiter, lower_32_bits(offset)); 15331487f786SFrançois Tigeot intel_ring_emit(waiter, upper_32_bits(offset)); 153424edb884SFrançois Tigeot intel_ring_advance(waiter); 15351487f786SFrançois Tigeot 15361487f786SFrançois Tigeot /* When the !RCS engines idle waiting upon a semaphore, they lose their 15371487f786SFrançois Tigeot * pagetables and we must reload them before executing the batch. 15381487f786SFrançois Tigeot * We do this on the i915_switch_context() following the wait and 15391487f786SFrançois Tigeot * before the dispatch. 15401487f786SFrançois Tigeot */ 15411487f786SFrançois Tigeot ppgtt = waiter_req->ctx->ppgtt; 15421487f786SFrançois Tigeot if (ppgtt && waiter_req->engine->id != RCS) 15431487f786SFrançois Tigeot ppgtt->pd_dirty_rings |= intel_engine_flag(waiter_req->engine); 154424edb884SFrançois Tigeot return 0; 154524edb884SFrançois Tigeot } 154624edb884SFrançois Tigeot 1547e3adcf8fSFrançois Tigeot static int 1548a05eeebfSFrançois Tigeot gen6_ring_sync(struct drm_i915_gem_request *waiter_req, 1549ba55f2f5SFrançois Tigeot struct intel_engine_cs *signaller, 1550e3adcf8fSFrançois Tigeot u32 seqno) 1551e3adcf8fSFrançois Tigeot { 15528621f407SFrançois Tigeot struct intel_engine_cs *waiter = waiter_req->engine; 1553e3adcf8fSFrançois Tigeot u32 dw1 = MI_SEMAPHORE_MBOX | 1554e3adcf8fSFrançois Tigeot MI_SEMAPHORE_COMPARE | 1555e3adcf8fSFrançois Tigeot MI_SEMAPHORE_REGISTER; 1556ba55f2f5SFrançois Tigeot u32 wait_mbox = signaller->semaphore.mbox.wait[waiter->id]; 1557ba55f2f5SFrançois Tigeot int ret; 1558e3adcf8fSFrançois Tigeot 1559686a02f1SFrançois Tigeot /* Throughout all of the GEM code, seqno passed implies our current 1560686a02f1SFrançois Tigeot * seqno is >= the last seqno executed. However for hardware the 1561686a02f1SFrançois Tigeot * comparison is strictly greater than. 1562686a02f1SFrançois Tigeot */ 1563686a02f1SFrançois Tigeot seqno -= 1; 1564686a02f1SFrançois Tigeot 1565ba55f2f5SFrançois Tigeot WARN_ON(wait_mbox == MI_SEMAPHORE_SYNC_INVALID); 1566686a02f1SFrançois Tigeot 1567a05eeebfSFrançois Tigeot ret = intel_ring_begin(waiter_req, 4); 1568e3adcf8fSFrançois Tigeot if (ret) 1569e3adcf8fSFrançois Tigeot return ret; 1570e3adcf8fSFrançois Tigeot 1571a2fdbec6SFrançois Tigeot /* If seqno wrap happened, omit the wait with no-ops */ 15721487f786SFrançois Tigeot if (likely(!i915_gem_has_seqno_wrapped(waiter_req->i915, seqno))) { 1573ba55f2f5SFrançois Tigeot intel_ring_emit(waiter, dw1 | wait_mbox); 1574e3adcf8fSFrançois Tigeot intel_ring_emit(waiter, seqno); 1575e3adcf8fSFrançois Tigeot intel_ring_emit(waiter, 0); 1576e3adcf8fSFrançois Tigeot intel_ring_emit(waiter, MI_NOOP); 1577a2fdbec6SFrançois Tigeot } else { 1578a2fdbec6SFrançois Tigeot intel_ring_emit(waiter, MI_NOOP); 1579a2fdbec6SFrançois Tigeot intel_ring_emit(waiter, MI_NOOP); 1580a2fdbec6SFrançois Tigeot intel_ring_emit(waiter, MI_NOOP); 1581a2fdbec6SFrançois Tigeot intel_ring_emit(waiter, MI_NOOP); 1582a2fdbec6SFrançois Tigeot } 1583e3adcf8fSFrançois Tigeot intel_ring_advance(waiter); 1584e3adcf8fSFrançois Tigeot 1585e3adcf8fSFrançois Tigeot return 0; 1586e3adcf8fSFrançois Tigeot } 1587e3adcf8fSFrançois Tigeot 1588*303bf270SFrançois Tigeot static void 1589*303bf270SFrançois Tigeot gen5_seqno_barrier(struct intel_engine_cs *ring) 1590e3adcf8fSFrançois Tigeot { 1591*303bf270SFrançois Tigeot /* MI_STORE are internally buffered by the GPU and not flushed 1592*303bf270SFrançois Tigeot * either by MI_FLUSH or SyncFlush or any other combination of 1593*303bf270SFrançois Tigeot * MI commands. 1594e3adcf8fSFrançois Tigeot * 1595*303bf270SFrançois Tigeot * "Only the submission of the store operation is guaranteed. 1596*303bf270SFrançois Tigeot * The write result will be complete (coherent) some time later 1597*303bf270SFrançois Tigeot * (this is practically a finite period but there is no guaranteed 1598*303bf270SFrançois Tigeot * latency)." 1599*303bf270SFrançois Tigeot * 1600*303bf270SFrançois Tigeot * Empirically, we observe that we need a delay of at least 75us to 1601*303bf270SFrançois Tigeot * be sure that the seqno write is visible by the CPU. 1602e3adcf8fSFrançois Tigeot */ 1603*303bf270SFrançois Tigeot usleep_range(125, 250); 1604e3adcf8fSFrançois Tigeot } 1605e3adcf8fSFrançois Tigeot 16068621f407SFrançois Tigeot static void 16078621f407SFrançois Tigeot gen6_seqno_barrier(struct intel_engine_cs *engine) 1608e3adcf8fSFrançois Tigeot { 16091487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 16108621f407SFrançois Tigeot 1611e3adcf8fSFrançois Tigeot /* Workaround to force correct ordering between irq and seqno writes on 1612e3adcf8fSFrançois Tigeot * ivb (and maybe also on snb) by reading from a CS register (like 16138621f407SFrançois Tigeot * ACTHD) before reading the status page. 16148621f407SFrançois Tigeot * 16158621f407SFrançois Tigeot * Note that this effectively stalls the read by the time it takes to 16168621f407SFrançois Tigeot * do a memory transaction, which more or less ensures that the write 16178621f407SFrançois Tigeot * from the GPU has sufficient time to invalidate the CPU cacheline. 16188621f407SFrançois Tigeot * Alternatively we could delay the interrupt from the CS ring to give 16198621f407SFrançois Tigeot * the write time to land, but that would incur a delay after every 16208621f407SFrançois Tigeot * batch i.e. much more frequent than a delay when waiting for the 16218621f407SFrançois Tigeot * interrupt (with the same net latency). 16228621f407SFrançois Tigeot * 16238621f407SFrançois Tigeot * Also note that to prevent whole machine hangs on gen7, we have to 16248621f407SFrançois Tigeot * take the spinlock to guard against concurrent cacheline access. 16258621f407SFrançois Tigeot */ 16268621f407SFrançois Tigeot spin_lock_irq(&dev_priv->uncore.lock); 16278621f407SFrançois Tigeot POSTING_READ_FW(RING_ACTHD(engine->mmio_base)); 16288621f407SFrançois Tigeot spin_unlock_irq(&dev_priv->uncore.lock); 1629e3adcf8fSFrançois Tigeot } 1630e3adcf8fSFrançois Tigeot 1631*303bf270SFrançois Tigeot static void 1632*303bf270SFrançois Tigeot gen5_irq_enable(struct intel_engine_cs *engine) 1633e3adcf8fSFrançois Tigeot { 1634*303bf270SFrançois Tigeot gen5_enable_gt_irq(engine->i915, engine->irq_enable_mask); 1635e3adcf8fSFrançois Tigeot } 1636e3adcf8fSFrançois Tigeot 1637a2fdbec6SFrançois Tigeot static void 1638*303bf270SFrançois Tigeot gen5_irq_disable(struct intel_engine_cs *engine) 1639a2fdbec6SFrançois Tigeot { 1640*303bf270SFrançois Tigeot gen5_disable_gt_irq(engine->i915, engine->irq_enable_mask); 1641e3adcf8fSFrançois Tigeot } 1642e3adcf8fSFrançois Tigeot 1643a2fdbec6SFrançois Tigeot static void 1644*303bf270SFrançois Tigeot i9xx_irq_enable(struct intel_engine_cs *engine) 1645e3adcf8fSFrançois Tigeot { 16461487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 1647e3adcf8fSFrançois Tigeot 16488621f407SFrançois Tigeot dev_priv->irq_mask &= ~engine->irq_enable_mask; 1649686a02f1SFrançois Tigeot I915_WRITE(IMR, dev_priv->irq_mask); 1650*303bf270SFrançois Tigeot POSTING_READ_FW(RING_IMR(engine->mmio_base)); 1651686a02f1SFrançois Tigeot } 1652686a02f1SFrançois Tigeot 1653686a02f1SFrançois Tigeot static void 1654*303bf270SFrançois Tigeot i9xx_irq_disable(struct intel_engine_cs *engine) 1655686a02f1SFrançois Tigeot { 16561487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 1657686a02f1SFrançois Tigeot 16588621f407SFrançois Tigeot dev_priv->irq_mask |= engine->irq_enable_mask; 1659686a02f1SFrançois Tigeot I915_WRITE(IMR, dev_priv->irq_mask); 1660686a02f1SFrançois Tigeot } 1661686a02f1SFrançois Tigeot 1662686a02f1SFrançois Tigeot static void 1663*303bf270SFrançois Tigeot i8xx_irq_enable(struct intel_engine_cs *engine) 1664686a02f1SFrançois Tigeot { 16651487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 1666686a02f1SFrançois Tigeot 1667*303bf270SFrançois Tigeot dev_priv->irq_mask &= ~engine->irq_enable_mask; 1668*303bf270SFrançois Tigeot I915_WRITE16(IMR, dev_priv->irq_mask); 1669*303bf270SFrançois Tigeot POSTING_READ16(RING_IMR(engine->mmio_base)); 1670*303bf270SFrançois Tigeot } 1671*303bf270SFrançois Tigeot 1672*303bf270SFrançois Tigeot static void 1673*303bf270SFrançois Tigeot i8xx_irq_disable(struct intel_engine_cs *engine) 1674*303bf270SFrançois Tigeot { 1675*303bf270SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 1676*303bf270SFrançois Tigeot 16778621f407SFrançois Tigeot dev_priv->irq_mask |= engine->irq_enable_mask; 1678686a02f1SFrançois Tigeot I915_WRITE16(IMR, dev_priv->irq_mask); 1679e3adcf8fSFrançois Tigeot } 1680e3adcf8fSFrançois Tigeot 1681e3adcf8fSFrançois Tigeot static int 1682a05eeebfSFrançois Tigeot bsd_ring_flush(struct drm_i915_gem_request *req, 1683b5c29a34SFrançois Tigeot u32 invalidate_domains, 1684b5c29a34SFrançois Tigeot u32 flush_domains) 1685e3adcf8fSFrançois Tigeot { 16868621f407SFrançois Tigeot struct intel_engine_cs *engine = req->engine; 1687e3adcf8fSFrançois Tigeot int ret; 1688e3adcf8fSFrançois Tigeot 1689a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 2); 1690e3adcf8fSFrançois Tigeot if (ret) 1691e3adcf8fSFrançois Tigeot return ret; 1692e3adcf8fSFrançois Tigeot 16938621f407SFrançois Tigeot intel_ring_emit(engine, MI_FLUSH); 16948621f407SFrançois Tigeot intel_ring_emit(engine, MI_NOOP); 16958621f407SFrançois Tigeot intel_ring_advance(engine); 1696e3adcf8fSFrançois Tigeot return 0; 1697e3adcf8fSFrançois Tigeot } 1698e3adcf8fSFrançois Tigeot 1699e3adcf8fSFrançois Tigeot static int 1700a05eeebfSFrançois Tigeot i9xx_add_request(struct drm_i915_gem_request *req) 1701e3adcf8fSFrançois Tigeot { 17028621f407SFrançois Tigeot struct intel_engine_cs *engine = req->engine; 1703e3adcf8fSFrançois Tigeot int ret; 1704e3adcf8fSFrançois Tigeot 1705a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 4); 1706e3adcf8fSFrançois Tigeot if (ret) 1707e3adcf8fSFrançois Tigeot return ret; 1708e3adcf8fSFrançois Tigeot 17098621f407SFrançois Tigeot intel_ring_emit(engine, MI_STORE_DWORD_INDEX); 17108621f407SFrançois Tigeot intel_ring_emit(engine, 17118621f407SFrançois Tigeot I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT); 1712*303bf270SFrançois Tigeot intel_ring_emit(engine, req->seqno); 17138621f407SFrançois Tigeot intel_ring_emit(engine, MI_USER_INTERRUPT); 17148621f407SFrançois Tigeot __intel_ring_advance(engine); 1715e3adcf8fSFrançois Tigeot 1716e3adcf8fSFrançois Tigeot return 0; 1717e3adcf8fSFrançois Tigeot } 1718e3adcf8fSFrançois Tigeot 1719*303bf270SFrançois Tigeot static void 1720*303bf270SFrançois Tigeot gen6_irq_enable(struct intel_engine_cs *engine) 1721e3adcf8fSFrançois Tigeot { 17221487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 1723e3adcf8fSFrançois Tigeot 17248621f407SFrançois Tigeot I915_WRITE_IMR(engine, 17258621f407SFrançois Tigeot ~(engine->irq_enable_mask | 1726*303bf270SFrançois Tigeot engine->irq_keep_mask)); 17278621f407SFrançois Tigeot gen5_enable_gt_irq(dev_priv, engine->irq_enable_mask); 1728e3adcf8fSFrançois Tigeot } 1729e3adcf8fSFrançois Tigeot 1730e3adcf8fSFrançois Tigeot static void 1731*303bf270SFrançois Tigeot gen6_irq_disable(struct intel_engine_cs *engine) 1732e3adcf8fSFrançois Tigeot { 17331487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 1734e3adcf8fSFrançois Tigeot 1735*303bf270SFrançois Tigeot I915_WRITE_IMR(engine, ~engine->irq_keep_mask); 17368621f407SFrançois Tigeot gen5_disable_gt_irq(dev_priv, engine->irq_enable_mask); 1737e3adcf8fSFrançois Tigeot } 1738e3adcf8fSFrançois Tigeot 1739*303bf270SFrançois Tigeot static void 1740*303bf270SFrançois Tigeot hsw_vebox_irq_enable(struct intel_engine_cs *engine) 17415d0b1887SFrançois Tigeot { 17421487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 17435d0b1887SFrançois Tigeot 17448621f407SFrançois Tigeot I915_WRITE_IMR(engine, ~engine->irq_enable_mask); 17458621f407SFrançois Tigeot gen6_enable_pm_irq(dev_priv, engine->irq_enable_mask); 17465d0b1887SFrançois Tigeot } 17475d0b1887SFrançois Tigeot 17485d0b1887SFrançois Tigeot static void 1749*303bf270SFrançois Tigeot hsw_vebox_irq_disable(struct intel_engine_cs *engine) 17505d0b1887SFrançois Tigeot { 17511487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 17525d0b1887SFrançois Tigeot 17538621f407SFrançois Tigeot I915_WRITE_IMR(engine, ~0); 17548621f407SFrançois Tigeot gen6_disable_pm_irq(dev_priv, engine->irq_enable_mask); 17555d0b1887SFrançois Tigeot } 17569edbd4a0SFrançois Tigeot 1757*303bf270SFrançois Tigeot static void 1758*303bf270SFrançois Tigeot gen8_irq_enable(struct intel_engine_cs *engine) 17599edbd4a0SFrançois Tigeot { 17601487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 17619edbd4a0SFrançois Tigeot 17628621f407SFrançois Tigeot I915_WRITE_IMR(engine, 17638621f407SFrançois Tigeot ~(engine->irq_enable_mask | 1764*303bf270SFrançois Tigeot engine->irq_keep_mask)); 1765*303bf270SFrançois Tigeot POSTING_READ_FW(RING_IMR(engine->mmio_base)); 17669edbd4a0SFrançois Tigeot } 17679edbd4a0SFrançois Tigeot 17689edbd4a0SFrançois Tigeot static void 1769*303bf270SFrançois Tigeot gen8_irq_disable(struct intel_engine_cs *engine) 17709edbd4a0SFrançois Tigeot { 17711487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 17729edbd4a0SFrançois Tigeot 1773*303bf270SFrançois Tigeot I915_WRITE_IMR(engine, ~engine->irq_keep_mask); 17745d0b1887SFrançois Tigeot } 17755d0b1887SFrançois Tigeot 1776e3adcf8fSFrançois Tigeot static int 1777a05eeebfSFrançois Tigeot i965_dispatch_execbuffer(struct drm_i915_gem_request *req, 1778ba55f2f5SFrançois Tigeot u64 offset, u32 length, 1779477eb7f9SFrançois Tigeot unsigned dispatch_flags) 1780e3adcf8fSFrançois Tigeot { 17818621f407SFrançois Tigeot struct intel_engine_cs *engine = req->engine; 1782e3adcf8fSFrançois Tigeot int ret; 1783e3adcf8fSFrançois Tigeot 1784a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 2); 1785e3adcf8fSFrançois Tigeot if (ret) 1786e3adcf8fSFrançois Tigeot return ret; 1787e3adcf8fSFrançois Tigeot 17888621f407SFrançois Tigeot intel_ring_emit(engine, 1789686a02f1SFrançois Tigeot MI_BATCH_BUFFER_START | 1790b5c29a34SFrançois Tigeot MI_BATCH_GTT | 1791477eb7f9SFrançois Tigeot (dispatch_flags & I915_DISPATCH_SECURE ? 1792477eb7f9SFrançois Tigeot 0 : MI_BATCH_NON_SECURE_I965)); 17938621f407SFrançois Tigeot intel_ring_emit(engine, offset); 17948621f407SFrançois Tigeot intel_ring_advance(engine); 1795e3adcf8fSFrançois Tigeot 1796e3adcf8fSFrançois Tigeot return 0; 1797e3adcf8fSFrançois Tigeot } 1798e3adcf8fSFrançois Tigeot 1799b5c29a34SFrançois Tigeot /* Just userspace ABI convention to limit the wa batch bo to a resonable size */ 1800b5c29a34SFrançois Tigeot #define I830_BATCH_LIMIT (256*1024) 180124edb884SFrançois Tigeot #define I830_TLB_ENTRIES (2) 180224edb884SFrançois Tigeot #define I830_WA_SIZE max(I830_TLB_ENTRIES*4096, I830_BATCH_LIMIT) 1803e3adcf8fSFrançois Tigeot static int 1804a05eeebfSFrançois Tigeot i830_dispatch_execbuffer(struct drm_i915_gem_request *req, 1805ba55f2f5SFrançois Tigeot u64 offset, u32 len, 1806477eb7f9SFrançois Tigeot unsigned dispatch_flags) 1807e3adcf8fSFrançois Tigeot { 18088621f407SFrançois Tigeot struct intel_engine_cs *engine = req->engine; 18098621f407SFrançois Tigeot u32 cs_offset = engine->scratch.gtt_offset; 1810e3adcf8fSFrançois Tigeot int ret; 1811e3adcf8fSFrançois Tigeot 1812a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 6); 181324edb884SFrançois Tigeot if (ret) 181424edb884SFrançois Tigeot return ret; 181524edb884SFrançois Tigeot 181624edb884SFrançois Tigeot /* Evict the invalid PTE TLBs */ 18178621f407SFrançois Tigeot intel_ring_emit(engine, COLOR_BLT_CMD | BLT_WRITE_RGBA); 18188621f407SFrançois Tigeot intel_ring_emit(engine, BLT_DEPTH_32 | BLT_ROP_COLOR_COPY | 4096); 18198621f407SFrançois Tigeot intel_ring_emit(engine, I830_TLB_ENTRIES << 16 | 4); /* load each page */ 18208621f407SFrançois Tigeot intel_ring_emit(engine, cs_offset); 18218621f407SFrançois Tigeot intel_ring_emit(engine, 0xdeadbeef); 18228621f407SFrançois Tigeot intel_ring_emit(engine, MI_NOOP); 18238621f407SFrançois Tigeot intel_ring_advance(engine); 182424edb884SFrançois Tigeot 1825477eb7f9SFrançois Tigeot if ((dispatch_flags & I915_DISPATCH_PINNED) == 0) { 182624edb884SFrançois Tigeot if (len > I830_BATCH_LIMIT) 182724edb884SFrançois Tigeot return -ENOSPC; 182824edb884SFrançois Tigeot 1829a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 6 + 2); 183024edb884SFrançois Tigeot if (ret) 183124edb884SFrançois Tigeot return ret; 183224edb884SFrançois Tigeot 183324edb884SFrançois Tigeot /* Blit the batch (which has now all relocs applied) to the 183424edb884SFrançois Tigeot * stable batch scratch bo area (so that the CS never 183524edb884SFrançois Tigeot * stumbles over its tlb invalidation bug) ... 183624edb884SFrançois Tigeot */ 18378621f407SFrançois Tigeot intel_ring_emit(engine, SRC_COPY_BLT_CMD | BLT_WRITE_RGBA); 18388621f407SFrançois Tigeot intel_ring_emit(engine, 18398621f407SFrançois Tigeot BLT_DEPTH_32 | BLT_ROP_SRC_COPY | 4096); 18408621f407SFrançois Tigeot intel_ring_emit(engine, DIV_ROUND_UP(len, 4096) << 16 | 4096); 18418621f407SFrançois Tigeot intel_ring_emit(engine, cs_offset); 18428621f407SFrançois Tigeot intel_ring_emit(engine, 4096); 18438621f407SFrançois Tigeot intel_ring_emit(engine, offset); 184424edb884SFrançois Tigeot 18458621f407SFrançois Tigeot intel_ring_emit(engine, MI_FLUSH); 18468621f407SFrançois Tigeot intel_ring_emit(engine, MI_NOOP); 18478621f407SFrançois Tigeot intel_ring_advance(engine); 184824edb884SFrançois Tigeot 184924edb884SFrançois Tigeot /* ... and execute it. */ 185024edb884SFrançois Tigeot offset = cs_offset; 185124edb884SFrançois Tigeot } 185224edb884SFrançois Tigeot 1853c0e85e96SFrançois Tigeot ret = intel_ring_begin(req, 2); 1854e3adcf8fSFrançois Tigeot if (ret) 1855e3adcf8fSFrançois Tigeot return ret; 1856e3adcf8fSFrançois Tigeot 18578621f407SFrançois Tigeot intel_ring_emit(engine, MI_BATCH_BUFFER_START | MI_BATCH_GTT); 18588621f407SFrançois Tigeot intel_ring_emit(engine, offset | (dispatch_flags & I915_DISPATCH_SECURE ? 1859477eb7f9SFrançois Tigeot 0 : MI_BATCH_NON_SECURE)); 18608621f407SFrançois Tigeot intel_ring_advance(engine); 1861686a02f1SFrançois Tigeot 1862686a02f1SFrançois Tigeot return 0; 1863686a02f1SFrançois Tigeot } 1864686a02f1SFrançois Tigeot 1865686a02f1SFrançois Tigeot static int 1866a05eeebfSFrançois Tigeot i915_dispatch_execbuffer(struct drm_i915_gem_request *req, 1867ba55f2f5SFrançois Tigeot u64 offset, u32 len, 1868477eb7f9SFrançois Tigeot unsigned dispatch_flags) 1869686a02f1SFrançois Tigeot { 18708621f407SFrançois Tigeot struct intel_engine_cs *engine = req->engine; 1871686a02f1SFrançois Tigeot int ret; 1872686a02f1SFrançois Tigeot 1873a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 2); 1874e3adcf8fSFrançois Tigeot if (ret) 1875e3adcf8fSFrançois Tigeot return ret; 1876e3adcf8fSFrançois Tigeot 18778621f407SFrançois Tigeot intel_ring_emit(engine, MI_BATCH_BUFFER_START | MI_BATCH_GTT); 18788621f407SFrançois Tigeot intel_ring_emit(engine, offset | (dispatch_flags & I915_DISPATCH_SECURE ? 1879477eb7f9SFrançois Tigeot 0 : MI_BATCH_NON_SECURE)); 18808621f407SFrançois Tigeot intel_ring_advance(engine); 1881e3adcf8fSFrançois Tigeot 1882e3adcf8fSFrançois Tigeot return 0; 1883e3adcf8fSFrançois Tigeot } 1884e3adcf8fSFrançois Tigeot 18858621f407SFrançois Tigeot static void cleanup_phys_status_page(struct intel_engine_cs *engine) 1886c0e85e96SFrançois Tigeot { 18871487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 1888c0e85e96SFrançois Tigeot 1889c0e85e96SFrançois Tigeot if (!dev_priv->status_page_dmah) 1890c0e85e96SFrançois Tigeot return; 1891c0e85e96SFrançois Tigeot 1892*303bf270SFrançois Tigeot drm_pci_free(&dev_priv->drm, dev_priv->status_page_dmah); 18938621f407SFrançois Tigeot engine->status_page.page_addr = NULL; 1894c0e85e96SFrançois Tigeot } 1895c0e85e96SFrançois Tigeot 18968621f407SFrançois Tigeot static void cleanup_status_page(struct intel_engine_cs *engine) 1897e3adcf8fSFrançois Tigeot { 1898e3adcf8fSFrançois Tigeot struct drm_i915_gem_object *obj; 1899e3adcf8fSFrançois Tigeot 19008621f407SFrançois Tigeot obj = engine->status_page.obj; 1901e3adcf8fSFrançois Tigeot if (obj == NULL) 1902e3adcf8fSFrançois Tigeot return; 1903e3adcf8fSFrançois Tigeot 19047ec9f8e5SFrançois Tigeot kunmap(sg_page(obj->pages->sgl)); 1905ba55f2f5SFrançois Tigeot i915_gem_object_ggtt_unpin(obj); 1906e3adcf8fSFrançois Tigeot drm_gem_object_unreference(&obj->base); 19078621f407SFrançois Tigeot engine->status_page.obj = NULL; 1908e3adcf8fSFrançois Tigeot } 1909e3adcf8fSFrançois Tigeot 19108621f407SFrançois Tigeot static int init_status_page(struct intel_engine_cs *engine) 1911e3adcf8fSFrançois Tigeot { 19128621f407SFrançois Tigeot struct drm_i915_gem_object *obj = engine->status_page.obj; 1913ba55f2f5SFrançois Tigeot 1914c0e85e96SFrançois Tigeot if (obj == NULL) { 191524edb884SFrançois Tigeot unsigned flags; 1916e3adcf8fSFrançois Tigeot int ret; 1917e3adcf8fSFrançois Tigeot 1918*303bf270SFrançois Tigeot obj = i915_gem_object_create(&engine->i915->drm, 4096); 19191487f786SFrançois Tigeot if (IS_ERR(obj)) { 1920e3adcf8fSFrançois Tigeot DRM_ERROR("Failed to allocate status page\n"); 19211487f786SFrançois Tigeot return PTR_ERR(obj); 1922e3adcf8fSFrançois Tigeot } 1923e3adcf8fSFrançois Tigeot 1924ba55f2f5SFrançois Tigeot ret = i915_gem_object_set_cache_level(obj, I915_CACHE_LLC); 1925ba55f2f5SFrançois Tigeot if (ret) 1926e3adcf8fSFrançois Tigeot goto err_unref; 1927ba55f2f5SFrançois Tigeot 192824edb884SFrançois Tigeot flags = 0; 19291487f786SFrançois Tigeot if (!HAS_LLC(engine->i915)) 193024edb884SFrançois Tigeot /* On g33, we cannot place HWS above 256MiB, so 193124edb884SFrançois Tigeot * restrict its pinning to the low mappable arena. 193224edb884SFrançois Tigeot * Though this restriction is not documented for 193324edb884SFrançois Tigeot * gen4, gen5, or byt, they also behave similarly 193424edb884SFrançois Tigeot * and hang if the HWS is placed at the top of the 193524edb884SFrançois Tigeot * GTT. To generalise, it appears that all !llc 193624edb884SFrançois Tigeot * platforms have issues with us placing the HWS 193724edb884SFrançois Tigeot * above the mappable region (even though we never 193824edb884SFrançois Tigeot * actualy map it). 193924edb884SFrançois Tigeot */ 194024edb884SFrançois Tigeot flags |= PIN_MAPPABLE; 194124edb884SFrançois Tigeot ret = i915_gem_obj_ggtt_pin(obj, 4096, flags); 1942ba55f2f5SFrançois Tigeot if (ret) { 1943ba55f2f5SFrançois Tigeot err_unref: 1944ba55f2f5SFrançois Tigeot drm_gem_object_unreference(&obj->base); 1945ba55f2f5SFrançois Tigeot return ret; 1946ba55f2f5SFrançois Tigeot } 1947ba55f2f5SFrançois Tigeot 19488621f407SFrançois Tigeot engine->status_page.obj = obj; 1949e3adcf8fSFrançois Tigeot } 1950e3adcf8fSFrançois Tigeot 19518621f407SFrançois Tigeot engine->status_page.gfx_addr = i915_gem_obj_ggtt_offset(obj); 19528621f407SFrançois Tigeot engine->status_page.page_addr = kmap(sg_page(obj->pages->sgl)); 19538621f407SFrançois Tigeot memset(engine->status_page.page_addr, 0, PAGE_SIZE); 1954e3adcf8fSFrançois Tigeot 1955b5c29a34SFrançois Tigeot DRM_DEBUG_DRIVER("%s hws offset: 0x%08x\n", 19568621f407SFrançois Tigeot engine->name, engine->status_page.gfx_addr); 1957e3adcf8fSFrançois Tigeot 1958e3adcf8fSFrançois Tigeot return 0; 1959e3adcf8fSFrançois Tigeot } 1960e3adcf8fSFrançois Tigeot 19618621f407SFrançois Tigeot static int init_phys_status_page(struct intel_engine_cs *engine) 1962686a02f1SFrançois Tigeot { 19631487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 1964686a02f1SFrançois Tigeot 1965686a02f1SFrançois Tigeot if (!dev_priv->status_page_dmah) { 1966686a02f1SFrançois Tigeot dev_priv->status_page_dmah = 1967*303bf270SFrançois Tigeot drm_pci_alloc(&dev_priv->drm, PAGE_SIZE, PAGE_SIZE); 1968686a02f1SFrançois Tigeot if (!dev_priv->status_page_dmah) 1969686a02f1SFrançois Tigeot return -ENOMEM; 1970686a02f1SFrançois Tigeot } 1971686a02f1SFrançois Tigeot 19728621f407SFrançois Tigeot engine->status_page.page_addr = dev_priv->status_page_dmah->vaddr; 19738621f407SFrançois Tigeot memset(engine->status_page.page_addr, 0, PAGE_SIZE); 1974686a02f1SFrançois Tigeot 1975686a02f1SFrançois Tigeot return 0; 1976686a02f1SFrançois Tigeot } 1977686a02f1SFrançois Tigeot 19782c9916cdSFrançois Tigeot void intel_unpin_ringbuffer_obj(struct intel_ringbuffer *ringbuf) 19792c9916cdSFrançois Tigeot { 19801487f786SFrançois Tigeot GEM_BUG_ON(ringbuf->vma == NULL); 19811487f786SFrançois Tigeot GEM_BUG_ON(ringbuf->virtual_start == NULL); 19821487f786SFrançois Tigeot 1983aee94f86SFrançois Tigeot if (HAS_LLC(ringbuf->obj->base.dev) && !ringbuf->obj->stolen) 19848621f407SFrançois Tigeot i915_gem_object_unpin_map(ringbuf->obj); 1985aee94f86SFrançois Tigeot else 19861487f786SFrançois Tigeot i915_vma_unpin_iomap(ringbuf->vma); 19872c9916cdSFrançois Tigeot ringbuf->virtual_start = NULL; 19881487f786SFrançois Tigeot 19892c9916cdSFrançois Tigeot i915_gem_object_ggtt_unpin(ringbuf->obj); 19901487f786SFrançois Tigeot ringbuf->vma = NULL; 19912c9916cdSFrançois Tigeot } 19922c9916cdSFrançois Tigeot 19931487f786SFrançois Tigeot int intel_pin_and_map_ringbuffer_obj(struct drm_i915_private *dev_priv, 19942c9916cdSFrançois Tigeot struct intel_ringbuffer *ringbuf) 19952c9916cdSFrançois Tigeot { 19962c9916cdSFrançois Tigeot struct drm_i915_gem_object *obj = ringbuf->obj; 1997c0e85e96SFrançois Tigeot /* Ring wraparound at offset 0 sometimes hangs. No idea why. */ 1998c0e85e96SFrançois Tigeot unsigned flags = PIN_OFFSET_BIAS | 4096; 19998621f407SFrançois Tigeot void *addr; 20002c9916cdSFrançois Tigeot int ret; 20012c9916cdSFrançois Tigeot 2002aee94f86SFrançois Tigeot if (HAS_LLC(dev_priv) && !obj->stolen) { 2003c0e85e96SFrançois Tigeot ret = i915_gem_obj_ggtt_pin(obj, PAGE_SIZE, flags); 2004aee94f86SFrançois Tigeot if (ret) 2005aee94f86SFrançois Tigeot return ret; 2006aee94f86SFrançois Tigeot 2007aee94f86SFrançois Tigeot ret = i915_gem_object_set_to_cpu_domain(obj, true); 20088621f407SFrançois Tigeot if (ret) 20098621f407SFrançois Tigeot goto err_unpin; 2010aee94f86SFrançois Tigeot 20118621f407SFrançois Tigeot addr = i915_gem_object_pin_map(obj); 20128621f407SFrançois Tigeot if (IS_ERR(addr)) { 20138621f407SFrançois Tigeot ret = PTR_ERR(addr); 20148621f407SFrançois Tigeot goto err_unpin; 2015aee94f86SFrançois Tigeot } 2016aee94f86SFrançois Tigeot } else { 2017c0e85e96SFrançois Tigeot ret = i915_gem_obj_ggtt_pin(obj, PAGE_SIZE, 2018c0e85e96SFrançois Tigeot flags | PIN_MAPPABLE); 20192c9916cdSFrançois Tigeot if (ret) 20202c9916cdSFrançois Tigeot return ret; 20212c9916cdSFrançois Tigeot 20222c9916cdSFrançois Tigeot ret = i915_gem_object_set_to_gtt_domain(obj, true); 20238621f407SFrançois Tigeot if (ret) 20248621f407SFrançois Tigeot goto err_unpin; 20252c9916cdSFrançois Tigeot 2026c0e85e96SFrançois Tigeot /* Access through the GTT requires the device to be awake. */ 2027c0e85e96SFrançois Tigeot assert_rpm_wakelock_held(dev_priv); 2028c0e85e96SFrançois Tigeot 20291487f786SFrançois Tigeot addr = i915_vma_pin_iomap(i915_gem_obj_to_ggtt(obj)); 20301487f786SFrançois Tigeot if (IS_ERR(addr)) { 20311487f786SFrançois Tigeot ret = PTR_ERR(addr); 20328621f407SFrançois Tigeot goto err_unpin; 20332c9916cdSFrançois Tigeot } 2034aee94f86SFrançois Tigeot } 20352c9916cdSFrançois Tigeot 20368621f407SFrançois Tigeot ringbuf->virtual_start = addr; 2037c0e85e96SFrançois Tigeot ringbuf->vma = i915_gem_obj_to_ggtt(obj); 20382c9916cdSFrançois Tigeot return 0; 20398621f407SFrançois Tigeot 20408621f407SFrançois Tigeot err_unpin: 20418621f407SFrançois Tigeot i915_gem_object_ggtt_unpin(obj); 20428621f407SFrançois Tigeot return ret; 20432c9916cdSFrançois Tigeot } 20442c9916cdSFrançois Tigeot 2045352ff8bdSFrançois Tigeot static void intel_destroy_ringbuffer_obj(struct intel_ringbuffer *ringbuf) 2046e3adcf8fSFrançois Tigeot { 204724edb884SFrançois Tigeot drm_gem_object_unreference(&ringbuf->obj->base); 204824edb884SFrançois Tigeot ringbuf->obj = NULL; 204924edb884SFrançois Tigeot } 205024edb884SFrançois Tigeot 2051352ff8bdSFrançois Tigeot static int intel_alloc_ringbuffer_obj(struct drm_device *dev, 205224edb884SFrançois Tigeot struct intel_ringbuffer *ringbuf) 205324edb884SFrançois Tigeot { 2054e3adcf8fSFrançois Tigeot struct drm_i915_gem_object *obj; 2055e3adcf8fSFrançois Tigeot 2056a2fdbec6SFrançois Tigeot obj = NULL; 2057a2fdbec6SFrançois Tigeot if (!HAS_LLC(dev)) 2058ba55f2f5SFrançois Tigeot obj = i915_gem_object_create_stolen(dev, ringbuf->size); 2059a2fdbec6SFrançois Tigeot if (obj == NULL) 20601487f786SFrançois Tigeot obj = i915_gem_object_create(dev, ringbuf->size); 20611487f786SFrançois Tigeot if (IS_ERR(obj)) 20621487f786SFrançois Tigeot return PTR_ERR(obj); 2063e3adcf8fSFrançois Tigeot 206424edb884SFrançois Tigeot /* mark ring buffers as read-only from GPU side by default */ 206524edb884SFrançois Tigeot obj->gt_ro = 1; 206624edb884SFrançois Tigeot 2067ba55f2f5SFrançois Tigeot ringbuf->obj = obj; 2068ba55f2f5SFrançois Tigeot 20692c9916cdSFrançois Tigeot return 0; 2070ba55f2f5SFrançois Tigeot } 2071ba55f2f5SFrançois Tigeot 2072352ff8bdSFrançois Tigeot struct intel_ringbuffer * 2073352ff8bdSFrançois Tigeot intel_engine_create_ringbuffer(struct intel_engine_cs *engine, int size) 2074352ff8bdSFrançois Tigeot { 2075352ff8bdSFrançois Tigeot struct intel_ringbuffer *ring; 2076352ff8bdSFrançois Tigeot int ret; 2077352ff8bdSFrançois Tigeot 2078352ff8bdSFrançois Tigeot ring = kzalloc(sizeof(*ring), GFP_KERNEL); 2079aee94f86SFrançois Tigeot if (ring == NULL) { 2080aee94f86SFrançois Tigeot DRM_DEBUG_DRIVER("Failed to allocate ringbuffer %s\n", 2081aee94f86SFrançois Tigeot engine->name); 2082352ff8bdSFrançois Tigeot return ERR_PTR(-ENOMEM); 2083aee94f86SFrançois Tigeot } 2084352ff8bdSFrançois Tigeot 20858621f407SFrançois Tigeot ring->engine = engine; 2086aee94f86SFrançois Tigeot list_add(&ring->link, &engine->buffers); 2087352ff8bdSFrançois Tigeot 2088352ff8bdSFrançois Tigeot ring->size = size; 2089352ff8bdSFrançois Tigeot /* Workaround an erratum on the i830 which causes a hang if 2090352ff8bdSFrançois Tigeot * the TAIL pointer points to within the last 2 cachelines 2091352ff8bdSFrançois Tigeot * of the buffer. 2092352ff8bdSFrançois Tigeot */ 2093352ff8bdSFrançois Tigeot ring->effective_size = size; 20941487f786SFrançois Tigeot if (IS_I830(engine->i915) || IS_845G(engine->i915)) 2095352ff8bdSFrançois Tigeot ring->effective_size -= 2 * CACHELINE_BYTES; 2096352ff8bdSFrançois Tigeot 2097352ff8bdSFrançois Tigeot ring->last_retired_head = -1; 2098352ff8bdSFrançois Tigeot intel_ring_update_space(ring); 2099352ff8bdSFrançois Tigeot 2100*303bf270SFrançois Tigeot ret = intel_alloc_ringbuffer_obj(&engine->i915->drm, ring); 2101352ff8bdSFrançois Tigeot if (ret) { 2102aee94f86SFrançois Tigeot DRM_DEBUG_DRIVER("Failed to allocate ringbuffer %s: %d\n", 2103352ff8bdSFrançois Tigeot engine->name, ret); 2104aee94f86SFrançois Tigeot list_del(&ring->link); 2105352ff8bdSFrançois Tigeot kfree(ring); 2106352ff8bdSFrançois Tigeot return ERR_PTR(ret); 2107352ff8bdSFrançois Tigeot } 2108352ff8bdSFrançois Tigeot 2109352ff8bdSFrançois Tigeot return ring; 2110352ff8bdSFrançois Tigeot } 2111352ff8bdSFrançois Tigeot 2112352ff8bdSFrançois Tigeot void 2113352ff8bdSFrançois Tigeot intel_ringbuffer_free(struct intel_ringbuffer *ring) 2114352ff8bdSFrançois Tigeot { 2115352ff8bdSFrançois Tigeot intel_destroy_ringbuffer_obj(ring); 2116aee94f86SFrançois Tigeot list_del(&ring->link); 2117352ff8bdSFrançois Tigeot kfree(ring); 2118352ff8bdSFrançois Tigeot } 2119352ff8bdSFrançois Tigeot 21201487f786SFrançois Tigeot static int intel_ring_context_pin(struct i915_gem_context *ctx, 21211487f786SFrançois Tigeot struct intel_engine_cs *engine) 21221487f786SFrançois Tigeot { 21231487f786SFrançois Tigeot struct intel_context *ce = &ctx->engine[engine->id]; 21241487f786SFrançois Tigeot int ret; 21251487f786SFrançois Tigeot 2126*303bf270SFrançois Tigeot lockdep_assert_held(&ctx->i915->drm.struct_mutex); 21271487f786SFrançois Tigeot 21281487f786SFrançois Tigeot if (ce->pin_count++) 21291487f786SFrançois Tigeot return 0; 21301487f786SFrançois Tigeot 21311487f786SFrançois Tigeot if (ce->state) { 21321487f786SFrançois Tigeot ret = i915_gem_obj_ggtt_pin(ce->state, ctx->ggtt_alignment, 0); 21331487f786SFrançois Tigeot if (ret) 21341487f786SFrançois Tigeot goto error; 21351487f786SFrançois Tigeot } 21361487f786SFrançois Tigeot 21371487f786SFrançois Tigeot /* The kernel context is only used as a placeholder for flushing the 21381487f786SFrançois Tigeot * active context. It is never used for submitting user rendering and 21391487f786SFrançois Tigeot * as such never requires the golden render context, and so we can skip 21401487f786SFrançois Tigeot * emitting it when we switch to the kernel context. This is required 21411487f786SFrançois Tigeot * as during eviction we cannot allocate and pin the renderstate in 21421487f786SFrançois Tigeot * order to initialise the context. 21431487f786SFrançois Tigeot */ 21441487f786SFrançois Tigeot if (ctx == ctx->i915->kernel_context) 21451487f786SFrançois Tigeot ce->initialised = true; 21461487f786SFrançois Tigeot 21471487f786SFrançois Tigeot i915_gem_context_reference(ctx); 21481487f786SFrançois Tigeot return 0; 21491487f786SFrançois Tigeot 21501487f786SFrançois Tigeot error: 21511487f786SFrançois Tigeot ce->pin_count = 0; 21521487f786SFrançois Tigeot return ret; 21531487f786SFrançois Tigeot } 21541487f786SFrançois Tigeot 21551487f786SFrançois Tigeot static void intel_ring_context_unpin(struct i915_gem_context *ctx, 21561487f786SFrançois Tigeot struct intel_engine_cs *engine) 21571487f786SFrançois Tigeot { 21581487f786SFrançois Tigeot struct intel_context *ce = &ctx->engine[engine->id]; 21591487f786SFrançois Tigeot 2160*303bf270SFrançois Tigeot lockdep_assert_held(&ctx->i915->drm.struct_mutex); 21611487f786SFrançois Tigeot 21621487f786SFrançois Tigeot if (--ce->pin_count) 21631487f786SFrançois Tigeot return; 21641487f786SFrançois Tigeot 21651487f786SFrançois Tigeot if (ce->state) 21661487f786SFrançois Tigeot i915_gem_object_ggtt_unpin(ce->state); 21671487f786SFrançois Tigeot 21681487f786SFrançois Tigeot i915_gem_context_unreference(ctx); 21691487f786SFrançois Tigeot } 21701487f786SFrançois Tigeot 2171ba55f2f5SFrançois Tigeot static int intel_init_ring_buffer(struct drm_device *dev, 21728621f407SFrançois Tigeot struct intel_engine_cs *engine) 2173ba55f2f5SFrançois Tigeot { 21741487f786SFrançois Tigeot struct drm_i915_private *dev_priv = to_i915(dev); 21752c9916cdSFrançois Tigeot struct intel_ringbuffer *ringbuf; 2176ba55f2f5SFrançois Tigeot int ret; 2177ba55f2f5SFrançois Tigeot 21788621f407SFrançois Tigeot WARN_ON(engine->buffer); 21792c9916cdSFrançois Tigeot 21801487f786SFrançois Tigeot engine->i915 = dev_priv; 21818621f407SFrançois Tigeot INIT_LIST_HEAD(&engine->active_list); 21828621f407SFrançois Tigeot INIT_LIST_HEAD(&engine->request_list); 21838621f407SFrançois Tigeot INIT_LIST_HEAD(&engine->execlist_queue); 21848621f407SFrançois Tigeot INIT_LIST_HEAD(&engine->buffers); 21858621f407SFrançois Tigeot i915_gem_batch_pool_init(dev, &engine->batch_pool); 21868621f407SFrançois Tigeot memset(engine->semaphore.sync_seqno, 0, 21878621f407SFrançois Tigeot sizeof(engine->semaphore.sync_seqno)); 2188ba55f2f5SFrançois Tigeot 2189*303bf270SFrançois Tigeot ret = intel_engine_init_breadcrumbs(engine); 2190*303bf270SFrançois Tigeot if (ret) 2191*303bf270SFrançois Tigeot goto error; 2192ba55f2f5SFrançois Tigeot 21931487f786SFrançois Tigeot /* We may need to do things with the shrinker which 21941487f786SFrançois Tigeot * require us to immediately switch back to the default 21951487f786SFrançois Tigeot * context. This can cause a problem as pinning the 21961487f786SFrançois Tigeot * default context also requires GTT space which may not 21971487f786SFrançois Tigeot * be available. To avoid this we always pin the default 21981487f786SFrançois Tigeot * context. 21991487f786SFrançois Tigeot */ 22001487f786SFrançois Tigeot ret = intel_ring_context_pin(dev_priv->kernel_context, engine); 22011487f786SFrançois Tigeot if (ret) 22021487f786SFrançois Tigeot goto error; 22031487f786SFrançois Tigeot 22048621f407SFrançois Tigeot ringbuf = intel_engine_create_ringbuffer(engine, 32 * PAGE_SIZE); 2205aee94f86SFrançois Tigeot if (IS_ERR(ringbuf)) { 2206aee94f86SFrançois Tigeot ret = PTR_ERR(ringbuf); 2207aee94f86SFrançois Tigeot goto error; 2208aee94f86SFrançois Tigeot } 22098621f407SFrançois Tigeot engine->buffer = ringbuf; 2210352ff8bdSFrançois Tigeot 22111487f786SFrançois Tigeot if (I915_NEED_GFX_HWS(dev_priv)) { 22128621f407SFrançois Tigeot ret = init_status_page(engine); 2213e3adcf8fSFrançois Tigeot if (ret) 2214ba55f2f5SFrançois Tigeot goto error; 2215ba55f2f5SFrançois Tigeot } else { 22168621f407SFrançois Tigeot WARN_ON(engine->id != RCS); 22178621f407SFrançois Tigeot ret = init_phys_status_page(engine); 2218ba55f2f5SFrançois Tigeot if (ret) 2219ba55f2f5SFrançois Tigeot goto error; 2220ba55f2f5SFrançois Tigeot } 2221ba55f2f5SFrançois Tigeot 22221487f786SFrançois Tigeot ret = intel_pin_and_map_ringbuffer_obj(dev_priv, ringbuf); 22232c9916cdSFrançois Tigeot if (ret) { 22242c9916cdSFrançois Tigeot DRM_ERROR("Failed to pin and map ringbuffer %s: %d\n", 22258621f407SFrançois Tigeot engine->name, ret); 22262c9916cdSFrançois Tigeot intel_destroy_ringbuffer_obj(ringbuf); 2227ba55f2f5SFrançois Tigeot goto error; 2228ba55f2f5SFrançois Tigeot } 2229e3adcf8fSFrançois Tigeot 22308621f407SFrançois Tigeot ret = i915_cmd_parser_init_ring(engine); 2231ba55f2f5SFrançois Tigeot if (ret) 2232ba55f2f5SFrançois Tigeot goto error; 2233ba55f2f5SFrançois Tigeot 2234e3adcf8fSFrançois Tigeot return 0; 2235e3adcf8fSFrançois Tigeot 2236ba55f2f5SFrançois Tigeot error: 22378621f407SFrançois Tigeot intel_cleanup_engine(engine); 2238e3adcf8fSFrançois Tigeot return ret; 2239e3adcf8fSFrançois Tigeot } 2240e3adcf8fSFrançois Tigeot 22418621f407SFrançois Tigeot void intel_cleanup_engine(struct intel_engine_cs *engine) 2242e3adcf8fSFrançois Tigeot { 22432c9916cdSFrançois Tigeot struct drm_i915_private *dev_priv; 2244e3adcf8fSFrançois Tigeot 22458621f407SFrançois Tigeot if (!intel_engine_initialized(engine)) 2246e3adcf8fSFrançois Tigeot return; 2247e3adcf8fSFrançois Tigeot 22481487f786SFrançois Tigeot dev_priv = engine->i915; 22492c9916cdSFrançois Tigeot 22508621f407SFrançois Tigeot if (engine->buffer) { 22518621f407SFrançois Tigeot intel_stop_engine(engine); 22521487f786SFrançois Tigeot WARN_ON(!IS_GEN2(dev_priv) && (I915_READ_MODE(engine) & MODE_IDLE) == 0); 2253b030f26bSFrançois Tigeot 22548621f407SFrançois Tigeot intel_unpin_ringbuffer_obj(engine->buffer); 22558621f407SFrançois Tigeot intel_ringbuffer_free(engine->buffer); 22568621f407SFrançois Tigeot engine->buffer = NULL; 2257aee94f86SFrançois Tigeot } 2258e3adcf8fSFrançois Tigeot 22598621f407SFrançois Tigeot if (engine->cleanup) 22608621f407SFrançois Tigeot engine->cleanup(engine); 2261e3adcf8fSFrançois Tigeot 22621487f786SFrançois Tigeot if (I915_NEED_GFX_HWS(dev_priv)) { 22638621f407SFrançois Tigeot cleanup_status_page(engine); 2264c0e85e96SFrançois Tigeot } else { 22658621f407SFrançois Tigeot WARN_ON(engine->id != RCS); 22668621f407SFrançois Tigeot cleanup_phys_status_page(engine); 2267c0e85e96SFrançois Tigeot } 2268ba55f2f5SFrançois Tigeot 22698621f407SFrançois Tigeot i915_cmd_parser_fini_ring(engine); 22708621f407SFrançois Tigeot i915_gem_batch_pool_fini(&engine->batch_pool); 2271*303bf270SFrançois Tigeot intel_engine_fini_breadcrumbs(engine); 22721487f786SFrançois Tigeot 22731487f786SFrançois Tigeot intel_ring_context_unpin(dev_priv->kernel_context, engine); 22741487f786SFrançois Tigeot 22751487f786SFrançois Tigeot engine->i915 = NULL; 2276e3adcf8fSFrançois Tigeot } 2277e3adcf8fSFrançois Tigeot 22788621f407SFrançois Tigeot int intel_engine_idle(struct intel_engine_cs *engine) 2279b030f26bSFrançois Tigeot { 22802c9916cdSFrançois Tigeot struct drm_i915_gem_request *req; 2281b5c29a34SFrançois Tigeot 2282b5c29a34SFrançois Tigeot /* Wait upon the last request to be completed */ 22838621f407SFrançois Tigeot if (list_empty(&engine->request_list)) 2284b5c29a34SFrançois Tigeot return 0; 2285b5c29a34SFrançois Tigeot 22868621f407SFrançois Tigeot req = list_entry(engine->request_list.prev, 2287b5c29a34SFrançois Tigeot struct drm_i915_gem_request, 22882c9916cdSFrançois Tigeot list); 2289b5c29a34SFrançois Tigeot 229019c468b4SFrançois Tigeot /* Make sure we do not trigger any retires */ 229119c468b4SFrançois Tigeot return __i915_wait_request(req, 22928621f407SFrançois Tigeot req->i915->mm.interruptible, 229319c468b4SFrançois Tigeot NULL, NULL); 2294b5c29a34SFrançois Tigeot } 2295b5c29a34SFrançois Tigeot 229619c468b4SFrançois Tigeot int intel_ring_alloc_request_extras(struct drm_i915_gem_request *request) 2297b5c29a34SFrançois Tigeot { 22981487f786SFrançois Tigeot int ret; 22999edbd4a0SFrançois Tigeot 23001487f786SFrançois Tigeot /* Flush enough space to reduce the likelihood of waiting after 23011487f786SFrançois Tigeot * we start building the request - in which case we will just 23021487f786SFrançois Tigeot * have to repeat work. 2303a05eeebfSFrançois Tigeot */ 23041487f786SFrançois Tigeot request->reserved_space += LEGACY_REQUEST_SIZE; 2305a2fdbec6SFrançois Tigeot 23061487f786SFrançois Tigeot request->ringbuf = request->engine->buffer; 2307a2fdbec6SFrançois Tigeot 23081487f786SFrançois Tigeot ret = intel_ring_begin(request, 0); 23091487f786SFrançois Tigeot if (ret) 23101487f786SFrançois Tigeot return ret; 2311a05eeebfSFrançois Tigeot 23121487f786SFrançois Tigeot request->reserved_space -= LEGACY_REQUEST_SIZE; 23131487f786SFrançois Tigeot return 0; 2314a05eeebfSFrançois Tigeot } 2315a05eeebfSFrançois Tigeot 23168621f407SFrançois Tigeot static int wait_for_space(struct drm_i915_gem_request *req, int bytes) 2317a05eeebfSFrançois Tigeot { 23188621f407SFrançois Tigeot struct intel_ringbuffer *ringbuf = req->ringbuf; 23198621f407SFrançois Tigeot struct intel_engine_cs *engine = req->engine; 23208621f407SFrançois Tigeot struct drm_i915_gem_request *target; 23218621f407SFrançois Tigeot 23228621f407SFrançois Tigeot intel_ring_update_space(ringbuf); 23238621f407SFrançois Tigeot if (ringbuf->space >= bytes) 23248621f407SFrançois Tigeot return 0; 23258621f407SFrançois Tigeot 23268621f407SFrançois Tigeot /* 23278621f407SFrançois Tigeot * Space is reserved in the ringbuffer for finalising the request, 23288621f407SFrançois Tigeot * as that cannot be allowed to fail. During request finalisation, 23298621f407SFrançois Tigeot * reserved_space is set to 0 to stop the overallocation and the 23308621f407SFrançois Tigeot * assumption is that then we never need to wait (which has the 23318621f407SFrançois Tigeot * risk of failing with EINTR). 23328621f407SFrançois Tigeot * 23338621f407SFrançois Tigeot * See also i915_gem_request_alloc() and i915_add_request(). 23348621f407SFrançois Tigeot */ 23351487f786SFrançois Tigeot GEM_BUG_ON(!req->reserved_space); 23368621f407SFrançois Tigeot 23378621f407SFrançois Tigeot list_for_each_entry(target, &engine->request_list, list) { 23388621f407SFrançois Tigeot unsigned space; 23398621f407SFrançois Tigeot 23408621f407SFrançois Tigeot /* 23418621f407SFrançois Tigeot * The request queue is per-engine, so can contain requests 23428621f407SFrançois Tigeot * from multiple ringbuffers. Here, we must ignore any that 23438621f407SFrançois Tigeot * aren't from the ringbuffer we're considering. 23448621f407SFrançois Tigeot */ 23458621f407SFrançois Tigeot if (target->ringbuf != ringbuf) 23468621f407SFrançois Tigeot continue; 23478621f407SFrançois Tigeot 23488621f407SFrançois Tigeot /* Would completion of this request free enough space? */ 23498621f407SFrançois Tigeot space = __intel_ring_space(target->postfix, ringbuf->tail, 23508621f407SFrançois Tigeot ringbuf->size); 23518621f407SFrançois Tigeot if (space >= bytes) 23528621f407SFrançois Tigeot break; 23538621f407SFrançois Tigeot } 23548621f407SFrançois Tigeot 23558621f407SFrançois Tigeot if (WARN_ON(&target->list == &engine->request_list)) 23568621f407SFrançois Tigeot return -ENOSPC; 23578621f407SFrançois Tigeot 23588621f407SFrançois Tigeot return i915_wait_request(target); 23598621f407SFrançois Tigeot } 23608621f407SFrançois Tigeot 23618621f407SFrançois Tigeot int intel_ring_begin(struct drm_i915_gem_request *req, int num_dwords) 23628621f407SFrançois Tigeot { 23638621f407SFrançois Tigeot struct intel_ringbuffer *ringbuf = req->ringbuf; 2364a05eeebfSFrançois Tigeot int remain_actual = ringbuf->size - ringbuf->tail; 23658621f407SFrançois Tigeot int remain_usable = ringbuf->effective_size - ringbuf->tail; 23668621f407SFrançois Tigeot int bytes = num_dwords * sizeof(u32); 23678621f407SFrançois Tigeot int total_bytes, wait_bytes; 2368a05eeebfSFrançois Tigeot bool need_wrap = false; 2369a05eeebfSFrançois Tigeot 23701487f786SFrançois Tigeot total_bytes = bytes + req->reserved_space; 2371a05eeebfSFrançois Tigeot 2372a05eeebfSFrançois Tigeot if (unlikely(bytes > remain_usable)) { 2373a05eeebfSFrançois Tigeot /* 2374a05eeebfSFrançois Tigeot * Not enough space for the basic request. So need to flush 2375a05eeebfSFrançois Tigeot * out the remainder and then wait for base + reserved. 2376a05eeebfSFrançois Tigeot */ 2377a05eeebfSFrançois Tigeot wait_bytes = remain_actual + total_bytes; 2378a05eeebfSFrançois Tigeot need_wrap = true; 23798621f407SFrançois Tigeot } else if (unlikely(total_bytes > remain_usable)) { 2380a05eeebfSFrançois Tigeot /* 2381a05eeebfSFrançois Tigeot * The base request will fit but the reserved space 23828621f407SFrançois Tigeot * falls off the end. So we don't need an immediate wrap 2383c0e85e96SFrançois Tigeot * and only need to effectively wait for the reserved 2384c0e85e96SFrançois Tigeot * size space from the start of ringbuffer. 2385a05eeebfSFrançois Tigeot */ 23861487f786SFrançois Tigeot wait_bytes = remain_actual + req->reserved_space; 23878621f407SFrançois Tigeot } else { 2388a05eeebfSFrançois Tigeot /* No wrapping required, just waiting. */ 2389a05eeebfSFrançois Tigeot wait_bytes = total_bytes; 2390a05eeebfSFrançois Tigeot } 2391a05eeebfSFrançois Tigeot 23928621f407SFrançois Tigeot if (wait_bytes > ringbuf->space) { 23938621f407SFrançois Tigeot int ret = wait_for_space(req, wait_bytes); 2394a2fdbec6SFrançois Tigeot if (unlikely(ret)) 2395a2fdbec6SFrançois Tigeot return ret; 2396a05eeebfSFrançois Tigeot 23978621f407SFrançois Tigeot intel_ring_update_space(ringbuf); 23988621f407SFrançois Tigeot if (unlikely(ringbuf->space < wait_bytes)) 23998621f407SFrançois Tigeot return -EAGAIN; 2400a2fdbec6SFrançois Tigeot } 2401a2fdbec6SFrançois Tigeot 24028621f407SFrançois Tigeot if (unlikely(need_wrap)) { 24038621f407SFrançois Tigeot GEM_BUG_ON(remain_actual > ringbuf->space); 24048621f407SFrançois Tigeot GEM_BUG_ON(ringbuf->tail + remain_actual > ringbuf->size); 24058621f407SFrançois Tigeot 24068621f407SFrançois Tigeot /* Fill the tail with MI_NOOP */ 24078621f407SFrançois Tigeot memset(ringbuf->virtual_start + ringbuf->tail, 24088621f407SFrançois Tigeot 0, remain_actual); 24098621f407SFrançois Tigeot ringbuf->tail = 0; 24108621f407SFrançois Tigeot ringbuf->space -= remain_actual; 2411a2fdbec6SFrançois Tigeot } 2412a2fdbec6SFrançois Tigeot 24138621f407SFrançois Tigeot ringbuf->space -= bytes; 24148621f407SFrançois Tigeot GEM_BUG_ON(ringbuf->space < 0); 24159edbd4a0SFrançois Tigeot return 0; 24169edbd4a0SFrançois Tigeot } 24179edbd4a0SFrançois Tigeot 24189edbd4a0SFrançois Tigeot /* Align the ring tail to a cacheline boundary */ 2419a05eeebfSFrançois Tigeot int intel_ring_cacheline_align(struct drm_i915_gem_request *req) 24209edbd4a0SFrançois Tigeot { 24218621f407SFrançois Tigeot struct intel_engine_cs *engine = req->engine; 24228621f407SFrançois Tigeot int num_dwords = (engine->buffer->tail & (CACHELINE_BYTES - 1)) / sizeof(uint32_t); 24239edbd4a0SFrançois Tigeot int ret; 24249edbd4a0SFrançois Tigeot 24259edbd4a0SFrançois Tigeot if (num_dwords == 0) 24269edbd4a0SFrançois Tigeot return 0; 24279edbd4a0SFrançois Tigeot 2428ba55f2f5SFrançois Tigeot num_dwords = CACHELINE_BYTES / sizeof(uint32_t) - num_dwords; 2429a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, num_dwords); 24309edbd4a0SFrançois Tigeot if (ret) 24319edbd4a0SFrançois Tigeot return ret; 24329edbd4a0SFrançois Tigeot 24339edbd4a0SFrançois Tigeot while (num_dwords--) 24348621f407SFrançois Tigeot intel_ring_emit(engine, MI_NOOP); 24359edbd4a0SFrançois Tigeot 24368621f407SFrançois Tigeot intel_ring_advance(engine); 24379edbd4a0SFrançois Tigeot 24389edbd4a0SFrançois Tigeot return 0; 2439e3adcf8fSFrançois Tigeot } 2440e3adcf8fSFrançois Tigeot 24418621f407SFrançois Tigeot void intel_ring_init_seqno(struct intel_engine_cs *engine, u32 seqno) 2442a2fdbec6SFrançois Tigeot { 24431487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 2444a2fdbec6SFrançois Tigeot 24458621f407SFrançois Tigeot /* Our semaphore implementation is strictly monotonic (i.e. we proceed 24468621f407SFrançois Tigeot * so long as the semaphore value in the register/page is greater 24478621f407SFrançois Tigeot * than the sync value), so whenever we reset the seqno, 24488621f407SFrançois Tigeot * so long as we reset the tracking semaphore value to 0, it will 24498621f407SFrançois Tigeot * always be before the next request's seqno. If we don't reset 24508621f407SFrançois Tigeot * the semaphore value, then when the seqno moves backwards all 24518621f407SFrançois Tigeot * future waits will complete instantly (causing rendering corruption). 24528621f407SFrançois Tigeot */ 24531487f786SFrançois Tigeot if (IS_GEN6(dev_priv) || IS_GEN7(dev_priv)) { 24548621f407SFrançois Tigeot I915_WRITE(RING_SYNC_0(engine->mmio_base), 0); 24558621f407SFrançois Tigeot I915_WRITE(RING_SYNC_1(engine->mmio_base), 0); 24568621f407SFrançois Tigeot if (HAS_VEBOX(dev_priv)) 24578621f407SFrançois Tigeot I915_WRITE(RING_SYNC_2(engine->mmio_base), 0); 24588621f407SFrançois Tigeot } 24598621f407SFrançois Tigeot if (dev_priv->semaphore_obj) { 24608621f407SFrançois Tigeot struct drm_i915_gem_object *obj = dev_priv->semaphore_obj; 2461f0bba3d1SFrançois Tigeot struct page *page = i915_gem_object_get_dirty_page(obj, 0); 24621487f786SFrançois Tigeot void *semaphores = kmap(page); 24638621f407SFrançois Tigeot memset(semaphores + GEN8_SEMAPHORE_OFFSET(engine->id, 0), 24648621f407SFrançois Tigeot 0, I915_NUM_ENGINES * gen8_semaphore_seqno_size); 24658621f407SFrançois Tigeot kunmap(page); 24668621f407SFrançois Tigeot } 24678621f407SFrançois Tigeot memset(engine->semaphore.sync_seqno, 0, 24688621f407SFrançois Tigeot sizeof(engine->semaphore.sync_seqno)); 24698621f407SFrançois Tigeot 2470*303bf270SFrançois Tigeot intel_write_status_page(engine, I915_GEM_HWS_INDEX, seqno); 2471*303bf270SFrançois Tigeot if (engine->irq_seqno_barrier) 2472*303bf270SFrançois Tigeot engine->irq_seqno_barrier(engine); 24738621f407SFrançois Tigeot engine->last_submitted_seqno = seqno; 24748621f407SFrançois Tigeot 24758621f407SFrançois Tigeot engine->hangcheck.seqno = seqno; 2476*303bf270SFrançois Tigeot 2477*303bf270SFrançois Tigeot /* After manually advancing the seqno, fake the interrupt in case 2478*303bf270SFrançois Tigeot * there are any waiters for that seqno. 2479*303bf270SFrançois Tigeot */ 2480*303bf270SFrançois Tigeot rcu_read_lock(); 2481*303bf270SFrançois Tigeot intel_engine_wakeup(engine); 2482*303bf270SFrançois Tigeot rcu_read_unlock(); 2483e3adcf8fSFrançois Tigeot } 2484e3adcf8fSFrançois Tigeot 24858621f407SFrançois Tigeot static void gen6_bsd_ring_write_tail(struct intel_engine_cs *engine, 2486f4e1c372SFrançois Tigeot u32 value) 2487e3adcf8fSFrançois Tigeot { 24881487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 24891487f786SFrançois Tigeot 24901487f786SFrançois Tigeot intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL); 2491e3adcf8fSFrançois Tigeot 2492e3adcf8fSFrançois Tigeot /* Every tail move must follow the sequence below */ 2493f4e1c372SFrançois Tigeot 2494f4e1c372SFrançois Tigeot /* Disable notification that the ring is IDLE. The GT 2495f4e1c372SFrançois Tigeot * will then assume that it is busy and bring it out of rc6. 2496f4e1c372SFrançois Tigeot */ 24971487f786SFrançois Tigeot I915_WRITE_FW(GEN6_BSD_SLEEP_PSMI_CONTROL, 2498f4e1c372SFrançois Tigeot _MASKED_BIT_ENABLE(GEN6_BSD_SLEEP_MSG_DISABLE)); 2499e3adcf8fSFrançois Tigeot 2500f4e1c372SFrançois Tigeot /* Clear the context id. Here be magic! */ 25011487f786SFrançois Tigeot I915_WRITE64_FW(GEN6_BSD_RNCID, 0x0); 2502e3adcf8fSFrançois Tigeot 2503f4e1c372SFrançois Tigeot /* Wait for the ring not to be idle, i.e. for it to wake up. */ 25041487f786SFrançois Tigeot if (intel_wait_for_register_fw(dev_priv, 25051487f786SFrançois Tigeot GEN6_BSD_SLEEP_PSMI_CONTROL, 25061487f786SFrançois Tigeot GEN6_BSD_SLEEP_INDICATOR, 25071487f786SFrançois Tigeot 0, 2508f4e1c372SFrançois Tigeot 50)) 2509f4e1c372SFrançois Tigeot DRM_ERROR("timed out waiting for the BSD ring to wake up\n"); 2510f4e1c372SFrançois Tigeot 2511f4e1c372SFrançois Tigeot /* Now that the ring is fully powered up, update the tail */ 25121487f786SFrançois Tigeot I915_WRITE_FW(RING_TAIL(engine->mmio_base), value); 25131487f786SFrançois Tigeot POSTING_READ_FW(RING_TAIL(engine->mmio_base)); 2514f4e1c372SFrançois Tigeot 2515f4e1c372SFrançois Tigeot /* Let the ring send IDLE messages to the GT again, 2516f4e1c372SFrançois Tigeot * and so let it sleep to conserve power when idle. 2517f4e1c372SFrançois Tigeot */ 25181487f786SFrançois Tigeot I915_WRITE_FW(GEN6_BSD_SLEEP_PSMI_CONTROL, 2519f4e1c372SFrançois Tigeot _MASKED_BIT_DISABLE(GEN6_BSD_SLEEP_MSG_DISABLE)); 25201487f786SFrançois Tigeot 25211487f786SFrançois Tigeot intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL); 2522e3adcf8fSFrançois Tigeot } 2523e3adcf8fSFrançois Tigeot 2524a05eeebfSFrançois Tigeot static int gen6_bsd_ring_flush(struct drm_i915_gem_request *req, 2525b5c29a34SFrançois Tigeot u32 invalidate, u32 flush) 2526e3adcf8fSFrançois Tigeot { 25278621f407SFrançois Tigeot struct intel_engine_cs *engine = req->engine; 2528e3adcf8fSFrançois Tigeot uint32_t cmd; 2529e3adcf8fSFrançois Tigeot int ret; 2530e3adcf8fSFrançois Tigeot 2531a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 4); 2532e3adcf8fSFrançois Tigeot if (ret) 2533e3adcf8fSFrançois Tigeot return ret; 2534e3adcf8fSFrançois Tigeot 2535e3adcf8fSFrançois Tigeot cmd = MI_FLUSH_DW; 25361487f786SFrançois Tigeot if (INTEL_GEN(req->i915) >= 8) 25379edbd4a0SFrançois Tigeot cmd += 1; 25382c9916cdSFrançois Tigeot 25392c9916cdSFrançois Tigeot /* We always require a command barrier so that subsequent 25402c9916cdSFrançois Tigeot * commands, such as breadcrumb interrupts, are strictly ordered 25412c9916cdSFrançois Tigeot * wrt the contents of the write cache being flushed to memory 25422c9916cdSFrançois Tigeot * (and thus being coherent from the CPU). 25432c9916cdSFrançois Tigeot */ 25442c9916cdSFrançois Tigeot cmd |= MI_FLUSH_DW_STORE_INDEX | MI_FLUSH_DW_OP_STOREDW; 25452c9916cdSFrançois Tigeot 2546b5c29a34SFrançois Tigeot /* 2547b5c29a34SFrançois Tigeot * Bspec vol 1c.5 - video engine command streamer: 2548b5c29a34SFrançois Tigeot * "If ENABLED, all TLBs will be invalidated once the flush 2549b5c29a34SFrançois Tigeot * operation is complete. This bit is only valid when the 2550b5c29a34SFrançois Tigeot * Post-Sync Operation field is a value of 1h or 3h." 2551b5c29a34SFrançois Tigeot */ 2552e3adcf8fSFrançois Tigeot if (invalidate & I915_GEM_GPU_DOMAINS) 25532c9916cdSFrançois Tigeot cmd |= MI_INVALIDATE_TLB | MI_INVALIDATE_BSD; 25542c9916cdSFrançois Tigeot 25558621f407SFrançois Tigeot intel_ring_emit(engine, cmd); 25568621f407SFrançois Tigeot intel_ring_emit(engine, 25578621f407SFrançois Tigeot I915_GEM_HWS_SCRATCH_ADDR | MI_FLUSH_DW_USE_GTT); 25581487f786SFrançois Tigeot if (INTEL_GEN(req->i915) >= 8) { 25598621f407SFrançois Tigeot intel_ring_emit(engine, 0); /* upper addr */ 25608621f407SFrançois Tigeot intel_ring_emit(engine, 0); /* value */ 25619edbd4a0SFrançois Tigeot } else { 25628621f407SFrançois Tigeot intel_ring_emit(engine, 0); 25638621f407SFrançois Tigeot intel_ring_emit(engine, MI_NOOP); 25649edbd4a0SFrançois Tigeot } 25658621f407SFrançois Tigeot intel_ring_advance(engine); 25669edbd4a0SFrançois Tigeot return 0; 25679edbd4a0SFrançois Tigeot } 25689edbd4a0SFrançois Tigeot 25699edbd4a0SFrançois Tigeot static int 2570a05eeebfSFrançois Tigeot gen8_ring_dispatch_execbuffer(struct drm_i915_gem_request *req, 2571ba55f2f5SFrançois Tigeot u64 offset, u32 len, 2572477eb7f9SFrançois Tigeot unsigned dispatch_flags) 25739edbd4a0SFrançois Tigeot { 25748621f407SFrançois Tigeot struct intel_engine_cs *engine = req->engine; 25758621f407SFrançois Tigeot bool ppgtt = USES_PPGTT(engine->dev) && 2576477eb7f9SFrançois Tigeot !(dispatch_flags & I915_DISPATCH_SECURE); 25779edbd4a0SFrançois Tigeot int ret; 25789edbd4a0SFrançois Tigeot 2579a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 4); 25809edbd4a0SFrançois Tigeot if (ret) 25819edbd4a0SFrançois Tigeot return ret; 25829edbd4a0SFrançois Tigeot 25839edbd4a0SFrançois Tigeot /* FIXME(BDW): Address space and security selectors. */ 25848621f407SFrançois Tigeot intel_ring_emit(engine, MI_BATCH_BUFFER_START_GEN8 | (ppgtt<<8) | 2585a05eeebfSFrançois Tigeot (dispatch_flags & I915_DISPATCH_RS ? 2586a05eeebfSFrançois Tigeot MI_BATCH_RESOURCE_STREAMER : 0)); 25878621f407SFrançois Tigeot intel_ring_emit(engine, lower_32_bits(offset)); 25888621f407SFrançois Tigeot intel_ring_emit(engine, upper_32_bits(offset)); 25898621f407SFrançois Tigeot intel_ring_emit(engine, MI_NOOP); 25908621f407SFrançois Tigeot intel_ring_advance(engine); 25919edbd4a0SFrançois Tigeot 2592e3adcf8fSFrançois Tigeot return 0; 2593e3adcf8fSFrançois Tigeot } 2594e3adcf8fSFrançois Tigeot 2595e3adcf8fSFrançois Tigeot static int 2596a05eeebfSFrançois Tigeot hsw_ring_dispatch_execbuffer(struct drm_i915_gem_request *req, 2597ba55f2f5SFrançois Tigeot u64 offset, u32 len, 2598477eb7f9SFrançois Tigeot unsigned dispatch_flags) 2599e3adcf8fSFrançois Tigeot { 26008621f407SFrançois Tigeot struct intel_engine_cs *engine = req->engine; 2601e3adcf8fSFrançois Tigeot int ret; 2602e3adcf8fSFrançois Tigeot 2603a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 2); 2604e3adcf8fSFrançois Tigeot if (ret) 2605e3adcf8fSFrançois Tigeot return ret; 2606e3adcf8fSFrançois Tigeot 26078621f407SFrançois Tigeot intel_ring_emit(engine, 26081b13d190SFrançois Tigeot MI_BATCH_BUFFER_START | 2609477eb7f9SFrançois Tigeot (dispatch_flags & I915_DISPATCH_SECURE ? 2610a05eeebfSFrançois Tigeot 0 : MI_BATCH_PPGTT_HSW | MI_BATCH_NON_SECURE_HSW) | 2611a05eeebfSFrançois Tigeot (dispatch_flags & I915_DISPATCH_RS ? 2612a05eeebfSFrançois Tigeot MI_BATCH_RESOURCE_STREAMER : 0)); 2613b5c29a34SFrançois Tigeot /* bit0-7 is the length on GEN6+ */ 26148621f407SFrançois Tigeot intel_ring_emit(engine, offset); 26158621f407SFrançois Tigeot intel_ring_advance(engine); 2616b5c29a34SFrançois Tigeot 2617b5c29a34SFrançois Tigeot return 0; 2618b5c29a34SFrançois Tigeot } 2619b5c29a34SFrançois Tigeot 2620b5c29a34SFrançois Tigeot static int 2621a05eeebfSFrançois Tigeot gen6_ring_dispatch_execbuffer(struct drm_i915_gem_request *req, 2622ba55f2f5SFrançois Tigeot u64 offset, u32 len, 2623477eb7f9SFrançois Tigeot unsigned dispatch_flags) 2624b5c29a34SFrançois Tigeot { 26258621f407SFrançois Tigeot struct intel_engine_cs *engine = req->engine; 2626b5c29a34SFrançois Tigeot int ret; 2627b5c29a34SFrançois Tigeot 2628a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 2); 2629b5c29a34SFrançois Tigeot if (ret) 2630b5c29a34SFrançois Tigeot return ret; 2631b5c29a34SFrançois Tigeot 26328621f407SFrançois Tigeot intel_ring_emit(engine, 2633b5c29a34SFrançois Tigeot MI_BATCH_BUFFER_START | 2634477eb7f9SFrançois Tigeot (dispatch_flags & I915_DISPATCH_SECURE ? 2635477eb7f9SFrançois Tigeot 0 : MI_BATCH_NON_SECURE_I965)); 2636e3adcf8fSFrançois Tigeot /* bit0-7 is the length on GEN6+ */ 26378621f407SFrançois Tigeot intel_ring_emit(engine, offset); 26388621f407SFrançois Tigeot intel_ring_advance(engine); 2639e3adcf8fSFrançois Tigeot 2640e3adcf8fSFrançois Tigeot return 0; 2641e3adcf8fSFrançois Tigeot } 2642e3adcf8fSFrançois Tigeot 2643e3adcf8fSFrançois Tigeot /* Blitter support (SandyBridge+) */ 2644e3adcf8fSFrançois Tigeot 2645a05eeebfSFrançois Tigeot static int gen6_ring_flush(struct drm_i915_gem_request *req, 2646b5c29a34SFrançois Tigeot u32 invalidate, u32 flush) 2647e3adcf8fSFrançois Tigeot { 26488621f407SFrançois Tigeot struct intel_engine_cs *engine = req->engine; 2649e3adcf8fSFrançois Tigeot uint32_t cmd; 2650e3adcf8fSFrançois Tigeot int ret; 2651e3adcf8fSFrançois Tigeot 2652a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 4); 2653e3adcf8fSFrançois Tigeot if (ret) 2654e3adcf8fSFrançois Tigeot return ret; 2655e3adcf8fSFrançois Tigeot 2656e3adcf8fSFrançois Tigeot cmd = MI_FLUSH_DW; 26571487f786SFrançois Tigeot if (INTEL_GEN(req->i915) >= 8) 26589edbd4a0SFrançois Tigeot cmd += 1; 26592c9916cdSFrançois Tigeot 26602c9916cdSFrançois Tigeot /* We always require a command barrier so that subsequent 26612c9916cdSFrançois Tigeot * commands, such as breadcrumb interrupts, are strictly ordered 26622c9916cdSFrançois Tigeot * wrt the contents of the write cache being flushed to memory 26632c9916cdSFrançois Tigeot * (and thus being coherent from the CPU). 26642c9916cdSFrançois Tigeot */ 26652c9916cdSFrançois Tigeot cmd |= MI_FLUSH_DW_STORE_INDEX | MI_FLUSH_DW_OP_STOREDW; 26662c9916cdSFrançois Tigeot 2667b5c29a34SFrançois Tigeot /* 2668b5c29a34SFrançois Tigeot * Bspec vol 1c.3 - blitter engine command streamer: 2669b5c29a34SFrançois Tigeot * "If ENABLED, all TLBs will be invalidated once the flush 2670b5c29a34SFrançois Tigeot * operation is complete. This bit is only valid when the 2671b5c29a34SFrançois Tigeot * Post-Sync Operation field is a value of 1h or 3h." 2672b5c29a34SFrançois Tigeot */ 2673e3adcf8fSFrançois Tigeot if (invalidate & I915_GEM_DOMAIN_RENDER) 26742c9916cdSFrançois Tigeot cmd |= MI_INVALIDATE_TLB; 26758621f407SFrançois Tigeot intel_ring_emit(engine, cmd); 26768621f407SFrançois Tigeot intel_ring_emit(engine, 26778621f407SFrançois Tigeot I915_GEM_HWS_SCRATCH_ADDR | MI_FLUSH_DW_USE_GTT); 26781487f786SFrançois Tigeot if (INTEL_GEN(req->i915) >= 8) { 26798621f407SFrançois Tigeot intel_ring_emit(engine, 0); /* upper addr */ 26808621f407SFrançois Tigeot intel_ring_emit(engine, 0); /* value */ 26819edbd4a0SFrançois Tigeot } else { 26828621f407SFrançois Tigeot intel_ring_emit(engine, 0); 26838621f407SFrançois Tigeot intel_ring_emit(engine, MI_NOOP); 26849edbd4a0SFrançois Tigeot } 26858621f407SFrançois Tigeot intel_ring_advance(engine); 26865d0b1887SFrançois Tigeot 2687e3adcf8fSFrançois Tigeot return 0; 2688e3adcf8fSFrançois Tigeot } 2689e3adcf8fSFrançois Tigeot 26901487f786SFrançois Tigeot static void intel_ring_init_semaphores(struct drm_i915_private *dev_priv, 26911487f786SFrançois Tigeot struct intel_engine_cs *engine) 26921487f786SFrançois Tigeot { 26931487f786SFrançois Tigeot struct drm_i915_gem_object *obj; 26941487f786SFrançois Tigeot int ret, i; 26951487f786SFrançois Tigeot 26961487f786SFrançois Tigeot if (!i915_semaphore_is_enabled(dev_priv)) 26971487f786SFrançois Tigeot return; 26981487f786SFrançois Tigeot 26991487f786SFrançois Tigeot if (INTEL_GEN(dev_priv) >= 8 && !dev_priv->semaphore_obj) { 2700*303bf270SFrançois Tigeot obj = i915_gem_object_create(&dev_priv->drm, 4096); 27011487f786SFrançois Tigeot if (IS_ERR(obj)) { 27021487f786SFrançois Tigeot DRM_ERROR("Failed to allocate semaphore bo. Disabling semaphores\n"); 27031487f786SFrançois Tigeot i915.semaphores = 0; 27041487f786SFrançois Tigeot } else { 27051487f786SFrançois Tigeot i915_gem_object_set_cache_level(obj, I915_CACHE_LLC); 27061487f786SFrançois Tigeot ret = i915_gem_obj_ggtt_pin(obj, 0, PIN_NONBLOCK); 27071487f786SFrançois Tigeot if (ret != 0) { 27081487f786SFrançois Tigeot drm_gem_object_unreference(&obj->base); 27091487f786SFrançois Tigeot DRM_ERROR("Failed to pin semaphore bo. Disabling semaphores\n"); 27101487f786SFrançois Tigeot i915.semaphores = 0; 27111487f786SFrançois Tigeot } else { 27121487f786SFrançois Tigeot dev_priv->semaphore_obj = obj; 27131487f786SFrançois Tigeot } 27141487f786SFrançois Tigeot } 27151487f786SFrançois Tigeot } 27161487f786SFrançois Tigeot 27171487f786SFrançois Tigeot if (!i915_semaphore_is_enabled(dev_priv)) 27181487f786SFrançois Tigeot return; 27191487f786SFrançois Tigeot 27201487f786SFrançois Tigeot if (INTEL_GEN(dev_priv) >= 8) { 27211487f786SFrançois Tigeot u64 offset = i915_gem_obj_ggtt_offset(dev_priv->semaphore_obj); 27221487f786SFrançois Tigeot 27231487f786SFrançois Tigeot engine->semaphore.sync_to = gen8_ring_sync; 27241487f786SFrançois Tigeot engine->semaphore.signal = gen8_xcs_signal; 27251487f786SFrançois Tigeot 27261487f786SFrançois Tigeot for (i = 0; i < I915_NUM_ENGINES; i++) { 27271487f786SFrançois Tigeot u64 ring_offset; 27281487f786SFrançois Tigeot 27291487f786SFrançois Tigeot if (i != engine->id) 27301487f786SFrançois Tigeot ring_offset = offset + GEN8_SEMAPHORE_OFFSET(engine->id, i); 27311487f786SFrançois Tigeot else 27321487f786SFrançois Tigeot ring_offset = MI_SEMAPHORE_SYNC_INVALID; 27331487f786SFrançois Tigeot 27341487f786SFrançois Tigeot engine->semaphore.signal_ggtt[i] = ring_offset; 27351487f786SFrançois Tigeot } 27361487f786SFrançois Tigeot } else if (INTEL_GEN(dev_priv) >= 6) { 27371487f786SFrançois Tigeot engine->semaphore.sync_to = gen6_ring_sync; 27381487f786SFrançois Tigeot engine->semaphore.signal = gen6_signal; 27391487f786SFrançois Tigeot 27401487f786SFrançois Tigeot /* 27411487f786SFrançois Tigeot * The current semaphore is only applied on pre-gen8 27421487f786SFrançois Tigeot * platform. And there is no VCS2 ring on the pre-gen8 27431487f786SFrançois Tigeot * platform. So the semaphore between RCS and VCS2 is 27441487f786SFrançois Tigeot * initialized as INVALID. Gen8 will initialize the 27451487f786SFrançois Tigeot * sema between VCS2 and RCS later. 27461487f786SFrançois Tigeot */ 27471487f786SFrançois Tigeot for (i = 0; i < I915_NUM_ENGINES; i++) { 27481487f786SFrançois Tigeot static const struct { 27491487f786SFrançois Tigeot u32 wait_mbox; 27501487f786SFrançois Tigeot i915_reg_t mbox_reg; 27511487f786SFrançois Tigeot } sem_data[I915_NUM_ENGINES][I915_NUM_ENGINES] = { 27521487f786SFrançois Tigeot [RCS] = { 27531487f786SFrançois Tigeot [VCS] = { .wait_mbox = MI_SEMAPHORE_SYNC_RV, .mbox_reg = GEN6_VRSYNC }, 27541487f786SFrançois Tigeot [BCS] = { .wait_mbox = MI_SEMAPHORE_SYNC_RB, .mbox_reg = GEN6_BRSYNC }, 27551487f786SFrançois Tigeot [VECS] = { .wait_mbox = MI_SEMAPHORE_SYNC_RVE, .mbox_reg = GEN6_VERSYNC }, 27561487f786SFrançois Tigeot }, 27571487f786SFrançois Tigeot [VCS] = { 27581487f786SFrançois Tigeot [RCS] = { .wait_mbox = MI_SEMAPHORE_SYNC_VR, .mbox_reg = GEN6_RVSYNC }, 27591487f786SFrançois Tigeot [BCS] = { .wait_mbox = MI_SEMAPHORE_SYNC_VB, .mbox_reg = GEN6_BVSYNC }, 27601487f786SFrançois Tigeot [VECS] = { .wait_mbox = MI_SEMAPHORE_SYNC_VVE, .mbox_reg = GEN6_VEVSYNC }, 27611487f786SFrançois Tigeot }, 27621487f786SFrançois Tigeot [BCS] = { 27631487f786SFrançois Tigeot [RCS] = { .wait_mbox = MI_SEMAPHORE_SYNC_BR, .mbox_reg = GEN6_RBSYNC }, 27641487f786SFrançois Tigeot [VCS] = { .wait_mbox = MI_SEMAPHORE_SYNC_BV, .mbox_reg = GEN6_VBSYNC }, 27651487f786SFrançois Tigeot [VECS] = { .wait_mbox = MI_SEMAPHORE_SYNC_BVE, .mbox_reg = GEN6_VEBSYNC }, 27661487f786SFrançois Tigeot }, 27671487f786SFrançois Tigeot [VECS] = { 27681487f786SFrançois Tigeot [RCS] = { .wait_mbox = MI_SEMAPHORE_SYNC_VER, .mbox_reg = GEN6_RVESYNC }, 27691487f786SFrançois Tigeot [VCS] = { .wait_mbox = MI_SEMAPHORE_SYNC_VEV, .mbox_reg = GEN6_VVESYNC }, 27701487f786SFrançois Tigeot [BCS] = { .wait_mbox = MI_SEMAPHORE_SYNC_VEB, .mbox_reg = GEN6_BVESYNC }, 27711487f786SFrançois Tigeot }, 27721487f786SFrançois Tigeot }; 27731487f786SFrançois Tigeot u32 wait_mbox; 27741487f786SFrançois Tigeot i915_reg_t mbox_reg; 27751487f786SFrançois Tigeot 27761487f786SFrançois Tigeot if (i == engine->id || i == VCS2) { 27771487f786SFrançois Tigeot wait_mbox = MI_SEMAPHORE_SYNC_INVALID; 27781487f786SFrançois Tigeot mbox_reg = GEN6_NOSYNC; 27791487f786SFrançois Tigeot } else { 27801487f786SFrançois Tigeot wait_mbox = sem_data[engine->id][i].wait_mbox; 27811487f786SFrançois Tigeot mbox_reg = sem_data[engine->id][i].mbox_reg; 27821487f786SFrançois Tigeot } 27831487f786SFrançois Tigeot 27841487f786SFrançois Tigeot engine->semaphore.mbox.wait[i] = wait_mbox; 27851487f786SFrançois Tigeot engine->semaphore.mbox.signal[i] = mbox_reg; 27861487f786SFrançois Tigeot } 27871487f786SFrançois Tigeot } 27881487f786SFrançois Tigeot } 27891487f786SFrançois Tigeot 27901487f786SFrançois Tigeot static void intel_ring_init_irq(struct drm_i915_private *dev_priv, 27911487f786SFrançois Tigeot struct intel_engine_cs *engine) 27921487f786SFrançois Tigeot { 27931487f786SFrançois Tigeot if (INTEL_GEN(dev_priv) >= 8) { 2794*303bf270SFrançois Tigeot engine->irq_enable = gen8_irq_enable; 2795*303bf270SFrançois Tigeot engine->irq_disable = gen8_irq_disable; 27961487f786SFrançois Tigeot engine->irq_seqno_barrier = gen6_seqno_barrier; 27971487f786SFrançois Tigeot } else if (INTEL_GEN(dev_priv) >= 6) { 2798*303bf270SFrançois Tigeot engine->irq_enable = gen6_irq_enable; 2799*303bf270SFrançois Tigeot engine->irq_disable = gen6_irq_disable; 28001487f786SFrançois Tigeot engine->irq_seqno_barrier = gen6_seqno_barrier; 28011487f786SFrançois Tigeot } else if (INTEL_GEN(dev_priv) >= 5) { 2802*303bf270SFrançois Tigeot engine->irq_enable = gen5_irq_enable; 2803*303bf270SFrançois Tigeot engine->irq_disable = gen5_irq_disable; 2804*303bf270SFrançois Tigeot engine->irq_seqno_barrier = gen5_seqno_barrier; 28051487f786SFrançois Tigeot } else if (INTEL_GEN(dev_priv) >= 3) { 2806*303bf270SFrançois Tigeot engine->irq_enable = i9xx_irq_enable; 2807*303bf270SFrançois Tigeot engine->irq_disable = i9xx_irq_disable; 28081487f786SFrançois Tigeot } else { 2809*303bf270SFrançois Tigeot engine->irq_enable = i8xx_irq_enable; 2810*303bf270SFrançois Tigeot engine->irq_disable = i8xx_irq_disable; 28111487f786SFrançois Tigeot } 28121487f786SFrançois Tigeot } 28131487f786SFrançois Tigeot 28141487f786SFrançois Tigeot static void intel_ring_default_vfuncs(struct drm_i915_private *dev_priv, 28151487f786SFrançois Tigeot struct intel_engine_cs *engine) 28161487f786SFrançois Tigeot { 28171487f786SFrançois Tigeot engine->init_hw = init_ring_common; 28181487f786SFrançois Tigeot engine->write_tail = ring_write_tail; 28191487f786SFrançois Tigeot 28201487f786SFrançois Tigeot engine->add_request = i9xx_add_request; 28211487f786SFrançois Tigeot if (INTEL_GEN(dev_priv) >= 6) 28221487f786SFrançois Tigeot engine->add_request = gen6_add_request; 28231487f786SFrançois Tigeot 28241487f786SFrançois Tigeot if (INTEL_GEN(dev_priv) >= 8) 28251487f786SFrançois Tigeot engine->dispatch_execbuffer = gen8_ring_dispatch_execbuffer; 28261487f786SFrançois Tigeot else if (INTEL_GEN(dev_priv) >= 6) 28271487f786SFrançois Tigeot engine->dispatch_execbuffer = gen6_ring_dispatch_execbuffer; 28281487f786SFrançois Tigeot else if (INTEL_GEN(dev_priv) >= 4) 28291487f786SFrançois Tigeot engine->dispatch_execbuffer = i965_dispatch_execbuffer; 28301487f786SFrançois Tigeot else if (IS_I830(dev_priv) || IS_845G(dev_priv)) 28311487f786SFrançois Tigeot engine->dispatch_execbuffer = i830_dispatch_execbuffer; 28321487f786SFrançois Tigeot else 28331487f786SFrançois Tigeot engine->dispatch_execbuffer = i915_dispatch_execbuffer; 28341487f786SFrançois Tigeot 28351487f786SFrançois Tigeot intel_ring_init_irq(dev_priv, engine); 28361487f786SFrançois Tigeot intel_ring_init_semaphores(dev_priv, engine); 28371487f786SFrançois Tigeot } 28381487f786SFrançois Tigeot 2839e3adcf8fSFrançois Tigeot int intel_init_render_ring_buffer(struct drm_device *dev) 2840e3adcf8fSFrançois Tigeot { 2841*303bf270SFrançois Tigeot struct drm_i915_private *dev_priv = to_i915(dev); 28428621f407SFrançois Tigeot struct intel_engine_cs *engine = &dev_priv->engine[RCS]; 284324edb884SFrançois Tigeot int ret; 2844e3adcf8fSFrançois Tigeot 28458621f407SFrançois Tigeot engine->name = "render ring"; 28468621f407SFrançois Tigeot engine->id = RCS; 28478621f407SFrançois Tigeot engine->exec_id = I915_EXEC_RENDER; 28488621f407SFrançois Tigeot engine->hw_id = 0; 28498621f407SFrançois Tigeot engine->mmio_base = RENDER_RING_BASE; 2850686a02f1SFrançois Tigeot 28511487f786SFrançois Tigeot intel_ring_default_vfuncs(dev_priv, engine); 28522c9916cdSFrançois Tigeot 2853*303bf270SFrançois Tigeot engine->irq_enable_mask = GT_RENDER_USER_INTERRUPT; 2854*303bf270SFrançois Tigeot if (HAS_L3_DPF(dev_priv)) 2855*303bf270SFrançois Tigeot engine->irq_keep_mask = GT_RENDER_L3_PARITY_ERROR_INTERRUPT; 2856*303bf270SFrançois Tigeot 28571487f786SFrançois Tigeot if (INTEL_GEN(dev_priv) >= 8) { 28588621f407SFrançois Tigeot engine->init_context = intel_rcs_ctx_init; 28591487f786SFrançois Tigeot engine->add_request = gen8_render_add_request; 28608621f407SFrançois Tigeot engine->flush = gen8_render_ring_flush; 28611487f786SFrançois Tigeot if (i915_semaphore_is_enabled(dev_priv)) 28628621f407SFrançois Tigeot engine->semaphore.signal = gen8_rcs_signal; 28631487f786SFrançois Tigeot } else if (INTEL_GEN(dev_priv) >= 6) { 28648621f407SFrançois Tigeot engine->init_context = intel_rcs_ctx_init; 28658621f407SFrançois Tigeot engine->flush = gen7_render_ring_flush; 28661487f786SFrançois Tigeot if (IS_GEN6(dev_priv)) 28678621f407SFrançois Tigeot engine->flush = gen6_render_ring_flush; 28681487f786SFrançois Tigeot } else if (IS_GEN5(dev_priv)) { 28698621f407SFrançois Tigeot engine->flush = gen4_render_ring_flush; 2870686a02f1SFrançois Tigeot } else { 28711487f786SFrançois Tigeot if (INTEL_GEN(dev_priv) < 4) 28728621f407SFrançois Tigeot engine->flush = gen2_render_ring_flush; 2873686a02f1SFrançois Tigeot else 28748621f407SFrançois Tigeot engine->flush = gen4_render_ring_flush; 28758621f407SFrançois Tigeot engine->irq_enable_mask = I915_USER_INTERRUPT; 2876686a02f1SFrançois Tigeot } 287724edb884SFrançois Tigeot 28781487f786SFrançois Tigeot if (IS_HASWELL(dev_priv)) 28798621f407SFrançois Tigeot engine->dispatch_execbuffer = hsw_ring_dispatch_execbuffer; 28801487f786SFrançois Tigeot 28818621f407SFrançois Tigeot engine->init_hw = init_render_ring; 28828621f407SFrançois Tigeot engine->cleanup = render_ring_cleanup; 2883e3adcf8fSFrançois Tigeot 28848621f407SFrançois Tigeot ret = intel_init_ring_buffer(dev, engine); 2885b5c29a34SFrançois Tigeot if (ret) 28862c9916cdSFrançois Tigeot return ret; 28872c9916cdSFrançois Tigeot 2888*303bf270SFrançois Tigeot if (INTEL_GEN(dev_priv) >= 6) { 2889*303bf270SFrançois Tigeot ret = intel_init_pipe_control(engine, 4096); 2890*303bf270SFrançois Tigeot if (ret) 2891*303bf270SFrançois Tigeot return ret; 2892*303bf270SFrançois Tigeot } else if (HAS_BROKEN_CS_TLB(dev_priv)) { 2893*303bf270SFrançois Tigeot ret = intel_init_pipe_control(engine, I830_WA_SIZE); 28942c9916cdSFrançois Tigeot if (ret) 28952c9916cdSFrançois Tigeot return ret; 2896b5c29a34SFrançois Tigeot } 2897b5c29a34SFrançois Tigeot 2898e3adcf8fSFrançois Tigeot return 0; 2899e3adcf8fSFrançois Tigeot } 2900e3adcf8fSFrançois Tigeot 2901e3adcf8fSFrançois Tigeot int intel_init_bsd_ring_buffer(struct drm_device *dev) 2902e3adcf8fSFrançois Tigeot { 2903*303bf270SFrançois Tigeot struct drm_i915_private *dev_priv = to_i915(dev); 29048621f407SFrançois Tigeot struct intel_engine_cs *engine = &dev_priv->engine[VCS]; 2905e3adcf8fSFrançois Tigeot 29068621f407SFrançois Tigeot engine->name = "bsd ring"; 29078621f407SFrançois Tigeot engine->id = VCS; 29088621f407SFrançois Tigeot engine->exec_id = I915_EXEC_BSD; 29098621f407SFrançois Tigeot engine->hw_id = 1; 2910686a02f1SFrançois Tigeot 29111487f786SFrançois Tigeot intel_ring_default_vfuncs(dev_priv, engine); 29121487f786SFrançois Tigeot 29131487f786SFrançois Tigeot if (INTEL_GEN(dev_priv) >= 6) { 29148621f407SFrançois Tigeot engine->mmio_base = GEN6_BSD_RING_BASE; 2915686a02f1SFrançois Tigeot /* gen6 bsd needs a special wa for tail updates */ 29161487f786SFrançois Tigeot if (IS_GEN6(dev_priv)) 29178621f407SFrançois Tigeot engine->write_tail = gen6_bsd_ring_write_tail; 29188621f407SFrançois Tigeot engine->flush = gen6_bsd_ring_flush; 29191487f786SFrançois Tigeot if (INTEL_GEN(dev_priv) >= 8) 29208621f407SFrançois Tigeot engine->irq_enable_mask = 29219edbd4a0SFrançois Tigeot GT_RENDER_USER_INTERRUPT << GEN8_VCS1_IRQ_SHIFT; 29221487f786SFrançois Tigeot else 29238621f407SFrançois Tigeot engine->irq_enable_mask = GT_BSD_USER_INTERRUPT; 2924686a02f1SFrançois Tigeot } else { 29258621f407SFrançois Tigeot engine->mmio_base = BSD_RING_BASE; 29268621f407SFrançois Tigeot engine->flush = bsd_ring_flush; 29271487f786SFrançois Tigeot if (IS_GEN5(dev_priv)) 29288621f407SFrançois Tigeot engine->irq_enable_mask = ILK_BSD_USER_INTERRUPT; 29291487f786SFrançois Tigeot else 29308621f407SFrançois Tigeot engine->irq_enable_mask = I915_BSD_USER_INTERRUPT; 2931686a02f1SFrançois Tigeot } 2932e3adcf8fSFrançois Tigeot 29338621f407SFrançois Tigeot return intel_init_ring_buffer(dev, engine); 2934e3adcf8fSFrançois Tigeot } 2935e3adcf8fSFrançois Tigeot 2936ba55f2f5SFrançois Tigeot /** 2937477eb7f9SFrançois Tigeot * Initialize the second BSD ring (eg. Broadwell GT3, Skylake GT3) 2938ba55f2f5SFrançois Tigeot */ 2939ba55f2f5SFrançois Tigeot int intel_init_bsd2_ring_buffer(struct drm_device *dev) 2940ba55f2f5SFrançois Tigeot { 2941*303bf270SFrançois Tigeot struct drm_i915_private *dev_priv = to_i915(dev); 29428621f407SFrançois Tigeot struct intel_engine_cs *engine = &dev_priv->engine[VCS2]; 2943ba55f2f5SFrançois Tigeot 29448621f407SFrançois Tigeot engine->name = "bsd2 ring"; 29458621f407SFrançois Tigeot engine->id = VCS2; 29468621f407SFrançois Tigeot engine->exec_id = I915_EXEC_BSD; 29478621f407SFrançois Tigeot engine->hw_id = 4; 29488621f407SFrançois Tigeot engine->mmio_base = GEN8_BSD2_RING_BASE; 29491487f786SFrançois Tigeot 29501487f786SFrançois Tigeot intel_ring_default_vfuncs(dev_priv, engine); 29511487f786SFrançois Tigeot 29528621f407SFrançois Tigeot engine->flush = gen6_bsd_ring_flush; 29538621f407SFrançois Tigeot engine->irq_enable_mask = 2954ba55f2f5SFrançois Tigeot GT_RENDER_USER_INTERRUPT << GEN8_VCS2_IRQ_SHIFT; 2955ba55f2f5SFrançois Tigeot 29568621f407SFrançois Tigeot return intel_init_ring_buffer(dev, engine); 2957ba55f2f5SFrançois Tigeot } 2958ba55f2f5SFrançois Tigeot 2959e3adcf8fSFrançois Tigeot int intel_init_blt_ring_buffer(struct drm_device *dev) 2960e3adcf8fSFrançois Tigeot { 2961*303bf270SFrançois Tigeot struct drm_i915_private *dev_priv = to_i915(dev); 29628621f407SFrançois Tigeot struct intel_engine_cs *engine = &dev_priv->engine[BCS]; 2963e3adcf8fSFrançois Tigeot 29648621f407SFrançois Tigeot engine->name = "blitter ring"; 29658621f407SFrançois Tigeot engine->id = BCS; 29668621f407SFrançois Tigeot engine->exec_id = I915_EXEC_BLT; 29678621f407SFrançois Tigeot engine->hw_id = 2; 29688621f407SFrançois Tigeot engine->mmio_base = BLT_RING_BASE; 29691487f786SFrançois Tigeot 29701487f786SFrançois Tigeot intel_ring_default_vfuncs(dev_priv, engine); 29711487f786SFrançois Tigeot 29728621f407SFrançois Tigeot engine->flush = gen6_ring_flush; 29731487f786SFrançois Tigeot if (INTEL_GEN(dev_priv) >= 8) 29748621f407SFrançois Tigeot engine->irq_enable_mask = 29759edbd4a0SFrançois Tigeot GT_RENDER_USER_INTERRUPT << GEN8_BCS_IRQ_SHIFT; 29761487f786SFrançois Tigeot else 29778621f407SFrançois Tigeot engine->irq_enable_mask = GT_BLT_USER_INTERRUPT; 29785d0b1887SFrançois Tigeot 29798621f407SFrançois Tigeot return intel_init_ring_buffer(dev, engine); 29805d0b1887SFrançois Tigeot } 29815d0b1887SFrançois Tigeot 29825d0b1887SFrançois Tigeot int intel_init_vebox_ring_buffer(struct drm_device *dev) 29835d0b1887SFrançois Tigeot { 2984*303bf270SFrançois Tigeot struct drm_i915_private *dev_priv = to_i915(dev); 29858621f407SFrançois Tigeot struct intel_engine_cs *engine = &dev_priv->engine[VECS]; 29865d0b1887SFrançois Tigeot 29878621f407SFrançois Tigeot engine->name = "video enhancement ring"; 29888621f407SFrançois Tigeot engine->id = VECS; 29898621f407SFrançois Tigeot engine->exec_id = I915_EXEC_VEBOX; 29908621f407SFrançois Tigeot engine->hw_id = 3; 29918621f407SFrançois Tigeot engine->mmio_base = VEBOX_RING_BASE; 29929edbd4a0SFrançois Tigeot 29931487f786SFrançois Tigeot intel_ring_default_vfuncs(dev_priv, engine); 29941487f786SFrançois Tigeot 29951487f786SFrançois Tigeot engine->flush = gen6_ring_flush; 29961487f786SFrançois Tigeot 29971487f786SFrançois Tigeot if (INTEL_GEN(dev_priv) >= 8) { 29988621f407SFrançois Tigeot engine->irq_enable_mask = 29999edbd4a0SFrançois Tigeot GT_RENDER_USER_INTERRUPT << GEN8_VECS_IRQ_SHIFT; 30009edbd4a0SFrançois Tigeot } else { 30018621f407SFrançois Tigeot engine->irq_enable_mask = PM_VEBOX_USER_INTERRUPT; 3002*303bf270SFrançois Tigeot engine->irq_enable = hsw_vebox_irq_enable; 3003*303bf270SFrançois Tigeot engine->irq_disable = hsw_vebox_irq_disable; 300424edb884SFrançois Tigeot } 3005e3adcf8fSFrançois Tigeot 30068621f407SFrançois Tigeot return intel_init_ring_buffer(dev, engine); 3007e3adcf8fSFrançois Tigeot } 3008b030f26bSFrançois Tigeot 3009b030f26bSFrançois Tigeot int 3010a05eeebfSFrançois Tigeot intel_ring_flush_all_caches(struct drm_i915_gem_request *req) 3011b030f26bSFrançois Tigeot { 30128621f407SFrançois Tigeot struct intel_engine_cs *engine = req->engine; 3013b030f26bSFrançois Tigeot int ret; 3014b030f26bSFrançois Tigeot 30158621f407SFrançois Tigeot if (!engine->gpu_caches_dirty) 3016b030f26bSFrançois Tigeot return 0; 3017b030f26bSFrançois Tigeot 30188621f407SFrançois Tigeot ret = engine->flush(req, 0, I915_GEM_GPU_DOMAINS); 3019b030f26bSFrançois Tigeot if (ret) 3020b030f26bSFrançois Tigeot return ret; 3021b030f26bSFrançois Tigeot 3022a05eeebfSFrançois Tigeot trace_i915_gem_ring_flush(req, 0, I915_GEM_GPU_DOMAINS); 3023a2fdbec6SFrançois Tigeot 30248621f407SFrançois Tigeot engine->gpu_caches_dirty = false; 3025b030f26bSFrançois Tigeot return 0; 3026b030f26bSFrançois Tigeot } 3027b030f26bSFrançois Tigeot 3028b030f26bSFrançois Tigeot int 3029a05eeebfSFrançois Tigeot intel_ring_invalidate_all_caches(struct drm_i915_gem_request *req) 3030b030f26bSFrançois Tigeot { 30318621f407SFrançois Tigeot struct intel_engine_cs *engine = req->engine; 3032b030f26bSFrançois Tigeot uint32_t flush_domains; 3033b030f26bSFrançois Tigeot int ret; 3034b030f26bSFrançois Tigeot 3035b030f26bSFrançois Tigeot flush_domains = 0; 30368621f407SFrançois Tigeot if (engine->gpu_caches_dirty) 3037b030f26bSFrançois Tigeot flush_domains = I915_GEM_GPU_DOMAINS; 3038b030f26bSFrançois Tigeot 30398621f407SFrançois Tigeot ret = engine->flush(req, I915_GEM_GPU_DOMAINS, flush_domains); 3040b030f26bSFrançois Tigeot if (ret) 3041b030f26bSFrançois Tigeot return ret; 3042b030f26bSFrançois Tigeot 3043a05eeebfSFrançois Tigeot trace_i915_gem_ring_flush(req, I915_GEM_GPU_DOMAINS, flush_domains); 3044a2fdbec6SFrançois Tigeot 30458621f407SFrançois Tigeot engine->gpu_caches_dirty = false; 3046b030f26bSFrançois Tigeot return 0; 3047b030f26bSFrançois Tigeot } 3048ba55f2f5SFrançois Tigeot 3049ba55f2f5SFrançois Tigeot void 30508621f407SFrançois Tigeot intel_stop_engine(struct intel_engine_cs *engine) 3051ba55f2f5SFrançois Tigeot { 3052ba55f2f5SFrançois Tigeot int ret; 3053ba55f2f5SFrançois Tigeot 30548621f407SFrançois Tigeot if (!intel_engine_initialized(engine)) 3055ba55f2f5SFrançois Tigeot return; 3056ba55f2f5SFrançois Tigeot 30578621f407SFrançois Tigeot ret = intel_engine_idle(engine); 30588621f407SFrançois Tigeot if (ret) 3059ba55f2f5SFrançois Tigeot DRM_ERROR("failed to quiesce %s whilst cleaning up: %d\n", 30608621f407SFrançois Tigeot engine->name, ret); 3061ba55f2f5SFrançois Tigeot 30628621f407SFrançois Tigeot stop_ring(engine); 3063ba55f2f5SFrançois Tigeot } 3064