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 3018e26a6dSFrançois Tigeot #include <drm/drmP.h> 31e3adcf8fSFrançois Tigeot #include "i915_drv.h" 32a2fdbec6SFrançois Tigeot #include <drm/i915_drm.h> 33a2fdbec6SFrançois Tigeot #include "i915_trace.h" 34e3adcf8fSFrançois Tigeot #include "intel_drv.h" 35e3adcf8fSFrançois Tigeot 36ba55f2f5SFrançois Tigeot /* Early gen2 devices have a cacheline of just 32 bytes, using 64 is overkill, 37ba55f2f5SFrançois Tigeot * but keeps the logic simple. Indeed, the whole purpose of this macro is just 38ba55f2f5SFrançois Tigeot * to give some inclination as to some of the magic values used in the various 39ba55f2f5SFrançois Tigeot * workarounds! 40ba55f2f5SFrançois Tigeot */ 41ba55f2f5SFrançois Tigeot #define CACHELINE_BYTES 64 42ba55f2f5SFrançois Tigeot 43ba55f2f5SFrançois Tigeot static inline int __ring_space(int head, int tail, int size) 44e3adcf8fSFrançois Tigeot { 45ba55f2f5SFrançois Tigeot int space = head - (tail + I915_RING_FREE_SPACE); 46e3adcf8fSFrançois Tigeot if (space < 0) 47ba55f2f5SFrançois Tigeot space += size; 48e3adcf8fSFrançois Tigeot return space; 49e3adcf8fSFrançois Tigeot } 50e3adcf8fSFrançois Tigeot 51*24edb884SFrançois Tigeot static inline int ring_space(struct intel_ringbuffer *ringbuf) 52ba55f2f5SFrançois Tigeot { 53ba55f2f5SFrançois Tigeot return __ring_space(ringbuf->head & HEAD_ADDR, ringbuf->tail, ringbuf->size); 54ba55f2f5SFrançois Tigeot } 55ba55f2f5SFrançois Tigeot 56ba55f2f5SFrançois Tigeot static bool intel_ring_stopped(struct intel_engine_cs *ring) 579edbd4a0SFrançois Tigeot { 589edbd4a0SFrançois Tigeot struct drm_i915_private *dev_priv = ring->dev->dev_private; 59ba55f2f5SFrançois Tigeot return dev_priv->gpu_error.stop_rings & intel_ring_flag(ring); 60ba55f2f5SFrançois Tigeot } 619edbd4a0SFrançois Tigeot 62ba55f2f5SFrançois Tigeot void __intel_ring_advance(struct intel_engine_cs *ring) 63ba55f2f5SFrançois Tigeot { 64ba55f2f5SFrançois Tigeot struct intel_ringbuffer *ringbuf = ring->buffer; 65ba55f2f5SFrançois Tigeot ringbuf->tail &= ringbuf->size - 1; 66ba55f2f5SFrançois Tigeot if (intel_ring_stopped(ring)) 679edbd4a0SFrançois Tigeot return; 68ba55f2f5SFrançois Tigeot ring->write_tail(ring, ringbuf->tail); 699edbd4a0SFrançois Tigeot } 709edbd4a0SFrançois Tigeot 71e3adcf8fSFrançois Tigeot static int 72ba55f2f5SFrançois Tigeot gen2_render_ring_flush(struct intel_engine_cs *ring, 73686a02f1SFrançois Tigeot u32 invalidate_domains, 74686a02f1SFrançois Tigeot u32 flush_domains) 75686a02f1SFrançois Tigeot { 76686a02f1SFrançois Tigeot u32 cmd; 77686a02f1SFrançois Tigeot int ret; 78686a02f1SFrançois Tigeot 79686a02f1SFrançois Tigeot cmd = MI_FLUSH; 80686a02f1SFrançois Tigeot if (((invalidate_domains|flush_domains) & I915_GEM_DOMAIN_RENDER) == 0) 81686a02f1SFrançois Tigeot cmd |= MI_NO_WRITE_FLUSH; 82686a02f1SFrançois Tigeot 83686a02f1SFrançois Tigeot if (invalidate_domains & I915_GEM_DOMAIN_SAMPLER) 84686a02f1SFrançois Tigeot cmd |= MI_READ_FLUSH; 85686a02f1SFrançois Tigeot 86686a02f1SFrançois Tigeot ret = intel_ring_begin(ring, 2); 87686a02f1SFrançois Tigeot if (ret) 88686a02f1SFrançois Tigeot return ret; 89686a02f1SFrançois Tigeot 90686a02f1SFrançois Tigeot intel_ring_emit(ring, cmd); 91686a02f1SFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 92686a02f1SFrançois Tigeot intel_ring_advance(ring); 93686a02f1SFrançois Tigeot 94686a02f1SFrançois Tigeot return 0; 95686a02f1SFrançois Tigeot } 96686a02f1SFrançois Tigeot 97686a02f1SFrançois Tigeot static int 98ba55f2f5SFrançois Tigeot gen4_render_ring_flush(struct intel_engine_cs *ring, 99686a02f1SFrançois Tigeot u32 invalidate_domains, 100686a02f1SFrançois Tigeot u32 flush_domains) 101e3adcf8fSFrançois Tigeot { 102e3adcf8fSFrançois Tigeot struct drm_device *dev = ring->dev; 103686a02f1SFrançois Tigeot u32 cmd; 104e3adcf8fSFrançois Tigeot int ret; 105e3adcf8fSFrançois Tigeot 106e3adcf8fSFrançois Tigeot /* 107e3adcf8fSFrançois Tigeot * read/write caches: 108e3adcf8fSFrançois Tigeot * 109e3adcf8fSFrançois Tigeot * I915_GEM_DOMAIN_RENDER is always invalidated, but is 110e3adcf8fSFrançois Tigeot * only flushed if MI_NO_WRITE_FLUSH is unset. On 965, it is 111e3adcf8fSFrançois Tigeot * also flushed at 2d versus 3d pipeline switches. 112e3adcf8fSFrançois Tigeot * 113e3adcf8fSFrançois Tigeot * read-only caches: 114e3adcf8fSFrançois Tigeot * 115e3adcf8fSFrançois Tigeot * I915_GEM_DOMAIN_SAMPLER is flushed on pre-965 if 116e3adcf8fSFrançois Tigeot * MI_READ_FLUSH is set, and is always flushed on 965. 117e3adcf8fSFrançois Tigeot * 118e3adcf8fSFrançois Tigeot * I915_GEM_DOMAIN_COMMAND may not exist? 119e3adcf8fSFrançois Tigeot * 120e3adcf8fSFrançois Tigeot * I915_GEM_DOMAIN_INSTRUCTION, which exists on 965, is 121e3adcf8fSFrançois Tigeot * invalidated when MI_EXE_FLUSH is set. 122e3adcf8fSFrançois Tigeot * 123e3adcf8fSFrançois Tigeot * I915_GEM_DOMAIN_VERTEX, which exists on 965, is 124e3adcf8fSFrançois Tigeot * invalidated with every MI_FLUSH. 125e3adcf8fSFrançois Tigeot * 126e3adcf8fSFrançois Tigeot * TLBs: 127e3adcf8fSFrançois Tigeot * 128e3adcf8fSFrançois Tigeot * On 965, TLBs associated with I915_GEM_DOMAIN_COMMAND 129e3adcf8fSFrançois Tigeot * and I915_GEM_DOMAIN_CPU in are invalidated at PTE write and 130e3adcf8fSFrançois Tigeot * I915_GEM_DOMAIN_RENDER and I915_GEM_DOMAIN_SAMPLER 131e3adcf8fSFrançois Tigeot * are flushed at any MI_FLUSH. 132e3adcf8fSFrançois Tigeot */ 133e3adcf8fSFrançois Tigeot 134e3adcf8fSFrançois Tigeot cmd = MI_FLUSH | MI_NO_WRITE_FLUSH; 135686a02f1SFrançois Tigeot if ((invalidate_domains|flush_domains) & I915_GEM_DOMAIN_RENDER) 136e3adcf8fSFrançois Tigeot cmd &= ~MI_NO_WRITE_FLUSH; 137e3adcf8fSFrançois Tigeot if (invalidate_domains & I915_GEM_DOMAIN_INSTRUCTION) 138e3adcf8fSFrançois Tigeot cmd |= MI_EXE_FLUSH; 139e3adcf8fSFrançois Tigeot 140e3adcf8fSFrançois Tigeot if (invalidate_domains & I915_GEM_DOMAIN_COMMAND && 141e3adcf8fSFrançois Tigeot (IS_G4X(dev) || IS_GEN5(dev))) 142e3adcf8fSFrançois Tigeot cmd |= MI_INVALIDATE_ISP; 143e3adcf8fSFrançois Tigeot 144e3adcf8fSFrançois Tigeot ret = intel_ring_begin(ring, 2); 145e3adcf8fSFrançois Tigeot if (ret) 146e3adcf8fSFrançois Tigeot return ret; 147e3adcf8fSFrançois Tigeot 148e3adcf8fSFrançois Tigeot intel_ring_emit(ring, cmd); 149e3adcf8fSFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 150e3adcf8fSFrançois Tigeot intel_ring_advance(ring); 151e3adcf8fSFrançois Tigeot 152e3adcf8fSFrançois Tigeot return 0; 153e3adcf8fSFrançois Tigeot } 154e3adcf8fSFrançois Tigeot 155e3adcf8fSFrançois Tigeot /** 156e3adcf8fSFrançois Tigeot * Emits a PIPE_CONTROL with a non-zero post-sync operation, for 157e3adcf8fSFrançois Tigeot * implementing two workarounds on gen6. From section 1.4.7.1 158e3adcf8fSFrançois Tigeot * "PIPE_CONTROL" of the Sandy Bridge PRM volume 2 part 1: 159e3adcf8fSFrançois Tigeot * 160e3adcf8fSFrançois Tigeot * [DevSNB-C+{W/A}] Before any depth stall flush (including those 161e3adcf8fSFrançois Tigeot * produced by non-pipelined state commands), software needs to first 162e3adcf8fSFrançois Tigeot * send a PIPE_CONTROL with no bits set except Post-Sync Operation != 163e3adcf8fSFrançois Tigeot * 0. 164e3adcf8fSFrançois Tigeot * 165e3adcf8fSFrançois Tigeot * [Dev-SNB{W/A}]: Before a PIPE_CONTROL with Write Cache Flush Enable 166e3adcf8fSFrançois Tigeot * =1, a PIPE_CONTROL with any non-zero post-sync-op is required. 167e3adcf8fSFrançois Tigeot * 168e3adcf8fSFrançois Tigeot * And the workaround for these two requires this workaround first: 169e3adcf8fSFrançois Tigeot * 170e3adcf8fSFrançois Tigeot * [Dev-SNB{W/A}]: Pipe-control with CS-stall bit set must be sent 171e3adcf8fSFrançois Tigeot * BEFORE the pipe-control with a post-sync op and no write-cache 172e3adcf8fSFrançois Tigeot * flushes. 173e3adcf8fSFrançois Tigeot * 174e3adcf8fSFrançois Tigeot * And this last workaround is tricky because of the requirements on 175e3adcf8fSFrançois Tigeot * that bit. From section 1.4.7.2.3 "Stall" of the Sandy Bridge PRM 176e3adcf8fSFrançois Tigeot * volume 2 part 1: 177e3adcf8fSFrançois Tigeot * 178e3adcf8fSFrançois Tigeot * "1 of the following must also be set: 179e3adcf8fSFrançois Tigeot * - Render Target Cache Flush Enable ([12] of DW1) 180e3adcf8fSFrançois Tigeot * - Depth Cache Flush Enable ([0] of DW1) 181e3adcf8fSFrançois Tigeot * - Stall at Pixel Scoreboard ([1] of DW1) 182e3adcf8fSFrançois Tigeot * - Depth Stall ([13] of DW1) 183e3adcf8fSFrançois Tigeot * - Post-Sync Operation ([13] of DW1) 184e3adcf8fSFrançois Tigeot * - Notify Enable ([8] of DW1)" 185e3adcf8fSFrançois Tigeot * 186e3adcf8fSFrançois Tigeot * The cache flushes require the workaround flush that triggered this 187e3adcf8fSFrançois Tigeot * one, so we can't use it. Depth stall would trigger the same. 188e3adcf8fSFrançois Tigeot * Post-sync nonzero is what triggered this second workaround, so we 189e3adcf8fSFrançois Tigeot * can't use that one either. Notify enable is IRQs, which aren't 190e3adcf8fSFrançois Tigeot * really our business. That leaves only stall at scoreboard. 191e3adcf8fSFrançois Tigeot */ 192e3adcf8fSFrançois Tigeot static int 193ba55f2f5SFrançois Tigeot intel_emit_post_sync_nonzero_flush(struct intel_engine_cs *ring) 194e3adcf8fSFrançois Tigeot { 195ba55f2f5SFrançois Tigeot u32 scratch_addr = ring->scratch.gtt_offset + 2 * CACHELINE_BYTES; 196e3adcf8fSFrançois Tigeot int ret; 197e3adcf8fSFrançois Tigeot 198e3adcf8fSFrançois Tigeot 199e3adcf8fSFrançois Tigeot ret = intel_ring_begin(ring, 6); 200e3adcf8fSFrançois Tigeot if (ret) 201e3adcf8fSFrançois Tigeot return ret; 202e3adcf8fSFrançois Tigeot 203e3adcf8fSFrançois Tigeot intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(5)); 204e3adcf8fSFrançois Tigeot intel_ring_emit(ring, PIPE_CONTROL_CS_STALL | 205e3adcf8fSFrançois Tigeot PIPE_CONTROL_STALL_AT_SCOREBOARD); 206e3adcf8fSFrançois Tigeot intel_ring_emit(ring, scratch_addr | PIPE_CONTROL_GLOBAL_GTT); /* address */ 207e3adcf8fSFrançois Tigeot intel_ring_emit(ring, 0); /* low dword */ 208e3adcf8fSFrançois Tigeot intel_ring_emit(ring, 0); /* high dword */ 209e3adcf8fSFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 210e3adcf8fSFrançois Tigeot intel_ring_advance(ring); 211e3adcf8fSFrançois Tigeot 212e3adcf8fSFrançois Tigeot ret = intel_ring_begin(ring, 6); 213e3adcf8fSFrançois Tigeot if (ret) 214e3adcf8fSFrançois Tigeot return ret; 215e3adcf8fSFrançois Tigeot 216e3adcf8fSFrançois Tigeot intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(5)); 217e3adcf8fSFrançois Tigeot intel_ring_emit(ring, PIPE_CONTROL_QW_WRITE); 218e3adcf8fSFrançois Tigeot intel_ring_emit(ring, scratch_addr | PIPE_CONTROL_GLOBAL_GTT); /* address */ 219e3adcf8fSFrançois Tigeot intel_ring_emit(ring, 0); 220e3adcf8fSFrançois Tigeot intel_ring_emit(ring, 0); 221e3adcf8fSFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 222e3adcf8fSFrançois Tigeot intel_ring_advance(ring); 223e3adcf8fSFrançois Tigeot 224e3adcf8fSFrançois Tigeot return 0; 225e3adcf8fSFrançois Tigeot } 226e3adcf8fSFrançois Tigeot 227e3adcf8fSFrançois Tigeot static int 228ba55f2f5SFrançois Tigeot gen6_render_ring_flush(struct intel_engine_cs *ring, 229e3adcf8fSFrançois Tigeot u32 invalidate_domains, u32 flush_domains) 230e3adcf8fSFrançois Tigeot { 231e3adcf8fSFrançois Tigeot u32 flags = 0; 232ba55f2f5SFrançois Tigeot u32 scratch_addr = ring->scratch.gtt_offset + 2 * CACHELINE_BYTES; 233e3adcf8fSFrançois Tigeot int ret; 234e3adcf8fSFrançois Tigeot 235e3adcf8fSFrançois Tigeot /* Force SNB workarounds for PIPE_CONTROL flushes */ 236686a02f1SFrançois Tigeot ret = intel_emit_post_sync_nonzero_flush(ring); 237686a02f1SFrançois Tigeot if (ret) 238686a02f1SFrançois Tigeot return ret; 239e3adcf8fSFrançois Tigeot 240e3adcf8fSFrançois Tigeot /* Just flush everything. Experiments have shown that reducing the 241e3adcf8fSFrançois Tigeot * number of bits based on the write domains has little performance 242e3adcf8fSFrançois Tigeot * impact. 243e3adcf8fSFrançois Tigeot */ 244b5c29a34SFrançois Tigeot if (flush_domains) { 245e3adcf8fSFrançois Tigeot flags |= PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH; 246b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_DEPTH_CACHE_FLUSH; 247b5c29a34SFrançois Tigeot /* 248b5c29a34SFrançois Tigeot * Ensure that any following seqno writes only happen 249b5c29a34SFrançois Tigeot * when the render cache is indeed flushed. 250b5c29a34SFrançois Tigeot */ 251b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_CS_STALL; 252b5c29a34SFrançois Tigeot } 253b5c29a34SFrançois Tigeot if (invalidate_domains) { 254686a02f1SFrançois Tigeot flags |= PIPE_CONTROL_TLB_INVALIDATE; 255e3adcf8fSFrançois Tigeot flags |= PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE; 256e3adcf8fSFrançois Tigeot flags |= PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE; 257e3adcf8fSFrançois Tigeot flags |= PIPE_CONTROL_VF_CACHE_INVALIDATE; 258e3adcf8fSFrançois Tigeot flags |= PIPE_CONTROL_CONST_CACHE_INVALIDATE; 259e3adcf8fSFrançois Tigeot flags |= PIPE_CONTROL_STATE_CACHE_INVALIDATE; 260686a02f1SFrançois Tigeot /* 261b5c29a34SFrançois Tigeot * TLB invalidate requires a post-sync write. 262686a02f1SFrançois Tigeot */ 263b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_QW_WRITE | PIPE_CONTROL_CS_STALL; 264b5c29a34SFrançois Tigeot } 265e3adcf8fSFrançois Tigeot 266b5c29a34SFrançois Tigeot ret = intel_ring_begin(ring, 4); 267e3adcf8fSFrançois Tigeot if (ret) 268e3adcf8fSFrançois Tigeot return ret; 269e3adcf8fSFrançois Tigeot 270b5c29a34SFrançois Tigeot intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(4)); 271e3adcf8fSFrançois Tigeot intel_ring_emit(ring, flags); 272e3adcf8fSFrançois Tigeot intel_ring_emit(ring, scratch_addr | PIPE_CONTROL_GLOBAL_GTT); 273b5c29a34SFrançois Tigeot intel_ring_emit(ring, 0); 274b5c29a34SFrançois Tigeot intel_ring_advance(ring); 275b5c29a34SFrançois Tigeot 276b5c29a34SFrançois Tigeot return 0; 277b5c29a34SFrançois Tigeot } 278b5c29a34SFrançois Tigeot 279b5c29a34SFrançois Tigeot static int 280ba55f2f5SFrançois Tigeot gen7_render_ring_cs_stall_wa(struct intel_engine_cs *ring) 281b5c29a34SFrançois Tigeot { 282b5c29a34SFrançois Tigeot int ret; 283b5c29a34SFrançois Tigeot 284b5c29a34SFrançois Tigeot ret = intel_ring_begin(ring, 4); 285b5c29a34SFrançois Tigeot if (ret) 286b5c29a34SFrançois Tigeot return ret; 287b5c29a34SFrançois Tigeot 288b5c29a34SFrançois Tigeot intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(4)); 289b5c29a34SFrançois Tigeot intel_ring_emit(ring, PIPE_CONTROL_CS_STALL | 290b5c29a34SFrançois Tigeot PIPE_CONTROL_STALL_AT_SCOREBOARD); 291b5c29a34SFrançois Tigeot intel_ring_emit(ring, 0); 292b5c29a34SFrançois Tigeot intel_ring_emit(ring, 0); 293b5c29a34SFrançois Tigeot intel_ring_advance(ring); 294b5c29a34SFrançois Tigeot 295b5c29a34SFrançois Tigeot return 0; 296b5c29a34SFrançois Tigeot } 297b5c29a34SFrançois Tigeot 298ba55f2f5SFrançois Tigeot static int gen7_ring_fbc_flush(struct intel_engine_cs *ring, u32 value) 2995d0b1887SFrançois Tigeot { 3005d0b1887SFrançois Tigeot int ret; 3015d0b1887SFrançois Tigeot 3025d0b1887SFrançois Tigeot if (!ring->fbc_dirty) 3035d0b1887SFrançois Tigeot return 0; 3045d0b1887SFrançois Tigeot 3059edbd4a0SFrançois Tigeot ret = intel_ring_begin(ring, 6); 3065d0b1887SFrançois Tigeot if (ret) 3075d0b1887SFrançois Tigeot return ret; 3085d0b1887SFrançois Tigeot /* WaFbcNukeOn3DBlt:ivb/hsw */ 3095d0b1887SFrançois Tigeot intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1)); 3105d0b1887SFrançois Tigeot intel_ring_emit(ring, MSG_FBC_REND_STATE); 3115d0b1887SFrançois Tigeot intel_ring_emit(ring, value); 3129edbd4a0SFrançois Tigeot intel_ring_emit(ring, MI_STORE_REGISTER_MEM(1) | MI_SRM_LRM_GLOBAL_GTT); 3139edbd4a0SFrançois Tigeot intel_ring_emit(ring, MSG_FBC_REND_STATE); 3149edbd4a0SFrançois Tigeot intel_ring_emit(ring, ring->scratch.gtt_offset + 256); 3155d0b1887SFrançois Tigeot intel_ring_advance(ring); 3165d0b1887SFrançois Tigeot 3175d0b1887SFrançois Tigeot ring->fbc_dirty = false; 3185d0b1887SFrançois Tigeot return 0; 3195d0b1887SFrançois Tigeot } 3205d0b1887SFrançois Tigeot 321b5c29a34SFrançois Tigeot static int 322ba55f2f5SFrançois Tigeot gen7_render_ring_flush(struct intel_engine_cs *ring, 323b5c29a34SFrançois Tigeot u32 invalidate_domains, u32 flush_domains) 324b5c29a34SFrançois Tigeot { 325b5c29a34SFrançois Tigeot u32 flags = 0; 326ba55f2f5SFrançois Tigeot u32 scratch_addr = ring->scratch.gtt_offset + 2 * CACHELINE_BYTES; 327b5c29a34SFrançois Tigeot int ret; 328b5c29a34SFrançois Tigeot 329b5c29a34SFrançois Tigeot /* 330b5c29a34SFrançois Tigeot * Ensure that any following seqno writes only happen when the render 331b5c29a34SFrançois Tigeot * cache is indeed flushed. 332b5c29a34SFrançois Tigeot * 333b5c29a34SFrançois Tigeot * Workaround: 4th PIPE_CONTROL command (except the ones with only 334b5c29a34SFrançois Tigeot * read-cache invalidate bits set) must have the CS_STALL bit set. We 335b5c29a34SFrançois Tigeot * don't try to be clever and just set it unconditionally. 336b5c29a34SFrançois Tigeot */ 337b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_CS_STALL; 338b5c29a34SFrançois Tigeot 339b5c29a34SFrançois Tigeot /* Just flush everything. Experiments have shown that reducing the 340b5c29a34SFrançois Tigeot * number of bits based on the write domains has little performance 341b5c29a34SFrançois Tigeot * impact. 342b5c29a34SFrançois Tigeot */ 343b5c29a34SFrançois Tigeot if (flush_domains) { 344b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH; 345b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_DEPTH_CACHE_FLUSH; 346b5c29a34SFrançois Tigeot } 347b5c29a34SFrançois Tigeot if (invalidate_domains) { 348b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_TLB_INVALIDATE; 349b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE; 350b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE; 351b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_VF_CACHE_INVALIDATE; 352b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_CONST_CACHE_INVALIDATE; 353b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_STATE_CACHE_INVALIDATE; 354b5c29a34SFrançois Tigeot /* 355b5c29a34SFrançois Tigeot * TLB invalidate requires a post-sync write. 356b5c29a34SFrançois Tigeot */ 357b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_QW_WRITE; 358a2fdbec6SFrançois Tigeot flags |= PIPE_CONTROL_GLOBAL_GTT_IVB; 359b5c29a34SFrançois Tigeot 3600dbf0ea8SMatthew Dillon flags |= PIPE_CONTROL_STALL_AT_SCOREBOARD; 3610dbf0ea8SMatthew Dillon 362b5c29a34SFrançois Tigeot /* Workaround: we must issue a pipe_control with CS-stall bit 363b5c29a34SFrançois Tigeot * set before a pipe_control command that has the state cache 364b5c29a34SFrançois Tigeot * invalidate bit set. */ 365b5c29a34SFrançois Tigeot gen7_render_ring_cs_stall_wa(ring); 366b5c29a34SFrançois Tigeot } 367b5c29a34SFrançois Tigeot 368b5c29a34SFrançois Tigeot ret = intel_ring_begin(ring, 4); 369b5c29a34SFrançois Tigeot if (ret) 370b5c29a34SFrançois Tigeot return ret; 371b5c29a34SFrançois Tigeot 372b5c29a34SFrançois Tigeot intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(4)); 373b5c29a34SFrançois Tigeot intel_ring_emit(ring, flags); 374a2fdbec6SFrançois Tigeot intel_ring_emit(ring, scratch_addr); 375b5c29a34SFrançois Tigeot intel_ring_emit(ring, 0); 376e3adcf8fSFrançois Tigeot intel_ring_advance(ring); 377e3adcf8fSFrançois Tigeot 3789edbd4a0SFrançois Tigeot if (!invalidate_domains && flush_domains) 3795d0b1887SFrançois Tigeot return gen7_ring_fbc_flush(ring, FBC_REND_NUKE); 3805d0b1887SFrançois Tigeot 381e3adcf8fSFrançois Tigeot return 0; 382e3adcf8fSFrançois Tigeot } 383e3adcf8fSFrançois Tigeot 3849edbd4a0SFrançois Tigeot static int 385*24edb884SFrançois Tigeot gen8_emit_pipe_control(struct intel_engine_cs *ring, 386*24edb884SFrançois Tigeot u32 flags, u32 scratch_addr) 387*24edb884SFrançois Tigeot { 388*24edb884SFrançois Tigeot int ret; 389*24edb884SFrançois Tigeot 390*24edb884SFrançois Tigeot ret = intel_ring_begin(ring, 6); 391*24edb884SFrançois Tigeot if (ret) 392*24edb884SFrançois Tigeot return ret; 393*24edb884SFrançois Tigeot 394*24edb884SFrançois Tigeot intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(6)); 395*24edb884SFrançois Tigeot intel_ring_emit(ring, flags); 396*24edb884SFrançois Tigeot intel_ring_emit(ring, scratch_addr); 397*24edb884SFrançois Tigeot intel_ring_emit(ring, 0); 398*24edb884SFrançois Tigeot intel_ring_emit(ring, 0); 399*24edb884SFrançois Tigeot intel_ring_emit(ring, 0); 400*24edb884SFrançois Tigeot intel_ring_advance(ring); 401*24edb884SFrançois Tigeot 402*24edb884SFrançois Tigeot return 0; 403*24edb884SFrançois Tigeot } 404*24edb884SFrançois Tigeot 405*24edb884SFrançois Tigeot static int 406ba55f2f5SFrançois Tigeot gen8_render_ring_flush(struct intel_engine_cs *ring, 4079edbd4a0SFrançois Tigeot u32 invalidate_domains, u32 flush_domains) 4089edbd4a0SFrançois Tigeot { 4099edbd4a0SFrançois Tigeot u32 flags = 0; 410ba55f2f5SFrançois Tigeot u32 scratch_addr = ring->scratch.gtt_offset + 2 * CACHELINE_BYTES; 4119edbd4a0SFrançois Tigeot int ret; 4129edbd4a0SFrançois Tigeot 4139edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_CS_STALL; 4149edbd4a0SFrançois Tigeot 4159edbd4a0SFrançois Tigeot if (flush_domains) { 4169edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH; 4179edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_DEPTH_CACHE_FLUSH; 4189edbd4a0SFrançois Tigeot } 4199edbd4a0SFrançois Tigeot if (invalidate_domains) { 4209edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_TLB_INVALIDATE; 4219edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE; 4229edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE; 4239edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_VF_CACHE_INVALIDATE; 4249edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_CONST_CACHE_INVALIDATE; 4259edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_STATE_CACHE_INVALIDATE; 4269edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_QW_WRITE; 4279edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_GLOBAL_GTT_IVB; 4289edbd4a0SFrançois Tigeot 429*24edb884SFrançois Tigeot /* WaCsStallBeforeStateCacheInvalidate:bdw,chv */ 430*24edb884SFrançois Tigeot ret = gen8_emit_pipe_control(ring, 431*24edb884SFrançois Tigeot PIPE_CONTROL_CS_STALL | 432*24edb884SFrançois Tigeot PIPE_CONTROL_STALL_AT_SCOREBOARD, 433*24edb884SFrançois Tigeot 0); 4349edbd4a0SFrançois Tigeot if (ret) 4359edbd4a0SFrançois Tigeot return ret; 436*24edb884SFrançois Tigeot } 4379edbd4a0SFrançois Tigeot 438*24edb884SFrançois Tigeot return gen8_emit_pipe_control(ring, flags, scratch_addr); 4399edbd4a0SFrançois Tigeot } 4409edbd4a0SFrançois Tigeot 441ba55f2f5SFrançois Tigeot static void ring_write_tail(struct intel_engine_cs *ring, 442b5c29a34SFrançois Tigeot u32 value) 443e3adcf8fSFrançois Tigeot { 444ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = ring->dev->dev_private; 445e3adcf8fSFrançois Tigeot I915_WRITE_TAIL(ring, value); 446e3adcf8fSFrançois Tigeot } 447e3adcf8fSFrançois Tigeot 448ba55f2f5SFrançois Tigeot u64 intel_ring_get_active_head(struct intel_engine_cs *ring) 449e3adcf8fSFrançois Tigeot { 450ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = ring->dev->dev_private; 451ba55f2f5SFrançois Tigeot u64 acthd; 452e3adcf8fSFrançois Tigeot 453ba55f2f5SFrançois Tigeot if (INTEL_INFO(ring->dev)->gen >= 8) 454ba55f2f5SFrançois Tigeot acthd = I915_READ64_2x32(RING_ACTHD(ring->mmio_base), 455ba55f2f5SFrançois Tigeot RING_ACTHD_UDW(ring->mmio_base)); 456ba55f2f5SFrançois Tigeot else if (INTEL_INFO(ring->dev)->gen >= 4) 457ba55f2f5SFrançois Tigeot acthd = I915_READ(RING_ACTHD(ring->mmio_base)); 458ba55f2f5SFrançois Tigeot else 459ba55f2f5SFrançois Tigeot acthd = I915_READ(ACTHD); 460ba55f2f5SFrançois Tigeot 461ba55f2f5SFrançois Tigeot return acthd; 462e3adcf8fSFrançois Tigeot } 463e3adcf8fSFrançois Tigeot 464ba55f2f5SFrançois Tigeot static void ring_setup_phys_status_page(struct intel_engine_cs *ring) 4655d0b1887SFrançois Tigeot { 4665d0b1887SFrançois Tigeot struct drm_i915_private *dev_priv = ring->dev->dev_private; 4675d0b1887SFrançois Tigeot u32 addr; 4685d0b1887SFrançois Tigeot 4695d0b1887SFrançois Tigeot addr = dev_priv->status_page_dmah->busaddr; 4705d0b1887SFrançois Tigeot if (INTEL_INFO(ring->dev)->gen >= 4) 4715d0b1887SFrançois Tigeot addr |= (dev_priv->status_page_dmah->busaddr >> 28) & 0xf0; 4725d0b1887SFrançois Tigeot I915_WRITE(HWS_PGA, addr); 4735d0b1887SFrançois Tigeot } 4745d0b1887SFrançois Tigeot 475ba55f2f5SFrançois Tigeot static bool stop_ring(struct intel_engine_cs *ring) 476e3adcf8fSFrançois Tigeot { 477ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = to_i915(ring->dev); 478e3adcf8fSFrançois Tigeot 479ba55f2f5SFrançois Tigeot if (!IS_GEN2(ring->dev)) { 480ba55f2f5SFrançois Tigeot I915_WRITE_MODE(ring, _MASKED_BIT_ENABLE(STOP_RING)); 481ba55f2f5SFrançois Tigeot if (wait_for_atomic((I915_READ_MODE(ring) & MODE_IDLE) != 0, 1000)) { 482ba55f2f5SFrançois Tigeot DRM_ERROR("%s :timed out trying to stop ring\n", ring->name); 483ba55f2f5SFrançois Tigeot return false; 484ba55f2f5SFrançois Tigeot } 485ba55f2f5SFrançois Tigeot } 486686a02f1SFrançois Tigeot 487e3adcf8fSFrançois Tigeot I915_WRITE_CTL(ring, 0); 488e3adcf8fSFrançois Tigeot I915_WRITE_HEAD(ring, 0); 489e3adcf8fSFrançois Tigeot ring->write_tail(ring, 0); 490e3adcf8fSFrançois Tigeot 491ba55f2f5SFrançois Tigeot if (!IS_GEN2(ring->dev)) { 492ba55f2f5SFrançois Tigeot (void)I915_READ_CTL(ring); 493ba55f2f5SFrançois Tigeot I915_WRITE_MODE(ring, _MASKED_BIT_DISABLE(STOP_RING)); 494ba55f2f5SFrançois Tigeot } 495e3adcf8fSFrançois Tigeot 496ba55f2f5SFrançois Tigeot return (I915_READ_HEAD(ring) & HEAD_ADDR) == 0; 497ba55f2f5SFrançois Tigeot } 498ba55f2f5SFrançois Tigeot 499ba55f2f5SFrançois Tigeot static int init_ring_common(struct intel_engine_cs *ring) 500ba55f2f5SFrançois Tigeot { 501ba55f2f5SFrançois Tigeot struct drm_device *dev = ring->dev; 502ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 503ba55f2f5SFrançois Tigeot struct intel_ringbuffer *ringbuf = ring->buffer; 504ba55f2f5SFrançois Tigeot struct drm_i915_gem_object *obj = ringbuf->obj; 505ba55f2f5SFrançois Tigeot int ret = 0; 506ba55f2f5SFrançois Tigeot 507ba55f2f5SFrançois Tigeot gen6_gt_force_wake_get(dev_priv, FORCEWAKE_ALL); 508ba55f2f5SFrançois Tigeot 509ba55f2f5SFrançois Tigeot if (!stop_ring(ring)) { 510ba55f2f5SFrançois Tigeot /* G45 ring initialization often fails to reset head to zero */ 511b5c29a34SFrançois Tigeot DRM_DEBUG_KMS("%s head not reset to zero " 512e3adcf8fSFrançois Tigeot "ctl %08x head %08x tail %08x start %08x\n", 513e3adcf8fSFrançois Tigeot ring->name, 514e3adcf8fSFrançois Tigeot I915_READ_CTL(ring), 515e3adcf8fSFrançois Tigeot I915_READ_HEAD(ring), 516e3adcf8fSFrançois Tigeot I915_READ_TAIL(ring), 517e3adcf8fSFrançois Tigeot I915_READ_START(ring)); 518e3adcf8fSFrançois Tigeot 519ba55f2f5SFrançois Tigeot if (!stop_ring(ring)) { 520e3adcf8fSFrançois Tigeot DRM_ERROR("failed to set %s head to zero " 521e3adcf8fSFrançois Tigeot "ctl %08x head %08x tail %08x start %08x\n", 522e3adcf8fSFrançois Tigeot ring->name, 523e3adcf8fSFrançois Tigeot I915_READ_CTL(ring), 524e3adcf8fSFrançois Tigeot I915_READ_HEAD(ring), 525e3adcf8fSFrançois Tigeot I915_READ_TAIL(ring), 526e3adcf8fSFrançois Tigeot I915_READ_START(ring)); 527686a02f1SFrançois Tigeot ret = -EIO; 528686a02f1SFrançois Tigeot goto out; 529e3adcf8fSFrançois Tigeot } 530ba55f2f5SFrançois Tigeot } 531ba55f2f5SFrançois Tigeot 532ba55f2f5SFrançois Tigeot if (I915_NEED_GFX_HWS(dev)) 533ba55f2f5SFrançois Tigeot intel_ring_setup_status_page(ring); 534ba55f2f5SFrançois Tigeot else 535ba55f2f5SFrançois Tigeot ring_setup_phys_status_page(ring); 536ba55f2f5SFrançois Tigeot 5370f370975SMatthew Dillon /* Enforce ordering by reading HEAD register back */ 5380f370975SMatthew Dillon I915_READ_HEAD(ring); 5390f370975SMatthew Dillon 540ba55f2f5SFrançois Tigeot /* Initialize the ring. This must happen _after_ we've cleared the ring 541ba55f2f5SFrançois Tigeot * registers with the above sequence (the readback of the HEAD registers 542ba55f2f5SFrançois Tigeot * also enforces ordering), otherwise the hw might lose the new ring 543ba55f2f5SFrançois Tigeot * register values. */ 544ba55f2f5SFrançois Tigeot I915_WRITE_START(ring, i915_gem_obj_ggtt_offset(obj)); 545ba55f2f5SFrançois Tigeot I915_WRITE_CTL(ring, 546ba55f2f5SFrançois Tigeot ((ringbuf->size - PAGE_SIZE) & RING_NR_PAGES) 547ba55f2f5SFrançois Tigeot | RING_VALID); 548ba55f2f5SFrançois Tigeot 549ba55f2f5SFrançois Tigeot /* If the head is still not zero, the ring is dead */ 550ba55f2f5SFrançois Tigeot if (wait_for((I915_READ_CTL(ring) & RING_VALID) != 0 && 551ba55f2f5SFrançois Tigeot I915_READ_START(ring) == i915_gem_obj_ggtt_offset(obj) && 552ba55f2f5SFrançois Tigeot (I915_READ_HEAD(ring) & HEAD_ADDR) == 0, 50)) { 553ba55f2f5SFrançois Tigeot DRM_ERROR("%s initialization failed " 554ba55f2f5SFrançois Tigeot "ctl %08x (valid? %d) head %08x tail %08x start %08x [expected %08lx]\n", 555ba55f2f5SFrançois Tigeot ring->name, 556ba55f2f5SFrançois Tigeot I915_READ_CTL(ring), I915_READ_CTL(ring) & RING_VALID, 557ba55f2f5SFrançois Tigeot I915_READ_HEAD(ring), I915_READ_TAIL(ring), 558ba55f2f5SFrançois Tigeot I915_READ_START(ring), (unsigned long)i915_gem_obj_ggtt_offset(obj)); 559ba55f2f5SFrançois Tigeot ret = -EIO; 560ba55f2f5SFrançois Tigeot goto out; 561ba55f2f5SFrançois Tigeot } 562e3adcf8fSFrançois Tigeot 563e3adcf8fSFrançois Tigeot if (!drm_core_check_feature(ring->dev, DRIVER_MODESET)) 564e3adcf8fSFrançois Tigeot i915_kernel_lost_context(ring->dev); 565e3adcf8fSFrançois Tigeot else { 566ba55f2f5SFrançois Tigeot ringbuf->head = I915_READ_HEAD(ring); 567ba55f2f5SFrançois Tigeot ringbuf->tail = I915_READ_TAIL(ring) & TAIL_ADDR; 568*24edb884SFrançois Tigeot ringbuf->space = ring_space(ringbuf); 569ba55f2f5SFrançois Tigeot ringbuf->last_retired_head = -1; 570e3adcf8fSFrançois Tigeot } 571e3adcf8fSFrançois Tigeot 5725d0b1887SFrançois Tigeot memset(&ring->hangcheck, 0, sizeof(ring->hangcheck)); 5735d0b1887SFrançois Tigeot 574686a02f1SFrançois Tigeot out: 5759edbd4a0SFrançois Tigeot gen6_gt_force_wake_put(dev_priv, FORCEWAKE_ALL); 576686a02f1SFrançois Tigeot 577686a02f1SFrançois Tigeot return ret; 578e3adcf8fSFrançois Tigeot } 579e3adcf8fSFrançois Tigeot 580e3adcf8fSFrançois Tigeot static int 581ba55f2f5SFrançois Tigeot init_pipe_control(struct intel_engine_cs *ring) 582e3adcf8fSFrançois Tigeot { 583e3adcf8fSFrançois Tigeot int ret; 584e3adcf8fSFrançois Tigeot 5859edbd4a0SFrançois Tigeot if (ring->scratch.obj) 586e3adcf8fSFrançois Tigeot return 0; 587e3adcf8fSFrançois Tigeot 5889edbd4a0SFrançois Tigeot ring->scratch.obj = i915_gem_alloc_object(ring->dev, 4096); 5899edbd4a0SFrançois Tigeot if (ring->scratch.obj == NULL) { 590e3adcf8fSFrançois Tigeot DRM_ERROR("Failed to allocate seqno page\n"); 591e3adcf8fSFrançois Tigeot ret = -ENOMEM; 592e3adcf8fSFrançois Tigeot goto err; 593e3adcf8fSFrançois Tigeot } 594e3adcf8fSFrançois Tigeot 595ba55f2f5SFrançois Tigeot ret = i915_gem_object_set_cache_level(ring->scratch.obj, I915_CACHE_LLC); 596ba55f2f5SFrançois Tigeot if (ret) 597ba55f2f5SFrançois Tigeot goto err_unref; 598e3adcf8fSFrançois Tigeot 599ba55f2f5SFrançois Tigeot ret = i915_gem_obj_ggtt_pin(ring->scratch.obj, 4096, 0); 600e3adcf8fSFrançois Tigeot if (ret) 601e3adcf8fSFrançois Tigeot goto err_unref; 602e3adcf8fSFrançois Tigeot 6039edbd4a0SFrançois Tigeot ring->scratch.gtt_offset = i915_gem_obj_ggtt_offset(ring->scratch.obj); 6049edbd4a0SFrançois Tigeot ring->scratch.cpu_page = kmap(ring->scratch.obj->pages[0]); 6059edbd4a0SFrançois Tigeot if (ring->scratch.cpu_page == NULL) { 6065d0b1887SFrançois Tigeot ret = -ENOMEM; 607e3adcf8fSFrançois Tigeot goto err_unpin; 6085d0b1887SFrançois Tigeot } 609a2fdbec6SFrançois Tigeot 610a2fdbec6SFrançois Tigeot DRM_DEBUG_DRIVER("%s pipe control offset: 0x%08x\n", 6119edbd4a0SFrançois Tigeot ring->name, ring->scratch.gtt_offset); 612e3adcf8fSFrançois Tigeot return 0; 613e3adcf8fSFrançois Tigeot 614e3adcf8fSFrançois Tigeot err_unpin: 615ba55f2f5SFrançois Tigeot i915_gem_object_ggtt_unpin(ring->scratch.obj); 616e3adcf8fSFrançois Tigeot err_unref: 6179edbd4a0SFrançois Tigeot drm_gem_object_unreference(&ring->scratch.obj->base); 618e3adcf8fSFrançois Tigeot err: 619e3adcf8fSFrançois Tigeot return ret; 620e3adcf8fSFrançois Tigeot } 621e3adcf8fSFrançois Tigeot 622ba55f2f5SFrançois Tigeot static int init_render_ring(struct intel_engine_cs *ring) 623e3adcf8fSFrançois Tigeot { 624e3adcf8fSFrançois Tigeot struct drm_device *dev = ring->dev; 625e3adcf8fSFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 626e3adcf8fSFrançois Tigeot int ret = init_ring_common(ring); 627*24edb884SFrançois Tigeot if (ret) 628*24edb884SFrançois Tigeot return ret; 629e3adcf8fSFrançois Tigeot 630ba55f2f5SFrançois Tigeot /* WaTimedSingleVertexDispatch:cl,bw,ctg,elk,ilk,snb */ 631ba55f2f5SFrançois Tigeot if (INTEL_INFO(dev)->gen >= 4 && INTEL_INFO(dev)->gen < 7) 632f4e1c372SFrançois Tigeot I915_WRITE(MI_MODE, _MASKED_BIT_ENABLE(VS_TIMER_DISPATCH)); 633f4e1c372SFrançois Tigeot 634f4e1c372SFrançois Tigeot /* We need to disable the AsyncFlip performance optimisations in order 635f4e1c372SFrançois Tigeot * to use MI_WAIT_FOR_EVENT within the CS. It should already be 636f4e1c372SFrançois Tigeot * programmed to '1' on all products. 6375d0b1887SFrançois Tigeot * 638ba55f2f5SFrançois Tigeot * WaDisableAsyncFlipPerfMode:snb,ivb,hsw,vlv,bdw,chv 639f4e1c372SFrançois Tigeot */ 640f4e1c372SFrançois Tigeot if (INTEL_INFO(dev)->gen >= 6) 641f4e1c372SFrançois Tigeot I915_WRITE(MI_MODE, _MASKED_BIT_ENABLE(ASYNC_FLIP_PERF_DISABLE)); 642f4e1c372SFrançois Tigeot 643f4e1c372SFrançois Tigeot /* Required for the hardware to program scanline values for waiting */ 644ba55f2f5SFrançois Tigeot /* WaEnableFlushTlbInvalidationMode:snb */ 645f4e1c372SFrançois Tigeot if (INTEL_INFO(dev)->gen == 6) 646f4e1c372SFrançois Tigeot I915_WRITE(GFX_MODE, 647ba55f2f5SFrançois Tigeot _MASKED_BIT_ENABLE(GFX_TLB_INVALIDATE_EXPLICIT)); 648f4e1c372SFrançois Tigeot 649ba55f2f5SFrançois Tigeot /* WaBCSVCSTlbInvalidationMode:ivb,vlv,hsw */ 650e3adcf8fSFrançois Tigeot if (IS_GEN7(dev)) 651e3adcf8fSFrançois Tigeot I915_WRITE(GFX_MODE_GEN7, 652ba55f2f5SFrançois Tigeot _MASKED_BIT_ENABLE(GFX_TLB_INVALIDATE_EXPLICIT) | 653f4e1c372SFrançois Tigeot _MASKED_BIT_ENABLE(GFX_REPLAY_MODE)); 654e3adcf8fSFrançois Tigeot 655e3adcf8fSFrançois Tigeot if (INTEL_INFO(dev)->gen >= 5) { 656e3adcf8fSFrançois Tigeot ret = init_pipe_control(ring); 657e3adcf8fSFrançois Tigeot if (ret) 658e3adcf8fSFrançois Tigeot return ret; 659e3adcf8fSFrançois Tigeot } 660e3adcf8fSFrançois Tigeot 661e3adcf8fSFrançois Tigeot if (IS_GEN6(dev)) { 662e3adcf8fSFrançois Tigeot /* From the Sandybridge PRM, volume 1 part 3, page 24: 663e3adcf8fSFrançois Tigeot * "If this bit is set, STCunit will have LRA as replacement 664e3adcf8fSFrançois Tigeot * policy. [...] This bit must be reset. LRA replacement 665e3adcf8fSFrançois Tigeot * policy is not supported." 666e3adcf8fSFrançois Tigeot */ 667e3adcf8fSFrançois Tigeot I915_WRITE(CACHE_MODE_0, 668f4e1c372SFrançois Tigeot _MASKED_BIT_DISABLE(CM0_STC_EVICT_DISABLE_LRA_SNB)); 669e3adcf8fSFrançois Tigeot } 670e3adcf8fSFrançois Tigeot 671f4e1c372SFrançois Tigeot if (INTEL_INFO(dev)->gen >= 6) 672f4e1c372SFrançois Tigeot I915_WRITE(INSTPM, _MASKED_BIT_ENABLE(INSTPM_FORCE_ORDERING)); 673f4e1c372SFrançois Tigeot 6749edbd4a0SFrançois Tigeot if (HAS_L3_DPF(dev)) 6759edbd4a0SFrançois Tigeot I915_WRITE_IMR(ring, ~GT_PARITY_ERROR(dev)); 676e3adcf8fSFrançois Tigeot 677e3adcf8fSFrançois Tigeot return ret; 678e3adcf8fSFrançois Tigeot } 679e3adcf8fSFrançois Tigeot 680ba55f2f5SFrançois Tigeot static void render_ring_cleanup(struct intel_engine_cs *ring) 681e3adcf8fSFrançois Tigeot { 682b5c29a34SFrançois Tigeot struct drm_device *dev = ring->dev; 683*24edb884SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 684*24edb884SFrançois Tigeot 685*24edb884SFrançois Tigeot if (dev_priv->semaphore_obj) { 686*24edb884SFrançois Tigeot i915_gem_object_ggtt_unpin(dev_priv->semaphore_obj); 687*24edb884SFrançois Tigeot drm_gem_object_unreference(&dev_priv->semaphore_obj->base); 688*24edb884SFrançois Tigeot dev_priv->semaphore_obj = NULL; 689*24edb884SFrançois Tigeot } 690b5c29a34SFrançois Tigeot 6919edbd4a0SFrançois Tigeot if (ring->scratch.obj == NULL) 692e3adcf8fSFrançois Tigeot return; 693e3adcf8fSFrançois Tigeot 6949edbd4a0SFrançois Tigeot if (INTEL_INFO(dev)->gen >= 5) { 6959edbd4a0SFrançois Tigeot kunmap(ring->scratch.obj->pages[0]); 696ba55f2f5SFrançois Tigeot i915_gem_object_ggtt_unpin(ring->scratch.obj); 6979edbd4a0SFrançois Tigeot } 698b5c29a34SFrançois Tigeot 6999edbd4a0SFrançois Tigeot drm_gem_object_unreference(&ring->scratch.obj->base); 7009edbd4a0SFrançois Tigeot ring->scratch.obj = NULL; 701e3adcf8fSFrançois Tigeot } 702e3adcf8fSFrançois Tigeot 703*24edb884SFrançois Tigeot static int gen8_rcs_signal(struct intel_engine_cs *signaller, 704*24edb884SFrançois Tigeot unsigned int num_dwords) 705*24edb884SFrançois Tigeot { 706*24edb884SFrançois Tigeot #define MBOX_UPDATE_DWORDS 8 707*24edb884SFrançois Tigeot struct drm_device *dev = signaller->dev; 708*24edb884SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 709*24edb884SFrançois Tigeot struct intel_engine_cs *waiter; 710*24edb884SFrançois Tigeot int i, ret, num_rings; 711*24edb884SFrançois Tigeot 712*24edb884SFrançois Tigeot num_rings = hweight32(INTEL_INFO(dev)->ring_mask); 713*24edb884SFrançois Tigeot num_dwords += (num_rings-1) * MBOX_UPDATE_DWORDS; 714*24edb884SFrançois Tigeot #undef MBOX_UPDATE_DWORDS 715*24edb884SFrançois Tigeot 716*24edb884SFrançois Tigeot ret = intel_ring_begin(signaller, num_dwords); 717*24edb884SFrançois Tigeot if (ret) 718*24edb884SFrançois Tigeot return ret; 719*24edb884SFrançois Tigeot 720*24edb884SFrançois Tigeot for_each_ring(waiter, dev_priv, i) { 721*24edb884SFrançois Tigeot u64 gtt_offset = signaller->semaphore.signal_ggtt[i]; 722*24edb884SFrançois Tigeot if (gtt_offset == MI_SEMAPHORE_SYNC_INVALID) 723*24edb884SFrançois Tigeot continue; 724*24edb884SFrançois Tigeot 725*24edb884SFrançois Tigeot intel_ring_emit(signaller, GFX_OP_PIPE_CONTROL(6)); 726*24edb884SFrançois Tigeot intel_ring_emit(signaller, PIPE_CONTROL_GLOBAL_GTT_IVB | 727*24edb884SFrançois Tigeot PIPE_CONTROL_QW_WRITE | 728*24edb884SFrançois Tigeot PIPE_CONTROL_FLUSH_ENABLE); 729*24edb884SFrançois Tigeot intel_ring_emit(signaller, lower_32_bits(gtt_offset)); 730*24edb884SFrançois Tigeot intel_ring_emit(signaller, upper_32_bits(gtt_offset)); 731*24edb884SFrançois Tigeot intel_ring_emit(signaller, signaller->outstanding_lazy_seqno); 732*24edb884SFrançois Tigeot intel_ring_emit(signaller, 0); 733*24edb884SFrançois Tigeot intel_ring_emit(signaller, MI_SEMAPHORE_SIGNAL | 734*24edb884SFrançois Tigeot MI_SEMAPHORE_TARGET(waiter->id)); 735*24edb884SFrançois Tigeot intel_ring_emit(signaller, 0); 736*24edb884SFrançois Tigeot } 737*24edb884SFrançois Tigeot 738*24edb884SFrançois Tigeot return 0; 739*24edb884SFrançois Tigeot } 740*24edb884SFrançois Tigeot 741*24edb884SFrançois Tigeot static int gen8_xcs_signal(struct intel_engine_cs *signaller, 742*24edb884SFrançois Tigeot unsigned int num_dwords) 743*24edb884SFrançois Tigeot { 744*24edb884SFrançois Tigeot #define MBOX_UPDATE_DWORDS 6 745*24edb884SFrançois Tigeot struct drm_device *dev = signaller->dev; 746*24edb884SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 747*24edb884SFrançois Tigeot struct intel_engine_cs *waiter; 748*24edb884SFrançois Tigeot int i, ret, num_rings; 749*24edb884SFrançois Tigeot 750*24edb884SFrançois Tigeot num_rings = hweight32(INTEL_INFO(dev)->ring_mask); 751*24edb884SFrançois Tigeot num_dwords += (num_rings-1) * MBOX_UPDATE_DWORDS; 752*24edb884SFrançois Tigeot #undef MBOX_UPDATE_DWORDS 753*24edb884SFrançois Tigeot 754*24edb884SFrançois Tigeot ret = intel_ring_begin(signaller, num_dwords); 755*24edb884SFrançois Tigeot if (ret) 756*24edb884SFrançois Tigeot return ret; 757*24edb884SFrançois Tigeot 758*24edb884SFrançois Tigeot for_each_ring(waiter, dev_priv, i) { 759*24edb884SFrançois Tigeot u64 gtt_offset = signaller->semaphore.signal_ggtt[i]; 760*24edb884SFrançois Tigeot if (gtt_offset == MI_SEMAPHORE_SYNC_INVALID) 761*24edb884SFrançois Tigeot continue; 762*24edb884SFrançois Tigeot 763*24edb884SFrançois Tigeot intel_ring_emit(signaller, (MI_FLUSH_DW + 1) | 764*24edb884SFrançois Tigeot MI_FLUSH_DW_OP_STOREDW); 765*24edb884SFrançois Tigeot intel_ring_emit(signaller, lower_32_bits(gtt_offset) | 766*24edb884SFrançois Tigeot MI_FLUSH_DW_USE_GTT); 767*24edb884SFrançois Tigeot intel_ring_emit(signaller, upper_32_bits(gtt_offset)); 768*24edb884SFrançois Tigeot intel_ring_emit(signaller, signaller->outstanding_lazy_seqno); 769*24edb884SFrançois Tigeot intel_ring_emit(signaller, MI_SEMAPHORE_SIGNAL | 770*24edb884SFrançois Tigeot MI_SEMAPHORE_TARGET(waiter->id)); 771*24edb884SFrançois Tigeot intel_ring_emit(signaller, 0); 772*24edb884SFrançois Tigeot } 773*24edb884SFrançois Tigeot 774*24edb884SFrançois Tigeot return 0; 775*24edb884SFrançois Tigeot } 776*24edb884SFrançois Tigeot 777ba55f2f5SFrançois Tigeot static int gen6_signal(struct intel_engine_cs *signaller, 778ba55f2f5SFrançois Tigeot unsigned int num_dwords) 779e3adcf8fSFrançois Tigeot { 780ba55f2f5SFrançois Tigeot struct drm_device *dev = signaller->dev; 781ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 782ba55f2f5SFrançois Tigeot struct intel_engine_cs *useless; 783*24edb884SFrançois Tigeot int i, ret, num_rings; 784ba55f2f5SFrançois Tigeot 785*24edb884SFrançois Tigeot #define MBOX_UPDATE_DWORDS 3 786*24edb884SFrançois Tigeot num_rings = hweight32(INTEL_INFO(dev)->ring_mask); 787*24edb884SFrançois Tigeot num_dwords += round_up((num_rings-1) * MBOX_UPDATE_DWORDS, 2); 788*24edb884SFrançois Tigeot #undef MBOX_UPDATE_DWORDS 789ba55f2f5SFrançois Tigeot 790ba55f2f5SFrançois Tigeot ret = intel_ring_begin(signaller, num_dwords); 791ba55f2f5SFrançois Tigeot if (ret) 792ba55f2f5SFrançois Tigeot return ret; 793ba55f2f5SFrançois Tigeot 794ba55f2f5SFrançois Tigeot for_each_ring(useless, dev_priv, i) { 795ba55f2f5SFrançois Tigeot u32 mbox_reg = signaller->semaphore.mbox.signal[i]; 796ba55f2f5SFrançois Tigeot if (mbox_reg != GEN6_NOSYNC) { 797ba55f2f5SFrançois Tigeot intel_ring_emit(signaller, MI_LOAD_REGISTER_IMM(1)); 798ba55f2f5SFrançois Tigeot intel_ring_emit(signaller, mbox_reg); 799ba55f2f5SFrançois Tigeot intel_ring_emit(signaller, signaller->outstanding_lazy_seqno); 800ba55f2f5SFrançois Tigeot } 801ba55f2f5SFrançois Tigeot } 802ba55f2f5SFrançois Tigeot 803*24edb884SFrançois Tigeot /* If num_dwords was rounded, make sure the tail pointer is correct */ 804*24edb884SFrançois Tigeot if (num_rings % 2 == 0) 805*24edb884SFrançois Tigeot intel_ring_emit(signaller, MI_NOOP); 806*24edb884SFrançois Tigeot 807ba55f2f5SFrançois Tigeot return 0; 808e3adcf8fSFrançois Tigeot } 809e3adcf8fSFrançois Tigeot 810e3adcf8fSFrançois Tigeot /** 811e3adcf8fSFrançois Tigeot * gen6_add_request - Update the semaphore mailbox registers 812e3adcf8fSFrançois Tigeot * 813e3adcf8fSFrançois Tigeot * @ring - ring that is adding a request 814e3adcf8fSFrançois Tigeot * @seqno - return seqno stuck into the ring 815e3adcf8fSFrançois Tigeot * 816e3adcf8fSFrançois Tigeot * Update the mailbox registers in the *other* rings with the current seqno. 817e3adcf8fSFrançois Tigeot * This acts like a signal in the canonical semaphore. 818e3adcf8fSFrançois Tigeot */ 819e3adcf8fSFrançois Tigeot static int 820ba55f2f5SFrançois Tigeot gen6_add_request(struct intel_engine_cs *ring) 821e3adcf8fSFrançois Tigeot { 822ba55f2f5SFrançois Tigeot int ret; 823e3adcf8fSFrançois Tigeot 824*24edb884SFrançois Tigeot if (ring->semaphore.signal) 825ba55f2f5SFrançois Tigeot ret = ring->semaphore.signal(ring, 4); 826*24edb884SFrançois Tigeot else 827*24edb884SFrançois Tigeot ret = intel_ring_begin(ring, 4); 828*24edb884SFrançois Tigeot 8299edbd4a0SFrançois Tigeot if (ret) 8309edbd4a0SFrançois Tigeot return ret; 8319edbd4a0SFrançois Tigeot 832e3adcf8fSFrançois Tigeot intel_ring_emit(ring, MI_STORE_DWORD_INDEX); 833e3adcf8fSFrançois Tigeot intel_ring_emit(ring, I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT); 8349edbd4a0SFrançois Tigeot intel_ring_emit(ring, ring->outstanding_lazy_seqno); 835e3adcf8fSFrançois Tigeot intel_ring_emit(ring, MI_USER_INTERRUPT); 8369edbd4a0SFrançois Tigeot __intel_ring_advance(ring); 837e3adcf8fSFrançois Tigeot 838e3adcf8fSFrançois Tigeot return 0; 839e3adcf8fSFrançois Tigeot } 840e3adcf8fSFrançois Tigeot 841a2fdbec6SFrançois Tigeot static inline bool i915_gem_has_seqno_wrapped(struct drm_device *dev, 842a2fdbec6SFrançois Tigeot u32 seqno) 843a2fdbec6SFrançois Tigeot { 844a2fdbec6SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 845a2fdbec6SFrançois Tigeot return dev_priv->last_seqno < seqno; 846a2fdbec6SFrançois Tigeot } 847a2fdbec6SFrançois Tigeot 848e3adcf8fSFrançois Tigeot /** 849e3adcf8fSFrançois Tigeot * intel_ring_sync - sync the waiter to the signaller on seqno 850e3adcf8fSFrançois Tigeot * 851e3adcf8fSFrançois Tigeot * @waiter - ring that is waiting 852e3adcf8fSFrançois Tigeot * @signaller - ring which has, or will signal 853e3adcf8fSFrançois Tigeot * @seqno - seqno which the waiter will block on 854e3adcf8fSFrançois Tigeot */ 855*24edb884SFrançois Tigeot 856*24edb884SFrançois Tigeot static int 857*24edb884SFrançois Tigeot gen8_ring_sync(struct intel_engine_cs *waiter, 858*24edb884SFrançois Tigeot struct intel_engine_cs *signaller, 859*24edb884SFrançois Tigeot u32 seqno) 860*24edb884SFrançois Tigeot { 861*24edb884SFrançois Tigeot struct drm_i915_private *dev_priv = waiter->dev->dev_private; 862*24edb884SFrançois Tigeot int ret; 863*24edb884SFrançois Tigeot 864*24edb884SFrançois Tigeot ret = intel_ring_begin(waiter, 4); 865*24edb884SFrançois Tigeot if (ret) 866*24edb884SFrançois Tigeot return ret; 867*24edb884SFrançois Tigeot 868*24edb884SFrançois Tigeot intel_ring_emit(waiter, MI_SEMAPHORE_WAIT | 869*24edb884SFrançois Tigeot MI_SEMAPHORE_GLOBAL_GTT | 870*24edb884SFrançois Tigeot MI_SEMAPHORE_POLL | 871*24edb884SFrançois Tigeot MI_SEMAPHORE_SAD_GTE_SDD); 872*24edb884SFrançois Tigeot intel_ring_emit(waiter, seqno); 873*24edb884SFrançois Tigeot intel_ring_emit(waiter, 874*24edb884SFrançois Tigeot lower_32_bits(GEN8_WAIT_OFFSET(waiter, signaller->id))); 875*24edb884SFrançois Tigeot intel_ring_emit(waiter, 876*24edb884SFrançois Tigeot upper_32_bits(GEN8_WAIT_OFFSET(waiter, signaller->id))); 877*24edb884SFrançois Tigeot intel_ring_advance(waiter); 878*24edb884SFrançois Tigeot return 0; 879*24edb884SFrançois Tigeot } 880*24edb884SFrançois Tigeot 881e3adcf8fSFrançois Tigeot static int 882ba55f2f5SFrançois Tigeot gen6_ring_sync(struct intel_engine_cs *waiter, 883ba55f2f5SFrançois Tigeot struct intel_engine_cs *signaller, 884e3adcf8fSFrançois Tigeot u32 seqno) 885e3adcf8fSFrançois Tigeot { 886e3adcf8fSFrançois Tigeot u32 dw1 = MI_SEMAPHORE_MBOX | 887e3adcf8fSFrançois Tigeot MI_SEMAPHORE_COMPARE | 888e3adcf8fSFrançois Tigeot MI_SEMAPHORE_REGISTER; 889ba55f2f5SFrançois Tigeot u32 wait_mbox = signaller->semaphore.mbox.wait[waiter->id]; 890ba55f2f5SFrançois Tigeot int ret; 891e3adcf8fSFrançois Tigeot 892686a02f1SFrançois Tigeot /* Throughout all of the GEM code, seqno passed implies our current 893686a02f1SFrançois Tigeot * seqno is >= the last seqno executed. However for hardware the 894686a02f1SFrançois Tigeot * comparison is strictly greater than. 895686a02f1SFrançois Tigeot */ 896686a02f1SFrançois Tigeot seqno -= 1; 897686a02f1SFrançois Tigeot 898ba55f2f5SFrançois Tigeot WARN_ON(wait_mbox == MI_SEMAPHORE_SYNC_INVALID); 899686a02f1SFrançois Tigeot 900e3adcf8fSFrançois Tigeot ret = intel_ring_begin(waiter, 4); 901e3adcf8fSFrançois Tigeot if (ret) 902e3adcf8fSFrançois Tigeot return ret; 903e3adcf8fSFrançois Tigeot 904a2fdbec6SFrançois Tigeot /* If seqno wrap happened, omit the wait with no-ops */ 905a2fdbec6SFrançois Tigeot if (likely(!i915_gem_has_seqno_wrapped(waiter->dev, seqno))) { 906ba55f2f5SFrançois Tigeot intel_ring_emit(waiter, dw1 | wait_mbox); 907e3adcf8fSFrançois Tigeot intel_ring_emit(waiter, seqno); 908e3adcf8fSFrançois Tigeot intel_ring_emit(waiter, 0); 909e3adcf8fSFrançois Tigeot intel_ring_emit(waiter, MI_NOOP); 910a2fdbec6SFrançois Tigeot } else { 911a2fdbec6SFrançois Tigeot intel_ring_emit(waiter, MI_NOOP); 912a2fdbec6SFrançois Tigeot intel_ring_emit(waiter, MI_NOOP); 913a2fdbec6SFrançois Tigeot intel_ring_emit(waiter, MI_NOOP); 914a2fdbec6SFrançois Tigeot intel_ring_emit(waiter, MI_NOOP); 915a2fdbec6SFrançois Tigeot } 916e3adcf8fSFrançois Tigeot intel_ring_advance(waiter); 917e3adcf8fSFrançois Tigeot 918e3adcf8fSFrançois Tigeot return 0; 919e3adcf8fSFrançois Tigeot } 920e3adcf8fSFrançois Tigeot 921e3adcf8fSFrançois Tigeot #define PIPE_CONTROL_FLUSH(ring__, addr__) \ 922e3adcf8fSFrançois Tigeot do { \ 923e3adcf8fSFrançois Tigeot intel_ring_emit(ring__, GFX_OP_PIPE_CONTROL(4) | PIPE_CONTROL_QW_WRITE | \ 924e3adcf8fSFrançois Tigeot PIPE_CONTROL_DEPTH_STALL); \ 925e3adcf8fSFrançois Tigeot intel_ring_emit(ring__, (addr__) | PIPE_CONTROL_GLOBAL_GTT); \ 926e3adcf8fSFrançois Tigeot intel_ring_emit(ring__, 0); \ 927e3adcf8fSFrançois Tigeot intel_ring_emit(ring__, 0); \ 928e3adcf8fSFrançois Tigeot } while (0) 929e3adcf8fSFrançois Tigeot 930e3adcf8fSFrançois Tigeot static int 931ba55f2f5SFrançois Tigeot pc_render_add_request(struct intel_engine_cs *ring) 932e3adcf8fSFrançois Tigeot { 933ba55f2f5SFrançois Tigeot u32 scratch_addr = ring->scratch.gtt_offset + 2 * CACHELINE_BYTES; 934e3adcf8fSFrançois Tigeot int ret; 935e3adcf8fSFrançois Tigeot 936e3adcf8fSFrançois Tigeot /* For Ironlake, MI_USER_INTERRUPT was deprecated and apparently 937e3adcf8fSFrançois Tigeot * incoherent with writes to memory, i.e. completely fubar, 938e3adcf8fSFrançois Tigeot * so we need to use PIPE_NOTIFY instead. 939e3adcf8fSFrançois Tigeot * 940e3adcf8fSFrançois Tigeot * However, we also need to workaround the qword write 941e3adcf8fSFrançois Tigeot * incoherence by flushing the 6 PIPE_NOTIFY buffers out to 942e3adcf8fSFrançois Tigeot * memory before requesting an interrupt. 943e3adcf8fSFrançois Tigeot */ 944e3adcf8fSFrançois Tigeot ret = intel_ring_begin(ring, 32); 945e3adcf8fSFrançois Tigeot if (ret) 946e3adcf8fSFrançois Tigeot return ret; 947e3adcf8fSFrançois Tigeot 948e3adcf8fSFrançois Tigeot intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(4) | PIPE_CONTROL_QW_WRITE | 949e3adcf8fSFrançois Tigeot PIPE_CONTROL_WRITE_FLUSH | 950e3adcf8fSFrançois Tigeot PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE); 9519edbd4a0SFrançois Tigeot intel_ring_emit(ring, ring->scratch.gtt_offset | PIPE_CONTROL_GLOBAL_GTT); 9529edbd4a0SFrançois Tigeot intel_ring_emit(ring, ring->outstanding_lazy_seqno); 953e3adcf8fSFrançois Tigeot intel_ring_emit(ring, 0); 954e3adcf8fSFrançois Tigeot PIPE_CONTROL_FLUSH(ring, scratch_addr); 955ba55f2f5SFrançois Tigeot scratch_addr += 2 * CACHELINE_BYTES; /* write to separate cachelines */ 956e3adcf8fSFrançois Tigeot PIPE_CONTROL_FLUSH(ring, scratch_addr); 957ba55f2f5SFrançois Tigeot scratch_addr += 2 * CACHELINE_BYTES; 958e3adcf8fSFrançois Tigeot PIPE_CONTROL_FLUSH(ring, scratch_addr); 959ba55f2f5SFrançois Tigeot scratch_addr += 2 * CACHELINE_BYTES; 960e3adcf8fSFrançois Tigeot PIPE_CONTROL_FLUSH(ring, scratch_addr); 961ba55f2f5SFrançois Tigeot scratch_addr += 2 * CACHELINE_BYTES; 962e3adcf8fSFrançois Tigeot PIPE_CONTROL_FLUSH(ring, scratch_addr); 963ba55f2f5SFrançois Tigeot scratch_addr += 2 * CACHELINE_BYTES; 964e3adcf8fSFrançois Tigeot PIPE_CONTROL_FLUSH(ring, scratch_addr); 965b5c29a34SFrançois Tigeot 966e3adcf8fSFrançois Tigeot intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(4) | PIPE_CONTROL_QW_WRITE | 967e3adcf8fSFrançois Tigeot PIPE_CONTROL_WRITE_FLUSH | 968e3adcf8fSFrançois Tigeot PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE | 969e3adcf8fSFrançois Tigeot PIPE_CONTROL_NOTIFY); 9709edbd4a0SFrançois Tigeot intel_ring_emit(ring, ring->scratch.gtt_offset | PIPE_CONTROL_GLOBAL_GTT); 9719edbd4a0SFrançois Tigeot intel_ring_emit(ring, ring->outstanding_lazy_seqno); 972e3adcf8fSFrançois Tigeot intel_ring_emit(ring, 0); 9739edbd4a0SFrançois Tigeot __intel_ring_advance(ring); 974e3adcf8fSFrançois Tigeot 975e3adcf8fSFrançois Tigeot return 0; 976e3adcf8fSFrançois Tigeot } 977e3adcf8fSFrançois Tigeot 978e3adcf8fSFrançois Tigeot static u32 979ba55f2f5SFrançois Tigeot gen6_ring_get_seqno(struct intel_engine_cs *ring, bool lazy_coherency) 980e3adcf8fSFrançois Tigeot { 981e3adcf8fSFrançois Tigeot /* Workaround to force correct ordering between irq and seqno writes on 982e3adcf8fSFrançois Tigeot * ivb (and maybe also on snb) by reading from a CS register (like 983e3adcf8fSFrançois Tigeot * ACTHD) before reading the status page. */ 984ba55f2f5SFrançois Tigeot if (!lazy_coherency) { 985ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = ring->dev->dev_private; 986ba55f2f5SFrançois Tigeot POSTING_READ(RING_ACTHD(ring->mmio_base)); 987ba55f2f5SFrançois Tigeot } 988ba55f2f5SFrançois Tigeot 989e3adcf8fSFrançois Tigeot return intel_read_status_page(ring, I915_GEM_HWS_INDEX); 990e3adcf8fSFrançois Tigeot } 991e3adcf8fSFrançois Tigeot 992b030f26bSFrançois Tigeot static u32 993ba55f2f5SFrançois Tigeot ring_get_seqno(struct intel_engine_cs *ring, bool lazy_coherency) 994e3adcf8fSFrançois Tigeot { 995e3adcf8fSFrançois Tigeot return intel_read_status_page(ring, I915_GEM_HWS_INDEX); 996e3adcf8fSFrançois Tigeot } 997e3adcf8fSFrançois Tigeot 998a2fdbec6SFrançois Tigeot static void 999ba55f2f5SFrançois Tigeot ring_set_seqno(struct intel_engine_cs *ring, u32 seqno) 1000a2fdbec6SFrançois Tigeot { 1001a2fdbec6SFrançois Tigeot intel_write_status_page(ring, I915_GEM_HWS_INDEX, seqno); 1002a2fdbec6SFrançois Tigeot } 1003a2fdbec6SFrançois Tigeot 1004b030f26bSFrançois Tigeot static u32 1005ba55f2f5SFrançois Tigeot pc_render_get_seqno(struct intel_engine_cs *ring, bool lazy_coherency) 1006e3adcf8fSFrançois Tigeot { 10079edbd4a0SFrançois Tigeot return ring->scratch.cpu_page[0]; 1008e3adcf8fSFrançois Tigeot } 1009e3adcf8fSFrançois Tigeot 1010a2fdbec6SFrançois Tigeot static void 1011ba55f2f5SFrançois Tigeot pc_render_set_seqno(struct intel_engine_cs *ring, u32 seqno) 1012a2fdbec6SFrançois Tigeot { 10139edbd4a0SFrançois Tigeot ring->scratch.cpu_page[0] = seqno; 1014a2fdbec6SFrançois Tigeot } 1015a2fdbec6SFrançois Tigeot 1016e3adcf8fSFrançois Tigeot static bool 1017ba55f2f5SFrançois Tigeot gen5_ring_get_irq(struct intel_engine_cs *ring) 1018e3adcf8fSFrançois Tigeot { 1019e3adcf8fSFrançois Tigeot struct drm_device *dev = ring->dev; 1020ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 1021e3adcf8fSFrançois Tigeot 1022e3adcf8fSFrançois Tigeot if (!dev->irq_enabled) 1023e3adcf8fSFrançois Tigeot return false; 1024e3adcf8fSFrançois Tigeot 102502727ecdSFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_EXCLUSIVE); 10269edbd4a0SFrançois Tigeot if (ring->irq_refcount++ == 0) 1027*24edb884SFrançois Tigeot gen5_enable_gt_irq(dev_priv, ring->irq_enable_mask); 102802727ecdSFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_RELEASE); 1029e3adcf8fSFrançois Tigeot 1030e3adcf8fSFrançois Tigeot return true; 1031e3adcf8fSFrançois Tigeot } 1032e3adcf8fSFrançois Tigeot 1033e3adcf8fSFrançois Tigeot static void 1034ba55f2f5SFrançois Tigeot gen5_ring_put_irq(struct intel_engine_cs *ring) 1035e3adcf8fSFrançois Tigeot { 1036e3adcf8fSFrançois Tigeot struct drm_device *dev = ring->dev; 1037ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 1038e3adcf8fSFrançois Tigeot 103902727ecdSFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_EXCLUSIVE); 10409edbd4a0SFrançois Tigeot if (--ring->irq_refcount == 0) 1041*24edb884SFrançois Tigeot gen5_disable_gt_irq(dev_priv, ring->irq_enable_mask); 1042686a02f1SFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_RELEASE); 1043686a02f1SFrançois Tigeot } 1044686a02f1SFrançois Tigeot 1045686a02f1SFrançois Tigeot static bool 1046ba55f2f5SFrançois Tigeot i9xx_ring_get_irq(struct intel_engine_cs *ring) 1047686a02f1SFrançois Tigeot { 1048686a02f1SFrançois Tigeot struct drm_device *dev = ring->dev; 1049ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 1050686a02f1SFrançois Tigeot 1051686a02f1SFrançois Tigeot if (!dev->irq_enabled) 1052686a02f1SFrançois Tigeot return false; 1053686a02f1SFrançois Tigeot 1054686a02f1SFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_EXCLUSIVE); 10559edbd4a0SFrançois Tigeot if (ring->irq_refcount++ == 0) { 1056686a02f1SFrançois Tigeot dev_priv->irq_mask &= ~ring->irq_enable_mask; 1057686a02f1SFrançois Tigeot I915_WRITE(IMR, dev_priv->irq_mask); 1058686a02f1SFrançois Tigeot POSTING_READ(IMR); 1059686a02f1SFrançois Tigeot } 1060686a02f1SFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_RELEASE); 1061686a02f1SFrançois Tigeot 1062686a02f1SFrançois Tigeot return true; 1063686a02f1SFrançois Tigeot } 1064686a02f1SFrançois Tigeot 1065686a02f1SFrançois Tigeot static void 1066ba55f2f5SFrançois Tigeot i9xx_ring_put_irq(struct intel_engine_cs *ring) 1067686a02f1SFrançois Tigeot { 1068686a02f1SFrançois Tigeot struct drm_device *dev = ring->dev; 1069ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 1070686a02f1SFrançois Tigeot 1071686a02f1SFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_EXCLUSIVE); 10729edbd4a0SFrançois Tigeot if (--ring->irq_refcount == 0) { 1073686a02f1SFrançois Tigeot dev_priv->irq_mask |= ring->irq_enable_mask; 1074686a02f1SFrançois Tigeot I915_WRITE(IMR, dev_priv->irq_mask); 1075686a02f1SFrançois Tigeot POSTING_READ(IMR); 1076686a02f1SFrançois Tigeot } 1077686a02f1SFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_RELEASE); 1078686a02f1SFrançois Tigeot } 1079686a02f1SFrançois Tigeot 1080686a02f1SFrançois Tigeot static bool 1081ba55f2f5SFrançois Tigeot i8xx_ring_get_irq(struct intel_engine_cs *ring) 1082686a02f1SFrançois Tigeot { 1083686a02f1SFrançois Tigeot struct drm_device *dev = ring->dev; 1084ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 1085686a02f1SFrançois Tigeot 1086686a02f1SFrançois Tigeot if (!dev->irq_enabled) 1087686a02f1SFrançois Tigeot return false; 1088686a02f1SFrançois Tigeot 1089686a02f1SFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_EXCLUSIVE); 10909edbd4a0SFrançois Tigeot if (ring->irq_refcount++ == 0) { 1091686a02f1SFrançois Tigeot dev_priv->irq_mask &= ~ring->irq_enable_mask; 1092686a02f1SFrançois Tigeot I915_WRITE16(IMR, dev_priv->irq_mask); 1093686a02f1SFrançois Tigeot POSTING_READ16(IMR); 1094686a02f1SFrançois Tigeot } 1095686a02f1SFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_RELEASE); 1096686a02f1SFrançois Tigeot 1097686a02f1SFrançois Tigeot return true; 1098686a02f1SFrançois Tigeot } 1099686a02f1SFrançois Tigeot 1100686a02f1SFrançois Tigeot static void 1101ba55f2f5SFrançois Tigeot i8xx_ring_put_irq(struct intel_engine_cs *ring) 1102686a02f1SFrançois Tigeot { 1103686a02f1SFrançois Tigeot struct drm_device *dev = ring->dev; 1104ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 1105686a02f1SFrançois Tigeot 1106686a02f1SFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_EXCLUSIVE); 11079edbd4a0SFrançois Tigeot if (--ring->irq_refcount == 0) { 1108686a02f1SFrançois Tigeot dev_priv->irq_mask |= ring->irq_enable_mask; 1109686a02f1SFrançois Tigeot I915_WRITE16(IMR, dev_priv->irq_mask); 1110686a02f1SFrançois Tigeot POSTING_READ16(IMR); 1111e3adcf8fSFrançois Tigeot } 111202727ecdSFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_RELEASE); 1113e3adcf8fSFrançois Tigeot } 1114e3adcf8fSFrançois Tigeot 1115ba55f2f5SFrançois Tigeot void intel_ring_setup_status_page(struct intel_engine_cs *ring) 1116e3adcf8fSFrançois Tigeot { 1117e3adcf8fSFrançois Tigeot struct drm_device *dev = ring->dev; 1118ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = ring->dev->dev_private; 1119b5c29a34SFrançois Tigeot u32 mmio = 0; 1120e3adcf8fSFrançois Tigeot 1121e3adcf8fSFrançois Tigeot /* The ring status page addresses are no longer next to the rest of 1122e3adcf8fSFrançois Tigeot * the ring registers as of gen7. 1123e3adcf8fSFrançois Tigeot */ 1124e3adcf8fSFrançois Tigeot if (IS_GEN7(dev)) { 1125e3adcf8fSFrançois Tigeot switch (ring->id) { 1126e3adcf8fSFrançois Tigeot case RCS: 1127e3adcf8fSFrançois Tigeot mmio = RENDER_HWS_PGA_GEN7; 1128e3adcf8fSFrançois Tigeot break; 1129e3adcf8fSFrançois Tigeot case BCS: 1130e3adcf8fSFrançois Tigeot mmio = BLT_HWS_PGA_GEN7; 1131e3adcf8fSFrançois Tigeot break; 1132ba55f2f5SFrançois Tigeot /* 1133ba55f2f5SFrançois Tigeot * VCS2 actually doesn't exist on Gen7. Only shut up 1134ba55f2f5SFrançois Tigeot * gcc switch check warning 1135ba55f2f5SFrançois Tigeot */ 1136ba55f2f5SFrançois Tigeot case VCS2: 1137e3adcf8fSFrançois Tigeot case VCS: 1138e3adcf8fSFrançois Tigeot mmio = BSD_HWS_PGA_GEN7; 1139e3adcf8fSFrançois Tigeot break; 11405d0b1887SFrançois Tigeot case VECS: 11415d0b1887SFrançois Tigeot mmio = VEBOX_HWS_PGA_GEN7; 11425d0b1887SFrançois Tigeot break; 1143e3adcf8fSFrançois Tigeot } 1144b5c29a34SFrançois Tigeot } else if (IS_GEN6(ring->dev)) { 1145e3adcf8fSFrançois Tigeot mmio = RING_HWS_PGA_GEN6(ring->mmio_base); 1146e3adcf8fSFrançois Tigeot } else { 11479edbd4a0SFrançois Tigeot /* XXX: gen8 returns to sanity */ 1148e3adcf8fSFrançois Tigeot mmio = RING_HWS_PGA(ring->mmio_base); 1149e3adcf8fSFrançois Tigeot } 1150e3adcf8fSFrançois Tigeot 1151e3adcf8fSFrançois Tigeot I915_WRITE(mmio, (u32)ring->status_page.gfx_addr); 1152e3adcf8fSFrançois Tigeot POSTING_READ(mmio); 11535d0b1887SFrançois Tigeot 1154ba55f2f5SFrançois Tigeot /* 1155ba55f2f5SFrançois Tigeot * Flush the TLB for this page 1156ba55f2f5SFrançois Tigeot * 1157ba55f2f5SFrançois Tigeot * FIXME: These two bits have disappeared on gen8, so a question 1158ba55f2f5SFrançois Tigeot * arises: do we still need this and if so how should we go about 1159ba55f2f5SFrançois Tigeot * invalidating the TLB? 1160ba55f2f5SFrançois Tigeot */ 1161ba55f2f5SFrançois Tigeot if (INTEL_INFO(dev)->gen >= 6 && INTEL_INFO(dev)->gen < 8) { 11625d0b1887SFrançois Tigeot u32 reg = RING_INSTPM(ring->mmio_base); 1163ba55f2f5SFrançois Tigeot 1164ba55f2f5SFrançois Tigeot /* ring should be idle before issuing a sync flush*/ 1165ba55f2f5SFrançois Tigeot WARN_ON((I915_READ_MODE(ring) & MODE_IDLE) == 0); 1166ba55f2f5SFrançois Tigeot 11675d0b1887SFrançois Tigeot I915_WRITE(reg, 11685d0b1887SFrançois Tigeot _MASKED_BIT_ENABLE(INSTPM_TLB_INVALIDATE | 11695d0b1887SFrançois Tigeot INSTPM_SYNC_FLUSH)); 11705d0b1887SFrançois Tigeot if (wait_for((I915_READ(reg) & INSTPM_SYNC_FLUSH) == 0, 11715d0b1887SFrançois Tigeot 1000)) 11725d0b1887SFrançois Tigeot DRM_ERROR("%s: wait for SyncFlush to complete for TLB invalidation timed out\n", 11735d0b1887SFrançois Tigeot ring->name); 11745d0b1887SFrançois Tigeot } 1175e3adcf8fSFrançois Tigeot } 1176e3adcf8fSFrançois Tigeot 1177e3adcf8fSFrançois Tigeot static int 1178ba55f2f5SFrançois Tigeot bsd_ring_flush(struct intel_engine_cs *ring, 1179b5c29a34SFrançois Tigeot u32 invalidate_domains, 1180b5c29a34SFrançois Tigeot u32 flush_domains) 1181e3adcf8fSFrançois Tigeot { 1182e3adcf8fSFrançois Tigeot int ret; 1183e3adcf8fSFrançois Tigeot 1184e3adcf8fSFrançois Tigeot ret = intel_ring_begin(ring, 2); 1185e3adcf8fSFrançois Tigeot if (ret) 1186e3adcf8fSFrançois Tigeot return ret; 1187e3adcf8fSFrançois Tigeot 1188e3adcf8fSFrançois Tigeot intel_ring_emit(ring, MI_FLUSH); 1189e3adcf8fSFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 1190e3adcf8fSFrançois Tigeot intel_ring_advance(ring); 1191e3adcf8fSFrançois Tigeot return 0; 1192e3adcf8fSFrançois Tigeot } 1193e3adcf8fSFrançois Tigeot 1194e3adcf8fSFrançois Tigeot static int 1195ba55f2f5SFrançois Tigeot i9xx_add_request(struct intel_engine_cs *ring) 1196e3adcf8fSFrançois Tigeot { 1197e3adcf8fSFrançois Tigeot int ret; 1198e3adcf8fSFrançois Tigeot 1199e3adcf8fSFrançois Tigeot ret = intel_ring_begin(ring, 4); 1200e3adcf8fSFrançois Tigeot if (ret) 1201e3adcf8fSFrançois Tigeot return ret; 1202e3adcf8fSFrançois Tigeot 1203e3adcf8fSFrançois Tigeot intel_ring_emit(ring, MI_STORE_DWORD_INDEX); 1204e3adcf8fSFrançois Tigeot intel_ring_emit(ring, I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT); 12059edbd4a0SFrançois Tigeot intel_ring_emit(ring, ring->outstanding_lazy_seqno); 1206e3adcf8fSFrançois Tigeot intel_ring_emit(ring, MI_USER_INTERRUPT); 12079edbd4a0SFrançois Tigeot __intel_ring_advance(ring); 1208e3adcf8fSFrançois Tigeot 1209e3adcf8fSFrançois Tigeot return 0; 1210e3adcf8fSFrançois Tigeot } 1211e3adcf8fSFrançois Tigeot 1212e3adcf8fSFrançois Tigeot static bool 1213ba55f2f5SFrançois Tigeot gen6_ring_get_irq(struct intel_engine_cs *ring) 1214e3adcf8fSFrançois Tigeot { 1215e3adcf8fSFrançois Tigeot struct drm_device *dev = ring->dev; 1216ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 1217e3adcf8fSFrançois Tigeot 1218e3adcf8fSFrançois Tigeot if (!dev->irq_enabled) 1219e3adcf8fSFrançois Tigeot return false; 1220e3adcf8fSFrançois Tigeot 122102727ecdSFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_EXCLUSIVE); 12229edbd4a0SFrançois Tigeot if (ring->irq_refcount++ == 0) { 12239edbd4a0SFrançois Tigeot if (HAS_L3_DPF(dev) && ring->id == RCS) 12245d0b1887SFrançois Tigeot I915_WRITE_IMR(ring, 12255d0b1887SFrançois Tigeot ~(ring->irq_enable_mask | 12269edbd4a0SFrançois Tigeot GT_PARITY_ERROR(dev))); 1227686a02f1SFrançois Tigeot else 1228686a02f1SFrançois Tigeot I915_WRITE_IMR(ring, ~ring->irq_enable_mask); 1229*24edb884SFrançois Tigeot gen5_enable_gt_irq(dev_priv, ring->irq_enable_mask); 1230e3adcf8fSFrançois Tigeot } 123102727ecdSFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_RELEASE); 1232e3adcf8fSFrançois Tigeot 1233e3adcf8fSFrançois Tigeot return true; 1234e3adcf8fSFrançois Tigeot } 1235e3adcf8fSFrançois Tigeot 1236e3adcf8fSFrançois Tigeot static void 1237ba55f2f5SFrançois Tigeot gen6_ring_put_irq(struct intel_engine_cs *ring) 1238e3adcf8fSFrançois Tigeot { 1239e3adcf8fSFrançois Tigeot struct drm_device *dev = ring->dev; 1240ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 1241e3adcf8fSFrançois Tigeot 124202727ecdSFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_EXCLUSIVE); 12439edbd4a0SFrançois Tigeot if (--ring->irq_refcount == 0) { 12449edbd4a0SFrançois Tigeot if (HAS_L3_DPF(dev) && ring->id == RCS) 12459edbd4a0SFrançois Tigeot I915_WRITE_IMR(ring, ~GT_PARITY_ERROR(dev)); 1246686a02f1SFrançois Tigeot else 1247686a02f1SFrançois Tigeot I915_WRITE_IMR(ring, ~0); 1248*24edb884SFrançois Tigeot gen5_disable_gt_irq(dev_priv, ring->irq_enable_mask); 1249e3adcf8fSFrançois Tigeot } 125002727ecdSFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_RELEASE); 1251e3adcf8fSFrançois Tigeot } 1252e3adcf8fSFrançois Tigeot 12535d0b1887SFrançois Tigeot static bool 1254ba55f2f5SFrançois Tigeot hsw_vebox_get_irq(struct intel_engine_cs *ring) 12555d0b1887SFrançois Tigeot { 12565d0b1887SFrançois Tigeot struct drm_device *dev = ring->dev; 12575d0b1887SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 12585d0b1887SFrançois Tigeot 12595d0b1887SFrançois Tigeot if (!dev->irq_enabled) 12605d0b1887SFrançois Tigeot return false; 12615d0b1887SFrançois Tigeot 12629edbd4a0SFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_EXCLUSIVE); 12639edbd4a0SFrançois Tigeot if (ring->irq_refcount++ == 0) { 12645d0b1887SFrançois Tigeot I915_WRITE_IMR(ring, ~ring->irq_enable_mask); 1265*24edb884SFrançois Tigeot gen6_enable_pm_irq(dev_priv, ring->irq_enable_mask); 12665d0b1887SFrançois Tigeot } 12679edbd4a0SFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_RELEASE); 12685d0b1887SFrançois Tigeot 12695d0b1887SFrançois Tigeot return true; 12705d0b1887SFrançois Tigeot } 12715d0b1887SFrançois Tigeot 12725d0b1887SFrançois Tigeot static void 1273ba55f2f5SFrançois Tigeot hsw_vebox_put_irq(struct intel_engine_cs *ring) 12745d0b1887SFrançois Tigeot { 12755d0b1887SFrançois Tigeot struct drm_device *dev = ring->dev; 12765d0b1887SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 12775d0b1887SFrançois Tigeot 12785d0b1887SFrançois Tigeot if (!dev->irq_enabled) 12795d0b1887SFrançois Tigeot return; 12805d0b1887SFrançois Tigeot 12819edbd4a0SFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_EXCLUSIVE); 12829edbd4a0SFrançois Tigeot if (--ring->irq_refcount == 0) { 12835d0b1887SFrançois Tigeot I915_WRITE_IMR(ring, ~0); 1284*24edb884SFrançois Tigeot gen6_disable_pm_irq(dev_priv, ring->irq_enable_mask); 12855d0b1887SFrançois Tigeot } 12869edbd4a0SFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_RELEASE); 12879edbd4a0SFrançois Tigeot } 12889edbd4a0SFrançois Tigeot 12899edbd4a0SFrançois Tigeot static bool 1290ba55f2f5SFrançois Tigeot gen8_ring_get_irq(struct intel_engine_cs *ring) 12919edbd4a0SFrançois Tigeot { 12929edbd4a0SFrançois Tigeot struct drm_device *dev = ring->dev; 12939edbd4a0SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 12949edbd4a0SFrançois Tigeot 12959edbd4a0SFrançois Tigeot if (!dev->irq_enabled) 12969edbd4a0SFrançois Tigeot return false; 12979edbd4a0SFrançois Tigeot 12989edbd4a0SFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_EXCLUSIVE); 12999edbd4a0SFrançois Tigeot if (ring->irq_refcount++ == 0) { 13009edbd4a0SFrançois Tigeot if (HAS_L3_DPF(dev) && ring->id == RCS) { 13019edbd4a0SFrançois Tigeot I915_WRITE_IMR(ring, 13029edbd4a0SFrançois Tigeot ~(ring->irq_enable_mask | 13039edbd4a0SFrançois Tigeot GT_RENDER_L3_PARITY_ERROR_INTERRUPT)); 13049edbd4a0SFrançois Tigeot } else { 13059edbd4a0SFrançois Tigeot I915_WRITE_IMR(ring, ~ring->irq_enable_mask); 13069edbd4a0SFrançois Tigeot } 13079edbd4a0SFrançois Tigeot POSTING_READ(RING_IMR(ring->mmio_base)); 13089edbd4a0SFrançois Tigeot } 13099edbd4a0SFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_RELEASE); 13109edbd4a0SFrançois Tigeot 13119edbd4a0SFrançois Tigeot return true; 13129edbd4a0SFrançois Tigeot } 13139edbd4a0SFrançois Tigeot 13149edbd4a0SFrançois Tigeot static void 1315ba55f2f5SFrançois Tigeot gen8_ring_put_irq(struct intel_engine_cs *ring) 13169edbd4a0SFrançois Tigeot { 13179edbd4a0SFrançois Tigeot struct drm_device *dev = ring->dev; 13189edbd4a0SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 13199edbd4a0SFrançois Tigeot 13209edbd4a0SFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_EXCLUSIVE); 13219edbd4a0SFrançois Tigeot if (--ring->irq_refcount == 0) { 13229edbd4a0SFrançois Tigeot if (HAS_L3_DPF(dev) && ring->id == RCS) { 13239edbd4a0SFrançois Tigeot I915_WRITE_IMR(ring, 13249edbd4a0SFrançois Tigeot ~GT_RENDER_L3_PARITY_ERROR_INTERRUPT); 13259edbd4a0SFrançois Tigeot } else { 13269edbd4a0SFrançois Tigeot I915_WRITE_IMR(ring, ~0); 13279edbd4a0SFrançois Tigeot } 13289edbd4a0SFrançois Tigeot POSTING_READ(RING_IMR(ring->mmio_base)); 13299edbd4a0SFrançois Tigeot } 13309edbd4a0SFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_RELEASE); 13315d0b1887SFrançois Tigeot } 13325d0b1887SFrançois Tigeot 1333e3adcf8fSFrançois Tigeot static int 1334ba55f2f5SFrançois Tigeot i965_dispatch_execbuffer(struct intel_engine_cs *ring, 1335ba55f2f5SFrançois Tigeot u64 offset, u32 length, 1336b5c29a34SFrançois Tigeot unsigned flags) 1337e3adcf8fSFrançois Tigeot { 1338e3adcf8fSFrançois Tigeot int ret; 1339e3adcf8fSFrançois Tigeot 1340e3adcf8fSFrançois Tigeot ret = intel_ring_begin(ring, 2); 1341e3adcf8fSFrançois Tigeot if (ret) 1342e3adcf8fSFrançois Tigeot return ret; 1343e3adcf8fSFrançois Tigeot 1344e3adcf8fSFrançois Tigeot intel_ring_emit(ring, 1345686a02f1SFrançois Tigeot MI_BATCH_BUFFER_START | 1346b5c29a34SFrançois Tigeot MI_BATCH_GTT | 1347b5c29a34SFrançois Tigeot (flags & I915_DISPATCH_SECURE ? 0 : MI_BATCH_NON_SECURE_I965)); 1348e3adcf8fSFrançois Tigeot intel_ring_emit(ring, offset); 1349e3adcf8fSFrançois Tigeot intel_ring_advance(ring); 1350e3adcf8fSFrançois Tigeot 1351e3adcf8fSFrançois Tigeot return 0; 1352e3adcf8fSFrançois Tigeot } 1353e3adcf8fSFrançois Tigeot 1354b5c29a34SFrançois Tigeot /* Just userspace ABI convention to limit the wa batch bo to a resonable size */ 1355b5c29a34SFrançois Tigeot #define I830_BATCH_LIMIT (256*1024) 1356*24edb884SFrançois Tigeot #define I830_TLB_ENTRIES (2) 1357*24edb884SFrançois Tigeot #define I830_WA_SIZE max(I830_TLB_ENTRIES*4096, I830_BATCH_LIMIT) 1358e3adcf8fSFrançois Tigeot static int 1359ba55f2f5SFrançois Tigeot i830_dispatch_execbuffer(struct intel_engine_cs *ring, 1360ba55f2f5SFrançois Tigeot u64 offset, u32 len, 1361b5c29a34SFrançois Tigeot unsigned flags) 1362e3adcf8fSFrançois Tigeot { 1363*24edb884SFrançois Tigeot u32 cs_offset = ring->scratch.gtt_offset; 1364e3adcf8fSFrançois Tigeot int ret; 1365e3adcf8fSFrançois Tigeot 1366*24edb884SFrançois Tigeot ret = intel_ring_begin(ring, 6); 1367*24edb884SFrançois Tigeot if (ret) 1368*24edb884SFrançois Tigeot return ret; 1369*24edb884SFrançois Tigeot 1370*24edb884SFrançois Tigeot /* Evict the invalid PTE TLBs */ 1371*24edb884SFrançois Tigeot intel_ring_emit(ring, COLOR_BLT_CMD | BLT_WRITE_RGBA); 1372*24edb884SFrançois Tigeot intel_ring_emit(ring, BLT_DEPTH_32 | BLT_ROP_COLOR_COPY | 4096); 1373*24edb884SFrançois Tigeot intel_ring_emit(ring, I830_TLB_ENTRIES << 16 | 4); /* load each page */ 1374*24edb884SFrançois Tigeot intel_ring_emit(ring, cs_offset); 1375*24edb884SFrançois Tigeot intel_ring_emit(ring, 0xdeadbeef); 1376*24edb884SFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 1377*24edb884SFrançois Tigeot intel_ring_advance(ring); 1378*24edb884SFrançois Tigeot 1379*24edb884SFrançois Tigeot if ((flags & I915_DISPATCH_PINNED) == 0) { 1380*24edb884SFrançois Tigeot if (len > I830_BATCH_LIMIT) 1381*24edb884SFrançois Tigeot return -ENOSPC; 1382*24edb884SFrançois Tigeot 1383*24edb884SFrançois Tigeot ret = intel_ring_begin(ring, 6 + 2); 1384*24edb884SFrançois Tigeot if (ret) 1385*24edb884SFrançois Tigeot return ret; 1386*24edb884SFrançois Tigeot 1387*24edb884SFrançois Tigeot /* Blit the batch (which has now all relocs applied) to the 1388*24edb884SFrançois Tigeot * stable batch scratch bo area (so that the CS never 1389*24edb884SFrançois Tigeot * stumbles over its tlb invalidation bug) ... 1390*24edb884SFrançois Tigeot */ 1391*24edb884SFrançois Tigeot intel_ring_emit(ring, SRC_COPY_BLT_CMD | BLT_WRITE_RGBA); 1392*24edb884SFrançois Tigeot intel_ring_emit(ring, BLT_DEPTH_32 | BLT_ROP_SRC_COPY | 4096); 1393*24edb884SFrançois Tigeot intel_ring_emit(ring, DIV_ROUND_UP(len, 4096) << 16 | 4096); 1394*24edb884SFrançois Tigeot intel_ring_emit(ring, cs_offset); 1395*24edb884SFrançois Tigeot intel_ring_emit(ring, 4096); 1396*24edb884SFrançois Tigeot intel_ring_emit(ring, offset); 1397*24edb884SFrançois Tigeot 1398*24edb884SFrançois Tigeot intel_ring_emit(ring, MI_FLUSH); 1399*24edb884SFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 1400*24edb884SFrançois Tigeot intel_ring_advance(ring); 1401*24edb884SFrançois Tigeot 1402*24edb884SFrançois Tigeot /* ... and execute it. */ 1403*24edb884SFrançois Tigeot offset = cs_offset; 1404*24edb884SFrançois Tigeot } 1405*24edb884SFrançois Tigeot 1406e3adcf8fSFrançois Tigeot ret = intel_ring_begin(ring, 4); 1407e3adcf8fSFrançois Tigeot if (ret) 1408e3adcf8fSFrançois Tigeot return ret; 1409e3adcf8fSFrançois Tigeot 1410e3adcf8fSFrançois Tigeot intel_ring_emit(ring, MI_BATCH_BUFFER); 1411b5c29a34SFrançois Tigeot intel_ring_emit(ring, offset | (flags & I915_DISPATCH_SECURE ? 0 : MI_BATCH_NON_SECURE)); 1412e3adcf8fSFrançois Tigeot intel_ring_emit(ring, offset + len - 8); 1413b5c29a34SFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 1414686a02f1SFrançois Tigeot intel_ring_advance(ring); 1415686a02f1SFrançois Tigeot 1416686a02f1SFrançois Tigeot return 0; 1417686a02f1SFrançois Tigeot } 1418686a02f1SFrançois Tigeot 1419686a02f1SFrançois Tigeot static int 1420ba55f2f5SFrançois Tigeot i915_dispatch_execbuffer(struct intel_engine_cs *ring, 1421ba55f2f5SFrançois Tigeot u64 offset, u32 len, 1422b5c29a34SFrançois Tigeot unsigned flags) 1423686a02f1SFrançois Tigeot { 1424686a02f1SFrançois Tigeot int ret; 1425686a02f1SFrançois Tigeot 1426e3adcf8fSFrançois Tigeot ret = intel_ring_begin(ring, 2); 1427e3adcf8fSFrançois Tigeot if (ret) 1428e3adcf8fSFrançois Tigeot return ret; 1429e3adcf8fSFrançois Tigeot 1430686a02f1SFrançois Tigeot intel_ring_emit(ring, MI_BATCH_BUFFER_START | MI_BATCH_GTT); 1431686a02f1SFrançois Tigeot intel_ring_emit(ring, offset | (flags & I915_DISPATCH_SECURE ? 0 : MI_BATCH_NON_SECURE)); 1432e3adcf8fSFrançois Tigeot intel_ring_advance(ring); 1433e3adcf8fSFrançois Tigeot 1434e3adcf8fSFrançois Tigeot return 0; 1435e3adcf8fSFrançois Tigeot } 1436e3adcf8fSFrançois Tigeot 1437ba55f2f5SFrançois Tigeot static void cleanup_status_page(struct intel_engine_cs *ring) 1438e3adcf8fSFrançois Tigeot { 1439e3adcf8fSFrançois Tigeot struct drm_i915_gem_object *obj; 1440e3adcf8fSFrançois Tigeot 1441e3adcf8fSFrançois Tigeot obj = ring->status_page.obj; 1442e3adcf8fSFrançois Tigeot if (obj == NULL) 1443e3adcf8fSFrançois Tigeot return; 1444e3adcf8fSFrançois Tigeot 14459edbd4a0SFrançois Tigeot kunmap(obj->pages[0]); 1446ba55f2f5SFrançois Tigeot i915_gem_object_ggtt_unpin(obj); 1447e3adcf8fSFrançois Tigeot drm_gem_object_unreference(&obj->base); 1448e3adcf8fSFrançois Tigeot ring->status_page.obj = NULL; 1449e3adcf8fSFrançois Tigeot } 1450e3adcf8fSFrançois Tigeot 1451ba55f2f5SFrançois Tigeot static int init_status_page(struct intel_engine_cs *ring) 1452e3adcf8fSFrançois Tigeot { 1453e3adcf8fSFrançois Tigeot struct drm_i915_gem_object *obj; 1454ba55f2f5SFrançois Tigeot 1455ba55f2f5SFrançois Tigeot if ((obj = ring->status_page.obj) == NULL) { 1456*24edb884SFrançois Tigeot unsigned flags; 1457e3adcf8fSFrançois Tigeot int ret; 1458e3adcf8fSFrançois Tigeot 1459ba55f2f5SFrançois Tigeot obj = i915_gem_alloc_object(ring->dev, 4096); 1460e3adcf8fSFrançois Tigeot if (obj == NULL) { 1461e3adcf8fSFrançois Tigeot DRM_ERROR("Failed to allocate status page\n"); 1462ba55f2f5SFrançois Tigeot return -ENOMEM; 1463e3adcf8fSFrançois Tigeot } 1464e3adcf8fSFrançois Tigeot 1465ba55f2f5SFrançois Tigeot ret = i915_gem_object_set_cache_level(obj, I915_CACHE_LLC); 1466ba55f2f5SFrançois Tigeot if (ret) 1467e3adcf8fSFrançois Tigeot goto err_unref; 1468ba55f2f5SFrançois Tigeot 1469*24edb884SFrançois Tigeot flags = 0; 1470*24edb884SFrançois Tigeot if (!HAS_LLC(ring->dev)) 1471*24edb884SFrançois Tigeot /* On g33, we cannot place HWS above 256MiB, so 1472*24edb884SFrançois Tigeot * restrict its pinning to the low mappable arena. 1473*24edb884SFrançois Tigeot * Though this restriction is not documented for 1474*24edb884SFrançois Tigeot * gen4, gen5, or byt, they also behave similarly 1475*24edb884SFrançois Tigeot * and hang if the HWS is placed at the top of the 1476*24edb884SFrançois Tigeot * GTT. To generalise, it appears that all !llc 1477*24edb884SFrançois Tigeot * platforms have issues with us placing the HWS 1478*24edb884SFrançois Tigeot * above the mappable region (even though we never 1479*24edb884SFrançois Tigeot * actualy map it). 1480*24edb884SFrançois Tigeot */ 1481*24edb884SFrançois Tigeot flags |= PIN_MAPPABLE; 1482*24edb884SFrançois Tigeot ret = i915_gem_obj_ggtt_pin(obj, 4096, flags); 1483ba55f2f5SFrançois Tigeot if (ret) { 1484ba55f2f5SFrançois Tigeot err_unref: 1485ba55f2f5SFrançois Tigeot drm_gem_object_unreference(&obj->base); 1486ba55f2f5SFrançois Tigeot return ret; 1487ba55f2f5SFrançois Tigeot } 1488ba55f2f5SFrançois Tigeot 1489ba55f2f5SFrançois Tigeot ring->status_page.obj = obj; 1490e3adcf8fSFrançois Tigeot } 1491e3adcf8fSFrançois Tigeot 14929edbd4a0SFrançois Tigeot ring->status_page.gfx_addr = i915_gem_obj_ggtt_offset(obj); 1493f4f90b23SFrançois Tigeot ring->status_page.page_addr = kmap(obj->pages[0]); 1494e3adcf8fSFrançois Tigeot memset(ring->status_page.page_addr, 0, PAGE_SIZE); 1495e3adcf8fSFrançois Tigeot 1496b5c29a34SFrançois Tigeot DRM_DEBUG_DRIVER("%s hws offset: 0x%08x\n", 1497e3adcf8fSFrançois Tigeot ring->name, ring->status_page.gfx_addr); 1498e3adcf8fSFrançois Tigeot 1499e3adcf8fSFrançois Tigeot return 0; 1500e3adcf8fSFrançois Tigeot } 1501e3adcf8fSFrançois Tigeot 1502ba55f2f5SFrançois Tigeot static int init_phys_status_page(struct intel_engine_cs *ring) 1503686a02f1SFrançois Tigeot { 1504686a02f1SFrançois Tigeot struct drm_i915_private *dev_priv = ring->dev->dev_private; 1505686a02f1SFrançois Tigeot 1506686a02f1SFrançois Tigeot if (!dev_priv->status_page_dmah) { 1507686a02f1SFrançois Tigeot dev_priv->status_page_dmah = 1508b31e9d59SFrançois Tigeot drm_pci_alloc(ring->dev, PAGE_SIZE, PAGE_SIZE); 1509686a02f1SFrançois Tigeot if (!dev_priv->status_page_dmah) 1510686a02f1SFrançois Tigeot return -ENOMEM; 1511686a02f1SFrançois Tigeot } 1512686a02f1SFrançois Tigeot 1513686a02f1SFrançois Tigeot ring->status_page.page_addr = dev_priv->status_page_dmah->vaddr; 1514686a02f1SFrançois Tigeot memset(ring->status_page.page_addr, 0, PAGE_SIZE); 1515686a02f1SFrançois Tigeot 1516686a02f1SFrançois Tigeot return 0; 1517686a02f1SFrançois Tigeot } 1518686a02f1SFrançois Tigeot 1519*24edb884SFrançois Tigeot static void intel_destroy_ringbuffer_obj(struct intel_ringbuffer *ringbuf) 1520e3adcf8fSFrançois Tigeot { 1521*24edb884SFrançois Tigeot if (!ringbuf->obj) 1522*24edb884SFrançois Tigeot return; 1523*24edb884SFrançois Tigeot 1524*24edb884SFrançois Tigeot iounmap(ringbuf->virtual_start, ringbuf->size); 1525*24edb884SFrançois Tigeot i915_gem_object_ggtt_unpin(ringbuf->obj); 1526*24edb884SFrançois Tigeot drm_gem_object_unreference(&ringbuf->obj->base); 1527*24edb884SFrançois Tigeot ringbuf->obj = NULL; 1528*24edb884SFrançois Tigeot } 1529*24edb884SFrançois Tigeot 1530*24edb884SFrançois Tigeot static int intel_alloc_ringbuffer_obj(struct drm_device *dev, 1531*24edb884SFrançois Tigeot struct intel_ringbuffer *ringbuf) 1532*24edb884SFrançois Tigeot { 1533e3adcf8fSFrançois Tigeot struct drm_i915_gem_object *obj; 1534e3adcf8fSFrançois Tigeot int ret; 1535e3adcf8fSFrançois Tigeot 1536*24edb884SFrançois Tigeot if (ringbuf->obj) 1537ba55f2f5SFrançois Tigeot return 0; 1538e3adcf8fSFrançois Tigeot 1539a2fdbec6SFrançois Tigeot obj = NULL; 1540a2fdbec6SFrançois Tigeot if (!HAS_LLC(dev)) 1541ba55f2f5SFrançois Tigeot obj = i915_gem_object_create_stolen(dev, ringbuf->size); 1542a2fdbec6SFrançois Tigeot if (obj == NULL) 1543ba55f2f5SFrançois Tigeot obj = i915_gem_alloc_object(dev, ringbuf->size); 1544ba55f2f5SFrançois Tigeot if (obj == NULL) 1545ba55f2f5SFrançois Tigeot return -ENOMEM; 1546e3adcf8fSFrançois Tigeot 1547*24edb884SFrançois Tigeot /* mark ring buffers as read-only from GPU side by default */ 1548*24edb884SFrançois Tigeot obj->gt_ro = 1; 1549*24edb884SFrançois Tigeot 1550ba55f2f5SFrançois Tigeot ret = i915_gem_obj_ggtt_pin(obj, PAGE_SIZE, PIN_MAPPABLE); 1551e3adcf8fSFrançois Tigeot if (ret) 1552e3adcf8fSFrançois Tigeot goto err_unref; 1553e3adcf8fSFrançois Tigeot 1554686a02f1SFrançois Tigeot ret = i915_gem_object_set_to_gtt_domain(obj, true); 1555686a02f1SFrançois Tigeot if (ret) 1556686a02f1SFrançois Tigeot goto err_unpin; 1557e3adcf8fSFrançois Tigeot 1558ba55f2f5SFrançois Tigeot ringbuf->virtual_start = 15599edbd4a0SFrançois Tigeot ioremap_wc(dev->agp->base + i915_gem_obj_ggtt_offset(obj), 1560ba55f2f5SFrançois Tigeot ringbuf->size); 1561ba55f2f5SFrançois Tigeot if (ringbuf->virtual_start == NULL) { 1562e3adcf8fSFrançois Tigeot ret = -EINVAL; 1563e3adcf8fSFrançois Tigeot goto err_unpin; 1564e3adcf8fSFrançois Tigeot } 1565e3adcf8fSFrançois Tigeot 1566ba55f2f5SFrançois Tigeot ringbuf->obj = obj; 1567ba55f2f5SFrançois Tigeot return 0; 1568ba55f2f5SFrançois Tigeot 1569ba55f2f5SFrançois Tigeot err_unpin: 1570ba55f2f5SFrançois Tigeot i915_gem_object_ggtt_unpin(obj); 1571ba55f2f5SFrançois Tigeot err_unref: 1572ba55f2f5SFrançois Tigeot drm_gem_object_unreference(&obj->base); 1573ba55f2f5SFrançois Tigeot return ret; 1574ba55f2f5SFrançois Tigeot } 1575ba55f2f5SFrançois Tigeot 1576ba55f2f5SFrançois Tigeot static int intel_init_ring_buffer(struct drm_device *dev, 1577ba55f2f5SFrançois Tigeot struct intel_engine_cs *ring) 1578ba55f2f5SFrançois Tigeot { 1579ba55f2f5SFrançois Tigeot struct intel_ringbuffer *ringbuf = ring->buffer; 1580ba55f2f5SFrançois Tigeot int ret; 1581ba55f2f5SFrançois Tigeot 1582ba55f2f5SFrançois Tigeot if (ringbuf == NULL) { 1583ba55f2f5SFrançois Tigeot ringbuf = kzalloc(sizeof(*ringbuf), GFP_KERNEL); 1584ba55f2f5SFrançois Tigeot if (!ringbuf) 1585ba55f2f5SFrançois Tigeot return -ENOMEM; 1586ba55f2f5SFrançois Tigeot ring->buffer = ringbuf; 1587ba55f2f5SFrançois Tigeot } 1588ba55f2f5SFrançois Tigeot 1589ba55f2f5SFrançois Tigeot ring->dev = dev; 1590ba55f2f5SFrançois Tigeot INIT_LIST_HEAD(&ring->active_list); 1591ba55f2f5SFrançois Tigeot INIT_LIST_HEAD(&ring->request_list); 1592ba55f2f5SFrançois Tigeot ringbuf->size = 32 * PAGE_SIZE; 1593ba55f2f5SFrançois Tigeot memset(ring->semaphore.sync_seqno, 0, sizeof(ring->semaphore.sync_seqno)); 1594ba55f2f5SFrançois Tigeot 1595ba55f2f5SFrançois Tigeot init_waitqueue_head(&ring->irq_queue); 1596ba55f2f5SFrançois Tigeot 1597ba55f2f5SFrançois Tigeot if (I915_NEED_GFX_HWS(dev)) { 1598ba55f2f5SFrançois Tigeot ret = init_status_page(ring); 1599e3adcf8fSFrançois Tigeot if (ret) 1600ba55f2f5SFrançois Tigeot goto error; 1601ba55f2f5SFrançois Tigeot } else { 1602ba55f2f5SFrançois Tigeot BUG_ON(ring->id != RCS); 1603ba55f2f5SFrançois Tigeot ret = init_phys_status_page(ring); 1604ba55f2f5SFrançois Tigeot if (ret) 1605ba55f2f5SFrançois Tigeot goto error; 1606ba55f2f5SFrançois Tigeot } 1607ba55f2f5SFrançois Tigeot 1608*24edb884SFrançois Tigeot ret = intel_alloc_ringbuffer_obj(dev, ringbuf); 1609ba55f2f5SFrançois Tigeot if (ret) { 1610ba55f2f5SFrançois Tigeot DRM_ERROR("Failed to allocate ringbuffer %s: %d\n", ring->name, ret); 1611ba55f2f5SFrançois Tigeot goto error; 1612ba55f2f5SFrançois Tigeot } 1613e3adcf8fSFrançois Tigeot 1614e3adcf8fSFrançois Tigeot /* Workaround an erratum on the i830 which causes a hang if 1615e3adcf8fSFrançois Tigeot * the TAIL pointer points to within the last 2 cachelines 1616e3adcf8fSFrançois Tigeot * of the buffer. 1617e3adcf8fSFrançois Tigeot */ 1618ba55f2f5SFrançois Tigeot ringbuf->effective_size = ringbuf->size; 1619ba55f2f5SFrançois Tigeot if (IS_I830(dev) || IS_845G(dev)) 1620ba55f2f5SFrançois Tigeot ringbuf->effective_size -= 2 * CACHELINE_BYTES; 1621ba55f2f5SFrançois Tigeot 1622ba55f2f5SFrançois Tigeot ret = i915_cmd_parser_init_ring(ring); 1623ba55f2f5SFrançois Tigeot if (ret) 1624ba55f2f5SFrançois Tigeot goto error; 1625ba55f2f5SFrançois Tigeot 1626ba55f2f5SFrançois Tigeot ret = ring->init(ring); 1627ba55f2f5SFrançois Tigeot if (ret) 1628ba55f2f5SFrançois Tigeot goto error; 1629e3adcf8fSFrançois Tigeot 1630e3adcf8fSFrançois Tigeot return 0; 1631e3adcf8fSFrançois Tigeot 1632ba55f2f5SFrançois Tigeot error: 1633ba55f2f5SFrançois Tigeot kfree(ringbuf); 1634ba55f2f5SFrançois Tigeot ring->buffer = NULL; 1635e3adcf8fSFrançois Tigeot return ret; 1636e3adcf8fSFrançois Tigeot } 1637e3adcf8fSFrançois Tigeot 1638ba55f2f5SFrançois Tigeot void intel_cleanup_ring_buffer(struct intel_engine_cs *ring) 1639e3adcf8fSFrançois Tigeot { 1640ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = to_i915(ring->dev); 1641ba55f2f5SFrançois Tigeot struct intel_ringbuffer *ringbuf = ring->buffer; 1642e3adcf8fSFrançois Tigeot 1643ba55f2f5SFrançois Tigeot if (!intel_ring_initialized(ring)) 1644e3adcf8fSFrançois Tigeot return; 1645e3adcf8fSFrançois Tigeot 1646ba55f2f5SFrançois Tigeot intel_stop_ring_buffer(ring); 1647ba55f2f5SFrançois Tigeot WARN_ON(!IS_GEN2(ring->dev) && (I915_READ_MODE(ring) & MODE_IDLE) == 0); 1648b030f26bSFrançois Tigeot 1649*24edb884SFrançois Tigeot intel_destroy_ringbuffer_obj(ringbuf); 16509edbd4a0SFrançois Tigeot ring->preallocated_lazy_request = NULL; 16519edbd4a0SFrançois Tigeot ring->outstanding_lazy_seqno = 0; 1652e3adcf8fSFrançois Tigeot 1653e3adcf8fSFrançois Tigeot if (ring->cleanup) 1654e3adcf8fSFrançois Tigeot ring->cleanup(ring); 1655e3adcf8fSFrançois Tigeot 1656e3adcf8fSFrançois Tigeot cleanup_status_page(ring); 1657ba55f2f5SFrançois Tigeot 1658ba55f2f5SFrançois Tigeot i915_cmd_parser_fini_ring(ring); 1659ba55f2f5SFrançois Tigeot 1660ba55f2f5SFrançois Tigeot kfree(ringbuf); 1661ba55f2f5SFrançois Tigeot ring->buffer = NULL; 1662e3adcf8fSFrançois Tigeot } 1663e3adcf8fSFrançois Tigeot 1664ba55f2f5SFrançois Tigeot static int intel_ring_wait_request(struct intel_engine_cs *ring, int n) 1665e3adcf8fSFrançois Tigeot { 1666ba55f2f5SFrançois Tigeot struct intel_ringbuffer *ringbuf = ring->buffer; 1667e3adcf8fSFrançois Tigeot struct drm_i915_gem_request *request; 1668e3adcf8fSFrançois Tigeot u32 seqno = 0; 1669e3adcf8fSFrançois Tigeot int ret; 1670e3adcf8fSFrançois Tigeot 1671ba55f2f5SFrançois Tigeot if (ringbuf->last_retired_head != -1) { 1672ba55f2f5SFrançois Tigeot ringbuf->head = ringbuf->last_retired_head; 1673ba55f2f5SFrançois Tigeot ringbuf->last_retired_head = -1; 1674e3adcf8fSFrançois Tigeot 1675*24edb884SFrançois Tigeot ringbuf->space = ring_space(ringbuf); 1676ba55f2f5SFrançois Tigeot if (ringbuf->space >= n) 1677e3adcf8fSFrançois Tigeot return 0; 1678e3adcf8fSFrançois Tigeot } 1679e3adcf8fSFrançois Tigeot 1680e3adcf8fSFrançois Tigeot list_for_each_entry(request, &ring->request_list, list) { 1681ba55f2f5SFrançois Tigeot if (__ring_space(request->tail, ringbuf->tail, ringbuf->size) >= n) { 1682e3adcf8fSFrançois Tigeot seqno = request->seqno; 1683e3adcf8fSFrançois Tigeot break; 1684e3adcf8fSFrançois Tigeot } 1685e3adcf8fSFrançois Tigeot } 1686e3adcf8fSFrançois Tigeot 1687e3adcf8fSFrançois Tigeot if (seqno == 0) 1688e3adcf8fSFrançois Tigeot return -ENOSPC; 1689e3adcf8fSFrançois Tigeot 1690ba55f2f5SFrançois Tigeot ret = i915_wait_seqno(ring, seqno); 1691e3adcf8fSFrançois Tigeot if (ret) 1692e3adcf8fSFrançois Tigeot return ret; 1693e3adcf8fSFrançois Tigeot 1694ba55f2f5SFrançois Tigeot i915_gem_retire_requests_ring(ring); 1695ba55f2f5SFrançois Tigeot ringbuf->head = ringbuf->last_retired_head; 1696ba55f2f5SFrançois Tigeot ringbuf->last_retired_head = -1; 1697e3adcf8fSFrançois Tigeot 1698*24edb884SFrançois Tigeot ringbuf->space = ring_space(ringbuf); 1699e3adcf8fSFrançois Tigeot return 0; 1700e3adcf8fSFrançois Tigeot } 1701e3adcf8fSFrançois Tigeot 1702ba55f2f5SFrançois Tigeot static int ring_wait_for_space(struct intel_engine_cs *ring, int n) 1703e3adcf8fSFrançois Tigeot { 1704e3adcf8fSFrançois Tigeot struct drm_device *dev = ring->dev; 1705e3adcf8fSFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 1706ba55f2f5SFrançois Tigeot struct intel_ringbuffer *ringbuf = ring->buffer; 1707245593daSFrançois Tigeot unsigned long end; 1708e3adcf8fSFrançois Tigeot int ret; 1709e3adcf8fSFrançois Tigeot 1710e3adcf8fSFrançois Tigeot ret = intel_ring_wait_request(ring, n); 1711e3adcf8fSFrançois Tigeot if (ret != -ENOSPC) 1712e3adcf8fSFrançois Tigeot return ret; 1713e3adcf8fSFrançois Tigeot 17149edbd4a0SFrançois Tigeot /* force the tail write in case we have been skipping them */ 17159edbd4a0SFrançois Tigeot __intel_ring_advance(ring); 17169edbd4a0SFrançois Tigeot 1717e3adcf8fSFrançois Tigeot /* With GEM the hangcheck timer should kick us out of the loop, 1718e3adcf8fSFrançois Tigeot * leaving it early runs the risk of corrupting GEM state (due 1719e3adcf8fSFrançois Tigeot * to running on almost untested codepaths). But on resume 1720e3adcf8fSFrançois Tigeot * timers don't work yet, so prevent a complete hang in that 1721e3adcf8fSFrançois Tigeot * case by choosing an insanely large timeout. */ 1722e3440f96SFrançois Tigeot end = jiffies + 60 * HZ; 1723245593daSFrançois Tigeot 1724ba55f2f5SFrançois Tigeot trace_i915_ring_wait_begin(ring); 1725e3adcf8fSFrançois Tigeot do { 1726ba55f2f5SFrançois Tigeot ringbuf->head = I915_READ_HEAD(ring); 1727*24edb884SFrançois Tigeot ringbuf->space = ring_space(ringbuf); 1728ba55f2f5SFrançois Tigeot if (ringbuf->space >= n) { 1729ba55f2f5SFrançois Tigeot ret = 0; 1730ba55f2f5SFrançois Tigeot break; 1731e3adcf8fSFrançois Tigeot } 1732e3adcf8fSFrançois Tigeot 1733e3adcf8fSFrançois Tigeot #if 0 1734ba55f2f5SFrançois Tigeot if (!drm_core_check_feature(dev, DRIVER_MODESET) && 1735ba55f2f5SFrançois Tigeot dev->primary->master) { 1736e3adcf8fSFrançois Tigeot struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv; 1737e3adcf8fSFrançois Tigeot if (master_priv->sarea_priv) 1738e3adcf8fSFrançois Tigeot master_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT; 1739e3adcf8fSFrançois Tigeot } 1740e3adcf8fSFrançois Tigeot #else 1741e3adcf8fSFrançois Tigeot if (dev_priv->sarea_priv) 1742e3adcf8fSFrançois Tigeot dev_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT; 1743e3adcf8fSFrançois Tigeot #endif 1744e3adcf8fSFrançois Tigeot 1745ba55f2f5SFrançois Tigeot 1746e3440f96SFrançois Tigeot msleep(1); 1747245593daSFrançois Tigeot 1748ba55f2f5SFrançois Tigeot #if 0 1749ba55f2f5SFrançois Tigeot if (dev_priv->mm.interruptible && signal_pending(current)) { 1750ba55f2f5SFrançois Tigeot ret = -ERESTARTSYS; 1751ba55f2f5SFrançois Tigeot break; 1752ba55f2f5SFrançois Tigeot } 1753ba55f2f5SFrançois Tigeot #endif 1754ba55f2f5SFrançois Tigeot 1755a2fdbec6SFrançois Tigeot ret = i915_gem_check_wedge(&dev_priv->gpu_error, 1756a2fdbec6SFrançois Tigeot dev_priv->mm.interruptible); 1757245593daSFrançois Tigeot if (ret) 1758ba55f2f5SFrançois Tigeot break; 1759ba55f2f5SFrançois Tigeot 1760ba55f2f5SFrançois Tigeot if (time_after(jiffies, end)) { 1761ba55f2f5SFrançois Tigeot ret = -EBUSY; 1762ba55f2f5SFrançois Tigeot break; 1763ba55f2f5SFrançois Tigeot } 1764ba55f2f5SFrançois Tigeot } while (1); 1765a2fdbec6SFrançois Tigeot trace_i915_ring_wait_end(ring); 1766ba55f2f5SFrançois Tigeot return ret; 1767e3adcf8fSFrançois Tigeot } 1768e3adcf8fSFrançois Tigeot 1769ba55f2f5SFrançois Tigeot static int intel_wrap_ring_buffer(struct intel_engine_cs *ring) 1770b030f26bSFrançois Tigeot { 1771b030f26bSFrançois Tigeot uint32_t __iomem *virt; 1772ba55f2f5SFrançois Tigeot struct intel_ringbuffer *ringbuf = ring->buffer; 1773ba55f2f5SFrançois Tigeot int rem = ringbuf->size - ringbuf->tail; 1774b030f26bSFrançois Tigeot 1775ba55f2f5SFrançois Tigeot if (ringbuf->space < rem) { 1776b030f26bSFrançois Tigeot int ret = ring_wait_for_space(ring, rem); 1777b030f26bSFrançois Tigeot if (ret) 1778b030f26bSFrançois Tigeot return ret; 1779b030f26bSFrançois Tigeot } 1780b030f26bSFrançois Tigeot 1781ba55f2f5SFrançois Tigeot virt = (unsigned int *)((char *)ringbuf->virtual_start + ringbuf->tail); 1782b030f26bSFrançois Tigeot rem /= 4; 1783b030f26bSFrançois Tigeot while (rem--) 1784686a02f1SFrançois Tigeot iowrite32(MI_NOOP, virt++); 1785b030f26bSFrançois Tigeot 1786ba55f2f5SFrançois Tigeot ringbuf->tail = 0; 1787*24edb884SFrançois Tigeot ringbuf->space = ring_space(ringbuf); 1788b030f26bSFrançois Tigeot 1789b030f26bSFrançois Tigeot return 0; 1790b030f26bSFrançois Tigeot } 1791b030f26bSFrançois Tigeot 1792ba55f2f5SFrançois Tigeot int intel_ring_idle(struct intel_engine_cs *ring) 1793b030f26bSFrançois Tigeot { 1794b5c29a34SFrançois Tigeot u32 seqno; 1795b5c29a34SFrançois Tigeot int ret; 1796b5c29a34SFrançois Tigeot 1797b5c29a34SFrançois Tigeot /* We need to add any requests required to flush the objects and ring */ 17989edbd4a0SFrançois Tigeot if (ring->outstanding_lazy_seqno) { 17995d0b1887SFrançois Tigeot ret = i915_add_request(ring, NULL); 1800b5c29a34SFrançois Tigeot if (ret) 1801b5c29a34SFrançois Tigeot return ret; 1802b5c29a34SFrançois Tigeot } 1803b5c29a34SFrançois Tigeot 1804b5c29a34SFrançois Tigeot /* Wait upon the last request to be completed */ 1805b5c29a34SFrançois Tigeot if (list_empty(&ring->request_list)) 1806b5c29a34SFrançois Tigeot return 0; 1807b5c29a34SFrançois Tigeot 1808b5c29a34SFrançois Tigeot seqno = list_entry(ring->request_list.prev, 1809b5c29a34SFrançois Tigeot struct drm_i915_gem_request, 1810b5c29a34SFrançois Tigeot list)->seqno; 1811b5c29a34SFrançois Tigeot 1812b5c29a34SFrançois Tigeot return i915_wait_seqno(ring, seqno); 1813b5c29a34SFrançois Tigeot } 1814b5c29a34SFrançois Tigeot 1815b5c29a34SFrançois Tigeot static int 1816ba55f2f5SFrançois Tigeot intel_ring_alloc_seqno(struct intel_engine_cs *ring) 1817b5c29a34SFrançois Tigeot { 18189edbd4a0SFrançois Tigeot if (ring->outstanding_lazy_seqno) 1819b5c29a34SFrançois Tigeot return 0; 1820b5c29a34SFrançois Tigeot 18219edbd4a0SFrançois Tigeot if (ring->preallocated_lazy_request == NULL) { 18229edbd4a0SFrançois Tigeot struct drm_i915_gem_request *request; 18239edbd4a0SFrançois Tigeot 18249edbd4a0SFrançois Tigeot request = kmalloc(sizeof(*request), M_DRM, M_WAITOK); 18259edbd4a0SFrançois Tigeot if (request == NULL) 18269edbd4a0SFrançois Tigeot return -ENOMEM; 18279edbd4a0SFrançois Tigeot 18289edbd4a0SFrançois Tigeot ring->preallocated_lazy_request = request; 1829b030f26bSFrançois Tigeot } 1830b030f26bSFrançois Tigeot 18319edbd4a0SFrançois Tigeot return i915_gem_get_seqno(ring->dev, &ring->outstanding_lazy_seqno); 18329edbd4a0SFrançois Tigeot } 18339edbd4a0SFrançois Tigeot 1834ba55f2f5SFrançois Tigeot static int __intel_ring_prepare(struct intel_engine_cs *ring, 1835a2fdbec6SFrançois Tigeot int bytes) 1836a2fdbec6SFrançois Tigeot { 1837ba55f2f5SFrançois Tigeot struct intel_ringbuffer *ringbuf = ring->buffer; 1838a2fdbec6SFrançois Tigeot int ret; 1839a2fdbec6SFrançois Tigeot 1840ba55f2f5SFrançois Tigeot if (unlikely(ringbuf->tail + bytes > ringbuf->effective_size)) { 1841a2fdbec6SFrançois Tigeot ret = intel_wrap_ring_buffer(ring); 1842a2fdbec6SFrançois Tigeot if (unlikely(ret)) 1843a2fdbec6SFrançois Tigeot return ret; 1844a2fdbec6SFrançois Tigeot } 1845a2fdbec6SFrançois Tigeot 1846ba55f2f5SFrançois Tigeot if (unlikely(ringbuf->space < bytes)) { 1847a2fdbec6SFrançois Tigeot ret = ring_wait_for_space(ring, bytes); 1848a2fdbec6SFrançois Tigeot if (unlikely(ret)) 1849a2fdbec6SFrançois Tigeot return ret; 1850a2fdbec6SFrançois Tigeot } 1851a2fdbec6SFrançois Tigeot 1852a2fdbec6SFrançois Tigeot return 0; 1853a2fdbec6SFrançois Tigeot } 1854a2fdbec6SFrançois Tigeot 1855ba55f2f5SFrançois Tigeot int intel_ring_begin(struct intel_engine_cs *ring, 1856e3adcf8fSFrançois Tigeot int num_dwords) 1857e3adcf8fSFrançois Tigeot { 1858ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = ring->dev->dev_private; 1859e3adcf8fSFrançois Tigeot int ret; 1860e3adcf8fSFrançois Tigeot 1861a2fdbec6SFrançois Tigeot ret = i915_gem_check_wedge(&dev_priv->gpu_error, 1862a2fdbec6SFrançois Tigeot dev_priv->mm.interruptible); 1863245593daSFrançois Tigeot if (ret) 1864245593daSFrançois Tigeot return ret; 1865e3adcf8fSFrançois Tigeot 18669edbd4a0SFrançois Tigeot ret = __intel_ring_prepare(ring, num_dwords * sizeof(uint32_t)); 18679edbd4a0SFrançois Tigeot if (ret) 18689edbd4a0SFrançois Tigeot return ret; 18699edbd4a0SFrançois Tigeot 1870b5c29a34SFrançois Tigeot /* Preallocate the olr before touching the ring */ 1871b5c29a34SFrançois Tigeot ret = intel_ring_alloc_seqno(ring); 1872b5c29a34SFrançois Tigeot if (ret) 1873b5c29a34SFrançois Tigeot return ret; 1874b5c29a34SFrançois Tigeot 1875ba55f2f5SFrançois Tigeot ring->buffer->space -= num_dwords * sizeof(uint32_t); 18769edbd4a0SFrançois Tigeot return 0; 18779edbd4a0SFrançois Tigeot } 18789edbd4a0SFrançois Tigeot 18799edbd4a0SFrançois Tigeot /* Align the ring tail to a cacheline boundary */ 1880ba55f2f5SFrançois Tigeot int intel_ring_cacheline_align(struct intel_engine_cs *ring) 18819edbd4a0SFrançois Tigeot { 1882ba55f2f5SFrançois Tigeot int num_dwords = (ring->buffer->tail & (CACHELINE_BYTES - 1)) / sizeof(uint32_t); 18839edbd4a0SFrançois Tigeot int ret; 18849edbd4a0SFrançois Tigeot 18859edbd4a0SFrançois Tigeot if (num_dwords == 0) 18869edbd4a0SFrançois Tigeot return 0; 18879edbd4a0SFrançois Tigeot 1888ba55f2f5SFrançois Tigeot num_dwords = CACHELINE_BYTES / sizeof(uint32_t) - num_dwords; 18899edbd4a0SFrançois Tigeot ret = intel_ring_begin(ring, num_dwords); 18909edbd4a0SFrançois Tigeot if (ret) 18919edbd4a0SFrançois Tigeot return ret; 18929edbd4a0SFrançois Tigeot 18939edbd4a0SFrançois Tigeot while (num_dwords--) 18949edbd4a0SFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 18959edbd4a0SFrançois Tigeot 18969edbd4a0SFrançois Tigeot intel_ring_advance(ring); 18979edbd4a0SFrançois Tigeot 18989edbd4a0SFrançois Tigeot return 0; 1899e3adcf8fSFrançois Tigeot } 1900e3adcf8fSFrançois Tigeot 1901ba55f2f5SFrançois Tigeot void intel_ring_init_seqno(struct intel_engine_cs *ring, u32 seqno) 1902a2fdbec6SFrançois Tigeot { 1903*24edb884SFrançois Tigeot struct drm_device *dev = ring->dev; 1904*24edb884SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 1905a2fdbec6SFrançois Tigeot 19069edbd4a0SFrançois Tigeot BUG_ON(ring->outstanding_lazy_seqno); 1907a2fdbec6SFrançois Tigeot 1908*24edb884SFrançois Tigeot if (INTEL_INFO(dev)->gen == 6 || INTEL_INFO(dev)->gen == 7) { 1909a2fdbec6SFrançois Tigeot I915_WRITE(RING_SYNC_0(ring->mmio_base), 0); 1910a2fdbec6SFrançois Tigeot I915_WRITE(RING_SYNC_1(ring->mmio_base), 0); 1911*24edb884SFrançois Tigeot if (HAS_VEBOX(dev)) 19129edbd4a0SFrançois Tigeot I915_WRITE(RING_SYNC_2(ring->mmio_base), 0); 1913e3adcf8fSFrançois Tigeot } 1914e3adcf8fSFrançois Tigeot 1915a2fdbec6SFrançois Tigeot ring->set_seqno(ring, seqno); 19165d0b1887SFrançois Tigeot ring->hangcheck.seqno = seqno; 1917e3adcf8fSFrançois Tigeot } 1918e3adcf8fSFrançois Tigeot 1919ba55f2f5SFrançois Tigeot static void gen6_bsd_ring_write_tail(struct intel_engine_cs *ring, 1920f4e1c372SFrançois Tigeot u32 value) 1921e3adcf8fSFrançois Tigeot { 1922ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = ring->dev->dev_private; 1923e3adcf8fSFrançois Tigeot 1924e3adcf8fSFrançois Tigeot /* Every tail move must follow the sequence below */ 1925f4e1c372SFrançois Tigeot 1926f4e1c372SFrançois Tigeot /* Disable notification that the ring is IDLE. The GT 1927f4e1c372SFrançois Tigeot * will then assume that it is busy and bring it out of rc6. 1928f4e1c372SFrançois Tigeot */ 1929e3adcf8fSFrançois Tigeot I915_WRITE(GEN6_BSD_SLEEP_PSMI_CONTROL, 1930f4e1c372SFrançois Tigeot _MASKED_BIT_ENABLE(GEN6_BSD_SLEEP_MSG_DISABLE)); 1931e3adcf8fSFrançois Tigeot 1932f4e1c372SFrançois Tigeot /* Clear the context id. Here be magic! */ 1933f4e1c372SFrançois Tigeot I915_WRITE64(GEN6_BSD_RNCID, 0x0); 1934e3adcf8fSFrançois Tigeot 1935f4e1c372SFrançois Tigeot /* Wait for the ring not to be idle, i.e. for it to wake up. */ 1936f4e1c372SFrançois Tigeot if (wait_for((I915_READ(GEN6_BSD_SLEEP_PSMI_CONTROL) & 1937f4e1c372SFrançois Tigeot GEN6_BSD_SLEEP_INDICATOR) == 0, 1938f4e1c372SFrançois Tigeot 50)) 1939f4e1c372SFrançois Tigeot DRM_ERROR("timed out waiting for the BSD ring to wake up\n"); 1940f4e1c372SFrançois Tigeot 1941f4e1c372SFrançois Tigeot /* Now that the ring is fully powered up, update the tail */ 1942e3adcf8fSFrançois Tigeot I915_WRITE_TAIL(ring, value); 1943f4e1c372SFrançois Tigeot POSTING_READ(RING_TAIL(ring->mmio_base)); 1944f4e1c372SFrançois Tigeot 1945f4e1c372SFrançois Tigeot /* Let the ring send IDLE messages to the GT again, 1946f4e1c372SFrançois Tigeot * and so let it sleep to conserve power when idle. 1947f4e1c372SFrançois Tigeot */ 1948e3adcf8fSFrançois Tigeot I915_WRITE(GEN6_BSD_SLEEP_PSMI_CONTROL, 1949f4e1c372SFrançois Tigeot _MASKED_BIT_DISABLE(GEN6_BSD_SLEEP_MSG_DISABLE)); 1950e3adcf8fSFrançois Tigeot } 1951e3adcf8fSFrançois Tigeot 1952ba55f2f5SFrançois Tigeot static int gen6_bsd_ring_flush(struct intel_engine_cs *ring, 1953b5c29a34SFrançois Tigeot u32 invalidate, u32 flush) 1954e3adcf8fSFrançois Tigeot { 1955e3adcf8fSFrançois Tigeot uint32_t cmd; 1956e3adcf8fSFrançois Tigeot int ret; 1957e3adcf8fSFrançois Tigeot 1958e3adcf8fSFrançois Tigeot ret = intel_ring_begin(ring, 4); 1959e3adcf8fSFrançois Tigeot if (ret) 1960e3adcf8fSFrançois Tigeot return ret; 1961e3adcf8fSFrançois Tigeot 1962e3adcf8fSFrançois Tigeot cmd = MI_FLUSH_DW; 19639edbd4a0SFrançois Tigeot if (INTEL_INFO(ring->dev)->gen >= 8) 19649edbd4a0SFrançois Tigeot cmd += 1; 1965b5c29a34SFrançois Tigeot /* 1966b5c29a34SFrançois Tigeot * Bspec vol 1c.5 - video engine command streamer: 1967b5c29a34SFrançois Tigeot * "If ENABLED, all TLBs will be invalidated once the flush 1968b5c29a34SFrançois Tigeot * operation is complete. This bit is only valid when the 1969b5c29a34SFrançois Tigeot * Post-Sync Operation field is a value of 1h or 3h." 1970b5c29a34SFrançois Tigeot */ 1971e3adcf8fSFrançois Tigeot if (invalidate & I915_GEM_GPU_DOMAINS) 1972b5c29a34SFrançois Tigeot cmd |= MI_INVALIDATE_TLB | MI_INVALIDATE_BSD | 1973b5c29a34SFrançois Tigeot MI_FLUSH_DW_STORE_INDEX | MI_FLUSH_DW_OP_STOREDW; 1974e3adcf8fSFrançois Tigeot intel_ring_emit(ring, cmd); 1975b5c29a34SFrançois Tigeot intel_ring_emit(ring, I915_GEM_HWS_SCRATCH_ADDR | MI_FLUSH_DW_USE_GTT); 19769edbd4a0SFrançois Tigeot if (INTEL_INFO(ring->dev)->gen >= 8) { 19779edbd4a0SFrançois Tigeot intel_ring_emit(ring, 0); /* upper addr */ 19789edbd4a0SFrançois Tigeot intel_ring_emit(ring, 0); /* value */ 19799edbd4a0SFrançois Tigeot } else { 19809edbd4a0SFrançois Tigeot intel_ring_emit(ring, 0); 19819edbd4a0SFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 19829edbd4a0SFrançois Tigeot } 19839edbd4a0SFrançois Tigeot intel_ring_advance(ring); 19849edbd4a0SFrançois Tigeot return 0; 19859edbd4a0SFrançois Tigeot } 19869edbd4a0SFrançois Tigeot 19879edbd4a0SFrançois Tigeot static int 1988ba55f2f5SFrançois Tigeot gen8_ring_dispatch_execbuffer(struct intel_engine_cs *ring, 1989ba55f2f5SFrançois Tigeot u64 offset, u32 len, 19909edbd4a0SFrançois Tigeot unsigned flags) 19919edbd4a0SFrançois Tigeot { 19929edbd4a0SFrançois Tigeot struct drm_i915_private *dev_priv = ring->dev->dev_private; 19939edbd4a0SFrançois Tigeot bool ppgtt = dev_priv->mm.aliasing_ppgtt != NULL && 19949edbd4a0SFrançois Tigeot !(flags & I915_DISPATCH_SECURE); 19959edbd4a0SFrançois Tigeot int ret; 19969edbd4a0SFrançois Tigeot 19979edbd4a0SFrançois Tigeot ret = intel_ring_begin(ring, 4); 19989edbd4a0SFrançois Tigeot if (ret) 19999edbd4a0SFrançois Tigeot return ret; 20009edbd4a0SFrançois Tigeot 20019edbd4a0SFrançois Tigeot /* FIXME(BDW): Address space and security selectors. */ 20029edbd4a0SFrançois Tigeot intel_ring_emit(ring, MI_BATCH_BUFFER_START_GEN8 | (ppgtt<<8)); 2003ba55f2f5SFrançois Tigeot intel_ring_emit(ring, lower_32_bits(offset)); 2004ba55f2f5SFrançois Tigeot intel_ring_emit(ring, upper_32_bits(offset)); 2005e3adcf8fSFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 2006e3adcf8fSFrançois Tigeot intel_ring_advance(ring); 20079edbd4a0SFrançois Tigeot 2008e3adcf8fSFrançois Tigeot return 0; 2009e3adcf8fSFrançois Tigeot } 2010e3adcf8fSFrançois Tigeot 2011e3adcf8fSFrançois Tigeot static int 2012ba55f2f5SFrançois Tigeot hsw_ring_dispatch_execbuffer(struct intel_engine_cs *ring, 2013ba55f2f5SFrançois Tigeot u64 offset, u32 len, 2014b5c29a34SFrançois Tigeot unsigned flags) 2015e3adcf8fSFrançois Tigeot { 2016e3adcf8fSFrançois Tigeot int ret; 2017e3adcf8fSFrançois Tigeot 2018e3adcf8fSFrançois Tigeot ret = intel_ring_begin(ring, 2); 2019e3adcf8fSFrançois Tigeot if (ret) 2020e3adcf8fSFrançois Tigeot return ret; 2021e3adcf8fSFrançois Tigeot 2022b5c29a34SFrançois Tigeot intel_ring_emit(ring, 2023b5c29a34SFrançois Tigeot MI_BATCH_BUFFER_START | MI_BATCH_PPGTT_HSW | 2024b5c29a34SFrançois Tigeot (flags & I915_DISPATCH_SECURE ? 0 : MI_BATCH_NON_SECURE_HSW)); 2025b5c29a34SFrançois Tigeot /* bit0-7 is the length on GEN6+ */ 2026b5c29a34SFrançois Tigeot intel_ring_emit(ring, offset); 2027b5c29a34SFrançois Tigeot intel_ring_advance(ring); 2028b5c29a34SFrançois Tigeot 2029b5c29a34SFrançois Tigeot return 0; 2030b5c29a34SFrançois Tigeot } 2031b5c29a34SFrançois Tigeot 2032b5c29a34SFrançois Tigeot static int 2033ba55f2f5SFrançois Tigeot gen6_ring_dispatch_execbuffer(struct intel_engine_cs *ring, 2034ba55f2f5SFrançois Tigeot u64 offset, u32 len, 2035b5c29a34SFrançois Tigeot unsigned flags) 2036b5c29a34SFrançois Tigeot { 2037b5c29a34SFrançois Tigeot int ret; 2038b5c29a34SFrançois Tigeot 2039b5c29a34SFrançois Tigeot ret = intel_ring_begin(ring, 2); 2040b5c29a34SFrançois Tigeot if (ret) 2041b5c29a34SFrançois Tigeot return ret; 2042b5c29a34SFrançois Tigeot 2043b5c29a34SFrançois Tigeot intel_ring_emit(ring, 2044b5c29a34SFrançois Tigeot MI_BATCH_BUFFER_START | 2045b5c29a34SFrançois Tigeot (flags & I915_DISPATCH_SECURE ? 0 : MI_BATCH_NON_SECURE_I965)); 2046e3adcf8fSFrançois Tigeot /* bit0-7 is the length on GEN6+ */ 2047e3adcf8fSFrançois Tigeot intel_ring_emit(ring, offset); 2048e3adcf8fSFrançois Tigeot intel_ring_advance(ring); 2049e3adcf8fSFrançois Tigeot 2050e3adcf8fSFrançois Tigeot return 0; 2051e3adcf8fSFrançois Tigeot } 2052e3adcf8fSFrançois Tigeot 2053e3adcf8fSFrançois Tigeot /* Blitter support (SandyBridge+) */ 2054e3adcf8fSFrançois Tigeot 2055ba55f2f5SFrançois Tigeot static int gen6_ring_flush(struct intel_engine_cs *ring, 2056b5c29a34SFrançois Tigeot u32 invalidate, u32 flush) 2057e3adcf8fSFrançois Tigeot { 20585d0b1887SFrançois Tigeot struct drm_device *dev = ring->dev; 2059e3adcf8fSFrançois Tigeot uint32_t cmd; 2060e3adcf8fSFrançois Tigeot int ret; 2061e3adcf8fSFrançois Tigeot 2062e3adcf8fSFrançois Tigeot ret = intel_ring_begin(ring, 4); 2063e3adcf8fSFrançois Tigeot if (ret) 2064e3adcf8fSFrançois Tigeot return ret; 2065e3adcf8fSFrançois Tigeot 2066e3adcf8fSFrançois Tigeot cmd = MI_FLUSH_DW; 20679edbd4a0SFrançois Tigeot if (INTEL_INFO(ring->dev)->gen >= 8) 20689edbd4a0SFrançois Tigeot cmd += 1; 2069b5c29a34SFrançois Tigeot /* 2070b5c29a34SFrançois Tigeot * Bspec vol 1c.3 - blitter engine command streamer: 2071b5c29a34SFrançois Tigeot * "If ENABLED, all TLBs will be invalidated once the flush 2072b5c29a34SFrançois Tigeot * operation is complete. This bit is only valid when the 2073b5c29a34SFrançois Tigeot * Post-Sync Operation field is a value of 1h or 3h." 2074b5c29a34SFrançois Tigeot */ 2075e3adcf8fSFrançois Tigeot if (invalidate & I915_GEM_DOMAIN_RENDER) 2076b5c29a34SFrançois Tigeot cmd |= MI_INVALIDATE_TLB | MI_FLUSH_DW_STORE_INDEX | 2077b5c29a34SFrançois Tigeot MI_FLUSH_DW_OP_STOREDW; 2078e3adcf8fSFrançois Tigeot intel_ring_emit(ring, cmd); 2079b5c29a34SFrançois Tigeot intel_ring_emit(ring, I915_GEM_HWS_SCRATCH_ADDR | MI_FLUSH_DW_USE_GTT); 20809edbd4a0SFrançois Tigeot if (INTEL_INFO(ring->dev)->gen >= 8) { 20819edbd4a0SFrançois Tigeot intel_ring_emit(ring, 0); /* upper addr */ 20829edbd4a0SFrançois Tigeot intel_ring_emit(ring, 0); /* value */ 20839edbd4a0SFrançois Tigeot } else { 2084e3adcf8fSFrançois Tigeot intel_ring_emit(ring, 0); 2085e3adcf8fSFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 20869edbd4a0SFrançois Tigeot } 2087e3adcf8fSFrançois Tigeot intel_ring_advance(ring); 20885d0b1887SFrançois Tigeot 20899edbd4a0SFrançois Tigeot if (IS_GEN7(dev) && !invalidate && flush) 20905d0b1887SFrançois Tigeot return gen7_ring_fbc_flush(ring, FBC_REND_CACHE_CLEAN); 20915d0b1887SFrançois Tigeot 2092e3adcf8fSFrançois Tigeot return 0; 2093e3adcf8fSFrançois Tigeot } 2094e3adcf8fSFrançois Tigeot 2095e3adcf8fSFrançois Tigeot int intel_init_render_ring_buffer(struct drm_device *dev) 2096e3adcf8fSFrançois Tigeot { 2097ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 2098ba55f2f5SFrançois Tigeot struct intel_engine_cs *ring = &dev_priv->ring[RCS]; 2099*24edb884SFrançois Tigeot struct drm_i915_gem_object *obj; 2100*24edb884SFrançois Tigeot int ret; 2101e3adcf8fSFrançois Tigeot 2102686a02f1SFrançois Tigeot ring->name = "render ring"; 2103686a02f1SFrançois Tigeot ring->id = RCS; 2104686a02f1SFrançois Tigeot ring->mmio_base = RENDER_RING_BASE; 2105686a02f1SFrançois Tigeot 2106*24edb884SFrançois Tigeot if (INTEL_INFO(dev)->gen >= 8) { 2107*24edb884SFrançois Tigeot if (i915_semaphore_is_enabled(dev)) { 2108*24edb884SFrançois Tigeot obj = i915_gem_alloc_object(dev, 4096); 2109*24edb884SFrançois Tigeot if (obj == NULL) { 2110*24edb884SFrançois Tigeot DRM_ERROR("Failed to allocate semaphore bo. Disabling semaphores\n"); 2111*24edb884SFrançois Tigeot i915.semaphores = 0; 2112*24edb884SFrançois Tigeot } else { 2113*24edb884SFrançois Tigeot i915_gem_object_set_cache_level(obj, I915_CACHE_LLC); 2114*24edb884SFrançois Tigeot ret = i915_gem_obj_ggtt_pin(obj, 0, PIN_NONBLOCK); 2115*24edb884SFrançois Tigeot if (ret != 0) { 2116*24edb884SFrançois Tigeot drm_gem_object_unreference(&obj->base); 2117*24edb884SFrançois Tigeot DRM_ERROR("Failed to pin semaphore bo. Disabling semaphores\n"); 2118*24edb884SFrançois Tigeot i915.semaphores = 0; 2119*24edb884SFrançois Tigeot } else 2120*24edb884SFrançois Tigeot dev_priv->semaphore_obj = obj; 2121*24edb884SFrançois Tigeot } 2122*24edb884SFrançois Tigeot } 2123*24edb884SFrançois Tigeot ring->add_request = gen6_add_request; 2124*24edb884SFrançois Tigeot ring->flush = gen8_render_ring_flush; 2125*24edb884SFrançois Tigeot ring->irq_get = gen8_ring_get_irq; 2126*24edb884SFrançois Tigeot ring->irq_put = gen8_ring_put_irq; 2127*24edb884SFrançois Tigeot ring->irq_enable_mask = GT_RENDER_USER_INTERRUPT; 2128*24edb884SFrançois Tigeot ring->get_seqno = gen6_ring_get_seqno; 2129*24edb884SFrançois Tigeot ring->set_seqno = ring_set_seqno; 2130*24edb884SFrançois Tigeot if (i915_semaphore_is_enabled(dev)) { 2131*24edb884SFrançois Tigeot WARN_ON(!dev_priv->semaphore_obj); 2132*24edb884SFrançois Tigeot ring->semaphore.sync_to = gen8_ring_sync; 2133*24edb884SFrançois Tigeot ring->semaphore.signal = gen8_rcs_signal; 2134*24edb884SFrançois Tigeot GEN8_RING_SEMAPHORE_INIT; 2135*24edb884SFrançois Tigeot } 2136*24edb884SFrançois Tigeot } else if (INTEL_INFO(dev)->gen >= 6) { 2137e3adcf8fSFrançois Tigeot ring->add_request = gen6_add_request; 2138b5c29a34SFrançois Tigeot ring->flush = gen7_render_ring_flush; 2139b5c29a34SFrançois Tigeot if (INTEL_INFO(dev)->gen == 6) 2140e3adcf8fSFrançois Tigeot ring->flush = gen6_render_ring_flush; 2141686a02f1SFrançois Tigeot ring->irq_get = gen6_ring_get_irq; 2142686a02f1SFrançois Tigeot ring->irq_put = gen6_ring_put_irq; 21435d0b1887SFrançois Tigeot ring->irq_enable_mask = GT_RENDER_USER_INTERRUPT; 2144e3adcf8fSFrançois Tigeot ring->get_seqno = gen6_ring_get_seqno; 2145a2fdbec6SFrançois Tigeot ring->set_seqno = ring_set_seqno; 2146*24edb884SFrançois Tigeot if (i915_semaphore_is_enabled(dev)) { 2147ba55f2f5SFrançois Tigeot ring->semaphore.sync_to = gen6_ring_sync; 2148ba55f2f5SFrançois Tigeot ring->semaphore.signal = gen6_signal; 2149ba55f2f5SFrançois Tigeot /* 2150*24edb884SFrançois Tigeot * The current semaphore is only applied on pre-gen8 2151*24edb884SFrançois Tigeot * platform. And there is no VCS2 ring on the pre-gen8 2152*24edb884SFrançois Tigeot * platform. So the semaphore between RCS and VCS2 is 2153*24edb884SFrançois Tigeot * initialized as INVALID. Gen8 will initialize the 2154*24edb884SFrançois Tigeot * sema between VCS2 and RCS later. 2155ba55f2f5SFrançois Tigeot */ 2156ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[RCS] = MI_SEMAPHORE_SYNC_INVALID; 2157ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[VCS] = MI_SEMAPHORE_SYNC_RV; 2158ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[BCS] = MI_SEMAPHORE_SYNC_RB; 2159ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[VECS] = MI_SEMAPHORE_SYNC_RVE; 2160ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[VCS2] = MI_SEMAPHORE_SYNC_INVALID; 2161ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[RCS] = GEN6_NOSYNC; 2162ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[VCS] = GEN6_VRSYNC; 2163ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[BCS] = GEN6_BRSYNC; 2164ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[VECS] = GEN6_VERSYNC; 2165ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[VCS2] = GEN6_NOSYNC; 2166*24edb884SFrançois Tigeot } 2167e3adcf8fSFrançois Tigeot } else if (IS_GEN5(dev)) { 2168e3adcf8fSFrançois Tigeot ring->add_request = pc_render_add_request; 2169686a02f1SFrançois Tigeot ring->flush = gen4_render_ring_flush; 2170e3adcf8fSFrançois Tigeot ring->get_seqno = pc_render_get_seqno; 2171a2fdbec6SFrançois Tigeot ring->set_seqno = pc_render_set_seqno; 2172686a02f1SFrançois Tigeot ring->irq_get = gen5_ring_get_irq; 2173686a02f1SFrançois Tigeot ring->irq_put = gen5_ring_put_irq; 21745d0b1887SFrançois Tigeot ring->irq_enable_mask = GT_RENDER_USER_INTERRUPT | 21755d0b1887SFrançois Tigeot GT_RENDER_PIPECTL_NOTIFY_INTERRUPT; 2176686a02f1SFrançois Tigeot } else { 2177686a02f1SFrançois Tigeot ring->add_request = i9xx_add_request; 2178686a02f1SFrançois Tigeot if (INTEL_INFO(dev)->gen < 4) 2179686a02f1SFrançois Tigeot ring->flush = gen2_render_ring_flush; 2180686a02f1SFrançois Tigeot else 2181686a02f1SFrançois Tigeot ring->flush = gen4_render_ring_flush; 2182686a02f1SFrançois Tigeot ring->get_seqno = ring_get_seqno; 2183a2fdbec6SFrançois Tigeot ring->set_seqno = ring_set_seqno; 2184686a02f1SFrançois Tigeot if (IS_GEN2(dev)) { 2185686a02f1SFrançois Tigeot ring->irq_get = i8xx_ring_get_irq; 2186686a02f1SFrançois Tigeot ring->irq_put = i8xx_ring_put_irq; 2187686a02f1SFrançois Tigeot } else { 2188686a02f1SFrançois Tigeot ring->irq_get = i9xx_ring_get_irq; 2189686a02f1SFrançois Tigeot ring->irq_put = i9xx_ring_put_irq; 2190e3adcf8fSFrançois Tigeot } 2191686a02f1SFrançois Tigeot ring->irq_enable_mask = I915_USER_INTERRUPT; 2192686a02f1SFrançois Tigeot } 2193686a02f1SFrançois Tigeot ring->write_tail = ring_write_tail; 2194*24edb884SFrançois Tigeot 2195b5c29a34SFrançois Tigeot if (IS_HASWELL(dev)) 2196b5c29a34SFrançois Tigeot ring->dispatch_execbuffer = hsw_ring_dispatch_execbuffer; 21979edbd4a0SFrançois Tigeot else if (IS_GEN8(dev)) 21989edbd4a0SFrançois Tigeot ring->dispatch_execbuffer = gen8_ring_dispatch_execbuffer; 2199b5c29a34SFrançois Tigeot else if (INTEL_INFO(dev)->gen >= 6) 2200686a02f1SFrançois Tigeot ring->dispatch_execbuffer = gen6_ring_dispatch_execbuffer; 2201686a02f1SFrançois Tigeot else if (INTEL_INFO(dev)->gen >= 4) 2202686a02f1SFrançois Tigeot ring->dispatch_execbuffer = i965_dispatch_execbuffer; 2203686a02f1SFrançois Tigeot else if (IS_I830(dev) || IS_845G(dev)) 2204686a02f1SFrançois Tigeot ring->dispatch_execbuffer = i830_dispatch_execbuffer; 2205686a02f1SFrançois Tigeot else 2206686a02f1SFrançois Tigeot ring->dispatch_execbuffer = i915_dispatch_execbuffer; 2207686a02f1SFrançois Tigeot ring->init = init_render_ring; 2208686a02f1SFrançois Tigeot ring->cleanup = render_ring_cleanup; 2209e3adcf8fSFrançois Tigeot 2210b5c29a34SFrançois Tigeot /* Workaround batchbuffer to combat CS tlb bug. */ 2211b5c29a34SFrançois Tigeot if (HAS_BROKEN_CS_TLB(dev)) { 2212*24edb884SFrançois Tigeot obj = i915_gem_alloc_object(dev, I830_WA_SIZE); 2213b5c29a34SFrançois Tigeot if (obj == NULL) { 2214b5c29a34SFrançois Tigeot DRM_ERROR("Failed to allocate batch bo\n"); 2215b5c29a34SFrançois Tigeot return -ENOMEM; 2216b5c29a34SFrançois Tigeot } 2217b5c29a34SFrançois Tigeot 2218ba55f2f5SFrançois Tigeot ret = i915_gem_obj_ggtt_pin(obj, 0, 0); 2219b5c29a34SFrançois Tigeot if (ret != 0) { 2220b5c29a34SFrançois Tigeot drm_gem_object_unreference(&obj->base); 2221b5c29a34SFrançois Tigeot DRM_ERROR("Failed to ping batch bo\n"); 2222b5c29a34SFrançois Tigeot return ret; 2223b5c29a34SFrançois Tigeot } 2224b5c29a34SFrançois Tigeot 22259edbd4a0SFrançois Tigeot ring->scratch.obj = obj; 22269edbd4a0SFrançois Tigeot ring->scratch.gtt_offset = i915_gem_obj_ggtt_offset(obj); 2227e3adcf8fSFrançois Tigeot } 2228e3adcf8fSFrançois Tigeot 2229e3adcf8fSFrançois Tigeot return intel_init_ring_buffer(dev, ring); 2230e3adcf8fSFrançois Tigeot } 2231e3adcf8fSFrançois Tigeot 2232686a02f1SFrançois Tigeot int intel_render_ring_init_dri(struct drm_device *dev, u64 start, u32 size) 2233e3adcf8fSFrançois Tigeot { 2234ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 2235ba55f2f5SFrançois Tigeot struct intel_engine_cs *ring = &dev_priv->ring[RCS]; 2236ba55f2f5SFrançois Tigeot struct intel_ringbuffer *ringbuf = ring->buffer; 2237b5c29a34SFrançois Tigeot int ret; 2238e3adcf8fSFrançois Tigeot 2239ba55f2f5SFrançois Tigeot if (ringbuf == NULL) { 2240ba55f2f5SFrançois Tigeot ringbuf = kzalloc(sizeof(*ringbuf), GFP_KERNEL); 2241ba55f2f5SFrançois Tigeot if (!ringbuf) 2242ba55f2f5SFrançois Tigeot return -ENOMEM; 2243ba55f2f5SFrançois Tigeot ring->buffer = ringbuf; 2244ba55f2f5SFrançois Tigeot } 2245ba55f2f5SFrançois Tigeot 2246686a02f1SFrançois Tigeot ring->name = "render ring"; 2247686a02f1SFrançois Tigeot ring->id = RCS; 2248686a02f1SFrançois Tigeot ring->mmio_base = RENDER_RING_BASE; 2249686a02f1SFrançois Tigeot 2250e3adcf8fSFrançois Tigeot if (INTEL_INFO(dev)->gen >= 6) { 2251686a02f1SFrançois Tigeot /* non-kms not supported on gen6+ */ 2252ba55f2f5SFrançois Tigeot ret = -ENODEV; 2253ba55f2f5SFrançois Tigeot goto err_ringbuf; 2254e3adcf8fSFrançois Tigeot } 2255e3adcf8fSFrançois Tigeot 2256686a02f1SFrançois Tigeot /* Note: gem is not supported on gen5/ilk without kms (the corresponding 2257686a02f1SFrançois Tigeot * gem_init ioctl returns with -ENODEV). Hence we do not need to set up 2258686a02f1SFrançois Tigeot * the special gen5 functions. */ 2259686a02f1SFrançois Tigeot ring->add_request = i9xx_add_request; 2260686a02f1SFrançois Tigeot if (INTEL_INFO(dev)->gen < 4) 2261686a02f1SFrançois Tigeot ring->flush = gen2_render_ring_flush; 2262686a02f1SFrançois Tigeot else 2263686a02f1SFrançois Tigeot ring->flush = gen4_render_ring_flush; 2264686a02f1SFrançois Tigeot ring->get_seqno = ring_get_seqno; 2265a2fdbec6SFrançois Tigeot ring->set_seqno = ring_set_seqno; 2266686a02f1SFrançois Tigeot if (IS_GEN2(dev)) { 2267686a02f1SFrançois Tigeot ring->irq_get = i8xx_ring_get_irq; 2268686a02f1SFrançois Tigeot ring->irq_put = i8xx_ring_put_irq; 2269686a02f1SFrançois Tigeot } else { 2270686a02f1SFrançois Tigeot ring->irq_get = i9xx_ring_get_irq; 2271686a02f1SFrançois Tigeot ring->irq_put = i9xx_ring_put_irq; 2272686a02f1SFrançois Tigeot } 2273686a02f1SFrançois Tigeot ring->irq_enable_mask = I915_USER_INTERRUPT; 2274686a02f1SFrançois Tigeot ring->write_tail = ring_write_tail; 2275686a02f1SFrançois Tigeot if (INTEL_INFO(dev)->gen >= 4) 2276686a02f1SFrançois Tigeot ring->dispatch_execbuffer = i965_dispatch_execbuffer; 2277686a02f1SFrançois Tigeot else if (IS_I830(dev) || IS_845G(dev)) 2278686a02f1SFrançois Tigeot ring->dispatch_execbuffer = i830_dispatch_execbuffer; 2279686a02f1SFrançois Tigeot else 2280686a02f1SFrançois Tigeot ring->dispatch_execbuffer = i915_dispatch_execbuffer; 2281686a02f1SFrançois Tigeot ring->init = init_render_ring; 2282686a02f1SFrançois Tigeot ring->cleanup = render_ring_cleanup; 2283686a02f1SFrançois Tigeot 2284e3adcf8fSFrançois Tigeot ring->dev = dev; 2285e3adcf8fSFrançois Tigeot INIT_LIST_HEAD(&ring->active_list); 2286e3adcf8fSFrançois Tigeot INIT_LIST_HEAD(&ring->request_list); 2287e3adcf8fSFrançois Tigeot 2288ba55f2f5SFrançois Tigeot ringbuf->size = size; 2289ba55f2f5SFrançois Tigeot ringbuf->effective_size = ringbuf->size; 2290b5c29a34SFrançois Tigeot if (IS_I830(ring->dev) || IS_845G(ring->dev)) 2291ba55f2f5SFrançois Tigeot ringbuf->effective_size -= 2 * CACHELINE_BYTES; 2292e3adcf8fSFrançois Tigeot 2293ba55f2f5SFrançois Tigeot ringbuf->virtual_start = ioremap_wc(start, size); 2294ba55f2f5SFrançois Tigeot if (ringbuf->virtual_start == NULL) { 2295e3adcf8fSFrançois Tigeot DRM_ERROR("can not ioremap virtual address for" 2296e3adcf8fSFrançois Tigeot " ring buffer\n"); 2297ba55f2f5SFrançois Tigeot ret = -ENOMEM; 2298ba55f2f5SFrançois Tigeot goto err_ringbuf; 2299e3adcf8fSFrançois Tigeot } 2300e3adcf8fSFrançois Tigeot 2301b5c29a34SFrançois Tigeot if (!I915_NEED_GFX_HWS(dev)) { 23025d0b1887SFrançois Tigeot ret = init_phys_status_page(ring); 2303b5c29a34SFrançois Tigeot if (ret) 2304ba55f2f5SFrançois Tigeot goto err_vstart; 2305b5c29a34SFrançois Tigeot } 2306b5c29a34SFrançois Tigeot 2307e3adcf8fSFrançois Tigeot return 0; 2308ba55f2f5SFrançois Tigeot 2309ba55f2f5SFrançois Tigeot err_vstart: 2310ba55f2f5SFrançois Tigeot pmap_unmapdev((vm_offset_t)ring->buffer->virtual_start, size); 2311ba55f2f5SFrançois Tigeot err_ringbuf: 2312ba55f2f5SFrançois Tigeot kfree(ringbuf); 2313ba55f2f5SFrançois Tigeot ring->buffer = NULL; 2314ba55f2f5SFrançois Tigeot return ret; 2315e3adcf8fSFrançois Tigeot } 2316e3adcf8fSFrançois Tigeot 2317e3adcf8fSFrançois Tigeot int intel_init_bsd_ring_buffer(struct drm_device *dev) 2318e3adcf8fSFrançois Tigeot { 2319ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 2320ba55f2f5SFrançois Tigeot struct intel_engine_cs *ring = &dev_priv->ring[VCS]; 2321e3adcf8fSFrançois Tigeot 2322686a02f1SFrançois Tigeot ring->name = "bsd ring"; 2323686a02f1SFrançois Tigeot ring->id = VCS; 2324686a02f1SFrançois Tigeot 2325686a02f1SFrançois Tigeot ring->write_tail = ring_write_tail; 23269edbd4a0SFrançois Tigeot if (INTEL_INFO(dev)->gen >= 6) { 2327686a02f1SFrançois Tigeot ring->mmio_base = GEN6_BSD_RING_BASE; 2328686a02f1SFrançois Tigeot /* gen6 bsd needs a special wa for tail updates */ 2329686a02f1SFrançois Tigeot if (IS_GEN6(dev)) 2330686a02f1SFrançois Tigeot ring->write_tail = gen6_bsd_ring_write_tail; 23315d0b1887SFrançois Tigeot ring->flush = gen6_bsd_ring_flush; 2332686a02f1SFrançois Tigeot ring->add_request = gen6_add_request; 2333686a02f1SFrançois Tigeot ring->get_seqno = gen6_ring_get_seqno; 2334a2fdbec6SFrançois Tigeot ring->set_seqno = ring_set_seqno; 23359edbd4a0SFrançois Tigeot if (INTEL_INFO(dev)->gen >= 8) { 23369edbd4a0SFrançois Tigeot ring->irq_enable_mask = 23379edbd4a0SFrançois Tigeot GT_RENDER_USER_INTERRUPT << GEN8_VCS1_IRQ_SHIFT; 23389edbd4a0SFrançois Tigeot ring->irq_get = gen8_ring_get_irq; 23399edbd4a0SFrançois Tigeot ring->irq_put = gen8_ring_put_irq; 23409edbd4a0SFrançois Tigeot ring->dispatch_execbuffer = 23419edbd4a0SFrançois Tigeot gen8_ring_dispatch_execbuffer; 2342*24edb884SFrançois Tigeot if (i915_semaphore_is_enabled(dev)) { 2343*24edb884SFrançois Tigeot ring->semaphore.sync_to = gen8_ring_sync; 2344*24edb884SFrançois Tigeot ring->semaphore.signal = gen8_xcs_signal; 2345*24edb884SFrançois Tigeot GEN8_RING_SEMAPHORE_INIT; 2346*24edb884SFrançois Tigeot } 23479edbd4a0SFrançois Tigeot } else { 23485d0b1887SFrançois Tigeot ring->irq_enable_mask = GT_BSD_USER_INTERRUPT; 2349686a02f1SFrançois Tigeot ring->irq_get = gen6_ring_get_irq; 2350686a02f1SFrançois Tigeot ring->irq_put = gen6_ring_put_irq; 23519edbd4a0SFrançois Tigeot ring->dispatch_execbuffer = 23529edbd4a0SFrançois Tigeot gen6_ring_dispatch_execbuffer; 2353*24edb884SFrançois Tigeot if (i915_semaphore_is_enabled(dev)) { 2354ba55f2f5SFrançois Tigeot ring->semaphore.sync_to = gen6_ring_sync; 2355ba55f2f5SFrançois Tigeot ring->semaphore.signal = gen6_signal; 2356ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[RCS] = MI_SEMAPHORE_SYNC_VR; 2357ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[VCS] = MI_SEMAPHORE_SYNC_INVALID; 2358ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[BCS] = MI_SEMAPHORE_SYNC_VB; 2359ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[VECS] = MI_SEMAPHORE_SYNC_VVE; 2360ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[VCS2] = MI_SEMAPHORE_SYNC_INVALID; 2361ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[RCS] = GEN6_RVSYNC; 2362ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[VCS] = GEN6_NOSYNC; 2363ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[BCS] = GEN6_BVSYNC; 2364ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[VECS] = GEN6_VEVSYNC; 2365ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[VCS2] = GEN6_NOSYNC; 2366*24edb884SFrançois Tigeot } 2367*24edb884SFrançois Tigeot } 2368686a02f1SFrançois Tigeot } else { 2369686a02f1SFrançois Tigeot ring->mmio_base = BSD_RING_BASE; 2370686a02f1SFrançois Tigeot ring->flush = bsd_ring_flush; 2371686a02f1SFrançois Tigeot ring->add_request = i9xx_add_request; 2372686a02f1SFrançois Tigeot ring->get_seqno = ring_get_seqno; 2373a2fdbec6SFrançois Tigeot ring->set_seqno = ring_set_seqno; 2374686a02f1SFrançois Tigeot if (IS_GEN5(dev)) { 23755d0b1887SFrançois Tigeot ring->irq_enable_mask = ILK_BSD_USER_INTERRUPT; 2376686a02f1SFrançois Tigeot ring->irq_get = gen5_ring_get_irq; 2377686a02f1SFrançois Tigeot ring->irq_put = gen5_ring_put_irq; 2378686a02f1SFrançois Tigeot } else { 2379686a02f1SFrançois Tigeot ring->irq_enable_mask = I915_BSD_USER_INTERRUPT; 2380686a02f1SFrançois Tigeot ring->irq_get = i9xx_ring_get_irq; 2381686a02f1SFrançois Tigeot ring->irq_put = i9xx_ring_put_irq; 2382686a02f1SFrançois Tigeot } 2383686a02f1SFrançois Tigeot ring->dispatch_execbuffer = i965_dispatch_execbuffer; 2384686a02f1SFrançois Tigeot } 2385686a02f1SFrançois Tigeot ring->init = init_ring_common; 2386e3adcf8fSFrançois Tigeot 2387e3adcf8fSFrançois Tigeot return intel_init_ring_buffer(dev, ring); 2388e3adcf8fSFrançois Tigeot } 2389e3adcf8fSFrançois Tigeot 2390ba55f2f5SFrançois Tigeot /** 2391ba55f2f5SFrançois Tigeot * Initialize the second BSD ring for Broadwell GT3. 2392ba55f2f5SFrançois Tigeot * It is noted that this only exists on Broadwell GT3. 2393ba55f2f5SFrançois Tigeot */ 2394ba55f2f5SFrançois Tigeot int intel_init_bsd2_ring_buffer(struct drm_device *dev) 2395ba55f2f5SFrançois Tigeot { 2396ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 2397ba55f2f5SFrançois Tigeot struct intel_engine_cs *ring = &dev_priv->ring[VCS2]; 2398ba55f2f5SFrançois Tigeot 2399ba55f2f5SFrançois Tigeot if ((INTEL_INFO(dev)->gen != 8)) { 2400ba55f2f5SFrançois Tigeot DRM_ERROR("No dual-BSD ring on non-BDW machine\n"); 2401ba55f2f5SFrançois Tigeot return -EINVAL; 2402ba55f2f5SFrançois Tigeot } 2403ba55f2f5SFrançois Tigeot 2404*24edb884SFrançois Tigeot ring->name = "bsd2 ring"; 2405ba55f2f5SFrançois Tigeot ring->id = VCS2; 2406ba55f2f5SFrançois Tigeot 2407ba55f2f5SFrançois Tigeot ring->write_tail = ring_write_tail; 2408ba55f2f5SFrançois Tigeot ring->mmio_base = GEN8_BSD2_RING_BASE; 2409ba55f2f5SFrançois Tigeot ring->flush = gen6_bsd_ring_flush; 2410ba55f2f5SFrançois Tigeot ring->add_request = gen6_add_request; 2411ba55f2f5SFrançois Tigeot ring->get_seqno = gen6_ring_get_seqno; 2412ba55f2f5SFrançois Tigeot ring->set_seqno = ring_set_seqno; 2413ba55f2f5SFrançois Tigeot ring->irq_enable_mask = 2414ba55f2f5SFrançois Tigeot GT_RENDER_USER_INTERRUPT << GEN8_VCS2_IRQ_SHIFT; 2415ba55f2f5SFrançois Tigeot ring->irq_get = gen8_ring_get_irq; 2416ba55f2f5SFrançois Tigeot ring->irq_put = gen8_ring_put_irq; 2417ba55f2f5SFrançois Tigeot ring->dispatch_execbuffer = 2418ba55f2f5SFrançois Tigeot gen8_ring_dispatch_execbuffer; 2419*24edb884SFrançois Tigeot if (i915_semaphore_is_enabled(dev)) { 2420*24edb884SFrançois Tigeot ring->semaphore.sync_to = gen8_ring_sync; 2421*24edb884SFrançois Tigeot ring->semaphore.signal = gen8_xcs_signal; 2422*24edb884SFrançois Tigeot GEN8_RING_SEMAPHORE_INIT; 2423*24edb884SFrançois Tigeot } 2424ba55f2f5SFrançois Tigeot ring->init = init_ring_common; 2425ba55f2f5SFrançois Tigeot 2426ba55f2f5SFrançois Tigeot return intel_init_ring_buffer(dev, ring); 2427ba55f2f5SFrançois Tigeot } 2428ba55f2f5SFrançois Tigeot 2429e3adcf8fSFrançois Tigeot int intel_init_blt_ring_buffer(struct drm_device *dev) 2430e3adcf8fSFrançois Tigeot { 2431ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 2432ba55f2f5SFrançois Tigeot struct intel_engine_cs *ring = &dev_priv->ring[BCS]; 2433e3adcf8fSFrançois Tigeot 2434686a02f1SFrançois Tigeot ring->name = "blitter ring"; 2435686a02f1SFrançois Tigeot ring->id = BCS; 2436686a02f1SFrançois Tigeot 2437686a02f1SFrançois Tigeot ring->mmio_base = BLT_RING_BASE; 2438686a02f1SFrançois Tigeot ring->write_tail = ring_write_tail; 24395d0b1887SFrançois Tigeot ring->flush = gen6_ring_flush; 2440686a02f1SFrançois Tigeot ring->add_request = gen6_add_request; 2441686a02f1SFrançois Tigeot ring->get_seqno = gen6_ring_get_seqno; 2442a2fdbec6SFrançois Tigeot ring->set_seqno = ring_set_seqno; 24439edbd4a0SFrançois Tigeot if (INTEL_INFO(dev)->gen >= 8) { 24449edbd4a0SFrançois Tigeot ring->irq_enable_mask = 24459edbd4a0SFrançois Tigeot GT_RENDER_USER_INTERRUPT << GEN8_BCS_IRQ_SHIFT; 24469edbd4a0SFrançois Tigeot ring->irq_get = gen8_ring_get_irq; 24479edbd4a0SFrançois Tigeot ring->irq_put = gen8_ring_put_irq; 24489edbd4a0SFrançois Tigeot ring->dispatch_execbuffer = gen8_ring_dispatch_execbuffer; 2449*24edb884SFrançois Tigeot if (i915_semaphore_is_enabled(dev)) { 2450*24edb884SFrançois Tigeot ring->semaphore.sync_to = gen8_ring_sync; 2451*24edb884SFrançois Tigeot ring->semaphore.signal = gen8_xcs_signal; 2452*24edb884SFrançois Tigeot GEN8_RING_SEMAPHORE_INIT; 2453*24edb884SFrançois Tigeot } 24549edbd4a0SFrançois Tigeot } else { 24555d0b1887SFrançois Tigeot ring->irq_enable_mask = GT_BLT_USER_INTERRUPT; 2456686a02f1SFrançois Tigeot ring->irq_get = gen6_ring_get_irq; 2457686a02f1SFrançois Tigeot ring->irq_put = gen6_ring_put_irq; 2458686a02f1SFrançois Tigeot ring->dispatch_execbuffer = gen6_ring_dispatch_execbuffer; 2459*24edb884SFrançois Tigeot if (i915_semaphore_is_enabled(dev)) { 2460ba55f2f5SFrançois Tigeot ring->semaphore.signal = gen6_signal; 2461*24edb884SFrançois Tigeot ring->semaphore.sync_to = gen6_ring_sync; 2462ba55f2f5SFrançois Tigeot /* 2463*24edb884SFrançois Tigeot * The current semaphore is only applied on pre-gen8 2464*24edb884SFrançois Tigeot * platform. And there is no VCS2 ring on the pre-gen8 2465*24edb884SFrançois Tigeot * platform. So the semaphore between BCS and VCS2 is 2466*24edb884SFrançois Tigeot * initialized as INVALID. Gen8 will initialize the 2467*24edb884SFrançois Tigeot * sema between BCS and VCS2 later. 2468ba55f2f5SFrançois Tigeot */ 2469ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[RCS] = MI_SEMAPHORE_SYNC_BR; 2470ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[VCS] = MI_SEMAPHORE_SYNC_BV; 2471ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[BCS] = MI_SEMAPHORE_SYNC_INVALID; 2472ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[VECS] = MI_SEMAPHORE_SYNC_BVE; 2473ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[VCS2] = MI_SEMAPHORE_SYNC_INVALID; 2474ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[RCS] = GEN6_RBSYNC; 2475ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[VCS] = GEN6_VBSYNC; 2476ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[BCS] = GEN6_NOSYNC; 2477ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[VECS] = GEN6_VEBSYNC; 2478ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[VCS2] = GEN6_NOSYNC; 2479*24edb884SFrançois Tigeot } 2480*24edb884SFrançois Tigeot } 24815d0b1887SFrançois Tigeot ring->init = init_ring_common; 24825d0b1887SFrançois Tigeot 24835d0b1887SFrançois Tigeot return intel_init_ring_buffer(dev, ring); 24845d0b1887SFrançois Tigeot } 24855d0b1887SFrançois Tigeot 24865d0b1887SFrançois Tigeot int intel_init_vebox_ring_buffer(struct drm_device *dev) 24875d0b1887SFrançois Tigeot { 2488ba55f2f5SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 2489ba55f2f5SFrançois Tigeot struct intel_engine_cs *ring = &dev_priv->ring[VECS]; 24905d0b1887SFrançois Tigeot 24915d0b1887SFrançois Tigeot ring->name = "video enhancement ring"; 24925d0b1887SFrançois Tigeot ring->id = VECS; 24935d0b1887SFrançois Tigeot 24945d0b1887SFrançois Tigeot ring->mmio_base = VEBOX_RING_BASE; 24955d0b1887SFrançois Tigeot ring->write_tail = ring_write_tail; 24965d0b1887SFrançois Tigeot ring->flush = gen6_ring_flush; 24975d0b1887SFrançois Tigeot ring->add_request = gen6_add_request; 24985d0b1887SFrançois Tigeot ring->get_seqno = gen6_ring_get_seqno; 24995d0b1887SFrançois Tigeot ring->set_seqno = ring_set_seqno; 25009edbd4a0SFrançois Tigeot 25019edbd4a0SFrançois Tigeot if (INTEL_INFO(dev)->gen >= 8) { 25029edbd4a0SFrançois Tigeot ring->irq_enable_mask = 25039edbd4a0SFrançois Tigeot GT_RENDER_USER_INTERRUPT << GEN8_VECS_IRQ_SHIFT; 25049edbd4a0SFrançois Tigeot ring->irq_get = gen8_ring_get_irq; 25059edbd4a0SFrançois Tigeot ring->irq_put = gen8_ring_put_irq; 25069edbd4a0SFrançois Tigeot ring->dispatch_execbuffer = gen8_ring_dispatch_execbuffer; 2507*24edb884SFrançois Tigeot if (i915_semaphore_is_enabled(dev)) { 2508*24edb884SFrançois Tigeot ring->semaphore.sync_to = gen8_ring_sync; 2509*24edb884SFrançois Tigeot ring->semaphore.signal = gen8_xcs_signal; 2510*24edb884SFrançois Tigeot GEN8_RING_SEMAPHORE_INIT; 2511*24edb884SFrançois Tigeot } 25129edbd4a0SFrançois Tigeot } else { 25139edbd4a0SFrançois Tigeot ring->irq_enable_mask = PM_VEBOX_USER_INTERRUPT; 25145d0b1887SFrançois Tigeot ring->irq_get = hsw_vebox_get_irq; 25155d0b1887SFrançois Tigeot ring->irq_put = hsw_vebox_put_irq; 25165d0b1887SFrançois Tigeot ring->dispatch_execbuffer = gen6_ring_dispatch_execbuffer; 2517*24edb884SFrançois Tigeot if (i915_semaphore_is_enabled(dev)) { 2518ba55f2f5SFrançois Tigeot ring->semaphore.sync_to = gen6_ring_sync; 2519ba55f2f5SFrançois Tigeot ring->semaphore.signal = gen6_signal; 2520ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[RCS] = MI_SEMAPHORE_SYNC_VER; 2521ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[VCS] = MI_SEMAPHORE_SYNC_VEV; 2522ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[BCS] = MI_SEMAPHORE_SYNC_VEB; 2523ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[VECS] = MI_SEMAPHORE_SYNC_INVALID; 2524ba55f2f5SFrançois Tigeot ring->semaphore.mbox.wait[VCS2] = MI_SEMAPHORE_SYNC_INVALID; 2525ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[RCS] = GEN6_RVESYNC; 2526ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[VCS] = GEN6_VVESYNC; 2527ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[BCS] = GEN6_BVESYNC; 2528ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[VECS] = GEN6_NOSYNC; 2529ba55f2f5SFrançois Tigeot ring->semaphore.mbox.signal[VCS2] = GEN6_NOSYNC; 2530*24edb884SFrançois Tigeot } 2531*24edb884SFrançois Tigeot } 2532686a02f1SFrançois Tigeot ring->init = init_ring_common; 2533e3adcf8fSFrançois Tigeot 2534e3adcf8fSFrançois Tigeot return intel_init_ring_buffer(dev, ring); 2535e3adcf8fSFrançois Tigeot } 2536b030f26bSFrançois Tigeot 2537b030f26bSFrançois Tigeot int 2538ba55f2f5SFrançois Tigeot intel_ring_flush_all_caches(struct intel_engine_cs *ring) 2539b030f26bSFrançois Tigeot { 2540b030f26bSFrançois Tigeot int ret; 2541b030f26bSFrançois Tigeot 2542b030f26bSFrançois Tigeot if (!ring->gpu_caches_dirty) 2543b030f26bSFrançois Tigeot return 0; 2544b030f26bSFrançois Tigeot 2545b030f26bSFrançois Tigeot ret = ring->flush(ring, 0, I915_GEM_GPU_DOMAINS); 2546b030f26bSFrançois Tigeot if (ret) 2547b030f26bSFrançois Tigeot return ret; 2548b030f26bSFrançois Tigeot 2549a2fdbec6SFrançois Tigeot trace_i915_gem_ring_flush(ring, 0, I915_GEM_GPU_DOMAINS); 2550a2fdbec6SFrançois Tigeot 2551b030f26bSFrançois Tigeot ring->gpu_caches_dirty = false; 2552b030f26bSFrançois Tigeot return 0; 2553b030f26bSFrançois Tigeot } 2554b030f26bSFrançois Tigeot 2555b030f26bSFrançois Tigeot int 2556ba55f2f5SFrançois Tigeot intel_ring_invalidate_all_caches(struct intel_engine_cs *ring) 2557b030f26bSFrançois Tigeot { 2558b030f26bSFrançois Tigeot uint32_t flush_domains; 2559b030f26bSFrançois Tigeot int ret; 2560b030f26bSFrançois Tigeot 2561b030f26bSFrançois Tigeot flush_domains = 0; 2562b030f26bSFrançois Tigeot if (ring->gpu_caches_dirty) 2563b030f26bSFrançois Tigeot flush_domains = I915_GEM_GPU_DOMAINS; 2564b030f26bSFrançois Tigeot 2565b030f26bSFrançois Tigeot ret = ring->flush(ring, I915_GEM_GPU_DOMAINS, flush_domains); 2566b030f26bSFrançois Tigeot if (ret) 2567b030f26bSFrançois Tigeot return ret; 2568b030f26bSFrançois Tigeot 2569a2fdbec6SFrançois Tigeot trace_i915_gem_ring_flush(ring, I915_GEM_GPU_DOMAINS, flush_domains); 2570a2fdbec6SFrançois Tigeot 2571b030f26bSFrançois Tigeot ring->gpu_caches_dirty = false; 2572b030f26bSFrançois Tigeot return 0; 2573b030f26bSFrançois Tigeot } 2574ba55f2f5SFrançois Tigeot 2575ba55f2f5SFrançois Tigeot void 2576ba55f2f5SFrançois Tigeot intel_stop_ring_buffer(struct intel_engine_cs *ring) 2577ba55f2f5SFrançois Tigeot { 2578ba55f2f5SFrançois Tigeot int ret; 2579ba55f2f5SFrançois Tigeot 2580ba55f2f5SFrançois Tigeot if (!intel_ring_initialized(ring)) 2581ba55f2f5SFrançois Tigeot return; 2582ba55f2f5SFrançois Tigeot 2583ba55f2f5SFrançois Tigeot ret = intel_ring_idle(ring); 2584ba55f2f5SFrançois Tigeot if (ret && !i915_reset_in_progress(&to_i915(ring->dev)->gpu_error)) 2585ba55f2f5SFrançois Tigeot DRM_ERROR("failed to quiesce %s whilst cleaning up: %d\n", 2586ba55f2f5SFrançois Tigeot ring->name, ret); 2587ba55f2f5SFrançois Tigeot 2588ba55f2f5SFrançois Tigeot stop_ring(ring); 2589ba55f2f5SFrançois Tigeot } 2590