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 * $FreeBSD: head/sys/dev/drm2/i915/intel_ringbuffer.c 253709 2013-07-27 16:42:29Z kib $ 29e3adcf8fSFrançois Tigeot */ 30e3adcf8fSFrançois Tigeot 3118e26a6dSFrançois Tigeot #include <drm/drmP.h> 325c6c6f23SFrançois Tigeot #include <drm/i915_drm.h> 33e3adcf8fSFrançois Tigeot #include "i915_drv.h" 34e3adcf8fSFrançois Tigeot #include "intel_drv.h" 35e3adcf8fSFrançois Tigeot #include "intel_ringbuffer.h" 36e3adcf8fSFrançois Tigeot #include <sys/sched.h> 37e3adcf8fSFrançois Tigeot 38e3adcf8fSFrançois Tigeot /* 39e3adcf8fSFrançois Tigeot * 965+ support PIPE_CONTROL commands, which provide finer grained control 40e3adcf8fSFrançois Tigeot * over cache flushing. 41e3adcf8fSFrançois Tigeot */ 42e3adcf8fSFrançois Tigeot struct pipe_control { 43e3adcf8fSFrançois Tigeot struct drm_i915_gem_object *obj; 44e3adcf8fSFrançois Tigeot volatile u32 *cpu_page; 45e3adcf8fSFrançois Tigeot u32 gtt_offset; 46e3adcf8fSFrançois Tigeot }; 47e3adcf8fSFrançois Tigeot 48e3adcf8fSFrançois Tigeot static inline int ring_space(struct intel_ring_buffer *ring) 49e3adcf8fSFrançois Tigeot { 507cbd1a46SFrançois Tigeot int space = (ring->head & HEAD_ADDR) - (ring->tail + I915_RING_FREE_SPACE); 51e3adcf8fSFrançois Tigeot if (space < 0) 52e3adcf8fSFrançois Tigeot space += ring->size; 53e3adcf8fSFrançois Tigeot return space; 54e3adcf8fSFrançois Tigeot } 55e3adcf8fSFrançois Tigeot 56e3adcf8fSFrançois Tigeot static int 57e3adcf8fSFrançois Tigeot render_ring_flush(struct intel_ring_buffer *ring, 58e3adcf8fSFrançois Tigeot uint32_t invalidate_domains, 59e3adcf8fSFrançois Tigeot uint32_t flush_domains) 60e3adcf8fSFrançois Tigeot { 61e3adcf8fSFrançois Tigeot struct drm_device *dev = ring->dev; 62e3adcf8fSFrançois Tigeot uint32_t cmd; 63e3adcf8fSFrançois Tigeot int ret; 64e3adcf8fSFrançois Tigeot 65e3adcf8fSFrançois Tigeot /* 66e3adcf8fSFrançois Tigeot * read/write caches: 67e3adcf8fSFrançois Tigeot * 68e3adcf8fSFrançois Tigeot * I915_GEM_DOMAIN_RENDER is always invalidated, but is 69e3adcf8fSFrançois Tigeot * only flushed if MI_NO_WRITE_FLUSH is unset. On 965, it is 70e3adcf8fSFrançois Tigeot * also flushed at 2d versus 3d pipeline switches. 71e3adcf8fSFrançois Tigeot * 72e3adcf8fSFrançois Tigeot * read-only caches: 73e3adcf8fSFrançois Tigeot * 74e3adcf8fSFrançois Tigeot * I915_GEM_DOMAIN_SAMPLER is flushed on pre-965 if 75e3adcf8fSFrançois Tigeot * MI_READ_FLUSH is set, and is always flushed on 965. 76e3adcf8fSFrançois Tigeot * 77e3adcf8fSFrançois Tigeot * I915_GEM_DOMAIN_COMMAND may not exist? 78e3adcf8fSFrançois Tigeot * 79e3adcf8fSFrançois Tigeot * I915_GEM_DOMAIN_INSTRUCTION, which exists on 965, is 80e3adcf8fSFrançois Tigeot * invalidated when MI_EXE_FLUSH is set. 81e3adcf8fSFrançois Tigeot * 82e3adcf8fSFrançois Tigeot * I915_GEM_DOMAIN_VERTEX, which exists on 965, is 83e3adcf8fSFrançois Tigeot * invalidated with every MI_FLUSH. 84e3adcf8fSFrançois Tigeot * 85e3adcf8fSFrançois Tigeot * TLBs: 86e3adcf8fSFrançois Tigeot * 87e3adcf8fSFrançois Tigeot * On 965, TLBs associated with I915_GEM_DOMAIN_COMMAND 88e3adcf8fSFrançois Tigeot * and I915_GEM_DOMAIN_CPU in are invalidated at PTE write and 89e3adcf8fSFrançois Tigeot * I915_GEM_DOMAIN_RENDER and I915_GEM_DOMAIN_SAMPLER 90e3adcf8fSFrançois Tigeot * are flushed at any MI_FLUSH. 91e3adcf8fSFrançois Tigeot */ 92e3adcf8fSFrançois Tigeot 93e3adcf8fSFrançois Tigeot cmd = MI_FLUSH | MI_NO_WRITE_FLUSH; 94e3adcf8fSFrançois Tigeot if ((invalidate_domains|flush_domains) & 95e3adcf8fSFrançois Tigeot I915_GEM_DOMAIN_RENDER) 96e3adcf8fSFrançois Tigeot cmd &= ~MI_NO_WRITE_FLUSH; 97e3adcf8fSFrançois Tigeot if (INTEL_INFO(dev)->gen < 4) { 98e3adcf8fSFrançois Tigeot /* 99e3adcf8fSFrançois Tigeot * On the 965, the sampler cache always gets flushed 100e3adcf8fSFrançois Tigeot * and this bit is reserved. 101e3adcf8fSFrançois Tigeot */ 102e3adcf8fSFrançois Tigeot if (invalidate_domains & I915_GEM_DOMAIN_SAMPLER) 103e3adcf8fSFrançois Tigeot cmd |= MI_READ_FLUSH; 104e3adcf8fSFrançois Tigeot } 105e3adcf8fSFrançois Tigeot if (invalidate_domains & I915_GEM_DOMAIN_INSTRUCTION) 106e3adcf8fSFrançois Tigeot cmd |= MI_EXE_FLUSH; 107e3adcf8fSFrançois Tigeot 108e3adcf8fSFrançois Tigeot if (invalidate_domains & I915_GEM_DOMAIN_COMMAND && 109e3adcf8fSFrançois Tigeot (IS_G4X(dev) || IS_GEN5(dev))) 110e3adcf8fSFrançois Tigeot cmd |= MI_INVALIDATE_ISP; 111e3adcf8fSFrançois Tigeot 112e3adcf8fSFrançois Tigeot ret = intel_ring_begin(ring, 2); 113e3adcf8fSFrançois Tigeot if (ret) 114e3adcf8fSFrançois Tigeot return ret; 115e3adcf8fSFrançois Tigeot 116e3adcf8fSFrançois Tigeot intel_ring_emit(ring, cmd); 117e3adcf8fSFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 118e3adcf8fSFrançois Tigeot intel_ring_advance(ring); 119e3adcf8fSFrançois Tigeot 120e3adcf8fSFrançois Tigeot return 0; 121e3adcf8fSFrançois Tigeot } 122e3adcf8fSFrançois Tigeot 123e3adcf8fSFrançois Tigeot /** 124e3adcf8fSFrançois Tigeot * Emits a PIPE_CONTROL with a non-zero post-sync operation, for 125e3adcf8fSFrançois Tigeot * implementing two workarounds on gen6. From section 1.4.7.1 126e3adcf8fSFrançois Tigeot * "PIPE_CONTROL" of the Sandy Bridge PRM volume 2 part 1: 127e3adcf8fSFrançois Tigeot * 128e3adcf8fSFrançois Tigeot * [DevSNB-C+{W/A}] Before any depth stall flush (including those 129e3adcf8fSFrançois Tigeot * produced by non-pipelined state commands), software needs to first 130e3adcf8fSFrançois Tigeot * send a PIPE_CONTROL with no bits set except Post-Sync Operation != 131e3adcf8fSFrançois Tigeot * 0. 132e3adcf8fSFrançois Tigeot * 133e3adcf8fSFrançois Tigeot * [Dev-SNB{W/A}]: Before a PIPE_CONTROL with Write Cache Flush Enable 134e3adcf8fSFrançois Tigeot * =1, a PIPE_CONTROL with any non-zero post-sync-op is required. 135e3adcf8fSFrançois Tigeot * 136e3adcf8fSFrançois Tigeot * And the workaround for these two requires this workaround first: 137e3adcf8fSFrançois Tigeot * 138e3adcf8fSFrançois Tigeot * [Dev-SNB{W/A}]: Pipe-control with CS-stall bit set must be sent 139e3adcf8fSFrançois Tigeot * BEFORE the pipe-control with a post-sync op and no write-cache 140e3adcf8fSFrançois Tigeot * flushes. 141e3adcf8fSFrançois Tigeot * 142e3adcf8fSFrançois Tigeot * And this last workaround is tricky because of the requirements on 143e3adcf8fSFrançois Tigeot * that bit. From section 1.4.7.2.3 "Stall" of the Sandy Bridge PRM 144e3adcf8fSFrançois Tigeot * volume 2 part 1: 145e3adcf8fSFrançois Tigeot * 146e3adcf8fSFrançois Tigeot * "1 of the following must also be set: 147e3adcf8fSFrançois Tigeot * - Render Target Cache Flush Enable ([12] of DW1) 148e3adcf8fSFrançois Tigeot * - Depth Cache Flush Enable ([0] of DW1) 149e3adcf8fSFrançois Tigeot * - Stall at Pixel Scoreboard ([1] of DW1) 150e3adcf8fSFrançois Tigeot * - Depth Stall ([13] of DW1) 151e3adcf8fSFrançois Tigeot * - Post-Sync Operation ([13] of DW1) 152e3adcf8fSFrançois Tigeot * - Notify Enable ([8] of DW1)" 153e3adcf8fSFrançois Tigeot * 154e3adcf8fSFrançois Tigeot * The cache flushes require the workaround flush that triggered this 155e3adcf8fSFrançois Tigeot * one, so we can't use it. Depth stall would trigger the same. 156e3adcf8fSFrançois Tigeot * Post-sync nonzero is what triggered this second workaround, so we 157e3adcf8fSFrançois Tigeot * can't use that one either. Notify enable is IRQs, which aren't 158e3adcf8fSFrançois Tigeot * really our business. That leaves only stall at scoreboard. 159e3adcf8fSFrançois Tigeot */ 160e3adcf8fSFrançois Tigeot static int 161e3adcf8fSFrançois Tigeot intel_emit_post_sync_nonzero_flush(struct intel_ring_buffer *ring) 162e3adcf8fSFrançois Tigeot { 163e3adcf8fSFrançois Tigeot struct pipe_control *pc = ring->private; 164e3adcf8fSFrançois Tigeot u32 scratch_addr = pc->gtt_offset + 128; 165e3adcf8fSFrançois Tigeot int ret; 166e3adcf8fSFrançois Tigeot 167e3adcf8fSFrançois Tigeot 168e3adcf8fSFrançois Tigeot ret = intel_ring_begin(ring, 6); 169e3adcf8fSFrançois Tigeot if (ret) 170e3adcf8fSFrançois Tigeot return ret; 171e3adcf8fSFrançois Tigeot 172e3adcf8fSFrançois Tigeot intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(5)); 173e3adcf8fSFrançois Tigeot intel_ring_emit(ring, PIPE_CONTROL_CS_STALL | 174e3adcf8fSFrançois Tigeot PIPE_CONTROL_STALL_AT_SCOREBOARD); 175e3adcf8fSFrançois Tigeot intel_ring_emit(ring, scratch_addr | PIPE_CONTROL_GLOBAL_GTT); /* address */ 176e3adcf8fSFrançois Tigeot intel_ring_emit(ring, 0); /* low dword */ 177e3adcf8fSFrançois Tigeot intel_ring_emit(ring, 0); /* high dword */ 178e3adcf8fSFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 179e3adcf8fSFrançois Tigeot intel_ring_advance(ring); 180e3adcf8fSFrançois Tigeot 181e3adcf8fSFrançois Tigeot ret = intel_ring_begin(ring, 6); 182e3adcf8fSFrançois Tigeot if (ret) 183e3adcf8fSFrançois Tigeot return ret; 184e3adcf8fSFrançois Tigeot 185e3adcf8fSFrançois Tigeot intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(5)); 186e3adcf8fSFrançois Tigeot intel_ring_emit(ring, PIPE_CONTROL_QW_WRITE); 187e3adcf8fSFrançois Tigeot intel_ring_emit(ring, scratch_addr | PIPE_CONTROL_GLOBAL_GTT); /* address */ 188e3adcf8fSFrançois Tigeot intel_ring_emit(ring, 0); 189e3adcf8fSFrançois Tigeot intel_ring_emit(ring, 0); 190e3adcf8fSFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 191e3adcf8fSFrançois Tigeot intel_ring_advance(ring); 192e3adcf8fSFrançois Tigeot 193e3adcf8fSFrançois Tigeot return 0; 194e3adcf8fSFrançois Tigeot } 195e3adcf8fSFrançois Tigeot 196e3adcf8fSFrançois Tigeot static int 197e3adcf8fSFrançois Tigeot gen6_render_ring_flush(struct intel_ring_buffer *ring, 198e3adcf8fSFrançois Tigeot u32 invalidate_domains, u32 flush_domains) 199e3adcf8fSFrançois Tigeot { 200e3adcf8fSFrançois Tigeot u32 flags = 0; 201e3adcf8fSFrançois Tigeot struct pipe_control *pc = ring->private; 202e3adcf8fSFrançois Tigeot u32 scratch_addr = pc->gtt_offset + 128; 203e3adcf8fSFrançois Tigeot int ret; 204e3adcf8fSFrançois Tigeot 205e3adcf8fSFrançois Tigeot /* Force SNB workarounds for PIPE_CONTROL flushes */ 206e3adcf8fSFrançois Tigeot intel_emit_post_sync_nonzero_flush(ring); 207e3adcf8fSFrançois Tigeot 208e3adcf8fSFrançois Tigeot /* Just flush everything. Experiments have shown that reducing the 209e3adcf8fSFrançois Tigeot * number of bits based on the write domains has little performance 210e3adcf8fSFrançois Tigeot * impact. 211e3adcf8fSFrançois Tigeot */ 212e3adcf8fSFrançois Tigeot flags |= PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH; 213e3adcf8fSFrançois Tigeot flags |= PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE; 214e3adcf8fSFrançois Tigeot flags |= PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE; 215e3adcf8fSFrançois Tigeot flags |= PIPE_CONTROL_DEPTH_CACHE_FLUSH; 216e3adcf8fSFrançois Tigeot flags |= PIPE_CONTROL_VF_CACHE_INVALIDATE; 217e3adcf8fSFrançois Tigeot flags |= PIPE_CONTROL_CONST_CACHE_INVALIDATE; 218e3adcf8fSFrançois Tigeot flags |= PIPE_CONTROL_STATE_CACHE_INVALIDATE; 219e3adcf8fSFrançois Tigeot 220e3adcf8fSFrançois Tigeot ret = intel_ring_begin(ring, 6); 221e3adcf8fSFrançois Tigeot if (ret) 222e3adcf8fSFrançois Tigeot return ret; 223e3adcf8fSFrançois Tigeot 224e3adcf8fSFrançois Tigeot intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(5)); 225e3adcf8fSFrançois Tigeot intel_ring_emit(ring, flags); 226e3adcf8fSFrançois Tigeot intel_ring_emit(ring, scratch_addr | PIPE_CONTROL_GLOBAL_GTT); 227e3adcf8fSFrançois Tigeot intel_ring_emit(ring, 0); /* lower dword */ 228e3adcf8fSFrançois Tigeot intel_ring_emit(ring, 0); /* uppwer dword */ 229e3adcf8fSFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 230e3adcf8fSFrançois Tigeot intel_ring_advance(ring); 231e3adcf8fSFrançois Tigeot 232e3adcf8fSFrançois Tigeot return 0; 233e3adcf8fSFrançois Tigeot } 234e3adcf8fSFrançois Tigeot 235e3adcf8fSFrançois Tigeot static void ring_write_tail(struct intel_ring_buffer *ring, 236e3adcf8fSFrançois Tigeot uint32_t value) 237e3adcf8fSFrançois Tigeot { 238e3adcf8fSFrançois Tigeot drm_i915_private_t *dev_priv = ring->dev->dev_private; 239e3adcf8fSFrançois Tigeot I915_WRITE_TAIL(ring, value); 240e3adcf8fSFrançois Tigeot } 241e3adcf8fSFrançois Tigeot 242e3adcf8fSFrançois Tigeot u32 intel_ring_get_active_head(struct intel_ring_buffer *ring) 243e3adcf8fSFrançois Tigeot { 244e3adcf8fSFrançois Tigeot drm_i915_private_t *dev_priv = ring->dev->dev_private; 245e3adcf8fSFrançois Tigeot uint32_t acthd_reg = INTEL_INFO(ring->dev)->gen >= 4 ? 246e3adcf8fSFrançois Tigeot RING_ACTHD(ring->mmio_base) : ACTHD; 247e3adcf8fSFrançois Tigeot 248e3adcf8fSFrançois Tigeot return I915_READ(acthd_reg); 249e3adcf8fSFrançois Tigeot } 250e3adcf8fSFrançois Tigeot 251e3adcf8fSFrançois Tigeot static int init_ring_common(struct intel_ring_buffer *ring) 252e3adcf8fSFrançois Tigeot { 253e3adcf8fSFrançois Tigeot drm_i915_private_t *dev_priv = ring->dev->dev_private; 254e3adcf8fSFrançois Tigeot struct drm_i915_gem_object *obj = ring->obj; 255e3adcf8fSFrançois Tigeot uint32_t head; 256e3adcf8fSFrançois Tigeot 257e3adcf8fSFrançois Tigeot /* Stop the ring if it's running. */ 258e3adcf8fSFrançois Tigeot I915_WRITE_CTL(ring, 0); 259e3adcf8fSFrançois Tigeot I915_WRITE_HEAD(ring, 0); 260e3adcf8fSFrançois Tigeot ring->write_tail(ring, 0); 261e3adcf8fSFrançois Tigeot 262e3adcf8fSFrançois Tigeot /* Initialize the ring. */ 263e3adcf8fSFrançois Tigeot I915_WRITE_START(ring, obj->gtt_offset); 264e3adcf8fSFrançois Tigeot head = I915_READ_HEAD(ring) & HEAD_ADDR; 265e3adcf8fSFrançois Tigeot 266e3adcf8fSFrançois Tigeot /* G45 ring initialization fails to reset head to zero */ 267e3adcf8fSFrançois Tigeot if (head != 0) { 268e3adcf8fSFrançois Tigeot DRM_DEBUG("%s head not reset to zero " 269e3adcf8fSFrançois Tigeot "ctl %08x head %08x tail %08x start %08x\n", 270e3adcf8fSFrançois Tigeot ring->name, 271e3adcf8fSFrançois Tigeot I915_READ_CTL(ring), 272e3adcf8fSFrançois Tigeot I915_READ_HEAD(ring), 273e3adcf8fSFrançois Tigeot I915_READ_TAIL(ring), 274e3adcf8fSFrançois Tigeot I915_READ_START(ring)); 275e3adcf8fSFrançois Tigeot 276e3adcf8fSFrançois Tigeot I915_WRITE_HEAD(ring, 0); 277e3adcf8fSFrançois Tigeot 278e3adcf8fSFrançois Tigeot if (I915_READ_HEAD(ring) & HEAD_ADDR) { 279e3adcf8fSFrançois Tigeot DRM_ERROR("failed to set %s head to zero " 280e3adcf8fSFrançois Tigeot "ctl %08x head %08x tail %08x start %08x\n", 281e3adcf8fSFrançois Tigeot ring->name, 282e3adcf8fSFrançois Tigeot I915_READ_CTL(ring), 283e3adcf8fSFrançois Tigeot I915_READ_HEAD(ring), 284e3adcf8fSFrançois Tigeot I915_READ_TAIL(ring), 285e3adcf8fSFrançois Tigeot I915_READ_START(ring)); 286e3adcf8fSFrançois Tigeot } 287e3adcf8fSFrançois Tigeot } 288e3adcf8fSFrançois Tigeot 289e3adcf8fSFrançois Tigeot I915_WRITE_CTL(ring, 290e3adcf8fSFrançois Tigeot ((ring->size - PAGE_SIZE) & RING_NR_PAGES) 291e3adcf8fSFrançois Tigeot | RING_VALID); 292e3adcf8fSFrançois Tigeot 293e3adcf8fSFrançois Tigeot /* If the head is still not zero, the ring is dead */ 294e3adcf8fSFrançois Tigeot if (_intel_wait_for(ring->dev, 295e3adcf8fSFrançois Tigeot (I915_READ_CTL(ring) & RING_VALID) != 0 && 296e3adcf8fSFrançois Tigeot I915_READ_START(ring) == obj->gtt_offset && 297e3adcf8fSFrançois Tigeot (I915_READ_HEAD(ring) & HEAD_ADDR) == 0, 298e3adcf8fSFrançois Tigeot 50, 1, "915rii")) { 299e3adcf8fSFrançois Tigeot DRM_ERROR("%s initialization failed " 300e3adcf8fSFrançois Tigeot "ctl %08x head %08x tail %08x start %08x\n", 301e3adcf8fSFrançois Tigeot ring->name, 302e3adcf8fSFrançois Tigeot I915_READ_CTL(ring), 303e3adcf8fSFrançois Tigeot I915_READ_HEAD(ring), 304e3adcf8fSFrançois Tigeot I915_READ_TAIL(ring), 305e3adcf8fSFrançois Tigeot I915_READ_START(ring)); 306e3adcf8fSFrançois Tigeot return -EIO; 307e3adcf8fSFrançois Tigeot } 308e3adcf8fSFrançois Tigeot 309e3adcf8fSFrançois Tigeot if (!drm_core_check_feature(ring->dev, DRIVER_MODESET)) 310e3adcf8fSFrançois Tigeot i915_kernel_lost_context(ring->dev); 311e3adcf8fSFrançois Tigeot else { 312e3adcf8fSFrançois Tigeot ring->head = I915_READ_HEAD(ring); 313e3adcf8fSFrançois Tigeot ring->tail = I915_READ_TAIL(ring) & TAIL_ADDR; 314e3adcf8fSFrançois Tigeot ring->space = ring_space(ring); 315e3adcf8fSFrançois Tigeot } 316e3adcf8fSFrançois Tigeot 317e3adcf8fSFrançois Tigeot return 0; 318e3adcf8fSFrançois Tigeot } 319e3adcf8fSFrançois Tigeot 320e3adcf8fSFrançois Tigeot static int 321e3adcf8fSFrançois Tigeot init_pipe_control(struct intel_ring_buffer *ring) 322e3adcf8fSFrançois Tigeot { 323e3adcf8fSFrançois Tigeot struct pipe_control *pc; 324e3adcf8fSFrançois Tigeot struct drm_i915_gem_object *obj; 325e3adcf8fSFrançois Tigeot int ret; 326e3adcf8fSFrançois Tigeot 327e3adcf8fSFrançois Tigeot if (ring->private) 328e3adcf8fSFrançois Tigeot return 0; 329e3adcf8fSFrançois Tigeot 330e3adcf8fSFrançois Tigeot pc = kmalloc(sizeof(*pc), DRM_I915_GEM, M_WAITOK); 331e3adcf8fSFrançois Tigeot if (!pc) 332e3adcf8fSFrançois Tigeot return -ENOMEM; 333e3adcf8fSFrançois Tigeot 334e3adcf8fSFrançois Tigeot obj = i915_gem_alloc_object(ring->dev, 4096); 335e3adcf8fSFrançois Tigeot if (obj == NULL) { 336e3adcf8fSFrançois Tigeot DRM_ERROR("Failed to allocate seqno page\n"); 337e3adcf8fSFrançois Tigeot ret = -ENOMEM; 338e3adcf8fSFrançois Tigeot goto err; 339e3adcf8fSFrançois Tigeot } 340e3adcf8fSFrançois Tigeot 341e3adcf8fSFrançois Tigeot i915_gem_object_set_cache_level(obj, I915_CACHE_LLC); 342e3adcf8fSFrançois Tigeot 343e3adcf8fSFrançois Tigeot ret = i915_gem_object_pin(obj, 4096, true); 344e3adcf8fSFrançois Tigeot if (ret) 345e3adcf8fSFrançois Tigeot goto err_unref; 346e3adcf8fSFrançois Tigeot 347e3adcf8fSFrançois Tigeot pc->gtt_offset = obj->gtt_offset; 348e3adcf8fSFrançois Tigeot pc->cpu_page = (uint32_t *)kmem_alloc_nofault(&kernel_map, PAGE_SIZE, PAGE_SIZE); 349e3adcf8fSFrançois Tigeot if (pc->cpu_page == NULL) 350e3adcf8fSFrançois Tigeot goto err_unpin; 351e3adcf8fSFrançois Tigeot pmap_qenter((uintptr_t)pc->cpu_page, &obj->pages[0], 1); 352e3adcf8fSFrançois Tigeot pmap_invalidate_cache_range((vm_offset_t)pc->cpu_page, 353e3adcf8fSFrançois Tigeot (vm_offset_t)pc->cpu_page + PAGE_SIZE); 354e3adcf8fSFrançois Tigeot 355e3adcf8fSFrançois Tigeot pc->obj = obj; 356e3adcf8fSFrançois Tigeot ring->private = pc; 357e3adcf8fSFrançois Tigeot return 0; 358e3adcf8fSFrançois Tigeot 359e3adcf8fSFrançois Tigeot err_unpin: 360e3adcf8fSFrançois Tigeot i915_gem_object_unpin(obj); 361e3adcf8fSFrançois Tigeot err_unref: 362e3adcf8fSFrançois Tigeot drm_gem_object_unreference(&obj->base); 363e3adcf8fSFrançois Tigeot err: 364e3adcf8fSFrançois Tigeot drm_free(pc, DRM_I915_GEM); 365e3adcf8fSFrançois Tigeot return ret; 366e3adcf8fSFrançois Tigeot } 367e3adcf8fSFrançois Tigeot 368e3adcf8fSFrançois Tigeot static void 369e3adcf8fSFrançois Tigeot cleanup_pipe_control(struct intel_ring_buffer *ring) 370e3adcf8fSFrançois Tigeot { 371e3adcf8fSFrançois Tigeot struct pipe_control *pc = ring->private; 372e3adcf8fSFrançois Tigeot struct drm_i915_gem_object *obj; 373e3adcf8fSFrançois Tigeot 374e3adcf8fSFrançois Tigeot if (!ring->private) 375e3adcf8fSFrançois Tigeot return; 376e3adcf8fSFrançois Tigeot 377e3adcf8fSFrançois Tigeot obj = pc->obj; 378e3adcf8fSFrançois Tigeot pmap_qremove((vm_offset_t)pc->cpu_page, 1); 379e3adcf8fSFrançois Tigeot kmem_free(&kernel_map, (uintptr_t)pc->cpu_page, PAGE_SIZE); 380e3adcf8fSFrançois Tigeot i915_gem_object_unpin(obj); 381e3adcf8fSFrançois Tigeot drm_gem_object_unreference(&obj->base); 382e3adcf8fSFrançois Tigeot 383e3adcf8fSFrançois Tigeot drm_free(pc, DRM_I915_GEM); 384e3adcf8fSFrançois Tigeot ring->private = NULL; 385e3adcf8fSFrançois Tigeot } 386e3adcf8fSFrançois Tigeot 387e3adcf8fSFrançois Tigeot static int init_render_ring(struct intel_ring_buffer *ring) 388e3adcf8fSFrançois Tigeot { 389e3adcf8fSFrançois Tigeot struct drm_device *dev = ring->dev; 390e3adcf8fSFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 391e3adcf8fSFrançois Tigeot int ret = init_ring_common(ring); 392e3adcf8fSFrançois Tigeot 393f4e1c372SFrançois Tigeot if (INTEL_INFO(dev)->gen > 3) 394f4e1c372SFrançois Tigeot I915_WRITE(MI_MODE, _MASKED_BIT_ENABLE(VS_TIMER_DISPATCH)); 395f4e1c372SFrançois Tigeot 396f4e1c372SFrançois Tigeot /* We need to disable the AsyncFlip performance optimisations in order 397f4e1c372SFrançois Tigeot * to use MI_WAIT_FOR_EVENT within the CS. It should already be 398f4e1c372SFrançois Tigeot * programmed to '1' on all products. 399f4e1c372SFrançois Tigeot */ 400f4e1c372SFrançois Tigeot if (INTEL_INFO(dev)->gen >= 6) 401f4e1c372SFrançois Tigeot I915_WRITE(MI_MODE, _MASKED_BIT_ENABLE(ASYNC_FLIP_PERF_DISABLE)); 402f4e1c372SFrançois Tigeot 403f4e1c372SFrançois Tigeot /* Required for the hardware to program scanline values for waiting */ 404f4e1c372SFrançois Tigeot if (INTEL_INFO(dev)->gen == 6) 405f4e1c372SFrançois Tigeot I915_WRITE(GFX_MODE, 406f4e1c372SFrançois Tigeot _MASKED_BIT_ENABLE(GFX_TLB_INVALIDATE_ALWAYS)); 407f4e1c372SFrançois Tigeot 408e3adcf8fSFrançois Tigeot if (IS_GEN7(dev)) 409e3adcf8fSFrançois Tigeot I915_WRITE(GFX_MODE_GEN7, 410f4e1c372SFrançois Tigeot _MASKED_BIT_DISABLE(GFX_TLB_INVALIDATE_ALWAYS) | 411f4e1c372SFrançois Tigeot _MASKED_BIT_ENABLE(GFX_REPLAY_MODE)); 412e3adcf8fSFrançois Tigeot 413e3adcf8fSFrançois Tigeot if (INTEL_INFO(dev)->gen >= 5) { 414e3adcf8fSFrançois Tigeot ret = init_pipe_control(ring); 415e3adcf8fSFrançois Tigeot if (ret) 416e3adcf8fSFrançois Tigeot return ret; 417e3adcf8fSFrançois Tigeot } 418e3adcf8fSFrançois Tigeot 419e3adcf8fSFrançois Tigeot if (IS_GEN6(dev)) { 420e3adcf8fSFrançois Tigeot /* From the Sandybridge PRM, volume 1 part 3, page 24: 421e3adcf8fSFrançois Tigeot * "If this bit is set, STCunit will have LRA as replacement 422e3adcf8fSFrançois Tigeot * policy. [...] This bit must be reset. LRA replacement 423e3adcf8fSFrançois Tigeot * policy is not supported." 424e3adcf8fSFrançois Tigeot */ 425e3adcf8fSFrançois Tigeot I915_WRITE(CACHE_MODE_0, 426f4e1c372SFrançois Tigeot _MASKED_BIT_DISABLE(CM0_STC_EVICT_DISABLE_LRA_SNB)); 427e3adcf8fSFrançois Tigeot } 428e3adcf8fSFrançois Tigeot 429f4e1c372SFrançois Tigeot if (INTEL_INFO(dev)->gen >= 6) 430f4e1c372SFrançois Tigeot I915_WRITE(INSTPM, _MASKED_BIT_ENABLE(INSTPM_FORCE_ORDERING)); 431f4e1c372SFrançois Tigeot 432f4e1c372SFrançois Tigeot if (HAS_L3_GPU_CACHE(dev)) 433f4e1c372SFrançois Tigeot I915_WRITE_IMR(ring, ~GEN6_RENDER_L3_PARITY_ERROR); 434e3adcf8fSFrançois Tigeot 435e3adcf8fSFrançois Tigeot return ret; 436e3adcf8fSFrançois Tigeot } 437e3adcf8fSFrançois Tigeot 438e3adcf8fSFrançois Tigeot static void render_ring_cleanup(struct intel_ring_buffer *ring) 439e3adcf8fSFrançois Tigeot { 440e3adcf8fSFrançois Tigeot if (!ring->private) 441e3adcf8fSFrançois Tigeot return; 442e3adcf8fSFrançois Tigeot 443e3adcf8fSFrançois Tigeot cleanup_pipe_control(ring); 444e3adcf8fSFrançois Tigeot } 445e3adcf8fSFrançois Tigeot 446e3adcf8fSFrançois Tigeot static void 447e3adcf8fSFrançois Tigeot update_mboxes(struct intel_ring_buffer *ring, 448e3adcf8fSFrançois Tigeot u32 seqno, 449e3adcf8fSFrançois Tigeot u32 mmio_offset) 450e3adcf8fSFrançois Tigeot { 451e3adcf8fSFrançois Tigeot intel_ring_emit(ring, MI_SEMAPHORE_MBOX | 452e3adcf8fSFrançois Tigeot MI_SEMAPHORE_GLOBAL_GTT | 453e3adcf8fSFrançois Tigeot MI_SEMAPHORE_REGISTER | 454e3adcf8fSFrançois Tigeot MI_SEMAPHORE_UPDATE); 455e3adcf8fSFrançois Tigeot intel_ring_emit(ring, seqno); 456e3adcf8fSFrançois Tigeot intel_ring_emit(ring, mmio_offset); 457e3adcf8fSFrançois Tigeot } 458e3adcf8fSFrançois Tigeot 459e3adcf8fSFrançois Tigeot /** 460e3adcf8fSFrançois Tigeot * gen6_add_request - Update the semaphore mailbox registers 461e3adcf8fSFrançois Tigeot * 462e3adcf8fSFrançois Tigeot * @ring - ring that is adding a request 463e3adcf8fSFrançois Tigeot * @seqno - return seqno stuck into the ring 464e3adcf8fSFrançois Tigeot * 465e3adcf8fSFrançois Tigeot * Update the mailbox registers in the *other* rings with the current seqno. 466e3adcf8fSFrançois Tigeot * This acts like a signal in the canonical semaphore. 467e3adcf8fSFrançois Tigeot */ 468e3adcf8fSFrançois Tigeot static int 469e3adcf8fSFrançois Tigeot gen6_add_request(struct intel_ring_buffer *ring, 470e3adcf8fSFrançois Tigeot u32 *seqno) 471e3adcf8fSFrançois Tigeot { 472e3adcf8fSFrançois Tigeot u32 mbox1_reg; 473e3adcf8fSFrançois Tigeot u32 mbox2_reg; 474e3adcf8fSFrançois Tigeot int ret; 475e3adcf8fSFrançois Tigeot 476e3adcf8fSFrançois Tigeot ret = intel_ring_begin(ring, 10); 477e3adcf8fSFrançois Tigeot if (ret) 478e3adcf8fSFrançois Tigeot return ret; 479e3adcf8fSFrançois Tigeot 480e3adcf8fSFrançois Tigeot mbox1_reg = ring->signal_mbox[0]; 481e3adcf8fSFrançois Tigeot mbox2_reg = ring->signal_mbox[1]; 482e3adcf8fSFrançois Tigeot 483e3adcf8fSFrançois Tigeot *seqno = i915_gem_next_request_seqno(ring); 484e3adcf8fSFrançois Tigeot 485e3adcf8fSFrançois Tigeot update_mboxes(ring, *seqno, mbox1_reg); 486e3adcf8fSFrançois Tigeot update_mboxes(ring, *seqno, mbox2_reg); 487e3adcf8fSFrançois Tigeot intel_ring_emit(ring, MI_STORE_DWORD_INDEX); 488e3adcf8fSFrançois Tigeot intel_ring_emit(ring, I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT); 489e3adcf8fSFrançois Tigeot intel_ring_emit(ring, *seqno); 490e3adcf8fSFrançois Tigeot intel_ring_emit(ring, MI_USER_INTERRUPT); 491e3adcf8fSFrançois Tigeot intel_ring_advance(ring); 492e3adcf8fSFrançois Tigeot 493e3adcf8fSFrançois Tigeot return 0; 494e3adcf8fSFrançois Tigeot } 495e3adcf8fSFrançois Tigeot 496e3adcf8fSFrançois Tigeot /** 497e3adcf8fSFrançois Tigeot * intel_ring_sync - sync the waiter to the signaller on seqno 498e3adcf8fSFrançois Tigeot * 499e3adcf8fSFrançois Tigeot * @waiter - ring that is waiting 500e3adcf8fSFrançois Tigeot * @signaller - ring which has, or will signal 501e3adcf8fSFrançois Tigeot * @seqno - seqno which the waiter will block on 502e3adcf8fSFrançois Tigeot */ 503e3adcf8fSFrançois Tigeot static int 504e3adcf8fSFrançois Tigeot intel_ring_sync(struct intel_ring_buffer *waiter, 505e3adcf8fSFrançois Tigeot struct intel_ring_buffer *signaller, 506e3adcf8fSFrançois Tigeot int ring, 507e3adcf8fSFrançois Tigeot u32 seqno) 508e3adcf8fSFrançois Tigeot { 509e3adcf8fSFrançois Tigeot int ret; 510e3adcf8fSFrançois Tigeot u32 dw1 = MI_SEMAPHORE_MBOX | 511e3adcf8fSFrançois Tigeot MI_SEMAPHORE_COMPARE | 512e3adcf8fSFrançois Tigeot MI_SEMAPHORE_REGISTER; 513e3adcf8fSFrançois Tigeot 514e3adcf8fSFrançois Tigeot ret = intel_ring_begin(waiter, 4); 515e3adcf8fSFrançois Tigeot if (ret) 516e3adcf8fSFrançois Tigeot return ret; 517e3adcf8fSFrançois Tigeot 518e3adcf8fSFrançois Tigeot intel_ring_emit(waiter, dw1 | signaller->semaphore_register[ring]); 519e3adcf8fSFrançois Tigeot intel_ring_emit(waiter, seqno); 520e3adcf8fSFrançois Tigeot intel_ring_emit(waiter, 0); 521e3adcf8fSFrançois Tigeot intel_ring_emit(waiter, MI_NOOP); 522e3adcf8fSFrançois Tigeot intel_ring_advance(waiter); 523e3adcf8fSFrançois Tigeot 524e3adcf8fSFrançois Tigeot return 0; 525e3adcf8fSFrançois Tigeot } 526e3adcf8fSFrançois Tigeot 527e3adcf8fSFrançois Tigeot int render_ring_sync_to(struct intel_ring_buffer *waiter, 528e3adcf8fSFrançois Tigeot struct intel_ring_buffer *signaller, u32 seqno); 529e3adcf8fSFrançois Tigeot int gen6_bsd_ring_sync_to(struct intel_ring_buffer *waiter, 530e3adcf8fSFrançois Tigeot struct intel_ring_buffer *signaller, u32 seqno); 531e3adcf8fSFrançois Tigeot int gen6_blt_ring_sync_to(struct intel_ring_buffer *waiter, 532e3adcf8fSFrançois Tigeot struct intel_ring_buffer *signaller, u32 seqno); 533e3adcf8fSFrançois Tigeot 534e3adcf8fSFrançois Tigeot /* VCS->RCS (RVSYNC) or BCS->RCS (RBSYNC) */ 535e3adcf8fSFrançois Tigeot int 536e3adcf8fSFrançois Tigeot render_ring_sync_to(struct intel_ring_buffer *waiter, 537e3adcf8fSFrançois Tigeot struct intel_ring_buffer *signaller, 538e3adcf8fSFrançois Tigeot u32 seqno) 539e3adcf8fSFrançois Tigeot { 540e3adcf8fSFrançois Tigeot KASSERT(signaller->semaphore_register[RCS] != MI_SEMAPHORE_SYNC_INVALID, 541e3adcf8fSFrançois Tigeot ("valid RCS semaphore")); 542e3adcf8fSFrançois Tigeot return intel_ring_sync(waiter, 543e3adcf8fSFrançois Tigeot signaller, 544e3adcf8fSFrançois Tigeot RCS, 545e3adcf8fSFrançois Tigeot seqno); 546e3adcf8fSFrançois Tigeot } 547e3adcf8fSFrançois Tigeot 548e3adcf8fSFrançois Tigeot /* RCS->VCS (VRSYNC) or BCS->VCS (VBSYNC) */ 549e3adcf8fSFrançois Tigeot int 550e3adcf8fSFrançois Tigeot gen6_bsd_ring_sync_to(struct intel_ring_buffer *waiter, 551e3adcf8fSFrançois Tigeot struct intel_ring_buffer *signaller, 552e3adcf8fSFrançois Tigeot u32 seqno) 553e3adcf8fSFrançois Tigeot { 554e3adcf8fSFrançois Tigeot KASSERT(signaller->semaphore_register[VCS] != MI_SEMAPHORE_SYNC_INVALID, 555e3adcf8fSFrançois Tigeot ("Valid VCS semaphore")); 556e3adcf8fSFrançois Tigeot return intel_ring_sync(waiter, 557e3adcf8fSFrançois Tigeot signaller, 558e3adcf8fSFrançois Tigeot VCS, 559e3adcf8fSFrançois Tigeot seqno); 560e3adcf8fSFrançois Tigeot } 561e3adcf8fSFrançois Tigeot 562e3adcf8fSFrançois Tigeot /* RCS->BCS (BRSYNC) or VCS->BCS (BVSYNC) */ 563e3adcf8fSFrançois Tigeot int 564e3adcf8fSFrançois Tigeot gen6_blt_ring_sync_to(struct intel_ring_buffer *waiter, 565e3adcf8fSFrançois Tigeot struct intel_ring_buffer *signaller, 566e3adcf8fSFrançois Tigeot u32 seqno) 567e3adcf8fSFrançois Tigeot { 568e3adcf8fSFrançois Tigeot KASSERT(signaller->semaphore_register[BCS] != MI_SEMAPHORE_SYNC_INVALID, 569e3adcf8fSFrançois Tigeot ("Valid BCS semaphore")); 570e3adcf8fSFrançois Tigeot return intel_ring_sync(waiter, 571e3adcf8fSFrançois Tigeot signaller, 572e3adcf8fSFrançois Tigeot BCS, 573e3adcf8fSFrançois Tigeot seqno); 574e3adcf8fSFrançois Tigeot } 575e3adcf8fSFrançois Tigeot 576e3adcf8fSFrançois Tigeot #define PIPE_CONTROL_FLUSH(ring__, addr__) \ 577e3adcf8fSFrançois Tigeot do { \ 578e3adcf8fSFrançois Tigeot intel_ring_emit(ring__, GFX_OP_PIPE_CONTROL(4) | PIPE_CONTROL_QW_WRITE | \ 579e3adcf8fSFrançois Tigeot PIPE_CONTROL_DEPTH_STALL); \ 580e3adcf8fSFrançois Tigeot intel_ring_emit(ring__, (addr__) | PIPE_CONTROL_GLOBAL_GTT); \ 581e3adcf8fSFrançois Tigeot intel_ring_emit(ring__, 0); \ 582e3adcf8fSFrançois Tigeot intel_ring_emit(ring__, 0); \ 583e3adcf8fSFrançois Tigeot } while (0) 584e3adcf8fSFrançois Tigeot 585e3adcf8fSFrançois Tigeot static int 586e3adcf8fSFrançois Tigeot pc_render_add_request(struct intel_ring_buffer *ring, 587e3adcf8fSFrançois Tigeot uint32_t *result) 588e3adcf8fSFrançois Tigeot { 589e3adcf8fSFrançois Tigeot u32 seqno = i915_gem_next_request_seqno(ring); 590e3adcf8fSFrançois Tigeot struct pipe_control *pc = ring->private; 591e3adcf8fSFrançois Tigeot u32 scratch_addr = pc->gtt_offset + 128; 592e3adcf8fSFrançois Tigeot int ret; 593e3adcf8fSFrançois Tigeot 594e3adcf8fSFrançois Tigeot /* For Ironlake, MI_USER_INTERRUPT was deprecated and apparently 595e3adcf8fSFrançois Tigeot * incoherent with writes to memory, i.e. completely fubar, 596e3adcf8fSFrançois Tigeot * so we need to use PIPE_NOTIFY instead. 597e3adcf8fSFrançois Tigeot * 598e3adcf8fSFrançois Tigeot * However, we also need to workaround the qword write 599e3adcf8fSFrançois Tigeot * incoherence by flushing the 6 PIPE_NOTIFY buffers out to 600e3adcf8fSFrançois Tigeot * memory before requesting an interrupt. 601e3adcf8fSFrançois Tigeot */ 602e3adcf8fSFrançois Tigeot ret = intel_ring_begin(ring, 32); 603e3adcf8fSFrançois Tigeot if (ret) 604e3adcf8fSFrançois Tigeot return ret; 605e3adcf8fSFrançois Tigeot 606e3adcf8fSFrançois Tigeot intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(4) | PIPE_CONTROL_QW_WRITE | 607e3adcf8fSFrançois Tigeot PIPE_CONTROL_WRITE_FLUSH | 608e3adcf8fSFrançois Tigeot PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE); 609e3adcf8fSFrançois Tigeot intel_ring_emit(ring, pc->gtt_offset | PIPE_CONTROL_GLOBAL_GTT); 610e3adcf8fSFrançois Tigeot intel_ring_emit(ring, seqno); 611e3adcf8fSFrançois Tigeot intel_ring_emit(ring, 0); 612e3adcf8fSFrançois Tigeot PIPE_CONTROL_FLUSH(ring, scratch_addr); 613e3adcf8fSFrançois Tigeot scratch_addr += 128; /* write to separate cachelines */ 614e3adcf8fSFrançois Tigeot PIPE_CONTROL_FLUSH(ring, scratch_addr); 615e3adcf8fSFrançois Tigeot scratch_addr += 128; 616e3adcf8fSFrançois Tigeot PIPE_CONTROL_FLUSH(ring, scratch_addr); 617e3adcf8fSFrançois Tigeot scratch_addr += 128; 618e3adcf8fSFrançois Tigeot PIPE_CONTROL_FLUSH(ring, scratch_addr); 619e3adcf8fSFrançois Tigeot scratch_addr += 128; 620e3adcf8fSFrançois Tigeot PIPE_CONTROL_FLUSH(ring, scratch_addr); 621e3adcf8fSFrançois Tigeot scratch_addr += 128; 622e3adcf8fSFrançois Tigeot PIPE_CONTROL_FLUSH(ring, scratch_addr); 623e3adcf8fSFrançois Tigeot intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(4) | PIPE_CONTROL_QW_WRITE | 624e3adcf8fSFrançois Tigeot PIPE_CONTROL_WRITE_FLUSH | 625e3adcf8fSFrançois Tigeot PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE | 626e3adcf8fSFrançois Tigeot PIPE_CONTROL_NOTIFY); 627e3adcf8fSFrançois Tigeot intel_ring_emit(ring, pc->gtt_offset | PIPE_CONTROL_GLOBAL_GTT); 628e3adcf8fSFrançois Tigeot intel_ring_emit(ring, seqno); 629e3adcf8fSFrançois Tigeot intel_ring_emit(ring, 0); 630e3adcf8fSFrançois Tigeot intel_ring_advance(ring); 631e3adcf8fSFrançois Tigeot 632e3adcf8fSFrançois Tigeot *result = seqno; 633e3adcf8fSFrançois Tigeot return 0; 634e3adcf8fSFrançois Tigeot } 635e3adcf8fSFrançois Tigeot 636e3adcf8fSFrançois Tigeot static int 637e3adcf8fSFrançois Tigeot render_ring_add_request(struct intel_ring_buffer *ring, 638e3adcf8fSFrançois Tigeot uint32_t *result) 639e3adcf8fSFrançois Tigeot { 640e3adcf8fSFrançois Tigeot u32 seqno = i915_gem_next_request_seqno(ring); 641e3adcf8fSFrançois Tigeot int ret; 642e3adcf8fSFrançois Tigeot 643e3adcf8fSFrançois Tigeot ret = intel_ring_begin(ring, 4); 644e3adcf8fSFrançois Tigeot if (ret) 645e3adcf8fSFrançois Tigeot return ret; 646e3adcf8fSFrançois Tigeot 647e3adcf8fSFrançois Tigeot intel_ring_emit(ring, MI_STORE_DWORD_INDEX); 648e3adcf8fSFrançois Tigeot intel_ring_emit(ring, I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT); 649e3adcf8fSFrançois Tigeot intel_ring_emit(ring, seqno); 650e3adcf8fSFrançois Tigeot intel_ring_emit(ring, MI_USER_INTERRUPT); 651e3adcf8fSFrançois Tigeot intel_ring_advance(ring); 652e3adcf8fSFrançois Tigeot 653e3adcf8fSFrançois Tigeot *result = seqno; 654e3adcf8fSFrançois Tigeot return 0; 655e3adcf8fSFrançois Tigeot } 656e3adcf8fSFrançois Tigeot 657e3adcf8fSFrançois Tigeot static u32 658b030f26bSFrançois Tigeot gen6_ring_get_seqno(struct intel_ring_buffer *ring, bool lazy_coherency) 659e3adcf8fSFrançois Tigeot { 660e3adcf8fSFrançois Tigeot /* Workaround to force correct ordering between irq and seqno writes on 661e3adcf8fSFrançois Tigeot * ivb (and maybe also on snb) by reading from a CS register (like 662e3adcf8fSFrançois Tigeot * ACTHD) before reading the status page. */ 663b030f26bSFrançois Tigeot if (!lazy_coherency) 664e3adcf8fSFrançois Tigeot intel_ring_get_active_head(ring); 665e3adcf8fSFrançois Tigeot return intel_read_status_page(ring, I915_GEM_HWS_INDEX); 666e3adcf8fSFrançois Tigeot } 667e3adcf8fSFrançois Tigeot 668b030f26bSFrançois Tigeot static u32 669b030f26bSFrançois Tigeot ring_get_seqno(struct intel_ring_buffer *ring, bool lazy_coherency) 670e3adcf8fSFrançois Tigeot { 671e3adcf8fSFrançois Tigeot return intel_read_status_page(ring, I915_GEM_HWS_INDEX); 672e3adcf8fSFrançois Tigeot } 673e3adcf8fSFrançois Tigeot 674b030f26bSFrançois Tigeot static u32 675b030f26bSFrançois Tigeot pc_render_get_seqno(struct intel_ring_buffer *ring, bool lazy_coherency) 676e3adcf8fSFrançois Tigeot { 677e3adcf8fSFrançois Tigeot struct pipe_control *pc = ring->private; 678e3adcf8fSFrançois Tigeot return pc->cpu_page[0]; 679e3adcf8fSFrançois Tigeot } 680e3adcf8fSFrançois Tigeot 681e3adcf8fSFrançois Tigeot static void 682e3adcf8fSFrançois Tigeot ironlake_enable_irq(drm_i915_private_t *dev_priv, uint32_t mask) 683e3adcf8fSFrançois Tigeot { 684e3adcf8fSFrançois Tigeot dev_priv->gt_irq_mask &= ~mask; 685e3adcf8fSFrançois Tigeot I915_WRITE(GTIMR, dev_priv->gt_irq_mask); 686e3adcf8fSFrançois Tigeot POSTING_READ(GTIMR); 687e3adcf8fSFrançois Tigeot } 688e3adcf8fSFrançois Tigeot 689e3adcf8fSFrançois Tigeot static void 690e3adcf8fSFrançois Tigeot ironlake_disable_irq(drm_i915_private_t *dev_priv, uint32_t mask) 691e3adcf8fSFrançois Tigeot { 692e3adcf8fSFrançois Tigeot dev_priv->gt_irq_mask |= mask; 693e3adcf8fSFrançois Tigeot I915_WRITE(GTIMR, dev_priv->gt_irq_mask); 694e3adcf8fSFrançois Tigeot POSTING_READ(GTIMR); 695e3adcf8fSFrançois Tigeot } 696e3adcf8fSFrançois Tigeot 697e3adcf8fSFrançois Tigeot static void 698e3adcf8fSFrançois Tigeot i915_enable_irq(drm_i915_private_t *dev_priv, uint32_t mask) 699e3adcf8fSFrançois Tigeot { 700e3adcf8fSFrançois Tigeot dev_priv->irq_mask &= ~mask; 701e3adcf8fSFrançois Tigeot I915_WRITE(IMR, dev_priv->irq_mask); 702e3adcf8fSFrançois Tigeot POSTING_READ(IMR); 703e3adcf8fSFrançois Tigeot } 704e3adcf8fSFrançois Tigeot 705e3adcf8fSFrançois Tigeot static void 706e3adcf8fSFrançois Tigeot i915_disable_irq(drm_i915_private_t *dev_priv, uint32_t mask) 707e3adcf8fSFrançois Tigeot { 708e3adcf8fSFrançois Tigeot dev_priv->irq_mask |= mask; 709e3adcf8fSFrançois Tigeot I915_WRITE(IMR, dev_priv->irq_mask); 710e3adcf8fSFrançois Tigeot POSTING_READ(IMR); 711e3adcf8fSFrançois Tigeot } 712e3adcf8fSFrançois Tigeot 713e3adcf8fSFrançois Tigeot static bool 714e3adcf8fSFrançois Tigeot render_ring_get_irq(struct intel_ring_buffer *ring) 715e3adcf8fSFrançois Tigeot { 716e3adcf8fSFrançois Tigeot struct drm_device *dev = ring->dev; 717e3adcf8fSFrançois Tigeot drm_i915_private_t *dev_priv = dev->dev_private; 718e3adcf8fSFrançois Tigeot 719e3adcf8fSFrançois Tigeot if (!dev->irq_enabled) 720e3adcf8fSFrançois Tigeot return false; 721e3adcf8fSFrançois Tigeot 722*02727ecdSFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_EXCLUSIVE); 723e3adcf8fSFrançois Tigeot if (ring->irq_refcount++ == 0) { 724e3adcf8fSFrançois Tigeot if (HAS_PCH_SPLIT(dev)) 725e3adcf8fSFrançois Tigeot ironlake_enable_irq(dev_priv, 726e3adcf8fSFrançois Tigeot GT_PIPE_NOTIFY | GT_USER_INTERRUPT); 727e3adcf8fSFrançois Tigeot else 728e3adcf8fSFrançois Tigeot i915_enable_irq(dev_priv, I915_USER_INTERRUPT); 729e3adcf8fSFrançois Tigeot } 730*02727ecdSFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_RELEASE); 731e3adcf8fSFrançois Tigeot 732e3adcf8fSFrançois Tigeot return true; 733e3adcf8fSFrançois Tigeot } 734e3adcf8fSFrançois Tigeot 735e3adcf8fSFrançois Tigeot static void 736e3adcf8fSFrançois Tigeot render_ring_put_irq(struct intel_ring_buffer *ring) 737e3adcf8fSFrançois Tigeot { 738e3adcf8fSFrançois Tigeot struct drm_device *dev = ring->dev; 739e3adcf8fSFrançois Tigeot drm_i915_private_t *dev_priv = dev->dev_private; 740e3adcf8fSFrançois Tigeot 741*02727ecdSFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_EXCLUSIVE); 742e3adcf8fSFrançois Tigeot if (--ring->irq_refcount == 0) { 743e3adcf8fSFrançois Tigeot if (HAS_PCH_SPLIT(dev)) 744e3adcf8fSFrançois Tigeot ironlake_disable_irq(dev_priv, 745e3adcf8fSFrançois Tigeot GT_USER_INTERRUPT | 746e3adcf8fSFrançois Tigeot GT_PIPE_NOTIFY); 747e3adcf8fSFrançois Tigeot else 748e3adcf8fSFrançois Tigeot i915_disable_irq(dev_priv, I915_USER_INTERRUPT); 749e3adcf8fSFrançois Tigeot } 750*02727ecdSFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_RELEASE); 751e3adcf8fSFrançois Tigeot } 752e3adcf8fSFrançois Tigeot 753e3adcf8fSFrançois Tigeot void intel_ring_setup_status_page(struct intel_ring_buffer *ring) 754e3adcf8fSFrançois Tigeot { 755e3adcf8fSFrançois Tigeot struct drm_device *dev = ring->dev; 756e3adcf8fSFrançois Tigeot drm_i915_private_t *dev_priv = dev->dev_private; 757e3adcf8fSFrançois Tigeot uint32_t mmio = 0; 758e3adcf8fSFrançois Tigeot 759e3adcf8fSFrançois Tigeot /* The ring status page addresses are no longer next to the rest of 760e3adcf8fSFrançois Tigeot * the ring registers as of gen7. 761e3adcf8fSFrançois Tigeot */ 762e3adcf8fSFrançois Tigeot if (IS_GEN7(dev)) { 763e3adcf8fSFrançois Tigeot switch (ring->id) { 764e3adcf8fSFrançois Tigeot case RCS: 765e3adcf8fSFrançois Tigeot mmio = RENDER_HWS_PGA_GEN7; 766e3adcf8fSFrançois Tigeot break; 767e3adcf8fSFrançois Tigeot case BCS: 768e3adcf8fSFrançois Tigeot mmio = BLT_HWS_PGA_GEN7; 769e3adcf8fSFrançois Tigeot break; 770e3adcf8fSFrançois Tigeot case VCS: 771e3adcf8fSFrançois Tigeot mmio = BSD_HWS_PGA_GEN7; 772e3adcf8fSFrançois Tigeot break; 773e3adcf8fSFrançois Tigeot } 774e3adcf8fSFrançois Tigeot } else if (IS_GEN6(dev)) { 775e3adcf8fSFrançois Tigeot mmio = RING_HWS_PGA_GEN6(ring->mmio_base); 776e3adcf8fSFrançois Tigeot } else { 777e3adcf8fSFrançois Tigeot mmio = RING_HWS_PGA(ring->mmio_base); 778e3adcf8fSFrançois Tigeot } 779e3adcf8fSFrançois Tigeot 780e3adcf8fSFrançois Tigeot I915_WRITE(mmio, (u32)ring->status_page.gfx_addr); 781e3adcf8fSFrançois Tigeot POSTING_READ(mmio); 782e3adcf8fSFrançois Tigeot } 783e3adcf8fSFrançois Tigeot 784e3adcf8fSFrançois Tigeot static int 785e3adcf8fSFrançois Tigeot bsd_ring_flush(struct intel_ring_buffer *ring, 786e3adcf8fSFrançois Tigeot uint32_t invalidate_domains, 787e3adcf8fSFrançois Tigeot uint32_t flush_domains) 788e3adcf8fSFrançois Tigeot { 789e3adcf8fSFrançois Tigeot int ret; 790e3adcf8fSFrançois Tigeot 791e3adcf8fSFrançois Tigeot ret = intel_ring_begin(ring, 2); 792e3adcf8fSFrançois Tigeot if (ret) 793e3adcf8fSFrançois Tigeot return ret; 794e3adcf8fSFrançois Tigeot 795e3adcf8fSFrançois Tigeot intel_ring_emit(ring, MI_FLUSH); 796e3adcf8fSFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 797e3adcf8fSFrançois Tigeot intel_ring_advance(ring); 798e3adcf8fSFrançois Tigeot return 0; 799e3adcf8fSFrançois Tigeot } 800e3adcf8fSFrançois Tigeot 801e3adcf8fSFrançois Tigeot static int 802e3adcf8fSFrançois Tigeot ring_add_request(struct intel_ring_buffer *ring, 803e3adcf8fSFrançois Tigeot uint32_t *result) 804e3adcf8fSFrançois Tigeot { 805e3adcf8fSFrançois Tigeot uint32_t seqno; 806e3adcf8fSFrançois Tigeot int ret; 807e3adcf8fSFrançois Tigeot 808e3adcf8fSFrançois Tigeot ret = intel_ring_begin(ring, 4); 809e3adcf8fSFrançois Tigeot if (ret) 810e3adcf8fSFrançois Tigeot return ret; 811e3adcf8fSFrançois Tigeot 812e3adcf8fSFrançois Tigeot seqno = i915_gem_next_request_seqno(ring); 813e3adcf8fSFrançois Tigeot 814e3adcf8fSFrançois Tigeot intel_ring_emit(ring, MI_STORE_DWORD_INDEX); 815e3adcf8fSFrançois Tigeot intel_ring_emit(ring, I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT); 816e3adcf8fSFrançois Tigeot intel_ring_emit(ring, seqno); 817e3adcf8fSFrançois Tigeot intel_ring_emit(ring, MI_USER_INTERRUPT); 818e3adcf8fSFrançois Tigeot intel_ring_advance(ring); 819e3adcf8fSFrançois Tigeot 820e3adcf8fSFrançois Tigeot *result = seqno; 821e3adcf8fSFrançois Tigeot return 0; 822e3adcf8fSFrançois Tigeot } 823e3adcf8fSFrançois Tigeot 824e3adcf8fSFrançois Tigeot static bool 825e3adcf8fSFrançois Tigeot gen6_ring_get_irq(struct intel_ring_buffer *ring, uint32_t gflag, uint32_t rflag) 826e3adcf8fSFrançois Tigeot { 827e3adcf8fSFrançois Tigeot struct drm_device *dev = ring->dev; 828e3adcf8fSFrançois Tigeot drm_i915_private_t *dev_priv = dev->dev_private; 829e3adcf8fSFrançois Tigeot 830e3adcf8fSFrançois Tigeot if (!dev->irq_enabled) 831e3adcf8fSFrançois Tigeot return false; 832e3adcf8fSFrançois Tigeot 833e3adcf8fSFrançois Tigeot gen6_gt_force_wake_get(dev_priv); 834e3adcf8fSFrançois Tigeot 835*02727ecdSFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_EXCLUSIVE); 836e3adcf8fSFrançois Tigeot if (ring->irq_refcount++ == 0) { 837e3adcf8fSFrançois Tigeot ring->irq_mask &= ~rflag; 838e3adcf8fSFrançois Tigeot I915_WRITE_IMR(ring, ring->irq_mask); 839e3adcf8fSFrançois Tigeot ironlake_enable_irq(dev_priv, gflag); 840e3adcf8fSFrançois Tigeot } 841*02727ecdSFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_RELEASE); 842e3adcf8fSFrançois Tigeot 843e3adcf8fSFrançois Tigeot return true; 844e3adcf8fSFrançois Tigeot } 845e3adcf8fSFrançois Tigeot 846e3adcf8fSFrançois Tigeot static void 847e3adcf8fSFrançois Tigeot gen6_ring_put_irq(struct intel_ring_buffer *ring, uint32_t gflag, uint32_t rflag) 848e3adcf8fSFrançois Tigeot { 849e3adcf8fSFrançois Tigeot struct drm_device *dev = ring->dev; 850e3adcf8fSFrançois Tigeot drm_i915_private_t *dev_priv = dev->dev_private; 851e3adcf8fSFrançois Tigeot 852*02727ecdSFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_EXCLUSIVE); 853e3adcf8fSFrançois Tigeot if (--ring->irq_refcount == 0) { 854e3adcf8fSFrançois Tigeot ring->irq_mask |= rflag; 855e3adcf8fSFrançois Tigeot I915_WRITE_IMR(ring, ring->irq_mask); 856e3adcf8fSFrançois Tigeot ironlake_disable_irq(dev_priv, gflag); 857e3adcf8fSFrançois Tigeot } 858*02727ecdSFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_RELEASE); 859e3adcf8fSFrançois Tigeot 860e3adcf8fSFrançois Tigeot gen6_gt_force_wake_put(dev_priv); 861e3adcf8fSFrançois Tigeot } 862e3adcf8fSFrançois Tigeot 863e3adcf8fSFrançois Tigeot static bool 864e3adcf8fSFrançois Tigeot bsd_ring_get_irq(struct intel_ring_buffer *ring) 865e3adcf8fSFrançois Tigeot { 866e3adcf8fSFrançois Tigeot struct drm_device *dev = ring->dev; 867e3adcf8fSFrançois Tigeot drm_i915_private_t *dev_priv = dev->dev_private; 868e3adcf8fSFrançois Tigeot 869e3adcf8fSFrançois Tigeot if (!dev->irq_enabled) 870e3adcf8fSFrançois Tigeot return false; 871e3adcf8fSFrançois Tigeot 872*02727ecdSFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_EXCLUSIVE); 873e3adcf8fSFrançois Tigeot if (ring->irq_refcount++ == 0) { 874e3adcf8fSFrançois Tigeot if (IS_G4X(dev)) 875e3adcf8fSFrançois Tigeot i915_enable_irq(dev_priv, I915_BSD_USER_INTERRUPT); 876e3adcf8fSFrançois Tigeot else 877e3adcf8fSFrançois Tigeot ironlake_enable_irq(dev_priv, GT_BSD_USER_INTERRUPT); 878e3adcf8fSFrançois Tigeot } 879*02727ecdSFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_RELEASE); 880e3adcf8fSFrançois Tigeot 881e3adcf8fSFrançois Tigeot return true; 882e3adcf8fSFrançois Tigeot } 883e3adcf8fSFrançois Tigeot static void 884e3adcf8fSFrançois Tigeot bsd_ring_put_irq(struct intel_ring_buffer *ring) 885e3adcf8fSFrançois Tigeot { 886e3adcf8fSFrançois Tigeot struct drm_device *dev = ring->dev; 887e3adcf8fSFrançois Tigeot drm_i915_private_t *dev_priv = dev->dev_private; 888e3adcf8fSFrançois Tigeot 889*02727ecdSFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_EXCLUSIVE); 890e3adcf8fSFrançois Tigeot if (--ring->irq_refcount == 0) { 891e3adcf8fSFrançois Tigeot if (IS_G4X(dev)) 892e3adcf8fSFrançois Tigeot i915_disable_irq(dev_priv, I915_BSD_USER_INTERRUPT); 893e3adcf8fSFrançois Tigeot else 894e3adcf8fSFrançois Tigeot ironlake_disable_irq(dev_priv, GT_BSD_USER_INTERRUPT); 895e3adcf8fSFrançois Tigeot } 896*02727ecdSFrançois Tigeot lockmgr(&dev_priv->irq_lock, LK_RELEASE); 897e3adcf8fSFrançois Tigeot } 898e3adcf8fSFrançois Tigeot 899e3adcf8fSFrançois Tigeot static int 900e3adcf8fSFrançois Tigeot ring_dispatch_execbuffer(struct intel_ring_buffer *ring, uint32_t offset, 901e3adcf8fSFrançois Tigeot uint32_t length) 902e3adcf8fSFrançois Tigeot { 903e3adcf8fSFrançois Tigeot int ret; 904e3adcf8fSFrançois Tigeot 905e3adcf8fSFrançois Tigeot ret = intel_ring_begin(ring, 2); 906e3adcf8fSFrançois Tigeot if (ret) 907e3adcf8fSFrançois Tigeot return ret; 908e3adcf8fSFrançois Tigeot 909e3adcf8fSFrançois Tigeot intel_ring_emit(ring, 910e3adcf8fSFrançois Tigeot MI_BATCH_BUFFER_START | (2 << 6) | 911e3adcf8fSFrançois Tigeot MI_BATCH_NON_SECURE_I965); 912e3adcf8fSFrançois Tigeot intel_ring_emit(ring, offset); 913e3adcf8fSFrançois Tigeot intel_ring_advance(ring); 914e3adcf8fSFrançois Tigeot 915e3adcf8fSFrançois Tigeot return 0; 916e3adcf8fSFrançois Tigeot } 917e3adcf8fSFrançois Tigeot 918e3adcf8fSFrançois Tigeot static int 919e3adcf8fSFrançois Tigeot render_ring_dispatch_execbuffer(struct intel_ring_buffer *ring, 920e3adcf8fSFrançois Tigeot uint32_t offset, uint32_t len) 921e3adcf8fSFrançois Tigeot { 922e3adcf8fSFrançois Tigeot struct drm_device *dev = ring->dev; 923e3adcf8fSFrançois Tigeot int ret; 924e3adcf8fSFrançois Tigeot 925e3adcf8fSFrançois Tigeot if (IS_I830(dev) || IS_845G(dev)) { 926e3adcf8fSFrançois Tigeot ret = intel_ring_begin(ring, 4); 927e3adcf8fSFrançois Tigeot if (ret) 928e3adcf8fSFrançois Tigeot return ret; 929e3adcf8fSFrançois Tigeot 930e3adcf8fSFrançois Tigeot intel_ring_emit(ring, MI_BATCH_BUFFER); 931e3adcf8fSFrançois Tigeot intel_ring_emit(ring, offset | MI_BATCH_NON_SECURE); 932e3adcf8fSFrançois Tigeot intel_ring_emit(ring, offset + len - 8); 933e3adcf8fSFrançois Tigeot intel_ring_emit(ring, 0); 934e3adcf8fSFrançois Tigeot } else { 935e3adcf8fSFrançois Tigeot ret = intel_ring_begin(ring, 2); 936e3adcf8fSFrançois Tigeot if (ret) 937e3adcf8fSFrançois Tigeot return ret; 938e3adcf8fSFrançois Tigeot 939e3adcf8fSFrançois Tigeot if (INTEL_INFO(dev)->gen >= 4) { 940e3adcf8fSFrançois Tigeot intel_ring_emit(ring, 941e3adcf8fSFrançois Tigeot MI_BATCH_BUFFER_START | (2 << 6) | 942e3adcf8fSFrançois Tigeot MI_BATCH_NON_SECURE_I965); 943e3adcf8fSFrançois Tigeot intel_ring_emit(ring, offset); 944e3adcf8fSFrançois Tigeot } else { 945e3adcf8fSFrançois Tigeot intel_ring_emit(ring, 946e3adcf8fSFrançois Tigeot MI_BATCH_BUFFER_START | (2 << 6)); 947e3adcf8fSFrançois Tigeot intel_ring_emit(ring, offset | MI_BATCH_NON_SECURE); 948e3adcf8fSFrançois Tigeot } 949e3adcf8fSFrançois Tigeot } 950e3adcf8fSFrançois Tigeot intel_ring_advance(ring); 951e3adcf8fSFrançois Tigeot 952e3adcf8fSFrançois Tigeot return 0; 953e3adcf8fSFrançois Tigeot } 954e3adcf8fSFrançois Tigeot 955e3adcf8fSFrançois Tigeot static void cleanup_status_page(struct intel_ring_buffer *ring) 956e3adcf8fSFrançois Tigeot { 957e3adcf8fSFrançois Tigeot drm_i915_private_t *dev_priv = ring->dev->dev_private; 958e3adcf8fSFrançois Tigeot struct drm_i915_gem_object *obj; 959e3adcf8fSFrançois Tigeot 960e3adcf8fSFrançois Tigeot obj = ring->status_page.obj; 961e3adcf8fSFrançois Tigeot if (obj == NULL) 962e3adcf8fSFrançois Tigeot return; 963e3adcf8fSFrançois Tigeot 964e3adcf8fSFrançois Tigeot pmap_qremove((vm_offset_t)ring->status_page.page_addr, 1); 965e3adcf8fSFrançois Tigeot kmem_free(&kernel_map, (vm_offset_t)ring->status_page.page_addr, 966e3adcf8fSFrançois Tigeot PAGE_SIZE); 967e3adcf8fSFrançois Tigeot i915_gem_object_unpin(obj); 968e3adcf8fSFrançois Tigeot drm_gem_object_unreference(&obj->base); 969e3adcf8fSFrançois Tigeot ring->status_page.obj = NULL; 970e3adcf8fSFrançois Tigeot 971e3adcf8fSFrançois Tigeot memset(&dev_priv->hws_map, 0, sizeof(dev_priv->hws_map)); 972e3adcf8fSFrançois Tigeot } 973e3adcf8fSFrançois Tigeot 974e3adcf8fSFrançois Tigeot static int init_status_page(struct intel_ring_buffer *ring) 975e3adcf8fSFrançois Tigeot { 976e3adcf8fSFrançois Tigeot struct drm_device *dev = ring->dev; 977e3adcf8fSFrançois Tigeot drm_i915_private_t *dev_priv = dev->dev_private; 978e3adcf8fSFrançois Tigeot struct drm_i915_gem_object *obj; 979e3adcf8fSFrançois Tigeot int ret; 980e3adcf8fSFrançois Tigeot 981e3adcf8fSFrançois Tigeot obj = i915_gem_alloc_object(dev, 4096); 982e3adcf8fSFrançois Tigeot if (obj == NULL) { 983e3adcf8fSFrançois Tigeot DRM_ERROR("Failed to allocate status page\n"); 984e3adcf8fSFrançois Tigeot ret = -ENOMEM; 985e3adcf8fSFrançois Tigeot goto err; 986e3adcf8fSFrançois Tigeot } 987e3adcf8fSFrançois Tigeot 988e3adcf8fSFrançois Tigeot i915_gem_object_set_cache_level(obj, I915_CACHE_LLC); 989e3adcf8fSFrançois Tigeot 990e3adcf8fSFrançois Tigeot ret = i915_gem_object_pin(obj, 4096, true); 991e3adcf8fSFrançois Tigeot if (ret != 0) { 992e3adcf8fSFrançois Tigeot goto err_unref; 993e3adcf8fSFrançois Tigeot } 994e3adcf8fSFrançois Tigeot 995e3adcf8fSFrançois Tigeot ring->status_page.gfx_addr = obj->gtt_offset; 996e3adcf8fSFrançois Tigeot ring->status_page.page_addr = (void *)kmem_alloc_nofault(&kernel_map, 997e3adcf8fSFrançois Tigeot PAGE_SIZE, PAGE_SIZE); 998e3adcf8fSFrançois Tigeot if (ring->status_page.page_addr == NULL) { 999e3adcf8fSFrançois Tigeot memset(&dev_priv->hws_map, 0, sizeof(dev_priv->hws_map)); 1000e3adcf8fSFrançois Tigeot goto err_unpin; 1001e3adcf8fSFrançois Tigeot } 1002e3adcf8fSFrançois Tigeot pmap_qenter((vm_offset_t)ring->status_page.page_addr, &obj->pages[0], 1003e3adcf8fSFrançois Tigeot 1); 1004e3adcf8fSFrançois Tigeot pmap_invalidate_cache_range((vm_offset_t)ring->status_page.page_addr, 1005e3adcf8fSFrançois Tigeot (vm_offset_t)ring->status_page.page_addr + PAGE_SIZE); 1006e3adcf8fSFrançois Tigeot ring->status_page.obj = obj; 1007e3adcf8fSFrançois Tigeot memset(ring->status_page.page_addr, 0, PAGE_SIZE); 1008e3adcf8fSFrançois Tigeot 1009e3adcf8fSFrançois Tigeot intel_ring_setup_status_page(ring); 1010e3adcf8fSFrançois Tigeot DRM_DEBUG("i915: init_status_page %s hws offset: 0x%08x\n", 1011e3adcf8fSFrançois Tigeot ring->name, ring->status_page.gfx_addr); 1012e3adcf8fSFrançois Tigeot 1013e3adcf8fSFrançois Tigeot return 0; 1014e3adcf8fSFrançois Tigeot 1015e3adcf8fSFrançois Tigeot err_unpin: 1016e3adcf8fSFrançois Tigeot i915_gem_object_unpin(obj); 1017e3adcf8fSFrançois Tigeot err_unref: 1018e3adcf8fSFrançois Tigeot drm_gem_object_unreference(&obj->base); 1019e3adcf8fSFrançois Tigeot err: 1020e3adcf8fSFrançois Tigeot return ret; 1021e3adcf8fSFrançois Tigeot } 1022e3adcf8fSFrançois Tigeot 1023b030f26bSFrançois Tigeot static int intel_init_ring_buffer(struct drm_device *dev, 1024e3adcf8fSFrançois Tigeot struct intel_ring_buffer *ring) 1025e3adcf8fSFrançois Tigeot { 1026e3adcf8fSFrançois Tigeot struct drm_i915_gem_object *obj; 1027e3adcf8fSFrançois Tigeot int ret; 1028e3adcf8fSFrançois Tigeot 1029e3adcf8fSFrançois Tigeot ring->dev = dev; 1030e3adcf8fSFrançois Tigeot INIT_LIST_HEAD(&ring->active_list); 1031e3adcf8fSFrançois Tigeot INIT_LIST_HEAD(&ring->request_list); 1032e3adcf8fSFrançois Tigeot INIT_LIST_HEAD(&ring->gpu_write_list); 1033e3adcf8fSFrançois Tigeot 1034e3adcf8fSFrançois Tigeot lockinit(&ring->irq_lock, "ringb", 0, LK_CANRECURSE); 1035e3adcf8fSFrançois Tigeot ring->irq_mask = ~0; 1036e3adcf8fSFrançois Tigeot 1037b030f26bSFrançois Tigeot init_waitqueue_head(&ring->irq_queue); 1038b030f26bSFrançois Tigeot 1039e3adcf8fSFrançois Tigeot if (I915_NEED_GFX_HWS(dev)) { 1040e3adcf8fSFrançois Tigeot ret = init_status_page(ring); 1041e3adcf8fSFrançois Tigeot if (ret) 1042e3adcf8fSFrançois Tigeot return ret; 1043e3adcf8fSFrançois Tigeot } 1044e3adcf8fSFrançois Tigeot 1045e3adcf8fSFrançois Tigeot obj = i915_gem_alloc_object(dev, ring->size); 1046e3adcf8fSFrançois Tigeot if (obj == NULL) { 1047e3adcf8fSFrançois Tigeot DRM_ERROR("Failed to allocate ringbuffer\n"); 1048e3adcf8fSFrançois Tigeot ret = -ENOMEM; 1049e3adcf8fSFrançois Tigeot goto err_hws; 1050e3adcf8fSFrançois Tigeot } 1051e3adcf8fSFrançois Tigeot 1052e3adcf8fSFrançois Tigeot ring->obj = obj; 1053e3adcf8fSFrançois Tigeot 1054e3adcf8fSFrançois Tigeot ret = i915_gem_object_pin(obj, PAGE_SIZE, true); 1055e3adcf8fSFrançois Tigeot if (ret) 1056e3adcf8fSFrançois Tigeot goto err_unref; 1057e3adcf8fSFrançois Tigeot 1058e3adcf8fSFrançois Tigeot ring->map.size = ring->size; 1059e3adcf8fSFrançois Tigeot ring->map.offset = dev->agp->base + obj->gtt_offset; 1060e3adcf8fSFrançois Tigeot ring->map.type = 0; 1061e3adcf8fSFrançois Tigeot ring->map.flags = 0; 1062e3adcf8fSFrançois Tigeot ring->map.mtrr = 0; 1063e3adcf8fSFrançois Tigeot 1064e3adcf8fSFrançois Tigeot drm_core_ioremap_wc(&ring->map, dev); 1065e3adcf8fSFrançois Tigeot if (ring->map.virtual == NULL) { 1066e3adcf8fSFrançois Tigeot DRM_ERROR("Failed to map ringbuffer.\n"); 1067e3adcf8fSFrançois Tigeot ret = -EINVAL; 1068e3adcf8fSFrançois Tigeot goto err_unpin; 1069e3adcf8fSFrançois Tigeot } 1070e3adcf8fSFrançois Tigeot 1071e3adcf8fSFrançois Tigeot ring->virtual_start = ring->map.virtual; 1072e3adcf8fSFrançois Tigeot ret = ring->init(ring); 1073e3adcf8fSFrançois Tigeot if (ret) 1074e3adcf8fSFrançois Tigeot goto err_unmap; 1075e3adcf8fSFrançois Tigeot 1076e3adcf8fSFrançois Tigeot /* Workaround an erratum on the i830 which causes a hang if 1077e3adcf8fSFrançois Tigeot * the TAIL pointer points to within the last 2 cachelines 1078e3adcf8fSFrançois Tigeot * of the buffer. 1079e3adcf8fSFrançois Tigeot */ 1080e3adcf8fSFrançois Tigeot ring->effective_size = ring->size; 1081e3adcf8fSFrançois Tigeot if (IS_I830(ring->dev) || IS_845G(ring->dev)) 1082e3adcf8fSFrançois Tigeot ring->effective_size -= 128; 1083e3adcf8fSFrançois Tigeot 1084e3adcf8fSFrançois Tigeot return 0; 1085e3adcf8fSFrançois Tigeot 1086e3adcf8fSFrançois Tigeot err_unmap: 1087e3adcf8fSFrançois Tigeot drm_core_ioremapfree(&ring->map, dev); 1088e3adcf8fSFrançois Tigeot err_unpin: 1089e3adcf8fSFrançois Tigeot i915_gem_object_unpin(obj); 1090e3adcf8fSFrançois Tigeot err_unref: 1091e3adcf8fSFrançois Tigeot drm_gem_object_unreference(&obj->base); 1092e3adcf8fSFrançois Tigeot ring->obj = NULL; 1093e3adcf8fSFrançois Tigeot err_hws: 1094e3adcf8fSFrançois Tigeot cleanup_status_page(ring); 1095e3adcf8fSFrançois Tigeot return ret; 1096e3adcf8fSFrançois Tigeot } 1097e3adcf8fSFrançois Tigeot 1098e3adcf8fSFrançois Tigeot void intel_cleanup_ring_buffer(struct intel_ring_buffer *ring) 1099e3adcf8fSFrançois Tigeot { 1100e3adcf8fSFrançois Tigeot struct drm_i915_private *dev_priv; 1101e3adcf8fSFrançois Tigeot int ret; 1102e3adcf8fSFrançois Tigeot 1103e3adcf8fSFrançois Tigeot if (ring->obj == NULL) 1104e3adcf8fSFrançois Tigeot return; 1105e3adcf8fSFrançois Tigeot 1106e3adcf8fSFrançois Tigeot /* Disable the ring buffer. The ring must be idle at this point */ 1107e3adcf8fSFrançois Tigeot dev_priv = ring->dev->dev_private; 1108b030f26bSFrançois Tigeot ret = intel_ring_idle(ring); 1109b030f26bSFrançois Tigeot if (ret) 1110b030f26bSFrançois Tigeot DRM_ERROR("failed to quiesce %s whilst cleaning up: %d\n", 1111b030f26bSFrançois Tigeot ring->name, ret); 1112b030f26bSFrançois Tigeot 1113e3adcf8fSFrançois Tigeot I915_WRITE_CTL(ring, 0); 1114e3adcf8fSFrançois Tigeot 1115e3adcf8fSFrançois Tigeot drm_core_ioremapfree(&ring->map, ring->dev); 1116e3adcf8fSFrançois Tigeot 1117e3adcf8fSFrançois Tigeot i915_gem_object_unpin(ring->obj); 1118e3adcf8fSFrançois Tigeot drm_gem_object_unreference(&ring->obj->base); 1119e3adcf8fSFrançois Tigeot ring->obj = NULL; 1120e3adcf8fSFrançois Tigeot 1121e3adcf8fSFrançois Tigeot if (ring->cleanup) 1122e3adcf8fSFrançois Tigeot ring->cleanup(ring); 1123e3adcf8fSFrançois Tigeot 1124e3adcf8fSFrançois Tigeot cleanup_status_page(ring); 1125e3adcf8fSFrançois Tigeot } 1126e3adcf8fSFrançois Tigeot 1127e3adcf8fSFrançois Tigeot static int intel_ring_wait_seqno(struct intel_ring_buffer *ring, u32 seqno) 1128e3adcf8fSFrançois Tigeot { 1129e3adcf8fSFrançois Tigeot int ret; 1130e3adcf8fSFrançois Tigeot 1131b030f26bSFrançois Tigeot ret = i915_wait_seqno(ring, seqno); 1132b030f26bSFrançois Tigeot if (!ret) 1133b030f26bSFrançois Tigeot i915_gem_retire_requests_ring(ring); 1134e3adcf8fSFrançois Tigeot 1135e3adcf8fSFrançois Tigeot return ret; 1136e3adcf8fSFrançois Tigeot } 1137e3adcf8fSFrançois Tigeot 1138e3adcf8fSFrançois Tigeot static int intel_ring_wait_request(struct intel_ring_buffer *ring, int n) 1139e3adcf8fSFrançois Tigeot { 1140e3adcf8fSFrançois Tigeot struct drm_i915_gem_request *request; 1141e3adcf8fSFrançois Tigeot u32 seqno = 0; 1142e3adcf8fSFrançois Tigeot int ret; 1143e3adcf8fSFrançois Tigeot 1144e3adcf8fSFrançois Tigeot i915_gem_retire_requests_ring(ring); 1145e3adcf8fSFrançois Tigeot 1146e3adcf8fSFrançois Tigeot if (ring->last_retired_head != -1) { 1147e3adcf8fSFrançois Tigeot ring->head = ring->last_retired_head; 1148e3adcf8fSFrançois Tigeot ring->last_retired_head = -1; 1149e3adcf8fSFrançois Tigeot ring->space = ring_space(ring); 1150e3adcf8fSFrançois Tigeot if (ring->space >= n) 1151e3adcf8fSFrançois Tigeot return 0; 1152e3adcf8fSFrançois Tigeot } 1153e3adcf8fSFrançois Tigeot 1154e3adcf8fSFrançois Tigeot list_for_each_entry(request, &ring->request_list, list) { 1155e3adcf8fSFrançois Tigeot int space; 1156e3adcf8fSFrançois Tigeot 1157e3adcf8fSFrançois Tigeot if (request->tail == -1) 1158e3adcf8fSFrançois Tigeot continue; 1159e3adcf8fSFrançois Tigeot 1160e3adcf8fSFrançois Tigeot space = request->tail - (ring->tail + 8); 1161e3adcf8fSFrançois Tigeot if (space < 0) 1162e3adcf8fSFrançois Tigeot space += ring->size; 1163e3adcf8fSFrançois Tigeot if (space >= n) { 1164e3adcf8fSFrançois Tigeot seqno = request->seqno; 1165e3adcf8fSFrançois Tigeot break; 1166e3adcf8fSFrançois Tigeot } 1167e3adcf8fSFrançois Tigeot 1168e3adcf8fSFrançois Tigeot /* Consume this request in case we need more space than 1169e3adcf8fSFrançois Tigeot * is available and so need to prevent a race between 1170e3adcf8fSFrançois Tigeot * updating last_retired_head and direct reads of 1171e3adcf8fSFrançois Tigeot * I915_RING_HEAD. It also provides a nice sanity check. 1172e3adcf8fSFrançois Tigeot */ 1173e3adcf8fSFrançois Tigeot request->tail = -1; 1174e3adcf8fSFrançois Tigeot } 1175e3adcf8fSFrançois Tigeot 1176e3adcf8fSFrançois Tigeot if (seqno == 0) 1177e3adcf8fSFrançois Tigeot return -ENOSPC; 1178e3adcf8fSFrançois Tigeot 1179e3adcf8fSFrançois Tigeot ret = intel_ring_wait_seqno(ring, seqno); 1180e3adcf8fSFrançois Tigeot if (ret) 1181e3adcf8fSFrançois Tigeot return ret; 1182e3adcf8fSFrançois Tigeot 1183e3adcf8fSFrançois Tigeot if (ring->last_retired_head == -1) 1184e3adcf8fSFrançois Tigeot return -ENOSPC; 1185e3adcf8fSFrançois Tigeot 1186e3adcf8fSFrançois Tigeot ring->head = ring->last_retired_head; 1187e3adcf8fSFrançois Tigeot ring->last_retired_head = -1; 1188e3adcf8fSFrançois Tigeot ring->space = ring_space(ring); 1189e3adcf8fSFrançois Tigeot if (ring->space < n) 1190e3adcf8fSFrançois Tigeot return -ENOSPC; 1191e3adcf8fSFrançois Tigeot 1192e3adcf8fSFrançois Tigeot return 0; 1193e3adcf8fSFrançois Tigeot } 1194e3adcf8fSFrançois Tigeot 1195b030f26bSFrançois Tigeot static int ring_wait_for_space(struct intel_ring_buffer *ring, int n) 1196e3adcf8fSFrançois Tigeot { 1197e3adcf8fSFrançois Tigeot struct drm_device *dev = ring->dev; 1198e3adcf8fSFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 1199245593daSFrançois Tigeot unsigned long end; 1200e3adcf8fSFrançois Tigeot int ret; 1201e3adcf8fSFrançois Tigeot 1202e3adcf8fSFrançois Tigeot ret = intel_ring_wait_request(ring, n); 1203e3adcf8fSFrançois Tigeot if (ret != -ENOSPC) 1204e3adcf8fSFrançois Tigeot return ret; 1205e3adcf8fSFrançois Tigeot 1206e3adcf8fSFrançois Tigeot /* With GEM the hangcheck timer should kick us out of the loop, 1207e3adcf8fSFrançois Tigeot * leaving it early runs the risk of corrupting GEM state (due 1208e3adcf8fSFrançois Tigeot * to running on almost untested codepaths). But on resume 1209e3adcf8fSFrançois Tigeot * timers don't work yet, so prevent a complete hang in that 1210e3adcf8fSFrançois Tigeot * case by choosing an insanely large timeout. */ 1211245593daSFrançois Tigeot end = ticks + 60 * hz; 1212245593daSFrançois Tigeot 1213e3adcf8fSFrançois Tigeot do { 1214e3adcf8fSFrançois Tigeot ring->head = I915_READ_HEAD(ring); 1215e3adcf8fSFrançois Tigeot ring->space = ring_space(ring); 1216e3adcf8fSFrançois Tigeot if (ring->space >= n) { 1217e3adcf8fSFrançois Tigeot return 0; 1218e3adcf8fSFrançois Tigeot } 1219e3adcf8fSFrançois Tigeot 1220e3adcf8fSFrançois Tigeot #if 0 1221e3adcf8fSFrançois Tigeot if (dev->primary->master) { 1222e3adcf8fSFrançois Tigeot struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv; 1223e3adcf8fSFrançois Tigeot if (master_priv->sarea_priv) 1224e3adcf8fSFrançois Tigeot master_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT; 1225e3adcf8fSFrançois Tigeot } 1226e3adcf8fSFrançois Tigeot #else 1227e3adcf8fSFrançois Tigeot if (dev_priv->sarea_priv) 1228e3adcf8fSFrançois Tigeot dev_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT; 1229e3adcf8fSFrançois Tigeot #endif 1230e3adcf8fSFrançois Tigeot 1231e3adcf8fSFrançois Tigeot DELAY(1000); 1232245593daSFrançois Tigeot 1233245593daSFrançois Tigeot ret = i915_gem_check_wedge(dev_priv, dev_priv->mm.interruptible); 1234245593daSFrançois Tigeot if (ret) 1235245593daSFrançois Tigeot return ret; 1236e3adcf8fSFrançois Tigeot } while (!time_after(ticks, end)); 1237e3adcf8fSFrançois Tigeot return -EBUSY; 1238e3adcf8fSFrançois Tigeot } 1239e3adcf8fSFrançois Tigeot 1240b030f26bSFrançois Tigeot static int intel_wrap_ring_buffer(struct intel_ring_buffer *ring) 1241b030f26bSFrançois Tigeot { 1242b030f26bSFrançois Tigeot uint32_t __iomem *virt; 1243b030f26bSFrançois Tigeot int rem = ring->size - ring->tail; 1244b030f26bSFrançois Tigeot 1245b030f26bSFrançois Tigeot if (ring->space < rem) { 1246b030f26bSFrançois Tigeot int ret = ring_wait_for_space(ring, rem); 1247b030f26bSFrançois Tigeot if (ret) 1248b030f26bSFrançois Tigeot return ret; 1249b030f26bSFrançois Tigeot } 1250b030f26bSFrançois Tigeot 1251b030f26bSFrançois Tigeot virt = (unsigned int *)((char *)ring->virtual_start + ring->tail); 1252b030f26bSFrançois Tigeot rem /= 4; 1253b030f26bSFrançois Tigeot while (rem--) 1254b030f26bSFrançois Tigeot *virt++ = MI_NOOP; 1255b030f26bSFrançois Tigeot 1256b030f26bSFrançois Tigeot ring->tail = 0; 1257b030f26bSFrançois Tigeot ring->space = ring_space(ring); 1258b030f26bSFrançois Tigeot 1259b030f26bSFrançois Tigeot return 0; 1260b030f26bSFrançois Tigeot } 1261b030f26bSFrançois Tigeot 1262b030f26bSFrançois Tigeot int intel_ring_idle(struct intel_ring_buffer *ring) 1263b030f26bSFrançois Tigeot { 1264b030f26bSFrançois Tigeot return ring_wait_for_space(ring, ring->size - 8); 1265b030f26bSFrançois Tigeot } 1266b030f26bSFrançois Tigeot 1267e3adcf8fSFrançois Tigeot int intel_ring_begin(struct intel_ring_buffer *ring, 1268e3adcf8fSFrançois Tigeot int num_dwords) 1269e3adcf8fSFrançois Tigeot { 1270e3adcf8fSFrançois Tigeot struct drm_i915_private *dev_priv = ring->dev->dev_private; 1271e3adcf8fSFrançois Tigeot int n = 4*num_dwords; 1272e3adcf8fSFrançois Tigeot int ret; 1273e3adcf8fSFrançois Tigeot 1274245593daSFrançois Tigeot ret = i915_gem_check_wedge(dev_priv, dev_priv->mm.interruptible); 1275245593daSFrançois Tigeot if (ret) 1276245593daSFrançois Tigeot return ret; 1277e3adcf8fSFrançois Tigeot 1278245593daSFrançois Tigeot if (unlikely(ring->tail + n > ring->effective_size)) { 1279e3adcf8fSFrançois Tigeot ret = intel_wrap_ring_buffer(ring); 1280245593daSFrançois Tigeot if (unlikely(ret)) 1281e3adcf8fSFrançois Tigeot return ret; 1282e3adcf8fSFrançois Tigeot } 1283e3adcf8fSFrançois Tigeot 1284b030f26bSFrançois Tigeot if (unlikely(ring->space < n)) { 1285b030f26bSFrançois Tigeot ret = ring_wait_for_space(ring, n); 1286b030f26bSFrançois Tigeot if (unlikely(ret)) 1287e3adcf8fSFrançois Tigeot return ret; 1288e3adcf8fSFrançois Tigeot } 1289e3adcf8fSFrançois Tigeot 1290e3adcf8fSFrançois Tigeot ring->space -= n; 1291e3adcf8fSFrançois Tigeot return 0; 1292e3adcf8fSFrançois Tigeot } 1293e3adcf8fSFrançois Tigeot 1294e3adcf8fSFrançois Tigeot void intel_ring_advance(struct intel_ring_buffer *ring) 1295e3adcf8fSFrançois Tigeot { 1296e3adcf8fSFrançois Tigeot ring->tail &= ring->size - 1; 1297e3adcf8fSFrançois Tigeot ring->write_tail(ring, ring->tail); 1298e3adcf8fSFrançois Tigeot } 1299e3adcf8fSFrançois Tigeot 1300e3adcf8fSFrançois Tigeot static const struct intel_ring_buffer render_ring = { 1301e3adcf8fSFrançois Tigeot .name = "render ring", 1302e3adcf8fSFrançois Tigeot .id = RCS, 1303e3adcf8fSFrançois Tigeot .mmio_base = RENDER_RING_BASE, 1304e3adcf8fSFrançois Tigeot .size = 32 * PAGE_SIZE, 1305e3adcf8fSFrançois Tigeot .init = init_render_ring, 1306e3adcf8fSFrançois Tigeot .write_tail = ring_write_tail, 1307e3adcf8fSFrançois Tigeot .flush = render_ring_flush, 1308e3adcf8fSFrançois Tigeot .add_request = render_ring_add_request, 1309e3adcf8fSFrançois Tigeot .get_seqno = ring_get_seqno, 1310e3adcf8fSFrançois Tigeot .irq_get = render_ring_get_irq, 1311e3adcf8fSFrançois Tigeot .irq_put = render_ring_put_irq, 1312e3adcf8fSFrançois Tigeot .dispatch_execbuffer = render_ring_dispatch_execbuffer, 1313e3adcf8fSFrançois Tigeot .cleanup = render_ring_cleanup, 1314e3adcf8fSFrançois Tigeot .sync_to = render_ring_sync_to, 1315e3adcf8fSFrançois Tigeot .semaphore_register = {MI_SEMAPHORE_SYNC_INVALID, 1316e3adcf8fSFrançois Tigeot MI_SEMAPHORE_SYNC_RV, 1317e3adcf8fSFrançois Tigeot MI_SEMAPHORE_SYNC_RB}, 1318e3adcf8fSFrançois Tigeot .signal_mbox = {GEN6_VRSYNC, GEN6_BRSYNC}, 1319e3adcf8fSFrançois Tigeot }; 1320e3adcf8fSFrançois Tigeot 1321e3adcf8fSFrançois Tigeot /* ring buffer for bit-stream decoder */ 1322e3adcf8fSFrançois Tigeot 1323e3adcf8fSFrançois Tigeot static const struct intel_ring_buffer bsd_ring = { 1324e3adcf8fSFrançois Tigeot .name = "bsd ring", 1325e3adcf8fSFrançois Tigeot .id = VCS, 1326e3adcf8fSFrançois Tigeot .mmio_base = BSD_RING_BASE, 1327e3adcf8fSFrançois Tigeot .size = 32 * PAGE_SIZE, 1328e3adcf8fSFrançois Tigeot .init = init_ring_common, 1329e3adcf8fSFrançois Tigeot .write_tail = ring_write_tail, 1330e3adcf8fSFrançois Tigeot .flush = bsd_ring_flush, 1331e3adcf8fSFrançois Tigeot .add_request = ring_add_request, 1332e3adcf8fSFrançois Tigeot .get_seqno = ring_get_seqno, 1333e3adcf8fSFrançois Tigeot .irq_get = bsd_ring_get_irq, 1334e3adcf8fSFrançois Tigeot .irq_put = bsd_ring_put_irq, 1335e3adcf8fSFrançois Tigeot .dispatch_execbuffer = ring_dispatch_execbuffer, 1336e3adcf8fSFrançois Tigeot }; 1337e3adcf8fSFrançois Tigeot 1338e3adcf8fSFrançois Tigeot 1339e3adcf8fSFrançois Tigeot static void gen6_bsd_ring_write_tail(struct intel_ring_buffer *ring, 1340f4e1c372SFrançois Tigeot u32 value) 1341e3adcf8fSFrançois Tigeot { 1342e3adcf8fSFrançois Tigeot drm_i915_private_t *dev_priv = ring->dev->dev_private; 1343e3adcf8fSFrançois Tigeot 1344e3adcf8fSFrançois Tigeot /* Every tail move must follow the sequence below */ 1345f4e1c372SFrançois Tigeot 1346f4e1c372SFrançois Tigeot /* Disable notification that the ring is IDLE. The GT 1347f4e1c372SFrançois Tigeot * will then assume that it is busy and bring it out of rc6. 1348f4e1c372SFrançois Tigeot */ 1349e3adcf8fSFrançois Tigeot I915_WRITE(GEN6_BSD_SLEEP_PSMI_CONTROL, 1350f4e1c372SFrançois Tigeot _MASKED_BIT_ENABLE(GEN6_BSD_SLEEP_MSG_DISABLE)); 1351e3adcf8fSFrançois Tigeot 1352f4e1c372SFrançois Tigeot /* Clear the context id. Here be magic! */ 1353f4e1c372SFrançois Tigeot I915_WRITE64(GEN6_BSD_RNCID, 0x0); 1354e3adcf8fSFrançois Tigeot 1355f4e1c372SFrançois Tigeot /* Wait for the ring not to be idle, i.e. for it to wake up. */ 1356f4e1c372SFrançois Tigeot if (wait_for((I915_READ(GEN6_BSD_SLEEP_PSMI_CONTROL) & 1357f4e1c372SFrançois Tigeot GEN6_BSD_SLEEP_INDICATOR) == 0, 1358f4e1c372SFrançois Tigeot 50)) 1359f4e1c372SFrançois Tigeot DRM_ERROR("timed out waiting for the BSD ring to wake up\n"); 1360f4e1c372SFrançois Tigeot 1361f4e1c372SFrançois Tigeot /* Now that the ring is fully powered up, update the tail */ 1362e3adcf8fSFrançois Tigeot I915_WRITE_TAIL(ring, value); 1363f4e1c372SFrançois Tigeot POSTING_READ(RING_TAIL(ring->mmio_base)); 1364f4e1c372SFrançois Tigeot 1365f4e1c372SFrançois Tigeot /* Let the ring send IDLE messages to the GT again, 1366f4e1c372SFrançois Tigeot * and so let it sleep to conserve power when idle. 1367f4e1c372SFrançois Tigeot */ 1368e3adcf8fSFrançois Tigeot I915_WRITE(GEN6_BSD_SLEEP_PSMI_CONTROL, 1369f4e1c372SFrançois Tigeot _MASKED_BIT_DISABLE(GEN6_BSD_SLEEP_MSG_DISABLE)); 1370e3adcf8fSFrançois Tigeot } 1371e3adcf8fSFrançois Tigeot 1372e3adcf8fSFrançois Tigeot static int gen6_ring_flush(struct intel_ring_buffer *ring, 1373e3adcf8fSFrançois Tigeot uint32_t invalidate, uint32_t flush) 1374e3adcf8fSFrançois Tigeot { 1375e3adcf8fSFrançois Tigeot uint32_t cmd; 1376e3adcf8fSFrançois Tigeot int ret; 1377e3adcf8fSFrançois Tigeot 1378e3adcf8fSFrançois Tigeot ret = intel_ring_begin(ring, 4); 1379e3adcf8fSFrançois Tigeot if (ret) 1380e3adcf8fSFrançois Tigeot return ret; 1381e3adcf8fSFrançois Tigeot 1382e3adcf8fSFrançois Tigeot cmd = MI_FLUSH_DW; 1383e3adcf8fSFrançois Tigeot if (invalidate & I915_GEM_GPU_DOMAINS) 1384e3adcf8fSFrançois Tigeot cmd |= MI_INVALIDATE_TLB | MI_INVALIDATE_BSD; 1385e3adcf8fSFrançois Tigeot intel_ring_emit(ring, cmd); 1386e3adcf8fSFrançois Tigeot intel_ring_emit(ring, 0); 1387e3adcf8fSFrançois Tigeot intel_ring_emit(ring, 0); 1388e3adcf8fSFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 1389e3adcf8fSFrançois Tigeot intel_ring_advance(ring); 1390e3adcf8fSFrançois Tigeot return 0; 1391e3adcf8fSFrançois Tigeot } 1392e3adcf8fSFrançois Tigeot 1393e3adcf8fSFrançois Tigeot static int 1394e3adcf8fSFrançois Tigeot gen6_ring_dispatch_execbuffer(struct intel_ring_buffer *ring, 1395e3adcf8fSFrançois Tigeot uint32_t offset, uint32_t len) 1396e3adcf8fSFrançois Tigeot { 1397e3adcf8fSFrançois Tigeot int ret; 1398e3adcf8fSFrançois Tigeot 1399e3adcf8fSFrançois Tigeot ret = intel_ring_begin(ring, 2); 1400e3adcf8fSFrançois Tigeot if (ret) 1401e3adcf8fSFrançois Tigeot return ret; 1402e3adcf8fSFrançois Tigeot 1403e3adcf8fSFrançois Tigeot intel_ring_emit(ring, MI_BATCH_BUFFER_START | MI_BATCH_NON_SECURE_I965); 1404e3adcf8fSFrançois Tigeot /* bit0-7 is the length on GEN6+ */ 1405e3adcf8fSFrançois Tigeot intel_ring_emit(ring, offset); 1406e3adcf8fSFrançois Tigeot intel_ring_advance(ring); 1407e3adcf8fSFrançois Tigeot 1408e3adcf8fSFrançois Tigeot return 0; 1409e3adcf8fSFrançois Tigeot } 1410e3adcf8fSFrançois Tigeot 1411e3adcf8fSFrançois Tigeot static bool 1412e3adcf8fSFrançois Tigeot gen6_render_ring_get_irq(struct intel_ring_buffer *ring) 1413e3adcf8fSFrançois Tigeot { 1414e3adcf8fSFrançois Tigeot return gen6_ring_get_irq(ring, 1415e3adcf8fSFrançois Tigeot GT_USER_INTERRUPT, 1416e3adcf8fSFrançois Tigeot GEN6_RENDER_USER_INTERRUPT); 1417e3adcf8fSFrançois Tigeot } 1418e3adcf8fSFrançois Tigeot 1419e3adcf8fSFrançois Tigeot static void 1420e3adcf8fSFrançois Tigeot gen6_render_ring_put_irq(struct intel_ring_buffer *ring) 1421e3adcf8fSFrançois Tigeot { 1422e3adcf8fSFrançois Tigeot return gen6_ring_put_irq(ring, 1423e3adcf8fSFrançois Tigeot GT_USER_INTERRUPT, 1424e3adcf8fSFrançois Tigeot GEN6_RENDER_USER_INTERRUPT); 1425e3adcf8fSFrançois Tigeot } 1426e3adcf8fSFrançois Tigeot 1427e3adcf8fSFrançois Tigeot static bool 1428e3adcf8fSFrançois Tigeot gen6_bsd_ring_get_irq(struct intel_ring_buffer *ring) 1429e3adcf8fSFrançois Tigeot { 1430e3adcf8fSFrançois Tigeot return gen6_ring_get_irq(ring, 1431e3adcf8fSFrançois Tigeot GT_GEN6_BSD_USER_INTERRUPT, 1432e3adcf8fSFrançois Tigeot GEN6_BSD_USER_INTERRUPT); 1433e3adcf8fSFrançois Tigeot } 1434e3adcf8fSFrançois Tigeot 1435e3adcf8fSFrançois Tigeot static void 1436e3adcf8fSFrançois Tigeot gen6_bsd_ring_put_irq(struct intel_ring_buffer *ring) 1437e3adcf8fSFrançois Tigeot { 1438e3adcf8fSFrançois Tigeot return gen6_ring_put_irq(ring, 1439e3adcf8fSFrançois Tigeot GT_GEN6_BSD_USER_INTERRUPT, 1440e3adcf8fSFrançois Tigeot GEN6_BSD_USER_INTERRUPT); 1441e3adcf8fSFrançois Tigeot } 1442e3adcf8fSFrançois Tigeot 1443e3adcf8fSFrançois Tigeot /* ring buffer for Video Codec for Gen6+ */ 1444e3adcf8fSFrançois Tigeot static const struct intel_ring_buffer gen6_bsd_ring = { 1445e3adcf8fSFrançois Tigeot .name = "gen6 bsd ring", 1446e3adcf8fSFrançois Tigeot .id = VCS, 1447e3adcf8fSFrançois Tigeot .mmio_base = GEN6_BSD_RING_BASE, 1448e3adcf8fSFrançois Tigeot .size = 32 * PAGE_SIZE, 1449e3adcf8fSFrançois Tigeot .init = init_ring_common, 1450e3adcf8fSFrançois Tigeot .write_tail = gen6_bsd_ring_write_tail, 1451e3adcf8fSFrançois Tigeot .flush = gen6_ring_flush, 1452e3adcf8fSFrançois Tigeot .add_request = gen6_add_request, 1453e3adcf8fSFrançois Tigeot .get_seqno = gen6_ring_get_seqno, 1454e3adcf8fSFrançois Tigeot .irq_get = gen6_bsd_ring_get_irq, 1455e3adcf8fSFrançois Tigeot .irq_put = gen6_bsd_ring_put_irq, 1456e3adcf8fSFrançois Tigeot .dispatch_execbuffer = gen6_ring_dispatch_execbuffer, 1457e3adcf8fSFrançois Tigeot .sync_to = gen6_bsd_ring_sync_to, 1458e3adcf8fSFrançois Tigeot .semaphore_register = {MI_SEMAPHORE_SYNC_VR, 1459e3adcf8fSFrançois Tigeot MI_SEMAPHORE_SYNC_INVALID, 1460e3adcf8fSFrançois Tigeot MI_SEMAPHORE_SYNC_VB}, 1461e3adcf8fSFrançois Tigeot .signal_mbox = {GEN6_RVSYNC, GEN6_BVSYNC}, 1462e3adcf8fSFrançois Tigeot }; 1463e3adcf8fSFrançois Tigeot 1464e3adcf8fSFrançois Tigeot /* Blitter support (SandyBridge+) */ 1465e3adcf8fSFrançois Tigeot 1466e3adcf8fSFrançois Tigeot static bool 1467e3adcf8fSFrançois Tigeot blt_ring_get_irq(struct intel_ring_buffer *ring) 1468e3adcf8fSFrançois Tigeot { 1469e3adcf8fSFrançois Tigeot return gen6_ring_get_irq(ring, 1470f4e1c372SFrançois Tigeot GT_GEN6_BLT_USER_INTERRUPT, 1471e3adcf8fSFrançois Tigeot GEN6_BLITTER_USER_INTERRUPT); 1472e3adcf8fSFrançois Tigeot } 1473e3adcf8fSFrançois Tigeot 1474e3adcf8fSFrançois Tigeot static void 1475e3adcf8fSFrançois Tigeot blt_ring_put_irq(struct intel_ring_buffer *ring) 1476e3adcf8fSFrançois Tigeot { 1477e3adcf8fSFrançois Tigeot gen6_ring_put_irq(ring, 1478f4e1c372SFrançois Tigeot GT_GEN6_BLT_USER_INTERRUPT, 1479e3adcf8fSFrançois Tigeot GEN6_BLITTER_USER_INTERRUPT); 1480e3adcf8fSFrançois Tigeot } 1481e3adcf8fSFrançois Tigeot 1482e3adcf8fSFrançois Tigeot static int blt_ring_flush(struct intel_ring_buffer *ring, 1483e3adcf8fSFrançois Tigeot uint32_t invalidate, uint32_t flush) 1484e3adcf8fSFrançois Tigeot { 1485e3adcf8fSFrançois Tigeot uint32_t cmd; 1486e3adcf8fSFrançois Tigeot int ret; 1487e3adcf8fSFrançois Tigeot 1488e3adcf8fSFrançois Tigeot ret = intel_ring_begin(ring, 4); 1489e3adcf8fSFrançois Tigeot if (ret) 1490e3adcf8fSFrançois Tigeot return ret; 1491e3adcf8fSFrançois Tigeot 1492e3adcf8fSFrançois Tigeot cmd = MI_FLUSH_DW; 1493e3adcf8fSFrançois Tigeot if (invalidate & I915_GEM_DOMAIN_RENDER) 1494e3adcf8fSFrançois Tigeot cmd |= MI_INVALIDATE_TLB; 1495e3adcf8fSFrançois Tigeot intel_ring_emit(ring, cmd); 1496e3adcf8fSFrançois Tigeot intel_ring_emit(ring, 0); 1497e3adcf8fSFrançois Tigeot intel_ring_emit(ring, 0); 1498e3adcf8fSFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 1499e3adcf8fSFrançois Tigeot intel_ring_advance(ring); 1500e3adcf8fSFrançois Tigeot return 0; 1501e3adcf8fSFrançois Tigeot } 1502e3adcf8fSFrançois Tigeot 1503e3adcf8fSFrançois Tigeot static const struct intel_ring_buffer gen6_blt_ring = { 1504e3adcf8fSFrançois Tigeot .name = "blt ring", 1505e3adcf8fSFrançois Tigeot .id = BCS, 1506e3adcf8fSFrançois Tigeot .mmio_base = BLT_RING_BASE, 1507e3adcf8fSFrançois Tigeot .size = 32 * PAGE_SIZE, 1508e3adcf8fSFrançois Tigeot .init = init_ring_common, 1509e3adcf8fSFrançois Tigeot .write_tail = ring_write_tail, 1510e3adcf8fSFrançois Tigeot .flush = blt_ring_flush, 1511e3adcf8fSFrançois Tigeot .add_request = gen6_add_request, 1512e3adcf8fSFrançois Tigeot .get_seqno = gen6_ring_get_seqno, 1513e3adcf8fSFrançois Tigeot .irq_get = blt_ring_get_irq, 1514e3adcf8fSFrançois Tigeot .irq_put = blt_ring_put_irq, 1515e3adcf8fSFrançois Tigeot .dispatch_execbuffer = gen6_ring_dispatch_execbuffer, 1516e3adcf8fSFrançois Tigeot .sync_to = gen6_blt_ring_sync_to, 1517e3adcf8fSFrançois Tigeot .semaphore_register = {MI_SEMAPHORE_SYNC_BR, 1518e3adcf8fSFrançois Tigeot MI_SEMAPHORE_SYNC_BV, 1519e3adcf8fSFrançois Tigeot MI_SEMAPHORE_SYNC_INVALID}, 1520e3adcf8fSFrançois Tigeot .signal_mbox = {GEN6_RBSYNC, GEN6_VBSYNC}, 1521e3adcf8fSFrançois Tigeot }; 1522e3adcf8fSFrançois Tigeot 1523e3adcf8fSFrançois Tigeot int intel_init_render_ring_buffer(struct drm_device *dev) 1524e3adcf8fSFrançois Tigeot { 1525e3adcf8fSFrançois Tigeot drm_i915_private_t *dev_priv = dev->dev_private; 1526ad50ea93SFrançois Tigeot struct intel_ring_buffer *ring = &dev_priv->ring[RCS]; 1527e3adcf8fSFrançois Tigeot 1528e3adcf8fSFrançois Tigeot *ring = render_ring; 1529e3adcf8fSFrançois Tigeot if (INTEL_INFO(dev)->gen >= 6) { 1530e3adcf8fSFrançois Tigeot ring->add_request = gen6_add_request; 1531e3adcf8fSFrançois Tigeot ring->flush = gen6_render_ring_flush; 1532e3adcf8fSFrançois Tigeot ring->irq_get = gen6_render_ring_get_irq; 1533e3adcf8fSFrançois Tigeot ring->irq_put = gen6_render_ring_put_irq; 1534e3adcf8fSFrançois Tigeot ring->get_seqno = gen6_ring_get_seqno; 1535e3adcf8fSFrançois Tigeot } else if (IS_GEN5(dev)) { 1536e3adcf8fSFrançois Tigeot ring->add_request = pc_render_add_request; 1537e3adcf8fSFrançois Tigeot ring->get_seqno = pc_render_get_seqno; 1538e3adcf8fSFrançois Tigeot } 1539e3adcf8fSFrançois Tigeot 1540e3adcf8fSFrançois Tigeot if (!I915_NEED_GFX_HWS(dev)) { 1541e3adcf8fSFrançois Tigeot ring->status_page.page_addr = dev_priv->status_page_dmah->vaddr; 1542e3adcf8fSFrançois Tigeot memset(ring->status_page.page_addr, 0, PAGE_SIZE); 1543e3adcf8fSFrançois Tigeot } 1544e3adcf8fSFrançois Tigeot 1545e3adcf8fSFrançois Tigeot return intel_init_ring_buffer(dev, ring); 1546e3adcf8fSFrançois Tigeot } 1547e3adcf8fSFrançois Tigeot 1548e3adcf8fSFrançois Tigeot int intel_render_ring_init_dri(struct drm_device *dev, uint64_t start, 1549e3adcf8fSFrançois Tigeot uint32_t size) 1550e3adcf8fSFrançois Tigeot { 1551e3adcf8fSFrançois Tigeot drm_i915_private_t *dev_priv = dev->dev_private; 1552ad50ea93SFrançois Tigeot struct intel_ring_buffer *ring = &dev_priv->ring[RCS]; 1553e3adcf8fSFrançois Tigeot 1554e3adcf8fSFrançois Tigeot *ring = render_ring; 1555e3adcf8fSFrançois Tigeot if (INTEL_INFO(dev)->gen >= 6) { 1556e3adcf8fSFrançois Tigeot ring->add_request = gen6_add_request; 1557e3adcf8fSFrançois Tigeot ring->irq_get = gen6_render_ring_get_irq; 1558e3adcf8fSFrançois Tigeot ring->irq_put = gen6_render_ring_put_irq; 1559e3adcf8fSFrançois Tigeot } else if (IS_GEN5(dev)) { 1560e3adcf8fSFrançois Tigeot ring->add_request = pc_render_add_request; 1561e3adcf8fSFrançois Tigeot ring->get_seqno = pc_render_get_seqno; 1562e3adcf8fSFrançois Tigeot } 1563e3adcf8fSFrançois Tigeot 1564e3adcf8fSFrançois Tigeot ring->dev = dev; 1565e3adcf8fSFrançois Tigeot INIT_LIST_HEAD(&ring->active_list); 1566e3adcf8fSFrançois Tigeot INIT_LIST_HEAD(&ring->request_list); 1567e3adcf8fSFrançois Tigeot INIT_LIST_HEAD(&ring->gpu_write_list); 1568e3adcf8fSFrançois Tigeot 1569e3adcf8fSFrançois Tigeot ring->size = size; 1570e3adcf8fSFrançois Tigeot ring->effective_size = ring->size; 1571e3adcf8fSFrançois Tigeot if (IS_I830(ring->dev)) 1572e3adcf8fSFrançois Tigeot ring->effective_size -= 128; 1573e3adcf8fSFrançois Tigeot 1574e3adcf8fSFrançois Tigeot ring->map.offset = start; 1575e3adcf8fSFrançois Tigeot ring->map.size = size; 1576e3adcf8fSFrançois Tigeot ring->map.type = 0; 1577e3adcf8fSFrançois Tigeot ring->map.flags = 0; 1578e3adcf8fSFrançois Tigeot ring->map.mtrr = 0; 1579e3adcf8fSFrançois Tigeot 1580e3adcf8fSFrançois Tigeot drm_core_ioremap_wc(&ring->map, dev); 1581e3adcf8fSFrançois Tigeot if (ring->map.virtual == NULL) { 1582e3adcf8fSFrançois Tigeot DRM_ERROR("can not ioremap virtual address for" 1583e3adcf8fSFrançois Tigeot " ring buffer\n"); 1584e3adcf8fSFrançois Tigeot return -ENOMEM; 1585e3adcf8fSFrançois Tigeot } 1586e3adcf8fSFrançois Tigeot 1587e3adcf8fSFrançois Tigeot ring->virtual_start = (void *)ring->map.virtual; 1588e3adcf8fSFrançois Tigeot return 0; 1589e3adcf8fSFrançois Tigeot } 1590e3adcf8fSFrançois Tigeot 1591e3adcf8fSFrançois Tigeot int intel_init_bsd_ring_buffer(struct drm_device *dev) 1592e3adcf8fSFrançois Tigeot { 1593e3adcf8fSFrançois Tigeot drm_i915_private_t *dev_priv = dev->dev_private; 1594ad50ea93SFrançois Tigeot struct intel_ring_buffer *ring = &dev_priv->ring[VCS]; 1595e3adcf8fSFrançois Tigeot 1596e3adcf8fSFrançois Tigeot if (IS_GEN6(dev) || IS_GEN7(dev)) 1597e3adcf8fSFrançois Tigeot *ring = gen6_bsd_ring; 1598e3adcf8fSFrançois Tigeot else 1599e3adcf8fSFrançois Tigeot *ring = bsd_ring; 1600e3adcf8fSFrançois Tigeot 1601e3adcf8fSFrançois Tigeot return intel_init_ring_buffer(dev, ring); 1602e3adcf8fSFrançois Tigeot } 1603e3adcf8fSFrançois Tigeot 1604e3adcf8fSFrançois Tigeot int intel_init_blt_ring_buffer(struct drm_device *dev) 1605e3adcf8fSFrançois Tigeot { 1606e3adcf8fSFrançois Tigeot drm_i915_private_t *dev_priv = dev->dev_private; 1607ad50ea93SFrançois Tigeot struct intel_ring_buffer *ring = &dev_priv->ring[BCS]; 1608e3adcf8fSFrançois Tigeot 1609e3adcf8fSFrançois Tigeot *ring = gen6_blt_ring; 1610e3adcf8fSFrançois Tigeot 1611e3adcf8fSFrançois Tigeot return intel_init_ring_buffer(dev, ring); 1612e3adcf8fSFrançois Tigeot } 1613b030f26bSFrançois Tigeot 1614b030f26bSFrançois Tigeot int 1615b030f26bSFrançois Tigeot intel_ring_flush_all_caches(struct intel_ring_buffer *ring) 1616b030f26bSFrançois Tigeot { 1617b030f26bSFrançois Tigeot int ret; 1618b030f26bSFrançois Tigeot 1619b030f26bSFrançois Tigeot if (!ring->gpu_caches_dirty) 1620b030f26bSFrançois Tigeot return 0; 1621b030f26bSFrançois Tigeot 1622b030f26bSFrançois Tigeot ret = ring->flush(ring, 0, I915_GEM_GPU_DOMAINS); 1623b030f26bSFrançois Tigeot if (ret) 1624b030f26bSFrançois Tigeot return ret; 1625b030f26bSFrançois Tigeot 1626b030f26bSFrançois Tigeot ring->gpu_caches_dirty = false; 1627b030f26bSFrançois Tigeot return 0; 1628b030f26bSFrançois Tigeot } 1629b030f26bSFrançois Tigeot 1630b030f26bSFrançois Tigeot int 1631b030f26bSFrançois Tigeot intel_ring_invalidate_all_caches(struct intel_ring_buffer *ring) 1632b030f26bSFrançois Tigeot { 1633b030f26bSFrançois Tigeot uint32_t flush_domains; 1634b030f26bSFrançois Tigeot int ret; 1635b030f26bSFrançois Tigeot 1636b030f26bSFrançois Tigeot flush_domains = 0; 1637b030f26bSFrançois Tigeot if (ring->gpu_caches_dirty) 1638b030f26bSFrançois Tigeot flush_domains = I915_GEM_GPU_DOMAINS; 1639b030f26bSFrançois Tigeot 1640b030f26bSFrançois Tigeot ret = ring->flush(ring, I915_GEM_GPU_DOMAINS, flush_domains); 1641b030f26bSFrançois Tigeot if (ret) 1642b030f26bSFrançois Tigeot return ret; 1643b030f26bSFrançois Tigeot 1644b030f26bSFrançois Tigeot ring->gpu_caches_dirty = false; 1645b030f26bSFrançois Tigeot return 0; 1646b030f26bSFrançois Tigeot } 1647