diff options
| author | Thomas Hellstrom <thomas-at-tungstengraphics-dot-com> | 2008-02-05 10:35:56 +0100 | 
|---|---|---|
| committer | Thomas Hellstrom <thomas-at-tungstengraphics-dot-com> | 2008-02-05 10:36:49 +0100 | 
| commit | 76748efae2f51409813eeb6b91b783c73cb2845e (patch) | |
| tree | bfcb049319161c6429dbef1607646f50fccf77b0 /linux-core | |
| parent | a0781e762295ce3d5f6e839d437a0de505cefa3b (diff) | |
i915: Re-report breadcrumbs on poll to the fence manager,
since a breadcrumb may actually turn up before a corresponding fence object
has been placed on the fence ring.
Diffstat (limited to 'linux-core')
| -rw-r--r-- | linux-core/i915_fence.c | 94 | 
1 files changed, 36 insertions, 58 deletions
diff --git a/linux-core/i915_fence.c b/linux-core/i915_fence.c index 8a2e7f13..de64a4f2 100644 --- a/linux-core/i915_fence.c +++ b/linux-core/i915_fence.c @@ -38,10 +38,10 @@   * 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)),  | 
