1 // SPDX-License-Identifier: MIT 2 /* 3 * Copyright © 2021 Intel Corporation 4 */ 5 6 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 7 8 #include <linux/bug.h> 9 #include <linux/export.h> 10 #include <linux/kmemleak.h> 11 #include <linux/module.h> 12 #include <linux/sizes.h> 13 #include <linux/slab.h> 14 15 #include <linux/gpu_buddy.h> 16 17 /** 18 * gpu_buddy_assert - assert a condition in the buddy allocator 19 * @condition: condition expected to be true 20 * 21 * When CONFIG_KUNIT is enabled, evaluates @condition and, if false, triggers 22 * a WARN_ON() and also calls kunit_fail_current_test() so that any running 23 * kunit test is properly marked as failed. The stringified condition is 24 * included in the failure message for easy identification. 25 * 26 * When CONFIG_KUNIT is not enabled, this reduces to WARN_ON() so production 27 * builds retain the same warning semantics as before. 28 */ 29 #if IS_ENABLED(CONFIG_KUNIT) 30 #include <kunit/test-bug.h> 31 #define gpu_buddy_assert(condition) do { \ 32 if (WARN_ON(!(condition))) \ 33 kunit_fail_current_test("gpu_buddy_assert(" #condition ")"); \ 34 } while (0) 35 #else 36 #define gpu_buddy_assert(condition) WARN_ON(!(condition)) 37 #endif 38 39 static struct kmem_cache *slab_blocks; 40 static struct kmem_cache *slab_extents; 41 42 /* 43 * Dirty tracker 44 * ------------- 45 * 46 * The dirty tracker maintains an augmented interval rbtree of contiguous 47 * dirty address ranges, decoupled from the buddy free trees. 48 * Each node covers a maximal coalesced run; adjacent extents are merged 49 * on insertion so the tree always holds the smallest possible number of 50 * extents. The augmentation field @subtree_max_size lets the allocator 51 * locate the largest dirty extent in O(log E). 52 * 53 * Free trees (mm->free_tree[]) 54 * ---------------------------- 55 * 56 * Per-order augmented rbtrees of FREE buddy blocks, keyed by offset. 57 * Every node carries: 58 * - subtree_max_alignment: largest natural alignment in the subtree, 59 * used by aligned/range allocations to skip unsuitable subtrees in 60 * O(log N). 61 * - subtree_block_state: the highest clear class (DIRTY < MIXED < CLEAR) 62 * of any block in the subtree, maintained as a max augment. A value of 63 * >= MIXED means a clear-or-mixed block exists; == CLEAR means a 64 * fully-clear block exists. 65 * 66 * Block classes 67 * ------------- 68 * 69 * Each FREE block falls into one of three classes, determined in 70 * mark_free() by querying the dirty tracker for the block's range: 71 * 72 * clear -- HEADER_CLEAR set; no dirty extent overlaps the range. 73 * mixed -- HEADER_CLEAR unset; range has both dirty and clear bytes. 74 * dirty -- HEADER_CLEAR unset; range is fully dirty. 75 * 76 * Clear allocation 77 * ---------------- 78 * 79 * A clear (CLEAR_ALLOCATION) request prefers clear -> mixed -> dirty. 80 * Climbing from the requested order up to max_order, rbtree_last_clear_free_block() 81 * returns, in one O(log N) descent per order, the right-most clear-or-mixed block 82 * (fully-clear preferred over mixed) at the lowest order whose free tree contains 83 * such a block. Only if no clear-or-mixed block exists at any order >= the 84 * requested one does it fall back to a dirty block. 85 * 86 * Clear state is reported to the driver per whole block via HEADER_CLEAR, so a 87 * fully-clear block of the requested order lets the driver skip the clear pass. 88 * 89 * The effective allocation preference depends on how the driver handles 90 * freed blocks: 91 * 92 * 1) Never clear on free: 93 * No free block contains clear bytes, so clear allocations always 94 * fall back to dirty blocks. 95 * 96 * 2) Always clear on free: 97 * Freed blocks become clear while untouched blocks remain dirty. 98 * Merging clear and dirty buddies produces mixed blocks, which are 99 * reclassified when split. Over time, clear blocks become dominant, 100 * so clear allocations are typically satisfied from clear blocks, 101 * following a clear -> mixed -> dirty preference. 102 * 103 * 3) Selective clear on free: 104 * For each order examined, fully-clear blocks are preferred over 105 * mixed blocks, and mixed blocks are preferred over dirty blocks. 106 * If a clear or mixed block is found at an order, it is selected 107 * without searching higher orders. Dirty blocks are used only when 108 * no clear or mixed block exists at any eligible order. 109 */ 110 111 static u64 extent_size(struct gpu_dirty_extent *dirty_extent) 112 { 113 return dirty_extent->end - dirty_extent->start; 114 } 115 116 RB_DECLARE_CALLBACKS_MAX(static, gpu_dirty_augment_cb, 117 struct gpu_dirty_extent, rb, 118 u64, subtree_max_size, 119 extent_size) 120 121 static struct gpu_dirty_extent *extent_alloc(struct gpu_dirty_tracker *dirty_tracker) 122 { 123 return kmem_cache_alloc(slab_extents, GFP_KERNEL); 124 } 125 126 static void extent_free(struct gpu_dirty_tracker *dirty_tracker, 127 struct gpu_dirty_extent *dirty_extent) 128 { 129 kmem_cache_free(slab_extents, dirty_extent); 130 } 131 132 /* Return the rightmost extent whose start is strictly below @offset. */ 133 static struct gpu_dirty_extent * 134 prev_extent(struct gpu_dirty_tracker *dirty_tracker, u64 offset) 135 { 136 struct rb_node *rb = dirty_tracker->root.rb_node; 137 struct gpu_dirty_extent *dirty_extent = NULL; 138 139 while (rb) { 140 struct gpu_dirty_extent *tmp_extent = 141 rb_entry(rb, struct gpu_dirty_extent, rb); 142 143 if (tmp_extent->start < offset) { 144 dirty_extent = tmp_extent; 145 rb = rb->rb_right; 146 } else { 147 rb = rb->rb_left; 148 } 149 } 150 151 return dirty_extent; 152 } 153 154 /* Return the leftmost extent whose start is at or above @offset. */ 155 static struct gpu_dirty_extent * 156 next_extent(struct gpu_dirty_tracker *dirty_tracker, u64 offset) 157 { 158 struct rb_node *rb = dirty_tracker->root.rb_node; 159 struct gpu_dirty_extent *dirty_extent = NULL; 160 161 while (rb) { 162 struct gpu_dirty_extent *tmp_extent = 163 rb_entry(rb, struct gpu_dirty_extent, rb); 164 165 if (tmp_extent->start >= offset) { 166 dirty_extent = tmp_extent; 167 rb = rb->rb_left; 168 } else { 169 rb = rb->rb_right; 170 } 171 } 172 173 return dirty_extent; 174 } 175 176 static void insert_extent(struct gpu_dirty_tracker *dirty_tracker, 177 struct gpu_dirty_extent *dirty_extent) 178 { 179 struct rb_node **link = &dirty_tracker->root.rb_node; 180 struct rb_node *parent = NULL; 181 u64 size = extent_size(dirty_extent); 182 183 while (*link) { 184 struct gpu_dirty_extent *tmp_extent; 185 186 parent = *link; 187 tmp_extent = rb_entry(parent, struct gpu_dirty_extent, rb); 188 189 if (tmp_extent->subtree_max_size < size) 190 tmp_extent->subtree_max_size = size; 191 192 if (dirty_extent->start < tmp_extent->start) 193 link = &parent->rb_left; 194 else 195 link = &parent->rb_right; 196 } 197 198 dirty_extent->subtree_max_size = size; 199 rb_link_node(&dirty_extent->rb, parent, link); 200 rb_insert_augmented(&dirty_extent->rb, &dirty_tracker->root, &gpu_dirty_augment_cb); 201 } 202 203 static void remove_extent(struct gpu_dirty_tracker *dirty_tracker, 204 struct gpu_dirty_extent *dirty_extent) 205 { 206 rb_erase_augmented(&dirty_extent->rb, &dirty_tracker->root, &gpu_dirty_augment_cb); 207 RB_CLEAR_NODE(&dirty_extent->rb); 208 } 209 210 static void gpu_dirty_tracker_init(struct gpu_dirty_tracker *dirty_tracker) 211 { 212 dirty_tracker->root = RB_ROOT; 213 dirty_tracker->total_dirty = 0; 214 } 215 216 static void gpu_dirty_tracker_empty(struct gpu_dirty_tracker *dirty_tracker) 217 { 218 struct rb_node *rb; 219 220 while ((rb = rb_first(&dirty_tracker->root))) { 221 struct gpu_dirty_extent *dirty_extent = 222 rb_entry(rb, struct gpu_dirty_extent, rb); 223 224 remove_extent(dirty_tracker, dirty_extent); 225 extent_free(dirty_tracker, dirty_extent); 226 } 227 228 dirty_tracker->total_dirty = 0; 229 } 230 231 static void gpu_dirty_tracker_fini(struct gpu_dirty_tracker *dirty_tracker) 232 { 233 gpu_dirty_tracker_empty(dirty_tracker); 234 } 235 236 /* 237 * Mark the range [start, start + size] as dirty. Merge with the neighbour on 238 * each side if they are contiguous, so the tree never holds two adjacent ranges. 239 */ 240 static void gpu_dirty_tracker_mark_dirty(struct gpu_dirty_tracker *dirty_tracker, 241 u64 start, u64 size) 242 { 243 struct gpu_dirty_extent *left, *right, *dirty_extent; 244 u64 end = start + size; 245 246 gpu_buddy_assert(size); 247 248 /* Find contiguous neighbours, if any. */ 249 left = prev_extent(dirty_tracker, start); 250 if (left && left->end != start) 251 left = NULL; 252 253 right = next_extent(dirty_tracker, end); 254 if (right && right->start != end) 255 right = NULL; 256 257 if (left && right) { 258 /* Merge left + new + right into a single extent. */ 259 remove_extent(dirty_tracker, left); 260 remove_extent(dirty_tracker, right); 261 left->end = right->end; 262 extent_free(dirty_tracker, right); 263 insert_extent(dirty_tracker, left); 264 } else if (left) { 265 /* Extend left neighbour rightwards. */ 266 remove_extent(dirty_tracker, left); 267 left->end = end; 268 insert_extent(dirty_tracker, left); 269 } else if (right) { 270 /* Extend right neighbour leftwards. */ 271 remove_extent(dirty_tracker, right); 272 right->start = start; 273 insert_extent(dirty_tracker, right); 274 } else { 275 /* Standalone extent. */ 276 dirty_extent = extent_alloc(dirty_tracker); 277 if (!dirty_extent) { 278 pr_warn_once("dirty extent allocation failed, skipping tracker update\n"); 279 return; 280 } 281 dirty_extent->start = start; 282 dirty_extent->end = end; 283 insert_extent(dirty_tracker, dirty_extent); 284 } 285 286 dirty_tracker->total_dirty += size; 287 } 288 289 /* 290 * Remove the range [start, start + size] from the dirty tracker. Punch the 291 * range out of every overlapping dirty extent, splitting one extent in two if 292 * the removed range falls strictly inside it. 293 */ 294 static void gpu_dirty_tracker_remove_range(struct gpu_dirty_tracker *dirty_tracker, 295 u64 start, u64 size) 296 { 297 struct gpu_dirty_extent *dirty_extent, *next; 298 u64 end = start + size; 299 300 gpu_buddy_assert(size); 301 302 dirty_extent = prev_extent(dirty_tracker, start + 1); 303 if (!dirty_extent) 304 dirty_extent = next_extent(dirty_tracker, start); 305 306 while (dirty_extent && dirty_extent->start < end) { 307 struct rb_node *next_node = rb_next(&dirty_extent->rb); 308 u64 extent_start = dirty_extent->start; 309 u64 extent_end = dirty_extent->end; 310 311 if (next_node) 312 next = rb_entry(next_node, struct gpu_dirty_extent, rb); 313 else 314 next = NULL; 315 316 /* Skip a non-overlapping neighbour returned by prev_extent(). */ 317 if (extent_end <= start) { 318 dirty_extent = next; 319 continue; 320 } 321 322 if (extent_start < start && extent_end > end) { 323 /* 324 * Removed range lies strictly inside this dirty extent: 325 * split it into the dirty left and right halves. 326 */ 327 struct gpu_dirty_extent *right = extent_alloc(dirty_tracker); 328 329 if (!right) { 330 pr_warn_once("dirty extent allocation failed, skipping tracker update\n"); 331 dirty_extent = next; 332 continue; 333 } 334 335 remove_extent(dirty_tracker, dirty_extent); 336 337 dirty_extent->end = start; 338 right->start = end; 339 right->end = extent_end; 340 341 insert_extent(dirty_tracker, dirty_extent); 342 insert_extent(dirty_tracker, right); 343 344 dirty_tracker->total_dirty -= size; 345 } else if (extent_start >= start && extent_end <= end) { 346 /* Extent fully covered: drop it. */ 347 remove_extent(dirty_tracker, dirty_extent); 348 extent_free(dirty_tracker, dirty_extent); 349 350 dirty_tracker->total_dirty -= (extent_end - extent_start); 351 } else if (extent_start < start) { 352 /* Extent overlaps from the left: trim its right end. */ 353 remove_extent(dirty_tracker, dirty_extent); 354 dirty_extent->end = start; 355 insert_extent(dirty_tracker, dirty_extent); 356 357 dirty_tracker->total_dirty -= (extent_end - start); 358 } else { 359 /* Extent overlaps from the right: trim its left end. */ 360 remove_extent(dirty_tracker, dirty_extent); 361 dirty_extent->start = end; 362 insert_extent(dirty_tracker, dirty_extent); 363 364 dirty_tracker->total_dirty -= (end - extent_start); 365 } 366 367 dirty_extent = next; 368 } 369 } 370 371 static enum gpu_block_state 372 gpu_dirty_range_state(struct gpu_dirty_tracker *dirty_tracker, 373 u64 start, u64 size) 374 { 375 struct gpu_dirty_extent *dirty_extent; 376 u64 end = start + size; 377 378 dirty_extent = prev_extent(dirty_tracker, start + 1); 379 if (dirty_extent) { 380 if (dirty_extent->start <= start && dirty_extent->end >= end) 381 return GPU_BLOCK_DIRTY; 382 if (dirty_extent->start < end && dirty_extent->end > start) 383 return GPU_BLOCK_MIXED; 384 } 385 386 dirty_extent = next_extent(dirty_tracker, start); 387 if (dirty_extent && dirty_extent->start < end) 388 return GPU_BLOCK_MIXED; 389 390 return GPU_BLOCK_CLEAR; 391 } 392 393 static struct rb_node * 394 dirty_tracker_descend_right(struct rb_node *node, u64 min_size) 395 { 396 while (node->rb_right) { 397 struct gpu_dirty_extent *tmp_extent; 398 399 tmp_extent = rb_entry(node->rb_right, struct gpu_dirty_extent, rb); 400 401 if (tmp_extent->subtree_max_size < min_size) 402 break; 403 node = node->rb_right; 404 } 405 406 return node; 407 } 408 409 static struct gpu_dirty_extent * 410 gpu_dirty_tracker_find(struct gpu_dirty_tracker *dirty_tracker, 411 u64 min_size, u64 *aligned_start_out) 412 { 413 struct rb_node *rb = dirty_tracker->root.rb_node; 414 struct gpu_dirty_extent *root_extent; 415 struct rb_node *parent; 416 417 if (!min_size || !is_power_of_2(min_size)) 418 return NULL; 419 420 if (!rb) 421 return NULL; 422 423 root_extent = rb_entry(rb, struct gpu_dirty_extent, rb); 424 if (root_extent->subtree_max_size < min_size) 425 return NULL; 426 427 rb = dirty_tracker_descend_right(rb, min_size); 428 429 while (rb) { 430 struct gpu_dirty_extent *dirty_extent; 431 u64 aligned_start; 432 433 dirty_extent = rb_entry(rb, struct gpu_dirty_extent, rb); 434 aligned_start = ALIGN(dirty_extent->start, min_size); 435 436 /* Check if a min_size block fits after the alignment skip. */ 437 if (aligned_start <= dirty_extent->end && 438 dirty_extent->end - aligned_start >= min_size) { 439 *aligned_start_out = aligned_start; 440 return dirty_extent; 441 } 442 443 if (rb->rb_left) { 444 struct gpu_dirty_extent *tmp_extent; 445 446 tmp_extent = rb_entry(rb->rb_left, struct gpu_dirty_extent, rb); 447 if (tmp_extent->subtree_max_size >= min_size) { 448 rb = dirty_tracker_descend_right(rb->rb_left, min_size); 449 continue; 450 } 451 } 452 453 /* Walk up until we exit a node via its right child. */ 454 parent = rb_parent(rb); 455 while (parent && parent->rb_right != rb) { 456 rb = parent; 457 parent = rb_parent(rb); 458 } 459 rb = parent; 460 } 461 462 return NULL; 463 } 464 465 static unsigned int 466 gpu_buddy_block_state(struct gpu_buddy_block *block) 467 { 468 return block->header & GPU_BUDDY_HEADER_STATE; 469 } 470 471 static bool 472 gpu_buddy_block_is_allocated(struct gpu_buddy_block *block) 473 { 474 return gpu_buddy_block_state(block) == GPU_BUDDY_ALLOCATED; 475 } 476 477 static bool 478 gpu_buddy_block_is_split(struct gpu_buddy_block *block) 479 { 480 return gpu_buddy_block_state(block) == GPU_BUDDY_SPLIT; 481 } 482 483 static unsigned int gpu_buddy_block_offset_alignment(struct gpu_buddy_block *block) 484 { 485 u64 offset = gpu_buddy_block_offset(block); 486 487 if (!offset) 488 /* 489 * __ffs64(0) is undefined; offset 0 is maximally aligned, so return 490 * a value greater than any possible alignment. 491 */ 492 return 64 + 1; 493 494 return __ffs64(offset); 495 } 496 497 static inline enum gpu_block_state 498 gpu_block_cached_state(struct gpu_buddy_block *block) 499 { 500 if (gpu_buddy_block_is_clear(block)) 501 return GPU_BLOCK_CLEAR; 502 if (block->has_clear) 503 return GPU_BLOCK_MIXED; 504 return GPU_BLOCK_DIRTY; 505 } 506 507 static inline void gpu_buddy_augment_compute(struct gpu_buddy_block *block) 508 { 509 enum gpu_block_state block_state; 510 struct gpu_buddy_block *right; 511 struct gpu_buddy_block *left; 512 unsigned int max_align; 513 514 max_align = gpu_buddy_block_offset_alignment(block); 515 block_state = gpu_block_cached_state(block); 516 517 left = rb_entry_safe(block->rb.rb_left, struct gpu_buddy_block, rb); 518 if (left) { 519 if (left->subtree_max_alignment > max_align) 520 max_align = left->subtree_max_alignment; 521 522 block_state = max(block_state, left->subtree_block_state); 523 } 524 525 right = rb_entry_safe(block->rb.rb_right, struct gpu_buddy_block, rb); 526 if (right) { 527 if (right->subtree_max_alignment > max_align) 528 max_align = right->subtree_max_alignment; 529 530 block_state = max(block_state, right->subtree_block_state); 531 } 532 533 block->subtree_max_alignment = max_align; 534 block->subtree_block_state = block_state; 535 } 536 537 static void gpu_buddy_augment_propagate(struct rb_node *rb, struct rb_node *stop) 538 { 539 while (rb != stop) { 540 struct gpu_buddy_block *block; 541 unsigned int old_align; 542 enum gpu_block_state old_block_state; 543 544 block = rb_entry(rb, struct gpu_buddy_block, rb); 545 old_align = block->subtree_max_alignment; 546 old_block_state = block->subtree_block_state; 547 548 gpu_buddy_augment_compute(block); 549 if (block->subtree_max_alignment == old_align && 550 block->subtree_block_state == old_block_state) 551 break; 552 553 rb = rb_parent(&block->rb); 554 } 555 } 556 557 static void gpu_buddy_augment_copy(struct rb_node *rb_old, struct rb_node *rb_new) 558 { 559 struct gpu_buddy_block *old; 560 struct gpu_buddy_block *new; 561 562 old = rb_entry(rb_old, struct gpu_buddy_block, rb); 563 new = rb_entry(rb_new, struct gpu_buddy_block, rb); 564 565 new->subtree_max_alignment = old->subtree_max_alignment; 566 new->subtree_block_state = old->subtree_block_state; 567 } 568 569 static void gpu_buddy_augment_rotate(struct rb_node *rb_old, struct rb_node *rb_new) 570 { 571 struct gpu_buddy_block *old; 572 struct gpu_buddy_block *new; 573 574 old = rb_entry(rb_old, struct gpu_buddy_block, rb); 575 new = rb_entry(rb_new, struct gpu_buddy_block, rb); 576 577 new->subtree_max_alignment = old->subtree_max_alignment; 578 new->subtree_block_state = old->subtree_block_state; 579 580 gpu_buddy_augment_compute(old); 581 } 582 583 static const struct rb_augment_callbacks gpu_buddy_augment_cb = { 584 .propagate = gpu_buddy_augment_propagate, 585 .copy = gpu_buddy_augment_copy, 586 .rotate = gpu_buddy_augment_rotate, 587 }; 588 589 static struct gpu_buddy_block *gpu_block_alloc(struct gpu_buddy *mm, 590 struct gpu_buddy_block *parent, 591 unsigned int order, 592 u64 offset) 593 { 594 struct gpu_buddy_block *block; 595 596 BUG_ON(order > GPU_BUDDY_MAX_ORDER); 597 598 block = kmem_cache_zalloc(slab_blocks, GFP_KERNEL); 599 if (!block) 600 return NULL; 601 602 block->header = offset; 603 block->header |= order; 604 block->parent = parent; 605 606 RB_CLEAR_NODE(&block->rb); 607 608 BUG_ON(block->header & GPU_BUDDY_HEADER_UNUSED); 609 return block; 610 } 611 612 static void gpu_block_free(struct gpu_buddy *mm, 613 struct gpu_buddy_block *block) 614 { 615 kmem_cache_free(slab_blocks, block); 616 } 617 618 static struct gpu_buddy_block * 619 rbtree_get_free_block(const struct rb_node *node) 620 { 621 return node ? rb_entry(node, struct gpu_buddy_block, rb) : NULL; 622 } 623 624 static struct gpu_buddy_block * 625 rbtree_last_free_block(struct rb_root *root) 626 { 627 return rbtree_get_free_block(rb_last(root)); 628 } 629 630 static struct gpu_buddy_block * 631 rbtree_last_clear_free_block(struct rb_root *root, 632 enum gpu_block_state min_block_state) 633 { 634 struct rb_node *node = root->rb_node; 635 struct gpu_buddy_block *block = NULL; 636 struct gpu_buddy_block *root_block; 637 enum gpu_block_state target_state; 638 639 root_block = rbtree_get_free_block(node); 640 if (!root_block || root_block->subtree_block_state < min_block_state) 641 return NULL; 642 643 target_state = root_block->subtree_block_state; 644 645 while (node) { 646 struct gpu_buddy_block *right_block; 647 struct gpu_buddy_block *node_block; 648 649 node_block = rbtree_get_free_block(node); 650 right_block = rbtree_get_free_block(node->rb_right); 651 652 if (right_block && right_block->subtree_block_state >= target_state) { 653 node = node->rb_right; 654 continue; 655 } 656 657 if (gpu_block_cached_state(node_block) == target_state) { 658 block = node_block; 659 break; 660 } 661 662 node = node->rb_left; 663 } 664 665 return block; 666 } 667 668 static void rbtree_insert(struct gpu_buddy *mm, 669 struct gpu_buddy_block *block) 670 { 671 struct rb_node **link, *parent = NULL; 672 enum gpu_block_state block_state; 673 struct gpu_buddy_block *node; 674 unsigned int block_alignment; 675 struct rb_root *root; 676 unsigned int order; 677 678 order = gpu_buddy_block_order(block); 679 block_alignment = gpu_buddy_block_offset_alignment(block); 680 block_state = gpu_block_cached_state(block); 681 682 root = &mm->free_tree[order]; 683 link = &root->rb_node; 684 685 while (*link) { 686 parent = *link; 687 node = rbtree_get_free_block(parent); 688 /* 689 * Manual augmentation update during insertion traversal. Required 690 * because rb_insert_augmented() only calls rotate callback during 691 * rotations. This ensures all ancestors on the insertion path have 692 * correct subtree_max_alignment / subtree_block_state values. 693 */ 694 if (node->subtree_max_alignment < block_alignment) 695 node->subtree_max_alignment = block_alignment; 696 if (node->subtree_block_state < block_state) 697 node->subtree_block_state = block_state; 698 699 if (gpu_buddy_block_offset(block) < gpu_buddy_block_offset(node)) 700 link = &parent->rb_left; 701 else 702 link = &parent->rb_right; 703 } 704 705 block->subtree_max_alignment = block_alignment; 706 block->subtree_block_state = block_state; 707 rb_link_node(&block->rb, parent, link); 708 rb_insert_augmented(&block->rb, root, &gpu_buddy_augment_cb); 709 } 710 711 static void rbtree_remove(struct gpu_buddy *mm, 712 struct gpu_buddy_block *block) 713 { 714 unsigned int order = gpu_buddy_block_order(block); 715 716 rb_erase_augmented(&block->rb, &mm->free_tree[order], &gpu_buddy_augment_cb); 717 RB_CLEAR_NODE(&block->rb); 718 } 719 720 static void mark_allocated(struct gpu_buddy *mm, 721 struct gpu_buddy_block *block) 722 { 723 block->header &= ~GPU_BUDDY_HEADER_STATE; 724 block->header |= GPU_BUDDY_ALLOCATED; 725 726 block->has_clear = false; 727 728 mm->free_scoreboard[gpu_buddy_block_order(block)]--; 729 mm->used_scoreboard[gpu_buddy_block_order(block)]++; 730 731 rbtree_remove(mm, block); 732 } 733 734 static void __mark_free(struct gpu_buddy *mm, 735 struct gpu_buddy_block *block, 736 enum gpu_block_state block_state) 737 { 738 if (gpu_buddy_block_is_allocated(block)) 739 mm->used_scoreboard[gpu_buddy_block_order(block)]--; 740 741 block->header &= ~GPU_BUDDY_HEADER_STATE; 742 block->header |= GPU_BUDDY_FREE; 743 744 block->header &= ~GPU_BUDDY_HEADER_CLEAR; 745 746 block->has_clear = (block_state != GPU_BLOCK_DIRTY); 747 if (block_state == GPU_BLOCK_CLEAR) 748 block->header |= GPU_BUDDY_HEADER_CLEAR; 749 750 mm->free_scoreboard[gpu_buddy_block_order(block)]++; 751 752 rbtree_insert(mm, block); 753 } 754 755 static void mark_free(struct gpu_buddy *mm, 756 struct gpu_buddy_block *block) 757 { 758 enum gpu_block_state block_state; 759 760 block_state = gpu_dirty_range_state(&mm->dirty, 761 gpu_buddy_block_offset(block), 762 gpu_buddy_block_size(mm, block)); 763 __mark_free(mm, block, block_state); 764 } 765 766 static void mark_split(struct gpu_buddy *mm, 767 struct gpu_buddy_block *block) 768 { 769 block->header &= ~GPU_BUDDY_HEADER_STATE; 770 block->header |= GPU_BUDDY_SPLIT; 771 772 mm->free_scoreboard[gpu_buddy_block_order(block)]--; 773 774 rbtree_remove(mm, block); 775 } 776 777 static inline bool overlaps(u64 s1, u64 e1, u64 s2, u64 e2) 778 { 779 return s1 <= e2 && e1 >= s2; 780 } 781 782 static inline bool contains(u64 s1, u64 e1, u64 s2, u64 e2) 783 { 784 return s1 <= s2 && e1 >= e2; 785 } 786 787 static struct gpu_buddy_block * 788 __get_buddy(struct gpu_buddy_block *block) 789 { 790 struct gpu_buddy_block *parent; 791 792 parent = block->parent; 793 if (!parent) 794 return NULL; 795 796 if (parent->left == block) 797 return parent->right; 798 799 return parent->left; 800 } 801 802 static unsigned int __gpu_buddy_free(struct gpu_buddy *mm, 803 struct gpu_buddy_block *block) 804 { 805 enum gpu_block_state block_state; 806 struct gpu_buddy_block *parent; 807 unsigned int order; 808 809 block_state = gpu_block_cached_state(block); 810 811 while ((parent = block->parent)) { 812 struct gpu_buddy_block *buddy = __get_buddy(block); 813 814 if (!gpu_buddy_block_is_free(buddy)) 815 break; 816 817 if (block_state != GPU_BLOCK_MIXED) { 818 enum gpu_block_state buddy_state; 819 820 buddy_state = gpu_block_cached_state(buddy); 821 822 if (buddy_state != block_state) 823 block_state = GPU_BLOCK_MIXED; 824 } 825 826 rbtree_remove(mm, buddy); 827 mm->free_scoreboard[gpu_buddy_block_order(buddy)]--; 828 829 if (gpu_buddy_block_is_allocated(block)) 830 mm->used_scoreboard[gpu_buddy_block_order(block)]--; 831 832 gpu_block_free(mm, block); 833 gpu_block_free(mm, buddy); 834 835 block = parent; 836 } 837 838 order = gpu_buddy_block_order(block); 839 __mark_free(mm, block, block_state); 840 841 return order; 842 } 843 844 /** 845 * gpu_buddy_init - init memory manager 846 * 847 * @mm: GPU buddy manager to initialize 848 * @size: size in bytes to manage 849 * @chunk_size: minimum page size in bytes for our allocations 850 * 851 * Initializes the memory manager and its resources. 852 * 853 * Returns: 854 * 0 on success, error code on failure. 855 */ 856 int gpu_buddy_init(struct gpu_buddy *mm, u64 size, u64 chunk_size) 857 { 858 unsigned int root_count = 0; 859 u64 offset = 0; 860 861 if (size < chunk_size) 862 return -EINVAL; 863 864 if (chunk_size < SZ_4K) 865 return -EINVAL; 866 867 if (!is_power_of_2(chunk_size)) 868 return -EINVAL; 869 870 size = round_down(size, chunk_size); 871 872 mm->size = size; 873 mm->avail = size; 874 mm->chunk_size = chunk_size; 875 mm->max_order = ilog2(size) - ilog2(chunk_size); 876 877 BUG_ON(mm->max_order > GPU_BUDDY_MAX_ORDER); 878 879 mm->free_scoreboard = kcalloc(mm->max_order + 1, 880 sizeof(*mm->free_scoreboard), 881 GFP_KERNEL); 882 if (!mm->free_scoreboard) 883 return -ENOMEM; 884 885 mm->used_scoreboard = kcalloc(mm->max_order + 1, 886 sizeof(*mm->used_scoreboard), 887 GFP_KERNEL); 888 if (!mm->used_scoreboard) 889 goto out_free_free_scoreboard; 890 891 mm->free_tree = kcalloc(mm->max_order + 1, 892 sizeof(struct rb_root), 893 GFP_KERNEL); 894 if (!mm->free_tree) 895 goto out_free_used_scoreboard; 896 897 gpu_dirty_tracker_init(&mm->dirty); 898 899 mm->n_roots = hweight64(size); 900 901 mm->roots = kmalloc_objs(struct gpu_buddy_block *, mm->n_roots); 902 if (!mm->roots) 903 goto out_free_tree; 904 905 /* 906 * Split into power-of-two blocks, in case we are given a size that is 907 * not itself a power-of-two. 908 */ 909 do { 910 struct gpu_buddy_block *root; 911 unsigned int order; 912 u64 root_size; 913 914 order = ilog2(size) - ilog2(chunk_size); 915 root_size = chunk_size << order; 916 917 root = gpu_block_alloc(mm, NULL, order, offset); 918 if (!root) 919 goto out_free_roots; 920 921 gpu_dirty_tracker_mark_dirty(&mm->dirty, offset, root_size); 922 __mark_free(mm, root, GPU_BLOCK_DIRTY); 923 924 BUG_ON(root_count > mm->max_order); 925 BUG_ON(gpu_buddy_block_size(mm, root) < chunk_size); 926 927 mm->roots[root_count] = root; 928 929 offset += root_size; 930 size -= root_size; 931 root_count++; 932 } while (size); 933 934 #ifdef CONFIG_LOCKDEP 935 mm->lock_dep_map = NULL; 936 #endif 937 return 0; 938 939 out_free_roots: 940 while (root_count--) 941 gpu_block_free(mm, mm->roots[root_count]); 942 kfree(mm->roots); 943 out_free_tree: 944 gpu_dirty_tracker_fini(&mm->dirty); 945 kfree(mm->free_tree); 946 out_free_used_scoreboard: 947 kfree(mm->used_scoreboard); 948 out_free_free_scoreboard: 949 kfree(mm->free_scoreboard); 950 return -ENOMEM; 951 } 952 EXPORT_SYMBOL(gpu_buddy_init); 953 954 /** 955 * gpu_buddy_fini - tear down the memory manager 956 * 957 * @mm: GPU buddy manager to free 958 * 959 * Cleanup memory manager resources and the freetree 960 */ 961 void gpu_buddy_fini(struct gpu_buddy *mm) 962 { 963 u64 root_size, size; 964 unsigned int order; 965 int i; 966 967 size = mm->size; 968 969 for (i = 0; i < mm->n_roots; ++i) { 970 order = ilog2(size) - ilog2(mm->chunk_size); 971 root_size = mm->chunk_size << order; 972 973 gpu_buddy_assert(gpu_buddy_block_is_free(mm->roots[i])); 974 gpu_block_free(mm, mm->roots[i]); 975 size -= root_size; 976 } 977 978 gpu_buddy_assert(mm->avail == mm->size); 979 980 for (i = 0; i <= mm->max_order; ++i) 981 gpu_buddy_assert(!mm->used_scoreboard[i]); 982 983 gpu_dirty_tracker_fini(&mm->dirty); 984 kfree(mm->free_tree); 985 kfree(mm->roots); 986 kfree(mm->free_scoreboard); 987 kfree(mm->used_scoreboard); 988 } 989 EXPORT_SYMBOL(gpu_buddy_fini); 990 991 static int split_block(struct gpu_buddy *mm, 992 struct gpu_buddy_block *block) 993 { 994 unsigned int block_order = gpu_buddy_block_order(block) - 1; 995 u64 offset = gpu_buddy_block_offset(block); 996 enum gpu_block_state parent_state; 997 998 BUG_ON(!gpu_buddy_block_is_free(block)); 999 BUG_ON(!gpu_buddy_block_order(block)); 1000 1001 block->left = gpu_block_alloc(mm, block, block_order, offset); 1002 if (!block->left) 1003 return -ENOMEM; 1004 1005 block->right = gpu_block_alloc(mm, block, block_order, 1006 offset + (mm->chunk_size << block_order)); 1007 if (!block->right) { 1008 gpu_block_free(mm, block->left); 1009 return -ENOMEM; 1010 } 1011 1012 parent_state = gpu_block_cached_state(block); 1013 1014 mark_split(mm, block); 1015 1016 if (parent_state == GPU_BLOCK_MIXED) { 1017 mark_free(mm, block->left); 1018 mark_free(mm, block->right); 1019 } else { 1020 __mark_free(mm, block->left, parent_state); 1021 __mark_free(mm, block->right, parent_state); 1022 } 1023 1024 return 0; 1025 } 1026 1027 /** 1028 * gpu_buddy_reset_clear - reset blocks clear state 1029 * 1030 * @mm: GPU buddy manager 1031 * @is_clear: blocks clear state 1032 * 1033 * Reset the clear state based on @is_clear value for each block 1034 * in the freetree. 1035 */ 1036 void gpu_buddy_reset_clear(struct gpu_buddy *mm, bool is_clear) 1037 { 1038 unsigned int i; 1039 1040 gpu_buddy_driver_lock_held(mm); 1041 1042 gpu_dirty_tracker_empty(&mm->dirty); 1043 1044 for (i = 0; i <= mm->max_order; ++i) { 1045 struct gpu_buddy_block *block, *tmp; 1046 1047 rbtree_postorder_for_each_entry_safe(block, tmp, 1048 &mm->free_tree[i], rb) { 1049 if (is_clear) { 1050 if (!gpu_buddy_block_is_clear(block)) 1051 block->header |= GPU_BUDDY_HEADER_CLEAR; 1052 block->has_clear = true; 1053 } else { 1054 block->header &= ~GPU_BUDDY_HEADER_CLEAR; 1055 block->has_clear = false; 1056 gpu_dirty_tracker_mark_dirty(&mm->dirty, 1057 gpu_buddy_block_offset(block), 1058 gpu_buddy_block_size(mm, block)); 1059 } 1060 1061 gpu_buddy_augment_compute(block); 1062 } 1063 } 1064 } 1065 EXPORT_SYMBOL(gpu_buddy_reset_clear); 1066 1067 static void __gpu_buddy_free_block_internal(struct gpu_buddy *mm, 1068 struct gpu_buddy_block *block) 1069 { 1070 u64 size = gpu_buddy_block_size(mm, block); 1071 1072 gpu_buddy_driver_lock_held(mm); 1073 BUG_ON(!gpu_buddy_block_is_allocated(block)); 1074 1075 mm->avail += size; 1076 __gpu_buddy_free(mm, block); 1077 } 1078 1079 /** 1080 * gpu_buddy_free_block - free a block 1081 * 1082 * @mm: GPU buddy manager 1083 * @block: block to be freed 1084 */ 1085 void gpu_buddy_free_block(struct gpu_buddy *mm, 1086 struct gpu_buddy_block *block) 1087 { 1088 if (!gpu_buddy_block_is_clear(block)) 1089 gpu_dirty_tracker_mark_dirty(&mm->dirty, 1090 gpu_buddy_block_offset(block), 1091 gpu_buddy_block_size(mm, block)); 1092 1093 __gpu_buddy_free_block_internal(mm, block); 1094 } 1095 EXPORT_SYMBOL(gpu_buddy_free_block); 1096 1097 /** 1098 * gpu_buddy_allocated_addr_to_block - given relative address find the allocated block 1099 * 1100 * @mm: GPU buddy manager 1101 * @addr: Relative address 1102 * 1103 * Returns: 1104 * gpu_buddy_block on success, NULL or error code on failure 1105 */ 1106 struct gpu_buddy_block *gpu_buddy_allocated_addr_to_block(struct gpu_buddy *mm, u64 addr) 1107 { 1108 struct gpu_buddy_block *block; 1109 LIST_HEAD(dfs); 1110 u64 end; 1111 int i; 1112 1113 gpu_buddy_driver_lock_held(mm); 1114 1115 end = addr + mm->chunk_size - 1; 1116 for (i = 0; i < mm->n_roots; ++i) 1117 list_add_tail(&mm->roots[i]->tmp_link, &dfs); 1118 1119 do { 1120 u64 block_start; 1121 u64 block_end; 1122 1123 block = list_first_entry_or_null(&dfs, 1124 struct gpu_buddy_block, 1125 tmp_link); 1126 if (!block) 1127 break; 1128 1129 list_del(&block->tmp_link); 1130 1131 block_start = gpu_buddy_block_offset(block); 1132 block_end = block_start + gpu_buddy_block_size(mm, block) - 1; 1133 1134 if (!overlaps(addr, end, block_start, block_end)) 1135 continue; 1136 1137 if (gpu_buddy_block_is_allocated(block)) 1138 return block; 1139 else if (gpu_buddy_block_is_free(block)) 1140 return NULL; 1141 1142 list_add(&block->right->tmp_link, &dfs); 1143 list_add(&block->left->tmp_link, &dfs); 1144 } while (1); 1145 1146 return ERR_PTR(-ENXIO); 1147 } 1148 EXPORT_SYMBOL(gpu_buddy_allocated_addr_to_block); 1149 1150 static void __gpu_buddy_free_list(struct gpu_buddy *mm, 1151 struct list_head *objects, 1152 bool mark_clear, 1153 bool mark_dirty) 1154 { 1155 struct gpu_buddy_block *block, *on; 1156 u64 dirty_start = 0, dirty_size = 0; 1157 1158 gpu_buddy_assert(!(mark_dirty && mark_clear)); 1159 1160 list_for_each_entry_safe(block, on, objects, link) { 1161 u64 offset = gpu_buddy_block_offset(block); 1162 u64 size = gpu_buddy_block_size(mm, block); 1163 1164 if (mark_clear) 1165 block->header |= GPU_BUDDY_HEADER_CLEAR; 1166 else if (mark_dirty) 1167 block->header &= ~GPU_BUDDY_HEADER_CLEAR; 1168 1169 /* 1170 * Coalesce contiguous dirty blocks into one extent update so 1171 * a multi-block contiguous free costs a single mark_dirty(). 1172 * Flush the pending extent and start over on a gap. 1173 */ 1174 if (!gpu_buddy_block_is_clear(block)) { 1175 if (dirty_size && 1176 (dirty_start + dirty_size == offset || 1177 offset + size == dirty_start)) { 1178 dirty_start = min(dirty_start, offset); 1179 dirty_size += size; 1180 } else { 1181 if (dirty_size) 1182 gpu_dirty_tracker_mark_dirty(&mm->dirty, 1183 dirty_start, 1184 dirty_size); 1185 dirty_start = offset; 1186 dirty_size = size; 1187 } 1188 } 1189 1190 __gpu_buddy_free_block_internal(mm, block); 1191 cond_resched(); 1192 } 1193 1194 if (dirty_size) 1195 gpu_dirty_tracker_mark_dirty(&mm->dirty, dirty_start, dirty_size); 1196 1197 INIT_LIST_HEAD(objects); 1198 } 1199 1200 static void gpu_buddy_free_list_internal(struct gpu_buddy *mm, 1201 struct list_head *objects) 1202 { 1203 /* 1204 * Don't touch the clear/dirty bit, since allocation is still internal 1205 * at this point. For example we might have just failed part of the 1206 * allocation. 1207 */ 1208 __gpu_buddy_free_list(mm, objects, false, false); 1209 } 1210 1211 /** 1212 * gpu_buddy_free_list - free blocks 1213 * 1214 * @mm: GPU buddy manager 1215 * @objects: input list head to free blocks 1216 * @flags: optional flags like GPU_BUDDY_CLEARED 1217 */ 1218 void gpu_buddy_free_list(struct gpu_buddy *mm, 1219 struct list_head *objects, 1220 unsigned int flags) 1221 { 1222 bool mark_clear = flags & GPU_BUDDY_CLEARED; 1223 1224 gpu_buddy_driver_lock_held(mm); 1225 __gpu_buddy_free_list(mm, objects, mark_clear, !mark_clear); 1226 } 1227 EXPORT_SYMBOL(gpu_buddy_free_list); 1228 1229 static void __gpu_buddy_undo_splits(struct gpu_buddy *mm, 1230 struct gpu_buddy_block *block) 1231 { 1232 struct gpu_buddy_block *buddy = __get_buddy(block); 1233 1234 if (buddy && 1235 (gpu_buddy_block_is_free(block) && 1236 gpu_buddy_block_is_free(buddy))) { 1237 rbtree_remove(mm, block); 1238 mm->free_scoreboard[gpu_buddy_block_order(block)]--; 1239 __gpu_buddy_free(mm, block); 1240 } 1241 } 1242 1243 static struct gpu_buddy_block * 1244 __alloc_range_bias(struct gpu_buddy *mm, 1245 u64 start, u64 end, 1246 unsigned int order, 1247 unsigned long flags) 1248 { 1249 u64 req_size = mm->chunk_size << order; 1250 struct gpu_buddy_block *block; 1251 LIST_HEAD(dfs); 1252 int err; 1253 int i; 1254 1255 end = end - 1; 1256 1257 /* 1258 * This range-constrained search hands back the highest/right-most 1259 * address that satisfies the request: the roots are seeded high-to-low 1260 * and the right (higher-address) child is descended first, making 1261 * top-down the default placement here. A non-top-down clear request is 1262 * the only exception, where the descent is biased towards clear or 1263 * clear-containing subtrees to satisfy the clear preference. 1264 */ 1265 for (i = mm->n_roots - 1; i >= 0; --i) 1266 list_add_tail(&mm->roots[i]->tmp_link, &dfs); 1267 1268 do { 1269 u64 block_start; 1270 u64 block_end; 1271 1272 block = list_first_entry_or_null(&dfs, 1273 struct gpu_buddy_block, 1274 tmp_link); 1275 if (!block) 1276 break; 1277 1278 list_del(&block->tmp_link); 1279 1280 if (gpu_buddy_block_order(block) < order) 1281 continue; 1282 1283 block_start = gpu_buddy_block_offset(block); 1284 block_end = block_start + gpu_buddy_block_size(mm, block) - 1; 1285 1286 if (!overlaps(start, end, block_start, block_end)) 1287 continue; 1288 1289 if (gpu_buddy_block_is_allocated(block)) 1290 continue; 1291 1292 if (block_start < start || block_end > end) { 1293 u64 adjusted_start = max(block_start, start); 1294 u64 adjusted_end = min(block_end, end); 1295 1296 if (round_down(adjusted_end + 1, req_size) <= 1297 round_up(adjusted_start, req_size)) 1298 continue; 1299 } 1300 1301 if (contains(start, end, block_start, block_end) && 1302 order == gpu_buddy_block_order(block)) { 1303 /* 1304 * Find the free block within the range. 1305 */ 1306 if (gpu_buddy_block_is_free(block)) 1307 return block; 1308 1309 continue; 1310 } 1311 1312 if (!gpu_buddy_block_is_split(block)) { 1313 err = split_block(mm, block); 1314 if (unlikely(err)) 1315 goto err_undo; 1316 } 1317 1318 /* 1319 * Top-down is a strict address-placement policy, so when it is 1320 * requested we ignore clear steering and simply descend the 1321 * right (higher-address) child first. Only a non-top-down clear 1322 * request biases the descent towards clear/has_clear subtrees. 1323 */ 1324 if ((flags & GPU_BUDDY_CLEAR_ALLOCATION) && 1325 !(flags & GPU_BUDDY_TOPDOWN_ALLOCATION)) { 1326 struct gpu_buddy_block *prefer; 1327 1328 if (gpu_buddy_block_is_clear(block->right)) 1329 prefer = block->right; 1330 else if (gpu_buddy_block_is_clear(block->left)) 1331 prefer = block->left; 1332 else if (block->right->has_clear) 1333 prefer = block->right; 1334 else if (block->left->has_clear) 1335 prefer = block->left; 1336 else 1337 prefer = block->right; 1338 1339 if (prefer == block->right) { 1340 list_add(&block->left->tmp_link, &dfs); 1341 list_add(&block->right->tmp_link, &dfs); 1342 } else { 1343 list_add(&block->right->tmp_link, &dfs); 1344 list_add(&block->left->tmp_link, &dfs); 1345 } 1346 } else { 1347 list_add(&block->left->tmp_link, &dfs); 1348 list_add(&block->right->tmp_link, &dfs); 1349 } 1350 } while (1); 1351 1352 return ERR_PTR(-ENOSPC); 1353 1354 err_undo: 1355 /* 1356 * We really don't want to leave around a bunch of split blocks, since 1357 * bigger is better, so make sure we merge everything back before we 1358 * free the allocated blocks. 1359 */ 1360 __gpu_buddy_undo_splits(mm, block); 1361 return ERR_PTR(err); 1362 } 1363 1364 /* Return the highest-address free block of at least @order. */ 1365 static struct gpu_buddy_block * 1366 get_maxblock(struct gpu_buddy *mm, 1367 unsigned int order) 1368 { 1369 struct gpu_buddy_block *max_block; 1370 struct gpu_buddy_block *block; 1371 unsigned int i; 1372 1373 /* 1374 * Top-down allocation is a strict address-placement policy: the block 1375 * is chosen purely by offset, regardless of its clear/dirty state. 1376 * Clear state is re-derived from the dirty tracker once the allocation 1377 * completes, and the driver is responsible for issuing the clear pass 1378 * if a clear region is required. 1379 */ 1380 max_block = NULL; 1381 1382 for (i = order; i <= mm->max_order; ++i) { 1383 block = rbtree_last_free_block(&mm->free_tree[i]); 1384 if (!block) 1385 continue; 1386 1387 if (!max_block || 1388 gpu_buddy_block_offset(block) > gpu_buddy_block_offset(max_block)) 1389 max_block = block; 1390 } 1391 1392 return max_block; 1393 } 1394 1395 static struct gpu_buddy_block * 1396 alloc_from_freetree(struct gpu_buddy *mm, 1397 unsigned int order, 1398 unsigned long flags) 1399 { 1400 struct gpu_buddy_block *block = NULL; 1401 unsigned int tmp; 1402 int err; 1403 1404 if (flags & GPU_BUDDY_TOPDOWN_ALLOCATION) { 1405 block = get_maxblock(mm, order); 1406 if (block) 1407 tmp = gpu_buddy_block_order(block); 1408 } else { 1409 if (flags & GPU_BUDDY_CLEAR_ALLOCATION) { 1410 for (tmp = order; tmp <= mm->max_order; ++tmp) { 1411 block = rbtree_last_clear_free_block(&mm->free_tree[tmp], 1412 GPU_BLOCK_MIXED); 1413 if (block) 1414 break; 1415 } 1416 } 1417 if (!block) { 1418 for (tmp = order; tmp <= mm->max_order; ++tmp) { 1419 block = rbtree_last_free_block(&mm->free_tree[tmp]); 1420 if (block) 1421 break; 1422 } 1423 } 1424 } 1425 1426 if (!block) 1427 return ERR_PTR(-ENOSPC); 1428 1429 BUG_ON(!gpu_buddy_block_is_free(block)); 1430 1431 while (tmp != order) { 1432 err = split_block(mm, block); 1433 if (unlikely(err)) 1434 goto err_undo; 1435 1436 if ((flags & GPU_BUDDY_CLEAR_ALLOCATION) && 1437 !(flags & GPU_BUDDY_TOPDOWN_ALLOCATION)) { 1438 bool right_clear, left_clear; 1439 1440 right_clear = gpu_buddy_block_is_clear(block->right); 1441 left_clear = gpu_buddy_block_is_clear(block->left); 1442 1443 if (right_clear) 1444 block = block->right; 1445 else if (left_clear) 1446 block = block->left; 1447 else if (block->right->has_clear) 1448 block = block->right; 1449 else if (block->left->has_clear) 1450 block = block->left; 1451 else 1452 block = block->right; 1453 } else { 1454 block = block->right; 1455 } 1456 tmp--; 1457 } 1458 return block; 1459 1460 err_undo: 1461 __gpu_buddy_undo_splits(mm, block); 1462 return ERR_PTR(err); 1463 } 1464 1465 static bool 1466 gpu_buddy_can_offset_align(u64 size, u64 min_block_size) 1467 { 1468 return size < min_block_size && is_power_of_2(size); 1469 } 1470 1471 static bool gpu_buddy_subtree_can_satisfy(struct rb_node *node, 1472 unsigned int alignment) 1473 { 1474 struct gpu_buddy_block *block; 1475 1476 block = rbtree_get_free_block(node); 1477 return block->subtree_max_alignment >= alignment; 1478 } 1479 1480 static struct gpu_buddy_block * 1481 gpu_buddy_find_block_aligned(struct gpu_buddy *mm, 1482 unsigned int order, 1483 unsigned int alignment) 1484 { 1485 struct rb_root *root = &mm->free_tree[order]; 1486 struct rb_node *rb = root->rb_node; 1487 1488 while (rb) { 1489 struct gpu_buddy_block *block = rbtree_get_free_block(rb); 1490 struct rb_node *left_node = rb->rb_left, *right_node = rb->rb_right; 1491 1492 if (right_node) { 1493 if (gpu_buddy_subtree_can_satisfy(right_node, alignment)) { 1494 rb = right_node; 1495 continue; 1496 } 1497 } 1498 1499 if (gpu_buddy_block_offset_alignment(block) >= alignment) 1500 return block; 1501 1502 if (left_node) { 1503 if (gpu_buddy_subtree_can_satisfy(left_node, alignment)) { 1504 rb = left_node; 1505 continue; 1506 } 1507 } 1508 1509 break; 1510 } 1511 1512 return NULL; 1513 } 1514 1515 static struct gpu_buddy_block * 1516 gpu_buddy_offset_aligned_allocation(struct gpu_buddy *mm, 1517 u64 size, 1518 u64 min_block_size) 1519 { 1520 struct gpu_buddy_block *block = NULL; 1521 unsigned int order, tmp, alignment; 1522 unsigned long pages; 1523 int err; 1524 1525 alignment = ilog2(min_block_size); 1526 pages = size >> ilog2(mm->chunk_size); 1527 order = fls(pages) - 1; 1528 1529 /* 1530 * Offset-aligned allocation is a strict address-placement policy: the 1531 * block is chosen purely by its offset alignment, regardless of its 1532 * clear/dirty state. Clear state is re-derived from the dirty tracker 1533 * once the allocation completes, and the driver is responsible for 1534 * issuing the clear pass if a clear region is required. 1535 */ 1536 for (tmp = order; tmp <= mm->max_order; ++tmp) { 1537 block = gpu_buddy_find_block_aligned(mm, tmp, alignment); 1538 if (block) 1539 break; 1540 } 1541 1542 if (!block) 1543 return ERR_PTR(-ENOSPC); 1544 1545 while (gpu_buddy_block_order(block) > order) { 1546 struct gpu_buddy_block *left, *right; 1547 1548 err = split_block(mm, block); 1549 if (unlikely(err)) 1550 goto err_undo; 1551 1552 left = block->left; 1553 right = block->right; 1554 1555 if (gpu_buddy_block_offset_alignment(right) >= alignment) 1556 block = right; 1557 else 1558 block = left; 1559 } 1560 1561 return block; 1562 1563 err_undo: 1564 /* 1565 * We really don't want to leave around a bunch of split blocks, since 1566 * bigger is better, so make sure we merge everything back before we 1567 * free the allocated blocks. 1568 */ 1569 __gpu_buddy_undo_splits(mm, block); 1570 return ERR_PTR(err); 1571 } 1572 1573 static int __alloc_range(struct gpu_buddy *mm, 1574 struct list_head *dfs, 1575 u64 start, u64 size, 1576 unsigned long flags, 1577 struct list_head *blocks, 1578 u64 *total_allocated_on_err) 1579 { 1580 struct gpu_buddy_block *block; 1581 u64 total_allocated = 0; 1582 LIST_HEAD(allocated); 1583 u64 end; 1584 int err; 1585 1586 end = start + size - 1; 1587 1588 do { 1589 u64 block_start; 1590 u64 block_end; 1591 1592 block = list_first_entry_or_null(dfs, 1593 struct gpu_buddy_block, 1594 tmp_link); 1595 if (!block) 1596 break; 1597 1598 list_del(&block->tmp_link); 1599 1600 block_start = gpu_buddy_block_offset(block); 1601 block_end = block_start + gpu_buddy_block_size(mm, block) - 1; 1602 1603 if (!overlaps(start, end, block_start, block_end)) 1604 continue; 1605 1606 if (gpu_buddy_block_is_allocated(block)) { 1607 err = -ENOSPC; 1608 goto err_free; 1609 } 1610 1611 if (contains(start, end, block_start, block_end)) { 1612 if (gpu_buddy_block_is_free(block)) { 1613 u64 block_offset; 1614 u64 block_size; 1615 1616 block_size = gpu_buddy_block_size(mm, block); 1617 block_offset = gpu_buddy_block_offset(block); 1618 1619 if (!gpu_buddy_block_is_clear(block)) 1620 gpu_dirty_tracker_remove_range(&mm->dirty, 1621 block_offset, 1622 block_size); 1623 1624 mark_allocated(mm, block); 1625 total_allocated += block_size; 1626 mm->avail -= block_size; 1627 1628 list_add_tail(&block->link, &allocated); 1629 continue; 1630 } 1631 } 1632 1633 if (!gpu_buddy_block_is_split(block)) { 1634 err = split_block(mm, block); 1635 if (unlikely(err)) 1636 goto err_undo; 1637 } 1638 1639 list_add(&block->right->tmp_link, dfs); 1640 list_add(&block->left->tmp_link, dfs); 1641 } while (1); 1642 1643 if (total_allocated < size) { 1644 err = -ENOSPC; 1645 goto err_free; 1646 } 1647 1648 list_splice_tail(&allocated, blocks); 1649 1650 return 0; 1651 1652 err_undo: 1653 /* 1654 * We really don't want to leave around a bunch of split blocks, since 1655 * bigger is better, so make sure we merge everything back before we 1656 * free the allocated blocks. 1657 */ 1658 __gpu_buddy_undo_splits(mm, block); 1659 1660 err_free: 1661 if (err == -ENOSPC && total_allocated_on_err) { 1662 list_splice_tail(&allocated, blocks); 1663 *total_allocated_on_err = total_allocated; 1664 } else { 1665 gpu_buddy_free_list_internal(mm, &allocated); 1666 } 1667 1668 return err; 1669 } 1670 1671 static int __gpu_buddy_alloc_range(struct gpu_buddy *mm, 1672 u64 start, 1673 u64 size, 1674 unsigned long flags, 1675 u64 *total_allocated_on_err, 1676 struct list_head *blocks) 1677 { 1678 LIST_HEAD(dfs); 1679 int i; 1680 1681 for (i = 0; i < mm->n_roots; ++i) 1682 list_add_tail(&mm->roots[i]->tmp_link, &dfs); 1683 1684 return __alloc_range(mm, &dfs, start, size, flags, 1685 blocks, total_allocated_on_err); 1686 } 1687 1688 static int __alloc_contig_aligned_retry(struct gpu_buddy *mm, 1689 u64 unaligned_offset, 1690 u64 size, 1691 u64 min_block_size, 1692 unsigned long flags, 1693 struct list_head *blocks) 1694 { 1695 u64 aligned_offset = round_down(unaligned_offset, min_block_size); 1696 1697 return __gpu_buddy_alloc_range(mm, aligned_offset, size, flags, 1698 NULL, blocks); 1699 } 1700 1701 static int __alloc_contig_try_harder(struct gpu_buddy *mm, 1702 u64 size, 1703 u64 min_block_size, 1704 unsigned long flags, 1705 struct list_head *blocks) 1706 { 1707 u64 rhs_offset, lhs_offset, filled; 1708 struct gpu_buddy_block *block; 1709 struct rb_root *root; 1710 struct rb_node *iter; 1711 unsigned long pages; 1712 unsigned int order; 1713 u64 modify_size; 1714 int err; 1715 1716 modify_size = rounddown_pow_of_two(size); 1717 pages = modify_size >> ilog2(mm->chunk_size); 1718 order = fls(pages) - 1; 1719 if (order == 0) 1720 return -ENOSPC; 1721 1722 root = &mm->free_tree[order]; 1723 if (RB_EMPTY_ROOT(root)) 1724 return -ENOSPC; 1725 1726 iter = rb_last(root); 1727 while (iter) { 1728 block = rbtree_get_free_block(iter); 1729 1730 rhs_offset = gpu_buddy_block_offset(block); 1731 1732 /* Allocate blocks traversing RHS */ 1733 err = __gpu_buddy_alloc_range(mm, rhs_offset, size, 1734 flags, &filled, blocks); 1735 if (err && err != -ENOSPC) 1736 return err; 1737 if (!err && IS_ALIGNED(rhs_offset, min_block_size)) 1738 return 0; 1739 if (!err) { 1740 /* Allocate the unaligned RHS offset using round_down */ 1741 gpu_buddy_free_list_internal(mm, blocks); 1742 err = __alloc_contig_aligned_retry(mm, rhs_offset, 1743 size, 1744 min_block_size, 1745 flags, blocks); 1746 if (!err) 1747 return 0; 1748 if (err != -ENOSPC) { 1749 gpu_buddy_free_list_internal(mm, blocks); 1750 return err; 1751 } 1752 goto next; 1753 } 1754 1755 if (size - filled > rhs_offset) 1756 goto next; 1757 1758 lhs_offset = rhs_offset - (size - filled); 1759 1760 /* Allocate the unaligned LHS offset using round_down */ 1761 gpu_buddy_free_list_internal(mm, blocks); 1762 err = __alloc_contig_aligned_retry(mm, lhs_offset, 1763 size, 1764 min_block_size, 1765 flags, blocks); 1766 if (!err) 1767 return 0; 1768 if (err != -ENOSPC) { 1769 gpu_buddy_free_list_internal(mm, blocks); 1770 return err; 1771 } 1772 next: 1773 gpu_buddy_free_list_internal(mm, blocks); 1774 iter = rb_prev(iter); 1775 } 1776 1777 return -ENOSPC; 1778 } 1779 1780 /** 1781 * gpu_buddy_block_trim - free unused pages 1782 * 1783 * @mm: GPU buddy manager 1784 * @start: start address to begin the trimming. 1785 * @new_size: original size requested 1786 * @blocks: Input and output list of allocated blocks. 1787 * MUST contain single block as input to be trimmed. 1788 * On success will contain the newly allocated blocks 1789 * making up the @new_size. Blocks always appear in 1790 * ascending order 1791 * 1792 * For contiguous allocation, we round up the size to the nearest 1793 * power of two value, drivers consume *actual* size, so remaining 1794 * portions are unused and can be optionally freed with this function 1795 * 1796 * Returns: 1797 * 0 on success, error code on failure. 1798 */ 1799 int gpu_buddy_block_trim(struct gpu_buddy *mm, 1800 u64 *start, 1801 u64 new_size, 1802 struct list_head *blocks) 1803 { 1804 struct gpu_buddy_block *parent; 1805 struct gpu_buddy_block *block; 1806 u64 block_start, block_end; 1807 LIST_HEAD(dfs); 1808 bool was_clear; 1809 u64 new_start; 1810 int err; 1811 1812 gpu_buddy_driver_lock_held(mm); 1813 1814 if (!list_is_singular(blocks)) 1815 return -EINVAL; 1816 1817 block = list_first_entry(blocks, 1818 struct gpu_buddy_block, 1819 link); 1820 1821 block_start = gpu_buddy_block_offset(block); 1822 block_end = block_start + gpu_buddy_block_size(mm, block); 1823 1824 if (WARN_ON(!gpu_buddy_block_is_allocated(block))) 1825 return -EINVAL; 1826 1827 if (new_size > gpu_buddy_block_size(mm, block)) 1828 return -EINVAL; 1829 1830 if (!new_size || !IS_ALIGNED(new_size, mm->chunk_size)) 1831 return -EINVAL; 1832 1833 if (new_size == gpu_buddy_block_size(mm, block)) 1834 return 0; 1835 1836 new_start = block_start; 1837 if (start) { 1838 new_start = *start; 1839 1840 if (new_start < block_start) 1841 return -EINVAL; 1842 1843 if (!IS_ALIGNED(new_start, mm->chunk_size)) 1844 return -EINVAL; 1845 1846 if (range_overflows(new_start, new_size, block_end)) 1847 return -EINVAL; 1848 } 1849 1850 list_del(&block->link); 1851 1852 was_clear = gpu_buddy_block_is_clear(block); 1853 1854 if (!was_clear) 1855 gpu_dirty_tracker_mark_dirty(&mm->dirty, 1856 gpu_buddy_block_offset(block), 1857 gpu_buddy_block_size(mm, block)); 1858 1859 __mark_free(mm, block, was_clear ? GPU_BLOCK_CLEAR : GPU_BLOCK_DIRTY); 1860 mm->avail += gpu_buddy_block_size(mm, block); 1861 1862 /* Prevent recursively freeing this node */ 1863 parent = block->parent; 1864 block->parent = NULL; 1865 1866 list_add(&block->tmp_link, &dfs); 1867 err = __alloc_range(mm, &dfs, new_start, new_size, 1868 was_clear ? GPU_BUDDY_CLEAR_ALLOCATION : 0, 1869 blocks, NULL); 1870 if (err) { 1871 mark_allocated(mm, block); 1872 mm->avail -= gpu_buddy_block_size(mm, block); 1873 if (!was_clear) { 1874 gpu_dirty_tracker_remove_range(&mm->dirty, 1875 gpu_buddy_block_offset(block), 1876 gpu_buddy_block_size(mm, block)); 1877 } 1878 if (was_clear) 1879 block->header |= GPU_BUDDY_HEADER_CLEAR; 1880 list_add(&block->link, blocks); 1881 } 1882 1883 block->parent = parent; 1884 return err; 1885 } 1886 EXPORT_SYMBOL(gpu_buddy_block_trim); 1887 1888 static bool dirty_steer_window(struct gpu_buddy *mm, u64 req_size, 1889 u64 *start, u64 *end, unsigned long *flags) 1890 { 1891 u64 aligned_start; 1892 struct gpu_dirty_extent *ext = 1893 gpu_dirty_tracker_find(&mm->dirty, req_size, &aligned_start); 1894 1895 if (!ext) 1896 return false; 1897 1898 *start = aligned_start; 1899 *end = ext->end; 1900 *flags |= GPU_BUDDY_RANGE_ALLOCATION; 1901 return true; 1902 } 1903 1904 static struct gpu_buddy_block * 1905 __gpu_buddy_alloc_blocks(struct gpu_buddy *mm, 1906 u64 start, u64 end, 1907 u64 size, u64 min_block_size, 1908 unsigned int order, 1909 unsigned long flags) 1910 { 1911 struct gpu_buddy_block *block; 1912 bool steered = false; 1913 1914 /* Allocate from dirty tracker */ 1915 if (!(flags & GPU_BUDDY_RANGE_ALLOCATION) && 1916 !(flags & GPU_BUDDY_CLEAR_ALLOCATION) && 1917 size >= min_block_size && 1918 gpu_buddy_clear_avail(mm) && mm->dirty.total_dirty) { 1919 u64 block_size = mm->chunk_size << order; 1920 1921 steered = dirty_steer_window(mm, block_size, 1922 &start, &end, &flags); 1923 } 1924 1925 if (flags & GPU_BUDDY_RANGE_ALLOCATION) { 1926 /* Allocate traversing within the range */ 1927 block = __alloc_range_bias(mm, start, end, order, flags); 1928 if (!IS_ERR(block) || !steered) 1929 return block; 1930 1931 flags &= ~GPU_BUDDY_RANGE_ALLOCATION; 1932 } 1933 1934 if (size < min_block_size) 1935 /* Allocate from an offset-aligned region without size rounding */ 1936 return gpu_buddy_offset_aligned_allocation(mm, size, 1937 min_block_size); 1938 1939 /* Allocate from freetree */ 1940 return alloc_from_freetree(mm, order, flags); 1941 } 1942 1943 /** 1944 * gpu_buddy_alloc_blocks - allocate power-of-two blocks 1945 * 1946 * @mm: GPU buddy manager to allocate from 1947 * @start: start of the allowed range for this block 1948 * @end: end of the allowed range for this block 1949 * @size: size of the allocation in bytes 1950 * @min_block_size: alignment of the allocation 1951 * @blocks: output list head to add allocated blocks 1952 * @flags: GPU_BUDDY_*_ALLOCATION flags 1953 * 1954 * alloc_range_bias() called on range limitations, which traverses 1955 * the tree and returns the desired block. 1956 * 1957 * alloc_from_freetree() called when *no* range restrictions 1958 * are enforced, which picks the block from the freetree. 1959 * 1960 * Returns: 1961 * 0 on success, error code on failure. 1962 */ 1963 int gpu_buddy_alloc_blocks(struct gpu_buddy *mm, 1964 u64 start, u64 end, u64 size, 1965 u64 min_block_size, 1966 struct list_head *blocks, 1967 unsigned long flags) 1968 { 1969 struct gpu_buddy_block *block = NULL; 1970 u64 original_size, original_min_size; 1971 unsigned int min_order, order; 1972 LIST_HEAD(allocated); 1973 unsigned long pages; 1974 int err; 1975 1976 gpu_buddy_driver_lock_held(mm); 1977 1978 if (size < mm->chunk_size) 1979 return -EINVAL; 1980 1981 if (min_block_size < mm->chunk_size) 1982 return -EINVAL; 1983 1984 if (!is_power_of_2(min_block_size)) 1985 return -EINVAL; 1986 1987 if (!IS_ALIGNED(start | end | size, mm->chunk_size)) 1988 return -EINVAL; 1989 1990 if (end > mm->size) 1991 return -EINVAL; 1992 1993 if (range_overflows(start, size, mm->size)) 1994 return -EINVAL; 1995 1996 /* Actual range allocation */ 1997 if (start + size == end) { 1998 if (!IS_ALIGNED(start | end, min_block_size)) 1999 return -EINVAL; 2000 2001 return __gpu_buddy_alloc_range(mm, start, size, flags, NULL, blocks); 2002 } 2003 2004 original_size = size; 2005 original_min_size = min_block_size; 2006 2007 /* Roundup the size to power of 2 */ 2008 if (flags & GPU_BUDDY_CONTIGUOUS_ALLOCATION) { 2009 size = roundup_pow_of_two(size); 2010 min_block_size = size; 2011 /* 2012 * Normalize the requested size to min_block_size for regular allocations. 2013 * Offset-aligned allocations intentionally skip size rounding. 2014 */ 2015 } else if (!gpu_buddy_can_offset_align(size, min_block_size)) { 2016 size = round_up(size, min_block_size); 2017 } 2018 2019 pages = size >> ilog2(mm->chunk_size); 2020 order = fls(pages) - 1; 2021 min_order = ilog2(min_block_size) - ilog2(mm->chunk_size); 2022 2023 if (order > mm->max_order || size > mm->size) { 2024 if ((flags & GPU_BUDDY_CONTIGUOUS_ALLOCATION) && 2025 !(flags & GPU_BUDDY_RANGE_ALLOCATION)) 2026 return __alloc_contig_try_harder(mm, original_size, 2027 original_min_size, 2028 flags, blocks); 2029 2030 return -EINVAL; 2031 } 2032 2033 do { 2034 order = min(order, (unsigned int)fls(pages) - 1); 2035 BUG_ON(order > mm->max_order); 2036 /* 2037 * Regular allocations must not allocate blocks smaller than min_block_size. 2038 * Offset-aligned allocations deliberately bypass this constraint. 2039 */ 2040 BUG_ON(size >= min_block_size && order < min_order); 2041 2042 do { 2043 block = __gpu_buddy_alloc_blocks(mm, start, 2044 end, 2045 size, 2046 min_block_size, 2047 order, 2048 flags); 2049 if (!IS_ERR(block)) 2050 break; 2051 2052 if (size >= min_block_size && order > min_order) { 2053 order--; 2054 continue; 2055 } 2056 2057 /* 2058 * Try contiguous block allocation through 2059 * try harder method. 2060 */ 2061 if (flags & GPU_BUDDY_CONTIGUOUS_ALLOCATION && 2062 !(flags & GPU_BUDDY_RANGE_ALLOCATION)) { 2063 err = __alloc_contig_try_harder(mm, 2064 original_size, 2065 original_min_size, 2066 flags, 2067 blocks); 2068 if (!err) 2069 return 0; 2070 if (err != -ENOSPC) 2071 return err; 2072 goto err_free; 2073 } 2074 err = -ENOSPC; 2075 goto err_free; 2076 } while (1); 2077 2078 if (!gpu_buddy_block_is_clear(block)) 2079 gpu_dirty_tracker_remove_range(&mm->dirty, 2080 gpu_buddy_block_offset(block), 2081 gpu_buddy_block_size(mm, block)); 2082 2083 mark_allocated(mm, block); 2084 mm->avail -= gpu_buddy_block_size(mm, block); 2085 2086 kmemleak_update_trace(block); 2087 list_add_tail(&block->link, &allocated); 2088 2089 pages -= BIT(order); 2090 2091 if (!pages) 2092 break; 2093 } while (1); 2094 2095 /* Trim the allocated block to the required size */ 2096 if (!(flags & GPU_BUDDY_TRIM_DISABLE) && 2097 original_size != size) { 2098 struct list_head *trim_list; 2099 LIST_HEAD(temp); 2100 u64 trim_size; 2101 2102 trim_list = &allocated; 2103 trim_size = original_size; 2104 2105 if (!list_is_singular(&allocated)) { 2106 block = list_last_entry(&allocated, typeof(*block), link); 2107 list_move(&block->link, &temp); 2108 trim_list = &temp; 2109 trim_size = gpu_buddy_block_size(mm, block) - 2110 (size - original_size); 2111 } 2112 2113 gpu_buddy_block_trim(mm, 2114 NULL, 2115 trim_size, 2116 trim_list); 2117 2118 if (!list_empty(&temp)) 2119 list_splice_tail(trim_list, &allocated); 2120 } 2121 2122 list_splice_tail(&allocated, blocks); 2123 return 0; 2124 2125 err_free: 2126 gpu_buddy_free_list_internal(mm, &allocated); 2127 return err; 2128 } 2129 EXPORT_SYMBOL(gpu_buddy_alloc_blocks); 2130 2131 /** 2132 * gpu_buddy_block_print - print block information 2133 * 2134 * @mm: GPU buddy manager 2135 * @block: GPU buddy block 2136 */ 2137 void gpu_buddy_block_print(struct gpu_buddy *mm, 2138 struct gpu_buddy_block *block) 2139 { 2140 u64 start = gpu_buddy_block_offset(block); 2141 u64 size = gpu_buddy_block_size(mm, block); 2142 2143 pr_info("%#018llx-%#018llx: %llu\n", start, start + size, size); 2144 } 2145 EXPORT_SYMBOL(gpu_buddy_block_print); 2146 2147 /** 2148 * gpu_buddy_print - print allocator state 2149 * 2150 * @mm: GPU buddy manager 2151 */ 2152 void gpu_buddy_print(struct gpu_buddy *mm) 2153 { 2154 int order; 2155 2156 gpu_buddy_driver_lock_held(mm); 2157 pr_info("chunk_size: %lluKiB, total: %lluMiB, free: %lluMiB, clear_free: %lluMiB\n", 2158 mm->chunk_size >> 10, mm->size >> 20, mm->avail >> 20, 2159 gpu_buddy_clear_avail(mm) >> 20); 2160 2161 for (order = mm->max_order; order >= 0; order--) { 2162 u64 free_count = mm->free_scoreboard[order]; 2163 u64 used_count = mm->used_scoreboard[order]; 2164 u64 block_size = mm->chunk_size << order; 2165 u64 free = free_count * block_size; 2166 u64 used = used_count * block_size; 2167 2168 if (block_size < SZ_1M) 2169 pr_info("order-%2d free: %8llu KiB, used: %8llu KiB, free_blocks: %llu, used_blocks: %llu\n", 2170 order, free >> 10, used >> 10, free_count, used_count); 2171 else 2172 pr_info("order-%2d free: %8llu MiB, used: %8llu MiB, free_blocks: %llu, used_blocks: %llu\n", 2173 order, free >> 20, used >> 20, free_count, used_count); 2174 } 2175 } 2176 EXPORT_SYMBOL(gpu_buddy_print); 2177 2178 static void gpu_buddy_module_exit(void) 2179 { 2180 kmem_cache_destroy(slab_extents); 2181 kmem_cache_destroy(slab_blocks); 2182 } 2183 2184 static int __init gpu_buddy_module_init(void) 2185 { 2186 slab_blocks = KMEM_CACHE(gpu_buddy_block, 0); 2187 if (!slab_blocks) 2188 return -ENOMEM; 2189 2190 slab_extents = KMEM_CACHE(gpu_dirty_extent, 0); 2191 if (!slab_extents) 2192 goto err_destroy_blocks; 2193 2194 return 0; 2195 2196 err_destroy_blocks: 2197 kmem_cache_destroy(slab_blocks); 2198 return -ENOMEM; 2199 } 2200 2201 module_init(gpu_buddy_module_init); 2202 module_exit(gpu_buddy_module_exit); 2203 2204 MODULE_DESCRIPTION("GPU Buddy Allocator"); 2205 MODULE_LICENSE("Dual MIT/GPL"); 2206