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; |