diff options
author | Christian König <christian.koenig@amd.com> | 2016-09-16 09:36:49 -0400 |
---|---|---|
committer | Alex Deucher <alexander.deucher@amd.com> | 2016-10-25 14:38:25 -0400 |
commit | f8991bab1aa2121e33b8569857dfb22e536bc396 (patch) | |
tree | 14fd7934fdda92dbe79006fb8e3fbae95504f712 /drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | |
parent | 42e8cb5001d317ebbfcd95af26f263af377ff3a5 (diff) |
drm/amdgpu: update the shadow PD together with the real one v2
Far less CPU cycles needed for this approach.
v2: fix typo
Signed-off-by: Christian König <christian.koenig@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c')
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 134 |
1 files changed, 69 insertions, 65 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c index e2fefbbd3cc8..840ac52f45b6 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | |||
@@ -612,16 +612,26 @@ static uint64_t amdgpu_vm_map_gart(const dma_addr_t *pages_addr, uint64_t addr) | |||
612 | return result; | 612 | return result; |
613 | } | 613 | } |
614 | 614 | ||
615 | static int amdgpu_vm_update_pd_or_shadow(struct amdgpu_device *adev, | 615 | /* |
616 | struct amdgpu_vm *vm, | 616 | * amdgpu_vm_update_pdes - make sure that page directory is valid |
617 | bool shadow) | 617 | * |
618 | * @adev: amdgpu_device pointer | ||
619 | * @vm: requested vm | ||
620 | * @start: start of GPU address range | ||
621 | * @end: end of GPU address range | ||
622 | * | ||
623 | * Allocates new page tables if necessary | ||
624 | * and updates the page directory. | ||
625 | * Returns 0 for success, error for failure. | ||
626 | */ | ||
627 | int amdgpu_vm_update_page_directory(struct amdgpu_device *adev, | ||
628 | struct amdgpu_vm *vm) | ||
618 | { | 629 | { |
630 | struct amdgpu_bo *shadow; | ||
619 | struct amdgpu_ring *ring; | 631 | struct amdgpu_ring *ring; |
620 | struct amdgpu_bo *pd = shadow ? vm->page_directory->shadow : | 632 | uint64_t pd_addr, shadow_addr; |
621 | vm->page_directory; | ||
622 | uint64_t pd_addr; | ||
623 | uint32_t incr = AMDGPU_VM_PTE_COUNT * 8; | 633 | uint32_t incr = AMDGPU_VM_PTE_COUNT * 8; |
624 | uint64_t last_pde = ~0, last_pt = ~0; | 634 | uint64_t last_pde = ~0, last_pt = ~0, last_shadow = ~0; |
625 | unsigned count = 0, pt_idx, ndw; | 635 | unsigned count = 0, pt_idx, ndw; |
626 | struct amdgpu_job *job; | 636 | struct amdgpu_job *job; |
627 | struct amdgpu_pte_update_params params; | 637 | struct amdgpu_pte_update_params params; |
@@ -629,15 +639,8 @@ static int amdgpu_vm_update_pd_or_shadow(struct amdgpu_device *adev, | |||
629 | 639 | ||
630 | int r; | 640 | int r; |
631 | 641 | ||
632 | if (!pd) | ||
633 | return 0; | ||
634 | |||
635 | r = amdgpu_ttm_bind(&pd->tbo, &pd->tbo.mem); | ||
636 | if (r) | ||
637 | return r; | ||
638 | |||
639 | pd_addr = amdgpu_bo_gpu_offset(pd); | ||
640 | ring = container_of(vm->entity.sched, struct amdgpu_ring, sched); | 642 | ring = container_of(vm->entity.sched, struct amdgpu_ring, sched); |
643 | shadow = vm->page_directory->shadow; | ||
641 | 644 | ||
642 | /* padding, etc. */ | 645 | /* padding, etc. */ |
643 | ndw = 64; | 646 | ndw = 64; |
@@ -645,6 +648,17 @@ static int amdgpu_vm_update_pd_or_shadow(struct amdgpu_device *adev, | |||
645 | /* assume the worst case */ | 648 | /* assume the worst case */ |
646 | ndw += vm->max_pde_used * 6; | 649 | ndw += vm->max_pde_used * 6; |
647 | 650 | ||
651 | pd_addr = amdgpu_bo_gpu_offset(vm->page_directory); | ||
652 | if (shadow) { | ||
653 | r = amdgpu_ttm_bind(&shadow->tbo, &shadow->tbo.mem); | ||
654 | if (r) | ||
655 | return r; | ||
656 | shadow_addr = amdgpu_bo_gpu_offset(shadow); | ||
657 | ndw *= 2; | ||
658 | } else { | ||
659 | shadow_addr = 0; | ||
660 | } | ||
661 | |||
648 | r = amdgpu_job_alloc_with_ib(adev, ndw * 4, &job); | 662 | r = amdgpu_job_alloc_with_ib(adev, ndw * 4, &job); |
649 | if (r) | 663 | if (r) |
650 | return r; | 664 | return r; |
@@ -662,23 +676,19 @@ static int amdgpu_vm_update_pd_or_shadow(struct amdgpu_device *adev, | |||
662 | continue; | 676 | continue; |
663 | 677 | ||
664 | if (bo->shadow) { | 678 | if (bo->shadow) { |
665 | struct amdgpu_bo *shadow = bo->shadow; | 679 | struct amdgpu_bo *pt_shadow = bo->shadow; |
666 | 680 | ||
667 | r = amdgpu_ttm_bind(&shadow->tbo, &shadow->tbo.mem); | 681 | r = amdgpu_ttm_bind(&pt_shadow->tbo, |
682 | &pt_shadow->tbo.mem); | ||
668 | if (r) | 683 | if (r) |
669 | return r; | 684 | return r; |
670 | } | 685 | } |
671 | 686 | ||
672 | pt = amdgpu_bo_gpu_offset(bo); | 687 | pt = amdgpu_bo_gpu_offset(bo); |
673 | if (!shadow) { | 688 | if (vm->page_tables[pt_idx].addr == pt) |
674 | if (vm->page_tables[pt_idx].addr == pt) | 689 | continue; |
675 | continue; | 690 | |
676 | vm->page_tables[pt_idx].addr = pt; | 691 | vm->page_tables[pt_idx].addr = pt; |
677 | } else { | ||
678 | if (vm->page_tables[pt_idx].shadow_addr == pt) | ||
679 | continue; | ||
680 | vm->page_tables[pt_idx].shadow_addr = pt; | ||
681 | } | ||
682 | 692 | ||
683 | pde = pd_addr + pt_idx * 8; | 693 | pde = pd_addr + pt_idx * 8; |
684 | if (((last_pde + 8 * count) != pde) || | 694 | if (((last_pde + 8 * count) != pde) || |
@@ -686,6 +696,13 @@ static int amdgpu_vm_update_pd_or_shadow(struct amdgpu_device *adev, | |||
686 | (count == AMDGPU_VM_MAX_UPDATE_SIZE)) { | 696 | (count == AMDGPU_VM_MAX_UPDATE_SIZE)) { |
687 | 697 | ||
688 | if (count) { | 698 | if (count) { |
699 | if (shadow) | ||
700 | amdgpu_vm_do_set_ptes(¶ms, | ||
701 | last_shadow, | ||
702 | last_pt, count, | ||
703 | incr, | ||
704 | AMDGPU_PTE_VALID); | ||
705 | |||
689 | amdgpu_vm_do_set_ptes(¶ms, last_pde, | 706 | amdgpu_vm_do_set_ptes(¶ms, last_pde, |
690 | last_pt, count, incr, | 707 | last_pt, count, incr, |
691 | AMDGPU_PTE_VALID); | 708 | AMDGPU_PTE_VALID); |
@@ -693,34 +710,44 @@ static int amdgpu_vm_update_pd_or_shadow(struct amdgpu_device *adev, | |||
693 | 710 | ||
694 | count = 1; | 711 | count = 1; |
695 | last_pde = pde; | 712 | last_pde = pde; |
713 | last_shadow = shadow_addr + pt_idx * 8; | ||
696 | last_pt = pt; | 714 | last_pt = pt; |
697 | } else { | 715 | } else { |
698 | ++count; | 716 | ++count; |
699 | } | 717 | } |
700 | } | 718 | } |
701 | 719 | ||
702 | if (count) | 720 | if (count) { |
721 | if (vm->page_directory->shadow) | ||
722 | amdgpu_vm_do_set_ptes(¶ms, last_shadow, last_pt, | ||
723 | count, incr, AMDGPU_PTE_VALID); | ||
724 | |||
703 | amdgpu_vm_do_set_ptes(¶ms, last_pde, last_pt, | 725 | amdgpu_vm_do_set_ptes(¶ms, last_pde, last_pt, |
704 | count, incr, AMDGPU_PTE_VALID); | 726 | count, incr, AMDGPU_PTE_VALID); |
727 | } | ||
728 | |||
729 | if (params.ib->length_dw == 0) { | ||
730 | amdgpu_job_free(job); | ||
731 | return 0; | ||
732 | } | ||
705 | 733 | ||
706 | if (params.ib->length_dw != 0) { | 734 | amdgpu_ring_pad_ib(ring, params.ib); |
707 | amdgpu_ring_pad_ib(ring, params.ib); | 735 | amdgpu_sync_resv(adev, &job->sync, vm->page_directory->tbo.resv, |
708 | amdgpu_sync_resv(adev, &job->sync, pd->tbo.resv, | 736 | AMDGPU_FENCE_OWNER_VM); |
737 | if (shadow) | ||
738 | amdgpu_sync_resv(adev, &job->sync, shadow->tbo.resv, | ||
709 | AMDGPU_FENCE_OWNER_VM); | 739 | AMDGPU_FENCE_OWNER_VM); |
710 | WARN_ON(params.ib->length_dw > ndw); | ||
711 | r = amdgpu_job_submit(job, ring, &vm->entity, | ||
712 | AMDGPU_FENCE_OWNER_VM, &fence); | ||
713 | if (r) | ||
714 | goto error_free; | ||
715 | 740 | ||
716 | amdgpu_bo_fence(pd, fence, true); | 741 | WARN_ON(params.ib->length_dw > ndw); |
717 | fence_put(vm->page_directory_fence); | 742 | r = amdgpu_job_submit(job, ring, &vm->entity, |
718 | vm->page_directory_fence = fence_get(fence); | 743 | AMDGPU_FENCE_OWNER_VM, &fence); |
719 | fence_put(fence); | 744 | if (r) |
745 | goto error_free; | ||
720 | 746 | ||
721 | } else { | 747 | amdgpu_bo_fence(vm->page_directory, fence, true); |
722 | amdgpu_job_free(job); | 748 | fence_put(vm->page_directory_fence); |
723 | } | 749 | vm->page_directory_fence = fence_get(fence); |
750 | fence_put(fence); | ||
724 | 751 | ||
725 | return 0; | 752 | return 0; |
726 | 753 | ||
@@ -729,29 +756,6 @@ error_free: | |||
729 | return r; | 756 | return r; |
730 | } | 757 | } |
731 | 758 | ||
732 | /* | ||
733 | * amdgpu_vm_update_pdes - make sure that page directory is valid | ||
734 | * | ||
735 | * @adev: amdgpu_device pointer | ||
736 | * @vm: requested vm | ||
737 | * @start: start of GPU address range | ||
738 | * @end: end of GPU address range | ||
739 | * | ||
740 | * Allocates new page tables if necessary | ||
741 | * and updates the page directory. | ||
742 | * Returns 0 for success, error for failure. | ||
743 | */ | ||
744 | int amdgpu_vm_update_page_directory(struct amdgpu_device *adev, | ||
745 | struct amdgpu_vm *vm) | ||
746 | { | ||
747 | int r; | ||
748 | |||
749 | r = amdgpu_vm_update_pd_or_shadow(adev, vm, true); | ||
750 | if (r) | ||
751 | return r; | ||
752 | return amdgpu_vm_update_pd_or_shadow(adev, vm, false); | ||
753 | } | ||
754 | |||
755 | /** | 759 | /** |
756 | * amdgpu_vm_update_ptes - make sure that page tables are valid | 760 | * amdgpu_vm_update_ptes - make sure that page tables are valid |
757 | * | 761 | * |