1 /* 2 * Copyright 2020 Advanced Micro Devices, Inc. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included in 12 * all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 * OTHER DEALINGS IN THE SOFTWARE. 21 * 22 * Authors: Christian König 23 */ 24 25 #include <linux/debugfs.h> 26 #include <linux/export.h> 27 #include <linux/io-mapping.h> 28 #include <linux/iosys-map.h> 29 #include <linux/scatterlist.h> 30 #include <linux/cgroup_dmem.h> 31 32 #include <drm/ttm/ttm_bo.h> 33 #include <drm/ttm/ttm_placement.h> 34 #include <drm/ttm/ttm_resource.h> 35 #include <drm/ttm/ttm_tt.h> 36 37 #include <drm/drm_print.h> 38 #include <drm/drm_util.h> 39 40 /* Detach the cursor from the bulk move list */ 41 static void 42 ttm_resource_cursor_clear_bulk(struct ttm_resource_cursor *cursor) 43 { 44 lockdep_assert_held(&cursor->man->bdev->lru_lock); 45 46 cursor->bulk = NULL; 47 list_del_init(&cursor->bulk_link); 48 } 49 50 /* Move the cursor to the end of the bulk move list it's in */ 51 static void ttm_resource_cursor_move_bulk_tail(struct ttm_lru_bulk_move *bulk, 52 struct ttm_resource_cursor *cursor) 53 { 54 struct ttm_lru_bulk_move_pos *pos; 55 56 lockdep_assert_held(&cursor->man->bdev->lru_lock); 57 58 if (WARN_ON_ONCE(bulk != cursor->bulk)) { 59 list_del_init(&cursor->bulk_link); 60 return; 61 } 62 63 pos = &bulk->pos[cursor->mem_type][cursor->priority]; 64 if (pos->last) 65 list_move(&cursor->hitch.link, &pos->last->lru.link); 66 ttm_resource_cursor_clear_bulk(cursor); 67 } 68 69 /* Move all cursors attached to a bulk move to its end */ 70 static void ttm_bulk_move_adjust_cursors(struct ttm_lru_bulk_move *bulk) 71 { 72 struct ttm_resource_cursor *cursor, *next; 73 74 list_for_each_entry_safe(cursor, next, &bulk->cursor_list, bulk_link) 75 ttm_resource_cursor_move_bulk_tail(bulk, cursor); 76 } 77 78 /* Remove a cursor from an empty bulk move list */ 79 static void ttm_bulk_move_drop_cursors(struct ttm_lru_bulk_move *bulk) 80 { 81 struct ttm_resource_cursor *cursor, *next; 82 83 list_for_each_entry_safe(cursor, next, &bulk->cursor_list, bulk_link) 84 ttm_resource_cursor_clear_bulk(cursor); 85 } 86 87 /** 88 * ttm_resource_cursor_init() - Initialize a struct ttm_resource_cursor 89 * @cursor: The cursor to initialize. 90 * @man: The resource manager. 91 * 92 * Initialize the cursor before using it for iteration. 93 */ 94 void ttm_resource_cursor_init(struct ttm_resource_cursor *cursor, 95 struct ttm_resource_manager *man) 96 { 97 cursor->priority = 0; 98 cursor->man = man; 99 ttm_lru_item_init(&cursor->hitch, TTM_LRU_HITCH); 100 INIT_LIST_HEAD(&cursor->bulk_link); 101 INIT_LIST_HEAD(&cursor->hitch.link); 102 } 103 104 /** 105 * ttm_resource_cursor_fini() - Finalize the LRU list cursor usage 106 * @cursor: The struct ttm_resource_cursor to finalize. 107 * 108 * The function pulls the LRU list cursor off any lists it was previously 109 * attached to. Needs to be called with the LRU lock held. The function 110 * can be called multiple times after each other. 111 */ 112 void ttm_resource_cursor_fini(struct ttm_resource_cursor *cursor) 113 { 114 lockdep_assert_held(&cursor->man->bdev->lru_lock); 115 list_del_init(&cursor->hitch.link); 116 ttm_resource_cursor_clear_bulk(cursor); 117 } 118 119 /** 120 * ttm_lru_bulk_move_init - initialize a bulk move structure 121 * @bulk: the structure to init 122 * 123 * For now just memset the structure to zero. 124 */ 125 void ttm_lru_bulk_move_init(struct ttm_lru_bulk_move *bulk) 126 { 127 memset(bulk, 0, sizeof(*bulk)); 128 INIT_LIST_HEAD(&bulk->cursor_list); 129 } 130 EXPORT_SYMBOL(ttm_lru_bulk_move_init); 131 132 /** 133 * ttm_lru_bulk_move_fini - finalize a bulk move structure 134 * @bdev: The struct ttm_device 135 * @bulk: the structure to finalize 136 * 137 * Sanity checks that bulk moves don't have any 138 * resources left and hence no cursors attached. 139 */ 140 void ttm_lru_bulk_move_fini(struct ttm_device *bdev, 141 struct ttm_lru_bulk_move *bulk) 142 { 143 spin_lock(&bdev->lru_lock); 144 ttm_bulk_move_drop_cursors(bulk); 145 spin_unlock(&bdev->lru_lock); 146 } 147 EXPORT_SYMBOL(ttm_lru_bulk_move_fini); 148 149 /** 150 * ttm_lru_bulk_move_tail - bulk move range of resources to the LRU tail. 151 * 152 * @bulk: bulk move structure 153 * 154 * Bulk move BOs to the LRU tail, only valid to use when driver makes sure that 155 * resource order never changes. Should be called with &ttm_device.lru_lock held. 156 */ 157 void ttm_lru_bulk_move_tail(struct ttm_lru_bulk_move *bulk) 158 { 159 unsigned i, j; 160 161 ttm_bulk_move_adjust_cursors(bulk); 162 for (i = 0; i < TTM_NUM_MEM_TYPES; ++i) { 163 for (j = 0; j < TTM_MAX_BO_PRIORITY; ++j) { 164 struct ttm_lru_bulk_move_pos *pos = &bulk->pos[i][j]; 165 struct ttm_resource_manager *man; 166 167 if (!pos->first) 168 continue; 169 170 lockdep_assert_held(&pos->first->bo->bdev->lru_lock); 171 dma_resv_assert_held(pos->first->bo->base.resv); 172 dma_resv_assert_held(pos->last->bo->base.resv); 173 174 man = ttm_manager_type(pos->first->bo->bdev, i); 175 list_bulk_move_tail(&man->lru[j], &pos->first->lru.link, 176 &pos->last->lru.link); 177 } 178 } 179 } 180 EXPORT_SYMBOL(ttm_lru_bulk_move_tail); 181 182 /* Return the bulk move pos object for this resource */ 183 static struct ttm_lru_bulk_move_pos * 184 ttm_lru_bulk_move_pos(struct ttm_lru_bulk_move *bulk, struct ttm_resource *res) 185 { 186 return &bulk->pos[res->mem_type][res->bo->priority]; 187 } 188 189 /* Return the previous resource on the list (skip over non-resource list items) */ 190 static struct ttm_resource *ttm_lru_prev_res(struct ttm_resource *cur) 191 { 192 struct ttm_lru_item *lru = &cur->lru; 193 194 do { 195 lru = list_prev_entry(lru, link); 196 } while (!ttm_lru_item_is_res(lru)); 197 198 return ttm_lru_item_to_res(lru); 199 } 200 201 /* Return the next resource on the list (skip over non-resource list items) */ 202 static struct ttm_resource *ttm_lru_next_res(struct ttm_resource *cur) 203 { 204 struct ttm_lru_item *lru = &cur->lru; 205 206 do { 207 lru = list_next_entry(lru, link); 208 } while (!ttm_lru_item_is_res(lru)); 209 210 return ttm_lru_item_to_res(lru); 211 } 212 213 /* Move the resource to the tail of the bulk move range */ 214 static void ttm_lru_bulk_move_pos_tail(struct ttm_lru_bulk_move_pos *pos, 215 struct ttm_resource *res) 216 { 217 if (pos->last != res) { 218 if (pos->first == res) 219 pos->first = ttm_lru_next_res(res); 220 list_move(&res->lru.link, &pos->last->lru.link); 221 pos->last = res; 222 } 223 } 224 225 /* Add the resource to a bulk_move cursor */ 226 static void ttm_lru_bulk_move_add(struct ttm_lru_bulk_move *bulk, 227 struct ttm_resource *res) 228 { 229 struct ttm_lru_bulk_move_pos *pos = ttm_lru_bulk_move_pos(bulk, res); 230 231 if (!pos->first) { 232 pos->first = res; 233 pos->last = res; 234 } else { 235 WARN_ON(pos->first->bo->base.resv != res->bo->base.resv); 236 ttm_lru_bulk_move_pos_tail(pos, res); 237 } 238 } 239 240 /* Remove the resource from a bulk_move range */ 241 static void ttm_lru_bulk_move_del(struct ttm_lru_bulk_move *bulk, 242 struct ttm_resource *res) 243 { 244 struct ttm_lru_bulk_move_pos *pos = ttm_lru_bulk_move_pos(bulk, res); 245 246 if (unlikely(WARN_ON(!pos->first || !pos->last) || 247 (pos->first == res && pos->last == res))) { 248 pos->first = NULL; 249 pos->last = NULL; 250 } else if (pos->first == res) { 251 pos->first = ttm_lru_next_res(res); 252 } else if (pos->last == res) { 253 pos->last = ttm_lru_prev_res(res); 254 } else { 255 list_move(&res->lru.link, &pos->last->lru.link); 256 } 257 } 258 259 static bool ttm_resource_is_swapped(struct ttm_resource *res, struct ttm_buffer_object *bo) 260 { 261 /* 262 * Take care when creating a new resource for a bo, that it is not considered 263 * swapped if it's not the current resource for the bo and is thus logically 264 * associated with the ttm_tt. Think a VRAM resource created to move a 265 * swapped-out bo to VRAM. 266 */ 267 if (bo->resource != res || !bo->ttm) 268 return false; 269 270 dma_resv_assert_held(bo->base.resv); 271 return ttm_tt_is_swapped(bo->ttm); 272 } 273 274 static bool ttm_resource_unevictable(struct ttm_resource *res, struct ttm_buffer_object *bo) 275 { 276 return bo->pin_count || ttm_resource_is_swapped(res, bo); 277 } 278 279 /* Add the resource to a bulk move if the BO is configured for it */ 280 void ttm_resource_add_bulk_move(struct ttm_resource *res, 281 struct ttm_buffer_object *bo) 282 { 283 if (bo->bulk_move && !ttm_resource_unevictable(res, bo)) 284 ttm_lru_bulk_move_add(bo->bulk_move, res); 285 } 286 287 /* Remove the resource from a bulk move if the BO is configured for it */ 288 void ttm_resource_del_bulk_move(struct ttm_resource *res, 289 struct ttm_buffer_object *bo) 290 { 291 if (bo->bulk_move && !ttm_resource_unevictable(res, bo)) 292 ttm_lru_bulk_move_del(bo->bulk_move, res); 293 } 294 295 /* 296 * Remove a resource from its bulk_move, bypassing the unevictable check. 297 * Use only when the resource is known to still be tracked in the range despite 298 * the BO having just become unevictable; asserts that this is the case. 299 */ 300 void ttm_resource_del_bulk_move_unevictable(struct ttm_resource *res, 301 struct ttm_buffer_object *bo) 302 { 303 WARN_ON_ONCE(!ttm_resource_unevictable(res, bo)); 304 if (bo->bulk_move) 305 ttm_lru_bulk_move_del(bo->bulk_move, res); 306 } 307 308 /* Move a resource to the LRU or bulk tail */ 309 void ttm_resource_move_to_lru_tail(struct ttm_resource *res) 310 { 311 struct ttm_buffer_object *bo = res->bo; 312 struct ttm_device *bdev = bo->bdev; 313 314 lockdep_assert_held(&bo->bdev->lru_lock); 315 316 if (ttm_resource_unevictable(res, bo)) { 317 list_move_tail(&res->lru.link, &bdev->unevictable); 318 319 } else if (bo->bulk_move) { 320 struct ttm_lru_bulk_move_pos *pos = 321 ttm_lru_bulk_move_pos(bo->bulk_move, res); 322 323 ttm_lru_bulk_move_pos_tail(pos, res); 324 } else { 325 struct ttm_resource_manager *man; 326 327 man = ttm_manager_type(bdev, res->mem_type); 328 list_move_tail(&res->lru.link, &man->lru[bo->priority]); 329 } 330 } 331 332 /** 333 * ttm_resource_init - resource object constructor 334 * @bo: buffer object this resource is allocated for 335 * @place: placement of the resource 336 * @res: the resource object to initialize 337 * 338 * Initialize a new resource object. Counterpart of ttm_resource_fini(). 339 */ 340 void ttm_resource_init(struct ttm_buffer_object *bo, 341 const struct ttm_place *place, 342 struct ttm_resource *res) 343 { 344 struct ttm_resource_manager *man; 345 346 res->start = 0; 347 res->size = bo->base.size; 348 res->mem_type = place->mem_type; 349 res->placement = place->flags; 350 res->bus.addr = NULL; 351 res->bus.offset = 0; 352 res->bus.is_iomem = false; 353 res->bus.caching = ttm_cached; 354 res->bo = bo; 355 356 man = ttm_manager_type(bo->bdev, place->mem_type); 357 spin_lock(&bo->bdev->lru_lock); 358 if (ttm_resource_unevictable(res, bo)) 359 list_add_tail(&res->lru.link, &bo->bdev->unevictable); 360 else 361 list_add_tail(&res->lru.link, &man->lru[bo->priority]); 362 man->usage += res->size; 363 spin_unlock(&bo->bdev->lru_lock); 364 } 365 EXPORT_SYMBOL(ttm_resource_init); 366 367 /** 368 * ttm_resource_fini - resource destructor 369 * @man: the resource manager this resource belongs to 370 * @res: the resource to clean up 371 * 372 * Should be used by resource manager backends to clean up the TTM resource 373 * objects before freeing the underlying structure. Makes sure the resource is 374 * removed from the LRU before destruction. 375 * Counterpart of ttm_resource_init(). 376 */ 377 void ttm_resource_fini(struct ttm_resource_manager *man, 378 struct ttm_resource *res) 379 { 380 struct ttm_device *bdev = man->bdev; 381 382 spin_lock(&bdev->lru_lock); 383 list_del_init(&res->lru.link); 384 man->usage -= res->size; 385 spin_unlock(&bdev->lru_lock); 386 } 387 EXPORT_SYMBOL(ttm_resource_fini); 388 389 /** 390 * ttm_resource_try_charge - charge a resource manager's cgroup pool 391 * @bo: buffer for which an allocation should be charged 392 * @place: where the allocation is attempted to be placed 393 * @ret_pool: on charge success, the pool that was charged 394 * @ret_limit_pool: on charge failure, the pool responsible for the failure 395 * 396 * Should be used to charge cgroups before attempting resource allocation. 397 * When charging succeeds, the value of ret_pool should be passed to 398 * ttm_resource_alloc. 399 * 400 * Returns: 0 on charge success, negative errno on failure. 401 */ 402 int ttm_resource_try_charge(struct ttm_buffer_object *bo, 403 const struct ttm_place *place, 404 struct dmem_cgroup_pool_state **ret_pool, 405 struct dmem_cgroup_pool_state **ret_limit_pool) 406 { 407 struct ttm_resource_manager *man = 408 ttm_manager_type(bo->bdev, place->mem_type); 409 410 if (!man->cg) { 411 *ret_pool = NULL; 412 if (ret_limit_pool) 413 *ret_limit_pool = NULL; 414 return 0; 415 } 416 417 return dmem_cgroup_try_charge(man->cg, bo->base.size, ret_pool, 418 ret_limit_pool); 419 } 420 421 int ttm_resource_alloc(struct ttm_buffer_object *bo, 422 const struct ttm_place *place, 423 struct ttm_resource **res_ptr, 424 struct dmem_cgroup_pool_state *charge_pool) 425 { 426 struct ttm_resource_manager *man = 427 ttm_manager_type(bo->bdev, place->mem_type); 428 int ret; 429 430 ret = man->func->alloc(man, bo, place, res_ptr); 431 if (ret) 432 return ret; 433 434 (*res_ptr)->css = charge_pool; 435 436 spin_lock(&bo->bdev->lru_lock); 437 ttm_resource_add_bulk_move(*res_ptr, bo); 438 spin_unlock(&bo->bdev->lru_lock); 439 return 0; 440 } 441 EXPORT_SYMBOL_FOR_TESTS_ONLY(ttm_resource_alloc); 442 443 void ttm_resource_free(struct ttm_buffer_object *bo, struct ttm_resource **res) 444 { 445 struct ttm_resource_manager *man; 446 struct dmem_cgroup_pool_state *pool; 447 448 if (!*res) 449 return; 450 451 spin_lock(&bo->bdev->lru_lock); 452 ttm_resource_del_bulk_move(*res, bo); 453 spin_unlock(&bo->bdev->lru_lock); 454 455 pool = (*res)->css; 456 man = ttm_manager_type(bo->bdev, (*res)->mem_type); 457 man->func->free(man, *res); 458 *res = NULL; 459 if (pool) 460 dmem_cgroup_uncharge(pool, bo->base.size); 461 } 462 EXPORT_SYMBOL(ttm_resource_free); 463 464 /** 465 * ttm_resource_intersects - test for intersection 466 * 467 * @bdev: TTM device structure 468 * @res: The resource to test 469 * @place: The placement to test 470 * @size: How many bytes the new allocation needs. 471 * 472 * Test if @res intersects with @place and @size. Used for testing if evictions 473 * are valuable or not. 474 * 475 * Returns true if the res placement intersects with @place and @size. 476 */ 477 bool ttm_resource_intersects(struct ttm_device *bdev, 478 struct ttm_resource *res, 479 const struct ttm_place *place, 480 size_t size) 481 { 482 struct ttm_resource_manager *man; 483 484 man = ttm_manager_type(bdev, res->mem_type); 485 if (!place || !man->func->intersects) 486 return true; 487 488 return man->func->intersects(man, res, place, size); 489 } 490 491 /** 492 * ttm_resource_compatible - check if resource is compatible with placement 493 * 494 * @res: the resource to check 495 * @placement: the placement to check against 496 * @evicting: true if the caller is doing evictions 497 * 498 * Returns true if the placement is compatible. 499 */ 500 bool ttm_resource_compatible(struct ttm_resource *res, 501 struct ttm_placement *placement, 502 bool evicting) 503 { 504 struct ttm_buffer_object *bo = res->bo; 505 struct ttm_device *bdev = bo->bdev; 506 unsigned i; 507 508 if (res->placement & TTM_PL_FLAG_TEMPORARY) 509 return false; 510 511 for (i = 0; i < placement->num_placement; i++) { 512 const struct ttm_place *place = &placement->placement[i]; 513 struct ttm_resource_manager *man; 514 515 if (res->mem_type != place->mem_type) 516 continue; 517 518 if (place->flags & (evicting ? TTM_PL_FLAG_DESIRED : 519 TTM_PL_FLAG_FALLBACK)) 520 continue; 521 522 if (place->flags & TTM_PL_FLAG_CONTIGUOUS && 523 !(res->placement & TTM_PL_FLAG_CONTIGUOUS)) 524 continue; 525 526 man = ttm_manager_type(bdev, res->mem_type); 527 if (man->func->compatible && 528 !man->func->compatible(man, res, place, bo->base.size)) 529 continue; 530 531 return true; 532 } 533 return false; 534 } 535 536 void ttm_resource_set_bo(struct ttm_resource *res, 537 struct ttm_buffer_object *bo) 538 { 539 spin_lock(&bo->bdev->lru_lock); 540 res->bo = bo; 541 spin_unlock(&bo->bdev->lru_lock); 542 } 543 544 /** 545 * ttm_resource_manager_init 546 * 547 * @man: memory manager object to init 548 * @bdev: ttm device this manager belongs to 549 * @size: size of managed resources in arbitrary units 550 * 551 * Initialize core parts of a manager object. 552 */ 553 void ttm_resource_manager_init(struct ttm_resource_manager *man, 554 struct ttm_device *bdev, 555 uint64_t size) 556 { 557 unsigned i; 558 559 man->bdev = bdev; 560 man->size = size; 561 man->usage = 0; 562 563 for (i = 0; i < TTM_MAX_BO_PRIORITY; ++i) 564 INIT_LIST_HEAD(&man->lru[i]); 565 spin_lock_init(&man->eviction_lock); 566 for (i = 0; i < TTM_NUM_MOVE_FENCES; i++) 567 man->eviction_fences[i] = NULL; 568 } 569 EXPORT_SYMBOL(ttm_resource_manager_init); 570 571 /* 572 * ttm_resource_manager_evict_all 573 * 574 * @bdev: device to use 575 * @man: manager to use 576 * 577 * Evict all the objects out of a memory manager until it is empty. 578 * Part of memory manager cleanup sequence. 579 */ 580 int ttm_resource_manager_evict_all(struct ttm_device *bdev, 581 struct ttm_resource_manager *man) 582 { 583 struct ttm_operation_ctx ctx = { }; 584 struct dma_fence *fence; 585 int ret, i; 586 587 do { 588 ret = ttm_bo_evict_first(bdev, man, &ctx); 589 cond_resched(); 590 } while (!ret); 591 592 if (ret && ret != -ENOENT) 593 return ret; 594 595 ret = 0; 596 597 spin_lock(&man->eviction_lock); 598 for (i = 0; i < TTM_NUM_MOVE_FENCES; i++) { 599 fence = man->eviction_fences[i]; 600 if (fence && !dma_fence_is_signaled(fence)) { 601 dma_fence_get(fence); 602 spin_unlock(&man->eviction_lock); 603 ret = dma_fence_wait(fence, false); 604 dma_fence_put(fence); 605 if (ret) 606 return ret; 607 spin_lock(&man->eviction_lock); 608 } 609 } 610 spin_unlock(&man->eviction_lock); 611 612 return ret; 613 } 614 EXPORT_SYMBOL(ttm_resource_manager_evict_all); 615 616 /** 617 * ttm_resource_manager_usage 618 * 619 * @man: A memory manager object. 620 * 621 * Return how many resources are currently used. 622 */ 623 uint64_t ttm_resource_manager_usage(struct ttm_resource_manager *man) 624 { 625 uint64_t usage; 626 627 if (WARN_ON_ONCE(!man->bdev)) 628 return 0; 629 630 spin_lock(&man->bdev->lru_lock); 631 usage = man->usage; 632 spin_unlock(&man->bdev->lru_lock); 633 return usage; 634 } 635 EXPORT_SYMBOL(ttm_resource_manager_usage); 636 637 /** 638 * ttm_resource_manager_debug 639 * 640 * @man: manager type to dump. 641 * @p: printer to use for debug. 642 */ 643 void ttm_resource_manager_debug(struct ttm_resource_manager *man, 644 struct drm_printer *p) 645 { 646 drm_printf(p, " use_type: %d\n", man->use_type); 647 drm_printf(p, " use_tt: %d\n", man->use_tt); 648 drm_printf(p, " size: %llu\n", man->size); 649 drm_printf(p, " usage: %llu\n", ttm_resource_manager_usage(man)); 650 if (man->func->debug) 651 man->func->debug(man, p); 652 } 653 EXPORT_SYMBOL(ttm_resource_manager_debug); 654 655 static void 656 ttm_resource_cursor_check_bulk(struct ttm_resource_cursor *cursor, 657 struct ttm_lru_item *next_lru) 658 { 659 struct ttm_resource *next = ttm_lru_item_to_res(next_lru); 660 struct ttm_lru_bulk_move *bulk; 661 662 lockdep_assert_held(&cursor->man->bdev->lru_lock); 663 664 bulk = next->bo->bulk_move; 665 666 if (cursor->bulk != bulk) { 667 if (bulk) { 668 list_move_tail(&cursor->bulk_link, &bulk->cursor_list); 669 cursor->mem_type = next->mem_type; 670 } else { 671 list_del_init(&cursor->bulk_link); 672 } 673 cursor->bulk = bulk; 674 } 675 } 676 677 /** 678 * ttm_resource_manager_first() - Start iterating over the resources 679 * of a resource manager 680 * @cursor: cursor to record the position 681 * 682 * Initializes the cursor and starts iterating. When done iterating, 683 * the caller must explicitly call ttm_resource_cursor_fini(). 684 * 685 * Return: The first resource from the resource manager. 686 */ 687 struct ttm_resource * 688 ttm_resource_manager_first(struct ttm_resource_cursor *cursor) 689 { 690 struct ttm_resource_manager *man = cursor->man; 691 692 if (WARN_ON_ONCE(!man)) 693 return NULL; 694 695 lockdep_assert_held(&man->bdev->lru_lock); 696 697 list_move(&cursor->hitch.link, &man->lru[cursor->priority]); 698 return ttm_resource_manager_next(cursor); 699 } 700 701 /** 702 * ttm_resource_manager_next() - Continue iterating over the resource manager 703 * resources 704 * @cursor: cursor to record the position 705 * 706 * Return: the next resource from the resource manager. 707 */ 708 struct ttm_resource * 709 ttm_resource_manager_next(struct ttm_resource_cursor *cursor) 710 { 711 struct ttm_resource_manager *man = cursor->man; 712 struct ttm_lru_item *lru; 713 714 lockdep_assert_held(&man->bdev->lru_lock); 715 716 for (;;) { 717 lru = &cursor->hitch; 718 list_for_each_entry_continue(lru, &man->lru[cursor->priority], link) { 719 if (ttm_lru_item_is_res(lru)) { 720 ttm_resource_cursor_check_bulk(cursor, lru); 721 list_move(&cursor->hitch.link, &lru->link); 722 return ttm_lru_item_to_res(lru); 723 } 724 } 725 726 if (++cursor->priority >= TTM_MAX_BO_PRIORITY) 727 break; 728 729 list_move(&cursor->hitch.link, &man->lru[cursor->priority]); 730 ttm_resource_cursor_clear_bulk(cursor); 731 } 732 733 return NULL; 734 } 735 736 /** 737 * ttm_lru_first_res_or_null() - Return the first resource on an lru list 738 * @head: The list head of the lru list. 739 * 740 * Return: Pointer to the first resource on the lru list or NULL if 741 * there is none. 742 */ 743 struct ttm_resource *ttm_lru_first_res_or_null(struct list_head *head) 744 { 745 struct ttm_lru_item *lru; 746 747 list_for_each_entry(lru, head, link) { 748 if (ttm_lru_item_is_res(lru)) 749 return ttm_lru_item_to_res(lru); 750 } 751 752 return NULL; 753 } 754 755 static void ttm_kmap_iter_iomap_map_local(struct ttm_kmap_iter *iter, 756 struct iosys_map *dmap, 757 pgoff_t i) 758 { 759 struct ttm_kmap_iter_iomap *iter_io = 760 container_of(iter, typeof(*iter_io), base); 761 void __iomem *addr; 762 763 retry: 764 while (i >= iter_io->cache.end) { 765 iter_io->cache.sg = iter_io->cache.sg ? 766 sg_next(iter_io->cache.sg) : iter_io->st->sgl; 767 iter_io->cache.i = iter_io->cache.end; 768 iter_io->cache.end += sg_dma_len(iter_io->cache.sg) >> 769 PAGE_SHIFT; 770 iter_io->cache.offs = sg_dma_address(iter_io->cache.sg) - 771 iter_io->start; 772 } 773 774 if (i < iter_io->cache.i) { 775 iter_io->cache.end = 0; 776 iter_io->cache.sg = NULL; 777 goto retry; 778 } 779 780 addr = io_mapping_map_local_wc(iter_io->iomap, iter_io->cache.offs + 781 (((resource_size_t)i - iter_io->cache.i) 782 << PAGE_SHIFT)); 783 iosys_map_set_vaddr_iomem(dmap, addr); 784 } 785 786 static void ttm_kmap_iter_iomap_unmap_local(struct ttm_kmap_iter *iter, 787 struct iosys_map *map) 788 { 789 io_mapping_unmap_local(map->vaddr_iomem); 790 } 791 792 static const struct ttm_kmap_iter_ops ttm_kmap_iter_io_ops = { 793 .map_local = ttm_kmap_iter_iomap_map_local, 794 .unmap_local = ttm_kmap_iter_iomap_unmap_local, 795 .maps_tt = false, 796 }; 797 798 /** 799 * ttm_kmap_iter_iomap_init - Initialize a struct ttm_kmap_iter_iomap 800 * @iter_io: The struct ttm_kmap_iter_iomap to initialize. 801 * @iomap: The struct io_mapping representing the underlying linear io_memory. 802 * @st: sg_table into @iomap, representing the memory of the struct 803 * ttm_resource. 804 * @start: Offset that needs to be subtracted from @st to make 805 * sg_dma_address(st->sgl) - @start == 0 for @iomap start. 806 * 807 * Return: Pointer to the embedded struct ttm_kmap_iter. 808 */ 809 struct ttm_kmap_iter * 810 ttm_kmap_iter_iomap_init(struct ttm_kmap_iter_iomap *iter_io, 811 struct io_mapping *iomap, 812 struct sg_table *st, 813 resource_size_t start) 814 { 815 iter_io->base.ops = &ttm_kmap_iter_io_ops; 816 iter_io->iomap = iomap; 817 iter_io->st = st; 818 iter_io->start = start; 819 memset(&iter_io->cache, 0, sizeof(iter_io->cache)); 820 821 return &iter_io->base; 822 } 823 EXPORT_SYMBOL(ttm_kmap_iter_iomap_init); 824 825 /** 826 * DOC: Linear io iterator 827 * 828 * This code should die in the not too near future. Best would be if we could 829 * make io-mapping use memremap for all io memory, and have memremap 830 * implement a kmap_local functionality. We could then strip a huge amount of 831 * code. These linear io iterators are implemented to mimic old functionality, 832 * and they don't use kmap_local semantics at all internally. Rather ioremap or 833 * friends, and at least on 32-bit they add global TLB flushes and points 834 * of failure. 835 */ 836 837 static void ttm_kmap_iter_linear_io_map_local(struct ttm_kmap_iter *iter, 838 struct iosys_map *dmap, 839 pgoff_t i) 840 { 841 struct ttm_kmap_iter_linear_io *iter_io = 842 container_of(iter, typeof(*iter_io), base); 843 844 *dmap = iter_io->dmap; 845 iosys_map_incr(dmap, i * PAGE_SIZE); 846 } 847 848 static const struct ttm_kmap_iter_ops ttm_kmap_iter_linear_io_ops = { 849 .map_local = ttm_kmap_iter_linear_io_map_local, 850 .maps_tt = false, 851 }; 852 853 /** 854 * ttm_kmap_iter_linear_io_init - Initialize an iterator for linear io memory 855 * @iter_io: The iterator to initialize 856 * @bdev: The TTM device 857 * @mem: The ttm resource representing the iomap. 858 * 859 * This function is for internal TTM use only. It sets up a memcpy kmap iterator 860 * pointing at a linear chunk of io memory. 861 * 862 * Return: A pointer to the embedded struct ttm_kmap_iter or error pointer on 863 * failure. 864 */ 865 struct ttm_kmap_iter * 866 ttm_kmap_iter_linear_io_init(struct ttm_kmap_iter_linear_io *iter_io, 867 struct ttm_device *bdev, 868 struct ttm_resource *mem) 869 { 870 int ret; 871 872 ret = ttm_mem_io_reserve(bdev, mem); 873 if (ret) 874 goto out_err; 875 if (!mem->bus.is_iomem) { 876 ret = -EINVAL; 877 goto out_io_free; 878 } 879 880 if (mem->bus.addr) { 881 iosys_map_set_vaddr(&iter_io->dmap, mem->bus.addr); 882 iter_io->needs_unmap = false; 883 } else { 884 iter_io->needs_unmap = true; 885 memset(&iter_io->dmap, 0, sizeof(iter_io->dmap)); 886 if (mem->bus.caching == ttm_write_combined) 887 iosys_map_set_vaddr_iomem(&iter_io->dmap, 888 ioremap_wc(mem->bus.offset, 889 mem->size)); 890 else if (mem->bus.caching == ttm_cached) 891 iosys_map_set_vaddr(&iter_io->dmap, 892 memremap(mem->bus.offset, mem->size, 893 MEMREMAP_WB | 894 MEMREMAP_WT | 895 MEMREMAP_WC)); 896 897 /* If uncached requested or if mapping cached or wc failed */ 898 if (iosys_map_is_null(&iter_io->dmap)) 899 iosys_map_set_vaddr_iomem(&iter_io->dmap, 900 ioremap(mem->bus.offset, 901 mem->size)); 902 903 if (iosys_map_is_null(&iter_io->dmap)) { 904 ret = -ENOMEM; 905 goto out_io_free; 906 } 907 } 908 909 iter_io->base.ops = &ttm_kmap_iter_linear_io_ops; 910 return &iter_io->base; 911 912 out_io_free: 913 ttm_mem_io_free(bdev, mem); 914 out_err: 915 return ERR_PTR(ret); 916 } 917 918 /** 919 * ttm_kmap_iter_linear_io_fini - Clean up an iterator for linear io memory 920 * @iter_io: The iterator to finalize 921 * @bdev: The TTM device 922 * @mem: The ttm resource representing the iomap. 923 * 924 * This function is for internal TTM use only. It cleans up a memcpy kmap 925 * iterator initialized by ttm_kmap_iter_linear_io_init. 926 */ 927 void 928 ttm_kmap_iter_linear_io_fini(struct ttm_kmap_iter_linear_io *iter_io, 929 struct ttm_device *bdev, 930 struct ttm_resource *mem) 931 { 932 if (iter_io->needs_unmap && iosys_map_is_set(&iter_io->dmap)) { 933 if (iter_io->dmap.is_iomem) 934 iounmap(iter_io->dmap.vaddr_iomem); 935 else 936 memunmap(iter_io->dmap.vaddr); 937 } 938 939 ttm_mem_io_free(bdev, mem); 940 } 941 942 #if defined(CONFIG_DEBUG_FS) 943 944 static int ttm_resource_manager_show(struct seq_file *m, void *unused) 945 { 946 struct ttm_resource_manager *man = 947 (struct ttm_resource_manager *)m->private; 948 struct drm_printer p = drm_seq_file_printer(m); 949 ttm_resource_manager_debug(man, &p); 950 return 0; 951 } 952 DEFINE_SHOW_ATTRIBUTE(ttm_resource_manager); 953 954 #endif 955 956 /** 957 * ttm_resource_manager_create_debugfs - Create debugfs entry for specified 958 * resource manager. 959 * @man: The TTM resource manager for which the debugfs stats file to be created 960 * @parent: debugfs directory in which the file will reside 961 * @name: The filename to create. 962 * 963 * This function sets up a debugfs file that can be used to look 964 * at debug statistics of the specified ttm_resource_manager. 965 */ 966 void ttm_resource_manager_create_debugfs(struct ttm_resource_manager *man, 967 struct dentry *parent, 968 const char *name) 969 { 970 #if defined(CONFIG_DEBUG_FS) 971 debugfs_create_file(name, 0444, parent, man, &ttm_resource_manager_fops); 972 #endif 973 } 974 EXPORT_SYMBOL(ttm_resource_manager_create_debugfs); 975 976 /** 977 * ttm_resource_manager_dmem_reclaim() - dmem cgroup reclaim callback for TTM 978 * resource managers. 979 * @pool: The dmem cgroup pool state for the cgroup being reclaimed. 980 * @target_bytes: Number of bytes to try to free. 981 * @priv: The &ttm_resource_manager pointer, passed as @init.reclaim_priv to 982 * dmem_cgroup_register_region(). 983 * 984 * Drivers should use this as the @reclaim member of their own 985 * &struct dmem_cgroup_ops, with the &ttm_resource_manager pointer as 986 * @init.reclaim_priv. 987 * 988 * Return: 0 if some memory was freed, -ENOSPC if nothing was freed, or 989 * another negative error code on fatal failure. 990 */ 991 int ttm_resource_manager_dmem_reclaim(struct dmem_cgroup_pool_state *pool, 992 u64 target_bytes, void *priv) 993 { 994 struct ttm_resource_manager *man = priv; 995 struct ttm_operation_ctx ctx = { .interruptible = true }; 996 s64 freed; 997 998 freed = ttm_bo_evict_cgroup(man->bdev, man, pool, target_bytes, &ctx); 999 if (freed < 0) 1000 return freed; 1001 1002 return freed > 0 ? 0 : -ENOSPC; 1003 } 1004 EXPORT_SYMBOL(ttm_resource_manager_dmem_reclaim); 1005 1006 /** 1007 * ttm_resource_manager_set_dmem_region() - Associate a dmem cgroup region with a 1008 * resource manager. 1009 * @man: The resource manager. 1010 * @region: The dmem cgroup region to associate, may be NULL or IS_ERR(). 1011 * 1012 * When @region is valid, stores it in @man->cg so that TTM can look up the 1013 * associated pool during charging and eviction-target selection. When 1014 * @region is %NULL, clears @man->cg to detach the region before teardown. 1015 * An IS_ERR() @region is ignored, leaving @man->cg unchanged. 1016 * The reclaim callback must be wired up using ttm_resource_manager_dmem_reclaim() 1017 * in the driver's own &struct dmem_cgroup_ops, with the manager pointer as 1018 * @init.reclaim_priv. 1019 */ 1020 void ttm_resource_manager_set_dmem_region(struct ttm_resource_manager *man, 1021 struct dmem_cgroup_region *region) 1022 { 1023 if (!IS_ERR(region)) 1024 man->cg = region; 1025 } 1026 EXPORT_SYMBOL(ttm_resource_manager_set_dmem_region); 1027