drm/i915: Don't emit semaphore wait if wrap happened
authorMika Kuoppala <mika.kuoppala@linux.intel.com>
Mon, 10 Dec 2012 13:41:48 +0000 (15:41 +0200)
committerDaniel Vetter <daniel.vetter@ffwll.ch>
Tue, 11 Dec 2012 12:32:26 +0000 (13:32 +0100)
If wrap just happened we need to prevent emitting waits for
pre wrap values. Detect this and emit no-ops instead.

v2: Use olr > seqno to detect wrap instead of *seqno == 0
as suggested by Chris Wilson.

v3: Use last used seqno to detect the wraparound. From
Chris Wilson

v4: Fixed unnecessary last_seqno assigment

References: https://bugs.freedesktop.org/show_bug.cgi?id=57967
Signed-off-by: Mika Kuoppala <mika.kuoppala@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/i915_gem.c
drivers/gpu/drm/i915/intel_ringbuffer.c

index 2ab476df1dc20bdb62a540f8267a0ca10a64b981..9da67824dde302866b0ae98e02e0b3370d95c8e3 100644 (file)
@@ -671,7 +671,7 @@ typedef struct drm_i915_private {
 
        struct pci_dev *bridge_dev;
        struct intel_ring_buffer ring[I915_NUM_RINGS];
-       uint32_t next_seqno;
+       uint32_t last_seqno, next_seqno;
 
        drm_dma_handle_t *status_page_dmah;
        struct resource mch_res;
index e4b233df576fe4de89ff793940b4c0330859df60..a81b78a59bd94c94a212e747a8fda50742dd40c7 100644 (file)
@@ -1969,7 +1969,7 @@ i915_gem_get_seqno(struct drm_device *dev, u32 *seqno)
                dev_priv->next_seqno = 1;
        }
 
-       *seqno = dev_priv->next_seqno++;
+       *seqno = dev_priv->last_seqno = dev_priv->next_seqno++;
        return 0;
 }
 
index 0d03dc649c5ef4e8dcc7ac9f04959882635deb36..69bbe7bb9f6d464f190fa27017aa84aa2a2246f2 100644 (file)
@@ -596,6 +596,13 @@ gen6_add_request(struct intel_ring_buffer *ring)
        return 0;
 }
 
+static inline bool i915_gem_has_seqno_wrapped(struct drm_device *dev,
+                                             u32 seqno)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       return dev_priv->last_seqno < seqno;
+}
+
 /**
  * intel_ring_sync - sync the waiter to the signaller on seqno
  *
@@ -626,11 +633,20 @@ gen6_ring_sync(struct intel_ring_buffer *waiter,
        if (ret)
                return ret;
 
-       intel_ring_emit(waiter,
-                       dw1 | signaller->semaphore_register[waiter->id]);
-       intel_ring_emit(waiter, seqno);
-       intel_ring_emit(waiter, 0);
-       intel_ring_emit(waiter, MI_NOOP);
+       /* If seqno wrap happened, omit the wait with no-ops */
+       if (likely(!i915_gem_has_seqno_wrapped(waiter->dev, seqno))) {
+               intel_ring_emit(waiter,
+                               dw1 |
+                               signaller->semaphore_register[waiter->id]);
+               intel_ring_emit(waiter, seqno);
+               intel_ring_emit(waiter, 0);
+               intel_ring_emit(waiter, MI_NOOP);
+       } else {
+               intel_ring_emit(waiter, MI_NOOP);
+               intel_ring_emit(waiter, MI_NOOP);
+               intel_ring_emit(waiter, MI_NOOP);
+               intel_ring_emit(waiter, MI_NOOP);
+       }
        intel_ring_advance(waiter);
 
        return 0;