diff options
author | Daniel Vetter <daniel.vetter@ffwll.ch> | 2015-09-02 08:33:42 -0400 |
---|---|---|
committer | Daniel Vetter <daniel.vetter@ffwll.ch> | 2015-09-02 08:33:42 -0400 |
commit | e93c28f39375558409329a02a767d5cadfcc4a31 (patch) | |
tree | 9f1b4b5ce765b887b6002cded59fc934e6c9c012 /drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | |
parent | 85a62bf9d8ef8d533635270ae985281c58e8c974 (diff) | |
parent | 6fa2d197936ba0b8936e813d0adecefac160062b (diff) |
Merge tag 'drm-intel-next-fixes-2015-09-02' into drm-intel-next-queued
Backmerge -fixes since there's more DDI-E related cleanups on top of
the pile of -fixes for skl that just landed for 4.3.
Conflicts:
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i914/intel_dp.c
drivers/gpu/drm/i915/intel_lrc.c
Conflicts are all fairly harmless adjacent line stuff.
Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c')
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 274 |
1 files changed, 178 insertions, 96 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c index 9a4e3b63f1cb..a78a206e176e 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | |||
@@ -127,16 +127,16 @@ struct amdgpu_bo_list_entry *amdgpu_vm_get_bos(struct amdgpu_device *adev, | |||
127 | /** | 127 | /** |
128 | * amdgpu_vm_grab_id - allocate the next free VMID | 128 | * amdgpu_vm_grab_id - allocate the next free VMID |
129 | * | 129 | * |
130 | * @ring: ring we want to submit job to | ||
131 | * @vm: vm to allocate id for | 130 | * @vm: vm to allocate id for |
131 | * @ring: ring we want to submit job to | ||
132 | * @sync: sync object where we add dependencies | ||
132 | * | 133 | * |
133 | * Allocate an id for the vm (cayman+). | 134 | * Allocate an id for the vm, adding fences to the sync obj as necessary. |
134 | * Returns the fence we need to sync to (if any). | ||
135 | * | 135 | * |
136 | * Global and local mutex must be locked! | 136 | * Global mutex must be locked! |
137 | */ | 137 | */ |
138 | struct amdgpu_fence *amdgpu_vm_grab_id(struct amdgpu_ring *ring, | 138 | int amdgpu_vm_grab_id(struct amdgpu_vm *vm, struct amdgpu_ring *ring, |
139 | struct amdgpu_vm *vm) | 139 | struct amdgpu_sync *sync) |
140 | { | 140 | { |
141 | struct amdgpu_fence *best[AMDGPU_MAX_RINGS] = {}; | 141 | struct amdgpu_fence *best[AMDGPU_MAX_RINGS] = {}; |
142 | struct amdgpu_vm_id *vm_id = &vm->ids[ring->idx]; | 142 | struct amdgpu_vm_id *vm_id = &vm->ids[ring->idx]; |
@@ -148,7 +148,7 @@ struct amdgpu_fence *amdgpu_vm_grab_id(struct amdgpu_ring *ring, | |||
148 | /* check if the id is still valid */ | 148 | /* check if the id is still valid */ |
149 | if (vm_id->id && vm_id->last_id_use && | 149 | if (vm_id->id && vm_id->last_id_use && |
150 | vm_id->last_id_use == adev->vm_manager.active[vm_id->id]) | 150 | vm_id->last_id_use == adev->vm_manager.active[vm_id->id]) |
151 | return NULL; | 151 | return 0; |
152 | 152 | ||
153 | /* we definately need to flush */ | 153 | /* we definately need to flush */ |
154 | vm_id->pd_gpu_addr = ~0ll; | 154 | vm_id->pd_gpu_addr = ~0ll; |
@@ -161,7 +161,7 @@ struct amdgpu_fence *amdgpu_vm_grab_id(struct amdgpu_ring *ring, | |||
161 | /* found a free one */ | 161 | /* found a free one */ |
162 | vm_id->id = i; | 162 | vm_id->id = i; |
163 | trace_amdgpu_vm_grab_id(i, ring->idx); | 163 | trace_amdgpu_vm_grab_id(i, ring->idx); |
164 | return NULL; | 164 | return 0; |
165 | } | 165 | } |
166 | 166 | ||
167 | if (amdgpu_fence_is_earlier(fence, best[fence->ring->idx])) { | 167 | if (amdgpu_fence_is_earlier(fence, best[fence->ring->idx])) { |
@@ -172,15 +172,19 @@ struct amdgpu_fence *amdgpu_vm_grab_id(struct amdgpu_ring *ring, | |||
172 | 172 | ||
173 | for (i = 0; i < 2; ++i) { | 173 | for (i = 0; i < 2; ++i) { |
174 | if (choices[i]) { | 174 | if (choices[i]) { |
175 | struct amdgpu_fence *fence; | ||
176 | |||
177 | fence = adev->vm_manager.active[choices[i]]; | ||
175 | vm_id->id = choices[i]; | 178 | vm_id->id = choices[i]; |
179 | |||
176 | trace_amdgpu_vm_grab_id(choices[i], ring->idx); | 180 | trace_amdgpu_vm_grab_id(choices[i], ring->idx); |
177 | return adev->vm_manager.active[choices[i]]; | 181 | return amdgpu_sync_fence(ring->adev, sync, &fence->base); |
178 | } | 182 | } |
179 | } | 183 | } |
180 | 184 | ||
181 | /* should never happen */ | 185 | /* should never happen */ |
182 | BUG(); | 186 | BUG(); |
183 | return NULL; | 187 | return -EINVAL; |
184 | } | 188 | } |
185 | 189 | ||
186 | /** | 190 | /** |
@@ -200,13 +204,15 @@ void amdgpu_vm_flush(struct amdgpu_ring *ring, | |||
200 | { | 204 | { |
201 | uint64_t pd_addr = amdgpu_bo_gpu_offset(vm->page_directory); | 205 | uint64_t pd_addr = amdgpu_bo_gpu_offset(vm->page_directory); |
202 | struct amdgpu_vm_id *vm_id = &vm->ids[ring->idx]; | 206 | struct amdgpu_vm_id *vm_id = &vm->ids[ring->idx]; |
207 | struct amdgpu_fence *flushed_updates = vm_id->flushed_updates; | ||
203 | 208 | ||
204 | if (pd_addr != vm_id->pd_gpu_addr || !vm_id->flushed_updates || | 209 | if (pd_addr != vm_id->pd_gpu_addr || !flushed_updates || |
205 | amdgpu_fence_is_earlier(vm_id->flushed_updates, updates)) { | 210 | (updates && amdgpu_fence_is_earlier(flushed_updates, updates))) { |
206 | 211 | ||
207 | trace_amdgpu_vm_flush(pd_addr, ring->idx, vm_id->id); | 212 | trace_amdgpu_vm_flush(pd_addr, ring->idx, vm_id->id); |
208 | amdgpu_fence_unref(&vm_id->flushed_updates); | 213 | vm_id->flushed_updates = amdgpu_fence_ref( |
209 | vm_id->flushed_updates = amdgpu_fence_ref(updates); | 214 | amdgpu_fence_later(flushed_updates, updates)); |
215 | amdgpu_fence_unref(&flushed_updates); | ||
210 | vm_id->pd_gpu_addr = pd_addr; | 216 | vm_id->pd_gpu_addr = pd_addr; |
211 | amdgpu_ring_emit_vm_flush(ring, vm_id->id, vm_id->pd_gpu_addr); | 217 | amdgpu_ring_emit_vm_flush(ring, vm_id->id, vm_id->pd_gpu_addr); |
212 | } | 218 | } |
@@ -300,6 +306,16 @@ static void amdgpu_vm_update_pages(struct amdgpu_device *adev, | |||
300 | } | 306 | } |
301 | } | 307 | } |
302 | 308 | ||
309 | static int amdgpu_vm_free_job( | ||
310 | struct amdgpu_cs_parser *sched_job) | ||
311 | { | ||
312 | int i; | ||
313 | for (i = 0; i < sched_job->num_ibs; i++) | ||
314 | amdgpu_ib_free(sched_job->adev, &sched_job->ibs[i]); | ||
315 | kfree(sched_job->ibs); | ||
316 | return 0; | ||
317 | } | ||
318 | |||
303 | /** | 319 | /** |
304 | * amdgpu_vm_clear_bo - initially clear the page dir/table | 320 | * amdgpu_vm_clear_bo - initially clear the page dir/table |
305 | * | 321 | * |
@@ -310,7 +326,8 @@ static int amdgpu_vm_clear_bo(struct amdgpu_device *adev, | |||
310 | struct amdgpu_bo *bo) | 326 | struct amdgpu_bo *bo) |
311 | { | 327 | { |
312 | struct amdgpu_ring *ring = adev->vm_manager.vm_pte_funcs_ring; | 328 | struct amdgpu_ring *ring = adev->vm_manager.vm_pte_funcs_ring; |
313 | struct amdgpu_ib ib; | 329 | struct fence *fence = NULL; |
330 | struct amdgpu_ib *ib; | ||
314 | unsigned entries; | 331 | unsigned entries; |
315 | uint64_t addr; | 332 | uint64_t addr; |
316 | int r; | 333 | int r; |
@@ -330,24 +347,33 @@ static int amdgpu_vm_clear_bo(struct amdgpu_device *adev, | |||
330 | addr = amdgpu_bo_gpu_offset(bo); | 347 | addr = amdgpu_bo_gpu_offset(bo); |
331 | entries = amdgpu_bo_size(bo) / 8; | 348 | entries = amdgpu_bo_size(bo) / 8; |
332 | 349 | ||
333 | r = amdgpu_ib_get(ring, NULL, entries * 2 + 64, &ib); | 350 | ib = kzalloc(sizeof(struct amdgpu_ib), GFP_KERNEL); |
334 | if (r) | 351 | if (!ib) |
335 | goto error_unreserve; | 352 | goto error_unreserve; |
336 | 353 | ||
337 | ib.length_dw = 0; | 354 | r = amdgpu_ib_get(ring, NULL, entries * 2 + 64, ib); |
338 | |||
339 | amdgpu_vm_update_pages(adev, &ib, addr, 0, entries, 0, 0, 0); | ||
340 | amdgpu_vm_pad_ib(adev, &ib); | ||
341 | WARN_ON(ib.length_dw > 64); | ||
342 | |||
343 | r = amdgpu_ib_schedule(adev, 1, &ib, AMDGPU_FENCE_OWNER_VM); | ||
344 | if (r) | 355 | if (r) |
345 | goto error_free; | 356 | goto error_free; |
346 | 357 | ||
347 | amdgpu_bo_fence(bo, ib.fence, true); | 358 | ib->length_dw = 0; |
348 | 359 | ||
360 | amdgpu_vm_update_pages(adev, ib, addr, 0, entries, 0, 0, 0); | ||
361 | amdgpu_vm_pad_ib(adev, ib); | ||
362 | WARN_ON(ib->length_dw > 64); | ||
363 | r = amdgpu_sched_ib_submit_kernel_helper(adev, ring, ib, 1, | ||
364 | &amdgpu_vm_free_job, | ||
365 | AMDGPU_FENCE_OWNER_VM, | ||
366 | &fence); | ||
367 | if (!r) | ||
368 | amdgpu_bo_fence(bo, fence, true); | ||
369 | fence_put(fence); | ||
370 | if (amdgpu_enable_scheduler) { | ||
371 | amdgpu_bo_unreserve(bo); | ||
372 | return 0; | ||
373 | } | ||
349 | error_free: | 374 | error_free: |
350 | amdgpu_ib_free(adev, &ib); | 375 | amdgpu_ib_free(adev, ib); |
376 | kfree(ib); | ||
351 | 377 | ||
352 | error_unreserve: | 378 | error_unreserve: |
353 | amdgpu_bo_unreserve(bo); | 379 | amdgpu_bo_unreserve(bo); |
@@ -400,7 +426,9 @@ int amdgpu_vm_update_page_directory(struct amdgpu_device *adev, | |||
400 | uint32_t incr = AMDGPU_VM_PTE_COUNT * 8; | 426 | uint32_t incr = AMDGPU_VM_PTE_COUNT * 8; |
401 | uint64_t last_pde = ~0, last_pt = ~0; | 427 | uint64_t last_pde = ~0, last_pt = ~0; |
402 | unsigned count = 0, pt_idx, ndw; | 428 | unsigned count = 0, pt_idx, ndw; |
403 | struct amdgpu_ib ib; | 429 | struct amdgpu_ib *ib; |
430 | struct fence *fence = NULL; | ||
431 | |||
404 | int r; | 432 | int r; |
405 | 433 | ||
406 | /* padding, etc. */ | 434 | /* padding, etc. */ |
@@ -413,10 +441,14 @@ int amdgpu_vm_update_page_directory(struct amdgpu_device *adev, | |||
413 | if (ndw > 0xfffff) | 441 | if (ndw > 0xfffff) |
414 | return -ENOMEM; | 442 | return -ENOMEM; |
415 | 443 | ||
416 | r = amdgpu_ib_get(ring, NULL, ndw * 4, &ib); | 444 | ib = kzalloc(sizeof(struct amdgpu_ib), GFP_KERNEL); |
445 | if (!ib) | ||
446 | return -ENOMEM; | ||
447 | |||
448 | r = amdgpu_ib_get(ring, NULL, ndw * 4, ib); | ||
417 | if (r) | 449 | if (r) |
418 | return r; | 450 | return r; |
419 | ib.length_dw = 0; | 451 | ib->length_dw = 0; |
420 | 452 | ||
421 | /* walk over the address space and update the page directory */ | 453 | /* walk over the address space and update the page directory */ |
422 | for (pt_idx = 0; pt_idx <= vm->max_pde_used; ++pt_idx) { | 454 | for (pt_idx = 0; pt_idx <= vm->max_pde_used; ++pt_idx) { |
@@ -436,7 +468,7 @@ int amdgpu_vm_update_page_directory(struct amdgpu_device *adev, | |||
436 | ((last_pt + incr * count) != pt)) { | 468 | ((last_pt + incr * count) != pt)) { |
437 | 469 | ||
438 | if (count) { | 470 | if (count) { |
439 | amdgpu_vm_update_pages(adev, &ib, last_pde, | 471 | amdgpu_vm_update_pages(adev, ib, last_pde, |
440 | last_pt, count, incr, | 472 | last_pt, count, incr, |
441 | AMDGPU_PTE_VALID, 0); | 473 | AMDGPU_PTE_VALID, 0); |
442 | } | 474 | } |
@@ -450,23 +482,37 @@ int amdgpu_vm_update_page_directory(struct amdgpu_device *adev, | |||
450 | } | 482 | } |
451 | 483 | ||
452 | if (count) | 484 | if (count) |
453 | amdgpu_vm_update_pages(adev, &ib, last_pde, last_pt, count, | 485 | amdgpu_vm_update_pages(adev, ib, last_pde, last_pt, count, |
454 | incr, AMDGPU_PTE_VALID, 0); | 486 | incr, AMDGPU_PTE_VALID, 0); |
455 | 487 | ||
456 | if (ib.length_dw != 0) { | 488 | if (ib->length_dw != 0) { |
457 | amdgpu_vm_pad_ib(adev, &ib); | 489 | amdgpu_vm_pad_ib(adev, ib); |
458 | amdgpu_sync_resv(adev, &ib.sync, pd->tbo.resv, AMDGPU_FENCE_OWNER_VM); | 490 | amdgpu_sync_resv(adev, &ib->sync, pd->tbo.resv, AMDGPU_FENCE_OWNER_VM); |
459 | WARN_ON(ib.length_dw > ndw); | 491 | WARN_ON(ib->length_dw > ndw); |
460 | r = amdgpu_ib_schedule(adev, 1, &ib, AMDGPU_FENCE_OWNER_VM); | 492 | r = amdgpu_sched_ib_submit_kernel_helper(adev, ring, ib, 1, |
461 | if (r) { | 493 | &amdgpu_vm_free_job, |
462 | amdgpu_ib_free(adev, &ib); | 494 | AMDGPU_FENCE_OWNER_VM, |
463 | return r; | 495 | &fence); |
464 | } | 496 | if (r) |
465 | amdgpu_bo_fence(pd, ib.fence, true); | 497 | goto error_free; |
498 | |||
499 | amdgpu_bo_fence(pd, fence, true); | ||
500 | fence_put(vm->page_directory_fence); | ||
501 | vm->page_directory_fence = fence_get(fence); | ||
502 | fence_put(fence); | ||
503 | } | ||
504 | |||
505 | if (!amdgpu_enable_scheduler || ib->length_dw == 0) { | ||
506 | amdgpu_ib_free(adev, ib); | ||
507 | kfree(ib); | ||
466 | } | 508 | } |
467 | amdgpu_ib_free(adev, &ib); | ||
468 | 509 | ||
469 | return 0; | 510 | return 0; |
511 | |||
512 | error_free: | ||
513 | amdgpu_ib_free(adev, ib); | ||
514 | kfree(ib); | ||
515 | return r; | ||
470 | } | 516 | } |
471 | 517 | ||
472 | /** | 518 | /** |
@@ -640,7 +686,7 @@ static int amdgpu_vm_update_ptes(struct amdgpu_device *adev, | |||
640 | */ | 686 | */ |
641 | static void amdgpu_vm_fence_pts(struct amdgpu_vm *vm, | 687 | static void amdgpu_vm_fence_pts(struct amdgpu_vm *vm, |
642 | uint64_t start, uint64_t end, | 688 | uint64_t start, uint64_t end, |
643 | struct amdgpu_fence *fence) | 689 | struct fence *fence) |
644 | { | 690 | { |
645 | unsigned i; | 691 | unsigned i; |
646 | 692 | ||
@@ -670,12 +716,13 @@ static int amdgpu_vm_bo_update_mapping(struct amdgpu_device *adev, | |||
670 | struct amdgpu_vm *vm, | 716 | struct amdgpu_vm *vm, |
671 | struct amdgpu_bo_va_mapping *mapping, | 717 | struct amdgpu_bo_va_mapping *mapping, |
672 | uint64_t addr, uint32_t gtt_flags, | 718 | uint64_t addr, uint32_t gtt_flags, |
673 | struct amdgpu_fence **fence) | 719 | struct fence **fence) |
674 | { | 720 | { |
675 | struct amdgpu_ring *ring = adev->vm_manager.vm_pte_funcs_ring; | 721 | struct amdgpu_ring *ring = adev->vm_manager.vm_pte_funcs_ring; |
676 | unsigned nptes, ncmds, ndw; | 722 | unsigned nptes, ncmds, ndw; |
677 | uint32_t flags = gtt_flags; | 723 | uint32_t flags = gtt_flags; |
678 | struct amdgpu_ib ib; | 724 | struct amdgpu_ib *ib; |
725 | struct fence *f = NULL; | ||
679 | int r; | 726 | int r; |
680 | 727 | ||
681 | /* normally,bo_va->flags only contians READABLE and WIRTEABLE bit go here | 728 | /* normally,bo_va->flags only contians READABLE and WIRTEABLE bit go here |
@@ -722,46 +769,65 @@ static int amdgpu_vm_bo_update_mapping(struct amdgpu_device *adev, | |||
722 | if (ndw > 0xfffff) | 769 | if (ndw > 0xfffff) |
723 | return -ENOMEM; | 770 | return -ENOMEM; |
724 | 771 | ||
725 | r = amdgpu_ib_get(ring, NULL, ndw * 4, &ib); | 772 | ib = kzalloc(sizeof(struct amdgpu_ib), GFP_KERNEL); |
726 | if (r) | 773 | if (!ib) |
774 | return -ENOMEM; | ||
775 | |||
776 | r = amdgpu_ib_get(ring, NULL, ndw * 4, ib); | ||
777 | if (r) { | ||
778 | kfree(ib); | ||
727 | return r; | 779 | return r; |
728 | ib.length_dw = 0; | 780 | } |
781 | |||
782 | ib->length_dw = 0; | ||
729 | 783 | ||
730 | if (!(flags & AMDGPU_PTE_VALID)) { | 784 | if (!(flags & AMDGPU_PTE_VALID)) { |
731 | unsigned i; | 785 | unsigned i; |
732 | 786 | ||
733 | for (i = 0; i < AMDGPU_MAX_RINGS; ++i) { | 787 | for (i = 0; i < AMDGPU_MAX_RINGS; ++i) { |
734 | struct amdgpu_fence *f = vm->ids[i].last_id_use; | 788 | struct amdgpu_fence *f = vm->ids[i].last_id_use; |
735 | amdgpu_sync_fence(&ib.sync, f); | 789 | r = amdgpu_sync_fence(adev, &ib->sync, &f->base); |
790 | if (r) | ||
791 | return r; | ||
736 | } | 792 | } |
737 | } | 793 | } |
738 | 794 | ||
739 | r = amdgpu_vm_update_ptes(adev, vm, &ib, mapping->it.start, | 795 | r = amdgpu_vm_update_ptes(adev, vm, ib, mapping->it.start, |
740 | mapping->it.last + 1, addr + mapping->offset, | 796 | mapping->it.last + 1, addr + mapping->offset, |
741 | flags, gtt_flags); | 797 | flags, gtt_flags); |
742 | 798 | ||
743 | if (r) { | 799 | if (r) { |
744 | amdgpu_ib_free(adev, &ib); | 800 | amdgpu_ib_free(adev, ib); |
801 | kfree(ib); | ||
745 | return r; | 802 | return r; |
746 | } | 803 | } |
747 | 804 | ||
748 | amdgpu_vm_pad_ib(adev, &ib); | 805 | amdgpu_vm_pad_ib(adev, ib); |
749 | WARN_ON(ib.length_dw > ndw); | 806 | WARN_ON(ib->length_dw > ndw); |
807 | r = amdgpu_sched_ib_submit_kernel_helper(adev, ring, ib, 1, | ||
808 | &amdgpu_vm_free_job, | ||
809 | AMDGPU_FENCE_OWNER_VM, | ||
810 | &f); | ||
811 | if (r) | ||
812 | goto error_free; | ||
750 | 813 | ||
751 | r = amdgpu_ib_schedule(adev, 1, &ib, AMDGPU_FENCE_OWNER_VM); | ||
752 | if (r) { | ||
753 | amdgpu_ib_free(adev, &ib); | ||
754 | return r; | ||
755 | } | ||
756 | amdgpu_vm_fence_pts(vm, mapping->it.start, | 814 | amdgpu_vm_fence_pts(vm, mapping->it.start, |
757 | mapping->it.last + 1, ib.fence); | 815 | mapping->it.last + 1, f); |
758 | if (fence) { | 816 | if (fence) { |
759 | amdgpu_fence_unref(fence); | 817 | fence_put(*fence); |
760 | *fence = amdgpu_fence_ref(ib.fence); | 818 | *fence = fence_get(f); |
819 | } | ||
820 | fence_put(f); | ||
821 | if (!amdgpu_enable_scheduler) { | ||
822 | amdgpu_ib_free(adev, ib); | ||
823 | kfree(ib); | ||
761 | } | 824 | } |
762 | amdgpu_ib_free(adev, &ib); | ||
763 | |||
764 | return 0; | 825 | return 0; |
826 | |||
827 | error_free: | ||
828 | amdgpu_ib_free(adev, ib); | ||
829 | kfree(ib); | ||
830 | return r; | ||
765 | } | 831 | } |
766 | 832 | ||
767 | /** | 833 | /** |
@@ -794,21 +860,25 @@ int amdgpu_vm_bo_update(struct amdgpu_device *adev, | |||
794 | addr = 0; | 860 | addr = 0; |
795 | } | 861 | } |
796 | 862 | ||
797 | if (addr == bo_va->addr) | ||
798 | return 0; | ||
799 | |||
800 | flags = amdgpu_ttm_tt_pte_flags(adev, bo_va->bo->tbo.ttm, mem); | 863 | flags = amdgpu_ttm_tt_pte_flags(adev, bo_va->bo->tbo.ttm, mem); |
801 | 864 | ||
802 | list_for_each_entry(mapping, &bo_va->mappings, list) { | 865 | spin_lock(&vm->status_lock); |
866 | if (!list_empty(&bo_va->vm_status)) | ||
867 | list_splice_init(&bo_va->valids, &bo_va->invalids); | ||
868 | spin_unlock(&vm->status_lock); | ||
869 | |||
870 | list_for_each_entry(mapping, &bo_va->invalids, list) { | ||
803 | r = amdgpu_vm_bo_update_mapping(adev, vm, mapping, addr, | 871 | r = amdgpu_vm_bo_update_mapping(adev, vm, mapping, addr, |
804 | flags, &bo_va->last_pt_update); | 872 | flags, &bo_va->last_pt_update); |
805 | if (r) | 873 | if (r) |
806 | return r; | 874 | return r; |
807 | } | 875 | } |
808 | 876 | ||
809 | bo_va->addr = addr; | ||
810 | spin_lock(&vm->status_lock); | 877 | spin_lock(&vm->status_lock); |
878 | list_splice_init(&bo_va->invalids, &bo_va->valids); | ||
811 | list_del_init(&bo_va->vm_status); | 879 | list_del_init(&bo_va->vm_status); |
880 | if (!mem) | ||
881 | list_add(&bo_va->vm_status, &vm->cleared); | ||
812 | spin_unlock(&vm->status_lock); | 882 | spin_unlock(&vm->status_lock); |
813 | 883 | ||
814 | return 0; | 884 | return 0; |
@@ -861,7 +931,7 @@ int amdgpu_vm_clear_invalids(struct amdgpu_device *adev, | |||
861 | struct amdgpu_vm *vm, struct amdgpu_sync *sync) | 931 | struct amdgpu_vm *vm, struct amdgpu_sync *sync) |
862 | { | 932 | { |
863 | struct amdgpu_bo_va *bo_va = NULL; | 933 | struct amdgpu_bo_va *bo_va = NULL; |
864 | int r; | 934 | int r = 0; |
865 | 935 | ||
866 | spin_lock(&vm->status_lock); | 936 | spin_lock(&vm->status_lock); |
867 | while (!list_empty(&vm->invalidated)) { | 937 | while (!list_empty(&vm->invalidated)) { |
@@ -878,8 +948,9 @@ int amdgpu_vm_clear_invalids(struct amdgpu_device *adev, | |||
878 | spin_unlock(&vm->status_lock); | 948 | spin_unlock(&vm->status_lock); |
879 | 949 | ||
880 | if (bo_va) | 950 | if (bo_va) |
881 | amdgpu_sync_fence(sync, bo_va->last_pt_update); | 951 | r = amdgpu_sync_fence(adev, sync, bo_va->last_pt_update); |
882 | return 0; | 952 | |
953 | return r; | ||
883 | } | 954 | } |
884 | 955 | ||
885 | /** | 956 | /** |
@@ -907,10 +978,10 @@ struct amdgpu_bo_va *amdgpu_vm_bo_add(struct amdgpu_device *adev, | |||
907 | } | 978 | } |
908 | bo_va->vm = vm; | 979 | bo_va->vm = vm; |
909 | bo_va->bo = bo; | 980 | bo_va->bo = bo; |
910 | bo_va->addr = 0; | ||
911 | bo_va->ref_count = 1; | 981 | bo_va->ref_count = 1; |
912 | INIT_LIST_HEAD(&bo_va->bo_list); | 982 | INIT_LIST_HEAD(&bo_va->bo_list); |
913 | INIT_LIST_HEAD(&bo_va->mappings); | 983 | INIT_LIST_HEAD(&bo_va->valids); |
984 | INIT_LIST_HEAD(&bo_va->invalids); | ||
914 | INIT_LIST_HEAD(&bo_va->vm_status); | 985 | INIT_LIST_HEAD(&bo_va->vm_status); |
915 | 986 | ||
916 | mutex_lock(&vm->mutex); | 987 | mutex_lock(&vm->mutex); |
@@ -999,12 +1070,10 @@ int amdgpu_vm_bo_map(struct amdgpu_device *adev, | |||
999 | mapping->offset = offset; | 1070 | mapping->offset = offset; |
1000 | mapping->flags = flags; | 1071 | mapping->flags = flags; |
1001 | 1072 | ||
1002 | list_add(&mapping->list, &bo_va->mappings); | 1073 | list_add(&mapping->list, &bo_va->invalids); |
1003 | interval_tree_insert(&mapping->it, &vm->va); | 1074 | interval_tree_insert(&mapping->it, &vm->va); |
1004 | trace_amdgpu_vm_bo_map(bo_va, mapping); | 1075 | trace_amdgpu_vm_bo_map(bo_va, mapping); |
1005 | 1076 | ||
1006 | bo_va->addr = 0; | ||
1007 | |||
1008 | /* Make sure the page tables are allocated */ | 1077 | /* Make sure the page tables are allocated */ |
1009 | saddr >>= amdgpu_vm_block_size; | 1078 | saddr >>= amdgpu_vm_block_size; |
1010 | eaddr >>= amdgpu_vm_block_size; | 1079 | eaddr >>= amdgpu_vm_block_size; |
@@ -1085,17 +1154,27 @@ int amdgpu_vm_bo_unmap(struct amdgpu_device *adev, | |||
1085 | { | 1154 | { |
1086 | struct amdgpu_bo_va_mapping *mapping; | 1155 | struct amdgpu_bo_va_mapping *mapping; |
1087 | struct amdgpu_vm *vm = bo_va->vm; | 1156 | struct amdgpu_vm *vm = bo_va->vm; |
1157 | bool valid = true; | ||
1088 | 1158 | ||
1089 | saddr /= AMDGPU_GPU_PAGE_SIZE; | 1159 | saddr /= AMDGPU_GPU_PAGE_SIZE; |
1090 | 1160 | ||
1091 | list_for_each_entry(mapping, &bo_va->mappings, list) { | 1161 | list_for_each_entry(mapping, &bo_va->valids, list) { |
1092 | if (mapping->it.start == saddr) | 1162 | if (mapping->it.start == saddr) |
1093 | break; | 1163 | break; |
1094 | } | 1164 | } |
1095 | 1165 | ||
1096 | if (&mapping->list == &bo_va->mappings) { | 1166 | if (&mapping->list == &bo_va->valids) { |
1097 | amdgpu_bo_unreserve(bo_va->bo); | 1167 | valid = false; |
1098 | return -ENOENT; | 1168 | |
1169 | list_for_each_entry(mapping, &bo_va->invalids, list) { | ||
1170 | if (mapping->it.start == saddr) | ||
1171 | break; | ||
1172 | } | ||
1173 | |||
1174 | if (&mapping->list == &bo_va->invalids) { | ||
1175 | amdgpu_bo_unreserve(bo_va->bo); | ||
1176 | return -ENOENT; | ||
1177 | } | ||
1099 | } | 1178 | } |
1100 | 1179 | ||
1101 | mutex_lock(&vm->mutex); | 1180 | mutex_lock(&vm->mutex); |
@@ -1103,12 +1182,10 @@ int amdgpu_vm_bo_unmap(struct amdgpu_device *adev, | |||
1103 | interval_tree_remove(&mapping->it, &vm->va); | 1182 | interval_tree_remove(&mapping->it, &vm->va); |
1104 | trace_amdgpu_vm_bo_unmap(bo_va, mapping); | 1183 | trace_amdgpu_vm_bo_unmap(bo_va, mapping); |
1105 | 1184 | ||
1106 | if (bo_va->addr) { | 1185 | if (valid) |
1107 | /* clear the old address */ | ||
1108 | list_add(&mapping->list, &vm->freed); | 1186 | list_add(&mapping->list, &vm->freed); |
1109 | } else { | 1187 | else |
1110 | kfree(mapping); | 1188 | kfree(mapping); |
1111 | } | ||
1112 | mutex_unlock(&vm->mutex); | 1189 | mutex_unlock(&vm->mutex); |
1113 | amdgpu_bo_unreserve(bo_va->bo); | 1190 | amdgpu_bo_unreserve(bo_va->bo); |
1114 | 1191 | ||
@@ -1139,16 +1216,19 @@ void amdgpu_vm_bo_rmv(struct amdgpu_device *adev, | |||
1139 | list_del(&bo_va->vm_status); | 1216 | list_del(&bo_va->vm_status); |
1140 | spin_unlock(&vm->status_lock); | 1217 | spin_unlock(&vm->status_lock); |
1141 | 1218 | ||
1142 | list_for_each_entry_safe(mapping, next, &bo_va->mappings, list) { | 1219 | list_for_each_entry_safe(mapping, next, &bo_va->valids, list) { |
1143 | list_del(&mapping->list); | 1220 | list_del(&mapping->list); |
1144 | interval_tree_remove(&mapping->it, &vm->va); | 1221 | interval_tree_remove(&mapping->it, &vm->va); |
1145 | trace_amdgpu_vm_bo_unmap(bo_va, mapping); | 1222 | trace_amdgpu_vm_bo_unmap(bo_va, mapping); |
1146 | if (bo_va->addr) | 1223 | list_add(&mapping->list, &vm->freed); |
1147 | list_add(&mapping->list, &vm->freed); | ||
1148 | else | ||
1149 | kfree(mapping); | ||
1150 | } | 1224 | } |
1151 | amdgpu_fence_unref(&bo_va->last_pt_update); | 1225 | list_for_each_entry_safe(mapping, next, &bo_va->invalids, list) { |
1226 | list_del(&mapping->list); | ||
1227 | interval_tree_remove(&mapping->it, &vm->va); | ||
1228 | kfree(mapping); | ||
1229 | } | ||
1230 | |||
1231 | fence_put(bo_va->last_pt_update); | ||
1152 | kfree(bo_va); | 1232 | kfree(bo_va); |
1153 | 1233 | ||
1154 | mutex_unlock(&vm->mutex); | 1234 | mutex_unlock(&vm->mutex); |
@@ -1169,12 +1249,10 @@ void amdgpu_vm_bo_invalidate(struct amdgpu_device *adev, | |||
1169 | struct amdgpu_bo_va *bo_va; | 1249 | struct amdgpu_bo_va *bo_va; |
1170 | 1250 | ||
1171 | list_for_each_entry(bo_va, &bo->va, bo_list) { | 1251 | list_for_each_entry(bo_va, &bo->va, bo_list) { |
1172 | if (bo_va->addr) { | 1252 | spin_lock(&bo_va->vm->status_lock); |
1173 | spin_lock(&bo_va->vm->status_lock); | 1253 | if (list_empty(&bo_va->vm_status)) |
1174 | list_del(&bo_va->vm_status); | ||
1175 | list_add(&bo_va->vm_status, &bo_va->vm->invalidated); | 1254 | list_add(&bo_va->vm_status, &bo_va->vm->invalidated); |
1176 | spin_unlock(&bo_va->vm->status_lock); | 1255 | spin_unlock(&bo_va->vm->status_lock); |
1177 | } | ||
1178 | } | 1256 | } |
1179 | } | 1257 | } |
1180 | 1258 | ||
@@ -1202,6 +1280,7 @@ int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm) | |||
1202 | vm->va = RB_ROOT; | 1280 | vm->va = RB_ROOT; |
1203 | spin_lock_init(&vm->status_lock); | 1281 | spin_lock_init(&vm->status_lock); |
1204 | INIT_LIST_HEAD(&vm->invalidated); | 1282 | INIT_LIST_HEAD(&vm->invalidated); |
1283 | INIT_LIST_HEAD(&vm->cleared); | ||
1205 | INIT_LIST_HEAD(&vm->freed); | 1284 | INIT_LIST_HEAD(&vm->freed); |
1206 | 1285 | ||
1207 | pd_size = amdgpu_vm_directory_size(adev); | 1286 | pd_size = amdgpu_vm_directory_size(adev); |
@@ -1215,6 +1294,8 @@ int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm) | |||
1215 | return -ENOMEM; | 1294 | return -ENOMEM; |
1216 | } | 1295 | } |
1217 | 1296 | ||
1297 | vm->page_directory_fence = NULL; | ||
1298 | |||
1218 | r = amdgpu_bo_create(adev, pd_size, align, true, | 1299 | r = amdgpu_bo_create(adev, pd_size, align, true, |
1219 | AMDGPU_GEM_DOMAIN_VRAM, 0, | 1300 | AMDGPU_GEM_DOMAIN_VRAM, 0, |
1220 | NULL, &vm->page_directory); | 1301 | NULL, &vm->page_directory); |
@@ -1263,6 +1344,7 @@ void amdgpu_vm_fini(struct amdgpu_device *adev, struct amdgpu_vm *vm) | |||
1263 | kfree(vm->page_tables); | 1344 | kfree(vm->page_tables); |
1264 | 1345 | ||
1265 | amdgpu_bo_unref(&vm->page_directory); | 1346 | amdgpu_bo_unref(&vm->page_directory); |
1347 | fence_put(vm->page_directory_fence); | ||
1266 | 1348 | ||
1267 | for (i = 0; i < AMDGPU_MAX_RINGS; ++i) { | 1349 | for (i = 0; i < AMDGPU_MAX_RINGS; ++i) { |
1268 | amdgpu_fence_unref(&vm->ids[i].flushed_updates); | 1350 | amdgpu_fence_unref(&vm->ids[i].flushed_updates); |