aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
diff options
context:
space:
mode:
authorChristian König <christian.koenig@amd.com>2016-01-25 08:27:31 -0500
committerAlex Deucher <alexander.deucher@amd.com>2016-02-10 14:17:05 -0500
commita14faa6573d956e7212c41f4dd0e346798491a7d (patch)
tree0d450e5eae9bcc85735d0296c43659df326c6c10 /drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
parent9ab21462894ddcb5463211cefaab18334fdde244 (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.c104
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 */
710static int amdgpu_vm_bo_update_mapping(struct amdgpu_device *adev, 710static 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 */
812static 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;