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> 315c6c6f23SFrançois Tigeot #include <drm/i915_drm.h> 32e3adcf8fSFrançois Tigeot #include "i915_drv.h" 33e3adcf8fSFrançois Tigeot #include "intel_drv.h" 34e3adcf8fSFrançois Tigeot #include "intel_ringbuffer.h" 35e3adcf8fSFrançois Tigeot #include <sys/sched.h> 36e3adcf8fSFrançois Tigeot 37e3adcf8fSFrançois Tigeot /* 38e3adcf8fSFrançois Tigeot * 965+ support PIPE_CONTROL commands, which provide finer grained control 39e3adcf8fSFrançois Tigeot * over cache flushing. 40e3adcf8fSFrançois Tigeot */ 41e3adcf8fSFrançois Tigeot struct pipe_control { 42e3adcf8fSFrançois Tigeot struct drm_i915_gem_object *obj; 43e3adcf8fSFrançois Tigeot volatile u32 *cpu_page; 44e3adcf8fSFrançois Tigeot u32 gtt_offset; 45e3adcf8fSFrançois Tigeot }; 46e3adcf8fSFrançois Tigeot 47e3adcf8fSFrançois Tigeot static inline int ring_space(struct intel_ring_buffer *ring) 48e3adcf8fSFrançois Tigeot { 497cbd1a46SFrançois Tigeot int space = (ring->head & HEAD_ADDR) - (ring->tail + I915_RING_FREE_SPACE); 50e3adcf8fSFrançois Tigeot if (space < 0) 51e3adcf8fSFrançois Tigeot space += ring->size; 52e3adcf8fSFrançois Tigeot return space; 53e3adcf8fSFrançois Tigeot } 54e3adcf8fSFrançois Tigeot 55e3adcf8fSFrançois Tigeot static int 56686a02f1SFrançois Tigeot gen2_render_ring_flush(struct intel_ring_buffer *ring, 57686a02f1SFrançois Tigeot u32 invalidate_domains, 58686a02f1SFrançois Tigeot u32 flush_domains) 59686a02f1SFrançois Tigeot { 60686a02f1SFrançois Tigeot u32 cmd; 61686a02f1SFrançois Tigeot int ret; 62686a02f1SFrançois Tigeot 63686a02f1SFrançois Tigeot cmd = MI_FLUSH; 64686a02f1SFrançois Tigeot if (((invalidate_domains|flush_domains) & I915_GEM_DOMAIN_RENDER) == 0) 65686a02f1SFrançois Tigeot cmd |= MI_NO_WRITE_FLUSH; 66686a02f1SFrançois Tigeot 67686a02f1SFrançois Tigeot if (invalidate_domains & I915_GEM_DOMAIN_SAMPLER) 68686a02f1SFrançois Tigeot cmd |= MI_READ_FLUSH; 69686a02f1SFrançois Tigeot 70686a02f1SFrançois Tigeot ret = intel_ring_begin(ring, 2); 71686a02f1SFrançois Tigeot if (ret) 72686a02f1SFrançois Tigeot return ret; 73686a02f1SFrançois Tigeot 74686a02f1SFrançois Tigeot intel_ring_emit(ring, cmd); 75686a02f1SFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 76686a02f1SFrançois Tigeot intel_ring_advance(ring); 77686a02f1SFrançois Tigeot 78686a02f1SFrançois Tigeot return 0; 79686a02f1SFrançois Tigeot } 80686a02f1SFrançois Tigeot 81686a02f1SFrançois Tigeot static int 82686a02f1SFrançois Tigeot gen4_render_ring_flush(struct intel_ring_buffer *ring, 83686a02f1SFrançois Tigeot u32 invalidate_domains, 84686a02f1SFrançois Tigeot u32 flush_domains) 85e3adcf8fSFrançois Tigeot { 86e3adcf8fSFrançois Tigeot struct drm_device *dev = ring->dev; 87686a02f1SFrançois Tigeot u32 cmd; 88e3adcf8fSFrançois Tigeot int ret; 89e3adcf8fSFrançois Tigeot 90e3adcf8fSFrançois Tigeot /* 91e3adcf8fSFrançois Tigeot * read/write caches: 92e3adcf8fSFrançois Tigeot * 93e3adcf8fSFrançois Tigeot * I915_GEM_DOMAIN_RENDER is always invalidated, but is 94e3adcf8fSFrançois Tigeot * only flushed if MI_NO_WRITE_FLUSH is unset. On 965, it is 95e3adcf8fSFrançois Tigeot * also flushed at 2d versus 3d pipeline switches. 96e3adcf8fSFrançois Tigeot * 97e3adcf8fSFrançois Tigeot * read-only caches: 98e3adcf8fSFrançois Tigeot * 99e3adcf8fSFrançois Tigeot * I915_GEM_DOMAIN_SAMPLER is flushed on pre-965 if 100e3adcf8fSFrançois Tigeot * MI_READ_FLUSH is set, and is always flushed on 965. 101e3adcf8fSFrançois Tigeot * 102e3adcf8fSFrançois Tigeot * I915_GEM_DOMAIN_COMMAND may not exist? 103e3adcf8fSFrançois Tigeot * 104e3adcf8fSFrançois Tigeot * I915_GEM_DOMAIN_INSTRUCTION, which exists on 965, is 105e3adcf8fSFrançois Tigeot * invalidated when MI_EXE_FLUSH is set. 106e3adcf8fSFrançois Tigeot * 107e3adcf8fSFrançois Tigeot * I915_GEM_DOMAIN_VERTEX, which exists on 965, is 108e3adcf8fSFrançois Tigeot * invalidated with every MI_FLUSH. 109e3adcf8fSFrançois Tigeot * 110e3adcf8fSFrançois Tigeot * TLBs: 111e3adcf8fSFrançois Tigeot * 112e3adcf8fSFrançois Tigeot * On 965, TLBs associated with I915_GEM_DOMAIN_COMMAND 113e3adcf8fSFrançois Tigeot * and I915_GEM_DOMAIN_CPU in are invalidated at PTE write and 114e3adcf8fSFrançois Tigeot * I915_GEM_DOMAIN_RENDER and I915_GEM_DOMAIN_SAMPLER 115e3adcf8fSFrançois Tigeot * are flushed at any MI_FLUSH. 116e3adcf8fSFrançois Tigeot */ 117e3adcf8fSFrançois Tigeot 118e3adcf8fSFrançois Tigeot cmd = MI_FLUSH | MI_NO_WRITE_FLUSH; 119686a02f1SFrançois Tigeot if ((invalidate_domains|flush_domains) & I915_GEM_DOMAIN_RENDER) 120e3adcf8fSFrançois Tigeot cmd &= ~MI_NO_WRITE_FLUSH; 121e3adcf8fSFrançois Tigeot if (invalidate_domains & I915_GEM_DOMAIN_INSTRUCTION) 122e3adcf8fSFrançois Tigeot cmd |= MI_EXE_FLUSH; 123e3adcf8fSFrançois Tigeot 124e3adcf8fSFrançois Tigeot if (invalidate_domains & I915_GEM_DOMAIN_COMMAND && 125e3adcf8fSFrançois Tigeot (IS_G4X(dev) || IS_GEN5(dev))) 126e3adcf8fSFrançois Tigeot cmd |= MI_INVALIDATE_ISP; 127e3adcf8fSFrançois Tigeot 128e3adcf8fSFrançois Tigeot ret = intel_ring_begin(ring, 2); 129e3adcf8fSFrançois Tigeot if (ret) 130e3adcf8fSFrançois Tigeot return ret; 131e3adcf8fSFrançois Tigeot 132e3adcf8fSFrançois Tigeot intel_ring_emit(ring, cmd); 133e3adcf8fSFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 134e3adcf8fSFrançois Tigeot intel_ring_advance(ring); 135e3adcf8fSFrançois Tigeot 136e3adcf8fSFrançois Tigeot return 0; 137e3adcf8fSFrançois Tigeot } 138e3adcf8fSFrançois Tigeot 139e3adcf8fSFrançois Tigeot /** 140e3adcf8fSFrançois Tigeot * Emits a PIPE_CONTROL with a non-zero post-sync operation, for 141e3adcf8fSFrançois Tigeot * implementing two workarounds on gen6. From section 1.4.7.1 142e3adcf8fSFrançois Tigeot * "PIPE_CONTROL" of the Sandy Bridge PRM volume 2 part 1: 143e3adcf8fSFrançois Tigeot * 144e3adcf8fSFrançois Tigeot * [DevSNB-C+{W/A}] Before any depth stall flush (including those 145e3adcf8fSFrançois Tigeot * produced by non-pipelined state commands), software needs to first 146e3adcf8fSFrançois Tigeot * send a PIPE_CONTROL with no bits set except Post-Sync Operation != 147e3adcf8fSFrançois Tigeot * 0. 148e3adcf8fSFrançois Tigeot * 149e3adcf8fSFrançois Tigeot * [Dev-SNB{W/A}]: Before a PIPE_CONTROL with Write Cache Flush Enable 150e3adcf8fSFrançois Tigeot * =1, a PIPE_CONTROL with any non-zero post-sync-op is required. 151e3adcf8fSFrançois Tigeot * 152e3adcf8fSFrançois Tigeot * And the workaround for these two requires this workaround first: 153e3adcf8fSFrançois Tigeot * 154e3adcf8fSFrançois Tigeot * [Dev-SNB{W/A}]: Pipe-control with CS-stall bit set must be sent 155e3adcf8fSFrançois Tigeot * BEFORE the pipe-control with a post-sync op and no write-cache 156e3adcf8fSFrançois Tigeot * flushes. 157e3adcf8fSFrançois Tigeot * 158e3adcf8fSFrançois Tigeot * And this last workaround is tricky because of the requirements on 159e3adcf8fSFrançois Tigeot * that bit. From section 1.4.7.2.3 "Stall" of the Sandy Bridge PRM 160e3adcf8fSFrançois Tigeot * volume 2 part 1: 161e3adcf8fSFrançois Tigeot * 162e3adcf8fSFrançois Tigeot * "1 of the following must also be set: 163e3adcf8fSFrançois Tigeot * - Render Target Cache Flush Enable ([12] of DW1) 164e3adcf8fSFrançois Tigeot * - Depth Cache Flush Enable ([0] of DW1) 165e3adcf8fSFrançois Tigeot * - Stall at Pixel Scoreboard ([1] of DW1) 166e3adcf8fSFrançois Tigeot * - Depth Stall ([13] of DW1) 167e3adcf8fSFrançois Tigeot * - Post-Sync Operation ([13] of DW1) 168e3adcf8fSFrançois Tigeot * - Notify Enable ([8] of DW1)" 169e3adcf8fSFrançois Tigeot * 170e3adcf8fSFrançois Tigeot * The cache flushes require the workaround flush that triggered this 171e3adcf8fSFrançois Tigeot * one, so we can't use it. Depth stall would trigger the same. 172e3adcf8fSFrançois Tigeot * Post-sync nonzero is what triggered this second workaround, so we 173e3adcf8fSFrançois Tigeot * can't use that one either. Notify enable is IRQs, which aren't 174e3adcf8fSFrançois Tigeot * really our business. That leaves only stall at scoreboard. 175e3adcf8fSFrançois Tigeot */ 176e3adcf8fSFrançois Tigeot static int 177e3adcf8fSFrançois Tigeot intel_emit_post_sync_nonzero_flush(struct intel_ring_buffer *ring) 178e3adcf8fSFrançois Tigeot { 179e3adcf8fSFrançois Tigeot struct pipe_control *pc = ring->private; 180e3adcf8fSFrançois Tigeot u32 scratch_addr = pc->gtt_offset + 128; 181e3adcf8fSFrançois Tigeot int ret; 182e3adcf8fSFrançois Tigeot 183e3adcf8fSFrançois Tigeot 184e3adcf8fSFrançois Tigeot ret = intel_ring_begin(ring, 6); 185e3adcf8fSFrançois Tigeot if (ret) 186e3adcf8fSFrançois Tigeot return ret; 187e3adcf8fSFrançois Tigeot 188e3adcf8fSFrançois Tigeot intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(5)); 189e3adcf8fSFrançois Tigeot intel_ring_emit(ring, PIPE_CONTROL_CS_STALL | 190e3adcf8fSFrançois Tigeot PIPE_CONTROL_STALL_AT_SCOREBOARD); 191e3adcf8fSFrançois Tigeot intel_ring_emit(ring, scratch_addr | PIPE_CONTROL_GLOBAL_GTT); /* address */ 192e3adcf8fSFrançois Tigeot intel_ring_emit(ring, 0); /* low dword */ 193e3adcf8fSFrançois Tigeot intel_ring_emit(ring, 0); /* high dword */ 194e3adcf8fSFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 195e3adcf8fSFrançois Tigeot intel_ring_advance(ring); 196e3adcf8fSFrançois Tigeot 197e3adcf8fSFrançois Tigeot ret = intel_ring_begin(ring, 6); 198e3adcf8fSFrançois Tigeot if (ret) 199e3adcf8fSFrançois Tigeot return ret; 200e3adcf8fSFrançois Tigeot 201e3adcf8fSFrançois Tigeot intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(5)); 202e3adcf8fSFrançois Tigeot intel_ring_emit(ring, PIPE_CONTROL_QW_WRITE); 203e3adcf8fSFrançois Tigeot intel_ring_emit(ring, scratch_addr | PIPE_CONTROL_GLOBAL_GTT); /* address */ 204e3adcf8fSFrançois Tigeot intel_ring_emit(ring, 0); 205e3adcf8fSFrançois Tigeot intel_ring_emit(ring, 0); 206e3adcf8fSFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 207e3adcf8fSFrançois Tigeot intel_ring_advance(ring); 208e3adcf8fSFrançois Tigeot 209e3adcf8fSFrançois Tigeot return 0; 210e3adcf8fSFrançois Tigeot } 211e3adcf8fSFrançois Tigeot 212e3adcf8fSFrançois Tigeot static int 213e3adcf8fSFrançois Tigeot gen6_render_ring_flush(struct intel_ring_buffer *ring, 214e3adcf8fSFrançois Tigeot u32 invalidate_domains, u32 flush_domains) 215e3adcf8fSFrançois Tigeot { 216e3adcf8fSFrançois Tigeot u32 flags = 0; 217e3adcf8fSFrançois Tigeot struct pipe_control *pc = ring->private; 218e3adcf8fSFrançois Tigeot u32 scratch_addr = pc->gtt_offset + 128; 219e3adcf8fSFrançois Tigeot int ret; 220e3adcf8fSFrançois Tigeot 221e3adcf8fSFrançois Tigeot /* Force SNB workarounds for PIPE_CONTROL flushes */ 222686a02f1SFrançois Tigeot ret = intel_emit_post_sync_nonzero_flush(ring); 223686a02f1SFrançois Tigeot if (ret) 224686a02f1SFrançois Tigeot return ret; 225e3adcf8fSFrançois Tigeot 226e3adcf8fSFrançois Tigeot /* Just flush everything. Experiments have shown that reducing the 227e3adcf8fSFrançois Tigeot * number of bits based on the write domains has little performance 228e3adcf8fSFrançois Tigeot * impact. 229e3adcf8fSFrançois Tigeot */ 230*b5c29a34SFrançois Tigeot if (flush_domains) { 231e3adcf8fSFrançois Tigeot flags |= PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH; 232*b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_DEPTH_CACHE_FLUSH; 233*b5c29a34SFrançois Tigeot /* 234*b5c29a34SFrançois Tigeot * Ensure that any following seqno writes only happen 235*b5c29a34SFrançois Tigeot * when the render cache is indeed flushed. 236*b5c29a34SFrançois Tigeot */ 237*b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_CS_STALL; 238*b5c29a34SFrançois Tigeot } 239*b5c29a34SFrançois Tigeot if (invalidate_domains) { 240686a02f1SFrançois Tigeot flags |= PIPE_CONTROL_TLB_INVALIDATE; 241e3adcf8fSFrançois Tigeot flags |= PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE; 242e3adcf8fSFrançois Tigeot flags |= PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE; 243e3adcf8fSFrançois Tigeot flags |= PIPE_CONTROL_VF_CACHE_INVALIDATE; 244e3adcf8fSFrançois Tigeot flags |= PIPE_CONTROL_CONST_CACHE_INVALIDATE; 245e3adcf8fSFrançois Tigeot flags |= PIPE_CONTROL_STATE_CACHE_INVALIDATE; 246686a02f1SFrançois Tigeot /* 247*b5c29a34SFrançois Tigeot * TLB invalidate requires a post-sync write. 248686a02f1SFrançois Tigeot */ 249*b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_QW_WRITE | PIPE_CONTROL_CS_STALL; 250*b5c29a34SFrançois Tigeot } 251e3adcf8fSFrançois Tigeot 252*b5c29a34SFrançois Tigeot ret = intel_ring_begin(ring, 4); 253e3adcf8fSFrançois Tigeot if (ret) 254e3adcf8fSFrançois Tigeot return ret; 255e3adcf8fSFrançois Tigeot 256*b5c29a34SFrançois Tigeot intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(4)); 257e3adcf8fSFrançois Tigeot intel_ring_emit(ring, flags); 258e3adcf8fSFrançois Tigeot intel_ring_emit(ring, scratch_addr | PIPE_CONTROL_GLOBAL_GTT); 259*b5c29a34SFrançois Tigeot intel_ring_emit(ring, 0); 260*b5c29a34SFrançois Tigeot intel_ring_advance(ring); 261*b5c29a34SFrançois Tigeot 262*b5c29a34SFrançois Tigeot return 0; 263*b5c29a34SFrançois Tigeot } 264*b5c29a34SFrançois Tigeot 265*b5c29a34SFrançois Tigeot static int 266*b5c29a34SFrançois Tigeot gen7_render_ring_cs_stall_wa(struct intel_ring_buffer *ring) 267*b5c29a34SFrançois Tigeot { 268*b5c29a34SFrançois Tigeot int ret; 269*b5c29a34SFrançois Tigeot 270*b5c29a34SFrançois Tigeot ret = intel_ring_begin(ring, 4); 271*b5c29a34SFrançois Tigeot if (ret) 272*b5c29a34SFrançois Tigeot return ret; 273*b5c29a34SFrançois Tigeot 274*b5c29a34SFrançois Tigeot intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(4)); 275*b5c29a34SFrançois Tigeot intel_ring_emit(ring, PIPE_CONTROL_CS_STALL | 276*b5c29a34SFrançois Tigeot PIPE_CONTROL_STALL_AT_SCOREBOARD); 277*b5c29a34SFrançois Tigeot intel_ring_emit(ring, 0); 278*b5c29a34SFrançois Tigeot intel_ring_emit(ring, 0); 279*b5c29a34SFrançois Tigeot intel_ring_advance(ring); 280*b5c29a34SFrançois Tigeot 281*b5c29a34SFrançois Tigeot return 0; 282*b5c29a34SFrançois Tigeot } 283*b5c29a34SFrançois Tigeot 284*b5c29a34SFrançois Tigeot static int 285*b5c29a34SFrançois Tigeot gen7_render_ring_flush(struct intel_ring_buffer *ring, 286*b5c29a34SFrançois Tigeot u32 invalidate_domains, u32 flush_domains) 287*b5c29a34SFrançois Tigeot { 288*b5c29a34SFrançois Tigeot u32 flags = 0; 289*b5c29a34SFrançois Tigeot struct pipe_control *pc = ring->private; 290*b5c29a34SFrançois Tigeot u32 scratch_addr = pc->gtt_offset + 128; 291*b5c29a34SFrançois Tigeot int ret; 292*b5c29a34SFrançois Tigeot 293*b5c29a34SFrançois Tigeot /* 294*b5c29a34SFrançois Tigeot * Ensure that any following seqno writes only happen when the render 295*b5c29a34SFrançois Tigeot * cache is indeed flushed. 296*b5c29a34SFrançois Tigeot * 297*b5c29a34SFrançois Tigeot * Workaround: 4th PIPE_CONTROL command (except the ones with only 298*b5c29a34SFrançois Tigeot * read-cache invalidate bits set) must have the CS_STALL bit set. We 299*b5c29a34SFrançois Tigeot * don't try to be clever and just set it unconditionally. 300*b5c29a34SFrançois Tigeot */ 301*b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_CS_STALL; 302*b5c29a34SFrançois Tigeot 303*b5c29a34SFrançois Tigeot /* Just flush everything. Experiments have shown that reducing the 304*b5c29a34SFrançois Tigeot * number of bits based on the write domains has little performance 305*b5c29a34SFrançois Tigeot * impact. 306*b5c29a34SFrançois Tigeot */ 307*b5c29a34SFrançois Tigeot if (flush_domains) { 308*b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH; 309*b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_DEPTH_CACHE_FLUSH; 310*b5c29a34SFrançois Tigeot } 311*b5c29a34SFrançois Tigeot if (invalidate_domains) { 312*b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_TLB_INVALIDATE; 313*b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE; 314*b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE; 315*b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_VF_CACHE_INVALIDATE; 316*b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_CONST_CACHE_INVALIDATE; 317*b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_STATE_CACHE_INVALIDATE; 318*b5c29a34SFrançois Tigeot /* 319*b5c29a34SFrançois Tigeot * TLB invalidate requires a post-sync write. 320*b5c29a34SFrançois Tigeot */ 321*b5c29a34SFrançois Tigeot flags |= PIPE_CONTROL_QW_WRITE; 322*b5c29a34SFrançois Tigeot 323*b5c29a34SFrançois Tigeot /* Workaround: we must issue a pipe_control with CS-stall bit 324*b5c29a34SFrançois Tigeot * set before a pipe_control command that has the state cache 325*b5c29a34SFrançois Tigeot * invalidate bit set. */ 326*b5c29a34SFrançois Tigeot gen7_render_ring_cs_stall_wa(ring); 327*b5c29a34SFrançois Tigeot } 328*b5c29a34SFrançois Tigeot 329*b5c29a34SFrançois Tigeot ret = intel_ring_begin(ring, 4); 330*b5c29a34SFrançois Tigeot if (ret) 331*b5c29a34SFrançois Tigeot return ret; 332*b5c29a34SFrançois Tigeot 333*b5c29a34SFrançois Tigeot intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(4)); 334*b5c29a34SFrançois Tigeot intel_ring_emit(ring, flags); 335*b5c29a34SFrançois Tigeot intel_ring_emit(ring, scratch_addr | PIPE_CONTROL_GLOBAL_GTT); 336*b5c29a34SFrançois Tigeot intel_ring_emit(ring, 0); 337e3adcf8fSFrançois Tigeot intel_ring_advance(ring); 338e3adcf8fSFrançois Tigeot 339e3adcf8fSFrançois Tigeot return 0; 340e3adcf8fSFrançois Tigeot } 341e3adcf8fSFrançois Tigeot 342e3adcf8fSFrançois Tigeot static void ring_write_tail(struct intel_ring_buffer *ring, 343*b5c29a34SFrançois Tigeot u32 value) 344e3adcf8fSFrançois Tigeot { 345e3adcf8fSFrançois Tigeot drm_i915_private_t *dev_priv = ring->dev->dev_private; 346e3adcf8fSFrançois Tigeot I915_WRITE_TAIL(ring, value); 347e3adcf8fSFrançois Tigeot } 348e3adcf8fSFrançois Tigeot 349e3adcf8fSFrançois Tigeot u32 intel_ring_get_active_head(struct intel_ring_buffer *ring) 350e3adcf8fSFrançois Tigeot { 351e3adcf8fSFrançois Tigeot drm_i915_private_t *dev_priv = ring->dev->dev_private; 352*b5c29a34SFrançois Tigeot u32 acthd_reg = INTEL_INFO(ring->dev)->gen >= 4 ? 353e3adcf8fSFrançois Tigeot RING_ACTHD(ring->mmio_base) : ACTHD; 354e3adcf8fSFrançois Tigeot 355e3adcf8fSFrançois Tigeot return I915_READ(acthd_reg); 356e3adcf8fSFrançois Tigeot } 357e3adcf8fSFrançois Tigeot 358e3adcf8fSFrançois Tigeot static int init_ring_common(struct intel_ring_buffer *ring) 359e3adcf8fSFrançois Tigeot { 360686a02f1SFrançois Tigeot struct drm_device *dev = ring->dev; 361686a02f1SFrançois Tigeot drm_i915_private_t *dev_priv = dev->dev_private; 362e3adcf8fSFrançois Tigeot struct drm_i915_gem_object *obj = ring->obj; 363686a02f1SFrançois Tigeot int ret = 0; 364*b5c29a34SFrançois Tigeot u32 head; 365e3adcf8fSFrançois Tigeot 366686a02f1SFrançois Tigeot if (HAS_FORCE_WAKE(dev)) 367686a02f1SFrançois Tigeot gen6_gt_force_wake_get(dev_priv); 368686a02f1SFrançois Tigeot 369e3adcf8fSFrançois Tigeot /* Stop the ring if it's running. */ 370e3adcf8fSFrançois Tigeot I915_WRITE_CTL(ring, 0); 371e3adcf8fSFrançois Tigeot I915_WRITE_HEAD(ring, 0); 372e3adcf8fSFrançois Tigeot ring->write_tail(ring, 0); 373e3adcf8fSFrançois Tigeot 374e3adcf8fSFrançois Tigeot head = I915_READ_HEAD(ring) & HEAD_ADDR; 375e3adcf8fSFrançois Tigeot 376e3adcf8fSFrançois Tigeot /* G45 ring initialization fails to reset head to zero */ 377e3adcf8fSFrançois Tigeot if (head != 0) { 378*b5c29a34SFrançois Tigeot DRM_DEBUG_KMS("%s head not reset to zero " 379e3adcf8fSFrançois Tigeot "ctl %08x head %08x tail %08x start %08x\n", 380e3adcf8fSFrançois Tigeot ring->name, 381e3adcf8fSFrançois Tigeot I915_READ_CTL(ring), 382e3adcf8fSFrançois Tigeot I915_READ_HEAD(ring), 383e3adcf8fSFrançois Tigeot I915_READ_TAIL(ring), 384e3adcf8fSFrançois Tigeot I915_READ_START(ring)); 385e3adcf8fSFrançois Tigeot 386e3adcf8fSFrançois Tigeot I915_WRITE_HEAD(ring, 0); 387e3adcf8fSFrançois Tigeot 388e3adcf8fSFrançois Tigeot if (I915_READ_HEAD(ring) & HEAD_ADDR) { 389e3adcf8fSFrançois Tigeot DRM_ERROR("failed to set %s head to zero " 390e3adcf8fSFrançois Tigeot "ctl %08x head %08x tail %08x start %08x\n", 391e3adcf8fSFrançois Tigeot ring->name, 392e3adcf8fSFrançois Tigeot I915_READ_CTL(ring), 393e3adcf8fSFrançois Tigeot I915_READ_HEAD(ring), 394e3adcf8fSFrançois Tigeot I915_READ_TAIL(ring), 395e3adcf8fSFrançois Tigeot I915_READ_START(ring)); 396e3adcf8fSFrançois Tigeot } 397e3adcf8fSFrançois Tigeot } 398e3adcf8fSFrançois Tigeot 399*b5c29a34SFrançois Tigeot /* Initialize the ring. This must happen _after_ we've cleared the ring 400*b5c29a34SFrançois Tigeot * registers with the above sequence (the readback of the HEAD registers 401*b5c29a34SFrançois Tigeot * also enforces ordering), otherwise the hw might lose the new ring 402*b5c29a34SFrançois Tigeot * register values. */ 403*b5c29a34SFrançois Tigeot I915_WRITE_START(ring, obj->gtt_offset); 404e3adcf8fSFrançois Tigeot I915_WRITE_CTL(ring, 405e3adcf8fSFrançois Tigeot ((ring->size - PAGE_SIZE) & RING_NR_PAGES) 406e3adcf8fSFrançois Tigeot | RING_VALID); 407e3adcf8fSFrançois Tigeot 408e3adcf8fSFrançois Tigeot /* If the head is still not zero, the ring is dead */ 409*b5c29a34SFrançois Tigeot if (wait_for((I915_READ_CTL(ring) & RING_VALID) != 0 && 410e3adcf8fSFrançois Tigeot I915_READ_START(ring) == obj->gtt_offset && 411*b5c29a34SFrançois Tigeot (I915_READ_HEAD(ring) & HEAD_ADDR) == 0, 50)) { 412e3adcf8fSFrançois Tigeot DRM_ERROR("%s initialization failed " 413e3adcf8fSFrançois Tigeot "ctl %08x head %08x tail %08x start %08x\n", 414e3adcf8fSFrançois Tigeot ring->name, 415e3adcf8fSFrançois Tigeot I915_READ_CTL(ring), 416e3adcf8fSFrançois Tigeot I915_READ_HEAD(ring), 417e3adcf8fSFrançois Tigeot I915_READ_TAIL(ring), 418e3adcf8fSFrançois Tigeot I915_READ_START(ring)); 419686a02f1SFrançois Tigeot ret = -EIO; 420686a02f1SFrançois Tigeot goto out; 421e3adcf8fSFrançois Tigeot } 422e3adcf8fSFrançois Tigeot 423e3adcf8fSFrançois Tigeot if (!drm_core_check_feature(ring->dev, DRIVER_MODESET)) 424e3adcf8fSFrançois Tigeot i915_kernel_lost_context(ring->dev); 425e3adcf8fSFrançois Tigeot else { 426e3adcf8fSFrançois Tigeot ring->head = I915_READ_HEAD(ring); 427e3adcf8fSFrançois Tigeot ring->tail = I915_READ_TAIL(ring) & TAIL_ADDR; 428e3adcf8fSFrançois Tigeot ring->space = ring_space(ring); 429686a02f1SFrançois Tigeot ring->last_retired_head = -1; 430e3adcf8fSFrançois Tigeot } 431e3adcf8fSFrançois Tigeot 432686a02f1SFrançois Tigeot out: 433686a02f1SFrançois Tigeot if (HAS_FORCE_WAKE(dev)) 434686a02f1SFrançois Tigeot gen6_gt_force_wake_put(dev_priv); 435686a02f1SFrançois Tigeot 436686a02f1SFrançois Tigeot return ret; 437e3adcf8fSFrançois Tigeot } 438e3adcf8fSFrançois Tigeot 439e3adcf8fSFrançois Tigeot static int 440e3adcf8fSFrançois Tigeot init_pipe_control(struct intel_ring_buffer *ring) 441e3adcf8fSFrançois Tigeot { 442e3adcf8fSFrançois Tigeot struct pipe_control *pc; 443e3adcf8fSFrançois Tigeot struct drm_i915_gem_object *obj; 444e3adcf8fSFrançois Tigeot int ret; 445e3adcf8fSFrançois Tigeot 446e3adcf8fSFrançois Tigeot if (ring->private) 447e3adcf8fSFrançois Tigeot return 0; 448e3adcf8fSFrançois Tigeot 449e3adcf8fSFrançois Tigeot pc = kmalloc(sizeof(*pc), DRM_I915_GEM, M_WAITOK); 450e3adcf8fSFrançois Tigeot if (!pc) 451e3adcf8fSFrançois Tigeot return -ENOMEM; 452e3adcf8fSFrançois Tigeot 453e3adcf8fSFrançois Tigeot obj = i915_gem_alloc_object(ring->dev, 4096); 454e3adcf8fSFrançois Tigeot if (obj == NULL) { 455e3adcf8fSFrançois Tigeot DRM_ERROR("Failed to allocate seqno page\n"); 456e3adcf8fSFrançois Tigeot ret = -ENOMEM; 457e3adcf8fSFrançois Tigeot goto err; 458e3adcf8fSFrançois Tigeot } 459e3adcf8fSFrançois Tigeot 460e3adcf8fSFrançois Tigeot i915_gem_object_set_cache_level(obj, I915_CACHE_LLC); 461e3adcf8fSFrançois Tigeot 462e3adcf8fSFrançois Tigeot ret = i915_gem_object_pin(obj, 4096, true); 463e3adcf8fSFrançois Tigeot if (ret) 464e3adcf8fSFrançois Tigeot goto err_unref; 465e3adcf8fSFrançois Tigeot 466e3adcf8fSFrançois Tigeot pc->gtt_offset = obj->gtt_offset; 467e3adcf8fSFrançois Tigeot pc->cpu_page = (uint32_t *)kmem_alloc_nofault(&kernel_map, PAGE_SIZE, PAGE_SIZE); 468e3adcf8fSFrançois Tigeot if (pc->cpu_page == NULL) 469e3adcf8fSFrançois Tigeot goto err_unpin; 470e3adcf8fSFrançois Tigeot pmap_qenter((uintptr_t)pc->cpu_page, &obj->pages[0], 1); 471e3adcf8fSFrançois Tigeot pmap_invalidate_cache_range((vm_offset_t)pc->cpu_page, 472e3adcf8fSFrançois Tigeot (vm_offset_t)pc->cpu_page + PAGE_SIZE); 473e3adcf8fSFrançois Tigeot 474e3adcf8fSFrançois Tigeot pc->obj = obj; 475e3adcf8fSFrançois Tigeot ring->private = pc; 476e3adcf8fSFrançois Tigeot return 0; 477e3adcf8fSFrançois Tigeot 478e3adcf8fSFrançois Tigeot err_unpin: 479e3adcf8fSFrançois Tigeot i915_gem_object_unpin(obj); 480e3adcf8fSFrançois Tigeot err_unref: 481e3adcf8fSFrançois Tigeot drm_gem_object_unreference(&obj->base); 482e3adcf8fSFrançois Tigeot err: 483e3adcf8fSFrançois Tigeot drm_free(pc, DRM_I915_GEM); 484e3adcf8fSFrançois Tigeot return ret; 485e3adcf8fSFrançois Tigeot } 486e3adcf8fSFrançois Tigeot 487e3adcf8fSFrançois Tigeot static void 488e3adcf8fSFrançois Tigeot cleanup_pipe_control(struct intel_ring_buffer *ring) 489e3adcf8fSFrançois Tigeot { 490e3adcf8fSFrançois Tigeot struct pipe_control *pc = ring->private; 491e3adcf8fSFrançois Tigeot struct drm_i915_gem_object *obj; 492e3adcf8fSFrançois Tigeot 493e3adcf8fSFrançois Tigeot if (!ring->private) 494e3adcf8fSFrançois Tigeot return; 495e3adcf8fSFrançois Tigeot 496e3adcf8fSFrançois Tigeot obj = pc->obj; 497e3adcf8fSFrançois Tigeot pmap_qremove((vm_offset_t)pc->cpu_page, 1); 498e3adcf8fSFrançois Tigeot kmem_free(&kernel_map, (uintptr_t)pc->cpu_page, PAGE_SIZE); 499e3adcf8fSFrançois Tigeot i915_gem_object_unpin(obj); 500e3adcf8fSFrançois Tigeot drm_gem_object_unreference(&obj->base); 501e3adcf8fSFrançois Tigeot 502e3adcf8fSFrançois Tigeot drm_free(pc, DRM_I915_GEM); 503e3adcf8fSFrançois Tigeot ring->private = NULL; 504e3adcf8fSFrançois Tigeot } 505e3adcf8fSFrançois Tigeot 506e3adcf8fSFrançois Tigeot static int init_render_ring(struct intel_ring_buffer *ring) 507e3adcf8fSFrançois Tigeot { 508e3adcf8fSFrançois Tigeot struct drm_device *dev = ring->dev; 509e3adcf8fSFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 510e3adcf8fSFrançois Tigeot int ret = init_ring_common(ring); 511e3adcf8fSFrançois Tigeot 512f4e1c372SFrançois Tigeot if (INTEL_INFO(dev)->gen > 3) 513f4e1c372SFrançois Tigeot I915_WRITE(MI_MODE, _MASKED_BIT_ENABLE(VS_TIMER_DISPATCH)); 514f4e1c372SFrançois Tigeot 515f4e1c372SFrançois Tigeot /* We need to disable the AsyncFlip performance optimisations in order 516f4e1c372SFrançois Tigeot * to use MI_WAIT_FOR_EVENT within the CS. It should already be 517f4e1c372SFrançois Tigeot * programmed to '1' on all products. 518f4e1c372SFrançois Tigeot */ 519f4e1c372SFrançois Tigeot if (INTEL_INFO(dev)->gen >= 6) 520f4e1c372SFrançois Tigeot I915_WRITE(MI_MODE, _MASKED_BIT_ENABLE(ASYNC_FLIP_PERF_DISABLE)); 521f4e1c372SFrançois Tigeot 522f4e1c372SFrançois Tigeot /* Required for the hardware to program scanline values for waiting */ 523f4e1c372SFrançois Tigeot if (INTEL_INFO(dev)->gen == 6) 524f4e1c372SFrançois Tigeot I915_WRITE(GFX_MODE, 525f4e1c372SFrançois Tigeot _MASKED_BIT_ENABLE(GFX_TLB_INVALIDATE_ALWAYS)); 526f4e1c372SFrançois Tigeot 527e3adcf8fSFrançois Tigeot if (IS_GEN7(dev)) 528e3adcf8fSFrançois Tigeot I915_WRITE(GFX_MODE_GEN7, 529f4e1c372SFrançois Tigeot _MASKED_BIT_DISABLE(GFX_TLB_INVALIDATE_ALWAYS) | 530f4e1c372SFrançois Tigeot _MASKED_BIT_ENABLE(GFX_REPLAY_MODE)); 531e3adcf8fSFrançois Tigeot 532e3adcf8fSFrançois Tigeot if (INTEL_INFO(dev)->gen >= 5) { 533e3adcf8fSFrançois Tigeot ret = init_pipe_control(ring); 534e3adcf8fSFrançois Tigeot if (ret) 535e3adcf8fSFrançois Tigeot return ret; 536e3adcf8fSFrançois Tigeot } 537e3adcf8fSFrançois Tigeot 538e3adcf8fSFrançois Tigeot if (IS_GEN6(dev)) { 539e3adcf8fSFrançois Tigeot /* From the Sandybridge PRM, volume 1 part 3, page 24: 540e3adcf8fSFrançois Tigeot * "If this bit is set, STCunit will have LRA as replacement 541e3adcf8fSFrançois Tigeot * policy. [...] This bit must be reset. LRA replacement 542e3adcf8fSFrançois Tigeot * policy is not supported." 543e3adcf8fSFrançois Tigeot */ 544e3adcf8fSFrançois Tigeot I915_WRITE(CACHE_MODE_0, 545f4e1c372SFrançois Tigeot _MASKED_BIT_DISABLE(CM0_STC_EVICT_DISABLE_LRA_SNB)); 546686a02f1SFrançois Tigeot 547686a02f1SFrançois Tigeot /* This is not explicitly set for GEN6, so read the register. 548686a02f1SFrançois Tigeot * see intel_ring_mi_set_context() for why we care. 549686a02f1SFrançois Tigeot * TODO: consider explicitly setting the bit for GEN5 550686a02f1SFrançois Tigeot */ 551686a02f1SFrançois Tigeot ring->itlb_before_ctx_switch = 552686a02f1SFrançois Tigeot !!(I915_READ(GFX_MODE) & GFX_TLB_INVALIDATE_ALWAYS); 553e3adcf8fSFrançois Tigeot } 554e3adcf8fSFrançois Tigeot 555f4e1c372SFrançois Tigeot if (INTEL_INFO(dev)->gen >= 6) 556f4e1c372SFrançois Tigeot I915_WRITE(INSTPM, _MASKED_BIT_ENABLE(INSTPM_FORCE_ORDERING)); 557f4e1c372SFrançois Tigeot 558f4e1c372SFrançois Tigeot if (HAS_L3_GPU_CACHE(dev)) 559f4e1c372SFrançois Tigeot I915_WRITE_IMR(ring, ~GEN6_RENDER_L3_PARITY_ERROR); 560e3adcf8fSFrançois Tigeot 561e3adcf8fSFrançois Tigeot return ret; 562e3adcf8fSFrançois Tigeot } 563e3adcf8fSFrançois Tigeot 564e3adcf8fSFrançois Tigeot static void render_ring_cleanup(struct intel_ring_buffer *ring) 565e3adcf8fSFrançois Tigeot { 566*b5c29a34SFrançois Tigeot struct drm_device *dev = ring->dev; 567*b5c29a34SFrançois Tigeot 568e3adcf8fSFrançois Tigeot if (!ring->private) 569e3adcf8fSFrançois Tigeot return; 570e3adcf8fSFrançois Tigeot 571*b5c29a34SFrançois Tigeot if (HAS_BROKEN_CS_TLB(dev)) 572*b5c29a34SFrançois Tigeot drm_gem_object_unreference(to_gem_object(ring->private)); 573*b5c29a34SFrançois Tigeot 574e3adcf8fSFrançois Tigeot cleanup_pipe_control(ring); 575e3adcf8fSFrançois Tigeot } 576e3adcf8fSFrançois Tigeot 577e3adcf8fSFrançois Tigeot static void 578e3adcf8fSFrançois Tigeot update_mboxes(struct intel_ring_buffer *ring, 579e3adcf8fSFrançois Tigeot u32 mmio_offset) 580e3adcf8fSFrançois Tigeot { 581*b5c29a34SFrançois Tigeot intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1)); 582e3adcf8fSFrançois Tigeot intel_ring_emit(ring, mmio_offset); 583*b5c29a34SFrançois Tigeot intel_ring_emit(ring, ring->outstanding_lazy_request); 584e3adcf8fSFrançois Tigeot } 585e3adcf8fSFrançois Tigeot 586e3adcf8fSFrançois Tigeot /** 587e3adcf8fSFrançois Tigeot * gen6_add_request - Update the semaphore mailbox registers 588e3adcf8fSFrançois Tigeot * 589e3adcf8fSFrançois Tigeot * @ring - ring that is adding a request 590e3adcf8fSFrançois Tigeot * @seqno - return seqno stuck into the ring 591e3adcf8fSFrançois Tigeot * 592e3adcf8fSFrançois Tigeot * Update the mailbox registers in the *other* rings with the current seqno. 593e3adcf8fSFrançois Tigeot * This acts like a signal in the canonical semaphore. 594e3adcf8fSFrançois Tigeot */ 595e3adcf8fSFrançois Tigeot static int 596*b5c29a34SFrançois Tigeot gen6_add_request(struct intel_ring_buffer *ring) 597e3adcf8fSFrançois Tigeot { 598e3adcf8fSFrançois Tigeot u32 mbox1_reg; 599e3adcf8fSFrançois Tigeot u32 mbox2_reg; 600e3adcf8fSFrançois Tigeot int ret; 601e3adcf8fSFrançois Tigeot 602e3adcf8fSFrançois Tigeot ret = intel_ring_begin(ring, 10); 603e3adcf8fSFrançois Tigeot if (ret) 604e3adcf8fSFrançois Tigeot return ret; 605e3adcf8fSFrançois Tigeot 606e3adcf8fSFrançois Tigeot mbox1_reg = ring->signal_mbox[0]; 607e3adcf8fSFrançois Tigeot mbox2_reg = ring->signal_mbox[1]; 608e3adcf8fSFrançois Tigeot 609*b5c29a34SFrançois Tigeot update_mboxes(ring, mbox1_reg); 610*b5c29a34SFrançois Tigeot update_mboxes(ring, mbox2_reg); 611e3adcf8fSFrançois Tigeot intel_ring_emit(ring, MI_STORE_DWORD_INDEX); 612e3adcf8fSFrançois Tigeot intel_ring_emit(ring, I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT); 613*b5c29a34SFrançois Tigeot intel_ring_emit(ring, ring->outstanding_lazy_request); 614e3adcf8fSFrançois Tigeot intel_ring_emit(ring, MI_USER_INTERRUPT); 615e3adcf8fSFrançois Tigeot intel_ring_advance(ring); 616e3adcf8fSFrançois Tigeot 617e3adcf8fSFrançois Tigeot return 0; 618e3adcf8fSFrançois Tigeot } 619e3adcf8fSFrançois Tigeot 620e3adcf8fSFrançois Tigeot /** 621e3adcf8fSFrançois Tigeot * intel_ring_sync - sync the waiter to the signaller on seqno 622e3adcf8fSFrançois Tigeot * 623e3adcf8fSFrançois Tigeot * @waiter - ring that is waiting 624e3adcf8fSFrançois Tigeot * @signaller - ring which has, or will signal 625e3adcf8fSFrançois Tigeot * @seqno - seqno which the waiter will block on 626e3adcf8fSFrançois Tigeot */ 627e3adcf8fSFrançois Tigeot static int 628686a02f1SFrançois Tigeot gen6_ring_sync(struct intel_ring_buffer *waiter, 629e3adcf8fSFrançois Tigeot struct intel_ring_buffer *signaller, 630e3adcf8fSFrançois Tigeot u32 seqno) 631e3adcf8fSFrançois Tigeot { 632e3adcf8fSFrançois Tigeot int ret; 633e3adcf8fSFrançois Tigeot u32 dw1 = MI_SEMAPHORE_MBOX | 634e3adcf8fSFrançois Tigeot MI_SEMAPHORE_COMPARE | 635e3adcf8fSFrançois Tigeot MI_SEMAPHORE_REGISTER; 636e3adcf8fSFrançois Tigeot 637686a02f1SFrançois Tigeot /* Throughout all of the GEM code, seqno passed implies our current 638686a02f1SFrançois Tigeot * seqno is >= the last seqno executed. However for hardware the 639686a02f1SFrançois Tigeot * comparison is strictly greater than. 640686a02f1SFrançois Tigeot */ 641686a02f1SFrançois Tigeot seqno -= 1; 642686a02f1SFrançois Tigeot 643686a02f1SFrançois Tigeot WARN_ON(signaller->semaphore_register[waiter->id] == 644686a02f1SFrançois Tigeot MI_SEMAPHORE_SYNC_INVALID); 645686a02f1SFrançois Tigeot 646e3adcf8fSFrançois Tigeot ret = intel_ring_begin(waiter, 4); 647e3adcf8fSFrançois Tigeot if (ret) 648e3adcf8fSFrançois Tigeot return ret; 649e3adcf8fSFrançois Tigeot 650686a02f1SFrançois Tigeot intel_ring_emit(waiter, 651686a02f1SFrançois Tigeot dw1 | signaller->semaphore_register[waiter->id]); 652e3adcf8fSFrançois Tigeot intel_ring_emit(waiter, seqno); 653e3adcf8fSFrançois Tigeot intel_ring_emit(waiter, 0); 654e3adcf8fSFrançois Tigeot intel_ring_emit(waiter, MI_NOOP); 655e3adcf8fSFrançois Tigeot intel_ring_advance(waiter); 656e3adcf8fSFrançois Tigeot 657e3adcf8fSFrançois Tigeot return 0; 658e3adcf8fSFrançois Tigeot } 659e3adcf8fSFrançois Tigeot 660e3adcf8fSFrançois Tigeot #define PIPE_CONTROL_FLUSH(ring__, addr__) \ 661e3adcf8fSFrançois Tigeot do { \ 662e3adcf8fSFrançois Tigeot intel_ring_emit(ring__, GFX_OP_PIPE_CONTROL(4) | PIPE_CONTROL_QW_WRITE | \ 663e3adcf8fSFrançois Tigeot PIPE_CONTROL_DEPTH_STALL); \ 664e3adcf8fSFrançois Tigeot intel_ring_emit(ring__, (addr__) | PIPE_CONTROL_GLOBAL_GTT); \ 665e3adcf8fSFrançois Tigeot intel_ring_emit(ring__, 0); \ 666e3adcf8fSFrançois Tigeot intel_ring_emit(ring__, 0); \ 667e3adcf8fSFrançois Tigeot } while (0) 668e3adcf8fSFrançois Tigeot 669e3adcf8fSFrançois Tigeot static int 670*b5c29a34SFrançois Tigeot pc_render_add_request(struct intel_ring_buffer *ring) 671e3adcf8fSFrançois Tigeot { 672e3adcf8fSFrançois Tigeot struct pipe_control *pc = ring->private; 673e3adcf8fSFrançois Tigeot u32 scratch_addr = pc->gtt_offset + 128; 674e3adcf8fSFrançois Tigeot int ret; 675e3adcf8fSFrançois Tigeot 676e3adcf8fSFrançois Tigeot /* For Ironlake, MI_USER_INTERRUPT was deprecated and apparently 677e3adcf8fSFrançois Tigeot * incoherent with writes to memory, i.e. completely fubar, 678e3adcf8fSFrançois Tigeot * so we need to use PIPE_NOTIFY instead. 679e3adcf8fSFrançois Tigeot * 680e3adcf8fSFrançois Tigeot * However, we also need to workaround the qword write 681e3adcf8fSFrançois Tigeot * incoherence by flushing the 6 PIPE_NOTIFY buffers out to 682e3adcf8fSFrançois Tigeot * memory before requesting an interrupt. 683e3adcf8fSFrançois Tigeot */ 684e3adcf8fSFrançois Tigeot ret = intel_ring_begin(ring, 32); 685e3adcf8fSFrançois Tigeot if (ret) 686e3adcf8fSFrançois Tigeot return ret; 687e3adcf8fSFrançois Tigeot 688e3adcf8fSFrançois Tigeot intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(4) | PIPE_CONTROL_QW_WRITE | 689e3adcf8fSFrançois Tigeot PIPE_CONTROL_WRITE_FLUSH | 690e3adcf8fSFrançois Tigeot PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE); 691e3adcf8fSFrançois Tigeot intel_ring_emit(ring, pc->gtt_offset | PIPE_CONTROL_GLOBAL_GTT); 692*b5c29a34SFrançois Tigeot intel_ring_emit(ring, ring->outstanding_lazy_request); 693e3adcf8fSFrançois Tigeot intel_ring_emit(ring, 0); 694e3adcf8fSFrançois Tigeot PIPE_CONTROL_FLUSH(ring, scratch_addr); 695e3adcf8fSFrançois Tigeot scratch_addr += 128; /* write to separate cachelines */ 696e3adcf8fSFrançois Tigeot PIPE_CONTROL_FLUSH(ring, scratch_addr); 697e3adcf8fSFrançois Tigeot scratch_addr += 128; 698e3adcf8fSFrançois Tigeot PIPE_CONTROL_FLUSH(ring, scratch_addr); 699e3adcf8fSFrançois Tigeot scratch_addr += 128; 700e3adcf8fSFrançois Tigeot PIPE_CONTROL_FLUSH(ring, scratch_addr); 701e3adcf8fSFrançois Tigeot scratch_addr += 128; 702e3adcf8fSFrançois Tigeot PIPE_CONTROL_FLUSH(ring, scratch_addr); 703e3adcf8fSFrançois Tigeot scratch_addr += 128; 704e3adcf8fSFrançois Tigeot PIPE_CONTROL_FLUSH(ring, scratch_addr); 705*b5c29a34SFrançois Tigeot 706e3adcf8fSFrançois Tigeot intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(4) | PIPE_CONTROL_QW_WRITE | 707e3adcf8fSFrançois Tigeot PIPE_CONTROL_WRITE_FLUSH | 708e3adcf8fSFrançois Tigeot PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE | 709e3adcf8fSFrançois Tigeot PIPE_CONTROL_NOTIFY); 710e3adcf8fSFrançois Tigeot intel_ring_emit(ring, pc->gtt_offset | PIPE_CONTROL_GLOBAL_GTT); 711*b5c29a34SFrançois Tigeot intel_ring_emit(ring, ring->outstanding_lazy_request); 712e3adcf8fSFrançois Tigeot intel_ring_emit(ring, 0); 713e3adcf8fSFrançois Tigeot intel_ring_advance(ring); 714e3adcf8fSFrançois Tigeot 715e3adcf8fSFrançois Tigeot return 0; 716e3adcf8fSFrançois Tigeot } 717e3adcf8fSFrançois Tigeot 718e3adcf8fSFrançois Tigeot static u32 719b030f26bSFrançois Tigeot gen6_ring_get_seqno(struct intel_ring_buffer *ring, bool lazy_coherency) 720e3adcf8fSFrançois Tigeot { 721e3adcf8fSFrançois Tigeot /* Workaround to force correct ordering between irq and seqno writes on 722e3adcf8fSFrançois Tigeot * ivb (and maybe also on snb) by reading from a CS register (like 723e3adcf8fSFrançois Tigeot * ACTHD) before reading the status page. */ 724b030f26bSFrançois Tigeot if (!lazy_coherency) 725e3adcf8fSFrançois Tigeot intel_ring_get_active_head(ring); 726e3adcf8fSFrançois Tigeot return intel_read_status_page(ring, I915_GEM_HWS_INDEX); 727e3adcf8fSFrançois Tigeot } 728e3adcf8fSFrançois Tigeot 729b030f26bSFrançois Tigeot static u32 730b030f26bSFrançois Tigeot ring_get_seqno(struct intel_ring_buffer *ring, bool lazy_coherency) 731e3adcf8fSFrançois Tigeot { 732e3adcf8fSFrançois Tigeot return intel_read_status_page(ring, I915_GEM_HWS_INDEX); 733e3adcf8fSFrançois Tigeot } 734e3adcf8fSFrançois Tigeot 735b030f26bSFrançois Tigeot static u32 736b030f26bSFrançois Tigeot pc_render_get_seqno(struct intel_ring_buffer *ring, bool lazy_coherency) 737e3adcf8fSFrançois Tigeot { 738e3adcf8fSFrançois Tigeot struct pipe_control *pc = ring->private; 739e3adcf8fSFrançois Tigeot return pc->cpu_page[0]; 740e3adcf8fSFrançois Tigeot } 741e3adcf8fSFrançois Tigeot 742e3adcf8fSFrançois Tigeot static bool 743686a02f1SFrançois Tigeot gen5_ring_get_irq(struct intel_ring_buffer *ring) 744e3adcf8fSFrançois Tigeot { 745e3adcf8fSFrançois Tigeot struct drm_device *dev = ring->dev; 746e3adcf8fSFrançois Tigeot drm_i915_private_t *dev_priv = dev->dev_private; 747e3adcf8fSFrançois Tigeot 748e3adcf8fSFrançois Tigeot if (!dev->irq_enabled) 749e3adcf8fSFrançois Tigeot return false; 750e3adcf8fSFrançois Tigeot 75102727ecdSFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_EXCLUSIVE); 752e3adcf8fSFrançois Tigeot if (ring->irq_refcount++ == 0) { 753686a02f1SFrançois Tigeot dev_priv->gt_irq_mask &= ~ring->irq_enable_mask; 754686a02f1SFrançois Tigeot I915_WRITE(GTIMR, dev_priv->gt_irq_mask); 755686a02f1SFrançois Tigeot POSTING_READ(GTIMR); 756e3adcf8fSFrançois Tigeot } 75702727ecdSFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_RELEASE); 758e3adcf8fSFrançois Tigeot 759e3adcf8fSFrançois Tigeot return true; 760e3adcf8fSFrançois Tigeot } 761e3adcf8fSFrançois Tigeot 762e3adcf8fSFrançois Tigeot static void 763686a02f1SFrançois Tigeot gen5_ring_put_irq(struct intel_ring_buffer *ring) 764e3adcf8fSFrançois Tigeot { 765e3adcf8fSFrançois Tigeot struct drm_device *dev = ring->dev; 766e3adcf8fSFrançois Tigeot drm_i915_private_t *dev_priv = dev->dev_private; 767e3adcf8fSFrançois Tigeot 76802727ecdSFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_EXCLUSIVE); 769e3adcf8fSFrançois Tigeot if (--ring->irq_refcount == 0) { 770686a02f1SFrançois Tigeot dev_priv->gt_irq_mask |= ring->irq_enable_mask; 771686a02f1SFrançois Tigeot I915_WRITE(GTIMR, dev_priv->gt_irq_mask); 772686a02f1SFrançois Tigeot POSTING_READ(GTIMR); 773686a02f1SFrançois Tigeot } 774686a02f1SFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_RELEASE); 775686a02f1SFrançois Tigeot } 776686a02f1SFrançois Tigeot 777686a02f1SFrançois Tigeot static bool 778686a02f1SFrançois Tigeot i9xx_ring_get_irq(struct intel_ring_buffer *ring) 779686a02f1SFrançois Tigeot { 780686a02f1SFrançois Tigeot struct drm_device *dev = ring->dev; 781686a02f1SFrançois Tigeot drm_i915_private_t *dev_priv = dev->dev_private; 782686a02f1SFrançois Tigeot 783686a02f1SFrançois Tigeot if (!dev->irq_enabled) 784686a02f1SFrançois Tigeot return false; 785686a02f1SFrançois Tigeot 786686a02f1SFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_EXCLUSIVE); 787686a02f1SFrançois Tigeot if (ring->irq_refcount++ == 0) { 788686a02f1SFrançois Tigeot dev_priv->irq_mask &= ~ring->irq_enable_mask; 789686a02f1SFrançois Tigeot I915_WRITE(IMR, dev_priv->irq_mask); 790686a02f1SFrançois Tigeot POSTING_READ(IMR); 791686a02f1SFrançois Tigeot } 792686a02f1SFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_RELEASE); 793686a02f1SFrançois Tigeot 794686a02f1SFrançois Tigeot return true; 795686a02f1SFrançois Tigeot } 796686a02f1SFrançois Tigeot 797686a02f1SFrançois Tigeot static void 798686a02f1SFrançois Tigeot i9xx_ring_put_irq(struct intel_ring_buffer *ring) 799686a02f1SFrançois Tigeot { 800686a02f1SFrançois Tigeot struct drm_device *dev = ring->dev; 801686a02f1SFrançois Tigeot drm_i915_private_t *dev_priv = dev->dev_private; 802686a02f1SFrançois Tigeot 803686a02f1SFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_EXCLUSIVE); 804686a02f1SFrançois Tigeot if (--ring->irq_refcount == 0) { 805686a02f1SFrançois Tigeot dev_priv->irq_mask |= ring->irq_enable_mask; 806686a02f1SFrançois Tigeot I915_WRITE(IMR, dev_priv->irq_mask); 807686a02f1SFrançois Tigeot POSTING_READ(IMR); 808686a02f1SFrançois Tigeot } 809686a02f1SFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_RELEASE); 810686a02f1SFrançois Tigeot } 811686a02f1SFrançois Tigeot 812686a02f1SFrançois Tigeot static bool 813686a02f1SFrançois Tigeot i8xx_ring_get_irq(struct intel_ring_buffer *ring) 814686a02f1SFrançois Tigeot { 815686a02f1SFrançois Tigeot struct drm_device *dev = ring->dev; 816686a02f1SFrançois Tigeot drm_i915_private_t *dev_priv = dev->dev_private; 817686a02f1SFrançois Tigeot 818686a02f1SFrançois Tigeot if (!dev->irq_enabled) 819686a02f1SFrançois Tigeot return false; 820686a02f1SFrançois Tigeot 821686a02f1SFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_EXCLUSIVE); 822686a02f1SFrançois Tigeot if (ring->irq_refcount++ == 0) { 823686a02f1SFrançois Tigeot dev_priv->irq_mask &= ~ring->irq_enable_mask; 824686a02f1SFrançois Tigeot I915_WRITE16(IMR, dev_priv->irq_mask); 825686a02f1SFrançois Tigeot POSTING_READ16(IMR); 826686a02f1SFrançois Tigeot } 827686a02f1SFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_RELEASE); 828686a02f1SFrançois Tigeot 829686a02f1SFrançois Tigeot return true; 830686a02f1SFrançois Tigeot } 831686a02f1SFrançois Tigeot 832686a02f1SFrançois Tigeot static void 833686a02f1SFrançois Tigeot i8xx_ring_put_irq(struct intel_ring_buffer *ring) 834686a02f1SFrançois Tigeot { 835686a02f1SFrançois Tigeot struct drm_device *dev = ring->dev; 836686a02f1SFrançois Tigeot drm_i915_private_t *dev_priv = dev->dev_private; 837686a02f1SFrançois Tigeot 838686a02f1SFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_EXCLUSIVE); 839686a02f1SFrançois Tigeot if (--ring->irq_refcount == 0) { 840686a02f1SFrançois Tigeot dev_priv->irq_mask |= ring->irq_enable_mask; 841686a02f1SFrançois Tigeot I915_WRITE16(IMR, dev_priv->irq_mask); 842686a02f1SFrançois Tigeot POSTING_READ16(IMR); 843e3adcf8fSFrançois Tigeot } 84402727ecdSFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_RELEASE); 845e3adcf8fSFrançois Tigeot } 846e3adcf8fSFrançois Tigeot 847e3adcf8fSFrançois Tigeot void intel_ring_setup_status_page(struct intel_ring_buffer *ring) 848e3adcf8fSFrançois Tigeot { 849e3adcf8fSFrançois Tigeot struct drm_device *dev = ring->dev; 850*b5c29a34SFrançois Tigeot drm_i915_private_t *dev_priv = ring->dev->dev_private; 851*b5c29a34SFrançois Tigeot u32 mmio = 0; 852e3adcf8fSFrançois Tigeot 853e3adcf8fSFrançois Tigeot /* The ring status page addresses are no longer next to the rest of 854e3adcf8fSFrançois Tigeot * the ring registers as of gen7. 855e3adcf8fSFrançois Tigeot */ 856e3adcf8fSFrançois Tigeot if (IS_GEN7(dev)) { 857e3adcf8fSFrançois Tigeot switch (ring->id) { 858e3adcf8fSFrançois Tigeot case RCS: 859e3adcf8fSFrançois Tigeot mmio = RENDER_HWS_PGA_GEN7; 860e3adcf8fSFrançois Tigeot break; 861e3adcf8fSFrançois Tigeot case BCS: 862e3adcf8fSFrançois Tigeot mmio = BLT_HWS_PGA_GEN7; 863e3adcf8fSFrançois Tigeot break; 864e3adcf8fSFrançois Tigeot case VCS: 865e3adcf8fSFrançois Tigeot mmio = BSD_HWS_PGA_GEN7; 866e3adcf8fSFrançois Tigeot break; 867e3adcf8fSFrançois Tigeot } 868*b5c29a34SFrançois Tigeot } else if (IS_GEN6(ring->dev)) { 869e3adcf8fSFrançois Tigeot mmio = RING_HWS_PGA_GEN6(ring->mmio_base); 870e3adcf8fSFrançois Tigeot } else { 871e3adcf8fSFrançois Tigeot mmio = RING_HWS_PGA(ring->mmio_base); 872e3adcf8fSFrançois Tigeot } 873e3adcf8fSFrançois Tigeot 874e3adcf8fSFrançois Tigeot I915_WRITE(mmio, (u32)ring->status_page.gfx_addr); 875e3adcf8fSFrançois Tigeot POSTING_READ(mmio); 876e3adcf8fSFrançois Tigeot } 877e3adcf8fSFrançois Tigeot 878e3adcf8fSFrançois Tigeot static int 879e3adcf8fSFrançois Tigeot bsd_ring_flush(struct intel_ring_buffer *ring, 880*b5c29a34SFrançois Tigeot u32 invalidate_domains, 881*b5c29a34SFrançois Tigeot u32 flush_domains) 882e3adcf8fSFrançois Tigeot { 883e3adcf8fSFrançois Tigeot int ret; 884e3adcf8fSFrançois Tigeot 885e3adcf8fSFrançois Tigeot ret = intel_ring_begin(ring, 2); 886e3adcf8fSFrançois Tigeot if (ret) 887e3adcf8fSFrançois Tigeot return ret; 888e3adcf8fSFrançois Tigeot 889e3adcf8fSFrançois Tigeot intel_ring_emit(ring, MI_FLUSH); 890e3adcf8fSFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 891e3adcf8fSFrançois Tigeot intel_ring_advance(ring); 892e3adcf8fSFrançois Tigeot return 0; 893e3adcf8fSFrançois Tigeot } 894e3adcf8fSFrançois Tigeot 895e3adcf8fSFrançois Tigeot static int 896*b5c29a34SFrançois Tigeot i9xx_add_request(struct intel_ring_buffer *ring) 897e3adcf8fSFrançois Tigeot { 898e3adcf8fSFrançois Tigeot int ret; 899e3adcf8fSFrançois Tigeot 900e3adcf8fSFrançois Tigeot ret = intel_ring_begin(ring, 4); 901e3adcf8fSFrançois Tigeot if (ret) 902e3adcf8fSFrançois Tigeot return ret; 903e3adcf8fSFrançois Tigeot 904e3adcf8fSFrançois Tigeot intel_ring_emit(ring, MI_STORE_DWORD_INDEX); 905e3adcf8fSFrançois Tigeot intel_ring_emit(ring, I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT); 906*b5c29a34SFrançois Tigeot intel_ring_emit(ring, ring->outstanding_lazy_request); 907e3adcf8fSFrançois Tigeot intel_ring_emit(ring, MI_USER_INTERRUPT); 908e3adcf8fSFrançois Tigeot intel_ring_advance(ring); 909e3adcf8fSFrançois Tigeot 910e3adcf8fSFrançois Tigeot return 0; 911e3adcf8fSFrançois Tigeot } 912e3adcf8fSFrançois Tigeot 913e3adcf8fSFrançois Tigeot static bool 914686a02f1SFrançois Tigeot gen6_ring_get_irq(struct intel_ring_buffer *ring) 915e3adcf8fSFrançois Tigeot { 916e3adcf8fSFrançois Tigeot struct drm_device *dev = ring->dev; 917e3adcf8fSFrançois Tigeot drm_i915_private_t *dev_priv = dev->dev_private; 918e3adcf8fSFrançois Tigeot 919e3adcf8fSFrançois Tigeot if (!dev->irq_enabled) 920e3adcf8fSFrançois Tigeot return false; 921e3adcf8fSFrançois Tigeot 922686a02f1SFrançois Tigeot /* It looks like we need to prevent the gt from suspending while waiting 923686a02f1SFrançois Tigeot * for an notifiy irq, otherwise irqs seem to get lost on at least the 924686a02f1SFrançois Tigeot * blt/bsd rings on ivb. */ 925e3adcf8fSFrançois Tigeot gen6_gt_force_wake_get(dev_priv); 926e3adcf8fSFrançois Tigeot 92702727ecdSFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_EXCLUSIVE); 928e3adcf8fSFrançois Tigeot if (ring->irq_refcount++ == 0) { 929686a02f1SFrançois Tigeot if (HAS_L3_GPU_CACHE(dev) && ring->id == RCS) 930686a02f1SFrançois Tigeot I915_WRITE_IMR(ring, ~(ring->irq_enable_mask | 931686a02f1SFrançois Tigeot GEN6_RENDER_L3_PARITY_ERROR)); 932686a02f1SFrançois Tigeot else 933686a02f1SFrançois Tigeot I915_WRITE_IMR(ring, ~ring->irq_enable_mask); 934686a02f1SFrançois Tigeot dev_priv->gt_irq_mask &= ~ring->irq_enable_mask; 935686a02f1SFrançois Tigeot I915_WRITE(GTIMR, dev_priv->gt_irq_mask); 936686a02f1SFrançois Tigeot POSTING_READ(GTIMR); 937e3adcf8fSFrançois Tigeot } 93802727ecdSFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_RELEASE); 939e3adcf8fSFrançois Tigeot 940e3adcf8fSFrançois Tigeot return true; 941e3adcf8fSFrançois Tigeot } 942e3adcf8fSFrançois Tigeot 943e3adcf8fSFrançois Tigeot static void 944686a02f1SFrançois Tigeot gen6_ring_put_irq(struct intel_ring_buffer *ring) 945e3adcf8fSFrançois Tigeot { 946e3adcf8fSFrançois Tigeot struct drm_device *dev = ring->dev; 947e3adcf8fSFrançois Tigeot drm_i915_private_t *dev_priv = dev->dev_private; 948e3adcf8fSFrançois Tigeot 94902727ecdSFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_EXCLUSIVE); 950e3adcf8fSFrançois Tigeot if (--ring->irq_refcount == 0) { 951686a02f1SFrançois Tigeot if (HAS_L3_GPU_CACHE(dev) && ring->id == RCS) 952686a02f1SFrançois Tigeot I915_WRITE_IMR(ring, ~GEN6_RENDER_L3_PARITY_ERROR); 953686a02f1SFrançois Tigeot else 954686a02f1SFrançois Tigeot I915_WRITE_IMR(ring, ~0); 955686a02f1SFrançois Tigeot dev_priv->gt_irq_mask |= ring->irq_enable_mask; 956686a02f1SFrançois Tigeot I915_WRITE(GTIMR, dev_priv->gt_irq_mask); 957686a02f1SFrançois Tigeot POSTING_READ(GTIMR); 958e3adcf8fSFrançois Tigeot } 95902727ecdSFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_RELEASE); 960e3adcf8fSFrançois Tigeot 961e3adcf8fSFrançois Tigeot gen6_gt_force_wake_put(dev_priv); 962e3adcf8fSFrançois Tigeot } 963e3adcf8fSFrançois Tigeot 964e3adcf8fSFrançois Tigeot static int 965*b5c29a34SFrançois Tigeot i965_dispatch_execbuffer(struct intel_ring_buffer *ring, 966*b5c29a34SFrançois Tigeot u32 offset, u32 length, 967*b5c29a34SFrançois Tigeot unsigned flags) 968e3adcf8fSFrançois Tigeot { 969e3adcf8fSFrançois Tigeot int ret; 970e3adcf8fSFrançois Tigeot 971e3adcf8fSFrançois Tigeot ret = intel_ring_begin(ring, 2); 972e3adcf8fSFrançois Tigeot if (ret) 973e3adcf8fSFrançois Tigeot return ret; 974e3adcf8fSFrançois Tigeot 975e3adcf8fSFrançois Tigeot intel_ring_emit(ring, 976686a02f1SFrançois Tigeot MI_BATCH_BUFFER_START | 977*b5c29a34SFrançois Tigeot MI_BATCH_GTT | 978*b5c29a34SFrançois Tigeot (flags & I915_DISPATCH_SECURE ? 0 : MI_BATCH_NON_SECURE_I965)); 979e3adcf8fSFrançois Tigeot intel_ring_emit(ring, offset); 980e3adcf8fSFrançois Tigeot intel_ring_advance(ring); 981e3adcf8fSFrançois Tigeot 982e3adcf8fSFrançois Tigeot return 0; 983e3adcf8fSFrançois Tigeot } 984e3adcf8fSFrançois Tigeot 985*b5c29a34SFrançois Tigeot /* Just userspace ABI convention to limit the wa batch bo to a resonable size */ 986*b5c29a34SFrançois Tigeot #define I830_BATCH_LIMIT (256*1024) 987e3adcf8fSFrançois Tigeot static int 988686a02f1SFrançois Tigeot i830_dispatch_execbuffer(struct intel_ring_buffer *ring, 989*b5c29a34SFrançois Tigeot u32 offset, u32 len, 990*b5c29a34SFrançois Tigeot unsigned flags) 991e3adcf8fSFrançois Tigeot { 992e3adcf8fSFrançois Tigeot int ret; 993e3adcf8fSFrançois Tigeot 994*b5c29a34SFrançois Tigeot if (flags & I915_DISPATCH_PINNED) { 995e3adcf8fSFrançois Tigeot ret = intel_ring_begin(ring, 4); 996e3adcf8fSFrançois Tigeot if (ret) 997e3adcf8fSFrançois Tigeot return ret; 998e3adcf8fSFrançois Tigeot 999e3adcf8fSFrançois Tigeot intel_ring_emit(ring, MI_BATCH_BUFFER); 1000*b5c29a34SFrançois Tigeot intel_ring_emit(ring, offset | (flags & I915_DISPATCH_SECURE ? 0 : MI_BATCH_NON_SECURE)); 1001e3adcf8fSFrançois Tigeot intel_ring_emit(ring, offset + len - 8); 1002*b5c29a34SFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 1003686a02f1SFrançois Tigeot intel_ring_advance(ring); 1004*b5c29a34SFrançois Tigeot } else { 1005*b5c29a34SFrançois Tigeot struct drm_i915_gem_object *obj = ring->private; 1006*b5c29a34SFrançois Tigeot u32 cs_offset = obj->gtt_offset; 1007*b5c29a34SFrançois Tigeot 1008*b5c29a34SFrançois Tigeot if (len > I830_BATCH_LIMIT) 1009*b5c29a34SFrançois Tigeot return -ENOSPC; 1010*b5c29a34SFrançois Tigeot 1011*b5c29a34SFrançois Tigeot ret = intel_ring_begin(ring, 9+3); 1012*b5c29a34SFrançois Tigeot if (ret) 1013*b5c29a34SFrançois Tigeot return ret; 1014*b5c29a34SFrançois Tigeot /* Blit the batch (which has now all relocs applied) to the stable batch 1015*b5c29a34SFrançois Tigeot * scratch bo area (so that the CS never stumbles over its tlb 1016*b5c29a34SFrançois Tigeot * invalidation bug) ... */ 1017*b5c29a34SFrançois Tigeot intel_ring_emit(ring, XY_SRC_COPY_BLT_CMD | 1018*b5c29a34SFrançois Tigeot XY_SRC_COPY_BLT_WRITE_ALPHA | 1019*b5c29a34SFrançois Tigeot XY_SRC_COPY_BLT_WRITE_RGB); 1020*b5c29a34SFrançois Tigeot intel_ring_emit(ring, BLT_DEPTH_32 | BLT_ROP_GXCOPY | 4096); 1021*b5c29a34SFrançois Tigeot intel_ring_emit(ring, 0); 1022*b5c29a34SFrançois Tigeot intel_ring_emit(ring, (DIV_ROUND_UP(len, 4096) << 16) | 1024); 1023*b5c29a34SFrançois Tigeot intel_ring_emit(ring, cs_offset); 1024*b5c29a34SFrançois Tigeot intel_ring_emit(ring, 0); 1025*b5c29a34SFrançois Tigeot intel_ring_emit(ring, 4096); 1026*b5c29a34SFrançois Tigeot intel_ring_emit(ring, offset); 1027*b5c29a34SFrançois Tigeot intel_ring_emit(ring, MI_FLUSH); 1028*b5c29a34SFrançois Tigeot 1029*b5c29a34SFrançois Tigeot /* ... and execute it. */ 1030*b5c29a34SFrançois Tigeot intel_ring_emit(ring, MI_BATCH_BUFFER); 1031*b5c29a34SFrançois Tigeot intel_ring_emit(ring, cs_offset | (flags & I915_DISPATCH_SECURE ? 0 : MI_BATCH_NON_SECURE)); 1032*b5c29a34SFrançois Tigeot intel_ring_emit(ring, cs_offset + len - 8); 1033*b5c29a34SFrançois Tigeot intel_ring_advance(ring); 1034*b5c29a34SFrançois Tigeot } 1035686a02f1SFrançois Tigeot 1036686a02f1SFrançois Tigeot return 0; 1037686a02f1SFrançois Tigeot } 1038686a02f1SFrançois Tigeot 1039686a02f1SFrançois Tigeot static int 1040686a02f1SFrançois Tigeot i915_dispatch_execbuffer(struct intel_ring_buffer *ring, 1041*b5c29a34SFrançois Tigeot u32 offset, u32 len, 1042*b5c29a34SFrançois Tigeot unsigned flags) 1043686a02f1SFrançois Tigeot { 1044686a02f1SFrançois Tigeot int ret; 1045686a02f1SFrançois Tigeot 1046e3adcf8fSFrançois Tigeot ret = intel_ring_begin(ring, 2); 1047e3adcf8fSFrançois Tigeot if (ret) 1048e3adcf8fSFrançois Tigeot return ret; 1049e3adcf8fSFrançois Tigeot 1050686a02f1SFrançois Tigeot intel_ring_emit(ring, MI_BATCH_BUFFER_START | MI_BATCH_GTT); 1051686a02f1SFrançois Tigeot intel_ring_emit(ring, offset | (flags & I915_DISPATCH_SECURE ? 0 : MI_BATCH_NON_SECURE)); 1052e3adcf8fSFrançois Tigeot intel_ring_advance(ring); 1053e3adcf8fSFrançois Tigeot 1054e3adcf8fSFrançois Tigeot return 0; 1055e3adcf8fSFrançois Tigeot } 1056e3adcf8fSFrançois Tigeot 1057e3adcf8fSFrançois Tigeot static void cleanup_status_page(struct intel_ring_buffer *ring) 1058e3adcf8fSFrançois Tigeot { 1059e3adcf8fSFrançois Tigeot struct drm_i915_gem_object *obj; 1060e3adcf8fSFrançois Tigeot 1061e3adcf8fSFrançois Tigeot obj = ring->status_page.obj; 1062e3adcf8fSFrançois Tigeot if (obj == NULL) 1063e3adcf8fSFrançois Tigeot return; 1064e3adcf8fSFrançois Tigeot 1065e3adcf8fSFrançois Tigeot pmap_qremove((vm_offset_t)ring->status_page.page_addr, 1); 1066e3adcf8fSFrançois Tigeot kmem_free(&kernel_map, (vm_offset_t)ring->status_page.page_addr, 1067e3adcf8fSFrançois Tigeot PAGE_SIZE); 1068e3adcf8fSFrançois Tigeot i915_gem_object_unpin(obj); 1069e3adcf8fSFrançois Tigeot drm_gem_object_unreference(&obj->base); 1070e3adcf8fSFrançois Tigeot ring->status_page.obj = NULL; 1071e3adcf8fSFrançois Tigeot } 1072e3adcf8fSFrançois Tigeot 1073e3adcf8fSFrançois Tigeot static int init_status_page(struct intel_ring_buffer *ring) 1074e3adcf8fSFrançois Tigeot { 1075e3adcf8fSFrançois Tigeot struct drm_device *dev = ring->dev; 1076e3adcf8fSFrançois Tigeot struct drm_i915_gem_object *obj; 1077e3adcf8fSFrançois Tigeot int ret; 1078e3adcf8fSFrançois Tigeot 1079e3adcf8fSFrançois Tigeot obj = i915_gem_alloc_object(dev, 4096); 1080e3adcf8fSFrançois Tigeot if (obj == NULL) { 1081e3adcf8fSFrançois Tigeot DRM_ERROR("Failed to allocate status page\n"); 1082e3adcf8fSFrançois Tigeot ret = -ENOMEM; 1083e3adcf8fSFrançois Tigeot goto err; 1084e3adcf8fSFrançois Tigeot } 1085e3adcf8fSFrançois Tigeot 1086e3adcf8fSFrançois Tigeot i915_gem_object_set_cache_level(obj, I915_CACHE_LLC); 1087e3adcf8fSFrançois Tigeot 1088e3adcf8fSFrançois Tigeot ret = i915_gem_object_pin(obj, 4096, true); 1089e3adcf8fSFrançois Tigeot if (ret != 0) { 1090e3adcf8fSFrançois Tigeot goto err_unref; 1091e3adcf8fSFrançois Tigeot } 1092e3adcf8fSFrançois Tigeot 1093e3adcf8fSFrançois Tigeot ring->status_page.gfx_addr = obj->gtt_offset; 1094e3adcf8fSFrançois Tigeot ring->status_page.page_addr = (void *)kmem_alloc_nofault(&kernel_map, 1095e3adcf8fSFrançois Tigeot PAGE_SIZE, PAGE_SIZE); 1096e3adcf8fSFrançois Tigeot if (ring->status_page.page_addr == NULL) { 1097686a02f1SFrançois Tigeot ret = -ENOMEM; 1098e3adcf8fSFrançois Tigeot goto err_unpin; 1099e3adcf8fSFrançois Tigeot } 1100e3adcf8fSFrançois Tigeot pmap_qenter((vm_offset_t)ring->status_page.page_addr, &obj->pages[0], 1101e3adcf8fSFrançois Tigeot 1); 1102e3adcf8fSFrançois Tigeot pmap_invalidate_cache_range((vm_offset_t)ring->status_page.page_addr, 1103e3adcf8fSFrançois Tigeot (vm_offset_t)ring->status_page.page_addr + PAGE_SIZE); 1104e3adcf8fSFrançois Tigeot ring->status_page.obj = obj; 1105e3adcf8fSFrançois Tigeot memset(ring->status_page.page_addr, 0, PAGE_SIZE); 1106e3adcf8fSFrançois Tigeot 1107e3adcf8fSFrançois Tigeot intel_ring_setup_status_page(ring); 1108*b5c29a34SFrançois Tigeot DRM_DEBUG_DRIVER("%s hws offset: 0x%08x\n", 1109e3adcf8fSFrançois Tigeot ring->name, ring->status_page.gfx_addr); 1110e3adcf8fSFrançois Tigeot 1111e3adcf8fSFrançois Tigeot return 0; 1112e3adcf8fSFrançois Tigeot 1113e3adcf8fSFrançois Tigeot err_unpin: 1114e3adcf8fSFrançois Tigeot i915_gem_object_unpin(obj); 1115e3adcf8fSFrançois Tigeot err_unref: 1116e3adcf8fSFrançois Tigeot drm_gem_object_unreference(&obj->base); 1117e3adcf8fSFrançois Tigeot err: 1118e3adcf8fSFrançois Tigeot return ret; 1119e3adcf8fSFrançois Tigeot } 1120e3adcf8fSFrançois Tigeot 1121686a02f1SFrançois Tigeot static int init_phys_hws_pga(struct intel_ring_buffer *ring) 1122686a02f1SFrançois Tigeot { 1123686a02f1SFrançois Tigeot struct drm_i915_private *dev_priv = ring->dev->dev_private; 1124686a02f1SFrançois Tigeot u32 addr; 1125686a02f1SFrançois Tigeot 1126686a02f1SFrançois Tigeot if (!dev_priv->status_page_dmah) { 1127686a02f1SFrançois Tigeot dev_priv->status_page_dmah = 1128686a02f1SFrançois Tigeot drm_pci_alloc(ring->dev, PAGE_SIZE, PAGE_SIZE, ~0); 1129686a02f1SFrançois Tigeot if (!dev_priv->status_page_dmah) 1130686a02f1SFrançois Tigeot return -ENOMEM; 1131686a02f1SFrançois Tigeot } 1132686a02f1SFrançois Tigeot 1133686a02f1SFrançois Tigeot addr = dev_priv->status_page_dmah->busaddr; 1134686a02f1SFrançois Tigeot if (INTEL_INFO(ring->dev)->gen >= 4) 1135686a02f1SFrançois Tigeot addr |= (dev_priv->status_page_dmah->busaddr >> 28) & 0xf0; 1136686a02f1SFrançois Tigeot I915_WRITE(HWS_PGA, addr); 1137686a02f1SFrançois Tigeot 1138686a02f1SFrançois Tigeot ring->status_page.page_addr = dev_priv->status_page_dmah->vaddr; 1139686a02f1SFrançois Tigeot memset(ring->status_page.page_addr, 0, PAGE_SIZE); 1140686a02f1SFrançois Tigeot 1141686a02f1SFrançois Tigeot return 0; 1142686a02f1SFrançois Tigeot } 1143686a02f1SFrançois Tigeot 1144686a02f1SFrançois Tigeot static inline void __iomem *ioremap_wc(resource_size_t phys_addr, unsigned long size) 1145686a02f1SFrançois Tigeot { 1146686a02f1SFrançois Tigeot return pmap_mapdev_attr(phys_addr, size, VM_MEMATTR_WRITE_COMBINING); 1147686a02f1SFrançois Tigeot } 1148686a02f1SFrançois Tigeot 1149b030f26bSFrançois Tigeot static int intel_init_ring_buffer(struct drm_device *dev, 1150e3adcf8fSFrançois Tigeot struct intel_ring_buffer *ring) 1151e3adcf8fSFrançois Tigeot { 1152e3adcf8fSFrançois Tigeot struct drm_i915_gem_object *obj; 1153e3adcf8fSFrançois Tigeot int ret; 1154e3adcf8fSFrançois Tigeot 1155e3adcf8fSFrançois Tigeot ring->dev = dev; 1156e3adcf8fSFrançois Tigeot INIT_LIST_HEAD(&ring->active_list); 1157e3adcf8fSFrançois Tigeot INIT_LIST_HEAD(&ring->request_list); 1158686a02f1SFrançois Tigeot ring->size = 32 * PAGE_SIZE; 1159686a02f1SFrançois Tigeot memset(ring->sync_seqno, 0, sizeof(ring->sync_seqno)); 1160e3adcf8fSFrançois Tigeot 1161b030f26bSFrançois Tigeot init_waitqueue_head(&ring->irq_queue); 1162b030f26bSFrançois Tigeot 1163e3adcf8fSFrançois Tigeot if (I915_NEED_GFX_HWS(dev)) { 1164e3adcf8fSFrançois Tigeot ret = init_status_page(ring); 1165e3adcf8fSFrançois Tigeot if (ret) 1166e3adcf8fSFrançois Tigeot return ret; 1167686a02f1SFrançois Tigeot } else { 1168686a02f1SFrançois Tigeot BUG_ON(ring->id != RCS); 1169686a02f1SFrançois Tigeot ret = init_phys_hws_pga(ring); 1170686a02f1SFrançois Tigeot if (ret) 1171686a02f1SFrançois Tigeot return ret; 1172e3adcf8fSFrançois Tigeot } 1173e3adcf8fSFrançois Tigeot 1174e3adcf8fSFrançois Tigeot obj = i915_gem_alloc_object(dev, ring->size); 1175e3adcf8fSFrançois Tigeot if (obj == NULL) { 1176e3adcf8fSFrançois Tigeot DRM_ERROR("Failed to allocate ringbuffer\n"); 1177e3adcf8fSFrançois Tigeot ret = -ENOMEM; 1178e3adcf8fSFrançois Tigeot goto err_hws; 1179e3adcf8fSFrançois Tigeot } 1180e3adcf8fSFrançois Tigeot 1181e3adcf8fSFrançois Tigeot ring->obj = obj; 1182e3adcf8fSFrançois Tigeot 1183e3adcf8fSFrançois Tigeot ret = i915_gem_object_pin(obj, PAGE_SIZE, true); 1184e3adcf8fSFrançois Tigeot if (ret) 1185e3adcf8fSFrançois Tigeot goto err_unref; 1186e3adcf8fSFrançois Tigeot 1187686a02f1SFrançois Tigeot ret = i915_gem_object_set_to_gtt_domain(obj, true); 1188686a02f1SFrançois Tigeot if (ret) 1189686a02f1SFrançois Tigeot goto err_unpin; 1190e3adcf8fSFrançois Tigeot 1191686a02f1SFrançois Tigeot ring->virtual_start = ioremap_wc(dev->agp->base + obj->gtt_offset, 1192686a02f1SFrançois Tigeot ring->size); 1193686a02f1SFrançois Tigeot if (ring->virtual_start == NULL) { 1194e3adcf8fSFrançois Tigeot DRM_ERROR("Failed to map ringbuffer.\n"); 1195e3adcf8fSFrançois Tigeot ret = -EINVAL; 1196e3adcf8fSFrançois Tigeot goto err_unpin; 1197e3adcf8fSFrançois Tigeot } 1198e3adcf8fSFrançois Tigeot 1199e3adcf8fSFrançois Tigeot ret = ring->init(ring); 1200e3adcf8fSFrançois Tigeot if (ret) 1201e3adcf8fSFrançois Tigeot goto err_unmap; 1202e3adcf8fSFrançois Tigeot 1203e3adcf8fSFrançois Tigeot /* Workaround an erratum on the i830 which causes a hang if 1204e3adcf8fSFrançois Tigeot * the TAIL pointer points to within the last 2 cachelines 1205e3adcf8fSFrançois Tigeot * of the buffer. 1206e3adcf8fSFrançois Tigeot */ 1207e3adcf8fSFrançois Tigeot ring->effective_size = ring->size; 1208e3adcf8fSFrançois Tigeot if (IS_I830(ring->dev) || IS_845G(ring->dev)) 1209e3adcf8fSFrançois Tigeot ring->effective_size -= 128; 1210e3adcf8fSFrançois Tigeot 1211e3adcf8fSFrançois Tigeot return 0; 1212e3adcf8fSFrançois Tigeot 1213e3adcf8fSFrançois Tigeot err_unmap: 1214686a02f1SFrançois Tigeot pmap_unmapdev((vm_offset_t)ring->virtual_start, ring->size); 1215e3adcf8fSFrançois Tigeot err_unpin: 1216e3adcf8fSFrançois Tigeot i915_gem_object_unpin(obj); 1217e3adcf8fSFrançois Tigeot err_unref: 1218e3adcf8fSFrançois Tigeot drm_gem_object_unreference(&obj->base); 1219e3adcf8fSFrançois Tigeot ring->obj = NULL; 1220e3adcf8fSFrançois Tigeot err_hws: 1221e3adcf8fSFrançois Tigeot cleanup_status_page(ring); 1222e3adcf8fSFrançois Tigeot return ret; 1223e3adcf8fSFrançois Tigeot } 1224e3adcf8fSFrançois Tigeot 1225e3adcf8fSFrançois Tigeot void intel_cleanup_ring_buffer(struct intel_ring_buffer *ring) 1226e3adcf8fSFrançois Tigeot { 1227e3adcf8fSFrançois Tigeot struct drm_i915_private *dev_priv; 1228e3adcf8fSFrançois Tigeot int ret; 1229e3adcf8fSFrançois Tigeot 1230e3adcf8fSFrançois Tigeot if (ring->obj == NULL) 1231e3adcf8fSFrançois Tigeot return; 1232e3adcf8fSFrançois Tigeot 1233e3adcf8fSFrançois Tigeot /* Disable the ring buffer. The ring must be idle at this point */ 1234e3adcf8fSFrançois Tigeot dev_priv = ring->dev->dev_private; 1235b030f26bSFrançois Tigeot ret = intel_ring_idle(ring); 1236b030f26bSFrançois Tigeot if (ret) 1237b030f26bSFrançois Tigeot DRM_ERROR("failed to quiesce %s whilst cleaning up: %d\n", 1238b030f26bSFrançois Tigeot ring->name, ret); 1239b030f26bSFrançois Tigeot 1240e3adcf8fSFrançois Tigeot I915_WRITE_CTL(ring, 0); 1241e3adcf8fSFrançois Tigeot 1242686a02f1SFrançois Tigeot pmap_unmapdev((vm_offset_t)ring->virtual_start, ring->size); 1243e3adcf8fSFrançois Tigeot 1244e3adcf8fSFrançois Tigeot i915_gem_object_unpin(ring->obj); 1245e3adcf8fSFrançois Tigeot drm_gem_object_unreference(&ring->obj->base); 1246e3adcf8fSFrançois Tigeot ring->obj = NULL; 1247e3adcf8fSFrançois Tigeot 1248e3adcf8fSFrançois Tigeot if (ring->cleanup) 1249e3adcf8fSFrançois Tigeot ring->cleanup(ring); 1250e3adcf8fSFrançois Tigeot 1251e3adcf8fSFrançois Tigeot cleanup_status_page(ring); 1252e3adcf8fSFrançois Tigeot } 1253e3adcf8fSFrançois Tigeot 1254e3adcf8fSFrançois Tigeot static int intel_ring_wait_seqno(struct intel_ring_buffer *ring, u32 seqno) 1255e3adcf8fSFrançois Tigeot { 1256e3adcf8fSFrançois Tigeot int ret; 1257e3adcf8fSFrançois Tigeot 1258b030f26bSFrançois Tigeot ret = i915_wait_seqno(ring, seqno); 1259b030f26bSFrançois Tigeot if (!ret) 1260b030f26bSFrançois Tigeot i915_gem_retire_requests_ring(ring); 1261e3adcf8fSFrançois Tigeot 1262e3adcf8fSFrançois Tigeot return ret; 1263e3adcf8fSFrançois Tigeot } 1264e3adcf8fSFrançois Tigeot 1265e3adcf8fSFrançois Tigeot static int intel_ring_wait_request(struct intel_ring_buffer *ring, int n) 1266e3adcf8fSFrançois Tigeot { 1267e3adcf8fSFrançois Tigeot struct drm_i915_gem_request *request; 1268e3adcf8fSFrançois Tigeot u32 seqno = 0; 1269e3adcf8fSFrançois Tigeot int ret; 1270e3adcf8fSFrançois Tigeot 1271e3adcf8fSFrançois Tigeot i915_gem_retire_requests_ring(ring); 1272e3adcf8fSFrançois Tigeot 1273e3adcf8fSFrançois Tigeot if (ring->last_retired_head != -1) { 1274e3adcf8fSFrançois Tigeot ring->head = ring->last_retired_head; 1275e3adcf8fSFrançois Tigeot ring->last_retired_head = -1; 1276e3adcf8fSFrançois Tigeot ring->space = ring_space(ring); 1277e3adcf8fSFrançois Tigeot if (ring->space >= n) 1278e3adcf8fSFrançois Tigeot return 0; 1279e3adcf8fSFrançois Tigeot } 1280e3adcf8fSFrançois Tigeot 1281e3adcf8fSFrançois Tigeot list_for_each_entry(request, &ring->request_list, list) { 1282e3adcf8fSFrançois Tigeot int space; 1283e3adcf8fSFrançois Tigeot 1284e3adcf8fSFrançois Tigeot if (request->tail == -1) 1285e3adcf8fSFrançois Tigeot continue; 1286e3adcf8fSFrançois Tigeot 1287*b5c29a34SFrançois Tigeot space = request->tail - (ring->tail + I915_RING_FREE_SPACE); 1288e3adcf8fSFrançois Tigeot if (space < 0) 1289e3adcf8fSFrançois Tigeot space += ring->size; 1290e3adcf8fSFrançois Tigeot if (space >= n) { 1291e3adcf8fSFrançois Tigeot seqno = request->seqno; 1292e3adcf8fSFrançois Tigeot break; 1293e3adcf8fSFrançois Tigeot } 1294e3adcf8fSFrançois Tigeot 1295e3adcf8fSFrançois Tigeot /* Consume this request in case we need more space than 1296e3adcf8fSFrançois Tigeot * is available and so need to prevent a race between 1297e3adcf8fSFrançois Tigeot * updating last_retired_head and direct reads of 1298e3adcf8fSFrançois Tigeot * I915_RING_HEAD. It also provides a nice sanity check. 1299e3adcf8fSFrançois Tigeot */ 1300e3adcf8fSFrançois Tigeot request->tail = -1; 1301e3adcf8fSFrançois Tigeot } 1302e3adcf8fSFrançois Tigeot 1303e3adcf8fSFrançois Tigeot if (seqno == 0) 1304e3adcf8fSFrançois Tigeot return -ENOSPC; 1305e3adcf8fSFrançois Tigeot 1306e3adcf8fSFrançois Tigeot ret = intel_ring_wait_seqno(ring, seqno); 1307e3adcf8fSFrançois Tigeot if (ret) 1308e3adcf8fSFrançois Tigeot return ret; 1309e3adcf8fSFrançois Tigeot 1310*b5c29a34SFrançois Tigeot if (WARN_ON(ring->last_retired_head == -1)) 1311e3adcf8fSFrançois Tigeot return -ENOSPC; 1312e3adcf8fSFrançois Tigeot 1313e3adcf8fSFrançois Tigeot ring->head = ring->last_retired_head; 1314e3adcf8fSFrançois Tigeot ring->last_retired_head = -1; 1315e3adcf8fSFrançois Tigeot ring->space = ring_space(ring); 1316*b5c29a34SFrançois Tigeot if (WARN_ON(ring->space < n)) 1317e3adcf8fSFrançois Tigeot return -ENOSPC; 1318e3adcf8fSFrançois Tigeot 1319e3adcf8fSFrançois Tigeot return 0; 1320e3adcf8fSFrançois Tigeot } 1321e3adcf8fSFrançois Tigeot 1322b030f26bSFrançois Tigeot static int ring_wait_for_space(struct intel_ring_buffer *ring, int n) 1323e3adcf8fSFrançois Tigeot { 1324e3adcf8fSFrançois Tigeot struct drm_device *dev = ring->dev; 1325e3adcf8fSFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 1326245593daSFrançois Tigeot unsigned long end; 1327e3adcf8fSFrançois Tigeot int ret; 1328e3adcf8fSFrançois Tigeot 1329e3adcf8fSFrançois Tigeot ret = intel_ring_wait_request(ring, n); 1330e3adcf8fSFrançois Tigeot if (ret != -ENOSPC) 1331e3adcf8fSFrançois Tigeot return ret; 1332e3adcf8fSFrançois Tigeot 1333e3adcf8fSFrançois Tigeot /* With GEM the hangcheck timer should kick us out of the loop, 1334e3adcf8fSFrançois Tigeot * leaving it early runs the risk of corrupting GEM state (due 1335e3adcf8fSFrançois Tigeot * to running on almost untested codepaths). But on resume 1336e3adcf8fSFrançois Tigeot * timers don't work yet, so prevent a complete hang in that 1337e3adcf8fSFrançois Tigeot * case by choosing an insanely large timeout. */ 1338245593daSFrançois Tigeot end = ticks + 60 * hz; 1339245593daSFrançois Tigeot 1340e3adcf8fSFrançois Tigeot do { 1341e3adcf8fSFrançois Tigeot ring->head = I915_READ_HEAD(ring); 1342e3adcf8fSFrançois Tigeot ring->space = ring_space(ring); 1343e3adcf8fSFrançois Tigeot if (ring->space >= n) { 1344e3adcf8fSFrançois Tigeot return 0; 1345e3adcf8fSFrançois Tigeot } 1346e3adcf8fSFrançois Tigeot 1347e3adcf8fSFrançois Tigeot #if 0 1348e3adcf8fSFrançois Tigeot if (dev->primary->master) { 1349e3adcf8fSFrançois Tigeot struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv; 1350e3adcf8fSFrançois Tigeot if (master_priv->sarea_priv) 1351e3adcf8fSFrançois Tigeot master_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT; 1352e3adcf8fSFrançois Tigeot } 1353e3adcf8fSFrançois Tigeot #else 1354e3adcf8fSFrançois Tigeot if (dev_priv->sarea_priv) 1355e3adcf8fSFrançois Tigeot dev_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT; 1356e3adcf8fSFrançois Tigeot #endif 1357e3adcf8fSFrançois Tigeot 1358e3adcf8fSFrançois Tigeot DELAY(1000); 1359245593daSFrançois Tigeot 1360245593daSFrançois Tigeot ret = i915_gem_check_wedge(dev_priv, dev_priv->mm.interruptible); 1361245593daSFrançois Tigeot if (ret) 1362245593daSFrançois Tigeot return ret; 1363e3adcf8fSFrançois Tigeot } while (!time_after(ticks, end)); 1364e3adcf8fSFrançois Tigeot return -EBUSY; 1365e3adcf8fSFrançois Tigeot } 1366e3adcf8fSFrançois Tigeot 1367b030f26bSFrançois Tigeot static int intel_wrap_ring_buffer(struct intel_ring_buffer *ring) 1368b030f26bSFrançois Tigeot { 1369b030f26bSFrançois Tigeot uint32_t __iomem *virt; 1370b030f26bSFrançois Tigeot int rem = ring->size - ring->tail; 1371b030f26bSFrançois Tigeot 1372b030f26bSFrançois Tigeot if (ring->space < rem) { 1373b030f26bSFrançois Tigeot int ret = ring_wait_for_space(ring, rem); 1374b030f26bSFrançois Tigeot if (ret) 1375b030f26bSFrançois Tigeot return ret; 1376b030f26bSFrançois Tigeot } 1377b030f26bSFrançois Tigeot 1378b030f26bSFrançois Tigeot virt = (unsigned int *)((char *)ring->virtual_start + ring->tail); 1379b030f26bSFrançois Tigeot rem /= 4; 1380b030f26bSFrançois Tigeot while (rem--) 1381686a02f1SFrançois Tigeot iowrite32(MI_NOOP, virt++); 1382b030f26bSFrançois Tigeot 1383b030f26bSFrançois Tigeot ring->tail = 0; 1384b030f26bSFrançois Tigeot ring->space = ring_space(ring); 1385b030f26bSFrançois Tigeot 1386b030f26bSFrançois Tigeot return 0; 1387b030f26bSFrançois Tigeot } 1388b030f26bSFrançois Tigeot 1389b030f26bSFrançois Tigeot int intel_ring_idle(struct intel_ring_buffer *ring) 1390b030f26bSFrançois Tigeot { 1391*b5c29a34SFrançois Tigeot u32 seqno; 1392*b5c29a34SFrançois Tigeot int ret; 1393*b5c29a34SFrançois Tigeot 1394*b5c29a34SFrançois Tigeot /* We need to add any requests required to flush the objects and ring */ 1395*b5c29a34SFrançois Tigeot if (ring->outstanding_lazy_request) { 1396*b5c29a34SFrançois Tigeot ret = i915_add_request(ring, NULL, NULL); 1397*b5c29a34SFrançois Tigeot if (ret) 1398*b5c29a34SFrançois Tigeot return ret; 1399*b5c29a34SFrançois Tigeot } 1400*b5c29a34SFrançois Tigeot 1401*b5c29a34SFrançois Tigeot /* Wait upon the last request to be completed */ 1402*b5c29a34SFrançois Tigeot if (list_empty(&ring->request_list)) 1403*b5c29a34SFrançois Tigeot return 0; 1404*b5c29a34SFrançois Tigeot 1405*b5c29a34SFrançois Tigeot seqno = list_entry(ring->request_list.prev, 1406*b5c29a34SFrançois Tigeot struct drm_i915_gem_request, 1407*b5c29a34SFrançois Tigeot list)->seqno; 1408*b5c29a34SFrançois Tigeot 1409*b5c29a34SFrançois Tigeot return i915_wait_seqno(ring, seqno); 1410*b5c29a34SFrançois Tigeot } 1411*b5c29a34SFrançois Tigeot 1412*b5c29a34SFrançois Tigeot static int 1413*b5c29a34SFrançois Tigeot intel_ring_alloc_seqno(struct intel_ring_buffer *ring) 1414*b5c29a34SFrançois Tigeot { 1415*b5c29a34SFrançois Tigeot if (ring->outstanding_lazy_request) 1416*b5c29a34SFrançois Tigeot return 0; 1417*b5c29a34SFrançois Tigeot 1418*b5c29a34SFrançois Tigeot return i915_gem_get_seqno(ring->dev, &ring->outstanding_lazy_request); 1419b030f26bSFrançois Tigeot } 1420b030f26bSFrançois Tigeot 1421e3adcf8fSFrançois Tigeot int intel_ring_begin(struct intel_ring_buffer *ring, 1422e3adcf8fSFrançois Tigeot int num_dwords) 1423e3adcf8fSFrançois Tigeot { 1424*b5c29a34SFrançois Tigeot drm_i915_private_t *dev_priv = ring->dev->dev_private; 1425e3adcf8fSFrançois Tigeot int n = 4*num_dwords; 1426e3adcf8fSFrançois Tigeot int ret; 1427e3adcf8fSFrançois Tigeot 1428245593daSFrançois Tigeot ret = i915_gem_check_wedge(dev_priv, dev_priv->mm.interruptible); 1429245593daSFrançois Tigeot if (ret) 1430245593daSFrançois Tigeot return ret; 1431e3adcf8fSFrançois Tigeot 1432*b5c29a34SFrançois Tigeot /* Preallocate the olr before touching the ring */ 1433*b5c29a34SFrançois Tigeot ret = intel_ring_alloc_seqno(ring); 1434*b5c29a34SFrançois Tigeot if (ret) 1435*b5c29a34SFrançois Tigeot return ret; 1436*b5c29a34SFrançois Tigeot 1437245593daSFrançois Tigeot if (unlikely(ring->tail + n > ring->effective_size)) { 1438e3adcf8fSFrançois Tigeot ret = intel_wrap_ring_buffer(ring); 1439245593daSFrançois Tigeot if (unlikely(ret)) 1440e3adcf8fSFrançois Tigeot return ret; 1441e3adcf8fSFrançois Tigeot } 1442e3adcf8fSFrançois Tigeot 1443b030f26bSFrançois Tigeot if (unlikely(ring->space < n)) { 1444b030f26bSFrançois Tigeot ret = ring_wait_for_space(ring, n); 1445b030f26bSFrançois Tigeot if (unlikely(ret)) 1446e3adcf8fSFrançois Tigeot return ret; 1447e3adcf8fSFrançois Tigeot } 1448e3adcf8fSFrançois Tigeot 1449e3adcf8fSFrançois Tigeot ring->space -= n; 1450e3adcf8fSFrançois Tigeot return 0; 1451e3adcf8fSFrançois Tigeot } 1452e3adcf8fSFrançois Tigeot 1453e3adcf8fSFrançois Tigeot void intel_ring_advance(struct intel_ring_buffer *ring) 1454e3adcf8fSFrançois Tigeot { 1455686a02f1SFrançois Tigeot struct drm_i915_private *dev_priv = ring->dev->dev_private; 1456686a02f1SFrançois Tigeot 1457e3adcf8fSFrançois Tigeot ring->tail &= ring->size - 1; 1458686a02f1SFrançois Tigeot if (dev_priv->stop_rings & intel_ring_flag(ring)) 1459686a02f1SFrançois Tigeot return; 1460e3adcf8fSFrançois Tigeot ring->write_tail(ring, ring->tail); 1461e3adcf8fSFrançois Tigeot } 1462e3adcf8fSFrançois Tigeot 1463*b5c29a34SFrançois Tigeot 1464e3adcf8fSFrançois Tigeot static void gen6_bsd_ring_write_tail(struct intel_ring_buffer *ring, 1465f4e1c372SFrançois Tigeot u32 value) 1466e3adcf8fSFrançois Tigeot { 1467e3adcf8fSFrançois Tigeot drm_i915_private_t *dev_priv = ring->dev->dev_private; 1468e3adcf8fSFrançois Tigeot 1469e3adcf8fSFrançois Tigeot /* Every tail move must follow the sequence below */ 1470f4e1c372SFrançois Tigeot 1471f4e1c372SFrançois Tigeot /* Disable notification that the ring is IDLE. The GT 1472f4e1c372SFrançois Tigeot * will then assume that it is busy and bring it out of rc6. 1473f4e1c372SFrançois Tigeot */ 1474e3adcf8fSFrançois Tigeot I915_WRITE(GEN6_BSD_SLEEP_PSMI_CONTROL, 1475f4e1c372SFrançois Tigeot _MASKED_BIT_ENABLE(GEN6_BSD_SLEEP_MSG_DISABLE)); 1476e3adcf8fSFrançois Tigeot 1477f4e1c372SFrançois Tigeot /* Clear the context id. Here be magic! */ 1478f4e1c372SFrançois Tigeot I915_WRITE64(GEN6_BSD_RNCID, 0x0); 1479e3adcf8fSFrançois Tigeot 1480f4e1c372SFrançois Tigeot /* Wait for the ring not to be idle, i.e. for it to wake up. */ 1481f4e1c372SFrançois Tigeot if (wait_for((I915_READ(GEN6_BSD_SLEEP_PSMI_CONTROL) & 1482f4e1c372SFrançois Tigeot GEN6_BSD_SLEEP_INDICATOR) == 0, 1483f4e1c372SFrançois Tigeot 50)) 1484f4e1c372SFrançois Tigeot DRM_ERROR("timed out waiting for the BSD ring to wake up\n"); 1485f4e1c372SFrançois Tigeot 1486f4e1c372SFrançois Tigeot /* Now that the ring is fully powered up, update the tail */ 1487e3adcf8fSFrançois Tigeot I915_WRITE_TAIL(ring, value); 1488f4e1c372SFrançois Tigeot POSTING_READ(RING_TAIL(ring->mmio_base)); 1489f4e1c372SFrançois Tigeot 1490f4e1c372SFrançois Tigeot /* Let the ring send IDLE messages to the GT again, 1491f4e1c372SFrançois Tigeot * and so let it sleep to conserve power when idle. 1492f4e1c372SFrançois Tigeot */ 1493e3adcf8fSFrançois Tigeot I915_WRITE(GEN6_BSD_SLEEP_PSMI_CONTROL, 1494f4e1c372SFrançois Tigeot _MASKED_BIT_DISABLE(GEN6_BSD_SLEEP_MSG_DISABLE)); 1495e3adcf8fSFrançois Tigeot } 1496e3adcf8fSFrançois Tigeot 1497e3adcf8fSFrançois Tigeot static int gen6_ring_flush(struct intel_ring_buffer *ring, 1498*b5c29a34SFrançois Tigeot u32 invalidate, u32 flush) 1499e3adcf8fSFrançois Tigeot { 1500e3adcf8fSFrançois Tigeot uint32_t cmd; 1501e3adcf8fSFrançois Tigeot int ret; 1502e3adcf8fSFrançois Tigeot 1503e3adcf8fSFrançois Tigeot ret = intel_ring_begin(ring, 4); 1504e3adcf8fSFrançois Tigeot if (ret) 1505e3adcf8fSFrançois Tigeot return ret; 1506e3adcf8fSFrançois Tigeot 1507e3adcf8fSFrançois Tigeot cmd = MI_FLUSH_DW; 1508*b5c29a34SFrançois Tigeot /* 1509*b5c29a34SFrançois Tigeot * Bspec vol 1c.5 - video engine command streamer: 1510*b5c29a34SFrançois Tigeot * "If ENABLED, all TLBs will be invalidated once the flush 1511*b5c29a34SFrançois Tigeot * operation is complete. This bit is only valid when the 1512*b5c29a34SFrançois Tigeot * Post-Sync Operation field is a value of 1h or 3h." 1513*b5c29a34SFrançois Tigeot */ 1514e3adcf8fSFrançois Tigeot if (invalidate & I915_GEM_GPU_DOMAINS) 1515*b5c29a34SFrançois Tigeot cmd |= MI_INVALIDATE_TLB | MI_INVALIDATE_BSD | 1516*b5c29a34SFrançois Tigeot MI_FLUSH_DW_STORE_INDEX | MI_FLUSH_DW_OP_STOREDW; 1517e3adcf8fSFrançois Tigeot intel_ring_emit(ring, cmd); 1518*b5c29a34SFrançois Tigeot intel_ring_emit(ring, I915_GEM_HWS_SCRATCH_ADDR | MI_FLUSH_DW_USE_GTT); 1519e3adcf8fSFrançois Tigeot intel_ring_emit(ring, 0); 1520e3adcf8fSFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 1521e3adcf8fSFrançois Tigeot intel_ring_advance(ring); 1522e3adcf8fSFrançois Tigeot return 0; 1523e3adcf8fSFrançois Tigeot } 1524e3adcf8fSFrançois Tigeot 1525e3adcf8fSFrançois Tigeot static int 1526*b5c29a34SFrançois Tigeot hsw_ring_dispatch_execbuffer(struct intel_ring_buffer *ring, 1527*b5c29a34SFrançois Tigeot u32 offset, u32 len, 1528*b5c29a34SFrançois Tigeot unsigned flags) 1529e3adcf8fSFrançois Tigeot { 1530e3adcf8fSFrançois Tigeot int ret; 1531e3adcf8fSFrançois Tigeot 1532e3adcf8fSFrançois Tigeot ret = intel_ring_begin(ring, 2); 1533e3adcf8fSFrançois Tigeot if (ret) 1534e3adcf8fSFrançois Tigeot return ret; 1535e3adcf8fSFrançois Tigeot 1536*b5c29a34SFrançois Tigeot intel_ring_emit(ring, 1537*b5c29a34SFrançois Tigeot MI_BATCH_BUFFER_START | MI_BATCH_PPGTT_HSW | 1538*b5c29a34SFrançois Tigeot (flags & I915_DISPATCH_SECURE ? 0 : MI_BATCH_NON_SECURE_HSW)); 1539*b5c29a34SFrançois Tigeot /* bit0-7 is the length on GEN6+ */ 1540*b5c29a34SFrançois Tigeot intel_ring_emit(ring, offset); 1541*b5c29a34SFrançois Tigeot intel_ring_advance(ring); 1542*b5c29a34SFrançois Tigeot 1543*b5c29a34SFrançois Tigeot return 0; 1544*b5c29a34SFrançois Tigeot } 1545*b5c29a34SFrançois Tigeot 1546*b5c29a34SFrançois Tigeot static int 1547*b5c29a34SFrançois Tigeot gen6_ring_dispatch_execbuffer(struct intel_ring_buffer *ring, 1548*b5c29a34SFrançois Tigeot u32 offset, u32 len, 1549*b5c29a34SFrançois Tigeot unsigned flags) 1550*b5c29a34SFrançois Tigeot { 1551*b5c29a34SFrançois Tigeot int ret; 1552*b5c29a34SFrançois Tigeot 1553*b5c29a34SFrançois Tigeot ret = intel_ring_begin(ring, 2); 1554*b5c29a34SFrançois Tigeot if (ret) 1555*b5c29a34SFrançois Tigeot return ret; 1556*b5c29a34SFrançois Tigeot 1557*b5c29a34SFrançois Tigeot intel_ring_emit(ring, 1558*b5c29a34SFrançois Tigeot MI_BATCH_BUFFER_START | 1559*b5c29a34SFrançois Tigeot (flags & I915_DISPATCH_SECURE ? 0 : MI_BATCH_NON_SECURE_I965)); 1560e3adcf8fSFrançois Tigeot /* bit0-7 is the length on GEN6+ */ 1561e3adcf8fSFrançois Tigeot intel_ring_emit(ring, offset); 1562e3adcf8fSFrançois Tigeot intel_ring_advance(ring); 1563e3adcf8fSFrançois Tigeot 1564e3adcf8fSFrançois Tigeot return 0; 1565e3adcf8fSFrançois Tigeot } 1566e3adcf8fSFrançois Tigeot 1567e3adcf8fSFrançois Tigeot /* Blitter support (SandyBridge+) */ 1568e3adcf8fSFrançois Tigeot 1569e3adcf8fSFrançois Tigeot static int blt_ring_flush(struct intel_ring_buffer *ring, 1570*b5c29a34SFrançois Tigeot u32 invalidate, u32 flush) 1571e3adcf8fSFrançois Tigeot { 1572e3adcf8fSFrançois Tigeot uint32_t cmd; 1573e3adcf8fSFrançois Tigeot int ret; 1574e3adcf8fSFrançois Tigeot 1575e3adcf8fSFrançois Tigeot ret = intel_ring_begin(ring, 4); 1576e3adcf8fSFrançois Tigeot if (ret) 1577e3adcf8fSFrançois Tigeot return ret; 1578e3adcf8fSFrançois Tigeot 1579e3adcf8fSFrançois Tigeot cmd = MI_FLUSH_DW; 1580*b5c29a34SFrançois Tigeot /* 1581*b5c29a34SFrançois Tigeot * Bspec vol 1c.3 - blitter engine command streamer: 1582*b5c29a34SFrançois Tigeot * "If ENABLED, all TLBs will be invalidated once the flush 1583*b5c29a34SFrançois Tigeot * operation is complete. This bit is only valid when the 1584*b5c29a34SFrançois Tigeot * Post-Sync Operation field is a value of 1h or 3h." 1585*b5c29a34SFrançois Tigeot */ 1586e3adcf8fSFrançois Tigeot if (invalidate & I915_GEM_DOMAIN_RENDER) 1587*b5c29a34SFrançois Tigeot cmd |= MI_INVALIDATE_TLB | MI_FLUSH_DW_STORE_INDEX | 1588*b5c29a34SFrançois Tigeot MI_FLUSH_DW_OP_STOREDW; 1589e3adcf8fSFrançois Tigeot intel_ring_emit(ring, cmd); 1590*b5c29a34SFrançois Tigeot intel_ring_emit(ring, I915_GEM_HWS_SCRATCH_ADDR | MI_FLUSH_DW_USE_GTT); 1591e3adcf8fSFrançois Tigeot intel_ring_emit(ring, 0); 1592e3adcf8fSFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 1593e3adcf8fSFrançois Tigeot intel_ring_advance(ring); 1594e3adcf8fSFrançois Tigeot return 0; 1595e3adcf8fSFrançois Tigeot } 1596e3adcf8fSFrançois Tigeot 1597e3adcf8fSFrançois Tigeot int intel_init_render_ring_buffer(struct drm_device *dev) 1598e3adcf8fSFrançois Tigeot { 1599e3adcf8fSFrançois Tigeot drm_i915_private_t *dev_priv = dev->dev_private; 1600ad50ea93SFrançois Tigeot struct intel_ring_buffer *ring = &dev_priv->ring[RCS]; 1601e3adcf8fSFrançois Tigeot 1602686a02f1SFrançois Tigeot ring->name = "render ring"; 1603686a02f1SFrançois Tigeot ring->id = RCS; 1604686a02f1SFrançois Tigeot ring->mmio_base = RENDER_RING_BASE; 1605686a02f1SFrançois Tigeot 1606e3adcf8fSFrançois Tigeot if (INTEL_INFO(dev)->gen >= 6) { 1607e3adcf8fSFrançois Tigeot ring->add_request = gen6_add_request; 1608*b5c29a34SFrançois Tigeot ring->flush = gen7_render_ring_flush; 1609*b5c29a34SFrançois Tigeot if (INTEL_INFO(dev)->gen == 6) 1610e3adcf8fSFrançois Tigeot ring->flush = gen6_render_ring_flush; 1611686a02f1SFrançois Tigeot ring->irq_get = gen6_ring_get_irq; 1612686a02f1SFrançois Tigeot ring->irq_put = gen6_ring_put_irq; 1613686a02f1SFrançois Tigeot ring->irq_enable_mask = GT_USER_INTERRUPT; 1614e3adcf8fSFrançois Tigeot ring->get_seqno = gen6_ring_get_seqno; 1615686a02f1SFrançois Tigeot ring->sync_to = gen6_ring_sync; 1616686a02f1SFrançois Tigeot ring->semaphore_register[0] = MI_SEMAPHORE_SYNC_INVALID; 1617686a02f1SFrançois Tigeot ring->semaphore_register[1] = MI_SEMAPHORE_SYNC_RV; 1618686a02f1SFrançois Tigeot ring->semaphore_register[2] = MI_SEMAPHORE_SYNC_RB; 1619686a02f1SFrançois Tigeot ring->signal_mbox[0] = GEN6_VRSYNC; 1620686a02f1SFrançois Tigeot ring->signal_mbox[1] = GEN6_BRSYNC; 1621e3adcf8fSFrançois Tigeot } else if (IS_GEN5(dev)) { 1622e3adcf8fSFrançois Tigeot ring->add_request = pc_render_add_request; 1623686a02f1SFrançois Tigeot ring->flush = gen4_render_ring_flush; 1624e3adcf8fSFrançois Tigeot ring->get_seqno = pc_render_get_seqno; 1625686a02f1SFrançois Tigeot ring->irq_get = gen5_ring_get_irq; 1626686a02f1SFrançois Tigeot ring->irq_put = gen5_ring_put_irq; 1627686a02f1SFrançois Tigeot ring->irq_enable_mask = GT_USER_INTERRUPT | GT_PIPE_NOTIFY; 1628686a02f1SFrançois Tigeot } else { 1629686a02f1SFrançois Tigeot ring->add_request = i9xx_add_request; 1630686a02f1SFrançois Tigeot if (INTEL_INFO(dev)->gen < 4) 1631686a02f1SFrançois Tigeot ring->flush = gen2_render_ring_flush; 1632686a02f1SFrançois Tigeot else 1633686a02f1SFrançois Tigeot ring->flush = gen4_render_ring_flush; 1634686a02f1SFrançois Tigeot ring->get_seqno = ring_get_seqno; 1635686a02f1SFrançois Tigeot if (IS_GEN2(dev)) { 1636686a02f1SFrançois Tigeot ring->irq_get = i8xx_ring_get_irq; 1637686a02f1SFrançois Tigeot ring->irq_put = i8xx_ring_put_irq; 1638686a02f1SFrançois Tigeot } else { 1639686a02f1SFrançois Tigeot ring->irq_get = i9xx_ring_get_irq; 1640686a02f1SFrançois Tigeot ring->irq_put = i9xx_ring_put_irq; 1641e3adcf8fSFrançois Tigeot } 1642686a02f1SFrançois Tigeot ring->irq_enable_mask = I915_USER_INTERRUPT; 1643686a02f1SFrançois Tigeot } 1644686a02f1SFrançois Tigeot ring->write_tail = ring_write_tail; 1645*b5c29a34SFrançois Tigeot if (IS_HASWELL(dev)) 1646*b5c29a34SFrançois Tigeot ring->dispatch_execbuffer = hsw_ring_dispatch_execbuffer; 1647*b5c29a34SFrançois Tigeot else if (INTEL_INFO(dev)->gen >= 6) 1648686a02f1SFrançois Tigeot ring->dispatch_execbuffer = gen6_ring_dispatch_execbuffer; 1649686a02f1SFrançois Tigeot else if (INTEL_INFO(dev)->gen >= 4) 1650686a02f1SFrançois Tigeot ring->dispatch_execbuffer = i965_dispatch_execbuffer; 1651686a02f1SFrançois Tigeot else if (IS_I830(dev) || IS_845G(dev)) 1652686a02f1SFrançois Tigeot ring->dispatch_execbuffer = i830_dispatch_execbuffer; 1653686a02f1SFrançois Tigeot else 1654686a02f1SFrançois Tigeot ring->dispatch_execbuffer = i915_dispatch_execbuffer; 1655686a02f1SFrançois Tigeot ring->init = init_render_ring; 1656686a02f1SFrançois Tigeot ring->cleanup = render_ring_cleanup; 1657e3adcf8fSFrançois Tigeot 1658*b5c29a34SFrançois Tigeot /* Workaround batchbuffer to combat CS tlb bug. */ 1659*b5c29a34SFrançois Tigeot if (HAS_BROKEN_CS_TLB(dev)) { 1660*b5c29a34SFrançois Tigeot struct drm_i915_gem_object *obj; 1661*b5c29a34SFrançois Tigeot int ret; 1662*b5c29a34SFrançois Tigeot 1663*b5c29a34SFrançois Tigeot obj = i915_gem_alloc_object(dev, I830_BATCH_LIMIT); 1664*b5c29a34SFrançois Tigeot if (obj == NULL) { 1665*b5c29a34SFrançois Tigeot DRM_ERROR("Failed to allocate batch bo\n"); 1666*b5c29a34SFrançois Tigeot return -ENOMEM; 1667*b5c29a34SFrançois Tigeot } 1668*b5c29a34SFrançois Tigeot 1669*b5c29a34SFrançois Tigeot ret = i915_gem_object_pin(obj, 0, true); 1670*b5c29a34SFrançois Tigeot if (ret != 0) { 1671*b5c29a34SFrançois Tigeot drm_gem_object_unreference(&obj->base); 1672*b5c29a34SFrançois Tigeot DRM_ERROR("Failed to ping batch bo\n"); 1673*b5c29a34SFrançois Tigeot return ret; 1674*b5c29a34SFrançois Tigeot } 1675*b5c29a34SFrançois Tigeot 1676*b5c29a34SFrançois Tigeot ring->private = obj; 1677e3adcf8fSFrançois Tigeot } 1678e3adcf8fSFrançois Tigeot 1679e3adcf8fSFrançois Tigeot return intel_init_ring_buffer(dev, ring); 1680e3adcf8fSFrançois Tigeot } 1681e3adcf8fSFrançois Tigeot 1682686a02f1SFrançois Tigeot int intel_render_ring_init_dri(struct drm_device *dev, u64 start, u32 size) 1683e3adcf8fSFrançois Tigeot { 1684e3adcf8fSFrançois Tigeot drm_i915_private_t *dev_priv = dev->dev_private; 1685ad50ea93SFrançois Tigeot struct intel_ring_buffer *ring = &dev_priv->ring[RCS]; 1686*b5c29a34SFrançois Tigeot int ret; 1687e3adcf8fSFrançois Tigeot 1688686a02f1SFrançois Tigeot ring->name = "render ring"; 1689686a02f1SFrançois Tigeot ring->id = RCS; 1690686a02f1SFrançois Tigeot ring->mmio_base = RENDER_RING_BASE; 1691686a02f1SFrançois Tigeot 1692e3adcf8fSFrançois Tigeot if (INTEL_INFO(dev)->gen >= 6) { 1693686a02f1SFrançois Tigeot /* non-kms not supported on gen6+ */ 1694686a02f1SFrançois Tigeot return -ENODEV; 1695e3adcf8fSFrançois Tigeot } 1696e3adcf8fSFrançois Tigeot 1697686a02f1SFrançois Tigeot /* Note: gem is not supported on gen5/ilk without kms (the corresponding 1698686a02f1SFrançois Tigeot * gem_init ioctl returns with -ENODEV). Hence we do not need to set up 1699686a02f1SFrançois Tigeot * the special gen5 functions. */ 1700686a02f1SFrançois Tigeot ring->add_request = i9xx_add_request; 1701686a02f1SFrançois Tigeot if (INTEL_INFO(dev)->gen < 4) 1702686a02f1SFrançois Tigeot ring->flush = gen2_render_ring_flush; 1703686a02f1SFrançois Tigeot else 1704686a02f1SFrançois Tigeot ring->flush = gen4_render_ring_flush; 1705686a02f1SFrançois Tigeot ring->get_seqno = ring_get_seqno; 1706686a02f1SFrançois Tigeot if (IS_GEN2(dev)) { 1707686a02f1SFrançois Tigeot ring->irq_get = i8xx_ring_get_irq; 1708686a02f1SFrançois Tigeot ring->irq_put = i8xx_ring_put_irq; 1709686a02f1SFrançois Tigeot } else { 1710686a02f1SFrançois Tigeot ring->irq_get = i9xx_ring_get_irq; 1711686a02f1SFrançois Tigeot ring->irq_put = i9xx_ring_put_irq; 1712686a02f1SFrançois Tigeot } 1713686a02f1SFrançois Tigeot ring->irq_enable_mask = I915_USER_INTERRUPT; 1714686a02f1SFrançois Tigeot ring->write_tail = ring_write_tail; 1715686a02f1SFrançois Tigeot if (INTEL_INFO(dev)->gen >= 4) 1716686a02f1SFrançois Tigeot ring->dispatch_execbuffer = i965_dispatch_execbuffer; 1717686a02f1SFrançois Tigeot else if (IS_I830(dev) || IS_845G(dev)) 1718686a02f1SFrançois Tigeot ring->dispatch_execbuffer = i830_dispatch_execbuffer; 1719686a02f1SFrançois Tigeot else 1720686a02f1SFrançois Tigeot ring->dispatch_execbuffer = i915_dispatch_execbuffer; 1721686a02f1SFrançois Tigeot ring->init = init_render_ring; 1722686a02f1SFrançois Tigeot ring->cleanup = render_ring_cleanup; 1723686a02f1SFrançois Tigeot 1724e3adcf8fSFrançois Tigeot ring->dev = dev; 1725e3adcf8fSFrançois Tigeot INIT_LIST_HEAD(&ring->active_list); 1726e3adcf8fSFrançois Tigeot INIT_LIST_HEAD(&ring->request_list); 1727e3adcf8fSFrançois Tigeot INIT_LIST_HEAD(&ring->gpu_write_list); 1728e3adcf8fSFrançois Tigeot 1729e3adcf8fSFrançois Tigeot ring->size = size; 1730e3adcf8fSFrançois Tigeot ring->effective_size = ring->size; 1731*b5c29a34SFrançois Tigeot if (IS_I830(ring->dev) || IS_845G(ring->dev)) 1732e3adcf8fSFrançois Tigeot ring->effective_size -= 128; 1733e3adcf8fSFrançois Tigeot 1734686a02f1SFrançois Tigeot ring->virtual_start = ioremap_wc(start, size); 1735686a02f1SFrançois Tigeot if (ring->virtual_start == NULL) { 1736e3adcf8fSFrançois Tigeot DRM_ERROR("can not ioremap virtual address for" 1737e3adcf8fSFrançois Tigeot " ring buffer\n"); 1738e3adcf8fSFrançois Tigeot return -ENOMEM; 1739e3adcf8fSFrançois Tigeot } 1740e3adcf8fSFrançois Tigeot 1741*b5c29a34SFrançois Tigeot if (!I915_NEED_GFX_HWS(dev)) { 1742*b5c29a34SFrançois Tigeot ret = init_phys_hws_pga(ring); 1743*b5c29a34SFrançois Tigeot if (ret) 1744*b5c29a34SFrançois Tigeot return ret; 1745*b5c29a34SFrançois Tigeot } 1746*b5c29a34SFrançois Tigeot 1747e3adcf8fSFrançois Tigeot return 0; 1748e3adcf8fSFrançois Tigeot } 1749e3adcf8fSFrançois Tigeot 1750e3adcf8fSFrançois Tigeot int intel_init_bsd_ring_buffer(struct drm_device *dev) 1751e3adcf8fSFrançois Tigeot { 1752e3adcf8fSFrançois Tigeot drm_i915_private_t *dev_priv = dev->dev_private; 1753ad50ea93SFrançois Tigeot struct intel_ring_buffer *ring = &dev_priv->ring[VCS]; 1754e3adcf8fSFrançois Tigeot 1755686a02f1SFrançois Tigeot ring->name = "bsd ring"; 1756686a02f1SFrançois Tigeot ring->id = VCS; 1757686a02f1SFrançois Tigeot 1758686a02f1SFrançois Tigeot ring->write_tail = ring_write_tail; 1759686a02f1SFrançois Tigeot if (IS_GEN6(dev) || IS_GEN7(dev)) { 1760686a02f1SFrançois Tigeot ring->mmio_base = GEN6_BSD_RING_BASE; 1761686a02f1SFrançois Tigeot /* gen6 bsd needs a special wa for tail updates */ 1762686a02f1SFrançois Tigeot if (IS_GEN6(dev)) 1763686a02f1SFrançois Tigeot ring->write_tail = gen6_bsd_ring_write_tail; 1764686a02f1SFrançois Tigeot ring->flush = gen6_ring_flush; 1765686a02f1SFrançois Tigeot ring->add_request = gen6_add_request; 1766686a02f1SFrançois Tigeot ring->get_seqno = gen6_ring_get_seqno; 1767686a02f1SFrançois Tigeot ring->irq_enable_mask = GEN6_BSD_USER_INTERRUPT; 1768686a02f1SFrançois Tigeot ring->irq_get = gen6_ring_get_irq; 1769686a02f1SFrançois Tigeot ring->irq_put = gen6_ring_put_irq; 1770686a02f1SFrançois Tigeot ring->dispatch_execbuffer = gen6_ring_dispatch_execbuffer; 1771686a02f1SFrançois Tigeot ring->sync_to = gen6_ring_sync; 1772686a02f1SFrançois Tigeot ring->semaphore_register[0] = MI_SEMAPHORE_SYNC_VR; 1773686a02f1SFrançois Tigeot ring->semaphore_register[1] = MI_SEMAPHORE_SYNC_INVALID; 1774686a02f1SFrançois Tigeot ring->semaphore_register[2] = MI_SEMAPHORE_SYNC_VB; 1775686a02f1SFrançois Tigeot ring->signal_mbox[0] = GEN6_RVSYNC; 1776686a02f1SFrançois Tigeot ring->signal_mbox[1] = GEN6_BVSYNC; 1777686a02f1SFrançois Tigeot } else { 1778686a02f1SFrançois Tigeot ring->mmio_base = BSD_RING_BASE; 1779686a02f1SFrançois Tigeot ring->flush = bsd_ring_flush; 1780686a02f1SFrançois Tigeot ring->add_request = i9xx_add_request; 1781686a02f1SFrançois Tigeot ring->get_seqno = ring_get_seqno; 1782686a02f1SFrançois Tigeot if (IS_GEN5(dev)) { 1783686a02f1SFrançois Tigeot ring->irq_enable_mask = GT_BSD_USER_INTERRUPT; 1784686a02f1SFrançois Tigeot ring->irq_get = gen5_ring_get_irq; 1785686a02f1SFrançois Tigeot ring->irq_put = gen5_ring_put_irq; 1786686a02f1SFrançois Tigeot } else { 1787686a02f1SFrançois Tigeot ring->irq_enable_mask = I915_BSD_USER_INTERRUPT; 1788686a02f1SFrançois Tigeot ring->irq_get = i9xx_ring_get_irq; 1789686a02f1SFrançois Tigeot ring->irq_put = i9xx_ring_put_irq; 1790686a02f1SFrançois Tigeot } 1791686a02f1SFrançois Tigeot ring->dispatch_execbuffer = i965_dispatch_execbuffer; 1792686a02f1SFrançois Tigeot } 1793686a02f1SFrançois Tigeot ring->init = init_ring_common; 1794e3adcf8fSFrançois Tigeot 1795e3adcf8fSFrançois Tigeot return intel_init_ring_buffer(dev, ring); 1796e3adcf8fSFrançois Tigeot } 1797e3adcf8fSFrançois Tigeot 1798e3adcf8fSFrançois Tigeot int intel_init_blt_ring_buffer(struct drm_device *dev) 1799e3adcf8fSFrançois Tigeot { 1800e3adcf8fSFrançois Tigeot drm_i915_private_t *dev_priv = dev->dev_private; 1801ad50ea93SFrançois Tigeot struct intel_ring_buffer *ring = &dev_priv->ring[BCS]; 1802e3adcf8fSFrançois Tigeot 1803686a02f1SFrançois Tigeot ring->name = "blitter ring"; 1804686a02f1SFrançois Tigeot ring->id = BCS; 1805686a02f1SFrançois Tigeot 1806686a02f1SFrançois Tigeot ring->mmio_base = BLT_RING_BASE; 1807686a02f1SFrançois Tigeot ring->write_tail = ring_write_tail; 1808686a02f1SFrançois Tigeot ring->flush = blt_ring_flush; 1809686a02f1SFrançois Tigeot ring->add_request = gen6_add_request; 1810686a02f1SFrançois Tigeot ring->get_seqno = gen6_ring_get_seqno; 1811686a02f1SFrançois Tigeot ring->irq_enable_mask = GEN6_BLITTER_USER_INTERRUPT; 1812686a02f1SFrançois Tigeot ring->irq_get = gen6_ring_get_irq; 1813686a02f1SFrançois Tigeot ring->irq_put = gen6_ring_put_irq; 1814686a02f1SFrançois Tigeot ring->dispatch_execbuffer = gen6_ring_dispatch_execbuffer; 1815686a02f1SFrançois Tigeot ring->sync_to = gen6_ring_sync; 1816686a02f1SFrançois Tigeot ring->semaphore_register[0] = MI_SEMAPHORE_SYNC_BR; 1817686a02f1SFrançois Tigeot ring->semaphore_register[1] = MI_SEMAPHORE_SYNC_BV; 1818686a02f1SFrançois Tigeot ring->semaphore_register[2] = MI_SEMAPHORE_SYNC_INVALID; 1819686a02f1SFrançois Tigeot ring->signal_mbox[0] = GEN6_RBSYNC; 1820686a02f1SFrançois Tigeot ring->signal_mbox[1] = GEN6_VBSYNC; 1821686a02f1SFrançois Tigeot ring->init = init_ring_common; 1822e3adcf8fSFrançois Tigeot 1823e3adcf8fSFrançois Tigeot return intel_init_ring_buffer(dev, ring); 1824e3adcf8fSFrançois Tigeot } 1825b030f26bSFrançois Tigeot 1826b030f26bSFrançois Tigeot int 1827b030f26bSFrançois Tigeot intel_ring_flush_all_caches(struct intel_ring_buffer *ring) 1828b030f26bSFrançois Tigeot { 1829b030f26bSFrançois Tigeot int ret; 1830b030f26bSFrançois Tigeot 1831b030f26bSFrançois Tigeot if (!ring->gpu_caches_dirty) 1832b030f26bSFrançois Tigeot return 0; 1833b030f26bSFrançois Tigeot 1834b030f26bSFrançois Tigeot ret = ring->flush(ring, 0, I915_GEM_GPU_DOMAINS); 1835b030f26bSFrançois Tigeot if (ret) 1836b030f26bSFrançois Tigeot return ret; 1837b030f26bSFrançois Tigeot 1838b030f26bSFrançois Tigeot ring->gpu_caches_dirty = false; 1839b030f26bSFrançois Tigeot return 0; 1840b030f26bSFrançois Tigeot } 1841b030f26bSFrançois Tigeot 1842b030f26bSFrançois Tigeot int 1843b030f26bSFrançois Tigeot intel_ring_invalidate_all_caches(struct intel_ring_buffer *ring) 1844b030f26bSFrançois Tigeot { 1845b030f26bSFrançois Tigeot uint32_t flush_domains; 1846b030f26bSFrançois Tigeot int ret; 1847b030f26bSFrançois Tigeot 1848b030f26bSFrançois Tigeot flush_domains = 0; 1849b030f26bSFrançois Tigeot if (ring->gpu_caches_dirty) 1850b030f26bSFrançois Tigeot flush_domains = I915_GEM_GPU_DOMAINS; 1851b030f26bSFrançois Tigeot 1852b030f26bSFrançois Tigeot ret = ring->flush(ring, I915_GEM_GPU_DOMAINS, flush_domains); 1853b030f26bSFrançois Tigeot if (ret) 1854b030f26bSFrançois Tigeot return ret; 1855b030f26bSFrançois Tigeot 1856b030f26bSFrançois Tigeot ring->gpu_caches_dirty = false; 1857b030f26bSFrançois Tigeot return 0; 1858b030f26bSFrançois Tigeot } 1859