diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2009-05-22 09:14:22 -0400 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2009-06-14 19:35:33 -0400 |
commit | e6c03c5b40314d787f7053f631594d6b1bd609e8 (patch) | |
tree | 78812c9e3bd28996817b5653e024915cb794b325 | |
parent | 602c11a8ee62d49cddbc5972e5edb876dd415113 (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.c | 20 |
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 | ||
191 | struct drm_mm_node *drm_mm_get_block(struct drm_mm_node * parent, | 191 | struct 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 | ||
223 | EXPORT_SYMBOL(drm_mm_get_block); | 221 | EXPORT_SYMBOL(drm_mm_get_block); |