diff options
Diffstat (limited to 'drivers/gpu/drm/i915/intel_ringbuffer.c')
-rw-r--r-- | drivers/gpu/drm/i915/intel_ringbuffer.c | 103 |
1 files changed, 58 insertions, 45 deletions
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 26362f8495a8..51e9c9e718c4 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c | |||
@@ -33,18 +33,35 @@ | |||
33 | #include "i915_drm.h" | 33 | #include "i915_drm.h" |
34 | #include "i915_trace.h" | 34 | #include "i915_trace.h" |
35 | 35 | ||
36 | static u32 i915_gem_get_seqno(struct drm_device *dev) | ||
37 | { | ||
38 | drm_i915_private_t *dev_priv = dev->dev_private; | ||
39 | u32 seqno; | ||
40 | |||
41 | seqno = dev_priv->next_seqno; | ||
42 | |||
43 | /* reserve 0 for non-seqno */ | ||
44 | if (++dev_priv->next_seqno == 0) | ||
45 | dev_priv->next_seqno = 1; | ||
46 | |||
47 | return seqno; | ||
48 | } | ||
49 | |||
36 | static void | 50 | static void |
37 | render_ring_flush(struct drm_device *dev, | 51 | render_ring_flush(struct drm_device *dev, |
38 | struct intel_ring_buffer *ring, | 52 | struct intel_ring_buffer *ring, |
39 | u32 invalidate_domains, | 53 | u32 invalidate_domains, |
40 | u32 flush_domains) | 54 | u32 flush_domains) |
41 | { | 55 | { |
56 | drm_i915_private_t *dev_priv = dev->dev_private; | ||
57 | u32 cmd; | ||
58 | |||
42 | #if WATCH_EXEC | 59 | #if WATCH_EXEC |
43 | DRM_INFO("%s: invalidate %08x flush %08x\n", __func__, | 60 | DRM_INFO("%s: invalidate %08x flush %08x\n", __func__, |
44 | invalidate_domains, flush_domains); | 61 | invalidate_domains, flush_domains); |
45 | #endif | 62 | #endif |
46 | u32 cmd; | 63 | |
47 | trace_i915_gem_request_flush(dev, ring->next_seqno, | 64 | trace_i915_gem_request_flush(dev, dev_priv->next_seqno, |
48 | invalidate_domains, flush_domains); | 65 | invalidate_domains, flush_domains); |
49 | 66 | ||
50 | if ((invalidate_domains | flush_domains) & I915_GEM_GPU_DOMAINS) { | 67 | if ((invalidate_domains | flush_domains) & I915_GEM_GPU_DOMAINS) { |
@@ -233,9 +250,10 @@ render_ring_add_request(struct drm_device *dev, | |||
233 | struct drm_file *file_priv, | 250 | struct drm_file *file_priv, |
234 | u32 flush_domains) | 251 | u32 flush_domains) |
235 | { | 252 | { |
236 | u32 seqno; | ||
237 | drm_i915_private_t *dev_priv = dev->dev_private; | 253 | drm_i915_private_t *dev_priv = dev->dev_private; |
238 | seqno = intel_ring_get_seqno(dev, ring); | 254 | u32 seqno; |
255 | |||
256 | seqno = i915_gem_get_seqno(dev); | ||
239 | 257 | ||
240 | if (IS_GEN6(dev)) { | 258 | if (IS_GEN6(dev)) { |
241 | BEGIN_LP_RING(6); | 259 | BEGIN_LP_RING(6); |
@@ -405,7 +423,9 @@ bsd_ring_add_request(struct drm_device *dev, | |||
405 | u32 flush_domains) | 423 | u32 flush_domains) |
406 | { | 424 | { |
407 | u32 seqno; | 425 | u32 seqno; |
408 | seqno = intel_ring_get_seqno(dev, ring); | 426 | |
427 | seqno = i915_gem_get_seqno(dev); | ||
428 | |||
409 | intel_ring_begin(dev, ring, 4); | 429 | intel_ring_begin(dev, ring, 4); |
410 | intel_ring_emit(dev, ring, MI_STORE_DWORD_INDEX); | 430 | intel_ring_emit(dev, ring, MI_STORE_DWORD_INDEX); |
411 | intel_ring_emit(dev, ring, | 431 | intel_ring_emit(dev, ring, |
@@ -479,7 +499,7 @@ render_ring_dispatch_gem_execbuffer(struct drm_device *dev, | |||
479 | exec_start = (uint32_t) exec_offset + exec->batch_start_offset; | 499 | exec_start = (uint32_t) exec_offset + exec->batch_start_offset; |
480 | exec_len = (uint32_t) exec->batch_len; | 500 | exec_len = (uint32_t) exec->batch_len; |
481 | 501 | ||
482 | trace_i915_gem_request_submit(dev, dev_priv->mm.next_gem_seqno + 1); | 502 | trace_i915_gem_request_submit(dev, dev_priv->next_seqno + 1); |
483 | 503 | ||
484 | count = nbox ? nbox : 1; | 504 | count = nbox ? nbox : 1; |
485 | 505 | ||
@@ -515,7 +535,16 @@ render_ring_dispatch_gem_execbuffer(struct drm_device *dev, | |||
515 | intel_ring_advance(dev, ring); | 535 | intel_ring_advance(dev, ring); |
516 | } | 536 | } |
517 | 537 | ||
538 | if (IS_G4X(dev) || IS_IRONLAKE(dev)) { | ||
539 | intel_ring_begin(dev, ring, 2); | ||
540 | intel_ring_emit(dev, ring, MI_FLUSH | | ||
541 | MI_NO_WRITE_FLUSH | | ||
542 | MI_INVALIDATE_ISP ); | ||
543 | intel_ring_emit(dev, ring, MI_NOOP); | ||
544 | intel_ring_advance(dev, ring); | ||
545 | } | ||
518 | /* XXX breadcrumb */ | 546 | /* XXX breadcrumb */ |
547 | |||
519 | return 0; | 548 | return 0; |
520 | } | 549 | } |
521 | 550 | ||
@@ -588,9 +617,10 @@ err: | |||
588 | int intel_init_ring_buffer(struct drm_device *dev, | 617 | int intel_init_ring_buffer(struct drm_device *dev, |
589 | struct intel_ring_buffer *ring) | 618 | struct intel_ring_buffer *ring) |
590 | { | 619 | { |
591 | int ret; | ||
592 | struct drm_i915_gem_object *obj_priv; | 620 | struct drm_i915_gem_object *obj_priv; |
593 | struct drm_gem_object *obj; | 621 | struct drm_gem_object *obj; |
622 | int ret; | ||
623 | |||
594 | ring->dev = dev; | 624 | ring->dev = dev; |
595 | 625 | ||
596 | if (I915_NEED_GFX_HWS(dev)) { | 626 | if (I915_NEED_GFX_HWS(dev)) { |
@@ -603,16 +633,14 @@ int intel_init_ring_buffer(struct drm_device *dev, | |||
603 | if (obj == NULL) { | 633 | if (obj == NULL) { |
604 | DRM_ERROR("Failed to allocate ringbuffer\n"); | 634 | DRM_ERROR("Failed to allocate ringbuffer\n"); |
605 | ret = -ENOMEM; | 635 | ret = -ENOMEM; |
606 | goto cleanup; | 636 | goto err_hws; |
607 | } | 637 | } |
608 | 638 | ||
609 | ring->gem_object = obj; | 639 | ring->gem_object = obj; |
610 | 640 | ||
611 | ret = i915_gem_object_pin(obj, ring->alignment); | 641 | ret = i915_gem_object_pin(obj, ring->alignment); |
612 | if (ret != 0) { | 642 | if (ret) |
613 | drm_gem_object_unreference(obj); | 643 | goto err_unref; |
614 | goto cleanup; | ||
615 | } | ||
616 | 644 | ||
617 | obj_priv = to_intel_bo(obj); | 645 | obj_priv = to_intel_bo(obj); |
618 | ring->map.size = ring->size; | 646 | ring->map.size = ring->size; |
@@ -624,18 +652,14 @@ int intel_init_ring_buffer(struct drm_device *dev, | |||
624 | drm_core_ioremap_wc(&ring->map, dev); | 652 | drm_core_ioremap_wc(&ring->map, dev); |
625 | if (ring->map.handle == NULL) { | 653 | if (ring->map.handle == NULL) { |
626 | DRM_ERROR("Failed to map ringbuffer.\n"); | 654 | DRM_ERROR("Failed to map ringbuffer.\n"); |
627 | i915_gem_object_unpin(obj); | ||
628 | drm_gem_object_unreference(obj); | ||
629 | ret = -EINVAL; | 655 | ret = -EINVAL; |
630 | goto cleanup; | 656 | goto err_unpin; |
631 | } | 657 | } |
632 | 658 | ||
633 | ring->virtual_start = ring->map.handle; | 659 | ring->virtual_start = ring->map.handle; |
634 | ret = ring->init(dev, ring); | 660 | ret = ring->init(dev, ring); |
635 | if (ret != 0) { | 661 | if (ret) |
636 | intel_cleanup_ring_buffer(dev, ring); | 662 | goto err_unmap; |
637 | return ret; | ||
638 | } | ||
639 | 663 | ||
640 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) | 664 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) |
641 | i915_kernel_lost_context(dev); | 665 | i915_kernel_lost_context(dev); |
@@ -649,7 +673,15 @@ int intel_init_ring_buffer(struct drm_device *dev, | |||
649 | INIT_LIST_HEAD(&ring->active_list); | 673 | INIT_LIST_HEAD(&ring->active_list); |
650 | INIT_LIST_HEAD(&ring->request_list); | 674 | INIT_LIST_HEAD(&ring->request_list); |
651 | return ret; | 675 | return ret; |
652 | cleanup: | 676 | |
677 | err_unmap: | ||
678 | drm_core_ioremapfree(&ring->map, dev); | ||
679 | err_unpin: | ||
680 | i915_gem_object_unpin(obj); | ||
681 | err_unref: | ||
682 | drm_gem_object_unreference(obj); | ||
683 | ring->gem_object = NULL; | ||
684 | err_hws: | ||
653 | cleanup_status_page(dev, ring); | 685 | cleanup_status_page(dev, ring); |
654 | return ret; | 686 | return ret; |
655 | } | 687 | } |
@@ -682,9 +714,11 @@ int intel_wrap_ring_buffer(struct drm_device *dev, | |||
682 | } | 714 | } |
683 | 715 | ||
684 | virt = (unsigned int *)(ring->virtual_start + ring->tail); | 716 | virt = (unsigned int *)(ring->virtual_start + ring->tail); |
685 | rem /= 4; | 717 | rem /= 8; |
686 | while (rem--) | 718 | while (rem--) { |
719 | *virt++ = MI_NOOP; | ||
687 | *virt++ = MI_NOOP; | 720 | *virt++ = MI_NOOP; |
721 | } | ||
688 | 722 | ||
689 | ring->tail = 0; | 723 | ring->tail = 0; |
690 | ring->space = ring->head - 8; | 724 | ring->space = ring->head - 8; |
@@ -729,21 +763,14 @@ void intel_ring_begin(struct drm_device *dev, | |||
729 | intel_wrap_ring_buffer(dev, ring); | 763 | intel_wrap_ring_buffer(dev, ring); |
730 | if (unlikely(ring->space < n)) | 764 | if (unlikely(ring->space < n)) |
731 | intel_wait_ring_buffer(dev, ring, n); | 765 | intel_wait_ring_buffer(dev, ring, n); |
732 | } | ||
733 | 766 | ||
734 | void intel_ring_emit(struct drm_device *dev, | 767 | ring->space -= n; |
735 | struct intel_ring_buffer *ring, unsigned int data) | ||
736 | { | ||
737 | unsigned int *virt = ring->virtual_start + ring->tail; | ||
738 | *virt = data; | ||
739 | ring->tail += 4; | ||
740 | ring->tail &= ring->size - 1; | ||
741 | ring->space -= 4; | ||
742 | } | 768 | } |
743 | 769 | ||
744 | void intel_ring_advance(struct drm_device *dev, | 770 | void intel_ring_advance(struct drm_device *dev, |
745 | struct intel_ring_buffer *ring) | 771 | struct intel_ring_buffer *ring) |
746 | { | 772 | { |
773 | ring->tail &= ring->size - 1; | ||
747 | ring->advance_ring(dev, ring); | 774 | ring->advance_ring(dev, ring); |
748 | } | 775 | } |
749 | 776 | ||
@@ -762,18 +789,6 @@ void intel_fill_struct(struct drm_device *dev, | |||
762 | intel_ring_advance(dev, ring); | 789 | intel_ring_advance(dev, ring); |
763 | } | 790 | } |
764 | 791 | ||
765 | u32 intel_ring_get_seqno(struct drm_device *dev, | ||
766 | struct intel_ring_buffer *ring) | ||
767 | { | ||
768 | u32 seqno; | ||
769 | seqno = ring->next_seqno; | ||
770 | |||
771 | /* reserve 0 for non-seqno */ | ||
772 | if (++ring->next_seqno == 0) | ||
773 | ring->next_seqno = 1; | ||
774 | return seqno; | ||
775 | } | ||
776 | |||
777 | struct intel_ring_buffer render_ring = { | 792 | struct intel_ring_buffer render_ring = { |
778 | .name = "render ring", | 793 | .name = "render ring", |
779 | .regs = { | 794 | .regs = { |
@@ -791,7 +806,6 @@ struct intel_ring_buffer render_ring = { | |||
791 | .head = 0, | 806 | .head = 0, |
792 | .tail = 0, | 807 | .tail = 0, |
793 | .space = 0, | 808 | .space = 0, |
794 | .next_seqno = 1, | ||
795 | .user_irq_refcount = 0, | 809 | .user_irq_refcount = 0, |
796 | .irq_gem_seqno = 0, | 810 | .irq_gem_seqno = 0, |
797 | .waiting_gem_seqno = 0, | 811 | .waiting_gem_seqno = 0, |
@@ -830,7 +844,6 @@ struct intel_ring_buffer bsd_ring = { | |||
830 | .head = 0, | 844 | .head = 0, |
831 | .tail = 0, | 845 | .tail = 0, |
832 | .space = 0, | 846 | .space = 0, |
833 | .next_seqno = 1, | ||
834 | .user_irq_refcount = 0, | 847 | .user_irq_refcount = 0, |
835 | .irq_gem_seqno = 0, | 848 | .irq_gem_seqno = 0, |
836 | .waiting_gem_seqno = 0, | 849 | .waiting_gem_seqno = 0, |