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 36e3adcf8fSFrançois Tigeot static inline int ring_space(struct intel_ring_buffer *ring) 37e3adcf8fSFrançois Tigeot { 387cbd1a46SFrançois Tigeot int space = (ring->head & HEAD_ADDR) - (ring->tail + I915_RING_FREE_SPACE); 39e3adcf8fSFrançois Tigeot if (space < 0) 40e3adcf8fSFrançois Tigeot space += ring->size; 41e3adcf8fSFrançois Tigeot return space; 42e3adcf8fSFrançois Tigeot } 43e3adcf8fSFrançois Tigeot 44*9edbd4a0SFrançois Tigeot void __intel_ring_advance(struct intel_ring_buffer *ring) 45*9edbd4a0SFrançois Tigeot { 46*9edbd4a0SFrançois Tigeot struct drm_i915_private *dev_priv = ring->dev->dev_private; 47*9edbd4a0SFrançois Tigeot 48*9edbd4a0SFrançois Tigeot ring->tail &= ring->size - 1; 49*9edbd4a0SFrançois Tigeot if (dev_priv->gpu_error.stop_rings & intel_ring_flag(ring)) 50*9edbd4a0SFrançois Tigeot return; 51*9edbd4a0SFrançois Tigeot ring->write_tail(ring, ring->tail); 52*9edbd4a0SFrançois Tigeot } 53*9edbd4a0SFrançois Tigeot 54e3adcf8fSFrançois Tigeot static int 55686a02f1SFrançois Tigeot gen2_render_ring_flush(struct intel_ring_buffer *ring, 56686a02f1SFrançois Tigeot u32 invalidate_domains, 57686a02f1SFrançois Tigeot u32 flush_domains) 58686a02f1SFrançois Tigeot { 59686a02f1SFrançois Tigeot u32 cmd; 60686a02f1SFrançois Tigeot int ret; 61686a02f1SFrançois Tigeot 62686a02f1SFrançois Tigeot cmd = MI_FLUSH; 63686a02f1SFrançois Tigeot if (((invalidate_domains|flush_domains) & I915_GEM_DOMAIN_RENDER) == 0) 64686a02f1SFrançois Tigeot cmd |= MI_NO_WRITE_FLUSH; 65686a02f1SFrançois Tigeot 66686a02f1SFrançois Tigeot if (invalidate_domains & I915_GEM_DOMAIN_SAMPLER) 67686a02f1SFrançois Tigeot cmd |= MI_READ_FLUSH; 68686a02f1SFrançois Tigeot 69686a02f1SFrançois Tigeot ret = intel_ring_begin(ring, 2); 70686a02f1SFrançois Tigeot if (ret) 71686a02f1SFrançois Tigeot return ret; 72686a02f1SFrançois Tigeot 73686a02f1SFrançois Tigeot intel_ring_emit(ring, cmd); 74686a02f1SFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 75686a02f1SFrançois Tigeot intel_ring_advance(ring); 76686a02f1SFrançois Tigeot 77686a02f1SFrançois Tigeot return 0; 78686a02f1SFrançois Tigeot } 79686a02f1SFrançois Tigeot 80686a02f1SFrançois Tigeot static int 81686a02f1SFrançois Tigeot gen4_render_ring_flush(struct intel_ring_buffer *ring, 82686a02f1SFrançois Tigeot u32 invalidate_domains, 83686a02f1SFrançois Tigeot u32 flush_domains) 84e3adcf8fSFrançois Tigeot { 85e3adcf8fSFrançois Tigeot struct drm_device *dev = ring->dev; 86686a02f1SFrançois Tigeot u32 cmd; 87e3adcf8fSFrançois Tigeot int ret; 88e3adcf8fSFrançois Tigeot 89e3adcf8fSFrançois Tigeot /* 90e3adcf8fSFrançois Tigeot * read/write caches: 91e3adcf8fSFrançois Tigeot * 92e3adcf8fSFrançois Tigeot * I915_GEM_DOMAIN_RENDER is always invalidated, but is 93e3adcf8fSFrançois Tigeot * only flushed if MI_NO_WRITE_FLUSH is unset. On 965, it is 94e3adcf8fSFrançois Tigeot * also flushed at 2d versus 3d pipeline switches. 95e3adcf8fSFrançois Tigeot * 96e3adcf8fSFrançois Tigeot * read-only caches: 97e3adcf8fSFrançois Tigeot * 98e3adcf8fSFrançois Tigeot * I915_GEM_DOMAIN_SAMPLER is flushed on pre-965 if 99e3adcf8fSFrançois Tigeot * MI_READ_FLUSH is set, and is always flushed on 965. 100e3adcf8fSFrançois Tigeot * 101e3adcf8fSFrançois Tigeot * I915_GEM_DOMAIN_COMMAND may not exist? 102e3adcf8fSFrançois Tigeot * 103e3adcf8fSFrançois Tigeot * I915_GEM_DOMAIN_INSTRUCTION, which exists on 965, is 104e3adcf8fSFrançois Tigeot * invalidated when MI_EXE_FLUSH is set. 105e3adcf8fSFrançois Tigeot * 106e3adcf8fSFrançois Tigeot * I915_GEM_DOMAIN_VERTEX, which exists on 965, is 107e3adcf8fSFrançois Tigeot * invalidated with every MI_FLUSH. 108e3adcf8fSFrançois Tigeot * 109e3adcf8fSFrançois Tigeot * TLBs: 110e3adcf8fSFrançois Tigeot * 111e3adcf8fSFrançois Tigeot * On 965, TLBs associated with I915_GEM_DOMAIN_COMMAND 112e3adcf8fSFrançois Tigeot * and I915_GEM_DOMAIN_CPU in are invalidated at PTE write and 113e3adcf8fSFrançois Tigeot * I915_GEM_DOMAIN_RENDER and I915_GEM_DOMAIN_SAMPLER 114e3adcf8fSFrançois Tigeot * are flushed at any MI_FLUSH. 115e3adcf8fSFrançois Tigeot */ 116e3adcf8fSFrançois Tigeot 117e3adcf8fSFrançois Tigeot cmd = MI_FLUSH | MI_NO_WRITE_FLUSH; 118686a02f1SFrançois Tigeot if ((invalidate_domains|flush_domains) & I915_GEM_DOMAIN_RENDER) 119e3adcf8fSFrançois Tigeot cmd &= ~MI_NO_WRITE_FLUSH; 120e3adcf8fSFrançois Tigeot if (invalidate_domains & I915_GEM_DOMAIN_INSTRUCTION) 121e3adcf8fSFrançois Tigeot cmd |= MI_EXE_FLUSH; 122e3adcf8fSFrançois Tigeot 123e3adcf8fSFrançois Tigeot if (invalidate_domains & I915_GEM_DOMAIN_COMMAND && 124e3adcf8fSFrançois Tigeot (IS_G4X(dev) || IS_GEN5(dev))) 125e3adcf8fSFrançois Tigeot cmd |= MI_INVALIDATE_ISP; 126e3adcf8fSFrançois Tigeot 127e3adcf8fSFrançois Tigeot ret = intel_ring_begin(ring, 2); 128e3adcf8fSFrançois Tigeot if (ret) 129e3adcf8fSFrançois Tigeot return ret; 130e3adcf8fSFrançois Tigeot 131e3adcf8fSFrançois Tigeot intel_ring_emit(ring, cmd); 132e3adcf8fSFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 133e3adcf8fSFrançois Tigeot intel_ring_advance(ring); 134e3adcf8fSFrançois Tigeot 135e3adcf8fSFrançois Tigeot return 0; 136e3adcf8fSFrançois Tigeot } 137e3adcf8fSFrançois Tigeot 138e3adcf8fSFrançois Tigeot /** 139e3adcf8fSFrançois Tigeot * Emits a PIPE_CONTROL with a non-zero post-sync operation, for 140e3adcf8fSFrançois Tigeot * implementing two workarounds on gen6. From section 1.4.7.1 141e3adcf8fSFrançois Tigeot * "PIPE_CONTROL" of the Sandy Bridge PRM volume 2 part 1: 142e3adcf8fSFrançois Tigeot * 143e3adcf8fSFrançois Tigeot * [DevSNB-C+{W/A}] Before any depth stall flush (including those 144e3adcf8fSFrançois Tigeot * produced by non-pipelined state commands), software needs to first 145e3adcf8fSFrançois Tigeot * send a PIPE_CONTROL with no bits set except Post-Sync Operation != 146e3adcf8fSFrançois Tigeot * 0. 147e3adcf8fSFrançois Tigeot * 148e3adcf8fSFrançois Tigeot * [Dev-SNB{W/A}]: Before a PIPE_CONTROL with Write Cache Flush Enable 149e3adcf8fSFrançois Tigeot * =1, a PIPE_CONTROL with any non-zero post-sync-op is required. 150e3adcf8fSFrançois Tigeot * 151e3adcf8fSFrançois Tigeot * And the workaround for these two requires this workaround first: 152e3adcf8fSFrançois Tigeot * 153e3adcf8fSFrançois Tigeot * [Dev-SNB{W/A}]: Pipe-control with CS-stall bit set must be sent 154e3adcf8fSFrançois Tigeot * BEFORE the pipe-control with a post-sync op and no write-cache 155e3adcf8fSFrançois Tigeot * flushes. 156e3adcf8fSFrançois Tigeot * 157e3adcf8fSFrançois Tigeot * And this last workaround is tricky because of the requirements on 158e3adcf8fSFrançois Tigeot * that bit. From section 1.4.7.2.3 "Stall" of the Sandy Bridge PRM 159e3adcf8fSFrançois Tigeot * volume 2 part 1: 160e3adcf8fSFrançois Tigeot * 161e3adcf8fSFrançois Tigeot * "1 of the following must also be set: 162e3adcf8fSFrançois Tigeot * - Render Target Cache Flush Enable ([12] of DW1) 163e3adcf8fSFrançois Tigeot * - Depth Cache Flush Enable ([0] of DW1) 164e3adcf8fSFrançois Tigeot * - Stall at Pixel Scoreboard ([1] of DW1) 165e3adcf8fSFrançois Tigeot * - Depth Stall ([13] of DW1) 166e3adcf8fSFrançois Tigeot * - Post-Sync Operation ([13] of DW1) 167e3adcf8fSFrançois Tigeot * - Notify Enable ([8] of DW1)" 168e3adcf8fSFrançois Tigeot * 169e3adcf8fSFrançois Tigeot * The cache flushes require the workaround flush that triggered this 170e3adcf8fSFrançois Tigeot * one, so we can't use it. Depth stall would trigger the same. 171e3adcf8fSFrançois Tigeot * Post-sync nonzero is what triggered this second workaround, so we 172e3adcf8fSFrançois Tigeot * can't use that one either. Notify enable is IRQs, which aren't 173e3adcf8fSFrançois Tigeot * really our business. That leaves only stall at scoreboard. 174e3adcf8fSFrançois Tigeot */ 175e3adcf8fSFrançois Tigeot static int 176e3adcf8fSFrançois Tigeot intel_emit_post_sync_nonzero_flush(struct intel_ring_buffer *ring) 177e3adcf8fSFrançois Tigeot { 178*9edbd4a0SFrançois Tigeot u32 scratch_addr = ring->scratch.gtt_offset + 128; 179e3adcf8fSFrançois Tigeot int ret; 180e3adcf8fSFrançois Tigeot 181e3adcf8fSFrançois Tigeot 182e3adcf8fSFrançois Tigeot ret = intel_ring_begin(ring, 6); 183e3adcf8fSFrançois Tigeot if (ret) 184e3adcf8fSFrançois Tigeot return ret; 185e3adcf8fSFrançois Tigeot 186e3adcf8fSFrançois Tigeot intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(5)); 187e3adcf8fSFrançois Tigeot intel_ring_emit(ring, PIPE_CONTROL_CS_STALL | 188e3adcf8fSFrançois Tigeot PIPE_CONTROL_STALL_AT_SCOREBOARD); 189e3adcf8fSFrançois Tigeot intel_ring_emit(ring, scratch_addr | PIPE_CONTROL_GLOBAL_GTT); /* address */ 190e3adcf8fSFrançois Tigeot intel_ring_emit(ring, 0); /* low dword */ 191e3adcf8fSFrançois Tigeot intel_ring_emit(ring, 0); /* high dword */ 192e3adcf8fSFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 193e3adcf8fSFrançois Tigeot intel_ring_advance(ring); 194e3adcf8fSFrançois Tigeot 195e3adcf8fSFrançois Tigeot ret = intel_ring_begin(ring, 6); 196e3adcf8fSFrançois Tigeot if (ret) 197e3adcf8fSFrançois Tigeot return ret; 198e3adcf8fSFrançois Tigeot 199e3adcf8fSFrançois Tigeot intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(5)); 200e3adcf8fSFrançois Tigeot intel_ring_emit(ring, PIPE_CONTROL_QW_WRITE); 201e3adcf8fSFrançois Tigeot intel_ring_emit(ring, scratch_addr | PIPE_CONTROL_GLOBAL_GTT); /* address */ 202e3adcf8fSFrançois Tigeot intel_ring_emit(ring, 0); 203e3adcf8fSFrançois Tigeot intel_ring_emit(ring, 0); 204e3adcf8fSFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 205e3adcf8fSFrançois Tigeot intel_ring_advance(ring); 206e3adcf8fSFrançois Tigeot 207e3adcf8fSFrançois Tigeot return 0; 208e3adcf8fSFrançois Tigeot } 209e3adcf8fSFrançois Tigeot 210e3adcf8fSFrançois Tigeot static int 211e3adcf8fSFrançois Tigeot gen6_render_ring_flush(struct intel_ring_buffer *ring, 212e3adcf8fSFrançois Tigeot u32 invalidate_domains, u32 flush_domains) 213e3adcf8fSFrançois Tigeot { 214e3adcf8fSFrançois Tigeot u32 flags = 0; 215*9edbd4a0SFrançois Tigeot u32 scratch_addr = ring->scratch.gtt_offset + 128; 216e3adcf8fSFrançois Tigeot int ret; 217e3adcf8fSFrançois Tigeot 218e3adcf8fSFrançois Tigeot /* Force SNB workarounds for PIPE_CONTROL flushes */ 219686a02f1SFrançois Tigeot ret = intel_emit_post_sync_nonzero_flush(ring); 220686a02f1SFrançois Tigeot if (ret) 221686a02f1SFrançois Tigeot return ret; 222e3adcf8fSFrançois Tigeot 223e3adcf8fSFrançois Tigeot /* Just flush everything. Experiments have shown that reducing the 224e3adcf8fSFrançois Tigeot * number of bits based on the write domains has little performance 225e3adcf8fSFrançois Tigeot * impact. 226e3adcf8fSFrançois Tigeot */ 227b5c29a34SFrançois Tigeot if (flush_domains) { 228e3adcf8fSFrançois Tigeot flags |= PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH; 229b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_DEPTH_CACHE_FLUSH; 230b5c29a34SFrançois Tigeot /* 231b5c29a34SFrançois Tigeot * Ensure that any following seqno writes only happen 232b5c29a34SFrançois Tigeot * when the render cache is indeed flushed. 233b5c29a34SFrançois Tigeot */ 234b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_CS_STALL; 235b5c29a34SFrançois Tigeot } 236b5c29a34SFrançois Tigeot if (invalidate_domains) { 237686a02f1SFrançois Tigeot flags |= PIPE_CONTROL_TLB_INVALIDATE; 238e3adcf8fSFrançois Tigeot flags |= PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE; 239e3adcf8fSFrançois Tigeot flags |= PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE; 240e3adcf8fSFrançois Tigeot flags |= PIPE_CONTROL_VF_CACHE_INVALIDATE; 241e3adcf8fSFrançois Tigeot flags |= PIPE_CONTROL_CONST_CACHE_INVALIDATE; 242e3adcf8fSFrançois Tigeot flags |= PIPE_CONTROL_STATE_CACHE_INVALIDATE; 243686a02f1SFrançois Tigeot /* 244b5c29a34SFrançois Tigeot * TLB invalidate requires a post-sync write. 245686a02f1SFrançois Tigeot */ 246b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_QW_WRITE | PIPE_CONTROL_CS_STALL; 247b5c29a34SFrançois Tigeot } 248e3adcf8fSFrançois Tigeot 249b5c29a34SFrançois Tigeot ret = intel_ring_begin(ring, 4); 250e3adcf8fSFrançois Tigeot if (ret) 251e3adcf8fSFrançois Tigeot return ret; 252e3adcf8fSFrançois Tigeot 253b5c29a34SFrançois Tigeot intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(4)); 254e3adcf8fSFrançois Tigeot intel_ring_emit(ring, flags); 255e3adcf8fSFrançois Tigeot intel_ring_emit(ring, scratch_addr | PIPE_CONTROL_GLOBAL_GTT); 256b5c29a34SFrançois Tigeot intel_ring_emit(ring, 0); 257b5c29a34SFrançois Tigeot intel_ring_advance(ring); 258b5c29a34SFrançois Tigeot 259b5c29a34SFrançois Tigeot return 0; 260b5c29a34SFrançois Tigeot } 261b5c29a34SFrançois Tigeot 262b5c29a34SFrançois Tigeot static int 263b5c29a34SFrançois Tigeot gen7_render_ring_cs_stall_wa(struct intel_ring_buffer *ring) 264b5c29a34SFrançois Tigeot { 265b5c29a34SFrançois Tigeot int ret; 266b5c29a34SFrançois Tigeot 267b5c29a34SFrançois Tigeot ret = intel_ring_begin(ring, 4); 268b5c29a34SFrançois Tigeot if (ret) 269b5c29a34SFrançois Tigeot return ret; 270b5c29a34SFrançois Tigeot 271b5c29a34SFrançois Tigeot intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(4)); 272b5c29a34SFrançois Tigeot intel_ring_emit(ring, PIPE_CONTROL_CS_STALL | 273b5c29a34SFrançois Tigeot PIPE_CONTROL_STALL_AT_SCOREBOARD); 274b5c29a34SFrançois Tigeot intel_ring_emit(ring, 0); 275b5c29a34SFrançois Tigeot intel_ring_emit(ring, 0); 276b5c29a34SFrançois Tigeot intel_ring_advance(ring); 277b5c29a34SFrançois Tigeot 278b5c29a34SFrançois Tigeot return 0; 279b5c29a34SFrançois Tigeot } 280b5c29a34SFrançois Tigeot 2815d0b1887SFrançois Tigeot static int gen7_ring_fbc_flush(struct intel_ring_buffer *ring, u32 value) 2825d0b1887SFrançois Tigeot { 2835d0b1887SFrançois Tigeot int ret; 2845d0b1887SFrançois Tigeot 2855d0b1887SFrançois Tigeot if (!ring->fbc_dirty) 2865d0b1887SFrançois Tigeot return 0; 2875d0b1887SFrançois Tigeot 288*9edbd4a0SFrançois Tigeot ret = intel_ring_begin(ring, 6); 2895d0b1887SFrançois Tigeot if (ret) 2905d0b1887SFrançois Tigeot return ret; 2915d0b1887SFrançois Tigeot /* WaFbcNukeOn3DBlt:ivb/hsw */ 2925d0b1887SFrançois Tigeot intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1)); 2935d0b1887SFrançois Tigeot intel_ring_emit(ring, MSG_FBC_REND_STATE); 2945d0b1887SFrançois Tigeot intel_ring_emit(ring, value); 295*9edbd4a0SFrançois Tigeot intel_ring_emit(ring, MI_STORE_REGISTER_MEM(1) | MI_SRM_LRM_GLOBAL_GTT); 296*9edbd4a0SFrançois Tigeot intel_ring_emit(ring, MSG_FBC_REND_STATE); 297*9edbd4a0SFrançois Tigeot intel_ring_emit(ring, ring->scratch.gtt_offset + 256); 2985d0b1887SFrançois Tigeot intel_ring_advance(ring); 2995d0b1887SFrançois Tigeot 3005d0b1887SFrançois Tigeot ring->fbc_dirty = false; 3015d0b1887SFrançois Tigeot return 0; 3025d0b1887SFrançois Tigeot } 3035d0b1887SFrançois Tigeot 304b5c29a34SFrançois Tigeot static int 305b5c29a34SFrançois Tigeot gen7_render_ring_flush(struct intel_ring_buffer *ring, 306b5c29a34SFrançois Tigeot u32 invalidate_domains, u32 flush_domains) 307b5c29a34SFrançois Tigeot { 308b5c29a34SFrançois Tigeot u32 flags = 0; 309*9edbd4a0SFrançois Tigeot u32 scratch_addr = ring->scratch.gtt_offset + 128; 310b5c29a34SFrançois Tigeot int ret; 311b5c29a34SFrançois Tigeot 312b5c29a34SFrançois Tigeot /* 313b5c29a34SFrançois Tigeot * Ensure that any following seqno writes only happen when the render 314b5c29a34SFrançois Tigeot * cache is indeed flushed. 315b5c29a34SFrançois Tigeot * 316b5c29a34SFrançois Tigeot * Workaround: 4th PIPE_CONTROL command (except the ones with only 317b5c29a34SFrançois Tigeot * read-cache invalidate bits set) must have the CS_STALL bit set. We 318b5c29a34SFrançois Tigeot * don't try to be clever and just set it unconditionally. 319b5c29a34SFrançois Tigeot */ 320b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_CS_STALL; 321b5c29a34SFrançois Tigeot 322b5c29a34SFrançois Tigeot /* Just flush everything. Experiments have shown that reducing the 323b5c29a34SFrançois Tigeot * number of bits based on the write domains has little performance 324b5c29a34SFrançois Tigeot * impact. 325b5c29a34SFrançois Tigeot */ 326b5c29a34SFrançois Tigeot if (flush_domains) { 327b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH; 328b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_DEPTH_CACHE_FLUSH; 329b5c29a34SFrançois Tigeot } 330b5c29a34SFrançois Tigeot if (invalidate_domains) { 331b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_TLB_INVALIDATE; 332b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE; 333b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE; 334b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_VF_CACHE_INVALIDATE; 335b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_CONST_CACHE_INVALIDATE; 336b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_STATE_CACHE_INVALIDATE; 337b5c29a34SFrançois Tigeot /* 338b5c29a34SFrançois Tigeot * TLB invalidate requires a post-sync write. 339b5c29a34SFrançois Tigeot */ 340b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_QW_WRITE; 341a2fdbec6SFrançois Tigeot flags |= PIPE_CONTROL_GLOBAL_GTT_IVB; 342b5c29a34SFrançois Tigeot 343b5c29a34SFrançois Tigeot /* Workaround: we must issue a pipe_control with CS-stall bit 344b5c29a34SFrançois Tigeot * set before a pipe_control command that has the state cache 345b5c29a34SFrançois Tigeot * invalidate bit set. */ 346b5c29a34SFrançois Tigeot gen7_render_ring_cs_stall_wa(ring); 347b5c29a34SFrançois Tigeot } 348b5c29a34SFrançois Tigeot 349b5c29a34SFrançois Tigeot ret = intel_ring_begin(ring, 4); 350b5c29a34SFrançois Tigeot if (ret) 351b5c29a34SFrançois Tigeot return ret; 352b5c29a34SFrançois Tigeot 353b5c29a34SFrançois Tigeot intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(4)); 354b5c29a34SFrançois Tigeot intel_ring_emit(ring, flags); 355a2fdbec6SFrançois Tigeot intel_ring_emit(ring, scratch_addr); 356b5c29a34SFrançois Tigeot intel_ring_emit(ring, 0); 357e3adcf8fSFrançois Tigeot intel_ring_advance(ring); 358e3adcf8fSFrançois Tigeot 359*9edbd4a0SFrançois Tigeot if (!invalidate_domains && flush_domains) 3605d0b1887SFrançois Tigeot return gen7_ring_fbc_flush(ring, FBC_REND_NUKE); 3615d0b1887SFrançois Tigeot 362e3adcf8fSFrançois Tigeot return 0; 363e3adcf8fSFrançois Tigeot } 364e3adcf8fSFrançois Tigeot 365*9edbd4a0SFrançois Tigeot static int 366*9edbd4a0SFrançois Tigeot gen8_render_ring_flush(struct intel_ring_buffer *ring, 367*9edbd4a0SFrançois Tigeot u32 invalidate_domains, u32 flush_domains) 368*9edbd4a0SFrançois Tigeot { 369*9edbd4a0SFrançois Tigeot u32 flags = 0; 370*9edbd4a0SFrançois Tigeot u32 scratch_addr = ring->scratch.gtt_offset + 128; 371*9edbd4a0SFrançois Tigeot int ret; 372*9edbd4a0SFrançois Tigeot 373*9edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_CS_STALL; 374*9edbd4a0SFrançois Tigeot 375*9edbd4a0SFrançois Tigeot if (flush_domains) { 376*9edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH; 377*9edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_DEPTH_CACHE_FLUSH; 378*9edbd4a0SFrançois Tigeot } 379*9edbd4a0SFrançois Tigeot if (invalidate_domains) { 380*9edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_TLB_INVALIDATE; 381*9edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE; 382*9edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE; 383*9edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_VF_CACHE_INVALIDATE; 384*9edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_CONST_CACHE_INVALIDATE; 385*9edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_STATE_CACHE_INVALIDATE; 386*9edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_QW_WRITE; 387*9edbd4a0SFrançois Tigeot flags |= PIPE_CONTROL_GLOBAL_GTT_IVB; 388*9edbd4a0SFrançois Tigeot } 389*9edbd4a0SFrançois Tigeot 390*9edbd4a0SFrançois Tigeot ret = intel_ring_begin(ring, 6); 391*9edbd4a0SFrançois Tigeot if (ret) 392*9edbd4a0SFrançois Tigeot return ret; 393*9edbd4a0SFrançois Tigeot 394*9edbd4a0SFrançois Tigeot intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(6)); 395*9edbd4a0SFrançois Tigeot intel_ring_emit(ring, flags); 396*9edbd4a0SFrançois Tigeot intel_ring_emit(ring, scratch_addr); 397*9edbd4a0SFrançois Tigeot intel_ring_emit(ring, 0); 398*9edbd4a0SFrançois Tigeot intel_ring_emit(ring, 0); 399*9edbd4a0SFrançois Tigeot intel_ring_emit(ring, 0); 400*9edbd4a0SFrançois Tigeot intel_ring_advance(ring); 401*9edbd4a0SFrançois Tigeot 402*9edbd4a0SFrançois Tigeot return 0; 403*9edbd4a0SFrançois Tigeot 404*9edbd4a0SFrançois Tigeot } 405*9edbd4a0SFrançois Tigeot 406e3adcf8fSFrançois Tigeot static void ring_write_tail(struct intel_ring_buffer *ring, 407b5c29a34SFrançois Tigeot u32 value) 408e3adcf8fSFrançois Tigeot { 409e3adcf8fSFrançois Tigeot drm_i915_private_t *dev_priv = ring->dev->dev_private; 410e3adcf8fSFrançois Tigeot I915_WRITE_TAIL(ring, value); 411e3adcf8fSFrançois Tigeot } 412e3adcf8fSFrançois Tigeot 413e3adcf8fSFrançois Tigeot u32 intel_ring_get_active_head(struct intel_ring_buffer *ring) 414e3adcf8fSFrançois Tigeot { 415e3adcf8fSFrançois Tigeot drm_i915_private_t *dev_priv = ring->dev->dev_private; 416b5c29a34SFrançois Tigeot u32 acthd_reg = INTEL_INFO(ring->dev)->gen >= 4 ? 417e3adcf8fSFrançois Tigeot RING_ACTHD(ring->mmio_base) : ACTHD; 418e3adcf8fSFrançois Tigeot 419e3adcf8fSFrançois Tigeot return I915_READ(acthd_reg); 420e3adcf8fSFrançois Tigeot } 421e3adcf8fSFrançois Tigeot 4225d0b1887SFrançois Tigeot static void ring_setup_phys_status_page(struct intel_ring_buffer *ring) 4235d0b1887SFrançois Tigeot { 4245d0b1887SFrançois Tigeot struct drm_i915_private *dev_priv = ring->dev->dev_private; 4255d0b1887SFrançois Tigeot u32 addr; 4265d0b1887SFrançois Tigeot 4275d0b1887SFrançois Tigeot addr = dev_priv->status_page_dmah->busaddr; 4285d0b1887SFrançois Tigeot if (INTEL_INFO(ring->dev)->gen >= 4) 4295d0b1887SFrançois Tigeot addr |= (dev_priv->status_page_dmah->busaddr >> 28) & 0xf0; 4305d0b1887SFrançois Tigeot I915_WRITE(HWS_PGA, addr); 4315d0b1887SFrançois Tigeot } 4325d0b1887SFrançois Tigeot 433e3adcf8fSFrançois Tigeot static int init_ring_common(struct intel_ring_buffer *ring) 434e3adcf8fSFrançois Tigeot { 435686a02f1SFrançois Tigeot struct drm_device *dev = ring->dev; 436686a02f1SFrançois Tigeot drm_i915_private_t *dev_priv = dev->dev_private; 437e3adcf8fSFrançois Tigeot struct drm_i915_gem_object *obj = ring->obj; 438686a02f1SFrançois Tigeot int ret = 0; 439b5c29a34SFrançois Tigeot u32 head; 440e3adcf8fSFrançois Tigeot 441*9edbd4a0SFrançois Tigeot gen6_gt_force_wake_get(dev_priv, FORCEWAKE_ALL); 442686a02f1SFrançois Tigeot 4435d0b1887SFrançois Tigeot if (I915_NEED_GFX_HWS(dev)) 4445d0b1887SFrançois Tigeot intel_ring_setup_status_page(ring); 4455d0b1887SFrançois Tigeot else 4465d0b1887SFrançois Tigeot ring_setup_phys_status_page(ring); 4475d0b1887SFrançois Tigeot 448e3adcf8fSFrançois Tigeot /* Stop the ring if it's running. */ 449e3adcf8fSFrançois Tigeot I915_WRITE_CTL(ring, 0); 450e3adcf8fSFrançois Tigeot I915_WRITE_HEAD(ring, 0); 451e3adcf8fSFrançois Tigeot ring->write_tail(ring, 0); 452e3adcf8fSFrançois Tigeot 453e3adcf8fSFrançois Tigeot head = I915_READ_HEAD(ring) & HEAD_ADDR; 454e3adcf8fSFrançois Tigeot 455e3adcf8fSFrançois Tigeot /* G45 ring initialization fails to reset head to zero */ 456e3adcf8fSFrançois Tigeot if (head != 0) { 457b5c29a34SFrançois Tigeot DRM_DEBUG_KMS("%s head not reset to zero " 458e3adcf8fSFrançois Tigeot "ctl %08x head %08x tail %08x start %08x\n", 459e3adcf8fSFrançois Tigeot ring->name, 460e3adcf8fSFrançois Tigeot I915_READ_CTL(ring), 461e3adcf8fSFrançois Tigeot I915_READ_HEAD(ring), 462e3adcf8fSFrançois Tigeot I915_READ_TAIL(ring), 463e3adcf8fSFrançois Tigeot I915_READ_START(ring)); 464e3adcf8fSFrançois Tigeot 465e3adcf8fSFrançois Tigeot I915_WRITE_HEAD(ring, 0); 466e3adcf8fSFrançois Tigeot 467e3adcf8fSFrançois Tigeot if (I915_READ_HEAD(ring) & HEAD_ADDR) { 468e3adcf8fSFrançois Tigeot DRM_ERROR("failed to set %s head to zero " 469e3adcf8fSFrançois Tigeot "ctl %08x head %08x tail %08x start %08x\n", 470e3adcf8fSFrançois Tigeot ring->name, 471e3adcf8fSFrançois Tigeot I915_READ_CTL(ring), 472e3adcf8fSFrançois Tigeot I915_READ_HEAD(ring), 473e3adcf8fSFrançois Tigeot I915_READ_TAIL(ring), 474e3adcf8fSFrançois Tigeot I915_READ_START(ring)); 475e3adcf8fSFrançois Tigeot } 476e3adcf8fSFrançois Tigeot } 477e3adcf8fSFrançois Tigeot 478b5c29a34SFrançois Tigeot /* Initialize the ring. This must happen _after_ we've cleared the ring 479b5c29a34SFrançois Tigeot * registers with the above sequence (the readback of the HEAD registers 480b5c29a34SFrançois Tigeot * also enforces ordering), otherwise the hw might lose the new ring 481b5c29a34SFrançois Tigeot * register values. */ 482*9edbd4a0SFrançois Tigeot I915_WRITE_START(ring, i915_gem_obj_ggtt_offset(obj)); 483e3adcf8fSFrançois Tigeot I915_WRITE_CTL(ring, 484e3adcf8fSFrançois Tigeot ((ring->size - PAGE_SIZE) & RING_NR_PAGES) 485e3adcf8fSFrançois Tigeot | RING_VALID); 486e3adcf8fSFrançois Tigeot 487e3adcf8fSFrançois Tigeot /* If the head is still not zero, the ring is dead */ 488b5c29a34SFrançois Tigeot if (wait_for((I915_READ_CTL(ring) & RING_VALID) != 0 && 489*9edbd4a0SFrançois Tigeot I915_READ_START(ring) == i915_gem_obj_ggtt_offset(obj) && 490b5c29a34SFrançois Tigeot (I915_READ_HEAD(ring) & HEAD_ADDR) == 0, 50)) { 491e3adcf8fSFrançois Tigeot DRM_ERROR("%s initialization failed " 492e3adcf8fSFrançois Tigeot "ctl %08x head %08x tail %08x start %08x\n", 493e3adcf8fSFrançois Tigeot ring->name, 494e3adcf8fSFrançois Tigeot I915_READ_CTL(ring), 495e3adcf8fSFrançois Tigeot I915_READ_HEAD(ring), 496e3adcf8fSFrançois Tigeot I915_READ_TAIL(ring), 497e3adcf8fSFrançois Tigeot I915_READ_START(ring)); 498686a02f1SFrançois Tigeot ret = -EIO; 499686a02f1SFrançois Tigeot goto out; 500e3adcf8fSFrançois Tigeot } 501e3adcf8fSFrançois Tigeot 502e3adcf8fSFrançois Tigeot if (!drm_core_check_feature(ring->dev, DRIVER_MODESET)) 503e3adcf8fSFrançois Tigeot i915_kernel_lost_context(ring->dev); 504e3adcf8fSFrançois Tigeot else { 505e3adcf8fSFrançois Tigeot ring->head = I915_READ_HEAD(ring); 506e3adcf8fSFrançois Tigeot ring->tail = I915_READ_TAIL(ring) & TAIL_ADDR; 507e3adcf8fSFrançois Tigeot ring->space = ring_space(ring); 508686a02f1SFrançois Tigeot ring->last_retired_head = -1; 509e3adcf8fSFrançois Tigeot } 510e3adcf8fSFrançois Tigeot 5115d0b1887SFrançois Tigeot memset(&ring->hangcheck, 0, sizeof(ring->hangcheck)); 5125d0b1887SFrançois Tigeot 513686a02f1SFrançois Tigeot out: 514*9edbd4a0SFrançois Tigeot gen6_gt_force_wake_put(dev_priv, FORCEWAKE_ALL); 515686a02f1SFrançois Tigeot 516686a02f1SFrançois Tigeot return ret; 517e3adcf8fSFrançois Tigeot } 518e3adcf8fSFrançois Tigeot 519e3adcf8fSFrançois Tigeot static int 520e3adcf8fSFrançois Tigeot init_pipe_control(struct intel_ring_buffer *ring) 521e3adcf8fSFrançois Tigeot { 522e3adcf8fSFrançois Tigeot int ret; 523e3adcf8fSFrançois Tigeot 524*9edbd4a0SFrançois Tigeot if (ring->scratch.obj) 525e3adcf8fSFrançois Tigeot return 0; 526e3adcf8fSFrançois Tigeot 527*9edbd4a0SFrançois Tigeot ring->scratch.obj = i915_gem_alloc_object(ring->dev, 4096); 528*9edbd4a0SFrançois Tigeot if (ring->scratch.obj == NULL) { 529e3adcf8fSFrançois Tigeot DRM_ERROR("Failed to allocate seqno page\n"); 530e3adcf8fSFrançois Tigeot ret = -ENOMEM; 531e3adcf8fSFrançois Tigeot goto err; 532e3adcf8fSFrançois Tigeot } 533e3adcf8fSFrançois Tigeot 534*9edbd4a0SFrançois Tigeot i915_gem_object_set_cache_level(ring->scratch.obj, I915_CACHE_LLC); 535e3adcf8fSFrançois Tigeot 536*9edbd4a0SFrançois Tigeot ret = i915_gem_obj_ggtt_pin(ring->scratch.obj, 4096, true, false); 537e3adcf8fSFrançois Tigeot if (ret) 538e3adcf8fSFrançois Tigeot goto err_unref; 539e3adcf8fSFrançois Tigeot 540*9edbd4a0SFrançois Tigeot ring->scratch.gtt_offset = i915_gem_obj_ggtt_offset(ring->scratch.obj); 541*9edbd4a0SFrançois Tigeot ring->scratch.cpu_page = kmap(ring->scratch.obj->pages[0]); 542*9edbd4a0SFrançois Tigeot if (ring->scratch.cpu_page == NULL) { 5435d0b1887SFrançois Tigeot ret = -ENOMEM; 544e3adcf8fSFrançois Tigeot goto err_unpin; 5455d0b1887SFrançois Tigeot } 546a2fdbec6SFrançois Tigeot 547a2fdbec6SFrançois Tigeot DRM_DEBUG_DRIVER("%s pipe control offset: 0x%08x\n", 548*9edbd4a0SFrançois Tigeot ring->name, ring->scratch.gtt_offset); 549e3adcf8fSFrançois Tigeot return 0; 550e3adcf8fSFrançois Tigeot 551e3adcf8fSFrançois Tigeot err_unpin: 552*9edbd4a0SFrançois Tigeot i915_gem_object_unpin(ring->scratch.obj); 553e3adcf8fSFrançois Tigeot err_unref: 554*9edbd4a0SFrançois Tigeot drm_gem_object_unreference(&ring->scratch.obj->base); 555e3adcf8fSFrançois Tigeot err: 556e3adcf8fSFrançois Tigeot return ret; 557e3adcf8fSFrançois Tigeot } 558e3adcf8fSFrançois Tigeot 559e3adcf8fSFrançois Tigeot static int init_render_ring(struct intel_ring_buffer *ring) 560e3adcf8fSFrançois Tigeot { 561e3adcf8fSFrançois Tigeot struct drm_device *dev = ring->dev; 562e3adcf8fSFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 563e3adcf8fSFrançois Tigeot int ret = init_ring_common(ring); 564e3adcf8fSFrançois Tigeot 565f4e1c372SFrançois Tigeot if (INTEL_INFO(dev)->gen > 3) 566f4e1c372SFrançois Tigeot I915_WRITE(MI_MODE, _MASKED_BIT_ENABLE(VS_TIMER_DISPATCH)); 567f4e1c372SFrançois Tigeot 568f4e1c372SFrançois Tigeot /* We need to disable the AsyncFlip performance optimisations in order 569f4e1c372SFrançois Tigeot * to use MI_WAIT_FOR_EVENT within the CS. It should already be 570f4e1c372SFrançois Tigeot * programmed to '1' on all products. 5715d0b1887SFrançois Tigeot * 5725d0b1887SFrançois Tigeot * WaDisableAsyncFlipPerfMode:snb,ivb,hsw,vlv 573f4e1c372SFrançois Tigeot */ 574f4e1c372SFrançois Tigeot if (INTEL_INFO(dev)->gen >= 6) 575f4e1c372SFrançois Tigeot I915_WRITE(MI_MODE, _MASKED_BIT_ENABLE(ASYNC_FLIP_PERF_DISABLE)); 576f4e1c372SFrançois Tigeot 577f4e1c372SFrançois Tigeot /* Required for the hardware to program scanline values for waiting */ 578f4e1c372SFrançois Tigeot if (INTEL_INFO(dev)->gen == 6) 579f4e1c372SFrançois Tigeot I915_WRITE(GFX_MODE, 580f4e1c372SFrançois Tigeot _MASKED_BIT_ENABLE(GFX_TLB_INVALIDATE_ALWAYS)); 581f4e1c372SFrançois Tigeot 582e3adcf8fSFrançois Tigeot if (IS_GEN7(dev)) 583e3adcf8fSFrançois Tigeot I915_WRITE(GFX_MODE_GEN7, 584f4e1c372SFrançois Tigeot _MASKED_BIT_DISABLE(GFX_TLB_INVALIDATE_ALWAYS) | 585f4e1c372SFrançois Tigeot _MASKED_BIT_ENABLE(GFX_REPLAY_MODE)); 586e3adcf8fSFrançois Tigeot 587e3adcf8fSFrançois Tigeot if (INTEL_INFO(dev)->gen >= 5) { 588e3adcf8fSFrançois Tigeot ret = init_pipe_control(ring); 589e3adcf8fSFrançois Tigeot if (ret) 590e3adcf8fSFrançois Tigeot return ret; 591e3adcf8fSFrançois Tigeot } 592e3adcf8fSFrançois Tigeot 593e3adcf8fSFrançois Tigeot if (IS_GEN6(dev)) { 594e3adcf8fSFrançois Tigeot /* From the Sandybridge PRM, volume 1 part 3, page 24: 595e3adcf8fSFrançois Tigeot * "If this bit is set, STCunit will have LRA as replacement 596e3adcf8fSFrançois Tigeot * policy. [...] This bit must be reset. LRA replacement 597e3adcf8fSFrançois Tigeot * policy is not supported." 598e3adcf8fSFrançois Tigeot */ 599e3adcf8fSFrançois Tigeot I915_WRITE(CACHE_MODE_0, 600f4e1c372SFrançois Tigeot _MASKED_BIT_DISABLE(CM0_STC_EVICT_DISABLE_LRA_SNB)); 601686a02f1SFrançois Tigeot 602686a02f1SFrançois Tigeot /* This is not explicitly set for GEN6, so read the register. 603686a02f1SFrançois Tigeot * see intel_ring_mi_set_context() for why we care. 604686a02f1SFrançois Tigeot * TODO: consider explicitly setting the bit for GEN5 605686a02f1SFrançois Tigeot */ 606686a02f1SFrançois Tigeot ring->itlb_before_ctx_switch = 607686a02f1SFrançois Tigeot !!(I915_READ(GFX_MODE) & GFX_TLB_INVALIDATE_ALWAYS); 608e3adcf8fSFrançois Tigeot } 609e3adcf8fSFrançois Tigeot 610f4e1c372SFrançois Tigeot if (INTEL_INFO(dev)->gen >= 6) 611f4e1c372SFrançois Tigeot I915_WRITE(INSTPM, _MASKED_BIT_ENABLE(INSTPM_FORCE_ORDERING)); 612f4e1c372SFrançois Tigeot 613*9edbd4a0SFrançois Tigeot if (HAS_L3_DPF(dev)) 614*9edbd4a0SFrançois Tigeot I915_WRITE_IMR(ring, ~GT_PARITY_ERROR(dev)); 615e3adcf8fSFrançois Tigeot 616e3adcf8fSFrançois Tigeot return ret; 617e3adcf8fSFrançois Tigeot } 618e3adcf8fSFrançois Tigeot 619e3adcf8fSFrançois Tigeot static void render_ring_cleanup(struct intel_ring_buffer *ring) 620e3adcf8fSFrançois Tigeot { 621b5c29a34SFrançois Tigeot struct drm_device *dev = ring->dev; 622b5c29a34SFrançois Tigeot 623*9edbd4a0SFrançois Tigeot if (ring->scratch.obj == NULL) 624e3adcf8fSFrançois Tigeot return; 625e3adcf8fSFrançois Tigeot 626*9edbd4a0SFrançois Tigeot if (INTEL_INFO(dev)->gen >= 5) { 627*9edbd4a0SFrançois Tigeot kunmap(ring->scratch.obj->pages[0]); 628*9edbd4a0SFrançois Tigeot i915_gem_object_unpin(ring->scratch.obj); 629*9edbd4a0SFrançois Tigeot } 630b5c29a34SFrançois Tigeot 631*9edbd4a0SFrançois Tigeot drm_gem_object_unreference(&ring->scratch.obj->base); 632*9edbd4a0SFrançois Tigeot ring->scratch.obj = NULL; 633e3adcf8fSFrançois Tigeot } 634e3adcf8fSFrançois Tigeot 635e3adcf8fSFrançois Tigeot static void 636e3adcf8fSFrançois Tigeot update_mboxes(struct intel_ring_buffer *ring, 637e3adcf8fSFrançois Tigeot u32 mmio_offset) 638e3adcf8fSFrançois Tigeot { 6395d0b1887SFrançois Tigeot /* NB: In order to be able to do semaphore MBOX updates for varying number 6405d0b1887SFrançois Tigeot * of rings, it's easiest if we round up each individual update to a 6415d0b1887SFrançois Tigeot * multiple of 2 (since ring updates must always be a multiple of 2) 6425d0b1887SFrançois Tigeot * even though the actual update only requires 3 dwords. 6435d0b1887SFrançois Tigeot */ 6445d0b1887SFrançois Tigeot #define MBOX_UPDATE_DWORDS 4 645b5c29a34SFrançois Tigeot intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1)); 646e3adcf8fSFrançois Tigeot intel_ring_emit(ring, mmio_offset); 647*9edbd4a0SFrançois Tigeot intel_ring_emit(ring, ring->outstanding_lazy_seqno); 6485d0b1887SFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 649e3adcf8fSFrançois Tigeot } 650e3adcf8fSFrançois Tigeot 651e3adcf8fSFrançois Tigeot /** 652e3adcf8fSFrançois Tigeot * gen6_add_request - Update the semaphore mailbox registers 653e3adcf8fSFrançois Tigeot * 654e3adcf8fSFrançois Tigeot * @ring - ring that is adding a request 655e3adcf8fSFrançois Tigeot * @seqno - return seqno stuck into the ring 656e3adcf8fSFrançois Tigeot * 657e3adcf8fSFrançois Tigeot * Update the mailbox registers in the *other* rings with the current seqno. 658e3adcf8fSFrançois Tigeot * This acts like a signal in the canonical semaphore. 659e3adcf8fSFrançois Tigeot */ 660e3adcf8fSFrançois Tigeot static int 661b5c29a34SFrançois Tigeot gen6_add_request(struct intel_ring_buffer *ring) 662e3adcf8fSFrançois Tigeot { 6635d0b1887SFrançois Tigeot struct drm_device *dev = ring->dev; 6645d0b1887SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 6655d0b1887SFrançois Tigeot struct intel_ring_buffer *useless; 666*9edbd4a0SFrançois Tigeot int i, ret, num_dwords = 4; 667e3adcf8fSFrançois Tigeot 668*9edbd4a0SFrançois Tigeot if (i915_semaphore_is_enabled(dev)) 669*9edbd4a0SFrançois Tigeot num_dwords += ((I915_NUM_RINGS-1) * MBOX_UPDATE_DWORDS); 6705d0b1887SFrançois Tigeot #undef MBOX_UPDATE_DWORDS 671e3adcf8fSFrançois Tigeot 672*9edbd4a0SFrançois Tigeot ret = intel_ring_begin(ring, num_dwords); 673*9edbd4a0SFrançois Tigeot if (ret) 674*9edbd4a0SFrançois Tigeot return ret; 675*9edbd4a0SFrançois Tigeot 676*9edbd4a0SFrançois Tigeot if (i915_semaphore_is_enabled(dev)) { 6775d0b1887SFrançois Tigeot for_each_ring(useless, dev_priv, i) { 6785d0b1887SFrançois Tigeot u32 mbox_reg = ring->signal_mbox[i]; 6795d0b1887SFrançois Tigeot if (mbox_reg != GEN6_NOSYNC) 6805d0b1887SFrançois Tigeot update_mboxes(ring, mbox_reg); 6815d0b1887SFrançois Tigeot } 682*9edbd4a0SFrançois Tigeot } 683e3adcf8fSFrançois Tigeot 684e3adcf8fSFrançois Tigeot intel_ring_emit(ring, MI_STORE_DWORD_INDEX); 685e3adcf8fSFrançois Tigeot intel_ring_emit(ring, I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT); 686*9edbd4a0SFrançois Tigeot intel_ring_emit(ring, ring->outstanding_lazy_seqno); 687e3adcf8fSFrançois Tigeot intel_ring_emit(ring, MI_USER_INTERRUPT); 688*9edbd4a0SFrançois Tigeot __intel_ring_advance(ring); 689e3adcf8fSFrançois Tigeot 690e3adcf8fSFrançois Tigeot return 0; 691e3adcf8fSFrançois Tigeot } 692e3adcf8fSFrançois Tigeot 693a2fdbec6SFrançois Tigeot static inline bool i915_gem_has_seqno_wrapped(struct drm_device *dev, 694a2fdbec6SFrançois Tigeot u32 seqno) 695a2fdbec6SFrançois Tigeot { 696a2fdbec6SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 697a2fdbec6SFrançois Tigeot return dev_priv->last_seqno < seqno; 698a2fdbec6SFrançois Tigeot } 699a2fdbec6SFrançois Tigeot 700e3adcf8fSFrançois Tigeot /** 701e3adcf8fSFrançois Tigeot * intel_ring_sync - sync the waiter to the signaller on seqno 702e3adcf8fSFrançois Tigeot * 703e3adcf8fSFrançois Tigeot * @waiter - ring that is waiting 704e3adcf8fSFrançois Tigeot * @signaller - ring which has, or will signal 705e3adcf8fSFrançois Tigeot * @seqno - seqno which the waiter will block on 706e3adcf8fSFrançois Tigeot */ 707e3adcf8fSFrançois Tigeot static int 708686a02f1SFrançois Tigeot gen6_ring_sync(struct intel_ring_buffer *waiter, 709e3adcf8fSFrançois Tigeot struct intel_ring_buffer *signaller, 710e3adcf8fSFrançois Tigeot u32 seqno) 711e3adcf8fSFrançois Tigeot { 712e3adcf8fSFrançois Tigeot int ret; 713e3adcf8fSFrançois Tigeot u32 dw1 = MI_SEMAPHORE_MBOX | 714e3adcf8fSFrançois Tigeot MI_SEMAPHORE_COMPARE | 715e3adcf8fSFrançois Tigeot MI_SEMAPHORE_REGISTER; 716e3adcf8fSFrançois Tigeot 717686a02f1SFrançois Tigeot /* Throughout all of the GEM code, seqno passed implies our current 718686a02f1SFrançois Tigeot * seqno is >= the last seqno executed. However for hardware the 719686a02f1SFrançois Tigeot * comparison is strictly greater than. 720686a02f1SFrançois Tigeot */ 721686a02f1SFrançois Tigeot seqno -= 1; 722686a02f1SFrançois Tigeot 723686a02f1SFrançois Tigeot WARN_ON(signaller->semaphore_register[waiter->id] == 724686a02f1SFrançois Tigeot MI_SEMAPHORE_SYNC_INVALID); 725686a02f1SFrançois Tigeot 726e3adcf8fSFrançois Tigeot ret = intel_ring_begin(waiter, 4); 727e3adcf8fSFrançois Tigeot if (ret) 728e3adcf8fSFrançois Tigeot return ret; 729e3adcf8fSFrançois Tigeot 730a2fdbec6SFrançois Tigeot /* If seqno wrap happened, omit the wait with no-ops */ 731a2fdbec6SFrançois Tigeot if (likely(!i915_gem_has_seqno_wrapped(waiter->dev, seqno))) { 732686a02f1SFrançois Tigeot intel_ring_emit(waiter, 733a2fdbec6SFrançois Tigeot dw1 | 734a2fdbec6SFrançois Tigeot signaller->semaphore_register[waiter->id]); 735e3adcf8fSFrançois Tigeot intel_ring_emit(waiter, seqno); 736e3adcf8fSFrançois Tigeot intel_ring_emit(waiter, 0); 737e3adcf8fSFrançois Tigeot intel_ring_emit(waiter, MI_NOOP); 738a2fdbec6SFrançois Tigeot } else { 739a2fdbec6SFrançois Tigeot intel_ring_emit(waiter, MI_NOOP); 740a2fdbec6SFrançois Tigeot intel_ring_emit(waiter, MI_NOOP); 741a2fdbec6SFrançois Tigeot intel_ring_emit(waiter, MI_NOOP); 742a2fdbec6SFrançois Tigeot intel_ring_emit(waiter, MI_NOOP); 743a2fdbec6SFrançois Tigeot } 744e3adcf8fSFrançois Tigeot intel_ring_advance(waiter); 745e3adcf8fSFrançois Tigeot 746e3adcf8fSFrançois Tigeot return 0; 747e3adcf8fSFrançois Tigeot } 748e3adcf8fSFrançois Tigeot 749e3adcf8fSFrançois Tigeot #define PIPE_CONTROL_FLUSH(ring__, addr__) \ 750e3adcf8fSFrançois Tigeot do { \ 751e3adcf8fSFrançois Tigeot intel_ring_emit(ring__, GFX_OP_PIPE_CONTROL(4) | PIPE_CONTROL_QW_WRITE | \ 752e3adcf8fSFrançois Tigeot PIPE_CONTROL_DEPTH_STALL); \ 753e3adcf8fSFrançois Tigeot intel_ring_emit(ring__, (addr__) | PIPE_CONTROL_GLOBAL_GTT); \ 754e3adcf8fSFrançois Tigeot intel_ring_emit(ring__, 0); \ 755e3adcf8fSFrançois Tigeot intel_ring_emit(ring__, 0); \ 756e3adcf8fSFrançois Tigeot } while (0) 757e3adcf8fSFrançois Tigeot 758e3adcf8fSFrançois Tigeot static int 759b5c29a34SFrançois Tigeot pc_render_add_request(struct intel_ring_buffer *ring) 760e3adcf8fSFrançois Tigeot { 761*9edbd4a0SFrançois Tigeot u32 scratch_addr = ring->scratch.gtt_offset + 128; 762e3adcf8fSFrançois Tigeot int ret; 763e3adcf8fSFrançois Tigeot 764e3adcf8fSFrançois Tigeot /* For Ironlake, MI_USER_INTERRUPT was deprecated and apparently 765e3adcf8fSFrançois Tigeot * incoherent with writes to memory, i.e. completely fubar, 766e3adcf8fSFrançois Tigeot * so we need to use PIPE_NOTIFY instead. 767e3adcf8fSFrançois Tigeot * 768e3adcf8fSFrançois Tigeot * However, we also need to workaround the qword write 769e3adcf8fSFrançois Tigeot * incoherence by flushing the 6 PIPE_NOTIFY buffers out to 770e3adcf8fSFrançois Tigeot * memory before requesting an interrupt. 771e3adcf8fSFrançois Tigeot */ 772e3adcf8fSFrançois Tigeot ret = intel_ring_begin(ring, 32); 773e3adcf8fSFrançois Tigeot if (ret) 774e3adcf8fSFrançois Tigeot return ret; 775e3adcf8fSFrançois Tigeot 776e3adcf8fSFrançois Tigeot intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(4) | PIPE_CONTROL_QW_WRITE | 777e3adcf8fSFrançois Tigeot PIPE_CONTROL_WRITE_FLUSH | 778e3adcf8fSFrançois Tigeot PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE); 779*9edbd4a0SFrançois Tigeot intel_ring_emit(ring, ring->scratch.gtt_offset | PIPE_CONTROL_GLOBAL_GTT); 780*9edbd4a0SFrançois Tigeot intel_ring_emit(ring, ring->outstanding_lazy_seqno); 781e3adcf8fSFrançois Tigeot intel_ring_emit(ring, 0); 782e3adcf8fSFrançois Tigeot PIPE_CONTROL_FLUSH(ring, scratch_addr); 783e3adcf8fSFrançois Tigeot scratch_addr += 128; /* write to separate cachelines */ 784e3adcf8fSFrançois Tigeot PIPE_CONTROL_FLUSH(ring, scratch_addr); 785e3adcf8fSFrançois Tigeot scratch_addr += 128; 786e3adcf8fSFrançois Tigeot PIPE_CONTROL_FLUSH(ring, scratch_addr); 787e3adcf8fSFrançois Tigeot scratch_addr += 128; 788e3adcf8fSFrançois Tigeot PIPE_CONTROL_FLUSH(ring, scratch_addr); 789e3adcf8fSFrançois Tigeot scratch_addr += 128; 790e3adcf8fSFrançois Tigeot PIPE_CONTROL_FLUSH(ring, scratch_addr); 791e3adcf8fSFrançois Tigeot scratch_addr += 128; 792e3adcf8fSFrançois Tigeot PIPE_CONTROL_FLUSH(ring, scratch_addr); 793b5c29a34SFrançois Tigeot 794e3adcf8fSFrançois Tigeot intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(4) | PIPE_CONTROL_QW_WRITE | 795e3adcf8fSFrançois Tigeot PIPE_CONTROL_WRITE_FLUSH | 796e3adcf8fSFrançois Tigeot PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE | 797e3adcf8fSFrançois Tigeot PIPE_CONTROL_NOTIFY); 798*9edbd4a0SFrançois Tigeot intel_ring_emit(ring, ring->scratch.gtt_offset | PIPE_CONTROL_GLOBAL_GTT); 799*9edbd4a0SFrançois Tigeot intel_ring_emit(ring, ring->outstanding_lazy_seqno); 800e3adcf8fSFrançois Tigeot intel_ring_emit(ring, 0); 801*9edbd4a0SFrançois Tigeot __intel_ring_advance(ring); 802e3adcf8fSFrançois Tigeot 803e3adcf8fSFrançois Tigeot return 0; 804e3adcf8fSFrançois Tigeot } 805e3adcf8fSFrançois Tigeot 806e3adcf8fSFrançois Tigeot static u32 807b030f26bSFrançois Tigeot gen6_ring_get_seqno(struct intel_ring_buffer *ring, bool lazy_coherency) 808e3adcf8fSFrançois Tigeot { 809e3adcf8fSFrançois Tigeot /* Workaround to force correct ordering between irq and seqno writes on 810e3adcf8fSFrançois Tigeot * ivb (and maybe also on snb) by reading from a CS register (like 811e3adcf8fSFrançois Tigeot * ACTHD) before reading the status page. */ 812b030f26bSFrançois Tigeot if (!lazy_coherency) 813e3adcf8fSFrançois Tigeot intel_ring_get_active_head(ring); 814e3adcf8fSFrançois Tigeot return intel_read_status_page(ring, I915_GEM_HWS_INDEX); 815e3adcf8fSFrançois Tigeot } 816e3adcf8fSFrançois Tigeot 817b030f26bSFrançois Tigeot static u32 818b030f26bSFrançois Tigeot ring_get_seqno(struct intel_ring_buffer *ring, bool lazy_coherency) 819e3adcf8fSFrançois Tigeot { 820e3adcf8fSFrançois Tigeot return intel_read_status_page(ring, I915_GEM_HWS_INDEX); 821e3adcf8fSFrançois Tigeot } 822e3adcf8fSFrançois Tigeot 823a2fdbec6SFrançois Tigeot static void 824a2fdbec6SFrançois Tigeot ring_set_seqno(struct intel_ring_buffer *ring, u32 seqno) 825a2fdbec6SFrançois Tigeot { 826a2fdbec6SFrançois Tigeot intel_write_status_page(ring, I915_GEM_HWS_INDEX, seqno); 827a2fdbec6SFrançois Tigeot } 828a2fdbec6SFrançois Tigeot 829b030f26bSFrançois Tigeot static u32 830b030f26bSFrançois Tigeot pc_render_get_seqno(struct intel_ring_buffer *ring, bool lazy_coherency) 831e3adcf8fSFrançois Tigeot { 832*9edbd4a0SFrançois Tigeot return ring->scratch.cpu_page[0]; 833e3adcf8fSFrançois Tigeot } 834e3adcf8fSFrançois Tigeot 835a2fdbec6SFrançois Tigeot static void 836a2fdbec6SFrançois Tigeot pc_render_set_seqno(struct intel_ring_buffer *ring, u32 seqno) 837a2fdbec6SFrançois Tigeot { 838*9edbd4a0SFrançois Tigeot ring->scratch.cpu_page[0] = seqno; 839a2fdbec6SFrançois Tigeot } 840a2fdbec6SFrançois Tigeot 841e3adcf8fSFrançois Tigeot static bool 842686a02f1SFrançois Tigeot gen5_ring_get_irq(struct intel_ring_buffer *ring) 843e3adcf8fSFrançois Tigeot { 844e3adcf8fSFrançois Tigeot struct drm_device *dev = ring->dev; 845e3adcf8fSFrançois Tigeot drm_i915_private_t *dev_priv = dev->dev_private; 846e3adcf8fSFrançois Tigeot 847e3adcf8fSFrançois Tigeot if (!dev->irq_enabled) 848e3adcf8fSFrançois Tigeot return false; 849e3adcf8fSFrançois Tigeot 85002727ecdSFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_EXCLUSIVE); 851*9edbd4a0SFrançois Tigeot if (ring->irq_refcount++ == 0) 852*9edbd4a0SFrançois Tigeot ilk_enable_gt_irq(dev_priv, ring->irq_enable_mask); 85302727ecdSFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_RELEASE); 854e3adcf8fSFrançois Tigeot 855e3adcf8fSFrançois Tigeot return true; 856e3adcf8fSFrançois Tigeot } 857e3adcf8fSFrançois Tigeot 858e3adcf8fSFrançois Tigeot static void 859686a02f1SFrançois Tigeot gen5_ring_put_irq(struct intel_ring_buffer *ring) 860e3adcf8fSFrançois Tigeot { 861e3adcf8fSFrançois Tigeot struct drm_device *dev = ring->dev; 862e3adcf8fSFrançois Tigeot drm_i915_private_t *dev_priv = dev->dev_private; 863e3adcf8fSFrançois Tigeot 86402727ecdSFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_EXCLUSIVE); 865*9edbd4a0SFrançois Tigeot if (--ring->irq_refcount == 0) 866*9edbd4a0SFrançois Tigeot ilk_disable_gt_irq(dev_priv, ring->irq_enable_mask); 867686a02f1SFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_RELEASE); 868686a02f1SFrançois Tigeot } 869686a02f1SFrançois Tigeot 870686a02f1SFrançois Tigeot static bool 871686a02f1SFrançois Tigeot i9xx_ring_get_irq(struct intel_ring_buffer *ring) 872686a02f1SFrançois Tigeot { 873686a02f1SFrançois Tigeot struct drm_device *dev = ring->dev; 874686a02f1SFrançois Tigeot drm_i915_private_t *dev_priv = dev->dev_private; 875686a02f1SFrançois Tigeot 876686a02f1SFrançois Tigeot if (!dev->irq_enabled) 877686a02f1SFrançois Tigeot return false; 878686a02f1SFrançois Tigeot 879686a02f1SFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_EXCLUSIVE); 880*9edbd4a0SFrançois Tigeot if (ring->irq_refcount++ == 0) { 881686a02f1SFrançois Tigeot dev_priv->irq_mask &= ~ring->irq_enable_mask; 882686a02f1SFrançois Tigeot I915_WRITE(IMR, dev_priv->irq_mask); 883686a02f1SFrançois Tigeot POSTING_READ(IMR); 884686a02f1SFrançois Tigeot } 885686a02f1SFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_RELEASE); 886686a02f1SFrançois Tigeot 887686a02f1SFrançois Tigeot return true; 888686a02f1SFrançois Tigeot } 889686a02f1SFrançois Tigeot 890686a02f1SFrançois Tigeot static void 891686a02f1SFrançois Tigeot i9xx_ring_put_irq(struct intel_ring_buffer *ring) 892686a02f1SFrançois Tigeot { 893686a02f1SFrançois Tigeot struct drm_device *dev = ring->dev; 894686a02f1SFrançois Tigeot drm_i915_private_t *dev_priv = dev->dev_private; 895686a02f1SFrançois Tigeot 896686a02f1SFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_EXCLUSIVE); 897*9edbd4a0SFrançois Tigeot if (--ring->irq_refcount == 0) { 898686a02f1SFrançois Tigeot dev_priv->irq_mask |= ring->irq_enable_mask; 899686a02f1SFrançois Tigeot I915_WRITE(IMR, dev_priv->irq_mask); 900686a02f1SFrançois Tigeot POSTING_READ(IMR); 901686a02f1SFrançois Tigeot } 902686a02f1SFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_RELEASE); 903686a02f1SFrançois Tigeot } 904686a02f1SFrançois Tigeot 905686a02f1SFrançois Tigeot static bool 906686a02f1SFrançois Tigeot i8xx_ring_get_irq(struct intel_ring_buffer *ring) 907686a02f1SFrançois Tigeot { 908686a02f1SFrançois Tigeot struct drm_device *dev = ring->dev; 909686a02f1SFrançois Tigeot drm_i915_private_t *dev_priv = dev->dev_private; 910686a02f1SFrançois Tigeot 911686a02f1SFrançois Tigeot if (!dev->irq_enabled) 912686a02f1SFrançois Tigeot return false; 913686a02f1SFrançois Tigeot 914686a02f1SFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_EXCLUSIVE); 915*9edbd4a0SFrançois Tigeot if (ring->irq_refcount++ == 0) { 916686a02f1SFrançois Tigeot dev_priv->irq_mask &= ~ring->irq_enable_mask; 917686a02f1SFrançois Tigeot I915_WRITE16(IMR, dev_priv->irq_mask); 918686a02f1SFrançois Tigeot POSTING_READ16(IMR); 919686a02f1SFrançois Tigeot } 920686a02f1SFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_RELEASE); 921686a02f1SFrançois Tigeot 922686a02f1SFrançois Tigeot return true; 923686a02f1SFrançois Tigeot } 924686a02f1SFrançois Tigeot 925686a02f1SFrançois Tigeot static void 926686a02f1SFrançois Tigeot i8xx_ring_put_irq(struct intel_ring_buffer *ring) 927686a02f1SFrançois Tigeot { 928686a02f1SFrançois Tigeot struct drm_device *dev = ring->dev; 929686a02f1SFrançois Tigeot drm_i915_private_t *dev_priv = dev->dev_private; 930686a02f1SFrançois Tigeot 931686a02f1SFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_EXCLUSIVE); 932*9edbd4a0SFrançois Tigeot if (--ring->irq_refcount == 0) { 933686a02f1SFrançois Tigeot dev_priv->irq_mask |= ring->irq_enable_mask; 934686a02f1SFrançois Tigeot I915_WRITE16(IMR, dev_priv->irq_mask); 935686a02f1SFrançois Tigeot POSTING_READ16(IMR); 936e3adcf8fSFrançois Tigeot } 93702727ecdSFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_RELEASE); 938e3adcf8fSFrançois Tigeot } 939e3adcf8fSFrançois Tigeot 940e3adcf8fSFrançois Tigeot void intel_ring_setup_status_page(struct intel_ring_buffer *ring) 941e3adcf8fSFrançois Tigeot { 942e3adcf8fSFrançois Tigeot struct drm_device *dev = ring->dev; 943b5c29a34SFrançois Tigeot drm_i915_private_t *dev_priv = ring->dev->dev_private; 944b5c29a34SFrançois Tigeot u32 mmio = 0; 945e3adcf8fSFrançois Tigeot 946e3adcf8fSFrançois Tigeot /* The ring status page addresses are no longer next to the rest of 947e3adcf8fSFrançois Tigeot * the ring registers as of gen7. 948e3adcf8fSFrançois Tigeot */ 949e3adcf8fSFrançois Tigeot if (IS_GEN7(dev)) { 950e3adcf8fSFrançois Tigeot switch (ring->id) { 951e3adcf8fSFrançois Tigeot case RCS: 952e3adcf8fSFrançois Tigeot mmio = RENDER_HWS_PGA_GEN7; 953e3adcf8fSFrançois Tigeot break; 954e3adcf8fSFrançois Tigeot case BCS: 955e3adcf8fSFrançois Tigeot mmio = BLT_HWS_PGA_GEN7; 956e3adcf8fSFrançois Tigeot break; 957e3adcf8fSFrançois Tigeot case VCS: 958e3adcf8fSFrançois Tigeot mmio = BSD_HWS_PGA_GEN7; 959e3adcf8fSFrançois Tigeot break; 9605d0b1887SFrançois Tigeot case VECS: 9615d0b1887SFrançois Tigeot mmio = VEBOX_HWS_PGA_GEN7; 9625d0b1887SFrançois Tigeot break; 963e3adcf8fSFrançois Tigeot } 964b5c29a34SFrançois Tigeot } else if (IS_GEN6(ring->dev)) { 965e3adcf8fSFrançois Tigeot mmio = RING_HWS_PGA_GEN6(ring->mmio_base); 966e3adcf8fSFrançois Tigeot } else { 967*9edbd4a0SFrançois Tigeot /* XXX: gen8 returns to sanity */ 968e3adcf8fSFrançois Tigeot mmio = RING_HWS_PGA(ring->mmio_base); 969e3adcf8fSFrançois Tigeot } 970e3adcf8fSFrançois Tigeot 971e3adcf8fSFrançois Tigeot I915_WRITE(mmio, (u32)ring->status_page.gfx_addr); 972e3adcf8fSFrançois Tigeot POSTING_READ(mmio); 9735d0b1887SFrançois Tigeot 9745d0b1887SFrançois Tigeot /* Flush the TLB for this page */ 9755d0b1887SFrançois Tigeot if (INTEL_INFO(dev)->gen >= 6) { 9765d0b1887SFrançois Tigeot u32 reg = RING_INSTPM(ring->mmio_base); 9775d0b1887SFrançois Tigeot I915_WRITE(reg, 9785d0b1887SFrançois Tigeot _MASKED_BIT_ENABLE(INSTPM_TLB_INVALIDATE | 9795d0b1887SFrançois Tigeot INSTPM_SYNC_FLUSH)); 9805d0b1887SFrançois Tigeot if (wait_for((I915_READ(reg) & INSTPM_SYNC_FLUSH) == 0, 9815d0b1887SFrançois Tigeot 1000)) 9825d0b1887SFrançois Tigeot DRM_ERROR("%s: wait for SyncFlush to complete for TLB invalidation timed out\n", 9835d0b1887SFrançois Tigeot ring->name); 9845d0b1887SFrançois Tigeot } 985e3adcf8fSFrançois Tigeot } 986e3adcf8fSFrançois Tigeot 987e3adcf8fSFrançois Tigeot static int 988e3adcf8fSFrançois Tigeot bsd_ring_flush(struct intel_ring_buffer *ring, 989b5c29a34SFrançois Tigeot u32 invalidate_domains, 990b5c29a34SFrançois Tigeot u32 flush_domains) 991e3adcf8fSFrançois Tigeot { 992e3adcf8fSFrançois Tigeot int ret; 993e3adcf8fSFrançois Tigeot 994e3adcf8fSFrançois Tigeot ret = intel_ring_begin(ring, 2); 995e3adcf8fSFrançois Tigeot if (ret) 996e3adcf8fSFrançois Tigeot return ret; 997e3adcf8fSFrançois Tigeot 998e3adcf8fSFrançois Tigeot intel_ring_emit(ring, MI_FLUSH); 999e3adcf8fSFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 1000e3adcf8fSFrançois Tigeot intel_ring_advance(ring); 1001e3adcf8fSFrançois Tigeot return 0; 1002e3adcf8fSFrançois Tigeot } 1003e3adcf8fSFrançois Tigeot 1004e3adcf8fSFrançois Tigeot static int 1005b5c29a34SFrançois Tigeot i9xx_add_request(struct intel_ring_buffer *ring) 1006e3adcf8fSFrançois Tigeot { 1007e3adcf8fSFrançois Tigeot int ret; 1008e3adcf8fSFrançois Tigeot 1009e3adcf8fSFrançois Tigeot ret = intel_ring_begin(ring, 4); 1010e3adcf8fSFrançois Tigeot if (ret) 1011e3adcf8fSFrançois Tigeot return ret; 1012e3adcf8fSFrançois Tigeot 1013e3adcf8fSFrançois Tigeot intel_ring_emit(ring, MI_STORE_DWORD_INDEX); 1014e3adcf8fSFrançois Tigeot intel_ring_emit(ring, I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT); 1015*9edbd4a0SFrançois Tigeot intel_ring_emit(ring, ring->outstanding_lazy_seqno); 1016e3adcf8fSFrançois Tigeot intel_ring_emit(ring, MI_USER_INTERRUPT); 1017*9edbd4a0SFrançois Tigeot __intel_ring_advance(ring); 1018e3adcf8fSFrançois Tigeot 1019e3adcf8fSFrançois Tigeot return 0; 1020e3adcf8fSFrançois Tigeot } 1021e3adcf8fSFrançois Tigeot 1022e3adcf8fSFrançois Tigeot static bool 1023686a02f1SFrançois Tigeot gen6_ring_get_irq(struct intel_ring_buffer *ring) 1024e3adcf8fSFrançois Tigeot { 1025e3adcf8fSFrançois Tigeot struct drm_device *dev = ring->dev; 1026e3adcf8fSFrançois Tigeot drm_i915_private_t *dev_priv = dev->dev_private; 1027e3adcf8fSFrançois Tigeot 1028e3adcf8fSFrançois Tigeot if (!dev->irq_enabled) 1029e3adcf8fSFrançois Tigeot return false; 1030e3adcf8fSFrançois Tigeot 103102727ecdSFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_EXCLUSIVE); 1032*9edbd4a0SFrançois Tigeot if (ring->irq_refcount++ == 0) { 1033*9edbd4a0SFrançois Tigeot if (HAS_L3_DPF(dev) && ring->id == RCS) 10345d0b1887SFrançois Tigeot I915_WRITE_IMR(ring, 10355d0b1887SFrançois Tigeot ~(ring->irq_enable_mask | 1036*9edbd4a0SFrançois Tigeot GT_PARITY_ERROR(dev))); 1037686a02f1SFrançois Tigeot else 1038686a02f1SFrançois Tigeot I915_WRITE_IMR(ring, ~ring->irq_enable_mask); 1039*9edbd4a0SFrançois Tigeot ilk_enable_gt_irq(dev_priv, ring->irq_enable_mask); 1040e3adcf8fSFrançois Tigeot } 104102727ecdSFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_RELEASE); 1042e3adcf8fSFrançois Tigeot 1043e3adcf8fSFrançois Tigeot return true; 1044e3adcf8fSFrançois Tigeot } 1045e3adcf8fSFrançois Tigeot 1046e3adcf8fSFrançois Tigeot static void 1047686a02f1SFrançois Tigeot gen6_ring_put_irq(struct intel_ring_buffer *ring) 1048e3adcf8fSFrançois Tigeot { 1049e3adcf8fSFrançois Tigeot struct drm_device *dev = ring->dev; 1050e3adcf8fSFrançois Tigeot drm_i915_private_t *dev_priv = dev->dev_private; 1051e3adcf8fSFrançois Tigeot 105202727ecdSFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_EXCLUSIVE); 1053*9edbd4a0SFrançois Tigeot if (--ring->irq_refcount == 0) { 1054*9edbd4a0SFrançois Tigeot if (HAS_L3_DPF(dev) && ring->id == RCS) 1055*9edbd4a0SFrançois Tigeot I915_WRITE_IMR(ring, ~GT_PARITY_ERROR(dev)); 1056686a02f1SFrançois Tigeot else 1057686a02f1SFrançois Tigeot I915_WRITE_IMR(ring, ~0); 1058*9edbd4a0SFrançois Tigeot ilk_disable_gt_irq(dev_priv, ring->irq_enable_mask); 1059e3adcf8fSFrançois Tigeot } 106002727ecdSFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_RELEASE); 1061e3adcf8fSFrançois Tigeot } 1062e3adcf8fSFrançois Tigeot 10635d0b1887SFrançois Tigeot static bool 10645d0b1887SFrançois Tigeot hsw_vebox_get_irq(struct intel_ring_buffer *ring) 10655d0b1887SFrançois Tigeot { 10665d0b1887SFrançois Tigeot struct drm_device *dev = ring->dev; 10675d0b1887SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 10685d0b1887SFrançois Tigeot 10695d0b1887SFrançois Tigeot if (!dev->irq_enabled) 10705d0b1887SFrançois Tigeot return false; 10715d0b1887SFrançois Tigeot 1072*9edbd4a0SFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_EXCLUSIVE); 1073*9edbd4a0SFrançois Tigeot if (ring->irq_refcount++ == 0) { 10745d0b1887SFrançois Tigeot I915_WRITE_IMR(ring, ~ring->irq_enable_mask); 1075*9edbd4a0SFrançois Tigeot snb_enable_pm_irq(dev_priv, ring->irq_enable_mask); 10765d0b1887SFrançois Tigeot } 1077*9edbd4a0SFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_RELEASE); 10785d0b1887SFrançois Tigeot 10795d0b1887SFrançois Tigeot return true; 10805d0b1887SFrançois Tigeot } 10815d0b1887SFrançois Tigeot 10825d0b1887SFrançois Tigeot static void 10835d0b1887SFrançois Tigeot hsw_vebox_put_irq(struct intel_ring_buffer *ring) 10845d0b1887SFrançois Tigeot { 10855d0b1887SFrançois Tigeot struct drm_device *dev = ring->dev; 10865d0b1887SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 10875d0b1887SFrançois Tigeot 10885d0b1887SFrançois Tigeot if (!dev->irq_enabled) 10895d0b1887SFrançois Tigeot return; 10905d0b1887SFrançois Tigeot 1091*9edbd4a0SFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_EXCLUSIVE); 1092*9edbd4a0SFrançois Tigeot if (--ring->irq_refcount == 0) { 10935d0b1887SFrançois Tigeot I915_WRITE_IMR(ring, ~0); 1094*9edbd4a0SFrançois Tigeot snb_disable_pm_irq(dev_priv, ring->irq_enable_mask); 10955d0b1887SFrançois Tigeot } 1096*9edbd4a0SFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_RELEASE); 1097*9edbd4a0SFrançois Tigeot } 1098*9edbd4a0SFrançois Tigeot 1099*9edbd4a0SFrançois Tigeot static bool 1100*9edbd4a0SFrançois Tigeot gen8_ring_get_irq(struct intel_ring_buffer *ring) 1101*9edbd4a0SFrançois Tigeot { 1102*9edbd4a0SFrançois Tigeot struct drm_device *dev = ring->dev; 1103*9edbd4a0SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 1104*9edbd4a0SFrançois Tigeot 1105*9edbd4a0SFrançois Tigeot if (!dev->irq_enabled) 1106*9edbd4a0SFrançois Tigeot return false; 1107*9edbd4a0SFrançois Tigeot 1108*9edbd4a0SFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_EXCLUSIVE); 1109*9edbd4a0SFrançois Tigeot if (ring->irq_refcount++ == 0) { 1110*9edbd4a0SFrançois Tigeot if (HAS_L3_DPF(dev) && ring->id == RCS) { 1111*9edbd4a0SFrançois Tigeot I915_WRITE_IMR(ring, 1112*9edbd4a0SFrançois Tigeot ~(ring->irq_enable_mask | 1113*9edbd4a0SFrançois Tigeot GT_RENDER_L3_PARITY_ERROR_INTERRUPT)); 1114*9edbd4a0SFrançois Tigeot } else { 1115*9edbd4a0SFrançois Tigeot I915_WRITE_IMR(ring, ~ring->irq_enable_mask); 1116*9edbd4a0SFrançois Tigeot } 1117*9edbd4a0SFrançois Tigeot POSTING_READ(RING_IMR(ring->mmio_base)); 1118*9edbd4a0SFrançois Tigeot } 1119*9edbd4a0SFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_RELEASE); 1120*9edbd4a0SFrançois Tigeot 1121*9edbd4a0SFrançois Tigeot return true; 1122*9edbd4a0SFrançois Tigeot } 1123*9edbd4a0SFrançois Tigeot 1124*9edbd4a0SFrançois Tigeot static void 1125*9edbd4a0SFrançois Tigeot gen8_ring_put_irq(struct intel_ring_buffer *ring) 1126*9edbd4a0SFrançois Tigeot { 1127*9edbd4a0SFrançois Tigeot struct drm_device *dev = ring->dev; 1128*9edbd4a0SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 1129*9edbd4a0SFrançois Tigeot 1130*9edbd4a0SFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_EXCLUSIVE); 1131*9edbd4a0SFrançois Tigeot if (--ring->irq_refcount == 0) { 1132*9edbd4a0SFrançois Tigeot if (HAS_L3_DPF(dev) && ring->id == RCS) { 1133*9edbd4a0SFrançois Tigeot I915_WRITE_IMR(ring, 1134*9edbd4a0SFrançois Tigeot ~GT_RENDER_L3_PARITY_ERROR_INTERRUPT); 1135*9edbd4a0SFrançois Tigeot } else { 1136*9edbd4a0SFrançois Tigeot I915_WRITE_IMR(ring, ~0); 1137*9edbd4a0SFrançois Tigeot } 1138*9edbd4a0SFrançois Tigeot POSTING_READ(RING_IMR(ring->mmio_base)); 1139*9edbd4a0SFrançois Tigeot } 1140*9edbd4a0SFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_RELEASE); 11415d0b1887SFrançois Tigeot } 11425d0b1887SFrançois Tigeot 1143e3adcf8fSFrançois Tigeot static int 1144b5c29a34SFrançois Tigeot i965_dispatch_execbuffer(struct intel_ring_buffer *ring, 1145b5c29a34SFrançois Tigeot u32 offset, u32 length, 1146b5c29a34SFrançois Tigeot unsigned flags) 1147e3adcf8fSFrançois Tigeot { 1148e3adcf8fSFrançois Tigeot int ret; 1149e3adcf8fSFrançois Tigeot 1150e3adcf8fSFrançois Tigeot ret = intel_ring_begin(ring, 2); 1151e3adcf8fSFrançois Tigeot if (ret) 1152e3adcf8fSFrançois Tigeot return ret; 1153e3adcf8fSFrançois Tigeot 1154e3adcf8fSFrançois Tigeot intel_ring_emit(ring, 1155686a02f1SFrançois Tigeot MI_BATCH_BUFFER_START | 1156b5c29a34SFrançois Tigeot MI_BATCH_GTT | 1157b5c29a34SFrançois Tigeot (flags & I915_DISPATCH_SECURE ? 0 : MI_BATCH_NON_SECURE_I965)); 1158e3adcf8fSFrançois Tigeot intel_ring_emit(ring, offset); 1159e3adcf8fSFrançois Tigeot intel_ring_advance(ring); 1160e3adcf8fSFrançois Tigeot 1161e3adcf8fSFrançois Tigeot return 0; 1162e3adcf8fSFrançois Tigeot } 1163e3adcf8fSFrançois Tigeot 1164b5c29a34SFrançois Tigeot /* Just userspace ABI convention to limit the wa batch bo to a resonable size */ 1165b5c29a34SFrançois Tigeot #define I830_BATCH_LIMIT (256*1024) 1166e3adcf8fSFrançois Tigeot static int 1167686a02f1SFrançois Tigeot i830_dispatch_execbuffer(struct intel_ring_buffer *ring, 1168b5c29a34SFrançois Tigeot u32 offset, u32 len, 1169b5c29a34SFrançois Tigeot unsigned flags) 1170e3adcf8fSFrançois Tigeot { 1171e3adcf8fSFrançois Tigeot int ret; 1172e3adcf8fSFrançois Tigeot 1173b5c29a34SFrançois Tigeot if (flags & I915_DISPATCH_PINNED) { 1174e3adcf8fSFrançois Tigeot ret = intel_ring_begin(ring, 4); 1175e3adcf8fSFrançois Tigeot if (ret) 1176e3adcf8fSFrançois Tigeot return ret; 1177e3adcf8fSFrançois Tigeot 1178e3adcf8fSFrançois Tigeot intel_ring_emit(ring, MI_BATCH_BUFFER); 1179b5c29a34SFrançois Tigeot intel_ring_emit(ring, offset | (flags & I915_DISPATCH_SECURE ? 0 : MI_BATCH_NON_SECURE)); 1180e3adcf8fSFrançois Tigeot intel_ring_emit(ring, offset + len - 8); 1181b5c29a34SFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 1182686a02f1SFrançois Tigeot intel_ring_advance(ring); 1183b5c29a34SFrançois Tigeot } else { 1184*9edbd4a0SFrançois Tigeot u32 cs_offset = ring->scratch.gtt_offset; 1185b5c29a34SFrançois Tigeot 1186b5c29a34SFrançois Tigeot if (len > I830_BATCH_LIMIT) 1187b5c29a34SFrançois Tigeot return -ENOSPC; 1188b5c29a34SFrançois Tigeot 1189b5c29a34SFrançois Tigeot ret = intel_ring_begin(ring, 9+3); 1190b5c29a34SFrançois Tigeot if (ret) 1191b5c29a34SFrançois Tigeot return ret; 1192b5c29a34SFrançois Tigeot /* Blit the batch (which has now all relocs applied) to the stable batch 1193b5c29a34SFrançois Tigeot * scratch bo area (so that the CS never stumbles over its tlb 1194b5c29a34SFrançois Tigeot * invalidation bug) ... */ 1195b5c29a34SFrançois Tigeot intel_ring_emit(ring, XY_SRC_COPY_BLT_CMD | 1196b5c29a34SFrançois Tigeot XY_SRC_COPY_BLT_WRITE_ALPHA | 1197b5c29a34SFrançois Tigeot XY_SRC_COPY_BLT_WRITE_RGB); 1198b5c29a34SFrançois Tigeot intel_ring_emit(ring, BLT_DEPTH_32 | BLT_ROP_GXCOPY | 4096); 1199b5c29a34SFrançois Tigeot intel_ring_emit(ring, 0); 1200b5c29a34SFrançois Tigeot intel_ring_emit(ring, (DIV_ROUND_UP(len, 4096) << 16) | 1024); 1201b5c29a34SFrançois Tigeot intel_ring_emit(ring, cs_offset); 1202b5c29a34SFrançois Tigeot intel_ring_emit(ring, 0); 1203b5c29a34SFrançois Tigeot intel_ring_emit(ring, 4096); 1204b5c29a34SFrançois Tigeot intel_ring_emit(ring, offset); 1205b5c29a34SFrançois Tigeot intel_ring_emit(ring, MI_FLUSH); 1206b5c29a34SFrançois Tigeot 1207b5c29a34SFrançois Tigeot /* ... and execute it. */ 1208b5c29a34SFrançois Tigeot intel_ring_emit(ring, MI_BATCH_BUFFER); 1209b5c29a34SFrançois Tigeot intel_ring_emit(ring, cs_offset | (flags & I915_DISPATCH_SECURE ? 0 : MI_BATCH_NON_SECURE)); 1210b5c29a34SFrançois Tigeot intel_ring_emit(ring, cs_offset + len - 8); 1211b5c29a34SFrançois Tigeot intel_ring_advance(ring); 1212b5c29a34SFrançois Tigeot } 1213686a02f1SFrançois Tigeot 1214686a02f1SFrançois Tigeot return 0; 1215686a02f1SFrançois Tigeot } 1216686a02f1SFrançois Tigeot 1217686a02f1SFrançois Tigeot static int 1218686a02f1SFrançois Tigeot i915_dispatch_execbuffer(struct intel_ring_buffer *ring, 1219b5c29a34SFrançois Tigeot u32 offset, u32 len, 1220b5c29a34SFrançois Tigeot unsigned flags) 1221686a02f1SFrançois Tigeot { 1222686a02f1SFrançois Tigeot int ret; 1223686a02f1SFrançois Tigeot 1224e3adcf8fSFrançois Tigeot ret = intel_ring_begin(ring, 2); 1225e3adcf8fSFrançois Tigeot if (ret) 1226e3adcf8fSFrançois Tigeot return ret; 1227e3adcf8fSFrançois Tigeot 1228686a02f1SFrançois Tigeot intel_ring_emit(ring, MI_BATCH_BUFFER_START | MI_BATCH_GTT); 1229686a02f1SFrançois Tigeot intel_ring_emit(ring, offset | (flags & I915_DISPATCH_SECURE ? 0 : MI_BATCH_NON_SECURE)); 1230e3adcf8fSFrançois Tigeot intel_ring_advance(ring); 1231e3adcf8fSFrançois Tigeot 1232e3adcf8fSFrançois Tigeot return 0; 1233e3adcf8fSFrançois Tigeot } 1234e3adcf8fSFrançois Tigeot 1235e3adcf8fSFrançois Tigeot static void cleanup_status_page(struct intel_ring_buffer *ring) 1236e3adcf8fSFrançois Tigeot { 1237e3adcf8fSFrançois Tigeot struct drm_i915_gem_object *obj; 1238e3adcf8fSFrançois Tigeot 1239e3adcf8fSFrançois Tigeot obj = ring->status_page.obj; 1240e3adcf8fSFrançois Tigeot if (obj == NULL) 1241e3adcf8fSFrançois Tigeot return; 1242e3adcf8fSFrançois Tigeot 1243*9edbd4a0SFrançois Tigeot kunmap(obj->pages[0]); 1244e3adcf8fSFrançois Tigeot i915_gem_object_unpin(obj); 1245e3adcf8fSFrançois Tigeot drm_gem_object_unreference(&obj->base); 1246e3adcf8fSFrançois Tigeot ring->status_page.obj = NULL; 1247e3adcf8fSFrançois Tigeot } 1248e3adcf8fSFrançois Tigeot 1249e3adcf8fSFrançois Tigeot static int init_status_page(struct intel_ring_buffer *ring) 1250e3adcf8fSFrançois Tigeot { 1251e3adcf8fSFrançois Tigeot struct drm_device *dev = ring->dev; 1252e3adcf8fSFrançois Tigeot struct drm_i915_gem_object *obj; 1253e3adcf8fSFrançois Tigeot int ret; 1254e3adcf8fSFrançois Tigeot 1255e3adcf8fSFrançois Tigeot obj = i915_gem_alloc_object(dev, 4096); 1256e3adcf8fSFrançois Tigeot if (obj == NULL) { 1257e3adcf8fSFrançois Tigeot DRM_ERROR("Failed to allocate status page\n"); 1258e3adcf8fSFrançois Tigeot ret = -ENOMEM; 1259e3adcf8fSFrançois Tigeot goto err; 1260e3adcf8fSFrançois Tigeot } 1261e3adcf8fSFrançois Tigeot 1262e3adcf8fSFrançois Tigeot i915_gem_object_set_cache_level(obj, I915_CACHE_LLC); 1263e3adcf8fSFrançois Tigeot 1264*9edbd4a0SFrançois Tigeot ret = i915_gem_obj_ggtt_pin(obj, 4096, true, false); 1265e3adcf8fSFrançois Tigeot if (ret != 0) { 1266e3adcf8fSFrançois Tigeot goto err_unref; 1267e3adcf8fSFrançois Tigeot } 1268e3adcf8fSFrançois Tigeot 1269*9edbd4a0SFrançois Tigeot ring->status_page.gfx_addr = i915_gem_obj_ggtt_offset(obj); 1270f4f90b23SFrançois Tigeot ring->status_page.page_addr = kmap(obj->pages[0]); 1271e3adcf8fSFrançois Tigeot if (ring->status_page.page_addr == NULL) { 1272686a02f1SFrançois Tigeot ret = -ENOMEM; 1273e3adcf8fSFrançois Tigeot goto err_unpin; 1274e3adcf8fSFrançois Tigeot } 1275e3adcf8fSFrançois Tigeot ring->status_page.obj = obj; 1276e3adcf8fSFrançois Tigeot memset(ring->status_page.page_addr, 0, PAGE_SIZE); 1277e3adcf8fSFrançois Tigeot 1278b5c29a34SFrançois Tigeot DRM_DEBUG_DRIVER("%s hws offset: 0x%08x\n", 1279e3adcf8fSFrançois Tigeot ring->name, ring->status_page.gfx_addr); 1280e3adcf8fSFrançois Tigeot 1281e3adcf8fSFrançois Tigeot return 0; 1282e3adcf8fSFrançois Tigeot 1283e3adcf8fSFrançois Tigeot err_unpin: 1284e3adcf8fSFrançois Tigeot i915_gem_object_unpin(obj); 1285e3adcf8fSFrançois Tigeot err_unref: 1286e3adcf8fSFrançois Tigeot drm_gem_object_unreference(&obj->base); 1287e3adcf8fSFrançois Tigeot err: 1288e3adcf8fSFrançois Tigeot return ret; 1289e3adcf8fSFrançois Tigeot } 1290e3adcf8fSFrançois Tigeot 12915d0b1887SFrançois Tigeot static int init_phys_status_page(struct intel_ring_buffer *ring) 1292686a02f1SFrançois Tigeot { 1293686a02f1SFrançois Tigeot struct drm_i915_private *dev_priv = ring->dev->dev_private; 1294686a02f1SFrançois Tigeot 1295686a02f1SFrançois Tigeot if (!dev_priv->status_page_dmah) { 1296686a02f1SFrançois Tigeot dev_priv->status_page_dmah = 1297b31e9d59SFrançois Tigeot drm_pci_alloc(ring->dev, PAGE_SIZE, PAGE_SIZE); 1298686a02f1SFrançois Tigeot if (!dev_priv->status_page_dmah) 1299686a02f1SFrançois Tigeot return -ENOMEM; 1300686a02f1SFrançois Tigeot } 1301686a02f1SFrançois Tigeot 1302686a02f1SFrançois Tigeot ring->status_page.page_addr = dev_priv->status_page_dmah->vaddr; 1303686a02f1SFrançois Tigeot memset(ring->status_page.page_addr, 0, PAGE_SIZE); 1304686a02f1SFrançois Tigeot 1305686a02f1SFrançois Tigeot return 0; 1306686a02f1SFrançois Tigeot } 1307686a02f1SFrançois Tigeot 1308b030f26bSFrançois Tigeot static int intel_init_ring_buffer(struct drm_device *dev, 1309e3adcf8fSFrançois Tigeot struct intel_ring_buffer *ring) 1310e3adcf8fSFrançois Tigeot { 1311e3adcf8fSFrançois Tigeot struct drm_i915_gem_object *obj; 1312e3adcf8fSFrançois Tigeot int ret; 1313e3adcf8fSFrançois Tigeot 1314e3adcf8fSFrançois Tigeot ring->dev = dev; 1315e3adcf8fSFrançois Tigeot INIT_LIST_HEAD(&ring->active_list); 1316e3adcf8fSFrançois Tigeot INIT_LIST_HEAD(&ring->request_list); 1317686a02f1SFrançois Tigeot ring->size = 32 * PAGE_SIZE; 1318686a02f1SFrançois Tigeot memset(ring->sync_seqno, 0, sizeof(ring->sync_seqno)); 1319e3adcf8fSFrançois Tigeot 1320b030f26bSFrançois Tigeot init_waitqueue_head(&ring->irq_queue); 1321b030f26bSFrançois Tigeot 1322e3adcf8fSFrançois Tigeot if (I915_NEED_GFX_HWS(dev)) { 1323e3adcf8fSFrançois Tigeot ret = init_status_page(ring); 1324e3adcf8fSFrançois Tigeot if (ret) 1325e3adcf8fSFrançois Tigeot return ret; 1326686a02f1SFrançois Tigeot } else { 1327686a02f1SFrançois Tigeot BUG_ON(ring->id != RCS); 13285d0b1887SFrançois Tigeot ret = init_phys_status_page(ring); 1329686a02f1SFrançois Tigeot if (ret) 1330686a02f1SFrançois Tigeot return ret; 1331e3adcf8fSFrançois Tigeot } 1332e3adcf8fSFrançois Tigeot 1333a2fdbec6SFrançois Tigeot obj = NULL; 1334a2fdbec6SFrançois Tigeot if (!HAS_LLC(dev)) 1335*9edbd4a0SFrançois Tigeot obj = i915_gem_object_create_stolen(dev, ring->size); 1336a2fdbec6SFrançois Tigeot if (obj == NULL) 1337e3adcf8fSFrançois Tigeot obj = i915_gem_alloc_object(dev, ring->size); 1338e3adcf8fSFrançois Tigeot if (obj == NULL) { 1339e3adcf8fSFrançois Tigeot DRM_ERROR("Failed to allocate ringbuffer\n"); 1340e3adcf8fSFrançois Tigeot ret = -ENOMEM; 1341e3adcf8fSFrançois Tigeot goto err_hws; 1342e3adcf8fSFrançois Tigeot } 1343e3adcf8fSFrançois Tigeot 1344e3adcf8fSFrançois Tigeot ring->obj = obj; 1345e3adcf8fSFrançois Tigeot 1346*9edbd4a0SFrançois Tigeot ret = i915_gem_obj_ggtt_pin(obj, PAGE_SIZE, true, false); 1347e3adcf8fSFrançois Tigeot if (ret) 1348e3adcf8fSFrançois Tigeot goto err_unref; 1349e3adcf8fSFrançois Tigeot 1350686a02f1SFrançois Tigeot ret = i915_gem_object_set_to_gtt_domain(obj, true); 1351686a02f1SFrançois Tigeot if (ret) 1352686a02f1SFrançois Tigeot goto err_unpin; 1353e3adcf8fSFrançois Tigeot 1354a2fdbec6SFrançois Tigeot ring->virtual_start = 1355*9edbd4a0SFrançois Tigeot ioremap_wc(dev->agp->base + i915_gem_obj_ggtt_offset(obj), 1356686a02f1SFrançois Tigeot ring->size); 1357686a02f1SFrançois Tigeot if (ring->virtual_start == NULL) { 1358e3adcf8fSFrançois Tigeot DRM_ERROR("Failed to map ringbuffer.\n"); 1359e3adcf8fSFrançois Tigeot ret = -EINVAL; 1360e3adcf8fSFrançois Tigeot goto err_unpin; 1361e3adcf8fSFrançois Tigeot } 1362e3adcf8fSFrançois Tigeot 1363e3adcf8fSFrançois Tigeot ret = ring->init(ring); 1364e3adcf8fSFrançois Tigeot if (ret) 1365e3adcf8fSFrançois Tigeot goto err_unmap; 1366e3adcf8fSFrançois Tigeot 1367e3adcf8fSFrançois Tigeot /* Workaround an erratum on the i830 which causes a hang if 1368e3adcf8fSFrançois Tigeot * the TAIL pointer points to within the last 2 cachelines 1369e3adcf8fSFrançois Tigeot * of the buffer. 1370e3adcf8fSFrançois Tigeot */ 1371e3adcf8fSFrançois Tigeot ring->effective_size = ring->size; 1372e3adcf8fSFrançois Tigeot if (IS_I830(ring->dev) || IS_845G(ring->dev)) 1373e3adcf8fSFrançois Tigeot ring->effective_size -= 128; 1374e3adcf8fSFrançois Tigeot 1375e3adcf8fSFrançois Tigeot return 0; 1376e3adcf8fSFrançois Tigeot 1377e3adcf8fSFrançois Tigeot err_unmap: 1378686a02f1SFrançois Tigeot pmap_unmapdev((vm_offset_t)ring->virtual_start, ring->size); 1379e3adcf8fSFrançois Tigeot err_unpin: 1380e3adcf8fSFrançois Tigeot i915_gem_object_unpin(obj); 1381e3adcf8fSFrançois Tigeot err_unref: 1382e3adcf8fSFrançois Tigeot drm_gem_object_unreference(&obj->base); 1383e3adcf8fSFrançois Tigeot ring->obj = NULL; 1384e3adcf8fSFrançois Tigeot err_hws: 1385e3adcf8fSFrançois Tigeot cleanup_status_page(ring); 1386e3adcf8fSFrançois Tigeot return ret; 1387e3adcf8fSFrançois Tigeot } 1388e3adcf8fSFrançois Tigeot 1389e3adcf8fSFrançois Tigeot void intel_cleanup_ring_buffer(struct intel_ring_buffer *ring) 1390e3adcf8fSFrançois Tigeot { 1391e3adcf8fSFrançois Tigeot struct drm_i915_private *dev_priv; 1392e3adcf8fSFrançois Tigeot int ret; 1393e3adcf8fSFrançois Tigeot 1394e3adcf8fSFrançois Tigeot if (ring->obj == NULL) 1395e3adcf8fSFrançois Tigeot return; 1396e3adcf8fSFrançois Tigeot 1397e3adcf8fSFrançois Tigeot /* Disable the ring buffer. The ring must be idle at this point */ 1398e3adcf8fSFrançois Tigeot dev_priv = ring->dev->dev_private; 1399b030f26bSFrançois Tigeot ret = intel_ring_idle(ring); 1400*9edbd4a0SFrançois Tigeot if (ret && !i915_reset_in_progress(&dev_priv->gpu_error)) 1401b030f26bSFrançois Tigeot DRM_ERROR("failed to quiesce %s whilst cleaning up: %d\n", 1402b030f26bSFrançois Tigeot ring->name, ret); 1403b030f26bSFrançois Tigeot 1404e3adcf8fSFrançois Tigeot I915_WRITE_CTL(ring, 0); 1405e3adcf8fSFrançois Tigeot 1406686a02f1SFrançois Tigeot pmap_unmapdev((vm_offset_t)ring->virtual_start, ring->size); 1407e3adcf8fSFrançois Tigeot 1408e3adcf8fSFrançois Tigeot i915_gem_object_unpin(ring->obj); 1409e3adcf8fSFrançois Tigeot drm_gem_object_unreference(&ring->obj->base); 1410e3adcf8fSFrançois Tigeot ring->obj = NULL; 1411*9edbd4a0SFrançois Tigeot ring->preallocated_lazy_request = NULL; 1412*9edbd4a0SFrançois Tigeot ring->outstanding_lazy_seqno = 0; 1413e3adcf8fSFrançois Tigeot 1414e3adcf8fSFrançois Tigeot if (ring->cleanup) 1415e3adcf8fSFrançois Tigeot ring->cleanup(ring); 1416e3adcf8fSFrançois Tigeot 1417e3adcf8fSFrançois Tigeot cleanup_status_page(ring); 1418e3adcf8fSFrançois Tigeot } 1419e3adcf8fSFrançois Tigeot 1420e3adcf8fSFrançois Tigeot static int intel_ring_wait_seqno(struct intel_ring_buffer *ring, u32 seqno) 1421e3adcf8fSFrançois Tigeot { 1422e3adcf8fSFrançois Tigeot int ret; 1423e3adcf8fSFrançois Tigeot 1424b030f26bSFrançois Tigeot ret = i915_wait_seqno(ring, seqno); 1425b030f26bSFrançois Tigeot if (!ret) 1426b030f26bSFrançois Tigeot i915_gem_retire_requests_ring(ring); 1427e3adcf8fSFrançois Tigeot 1428e3adcf8fSFrançois Tigeot return ret; 1429e3adcf8fSFrançois Tigeot } 1430e3adcf8fSFrançois Tigeot 1431e3adcf8fSFrançois Tigeot static int intel_ring_wait_request(struct intel_ring_buffer *ring, int n) 1432e3adcf8fSFrançois Tigeot { 1433e3adcf8fSFrançois Tigeot struct drm_i915_gem_request *request; 1434e3adcf8fSFrançois Tigeot u32 seqno = 0; 1435e3adcf8fSFrançois Tigeot int ret; 1436e3adcf8fSFrançois Tigeot 1437e3adcf8fSFrançois Tigeot i915_gem_retire_requests_ring(ring); 1438e3adcf8fSFrançois Tigeot 1439e3adcf8fSFrançois Tigeot if (ring->last_retired_head != -1) { 1440e3adcf8fSFrançois Tigeot ring->head = ring->last_retired_head; 1441e3adcf8fSFrançois Tigeot ring->last_retired_head = -1; 1442e3adcf8fSFrançois Tigeot ring->space = ring_space(ring); 1443e3adcf8fSFrançois Tigeot if (ring->space >= n) 1444e3adcf8fSFrançois Tigeot return 0; 1445e3adcf8fSFrançois Tigeot } 1446e3adcf8fSFrançois Tigeot 1447e3adcf8fSFrançois Tigeot list_for_each_entry(request, &ring->request_list, list) { 1448e3adcf8fSFrançois Tigeot int space; 1449e3adcf8fSFrançois Tigeot 1450e3adcf8fSFrançois Tigeot if (request->tail == -1) 1451e3adcf8fSFrançois Tigeot continue; 1452e3adcf8fSFrançois Tigeot 1453b5c29a34SFrançois Tigeot space = request->tail - (ring->tail + I915_RING_FREE_SPACE); 1454e3adcf8fSFrançois Tigeot if (space < 0) 1455e3adcf8fSFrançois Tigeot space += ring->size; 1456e3adcf8fSFrançois Tigeot if (space >= n) { 1457e3adcf8fSFrançois Tigeot seqno = request->seqno; 1458e3adcf8fSFrançois Tigeot break; 1459e3adcf8fSFrançois Tigeot } 1460e3adcf8fSFrançois Tigeot 1461e3adcf8fSFrançois Tigeot /* Consume this request in case we need more space than 1462e3adcf8fSFrançois Tigeot * is available and so need to prevent a race between 1463e3adcf8fSFrançois Tigeot * updating last_retired_head and direct reads of 1464e3adcf8fSFrançois Tigeot * I915_RING_HEAD. It also provides a nice sanity check. 1465e3adcf8fSFrançois Tigeot */ 1466e3adcf8fSFrançois Tigeot request->tail = -1; 1467e3adcf8fSFrançois Tigeot } 1468e3adcf8fSFrançois Tigeot 1469e3adcf8fSFrançois Tigeot if (seqno == 0) 1470e3adcf8fSFrançois Tigeot return -ENOSPC; 1471e3adcf8fSFrançois Tigeot 1472e3adcf8fSFrançois Tigeot ret = intel_ring_wait_seqno(ring, seqno); 1473e3adcf8fSFrançois Tigeot if (ret) 1474e3adcf8fSFrançois Tigeot return ret; 1475e3adcf8fSFrançois Tigeot 1476b5c29a34SFrançois Tigeot if (WARN_ON(ring->last_retired_head == -1)) 1477e3adcf8fSFrançois Tigeot return -ENOSPC; 1478e3adcf8fSFrançois Tigeot 1479e3adcf8fSFrançois Tigeot ring->head = ring->last_retired_head; 1480e3adcf8fSFrançois Tigeot ring->last_retired_head = -1; 1481e3adcf8fSFrançois Tigeot ring->space = ring_space(ring); 1482b5c29a34SFrançois Tigeot if (WARN_ON(ring->space < n)) 1483e3adcf8fSFrançois Tigeot return -ENOSPC; 1484e3adcf8fSFrançois Tigeot 1485e3adcf8fSFrançois Tigeot return 0; 1486e3adcf8fSFrançois Tigeot } 1487e3adcf8fSFrançois Tigeot 1488b030f26bSFrançois Tigeot static int ring_wait_for_space(struct intel_ring_buffer *ring, int n) 1489e3adcf8fSFrançois Tigeot { 1490e3adcf8fSFrançois Tigeot struct drm_device *dev = ring->dev; 1491e3adcf8fSFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 1492245593daSFrançois Tigeot unsigned long end; 1493e3adcf8fSFrançois Tigeot int ret; 1494e3adcf8fSFrançois Tigeot 1495e3adcf8fSFrançois Tigeot ret = intel_ring_wait_request(ring, n); 1496e3adcf8fSFrançois Tigeot if (ret != -ENOSPC) 1497e3adcf8fSFrançois Tigeot return ret; 1498e3adcf8fSFrançois Tigeot 1499*9edbd4a0SFrançois Tigeot /* force the tail write in case we have been skipping them */ 1500*9edbd4a0SFrançois Tigeot __intel_ring_advance(ring); 1501*9edbd4a0SFrançois Tigeot 1502a2fdbec6SFrançois Tigeot trace_i915_ring_wait_begin(ring); 1503e3adcf8fSFrançois Tigeot /* With GEM the hangcheck timer should kick us out of the loop, 1504e3adcf8fSFrançois Tigeot * leaving it early runs the risk of corrupting GEM state (due 1505e3adcf8fSFrançois Tigeot * to running on almost untested codepaths). But on resume 1506e3adcf8fSFrançois Tigeot * timers don't work yet, so prevent a complete hang in that 1507e3adcf8fSFrançois Tigeot * case by choosing an insanely large timeout. */ 1508e3440f96SFrançois Tigeot end = jiffies + 60 * HZ; 1509245593daSFrançois Tigeot 1510e3adcf8fSFrançois Tigeot do { 1511e3adcf8fSFrançois Tigeot ring->head = I915_READ_HEAD(ring); 1512e3adcf8fSFrançois Tigeot ring->space = ring_space(ring); 1513e3adcf8fSFrançois Tigeot if (ring->space >= n) { 1514a2fdbec6SFrançois Tigeot trace_i915_ring_wait_end(ring); 1515e3adcf8fSFrançois Tigeot return 0; 1516e3adcf8fSFrançois Tigeot } 1517e3adcf8fSFrançois Tigeot 1518e3adcf8fSFrançois Tigeot #if 0 1519e3adcf8fSFrançois Tigeot if (dev->primary->master) { 1520e3adcf8fSFrançois Tigeot struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv; 1521e3adcf8fSFrançois Tigeot if (master_priv->sarea_priv) 1522e3adcf8fSFrançois Tigeot master_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT; 1523e3adcf8fSFrançois Tigeot } 1524e3adcf8fSFrançois Tigeot #else 1525e3adcf8fSFrançois Tigeot if (dev_priv->sarea_priv) 1526e3adcf8fSFrançois Tigeot dev_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT; 1527e3adcf8fSFrançois Tigeot #endif 1528e3adcf8fSFrançois Tigeot 1529e3440f96SFrançois Tigeot msleep(1); 1530245593daSFrançois Tigeot 1531a2fdbec6SFrançois Tigeot ret = i915_gem_check_wedge(&dev_priv->gpu_error, 1532a2fdbec6SFrançois Tigeot dev_priv->mm.interruptible); 1533245593daSFrançois Tigeot if (ret) 1534245593daSFrançois Tigeot return ret; 1535e3440f96SFrançois Tigeot } while (!time_after(jiffies, end)); 1536a2fdbec6SFrançois Tigeot trace_i915_ring_wait_end(ring); 1537e3adcf8fSFrançois Tigeot return -EBUSY; 1538e3adcf8fSFrançois Tigeot } 1539e3adcf8fSFrançois Tigeot 1540b030f26bSFrançois Tigeot static int intel_wrap_ring_buffer(struct intel_ring_buffer *ring) 1541b030f26bSFrançois Tigeot { 1542b030f26bSFrançois Tigeot uint32_t __iomem *virt; 1543b030f26bSFrançois Tigeot int rem = ring->size - ring->tail; 1544b030f26bSFrançois Tigeot 1545b030f26bSFrançois Tigeot if (ring->space < rem) { 1546b030f26bSFrançois Tigeot int ret = ring_wait_for_space(ring, rem); 1547b030f26bSFrançois Tigeot if (ret) 1548b030f26bSFrançois Tigeot return ret; 1549b030f26bSFrançois Tigeot } 1550b030f26bSFrançois Tigeot 1551b030f26bSFrançois Tigeot virt = (unsigned int *)((char *)ring->virtual_start + ring->tail); 1552b030f26bSFrançois Tigeot rem /= 4; 1553b030f26bSFrançois Tigeot while (rem--) 1554686a02f1SFrançois Tigeot iowrite32(MI_NOOP, virt++); 1555b030f26bSFrançois Tigeot 1556b030f26bSFrançois Tigeot ring->tail = 0; 1557b030f26bSFrançois Tigeot ring->space = ring_space(ring); 1558b030f26bSFrançois Tigeot 1559b030f26bSFrançois Tigeot return 0; 1560b030f26bSFrançois Tigeot } 1561b030f26bSFrançois Tigeot 1562b030f26bSFrançois Tigeot int intel_ring_idle(struct intel_ring_buffer *ring) 1563b030f26bSFrançois Tigeot { 1564b5c29a34SFrançois Tigeot u32 seqno; 1565b5c29a34SFrançois Tigeot int ret; 1566b5c29a34SFrançois Tigeot 1567b5c29a34SFrançois Tigeot /* We need to add any requests required to flush the objects and ring */ 1568*9edbd4a0SFrançois Tigeot if (ring->outstanding_lazy_seqno) { 15695d0b1887SFrançois Tigeot ret = i915_add_request(ring, NULL); 1570b5c29a34SFrançois Tigeot if (ret) 1571b5c29a34SFrançois Tigeot return ret; 1572b5c29a34SFrançois Tigeot } 1573b5c29a34SFrançois Tigeot 1574b5c29a34SFrançois Tigeot /* Wait upon the last request to be completed */ 1575b5c29a34SFrançois Tigeot if (list_empty(&ring->request_list)) 1576b5c29a34SFrançois Tigeot return 0; 1577b5c29a34SFrançois Tigeot 1578b5c29a34SFrançois Tigeot seqno = list_entry(ring->request_list.prev, 1579b5c29a34SFrançois Tigeot struct drm_i915_gem_request, 1580b5c29a34SFrançois Tigeot list)->seqno; 1581b5c29a34SFrançois Tigeot 1582b5c29a34SFrançois Tigeot return i915_wait_seqno(ring, seqno); 1583b5c29a34SFrançois Tigeot } 1584b5c29a34SFrançois Tigeot 1585b5c29a34SFrançois Tigeot static int 1586b5c29a34SFrançois Tigeot intel_ring_alloc_seqno(struct intel_ring_buffer *ring) 1587b5c29a34SFrançois Tigeot { 1588*9edbd4a0SFrançois Tigeot if (ring->outstanding_lazy_seqno) 1589b5c29a34SFrançois Tigeot return 0; 1590b5c29a34SFrançois Tigeot 1591*9edbd4a0SFrançois Tigeot if (ring->preallocated_lazy_request == NULL) { 1592*9edbd4a0SFrançois Tigeot struct drm_i915_gem_request *request; 1593*9edbd4a0SFrançois Tigeot 1594*9edbd4a0SFrançois Tigeot request = kmalloc(sizeof(*request), M_DRM, M_WAITOK); 1595*9edbd4a0SFrançois Tigeot if (request == NULL) 1596*9edbd4a0SFrançois Tigeot return -ENOMEM; 1597*9edbd4a0SFrançois Tigeot 1598*9edbd4a0SFrançois Tigeot ring->preallocated_lazy_request = request; 1599b030f26bSFrançois Tigeot } 1600b030f26bSFrançois Tigeot 1601*9edbd4a0SFrançois Tigeot return i915_gem_get_seqno(ring->dev, &ring->outstanding_lazy_seqno); 1602*9edbd4a0SFrançois Tigeot } 1603*9edbd4a0SFrançois Tigeot 1604*9edbd4a0SFrançois Tigeot static int __intel_ring_prepare(struct intel_ring_buffer *ring, 1605a2fdbec6SFrançois Tigeot int bytes) 1606a2fdbec6SFrançois Tigeot { 1607a2fdbec6SFrançois Tigeot int ret; 1608a2fdbec6SFrançois Tigeot 1609a2fdbec6SFrançois Tigeot if (unlikely(ring->tail + bytes > ring->effective_size)) { 1610a2fdbec6SFrançois Tigeot ret = intel_wrap_ring_buffer(ring); 1611a2fdbec6SFrançois Tigeot if (unlikely(ret)) 1612a2fdbec6SFrançois Tigeot return ret; 1613a2fdbec6SFrançois Tigeot } 1614a2fdbec6SFrançois Tigeot 1615a2fdbec6SFrançois Tigeot if (unlikely(ring->space < bytes)) { 1616a2fdbec6SFrançois Tigeot ret = ring_wait_for_space(ring, bytes); 1617a2fdbec6SFrançois Tigeot if (unlikely(ret)) 1618a2fdbec6SFrançois Tigeot return ret; 1619a2fdbec6SFrançois Tigeot } 1620a2fdbec6SFrançois Tigeot 1621a2fdbec6SFrançois Tigeot return 0; 1622a2fdbec6SFrançois Tigeot } 1623a2fdbec6SFrançois Tigeot 1624e3adcf8fSFrançois Tigeot int intel_ring_begin(struct intel_ring_buffer *ring, 1625e3adcf8fSFrançois Tigeot int num_dwords) 1626e3adcf8fSFrançois Tigeot { 1627b5c29a34SFrançois Tigeot drm_i915_private_t *dev_priv = ring->dev->dev_private; 1628e3adcf8fSFrançois Tigeot int ret; 1629e3adcf8fSFrançois Tigeot 1630a2fdbec6SFrançois Tigeot ret = i915_gem_check_wedge(&dev_priv->gpu_error, 1631a2fdbec6SFrançois Tigeot dev_priv->mm.interruptible); 1632245593daSFrançois Tigeot if (ret) 1633245593daSFrançois Tigeot return ret; 1634e3adcf8fSFrançois Tigeot 1635*9edbd4a0SFrançois Tigeot ret = __intel_ring_prepare(ring, num_dwords * sizeof(uint32_t)); 1636*9edbd4a0SFrançois Tigeot if (ret) 1637*9edbd4a0SFrançois Tigeot return ret; 1638*9edbd4a0SFrançois Tigeot 1639b5c29a34SFrançois Tigeot /* Preallocate the olr before touching the ring */ 1640b5c29a34SFrançois Tigeot ret = intel_ring_alloc_seqno(ring); 1641b5c29a34SFrançois Tigeot if (ret) 1642b5c29a34SFrançois Tigeot return ret; 1643b5c29a34SFrançois Tigeot 1644*9edbd4a0SFrançois Tigeot ring->space -= num_dwords * sizeof(uint32_t); 1645*9edbd4a0SFrançois Tigeot return 0; 1646*9edbd4a0SFrançois Tigeot } 1647*9edbd4a0SFrançois Tigeot 1648*9edbd4a0SFrançois Tigeot /* Align the ring tail to a cacheline boundary */ 1649*9edbd4a0SFrançois Tigeot int intel_ring_cacheline_align(struct intel_ring_buffer *ring) 1650*9edbd4a0SFrançois Tigeot { 1651*9edbd4a0SFrançois Tigeot int num_dwords = (64 - (ring->tail & 63)) / sizeof(uint32_t); 1652*9edbd4a0SFrançois Tigeot int ret; 1653*9edbd4a0SFrançois Tigeot 1654*9edbd4a0SFrançois Tigeot if (num_dwords == 0) 1655*9edbd4a0SFrançois Tigeot return 0; 1656*9edbd4a0SFrançois Tigeot 1657*9edbd4a0SFrançois Tigeot ret = intel_ring_begin(ring, num_dwords); 1658*9edbd4a0SFrançois Tigeot if (ret) 1659*9edbd4a0SFrançois Tigeot return ret; 1660*9edbd4a0SFrançois Tigeot 1661*9edbd4a0SFrançois Tigeot while (num_dwords--) 1662*9edbd4a0SFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 1663*9edbd4a0SFrançois Tigeot 1664*9edbd4a0SFrançois Tigeot intel_ring_advance(ring); 1665*9edbd4a0SFrançois Tigeot 1666*9edbd4a0SFrançois Tigeot return 0; 1667e3adcf8fSFrançois Tigeot } 1668e3adcf8fSFrançois Tigeot 1669a2fdbec6SFrançois Tigeot void intel_ring_init_seqno(struct intel_ring_buffer *ring, u32 seqno) 1670a2fdbec6SFrançois Tigeot { 1671a2fdbec6SFrançois Tigeot struct drm_i915_private *dev_priv = ring->dev->dev_private; 1672a2fdbec6SFrançois Tigeot 1673*9edbd4a0SFrançois Tigeot BUG_ON(ring->outstanding_lazy_seqno); 1674a2fdbec6SFrançois Tigeot 1675a2fdbec6SFrançois Tigeot if (INTEL_INFO(ring->dev)->gen >= 6) { 1676a2fdbec6SFrançois Tigeot I915_WRITE(RING_SYNC_0(ring->mmio_base), 0); 1677a2fdbec6SFrançois Tigeot I915_WRITE(RING_SYNC_1(ring->mmio_base), 0); 1678*9edbd4a0SFrançois Tigeot if (HAS_VEBOX(ring->dev)) 1679*9edbd4a0SFrançois Tigeot I915_WRITE(RING_SYNC_2(ring->mmio_base), 0); 1680e3adcf8fSFrançois Tigeot } 1681e3adcf8fSFrançois Tigeot 1682a2fdbec6SFrançois Tigeot ring->set_seqno(ring, seqno); 16835d0b1887SFrançois Tigeot ring->hangcheck.seqno = seqno; 1684e3adcf8fSFrançois Tigeot } 1685e3adcf8fSFrançois Tigeot 1686e3adcf8fSFrançois Tigeot static void gen6_bsd_ring_write_tail(struct intel_ring_buffer *ring, 1687f4e1c372SFrançois Tigeot u32 value) 1688e3adcf8fSFrançois Tigeot { 1689e3adcf8fSFrançois Tigeot drm_i915_private_t *dev_priv = ring->dev->dev_private; 1690e3adcf8fSFrançois Tigeot 1691e3adcf8fSFrançois Tigeot /* Every tail move must follow the sequence below */ 1692f4e1c372SFrançois Tigeot 1693f4e1c372SFrançois Tigeot /* Disable notification that the ring is IDLE. The GT 1694f4e1c372SFrançois Tigeot * will then assume that it is busy and bring it out of rc6. 1695f4e1c372SFrançois Tigeot */ 1696e3adcf8fSFrançois Tigeot I915_WRITE(GEN6_BSD_SLEEP_PSMI_CONTROL, 1697f4e1c372SFrançois Tigeot _MASKED_BIT_ENABLE(GEN6_BSD_SLEEP_MSG_DISABLE)); 1698e3adcf8fSFrançois Tigeot 1699f4e1c372SFrançois Tigeot /* Clear the context id. Here be magic! */ 1700f4e1c372SFrançois Tigeot I915_WRITE64(GEN6_BSD_RNCID, 0x0); 1701e3adcf8fSFrançois Tigeot 1702f4e1c372SFrançois Tigeot /* Wait for the ring not to be idle, i.e. for it to wake up. */ 1703f4e1c372SFrançois Tigeot if (wait_for((I915_READ(GEN6_BSD_SLEEP_PSMI_CONTROL) & 1704f4e1c372SFrançois Tigeot GEN6_BSD_SLEEP_INDICATOR) == 0, 1705f4e1c372SFrançois Tigeot 50)) 1706f4e1c372SFrançois Tigeot DRM_ERROR("timed out waiting for the BSD ring to wake up\n"); 1707f4e1c372SFrançois Tigeot 1708f4e1c372SFrançois Tigeot /* Now that the ring is fully powered up, update the tail */ 1709e3adcf8fSFrançois Tigeot I915_WRITE_TAIL(ring, value); 1710f4e1c372SFrançois Tigeot POSTING_READ(RING_TAIL(ring->mmio_base)); 1711f4e1c372SFrançois Tigeot 1712f4e1c372SFrançois Tigeot /* Let the ring send IDLE messages to the GT again, 1713f4e1c372SFrançois Tigeot * and so let it sleep to conserve power when idle. 1714f4e1c372SFrançois Tigeot */ 1715e3adcf8fSFrançois Tigeot I915_WRITE(GEN6_BSD_SLEEP_PSMI_CONTROL, 1716f4e1c372SFrançois Tigeot _MASKED_BIT_DISABLE(GEN6_BSD_SLEEP_MSG_DISABLE)); 1717e3adcf8fSFrançois Tigeot } 1718e3adcf8fSFrançois Tigeot 17195d0b1887SFrançois Tigeot static int gen6_bsd_ring_flush(struct intel_ring_buffer *ring, 1720b5c29a34SFrançois Tigeot u32 invalidate, u32 flush) 1721e3adcf8fSFrançois Tigeot { 1722e3adcf8fSFrançois Tigeot uint32_t cmd; 1723e3adcf8fSFrançois Tigeot int ret; 1724e3adcf8fSFrançois Tigeot 1725e3adcf8fSFrançois Tigeot ret = intel_ring_begin(ring, 4); 1726e3adcf8fSFrançois Tigeot if (ret) 1727e3adcf8fSFrançois Tigeot return ret; 1728e3adcf8fSFrançois Tigeot 1729e3adcf8fSFrançois Tigeot cmd = MI_FLUSH_DW; 1730*9edbd4a0SFrançois Tigeot if (INTEL_INFO(ring->dev)->gen >= 8) 1731*9edbd4a0SFrançois Tigeot cmd += 1; 1732b5c29a34SFrançois Tigeot /* 1733b5c29a34SFrançois Tigeot * Bspec vol 1c.5 - video engine command streamer: 1734b5c29a34SFrançois Tigeot * "If ENABLED, all TLBs will be invalidated once the flush 1735b5c29a34SFrançois Tigeot * operation is complete. This bit is only valid when the 1736b5c29a34SFrançois Tigeot * Post-Sync Operation field is a value of 1h or 3h." 1737b5c29a34SFrançois Tigeot */ 1738e3adcf8fSFrançois Tigeot if (invalidate & I915_GEM_GPU_DOMAINS) 1739b5c29a34SFrançois Tigeot cmd |= MI_INVALIDATE_TLB | MI_INVALIDATE_BSD | 1740b5c29a34SFrançois Tigeot MI_FLUSH_DW_STORE_INDEX | MI_FLUSH_DW_OP_STOREDW; 1741e3adcf8fSFrançois Tigeot intel_ring_emit(ring, cmd); 1742b5c29a34SFrançois Tigeot intel_ring_emit(ring, I915_GEM_HWS_SCRATCH_ADDR | MI_FLUSH_DW_USE_GTT); 1743*9edbd4a0SFrançois Tigeot if (INTEL_INFO(ring->dev)->gen >= 8) { 1744*9edbd4a0SFrançois Tigeot intel_ring_emit(ring, 0); /* upper addr */ 1745*9edbd4a0SFrançois Tigeot intel_ring_emit(ring, 0); /* value */ 1746*9edbd4a0SFrançois Tigeot } else { 1747*9edbd4a0SFrançois Tigeot intel_ring_emit(ring, 0); 1748*9edbd4a0SFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 1749*9edbd4a0SFrançois Tigeot } 1750*9edbd4a0SFrançois Tigeot intel_ring_advance(ring); 1751*9edbd4a0SFrançois Tigeot return 0; 1752*9edbd4a0SFrançois Tigeot } 1753*9edbd4a0SFrançois Tigeot 1754*9edbd4a0SFrançois Tigeot static int 1755*9edbd4a0SFrançois Tigeot gen8_ring_dispatch_execbuffer(struct intel_ring_buffer *ring, 1756*9edbd4a0SFrançois Tigeot u32 offset, u32 len, 1757*9edbd4a0SFrançois Tigeot unsigned flags) 1758*9edbd4a0SFrançois Tigeot { 1759*9edbd4a0SFrançois Tigeot struct drm_i915_private *dev_priv = ring->dev->dev_private; 1760*9edbd4a0SFrançois Tigeot bool ppgtt = dev_priv->mm.aliasing_ppgtt != NULL && 1761*9edbd4a0SFrançois Tigeot !(flags & I915_DISPATCH_SECURE); 1762*9edbd4a0SFrançois Tigeot int ret; 1763*9edbd4a0SFrançois Tigeot 1764*9edbd4a0SFrançois Tigeot ret = intel_ring_begin(ring, 4); 1765*9edbd4a0SFrançois Tigeot if (ret) 1766*9edbd4a0SFrançois Tigeot return ret; 1767*9edbd4a0SFrançois Tigeot 1768*9edbd4a0SFrançois Tigeot /* FIXME(BDW): Address space and security selectors. */ 1769*9edbd4a0SFrançois Tigeot intel_ring_emit(ring, MI_BATCH_BUFFER_START_GEN8 | (ppgtt<<8)); 1770*9edbd4a0SFrançois Tigeot intel_ring_emit(ring, offset); 1771e3adcf8fSFrançois Tigeot intel_ring_emit(ring, 0); 1772e3adcf8fSFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 1773e3adcf8fSFrançois Tigeot intel_ring_advance(ring); 1774*9edbd4a0SFrançois Tigeot 1775e3adcf8fSFrançois Tigeot return 0; 1776e3adcf8fSFrançois Tigeot } 1777e3adcf8fSFrançois Tigeot 1778e3adcf8fSFrançois Tigeot static int 1779b5c29a34SFrançois Tigeot hsw_ring_dispatch_execbuffer(struct intel_ring_buffer *ring, 1780b5c29a34SFrançois Tigeot u32 offset, u32 len, 1781b5c29a34SFrançois Tigeot unsigned flags) 1782e3adcf8fSFrançois Tigeot { 1783e3adcf8fSFrançois Tigeot int ret; 1784e3adcf8fSFrançois Tigeot 1785e3adcf8fSFrançois Tigeot ret = intel_ring_begin(ring, 2); 1786e3adcf8fSFrançois Tigeot if (ret) 1787e3adcf8fSFrançois Tigeot return ret; 1788e3adcf8fSFrançois Tigeot 1789b5c29a34SFrançois Tigeot intel_ring_emit(ring, 1790b5c29a34SFrançois Tigeot MI_BATCH_BUFFER_START | MI_BATCH_PPGTT_HSW | 1791b5c29a34SFrançois Tigeot (flags & I915_DISPATCH_SECURE ? 0 : MI_BATCH_NON_SECURE_HSW)); 1792b5c29a34SFrançois Tigeot /* bit0-7 is the length on GEN6+ */ 1793b5c29a34SFrançois Tigeot intel_ring_emit(ring, offset); 1794b5c29a34SFrançois Tigeot intel_ring_advance(ring); 1795b5c29a34SFrançois Tigeot 1796b5c29a34SFrançois Tigeot return 0; 1797b5c29a34SFrançois Tigeot } 1798b5c29a34SFrançois Tigeot 1799b5c29a34SFrançois Tigeot static int 1800b5c29a34SFrançois Tigeot gen6_ring_dispatch_execbuffer(struct intel_ring_buffer *ring, 1801b5c29a34SFrançois Tigeot u32 offset, u32 len, 1802b5c29a34SFrançois Tigeot unsigned flags) 1803b5c29a34SFrançois Tigeot { 1804b5c29a34SFrançois Tigeot int ret; 1805b5c29a34SFrançois Tigeot 1806b5c29a34SFrançois Tigeot ret = intel_ring_begin(ring, 2); 1807b5c29a34SFrançois Tigeot if (ret) 1808b5c29a34SFrançois Tigeot return ret; 1809b5c29a34SFrançois Tigeot 1810b5c29a34SFrançois Tigeot intel_ring_emit(ring, 1811b5c29a34SFrançois Tigeot MI_BATCH_BUFFER_START | 1812b5c29a34SFrançois Tigeot (flags & I915_DISPATCH_SECURE ? 0 : MI_BATCH_NON_SECURE_I965)); 1813e3adcf8fSFrançois Tigeot /* bit0-7 is the length on GEN6+ */ 1814e3adcf8fSFrançois Tigeot intel_ring_emit(ring, offset); 1815e3adcf8fSFrançois Tigeot intel_ring_advance(ring); 1816e3adcf8fSFrançois Tigeot 1817e3adcf8fSFrançois Tigeot return 0; 1818e3adcf8fSFrançois Tigeot } 1819e3adcf8fSFrançois Tigeot 1820e3adcf8fSFrançois Tigeot /* Blitter support (SandyBridge+) */ 1821e3adcf8fSFrançois Tigeot 18225d0b1887SFrançois Tigeot static int gen6_ring_flush(struct intel_ring_buffer *ring, 1823b5c29a34SFrançois Tigeot u32 invalidate, u32 flush) 1824e3adcf8fSFrançois Tigeot { 18255d0b1887SFrançois Tigeot struct drm_device *dev = ring->dev; 1826e3adcf8fSFrançois Tigeot uint32_t cmd; 1827e3adcf8fSFrançois Tigeot int ret; 1828e3adcf8fSFrançois Tigeot 1829e3adcf8fSFrançois Tigeot ret = intel_ring_begin(ring, 4); 1830e3adcf8fSFrançois Tigeot if (ret) 1831e3adcf8fSFrançois Tigeot return ret; 1832e3adcf8fSFrançois Tigeot 1833e3adcf8fSFrançois Tigeot cmd = MI_FLUSH_DW; 1834*9edbd4a0SFrançois Tigeot if (INTEL_INFO(ring->dev)->gen >= 8) 1835*9edbd4a0SFrançois Tigeot cmd += 1; 1836b5c29a34SFrançois Tigeot /* 1837b5c29a34SFrançois Tigeot * Bspec vol 1c.3 - blitter engine command streamer: 1838b5c29a34SFrançois Tigeot * "If ENABLED, all TLBs will be invalidated once the flush 1839b5c29a34SFrançois Tigeot * operation is complete. This bit is only valid when the 1840b5c29a34SFrançois Tigeot * Post-Sync Operation field is a value of 1h or 3h." 1841b5c29a34SFrançois Tigeot */ 1842e3adcf8fSFrançois Tigeot if (invalidate & I915_GEM_DOMAIN_RENDER) 1843b5c29a34SFrançois Tigeot cmd |= MI_INVALIDATE_TLB | MI_FLUSH_DW_STORE_INDEX | 1844b5c29a34SFrançois Tigeot MI_FLUSH_DW_OP_STOREDW; 1845e3adcf8fSFrançois Tigeot intel_ring_emit(ring, cmd); 1846b5c29a34SFrançois Tigeot intel_ring_emit(ring, I915_GEM_HWS_SCRATCH_ADDR | MI_FLUSH_DW_USE_GTT); 1847*9edbd4a0SFrançois Tigeot if (INTEL_INFO(ring->dev)->gen >= 8) { 1848*9edbd4a0SFrançois Tigeot intel_ring_emit(ring, 0); /* upper addr */ 1849*9edbd4a0SFrançois Tigeot intel_ring_emit(ring, 0); /* value */ 1850*9edbd4a0SFrançois Tigeot } else { 1851e3adcf8fSFrançois Tigeot intel_ring_emit(ring, 0); 1852e3adcf8fSFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 1853*9edbd4a0SFrançois Tigeot } 1854e3adcf8fSFrançois Tigeot intel_ring_advance(ring); 18555d0b1887SFrançois Tigeot 1856*9edbd4a0SFrançois Tigeot if (IS_GEN7(dev) && !invalidate && flush) 18575d0b1887SFrançois Tigeot return gen7_ring_fbc_flush(ring, FBC_REND_CACHE_CLEAN); 18585d0b1887SFrançois Tigeot 1859e3adcf8fSFrançois Tigeot return 0; 1860e3adcf8fSFrançois Tigeot } 1861e3adcf8fSFrançois Tigeot 1862e3adcf8fSFrançois Tigeot int intel_init_render_ring_buffer(struct drm_device *dev) 1863e3adcf8fSFrançois Tigeot { 1864e3adcf8fSFrançois Tigeot drm_i915_private_t *dev_priv = dev->dev_private; 1865ad50ea93SFrançois Tigeot struct intel_ring_buffer *ring = &dev_priv->ring[RCS]; 1866e3adcf8fSFrançois Tigeot 1867686a02f1SFrançois Tigeot ring->name = "render ring"; 1868686a02f1SFrançois Tigeot ring->id = RCS; 1869686a02f1SFrançois Tigeot ring->mmio_base = RENDER_RING_BASE; 1870686a02f1SFrançois Tigeot 1871e3adcf8fSFrançois Tigeot if (INTEL_INFO(dev)->gen >= 6) { 1872e3adcf8fSFrançois Tigeot ring->add_request = gen6_add_request; 1873b5c29a34SFrançois Tigeot ring->flush = gen7_render_ring_flush; 1874b5c29a34SFrançois Tigeot if (INTEL_INFO(dev)->gen == 6) 1875e3adcf8fSFrançois Tigeot ring->flush = gen6_render_ring_flush; 1876*9edbd4a0SFrançois Tigeot if (INTEL_INFO(dev)->gen >= 8) { 1877*9edbd4a0SFrançois Tigeot ring->flush = gen8_render_ring_flush; 1878*9edbd4a0SFrançois Tigeot ring->irq_get = gen8_ring_get_irq; 1879*9edbd4a0SFrançois Tigeot ring->irq_put = gen8_ring_put_irq; 1880*9edbd4a0SFrançois Tigeot } else { 1881686a02f1SFrançois Tigeot ring->irq_get = gen6_ring_get_irq; 1882686a02f1SFrançois Tigeot ring->irq_put = gen6_ring_put_irq; 1883*9edbd4a0SFrançois Tigeot } 18845d0b1887SFrançois Tigeot ring->irq_enable_mask = GT_RENDER_USER_INTERRUPT; 1885e3adcf8fSFrançois Tigeot ring->get_seqno = gen6_ring_get_seqno; 1886a2fdbec6SFrançois Tigeot ring->set_seqno = ring_set_seqno; 1887686a02f1SFrançois Tigeot ring->sync_to = gen6_ring_sync; 18885d0b1887SFrançois Tigeot ring->semaphore_register[RCS] = MI_SEMAPHORE_SYNC_INVALID; 18895d0b1887SFrançois Tigeot ring->semaphore_register[VCS] = MI_SEMAPHORE_SYNC_RV; 18905d0b1887SFrançois Tigeot ring->semaphore_register[BCS] = MI_SEMAPHORE_SYNC_RB; 18915d0b1887SFrançois Tigeot ring->semaphore_register[VECS] = MI_SEMAPHORE_SYNC_RVE; 18925d0b1887SFrançois Tigeot ring->signal_mbox[RCS] = GEN6_NOSYNC; 18935d0b1887SFrançois Tigeot ring->signal_mbox[VCS] = GEN6_VRSYNC; 18945d0b1887SFrançois Tigeot ring->signal_mbox[BCS] = GEN6_BRSYNC; 18955d0b1887SFrançois Tigeot ring->signal_mbox[VECS] = GEN6_VERSYNC; 1896e3adcf8fSFrançois Tigeot } else if (IS_GEN5(dev)) { 1897e3adcf8fSFrançois Tigeot ring->add_request = pc_render_add_request; 1898686a02f1SFrançois Tigeot ring->flush = gen4_render_ring_flush; 1899e3adcf8fSFrançois Tigeot ring->get_seqno = pc_render_get_seqno; 1900a2fdbec6SFrançois Tigeot ring->set_seqno = pc_render_set_seqno; 1901686a02f1SFrançois Tigeot ring->irq_get = gen5_ring_get_irq; 1902686a02f1SFrançois Tigeot ring->irq_put = gen5_ring_put_irq; 19035d0b1887SFrançois Tigeot ring->irq_enable_mask = GT_RENDER_USER_INTERRUPT | 19045d0b1887SFrançois Tigeot GT_RENDER_PIPECTL_NOTIFY_INTERRUPT; 1905686a02f1SFrançois Tigeot } else { 1906686a02f1SFrançois Tigeot ring->add_request = i9xx_add_request; 1907686a02f1SFrançois Tigeot if (INTEL_INFO(dev)->gen < 4) 1908686a02f1SFrançois Tigeot ring->flush = gen2_render_ring_flush; 1909686a02f1SFrançois Tigeot else 1910686a02f1SFrançois Tigeot ring->flush = gen4_render_ring_flush; 1911686a02f1SFrançois Tigeot ring->get_seqno = ring_get_seqno; 1912a2fdbec6SFrançois Tigeot ring->set_seqno = ring_set_seqno; 1913686a02f1SFrançois Tigeot if (IS_GEN2(dev)) { 1914686a02f1SFrançois Tigeot ring->irq_get = i8xx_ring_get_irq; 1915686a02f1SFrançois Tigeot ring->irq_put = i8xx_ring_put_irq; 1916686a02f1SFrançois Tigeot } else { 1917686a02f1SFrançois Tigeot ring->irq_get = i9xx_ring_get_irq; 1918686a02f1SFrançois Tigeot ring->irq_put = i9xx_ring_put_irq; 1919e3adcf8fSFrançois Tigeot } 1920686a02f1SFrançois Tigeot ring->irq_enable_mask = I915_USER_INTERRUPT; 1921686a02f1SFrançois Tigeot } 1922686a02f1SFrançois Tigeot ring->write_tail = ring_write_tail; 1923b5c29a34SFrançois Tigeot if (IS_HASWELL(dev)) 1924b5c29a34SFrançois Tigeot ring->dispatch_execbuffer = hsw_ring_dispatch_execbuffer; 1925*9edbd4a0SFrançois Tigeot else if (IS_GEN8(dev)) 1926*9edbd4a0SFrançois Tigeot ring->dispatch_execbuffer = gen8_ring_dispatch_execbuffer; 1927b5c29a34SFrançois Tigeot else if (INTEL_INFO(dev)->gen >= 6) 1928686a02f1SFrançois Tigeot ring->dispatch_execbuffer = gen6_ring_dispatch_execbuffer; 1929686a02f1SFrançois Tigeot else if (INTEL_INFO(dev)->gen >= 4) 1930686a02f1SFrançois Tigeot ring->dispatch_execbuffer = i965_dispatch_execbuffer; 1931686a02f1SFrançois Tigeot else if (IS_I830(dev) || IS_845G(dev)) 1932686a02f1SFrançois Tigeot ring->dispatch_execbuffer = i830_dispatch_execbuffer; 1933686a02f1SFrançois Tigeot else 1934686a02f1SFrançois Tigeot ring->dispatch_execbuffer = i915_dispatch_execbuffer; 1935686a02f1SFrançois Tigeot ring->init = init_render_ring; 1936686a02f1SFrançois Tigeot ring->cleanup = render_ring_cleanup; 1937e3adcf8fSFrançois Tigeot 1938b5c29a34SFrançois Tigeot /* Workaround batchbuffer to combat CS tlb bug. */ 1939b5c29a34SFrançois Tigeot if (HAS_BROKEN_CS_TLB(dev)) { 1940b5c29a34SFrançois Tigeot struct drm_i915_gem_object *obj; 1941b5c29a34SFrançois Tigeot int ret; 1942b5c29a34SFrançois Tigeot 1943b5c29a34SFrançois Tigeot obj = i915_gem_alloc_object(dev, I830_BATCH_LIMIT); 1944b5c29a34SFrançois Tigeot if (obj == NULL) { 1945b5c29a34SFrançois Tigeot DRM_ERROR("Failed to allocate batch bo\n"); 1946b5c29a34SFrançois Tigeot return -ENOMEM; 1947b5c29a34SFrançois Tigeot } 1948b5c29a34SFrançois Tigeot 1949*9edbd4a0SFrançois Tigeot ret = i915_gem_obj_ggtt_pin(obj, 0, true, false); 1950b5c29a34SFrançois Tigeot if (ret != 0) { 1951b5c29a34SFrançois Tigeot drm_gem_object_unreference(&obj->base); 1952b5c29a34SFrançois Tigeot DRM_ERROR("Failed to ping batch bo\n"); 1953b5c29a34SFrançois Tigeot return ret; 1954b5c29a34SFrançois Tigeot } 1955b5c29a34SFrançois Tigeot 1956*9edbd4a0SFrançois Tigeot ring->scratch.obj = obj; 1957*9edbd4a0SFrançois Tigeot ring->scratch.gtt_offset = i915_gem_obj_ggtt_offset(obj); 1958e3adcf8fSFrançois Tigeot } 1959e3adcf8fSFrançois Tigeot 1960e3adcf8fSFrançois Tigeot return intel_init_ring_buffer(dev, ring); 1961e3adcf8fSFrançois Tigeot } 1962e3adcf8fSFrançois Tigeot 1963686a02f1SFrançois Tigeot int intel_render_ring_init_dri(struct drm_device *dev, u64 start, u32 size) 1964e3adcf8fSFrançois Tigeot { 1965e3adcf8fSFrançois Tigeot drm_i915_private_t *dev_priv = dev->dev_private; 1966ad50ea93SFrançois Tigeot struct intel_ring_buffer *ring = &dev_priv->ring[RCS]; 1967b5c29a34SFrançois Tigeot int ret; 1968e3adcf8fSFrançois Tigeot 1969686a02f1SFrançois Tigeot ring->name = "render ring"; 1970686a02f1SFrançois Tigeot ring->id = RCS; 1971686a02f1SFrançois Tigeot ring->mmio_base = RENDER_RING_BASE; 1972686a02f1SFrançois Tigeot 1973e3adcf8fSFrançois Tigeot if (INTEL_INFO(dev)->gen >= 6) { 1974686a02f1SFrançois Tigeot /* non-kms not supported on gen6+ */ 1975686a02f1SFrançois Tigeot return -ENODEV; 1976e3adcf8fSFrançois Tigeot } 1977e3adcf8fSFrançois Tigeot 1978686a02f1SFrançois Tigeot /* Note: gem is not supported on gen5/ilk without kms (the corresponding 1979686a02f1SFrançois Tigeot * gem_init ioctl returns with -ENODEV). Hence we do not need to set up 1980686a02f1SFrançois Tigeot * the special gen5 functions. */ 1981686a02f1SFrançois Tigeot ring->add_request = i9xx_add_request; 1982686a02f1SFrançois Tigeot if (INTEL_INFO(dev)->gen < 4) 1983686a02f1SFrançois Tigeot ring->flush = gen2_render_ring_flush; 1984686a02f1SFrançois Tigeot else 1985686a02f1SFrançois Tigeot ring->flush = gen4_render_ring_flush; 1986686a02f1SFrançois Tigeot ring->get_seqno = ring_get_seqno; 1987a2fdbec6SFrançois Tigeot ring->set_seqno = ring_set_seqno; 1988686a02f1SFrançois Tigeot if (IS_GEN2(dev)) { 1989686a02f1SFrançois Tigeot ring->irq_get = i8xx_ring_get_irq; 1990686a02f1SFrançois Tigeot ring->irq_put = i8xx_ring_put_irq; 1991686a02f1SFrançois Tigeot } else { 1992686a02f1SFrançois Tigeot ring->irq_get = i9xx_ring_get_irq; 1993686a02f1SFrançois Tigeot ring->irq_put = i9xx_ring_put_irq; 1994686a02f1SFrançois Tigeot } 1995686a02f1SFrançois Tigeot ring->irq_enable_mask = I915_USER_INTERRUPT; 1996686a02f1SFrançois Tigeot ring->write_tail = ring_write_tail; 1997686a02f1SFrançois Tigeot if (INTEL_INFO(dev)->gen >= 4) 1998686a02f1SFrançois Tigeot ring->dispatch_execbuffer = i965_dispatch_execbuffer; 1999686a02f1SFrançois Tigeot else if (IS_I830(dev) || IS_845G(dev)) 2000686a02f1SFrançois Tigeot ring->dispatch_execbuffer = i830_dispatch_execbuffer; 2001686a02f1SFrançois Tigeot else 2002686a02f1SFrançois Tigeot ring->dispatch_execbuffer = i915_dispatch_execbuffer; 2003686a02f1SFrançois Tigeot ring->init = init_render_ring; 2004686a02f1SFrançois Tigeot ring->cleanup = render_ring_cleanup; 2005686a02f1SFrançois Tigeot 2006e3adcf8fSFrançois Tigeot ring->dev = dev; 2007e3adcf8fSFrançois Tigeot INIT_LIST_HEAD(&ring->active_list); 2008e3adcf8fSFrançois Tigeot INIT_LIST_HEAD(&ring->request_list); 2009e3adcf8fSFrançois Tigeot 2010e3adcf8fSFrançois Tigeot ring->size = size; 2011e3adcf8fSFrançois Tigeot ring->effective_size = ring->size; 2012b5c29a34SFrançois Tigeot if (IS_I830(ring->dev) || IS_845G(ring->dev)) 2013e3adcf8fSFrançois Tigeot ring->effective_size -= 128; 2014e3adcf8fSFrançois Tigeot 2015686a02f1SFrançois Tigeot ring->virtual_start = ioremap_wc(start, size); 2016686a02f1SFrançois Tigeot if (ring->virtual_start == NULL) { 2017e3adcf8fSFrançois Tigeot DRM_ERROR("can not ioremap virtual address for" 2018e3adcf8fSFrançois Tigeot " ring buffer\n"); 2019e3adcf8fSFrançois Tigeot return -ENOMEM; 2020e3adcf8fSFrançois Tigeot } 2021e3adcf8fSFrançois Tigeot 2022b5c29a34SFrançois Tigeot if (!I915_NEED_GFX_HWS(dev)) { 20235d0b1887SFrançois Tigeot ret = init_phys_status_page(ring); 2024b5c29a34SFrançois Tigeot if (ret) 2025b5c29a34SFrançois Tigeot return ret; 2026b5c29a34SFrançois Tigeot } 2027b5c29a34SFrançois Tigeot 2028e3adcf8fSFrançois Tigeot return 0; 2029e3adcf8fSFrançois Tigeot } 2030e3adcf8fSFrançois Tigeot 2031e3adcf8fSFrançois Tigeot int intel_init_bsd_ring_buffer(struct drm_device *dev) 2032e3adcf8fSFrançois Tigeot { 2033e3adcf8fSFrançois Tigeot drm_i915_private_t *dev_priv = dev->dev_private; 2034ad50ea93SFrançois Tigeot struct intel_ring_buffer *ring = &dev_priv->ring[VCS]; 2035e3adcf8fSFrançois Tigeot 2036686a02f1SFrançois Tigeot ring->name = "bsd ring"; 2037686a02f1SFrançois Tigeot ring->id = VCS; 2038686a02f1SFrançois Tigeot 2039686a02f1SFrançois Tigeot ring->write_tail = ring_write_tail; 2040*9edbd4a0SFrançois Tigeot if (INTEL_INFO(dev)->gen >= 6) { 2041686a02f1SFrançois Tigeot ring->mmio_base = GEN6_BSD_RING_BASE; 2042686a02f1SFrançois Tigeot /* gen6 bsd needs a special wa for tail updates */ 2043686a02f1SFrançois Tigeot if (IS_GEN6(dev)) 2044686a02f1SFrançois Tigeot ring->write_tail = gen6_bsd_ring_write_tail; 20455d0b1887SFrançois Tigeot ring->flush = gen6_bsd_ring_flush; 2046686a02f1SFrançois Tigeot ring->add_request = gen6_add_request; 2047686a02f1SFrançois Tigeot ring->get_seqno = gen6_ring_get_seqno; 2048a2fdbec6SFrançois Tigeot ring->set_seqno = ring_set_seqno; 2049*9edbd4a0SFrançois Tigeot if (INTEL_INFO(dev)->gen >= 8) { 2050*9edbd4a0SFrançois Tigeot ring->irq_enable_mask = 2051*9edbd4a0SFrançois Tigeot GT_RENDER_USER_INTERRUPT << GEN8_VCS1_IRQ_SHIFT; 2052*9edbd4a0SFrançois Tigeot ring->irq_get = gen8_ring_get_irq; 2053*9edbd4a0SFrançois Tigeot ring->irq_put = gen8_ring_put_irq; 2054*9edbd4a0SFrançois Tigeot ring->dispatch_execbuffer = 2055*9edbd4a0SFrançois Tigeot gen8_ring_dispatch_execbuffer; 2056*9edbd4a0SFrançois Tigeot } else { 20575d0b1887SFrançois Tigeot ring->irq_enable_mask = GT_BSD_USER_INTERRUPT; 2058686a02f1SFrançois Tigeot ring->irq_get = gen6_ring_get_irq; 2059686a02f1SFrançois Tigeot ring->irq_put = gen6_ring_put_irq; 2060*9edbd4a0SFrançois Tigeot ring->dispatch_execbuffer = 2061*9edbd4a0SFrançois Tigeot gen6_ring_dispatch_execbuffer; 2062*9edbd4a0SFrançois Tigeot } 2063686a02f1SFrançois Tigeot ring->sync_to = gen6_ring_sync; 20645d0b1887SFrançois Tigeot ring->semaphore_register[RCS] = MI_SEMAPHORE_SYNC_VR; 20655d0b1887SFrançois Tigeot ring->semaphore_register[VCS] = MI_SEMAPHORE_SYNC_INVALID; 20665d0b1887SFrançois Tigeot ring->semaphore_register[BCS] = MI_SEMAPHORE_SYNC_VB; 20675d0b1887SFrançois Tigeot ring->semaphore_register[VECS] = MI_SEMAPHORE_SYNC_VVE; 20685d0b1887SFrançois Tigeot ring->signal_mbox[RCS] = GEN6_RVSYNC; 20695d0b1887SFrançois Tigeot ring->signal_mbox[VCS] = GEN6_NOSYNC; 20705d0b1887SFrançois Tigeot ring->signal_mbox[BCS] = GEN6_BVSYNC; 20715d0b1887SFrançois Tigeot ring->signal_mbox[VECS] = GEN6_VEVSYNC; 2072686a02f1SFrançois Tigeot } else { 2073686a02f1SFrançois Tigeot ring->mmio_base = BSD_RING_BASE; 2074686a02f1SFrançois Tigeot ring->flush = bsd_ring_flush; 2075686a02f1SFrançois Tigeot ring->add_request = i9xx_add_request; 2076686a02f1SFrançois Tigeot ring->get_seqno = ring_get_seqno; 2077a2fdbec6SFrançois Tigeot ring->set_seqno = ring_set_seqno; 2078686a02f1SFrançois Tigeot if (IS_GEN5(dev)) { 20795d0b1887SFrançois Tigeot ring->irq_enable_mask = ILK_BSD_USER_INTERRUPT; 2080686a02f1SFrançois Tigeot ring->irq_get = gen5_ring_get_irq; 2081686a02f1SFrançois Tigeot ring->irq_put = gen5_ring_put_irq; 2082686a02f1SFrançois Tigeot } else { 2083686a02f1SFrançois Tigeot ring->irq_enable_mask = I915_BSD_USER_INTERRUPT; 2084686a02f1SFrançois Tigeot ring->irq_get = i9xx_ring_get_irq; 2085686a02f1SFrançois Tigeot ring->irq_put = i9xx_ring_put_irq; 2086686a02f1SFrançois Tigeot } 2087686a02f1SFrançois Tigeot ring->dispatch_execbuffer = i965_dispatch_execbuffer; 2088686a02f1SFrançois Tigeot } 2089686a02f1SFrançois Tigeot ring->init = init_ring_common; 2090e3adcf8fSFrançois Tigeot 2091e3adcf8fSFrançois Tigeot return intel_init_ring_buffer(dev, ring); 2092e3adcf8fSFrançois Tigeot } 2093e3adcf8fSFrançois Tigeot 2094e3adcf8fSFrançois Tigeot int intel_init_blt_ring_buffer(struct drm_device *dev) 2095e3adcf8fSFrançois Tigeot { 2096e3adcf8fSFrançois Tigeot drm_i915_private_t *dev_priv = dev->dev_private; 2097ad50ea93SFrançois Tigeot struct intel_ring_buffer *ring = &dev_priv->ring[BCS]; 2098e3adcf8fSFrançois Tigeot 2099686a02f1SFrançois Tigeot ring->name = "blitter ring"; 2100686a02f1SFrançois Tigeot ring->id = BCS; 2101686a02f1SFrançois Tigeot 2102686a02f1SFrançois Tigeot ring->mmio_base = BLT_RING_BASE; 2103686a02f1SFrançois Tigeot ring->write_tail = ring_write_tail; 21045d0b1887SFrançois Tigeot ring->flush = gen6_ring_flush; 2105686a02f1SFrançois Tigeot ring->add_request = gen6_add_request; 2106686a02f1SFrançois Tigeot ring->get_seqno = gen6_ring_get_seqno; 2107a2fdbec6SFrançois Tigeot ring->set_seqno = ring_set_seqno; 2108*9edbd4a0SFrançois Tigeot if (INTEL_INFO(dev)->gen >= 8) { 2109*9edbd4a0SFrançois Tigeot ring->irq_enable_mask = 2110*9edbd4a0SFrançois Tigeot GT_RENDER_USER_INTERRUPT << GEN8_BCS_IRQ_SHIFT; 2111*9edbd4a0SFrançois Tigeot ring->irq_get = gen8_ring_get_irq; 2112*9edbd4a0SFrançois Tigeot ring->irq_put = gen8_ring_put_irq; 2113*9edbd4a0SFrançois Tigeot ring->dispatch_execbuffer = gen8_ring_dispatch_execbuffer; 2114*9edbd4a0SFrançois Tigeot } else { 21155d0b1887SFrançois Tigeot ring->irq_enable_mask = GT_BLT_USER_INTERRUPT; 2116686a02f1SFrançois Tigeot ring->irq_get = gen6_ring_get_irq; 2117686a02f1SFrançois Tigeot ring->irq_put = gen6_ring_put_irq; 2118686a02f1SFrançois Tigeot ring->dispatch_execbuffer = gen6_ring_dispatch_execbuffer; 2119*9edbd4a0SFrançois Tigeot } 2120686a02f1SFrançois Tigeot ring->sync_to = gen6_ring_sync; 21215d0b1887SFrançois Tigeot ring->semaphore_register[RCS] = MI_SEMAPHORE_SYNC_BR; 21225d0b1887SFrançois Tigeot ring->semaphore_register[VCS] = MI_SEMAPHORE_SYNC_BV; 21235d0b1887SFrançois Tigeot ring->semaphore_register[BCS] = MI_SEMAPHORE_SYNC_INVALID; 21245d0b1887SFrançois Tigeot ring->semaphore_register[VECS] = MI_SEMAPHORE_SYNC_BVE; 21255d0b1887SFrançois Tigeot ring->signal_mbox[RCS] = GEN6_RBSYNC; 21265d0b1887SFrançois Tigeot ring->signal_mbox[VCS] = GEN6_VBSYNC; 21275d0b1887SFrançois Tigeot ring->signal_mbox[BCS] = GEN6_NOSYNC; 21285d0b1887SFrançois Tigeot ring->signal_mbox[VECS] = GEN6_VEBSYNC; 21295d0b1887SFrançois Tigeot ring->init = init_ring_common; 21305d0b1887SFrançois Tigeot 21315d0b1887SFrançois Tigeot return intel_init_ring_buffer(dev, ring); 21325d0b1887SFrançois Tigeot } 21335d0b1887SFrançois Tigeot 21345d0b1887SFrançois Tigeot int intel_init_vebox_ring_buffer(struct drm_device *dev) 21355d0b1887SFrançois Tigeot { 21365d0b1887SFrançois Tigeot drm_i915_private_t *dev_priv = dev->dev_private; 21375d0b1887SFrançois Tigeot struct intel_ring_buffer *ring = &dev_priv->ring[VECS]; 21385d0b1887SFrançois Tigeot 21395d0b1887SFrançois Tigeot ring->name = "video enhancement ring"; 21405d0b1887SFrançois Tigeot ring->id = VECS; 21415d0b1887SFrançois Tigeot 21425d0b1887SFrançois Tigeot ring->mmio_base = VEBOX_RING_BASE; 21435d0b1887SFrançois Tigeot ring->write_tail = ring_write_tail; 21445d0b1887SFrançois Tigeot ring->flush = gen6_ring_flush; 21455d0b1887SFrançois Tigeot ring->add_request = gen6_add_request; 21465d0b1887SFrançois Tigeot ring->get_seqno = gen6_ring_get_seqno; 21475d0b1887SFrançois Tigeot ring->set_seqno = ring_set_seqno; 2148*9edbd4a0SFrançois Tigeot 2149*9edbd4a0SFrançois Tigeot if (INTEL_INFO(dev)->gen >= 8) { 2150*9edbd4a0SFrançois Tigeot ring->irq_enable_mask = 2151*9edbd4a0SFrançois Tigeot GT_RENDER_USER_INTERRUPT << GEN8_VECS_IRQ_SHIFT; 2152*9edbd4a0SFrançois Tigeot ring->irq_get = gen8_ring_get_irq; 2153*9edbd4a0SFrançois Tigeot ring->irq_put = gen8_ring_put_irq; 2154*9edbd4a0SFrançois Tigeot ring->dispatch_execbuffer = gen8_ring_dispatch_execbuffer; 2155*9edbd4a0SFrançois Tigeot } else { 2156*9edbd4a0SFrançois Tigeot ring->irq_enable_mask = PM_VEBOX_USER_INTERRUPT; 21575d0b1887SFrançois Tigeot ring->irq_get = hsw_vebox_get_irq; 21585d0b1887SFrançois Tigeot ring->irq_put = hsw_vebox_put_irq; 21595d0b1887SFrançois Tigeot ring->dispatch_execbuffer = gen6_ring_dispatch_execbuffer; 2160*9edbd4a0SFrançois Tigeot } 21615d0b1887SFrançois Tigeot ring->sync_to = gen6_ring_sync; 21625d0b1887SFrançois Tigeot ring->semaphore_register[RCS] = MI_SEMAPHORE_SYNC_VER; 21635d0b1887SFrançois Tigeot ring->semaphore_register[VCS] = MI_SEMAPHORE_SYNC_VEV; 21645d0b1887SFrançois Tigeot ring->semaphore_register[BCS] = MI_SEMAPHORE_SYNC_VEB; 21655d0b1887SFrançois Tigeot ring->semaphore_register[VECS] = MI_SEMAPHORE_SYNC_INVALID; 21665d0b1887SFrançois Tigeot ring->signal_mbox[RCS] = GEN6_RVESYNC; 21675d0b1887SFrançois Tigeot ring->signal_mbox[VCS] = GEN6_VVESYNC; 21685d0b1887SFrançois Tigeot ring->signal_mbox[BCS] = GEN6_BVESYNC; 21695d0b1887SFrançois Tigeot ring->signal_mbox[VECS] = GEN6_NOSYNC; 2170686a02f1SFrançois Tigeot ring->init = init_ring_common; 2171e3adcf8fSFrançois Tigeot 2172e3adcf8fSFrançois Tigeot return intel_init_ring_buffer(dev, ring); 2173e3adcf8fSFrançois Tigeot } 2174b030f26bSFrançois Tigeot 2175b030f26bSFrançois Tigeot int 2176b030f26bSFrançois Tigeot intel_ring_flush_all_caches(struct intel_ring_buffer *ring) 2177b030f26bSFrançois Tigeot { 2178b030f26bSFrançois Tigeot int ret; 2179b030f26bSFrançois Tigeot 2180b030f26bSFrançois Tigeot if (!ring->gpu_caches_dirty) 2181b030f26bSFrançois Tigeot return 0; 2182b030f26bSFrançois Tigeot 2183b030f26bSFrançois Tigeot ret = ring->flush(ring, 0, I915_GEM_GPU_DOMAINS); 2184b030f26bSFrançois Tigeot if (ret) 2185b030f26bSFrançois Tigeot return ret; 2186b030f26bSFrançois Tigeot 2187a2fdbec6SFrançois Tigeot trace_i915_gem_ring_flush(ring, 0, I915_GEM_GPU_DOMAINS); 2188a2fdbec6SFrançois Tigeot 2189b030f26bSFrançois Tigeot ring->gpu_caches_dirty = false; 2190b030f26bSFrançois Tigeot return 0; 2191b030f26bSFrançois Tigeot } 2192b030f26bSFrançois Tigeot 2193b030f26bSFrançois Tigeot int 2194b030f26bSFrançois Tigeot intel_ring_invalidate_all_caches(struct intel_ring_buffer *ring) 2195b030f26bSFrançois Tigeot { 2196b030f26bSFrançois Tigeot uint32_t flush_domains; 2197b030f26bSFrançois Tigeot int ret; 2198b030f26bSFrançois Tigeot 2199b030f26bSFrançois Tigeot flush_domains = 0; 2200b030f26bSFrançois Tigeot if (ring->gpu_caches_dirty) 2201b030f26bSFrançois Tigeot flush_domains = I915_GEM_GPU_DOMAINS; 2202b030f26bSFrançois Tigeot 2203b030f26bSFrançois Tigeot ret = ring->flush(ring, I915_GEM_GPU_DOMAINS, flush_domains); 2204b030f26bSFrançois Tigeot if (ret) 2205b030f26bSFrançois Tigeot return ret; 2206b030f26bSFrançois Tigeot 2207a2fdbec6SFrançois Tigeot trace_i915_gem_ring_flush(ring, I915_GEM_GPU_DOMAINS, flush_domains); 2208a2fdbec6SFrançois Tigeot 2209b030f26bSFrançois Tigeot ring->gpu_caches_dirty = false; 2210b030f26bSFrançois Tigeot return 0; 2211b030f26bSFrançois Tigeot } 2212