Lines Matching full:block
19 struct drm_buddy_block *block; in drm_block_alloc() local
23 block = kmem_cache_zalloc(slab_blocks, GFP_KERNEL); in drm_block_alloc()
24 if (!block) in drm_block_alloc()
27 block->header = offset; in drm_block_alloc()
28 block->header |= order; in drm_block_alloc()
29 block->parent = parent; in drm_block_alloc()
31 BUG_ON(block->header & DRM_BUDDY_HEADER_UNUSED); in drm_block_alloc()
32 return block; in drm_block_alloc()
36 struct drm_buddy_block *block) in drm_block_free() argument
38 kmem_cache_free(slab_blocks, block); in drm_block_free()
42 struct drm_buddy_block *block) in list_insert_sorted() argument
47 head = &mm->free_list[drm_buddy_block_order(block)]; in list_insert_sorted()
49 list_add(&block->link, head); in list_insert_sorted()
54 if (drm_buddy_block_offset(block) < drm_buddy_block_offset(node)) in list_insert_sorted()
57 __list_add(&block->link, node->link.prev, &node->link); in list_insert_sorted()
60 static void clear_reset(struct drm_buddy_block *block) in clear_reset() argument
62 block->header &= ~DRM_BUDDY_HEADER_CLEAR; in clear_reset()
65 static void mark_cleared(struct drm_buddy_block *block) in mark_cleared() argument
67 block->header |= DRM_BUDDY_HEADER_CLEAR; in mark_cleared()
70 static void mark_allocated(struct drm_buddy_block *block) in mark_allocated() argument
72 block->header &= ~DRM_BUDDY_HEADER_STATE; in mark_allocated()
73 block->header |= DRM_BUDDY_ALLOCATED; in mark_allocated()
75 list_del(&block->link); in mark_allocated()
79 struct drm_buddy_block *block) in mark_free() argument
81 block->header &= ~DRM_BUDDY_HEADER_STATE; in mark_free()
82 block->header |= DRM_BUDDY_FREE; in mark_free()
84 list_insert_sorted(mm, block); in mark_free()
87 static void mark_split(struct drm_buddy_block *block) in mark_split() argument
89 block->header &= ~DRM_BUDDY_HEADER_STATE; in mark_split()
90 block->header |= DRM_BUDDY_SPLIT; in mark_split()
92 list_del(&block->link); in mark_split()
106 __get_buddy(struct drm_buddy_block *block) in __get_buddy() argument
110 parent = block->parent; in __get_buddy()
114 if (parent->left == block) in __get_buddy()
121 struct drm_buddy_block *block, in __drm_buddy_free() argument
127 while ((parent = block->parent)) { in __drm_buddy_free()
130 buddy = __get_buddy(block); in __drm_buddy_free()
137 * Check the block and its buddy clear state and exit in __drm_buddy_free()
140 if (drm_buddy_block_is_clear(block) != in __drm_buddy_free()
144 if (drm_buddy_block_is_clear(block)) in __drm_buddy_free()
152 drm_block_free(mm, block); in __drm_buddy_free()
155 block = parent; in __drm_buddy_free()
158 order = drm_buddy_block_order(block); in __drm_buddy_free()
159 mark_free(mm, block); in __drm_buddy_free()
179 struct drm_buddy_block *block, *prev; in __force_merge() local
181 list_for_each_entry_safe_reverse(block, prev, &mm->free_list[i], link) { in __force_merge()
185 if (!block->parent) in __force_merge()
188 block_start = drm_buddy_block_offset(block); in __force_merge()
189 block_end = block_start + drm_buddy_block_size(mm, block) - 1; in __force_merge()
194 buddy = __get_buddy(block); in __force_merge()
198 WARN_ON(drm_buddy_block_is_clear(block) == in __force_merge()
202 * If the prev block is same as buddy, don't access the in __force_merge()
203 * block in the next iteration as we would free the in __force_merge()
204 * buddy block as part of the free function. in __force_merge()
209 list_del(&block->link); in __force_merge()
210 if (drm_buddy_block_is_clear(block)) in __force_merge()
211 mm->clear_avail -= drm_buddy_block_size(mm, block); in __force_merge()
213 order = __drm_buddy_free(mm, block, true); in __force_merge()
352 struct drm_buddy_block *block) in split_block() argument
354 unsigned int block_order = drm_buddy_block_order(block) - 1; in split_block()
355 u64 offset = drm_buddy_block_offset(block); in split_block()
357 BUG_ON(!drm_buddy_block_is_free(block)); in split_block()
358 BUG_ON(!drm_buddy_block_order(block)); in split_block()
360 block->left = drm_block_alloc(mm, block, block_order, offset); in split_block()
361 if (!block->left) in split_block()
364 block->right = drm_block_alloc(mm, block, block_order, in split_block()
366 if (!block->right) { in split_block()
367 drm_block_free(mm, block->left); in split_block()
371 mark_free(mm, block->left); in split_block()
372 mark_free(mm, block->right); in split_block()
374 if (drm_buddy_block_is_clear(block)) { in split_block()
375 mark_cleared(block->left); in split_block()
376 mark_cleared(block->right); in split_block()
377 clear_reset(block); in split_block()
380 mark_split(block); in split_block()
388 * @block: DRM buddy block
390 * Returns the corresponding buddy block for @block, or NULL
391 * if this is a root block and can't be merged further.
396 drm_get_buddy(struct drm_buddy_block *block) in drm_get_buddy() argument
398 return __get_buddy(block); in drm_get_buddy()
403 * drm_buddy_free_block - free a block
406 * @block: block to be freed
409 struct drm_buddy_block *block) in drm_buddy_free_block() argument
411 BUG_ON(!drm_buddy_block_is_allocated(block)); in drm_buddy_free_block()
412 mm->avail += drm_buddy_block_size(mm, block); in drm_buddy_free_block()
413 if (drm_buddy_block_is_clear(block)) in drm_buddy_free_block()
414 mm->clear_avail += drm_buddy_block_size(mm, block); in drm_buddy_free_block()
416 __drm_buddy_free(mm, block, false); in drm_buddy_free_block()
425 struct drm_buddy_block *block, *on; in __drm_buddy_free_list() local
429 list_for_each_entry_safe(block, on, objects, link) { in __drm_buddy_free_list()
431 mark_cleared(block); in __drm_buddy_free_list()
433 clear_reset(block); in __drm_buddy_free_list()
434 drm_buddy_free_block(mm, block); in __drm_buddy_free_list()
468 static bool block_incompatible(struct drm_buddy_block *block, unsigned int flags) in block_incompatible() argument
472 return needs_clear != drm_buddy_block_is_clear(block); in block_incompatible()
483 struct drm_buddy_block *block; in __alloc_range_bias() local
498 block = list_first_entry_or_null(&dfs, in __alloc_range_bias()
501 if (!block) in __alloc_range_bias()
504 list_del(&block->tmp_link); in __alloc_range_bias()
506 if (drm_buddy_block_order(block) < order) in __alloc_range_bias()
509 block_start = drm_buddy_block_offset(block); in __alloc_range_bias()
510 block_end = block_start + drm_buddy_block_size(mm, block) - 1; in __alloc_range_bias()
515 if (drm_buddy_block_is_allocated(block)) in __alloc_range_bias()
527 if (!fallback && block_incompatible(block, flags)) in __alloc_range_bias()
531 order == drm_buddy_block_order(block)) { in __alloc_range_bias()
533 * Find the free block within the range. in __alloc_range_bias()
535 if (drm_buddy_block_is_free(block)) in __alloc_range_bias()
536 return block; in __alloc_range_bias()
541 if (!drm_buddy_block_is_split(block)) { in __alloc_range_bias()
542 err = split_block(mm, block); in __alloc_range_bias()
547 list_add(&block->right->tmp_link, &dfs); in __alloc_range_bias()
548 list_add(&block->left->tmp_link, &dfs); in __alloc_range_bias()
559 buddy = __get_buddy(block); in __alloc_range_bias()
561 (drm_buddy_block_is_free(block) && in __alloc_range_bias()
563 __drm_buddy_free(mm, block, false); in __alloc_range_bias()
573 struct drm_buddy_block *block; in __drm_buddy_alloc_range_bias() local
576 block = __alloc_range_bias(mm, start, end, order, in __drm_buddy_alloc_range_bias()
578 if (IS_ERR(block)) in __drm_buddy_alloc_range_bias()
582 return block; in __drm_buddy_alloc_range_bias()
589 struct drm_buddy_block *max_block = NULL, *block = NULL; in get_maxblock() local
599 block = tmp_block; in get_maxblock()
603 if (!block) in get_maxblock()
607 max_block = block; in get_maxblock()
611 if (drm_buddy_block_offset(block) > in get_maxblock()
613 max_block = block; in get_maxblock()
625 struct drm_buddy_block *block = NULL; in alloc_from_freelist() local
630 block = get_maxblock(mm, order, flags); in alloc_from_freelist()
631 if (block) in alloc_from_freelist()
632 /* Store the obtained block order */ in alloc_from_freelist()
633 tmp = drm_buddy_block_order(block); in alloc_from_freelist()
642 block = tmp_block; in alloc_from_freelist()
646 if (block) in alloc_from_freelist()
651 if (!block) { in alloc_from_freelist()
655 block = list_last_entry(&mm->free_list[tmp], in alloc_from_freelist()
658 if (block) in alloc_from_freelist()
663 if (!block) in alloc_from_freelist()
667 BUG_ON(!drm_buddy_block_is_free(block)); in alloc_from_freelist()
670 err = split_block(mm, block); in alloc_from_freelist()
674 block = block->right; in alloc_from_freelist()
677 return block; in alloc_from_freelist()
681 __drm_buddy_free(mm, block, false); in alloc_from_freelist()
691 struct drm_buddy_block *block; in __alloc_range() local
704 block = list_first_entry_or_null(dfs, in __alloc_range()
707 if (!block) in __alloc_range()
710 list_del(&block->tmp_link); in __alloc_range()
712 block_start = drm_buddy_block_offset(block); in __alloc_range()
713 block_end = block_start + drm_buddy_block_size(mm, block) - 1; in __alloc_range()
718 if (drm_buddy_block_is_allocated(block)) { in __alloc_range()
724 if (drm_buddy_block_is_free(block)) { in __alloc_range()
725 mark_allocated(block); in __alloc_range()
726 total_allocated += drm_buddy_block_size(mm, block); in __alloc_range()
727 mm->avail -= drm_buddy_block_size(mm, block); in __alloc_range()
728 if (drm_buddy_block_is_clear(block)) in __alloc_range()
729 mm->clear_avail -= drm_buddy_block_size(mm, block); in __alloc_range()
730 list_add_tail(&block->link, &allocated); in __alloc_range()
738 if (!drm_buddy_block_is_split(block)) { in __alloc_range()
739 err = split_block(mm, block); in __alloc_range()
744 list_add(&block->right->tmp_link, dfs); in __alloc_range()
745 list_add(&block->left->tmp_link, dfs); in __alloc_range()
763 buddy = __get_buddy(block); in __alloc_range()
765 (drm_buddy_block_is_free(block) && in __alloc_range()
767 __drm_buddy_free(mm, block, false); in __alloc_range()
802 struct drm_buddy_block *block; in __alloc_contig_try_harder() local
820 list_for_each_entry_reverse(block, list, link) { in __alloc_contig_try_harder()
822 rhs_offset = drm_buddy_block_offset(block); in __alloc_contig_try_harder()
833 lhs_offset = drm_buddy_block_offset(block) - lhs_size; in __alloc_contig_try_harder()
857 * MUST contain single block as input to be trimmed.
875 struct drm_buddy_block *block; in drm_buddy_block_trim() local
884 block = list_first_entry(blocks, in drm_buddy_block_trim()
888 block_start = drm_buddy_block_offset(block); in drm_buddy_block_trim()
889 block_end = block_start + drm_buddy_block_size(mm, block); in drm_buddy_block_trim()
891 if (WARN_ON(!drm_buddy_block_is_allocated(block))) in drm_buddy_block_trim()
894 if (new_size > drm_buddy_block_size(mm, block)) in drm_buddy_block_trim()
900 if (new_size == drm_buddy_block_size(mm, block)) in drm_buddy_block_trim()
917 list_del(&block->link); in drm_buddy_block_trim()
918 mark_free(mm, block); in drm_buddy_block_trim()
919 mm->avail += drm_buddy_block_size(mm, block); in drm_buddy_block_trim()
920 if (drm_buddy_block_is_clear(block)) in drm_buddy_block_trim()
921 mm->clear_avail += drm_buddy_block_size(mm, block); in drm_buddy_block_trim()
924 parent = block->parent; in drm_buddy_block_trim()
925 block->parent = NULL; in drm_buddy_block_trim()
927 list_add(&block->tmp_link, &dfs); in drm_buddy_block_trim()
930 mark_allocated(block); in drm_buddy_block_trim()
931 mm->avail -= drm_buddy_block_size(mm, block); in drm_buddy_block_trim()
932 if (drm_buddy_block_is_clear(block)) in drm_buddy_block_trim()
933 mm->clear_avail -= drm_buddy_block_size(mm, block); in drm_buddy_block_trim()
934 list_add(&block->link, blocks); in drm_buddy_block_trim()
937 block->parent = parent; in drm_buddy_block_trim()
961 * @start: start of the allowed range for this block
962 * @end: end of the allowed range for this block
969 * the tree and returns the desired block.
972 * are enforced, which picks the block from the freelist.
983 struct drm_buddy_block *block = NULL; in drm_buddy_alloc_blocks() local
1038 block = __drm_buddy_alloc_blocks(mm, start, in drm_buddy_alloc_blocks()
1042 if (!IS_ERR(block)) in drm_buddy_alloc_blocks()
1049 block = __drm_buddy_alloc_blocks(mm, start, in drm_buddy_alloc_blocks()
1053 if (!IS_ERR(block)) { in drm_buddy_alloc_blocks()
1060 * Try contiguous block allocation through in drm_buddy_alloc_blocks()
1074 mark_allocated(block); in drm_buddy_alloc_blocks()
1075 mm->avail -= drm_buddy_block_size(mm, block); in drm_buddy_alloc_blocks()
1076 if (drm_buddy_block_is_clear(block)) in drm_buddy_alloc_blocks()
1077 mm->clear_avail -= drm_buddy_block_size(mm, block); in drm_buddy_alloc_blocks()
1078 kmemleak_update_trace(block); in drm_buddy_alloc_blocks()
1079 list_add_tail(&block->link, &allocated); in drm_buddy_alloc_blocks()
1087 /* Trim the allocated block to the required size */ in drm_buddy_alloc_blocks()
1098 block = list_last_entry(&allocated, typeof(*block), link); in drm_buddy_alloc_blocks()
1099 list_move(&block->link, &temp); in drm_buddy_alloc_blocks()
1101 trim_size = drm_buddy_block_size(mm, block) - in drm_buddy_alloc_blocks()
1124 * drm_buddy_block_print - print block information
1127 * @block: DRM buddy block
1131 struct drm_buddy_block *block, in drm_buddy_block_print() argument
1134 u64 start = drm_buddy_block_offset(block); in drm_buddy_block_print()
1135 u64 size = drm_buddy_block_size(mm, block); in drm_buddy_block_print()
1155 struct drm_buddy_block *block; in drm_buddy_print() local
1158 list_for_each_entry(block, &mm->free_list[order], link) { in drm_buddy_print()
1159 BUG_ON(!drm_buddy_block_is_free(block)); in drm_buddy_print()