Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Eric Anholt <eric@anholt.net>

authored by

Chris Wilson and committed by
Eric Anholt
d7619c4b fc7170ba

+31 -7
+31 -7
drivers/gpu/drm/i915/i915_gem.c
··· 1595 1595 1596 1596 /* None available, try to steal one or wait for a user to finish */ 1597 1597 if (i == dev_priv->num_fence_regs) { 1598 + uint32_t seqno = dev_priv->mm.next_gem_seqno; 1598 1599 loff_t offset; 1599 1600 1600 1601 if (avail == 0) 1601 1602 return -ENOMEM; 1602 1603 1603 - /* Could try to use LRU here instead... */ 1604 1604 for (i = dev_priv->fence_reg_start; 1605 1605 i < dev_priv->num_fence_regs; i++) { 1606 + uint32_t this_seqno; 1607 + 1606 1608 reg = &dev_priv->fence_regs[i]; 1607 1609 old_obj_priv = reg->obj->driver_private; 1608 - if (!old_obj_priv->pin_count) 1610 + 1611 + if (old_obj_priv->pin_count) 1612 + continue; 1613 + 1614 + /* i915 uses fences for GPU access to tiled buffers */ 1615 + if (IS_I965G(dev) || !old_obj_priv->active) 1609 1616 break; 1617 + 1618 + /* find the seqno of the first available fence */ 1619 + this_seqno = old_obj_priv->last_rendering_seqno; 1620 + if (this_seqno != 0 && 1621 + reg->obj->write_domain == 0 && 1622 + i915_seqno_passed(seqno, this_seqno)) 1623 + seqno = this_seqno; 1610 1624 } 1611 1625 1612 1626 /* ··· 1628 1614 * objects to finish before trying again. 1629 1615 */ 1630 1616 if (i == dev_priv->num_fence_regs) { 1631 - ret = i915_gem_object_set_to_gtt_domain(reg->obj, 0); 1632 - if (ret) { 1633 - WARN(ret != -ERESTARTSYS, 1634 - "switch to GTT domain failed: %d\n", ret); 1635 - return ret; 1617 + if (seqno == dev_priv->mm.next_gem_seqno) { 1618 + i915_gem_flush(dev, 1619 + I915_GEM_GPU_DOMAINS, 1620 + I915_GEM_GPU_DOMAINS); 1621 + seqno = i915_add_request(dev, 1622 + I915_GEM_GPU_DOMAINS); 1623 + if (seqno == 0) 1624 + return -ENOMEM; 1636 1625 } 1626 + 1627 + ret = i915_wait_request(dev, seqno); 1628 + if (ret) 1629 + return ret; 1637 1630 goto try_again; 1638 1631 } 1632 + 1633 + BUG_ON(old_obj_priv->active || 1634 + (reg->obj->write_domain & I915_GEM_GPU_DOMAINS)); 1639 1635 1640 1636 /* 1641 1637 * Zap this virtual mapping so we can set up a fence again