diff options
author | Christian König <christian.koenig@amd.com> | 2017-11-30 09:19:50 -0500 |
---|---|---|
committer | Alex Deucher <alexander.deucher@amd.com> | 2017-12-12 14:45:41 -0500 |
commit | b852f3d3fb5d770f54c10614e6320a29943eb52f (patch) | |
tree | 51452b448fe3732c479cf2eef35c53a891a7fff6 /drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | |
parent | 94c6f5e4d1574094a91b1712536ab5b6a43f7a23 (diff) |
drm/amdgpu: update one PDE at a time v2
Horrible inefficient, but avoids problems when the root PD size becomes
to big.
v2: remove incr as well.
Signed-off-by: Christian König <christian.koenig@amd.com>
Reviewed-by: Chunming Zhou <davdi1.zhou@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 | 80 |
1 files changed, 34 insertions, 46 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c index 17ae6afdef70..1c3dd6e0ed33 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | |||
@@ -1069,18 +1069,20 @@ static int amdgpu_vm_wait_pd(struct amdgpu_device *adev, struct amdgpu_vm *vm, | |||
1069 | * Makes sure all entries in @parent are up to date. | 1069 | * Makes sure all entries in @parent are up to date. |
1070 | * Returns 0 for success, error for failure. | 1070 | * Returns 0 for success, error for failure. |
1071 | */ | 1071 | */ |
1072 | static int amdgpu_vm_update_level(struct amdgpu_device *adev, | 1072 | static int amdgpu_vm_update_pde(struct amdgpu_device *adev, |
1073 | struct amdgpu_vm *vm, | 1073 | struct amdgpu_vm *vm, |
1074 | struct amdgpu_vm_pt *parent) | 1074 | struct amdgpu_vm_pt *parent, |
1075 | struct amdgpu_vm_pt *entry) | ||
1075 | { | 1076 | { |
1077 | struct amdgpu_pte_update_params params; | ||
1078 | struct amdgpu_bo *bo = entry->base.bo; | ||
1076 | struct amdgpu_bo *shadow; | 1079 | struct amdgpu_bo *shadow; |
1077 | struct amdgpu_ring *ring = NULL; | 1080 | struct amdgpu_ring *ring = NULL; |
1078 | uint64_t pd_addr, shadow_addr = 0; | 1081 | uint64_t pd_addr, shadow_addr = 0; |
1079 | unsigned pt_idx, ndw = 0; | ||
1080 | struct amdgpu_job *job; | 1082 | struct amdgpu_job *job; |
1081 | struct amdgpu_pte_update_params params; | ||
1082 | struct dma_fence *fence = NULL; | 1083 | struct dma_fence *fence = NULL; |
1083 | uint32_t incr; | 1084 | unsigned ndw = 0; |
1085 | uint64_t pde, pt; | ||
1084 | 1086 | ||
1085 | int r; | 1087 | int r; |
1086 | 1088 | ||
@@ -1102,20 +1104,14 @@ static int amdgpu_vm_update_level(struct amdgpu_device *adev, | |||
1102 | ring = container_of(vm->entity.sched, struct amdgpu_ring, | 1104 | ring = container_of(vm->entity.sched, struct amdgpu_ring, |
1103 | sched); | 1105 | sched); |
1104 | 1106 | ||
1105 | /* padding, etc. */ | 1107 | /* should be sufficient for two commands plus padding, etc. */ |
1106 | ndw = 64; | 1108 | ndw = 64; |
1107 | 1109 | ||
1108 | /* assume the worst case */ | ||
1109 | ndw += parent->last_entry_used * 6; | ||
1110 | |||
1111 | pd_addr = amdgpu_bo_gpu_offset(parent->base.bo); | 1110 | pd_addr = amdgpu_bo_gpu_offset(parent->base.bo); |
1112 | 1111 | if (shadow) | |
1113 | if (shadow) { | ||
1114 | shadow_addr = amdgpu_bo_gpu_offset(shadow); | 1112 | shadow_addr = amdgpu_bo_gpu_offset(shadow); |
1115 | ndw *= 2; | 1113 | else |
1116 | } else { | ||
1117 | shadow_addr = 0; | 1114 | shadow_addr = 0; |
1118 | } | ||
1119 | 1115 | ||
1120 | r = amdgpu_job_alloc_with_ib(adev, ndw * 4, &job); | 1116 | r = amdgpu_job_alloc_with_ib(adev, ndw * 4, &job); |
1121 | if (r) | 1117 | if (r) |
@@ -1125,40 +1121,30 @@ static int amdgpu_vm_update_level(struct amdgpu_device *adev, | |||
1125 | params.func = amdgpu_vm_do_set_ptes; | 1121 | params.func = amdgpu_vm_do_set_ptes; |
1126 | } | 1122 | } |
1127 | 1123 | ||
1124 | spin_lock(&vm->status_lock); | ||
1125 | list_del_init(&entry->base.vm_status); | ||
1126 | spin_unlock(&vm->status_lock); | ||
1128 | 1127 | ||
1129 | /* walk over the address space and update the directory */ | 1128 | pt = amdgpu_bo_gpu_offset(bo); |
1130 | for (pt_idx = 0; pt_idx <= parent->last_entry_used; ++pt_idx) { | 1129 | pt = amdgpu_gart_get_vm_pde(adev, pt); |
1131 | struct amdgpu_vm_pt *entry = &parent->entries[pt_idx]; | 1130 | /* Don't update huge pages here */ |
1132 | struct amdgpu_bo *bo = entry->base.bo; | 1131 | if (entry->addr & AMDGPU_PDE_PTE || |
1133 | uint64_t pde, pt; | 1132 | entry->addr == (pt | AMDGPU_PTE_VALID)) { |
1134 | 1133 | if (!vm->use_cpu_for_update) | |
1135 | if (bo == NULL) | 1134 | amdgpu_job_free(job); |
1136 | continue; | 1135 | return 0; |
1137 | 1136 | } | |
1138 | spin_lock(&vm->status_lock); | ||
1139 | list_del_init(&entry->base.vm_status); | ||
1140 | spin_unlock(&vm->status_lock); | ||
1141 | |||
1142 | pt = amdgpu_bo_gpu_offset(bo); | ||
1143 | pt = amdgpu_gart_get_vm_pde(adev, pt); | ||
1144 | /* Don't update huge pages here */ | ||
1145 | if ((parent->entries[pt_idx].addr & AMDGPU_PDE_PTE) || | ||
1146 | parent->entries[pt_idx].addr == (pt | AMDGPU_PTE_VALID)) | ||
1147 | continue; | ||
1148 | |||
1149 | parent->entries[pt_idx].addr = pt | AMDGPU_PTE_VALID; | ||
1150 | 1137 | ||
1151 | incr = amdgpu_bo_size(bo); | 1138 | entry->addr = pt | AMDGPU_PTE_VALID; |
1152 | if (shadow) { | ||
1153 | pde = shadow_addr + pt_idx * 8; | ||
1154 | params.func(¶ms, pde, pt, 1, incr, | ||
1155 | AMDGPU_PTE_VALID); | ||
1156 | } | ||
1157 | 1139 | ||
1158 | pde = pd_addr + pt_idx * 8; | 1140 | if (shadow) { |
1159 | params.func(¶ms, pde, pt, 1, incr, AMDGPU_PTE_VALID); | 1141 | pde = shadow_addr + (entry - parent->entries) * 8; |
1142 | params.func(¶ms, pde, pt, 1, 0, AMDGPU_PTE_VALID); | ||
1160 | } | 1143 | } |
1161 | 1144 | ||
1145 | pde = pd_addr + (entry - parent->entries) * 8; | ||
1146 | params.func(¶ms, pde, pt, 1, 0, AMDGPU_PTE_VALID); | ||
1147 | |||
1162 | if (!vm->use_cpu_for_update) { | 1148 | if (!vm->use_cpu_for_update) { |
1163 | if (params.ib->length_dw == 0) { | 1149 | if (params.ib->length_dw == 0) { |
1164 | amdgpu_job_free(job); | 1150 | amdgpu_job_free(job); |
@@ -1249,14 +1235,16 @@ int amdgpu_vm_update_directories(struct amdgpu_device *adev, | |||
1249 | bo = bo_base->bo->parent; | 1235 | bo = bo_base->bo->parent; |
1250 | if (bo) { | 1236 | if (bo) { |
1251 | struct amdgpu_vm_bo_base *parent; | 1237 | struct amdgpu_vm_bo_base *parent; |
1252 | struct amdgpu_vm_pt *pt; | 1238 | struct amdgpu_vm_pt *pt, *entry; |
1253 | 1239 | ||
1254 | parent = list_first_entry(&bo->va, | 1240 | parent = list_first_entry(&bo->va, |
1255 | struct amdgpu_vm_bo_base, | 1241 | struct amdgpu_vm_bo_base, |
1256 | bo_list); | 1242 | bo_list); |
1257 | pt = container_of(parent, struct amdgpu_vm_pt, base); | 1243 | pt = container_of(parent, struct amdgpu_vm_pt, base); |
1244 | entry = container_of(bo_base, struct amdgpu_vm_pt, | ||
1245 | base); | ||
1258 | 1246 | ||
1259 | r = amdgpu_vm_update_level(adev, vm, pt); | 1247 | r = amdgpu_vm_update_pde(adev, vm, pt, entry); |
1260 | if (r) { | 1248 | if (r) { |
1261 | amdgpu_vm_invalidate_level(vm, &vm->root); | 1249 | amdgpu_vm_invalidate_level(vm, &vm->root); |
1262 | return r; | 1250 | return r; |