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 int ttm_resource_alloc(struct ttm_buffer_object *bo, 390 const struct ttm_place *place, 391 struct ttm_resource **res_ptr, 392 struct dmem_cgroup_pool_state **ret_limit_pool) 393 { 394 struct ttm_resource_manager *man = 395 ttm_manager_type(bo->bdev, place->mem_type); 396 struct dmem_cgroup_pool_state *pool = NULL; 397 int ret; 398 399 if (man->cg) { 400 ret = dmem_cgroup_try_charge(man->cg, bo->base.size, &pool, ret_limit_pool); 401 if (ret) { 402 if (ret == -EAGAIN) 403 ret = -ENOSPC; 404 return ret; 405 } 406 } 407 408 ret = man->func->alloc(man, bo, place, res_ptr); 409 if (ret) { 410 if (pool) 411 dmem_cgroup_uncharge(pool, bo->base.size); 412 return ret; 413 } 414 415 (*res_ptr)->css = pool; 416 417 spin_lock(&bo->bdev->lru_lock); 418 ttm_resource_add_bulk_move(*res_ptr, bo); 419 spin_unlock(&bo->bdev->lru_lock); 420 return 0; 421 } 422 EXPORT_SYMBOL_FOR_TESTS_ONLY(ttm_resource_alloc); 423 424 void ttm_resource_free(struct ttm_buffer_object *bo, struct ttm_resource **res) 425 { 426 struct ttm_resource_manager *man; 427 struct dmem_cgroup_pool_state *pool; 428 429 if (!*res) 430 return; 431 432 spin_lock(&bo->bdev->lru_lock); 433 ttm_resource_del_bulk_move(*res, bo); 434 spin_unlock(&bo->bdev->lru_lock); 435 436 pool = (*res)->css; 437 man = ttm_manager_type(bo->bdev, (*res)->mem_type); 438 man->func->free(man, *res); 439 *res = NULL; 440 if (man->cg) 441 dmem_cgroup_uncharge(pool, bo->base.size); 442 } 443 EXPORT_SYMBOL(ttm_resource_free); 444 445 /** 446 * ttm_resource_intersects - test for intersection 447 * 448 * @bdev: TTM device structure 449 * @res: The resource to test 450 * @place: The placement to test 451 * @size: How many bytes the new allocation needs. 452 * 453 * Test if @res intersects with @place and @size. Used for testing if evictions 454 * are valuable or not. 455 * 456 * Returns true if the res placement intersects with @place and @size. 457 */ 458 bool ttm_resource_intersects(struct ttm_device *bdev, 459 struct ttm_resource *res, 460 const struct ttm_place *place, 461 size_t size) 462 { 463 struct ttm_resource_manager *man; 464 465 man = ttm_manager_type(bdev, res->mem_type); 466 if (!place || !man->func->intersects) 467 return true; 468 469 return man->func->intersects(man, res, place, size); 470 } 471 472 /** 473 * ttm_resource_compatible - check if resource is compatible with placement 474 * 475 * @res: the resource to check 476 * @placement: the placement to check against 477 * @evicting: true if the caller is doing evictions 478 * 479 * Returns true if the placement is compatible. 480 */ 481 bool ttm_resource_compatible(struct ttm_resource *res, 482 struct ttm_placement *placement, 483 bool evicting) 484 { 485 struct ttm_buffer_object *bo = res->bo; 486 struct ttm_device *bdev = bo->bdev; 487 unsigned i; 488 489 if (res->placement & TTM_PL_FLAG_TEMPORARY) 490 return false; 491 492 for (i = 0; i < placement->num_placement; i++) { 493 const struct ttm_place *place = &placement->placement[i]; 494 struct ttm_resource_manager *man; 495 496 if (res->mem_type != place->mem_type) 497 continue; 498 499 if (place->flags & (evicting ? TTM_PL_FLAG_DESIRED : 500 TTM_PL_FLAG_FALLBACK)) 501 continue; 502 503 if (place->flags & TTM_PL_FLAG_CONTIGUOUS && 504 !(res->placement & TTM_PL_FLAG_CONTIGUOUS)) 505 continue; 506 507 man = ttm_manager_type(bdev, res->mem_type); 508 if (man->func->compatible && 509 !man->func->compatible(man, res, place, bo->base.size)) 510 continue; 511 512 return true; 513 } 514 return false; 515 } 516 517 void ttm_resource_set_bo(struct ttm_resource *res, 518 struct ttm_buffer_object *bo) 519 { 520 spin_lock(&bo->bdev->lru_lock); 521 res->bo = bo; 522 spin_unlock(&bo->bdev->lru_lock); 523 } 524 525 /** 526 * ttm_resource_manager_init 527 * 528 * @man: memory manager object to init 529 * @bdev: ttm device this manager belongs to 530 * @size: size of managed resources in arbitrary units 531 * 532 * Initialize core parts of a manager object. 533 */ 534 void ttm_resource_manager_init(struct ttm_resource_manager *man, 535 struct ttm_device *bdev, 536 uint64_t size) 537 { 538 unsigned i; 539 540 man->bdev = bdev; 541 man->size = size; 542 man->usage = 0; 543 544 for (i = 0; i < TTM_MAX_BO_PRIORITY; ++i) 545 INIT_LIST_HEAD(&man->lru[i]); 546 spin_lock_init(&man->eviction_lock); 547 for (i = 0; i < TTM_NUM_MOVE_FENCES; i++) 548 man->eviction_fences[i] = NULL; 549 } 550 EXPORT_SYMBOL(ttm_resource_manager_init); 551 552 /* 553 * ttm_resource_manager_evict_all 554 * 555 * @bdev: device to use 556 * @man: manager to use 557 * 558 * Evict all the objects out of a memory manager until it is empty. 559 * Part of memory manager cleanup sequence. 560 */ 561 int ttm_resource_manager_evict_all(struct ttm_device *bdev, 562 struct ttm_resource_manager *man) 563 { 564 struct ttm_operation_ctx ctx = { }; 565 struct dma_fence *fence; 566 int ret, i; 567 568 do { 569 ret = ttm_bo_evict_first(bdev, man, &ctx); 570 cond_resched(); 571 } while (!ret); 572 573 if (ret && ret != -ENOENT) 574 return ret; 575 576 ret = 0; 577 578 spin_lock(&man->eviction_lock); 579 for (i = 0; i < TTM_NUM_MOVE_FENCES; i++) { 580 fence = man->eviction_fences[i]; 581 if (fence && !dma_fence_is_signaled(fence)) { 582 dma_fence_get(fence); 583 spin_unlock(&man->eviction_lock); 584 ret = dma_fence_wait(fence, false); 585 dma_fence_put(fence); 586 if (ret) 587 return ret; 588 spin_lock(&man->eviction_lock); 589 } 590 } 591 spin_unlock(&man->eviction_lock); 592 593 return ret; 594 } 595 EXPORT_SYMBOL(ttm_resource_manager_evict_all); 596 597 /** 598 * ttm_resource_manager_usage 599 * 600 * @man: A memory manager object. 601 * 602 * Return how many resources are currently used. 603 */ 604 uint64_t ttm_resource_manager_usage(struct ttm_resource_manager *man) 605 { 606 uint64_t usage; 607 608 if (WARN_ON_ONCE(!man->bdev)) 609 return 0; 610 611 spin_lock(&man->bdev->lru_lock); 612 usage = man->usage; 613 spin_unlock(&man->bdev->lru_lock); 614 return usage; 615 } 616 EXPORT_SYMBOL(ttm_resource_manager_usage); 617 618 /** 619 * ttm_resource_manager_debug 620 * 621 * @man: manager type to dump. 622 * @p: printer to use for debug. 623 */ 624 void ttm_resource_manager_debug(struct ttm_resource_manager *man, 625 struct drm_printer *p) 626 { 627 drm_printf(p, " use_type: %d\n", man->use_type); 628 drm_printf(p, " use_tt: %d\n", man->use_tt); 629 drm_printf(p, " size: %llu\n", man->size); 630 drm_printf(p, " usage: %llu\n", ttm_resource_manager_usage(man)); 631 if (man->func->debug) 632 man->func->debug(man, p); 633 } 634 EXPORT_SYMBOL(ttm_resource_manager_debug); 635 636 static void 637 ttm_resource_cursor_check_bulk(struct ttm_resource_cursor *cursor, 638 struct ttm_lru_item *next_lru) 639 { 640 struct ttm_resource *next = ttm_lru_item_to_res(next_lru); 641 struct ttm_lru_bulk_move *bulk; 642 643 lockdep_assert_held(&cursor->man->bdev->lru_lock); 644 645 bulk = next->bo->bulk_move; 646 647 if (cursor->bulk != bulk) { 648 if (bulk) { 649 list_move_tail(&cursor->bulk_link, &bulk->cursor_list); 650 cursor->mem_type = next->mem_type; 651 } else { 652 list_del_init(&cursor->bulk_link); 653 } 654 cursor->bulk = bulk; 655 } 656 } 657 658 /** 659 * ttm_resource_manager_first() - Start iterating over the resources 660 * of a resource manager 661 * @cursor: cursor to record the position 662 * 663 * Initializes the cursor and starts iterating. When done iterating, 664 * the caller must explicitly call ttm_resource_cursor_fini(). 665 * 666 * Return: The first resource from the resource manager. 667 */ 668 struct ttm_resource * 669 ttm_resource_manager_first(struct ttm_resource_cursor *cursor) 670 { 671 struct ttm_resource_manager *man = cursor->man; 672 673 if (WARN_ON_ONCE(!man)) 674 return NULL; 675 676 lockdep_assert_held(&man->bdev->lru_lock); 677 678 list_move(&cursor->hitch.link, &man->lru[cursor->priority]); 679 return ttm_resource_manager_next(cursor); 680 } 681 682 /** 683 * ttm_resource_manager_next() - Continue iterating over the resource manager 684 * resources 685 * @cursor: cursor to record the position 686 * 687 * Return: the next resource from the resource manager. 688 */ 689 struct ttm_resource * 690 ttm_resource_manager_next(struct ttm_resource_cursor *cursor) 691 { 692 struct ttm_resource_manager *man = cursor->man; 693 struct ttm_lru_item *lru; 694 695 lockdep_assert_held(&man->bdev->lru_lock); 696 697 for (;;) { 698 lru = &cursor->hitch; 699 list_for_each_entry_continue(lru, &man->lru[cursor->priority], link) { 700 if (ttm_lru_item_is_res(lru)) { 701 ttm_resource_cursor_check_bulk(cursor, lru); 702 list_move(&cursor->hitch.link, &lru->link); 703 return ttm_lru_item_to_res(lru); 704 } 705 } 706 707 if (++cursor->priority >= TTM_MAX_BO_PRIORITY) 708 break; 709 710 list_move(&cursor->hitch.link, &man->lru[cursor->priority]); 711 ttm_resource_cursor_clear_bulk(cursor); 712 } 713 714 return NULL; 715 } 716 717 /** 718 * ttm_lru_first_res_or_null() - Return the first resource on an lru list 719 * @head: The list head of the lru list. 720 * 721 * Return: Pointer to the first resource on the lru list or NULL if 722 * there is none. 723 */ 724 struct ttm_resource *ttm_lru_first_res_or_null(struct list_head *head) 725 { 726 struct ttm_lru_item *lru; 727 728 list_for_each_entry(lru, head, link) { 729 if (ttm_lru_item_is_res(lru)) 730 return ttm_lru_item_to_res(lru); 731 } 732 733 return NULL; 734 } 735 736 static void ttm_kmap_iter_iomap_map_local(struct ttm_kmap_iter *iter, 737 struct iosys_map *dmap, 738 pgoff_t i) 739 { 740 struct ttm_kmap_iter_iomap *iter_io = 741 container_of(iter, typeof(*iter_io), base); 742 void __iomem *addr; 743 744 retry: 745 while (i >= iter_io->cache.end) { 746 iter_io->cache.sg = iter_io->cache.sg ? 747 sg_next(iter_io->cache.sg) : iter_io->st->sgl; 748 iter_io->cache.i = iter_io->cache.end; 749 iter_io->cache.end += sg_dma_len(iter_io->cache.sg) >> 750 PAGE_SHIFT; 751 iter_io->cache.offs = sg_dma_address(iter_io->cache.sg) - 752 iter_io->start; 753 } 754 755 if (i < iter_io->cache.i) { 756 iter_io->cache.end = 0; 757 iter_io->cache.sg = NULL; 758 goto retry; 759 } 760 761 addr = io_mapping_map_local_wc(iter_io->iomap, iter_io->cache.offs + 762 (((resource_size_t)i - iter_io->cache.i) 763 << PAGE_SHIFT)); 764 iosys_map_set_vaddr_iomem(dmap, addr); 765 } 766 767 static void ttm_kmap_iter_iomap_unmap_local(struct ttm_kmap_iter *iter, 768 struct iosys_map *map) 769 { 770 io_mapping_unmap_local(map->vaddr_iomem); 771 } 772 773 static const struct ttm_kmap_iter_ops ttm_kmap_iter_io_ops = { 774 .map_local = ttm_kmap_iter_iomap_map_local, 775 .unmap_local = ttm_kmap_iter_iomap_unmap_local, 776 .maps_tt = false, 777 }; 778 779 /** 780 * ttm_kmap_iter_iomap_init - Initialize a struct ttm_kmap_iter_iomap 781 * @iter_io: The struct ttm_kmap_iter_iomap to initialize. 782 * @iomap: The struct io_mapping representing the underlying linear io_memory. 783 * @st: sg_table into @iomap, representing the memory of the struct 784 * ttm_resource. 785 * @start: Offset that needs to be subtracted from @st to make 786 * sg_dma_address(st->sgl) - @start == 0 for @iomap start. 787 * 788 * Return: Pointer to the embedded struct ttm_kmap_iter. 789 */ 790 struct ttm_kmap_iter * 791 ttm_kmap_iter_iomap_init(struct ttm_kmap_iter_iomap *iter_io, 792 struct io_mapping *iomap, 793 struct sg_table *st, 794 resource_size_t start) 795 { 796 iter_io->base.ops = &ttm_kmap_iter_io_ops; 797 iter_io->iomap = iomap; 798 iter_io->st = st; 799 iter_io->start = start; 800 memset(&iter_io->cache, 0, sizeof(iter_io->cache)); 801 802 return &iter_io->base; 803 } 804 EXPORT_SYMBOL(ttm_kmap_iter_iomap_init); 805 806 /** 807 * DOC: Linear io iterator 808 * 809 * This code should die in the not too near future. Best would be if we could 810 * make io-mapping use memremap for all io memory, and have memremap 811 * implement a kmap_local functionality. We could then strip a huge amount of 812 * code. These linear io iterators are implemented to mimic old functionality, 813 * and they don't use kmap_local semantics at all internally. Rather ioremap or 814 * friends, and at least on 32-bit they add global TLB flushes and points 815 * of failure. 816 */ 817 818 static void ttm_kmap_iter_linear_io_map_local(struct ttm_kmap_iter *iter, 819 struct iosys_map *dmap, 820 pgoff_t i) 821 { 822 struct ttm_kmap_iter_linear_io *iter_io = 823 container_of(iter, typeof(*iter_io), base); 824 825 *dmap = iter_io->dmap; 826 iosys_map_incr(dmap, i * PAGE_SIZE); 827 } 828 829 static const struct ttm_kmap_iter_ops ttm_kmap_iter_linear_io_ops = { 830 .map_local = ttm_kmap_iter_linear_io_map_local, 831 .maps_tt = false, 832 }; 833 834 /** 835 * ttm_kmap_iter_linear_io_init - Initialize an iterator for linear io memory 836 * @iter_io: The iterator to initialize 837 * @bdev: The TTM device 838 * @mem: The ttm resource representing the iomap. 839 * 840 * This function is for internal TTM use only. It sets up a memcpy kmap iterator 841 * pointing at a linear chunk of io memory. 842 * 843 * Return: A pointer to the embedded struct ttm_kmap_iter or error pointer on 844 * failure. 845 */ 846 struct ttm_kmap_iter * 847 ttm_kmap_iter_linear_io_init(struct ttm_kmap_iter_linear_io *iter_io, 848 struct ttm_device *bdev, 849 struct ttm_resource *mem) 850 { 851 int ret; 852 853 ret = ttm_mem_io_reserve(bdev, mem); 854 if (ret) 855 goto out_err; 856 if (!mem->bus.is_iomem) { 857 ret = -EINVAL; 858 goto out_io_free; 859 } 860 861 if (mem->bus.addr) { 862 iosys_map_set_vaddr(&iter_io->dmap, mem->bus.addr); 863 iter_io->needs_unmap = false; 864 } else { 865 iter_io->needs_unmap = true; 866 memset(&iter_io->dmap, 0, sizeof(iter_io->dmap)); 867 if (mem->bus.caching == ttm_write_combined) 868 iosys_map_set_vaddr_iomem(&iter_io->dmap, 869 ioremap_wc(mem->bus.offset, 870 mem->size)); 871 else if (mem->bus.caching == ttm_cached) 872 iosys_map_set_vaddr(&iter_io->dmap, 873 memremap(mem->bus.offset, mem->size, 874 MEMREMAP_WB | 875 MEMREMAP_WT | 876 MEMREMAP_WC)); 877 878 /* If uncached requested or if mapping cached or wc failed */ 879 if (iosys_map_is_null(&iter_io->dmap)) 880 iosys_map_set_vaddr_iomem(&iter_io->dmap, 881 ioremap(mem->bus.offset, 882 mem->size)); 883 884 if (iosys_map_is_null(&iter_io->dmap)) { 885 ret = -ENOMEM; 886 goto out_io_free; 887 } 888 } 889 890 iter_io->base.ops = &ttm_kmap_iter_linear_io_ops; 891 return &iter_io->base; 892 893 out_io_free: 894 ttm_mem_io_free(bdev, mem); 895 out_err: 896 return ERR_PTR(ret); 897 } 898 899 /** 900 * ttm_kmap_iter_linear_io_fini - Clean up an iterator for linear io memory 901 * @iter_io: The iterator to finalize 902 * @bdev: The TTM device 903 * @mem: The ttm resource representing the iomap. 904 * 905 * This function is for internal TTM use only. It cleans up a memcpy kmap 906 * iterator initialized by ttm_kmap_iter_linear_io_init. 907 */ 908 void 909 ttm_kmap_iter_linear_io_fini(struct ttm_kmap_iter_linear_io *iter_io, 910 struct ttm_device *bdev, 911 struct ttm_resource *mem) 912 { 913 if (iter_io->needs_unmap && iosys_map_is_set(&iter_io->dmap)) { 914 if (iter_io->dmap.is_iomem) 915 iounmap(iter_io->dmap.vaddr_iomem); 916 else 917 memunmap(iter_io->dmap.vaddr); 918 } 919 920 ttm_mem_io_free(bdev, mem); 921 } 922 923 #if defined(CONFIG_DEBUG_FS) 924 925 static int ttm_resource_manager_show(struct seq_file *m, void *unused) 926 { 927 struct ttm_resource_manager *man = 928 (struct ttm_resource_manager *)m->private; 929 struct drm_printer p = drm_seq_file_printer(m); 930 ttm_resource_manager_debug(man, &p); 931 return 0; 932 } 933 DEFINE_SHOW_ATTRIBUTE(ttm_resource_manager); 934 935 #endif 936 937 /** 938 * ttm_resource_manager_create_debugfs - Create debugfs entry for specified 939 * resource manager. 940 * @man: The TTM resource manager for which the debugfs stats file to be created 941 * @parent: debugfs directory in which the file will reside 942 * @name: The filename to create. 943 * 944 * This function sets up a debugfs file that can be used to look 945 * at debug statistics of the specified ttm_resource_manager. 946 */ 947 void ttm_resource_manager_create_debugfs(struct ttm_resource_manager *man, 948 struct dentry *parent, 949 const char *name) 950 { 951 #if defined(CONFIG_DEBUG_FS) 952 debugfs_create_file(name, 0444, parent, man, &ttm_resource_manager_fops); 953 #endif 954 } 955 EXPORT_SYMBOL(ttm_resource_manager_create_debugfs); 956