diff options
author | Daniel Vetter <daniel.vetter@ffwll.ch> | 2010-10-01 16:05:20 -0400 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2010-10-27 18:31:08 -0400 |
commit | fb7d516af11837126eb1e4a44ab0653bf9b57702 (patch) | |
tree | f74c587c80c53f6f30fdab9d80d41a40bbd1bc5e | |
parent | ec57d2602a985b54b53e53098f74fdefc24723af (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.c | 6 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_drv.h | 12 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_gem.c | 93 |
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 | ||
86 | static void i915_gem_info_add_gtt(struct drm_i915_private *dev_priv, | 86 | static 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 | ||
93 | static void i915_gem_info_remove_gtt(struct drm_i915_private *dev_priv, | 100 | static 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 | */ | ||
119 | static void | ||
120 | i915_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 | ||
100 | static void i915_gem_info_add_pin(struct drm_i915_private *dev_priv, | 141 | static 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 | ||
107 | static void i915_gem_info_remove_pin(struct drm_i915_private *dev_priv, | 154 | static 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 | ||
114 | int | 166 | int |
@@ -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 | |||
1396 | i915_gem_release_mmap(struct drm_gem_object *obj) | 1455 | i915_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 | ||
1406 | static void | 1471 | static 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 | } |