diff options
author | Christian König <christian.koenig@amd.com> | 2019-01-30 10:07:29 -0500 |
---|---|---|
committer | Alex Deucher <alexander.deucher@amd.com> | 2019-03-19 16:36:48 -0400 |
commit | 0ce15d6f7d3fb1162fd7de2829dbdf6d63a6a02a (patch) | |
tree | c83a9a486a58d392808ea1453a7f5fa8b689d352 /drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | |
parent | 780637cbdf8fd614cc85a01c6c810d9d28902a59 (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.c | 136 |
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 | */ | ||
533 | static 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 | */ | ||
549 | static 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 | */ |
935 | int amdgpu_vm_alloc_pts(struct amdgpu_device *adev, | 894 | static 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 | ||
1005 | error_free_pt: | 941 | error_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) { |