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 /* 37e3adcf8fSFrançois Tigeot * 965+ support PIPE_CONTROL commands, which provide finer grained control 38e3adcf8fSFrançois Tigeot * over cache flushing. 39e3adcf8fSFrançois Tigeot */ 40e3adcf8fSFrançois Tigeot struct pipe_control { 41e3adcf8fSFrançois Tigeot struct drm_i915_gem_object *obj; 42e3adcf8fSFrançois Tigeot volatile u32 *cpu_page; 43e3adcf8fSFrançois Tigeot u32 gtt_offset; 44e3adcf8fSFrançois Tigeot }; 45e3adcf8fSFrançois Tigeot 46e3adcf8fSFrançois Tigeot static inline int ring_space(struct intel_ring_buffer *ring) 47e3adcf8fSFrançois Tigeot { 487cbd1a46SFrançois Tigeot int space = (ring->head & HEAD_ADDR) - (ring->tail + I915_RING_FREE_SPACE); 49e3adcf8fSFrançois Tigeot if (space < 0) 50e3adcf8fSFrançois Tigeot space += ring->size; 51e3adcf8fSFrançois Tigeot return space; 52e3adcf8fSFrançois Tigeot } 53e3adcf8fSFranç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 { 178e3adcf8fSFrançois Tigeot struct pipe_control *pc = ring->private; 179e3adcf8fSFrançois Tigeot u32 scratch_addr = pc->gtt_offset + 128; 180e3adcf8fSFrançois Tigeot int ret; 181e3adcf8fSFrançois Tigeot 182e3adcf8fSFrançois Tigeot 183e3adcf8fSFrançois Tigeot ret = intel_ring_begin(ring, 6); 184e3adcf8fSFrançois Tigeot if (ret) 185e3adcf8fSFrançois Tigeot return ret; 186e3adcf8fSFrançois Tigeot 187e3adcf8fSFrançois Tigeot intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(5)); 188e3adcf8fSFrançois Tigeot intel_ring_emit(ring, PIPE_CONTROL_CS_STALL | 189e3adcf8fSFrançois Tigeot PIPE_CONTROL_STALL_AT_SCOREBOARD); 190e3adcf8fSFrançois Tigeot intel_ring_emit(ring, scratch_addr | PIPE_CONTROL_GLOBAL_GTT); /* address */ 191e3adcf8fSFrançois Tigeot intel_ring_emit(ring, 0); /* low dword */ 192e3adcf8fSFrançois Tigeot intel_ring_emit(ring, 0); /* high dword */ 193e3adcf8fSFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 194e3adcf8fSFrançois Tigeot intel_ring_advance(ring); 195e3adcf8fSFrançois Tigeot 196e3adcf8fSFrançois Tigeot ret = intel_ring_begin(ring, 6); 197e3adcf8fSFrançois Tigeot if (ret) 198e3adcf8fSFrançois Tigeot return ret; 199e3adcf8fSFrançois Tigeot 200e3adcf8fSFrançois Tigeot intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(5)); 201e3adcf8fSFrançois Tigeot intel_ring_emit(ring, PIPE_CONTROL_QW_WRITE); 202e3adcf8fSFrançois Tigeot intel_ring_emit(ring, scratch_addr | PIPE_CONTROL_GLOBAL_GTT); /* address */ 203e3adcf8fSFrançois Tigeot intel_ring_emit(ring, 0); 204e3adcf8fSFrançois Tigeot intel_ring_emit(ring, 0); 205e3adcf8fSFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 206e3adcf8fSFrançois Tigeot intel_ring_advance(ring); 207e3adcf8fSFrançois Tigeot 208e3adcf8fSFrançois Tigeot return 0; 209e3adcf8fSFrançois Tigeot } 210e3adcf8fSFrançois Tigeot 211e3adcf8fSFrançois Tigeot static int 212e3adcf8fSFrançois Tigeot gen6_render_ring_flush(struct intel_ring_buffer *ring, 213e3adcf8fSFrançois Tigeot u32 invalidate_domains, u32 flush_domains) 214e3adcf8fSFrançois Tigeot { 215e3adcf8fSFrançois Tigeot u32 flags = 0; 216e3adcf8fSFrançois Tigeot struct pipe_control *pc = ring->private; 217e3adcf8fSFrançois Tigeot u32 scratch_addr = pc->gtt_offset + 128; 218e3adcf8fSFrançois Tigeot int ret; 219e3adcf8fSFrançois Tigeot 220e3adcf8fSFrançois Tigeot /* Force SNB workarounds for PIPE_CONTROL flushes */ 221686a02f1SFrançois Tigeot ret = intel_emit_post_sync_nonzero_flush(ring); 222686a02f1SFrançois Tigeot if (ret) 223686a02f1SFrançois Tigeot return ret; 224e3adcf8fSFrançois Tigeot 225e3adcf8fSFrançois Tigeot /* Just flush everything. Experiments have shown that reducing the 226e3adcf8fSFrançois Tigeot * number of bits based on the write domains has little performance 227e3adcf8fSFrançois Tigeot * impact. 228e3adcf8fSFrançois Tigeot */ 229b5c29a34SFrançois Tigeot if (flush_domains) { 230e3adcf8fSFrançois Tigeot flags |= PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH; 231b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_DEPTH_CACHE_FLUSH; 232b5c29a34SFrançois Tigeot /* 233b5c29a34SFrançois Tigeot * Ensure that any following seqno writes only happen 234b5c29a34SFrançois Tigeot * when the render cache is indeed flushed. 235b5c29a34SFrançois Tigeot */ 236b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_CS_STALL; 237b5c29a34SFrançois Tigeot } 238b5c29a34SFrançois Tigeot if (invalidate_domains) { 239686a02f1SFrançois Tigeot flags |= PIPE_CONTROL_TLB_INVALIDATE; 240e3adcf8fSFrançois Tigeot flags |= PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE; 241e3adcf8fSFrançois Tigeot flags |= PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE; 242e3adcf8fSFrançois Tigeot flags |= PIPE_CONTROL_VF_CACHE_INVALIDATE; 243e3adcf8fSFrançois Tigeot flags |= PIPE_CONTROL_CONST_CACHE_INVALIDATE; 244e3adcf8fSFrançois Tigeot flags |= PIPE_CONTROL_STATE_CACHE_INVALIDATE; 245686a02f1SFrançois Tigeot /* 246b5c29a34SFrançois Tigeot * TLB invalidate requires a post-sync write. 247686a02f1SFrançois Tigeot */ 248b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_QW_WRITE | PIPE_CONTROL_CS_STALL; 249b5c29a34SFrançois Tigeot } 250e3adcf8fSFrançois Tigeot 251b5c29a34SFrançois Tigeot ret = intel_ring_begin(ring, 4); 252e3adcf8fSFrançois Tigeot if (ret) 253e3adcf8fSFrançois Tigeot return ret; 254e3adcf8fSFrançois Tigeot 255b5c29a34SFrançois Tigeot intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(4)); 256e3adcf8fSFrançois Tigeot intel_ring_emit(ring, flags); 257e3adcf8fSFrançois Tigeot intel_ring_emit(ring, scratch_addr | PIPE_CONTROL_GLOBAL_GTT); 258b5c29a34SFrançois Tigeot intel_ring_emit(ring, 0); 259b5c29a34SFrançois Tigeot intel_ring_advance(ring); 260b5c29a34SFrançois Tigeot 261b5c29a34SFrançois Tigeot return 0; 262b5c29a34SFrançois Tigeot } 263b5c29a34SFrançois Tigeot 264b5c29a34SFrançois Tigeot static int 265b5c29a34SFrançois Tigeot gen7_render_ring_cs_stall_wa(struct intel_ring_buffer *ring) 266b5c29a34SFrançois Tigeot { 267b5c29a34SFrançois Tigeot int ret; 268b5c29a34SFrançois Tigeot 269b5c29a34SFrançois Tigeot ret = intel_ring_begin(ring, 4); 270b5c29a34SFrançois Tigeot if (ret) 271b5c29a34SFrançois Tigeot return ret; 272b5c29a34SFrançois Tigeot 273b5c29a34SFrançois Tigeot intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(4)); 274b5c29a34SFrançois Tigeot intel_ring_emit(ring, PIPE_CONTROL_CS_STALL | 275b5c29a34SFrançois Tigeot PIPE_CONTROL_STALL_AT_SCOREBOARD); 276b5c29a34SFrançois Tigeot intel_ring_emit(ring, 0); 277b5c29a34SFrançois Tigeot intel_ring_emit(ring, 0); 278b5c29a34SFrançois Tigeot intel_ring_advance(ring); 279b5c29a34SFrançois Tigeot 280b5c29a34SFrançois Tigeot return 0; 281b5c29a34SFrançois Tigeot } 282b5c29a34SFrançois Tigeot 2835d0b1887SFrançois Tigeot static int gen7_ring_fbc_flush(struct intel_ring_buffer *ring, u32 value) 2845d0b1887SFrançois Tigeot { 2855d0b1887SFrançois Tigeot int ret; 2865d0b1887SFrançois Tigeot 2875d0b1887SFrançois Tigeot if (!ring->fbc_dirty) 2885d0b1887SFrançois Tigeot return 0; 2895d0b1887SFrançois Tigeot 2905d0b1887SFrançois Tigeot ret = intel_ring_begin(ring, 4); 2915d0b1887SFrançois Tigeot if (ret) 2925d0b1887SFrançois Tigeot return ret; 2935d0b1887SFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 2945d0b1887SFrançois Tigeot /* WaFbcNukeOn3DBlt:ivb/hsw */ 2955d0b1887SFrançois Tigeot intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1)); 2965d0b1887SFrançois Tigeot intel_ring_emit(ring, MSG_FBC_REND_STATE); 2975d0b1887SFrançois Tigeot intel_ring_emit(ring, value); 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; 309b5c29a34SFrançois Tigeot struct pipe_control *pc = ring->private; 310b5c29a34SFrançois Tigeot u32 scratch_addr = pc->gtt_offset + 128; 311b5c29a34SFrançois Tigeot int ret; 312b5c29a34SFrançois Tigeot 313b5c29a34SFrançois Tigeot /* 314b5c29a34SFrançois Tigeot * Ensure that any following seqno writes only happen when the render 315b5c29a34SFrançois Tigeot * cache is indeed flushed. 316b5c29a34SFrançois Tigeot * 317b5c29a34SFrançois Tigeot * Workaround: 4th PIPE_CONTROL command (except the ones with only 318b5c29a34SFrançois Tigeot * read-cache invalidate bits set) must have the CS_STALL bit set. We 319b5c29a34SFrançois Tigeot * don't try to be clever and just set it unconditionally. 320b5c29a34SFrançois Tigeot */ 321b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_CS_STALL; 322b5c29a34SFrançois Tigeot 323b5c29a34SFrançois Tigeot /* Just flush everything. Experiments have shown that reducing the 324b5c29a34SFrançois Tigeot * number of bits based on the write domains has little performance 325b5c29a34SFrançois Tigeot * impact. 326b5c29a34SFrançois Tigeot */ 327b5c29a34SFrançois Tigeot if (flush_domains) { 328b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH; 329b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_DEPTH_CACHE_FLUSH; 330b5c29a34SFrançois Tigeot } 331b5c29a34SFrançois Tigeot if (invalidate_domains) { 332b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_TLB_INVALIDATE; 333b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE; 334b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE; 335b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_VF_CACHE_INVALIDATE; 336b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_CONST_CACHE_INVALIDATE; 337b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_STATE_CACHE_INVALIDATE; 338b5c29a34SFrançois Tigeot /* 339b5c29a34SFrançois Tigeot * TLB invalidate requires a post-sync write. 340b5c29a34SFrançois Tigeot */ 341b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_QW_WRITE; 342a2fdbec6SFrançois Tigeot flags |= PIPE_CONTROL_GLOBAL_GTT_IVB; 343b5c29a34SFrançois Tigeot 344b5c29a34SFrançois Tigeot /* Workaround: we must issue a pipe_control with CS-stall bit 345b5c29a34SFrançois Tigeot * set before a pipe_control command that has the state cache 346b5c29a34SFrançois Tigeot * invalidate bit set. */ 347b5c29a34SFrançois Tigeot gen7_render_ring_cs_stall_wa(ring); 348b5c29a34SFrançois Tigeot } 349b5c29a34SFrançois Tigeot 350b5c29a34SFrançois Tigeot ret = intel_ring_begin(ring, 4); 351b5c29a34SFrançois Tigeot if (ret) 352b5c29a34SFrançois Tigeot return ret; 353b5c29a34SFrançois Tigeot 354b5c29a34SFrançois Tigeot intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(4)); 355b5c29a34SFrançois Tigeot intel_ring_emit(ring, flags); 356a2fdbec6SFrançois Tigeot intel_ring_emit(ring, scratch_addr); 357b5c29a34SFrançois Tigeot intel_ring_emit(ring, 0); 358e3adcf8fSFrançois Tigeot intel_ring_advance(ring); 359e3adcf8fSFrançois Tigeot 3605d0b1887SFrançois Tigeot if (flush_domains) 3615d0b1887SFrançois Tigeot return gen7_ring_fbc_flush(ring, FBC_REND_NUKE); 3625d0b1887SFrançois Tigeot 363e3adcf8fSFrançois Tigeot return 0; 364e3adcf8fSFrançois Tigeot } 365e3adcf8fSFrançois Tigeot 366e3adcf8fSFrançois Tigeot static void ring_write_tail(struct intel_ring_buffer *ring, 367b5c29a34SFrançois Tigeot u32 value) 368e3adcf8fSFrançois Tigeot { 369e3adcf8fSFrançois Tigeot drm_i915_private_t *dev_priv = ring->dev->dev_private; 370e3adcf8fSFrançois Tigeot I915_WRITE_TAIL(ring, value); 371e3adcf8fSFrançois Tigeot } 372e3adcf8fSFrançois Tigeot 373e3adcf8fSFrançois Tigeot u32 intel_ring_get_active_head(struct intel_ring_buffer *ring) 374e3adcf8fSFrançois Tigeot { 375e3adcf8fSFrançois Tigeot drm_i915_private_t *dev_priv = ring->dev->dev_private; 376b5c29a34SFrançois Tigeot u32 acthd_reg = INTEL_INFO(ring->dev)->gen >= 4 ? 377e3adcf8fSFrançois Tigeot RING_ACTHD(ring->mmio_base) : ACTHD; 378e3adcf8fSFrançois Tigeot 379e3adcf8fSFrançois Tigeot return I915_READ(acthd_reg); 380e3adcf8fSFrançois Tigeot } 381e3adcf8fSFrançois Tigeot 3825d0b1887SFrançois Tigeot static void ring_setup_phys_status_page(struct intel_ring_buffer *ring) 3835d0b1887SFrançois Tigeot { 3845d0b1887SFrançois Tigeot struct drm_i915_private *dev_priv = ring->dev->dev_private; 3855d0b1887SFrançois Tigeot u32 addr; 3865d0b1887SFrançois Tigeot 3875d0b1887SFrançois Tigeot addr = dev_priv->status_page_dmah->busaddr; 3885d0b1887SFrançois Tigeot if (INTEL_INFO(ring->dev)->gen >= 4) 3895d0b1887SFrançois Tigeot addr |= (dev_priv->status_page_dmah->busaddr >> 28) & 0xf0; 3905d0b1887SFrançois Tigeot I915_WRITE(HWS_PGA, addr); 3915d0b1887SFrançois Tigeot } 3925d0b1887SFrançois Tigeot 393e3adcf8fSFrançois Tigeot static int init_ring_common(struct intel_ring_buffer *ring) 394e3adcf8fSFrançois Tigeot { 395686a02f1SFrançois Tigeot struct drm_device *dev = ring->dev; 396686a02f1SFrançois Tigeot drm_i915_private_t *dev_priv = dev->dev_private; 397e3adcf8fSFrançois Tigeot struct drm_i915_gem_object *obj = ring->obj; 398686a02f1SFrançois Tigeot int ret = 0; 399b5c29a34SFrançois Tigeot u32 head; 400e3adcf8fSFrançois Tigeot 401686a02f1SFrançois Tigeot if (HAS_FORCE_WAKE(dev)) 402686a02f1SFrançois Tigeot gen6_gt_force_wake_get(dev_priv); 403686a02f1SFrançois Tigeot 4045d0b1887SFrançois Tigeot if (I915_NEED_GFX_HWS(dev)) 4055d0b1887SFrançois Tigeot intel_ring_setup_status_page(ring); 4065d0b1887SFrançois Tigeot else 4075d0b1887SFrançois Tigeot ring_setup_phys_status_page(ring); 4085d0b1887SFrançois Tigeot 409e3adcf8fSFrançois Tigeot /* Stop the ring if it's running. */ 410e3adcf8fSFrançois Tigeot I915_WRITE_CTL(ring, 0); 411e3adcf8fSFrançois Tigeot I915_WRITE_HEAD(ring, 0); 412e3adcf8fSFrançois Tigeot ring->write_tail(ring, 0); 413e3adcf8fSFrançois Tigeot 414e3adcf8fSFrançois Tigeot head = I915_READ_HEAD(ring) & HEAD_ADDR; 415e3adcf8fSFrançois Tigeot 416e3adcf8fSFrançois Tigeot /* G45 ring initialization fails to reset head to zero */ 417e3adcf8fSFrançois Tigeot if (head != 0) { 418b5c29a34SFrançois Tigeot DRM_DEBUG_KMS("%s head not reset to zero " 419e3adcf8fSFrançois Tigeot "ctl %08x head %08x tail %08x start %08x\n", 420e3adcf8fSFrançois Tigeot ring->name, 421e3adcf8fSFrançois Tigeot I915_READ_CTL(ring), 422e3adcf8fSFrançois Tigeot I915_READ_HEAD(ring), 423e3adcf8fSFrançois Tigeot I915_READ_TAIL(ring), 424e3adcf8fSFrançois Tigeot I915_READ_START(ring)); 425e3adcf8fSFrançois Tigeot 426e3adcf8fSFrançois Tigeot I915_WRITE_HEAD(ring, 0); 427e3adcf8fSFrançois Tigeot 428e3adcf8fSFrançois Tigeot if (I915_READ_HEAD(ring) & HEAD_ADDR) { 429e3adcf8fSFrançois Tigeot DRM_ERROR("failed to set %s head to zero " 430e3adcf8fSFrançois Tigeot "ctl %08x head %08x tail %08x start %08x\n", 431e3adcf8fSFrançois Tigeot ring->name, 432e3adcf8fSFrançois Tigeot I915_READ_CTL(ring), 433e3adcf8fSFrançois Tigeot I915_READ_HEAD(ring), 434e3adcf8fSFrançois Tigeot I915_READ_TAIL(ring), 435e3adcf8fSFrançois Tigeot I915_READ_START(ring)); 436e3adcf8fSFrançois Tigeot } 437e3adcf8fSFrançois Tigeot } 438e3adcf8fSFrançois Tigeot 439b5c29a34SFrançois Tigeot /* Initialize the ring. This must happen _after_ we've cleared the ring 440b5c29a34SFrançois Tigeot * registers with the above sequence (the readback of the HEAD registers 441b5c29a34SFrançois Tigeot * also enforces ordering), otherwise the hw might lose the new ring 442b5c29a34SFrançois Tigeot * register values. */ 443b5c29a34SFrançois Tigeot I915_WRITE_START(ring, obj->gtt_offset); 444e3adcf8fSFrançois Tigeot I915_WRITE_CTL(ring, 445e3adcf8fSFrançois Tigeot ((ring->size - PAGE_SIZE) & RING_NR_PAGES) 446e3adcf8fSFrançois Tigeot | RING_VALID); 447e3adcf8fSFrançois Tigeot 448e3adcf8fSFrançois Tigeot /* If the head is still not zero, the ring is dead */ 449b5c29a34SFrançois Tigeot if (wait_for((I915_READ_CTL(ring) & RING_VALID) != 0 && 450e3adcf8fSFrançois Tigeot I915_READ_START(ring) == obj->gtt_offset && 451b5c29a34SFrançois Tigeot (I915_READ_HEAD(ring) & HEAD_ADDR) == 0, 50)) { 452e3adcf8fSFrançois Tigeot DRM_ERROR("%s initialization failed " 453e3adcf8fSFrançois Tigeot "ctl %08x head %08x tail %08x start %08x\n", 454e3adcf8fSFrançois Tigeot ring->name, 455e3adcf8fSFrançois Tigeot I915_READ_CTL(ring), 456e3adcf8fSFrançois Tigeot I915_READ_HEAD(ring), 457e3adcf8fSFrançois Tigeot I915_READ_TAIL(ring), 458e3adcf8fSFrançois Tigeot I915_READ_START(ring)); 459686a02f1SFrançois Tigeot ret = -EIO; 460686a02f1SFrançois Tigeot goto out; 461e3adcf8fSFrançois Tigeot } 462e3adcf8fSFrançois Tigeot 463e3adcf8fSFrançois Tigeot if (!drm_core_check_feature(ring->dev, DRIVER_MODESET)) 464e3adcf8fSFrançois Tigeot i915_kernel_lost_context(ring->dev); 465e3adcf8fSFrançois Tigeot else { 466e3adcf8fSFrançois Tigeot ring->head = I915_READ_HEAD(ring); 467e3adcf8fSFrançois Tigeot ring->tail = I915_READ_TAIL(ring) & TAIL_ADDR; 468e3adcf8fSFrançois Tigeot ring->space = ring_space(ring); 469686a02f1SFrançois Tigeot ring->last_retired_head = -1; 470e3adcf8fSFrançois Tigeot } 471e3adcf8fSFrançois Tigeot 4725d0b1887SFrançois Tigeot memset(&ring->hangcheck, 0, sizeof(ring->hangcheck)); 4735d0b1887SFrançois Tigeot 474686a02f1SFrançois Tigeot out: 475686a02f1SFrançois Tigeot if (HAS_FORCE_WAKE(dev)) 476686a02f1SFrançois Tigeot gen6_gt_force_wake_put(dev_priv); 477686a02f1SFrançois Tigeot 478686a02f1SFrançois Tigeot return ret; 479e3adcf8fSFrançois Tigeot } 480e3adcf8fSFrançois Tigeot 481e3adcf8fSFrançois Tigeot static int 482e3adcf8fSFrançois Tigeot init_pipe_control(struct intel_ring_buffer *ring) 483e3adcf8fSFrançois Tigeot { 484e3adcf8fSFrançois Tigeot struct pipe_control *pc; 485e3adcf8fSFrançois Tigeot struct drm_i915_gem_object *obj; 486e3adcf8fSFrançois Tigeot int ret; 487e3adcf8fSFrançois Tigeot 488e3adcf8fSFrançois Tigeot if (ring->private) 489e3adcf8fSFrançois Tigeot return 0; 490e3adcf8fSFrançois Tigeot 4915a3b77d5SFrançois Tigeot pc = kmalloc(sizeof(*pc), M_DRM, M_WAITOK); 492e3adcf8fSFrançois Tigeot if (!pc) 493e3adcf8fSFrançois Tigeot return -ENOMEM; 494e3adcf8fSFrançois Tigeot 495e3adcf8fSFrançois Tigeot obj = i915_gem_alloc_object(ring->dev, 4096); 496e3adcf8fSFrançois Tigeot if (obj == NULL) { 497e3adcf8fSFrançois Tigeot DRM_ERROR("Failed to allocate seqno page\n"); 498e3adcf8fSFrançois Tigeot ret = -ENOMEM; 499e3adcf8fSFrançois Tigeot goto err; 500e3adcf8fSFrançois Tigeot } 501e3adcf8fSFrançois Tigeot 502e3adcf8fSFrançois Tigeot i915_gem_object_set_cache_level(obj, I915_CACHE_LLC); 503e3adcf8fSFrançois Tigeot 504b00bc81cSFrançois Tigeot ret = i915_gem_object_pin(obj, 4096, true, false); 505e3adcf8fSFrançois Tigeot if (ret) 506e3adcf8fSFrançois Tigeot goto err_unref; 507e3adcf8fSFrançois Tigeot 508e3adcf8fSFrançois Tigeot pc->gtt_offset = obj->gtt_offset; 509*f4f90b23SFrançois Tigeot pc->cpu_page = kmap(obj->pages[0]); 5105d0b1887SFrançois Tigeot if (pc->cpu_page == NULL) { 5115d0b1887SFrançois Tigeot ret = -ENOMEM; 512e3adcf8fSFrançois Tigeot goto err_unpin; 5135d0b1887SFrançois Tigeot } 514a2fdbec6SFrançois Tigeot 515e3adcf8fSFrançois Tigeot pmap_qenter((uintptr_t)pc->cpu_page, &obj->pages[0], 1); 516e3adcf8fSFrançois Tigeot pmap_invalidate_cache_range((vm_offset_t)pc->cpu_page, 517e3adcf8fSFrançois Tigeot (vm_offset_t)pc->cpu_page + PAGE_SIZE); 518a2fdbec6SFrançois Tigeot DRM_DEBUG_DRIVER("%s pipe control offset: 0x%08x\n", 519a2fdbec6SFrançois Tigeot ring->name, pc->gtt_offset); 520e3adcf8fSFrançois Tigeot 521e3adcf8fSFrançois Tigeot pc->obj = obj; 522e3adcf8fSFrançois Tigeot ring->private = pc; 523e3adcf8fSFrançois Tigeot return 0; 524e3adcf8fSFrançois Tigeot 525e3adcf8fSFrançois Tigeot err_unpin: 526e3adcf8fSFrançois Tigeot i915_gem_object_unpin(obj); 527e3adcf8fSFrançois Tigeot err_unref: 528e3adcf8fSFrançois Tigeot drm_gem_object_unreference(&obj->base); 529e3adcf8fSFrançois Tigeot err: 530158486a6SFrançois Tigeot kfree(pc); 531e3adcf8fSFrançois Tigeot return ret; 532e3adcf8fSFrançois Tigeot } 533e3adcf8fSFrançois Tigeot 534e3adcf8fSFrançois Tigeot static void 535e3adcf8fSFrançois Tigeot cleanup_pipe_control(struct intel_ring_buffer *ring) 536e3adcf8fSFrançois Tigeot { 537e3adcf8fSFrançois Tigeot struct pipe_control *pc = ring->private; 538e3adcf8fSFrançois Tigeot struct drm_i915_gem_object *obj; 539e3adcf8fSFrançois Tigeot 540e3adcf8fSFrançois Tigeot obj = pc->obj; 541a2fdbec6SFrançois Tigeot 542e3adcf8fSFrançois Tigeot pmap_qremove((vm_offset_t)pc->cpu_page, 1); 543e3adcf8fSFrançois Tigeot kmem_free(&kernel_map, (uintptr_t)pc->cpu_page, PAGE_SIZE); 544e3adcf8fSFrançois Tigeot i915_gem_object_unpin(obj); 545e3adcf8fSFrançois Tigeot drm_gem_object_unreference(&obj->base); 546e3adcf8fSFrançois Tigeot 547158486a6SFrançois Tigeot kfree(pc); 548e3adcf8fSFrançois Tigeot } 549e3adcf8fSFrançois Tigeot 550e3adcf8fSFrançois Tigeot static int init_render_ring(struct intel_ring_buffer *ring) 551e3adcf8fSFrançois Tigeot { 552e3adcf8fSFrançois Tigeot struct drm_device *dev = ring->dev; 553e3adcf8fSFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 554e3adcf8fSFrançois Tigeot int ret = init_ring_common(ring); 555e3adcf8fSFrançois Tigeot 556f4e1c372SFrançois Tigeot if (INTEL_INFO(dev)->gen > 3) 557f4e1c372SFrançois Tigeot I915_WRITE(MI_MODE, _MASKED_BIT_ENABLE(VS_TIMER_DISPATCH)); 558f4e1c372SFrançois Tigeot 559f4e1c372SFrançois Tigeot /* We need to disable the AsyncFlip performance optimisations in order 560f4e1c372SFrançois Tigeot * to use MI_WAIT_FOR_EVENT within the CS. It should already be 561f4e1c372SFrançois Tigeot * programmed to '1' on all products. 5625d0b1887SFrançois Tigeot * 5635d0b1887SFrançois Tigeot * WaDisableAsyncFlipPerfMode:snb,ivb,hsw,vlv 564f4e1c372SFrançois Tigeot */ 565f4e1c372SFrançois Tigeot if (INTEL_INFO(dev)->gen >= 6) 566f4e1c372SFrançois Tigeot I915_WRITE(MI_MODE, _MASKED_BIT_ENABLE(ASYNC_FLIP_PERF_DISABLE)); 567f4e1c372SFrançois Tigeot 568f4e1c372SFrançois Tigeot /* Required for the hardware to program scanline values for waiting */ 569f4e1c372SFrançois Tigeot if (INTEL_INFO(dev)->gen == 6) 570f4e1c372SFrançois Tigeot I915_WRITE(GFX_MODE, 571f4e1c372SFrançois Tigeot _MASKED_BIT_ENABLE(GFX_TLB_INVALIDATE_ALWAYS)); 572f4e1c372SFrançois Tigeot 573e3adcf8fSFrançois Tigeot if (IS_GEN7(dev)) 574e3adcf8fSFrançois Tigeot I915_WRITE(GFX_MODE_GEN7, 575f4e1c372SFrançois Tigeot _MASKED_BIT_DISABLE(GFX_TLB_INVALIDATE_ALWAYS) | 576f4e1c372SFrançois Tigeot _MASKED_BIT_ENABLE(GFX_REPLAY_MODE)); 577e3adcf8fSFrançois Tigeot 578e3adcf8fSFrançois Tigeot if (INTEL_INFO(dev)->gen >= 5) { 579e3adcf8fSFrançois Tigeot ret = init_pipe_control(ring); 580e3adcf8fSFrançois Tigeot if (ret) 581e3adcf8fSFrançois Tigeot return ret; 582e3adcf8fSFrançois Tigeot } 583e3adcf8fSFrançois Tigeot 584e3adcf8fSFrançois Tigeot if (IS_GEN6(dev)) { 585e3adcf8fSFrançois Tigeot /* From the Sandybridge PRM, volume 1 part 3, page 24: 586e3adcf8fSFrançois Tigeot * "If this bit is set, STCunit will have LRA as replacement 587e3adcf8fSFrançois Tigeot * policy. [...] This bit must be reset. LRA replacement 588e3adcf8fSFrançois Tigeot * policy is not supported." 589e3adcf8fSFrançois Tigeot */ 590e3adcf8fSFrançois Tigeot I915_WRITE(CACHE_MODE_0, 591f4e1c372SFrançois Tigeot _MASKED_BIT_DISABLE(CM0_STC_EVICT_DISABLE_LRA_SNB)); 592686a02f1SFrançois Tigeot 593686a02f1SFrançois Tigeot /* This is not explicitly set for GEN6, so read the register. 594686a02f1SFrançois Tigeot * see intel_ring_mi_set_context() for why we care. 595686a02f1SFrançois Tigeot * TODO: consider explicitly setting the bit for GEN5 596686a02f1SFrançois Tigeot */ 597686a02f1SFrançois Tigeot ring->itlb_before_ctx_switch = 598686a02f1SFrançois Tigeot !!(I915_READ(GFX_MODE) & GFX_TLB_INVALIDATE_ALWAYS); 599e3adcf8fSFrançois Tigeot } 600e3adcf8fSFrançois Tigeot 601f4e1c372SFrançois Tigeot if (INTEL_INFO(dev)->gen >= 6) 602f4e1c372SFrançois Tigeot I915_WRITE(INSTPM, _MASKED_BIT_ENABLE(INSTPM_FORCE_ORDERING)); 603f4e1c372SFrançois Tigeot 604f4e1c372SFrançois Tigeot if (HAS_L3_GPU_CACHE(dev)) 6055d0b1887SFrançois Tigeot I915_WRITE_IMR(ring, ~GT_RENDER_L3_PARITY_ERROR_INTERRUPT); 606e3adcf8fSFrançois Tigeot 607e3adcf8fSFrançois Tigeot return ret; 608e3adcf8fSFrançois Tigeot } 609e3adcf8fSFrançois Tigeot 610e3adcf8fSFrançois Tigeot static void render_ring_cleanup(struct intel_ring_buffer *ring) 611e3adcf8fSFrançois Tigeot { 612b5c29a34SFrançois Tigeot struct drm_device *dev = ring->dev; 613b5c29a34SFrançois Tigeot 614e3adcf8fSFrançois Tigeot if (!ring->private) 615e3adcf8fSFrançois Tigeot return; 616e3adcf8fSFrançois Tigeot 617b5c29a34SFrançois Tigeot if (HAS_BROKEN_CS_TLB(dev)) 618b5c29a34SFrançois Tigeot drm_gem_object_unreference(to_gem_object(ring->private)); 619b5c29a34SFrançois Tigeot 6205d0b1887SFrançois Tigeot if (INTEL_INFO(dev)->gen >= 5) 621e3adcf8fSFrançois Tigeot cleanup_pipe_control(ring); 6225d0b1887SFrançois Tigeot 6235d0b1887SFrançois Tigeot ring->private = NULL; 624e3adcf8fSFrançois Tigeot } 625e3adcf8fSFrançois Tigeot 626e3adcf8fSFrançois Tigeot static void 627e3adcf8fSFrançois Tigeot update_mboxes(struct intel_ring_buffer *ring, 628e3adcf8fSFrançois Tigeot u32 mmio_offset) 629e3adcf8fSFrançois Tigeot { 6305d0b1887SFrançois Tigeot /* NB: In order to be able to do semaphore MBOX updates for varying number 6315d0b1887SFrançois Tigeot * of rings, it's easiest if we round up each individual update to a 6325d0b1887SFrançois Tigeot * multiple of 2 (since ring updates must always be a multiple of 2) 6335d0b1887SFrançois Tigeot * even though the actual update only requires 3 dwords. 6345d0b1887SFrançois Tigeot */ 6355d0b1887SFrançois Tigeot #define MBOX_UPDATE_DWORDS 4 636b5c29a34SFrançois Tigeot intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1)); 637e3adcf8fSFrançois Tigeot intel_ring_emit(ring, mmio_offset); 638b5c29a34SFrançois Tigeot intel_ring_emit(ring, ring->outstanding_lazy_request); 6395d0b1887SFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 640e3adcf8fSFrançois Tigeot } 641e3adcf8fSFrançois Tigeot 642e3adcf8fSFrançois Tigeot /** 643e3adcf8fSFrançois Tigeot * gen6_add_request - Update the semaphore mailbox registers 644e3adcf8fSFrançois Tigeot * 645e3adcf8fSFrançois Tigeot * @ring - ring that is adding a request 646e3adcf8fSFrançois Tigeot * @seqno - return seqno stuck into the ring 647e3adcf8fSFrançois Tigeot * 648e3adcf8fSFrançois Tigeot * Update the mailbox registers in the *other* rings with the current seqno. 649e3adcf8fSFrançois Tigeot * This acts like a signal in the canonical semaphore. 650e3adcf8fSFrançois Tigeot */ 651e3adcf8fSFrançois Tigeot static int 652b5c29a34SFrançois Tigeot gen6_add_request(struct intel_ring_buffer *ring) 653e3adcf8fSFrançois Tigeot { 6545d0b1887SFrançois Tigeot struct drm_device *dev = ring->dev; 6555d0b1887SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 6565d0b1887SFrançois Tigeot struct intel_ring_buffer *useless; 6575d0b1887SFrançois Tigeot int i, ret; 658e3adcf8fSFrançois Tigeot 6595d0b1887SFrançois Tigeot ret = intel_ring_begin(ring, ((I915_NUM_RINGS-1) * 6605d0b1887SFrançois Tigeot MBOX_UPDATE_DWORDS) + 6615d0b1887SFrançois Tigeot 4); 662e3adcf8fSFrançois Tigeot if (ret) 663e3adcf8fSFrançois Tigeot return ret; 6645d0b1887SFrançois Tigeot #undef MBOX_UPDATE_DWORDS 665e3adcf8fSFrançois Tigeot 6665d0b1887SFrançois Tigeot for_each_ring(useless, dev_priv, i) { 6675d0b1887SFrançois Tigeot u32 mbox_reg = ring->signal_mbox[i]; 6685d0b1887SFrançois Tigeot if (mbox_reg != GEN6_NOSYNC) 6695d0b1887SFrançois Tigeot update_mboxes(ring, mbox_reg); 6705d0b1887SFrançois Tigeot } 671e3adcf8fSFrançois Tigeot 672e3adcf8fSFrançois Tigeot intel_ring_emit(ring, MI_STORE_DWORD_INDEX); 673e3adcf8fSFrançois Tigeot intel_ring_emit(ring, I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT); 674b5c29a34SFrançois Tigeot intel_ring_emit(ring, ring->outstanding_lazy_request); 675e3adcf8fSFrançois Tigeot intel_ring_emit(ring, MI_USER_INTERRUPT); 676e3adcf8fSFrançois Tigeot intel_ring_advance(ring); 677e3adcf8fSFrançois Tigeot 678e3adcf8fSFrançois Tigeot return 0; 679e3adcf8fSFrançois Tigeot } 680e3adcf8fSFrançois Tigeot 681a2fdbec6SFrançois Tigeot static inline bool i915_gem_has_seqno_wrapped(struct drm_device *dev, 682a2fdbec6SFrançois Tigeot u32 seqno) 683a2fdbec6SFrançois Tigeot { 684a2fdbec6SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 685a2fdbec6SFrançois Tigeot return dev_priv->last_seqno < seqno; 686a2fdbec6SFrançois Tigeot } 687a2fdbec6SFrançois Tigeot 688e3adcf8fSFrançois Tigeot /** 689e3adcf8fSFrançois Tigeot * intel_ring_sync - sync the waiter to the signaller on seqno 690e3adcf8fSFrançois Tigeot * 691e3adcf8fSFrançois Tigeot * @waiter - ring that is waiting 692e3adcf8fSFrançois Tigeot * @signaller - ring which has, or will signal 693e3adcf8fSFrançois Tigeot * @seqno - seqno which the waiter will block on 694e3adcf8fSFrançois Tigeot */ 695e3adcf8fSFrançois Tigeot static int 696686a02f1SFrançois Tigeot gen6_ring_sync(struct intel_ring_buffer *waiter, 697e3adcf8fSFrançois Tigeot struct intel_ring_buffer *signaller, 698e3adcf8fSFrançois Tigeot u32 seqno) 699e3adcf8fSFrançois Tigeot { 700e3adcf8fSFrançois Tigeot int ret; 701e3adcf8fSFrançois Tigeot u32 dw1 = MI_SEMAPHORE_MBOX | 702e3adcf8fSFrançois Tigeot MI_SEMAPHORE_COMPARE | 703e3adcf8fSFrançois Tigeot MI_SEMAPHORE_REGISTER; 704e3adcf8fSFrançois Tigeot 705686a02f1SFrançois Tigeot /* Throughout all of the GEM code, seqno passed implies our current 706686a02f1SFrançois Tigeot * seqno is >= the last seqno executed. However for hardware the 707686a02f1SFrançois Tigeot * comparison is strictly greater than. 708686a02f1SFrançois Tigeot */ 709686a02f1SFrançois Tigeot seqno -= 1; 710686a02f1SFrançois Tigeot 711686a02f1SFrançois Tigeot WARN_ON(signaller->semaphore_register[waiter->id] == 712686a02f1SFrançois Tigeot MI_SEMAPHORE_SYNC_INVALID); 713686a02f1SFrançois Tigeot 714e3adcf8fSFrançois Tigeot ret = intel_ring_begin(waiter, 4); 715e3adcf8fSFrançois Tigeot if (ret) 716e3adcf8fSFrançois Tigeot return ret; 717e3adcf8fSFrançois Tigeot 718a2fdbec6SFrançois Tigeot /* If seqno wrap happened, omit the wait with no-ops */ 719a2fdbec6SFrançois Tigeot if (likely(!i915_gem_has_seqno_wrapped(waiter->dev, seqno))) { 720686a02f1SFrançois Tigeot intel_ring_emit(waiter, 721a2fdbec6SFrançois Tigeot dw1 | 722a2fdbec6SFrançois Tigeot signaller->semaphore_register[waiter->id]); 723e3adcf8fSFrançois Tigeot intel_ring_emit(waiter, seqno); 724e3adcf8fSFrançois Tigeot intel_ring_emit(waiter, 0); 725e3adcf8fSFrançois Tigeot intel_ring_emit(waiter, MI_NOOP); 726a2fdbec6SFrançois Tigeot } else { 727a2fdbec6SFrançois Tigeot intel_ring_emit(waiter, MI_NOOP); 728a2fdbec6SFrançois Tigeot intel_ring_emit(waiter, MI_NOOP); 729a2fdbec6SFrançois Tigeot intel_ring_emit(waiter, MI_NOOP); 730a2fdbec6SFrançois Tigeot intel_ring_emit(waiter, MI_NOOP); 731a2fdbec6SFrançois Tigeot } 732e3adcf8fSFrançois Tigeot intel_ring_advance(waiter); 733e3adcf8fSFrançois Tigeot 734e3adcf8fSFrançois Tigeot return 0; 735e3adcf8fSFrançois Tigeot } 736e3adcf8fSFrançois Tigeot 737e3adcf8fSFrançois Tigeot #define PIPE_CONTROL_FLUSH(ring__, addr__) \ 738e3adcf8fSFrançois Tigeot do { \ 739e3adcf8fSFrançois Tigeot intel_ring_emit(ring__, GFX_OP_PIPE_CONTROL(4) | PIPE_CONTROL_QW_WRITE | \ 740e3adcf8fSFrançois Tigeot PIPE_CONTROL_DEPTH_STALL); \ 741e3adcf8fSFrançois Tigeot intel_ring_emit(ring__, (addr__) | PIPE_CONTROL_GLOBAL_GTT); \ 742e3adcf8fSFrançois Tigeot intel_ring_emit(ring__, 0); \ 743e3adcf8fSFrançois Tigeot intel_ring_emit(ring__, 0); \ 744e3adcf8fSFrançois Tigeot } while (0) 745e3adcf8fSFrançois Tigeot 746e3adcf8fSFrançois Tigeot static int 747b5c29a34SFrançois Tigeot pc_render_add_request(struct intel_ring_buffer *ring) 748e3adcf8fSFrançois Tigeot { 749e3adcf8fSFrançois Tigeot struct pipe_control *pc = ring->private; 750e3adcf8fSFrançois Tigeot u32 scratch_addr = pc->gtt_offset + 128; 751e3adcf8fSFrançois Tigeot int ret; 752e3adcf8fSFrançois Tigeot 753e3adcf8fSFrançois Tigeot /* For Ironlake, MI_USER_INTERRUPT was deprecated and apparently 754e3adcf8fSFrançois Tigeot * incoherent with writes to memory, i.e. completely fubar, 755e3adcf8fSFrançois Tigeot * so we need to use PIPE_NOTIFY instead. 756e3adcf8fSFrançois Tigeot * 757e3adcf8fSFrançois Tigeot * However, we also need to workaround the qword write 758e3adcf8fSFrançois Tigeot * incoherence by flushing the 6 PIPE_NOTIFY buffers out to 759e3adcf8fSFrançois Tigeot * memory before requesting an interrupt. 760e3adcf8fSFrançois Tigeot */ 761e3adcf8fSFrançois Tigeot ret = intel_ring_begin(ring, 32); 762e3adcf8fSFrançois Tigeot if (ret) 763e3adcf8fSFrançois Tigeot return ret; 764e3adcf8fSFrançois Tigeot 765e3adcf8fSFrançois Tigeot intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(4) | PIPE_CONTROL_QW_WRITE | 766e3adcf8fSFrançois Tigeot PIPE_CONTROL_WRITE_FLUSH | 767e3adcf8fSFrançois Tigeot PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE); 768e3adcf8fSFrançois Tigeot intel_ring_emit(ring, pc->gtt_offset | PIPE_CONTROL_GLOBAL_GTT); 769b5c29a34SFrançois Tigeot intel_ring_emit(ring, ring->outstanding_lazy_request); 770e3adcf8fSFrançois Tigeot intel_ring_emit(ring, 0); 771e3adcf8fSFrançois Tigeot PIPE_CONTROL_FLUSH(ring, scratch_addr); 772e3adcf8fSFrançois Tigeot scratch_addr += 128; /* write to separate cachelines */ 773e3adcf8fSFrançois Tigeot PIPE_CONTROL_FLUSH(ring, scratch_addr); 774e3adcf8fSFrançois Tigeot scratch_addr += 128; 775e3adcf8fSFrançois Tigeot PIPE_CONTROL_FLUSH(ring, scratch_addr); 776e3adcf8fSFrançois Tigeot scratch_addr += 128; 777e3adcf8fSFrançois Tigeot PIPE_CONTROL_FLUSH(ring, scratch_addr); 778e3adcf8fSFrançois Tigeot scratch_addr += 128; 779e3adcf8fSFrançois Tigeot PIPE_CONTROL_FLUSH(ring, scratch_addr); 780e3adcf8fSFrançois Tigeot scratch_addr += 128; 781e3adcf8fSFrançois Tigeot PIPE_CONTROL_FLUSH(ring, scratch_addr); 782b5c29a34SFrançois Tigeot 783e3adcf8fSFrançois Tigeot intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(4) | PIPE_CONTROL_QW_WRITE | 784e3adcf8fSFrançois Tigeot PIPE_CONTROL_WRITE_FLUSH | 785e3adcf8fSFrançois Tigeot PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE | 786e3adcf8fSFrançois Tigeot PIPE_CONTROL_NOTIFY); 787e3adcf8fSFrançois Tigeot intel_ring_emit(ring, pc->gtt_offset | PIPE_CONTROL_GLOBAL_GTT); 788b5c29a34SFrançois Tigeot intel_ring_emit(ring, ring->outstanding_lazy_request); 789e3adcf8fSFrançois Tigeot intel_ring_emit(ring, 0); 790e3adcf8fSFrançois Tigeot intel_ring_advance(ring); 791e3adcf8fSFrançois Tigeot 792e3adcf8fSFrançois Tigeot return 0; 793e3adcf8fSFrançois Tigeot } 794e3adcf8fSFrançois Tigeot 795e3adcf8fSFrançois Tigeot static u32 796b030f26bSFrançois Tigeot gen6_ring_get_seqno(struct intel_ring_buffer *ring, bool lazy_coherency) 797e3adcf8fSFrançois Tigeot { 798e3adcf8fSFrançois Tigeot /* Workaround to force correct ordering between irq and seqno writes on 799e3adcf8fSFrançois Tigeot * ivb (and maybe also on snb) by reading from a CS register (like 800e3adcf8fSFrançois Tigeot * ACTHD) before reading the status page. */ 801b030f26bSFrançois Tigeot if (!lazy_coherency) 802e3adcf8fSFrançois Tigeot intel_ring_get_active_head(ring); 803e3adcf8fSFrançois Tigeot return intel_read_status_page(ring, I915_GEM_HWS_INDEX); 804e3adcf8fSFrançois Tigeot } 805e3adcf8fSFrançois Tigeot 806b030f26bSFrançois Tigeot static u32 807b030f26bSFrançois Tigeot ring_get_seqno(struct intel_ring_buffer *ring, bool lazy_coherency) 808e3adcf8fSFrançois Tigeot { 809e3adcf8fSFrançois Tigeot return intel_read_status_page(ring, I915_GEM_HWS_INDEX); 810e3adcf8fSFrançois Tigeot } 811e3adcf8fSFrançois Tigeot 812a2fdbec6SFrançois Tigeot static void 813a2fdbec6SFrançois Tigeot ring_set_seqno(struct intel_ring_buffer *ring, u32 seqno) 814a2fdbec6SFrançois Tigeot { 815a2fdbec6SFrançois Tigeot intel_write_status_page(ring, I915_GEM_HWS_INDEX, seqno); 816a2fdbec6SFrançois Tigeot } 817a2fdbec6SFrançois Tigeot 818b030f26bSFrançois Tigeot static u32 819b030f26bSFrançois Tigeot pc_render_get_seqno(struct intel_ring_buffer *ring, bool lazy_coherency) 820e3adcf8fSFrançois Tigeot { 821e3adcf8fSFrançois Tigeot struct pipe_control *pc = ring->private; 822e3adcf8fSFrançois Tigeot return pc->cpu_page[0]; 823e3adcf8fSFrançois Tigeot } 824e3adcf8fSFrançois Tigeot 825a2fdbec6SFrançois Tigeot static void 826a2fdbec6SFrançois Tigeot pc_render_set_seqno(struct intel_ring_buffer *ring, u32 seqno) 827a2fdbec6SFrançois Tigeot { 828a2fdbec6SFrançois Tigeot struct pipe_control *pc = ring->private; 829a2fdbec6SFrançois Tigeot pc->cpu_page[0] = seqno; 830a2fdbec6SFrançois Tigeot } 831a2fdbec6SFrançois Tigeot 832e3adcf8fSFrançois Tigeot static bool 833686a02f1SFrançois Tigeot gen5_ring_get_irq(struct intel_ring_buffer *ring) 834e3adcf8fSFrançois Tigeot { 835e3adcf8fSFrançois Tigeot struct drm_device *dev = ring->dev; 836e3adcf8fSFrançois Tigeot drm_i915_private_t *dev_priv = dev->dev_private; 837e3adcf8fSFrançois Tigeot 838e3adcf8fSFrançois Tigeot if (!dev->irq_enabled) 839e3adcf8fSFrançois Tigeot return false; 840e3adcf8fSFrançois Tigeot 84102727ecdSFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_EXCLUSIVE); 8425d0b1887SFrançois Tigeot if (ring->irq_refcount.gt++ == 0) { 843686a02f1SFrançois Tigeot dev_priv->gt_irq_mask &= ~ring->irq_enable_mask; 844686a02f1SFrançois Tigeot I915_WRITE(GTIMR, dev_priv->gt_irq_mask); 845686a02f1SFrançois Tigeot POSTING_READ(GTIMR); 846e3adcf8fSFrançois Tigeot } 84702727ecdSFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_RELEASE); 848e3adcf8fSFrançois Tigeot 849e3adcf8fSFrançois Tigeot return true; 850e3adcf8fSFrançois Tigeot } 851e3adcf8fSFrançois Tigeot 852e3adcf8fSFrançois Tigeot static void 853686a02f1SFrançois Tigeot gen5_ring_put_irq(struct intel_ring_buffer *ring) 854e3adcf8fSFrançois Tigeot { 855e3adcf8fSFrançois Tigeot struct drm_device *dev = ring->dev; 856e3adcf8fSFrançois Tigeot drm_i915_private_t *dev_priv = dev->dev_private; 857e3adcf8fSFrançois Tigeot 85802727ecdSFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_EXCLUSIVE); 8595d0b1887SFrançois Tigeot if (--ring->irq_refcount.gt == 0) { 860686a02f1SFrançois Tigeot dev_priv->gt_irq_mask |= ring->irq_enable_mask; 861686a02f1SFrançois Tigeot I915_WRITE(GTIMR, dev_priv->gt_irq_mask); 862686a02f1SFrançois Tigeot POSTING_READ(GTIMR); 863686a02f1SFrançois Tigeot } 864686a02f1SFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_RELEASE); 865686a02f1SFrançois Tigeot } 866686a02f1SFrançois Tigeot 867686a02f1SFrançois Tigeot static bool 868686a02f1SFrançois Tigeot i9xx_ring_get_irq(struct intel_ring_buffer *ring) 869686a02f1SFrançois Tigeot { 870686a02f1SFrançois Tigeot struct drm_device *dev = ring->dev; 871686a02f1SFrançois Tigeot drm_i915_private_t *dev_priv = dev->dev_private; 872686a02f1SFrançois Tigeot 873686a02f1SFrançois Tigeot if (!dev->irq_enabled) 874686a02f1SFrançois Tigeot return false; 875686a02f1SFrançois Tigeot 876686a02f1SFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_EXCLUSIVE); 8775d0b1887SFrançois Tigeot if (ring->irq_refcount.gt++ == 0) { 878686a02f1SFrançois Tigeot dev_priv->irq_mask &= ~ring->irq_enable_mask; 879686a02f1SFrançois Tigeot I915_WRITE(IMR, dev_priv->irq_mask); 880686a02f1SFrançois Tigeot POSTING_READ(IMR); 881686a02f1SFrançois Tigeot } 882686a02f1SFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_RELEASE); 883686a02f1SFrançois Tigeot 884686a02f1SFrançois Tigeot return true; 885686a02f1SFrançois Tigeot } 886686a02f1SFrançois Tigeot 887686a02f1SFrançois Tigeot static void 888686a02f1SFrançois Tigeot i9xx_ring_put_irq(struct intel_ring_buffer *ring) 889686a02f1SFrançois Tigeot { 890686a02f1SFrançois Tigeot struct drm_device *dev = ring->dev; 891686a02f1SFrançois Tigeot drm_i915_private_t *dev_priv = dev->dev_private; 892686a02f1SFrançois Tigeot 893686a02f1SFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_EXCLUSIVE); 8945d0b1887SFrançois Tigeot if (--ring->irq_refcount.gt == 0) { 895686a02f1SFrançois Tigeot dev_priv->irq_mask |= ring->irq_enable_mask; 896686a02f1SFrançois Tigeot I915_WRITE(IMR, dev_priv->irq_mask); 897686a02f1SFrançois Tigeot POSTING_READ(IMR); 898686a02f1SFrançois Tigeot } 899686a02f1SFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_RELEASE); 900686a02f1SFrançois Tigeot } 901686a02f1SFrançois Tigeot 902686a02f1SFrançois Tigeot static bool 903686a02f1SFrançois Tigeot i8xx_ring_get_irq(struct intel_ring_buffer *ring) 904686a02f1SFrançois Tigeot { 905686a02f1SFrançois Tigeot struct drm_device *dev = ring->dev; 906686a02f1SFrançois Tigeot drm_i915_private_t *dev_priv = dev->dev_private; 907686a02f1SFrançois Tigeot 908686a02f1SFrançois Tigeot if (!dev->irq_enabled) 909686a02f1SFrançois Tigeot return false; 910686a02f1SFrançois Tigeot 911686a02f1SFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_EXCLUSIVE); 9125d0b1887SFrançois Tigeot if (ring->irq_refcount.gt++ == 0) { 913686a02f1SFrançois Tigeot dev_priv->irq_mask &= ~ring->irq_enable_mask; 914686a02f1SFrançois Tigeot I915_WRITE16(IMR, dev_priv->irq_mask); 915686a02f1SFrançois Tigeot POSTING_READ16(IMR); 916686a02f1SFrançois Tigeot } 917686a02f1SFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_RELEASE); 918686a02f1SFrançois Tigeot 919686a02f1SFrançois Tigeot return true; 920686a02f1SFrançois Tigeot } 921686a02f1SFrançois Tigeot 922686a02f1SFrançois Tigeot static void 923686a02f1SFrançois Tigeot i8xx_ring_put_irq(struct intel_ring_buffer *ring) 924686a02f1SFrançois Tigeot { 925686a02f1SFrançois Tigeot struct drm_device *dev = ring->dev; 926686a02f1SFrançois Tigeot drm_i915_private_t *dev_priv = dev->dev_private; 927686a02f1SFrançois Tigeot 928686a02f1SFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_EXCLUSIVE); 9295d0b1887SFrançois Tigeot if (--ring->irq_refcount.gt == 0) { 930686a02f1SFrançois Tigeot dev_priv->irq_mask |= ring->irq_enable_mask; 931686a02f1SFrançois Tigeot I915_WRITE16(IMR, dev_priv->irq_mask); 932686a02f1SFrançois Tigeot POSTING_READ16(IMR); 933e3adcf8fSFrançois Tigeot } 93402727ecdSFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_RELEASE); 935e3adcf8fSFrançois Tigeot } 936e3adcf8fSFrançois Tigeot 937e3adcf8fSFrançois Tigeot void intel_ring_setup_status_page(struct intel_ring_buffer *ring) 938e3adcf8fSFrançois Tigeot { 939e3adcf8fSFrançois Tigeot struct drm_device *dev = ring->dev; 940b5c29a34SFrançois Tigeot drm_i915_private_t *dev_priv = ring->dev->dev_private; 941b5c29a34SFrançois Tigeot u32 mmio = 0; 942e3adcf8fSFrançois Tigeot 943e3adcf8fSFrançois Tigeot /* The ring status page addresses are no longer next to the rest of 944e3adcf8fSFrançois Tigeot * the ring registers as of gen7. 945e3adcf8fSFrançois Tigeot */ 946e3adcf8fSFrançois Tigeot if (IS_GEN7(dev)) { 947e3adcf8fSFrançois Tigeot switch (ring->id) { 948e3adcf8fSFrançois Tigeot case RCS: 949e3adcf8fSFrançois Tigeot mmio = RENDER_HWS_PGA_GEN7; 950e3adcf8fSFrançois Tigeot break; 951e3adcf8fSFrançois Tigeot case BCS: 952e3adcf8fSFrançois Tigeot mmio = BLT_HWS_PGA_GEN7; 953e3adcf8fSFrançois Tigeot break; 954e3adcf8fSFrançois Tigeot case VCS: 955e3adcf8fSFrançois Tigeot mmio = BSD_HWS_PGA_GEN7; 956e3adcf8fSFrançois Tigeot break; 9575d0b1887SFrançois Tigeot case VECS: 9585d0b1887SFrançois Tigeot mmio = VEBOX_HWS_PGA_GEN7; 9595d0b1887SFrançois Tigeot break; 960e3adcf8fSFrançois Tigeot } 961b5c29a34SFrançois Tigeot } else if (IS_GEN6(ring->dev)) { 962e3adcf8fSFrançois Tigeot mmio = RING_HWS_PGA_GEN6(ring->mmio_base); 963e3adcf8fSFrançois Tigeot } else { 964e3adcf8fSFrançois Tigeot mmio = RING_HWS_PGA(ring->mmio_base); 965e3adcf8fSFrançois Tigeot } 966e3adcf8fSFrançois Tigeot 967e3adcf8fSFrançois Tigeot I915_WRITE(mmio, (u32)ring->status_page.gfx_addr); 968e3adcf8fSFrançois Tigeot POSTING_READ(mmio); 9695d0b1887SFrançois Tigeot 9705d0b1887SFrançois Tigeot /* Flush the TLB for this page */ 9715d0b1887SFrançois Tigeot if (INTEL_INFO(dev)->gen >= 6) { 9725d0b1887SFrançois Tigeot u32 reg = RING_INSTPM(ring->mmio_base); 9735d0b1887SFrançois Tigeot I915_WRITE(reg, 9745d0b1887SFrançois Tigeot _MASKED_BIT_ENABLE(INSTPM_TLB_INVALIDATE | 9755d0b1887SFrançois Tigeot INSTPM_SYNC_FLUSH)); 9765d0b1887SFrançois Tigeot if (wait_for((I915_READ(reg) & INSTPM_SYNC_FLUSH) == 0, 9775d0b1887SFrançois Tigeot 1000)) 9785d0b1887SFrançois Tigeot DRM_ERROR("%s: wait for SyncFlush to complete for TLB invalidation timed out\n", 9795d0b1887SFrançois Tigeot ring->name); 9805d0b1887SFrançois Tigeot } 981e3adcf8fSFrançois Tigeot } 982e3adcf8fSFrançois Tigeot 983e3adcf8fSFrançois Tigeot static int 984e3adcf8fSFrançois Tigeot bsd_ring_flush(struct intel_ring_buffer *ring, 985b5c29a34SFrançois Tigeot u32 invalidate_domains, 986b5c29a34SFrançois Tigeot u32 flush_domains) 987e3adcf8fSFrançois Tigeot { 988e3adcf8fSFrançois Tigeot int ret; 989e3adcf8fSFrançois Tigeot 990e3adcf8fSFrançois Tigeot ret = intel_ring_begin(ring, 2); 991e3adcf8fSFrançois Tigeot if (ret) 992e3adcf8fSFrançois Tigeot return ret; 993e3adcf8fSFrançois Tigeot 994e3adcf8fSFrançois Tigeot intel_ring_emit(ring, MI_FLUSH); 995e3adcf8fSFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 996e3adcf8fSFrançois Tigeot intel_ring_advance(ring); 997e3adcf8fSFrançois Tigeot return 0; 998e3adcf8fSFrançois Tigeot } 999e3adcf8fSFrançois Tigeot 1000e3adcf8fSFrançois Tigeot static int 1001b5c29a34SFrançois Tigeot i9xx_add_request(struct intel_ring_buffer *ring) 1002e3adcf8fSFrançois Tigeot { 1003e3adcf8fSFrançois Tigeot int ret; 1004e3adcf8fSFrançois Tigeot 1005e3adcf8fSFrançois Tigeot ret = intel_ring_begin(ring, 4); 1006e3adcf8fSFrançois Tigeot if (ret) 1007e3adcf8fSFrançois Tigeot return ret; 1008e3adcf8fSFrançois Tigeot 1009e3adcf8fSFrançois Tigeot intel_ring_emit(ring, MI_STORE_DWORD_INDEX); 1010e3adcf8fSFrançois Tigeot intel_ring_emit(ring, I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT); 1011b5c29a34SFrançois Tigeot intel_ring_emit(ring, ring->outstanding_lazy_request); 1012e3adcf8fSFrançois Tigeot intel_ring_emit(ring, MI_USER_INTERRUPT); 1013e3adcf8fSFrançois Tigeot intel_ring_advance(ring); 1014e3adcf8fSFrançois Tigeot 1015e3adcf8fSFrançois Tigeot return 0; 1016e3adcf8fSFrançois Tigeot } 1017e3adcf8fSFrançois Tigeot 1018e3adcf8fSFrançois Tigeot static bool 1019686a02f1SFrançois Tigeot gen6_ring_get_irq(struct intel_ring_buffer *ring) 1020e3adcf8fSFrançois Tigeot { 1021e3adcf8fSFrançois Tigeot struct drm_device *dev = ring->dev; 1022e3adcf8fSFrançois Tigeot drm_i915_private_t *dev_priv = dev->dev_private; 1023e3adcf8fSFrançois Tigeot 1024e3adcf8fSFrançois Tigeot if (!dev->irq_enabled) 1025e3adcf8fSFrançois Tigeot return false; 1026e3adcf8fSFrançois Tigeot 1027686a02f1SFrançois Tigeot /* It looks like we need to prevent the gt from suspending while waiting 1028686a02f1SFrançois Tigeot * for an notifiy irq, otherwise irqs seem to get lost on at least the 1029686a02f1SFrançois Tigeot * blt/bsd rings on ivb. */ 1030e3adcf8fSFrançois Tigeot gen6_gt_force_wake_get(dev_priv); 1031e3adcf8fSFrançois Tigeot 103202727ecdSFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_EXCLUSIVE); 10335d0b1887SFrançois Tigeot if (ring->irq_refcount.gt++ == 0) { 1034686a02f1SFrançois Tigeot if (HAS_L3_GPU_CACHE(dev) && ring->id == RCS) 10355d0b1887SFrançois Tigeot I915_WRITE_IMR(ring, 10365d0b1887SFrançois Tigeot ~(ring->irq_enable_mask | 10375d0b1887SFrançois Tigeot GT_RENDER_L3_PARITY_ERROR_INTERRUPT)); 1038686a02f1SFrançois Tigeot else 1039686a02f1SFrançois Tigeot I915_WRITE_IMR(ring, ~ring->irq_enable_mask); 1040686a02f1SFrançois Tigeot dev_priv->gt_irq_mask &= ~ring->irq_enable_mask; 1041686a02f1SFrançois Tigeot I915_WRITE(GTIMR, dev_priv->gt_irq_mask); 1042686a02f1SFrançois Tigeot POSTING_READ(GTIMR); 1043e3adcf8fSFrançois Tigeot } 104402727ecdSFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_RELEASE); 1045e3adcf8fSFrançois Tigeot 1046e3adcf8fSFrançois Tigeot return true; 1047e3adcf8fSFrançois Tigeot } 1048e3adcf8fSFrançois Tigeot 1049e3adcf8fSFrançois Tigeot static void 1050686a02f1SFrançois Tigeot gen6_ring_put_irq(struct intel_ring_buffer *ring) 1051e3adcf8fSFrançois Tigeot { 1052e3adcf8fSFrançois Tigeot struct drm_device *dev = ring->dev; 1053e3adcf8fSFrançois Tigeot drm_i915_private_t *dev_priv = dev->dev_private; 1054e3adcf8fSFrançois Tigeot 105502727ecdSFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_EXCLUSIVE); 10565d0b1887SFrançois Tigeot if (--ring->irq_refcount.gt == 0) { 1057686a02f1SFrançois Tigeot if (HAS_L3_GPU_CACHE(dev) && ring->id == RCS) 10585d0b1887SFrançois Tigeot I915_WRITE_IMR(ring, 10595d0b1887SFrançois Tigeot ~GT_RENDER_L3_PARITY_ERROR_INTERRUPT); 1060686a02f1SFrançois Tigeot else 1061686a02f1SFrançois Tigeot I915_WRITE_IMR(ring, ~0); 1062686a02f1SFrançois Tigeot dev_priv->gt_irq_mask |= ring->irq_enable_mask; 1063686a02f1SFrançois Tigeot I915_WRITE(GTIMR, dev_priv->gt_irq_mask); 1064686a02f1SFrançois Tigeot POSTING_READ(GTIMR); 1065e3adcf8fSFrançois Tigeot } 106602727ecdSFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_RELEASE); 1067e3adcf8fSFrançois Tigeot 1068e3adcf8fSFrançois Tigeot gen6_gt_force_wake_put(dev_priv); 1069e3adcf8fSFrançois Tigeot } 1070e3adcf8fSFrançois Tigeot 10715d0b1887SFrançois Tigeot static bool 10725d0b1887SFrançois Tigeot hsw_vebox_get_irq(struct intel_ring_buffer *ring) 10735d0b1887SFrançois Tigeot { 10745d0b1887SFrançois Tigeot struct drm_device *dev = ring->dev; 10755d0b1887SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 10765d0b1887SFrançois Tigeot 10775d0b1887SFrançois Tigeot if (!dev->irq_enabled) 10785d0b1887SFrançois Tigeot return false; 10795d0b1887SFrançois Tigeot 10805d0b1887SFrançois Tigeot lockmgr(&dev_priv->rps.lock, LK_EXCLUSIVE); 10815d0b1887SFrançois Tigeot if (ring->irq_refcount.pm++ == 0) { 10825d0b1887SFrançois Tigeot u32 pm_imr = I915_READ(GEN6_PMIMR); 10835d0b1887SFrançois Tigeot I915_WRITE_IMR(ring, ~ring->irq_enable_mask); 10845d0b1887SFrançois Tigeot I915_WRITE(GEN6_PMIMR, pm_imr & ~ring->irq_enable_mask); 10855d0b1887SFrançois Tigeot POSTING_READ(GEN6_PMIMR); 10865d0b1887SFrançois Tigeot } 10875d0b1887SFrançois Tigeot lockmgr(&dev_priv->rps.lock, LK_RELEASE); 10885d0b1887SFrançois Tigeot 10895d0b1887SFrançois Tigeot return true; 10905d0b1887SFrançois Tigeot } 10915d0b1887SFrançois Tigeot 10925d0b1887SFrançois Tigeot static void 10935d0b1887SFrançois Tigeot hsw_vebox_put_irq(struct intel_ring_buffer *ring) 10945d0b1887SFrançois Tigeot { 10955d0b1887SFrançois Tigeot struct drm_device *dev = ring->dev; 10965d0b1887SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 10975d0b1887SFrançois Tigeot 10985d0b1887SFrançois Tigeot if (!dev->irq_enabled) 10995d0b1887SFrançois Tigeot return; 11005d0b1887SFrançois Tigeot 11015d0b1887SFrançois Tigeot lockmgr(&dev_priv->rps.lock, LK_EXCLUSIVE); 11025d0b1887SFrançois Tigeot if (--ring->irq_refcount.pm == 0) { 11035d0b1887SFrançois Tigeot u32 pm_imr = I915_READ(GEN6_PMIMR); 11045d0b1887SFrançois Tigeot I915_WRITE_IMR(ring, ~0); 11055d0b1887SFrançois Tigeot I915_WRITE(GEN6_PMIMR, pm_imr | ring->irq_enable_mask); 11065d0b1887SFrançois Tigeot POSTING_READ(GEN6_PMIMR); 11075d0b1887SFrançois Tigeot } 11085d0b1887SFrançois Tigeot lockmgr(&dev_priv->rps.lock, LK_RELEASE); 11095d0b1887SFrançois Tigeot } 11105d0b1887SFrançois Tigeot 1111e3adcf8fSFrançois Tigeot static int 1112b5c29a34SFrançois Tigeot i965_dispatch_execbuffer(struct intel_ring_buffer *ring, 1113b5c29a34SFrançois Tigeot u32 offset, u32 length, 1114b5c29a34SFrançois Tigeot unsigned flags) 1115e3adcf8fSFrançois Tigeot { 1116e3adcf8fSFrançois Tigeot int ret; 1117e3adcf8fSFrançois Tigeot 1118e3adcf8fSFrançois Tigeot ret = intel_ring_begin(ring, 2); 1119e3adcf8fSFrançois Tigeot if (ret) 1120e3adcf8fSFrançois Tigeot return ret; 1121e3adcf8fSFrançois Tigeot 1122e3adcf8fSFrançois Tigeot intel_ring_emit(ring, 1123686a02f1SFrançois Tigeot MI_BATCH_BUFFER_START | 1124b5c29a34SFrançois Tigeot MI_BATCH_GTT | 1125b5c29a34SFrançois Tigeot (flags & I915_DISPATCH_SECURE ? 0 : MI_BATCH_NON_SECURE_I965)); 1126e3adcf8fSFrançois Tigeot intel_ring_emit(ring, offset); 1127e3adcf8fSFrançois Tigeot intel_ring_advance(ring); 1128e3adcf8fSFrançois Tigeot 1129e3adcf8fSFrançois Tigeot return 0; 1130e3adcf8fSFrançois Tigeot } 1131e3adcf8fSFrançois Tigeot 1132b5c29a34SFrançois Tigeot /* Just userspace ABI convention to limit the wa batch bo to a resonable size */ 1133b5c29a34SFrançois Tigeot #define I830_BATCH_LIMIT (256*1024) 1134e3adcf8fSFrançois Tigeot static int 1135686a02f1SFrançois Tigeot i830_dispatch_execbuffer(struct intel_ring_buffer *ring, 1136b5c29a34SFrançois Tigeot u32 offset, u32 len, 1137b5c29a34SFrançois Tigeot unsigned flags) 1138e3adcf8fSFrançois Tigeot { 1139e3adcf8fSFrançois Tigeot int ret; 1140e3adcf8fSFrançois Tigeot 1141b5c29a34SFrançois Tigeot if (flags & I915_DISPATCH_PINNED) { 1142e3adcf8fSFrançois Tigeot ret = intel_ring_begin(ring, 4); 1143e3adcf8fSFrançois Tigeot if (ret) 1144e3adcf8fSFrançois Tigeot return ret; 1145e3adcf8fSFrançois Tigeot 1146e3adcf8fSFrançois Tigeot intel_ring_emit(ring, MI_BATCH_BUFFER); 1147b5c29a34SFrançois Tigeot intel_ring_emit(ring, offset | (flags & I915_DISPATCH_SECURE ? 0 : MI_BATCH_NON_SECURE)); 1148e3adcf8fSFrançois Tigeot intel_ring_emit(ring, offset + len - 8); 1149b5c29a34SFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 1150686a02f1SFrançois Tigeot intel_ring_advance(ring); 1151b5c29a34SFrançois Tigeot } else { 1152b5c29a34SFrançois Tigeot struct drm_i915_gem_object *obj = ring->private; 1153b5c29a34SFrançois Tigeot u32 cs_offset = obj->gtt_offset; 1154b5c29a34SFrançois Tigeot 1155b5c29a34SFrançois Tigeot if (len > I830_BATCH_LIMIT) 1156b5c29a34SFrançois Tigeot return -ENOSPC; 1157b5c29a34SFrançois Tigeot 1158b5c29a34SFrançois Tigeot ret = intel_ring_begin(ring, 9+3); 1159b5c29a34SFrançois Tigeot if (ret) 1160b5c29a34SFrançois Tigeot return ret; 1161b5c29a34SFrançois Tigeot /* Blit the batch (which has now all relocs applied) to the stable batch 1162b5c29a34SFrançois Tigeot * scratch bo area (so that the CS never stumbles over its tlb 1163b5c29a34SFrançois Tigeot * invalidation bug) ... */ 1164b5c29a34SFrançois Tigeot intel_ring_emit(ring, XY_SRC_COPY_BLT_CMD | 1165b5c29a34SFrançois Tigeot XY_SRC_COPY_BLT_WRITE_ALPHA | 1166b5c29a34SFrançois Tigeot XY_SRC_COPY_BLT_WRITE_RGB); 1167b5c29a34SFrançois Tigeot intel_ring_emit(ring, BLT_DEPTH_32 | BLT_ROP_GXCOPY | 4096); 1168b5c29a34SFrançois Tigeot intel_ring_emit(ring, 0); 1169b5c29a34SFrançois Tigeot intel_ring_emit(ring, (DIV_ROUND_UP(len, 4096) << 16) | 1024); 1170b5c29a34SFrançois Tigeot intel_ring_emit(ring, cs_offset); 1171b5c29a34SFrançois Tigeot intel_ring_emit(ring, 0); 1172b5c29a34SFrançois Tigeot intel_ring_emit(ring, 4096); 1173b5c29a34SFrançois Tigeot intel_ring_emit(ring, offset); 1174b5c29a34SFrançois Tigeot intel_ring_emit(ring, MI_FLUSH); 1175b5c29a34SFrançois Tigeot 1176b5c29a34SFrançois Tigeot /* ... and execute it. */ 1177b5c29a34SFrançois Tigeot intel_ring_emit(ring, MI_BATCH_BUFFER); 1178b5c29a34SFrançois Tigeot intel_ring_emit(ring, cs_offset | (flags & I915_DISPATCH_SECURE ? 0 : MI_BATCH_NON_SECURE)); 1179b5c29a34SFrançois Tigeot intel_ring_emit(ring, cs_offset + len - 8); 1180b5c29a34SFrançois Tigeot intel_ring_advance(ring); 1181b5c29a34SFrançois Tigeot } 1182686a02f1SFrançois Tigeot 1183686a02f1SFrançois Tigeot return 0; 1184686a02f1SFrançois Tigeot } 1185686a02f1SFrançois Tigeot 1186686a02f1SFrançois Tigeot static int 1187686a02f1SFrançois Tigeot i915_dispatch_execbuffer(struct intel_ring_buffer *ring, 1188b5c29a34SFrançois Tigeot u32 offset, u32 len, 1189b5c29a34SFrançois Tigeot unsigned flags) 1190686a02f1SFrançois Tigeot { 1191686a02f1SFrançois Tigeot int ret; 1192686a02f1SFrançois Tigeot 1193e3adcf8fSFrançois Tigeot ret = intel_ring_begin(ring, 2); 1194e3adcf8fSFrançois Tigeot if (ret) 1195e3adcf8fSFrançois Tigeot return ret; 1196e3adcf8fSFrançois Tigeot 1197686a02f1SFrançois Tigeot intel_ring_emit(ring, MI_BATCH_BUFFER_START | MI_BATCH_GTT); 1198686a02f1SFrançois Tigeot intel_ring_emit(ring, offset | (flags & I915_DISPATCH_SECURE ? 0 : MI_BATCH_NON_SECURE)); 1199e3adcf8fSFrançois Tigeot intel_ring_advance(ring); 1200e3adcf8fSFrançois Tigeot 1201e3adcf8fSFrançois Tigeot return 0; 1202e3adcf8fSFrançois Tigeot } 1203e3adcf8fSFrançois Tigeot 1204e3adcf8fSFrançois Tigeot static void cleanup_status_page(struct intel_ring_buffer *ring) 1205e3adcf8fSFrançois Tigeot { 1206e3adcf8fSFrançois Tigeot struct drm_i915_gem_object *obj; 1207e3adcf8fSFrançois Tigeot 1208e3adcf8fSFrançois Tigeot obj = ring->status_page.obj; 1209e3adcf8fSFrançois Tigeot if (obj == NULL) 1210e3adcf8fSFrançois Tigeot return; 1211e3adcf8fSFrançois Tigeot 1212e3adcf8fSFrançois Tigeot pmap_qremove((vm_offset_t)ring->status_page.page_addr, 1); 1213e3adcf8fSFrançois Tigeot kmem_free(&kernel_map, (vm_offset_t)ring->status_page.page_addr, 1214e3adcf8fSFrançois Tigeot PAGE_SIZE); 1215e3adcf8fSFrançois Tigeot i915_gem_object_unpin(obj); 1216e3adcf8fSFrançois Tigeot drm_gem_object_unreference(&obj->base); 1217e3adcf8fSFrançois Tigeot ring->status_page.obj = NULL; 1218e3adcf8fSFrançois Tigeot } 1219e3adcf8fSFrançois Tigeot 1220e3adcf8fSFrançois Tigeot static int init_status_page(struct intel_ring_buffer *ring) 1221e3adcf8fSFrançois Tigeot { 1222e3adcf8fSFrançois Tigeot struct drm_device *dev = ring->dev; 1223e3adcf8fSFrançois Tigeot struct drm_i915_gem_object *obj; 1224e3adcf8fSFrançois Tigeot int ret; 1225e3adcf8fSFrançois Tigeot 1226e3adcf8fSFrançois Tigeot obj = i915_gem_alloc_object(dev, 4096); 1227e3adcf8fSFrançois Tigeot if (obj == NULL) { 1228e3adcf8fSFrançois Tigeot DRM_ERROR("Failed to allocate status page\n"); 1229e3adcf8fSFrançois Tigeot ret = -ENOMEM; 1230e3adcf8fSFrançois Tigeot goto err; 1231e3adcf8fSFrançois Tigeot } 1232e3adcf8fSFrançois Tigeot 1233e3adcf8fSFrançois Tigeot i915_gem_object_set_cache_level(obj, I915_CACHE_LLC); 1234e3adcf8fSFrançois Tigeot 1235b00bc81cSFrançois Tigeot ret = i915_gem_object_pin(obj, 4096, true, false); 1236e3adcf8fSFrançois Tigeot if (ret != 0) { 1237e3adcf8fSFrançois Tigeot goto err_unref; 1238e3adcf8fSFrançois Tigeot } 1239e3adcf8fSFrançois Tigeot 1240e3adcf8fSFrançois Tigeot ring->status_page.gfx_addr = obj->gtt_offset; 1241*f4f90b23SFrançois Tigeot ring->status_page.page_addr = kmap(obj->pages[0]); 1242e3adcf8fSFrançois Tigeot if (ring->status_page.page_addr == NULL) { 1243686a02f1SFrançois Tigeot ret = -ENOMEM; 1244e3adcf8fSFrançois Tigeot goto err_unpin; 1245e3adcf8fSFrançois Tigeot } 1246a2fdbec6SFrançois Tigeot pmap_qenter((vm_offset_t)ring->status_page.page_addr, &obj->pages[0], 1); 1247e3adcf8fSFrançois Tigeot pmap_invalidate_cache_range((vm_offset_t)ring->status_page.page_addr, 1248e3adcf8fSFrançois Tigeot (vm_offset_t)ring->status_page.page_addr + PAGE_SIZE); 1249e3adcf8fSFrançois Tigeot ring->status_page.obj = obj; 1250e3adcf8fSFrançois Tigeot memset(ring->status_page.page_addr, 0, PAGE_SIZE); 1251e3adcf8fSFrançois Tigeot 1252b5c29a34SFrançois Tigeot DRM_DEBUG_DRIVER("%s hws offset: 0x%08x\n", 1253e3adcf8fSFrançois Tigeot ring->name, ring->status_page.gfx_addr); 1254e3adcf8fSFrançois Tigeot 1255e3adcf8fSFrançois Tigeot return 0; 1256e3adcf8fSFrançois Tigeot 1257e3adcf8fSFrançois Tigeot err_unpin: 1258e3adcf8fSFrançois Tigeot i915_gem_object_unpin(obj); 1259e3adcf8fSFrançois Tigeot err_unref: 1260e3adcf8fSFrançois Tigeot drm_gem_object_unreference(&obj->base); 1261e3adcf8fSFrançois Tigeot err: 1262e3adcf8fSFrançois Tigeot return ret; 1263e3adcf8fSFrançois Tigeot } 1264e3adcf8fSFrançois Tigeot 12655d0b1887SFrançois Tigeot static int init_phys_status_page(struct intel_ring_buffer *ring) 1266686a02f1SFrançois Tigeot { 1267686a02f1SFrançois Tigeot struct drm_i915_private *dev_priv = ring->dev->dev_private; 1268686a02f1SFrançois Tigeot 1269686a02f1SFrançois Tigeot if (!dev_priv->status_page_dmah) { 1270686a02f1SFrançois Tigeot dev_priv->status_page_dmah = 1271b31e9d59SFrançois Tigeot drm_pci_alloc(ring->dev, PAGE_SIZE, PAGE_SIZE); 1272686a02f1SFrançois Tigeot if (!dev_priv->status_page_dmah) 1273686a02f1SFrançois Tigeot return -ENOMEM; 1274686a02f1SFrançois Tigeot } 1275686a02f1SFrançois Tigeot 1276686a02f1SFrançois Tigeot ring->status_page.page_addr = dev_priv->status_page_dmah->vaddr; 1277686a02f1SFrançois Tigeot memset(ring->status_page.page_addr, 0, PAGE_SIZE); 1278686a02f1SFrançois Tigeot 1279686a02f1SFrançois Tigeot return 0; 1280686a02f1SFrançois Tigeot } 1281686a02f1SFrançois Tigeot 1282b030f26bSFrançois Tigeot static int intel_init_ring_buffer(struct drm_device *dev, 1283e3adcf8fSFrançois Tigeot struct intel_ring_buffer *ring) 1284e3adcf8fSFrançois Tigeot { 1285e3adcf8fSFrançois Tigeot struct drm_i915_gem_object *obj; 1286e3adcf8fSFrançois Tigeot int ret; 1287e3adcf8fSFrançois Tigeot 1288e3adcf8fSFrançois Tigeot ring->dev = dev; 1289e3adcf8fSFrançois Tigeot INIT_LIST_HEAD(&ring->active_list); 1290e3adcf8fSFrançois Tigeot INIT_LIST_HEAD(&ring->request_list); 1291686a02f1SFrançois Tigeot ring->size = 32 * PAGE_SIZE; 1292686a02f1SFrançois Tigeot memset(ring->sync_seqno, 0, sizeof(ring->sync_seqno)); 1293e3adcf8fSFrançois Tigeot 1294b030f26bSFrançois Tigeot init_waitqueue_head(&ring->irq_queue); 1295b030f26bSFrançois Tigeot 1296e3adcf8fSFrançois Tigeot if (I915_NEED_GFX_HWS(dev)) { 1297e3adcf8fSFrançois Tigeot ret = init_status_page(ring); 1298e3adcf8fSFrançois Tigeot if (ret) 1299e3adcf8fSFrançois Tigeot return ret; 1300686a02f1SFrançois Tigeot } else { 1301686a02f1SFrançois Tigeot BUG_ON(ring->id != RCS); 13025d0b1887SFrançois Tigeot ret = init_phys_status_page(ring); 1303686a02f1SFrançois Tigeot if (ret) 1304686a02f1SFrançois Tigeot return ret; 1305e3adcf8fSFrançois Tigeot } 1306e3adcf8fSFrançois Tigeot 1307a2fdbec6SFrançois Tigeot obj = NULL; 1308a2fdbec6SFrançois Tigeot if (!HAS_LLC(dev)) 1309a2fdbec6SFrançois Tigeot obj = i915_gem_alloc_object(dev, ring->size); 1310a2fdbec6SFrançois Tigeot if (obj == NULL) 1311e3adcf8fSFrançois Tigeot obj = i915_gem_alloc_object(dev, ring->size); 1312e3adcf8fSFrançois Tigeot if (obj == NULL) { 1313e3adcf8fSFrançois Tigeot DRM_ERROR("Failed to allocate ringbuffer\n"); 1314e3adcf8fSFrançois Tigeot ret = -ENOMEM; 1315e3adcf8fSFrançois Tigeot goto err_hws; 1316e3adcf8fSFrançois Tigeot } 1317e3adcf8fSFrançois Tigeot 1318e3adcf8fSFrançois Tigeot ring->obj = obj; 1319e3adcf8fSFrançois Tigeot 1320b00bc81cSFrançois Tigeot ret = i915_gem_object_pin(obj, PAGE_SIZE, true, false); 1321e3adcf8fSFrançois Tigeot if (ret) 1322e3adcf8fSFrançois Tigeot goto err_unref; 1323e3adcf8fSFrançois Tigeot 1324686a02f1SFrançois Tigeot ret = i915_gem_object_set_to_gtt_domain(obj, true); 1325686a02f1SFrançois Tigeot if (ret) 1326686a02f1SFrançois Tigeot goto err_unpin; 1327e3adcf8fSFrançois Tigeot 1328a2fdbec6SFrançois Tigeot ring->virtual_start = 1329a2fdbec6SFrançois Tigeot ioremap_wc(dev->agp->base + obj->gtt_offset, 1330686a02f1SFrançois Tigeot ring->size); 1331686a02f1SFrançois Tigeot if (ring->virtual_start == NULL) { 1332e3adcf8fSFrançois Tigeot DRM_ERROR("Failed to map ringbuffer.\n"); 1333e3adcf8fSFrançois Tigeot ret = -EINVAL; 1334e3adcf8fSFrançois Tigeot goto err_unpin; 1335e3adcf8fSFrançois Tigeot } 1336e3adcf8fSFrançois Tigeot 1337e3adcf8fSFrançois Tigeot ret = ring->init(ring); 1338e3adcf8fSFrançois Tigeot if (ret) 1339e3adcf8fSFrançois Tigeot goto err_unmap; 1340e3adcf8fSFrançois Tigeot 1341e3adcf8fSFrançois Tigeot /* Workaround an erratum on the i830 which causes a hang if 1342e3adcf8fSFrançois Tigeot * the TAIL pointer points to within the last 2 cachelines 1343e3adcf8fSFrançois Tigeot * of the buffer. 1344e3adcf8fSFrançois Tigeot */ 1345e3adcf8fSFrançois Tigeot ring->effective_size = ring->size; 1346e3adcf8fSFrançois Tigeot if (IS_I830(ring->dev) || IS_845G(ring->dev)) 1347e3adcf8fSFrançois Tigeot ring->effective_size -= 128; 1348e3adcf8fSFrançois Tigeot 1349e3adcf8fSFrançois Tigeot return 0; 1350e3adcf8fSFrançois Tigeot 1351e3adcf8fSFrançois Tigeot err_unmap: 1352686a02f1SFrançois Tigeot pmap_unmapdev((vm_offset_t)ring->virtual_start, ring->size); 1353e3adcf8fSFrançois Tigeot err_unpin: 1354e3adcf8fSFrançois Tigeot i915_gem_object_unpin(obj); 1355e3adcf8fSFrançois Tigeot err_unref: 1356e3adcf8fSFrançois Tigeot drm_gem_object_unreference(&obj->base); 1357e3adcf8fSFrançois Tigeot ring->obj = NULL; 1358e3adcf8fSFrançois Tigeot err_hws: 1359e3adcf8fSFrançois Tigeot cleanup_status_page(ring); 1360e3adcf8fSFrançois Tigeot return ret; 1361e3adcf8fSFrançois Tigeot } 1362e3adcf8fSFrançois Tigeot 1363e3adcf8fSFrançois Tigeot void intel_cleanup_ring_buffer(struct intel_ring_buffer *ring) 1364e3adcf8fSFrançois Tigeot { 1365e3adcf8fSFrançois Tigeot struct drm_i915_private *dev_priv; 1366e3adcf8fSFrançois Tigeot int ret; 1367e3adcf8fSFrançois Tigeot 1368e3adcf8fSFrançois Tigeot if (ring->obj == NULL) 1369e3adcf8fSFrançois Tigeot return; 1370e3adcf8fSFrançois Tigeot 1371e3adcf8fSFrançois Tigeot /* Disable the ring buffer. The ring must be idle at this point */ 1372e3adcf8fSFrançois Tigeot dev_priv = ring->dev->dev_private; 1373b030f26bSFrançois Tigeot ret = intel_ring_idle(ring); 1374b030f26bSFrançois Tigeot if (ret) 1375b030f26bSFrançois Tigeot DRM_ERROR("failed to quiesce %s whilst cleaning up: %d\n", 1376b030f26bSFrançois Tigeot ring->name, ret); 1377b030f26bSFrançois Tigeot 1378e3adcf8fSFrançois Tigeot I915_WRITE_CTL(ring, 0); 1379e3adcf8fSFrançois Tigeot 1380686a02f1SFrançois Tigeot pmap_unmapdev((vm_offset_t)ring->virtual_start, ring->size); 1381e3adcf8fSFrançois Tigeot 1382e3adcf8fSFrançois Tigeot i915_gem_object_unpin(ring->obj); 1383e3adcf8fSFrançois Tigeot drm_gem_object_unreference(&ring->obj->base); 1384e3adcf8fSFrançois Tigeot ring->obj = NULL; 1385e3adcf8fSFrançois Tigeot 1386e3adcf8fSFrançois Tigeot if (ring->cleanup) 1387e3adcf8fSFrançois Tigeot ring->cleanup(ring); 1388e3adcf8fSFrançois Tigeot 1389e3adcf8fSFrançois Tigeot cleanup_status_page(ring); 1390e3adcf8fSFrançois Tigeot } 1391e3adcf8fSFrançois Tigeot 1392e3adcf8fSFrançois Tigeot static int intel_ring_wait_seqno(struct intel_ring_buffer *ring, u32 seqno) 1393e3adcf8fSFrançois Tigeot { 1394e3adcf8fSFrançois Tigeot int ret; 1395e3adcf8fSFrançois Tigeot 1396b030f26bSFrançois Tigeot ret = i915_wait_seqno(ring, seqno); 1397b030f26bSFrançois Tigeot if (!ret) 1398b030f26bSFrançois Tigeot i915_gem_retire_requests_ring(ring); 1399e3adcf8fSFrançois Tigeot 1400e3adcf8fSFrançois Tigeot return ret; 1401e3adcf8fSFrançois Tigeot } 1402e3adcf8fSFrançois Tigeot 1403e3adcf8fSFrançois Tigeot static int intel_ring_wait_request(struct intel_ring_buffer *ring, int n) 1404e3adcf8fSFrançois Tigeot { 1405e3adcf8fSFrançois Tigeot struct drm_i915_gem_request *request; 1406e3adcf8fSFrançois Tigeot u32 seqno = 0; 1407e3adcf8fSFrançois Tigeot int ret; 1408e3adcf8fSFrançois Tigeot 1409e3adcf8fSFrançois Tigeot i915_gem_retire_requests_ring(ring); 1410e3adcf8fSFrançois Tigeot 1411e3adcf8fSFrançois Tigeot if (ring->last_retired_head != -1) { 1412e3adcf8fSFrançois Tigeot ring->head = ring->last_retired_head; 1413e3adcf8fSFrançois Tigeot ring->last_retired_head = -1; 1414e3adcf8fSFrançois Tigeot ring->space = ring_space(ring); 1415e3adcf8fSFrançois Tigeot if (ring->space >= n) 1416e3adcf8fSFrançois Tigeot return 0; 1417e3adcf8fSFrançois Tigeot } 1418e3adcf8fSFrançois Tigeot 1419e3adcf8fSFrançois Tigeot list_for_each_entry(request, &ring->request_list, list) { 1420e3adcf8fSFrançois Tigeot int space; 1421e3adcf8fSFrançois Tigeot 1422e3adcf8fSFrançois Tigeot if (request->tail == -1) 1423e3adcf8fSFrançois Tigeot continue; 1424e3adcf8fSFrançois Tigeot 1425b5c29a34SFrançois Tigeot space = request->tail - (ring->tail + I915_RING_FREE_SPACE); 1426e3adcf8fSFrançois Tigeot if (space < 0) 1427e3adcf8fSFrançois Tigeot space += ring->size; 1428e3adcf8fSFrançois Tigeot if (space >= n) { 1429e3adcf8fSFrançois Tigeot seqno = request->seqno; 1430e3adcf8fSFrançois Tigeot break; 1431e3adcf8fSFrançois Tigeot } 1432e3adcf8fSFrançois Tigeot 1433e3adcf8fSFrançois Tigeot /* Consume this request in case we need more space than 1434e3adcf8fSFrançois Tigeot * is available and so need to prevent a race between 1435e3adcf8fSFrançois Tigeot * updating last_retired_head and direct reads of 1436e3adcf8fSFrançois Tigeot * I915_RING_HEAD. It also provides a nice sanity check. 1437e3adcf8fSFrançois Tigeot */ 1438e3adcf8fSFrançois Tigeot request->tail = -1; 1439e3adcf8fSFrançois Tigeot } 1440e3adcf8fSFrançois Tigeot 1441e3adcf8fSFrançois Tigeot if (seqno == 0) 1442e3adcf8fSFrançois Tigeot return -ENOSPC; 1443e3adcf8fSFrançois Tigeot 1444e3adcf8fSFrançois Tigeot ret = intel_ring_wait_seqno(ring, seqno); 1445e3adcf8fSFrançois Tigeot if (ret) 1446e3adcf8fSFrançois Tigeot return ret; 1447e3adcf8fSFrançois Tigeot 1448b5c29a34SFrançois Tigeot if (WARN_ON(ring->last_retired_head == -1)) 1449e3adcf8fSFrançois Tigeot return -ENOSPC; 1450e3adcf8fSFrançois Tigeot 1451e3adcf8fSFrançois Tigeot ring->head = ring->last_retired_head; 1452e3adcf8fSFrançois Tigeot ring->last_retired_head = -1; 1453e3adcf8fSFrançois Tigeot ring->space = ring_space(ring); 1454b5c29a34SFrançois Tigeot if (WARN_ON(ring->space < n)) 1455e3adcf8fSFrançois Tigeot return -ENOSPC; 1456e3adcf8fSFrançois Tigeot 1457e3adcf8fSFrançois Tigeot return 0; 1458e3adcf8fSFrançois Tigeot } 1459e3adcf8fSFrançois Tigeot 1460b030f26bSFrançois Tigeot static int ring_wait_for_space(struct intel_ring_buffer *ring, int n) 1461e3adcf8fSFrançois Tigeot { 1462e3adcf8fSFrançois Tigeot struct drm_device *dev = ring->dev; 1463e3adcf8fSFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 1464245593daSFrançois Tigeot unsigned long end; 1465e3adcf8fSFrançois Tigeot int ret; 1466e3adcf8fSFrançois Tigeot 1467e3adcf8fSFrançois Tigeot ret = intel_ring_wait_request(ring, n); 1468e3adcf8fSFrançois Tigeot if (ret != -ENOSPC) 1469e3adcf8fSFrançois Tigeot return ret; 1470e3adcf8fSFrançois Tigeot 1471a2fdbec6SFrançois Tigeot trace_i915_ring_wait_begin(ring); 1472e3adcf8fSFrançois Tigeot /* With GEM the hangcheck timer should kick us out of the loop, 1473e3adcf8fSFrançois Tigeot * leaving it early runs the risk of corrupting GEM state (due 1474e3adcf8fSFrançois Tigeot * to running on almost untested codepaths). But on resume 1475e3adcf8fSFrançois Tigeot * timers don't work yet, so prevent a complete hang in that 1476e3adcf8fSFrançois Tigeot * case by choosing an insanely large timeout. */ 1477e3440f96SFrançois Tigeot end = jiffies + 60 * HZ; 1478245593daSFrançois Tigeot 1479e3adcf8fSFrançois Tigeot do { 1480e3adcf8fSFrançois Tigeot ring->head = I915_READ_HEAD(ring); 1481e3adcf8fSFrançois Tigeot ring->space = ring_space(ring); 1482e3adcf8fSFrançois Tigeot if (ring->space >= n) { 1483a2fdbec6SFrançois Tigeot trace_i915_ring_wait_end(ring); 1484e3adcf8fSFrançois Tigeot return 0; 1485e3adcf8fSFrançois Tigeot } 1486e3adcf8fSFrançois Tigeot 1487e3adcf8fSFrançois Tigeot #if 0 1488e3adcf8fSFrançois Tigeot if (dev->primary->master) { 1489e3adcf8fSFrançois Tigeot struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv; 1490e3adcf8fSFrançois Tigeot if (master_priv->sarea_priv) 1491e3adcf8fSFrançois Tigeot master_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT; 1492e3adcf8fSFrançois Tigeot } 1493e3adcf8fSFrançois Tigeot #else 1494e3adcf8fSFrançois Tigeot if (dev_priv->sarea_priv) 1495e3adcf8fSFrançois Tigeot dev_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT; 1496e3adcf8fSFrançois Tigeot #endif 1497e3adcf8fSFrançois Tigeot 1498e3440f96SFrançois Tigeot msleep(1); 1499245593daSFrançois Tigeot 1500a2fdbec6SFrançois Tigeot ret = i915_gem_check_wedge(&dev_priv->gpu_error, 1501a2fdbec6SFrançois Tigeot dev_priv->mm.interruptible); 1502245593daSFrançois Tigeot if (ret) 1503245593daSFrançois Tigeot return ret; 1504e3440f96SFrançois Tigeot } while (!time_after(jiffies, end)); 1505a2fdbec6SFrançois Tigeot trace_i915_ring_wait_end(ring); 1506e3adcf8fSFrançois Tigeot return -EBUSY; 1507e3adcf8fSFrançois Tigeot } 1508e3adcf8fSFrançois Tigeot 1509b030f26bSFrançois Tigeot static int intel_wrap_ring_buffer(struct intel_ring_buffer *ring) 1510b030f26bSFrançois Tigeot { 1511b030f26bSFrançois Tigeot uint32_t __iomem *virt; 1512b030f26bSFrançois Tigeot int rem = ring->size - ring->tail; 1513b030f26bSFrançois Tigeot 1514b030f26bSFrançois Tigeot if (ring->space < rem) { 1515b030f26bSFrançois Tigeot int ret = ring_wait_for_space(ring, rem); 1516b030f26bSFrançois Tigeot if (ret) 1517b030f26bSFrançois Tigeot return ret; 1518b030f26bSFrançois Tigeot } 1519b030f26bSFrançois Tigeot 1520b030f26bSFrançois Tigeot virt = (unsigned int *)((char *)ring->virtual_start + ring->tail); 1521b030f26bSFrançois Tigeot rem /= 4; 1522b030f26bSFrançois Tigeot while (rem--) 1523686a02f1SFrançois Tigeot iowrite32(MI_NOOP, virt++); 1524b030f26bSFrançois Tigeot 1525b030f26bSFrançois Tigeot ring->tail = 0; 1526b030f26bSFrançois Tigeot ring->space = ring_space(ring); 1527b030f26bSFrançois Tigeot 1528b030f26bSFrançois Tigeot return 0; 1529b030f26bSFrançois Tigeot } 1530b030f26bSFrançois Tigeot 1531b030f26bSFrançois Tigeot int intel_ring_idle(struct intel_ring_buffer *ring) 1532b030f26bSFrançois Tigeot { 1533b5c29a34SFrançois Tigeot u32 seqno; 1534b5c29a34SFrançois Tigeot int ret; 1535b5c29a34SFrançois Tigeot 1536b5c29a34SFrançois Tigeot /* We need to add any requests required to flush the objects and ring */ 1537b5c29a34SFrançois Tigeot if (ring->outstanding_lazy_request) { 15385d0b1887SFrançois Tigeot ret = i915_add_request(ring, NULL); 1539b5c29a34SFrançois Tigeot if (ret) 1540b5c29a34SFrançois Tigeot return ret; 1541b5c29a34SFrançois Tigeot } 1542b5c29a34SFrançois Tigeot 1543b5c29a34SFrançois Tigeot /* Wait upon the last request to be completed */ 1544b5c29a34SFrançois Tigeot if (list_empty(&ring->request_list)) 1545b5c29a34SFrançois Tigeot return 0; 1546b5c29a34SFrançois Tigeot 1547b5c29a34SFrançois Tigeot seqno = list_entry(ring->request_list.prev, 1548b5c29a34SFrançois Tigeot struct drm_i915_gem_request, 1549b5c29a34SFrançois Tigeot list)->seqno; 1550b5c29a34SFrançois Tigeot 1551b5c29a34SFrançois Tigeot return i915_wait_seqno(ring, seqno); 1552b5c29a34SFrançois Tigeot } 1553b5c29a34SFrançois Tigeot 1554b5c29a34SFrançois Tigeot static int 1555b5c29a34SFrançois Tigeot intel_ring_alloc_seqno(struct intel_ring_buffer *ring) 1556b5c29a34SFrançois Tigeot { 1557b5c29a34SFrançois Tigeot if (ring->outstanding_lazy_request) 1558b5c29a34SFrançois Tigeot return 0; 1559b5c29a34SFrançois Tigeot 1560b5c29a34SFrançois Tigeot return i915_gem_get_seqno(ring->dev, &ring->outstanding_lazy_request); 1561b030f26bSFrançois Tigeot } 1562b030f26bSFrançois Tigeot 1563a2fdbec6SFrançois Tigeot static int __intel_ring_begin(struct intel_ring_buffer *ring, 1564a2fdbec6SFrançois Tigeot int bytes) 1565a2fdbec6SFrançois Tigeot { 1566a2fdbec6SFrançois Tigeot int ret; 1567a2fdbec6SFrançois Tigeot 1568a2fdbec6SFrançois Tigeot if (unlikely(ring->tail + bytes > ring->effective_size)) { 1569a2fdbec6SFrançois Tigeot ret = intel_wrap_ring_buffer(ring); 1570a2fdbec6SFrançois Tigeot if (unlikely(ret)) 1571a2fdbec6SFrançois Tigeot return ret; 1572a2fdbec6SFrançois Tigeot } 1573a2fdbec6SFrançois Tigeot 1574a2fdbec6SFrançois Tigeot if (unlikely(ring->space < bytes)) { 1575a2fdbec6SFrançois Tigeot ret = ring_wait_for_space(ring, bytes); 1576a2fdbec6SFrançois Tigeot if (unlikely(ret)) 1577a2fdbec6SFrançois Tigeot return ret; 1578a2fdbec6SFrançois Tigeot } 1579a2fdbec6SFrançois Tigeot 1580a2fdbec6SFrançois Tigeot ring->space -= bytes; 1581a2fdbec6SFrançois Tigeot return 0; 1582a2fdbec6SFrançois Tigeot } 1583a2fdbec6SFrançois Tigeot 1584e3adcf8fSFrançois Tigeot int intel_ring_begin(struct intel_ring_buffer *ring, 1585e3adcf8fSFrançois Tigeot int num_dwords) 1586e3adcf8fSFrançois Tigeot { 1587b5c29a34SFrançois Tigeot drm_i915_private_t *dev_priv = ring->dev->dev_private; 1588e3adcf8fSFrançois Tigeot int ret; 1589e3adcf8fSFrançois Tigeot 1590a2fdbec6SFrançois Tigeot ret = i915_gem_check_wedge(&dev_priv->gpu_error, 1591a2fdbec6SFrançois Tigeot dev_priv->mm.interruptible); 1592245593daSFrançois Tigeot if (ret) 1593245593daSFrançois Tigeot return ret; 1594e3adcf8fSFrançois Tigeot 1595b5c29a34SFrançois Tigeot /* Preallocate the olr before touching the ring */ 1596b5c29a34SFrançois Tigeot ret = intel_ring_alloc_seqno(ring); 1597b5c29a34SFrançois Tigeot if (ret) 1598b5c29a34SFrançois Tigeot return ret; 1599b5c29a34SFrançois Tigeot 1600a2fdbec6SFrançois Tigeot return __intel_ring_begin(ring, num_dwords * sizeof(uint32_t)); 1601e3adcf8fSFrançois Tigeot } 1602e3adcf8fSFrançois Tigeot 1603a2fdbec6SFrançois Tigeot void intel_ring_init_seqno(struct intel_ring_buffer *ring, u32 seqno) 1604a2fdbec6SFrançois Tigeot { 1605a2fdbec6SFrançois Tigeot struct drm_i915_private *dev_priv = ring->dev->dev_private; 1606a2fdbec6SFrançois Tigeot 1607a2fdbec6SFrançois Tigeot BUG_ON(ring->outstanding_lazy_request); 1608a2fdbec6SFrançois Tigeot 1609a2fdbec6SFrançois Tigeot if (INTEL_INFO(ring->dev)->gen >= 6) { 1610a2fdbec6SFrançois Tigeot I915_WRITE(RING_SYNC_0(ring->mmio_base), 0); 1611a2fdbec6SFrançois Tigeot I915_WRITE(RING_SYNC_1(ring->mmio_base), 0); 1612e3adcf8fSFrançois Tigeot } 1613e3adcf8fSFrançois Tigeot 1614a2fdbec6SFrançois Tigeot ring->set_seqno(ring, seqno); 16155d0b1887SFrançois Tigeot ring->hangcheck.seqno = seqno; 1616e3adcf8fSFrançois Tigeot } 1617e3adcf8fSFrançois Tigeot 1618e3adcf8fSFrançois Tigeot void intel_ring_advance(struct intel_ring_buffer *ring) 1619e3adcf8fSFrançois Tigeot { 1620686a02f1SFrançois Tigeot struct drm_i915_private *dev_priv = ring->dev->dev_private; 1621686a02f1SFrançois Tigeot 1622e3adcf8fSFrançois Tigeot ring->tail &= ring->size - 1; 1623a2fdbec6SFrançois Tigeot if (dev_priv->gpu_error.stop_rings & intel_ring_flag(ring)) 1624686a02f1SFrançois Tigeot return; 1625e3adcf8fSFrançois Tigeot ring->write_tail(ring, ring->tail); 1626e3adcf8fSFrançois Tigeot } 1627e3adcf8fSFrançois Tigeot 1628b5c29a34SFrançois Tigeot 1629e3adcf8fSFrançois Tigeot static void gen6_bsd_ring_write_tail(struct intel_ring_buffer *ring, 1630f4e1c372SFrançois Tigeot u32 value) 1631e3adcf8fSFrançois Tigeot { 1632e3adcf8fSFrançois Tigeot drm_i915_private_t *dev_priv = ring->dev->dev_private; 1633e3adcf8fSFrançois Tigeot 1634e3adcf8fSFrançois Tigeot /* Every tail move must follow the sequence below */ 1635f4e1c372SFrançois Tigeot 1636f4e1c372SFrançois Tigeot /* Disable notification that the ring is IDLE. The GT 1637f4e1c372SFrançois Tigeot * will then assume that it is busy and bring it out of rc6. 1638f4e1c372SFrançois Tigeot */ 1639e3adcf8fSFrançois Tigeot I915_WRITE(GEN6_BSD_SLEEP_PSMI_CONTROL, 1640f4e1c372SFrançois Tigeot _MASKED_BIT_ENABLE(GEN6_BSD_SLEEP_MSG_DISABLE)); 1641e3adcf8fSFrançois Tigeot 1642f4e1c372SFrançois Tigeot /* Clear the context id. Here be magic! */ 1643f4e1c372SFrançois Tigeot I915_WRITE64(GEN6_BSD_RNCID, 0x0); 1644e3adcf8fSFrançois Tigeot 1645f4e1c372SFrançois Tigeot /* Wait for the ring not to be idle, i.e. for it to wake up. */ 1646f4e1c372SFrançois Tigeot if (wait_for((I915_READ(GEN6_BSD_SLEEP_PSMI_CONTROL) & 1647f4e1c372SFrançois Tigeot GEN6_BSD_SLEEP_INDICATOR) == 0, 1648f4e1c372SFrançois Tigeot 50)) 1649f4e1c372SFrançois Tigeot DRM_ERROR("timed out waiting for the BSD ring to wake up\n"); 1650f4e1c372SFrançois Tigeot 1651f4e1c372SFrançois Tigeot /* Now that the ring is fully powered up, update the tail */ 1652e3adcf8fSFrançois Tigeot I915_WRITE_TAIL(ring, value); 1653f4e1c372SFrançois Tigeot POSTING_READ(RING_TAIL(ring->mmio_base)); 1654f4e1c372SFrançois Tigeot 1655f4e1c372SFrançois Tigeot /* Let the ring send IDLE messages to the GT again, 1656f4e1c372SFrançois Tigeot * and so let it sleep to conserve power when idle. 1657f4e1c372SFrançois Tigeot */ 1658e3adcf8fSFrançois Tigeot I915_WRITE(GEN6_BSD_SLEEP_PSMI_CONTROL, 1659f4e1c372SFrançois Tigeot _MASKED_BIT_DISABLE(GEN6_BSD_SLEEP_MSG_DISABLE)); 1660e3adcf8fSFrançois Tigeot } 1661e3adcf8fSFrançois Tigeot 16625d0b1887SFrançois Tigeot static int gen6_bsd_ring_flush(struct intel_ring_buffer *ring, 1663b5c29a34SFrançois Tigeot u32 invalidate, u32 flush) 1664e3adcf8fSFrançois Tigeot { 1665e3adcf8fSFrançois Tigeot uint32_t cmd; 1666e3adcf8fSFrançois Tigeot int ret; 1667e3adcf8fSFrançois Tigeot 1668e3adcf8fSFrançois Tigeot ret = intel_ring_begin(ring, 4); 1669e3adcf8fSFrançois Tigeot if (ret) 1670e3adcf8fSFrançois Tigeot return ret; 1671e3adcf8fSFrançois Tigeot 1672e3adcf8fSFrançois Tigeot cmd = MI_FLUSH_DW; 1673b5c29a34SFrançois Tigeot /* 1674b5c29a34SFrançois Tigeot * Bspec vol 1c.5 - video engine command streamer: 1675b5c29a34SFrançois Tigeot * "If ENABLED, all TLBs will be invalidated once the flush 1676b5c29a34SFrançois Tigeot * operation is complete. This bit is only valid when the 1677b5c29a34SFrançois Tigeot * Post-Sync Operation field is a value of 1h or 3h." 1678b5c29a34SFrançois Tigeot */ 1679e3adcf8fSFrançois Tigeot if (invalidate & I915_GEM_GPU_DOMAINS) 1680b5c29a34SFrançois Tigeot cmd |= MI_INVALIDATE_TLB | MI_INVALIDATE_BSD | 1681b5c29a34SFrançois Tigeot MI_FLUSH_DW_STORE_INDEX | MI_FLUSH_DW_OP_STOREDW; 1682e3adcf8fSFrançois Tigeot intel_ring_emit(ring, cmd); 1683b5c29a34SFrançois Tigeot intel_ring_emit(ring, I915_GEM_HWS_SCRATCH_ADDR | MI_FLUSH_DW_USE_GTT); 1684e3adcf8fSFrançois Tigeot intel_ring_emit(ring, 0); 1685e3adcf8fSFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 1686e3adcf8fSFrançois Tigeot intel_ring_advance(ring); 1687e3adcf8fSFrançois Tigeot return 0; 1688e3adcf8fSFrançois Tigeot } 1689e3adcf8fSFrançois Tigeot 1690e3adcf8fSFrançois Tigeot static int 1691b5c29a34SFrançois Tigeot hsw_ring_dispatch_execbuffer(struct intel_ring_buffer *ring, 1692b5c29a34SFrançois Tigeot u32 offset, u32 len, 1693b5c29a34SFrançois Tigeot unsigned flags) 1694e3adcf8fSFrançois Tigeot { 1695e3adcf8fSFrançois Tigeot int ret; 1696e3adcf8fSFrançois Tigeot 1697e3adcf8fSFrançois Tigeot ret = intel_ring_begin(ring, 2); 1698e3adcf8fSFrançois Tigeot if (ret) 1699e3adcf8fSFrançois Tigeot return ret; 1700e3adcf8fSFrançois Tigeot 1701b5c29a34SFrançois Tigeot intel_ring_emit(ring, 1702b5c29a34SFrançois Tigeot MI_BATCH_BUFFER_START | MI_BATCH_PPGTT_HSW | 1703b5c29a34SFrançois Tigeot (flags & I915_DISPATCH_SECURE ? 0 : MI_BATCH_NON_SECURE_HSW)); 1704b5c29a34SFrançois Tigeot /* bit0-7 is the length on GEN6+ */ 1705b5c29a34SFrançois Tigeot intel_ring_emit(ring, offset); 1706b5c29a34SFrançois Tigeot intel_ring_advance(ring); 1707b5c29a34SFrançois Tigeot 1708b5c29a34SFrançois Tigeot return 0; 1709b5c29a34SFrançois Tigeot } 1710b5c29a34SFrançois Tigeot 1711b5c29a34SFrançois Tigeot static int 1712b5c29a34SFrançois Tigeot gen6_ring_dispatch_execbuffer(struct intel_ring_buffer *ring, 1713b5c29a34SFrançois Tigeot u32 offset, u32 len, 1714b5c29a34SFrançois Tigeot unsigned flags) 1715b5c29a34SFrançois Tigeot { 1716b5c29a34SFrançois Tigeot int ret; 1717b5c29a34SFrançois Tigeot 1718b5c29a34SFrançois Tigeot ret = intel_ring_begin(ring, 2); 1719b5c29a34SFrançois Tigeot if (ret) 1720b5c29a34SFrançois Tigeot return ret; 1721b5c29a34SFrançois Tigeot 1722b5c29a34SFrançois Tigeot intel_ring_emit(ring, 1723b5c29a34SFrançois Tigeot MI_BATCH_BUFFER_START | 1724b5c29a34SFrançois Tigeot (flags & I915_DISPATCH_SECURE ? 0 : MI_BATCH_NON_SECURE_I965)); 1725e3adcf8fSFrançois Tigeot /* bit0-7 is the length on GEN6+ */ 1726e3adcf8fSFrançois Tigeot intel_ring_emit(ring, offset); 1727e3adcf8fSFrançois Tigeot intel_ring_advance(ring); 1728e3adcf8fSFrançois Tigeot 1729e3adcf8fSFrançois Tigeot return 0; 1730e3adcf8fSFrançois Tigeot } 1731e3adcf8fSFrançois Tigeot 1732e3adcf8fSFrançois Tigeot /* Blitter support (SandyBridge+) */ 1733e3adcf8fSFrançois Tigeot 17345d0b1887SFrançois Tigeot static int gen6_ring_flush(struct intel_ring_buffer *ring, 1735b5c29a34SFrançois Tigeot u32 invalidate, u32 flush) 1736e3adcf8fSFrançois Tigeot { 17375d0b1887SFrançois Tigeot struct drm_device *dev = ring->dev; 1738e3adcf8fSFrançois Tigeot uint32_t cmd; 1739e3adcf8fSFrançois Tigeot int ret; 1740e3adcf8fSFrançois Tigeot 1741e3adcf8fSFrançois Tigeot ret = intel_ring_begin(ring, 4); 1742e3adcf8fSFrançois Tigeot if (ret) 1743e3adcf8fSFrançois Tigeot return ret; 1744e3adcf8fSFrançois Tigeot 1745e3adcf8fSFrançois Tigeot cmd = MI_FLUSH_DW; 1746b5c29a34SFrançois Tigeot /* 1747b5c29a34SFrançois Tigeot * Bspec vol 1c.3 - blitter engine command streamer: 1748b5c29a34SFrançois Tigeot * "If ENABLED, all TLBs will be invalidated once the flush 1749b5c29a34SFrançois Tigeot * operation is complete. This bit is only valid when the 1750b5c29a34SFrançois Tigeot * Post-Sync Operation field is a value of 1h or 3h." 1751b5c29a34SFrançois Tigeot */ 1752e3adcf8fSFrançois Tigeot if (invalidate & I915_GEM_DOMAIN_RENDER) 1753b5c29a34SFrançois Tigeot cmd |= MI_INVALIDATE_TLB | MI_FLUSH_DW_STORE_INDEX | 1754b5c29a34SFrançois Tigeot MI_FLUSH_DW_OP_STOREDW; 1755e3adcf8fSFrançois Tigeot intel_ring_emit(ring, cmd); 1756b5c29a34SFrançois Tigeot intel_ring_emit(ring, I915_GEM_HWS_SCRATCH_ADDR | MI_FLUSH_DW_USE_GTT); 1757e3adcf8fSFrançois Tigeot intel_ring_emit(ring, 0); 1758e3adcf8fSFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 1759e3adcf8fSFrançois Tigeot intel_ring_advance(ring); 17605d0b1887SFrançois Tigeot 17615d0b1887SFrançois Tigeot if (IS_GEN7(dev) && flush) 17625d0b1887SFrançois Tigeot return gen7_ring_fbc_flush(ring, FBC_REND_CACHE_CLEAN); 17635d0b1887SFrançois Tigeot 1764e3adcf8fSFrançois Tigeot return 0; 1765e3adcf8fSFrançois Tigeot } 1766e3adcf8fSFrançois Tigeot 1767e3adcf8fSFrançois Tigeot int intel_init_render_ring_buffer(struct drm_device *dev) 1768e3adcf8fSFrançois Tigeot { 1769e3adcf8fSFrançois Tigeot drm_i915_private_t *dev_priv = dev->dev_private; 1770ad50ea93SFrançois Tigeot struct intel_ring_buffer *ring = &dev_priv->ring[RCS]; 1771e3adcf8fSFrançois Tigeot 1772686a02f1SFrançois Tigeot ring->name = "render ring"; 1773686a02f1SFrançois Tigeot ring->id = RCS; 1774686a02f1SFrançois Tigeot ring->mmio_base = RENDER_RING_BASE; 1775686a02f1SFrançois Tigeot 1776e3adcf8fSFrançois Tigeot if (INTEL_INFO(dev)->gen >= 6) { 1777e3adcf8fSFrançois Tigeot ring->add_request = gen6_add_request; 1778b5c29a34SFrançois Tigeot ring->flush = gen7_render_ring_flush; 1779b5c29a34SFrançois Tigeot if (INTEL_INFO(dev)->gen == 6) 1780e3adcf8fSFrançois Tigeot ring->flush = gen6_render_ring_flush; 1781686a02f1SFrançois Tigeot ring->irq_get = gen6_ring_get_irq; 1782686a02f1SFrançois Tigeot ring->irq_put = gen6_ring_put_irq; 17835d0b1887SFrançois Tigeot ring->irq_enable_mask = GT_RENDER_USER_INTERRUPT; 1784e3adcf8fSFrançois Tigeot ring->get_seqno = gen6_ring_get_seqno; 1785a2fdbec6SFrançois Tigeot ring->set_seqno = ring_set_seqno; 1786686a02f1SFrançois Tigeot ring->sync_to = gen6_ring_sync; 17875d0b1887SFrançois Tigeot ring->semaphore_register[RCS] = MI_SEMAPHORE_SYNC_INVALID; 17885d0b1887SFrançois Tigeot ring->semaphore_register[VCS] = MI_SEMAPHORE_SYNC_RV; 17895d0b1887SFrançois Tigeot ring->semaphore_register[BCS] = MI_SEMAPHORE_SYNC_RB; 17905d0b1887SFrançois Tigeot ring->semaphore_register[VECS] = MI_SEMAPHORE_SYNC_RVE; 17915d0b1887SFrançois Tigeot ring->signal_mbox[RCS] = GEN6_NOSYNC; 17925d0b1887SFrançois Tigeot ring->signal_mbox[VCS] = GEN6_VRSYNC; 17935d0b1887SFrançois Tigeot ring->signal_mbox[BCS] = GEN6_BRSYNC; 17945d0b1887SFrançois Tigeot ring->signal_mbox[VECS] = GEN6_VERSYNC; 1795e3adcf8fSFrançois Tigeot } else if (IS_GEN5(dev)) { 1796e3adcf8fSFrançois Tigeot ring->add_request = pc_render_add_request; 1797686a02f1SFrançois Tigeot ring->flush = gen4_render_ring_flush; 1798e3adcf8fSFrançois Tigeot ring->get_seqno = pc_render_get_seqno; 1799a2fdbec6SFrançois Tigeot ring->set_seqno = pc_render_set_seqno; 1800686a02f1SFrançois Tigeot ring->irq_get = gen5_ring_get_irq; 1801686a02f1SFrançois Tigeot ring->irq_put = gen5_ring_put_irq; 18025d0b1887SFrançois Tigeot ring->irq_enable_mask = GT_RENDER_USER_INTERRUPT | 18035d0b1887SFrançois Tigeot GT_RENDER_PIPECTL_NOTIFY_INTERRUPT; 1804686a02f1SFrançois Tigeot } else { 1805686a02f1SFrançois Tigeot ring->add_request = i9xx_add_request; 1806686a02f1SFrançois Tigeot if (INTEL_INFO(dev)->gen < 4) 1807686a02f1SFrançois Tigeot ring->flush = gen2_render_ring_flush; 1808686a02f1SFrançois Tigeot else 1809686a02f1SFrançois Tigeot ring->flush = gen4_render_ring_flush; 1810686a02f1SFrançois Tigeot ring->get_seqno = ring_get_seqno; 1811a2fdbec6SFrançois Tigeot ring->set_seqno = ring_set_seqno; 1812686a02f1SFrançois Tigeot if (IS_GEN2(dev)) { 1813686a02f1SFrançois Tigeot ring->irq_get = i8xx_ring_get_irq; 1814686a02f1SFrançois Tigeot ring->irq_put = i8xx_ring_put_irq; 1815686a02f1SFrançois Tigeot } else { 1816686a02f1SFrançois Tigeot ring->irq_get = i9xx_ring_get_irq; 1817686a02f1SFrançois Tigeot ring->irq_put = i9xx_ring_put_irq; 1818e3adcf8fSFrançois Tigeot } 1819686a02f1SFrançois Tigeot ring->irq_enable_mask = I915_USER_INTERRUPT; 1820686a02f1SFrançois Tigeot } 1821686a02f1SFrançois Tigeot ring->write_tail = ring_write_tail; 1822b5c29a34SFrançois Tigeot if (IS_HASWELL(dev)) 1823b5c29a34SFrançois Tigeot ring->dispatch_execbuffer = hsw_ring_dispatch_execbuffer; 1824b5c29a34SFrançois Tigeot else if (INTEL_INFO(dev)->gen >= 6) 1825686a02f1SFrançois Tigeot ring->dispatch_execbuffer = gen6_ring_dispatch_execbuffer; 1826686a02f1SFrançois Tigeot else if (INTEL_INFO(dev)->gen >= 4) 1827686a02f1SFrançois Tigeot ring->dispatch_execbuffer = i965_dispatch_execbuffer; 1828686a02f1SFrançois Tigeot else if (IS_I830(dev) || IS_845G(dev)) 1829686a02f1SFrançois Tigeot ring->dispatch_execbuffer = i830_dispatch_execbuffer; 1830686a02f1SFrançois Tigeot else 1831686a02f1SFrançois Tigeot ring->dispatch_execbuffer = i915_dispatch_execbuffer; 1832686a02f1SFrançois Tigeot ring->init = init_render_ring; 1833686a02f1SFrançois Tigeot ring->cleanup = render_ring_cleanup; 1834e3adcf8fSFrançois Tigeot 1835b5c29a34SFrançois Tigeot /* Workaround batchbuffer to combat CS tlb bug. */ 1836b5c29a34SFrançois Tigeot if (HAS_BROKEN_CS_TLB(dev)) { 1837b5c29a34SFrançois Tigeot struct drm_i915_gem_object *obj; 1838b5c29a34SFrançois Tigeot int ret; 1839b5c29a34SFrançois Tigeot 1840b5c29a34SFrançois Tigeot obj = i915_gem_alloc_object(dev, I830_BATCH_LIMIT); 1841b5c29a34SFrançois Tigeot if (obj == NULL) { 1842b5c29a34SFrançois Tigeot DRM_ERROR("Failed to allocate batch bo\n"); 1843b5c29a34SFrançois Tigeot return -ENOMEM; 1844b5c29a34SFrançois Tigeot } 1845b5c29a34SFrançois Tigeot 1846b00bc81cSFrançois Tigeot ret = i915_gem_object_pin(obj, 0, true, false); 1847b5c29a34SFrançois Tigeot if (ret != 0) { 1848b5c29a34SFrançois Tigeot drm_gem_object_unreference(&obj->base); 1849b5c29a34SFrançois Tigeot DRM_ERROR("Failed to ping batch bo\n"); 1850b5c29a34SFrançois Tigeot return ret; 1851b5c29a34SFrançois Tigeot } 1852b5c29a34SFrançois Tigeot 1853b5c29a34SFrançois Tigeot ring->private = obj; 1854e3adcf8fSFrançois Tigeot } 1855e3adcf8fSFrançois Tigeot 1856e3adcf8fSFrançois Tigeot return intel_init_ring_buffer(dev, ring); 1857e3adcf8fSFrançois Tigeot } 1858e3adcf8fSFrançois Tigeot 1859686a02f1SFrançois Tigeot int intel_render_ring_init_dri(struct drm_device *dev, u64 start, u32 size) 1860e3adcf8fSFrançois Tigeot { 1861e3adcf8fSFrançois Tigeot drm_i915_private_t *dev_priv = dev->dev_private; 1862ad50ea93SFrançois Tigeot struct intel_ring_buffer *ring = &dev_priv->ring[RCS]; 1863b5c29a34SFrançois Tigeot int ret; 1864e3adcf8fSFrançois Tigeot 1865686a02f1SFrançois Tigeot ring->name = "render ring"; 1866686a02f1SFrançois Tigeot ring->id = RCS; 1867686a02f1SFrançois Tigeot ring->mmio_base = RENDER_RING_BASE; 1868686a02f1SFrançois Tigeot 1869e3adcf8fSFrançois Tigeot if (INTEL_INFO(dev)->gen >= 6) { 1870686a02f1SFrançois Tigeot /* non-kms not supported on gen6+ */ 1871686a02f1SFrançois Tigeot return -ENODEV; 1872e3adcf8fSFrançois Tigeot } 1873e3adcf8fSFrançois Tigeot 1874686a02f1SFrançois Tigeot /* Note: gem is not supported on gen5/ilk without kms (the corresponding 1875686a02f1SFrançois Tigeot * gem_init ioctl returns with -ENODEV). Hence we do not need to set up 1876686a02f1SFrançois Tigeot * the special gen5 functions. */ 1877686a02f1SFrançois Tigeot ring->add_request = i9xx_add_request; 1878686a02f1SFrançois Tigeot if (INTEL_INFO(dev)->gen < 4) 1879686a02f1SFrançois Tigeot ring->flush = gen2_render_ring_flush; 1880686a02f1SFrançois Tigeot else 1881686a02f1SFrançois Tigeot ring->flush = gen4_render_ring_flush; 1882686a02f1SFrançois Tigeot ring->get_seqno = ring_get_seqno; 1883a2fdbec6SFrançois Tigeot ring->set_seqno = ring_set_seqno; 1884686a02f1SFrançois Tigeot if (IS_GEN2(dev)) { 1885686a02f1SFrançois Tigeot ring->irq_get = i8xx_ring_get_irq; 1886686a02f1SFrançois Tigeot ring->irq_put = i8xx_ring_put_irq; 1887686a02f1SFrançois Tigeot } else { 1888686a02f1SFrançois Tigeot ring->irq_get = i9xx_ring_get_irq; 1889686a02f1SFrançois Tigeot ring->irq_put = i9xx_ring_put_irq; 1890686a02f1SFrançois Tigeot } 1891686a02f1SFrançois Tigeot ring->irq_enable_mask = I915_USER_INTERRUPT; 1892686a02f1SFrançois Tigeot ring->write_tail = ring_write_tail; 1893686a02f1SFrançois Tigeot if (INTEL_INFO(dev)->gen >= 4) 1894686a02f1SFrançois Tigeot ring->dispatch_execbuffer = i965_dispatch_execbuffer; 1895686a02f1SFrançois Tigeot else if (IS_I830(dev) || IS_845G(dev)) 1896686a02f1SFrançois Tigeot ring->dispatch_execbuffer = i830_dispatch_execbuffer; 1897686a02f1SFrançois Tigeot else 1898686a02f1SFrançois Tigeot ring->dispatch_execbuffer = i915_dispatch_execbuffer; 1899686a02f1SFrançois Tigeot ring->init = init_render_ring; 1900686a02f1SFrançois Tigeot ring->cleanup = render_ring_cleanup; 1901686a02f1SFrançois Tigeot 1902e3adcf8fSFrançois Tigeot ring->dev = dev; 1903e3adcf8fSFrançois Tigeot INIT_LIST_HEAD(&ring->active_list); 1904e3adcf8fSFrançois Tigeot INIT_LIST_HEAD(&ring->request_list); 1905e3adcf8fSFrançois Tigeot 1906e3adcf8fSFrançois Tigeot ring->size = size; 1907e3adcf8fSFrançois Tigeot ring->effective_size = ring->size; 1908b5c29a34SFrançois Tigeot if (IS_I830(ring->dev) || IS_845G(ring->dev)) 1909e3adcf8fSFrançois Tigeot ring->effective_size -= 128; 1910e3adcf8fSFrançois Tigeot 1911686a02f1SFrançois Tigeot ring->virtual_start = ioremap_wc(start, size); 1912686a02f1SFrançois Tigeot if (ring->virtual_start == NULL) { 1913e3adcf8fSFrançois Tigeot DRM_ERROR("can not ioremap virtual address for" 1914e3adcf8fSFrançois Tigeot " ring buffer\n"); 1915e3adcf8fSFrançois Tigeot return -ENOMEM; 1916e3adcf8fSFrançois Tigeot } 1917e3adcf8fSFrançois Tigeot 1918b5c29a34SFrançois Tigeot if (!I915_NEED_GFX_HWS(dev)) { 19195d0b1887SFrançois Tigeot ret = init_phys_status_page(ring); 1920b5c29a34SFrançois Tigeot if (ret) 1921b5c29a34SFrançois Tigeot return ret; 1922b5c29a34SFrançois Tigeot } 1923b5c29a34SFrançois Tigeot 1924e3adcf8fSFrançois Tigeot return 0; 1925e3adcf8fSFrançois Tigeot } 1926e3adcf8fSFrançois Tigeot 1927e3adcf8fSFrançois Tigeot int intel_init_bsd_ring_buffer(struct drm_device *dev) 1928e3adcf8fSFrançois Tigeot { 1929e3adcf8fSFrançois Tigeot drm_i915_private_t *dev_priv = dev->dev_private; 1930ad50ea93SFrançois Tigeot struct intel_ring_buffer *ring = &dev_priv->ring[VCS]; 1931e3adcf8fSFrançois Tigeot 1932686a02f1SFrançois Tigeot ring->name = "bsd ring"; 1933686a02f1SFrançois Tigeot ring->id = VCS; 1934686a02f1SFrançois Tigeot 1935686a02f1SFrançois Tigeot ring->write_tail = ring_write_tail; 1936686a02f1SFrançois Tigeot if (IS_GEN6(dev) || IS_GEN7(dev)) { 1937686a02f1SFrançois Tigeot ring->mmio_base = GEN6_BSD_RING_BASE; 1938686a02f1SFrançois Tigeot /* gen6 bsd needs a special wa for tail updates */ 1939686a02f1SFrançois Tigeot if (IS_GEN6(dev)) 1940686a02f1SFrançois Tigeot ring->write_tail = gen6_bsd_ring_write_tail; 19415d0b1887SFrançois Tigeot ring->flush = gen6_bsd_ring_flush; 1942686a02f1SFrançois Tigeot ring->add_request = gen6_add_request; 1943686a02f1SFrançois Tigeot ring->get_seqno = gen6_ring_get_seqno; 1944a2fdbec6SFrançois Tigeot ring->set_seqno = ring_set_seqno; 19455d0b1887SFrançois Tigeot ring->irq_enable_mask = GT_BSD_USER_INTERRUPT; 1946686a02f1SFrançois Tigeot ring->irq_get = gen6_ring_get_irq; 1947686a02f1SFrançois Tigeot ring->irq_put = gen6_ring_put_irq; 1948686a02f1SFrançois Tigeot ring->dispatch_execbuffer = gen6_ring_dispatch_execbuffer; 1949686a02f1SFrançois Tigeot ring->sync_to = gen6_ring_sync; 19505d0b1887SFrançois Tigeot ring->semaphore_register[RCS] = MI_SEMAPHORE_SYNC_VR; 19515d0b1887SFrançois Tigeot ring->semaphore_register[VCS] = MI_SEMAPHORE_SYNC_INVALID; 19525d0b1887SFrançois Tigeot ring->semaphore_register[BCS] = MI_SEMAPHORE_SYNC_VB; 19535d0b1887SFrançois Tigeot ring->semaphore_register[VECS] = MI_SEMAPHORE_SYNC_VVE; 19545d0b1887SFrançois Tigeot ring->signal_mbox[RCS] = GEN6_RVSYNC; 19555d0b1887SFrançois Tigeot ring->signal_mbox[VCS] = GEN6_NOSYNC; 19565d0b1887SFrançois Tigeot ring->signal_mbox[BCS] = GEN6_BVSYNC; 19575d0b1887SFrançois Tigeot ring->signal_mbox[VECS] = GEN6_VEVSYNC; 1958686a02f1SFrançois Tigeot } else { 1959686a02f1SFrançois Tigeot ring->mmio_base = BSD_RING_BASE; 1960686a02f1SFrançois Tigeot ring->flush = bsd_ring_flush; 1961686a02f1SFrançois Tigeot ring->add_request = i9xx_add_request; 1962686a02f1SFrançois Tigeot ring->get_seqno = ring_get_seqno; 1963a2fdbec6SFrançois Tigeot ring->set_seqno = ring_set_seqno; 1964686a02f1SFrançois Tigeot if (IS_GEN5(dev)) { 19655d0b1887SFrançois Tigeot ring->irq_enable_mask = ILK_BSD_USER_INTERRUPT; 1966686a02f1SFrançois Tigeot ring->irq_get = gen5_ring_get_irq; 1967686a02f1SFrançois Tigeot ring->irq_put = gen5_ring_put_irq; 1968686a02f1SFrançois Tigeot } else { 1969686a02f1SFrançois Tigeot ring->irq_enable_mask = I915_BSD_USER_INTERRUPT; 1970686a02f1SFrançois Tigeot ring->irq_get = i9xx_ring_get_irq; 1971686a02f1SFrançois Tigeot ring->irq_put = i9xx_ring_put_irq; 1972686a02f1SFrançois Tigeot } 1973686a02f1SFrançois Tigeot ring->dispatch_execbuffer = i965_dispatch_execbuffer; 1974686a02f1SFrançois Tigeot } 1975686a02f1SFrançois Tigeot ring->init = init_ring_common; 1976e3adcf8fSFrançois Tigeot 1977e3adcf8fSFrançois Tigeot return intel_init_ring_buffer(dev, ring); 1978e3adcf8fSFrançois Tigeot } 1979e3adcf8fSFrançois Tigeot 1980e3adcf8fSFrançois Tigeot int intel_init_blt_ring_buffer(struct drm_device *dev) 1981e3adcf8fSFrançois Tigeot { 1982e3adcf8fSFrançois Tigeot drm_i915_private_t *dev_priv = dev->dev_private; 1983ad50ea93SFrançois Tigeot struct intel_ring_buffer *ring = &dev_priv->ring[BCS]; 1984e3adcf8fSFrançois Tigeot 1985686a02f1SFrançois Tigeot ring->name = "blitter ring"; 1986686a02f1SFrançois Tigeot ring->id = BCS; 1987686a02f1SFrançois Tigeot 1988686a02f1SFrançois Tigeot ring->mmio_base = BLT_RING_BASE; 1989686a02f1SFrançois Tigeot ring->write_tail = ring_write_tail; 19905d0b1887SFrançois Tigeot ring->flush = gen6_ring_flush; 1991686a02f1SFrançois Tigeot ring->add_request = gen6_add_request; 1992686a02f1SFrançois Tigeot ring->get_seqno = gen6_ring_get_seqno; 1993a2fdbec6SFrançois Tigeot ring->set_seqno = ring_set_seqno; 19945d0b1887SFrançois Tigeot ring->irq_enable_mask = GT_BLT_USER_INTERRUPT; 1995686a02f1SFrançois Tigeot ring->irq_get = gen6_ring_get_irq; 1996686a02f1SFrançois Tigeot ring->irq_put = gen6_ring_put_irq; 1997686a02f1SFrançois Tigeot ring->dispatch_execbuffer = gen6_ring_dispatch_execbuffer; 1998686a02f1SFrançois Tigeot ring->sync_to = gen6_ring_sync; 19995d0b1887SFrançois Tigeot ring->semaphore_register[RCS] = MI_SEMAPHORE_SYNC_BR; 20005d0b1887SFrançois Tigeot ring->semaphore_register[VCS] = MI_SEMAPHORE_SYNC_BV; 20015d0b1887SFrançois Tigeot ring->semaphore_register[BCS] = MI_SEMAPHORE_SYNC_INVALID; 20025d0b1887SFrançois Tigeot ring->semaphore_register[VECS] = MI_SEMAPHORE_SYNC_BVE; 20035d0b1887SFrançois Tigeot ring->signal_mbox[RCS] = GEN6_RBSYNC; 20045d0b1887SFrançois Tigeot ring->signal_mbox[VCS] = GEN6_VBSYNC; 20055d0b1887SFrançois Tigeot ring->signal_mbox[BCS] = GEN6_NOSYNC; 20065d0b1887SFrançois Tigeot ring->signal_mbox[VECS] = GEN6_VEBSYNC; 20075d0b1887SFrançois Tigeot ring->init = init_ring_common; 20085d0b1887SFrançois Tigeot 20095d0b1887SFrançois Tigeot return intel_init_ring_buffer(dev, ring); 20105d0b1887SFrançois Tigeot } 20115d0b1887SFrançois Tigeot 20125d0b1887SFrançois Tigeot int intel_init_vebox_ring_buffer(struct drm_device *dev) 20135d0b1887SFrançois Tigeot { 20145d0b1887SFrançois Tigeot drm_i915_private_t *dev_priv = dev->dev_private; 20155d0b1887SFrançois Tigeot struct intel_ring_buffer *ring = &dev_priv->ring[VECS]; 20165d0b1887SFrançois Tigeot 20175d0b1887SFrançois Tigeot ring->name = "video enhancement ring"; 20185d0b1887SFrançois Tigeot ring->id = VECS; 20195d0b1887SFrançois Tigeot 20205d0b1887SFrançois Tigeot ring->mmio_base = VEBOX_RING_BASE; 20215d0b1887SFrançois Tigeot ring->write_tail = ring_write_tail; 20225d0b1887SFrançois Tigeot ring->flush = gen6_ring_flush; 20235d0b1887SFrançois Tigeot ring->add_request = gen6_add_request; 20245d0b1887SFrançois Tigeot ring->get_seqno = gen6_ring_get_seqno; 20255d0b1887SFrançois Tigeot ring->set_seqno = ring_set_seqno; 20265d0b1887SFrançois Tigeot ring->irq_enable_mask = PM_VEBOX_USER_INTERRUPT | 20275d0b1887SFrançois Tigeot PM_VEBOX_CS_ERROR_INTERRUPT; 20285d0b1887SFrançois Tigeot ring->irq_get = hsw_vebox_get_irq; 20295d0b1887SFrançois Tigeot ring->irq_put = hsw_vebox_put_irq; 20305d0b1887SFrançois Tigeot ring->dispatch_execbuffer = gen6_ring_dispatch_execbuffer; 20315d0b1887SFrançois Tigeot ring->sync_to = gen6_ring_sync; 20325d0b1887SFrançois Tigeot ring->semaphore_register[RCS] = MI_SEMAPHORE_SYNC_VER; 20335d0b1887SFrançois Tigeot ring->semaphore_register[VCS] = MI_SEMAPHORE_SYNC_VEV; 20345d0b1887SFrançois Tigeot ring->semaphore_register[BCS] = MI_SEMAPHORE_SYNC_VEB; 20355d0b1887SFrançois Tigeot ring->semaphore_register[VECS] = MI_SEMAPHORE_SYNC_INVALID; 20365d0b1887SFrançois Tigeot ring->signal_mbox[RCS] = GEN6_RVESYNC; 20375d0b1887SFrançois Tigeot ring->signal_mbox[VCS] = GEN6_VVESYNC; 20385d0b1887SFrançois Tigeot ring->signal_mbox[BCS] = GEN6_BVESYNC; 20395d0b1887SFrançois Tigeot ring->signal_mbox[VECS] = GEN6_NOSYNC; 2040686a02f1SFrançois Tigeot ring->init = init_ring_common; 2041e3adcf8fSFrançois Tigeot 2042e3adcf8fSFrançois Tigeot return intel_init_ring_buffer(dev, ring); 2043e3adcf8fSFrançois Tigeot } 2044b030f26bSFrançois Tigeot 2045b030f26bSFrançois Tigeot int 2046b030f26bSFrançois Tigeot intel_ring_flush_all_caches(struct intel_ring_buffer *ring) 2047b030f26bSFrançois Tigeot { 2048b030f26bSFrançois Tigeot int ret; 2049b030f26bSFrançois Tigeot 2050b030f26bSFrançois Tigeot if (!ring->gpu_caches_dirty) 2051b030f26bSFrançois Tigeot return 0; 2052b030f26bSFrançois Tigeot 2053b030f26bSFrançois Tigeot ret = ring->flush(ring, 0, I915_GEM_GPU_DOMAINS); 2054b030f26bSFrançois Tigeot if (ret) 2055b030f26bSFrançois Tigeot return ret; 2056b030f26bSFrançois Tigeot 2057a2fdbec6SFrançois Tigeot trace_i915_gem_ring_flush(ring, 0, I915_GEM_GPU_DOMAINS); 2058a2fdbec6SFrançois Tigeot 2059b030f26bSFrançois Tigeot ring->gpu_caches_dirty = false; 2060b030f26bSFrançois Tigeot return 0; 2061b030f26bSFrançois Tigeot } 2062b030f26bSFrançois Tigeot 2063b030f26bSFrançois Tigeot int 2064b030f26bSFrançois Tigeot intel_ring_invalidate_all_caches(struct intel_ring_buffer *ring) 2065b030f26bSFrançois Tigeot { 2066b030f26bSFrançois Tigeot uint32_t flush_domains; 2067b030f26bSFrançois Tigeot int ret; 2068b030f26bSFrançois Tigeot 2069b030f26bSFrançois Tigeot flush_domains = 0; 2070b030f26bSFrançois Tigeot if (ring->gpu_caches_dirty) 2071b030f26bSFrançois Tigeot flush_domains = I915_GEM_GPU_DOMAINS; 2072b030f26bSFrançois Tigeot 2073b030f26bSFrançois Tigeot ret = ring->flush(ring, I915_GEM_GPU_DOMAINS, flush_domains); 2074b030f26bSFrançois Tigeot if (ret) 2075b030f26bSFrançois Tigeot return ret; 2076b030f26bSFrançois Tigeot 2077a2fdbec6SFrançois Tigeot trace_i915_gem_ring_flush(ring, I915_GEM_GPU_DOMAINS, flush_domains); 2078a2fdbec6SFrançois Tigeot 2079b030f26bSFrançois Tigeot ring->gpu_caches_dirty = false; 2080b030f26bSFrançois Tigeot return 0; 2081b030f26bSFrançois Tigeot } 2082