diff options
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c')
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 101 |
1 files changed, 90 insertions, 11 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c index f922e4356758..fa06b2a4645f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | |||
@@ -69,6 +69,12 @@ struct amdgpu_pte_update_params { | |||
69 | bool shadow; | 69 | bool shadow; |
70 | }; | 70 | }; |
71 | 71 | ||
72 | /* Helper to disable partial resident texture feature from a fence callback */ | ||
73 | struct amdgpu_prt_cb { | ||
74 | struct amdgpu_device *adev; | ||
75 | struct dma_fence_cb cb; | ||
76 | }; | ||
77 | |||
72 | /** | 78 | /** |
73 | * amdgpu_vm_num_pde - return the number of page directory entries | 79 | * amdgpu_vm_num_pde - return the number of page directory entries |
74 | * | 80 | * |
@@ -989,11 +995,8 @@ static int amdgpu_vm_bo_update_mapping(struct amdgpu_device *adev, | |||
989 | goto error_free; | 995 | goto error_free; |
990 | 996 | ||
991 | amdgpu_bo_fence(vm->page_directory, f, true); | 997 | amdgpu_bo_fence(vm->page_directory, f, true); |
992 | if (fence) { | 998 | dma_fence_put(*fence); |
993 | dma_fence_put(*fence); | 999 | *fence = f; |
994 | *fence = dma_fence_get(f); | ||
995 | } | ||
996 | dma_fence_put(f); | ||
997 | return 0; | 1000 | return 0; |
998 | 1001 | ||
999 | error_free: | 1002 | error_free: |
@@ -1177,6 +1180,61 @@ int amdgpu_vm_bo_update(struct amdgpu_device *adev, | |||
1177 | } | 1180 | } |
1178 | 1181 | ||
1179 | /** | 1182 | /** |
1183 | * amdgpu_vm_update_prt_state - update the global PRT state | ||
1184 | */ | ||
1185 | static void amdgpu_vm_update_prt_state(struct amdgpu_device *adev) | ||
1186 | { | ||
1187 | unsigned long flags; | ||
1188 | bool enable; | ||
1189 | |||
1190 | spin_lock_irqsave(&adev->vm_manager.prt_lock, flags); | ||
1191 | enable = !!atomic_read(&adev->vm_manager.num_prt_mappings); | ||
1192 | adev->gart.gart_funcs->set_prt(adev, enable); | ||
1193 | spin_unlock_irqrestore(&adev->vm_manager.prt_lock, flags); | ||
1194 | } | ||
1195 | |||
1196 | /** | ||
1197 | * amdgpu_vm_prt - callback for updating the PRT status | ||
1198 | */ | ||
1199 | static void amdgpu_vm_prt_cb(struct dma_fence *fence, struct dma_fence_cb *_cb) | ||
1200 | { | ||
1201 | struct amdgpu_prt_cb *cb = container_of(_cb, struct amdgpu_prt_cb, cb); | ||
1202 | |||
1203 | amdgpu_vm_update_prt_state(cb->adev); | ||
1204 | kfree(cb); | ||
1205 | } | ||
1206 | |||
1207 | /** | ||
1208 | * amdgpu_vm_free_mapping - free a mapping | ||
1209 | * | ||
1210 | * @adev: amdgpu_device pointer | ||
1211 | * @vm: requested vm | ||
1212 | * @mapping: mapping to be freed | ||
1213 | * @fence: fence of the unmap operation | ||
1214 | * | ||
1215 | * Free a mapping and make sure we decrease the PRT usage count if applicable. | ||
1216 | */ | ||
1217 | static void amdgpu_vm_free_mapping(struct amdgpu_device *adev, | ||
1218 | struct amdgpu_vm *vm, | ||
1219 | struct amdgpu_bo_va_mapping *mapping, | ||
1220 | struct dma_fence *fence) | ||
1221 | { | ||
1222 | if ((mapping->flags & AMDGPU_PTE_PRT) && | ||
1223 | atomic_dec_return(&adev->vm_manager.num_prt_mappings) == 0) { | ||
1224 | struct amdgpu_prt_cb *cb = kmalloc(sizeof(struct amdgpu_prt_cb), | ||
1225 | GFP_KERNEL); | ||
1226 | |||
1227 | cb->adev = adev; | ||
1228 | if (!fence || dma_fence_add_callback(fence, &cb->cb, | ||
1229 | amdgpu_vm_prt_cb)) { | ||
1230 | amdgpu_vm_update_prt_state(adev); | ||
1231 | kfree(cb); | ||
1232 | } | ||
1233 | } | ||
1234 | kfree(mapping); | ||
1235 | } | ||
1236 | |||
1237 | /** | ||
1180 | * amdgpu_vm_clear_freed - clear freed BOs in the PT | 1238 | * amdgpu_vm_clear_freed - clear freed BOs in the PT |
1181 | * | 1239 | * |
1182 | * @adev: amdgpu_device pointer | 1240 | * @adev: amdgpu_device pointer |
@@ -1191,6 +1249,7 @@ int amdgpu_vm_clear_freed(struct amdgpu_device *adev, | |||
1191 | struct amdgpu_vm *vm) | 1249 | struct amdgpu_vm *vm) |
1192 | { | 1250 | { |
1193 | struct amdgpu_bo_va_mapping *mapping; | 1251 | struct amdgpu_bo_va_mapping *mapping; |
1252 | struct dma_fence *fence = NULL; | ||
1194 | int r; | 1253 | int r; |
1195 | 1254 | ||
1196 | while (!list_empty(&vm->freed)) { | 1255 | while (!list_empty(&vm->freed)) { |
@@ -1199,12 +1258,15 @@ int amdgpu_vm_clear_freed(struct amdgpu_device *adev, | |||
1199 | list_del(&mapping->list); | 1258 | list_del(&mapping->list); |
1200 | 1259 | ||
1201 | r = amdgpu_vm_bo_split_mapping(adev, NULL, 0, NULL, vm, mapping, | 1260 | r = amdgpu_vm_bo_split_mapping(adev, NULL, 0, NULL, vm, mapping, |
1202 | 0, 0, NULL); | 1261 | 0, 0, &fence); |
1203 | kfree(mapping); | 1262 | amdgpu_vm_free_mapping(adev, vm, mapping, fence); |
1204 | if (r) | 1263 | if (r) { |
1264 | dma_fence_put(fence); | ||
1205 | return r; | 1265 | return r; |
1266 | } | ||
1206 | 1267 | ||
1207 | } | 1268 | } |
1269 | dma_fence_put(fence); | ||
1208 | return 0; | 1270 | return 0; |
1209 | 1271 | ||
1210 | } | 1272 | } |
@@ -1314,6 +1376,15 @@ int amdgpu_vm_bo_map(struct amdgpu_device *adev, | |||
1314 | size == 0 || size & AMDGPU_GPU_PAGE_MASK) | 1376 | size == 0 || size & AMDGPU_GPU_PAGE_MASK) |
1315 | return -EINVAL; | 1377 | return -EINVAL; |
1316 | 1378 | ||
1379 | if (flags & AMDGPU_PTE_PRT) { | ||
1380 | /* Check if we have PRT hardware support */ | ||
1381 | if (!adev->gart.gart_funcs->set_prt) | ||
1382 | return -EINVAL; | ||
1383 | |||
1384 | if (atomic_inc_return(&adev->vm_manager.num_prt_mappings) == 1) | ||
1385 | amdgpu_vm_update_prt_state(adev); | ||
1386 | } | ||
1387 | |||
1317 | /* make sure object fit at this offset */ | 1388 | /* make sure object fit at this offset */ |
1318 | eaddr = saddr + size - 1; | 1389 | eaddr = saddr + size - 1; |
1319 | if (saddr >= eaddr || | 1390 | if (saddr >= eaddr || |
@@ -1400,7 +1471,7 @@ error_free: | |||
1400 | list_del(&mapping->list); | 1471 | list_del(&mapping->list); |
1401 | interval_tree_remove(&mapping->it, &vm->va); | 1472 | interval_tree_remove(&mapping->it, &vm->va); |
1402 | trace_amdgpu_vm_bo_unmap(bo_va, mapping); | 1473 | trace_amdgpu_vm_bo_unmap(bo_va, mapping); |
1403 | kfree(mapping); | 1474 | amdgpu_vm_free_mapping(adev, vm, mapping, NULL); |
1404 | 1475 | ||
1405 | error: | 1476 | error: |
1406 | return r; | 1477 | return r; |
@@ -1452,7 +1523,8 @@ int amdgpu_vm_bo_unmap(struct amdgpu_device *adev, | |||
1452 | if (valid) | 1523 | if (valid) |
1453 | list_add(&mapping->list, &vm->freed); | 1524 | list_add(&mapping->list, &vm->freed); |
1454 | else | 1525 | else |
1455 | kfree(mapping); | 1526 | amdgpu_vm_free_mapping(adev, vm, mapping, |
1527 | bo_va->last_pt_update); | ||
1456 | 1528 | ||
1457 | return 0; | 1529 | return 0; |
1458 | } | 1530 | } |
@@ -1488,7 +1560,8 @@ void amdgpu_vm_bo_rmv(struct amdgpu_device *adev, | |||
1488 | list_for_each_entry_safe(mapping, next, &bo_va->invalids, list) { | 1560 | list_for_each_entry_safe(mapping, next, &bo_va->invalids, list) { |
1489 | list_del(&mapping->list); | 1561 | list_del(&mapping->list); |
1490 | interval_tree_remove(&mapping->it, &vm->va); | 1562 | interval_tree_remove(&mapping->it, &vm->va); |
1491 | kfree(mapping); | 1563 | amdgpu_vm_free_mapping(adev, vm, mapping, |
1564 | bo_va->last_pt_update); | ||
1492 | } | 1565 | } |
1493 | 1566 | ||
1494 | dma_fence_put(bo_va->last_pt_update); | 1567 | dma_fence_put(bo_va->last_pt_update); |
@@ -1625,9 +1698,13 @@ void amdgpu_vm_fini(struct amdgpu_device *adev, struct amdgpu_vm *vm) | |||
1625 | kfree(mapping); | 1698 | kfree(mapping); |
1626 | } | 1699 | } |
1627 | list_for_each_entry_safe(mapping, tmp, &vm->freed, list) { | 1700 | list_for_each_entry_safe(mapping, tmp, &vm->freed, list) { |
1701 | if (mapping->flags & AMDGPU_PTE_PRT) | ||
1702 | continue; | ||
1703 | |||
1628 | list_del(&mapping->list); | 1704 | list_del(&mapping->list); |
1629 | kfree(mapping); | 1705 | kfree(mapping); |
1630 | } | 1706 | } |
1707 | amdgpu_vm_clear_freed(adev, vm); | ||
1631 | 1708 | ||
1632 | for (i = 0; i < amdgpu_vm_num_pdes(adev); i++) { | 1709 | for (i = 0; i < amdgpu_vm_num_pdes(adev); i++) { |
1633 | struct amdgpu_bo *pt = vm->page_tables[i].bo; | 1710 | struct amdgpu_bo *pt = vm->page_tables[i].bo; |
@@ -1673,6 +1750,8 @@ void amdgpu_vm_manager_init(struct amdgpu_device *adev) | |||
1673 | 1750 | ||
1674 | atomic_set(&adev->vm_manager.vm_pte_next_ring, 0); | 1751 | atomic_set(&adev->vm_manager.vm_pte_next_ring, 0); |
1675 | atomic64_set(&adev->vm_manager.client_counter, 0); | 1752 | atomic64_set(&adev->vm_manager.client_counter, 0); |
1753 | spin_lock_init(&adev->vm_manager.prt_lock); | ||
1754 | atomic_set(&adev->vm_manager.num_prt_mappings, 0); | ||
1676 | } | 1755 | } |
1677 | 1756 | ||
1678 | /** | 1757 | /** |