Rev 5078 | Rev 6104 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 5078 | Rev 5271 | ||
---|---|---|---|
Line 123... | Line 123... | ||
123 | * @head: head of validation list |
123 | * @head: head of validation list |
124 | * |
124 | * |
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 | */ |
128 | struct radeon_cs_reloc *radeon_vm_get_bos(struct radeon_device *rdev, |
128 | struct 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; |
Line 134... | Line 134... | ||
134 | 134 | ||
135 | list = kmalloc_array(vm->max_pde_used + 2, |
135 | list = kmalloc_array(vm->max_pde_used + 2, |
136 | sizeof(struct radeon_cs_reloc), GFP_KERNEL); |
136 | sizeof(struct radeon_bo_list), GFP_KERNEL); |
137 | if (!list) |
137 | if (!list) |
Line 138... | Line 138... | ||
138 | return NULL; |
138 | return NULL; |
139 | - | ||
140 | /* add the vm page table to the list */ |
139 | |
141 | list[0].gobj = NULL; |
140 | /* add the vm page table to the list */ |
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; |
- | 143 | list[0].allowed_domains = RADEON_GEM_DOMAIN_VRAM; |
|
144 | list[0].allowed_domains = RADEON_GEM_DOMAIN_VRAM; |
144 | list[0].tv.bo = &vm->page_directory->tbo; |
145 | list[0].tv.bo = &vm->page_directory->tbo; |
- | |
146 | list[0].tiling_flags = 0; |
145 | list[0].tv.shared = true; |
Line 147... | Line 146... | ||
147 | list[0].handle = 0; |
146 | list[0].tiling_flags = 0; |
148 | list_add(&list[0].tv.head, head); |
147 | list_add(&list[0].tv.head, head); |
149 | 148 | ||
Line 150... | Line -... | ||
150 | for (i = 0, idx = 1; i <= vm->max_pde_used; i++) { |
- | |
151 | if (!vm->page_tables[i].bo) |
149 | for (i = 0, idx = 1; i <= vm->max_pde_used; i++) { |
152 | continue; |
150 | if (!vm->page_tables[i].bo) |
153 | 151 | continue; |
|
154 | list[idx].gobj = NULL; |
152 | |
- | 153 | list[idx].robj = vm->page_tables[i].bo; |
|
155 | list[idx].robj = vm->page_tables[i].bo; |
154 | list[idx].prefered_domains = RADEON_GEM_DOMAIN_VRAM; |
156 | list[idx].prefered_domains = RADEON_GEM_DOMAIN_VRAM; |
- | |
157 | list[idx].allowed_domains = RADEON_GEM_DOMAIN_VRAM; |
155 | list[idx].allowed_domains = RADEON_GEM_DOMAIN_VRAM; |
158 | list[idx].tv.bo = &list[idx].robj->tbo; |
156 | list[idx].tv.bo = &list[idx].robj->tbo; |
Line 159... | Line 157... | ||
159 | list[idx].tiling_flags = 0; |
157 | list[idx].tv.shared = true; |
160 | list[idx].handle = 0; |
158 | list[idx].tiling_flags = 0; |
Line 178... | Line 176... | ||
178 | */ |
176 | */ |
179 | struct radeon_fence *radeon_vm_grab_id(struct radeon_device *rdev, |
177 | struct radeon_fence *radeon_vm_grab_id(struct radeon_device *rdev, |
180 | struct radeon_vm *vm, int ring) |
178 | struct radeon_vm *vm, int ring) |
181 | { |
179 | { |
182 | 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 | ||
183 | unsigned choices[2] = {}; |
183 | unsigned choices[2] = {}; |
184 | unsigned i; |
184 | unsigned i; |
Line 185... | Line 185... | ||
185 | 185 | ||
- | 186 | /* check if the id is still valid */ |
|
186 | /* check if the id is still valid */ |
187 | if (vm_id->id && vm_id->last_id_use && |
187 | if (vm->last_id_use && vm->last_id_use == rdev->vm_manager.active[vm->id]) |
188 | vm_id->last_id_use == rdev->vm_manager.active[vm_id->id]) |
Line 188... | Line 189... | ||
188 | return NULL; |
189 | return NULL; |
189 | 190 | ||
Line 190... | Line 191... | ||
190 | /* we definately need to flush */ |
191 | /* we definately need to flush */ |
191 | radeon_fence_unref(&vm->last_flush); |
192 | vm_id->pd_gpu_addr = ~0ll; |
192 | 193 | ||
Line 193... | Line 194... | ||
193 | /* skip over VMID 0, since it is the system VM */ |
194 | /* skip over VMID 0, since it is the system VM */ |
194 | for (i = 1; i < rdev->vm_manager.nvm; ++i) { |
195 | for (i = 1; i < rdev->vm_manager.nvm; ++i) { |
195 | struct radeon_fence *fence = rdev->vm_manager.active[i]; |
196 | struct radeon_fence *fence = rdev->vm_manager.active[i]; |
196 | 197 | ||
197 | if (fence == NULL) { |
198 | if (fence == NULL) { |
198 | /* found a free one */ |
199 | /* found a free one */ |
Line 199... | Line 200... | ||
199 | vm->id = i; |
200 | vm_id->id = i; |
200 | trace_radeon_vm_grab_id(vm->id, ring); |
201 | trace_radeon_vm_grab_id(i, ring); |
Line 207... | Line 208... | ||
207 | } |
208 | } |
208 | } |
209 | } |
Line 209... | Line 210... | ||
209 | 210 | ||
210 | for (i = 0; i < 2; ++i) { |
211 | for (i = 0; i < 2; ++i) { |
211 | if (choices[i]) { |
212 | if (choices[i]) { |
212 | vm->id = choices[i]; |
213 | vm_id->id = choices[i]; |
213 | trace_radeon_vm_grab_id(vm->id, ring); |
214 | trace_radeon_vm_grab_id(choices[i], ring); |
214 | return rdev->vm_manager.active[choices[i]]; |
215 | return rdev->vm_manager.active[choices[i]]; |
215 | } |
216 | } |
Line 216... | Line 217... | ||
216 | } |
217 | } |
Line 224... | Line 225... | ||
224 | * radeon_vm_flush - hardware flush the vm |
225 | * radeon_vm_flush - hardware flush the vm |
225 | * |
226 | * |
226 | * @rdev: radeon_device pointer |
227 | * @rdev: radeon_device pointer |
227 | * @vm: vm we want to flush |
228 | * @vm: vm we want to flush |
228 | * @ring: ring to use for flush |
229 | * @ring: ring to use for flush |
- | 230 | * @updates: last vm update that is waited for |
|
229 | * |
231 | * |
230 | * Flush the vm (cayman+). |
232 | * Flush the vm (cayman+). |
231 | * |
233 | * |
232 | * Global and local mutex must be locked! |
234 | * Global and local mutex must be locked! |
233 | */ |
235 | */ |
234 | void radeon_vm_flush(struct radeon_device *rdev, |
236 | void radeon_vm_flush(struct radeon_device *rdev, |
235 | struct radeon_vm *vm, |
237 | struct radeon_vm *vm, |
236 | int ring) |
238 | int ring, struct radeon_fence *updates) |
237 | { |
239 | { |
238 | 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); |
|
Line 239... | Line -... | ||
239 | - | ||
240 | /* if we can't remember our last VM flush then flush now! */ |
- | |
241 | if (!vm->last_flush || pd_addr != vm->pd_gpu_addr) { |
- | |
242 | trace_radeon_vm_flush(pd_addr, ring, vm->id); |
- | |
243 | vm->pd_gpu_addr = pd_addr; |
- | |
244 | radeon_ring_vm_flush(rdev, ring, vm); |
252 | |
245 | } |
253 | } |
Line 246... | Line 254... | ||
246 | } |
254 | } |
247 | 255 | ||
Line 259... | Line 267... | ||
259 | */ |
267 | */ |
260 | void radeon_vm_fence(struct radeon_device *rdev, |
268 | void radeon_vm_fence(struct radeon_device *rdev, |
261 | struct radeon_vm *vm, |
269 | struct radeon_vm *vm, |
262 | struct radeon_fence *fence) |
270 | struct radeon_fence *fence) |
263 | { |
271 | { |
264 | radeon_fence_unref(&vm->fence); |
- | |
265 | vm->fence = radeon_fence_ref(fence); |
272 | unsigned vm_id = vm->ids[fence->ring].id; |
266 | - | ||
267 | radeon_fence_unref(&rdev->vm_manager.active[vm->id]); |
- | |
268 | rdev->vm_manager.active[vm->id] = radeon_fence_ref(fence); |
- | |
Line 269... | Line 273... | ||
269 | 273 | ||
270 | radeon_fence_unref(&vm->last_id_use); |
274 | radeon_fence_unref(&rdev->vm_manager.active[vm_id]); |
Line 271... | Line 275... | ||
271 | vm->last_id_use = radeon_fence_ref(fence); |
275 | rdev->vm_manager.active[vm_id] = radeon_fence_ref(fence); |
272 | - | ||
273 | /* we just flushed the VM, remember that */ |
276 | |
274 | if (!vm->last_flush) |
277 | radeon_fence_unref(&vm->ids[fence->ring].last_id_use); |
Line 275... | Line 278... | ||
275 | vm->last_flush = radeon_fence_ref(fence); |
278 | vm->ids[fence->ring].last_id_use = radeon_fence_ref(fence); |
276 | } |
279 | } |
277 | 280 | ||
Line 383... | Line 386... | ||
383 | * @bo: bo to clear |
386 | * @bo: bo to clear |
384 | */ |
387 | */ |
385 | static int radeon_vm_clear_bo(struct radeon_device *rdev, |
388 | static int radeon_vm_clear_bo(struct radeon_device *rdev, |
386 | struct radeon_bo *bo) |
389 | struct radeon_bo *bo) |
387 | { |
390 | { |
388 | struct ttm_validate_buffer tv; |
- | |
389 | struct ww_acquire_ctx ticket; |
- | |
390 | struct list_head head; |
- | |
391 | struct radeon_ib ib; |
391 | struct radeon_ib ib; |
392 | unsigned entries; |
392 | unsigned entries; |
393 | uint64_t addr; |
393 | uint64_t addr; |
394 | int r; |
394 | int r; |
Line 395... | Line -... | ||
395 | - | ||
396 | memset(&tv, 0, sizeof(tv)); |
- | |
397 | tv.bo = &bo->tbo; |
- | |
398 | - | ||
399 | INIT_LIST_HEAD(&head); |
395 | |
400 | list_add(&tv.head, &head); |
- | |
401 | - | ||
402 | r = ttm_eu_reserve_buffers(&ticket, &head); |
396 | r = radeon_bo_reserve(bo, false); |
403 | if (r) |
397 | if (r) |
Line 404... | Line 398... | ||
404 | return r; |
398 | return r; |
405 | 399 | ||
406 | r = ttm_bo_validate(&bo->tbo, &bo->placement, true, false); |
400 | r = ttm_bo_validate(&bo->tbo, &bo->placement, true, false); |
Line 407... | Line 401... | ||
407 | if (r) |
401 | if (r) |
408 | goto error; |
402 | goto error_unreserve; |
Line 409... | Line 403... | ||
409 | 403 | ||
410 | addr = radeon_bo_gpu_offset(bo); |
404 | addr = radeon_bo_gpu_offset(bo); |
411 | entries = radeon_bo_size(bo) / 8; |
405 | entries = radeon_bo_size(bo) / 8; |
Line 412... | Line 406... | ||
412 | 406 | ||
Line 413... | Line 407... | ||
413 | 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); |
414 | if (r) |
408 | if (r) |
415 | goto error; |
409 | goto error_unreserve; |
Line 416... | Line 410... | ||
416 | 410 | ||
417 | ib.length_dw = 0; |
411 | ib.length_dw = 0; |
418 | 412 | ||
Line 419... | Line 413... | ||
419 | radeon_vm_set_pages(rdev, &ib, addr, 0, entries, 0, 0); |
413 | radeon_vm_set_pages(rdev, &ib, addr, 0, entries, 0, 0); |
420 | radeon_asic_vm_pad_ib(rdev, &ib); |
414 | radeon_asic_vm_pad_ib(rdev, &ib); |
Line 421... | Line 415... | ||
421 | WARN_ON(ib.length_dw > 64); |
415 | WARN_ON(ib.length_dw > 64); |
- | 416 | ||
Line 422... | Line 417... | ||
422 | 417 | r = radeon_ib_schedule(rdev, &ib, NULL, false); |
|
423 | r = radeon_ib_schedule(rdev, &ib, NULL, false); |
418 | if (r) |
424 | if (r) |
419 | goto error_free; |
425 | goto error; |
420 | |
Line 426... | Line 421... | ||
426 | 421 | ib.fence->is_vm_update = true; |
|
427 | ttm_eu_fence_buffer_objects(&ticket, &head, ib.fence); |
422 | radeon_bo_fence(bo, ib.fence, false); |
Line 444... | Line 439... | ||
444 | * |
439 | * |
445 | * Set offset of @bo_va (cayman+). |
440 | * Set offset of @bo_va (cayman+). |
446 | * Validate and set the offset requested within the vm address space. |
441 | * Validate and set the offset requested within the vm address space. |
447 | * Returns 0 for success, error for failure. |
442 | * Returns 0 for success, error for failure. |
448 | * |
443 | * |
449 | * Object has to be reserved! |
444 | * Object has to be reserved and gets unreserved by this function! |
450 | */ |
445 | */ |
451 | int radeon_vm_bo_set_addr(struct radeon_device *rdev, |
446 | int radeon_vm_bo_set_addr(struct radeon_device *rdev, |
452 | struct radeon_bo_va *bo_va, |
447 | struct radeon_bo_va *bo_va, |
453 | uint64_t soffset, |
448 | uint64_t soffset, |
454 | uint32_t flags) |
449 | uint32_t flags) |
Line 490... | Line 485... | ||
490 | tmp->it.start = bo_va->it.start; |
485 | tmp->it.start = bo_va->it.start; |
491 | tmp->it.last = bo_va->it.last; |
486 | tmp->it.last = bo_va->it.last; |
492 | tmp->vm = vm; |
487 | tmp->vm = vm; |
493 | tmp->addr = bo_va->addr; |
488 | tmp->addr = bo_va->addr; |
494 | tmp->bo = radeon_bo_ref(bo_va->bo); |
489 | tmp->bo = radeon_bo_ref(bo_va->bo); |
- | 490 | spin_lock(&vm->status_lock); |
|
495 | list_add(&tmp->vm_status, &vm->freed); |
491 | list_add(&tmp->vm_status, &vm->freed); |
- | 492 | spin_unlock(&vm->status_lock); |
|
496 | } |
493 | } |
Line 497... | Line 494... | ||
497 | 494 | ||
498 | interval_tree_remove(&bo_va->it, &vm->va); |
495 | interval_tree_remove(&bo_va->it, &vm->va); |
499 | bo_va->it.start = 0; |
496 | bo_va->it.start = 0; |
Line 543... | Line 540... | ||
543 | /* drop mutex to allocate and clear page table */ |
540 | /* drop mutex to allocate and clear page table */ |
544 | mutex_unlock(&vm->mutex); |
541 | mutex_unlock(&vm->mutex); |
Line 545... | Line 542... | ||
545 | 542 | ||
546 | r = radeon_bo_create(rdev, RADEON_VM_PTE_COUNT * 8, |
543 | r = radeon_bo_create(rdev, RADEON_VM_PTE_COUNT * 8, |
547 | RADEON_GPU_PAGE_SIZE, true, |
544 | RADEON_GPU_PAGE_SIZE, true, |
- | 545 | RADEON_GEM_DOMAIN_VRAM, 0, |
|
548 | RADEON_GEM_DOMAIN_VRAM, 0, NULL, &pt); |
546 | NULL, NULL, &pt); |
549 | if (r) |
547 | if (r) |
Line 550... | Line 548... | ||
550 | return r; |
548 | return r; |
551 | 549 | ||
Line 569... | Line 567... | ||
569 | vm->page_tables[pt_idx].addr = 0; |
567 | vm->page_tables[pt_idx].addr = 0; |
570 | vm->page_tables[pt_idx].bo = pt; |
568 | vm->page_tables[pt_idx].bo = pt; |
571 | } |
569 | } |
Line 572... | Line 570... | ||
572 | 570 | ||
573 | mutex_unlock(&vm->mutex); |
571 | mutex_unlock(&vm->mutex); |
574 | return radeon_bo_reserve(bo_va->bo, false); |
572 | return 0; |
Line 575... | Line 573... | ||
575 | } |
573 | } |
576 | 574 | ||
577 | /** |
575 | /** |
Line 692... | Line 690... | ||
692 | radeon_vm_set_pages(rdev, &ib, last_pde, last_pt, count, |
690 | radeon_vm_set_pages(rdev, &ib, last_pde, last_pt, count, |
693 | incr, R600_PTE_VALID); |
691 | incr, R600_PTE_VALID); |
Line 694... | Line 692... | ||
694 | 692 | ||
695 | if (ib.length_dw != 0) { |
693 | if (ib.length_dw != 0) { |
- | 694 | radeon_asic_vm_pad_ib(rdev, &ib); |
|
696 | radeon_asic_vm_pad_ib(rdev, &ib); |
695 | |
697 | radeon_semaphore_sync_to(ib.semaphore, pd->tbo.sync_obj); |
- | |
698 | radeon_semaphore_sync_to(ib.semaphore, vm->last_id_use); |
696 | radeon_sync_resv(rdev, &ib.sync, pd->tbo.resv, true); |
699 | WARN_ON(ib.length_dw > ndw); |
697 | WARN_ON(ib.length_dw > ndw); |
700 | r = radeon_ib_schedule(rdev, &ib, NULL, false); |
698 | r = radeon_ib_schedule(rdev, &ib, NULL, false); |
701 | if (r) { |
699 | if (r) { |
702 | radeon_ib_free(rdev, &ib); |
700 | radeon_ib_free(rdev, &ib); |
703 | return r; |
701 | return r; |
704 | } |
- | |
705 | radeon_fence_unref(&vm->fence); |
702 | } |
706 | vm->fence = radeon_fence_ref(ib.fence); |
703 | ib.fence->is_vm_update = true; |
707 | radeon_fence_unref(&vm->last_flush); |
704 | radeon_bo_fence(pd, ib.fence, false); |
708 | } |
705 | } |
Line 709... | Line 706... | ||
709 | radeon_ib_free(rdev, &ib); |
706 | radeon_ib_free(rdev, &ib); |
710 | 707 | ||
Line 801... | Line 798... | ||
801 | * |
798 | * |
802 | * Update the page tables in the range @start - @end (cayman+). |
799 | * Update the page tables in the range @start - @end (cayman+). |
803 | * |
800 | * |
804 | * Global and local mutex must be locked! |
801 | * Global and local mutex must be locked! |
805 | */ |
802 | */ |
806 | static void radeon_vm_update_ptes(struct radeon_device *rdev, |
803 | static int radeon_vm_update_ptes(struct radeon_device *rdev, |
807 | struct radeon_vm *vm, |
804 | struct radeon_vm *vm, |
808 | struct radeon_ib *ib, |
805 | struct radeon_ib *ib, |
809 | uint64_t start, uint64_t end, |
806 | uint64_t start, uint64_t end, |
810 | uint64_t dst, uint32_t flags) |
807 | uint64_t dst, uint32_t flags) |
811 | { |
808 | { |
Line 818... | Line 815... | ||
818 | for (addr = start; addr < end; ) { |
815 | for (addr = start; addr < end; ) { |
819 | uint64_t pt_idx = addr >> radeon_vm_block_size; |
816 | uint64_t pt_idx = addr >> radeon_vm_block_size; |
820 | struct radeon_bo *pt = vm->page_tables[pt_idx].bo; |
817 | struct radeon_bo *pt = vm->page_tables[pt_idx].bo; |
821 | unsigned nptes; |
818 | unsigned nptes; |
822 | uint64_t pte; |
819 | uint64_t pte; |
- | 820 | int r; |
|
Line 823... | Line 821... | ||
823 | 821 | ||
- | 822 | radeon_sync_resv(rdev, &ib->sync, pt->tbo.resv, true); |
|
- | 823 | r = reservation_object_reserve_shared(pt->tbo.resv); |
|
- | 824 | if (r) |
|
Line 824... | Line 825... | ||
824 | radeon_semaphore_sync_to(ib->semaphore, pt->tbo.sync_obj); |
825 | return r; |
825 | 826 | ||
826 | if ((addr & ~mask) == (end & ~mask)) |
827 | if ((addr & ~mask) == (end & ~mask)) |
827 | nptes = end - addr; |
828 | nptes = end - addr; |
Line 853... | Line 854... | ||
853 | if (count) { |
854 | if (count) { |
854 | radeon_vm_frag_ptes(rdev, ib, last_pte, |
855 | radeon_vm_frag_ptes(rdev, ib, last_pte, |
855 | last_pte + 8 * count, |
856 | last_pte + 8 * count, |
856 | last_dst, flags); |
857 | last_dst, flags); |
857 | } |
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 | */ |
|
- | 875 | static 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); |
|
858 | } |
886 | } |
Line 859... | Line 887... | ||
859 | 887 | ||
860 | /** |
888 | /** |
861 | * radeon_vm_bo_update - map a bo into the vm page table |
889 | * radeon_vm_bo_update - map a bo into the vm page table |
Line 885... | Line 913... | ||
885 | dev_err(rdev->dev, "bo %p don't has a mapping in vm %p\n", |
913 | dev_err(rdev->dev, "bo %p don't has a mapping in vm %p\n", |
886 | bo_va->bo, vm); |
914 | bo_va->bo, vm); |
887 | return -EINVAL; |
915 | return -EINVAL; |
888 | } |
916 | } |
Line -... | Line 917... | ||
- | 917 | ||
889 | 918 | spin_lock(&vm->status_lock); |
|
- | 919 | list_del_init(&bo_va->vm_status); |
|
Line 890... | Line 920... | ||
890 | list_del_init(&bo_va->vm_status); |
920 | spin_unlock(&vm->status_lock); |
891 | 921 | ||
892 | bo_va->flags &= ~RADEON_VM_PAGE_VALID; |
922 | bo_va->flags &= ~RADEON_VM_PAGE_VALID; |
- | 923 | bo_va->flags &= ~RADEON_VM_PAGE_SYSTEM; |
|
- | 924 | bo_va->flags &= ~RADEON_VM_PAGE_SNOOPED; |
|
- | 925 | // if (bo_va->bo && radeon_ttm_tt_is_readonly(bo_va->bo->tbo.ttm)) |
|
893 | bo_va->flags &= ~RADEON_VM_PAGE_SYSTEM; |
926 | // bo_va->flags &= ~RADEON_VM_PAGE_WRITEABLE; |
894 | bo_va->flags &= ~RADEON_VM_PAGE_SNOOPED; |
927 | |
895 | if (mem) { |
928 | if (mem) { |
896 | addr = mem->start << PAGE_SHIFT; |
929 | addr = mem->start << PAGE_SHIFT; |
897 | if (mem->mem_type != TTM_PL_SYSTEM) { |
930 | if (mem->mem_type != TTM_PL_SYSTEM) { |
Line 951... | Line 984... | ||
951 | r = radeon_ib_get(rdev, R600_RING_TYPE_DMA_INDEX, &ib, NULL, ndw * 4); |
984 | r = radeon_ib_get(rdev, R600_RING_TYPE_DMA_INDEX, &ib, NULL, ndw * 4); |
952 | if (r) |
985 | if (r) |
953 | return r; |
986 | return r; |
954 | ib.length_dw = 0; |
987 | ib.length_dw = 0; |
Line -... | Line 988... | ||
- | 988 | ||
- | 989 | if (!(bo_va->flags & RADEON_VM_PAGE_VALID)) { |
|
- | 990 | unsigned i; |
|
- | 991 | ||
- | 992 | for (i = 0; i < RADEON_NUM_RINGS; ++i) |
|
- | 993 | radeon_sync_fence(&ib.sync, vm->ids[i].last_id_use); |
|
- | 994 | } |
|
955 | 995 | ||
956 | radeon_vm_update_ptes(rdev, vm, &ib, bo_va->it.start, |
996 | r = radeon_vm_update_ptes(rdev, vm, &ib, bo_va->it.start, |
957 | bo_va->it.last + 1, addr, |
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; |
|
Line 958... | Line 1002... | ||
958 | radeon_vm_page_flags(bo_va->flags)); |
1002 | } |
959 | 1003 | ||
Line 960... | Line -... | ||
960 | radeon_asic_vm_pad_ib(rdev, &ib); |
- | |
961 | WARN_ON(ib.length_dw > ndw); |
1004 | radeon_asic_vm_pad_ib(rdev, &ib); |
962 | 1005 | WARN_ON(ib.length_dw > ndw); |
|
963 | radeon_semaphore_sync_to(ib.semaphore, vm->fence); |
1006 | |
964 | r = radeon_ib_schedule(rdev, &ib, NULL, false); |
1007 | r = radeon_ib_schedule(rdev, &ib, NULL, false); |
965 | if (r) { |
1008 | if (r) { |
- | 1009 | radeon_ib_free(rdev, &ib); |
|
- | 1010 | return r; |
|
966 | radeon_ib_free(rdev, &ib); |
1011 | } |
967 | return r; |
1012 | ib.fence->is_vm_update = true; |
968 | } |
1013 | radeon_vm_fence_pts(vm, bo_va->it.start, bo_va->it.last + 1, ib.fence); |
969 | radeon_fence_unref(&vm->fence); |
- | |
Line 970... | Line 1014... | ||
970 | vm->fence = radeon_fence_ref(ib.fence); |
1014 | radeon_fence_unref(&bo_va->last_pt_update); |
971 | radeon_ib_free(rdev, &ib); |
1015 | bo_va->last_pt_update = radeon_fence_ref(ib.fence); |
Line 972... | Line 1016... | ||
972 | radeon_fence_unref(&vm->last_flush); |
1016 | radeon_ib_free(rdev, &ib); |
Line 986... | Line 1030... | ||
986 | * PTs have to be reserved and mutex must be locked! |
1030 | * PTs have to be reserved and mutex must be locked! |
987 | */ |
1031 | */ |
988 | int radeon_vm_clear_freed(struct radeon_device *rdev, |
1032 | int radeon_vm_clear_freed(struct radeon_device *rdev, |
989 | struct radeon_vm *vm) |
1033 | struct radeon_vm *vm) |
990 | { |
1034 | { |
991 | struct radeon_bo_va *bo_va, *tmp; |
1035 | struct radeon_bo_va *bo_va; |
992 | int r; |
1036 | int r; |
Line -... | Line 1037... | ||
- | 1037 | ||
- | 1038 | spin_lock(&vm->status_lock); |
|
- | 1039 | while (!list_empty(&vm->freed)) { |
|
993 | 1040 | bo_va = list_first_entry(&vm->freed, |
|
- | 1041 | struct radeon_bo_va, vm_status); |
|
- | 1042 | spin_unlock(&vm->status_lock); |
|
994 | list_for_each_entry_safe(bo_va, tmp, &vm->freed, vm_status) { |
1043 | |
995 | r = radeon_vm_bo_update(rdev, bo_va, NULL); |
1044 | r = radeon_vm_bo_update(rdev, bo_va, NULL); |
- | 1045 | radeon_bo_unref(&bo_va->bo); |
|
996 | radeon_bo_unref(&bo_va->bo); |
1046 | radeon_fence_unref(&bo_va->last_pt_update); |
997 | kfree(bo_va); |
1047 | kfree(bo_va); |
998 | if (r) |
1048 | if (r) |
- | 1049 | return r; |
|
- | 1050 | ||
999 | return r; |
1051 | spin_lock(&vm->status_lock); |
- | 1052 | } |
|
1000 | } |
1053 | spin_unlock(&vm->status_lock); |
Line 1001... | Line 1054... | ||
1001 | return 0; |
1054 | return 0; |
Line 1002... | Line 1055... | ||
1002 | 1055 | ||
Line 1014... | Line 1067... | ||
1014 | * PTs have to be reserved and mutex must be locked! |
1067 | * PTs have to be reserved and mutex must be locked! |
1015 | */ |
1068 | */ |
1016 | int radeon_vm_clear_invalids(struct radeon_device *rdev, |
1069 | int radeon_vm_clear_invalids(struct radeon_device *rdev, |
1017 | struct radeon_vm *vm) |
1070 | struct radeon_vm *vm) |
1018 | { |
1071 | { |
1019 | struct radeon_bo_va *bo_va, *tmp; |
1072 | struct radeon_bo_va *bo_va; |
1020 | int r; |
1073 | int r; |
Line -... | Line 1074... | ||
- | 1074 | ||
- | 1075 | spin_lock(&vm->status_lock); |
|
1021 | 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); |
|
1022 | list_for_each_entry_safe(bo_va, tmp, &vm->invalidated, vm_status) { |
1080 | |
1023 | r = radeon_vm_bo_update(rdev, bo_va, NULL); |
1081 | r = radeon_vm_bo_update(rdev, bo_va, NULL); |
1024 | if (r) |
1082 | if (r) |
- | 1083 | return r; |
|
- | 1084 | ||
1025 | return r; |
1085 | spin_lock(&vm->status_lock); |
- | 1086 | } |
|
- | 1087 | spin_unlock(&vm->status_lock); |
|
1026 | } |
1088 | |
1027 | return 0; |
1089 | return 0; |
Line 1028... | Line 1090... | ||
1028 | } |
1090 | } |
1029 | 1091 | ||
Line 1044... | Line 1106... | ||
1044 | 1106 | ||
Line 1045... | Line 1107... | ||
1045 | list_del(&bo_va->bo_list); |
1107 | list_del(&bo_va->bo_list); |
1046 | 1108 | ||
- | 1109 | mutex_lock(&vm->mutex); |
|
1047 | mutex_lock(&vm->mutex); |
1110 | interval_tree_remove(&bo_va->it, &vm->va); |
Line 1048... | Line 1111... | ||
1048 | interval_tree_remove(&bo_va->it, &vm->va); |
1111 | spin_lock(&vm->status_lock); |
1049 | list_del(&bo_va->vm_status); |
1112 | list_del(&bo_va->vm_status); |
1050 | 1113 | ||
1051 | if (bo_va->addr) { |
1114 | if (bo_va->addr) { |
- | 1115 | bo_va->bo = radeon_bo_ref(bo_va->bo); |
|
1052 | bo_va->bo = radeon_bo_ref(bo_va->bo); |
1116 | list_add(&bo_va->vm_status, &vm->freed); |
1053 | list_add(&bo_va->vm_status, &vm->freed); |
1117 | } else { |
- | 1118 | radeon_fence_unref(&bo_va->last_pt_update); |
|
Line 1054... | Line 1119... | ||
1054 | } else { |
1119 | kfree(bo_va); |
1055 | kfree(bo_va); |
1120 | } |
Line 1056... | Line 1121... | ||
1056 | } |
1121 | spin_unlock(&vm->status_lock); |
Line 1072... | Line 1137... | ||
1072 | { |
1137 | { |
1073 | struct radeon_bo_va *bo_va; |
1138 | struct radeon_bo_va *bo_va; |
Line 1074... | Line 1139... | ||
1074 | 1139 | ||
1075 | list_for_each_entry(bo_va, &bo->va, bo_list) { |
1140 | list_for_each_entry(bo_va, &bo->va, bo_list) { |
1076 | if (bo_va->addr) { |
1141 | if (bo_va->addr) { |
1077 | mutex_lock(&bo_va->vm->mutex); |
1142 | spin_lock(&bo_va->vm->status_lock); |
1078 | list_del(&bo_va->vm_status); |
1143 | list_del(&bo_va->vm_status); |
1079 | list_add(&bo_va->vm_status, &bo_va->vm->invalidated); |
1144 | list_add(&bo_va->vm_status, &bo_va->vm->invalidated); |
1080 | mutex_unlock(&bo_va->vm->mutex); |
1145 | spin_unlock(&bo_va->vm->status_lock); |
1081 | } |
1146 | } |
1082 | } |
1147 | } |
Line 1083... | Line 1148... | ||
1083 | } |
1148 | } |
Line 1093... | Line 1158... | ||
1093 | int radeon_vm_init(struct radeon_device *rdev, struct radeon_vm *vm) |
1158 | int radeon_vm_init(struct radeon_device *rdev, struct radeon_vm *vm) |
1094 | { |
1159 | { |
1095 | const unsigned align = min(RADEON_VM_PTB_ALIGN_SIZE, |
1160 | const unsigned align = min(RADEON_VM_PTB_ALIGN_SIZE, |
1096 | RADEON_VM_PTE_COUNT * 8); |
1161 | RADEON_VM_PTE_COUNT * 8); |
1097 | unsigned pd_size, pd_entries, pts_size; |
1162 | unsigned pd_size, pd_entries, pts_size; |
1098 | int r; |
1163 | int i, r; |
Line 1099... | Line -... | ||
1099 | - | ||
1100 | vm->id = 0; |
1164 | |
- | 1165 | vm->ib_bo_va = NULL; |
|
1101 | vm->ib_bo_va = NULL; |
1166 | for (i = 0; i < RADEON_NUM_RINGS; ++i) { |
1102 | vm->fence = NULL; |
1167 | vm->ids[i].id = 0; |
1103 | vm->last_flush = NULL; |
1168 | vm->ids[i].flushed_updates = NULL; |
- | 1169 | vm->ids[i].last_id_use = NULL; |
|
1104 | vm->last_id_use = NULL; |
1170 | } |
1105 | mutex_init(&vm->mutex); |
1171 | mutex_init(&vm->mutex); |
- | 1172 | vm->va = RB_ROOT; |
|
1106 | vm->va = RB_ROOT; |
1173 | spin_lock_init(&vm->status_lock); |
1107 | INIT_LIST_HEAD(&vm->invalidated); |
1174 | INIT_LIST_HEAD(&vm->invalidated); |
Line 1108... | Line 1175... | ||
1108 | INIT_LIST_HEAD(&vm->freed); |
1175 | INIT_LIST_HEAD(&vm->freed); |
1109 | 1176 | ||
Line 1118... | Line 1185... | ||
1118 | return -ENOMEM; |
1185 | return -ENOMEM; |
1119 | } |
1186 | } |
Line 1120... | Line 1187... | ||
1120 | 1187 | ||
1121 | r = radeon_bo_create(rdev, pd_size, align, true, |
1188 | r = radeon_bo_create(rdev, pd_size, align, true, |
1122 | RADEON_GEM_DOMAIN_VRAM, 0, NULL, |
1189 | RADEON_GEM_DOMAIN_VRAM, 0, NULL, |
1123 | &vm->page_directory); |
1190 | NULL, &vm->page_directory); |
1124 | if (r) |
1191 | if (r) |
Line 1125... | Line 1192... | ||
1125 | return r; |
1192 | return r; |
1126 | 1193 | ||
Line 1155... | Line 1222... | ||
1155 | interval_tree_remove(&bo_va->it, &vm->va); |
1222 | interval_tree_remove(&bo_va->it, &vm->va); |
1156 | r = radeon_bo_reserve(bo_va->bo, false); |
1223 | r = radeon_bo_reserve(bo_va->bo, false); |
1157 | if (!r) { |
1224 | if (!r) { |
1158 | list_del_init(&bo_va->bo_list); |
1225 | list_del_init(&bo_va->bo_list); |
1159 | radeon_bo_unreserve(bo_va->bo); |
1226 | radeon_bo_unreserve(bo_va->bo); |
- | 1227 | radeon_fence_unref(&bo_va->last_pt_update); |
|
1160 | kfree(bo_va); |
1228 | kfree(bo_va); |
1161 | } |
1229 | } |
1162 | } |
1230 | } |
1163 | 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) { |
1164 | radeon_bo_unref(&bo_va->bo); |
1232 | radeon_bo_unref(&bo_va->bo); |
- | 1233 | radeon_fence_unref(&bo_va->last_pt_update); |
|
1165 | kfree(bo_va); |
1234 | kfree(bo_va); |
1166 | } |
1235 | } |
Line 1167... | Line 1236... | ||
1167 | 1236 | ||
1168 | for (i = 0; i < radeon_vm_num_pdes(rdev); i++) |
1237 | for (i = 0; i < radeon_vm_num_pdes(rdev); i++) |
1169 | radeon_bo_unref(&vm->page_tables[i].bo); |
1238 | radeon_bo_unref(&vm->page_tables[i].bo); |
Line 1170... | Line 1239... | ||
1170 | kfree(vm->page_tables); |
1239 | kfree(vm->page_tables); |
Line 1171... | Line 1240... | ||
1171 | 1240 | ||
1172 | radeon_bo_unref(&vm->page_directory); |
1241 | radeon_bo_unref(&vm->page_directory); |
1173 | 1242 | ||
- | 1243 | for (i = 0; i < RADEON_NUM_RINGS; ++i) { |
|
Line 1174... | Line 1244... | ||
1174 | radeon_fence_unref(&vm->fence); |
1244 | radeon_fence_unref(&vm->ids[i].flushed_updates); |
1175 | radeon_fence_unref(&vm->last_flush); |
1245 | radeon_fence_unref(&vm->ids[i].last_id_use); |