drm: Merge tag 'v3.3-rc7' into drm-core-next
[pandora-kernel.git] / drivers / gpu / drm / i915 / intel_ringbuffer.c
index 5361915..fc66af6 100644 (file)
@@ -52,20 +52,6 @@ static inline int ring_space(struct intel_ring_buffer *ring)
        return space;
 }
 
-static u32 i915_gem_get_seqno(struct drm_device *dev)
-{
-       drm_i915_private_t *dev_priv = dev->dev_private;
-       u32 seqno;
-
-       seqno = dev_priv->next_seqno;
-
-       /* reserve 0 for non-seqno */
-       if (++dev_priv->next_seqno == 0)
-               dev_priv->next_seqno = 1;
-
-       return seqno;
-}
-
 static int
 render_ring_flush(struct intel_ring_buffer *ring,
                  u32   invalidate_domains,
@@ -399,8 +385,6 @@ static int init_render_ring(struct intel_ring_buffer *ring)
 
        if (INTEL_INFO(dev)->gen > 3) {
                int mode = VS_TIMER_DISPATCH << 16 | VS_TIMER_DISPATCH;
-               if (IS_GEN6(dev) || IS_GEN7(dev))
-                       mode |= MI_FLUSH_ENABLE << 16 | MI_FLUSH_ENABLE;
                I915_WRITE(MI_MODE, mode);
                if (IS_GEN7(dev))
                        I915_WRITE(GFX_MODE_GEN7,
@@ -467,7 +451,7 @@ gen6_add_request(struct intel_ring_buffer *ring,
        mbox1_reg = ring->signal_mbox[0];
        mbox2_reg = ring->signal_mbox[1];
 
-       *seqno = i915_gem_get_seqno(ring->dev);
+       *seqno = i915_gem_next_request_seqno(ring);
 
        update_mboxes(ring, *seqno, mbox1_reg);
        update_mboxes(ring, *seqno, mbox2_reg);
@@ -565,8 +549,7 @@ static int
 pc_render_add_request(struct intel_ring_buffer *ring,
                      u32 *result)
 {
-       struct drm_device *dev = ring->dev;
-       u32 seqno = i915_gem_get_seqno(dev);
+       u32 seqno = i915_gem_next_request_seqno(ring);
        struct pipe_control *pc = ring->private;
        u32 scratch_addr = pc->gtt_offset + 128;
        int ret;
@@ -600,6 +583,7 @@ pc_render_add_request(struct intel_ring_buffer *ring,
        PIPE_CONTROL_FLUSH(ring, scratch_addr);
        scratch_addr += 128;
        PIPE_CONTROL_FLUSH(ring, scratch_addr);
+
        intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(4) | PIPE_CONTROL_QW_WRITE |
                        PIPE_CONTROL_WRITE_FLUSH |
                        PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE |
@@ -617,8 +601,7 @@ static int
 render_ring_add_request(struct intel_ring_buffer *ring,
                        u32 *result)
 {
-       struct drm_device *dev = ring->dev;
-       u32 seqno = i915_gem_get_seqno(dev);
+       u32 seqno = i915_gem_next_request_seqno(ring);
        int ret;
 
        ret = intel_ring_begin(ring, 4);
@@ -744,13 +727,13 @@ void intel_ring_setup_status_page(struct intel_ring_buffer *ring)
         */
        if (IS_GEN7(dev)) {
                switch (ring->id) {
-               case RING_RENDER:
+               case RCS:
                        mmio = RENDER_HWS_PGA_GEN7;
                        break;
-               case RING_BLT:
+               case BCS:
                        mmio = BLT_HWS_PGA_GEN7;
                        break;
-               case RING_BSD:
+               case VCS:
                        mmio = BSD_HWS_PGA_GEN7;
                        break;
                }
@@ -792,7 +775,7 @@ ring_add_request(struct intel_ring_buffer *ring,
        if (ret)
                return ret;
 
-       seqno = i915_gem_get_seqno(ring->dev);
+       seqno = i915_gem_next_request_seqno(ring);
 
        intel_ring_emit(ring, MI_STORE_DWORD_INDEX);
        intel_ring_emit(ring, I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT);
@@ -816,8 +799,7 @@ gen6_ring_get_irq(struct intel_ring_buffer *ring, u32 gflag, u32 rflag)
        /* It looks like we need to prevent the gt from suspending while waiting
         * for an notifiy irq, otherwise irqs seem to get lost on at least the
         * blt/bsd rings on ivb. */
-       if (IS_GEN7(dev))
-               gen6_gt_force_wake_get(dev_priv);
+       gen6_gt_force_wake_get(dev_priv);
 
        spin_lock(&ring->irq_lock);
        if (ring->irq_refcount++ == 0) {
@@ -844,8 +826,7 @@ gen6_ring_put_irq(struct intel_ring_buffer *ring, u32 gflag, u32 rflag)
        }
        spin_unlock(&ring->irq_lock);
 
-       if (IS_GEN7(dev))
-               gen6_gt_force_wake_put(dev_priv);
+       gen6_gt_force_wake_put(dev_priv);
 }
 
 static bool
@@ -1127,11 +1108,93 @@ static int intel_wrap_ring_buffer(struct intel_ring_buffer *ring)
        return 0;
 }
 
+static int intel_ring_wait_seqno(struct intel_ring_buffer *ring, u32 seqno)
+{
+       struct drm_i915_private *dev_priv = ring->dev->dev_private;
+       bool was_interruptible;
+       int ret;
+
+       /* XXX As we have not yet audited all the paths to check that
+        * they are ready for ERESTARTSYS from intel_ring_begin, do not
+        * allow us to be interruptible by a signal.
+        */
+       was_interruptible = dev_priv->mm.interruptible;
+       dev_priv->mm.interruptible = false;
+
+       ret = i915_wait_request(ring, seqno, true);
+
+       dev_priv->mm.interruptible = was_interruptible;
+
+       return ret;
+}
+
+static int intel_ring_wait_request(struct intel_ring_buffer *ring, int n)
+{
+       struct drm_i915_gem_request *request;
+       u32 seqno = 0;
+       int ret;
+
+       i915_gem_retire_requests_ring(ring);
+
+       if (ring->last_retired_head != -1) {
+               ring->head = ring->last_retired_head;
+               ring->last_retired_head = -1;
+               ring->space = ring_space(ring);
+               if (ring->space >= n)
+                       return 0;
+       }
+
+       list_for_each_entry(request, &ring->request_list, list) {
+               int space;
+
+               if (request->tail == -1)
+                       continue;
+
+               space = request->tail - (ring->tail + 8);
+               if (space < 0)
+                       space += ring->size;
+               if (space >= n) {
+                       seqno = request->seqno;
+                       break;
+               }
+
+               /* Consume this request in case we need more space than
+                * is available and so need to prevent a race between
+                * updating last_retired_head and direct reads of
+                * I915_RING_HEAD. It also provides a nice sanity check.
+                */
+               request->tail = -1;
+       }
+
+       if (seqno == 0)
+               return -ENOSPC;
+
+       ret = intel_ring_wait_seqno(ring, seqno);
+       if (ret)
+               return ret;
+
+       if (WARN_ON(ring->last_retired_head == -1))
+               return -ENOSPC;
+
+       ring->head = ring->last_retired_head;
+       ring->last_retired_head = -1;
+       ring->space = ring_space(ring);
+       if (WARN_ON(ring->space < n))
+               return -ENOSPC;
+
+       return 0;
+}
+
 int intel_wait_ring_buffer(struct intel_ring_buffer *ring, int n)
 {
        struct drm_device *dev = ring->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        unsigned long end;
+       int ret;
+
+       ret = intel_ring_wait_request(ring, n);
+       if (ret != -ENOSPC)
+               return ret;
 
        trace_i915_ring_wait_begin(ring);
        if (drm_core_check_feature(dev, DRIVER_GEM))
@@ -1200,7 +1263,7 @@ void intel_ring_advance(struct intel_ring_buffer *ring)
 
 static const struct intel_ring_buffer render_ring = {
        .name                   = "render ring",
-       .id                     = RING_RENDER,
+       .id                     = RCS,
        .mmio_base              = RENDER_RING_BASE,
        .size                   = 32 * PAGE_SIZE,
        .init                   = init_render_ring,
@@ -1223,7 +1286,7 @@ static const struct intel_ring_buffer render_ring = {
 
 static const struct intel_ring_buffer bsd_ring = {
        .name                   = "bsd ring",
-       .id                     = RING_BSD,
+       .id                     = VCS,
        .mmio_base              = BSD_RING_BASE,
        .size                   = 32 * PAGE_SIZE,
        .init                   = init_ring_common,
@@ -1333,7 +1396,7 @@ gen6_bsd_ring_put_irq(struct intel_ring_buffer *ring)
 /* ring buffer for Video Codec for Gen6+ */
 static const struct intel_ring_buffer gen6_bsd_ring = {
        .name                   = "gen6 bsd ring",
-       .id                     = RING_BSD,
+       .id                     = VCS,
        .mmio_base              = GEN6_BSD_RING_BASE,
        .size                   = 32 * PAGE_SIZE,
        .init                   = init_ring_common,
@@ -1369,79 +1432,13 @@ blt_ring_put_irq(struct intel_ring_buffer *ring)
                          GEN6_BLITTER_USER_INTERRUPT);
 }
 
-
-/* Workaround for some stepping of SNB,
- * each time when BLT engine ring tail moved,
- * the first command in the ring to be parsed
- * should be MI_BATCH_BUFFER_START
- */
-#define NEED_BLT_WORKAROUND(dev) \
-       (IS_GEN6(dev) && (dev->pdev->revision < 8))
-
-static inline struct drm_i915_gem_object *
-to_blt_workaround(struct intel_ring_buffer *ring)
-{
-       return ring->private;
-}
-
-static int blt_ring_init(struct intel_ring_buffer *ring)
-{
-       if (NEED_BLT_WORKAROUND(ring->dev)) {
-               struct drm_i915_gem_object *obj;
-               u32 *ptr;
-               int ret;
-
-               obj = i915_gem_alloc_object(ring->dev, 4096);
-               if (obj == NULL)
-                       return -ENOMEM;
-
-               ret = i915_gem_object_pin(obj, 4096, true);
-               if (ret) {
-                       drm_gem_object_unreference(&obj->base);
-                       return ret;
-               }
-
-               ptr = kmap(obj->pages[0]);
-               *ptr++ = MI_BATCH_BUFFER_END;
-               *ptr++ = MI_NOOP;
-               kunmap(obj->pages[0]);
-
-               ret = i915_gem_object_set_to_gtt_domain(obj, false);
-               if (ret) {
-                       i915_gem_object_unpin(obj);
-                       drm_gem_object_unreference(&obj->base);
-                       return ret;
-               }
-
-               ring->private = obj;
-       }
-
-       return init_ring_common(ring);
-}
-
-static int blt_ring_begin(struct intel_ring_buffer *ring,
-                         int num_dwords)
-{
-       if (ring->private) {
-               int ret = intel_ring_begin(ring, num_dwords+2);
-               if (ret)
-                       return ret;
-
-               intel_ring_emit(ring, MI_BATCH_BUFFER_START);
-               intel_ring_emit(ring, to_blt_workaround(ring)->gtt_offset);
-
-               return 0;
-       } else
-               return intel_ring_begin(ring, 4);
-}
-
 static int blt_ring_flush(struct intel_ring_buffer *ring,
                          u32 invalidate, u32 flush)
 {
        uint32_t cmd;
        int ret;
 
-       ret = blt_ring_begin(ring, 4);
+       ret = intel_ring_begin(ring, 4);
        if (ret)
                return ret;
 
@@ -1456,22 +1453,12 @@ static int blt_ring_flush(struct intel_ring_buffer *ring,
        return 0;
 }
 
-static void blt_ring_cleanup(struct intel_ring_buffer *ring)
-{
-       if (!ring->private)
-               return;
-
-       i915_gem_object_unpin(ring->private);
-       drm_gem_object_unreference(ring->private);
-       ring->private = NULL;
-}
-
 static const struct intel_ring_buffer gen6_blt_ring = {
        .name                   = "blt ring",
-       .id                     = RING_BLT,
+       .id                     = BCS,
        .mmio_base              = BLT_RING_BASE,
        .size                   = 32 * PAGE_SIZE,
-       .init                   = blt_ring_init,
+       .init                   = init_ring_common,
        .write_tail             = ring_write_tail,
        .flush                  = blt_ring_flush,
        .add_request            = gen6_add_request,
@@ -1479,7 +1466,6 @@ static const struct intel_ring_buffer gen6_blt_ring = {
        .irq_get                = blt_ring_get_irq,
        .irq_put                = blt_ring_put_irq,
        .dispatch_execbuffer    = gen6_ring_dispatch_execbuffer,
-       .cleanup                = blt_ring_cleanup,
        .sync_to                = gen6_blt_ring_sync_to,
        .semaphore_register     = {MI_SEMAPHORE_SYNC_BR,
                                   MI_SEMAPHORE_SYNC_BV,