184,19 → 184,27 |
* -ENOSPC if no suitable free area is available. The preallocated memory node |
* must be cleared. |
*/ |
int drm_mm_insert_node(struct drm_mm *mm, struct drm_mm_node *node, |
unsigned long size, unsigned alignment) |
int drm_mm_insert_node_generic(struct drm_mm *mm, struct drm_mm_node *node, |
unsigned long size, unsigned alignment, |
unsigned long color) |
{ |
struct drm_mm_node *hole_node; |
|
hole_node = drm_mm_search_free(mm, size, alignment, false); |
hole_node = drm_mm_search_free_generic(mm, size, alignment, |
color, 0); |
if (!hole_node) |
return -ENOSPC; |
|
drm_mm_insert_helper(hole_node, node, size, alignment, 0); |
|
drm_mm_insert_helper(hole_node, node, size, alignment, color); |
return 0; |
} |
EXPORT_SYMBOL(drm_mm_insert_node_generic); |
|
int drm_mm_insert_node(struct drm_mm *mm, struct drm_mm_node *node, |
unsigned long size, unsigned alignment) |
{ |
return drm_mm_insert_node_generic(mm, node, size, alignment, 0); |
} |
EXPORT_SYMBOL(drm_mm_insert_node); |
|
static void drm_mm_insert_helper_range(struct drm_mm_node *hole_node, |
213,12 → 221,14 |
|
BUG_ON(!hole_node->hole_follows || node->allocated); |
|
if (adj_start < start) |
adj_start = start; |
if (adj_end > end) |
adj_end = end; |
|
if (mm->color_adjust) |
mm->color_adjust(hole_node, color, &adj_start, &adj_end); |
|
if (adj_start < start) |
adj_start = start; |
|
if (alignment) { |
unsigned tmp = adj_start % alignment; |
if (tmp) |
275,22 → 285,31 |
* -ENOSPC if no suitable free area is available. This is for range |
* restricted allocations. The preallocated memory node must be cleared. |
*/ |
int drm_mm_insert_node_in_range(struct drm_mm *mm, struct drm_mm_node *node, |
unsigned long size, unsigned alignment, |
int drm_mm_insert_node_in_range_generic(struct drm_mm *mm, struct drm_mm_node *node, |
unsigned long size, unsigned alignment, unsigned long color, |
unsigned long start, unsigned long end) |
{ |
struct drm_mm_node *hole_node; |
|
hole_node = drm_mm_search_free_in_range(mm, size, alignment, |
start, end, false); |
hole_node = drm_mm_search_free_in_range_generic(mm, |
size, alignment, color, |
start, end, 0); |
if (!hole_node) |
return -ENOSPC; |
|
drm_mm_insert_helper_range(hole_node, node, size, alignment, 0, |
drm_mm_insert_helper_range(hole_node, node, |
size, alignment, color, |
start, end); |
|
return 0; |
} |
EXPORT_SYMBOL(drm_mm_insert_node_in_range_generic); |
|
int drm_mm_insert_node_in_range(struct drm_mm *mm, struct drm_mm_node *node, |
unsigned long size, unsigned alignment, |
unsigned long start, unsigned long end) |
{ |
return drm_mm_insert_node_in_range_generic(mm, node, size, alignment, 0, start, end); |
} |
EXPORT_SYMBOL(drm_mm_insert_node_in_range); |
|
/** |
489,7 → 508,7 |
mm->scan_size = size; |
mm->scanned_blocks = 0; |
mm->scan_hit_start = 0; |
mm->scan_hit_size = 0; |
mm->scan_hit_end = 0; |
mm->scan_check_range = 0; |
mm->prev_scanned_node = NULL; |
} |
516,7 → 535,7 |
mm->scan_size = size; |
mm->scanned_blocks = 0; |
mm->scan_hit_start = 0; |
mm->scan_hit_size = 0; |
mm->scan_hit_end = 0; |
mm->scan_start = start; |
mm->scan_end = end; |
mm->scan_check_range = 1; |
535,8 → 554,7 |
struct drm_mm *mm = node->mm; |
struct drm_mm_node *prev_node; |
unsigned long hole_start, hole_end; |
unsigned long adj_start; |
unsigned long adj_end; |
unsigned long adj_start, adj_end; |
|
mm->scanned_blocks++; |
|
553,15 → 571,9 |
node->node_list.next = &mm->prev_scanned_node->node_list; |
mm->prev_scanned_node = node; |
|
hole_start = drm_mm_hole_node_start(prev_node); |
hole_end = drm_mm_hole_node_end(prev_node); |
adj_start = hole_start = drm_mm_hole_node_start(prev_node); |
adj_end = hole_end = drm_mm_hole_node_end(prev_node); |
|
adj_start = hole_start; |
adj_end = hole_end; |
|
if (mm->color_adjust) |
mm->color_adjust(prev_node, mm->scan_color, &adj_start, &adj_end); |
|
if (mm->scan_check_range) { |
if (adj_start < mm->scan_start) |
adj_start = mm->scan_start; |
569,11 → 581,14 |
adj_end = mm->scan_end; |
} |
|
if (mm->color_adjust) |
mm->color_adjust(prev_node, mm->scan_color, |
&adj_start, &adj_end); |
|
if (check_free_hole(adj_start, adj_end, |
mm->scan_size, mm->scan_alignment)) { |
mm->scan_hit_start = hole_start; |
mm->scan_hit_size = hole_end; |
|
mm->scan_hit_end = hole_end; |
return 1; |
} |
|
609,20 → 624,11 |
node_list); |
|
prev_node->hole_follows = node->scanned_preceeds_hole; |
INIT_LIST_HEAD(&node->node_list); |
list_add(&node->node_list, &prev_node->node_list); |
|
/* Only need to check for containement because start&size for the |
* complete resulting free block (not just the desired part) is |
* stored. */ |
if (node->start >= mm->scan_hit_start && |
node->start + node->size |
<= mm->scan_hit_start + mm->scan_hit_size) { |
return 1; |
return (drm_mm_hole_node_end(node) > mm->scan_hit_start && |
node->start < mm->scan_hit_end); |
} |
|
return 0; |
} |
EXPORT_SYMBOL(drm_mm_scan_remove_block); |
|
int drm_mm_clean(struct drm_mm * mm) |
679,3 → 685,78 |
BUG_ON(mm->num_unused != 0); |
} |
EXPORT_SYMBOL(drm_mm_takedown); |
|
void drm_mm_debug_table(struct drm_mm *mm, const char *prefix) |
{ |
struct drm_mm_node *entry; |
unsigned long total_used = 0, total_free = 0, total = 0; |
unsigned long hole_start, hole_end, hole_size; |
|
hole_start = drm_mm_hole_node_start(&mm->head_node); |
hole_end = drm_mm_hole_node_end(&mm->head_node); |
hole_size = hole_end - hole_start; |
if (hole_size) |
printk(KERN_DEBUG "%s 0x%08lx-0x%08lx: %8lu: free\n", |
prefix, hole_start, hole_end, |
hole_size); |
total_free += hole_size; |
|
drm_mm_for_each_node(entry, mm) { |
printk(KERN_DEBUG "%s 0x%08lx-0x%08lx: %8lu: used\n", |
prefix, entry->start, entry->start + entry->size, |
entry->size); |
total_used += entry->size; |
|
if (entry->hole_follows) { |
hole_start = drm_mm_hole_node_start(entry); |
hole_end = drm_mm_hole_node_end(entry); |
hole_size = hole_end - hole_start; |
printk(KERN_DEBUG "%s 0x%08lx-0x%08lx: %8lu: free\n", |
prefix, hole_start, hole_end, |
hole_size); |
total_free += hole_size; |
} |
} |
total = total_free + total_used; |
|
printk(KERN_DEBUG "%s total: %lu, used %lu free %lu\n", prefix, total, |
total_used, total_free); |
} |
EXPORT_SYMBOL(drm_mm_debug_table); |
|
#if defined(CONFIG_DEBUG_FS) |
int drm_mm_dump_table(struct seq_file *m, struct drm_mm *mm) |
{ |
struct drm_mm_node *entry; |
unsigned long total_used = 0, total_free = 0, total = 0; |
unsigned long hole_start, hole_end, hole_size; |
|
hole_start = drm_mm_hole_node_start(&mm->head_node); |
hole_end = drm_mm_hole_node_end(&mm->head_node); |
hole_size = hole_end - hole_start; |
if (hole_size) |
seq_printf(m, "0x%08lx-0x%08lx: 0x%08lx: free\n", |
hole_start, hole_end, hole_size); |
total_free += hole_size; |
|
drm_mm_for_each_node(entry, mm) { |
seq_printf(m, "0x%08lx-0x%08lx: 0x%08lx: used\n", |
entry->start, entry->start + entry->size, |
entry->size); |
total_used += entry->size; |
if (entry->hole_follows) { |
hole_start = drm_mm_hole_node_start(entry); |
hole_end = drm_mm_hole_node_end(entry); |
hole_size = hole_end - hole_start; |
seq_printf(m, "0x%08lx-0x%08lx: 0x%08lx: free\n", |
hole_start, hole_end, hole_size); |
total_free += hole_size; |
} |
} |
total = total_free + total_used; |
|
seq_printf(m, "total: %lu, used %lu free %lu\n", total, total_used, total_free); |
return 0; |
} |
EXPORT_SYMBOL(drm_mm_dump_table); |
#endif |