Commit 75214733 authored by Daniel Vetter's avatar Daniel Vetter Committed by Dave Airlie

drm: mm: fix range restricted allocations

With the code cleanup in

7a6b2896 is the first bad commit
commit 7a6b2896
Author: Daniel Vetter <daniel.vetter@ffwll.ch>
Date:   Fri Jul 2 15:02:15 2010 +0100

    drm_mm: extract check_free_mm_node

I've botched up the range-restriction checks. The result is usually
an X server dying with SIGBUS in libpixman (software fallback rendering).
Change the code to adjust the start and end for range restricted
allocations. IMHO this even makes the code a bit clearer.

Fixes regression bug: https://bugs.freedesktop.org/show_bug.cgi?id=29738Reported-by-Tested-by: default avatarTill MAtthiesen <entropy@everymail.net>
Acked-by: default avatarAlex Deucher <alexdeucher@gmail.com>
Signed-off-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
parent 5afda9e9
...@@ -285,21 +285,21 @@ void drm_mm_put_block(struct drm_mm_node *cur) ...@@ -285,21 +285,21 @@ void drm_mm_put_block(struct drm_mm_node *cur)
EXPORT_SYMBOL(drm_mm_put_block); EXPORT_SYMBOL(drm_mm_put_block);
static int check_free_mm_node(struct drm_mm_node *entry, unsigned long size, static int check_free_hole(unsigned long start, unsigned long end,
unsigned alignment) unsigned long size, unsigned alignment)
{ {
unsigned wasted = 0; unsigned wasted = 0;
if (entry->size < size) if (end - start < size)
return 0; return 0;
if (alignment) { if (alignment) {
register unsigned tmp = entry->start % alignment; unsigned tmp = start % alignment;
if (tmp) if (tmp)
wasted = alignment - tmp; wasted = alignment - tmp;
} }
if (entry->size >= size + wasted) { if (end >= start + size + wasted) {
return 1; return 1;
} }
...@@ -320,7 +320,8 @@ struct drm_mm_node *drm_mm_search_free(const struct drm_mm *mm, ...@@ -320,7 +320,8 @@ struct drm_mm_node *drm_mm_search_free(const struct drm_mm *mm,
best_size = ~0UL; best_size = ~0UL;
list_for_each_entry(entry, &mm->free_stack, free_stack) { list_for_each_entry(entry, &mm->free_stack, free_stack) {
if (!check_free_mm_node(entry, size, alignment)) if (!check_free_hole(entry->start, entry->start + entry->size,
size, alignment))
continue; continue;
if (!best_match) if (!best_match)
...@@ -353,10 +354,12 @@ struct drm_mm_node *drm_mm_search_free_in_range(const struct drm_mm *mm, ...@@ -353,10 +354,12 @@ struct drm_mm_node *drm_mm_search_free_in_range(const struct drm_mm *mm,
best_size = ~0UL; best_size = ~0UL;
list_for_each_entry(entry, &mm->free_stack, free_stack) { list_for_each_entry(entry, &mm->free_stack, free_stack) {
if (entry->start > end || (entry->start+entry->size) < start) unsigned long adj_start = entry->start < start ?
continue; start : entry->start;
unsigned long adj_end = entry->start + entry->size > end ?
end : entry->start + entry->size;
if (!check_free_mm_node(entry, size, alignment)) if (!check_free_hole(adj_start, adj_end, size, alignment))
continue; continue;
if (!best_match) if (!best_match)
...@@ -449,7 +452,8 @@ int drm_mm_scan_add_block(struct drm_mm_node *node) ...@@ -449,7 +452,8 @@ int drm_mm_scan_add_block(struct drm_mm_node *node)
node->free_stack.prev = prev_free; node->free_stack.prev = prev_free;
node->free_stack.next = next_free; node->free_stack.next = next_free;
if (check_free_mm_node(node, mm->scan_size, mm->scan_alignment)) { if (check_free_hole(node->start, node->start + node->size,
mm->scan_size, mm->scan_alignment)) {
mm->scan_hit_start = node->start; mm->scan_hit_start = node->start;
mm->scan_hit_size = node->size; mm->scan_hit_size = node->size;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment