aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c')
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c116
1 files changed, 61 insertions, 55 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
index 264c5968a1d3..d9dc8bea5e98 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
@@ -50,6 +50,9 @@
50 * SI supports 16. 50 * SI supports 16.
51 */ 51 */
52 52
53/* Special value that no flush is necessary */
54#define AMDGPU_VM_NO_FLUSH (~0ll)
55
53/** 56/**
54 * amdgpu_vm_num_pde - return the number of page directory entries 57 * amdgpu_vm_num_pde - return the number of page directory entries
55 * 58 *
@@ -157,50 +160,70 @@ void amdgpu_vm_move_pt_bos_in_lru(struct amdgpu_device *adev,
157 * Allocate an id for the vm, adding fences to the sync obj as necessary. 160 * Allocate an id for the vm, adding fences to the sync obj as necessary.
158 */ 161 */
159int amdgpu_vm_grab_id(struct amdgpu_vm *vm, struct amdgpu_ring *ring, 162int amdgpu_vm_grab_id(struct amdgpu_vm *vm, struct amdgpu_ring *ring,
160 struct amdgpu_sync *sync, struct fence *fence) 163 struct amdgpu_sync *sync, struct fence *fence,
164 unsigned *vm_id, uint64_t *vm_pd_addr)
161{ 165{
162 struct amdgpu_vm_id *vm_id = &vm->ids[ring->idx]; 166 uint64_t pd_addr = amdgpu_bo_gpu_offset(vm->page_directory);
163 struct amdgpu_device *adev = ring->adev; 167 struct amdgpu_device *adev = ring->adev;
164 struct amdgpu_vm_manager_id *id; 168 struct amdgpu_vm_id *id = &vm->ids[ring->idx];
169 struct fence *updates = sync->last_vm_update;
165 int r; 170 int r;
166 171
167 mutex_lock(&adev->vm_manager.lock); 172 mutex_lock(&adev->vm_manager.lock);
168 173
169 /* check if the id is still valid */ 174 /* check if the id is still valid */
170 if (vm_id->id) { 175 if (id->mgr_id) {
176 struct fence *flushed = id->flushed_updates;
177 bool is_later;
171 long owner; 178 long owner;
172 179
173 id = &adev->vm_manager.ids[vm_id->id]; 180 if (!flushed)
174 owner = atomic_long_read(&id->owner); 181 is_later = true;
175 if (owner == (long)vm) { 182 else if (!updates)
176 list_move_tail(&id->list, &adev->vm_manager.ids_lru); 183 is_later = false;
177 trace_amdgpu_vm_grab_id(vm, vm_id->id, ring->idx); 184 else
185 is_later = fence_is_later(updates, flushed);
186
187 owner = atomic_long_read(&id->mgr_id->owner);
188 if (!is_later && owner == (long)id &&
189 pd_addr == id->pd_gpu_addr) {
190
191 fence_put(id->mgr_id->active);
192 id->mgr_id->active = fence_get(fence);
193
194 list_move_tail(&id->mgr_id->list,
195 &adev->vm_manager.ids_lru);
178 196
179 fence_put(id->active); 197 *vm_id = id->mgr_id - adev->vm_manager.ids;
180 id->active = fence_get(fence); 198 *vm_pd_addr = AMDGPU_VM_NO_FLUSH;
199 trace_amdgpu_vm_grab_id(vm, ring->idx, *vm_id,
200 *vm_pd_addr);
181 201
182 mutex_unlock(&adev->vm_manager.lock); 202 mutex_unlock(&adev->vm_manager.lock);
183 return 0; 203 return 0;
184 } 204 }
185 } 205 }
186 206
187 /* we definately need to flush */ 207 id->mgr_id = list_first_entry(&adev->vm_manager.ids_lru,
188 vm_id->pd_gpu_addr = ~0ll; 208 struct amdgpu_vm_manager_id,
209 list);
189 210
190 id = list_first_entry(&adev->vm_manager.ids_lru, 211 r = amdgpu_sync_fence(ring->adev, sync, id->mgr_id->active);
191 struct amdgpu_vm_manager_id, 212 if (!r) {
192 list); 213 fence_put(id->mgr_id->active);
193 list_move_tail(&id->list, &adev->vm_manager.ids_lru); 214 id->mgr_id->active = fence_get(fence);
194 atomic_long_set(&id->owner, (long)vm);
195 215
196 vm_id->id = id - adev->vm_manager.ids; 216 fence_put(id->flushed_updates);
197 trace_amdgpu_vm_grab_id(vm, vm_id->id, ring->idx); 217 id->flushed_updates = fence_get(updates);
198 218
199 r = amdgpu_sync_fence(ring->adev, sync, id->active); 219 id->pd_gpu_addr = pd_addr;
200 220
201 if (!r) { 221 list_move_tail(&id->mgr_id->list, &adev->vm_manager.ids_lru);
202 fence_put(id->active); 222 atomic_long_set(&id->mgr_id->owner, (long)id);
203 id->active = fence_get(fence); 223
224 *vm_id = id->mgr_id - adev->vm_manager.ids;
225 *vm_pd_addr = pd_addr;
226 trace_amdgpu_vm_grab_id(vm, ring->idx, *vm_id, *vm_pd_addr);
204 } 227 }
205 228
206 mutex_unlock(&adev->vm_manager.lock); 229 mutex_unlock(&adev->vm_manager.lock);
@@ -211,35 +234,18 @@ int amdgpu_vm_grab_id(struct amdgpu_vm *vm, struct amdgpu_ring *ring,
211 * amdgpu_vm_flush - hardware flush the vm 234 * amdgpu_vm_flush - hardware flush the vm
212 * 235 *
213 * @ring: ring to use for flush 236 * @ring: ring to use for flush
214 * @vm: vm we want to flush 237 * @vmid: vmid number to use
215 * @updates: last vm update that we waited for 238 * @pd_addr: address of the page directory
216 * 239 *
217 * Flush the vm. 240 * Emit a VM flush when it is necessary.
218 */ 241 */
219void amdgpu_vm_flush(struct amdgpu_ring *ring, 242void amdgpu_vm_flush(struct amdgpu_ring *ring,
220 struct amdgpu_vm *vm, 243 unsigned vmid,
221 struct fence *updates) 244 uint64_t pd_addr)
222{ 245{
223 uint64_t pd_addr = amdgpu_bo_gpu_offset(vm->page_directory); 246 if (pd_addr != AMDGPU_VM_NO_FLUSH) {
224 struct amdgpu_vm_id *vm_id = &vm->ids[ring->idx]; 247 trace_amdgpu_vm_flush(pd_addr, ring->idx, vmid);
225 struct fence *flushed_updates = vm_id->flushed_updates; 248 amdgpu_ring_emit_vm_flush(ring, vmid, pd_addr);
226 bool is_later;
227
228 if (!flushed_updates)
229 is_later = true;
230 else if (!updates)
231 is_later = false;
232 else
233 is_later = fence_is_later(updates, flushed_updates);
234
235 if (pd_addr != vm_id->pd_gpu_addr || is_later) {
236 trace_amdgpu_vm_flush(pd_addr, ring->idx, vm_id->id);
237 if (is_later) {
238 vm_id->flushed_updates = fence_get(updates);
239 fence_put(flushed_updates);
240 }
241 vm_id->pd_gpu_addr = pd_addr;
242 amdgpu_ring_emit_vm_flush(ring, vm_id->id, vm_id->pd_gpu_addr);
243 } 249 }
244} 250}
245 251
@@ -1284,7 +1290,7 @@ int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm)
1284 int i, r; 1290 int i, r;
1285 1291
1286 for (i = 0; i < AMDGPU_MAX_RINGS; ++i) { 1292 for (i = 0; i < AMDGPU_MAX_RINGS; ++i) {
1287 vm->ids[i].id = 0; 1293 vm->ids[i].mgr_id = NULL;
1288 vm->ids[i].flushed_updates = NULL; 1294 vm->ids[i].flushed_updates = NULL;
1289 } 1295 }
1290 vm->va = RB_ROOT; 1296 vm->va = RB_ROOT;
@@ -1381,13 +1387,13 @@ void amdgpu_vm_fini(struct amdgpu_device *adev, struct amdgpu_vm *vm)
1381 amdgpu_bo_unref(&vm->page_directory); 1387 amdgpu_bo_unref(&vm->page_directory);
1382 fence_put(vm->page_directory_fence); 1388 fence_put(vm->page_directory_fence);
1383 for (i = 0; i < AMDGPU_MAX_RINGS; ++i) { 1389 for (i = 0; i < AMDGPU_MAX_RINGS; ++i) {
1384 unsigned id = vm->ids[i].id; 1390 struct amdgpu_vm_id *id = &vm->ids[i];
1385 1391
1386 atomic_long_cmpxchg(&adev->vm_manager.ids[id].owner, 1392 if (id->mgr_id)
1387 (long)vm, 0); 1393 atomic_long_cmpxchg(&id->mgr_id->owner,
1388 fence_put(vm->ids[i].flushed_updates); 1394 (long)id, 0);
1395 fence_put(id->flushed_updates);
1389 } 1396 }
1390
1391} 1397}
1392 1398
1393/** 1399/**