aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/intel_ringbuffer.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/i915/intel_ringbuffer.c')
-rw-r--r--drivers/gpu/drm/i915/intel_ringbuffer.c129
1 files changed, 125 insertions, 4 deletions
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c
index 09f2dc353ae2..b83306f9244b 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.c
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.c
@@ -177,7 +177,7 @@ static int init_ring_common(struct drm_device *dev,
177 177
178 I915_WRITE_CTL(ring, 178 I915_WRITE_CTL(ring,
179 ((ring->gem_object->size - PAGE_SIZE) & RING_NR_PAGES) 179 ((ring->gem_object->size - PAGE_SIZE) & RING_NR_PAGES)
180 | RING_NO_REPORT | RING_VALID); 180 | RING_REPORT_64K | RING_VALID);
181 181
182 head = I915_READ_HEAD(ring) & HEAD_ADDR; 182 head = I915_READ_HEAD(ring) & HEAD_ADDR;
183 /* If the head is still not zero, the ring is dead */ 183 /* If the head is still not zero, the ring is dead */
@@ -654,6 +654,10 @@ void intel_cleanup_ring_buffer(struct drm_device *dev,
654 i915_gem_object_unpin(ring->gem_object); 654 i915_gem_object_unpin(ring->gem_object);
655 drm_gem_object_unreference(ring->gem_object); 655 drm_gem_object_unreference(ring->gem_object);
656 ring->gem_object = NULL; 656 ring->gem_object = NULL;
657
658 if (ring->cleanup)
659 ring->cleanup(ring);
660
657 cleanup_status_page(dev, ring); 661 cleanup_status_page(dev, ring);
658} 662}
659 663
@@ -688,6 +692,17 @@ int intel_wait_ring_buffer(struct drm_device *dev,
688{ 692{
689 unsigned long end; 693 unsigned long end;
690 drm_i915_private_t *dev_priv = dev->dev_private; 694 drm_i915_private_t *dev_priv = dev->dev_private;
695 u32 head;
696
697 head = intel_read_status_page(ring, 4);
698 if (head) {
699 ring->head = head & HEAD_ADDR;
700 ring->space = ring->head - (ring->tail + 8);
701 if (ring->space < 0)
702 ring->space += ring->size;
703 if (ring->space >= n)
704 return 0;
705 }
691 706
692 trace_i915_ring_wait_begin (dev); 707 trace_i915_ring_wait_begin (dev);
693 end = jiffies + 3 * HZ; 708 end = jiffies + 3 * HZ;
@@ -854,19 +869,125 @@ blt_ring_put_user_irq(struct drm_device *dev,
854 /* do nothing */ 869 /* do nothing */
855} 870}
856 871
872
873/* Workaround for some stepping of SNB,
874 * each time when BLT engine ring tail moved,
875 * the first command in the ring to be parsed
876 * should be MI_BATCH_BUFFER_START
877 */
878#define NEED_BLT_WORKAROUND(dev) \
879 (IS_GEN6(dev) && (dev->pdev->revision < 8))
880
881static inline struct drm_i915_gem_object *
882to_blt_workaround(struct intel_ring_buffer *ring)
883{
884 return ring->private;
885}
886
887static int blt_ring_init(struct drm_device *dev,
888 struct intel_ring_buffer *ring)
889{
890 if (NEED_BLT_WORKAROUND(dev)) {
891 struct drm_i915_gem_object *obj;
892 u32 __iomem *ptr;
893 int ret;
894
895 obj = to_intel_bo(i915_gem_alloc_object(dev, 4096));
896 if (obj == NULL)
897 return -ENOMEM;
898
899 ret = i915_gem_object_pin(&obj->base, 4096);
900 if (ret) {
901 drm_gem_object_unreference(&obj->base);
902 return ret;
903 }
904
905 ptr = kmap(obj->pages[0]);
906 iowrite32(MI_BATCH_BUFFER_END, ptr);
907 iowrite32(MI_NOOP, ptr+1);
908 kunmap(obj->pages[0]);
909
910 ret = i915_gem_object_set_to_gtt_domain(&obj->base, false);
911 if (ret) {
912 i915_gem_object_unpin(&obj->base);
913 drm_gem_object_unreference(&obj->base);
914 return ret;
915 }
916
917 ring->private = obj;
918 }
919
920 return init_ring_common(dev, ring);
921}
922
923static void blt_ring_begin(struct drm_device *dev,
924 struct intel_ring_buffer *ring,
925 int num_dwords)
926{
927 if (ring->private) {
928 intel_ring_begin(dev, ring, num_dwords+2);
929 intel_ring_emit(dev, ring, MI_BATCH_BUFFER_START);
930 intel_ring_emit(dev, ring, to_blt_workaround(ring)->gtt_offset);
931 } else
932 intel_ring_begin(dev, ring, 4);
933}
934
935static void blt_ring_flush(struct drm_device *dev,
936 struct intel_ring_buffer *ring,
937 u32 invalidate_domains,
938 u32 flush_domains)
939{
940 blt_ring_begin(dev, ring, 4);
941 intel_ring_emit(dev, ring, MI_FLUSH_DW);
942 intel_ring_emit(dev, ring, 0);
943 intel_ring_emit(dev, ring, 0);
944 intel_ring_emit(dev, ring, 0);
945 intel_ring_advance(dev, ring);
946}
947
948static u32
949blt_ring_add_request(struct drm_device *dev,
950 struct intel_ring_buffer *ring,
951 u32 flush_domains)
952{
953 u32 seqno = i915_gem_get_seqno(dev);
954
955 blt_ring_begin(dev, ring, 4);
956 intel_ring_emit(dev, ring, MI_STORE_DWORD_INDEX);
957 intel_ring_emit(dev, ring,
958 I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT);
959 intel_ring_emit(dev, ring, seqno);
960 intel_ring_emit(dev, ring, MI_USER_INTERRUPT);
961 intel_ring_advance(dev, ring);
962
963 DRM_DEBUG_DRIVER("%s %d\n", ring->name, seqno);
964 return seqno;
965}
966
967static void blt_ring_cleanup(struct intel_ring_buffer *ring)
968{
969 if (!ring->private)
970 return;
971
972 i915_gem_object_unpin(ring->private);
973 drm_gem_object_unreference(ring->private);
974 ring->private = NULL;
975}
976
857static const struct intel_ring_buffer gen6_blt_ring = { 977static const struct intel_ring_buffer gen6_blt_ring = {
858 .name = "blt ring", 978 .name = "blt ring",
859 .id = RING_BLT, 979 .id = RING_BLT,
860 .mmio_base = BLT_RING_BASE, 980 .mmio_base = BLT_RING_BASE,
861 .size = 32 * PAGE_SIZE, 981 .size = 32 * PAGE_SIZE,
862 .init = init_ring_common, 982 .init = blt_ring_init,
863 .write_tail = ring_write_tail, 983 .write_tail = ring_write_tail,
864 .flush = gen6_ring_flush, 984 .flush = blt_ring_flush,
865 .add_request = ring_add_request, 985 .add_request = blt_ring_add_request,
866 .get_seqno = ring_status_page_get_seqno, 986 .get_seqno = ring_status_page_get_seqno,
867 .user_irq_get = blt_ring_get_user_irq, 987 .user_irq_get = blt_ring_get_user_irq,
868 .user_irq_put = blt_ring_put_user_irq, 988 .user_irq_put = blt_ring_put_user_irq,
869 .dispatch_gem_execbuffer = gen6_ring_dispatch_gem_execbuffer, 989 .dispatch_gem_execbuffer = gen6_ring_dispatch_gem_execbuffer,
990 .cleanup = blt_ring_cleanup,
870}; 991};
871 992
872int intel_init_render_ring_buffer(struct drm_device *dev) 993int intel_init_render_ring_buffer(struct drm_device *dev)