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 static int init_ring_common(struct intel_engine_cs *engine) 5538621f407SFrançois Tigeot { 5541487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 5558621f407SFrançois Tigeot struct intel_ringbuffer *ringbuf = engine->buffer; 556ba55f2f5SFrançois Tigeot struct drm_i915_gem_object *obj = ringbuf->obj; 557ba55f2f5SFrançois Tigeot int ret = 0; 558ba55f2f5SFrançois Tigeot 5592c9916cdSFrançois Tigeot intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL); 560ba55f2f5SFrançois Tigeot 5618621f407SFrançois Tigeot if (!stop_ring(engine)) { 562ba55f2f5SFrançois Tigeot /* G45 ring initialization often fails to reset head to zero */ 563b5c29a34SFrançois Tigeot DRM_DEBUG_KMS("%s head not reset to zero " 564e3adcf8fSFrançois Tigeot "ctl %08x head %08x tail %08x start %08x\n", 5658621f407SFrançois Tigeot engine->name, 5668621f407SFrançois Tigeot I915_READ_CTL(engine), 5678621f407SFrançois Tigeot I915_READ_HEAD(engine), 5688621f407SFrançois Tigeot I915_READ_TAIL(engine), 5698621f407SFrançois Tigeot I915_READ_START(engine)); 570e3adcf8fSFrançois Tigeot 5718621f407SFrançois Tigeot if (!stop_ring(engine)) { 572e3adcf8fSFrançois Tigeot DRM_ERROR("failed to set %s head to zero " 573e3adcf8fSFrançois Tigeot "ctl %08x head %08x tail %08x start %08x\n", 5748621f407SFrançois Tigeot engine->name, 5758621f407SFrançois Tigeot I915_READ_CTL(engine), 5768621f407SFrançois Tigeot I915_READ_HEAD(engine), 5778621f407SFrançois Tigeot I915_READ_TAIL(engine), 5788621f407SFrançois Tigeot I915_READ_START(engine)); 579686a02f1SFrançois Tigeot ret = -EIO; 580686a02f1SFrançois Tigeot goto out; 581e3adcf8fSFrançois Tigeot } 582ba55f2f5SFrançois Tigeot } 583ba55f2f5SFrançois Tigeot 5841487f786SFrançois Tigeot if (I915_NEED_GFX_HWS(dev_priv)) 5858621f407SFrançois Tigeot intel_ring_setup_status_page(engine); 586ba55f2f5SFrançois Tigeot else 5878621f407SFrançois Tigeot ring_setup_phys_status_page(engine); 588ba55f2f5SFrançois Tigeot 5890f370975SMatthew Dillon /* Enforce ordering by reading HEAD register back */ 5908621f407SFrançois Tigeot I915_READ_HEAD(engine); 5910f370975SMatthew Dillon 592ba55f2f5SFrançois Tigeot /* Initialize the ring. This must happen _after_ we've cleared the ring 593ba55f2f5SFrançois Tigeot * registers with the above sequence (the readback of the HEAD registers 594ba55f2f5SFrançois Tigeot * also enforces ordering), otherwise the hw might lose the new ring 595ba55f2f5SFrançois Tigeot * register values. */ 5968621f407SFrançois Tigeot I915_WRITE_START(engine, i915_gem_obj_ggtt_offset(obj)); 5971b13d190SFrançois Tigeot 5981b13d190SFrançois Tigeot /* WaClearRingBufHeadRegAtInit:ctg,elk */ 5998621f407SFrançois Tigeot if (I915_READ_HEAD(engine)) 6001b13d190SFrançois Tigeot DRM_DEBUG("%s initialization failed [head=%08x], fudging\n", 6018621f407SFrançois Tigeot engine->name, I915_READ_HEAD(engine)); 6028621f407SFrançois Tigeot I915_WRITE_HEAD(engine, 0); 6038621f407SFrançois Tigeot (void)I915_READ_HEAD(engine); 6041b13d190SFrançois Tigeot 6058621f407SFrançois Tigeot I915_WRITE_CTL(engine, 606ba55f2f5SFrançois Tigeot ((ringbuf->size - PAGE_SIZE) & RING_NR_PAGES) 607ba55f2f5SFrançois Tigeot | RING_VALID); 608ba55f2f5SFrançois Tigeot 609ba55f2f5SFrançois Tigeot /* If the head is still not zero, the ring is dead */ 6108621f407SFrançois Tigeot if (wait_for((I915_READ_CTL(engine) & RING_VALID) != 0 && 6118621f407SFrançois Tigeot I915_READ_START(engine) == i915_gem_obj_ggtt_offset(obj) && 6128621f407SFrançois Tigeot (I915_READ_HEAD(engine) & HEAD_ADDR) == 0, 50)) { 613ba55f2f5SFrançois Tigeot DRM_ERROR("%s initialization failed " 614ba55f2f5SFrançois Tigeot "ctl %08x (valid? %d) head %08x tail %08x start %08x [expected %08lx]\n", 6158621f407SFrançois Tigeot engine->name, 6168621f407SFrançois Tigeot I915_READ_CTL(engine), 6178621f407SFrançois Tigeot I915_READ_CTL(engine) & RING_VALID, 6188621f407SFrançois Tigeot I915_READ_HEAD(engine), I915_READ_TAIL(engine), 6198621f407SFrançois Tigeot I915_READ_START(engine), 6208621f407SFrançois Tigeot (unsigned long)i915_gem_obj_ggtt_offset(obj)); 621ba55f2f5SFrançois Tigeot ret = -EIO; 622ba55f2f5SFrançois Tigeot goto out; 623ba55f2f5SFrançois Tigeot } 624e3adcf8fSFrançois Tigeot 6252c9916cdSFrançois Tigeot ringbuf->last_retired_head = -1; 6268621f407SFrançois Tigeot ringbuf->head = I915_READ_HEAD(engine); 6278621f407SFrançois Tigeot ringbuf->tail = I915_READ_TAIL(engine) & TAIL_ADDR; 6282c9916cdSFrançois Tigeot intel_ring_update_space(ringbuf); 629e3adcf8fSFrançois Tigeot 6308621f407SFrançois Tigeot intel_engine_init_hangcheck(engine); 6315d0b1887SFrançois Tigeot 632686a02f1SFrançois Tigeot out: 6332c9916cdSFrançois Tigeot intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL); 634686a02f1SFrançois Tigeot 635686a02f1SFrançois Tigeot return ret; 636e3adcf8fSFrançois Tigeot } 637e3adcf8fSFrançois Tigeot 638303bf270SFrançois Tigeot void intel_fini_pipe_control(struct intel_engine_cs *engine) 6391b13d190SFrançois Tigeot { 6408621f407SFrançois Tigeot if (engine->scratch.obj == NULL) 6411b13d190SFrançois Tigeot return; 6421b13d190SFrançois Tigeot 6438621f407SFrançois Tigeot i915_gem_object_ggtt_unpin(engine->scratch.obj); 644*87df8fc6SFrançois Tigeot i915_gem_object_put(engine->scratch.obj); 6458621f407SFrançois Tigeot engine->scratch.obj = NULL; 6461b13d190SFrançois Tigeot } 6471b13d190SFrançois Tigeot 648303bf270SFrançois Tigeot int intel_init_pipe_control(struct intel_engine_cs *engine, int size) 649e3adcf8fSFrançois Tigeot { 650303bf270SFrançois Tigeot struct drm_i915_gem_object *obj; 651e3adcf8fSFrançois Tigeot int ret; 652e3adcf8fSFrançois Tigeot 6538621f407SFrançois Tigeot WARN_ON(engine->scratch.obj); 654e3adcf8fSFrançois Tigeot 655303bf270SFrançois Tigeot obj = i915_gem_object_create_stolen(&engine->i915->drm, size); 656303bf270SFrançois Tigeot if (!obj) 657303bf270SFrançois Tigeot obj = i915_gem_object_create(&engine->i915->drm, size); 658303bf270SFrançois Tigeot if (IS_ERR(obj)) { 659303bf270SFrançois Tigeot DRM_ERROR("Failed to allocate scratch page\n"); 660303bf270SFrançois Tigeot ret = PTR_ERR(obj); 661e3adcf8fSFrançois Tigeot goto err; 662e3adcf8fSFrançois Tigeot } 663e3adcf8fSFrançois Tigeot 664303bf270SFrançois Tigeot ret = i915_gem_obj_ggtt_pin(obj, 4096, PIN_HIGH); 665ba55f2f5SFrançois Tigeot if (ret) 666ba55f2f5SFrançois Tigeot goto err_unref; 667e3adcf8fSFrançois Tigeot 668303bf270SFrançois Tigeot engine->scratch.obj = obj; 669303bf270SFrançois Tigeot engine->scratch.gtt_offset = i915_gem_obj_ggtt_offset(obj); 670a2fdbec6SFrançois Tigeot DRM_DEBUG_DRIVER("%s pipe control offset: 0x%08x\n", 6718621f407SFrançois Tigeot engine->name, engine->scratch.gtt_offset); 672e3adcf8fSFrançois Tigeot return 0; 673e3adcf8fSFrançois Tigeot 674e3adcf8fSFrançois Tigeot err_unref: 675*87df8fc6SFrançois Tigeot i915_gem_object_put(engine->scratch.obj); 676e3adcf8fSFrançois Tigeot err: 677e3adcf8fSFrançois Tigeot return ret; 678e3adcf8fSFrançois Tigeot } 679e3adcf8fSFrançois Tigeot 680a05eeebfSFrançois Tigeot static int intel_ring_workarounds_emit(struct drm_i915_gem_request *req) 6811b13d190SFrançois Tigeot { 6828621f407SFrançois Tigeot struct intel_engine_cs *engine = req->engine; 6831487f786SFrançois Tigeot struct i915_workarounds *w = &req->i915->workarounds; 6841487f786SFrançois Tigeot int ret, i; 6851b13d190SFrançois Tigeot 686352ff8bdSFrançois Tigeot if (w->count == 0) 6872c9916cdSFrançois Tigeot return 0; 6881b13d190SFrançois Tigeot 6898621f407SFrançois Tigeot engine->gpu_caches_dirty = true; 690a05eeebfSFrançois Tigeot ret = intel_ring_flush_all_caches(req); 6911b13d190SFrançois Tigeot if (ret) 6921b13d190SFrançois Tigeot return ret; 6931b13d190SFrançois Tigeot 694a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, (w->count * 2 + 2)); 6952c9916cdSFrançois Tigeot if (ret) 6962c9916cdSFrançois Tigeot return ret; 6972c9916cdSFrançois Tigeot 6988621f407SFrançois Tigeot intel_ring_emit(engine, MI_LOAD_REGISTER_IMM(w->count)); 6992c9916cdSFrançois Tigeot for (i = 0; i < w->count; i++) { 7008621f407SFrançois Tigeot intel_ring_emit_reg(engine, w->reg[i].addr); 7018621f407SFrançois Tigeot intel_ring_emit(engine, w->reg[i].value); 7022c9916cdSFrançois Tigeot } 7038621f407SFrançois Tigeot intel_ring_emit(engine, MI_NOOP); 7042c9916cdSFrançois Tigeot 7058621f407SFrançois Tigeot intel_ring_advance(engine); 7062c9916cdSFrançois Tigeot 7078621f407SFrançois Tigeot engine->gpu_caches_dirty = true; 708a05eeebfSFrançois Tigeot ret = intel_ring_flush_all_caches(req); 7092c9916cdSFrançois Tigeot if (ret) 7102c9916cdSFrançois Tigeot return ret; 7112c9916cdSFrançois Tigeot 7122c9916cdSFrançois Tigeot DRM_DEBUG_DRIVER("Number of Workarounds emitted: %d\n", w->count); 7132c9916cdSFrançois Tigeot 7142c9916cdSFrançois Tigeot return 0; 7152c9916cdSFrançois Tigeot } 7162c9916cdSFrançois Tigeot 717a05eeebfSFrançois Tigeot static int intel_rcs_ctx_init(struct drm_i915_gem_request *req) 7182c9916cdSFrançois Tigeot { 7192c9916cdSFrançois Tigeot int ret; 7202c9916cdSFrançois Tigeot 721a05eeebfSFrançois Tigeot ret = intel_ring_workarounds_emit(req); 7222c9916cdSFrançois Tigeot if (ret != 0) 7232c9916cdSFrançois Tigeot return ret; 7242c9916cdSFrançois Tigeot 725a05eeebfSFrançois Tigeot ret = i915_gem_render_state_init(req); 7262c9916cdSFrançois Tigeot if (ret) 7272c9916cdSFrançois Tigeot return ret; 728c0e85e96SFrançois Tigeot 729c0e85e96SFrançois Tigeot return 0; 7302c9916cdSFrançois Tigeot } 7312c9916cdSFrançois Tigeot 7322c9916cdSFrançois Tigeot static int wa_add(struct drm_i915_private *dev_priv, 733aee94f86SFrançois Tigeot i915_reg_t addr, 734aee94f86SFrançois Tigeot const u32 mask, const u32 val) 7352c9916cdSFrançois Tigeot { 7362c9916cdSFrançois Tigeot const u32 idx = dev_priv->workarounds.count; 7372c9916cdSFrançois Tigeot 7382c9916cdSFrançois Tigeot if (WARN_ON(idx >= I915_MAX_WA_REGS)) 7392c9916cdSFrançois Tigeot return -ENOSPC; 7402c9916cdSFrançois Tigeot 7412c9916cdSFrançois Tigeot dev_priv->workarounds.reg[idx].addr = addr; 7422c9916cdSFrançois Tigeot dev_priv->workarounds.reg[idx].value = val; 7432c9916cdSFrançois Tigeot dev_priv->workarounds.reg[idx].mask = mask; 7442c9916cdSFrançois Tigeot 7452c9916cdSFrançois Tigeot dev_priv->workarounds.count++; 7462c9916cdSFrançois Tigeot 7472c9916cdSFrançois Tigeot return 0; 7482c9916cdSFrançois Tigeot } 7492c9916cdSFrançois Tigeot 750a05eeebfSFrançois Tigeot #define WA_REG(addr, mask, val) do { \ 7512c9916cdSFrançois Tigeot const int r = wa_add(dev_priv, (addr), (mask), (val)); \ 7522c9916cdSFrançois Tigeot if (r) \ 7532c9916cdSFrançois Tigeot return r; \ 754a05eeebfSFrançois Tigeot } while (0) 7552c9916cdSFrançois Tigeot 7562c9916cdSFrançois Tigeot #define WA_SET_BIT_MASKED(addr, mask) \ 7572c9916cdSFrançois Tigeot WA_REG(addr, (mask), _MASKED_BIT_ENABLE(mask)) 7582c9916cdSFrançois Tigeot 7592c9916cdSFrançois Tigeot #define WA_CLR_BIT_MASKED(addr, mask) \ 7602c9916cdSFrançois Tigeot WA_REG(addr, (mask), _MASKED_BIT_DISABLE(mask)) 7612c9916cdSFrançois Tigeot 7622c9916cdSFrançois Tigeot #define WA_SET_FIELD_MASKED(addr, mask, value) \ 7632c9916cdSFrançois Tigeot WA_REG(addr, mask, _MASKED_FIELD(mask, value)) 7642c9916cdSFrançois Tigeot 7652c9916cdSFrançois Tigeot #define WA_SET_BIT(addr, mask) WA_REG(addr, mask, I915_READ(addr) | (mask)) 7662c9916cdSFrançois Tigeot #define WA_CLR_BIT(addr, mask) WA_REG(addr, mask, I915_READ(addr) & ~(mask)) 7672c9916cdSFrançois Tigeot 7682c9916cdSFrançois Tigeot #define WA_WRITE(addr, val) WA_REG(addr, 0xffffffff, val) 7692c9916cdSFrançois Tigeot 7708621f407SFrançois Tigeot static int wa_ring_whitelist_reg(struct intel_engine_cs *engine, 7718621f407SFrançois Tigeot i915_reg_t reg) 772c0e85e96SFrançois Tigeot { 7731487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 774c0e85e96SFrançois Tigeot struct i915_workarounds *wa = &dev_priv->workarounds; 7758621f407SFrançois Tigeot const uint32_t index = wa->hw_whitelist_count[engine->id]; 776c0e85e96SFrançois Tigeot 777c0e85e96SFrançois Tigeot if (WARN_ON(index >= RING_MAX_NONPRIV_SLOTS)) 778c0e85e96SFrançois Tigeot return -EINVAL; 779c0e85e96SFrançois Tigeot 7808621f407SFrançois Tigeot WA_WRITE(RING_FORCE_TO_NONPRIV(engine->mmio_base, index), 781c0e85e96SFrançois Tigeot i915_mmio_reg_offset(reg)); 7828621f407SFrançois Tigeot wa->hw_whitelist_count[engine->id]++; 783c0e85e96SFrançois Tigeot 784c0e85e96SFrançois Tigeot return 0; 785c0e85e96SFrançois Tigeot } 786c0e85e96SFrançois Tigeot 7878621f407SFrançois Tigeot static int gen8_init_workarounds(struct intel_engine_cs *engine) 7882c9916cdSFrançois Tigeot { 7891487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 7902c9916cdSFrançois Tigeot 791a05eeebfSFrançois Tigeot WA_SET_BIT_MASKED(INSTPM, INSTPM_FORCE_ORDERING); 792a05eeebfSFrançois Tigeot 793352ff8bdSFrançois Tigeot /* WaDisableAsyncFlipPerfMode:bdw,chv */ 794a05eeebfSFrançois Tigeot WA_SET_BIT_MASKED(MI_MODE, ASYNC_FLIP_PERF_DISABLE); 795a05eeebfSFrançois Tigeot 796352ff8bdSFrançois Tigeot /* WaDisablePartialInstShootdown:bdw,chv */ 7972c9916cdSFrançois Tigeot WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN, 798352ff8bdSFrançois Tigeot PARTIAL_INSTRUCTION_SHOOTDOWN_DISABLE); 7991b13d190SFrançois Tigeot 8001b13d190SFrançois Tigeot /* Use Force Non-Coherent whenever executing a 3D context. This is a 8011b13d190SFrançois Tigeot * workaround for for a possible hang in the unlikely event a TLB 8021b13d190SFrançois Tigeot * invalidation occurs during a PSD flush. 8031b13d190SFrançois Tigeot */ 804352ff8bdSFrançois Tigeot /* WaForceEnableNonCoherent:bdw,chv */ 805352ff8bdSFrançois Tigeot /* WaHdcDisableFetchWhenMasked:bdw,chv */ 8062c9916cdSFrançois Tigeot WA_SET_BIT_MASKED(HDC_CHICKEN0, 8072c9916cdSFrançois Tigeot HDC_DONOT_FETCH_MEM_WHEN_MASKED | 808352ff8bdSFrançois Tigeot HDC_FORCE_NON_COHERENT); 8092c9916cdSFrançois Tigeot 8102c9916cdSFrançois Tigeot /* From the Haswell PRM, Command Reference: Registers, CACHE_MODE_0: 8112c9916cdSFrançois Tigeot * "The Hierarchical Z RAW Stall Optimization allows non-overlapping 8122c9916cdSFrançois Tigeot * polygons in the same 8x4 pixel/sample area to be processed without 8132c9916cdSFrançois Tigeot * stalling waiting for the earlier ones to write to Hierarchical Z 8142c9916cdSFrançois Tigeot * buffer." 8152c9916cdSFrançois Tigeot * 816352ff8bdSFrançois Tigeot * This optimization is off by default for BDW and CHV; turn it on. 8172c9916cdSFrançois Tigeot */ 8182c9916cdSFrançois Tigeot WA_CLR_BIT_MASKED(CACHE_MODE_0_GEN7, HIZ_RAW_STALL_OPT_DISABLE); 8191b13d190SFrançois Tigeot 820352ff8bdSFrançois Tigeot /* Wa4x4STCOptimizationDisable:bdw,chv */ 821352ff8bdSFrançois Tigeot WA_SET_BIT_MASKED(CACHE_MODE_1, GEN8_4x4_STC_OPTIMIZATION_DISABLE); 8221b13d190SFrançois Tigeot 8231b13d190SFrançois Tigeot /* 8241b13d190SFrançois Tigeot * BSpec recommends 8x4 when MSAA is used, 8251b13d190SFrançois Tigeot * however in practice 16x4 seems fastest. 8261b13d190SFrançois Tigeot * 8271b13d190SFrançois Tigeot * Note that PS/WM thread counts depend on the WIZ hashing 8281b13d190SFrançois Tigeot * disable bit, which we don't touch here, but it's good 8291b13d190SFrançois Tigeot * to keep in mind (see 3DSTATE_PS and 3DSTATE_WM). 8301b13d190SFrançois Tigeot */ 8312c9916cdSFrançois Tigeot WA_SET_FIELD_MASKED(GEN7_GT_MODE, 8322c9916cdSFrançois Tigeot GEN6_WIZ_HASHING_MASK, 8332c9916cdSFrançois Tigeot GEN6_WIZ_HASHING_16x4); 8341b13d190SFrançois Tigeot 8351b13d190SFrançois Tigeot return 0; 8361b13d190SFrançois Tigeot } 8371b13d190SFrançois Tigeot 8388621f407SFrançois Tigeot static int bdw_init_workarounds(struct intel_engine_cs *engine) 8391b13d190SFrançois Tigeot { 8401487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 841352ff8bdSFrançois Tigeot int ret; 8421b13d190SFrançois Tigeot 8438621f407SFrançois Tigeot ret = gen8_init_workarounds(engine); 844352ff8bdSFrançois Tigeot if (ret) 845352ff8bdSFrançois Tigeot return ret; 846a05eeebfSFrançois Tigeot 847352ff8bdSFrançois Tigeot /* WaDisableThreadStallDopClockGating:bdw (pre-production) */ 848352ff8bdSFrançois Tigeot WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN, STALL_DOP_GATING_DISABLE); 849a05eeebfSFrançois Tigeot 850352ff8bdSFrançois Tigeot /* WaDisableDopClockGating:bdw */ 851352ff8bdSFrançois Tigeot WA_SET_BIT_MASKED(GEN7_ROW_CHICKEN2, 852352ff8bdSFrançois Tigeot DOP_CLOCK_GATING_DISABLE); 8531b13d190SFrançois Tigeot 854352ff8bdSFrançois Tigeot WA_SET_BIT_MASKED(HALF_SLICE_CHICKEN3, 855352ff8bdSFrançois Tigeot GEN8_SAMPLER_POWER_BYPASS_DIS); 856352ff8bdSFrançois Tigeot 8572c9916cdSFrançois Tigeot WA_SET_BIT_MASKED(HDC_CHICKEN0, 858352ff8bdSFrançois Tigeot /* WaForceContextSaveRestoreNonCoherent:bdw */ 859352ff8bdSFrançois Tigeot HDC_FORCE_CONTEXT_SAVE_RESTORE_NON_COHERENT | 860352ff8bdSFrançois Tigeot /* WaDisableFenceDestinationToSLM:bdw (pre-prod) */ 8611487f786SFrançois Tigeot (IS_BDW_GT3(dev_priv) ? HDC_FENCE_DEST_SLM_DISABLE : 0)); 8621b13d190SFrançois Tigeot 863352ff8bdSFrançois Tigeot return 0; 864352ff8bdSFrançois Tigeot } 8651b13d190SFrançois Tigeot 8668621f407SFrançois Tigeot static int chv_init_workarounds(struct intel_engine_cs *engine) 867352ff8bdSFrançois Tigeot { 8681487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 869352ff8bdSFrançois Tigeot int ret; 870352ff8bdSFrançois Tigeot 8718621f407SFrançois Tigeot ret = gen8_init_workarounds(engine); 872352ff8bdSFrançois Tigeot if (ret) 873352ff8bdSFrançois Tigeot return ret; 874352ff8bdSFrançois Tigeot 875352ff8bdSFrançois Tigeot /* WaDisableThreadStallDopClockGating:chv */ 876352ff8bdSFrançois Tigeot WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN, STALL_DOP_GATING_DISABLE); 8772c9916cdSFrançois Tigeot 8782c9916cdSFrançois Tigeot /* Improve HiZ throughput on CHV. */ 8792c9916cdSFrançois Tigeot WA_SET_BIT_MASKED(HIZ_CHICKEN, CHV_HZ_8X8_MODE_IN_1X); 8802c9916cdSFrançois Tigeot 8812c9916cdSFrançois Tigeot return 0; 8822c9916cdSFrançois Tigeot } 8832c9916cdSFrançois Tigeot 8848621f407SFrançois Tigeot static int gen9_init_workarounds(struct intel_engine_cs *engine) 885477eb7f9SFrançois Tigeot { 8861487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 887c0e85e96SFrançois Tigeot int ret; 888477eb7f9SFrançois Tigeot 8898621f407SFrançois Tigeot /* WaConextSwitchWithConcurrentTLBInvalidate:skl,bxt,kbl */ 8908621f407SFrançois Tigeot I915_WRITE(GEN9_CSFE_CHICKEN1_RCS, _MASKED_BIT_ENABLE(GEN9_PREEMPT_GPGPU_SYNC_SWITCH_DISABLE)); 8918621f407SFrançois Tigeot 8928621f407SFrançois Tigeot /* WaEnableLbsSlaRetryTimerDecrement:skl,bxt,kbl */ 893352ff8bdSFrançois Tigeot I915_WRITE(BDW_SCRATCH1, I915_READ(BDW_SCRATCH1) | 894352ff8bdSFrançois Tigeot GEN9_LBS_SLA_RETRY_TIMER_DECREMENT_ENABLE); 895352ff8bdSFrançois Tigeot 8968621f407SFrançois Tigeot /* WaDisableKillLogic:bxt,skl,kbl */ 897352ff8bdSFrançois Tigeot I915_WRITE(GAM_ECOCHK, I915_READ(GAM_ECOCHK) | 898352ff8bdSFrançois Tigeot ECOCHK_DIS_TLB); 899352ff8bdSFrançois Tigeot 9008621f407SFrançois Tigeot /* WaClearFlowControlGpgpuContextSave:skl,bxt,kbl */ 9018621f407SFrançois Tigeot /* WaDisablePartialInstShootdown:skl,bxt,kbl */ 902477eb7f9SFrançois Tigeot WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN, 9038621f407SFrançois Tigeot FLOW_CONTROL_ENABLE | 904477eb7f9SFrançois Tigeot PARTIAL_INSTRUCTION_SHOOTDOWN_DISABLE); 905477eb7f9SFrançois Tigeot 9068621f407SFrançois Tigeot /* Syncing dependencies between camera and graphics:skl,bxt,kbl */ 907477eb7f9SFrançois Tigeot WA_SET_BIT_MASKED(HALF_SLICE_CHICKEN3, 908477eb7f9SFrançois Tigeot GEN9_DISABLE_OCL_OOB_SUPPRESS_LOGIC); 909477eb7f9SFrançois Tigeot 91019c468b4SFrançois Tigeot /* WaDisableDgMirrorFixInHalfSliceChicken5:skl,bxt */ 9111487f786SFrançois Tigeot if (IS_SKL_REVID(dev_priv, 0, SKL_REVID_B0) || 9121487f786SFrançois Tigeot IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1)) 913477eb7f9SFrançois Tigeot WA_CLR_BIT_MASKED(GEN9_HALF_SLICE_CHICKEN5, 914477eb7f9SFrançois Tigeot GEN9_DG_MIRROR_FIX_ENABLE); 915477eb7f9SFrançois Tigeot 91619c468b4SFrançois Tigeot /* WaSetDisablePixMaskCammingAndRhwoInCommonSliceChicken:skl,bxt */ 9171487f786SFrançois Tigeot if (IS_SKL_REVID(dev_priv, 0, SKL_REVID_B0) || 9181487f786SFrançois Tigeot IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1)) { 919477eb7f9SFrançois Tigeot WA_SET_BIT_MASKED(GEN7_COMMON_SLICE_CHICKEN1, 920477eb7f9SFrançois Tigeot GEN9_RHWO_OPTIMIZATION_DISABLE); 921a05eeebfSFrançois Tigeot /* 922a05eeebfSFrançois Tigeot * WA also requires GEN9_SLICE_COMMON_ECO_CHICKEN0[14:14] to be set 923a05eeebfSFrançois Tigeot * but we do that in per ctx batchbuffer as there is an issue 924a05eeebfSFrançois Tigeot * with this register not getting restored on ctx restore 925a05eeebfSFrançois Tigeot */ 926477eb7f9SFrançois Tigeot } 927477eb7f9SFrançois Tigeot 9288621f407SFrançois Tigeot /* WaEnableYV12BugFixInHalfSliceChicken7:skl,bxt,kbl */ 9298621f407SFrançois Tigeot /* WaEnableSamplerGPGPUPreemptionSupport:skl,bxt,kbl */ 930477eb7f9SFrançois Tigeot WA_SET_BIT_MASKED(GEN9_HALF_SLICE_CHICKEN7, 9318621f407SFrançois Tigeot GEN9_ENABLE_YV12_BUGFIX | 9328621f407SFrançois Tigeot GEN9_ENABLE_GPGPU_PREEMPTION); 933477eb7f9SFrançois Tigeot 9348621f407SFrançois Tigeot /* Wa4x4STCOptimizationDisable:skl,bxt,kbl */ 9358621f407SFrançois Tigeot /* WaDisablePartialResolveInVc:skl,bxt,kbl */ 936352ff8bdSFrançois Tigeot WA_SET_BIT_MASKED(CACHE_MODE_1, (GEN8_4x4_STC_OPTIMIZATION_DISABLE | 937352ff8bdSFrançois Tigeot GEN9_PARTIAL_RESOLVE_IN_VC_DISABLE)); 938477eb7f9SFrançois Tigeot 9398621f407SFrançois Tigeot /* WaCcsTlbPrefetchDisable:skl,bxt,kbl */ 940477eb7f9SFrançois Tigeot WA_CLR_BIT_MASKED(GEN9_HALF_SLICE_CHICKEN5, 941477eb7f9SFrançois Tigeot GEN9_CCS_TLB_PREFETCH_ENABLE); 942477eb7f9SFrançois Tigeot 94319c468b4SFrançois Tigeot /* WaDisableMaskBasedCammingInRCC:skl,bxt */ 9441487f786SFrançois Tigeot if (IS_SKL_REVID(dev_priv, SKL_REVID_C0, SKL_REVID_C0) || 9451487f786SFrançois Tigeot IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1)) 94619c468b4SFrançois Tigeot WA_SET_BIT_MASKED(SLICE_ECO_CHICKEN0, 94719c468b4SFrançois Tigeot PIXEL_MASK_CAMMING_DISABLE); 94819c468b4SFrançois Tigeot 9498621f407SFrançois Tigeot /* WaForceContextSaveRestoreNonCoherent:skl,bxt,kbl */ 9508621f407SFrançois Tigeot WA_SET_BIT_MASKED(HDC_CHICKEN0, 9518621f407SFrançois Tigeot HDC_FORCE_CONTEXT_SAVE_RESTORE_NON_COHERENT | 9528621f407SFrançois Tigeot HDC_FORCE_CSR_NON_COHERENT_OVR_DISABLE); 95319c468b4SFrançois Tigeot 9548621f407SFrançois Tigeot /* WaForceEnableNonCoherent and WaDisableHDCInvalidation are 9558621f407SFrançois Tigeot * both tied to WaForceContextSaveRestoreNonCoherent 9568621f407SFrançois Tigeot * in some hsds for skl. We keep the tie for all gen9. The 9578621f407SFrançois Tigeot * documentation is a bit hazy and so we want to get common behaviour, 9588621f407SFrançois Tigeot * even though there is no clear evidence we would need both on kbl/bxt. 9598621f407SFrançois Tigeot * This area has been source of system hangs so we play it safe 9608621f407SFrançois Tigeot * and mimic the skl regardless of what bspec says. 9618621f407SFrançois Tigeot * 9628621f407SFrançois Tigeot * Use Force Non-Coherent whenever executing a 3D context. This 9638621f407SFrançois Tigeot * is a workaround for a possible hang in the unlikely event 9648621f407SFrançois Tigeot * a TLB invalidation occurs during a PSD flush. 9658621f407SFrançois Tigeot */ 9668621f407SFrançois Tigeot 9678621f407SFrançois Tigeot /* WaForceEnableNonCoherent:skl,bxt,kbl */ 9688621f407SFrançois Tigeot WA_SET_BIT_MASKED(HDC_CHICKEN0, 9698621f407SFrançois Tigeot HDC_FORCE_NON_COHERENT); 9708621f407SFrançois Tigeot 9718621f407SFrançois Tigeot /* WaDisableHDCInvalidation:skl,bxt,kbl */ 9728621f407SFrançois Tigeot I915_WRITE(GAM_ECOCHK, I915_READ(GAM_ECOCHK) | 9738621f407SFrançois Tigeot BDW_DISABLE_HDC_INVALIDATION); 9748621f407SFrançois Tigeot 9758621f407SFrançois Tigeot /* WaDisableSamplerPowerBypassForSOPingPong:skl,bxt,kbl */ 9768621f407SFrançois Tigeot if (IS_SKYLAKE(dev_priv) || 9778621f407SFrançois Tigeot IS_KABYLAKE(dev_priv) || 9788621f407SFrançois Tigeot IS_BXT_REVID(dev_priv, 0, BXT_REVID_B0)) 979352ff8bdSFrançois Tigeot WA_SET_BIT_MASKED(HALF_SLICE_CHICKEN3, 980352ff8bdSFrançois Tigeot GEN8_SAMPLER_POWER_BYPASS_DIS); 981352ff8bdSFrançois Tigeot 9828621f407SFrançois Tigeot /* WaDisableSTUnitPowerOptimization:skl,bxt,kbl */ 983352ff8bdSFrançois Tigeot WA_SET_BIT_MASKED(HALF_SLICE_CHICKEN2, GEN8_ST_PO_DISABLE); 984352ff8bdSFrançois Tigeot 9858621f407SFrançois Tigeot /* WaOCLCoherentLineFlush:skl,bxt,kbl */ 986c0e85e96SFrançois Tigeot I915_WRITE(GEN8_L3SQCREG4, (I915_READ(GEN8_L3SQCREG4) | 987c0e85e96SFrançois Tigeot GEN8_LQSC_FLUSH_COHERENT_LINES)); 988c0e85e96SFrançois Tigeot 9898621f407SFrançois Tigeot /* WaVFEStateAfterPipeControlwithMediaStateClear:skl,bxt */ 9908621f407SFrançois Tigeot ret = wa_ring_whitelist_reg(engine, GEN9_CTX_PREEMPT_REG); 991c0e85e96SFrançois Tigeot if (ret) 992c0e85e96SFrançois Tigeot return ret; 993c0e85e96SFrançois Tigeot 9948621f407SFrançois Tigeot /* WaEnablePreemptionGranularityControlByUMD:skl,bxt,kbl */ 9958621f407SFrançois Tigeot ret= wa_ring_whitelist_reg(engine, GEN8_CS_CHICKEN1); 9968621f407SFrançois Tigeot if (ret) 9978621f407SFrançois Tigeot return ret; 9988621f407SFrançois Tigeot 9998621f407SFrançois Tigeot /* WaAllowUMDToModifyHDCChicken1:skl,bxt,kbl */ 10008621f407SFrançois Tigeot ret = wa_ring_whitelist_reg(engine, GEN8_HDC_CHICKEN1); 1001c0e85e96SFrançois Tigeot if (ret) 1002c0e85e96SFrançois Tigeot return ret; 1003c0e85e96SFrançois Tigeot 1004477eb7f9SFrançois Tigeot return 0; 1005477eb7f9SFrançois Tigeot } 1006477eb7f9SFrançois Tigeot 10078621f407SFrançois Tigeot static int skl_tune_iz_hashing(struct intel_engine_cs *engine) 1008477eb7f9SFrançois Tigeot { 10091487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 1010477eb7f9SFrançois Tigeot u8 vals[3] = { 0, 0, 0 }; 1011477eb7f9SFrançois Tigeot unsigned int i; 1012477eb7f9SFrançois Tigeot 1013477eb7f9SFrançois Tigeot for (i = 0; i < 3; i++) { 1014477eb7f9SFrançois Tigeot u8 ss; 1015477eb7f9SFrançois Tigeot 1016477eb7f9SFrançois Tigeot /* 1017477eb7f9SFrançois Tigeot * Only consider slices where one, and only one, subslice has 7 1018477eb7f9SFrançois Tigeot * EUs 1019477eb7f9SFrançois Tigeot */ 1020aee94f86SFrançois Tigeot if (!is_power_of_2(dev_priv->info.subslice_7eu[i])) 1021477eb7f9SFrançois Tigeot continue; 1022477eb7f9SFrançois Tigeot 1023477eb7f9SFrançois Tigeot /* 1024477eb7f9SFrançois Tigeot * subslice_7eu[i] != 0 (because of the check above) and 1025477eb7f9SFrançois Tigeot * ss_max == 4 (maximum number of subslices possible per slice) 1026477eb7f9SFrançois Tigeot * 1027477eb7f9SFrançois Tigeot * -> 0 <= ss <= 3; 1028477eb7f9SFrançois Tigeot */ 1029477eb7f9SFrançois Tigeot ss = ffs(dev_priv->info.subslice_7eu[i]) - 1; 1030477eb7f9SFrançois Tigeot vals[i] = 3 - ss; 1031477eb7f9SFrançois Tigeot } 1032477eb7f9SFrançois Tigeot 1033477eb7f9SFrançois Tigeot if (vals[0] == 0 && vals[1] == 0 && vals[2] == 0) 1034477eb7f9SFrançois Tigeot return 0; 1035477eb7f9SFrançois Tigeot 1036477eb7f9SFrançois Tigeot /* Tune IZ hashing. See intel_device_info_runtime_init() */ 1037477eb7f9SFrançois Tigeot WA_SET_FIELD_MASKED(GEN7_GT_MODE, 1038477eb7f9SFrançois Tigeot GEN9_IZ_HASHING_MASK(2) | 1039477eb7f9SFrançois Tigeot GEN9_IZ_HASHING_MASK(1) | 1040477eb7f9SFrançois Tigeot GEN9_IZ_HASHING_MASK(0), 1041477eb7f9SFrançois Tigeot GEN9_IZ_HASHING(2, vals[2]) | 1042477eb7f9SFrançois Tigeot GEN9_IZ_HASHING(1, vals[1]) | 1043477eb7f9SFrançois Tigeot GEN9_IZ_HASHING(0, vals[0])); 1044477eb7f9SFrançois Tigeot 1045477eb7f9SFrançois Tigeot return 0; 1046477eb7f9SFrançois Tigeot } 1047477eb7f9SFrançois Tigeot 10488621f407SFrançois Tigeot static int skl_init_workarounds(struct intel_engine_cs *engine) 1049477eb7f9SFrançois Tigeot { 10501487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 1051352ff8bdSFrançois Tigeot int ret; 1052477eb7f9SFrançois Tigeot 10538621f407SFrançois Tigeot ret = gen9_init_workarounds(engine); 1054352ff8bdSFrançois Tigeot if (ret) 1055352ff8bdSFrançois Tigeot return ret; 1056352ff8bdSFrançois Tigeot 1057c0e85e96SFrançois Tigeot /* 1058c0e85e96SFrançois Tigeot * Actual WA is to disable percontext preemption granularity control 1059c0e85e96SFrançois Tigeot * until D0 which is the default case so this is equivalent to 1060c0e85e96SFrançois Tigeot * !WaDisablePerCtxtPreemptionGranularityControl:skl 1061c0e85e96SFrançois Tigeot */ 10621487f786SFrançois Tigeot if (IS_SKL_REVID(dev_priv, SKL_REVID_E0, REVID_FOREVER)) { 1063c0e85e96SFrançois Tigeot I915_WRITE(GEN7_FF_SLICE_CS_CHICKEN1, 1064c0e85e96SFrançois Tigeot _MASKED_BIT_ENABLE(GEN9_FFSC_PERCTX_PREEMPT_CTRL)); 1065c0e85e96SFrançois Tigeot } 1066c0e85e96SFrançois Tigeot 10671487f786SFrançois Tigeot if (IS_SKL_REVID(dev_priv, 0, SKL_REVID_E0)) { 1068352ff8bdSFrançois Tigeot /* WaDisableChickenBitTSGBarrierAckForFFSliceCS:skl */ 1069352ff8bdSFrançois Tigeot I915_WRITE(FF_SLICE_CS_CHICKEN2, 1070352ff8bdSFrançois Tigeot _MASKED_BIT_ENABLE(GEN9_TSG_BARRIER_ACK_DISABLE)); 1071352ff8bdSFrançois Tigeot } 1072352ff8bdSFrançois Tigeot 1073352ff8bdSFrançois Tigeot /* GEN8_L3SQCREG4 has a dependency with WA batch so any new changes 1074352ff8bdSFrançois Tigeot * involving this register should also be added to WA batch as required. 1075352ff8bdSFrançois Tigeot */ 10761487f786SFrançois Tigeot if (IS_SKL_REVID(dev_priv, 0, SKL_REVID_E0)) 1077352ff8bdSFrançois Tigeot /* WaDisableLSQCROPERFforOCL:skl */ 1078352ff8bdSFrançois Tigeot I915_WRITE(GEN8_L3SQCREG4, I915_READ(GEN8_L3SQCREG4) | 1079352ff8bdSFrançois Tigeot GEN8_LQSC_RO_PERF_DIS); 1080352ff8bdSFrançois Tigeot 1081352ff8bdSFrançois Tigeot /* WaEnableGapsTsvCreditFix:skl */ 10821487f786SFrançois Tigeot if (IS_SKL_REVID(dev_priv, SKL_REVID_C0, REVID_FOREVER)) { 1083352ff8bdSFrançois Tigeot I915_WRITE(GEN8_GARBCNTL, (I915_READ(GEN8_GARBCNTL) | 1084352ff8bdSFrançois Tigeot GEN9_GAPS_TSV_CREDIT_DISABLE)); 1085352ff8bdSFrançois Tigeot } 1086477eb7f9SFrançois Tigeot 1087477eb7f9SFrançois Tigeot /* WaDisablePowerCompilerClockGating:skl */ 10881487f786SFrançois Tigeot if (IS_SKL_REVID(dev_priv, SKL_REVID_B0, SKL_REVID_B0)) 1089477eb7f9SFrançois Tigeot WA_SET_BIT_MASKED(HIZ_CHICKEN, 1090477eb7f9SFrançois Tigeot BDW_HIZ_POWER_COMPILER_CLOCK_GATING_DISABLE); 1091477eb7f9SFrançois Tigeot 1092a05eeebfSFrançois Tigeot /* WaBarrierPerformanceFixDisable:skl */ 10931487f786SFrançois Tigeot if (IS_SKL_REVID(dev_priv, SKL_REVID_C0, SKL_REVID_D0)) 1094a05eeebfSFrançois Tigeot WA_SET_BIT_MASKED(HDC_CHICKEN0, 1095a05eeebfSFrançois Tigeot HDC_FENCE_DEST_SLM_DISABLE | 1096a05eeebfSFrançois Tigeot HDC_BARRIER_PERFORMANCE_DISABLE); 1097a05eeebfSFrançois Tigeot 1098a05eeebfSFrançois Tigeot /* WaDisableSbeCacheDispatchPortSharing:skl */ 10991487f786SFrançois Tigeot if (IS_SKL_REVID(dev_priv, 0, SKL_REVID_F0)) 1100a05eeebfSFrançois Tigeot WA_SET_BIT_MASKED( 1101a05eeebfSFrançois Tigeot GEN7_HALF_SLICE_CHICKEN1, 1102a05eeebfSFrançois Tigeot GEN7_SBE_SS_CACHE_DISPATCH_PORT_SHARING_DISABLE); 1103a05eeebfSFrançois Tigeot 11048621f407SFrançois Tigeot /* WaDisableGafsUnitClkGating:skl */ 11058621f407SFrançois Tigeot WA_SET_BIT(GEN7_UCGCTL4, GEN8_EU_GAUNIT_CLOCK_GATE_DISABLE); 11068621f407SFrançois Tigeot 1107bf017597SFrançois Tigeot /* WaInPlaceDecompressionHang:skl */ 1108bf017597SFrançois Tigeot if (IS_SKL_REVID(dev_priv, SKL_REVID_H0, REVID_FOREVER)) 1109bf017597SFrançois Tigeot WA_SET_BIT(GEN9_GAMT_ECO_REG_RW_IA, 1110bf017597SFrançois Tigeot GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS); 1111bf017597SFranç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 1176bf017597SFrançois Tigeot /* WaToEnableHwFixForPushConstHWBug:bxt */ 1177bf017597SFrançois Tigeot if (IS_BXT_REVID(dev_priv, BXT_REVID_C0, REVID_FOREVER)) 11788621f407SFrançois Tigeot WA_SET_BIT_MASKED(COMMON_SLICE_CHICKEN2, 11798621f407SFrançois Tigeot GEN8_SBE_DISABLE_REPLAY_BUF_OPTIMIZATION); 11808621f407SFrançois Tigeot 1181bf017597SFrançois Tigeot /* WaInPlaceDecompressionHang:bxt */ 1182bf017597SFrançois Tigeot if (IS_BXT_REVID(dev_priv, BXT_REVID_C0, REVID_FOREVER)) 1183bf017597SFrançois Tigeot WA_SET_BIT(GEN9_GAMT_ECO_REG_RW_IA, 1184bf017597SFrançois Tigeot GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS); 1185bf017597SFrançois Tigeot 118619c468b4SFrançois Tigeot return 0; 118719c468b4SFrançois Tigeot } 118819c468b4SFrançois Tigeot 11898621f407SFrançois Tigeot static int kbl_init_workarounds(struct intel_engine_cs *engine) 11902c9916cdSFrançois Tigeot { 11911487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 11928621f407SFrançois Tigeot int ret; 11938621f407SFrançois Tigeot 11948621f407SFrançois Tigeot ret = gen9_init_workarounds(engine); 11958621f407SFrançois Tigeot if (ret) 11968621f407SFrançois Tigeot return ret; 11978621f407SFrançois Tigeot 11988621f407SFrançois Tigeot /* WaEnableGapsTsvCreditFix:kbl */ 11998621f407SFrançois Tigeot I915_WRITE(GEN8_GARBCNTL, (I915_READ(GEN8_GARBCNTL) | 12008621f407SFrançois Tigeot GEN9_GAPS_TSV_CREDIT_DISABLE)); 12018621f407SFrançois Tigeot 12028621f407SFrançois Tigeot /* WaDisableDynamicCreditSharing:kbl */ 12038621f407SFrançois Tigeot if (IS_KBL_REVID(dev_priv, 0, KBL_REVID_B0)) 12048621f407SFrançois Tigeot WA_SET_BIT(GAMT_CHKN_BIT_REG, 12058621f407SFrançois Tigeot GAMT_CHKN_DISABLE_DYNAMIC_CREDIT_SHARING); 12068621f407SFrançois Tigeot 12078621f407SFrançois Tigeot /* WaDisableFenceDestinationToSLM:kbl (pre-prod) */ 12088621f407SFrançois Tigeot if (IS_KBL_REVID(dev_priv, KBL_REVID_A0, KBL_REVID_A0)) 12098621f407SFrançois Tigeot WA_SET_BIT_MASKED(HDC_CHICKEN0, 12108621f407SFrançois Tigeot HDC_FENCE_DEST_SLM_DISABLE); 12118621f407SFrançois Tigeot 12128621f407SFrançois Tigeot /* GEN8_L3SQCREG4 has a dependency with WA batch so any new changes 12138621f407SFrançois Tigeot * involving this register should also be added to WA batch as required. 12148621f407SFrançois Tigeot */ 12158621f407SFrançois Tigeot if (IS_KBL_REVID(dev_priv, 0, KBL_REVID_E0)) 12168621f407SFrançois Tigeot /* WaDisableLSQCROPERFforOCL:kbl */ 12178621f407SFrançois Tigeot I915_WRITE(GEN8_L3SQCREG4, I915_READ(GEN8_L3SQCREG4) | 12188621f407SFrançois Tigeot GEN8_LQSC_RO_PERF_DIS); 12198621f407SFrançois Tigeot 1220bf017597SFrançois Tigeot /* WaToEnableHwFixForPushConstHWBug:kbl */ 1221bf017597SFrançois Tigeot if (IS_KBL_REVID(dev_priv, KBL_REVID_C0, REVID_FOREVER)) 12228621f407SFrançois Tigeot WA_SET_BIT_MASKED(COMMON_SLICE_CHICKEN2, 12238621f407SFrançois Tigeot GEN8_SBE_DISABLE_REPLAY_BUF_OPTIMIZATION); 12248621f407SFrançois Tigeot 12258621f407SFrançois Tigeot /* WaDisableGafsUnitClkGating:kbl */ 12268621f407SFrançois Tigeot WA_SET_BIT(GEN7_UCGCTL4, GEN8_EU_GAUNIT_CLOCK_GATE_DISABLE); 12278621f407SFrançois Tigeot 12288621f407SFrançois Tigeot /* WaDisableSbeCacheDispatchPortSharing:kbl */ 12298621f407SFrançois Tigeot WA_SET_BIT_MASKED( 12308621f407SFrançois Tigeot GEN7_HALF_SLICE_CHICKEN1, 12318621f407SFrançois Tigeot GEN7_SBE_SS_CACHE_DISPATCH_PORT_SHARING_DISABLE); 12328621f407SFrançois Tigeot 1233bf017597SFrançois Tigeot /* WaInPlaceDecompressionHang:kbl */ 1234bf017597SFrançois Tigeot WA_SET_BIT(GEN9_GAMT_ECO_REG_RW_IA, 1235bf017597SFrançois Tigeot GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS); 1236bf017597SFrançois Tigeot 12378621f407SFrançois Tigeot /* WaDisableLSQCROPERFforOCL:kbl */ 12388621f407SFrançois Tigeot ret = wa_ring_whitelist_reg(engine, GEN8_L3SQCREG4); 12398621f407SFrançois Tigeot if (ret) 12408621f407SFrançois Tigeot return ret; 12418621f407SFrançois Tigeot 12428621f407SFrançois Tigeot return 0; 12438621f407SFrançois Tigeot } 12448621f407SFrançois Tigeot 12458621f407SFrançois Tigeot int init_workarounds_ring(struct intel_engine_cs *engine) 12468621f407SFrançois Tigeot { 12471487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 12482c9916cdSFrançois Tigeot 12498621f407SFrançois Tigeot WARN_ON(engine->id != RCS); 12502c9916cdSFrançois Tigeot 12512c9916cdSFrançois Tigeot dev_priv->workarounds.count = 0; 1252c0e85e96SFrançois Tigeot dev_priv->workarounds.hw_whitelist_count[RCS] = 0; 12532c9916cdSFrançois Tigeot 12541487f786SFrançois Tigeot if (IS_BROADWELL(dev_priv)) 12558621f407SFrançois Tigeot return bdw_init_workarounds(engine); 12562c9916cdSFrançois Tigeot 12571487f786SFrançois Tigeot if (IS_CHERRYVIEW(dev_priv)) 12588621f407SFrançois Tigeot return chv_init_workarounds(engine); 12591b13d190SFrançois Tigeot 12601487f786SFrançois Tigeot if (IS_SKYLAKE(dev_priv)) 12618621f407SFrançois Tigeot return skl_init_workarounds(engine); 126219c468b4SFrançois Tigeot 12631487f786SFrançois Tigeot if (IS_BROXTON(dev_priv)) 12648621f407SFrançois Tigeot return bxt_init_workarounds(engine); 12658621f407SFrançois Tigeot 12668621f407SFrançois Tigeot if (IS_KABYLAKE(dev_priv)) 12678621f407SFrançois Tigeot return kbl_init_workarounds(engine); 1268477eb7f9SFrançois Tigeot 12691b13d190SFrançois Tigeot return 0; 12701b13d190SFrançois Tigeot } 12711b13d190SFrançois Tigeot 12728621f407SFrançois Tigeot static int init_render_ring(struct intel_engine_cs *engine) 1273e3adcf8fSFrançois Tigeot { 12741487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 12758621f407SFrançois Tigeot int ret = init_ring_common(engine); 127624edb884SFrançois Tigeot if (ret) 127724edb884SFrançois Tigeot return ret; 1278e3adcf8fSFrançois Tigeot 1279ba55f2f5SFrançois Tigeot /* WaTimedSingleVertexDispatch:cl,bw,ctg,elk,ilk,snb */ 12801487f786SFrançois Tigeot if (IS_GEN(dev_priv, 4, 6)) 1281f4e1c372SFrançois Tigeot I915_WRITE(MI_MODE, _MASKED_BIT_ENABLE(VS_TIMER_DISPATCH)); 1282f4e1c372SFrançois Tigeot 1283f4e1c372SFrançois Tigeot /* We need to disable the AsyncFlip performance optimisations in order 1284f4e1c372SFrançois Tigeot * to use MI_WAIT_FOR_EVENT within the CS. It should already be 1285f4e1c372SFrançois Tigeot * programmed to '1' on all products. 12865d0b1887SFrançois Tigeot * 1287a05eeebfSFrançois Tigeot * WaDisableAsyncFlipPerfMode:snb,ivb,hsw,vlv 1288f4e1c372SFrançois Tigeot */ 12891487f786SFrançois Tigeot if (IS_GEN(dev_priv, 6, 7)) 1290f4e1c372SFrançois Tigeot I915_WRITE(MI_MODE, _MASKED_BIT_ENABLE(ASYNC_FLIP_PERF_DISABLE)); 1291f4e1c372SFrançois Tigeot 1292f4e1c372SFrançois Tigeot /* Required for the hardware to program scanline values for waiting */ 1293ba55f2f5SFrançois Tigeot /* WaEnableFlushTlbInvalidationMode:snb */ 12941487f786SFrançois Tigeot if (IS_GEN6(dev_priv)) 1295f4e1c372SFrançois Tigeot I915_WRITE(GFX_MODE, 1296ba55f2f5SFrançois Tigeot _MASKED_BIT_ENABLE(GFX_TLB_INVALIDATE_EXPLICIT)); 1297f4e1c372SFrançois Tigeot 1298ba55f2f5SFrançois Tigeot /* WaBCSVCSTlbInvalidationMode:ivb,vlv,hsw */ 12991487f786SFrançois Tigeot if (IS_GEN7(dev_priv)) 1300e3adcf8fSFrançois Tigeot I915_WRITE(GFX_MODE_GEN7, 1301ba55f2f5SFrançois Tigeot _MASKED_BIT_ENABLE(GFX_TLB_INVALIDATE_EXPLICIT) | 1302f4e1c372SFrançois Tigeot _MASKED_BIT_ENABLE(GFX_REPLAY_MODE)); 1303e3adcf8fSFrançois Tigeot 13041487f786SFrançois Tigeot if (IS_GEN6(dev_priv)) { 1305e3adcf8fSFrançois Tigeot /* From the Sandybridge PRM, volume 1 part 3, page 24: 1306e3adcf8fSFrançois Tigeot * "If this bit is set, STCunit will have LRA as replacement 1307e3adcf8fSFrançois Tigeot * policy. [...] This bit must be reset. LRA replacement 1308e3adcf8fSFrançois Tigeot * policy is not supported." 1309e3adcf8fSFrançois Tigeot */ 1310e3adcf8fSFrançois Tigeot I915_WRITE(CACHE_MODE_0, 1311f4e1c372SFrançois Tigeot _MASKED_BIT_DISABLE(CM0_STC_EVICT_DISABLE_LRA_SNB)); 1312e3adcf8fSFrançois Tigeot } 1313e3adcf8fSFrançois Tigeot 13141487f786SFrançois Tigeot if (IS_GEN(dev_priv, 6, 7)) 1315f4e1c372SFrançois Tigeot I915_WRITE(INSTPM, _MASKED_BIT_ENABLE(INSTPM_FORCE_ORDERING)); 1316f4e1c372SFrançois Tigeot 1317303bf270SFrançois Tigeot if (INTEL_INFO(dev_priv)->gen >= 6) 1318303bf270SFrançois Tigeot I915_WRITE_IMR(engine, ~engine->irq_keep_mask); 1319e3adcf8fSFrançois Tigeot 13208621f407SFrançois Tigeot return init_workarounds_ring(engine); 1321e3adcf8fSFrançois Tigeot } 1322e3adcf8fSFrançois Tigeot 13238621f407SFrançois Tigeot static void render_ring_cleanup(struct intel_engine_cs *engine) 1324e3adcf8fSFrançois Tigeot { 13251487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 132624edb884SFrançois Tigeot 132724edb884SFrançois Tigeot if (dev_priv->semaphore_obj) { 132824edb884SFrançois Tigeot i915_gem_object_ggtt_unpin(dev_priv->semaphore_obj); 1329*87df8fc6SFrançois Tigeot i915_gem_object_put(dev_priv->semaphore_obj); 133024edb884SFrançois Tigeot dev_priv->semaphore_obj = NULL; 133124edb884SFrançois Tigeot } 1332b5c29a34SFrançois Tigeot 13338621f407SFrançois Tigeot intel_fini_pipe_control(engine); 1334e3adcf8fSFrançois Tigeot } 1335e3adcf8fSFrançois Tigeot 1336a05eeebfSFrançois Tigeot static int gen8_rcs_signal(struct drm_i915_gem_request *signaller_req, 133724edb884SFrançois Tigeot unsigned int num_dwords) 133824edb884SFrançois Tigeot { 133924edb884SFrançois Tigeot #define MBOX_UPDATE_DWORDS 8 13408621f407SFrançois Tigeot struct intel_engine_cs *signaller = signaller_req->engine; 13411487f786SFrançois Tigeot struct drm_i915_private *dev_priv = signaller_req->i915; 134224edb884SFrançois Tigeot struct intel_engine_cs *waiter; 13438621f407SFrançois Tigeot enum intel_engine_id id; 13448621f407SFrançois Tigeot int ret, num_rings; 134524edb884SFrançois Tigeot 13461487f786SFrançois Tigeot num_rings = hweight32(INTEL_INFO(dev_priv)->ring_mask); 134724edb884SFrançois Tigeot num_dwords += (num_rings-1) * MBOX_UPDATE_DWORDS; 134824edb884SFrançois Tigeot #undef MBOX_UPDATE_DWORDS 134924edb884SFrançois Tigeot 1350a05eeebfSFrançois Tigeot ret = intel_ring_begin(signaller_req, num_dwords); 135124edb884SFrançois Tigeot if (ret) 135224edb884SFrançois Tigeot return ret; 135324edb884SFrançois Tigeot 13548621f407SFrançois Tigeot for_each_engine_id(waiter, dev_priv, id) { 13558621f407SFrançois Tigeot u64 gtt_offset = signaller->semaphore.signal_ggtt[id]; 135624edb884SFrançois Tigeot if (gtt_offset == MI_SEMAPHORE_SYNC_INVALID) 135724edb884SFrançois Tigeot continue; 135824edb884SFrançois Tigeot 135924edb884SFrançois Tigeot intel_ring_emit(signaller, GFX_OP_PIPE_CONTROL(6)); 136024edb884SFrançois Tigeot intel_ring_emit(signaller, PIPE_CONTROL_GLOBAL_GTT_IVB | 136124edb884SFrançois Tigeot PIPE_CONTROL_QW_WRITE | 13621487f786SFrançois Tigeot PIPE_CONTROL_CS_STALL); 136324edb884SFrançois Tigeot intel_ring_emit(signaller, lower_32_bits(gtt_offset)); 136424edb884SFrançois Tigeot intel_ring_emit(signaller, upper_32_bits(gtt_offset)); 1365*87df8fc6SFrançois Tigeot intel_ring_emit(signaller, signaller_req->fence.seqno); 136624edb884SFrançois Tigeot intel_ring_emit(signaller, 0); 136724edb884SFrançois Tigeot intel_ring_emit(signaller, MI_SEMAPHORE_SIGNAL | 13688621f407SFrançois Tigeot MI_SEMAPHORE_TARGET(waiter->hw_id)); 136924edb884SFrançois Tigeot intel_ring_emit(signaller, 0); 137024edb884SFrançois Tigeot } 137124edb884SFrançois Tigeot 137224edb884SFrançois Tigeot return 0; 137324edb884SFrançois Tigeot } 137424edb884SFrançois Tigeot 1375a05eeebfSFrançois Tigeot static int gen8_xcs_signal(struct drm_i915_gem_request *signaller_req, 137624edb884SFrançois Tigeot unsigned int num_dwords) 137724edb884SFrançois Tigeot { 137824edb884SFrançois Tigeot #define MBOX_UPDATE_DWORDS 6 13798621f407SFrançois Tigeot struct intel_engine_cs *signaller = signaller_req->engine; 13801487f786SFrançois Tigeot struct drm_i915_private *dev_priv = signaller_req->i915; 138124edb884SFrançois Tigeot struct intel_engine_cs *waiter; 13828621f407SFrançois Tigeot enum intel_engine_id id; 13838621f407SFrançois Tigeot int ret, num_rings; 138424edb884SFrançois Tigeot 13851487f786SFrançois Tigeot num_rings = hweight32(INTEL_INFO(dev_priv)->ring_mask); 138624edb884SFrançois Tigeot num_dwords += (num_rings-1) * MBOX_UPDATE_DWORDS; 138724edb884SFrançois Tigeot #undef MBOX_UPDATE_DWORDS 138824edb884SFrançois Tigeot 1389a05eeebfSFrançois Tigeot ret = intel_ring_begin(signaller_req, num_dwords); 139024edb884SFrançois Tigeot if (ret) 139124edb884SFrançois Tigeot return ret; 139224edb884SFrançois Tigeot 13938621f407SFrançois Tigeot for_each_engine_id(waiter, dev_priv, id) { 13948621f407SFrançois Tigeot u64 gtt_offset = signaller->semaphore.signal_ggtt[id]; 139524edb884SFrançois Tigeot if (gtt_offset == MI_SEMAPHORE_SYNC_INVALID) 139624edb884SFrançois Tigeot continue; 139724edb884SFrançois Tigeot 139824edb884SFrançois Tigeot intel_ring_emit(signaller, (MI_FLUSH_DW + 1) | 139924edb884SFrançois Tigeot MI_FLUSH_DW_OP_STOREDW); 140024edb884SFrançois Tigeot intel_ring_emit(signaller, lower_32_bits(gtt_offset) | 140124edb884SFrançois Tigeot MI_FLUSH_DW_USE_GTT); 140224edb884SFrançois Tigeot intel_ring_emit(signaller, upper_32_bits(gtt_offset)); 1403*87df8fc6SFrançois Tigeot intel_ring_emit(signaller, signaller_req->fence.seqno); 140424edb884SFrançois Tigeot intel_ring_emit(signaller, MI_SEMAPHORE_SIGNAL | 14058621f407SFrançois Tigeot MI_SEMAPHORE_TARGET(waiter->hw_id)); 140624edb884SFrançois Tigeot intel_ring_emit(signaller, 0); 140724edb884SFrançois Tigeot } 140824edb884SFrançois Tigeot 140924edb884SFrançois Tigeot return 0; 141024edb884SFrançois Tigeot } 141124edb884SFrançois Tigeot 1412a05eeebfSFrançois Tigeot static int gen6_signal(struct drm_i915_gem_request *signaller_req, 1413ba55f2f5SFrançois Tigeot unsigned int num_dwords) 1414e3adcf8fSFrançois Tigeot { 14158621f407SFrançois Tigeot struct intel_engine_cs *signaller = signaller_req->engine; 14161487f786SFrançois Tigeot struct drm_i915_private *dev_priv = signaller_req->i915; 1417ba55f2f5SFrançois Tigeot struct intel_engine_cs *useless; 14188621f407SFrançois Tigeot enum intel_engine_id id; 14198621f407SFrançois Tigeot int ret, num_rings; 1420ba55f2f5SFrançois Tigeot 142124edb884SFrançois Tigeot #define MBOX_UPDATE_DWORDS 3 14221487f786SFrançois Tigeot num_rings = hweight32(INTEL_INFO(dev_priv)->ring_mask); 142324edb884SFrançois Tigeot num_dwords += round_up((num_rings-1) * MBOX_UPDATE_DWORDS, 2); 142424edb884SFrançois Tigeot #undef MBOX_UPDATE_DWORDS 1425ba55f2f5SFrançois Tigeot 1426a05eeebfSFrançois Tigeot ret = intel_ring_begin(signaller_req, num_dwords); 1427ba55f2f5SFrançois Tigeot if (ret) 1428ba55f2f5SFrançois Tigeot return ret; 1429ba55f2f5SFrançois Tigeot 14308621f407SFrançois Tigeot for_each_engine_id(useless, dev_priv, id) { 14318621f407SFrançois Tigeot i915_reg_t mbox_reg = signaller->semaphore.mbox.signal[id]; 1432aee94f86SFrançois Tigeot 1433aee94f86SFrançois Tigeot if (i915_mmio_reg_valid(mbox_reg)) { 1434ba55f2f5SFrançois Tigeot intel_ring_emit(signaller, MI_LOAD_REGISTER_IMM(1)); 1435aee94f86SFrançois Tigeot intel_ring_emit_reg(signaller, mbox_reg); 1436*87df8fc6SFrançois Tigeot intel_ring_emit(signaller, signaller_req->fence.seqno); 1437ba55f2f5SFrançois Tigeot } 1438ba55f2f5SFrançois Tigeot } 1439ba55f2f5SFrançois Tigeot 144024edb884SFrançois Tigeot /* If num_dwords was rounded, make sure the tail pointer is correct */ 144124edb884SFrançois Tigeot if (num_rings % 2 == 0) 144224edb884SFrançois Tigeot intel_ring_emit(signaller, MI_NOOP); 144324edb884SFrançois Tigeot 1444ba55f2f5SFrançois Tigeot return 0; 1445e3adcf8fSFrançois Tigeot } 1446e3adcf8fSFrançois Tigeot 1447e3adcf8fSFrançois Tigeot /** 1448e3adcf8fSFrançois Tigeot * gen6_add_request - Update the semaphore mailbox registers 1449e3adcf8fSFrançois Tigeot * 1450a05eeebfSFrançois Tigeot * @request - request to write to the ring 1451e3adcf8fSFrançois Tigeot * 1452e3adcf8fSFrançois Tigeot * Update the mailbox registers in the *other* rings with the current seqno. 1453e3adcf8fSFrançois Tigeot * This acts like a signal in the canonical semaphore. 1454e3adcf8fSFrançois Tigeot */ 1455e3adcf8fSFrançois Tigeot static int 1456a05eeebfSFrançois Tigeot gen6_add_request(struct drm_i915_gem_request *req) 1457e3adcf8fSFrançois Tigeot { 14588621f407SFrançois Tigeot struct intel_engine_cs *engine = req->engine; 1459ba55f2f5SFrançois Tigeot int ret; 1460e3adcf8fSFrançois Tigeot 14618621f407SFrançois Tigeot if (engine->semaphore.signal) 14628621f407SFrançois Tigeot ret = engine->semaphore.signal(req, 4); 146324edb884SFrançois Tigeot else 1464a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 4); 146524edb884SFrançois Tigeot 14669edbd4a0SFrançois Tigeot if (ret) 14679edbd4a0SFrançois Tigeot return ret; 14689edbd4a0SFrançois Tigeot 14698621f407SFrançois Tigeot intel_ring_emit(engine, MI_STORE_DWORD_INDEX); 14708621f407SFrançois Tigeot intel_ring_emit(engine, 14718621f407SFrançois Tigeot I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT); 1472*87df8fc6SFrançois Tigeot intel_ring_emit(engine, req->fence.seqno); 14738621f407SFrançois Tigeot intel_ring_emit(engine, MI_USER_INTERRUPT); 14748621f407SFrançois Tigeot __intel_ring_advance(engine); 1475e3adcf8fSFrançois Tigeot 1476e3adcf8fSFrançois Tigeot return 0; 1477e3adcf8fSFrançois Tigeot } 1478e3adcf8fSFrançois Tigeot 14791487f786SFrançois Tigeot static int 14801487f786SFrançois Tigeot gen8_render_add_request(struct drm_i915_gem_request *req) 14811487f786SFrançois Tigeot { 14821487f786SFrançois Tigeot struct intel_engine_cs *engine = req->engine; 14831487f786SFrançois Tigeot int ret; 14841487f786SFrançois Tigeot 14851487f786SFrançois Tigeot if (engine->semaphore.signal) 14861487f786SFrançois Tigeot ret = engine->semaphore.signal(req, 8); 14871487f786SFrançois Tigeot else 14881487f786SFrançois Tigeot ret = intel_ring_begin(req, 8); 14891487f786SFrançois Tigeot if (ret) 14901487f786SFrançois Tigeot return ret; 14911487f786SFrançois Tigeot 14921487f786SFrançois Tigeot intel_ring_emit(engine, GFX_OP_PIPE_CONTROL(6)); 14931487f786SFrançois Tigeot intel_ring_emit(engine, (PIPE_CONTROL_GLOBAL_GTT_IVB | 14941487f786SFrançois Tigeot PIPE_CONTROL_CS_STALL | 14951487f786SFrançois Tigeot PIPE_CONTROL_QW_WRITE)); 14961487f786SFrançois Tigeot intel_ring_emit(engine, intel_hws_seqno_address(req->engine)); 14971487f786SFrançois Tigeot intel_ring_emit(engine, 0); 14981487f786SFrançois Tigeot intel_ring_emit(engine, i915_gem_request_get_seqno(req)); 14991487f786SFrançois Tigeot /* We're thrashing one dword of HWS. */ 15001487f786SFrançois Tigeot intel_ring_emit(engine, 0); 15011487f786SFrançois Tigeot intel_ring_emit(engine, MI_USER_INTERRUPT); 15021487f786SFrançois Tigeot intel_ring_emit(engine, MI_NOOP); 15031487f786SFrançois Tigeot __intel_ring_advance(engine); 15041487f786SFrançois Tigeot 15051487f786SFrançois Tigeot return 0; 15061487f786SFrançois Tigeot } 15071487f786SFrançois Tigeot 15081487f786SFrançois Tigeot static inline bool i915_gem_has_seqno_wrapped(struct drm_i915_private *dev_priv, 1509a2fdbec6SFrançois Tigeot u32 seqno) 1510a2fdbec6SFrançois Tigeot { 1511a2fdbec6SFrançois Tigeot return dev_priv->last_seqno < seqno; 1512a2fdbec6SFrançois Tigeot } 1513a2fdbec6SFrançois Tigeot 1514e3adcf8fSFrançois Tigeot /** 1515e3adcf8fSFrançois Tigeot * intel_ring_sync - sync the waiter to the signaller on seqno 1516e3adcf8fSFrançois Tigeot * 1517e3adcf8fSFrançois Tigeot * @waiter - ring that is waiting 1518e3adcf8fSFrançois Tigeot * @signaller - ring which has, or will signal 1519e3adcf8fSFrançois Tigeot * @seqno - seqno which the waiter will block on 1520e3adcf8fSFrançois Tigeot */ 152124edb884SFrançois Tigeot 152224edb884SFrançois Tigeot static int 1523a05eeebfSFrançois Tigeot gen8_ring_sync(struct drm_i915_gem_request *waiter_req, 152424edb884SFrançois Tigeot struct intel_engine_cs *signaller, 152524edb884SFrançois Tigeot u32 seqno) 152624edb884SFrançois Tigeot { 15278621f407SFrançois Tigeot struct intel_engine_cs *waiter = waiter_req->engine; 15281487f786SFrançois Tigeot struct drm_i915_private *dev_priv = waiter_req->i915; 15291487f786SFrançois Tigeot u64 offset = GEN8_WAIT_OFFSET(waiter, signaller->id); 15301487f786SFrançois Tigeot struct i915_hw_ppgtt *ppgtt; 153124edb884SFrançois Tigeot int ret; 153224edb884SFrançois Tigeot 1533a05eeebfSFrançois Tigeot ret = intel_ring_begin(waiter_req, 4); 153424edb884SFrançois Tigeot if (ret) 153524edb884SFrançois Tigeot return ret; 153624edb884SFrançois Tigeot 153724edb884SFrançois Tigeot intel_ring_emit(waiter, MI_SEMAPHORE_WAIT | 153824edb884SFrançois Tigeot MI_SEMAPHORE_GLOBAL_GTT | 153924edb884SFrançois Tigeot MI_SEMAPHORE_SAD_GTE_SDD); 154024edb884SFrançois Tigeot intel_ring_emit(waiter, seqno); 15411487f786SFrançois Tigeot intel_ring_emit(waiter, lower_32_bits(offset)); 15421487f786SFrançois Tigeot intel_ring_emit(waiter, upper_32_bits(offset)); 154324edb884SFrançois Tigeot intel_ring_advance(waiter); 15441487f786SFrançois Tigeot 15451487f786SFrançois Tigeot /* When the !RCS engines idle waiting upon a semaphore, they lose their 15461487f786SFrançois Tigeot * pagetables and we must reload them before executing the batch. 15471487f786SFrançois Tigeot * We do this on the i915_switch_context() following the wait and 15481487f786SFrançois Tigeot * before the dispatch. 15491487f786SFrançois Tigeot */ 15501487f786SFrançois Tigeot ppgtt = waiter_req->ctx->ppgtt; 15511487f786SFrançois Tigeot if (ppgtt && waiter_req->engine->id != RCS) 15521487f786SFrançois Tigeot ppgtt->pd_dirty_rings |= intel_engine_flag(waiter_req->engine); 155324edb884SFrançois Tigeot return 0; 155424edb884SFrançois Tigeot } 155524edb884SFrançois Tigeot 1556e3adcf8fSFrançois Tigeot static int 1557a05eeebfSFrançois Tigeot gen6_ring_sync(struct drm_i915_gem_request *waiter_req, 1558ba55f2f5SFrançois Tigeot struct intel_engine_cs *signaller, 1559e3adcf8fSFrançois Tigeot u32 seqno) 1560e3adcf8fSFrançois Tigeot { 15618621f407SFrançois Tigeot struct intel_engine_cs *waiter = waiter_req->engine; 1562e3adcf8fSFrançois Tigeot u32 dw1 = MI_SEMAPHORE_MBOX | 1563e3adcf8fSFrançois Tigeot MI_SEMAPHORE_COMPARE | 1564e3adcf8fSFrançois Tigeot MI_SEMAPHORE_REGISTER; 1565ba55f2f5SFrançois Tigeot u32 wait_mbox = signaller->semaphore.mbox.wait[waiter->id]; 1566ba55f2f5SFrançois Tigeot int ret; 1567e3adcf8fSFrançois Tigeot 1568686a02f1SFrançois Tigeot /* Throughout all of the GEM code, seqno passed implies our current 1569686a02f1SFrançois Tigeot * seqno is >= the last seqno executed. However for hardware the 1570686a02f1SFrançois Tigeot * comparison is strictly greater than. 1571686a02f1SFrançois Tigeot */ 1572686a02f1SFrançois Tigeot seqno -= 1; 1573686a02f1SFrançois Tigeot 1574ba55f2f5SFrançois Tigeot WARN_ON(wait_mbox == MI_SEMAPHORE_SYNC_INVALID); 1575686a02f1SFrançois Tigeot 1576a05eeebfSFrançois Tigeot ret = intel_ring_begin(waiter_req, 4); 1577e3adcf8fSFrançois Tigeot if (ret) 1578e3adcf8fSFrançois Tigeot return ret; 1579e3adcf8fSFrançois Tigeot 1580a2fdbec6SFrançois Tigeot /* If seqno wrap happened, omit the wait with no-ops */ 15811487f786SFrançois Tigeot if (likely(!i915_gem_has_seqno_wrapped(waiter_req->i915, seqno))) { 1582ba55f2f5SFrançois Tigeot intel_ring_emit(waiter, dw1 | wait_mbox); 1583e3adcf8fSFrançois Tigeot intel_ring_emit(waiter, seqno); 1584e3adcf8fSFrançois Tigeot intel_ring_emit(waiter, 0); 1585e3adcf8fSFrançois Tigeot intel_ring_emit(waiter, MI_NOOP); 1586a2fdbec6SFrançois Tigeot } else { 1587a2fdbec6SFrançois Tigeot intel_ring_emit(waiter, MI_NOOP); 1588a2fdbec6SFrançois Tigeot intel_ring_emit(waiter, MI_NOOP); 1589a2fdbec6SFrançois Tigeot intel_ring_emit(waiter, MI_NOOP); 1590a2fdbec6SFrançois Tigeot intel_ring_emit(waiter, MI_NOOP); 1591a2fdbec6SFrançois Tigeot } 1592e3adcf8fSFrançois Tigeot intel_ring_advance(waiter); 1593e3adcf8fSFrançois Tigeot 1594e3adcf8fSFrançois Tigeot return 0; 1595e3adcf8fSFrançois Tigeot } 1596e3adcf8fSFrançois Tigeot 1597303bf270SFrançois Tigeot static void 1598*87df8fc6SFrançois Tigeot gen5_seqno_barrier(struct intel_engine_cs *engine) 1599e3adcf8fSFrançois Tigeot { 1600303bf270SFrançois Tigeot /* MI_STORE are internally buffered by the GPU and not flushed 1601303bf270SFrançois Tigeot * either by MI_FLUSH or SyncFlush or any other combination of 1602303bf270SFrançois Tigeot * MI commands. 1603e3adcf8fSFrançois Tigeot * 1604303bf270SFrançois Tigeot * "Only the submission of the store operation is guaranteed. 1605303bf270SFrançois Tigeot * The write result will be complete (coherent) some time later 1606303bf270SFrançois Tigeot * (this is practically a finite period but there is no guaranteed 1607303bf270SFrançois Tigeot * latency)." 1608303bf270SFrançois Tigeot * 1609303bf270SFrançois Tigeot * Empirically, we observe that we need a delay of at least 75us to 1610303bf270SFrançois Tigeot * be sure that the seqno write is visible by the CPU. 1611e3adcf8fSFrançois Tigeot */ 1612303bf270SFrançois Tigeot usleep_range(125, 250); 1613e3adcf8fSFrançois Tigeot } 1614e3adcf8fSFrançois Tigeot 16158621f407SFrançois Tigeot static void 16168621f407SFrançois Tigeot gen6_seqno_barrier(struct intel_engine_cs *engine) 1617e3adcf8fSFrançois Tigeot { 16181487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 16198621f407SFrançois Tigeot 1620e3adcf8fSFrançois Tigeot /* Workaround to force correct ordering between irq and seqno writes on 1621e3adcf8fSFrançois Tigeot * ivb (and maybe also on snb) by reading from a CS register (like 16228621f407SFrançois Tigeot * ACTHD) before reading the status page. 16238621f407SFrançois Tigeot * 16248621f407SFrançois Tigeot * Note that this effectively stalls the read by the time it takes to 16258621f407SFrançois Tigeot * do a memory transaction, which more or less ensures that the write 16268621f407SFrançois Tigeot * from the GPU has sufficient time to invalidate the CPU cacheline. 16278621f407SFrançois Tigeot * Alternatively we could delay the interrupt from the CS ring to give 16288621f407SFrançois Tigeot * the write time to land, but that would incur a delay after every 16298621f407SFrançois Tigeot * batch i.e. much more frequent than a delay when waiting for the 16308621f407SFrançois Tigeot * interrupt (with the same net latency). 16318621f407SFrançois Tigeot * 16328621f407SFrançois Tigeot * Also note that to prevent whole machine hangs on gen7, we have to 16338621f407SFrançois Tigeot * take the spinlock to guard against concurrent cacheline access. 16348621f407SFrançois Tigeot */ 16358621f407SFrançois Tigeot spin_lock_irq(&dev_priv->uncore.lock); 16368621f407SFrançois Tigeot POSTING_READ_FW(RING_ACTHD(engine->mmio_base)); 16378621f407SFrançois Tigeot spin_unlock_irq(&dev_priv->uncore.lock); 1638e3adcf8fSFrançois Tigeot } 1639e3adcf8fSFrançois Tigeot 1640303bf270SFrançois Tigeot static void 1641303bf270SFrançois Tigeot gen5_irq_enable(struct intel_engine_cs *engine) 1642e3adcf8fSFrançois Tigeot { 1643303bf270SFrançois Tigeot gen5_enable_gt_irq(engine->i915, engine->irq_enable_mask); 1644e3adcf8fSFrançois Tigeot } 1645e3adcf8fSFrançois Tigeot 1646a2fdbec6SFrançois Tigeot static void 1647303bf270SFrançois Tigeot gen5_irq_disable(struct intel_engine_cs *engine) 1648a2fdbec6SFrançois Tigeot { 1649303bf270SFrançois Tigeot gen5_disable_gt_irq(engine->i915, engine->irq_enable_mask); 1650e3adcf8fSFrançois Tigeot } 1651e3adcf8fSFrançois Tigeot 1652a2fdbec6SFrançois Tigeot static void 1653303bf270SFrançois Tigeot i9xx_irq_enable(struct intel_engine_cs *engine) 1654e3adcf8fSFrançois Tigeot { 16551487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 1656e3adcf8fSFrançois Tigeot 16578621f407SFrançois Tigeot dev_priv->irq_mask &= ~engine->irq_enable_mask; 1658686a02f1SFrançois Tigeot I915_WRITE(IMR, dev_priv->irq_mask); 1659303bf270SFrançois Tigeot POSTING_READ_FW(RING_IMR(engine->mmio_base)); 1660686a02f1SFrançois Tigeot } 1661686a02f1SFrançois Tigeot 1662686a02f1SFrançois Tigeot static void 1663303bf270SFrançois Tigeot i9xx_irq_disable(struct intel_engine_cs *engine) 1664686a02f1SFrançois Tigeot { 16651487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 1666686a02f1SFrançois Tigeot 16678621f407SFrançois Tigeot dev_priv->irq_mask |= engine->irq_enable_mask; 1668686a02f1SFrançois Tigeot I915_WRITE(IMR, dev_priv->irq_mask); 1669686a02f1SFrançois Tigeot } 1670686a02f1SFrançois Tigeot 1671686a02f1SFrançois Tigeot static void 1672303bf270SFrançois Tigeot i8xx_irq_enable(struct intel_engine_cs *engine) 1673686a02f1SFrançois Tigeot { 16741487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 1675686a02f1SFrançois Tigeot 1676303bf270SFrançois Tigeot dev_priv->irq_mask &= ~engine->irq_enable_mask; 1677303bf270SFrançois Tigeot I915_WRITE16(IMR, dev_priv->irq_mask); 1678303bf270SFrançois Tigeot POSTING_READ16(RING_IMR(engine->mmio_base)); 1679303bf270SFrançois Tigeot } 1680303bf270SFrançois Tigeot 1681303bf270SFrançois Tigeot static void 1682303bf270SFrançois Tigeot i8xx_irq_disable(struct intel_engine_cs *engine) 1683303bf270SFrançois Tigeot { 1684303bf270SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 1685303bf270SFrançois Tigeot 16868621f407SFrançois Tigeot dev_priv->irq_mask |= engine->irq_enable_mask; 1687686a02f1SFrançois Tigeot I915_WRITE16(IMR, dev_priv->irq_mask); 1688e3adcf8fSFrançois Tigeot } 1689e3adcf8fSFrançois Tigeot 1690e3adcf8fSFrançois Tigeot static int 1691a05eeebfSFrançois Tigeot bsd_ring_flush(struct drm_i915_gem_request *req, 1692b5c29a34SFrançois Tigeot u32 invalidate_domains, 1693b5c29a34SFrançois Tigeot u32 flush_domains) 1694e3adcf8fSFrançois Tigeot { 16958621f407SFrançois Tigeot struct intel_engine_cs *engine = req->engine; 1696e3adcf8fSFrançois Tigeot int ret; 1697e3adcf8fSFrançois Tigeot 1698a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 2); 1699e3adcf8fSFrançois Tigeot if (ret) 1700e3adcf8fSFrançois Tigeot return ret; 1701e3adcf8fSFrançois Tigeot 17028621f407SFrançois Tigeot intel_ring_emit(engine, MI_FLUSH); 17038621f407SFrançois Tigeot intel_ring_emit(engine, MI_NOOP); 17048621f407SFrançois Tigeot intel_ring_advance(engine); 1705e3adcf8fSFrançois Tigeot return 0; 1706e3adcf8fSFrançois Tigeot } 1707e3adcf8fSFrançois Tigeot 1708e3adcf8fSFrançois Tigeot static int 1709a05eeebfSFrançois Tigeot i9xx_add_request(struct drm_i915_gem_request *req) 1710e3adcf8fSFrançois Tigeot { 17118621f407SFrançois Tigeot struct intel_engine_cs *engine = req->engine; 1712e3adcf8fSFrançois Tigeot int ret; 1713e3adcf8fSFrançois Tigeot 1714a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 4); 1715e3adcf8fSFrançois Tigeot if (ret) 1716e3adcf8fSFrançois Tigeot return ret; 1717e3adcf8fSFrançois Tigeot 17188621f407SFrançois Tigeot intel_ring_emit(engine, MI_STORE_DWORD_INDEX); 17198621f407SFrançois Tigeot intel_ring_emit(engine, 17208621f407SFrançois Tigeot I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT); 1721*87df8fc6SFrançois Tigeot intel_ring_emit(engine, req->fence.seqno); 17228621f407SFrançois Tigeot intel_ring_emit(engine, MI_USER_INTERRUPT); 17238621f407SFrançois Tigeot __intel_ring_advance(engine); 1724e3adcf8fSFrançois Tigeot 1725e3adcf8fSFrançois Tigeot return 0; 1726e3adcf8fSFrançois Tigeot } 1727e3adcf8fSFrançois Tigeot 1728303bf270SFrançois Tigeot static void 1729303bf270SFrançois Tigeot gen6_irq_enable(struct intel_engine_cs *engine) 1730e3adcf8fSFrançois Tigeot { 17311487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 1732e3adcf8fSFrançois Tigeot 17338621f407SFrançois Tigeot I915_WRITE_IMR(engine, 17348621f407SFrançois Tigeot ~(engine->irq_enable_mask | 1735303bf270SFrançois Tigeot engine->irq_keep_mask)); 17368621f407SFrançois Tigeot gen5_enable_gt_irq(dev_priv, engine->irq_enable_mask); 1737e3adcf8fSFrançois Tigeot } 1738e3adcf8fSFrançois Tigeot 1739e3adcf8fSFrançois Tigeot static void 1740303bf270SFrançois Tigeot gen6_irq_disable(struct intel_engine_cs *engine) 1741e3adcf8fSFrançois Tigeot { 17421487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 1743e3adcf8fSFrançois Tigeot 1744303bf270SFrançois Tigeot I915_WRITE_IMR(engine, ~engine->irq_keep_mask); 17458621f407SFrançois Tigeot gen5_disable_gt_irq(dev_priv, engine->irq_enable_mask); 1746e3adcf8fSFrançois Tigeot } 1747e3adcf8fSFrançois Tigeot 1748303bf270SFrançois Tigeot static void 1749303bf270SFrançois Tigeot hsw_vebox_irq_enable(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, ~engine->irq_enable_mask); 17548621f407SFrançois Tigeot gen6_enable_pm_irq(dev_priv, engine->irq_enable_mask); 17555d0b1887SFrançois Tigeot } 17565d0b1887SFrançois Tigeot 17575d0b1887SFrançois Tigeot static void 1758303bf270SFrançois Tigeot hsw_vebox_irq_disable(struct intel_engine_cs *engine) 17595d0b1887SFrançois Tigeot { 17601487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 17615d0b1887SFrançois Tigeot 17628621f407SFrançois Tigeot I915_WRITE_IMR(engine, ~0); 17638621f407SFrançois Tigeot gen6_disable_pm_irq(dev_priv, engine->irq_enable_mask); 17645d0b1887SFrançois Tigeot } 17659edbd4a0SFrançois Tigeot 1766303bf270SFrançois Tigeot static void 1767303bf270SFrançois Tigeot gen8_irq_enable(struct intel_engine_cs *engine) 17689edbd4a0SFrançois Tigeot { 17691487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 17709edbd4a0SFrançois Tigeot 17718621f407SFrançois Tigeot I915_WRITE_IMR(engine, 17728621f407SFrançois Tigeot ~(engine->irq_enable_mask | 1773303bf270SFrançois Tigeot engine->irq_keep_mask)); 1774303bf270SFrançois Tigeot POSTING_READ_FW(RING_IMR(engine->mmio_base)); 17759edbd4a0SFrançois Tigeot } 17769edbd4a0SFrançois Tigeot 17779edbd4a0SFrançois Tigeot static void 1778303bf270SFrançois Tigeot gen8_irq_disable(struct intel_engine_cs *engine) 17799edbd4a0SFrançois Tigeot { 17801487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 17819edbd4a0SFrançois Tigeot 1782303bf270SFrançois Tigeot I915_WRITE_IMR(engine, ~engine->irq_keep_mask); 17835d0b1887SFrançois Tigeot } 17845d0b1887SFrançois Tigeot 1785e3adcf8fSFrançois Tigeot static int 1786a05eeebfSFrançois Tigeot i965_dispatch_execbuffer(struct drm_i915_gem_request *req, 1787ba55f2f5SFrançois Tigeot u64 offset, u32 length, 1788477eb7f9SFrançois Tigeot unsigned dispatch_flags) 1789e3adcf8fSFrançois Tigeot { 17908621f407SFrançois Tigeot struct intel_engine_cs *engine = req->engine; 1791e3adcf8fSFrançois Tigeot int ret; 1792e3adcf8fSFrançois Tigeot 1793a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 2); 1794e3adcf8fSFrançois Tigeot if (ret) 1795e3adcf8fSFrançois Tigeot return ret; 1796e3adcf8fSFrançois Tigeot 17978621f407SFrançois Tigeot intel_ring_emit(engine, 1798686a02f1SFrançois Tigeot MI_BATCH_BUFFER_START | 1799b5c29a34SFrançois Tigeot MI_BATCH_GTT | 1800477eb7f9SFrançois Tigeot (dispatch_flags & I915_DISPATCH_SECURE ? 1801477eb7f9SFrançois Tigeot 0 : MI_BATCH_NON_SECURE_I965)); 18028621f407SFrançois Tigeot intel_ring_emit(engine, offset); 18038621f407SFrançois Tigeot intel_ring_advance(engine); 1804e3adcf8fSFrançois Tigeot 1805e3adcf8fSFrançois Tigeot return 0; 1806e3adcf8fSFrançois Tigeot } 1807e3adcf8fSFrançois Tigeot 1808b5c29a34SFrançois Tigeot /* Just userspace ABI convention to limit the wa batch bo to a resonable size */ 1809b5c29a34SFrançois Tigeot #define I830_BATCH_LIMIT (256*1024) 181024edb884SFrançois Tigeot #define I830_TLB_ENTRIES (2) 181124edb884SFrançois Tigeot #define I830_WA_SIZE max(I830_TLB_ENTRIES*4096, I830_BATCH_LIMIT) 1812e3adcf8fSFrançois Tigeot static int 1813a05eeebfSFrançois Tigeot i830_dispatch_execbuffer(struct drm_i915_gem_request *req, 1814ba55f2f5SFrançois Tigeot u64 offset, u32 len, 1815477eb7f9SFrançois Tigeot unsigned dispatch_flags) 1816e3adcf8fSFrançois Tigeot { 18178621f407SFrançois Tigeot struct intel_engine_cs *engine = req->engine; 18188621f407SFrançois Tigeot u32 cs_offset = engine->scratch.gtt_offset; 1819e3adcf8fSFrançois Tigeot int ret; 1820e3adcf8fSFrançois Tigeot 1821a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 6); 182224edb884SFrançois Tigeot if (ret) 182324edb884SFrançois Tigeot return ret; 182424edb884SFrançois Tigeot 182524edb884SFrançois Tigeot /* Evict the invalid PTE TLBs */ 18268621f407SFrançois Tigeot intel_ring_emit(engine, COLOR_BLT_CMD | BLT_WRITE_RGBA); 18278621f407SFrançois Tigeot intel_ring_emit(engine, BLT_DEPTH_32 | BLT_ROP_COLOR_COPY | 4096); 18288621f407SFrançois Tigeot intel_ring_emit(engine, I830_TLB_ENTRIES << 16 | 4); /* load each page */ 18298621f407SFrançois Tigeot intel_ring_emit(engine, cs_offset); 18308621f407SFrançois Tigeot intel_ring_emit(engine, 0xdeadbeef); 18318621f407SFrançois Tigeot intel_ring_emit(engine, MI_NOOP); 18328621f407SFrançois Tigeot intel_ring_advance(engine); 183324edb884SFrançois Tigeot 1834477eb7f9SFrançois Tigeot if ((dispatch_flags & I915_DISPATCH_PINNED) == 0) { 183524edb884SFrançois Tigeot if (len > I830_BATCH_LIMIT) 183624edb884SFrançois Tigeot return -ENOSPC; 183724edb884SFrançois Tigeot 1838a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 6 + 2); 183924edb884SFrançois Tigeot if (ret) 184024edb884SFrançois Tigeot return ret; 184124edb884SFrançois Tigeot 184224edb884SFrançois Tigeot /* Blit the batch (which has now all relocs applied) to the 184324edb884SFrançois Tigeot * stable batch scratch bo area (so that the CS never 184424edb884SFrançois Tigeot * stumbles over its tlb invalidation bug) ... 184524edb884SFrançois Tigeot */ 18468621f407SFrançois Tigeot intel_ring_emit(engine, SRC_COPY_BLT_CMD | BLT_WRITE_RGBA); 18478621f407SFrançois Tigeot intel_ring_emit(engine, 18488621f407SFrançois Tigeot BLT_DEPTH_32 | BLT_ROP_SRC_COPY | 4096); 18498621f407SFrançois Tigeot intel_ring_emit(engine, DIV_ROUND_UP(len, 4096) << 16 | 4096); 18508621f407SFrançois Tigeot intel_ring_emit(engine, cs_offset); 18518621f407SFrançois Tigeot intel_ring_emit(engine, 4096); 18528621f407SFrançois Tigeot intel_ring_emit(engine, offset); 185324edb884SFrançois Tigeot 18548621f407SFrançois Tigeot intel_ring_emit(engine, MI_FLUSH); 18558621f407SFrançois Tigeot intel_ring_emit(engine, MI_NOOP); 18568621f407SFrançois Tigeot intel_ring_advance(engine); 185724edb884SFrançois Tigeot 185824edb884SFrançois Tigeot /* ... and execute it. */ 185924edb884SFrançois Tigeot offset = cs_offset; 186024edb884SFrançois Tigeot } 186124edb884SFrançois Tigeot 1862c0e85e96SFrançois Tigeot ret = intel_ring_begin(req, 2); 1863e3adcf8fSFrançois Tigeot if (ret) 1864e3adcf8fSFrançois Tigeot return ret; 1865e3adcf8fSFrançois Tigeot 18668621f407SFrançois Tigeot intel_ring_emit(engine, MI_BATCH_BUFFER_START | MI_BATCH_GTT); 18678621f407SFrançois Tigeot intel_ring_emit(engine, offset | (dispatch_flags & I915_DISPATCH_SECURE ? 1868477eb7f9SFrançois Tigeot 0 : MI_BATCH_NON_SECURE)); 18698621f407SFrançois Tigeot intel_ring_advance(engine); 1870686a02f1SFrançois Tigeot 1871686a02f1SFrançois Tigeot return 0; 1872686a02f1SFrançois Tigeot } 1873686a02f1SFrançois Tigeot 1874686a02f1SFrançois Tigeot static int 1875a05eeebfSFrançois Tigeot i915_dispatch_execbuffer(struct drm_i915_gem_request *req, 1876ba55f2f5SFrançois Tigeot u64 offset, u32 len, 1877477eb7f9SFrançois Tigeot unsigned dispatch_flags) 1878686a02f1SFrançois Tigeot { 18798621f407SFrançois Tigeot struct intel_engine_cs *engine = req->engine; 1880686a02f1SFrançois Tigeot int ret; 1881686a02f1SFrançois Tigeot 1882a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 2); 1883e3adcf8fSFrançois Tigeot if (ret) 1884e3adcf8fSFrançois Tigeot return ret; 1885e3adcf8fSFrançois Tigeot 18868621f407SFrançois Tigeot intel_ring_emit(engine, MI_BATCH_BUFFER_START | MI_BATCH_GTT); 18878621f407SFrançois Tigeot intel_ring_emit(engine, offset | (dispatch_flags & I915_DISPATCH_SECURE ? 1888477eb7f9SFrançois Tigeot 0 : MI_BATCH_NON_SECURE)); 18898621f407SFrançois Tigeot intel_ring_advance(engine); 1890e3adcf8fSFrançois Tigeot 1891e3adcf8fSFrançois Tigeot return 0; 1892e3adcf8fSFrançois Tigeot } 1893e3adcf8fSFrançois Tigeot 18948621f407SFrançois Tigeot static void cleanup_phys_status_page(struct intel_engine_cs *engine) 1895c0e85e96SFrançois Tigeot { 18961487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 1897c0e85e96SFrançois Tigeot 1898c0e85e96SFrançois Tigeot if (!dev_priv->status_page_dmah) 1899c0e85e96SFrançois Tigeot return; 1900c0e85e96SFrançois Tigeot 1901303bf270SFrançois Tigeot drm_pci_free(&dev_priv->drm, dev_priv->status_page_dmah); 19028621f407SFrançois Tigeot engine->status_page.page_addr = NULL; 1903c0e85e96SFrançois Tigeot } 1904c0e85e96SFrançois Tigeot 19058621f407SFrançois Tigeot static void cleanup_status_page(struct intel_engine_cs *engine) 1906e3adcf8fSFrançois Tigeot { 1907e3adcf8fSFrançois Tigeot struct drm_i915_gem_object *obj; 1908e3adcf8fSFrançois Tigeot 19098621f407SFrançois Tigeot obj = engine->status_page.obj; 1910e3adcf8fSFrançois Tigeot if (obj == NULL) 1911e3adcf8fSFrançois Tigeot return; 1912e3adcf8fSFrançois Tigeot 19137ec9f8e5SFrançois Tigeot kunmap(sg_page(obj->pages->sgl)); 1914ba55f2f5SFrançois Tigeot i915_gem_object_ggtt_unpin(obj); 1915*87df8fc6SFrançois Tigeot i915_gem_object_put(obj); 19168621f407SFrançois Tigeot engine->status_page.obj = NULL; 1917e3adcf8fSFrançois Tigeot } 1918e3adcf8fSFrançois Tigeot 19198621f407SFrançois Tigeot static int init_status_page(struct intel_engine_cs *engine) 1920e3adcf8fSFrançois Tigeot { 19218621f407SFrançois Tigeot struct drm_i915_gem_object *obj = engine->status_page.obj; 1922ba55f2f5SFrançois Tigeot 1923c0e85e96SFrançois Tigeot if (obj == NULL) { 192424edb884SFrançois Tigeot unsigned flags; 1925e3adcf8fSFrançois Tigeot int ret; 1926e3adcf8fSFrançois Tigeot 1927303bf270SFrançois Tigeot obj = i915_gem_object_create(&engine->i915->drm, 4096); 19281487f786SFrançois Tigeot if (IS_ERR(obj)) { 1929e3adcf8fSFrançois Tigeot DRM_ERROR("Failed to allocate status page\n"); 19301487f786SFrançois Tigeot return PTR_ERR(obj); 1931e3adcf8fSFrançois Tigeot } 1932e3adcf8fSFrançois Tigeot 1933ba55f2f5SFrançois Tigeot ret = i915_gem_object_set_cache_level(obj, I915_CACHE_LLC); 1934ba55f2f5SFrançois Tigeot if (ret) 1935e3adcf8fSFrançois Tigeot goto err_unref; 1936ba55f2f5SFrançois Tigeot 193724edb884SFrançois Tigeot flags = 0; 19381487f786SFrançois Tigeot if (!HAS_LLC(engine->i915)) 193924edb884SFrançois Tigeot /* On g33, we cannot place HWS above 256MiB, so 194024edb884SFrançois Tigeot * restrict its pinning to the low mappable arena. 194124edb884SFrançois Tigeot * Though this restriction is not documented for 194224edb884SFrançois Tigeot * gen4, gen5, or byt, they also behave similarly 194324edb884SFrançois Tigeot * and hang if the HWS is placed at the top of the 194424edb884SFrançois Tigeot * GTT. To generalise, it appears that all !llc 194524edb884SFrançois Tigeot * platforms have issues with us placing the HWS 194624edb884SFrançois Tigeot * above the mappable region (even though we never 194724edb884SFrançois Tigeot * actualy map it). 194824edb884SFrançois Tigeot */ 194924edb884SFrançois Tigeot flags |= PIN_MAPPABLE; 195024edb884SFrançois Tigeot ret = i915_gem_obj_ggtt_pin(obj, 4096, flags); 1951ba55f2f5SFrançois Tigeot if (ret) { 1952ba55f2f5SFrançois Tigeot err_unref: 1953*87df8fc6SFrançois Tigeot i915_gem_object_put(obj); 1954ba55f2f5SFrançois Tigeot return ret; 1955ba55f2f5SFrançois Tigeot } 1956ba55f2f5SFrançois Tigeot 19578621f407SFrançois Tigeot engine->status_page.obj = obj; 1958e3adcf8fSFrançois Tigeot } 1959e3adcf8fSFrançois Tigeot 19608621f407SFrançois Tigeot engine->status_page.gfx_addr = i915_gem_obj_ggtt_offset(obj); 19618621f407SFrançois Tigeot engine->status_page.page_addr = kmap(sg_page(obj->pages->sgl)); 19628621f407SFrançois Tigeot memset(engine->status_page.page_addr, 0, PAGE_SIZE); 1963e3adcf8fSFrançois Tigeot 1964b5c29a34SFrançois Tigeot DRM_DEBUG_DRIVER("%s hws offset: 0x%08x\n", 19658621f407SFrançois Tigeot engine->name, engine->status_page.gfx_addr); 1966e3adcf8fSFrançois Tigeot 1967e3adcf8fSFrançois Tigeot return 0; 1968e3adcf8fSFrançois Tigeot } 1969e3adcf8fSFrançois Tigeot 19708621f407SFrançois Tigeot static int init_phys_status_page(struct intel_engine_cs *engine) 1971686a02f1SFrançois Tigeot { 19721487f786SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 1973686a02f1SFrançois Tigeot 1974686a02f1SFrançois Tigeot if (!dev_priv->status_page_dmah) { 1975686a02f1SFrançois Tigeot dev_priv->status_page_dmah = 1976303bf270SFrançois Tigeot drm_pci_alloc(&dev_priv->drm, PAGE_SIZE, PAGE_SIZE); 1977686a02f1SFrançois Tigeot if (!dev_priv->status_page_dmah) 1978686a02f1SFrançois Tigeot return -ENOMEM; 1979686a02f1SFrançois Tigeot } 1980686a02f1SFrançois Tigeot 19818621f407SFrançois Tigeot engine->status_page.page_addr = dev_priv->status_page_dmah->vaddr; 19828621f407SFrançois Tigeot memset(engine->status_page.page_addr, 0, PAGE_SIZE); 1983686a02f1SFrançois Tigeot 1984686a02f1SFrançois Tigeot return 0; 1985686a02f1SFrançois Tigeot } 1986686a02f1SFrançois Tigeot 19872c9916cdSFrançois Tigeot void intel_unpin_ringbuffer_obj(struct intel_ringbuffer *ringbuf) 19882c9916cdSFrançois Tigeot { 1989*87df8fc6SFrançois Tigeot GEM_BUG_ON(!ringbuf->vma); 1990*87df8fc6SFrançois Tigeot GEM_BUG_ON(!ringbuf->vaddr); 19911487f786SFrançois Tigeot 1992aee94f86SFrançois Tigeot if (HAS_LLC(ringbuf->obj->base.dev) && !ringbuf->obj->stolen) 19938621f407SFrançois Tigeot i915_gem_object_unpin_map(ringbuf->obj); 1994aee94f86SFrançois Tigeot else 19951487f786SFrançois Tigeot i915_vma_unpin_iomap(ringbuf->vma); 1996*87df8fc6SFrançois Tigeot ringbuf->vaddr = NULL; 19971487f786SFrançois Tigeot 19982c9916cdSFrançois Tigeot i915_gem_object_ggtt_unpin(ringbuf->obj); 19991487f786SFrançois Tigeot ringbuf->vma = NULL; 20002c9916cdSFrançois Tigeot } 20012c9916cdSFrançois Tigeot 20021487f786SFrançois Tigeot int intel_pin_and_map_ringbuffer_obj(struct drm_i915_private *dev_priv, 20032c9916cdSFrançois Tigeot struct intel_ringbuffer *ringbuf) 20042c9916cdSFrançois Tigeot { 20052c9916cdSFrançois Tigeot struct drm_i915_gem_object *obj = ringbuf->obj; 2006c0e85e96SFrançois Tigeot /* Ring wraparound at offset 0 sometimes hangs. No idea why. */ 2007c0e85e96SFrançois Tigeot unsigned flags = PIN_OFFSET_BIAS | 4096; 20088621f407SFrançois Tigeot void *addr; 20092c9916cdSFrançois Tigeot int ret; 20102c9916cdSFrançois Tigeot 2011aee94f86SFrançois Tigeot if (HAS_LLC(dev_priv) && !obj->stolen) { 2012c0e85e96SFrançois Tigeot ret = i915_gem_obj_ggtt_pin(obj, PAGE_SIZE, flags); 2013aee94f86SFrançois Tigeot if (ret) 2014aee94f86SFrançois Tigeot return ret; 2015aee94f86SFrançois Tigeot 2016aee94f86SFrançois Tigeot ret = i915_gem_object_set_to_cpu_domain(obj, true); 20178621f407SFrançois Tigeot if (ret) 20188621f407SFrançois Tigeot goto err_unpin; 2019aee94f86SFrançois Tigeot 20208621f407SFrançois Tigeot addr = i915_gem_object_pin_map(obj); 20218621f407SFrançois Tigeot if (IS_ERR(addr)) { 20228621f407SFrançois Tigeot ret = PTR_ERR(addr); 20238621f407SFrançois Tigeot goto err_unpin; 2024aee94f86SFrançois Tigeot } 2025aee94f86SFrançois Tigeot } else { 2026c0e85e96SFrançois Tigeot ret = i915_gem_obj_ggtt_pin(obj, PAGE_SIZE, 2027c0e85e96SFrançois Tigeot flags | PIN_MAPPABLE); 20282c9916cdSFrançois Tigeot if (ret) 20292c9916cdSFrançois Tigeot return ret; 20302c9916cdSFrançois Tigeot 20312c9916cdSFrançois Tigeot ret = i915_gem_object_set_to_gtt_domain(obj, true); 20328621f407SFrançois Tigeot if (ret) 20338621f407SFrançois Tigeot goto err_unpin; 20342c9916cdSFrançois Tigeot 2035c0e85e96SFrançois Tigeot /* Access through the GTT requires the device to be awake. */ 2036c0e85e96SFrançois Tigeot assert_rpm_wakelock_held(dev_priv); 2037c0e85e96SFrançois Tigeot 2038*87df8fc6SFrançois Tigeot addr = (void __force *) 2039*87df8fc6SFrançois Tigeot i915_vma_pin_iomap(i915_gem_obj_to_ggtt(obj)); 20401487f786SFrançois Tigeot if (IS_ERR(addr)) { 20411487f786SFrançois Tigeot ret = PTR_ERR(addr); 20428621f407SFrançois Tigeot goto err_unpin; 20432c9916cdSFrançois Tigeot } 2044aee94f86SFrançois Tigeot } 20452c9916cdSFrançois Tigeot 2046*87df8fc6SFrançois Tigeot ringbuf->vaddr = addr; 2047c0e85e96SFrançois Tigeot ringbuf->vma = i915_gem_obj_to_ggtt(obj); 20482c9916cdSFrançois Tigeot return 0; 20498621f407SFrançois Tigeot 20508621f407SFrançois Tigeot err_unpin: 20518621f407SFrançois Tigeot i915_gem_object_ggtt_unpin(obj); 20528621f407SFrançois Tigeot return ret; 20532c9916cdSFrançois Tigeot } 20542c9916cdSFrançois Tigeot 2055352ff8bdSFrançois Tigeot static void intel_destroy_ringbuffer_obj(struct intel_ringbuffer *ringbuf) 2056e3adcf8fSFrançois Tigeot { 2057*87df8fc6SFrançois Tigeot i915_gem_object_put(ringbuf->obj); 205824edb884SFrançois Tigeot ringbuf->obj = NULL; 205924edb884SFrançois Tigeot } 206024edb884SFrançois Tigeot 2061352ff8bdSFrançois Tigeot static int intel_alloc_ringbuffer_obj(struct drm_device *dev, 206224edb884SFrançois Tigeot struct intel_ringbuffer *ringbuf) 206324edb884SFrançois Tigeot { 2064e3adcf8fSFrançois Tigeot struct drm_i915_gem_object *obj; 2065e3adcf8fSFrançois Tigeot 2066a2fdbec6SFrançois Tigeot obj = NULL; 2067a2fdbec6SFrançois Tigeot if (!HAS_LLC(dev)) 2068ba55f2f5SFrançois Tigeot obj = i915_gem_object_create_stolen(dev, ringbuf->size); 2069a2fdbec6SFrançois Tigeot if (obj == NULL) 20701487f786SFrançois Tigeot obj = i915_gem_object_create(dev, ringbuf->size); 20711487f786SFrançois Tigeot if (IS_ERR(obj)) 20721487f786SFrançois Tigeot return PTR_ERR(obj); 2073e3adcf8fSFrançois Tigeot 207424edb884SFrançois Tigeot /* mark ring buffers as read-only from GPU side by default */ 207524edb884SFrançois Tigeot obj->gt_ro = 1; 207624edb884SFrançois Tigeot 2077ba55f2f5SFrançois Tigeot ringbuf->obj = obj; 2078ba55f2f5SFrançois Tigeot 20792c9916cdSFrançois Tigeot return 0; 2080ba55f2f5SFrançois Tigeot } 2081ba55f2f5SFrançois Tigeot 2082352ff8bdSFrançois Tigeot struct intel_ringbuffer * 2083352ff8bdSFrançois Tigeot intel_engine_create_ringbuffer(struct intel_engine_cs *engine, int size) 2084352ff8bdSFrançois Tigeot { 2085352ff8bdSFrançois Tigeot struct intel_ringbuffer *ring; 2086352ff8bdSFrançois Tigeot int ret; 2087352ff8bdSFrançois Tigeot 2088352ff8bdSFrançois Tigeot ring = kzalloc(sizeof(*ring), GFP_KERNEL); 2089aee94f86SFrançois Tigeot if (ring == NULL) { 2090aee94f86SFrançois Tigeot DRM_DEBUG_DRIVER("Failed to allocate ringbuffer %s\n", 2091aee94f86SFrançois Tigeot engine->name); 2092352ff8bdSFrançois Tigeot return ERR_PTR(-ENOMEM); 2093aee94f86SFrançois Tigeot } 2094352ff8bdSFrançois Tigeot 20958621f407SFrançois Tigeot ring->engine = engine; 2096aee94f86SFrançois Tigeot list_add(&ring->link, &engine->buffers); 2097352ff8bdSFrançois Tigeot 2098352ff8bdSFrançois Tigeot ring->size = size; 2099352ff8bdSFrançois Tigeot /* Workaround an erratum on the i830 which causes a hang if 2100352ff8bdSFrançois Tigeot * the TAIL pointer points to within the last 2 cachelines 2101352ff8bdSFrançois Tigeot * of the buffer. 2102352ff8bdSFrançois Tigeot */ 2103352ff8bdSFrançois Tigeot ring->effective_size = size; 21041487f786SFrançois Tigeot if (IS_I830(engine->i915) || IS_845G(engine->i915)) 2105352ff8bdSFrançois Tigeot ring->effective_size -= 2 * CACHELINE_BYTES; 2106352ff8bdSFrançois Tigeot 2107352ff8bdSFrançois Tigeot ring->last_retired_head = -1; 2108352ff8bdSFrançois Tigeot intel_ring_update_space(ring); 2109352ff8bdSFrançois Tigeot 2110303bf270SFrançois Tigeot ret = intel_alloc_ringbuffer_obj(&engine->i915->drm, ring); 2111352ff8bdSFrançois Tigeot if (ret) { 2112aee94f86SFrançois Tigeot DRM_DEBUG_DRIVER("Failed to allocate ringbuffer %s: %d\n", 2113352ff8bdSFrançois Tigeot engine->name, ret); 2114aee94f86SFrançois Tigeot list_del(&ring->link); 2115352ff8bdSFrançois Tigeot kfree(ring); 2116352ff8bdSFrançois Tigeot return ERR_PTR(ret); 2117352ff8bdSFrançois Tigeot } 2118352ff8bdSFrançois Tigeot 2119352ff8bdSFrançois Tigeot return ring; 2120352ff8bdSFrançois Tigeot } 2121352ff8bdSFrançois Tigeot 2122352ff8bdSFrançois Tigeot void 2123352ff8bdSFrançois Tigeot intel_ringbuffer_free(struct intel_ringbuffer *ring) 2124352ff8bdSFrançois Tigeot { 2125352ff8bdSFrançois Tigeot intel_destroy_ringbuffer_obj(ring); 2126aee94f86SFrançois Tigeot list_del(&ring->link); 2127352ff8bdSFrançois Tigeot kfree(ring); 2128352ff8bdSFrançois Tigeot } 2129352ff8bdSFrançois Tigeot 21301487f786SFrançois Tigeot static int intel_ring_context_pin(struct i915_gem_context *ctx, 21311487f786SFrançois Tigeot struct intel_engine_cs *engine) 21321487f786SFrançois Tigeot { 21331487f786SFrançois Tigeot struct intel_context *ce = &ctx->engine[engine->id]; 21341487f786SFrançois Tigeot int ret; 21351487f786SFrançois Tigeot 2136303bf270SFrançois Tigeot lockdep_assert_held(&ctx->i915->drm.struct_mutex); 21371487f786SFrançois Tigeot 21381487f786SFrançois Tigeot if (ce->pin_count++) 21391487f786SFrançois Tigeot return 0; 21401487f786SFrançois Tigeot 21411487f786SFrançois Tigeot if (ce->state) { 21421487f786SFrançois Tigeot ret = i915_gem_obj_ggtt_pin(ce->state, ctx->ggtt_alignment, 0); 21431487f786SFrançois Tigeot if (ret) 21441487f786SFrançois Tigeot goto error; 21451487f786SFrançois Tigeot } 21461487f786SFrançois Tigeot 21471487f786SFrançois Tigeot /* The kernel context is only used as a placeholder for flushing the 21481487f786SFrançois Tigeot * active context. It is never used for submitting user rendering and 21491487f786SFrançois Tigeot * as such never requires the golden render context, and so we can skip 21501487f786SFrançois Tigeot * emitting it when we switch to the kernel context. This is required 21511487f786SFrançois Tigeot * as during eviction we cannot allocate and pin the renderstate in 21521487f786SFrançois Tigeot * order to initialise the context. 21531487f786SFrançois Tigeot */ 21541487f786SFrançois Tigeot if (ctx == ctx->i915->kernel_context) 21551487f786SFrançois Tigeot ce->initialised = true; 21561487f786SFrançois Tigeot 2157*87df8fc6SFrançois Tigeot i915_gem_context_get(ctx); 21581487f786SFrançois Tigeot return 0; 21591487f786SFrançois Tigeot 21601487f786SFrançois Tigeot error: 21611487f786SFrançois Tigeot ce->pin_count = 0; 21621487f786SFrançois Tigeot return ret; 21631487f786SFrançois Tigeot } 21641487f786SFrançois Tigeot 21651487f786SFrançois Tigeot static void intel_ring_context_unpin(struct i915_gem_context *ctx, 21661487f786SFrançois Tigeot struct intel_engine_cs *engine) 21671487f786SFrançois Tigeot { 21681487f786SFrançois Tigeot struct intel_context *ce = &ctx->engine[engine->id]; 21691487f786SFrançois Tigeot 2170303bf270SFrançois Tigeot lockdep_assert_held(&ctx->i915->drm.struct_mutex); 21711487f786SFrançois Tigeot 21721487f786SFrançois Tigeot if (--ce->pin_count) 21731487f786SFrançois Tigeot return; 21741487f786SFrançois Tigeot 21751487f786SFrançois Tigeot if (ce->state) 21761487f786SFrançois Tigeot i915_gem_object_ggtt_unpin(ce->state); 21771487f786SFrançois Tigeot 2178*87df8fc6SFrançois Tigeot i915_gem_context_put(ctx); 21791487f786SFrançois Tigeot } 21801487f786SFrançois Tigeot 2181*87df8fc6SFrançois Tigeot static int intel_init_ring_buffer(struct intel_engine_cs *engine) 2182ba55f2f5SFrançois Tigeot { 2183*87df8fc6SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 21842c9916cdSFrançois Tigeot struct intel_ringbuffer *ringbuf; 2185ba55f2f5SFrançois Tigeot int ret; 2186ba55f2f5SFrançois Tigeot 21878621f407SFrançois Tigeot WARN_ON(engine->buffer); 21882c9916cdSFrançois Tigeot 2189*87df8fc6SFrançois Tigeot intel_engine_setup_common(engine); 2190*87df8fc6SFrançois Tigeot 21918621f407SFrançois Tigeot memset(engine->semaphore.sync_seqno, 0, 21928621f407SFrançois Tigeot sizeof(engine->semaphore.sync_seqno)); 2193ba55f2f5SFrançois Tigeot 2194*87df8fc6SFrançois Tigeot ret = intel_engine_init_common(engine); 2195303bf270SFrançois Tigeot if (ret) 2196303bf270SFrançois Tigeot goto error; 2197ba55f2f5SFrançois Tigeot 21981487f786SFrançois Tigeot /* We may need to do things with the shrinker which 21991487f786SFrançois Tigeot * require us to immediately switch back to the default 22001487f786SFrançois Tigeot * context. This can cause a problem as pinning the 22011487f786SFrançois Tigeot * default context also requires GTT space which may not 22021487f786SFrançois Tigeot * be available. To avoid this we always pin the default 22031487f786SFrançois Tigeot * context. 22041487f786SFrançois Tigeot */ 22051487f786SFrançois Tigeot ret = intel_ring_context_pin(dev_priv->kernel_context, engine); 22061487f786SFrançois Tigeot if (ret) 22071487f786SFrançois Tigeot goto error; 22081487f786SFrançois Tigeot 22098621f407SFrançois Tigeot ringbuf = intel_engine_create_ringbuffer(engine, 32 * PAGE_SIZE); 2210aee94f86SFrançois Tigeot if (IS_ERR(ringbuf)) { 2211aee94f86SFrançois Tigeot ret = PTR_ERR(ringbuf); 2212aee94f86SFrançois Tigeot goto error; 2213aee94f86SFrançois Tigeot } 22148621f407SFrançois Tigeot engine->buffer = ringbuf; 2215352ff8bdSFrançois Tigeot 22161487f786SFrançois Tigeot if (I915_NEED_GFX_HWS(dev_priv)) { 22178621f407SFrançois Tigeot ret = init_status_page(engine); 2218e3adcf8fSFrançois Tigeot if (ret) 2219ba55f2f5SFrançois Tigeot goto error; 2220ba55f2f5SFrançois Tigeot } else { 22218621f407SFrançois Tigeot WARN_ON(engine->id != RCS); 22228621f407SFrançois Tigeot ret = init_phys_status_page(engine); 2223ba55f2f5SFrançois Tigeot if (ret) 2224ba55f2f5SFrançois Tigeot goto error; 2225ba55f2f5SFrançois Tigeot } 2226ba55f2f5SFrançois Tigeot 22271487f786SFrançois Tigeot ret = intel_pin_and_map_ringbuffer_obj(dev_priv, ringbuf); 22282c9916cdSFrançois Tigeot if (ret) { 22292c9916cdSFrançois Tigeot DRM_ERROR("Failed to pin and map ringbuffer %s: %d\n", 22308621f407SFrançois Tigeot engine->name, ret); 22312c9916cdSFrançois Tigeot intel_destroy_ringbuffer_obj(ringbuf); 2232ba55f2f5SFrançois Tigeot goto error; 2233ba55f2f5SFrançois Tigeot } 2234e3adcf8fSFrançois Tigeot 2235e3adcf8fSFrançois Tigeot return 0; 2236e3adcf8fSFrançois Tigeot 2237ba55f2f5SFrançois Tigeot error: 22388621f407SFrançois Tigeot intel_cleanup_engine(engine); 2239e3adcf8fSFrançois Tigeot return ret; 2240e3adcf8fSFrançois Tigeot } 2241e3adcf8fSFrançois Tigeot 22428621f407SFrançois Tigeot void intel_cleanup_engine(struct intel_engine_cs *engine) 2243e3adcf8fSFrançois Tigeot { 22442c9916cdSFrançois Tigeot struct drm_i915_private *dev_priv; 2245e3adcf8fSFrançois Tigeot 22468621f407SFrançois Tigeot if (!intel_engine_initialized(engine)) 2247e3adcf8fSFrançois Tigeot return; 2248e3adcf8fSFrançois Tigeot 22491487f786SFrançois Tigeot dev_priv = engine->i915; 22502c9916cdSFrançois Tigeot 22518621f407SFrançois Tigeot if (engine->buffer) { 22528621f407SFrançois Tigeot intel_stop_engine(engine); 22531487f786SFrançois Tigeot WARN_ON(!IS_GEN2(dev_priv) && (I915_READ_MODE(engine) & MODE_IDLE) == 0); 2254b030f26bSFrançois Tigeot 22558621f407SFrançois Tigeot intel_unpin_ringbuffer_obj(engine->buffer); 22568621f407SFrançois Tigeot intel_ringbuffer_free(engine->buffer); 22578621f407SFrançois Tigeot engine->buffer = NULL; 2258aee94f86SFrançois Tigeot } 2259e3adcf8fSFrançois Tigeot 22608621f407SFrançois Tigeot if (engine->cleanup) 22618621f407SFrançois Tigeot engine->cleanup(engine); 2262e3adcf8fSFrançois Tigeot 22631487f786SFrançois Tigeot if (I915_NEED_GFX_HWS(dev_priv)) { 22648621f407SFrançois Tigeot cleanup_status_page(engine); 2265c0e85e96SFrançois Tigeot } else { 22668621f407SFrançois Tigeot WARN_ON(engine->id != RCS); 22678621f407SFrançois Tigeot cleanup_phys_status_page(engine); 2268c0e85e96SFrançois Tigeot } 2269ba55f2f5SFrançois Tigeot 22708621f407SFrançois Tigeot i915_cmd_parser_fini_ring(engine); 22718621f407SFrançois Tigeot i915_gem_batch_pool_fini(&engine->batch_pool); 2272303bf270SFrançois Tigeot intel_engine_fini_breadcrumbs(engine); 22731487f786SFrançois Tigeot 22741487f786SFrançois Tigeot intel_ring_context_unpin(dev_priv->kernel_context, engine); 22751487f786SFrançois Tigeot 22761487f786SFrançois Tigeot engine->i915 = NULL; 2277e3adcf8fSFrançois Tigeot } 2278e3adcf8fSFrançois Tigeot 22798621f407SFrançois Tigeot int intel_engine_idle(struct intel_engine_cs *engine) 2280b030f26bSFrançois Tigeot { 22812c9916cdSFrançois Tigeot struct drm_i915_gem_request *req; 2282b5c29a34SFrançois Tigeot 2283b5c29a34SFrançois Tigeot /* Wait upon the last request to be completed */ 22848621f407SFrançois Tigeot if (list_empty(&engine->request_list)) 2285b5c29a34SFrançois Tigeot return 0; 2286b5c29a34SFrançois Tigeot 22878621f407SFrançois Tigeot req = list_entry(engine->request_list.prev, 2288b5c29a34SFrançois Tigeot struct drm_i915_gem_request, 22892c9916cdSFrançois Tigeot list); 2290b5c29a34SFrançois Tigeot 229119c468b4SFrançois Tigeot /* Make sure we do not trigger any retires */ 229219c468b4SFrançois Tigeot return __i915_wait_request(req, 22938621f407SFrançois Tigeot req->i915->mm.interruptible, 229419c468b4SFrançois Tigeot NULL, NULL); 2295b5c29a34SFrançois Tigeot } 2296b5c29a34SFrançois Tigeot 229719c468b4SFrançois Tigeot int intel_ring_alloc_request_extras(struct drm_i915_gem_request *request) 2298b5c29a34SFrançois Tigeot { 22991487f786SFrançois Tigeot int ret; 23009edbd4a0SFrançois Tigeot 23011487f786SFrançois Tigeot /* Flush enough space to reduce the likelihood of waiting after 23021487f786SFrançois Tigeot * we start building the request - in which case we will just 23031487f786SFrançois Tigeot * have to repeat work. 2304a05eeebfSFrançois Tigeot */ 23051487f786SFrançois Tigeot request->reserved_space += LEGACY_REQUEST_SIZE; 2306a2fdbec6SFrançois Tigeot 23071487f786SFrançois Tigeot request->ringbuf = request->engine->buffer; 2308a2fdbec6SFrançois Tigeot 23091487f786SFrançois Tigeot ret = intel_ring_begin(request, 0); 23101487f786SFrançois Tigeot if (ret) 23111487f786SFrançois Tigeot return ret; 2312a05eeebfSFrançois Tigeot 23131487f786SFrançois Tigeot request->reserved_space -= LEGACY_REQUEST_SIZE; 23141487f786SFrançois Tigeot return 0; 2315a05eeebfSFrançois Tigeot } 2316a05eeebfSFrançois Tigeot 23178621f407SFrançois Tigeot static int wait_for_space(struct drm_i915_gem_request *req, int bytes) 2318a05eeebfSFrançois Tigeot { 23198621f407SFrançois Tigeot struct intel_ringbuffer *ringbuf = req->ringbuf; 23208621f407SFrançois Tigeot struct intel_engine_cs *engine = req->engine; 23218621f407SFrançois Tigeot struct drm_i915_gem_request *target; 23228621f407SFrançois Tigeot 23238621f407SFrançois Tigeot intel_ring_update_space(ringbuf); 23248621f407SFrançois Tigeot if (ringbuf->space >= bytes) 23258621f407SFrançois Tigeot return 0; 23268621f407SFrançois Tigeot 23278621f407SFrançois Tigeot /* 23288621f407SFrançois Tigeot * Space is reserved in the ringbuffer for finalising the request, 23298621f407SFrançois Tigeot * as that cannot be allowed to fail. During request finalisation, 23308621f407SFrançois Tigeot * reserved_space is set to 0 to stop the overallocation and the 23318621f407SFrançois Tigeot * assumption is that then we never need to wait (which has the 23328621f407SFrançois Tigeot * risk of failing with EINTR). 23338621f407SFrançois Tigeot * 23348621f407SFrançois Tigeot * See also i915_gem_request_alloc() and i915_add_request(). 23358621f407SFrançois Tigeot */ 23361487f786SFrançois Tigeot GEM_BUG_ON(!req->reserved_space); 23378621f407SFrançois Tigeot 23388621f407SFrançois Tigeot list_for_each_entry(target, &engine->request_list, list) { 23398621f407SFrançois Tigeot unsigned space; 23408621f407SFrançois Tigeot 23418621f407SFrançois Tigeot /* 23428621f407SFrançois Tigeot * The request queue is per-engine, so can contain requests 23438621f407SFrançois Tigeot * from multiple ringbuffers. Here, we must ignore any that 23448621f407SFrançois Tigeot * aren't from the ringbuffer we're considering. 23458621f407SFrançois Tigeot */ 23468621f407SFrançois Tigeot if (target->ringbuf != ringbuf) 23478621f407SFrançois Tigeot continue; 23488621f407SFrançois Tigeot 23498621f407SFrançois Tigeot /* Would completion of this request free enough space? */ 23508621f407SFrançois Tigeot space = __intel_ring_space(target->postfix, ringbuf->tail, 23518621f407SFrançois Tigeot ringbuf->size); 23528621f407SFrançois Tigeot if (space >= bytes) 23538621f407SFrançois Tigeot break; 23548621f407SFrançois Tigeot } 23558621f407SFrançois Tigeot 23568621f407SFrançois Tigeot if (WARN_ON(&target->list == &engine->request_list)) 23578621f407SFrançois Tigeot return -ENOSPC; 23588621f407SFrançois Tigeot 23598621f407SFrançois Tigeot return i915_wait_request(target); 23608621f407SFrançois Tigeot } 23618621f407SFrançois Tigeot 23628621f407SFrançois Tigeot int intel_ring_begin(struct drm_i915_gem_request *req, int num_dwords) 23638621f407SFrançois Tigeot { 23648621f407SFrançois Tigeot struct intel_ringbuffer *ringbuf = req->ringbuf; 2365a05eeebfSFrançois Tigeot int remain_actual = ringbuf->size - ringbuf->tail; 23668621f407SFrançois Tigeot int remain_usable = ringbuf->effective_size - ringbuf->tail; 23678621f407SFrançois Tigeot int bytes = num_dwords * sizeof(u32); 23688621f407SFrançois Tigeot int total_bytes, wait_bytes; 2369a05eeebfSFrançois Tigeot bool need_wrap = false; 2370a05eeebfSFrançois Tigeot 23711487f786SFrançois Tigeot total_bytes = bytes + req->reserved_space; 2372a05eeebfSFrançois Tigeot 2373a05eeebfSFrançois Tigeot if (unlikely(bytes > remain_usable)) { 2374a05eeebfSFrançois Tigeot /* 2375a05eeebfSFrançois Tigeot * Not enough space for the basic request. So need to flush 2376a05eeebfSFrançois Tigeot * out the remainder and then wait for base + reserved. 2377a05eeebfSFrançois Tigeot */ 2378a05eeebfSFrançois Tigeot wait_bytes = remain_actual + total_bytes; 2379a05eeebfSFrançois Tigeot need_wrap = true; 23808621f407SFrançois Tigeot } else if (unlikely(total_bytes > remain_usable)) { 2381a05eeebfSFrançois Tigeot /* 2382a05eeebfSFrançois Tigeot * The base request will fit but the reserved space 23838621f407SFrançois Tigeot * falls off the end. So we don't need an immediate wrap 2384c0e85e96SFrançois Tigeot * and only need to effectively wait for the reserved 2385c0e85e96SFrançois Tigeot * size space from the start of ringbuffer. 2386a05eeebfSFrançois Tigeot */ 23871487f786SFrançois Tigeot wait_bytes = remain_actual + req->reserved_space; 23888621f407SFrançois Tigeot } else { 2389a05eeebfSFrançois Tigeot /* No wrapping required, just waiting. */ 2390a05eeebfSFrançois Tigeot wait_bytes = total_bytes; 2391a05eeebfSFrançois Tigeot } 2392a05eeebfSFrançois Tigeot 23938621f407SFrançois Tigeot if (wait_bytes > ringbuf->space) { 23948621f407SFrançois Tigeot int ret = wait_for_space(req, wait_bytes); 2395a2fdbec6SFrançois Tigeot if (unlikely(ret)) 2396a2fdbec6SFrançois Tigeot return ret; 2397a05eeebfSFrançois Tigeot 23988621f407SFrançois Tigeot intel_ring_update_space(ringbuf); 23998621f407SFrançois Tigeot if (unlikely(ringbuf->space < wait_bytes)) 24008621f407SFrançois Tigeot return -EAGAIN; 2401a2fdbec6SFrançois Tigeot } 2402a2fdbec6SFrançois Tigeot 24038621f407SFrançois Tigeot if (unlikely(need_wrap)) { 24048621f407SFrançois Tigeot GEM_BUG_ON(remain_actual > ringbuf->space); 24058621f407SFrançois Tigeot GEM_BUG_ON(ringbuf->tail + remain_actual > ringbuf->size); 24068621f407SFrançois Tigeot 24078621f407SFrançois Tigeot /* Fill the tail with MI_NOOP */ 2408*87df8fc6SFrançois Tigeot memset(ringbuf->vaddr + ringbuf->tail, 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 2470303bf270SFrançois Tigeot intel_write_status_page(engine, I915_GEM_HWS_INDEX, seqno); 2471303bf270SFrançois Tigeot if (engine->irq_seqno_barrier) 2472303bf270SFranç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; 2476303bf270SFrançois Tigeot 2477303bf270SFrançois Tigeot /* After manually advancing the seqno, fake the interrupt in case 2478303bf270SFrançois Tigeot * there are any waiters for that seqno. 2479303bf270SFrançois Tigeot */ 2480303bf270SFrançois Tigeot rcu_read_lock(); 2481303bf270SFrançois Tigeot intel_engine_wakeup(engine); 2482303bf270SFranç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 2696*87df8fc6SFrançois Tigeot if (!i915.semaphores) 26971487f786SFrançois Tigeot return; 26981487f786SFrançois Tigeot 26991487f786SFrançois Tigeot if (INTEL_GEN(dev_priv) >= 8 && !dev_priv->semaphore_obj) { 2700303bf270SFranç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) { 2708*87df8fc6SFrançois Tigeot i915_gem_object_put(obj); 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 2717*87df8fc6SFrançois Tigeot if (!i915.semaphores) 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 { 2793*87df8fc6SFrançois Tigeot engine->irq_enable_mask = GT_RENDER_USER_INTERRUPT << engine->irq_shift; 2794*87df8fc6SFrançois Tigeot 27951487f786SFrançois Tigeot if (INTEL_GEN(dev_priv) >= 8) { 2796303bf270SFrançois Tigeot engine->irq_enable = gen8_irq_enable; 2797303bf270SFrançois Tigeot engine->irq_disable = gen8_irq_disable; 27981487f786SFrançois Tigeot engine->irq_seqno_barrier = gen6_seqno_barrier; 27991487f786SFrançois Tigeot } else if (INTEL_GEN(dev_priv) >= 6) { 2800303bf270SFrançois Tigeot engine->irq_enable = gen6_irq_enable; 2801303bf270SFrançois Tigeot engine->irq_disable = gen6_irq_disable; 28021487f786SFrançois Tigeot engine->irq_seqno_barrier = gen6_seqno_barrier; 28031487f786SFrançois Tigeot } else if (INTEL_GEN(dev_priv) >= 5) { 2804303bf270SFrançois Tigeot engine->irq_enable = gen5_irq_enable; 2805303bf270SFrançois Tigeot engine->irq_disable = gen5_irq_disable; 2806303bf270SFrançois Tigeot engine->irq_seqno_barrier = gen5_seqno_barrier; 28071487f786SFrançois Tigeot } else if (INTEL_GEN(dev_priv) >= 3) { 2808303bf270SFrançois Tigeot engine->irq_enable = i9xx_irq_enable; 2809303bf270SFrançois Tigeot engine->irq_disable = i9xx_irq_disable; 28101487f786SFrançois Tigeot } else { 2811303bf270SFrançois Tigeot engine->irq_enable = i8xx_irq_enable; 2812303bf270SFrançois Tigeot engine->irq_disable = i8xx_irq_disable; 28131487f786SFrançois Tigeot } 28141487f786SFrançois Tigeot } 28151487f786SFrançois Tigeot 28161487f786SFrançois Tigeot static void intel_ring_default_vfuncs(struct drm_i915_private *dev_priv, 28171487f786SFrançois Tigeot struct intel_engine_cs *engine) 28181487f786SFrançois Tigeot { 28191487f786SFrançois Tigeot engine->init_hw = init_ring_common; 28201487f786SFrançois Tigeot engine->write_tail = ring_write_tail; 28211487f786SFrançois Tigeot 28221487f786SFrançois Tigeot engine->add_request = i9xx_add_request; 28231487f786SFrançois Tigeot if (INTEL_GEN(dev_priv) >= 6) 28241487f786SFrançois Tigeot engine->add_request = gen6_add_request; 28251487f786SFrançois Tigeot 28261487f786SFrançois Tigeot if (INTEL_GEN(dev_priv) >= 8) 28271487f786SFrançois Tigeot engine->dispatch_execbuffer = gen8_ring_dispatch_execbuffer; 28281487f786SFrançois Tigeot else if (INTEL_GEN(dev_priv) >= 6) 28291487f786SFrançois Tigeot engine->dispatch_execbuffer = gen6_ring_dispatch_execbuffer; 28301487f786SFrançois Tigeot else if (INTEL_GEN(dev_priv) >= 4) 28311487f786SFrançois Tigeot engine->dispatch_execbuffer = i965_dispatch_execbuffer; 28321487f786SFrançois Tigeot else if (IS_I830(dev_priv) || IS_845G(dev_priv)) 28331487f786SFrançois Tigeot engine->dispatch_execbuffer = i830_dispatch_execbuffer; 28341487f786SFrançois Tigeot else 28351487f786SFrançois Tigeot engine->dispatch_execbuffer = i915_dispatch_execbuffer; 28361487f786SFrançois Tigeot 28371487f786SFrançois Tigeot intel_ring_init_irq(dev_priv, engine); 28381487f786SFrançois Tigeot intel_ring_init_semaphores(dev_priv, engine); 28391487f786SFrançois Tigeot } 28401487f786SFrançois Tigeot 2841*87df8fc6SFrançois Tigeot int intel_init_render_ring_buffer(struct intel_engine_cs *engine) 2842e3adcf8fSFrançois Tigeot { 2843*87df8fc6SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 284424edb884SFrançois Tigeot int ret; 2845e3adcf8fSFrançois Tigeot 28461487f786SFrançois Tigeot intel_ring_default_vfuncs(dev_priv, engine); 28472c9916cdSFrançois Tigeot 2848303bf270SFrançois Tigeot if (HAS_L3_DPF(dev_priv)) 2849303bf270SFrançois Tigeot engine->irq_keep_mask = GT_RENDER_L3_PARITY_ERROR_INTERRUPT; 2850303bf270SFrançois Tigeot 28511487f786SFrançois Tigeot if (INTEL_GEN(dev_priv) >= 8) { 28528621f407SFrançois Tigeot engine->init_context = intel_rcs_ctx_init; 28531487f786SFrançois Tigeot engine->add_request = gen8_render_add_request; 28548621f407SFrançois Tigeot engine->flush = gen8_render_ring_flush; 2855*87df8fc6SFrançois Tigeot if (i915.semaphores) 28568621f407SFrançois Tigeot engine->semaphore.signal = gen8_rcs_signal; 28571487f786SFrançois Tigeot } else if (INTEL_GEN(dev_priv) >= 6) { 28588621f407SFrançois Tigeot engine->init_context = intel_rcs_ctx_init; 28598621f407SFrançois Tigeot engine->flush = gen7_render_ring_flush; 28601487f786SFrançois Tigeot if (IS_GEN6(dev_priv)) 28618621f407SFrançois Tigeot engine->flush = gen6_render_ring_flush; 28621487f786SFrançois Tigeot } else if (IS_GEN5(dev_priv)) { 28638621f407SFrançois Tigeot engine->flush = gen4_render_ring_flush; 2864686a02f1SFrançois Tigeot } else { 28651487f786SFrançois Tigeot if (INTEL_GEN(dev_priv) < 4) 28668621f407SFrançois Tigeot engine->flush = gen2_render_ring_flush; 2867686a02f1SFrançois Tigeot else 28688621f407SFrançois Tigeot engine->flush = gen4_render_ring_flush; 28698621f407SFrançois Tigeot engine->irq_enable_mask = I915_USER_INTERRUPT; 2870686a02f1SFrançois Tigeot } 287124edb884SFrançois Tigeot 28721487f786SFrançois Tigeot if (IS_HASWELL(dev_priv)) 28738621f407SFrançois Tigeot engine->dispatch_execbuffer = hsw_ring_dispatch_execbuffer; 28741487f786SFrançois Tigeot 28758621f407SFrançois Tigeot engine->init_hw = init_render_ring; 28768621f407SFrançois Tigeot engine->cleanup = render_ring_cleanup; 2877e3adcf8fSFrançois Tigeot 2878*87df8fc6SFrançois Tigeot ret = intel_init_ring_buffer(engine); 2879b5c29a34SFrançois Tigeot if (ret) 28802c9916cdSFrançois Tigeot return ret; 28812c9916cdSFrançois Tigeot 2882303bf270SFrançois Tigeot if (INTEL_GEN(dev_priv) >= 6) { 2883303bf270SFrançois Tigeot ret = intel_init_pipe_control(engine, 4096); 2884303bf270SFrançois Tigeot if (ret) 2885303bf270SFrançois Tigeot return ret; 2886303bf270SFrançois Tigeot } else if (HAS_BROKEN_CS_TLB(dev_priv)) { 2887303bf270SFrançois Tigeot ret = intel_init_pipe_control(engine, I830_WA_SIZE); 28882c9916cdSFrançois Tigeot if (ret) 28892c9916cdSFrançois Tigeot return ret; 2890b5c29a34SFrançois Tigeot } 2891b5c29a34SFrançois Tigeot 2892e3adcf8fSFrançois Tigeot return 0; 2893e3adcf8fSFrançois Tigeot } 2894e3adcf8fSFrançois Tigeot 2895*87df8fc6SFrançois Tigeot int intel_init_bsd_ring_buffer(struct intel_engine_cs *engine) 2896e3adcf8fSFrançois Tigeot { 2897*87df8fc6SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 2898686a02f1SFrançois Tigeot 28991487f786SFrançois Tigeot intel_ring_default_vfuncs(dev_priv, engine); 29001487f786SFrançois Tigeot 29011487f786SFrançois Tigeot if (INTEL_GEN(dev_priv) >= 6) { 2902686a02f1SFrançois Tigeot /* gen6 bsd needs a special wa for tail updates */ 29031487f786SFrançois Tigeot if (IS_GEN6(dev_priv)) 29048621f407SFrançois Tigeot engine->write_tail = gen6_bsd_ring_write_tail; 29058621f407SFrançois Tigeot engine->flush = gen6_bsd_ring_flush; 2906*87df8fc6SFrançois Tigeot if (INTEL_GEN(dev_priv) < 8) 29078621f407SFrançois Tigeot engine->irq_enable_mask = GT_BSD_USER_INTERRUPT; 2908686a02f1SFrançois Tigeot } else { 29098621f407SFrançois Tigeot engine->mmio_base = BSD_RING_BASE; 29108621f407SFrançois Tigeot engine->flush = bsd_ring_flush; 29111487f786SFrançois Tigeot if (IS_GEN5(dev_priv)) 29128621f407SFrançois Tigeot engine->irq_enable_mask = ILK_BSD_USER_INTERRUPT; 29131487f786SFrançois Tigeot else 29148621f407SFrançois Tigeot engine->irq_enable_mask = I915_BSD_USER_INTERRUPT; 2915686a02f1SFrançois Tigeot } 2916e3adcf8fSFrançois Tigeot 2917*87df8fc6SFrançois Tigeot return intel_init_ring_buffer(engine); 2918e3adcf8fSFrançois Tigeot } 2919e3adcf8fSFrançois Tigeot 2920ba55f2f5SFrançois Tigeot /** 2921477eb7f9SFrançois Tigeot * Initialize the second BSD ring (eg. Broadwell GT3, Skylake GT3) 2922ba55f2f5SFrançois Tigeot */ 2923*87df8fc6SFrançois Tigeot int intel_init_bsd2_ring_buffer(struct intel_engine_cs *engine) 2924ba55f2f5SFrançois Tigeot { 2925*87df8fc6SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 29261487f786SFrançois Tigeot 29271487f786SFrançois Tigeot intel_ring_default_vfuncs(dev_priv, engine); 29281487f786SFrançois Tigeot 29298621f407SFrançois Tigeot engine->flush = gen6_bsd_ring_flush; 2930ba55f2f5SFrançois Tigeot 2931*87df8fc6SFrançois Tigeot return intel_init_ring_buffer(engine); 2932ba55f2f5SFrançois Tigeot } 2933ba55f2f5SFrançois Tigeot 2934*87df8fc6SFrançois Tigeot int intel_init_blt_ring_buffer(struct intel_engine_cs *engine) 2935e3adcf8fSFrançois Tigeot { 2936*87df8fc6SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 29371487f786SFrançois Tigeot 29381487f786SFrançois Tigeot intel_ring_default_vfuncs(dev_priv, engine); 29391487f786SFrançois Tigeot 29408621f407SFrançois Tigeot engine->flush = gen6_ring_flush; 2941*87df8fc6SFrançois Tigeot if (INTEL_GEN(dev_priv) < 8) 29428621f407SFrançois Tigeot engine->irq_enable_mask = GT_BLT_USER_INTERRUPT; 29435d0b1887SFrançois Tigeot 2944*87df8fc6SFrançois Tigeot return intel_init_ring_buffer(engine); 29455d0b1887SFrançois Tigeot } 29465d0b1887SFrançois Tigeot 2947*87df8fc6SFrançois Tigeot int intel_init_vebox_ring_buffer(struct intel_engine_cs *engine) 29485d0b1887SFrançois Tigeot { 2949*87df8fc6SFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 29509edbd4a0SFrançois Tigeot 29511487f786SFrançois Tigeot intel_ring_default_vfuncs(dev_priv, engine); 29521487f786SFrançois Tigeot 29531487f786SFrançois Tigeot engine->flush = gen6_ring_flush; 29541487f786SFrançois Tigeot 2955*87df8fc6SFrançois Tigeot if (INTEL_GEN(dev_priv) < 8) { 29568621f407SFrançois Tigeot engine->irq_enable_mask = PM_VEBOX_USER_INTERRUPT; 2957303bf270SFrançois Tigeot engine->irq_enable = hsw_vebox_irq_enable; 2958303bf270SFrançois Tigeot engine->irq_disable = hsw_vebox_irq_disable; 295924edb884SFrançois Tigeot } 2960e3adcf8fSFrançois Tigeot 2961*87df8fc6SFrançois Tigeot return intel_init_ring_buffer(engine); 2962e3adcf8fSFrançois Tigeot } 2963b030f26bSFrançois Tigeot 2964b030f26bSFrançois Tigeot int 2965a05eeebfSFrançois Tigeot intel_ring_flush_all_caches(struct drm_i915_gem_request *req) 2966b030f26bSFrançois Tigeot { 29678621f407SFrançois Tigeot struct intel_engine_cs *engine = req->engine; 2968b030f26bSFrançois Tigeot int ret; 2969b030f26bSFrançois Tigeot 29708621f407SFrançois Tigeot if (!engine->gpu_caches_dirty) 2971b030f26bSFrançois Tigeot return 0; 2972b030f26bSFrançois Tigeot 29738621f407SFrançois Tigeot ret = engine->flush(req, 0, I915_GEM_GPU_DOMAINS); 2974b030f26bSFrançois Tigeot if (ret) 2975b030f26bSFrançois Tigeot return ret; 2976b030f26bSFrançois Tigeot 2977a05eeebfSFrançois Tigeot trace_i915_gem_ring_flush(req, 0, I915_GEM_GPU_DOMAINS); 2978a2fdbec6SFrançois Tigeot 29798621f407SFrançois Tigeot engine->gpu_caches_dirty = false; 2980b030f26bSFrançois Tigeot return 0; 2981b030f26bSFrançois Tigeot } 2982b030f26bSFrançois Tigeot 2983b030f26bSFrançois Tigeot int 2984a05eeebfSFrançois Tigeot intel_ring_invalidate_all_caches(struct drm_i915_gem_request *req) 2985b030f26bSFrançois Tigeot { 29868621f407SFrançois Tigeot struct intel_engine_cs *engine = req->engine; 2987b030f26bSFrançois Tigeot uint32_t flush_domains; 2988b030f26bSFrançois Tigeot int ret; 2989b030f26bSFrançois Tigeot 2990b030f26bSFrançois Tigeot flush_domains = 0; 29918621f407SFrançois Tigeot if (engine->gpu_caches_dirty) 2992b030f26bSFrançois Tigeot flush_domains = I915_GEM_GPU_DOMAINS; 2993b030f26bSFrançois Tigeot 29948621f407SFrançois Tigeot ret = engine->flush(req, I915_GEM_GPU_DOMAINS, flush_domains); 2995b030f26bSFrançois Tigeot if (ret) 2996b030f26bSFrançois Tigeot return ret; 2997b030f26bSFrançois Tigeot 2998a05eeebfSFrançois Tigeot trace_i915_gem_ring_flush(req, I915_GEM_GPU_DOMAINS, flush_domains); 2999a2fdbec6SFrançois Tigeot 30008621f407SFrançois Tigeot engine->gpu_caches_dirty = false; 3001b030f26bSFrançois Tigeot return 0; 3002b030f26bSFrançois Tigeot } 3003ba55f2f5SFrançois Tigeot 3004ba55f2f5SFrançois Tigeot void 30058621f407SFrançois Tigeot intel_stop_engine(struct intel_engine_cs *engine) 3006ba55f2f5SFrançois Tigeot { 3007ba55f2f5SFrançois Tigeot int ret; 3008ba55f2f5SFrançois Tigeot 30098621f407SFrançois Tigeot if (!intel_engine_initialized(engine)) 3010ba55f2f5SFrançois Tigeot return; 3011ba55f2f5SFrançois Tigeot 30128621f407SFrançois Tigeot ret = intel_engine_idle(engine); 30138621f407SFrançois Tigeot if (ret) 3014ba55f2f5SFrançois Tigeot DRM_ERROR("failed to quiesce %s whilst cleaning up: %d\n", 30158621f407SFrançois Tigeot engine->name, ret); 3016ba55f2f5SFrançois Tigeot 30178621f407SFrançois Tigeot stop_ring(engine); 3018ba55f2f5SFrançois Tigeot } 3019