diff options
| author | Christian König <christian.koenig@amd.com> | 2017-03-13 05:13:37 -0400 |
|---|---|---|
| committer | Alex Deucher <alexander.deucher@amd.com> | 2017-03-29 23:54:00 -0400 |
| commit | 663e4577a5733fab18d601128f54486d78595bc0 (patch) | |
| tree | af0a0b2121dea7755bcb0b1bbde9af53f986db18 /drivers | |
| parent | 4388fc2ab0e83fd6247c48c7e97064cc75511848 (diff) | |
drm/amdgpu: separate page table allocation from mapping
This makes it easier to implement a replace operation.
Signed-off-by: Christian König <christian.koenig@amd.com>
Reviewed-by: Junwei Zhang <Jerry.Zhang@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c | 6 | ||||
| -rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c | 9 | ||||
| -rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 136 | ||||
| -rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h | 3 |
4 files changed, 92 insertions, 62 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c index 6daf004955b0..0240f108f90e 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c | |||
| @@ -631,8 +631,12 @@ int amdgpu_gem_va_ioctl(struct drm_device *dev, void *data, | |||
| 631 | 631 | ||
| 632 | switch (args->operation) { | 632 | switch (args->operation) { |
| 633 | case AMDGPU_VA_OP_MAP: | 633 | case AMDGPU_VA_OP_MAP: |
| 634 | va_flags = amdgpu_vm_get_pte_flags(adev, args->flags); | 634 | r = amdgpu_vm_alloc_pts(adev, bo_va->vm, args->va_address, |
| 635 | args->map_size); | ||
| 636 | if (r) | ||
| 637 | goto error_backoff; | ||
| 635 | 638 | ||
| 639 | va_flags = amdgpu_vm_get_pte_flags(adev, args->flags); | ||
| 636 | r = amdgpu_vm_bo_map(adev, bo_va, args->va_address, | 640 | r = amdgpu_vm_bo_map(adev, bo_va, args->va_address, |
| 637 | args->offset_in_bo, args->map_size, | 641 | args->offset_in_bo, args->map_size, |
| 638 | va_flags); | 642 | va_flags); |
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c index 2feb9aa3b1f4..ecef35a1fe33 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c | |||
| @@ -75,6 +75,15 @@ int amdgpu_map_static_csa(struct amdgpu_device *adev, struct amdgpu_vm *vm) | |||
| 75 | return -ENOMEM; | 75 | return -ENOMEM; |
| 76 | } | 76 | } |
| 77 | 77 | ||
| 78 | r = amdgpu_vm_alloc_pts(adev, bo_va->vm, AMDGPU_CSA_VADDR, | ||
| 79 | AMDGPU_CSA_SIZE); | ||
| 80 | if (r) { | ||
| 81 | DRM_ERROR("failed to allocate pts for static CSA, err=%d\n", r); | ||
| 82 | amdgpu_vm_bo_rmv(adev, bo_va); | ||
| 83 | ttm_eu_backoff_reservation(&ticket, &list); | ||
| 84 | return r; | ||
| 85 | } | ||
| 86 | |||
| 78 | r = amdgpu_vm_bo_map(adev, bo_va, AMDGPU_CSA_VADDR, 0,AMDGPU_CSA_SIZE, | 87 | r = amdgpu_vm_bo_map(adev, bo_va, AMDGPU_CSA_VADDR, 0,AMDGPU_CSA_SIZE, |
| 79 | AMDGPU_PTE_READABLE | AMDGPU_PTE_WRITEABLE | | 88 | AMDGPU_PTE_READABLE | AMDGPU_PTE_WRITEABLE | |
| 80 | AMDGPU_PTE_EXECUTABLE); | 89 | AMDGPU_PTE_EXECUTABLE); |
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c index f9f4e2055084..296e985d0b65 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | |||
| @@ -187,6 +187,78 @@ void amdgpu_vm_move_pt_bos_in_lru(struct amdgpu_device *adev, | |||
| 187 | spin_unlock(&glob->lru_lock); | 187 | spin_unlock(&glob->lru_lock); |
| 188 | } | 188 | } |
| 189 | 189 | ||
| 190 | /** | ||
| 191 | * amdgpu_vm_alloc_pts - Allocate page tables. | ||
| 192 | * | ||
| 193 | * @adev: amdgpu_device pointer | ||
| 194 | * @vm: VM to allocate page tables for | ||
| 195 | * @saddr: Start address which needs to be allocated | ||
| 196 | * @size: Size from start address we need. | ||
| 197 | * | ||
| 198 | * Make sure the page tables are allocated. | ||
| 199 | */ | ||
| 200 | int amdgpu_vm_alloc_pts(struct amdgpu_device *adev, | ||
| 201 | struct amdgpu_vm *vm, | ||
| 202 | uint64_t saddr, uint64_t size) | ||
| 203 | { | ||
| 204 | unsigned last_pfn, pt_idx; | ||
| 205 | uint64_t eaddr; | ||
| 206 | int r; | ||
| 207 | |||
| 208 | /* validate the parameters */ | ||
| 209 | if (saddr & AMDGPU_GPU_PAGE_MASK || size & AMDGPU_GPU_PAGE_MASK) | ||
| 210 | return -EINVAL; | ||
| 211 | |||
| 212 | eaddr = saddr + size - 1; | ||
| 213 | last_pfn = eaddr / AMDGPU_GPU_PAGE_SIZE; | ||
| 214 | if (last_pfn >= adev->vm_manager.max_pfn) { | ||
| 215 | dev_err(adev->dev, "va above limit (0x%08X >= 0x%08X)\n", | ||
| 216 | last_pfn, adev->vm_manager.max_pfn); | ||
| 217 | return -EINVAL; | ||
| 218 | } | ||
| 219 | |||
| 220 | saddr /= AMDGPU_GPU_PAGE_SIZE; | ||
| 221 | eaddr /= AMDGPU_GPU_PAGE_SIZE; | ||
| 222 | |||
| 223 | saddr >>= amdgpu_vm_block_size; | ||
| 224 | eaddr >>= amdgpu_vm_block_size; | ||
| 225 | |||
| 226 | BUG_ON(eaddr >= amdgpu_vm_num_pdes(adev)); | ||
| 227 | |||
| 228 | if (eaddr > vm->max_pde_used) | ||
| 229 | vm->max_pde_used = eaddr; | ||
| 230 | |||
| 231 | /* walk over the address space and allocate the page tables */ | ||
| 232 | for (pt_idx = saddr; pt_idx <= eaddr; ++pt_idx) { | ||
| 233 | struct reservation_object *resv = vm->page_directory->tbo.resv; | ||
| 234 | struct amdgpu_bo *pt; | ||
| 235 | |||
| 236 | if (vm->page_tables[pt_idx].bo) | ||
| 237 | continue; | ||
| 238 | |||
| 239 | r = amdgpu_bo_create(adev, AMDGPU_VM_PTE_COUNT * 8, | ||
| 240 | AMDGPU_GPU_PAGE_SIZE, true, | ||
| 241 | AMDGPU_GEM_DOMAIN_VRAM, | ||
| 242 | AMDGPU_GEM_CREATE_NO_CPU_ACCESS | | ||
| 243 | AMDGPU_GEM_CREATE_SHADOW | | ||
| 244 | AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS | | ||
| 245 | AMDGPU_GEM_CREATE_VRAM_CLEARED, | ||
| 246 | NULL, resv, &pt); | ||
| 247 | if (r) | ||
| 248 | return r; | ||
| 249 | |||
| 250 | /* Keep a reference to the page table to avoid freeing | ||
| 251 | * them up in the wrong order. | ||
| 252 | */ | ||
| 253 | pt->parent = amdgpu_bo_ref(vm->page_directory); | ||
| 254 | |||
| 255 | vm->page_tables[pt_idx].bo = pt; | ||
| 256 | vm->page_tables[pt_idx].addr = 0; | ||
| 257 | } | ||
| 258 | |||
| 259 | return 0; | ||
| 260 | } | ||
| 261 | |||
| 190 | static bool amdgpu_vm_is_gpu_reset(struct amdgpu_device *adev, | 262 | static bool amdgpu_vm_is_gpu_reset(struct amdgpu_device *adev, |
| 191 | struct amdgpu_vm_id *id) | 263 | struct amdgpu_vm_id *id) |
| 192 | { | 264 | { |
| @@ -1442,9 +1514,7 @@ int amdgpu_vm_bo_map(struct amdgpu_device *adev, | |||
| 1442 | struct amdgpu_bo_va_mapping *mapping; | 1514 | struct amdgpu_bo_va_mapping *mapping; |
| 1443 | struct amdgpu_vm *vm = bo_va->vm; | 1515 | struct amdgpu_vm *vm = bo_va->vm; |
| 1444 | struct interval_tree_node *it; | 1516 | struct interval_tree_node *it; |
| 1445 | unsigned last_pfn, pt_idx; | ||
| 1446 | uint64_t eaddr; | 1517 | uint64_t eaddr; |
| 1447 | int r; | ||
| 1448 | 1518 | ||
| 1449 | /* validate the parameters */ | 1519 | /* validate the parameters */ |
| 1450 | if (saddr & AMDGPU_GPU_PAGE_MASK || offset & AMDGPU_GPU_PAGE_MASK || | 1520 | if (saddr & AMDGPU_GPU_PAGE_MASK || offset & AMDGPU_GPU_PAGE_MASK || |
| @@ -1457,13 +1527,6 @@ int amdgpu_vm_bo_map(struct amdgpu_device *adev, | |||
| 1457 | (bo_va->bo && offset + size > amdgpu_bo_size(bo_va->bo))) | 1527 | (bo_va->bo && offset + size > amdgpu_bo_size(bo_va->bo))) |
| 1458 | return -EINVAL; | 1528 | return -EINVAL; |
| 1459 | 1529 | ||
| 1460 | last_pfn = eaddr / AMDGPU_GPU_PAGE_SIZE; | ||
| 1461 | if (last_pfn >= adev->vm_manager.max_pfn) { | ||
| 1462 | dev_err(adev->dev, "va above limit (0x%08X >= 0x%08X)\n", | ||
| 1463 | last_pfn, adev->vm_manager.max_pfn); | ||
| 1464 | return -EINVAL; | ||
| 1465 | } | ||
| 1466 | |||
| 1467 | saddr /= AMDGPU_GPU_PAGE_SIZE; | 1530 | saddr /= AMDGPU_GPU_PAGE_SIZE; |
| 1468 | eaddr /= AMDGPU_GPU_PAGE_SIZE; | 1531 | eaddr /= AMDGPU_GPU_PAGE_SIZE; |
| 1469 | 1532 | ||
| @@ -1475,15 +1538,12 @@ int amdgpu_vm_bo_map(struct amdgpu_device *adev, | |||
| 1475 | dev_err(adev->dev, "bo %p va 0x%010Lx-0x%010Lx conflict with " | 1538 | dev_err(adev->dev, "bo %p va 0x%010Lx-0x%010Lx conflict with " |
| 1476 | "0x%010lx-0x%010lx\n", bo_va->bo, saddr, eaddr, | 1539 | "0x%010lx-0x%010lx\n", bo_va->bo, saddr, eaddr, |
| 1477 | tmp->it.start, tmp->it.last + 1); | 1540 | tmp->it.start, tmp->it.last + 1); |
| 1478 | r = -EINVAL; | 1541 | return -EINVAL; |
| 1479 | goto error; | ||
| 1480 | } | 1542 | } |
| 1481 | 1543 | ||
| 1482 | mapping = kmalloc(sizeof(*mapping), GFP_KERNEL); | 1544 | mapping = kmalloc(sizeof(*mapping), GFP_KERNEL); |
| 1483 | if (!mapping) { | 1545 | if (!mapping) |
| 1484 | r = -ENOMEM; | 1546 | return -ENOMEM; |
| 1485 | goto error; | ||
| 1486 | } | ||
| 1487 | 1547 | ||
| 1488 | INIT_LIST_HEAD(&mapping->list); | 1548 | INIT_LIST_HEAD(&mapping->list); |
| 1489 | mapping->it.start = saddr; | 1549 | mapping->it.start = saddr; |
| @@ -1494,56 +1554,10 @@ int amdgpu_vm_bo_map(struct amdgpu_device *adev, | |||
| 1494 | list_add(&mapping->list, &bo_va->invalids); | 1554 | list_add(&mapping->list, &bo_va->invalids); |
| 1495 | interval_tree_insert(&mapping->it, &vm->va); | 1555 | interval_tree_insert(&mapping->it, &vm->va); |
| 1496 | 1556 | ||
| 1497 | /* Make sure the page tables are allocated */ | ||
| 1498 | saddr >>= amdgpu_vm_block_size; | ||
| 1499 | eaddr >>= amdgpu_vm_block_size; | ||
| 1500 | |||
| 1501 | BUG_ON(eaddr >= amdgpu_vm_num_pdes(adev)); | ||
| 1502 | |||
| 1503 | if (eaddr > vm->max_pde_used) | ||
| 1504 | vm->max_pde_used = eaddr; | ||
| 1505 | |||
| 1506 | /* walk over the address space and allocate the page tables */ | ||
| 1507 | for (pt_idx = saddr; pt_idx <= eaddr; ++pt_idx) { | ||
| 1508 | struct reservation_object *resv = vm->page_directory->tbo.resv; | ||
| 1509 | struct amdgpu_bo *pt; | ||
| 1510 | |||
| 1511 | if (vm->page_tables[pt_idx].bo) | ||
| 1512 | continue; | ||
| 1513 | |||
| 1514 | r = amdgpu_bo_create(adev, AMDGPU_VM_PTE_COUNT * 8, | ||
| 1515 | AMDGPU_GPU_PAGE_SIZE, true, | ||
| 1516 | AMDGPU_GEM_DOMAIN_VRAM, | ||
| 1517 | AMDGPU_GEM_CREATE_NO_CPU_ACCESS | | ||
| 1518 | AMDGPU_GEM_CREATE_SHADOW | | ||
| 1519 | AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS | | ||
| 1520 | AMDGPU_GEM_CREATE_VRAM_CLEARED, | ||
| 1521 | NULL, resv, &pt); | ||
| 1522 | if (r) | ||
| 1523 | goto error_free; | ||
| 1524 | |||
| 1525 | /* Keep a reference to the page table to avoid freeing | ||
| 1526 | * them up in the wrong order. | ||
| 1527 | */ | ||
| 1528 | pt->parent = amdgpu_bo_ref(vm->page_directory); | ||
| 1529 | |||
| 1530 | vm->page_tables[pt_idx].bo = pt; | ||
| 1531 | vm->page_tables[pt_idx].addr = 0; | ||
| 1532 | } | ||
| 1533 | |||
| 1534 | if (flags & AMDGPU_PTE_PRT) | 1557 | if (flags & AMDGPU_PTE_PRT) |
| 1535 | amdgpu_vm_prt_get(adev); | 1558 | amdgpu_vm_prt_get(adev); |
| 1536 | 1559 | ||
| 1537 | return 0; | 1560 | return 0; |
| 1538 | |||
| 1539 | error_free: | ||
| 1540 | list_del(&mapping->list); | ||
| 1541 | interval_tree_remove(&mapping->it, &vm->va); | ||
| 1542 | trace_amdgpu_vm_bo_unmap(bo_va, mapping); | ||
| 1543 | amdgpu_vm_free_mapping(adev, vm, mapping, NULL); | ||
| 1544 | |||
| 1545 | error: | ||
| 1546 | return r; | ||
| 1547 | } | 1561 | } |
| 1548 | 1562 | ||
| 1549 | /** | 1563 | /** |
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h index 57eaf71a5b1c..1e5a3b2c7927 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h | |||
| @@ -179,6 +179,9 @@ int amdgpu_vm_validate_pt_bos(struct amdgpu_device *adev, struct amdgpu_vm *vm, | |||
| 179 | void *param); | 179 | void *param); |
| 180 | void amdgpu_vm_move_pt_bos_in_lru(struct amdgpu_device *adev, | 180 | void amdgpu_vm_move_pt_bos_in_lru(struct amdgpu_device *adev, |
| 181 | struct amdgpu_vm *vm); | 181 | struct amdgpu_vm *vm); |
| 182 | int amdgpu_vm_alloc_pts(struct amdgpu_device *adev, | ||
| 183 | struct amdgpu_vm *vm, | ||
| 184 | uint64_t saddr, uint64_t size); | ||
| 182 | int amdgpu_vm_grab_id(struct amdgpu_vm *vm, struct amdgpu_ring *ring, | 185 | int amdgpu_vm_grab_id(struct amdgpu_vm *vm, struct amdgpu_ring *ring, |
| 183 | struct amdgpu_sync *sync, struct dma_fence *fence, | 186 | struct amdgpu_sync *sync, struct dma_fence *fence, |
| 184 | struct amdgpu_job *job); | 187 | struct amdgpu_job *job); |
