1e3adcf8fSFrançois Tigeot /* 2e3adcf8fSFrançois Tigeot * Copyright © 2008-2010 Intel Corporation 3e3adcf8fSFrançois Tigeot * 4e3adcf8fSFrançois Tigeot * Permission is hereby granted, free of charge, to any person obtaining a 5e3adcf8fSFrançois Tigeot * copy of this software and associated documentation files (the "Software"), 6e3adcf8fSFrançois Tigeot * to deal in the Software without restriction, including without limitation 7e3adcf8fSFrançois Tigeot * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8e3adcf8fSFrançois Tigeot * and/or sell copies of the Software, and to permit persons to whom the 9e3adcf8fSFrançois Tigeot * Software is furnished to do so, subject to the following conditions: 10e3adcf8fSFrançois Tigeot * 11e3adcf8fSFrançois Tigeot * The above copyright notice and this permission notice (including the next 12e3adcf8fSFrançois Tigeot * paragraph) shall be included in all copies or substantial portions of the 13e3adcf8fSFrançois Tigeot * Software. 14e3adcf8fSFrançois Tigeot * 15e3adcf8fSFrançois Tigeot * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16e3adcf8fSFrançois Tigeot * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17e3adcf8fSFrançois Tigeot * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18e3adcf8fSFrançois Tigeot * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19e3adcf8fSFrançois Tigeot * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20e3adcf8fSFrançois Tigeot * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21e3adcf8fSFrançois Tigeot * IN THE SOFTWARE. 22e3adcf8fSFrançois Tigeot * 23e3adcf8fSFrançois Tigeot * Authors: 24e3adcf8fSFrançois Tigeot * Eric Anholt <eric@anholt.net> 25e3adcf8fSFrançois Tigeot * Zou Nan hai <nanhai.zou@intel.com> 26e3adcf8fSFrançois Tigeot * Xiang Hai hao<haihao.xiang@intel.com> 27e3adcf8fSFrançois Tigeot * 28e3adcf8fSFrançois Tigeot */ 29e3adcf8fSFrançois Tigeot 30aee94f86SFrançois Tigeot #include <linux/log2.h> 3118e26a6dSFrançois Tigeot #include <drm/drmP.h> 32e3adcf8fSFrançois Tigeot #include "i915_drv.h" 33a2fdbec6SFrançois Tigeot #include <drm/i915_drm.h> 34a2fdbec6SFrançois Tigeot #include "i915_trace.h" 35e3adcf8fSFrançois Tigeot #include "intel_drv.h" 36e3adcf8fSFrançois Tigeot 371b13d190SFrançois Tigeot int __intel_ring_space(int head, int tail, int size) 38e3adcf8fSFrançois Tigeot { 392c9916cdSFrançois Tigeot int space = head - tail; 402c9916cdSFrançois Tigeot if (space <= 0) 41ba55f2f5SFrançois Tigeot space += size; 422c9916cdSFrançois Tigeot return space - I915_RING_FREE_SPACE; 432c9916cdSFrançois Tigeot } 442c9916cdSFrançois Tigeot 452c9916cdSFrançois Tigeot void intel_ring_update_space(struct intel_ringbuffer *ringbuf) 462c9916cdSFrançois Tigeot { 472c9916cdSFrançois Tigeot if (ringbuf->last_retired_head != -1) { 482c9916cdSFrançois Tigeot ringbuf->head = ringbuf->last_retired_head; 492c9916cdSFrançois Tigeot ringbuf->last_retired_head = -1; 502c9916cdSFrançois Tigeot } 512c9916cdSFrançois Tigeot 522c9916cdSFrançois Tigeot ringbuf->space = __intel_ring_space(ringbuf->head & HEAD_ADDR, 532c9916cdSFrançois Tigeot ringbuf->tail, ringbuf->size); 54e3adcf8fSFrançois Tigeot } 55e3adcf8fSFrançois Tigeot 561b13d190SFrançois Tigeot int intel_ring_space(struct intel_ringbuffer *ringbuf) 57ba55f2f5SFrançois Tigeot { 582c9916cdSFrançois Tigeot intel_ring_update_space(ringbuf); 592c9916cdSFrançois Tigeot return ringbuf->space; 60ba55f2f5SFrançois Tigeot } 61ba55f2f5SFrançois Tigeot 621b13d190SFrançois Tigeot bool intel_ring_stopped(struct intel_engine_cs *ring) 639edbd4a0SFrançois Tigeot { 649edbd4a0SFrançois Tigeot struct drm_i915_private *dev_priv = ring->dev->dev_private; 65ba55f2f5SFrançois Tigeot return dev_priv->gpu_error.stop_rings & intel_ring_flag(ring); 66ba55f2f5SFrançois Tigeot } 679edbd4a0SFrançois Tigeot 68a05eeebfSFrançois Tigeot static void __intel_ring_advance(struct intel_engine_cs *ring) 69ba55f2f5SFrançois Tigeot { 70ba55f2f5SFrançois Tigeot struct intel_ringbuffer *ringbuf = ring->buffer; 71ba55f2f5SFrançois Tigeot ringbuf->tail &= ringbuf->size - 1; 72ba55f2f5SFrançois Tigeot if (intel_ring_stopped(ring)) 739edbd4a0SFrançois Tigeot return; 74ba55f2f5SFrançois Tigeot ring->write_tail(ring, ringbuf->tail); 759edbd4a0SFrançois Tigeot } 769edbd4a0SFrançois Tigeot 77e3adcf8fSFrançois Tigeot static int 78a05eeebfSFrançois Tigeot gen2_render_ring_flush(struct drm_i915_gem_request *req, 79686a02f1SFrançois Tigeot u32 invalidate_domains, 80686a02f1SFrançois Tigeot u32 flush_domains) 81686a02f1SFrançois Tigeot { 82a05eeebfSFrançois Tigeot struct intel_engine_cs *ring = req->ring; 83686a02f1SFrançois Tigeot u32 cmd; 84686a02f1SFrançois Tigeot int ret; 85686a02f1SFrançois Tigeot 86686a02f1SFrançois Tigeot cmd = MI_FLUSH; 87686a02f1SFrançois Tigeot if (((invalidate_domains|flush_domains) & I915_GEM_DOMAIN_RENDER) == 0) 88686a02f1SFrançois Tigeot cmd |= MI_NO_WRITE_FLUSH; 89686a02f1SFrançois Tigeot 90686a02f1SFrançois Tigeot if (invalidate_domains & I915_GEM_DOMAIN_SAMPLER) 91686a02f1SFrançois Tigeot cmd |= MI_READ_FLUSH; 92686a02f1SFrançois Tigeot 93a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 2); 94686a02f1SFrançois Tigeot if (ret) 95686a02f1SFrançois Tigeot return ret; 96686a02f1SFrançois Tigeot 97686a02f1SFrançois Tigeot intel_ring_emit(ring, cmd); 98686a02f1SFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 99686a02f1SFrançois Tigeot intel_ring_advance(ring); 100686a02f1SFrançois Tigeot 101686a02f1SFrançois Tigeot return 0; 102686a02f1SFrançois Tigeot } 103686a02f1SFrançois Tigeot 104686a02f1SFrançois Tigeot static int 105a05eeebfSFrançois Tigeot gen4_render_ring_flush(struct drm_i915_gem_request *req, 106686a02f1SFrançois Tigeot u32 invalidate_domains, 107686a02f1SFrançois Tigeot u32 flush_domains) 108e3adcf8fSFrançois Tigeot { 109a05eeebfSFrançois Tigeot struct intel_engine_cs *ring = req->ring; 110e3adcf8fSFrançois Tigeot struct drm_device *dev = ring->dev; 111686a02f1SFrançois Tigeot u32 cmd; 112e3adcf8fSFrançois Tigeot int ret; 113e3adcf8fSFrançois Tigeot 114e3adcf8fSFrançois Tigeot /* 115e3adcf8fSFrançois Tigeot * read/write caches: 116e3adcf8fSFrançois Tigeot * 117e3adcf8fSFrançois Tigeot * I915_GEM_DOMAIN_RENDER is always invalidated, but is 118e3adcf8fSFrançois Tigeot * only flushed if MI_NO_WRITE_FLUSH is unset. On 965, it is 119e3adcf8fSFrançois Tigeot * also flushed at 2d versus 3d pipeline switches. 120e3adcf8fSFrançois Tigeot * 121e3adcf8fSFrançois Tigeot * read-only caches: 122e3adcf8fSFrançois Tigeot * 123e3adcf8fSFrançois Tigeot * I915_GEM_DOMAIN_SAMPLER is flushed on pre-965 if 124e3adcf8fSFrançois Tigeot * MI_READ_FLUSH is set, and is always flushed on 965. 125e3adcf8fSFrançois Tigeot * 126e3adcf8fSFrançois Tigeot * I915_GEM_DOMAIN_COMMAND may not exist? 127e3adcf8fSFrançois Tigeot * 128e3adcf8fSFrançois Tigeot * I915_GEM_DOMAIN_INSTRUCTION, which exists on 965, is 129e3adcf8fSFrançois Tigeot * invalidated when MI_EXE_FLUSH is set. 130e3adcf8fSFrançois Tigeot * 131e3adcf8fSFrançois Tigeot * I915_GEM_DOMAIN_VERTEX, which exists on 965, is 132e3adcf8fSFrançois Tigeot * invalidated with every MI_FLUSH. 133e3adcf8fSFrançois Tigeot * 134e3adcf8fSFrançois Tigeot * TLBs: 135e3adcf8fSFrançois Tigeot * 136e3adcf8fSFrançois Tigeot * On 965, TLBs associated with I915_GEM_DOMAIN_COMMAND 137e3adcf8fSFrançois Tigeot * and I915_GEM_DOMAIN_CPU in are invalidated at PTE write and 138e3adcf8fSFrançois Tigeot * I915_GEM_DOMAIN_RENDER and I915_GEM_DOMAIN_SAMPLER 139e3adcf8fSFrançois Tigeot * are flushed at any MI_FLUSH. 140e3adcf8fSFrançois Tigeot */ 141e3adcf8fSFrançois Tigeot 142e3adcf8fSFrançois Tigeot cmd = MI_FLUSH | MI_NO_WRITE_FLUSH; 143686a02f1SFrançois Tigeot if ((invalidate_domains|flush_domains) & I915_GEM_DOMAIN_RENDER) 144e3adcf8fSFrançois Tigeot cmd &= ~MI_NO_WRITE_FLUSH; 145e3adcf8fSFrançois Tigeot if (invalidate_domains & I915_GEM_DOMAIN_INSTRUCTION) 146e3adcf8fSFrançois Tigeot cmd |= MI_EXE_FLUSH; 147e3adcf8fSFrançois Tigeot 148e3adcf8fSFrançois Tigeot if (invalidate_domains & I915_GEM_DOMAIN_COMMAND && 149e3adcf8fSFrançois Tigeot (IS_G4X(dev) || IS_GEN5(dev))) 150e3adcf8fSFrançois Tigeot cmd |= MI_INVALIDATE_ISP; 151e3adcf8fSFrançois Tigeot 152a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 2); 153e3adcf8fSFrançois Tigeot if (ret) 154e3adcf8fSFrançois Tigeot return ret; 155e3adcf8fSFrançois Tigeot 156e3adcf8fSFrançois Tigeot intel_ring_emit(ring, cmd); 157e3adcf8fSFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 158e3adcf8fSFrançois Tigeot intel_ring_advance(ring); 159e3adcf8fSFrançois Tigeot 160e3adcf8fSFrançois Tigeot return 0; 161e3adcf8fSFrançois Tigeot } 162e3adcf8fSFrançois Tigeot 163e3adcf8fSFrançois Tigeot /** 164e3adcf8fSFrançois Tigeot * Emits a PIPE_CONTROL with a non-zero post-sync operation, for 165e3adcf8fSFrançois Tigeot * implementing two workarounds on gen6. From section 1.4.7.1 166e3adcf8fSFrançois Tigeot * "PIPE_CONTROL" of the Sandy Bridge PRM volume 2 part 1: 167e3adcf8fSFrançois Tigeot * 168e3adcf8fSFrançois Tigeot * [DevSNB-C+{W/A}] Before any depth stall flush (including those 169e3adcf8fSFrançois Tigeot * produced by non-pipelined state commands), software needs to first 170e3adcf8fSFrançois Tigeot * send a PIPE_CONTROL with no bits set except Post-Sync Operation != 171e3adcf8fSFrançois Tigeot * 0. 172e3adcf8fSFrançois Tigeot * 173e3adcf8fSFrançois Tigeot * [Dev-SNB{W/A}]: Before a PIPE_CONTROL with Write Cache Flush Enable 174e3adcf8fSFrançois Tigeot * =1, a PIPE_CONTROL with any non-zero post-sync-op is required. 175e3adcf8fSFrançois Tigeot * 176e3adcf8fSFrançois Tigeot * And the workaround for these two requires this workaround first: 177e3adcf8fSFrançois Tigeot * 178e3adcf8fSFrançois Tigeot * [Dev-SNB{W/A}]: Pipe-control with CS-stall bit set must be sent 179e3adcf8fSFrançois Tigeot * BEFORE the pipe-control with a post-sync op and no write-cache 180e3adcf8fSFrançois Tigeot * flushes. 181e3adcf8fSFrançois Tigeot * 182e3adcf8fSFrançois Tigeot * And this last workaround is tricky because of the requirements on 183e3adcf8fSFrançois Tigeot * that bit. From section 1.4.7.2.3 "Stall" of the Sandy Bridge PRM 184e3adcf8fSFrançois Tigeot * volume 2 part 1: 185e3adcf8fSFrançois Tigeot * 186e3adcf8fSFrançois Tigeot * "1 of the following must also be set: 187e3adcf8fSFrançois Tigeot * - Render Target Cache Flush Enable ([12] of DW1) 188e3adcf8fSFrançois Tigeot * - Depth Cache Flush Enable ([0] of DW1) 189e3adcf8fSFrançois Tigeot * - Stall at Pixel Scoreboard ([1] of DW1) 190e3adcf8fSFrançois Tigeot * - Depth Stall ([13] of DW1) 191e3adcf8fSFrançois Tigeot * - Post-Sync Operation ([13] of DW1) 192e3adcf8fSFrançois Tigeot * - Notify Enable ([8] of DW1)" 193e3adcf8fSFrançois Tigeot * 194e3adcf8fSFrançois Tigeot * The cache flushes require the workaround flush that triggered this 195e3adcf8fSFrançois Tigeot * one, so we can't use it. Depth stall would trigger the same. 196e3adcf8fSFrançois Tigeot * Post-sync nonzero is what triggered this second workaround, so we 197e3adcf8fSFrançois Tigeot * can't use that one either. Notify enable is IRQs, which aren't 198e3adcf8fSFrançois Tigeot * really our business. That leaves only stall at scoreboard. 199e3adcf8fSFrançois Tigeot */ 200e3adcf8fSFrançois Tigeot static int 201a05eeebfSFrançois Tigeot intel_emit_post_sync_nonzero_flush(struct drm_i915_gem_request *req) 202e3adcf8fSFrançois Tigeot { 203a05eeebfSFrançois Tigeot struct intel_engine_cs *ring = req->ring; 204ba55f2f5SFrançois Tigeot u32 scratch_addr = ring->scratch.gtt_offset + 2 * CACHELINE_BYTES; 205e3adcf8fSFrançois Tigeot int ret; 206e3adcf8fSFrançois Tigeot 207a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 6); 208e3adcf8fSFrançois Tigeot if (ret) 209e3adcf8fSFrançois Tigeot return ret; 210e3adcf8fSFrançois Tigeot 211e3adcf8fSFrançois Tigeot intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(5)); 212e3adcf8fSFrançois Tigeot intel_ring_emit(ring, PIPE_CONTROL_CS_STALL | 213e3adcf8fSFrançois Tigeot PIPE_CONTROL_STALL_AT_SCOREBOARD); 214e3adcf8fSFrançois Tigeot intel_ring_emit(ring, scratch_addr | PIPE_CONTROL_GLOBAL_GTT); /* address */ 215e3adcf8fSFrançois Tigeot intel_ring_emit(ring, 0); /* low dword */ 216e3adcf8fSFrançois Tigeot intel_ring_emit(ring, 0); /* high dword */ 217e3adcf8fSFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 218e3adcf8fSFrançois Tigeot intel_ring_advance(ring); 219e3adcf8fSFrançois Tigeot 220a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 6); 221e3adcf8fSFrançois Tigeot if (ret) 222e3adcf8fSFrançois Tigeot return ret; 223e3adcf8fSFrançois Tigeot 224e3adcf8fSFrançois Tigeot intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(5)); 225e3adcf8fSFrançois Tigeot intel_ring_emit(ring, PIPE_CONTROL_QW_WRITE); 226e3adcf8fSFrançois Tigeot intel_ring_emit(ring, scratch_addr | PIPE_CONTROL_GLOBAL_GTT); /* address */ 227e3adcf8fSFrançois Tigeot intel_ring_emit(ring, 0); 228e3adcf8fSFrançois Tigeot intel_ring_emit(ring, 0); 229e3adcf8fSFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 230e3adcf8fSFrançois Tigeot intel_ring_advance(ring); 231e3adcf8fSFrançois Tigeot 232e3adcf8fSFrançois Tigeot return 0; 233e3adcf8fSFrançois Tigeot } 234e3adcf8fSFrançois Tigeot 235e3adcf8fSFrançois Tigeot static int 236a05eeebfSFrançois Tigeot gen6_render_ring_flush(struct drm_i915_gem_request *req, 237e3adcf8fSFrançois Tigeot u32 invalidate_domains, u32 flush_domains) 238e3adcf8fSFrançois Tigeot { 239a05eeebfSFrançois Tigeot struct intel_engine_cs *ring = req->ring; 240e3adcf8fSFrançois Tigeot u32 flags = 0; 241ba55f2f5SFrançois Tigeot u32 scratch_addr = ring->scratch.gtt_offset + 2 * CACHELINE_BYTES; 242e3adcf8fSFrançois Tigeot int ret; 243e3adcf8fSFrançois Tigeot 244e3adcf8fSFrançois Tigeot /* Force SNB workarounds for PIPE_CONTROL flushes */ 245a05eeebfSFrançois Tigeot ret = intel_emit_post_sync_nonzero_flush(req); 246686a02f1SFrançois Tigeot if (ret) 247686a02f1SFrançois Tigeot return ret; 248e3adcf8fSFrançois Tigeot 249e3adcf8fSFrançois Tigeot /* Just flush everything. Experiments have shown that reducing the 250e3adcf8fSFrançois Tigeot * number of bits based on the write domains has little performance 251e3adcf8fSFrançois Tigeot * impact. 252e3adcf8fSFrançois Tigeot */ 253b5c29a34SFrançois Tigeot if (flush_domains) { 254e3adcf8fSFrançois Tigeot flags |= PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH; 255b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_DEPTH_CACHE_FLUSH; 256b5c29a34SFrançois Tigeot /* 257b5c29a34SFrançois Tigeot * Ensure that any following seqno writes only happen 258b5c29a34SFrançois Tigeot * when the render cache is indeed flushed. 259b5c29a34SFrançois Tigeot */ 260b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_CS_STALL; 261b5c29a34SFrançois Tigeot } 262b5c29a34SFrançois Tigeot if (invalidate_domains) { 263686a02f1SFrançois Tigeot flags |= PIPE_CONTROL_TLB_INVALIDATE; 264e3adcf8fSFrançois Tigeot flags |= PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE; 265e3adcf8fSFrançois Tigeot flags |= PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE; 266e3adcf8fSFrançois Tigeot flags |= PIPE_CONTROL_VF_CACHE_INVALIDATE; 267e3adcf8fSFrançois Tigeot flags |= PIPE_CONTROL_CONST_CACHE_INVALIDATE; 268e3adcf8fSFrançois Tigeot flags |= PIPE_CONTROL_STATE_CACHE_INVALIDATE; 269686a02f1SFrançois Tigeot /* 270b5c29a34SFrançois Tigeot * TLB invalidate requires a post-sync write. 271686a02f1SFrançois Tigeot */ 272b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_QW_WRITE | PIPE_CONTROL_CS_STALL; 273b5c29a34SFrançois Tigeot } 274e3adcf8fSFrançois Tigeot 275a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 4); 276e3adcf8fSFrançois Tigeot if (ret) 277e3adcf8fSFrançois Tigeot return ret; 278e3adcf8fSFrançois Tigeot 279b5c29a34SFrançois Tigeot intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(4)); 280e3adcf8fSFrançois Tigeot intel_ring_emit(ring, flags); 281e3adcf8fSFrançois Tigeot intel_ring_emit(ring, scratch_addr | PIPE_CONTROL_GLOBAL_GTT); 282b5c29a34SFrançois Tigeot intel_ring_emit(ring, 0); 283b5c29a34SFrançois Tigeot intel_ring_advance(ring); 284b5c29a34SFrançois Tigeot 285b5c29a34SFrançois Tigeot return 0; 286b5c29a34SFrançois Tigeot } 287b5c29a34SFrançois Tigeot 288b5c29a34SFrançois Tigeot static int 289a05eeebfSFrançois Tigeot gen7_render_ring_cs_stall_wa(struct drm_i915_gem_request *req) 290b5c29a34SFrançois Tigeot { 291a05eeebfSFrançois Tigeot struct intel_engine_cs *ring = req->ring; 292b5c29a34SFrançois Tigeot int ret; 293b5c29a34SFrançois Tigeot 294a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 4); 295b5c29a34SFrançois Tigeot if (ret) 296b5c29a34SFrançois Tigeot return ret; 297b5c29a34SFrançois Tigeot 298b5c29a34SFrançois Tigeot intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(4)); 299b5c29a34SFrançois Tigeot intel_ring_emit(ring, PIPE_CONTROL_CS_STALL | 300b5c29a34SFrançois Tigeot PIPE_CONTROL_STALL_AT_SCOREBOARD); 301b5c29a34SFrançois Tigeot intel_ring_emit(ring, 0); 302b5c29a34SFrançois Tigeot intel_ring_emit(ring, 0); 303b5c29a34SFrançois Tigeot intel_ring_advance(ring); 304b5c29a34SFrançois Tigeot 305b5c29a34SFrançois Tigeot return 0; 306b5c29a34SFrançois Tigeot } 307b5c29a34SFrançois Tigeot 308b5c29a34SFrançois Tigeot static int 309a05eeebfSFrançois Tigeot gen7_render_ring_flush(struct drm_i915_gem_request *req, 310b5c29a34SFrançois Tigeot u32 invalidate_domains, u32 flush_domains) 311b5c29a34SFrançois Tigeot { 312a05eeebfSFrançois Tigeot struct intel_engine_cs *ring = req->ring; 313b5c29a34SFrançois Tigeot u32 flags = 0; 314ba55f2f5SFrançois Tigeot u32 scratch_addr = ring->scratch.gtt_offset + 2 * CACHELINE_BYTES; 315b5c29a34SFrançois Tigeot int ret; 316b5c29a34SFrançois Tigeot 317b5c29a34SFrançois Tigeot /* 318b5c29a34SFrançois Tigeot * Ensure that any following seqno writes only happen when the render 319b5c29a34SFrançois Tigeot * cache is indeed flushed. 320b5c29a34SFrançois Tigeot * 321b5c29a34SFrançois Tigeot * Workaround: 4th PIPE_CONTROL command (except the ones with only 322b5c29a34SFrançois Tigeot * read-cache invalidate bits set) must have the CS_STALL bit set. We 323b5c29a34SFrançois Tigeot * don't try to be clever and just set it unconditionally. 324b5c29a34SFrançois Tigeot */ 325b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_CS_STALL; 326b5c29a34SFrançois Tigeot 327b5c29a34SFrançois Tigeot /* Just flush everything. Experiments have shown that reducing the 328b5c29a34SFrançois Tigeot * number of bits based on the write domains has little performance 329b5c29a34SFrançois Tigeot * impact. 330b5c29a34SFrançois Tigeot */ 331b5c29a34SFrançois Tigeot if (flush_domains) { 332b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH; 333b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_DEPTH_CACHE_FLUSH; 334aee94f86SFrançois Tigeot flags |= PIPE_CONTROL_DC_FLUSH_ENABLE; 335b49c8cf9SFrançois Tigeot flags |= PIPE_CONTROL_FLUSH_ENABLE; 336b5c29a34SFrançois Tigeot } 337b5c29a34SFrançois Tigeot if (invalidate_domains) { 338b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_TLB_INVALIDATE; 339b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE; 340b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE; 341b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_VF_CACHE_INVALIDATE; 342b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_CONST_CACHE_INVALIDATE; 343b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_STATE_CACHE_INVALIDATE; 3442c9916cdSFrançois Tigeot flags |= PIPE_CONTROL_MEDIA_STATE_CLEAR; 345b5c29a34SFrançois Tigeot /* 346b5c29a34SFrançois Tigeot * TLB invalidate requires a post-sync write. 347b5c29a34SFrançois Tigeot */ 348b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_QW_WRITE; 349a2fdbec6SFrançois Tigeot flags |= PIPE_CONTROL_GLOBAL_GTT_IVB; 350b5c29a34SFrançois Tigeot 3510dbf0ea8SMatthew Dillon flags |= PIPE_CONTROL_STALL_AT_SCOREBOARD; 3520dbf0ea8SMatthew Dillon 353b5c29a34SFrançois Tigeot /* Workaround: we must issue a pipe_control with CS-stall bit 354b5c29a34SFrançois Tigeot * set before a pipe_control command that has the state cache 355b5c29a34SFrançois Tigeot * invalidate bit set. */ 356a05eeebfSFrançois Tigeot gen7_render_ring_cs_stall_wa(req); 357b5c29a34SFrançois Tigeot } 358b5c29a34SFrançois Tigeot 359a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 4); 360b5c29a34SFrançois Tigeot if (ret) 361b5c29a34SFrançois Tigeot return ret; 362b5c29a34SFrançois Tigeot 363b5c29a34SFrançois Tigeot intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(4)); 364b5c29a34SFrançois Tigeot intel_ring_emit(ring, flags); 365a2fdbec6SFrançois Tigeot intel_ring_emit(ring, scratch_addr); 366b5c29a34SFrançois Tigeot intel_ring_emit(ring, 0); 367e3adcf8fSFrançois Tigeot intel_ring_advance(ring); 368e3adcf8fSFrançois Tigeot 369e3adcf8fSFrançois Tigeot return 0; 370e3adcf8fSFrançois Tigeot } 371e3adcf8fSFrançois Tigeot 3729edbd4a0SFrançois Tigeot static int 373a05eeebfSFrançois Tigeot gen8_emit_pipe_control(struct drm_i915_gem_request *req, 37424edb884SFrançois Tigeot u32 flags, u32 scratch_addr) 37524edb884SFrançois Tigeot { 376a05eeebfSFrançois Tigeot struct intel_engine_cs *ring = req->ring; 37724edb884SFrançois Tigeot int ret; 37824edb884SFrançois Tigeot 379a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 6); 38024edb884SFrançois Tigeot if (ret) 38124edb884SFrançois Tigeot return ret; 38224edb884SFrançois Tigeot 38324edb884SFrançois Tigeot intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(6)); 38424edb884SFrançois Tigeot intel_ring_emit(ring, flags); 38524edb884SFrançois Tigeot intel_ring_emit(ring, scratch_addr); 38624edb884SFrançois Tigeot intel_ring_emit(ring, 0); 38724edb884SFrançois Tigeot intel_ring_emit(ring, 0); 38824edb884SFrançois Tigeot intel_ring_emit(ring, 0); 38924edb884SFrançois Tigeot intel_ring_advance(ring); 39024edb884SFrançois Tigeot 39124edb884SFrançois Tigeot return 0; 39224edb884SFrançois Tigeot } 39324edb884SFrançois Tigeot 39424edb884SFrançois Tigeot static int 395a05eeebfSFrançois Tigeot gen8_render_ring_flush(struct drm_i915_gem_request *req, 3969edbd4a0SFrançois Tigeot u32 invalidate_domains, u32 flush_domains) 3979edbd4a0SFrançois Tigeot { 3989edbd4a0SFrançois Tigeot u32 flags = 0; 399a05eeebfSFrançois Tigeot u32 scratch_addr = req->ring->scratch.gtt_offset + 2 * CACHELINE_BYTES; 4009edbd4a0SFrançois Tigeot int ret; 4019edbd4a0SFrançois Tigeot 4029edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_CS_STALL; 4039edbd4a0SFrançois Tigeot 4049edbd4a0SFrançois Tigeot if (flush_domains) { 4059edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH; 4069edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_DEPTH_CACHE_FLUSH; 407aee94f86SFrançois Tigeot flags |= PIPE_CONTROL_DC_FLUSH_ENABLE; 408b49c8cf9SFrançois Tigeot flags |= PIPE_CONTROL_FLUSH_ENABLE; 4099edbd4a0SFrançois Tigeot } 4109edbd4a0SFrançois Tigeot if (invalidate_domains) { 4119edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_TLB_INVALIDATE; 4129edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE; 4139edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE; 4149edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_VF_CACHE_INVALIDATE; 4159edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_CONST_CACHE_INVALIDATE; 4169edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_STATE_CACHE_INVALIDATE; 4179edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_QW_WRITE; 4189edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_GLOBAL_GTT_IVB; 4199edbd4a0SFrançois Tigeot 42024edb884SFrançois Tigeot /* WaCsStallBeforeStateCacheInvalidate:bdw,chv */ 421a05eeebfSFrançois Tigeot ret = gen8_emit_pipe_control(req, 42224edb884SFrançois Tigeot PIPE_CONTROL_CS_STALL | 42324edb884SFrançois Tigeot PIPE_CONTROL_STALL_AT_SCOREBOARD, 42424edb884SFrançois Tigeot 0); 4259edbd4a0SFrançois Tigeot if (ret) 4269edbd4a0SFrançois Tigeot return ret; 42724edb884SFrançois Tigeot } 4289edbd4a0SFrançois Tigeot 429a05eeebfSFrançois Tigeot return gen8_emit_pipe_control(req, flags, scratch_addr); 4309edbd4a0SFrançois Tigeot } 4319edbd4a0SFrançois Tigeot 432ba55f2f5SFrançois Tigeot static void ring_write_tail(struct intel_engine_cs *ring, 433b5c29a34SFrançois Tigeot u32 value) 434e3adcf8fSFrançois Tigeot { 435ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = ring->dev->dev_private; 436e3adcf8fSFrançois Tigeot I915_WRITE_TAIL(ring, value); 437e3adcf8fSFrançois Tigeot } 438e3adcf8fSFrançois Tigeot 439ba55f2f5SFrançois Tigeot u64 intel_ring_get_active_head(struct intel_engine_cs *ring) 440e3adcf8fSFrançois Tigeot { 441ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = ring->dev->dev_private; 442ba55f2f5SFrançois Tigeot u64 acthd; 443e3adcf8fSFrançois Tigeot 444ba55f2f5SFrançois Tigeot if (INTEL_INFO(ring->dev)->gen >= 8) 445ba55f2f5SFrançois Tigeot acthd = I915_READ64_2x32(RING_ACTHD(ring->mmio_base), 446ba55f2f5SFrançois Tigeot RING_ACTHD_UDW(ring->mmio_base)); 447ba55f2f5SFrançois Tigeot else if (INTEL_INFO(ring->dev)->gen >= 4) 448ba55f2f5SFrançois Tigeot acthd = I915_READ(RING_ACTHD(ring->mmio_base)); 449ba55f2f5SFrançois Tigeot else 450ba55f2f5SFrançois Tigeot acthd = I915_READ(ACTHD); 451ba55f2f5SFrançois Tigeot 452ba55f2f5SFrançois Tigeot return acthd; 453e3adcf8fSFrançois Tigeot } 454e3adcf8fSFrançois Tigeot 455ba55f2f5SFrançois Tigeot static void ring_setup_phys_status_page(struct intel_engine_cs *ring) 4565d0b1887SFrançois Tigeot { 4575d0b1887SFrançois Tigeot struct drm_i915_private *dev_priv = ring->dev->dev_private; 4585d0b1887SFrançois Tigeot u32 addr; 4595d0b1887SFrançois Tigeot 4605d0b1887SFrançois Tigeot addr = dev_priv->status_page_dmah->busaddr; 4615d0b1887SFrançois Tigeot if (INTEL_INFO(ring->dev)->gen >= 4) 4625d0b1887SFrançois Tigeot addr |= (dev_priv->status_page_dmah->busaddr >> 28) & 0xf0; 4635d0b1887SFrançois Tigeot I915_WRITE(HWS_PGA, addr); 4645d0b1887SFrançois Tigeot } 4655d0b1887SFrançois Tigeot 466477eb7f9SFrançois Tigeot static void intel_ring_setup_status_page(struct intel_engine_cs *ring) 467477eb7f9SFrançois Tigeot { 468477eb7f9SFrançois Tigeot struct drm_device *dev = ring->dev; 469477eb7f9SFrançois Tigeot struct drm_i915_private *dev_priv = ring->dev->dev_private; 470aee94f86SFrançois Tigeot i915_reg_t mmio; 471477eb7f9SFrançois Tigeot 472477eb7f9SFrançois Tigeot /* The ring status page addresses are no longer next to the rest of 473477eb7f9SFrançois Tigeot * the ring registers as of gen7. 474477eb7f9SFrançois Tigeot */ 475477eb7f9SFrançois Tigeot if (IS_GEN7(dev)) { 476477eb7f9SFrançois Tigeot switch (ring->id) { 477477eb7f9SFrançois Tigeot case RCS: 478477eb7f9SFrançois Tigeot mmio = RENDER_HWS_PGA_GEN7; 479477eb7f9SFrançois Tigeot break; 480477eb7f9SFrançois Tigeot case BCS: 481477eb7f9SFrançois Tigeot mmio = BLT_HWS_PGA_GEN7; 482477eb7f9SFrançois Tigeot break; 483477eb7f9SFrançois Tigeot /* 484477eb7f9SFrançois Tigeot * VCS2 actually doesn't exist on Gen7. Only shut up 485477eb7f9SFrançois Tigeot * gcc switch check warning 486477eb7f9SFrançois Tigeot */ 487477eb7f9SFrançois Tigeot case VCS2: 488477eb7f9SFrançois Tigeot case VCS: 489477eb7f9SFrançois Tigeot mmio = BSD_HWS_PGA_GEN7; 490477eb7f9SFrançois Tigeot break; 491477eb7f9SFrançois Tigeot case VECS: 492477eb7f9SFrançois Tigeot mmio = VEBOX_HWS_PGA_GEN7; 493477eb7f9SFrançois Tigeot break; 494477eb7f9SFrançois Tigeot } 495477eb7f9SFrançois Tigeot } else if (IS_GEN6(ring->dev)) { 496477eb7f9SFrançois Tigeot mmio = RING_HWS_PGA_GEN6(ring->mmio_base); 497477eb7f9SFrançois Tigeot } else { 498477eb7f9SFrançois Tigeot /* XXX: gen8 returns to sanity */ 499477eb7f9SFrançois Tigeot mmio = RING_HWS_PGA(ring->mmio_base); 500477eb7f9SFrançois Tigeot } 501477eb7f9SFrançois Tigeot 502477eb7f9SFrançois Tigeot I915_WRITE(mmio, (u32)ring->status_page.gfx_addr); 503477eb7f9SFrançois Tigeot POSTING_READ(mmio); 504477eb7f9SFrançois Tigeot 505477eb7f9SFrançois Tigeot /* 506477eb7f9SFrançois Tigeot * Flush the TLB for this page 507477eb7f9SFrançois Tigeot * 508477eb7f9SFrançois Tigeot * FIXME: These two bits have disappeared on gen8, so a question 509477eb7f9SFrançois Tigeot * arises: do we still need this and if so how should we go about 510477eb7f9SFrançois Tigeot * invalidating the TLB? 511477eb7f9SFrançois Tigeot */ 512477eb7f9SFrançois Tigeot if (INTEL_INFO(dev)->gen >= 6 && INTEL_INFO(dev)->gen < 8) { 513aee94f86SFrançois Tigeot i915_reg_t reg = RING_INSTPM(ring->mmio_base); 514477eb7f9SFrançois Tigeot 515477eb7f9SFrançois Tigeot /* ring should be idle before issuing a sync flush*/ 516477eb7f9SFrançois Tigeot WARN_ON((I915_READ_MODE(ring) & MODE_IDLE) == 0); 517477eb7f9SFrançois Tigeot 518477eb7f9SFrançois Tigeot I915_WRITE(reg, 519477eb7f9SFrançois Tigeot _MASKED_BIT_ENABLE(INSTPM_TLB_INVALIDATE | 520477eb7f9SFrançois Tigeot INSTPM_SYNC_FLUSH)); 521477eb7f9SFrançois Tigeot if (wait_for((I915_READ(reg) & INSTPM_SYNC_FLUSH) == 0, 522477eb7f9SFrançois Tigeot 1000)) 523477eb7f9SFrançois Tigeot DRM_ERROR("%s: wait for SyncFlush to complete for TLB invalidation timed out\n", 524477eb7f9SFrançois Tigeot ring->name); 525477eb7f9SFrançois Tigeot } 526477eb7f9SFrançois Tigeot } 527477eb7f9SFrançois Tigeot 528ba55f2f5SFrançois Tigeot static bool stop_ring(struct intel_engine_cs *ring) 529e3adcf8fSFrançois Tigeot { 530ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = to_i915(ring->dev); 531e3adcf8fSFrançois Tigeot 532ba55f2f5SFrançois Tigeot if (!IS_GEN2(ring->dev)) { 533ba55f2f5SFrançois Tigeot I915_WRITE_MODE(ring, _MASKED_BIT_ENABLE(STOP_RING)); 5341b13d190SFrançois Tigeot if (wait_for((I915_READ_MODE(ring) & MODE_IDLE) != 0, 1000)) { 535ba55f2f5SFrançois Tigeot DRM_ERROR("%s : timed out trying to stop ring\n", ring->name); 5361b13d190SFrançois Tigeot /* Sometimes we observe that the idle flag is not 5371b13d190SFrançois Tigeot * set even though the ring is empty. So double 5381b13d190SFrançois Tigeot * check before giving up. 5391b13d190SFrançois Tigeot */ 5401b13d190SFrançois Tigeot if (I915_READ_HEAD(ring) != I915_READ_TAIL(ring)) 541ba55f2f5SFrançois Tigeot return false; 542ba55f2f5SFrançois Tigeot } 543ba55f2f5SFrançois Tigeot } 544686a02f1SFrançois Tigeot 545e3adcf8fSFrançois Tigeot I915_WRITE_CTL(ring, 0); 546e3adcf8fSFrançois Tigeot I915_WRITE_HEAD(ring, 0); 547e3adcf8fSFrançois Tigeot ring->write_tail(ring, 0); 548e3adcf8fSFrançois Tigeot 549ba55f2f5SFrançois Tigeot if (!IS_GEN2(ring->dev)) { 550ba55f2f5SFrançois Tigeot (void)I915_READ_CTL(ring); 551ba55f2f5SFrançois Tigeot I915_WRITE_MODE(ring, _MASKED_BIT_DISABLE(STOP_RING)); 552ba55f2f5SFrançois Tigeot } 553e3adcf8fSFrançois Tigeot 554ba55f2f5SFrançois Tigeot return (I915_READ_HEAD(ring) & HEAD_ADDR) == 0; 555ba55f2f5SFrançois Tigeot } 556ba55f2f5SFrançois Tigeot 557ba55f2f5SFrançois Tigeot static int init_ring_common(struct intel_engine_cs *ring) 558ba55f2f5SFrançois Tigeot { 559ba55f2f5SFrançois Tigeot struct drm_device *dev = ring->dev; 560ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 561ba55f2f5SFrançois Tigeot struct intel_ringbuffer *ringbuf = ring->buffer; 562ba55f2f5SFrançois Tigeot struct drm_i915_gem_object *obj = ringbuf->obj; 563ba55f2f5SFrançois Tigeot int ret = 0; 564ba55f2f5SFrançois Tigeot 5652c9916cdSFrançois Tigeot intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL); 566ba55f2f5SFrançois Tigeot 567ba55f2f5SFrançois Tigeot if (!stop_ring(ring)) { 568ba55f2f5SFrançois Tigeot /* G45 ring initialization often fails to reset head to zero */ 569b5c29a34SFrançois Tigeot DRM_DEBUG_KMS("%s head not reset to zero " 570e3adcf8fSFrançois Tigeot "ctl %08x head %08x tail %08x start %08x\n", 571e3adcf8fSFrançois Tigeot ring->name, 572e3adcf8fSFrançois Tigeot I915_READ_CTL(ring), 573e3adcf8fSFrançois Tigeot I915_READ_HEAD(ring), 574e3adcf8fSFrançois Tigeot I915_READ_TAIL(ring), 575e3adcf8fSFrançois Tigeot I915_READ_START(ring)); 576e3adcf8fSFrançois Tigeot 577ba55f2f5SFrançois Tigeot if (!stop_ring(ring)) { 578e3adcf8fSFrançois Tigeot DRM_ERROR("failed to set %s head to zero " 579e3adcf8fSFrançois Tigeot "ctl %08x head %08x tail %08x start %08x\n", 580e3adcf8fSFrançois Tigeot ring->name, 581e3adcf8fSFrançois Tigeot I915_READ_CTL(ring), 582e3adcf8fSFrançois Tigeot I915_READ_HEAD(ring), 583e3adcf8fSFrançois Tigeot I915_READ_TAIL(ring), 584e3adcf8fSFrançois Tigeot I915_READ_START(ring)); 585686a02f1SFrançois Tigeot ret = -EIO; 586686a02f1SFrançois Tigeot goto out; 587e3adcf8fSFrançois Tigeot } 588ba55f2f5SFrançois Tigeot } 589ba55f2f5SFrançois Tigeot 590ba55f2f5SFrançois Tigeot if (I915_NEED_GFX_HWS(dev)) 591ba55f2f5SFrançois Tigeot intel_ring_setup_status_page(ring); 592ba55f2f5SFrançois Tigeot else 593ba55f2f5SFrançois Tigeot ring_setup_phys_status_page(ring); 594ba55f2f5SFrançois Tigeot 5950f370975SMatthew Dillon /* Enforce ordering by reading HEAD register back */ 5960f370975SMatthew Dillon I915_READ_HEAD(ring); 5970f370975SMatthew Dillon 598ba55f2f5SFrançois Tigeot /* Initialize the ring. This must happen _after_ we've cleared the ring 599ba55f2f5SFrançois Tigeot * registers with the above sequence (the readback of the HEAD registers 600ba55f2f5SFrançois Tigeot * also enforces ordering), otherwise the hw might lose the new ring 601ba55f2f5SFrançois Tigeot * register values. */ 602ba55f2f5SFrançois Tigeot I915_WRITE_START(ring, i915_gem_obj_ggtt_offset(obj)); 6031b13d190SFrançois Tigeot 6041b13d190SFrançois Tigeot /* WaClearRingBufHeadRegAtInit:ctg,elk */ 6051b13d190SFrançois Tigeot if (I915_READ_HEAD(ring)) 6061b13d190SFrançois Tigeot DRM_DEBUG("%s initialization failed [head=%08x], fudging\n", 6071b13d190SFrançois Tigeot ring->name, I915_READ_HEAD(ring)); 6081b13d190SFrançois Tigeot I915_WRITE_HEAD(ring, 0); 6091b13d190SFrançois Tigeot (void)I915_READ_HEAD(ring); 6101b13d190SFrançois Tigeot 611ba55f2f5SFrançois Tigeot I915_WRITE_CTL(ring, 612ba55f2f5SFrançois Tigeot ((ringbuf->size - PAGE_SIZE) & RING_NR_PAGES) 613ba55f2f5SFrançois Tigeot | RING_VALID); 614ba55f2f5SFrançois Tigeot 615ba55f2f5SFrançois Tigeot /* If the head is still not zero, the ring is dead */ 616ba55f2f5SFrançois Tigeot if (wait_for((I915_READ_CTL(ring) & RING_VALID) != 0 && 617ba55f2f5SFrançois Tigeot I915_READ_START(ring) == i915_gem_obj_ggtt_offset(obj) && 618ba55f2f5SFrançois Tigeot (I915_READ_HEAD(ring) & HEAD_ADDR) == 0, 50)) { 619ba55f2f5SFrançois Tigeot DRM_ERROR("%s initialization failed " 620ba55f2f5SFrançois Tigeot "ctl %08x (valid? %d) head %08x tail %08x start %08x [expected %08lx]\n", 621ba55f2f5SFrançois Tigeot ring->name, 622ba55f2f5SFrançois Tigeot I915_READ_CTL(ring), I915_READ_CTL(ring) & RING_VALID, 623ba55f2f5SFrançois Tigeot I915_READ_HEAD(ring), I915_READ_TAIL(ring), 624ba55f2f5SFrançois Tigeot I915_READ_START(ring), (unsigned long)i915_gem_obj_ggtt_offset(obj)); 625ba55f2f5SFrançois Tigeot ret = -EIO; 626ba55f2f5SFrançois Tigeot goto out; 627ba55f2f5SFrançois Tigeot } 628e3adcf8fSFrançois Tigeot 6292c9916cdSFrançois Tigeot ringbuf->last_retired_head = -1; 630ba55f2f5SFrançois Tigeot ringbuf->head = I915_READ_HEAD(ring); 631ba55f2f5SFrançois Tigeot ringbuf->tail = I915_READ_TAIL(ring) & TAIL_ADDR; 6322c9916cdSFrançois Tigeot intel_ring_update_space(ringbuf); 633e3adcf8fSFrançois Tigeot 6345d0b1887SFrançois Tigeot memset(&ring->hangcheck, 0, sizeof(ring->hangcheck)); 6355d0b1887SFrançois Tigeot 636686a02f1SFrançois Tigeot out: 6372c9916cdSFrançois Tigeot intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL); 638686a02f1SFrançois Tigeot 639686a02f1SFrançois Tigeot return ret; 640e3adcf8fSFrançois Tigeot } 641e3adcf8fSFrançois Tigeot 6421b13d190SFrançois Tigeot void 6431b13d190SFrançois Tigeot intel_fini_pipe_control(struct intel_engine_cs *ring) 6441b13d190SFrançois Tigeot { 6451b13d190SFrançois Tigeot struct drm_device *dev = ring->dev; 6461b13d190SFrançois Tigeot 6471b13d190SFrançois Tigeot if (ring->scratch.obj == NULL) 6481b13d190SFrançois Tigeot return; 6491b13d190SFrançois Tigeot 6501b13d190SFrançois Tigeot if (INTEL_INFO(dev)->gen >= 5) { 6517ec9f8e5SFrançois Tigeot kunmap(sg_page(ring->scratch.obj->pages->sgl)); 6521b13d190SFrançois Tigeot i915_gem_object_ggtt_unpin(ring->scratch.obj); 6531b13d190SFrançois Tigeot } 6541b13d190SFrançois Tigeot 6551b13d190SFrançois Tigeot drm_gem_object_unreference(&ring->scratch.obj->base); 6561b13d190SFrançois Tigeot ring->scratch.obj = NULL; 6571b13d190SFrançois Tigeot } 6581b13d190SFrançois Tigeot 6591b13d190SFrançois Tigeot int 6601b13d190SFrançois Tigeot intel_init_pipe_control(struct intel_engine_cs *ring) 661e3adcf8fSFrançois Tigeot { 662e3adcf8fSFrançois Tigeot int ret; 663e3adcf8fSFrançois Tigeot 6642c9916cdSFrançois Tigeot WARN_ON(ring->scratch.obj); 665e3adcf8fSFrançois Tigeot 6669edbd4a0SFrançois Tigeot ring->scratch.obj = i915_gem_alloc_object(ring->dev, 4096); 6679edbd4a0SFrançois Tigeot if (ring->scratch.obj == NULL) { 668e3adcf8fSFrançois Tigeot DRM_ERROR("Failed to allocate seqno page\n"); 669e3adcf8fSFrançois Tigeot ret = -ENOMEM; 670e3adcf8fSFrançois Tigeot goto err; 671e3adcf8fSFrançois Tigeot } 672e3adcf8fSFrançois Tigeot 673ba55f2f5SFrançois Tigeot ret = i915_gem_object_set_cache_level(ring->scratch.obj, I915_CACHE_LLC); 674ba55f2f5SFrançois Tigeot if (ret) 675ba55f2f5SFrançois Tigeot goto err_unref; 676e3adcf8fSFrançois Tigeot 677ba55f2f5SFrançois Tigeot ret = i915_gem_obj_ggtt_pin(ring->scratch.obj, 4096, 0); 678e3adcf8fSFrançois Tigeot if (ret) 679e3adcf8fSFrançois Tigeot goto err_unref; 680e3adcf8fSFrançois Tigeot 6819edbd4a0SFrançois Tigeot ring->scratch.gtt_offset = i915_gem_obj_ggtt_offset(ring->scratch.obj); 6827ec9f8e5SFrançois Tigeot ring->scratch.cpu_page = kmap(sg_page(ring->scratch.obj->pages->sgl)); 6839edbd4a0SFrançois Tigeot if (ring->scratch.cpu_page == NULL) { 6845d0b1887SFrançois Tigeot ret = -ENOMEM; 685e3adcf8fSFrançois Tigeot goto err_unpin; 6865d0b1887SFrançois Tigeot } 687a2fdbec6SFrançois Tigeot 688a2fdbec6SFrançois Tigeot DRM_DEBUG_DRIVER("%s pipe control offset: 0x%08x\n", 6899edbd4a0SFrançois Tigeot ring->name, ring->scratch.gtt_offset); 690e3adcf8fSFrançois Tigeot return 0; 691e3adcf8fSFrançois Tigeot 692e3adcf8fSFrançois Tigeot err_unpin: 693ba55f2f5SFrançois Tigeot i915_gem_object_ggtt_unpin(ring->scratch.obj); 694e3adcf8fSFrançois Tigeot err_unref: 6959edbd4a0SFrançois Tigeot drm_gem_object_unreference(&ring->scratch.obj->base); 696e3adcf8fSFrançois Tigeot err: 697e3adcf8fSFrançois Tigeot return ret; 698e3adcf8fSFrançois Tigeot } 699e3adcf8fSFrançois Tigeot 700a05eeebfSFrançois Tigeot static int intel_ring_workarounds_emit(struct drm_i915_gem_request *req) 7011b13d190SFrançois Tigeot { 7022c9916cdSFrançois Tigeot int ret, i; 703a05eeebfSFrançois Tigeot struct intel_engine_cs *ring = req->ring; 7041b13d190SFrançois Tigeot struct drm_device *dev = ring->dev; 7051b13d190SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 7062c9916cdSFrançois Tigeot struct i915_workarounds *w = &dev_priv->workarounds; 7071b13d190SFrançois Tigeot 708352ff8bdSFrançois Tigeot if (w->count == 0) 7092c9916cdSFrançois Tigeot return 0; 7101b13d190SFrançois Tigeot 7112c9916cdSFrançois Tigeot ring->gpu_caches_dirty = true; 712a05eeebfSFrançois Tigeot ret = intel_ring_flush_all_caches(req); 7131b13d190SFrançois Tigeot if (ret) 7141b13d190SFrançois Tigeot return ret; 7151b13d190SFrançois Tigeot 716a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, (w->count * 2 + 2)); 7172c9916cdSFrançois Tigeot if (ret) 7182c9916cdSFrançois Tigeot return ret; 7192c9916cdSFrançois Tigeot 7202c9916cdSFrançois Tigeot intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(w->count)); 7212c9916cdSFrançois Tigeot for (i = 0; i < w->count; i++) { 722aee94f86SFrançois Tigeot intel_ring_emit_reg(ring, w->reg[i].addr); 7232c9916cdSFrançois Tigeot intel_ring_emit(ring, w->reg[i].value); 7242c9916cdSFrançois Tigeot } 7252c9916cdSFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 7262c9916cdSFrançois Tigeot 7272c9916cdSFrançois Tigeot intel_ring_advance(ring); 7282c9916cdSFrançois Tigeot 7292c9916cdSFrançois Tigeot ring->gpu_caches_dirty = true; 730a05eeebfSFrançois Tigeot ret = intel_ring_flush_all_caches(req); 7312c9916cdSFrançois Tigeot if (ret) 7322c9916cdSFrançois Tigeot return ret; 7332c9916cdSFrançois Tigeot 7342c9916cdSFrançois Tigeot DRM_DEBUG_DRIVER("Number of Workarounds emitted: %d\n", w->count); 7352c9916cdSFrançois Tigeot 7362c9916cdSFrançois Tigeot return 0; 7372c9916cdSFrançois Tigeot } 7382c9916cdSFrançois Tigeot 739a05eeebfSFrançois Tigeot static int intel_rcs_ctx_init(struct drm_i915_gem_request *req) 7402c9916cdSFrançois Tigeot { 7412c9916cdSFrançois Tigeot int ret; 7422c9916cdSFrançois Tigeot 743a05eeebfSFrançois Tigeot ret = intel_ring_workarounds_emit(req); 7442c9916cdSFrançois Tigeot if (ret != 0) 7452c9916cdSFrançois Tigeot return ret; 7462c9916cdSFrançois Tigeot 747a05eeebfSFrançois Tigeot ret = i915_gem_render_state_init(req); 7482c9916cdSFrançois Tigeot if (ret) 7492c9916cdSFrançois Tigeot return ret; 750*c0e85e96SFrançois Tigeot 751*c0e85e96SFrançois Tigeot return 0; 7522c9916cdSFrançois Tigeot } 7532c9916cdSFrançois Tigeot 7542c9916cdSFrançois Tigeot static int wa_add(struct drm_i915_private *dev_priv, 755aee94f86SFrançois Tigeot i915_reg_t addr, 756aee94f86SFrançois Tigeot const u32 mask, const u32 val) 7572c9916cdSFrançois Tigeot { 7582c9916cdSFrançois Tigeot const u32 idx = dev_priv->workarounds.count; 7592c9916cdSFrançois Tigeot 7602c9916cdSFrançois Tigeot if (WARN_ON(idx >= I915_MAX_WA_REGS)) 7612c9916cdSFrançois Tigeot return -ENOSPC; 7622c9916cdSFrançois Tigeot 7632c9916cdSFrançois Tigeot dev_priv->workarounds.reg[idx].addr = addr; 7642c9916cdSFrançois Tigeot dev_priv->workarounds.reg[idx].value = val; 7652c9916cdSFrançois Tigeot dev_priv->workarounds.reg[idx].mask = mask; 7662c9916cdSFrançois Tigeot 7672c9916cdSFrançois Tigeot dev_priv->workarounds.count++; 7682c9916cdSFrançois Tigeot 7692c9916cdSFrançois Tigeot return 0; 7702c9916cdSFrançois Tigeot } 7712c9916cdSFrançois Tigeot 772a05eeebfSFrançois Tigeot #define WA_REG(addr, mask, val) do { \ 7732c9916cdSFrançois Tigeot const int r = wa_add(dev_priv, (addr), (mask), (val)); \ 7742c9916cdSFrançois Tigeot if (r) \ 7752c9916cdSFrançois Tigeot return r; \ 776a05eeebfSFrançois Tigeot } while (0) 7772c9916cdSFrançois Tigeot 7782c9916cdSFrançois Tigeot #define WA_SET_BIT_MASKED(addr, mask) \ 7792c9916cdSFrançois Tigeot WA_REG(addr, (mask), _MASKED_BIT_ENABLE(mask)) 7802c9916cdSFrançois Tigeot 7812c9916cdSFrançois Tigeot #define WA_CLR_BIT_MASKED(addr, mask) \ 7822c9916cdSFrançois Tigeot WA_REG(addr, (mask), _MASKED_BIT_DISABLE(mask)) 7832c9916cdSFrançois Tigeot 7842c9916cdSFrançois Tigeot #define WA_SET_FIELD_MASKED(addr, mask, value) \ 7852c9916cdSFrançois Tigeot WA_REG(addr, mask, _MASKED_FIELD(mask, value)) 7862c9916cdSFrançois Tigeot 7872c9916cdSFrançois Tigeot #define WA_SET_BIT(addr, mask) WA_REG(addr, mask, I915_READ(addr) | (mask)) 7882c9916cdSFrançois Tigeot #define WA_CLR_BIT(addr, mask) WA_REG(addr, mask, I915_READ(addr) & ~(mask)) 7892c9916cdSFrançois Tigeot 7902c9916cdSFrançois Tigeot #define WA_WRITE(addr, val) WA_REG(addr, 0xffffffff, val) 7912c9916cdSFrançois Tigeot 792*c0e85e96SFrançois Tigeot static int wa_ring_whitelist_reg(struct intel_engine_cs *ring, i915_reg_t reg) 793*c0e85e96SFrançois Tigeot { 794*c0e85e96SFrançois Tigeot struct drm_i915_private *dev_priv = ring->dev->dev_private; 795*c0e85e96SFrançois Tigeot struct i915_workarounds *wa = &dev_priv->workarounds; 796*c0e85e96SFrançois Tigeot const uint32_t index = wa->hw_whitelist_count[ring->id]; 797*c0e85e96SFrançois Tigeot 798*c0e85e96SFrançois Tigeot if (WARN_ON(index >= RING_MAX_NONPRIV_SLOTS)) 799*c0e85e96SFrançois Tigeot return -EINVAL; 800*c0e85e96SFrançois Tigeot 801*c0e85e96SFrançois Tigeot WA_WRITE(RING_FORCE_TO_NONPRIV(ring->mmio_base, index), 802*c0e85e96SFrançois Tigeot i915_mmio_reg_offset(reg)); 803*c0e85e96SFrançois Tigeot wa->hw_whitelist_count[ring->id]++; 804*c0e85e96SFrançois Tigeot 805*c0e85e96SFrançois Tigeot return 0; 806*c0e85e96SFrançois Tigeot } 807*c0e85e96SFrançois Tigeot 808352ff8bdSFrançois Tigeot static int gen8_init_workarounds(struct intel_engine_cs *ring) 8092c9916cdSFrançois Tigeot { 8102c9916cdSFrançois Tigeot struct drm_device *dev = ring->dev; 8112c9916cdSFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 8122c9916cdSFrançois Tigeot 813a05eeebfSFrançois Tigeot WA_SET_BIT_MASKED(INSTPM, INSTPM_FORCE_ORDERING); 814a05eeebfSFrançois Tigeot 815352ff8bdSFrançois Tigeot /* WaDisableAsyncFlipPerfMode:bdw,chv */ 816a05eeebfSFrançois Tigeot WA_SET_BIT_MASKED(MI_MODE, ASYNC_FLIP_PERF_DISABLE); 817a05eeebfSFrançois Tigeot 818352ff8bdSFrançois Tigeot /* WaDisablePartialInstShootdown:bdw,chv */ 8192c9916cdSFrançois Tigeot WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN, 820352ff8bdSFrançois Tigeot PARTIAL_INSTRUCTION_SHOOTDOWN_DISABLE); 8211b13d190SFrançois Tigeot 8221b13d190SFrançois Tigeot /* Use Force Non-Coherent whenever executing a 3D context. This is a 8231b13d190SFrançois Tigeot * workaround for for a possible hang in the unlikely event a TLB 8241b13d190SFrançois Tigeot * invalidation occurs during a PSD flush. 8251b13d190SFrançois Tigeot */ 826352ff8bdSFrançois Tigeot /* WaForceEnableNonCoherent:bdw,chv */ 827352ff8bdSFrançois Tigeot /* WaHdcDisableFetchWhenMasked:bdw,chv */ 8282c9916cdSFrançois Tigeot WA_SET_BIT_MASKED(HDC_CHICKEN0, 8292c9916cdSFrançois Tigeot HDC_DONOT_FETCH_MEM_WHEN_MASKED | 830352ff8bdSFrançois Tigeot HDC_FORCE_NON_COHERENT); 8312c9916cdSFrançois Tigeot 8322c9916cdSFrançois Tigeot /* From the Haswell PRM, Command Reference: Registers, CACHE_MODE_0: 8332c9916cdSFrançois Tigeot * "The Hierarchical Z RAW Stall Optimization allows non-overlapping 8342c9916cdSFrançois Tigeot * polygons in the same 8x4 pixel/sample area to be processed without 8352c9916cdSFrançois Tigeot * stalling waiting for the earlier ones to write to Hierarchical Z 8362c9916cdSFrançois Tigeot * buffer." 8372c9916cdSFrançois Tigeot * 838352ff8bdSFrançois Tigeot * This optimization is off by default for BDW and CHV; turn it on. 8392c9916cdSFrançois Tigeot */ 8402c9916cdSFrançois Tigeot WA_CLR_BIT_MASKED(CACHE_MODE_0_GEN7, HIZ_RAW_STALL_OPT_DISABLE); 8411b13d190SFrançois Tigeot 842352ff8bdSFrançois Tigeot /* Wa4x4STCOptimizationDisable:bdw,chv */ 843352ff8bdSFrançois Tigeot WA_SET_BIT_MASKED(CACHE_MODE_1, GEN8_4x4_STC_OPTIMIZATION_DISABLE); 8441b13d190SFrançois Tigeot 8451b13d190SFrançois Tigeot /* 8461b13d190SFrançois Tigeot * BSpec recommends 8x4 when MSAA is used, 8471b13d190SFrançois Tigeot * however in practice 16x4 seems fastest. 8481b13d190SFrançois Tigeot * 8491b13d190SFrançois Tigeot * Note that PS/WM thread counts depend on the WIZ hashing 8501b13d190SFrançois Tigeot * disable bit, which we don't touch here, but it's good 8511b13d190SFrançois Tigeot * to keep in mind (see 3DSTATE_PS and 3DSTATE_WM). 8521b13d190SFrançois Tigeot */ 8532c9916cdSFrançois Tigeot WA_SET_FIELD_MASKED(GEN7_GT_MODE, 8542c9916cdSFrançois Tigeot GEN6_WIZ_HASHING_MASK, 8552c9916cdSFrançois Tigeot GEN6_WIZ_HASHING_16x4); 8561b13d190SFrançois Tigeot 8571b13d190SFrançois Tigeot return 0; 8581b13d190SFrançois Tigeot } 8591b13d190SFrançois Tigeot 860352ff8bdSFrançois Tigeot static int bdw_init_workarounds(struct intel_engine_cs *ring) 8611b13d190SFrançois Tigeot { 862352ff8bdSFrançois Tigeot int ret; 8631b13d190SFrançois Tigeot struct drm_device *dev = ring->dev; 8641b13d190SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 8651b13d190SFrançois Tigeot 866352ff8bdSFrançois Tigeot ret = gen8_init_workarounds(ring); 867352ff8bdSFrançois Tigeot if (ret) 868352ff8bdSFrançois Tigeot return ret; 869a05eeebfSFrançois Tigeot 870352ff8bdSFrançois Tigeot /* WaDisableThreadStallDopClockGating:bdw (pre-production) */ 871352ff8bdSFrançois Tigeot WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN, STALL_DOP_GATING_DISABLE); 872a05eeebfSFrançois Tigeot 873352ff8bdSFrançois Tigeot /* WaDisableDopClockGating:bdw */ 874352ff8bdSFrançois Tigeot WA_SET_BIT_MASKED(GEN7_ROW_CHICKEN2, 875352ff8bdSFrançois Tigeot DOP_CLOCK_GATING_DISABLE); 8761b13d190SFrançois Tigeot 877352ff8bdSFrançois Tigeot WA_SET_BIT_MASKED(HALF_SLICE_CHICKEN3, 878352ff8bdSFrançois Tigeot GEN8_SAMPLER_POWER_BYPASS_DIS); 879352ff8bdSFrançois Tigeot 8802c9916cdSFrançois Tigeot WA_SET_BIT_MASKED(HDC_CHICKEN0, 881352ff8bdSFrançois Tigeot /* WaForceContextSaveRestoreNonCoherent:bdw */ 882352ff8bdSFrançois Tigeot HDC_FORCE_CONTEXT_SAVE_RESTORE_NON_COHERENT | 883352ff8bdSFrançois Tigeot /* WaDisableFenceDestinationToSLM:bdw (pre-prod) */ 884352ff8bdSFrançois Tigeot (IS_BDW_GT3(dev) ? HDC_FENCE_DEST_SLM_DISABLE : 0)); 8851b13d190SFrançois Tigeot 886352ff8bdSFrançois Tigeot return 0; 887352ff8bdSFrançois Tigeot } 8881b13d190SFrançois Tigeot 889352ff8bdSFrançois Tigeot static int chv_init_workarounds(struct intel_engine_cs *ring) 890352ff8bdSFrançois Tigeot { 891352ff8bdSFrançois Tigeot int ret; 892352ff8bdSFrançois Tigeot struct drm_device *dev = ring->dev; 893352ff8bdSFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 894352ff8bdSFrançois Tigeot 895352ff8bdSFrançois Tigeot ret = gen8_init_workarounds(ring); 896352ff8bdSFrançois Tigeot if (ret) 897352ff8bdSFrançois Tigeot return ret; 898352ff8bdSFrançois Tigeot 899352ff8bdSFrançois Tigeot /* WaDisableThreadStallDopClockGating:chv */ 900352ff8bdSFrançois Tigeot WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN, STALL_DOP_GATING_DISABLE); 9012c9916cdSFrançois Tigeot 9022c9916cdSFrançois Tigeot /* Improve HiZ throughput on CHV. */ 9032c9916cdSFrançois Tigeot WA_SET_BIT_MASKED(HIZ_CHICKEN, CHV_HZ_8X8_MODE_IN_1X); 9042c9916cdSFrançois Tigeot 9052c9916cdSFrançois Tigeot return 0; 9062c9916cdSFrançois Tigeot } 9072c9916cdSFrançois Tigeot 908477eb7f9SFrançois Tigeot static int gen9_init_workarounds(struct intel_engine_cs *ring) 909477eb7f9SFrançois Tigeot { 910477eb7f9SFrançois Tigeot struct drm_device *dev = ring->dev; 911477eb7f9SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 91219c468b4SFrançois Tigeot uint32_t tmp; 913*c0e85e96SFrançois Tigeot int ret; 914477eb7f9SFrançois Tigeot 915352ff8bdSFrançois Tigeot /* WaEnableLbsSlaRetryTimerDecrement:skl */ 916352ff8bdSFrançois Tigeot I915_WRITE(BDW_SCRATCH1, I915_READ(BDW_SCRATCH1) | 917352ff8bdSFrançois Tigeot GEN9_LBS_SLA_RETRY_TIMER_DECREMENT_ENABLE); 918352ff8bdSFrançois Tigeot 919352ff8bdSFrançois Tigeot /* WaDisableKillLogic:bxt,skl */ 920352ff8bdSFrançois Tigeot I915_WRITE(GAM_ECOCHK, I915_READ(GAM_ECOCHK) | 921352ff8bdSFrançois Tigeot ECOCHK_DIS_TLB); 922352ff8bdSFrançois Tigeot 92319c468b4SFrançois Tigeot /* WaDisablePartialInstShootdown:skl,bxt */ 924477eb7f9SFrançois Tigeot WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN, 925477eb7f9SFrançois Tigeot PARTIAL_INSTRUCTION_SHOOTDOWN_DISABLE); 926477eb7f9SFrançois Tigeot 92719c468b4SFrançois Tigeot /* Syncing dependencies between camera and graphics:skl,bxt */ 928477eb7f9SFrançois Tigeot WA_SET_BIT_MASKED(HALF_SLICE_CHICKEN3, 929477eb7f9SFrançois Tigeot GEN9_DISABLE_OCL_OOB_SUPPRESS_LOGIC); 930477eb7f9SFrançois Tigeot 93119c468b4SFrançois Tigeot /* WaDisableDgMirrorFixInHalfSliceChicken5:skl,bxt */ 932aee94f86SFrançois Tigeot if (IS_SKL_REVID(dev, 0, SKL_REVID_B0) || 933aee94f86SFrançois Tigeot IS_BXT_REVID(dev, 0, BXT_REVID_A1)) 934477eb7f9SFrançois Tigeot WA_CLR_BIT_MASKED(GEN9_HALF_SLICE_CHICKEN5, 935477eb7f9SFrançois Tigeot GEN9_DG_MIRROR_FIX_ENABLE); 936477eb7f9SFrançois Tigeot 93719c468b4SFrançois Tigeot /* WaSetDisablePixMaskCammingAndRhwoInCommonSliceChicken:skl,bxt */ 938aee94f86SFrançois Tigeot if (IS_SKL_REVID(dev, 0, SKL_REVID_B0) || 939aee94f86SFrançois Tigeot IS_BXT_REVID(dev, 0, BXT_REVID_A1)) { 940477eb7f9SFrançois Tigeot WA_SET_BIT_MASKED(GEN7_COMMON_SLICE_CHICKEN1, 941477eb7f9SFrançois Tigeot GEN9_RHWO_OPTIMIZATION_DISABLE); 942a05eeebfSFrançois Tigeot /* 943a05eeebfSFrançois Tigeot * WA also requires GEN9_SLICE_COMMON_ECO_CHICKEN0[14:14] to be set 944a05eeebfSFrançois Tigeot * but we do that in per ctx batchbuffer as there is an issue 945a05eeebfSFrançois Tigeot * with this register not getting restored on ctx restore 946a05eeebfSFrançois Tigeot */ 947477eb7f9SFrançois Tigeot } 948477eb7f9SFrançois Tigeot 94919c468b4SFrançois Tigeot /* WaEnableYV12BugFixInHalfSliceChicken7:skl,bxt */ 950aee94f86SFrançois Tigeot if (IS_SKL_REVID(dev, SKL_REVID_C0, REVID_FOREVER) || IS_BROXTON(dev)) 951477eb7f9SFrançois Tigeot WA_SET_BIT_MASKED(GEN9_HALF_SLICE_CHICKEN7, 952477eb7f9SFrançois Tigeot GEN9_ENABLE_YV12_BUGFIX); 953477eb7f9SFrançois Tigeot 95419c468b4SFrançois Tigeot /* Wa4x4STCOptimizationDisable:skl,bxt */ 95519c468b4SFrançois Tigeot /* WaDisablePartialResolveInVc:skl,bxt */ 956352ff8bdSFrançois Tigeot WA_SET_BIT_MASKED(CACHE_MODE_1, (GEN8_4x4_STC_OPTIMIZATION_DISABLE | 957352ff8bdSFrançois Tigeot GEN9_PARTIAL_RESOLVE_IN_VC_DISABLE)); 958477eb7f9SFrançois Tigeot 95919c468b4SFrançois Tigeot /* WaCcsTlbPrefetchDisable:skl,bxt */ 960477eb7f9SFrançois Tigeot WA_CLR_BIT_MASKED(GEN9_HALF_SLICE_CHICKEN5, 961477eb7f9SFrançois Tigeot GEN9_CCS_TLB_PREFETCH_ENABLE); 962477eb7f9SFrançois Tigeot 96319c468b4SFrançois Tigeot /* WaDisableMaskBasedCammingInRCC:skl,bxt */ 964aee94f86SFrançois Tigeot if (IS_SKL_REVID(dev, SKL_REVID_C0, SKL_REVID_C0) || 965aee94f86SFrançois Tigeot IS_BXT_REVID(dev, 0, BXT_REVID_A1)) 96619c468b4SFrançois Tigeot WA_SET_BIT_MASKED(SLICE_ECO_CHICKEN0, 96719c468b4SFrançois Tigeot PIXEL_MASK_CAMMING_DISABLE); 96819c468b4SFrançois Tigeot 96919c468b4SFrançois Tigeot /* WaForceContextSaveRestoreNonCoherent:skl,bxt */ 97019c468b4SFrançois Tigeot tmp = HDC_FORCE_CONTEXT_SAVE_RESTORE_NON_COHERENT; 971*c0e85e96SFrançois Tigeot if (IS_SKL_REVID(dev, SKL_REVID_F0, REVID_FOREVER) || 972aee94f86SFrançois Tigeot IS_BXT_REVID(dev, BXT_REVID_B0, REVID_FOREVER)) 97319c468b4SFrançois Tigeot tmp |= HDC_FORCE_CSR_NON_COHERENT_OVR_DISABLE; 97419c468b4SFrançois Tigeot WA_SET_BIT_MASKED(HDC_CHICKEN0, tmp); 97519c468b4SFrançois Tigeot 976352ff8bdSFrançois Tigeot /* WaDisableSamplerPowerBypassForSOPingPong:skl,bxt */ 977aee94f86SFrançois Tigeot if (IS_SKYLAKE(dev) || IS_BXT_REVID(dev, 0, BXT_REVID_B0)) 978352ff8bdSFrançois Tigeot WA_SET_BIT_MASKED(HALF_SLICE_CHICKEN3, 979352ff8bdSFrançois Tigeot GEN8_SAMPLER_POWER_BYPASS_DIS); 980352ff8bdSFrançois Tigeot 981352ff8bdSFrançois Tigeot /* WaDisableSTUnitPowerOptimization:skl,bxt */ 982352ff8bdSFrançois Tigeot WA_SET_BIT_MASKED(HALF_SLICE_CHICKEN2, GEN8_ST_PO_DISABLE); 983352ff8bdSFrançois Tigeot 984*c0e85e96SFrançois Tigeot /* WaOCLCoherentLineFlush:skl,bxt */ 985*c0e85e96SFrançois Tigeot I915_WRITE(GEN8_L3SQCREG4, (I915_READ(GEN8_L3SQCREG4) | 986*c0e85e96SFrançois Tigeot GEN8_LQSC_FLUSH_COHERENT_LINES)); 987*c0e85e96SFrançois Tigeot 988*c0e85e96SFrançois Tigeot /* WaEnablePreemptionGranularityControlByUMD:skl,bxt */ 989*c0e85e96SFrançois Tigeot ret= wa_ring_whitelist_reg(ring, GEN8_CS_CHICKEN1); 990*c0e85e96SFrançois Tigeot if (ret) 991*c0e85e96SFrançois Tigeot return ret; 992*c0e85e96SFrançois Tigeot 993*c0e85e96SFrançois Tigeot /* WaAllowUMDToModifyHDCChicken1:skl,bxt */ 994*c0e85e96SFrançois Tigeot ret = wa_ring_whitelist_reg(ring, GEN8_HDC_CHICKEN1); 995*c0e85e96SFrançois Tigeot if (ret) 996*c0e85e96SFrançois Tigeot return ret; 997*c0e85e96SFrançois Tigeot 998477eb7f9SFrançois Tigeot return 0; 999477eb7f9SFrançois Tigeot } 1000477eb7f9SFrançois Tigeot 1001477eb7f9SFrançois Tigeot static int skl_tune_iz_hashing(struct intel_engine_cs *ring) 1002477eb7f9SFrançois Tigeot { 1003477eb7f9SFrançois Tigeot struct drm_device *dev = ring->dev; 1004477eb7f9SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 1005477eb7f9SFrançois Tigeot u8 vals[3] = { 0, 0, 0 }; 1006477eb7f9SFrançois Tigeot unsigned int i; 1007477eb7f9SFrançois Tigeot 1008477eb7f9SFrançois Tigeot for (i = 0; i < 3; i++) { 1009477eb7f9SFrançois Tigeot u8 ss; 1010477eb7f9SFrançois Tigeot 1011477eb7f9SFrançois Tigeot /* 1012477eb7f9SFrançois Tigeot * Only consider slices where one, and only one, subslice has 7 1013477eb7f9SFrançois Tigeot * EUs 1014477eb7f9SFrançois Tigeot */ 1015aee94f86SFrançois Tigeot if (!is_power_of_2(dev_priv->info.subslice_7eu[i])) 1016477eb7f9SFrançois Tigeot continue; 1017477eb7f9SFrançois Tigeot 1018477eb7f9SFrançois Tigeot /* 1019477eb7f9SFrançois Tigeot * subslice_7eu[i] != 0 (because of the check above) and 1020477eb7f9SFrançois Tigeot * ss_max == 4 (maximum number of subslices possible per slice) 1021477eb7f9SFrançois Tigeot * 1022477eb7f9SFrançois Tigeot * -> 0 <= ss <= 3; 1023477eb7f9SFrançois Tigeot */ 1024477eb7f9SFrançois Tigeot ss = ffs(dev_priv->info.subslice_7eu[i]) - 1; 1025477eb7f9SFrançois Tigeot vals[i] = 3 - ss; 1026477eb7f9SFrançois Tigeot } 1027477eb7f9SFrançois Tigeot 1028477eb7f9SFrançois Tigeot if (vals[0] == 0 && vals[1] == 0 && vals[2] == 0) 1029477eb7f9SFrançois Tigeot return 0; 1030477eb7f9SFrançois Tigeot 1031477eb7f9SFrançois Tigeot /* Tune IZ hashing. See intel_device_info_runtime_init() */ 1032477eb7f9SFrançois Tigeot WA_SET_FIELD_MASKED(GEN7_GT_MODE, 1033477eb7f9SFrançois Tigeot GEN9_IZ_HASHING_MASK(2) | 1034477eb7f9SFrançois Tigeot GEN9_IZ_HASHING_MASK(1) | 1035477eb7f9SFrançois Tigeot GEN9_IZ_HASHING_MASK(0), 1036477eb7f9SFrançois Tigeot GEN9_IZ_HASHING(2, vals[2]) | 1037477eb7f9SFrançois Tigeot GEN9_IZ_HASHING(1, vals[1]) | 1038477eb7f9SFrançois Tigeot GEN9_IZ_HASHING(0, vals[0])); 1039477eb7f9SFrançois Tigeot 1040477eb7f9SFrançois Tigeot return 0; 1041477eb7f9SFrançois Tigeot } 1042477eb7f9SFrançois Tigeot 1043477eb7f9SFrançois Tigeot static int skl_init_workarounds(struct intel_engine_cs *ring) 1044477eb7f9SFrançois Tigeot { 1045352ff8bdSFrançois Tigeot int ret; 1046477eb7f9SFrançois Tigeot struct drm_device *dev = ring->dev; 1047477eb7f9SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 1048477eb7f9SFrançois Tigeot 1049352ff8bdSFrançois Tigeot ret = gen9_init_workarounds(ring); 1050352ff8bdSFrançois Tigeot if (ret) 1051352ff8bdSFrançois Tigeot return ret; 1052352ff8bdSFrançois Tigeot 1053*c0e85e96SFrançois Tigeot /* 1054*c0e85e96SFrançois Tigeot * Actual WA is to disable percontext preemption granularity control 1055*c0e85e96SFrançois Tigeot * until D0 which is the default case so this is equivalent to 1056*c0e85e96SFrançois Tigeot * !WaDisablePerCtxtPreemptionGranularityControl:skl 1057*c0e85e96SFrançois Tigeot */ 1058*c0e85e96SFrançois Tigeot if (IS_SKL_REVID(dev, SKL_REVID_E0, REVID_FOREVER)) { 1059*c0e85e96SFrançois Tigeot I915_WRITE(GEN7_FF_SLICE_CS_CHICKEN1, 1060*c0e85e96SFrançois Tigeot _MASKED_BIT_ENABLE(GEN9_FFSC_PERCTX_PREEMPT_CTRL)); 1061*c0e85e96SFrançois Tigeot } 1062*c0e85e96SFrançois Tigeot 1063aee94f86SFrançois Tigeot if (IS_SKL_REVID(dev, 0, SKL_REVID_D0)) { 1064352ff8bdSFrançois Tigeot /* WaDisableChickenBitTSGBarrierAckForFFSliceCS:skl */ 1065352ff8bdSFrançois Tigeot I915_WRITE(FF_SLICE_CS_CHICKEN2, 1066352ff8bdSFrançois Tigeot _MASKED_BIT_ENABLE(GEN9_TSG_BARRIER_ACK_DISABLE)); 1067352ff8bdSFrançois Tigeot } 1068352ff8bdSFrançois Tigeot 1069352ff8bdSFrançois Tigeot /* GEN8_L3SQCREG4 has a dependency with WA batch so any new changes 1070352ff8bdSFrançois Tigeot * involving this register should also be added to WA batch as required. 1071352ff8bdSFrançois Tigeot */ 1072aee94f86SFrançois Tigeot if (IS_SKL_REVID(dev, 0, SKL_REVID_E0)) 1073352ff8bdSFrançois Tigeot /* WaDisableLSQCROPERFforOCL:skl */ 1074352ff8bdSFrançois Tigeot I915_WRITE(GEN8_L3SQCREG4, I915_READ(GEN8_L3SQCREG4) | 1075352ff8bdSFrançois Tigeot GEN8_LQSC_RO_PERF_DIS); 1076352ff8bdSFrançois Tigeot 1077352ff8bdSFrançois Tigeot /* WaEnableGapsTsvCreditFix:skl */ 1078aee94f86SFrançois Tigeot if (IS_SKL_REVID(dev, SKL_REVID_C0, REVID_FOREVER)) { 1079352ff8bdSFrançois Tigeot I915_WRITE(GEN8_GARBCNTL, (I915_READ(GEN8_GARBCNTL) | 1080352ff8bdSFrançois Tigeot GEN9_GAPS_TSV_CREDIT_DISABLE)); 1081352ff8bdSFrançois Tigeot } 1082477eb7f9SFrançois Tigeot 1083477eb7f9SFrançois Tigeot /* WaDisablePowerCompilerClockGating:skl */ 1084aee94f86SFrançois Tigeot if (IS_SKL_REVID(dev, SKL_REVID_B0, SKL_REVID_B0)) 1085477eb7f9SFrançois Tigeot WA_SET_BIT_MASKED(HIZ_CHICKEN, 1086477eb7f9SFrançois Tigeot BDW_HIZ_POWER_COMPILER_CLOCK_GATING_DISABLE); 1087477eb7f9SFrançois Tigeot 1088*c0e85e96SFrançois Tigeot /* This is tied to WaForceContextSaveRestoreNonCoherent */ 1089*c0e85e96SFrançois Tigeot if (IS_SKL_REVID(dev, 0, REVID_FOREVER)) { 109019c468b4SFrançois Tigeot /* 109119c468b4SFrançois Tigeot *Use Force Non-Coherent whenever executing a 3D context. This 109219c468b4SFrançois Tigeot * is a workaround for a possible hang in the unlikely event 109319c468b4SFrançois Tigeot * a TLB invalidation occurs during a PSD flush. 109419c468b4SFrançois Tigeot */ 109519c468b4SFrançois Tigeot /* WaForceEnableNonCoherent:skl */ 109619c468b4SFrançois Tigeot WA_SET_BIT_MASKED(HDC_CHICKEN0, 109719c468b4SFrançois Tigeot HDC_FORCE_NON_COHERENT); 1098aee94f86SFrançois Tigeot 1099aee94f86SFrançois Tigeot /* WaDisableHDCInvalidation:skl */ 1100aee94f86SFrançois Tigeot I915_WRITE(GAM_ECOCHK, I915_READ(GAM_ECOCHK) | 1101aee94f86SFrançois Tigeot BDW_DISABLE_HDC_INVALIDATION); 110219c468b4SFrançois Tigeot } 110319c468b4SFrançois Tigeot 1104a05eeebfSFrançois Tigeot /* WaBarrierPerformanceFixDisable:skl */ 1105aee94f86SFrançois Tigeot if (IS_SKL_REVID(dev, SKL_REVID_C0, SKL_REVID_D0)) 1106a05eeebfSFrançois Tigeot WA_SET_BIT_MASKED(HDC_CHICKEN0, 1107a05eeebfSFrançois Tigeot HDC_FENCE_DEST_SLM_DISABLE | 1108a05eeebfSFrançois Tigeot HDC_BARRIER_PERFORMANCE_DISABLE); 1109a05eeebfSFrançois Tigeot 1110a05eeebfSFrançois Tigeot /* WaDisableSbeCacheDispatchPortSharing:skl */ 1111aee94f86SFrançois Tigeot if (IS_SKL_REVID(dev, 0, SKL_REVID_F0)) 1112a05eeebfSFrançois Tigeot WA_SET_BIT_MASKED( 1113a05eeebfSFrançois Tigeot GEN7_HALF_SLICE_CHICKEN1, 1114a05eeebfSFrançois Tigeot GEN7_SBE_SS_CACHE_DISPATCH_PORT_SHARING_DISABLE); 1115a05eeebfSFrançois Tigeot 1116*c0e85e96SFrançois Tigeot /* WaDisableLSQCROPERFforOCL:skl */ 1117*c0e85e96SFrançois Tigeot ret = wa_ring_whitelist_reg(ring, GEN8_L3SQCREG4); 1118*c0e85e96SFrançois Tigeot if (ret) 1119*c0e85e96SFrançois Tigeot return ret; 1120*c0e85e96SFrançois Tigeot 1121477eb7f9SFrançois Tigeot return skl_tune_iz_hashing(ring); 1122477eb7f9SFrançois Tigeot } 1123477eb7f9SFrançois Tigeot 112419c468b4SFrançois Tigeot static int bxt_init_workarounds(struct intel_engine_cs *ring) 112519c468b4SFrançois Tigeot { 1126352ff8bdSFrançois Tigeot int ret; 112719c468b4SFrançois Tigeot struct drm_device *dev = ring->dev; 112819c468b4SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 112919c468b4SFrançois Tigeot 1130352ff8bdSFrançois Tigeot ret = gen9_init_workarounds(ring); 1131352ff8bdSFrançois Tigeot if (ret) 1132352ff8bdSFrançois Tigeot return ret; 1133352ff8bdSFrançois Tigeot 1134352ff8bdSFrançois Tigeot /* WaStoreMultiplePTEenable:bxt */ 1135352ff8bdSFrançois Tigeot /* This is a requirement according to Hardware specification */ 1136aee94f86SFrançois Tigeot if (IS_BXT_REVID(dev, 0, BXT_REVID_A1)) 1137352ff8bdSFrançois Tigeot I915_WRITE(TILECTL, I915_READ(TILECTL) | TILECTL_TLBPF); 1138352ff8bdSFrançois Tigeot 1139352ff8bdSFrançois Tigeot /* WaSetClckGatingDisableMedia:bxt */ 1140aee94f86SFrançois Tigeot if (IS_BXT_REVID(dev, 0, BXT_REVID_A1)) { 1141352ff8bdSFrançois Tigeot I915_WRITE(GEN7_MISCCPCTL, (I915_READ(GEN7_MISCCPCTL) & 1142352ff8bdSFrançois Tigeot ~GEN8_DOP_CLOCK_GATE_MEDIA_ENABLE)); 1143352ff8bdSFrançois Tigeot } 114419c468b4SFrançois Tigeot 114519c468b4SFrançois Tigeot /* WaDisableThreadStallDopClockGating:bxt */ 114619c468b4SFrançois Tigeot WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN, 114719c468b4SFrançois Tigeot STALL_DOP_GATING_DISABLE); 114819c468b4SFrançois Tigeot 114919c468b4SFrançois Tigeot /* WaDisableSbeCacheDispatchPortSharing:bxt */ 1150aee94f86SFrançois Tigeot if (IS_BXT_REVID(dev, 0, BXT_REVID_B0)) { 115119c468b4SFrançois Tigeot WA_SET_BIT_MASKED( 115219c468b4SFrançois Tigeot GEN7_HALF_SLICE_CHICKEN1, 115319c468b4SFrançois Tigeot GEN7_SBE_SS_CACHE_DISPATCH_PORT_SHARING_DISABLE); 115419c468b4SFrançois Tigeot } 115519c468b4SFrançois Tigeot 1156*c0e85e96SFrançois Tigeot /* WaDisableObjectLevelPreemptionForTrifanOrPolygon:bxt */ 1157*c0e85e96SFrançois Tigeot /* WaDisableObjectLevelPreemptionForInstancedDraw:bxt */ 1158*c0e85e96SFrançois Tigeot /* WaDisableObjectLevelPreemtionForInstanceId:bxt */ 1159*c0e85e96SFrançois Tigeot /* WaDisableLSQCROPERFforOCL:bxt */ 1160*c0e85e96SFrançois Tigeot if (IS_BXT_REVID(dev, 0, BXT_REVID_A1)) { 1161*c0e85e96SFrançois Tigeot ret = wa_ring_whitelist_reg(ring, GEN9_CS_DEBUG_MODE1); 1162*c0e85e96SFrançois Tigeot if (ret) 1163*c0e85e96SFrançois Tigeot return ret; 1164*c0e85e96SFrançois Tigeot 1165*c0e85e96SFrançois Tigeot ret = wa_ring_whitelist_reg(ring, GEN8_L3SQCREG4); 1166*c0e85e96SFrançois Tigeot if (ret) 1167*c0e85e96SFrançois Tigeot return ret; 1168*c0e85e96SFrançois Tigeot } 1169*c0e85e96SFrançois Tigeot 117019c468b4SFrançois Tigeot return 0; 117119c468b4SFrançois Tigeot } 117219c468b4SFrançois Tigeot 11732c9916cdSFrançois Tigeot int init_workarounds_ring(struct intel_engine_cs *ring) 11742c9916cdSFrançois Tigeot { 11752c9916cdSFrançois Tigeot struct drm_device *dev = ring->dev; 11762c9916cdSFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 11772c9916cdSFrançois Tigeot 11782c9916cdSFrançois Tigeot WARN_ON(ring->id != RCS); 11792c9916cdSFrançois Tigeot 11802c9916cdSFrançois Tigeot dev_priv->workarounds.count = 0; 1181*c0e85e96SFrançois Tigeot dev_priv->workarounds.hw_whitelist_count[RCS] = 0; 11822c9916cdSFrançois Tigeot 11832c9916cdSFrançois Tigeot if (IS_BROADWELL(dev)) 11842c9916cdSFrançois Tigeot return bdw_init_workarounds(ring); 11852c9916cdSFrançois Tigeot 11862c9916cdSFrançois Tigeot if (IS_CHERRYVIEW(dev)) 11872c9916cdSFrançois Tigeot return chv_init_workarounds(ring); 11881b13d190SFrançois Tigeot 1189477eb7f9SFrançois Tigeot if (IS_SKYLAKE(dev)) 1190477eb7f9SFrançois Tigeot return skl_init_workarounds(ring); 119119c468b4SFrançois Tigeot 119219c468b4SFrançois Tigeot if (IS_BROXTON(dev)) 119319c468b4SFrançois Tigeot return bxt_init_workarounds(ring); 1194477eb7f9SFrançois Tigeot 11951b13d190SFrançois Tigeot return 0; 11961b13d190SFrançois Tigeot } 11971b13d190SFrançois Tigeot 1198ba55f2f5SFrançois Tigeot static int init_render_ring(struct intel_engine_cs *ring) 1199e3adcf8fSFrançois Tigeot { 1200e3adcf8fSFrançois Tigeot struct drm_device *dev = ring->dev; 1201e3adcf8fSFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 1202e3adcf8fSFrançois Tigeot int ret = init_ring_common(ring); 120324edb884SFrançois Tigeot if (ret) 120424edb884SFrançois Tigeot return ret; 1205e3adcf8fSFrançois Tigeot 1206ba55f2f5SFrançois Tigeot /* WaTimedSingleVertexDispatch:cl,bw,ctg,elk,ilk,snb */ 1207ba55f2f5SFrançois Tigeot if (INTEL_INFO(dev)->gen >= 4 && INTEL_INFO(dev)->gen < 7) 1208f4e1c372SFrançois Tigeot I915_WRITE(MI_MODE, _MASKED_BIT_ENABLE(VS_TIMER_DISPATCH)); 1209f4e1c372SFrançois Tigeot 1210f4e1c372SFrançois Tigeot /* We need to disable the AsyncFlip performance optimisations in order 1211f4e1c372SFrançois Tigeot * to use MI_WAIT_FOR_EVENT within the CS. It should already be 1212f4e1c372SFrançois Tigeot * programmed to '1' on all products. 12135d0b1887SFrançois Tigeot * 1214a05eeebfSFrançois Tigeot * WaDisableAsyncFlipPerfMode:snb,ivb,hsw,vlv 1215f4e1c372SFrançois Tigeot */ 1216a05eeebfSFrançois Tigeot if (INTEL_INFO(dev)->gen >= 6 && INTEL_INFO(dev)->gen < 8) 1217f4e1c372SFrançois Tigeot I915_WRITE(MI_MODE, _MASKED_BIT_ENABLE(ASYNC_FLIP_PERF_DISABLE)); 1218f4e1c372SFrançois Tigeot 1219f4e1c372SFrançois Tigeot /* Required for the hardware to program scanline values for waiting */ 1220ba55f2f5SFrançois Tigeot /* WaEnableFlushTlbInvalidationMode:snb */ 1221f4e1c372SFrançois Tigeot if (INTEL_INFO(dev)->gen == 6) 1222f4e1c372SFrançois Tigeot I915_WRITE(GFX_MODE, 1223ba55f2f5SFrançois Tigeot _MASKED_BIT_ENABLE(GFX_TLB_INVALIDATE_EXPLICIT)); 1224f4e1c372SFrançois Tigeot 1225ba55f2f5SFrançois Tigeot /* WaBCSVCSTlbInvalidationMode:ivb,vlv,hsw */ 1226e3adcf8fSFrançois Tigeot if (IS_GEN7(dev)) 1227e3adcf8fSFrançois Tigeot I915_WRITE(GFX_MODE_GEN7, 1228ba55f2f5SFrançois Tigeot _MASKED_BIT_ENABLE(GFX_TLB_INVALIDATE_EXPLICIT) | 1229f4e1c372SFrançois Tigeot _MASKED_BIT_ENABLE(GFX_REPLAY_MODE)); 1230e3adcf8fSFrançois Tigeot 1231e3adcf8fSFrançois Tigeot if (IS_GEN6(dev)) { 1232e3adcf8fSFrançois Tigeot /* From the Sandybridge PRM, volume 1 part 3, page 24: 1233e3adcf8fSFrançois Tigeot * "If this bit is set, STCunit will have LRA as replacement 1234e3adcf8fSFrançois Tigeot * policy. [...] This bit must be reset. LRA replacement 1235e3adcf8fSFrançois Tigeot * policy is not supported." 1236e3adcf8fSFrançois Tigeot */ 1237e3adcf8fSFrançois Tigeot I915_WRITE(CACHE_MODE_0, 1238f4e1c372SFrançois Tigeot _MASKED_BIT_DISABLE(CM0_STC_EVICT_DISABLE_LRA_SNB)); 1239e3adcf8fSFrançois Tigeot } 1240e3adcf8fSFrançois Tigeot 1241a05eeebfSFrançois Tigeot if (INTEL_INFO(dev)->gen >= 6 && INTEL_INFO(dev)->gen < 8) 1242f4e1c372SFrançois Tigeot I915_WRITE(INSTPM, _MASKED_BIT_ENABLE(INSTPM_FORCE_ORDERING)); 1243f4e1c372SFrançois Tigeot 12449edbd4a0SFrançois Tigeot if (HAS_L3_DPF(dev)) 12459edbd4a0SFrançois Tigeot I915_WRITE_IMR(ring, ~GT_PARITY_ERROR(dev)); 1246e3adcf8fSFrançois Tigeot 12472c9916cdSFrançois Tigeot return init_workarounds_ring(ring); 1248e3adcf8fSFrançois Tigeot } 1249e3adcf8fSFrançois Tigeot 1250ba55f2f5SFrançois Tigeot static void render_ring_cleanup(struct intel_engine_cs *ring) 1251e3adcf8fSFrançois Tigeot { 1252b5c29a34SFrançois Tigeot struct drm_device *dev = ring->dev; 125324edb884SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 125424edb884SFrançois Tigeot 125524edb884SFrançois Tigeot if (dev_priv->semaphore_obj) { 125624edb884SFrançois Tigeot i915_gem_object_ggtt_unpin(dev_priv->semaphore_obj); 125724edb884SFrançois Tigeot drm_gem_object_unreference(&dev_priv->semaphore_obj->base); 125824edb884SFrançois Tigeot dev_priv->semaphore_obj = NULL; 125924edb884SFrançois Tigeot } 1260b5c29a34SFrançois Tigeot 12611b13d190SFrançois Tigeot intel_fini_pipe_control(ring); 1262e3adcf8fSFrançois Tigeot } 1263e3adcf8fSFrançois Tigeot 1264a05eeebfSFrançois Tigeot static int gen8_rcs_signal(struct drm_i915_gem_request *signaller_req, 126524edb884SFrançois Tigeot unsigned int num_dwords) 126624edb884SFrançois Tigeot { 126724edb884SFrançois Tigeot #define MBOX_UPDATE_DWORDS 8 1268a05eeebfSFrançois Tigeot struct intel_engine_cs *signaller = signaller_req->ring; 126924edb884SFrançois Tigeot struct drm_device *dev = signaller->dev; 127024edb884SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 127124edb884SFrançois Tigeot struct intel_engine_cs *waiter; 127224edb884SFrançois Tigeot int i, ret, num_rings; 127324edb884SFrançois Tigeot 127424edb884SFrançois Tigeot num_rings = hweight32(INTEL_INFO(dev)->ring_mask); 127524edb884SFrançois Tigeot num_dwords += (num_rings-1) * MBOX_UPDATE_DWORDS; 127624edb884SFrançois Tigeot #undef MBOX_UPDATE_DWORDS 127724edb884SFrançois Tigeot 1278a05eeebfSFrançois Tigeot ret = intel_ring_begin(signaller_req, num_dwords); 127924edb884SFrançois Tigeot if (ret) 128024edb884SFrançois Tigeot return ret; 128124edb884SFrançois Tigeot 128224edb884SFrançois Tigeot for_each_ring(waiter, dev_priv, i) { 12832c9916cdSFrançois Tigeot u32 seqno; 128424edb884SFrançois Tigeot u64 gtt_offset = signaller->semaphore.signal_ggtt[i]; 128524edb884SFrançois Tigeot if (gtt_offset == MI_SEMAPHORE_SYNC_INVALID) 128624edb884SFrançois Tigeot continue; 128724edb884SFrançois Tigeot 1288a05eeebfSFrançois Tigeot seqno = i915_gem_request_get_seqno(signaller_req); 128924edb884SFrançois Tigeot intel_ring_emit(signaller, GFX_OP_PIPE_CONTROL(6)); 129024edb884SFrançois Tigeot intel_ring_emit(signaller, PIPE_CONTROL_GLOBAL_GTT_IVB | 129124edb884SFrançois Tigeot PIPE_CONTROL_QW_WRITE | 129224edb884SFrançois Tigeot PIPE_CONTROL_FLUSH_ENABLE); 129324edb884SFrançois Tigeot intel_ring_emit(signaller, lower_32_bits(gtt_offset)); 129424edb884SFrançois Tigeot intel_ring_emit(signaller, upper_32_bits(gtt_offset)); 12952c9916cdSFrançois Tigeot intel_ring_emit(signaller, seqno); 129624edb884SFrançois Tigeot intel_ring_emit(signaller, 0); 129724edb884SFrançois Tigeot intel_ring_emit(signaller, MI_SEMAPHORE_SIGNAL | 129824edb884SFrançois Tigeot MI_SEMAPHORE_TARGET(waiter->id)); 129924edb884SFrançois Tigeot intel_ring_emit(signaller, 0); 130024edb884SFrançois Tigeot } 130124edb884SFrançois Tigeot 130224edb884SFrançois Tigeot return 0; 130324edb884SFrançois Tigeot } 130424edb884SFrançois Tigeot 1305a05eeebfSFrançois Tigeot static int gen8_xcs_signal(struct drm_i915_gem_request *signaller_req, 130624edb884SFrançois Tigeot unsigned int num_dwords) 130724edb884SFrançois Tigeot { 130824edb884SFrançois Tigeot #define MBOX_UPDATE_DWORDS 6 1309a05eeebfSFrançois Tigeot struct intel_engine_cs *signaller = signaller_req->ring; 131024edb884SFrançois Tigeot struct drm_device *dev = signaller->dev; 131124edb884SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 131224edb884SFrançois Tigeot struct intel_engine_cs *waiter; 131324edb884SFrançois Tigeot int i, ret, num_rings; 131424edb884SFrançois Tigeot 131524edb884SFrançois Tigeot num_rings = hweight32(INTEL_INFO(dev)->ring_mask); 131624edb884SFrançois Tigeot num_dwords += (num_rings-1) * MBOX_UPDATE_DWORDS; 131724edb884SFrançois Tigeot #undef MBOX_UPDATE_DWORDS 131824edb884SFrançois Tigeot 1319a05eeebfSFrançois Tigeot ret = intel_ring_begin(signaller_req, num_dwords); 132024edb884SFrançois Tigeot if (ret) 132124edb884SFrançois Tigeot return ret; 132224edb884SFrançois Tigeot 132324edb884SFrançois Tigeot for_each_ring(waiter, dev_priv, i) { 13242c9916cdSFrançois Tigeot u32 seqno; 132524edb884SFrançois Tigeot u64 gtt_offset = signaller->semaphore.signal_ggtt[i]; 132624edb884SFrançois Tigeot if (gtt_offset == MI_SEMAPHORE_SYNC_INVALID) 132724edb884SFrançois Tigeot continue; 132824edb884SFrançois Tigeot 1329a05eeebfSFrançois Tigeot seqno = i915_gem_request_get_seqno(signaller_req); 133024edb884SFrançois Tigeot intel_ring_emit(signaller, (MI_FLUSH_DW + 1) | 133124edb884SFrançois Tigeot MI_FLUSH_DW_OP_STOREDW); 133224edb884SFrançois Tigeot intel_ring_emit(signaller, lower_32_bits(gtt_offset) | 133324edb884SFrançois Tigeot MI_FLUSH_DW_USE_GTT); 133424edb884SFrançois Tigeot intel_ring_emit(signaller, upper_32_bits(gtt_offset)); 13352c9916cdSFrançois Tigeot intel_ring_emit(signaller, seqno); 133624edb884SFrançois Tigeot intel_ring_emit(signaller, MI_SEMAPHORE_SIGNAL | 133724edb884SFrançois Tigeot MI_SEMAPHORE_TARGET(waiter->id)); 133824edb884SFrançois Tigeot intel_ring_emit(signaller, 0); 133924edb884SFrançois Tigeot } 134024edb884SFrançois Tigeot 134124edb884SFrançois Tigeot return 0; 134224edb884SFrançois Tigeot } 134324edb884SFrançois Tigeot 1344a05eeebfSFrançois Tigeot static int gen6_signal(struct drm_i915_gem_request *signaller_req, 1345ba55f2f5SFrançois Tigeot unsigned int num_dwords) 1346e3adcf8fSFrançois Tigeot { 1347a05eeebfSFrançois Tigeot struct intel_engine_cs *signaller = signaller_req->ring; 1348ba55f2f5SFrançois Tigeot struct drm_device *dev = signaller->dev; 1349ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 1350ba55f2f5SFrançois Tigeot struct intel_engine_cs *useless; 135124edb884SFrançois Tigeot int i, ret, num_rings; 1352ba55f2f5SFrançois Tigeot 135324edb884SFrançois Tigeot #define MBOX_UPDATE_DWORDS 3 135424edb884SFrançois Tigeot num_rings = hweight32(INTEL_INFO(dev)->ring_mask); 135524edb884SFrançois Tigeot num_dwords += round_up((num_rings-1) * MBOX_UPDATE_DWORDS, 2); 135624edb884SFrançois Tigeot #undef MBOX_UPDATE_DWORDS 1357ba55f2f5SFrançois Tigeot 1358a05eeebfSFrançois Tigeot ret = intel_ring_begin(signaller_req, num_dwords); 1359ba55f2f5SFrançois Tigeot if (ret) 1360ba55f2f5SFrançois Tigeot return ret; 1361ba55f2f5SFrançois Tigeot 1362ba55f2f5SFrançois Tigeot for_each_ring(useless, dev_priv, i) { 1363aee94f86SFrançois Tigeot i915_reg_t mbox_reg = signaller->semaphore.mbox.signal[i]; 1364aee94f86SFrançois Tigeot 1365aee94f86SFrançois Tigeot if (i915_mmio_reg_valid(mbox_reg)) { 1366a05eeebfSFrançois Tigeot u32 seqno = i915_gem_request_get_seqno(signaller_req); 1367aee94f86SFrançois Tigeot 1368ba55f2f5SFrançois Tigeot intel_ring_emit(signaller, MI_LOAD_REGISTER_IMM(1)); 1369aee94f86SFrançois Tigeot intel_ring_emit_reg(signaller, mbox_reg); 13702c9916cdSFrançois Tigeot intel_ring_emit(signaller, seqno); 1371ba55f2f5SFrançois Tigeot } 1372ba55f2f5SFrançois Tigeot } 1373ba55f2f5SFrançois Tigeot 137424edb884SFrançois Tigeot /* If num_dwords was rounded, make sure the tail pointer is correct */ 137524edb884SFrançois Tigeot if (num_rings % 2 == 0) 137624edb884SFrançois Tigeot intel_ring_emit(signaller, MI_NOOP); 137724edb884SFrançois Tigeot 1378ba55f2f5SFrançois Tigeot return 0; 1379e3adcf8fSFrançois Tigeot } 1380e3adcf8fSFrançois Tigeot 1381e3adcf8fSFrançois Tigeot /** 1382e3adcf8fSFrançois Tigeot * gen6_add_request - Update the semaphore mailbox registers 1383e3adcf8fSFrançois Tigeot * 1384a05eeebfSFrançois Tigeot * @request - request to write to the ring 1385e3adcf8fSFrançois Tigeot * 1386e3adcf8fSFrançois Tigeot * Update the mailbox registers in the *other* rings with the current seqno. 1387e3adcf8fSFrançois Tigeot * This acts like a signal in the canonical semaphore. 1388e3adcf8fSFrançois Tigeot */ 1389e3adcf8fSFrançois Tigeot static int 1390a05eeebfSFrançois Tigeot gen6_add_request(struct drm_i915_gem_request *req) 1391e3adcf8fSFrançois Tigeot { 1392a05eeebfSFrançois Tigeot struct intel_engine_cs *ring = req->ring; 1393ba55f2f5SFrançois Tigeot int ret; 1394e3adcf8fSFrançois Tigeot 139524edb884SFrançois Tigeot if (ring->semaphore.signal) 1396a05eeebfSFrançois Tigeot ret = ring->semaphore.signal(req, 4); 139724edb884SFrançois Tigeot else 1398a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 4); 139924edb884SFrançois Tigeot 14009edbd4a0SFrançois Tigeot if (ret) 14019edbd4a0SFrançois Tigeot return ret; 14029edbd4a0SFrançois Tigeot 1403e3adcf8fSFrançois Tigeot intel_ring_emit(ring, MI_STORE_DWORD_INDEX); 1404e3adcf8fSFrançois Tigeot intel_ring_emit(ring, I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT); 1405a05eeebfSFrançois Tigeot intel_ring_emit(ring, i915_gem_request_get_seqno(req)); 1406e3adcf8fSFrançois Tigeot intel_ring_emit(ring, MI_USER_INTERRUPT); 14079edbd4a0SFrançois Tigeot __intel_ring_advance(ring); 1408e3adcf8fSFrançois Tigeot 1409e3adcf8fSFrançois Tigeot return 0; 1410e3adcf8fSFrançois Tigeot } 1411e3adcf8fSFrançois Tigeot 1412a2fdbec6SFrançois Tigeot static inline bool i915_gem_has_seqno_wrapped(struct drm_device *dev, 1413a2fdbec6SFrançois Tigeot u32 seqno) 1414a2fdbec6SFrançois Tigeot { 1415a2fdbec6SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 1416a2fdbec6SFrançois Tigeot return dev_priv->last_seqno < seqno; 1417a2fdbec6SFrançois Tigeot } 1418a2fdbec6SFrançois Tigeot 1419e3adcf8fSFrançois Tigeot /** 1420e3adcf8fSFrançois Tigeot * intel_ring_sync - sync the waiter to the signaller on seqno 1421e3adcf8fSFrançois Tigeot * 1422e3adcf8fSFrançois Tigeot * @waiter - ring that is waiting 1423e3adcf8fSFrançois Tigeot * @signaller - ring which has, or will signal 1424e3adcf8fSFrançois Tigeot * @seqno - seqno which the waiter will block on 1425e3adcf8fSFrançois Tigeot */ 142624edb884SFrançois Tigeot 142724edb884SFrançois Tigeot static int 1428a05eeebfSFrançois Tigeot gen8_ring_sync(struct drm_i915_gem_request *waiter_req, 142924edb884SFrançois Tigeot struct intel_engine_cs *signaller, 143024edb884SFrançois Tigeot u32 seqno) 143124edb884SFrançois Tigeot { 1432a05eeebfSFrançois Tigeot struct intel_engine_cs *waiter = waiter_req->ring; 143324edb884SFrançois Tigeot struct drm_i915_private *dev_priv = waiter->dev->dev_private; 143424edb884SFrançois Tigeot int ret; 143524edb884SFrançois Tigeot 1436a05eeebfSFrançois Tigeot ret = intel_ring_begin(waiter_req, 4); 143724edb884SFrançois Tigeot if (ret) 143824edb884SFrançois Tigeot return ret; 143924edb884SFrançois Tigeot 144024edb884SFrançois Tigeot intel_ring_emit(waiter, MI_SEMAPHORE_WAIT | 144124edb884SFrançois Tigeot MI_SEMAPHORE_GLOBAL_GTT | 144224edb884SFrançois Tigeot MI_SEMAPHORE_POLL | 144324edb884SFrançois Tigeot MI_SEMAPHORE_SAD_GTE_SDD); 144424edb884SFrançois Tigeot intel_ring_emit(waiter, seqno); 144524edb884SFrançois Tigeot intel_ring_emit(waiter, 144624edb884SFrançois Tigeot lower_32_bits(GEN8_WAIT_OFFSET(waiter, signaller->id))); 144724edb884SFrançois Tigeot intel_ring_emit(waiter, 144824edb884SFrançois Tigeot upper_32_bits(GEN8_WAIT_OFFSET(waiter, signaller->id))); 144924edb884SFrançois Tigeot intel_ring_advance(waiter); 145024edb884SFrançois Tigeot return 0; 145124edb884SFrançois Tigeot } 145224edb884SFrançois Tigeot 1453e3adcf8fSFrançois Tigeot static int 1454a05eeebfSFrançois Tigeot gen6_ring_sync(struct drm_i915_gem_request *waiter_req, 1455ba55f2f5SFrançois Tigeot struct intel_engine_cs *signaller, 1456e3adcf8fSFrançois Tigeot u32 seqno) 1457e3adcf8fSFrançois Tigeot { 1458a05eeebfSFrançois Tigeot struct intel_engine_cs *waiter = waiter_req->ring; 1459e3adcf8fSFrançois Tigeot u32 dw1 = MI_SEMAPHORE_MBOX | 1460e3adcf8fSFrançois Tigeot MI_SEMAPHORE_COMPARE | 1461e3adcf8fSFrançois Tigeot MI_SEMAPHORE_REGISTER; 1462ba55f2f5SFrançois Tigeot u32 wait_mbox = signaller->semaphore.mbox.wait[waiter->id]; 1463ba55f2f5SFrançois Tigeot int ret; 1464e3adcf8fSFrançois Tigeot 1465686a02f1SFrançois Tigeot /* Throughout all of the GEM code, seqno passed implies our current 1466686a02f1SFrançois Tigeot * seqno is >= the last seqno executed. However for hardware the 1467686a02f1SFrançois Tigeot * comparison is strictly greater than. 1468686a02f1SFrançois Tigeot */ 1469686a02f1SFrançois Tigeot seqno -= 1; 1470686a02f1SFrançois Tigeot 1471ba55f2f5SFrançois Tigeot WARN_ON(wait_mbox == MI_SEMAPHORE_SYNC_INVALID); 1472686a02f1SFrançois Tigeot 1473a05eeebfSFrançois Tigeot ret = intel_ring_begin(waiter_req, 4); 1474e3adcf8fSFrançois Tigeot if (ret) 1475e3adcf8fSFrançois Tigeot return ret; 1476e3adcf8fSFrançois Tigeot 1477a2fdbec6SFrançois Tigeot /* If seqno wrap happened, omit the wait with no-ops */ 1478a2fdbec6SFrançois Tigeot if (likely(!i915_gem_has_seqno_wrapped(waiter->dev, seqno))) { 1479ba55f2f5SFrançois Tigeot intel_ring_emit(waiter, dw1 | wait_mbox); 1480e3adcf8fSFrançois Tigeot intel_ring_emit(waiter, seqno); 1481e3adcf8fSFrançois Tigeot intel_ring_emit(waiter, 0); 1482e3adcf8fSFrançois Tigeot intel_ring_emit(waiter, MI_NOOP); 1483a2fdbec6SFrançois Tigeot } else { 1484a2fdbec6SFrançois Tigeot intel_ring_emit(waiter, MI_NOOP); 1485a2fdbec6SFrançois Tigeot intel_ring_emit(waiter, MI_NOOP); 1486a2fdbec6SFrançois Tigeot intel_ring_emit(waiter, MI_NOOP); 1487a2fdbec6SFrançois Tigeot intel_ring_emit(waiter, MI_NOOP); 1488a2fdbec6SFrançois Tigeot } 1489e3adcf8fSFrançois Tigeot intel_ring_advance(waiter); 1490e3adcf8fSFrançois Tigeot 1491e3adcf8fSFrançois Tigeot return 0; 1492e3adcf8fSFrançois Tigeot } 1493e3adcf8fSFrançois Tigeot 1494e3adcf8fSFrançois Tigeot #define PIPE_CONTROL_FLUSH(ring__, addr__) \ 1495e3adcf8fSFrançois Tigeot do { \ 1496e3adcf8fSFrançois Tigeot intel_ring_emit(ring__, GFX_OP_PIPE_CONTROL(4) | PIPE_CONTROL_QW_WRITE | \ 1497e3adcf8fSFrançois Tigeot PIPE_CONTROL_DEPTH_STALL); \ 1498e3adcf8fSFrançois Tigeot intel_ring_emit(ring__, (addr__) | PIPE_CONTROL_GLOBAL_GTT); \ 1499e3adcf8fSFrançois Tigeot intel_ring_emit(ring__, 0); \ 1500e3adcf8fSFrançois Tigeot intel_ring_emit(ring__, 0); \ 1501e3adcf8fSFrançois Tigeot } while (0) 1502e3adcf8fSFrançois Tigeot 1503e3adcf8fSFrançois Tigeot static int 1504a05eeebfSFrançois Tigeot pc_render_add_request(struct drm_i915_gem_request *req) 1505e3adcf8fSFrançois Tigeot { 1506a05eeebfSFrançois Tigeot struct intel_engine_cs *ring = req->ring; 1507ba55f2f5SFrançois Tigeot u32 scratch_addr = ring->scratch.gtt_offset + 2 * CACHELINE_BYTES; 1508e3adcf8fSFrançois Tigeot int ret; 1509e3adcf8fSFrançois Tigeot 1510e3adcf8fSFrançois Tigeot /* For Ironlake, MI_USER_INTERRUPT was deprecated and apparently 1511e3adcf8fSFrançois Tigeot * incoherent with writes to memory, i.e. completely fubar, 1512e3adcf8fSFrançois Tigeot * so we need to use PIPE_NOTIFY instead. 1513e3adcf8fSFrançois Tigeot * 1514e3adcf8fSFrançois Tigeot * However, we also need to workaround the qword write 1515e3adcf8fSFrançois Tigeot * incoherence by flushing the 6 PIPE_NOTIFY buffers out to 1516e3adcf8fSFrançois Tigeot * memory before requesting an interrupt. 1517e3adcf8fSFrançois Tigeot */ 1518a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 32); 1519e3adcf8fSFrançois Tigeot if (ret) 1520e3adcf8fSFrançois Tigeot return ret; 1521e3adcf8fSFrançois Tigeot 1522e3adcf8fSFrançois Tigeot intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(4) | PIPE_CONTROL_QW_WRITE | 1523e3adcf8fSFrançois Tigeot PIPE_CONTROL_WRITE_FLUSH | 1524e3adcf8fSFrançois Tigeot PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE); 15259edbd4a0SFrançois Tigeot intel_ring_emit(ring, ring->scratch.gtt_offset | PIPE_CONTROL_GLOBAL_GTT); 1526a05eeebfSFrançois Tigeot intel_ring_emit(ring, i915_gem_request_get_seqno(req)); 1527e3adcf8fSFrançois Tigeot intel_ring_emit(ring, 0); 1528e3adcf8fSFrançois Tigeot PIPE_CONTROL_FLUSH(ring, scratch_addr); 1529ba55f2f5SFrançois Tigeot scratch_addr += 2 * CACHELINE_BYTES; /* write to separate cachelines */ 1530e3adcf8fSFrançois Tigeot PIPE_CONTROL_FLUSH(ring, scratch_addr); 1531ba55f2f5SFrançois Tigeot scratch_addr += 2 * CACHELINE_BYTES; 1532e3adcf8fSFrançois Tigeot PIPE_CONTROL_FLUSH(ring, scratch_addr); 1533ba55f2f5SFrançois Tigeot scratch_addr += 2 * CACHELINE_BYTES; 1534e3adcf8fSFrançois Tigeot PIPE_CONTROL_FLUSH(ring, scratch_addr); 1535ba55f2f5SFrançois Tigeot scratch_addr += 2 * CACHELINE_BYTES; 1536e3adcf8fSFrançois Tigeot PIPE_CONTROL_FLUSH(ring, scratch_addr); 1537ba55f2f5SFrançois Tigeot scratch_addr += 2 * CACHELINE_BYTES; 1538e3adcf8fSFrançois Tigeot PIPE_CONTROL_FLUSH(ring, scratch_addr); 1539b5c29a34SFrançois Tigeot 1540e3adcf8fSFrançois Tigeot intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(4) | PIPE_CONTROL_QW_WRITE | 1541e3adcf8fSFrançois Tigeot PIPE_CONTROL_WRITE_FLUSH | 1542e3adcf8fSFrançois Tigeot PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE | 1543e3adcf8fSFrançois Tigeot PIPE_CONTROL_NOTIFY); 15449edbd4a0SFrançois Tigeot intel_ring_emit(ring, ring->scratch.gtt_offset | PIPE_CONTROL_GLOBAL_GTT); 1545a05eeebfSFrançois Tigeot intel_ring_emit(ring, i915_gem_request_get_seqno(req)); 1546e3adcf8fSFrançois Tigeot intel_ring_emit(ring, 0); 15479edbd4a0SFrançois Tigeot __intel_ring_advance(ring); 1548e3adcf8fSFrançois Tigeot 1549e3adcf8fSFrançois Tigeot return 0; 1550e3adcf8fSFrançois Tigeot } 1551e3adcf8fSFrançois Tigeot 1552e3adcf8fSFrançois Tigeot static u32 1553ba55f2f5SFrançois Tigeot gen6_ring_get_seqno(struct intel_engine_cs *ring, bool lazy_coherency) 1554e3adcf8fSFrançois Tigeot { 1555e3adcf8fSFrançois Tigeot /* Workaround to force correct ordering between irq and seqno writes on 1556e3adcf8fSFrançois Tigeot * ivb (and maybe also on snb) by reading from a CS register (like 1557e3adcf8fSFrançois Tigeot * ACTHD) before reading the status page. */ 1558ba55f2f5SFrançois Tigeot if (!lazy_coherency) { 1559ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = ring->dev->dev_private; 1560ba55f2f5SFrançois Tigeot POSTING_READ(RING_ACTHD(ring->mmio_base)); 1561ba55f2f5SFrançois Tigeot } 1562ba55f2f5SFrançois Tigeot 1563e3adcf8fSFrançois Tigeot return intel_read_status_page(ring, I915_GEM_HWS_INDEX); 1564e3adcf8fSFrançois Tigeot } 1565e3adcf8fSFrançois Tigeot 1566b030f26bSFrançois Tigeot static u32 1567ba55f2f5SFrançois Tigeot ring_get_seqno(struct intel_engine_cs *ring, bool lazy_coherency) 1568e3adcf8fSFrançois Tigeot { 1569e3adcf8fSFrançois Tigeot return intel_read_status_page(ring, I915_GEM_HWS_INDEX); 1570e3adcf8fSFrançois Tigeot } 1571e3adcf8fSFrançois Tigeot 1572a2fdbec6SFrançois Tigeot static void 1573ba55f2f5SFrançois Tigeot ring_set_seqno(struct intel_engine_cs *ring, u32 seqno) 1574a2fdbec6SFrançois Tigeot { 1575a2fdbec6SFrançois Tigeot intel_write_status_page(ring, I915_GEM_HWS_INDEX, seqno); 1576a2fdbec6SFrançois Tigeot } 1577a2fdbec6SFrançois Tigeot 1578b030f26bSFrançois Tigeot static u32 1579ba55f2f5SFrançois Tigeot pc_render_get_seqno(struct intel_engine_cs *ring, bool lazy_coherency) 1580e3adcf8fSFrançois Tigeot { 15819edbd4a0SFrançois Tigeot return ring->scratch.cpu_page[0]; 1582e3adcf8fSFrançois Tigeot } 1583e3adcf8fSFrançois Tigeot 1584a2fdbec6SFrançois Tigeot static void 1585ba55f2f5SFrançois Tigeot pc_render_set_seqno(struct intel_engine_cs *ring, u32 seqno) 1586a2fdbec6SFrançois Tigeot { 15879edbd4a0SFrançois Tigeot ring->scratch.cpu_page[0] = seqno; 1588a2fdbec6SFrançois Tigeot } 1589a2fdbec6SFrançois Tigeot 1590e3adcf8fSFrançois Tigeot static bool 1591ba55f2f5SFrançois Tigeot gen5_ring_get_irq(struct intel_engine_cs *ring) 1592e3adcf8fSFrançois Tigeot { 1593e3adcf8fSFrançois Tigeot struct drm_device *dev = ring->dev; 1594ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 15955e269720SFrançois Tigeot unsigned long flags; 1596e3adcf8fSFrançois Tigeot 15972c9916cdSFrançois Tigeot if (WARN_ON(!intel_irqs_enabled(dev_priv))) 1598e3adcf8fSFrançois Tigeot return false; 1599e3adcf8fSFrançois Tigeot 16005e269720SFrançois Tigeot spin_lock_irqsave(&dev_priv->irq_lock, flags); 16019edbd4a0SFrançois Tigeot if (ring->irq_refcount++ == 0) 160224edb884SFrançois Tigeot gen5_enable_gt_irq(dev_priv, ring->irq_enable_mask); 16035e269720SFrançois Tigeot spin_unlock_irqrestore(&dev_priv->irq_lock, flags); 1604e3adcf8fSFrançois Tigeot 1605e3adcf8fSFrançois Tigeot return true; 1606e3adcf8fSFrançois Tigeot } 1607e3adcf8fSFrançois Tigeot 1608e3adcf8fSFrançois Tigeot static void 1609ba55f2f5SFrançois Tigeot gen5_ring_put_irq(struct intel_engine_cs *ring) 1610e3adcf8fSFrançois Tigeot { 1611e3adcf8fSFrançois Tigeot struct drm_device *dev = ring->dev; 1612ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 16135e269720SFrançois Tigeot unsigned long flags; 1614e3adcf8fSFrançois Tigeot 16155e269720SFrançois Tigeot spin_lock_irqsave(&dev_priv->irq_lock, flags); 16169edbd4a0SFrançois Tigeot if (--ring->irq_refcount == 0) 161724edb884SFrançois Tigeot gen5_disable_gt_irq(dev_priv, ring->irq_enable_mask); 16185e269720SFrançois Tigeot spin_unlock_irqrestore(&dev_priv->irq_lock, flags); 1619686a02f1SFrançois Tigeot } 1620686a02f1SFrançois Tigeot 1621686a02f1SFrançois Tigeot static bool 1622ba55f2f5SFrançois Tigeot i9xx_ring_get_irq(struct intel_engine_cs *ring) 1623686a02f1SFrançois Tigeot { 1624686a02f1SFrançois Tigeot struct drm_device *dev = ring->dev; 1625ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 16265e269720SFrançois Tigeot unsigned long flags; 1627686a02f1SFrançois Tigeot 16282c9916cdSFrançois Tigeot if (!intel_irqs_enabled(dev_priv)) 1629686a02f1SFrançois Tigeot return false; 1630686a02f1SFrançois Tigeot 16315e269720SFrançois Tigeot spin_lock_irqsave(&dev_priv->irq_lock, flags); 16329edbd4a0SFrançois Tigeot if (ring->irq_refcount++ == 0) { 1633686a02f1SFrançois Tigeot dev_priv->irq_mask &= ~ring->irq_enable_mask; 1634686a02f1SFrançois Tigeot I915_WRITE(IMR, dev_priv->irq_mask); 1635686a02f1SFrançois Tigeot POSTING_READ(IMR); 1636686a02f1SFrançois Tigeot } 16375e269720SFrançois Tigeot spin_unlock_irqrestore(&dev_priv->irq_lock, flags); 1638686a02f1SFrançois Tigeot 1639686a02f1SFrançois Tigeot return true; 1640686a02f1SFrançois Tigeot } 1641686a02f1SFrançois Tigeot 1642686a02f1SFrançois Tigeot static void 1643ba55f2f5SFrançois Tigeot i9xx_ring_put_irq(struct intel_engine_cs *ring) 1644686a02f1SFrançois Tigeot { 1645686a02f1SFrançois Tigeot struct drm_device *dev = ring->dev; 1646ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 16475e269720SFrançois Tigeot unsigned long flags; 1648686a02f1SFrançois Tigeot 16495e269720SFrançois Tigeot spin_lock_irqsave(&dev_priv->irq_lock, flags); 16509edbd4a0SFrançois Tigeot if (--ring->irq_refcount == 0) { 1651686a02f1SFrançois Tigeot dev_priv->irq_mask |= ring->irq_enable_mask; 1652686a02f1SFrançois Tigeot I915_WRITE(IMR, dev_priv->irq_mask); 1653686a02f1SFrançois Tigeot POSTING_READ(IMR); 1654686a02f1SFrançois Tigeot } 16555e269720SFrançois Tigeot spin_unlock_irqrestore(&dev_priv->irq_lock, flags); 1656686a02f1SFrançois Tigeot } 1657686a02f1SFrançois Tigeot 1658686a02f1SFrançois Tigeot static bool 1659ba55f2f5SFrançois Tigeot i8xx_ring_get_irq(struct intel_engine_cs *ring) 1660686a02f1SFrançois Tigeot { 1661686a02f1SFrançois Tigeot struct drm_device *dev = ring->dev; 1662ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 16635e269720SFrançois Tigeot unsigned long flags; 1664686a02f1SFrançois Tigeot 16652c9916cdSFrançois Tigeot if (!intel_irqs_enabled(dev_priv)) 1666686a02f1SFrançois Tigeot return false; 1667686a02f1SFrançois Tigeot 16685e269720SFrançois Tigeot spin_lock_irqsave(&dev_priv->irq_lock, flags); 16699edbd4a0SFrançois Tigeot if (ring->irq_refcount++ == 0) { 1670686a02f1SFrançois Tigeot dev_priv->irq_mask &= ~ring->irq_enable_mask; 1671686a02f1SFrançois Tigeot I915_WRITE16(IMR, dev_priv->irq_mask); 1672686a02f1SFrançois Tigeot POSTING_READ16(IMR); 1673686a02f1SFrançois Tigeot } 16745e269720SFrançois Tigeot spin_unlock_irqrestore(&dev_priv->irq_lock, flags); 1675686a02f1SFrançois Tigeot 1676686a02f1SFrançois Tigeot return true; 1677686a02f1SFrançois Tigeot } 1678686a02f1SFrançois Tigeot 1679686a02f1SFrançois Tigeot static void 1680ba55f2f5SFrançois Tigeot i8xx_ring_put_irq(struct intel_engine_cs *ring) 1681686a02f1SFrançois Tigeot { 1682686a02f1SFrançois Tigeot struct drm_device *dev = ring->dev; 1683ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 16845e269720SFrançois Tigeot unsigned long flags; 1685686a02f1SFrançois Tigeot 16865e269720SFrançois Tigeot spin_lock_irqsave(&dev_priv->irq_lock, flags); 16879edbd4a0SFrançois Tigeot if (--ring->irq_refcount == 0) { 1688686a02f1SFrançois Tigeot dev_priv->irq_mask |= ring->irq_enable_mask; 1689686a02f1SFrançois Tigeot I915_WRITE16(IMR, dev_priv->irq_mask); 1690686a02f1SFrançois Tigeot POSTING_READ16(IMR); 1691e3adcf8fSFrançois Tigeot } 16925e269720SFrançois Tigeot spin_unlock_irqrestore(&dev_priv->irq_lock, flags); 1693e3adcf8fSFrançois Tigeot } 1694e3adcf8fSFrançois Tigeot 1695e3adcf8fSFrançois Tigeot static int 1696a05eeebfSFrançois Tigeot bsd_ring_flush(struct drm_i915_gem_request *req, 1697b5c29a34SFrançois Tigeot u32 invalidate_domains, 1698b5c29a34SFrançois Tigeot u32 flush_domains) 1699e3adcf8fSFrançois Tigeot { 1700a05eeebfSFrançois Tigeot struct intel_engine_cs *ring = req->ring; 1701e3adcf8fSFrançois Tigeot int ret; 1702e3adcf8fSFrançois Tigeot 1703a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 2); 1704e3adcf8fSFrançois Tigeot if (ret) 1705e3adcf8fSFrançois Tigeot return ret; 1706e3adcf8fSFrançois Tigeot 1707e3adcf8fSFrançois Tigeot intel_ring_emit(ring, MI_FLUSH); 1708e3adcf8fSFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 1709e3adcf8fSFrançois Tigeot intel_ring_advance(ring); 1710e3adcf8fSFrançois Tigeot return 0; 1711e3adcf8fSFrançois Tigeot } 1712e3adcf8fSFrançois Tigeot 1713e3adcf8fSFrançois Tigeot static int 1714a05eeebfSFrançois Tigeot i9xx_add_request(struct drm_i915_gem_request *req) 1715e3adcf8fSFrançois Tigeot { 1716a05eeebfSFrançois Tigeot struct intel_engine_cs *ring = req->ring; 1717e3adcf8fSFrançois Tigeot int ret; 1718e3adcf8fSFrançois Tigeot 1719a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 4); 1720e3adcf8fSFrançois Tigeot if (ret) 1721e3adcf8fSFrançois Tigeot return ret; 1722e3adcf8fSFrançois Tigeot 1723e3adcf8fSFrançois Tigeot intel_ring_emit(ring, MI_STORE_DWORD_INDEX); 1724e3adcf8fSFrançois Tigeot intel_ring_emit(ring, I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT); 1725a05eeebfSFrançois Tigeot intel_ring_emit(ring, i915_gem_request_get_seqno(req)); 1726e3adcf8fSFrançois Tigeot intel_ring_emit(ring, MI_USER_INTERRUPT); 17279edbd4a0SFrançois Tigeot __intel_ring_advance(ring); 1728e3adcf8fSFrançois Tigeot 1729e3adcf8fSFrançois Tigeot return 0; 1730e3adcf8fSFrançois Tigeot } 1731e3adcf8fSFrançois Tigeot 1732e3adcf8fSFrançois Tigeot static bool 1733ba55f2f5SFrançois Tigeot gen6_ring_get_irq(struct intel_engine_cs *ring) 1734e3adcf8fSFrançois Tigeot { 1735e3adcf8fSFrançois Tigeot struct drm_device *dev = ring->dev; 1736ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 17375e269720SFrançois Tigeot unsigned long flags; 1738e3adcf8fSFrançois Tigeot 17392c9916cdSFrançois Tigeot if (WARN_ON(!intel_irqs_enabled(dev_priv))) 1740e3adcf8fSFrançois Tigeot return false; 1741e3adcf8fSFrançois Tigeot 17425e269720SFrançois Tigeot spin_lock_irqsave(&dev_priv->irq_lock, flags); 17439edbd4a0SFrançois Tigeot if (ring->irq_refcount++ == 0) { 17449edbd4a0SFrançois Tigeot if (HAS_L3_DPF(dev) && ring->id == RCS) 17455d0b1887SFrançois Tigeot I915_WRITE_IMR(ring, 17465d0b1887SFrançois Tigeot ~(ring->irq_enable_mask | 17479edbd4a0SFrançois Tigeot GT_PARITY_ERROR(dev))); 1748686a02f1SFrançois Tigeot else 1749686a02f1SFrançois Tigeot I915_WRITE_IMR(ring, ~ring->irq_enable_mask); 175024edb884SFrançois Tigeot gen5_enable_gt_irq(dev_priv, ring->irq_enable_mask); 1751e3adcf8fSFrançois Tigeot } 17525e269720SFrançois Tigeot spin_unlock_irqrestore(&dev_priv->irq_lock, flags); 1753e3adcf8fSFrançois Tigeot 1754e3adcf8fSFrançois Tigeot return true; 1755e3adcf8fSFrançois Tigeot } 1756e3adcf8fSFrançois Tigeot 1757e3adcf8fSFrançois Tigeot static void 1758ba55f2f5SFrançois Tigeot gen6_ring_put_irq(struct intel_engine_cs *ring) 1759e3adcf8fSFrançois Tigeot { 1760e3adcf8fSFrançois Tigeot struct drm_device *dev = ring->dev; 1761ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 17625e269720SFrançois Tigeot unsigned long flags; 1763e3adcf8fSFrançois Tigeot 17645e269720SFrançois Tigeot spin_lock_irqsave(&dev_priv->irq_lock, flags); 17659edbd4a0SFrançois Tigeot if (--ring->irq_refcount == 0) { 17669edbd4a0SFrançois Tigeot if (HAS_L3_DPF(dev) && ring->id == RCS) 17679edbd4a0SFrançois Tigeot I915_WRITE_IMR(ring, ~GT_PARITY_ERROR(dev)); 1768686a02f1SFrançois Tigeot else 1769686a02f1SFrançois Tigeot I915_WRITE_IMR(ring, ~0); 177024edb884SFrançois Tigeot gen5_disable_gt_irq(dev_priv, ring->irq_enable_mask); 1771e3adcf8fSFrançois Tigeot } 17725e269720SFrançois Tigeot spin_unlock_irqrestore(&dev_priv->irq_lock, flags); 1773e3adcf8fSFrançois Tigeot } 1774e3adcf8fSFrançois Tigeot 17755d0b1887SFrançois Tigeot static bool 1776ba55f2f5SFrançois Tigeot hsw_vebox_get_irq(struct intel_engine_cs *ring) 17775d0b1887SFrançois Tigeot { 17785d0b1887SFrançois Tigeot struct drm_device *dev = ring->dev; 17795d0b1887SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 17805e269720SFrançois Tigeot unsigned long flags; 17815d0b1887SFrançois Tigeot 17822c9916cdSFrançois Tigeot if (WARN_ON(!intel_irqs_enabled(dev_priv))) 17835d0b1887SFrançois Tigeot return false; 17845d0b1887SFrançois Tigeot 17855e269720SFrançois Tigeot spin_lock_irqsave(&dev_priv->irq_lock, flags); 17869edbd4a0SFrançois Tigeot if (ring->irq_refcount++ == 0) { 17875d0b1887SFrançois Tigeot I915_WRITE_IMR(ring, ~ring->irq_enable_mask); 178824edb884SFrançois Tigeot gen6_enable_pm_irq(dev_priv, ring->irq_enable_mask); 17895d0b1887SFrançois Tigeot } 17905e269720SFrançois Tigeot spin_unlock_irqrestore(&dev_priv->irq_lock, flags); 17915d0b1887SFrançois Tigeot 17925d0b1887SFrançois Tigeot return true; 17935d0b1887SFrançois Tigeot } 17945d0b1887SFrançois Tigeot 17955d0b1887SFrançois Tigeot static void 1796ba55f2f5SFrançois Tigeot hsw_vebox_put_irq(struct intel_engine_cs *ring) 17975d0b1887SFrançois Tigeot { 17985d0b1887SFrançois Tigeot struct drm_device *dev = ring->dev; 17995d0b1887SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 18005e269720SFrançois Tigeot unsigned long flags; 18015d0b1887SFrançois Tigeot 18025e269720SFrançois Tigeot spin_lock_irqsave(&dev_priv->irq_lock, flags); 18039edbd4a0SFrançois Tigeot if (--ring->irq_refcount == 0) { 18045d0b1887SFrançois Tigeot I915_WRITE_IMR(ring, ~0); 180524edb884SFrançois Tigeot gen6_disable_pm_irq(dev_priv, ring->irq_enable_mask); 18065d0b1887SFrançois Tigeot } 18075e269720SFrançois Tigeot spin_unlock_irqrestore(&dev_priv->irq_lock, flags); 18089edbd4a0SFrançois Tigeot } 18099edbd4a0SFrançois Tigeot 18109edbd4a0SFrançois Tigeot static bool 1811ba55f2f5SFrançois Tigeot gen8_ring_get_irq(struct intel_engine_cs *ring) 18129edbd4a0SFrançois Tigeot { 18139edbd4a0SFrançois Tigeot struct drm_device *dev = ring->dev; 18149edbd4a0SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 18155e269720SFrançois Tigeot unsigned long flags; 18169edbd4a0SFrançois Tigeot 18172c9916cdSFrançois Tigeot if (WARN_ON(!intel_irqs_enabled(dev_priv))) 18189edbd4a0SFrançois Tigeot return false; 18199edbd4a0SFrançois Tigeot 18205e269720SFrançois Tigeot spin_lock_irqsave(&dev_priv->irq_lock, flags); 18219edbd4a0SFrançois Tigeot if (ring->irq_refcount++ == 0) { 18229edbd4a0SFrançois Tigeot if (HAS_L3_DPF(dev) && ring->id == RCS) { 18239edbd4a0SFrançois Tigeot I915_WRITE_IMR(ring, 18249edbd4a0SFrançois Tigeot ~(ring->irq_enable_mask | 18259edbd4a0SFrançois Tigeot GT_RENDER_L3_PARITY_ERROR_INTERRUPT)); 18269edbd4a0SFrançois Tigeot } else { 18279edbd4a0SFrançois Tigeot I915_WRITE_IMR(ring, ~ring->irq_enable_mask); 18289edbd4a0SFrançois Tigeot } 18299edbd4a0SFrançois Tigeot POSTING_READ(RING_IMR(ring->mmio_base)); 18309edbd4a0SFrançois Tigeot } 18315e269720SFrançois Tigeot spin_unlock_irqrestore(&dev_priv->irq_lock, flags); 18329edbd4a0SFrançois Tigeot 18339edbd4a0SFrançois Tigeot return true; 18349edbd4a0SFrançois Tigeot } 18359edbd4a0SFrançois Tigeot 18369edbd4a0SFrançois Tigeot static void 1837ba55f2f5SFrançois Tigeot gen8_ring_put_irq(struct intel_engine_cs *ring) 18389edbd4a0SFrançois Tigeot { 18399edbd4a0SFrançois Tigeot struct drm_device *dev = ring->dev; 18409edbd4a0SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 18415e269720SFrançois Tigeot unsigned long flags; 18429edbd4a0SFrançois Tigeot 18435e269720SFrançois Tigeot spin_lock_irqsave(&dev_priv->irq_lock, flags); 18449edbd4a0SFrançois Tigeot if (--ring->irq_refcount == 0) { 18459edbd4a0SFrançois Tigeot if (HAS_L3_DPF(dev) && ring->id == RCS) { 18469edbd4a0SFrançois Tigeot I915_WRITE_IMR(ring, 18479edbd4a0SFrançois Tigeot ~GT_RENDER_L3_PARITY_ERROR_INTERRUPT); 18489edbd4a0SFrançois Tigeot } else { 18499edbd4a0SFrançois Tigeot I915_WRITE_IMR(ring, ~0); 18509edbd4a0SFrançois Tigeot } 18519edbd4a0SFrançois Tigeot POSTING_READ(RING_IMR(ring->mmio_base)); 18529edbd4a0SFrançois Tigeot } 18535e269720SFrançois Tigeot spin_unlock_irqrestore(&dev_priv->irq_lock, flags); 18545d0b1887SFrançois Tigeot } 18555d0b1887SFrançois Tigeot 1856e3adcf8fSFrançois Tigeot static int 1857a05eeebfSFrançois Tigeot i965_dispatch_execbuffer(struct drm_i915_gem_request *req, 1858ba55f2f5SFrançois Tigeot u64 offset, u32 length, 1859477eb7f9SFrançois Tigeot unsigned dispatch_flags) 1860e3adcf8fSFrançois Tigeot { 1861a05eeebfSFrançois Tigeot struct intel_engine_cs *ring = req->ring; 1862e3adcf8fSFrançois Tigeot int ret; 1863e3adcf8fSFrançois Tigeot 1864a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 2); 1865e3adcf8fSFrançois Tigeot if (ret) 1866e3adcf8fSFrançois Tigeot return ret; 1867e3adcf8fSFrançois Tigeot 1868e3adcf8fSFrançois Tigeot intel_ring_emit(ring, 1869686a02f1SFrançois Tigeot MI_BATCH_BUFFER_START | 1870b5c29a34SFrançois Tigeot MI_BATCH_GTT | 1871477eb7f9SFrançois Tigeot (dispatch_flags & I915_DISPATCH_SECURE ? 1872477eb7f9SFrançois Tigeot 0 : MI_BATCH_NON_SECURE_I965)); 1873e3adcf8fSFrançois Tigeot intel_ring_emit(ring, offset); 1874e3adcf8fSFrançois Tigeot intel_ring_advance(ring); 1875e3adcf8fSFrançois Tigeot 1876e3adcf8fSFrançois Tigeot return 0; 1877e3adcf8fSFrançois Tigeot } 1878e3adcf8fSFrançois Tigeot 1879b5c29a34SFrançois Tigeot /* Just userspace ABI convention to limit the wa batch bo to a resonable size */ 1880b5c29a34SFrançois Tigeot #define I830_BATCH_LIMIT (256*1024) 188124edb884SFrançois Tigeot #define I830_TLB_ENTRIES (2) 188224edb884SFrançois Tigeot #define I830_WA_SIZE max(I830_TLB_ENTRIES*4096, I830_BATCH_LIMIT) 1883e3adcf8fSFrançois Tigeot static int 1884a05eeebfSFrançois Tigeot i830_dispatch_execbuffer(struct drm_i915_gem_request *req, 1885ba55f2f5SFrançois Tigeot u64 offset, u32 len, 1886477eb7f9SFrançois Tigeot unsigned dispatch_flags) 1887e3adcf8fSFrançois Tigeot { 1888a05eeebfSFrançois Tigeot struct intel_engine_cs *ring = req->ring; 188924edb884SFrançois Tigeot u32 cs_offset = ring->scratch.gtt_offset; 1890e3adcf8fSFrançois Tigeot int ret; 1891e3adcf8fSFrançois Tigeot 1892a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 6); 189324edb884SFrançois Tigeot if (ret) 189424edb884SFrançois Tigeot return ret; 189524edb884SFrançois Tigeot 189624edb884SFrançois Tigeot /* Evict the invalid PTE TLBs */ 189724edb884SFrançois Tigeot intel_ring_emit(ring, COLOR_BLT_CMD | BLT_WRITE_RGBA); 189824edb884SFrançois Tigeot intel_ring_emit(ring, BLT_DEPTH_32 | BLT_ROP_COLOR_COPY | 4096); 189924edb884SFrançois Tigeot intel_ring_emit(ring, I830_TLB_ENTRIES << 16 | 4); /* load each page */ 190024edb884SFrançois Tigeot intel_ring_emit(ring, cs_offset); 190124edb884SFrançois Tigeot intel_ring_emit(ring, 0xdeadbeef); 190224edb884SFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 190324edb884SFrançois Tigeot intel_ring_advance(ring); 190424edb884SFrançois Tigeot 1905477eb7f9SFrançois Tigeot if ((dispatch_flags & I915_DISPATCH_PINNED) == 0) { 190624edb884SFrançois Tigeot if (len > I830_BATCH_LIMIT) 190724edb884SFrançois Tigeot return -ENOSPC; 190824edb884SFrançois Tigeot 1909a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 6 + 2); 191024edb884SFrançois Tigeot if (ret) 191124edb884SFrançois Tigeot return ret; 191224edb884SFrançois Tigeot 191324edb884SFrançois Tigeot /* Blit the batch (which has now all relocs applied) to the 191424edb884SFrançois Tigeot * stable batch scratch bo area (so that the CS never 191524edb884SFrançois Tigeot * stumbles over its tlb invalidation bug) ... 191624edb884SFrançois Tigeot */ 191724edb884SFrançois Tigeot intel_ring_emit(ring, SRC_COPY_BLT_CMD | BLT_WRITE_RGBA); 191824edb884SFrançois Tigeot intel_ring_emit(ring, BLT_DEPTH_32 | BLT_ROP_SRC_COPY | 4096); 191924edb884SFrançois Tigeot intel_ring_emit(ring, DIV_ROUND_UP(len, 4096) << 16 | 4096); 192024edb884SFrançois Tigeot intel_ring_emit(ring, cs_offset); 192124edb884SFrançois Tigeot intel_ring_emit(ring, 4096); 192224edb884SFrançois Tigeot intel_ring_emit(ring, offset); 192324edb884SFrançois Tigeot 192424edb884SFrançois Tigeot intel_ring_emit(ring, MI_FLUSH); 192524edb884SFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 192624edb884SFrançois Tigeot intel_ring_advance(ring); 192724edb884SFrançois Tigeot 192824edb884SFrançois Tigeot /* ... and execute it. */ 192924edb884SFrançois Tigeot offset = cs_offset; 193024edb884SFrançois Tigeot } 193124edb884SFrançois Tigeot 1932*c0e85e96SFrançois Tigeot ret = intel_ring_begin(req, 2); 1933e3adcf8fSFrançois Tigeot if (ret) 1934e3adcf8fSFrançois Tigeot return ret; 1935e3adcf8fSFrançois Tigeot 1936*c0e85e96SFrançois Tigeot intel_ring_emit(ring, MI_BATCH_BUFFER_START | MI_BATCH_GTT); 1937477eb7f9SFrançois Tigeot intel_ring_emit(ring, offset | (dispatch_flags & I915_DISPATCH_SECURE ? 1938477eb7f9SFrançois Tigeot 0 : MI_BATCH_NON_SECURE)); 1939686a02f1SFrançois Tigeot intel_ring_advance(ring); 1940686a02f1SFrançois Tigeot 1941686a02f1SFrançois Tigeot return 0; 1942686a02f1SFrançois Tigeot } 1943686a02f1SFrançois Tigeot 1944686a02f1SFrançois Tigeot static int 1945a05eeebfSFrançois Tigeot i915_dispatch_execbuffer(struct drm_i915_gem_request *req, 1946ba55f2f5SFrançois Tigeot u64 offset, u32 len, 1947477eb7f9SFrançois Tigeot unsigned dispatch_flags) 1948686a02f1SFrançois Tigeot { 1949a05eeebfSFrançois Tigeot struct intel_engine_cs *ring = req->ring; 1950686a02f1SFrançois Tigeot int ret; 1951686a02f1SFrançois Tigeot 1952a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 2); 1953e3adcf8fSFrançois Tigeot if (ret) 1954e3adcf8fSFrançois Tigeot return ret; 1955e3adcf8fSFrançois Tigeot 1956686a02f1SFrançois Tigeot intel_ring_emit(ring, MI_BATCH_BUFFER_START | MI_BATCH_GTT); 1957477eb7f9SFrançois Tigeot intel_ring_emit(ring, offset | (dispatch_flags & I915_DISPATCH_SECURE ? 1958477eb7f9SFrançois Tigeot 0 : MI_BATCH_NON_SECURE)); 1959e3adcf8fSFrançois Tigeot intel_ring_advance(ring); 1960e3adcf8fSFrançois Tigeot 1961e3adcf8fSFrançois Tigeot return 0; 1962e3adcf8fSFrançois Tigeot } 1963e3adcf8fSFrançois Tigeot 1964*c0e85e96SFrançois Tigeot static void cleanup_phys_status_page(struct intel_engine_cs *ring) 1965*c0e85e96SFrançois Tigeot { 1966*c0e85e96SFrançois Tigeot struct drm_i915_private *dev_priv = to_i915(ring->dev); 1967*c0e85e96SFrançois Tigeot 1968*c0e85e96SFrançois Tigeot if (!dev_priv->status_page_dmah) 1969*c0e85e96SFrançois Tigeot return; 1970*c0e85e96SFrançois Tigeot 1971*c0e85e96SFrançois Tigeot drm_pci_free(ring->dev, dev_priv->status_page_dmah); 1972*c0e85e96SFrançois Tigeot ring->status_page.page_addr = NULL; 1973*c0e85e96SFrançois Tigeot } 1974*c0e85e96SFrançois Tigeot 1975ba55f2f5SFrançois Tigeot static void cleanup_status_page(struct intel_engine_cs *ring) 1976e3adcf8fSFrançois Tigeot { 1977e3adcf8fSFrançois Tigeot struct drm_i915_gem_object *obj; 1978e3adcf8fSFrançois Tigeot 1979e3adcf8fSFrançois Tigeot obj = ring->status_page.obj; 1980e3adcf8fSFrançois Tigeot if (obj == NULL) 1981e3adcf8fSFrançois Tigeot return; 1982e3adcf8fSFrançois Tigeot 19837ec9f8e5SFrançois Tigeot kunmap(sg_page(obj->pages->sgl)); 1984ba55f2f5SFrançois Tigeot i915_gem_object_ggtt_unpin(obj); 1985e3adcf8fSFrançois Tigeot drm_gem_object_unreference(&obj->base); 1986e3adcf8fSFrançois Tigeot ring->status_page.obj = NULL; 1987e3adcf8fSFrançois Tigeot } 1988e3adcf8fSFrançois Tigeot 1989ba55f2f5SFrançois Tigeot static int init_status_page(struct intel_engine_cs *ring) 1990e3adcf8fSFrançois Tigeot { 1991*c0e85e96SFrançois Tigeot struct drm_i915_gem_object *obj = ring->status_page.obj; 1992ba55f2f5SFrançois Tigeot 1993*c0e85e96SFrançois Tigeot if (obj == NULL) { 199424edb884SFrançois Tigeot unsigned flags; 1995e3adcf8fSFrançois Tigeot int ret; 1996e3adcf8fSFrançois Tigeot 1997ba55f2f5SFrançois Tigeot obj = i915_gem_alloc_object(ring->dev, 4096); 1998e3adcf8fSFrançois Tigeot if (obj == NULL) { 1999e3adcf8fSFrançois Tigeot DRM_ERROR("Failed to allocate status page\n"); 2000ba55f2f5SFrançois Tigeot return -ENOMEM; 2001e3adcf8fSFrançois Tigeot } 2002e3adcf8fSFrançois Tigeot 2003ba55f2f5SFrançois Tigeot ret = i915_gem_object_set_cache_level(obj, I915_CACHE_LLC); 2004ba55f2f5SFrançois Tigeot if (ret) 2005e3adcf8fSFrançois Tigeot goto err_unref; 2006ba55f2f5SFrançois Tigeot 200724edb884SFrançois Tigeot flags = 0; 200824edb884SFrançois Tigeot if (!HAS_LLC(ring->dev)) 200924edb884SFrançois Tigeot /* On g33, we cannot place HWS above 256MiB, so 201024edb884SFrançois Tigeot * restrict its pinning to the low mappable arena. 201124edb884SFrançois Tigeot * Though this restriction is not documented for 201224edb884SFrançois Tigeot * gen4, gen5, or byt, they also behave similarly 201324edb884SFrançois Tigeot * and hang if the HWS is placed at the top of the 201424edb884SFrançois Tigeot * GTT. To generalise, it appears that all !llc 201524edb884SFrançois Tigeot * platforms have issues with us placing the HWS 201624edb884SFrançois Tigeot * above the mappable region (even though we never 201724edb884SFrançois Tigeot * actualy map it). 201824edb884SFrançois Tigeot */ 201924edb884SFrançois Tigeot flags |= PIN_MAPPABLE; 202024edb884SFrançois Tigeot ret = i915_gem_obj_ggtt_pin(obj, 4096, flags); 2021ba55f2f5SFrançois Tigeot if (ret) { 2022ba55f2f5SFrançois Tigeot err_unref: 2023ba55f2f5SFrançois Tigeot drm_gem_object_unreference(&obj->base); 2024ba55f2f5SFrançois Tigeot return ret; 2025ba55f2f5SFrançois Tigeot } 2026ba55f2f5SFrançois Tigeot 2027ba55f2f5SFrançois Tigeot ring->status_page.obj = obj; 2028e3adcf8fSFrançois Tigeot } 2029e3adcf8fSFrançois Tigeot 20309edbd4a0SFrançois Tigeot ring->status_page.gfx_addr = i915_gem_obj_ggtt_offset(obj); 20317ec9f8e5SFrançois Tigeot ring->status_page.page_addr = kmap(sg_page(obj->pages->sgl)); 2032e3adcf8fSFrançois Tigeot memset(ring->status_page.page_addr, 0, PAGE_SIZE); 2033e3adcf8fSFrançois Tigeot 2034b5c29a34SFrançois Tigeot DRM_DEBUG_DRIVER("%s hws offset: 0x%08x\n", 2035e3adcf8fSFrançois Tigeot ring->name, ring->status_page.gfx_addr); 2036e3adcf8fSFrançois Tigeot 2037e3adcf8fSFrançois Tigeot return 0; 2038e3adcf8fSFrançois Tigeot } 2039e3adcf8fSFrançois Tigeot 2040ba55f2f5SFrançois Tigeot static int init_phys_status_page(struct intel_engine_cs *ring) 2041686a02f1SFrançois Tigeot { 2042686a02f1SFrançois Tigeot struct drm_i915_private *dev_priv = ring->dev->dev_private; 2043686a02f1SFrançois Tigeot 2044686a02f1SFrançois Tigeot if (!dev_priv->status_page_dmah) { 2045686a02f1SFrançois Tigeot dev_priv->status_page_dmah = 2046b31e9d59SFrançois Tigeot drm_pci_alloc(ring->dev, PAGE_SIZE, PAGE_SIZE); 2047686a02f1SFrançois Tigeot if (!dev_priv->status_page_dmah) 2048686a02f1SFrançois Tigeot return -ENOMEM; 2049686a02f1SFrançois Tigeot } 2050686a02f1SFrançois Tigeot 2051686a02f1SFrançois Tigeot ring->status_page.page_addr = dev_priv->status_page_dmah->vaddr; 2052686a02f1SFrançois Tigeot memset(ring->status_page.page_addr, 0, PAGE_SIZE); 2053686a02f1SFrançois Tigeot 2054686a02f1SFrançois Tigeot return 0; 2055686a02f1SFrançois Tigeot } 2056686a02f1SFrançois Tigeot 20572c9916cdSFrançois Tigeot void intel_unpin_ringbuffer_obj(struct intel_ringbuffer *ringbuf) 20582c9916cdSFrançois Tigeot { 2059aee94f86SFrançois Tigeot if (HAS_LLC(ringbuf->obj->base.dev) && !ringbuf->obj->stolen) 20606fe294aeSMatthew Dillon vunmap(ringbuf->virtual_start, ringbuf->virtual_count); 2061aee94f86SFrançois Tigeot else 206224409b39SFrançois Tigeot iounmap(ringbuf->virtual_start); 20632c9916cdSFrançois Tigeot ringbuf->virtual_start = NULL; 2064*c0e85e96SFrançois Tigeot ringbuf->vma = NULL; 20652c9916cdSFrançois Tigeot i915_gem_object_ggtt_unpin(ringbuf->obj); 20662c9916cdSFrançois Tigeot } 20672c9916cdSFrançois Tigeot 20686fe294aeSMatthew Dillon static u32 *vmap_obj(struct drm_i915_gem_object *obj, unsigned int *countp) 2069aee94f86SFrançois Tigeot { 2070aee94f86SFrançois Tigeot struct sg_page_iter sg_iter; 2071aee94f86SFrançois Tigeot struct vm_page **pages; 2072aee94f86SFrançois Tigeot void *addr; 2073aee94f86SFrançois Tigeot int i; 2074aee94f86SFrançois Tigeot 2075aee94f86SFrançois Tigeot pages = drm_malloc_ab(obj->base.size >> PAGE_SHIFT, sizeof(*pages)); 2076aee94f86SFrançois Tigeot if (pages == NULL) 2077aee94f86SFrançois Tigeot return NULL; 2078aee94f86SFrançois Tigeot 2079aee94f86SFrançois Tigeot i = 0; 2080aee94f86SFrançois Tigeot for_each_sg_page(obj->pages->sgl, &sg_iter, obj->pages->nents, 0) 2081aee94f86SFrançois Tigeot pages[i++] = sg_page_iter_page(&sg_iter); 20826fe294aeSMatthew Dillon *countp = i; 2083aee94f86SFrançois Tigeot 2084aee94f86SFrançois Tigeot addr = vmap(pages, i, 0, PAGE_KERNEL); 2085aee94f86SFrançois Tigeot drm_free_large(pages); 2086aee94f86SFrançois Tigeot 2087aee94f86SFrançois Tigeot return addr; 2088aee94f86SFrançois Tigeot } 2089aee94f86SFrançois Tigeot 20902c9916cdSFrançois Tigeot int intel_pin_and_map_ringbuffer_obj(struct drm_device *dev, 20912c9916cdSFrançois Tigeot struct intel_ringbuffer *ringbuf) 20922c9916cdSFrançois Tigeot { 20932c9916cdSFrançois Tigeot struct drm_i915_private *dev_priv = to_i915(dev); 20942c9916cdSFrançois Tigeot struct drm_i915_gem_object *obj = ringbuf->obj; 2095*c0e85e96SFrançois Tigeot /* Ring wraparound at offset 0 sometimes hangs. No idea why. */ 2096*c0e85e96SFrançois Tigeot unsigned flags = PIN_OFFSET_BIAS | 4096; 20972c9916cdSFrançois Tigeot int ret; 20982c9916cdSFrançois Tigeot 2099aee94f86SFrançois Tigeot if (HAS_LLC(dev_priv) && !obj->stolen) { 2100*c0e85e96SFrançois Tigeot ret = i915_gem_obj_ggtt_pin(obj, PAGE_SIZE, flags); 2101aee94f86SFrançois Tigeot if (ret) 2102aee94f86SFrançois Tigeot return ret; 2103aee94f86SFrançois Tigeot 2104aee94f86SFrançois Tigeot ret = i915_gem_object_set_to_cpu_domain(obj, true); 2105aee94f86SFrançois Tigeot if (ret) { 2106aee94f86SFrançois Tigeot i915_gem_object_ggtt_unpin(obj); 2107aee94f86SFrançois Tigeot return ret; 2108aee94f86SFrançois Tigeot } 2109aee94f86SFrançois Tigeot 21106fe294aeSMatthew Dillon ringbuf->virtual_start = (char *)vmap_obj(obj, 21116fe294aeSMatthew Dillon &ringbuf->virtual_count); 2112aee94f86SFrançois Tigeot if (ringbuf->virtual_start == NULL) { 2113aee94f86SFrançois Tigeot i915_gem_object_ggtt_unpin(obj); 2114aee94f86SFrançois Tigeot return -ENOMEM; 2115aee94f86SFrançois Tigeot } 2116aee94f86SFrançois Tigeot } else { 2117*c0e85e96SFrançois Tigeot ret = i915_gem_obj_ggtt_pin(obj, PAGE_SIZE, 2118*c0e85e96SFrançois Tigeot flags | PIN_MAPPABLE); 21192c9916cdSFrançois Tigeot if (ret) 21202c9916cdSFrançois Tigeot return ret; 21212c9916cdSFrançois Tigeot 21222c9916cdSFrançois Tigeot ret = i915_gem_object_set_to_gtt_domain(obj, true); 21232c9916cdSFrançois Tigeot if (ret) { 21242c9916cdSFrançois Tigeot i915_gem_object_ggtt_unpin(obj); 21252c9916cdSFrançois Tigeot return ret; 21262c9916cdSFrançois Tigeot } 21272c9916cdSFrançois Tigeot 2128*c0e85e96SFrançois Tigeot /* Access through the GTT requires the device to be awake. */ 2129*c0e85e96SFrançois Tigeot assert_rpm_wakelock_held(dev_priv); 2130*c0e85e96SFrançois Tigeot 21312c9916cdSFrançois Tigeot ringbuf->virtual_start = ioremap_wc(dev_priv->gtt.mappable_base + 21322c9916cdSFrançois Tigeot i915_gem_obj_ggtt_offset(obj), ringbuf->size); 21332c9916cdSFrançois Tigeot if (ringbuf->virtual_start == NULL) { 21342c9916cdSFrançois Tigeot i915_gem_object_ggtt_unpin(obj); 21352c9916cdSFrançois Tigeot return -EINVAL; 21362c9916cdSFrançois Tigeot } 2137aee94f86SFrançois Tigeot } 21382c9916cdSFrançois Tigeot 2139*c0e85e96SFrançois Tigeot ringbuf->vma = i915_gem_obj_to_ggtt(obj); 2140*c0e85e96SFrançois Tigeot 21412c9916cdSFrançois Tigeot return 0; 21422c9916cdSFrançois Tigeot } 21432c9916cdSFrançois Tigeot 2144352ff8bdSFrançois Tigeot static void intel_destroy_ringbuffer_obj(struct intel_ringbuffer *ringbuf) 2145e3adcf8fSFrançois Tigeot { 214624edb884SFrançois Tigeot drm_gem_object_unreference(&ringbuf->obj->base); 214724edb884SFrançois Tigeot ringbuf->obj = NULL; 214824edb884SFrançois Tigeot } 214924edb884SFrançois Tigeot 2150352ff8bdSFrançois Tigeot static int intel_alloc_ringbuffer_obj(struct drm_device *dev, 215124edb884SFrançois Tigeot struct intel_ringbuffer *ringbuf) 215224edb884SFrançois Tigeot { 2153e3adcf8fSFrançois Tigeot struct drm_i915_gem_object *obj; 2154e3adcf8fSFrançois Tigeot 2155a2fdbec6SFrançois Tigeot obj = NULL; 2156a2fdbec6SFrançois Tigeot if (!HAS_LLC(dev)) 2157ba55f2f5SFrançois Tigeot obj = i915_gem_object_create_stolen(dev, ringbuf->size); 2158a2fdbec6SFrançois Tigeot if (obj == NULL) 2159ba55f2f5SFrançois Tigeot obj = i915_gem_alloc_object(dev, ringbuf->size); 2160ba55f2f5SFrançois Tigeot if (obj == NULL) 2161ba55f2f5SFrançois Tigeot return -ENOMEM; 2162e3adcf8fSFrançois Tigeot 216324edb884SFrançois Tigeot /* mark ring buffers as read-only from GPU side by default */ 216424edb884SFrançois Tigeot obj->gt_ro = 1; 216524edb884SFrançois Tigeot 2166ba55f2f5SFrançois Tigeot ringbuf->obj = obj; 2167ba55f2f5SFrançois Tigeot 21682c9916cdSFrançois Tigeot return 0; 2169ba55f2f5SFrançois Tigeot } 2170ba55f2f5SFrançois Tigeot 2171352ff8bdSFrançois Tigeot struct intel_ringbuffer * 2172352ff8bdSFrançois Tigeot intel_engine_create_ringbuffer(struct intel_engine_cs *engine, int size) 2173352ff8bdSFrançois Tigeot { 2174352ff8bdSFrançois Tigeot struct intel_ringbuffer *ring; 2175352ff8bdSFrançois Tigeot int ret; 2176352ff8bdSFrançois Tigeot 2177352ff8bdSFrançois Tigeot ring = kzalloc(sizeof(*ring), GFP_KERNEL); 2178aee94f86SFrançois Tigeot if (ring == NULL) { 2179aee94f86SFrançois Tigeot DRM_DEBUG_DRIVER("Failed to allocate ringbuffer %s\n", 2180aee94f86SFrançois Tigeot engine->name); 2181352ff8bdSFrançois Tigeot return ERR_PTR(-ENOMEM); 2182aee94f86SFrançois Tigeot } 2183352ff8bdSFrançois Tigeot 2184352ff8bdSFrançois Tigeot ring->ring = engine; 2185aee94f86SFrançois Tigeot list_add(&ring->link, &engine->buffers); 2186352ff8bdSFrançois Tigeot 2187352ff8bdSFrançois Tigeot ring->size = size; 2188352ff8bdSFrançois Tigeot /* Workaround an erratum on the i830 which causes a hang if 2189352ff8bdSFrançois Tigeot * the TAIL pointer points to within the last 2 cachelines 2190352ff8bdSFrançois Tigeot * of the buffer. 2191352ff8bdSFrançois Tigeot */ 2192352ff8bdSFrançois Tigeot ring->effective_size = size; 2193352ff8bdSFrançois Tigeot if (IS_I830(engine->dev) || IS_845G(engine->dev)) 2194352ff8bdSFrançois Tigeot ring->effective_size -= 2 * CACHELINE_BYTES; 2195352ff8bdSFrançois Tigeot 2196352ff8bdSFrançois Tigeot ring->last_retired_head = -1; 2197352ff8bdSFrançois Tigeot intel_ring_update_space(ring); 2198352ff8bdSFrançois Tigeot 2199352ff8bdSFrançois Tigeot ret = intel_alloc_ringbuffer_obj(engine->dev, ring); 2200352ff8bdSFrançois Tigeot if (ret) { 2201aee94f86SFrançois Tigeot DRM_DEBUG_DRIVER("Failed to allocate ringbuffer %s: %d\n", 2202352ff8bdSFrançois Tigeot engine->name, ret); 2203aee94f86SFrançois Tigeot list_del(&ring->link); 2204352ff8bdSFrançois Tigeot kfree(ring); 2205352ff8bdSFrançois Tigeot return ERR_PTR(ret); 2206352ff8bdSFrançois Tigeot } 2207352ff8bdSFrançois Tigeot 2208352ff8bdSFrançois Tigeot return ring; 2209352ff8bdSFrançois Tigeot } 2210352ff8bdSFrançois Tigeot 2211352ff8bdSFrançois Tigeot void 2212352ff8bdSFrançois Tigeot intel_ringbuffer_free(struct intel_ringbuffer *ring) 2213352ff8bdSFrançois Tigeot { 2214352ff8bdSFrançois Tigeot intel_destroy_ringbuffer_obj(ring); 2215aee94f86SFrançois Tigeot list_del(&ring->link); 2216352ff8bdSFrançois Tigeot kfree(ring); 2217352ff8bdSFrançois Tigeot } 2218352ff8bdSFrançois Tigeot 2219ba55f2f5SFrançois Tigeot static int intel_init_ring_buffer(struct drm_device *dev, 2220ba55f2f5SFrançois Tigeot struct intel_engine_cs *ring) 2221ba55f2f5SFrançois Tigeot { 22222c9916cdSFrançois Tigeot struct intel_ringbuffer *ringbuf; 2223ba55f2f5SFrançois Tigeot int ret; 2224ba55f2f5SFrançois Tigeot 22252c9916cdSFrançois Tigeot WARN_ON(ring->buffer); 22262c9916cdSFrançois Tigeot 2227ba55f2f5SFrançois Tigeot ring->dev = dev; 2228ba55f2f5SFrançois Tigeot INIT_LIST_HEAD(&ring->active_list); 2229ba55f2f5SFrançois Tigeot INIT_LIST_HEAD(&ring->request_list); 22301b13d190SFrançois Tigeot INIT_LIST_HEAD(&ring->execlist_queue); 2231aee94f86SFrançois Tigeot INIT_LIST_HEAD(&ring->buffers); 223219c468b4SFrançois Tigeot i915_gem_batch_pool_init(dev, &ring->batch_pool); 2233ba55f2f5SFrançois Tigeot memset(ring->semaphore.sync_seqno, 0, sizeof(ring->semaphore.sync_seqno)); 2234ba55f2f5SFrançois Tigeot 2235ba55f2f5SFrançois Tigeot init_waitqueue_head(&ring->irq_queue); 2236ba55f2f5SFrançois Tigeot 2237352ff8bdSFrançois Tigeot ringbuf = intel_engine_create_ringbuffer(ring, 32 * PAGE_SIZE); 2238aee94f86SFrançois Tigeot if (IS_ERR(ringbuf)) { 2239aee94f86SFrançois Tigeot ret = PTR_ERR(ringbuf); 2240aee94f86SFrançois Tigeot goto error; 2241aee94f86SFrançois Tigeot } 2242352ff8bdSFrançois Tigeot ring->buffer = ringbuf; 2243352ff8bdSFrançois Tigeot 2244ba55f2f5SFrançois Tigeot if (I915_NEED_GFX_HWS(dev)) { 2245ba55f2f5SFrançois Tigeot ret = init_status_page(ring); 2246e3adcf8fSFrançois Tigeot if (ret) 2247ba55f2f5SFrançois Tigeot goto error; 2248ba55f2f5SFrançois Tigeot } else { 2249*c0e85e96SFrançois Tigeot WARN_ON(ring->id != RCS); 2250ba55f2f5SFrançois Tigeot ret = init_phys_status_page(ring); 2251ba55f2f5SFrançois Tigeot if (ret) 2252ba55f2f5SFrançois Tigeot goto error; 2253ba55f2f5SFrançois Tigeot } 2254ba55f2f5SFrançois Tigeot 22552c9916cdSFrançois Tigeot ret = intel_pin_and_map_ringbuffer_obj(dev, ringbuf); 22562c9916cdSFrançois Tigeot if (ret) { 22572c9916cdSFrançois Tigeot DRM_ERROR("Failed to pin and map ringbuffer %s: %d\n", 22582c9916cdSFrançois Tigeot ring->name, ret); 22592c9916cdSFrançois Tigeot intel_destroy_ringbuffer_obj(ringbuf); 2260ba55f2f5SFrançois Tigeot goto error; 2261ba55f2f5SFrançois Tigeot } 2262e3adcf8fSFrançois Tigeot 2263ba55f2f5SFrançois Tigeot ret = i915_cmd_parser_init_ring(ring); 2264ba55f2f5SFrançois Tigeot if (ret) 2265ba55f2f5SFrançois Tigeot goto error; 2266ba55f2f5SFrançois Tigeot 2267e3adcf8fSFrançois Tigeot return 0; 2268e3adcf8fSFrançois Tigeot 2269ba55f2f5SFrançois Tigeot error: 2270aee94f86SFrançois Tigeot intel_cleanup_ring_buffer(ring); 2271e3adcf8fSFrançois Tigeot return ret; 2272e3adcf8fSFrançois Tigeot } 2273e3adcf8fSFrançois Tigeot 2274ba55f2f5SFrançois Tigeot void intel_cleanup_ring_buffer(struct intel_engine_cs *ring) 2275e3adcf8fSFrançois Tigeot { 22762c9916cdSFrançois Tigeot struct drm_i915_private *dev_priv; 2277e3adcf8fSFrançois Tigeot 2278ba55f2f5SFrançois Tigeot if (!intel_ring_initialized(ring)) 2279e3adcf8fSFrançois Tigeot return; 2280e3adcf8fSFrançois Tigeot 22812c9916cdSFrançois Tigeot dev_priv = to_i915(ring->dev); 22822c9916cdSFrançois Tigeot 2283aee94f86SFrançois Tigeot if (ring->buffer) { 2284ba55f2f5SFrançois Tigeot intel_stop_ring_buffer(ring); 2285ba55f2f5SFrançois Tigeot WARN_ON(!IS_GEN2(ring->dev) && (I915_READ_MODE(ring) & MODE_IDLE) == 0); 2286b030f26bSFrançois Tigeot 2287352ff8bdSFrançois Tigeot intel_unpin_ringbuffer_obj(ring->buffer); 2288352ff8bdSFrançois Tigeot intel_ringbuffer_free(ring->buffer); 2289352ff8bdSFrançois Tigeot ring->buffer = NULL; 2290aee94f86SFrançois Tigeot } 2291e3adcf8fSFrançois Tigeot 2292e3adcf8fSFrançois Tigeot if (ring->cleanup) 2293e3adcf8fSFrançois Tigeot ring->cleanup(ring); 2294e3adcf8fSFrançois Tigeot 2295*c0e85e96SFrançois Tigeot if (I915_NEED_GFX_HWS(ring->dev)) { 2296e3adcf8fSFrançois Tigeot cleanup_status_page(ring); 2297*c0e85e96SFrançois Tigeot } else { 2298*c0e85e96SFrançois Tigeot WARN_ON(ring->id != RCS); 2299*c0e85e96SFrançois Tigeot cleanup_phys_status_page(ring); 2300*c0e85e96SFrançois Tigeot } 2301ba55f2f5SFrançois Tigeot 2302ba55f2f5SFrançois Tigeot i915_cmd_parser_fini_ring(ring); 230319c468b4SFrançois Tigeot i915_gem_batch_pool_fini(&ring->batch_pool); 2304aee94f86SFrançois Tigeot ring->dev = NULL; 2305e3adcf8fSFrançois Tigeot } 2306e3adcf8fSFrançois Tigeot 230719c468b4SFrançois Tigeot static int ring_wait_for_space(struct intel_engine_cs *ring, int n) 2308e3adcf8fSFrançois Tigeot { 2309ba55f2f5SFrançois Tigeot struct intel_ringbuffer *ringbuf = ring->buffer; 2310e3adcf8fSFrançois Tigeot struct drm_i915_gem_request *request; 231119c468b4SFrançois Tigeot unsigned space; 2312e3adcf8fSFrançois Tigeot int ret; 2313e3adcf8fSFrançois Tigeot 23142c9916cdSFrançois Tigeot if (intel_ring_space(ringbuf) >= n) 2315e3adcf8fSFrançois Tigeot return 0; 2316e3adcf8fSFrançois Tigeot 2317a05eeebfSFrançois Tigeot /* The whole point of reserving space is to not wait! */ 2318a05eeebfSFrançois Tigeot WARN_ON(ringbuf->reserved_in_use); 2319a05eeebfSFrançois Tigeot 2320e3adcf8fSFrançois Tigeot list_for_each_entry(request, &ring->request_list, list) { 232119c468b4SFrançois Tigeot space = __intel_ring_space(request->postfix, ringbuf->tail, 232219c468b4SFrançois Tigeot ringbuf->size); 232319c468b4SFrançois Tigeot if (space >= n) 2324e3adcf8fSFrançois Tigeot break; 2325e3adcf8fSFrançois Tigeot } 2326e3adcf8fSFrançois Tigeot 232719c468b4SFrançois Tigeot if (WARN_ON(&request->list == &ring->request_list)) 2328e3adcf8fSFrançois Tigeot return -ENOSPC; 2329e3adcf8fSFrançois Tigeot 23302c9916cdSFrançois Tigeot ret = i915_wait_request(request); 2331e3adcf8fSFrançois Tigeot if (ret) 2332e3adcf8fSFrançois Tigeot return ret; 2333e3adcf8fSFrançois Tigeot 233419c468b4SFrançois Tigeot ringbuf->space = space; 2335e3adcf8fSFrançois Tigeot return 0; 2336e3adcf8fSFrançois Tigeot } 2337e3adcf8fSFrançois Tigeot 2338a05eeebfSFrançois Tigeot static void __wrap_ring_buffer(struct intel_ringbuffer *ringbuf) 2339b030f26bSFrançois Tigeot { 2340b030f26bSFrançois Tigeot uint32_t __iomem *virt; 2341ba55f2f5SFrançois Tigeot int rem = ringbuf->size - ringbuf->tail; 2342b030f26bSFrançois Tigeot 2343ba55f2f5SFrançois Tigeot virt = (unsigned int *)((char *)ringbuf->virtual_start + ringbuf->tail); 2344b030f26bSFrançois Tigeot rem /= 4; 2345b030f26bSFrançois Tigeot while (rem--) 2346686a02f1SFrançois Tigeot iowrite32(MI_NOOP, virt++); 2347b030f26bSFrançois Tigeot 2348ba55f2f5SFrançois Tigeot ringbuf->tail = 0; 23492c9916cdSFrançois Tigeot intel_ring_update_space(ringbuf); 2350b030f26bSFrançois Tigeot } 2351b030f26bSFrançois Tigeot 2352ba55f2f5SFrançois Tigeot int intel_ring_idle(struct intel_engine_cs *ring) 2353b030f26bSFrançois Tigeot { 23542c9916cdSFrançois Tigeot struct drm_i915_gem_request *req; 2355b5c29a34SFrançois Tigeot 2356b5c29a34SFrançois Tigeot /* Wait upon the last request to be completed */ 2357b5c29a34SFrançois Tigeot if (list_empty(&ring->request_list)) 2358b5c29a34SFrançois Tigeot return 0; 2359b5c29a34SFrançois Tigeot 23602c9916cdSFrançois Tigeot req = list_entry(ring->request_list.prev, 2361b5c29a34SFrançois Tigeot struct drm_i915_gem_request, 23622c9916cdSFrançois Tigeot list); 2363b5c29a34SFrançois Tigeot 236419c468b4SFrançois Tigeot /* Make sure we do not trigger any retires */ 236519c468b4SFrançois Tigeot return __i915_wait_request(req, 236619c468b4SFrançois Tigeot atomic_read(&to_i915(ring->dev)->gpu_error.reset_counter), 236719c468b4SFrançois Tigeot to_i915(ring->dev)->mm.interruptible, 236819c468b4SFrançois Tigeot NULL, NULL); 2369b5c29a34SFrançois Tigeot } 2370b5c29a34SFrançois Tigeot 237119c468b4SFrançois Tigeot int intel_ring_alloc_request_extras(struct drm_i915_gem_request *request) 2372b5c29a34SFrançois Tigeot { 237319c468b4SFrançois Tigeot request->ringbuf = request->ring->buffer; 23742c9916cdSFrançois Tigeot return 0; 23759edbd4a0SFrançois Tigeot } 23769edbd4a0SFrançois Tigeot 2377a05eeebfSFrançois Tigeot int intel_ring_reserve_space(struct drm_i915_gem_request *request) 2378a2fdbec6SFrançois Tigeot { 2379a05eeebfSFrançois Tigeot /* 2380a05eeebfSFrançois Tigeot * The first call merely notes the reserve request and is common for 2381a05eeebfSFrançois Tigeot * all back ends. The subsequent localised _begin() call actually 2382a05eeebfSFrançois Tigeot * ensures that the reservation is available. Without the begin, if 2383a05eeebfSFrançois Tigeot * the request creator immediately submitted the request without 2384a05eeebfSFrançois Tigeot * adding any commands to it then there might not actually be 2385a05eeebfSFrançois Tigeot * sufficient room for the submission commands. 2386a05eeebfSFrançois Tigeot */ 2387a05eeebfSFrançois Tigeot intel_ring_reserved_space_reserve(request->ringbuf, MIN_SPACE_FOR_ADD_REQUEST); 2388a2fdbec6SFrançois Tigeot 2389a05eeebfSFrançois Tigeot return intel_ring_begin(request, 0); 2390a2fdbec6SFrançois Tigeot } 2391a2fdbec6SFrançois Tigeot 2392a05eeebfSFrançois Tigeot void intel_ring_reserved_space_reserve(struct intel_ringbuffer *ringbuf, int size) 2393a05eeebfSFrançois Tigeot { 2394a05eeebfSFrançois Tigeot WARN_ON(ringbuf->reserved_size); 2395a05eeebfSFrançois Tigeot WARN_ON(ringbuf->reserved_in_use); 2396a05eeebfSFrançois Tigeot 2397a05eeebfSFrançois Tigeot ringbuf->reserved_size = size; 2398a05eeebfSFrançois Tigeot } 2399a05eeebfSFrançois Tigeot 2400a05eeebfSFrançois Tigeot void intel_ring_reserved_space_cancel(struct intel_ringbuffer *ringbuf) 2401a05eeebfSFrançois Tigeot { 2402a05eeebfSFrançois Tigeot WARN_ON(ringbuf->reserved_in_use); 2403a05eeebfSFrançois Tigeot 2404a05eeebfSFrançois Tigeot ringbuf->reserved_size = 0; 2405a05eeebfSFrançois Tigeot ringbuf->reserved_in_use = false; 2406a05eeebfSFrançois Tigeot } 2407a05eeebfSFrançois Tigeot 2408a05eeebfSFrançois Tigeot void intel_ring_reserved_space_use(struct intel_ringbuffer *ringbuf) 2409a05eeebfSFrançois Tigeot { 2410a05eeebfSFrançois Tigeot WARN_ON(ringbuf->reserved_in_use); 2411a05eeebfSFrançois Tigeot 2412a05eeebfSFrançois Tigeot ringbuf->reserved_in_use = true; 2413a05eeebfSFrançois Tigeot ringbuf->reserved_tail = ringbuf->tail; 2414a05eeebfSFrançois Tigeot } 2415a05eeebfSFrançois Tigeot 2416a05eeebfSFrançois Tigeot void intel_ring_reserved_space_end(struct intel_ringbuffer *ringbuf) 2417a05eeebfSFrançois Tigeot { 2418a05eeebfSFrançois Tigeot WARN_ON(!ringbuf->reserved_in_use); 2419a05eeebfSFrançois Tigeot if (ringbuf->tail > ringbuf->reserved_tail) { 2420a05eeebfSFrançois Tigeot WARN(ringbuf->tail > ringbuf->reserved_tail + ringbuf->reserved_size, 2421a05eeebfSFrançois Tigeot "request reserved size too small: %d vs %d!\n", 2422a05eeebfSFrançois Tigeot ringbuf->tail - ringbuf->reserved_tail, ringbuf->reserved_size); 2423a05eeebfSFrançois Tigeot } else { 2424a05eeebfSFrançois Tigeot /* 2425a05eeebfSFrançois Tigeot * The ring was wrapped while the reserved space was in use. 2426a05eeebfSFrançois Tigeot * That means that some unknown amount of the ring tail was 2427a05eeebfSFrançois Tigeot * no-op filled and skipped. Thus simply adding the ring size 2428a05eeebfSFrançois Tigeot * to the tail and doing the above space check will not work. 2429a05eeebfSFrançois Tigeot * Rather than attempt to track how much tail was skipped, 2430a05eeebfSFrançois Tigeot * it is much simpler to say that also skipping the sanity 2431a05eeebfSFrançois Tigeot * check every once in a while is not a big issue. 2432a05eeebfSFrançois Tigeot */ 2433a05eeebfSFrançois Tigeot } 2434a05eeebfSFrançois Tigeot 2435a05eeebfSFrançois Tigeot ringbuf->reserved_size = 0; 2436a05eeebfSFrançois Tigeot ringbuf->reserved_in_use = false; 2437a05eeebfSFrançois Tigeot } 2438a05eeebfSFrançois Tigeot 2439a05eeebfSFrançois Tigeot static int __intel_ring_prepare(struct intel_engine_cs *ring, int bytes) 2440a05eeebfSFrançois Tigeot { 2441a05eeebfSFrançois Tigeot struct intel_ringbuffer *ringbuf = ring->buffer; 2442a05eeebfSFrançois Tigeot int remain_usable = ringbuf->effective_size - ringbuf->tail; 2443a05eeebfSFrançois Tigeot int remain_actual = ringbuf->size - ringbuf->tail; 2444a05eeebfSFrançois Tigeot int ret, total_bytes, wait_bytes = 0; 2445a05eeebfSFrançois Tigeot bool need_wrap = false; 2446a05eeebfSFrançois Tigeot 2447a05eeebfSFrançois Tigeot if (ringbuf->reserved_in_use) 2448a05eeebfSFrançois Tigeot total_bytes = bytes; 2449a05eeebfSFrançois Tigeot else 2450a05eeebfSFrançois Tigeot total_bytes = bytes + ringbuf->reserved_size; 2451a05eeebfSFrançois Tigeot 2452a05eeebfSFrançois Tigeot if (unlikely(bytes > remain_usable)) { 2453a05eeebfSFrançois Tigeot /* 2454a05eeebfSFrançois Tigeot * Not enough space for the basic request. So need to flush 2455a05eeebfSFrançois Tigeot * out the remainder and then wait for base + reserved. 2456a05eeebfSFrançois Tigeot */ 2457a05eeebfSFrançois Tigeot wait_bytes = remain_actual + total_bytes; 2458a05eeebfSFrançois Tigeot need_wrap = true; 2459a05eeebfSFrançois Tigeot } else { 2460a05eeebfSFrançois Tigeot if (unlikely(total_bytes > remain_usable)) { 2461a05eeebfSFrançois Tigeot /* 2462a05eeebfSFrançois Tigeot * The base request will fit but the reserved space 2463*c0e85e96SFrançois Tigeot * falls off the end. So don't need an immediate wrap 2464*c0e85e96SFrançois Tigeot * and only need to effectively wait for the reserved 2465*c0e85e96SFrançois Tigeot * size space from the start of ringbuffer. 2466a05eeebfSFrançois Tigeot */ 2467a05eeebfSFrançois Tigeot wait_bytes = remain_actual + ringbuf->reserved_size; 2468a05eeebfSFrançois Tigeot } else if (total_bytes > ringbuf->space) { 2469a05eeebfSFrançois Tigeot /* No wrapping required, just waiting. */ 2470a05eeebfSFrançois Tigeot wait_bytes = total_bytes; 2471a05eeebfSFrançois Tigeot } 2472a05eeebfSFrançois Tigeot } 2473a05eeebfSFrançois Tigeot 2474a05eeebfSFrançois Tigeot if (wait_bytes) { 2475a05eeebfSFrançois Tigeot ret = ring_wait_for_space(ring, wait_bytes); 2476a2fdbec6SFrançois Tigeot if (unlikely(ret)) 2477a2fdbec6SFrançois Tigeot return ret; 2478a05eeebfSFrançois Tigeot 2479a05eeebfSFrançois Tigeot if (need_wrap) 2480a05eeebfSFrançois Tigeot __wrap_ring_buffer(ringbuf); 2481a2fdbec6SFrançois Tigeot } 2482a2fdbec6SFrançois Tigeot 2483a2fdbec6SFrançois Tigeot return 0; 2484a2fdbec6SFrançois Tigeot } 2485a2fdbec6SFrançois Tigeot 2486a05eeebfSFrançois Tigeot int intel_ring_begin(struct drm_i915_gem_request *req, 2487e3adcf8fSFrançois Tigeot int num_dwords) 2488e3adcf8fSFrançois Tigeot { 2489a05eeebfSFrançois Tigeot struct intel_engine_cs *ring; 2490a05eeebfSFrançois Tigeot struct drm_i915_private *dev_priv; 2491e3adcf8fSFrançois Tigeot int ret; 2492e3adcf8fSFrançois Tigeot 2493a05eeebfSFrançois Tigeot WARN_ON(req == NULL); 2494a05eeebfSFrançois Tigeot ring = req->ring; 2495a05eeebfSFrançois Tigeot dev_priv = ring->dev->dev_private; 2496a05eeebfSFrançois Tigeot 2497a2fdbec6SFrançois Tigeot ret = i915_gem_check_wedge(&dev_priv->gpu_error, 2498a2fdbec6SFrançois Tigeot dev_priv->mm.interruptible); 2499245593daSFrançois Tigeot if (ret) 2500245593daSFrançois Tigeot return ret; 2501e3adcf8fSFrançois Tigeot 25029edbd4a0SFrançois Tigeot ret = __intel_ring_prepare(ring, num_dwords * sizeof(uint32_t)); 25039edbd4a0SFrançois Tigeot if (ret) 25049edbd4a0SFrançois Tigeot return ret; 25059edbd4a0SFrançois Tigeot 2506ba55f2f5SFrançois Tigeot ring->buffer->space -= num_dwords * sizeof(uint32_t); 25079edbd4a0SFrançois Tigeot return 0; 25089edbd4a0SFrançois Tigeot } 25099edbd4a0SFrançois Tigeot 25109edbd4a0SFrançois Tigeot /* Align the ring tail to a cacheline boundary */ 2511a05eeebfSFrançois Tigeot int intel_ring_cacheline_align(struct drm_i915_gem_request *req) 25129edbd4a0SFrançois Tigeot { 2513a05eeebfSFrançois Tigeot struct intel_engine_cs *ring = req->ring; 2514ba55f2f5SFrançois Tigeot int num_dwords = (ring->buffer->tail & (CACHELINE_BYTES - 1)) / sizeof(uint32_t); 25159edbd4a0SFrançois Tigeot int ret; 25169edbd4a0SFrançois Tigeot 25179edbd4a0SFrançois Tigeot if (num_dwords == 0) 25189edbd4a0SFrançois Tigeot return 0; 25199edbd4a0SFrançois Tigeot 2520ba55f2f5SFrançois Tigeot num_dwords = CACHELINE_BYTES / sizeof(uint32_t) - num_dwords; 2521a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, num_dwords); 25229edbd4a0SFrançois Tigeot if (ret) 25239edbd4a0SFrançois Tigeot return ret; 25249edbd4a0SFrançois Tigeot 25259edbd4a0SFrançois Tigeot while (num_dwords--) 25269edbd4a0SFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 25279edbd4a0SFrançois Tigeot 25289edbd4a0SFrançois Tigeot intel_ring_advance(ring); 25299edbd4a0SFrançois Tigeot 25309edbd4a0SFrançois Tigeot return 0; 2531e3adcf8fSFrançois Tigeot } 2532e3adcf8fSFrançois Tigeot 2533ba55f2f5SFrançois Tigeot void intel_ring_init_seqno(struct intel_engine_cs *ring, u32 seqno) 2534a2fdbec6SFrançois Tigeot { 253524edb884SFrançois Tigeot struct drm_device *dev = ring->dev; 253624edb884SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 2537a2fdbec6SFrançois Tigeot 253824edb884SFrançois Tigeot if (INTEL_INFO(dev)->gen == 6 || INTEL_INFO(dev)->gen == 7) { 2539a2fdbec6SFrançois Tigeot I915_WRITE(RING_SYNC_0(ring->mmio_base), 0); 2540a2fdbec6SFrançois Tigeot I915_WRITE(RING_SYNC_1(ring->mmio_base), 0); 254124edb884SFrançois Tigeot if (HAS_VEBOX(dev)) 25429edbd4a0SFrançois Tigeot I915_WRITE(RING_SYNC_2(ring->mmio_base), 0); 2543e3adcf8fSFrançois Tigeot } 2544e3adcf8fSFrançois Tigeot 2545a2fdbec6SFrançois Tigeot ring->set_seqno(ring, seqno); 25465d0b1887SFrançois Tigeot ring->hangcheck.seqno = seqno; 2547e3adcf8fSFrançois Tigeot } 2548e3adcf8fSFrançois Tigeot 2549ba55f2f5SFrançois Tigeot static void gen6_bsd_ring_write_tail(struct intel_engine_cs *ring, 2550f4e1c372SFrançois Tigeot u32 value) 2551e3adcf8fSFrançois Tigeot { 2552ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = ring->dev->dev_private; 2553e3adcf8fSFrançois Tigeot 2554e3adcf8fSFrançois Tigeot /* Every tail move must follow the sequence below */ 2555f4e1c372SFrançois Tigeot 2556f4e1c372SFrançois Tigeot /* Disable notification that the ring is IDLE. The GT 2557f4e1c372SFrançois Tigeot * will then assume that it is busy and bring it out of rc6. 2558f4e1c372SFrançois Tigeot */ 2559e3adcf8fSFrançois Tigeot I915_WRITE(GEN6_BSD_SLEEP_PSMI_CONTROL, 2560f4e1c372SFrançois Tigeot _MASKED_BIT_ENABLE(GEN6_BSD_SLEEP_MSG_DISABLE)); 2561e3adcf8fSFrançois Tigeot 2562f4e1c372SFrançois Tigeot /* Clear the context id. Here be magic! */ 2563f4e1c372SFrançois Tigeot I915_WRITE64(GEN6_BSD_RNCID, 0x0); 2564e3adcf8fSFrançois Tigeot 2565f4e1c372SFrançois Tigeot /* Wait for the ring not to be idle, i.e. for it to wake up. */ 2566f4e1c372SFrançois Tigeot if (wait_for((I915_READ(GEN6_BSD_SLEEP_PSMI_CONTROL) & 2567f4e1c372SFrançois Tigeot GEN6_BSD_SLEEP_INDICATOR) == 0, 2568f4e1c372SFrançois Tigeot 50)) 2569f4e1c372SFrançois Tigeot DRM_ERROR("timed out waiting for the BSD ring to wake up\n"); 2570f4e1c372SFrançois Tigeot 2571f4e1c372SFrançois Tigeot /* Now that the ring is fully powered up, update the tail */ 2572e3adcf8fSFrançois Tigeot I915_WRITE_TAIL(ring, value); 2573f4e1c372SFrançois Tigeot POSTING_READ(RING_TAIL(ring->mmio_base)); 2574f4e1c372SFrançois Tigeot 2575f4e1c372SFrançois Tigeot /* Let the ring send IDLE messages to the GT again, 2576f4e1c372SFrançois Tigeot * and so let it sleep to conserve power when idle. 2577f4e1c372SFrançois Tigeot */ 2578e3adcf8fSFrançois Tigeot I915_WRITE(GEN6_BSD_SLEEP_PSMI_CONTROL, 2579f4e1c372SFrançois Tigeot _MASKED_BIT_DISABLE(GEN6_BSD_SLEEP_MSG_DISABLE)); 2580e3adcf8fSFrançois Tigeot } 2581e3adcf8fSFrançois Tigeot 2582a05eeebfSFrançois Tigeot static int gen6_bsd_ring_flush(struct drm_i915_gem_request *req, 2583b5c29a34SFrançois Tigeot u32 invalidate, u32 flush) 2584e3adcf8fSFrançois Tigeot { 2585a05eeebfSFrançois Tigeot struct intel_engine_cs *ring = req->ring; 2586e3adcf8fSFrançois Tigeot uint32_t cmd; 2587e3adcf8fSFrançois Tigeot int ret; 2588e3adcf8fSFrançois Tigeot 2589a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 4); 2590e3adcf8fSFrançois Tigeot if (ret) 2591e3adcf8fSFrançois Tigeot return ret; 2592e3adcf8fSFrançois Tigeot 2593e3adcf8fSFrançois Tigeot cmd = MI_FLUSH_DW; 25949edbd4a0SFrançois Tigeot if (INTEL_INFO(ring->dev)->gen >= 8) 25959edbd4a0SFrançois Tigeot cmd += 1; 25962c9916cdSFrançois Tigeot 25972c9916cdSFrançois Tigeot /* We always require a command barrier so that subsequent 25982c9916cdSFrançois Tigeot * commands, such as breadcrumb interrupts, are strictly ordered 25992c9916cdSFrançois Tigeot * wrt the contents of the write cache being flushed to memory 26002c9916cdSFrançois Tigeot * (and thus being coherent from the CPU). 26012c9916cdSFrançois Tigeot */ 26022c9916cdSFrançois Tigeot cmd |= MI_FLUSH_DW_STORE_INDEX | MI_FLUSH_DW_OP_STOREDW; 26032c9916cdSFrançois Tigeot 2604b5c29a34SFrançois Tigeot /* 2605b5c29a34SFrançois Tigeot * Bspec vol 1c.5 - video engine command streamer: 2606b5c29a34SFrançois Tigeot * "If ENABLED, all TLBs will be invalidated once the flush 2607b5c29a34SFrançois Tigeot * operation is complete. This bit is only valid when the 2608b5c29a34SFrançois Tigeot * Post-Sync Operation field is a value of 1h or 3h." 2609b5c29a34SFrançois Tigeot */ 2610e3adcf8fSFrançois Tigeot if (invalidate & I915_GEM_GPU_DOMAINS) 26112c9916cdSFrançois Tigeot cmd |= MI_INVALIDATE_TLB | MI_INVALIDATE_BSD; 26122c9916cdSFrançois Tigeot 2613e3adcf8fSFrançois Tigeot intel_ring_emit(ring, cmd); 2614b5c29a34SFrançois Tigeot intel_ring_emit(ring, I915_GEM_HWS_SCRATCH_ADDR | MI_FLUSH_DW_USE_GTT); 26159edbd4a0SFrançois Tigeot if (INTEL_INFO(ring->dev)->gen >= 8) { 26169edbd4a0SFrançois Tigeot intel_ring_emit(ring, 0); /* upper addr */ 26179edbd4a0SFrançois Tigeot intel_ring_emit(ring, 0); /* value */ 26189edbd4a0SFrançois Tigeot } else { 26199edbd4a0SFrançois Tigeot intel_ring_emit(ring, 0); 26209edbd4a0SFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 26219edbd4a0SFrançois Tigeot } 26229edbd4a0SFrançois Tigeot intel_ring_advance(ring); 26239edbd4a0SFrançois Tigeot return 0; 26249edbd4a0SFrançois Tigeot } 26259edbd4a0SFrançois Tigeot 26269edbd4a0SFrançois Tigeot static int 2627a05eeebfSFrançois Tigeot gen8_ring_dispatch_execbuffer(struct drm_i915_gem_request *req, 2628ba55f2f5SFrançois Tigeot u64 offset, u32 len, 2629477eb7f9SFrançois Tigeot unsigned dispatch_flags) 26309edbd4a0SFrançois Tigeot { 2631a05eeebfSFrançois Tigeot struct intel_engine_cs *ring = req->ring; 2632477eb7f9SFrançois Tigeot bool ppgtt = USES_PPGTT(ring->dev) && 2633477eb7f9SFrançois Tigeot !(dispatch_flags & I915_DISPATCH_SECURE); 26349edbd4a0SFrançois Tigeot int ret; 26359edbd4a0SFrançois Tigeot 2636a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 4); 26379edbd4a0SFrançois Tigeot if (ret) 26389edbd4a0SFrançois Tigeot return ret; 26399edbd4a0SFrançois Tigeot 26409edbd4a0SFrançois Tigeot /* FIXME(BDW): Address space and security selectors. */ 2641a05eeebfSFrançois Tigeot intel_ring_emit(ring, MI_BATCH_BUFFER_START_GEN8 | (ppgtt<<8) | 2642a05eeebfSFrançois Tigeot (dispatch_flags & I915_DISPATCH_RS ? 2643a05eeebfSFrançois Tigeot MI_BATCH_RESOURCE_STREAMER : 0)); 2644ba55f2f5SFrançois Tigeot intel_ring_emit(ring, lower_32_bits(offset)); 2645ba55f2f5SFrançois Tigeot intel_ring_emit(ring, upper_32_bits(offset)); 2646e3adcf8fSFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 2647e3adcf8fSFrançois Tigeot intel_ring_advance(ring); 26489edbd4a0SFrançois Tigeot 2649e3adcf8fSFrançois Tigeot return 0; 2650e3adcf8fSFrançois Tigeot } 2651e3adcf8fSFrançois Tigeot 2652e3adcf8fSFrançois Tigeot static int 2653a05eeebfSFrançois Tigeot hsw_ring_dispatch_execbuffer(struct drm_i915_gem_request *req, 2654ba55f2f5SFrançois Tigeot u64 offset, u32 len, 2655477eb7f9SFrançois Tigeot unsigned dispatch_flags) 2656e3adcf8fSFrançois Tigeot { 2657a05eeebfSFrançois Tigeot struct intel_engine_cs *ring = req->ring; 2658e3adcf8fSFrançois Tigeot int ret; 2659e3adcf8fSFrançois Tigeot 2660a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 2); 2661e3adcf8fSFrançois Tigeot if (ret) 2662e3adcf8fSFrançois Tigeot return ret; 2663e3adcf8fSFrançois Tigeot 2664b5c29a34SFrançois Tigeot intel_ring_emit(ring, 26651b13d190SFrançois Tigeot MI_BATCH_BUFFER_START | 2666477eb7f9SFrançois Tigeot (dispatch_flags & I915_DISPATCH_SECURE ? 2667a05eeebfSFrançois Tigeot 0 : MI_BATCH_PPGTT_HSW | MI_BATCH_NON_SECURE_HSW) | 2668a05eeebfSFrançois Tigeot (dispatch_flags & I915_DISPATCH_RS ? 2669a05eeebfSFrançois Tigeot MI_BATCH_RESOURCE_STREAMER : 0)); 2670b5c29a34SFrançois Tigeot /* bit0-7 is the length on GEN6+ */ 2671b5c29a34SFrançois Tigeot intel_ring_emit(ring, offset); 2672b5c29a34SFrançois Tigeot intel_ring_advance(ring); 2673b5c29a34SFrançois Tigeot 2674b5c29a34SFrançois Tigeot return 0; 2675b5c29a34SFrançois Tigeot } 2676b5c29a34SFrançois Tigeot 2677b5c29a34SFrançois Tigeot static int 2678a05eeebfSFrançois Tigeot gen6_ring_dispatch_execbuffer(struct drm_i915_gem_request *req, 2679ba55f2f5SFrançois Tigeot u64 offset, u32 len, 2680477eb7f9SFrançois Tigeot unsigned dispatch_flags) 2681b5c29a34SFrançois Tigeot { 2682a05eeebfSFrançois Tigeot struct intel_engine_cs *ring = req->ring; 2683b5c29a34SFrançois Tigeot int ret; 2684b5c29a34SFrançois Tigeot 2685a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 2); 2686b5c29a34SFrançois Tigeot if (ret) 2687b5c29a34SFrançois Tigeot return ret; 2688b5c29a34SFrançois Tigeot 2689b5c29a34SFrançois Tigeot intel_ring_emit(ring, 2690b5c29a34SFrançois Tigeot MI_BATCH_BUFFER_START | 2691477eb7f9SFrançois Tigeot (dispatch_flags & I915_DISPATCH_SECURE ? 2692477eb7f9SFrançois Tigeot 0 : MI_BATCH_NON_SECURE_I965)); 2693e3adcf8fSFrançois Tigeot /* bit0-7 is the length on GEN6+ */ 2694e3adcf8fSFrançois Tigeot intel_ring_emit(ring, offset); 2695e3adcf8fSFrançois Tigeot intel_ring_advance(ring); 2696e3adcf8fSFrançois Tigeot 2697e3adcf8fSFrançois Tigeot return 0; 2698e3adcf8fSFrançois Tigeot } 2699e3adcf8fSFrançois Tigeot 2700e3adcf8fSFrançois Tigeot /* Blitter support (SandyBridge+) */ 2701e3adcf8fSFrançois Tigeot 2702a05eeebfSFrançois Tigeot static int gen6_ring_flush(struct drm_i915_gem_request *req, 2703b5c29a34SFrançois Tigeot u32 invalidate, u32 flush) 2704e3adcf8fSFrançois Tigeot { 2705a05eeebfSFrançois Tigeot struct intel_engine_cs *ring = req->ring; 27065d0b1887SFrançois Tigeot struct drm_device *dev = ring->dev; 2707e3adcf8fSFrançois Tigeot uint32_t cmd; 2708e3adcf8fSFrançois Tigeot int ret; 2709e3adcf8fSFrançois Tigeot 2710a05eeebfSFrançois Tigeot ret = intel_ring_begin(req, 4); 2711e3adcf8fSFrançois Tigeot if (ret) 2712e3adcf8fSFrançois Tigeot return ret; 2713e3adcf8fSFrançois Tigeot 2714e3adcf8fSFrançois Tigeot cmd = MI_FLUSH_DW; 2715477eb7f9SFrançois Tigeot if (INTEL_INFO(dev)->gen >= 8) 27169edbd4a0SFrançois Tigeot cmd += 1; 27172c9916cdSFrançois Tigeot 27182c9916cdSFrançois Tigeot /* We always require a command barrier so that subsequent 27192c9916cdSFrançois Tigeot * commands, such as breadcrumb interrupts, are strictly ordered 27202c9916cdSFrançois Tigeot * wrt the contents of the write cache being flushed to memory 27212c9916cdSFrançois Tigeot * (and thus being coherent from the CPU). 27222c9916cdSFrançois Tigeot */ 27232c9916cdSFrançois Tigeot cmd |= MI_FLUSH_DW_STORE_INDEX | MI_FLUSH_DW_OP_STOREDW; 27242c9916cdSFrançois Tigeot 2725b5c29a34SFrançois Tigeot /* 2726b5c29a34SFrançois Tigeot * Bspec vol 1c.3 - blitter engine command streamer: 2727b5c29a34SFrançois Tigeot * "If ENABLED, all TLBs will be invalidated once the flush 2728b5c29a34SFrançois Tigeot * operation is complete. This bit is only valid when the 2729b5c29a34SFrançois Tigeot * Post-Sync Operation field is a value of 1h or 3h." 2730b5c29a34SFrançois Tigeot */ 2731e3adcf8fSFrançois Tigeot if (invalidate & I915_GEM_DOMAIN_RENDER) 27322c9916cdSFrançois Tigeot cmd |= MI_INVALIDATE_TLB; 2733e3adcf8fSFrançois Tigeot intel_ring_emit(ring, cmd); 2734b5c29a34SFrançois Tigeot intel_ring_emit(ring, I915_GEM_HWS_SCRATCH_ADDR | MI_FLUSH_DW_USE_GTT); 2735477eb7f9SFrançois Tigeot if (INTEL_INFO(dev)->gen >= 8) { 27369edbd4a0SFrançois Tigeot intel_ring_emit(ring, 0); /* upper addr */ 27379edbd4a0SFrançois Tigeot intel_ring_emit(ring, 0); /* value */ 27389edbd4a0SFrançois Tigeot } else { 2739e3adcf8fSFrançois Tigeot intel_ring_emit(ring, 0); 2740e3adcf8fSFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 27419edbd4a0SFrançois Tigeot } 2742e3adcf8fSFrançois Tigeot intel_ring_advance(ring); 27435d0b1887SFrançois Tigeot 2744e3adcf8fSFrançois Tigeot return 0; 2745e3adcf8fSFrançois Tigeot } 2746e3adcf8fSFrançois Tigeot 2747e3adcf8fSFrançois Tigeot int intel_init_render_ring_buffer(struct drm_device *dev) 2748e3adcf8fSFrançois Tigeot { 2749ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 2750ba55f2f5SFrançois Tigeot struct intel_engine_cs *ring = &dev_priv->ring[RCS]; 275124edb884SFrançois Tigeot struct drm_i915_gem_object *obj; 275224edb884SFrançois Tigeot int ret; 2753e3adcf8fSFrançois Tigeot 2754686a02f1SFrançois Tigeot ring->name = "render ring"; 2755686a02f1SFrançois Tigeot ring->id = RCS; 2756*c0e85e96SFrançois Tigeot ring->exec_id = I915_EXEC_RENDER; 2757686a02f1SFrançois Tigeot ring->mmio_base = RENDER_RING_BASE; 2758686a02f1SFrançois Tigeot 275924edb884SFrançois Tigeot if (INTEL_INFO(dev)->gen >= 8) { 276024edb884SFrançois Tigeot if (i915_semaphore_is_enabled(dev)) { 276124edb884SFrançois Tigeot obj = i915_gem_alloc_object(dev, 4096); 276224edb884SFrançois Tigeot if (obj == NULL) { 276324edb884SFrançois Tigeot DRM_ERROR("Failed to allocate semaphore bo. Disabling semaphores\n"); 276424edb884SFrançois Tigeot i915.semaphores = 0; 276524edb884SFrançois Tigeot } else { 276624edb884SFrançois Tigeot i915_gem_object_set_cache_level(obj, I915_CACHE_LLC); 276724edb884SFrançois Tigeot ret = i915_gem_obj_ggtt_pin(obj, 0, PIN_NONBLOCK); 276824edb884SFrançois Tigeot if (ret != 0) { 276924edb884SFrançois Tigeot drm_gem_object_unreference(&obj->base); 277024edb884SFrançois Tigeot DRM_ERROR("Failed to pin semaphore bo. Disabling semaphores\n"); 277124edb884SFrançois Tigeot i915.semaphores = 0; 277224edb884SFrançois Tigeot } else 277324edb884SFrançois Tigeot dev_priv->semaphore_obj = obj; 277424edb884SFrançois Tigeot } 277524edb884SFrançois Tigeot } 27762c9916cdSFrançois Tigeot 27772c9916cdSFrançois Tigeot ring->init_context = intel_rcs_ctx_init; 277824edb884SFrançois Tigeot ring->add_request = gen6_add_request; 277924edb884SFrançois Tigeot ring->flush = gen8_render_ring_flush; 278024edb884SFrançois Tigeot ring->irq_get = gen8_ring_get_irq; 278124edb884SFrançois Tigeot ring->irq_put = gen8_ring_put_irq; 278224edb884SFrançois Tigeot ring->irq_enable_mask = GT_RENDER_USER_INTERRUPT; 278324edb884SFrançois Tigeot ring->get_seqno = gen6_ring_get_seqno; 278424edb884SFrançois Tigeot ring->set_seqno = ring_set_seqno; 278524edb884SFrançois Tigeot if (i915_semaphore_is_enabled(dev)) { 278624edb884SFrançois Tigeot WARN_ON(!dev_priv->semaphore_obj); 278724edb884SFrançois Tigeot ring->semaphore.sync_to = gen8_ring_sync; 278824edb884SFrançois Tigeot ring->semaphore.signal = gen8_rcs_signal; 278924edb884SFrançois Tigeot GEN8_RING_SEMAPHORE_INIT; 279024edb884SFrançois Tigeot } 279124edb884SFrançois Tigeot } else if (INTEL_INFO(dev)->gen >= 6) { 2792352ff8bdSFrançois Tigeot ring->init_context = intel_rcs_ctx_init; 2793e3adcf8fSFrançois Tigeot ring->add_request = gen6_add_request; 2794b5c29a34SFrançois Tigeot ring->flush = gen7_render_ring_flush; 2795b5c29a34SFrançois Tigeot if (INTEL_INFO(dev)->gen == 6) 2796e3adcf8fSFrançois Tigeot ring->flush = gen6_render_ring_flush; 2797686a02f1SFrançois Tigeot ring->irq_get = gen6_ring_get_irq; 2798686a02f1SFrançois Tigeot ring->irq_put = gen6_ring_put_irq; 27995d0b1887SFrançois Tigeot ring->irq_enable_mask = GT_RENDER_USER_INTERRUPT; 2800e3adcf8fSFrançois Tigeot ring->get_seqno = gen6_ring_get_seqno; 2801a2fdbec6SFrançois Tigeot ring->set_seqno = ring_set_seqno; 280224edb884SFrançois Tigeot if (i915_semaphore_is_enabled(dev)) { 2803ba55f2f5SFrançois Tigeot ring->semaphore.sync_to = gen6_ring_sync; 2804ba55f2f5SFrançois Tigeot ring->semaphore.signal = gen6_signal; 2805ba55f2f5SFrançois Tigeot /* 280624edb884SFrançois Tigeot * The current semaphore is only applied on pre-gen8 280724edb884SFrançois Tigeot * platform. And there is no VCS2 ring on the pre-gen8 280824edb884SFrançois Tigeot * platform. So the semaphore between RCS and VCS2 is 280924edb884SFrançois Tigeot * initialized as INVALID. Gen8 will initialize the 281024edb884SFrançois Tigeot * sema between VCS2 and RCS later. 2811ba55f2f5SFrançois Tigeot */ 2812ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[RCS] = MI_SEMAPHORE_SYNC_INVALID; 2813ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[VCS] = MI_SEMAPHORE_SYNC_RV; 2814ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[BCS] = MI_SEMAPHORE_SYNC_RB; 2815ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[VECS] = MI_SEMAPHORE_SYNC_RVE; 2816ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[VCS2] = MI_SEMAPHORE_SYNC_INVALID; 2817ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[RCS] = GEN6_NOSYNC; 2818ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[VCS] = GEN6_VRSYNC; 2819ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[BCS] = GEN6_BRSYNC; 2820ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[VECS] = GEN6_VERSYNC; 2821ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[VCS2] = GEN6_NOSYNC; 282224edb884SFrançois Tigeot } 2823e3adcf8fSFrançois Tigeot } else if (IS_GEN5(dev)) { 2824e3adcf8fSFrançois Tigeot ring->add_request = pc_render_add_request; 2825686a02f1SFrançois Tigeot ring->flush = gen4_render_ring_flush; 2826e3adcf8fSFrançois Tigeot ring->get_seqno = pc_render_get_seqno; 2827a2fdbec6SFrançois Tigeot ring->set_seqno = pc_render_set_seqno; 2828686a02f1SFrançois Tigeot ring->irq_get = gen5_ring_get_irq; 2829686a02f1SFrançois Tigeot ring->irq_put = gen5_ring_put_irq; 28305d0b1887SFrançois Tigeot ring->irq_enable_mask = GT_RENDER_USER_INTERRUPT | 28315d0b1887SFrançois Tigeot GT_RENDER_PIPECTL_NOTIFY_INTERRUPT; 2832686a02f1SFrançois Tigeot } else { 2833686a02f1SFrançois Tigeot ring->add_request = i9xx_add_request; 2834686a02f1SFrançois Tigeot if (INTEL_INFO(dev)->gen < 4) 2835686a02f1SFrançois Tigeot ring->flush = gen2_render_ring_flush; 2836686a02f1SFrançois Tigeot else 2837686a02f1SFrançois Tigeot ring->flush = gen4_render_ring_flush; 2838686a02f1SFrançois Tigeot ring->get_seqno = ring_get_seqno; 2839a2fdbec6SFrançois Tigeot ring->set_seqno = ring_set_seqno; 2840686a02f1SFrançois Tigeot if (IS_GEN2(dev)) { 2841686a02f1SFrançois Tigeot ring->irq_get = i8xx_ring_get_irq; 2842686a02f1SFrançois Tigeot ring->irq_put = i8xx_ring_put_irq; 2843686a02f1SFrançois Tigeot } else { 2844686a02f1SFrançois Tigeot ring->irq_get = i9xx_ring_get_irq; 2845686a02f1SFrançois Tigeot ring->irq_put = i9xx_ring_put_irq; 2846e3adcf8fSFrançois Tigeot } 2847686a02f1SFrançois Tigeot ring->irq_enable_mask = I915_USER_INTERRUPT; 2848686a02f1SFrançois Tigeot } 2849686a02f1SFrançois Tigeot ring->write_tail = ring_write_tail; 285024edb884SFrançois Tigeot 2851b5c29a34SFrançois Tigeot if (IS_HASWELL(dev)) 2852b5c29a34SFrançois Tigeot ring->dispatch_execbuffer = hsw_ring_dispatch_execbuffer; 28539edbd4a0SFrançois Tigeot else if (IS_GEN8(dev)) 28549edbd4a0SFrançois Tigeot ring->dispatch_execbuffer = gen8_ring_dispatch_execbuffer; 2855b5c29a34SFrançois Tigeot else if (INTEL_INFO(dev)->gen >= 6) 2856686a02f1SFrançois Tigeot ring->dispatch_execbuffer = gen6_ring_dispatch_execbuffer; 2857686a02f1SFrançois Tigeot else if (INTEL_INFO(dev)->gen >= 4) 2858686a02f1SFrançois Tigeot ring->dispatch_execbuffer = i965_dispatch_execbuffer; 2859686a02f1SFrançois Tigeot else if (IS_I830(dev) || IS_845G(dev)) 2860686a02f1SFrançois Tigeot ring->dispatch_execbuffer = i830_dispatch_execbuffer; 2861686a02f1SFrançois Tigeot else 2862686a02f1SFrançois Tigeot ring->dispatch_execbuffer = i915_dispatch_execbuffer; 28632c9916cdSFrançois Tigeot ring->init_hw = init_render_ring; 2864686a02f1SFrançois Tigeot ring->cleanup = render_ring_cleanup; 2865e3adcf8fSFrançois Tigeot 2866b5c29a34SFrançois Tigeot /* Workaround batchbuffer to combat CS tlb bug. */ 2867b5c29a34SFrançois Tigeot if (HAS_BROKEN_CS_TLB(dev)) { 286824edb884SFrançois Tigeot obj = i915_gem_alloc_object(dev, I830_WA_SIZE); 2869b5c29a34SFrançois Tigeot if (obj == NULL) { 2870b5c29a34SFrançois Tigeot DRM_ERROR("Failed to allocate batch bo\n"); 2871b5c29a34SFrançois Tigeot return -ENOMEM; 2872b5c29a34SFrançois Tigeot } 2873b5c29a34SFrançois Tigeot 2874ba55f2f5SFrançois Tigeot ret = i915_gem_obj_ggtt_pin(obj, 0, 0); 2875b5c29a34SFrançois Tigeot if (ret != 0) { 2876b5c29a34SFrançois Tigeot drm_gem_object_unreference(&obj->base); 2877b5c29a34SFrançois Tigeot DRM_ERROR("Failed to ping batch bo\n"); 2878b5c29a34SFrançois Tigeot return ret; 2879b5c29a34SFrançois Tigeot } 2880b5c29a34SFrançois Tigeot 28819edbd4a0SFrançois Tigeot ring->scratch.obj = obj; 28829edbd4a0SFrançois Tigeot ring->scratch.gtt_offset = i915_gem_obj_ggtt_offset(obj); 2883e3adcf8fSFrançois Tigeot } 2884e3adcf8fSFrançois Tigeot 28852c9916cdSFrançois Tigeot ret = intel_init_ring_buffer(dev, ring); 2886b5c29a34SFrançois Tigeot if (ret) 28872c9916cdSFrançois Tigeot return ret; 28882c9916cdSFrançois Tigeot 28892c9916cdSFrançois Tigeot if (INTEL_INFO(dev)->gen >= 5) { 28902c9916cdSFrançois Tigeot ret = intel_init_pipe_control(ring); 28912c9916cdSFrançois Tigeot if (ret) 28922c9916cdSFrançois Tigeot return ret; 2893b5c29a34SFrançois Tigeot } 2894b5c29a34SFrançois Tigeot 2895e3adcf8fSFrançois Tigeot return 0; 2896e3adcf8fSFrançois Tigeot } 2897e3adcf8fSFrançois Tigeot 2898e3adcf8fSFrançois Tigeot int intel_init_bsd_ring_buffer(struct drm_device *dev) 2899e3adcf8fSFrançois Tigeot { 2900ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 2901ba55f2f5SFrançois Tigeot struct intel_engine_cs *ring = &dev_priv->ring[VCS]; 2902e3adcf8fSFrançois Tigeot 2903686a02f1SFrançois Tigeot ring->name = "bsd ring"; 2904686a02f1SFrançois Tigeot ring->id = VCS; 2905*c0e85e96SFrançois Tigeot ring->exec_id = I915_EXEC_BSD; 2906686a02f1SFrançois Tigeot 2907686a02f1SFrançois Tigeot ring->write_tail = ring_write_tail; 29089edbd4a0SFrançois Tigeot if (INTEL_INFO(dev)->gen >= 6) { 2909686a02f1SFrançois Tigeot ring->mmio_base = GEN6_BSD_RING_BASE; 2910686a02f1SFrançois Tigeot /* gen6 bsd needs a special wa for tail updates */ 2911686a02f1SFrançois Tigeot if (IS_GEN6(dev)) 2912686a02f1SFrançois Tigeot ring->write_tail = gen6_bsd_ring_write_tail; 29135d0b1887SFrançois Tigeot ring->flush = gen6_bsd_ring_flush; 2914686a02f1SFrançois Tigeot ring->add_request = gen6_add_request; 2915686a02f1SFrançois Tigeot ring->get_seqno = gen6_ring_get_seqno; 2916a2fdbec6SFrançois Tigeot ring->set_seqno = ring_set_seqno; 29179edbd4a0SFrançois Tigeot if (INTEL_INFO(dev)->gen >= 8) { 29189edbd4a0SFrançois Tigeot ring->irq_enable_mask = 29199edbd4a0SFrançois Tigeot GT_RENDER_USER_INTERRUPT << GEN8_VCS1_IRQ_SHIFT; 29209edbd4a0SFrançois Tigeot ring->irq_get = gen8_ring_get_irq; 29219edbd4a0SFrançois Tigeot ring->irq_put = gen8_ring_put_irq; 29229edbd4a0SFrançois Tigeot ring->dispatch_execbuffer = 29239edbd4a0SFrançois Tigeot gen8_ring_dispatch_execbuffer; 292424edb884SFrançois Tigeot if (i915_semaphore_is_enabled(dev)) { 292524edb884SFrançois Tigeot ring->semaphore.sync_to = gen8_ring_sync; 292624edb884SFrançois Tigeot ring->semaphore.signal = gen8_xcs_signal; 292724edb884SFrançois Tigeot GEN8_RING_SEMAPHORE_INIT; 292824edb884SFrançois Tigeot } 29299edbd4a0SFrançois Tigeot } else { 29305d0b1887SFrançois Tigeot ring->irq_enable_mask = GT_BSD_USER_INTERRUPT; 2931686a02f1SFrançois Tigeot ring->irq_get = gen6_ring_get_irq; 2932686a02f1SFrançois Tigeot ring->irq_put = gen6_ring_put_irq; 29339edbd4a0SFrançois Tigeot ring->dispatch_execbuffer = 29349edbd4a0SFrançois Tigeot gen6_ring_dispatch_execbuffer; 293524edb884SFrançois Tigeot if (i915_semaphore_is_enabled(dev)) { 2936ba55f2f5SFrançois Tigeot ring->semaphore.sync_to = gen6_ring_sync; 2937ba55f2f5SFrançois Tigeot ring->semaphore.signal = gen6_signal; 2938ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[RCS] = MI_SEMAPHORE_SYNC_VR; 2939ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[VCS] = MI_SEMAPHORE_SYNC_INVALID; 2940ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[BCS] = MI_SEMAPHORE_SYNC_VB; 2941ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[VECS] = MI_SEMAPHORE_SYNC_VVE; 2942ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[VCS2] = MI_SEMAPHORE_SYNC_INVALID; 2943ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[RCS] = GEN6_RVSYNC; 2944ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[VCS] = GEN6_NOSYNC; 2945ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[BCS] = GEN6_BVSYNC; 2946ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[VECS] = GEN6_VEVSYNC; 2947ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[VCS2] = GEN6_NOSYNC; 294824edb884SFrançois Tigeot } 294924edb884SFrançois Tigeot } 2950686a02f1SFrançois Tigeot } else { 2951686a02f1SFrançois Tigeot ring->mmio_base = BSD_RING_BASE; 2952686a02f1SFrançois Tigeot ring->flush = bsd_ring_flush; 2953686a02f1SFrançois Tigeot ring->add_request = i9xx_add_request; 2954686a02f1SFrançois Tigeot ring->get_seqno = ring_get_seqno; 2955a2fdbec6SFrançois Tigeot ring->set_seqno = ring_set_seqno; 2956686a02f1SFrançois Tigeot if (IS_GEN5(dev)) { 29575d0b1887SFrançois Tigeot ring->irq_enable_mask = ILK_BSD_USER_INTERRUPT; 2958686a02f1SFrançois Tigeot ring->irq_get = gen5_ring_get_irq; 2959686a02f1SFrançois Tigeot ring->irq_put = gen5_ring_put_irq; 2960686a02f1SFrançois Tigeot } else { 2961686a02f1SFrançois Tigeot ring->irq_enable_mask = I915_BSD_USER_INTERRUPT; 2962686a02f1SFrançois Tigeot ring->irq_get = i9xx_ring_get_irq; 2963686a02f1SFrançois Tigeot ring->irq_put = i9xx_ring_put_irq; 2964686a02f1SFrançois Tigeot } 2965686a02f1SFrançois Tigeot ring->dispatch_execbuffer = i965_dispatch_execbuffer; 2966686a02f1SFrançois Tigeot } 29672c9916cdSFrançois Tigeot ring->init_hw = init_ring_common; 2968e3adcf8fSFrançois Tigeot 2969e3adcf8fSFrançois Tigeot return intel_init_ring_buffer(dev, ring); 2970e3adcf8fSFrançois Tigeot } 2971e3adcf8fSFrançois Tigeot 2972ba55f2f5SFrançois Tigeot /** 2973477eb7f9SFrançois Tigeot * Initialize the second BSD ring (eg. Broadwell GT3, Skylake GT3) 2974ba55f2f5SFrançois Tigeot */ 2975ba55f2f5SFrançois Tigeot int intel_init_bsd2_ring_buffer(struct drm_device *dev) 2976ba55f2f5SFrançois Tigeot { 2977ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 2978ba55f2f5SFrançois Tigeot struct intel_engine_cs *ring = &dev_priv->ring[VCS2]; 2979ba55f2f5SFrançois Tigeot 298024edb884SFrançois Tigeot ring->name = "bsd2 ring"; 2981ba55f2f5SFrançois Tigeot ring->id = VCS2; 2982*c0e85e96SFrançois Tigeot ring->exec_id = I915_EXEC_BSD; 2983ba55f2f5SFrançois Tigeot 2984ba55f2f5SFrançois Tigeot ring->write_tail = ring_write_tail; 2985ba55f2f5SFrançois Tigeot ring->mmio_base = GEN8_BSD2_RING_BASE; 2986ba55f2f5SFrançois Tigeot ring->flush = gen6_bsd_ring_flush; 2987ba55f2f5SFrançois Tigeot ring->add_request = gen6_add_request; 2988ba55f2f5SFrançois Tigeot ring->get_seqno = gen6_ring_get_seqno; 2989ba55f2f5SFrançois Tigeot ring->set_seqno = ring_set_seqno; 2990ba55f2f5SFrançois Tigeot ring->irq_enable_mask = 2991ba55f2f5SFrançois Tigeot GT_RENDER_USER_INTERRUPT << GEN8_VCS2_IRQ_SHIFT; 2992ba55f2f5SFrançois Tigeot ring->irq_get = gen8_ring_get_irq; 2993ba55f2f5SFrançois Tigeot ring->irq_put = gen8_ring_put_irq; 2994ba55f2f5SFrançois Tigeot ring->dispatch_execbuffer = 2995ba55f2f5SFrançois Tigeot gen8_ring_dispatch_execbuffer; 299624edb884SFrançois Tigeot if (i915_semaphore_is_enabled(dev)) { 299724edb884SFrançois Tigeot ring->semaphore.sync_to = gen8_ring_sync; 299824edb884SFrançois Tigeot ring->semaphore.signal = gen8_xcs_signal; 299924edb884SFrançois Tigeot GEN8_RING_SEMAPHORE_INIT; 300024edb884SFrançois Tigeot } 30012c9916cdSFrançois Tigeot ring->init_hw = init_ring_common; 3002ba55f2f5SFrançois Tigeot 3003ba55f2f5SFrançois Tigeot return intel_init_ring_buffer(dev, ring); 3004ba55f2f5SFrançois Tigeot } 3005ba55f2f5SFrançois Tigeot 3006e3adcf8fSFrançois Tigeot int intel_init_blt_ring_buffer(struct drm_device *dev) 3007e3adcf8fSFrançois Tigeot { 3008ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 3009ba55f2f5SFrançois Tigeot struct intel_engine_cs *ring = &dev_priv->ring[BCS]; 3010e3adcf8fSFrançois Tigeot 3011686a02f1SFrançois Tigeot ring->name = "blitter ring"; 3012686a02f1SFrançois Tigeot ring->id = BCS; 3013*c0e85e96SFrançois Tigeot ring->exec_id = I915_EXEC_BLT; 3014686a02f1SFrançois Tigeot 3015686a02f1SFrançois Tigeot ring->mmio_base = BLT_RING_BASE; 3016686a02f1SFrançois Tigeot ring->write_tail = ring_write_tail; 30175d0b1887SFrançois Tigeot ring->flush = gen6_ring_flush; 3018686a02f1SFrançois Tigeot ring->add_request = gen6_add_request; 3019686a02f1SFrançois Tigeot ring->get_seqno = gen6_ring_get_seqno; 3020a2fdbec6SFrançois Tigeot ring->set_seqno = ring_set_seqno; 30219edbd4a0SFrançois Tigeot if (INTEL_INFO(dev)->gen >= 8) { 30229edbd4a0SFrançois Tigeot ring->irq_enable_mask = 30239edbd4a0SFrançois Tigeot GT_RENDER_USER_INTERRUPT << GEN8_BCS_IRQ_SHIFT; 30249edbd4a0SFrançois Tigeot ring->irq_get = gen8_ring_get_irq; 30259edbd4a0SFrançois Tigeot ring->irq_put = gen8_ring_put_irq; 30269edbd4a0SFrançois Tigeot ring->dispatch_execbuffer = gen8_ring_dispatch_execbuffer; 302724edb884SFrançois Tigeot if (i915_semaphore_is_enabled(dev)) { 302824edb884SFrançois Tigeot ring->semaphore.sync_to = gen8_ring_sync; 302924edb884SFrançois Tigeot ring->semaphore.signal = gen8_xcs_signal; 303024edb884SFrançois Tigeot GEN8_RING_SEMAPHORE_INIT; 303124edb884SFrançois Tigeot } 30329edbd4a0SFrançois Tigeot } else { 30335d0b1887SFrançois Tigeot ring->irq_enable_mask = GT_BLT_USER_INTERRUPT; 3034686a02f1SFrançois Tigeot ring->irq_get = gen6_ring_get_irq; 3035686a02f1SFrançois Tigeot ring->irq_put = gen6_ring_put_irq; 3036686a02f1SFrançois Tigeot ring->dispatch_execbuffer = gen6_ring_dispatch_execbuffer; 303724edb884SFrançois Tigeot if (i915_semaphore_is_enabled(dev)) { 3038ba55f2f5SFrançois Tigeot ring->semaphore.signal = gen6_signal; 303924edb884SFrançois Tigeot ring->semaphore.sync_to = gen6_ring_sync; 3040ba55f2f5SFrançois Tigeot /* 304124edb884SFrançois Tigeot * The current semaphore is only applied on pre-gen8 304224edb884SFrançois Tigeot * platform. And there is no VCS2 ring on the pre-gen8 304324edb884SFrançois Tigeot * platform. So the semaphore between BCS and VCS2 is 304424edb884SFrançois Tigeot * initialized as INVALID. Gen8 will initialize the 304524edb884SFrançois Tigeot * sema between BCS and VCS2 later. 3046ba55f2f5SFrançois Tigeot */ 3047ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[RCS] = MI_SEMAPHORE_SYNC_BR; 3048ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[VCS] = MI_SEMAPHORE_SYNC_BV; 3049ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[BCS] = MI_SEMAPHORE_SYNC_INVALID; 3050ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[VECS] = MI_SEMAPHORE_SYNC_BVE; 3051ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[VCS2] = MI_SEMAPHORE_SYNC_INVALID; 3052ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[RCS] = GEN6_RBSYNC; 3053ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[VCS] = GEN6_VBSYNC; 3054ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[BCS] = GEN6_NOSYNC; 3055ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[VECS] = GEN6_VEBSYNC; 3056ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[VCS2] = GEN6_NOSYNC; 305724edb884SFrançois Tigeot } 305824edb884SFrançois Tigeot } 30592c9916cdSFrançois Tigeot ring->init_hw = init_ring_common; 30605d0b1887SFrançois Tigeot 30615d0b1887SFrançois Tigeot return intel_init_ring_buffer(dev, ring); 30625d0b1887SFrançois Tigeot } 30635d0b1887SFrançois Tigeot 30645d0b1887SFrançois Tigeot int intel_init_vebox_ring_buffer(struct drm_device *dev) 30655d0b1887SFrançois Tigeot { 3066ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 3067ba55f2f5SFrançois Tigeot struct intel_engine_cs *ring = &dev_priv->ring[VECS]; 30685d0b1887SFrançois Tigeot 30695d0b1887SFrançois Tigeot ring->name = "video enhancement ring"; 30705d0b1887SFrançois Tigeot ring->id = VECS; 3071*c0e85e96SFrançois Tigeot ring->exec_id = I915_EXEC_VEBOX; 30725d0b1887SFrançois Tigeot 30735d0b1887SFrançois Tigeot ring->mmio_base = VEBOX_RING_BASE; 30745d0b1887SFrançois Tigeot ring->write_tail = ring_write_tail; 30755d0b1887SFrançois Tigeot ring->flush = gen6_ring_flush; 30765d0b1887SFrançois Tigeot ring->add_request = gen6_add_request; 30775d0b1887SFrançois Tigeot ring->get_seqno = gen6_ring_get_seqno; 30785d0b1887SFrançois Tigeot ring->set_seqno = ring_set_seqno; 30799edbd4a0SFrançois Tigeot 30809edbd4a0SFrançois Tigeot if (INTEL_INFO(dev)->gen >= 8) { 30819edbd4a0SFrançois Tigeot ring->irq_enable_mask = 30829edbd4a0SFrançois Tigeot GT_RENDER_USER_INTERRUPT << GEN8_VECS_IRQ_SHIFT; 30839edbd4a0SFrançois Tigeot ring->irq_get = gen8_ring_get_irq; 30849edbd4a0SFrançois Tigeot ring->irq_put = gen8_ring_put_irq; 30859edbd4a0SFrançois Tigeot ring->dispatch_execbuffer = gen8_ring_dispatch_execbuffer; 308624edb884SFrançois Tigeot if (i915_semaphore_is_enabled(dev)) { 308724edb884SFrançois Tigeot ring->semaphore.sync_to = gen8_ring_sync; 308824edb884SFrançois Tigeot ring->semaphore.signal = gen8_xcs_signal; 308924edb884SFrançois Tigeot GEN8_RING_SEMAPHORE_INIT; 309024edb884SFrançois Tigeot } 30919edbd4a0SFrançois Tigeot } else { 30929edbd4a0SFrançois Tigeot ring->irq_enable_mask = PM_VEBOX_USER_INTERRUPT; 30935d0b1887SFrançois Tigeot ring->irq_get = hsw_vebox_get_irq; 30945d0b1887SFrançois Tigeot ring->irq_put = hsw_vebox_put_irq; 30955d0b1887SFrançois Tigeot ring->dispatch_execbuffer = gen6_ring_dispatch_execbuffer; 309624edb884SFrançois Tigeot if (i915_semaphore_is_enabled(dev)) { 3097ba55f2f5SFrançois Tigeot ring->semaphore.sync_to = gen6_ring_sync; 3098ba55f2f5SFrançois Tigeot ring->semaphore.signal = gen6_signal; 3099ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[RCS] = MI_SEMAPHORE_SYNC_VER; 3100ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[VCS] = MI_SEMAPHORE_SYNC_VEV; 3101ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[BCS] = MI_SEMAPHORE_SYNC_VEB; 3102ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[VECS] = MI_SEMAPHORE_SYNC_INVALID; 3103ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[VCS2] = MI_SEMAPHORE_SYNC_INVALID; 3104ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[RCS] = GEN6_RVESYNC; 3105ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[VCS] = GEN6_VVESYNC; 3106ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[BCS] = GEN6_BVESYNC; 3107ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[VECS] = GEN6_NOSYNC; 3108ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[VCS2] = GEN6_NOSYNC; 310924edb884SFrançois Tigeot } 311024edb884SFrançois Tigeot } 31112c9916cdSFrançois Tigeot ring->init_hw = init_ring_common; 3112e3adcf8fSFrançois Tigeot 3113e3adcf8fSFrançois Tigeot return intel_init_ring_buffer(dev, ring); 3114e3adcf8fSFrançois Tigeot } 3115b030f26bSFrançois Tigeot 3116b030f26bSFrançois Tigeot int 3117a05eeebfSFrançois Tigeot intel_ring_flush_all_caches(struct drm_i915_gem_request *req) 3118b030f26bSFrançois Tigeot { 3119a05eeebfSFrançois Tigeot struct intel_engine_cs *ring = req->ring; 3120b030f26bSFrançois Tigeot int ret; 3121b030f26bSFrançois Tigeot 3122b030f26bSFrançois Tigeot if (!ring->gpu_caches_dirty) 3123b030f26bSFrançois Tigeot return 0; 3124b030f26bSFrançois Tigeot 3125a05eeebfSFrançois Tigeot ret = ring->flush(req, 0, I915_GEM_GPU_DOMAINS); 3126b030f26bSFrançois Tigeot if (ret) 3127b030f26bSFrançois Tigeot return ret; 3128b030f26bSFrançois Tigeot 3129a05eeebfSFrançois Tigeot trace_i915_gem_ring_flush(req, 0, I915_GEM_GPU_DOMAINS); 3130a2fdbec6SFrançois Tigeot 3131b030f26bSFrançois Tigeot ring->gpu_caches_dirty = false; 3132b030f26bSFrançois Tigeot return 0; 3133b030f26bSFrançois Tigeot } 3134b030f26bSFrançois Tigeot 3135b030f26bSFrançois Tigeot int 3136a05eeebfSFrançois Tigeot intel_ring_invalidate_all_caches(struct drm_i915_gem_request *req) 3137b030f26bSFrançois Tigeot { 3138a05eeebfSFrançois Tigeot struct intel_engine_cs *ring = req->ring; 3139b030f26bSFrançois Tigeot uint32_t flush_domains; 3140b030f26bSFrançois Tigeot int ret; 3141b030f26bSFrançois Tigeot 3142b030f26bSFrançois Tigeot flush_domains = 0; 3143b030f26bSFrançois Tigeot if (ring->gpu_caches_dirty) 3144b030f26bSFrançois Tigeot flush_domains = I915_GEM_GPU_DOMAINS; 3145b030f26bSFrançois Tigeot 3146a05eeebfSFrançois Tigeot ret = ring->flush(req, I915_GEM_GPU_DOMAINS, flush_domains); 3147b030f26bSFrançois Tigeot if (ret) 3148b030f26bSFrançois Tigeot return ret; 3149b030f26bSFrançois Tigeot 3150a05eeebfSFrançois Tigeot trace_i915_gem_ring_flush(req, I915_GEM_GPU_DOMAINS, flush_domains); 3151a2fdbec6SFrançois Tigeot 3152b030f26bSFrançois Tigeot ring->gpu_caches_dirty = false; 3153b030f26bSFrançois Tigeot return 0; 3154b030f26bSFrançois Tigeot } 3155ba55f2f5SFrançois Tigeot 3156ba55f2f5SFrançois Tigeot void 3157ba55f2f5SFrançois Tigeot intel_stop_ring_buffer(struct intel_engine_cs *ring) 3158ba55f2f5SFrançois Tigeot { 3159ba55f2f5SFrançois Tigeot int ret; 3160ba55f2f5SFrançois Tigeot 3161ba55f2f5SFrançois Tigeot if (!intel_ring_initialized(ring)) 3162ba55f2f5SFrançois Tigeot return; 3163ba55f2f5SFrançois Tigeot 3164ba55f2f5SFrançois Tigeot ret = intel_ring_idle(ring); 3165ba55f2f5SFrançois Tigeot if (ret && !i915_reset_in_progress(&to_i915(ring->dev)->gpu_error)) 3166ba55f2f5SFrançois Tigeot DRM_ERROR("failed to quiesce %s whilst cleaning up: %d\n", 3167ba55f2f5SFrançois Tigeot ring->name, ret); 3168ba55f2f5SFrançois Tigeot 3169ba55f2f5SFrançois Tigeot stop_ring(ring); 3170ba55f2f5SFrançois Tigeot } 3171