diff options
Diffstat (limited to 'drivers/gpu/drm/i915/intel_ringbuffer.c')
| -rw-r--r-- | drivers/gpu/drm/i915/intel_ringbuffer.c | 54 | 
1 files changed, 34 insertions, 20 deletions
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 6bc68bdcf433..79fb4cc2137c 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -437,32 +437,41 @@ static void ring_setup_phys_status_page(struct intel_ring_buffer *ring)  	I915_WRITE(HWS_PGA, addr);  } -static int init_ring_common(struct intel_ring_buffer *ring) +static bool stop_ring(struct intel_ring_buffer *ring)  { -	struct drm_device *dev = ring->dev; -	struct drm_i915_private *dev_priv = dev->dev_private; -	struct drm_i915_gem_object *obj = ring->obj; -	int ret = 0; -	u32 head; +	struct drm_i915_private *dev_priv = to_i915(ring->dev); -	gen6_gt_force_wake_get(dev_priv, FORCEWAKE_ALL); +	if (!IS_GEN2(ring->dev)) { +		I915_WRITE_MODE(ring, _MASKED_BIT_ENABLE(STOP_RING)); +		if (wait_for_atomic((I915_READ_MODE(ring) & MODE_IDLE) != 0, 1000)) { +			DRM_ERROR("%s :timed out trying to stop ring\n", ring->name); +			return false; +		} +	} -	/* Stop the ring if it's running. */  	I915_WRITE_CTL(ring, 0);  	I915_WRITE_HEAD(ring, 0);  	ring->write_tail(ring, 0); -	if (wait_for_atomic((I915_READ_MODE(ring) & MODE_IDLE) != 0, 1000)) -		DRM_ERROR("%s :timed out trying to stop ring\n", ring->name); -	if (I915_NEED_GFX_HWS(dev)) -		intel_ring_setup_status_page(ring); -	else -		ring_setup_phys_status_page(ring); +	if (!IS_GEN2(ring->dev)) { +		(void)I915_READ_CTL(ring); +		I915_WRITE_MODE(ring, _MASKED_BIT_DISABLE(STOP_RING)); +	} -	head = I915_READ_HEAD(ring) & HEAD_ADDR; +	return (I915_READ_HEAD(ring) & HEAD_ADDR) == 0; +} -	/* G45 ring initialization fails to reset head to zero */ -	if (head != 0) { +static int init_ring_common(struct intel_ring_buffer *ring) +{ +	struct drm_device *dev = ring->dev; +	struct drm_i915_private *dev_priv = dev->dev_private; +	struct drm_i915_gem_object *obj = ring->obj; +	int ret = 0; + +	gen6_gt_force_wake_get(dev_priv, FORCEWAKE_ALL); + +	if (!stop_ring(ring)) { +		/* G45 ring initialization often fails to reset head to zero */  		DRM_DEBUG_KMS("%s head not reset to zero "  			      "ctl %08x head %08x tail %08x start %08x\n",  			      ring->name, @@ -471,9 +480,7 @@ static int init_ring_common(struct intel_ring_buffer *ring)  			      I915_READ_TAIL(ring),  			      I915_READ_START(ring)); -		I915_WRITE_HEAD(ring, 0); - -		if (I915_READ_HEAD(ring) & HEAD_ADDR) { +		if (!stop_ring(ring)) {  			DRM_ERROR("failed to set %s head to zero "  				  "ctl %08x head %08x tail %08x start %08x\n",  				  ring->name, @@ -481,9 +488,16 @@ static int init_ring_common(struct intel_ring_buffer *ring)  				  I915_READ_HEAD(ring),  				  I915_READ_TAIL(ring),  				  I915_READ_START(ring)); +			ret = -EIO; +			goto out;  		}  	} +	if (I915_NEED_GFX_HWS(dev)) +		intel_ring_setup_status_page(ring); +	else +		ring_setup_phys_status_page(ring); +  	/* Initialize the ring. This must happen _after_ we've cleared the ring  	 * registers with the above sequence (the readback of the HEAD registers  	 * also enforces ordering), otherwise the hw might lose the new ring  | 
