aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/drm_mm.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/drm_mm.c')
-rw-r--r--drivers/gpu/drm/drm_mm.c110
1 files changed, 109 insertions, 1 deletions
diff --git a/drivers/gpu/drm/drm_mm.c b/drivers/gpu/drm/drm_mm.c
index 97dc5a4f0de4..d7d7eac3ddd2 100644
--- a/drivers/gpu/drm/drm_mm.c
+++ b/drivers/gpu/drm/drm_mm.c
@@ -226,6 +226,44 @@ struct drm_mm_node *drm_mm_get_block_generic(struct drm_mm_node *node,
226} 226}
227EXPORT_SYMBOL(drm_mm_get_block_generic); 227EXPORT_SYMBOL(drm_mm_get_block_generic);
228 228
229struct drm_mm_node *drm_mm_get_block_range_generic(struct drm_mm_node *node,
230 unsigned long size,
231 unsigned alignment,
232 unsigned long start,
233 unsigned long end,
234 int atomic)
235{
236 struct drm_mm_node *align_splitoff = NULL;
237 unsigned tmp = 0;
238 unsigned wasted = 0;
239
240 if (node->start < start)
241 wasted += start - node->start;
242 if (alignment)
243 tmp = ((node->start + wasted) % alignment);
244
245 if (tmp)
246 wasted += alignment - tmp;
247 if (wasted) {
248 align_splitoff = drm_mm_split_at_start(node, wasted, atomic);
249 if (unlikely(align_splitoff == NULL))
250 return NULL;
251 }
252
253 if (node->size == size) {
254 list_del_init(&node->fl_entry);
255 node->free = 0;
256 } else {
257 node = drm_mm_split_at_start(node, size, atomic);
258 }
259
260 if (align_splitoff)
261 drm_mm_put_block(align_splitoff);
262
263 return node;
264}
265EXPORT_SYMBOL(drm_mm_get_block_range_generic);
266
229/* 267/*
230 * Put a block. Merge with the previous and / or next block if they are free. 268 * Put a block. Merge with the previous and / or next block if they are free.
231 * Otherwise add to the free stack. 269 * Otherwise add to the free stack.
@@ -331,6 +369,56 @@ struct drm_mm_node *drm_mm_search_free(const struct drm_mm *mm,
331} 369}
332EXPORT_SYMBOL(drm_mm_search_free); 370EXPORT_SYMBOL(drm_mm_search_free);
333 371
372struct drm_mm_node *drm_mm_search_free_in_range(const struct drm_mm *mm,
373 unsigned long size,
374 unsigned alignment,
375 unsigned long start,
376 unsigned long end,
377 int best_match)
378{
379 struct list_head *list;
380 const struct list_head *free_stack = &mm->fl_entry;
381 struct drm_mm_node *entry;
382 struct drm_mm_node *best;
383 unsigned long best_size;
384 unsigned wasted;
385
386 best = NULL;
387 best_size = ~0UL;
388
389 list_for_each(list, free_stack) {
390 entry = list_entry(list, struct drm_mm_node, fl_entry);
391 wasted = 0;
392
393 if (entry->size < size)
394 continue;
395
396 if (entry->start > end || (entry->start+entry->size) < start)
397 continue;
398
399 if (entry->start < start)
400 wasted += start - entry->start;
401
402 if (alignment) {
403 register unsigned tmp = (entry->start + wasted) % alignment;
404 if (tmp)
405 wasted += alignment - tmp;
406 }
407
408 if (entry->size >= size + wasted) {
409 if (!best_match)
410 return entry;
411 if (size < best_size) {
412 best = entry;
413 best_size = entry->size;
414 }
415 }
416 }
417
418 return best;
419}
420EXPORT_SYMBOL(drm_mm_search_free_in_range);
421
334int drm_mm_clean(struct drm_mm * mm) 422int drm_mm_clean(struct drm_mm * mm)
335{ 423{
336 struct list_head *head = &mm->ml_entry; 424 struct list_head *head = &mm->ml_entry;
@@ -381,6 +469,26 @@ void drm_mm_takedown(struct drm_mm * mm)
381} 469}
382EXPORT_SYMBOL(drm_mm_takedown); 470EXPORT_SYMBOL(drm_mm_takedown);
383 471
472void drm_mm_debug_table(struct drm_mm *mm, const char *prefix)
473{
474 struct drm_mm_node *entry;
475 int total_used = 0, total_free = 0, total = 0;
476
477 list_for_each_entry(entry, &mm->ml_entry, ml_entry) {
478 printk(KERN_DEBUG "%s 0x%08lx-0x%08lx: %8ld: %s\n",
479 prefix, entry->start, entry->start + entry->size,
480 entry->size, entry->free ? "free" : "used");
481 total += entry->size;
482 if (entry->free)
483 total_free += entry->size;
484 else
485 total_used += entry->size;
486 }
487 printk(KERN_DEBUG "%s total: %d, used %d free %d\n", prefix, total,
488 total_used, total_free);
489}
490EXPORT_SYMBOL(drm_mm_debug_table);
491
384#if defined(CONFIG_DEBUG_FS) 492#if defined(CONFIG_DEBUG_FS)
385int drm_mm_dump_table(struct seq_file *m, struct drm_mm *mm) 493int drm_mm_dump_table(struct seq_file *m, struct drm_mm *mm)
386{ 494{
@@ -395,7 +503,7 @@ int drm_mm_dump_table(struct seq_file *m, struct drm_mm *mm)
395 else 503 else
396 total_used += entry->size; 504 total_used += entry->size;
397 } 505 }
398 seq_printf(m, "total: %d, used %d free %d\n", total, total_free, total_used); 506 seq_printf(m, "total: %d, used %d free %d\n", total, total_used, total_free);
399 return 0; 507 return 0;
400} 508}
401EXPORT_SYMBOL(drm_mm_dump_table); 509EXPORT_SYMBOL(drm_mm_dump_table);