From 498d2ac15ce0fc08edb005a7faf9ed6b5aa028d8 Mon Sep 17 00:00:00 2001 From: Mika Kuoppala Date: Tue, 4 Dec 2012 15:12:04 +0200 Subject: drm/i915: Add intel_ring_handle_seqno wrap If there are pre-wrap values in semaphore-mbox registers after wrap, syncing against some after-wrap request will complete immediately. Fix this by emitting ring commands to set mbox registers to zero when the wrap happens. v2: Use __intel_ring_begin to emit ring commands, from Chris Wilson. Signed-off-by: Mika Kuoppala Reviewed-by: Chris Wilson [danvet: Add a small comment to handle_seqno_wrap.] Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_ringbuffer.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu/drm/i915/intel_ringbuffer.h') diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index d4b7416fa1b..b4a533e53fd 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h @@ -196,7 +196,7 @@ static inline void intel_ring_emit(struct intel_ring_buffer *ring, } void intel_ring_advance(struct intel_ring_buffer *ring); int __must_check intel_ring_idle(struct intel_ring_buffer *ring); - +int __must_check intel_ring_handle_seqno_wrap(struct intel_ring_buffer *ring); int intel_ring_flush_all_caches(struct intel_ring_buffer *ring); int intel_ring_invalidate_all_caches(struct intel_ring_buffer *ring); -- cgit v1.2.3-70-g09d2 From b70ec5bf439b35a18e702f88078d393261c3e3f2 Mon Sep 17 00:00:00 2001 From: Mika Kuoppala Date: Wed, 19 Dec 2012 11:13:05 +0200 Subject: drm/i915: Introduce ring set_seqno In preparation for setting per ring initial seqno values add ring::set_seqno(). Signed-off-by: Mika Kuoppala Reviewed-by: Chris Wilson Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_ringbuffer.c | 20 ++++++++++++++++++++ drivers/gpu/drm/i915/intel_ringbuffer.h | 9 +++++++++ 2 files changed, 29 insertions(+) (limited to 'drivers/gpu/drm/i915/intel_ringbuffer.h') diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 69bbe7bb9f6..f536a9951ab 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -727,6 +727,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) { @@ -734,6 +740,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) { @@ -1602,6 +1615,7 @@ int intel_init_render_ring_buffer(struct drm_device *dev) ring->irq_put = gen6_ring_put_irq; ring->irq_enable_mask = GT_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; @@ -1612,6 +1626,7 @@ int intel_init_render_ring_buffer(struct drm_device *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; @@ -1622,6 +1637,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; @@ -1672,6 +1688,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; @@ -1732,6 +1749,7 @@ int intel_init_bsd_ring_buffer(struct drm_device *dev) 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 = GEN6_BSD_USER_INTERRUPT; ring->irq_get = gen6_ring_get_irq; ring->irq_put = gen6_ring_put_irq; @@ -1747,6 +1765,7 @@ int intel_init_bsd_ring_buffer(struct drm_device *dev) 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_get = gen5_ring_get_irq; @@ -1776,6 +1795,7 @@ int intel_init_blt_ring_buffer(struct drm_device *dev) ring->flush = blt_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 = GEN6_BLITTER_USER_INTERRUPT; ring->irq_get = gen6_ring_get_irq; ring->irq_put = gen6_ring_put_irq; diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index b4a533e53fd..4a7cd67742d 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h @@ -79,6 +79,8 @@ struct intel_ring_buffer { */ u32 (*get_seqno)(struct intel_ring_buffer *ring, bool lazy_coherency); + void (*set_seqno)(struct intel_ring_buffer *ring, + u32 seqno); int (*dispatch_execbuffer)(struct intel_ring_buffer *ring, u32 offset, u32 length, unsigned flags); @@ -166,6 +168,13 @@ intel_read_status_page(struct intel_ring_buffer *ring, return ring->status_page.page_addr[reg]; } +static inline void +intel_write_status_page(struct intel_ring_buffer *ring, + int reg, u32 value) +{ + ring->status_page.page_addr[reg] = value; +} + /** * Reads a dword out of the status page, which is written to from the command * queue by automatic updates, MI_REPORT_HEAD, MI_STORE_DATA_INDEX, or -- cgit v1.2.3-70-g09d2 From f7e98ad4d4a8afa043126a6f24d0a154a684e081 Mon Sep 17 00:00:00 2001 From: Mika Kuoppala Date: Wed, 19 Dec 2012 11:13:06 +0200 Subject: drm/i915: Initialize hardware semaphore state on ring init Hardware status page needs to have proper seqno set as our initial seqno can be arbitrary. If initial seqno is close to wrap boundary on init and i915_seqno_passed() (31bit space) refers to hw status page which contains zero, errorneous result will be returned. v2: clear mboxes and set hws page directly instead of going through rings. Suggested by Chris Wilson. v3: hws needs to be updated for all gens. Noticed by Chris Wilson. References: https://bugs.freedesktop.org/show_bug.cgi?id=58230 Signed-off-by: Mika Kuoppala Reviewed-by: Chris Wilson Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem.c | 8 +++----- drivers/gpu/drm/i915/intel_ringbuffer.c | 24 +++++++++--------------- drivers/gpu/drm/i915/intel_ringbuffer.h | 2 +- 3 files changed, 13 insertions(+), 21 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_ringbuffer.h') diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 6685861cd17..51282b2c494 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1954,9 +1954,7 @@ i915_gem_handle_seqno_wrap(struct drm_device *dev) /* Finally reset hw state */ for_each_ring(ring, dev_priv, i) { - ret = intel_ring_handle_seqno_wrap(ring); - if (ret) - return ret; + intel_ring_init_seqno(ring, 0); for (j = 0; j < ARRAY_SIZE(ring->sync_seqno); j++) ring->sync_seqno[j] = 0; @@ -3935,6 +3933,8 @@ i915_gem_init_hw(struct drm_device *dev) i915_gem_init_swizzling(dev); + dev_priv->next_seqno = dev_priv->last_seqno = (u32)~0 - 0x1000; + ret = intel_init_render_ring_buffer(dev); if (ret) return ret; @@ -3951,8 +3951,6 @@ i915_gem_init_hw(struct drm_device *dev) goto cleanup_bsd_ring; } - dev_priv->next_seqno = (u32)-1 - 0x1000; - /* * XXX: There was some w/a described somewhere suggesting loading * contexts before PPGTT. diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index f536a9951ab..2bd074ad6f5 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -1184,6 +1184,8 @@ static int intel_init_ring_buffer(struct drm_device *dev, if (IS_I830(ring->dev) || IS_845G(ring->dev)) ring->effective_size -= 128; + intel_ring_init_seqno(ring, dev_priv->last_seqno); + return 0; err_unmap: @@ -1431,26 +1433,18 @@ int intel_ring_begin(struct intel_ring_buffer *ring, return __intel_ring_begin(ring, num_dwords * sizeof(uint32_t)); } -int intel_ring_handle_seqno_wrap(struct intel_ring_buffer *ring) +void intel_ring_init_seqno(struct intel_ring_buffer *ring, u32 seqno) { - int ret; + struct drm_i915_private *dev_priv = ring->dev->dev_private; BUG_ON(ring->outstanding_lazy_request); - if (INTEL_INFO(ring->dev)->gen < 6) - return 0; - - ret = __intel_ring_begin(ring, 6 * sizeof(uint32_t)); - if (ret) - return ret; - - /* Leaving a stale, pre-wrap seqno behind in the mboxes will result in - * post-wrap semaphore waits completing immediately. Clear them. */ - update_mboxes(ring, ring->signal_mbox[0]); - update_mboxes(ring, ring->signal_mbox[1]); - intel_ring_advance(ring); + 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); + } - return 0; + ring->set_seqno(ring, seqno); } void intel_ring_advance(struct intel_ring_buffer *ring) diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index 4a7cd67742d..e7b9a6aac95 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h @@ -205,7 +205,7 @@ static inline void intel_ring_emit(struct intel_ring_buffer *ring, } void intel_ring_advance(struct intel_ring_buffer *ring); int __must_check intel_ring_idle(struct intel_ring_buffer *ring); -int __must_check intel_ring_handle_seqno_wrap(struct intel_ring_buffer *ring); +void intel_ring_init_seqno(struct intel_ring_buffer *ring, u32 seqno); int intel_ring_flush_all_caches(struct intel_ring_buffer *ring); int intel_ring_invalidate_all_caches(struct intel_ring_buffer *ring); -- cgit v1.2.3-70-g09d2