diff options
-rw-r--r-- | linux-core/i915_gem.c | 39 |
1 files changed, 29 insertions, 10 deletions
diff --git a/linux-core/i915_gem.c b/linux-core/i915_gem.c index e086bc1b..27b6ddbb 100644 --- a/linux-core/i915_gem.c +++ b/linux-core/i915_gem.c @@ -2139,8 +2139,9 @@ static int i915_gem_idle(struct drm_device *dev) { drm_i915_private_t *dev_priv = dev->dev_private; - uint32_t seqno; + uint32_t seqno, cur_seqno, last_seqno; int ret; + int stuck; if (dev_priv->mm.suspended) return 0; @@ -2161,11 +2162,26 @@ i915_gem_idle(struct drm_device *dev) mutex_unlock(&dev->struct_mutex); return -ENOMEM; } - ret = i915_wait_request(dev, seqno); - if (ret) { - mutex_unlock(&dev->struct_mutex); - return ret; + + dev_priv->mm.waiting_gem_seqno = seqno; + last_seqno = 0; + stuck = 0; + for (;;) { + cur_seqno = i915_get_gem_seqno(dev); + if (i915_seqno_passed(cur_seqno, seqno)) + break; + if (last_seqno == cur_seqno) { + if (stuck++ > 100) { + DRM_ERROR("hardware wedged\n"); + break; + } + } + msleep(10); + last_seqno = cur_seqno; } + dev_priv->mm.waiting_gem_seqno = 0; + + i915_gem_retire_requests(dev); /* Active and flushing should now be empty as we've * waited for a sequence higher than any pending execbuffer @@ -2521,14 +2537,17 @@ void i915_gem_lastclose(struct drm_device *dev) { int ret; + drm_i915_private_t *dev_priv = dev->dev_private; mutex_lock(&dev->struct_mutex); - ret = i915_gem_idle(dev); - if (ret) - DRM_ERROR("failed to idle hardware: %d\n", ret); - - i915_gem_cleanup_ringbuffer(dev); + if (dev_priv->ring.ring_obj != NULL) { + ret = i915_gem_idle(dev); + if (ret) + DRM_ERROR("failed to idle hardware: %d\n", ret); + + i915_gem_cleanup_ringbuffer(dev); + } mutex_unlock(&dev->struct_mutex); } |