diff options
Diffstat (limited to 'drivers/gpu/drm/i915/intel_ringbuffer.c')
-rw-r--r-- | drivers/gpu/drm/i915/intel_ringbuffer.c | 449 |
1 files changed, 363 insertions, 86 deletions
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 2346b920bd8..e51ab552046 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -280,6 +280,27 @@ gen7_render_ring_cs_stall_wa(struct intel_ring_buffer *ring) return 0; } +static int gen7_ring_fbc_flush(struct intel_ring_buffer *ring, u32 value) +{ + int ret; + + if (!ring->fbc_dirty) + return 0; + + ret = intel_ring_begin(ring, 4); + if (ret) + return ret; + intel_ring_emit(ring, MI_NOOP); + /* WaFbcNukeOn3DBlt:ivb/hsw */ + intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1)); + intel_ring_emit(ring, MSG_FBC_REND_STATE); + intel_ring_emit(ring, value); + intel_ring_advance(ring); + + ring->fbc_dirty = false; + return 0; +} + static int gen7_render_ring_flush(struct intel_ring_buffer *ring, u32 invalidate_domains, u32 flush_domains) @@ -318,6 +339,7 @@ gen7_render_ring_flush(struct intel_ring_buffer *ring, * TLB invalidate requires a post-sync write. */ flags |= PIPE_CONTROL_QW_WRITE; + flags |= PIPE_CONTROL_GLOBAL_GTT_IVB; /* Workaround: we must issue a pipe_control with CS-stall bit * set before a pipe_control command that has the state cache @@ -331,10 +353,13 @@ gen7_render_ring_flush(struct intel_ring_buffer *ring, intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(4)); intel_ring_emit(ring, flags); - intel_ring_emit(ring, scratch_addr | PIPE_CONTROL_GLOBAL_GTT); + intel_ring_emit(ring, scratch_addr); intel_ring_emit(ring, 0); intel_ring_advance(ring); + if (flush_domains) + return gen7_ring_fbc_flush(ring, FBC_REND_NUKE); + return 0; } @@ -428,6 +453,8 @@ static int init_ring_common(struct intel_ring_buffer *ring) ring->last_retired_head = -1; } + memset(&ring->hangcheck, 0, sizeof(ring->hangcheck)); + out: if (HAS_FORCE_WAKE(dev)) gen6_gt_force_wake_put(dev_priv); @@ -463,9 +490,14 @@ init_pipe_control(struct intel_ring_buffer *ring) goto err_unref; pc->gtt_offset = obj->gtt_offset; - pc->cpu_page = kmap(sg_page(obj->pages->sgl)); - if (pc->cpu_page == NULL) + pc->cpu_page = kmap(sg_page(obj->pages->sgl)); + if (pc->cpu_page == NULL) { + ret = -ENOMEM; goto err_unpin; + } + + DRM_DEBUG_DRIVER("%s pipe control offset: 0x%08x\n", + ring->name, pc->gtt_offset); pc->obj = obj; ring->private = pc; @@ -505,13 +537,27 @@ static int init_render_ring(struct intel_ring_buffer *ring) struct drm_i915_private *dev_priv = dev->dev_private; int ret = init_ring_common(ring); - if (INTEL_INFO(dev)->gen > 3) { + if (INTEL_INFO(dev)->gen > 3) I915_WRITE(MI_MODE, _MASKED_BIT_ENABLE(VS_TIMER_DISPATCH)); - if (IS_GEN7(dev)) - I915_WRITE(GFX_MODE_GEN7, - _MASKED_BIT_DISABLE(GFX_TLB_INVALIDATE_ALWAYS) | - _MASKED_BIT_ENABLE(GFX_REPLAY_MODE)); - } + + /* We need to disable the AsyncFlip performance optimisations in order + * to use MI_WAIT_FOR_EVENT within the CS. It should already be + * programmed to '1' on all products. + * + * WaDisableAsyncFlipPerfMode:snb,ivb,hsw,vlv + */ + if (INTEL_INFO(dev)->gen >= 6) + I915_WRITE(MI_MODE, _MASKED_BIT_ENABLE(ASYNC_FLIP_PERF_DISABLE)); + + /* Required for the hardware to program scanline values for waiting */ + if (INTEL_INFO(dev)->gen == 6) + I915_WRITE(GFX_MODE, + _MASKED_BIT_ENABLE(GFX_TLB_INVALIDATE_ALWAYS)); + + if (IS_GEN7(dev)) + I915_WRITE(GFX_MODE_GEN7, + _MASKED_BIT_DISABLE(GFX_TLB_INVALIDATE_ALWAYS) | + _MASKED_BIT_ENABLE(GFX_REPLAY_MODE)); if (INTEL_INFO(dev)->gen >= 5) { ret = init_pipe_control(ring); @@ -540,16 +586,21 @@ static int init_render_ring(struct intel_ring_buffer *ring) I915_WRITE(INSTPM, _MASKED_BIT_ENABLE(INSTPM_FORCE_ORDERING)); if (HAS_L3_GPU_CACHE(dev)) - I915_WRITE_IMR(ring, ~GEN6_RENDER_L3_PARITY_ERROR); + I915_WRITE_IMR(ring, ~GT_RENDER_L3_PARITY_ERROR_INTERRUPT); return ret; } static void render_ring_cleanup(struct intel_ring_buffer *ring) { + struct drm_device *dev = ring->dev; + if (!ring->private) return; + if (HAS_BROKEN_CS_TLB(dev)) + drm_gem_object_unreference(to_gem_object(ring->private)); + cleanup_pipe_control(ring); } @@ -557,9 +608,16 @@ static void update_mboxes(struct intel_ring_buffer *ring, u32 mmio_offset) { +/* NB: In order to be able to do semaphore MBOX updates for varying number + * of rings, it's easiest if we round up each individual update to a + * multiple of 2 (since ring updates must always be a multiple of 2) + * even though the actual update only requires 3 dwords. + */ +#define MBOX_UPDATE_DWORDS 4 intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1)); intel_ring_emit(ring, mmio_offset); intel_ring_emit(ring, ring->outstanding_lazy_request); + intel_ring_emit(ring, MI_NOOP); } /** @@ -574,19 +632,24 @@ update_mboxes(struct intel_ring_buffer *ring, static int gen6_add_request(struct intel_ring_buffer *ring) { - u32 mbox1_reg; - u32 mbox2_reg; - int ret; + struct drm_device *dev = ring->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_ring_buffer *useless; + int i, ret; - ret = intel_ring_begin(ring, 10); + ret = intel_ring_begin(ring, ((I915_NUM_RINGS-1) * + MBOX_UPDATE_DWORDS) + + 4); if (ret) return ret; +#undef MBOX_UPDATE_DWORDS - mbox1_reg = ring->signal_mbox[0]; - mbox2_reg = ring->signal_mbox[1]; + for_each_ring(useless, dev_priv, i) { + u32 mbox_reg = ring->signal_mbox[i]; + if (mbox_reg != GEN6_NOSYNC) + update_mboxes(ring, mbox_reg); + } - update_mboxes(ring, mbox1_reg); - update_mboxes(ring, mbox2_reg); intel_ring_emit(ring, MI_STORE_DWORD_INDEX); intel_ring_emit(ring, I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT); intel_ring_emit(ring, ring->outstanding_lazy_request); @@ -596,6 +659,13 @@ gen6_add_request(struct intel_ring_buffer *ring) return 0; } +static inline bool i915_gem_has_seqno_wrapped(struct drm_device *dev, + u32 seqno) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + return dev_priv->last_seqno < seqno; +} + /** * intel_ring_sync - sync the waiter to the signaller on seqno * @@ -626,11 +696,20 @@ gen6_ring_sync(struct intel_ring_buffer *waiter, if (ret) return ret; - intel_ring_emit(waiter, - dw1 | signaller->semaphore_register[waiter->id]); - intel_ring_emit(waiter, seqno); - intel_ring_emit(waiter, 0); - intel_ring_emit(waiter, MI_NOOP); + /* If seqno wrap happened, omit the wait with no-ops */ + if (likely(!i915_gem_has_seqno_wrapped(waiter->dev, seqno))) { + intel_ring_emit(waiter, + dw1 | + signaller->semaphore_register[waiter->id]); + intel_ring_emit(waiter, seqno); + intel_ring_emit(waiter, 0); + intel_ring_emit(waiter, MI_NOOP); + } else { + intel_ring_emit(waiter, MI_NOOP); + intel_ring_emit(waiter, MI_NOOP); + intel_ring_emit(waiter, MI_NOOP); + intel_ring_emit(waiter, MI_NOOP); + } intel_ring_advance(waiter); return 0; @@ -711,6 +790,12 @@ ring_get_seqno(struct intel_ring_buffer *ring, bool lazy_coherency) return intel_read_status_page(ring, I915_GEM_HWS_INDEX); } +static void +ring_set_seqno(struct intel_ring_buffer *ring, u32 seqno) +{ + intel_write_status_page(ring, I915_GEM_HWS_INDEX, seqno); +} + static u32 pc_render_get_seqno(struct intel_ring_buffer *ring, bool lazy_coherency) { @@ -718,6 +803,13 @@ pc_render_get_seqno(struct intel_ring_buffer *ring, bool lazy_coherency) return pc->cpu_page[0]; } +static void +pc_render_set_seqno(struct intel_ring_buffer *ring, u32 seqno) +{ + struct pipe_control *pc = ring->private; + pc->cpu_page[0] = seqno; +} + static bool gen5_ring_get_irq(struct intel_ring_buffer *ring) { @@ -729,7 +821,7 @@ gen5_ring_get_irq(struct intel_ring_buffer *ring) return false; spin_lock_irqsave(&dev_priv->irq_lock, flags); - if (ring->irq_refcount++ == 0) { + if (ring->irq_refcount.gt++ == 0) { dev_priv->gt_irq_mask &= ~ring->irq_enable_mask; I915_WRITE(GTIMR, dev_priv->gt_irq_mask); POSTING_READ(GTIMR); @@ -747,7 +839,7 @@ gen5_ring_put_irq(struct intel_ring_buffer *ring) unsigned long flags; spin_lock_irqsave(&dev_priv->irq_lock, flags); - if (--ring->irq_refcount == 0) { + if (--ring->irq_refcount.gt == 0) { dev_priv->gt_irq_mask |= ring->irq_enable_mask; I915_WRITE(GTIMR, dev_priv->gt_irq_mask); POSTING_READ(GTIMR); @@ -766,7 +858,7 @@ i9xx_ring_get_irq(struct intel_ring_buffer *ring) return false; spin_lock_irqsave(&dev_priv->irq_lock, flags); - if (ring->irq_refcount++ == 0) { + if (ring->irq_refcount.gt++ == 0) { dev_priv->irq_mask &= ~ring->irq_enable_mask; I915_WRITE(IMR, dev_priv->irq_mask); POSTING_READ(IMR); @@ -784,7 +876,7 @@ i9xx_ring_put_irq(struct intel_ring_buffer *ring) unsigned long flags; spin_lock_irqsave(&dev_priv->irq_lock, flags); - if (--ring->irq_refcount == 0) { + if (--ring->irq_refcount.gt == 0) { dev_priv->irq_mask |= ring->irq_enable_mask; I915_WRITE(IMR, dev_priv->irq_mask); POSTING_READ(IMR); @@ -803,7 +895,7 @@ i8xx_ring_get_irq(struct intel_ring_buffer *ring) return false; spin_lock_irqsave(&dev_priv->irq_lock, flags); - if (ring->irq_refcount++ == 0) { + if (ring->irq_refcount.gt++ == 0) { dev_priv->irq_mask &= ~ring->irq_enable_mask; I915_WRITE16(IMR, dev_priv->irq_mask); POSTING_READ16(IMR); @@ -821,7 +913,7 @@ i8xx_ring_put_irq(struct intel_ring_buffer *ring) unsigned long flags; spin_lock_irqsave(&dev_priv->irq_lock, flags); - if (--ring->irq_refcount == 0) { + if (--ring->irq_refcount.gt == 0) { dev_priv->irq_mask |= ring->irq_enable_mask; I915_WRITE16(IMR, dev_priv->irq_mask); POSTING_READ16(IMR); @@ -849,6 +941,9 @@ void intel_ring_setup_status_page(struct intel_ring_buffer *ring) case VCS: mmio = BSD_HWS_PGA_GEN7; break; + case VECS: + mmio = VEBOX_HWS_PGA_GEN7; + break; } } else if (IS_GEN6(ring->dev)) { mmio = RING_HWS_PGA_GEN6(ring->mmio_base); @@ -911,10 +1006,11 @@ gen6_ring_get_irq(struct intel_ring_buffer *ring) gen6_gt_force_wake_get(dev_priv); spin_lock_irqsave(&dev_priv->irq_lock, flags); - if (ring->irq_refcount++ == 0) { + if (ring->irq_refcount.gt++ == 0) { if (HAS_L3_GPU_CACHE(dev) && ring->id == RCS) - I915_WRITE_IMR(ring, ~(ring->irq_enable_mask | - GEN6_RENDER_L3_PARITY_ERROR)); + I915_WRITE_IMR(ring, + ~(ring->irq_enable_mask | + GT_RENDER_L3_PARITY_ERROR_INTERRUPT)); else I915_WRITE_IMR(ring, ~ring->irq_enable_mask); dev_priv->gt_irq_mask &= ~ring->irq_enable_mask; @@ -934,9 +1030,10 @@ gen6_ring_put_irq(struct intel_ring_buffer *ring) unsigned long flags; spin_lock_irqsave(&dev_priv->irq_lock, flags); - if (--ring->irq_refcount == 0) { + if (--ring->irq_refcount.gt == 0) { if (HAS_L3_GPU_CACHE(dev) && ring->id == RCS) - I915_WRITE_IMR(ring, ~GEN6_RENDER_L3_PARITY_ERROR); + I915_WRITE_IMR(ring, + ~GT_RENDER_L3_PARITY_ERROR_INTERRUPT); else I915_WRITE_IMR(ring, ~0); dev_priv->gt_irq_mask |= ring->irq_enable_mask; @@ -948,6 +1045,48 @@ gen6_ring_put_irq(struct intel_ring_buffer *ring) gen6_gt_force_wake_put(dev_priv); } +static bool +hsw_vebox_get_irq(struct intel_ring_buffer *ring) +{ + struct drm_device *dev = ring->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + unsigned long flags; + + if (!dev->irq_enabled) + return false; + + spin_lock_irqsave(&dev_priv->rps.lock, flags); + if (ring->irq_refcount.pm++ == 0) { + u32 pm_imr = I915_READ(GEN6_PMIMR); + I915_WRITE_IMR(ring, ~ring->irq_enable_mask); + I915_WRITE(GEN6_PMIMR, pm_imr & ~ring->irq_enable_mask); + POSTING_READ(GEN6_PMIMR); + } + spin_unlock_irqrestore(&dev_priv->rps.lock, flags); + + return true; +} + +static void +hsw_vebox_put_irq(struct intel_ring_buffer *ring) +{ + struct drm_device *dev = ring->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + unsigned long flags; + + if (!dev->irq_enabled) + return; + + spin_lock_irqsave(&dev_priv->rps.lock, flags); + if (--ring->irq_refcount.pm == 0) { + u32 pm_imr = I915_READ(GEN6_PMIMR); + I915_WRITE_IMR(ring, ~0); + I915_WRITE(GEN6_PMIMR, pm_imr | ring->irq_enable_mask); + POSTING_READ(GEN6_PMIMR); + } + spin_unlock_irqrestore(&dev_priv->rps.lock, flags); +} + static int i965_dispatch_execbuffer(struct intel_ring_buffer *ring, u32 offset, u32 length, @@ -969,6 +1108,8 @@ i965_dispatch_execbuffer(struct intel_ring_buffer *ring, return 0; } +/* Just userspace ABI convention to limit the wa batch bo to a resonable size */ +#define I830_BATCH_LIMIT (256*1024) static int i830_dispatch_execbuffer(struct intel_ring_buffer *ring, u32 offset, u32 len, @@ -976,15 +1117,47 @@ i830_dispatch_execbuffer(struct intel_ring_buffer *ring, { int ret; - ret = intel_ring_begin(ring, 4); - if (ret) - return ret; + if (flags & I915_DISPATCH_PINNED) { + ret = intel_ring_begin(ring, 4); + if (ret) + return ret; - intel_ring_emit(ring, MI_BATCH_BUFFER); - intel_ring_emit(ring, offset | (flags & I915_DISPATCH_SECURE ? 0 : MI_BATCH_NON_SECURE)); - intel_ring_emit(ring, offset + len - 8); - intel_ring_emit(ring, 0); - intel_ring_advance(ring); + intel_ring_emit(ring, MI_BATCH_BUFFER); + intel_ring_emit(ring, offset | (flags & I915_DISPATCH_SECURE ? 0 : MI_BATCH_NON_SECURE)); + intel_ring_emit(ring, offset + len - 8); + intel_ring_emit(ring, MI_NOOP); + intel_ring_advance(ring); + } else { + struct drm_i915_gem_object *obj = ring->private; + u32 cs_offset = obj->gtt_offset; + + if (len > I830_BATCH_LIMIT) + return -ENOSPC; + + ret = intel_ring_begin(ring, 9+3); + if (ret) + return ret; + /* Blit the batch (which has now all relocs applied) to the stable batch + * scratch bo area (so that the CS never stumbles over its tlb + * invalidation bug) ... */ + intel_ring_emit(ring, XY_SRC_COPY_BLT_CMD | + XY_SRC_COPY_BLT_WRITE_ALPHA | + XY_SRC_COPY_BLT_WRITE_RGB); + intel_ring_emit(ring, BLT_DEPTH_32 | BLT_ROP_GXCOPY | 4096); + intel_ring_emit(ring, 0); + intel_ring_emit(ring, (DIV_ROUND_UP(len, 4096) << 16) | 1024); + intel_ring_emit(ring, cs_offset); + intel_ring_emit(ring, 0); + intel_ring_emit(ring, 4096); + intel_ring_emit(ring, offset); + intel_ring_emit(ring, MI_FLUSH); + + /* ... and execute it. */ + intel_ring_emit(ring, MI_BATCH_BUFFER); + intel_ring_emit(ring, cs_offset | (flags & I915_DISPATCH_SECURE ? 0 : MI_BATCH_NON_SECURE)); + intel_ring_emit(ring, cs_offset + len - 8); + intel_ring_advance(ring); + } return 0; } @@ -1113,7 +1286,11 @@ static int intel_init_ring_buffer(struct drm_device *dev, return ret; } - obj = i915_gem_alloc_object(dev, ring->size); + obj = NULL; + if (!HAS_LLC(dev)) + obj = i915_gem_object_create_stolen(dev, ring->size); + if (obj == NULL) + obj = i915_gem_alloc_object(dev, ring->size); if (obj == NULL) { DRM_ERROR("Failed to allocate ringbuffer\n"); ret = -ENOMEM; @@ -1131,7 +1308,7 @@ static int intel_init_ring_buffer(struct drm_device *dev, goto err_unpin; ring->virtual_start = - ioremap_wc(dev_priv->mm.gtt->gma_bus_addr + obj->gtt_offset, + ioremap_wc(dev_priv->gtt.mappable_base + obj->gtt_offset, ring->size); if (ring->virtual_start == NULL) { DRM_ERROR("Failed to map ringbuffer.\n"); @@ -1297,7 +1474,8 @@ static int ring_wait_for_space(struct intel_ring_buffer *ring, int n) msleep(1); - ret = i915_gem_check_wedge(dev_priv, dev_priv->mm.interruptible); + ret = i915_gem_check_wedge(&dev_priv->gpu_error, + dev_priv->mm.interruptible); if (ret) return ret; } while (!time_after(jiffies, end)); @@ -1334,7 +1512,7 @@ int intel_ring_idle(struct intel_ring_buffer *ring) /* We need to add any requests required to flush the objects and ring */ if (ring->outstanding_lazy_request) { - ret = i915_add_request(ring, NULL, NULL); + ret = i915_add_request(ring, NULL); if (ret) return ret; } @@ -1359,14 +1537,35 @@ intel_ring_alloc_seqno(struct intel_ring_buffer *ring) return i915_gem_get_seqno(ring->dev, &ring->outstanding_lazy_request); } +static int __intel_ring_begin(struct intel_ring_buffer *ring, + int bytes) +{ + int ret; + + if (unlikely(ring->tail + bytes > ring->effective_size)) { + ret = intel_wrap_ring_buffer(ring); + if (unlikely(ret)) + return ret; + } + + if (unlikely(ring->space < bytes)) { + ret = ring_wait_for_space(ring, bytes); + if (unlikely(ret)) + return ret; + } + + ring->space -= bytes; + return 0; +} + int intel_ring_begin(struct intel_ring_buffer *ring, int num_dwords) { drm_i915_private_t *dev_priv = ring->dev->dev_private; - int n = 4*num_dwords; int ret; - ret = i915_gem_check_wedge(dev_priv, dev_priv->mm.interruptible); + ret = i915_gem_check_wedge(&dev_priv->gpu_error, + dev_priv->mm.interruptible); if (ret) return ret; @@ -1375,20 +1574,22 @@ int intel_ring_begin(struct intel_ring_buffer *ring, if (ret) return ret; - if (unlikely(ring->tail + n > ring->effective_size)) { - ret = intel_wrap_ring_buffer(ring); - if (unlikely(ret)) - return ret; - } + return __intel_ring_begin(ring, num_dwords * sizeof(uint32_t)); +} - if (unlikely(ring->space < n)) { - ret = ring_wait_for_space(ring, n); - if (unlikely(ret)) - return ret; +void intel_ring_init_seqno(struct intel_ring_buffer *ring, u32 seqno) +{ + struct drm_i915_private *dev_priv = ring->dev->dev_private; + + BUG_ON(ring->outstanding_lazy_request); + + if (INTEL_INFO(ring->dev)->gen >= 6) { + I915_WRITE(RING_SYNC_0(ring->mmio_base), 0); + I915_WRITE(RING_SYNC_1(ring->mmio_base), 0); } - ring->space -= n; - return 0; + ring->set_seqno(ring, seqno); + ring->hangcheck.seqno = seqno; } void intel_ring_advance(struct intel_ring_buffer *ring) @@ -1396,7 +1597,7 @@ void intel_ring_advance(struct intel_ring_buffer *ring) struct drm_i915_private *dev_priv = ring->dev->dev_private; ring->tail &= ring->size - 1; - if (dev_priv->stop_rings & intel_ring_flag(ring)) + if (dev_priv->gpu_error.stop_rings & intel_ring_flag(ring)) return; ring->write_tail(ring, ring->tail); } @@ -1435,8 +1636,8 @@ static void gen6_bsd_ring_write_tail(struct intel_ring_buffer *ring, _MASKED_BIT_DISABLE(GEN6_BSD_SLEEP_MSG_DISABLE)); } -static int gen6_ring_flush(struct intel_ring_buffer *ring, - u32 invalidate, u32 flush) +static int gen6_bsd_ring_flush(struct intel_ring_buffer *ring, + u32 invalidate, u32 flush) { uint32_t cmd; int ret; @@ -1507,9 +1708,10 @@ gen6_ring_dispatch_execbuffer(struct intel_ring_buffer *ring, /* Blitter support (SandyBridge+) */ -static int blt_ring_flush(struct intel_ring_buffer *ring, - u32 invalidate, u32 flush) +static int gen6_ring_flush(struct intel_ring_buffer *ring, + u32 invalidate, u32 flush) { + struct drm_device *dev = ring->dev; uint32_t cmd; int ret; @@ -1532,6 +1734,10 @@ static int blt_ring_flush(struct intel_ring_buffer *ring, intel_ring_emit(ring, 0); intel_ring_emit(ring, MI_NOOP); intel_ring_advance(ring); + + if (IS_GEN7(dev) && flush) + return gen7_ring_fbc_flush(ring, FBC_REND_CACHE_CLEAN); + return 0; } @@ -1551,21 +1757,27 @@ int intel_init_render_ring_buffer(struct drm_device *dev) ring->flush = gen6_render_ring_flush; ring->irq_get = gen6_ring_get_irq; ring->irq_put = gen6_ring_put_irq; - ring->irq_enable_mask = GT_USER_INTERRUPT; + ring->irq_enable_mask = GT_RENDER_USER_INTERRUPT; ring->get_seqno = gen6_ring_get_seqno; + ring->set_seqno = ring_set_seqno; ring->sync_to = gen6_ring_sync; - ring->semaphore_register[0] = MI_SEMAPHORE_SYNC_INVALID; - ring->semaphore_register[1] = MI_SEMAPHORE_SYNC_RV; - ring->semaphore_register[2] = MI_SEMAPHORE_SYNC_RB; - ring->signal_mbox[0] = GEN6_VRSYNC; - ring->signal_mbox[1] = GEN6_BRSYNC; + ring->semaphore_register[RCS] = MI_SEMAPHORE_SYNC_INVALID; + ring->semaphore_register[VCS] = MI_SEMAPHORE_SYNC_RV; + ring->semaphore_register[BCS] = MI_SEMAPHORE_SYNC_RB; + ring->semaphore_register[VECS] = MI_SEMAPHORE_SYNC_RVE; + ring->signal_mbox[RCS] = GEN6_NOSYNC; + ring->signal_mbox[VCS] = GEN6_VRSYNC; + ring->signal_mbox[BCS] = GEN6_BRSYNC; + ring->signal_mbox[VECS] = GEN6_VERSYNC; } else if (IS_GEN5(dev)) { ring->add_request = pc_render_add_request; ring->flush = gen4_render_ring_flush; ring->get_seqno = pc_render_get_seqno; + ring->set_seqno = pc_render_set_seqno; ring->irq_get = gen5_ring_get_irq; ring->irq_put = gen5_ring_put_irq; - ring->irq_enable_mask = GT_USER_INTERRUPT | GT_PIPE_NOTIFY; + ring->irq_enable_mask = GT_RENDER_USER_INTERRUPT | + GT_RENDER_PIPECTL_NOTIFY_INTERRUPT; } else { ring->add_request = i9xx_add_request; if (INTEL_INFO(dev)->gen < 4) @@ -1573,6 +1785,7 @@ int intel_init_render_ring_buffer(struct drm_device *dev) else ring->flush = gen4_render_ring_flush; ring->get_seqno = ring_get_seqno; + ring->set_seqno = ring_set_seqno; if (IS_GEN2(dev)) { ring->irq_get = i8xx_ring_get_irq; ring->irq_put = i8xx_ring_put_irq; @@ -1596,6 +1809,27 @@ int intel_init_render_ring_buffer(struct drm_device *dev) ring->init = init_render_ring; ring->cleanup = render_ring_cleanup; + /* Workaround batchbuffer to combat CS tlb bug. */ + if (HAS_BROKEN_CS_TLB(dev)) { + struct drm_i915_gem_object *obj; + int ret; + + obj = i915_gem_alloc_object(dev, I830_BATCH_LIMIT); + if (obj == NULL) { + DRM_ERROR("Failed to allocate batch bo\n"); + return -ENOMEM; + } + + ret = i915_gem_object_pin(obj, 0, true, false); + if (ret != 0) { + drm_gem_object_unreference(&obj->base); + DRM_ERROR("Failed to ping batch bo\n"); + return ret; + } + + ring->private = obj; + } + return intel_init_ring_buffer(dev, ring); } @@ -1623,6 +1857,7 @@ int intel_render_ring_init_dri(struct drm_device *dev, u64 start, u32 size) else ring->flush = gen4_render_ring_flush; ring->get_seqno = ring_get_seqno; + ring->set_seqno = ring_set_seqno; if (IS_GEN2(dev)) { ring->irq_get = i8xx_ring_get_irq; ring->irq_put = i8xx_ring_put_irq; @@ -1680,26 +1915,31 @@ int intel_init_bsd_ring_buffer(struct drm_device *dev) /* gen6 bsd needs a special wa for tail updates */ if (IS_GEN6(dev)) ring->write_tail = gen6_bsd_ring_write_tail; - ring->flush = gen6_ring_flush; + ring->flush = gen6_bsd_ring_flush; ring->add_request = gen6_add_request; ring->get_seqno = gen6_ring_get_seqno; - ring->irq_enable_mask = GEN6_BSD_USER_INTERRUPT; + ring->set_seqno = ring_set_seqno; + ring->irq_enable_mask = GT_BSD_USER_INTERRUPT; ring->irq_get = gen6_ring_get_irq; ring->irq_put = gen6_ring_put_irq; ring->dispatch_execbuffer = gen6_ring_dispatch_execbuffer; ring->sync_to = gen6_ring_sync; - ring->semaphore_register[0] = MI_SEMAPHORE_SYNC_VR; - ring->semaphore_register[1] = MI_SEMAPHORE_SYNC_INVALID; - ring->semaphore_register[2] = MI_SEMAPHORE_SYNC_VB; - ring->signal_mbox[0] = GEN6_RVSYNC; - ring->signal_mbox[1] = GEN6_BVSYNC; + ring->semaphore_register[RCS] = MI_SEMAPHORE_SYNC_VR; + ring->semaphore_register[VCS] = MI_SEMAPHORE_SYNC_INVALID; + ring->semaphore_register[BCS] = MI_SEMAPHORE_SYNC_VB; + ring->semaphore_register[VECS] = MI_SEMAPHORE_SYNC_VVE; + ring->signal_mbox[RCS] = GEN6_RVSYNC; + ring->signal_mbox[VCS] = GEN6_NOSYNC; + ring->signal_mbox[BCS] = GEN6_BVSYNC; + ring->signal_mbox[VECS] = GEN6_VEVSYNC; } else { ring->mmio_base = BSD_RING_BASE; ring->flush = bsd_ring_flush; ring->add_request = i9xx_add_request; ring->get_seqno = ring_get_seqno; + ring->set_seqno = ring_set_seqno; if (IS_GEN5(dev)) { - ring->irq_enable_mask = GT_BSD_USER_INTERRUPT; + ring->irq_enable_mask = ILK_BSD_USER_INTERRUPT; ring->irq_get = gen5_ring_get_irq; ring->irq_put = gen5_ring_put_irq; } else { @@ -1724,19 +1964,56 @@ int intel_init_blt_ring_buffer(struct drm_device *dev) ring->mmio_base = BLT_RING_BASE; ring->write_tail = ring_write_tail; - ring->flush = blt_ring_flush; + ring->flush = gen6_ring_flush; ring->add_request = gen6_add_request; ring->get_seqno = gen6_ring_get_seqno; - ring->irq_enable_mask = GEN6_BLITTER_USER_INTERRUPT; + ring->set_seqno = ring_set_seqno; + ring->irq_enable_mask = GT_BLT_USER_INTERRUPT; ring->irq_get = gen6_ring_get_irq; ring->irq_put = gen6_ring_put_irq; ring->dispatch_execbuffer = gen6_ring_dispatch_execbuffer; ring->sync_to = gen6_ring_sync; - ring->semaphore_register[0] = MI_SEMAPHORE_SYNC_BR; - ring->semaphore_register[1] = MI_SEMAPHORE_SYNC_BV; - ring->semaphore_register[2] = MI_SEMAPHORE_SYNC_INVALID; - ring->signal_mbox[0] = GEN6_RBSYNC; - ring->signal_mbox[1] = GEN6_VBSYNC; + ring->semaphore_register[RCS] = MI_SEMAPHORE_SYNC_BR; + ring->semaphore_register[VCS] = MI_SEMAPHORE_SYNC_BV; + ring->semaphore_register[BCS] = MI_SEMAPHORE_SYNC_INVALID; + ring->semaphore_register[VECS] = MI_SEMAPHORE_SYNC_BVE; + ring->signal_mbox[RCS] = GEN6_RBSYNC; + ring->signal_mbox[VCS] = GEN6_VBSYNC; + ring->signal_mbox[BCS] = GEN6_NOSYNC; + ring->signal_mbox[VECS] = GEN6_VEBSYNC; + ring->init = init_ring_common; + + return intel_init_ring_buffer(dev, ring); +} + +int intel_init_vebox_ring_buffer(struct drm_device *dev) +{ + drm_i915_private_t *dev_priv = dev->dev_private; + struct intel_ring_buffer *ring = &dev_priv->ring[VECS]; + + ring->name = "video enhancement ring"; + ring->id = VECS; + + ring->mmio_base = VEBOX_RING_BASE; + ring->write_tail = ring_write_tail; + ring->flush = gen6_ring_flush; + ring->add_request = gen6_add_request; + ring->get_seqno = gen6_ring_get_seqno; + ring->set_seqno = ring_set_seqno; + ring->irq_enable_mask = PM_VEBOX_USER_INTERRUPT | + PM_VEBOX_CS_ERROR_INTERRUPT; + ring->irq_get = hsw_vebox_get_irq; + ring->irq_put = hsw_vebox_put_irq; + ring->dispatch_execbuffer = gen6_ring_dispatch_execbuffer; + ring->sync_to = gen6_ring_sync; + ring->semaphore_register[RCS] = MI_SEMAPHORE_SYNC_VER; + ring->semaphore_register[VCS] = MI_SEMAPHORE_SYNC_VEV; + ring->semaphore_register[BCS] = MI_SEMAPHORE_SYNC_VEB; + ring->semaphore_register[VECS] = MI_SEMAPHORE_SYNC_INVALID; + ring->signal_mbox[RCS] = GEN6_RVESYNC; + ring->signal_mbox[VCS] = GEN6_VVESYNC; + ring->signal_mbox[BCS] = GEN6_BVESYNC; + ring->signal_mbox[VECS] = GEN6_NOSYNC; ring->init = init_ring_common; return intel_init_ring_buffer(dev, ring); |