aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
diff options
context:
space:
mode:
authorChristian König <christian.koenig@amd.com>2016-02-26 10:18:26 -0500
committerAlex Deucher <alexander.deucher@amd.com>2016-02-29 11:33:46 -0500
commit4ff37a83f19dab4e67299325ee22e98346eee857 (patch)
treea8778a8fb2140caebf7cf8f2fd080e9828606c90 /drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
parentce22c4bfdf70c03e9308751df5c2bf78b79a893f (diff)
drm/amdgpu: fix VM faults caused by vm_grab_id() v4
The owner must be per ring as long as we don't support sharing VMIDs per process. Also move the assigned VMID and page directory address into the IB structure. v3: assign the VMID to all IBs, not just the first one. v4: use correct pointer for owner Signed-off-by: Christian König <christian.koenig@amd.com> Reviewed-by: Chunming Zhou <david1.zhou@amd.com> Acked-by: Alex Deucher <alexander.deucher@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.c115
1 files changed, 60 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..ba909245fef5 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,69 @@ 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, *vm_id, ring->idx);
181 200
182 mutex_unlock(&adev->vm_manager.lock); 201 mutex_unlock(&adev->vm_manager.lock);
183 return 0; 202 return 0;
184 } 203 }
185 } 204 }
186 205
187 /* we definately need to flush */ 206 id->mgr_id = list_first_entry(&adev->vm_manager.ids_lru,
188 vm_id->pd_gpu_addr = ~0ll; 207 struct amdgpu_vm_manager_id,
208 list);
189 209
190 id = list_first_entry(&adev->vm_manager.ids_lru, 210 r = amdgpu_sync_fence(ring->adev, sync, id->mgr_id->active);
191 struct amdgpu_vm_manager_id, 211 if (!r) {
192 list); 212 fence_put(id->mgr_id->active);
193 list_move_tail(&id->list, &adev->vm_manager.ids_lru); 213 id->mgr_id->active = fence_get(fence);
194 atomic_long_set(&id->owner, (long)vm);
195 214
196 vm_id->id = id - adev->vm_manager.ids; 215 fence_put(id->flushed_updates);
197 trace_amdgpu_vm_grab_id(vm, vm_id->id, ring->idx); 216 id->flushed_updates = fence_get(updates);
198 217
199 r = amdgpu_sync_fence(ring->adev, sync, id->active); 218 id->pd_gpu_addr = pd_addr;
200 219
201 if (!r) { 220 list_move_tail(&id->mgr_id->list, &adev->vm_manager.ids_lru);
202 fence_put(id->active); 221 atomic_long_set(&id->mgr_id->owner, (long)id);
203 id->active = fence_get(fence); 222
223 *vm_id = id->mgr_id - adev->vm_manager.ids;
224 *vm_pd_addr = pd_addr;
225 trace_amdgpu_vm_grab_id(vm, *vm_id, ring->idx);
204 } 226 }
205 227
206 mutex_unlock(&adev->vm_manager.lock); 228 mutex_unlock(&adev->vm_manager.lock);
@@ -211,35 +233,18 @@ int amdgpu_vm_grab_id(struct amdgpu_vm *vm, struct amdgpu_ring *ring,
211 * amdgpu_vm_flush - hardware flush the vm 233 * amdgpu_vm_flush - hardware flush the vm
212 * 234 *
213 * @ring: ring to use for flush 235 * @ring: ring to use for flush
214 * @vm: vm we want to flush 236 * @vmid: vmid number to use
215 * @updates: last vm update that we waited for 237 * @pd_addr: address of the page directory
216 * 238 *
217 * Flush the vm. 239 * Emit a VM flush when it is necessary.
218 */ 240 */
219void amdgpu_vm_flush(struct amdgpu_ring *ring, 241void amdgpu_vm_flush(struct amdgpu_ring *ring,
220 struct amdgpu_vm *vm, 242 unsigned vmid,
221 struct fence *updates) 243 uint64_t pd_addr)
222{ 244{
223 uint64_t pd_addr = amdgpu_bo_gpu_offset(vm->page_directory); 245 if (pd_addr != AMDGPU_VM_NO_FLUSH) {
224 struct amdgpu_vm_id *vm_id = &vm->ids[ring->idx]; 246 trace_amdgpu_vm_flush(pd_addr, ring->idx, vmid);
225 struct fence *flushed_updates = vm_id->flushed_updates; 247 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 } 248 }
244} 249}
245 250
@@ -1284,7 +1289,7 @@ int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm)
1284 int i, r; 1289 int i, r;
1285 1290
1286 for (i = 0; i < AMDGPU_MAX_RINGS; ++i) { 1291 for (i = 0; i < AMDGPU_MAX_RINGS; ++i) {
1287 vm->ids[i].id = 0; 1292 vm->ids[i].mgr_id = NULL;
1288 vm->ids[i].flushed_updates = NULL; 1293 vm->ids[i].flushed_updates = NULL;
1289 } 1294 }
1290 vm->va = RB_ROOT; 1295 vm->va = RB_ROOT;
@@ -1381,13 +1386,13 @@ void amdgpu_vm_fini(struct amdgpu_device *adev, struct amdgpu_vm *vm)
1381 amdgpu_bo_unref(&vm->page_directory); 1386 amdgpu_bo_unref(&vm->page_directory);
1382 fence_put(vm->page_directory_fence); 1387 fence_put(vm->page_directory_fence);
1383 for (i = 0; i < AMDGPU_MAX_RINGS; ++i) { 1388 for (i = 0; i < AMDGPU_MAX_RINGS; ++i) {
1384 unsigned id = vm->ids[i].id; 1389 struct amdgpu_vm_id *id = &vm->ids[i];
1385 1390
1386 atomic_long_cmpxchg(&adev->vm_manager.ids[id].owner, 1391 if (id->mgr_id)
1387 (long)vm, 0); 1392 atomic_long_cmpxchg(&id->mgr_id->owner,
1388 fence_put(vm->ids[i].flushed_updates); 1393 (long)id, 0);
1394 fence_put(id->flushed_updates);
1389 } 1395 }
1390
1391} 1396}
1392 1397
1393/** 1398/**