diff options
author | Christian König <christian.koenig@amd.com> | 2016-01-25 08:27:31 -0500 |
---|---|---|
committer | Alex Deucher <alexander.deucher@amd.com> | 2016-02-10 14:17:05 -0500 |
commit | a14faa6573d956e7212c41f4dd0e346798491a7d (patch) | |
tree | 0d450e5eae9bcc85735d0296c43659df326c6c10 /drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | |
parent | 9ab21462894ddcb5463211cefaab18334fdde244 (diff) |
drm/amdgpu: split VM mappings into smaller operations (v3)
If we can't copy entries from the GTT or fill them with one command split
up the mapping operation into multiple ones.
v2: agd: rebase on upstream
v3: squash in Christian's fix
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 | 104 |
1 files changed, 77 insertions, 27 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c index b371a60837eb..7b660db36931 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | |||
@@ -696,42 +696,32 @@ static int amdgpu_vm_update_ptes(struct amdgpu_device *adev, | |||
696 | * | 696 | * |
697 | * @adev: amdgpu_device pointer | 697 | * @adev: amdgpu_device pointer |
698 | * @gtt: GART instance to use for mapping | 698 | * @gtt: GART instance to use for mapping |
699 | * @gtt_flags: flags as they are used for GTT | ||
699 | * @vm: requested vm | 700 | * @vm: requested vm |
700 | * @mapping: mapped range and flags to use for the update | 701 | * @start: start of mapped range |
702 | * @last: last mapped entry | ||
703 | * @flags: flags for the entries | ||
701 | * @addr: addr to set the area to | 704 | * @addr: addr to set the area to |
702 | * @gtt_flags: flags as they are used for GTT | ||
703 | * @fence: optional resulting fence | 705 | * @fence: optional resulting fence |
704 | * | 706 | * |
705 | * Fill in the page table entries for @mapping. | 707 | * Fill in the page table entries between @start and @last. |
706 | * Returns 0 for success, -EINVAL for failure. | 708 | * Returns 0 for success, -EINVAL for failure. |
707 | * | ||
708 | * Object have to be reserved and mutex must be locked! | ||
709 | */ | 709 | */ |
710 | static int amdgpu_vm_bo_update_mapping(struct amdgpu_device *adev, | 710 | static int amdgpu_vm_bo_update_mapping(struct amdgpu_device *adev, |
711 | struct amdgpu_gart *gtt, | 711 | struct amdgpu_gart *gtt, |
712 | uint32_t gtt_flags, | 712 | uint32_t gtt_flags, |
713 | struct amdgpu_vm *vm, | 713 | struct amdgpu_vm *vm, |
714 | struct amdgpu_bo_va_mapping *mapping, | 714 | uint64_t start, uint64_t last, |
715 | uint64_t addr, struct fence **fence) | 715 | uint32_t flags, uint64_t addr, |
716 | struct fence **fence) | ||
716 | { | 717 | { |
717 | struct amdgpu_ring *ring = adev->vm_manager.vm_pte_funcs_ring; | 718 | struct amdgpu_ring *ring = adev->vm_manager.vm_pte_funcs_ring; |
718 | unsigned nptes, ncmds, ndw; | 719 | unsigned nptes, ncmds, ndw; |
719 | uint32_t flags = gtt_flags; | ||
720 | struct amdgpu_ib *ib; | 720 | struct amdgpu_ib *ib; |
721 | struct fence *f = NULL; | 721 | struct fence *f = NULL; |
722 | int r; | 722 | int r; |
723 | 723 | ||
724 | /* normally,bo_va->flags only contians READABLE and WIRTEABLE bit go here | 724 | nptes = last - start + 1; |
725 | * but in case of something, we filter the flags in first place | ||
726 | */ | ||
727 | if (!(mapping->flags & AMDGPU_PTE_READABLE)) | ||
728 | flags &= ~AMDGPU_PTE_READABLE; | ||
729 | if (!(mapping->flags & AMDGPU_PTE_WRITEABLE)) | ||
730 | flags &= ~AMDGPU_PTE_WRITEABLE; | ||
731 | |||
732 | trace_amdgpu_vm_bo_update(mapping); | ||
733 | |||
734 | nptes = mapping->it.last - mapping->it.start + 1; | ||
735 | 725 | ||
736 | /* | 726 | /* |
737 | * reserve space for one command every (1 << BLOCK_SIZE) | 727 | * reserve space for one command every (1 << BLOCK_SIZE) |
@@ -773,10 +763,8 @@ static int amdgpu_vm_bo_update_mapping(struct amdgpu_device *adev, | |||
773 | 763 | ||
774 | ib->length_dw = 0; | 764 | ib->length_dw = 0; |
775 | 765 | ||
776 | r = amdgpu_vm_update_ptes(adev, gtt, gtt_flags, vm, ib, | 766 | r = amdgpu_vm_update_ptes(adev, gtt, gtt_flags, vm, ib, start, |
777 | mapping->it.start, mapping->it.last + 1, | 767 | last + 1, addr, flags); |
778 | addr + mapping->offset, flags); | ||
779 | |||
780 | if (r) { | 768 | if (r) { |
781 | amdgpu_ib_free(adev, ib); | 769 | amdgpu_ib_free(adev, ib); |
782 | kfree(ib); | 770 | kfree(ib); |
@@ -807,6 +795,68 @@ error_free: | |||
807 | } | 795 | } |
808 | 796 | ||
809 | /** | 797 | /** |
798 | * amdgpu_vm_bo_split_mapping - split a mapping into smaller chunks | ||
799 | * | ||
800 | * @adev: amdgpu_device pointer | ||
801 | * @gtt: GART instance to use for mapping | ||
802 | * @vm: requested vm | ||
803 | * @mapping: mapped range and flags to use for the update | ||
804 | * @addr: addr to set the area to | ||
805 | * @gtt_flags: flags as they are used for GTT | ||
806 | * @fence: optional resulting fence | ||
807 | * | ||
808 | * Split the mapping into smaller chunks so that each update fits | ||
809 | * into a SDMA IB. | ||
810 | * Returns 0 for success, -EINVAL for failure. | ||
811 | */ | ||
812 | static int amdgpu_vm_bo_split_mapping(struct amdgpu_device *adev, | ||
813 | struct amdgpu_gart *gtt, | ||
814 | uint32_t gtt_flags, | ||
815 | struct amdgpu_vm *vm, | ||
816 | struct amdgpu_bo_va_mapping *mapping, | ||
817 | uint64_t addr, struct fence **fence) | ||
818 | { | ||
819 | const uint64_t max_size = 64ULL * 1024ULL * 1024ULL / AMDGPU_GPU_PAGE_SIZE; | ||
820 | |||
821 | uint64_t start = mapping->it.start; | ||
822 | uint32_t flags = gtt_flags; | ||
823 | int r; | ||
824 | |||
825 | /* normally,bo_va->flags only contians READABLE and WIRTEABLE bit go here | ||
826 | * but in case of something, we filter the flags in first place | ||
827 | */ | ||
828 | if (!(mapping->flags & AMDGPU_PTE_READABLE)) | ||
829 | flags &= ~AMDGPU_PTE_READABLE; | ||
830 | if (!(mapping->flags & AMDGPU_PTE_WRITEABLE)) | ||
831 | flags &= ~AMDGPU_PTE_WRITEABLE; | ||
832 | |||
833 | trace_amdgpu_vm_bo_update(mapping); | ||
834 | |||
835 | addr += mapping->offset; | ||
836 | |||
837 | if (!gtt || ((gtt == &adev->gart) && (flags == gtt_flags))) | ||
838 | return amdgpu_vm_bo_update_mapping(adev, gtt, gtt_flags, vm, | ||
839 | start, mapping->it.last, | ||
840 | flags, addr, fence); | ||
841 | |||
842 | while (start != mapping->it.last + 1) { | ||
843 | uint64_t last; | ||
844 | |||
845 | last = min((uint64_t)mapping->it.last, start + max_size); | ||
846 | r = amdgpu_vm_bo_update_mapping(adev, gtt, gtt_flags, vm, | ||
847 | start, last, flags, addr, | ||
848 | fence); | ||
849 | if (r) | ||
850 | return r; | ||
851 | |||
852 | start = last + 1; | ||
853 | addr += max_size; | ||
854 | } | ||
855 | |||
856 | return 0; | ||
857 | } | ||
858 | |||
859 | /** | ||
810 | * amdgpu_vm_bo_update - update all BO mappings in the vm page table | 860 | * amdgpu_vm_bo_update - update all BO mappings in the vm page table |
811 | * | 861 | * |
812 | * @adev: amdgpu_device pointer | 862 | * @adev: amdgpu_device pointer |
@@ -855,8 +905,8 @@ int amdgpu_vm_bo_update(struct amdgpu_device *adev, | |||
855 | spin_unlock(&vm->status_lock); | 905 | spin_unlock(&vm->status_lock); |
856 | 906 | ||
857 | list_for_each_entry(mapping, &bo_va->invalids, list) { | 907 | list_for_each_entry(mapping, &bo_va->invalids, list) { |
858 | r = amdgpu_vm_bo_update_mapping(adev, gtt, flags, vm, mapping, addr, | 908 | r = amdgpu_vm_bo_split_mapping(adev, gtt, flags, vm, mapping, addr, |
859 | &bo_va->last_pt_update); | 909 | &bo_va->last_pt_update); |
860 | if (r) | 910 | if (r) |
861 | return r; | 911 | return r; |
862 | } | 912 | } |
@@ -902,8 +952,8 @@ int amdgpu_vm_clear_freed(struct amdgpu_device *adev, | |||
902 | struct amdgpu_bo_va_mapping, list); | 952 | struct amdgpu_bo_va_mapping, list); |
903 | list_del(&mapping->list); | 953 | list_del(&mapping->list); |
904 | spin_unlock(&vm->freed_lock); | 954 | spin_unlock(&vm->freed_lock); |
905 | r = amdgpu_vm_bo_update_mapping(adev, NULL, 0, vm, mapping, | 955 | r = amdgpu_vm_bo_split_mapping(adev, NULL, 0, vm, mapping, |
906 | 0, NULL); | 956 | 0, NULL); |
907 | kfree(mapping); | 957 | kfree(mapping); |
908 | if (r) | 958 | if (r) |
909 | return r; | 959 | return r; |