Lines Matching full:block
21 struct drm_buddy_block *block; in drm_block_alloc() local
25 block = kmem_cache_zalloc(slab_blocks, GFP_KERNEL); in drm_block_alloc()
26 if (!block) in drm_block_alloc()
29 block->header = offset; in drm_block_alloc()
30 block->header |= order; in drm_block_alloc()
31 block->parent = parent; in drm_block_alloc()
33 BUG_ON(block->header & DRM_BUDDY_HEADER_UNUSED); in drm_block_alloc()
34 return block; in drm_block_alloc()
38 struct drm_buddy_block *block) in drm_block_free() argument
40 kmem_cache_free(slab_blocks, block); in drm_block_free()
44 struct drm_buddy_block *block) in list_insert_sorted() argument
49 head = &mm->free_list[drm_buddy_block_order(block)]; in list_insert_sorted()
51 list_add(&block->link, head); in list_insert_sorted()
56 if (drm_buddy_block_offset(block) < drm_buddy_block_offset(node)) in list_insert_sorted()
59 __list_add(&block->link, node->link.prev, &node->link); in list_insert_sorted()
62 static void clear_reset(struct drm_buddy_block *block) in clear_reset() argument
64 block->header &= ~DRM_BUDDY_HEADER_CLEAR; in clear_reset()
67 static void mark_cleared(struct drm_buddy_block *block) in mark_cleared() argument
69 block->header |= DRM_BUDDY_HEADER_CLEAR; in mark_cleared()
72 static void mark_allocated(struct drm_buddy_block *block) in mark_allocated() argument
74 block->header &= ~DRM_BUDDY_HEADER_STATE; in mark_allocated()
75 block->header |= DRM_BUDDY_ALLOCATED; in mark_allocated()
77 list_del(&block->link); in mark_allocated()
81 struct drm_buddy_block *block) in mark_free() argument
83 block->header &= ~DRM_BUDDY_HEADER_STATE; in mark_free()
84 block->header |= DRM_BUDDY_FREE; in mark_free()
86 list_insert_sorted(mm, block); in mark_free()
89 static void mark_split(struct drm_buddy_block *block) in mark_split() argument
91 block->header &= ~DRM_BUDDY_HEADER_STATE; in mark_split()
92 block->header |= DRM_BUDDY_SPLIT; in mark_split()
94 list_del(&block->link); in mark_split()
108 __get_buddy(struct drm_buddy_block *block) in __get_buddy() argument
112 parent = block->parent; in __get_buddy()
116 if (parent->left == block) in __get_buddy()
123 struct drm_buddy_block *block, in __drm_buddy_free() argument
129 while ((parent = block->parent)) { in __drm_buddy_free()
132 buddy = __get_buddy(block); in __drm_buddy_free()
139 * Check the block and its buddy clear state and exit in __drm_buddy_free()
142 if (drm_buddy_block_is_clear(block) != in __drm_buddy_free()
146 if (drm_buddy_block_is_clear(block)) in __drm_buddy_free()
154 drm_block_free(mm, block); in __drm_buddy_free()
157 block = parent; in __drm_buddy_free()
160 order = drm_buddy_block_order(block); in __drm_buddy_free()
161 mark_free(mm, block); in __drm_buddy_free()
181 struct drm_buddy_block *block, *prev; in __force_merge() local
183 list_for_each_entry_safe_reverse(block, prev, &mm->free_list[i], link) { in __force_merge()
187 if (!block->parent) in __force_merge()
190 block_start = drm_buddy_block_offset(block); in __force_merge()
191 block_end = block_start + drm_buddy_block_size(mm, block) - 1; in __force_merge()
196 buddy = __get_buddy(block); in __force_merge()
200 WARN_ON(drm_buddy_block_is_clear(block) == in __force_merge()
204 * If the prev block is same as buddy, don't access the in __force_merge()
205 * block in the next iteration as we would free the in __force_merge()
206 * buddy block as part of the free function. in __force_merge()
211 list_del(&block->link); in __force_merge()
212 if (drm_buddy_block_is_clear(block)) in __force_merge()
213 mm->clear_avail -= drm_buddy_block_size(mm, block); in __force_merge()
215 order = __drm_buddy_free(mm, block, true); in __force_merge()
357 struct drm_buddy_block *block) in split_block() argument
359 unsigned int block_order = drm_buddy_block_order(block) - 1; in split_block()
360 u64 offset = drm_buddy_block_offset(block); in split_block()
362 BUG_ON(!drm_buddy_block_is_free(block)); in split_block()
363 BUG_ON(!drm_buddy_block_order(block)); in split_block()
365 block->left = drm_block_alloc(mm, block, block_order, offset); in split_block()
366 if (!block->left) in split_block()
369 block->right = drm_block_alloc(mm, block, block_order, in split_block()
371 if (!block->right) { in split_block()
372 drm_block_free(mm, block->left); in split_block()
376 mark_free(mm, block->left); in split_block()
377 mark_free(mm, block->right); in split_block()
379 if (drm_buddy_block_is_clear(block)) { in split_block()
380 mark_cleared(block->left); in split_block()
381 mark_cleared(block->right); in split_block()
382 clear_reset(block); in split_block()
385 mark_split(block); in split_block()
393 * @block: DRM buddy block
395 * Returns the corresponding buddy block for @block, or NULL
396 * if this is a root block and can't be merged further.
401 drm_get_buddy(struct drm_buddy_block *block) in drm_get_buddy() argument
403 return __get_buddy(block); in drm_get_buddy()
408 * drm_buddy_free_block - free a block
411 * @block: block to be freed
414 struct drm_buddy_block *block) in drm_buddy_free_block() argument
416 BUG_ON(!drm_buddy_block_is_allocated(block)); in drm_buddy_free_block()
417 mm->avail += drm_buddy_block_size(mm, block); in drm_buddy_free_block()
418 if (drm_buddy_block_is_clear(block)) in drm_buddy_free_block()
419 mm->clear_avail += drm_buddy_block_size(mm, block); in drm_buddy_free_block()
421 __drm_buddy_free(mm, block, false); in drm_buddy_free_block()
430 struct drm_buddy_block *block, *on; in __drm_buddy_free_list() local
434 list_for_each_entry_safe(block, on, objects, link) { in __drm_buddy_free_list()
436 mark_cleared(block); in __drm_buddy_free_list()
438 clear_reset(block); in __drm_buddy_free_list()
439 drm_buddy_free_block(mm, block); in __drm_buddy_free_list()
473 static bool block_incompatible(struct drm_buddy_block *block, unsigned int flags) in block_incompatible() argument
477 return needs_clear != drm_buddy_block_is_clear(block); in block_incompatible()
488 struct drm_buddy_block *block; in __alloc_range_bias() local
503 block = list_first_entry_or_null(&dfs, in __alloc_range_bias()
506 if (!block) in __alloc_range_bias()
509 list_del(&block->tmp_link); in __alloc_range_bias()
511 if (drm_buddy_block_order(block) < order) in __alloc_range_bias()
514 block_start = drm_buddy_block_offset(block); in __alloc_range_bias()
515 block_end = block_start + drm_buddy_block_size(mm, block) - 1; in __alloc_range_bias()
520 if (drm_buddy_block_is_allocated(block)) in __alloc_range_bias()
532 if (!fallback && block_incompatible(block, flags)) in __alloc_range_bias()
536 order == drm_buddy_block_order(block)) { in __alloc_range_bias()
538 * Find the free block within the range. in __alloc_range_bias()
540 if (drm_buddy_block_is_free(block)) in __alloc_range_bias()
541 return block; in __alloc_range_bias()
546 if (!drm_buddy_block_is_split(block)) { in __alloc_range_bias()
547 err = split_block(mm, block); in __alloc_range_bias()
552 list_add(&block->right->tmp_link, &dfs); in __alloc_range_bias()
553 list_add(&block->left->tmp_link, &dfs); in __alloc_range_bias()
564 buddy = __get_buddy(block); in __alloc_range_bias()
566 (drm_buddy_block_is_free(block) && in __alloc_range_bias()
568 __drm_buddy_free(mm, block, false); in __alloc_range_bias()
578 struct drm_buddy_block *block; in __drm_buddy_alloc_range_bias() local
581 block = __alloc_range_bias(mm, start, end, order, in __drm_buddy_alloc_range_bias()
583 if (IS_ERR(block)) in __drm_buddy_alloc_range_bias()
587 return block; in __drm_buddy_alloc_range_bias()
594 struct drm_buddy_block *max_block = NULL, *block = NULL; in get_maxblock() local
604 block = tmp_block; in get_maxblock()
608 if (!block) in get_maxblock()
612 max_block = block; in get_maxblock()
616 if (drm_buddy_block_offset(block) > in get_maxblock()
618 max_block = block; in get_maxblock()
630 struct drm_buddy_block *block = NULL; in alloc_from_freelist() local
635 block = get_maxblock(mm, order, flags); in alloc_from_freelist()
636 if (block) in alloc_from_freelist()
637 /* Store the obtained block order */ in alloc_from_freelist()
638 tmp = drm_buddy_block_order(block); in alloc_from_freelist()
647 block = tmp_block; in alloc_from_freelist()
651 if (block) in alloc_from_freelist()
656 if (!block) { in alloc_from_freelist()
660 block = list_last_entry(&mm->free_list[tmp], in alloc_from_freelist()
663 if (block) in alloc_from_freelist()
668 if (!block) in alloc_from_freelist()
672 BUG_ON(!drm_buddy_block_is_free(block)); in alloc_from_freelist()
675 err = split_block(mm, block); in alloc_from_freelist()
679 block = block->right; in alloc_from_freelist()
682 return block; in alloc_from_freelist()
686 __drm_buddy_free(mm, block, false); in alloc_from_freelist()
696 struct drm_buddy_block *block; in __alloc_range() local
709 block = list_first_entry_or_null(dfs, in __alloc_range()
712 if (!block) in __alloc_range()
715 list_del(&block->tmp_link); in __alloc_range()
717 block_start = drm_buddy_block_offset(block); in __alloc_range()
718 block_end = block_start + drm_buddy_block_size(mm, block) - 1; in __alloc_range()
723 if (drm_buddy_block_is_allocated(block)) { in __alloc_range()
729 if (drm_buddy_block_is_free(block)) { in __alloc_range()
730 mark_allocated(block); in __alloc_range()
731 total_allocated += drm_buddy_block_size(mm, block); in __alloc_range()
732 mm->avail -= drm_buddy_block_size(mm, block); in __alloc_range()
733 if (drm_buddy_block_is_clear(block)) in __alloc_range()
734 mm->clear_avail -= drm_buddy_block_size(mm, block); in __alloc_range()
735 list_add_tail(&block->link, &allocated); in __alloc_range()
743 if (!drm_buddy_block_is_split(block)) { in __alloc_range()
744 err = split_block(mm, block); in __alloc_range()
749 list_add(&block->right->tmp_link, dfs); in __alloc_range()
750 list_add(&block->left->tmp_link, dfs); in __alloc_range()
768 buddy = __get_buddy(block); in __alloc_range()
770 (drm_buddy_block_is_free(block) && in __alloc_range()
772 __drm_buddy_free(mm, block, false); in __alloc_range()
807 struct drm_buddy_block *block; in __alloc_contig_try_harder() local
825 list_for_each_entry_reverse(block, list, link) { in __alloc_contig_try_harder()
827 rhs_offset = drm_buddy_block_offset(block); in __alloc_contig_try_harder()
838 lhs_offset = drm_buddy_block_offset(block) - lhs_size; in __alloc_contig_try_harder()
862 * MUST contain single block as input to be trimmed.
880 struct drm_buddy_block *block; in drm_buddy_block_trim() local
889 block = list_first_entry(blocks, in drm_buddy_block_trim()
893 block_start = drm_buddy_block_offset(block); in drm_buddy_block_trim()
894 block_end = block_start + drm_buddy_block_size(mm, block); in drm_buddy_block_trim()
896 if (WARN_ON(!drm_buddy_block_is_allocated(block))) in drm_buddy_block_trim()
899 if (new_size > drm_buddy_block_size(mm, block)) in drm_buddy_block_trim()
905 if (new_size == drm_buddy_block_size(mm, block)) in drm_buddy_block_trim()
922 list_del(&block->link); in drm_buddy_block_trim()
923 mark_free(mm, block); in drm_buddy_block_trim()
924 mm->avail += drm_buddy_block_size(mm, block); in drm_buddy_block_trim()
925 if (drm_buddy_block_is_clear(block)) in drm_buddy_block_trim()
926 mm->clear_avail += drm_buddy_block_size(mm, block); in drm_buddy_block_trim()
929 parent = block->parent; in drm_buddy_block_trim()
930 block->parent = NULL; in drm_buddy_block_trim()
932 list_add(&block->tmp_link, &dfs); in drm_buddy_block_trim()
935 mark_allocated(block); in drm_buddy_block_trim()
936 mm->avail -= drm_buddy_block_size(mm, block); in drm_buddy_block_trim()
937 if (drm_buddy_block_is_clear(block)) in drm_buddy_block_trim()
938 mm->clear_avail -= drm_buddy_block_size(mm, block); in drm_buddy_block_trim()
939 list_add(&block->link, blocks); in drm_buddy_block_trim()
942 block->parent = parent; in drm_buddy_block_trim()
966 * @start: start of the allowed range for this block
967 * @end: end of the allowed range for this block
974 * the tree and returns the desired block.
977 * are enforced, which picks the block from the freelist.
988 struct drm_buddy_block *block = NULL; in drm_buddy_alloc_blocks() local
1043 block = __drm_buddy_alloc_blocks(mm, start, in drm_buddy_alloc_blocks()
1047 if (!IS_ERR(block)) in drm_buddy_alloc_blocks()
1054 block = __drm_buddy_alloc_blocks(mm, start, in drm_buddy_alloc_blocks()
1058 if (!IS_ERR(block)) { in drm_buddy_alloc_blocks()
1065 * Try contiguous block allocation through in drm_buddy_alloc_blocks()
1079 mark_allocated(block); in drm_buddy_alloc_blocks()
1080 mm->avail -= drm_buddy_block_size(mm, block); in drm_buddy_alloc_blocks()
1081 if (drm_buddy_block_is_clear(block)) in drm_buddy_alloc_blocks()
1082 mm->clear_avail -= drm_buddy_block_size(mm, block); in drm_buddy_alloc_blocks()
1083 kmemleak_update_trace(block); in drm_buddy_alloc_blocks()
1084 list_add_tail(&block->link, &allocated); in drm_buddy_alloc_blocks()
1092 /* Trim the allocated block to the required size */ in drm_buddy_alloc_blocks()
1103 block = list_last_entry(&allocated, typeof(*block), link); in drm_buddy_alloc_blocks()
1104 list_move(&block->link, &temp); in drm_buddy_alloc_blocks()
1106 trim_size = drm_buddy_block_size(mm, block) - in drm_buddy_alloc_blocks()
1129 * drm_buddy_block_print - print block information
1132 * @block: DRM buddy block
1136 struct drm_buddy_block *block, in drm_buddy_block_print() argument
1139 u64 start = drm_buddy_block_offset(block); in drm_buddy_block_print()
1140 u64 size = drm_buddy_block_size(mm, block); in drm_buddy_block_print()
1160 struct drm_buddy_block *block; in drm_buddy_print() local
1163 list_for_each_entry(block, &mm->free_list[order], link) { in drm_buddy_print()
1164 BUG_ON(!drm_buddy_block_is_free(block)); in drm_buddy_print()