aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/intel_ringbuffer.c
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2012-11-27 11:22:52 -0500
committerDaniel Vetter <daniel.vetter@ffwll.ch>2012-11-29 05:43:52 -0500
commit9d7730914f4cd496e356acfab95b41075aa8eae8 (patch)
tree509e4ad7d5b7f32e3118fca228ce2f034403d634 /drivers/gpu/drm/i915/intel_ringbuffer.c
parent45e2b5f640b3766da3eda48f6c35f088155c06f3 (diff)
drm/i915: Preallocate next seqno before touching the ring
Based on the work by Mika Kuoppala, we realised that we need to handle seqno wraparound prior to committing our changes to the ring. The most obvious point then is to grab the seqno inside intel_ring_begin(), and then to reuse that seqno for all ring operations until the next request. As intel_ring_begin() can fail, the callers must already be prepared to handle such failure and so we can safely add further checks. This patch looks like it should be split up into the interface changes and the tweaks to move seqno wrapping from the execbuffer into the core seqno increment. However, I found no easy way to break it into incremental steps without introducing further broken behaviour. v2: Mika found a silly mistake and a subtle error in the existing code; inside i915_gem_retire_requests() we were resetting the sync_seqno of the target ring based on the seqno from this ring - which are only related by the order of their allocation, not retirement. Hence we were applying the optimisation that the rings were synchronised too early, fortunately the only real casualty there is the handling of seqno wrapping. v3: Do not forget to reset the sync_seqno upon module reinitialisation, ala resume. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Cc: Mika Kuoppala <mika.kuoppala@intel.com> Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=863861 Reviewed-by: Mika Kuoppala <mika.kuoppala@intel.com> [v2] Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Diffstat (limited to 'drivers/gpu/drm/i915/intel_ringbuffer.c')
-rw-r--r--drivers/gpu/drm/i915/intel_ringbuffer.c49
1 files changed, 26 insertions, 23 deletions
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c
index 987eb5fdaf39..e4682cdc00b0 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.c
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.c
@@ -555,12 +555,11 @@ static void render_ring_cleanup(struct intel_ring_buffer *ring)
555 555
556static void 556static void
557update_mboxes(struct intel_ring_buffer *ring, 557update_mboxes(struct intel_ring_buffer *ring,
558 u32 seqno, 558 u32 mmio_offset)
559 u32 mmio_offset)
560{ 559{
561 intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1)); 560 intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1));
562 intel_ring_emit(ring, mmio_offset); 561 intel_ring_emit(ring, mmio_offset);
563 intel_ring_emit(ring, seqno); 562 intel_ring_emit(ring, ring->outstanding_lazy_request);
564} 563}
565 564
566/** 565/**
@@ -573,8 +572,7 @@ update_mboxes(struct intel_ring_buffer *ring,
573 * This acts like a signal in the canonical semaphore. 572 * This acts like a signal in the canonical semaphore.
574 */ 573 */
575static int 574static int
576gen6_add_request(struct intel_ring_buffer *ring, 575gen6_add_request(struct intel_ring_buffer *ring)
577 u32 *seqno)
578{ 576{
579 u32 mbox1_reg; 577 u32 mbox1_reg;
580 u32 mbox2_reg; 578 u32 mbox2_reg;
@@ -587,13 +585,11 @@ gen6_add_request(struct intel_ring_buffer *ring,
587 mbox1_reg = ring->signal_mbox[0]; 585 mbox1_reg = ring->signal_mbox[0];
588 mbox2_reg = ring->signal_mbox[1]; 586 mbox2_reg = ring->signal_mbox[1];
589 587
590 *seqno = i915_gem_next_request_seqno(ring); 588 update_mboxes(ring, mbox1_reg);
591 589 update_mboxes(ring, mbox2_reg);
592 update_mboxes(ring, *seqno, mbox1_reg);
593 update_mboxes(ring, *seqno, mbox2_reg);
594 intel_ring_emit(ring, MI_STORE_DWORD_INDEX); 590 intel_ring_emit(ring, MI_STORE_DWORD_INDEX);
595 intel_ring_emit(ring, I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT); 591 intel_ring_emit(ring, I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT);
596 intel_ring_emit(ring, *seqno); 592 intel_ring_emit(ring, ring->outstanding_lazy_request);
597 intel_ring_emit(ring, MI_USER_INTERRUPT); 593 intel_ring_emit(ring, MI_USER_INTERRUPT);
598 intel_ring_advance(ring); 594 intel_ring_advance(ring);
599 595
@@ -650,10 +646,8 @@ do { \
650} while (0) 646} while (0)
651 647
652static int 648static int
653pc_render_add_request(struct intel_ring_buffer *ring, 649pc_render_add_request(struct intel_ring_buffer *ring)
654 u32 *result)
655{ 650{
656 u32 seqno = i915_gem_next_request_seqno(ring);
657 struct pipe_control *pc = ring->private; 651 struct pipe_control *pc = ring->private;
658 u32 scratch_addr = pc->gtt_offset + 128; 652 u32 scratch_addr = pc->gtt_offset + 128;
659 int ret; 653 int ret;
@@ -674,7 +668,7 @@ pc_render_add_request(struct intel_ring_buffer *ring,
674 PIPE_CONTROL_WRITE_FLUSH | 668 PIPE_CONTROL_WRITE_FLUSH |
675 PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE); 669 PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE);
676 intel_ring_emit(ring, pc->gtt_offset | PIPE_CONTROL_GLOBAL_GTT); 670 intel_ring_emit(ring, pc->gtt_offset | PIPE_CONTROL_GLOBAL_GTT);
677 intel_ring_emit(ring, seqno); 671 intel_ring_emit(ring, ring->outstanding_lazy_request);
678 intel_ring_emit(ring, 0); 672 intel_ring_emit(ring, 0);
679 PIPE_CONTROL_FLUSH(ring, scratch_addr); 673 PIPE_CONTROL_FLUSH(ring, scratch_addr);
680 scratch_addr += 128; /* write to separate cachelines */ 674 scratch_addr += 128; /* write to separate cachelines */
@@ -693,11 +687,10 @@ pc_render_add_request(struct intel_ring_buffer *ring,
693 PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE | 687 PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE |
694 PIPE_CONTROL_NOTIFY); 688 PIPE_CONTROL_NOTIFY);
695 intel_ring_emit(ring, pc->gtt_offset | PIPE_CONTROL_GLOBAL_GTT); 689 intel_ring_emit(ring, pc->gtt_offset | PIPE_CONTROL_GLOBAL_GTT);
696 intel_ring_emit(ring, seqno); 690 intel_ring_emit(ring, ring->outstanding_lazy_request);
697 intel_ring_emit(ring, 0); 691 intel_ring_emit(ring, 0);
698 intel_ring_advance(ring); 692 intel_ring_advance(ring);
699 693
700 *result = seqno;
701 return 0; 694 return 0;
702} 695}
703 696
@@ -885,25 +878,20 @@ bsd_ring_flush(struct intel_ring_buffer *ring,
885} 878}
886 879
887static int 880static int
888i9xx_add_request(struct intel_ring_buffer *ring, 881i9xx_add_request(struct intel_ring_buffer *ring)
889 u32 *result)
890{ 882{
891 u32 seqno;
892 int ret; 883 int ret;
893 884
894 ret = intel_ring_begin(ring, 4); 885 ret = intel_ring_begin(ring, 4);
895 if (ret) 886 if (ret)
896 return ret; 887 return ret;
897 888
898 seqno = i915_gem_next_request_seqno(ring);
899
900 intel_ring_emit(ring, MI_STORE_DWORD_INDEX); 889 intel_ring_emit(ring, MI_STORE_DWORD_INDEX);
901 intel_ring_emit(ring, I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT); 890 intel_ring_emit(ring, I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT);
902 intel_ring_emit(ring, seqno); 891 intel_ring_emit(ring, ring->outstanding_lazy_request);
903 intel_ring_emit(ring, MI_USER_INTERRUPT); 892 intel_ring_emit(ring, MI_USER_INTERRUPT);
904 intel_ring_advance(ring); 893 intel_ring_advance(ring);
905 894
906 *result = seqno;
907 return 0; 895 return 0;
908} 896}
909 897
@@ -1110,6 +1098,7 @@ static int intel_init_ring_buffer(struct drm_device *dev,
1110 INIT_LIST_HEAD(&ring->active_list); 1098 INIT_LIST_HEAD(&ring->active_list);
1111 INIT_LIST_HEAD(&ring->request_list); 1099 INIT_LIST_HEAD(&ring->request_list);
1112 ring->size = 32 * PAGE_SIZE; 1100 ring->size = 32 * PAGE_SIZE;
1101 memset(ring->sync_seqno, 0, sizeof(ring->sync_seqno));
1113 1102
1114 init_waitqueue_head(&ring->irq_queue); 1103 init_waitqueue_head(&ring->irq_queue);
1115 1104
@@ -1338,6 +1327,15 @@ int intel_wait_ring_buffer(struct intel_ring_buffer *ring, int n)
1338 return -EBUSY; 1327 return -EBUSY;
1339} 1328}
1340 1329
1330static int
1331intel_ring_alloc_seqno(struct intel_ring_buffer *ring)
1332{
1333 if (ring->outstanding_lazy_request)
1334 return 0;
1335
1336 return i915_gem_get_seqno(ring->dev, &ring->outstanding_lazy_request);
1337}
1338
1341int intel_ring_begin(struct intel_ring_buffer *ring, 1339int intel_ring_begin(struct intel_ring_buffer *ring,
1342 int num_dwords) 1340 int num_dwords)
1343{ 1341{
@@ -1349,6 +1347,11 @@ int intel_ring_begin(struct intel_ring_buffer *ring,
1349 if (ret) 1347 if (ret)
1350 return ret; 1348 return ret;
1351 1349
1350 /* Preallocate the olr before touching the ring */
1351 ret = intel_ring_alloc_seqno(ring);
1352 if (ret)
1353 return ret;
1354
1352 if (unlikely(ring->tail + n > ring->effective_size)) { 1355 if (unlikely(ring->tail + n > ring->effective_size)) {
1353 ret = intel_wrap_ring_buffer(ring); 1356 ret = intel_wrap_ring_buffer(ring);
1354 if (unlikely(ret)) 1357 if (unlikely(ret))