diff options
| -rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu.h | 2 | ||||
| -rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 101 | ||||
| -rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h | 6 |
3 files changed, 98 insertions, 11 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index c1b913541739..618f12884eed 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h | |||
| @@ -294,6 +294,8 @@ struct amdgpu_gart_funcs { | |||
| 294 | uint32_t gpu_page_idx, /* pte/pde to update */ | 294 | uint32_t gpu_page_idx, /* pte/pde to update */ |
| 295 | uint64_t addr, /* addr to write into pte/pde */ | 295 | uint64_t addr, /* addr to write into pte/pde */ |
| 296 | uint32_t flags); /* access flags */ | 296 | uint32_t flags); /* access flags */ |
| 297 | /* enable/disable PRT support */ | ||
| 298 | void (*set_prt)(struct amdgpu_device *adev, bool enable); | ||
| 297 | }; | 299 | }; |
| 298 | 300 | ||
| 299 | /* provided by the ih block */ | 301 | /* provided by the ih block */ |
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 | /** |
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h index 18c72c0b478d..f90e1c8daf01 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h | |||
| @@ -65,6 +65,8 @@ struct amdgpu_bo_list_entry; | |||
| 65 | 65 | ||
| 66 | #define AMDGPU_PTE_FRAG(x) ((x & 0x1f) << 7) | 66 | #define AMDGPU_PTE_FRAG(x) ((x & 0x1f) << 7) |
| 67 | 67 | ||
| 68 | #define AMDGPU_PTE_PRT (1UL << 63) | ||
| 69 | |||
| 68 | /* How to programm VM fault handling */ | 70 | /* How to programm VM fault handling */ |
| 69 | #define AMDGPU_VM_FAULT_STOP_NEVER 0 | 71 | #define AMDGPU_VM_FAULT_STOP_NEVER 0 |
| 70 | #define AMDGPU_VM_FAULT_STOP_FIRST 1 | 72 | #define AMDGPU_VM_FAULT_STOP_FIRST 1 |
| @@ -159,6 +161,10 @@ struct amdgpu_vm_manager { | |||
| 159 | atomic_t vm_pte_next_ring; | 161 | atomic_t vm_pte_next_ring; |
| 160 | /* client id counter */ | 162 | /* client id counter */ |
| 161 | atomic64_t client_counter; | 163 | atomic64_t client_counter; |
| 164 | |||
| 165 | /* partial resident texture handling */ | ||
| 166 | spinlock_t prt_lock; | ||
| 167 | atomic_t num_prt_mappings; | ||
| 162 | }; | 168 | }; |
| 163 | 169 | ||
| 164 | void amdgpu_vm_manager_init(struct amdgpu_device *adev); | 170 | void amdgpu_vm_manager_init(struct amdgpu_device *adev); |
