diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2012-11-27 11:22:52 -0500 |
---|---|---|
committer | Daniel Vetter <daniel.vetter@ffwll.ch> | 2012-11-29 05:43:52 -0500 |
commit | 9d7730914f4cd496e356acfab95b41075aa8eae8 (patch) | |
tree | 509e4ad7d5b7f32e3118fca228ce2f034403d634 /drivers/gpu/drm/i915/intel_ringbuffer.c | |
parent | 45e2b5f640b3766da3eda48f6c35f088155c06f3 (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.c | 49 |
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 | ||
556 | static void | 556 | static void |
557 | update_mboxes(struct intel_ring_buffer *ring, | 557 | update_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 | */ |
575 | static int | 574 | static int |
576 | gen6_add_request(struct intel_ring_buffer *ring, | 575 | gen6_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 | ||
652 | static int | 648 | static int |
653 | pc_render_add_request(struct intel_ring_buffer *ring, | 649 | pc_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 | ||
887 | static int | 880 | static int |
888 | i9xx_add_request(struct intel_ring_buffer *ring, | 881 | i9xx_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 | ||
1330 | static int | ||
1331 | intel_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 | |||
1341 | int intel_ring_begin(struct intel_ring_buffer *ring, | 1339 | int 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)) |