46 #include <linux/slab.h>
48 #include <linux/export.h>
50 #define MM_UNUSED_TARGET 4
105 static inline unsigned long drm_mm_hole_node_start(
struct drm_mm_node *hole_node)
107 return hole_node->
start + hole_node->
size;
110 static inline unsigned long drm_mm_hole_node_end(
struct drm_mm_node *hole_node)
116 return next_node->
start;
119 static void drm_mm_insert_helper(
struct drm_mm_node *hole_node,
125 unsigned long hole_start = drm_mm_hole_node_start(hole_node);
126 unsigned long hole_end = drm_mm_hole_node_end(hole_node);
127 unsigned long adj_start = hole_start;
128 unsigned long adj_end = hole_end;
133 mm->
color_adjust(hole_node, color, &adj_start, &adj_end);
138 adj_start += alignment -
tmp;
141 if (adj_start == hole_start) {
146 node->
start = adj_start;
158 if (node->
start + node->
size < hole_end) {
172 node = drm_mm_kmalloc(hole_node->
mm, atomic);
176 drm_mm_insert_helper(hole_node, node, size, alignment, color);
188 unsigned long size,
unsigned alignment)
192 hole_node = drm_mm_search_free(mm, size, alignment,
false);
196 drm_mm_insert_helper(hole_node, node, size, alignment, 0);
202 static void drm_mm_insert_helper_range(
struct drm_mm_node *hole_node,
204 unsigned long size,
unsigned alignment,
206 unsigned long start,
unsigned long end)
209 unsigned long hole_start = drm_mm_hole_node_start(hole_node);
210 unsigned long hole_end = drm_mm_hole_node_end(hole_node);
211 unsigned long adj_start = hole_start;
212 unsigned long adj_end = hole_end;
217 mm->
color_adjust(hole_node, color, &adj_start, &adj_end);
219 if (adj_start < start)
225 adj_start += alignment -
tmp;
228 if (adj_start == hole_start) {
233 node->
start = adj_start;
246 if (node->
start + node->
size < hole_end) {
262 node = drm_mm_kmalloc(hole_node->
mm, atomic);
266 drm_mm_insert_helper_range(hole_node, node, size, alignment, color,
279 unsigned long size,
unsigned alignment,
280 unsigned long start,
unsigned long end)
284 hole_node = drm_mm_search_free_in_range(mm, size, alignment,
289 drm_mm_insert_helper_range(hole_node, node, size, alignment, 0,
311 BUG_ON(drm_mm_hole_node_start(node)
312 == drm_mm_hole_node_end(node));
315 BUG_ON(drm_mm_hole_node_start(node)
316 != drm_mm_hole_node_end(node));
351 static int check_free_hole(
unsigned long start,
unsigned long end,
352 unsigned long size,
unsigned alignment)
354 if (end - start < size)
360 start += alignment -
tmp;
363 return end >= start +
size;
374 unsigned long best_size;
382 unsigned long adj_start = drm_mm_hole_node_start(entry);
383 unsigned long adj_end = drm_mm_hole_node_end(entry);
387 if (adj_end <= adj_start)
392 if (!check_free_hole(adj_start, adj_end, size, alignment))
398 if (entry->
size < best_size) {
400 best_size = entry->
size;
418 unsigned long best_size;
426 unsigned long adj_start = drm_mm_hole_node_start(entry) < start ?
427 start : drm_mm_hole_node_start(entry);
428 unsigned long adj_end = drm_mm_hole_node_end(entry) > end ?
429 end : drm_mm_hole_node_end(entry);
435 if (adj_end <= adj_start)
439 if (!check_free_hole(adj_start, adj_end, size, alignment))
445 if (entry->
size < best_size) {
447 best_size = entry->
size;
460 list_replace(&old->
node_list, &new->node_list);
461 list_replace(&old->
hole_stack, &new->hole_stack);
464 new->start = old->
start;
465 new->size = old->
size;
466 new->color = old->
color;
537 unsigned long hole_start, hole_end;
538 unsigned long adj_start;
539 unsigned long adj_end;
556 hole_start = drm_mm_hole_node_start(prev_node);
557 hole_end = drm_mm_hole_node_end(prev_node);
559 adj_start = hole_start;
566 if (adj_start < mm->scan_start)
572 if (check_free_hole(adj_start, adj_end,
632 return (head->
next->next == head);
645 INIT_LIST_HEAD(&mm->
head_node.node_list);
646 INIT_LIST_HEAD(&mm->
head_node.hole_stack);
666 if (!list_empty(&mm->
head_node.node_list)) {
667 DRM_ERROR(
"Memory manager not clean. Delaying takedown\n");
686 unsigned long total_used = 0, total_free = 0, total = 0;
687 unsigned long hole_start, hole_end, hole_size;
689 hole_start = drm_mm_hole_node_start(&mm->
head_node);
690 hole_end = drm_mm_hole_node_end(&mm->
head_node);
691 hole_size = hole_end - hole_start;
694 prefix, hole_start, hole_end,
696 total_free += hole_size;
702 total_used += entry->
size;
705 hole_start = drm_mm_hole_node_start(entry);
706 hole_end = drm_mm_hole_node_end(entry);
707 hole_size = hole_end - hole_start;
709 prefix, hole_start, hole_end,
711 total_free += hole_size;
714 total = total_free + total_used;
717 total_used, total_free);
721 #if defined(CONFIG_DEBUG_FS)
725 unsigned long total_used = 0, total_free = 0, total = 0;
726 unsigned long hole_start, hole_end, hole_size;
728 hole_start = drm_mm_hole_node_start(&mm->
head_node);
729 hole_end = drm_mm_hole_node_end(&mm->
head_node);
730 hole_size = hole_end - hole_start;
732 seq_printf(m,
"0x%08lx-0x%08lx: 0x%08lx: free\n",
733 hole_start, hole_end, hole_size);
734 total_free += hole_size;
737 seq_printf(m,
"0x%08lx-0x%08lx: 0x%08lx: used\n",
740 total_used += entry->
size;
742 hole_start = drm_mm_hole_node_start(entry);
743 hole_end = drm_mm_hole_node_end(entry);
744 hole_size = hole_end - hole_start;
745 seq_printf(m,
"0x%08lx-0x%08lx: 0x%08lx: free\n",
746 hole_start, hole_end, hole_size);
747 total_free += hole_size;
750 total = total_free + total_used;
752 seq_printf(m,
"total: %lu, used %lu free %lu\n", total, total_used, total_free);