summaryrefslogtreecommitdiff
path: root/linux-core/i915_gem.c
diff options
context:
space:
mode:
authorKeith Packard <keithp@keithp.com>2008-06-20 21:10:42 -0700
committerKeith Packard <keithp@keithp.com>2008-06-20 21:10:42 -0700
commit54817317e9dd8a791418f97503fe574038dbe4b9 (patch)
tree236ee1ad95b8f8fcef5b1fd47088103e6f85a47e /linux-core/i915_gem.c
parent71b1623e22c54d42837840a1d0479127a5049caf (diff)
[intel-gem] Use polling in i915_gem_idle instead of interrupts.
While waiting for the hardware to idle on leavevt or lastclose, poll for the sync sequence number instead of waiting for an interrupt. This allows the code to bail if the hardware hangs for some reason. Also, this avoids issues with signals as the exisiting wait function is interruptible.
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);
}