summaryrefslogtreecommitdiff
path: root/linux-core/i915_gem.c
diff options
context:
space:
mode:
Diffstat (limited to 'linux-core/i915_gem.c')
-rw-r--r--linux-core/i915_gem.c39
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);
}