Home | History | Annotate | Line # | Download | only in drm
drm_mm.c revision 1.13
      1 /*	$NetBSD: drm_mm.c,v 1.13 2021/12/19 11:51:22 riastradh Exp $	*/
      2 
      3 /**************************************************************************
      4  *
      5  * Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND., USA.
      6  * Copyright 2016 Intel Corporation
      7  * All Rights Reserved.
      8  *
      9  * Permission is hereby granted, free of charge, to any person obtaining a
     10  * copy of this software and associated documentation files (the
     11  * "Software"), to deal in the Software without restriction, including
     12  * without limitation the rights to use, copy, modify, merge, publish,
     13  * distribute, sub license, and/or sell copies of the Software, and to
     14  * permit persons to whom the Software is furnished to do so, subject to
     15  * the following conditions:
     16  *
     17  * The above copyright notice and this permission notice (including the
     18  * next paragraph) shall be included in all copies or substantial portions
     19  * of the Software.
     20  *
     21  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     22  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     23  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
     24  * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
     25  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
     26  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
     27  * USE OR OTHER DEALINGS IN THE SOFTWARE.
     28  *
     29  *
     30  **************************************************************************/
     31 
     32 /*
     33  * Generic simple memory manager implementation. Intended to be used as a base
     34  * class implementation for more advanced memory managers.
     35  *
     36  * Note that the algorithm used is quite simple and there might be substantial
     37  * performance gains if a smarter free list is implemented. Currently it is
     38  * just an unordered stack of free regions. This could easily be improved if
     39  * an RB-tree is used instead. At least if we expect heavy fragmentation.
     40  *
     41  * Aligned allocations can also see improvement.
     42  *
     43  * Authors:
     44  * Thomas Hellstrm <thomas-at-tungstengraphics-dot-com>
     45  */
     46 
     47 #include <sys/cdefs.h>
     48 __KERNEL_RCSID(0, "$NetBSD: drm_mm.c,v 1.13 2021/12/19 11:51:22 riastradh Exp $");
     49 
     50 #include <linux/export.h>
     51 #include <linux/interval_tree_generic.h>
     52 #include <linux/seq_file.h>
     53 #include <linux/slab.h>
     54 #include <linux/stacktrace.h>
     55 
     56 #include <drm/drm_mm.h>
     57 
     58 /**
     59  * DOC: Overview
     60  *
     61  * drm_mm provides a simple range allocator. The drivers are free to use the
     62  * resource allocator from the linux core if it suits them, the upside of drm_mm
     63  * is that it's in the DRM core. Which means that it's easier to extend for
     64  * some of the crazier special purpose needs of gpus.
     65  *
     66  * The main data struct is &drm_mm, allocations are tracked in &drm_mm_node.
     67  * Drivers are free to embed either of them into their own suitable
     68  * datastructures. drm_mm itself will not do any memory allocations of its own,
     69  * so if drivers choose not to embed nodes they need to still allocate them
     70  * themselves.
     71  *
     72  * The range allocator also supports reservation of preallocated blocks. This is
     73  * useful for taking over initial mode setting configurations from the firmware,
     74  * where an object needs to be created which exactly matches the firmware's
     75  * scanout target. As long as the range is still free it can be inserted anytime
     76  * after the allocator is initialized, which helps with avoiding looped
     77  * dependencies in the driver load sequence.
     78  *
     79  * drm_mm maintains a stack of most recently freed holes, which of all
     80  * simplistic datastructures seems to be a fairly decent approach to clustering
     81  * allocations and avoiding too much fragmentation. This means free space
     82  * searches are O(num_holes). Given that all the fancy features drm_mm supports
     83  * something better would be fairly complex and since gfx thrashing is a fairly
     84  * steep cliff not a real concern. Removing a node again is O(1).
     85  *
     86  * drm_mm supports a few features: Alignment and range restrictions can be
     87  * supplied. Furthermore every &drm_mm_node has a color value (which is just an
     88  * opaque unsigned long) which in conjunction with a driver callback can be used
     89  * to implement sophisticated placement restrictions. The i915 DRM driver uses
     90  * this to implement guard pages between incompatible caching domains in the
     91  * graphics TT.
     92  *
     93  * Two behaviors are supported for searching and allocating: bottom-up and
     94  * top-down. The default is bottom-up. Top-down allocation can be used if the
     95  * memory area has different restrictions, or just to reduce fragmentation.
     96  *
     97  * Finally iteration helpers to walk all nodes and all holes are provided as are
     98  * some basic allocator dumpers for debugging.
     99  *
    100  * Note that this range allocator is not thread-safe, drivers need to protect
    101  * modifications with their own locking. The idea behind this is that for a full
    102  * memory manager additional data needs to be protected anyway, hence internal
    103  * locking would be fully redundant.
    104  */
    105 
    106 #ifdef CONFIG_DRM_DEBUG_MM
    107 #include <linux/stackdepot.h>
    108 
    109 #define STACKDEPTH 32
    110 #define BUFSZ 4096
    111 
    112 static noinline void save_stack(struct drm_mm_node *node)
    113 {
    114 	unsigned long entries[STACKDEPTH];
    115 	unsigned int n;
    116 
    117 	n = stack_trace_save(entries, ARRAY_SIZE(entries), 1);
    118 
    119 	/* May be called under spinlock, so avoid sleeping */
    120 	node->stack = stack_depot_save(entries, n, GFP_NOWAIT);
    121 }
    122 
    123 static void show_leaks(struct drm_mm *mm)
    124 {
    125 	struct drm_mm_node *node;
    126 	unsigned long *entries;
    127 	unsigned int nr_entries;
    128 	char *buf;
    129 
    130 	buf = kmalloc(BUFSZ, GFP_KERNEL);
    131 	if (!buf)
    132 		return;
    133 
    134 	list_for_each_entry(node, drm_mm_nodes(mm), node_list) {
    135 		if (!node->stack) {
    136 			DRM_ERROR("node [%08"PRIx64" + %08"PRIx64"]: unknown owner\n",
    137 				  node->start, node->size);
    138 			continue;
    139 		}
    140 
    141 		nr_entries = stack_depot_fetch(node->stack, &entries);
    142 		stack_trace_snprint(buf, BUFSZ, entries, nr_entries, 0);
    143 		DRM_ERROR("node [%08"PRIx64" + %08"PRIx64"]: inserted at\n%s",
    144 			  node->start, node->size, buf);
    145 	}
    146 
    147 	kfree(buf);
    148 }
    149 
    150 #undef STACKDEPTH
    151 #undef BUFSZ
    152 #else
    153 static void save_stack(struct drm_mm_node *node) { }
    154 static void show_leaks(struct drm_mm *mm) { }
    155 #endif
    156 
    157 #define START(node) ((node)->start)
    158 #define LAST(node)  ((node)->start + (node)->size - 1)
    159 
    160 #ifndef __NetBSD__
    161 INTERVAL_TREE_DEFINE(struct drm_mm_node, rb,
    162 		     u64, __subtree_last,
    163 		     START, LAST, static inline, drm_mm_interval_tree)
    164 #endif
    165 
    166 struct drm_mm_node *
    167 __drm_mm_interval_first(const struct drm_mm *mm_const, u64 start, u64 last)
    168 {
    169 	struct drm_mm *mm = __UNCONST(mm_const);
    170 #ifdef __NetBSD__
    171 	struct drm_mm_node *node;
    172 	list_for_each_entry(node, &mm->head_node.node_list, node_list) {
    173 		if (node->start <= start)
    174 			return node;
    175 	}
    176 	return NULL;
    177 #else
    178 	return drm_mm_interval_tree_iter_first((struct rb_root_cached *)&mm->interval_tree,
    179 					       start, last) ?: (struct drm_mm_node *)&mm->head_node;
    180 #endif
    181 }
    182 EXPORT_SYMBOL(__drm_mm_interval_first);
    183 
    184 #ifndef __NetBSD__
    185 static void drm_mm_interval_tree_add_node(struct drm_mm_node *hole_node,
    186 					  struct drm_mm_node *node)
    187 {
    188 	struct drm_mm *mm = hole_node->mm;
    189 	struct rb_node **link, *rb;
    190 	struct drm_mm_node *parent;
    191 	bool leftmost;
    192 
    193 	node->__subtree_last = LAST(node);
    194 
    195 	if (drm_mm_node_allocated(hole_node)) {
    196 		rb = &hole_node->rb;
    197 		while (rb) {
    198 			parent = rb_entry(rb, struct drm_mm_node, rb);
    199 			if (parent->__subtree_last >= node->__subtree_last)
    200 				break;
    201 
    202 			parent->__subtree_last = node->__subtree_last;
    203 			rb = rb_parent(rb);
    204 		}
    205 
    206 		rb = &hole_node->rb;
    207 		link = &hole_node->rb.rb_right;
    208 		leftmost = false;
    209 	} else {
    210 		rb = NULL;
    211 		link = &mm->interval_tree.rb_root.rb_node;
    212 		leftmost = true;
    213 	}
    214 
    215 	while (*link) {
    216 		rb = *link;
    217 		parent = rb_entry(rb, struct drm_mm_node, rb);
    218 		if (parent->__subtree_last < node->__subtree_last)
    219 			parent->__subtree_last = node->__subtree_last;
    220 		if (node->start < parent->start) {
    221 			link = &parent->rb.rb_left;
    222 		} else {
    223 			link = &parent->rb.rb_right;
    224 			leftmost = false;
    225 		}
    226 	}
    227 
    228 	rb_link_node(&node->rb, rb, link);
    229 	rb_insert_augmented_cached(&node->rb, &mm->interval_tree, leftmost,
    230 				   &drm_mm_interval_tree_augment);
    231 }
    232 #endif
    233 
    234 #ifdef __NetBSD__
    235 
    236 static int
    237 compare_hole_addrs(void *cookie, const void *va, const void *vb)
    238 {
    239 	const struct drm_mm_node *a = va, *b = vb;
    240 	const u64 aa = __drm_mm_hole_node_start(a);
    241 	const u64 ba = __drm_mm_hole_node_start(b);
    242 
    243 	if (aa < ba)
    244 		return -1;
    245 	if (aa > ba)
    246 		return +1;
    247 	return 0;
    248 }
    249 
    250 static int
    251 compare_hole_addr_key(void *cookie, const void *vn, const void *vk)
    252 {
    253 	const struct drm_mm_node *n = vn;
    254 	const u64 a = __drm_mm_hole_node_start(n);
    255 	const u64 *k = vk;
    256 
    257 	if (a < *k)
    258 		return -1;
    259 	if (a > *k)
    260 		return +1;
    261 	return 0;
    262 }
    263 
    264 static const rb_tree_ops_t holes_addr_rb_ops = {
    265 	.rbto_compare_nodes = compare_hole_addrs,
    266 	.rbto_compare_key = compare_hole_addr_key,
    267 	.rbto_node_offset = offsetof(struct drm_mm_node, rb_hole_addr),
    268 };
    269 
    270 #else
    271 
    272 #define RB_INSERT(root, member, expr) do { \
    273 	struct rb_node **link = &root.rb_node, *rb = NULL; \
    274 	u64 x = expr(node); \
    275 	while (*link) { \
    276 		rb = *link; \
    277 		if (x < expr(rb_entry(rb, struct drm_mm_node, member))) \
    278 			link = &rb->rb_left; \
    279 		else \
    280 			link = &rb->rb_right; \
    281 	} \
    282 	rb_link_node(&node->member, rb, link); \
    283 	rb_insert_color(&node->member, &root); \
    284 } while (0)
    285 
    286 #endif
    287 
    288 #define HOLE_SIZE(NODE) ((NODE)->hole_size)
    289 #define HOLE_ADDR(NODE) (__drm_mm_hole_node_start(NODE))
    290 
    291 static u64 rb_to_hole_size(struct rb_node *rb)
    292 {
    293 	return rb_entry(rb, struct drm_mm_node, rb_hole_size)->hole_size;
    294 }
    295 
    296 static int
    297 compare_hole_sizes(void *cookie, const void *va, const void *vb)
    298 {
    299 	const struct drm_mm_node *a = va, *b = vb;
    300 
    301 	if (a->hole_size > b->hole_size)
    302 		return -1;
    303 	if (a->hole_size < b->hole_size)
    304 		return +1;
    305 	return (a < b ? -1 : a > b ? +1 : 0);
    306 }
    307 
    308 static int
    309 compare_hole_size_key(void *cookie, const void *vn, const void *vk)
    310 {
    311 	const struct drm_mm_node *n = vn;
    312 	const u64 *k = vk;
    313 
    314 	if (n->hole_size > *k)
    315 		return -1;
    316 	if (n->hole_size < *k)
    317 		return +1;
    318 	return 0;
    319 }
    320 
    321 static const rb_tree_ops_t holes_size_rb_ops = {
    322 	.rbto_compare_nodes = compare_hole_sizes,
    323 	.rbto_compare_key = compare_hole_size_key,
    324 	.rbto_node_offset = offsetof(struct drm_mm_node, rb_hole_size),
    325 };
    326 
    327 static void insert_hole_size(struct rb_root_cached *root,
    328 			     struct drm_mm_node *node)
    329 {
    330 #ifdef __NetBSD__
    331 	struct drm_mm_node *collision __diagused;
    332 	collision = rb_tree_insert_node(&root->rb_root.rbr_tree, node);
    333 	KASSERT(collision == node);
    334 #else
    335 	struct rb_node **link = &root->rb_root.rb_node, *rb = NULL;
    336 	u64 x = node->hole_size;
    337 	bool first = true;
    338 
    339 	while (*link) {
    340 		rb = *link;
    341 		if (x > rb_to_hole_size(rb)) {
    342 			link = &rb->rb_left;
    343 		} else {
    344 			link = &rb->rb_right;
    345 			first = false;
    346 		}
    347 	}
    348 
    349 	rb_link_node(&node->rb_hole_size, rb, link);
    350 	rb_insert_color_cached(&node->rb_hole_size, root, first);
    351 #endif
    352 }
    353 
    354 static void add_hole(struct drm_mm_node *node)
    355 {
    356 	struct drm_mm *mm = node->mm;
    357 
    358 	node->hole_size =
    359 		__drm_mm_hole_node_end(node) - __drm_mm_hole_node_start(node);
    360 	DRM_MM_BUG_ON(!drm_mm_hole_follows(node));
    361 
    362 	insert_hole_size(&mm->holes_size, node);
    363 #ifdef __NetBSD__
    364 	struct drm_mm_node *collision __diagused;
    365 	collision = rb_tree_insert_node(&mm->holes_addr.rbr_tree, node);
    366 	KASSERT(collision == node);
    367 #else
    368 	RB_INSERT(mm->holes_addr, rb_hole_addr, HOLE_ADDR);
    369 #endif
    370 
    371 	list_add(&node->hole_stack, &mm->hole_stack);
    372 }
    373 
    374 static void rm_hole(struct drm_mm_node *node)
    375 {
    376 	DRM_MM_BUG_ON(!drm_mm_hole_follows(node));
    377 
    378 	list_del(&node->hole_stack);
    379 	rb_erase_cached(&node->rb_hole_size, &node->mm->holes_size);
    380 	rb_erase(&node->rb_hole_addr, &node->mm->holes_addr);
    381 	node->hole_size = 0;
    382 
    383 	DRM_MM_BUG_ON(drm_mm_hole_follows(node));
    384 }
    385 
    386 static inline struct drm_mm_node *rb_hole_size_to_node(struct rb_node *rb)
    387 {
    388 	return rb_entry_safe(rb, struct drm_mm_node, rb_hole_size);
    389 }
    390 
    391 static inline struct drm_mm_node *rb_hole_addr_to_node(struct rb_node *rb)
    392 {
    393 	return rb_entry_safe(rb, struct drm_mm_node, rb_hole_addr);
    394 }
    395 
    396 static inline u64 rb_hole_size(struct rb_node *rb)
    397 {
    398 	return rb_entry(rb, struct drm_mm_node, rb_hole_size)->hole_size;
    399 }
    400 
    401 static struct drm_mm_node *best_hole(struct drm_mm *mm, u64 size)
    402 {
    403 #ifdef __NetBSD__
    404 	return rb_tree_find_node_geq(&mm->holes_size.rb_root.rbr_tree, &size);
    405 #else
    406 	struct rb_node *rb = mm->holes_size.rb_root.rb_node;
    407 	struct drm_mm_node *best = NULL;
    408 
    409 	do {
    410 		struct drm_mm_node *node =
    411 			rb_entry(rb, struct drm_mm_node, rb_hole_size);
    412 
    413 		if (size <= node->hole_size) {
    414 			best = node;
    415 			rb = rb->rb_right;
    416 		} else {
    417 			rb = rb->rb_left;
    418 		}
    419 	} while (rb);
    420 
    421 	return best;
    422 #endif
    423 }
    424 
    425 static struct drm_mm_node *find_hole(struct drm_mm *mm, u64 addr)
    426 {
    427 #ifdef __NetBSD__
    428 	return rb_tree_find_node_leq(&mm->holes_addr.rbr_tree, &addr);
    429 #else
    430 	struct rb_node *rb = mm->holes_addr.rb_node;
    431 	struct drm_mm_node *node = NULL;
    432 
    433 	while (rb) {
    434 		u64 hole_start;
    435 
    436 		node = rb_hole_addr_to_node(rb);
    437 		hole_start = __drm_mm_hole_node_start(node);
    438 
    439 		if (addr < hole_start)
    440 			rb = node->rb_hole_addr.rb_left;
    441 		else if (addr > hole_start + node->hole_size)
    442 			rb = node->rb_hole_addr.rb_right;
    443 		else
    444 			break;
    445 	}
    446 
    447 	return node;
    448 #endif
    449 }
    450 
    451 static struct drm_mm_node *
    452 first_hole(struct drm_mm *mm,
    453 	   u64 start, u64 end, u64 size,
    454 	   enum drm_mm_insert_mode mode)
    455 {
    456 	switch (mode) {
    457 	default:
    458 	case DRM_MM_INSERT_BEST:
    459 		return best_hole(mm, size);
    460 
    461 	case DRM_MM_INSERT_LOW:
    462 		return find_hole(mm, start);
    463 
    464 	case DRM_MM_INSERT_HIGH:
    465 		return find_hole(mm, end);
    466 
    467 	case DRM_MM_INSERT_EVICT:
    468 		return list_first_entry_or_null(&mm->hole_stack,
    469 						struct drm_mm_node,
    470 						hole_stack);
    471 	}
    472 }
    473 
    474 static struct drm_mm_node *
    475 next_hole(struct drm_mm *mm,
    476 	  struct drm_mm_node *node,
    477 	  enum drm_mm_insert_mode mode)
    478 {
    479 	switch (mode) {
    480 	default:
    481 	case DRM_MM_INSERT_BEST:
    482 #ifdef __NetBSD__
    483 		return RB_TREE_PREV(&mm->holes_size.rb_root.rbr_tree, node);
    484 #else
    485 		return rb_hole_size_to_node(rb_prev(&node->rb_hole_size));
    486 #endif
    487 
    488 	case DRM_MM_INSERT_LOW:
    489 #ifdef __NetBSD__
    490 		return RB_TREE_NEXT(&mm->holes_addr.rbr_tree, node);
    491 #else
    492 		return rb_hole_addr_to_node(rb_next(&node->rb_hole_addr));
    493 #endif
    494 
    495 	case DRM_MM_INSERT_HIGH:
    496 #ifdef __NetBSD__
    497 		return RB_TREE_PREV(&mm->holes_addr.rbr_tree, node);
    498 #else
    499 		return rb_hole_addr_to_node(rb_prev(&node->rb_hole_addr));
    500 #endif
    501 
    502 	case DRM_MM_INSERT_EVICT:
    503 		node = list_next_entry(node, hole_stack);
    504 		return &node->hole_stack == &mm->hole_stack ? NULL : node;
    505 	}
    506 }
    507 
    508 /**
    509  * drm_mm_reserve_node - insert an pre-initialized node
    510  * @mm: drm_mm allocator to insert @node into
    511  * @node: drm_mm_node to insert
    512  *
    513  * This functions inserts an already set-up &drm_mm_node into the allocator,
    514  * meaning that start, size and color must be set by the caller. All other
    515  * fields must be cleared to 0. This is useful to initialize the allocator with
    516  * preallocated objects which must be set-up before the range allocator can be
    517  * set-up, e.g. when taking over a firmware framebuffer.
    518  *
    519  * Returns:
    520  * 0 on success, -ENOSPC if there's no hole where @node is.
    521  */
    522 int drm_mm_reserve_node(struct drm_mm *mm, struct drm_mm_node *node)
    523 {
    524 	u64 end = node->start + node->size;
    525 	struct drm_mm_node *hole;
    526 	u64 hole_start, hole_end;
    527 	u64 adj_start, adj_end;
    528 
    529 	end = node->start + node->size;
    530 	if (unlikely(end <= node->start))
    531 		return -ENOSPC;
    532 
    533 	/* Find the relevant hole to add our node to */
    534 	hole = find_hole(mm, node->start);
    535 	if (!hole)
    536 		return -ENOSPC;
    537 
    538 	adj_start = hole_start = __drm_mm_hole_node_start(hole);
    539 	adj_end = hole_end = hole_start + hole->hole_size;
    540 
    541 	if (mm->color_adjust)
    542 		mm->color_adjust(hole, node->color, &adj_start, &adj_end);
    543 
    544 	if (adj_start > node->start || adj_end < end)
    545 		return -ENOSPC;
    546 
    547 	node->mm = mm;
    548 
    549 	__set_bit(DRM_MM_NODE_ALLOCATED_BIT, &node->flags);
    550 	list_add(&node->node_list, &hole->node_list);
    551 #ifndef __NetBSD__
    552 	drm_mm_interval_tree_add_node(hole, node);
    553 #endif
    554 	node->hole_size = 0;
    555 
    556 	rm_hole(hole);
    557 	if (node->start > hole_start)
    558 		add_hole(hole);
    559 	if (end < hole_end)
    560 		add_hole(node);
    561 
    562 	save_stack(node);
    563 	return 0;
    564 }
    565 EXPORT_SYMBOL(drm_mm_reserve_node);
    566 
    567 static u64 rb_to_hole_size_or_zero(struct rb_node *rb)
    568 {
    569 	return rb ? rb_to_hole_size(rb) : 0;
    570 }
    571 
    572 /**
    573  * drm_mm_insert_node_in_range - ranged search for space and insert @node
    574  * @mm: drm_mm to allocate from
    575  * @node: preallocate node to insert
    576  * @size: size of the allocation
    577  * @alignment: alignment of the allocation
    578  * @color: opaque tag value to use for this node
    579  * @range_start: start of the allowed range for this node
    580  * @range_end: end of the allowed range for this node
    581  * @mode: fine-tune the allocation search and placement
    582  *
    583  * The preallocated @node must be cleared to 0.
    584  *
    585  * Returns:
    586  * 0 on success, -ENOSPC if there's no suitable hole.
    587  */
    588 int drm_mm_insert_node_in_range(struct drm_mm * const mm,
    589 				struct drm_mm_node * const node,
    590 				u64 size, u64 alignment,
    591 				unsigned long color,
    592 				u64 range_start, u64 range_end,
    593 				enum drm_mm_insert_mode mode)
    594 {
    595 	struct drm_mm_node *hole;
    596 	u64 remainder_mask;
    597 	bool once;
    598 
    599 	DRM_MM_BUG_ON(range_start > range_end);
    600 
    601 	if (unlikely(size == 0 || range_end - range_start < size))
    602 		return -ENOSPC;
    603 
    604 	if (rb_to_hole_size_or_zero(rb_first_cached(&mm->holes_size)) < size)
    605 		return -ENOSPC;
    606 
    607 	if (alignment <= 1)
    608 		alignment = 0;
    609 
    610 	once = mode & DRM_MM_INSERT_ONCE;
    611 	mode &= ~DRM_MM_INSERT_ONCE;
    612 
    613 	remainder_mask = is_power_of_2(alignment) ? alignment - 1 : 0;
    614 	for (hole = first_hole(mm, range_start, range_end, size, mode);
    615 	     hole;
    616 	     hole = once ? NULL : next_hole(mm, hole, mode)) {
    617 		u64 hole_start = __drm_mm_hole_node_start(hole);
    618 		u64 hole_end = hole_start + hole->hole_size;
    619 		u64 adj_start, adj_end;
    620 		u64 col_start, col_end;
    621 
    622 		if (mode == DRM_MM_INSERT_LOW && hole_start >= range_end)
    623 			break;
    624 
    625 		if (mode == DRM_MM_INSERT_HIGH && hole_end <= range_start)
    626 			break;
    627 
    628 		col_start = hole_start;
    629 		col_end = hole_end;
    630 		if (mm->color_adjust)
    631 			mm->color_adjust(hole, color, &col_start, &col_end);
    632 
    633 		adj_start = max(col_start, range_start);
    634 		adj_end = min(col_end, range_end);
    635 
    636 		if (adj_end <= adj_start || adj_end - adj_start < size)
    637 			continue;
    638 
    639 		if (mode == DRM_MM_INSERT_HIGH)
    640 			adj_start = adj_end - size;
    641 
    642 		if (alignment) {
    643 			u64 rem;
    644 
    645 			if (likely(remainder_mask))
    646 				rem = adj_start & remainder_mask;
    647 			else
    648 				div64_u64_rem(adj_start, alignment, &rem);
    649 			if (rem) {
    650 				adj_start -= rem;
    651 				if (mode != DRM_MM_INSERT_HIGH)
    652 					adj_start += alignment;
    653 
    654 				if (adj_start < max(col_start, range_start) ||
    655 				    min(col_end, range_end) - adj_start < size)
    656 					continue;
    657 
    658 				if (adj_end <= adj_start ||
    659 				    adj_end - adj_start < size)
    660 					continue;
    661 			}
    662 		}
    663 
    664 		node->mm = mm;
    665 		node->size = size;
    666 		node->start = adj_start;
    667 		node->color = color;
    668 		node->hole_size = 0;
    669 
    670 		__set_bit(DRM_MM_NODE_ALLOCATED_BIT, &node->flags);
    671 		list_add(&node->node_list, &hole->node_list);
    672 #ifndef __NetBSD__
    673 		drm_mm_interval_tree_add_node(hole, node);
    674 #endif
    675 
    676 		rm_hole(hole);
    677 		if (adj_start > hole_start)
    678 			add_hole(hole);
    679 		if (adj_start + size < hole_end)
    680 			add_hole(node);
    681 
    682 		save_stack(node);
    683 		return 0;
    684 	}
    685 
    686 	return -ENOSPC;
    687 }
    688 EXPORT_SYMBOL(drm_mm_insert_node_in_range);
    689 
    690 static inline bool drm_mm_node_scanned_block(const struct drm_mm_node *node)
    691 {
    692 	return test_bit(DRM_MM_NODE_SCANNED_BIT, &node->flags);
    693 }
    694 
    695 /**
    696  * drm_mm_remove_node - Remove a memory node from the allocator.
    697  * @node: drm_mm_node to remove
    698  *
    699  * This just removes a node from its drm_mm allocator. The node does not need to
    700  * be cleared again before it can be re-inserted into this or any other drm_mm
    701  * allocator. It is a bug to call this function on a unallocated node.
    702  */
    703 void drm_mm_remove_node(struct drm_mm_node *node)
    704 {
    705 	struct drm_mm *mm = node->mm;
    706 	struct drm_mm_node *prev_node;
    707 
    708 	DRM_MM_BUG_ON(!drm_mm_node_allocated(node));
    709 	DRM_MM_BUG_ON(drm_mm_node_scanned_block(node));
    710 
    711 	prev_node = list_prev_entry(node, node_list);
    712 
    713 	if (drm_mm_hole_follows(node))
    714 		rm_hole(node);
    715 
    716 #ifdef __NetBSD__
    717 	__USE(mm);
    718 #else
    719 	drm_mm_interval_tree_remove(node, &mm->interval_tree);
    720 #endif
    721 	list_del(&node->node_list);
    722 
    723 	if (drm_mm_hole_follows(prev_node))
    724 		rm_hole(prev_node);
    725 	add_hole(prev_node);
    726 
    727 	clear_bit_unlock(DRM_MM_NODE_ALLOCATED_BIT, &node->flags);
    728 }
    729 EXPORT_SYMBOL(drm_mm_remove_node);
    730 
    731 /**
    732  * drm_mm_replace_node - move an allocation from @old to @new
    733  * @old: drm_mm_node to remove from the allocator
    734  * @new: drm_mm_node which should inherit @old's allocation
    735  *
    736  * This is useful for when drivers embed the drm_mm_node structure and hence
    737  * can't move allocations by reassigning pointers. It's a combination of remove
    738  * and insert with the guarantee that the allocation start will match.
    739  */
    740 void drm_mm_replace_node(struct drm_mm_node *old, struct drm_mm_node *new)
    741 {
    742 	struct drm_mm *mm = old->mm;
    743 
    744 	DRM_MM_BUG_ON(!drm_mm_node_allocated(old));
    745 
    746 	*new = *old;
    747 
    748 	__set_bit(DRM_MM_NODE_ALLOCATED_BIT, &new->flags);
    749 	list_replace(&old->node_list, &new->node_list);
    750 #ifndef __NetBSD__
    751 	rb_replace_node_cached(&old->rb, &new->rb, &mm->interval_tree);
    752 #endif
    753 
    754 	if (drm_mm_hole_follows(old)) {
    755 		list_replace(&old->hole_stack, &new->hole_stack);
    756 		rb_replace_node_cached(&old->rb_hole_size,
    757 				       &new->rb_hole_size,
    758 				       &mm->holes_size);
    759 		rb_replace_node(&old->rb_hole_addr,
    760 				&new->rb_hole_addr,
    761 				&mm->holes_addr);
    762 	}
    763 
    764 	clear_bit_unlock(DRM_MM_NODE_ALLOCATED_BIT, &old->flags);
    765 }
    766 EXPORT_SYMBOL(drm_mm_replace_node);
    767 
    768 /**
    769  * DOC: lru scan roster
    770  *
    771  * Very often GPUs need to have continuous allocations for a given object. When
    772  * evicting objects to make space for a new one it is therefore not most
    773  * efficient when we simply start to select all objects from the tail of an LRU
    774  * until there's a suitable hole: Especially for big objects or nodes that
    775  * otherwise have special allocation constraints there's a good chance we evict
    776  * lots of (smaller) objects unnecessarily.
    777  *
    778  * The DRM range allocator supports this use-case through the scanning
    779  * interfaces. First a scan operation needs to be initialized with
    780  * drm_mm_scan_init() or drm_mm_scan_init_with_range(). The driver adds
    781  * objects to the roster, probably by walking an LRU list, but this can be
    782  * freely implemented. Eviction candiates are added using
    783  * drm_mm_scan_add_block() until a suitable hole is found or there are no
    784  * further evictable objects. Eviction roster metadata is tracked in &struct
    785  * drm_mm_scan.
    786  *
    787  * The driver must walk through all objects again in exactly the reverse
    788  * order to restore the allocator state. Note that while the allocator is used
    789  * in the scan mode no other operation is allowed.
    790  *
    791  * Finally the driver evicts all objects selected (drm_mm_scan_remove_block()
    792  * reported true) in the scan, and any overlapping nodes after color adjustment
    793  * (drm_mm_scan_color_evict()). Adding and removing an object is O(1), and
    794  * since freeing a node is also O(1) the overall complexity is
    795  * O(scanned_objects). So like the free stack which needs to be walked before a
    796  * scan operation even begins this is linear in the number of objects. It
    797  * doesn't seem to hurt too badly.
    798  */
    799 
    800 /**
    801  * drm_mm_scan_init_with_range - initialize range-restricted lru scanning
    802  * @scan: scan state
    803  * @mm: drm_mm to scan
    804  * @size: size of the allocation
    805  * @alignment: alignment of the allocation
    806  * @color: opaque tag value to use for the allocation
    807  * @start: start of the allowed range for the allocation
    808  * @end: end of the allowed range for the allocation
    809  * @mode: fine-tune the allocation search and placement
    810  *
    811  * This simply sets up the scanning routines with the parameters for the desired
    812  * hole.
    813  *
    814  * Warning:
    815  * As long as the scan list is non-empty, no other operations than
    816  * adding/removing nodes to/from the scan list are allowed.
    817  */
    818 void drm_mm_scan_init_with_range(struct drm_mm_scan *scan,
    819 				 struct drm_mm *mm,
    820 				 u64 size,
    821 				 u64 alignment,
    822 				 unsigned long color,
    823 				 u64 start,
    824 				 u64 end,
    825 				 enum drm_mm_insert_mode mode)
    826 {
    827 	DRM_MM_BUG_ON(start >= end);
    828 	DRM_MM_BUG_ON(!size || size > end - start);
    829 	DRM_MM_BUG_ON(mm->scan_active);
    830 
    831 	scan->mm = mm;
    832 
    833 	if (alignment <= 1)
    834 		alignment = 0;
    835 
    836 	scan->color = color;
    837 	scan->alignment = alignment;
    838 	scan->remainder_mask = is_power_of_2(alignment) ? alignment - 1 : 0;
    839 	scan->size = size;
    840 	scan->mode = mode;
    841 
    842 	DRM_MM_BUG_ON(end <= start);
    843 	scan->range_start = start;
    844 	scan->range_end = end;
    845 
    846 	scan->hit_start = U64_MAX;
    847 	scan->hit_end = 0;
    848 }
    849 EXPORT_SYMBOL(drm_mm_scan_init_with_range);
    850 
    851 /**
    852  * drm_mm_scan_add_block - add a node to the scan list
    853  * @scan: the active drm_mm scanner
    854  * @node: drm_mm_node to add
    855  *
    856  * Add a node to the scan list that might be freed to make space for the desired
    857  * hole.
    858  *
    859  * Returns:
    860  * True if a hole has been found, false otherwise.
    861  */
    862 bool drm_mm_scan_add_block(struct drm_mm_scan *scan,
    863 			   struct drm_mm_node *node)
    864 {
    865 	struct drm_mm *mm = scan->mm;
    866 	struct drm_mm_node *hole;
    867 	u64 hole_start, hole_end;
    868 	u64 col_start, col_end;
    869 	u64 adj_start, adj_end;
    870 
    871 	DRM_MM_BUG_ON(node->mm != mm);
    872 	DRM_MM_BUG_ON(!drm_mm_node_allocated(node));
    873 	DRM_MM_BUG_ON(drm_mm_node_scanned_block(node));
    874 	__set_bit(DRM_MM_NODE_SCANNED_BIT, &node->flags);
    875 	mm->scan_active++;
    876 
    877 	/* Remove this block from the node_list so that we enlarge the hole
    878 	 * (distance between the end of our previous node and the start of
    879 	 * or next), without poisoning the link so that we can restore it
    880 	 * later in drm_mm_scan_remove_block().
    881 	 */
    882 	hole = list_prev_entry(node, node_list);
    883 	DRM_MM_BUG_ON(list_next_entry(hole, node_list) != node);
    884 	__list_del_entry(&node->node_list);
    885 
    886 	hole_start = __drm_mm_hole_node_start(hole);
    887 	hole_end = __drm_mm_hole_node_end(hole);
    888 
    889 	col_start = hole_start;
    890 	col_end = hole_end;
    891 	if (mm->color_adjust)
    892 		mm->color_adjust(hole, scan->color, &col_start, &col_end);
    893 
    894 	adj_start = max(col_start, scan->range_start);
    895 	adj_end = min(col_end, scan->range_end);
    896 	if (adj_end <= adj_start || adj_end - adj_start < scan->size)
    897 		return false;
    898 
    899 	if (scan->mode == DRM_MM_INSERT_HIGH)
    900 		adj_start = adj_end - scan->size;
    901 
    902 	if (scan->alignment) {
    903 		u64 rem;
    904 
    905 		if (likely(scan->remainder_mask))
    906 			rem = adj_start & scan->remainder_mask;
    907 		else
    908 			div64_u64_rem(adj_start, scan->alignment, &rem);
    909 		if (rem) {
    910 			adj_start -= rem;
    911 			if (scan->mode != DRM_MM_INSERT_HIGH)
    912 				adj_start += scan->alignment;
    913 			if (adj_start < max(col_start, scan->range_start) ||
    914 			    min(col_end, scan->range_end) - adj_start < scan->size)
    915 				return false;
    916 
    917 			if (adj_end <= adj_start ||
    918 			    adj_end - adj_start < scan->size)
    919 				return false;
    920 		}
    921 	}
    922 
    923 	scan->hit_start = adj_start;
    924 	scan->hit_end = adj_start + scan->size;
    925 
    926 	DRM_MM_BUG_ON(scan->hit_start >= scan->hit_end);
    927 	DRM_MM_BUG_ON(scan->hit_start < hole_start);
    928 	DRM_MM_BUG_ON(scan->hit_end > hole_end);
    929 
    930 	return true;
    931 }
    932 EXPORT_SYMBOL(drm_mm_scan_add_block);
    933 
    934 /**
    935  * drm_mm_scan_remove_block - remove a node from the scan list
    936  * @scan: the active drm_mm scanner
    937  * @node: drm_mm_node to remove
    938  *
    939  * Nodes **must** be removed in exactly the reverse order from the scan list as
    940  * they have been added (e.g. using list_add() as they are added and then
    941  * list_for_each() over that eviction list to remove), otherwise the internal
    942  * state of the memory manager will be corrupted.
    943  *
    944  * When the scan list is empty, the selected memory nodes can be freed. An
    945  * immediately following drm_mm_insert_node_in_range_generic() or one of the
    946  * simpler versions of that function with !DRM_MM_SEARCH_BEST will then return
    947  * the just freed block (because it's at the top of the free_stack list).
    948  *
    949  * Returns:
    950  * True if this block should be evicted, false otherwise. Will always
    951  * return false when no hole has been found.
    952  */
    953 bool drm_mm_scan_remove_block(struct drm_mm_scan *scan,
    954 			      struct drm_mm_node *node)
    955 {
    956 	struct drm_mm_node *prev_node;
    957 
    958 	DRM_MM_BUG_ON(node->mm != scan->mm);
    959 	DRM_MM_BUG_ON(!drm_mm_node_scanned_block(node));
    960 	__clear_bit(DRM_MM_NODE_SCANNED_BIT, &node->flags);
    961 
    962 	DRM_MM_BUG_ON(!node->mm->scan_active);
    963 	node->mm->scan_active--;
    964 
    965 	/* During drm_mm_scan_add_block() we decoupled this node leaving
    966 	 * its pointers intact. Now that the caller is walking back along
    967 	 * the eviction list we can restore this block into its rightful
    968 	 * place on the full node_list. To confirm that the caller is walking
    969 	 * backwards correctly we check that prev_node->next == node->next,
    970 	 * i.e. both believe the same node should be on the other side of the
    971 	 * hole.
    972 	 */
    973 	prev_node = list_prev_entry(node, node_list);
    974 	DRM_MM_BUG_ON(list_next_entry(prev_node, node_list) !=
    975 		      list_next_entry(node, node_list));
    976 	list_add(&node->node_list, &prev_node->node_list);
    977 
    978 	return (node->start + node->size > scan->hit_start &&
    979 		node->start < scan->hit_end);
    980 }
    981 EXPORT_SYMBOL(drm_mm_scan_remove_block);
    982 
    983 /**
    984  * drm_mm_scan_color_evict - evict overlapping nodes on either side of hole
    985  * @scan: drm_mm scan with target hole
    986  *
    987  * After completing an eviction scan and removing the selected nodes, we may
    988  * need to remove a few more nodes from either side of the target hole if
    989  * mm.color_adjust is being used.
    990  *
    991  * Returns:
    992  * A node to evict, or NULL if there are no overlapping nodes.
    993  */
    994 struct drm_mm_node *drm_mm_scan_color_evict(struct drm_mm_scan *scan)
    995 {
    996 	struct drm_mm *mm = scan->mm;
    997 	struct drm_mm_node *hole;
    998 	u64 hole_start, hole_end;
    999 
   1000 	DRM_MM_BUG_ON(list_empty(&mm->hole_stack));
   1001 
   1002 	if (!mm->color_adjust)
   1003 		return NULL;
   1004 
   1005 	/*
   1006 	 * The hole found during scanning should ideally be the first element
   1007 	 * in the hole_stack list, but due to side-effects in the driver it
   1008 	 * may not be.
   1009 	 */
   1010 	list_for_each_entry(hole, &mm->hole_stack, hole_stack) {
   1011 		hole_start = __drm_mm_hole_node_start(hole);
   1012 		hole_end = hole_start + hole->hole_size;
   1013 
   1014 		if (hole_start <= scan->hit_start &&
   1015 		    hole_end >= scan->hit_end)
   1016 			break;
   1017 	}
   1018 
   1019 	/* We should only be called after we found the hole previously */
   1020 	DRM_MM_BUG_ON(&hole->hole_stack == &mm->hole_stack);
   1021 	if (unlikely(&hole->hole_stack == &mm->hole_stack))
   1022 		return NULL;
   1023 
   1024 	DRM_MM_BUG_ON(hole_start > scan->hit_start);
   1025 	DRM_MM_BUG_ON(hole_end < scan->hit_end);
   1026 
   1027 	mm->color_adjust(hole, scan->color, &hole_start, &hole_end);
   1028 	if (hole_start > scan->hit_start)
   1029 		return hole;
   1030 	if (hole_end < scan->hit_end)
   1031 		return list_next_entry(hole, node_list);
   1032 
   1033 	return NULL;
   1034 }
   1035 EXPORT_SYMBOL(drm_mm_scan_color_evict);
   1036 
   1037 /**
   1038  * drm_mm_init - initialize a drm-mm allocator
   1039  * @mm: the drm_mm structure to initialize
   1040  * @start: start of the range managed by @mm
   1041  * @size: end of the range managed by @mm
   1042  *
   1043  * Note that @mm must be cleared to 0 before calling this function.
   1044  */
   1045 void drm_mm_init(struct drm_mm *mm, u64 start, u64 size)
   1046 {
   1047 	DRM_MM_BUG_ON(start + size <= start);
   1048 
   1049 	mm->color_adjust = NULL;
   1050 
   1051 	INIT_LIST_HEAD(&mm->hole_stack);
   1052 #ifdef __NetBSD__
   1053 	/* XXX interval tree */
   1054 	rb_tree_init(&mm->holes_size.rb_root.rbr_tree, &holes_size_rb_ops);
   1055 	rb_tree_init(&mm->holes_addr.rbr_tree, &holes_addr_rb_ops);
   1056 #else
   1057 	mm->interval_tree = RB_ROOT_CACHED;
   1058 	mm->holes_size = RB_ROOT_CACHED;
   1059 	mm->holes_addr = RB_ROOT;
   1060 #endif
   1061 
   1062 	/* Clever trick to avoid a special case in the free hole tracking. */
   1063 	INIT_LIST_HEAD(&mm->head_node.node_list);
   1064 	mm->head_node.flags = 0;
   1065 	mm->head_node.mm = mm;
   1066 	mm->head_node.start = start + size;
   1067 	mm->head_node.size = -size;
   1068 	add_hole(&mm->head_node);
   1069 
   1070 	mm->scan_active = 0;
   1071 }
   1072 EXPORT_SYMBOL(drm_mm_init);
   1073 
   1074 /**
   1075  * drm_mm_takedown - clean up a drm_mm allocator
   1076  * @mm: drm_mm allocator to clean up
   1077  *
   1078  * Note that it is a bug to call this function on an allocator which is not
   1079  * clean.
   1080  */
   1081 void drm_mm_takedown(struct drm_mm *mm)
   1082 {
   1083 	if (WARN(!drm_mm_clean(mm),
   1084 		 "Memory manager not clean during takedown.\n"))
   1085 		show_leaks(mm);
   1086 }
   1087 EXPORT_SYMBOL(drm_mm_takedown);
   1088 
   1089 static u64 drm_mm_dump_hole(struct drm_printer *p, const struct drm_mm_node *entry)
   1090 {
   1091 	u64 start, size;
   1092 
   1093 	size = entry->hole_size;
   1094 	if (size) {
   1095 		start = drm_mm_hole_node_start(entry);
   1096 		drm_printf(p, "%#018"PRIx64"-%#018"PRIx64": %"PRIu64": free\n",
   1097 			   start, start + size, size);
   1098 	}
   1099 
   1100 	return size;
   1101 }
   1102 /**
   1103  * drm_mm_print - print allocator state
   1104  * @mm: drm_mm allocator to print
   1105  * @p: DRM printer to use
   1106  */
   1107 void drm_mm_print(const struct drm_mm *mm, struct drm_printer *p)
   1108 {
   1109 	const struct drm_mm_node *entry;
   1110 	u64 total_used = 0, total_free = 0, total = 0;
   1111 
   1112 	total_free += drm_mm_dump_hole(p, &mm->head_node);
   1113 
   1114 	drm_mm_for_each_node(entry, mm) {
   1115 		drm_printf(p, "%#018"PRIx64"-%#018"PRIx64": %"PRIu64": used\n", entry->start,
   1116 			   entry->start + entry->size, entry->size);
   1117 		total_used += entry->size;
   1118 		total_free += drm_mm_dump_hole(p, entry);
   1119 	}
   1120 	total = total_free + total_used;
   1121 
   1122 	drm_printf(p, "total: %"PRIu64", used %"PRIu64" free %"PRIu64"\n", total,
   1123 		   total_used, total_free);
   1124 }
   1125 EXPORT_SYMBOL(drm_mm_print);
   1126