aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/radeon/radeon_vm.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-12-15 18:52:01 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2014-12-15 18:52:01 -0500
commit988adfdffdd43cfd841df734664727993076d7cb (patch)
tree6794f7bba8f595500c2b7d33376ad6614adcfaf2 /drivers/gpu/drm/radeon/radeon_vm.c
parent26178ec11ef3c6c814bf16a0a2b9c2f7242e3c64 (diff)
parent4e0cd68115620bc3236ff4e58e4c073948629b41 (diff)
Merge branch 'drm-next' of git://people.freedesktop.org/~airlied/linux
Pull drm updates from Dave Airlie: "Highlights: - AMD KFD driver merge This is the AMD HSA interface for exposing a lowlevel interface for GPGPU use. They have an open source userspace built on top of this interface, and the code looks as good as it was going to get out of tree. - Initial atomic modesetting work The need for an atomic modesetting interface to allow userspace to try and send a complete set of modesetting state to the driver has arisen, and been suffering from neglect this past year. No more, the start of the common code and changes for msm driver to use it are in this tree. Ongoing work to get the userspace ioctl finished and the code clean will probably wait until next kernel. - DisplayID 1.3 and tiled monitor exposed to userspace. Tiled monitor property is now exposed for userspace to make use of. - Rockchip drm driver merged. - imx gpu driver moved out of staging Other stuff: - core: panel - MIPI DSI + new panels. expose suggested x/y properties for virtual GPUs - i915: Initial Skylake (SKL) support gen3/4 reset work start of dri1/ums removal infoframe tracking fixes for lots of things. - nouveau: tegra k1 voltage support GM204 modesetting support GT21x memory reclocking work - radeon: CI dpm fixes GPUVM improvements Initial DPM fan control - rcar-du: HDMI support added removed some support for old boards slave encoder driver for Analog Devices adv7511 - exynos: Exynos4415 SoC support - msm: a4xx gpu support atomic helper conversion - tegra: iommu support universal plane support ganged-mode DSI support - sti: HDMI i2c improvements - vmwgfx: some late fixes. - qxl: use suggested x/y properties" * 'drm-next' of git://people.freedesktop.org/~airlied/linux: (969 commits) drm: sti: fix module compilation issue drm/i915: save/restore GMBUS freq across suspend/resume on gen4 drm: sti: correctly cleanup CRTC and planes drm: sti: add HQVDP plane drm: sti: add cursor plane drm: sti: enable auxiliary CRTC drm: sti: fix delay in VTG programming drm: sti: prepare sti_tvout to support auxiliary crtc drm: sti: use drm_crtc_vblank_{on/off} instead of drm_vblank_{on/off} drm: sti: fix hdmi avi infoframe drm: sti: remove event lock while disabling vblank drm: sti: simplify gdp code drm: sti: clear all mixer control drm: sti: remove gpio for HDMI hot plug detection drm: sti: allow to change hdmi ddc i2c adapter drm/doc: Document drm_add_modes_noedid() usage drm/i915: Remove '& 0xffff' from the mask given to WA_REG() drm/i915: Invert the mask and val arguments in wa_add() and WA_REG() drm: Zero out DRM object memory upon cleanup drm/i915/bdw: Fix the write setting up the WIZ hashing mode ...
Diffstat (limited to 'drivers/gpu/drm/radeon/radeon_vm.c')
-rw-r--r--drivers/gpu/drm/radeon/radeon_vm.c236
1 files changed, 149 insertions, 87 deletions
diff --git a/drivers/gpu/drm/radeon/radeon_vm.c b/drivers/gpu/drm/radeon/radeon_vm.c
index dfde266529e2..cde48c42b30a 100644
--- a/drivers/gpu/drm/radeon/radeon_vm.c
+++ b/drivers/gpu/drm/radeon/radeon_vm.c
@@ -125,41 +125,37 @@ void radeon_vm_manager_fini(struct radeon_device *rdev)
125 * Add the page directory to the list of BOs to 125 * Add the page directory to the list of BOs to
126 * validate for command submission (cayman+). 126 * validate for command submission (cayman+).
127 */ 127 */
128struct radeon_cs_reloc *radeon_vm_get_bos(struct radeon_device *rdev, 128struct radeon_bo_list *radeon_vm_get_bos(struct radeon_device *rdev,
129 struct radeon_vm *vm, 129 struct radeon_vm *vm,
130 struct list_head *head) 130 struct list_head *head)
131{ 131{
132 struct radeon_cs_reloc *list; 132 struct radeon_bo_list *list;
133 unsigned i, idx; 133 unsigned i, idx;
134 134
135 list = drm_malloc_ab(vm->max_pde_used + 2, 135 list = drm_malloc_ab(vm->max_pde_used + 2,
136 sizeof(struct radeon_cs_reloc)); 136 sizeof(struct radeon_bo_list));
137 if (!list) 137 if (!list)
138 return NULL; 138 return NULL;
139 139
140 /* add the vm page table to the list */ 140 /* add the vm page table to the list */
141 list[0].gobj = NULL;
142 list[0].robj = vm->page_directory; 141 list[0].robj = vm->page_directory;
143 list[0].prefered_domains = RADEON_GEM_DOMAIN_VRAM; 142 list[0].prefered_domains = RADEON_GEM_DOMAIN_VRAM;
144 list[0].allowed_domains = RADEON_GEM_DOMAIN_VRAM; 143 list[0].allowed_domains = RADEON_GEM_DOMAIN_VRAM;
145 list[0].tv.bo = &vm->page_directory->tbo; 144 list[0].tv.bo = &vm->page_directory->tbo;
146 list[0].tv.shared = false; 145 list[0].tv.shared = true;
147 list[0].tiling_flags = 0; 146 list[0].tiling_flags = 0;
148 list[0].handle = 0;
149 list_add(&list[0].tv.head, head); 147 list_add(&list[0].tv.head, head);
150 148
151 for (i = 0, idx = 1; i <= vm->max_pde_used; i++) { 149 for (i = 0, idx = 1; i <= vm->max_pde_used; i++) {
152 if (!vm->page_tables[i].bo) 150 if (!vm->page_tables[i].bo)
153 continue; 151 continue;
154 152
155 list[idx].gobj = NULL;
156 list[idx].robj = vm->page_tables[i].bo; 153 list[idx].robj = vm->page_tables[i].bo;
157 list[idx].prefered_domains = RADEON_GEM_DOMAIN_VRAM; 154 list[idx].prefered_domains = RADEON_GEM_DOMAIN_VRAM;
158 list[idx].allowed_domains = RADEON_GEM_DOMAIN_VRAM; 155 list[idx].allowed_domains = RADEON_GEM_DOMAIN_VRAM;
159 list[idx].tv.bo = &list[idx].robj->tbo; 156 list[idx].tv.bo = &list[idx].robj->tbo;
160 list[idx].tv.shared = false; 157 list[idx].tv.shared = true;
161 list[idx].tiling_flags = 0; 158 list[idx].tiling_flags = 0;
162 list[idx].handle = 0;
163 list_add(&list[idx++].tv.head, head); 159 list_add(&list[idx++].tv.head, head);
164 } 160 }
165 161
@@ -182,15 +178,18 @@ struct radeon_fence *radeon_vm_grab_id(struct radeon_device *rdev,
182 struct radeon_vm *vm, int ring) 178 struct radeon_vm *vm, int ring)
183{ 179{
184 struct radeon_fence *best[RADEON_NUM_RINGS] = {}; 180 struct radeon_fence *best[RADEON_NUM_RINGS] = {};
181 struct radeon_vm_id *vm_id = &vm->ids[ring];
182
185 unsigned choices[2] = {}; 183 unsigned choices[2] = {};
186 unsigned i; 184 unsigned i;
187 185
188 /* check if the id is still valid */ 186 /* check if the id is still valid */
189 if (vm->last_id_use && vm->last_id_use == rdev->vm_manager.active[vm->id]) 187 if (vm_id->id && vm_id->last_id_use &&
188 vm_id->last_id_use == rdev->vm_manager.active[vm_id->id])
190 return NULL; 189 return NULL;
191 190
192 /* we definately need to flush */ 191 /* we definately need to flush */
193 radeon_fence_unref(&vm->last_flush); 192 vm_id->pd_gpu_addr = ~0ll;
194 193
195 /* skip over VMID 0, since it is the system VM */ 194 /* skip over VMID 0, since it is the system VM */
196 for (i = 1; i < rdev->vm_manager.nvm; ++i) { 195 for (i = 1; i < rdev->vm_manager.nvm; ++i) {
@@ -198,8 +197,8 @@ struct radeon_fence *radeon_vm_grab_id(struct radeon_device *rdev,
198 197
199 if (fence == NULL) { 198 if (fence == NULL) {
200 /* found a free one */ 199 /* found a free one */
201 vm->id = i; 200 vm_id->id = i;
202 trace_radeon_vm_grab_id(vm->id, ring); 201 trace_radeon_vm_grab_id(i, ring);
203 return NULL; 202 return NULL;
204 } 203 }
205 204
@@ -211,8 +210,8 @@ struct radeon_fence *radeon_vm_grab_id(struct radeon_device *rdev,
211 210
212 for (i = 0; i < 2; ++i) { 211 for (i = 0; i < 2; ++i) {
213 if (choices[i]) { 212 if (choices[i]) {
214 vm->id = choices[i]; 213 vm_id->id = choices[i];
215 trace_radeon_vm_grab_id(vm->id, ring); 214 trace_radeon_vm_grab_id(choices[i], ring);
216 return rdev->vm_manager.active[choices[i]]; 215 return rdev->vm_manager.active[choices[i]];
217 } 216 }
218 } 217 }
@@ -228,6 +227,7 @@ struct radeon_fence *radeon_vm_grab_id(struct radeon_device *rdev,
228 * @rdev: radeon_device pointer 227 * @rdev: radeon_device pointer
229 * @vm: vm we want to flush 228 * @vm: vm we want to flush
230 * @ring: ring to use for flush 229 * @ring: ring to use for flush
230 * @updates: last vm update that is waited for
231 * 231 *
232 * Flush the vm (cayman+). 232 * Flush the vm (cayman+).
233 * 233 *
@@ -235,15 +235,21 @@ struct radeon_fence *radeon_vm_grab_id(struct radeon_device *rdev,
235 */ 235 */
236void radeon_vm_flush(struct radeon_device *rdev, 236void radeon_vm_flush(struct radeon_device *rdev,
237 struct radeon_vm *vm, 237 struct radeon_vm *vm,
238 int ring) 238 int ring, struct radeon_fence *updates)
239{ 239{
240 uint64_t pd_addr = radeon_bo_gpu_offset(vm->page_directory); 240 uint64_t pd_addr = radeon_bo_gpu_offset(vm->page_directory);
241 struct radeon_vm_id *vm_id = &vm->ids[ring];
242
243 if (pd_addr != vm_id->pd_gpu_addr || !vm_id->flushed_updates ||
244 radeon_fence_is_earlier(vm_id->flushed_updates, updates)) {
245
246 trace_radeon_vm_flush(pd_addr, ring, vm->ids[ring].id);
247 radeon_fence_unref(&vm_id->flushed_updates);
248 vm_id->flushed_updates = radeon_fence_ref(updates);
249 vm_id->pd_gpu_addr = pd_addr;
250 radeon_ring_vm_flush(rdev, &rdev->ring[ring],
251 vm_id->id, vm_id->pd_gpu_addr);
241 252
242 /* if we can't remember our last VM flush then flush now! */
243 if (!vm->last_flush || pd_addr != vm->pd_gpu_addr) {
244 trace_radeon_vm_flush(pd_addr, ring, vm->id);
245 vm->pd_gpu_addr = pd_addr;
246 radeon_ring_vm_flush(rdev, ring, vm);
247 } 253 }
248} 254}
249 255
@@ -263,18 +269,13 @@ void radeon_vm_fence(struct radeon_device *rdev,
263 struct radeon_vm *vm, 269 struct radeon_vm *vm,
264 struct radeon_fence *fence) 270 struct radeon_fence *fence)
265{ 271{
266 radeon_fence_unref(&vm->fence); 272 unsigned vm_id = vm->ids[fence->ring].id;
267 vm->fence = radeon_fence_ref(fence);
268
269 radeon_fence_unref(&rdev->vm_manager.active[vm->id]);
270 rdev->vm_manager.active[vm->id] = radeon_fence_ref(fence);
271 273
272 radeon_fence_unref(&vm->last_id_use); 274 radeon_fence_unref(&rdev->vm_manager.active[vm_id]);
273 vm->last_id_use = radeon_fence_ref(fence); 275 rdev->vm_manager.active[vm_id] = radeon_fence_ref(fence);
274 276
275 /* we just flushed the VM, remember that */ 277 radeon_fence_unref(&vm->ids[fence->ring].last_id_use);
276 if (!vm->last_flush) 278 vm->ids[fence->ring].last_id_use = radeon_fence_ref(fence);
277 vm->last_flush = radeon_fence_ref(fence);
278} 279}
279 280
280/** 281/**
@@ -387,35 +388,25 @@ static void radeon_vm_set_pages(struct radeon_device *rdev,
387static int radeon_vm_clear_bo(struct radeon_device *rdev, 388static int radeon_vm_clear_bo(struct radeon_device *rdev,
388 struct radeon_bo *bo) 389 struct radeon_bo *bo)
389{ 390{
390 struct ttm_validate_buffer tv;
391 struct ww_acquire_ctx ticket;
392 struct list_head head;
393 struct radeon_ib ib; 391 struct radeon_ib ib;
394 unsigned entries; 392 unsigned entries;
395 uint64_t addr; 393 uint64_t addr;
396 int r; 394 int r;
397 395
398 memset(&tv, 0, sizeof(tv)); 396 r = radeon_bo_reserve(bo, false);
399 tv.bo = &bo->tbo; 397 if (r)
400 tv.shared = false;
401
402 INIT_LIST_HEAD(&head);
403 list_add(&tv.head, &head);
404
405 r = ttm_eu_reserve_buffers(&ticket, &head, true);
406 if (r)
407 return r; 398 return r;
408 399
409 r = ttm_bo_validate(&bo->tbo, &bo->placement, true, false); 400 r = ttm_bo_validate(&bo->tbo, &bo->placement, true, false);
410 if (r) 401 if (r)
411 goto error; 402 goto error_unreserve;
412 403
413 addr = radeon_bo_gpu_offset(bo); 404 addr = radeon_bo_gpu_offset(bo);
414 entries = radeon_bo_size(bo) / 8; 405 entries = radeon_bo_size(bo) / 8;
415 406
416 r = radeon_ib_get(rdev, R600_RING_TYPE_DMA_INDEX, &ib, NULL, 256); 407 r = radeon_ib_get(rdev, R600_RING_TYPE_DMA_INDEX, &ib, NULL, 256);
417 if (r) 408 if (r)
418 goto error; 409 goto error_unreserve;
419 410
420 ib.length_dw = 0; 411 ib.length_dw = 0;
421 412
@@ -425,15 +416,16 @@ static int radeon_vm_clear_bo(struct radeon_device *rdev,
425 416
426 r = radeon_ib_schedule(rdev, &ib, NULL, false); 417 r = radeon_ib_schedule(rdev, &ib, NULL, false);
427 if (r) 418 if (r)
428 goto error; 419 goto error_free;
429 420
430 ttm_eu_fence_buffer_objects(&ticket, &head, &ib.fence->base); 421 ib.fence->is_vm_update = true;
431 radeon_ib_free(rdev, &ib); 422 radeon_bo_fence(bo, ib.fence, false);
432 423
433 return 0; 424error_free:
425 radeon_ib_free(rdev, &ib);
434 426
435error: 427error_unreserve:
436 ttm_eu_backoff_reservation(&ticket, &head); 428 radeon_bo_unreserve(bo);
437 return r; 429 return r;
438} 430}
439 431
@@ -449,7 +441,7 @@ error:
449 * Validate and set the offset requested within the vm address space. 441 * Validate and set the offset requested within the vm address space.
450 * Returns 0 for success, error for failure. 442 * Returns 0 for success, error for failure.
451 * 443 *
452 * Object has to be reserved! 444 * Object has to be reserved and gets unreserved by this function!
453 */ 445 */
454int radeon_vm_bo_set_addr(struct radeon_device *rdev, 446int radeon_vm_bo_set_addr(struct radeon_device *rdev,
455 struct radeon_bo_va *bo_va, 447 struct radeon_bo_va *bo_va,
@@ -495,7 +487,9 @@ int radeon_vm_bo_set_addr(struct radeon_device *rdev,
495 tmp->vm = vm; 487 tmp->vm = vm;
496 tmp->addr = bo_va->addr; 488 tmp->addr = bo_va->addr;
497 tmp->bo = radeon_bo_ref(bo_va->bo); 489 tmp->bo = radeon_bo_ref(bo_va->bo);
490 spin_lock(&vm->status_lock);
498 list_add(&tmp->vm_status, &vm->freed); 491 list_add(&tmp->vm_status, &vm->freed);
492 spin_unlock(&vm->status_lock);
499 } 493 }
500 494
501 interval_tree_remove(&bo_va->it, &vm->va); 495 interval_tree_remove(&bo_va->it, &vm->va);
@@ -575,7 +569,7 @@ int radeon_vm_bo_set_addr(struct radeon_device *rdev,
575 } 569 }
576 570
577 mutex_unlock(&vm->mutex); 571 mutex_unlock(&vm->mutex);
578 return radeon_bo_reserve(bo_va->bo, false); 572 return 0;
579} 573}
580 574
581/** 575/**
@@ -699,17 +693,15 @@ int radeon_vm_update_page_directory(struct radeon_device *rdev,
699 if (ib.length_dw != 0) { 693 if (ib.length_dw != 0) {
700 radeon_asic_vm_pad_ib(rdev, &ib); 694 radeon_asic_vm_pad_ib(rdev, &ib);
701 695
702 radeon_semaphore_sync_resv(rdev, ib.semaphore, pd->tbo.resv, false); 696 radeon_sync_resv(rdev, &ib.sync, pd->tbo.resv, true);
703 radeon_semaphore_sync_fence(ib.semaphore, vm->last_id_use);
704 WARN_ON(ib.length_dw > ndw); 697 WARN_ON(ib.length_dw > ndw);
705 r = radeon_ib_schedule(rdev, &ib, NULL, false); 698 r = radeon_ib_schedule(rdev, &ib, NULL, false);
706 if (r) { 699 if (r) {
707 radeon_ib_free(rdev, &ib); 700 radeon_ib_free(rdev, &ib);
708 return r; 701 return r;
709 } 702 }
710 radeon_fence_unref(&vm->fence); 703 ib.fence->is_vm_update = true;
711 vm->fence = radeon_fence_ref(ib.fence); 704 radeon_bo_fence(pd, ib.fence, false);
712 radeon_fence_unref(&vm->last_flush);
713 } 705 }
714 radeon_ib_free(rdev, &ib); 706 radeon_ib_free(rdev, &ib);
715 707
@@ -808,11 +800,11 @@ static void radeon_vm_frag_ptes(struct radeon_device *rdev,
808 * 800 *
809 * Global and local mutex must be locked! 801 * Global and local mutex must be locked!
810 */ 802 */
811static void radeon_vm_update_ptes(struct radeon_device *rdev, 803static int radeon_vm_update_ptes(struct radeon_device *rdev,
812 struct radeon_vm *vm, 804 struct radeon_vm *vm,
813 struct radeon_ib *ib, 805 struct radeon_ib *ib,
814 uint64_t start, uint64_t end, 806 uint64_t start, uint64_t end,
815 uint64_t dst, uint32_t flags) 807 uint64_t dst, uint32_t flags)
816{ 808{
817 uint64_t mask = RADEON_VM_PTE_COUNT - 1; 809 uint64_t mask = RADEON_VM_PTE_COUNT - 1;
818 uint64_t last_pte = ~0, last_dst = ~0; 810 uint64_t last_pte = ~0, last_dst = ~0;
@@ -825,8 +817,12 @@ static void radeon_vm_update_ptes(struct radeon_device *rdev,
825 struct radeon_bo *pt = vm->page_tables[pt_idx].bo; 817 struct radeon_bo *pt = vm->page_tables[pt_idx].bo;
826 unsigned nptes; 818 unsigned nptes;
827 uint64_t pte; 819 uint64_t pte;
820 int r;
828 821
829 radeon_semaphore_sync_resv(rdev, ib->semaphore, pt->tbo.resv, false); 822 radeon_sync_resv(rdev, &ib->sync, pt->tbo.resv, true);
823 r = reservation_object_reserve_shared(pt->tbo.resv);
824 if (r)
825 return r;
830 826
831 if ((addr & ~mask) == (end & ~mask)) 827 if ((addr & ~mask) == (end & ~mask))
832 nptes = end - addr; 828 nptes = end - addr;
@@ -860,6 +856,33 @@ static void radeon_vm_update_ptes(struct radeon_device *rdev,
860 last_pte + 8 * count, 856 last_pte + 8 * count,
861 last_dst, flags); 857 last_dst, flags);
862 } 858 }
859
860 return 0;
861}
862
863/**
864 * radeon_vm_fence_pts - fence page tables after an update
865 *
866 * @vm: requested vm
867 * @start: start of GPU address range
868 * @end: end of GPU address range
869 * @fence: fence to use
870 *
871 * Fence the page tables in the range @start - @end (cayman+).
872 *
873 * Global and local mutex must be locked!
874 */
875static void radeon_vm_fence_pts(struct radeon_vm *vm,
876 uint64_t start, uint64_t end,
877 struct radeon_fence *fence)
878{
879 unsigned i;
880
881 start >>= radeon_vm_block_size;
882 end >>= radeon_vm_block_size;
883
884 for (i = start; i <= end; ++i)
885 radeon_bo_fence(vm->page_tables[i].bo, fence, true);
863} 886}
864 887
865/** 888/**
@@ -892,7 +915,9 @@ int radeon_vm_bo_update(struct radeon_device *rdev,
892 return -EINVAL; 915 return -EINVAL;
893 } 916 }
894 917
918 spin_lock(&vm->status_lock);
895 list_del_init(&bo_va->vm_status); 919 list_del_init(&bo_va->vm_status);
920 spin_unlock(&vm->status_lock);
896 921
897 bo_va->flags &= ~RADEON_VM_PAGE_VALID; 922 bo_va->flags &= ~RADEON_VM_PAGE_VALID;
898 bo_va->flags &= ~RADEON_VM_PAGE_SYSTEM; 923 bo_va->flags &= ~RADEON_VM_PAGE_SYSTEM;
@@ -961,23 +986,34 @@ int radeon_vm_bo_update(struct radeon_device *rdev,
961 return r; 986 return r;
962 ib.length_dw = 0; 987 ib.length_dw = 0;
963 988
964 radeon_vm_update_ptes(rdev, vm, &ib, bo_va->it.start, 989 if (!(bo_va->flags & RADEON_VM_PAGE_VALID)) {
965 bo_va->it.last + 1, addr, 990 unsigned i;
966 radeon_vm_page_flags(bo_va->flags)); 991
992 for (i = 0; i < RADEON_NUM_RINGS; ++i)
993 radeon_sync_fence(&ib.sync, vm->ids[i].last_id_use);
994 }
995
996 r = radeon_vm_update_ptes(rdev, vm, &ib, bo_va->it.start,
997 bo_va->it.last + 1, addr,
998 radeon_vm_page_flags(bo_va->flags));
999 if (r) {
1000 radeon_ib_free(rdev, &ib);
1001 return r;
1002 }
967 1003
968 radeon_asic_vm_pad_ib(rdev, &ib); 1004 radeon_asic_vm_pad_ib(rdev, &ib);
969 WARN_ON(ib.length_dw > ndw); 1005 WARN_ON(ib.length_dw > ndw);
970 1006
971 radeon_semaphore_sync_fence(ib.semaphore, vm->fence);
972 r = radeon_ib_schedule(rdev, &ib, NULL, false); 1007 r = radeon_ib_schedule(rdev, &ib, NULL, false);
973 if (r) { 1008 if (r) {
974 radeon_ib_free(rdev, &ib); 1009 radeon_ib_free(rdev, &ib);
975 return r; 1010 return r;
976 } 1011 }
977 radeon_fence_unref(&vm->fence); 1012 ib.fence->is_vm_update = true;
978 vm->fence = radeon_fence_ref(ib.fence); 1013 radeon_vm_fence_pts(vm, bo_va->it.start, bo_va->it.last + 1, ib.fence);
1014 radeon_fence_unref(&bo_va->last_pt_update);
1015 bo_va->last_pt_update = radeon_fence_ref(ib.fence);
979 radeon_ib_free(rdev, &ib); 1016 radeon_ib_free(rdev, &ib);
980 radeon_fence_unref(&vm->last_flush);
981 1017
982 return 0; 1018 return 0;
983} 1019}
@@ -996,16 +1032,25 @@ int radeon_vm_bo_update(struct radeon_device *rdev,
996int radeon_vm_clear_freed(struct radeon_device *rdev, 1032int radeon_vm_clear_freed(struct radeon_device *rdev,
997 struct radeon_vm *vm) 1033 struct radeon_vm *vm)
998{ 1034{
999 struct radeon_bo_va *bo_va, *tmp; 1035 struct radeon_bo_va *bo_va;
1000 int r; 1036 int r;
1001 1037
1002 list_for_each_entry_safe(bo_va, tmp, &vm->freed, vm_status) { 1038 spin_lock(&vm->status_lock);
1039 while (!list_empty(&vm->freed)) {
1040 bo_va = list_first_entry(&vm->freed,
1041 struct radeon_bo_va, vm_status);
1042 spin_unlock(&vm->status_lock);
1043
1003 r = radeon_vm_bo_update(rdev, bo_va, NULL); 1044 r = radeon_vm_bo_update(rdev, bo_va, NULL);
1004 radeon_bo_unref(&bo_va->bo); 1045 radeon_bo_unref(&bo_va->bo);
1046 radeon_fence_unref(&bo_va->last_pt_update);
1005 kfree(bo_va); 1047 kfree(bo_va);
1006 if (r) 1048 if (r)
1007 return r; 1049 return r;
1050
1051 spin_lock(&vm->status_lock);
1008 } 1052 }
1053 spin_unlock(&vm->status_lock);
1009 return 0; 1054 return 0;
1010 1055
1011} 1056}
@@ -1024,14 +1069,23 @@ int radeon_vm_clear_freed(struct radeon_device *rdev,
1024int radeon_vm_clear_invalids(struct radeon_device *rdev, 1069int radeon_vm_clear_invalids(struct radeon_device *rdev,
1025 struct radeon_vm *vm) 1070 struct radeon_vm *vm)
1026{ 1071{
1027 struct radeon_bo_va *bo_va, *tmp; 1072 struct radeon_bo_va *bo_va;
1028 int r; 1073 int r;
1029 1074
1030 list_for_each_entry_safe(bo_va, tmp, &vm->invalidated, vm_status) { 1075 spin_lock(&vm->status_lock);
1076 while (!list_empty(&vm->invalidated)) {
1077 bo_va = list_first_entry(&vm->invalidated,
1078 struct radeon_bo_va, vm_status);
1079 spin_unlock(&vm->status_lock);
1080
1031 r = radeon_vm_bo_update(rdev, bo_va, NULL); 1081 r = radeon_vm_bo_update(rdev, bo_va, NULL);
1032 if (r) 1082 if (r)
1033 return r; 1083 return r;
1084
1085 spin_lock(&vm->status_lock);
1034 } 1086 }
1087 spin_unlock(&vm->status_lock);
1088
1035 return 0; 1089 return 0;
1036} 1090}
1037 1091
@@ -1054,14 +1108,17 @@ void radeon_vm_bo_rmv(struct radeon_device *rdev,
1054 1108
1055 mutex_lock(&vm->mutex); 1109 mutex_lock(&vm->mutex);
1056 interval_tree_remove(&bo_va->it, &vm->va); 1110 interval_tree_remove(&bo_va->it, &vm->va);
1111 spin_lock(&vm->status_lock);
1057 list_del(&bo_va->vm_status); 1112 list_del(&bo_va->vm_status);
1058 1113
1059 if (bo_va->addr) { 1114 if (bo_va->addr) {
1060 bo_va->bo = radeon_bo_ref(bo_va->bo); 1115 bo_va->bo = radeon_bo_ref(bo_va->bo);
1061 list_add(&bo_va->vm_status, &vm->freed); 1116 list_add(&bo_va->vm_status, &vm->freed);
1062 } else { 1117 } else {
1118 radeon_fence_unref(&bo_va->last_pt_update);
1063 kfree(bo_va); 1119 kfree(bo_va);
1064 } 1120 }
1121 spin_unlock(&vm->status_lock);
1065 1122
1066 mutex_unlock(&vm->mutex); 1123 mutex_unlock(&vm->mutex);
1067} 1124}
@@ -1082,10 +1139,10 @@ void radeon_vm_bo_invalidate(struct radeon_device *rdev,
1082 1139
1083 list_for_each_entry(bo_va, &bo->va, bo_list) { 1140 list_for_each_entry(bo_va, &bo->va, bo_list) {
1084 if (bo_va->addr) { 1141 if (bo_va->addr) {
1085 mutex_lock(&bo_va->vm->mutex); 1142 spin_lock(&bo_va->vm->status_lock);
1086 list_del(&bo_va->vm_status); 1143 list_del(&bo_va->vm_status);
1087 list_add(&bo_va->vm_status, &bo_va->vm->invalidated); 1144 list_add(&bo_va->vm_status, &bo_va->vm->invalidated);
1088 mutex_unlock(&bo_va->vm->mutex); 1145 spin_unlock(&bo_va->vm->status_lock);
1089 } 1146 }
1090 } 1147 }
1091} 1148}
@@ -1103,15 +1160,17 @@ int radeon_vm_init(struct radeon_device *rdev, struct radeon_vm *vm)
1103 const unsigned align = min(RADEON_VM_PTB_ALIGN_SIZE, 1160 const unsigned align = min(RADEON_VM_PTB_ALIGN_SIZE,
1104 RADEON_VM_PTE_COUNT * 8); 1161 RADEON_VM_PTE_COUNT * 8);
1105 unsigned pd_size, pd_entries, pts_size; 1162 unsigned pd_size, pd_entries, pts_size;
1106 int r; 1163 int i, r;
1107 1164
1108 vm->id = 0;
1109 vm->ib_bo_va = NULL; 1165 vm->ib_bo_va = NULL;
1110 vm->fence = NULL; 1166 for (i = 0; i < RADEON_NUM_RINGS; ++i) {
1111 vm->last_flush = NULL; 1167 vm->ids[i].id = 0;
1112 vm->last_id_use = NULL; 1168 vm->ids[i].flushed_updates = NULL;
1169 vm->ids[i].last_id_use = NULL;
1170 }
1113 mutex_init(&vm->mutex); 1171 mutex_init(&vm->mutex);
1114 vm->va = RB_ROOT; 1172 vm->va = RB_ROOT;
1173 spin_lock_init(&vm->status_lock);
1115 INIT_LIST_HEAD(&vm->invalidated); 1174 INIT_LIST_HEAD(&vm->invalidated);
1116 INIT_LIST_HEAD(&vm->freed); 1175 INIT_LIST_HEAD(&vm->freed);
1117 1176
@@ -1165,11 +1224,13 @@ void radeon_vm_fini(struct radeon_device *rdev, struct radeon_vm *vm)
1165 if (!r) { 1224 if (!r) {
1166 list_del_init(&bo_va->bo_list); 1225 list_del_init(&bo_va->bo_list);
1167 radeon_bo_unreserve(bo_va->bo); 1226 radeon_bo_unreserve(bo_va->bo);
1227 radeon_fence_unref(&bo_va->last_pt_update);
1168 kfree(bo_va); 1228 kfree(bo_va);
1169 } 1229 }
1170 } 1230 }
1171 list_for_each_entry_safe(bo_va, tmp, &vm->freed, vm_status) { 1231 list_for_each_entry_safe(bo_va, tmp, &vm->freed, vm_status) {
1172 radeon_bo_unref(&bo_va->bo); 1232 radeon_bo_unref(&bo_va->bo);
1233 radeon_fence_unref(&bo_va->last_pt_update);
1173 kfree(bo_va); 1234 kfree(bo_va);
1174 } 1235 }
1175 1236
@@ -1179,9 +1240,10 @@ void radeon_vm_fini(struct radeon_device *rdev, struct radeon_vm *vm)
1179 1240
1180 radeon_bo_unref(&vm->page_directory); 1241 radeon_bo_unref(&vm->page_directory);
1181 1242
1182 radeon_fence_unref(&vm->fence); 1243 for (i = 0; i < RADEON_NUM_RINGS; ++i) {
1183 radeon_fence_unref(&vm->last_flush); 1244 radeon_fence_unref(&vm->ids[i].flushed_updates);
1184 radeon_fence_unref(&vm->last_id_use); 1245 radeon_fence_unref(&vm->ids[i].last_id_use);
1246 }
1185 1247
1186 mutex_destroy(&vm->mutex); 1248 mutex_destroy(&vm->mutex);
1187} 1249}