i915: Re-report breadcrumbs on poll to the fence manager,
authorThomas Hellstrom <thomas-at-tungstengraphics-dot-com>
Tue, 5 Feb 2008 09:35:56 +0000 (10:35 +0100)
committerThomas Hellstrom <thomas-at-tungstengraphics-dot-com>
Tue, 5 Feb 2008 09:36:49 +0000 (10:36 +0100)
since a breadcrumb may actually turn up before a corresponding fence object
has been placed on the fence ring.

linux-core/i915_fence.c
shared-core/i915_dma.c
shared-core/i915_drv.h

index 8a2e7f1..de64a4f 100644 (file)
  * Initiate a sync flush if it's not already pending.
  */
 
-static void i915_initiate_rwflush(struct drm_i915_private *dev_priv, 
-                                 struct drm_fence_class_manager *fc)
+static inline void i915_initiate_rwflush(struct drm_i915_private *dev_priv,
+                                        struct drm_fence_class_manager *fc)
 {
-       if ((fc->pending_flush & DRM_I915_FENCE_TYPE_RW) && 
+       if ((fc->pending_flush & DRM_I915_FENCE_TYPE_RW) &&
            !dev_priv->flush_pending) {
                dev_priv->flush_sequence = (uint32_t) READ_BREADCRUMB(dev_priv);
                dev_priv->flush_flags = fc->pending_flush;
@@ -52,6 +52,27 @@ static void i915_initiate_rwflush(struct drm_i915_private *dev_priv,
        }
 }
 
+static inline void i915_report_rwflush(struct drm_device *dev,
+                                      struct drm_i915_private *dev_priv)
+{
+       if (unlikely(dev_priv->flush_pending)) {
+
+               uint32_t flush_flags;
+               uint32_t i_status;
+               uint32_t flush_sequence;
+
+               i_status = READ_HWSP(dev_priv, 0);
+               if ((i_status & (1 << 12)) !=
+                   (dev_priv->saved_flush_status & (1 << 12))) {
+                       flush_flags = dev_priv->flush_flags;
+                       flush_sequence = dev_priv->flush_sequence;
+                       dev_priv->flush_pending = 0;
+                       drm_fence_handler(dev, 0, flush_sequence,
+                                         flush_flags, 0);
+               }
+       }
+}
+
 static void i915_fence_flush(struct drm_device *dev,
                             uint32_t fence_class)
 {
@@ -69,15 +90,13 @@ static void i915_fence_flush(struct drm_device *dev,
        write_unlock_irqrestore(&fm->lock, irq_flags);
 }
 
+
 static void i915_fence_poll(struct drm_device *dev, uint32_t fence_class,
                            uint32_t waiting_types)
 {
        drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
        struct drm_fence_manager *fm = &dev->fm;
        struct drm_fence_class_manager *fc = &fm->fence_class[0];
-       uint32_t flush_flags = 0;
-       uint32_t flush_sequence = 0;
-       uint32_t i_status;
        uint32_t sequence;
 
        if (unlikely(!dev_priv))
@@ -87,36 +106,24 @@ static void i915_fence_poll(struct drm_device *dev, uint32_t fence_class,
         * First, report any executed sync flush:
         */
 
-       if (dev_priv->flush_pending) {
-               i_status = READ_HWSP(dev_priv, 0);
-               if ((i_status & (1 << 12)) !=
-                   (dev_priv->saved_flush_status & (1 << 12))) {
-                       flush_flags = dev_priv->flush_flags;
-                       flush_sequence = dev_priv->flush_sequence;
-                       dev_priv->flush_pending = 0;
-                       drm_fence_handler(dev, 0, flush_sequence, flush_flags, 0);
-               }
-       }               
+       i915_report_rwflush(dev, dev_priv);
 
        /*
         * Report A new breadcrumb, and adjust IRQs.
         */
 
        if (waiting_types & DRM_FENCE_TYPE_EXE) {
-               sequence = READ_BREADCRUMB(dev_priv);
 
-               if (sequence != dev_priv->reported_sequence ||
-                   !dev_priv->reported_sequence_valid) {
-                       drm_fence_handler(dev, 0, sequence, 
-                                         DRM_FENCE_TYPE_EXE, 0);
-                       dev_priv->reported_sequence = sequence;
-                       dev_priv->reported_sequence_valid = 1;
-               }
+               sequence = READ_BREADCRUMB(dev_priv);
+               drm_fence_handler(dev, 0, sequence,
+                                 DRM_FENCE_TYPE_EXE, 0);
 
-               if (dev_priv->fence_irq_on && !(waiting_types & DRM_FENCE_TYPE_EXE)) {
+               if (dev_priv->fence_irq_on &&
+                   !(fc->waiting_types & DRM_FENCE_TYPE_EXE)) {
                        i915_user_irq_off(dev_priv);
                        dev_priv->fence_irq_on = 0;
-               } else if (!dev_priv->fence_irq_on && (waiting_types & DRM_FENCE_TYPE_EXE)) {
+               } else if (!dev_priv->fence_irq_on &&
+                          (fc->waiting_types & DRM_FENCE_TYPE_EXE)) {
                        i915_user_irq_on(dev_priv);
                        dev_priv->fence_irq_on = 1;
                }
@@ -129,19 +136,11 @@ static void i915_fence_poll(struct drm_device *dev, uint32_t fence_class,
        i915_initiate_rwflush(dev_priv, fc); 
 
        /*
-        * And possibly, but unlikely, they finish immediately. 
+        * And possibly, but unlikely, they finish immediately.
         */
 
-       if (dev_priv->flush_pending) {
-               i_status = READ_HWSP(dev_priv, 0);
-               if (unlikely((i_status & (1 << 12)) !=
-                   (dev_priv->saved_flush_status & (1 << 12)))) {
-                       flush_flags = dev_priv->flush_flags;
-                       flush_sequence = dev_priv->flush_sequence;
-                       dev_priv->flush_pending = 0;
-                       drm_fence_handler(dev, 0, flush_sequence, flush_flags, 0);
-               }
-       }
+       i915_report_rwflush(dev, dev_priv);
+
 }
 
 static int i915_fence_emit_sequence(struct drm_device *dev, uint32_t class,
@@ -258,27 +257,6 @@ static uint32_t i915_fence_needed_flush(struct drm_fence_object *fence)
        return flush_flags;
 }
 
-/*
- * In the very unlikely event that "poll" is not really called very often
- * we need the following function to handle sequence wraparounds.
- */
-
-void i915_invalidate_reported_sequence(struct drm_device *dev)
-{
-       struct drm_i915_private *dev_priv = (struct drm_i915_private *) 
-               dev->dev_private;
-       struct drm_fence_manager *fm = &dev->fm;
-       unsigned long irq_flags;
-
-       if (unlikely(!dev_priv))
-               return;
-       
-       write_lock_irqsave(&fm->lock, irq_flags);
-       dev_priv->reported_sequence_valid = 0;
-       write_unlock_irqrestore(&fm->lock, irq_flags);
-}
-       
-
 struct drm_fence_driver i915_fence_driver = {
        .num_classes = 1,
        .wrap_diff = (1U << (BREADCRUMB_BITS - 1)),
index a012f68..608723f 100644 (file)
@@ -422,9 +422,6 @@ void i915_emit_breadcrumb(struct drm_device *dev)
        RING_LOCALS;
 
        if (++dev_priv->counter > BREADCRUMB_MASK) {
-#ifdef I915_HAVE_FENCE
-               i915_invalidate_reported_sequence(dev);
-#endif
                 dev_priv->counter = 1;
                 DRM_DEBUG("Breadcrumb counter wrapped around\n");
        }
index 3f6c806..8759467 100644 (file)
@@ -136,8 +136,6 @@ typedef struct drm_i915_private {
        uint32_t flush_flags;
        uint32_t flush_pending;
        uint32_t saved_flush_status;
-       uint32_t reported_sequence;
-       int reported_sequence_valid;
 #endif
 #ifdef I915_HAVE_BUFFER
        void *agp_iomap;