aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
diff options
context:
space:
mode:
authorChristian König <christian.koenig@amd.com>2019-01-30 10:07:29 -0500
committerAlex Deucher <alexander.deucher@amd.com>2019-03-19 16:36:48 -0400
commit0ce15d6f7d3fb1162fd7de2829dbdf6d63a6a02a (patch)
treec83a9a486a58d392808ea1453a7f5fa8b689d352 /drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
parent780637cbdf8fd614cc85a01c6c810d9d28902a59 (diff)
drm/amdgpu: allocate VM PDs/PTs on demand
Let's start to allocate VM PDs/PTs on demand instead of pre-allocating them during mapping. Signed-off-by: Christian König <christian.koenig@amd.com> Reviewed-by: Felix Kuehling <Felix.Kuehling@amd.com> Acked-by: Huang Rui <ray.huang@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.c136
1 files changed, 38 insertions, 98 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
index 90c6970e080f..b25be87eb412 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
@@ -521,47 +521,6 @@ static void amdgpu_vm_pt_next(struct amdgpu_device *adev,
521} 521}
522 522
523/** 523/**
524 * amdgpu_vm_pt_first_leaf - get first leaf PD/PT
525 *
526 * @adev: amdgpu_device pointer
527 * @vm: amdgpu_vm structure
528 * @start: start addr of the walk
529 * @cursor: state to initialize
530 *
531 * Start a walk and go directly to the leaf node.
532 */
533static void amdgpu_vm_pt_first_leaf(struct amdgpu_device *adev,
534 struct amdgpu_vm *vm, uint64_t start,
535 struct amdgpu_vm_pt_cursor *cursor)
536{
537 amdgpu_vm_pt_start(adev, vm, start, cursor);
538 while (amdgpu_vm_pt_descendant(adev, cursor));
539}
540
541/**
542 * amdgpu_vm_pt_next_leaf - get next leaf PD/PT
543 *
544 * @adev: amdgpu_device pointer
545 * @cursor: current state
546 *
547 * Walk the PD/PT tree to the next leaf node.
548 */
549static void amdgpu_vm_pt_next_leaf(struct amdgpu_device *adev,
550 struct amdgpu_vm_pt_cursor *cursor)
551{
552 amdgpu_vm_pt_next(adev, cursor);
553 if (cursor->pfn != ~0ll)
554 while (amdgpu_vm_pt_descendant(adev, cursor));
555}
556
557/**
558 * for_each_amdgpu_vm_pt_leaf - walk over all leaf PDs/PTs in the hierarchy
559 */
560#define for_each_amdgpu_vm_pt_leaf(adev, vm, start, end, cursor) \
561 for (amdgpu_vm_pt_first_leaf((adev), (vm), (start), &(cursor)); \
562 (cursor).pfn <= end; amdgpu_vm_pt_next_leaf((adev), &(cursor)))
563
564/**
565 * amdgpu_vm_pt_first_dfs - start a deep first search 524 * amdgpu_vm_pt_first_dfs - start a deep first search
566 * 525 *
567 * @adev: amdgpu_device structure 526 * @adev: amdgpu_device structure
@@ -932,74 +891,51 @@ static void amdgpu_vm_bo_param(struct amdgpu_device *adev, struct amdgpu_vm *vm,
932 * Returns: 891 * Returns:
933 * 0 on success, errno otherwise. 892 * 0 on success, errno otherwise.
934 */ 893 */
935int amdgpu_vm_alloc_pts(struct amdgpu_device *adev, 894static int amdgpu_vm_alloc_pts(struct amdgpu_device *adev,
936 struct amdgpu_vm *vm, 895 struct amdgpu_vm *vm,
937 uint64_t saddr, uint64_t size) 896 struct amdgpu_vm_pt_cursor *cursor)
938{ 897{
939 struct amdgpu_vm_pt_cursor cursor; 898 struct amdgpu_vm_pt *entry = cursor->entry;
899 struct amdgpu_bo_param bp;
940 struct amdgpu_bo *pt; 900 struct amdgpu_bo *pt;
941 uint64_t eaddr;
942 int r; 901 int r;
943 902
944 /* validate the parameters */ 903 if (cursor->level < AMDGPU_VM_PTB && !entry->entries) {
945 if (saddr & AMDGPU_GPU_PAGE_MASK || size & AMDGPU_GPU_PAGE_MASK) 904 unsigned num_entries;
946 return -EINVAL;
947 905
948 eaddr = saddr + size - 1; 906 num_entries = amdgpu_vm_num_entries(adev, cursor->level);
949 907 entry->entries = kvmalloc_array(num_entries,
950 saddr /= AMDGPU_GPU_PAGE_SIZE; 908 sizeof(*entry->entries),
951 eaddr /= AMDGPU_GPU_PAGE_SIZE; 909 GFP_KERNEL | __GFP_ZERO);
952 910 if (!entry->entries)
953 if (eaddr >= adev->vm_manager.max_pfn) { 911 return -ENOMEM;
954 dev_err(adev->dev, "va above limit (0x%08llX >= 0x%08llX)\n",
955 eaddr, adev->vm_manager.max_pfn);
956 return -EINVAL;
957 } 912 }
958 913
959 for_each_amdgpu_vm_pt_leaf(adev, vm, saddr, eaddr, cursor) { 914 if (entry->base.bo)
960 struct amdgpu_vm_pt *entry = cursor.entry; 915 return 0;
961 struct amdgpu_bo_param bp;
962
963 if (cursor.level < AMDGPU_VM_PTB) {
964 unsigned num_entries;
965
966 num_entries = amdgpu_vm_num_entries(adev, cursor.level);
967 entry->entries = kvmalloc_array(num_entries,
968 sizeof(*entry->entries),
969 GFP_KERNEL |
970 __GFP_ZERO);
971 if (!entry->entries)
972 return -ENOMEM;
973 }
974
975
976 if (entry->base.bo)
977 continue;
978
979 amdgpu_vm_bo_param(adev, vm, cursor.level, &bp);
980
981 r = amdgpu_bo_create(adev, &bp, &pt);
982 if (r)
983 return r;
984
985 if (vm->use_cpu_for_update) {
986 r = amdgpu_bo_kmap(pt, NULL);
987 if (r)
988 goto error_free_pt;
989 }
990 916
991 /* Keep a reference to the root directory to avoid 917 amdgpu_vm_bo_param(adev, vm, cursor->level, &bp);
992 * freeing them up in the wrong order.
993 */
994 pt->parent = amdgpu_bo_ref(cursor.parent->base.bo);
995 918
996 amdgpu_vm_bo_base_init(&entry->base, vm, pt); 919 r = amdgpu_bo_create(adev, &bp, &pt);
920 if (r)
921 return r;
997 922
998 r = amdgpu_vm_clear_bo(adev, vm, pt); 923 if (vm->use_cpu_for_update) {
924 r = amdgpu_bo_kmap(pt, NULL);
999 if (r) 925 if (r)
1000 goto error_free_pt; 926 goto error_free_pt;
1001 } 927 }
1002 928
929 /* Keep a reference to the root directory to avoid
930 * freeing them up in the wrong order.
931 */
932 pt->parent = amdgpu_bo_ref(cursor->parent->base.bo);
933 amdgpu_vm_bo_base_init(&entry->base, vm, pt);
934
935 r = amdgpu_vm_clear_bo(adev, vm, pt);
936 if (r)
937 goto error_free_pt;
938
1003 return 0; 939 return 0;
1004 940
1005error_free_pt: 941error_free_pt:
@@ -1644,6 +1580,7 @@ static int amdgpu_vm_update_ptes(struct amdgpu_pte_update_params *params,
1644 struct amdgpu_vm_pt_cursor cursor; 1580 struct amdgpu_vm_pt_cursor cursor;
1645 uint64_t frag_start = start, frag_end; 1581 uint64_t frag_start = start, frag_end;
1646 unsigned int frag; 1582 unsigned int frag;
1583 int r;
1647 1584
1648 /* figure out the initial fragment */ 1585 /* figure out the initial fragment */
1649 amdgpu_vm_fragment(params, frag_start, end, flags, &frag, &frag_end); 1586 amdgpu_vm_fragment(params, frag_start, end, flags, &frag, &frag_end);
@@ -1651,12 +1588,15 @@ static int amdgpu_vm_update_ptes(struct amdgpu_pte_update_params *params,
1651 /* walk over the address space and update the PTs */ 1588 /* walk over the address space and update the PTs */
1652 amdgpu_vm_pt_start(adev, params->vm, start, &cursor); 1589 amdgpu_vm_pt_start(adev, params->vm, start, &cursor);
1653 while (cursor.pfn < end) { 1590 while (cursor.pfn < end) {
1654 struct amdgpu_bo *pt = cursor.entry->base.bo;
1655 unsigned shift, parent_shift, mask; 1591 unsigned shift, parent_shift, mask;
1656 uint64_t incr, entry_end, pe_start; 1592 uint64_t incr, entry_end, pe_start;
1593 struct amdgpu_bo *pt;
1657 1594
1658 if (!pt) 1595 r = amdgpu_vm_alloc_pts(params->adev, params->vm, &cursor);
1659 return -ENOENT; 1596 if (r)
1597 return r;
1598
1599 pt = cursor.entry->base.bo;
1660 1600
1661 /* The root level can't be a huge page */ 1601 /* The root level can't be a huge page */
1662 if (cursor.level == adev->vm_manager.root_level) { 1602 if (cursor.level == adev->vm_manager.root_level) {