aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2009-05-22 09:14:22 -0400
committerDave Airlie <airlied@redhat.com>2009-06-14 19:35:33 -0400
commite6c03c5b40314d787f7053f631594d6b1bd609e8 (patch)
tree78812c9e3bd28996817b5653e024915cb794b325
parent602c11a8ee62d49cddbc5972e5edb876dd415113 (diff)
drm: Memory fragmentation from lost alignment blocks
If the block needs an alignment but otherwise fits exactly into the tail, then the split-off block from the start would remain marked as non-free. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Acked-by: Thomas Hellstrom <thellstrom@vmware.com> Signed-off-by: Dave Airlie <airlied@redhat.com>
-rw-r--r--drivers/gpu/drm/drm_mm.c20
1 files changed, 9 insertions, 11 deletions
diff --git a/drivers/gpu/drm/drm_mm.c b/drivers/gpu/drm/drm_mm.c
index 7819fd930a51..a912a0ff11cc 100644
--- a/drivers/gpu/drm/drm_mm.c
+++ b/drivers/gpu/drm/drm_mm.c
@@ -188,36 +188,34 @@ static struct drm_mm_node *drm_mm_split_at_start(struct drm_mm_node *parent,
188 188
189 189
190 190
191struct drm_mm_node *drm_mm_get_block(struct drm_mm_node * parent, 191struct drm_mm_node *drm_mm_get_block(struct drm_mm_node *node,
192 unsigned long size, unsigned alignment) 192 unsigned long size, unsigned alignment)
193{ 193{
194 194
195 struct drm_mm_node *align_splitoff = NULL; 195 struct drm_mm_node *align_splitoff = NULL;
196 struct drm_mm_node *child;
197 unsigned tmp = 0; 196 unsigned tmp = 0;
198 197
199 if (alignment) 198 if (alignment)
200 tmp = parent->start % alignment; 199 tmp = node->start % alignment;
201 200
202 if (tmp) { 201 if (tmp) {
203 align_splitoff = 202 align_splitoff =
204 drm_mm_split_at_start(parent, alignment - tmp, 0); 203 drm_mm_split_at_start(node, alignment - tmp, 0);
205 if (unlikely(align_splitoff == NULL)) 204 if (unlikely(align_splitoff == NULL))
206 return NULL; 205 return NULL;
207 } 206 }
208 207
209 if (parent->size == size) { 208 if (node->size == size) {
210 list_del_init(&parent->fl_entry); 209 list_del_init(&node->fl_entry);
211 parent->free = 0; 210 node->free = 0;
212 return parent;
213 } else { 211 } else {
214 child = drm_mm_split_at_start(parent, size, 0); 212 node = drm_mm_split_at_start(node, size, 0);
215 } 213 }
216 214
217 if (align_splitoff) 215 if (align_splitoff)
218 drm_mm_put_block(align_splitoff); 216 drm_mm_put_block(align_splitoff);
219 217
220 return child; 218 return node;
221} 219}
222 220
223EXPORT_SYMBOL(drm_mm_get_block); 221EXPORT_SYMBOL(drm_mm_get_block);