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.c113
1 files changed, 111 insertions, 2 deletions
diff --git a/drivers/gpu/drm/drm_mm.c b/drivers/gpu/drm/drm_mm.c
index 97dc5a4f0de4..2ac074c8f5d2 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.
@@ -320,7 +358,7 @@ struct drm_mm_node *drm_mm_search_free(const struct drm_mm *mm,
320 if (entry->size >= size + wasted) { 358 if (entry->size >= size + wasted) {
321 if (!best_match) 359 if (!best_match)
322 return entry; 360 return entry;
323 if (size < best_size) { 361 if (entry->size < best_size) {
324 best = entry; 362 best = entry;
325 best_size = entry->size; 363 best_size = entry->size;
326 } 364 }
@@ -331,6 +369,57 @@ 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 (entry->start + wasted + size) <= end) {
410 if (!best_match)
411 return entry;
412 if (entry->size < best_size) {
413 best = entry;
414 best_size = entry->size;
415 }
416 }
417 }
418
419 return best;
420}
421EXPORT_SYMBOL(drm_mm_search_free_in_range);
422
334int drm_mm_clean(struct drm_mm * mm) 423int drm_mm_clean(struct drm_mm * mm)
335{ 424{
336 struct list_head *head = &mm->ml_entry; 425 struct list_head *head = &mm->ml_entry;
@@ -381,6 +470,26 @@ void drm_mm_takedown(struct drm_mm * mm)
381} 470}
382EXPORT_SYMBOL(drm_mm_takedown); 471EXPORT_SYMBOL(drm_mm_takedown);
383 472
473void drm_mm_debug_table(struct drm_mm *mm, const char *prefix)
474{
475 struct drm_mm_node *entry;
476 int total_used = 0, total_free = 0, total = 0;
477
478 list_for_each_entry(entry, &mm->ml_entry, ml_entry) {
479 printk(KERN_DEBUG "%s 0x%08lx-0x%08lx: %8ld: %s\n",
480 prefix, entry->start, entry->start + entry->size,
481 entry->size, entry->free ? "free" : "used");
482 total += entry->size;
483 if (entry->free)
484 total_free += entry->size;
485 else
486 total_used += entry->size;
487 }
488 printk(KERN_DEBUG "%s total: %d, used %d free %d\n", prefix, total,
489 total_used, total_free);
490}
491EXPORT_SYMBOL(drm_mm_debug_table);
492
384#if defined(CONFIG_DEBUG_FS) 493#if defined(CONFIG_DEBUG_FS)
385int drm_mm_dump_table(struct seq_file *m, struct drm_mm *mm) 494int drm_mm_dump_table(struct seq_file *m, struct drm_mm *mm)
386{ 495{
@@ -395,7 +504,7 @@ int drm_mm_dump_table(struct seq_file *m, struct drm_mm *mm)
395 else 504 else
396 total_used += entry->size; 505 total_used += entry->size;
397 } 506 }
398 seq_printf(m, "total: %d, used %d free %d\n", total, total_free, total_used); 507 seq_printf(m, "total: %d, used %d free %d\n", total, total_used, total_free);
399 return 0; 508 return 0;
400} 509}
401EXPORT_SYMBOL(drm_mm_dump_table); 510EXPORT_SYMBOL(drm_mm_dump_table);