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 | |
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>
-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); |