aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2010-11-12 08:53:37 -0500
committerChris Wilson <chris@chris-wilson.co.uk>2010-11-24 08:30:52 -0500
commitcaea7476d48e5f401f2d18b1738827748fb56c12 (patch)
tree583a60d043ef7c6676499349ad74491e47ce565a
parenta7a09aebe8c0dd2b76c7b97018a9c614ddb483a5 (diff)
drm/i915: More accurately track last fence usage by the GPU
Based on a patch by Daniel Vetter. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
-rw-r--r--drivers/gpu/drm/i915/i915_debugfs.c3
-rw-r--r--drivers/gpu/drm/i915/i915_drv.h17
-rw-r--r--drivers/gpu/drm/i915/i915_gem.c110
3 files changed, 78 insertions, 52 deletions
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index addb9392e1c4..5faae476954c 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -110,7 +110,7 @@ static const char *get_tiling_flag(struct drm_i915_gem_object *obj)
110static void 110static void
111describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj) 111describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj)
112{ 112{
113 seq_printf(m, "%p: %s%s %8zd %08x %08x %d%s%s", 113 seq_printf(m, "%p: %s%s %8zd %04x %04x %d %d%s%s",
114 &obj->base, 114 &obj->base,
115 get_pin_flag(obj), 115 get_pin_flag(obj),
116 get_tiling_flag(obj), 116 get_tiling_flag(obj),
@@ -118,6 +118,7 @@ describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj)
118 obj->base.read_domains, 118 obj->base.read_domains,
119 obj->base.write_domain, 119 obj->base.write_domain,
120 obj->last_rendering_seqno, 120 obj->last_rendering_seqno,
121 obj->last_fenced_seqno,
121 obj->dirty ? " dirty" : "", 122 obj->dirty ? " dirty" : "",
122 obj->madv == I915_MADV_DONTNEED ? " purgeable" : ""); 123 obj->madv == I915_MADV_DONTNEED ? " purgeable" : "");
123 if (obj->base.name) 124 if (obj->base.name)
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 42d3e901619d..ee7df1d2b8c8 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -124,9 +124,8 @@ struct drm_i915_master_private {
124#define I915_FENCE_REG_NONE -1 124#define I915_FENCE_REG_NONE -1
125 125
126struct drm_i915_fence_reg { 126struct drm_i915_fence_reg {
127 struct drm_i915_gem_object *obj;
128 struct list_head lru_list; 127 struct list_head lru_list;
129 bool gpu; 128 struct drm_i915_gem_object *obj;
130}; 129};
131 130
132struct sdvo_device_mapping { 131struct sdvo_device_mapping {
@@ -787,6 +786,12 @@ struct drm_i915_gem_object {
787 unsigned int fault_mappable : 1; 786 unsigned int fault_mappable : 1;
788 unsigned int pin_mappable : 1; 787 unsigned int pin_mappable : 1;
789 788
789 /*
790 * Is the GPU currently using a fence to access this buffer,
791 */
792 unsigned int pending_fenced_gpu_access:1;
793 unsigned int fenced_gpu_access:1;
794
790 struct page **pages; 795 struct page **pages;
791 796
792 /** 797 /**
@@ -802,11 +807,13 @@ struct drm_i915_gem_object {
802 */ 807 */
803 uint32_t gtt_offset; 808 uint32_t gtt_offset;
804 809
805 /* Which ring is refering to is this object */
806 struct intel_ring_buffer *ring;
807
808 /** Breadcrumb of last rendering to the buffer. */ 810 /** Breadcrumb of last rendering to the buffer. */
809 uint32_t last_rendering_seqno; 811 uint32_t last_rendering_seqno;
812 struct intel_ring_buffer *ring;
813
814 /** Breadcrumb of last fenced GPU access to the buffer. */
815 uint32_t last_fenced_seqno;
816 struct intel_ring_buffer *last_fenced_ring;
810 817
811 /** Current tiling stride for the object, if it's tiled. */ 818 /** Current tiling stride for the object, if it's tiled. */
812 uint32_t stride; 819 uint32_t stride;
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 061426e1bbf4..2cfdee8811c4 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -1688,7 +1688,27 @@ i915_gem_object_move_to_active(struct drm_i915_gem_object *obj,
1688 /* Move from whatever list we were on to the tail of execution. */ 1688 /* Move from whatever list we were on to the tail of execution. */
1689 list_move_tail(&obj->mm_list, &dev_priv->mm.active_list); 1689 list_move_tail(&obj->mm_list, &dev_priv->mm.active_list);
1690 list_move_tail(&obj->ring_list, &ring->active_list); 1690 list_move_tail(&obj->ring_list, &ring->active_list);
1691
1691 obj->last_rendering_seqno = seqno; 1692 obj->last_rendering_seqno = seqno;
1693 if (obj->fenced_gpu_access) {
1694 struct drm_i915_fence_reg *reg;
1695
1696 BUG_ON(obj->fence_reg == I915_FENCE_REG_NONE);
1697
1698 obj->last_fenced_seqno = seqno;
1699 obj->last_fenced_ring = ring;
1700
1701 reg = &dev_priv->fence_regs[obj->fence_reg];
1702 list_move_tail(&reg->lru_list, &dev_priv->mm.fence_list);
1703 }
1704}
1705
1706static void
1707i915_gem_object_move_off_active(struct drm_i915_gem_object *obj)
1708{
1709 list_del_init(&obj->ring_list);
1710 obj->last_rendering_seqno = 0;
1711 obj->last_fenced_seqno = 0;
1692} 1712}
1693 1713
1694static void 1714static void
@@ -1699,8 +1719,33 @@ i915_gem_object_move_to_flushing(struct drm_i915_gem_object *obj)
1699 1719
1700 BUG_ON(!obj->active); 1720 BUG_ON(!obj->active);
1701 list_move_tail(&obj->mm_list, &dev_priv->mm.flushing_list); 1721 list_move_tail(&obj->mm_list, &dev_priv->mm.flushing_list);
1702 list_del_init(&obj->ring_list); 1722
1703 obj->last_rendering_seqno = 0; 1723 i915_gem_object_move_off_active(obj);
1724}
1725
1726static void
1727i915_gem_object_move_to_inactive(struct drm_i915_gem_object *obj)
1728{
1729 struct drm_device *dev = obj->base.dev;
1730 struct drm_i915_private *dev_priv = dev->dev_private;
1731
1732 if (obj->pin_count != 0)
1733 list_move_tail(&obj->mm_list, &dev_priv->mm.pinned_list);
1734 else
1735 list_move_tail(&obj->mm_list, &dev_priv->mm.inactive_list);
1736
1737 BUG_ON(!list_empty(&obj->gpu_write_list));
1738 BUG_ON(!obj->active);
1739 obj->ring = NULL;
1740
1741 i915_gem_object_move_off_active(obj);
1742 obj->fenced_gpu_access = false;
1743 obj->last_fenced_ring = NULL;
1744
1745 obj->active = 0;
1746 drm_gem_object_unreference(&obj->base);
1747
1748 WARN_ON(i915_verify_lists(dev));
1704} 1749}
1705 1750
1706/* Immediately discard the backing storage */ 1751/* Immediately discard the backing storage */
@@ -1730,34 +1775,10 @@ i915_gem_object_is_purgeable(struct drm_i915_gem_object *obj)
1730} 1775}
1731 1776
1732static void 1777static void
1733i915_gem_object_move_to_inactive(struct drm_i915_gem_object *obj)
1734{
1735 struct drm_device *dev = obj->base.dev;
1736 drm_i915_private_t *dev_priv = dev->dev_private;
1737
1738 if (obj->pin_count != 0)
1739 list_move_tail(&obj->mm_list, &dev_priv->mm.pinned_list);
1740 else
1741 list_move_tail(&obj->mm_list, &dev_priv->mm.inactive_list);
1742 list_del_init(&obj->ring_list);
1743
1744 BUG_ON(!list_empty(&obj->gpu_write_list));
1745
1746 obj->last_rendering_seqno = 0;
1747 obj->ring = NULL;
1748 if (obj->active) {
1749 obj->active = 0;
1750 drm_gem_object_unreference(&obj->base);
1751 }
1752 WARN_ON(i915_verify_lists(dev));
1753}
1754
1755static void
1756i915_gem_process_flushing_list(struct drm_device *dev, 1778i915_gem_process_flushing_list(struct drm_device *dev,
1757 uint32_t flush_domains, 1779 uint32_t flush_domains,
1758 struct intel_ring_buffer *ring) 1780 struct intel_ring_buffer *ring)
1759{ 1781{
1760 drm_i915_private_t *dev_priv = dev->dev_private;
1761 struct drm_i915_gem_object *obj, *next; 1782 struct drm_i915_gem_object *obj, *next;
1762 1783
1763 list_for_each_entry_safe(obj, next, 1784 list_for_each_entry_safe(obj, next,
@@ -1770,14 +1791,6 @@ i915_gem_process_flushing_list(struct drm_device *dev,
1770 list_del_init(&obj->gpu_write_list); 1791 list_del_init(&obj->gpu_write_list);
1771 i915_gem_object_move_to_active(obj, ring); 1792 i915_gem_object_move_to_active(obj, ring);
1772 1793
1773 /* update the fence lru list */
1774 if (obj->fence_reg != I915_FENCE_REG_NONE) {
1775 struct drm_i915_fence_reg *reg =
1776 &dev_priv->fence_regs[obj->fence_reg];
1777 list_move_tail(&reg->lru_list,
1778 &dev_priv->mm.fence_list);
1779 }
1780
1781 trace_i915_gem_object_change_domain(obj, 1794 trace_i915_gem_object_change_domain(obj,
1782 obj->base.read_domains, 1795 obj->base.read_domains,
1783 old_write_domain); 1796 old_write_domain);
@@ -2615,8 +2628,7 @@ i915_gem_object_put_fence_reg(struct drm_i915_gem_object *obj,
2615 bool interruptible) 2628 bool interruptible)
2616{ 2629{
2617 struct drm_device *dev = obj->base.dev; 2630 struct drm_device *dev = obj->base.dev;
2618 struct drm_i915_private *dev_priv = dev->dev_private; 2631 int ret;
2619 struct drm_i915_fence_reg *reg;
2620 2632
2621 if (obj->fence_reg == I915_FENCE_REG_NONE) 2633 if (obj->fence_reg == I915_FENCE_REG_NONE)
2622 return 0; 2634 return 0;
@@ -2631,19 +2643,23 @@ i915_gem_object_put_fence_reg(struct drm_i915_gem_object *obj,
2631 * therefore we must wait for any outstanding access to complete 2643 * therefore we must wait for any outstanding access to complete
2632 * before clearing the fence. 2644 * before clearing the fence.
2633 */ 2645 */
2634 reg = &dev_priv->fence_regs[obj->fence_reg]; 2646 if (obj->fenced_gpu_access) {
2635 if (reg->gpu) {
2636 int ret;
2637
2638 ret = i915_gem_object_flush_gpu_write_domain(obj, NULL); 2647 ret = i915_gem_object_flush_gpu_write_domain(obj, NULL);
2639 if (ret) 2648 if (ret)
2640 return ret; 2649 return ret;
2641 2650
2642 ret = i915_gem_object_wait_rendering(obj, interruptible); 2651 obj->fenced_gpu_access = false;
2652 }
2653
2654 if (obj->last_fenced_seqno) {
2655 ret = i915_do_wait_request(dev,
2656 obj->last_fenced_seqno,
2657 interruptible,
2658 obj->last_fenced_ring);
2643 if (ret) 2659 if (ret)
2644 return ret; 2660 return ret;
2645 2661
2646 reg->gpu = false; 2662 obj->last_fenced_seqno = false;
2647 } 2663 }
2648 2664
2649 i915_gem_object_flush_gtt_write_domain(obj); 2665 i915_gem_object_flush_gtt_write_domain(obj);
@@ -3166,8 +3182,9 @@ i915_gem_object_set_to_gpu_domain(struct drm_i915_gem_object *obj,
3166 * write domain 3182 * write domain
3167 */ 3183 */
3168 if (obj->base.write_domain && 3184 if (obj->base.write_domain &&
3169 (obj->base.write_domain != obj->base.pending_read_domains || 3185 (((obj->base.write_domain != obj->base.pending_read_domains ||
3170 obj->ring != ring)) { 3186 obj->ring != ring)) ||
3187 (obj->fenced_gpu_access && !obj->pending_fenced_gpu_access))) {
3171 flush_domains |= obj->base.write_domain; 3188 flush_domains |= obj->base.write_domain;
3172 invalidate_domains |= 3189 invalidate_domains |=
3173 obj->base.pending_read_domains & ~obj->base.write_domain; 3190 obj->base.pending_read_domains & ~obj->base.write_domain;
@@ -3528,7 +3545,6 @@ i915_gem_execbuffer_reserve(struct drm_device *dev,
3528 struct drm_i915_gem_exec_object2 *exec_list, 3545 struct drm_i915_gem_exec_object2 *exec_list,
3529 int count) 3546 int count)
3530{ 3547{
3531 struct drm_i915_private *dev_priv = dev->dev_private;
3532 int ret, i, retry; 3548 int ret, i, retry;
3533 3549
3534 /* Attempt to pin all of the buffers into the GTT. 3550 /* Attempt to pin all of the buffers into the GTT.
@@ -3601,7 +3617,7 @@ i915_gem_execbuffer_reserve(struct drm_device *dev,
3601 if (ret) 3617 if (ret)
3602 break; 3618 break;
3603 3619
3604 dev_priv->fence_regs[obj->fence_reg].gpu = true; 3620 obj->pending_fenced_gpu_access = true;
3605 } 3621 }
3606 3622
3607 entry->offset = obj->gtt_offset; 3623 entry->offset = obj->gtt_offset;
@@ -3981,6 +3997,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
3981 goto err; 3997 goto err;
3982 } 3998 }
3983 obj->in_execbuffer = true; 3999 obj->in_execbuffer = true;
4000 obj->pending_fenced_gpu_access = false;
3984 } 4001 }
3985 4002
3986 /* Move the objects en-masse into the GTT, evicting if necessary. */ 4003 /* Move the objects en-masse into the GTT, evicting if necessary. */
@@ -4085,6 +4102,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
4085 4102
4086 obj->base.read_domains = obj->base.pending_read_domains; 4103 obj->base.read_domains = obj->base.pending_read_domains;
4087 obj->base.write_domain = obj->base.pending_write_domain; 4104 obj->base.write_domain = obj->base.pending_write_domain;
4105 obj->fenced_gpu_access = obj->pending_fenced_gpu_access;
4088 4106
4089 i915_gem_object_move_to_active(obj, ring); 4107 i915_gem_object_move_to_active(obj, ring);
4090 if (obj->base.write_domain) { 4108 if (obj->base.write_domain) {