xref: /linux/drivers/gpu/drm/drm_buddy.c (revision eee8227dd18868bb16dbf72e2ab11d1a9008b874)
1 // SPDX-License-Identifier: MIT
2 /*
3  * Copyright © 2021 Intel Corporation
4  */
5 
6 #include <kunit/test-bug.h>
7 
8 #include <linux/export.h>
9 #include <linux/kmemleak.h>
10 #include <linux/module.h>
11 #include <linux/sizes.h>
12 
13 #include <drm/drm_buddy.h>
14 #include <drm/drm_print.h>
15 
16 enum drm_buddy_free_tree {
17 	DRM_BUDDY_CLEAR_TREE = 0,
18 	DRM_BUDDY_DIRTY_TREE,
19 	DRM_BUDDY_MAX_FREE_TREES,
20 };
21 
22 static struct kmem_cache *slab_blocks;
23 
24 #define for_each_free_tree(tree) \
25 	for ((tree) = 0; (tree) < DRM_BUDDY_MAX_FREE_TREES; (tree)++)
26 
27 static struct drm_buddy_block *drm_block_alloc(struct drm_buddy *mm,
28 					       struct drm_buddy_block *parent,
29 					       unsigned int order,
30 					       u64 offset)
31 {
32 	struct drm_buddy_block *block;
33 
34 	BUG_ON(order > DRM_BUDDY_MAX_ORDER);
35 
36 	block = kmem_cache_zalloc(slab_blocks, GFP_KERNEL);
37 	if (!block)
38 		return NULL;
39 
40 	block->header = offset;
41 	block->header |= order;
42 	block->parent = parent;
43 
44 	RB_CLEAR_NODE(&block->rb);
45 
46 	BUG_ON(block->header & DRM_BUDDY_HEADER_UNUSED);
47 	return block;
48 }
49 
50 static void drm_block_free(struct drm_buddy *mm,
51 			   struct drm_buddy_block *block)
52 {
53 	kmem_cache_free(slab_blocks, block);
54 }
55 
56 static enum drm_buddy_free_tree
57 get_block_tree(struct drm_buddy_block *block)
58 {
59 	return drm_buddy_block_is_clear(block) ?
60 	       DRM_BUDDY_CLEAR_TREE : DRM_BUDDY_DIRTY_TREE;
61 }
62 
63 static struct drm_buddy_block *
64 rbtree_get_free_block(const struct rb_node *node)
65 {
66 	return node ? rb_entry(node, struct drm_buddy_block, rb) : NULL;
67 }
68 
69 static struct drm_buddy_block *
70 rbtree_last_free_block(struct rb_root *root)
71 {
72 	return rbtree_get_free_block(rb_last(root));
73 }
74 
75 static bool rbtree_is_empty(struct rb_root *root)
76 {
77 	return RB_EMPTY_ROOT(root);
78 }
79 
80 static bool drm_buddy_block_offset_less(const struct drm_buddy_block *block,
81 					const struct drm_buddy_block *node)
82 {
83 	return drm_buddy_block_offset(block) < drm_buddy_block_offset(node);
84 }
85 
86 static bool rbtree_block_offset_less(struct rb_node *block,
87 				     const struct rb_node *node)
88 {
89 	return drm_buddy_block_offset_less(rbtree_get_free_block(block),
90 					   rbtree_get_free_block(node));
91 }
92 
93 static void rbtree_insert(struct drm_buddy *mm,
94 			  struct drm_buddy_block *block,
95 			  enum drm_buddy_free_tree tree)
96 {
97 	rb_add(&block->rb,
98 	       &mm->free_trees[tree][drm_buddy_block_order(block)],
99 	       rbtree_block_offset_less);
100 }
101 
102 static void rbtree_remove(struct drm_buddy *mm,
103 			  struct drm_buddy_block *block)
104 {
105 	unsigned int order = drm_buddy_block_order(block);
106 	enum drm_buddy_free_tree tree;
107 	struct rb_root *root;
108 
109 	tree = get_block_tree(block);
110 	root = &mm->free_trees[tree][order];
111 
112 	rb_erase(&block->rb, root);
113 	RB_CLEAR_NODE(&block->rb);
114 }
115 
116 static void clear_reset(struct drm_buddy_block *block)
117 {
118 	block->header &= ~DRM_BUDDY_HEADER_CLEAR;
119 }
120 
121 static void mark_cleared(struct drm_buddy_block *block)
122 {
123 	block->header |= DRM_BUDDY_HEADER_CLEAR;
124 }
125 
126 static void mark_allocated(struct drm_buddy *mm,
127 			   struct drm_buddy_block *block)
128 {
129 	block->header &= ~DRM_BUDDY_HEADER_STATE;
130 	block->header |= DRM_BUDDY_ALLOCATED;
131 
132 	rbtree_remove(mm, block);
133 }
134 
135 static void mark_free(struct drm_buddy *mm,
136 		      struct drm_buddy_block *block)
137 {
138 	enum drm_buddy_free_tree tree;
139 
140 	block->header &= ~DRM_BUDDY_HEADER_STATE;
141 	block->header |= DRM_BUDDY_FREE;
142 
143 	tree = get_block_tree(block);
144 	rbtree_insert(mm, block, tree);
145 }
146 
147 static void mark_split(struct drm_buddy *mm,
148 		       struct drm_buddy_block *block)
149 {
150 	block->header &= ~DRM_BUDDY_HEADER_STATE;
151 	block->header |= DRM_BUDDY_SPLIT;
152 
153 	rbtree_remove(mm, block);
154 }
155 
156 static inline bool overlaps(u64 s1, u64 e1, u64 s2, u64 e2)
157 {
158 	return s1 <= e2 && e1 >= s2;
159 }
160 
161 static inline bool contains(u64 s1, u64 e1, u64 s2, u64 e2)
162 {
163 	return s1 <= s2 && e1 >= e2;
164 }
165 
166 static struct drm_buddy_block *
167 __get_buddy(struct drm_buddy_block *block)
168 {
169 	struct drm_buddy_block *parent;
170 
171 	parent = block->parent;
172 	if (!parent)
173 		return NULL;
174 
175 	if (parent->left == block)
176 		return parent->right;
177 
178 	return parent->left;
179 }
180 
181 static unsigned int __drm_buddy_free(struct drm_buddy *mm,
182 				     struct drm_buddy_block *block,
183 				     bool force_merge)
184 {
185 	struct drm_buddy_block *parent;
186 	unsigned int order;
187 
188 	while ((parent = block->parent)) {
189 		struct drm_buddy_block *buddy;
190 
191 		buddy = __get_buddy(block);
192 
193 		if (!drm_buddy_block_is_free(buddy))
194 			break;
195 
196 		if (!force_merge) {
197 			/*
198 			 * Check the block and its buddy clear state and exit
199 			 * the loop if they both have the dissimilar state.
200 			 */
201 			if (drm_buddy_block_is_clear(block) !=
202 			    drm_buddy_block_is_clear(buddy))
203 				break;
204 
205 			if (drm_buddy_block_is_clear(block))
206 				mark_cleared(parent);
207 		}
208 
209 		rbtree_remove(mm, buddy);
210 		if (force_merge && drm_buddy_block_is_clear(buddy))
211 			mm->clear_avail -= drm_buddy_block_size(mm, buddy);
212 
213 		drm_block_free(mm, block);
214 		drm_block_free(mm, buddy);
215 
216 		block = parent;
217 	}
218 
219 	order = drm_buddy_block_order(block);
220 	mark_free(mm, block);
221 
222 	return order;
223 }
224 
225 static int __force_merge(struct drm_buddy *mm,
226 			 u64 start,
227 			 u64 end,
228 			 unsigned int min_order)
229 {
230 	unsigned int tree, order;
231 	int i;
232 
233 	if (!min_order)
234 		return -ENOMEM;
235 
236 	if (min_order > mm->max_order)
237 		return -EINVAL;
238 
239 	for_each_free_tree(tree) {
240 		for (i = min_order - 1; i >= 0; i--) {
241 			struct rb_node *iter = rb_last(&mm->free_trees[tree][i]);
242 
243 			while (iter) {
244 				struct drm_buddy_block *block, *buddy;
245 				u64 block_start, block_end;
246 
247 				block = rbtree_get_free_block(iter);
248 				iter = rb_prev(iter);
249 
250 				if (!block || !block->parent)
251 					continue;
252 
253 				block_start = drm_buddy_block_offset(block);
254 				block_end = block_start + drm_buddy_block_size(mm, block) - 1;
255 
256 				if (!contains(start, end, block_start, block_end))
257 					continue;
258 
259 				buddy = __get_buddy(block);
260 				if (!drm_buddy_block_is_free(buddy))
261 					continue;
262 
263 				WARN_ON(drm_buddy_block_is_clear(block) ==
264 					drm_buddy_block_is_clear(buddy));
265 
266 				/*
267 				 * Advance to the next node when the current node is the buddy,
268 				 * as freeing the block will also remove its buddy from the tree.
269 				 */
270 				if (iter == &buddy->rb)
271 					iter = rb_prev(iter);
272 
273 				rbtree_remove(mm, block);
274 				if (drm_buddy_block_is_clear(block))
275 					mm->clear_avail -= drm_buddy_block_size(mm, block);
276 
277 				order = __drm_buddy_free(mm, block, true);
278 				if (order >= min_order)
279 					return 0;
280 			}
281 		}
282 	}
283 
284 	return -ENOMEM;
285 }
286 
287 /**
288  * drm_buddy_init - init memory manager
289  *
290  * @mm: DRM buddy manager to initialize
291  * @size: size in bytes to manage
292  * @chunk_size: minimum page size in bytes for our allocations
293  *
294  * Initializes the memory manager and its resources.
295  *
296  * Returns:
297  * 0 on success, error code on failure.
298  */
299 int drm_buddy_init(struct drm_buddy *mm, u64 size, u64 chunk_size)
300 {
301 	unsigned int i, j, root_count = 0;
302 	u64 offset = 0;
303 
304 	if (size < chunk_size)
305 		return -EINVAL;
306 
307 	if (chunk_size < SZ_4K)
308 		return -EINVAL;
309 
310 	if (!is_power_of_2(chunk_size))
311 		return -EINVAL;
312 
313 	size = round_down(size, chunk_size);
314 
315 	mm->size = size;
316 	mm->avail = size;
317 	mm->clear_avail = 0;
318 	mm->chunk_size = chunk_size;
319 	mm->max_order = ilog2(size) - ilog2(chunk_size);
320 
321 	BUG_ON(mm->max_order > DRM_BUDDY_MAX_ORDER);
322 
323 	mm->free_trees = kmalloc_array(DRM_BUDDY_MAX_FREE_TREES,
324 				       sizeof(*mm->free_trees),
325 				       GFP_KERNEL);
326 	if (!mm->free_trees)
327 		return -ENOMEM;
328 
329 	for_each_free_tree(i) {
330 		mm->free_trees[i] = kmalloc_array(mm->max_order + 1,
331 						  sizeof(struct rb_root),
332 						  GFP_KERNEL);
333 		if (!mm->free_trees[i])
334 			goto out_free_tree;
335 
336 		for (j = 0; j <= mm->max_order; ++j)
337 			mm->free_trees[i][j] = RB_ROOT;
338 	}
339 
340 	mm->n_roots = hweight64(size);
341 
342 	mm->roots = kmalloc_array(mm->n_roots,
343 				  sizeof(struct drm_buddy_block *),
344 				  GFP_KERNEL);
345 	if (!mm->roots)
346 		goto out_free_tree;
347 
348 	/*
349 	 * Split into power-of-two blocks, in case we are given a size that is
350 	 * not itself a power-of-two.
351 	 */
352 	do {
353 		struct drm_buddy_block *root;
354 		unsigned int order;
355 		u64 root_size;
356 
357 		order = ilog2(size) - ilog2(chunk_size);
358 		root_size = chunk_size << order;
359 
360 		root = drm_block_alloc(mm, NULL, order, offset);
361 		if (!root)
362 			goto out_free_roots;
363 
364 		mark_free(mm, root);
365 
366 		BUG_ON(root_count > mm->max_order);
367 		BUG_ON(drm_buddy_block_size(mm, root) < chunk_size);
368 
369 		mm->roots[root_count] = root;
370 
371 		offset += root_size;
372 		size -= root_size;
373 		root_count++;
374 	} while (size);
375 
376 	return 0;
377 
378 out_free_roots:
379 	while (root_count--)
380 		drm_block_free(mm, mm->roots[root_count]);
381 	kfree(mm->roots);
382 out_free_tree:
383 	while (i--)
384 		kfree(mm->free_trees[i]);
385 	kfree(mm->free_trees);
386 	return -ENOMEM;
387 }
388 EXPORT_SYMBOL(drm_buddy_init);
389 
390 /**
391  * drm_buddy_fini - tear down the memory manager
392  *
393  * @mm: DRM buddy manager to free
394  *
395  * Cleanup memory manager resources and the freetree
396  */
397 void drm_buddy_fini(struct drm_buddy *mm)
398 {
399 	u64 root_size, size, start;
400 	unsigned int order;
401 	int i;
402 
403 	size = mm->size;
404 
405 	for (i = 0; i < mm->n_roots; ++i) {
406 		order = ilog2(size) - ilog2(mm->chunk_size);
407 		start = drm_buddy_block_offset(mm->roots[i]);
408 		__force_merge(mm, start, start + size, order);
409 
410 		if (WARN_ON(!drm_buddy_block_is_free(mm->roots[i])))
411 			kunit_fail_current_test("buddy_fini() root");
412 
413 		drm_block_free(mm, mm->roots[i]);
414 
415 		root_size = mm->chunk_size << order;
416 		size -= root_size;
417 	}
418 
419 	WARN_ON(mm->avail != mm->size);
420 
421 	for_each_free_tree(i)
422 		kfree(mm->free_trees[i]);
423 	kfree(mm->free_trees);
424 	kfree(mm->roots);
425 }
426 EXPORT_SYMBOL(drm_buddy_fini);
427 
428 static int split_block(struct drm_buddy *mm,
429 		       struct drm_buddy_block *block)
430 {
431 	unsigned int block_order = drm_buddy_block_order(block) - 1;
432 	u64 offset = drm_buddy_block_offset(block);
433 
434 	BUG_ON(!drm_buddy_block_is_free(block));
435 	BUG_ON(!drm_buddy_block_order(block));
436 
437 	block->left = drm_block_alloc(mm, block, block_order, offset);
438 	if (!block->left)
439 		return -ENOMEM;
440 
441 	block->right = drm_block_alloc(mm, block, block_order,
442 				       offset + (mm->chunk_size << block_order));
443 	if (!block->right) {
444 		drm_block_free(mm, block->left);
445 		return -ENOMEM;
446 	}
447 
448 	mark_split(mm, block);
449 
450 	if (drm_buddy_block_is_clear(block)) {
451 		mark_cleared(block->left);
452 		mark_cleared(block->right);
453 		clear_reset(block);
454 	}
455 
456 	mark_free(mm, block->left);
457 	mark_free(mm, block->right);
458 
459 	return 0;
460 }
461 
462 /**
463  * drm_get_buddy - get buddy address
464  *
465  * @block: DRM buddy block
466  *
467  * Returns the corresponding buddy block for @block, or NULL
468  * if this is a root block and can't be merged further.
469  * Requires some kind of locking to protect against
470  * any concurrent allocate and free operations.
471  */
472 struct drm_buddy_block *
473 drm_get_buddy(struct drm_buddy_block *block)
474 {
475 	return __get_buddy(block);
476 }
477 EXPORT_SYMBOL(drm_get_buddy);
478 
479 /**
480  * drm_buddy_reset_clear - reset blocks clear state
481  *
482  * @mm: DRM buddy manager
483  * @is_clear: blocks clear state
484  *
485  * Reset the clear state based on @is_clear value for each block
486  * in the freetree.
487  */
488 void drm_buddy_reset_clear(struct drm_buddy *mm, bool is_clear)
489 {
490 	enum drm_buddy_free_tree src_tree, dst_tree;
491 	u64 root_size, size, start;
492 	unsigned int order;
493 	int i;
494 
495 	size = mm->size;
496 	for (i = 0; i < mm->n_roots; ++i) {
497 		order = ilog2(size) - ilog2(mm->chunk_size);
498 		start = drm_buddy_block_offset(mm->roots[i]);
499 		__force_merge(mm, start, start + size, order);
500 
501 		root_size = mm->chunk_size << order;
502 		size -= root_size;
503 	}
504 
505 	src_tree = is_clear ? DRM_BUDDY_DIRTY_TREE : DRM_BUDDY_CLEAR_TREE;
506 	dst_tree = is_clear ? DRM_BUDDY_CLEAR_TREE : DRM_BUDDY_DIRTY_TREE;
507 
508 	for (i = 0; i <= mm->max_order; ++i) {
509 		struct rb_root *root = &mm->free_trees[src_tree][i];
510 		struct drm_buddy_block *block, *tmp;
511 
512 		rbtree_postorder_for_each_entry_safe(block, tmp, root, rb) {
513 			rbtree_remove(mm, block);
514 			if (is_clear) {
515 				mark_cleared(block);
516 				mm->clear_avail += drm_buddy_block_size(mm, block);
517 			} else {
518 				clear_reset(block);
519 				mm->clear_avail -= drm_buddy_block_size(mm, block);
520 			}
521 
522 			rbtree_insert(mm, block, dst_tree);
523 		}
524 	}
525 }
526 EXPORT_SYMBOL(drm_buddy_reset_clear);
527 
528 /**
529  * drm_buddy_free_block - free a block
530  *
531  * @mm: DRM buddy manager
532  * @block: block to be freed
533  */
534 void drm_buddy_free_block(struct drm_buddy *mm,
535 			  struct drm_buddy_block *block)
536 {
537 	BUG_ON(!drm_buddy_block_is_allocated(block));
538 	mm->avail += drm_buddy_block_size(mm, block);
539 	if (drm_buddy_block_is_clear(block))
540 		mm->clear_avail += drm_buddy_block_size(mm, block);
541 
542 	__drm_buddy_free(mm, block, false);
543 }
544 EXPORT_SYMBOL(drm_buddy_free_block);
545 
546 static void __drm_buddy_free_list(struct drm_buddy *mm,
547 				  struct list_head *objects,
548 				  bool mark_clear,
549 				  bool mark_dirty)
550 {
551 	struct drm_buddy_block *block, *on;
552 
553 	WARN_ON(mark_dirty && mark_clear);
554 
555 	list_for_each_entry_safe(block, on, objects, link) {
556 		if (mark_clear)
557 			mark_cleared(block);
558 		else if (mark_dirty)
559 			clear_reset(block);
560 		drm_buddy_free_block(mm, block);
561 		cond_resched();
562 	}
563 	INIT_LIST_HEAD(objects);
564 }
565 
566 static void drm_buddy_free_list_internal(struct drm_buddy *mm,
567 					 struct list_head *objects)
568 {
569 	/*
570 	 * Don't touch the clear/dirty bit, since allocation is still internal
571 	 * at this point. For example we might have just failed part of the
572 	 * allocation.
573 	 */
574 	__drm_buddy_free_list(mm, objects, false, false);
575 }
576 
577 /**
578  * drm_buddy_free_list - free blocks
579  *
580  * @mm: DRM buddy manager
581  * @objects: input list head to free blocks
582  * @flags: optional flags like DRM_BUDDY_CLEARED
583  */
584 void drm_buddy_free_list(struct drm_buddy *mm,
585 			 struct list_head *objects,
586 			 unsigned int flags)
587 {
588 	bool mark_clear = flags & DRM_BUDDY_CLEARED;
589 
590 	__drm_buddy_free_list(mm, objects, mark_clear, !mark_clear);
591 }
592 EXPORT_SYMBOL(drm_buddy_free_list);
593 
594 static bool block_incompatible(struct drm_buddy_block *block, unsigned int flags)
595 {
596 	bool needs_clear = flags & DRM_BUDDY_CLEAR_ALLOCATION;
597 
598 	return needs_clear != drm_buddy_block_is_clear(block);
599 }
600 
601 static struct drm_buddy_block *
602 __alloc_range_bias(struct drm_buddy *mm,
603 		   u64 start, u64 end,
604 		   unsigned int order,
605 		   unsigned long flags,
606 		   bool fallback)
607 {
608 	u64 req_size = mm->chunk_size << order;
609 	struct drm_buddy_block *block;
610 	struct drm_buddy_block *buddy;
611 	LIST_HEAD(dfs);
612 	int err;
613 	int i;
614 
615 	end = end - 1;
616 
617 	for (i = 0; i < mm->n_roots; ++i)
618 		list_add_tail(&mm->roots[i]->tmp_link, &dfs);
619 
620 	do {
621 		u64 block_start;
622 		u64 block_end;
623 
624 		block = list_first_entry_or_null(&dfs,
625 						 struct drm_buddy_block,
626 						 tmp_link);
627 		if (!block)
628 			break;
629 
630 		list_del(&block->tmp_link);
631 
632 		if (drm_buddy_block_order(block) < order)
633 			continue;
634 
635 		block_start = drm_buddy_block_offset(block);
636 		block_end = block_start + drm_buddy_block_size(mm, block) - 1;
637 
638 		if (!overlaps(start, end, block_start, block_end))
639 			continue;
640 
641 		if (drm_buddy_block_is_allocated(block))
642 			continue;
643 
644 		if (block_start < start || block_end > end) {
645 			u64 adjusted_start = max(block_start, start);
646 			u64 adjusted_end = min(block_end, end);
647 
648 			if (round_down(adjusted_end + 1, req_size) <=
649 			    round_up(adjusted_start, req_size))
650 				continue;
651 		}
652 
653 		if (!fallback && block_incompatible(block, flags))
654 			continue;
655 
656 		if (contains(start, end, block_start, block_end) &&
657 		    order == drm_buddy_block_order(block)) {
658 			/*
659 			 * Find the free block within the range.
660 			 */
661 			if (drm_buddy_block_is_free(block))
662 				return block;
663 
664 			continue;
665 		}
666 
667 		if (!drm_buddy_block_is_split(block)) {
668 			err = split_block(mm, block);
669 			if (unlikely(err))
670 				goto err_undo;
671 		}
672 
673 		list_add(&block->right->tmp_link, &dfs);
674 		list_add(&block->left->tmp_link, &dfs);
675 	} while (1);
676 
677 	return ERR_PTR(-ENOSPC);
678 
679 err_undo:
680 	/*
681 	 * We really don't want to leave around a bunch of split blocks, since
682 	 * bigger is better, so make sure we merge everything back before we
683 	 * free the allocated blocks.
684 	 */
685 	buddy = __get_buddy(block);
686 	if (buddy &&
687 	    (drm_buddy_block_is_free(block) &&
688 	     drm_buddy_block_is_free(buddy)))
689 		__drm_buddy_free(mm, block, false);
690 	return ERR_PTR(err);
691 }
692 
693 static struct drm_buddy_block *
694 __drm_buddy_alloc_range_bias(struct drm_buddy *mm,
695 			     u64 start, u64 end,
696 			     unsigned int order,
697 			     unsigned long flags)
698 {
699 	struct drm_buddy_block *block;
700 	bool fallback = false;
701 
702 	block = __alloc_range_bias(mm, start, end, order,
703 				   flags, fallback);
704 	if (IS_ERR(block))
705 		return __alloc_range_bias(mm, start, end, order,
706 					  flags, !fallback);
707 
708 	return block;
709 }
710 
711 static struct drm_buddy_block *
712 get_maxblock(struct drm_buddy *mm,
713 	     unsigned int order,
714 	     enum drm_buddy_free_tree tree)
715 {
716 	struct drm_buddy_block *max_block = NULL, *block = NULL;
717 	struct rb_root *root;
718 	unsigned int i;
719 
720 	for (i = order; i <= mm->max_order; ++i) {
721 		root = &mm->free_trees[tree][i];
722 		block = rbtree_last_free_block(root);
723 		if (!block)
724 			continue;
725 
726 		if (!max_block) {
727 			max_block = block;
728 			continue;
729 		}
730 
731 		if (drm_buddy_block_offset(block) >
732 		    drm_buddy_block_offset(max_block)) {
733 			max_block = block;
734 		}
735 	}
736 
737 	return max_block;
738 }
739 
740 static struct drm_buddy_block *
741 alloc_from_freetree(struct drm_buddy *mm,
742 		    unsigned int order,
743 		    unsigned long flags)
744 {
745 	struct drm_buddy_block *block = NULL;
746 	struct rb_root *root;
747 	enum drm_buddy_free_tree tree;
748 	unsigned int tmp;
749 	int err;
750 
751 	tree = (flags & DRM_BUDDY_CLEAR_ALLOCATION) ?
752 		DRM_BUDDY_CLEAR_TREE : DRM_BUDDY_DIRTY_TREE;
753 
754 	if (flags & DRM_BUDDY_TOPDOWN_ALLOCATION) {
755 		block = get_maxblock(mm, order, tree);
756 		if (block)
757 			/* Store the obtained block order */
758 			tmp = drm_buddy_block_order(block);
759 	} else {
760 		for (tmp = order; tmp <= mm->max_order; ++tmp) {
761 			/* Get RB tree root for this order and tree */
762 			root = &mm->free_trees[tree][tmp];
763 			block = rbtree_last_free_block(root);
764 			if (block)
765 				break;
766 		}
767 	}
768 
769 	if (!block) {
770 		/* Try allocating from the other tree */
771 		tree = (tree == DRM_BUDDY_CLEAR_TREE) ?
772 			DRM_BUDDY_DIRTY_TREE : DRM_BUDDY_CLEAR_TREE;
773 
774 		for (tmp = order; tmp <= mm->max_order; ++tmp) {
775 			root = &mm->free_trees[tree][tmp];
776 			block = rbtree_last_free_block(root);
777 			if (block)
778 				break;
779 		}
780 
781 		if (!block)
782 			return ERR_PTR(-ENOSPC);
783 	}
784 
785 	BUG_ON(!drm_buddy_block_is_free(block));
786 
787 	while (tmp != order) {
788 		err = split_block(mm, block);
789 		if (unlikely(err))
790 			goto err_undo;
791 
792 		block = block->right;
793 		tmp--;
794 	}
795 	return block;
796 
797 err_undo:
798 	if (tmp != order)
799 		__drm_buddy_free(mm, block, false);
800 	return ERR_PTR(err);
801 }
802 
803 static int __alloc_range(struct drm_buddy *mm,
804 			 struct list_head *dfs,
805 			 u64 start, u64 size,
806 			 struct list_head *blocks,
807 			 u64 *total_allocated_on_err)
808 {
809 	struct drm_buddy_block *block;
810 	struct drm_buddy_block *buddy;
811 	u64 total_allocated = 0;
812 	LIST_HEAD(allocated);
813 	u64 end;
814 	int err;
815 
816 	end = start + size - 1;
817 
818 	do {
819 		u64 block_start;
820 		u64 block_end;
821 
822 		block = list_first_entry_or_null(dfs,
823 						 struct drm_buddy_block,
824 						 tmp_link);
825 		if (!block)
826 			break;
827 
828 		list_del(&block->tmp_link);
829 
830 		block_start = drm_buddy_block_offset(block);
831 		block_end = block_start + drm_buddy_block_size(mm, block) - 1;
832 
833 		if (!overlaps(start, end, block_start, block_end))
834 			continue;
835 
836 		if (drm_buddy_block_is_allocated(block)) {
837 			err = -ENOSPC;
838 			goto err_free;
839 		}
840 
841 		if (contains(start, end, block_start, block_end)) {
842 			if (drm_buddy_block_is_free(block)) {
843 				mark_allocated(mm, block);
844 				total_allocated += drm_buddy_block_size(mm, block);
845 				mm->avail -= drm_buddy_block_size(mm, block);
846 				if (drm_buddy_block_is_clear(block))
847 					mm->clear_avail -= drm_buddy_block_size(mm, block);
848 				list_add_tail(&block->link, &allocated);
849 				continue;
850 			} else if (!mm->clear_avail) {
851 				err = -ENOSPC;
852 				goto err_free;
853 			}
854 		}
855 
856 		if (!drm_buddy_block_is_split(block)) {
857 			err = split_block(mm, block);
858 			if (unlikely(err))
859 				goto err_undo;
860 		}
861 
862 		list_add(&block->right->tmp_link, dfs);
863 		list_add(&block->left->tmp_link, dfs);
864 	} while (1);
865 
866 	if (total_allocated < size) {
867 		err = -ENOSPC;
868 		goto err_free;
869 	}
870 
871 	list_splice_tail(&allocated, blocks);
872 
873 	return 0;
874 
875 err_undo:
876 	/*
877 	 * We really don't want to leave around a bunch of split blocks, since
878 	 * bigger is better, so make sure we merge everything back before we
879 	 * free the allocated blocks.
880 	 */
881 	buddy = __get_buddy(block);
882 	if (buddy &&
883 	    (drm_buddy_block_is_free(block) &&
884 	     drm_buddy_block_is_free(buddy)))
885 		__drm_buddy_free(mm, block, false);
886 
887 err_free:
888 	if (err == -ENOSPC && total_allocated_on_err) {
889 		list_splice_tail(&allocated, blocks);
890 		*total_allocated_on_err = total_allocated;
891 	} else {
892 		drm_buddy_free_list_internal(mm, &allocated);
893 	}
894 
895 	return err;
896 }
897 
898 static int __drm_buddy_alloc_range(struct drm_buddy *mm,
899 				   u64 start,
900 				   u64 size,
901 				   u64 *total_allocated_on_err,
902 				   struct list_head *blocks)
903 {
904 	LIST_HEAD(dfs);
905 	int i;
906 
907 	for (i = 0; i < mm->n_roots; ++i)
908 		list_add_tail(&mm->roots[i]->tmp_link, &dfs);
909 
910 	return __alloc_range(mm, &dfs, start, size,
911 			     blocks, total_allocated_on_err);
912 }
913 
914 static int __alloc_contig_try_harder(struct drm_buddy *mm,
915 				     u64 size,
916 				     u64 min_block_size,
917 				     struct list_head *blocks)
918 {
919 	u64 rhs_offset, lhs_offset, lhs_size, filled;
920 	struct drm_buddy_block *block;
921 	unsigned int tree, order;
922 	LIST_HEAD(blocks_lhs);
923 	unsigned long pages;
924 	u64 modify_size;
925 	int err;
926 
927 	modify_size = rounddown_pow_of_two(size);
928 	pages = modify_size >> ilog2(mm->chunk_size);
929 	order = fls(pages) - 1;
930 	if (order == 0)
931 		return -ENOSPC;
932 
933 	for_each_free_tree(tree) {
934 		struct rb_root *root;
935 		struct rb_node *iter;
936 
937 		root = &mm->free_trees[tree][order];
938 		if (rbtree_is_empty(root))
939 			continue;
940 
941 		iter = rb_last(root);
942 		while (iter) {
943 			block = rbtree_get_free_block(iter);
944 
945 			/* Allocate blocks traversing RHS */
946 			rhs_offset = drm_buddy_block_offset(block);
947 			err =  __drm_buddy_alloc_range(mm, rhs_offset, size,
948 						       &filled, blocks);
949 			if (!err || err != -ENOSPC)
950 				return err;
951 
952 			lhs_size = max((size - filled), min_block_size);
953 			if (!IS_ALIGNED(lhs_size, min_block_size))
954 				lhs_size = round_up(lhs_size, min_block_size);
955 
956 			/* Allocate blocks traversing LHS */
957 			lhs_offset = drm_buddy_block_offset(block) - lhs_size;
958 			err =  __drm_buddy_alloc_range(mm, lhs_offset, lhs_size,
959 						       NULL, &blocks_lhs);
960 			if (!err) {
961 				list_splice(&blocks_lhs, blocks);
962 				return 0;
963 			} else if (err != -ENOSPC) {
964 				drm_buddy_free_list_internal(mm, blocks);
965 				return err;
966 			}
967 			/* Free blocks for the next iteration */
968 			drm_buddy_free_list_internal(mm, blocks);
969 
970 			iter = rb_prev(iter);
971 		}
972 	}
973 
974 	return -ENOSPC;
975 }
976 
977 /**
978  * drm_buddy_block_trim - free unused pages
979  *
980  * @mm: DRM buddy manager
981  * @start: start address to begin the trimming.
982  * @new_size: original size requested
983  * @blocks: Input and output list of allocated blocks.
984  * MUST contain single block as input to be trimmed.
985  * On success will contain the newly allocated blocks
986  * making up the @new_size. Blocks always appear in
987  * ascending order
988  *
989  * For contiguous allocation, we round up the size to the nearest
990  * power of two value, drivers consume *actual* size, so remaining
991  * portions are unused and can be optionally freed with this function
992  *
993  * Returns:
994  * 0 on success, error code on failure.
995  */
996 int drm_buddy_block_trim(struct drm_buddy *mm,
997 			 u64 *start,
998 			 u64 new_size,
999 			 struct list_head *blocks)
1000 {
1001 	struct drm_buddy_block *parent;
1002 	struct drm_buddy_block *block;
1003 	u64 block_start, block_end;
1004 	LIST_HEAD(dfs);
1005 	u64 new_start;
1006 	int err;
1007 
1008 	if (!list_is_singular(blocks))
1009 		return -EINVAL;
1010 
1011 	block = list_first_entry(blocks,
1012 				 struct drm_buddy_block,
1013 				 link);
1014 
1015 	block_start = drm_buddy_block_offset(block);
1016 	block_end = block_start + drm_buddy_block_size(mm, block);
1017 
1018 	if (WARN_ON(!drm_buddy_block_is_allocated(block)))
1019 		return -EINVAL;
1020 
1021 	if (new_size > drm_buddy_block_size(mm, block))
1022 		return -EINVAL;
1023 
1024 	if (!new_size || !IS_ALIGNED(new_size, mm->chunk_size))
1025 		return -EINVAL;
1026 
1027 	if (new_size == drm_buddy_block_size(mm, block))
1028 		return 0;
1029 
1030 	new_start = block_start;
1031 	if (start) {
1032 		new_start = *start;
1033 
1034 		if (new_start < block_start)
1035 			return -EINVAL;
1036 
1037 		if (!IS_ALIGNED(new_start, mm->chunk_size))
1038 			return -EINVAL;
1039 
1040 		if (range_overflows(new_start, new_size, block_end))
1041 			return -EINVAL;
1042 	}
1043 
1044 	list_del(&block->link);
1045 	mark_free(mm, block);
1046 	mm->avail += drm_buddy_block_size(mm, block);
1047 	if (drm_buddy_block_is_clear(block))
1048 		mm->clear_avail += drm_buddy_block_size(mm, block);
1049 
1050 	/* Prevent recursively freeing this node */
1051 	parent = block->parent;
1052 	block->parent = NULL;
1053 
1054 	list_add(&block->tmp_link, &dfs);
1055 	err =  __alloc_range(mm, &dfs, new_start, new_size, blocks, NULL);
1056 	if (err) {
1057 		mark_allocated(mm, block);
1058 		mm->avail -= drm_buddy_block_size(mm, block);
1059 		if (drm_buddy_block_is_clear(block))
1060 			mm->clear_avail -= drm_buddy_block_size(mm, block);
1061 		list_add(&block->link, blocks);
1062 	}
1063 
1064 	block->parent = parent;
1065 	return err;
1066 }
1067 EXPORT_SYMBOL(drm_buddy_block_trim);
1068 
1069 static struct drm_buddy_block *
1070 __drm_buddy_alloc_blocks(struct drm_buddy *mm,
1071 			 u64 start, u64 end,
1072 			 unsigned int order,
1073 			 unsigned long flags)
1074 {
1075 	if (flags & DRM_BUDDY_RANGE_ALLOCATION)
1076 		/* Allocate traversing within the range */
1077 		return  __drm_buddy_alloc_range_bias(mm, start, end,
1078 						     order, flags);
1079 	else
1080 		/* Allocate from freetree */
1081 		return alloc_from_freetree(mm, order, flags);
1082 }
1083 
1084 /**
1085  * drm_buddy_alloc_blocks - allocate power-of-two blocks
1086  *
1087  * @mm: DRM buddy manager to allocate from
1088  * @start: start of the allowed range for this block
1089  * @end: end of the allowed range for this block
1090  * @size: size of the allocation in bytes
1091  * @min_block_size: alignment of the allocation
1092  * @blocks: output list head to add allocated blocks
1093  * @flags: DRM_BUDDY_*_ALLOCATION flags
1094  *
1095  * alloc_range_bias() called on range limitations, which traverses
1096  * the tree and returns the desired block.
1097  *
1098  * alloc_from_freetree() called when *no* range restrictions
1099  * are enforced, which picks the block from the freetree.
1100  *
1101  * Returns:
1102  * 0 on success, error code on failure.
1103  */
1104 int drm_buddy_alloc_blocks(struct drm_buddy *mm,
1105 			   u64 start, u64 end, u64 size,
1106 			   u64 min_block_size,
1107 			   struct list_head *blocks,
1108 			   unsigned long flags)
1109 {
1110 	struct drm_buddy_block *block = NULL;
1111 	u64 original_size, original_min_size;
1112 	unsigned int min_order, order;
1113 	LIST_HEAD(allocated);
1114 	unsigned long pages;
1115 	int err;
1116 
1117 	if (size < mm->chunk_size)
1118 		return -EINVAL;
1119 
1120 	if (min_block_size < mm->chunk_size)
1121 		return -EINVAL;
1122 
1123 	if (!is_power_of_2(min_block_size))
1124 		return -EINVAL;
1125 
1126 	if (!IS_ALIGNED(start | end | size, mm->chunk_size))
1127 		return -EINVAL;
1128 
1129 	if (end > mm->size)
1130 		return -EINVAL;
1131 
1132 	if (range_overflows(start, size, mm->size))
1133 		return -EINVAL;
1134 
1135 	/* Actual range allocation */
1136 	if (start + size == end) {
1137 		if (!IS_ALIGNED(start | end, min_block_size))
1138 			return -EINVAL;
1139 
1140 		return __drm_buddy_alloc_range(mm, start, size, NULL, blocks);
1141 	}
1142 
1143 	original_size = size;
1144 	original_min_size = min_block_size;
1145 
1146 	/* Roundup the size to power of 2 */
1147 	if (flags & DRM_BUDDY_CONTIGUOUS_ALLOCATION) {
1148 		size = roundup_pow_of_two(size);
1149 		min_block_size = size;
1150 	/* Align size value to min_block_size */
1151 	} else if (!IS_ALIGNED(size, min_block_size)) {
1152 		size = round_up(size, min_block_size);
1153 	}
1154 
1155 	pages = size >> ilog2(mm->chunk_size);
1156 	order = fls(pages) - 1;
1157 	min_order = ilog2(min_block_size) - ilog2(mm->chunk_size);
1158 
1159 	if (order > mm->max_order || size > mm->size) {
1160 		if ((flags & DRM_BUDDY_CONTIGUOUS_ALLOCATION) &&
1161 		    !(flags & DRM_BUDDY_RANGE_ALLOCATION))
1162 			return __alloc_contig_try_harder(mm, original_size,
1163 							 original_min_size, blocks);
1164 
1165 		return -EINVAL;
1166 	}
1167 
1168 	do {
1169 		order = min(order, (unsigned int)fls(pages) - 1);
1170 		BUG_ON(order > mm->max_order);
1171 		BUG_ON(order < min_order);
1172 
1173 		do {
1174 			block = __drm_buddy_alloc_blocks(mm, start,
1175 							 end,
1176 							 order,
1177 							 flags);
1178 			if (!IS_ERR(block))
1179 				break;
1180 
1181 			if (order-- == min_order) {
1182 				/* Try allocation through force merge method */
1183 				if (mm->clear_avail &&
1184 				    !__force_merge(mm, start, end, min_order)) {
1185 					block = __drm_buddy_alloc_blocks(mm, start,
1186 									 end,
1187 									 min_order,
1188 									 flags);
1189 					if (!IS_ERR(block)) {
1190 						order = min_order;
1191 						break;
1192 					}
1193 				}
1194 
1195 				/*
1196 				 * Try contiguous block allocation through
1197 				 * try harder method.
1198 				 */
1199 				if (flags & DRM_BUDDY_CONTIGUOUS_ALLOCATION &&
1200 				    !(flags & DRM_BUDDY_RANGE_ALLOCATION))
1201 					return __alloc_contig_try_harder(mm,
1202 									 original_size,
1203 									 original_min_size,
1204 									 blocks);
1205 				err = -ENOSPC;
1206 				goto err_free;
1207 			}
1208 		} while (1);
1209 
1210 		mark_allocated(mm, block);
1211 		mm->avail -= drm_buddy_block_size(mm, block);
1212 		if (drm_buddy_block_is_clear(block))
1213 			mm->clear_avail -= drm_buddy_block_size(mm, block);
1214 		kmemleak_update_trace(block);
1215 		list_add_tail(&block->link, &allocated);
1216 
1217 		pages -= BIT(order);
1218 
1219 		if (!pages)
1220 			break;
1221 	} while (1);
1222 
1223 	/* Trim the allocated block to the required size */
1224 	if (!(flags & DRM_BUDDY_TRIM_DISABLE) &&
1225 	    original_size != size) {
1226 		struct list_head *trim_list;
1227 		LIST_HEAD(temp);
1228 		u64 trim_size;
1229 
1230 		trim_list = &allocated;
1231 		trim_size = original_size;
1232 
1233 		if (!list_is_singular(&allocated)) {
1234 			block = list_last_entry(&allocated, typeof(*block), link);
1235 			list_move(&block->link, &temp);
1236 			trim_list = &temp;
1237 			trim_size = drm_buddy_block_size(mm, block) -
1238 				(size - original_size);
1239 		}
1240 
1241 		drm_buddy_block_trim(mm,
1242 				     NULL,
1243 				     trim_size,
1244 				     trim_list);
1245 
1246 		if (!list_empty(&temp))
1247 			list_splice_tail(trim_list, &allocated);
1248 	}
1249 
1250 	list_splice_tail(&allocated, blocks);
1251 	return 0;
1252 
1253 err_free:
1254 	drm_buddy_free_list_internal(mm, &allocated);
1255 	return err;
1256 }
1257 EXPORT_SYMBOL(drm_buddy_alloc_blocks);
1258 
1259 /**
1260  * drm_buddy_block_print - print block information
1261  *
1262  * @mm: DRM buddy manager
1263  * @block: DRM buddy block
1264  * @p: DRM printer to use
1265  */
1266 void drm_buddy_block_print(struct drm_buddy *mm,
1267 			   struct drm_buddy_block *block,
1268 			   struct drm_printer *p)
1269 {
1270 	u64 start = drm_buddy_block_offset(block);
1271 	u64 size = drm_buddy_block_size(mm, block);
1272 
1273 	drm_printf(p, "%#018llx-%#018llx: %llu\n", start, start + size, size);
1274 }
1275 EXPORT_SYMBOL(drm_buddy_block_print);
1276 
1277 /**
1278  * drm_buddy_print - print allocator state
1279  *
1280  * @mm: DRM buddy manager
1281  * @p: DRM printer to use
1282  */
1283 void drm_buddy_print(struct drm_buddy *mm, struct drm_printer *p)
1284 {
1285 	int order;
1286 
1287 	drm_printf(p, "chunk_size: %lluKiB, total: %lluMiB, free: %lluMiB, clear_free: %lluMiB\n",
1288 		   mm->chunk_size >> 10, mm->size >> 20, mm->avail >> 20, mm->clear_avail >> 20);
1289 
1290 	for (order = mm->max_order; order >= 0; order--) {
1291 		struct drm_buddy_block *block, *tmp;
1292 		struct rb_root *root;
1293 		u64 count = 0, free;
1294 		unsigned int tree;
1295 
1296 		for_each_free_tree(tree) {
1297 			root = &mm->free_trees[tree][order];
1298 
1299 			rbtree_postorder_for_each_entry_safe(block, tmp, root, rb) {
1300 				BUG_ON(!drm_buddy_block_is_free(block));
1301 				count++;
1302 			}
1303 		}
1304 
1305 		drm_printf(p, "order-%2d ", order);
1306 
1307 		free = count * (mm->chunk_size << order);
1308 		if (free < SZ_1M)
1309 			drm_printf(p, "free: %8llu KiB", free >> 10);
1310 		else
1311 			drm_printf(p, "free: %8llu MiB", free >> 20);
1312 
1313 		drm_printf(p, ", blocks: %llu\n", count);
1314 	}
1315 }
1316 EXPORT_SYMBOL(drm_buddy_print);
1317 
1318 static void drm_buddy_module_exit(void)
1319 {
1320 	kmem_cache_destroy(slab_blocks);
1321 }
1322 
1323 static int __init drm_buddy_module_init(void)
1324 {
1325 	slab_blocks = KMEM_CACHE(drm_buddy_block, 0);
1326 	if (!slab_blocks)
1327 		return -ENOMEM;
1328 
1329 	return 0;
1330 }
1331 
1332 module_init(drm_buddy_module_init);
1333 module_exit(drm_buddy_module_exit);
1334 
1335 MODULE_DESCRIPTION("DRM Buddy Allocator");
1336 MODULE_LICENSE("Dual MIT/GPL");
1337