aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Vetter <daniel.vetter@ffwll.ch>2010-10-01 16:05:20 -0400
committerChris Wilson <chris@chris-wilson.co.uk>2010-10-27 18:31:08 -0400
commitfb7d516af11837126eb1e4a44ab0653bf9b57702 (patch)
treef74c587c80c53f6f30fdab9d80d41a40bbd1bc5e
parentec57d2602a985b54b53e53098f74fdefc24723af (diff)
drm/i915: add accounting for mappable objects in gtt v2
More precisely: For those that _need_ to be mappable. Also add two BUG_ONs in fault and pin to check the consistency of the mappable flag. Changes in v2: - Add tracking of gtt mappable space (to notice mappable/unmappable balancing issues). - Improve the mappable working set tracking by tracking fault and pin separately. Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch> Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
-rw-r--r--drivers/gpu/drm/i915/i915_debugfs.c6
-rw-r--r--drivers/gpu/drm/i915/i915_drv.h12
-rw-r--r--drivers/gpu/drm/i915/i915_gem.c93
3 files changed, 98 insertions, 13 deletions
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index beb3de7921b5..2e5961139326 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -131,6 +131,8 @@ describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj)
131 seq_printf(m, " (fence: %d)", obj->fence_reg); 131 seq_printf(m, " (fence: %d)", obj->fence_reg);
132 if (obj->gtt_space != NULL) 132 if (obj->gtt_space != NULL)
133 seq_printf(m, " (gtt_offset: %08x)", obj->gtt_offset); 133 seq_printf(m, " (gtt_offset: %08x)", obj->gtt_offset);
134 if (obj->pin_mappable || obj->fault_mappable)
135 seq_printf(m, " (mappable)");
134 if (obj->ring != NULL) 136 if (obj->ring != NULL)
135 seq_printf(m, " (%s)", obj->ring->name); 137 seq_printf(m, " (%s)", obj->ring->name);
136} 138}
@@ -207,6 +209,10 @@ static int i915_gem_object_info(struct seq_file *m, void* data)
207 seq_printf(m, "%zu object bytes\n", dev_priv->mm.object_memory); 209 seq_printf(m, "%zu object bytes\n", dev_priv->mm.object_memory);
208 seq_printf(m, "%u pinned\n", dev_priv->mm.pin_count); 210 seq_printf(m, "%u pinned\n", dev_priv->mm.pin_count);
209 seq_printf(m, "%zu pin bytes\n", dev_priv->mm.pin_memory); 211 seq_printf(m, "%zu pin bytes\n", dev_priv->mm.pin_memory);
212 seq_printf(m, "%u mappable objects in gtt\n", dev_priv->mm.gtt_mappable_count);
213 seq_printf(m, "%zu mappable gtt bytes\n", dev_priv->mm.gtt_mappable_memory);
214 seq_printf(m, "%zu mappable gtt used bytes\n", dev_priv->mm.mappable_gtt_used);
215 seq_printf(m, "%zu mappable gtt total\n", dev_priv->mm.mappable_gtt_total);
210 seq_printf(m, "%u objects in gtt\n", dev_priv->mm.gtt_count); 216 seq_printf(m, "%u objects in gtt\n", dev_priv->mm.gtt_count);
211 seq_printf(m, "%zu gtt bytes\n", dev_priv->mm.gtt_memory); 217 seq_printf(m, "%zu gtt bytes\n", dev_priv->mm.gtt_memory);
212 seq_printf(m, "%zu gtt total\n", dev_priv->mm.gtt_total); 218 seq_printf(m, "%zu gtt total\n", dev_priv->mm.gtt_total);
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 296ed38b292f..cdae5d189165 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -643,9 +643,13 @@ typedef struct drm_i915_private {
643 size_t object_memory; 643 size_t object_memory;
644 size_t pin_memory; 644 size_t pin_memory;
645 size_t gtt_memory; 645 size_t gtt_memory;
646 size_t gtt_mappable_memory;
647 size_t mappable_gtt_used;
648 size_t mappable_gtt_total;
646 size_t gtt_total; 649 size_t gtt_total;
647 u32 object_count; 650 u32 object_count;
648 u32 pin_count; 651 u32 pin_count;
652 u32 gtt_mappable_count;
649 u32 gtt_count; 653 u32 gtt_count;
650 } mm; 654 } mm;
651 struct sdvo_device_mapping sdvo_mappings[2]; 655 struct sdvo_device_mapping sdvo_mappings[2];
@@ -775,6 +779,14 @@ struct drm_i915_gem_object {
775 unsigned int pin_count : 4; 779 unsigned int pin_count : 4;
776#define DRM_I915_GEM_OBJECT_MAX_PIN_COUNT 0xf 780#define DRM_I915_GEM_OBJECT_MAX_PIN_COUNT 0xf
777 781
782 /**
783 * Whether the current gtt mapping needs to be mappable (and isn't just
784 * mappable by accident). Track pin and fault separate for a more
785 * accurate mappable working set.
786 */
787 unsigned int fault_mappable : 1;
788 unsigned int pin_mappable : 1;
789
778 /** AGP memory structure for our GTT binding. */ 790 /** AGP memory structure for our GTT binding. */
779 DRM_AGP_MEM *agp_mem; 791 DRM_AGP_MEM *agp_mem;
780 792
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index bb5435ba01aa..2eceb24bf54b 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -84,31 +84,83 @@ static void i915_gem_info_remove_obj(struct drm_i915_private *dev_priv,
84} 84}
85 85
86static void i915_gem_info_add_gtt(struct drm_i915_private *dev_priv, 86static void i915_gem_info_add_gtt(struct drm_i915_private *dev_priv,
87 size_t size) 87 struct drm_gem_object *obj)
88{ 88{
89 struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
89 dev_priv->mm.gtt_count++; 90 dev_priv->mm.gtt_count++;
90 dev_priv->mm.gtt_memory += size; 91 dev_priv->mm.gtt_memory += obj->size;
92 if (obj_priv->gtt_offset < dev_priv->mm.gtt_mappable_end) {
93 dev_priv->mm.mappable_gtt_used +=
94 min_t(size_t, obj->size,
95 dev_priv->mm.gtt_mappable_end
96 - obj_priv->gtt_offset);
97 }
91} 98}
92 99
93static void i915_gem_info_remove_gtt(struct drm_i915_private *dev_priv, 100static void i915_gem_info_remove_gtt(struct drm_i915_private *dev_priv,
94 size_t size) 101 struct drm_gem_object *obj)
95{ 102{
103 struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
96 dev_priv->mm.gtt_count--; 104 dev_priv->mm.gtt_count--;
97 dev_priv->mm.gtt_memory -= size; 105 dev_priv->mm.gtt_memory -= obj->size;
106 if (obj_priv->gtt_offset < dev_priv->mm.gtt_mappable_end) {
107 dev_priv->mm.mappable_gtt_used -=
108 min_t(size_t, obj->size,
109 dev_priv->mm.gtt_mappable_end
110 - obj_priv->gtt_offset);
111 }
112}
113
114/**
115 * Update the mappable working set counters. Call _only_ when there is a change
116 * in one of (pin|fault)_mappable and update *_mappable _before_ calling.
117 * @mappable: new state the changed mappable flag (either pin_ or fault_).
118 */
119static void
120i915_gem_info_update_mappable(struct drm_i915_private *dev_priv,
121 struct drm_gem_object *obj,
122 bool mappable)
123{
124 struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
125
126 if (mappable) {
127 if (obj_priv->pin_mappable && obj_priv->fault_mappable)
128 /* Combined state was already mappable. */
129 return;
130 dev_priv->mm.gtt_mappable_count++;
131 dev_priv->mm.gtt_mappable_memory += obj->size;
132 } else {
133 if (obj_priv->pin_mappable || obj_priv->fault_mappable)
134 /* Combined state still mappable. */
135 return;
136 dev_priv->mm.gtt_mappable_count--;
137 dev_priv->mm.gtt_mappable_memory -= obj->size;
138 }
98} 139}
99 140
100static void i915_gem_info_add_pin(struct drm_i915_private *dev_priv, 141static void i915_gem_info_add_pin(struct drm_i915_private *dev_priv,
101 size_t size) 142 struct drm_gem_object *obj,
143 bool mappable)
102{ 144{
145 struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
103 dev_priv->mm.pin_count++; 146 dev_priv->mm.pin_count++;
104 dev_priv->mm.pin_memory += size; 147 dev_priv->mm.pin_memory += obj->size;
148 if (mappable) {
149 obj_priv->pin_mappable = true;
150 i915_gem_info_update_mappable(dev_priv, obj, true);
151 }
105} 152}
106 153
107static void i915_gem_info_remove_pin(struct drm_i915_private *dev_priv, 154static void i915_gem_info_remove_pin(struct drm_i915_private *dev_priv,
108 size_t size) 155 struct drm_gem_object *obj)
109{ 156{
157 struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
110 dev_priv->mm.pin_count--; 158 dev_priv->mm.pin_count--;
111 dev_priv->mm.pin_memory -= size; 159 dev_priv->mm.pin_memory -= obj->size;
160 if (obj_priv->pin_mappable) {
161 obj_priv->pin_mappable = false;
162 i915_gem_info_update_mappable(dev_priv, obj, false);
163 }
112} 164}
113 165
114int 166int
@@ -188,6 +240,7 @@ int i915_gem_do_init(struct drm_device *dev,
188 end - start); 240 end - start);
189 241
190 dev_priv->mm.gtt_total = end - start; 242 dev_priv->mm.gtt_total = end - start;
243 dev_priv->mm.mappable_gtt_total = min(end, mappable_end) - start;
191 dev_priv->mm.gtt_mappable_end = mappable_end; 244 dev_priv->mm.gtt_mappable_end = mappable_end;
192 245
193 return 0; 246 return 0;
@@ -1266,6 +1319,7 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
1266 1319
1267 /* Now bind it into the GTT if needed */ 1320 /* Now bind it into the GTT if needed */
1268 mutex_lock(&dev->struct_mutex); 1321 mutex_lock(&dev->struct_mutex);
1322 BUG_ON(obj_priv->pin_count && !obj_priv->pin_mappable);
1269 if (!i915_gem_object_cpu_accessible(obj_priv)) 1323 if (!i915_gem_object_cpu_accessible(obj_priv))
1270 i915_gem_object_unbind(obj); 1324 i915_gem_object_unbind(obj);
1271 1325
@@ -1279,6 +1333,11 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
1279 goto unlock; 1333 goto unlock;
1280 } 1334 }
1281 1335
1336 if (!obj_priv->fault_mappable) {
1337 obj_priv->fault_mappable = true;
1338 i915_gem_info_update_mappable(dev_priv, obj, true);
1339 }
1340
1282 /* Need a new fence register? */ 1341 /* Need a new fence register? */
1283 if (obj_priv->tiling_mode != I915_TILING_NONE) { 1342 if (obj_priv->tiling_mode != I915_TILING_NONE) {
1284 ret = i915_gem_object_get_fence_reg(obj, true); 1343 ret = i915_gem_object_get_fence_reg(obj, true);
@@ -1396,11 +1455,17 @@ void
1396i915_gem_release_mmap(struct drm_gem_object *obj) 1455i915_gem_release_mmap(struct drm_gem_object *obj)
1397{ 1456{
1398 struct drm_device *dev = obj->dev; 1457 struct drm_device *dev = obj->dev;
1458 struct drm_i915_private *dev_priv = dev->dev_private;
1399 struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); 1459 struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
1400 1460
1401 if (dev->dev_mapping) 1461 if (dev->dev_mapping)
1402 unmap_mapping_range(dev->dev_mapping, 1462 unmap_mapping_range(dev->dev_mapping,
1403 obj_priv->mmap_offset, obj->size, 1); 1463 obj_priv->mmap_offset, obj->size, 1);
1464
1465 if (obj_priv->fault_mappable) {
1466 obj_priv->fault_mappable = false;
1467 i915_gem_info_update_mappable(dev_priv, obj, false);
1468 }
1404} 1469}
1405 1470
1406static void 1471static void
@@ -2177,7 +2242,7 @@ i915_gem_object_unbind(struct drm_gem_object *obj)
2177 i915_gem_object_put_pages(obj); 2242 i915_gem_object_put_pages(obj);
2178 BUG_ON(obj_priv->pages_refcount); 2243 BUG_ON(obj_priv->pages_refcount);
2179 2244
2180 i915_gem_info_remove_gtt(dev_priv, obj->size); 2245 i915_gem_info_remove_gtt(dev_priv, obj);
2181 list_del_init(&obj_priv->mm_list); 2246 list_del_init(&obj_priv->mm_list);
2182 2247
2183 drm_mm_put_block(obj_priv->gtt_space); 2248 drm_mm_put_block(obj_priv->gtt_space);
@@ -2763,9 +2828,11 @@ i915_gem_object_bind_to_gtt(struct drm_gem_object *obj,
2763 goto search_free; 2828 goto search_free;
2764 } 2829 }
2765 2830
2831 obj_priv->gtt_offset = obj_priv->gtt_space->start;
2832
2766 /* keep track of bounds object by adding it to the inactive list */ 2833 /* keep track of bounds object by adding it to the inactive list */
2767 list_add_tail(&obj_priv->mm_list, &dev_priv->mm.inactive_list); 2834 list_add_tail(&obj_priv->mm_list, &dev_priv->mm.inactive_list);
2768 i915_gem_info_add_gtt(dev_priv, obj->size); 2835 i915_gem_info_add_gtt(dev_priv, obj);
2769 2836
2770 /* Assert that the object is not currently in any GPU domain. As it 2837 /* Assert that the object is not currently in any GPU domain. As it
2771 * wasn't in the GTT, there shouldn't be any way it could have been in 2838 * wasn't in the GTT, there shouldn't be any way it could have been in
@@ -2774,7 +2841,6 @@ i915_gem_object_bind_to_gtt(struct drm_gem_object *obj,
2774 BUG_ON(obj->read_domains & I915_GEM_GPU_DOMAINS); 2841 BUG_ON(obj->read_domains & I915_GEM_GPU_DOMAINS);
2775 BUG_ON(obj->write_domain & I915_GEM_GPU_DOMAINS); 2842 BUG_ON(obj->write_domain & I915_GEM_GPU_DOMAINS);
2776 2843
2777 obj_priv->gtt_offset = obj_priv->gtt_space->start;
2778 trace_i915_gem_object_bind(obj, obj_priv->gtt_offset, mappable); 2844 trace_i915_gem_object_bind(obj, obj_priv->gtt_offset, mappable);
2779 2845
2780 return 0; 2846 return 0;
@@ -4107,11 +4173,12 @@ i915_gem_object_pin(struct drm_gem_object *obj, uint32_t alignment,
4107 * remove it from the inactive list 4173 * remove it from the inactive list
4108 */ 4174 */
4109 if (obj_priv->pin_count == 1) { 4175 if (obj_priv->pin_count == 1) {
4110 i915_gem_info_add_pin(dev_priv, obj->size); 4176 i915_gem_info_add_pin(dev_priv, obj, mappable);
4111 if (!obj_priv->active) 4177 if (!obj_priv->active)
4112 list_move_tail(&obj_priv->mm_list, 4178 list_move_tail(&obj_priv->mm_list,
4113 &dev_priv->mm.pinned_list); 4179 &dev_priv->mm.pinned_list);
4114 } 4180 }
4181 BUG_ON(!obj_priv->pin_mappable && mappable);
4115 4182
4116 WARN_ON(i915_verify_lists(dev)); 4183 WARN_ON(i915_verify_lists(dev));
4117 return 0; 4184 return 0;
@@ -4137,7 +4204,7 @@ i915_gem_object_unpin(struct drm_gem_object *obj)
4137 if (!obj_priv->active) 4204 if (!obj_priv->active)
4138 list_move_tail(&obj_priv->mm_list, 4205 list_move_tail(&obj_priv->mm_list,
4139 &dev_priv->mm.inactive_list); 4206 &dev_priv->mm.inactive_list);
4140 i915_gem_info_remove_pin(dev_priv, obj->size); 4207 i915_gem_info_remove_pin(dev_priv, obj);
4141 } 4208 }
4142 WARN_ON(i915_verify_lists(dev)); 4209 WARN_ON(i915_verify_lists(dev));
4143} 4210}