diff options
| -rw-r--r-- | linux-core/i915_gem.c | 23 | ||||
| -rw-r--r-- | shared-core/i915_drv.h | 9 | 
2 files changed, 30 insertions, 2 deletions
| diff --git a/linux-core/i915_gem.c b/linux-core/i915_gem.c index 4dfbd2a1..16a1b07e 100644 --- a/linux-core/i915_gem.c +++ b/linux-core/i915_gem.c @@ -653,7 +653,7 @@ i915_gem_retire_requests(struct drm_device *dev)  					   list);  		retiring_seqno = request->seqno; -		if (i915_seqno_passed(seqno, retiring_seqno)) { +		if (i915_seqno_passed(seqno, retiring_seqno) || dev_priv->mm.wedged) {  			i915_gem_retire_request(dev, request);  			list_del(&request->list); @@ -697,10 +697,13 @@ i915_wait_request(struct drm_device *dev, uint32_t seqno)  		i915_user_irq_on(dev_priv);  		ret = wait_event_interruptible(dev_priv->irq_queue,  					       i915_seqno_passed(i915_get_gem_seqno(dev), -								 seqno)); +								 seqno) || dev_priv->mm.wedged);  		i915_user_irq_off(dev_priv);  		dev_priv->mm.waiting_gem_seqno = 0;  	} +	if (dev_priv->mm.wedged) +		ret = -EIO; +  	if (ret)  		DRM_ERROR("%s returns %d (awaiting %d at %d)\n",  			  __func__, ret, seqno, i915_get_gem_seqno(dev)); @@ -1019,6 +1022,8 @@ i915_gem_evict_something(struct drm_device *dev)  						   list);  			ret = i915_wait_request(dev, request->seqno); +			if (ret) +				break;  			/* if waiting caused an object to become inactive,  			 * then loop around and wait for it. Otherwise, we @@ -1822,6 +1827,13 @@ i915_gem_execbuffer(struct drm_device *dev, void *data,  	mutex_lock(&dev->struct_mutex);  	i915_verify_inactive(dev, __FILE__, __LINE__); + +	if (dev_priv->mm.wedged) { +		DRM_ERROR("Execbuf while wedged\n"); +		mutex_unlock(&dev->struct_mutex); +		return -EIO; +	} +		  	if (dev_priv->mm.suspended) {  		DRM_ERROR("Execbuf while VT-switched.\n");  		mutex_unlock(&dev->struct_mutex); @@ -2264,6 +2276,8 @@ i915_gem_idle(struct drm_device *dev)  		if (last_seqno == cur_seqno) {  			if (stuck++ > 100) {  				DRM_ERROR("hardware wedged\n"); +				dev_priv->mm.wedged = 1; +				DRM_WAKEUP(&dev_priv->irq_queue);  				break;  			}  		} @@ -2378,6 +2392,11 @@ i915_gem_entervt_ioctl(struct drm_device *dev, void *data,  	drm_i915_private_t *dev_priv = dev->dev_private;  	int ret; +	if (dev_priv->mm.wedged) { +		DRM_ERROR("Renabling wedged hardware, good luck\n"); +		dev_priv->mm.wedged = 0; +	} +  	ret = i915_gem_init_ringbuffer(dev);  	if (ret != 0)  		return ret; diff --git a/shared-core/i915_drv.h b/shared-core/i915_drv.h index 9f500330..0df5af9c 100644 --- a/shared-core/i915_drv.h +++ b/shared-core/i915_drv.h @@ -307,6 +307,15 @@ typedef struct drm_i915_private {  		 * transitioned away from for kernel modesetting.  		 */  		int suspended; + +		/** +		 * Flag if the hardware appears to be wedged. +		 * +		 * This is set when attempts to idle the device timeout. +		 * It prevents command submission from occuring and makes +		 * every pending request fail +		 */ +		int wedged;  	} mm;  } drm_i915_private_t; | 
