aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
diff options
context:
space:
mode:
authorChristian König <christian.koenig@amd.com>2017-11-30 09:19:50 -0500
committerAlex Deucher <alexander.deucher@amd.com>2017-12-12 14:45:41 -0500
commitb852f3d3fb5d770f54c10614e6320a29943eb52f (patch)
tree51452b448fe3732c479cf2eef35c53a891a7fff6 /drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
parent94c6f5e4d1574094a91b1712536ab5b6a43f7a23 (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.c80
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 */
1072static int amdgpu_vm_update_level(struct amdgpu_device *adev, 1072static 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(&params, pde, pt, 1, incr,
1155 AMDGPU_PTE_VALID);
1156 }
1157 1139
1158 pde = pd_addr + pt_idx * 8; 1140 if (shadow) {
1159 params.func(&params, pde, pt, 1, incr, AMDGPU_PTE_VALID); 1141 pde = shadow_addr + (entry - parent->entries) * 8;
1142 params.func(&params, pde, pt, 1, 0, AMDGPU_PTE_VALID);
1160 } 1143 }
1161 1144
1145 pde = pd_addr + (entry - parent->entries) * 8;
1146 params.func(&params, 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;