[PATCH] drm: mm: fix range restricted allocations

2010-08-26 Thread Daniel Vetter
With the code cleanup in

7a6b2896f261894dde287d3faefa4b432cddca53 is the first bad commit
commit 7a6b2896f261894dde287d3faefa4b432cddca53
Author: Daniel Vetter 
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.

Signed-off-by: Daniel Vetter 
---
 drivers/gpu/drm/drm_mm.c |   24 ++--
 1 files changed, 14 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/drm_mm.c b/drivers/gpu/drm/drm_mm.c
index da99edc..a6bfc30 100644
--- a/drivers/gpu/drm/drm_mm.c
+++ b/drivers/gpu/drm/drm_mm.c
@@ -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, >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, >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;

-- 
1.7.1



[PATCH] drm: mm: fix range restricted allocations

2010-08-26 Thread Daniel Vetter
With the code cleanup in

7a6b2896f261894dde287d3faefa4b432cddca53 is the first bad commit
commit 7a6b2896f261894dde287d3faefa4b432cddca53
Author: Daniel Vetter daniel.vet...@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.

Signed-off-by: Daniel Vetter daniel.vet...@ffwll.ch
---
 drivers/gpu/drm/drm_mm.c |   24 ++--
 1 files changed, 14 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/drm_mm.c b/drivers/gpu/drm/drm_mm.c
index da99edc..a6bfc30 100644
--- a/drivers/gpu/drm/drm_mm.c
+++ b/drivers/gpu/drm/drm_mm.c
@@ -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;
 
-- 
1.7.1

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel