Commit d7619c4b authored by Chris Wilson's avatar Chris Wilson Committed by Eric Anholt

drm/i915: Protect active fences on i915

The i915 also uses the fence registers for GPU access to tiled buffers so
we cannot reallocate one whilst it is on the active list. By performing a
LRU scan of the fenced buffers we also avoid waiting the possibility of
waiting on a pinned, or otherwise unusable, buffer.
Signed-off-by: default avatarChris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: default avatarEric Anholt <eric@anholt.net>
parent fc7170ba
...@@ -1595,18 +1595,32 @@ i915_gem_object_get_fence_reg(struct drm_gem_object *obj, bool write) ...@@ -1595,18 +1595,32 @@ i915_gem_object_get_fence_reg(struct drm_gem_object *obj, bool write)
/* None available, try to steal one or wait for a user to finish */ /* None available, try to steal one or wait for a user to finish */
if (i == dev_priv->num_fence_regs) { if (i == dev_priv->num_fence_regs) {
uint32_t seqno = dev_priv->mm.next_gem_seqno;
loff_t offset; loff_t offset;
if (avail == 0) if (avail == 0)
return -ENOMEM; return -ENOMEM;
/* Could try to use LRU here instead... */
for (i = dev_priv->fence_reg_start; for (i = dev_priv->fence_reg_start;
i < dev_priv->num_fence_regs; i++) { i < dev_priv->num_fence_regs; i++) {
uint32_t this_seqno;
reg = &dev_priv->fence_regs[i]; reg = &dev_priv->fence_regs[i];
old_obj_priv = reg->obj->driver_private; old_obj_priv = reg->obj->driver_private;
if (!old_obj_priv->pin_count)
if (old_obj_priv->pin_count)
continue;
/* i915 uses fences for GPU access to tiled buffers */
if (IS_I965G(dev) || !old_obj_priv->active)
break; break;
/* find the seqno of the first available fence */
this_seqno = old_obj_priv->last_rendering_seqno;
if (this_seqno != 0 &&
reg->obj->write_domain == 0 &&
i915_seqno_passed(seqno, this_seqno))
seqno = this_seqno;
} }
/* /*
...@@ -1614,15 +1628,25 @@ i915_gem_object_get_fence_reg(struct drm_gem_object *obj, bool write) ...@@ -1614,15 +1628,25 @@ i915_gem_object_get_fence_reg(struct drm_gem_object *obj, bool write)
* objects to finish before trying again. * objects to finish before trying again.
*/ */
if (i == dev_priv->num_fence_regs) { if (i == dev_priv->num_fence_regs) {
ret = i915_gem_object_set_to_gtt_domain(reg->obj, 0); if (seqno == dev_priv->mm.next_gem_seqno) {
if (ret) { i915_gem_flush(dev,
WARN(ret != -ERESTARTSYS, I915_GEM_GPU_DOMAINS,
"switch to GTT domain failed: %d\n", ret); I915_GEM_GPU_DOMAINS);
return ret; seqno = i915_add_request(dev,
I915_GEM_GPU_DOMAINS);
if (seqno == 0)
return -ENOMEM;
} }
ret = i915_wait_request(dev, seqno);
if (ret)
return ret;
goto try_again; goto try_again;
} }
BUG_ON(old_obj_priv->active ||
(reg->obj->write_domain & I915_GEM_GPU_DOMAINS));
/* /*
* Zap this virtual mapping so we can set up a fence again * Zap this virtual mapping so we can set up a fence again
* for this object next time we need it. * for this object next time we need it.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment