Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/ttm: add BO priorities for the LRUs

This way the driver can specify a priority for a BO which has the effect that
a BO is only evicted when all other BOs with a lower priority are evicted
first.

Reviewed-by: Sinclair Yeh <syeh@vmware.com>
Signed-off-by: Christian König <christian.koenig@amd.com>
Reviewed-by: Roger.He <Hongbo.He@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>

authored by

Christian König and committed by
Alex Deucher
cf6c467d 2ee7fc92

+52 -27
+2 -2
drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
··· 1166 1166 struct amdgpu_mman_lru *lru = &adev->mman.log2_size[i]; 1167 1167 1168 1168 for (j = 0; j < TTM_NUM_MEM_TYPES; ++j) 1169 - lru->lru[j] = &adev->mman.bdev.man[j].lru; 1170 - lru->swap_lru = &adev->mman.bdev.glob->swap_lru; 1169 + lru->lru[j] = &adev->mman.bdev.man[j].lru[0]; 1170 + lru->swap_lru = &adev->mman.bdev.glob->swap_lru[0]; 1171 1171 } 1172 1172 1173 1173 for (j = 0; j < TTM_NUM_MEM_TYPES; ++j)
+44 -23
drivers/gpu/drm/ttm/ttm_bo.c
··· 242 242 243 243 struct list_head *ttm_bo_default_lru_tail(struct ttm_buffer_object *bo) 244 244 { 245 - return bo->bdev->man[bo->mem.mem_type].lru.prev; 245 + return bo->bdev->man[bo->mem.mem_type].lru[bo->priority].prev; 246 246 } 247 247 EXPORT_SYMBOL(ttm_bo_default_lru_tail); 248 248 249 249 struct list_head *ttm_bo_default_swap_lru_tail(struct ttm_buffer_object *bo) 250 250 { 251 - return bo->glob->swap_lru.prev; 251 + return bo->glob->swap_lru[bo->priority].prev; 252 252 } 253 253 EXPORT_SYMBOL(ttm_bo_default_swap_lru_tail); 254 254 ··· 741 741 struct ttm_mem_type_manager *man = &bdev->man[mem_type]; 742 742 struct ttm_buffer_object *bo; 743 743 int ret = -EBUSY, put_count; 744 + unsigned i; 744 745 745 746 spin_lock(&glob->lru_lock); 746 - list_for_each_entry(bo, &man->lru, lru) { 747 - ret = __ttm_bo_reserve(bo, false, true, NULL); 748 - if (ret) 749 - continue; 747 + for (i = 0; i < TTM_MAX_BO_PRIORITY; ++i) { 748 + list_for_each_entry(bo, &man->lru[i], lru) { 749 + ret = __ttm_bo_reserve(bo, false, true, NULL); 750 + if (ret) 751 + continue; 750 752 751 - if (place && !bdev->driver->eviction_valuable(bo, place)) { 752 - __ttm_bo_unreserve(bo); 753 - ret = -EBUSY; 754 - continue; 753 + if (place && !bdev->driver->eviction_valuable(bo, 754 + place)) { 755 + __ttm_bo_unreserve(bo); 756 + ret = -EBUSY; 757 + continue; 758 + } 759 + 760 + break; 755 761 } 756 762 757 - break; 763 + if (!ret) 764 + break; 758 765 } 759 766 760 767 if (ret) { ··· 1204 1197 } 1205 1198 atomic_inc(&bo->glob->bo_count); 1206 1199 drm_vma_node_reset(&bo->vma_node); 1200 + bo->priority = 0; 1207 1201 1208 1202 /* 1209 1203 * For ttm_bo_type_device buffers, allocate ··· 1305 1297 struct ttm_bo_global *glob = bdev->glob; 1306 1298 struct dma_fence *fence; 1307 1299 int ret; 1300 + unsigned i; 1308 1301 1309 1302 /* 1310 1303 * Can't use standard list traversal since we're unlocking. 1311 1304 */ 1312 1305 1313 1306 spin_lock(&glob->lru_lock); 1314 - while (!list_empty(&man->lru)) { 1315 - spin_unlock(&glob->lru_lock); 1316 - ret = ttm_mem_evict_first(bdev, mem_type, NULL, false, false); 1317 - if (ret) 1318 - return ret; 1319 - spin_lock(&glob->lru_lock); 1307 + for (i = 0; i < TTM_MAX_BO_PRIORITY; ++i) { 1308 + while (!list_empty(&man->lru[i])) { 1309 + spin_unlock(&glob->lru_lock); 1310 + ret = ttm_mem_evict_first(bdev, mem_type, NULL, false, false); 1311 + if (ret) 1312 + return ret; 1313 + spin_lock(&glob->lru_lock); 1314 + } 1320 1315 } 1321 1316 spin_unlock(&glob->lru_lock); 1322 1317 ··· 1396 1385 { 1397 1386 int ret = -EINVAL; 1398 1387 struct ttm_mem_type_manager *man; 1388 + unsigned i; 1399 1389 1400 1390 BUG_ON(type >= TTM_NUM_MEM_TYPES); 1401 1391 man = &bdev->man[type]; ··· 1422 1410 man->use_type = true; 1423 1411 man->size = p_size; 1424 1412 1425 - INIT_LIST_HEAD(&man->lru); 1413 + for (i = 0; i < TTM_MAX_BO_PRIORITY; ++i) 1414 + INIT_LIST_HEAD(&man->lru[i]); 1426 1415 man->move = NULL; 1427 1416 1428 1417 return 0; ··· 1455 1442 container_of(ref, struct ttm_bo_global_ref, ref); 1456 1443 struct ttm_bo_global *glob = ref->object; 1457 1444 int ret; 1445 + unsigned i; 1458 1446 1459 1447 mutex_init(&glob->device_list_mutex); 1460 1448 spin_lock_init(&glob->lru_lock); ··· 1467 1453 goto out_no_drp; 1468 1454 } 1469 1455 1470 - INIT_LIST_HEAD(&glob->swap_lru); 1456 + for (i = 0; i < TTM_MAX_BO_PRIORITY; ++i) 1457 + INIT_LIST_HEAD(&glob->swap_lru[i]); 1471 1458 INIT_LIST_HEAD(&glob->device_list); 1472 1459 1473 1460 ttm_mem_init_shrink(&glob->shrink, ttm_bo_swapout); ··· 1527 1512 if (list_empty(&bdev->ddestroy)) 1528 1513 TTM_DEBUG("Delayed destroy list was clean\n"); 1529 1514 1530 - if (list_empty(&bdev->man[0].lru)) 1531 - TTM_DEBUG("Swap list was clean\n"); 1515 + for (i = 0; i < TTM_MAX_BO_PRIORITY; ++i) 1516 + if (list_empty(&bdev->man[0].lru[0])) 1517 + TTM_DEBUG("Swap list %d was clean\n", i); 1532 1518 spin_unlock(&glob->lru_lock); 1533 1519 1534 1520 drm_vma_offset_manager_destroy(&bdev->vma_manager); ··· 1681 1665 int ret = -EBUSY; 1682 1666 int put_count; 1683 1667 uint32_t swap_placement = (TTM_PL_FLAG_CACHED | TTM_PL_FLAG_SYSTEM); 1668 + unsigned i; 1684 1669 1685 1670 spin_lock(&glob->lru_lock); 1686 - list_for_each_entry(bo, &glob->swap_lru, swap) { 1687 - ret = __ttm_bo_reserve(bo, false, true, NULL); 1671 + for (i = 0; i < TTM_MAX_BO_PRIORITY; ++i) { 1672 + list_for_each_entry(bo, &glob->swap_lru[i], swap) { 1673 + ret = __ttm_bo_reserve(bo, false, true, NULL); 1674 + if (!ret) 1675 + break; 1676 + } 1688 1677 if (!ret) 1689 1678 break; 1690 1679 }
+2
include/drm/ttm/ttm_bo_api.h
··· 215 215 216 216 struct drm_vma_offset_node vma_node; 217 217 218 + unsigned priority; 219 + 218 220 /** 219 221 * Special members that are protected by the reserve lock 220 222 * and the bo::lock when written to. Can be read with
+4 -2
include/drm/ttm/ttm_bo_driver.h
··· 42 42 #include <linux/spinlock.h> 43 43 #include <linux/reservation.h> 44 44 45 + #define TTM_MAX_BO_PRIORITY 16 46 + 45 47 struct ttm_backend_func { 46 48 /** 47 49 * struct ttm_backend_func member bind ··· 300 298 * Protected by the global->lru_lock. 301 299 */ 302 300 303 - struct list_head lru; 301 + struct list_head lru[TTM_MAX_BO_PRIORITY]; 304 302 305 303 /* 306 304 * Protected by @move_lock. ··· 520 518 /** 521 519 * Protected by the lru_lock. 522 520 */ 523 - struct list_head swap_lru; 521 + struct list_head swap_lru[TTM_MAX_BO_PRIORITY]; 524 522 525 523 /** 526 524 * Internal protection.