mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-20 03:04:01 +08:00
drm: mm: fix range restricted allocations
With the code cleanup in7a6b2896f2
is the first bad commit commit7a6b2896f2
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=29738 Reported-by-Tested-by: Till MAtthiesen <entropy@everymail.net> Acked-by: Alex Deucher <alexdeucher@gmail.com> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch> Signed-off-by: Dave Airlie <airlied@redhat.com>
This commit is contained in:
parent
5afda9e9a4
commit
7521473305
@ -285,21 +285,21 @@ void drm_mm_put_block(struct drm_mm_node *cur)
|
||||
|
||||
EXPORT_SYMBOL(drm_mm_put_block);
|
||||
|
||||
static int check_free_mm_node(struct drm_mm_node *entry, unsigned long size,
|
||||
unsigned alignment)
|
||||
static int check_free_hole(unsigned long start, unsigned long end,
|
||||
unsigned long size, unsigned alignment)
|
||||
{
|
||||
unsigned wasted = 0;
|
||||
|
||||
if (entry->size < size)
|
||||
if (end - start < size)
|
||||
return 0;
|
||||
|
||||
if (alignment) {
|
||||
register unsigned tmp = entry->start % alignment;
|
||||
unsigned tmp = start % alignment;
|
||||
if (tmp)
|
||||
wasted = alignment - tmp;
|
||||
}
|
||||
|
||||
if (entry->size >= size + wasted) {
|
||||
if (end >= start + size + wasted) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -320,7 +320,8 @@ struct drm_mm_node *drm_mm_search_free(const struct drm_mm *mm,
|
||||
best_size = ~0UL;
|
||||
|
||||
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;
|
||||
|
||||
if (!best_match)
|
||||
@ -353,10 +354,12 @@ struct drm_mm_node *drm_mm_search_free_in_range(const struct drm_mm *mm,
|
||||
best_size = ~0UL;
|
||||
|
||||
list_for_each_entry(entry, &mm->free_stack, free_stack) {
|
||||
if (entry->start > end || (entry->start+entry->size) < start)
|
||||
continue;
|
||||
unsigned long adj_start = entry->start < start ?
|
||||
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;
|
||||
|
||||
if (!best_match)
|
||||
@ -449,7 +452,8 @@ int drm_mm_scan_add_block(struct drm_mm_node *node)
|
||||
node->free_stack.prev = prev_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_size = node->size;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user