diff options
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c')
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 171 |
1 files changed, 81 insertions, 90 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c index 1a8f4e0dd023..ccba88cc8c54 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | |||
@@ -119,9 +119,7 @@ static void amdgpu_vm_bo_base_init(struct amdgpu_vm_bo_base *base, | |||
119 | * is currently evicted. add the bo to the evicted list to make sure it | 119 | * is currently evicted. add the bo to the evicted list to make sure it |
120 | * is validated on next vm use to avoid fault. | 120 | * is validated on next vm use to avoid fault. |
121 | * */ | 121 | * */ |
122 | spin_lock(&vm->status_lock); | ||
123 | list_move_tail(&base->vm_status, &vm->evicted); | 122 | list_move_tail(&base->vm_status, &vm->evicted); |
124 | spin_unlock(&vm->status_lock); | ||
125 | } | 123 | } |
126 | 124 | ||
127 | /** | 125 | /** |
@@ -226,24 +224,16 @@ int amdgpu_vm_validate_pt_bos(struct amdgpu_device *adev, struct amdgpu_vm *vm, | |||
226 | void *param) | 224 | void *param) |
227 | { | 225 | { |
228 | struct ttm_bo_global *glob = adev->mman.bdev.glob; | 226 | struct ttm_bo_global *glob = adev->mman.bdev.glob; |
229 | int r; | 227 | struct amdgpu_vm_bo_base *bo_base, *tmp; |
230 | 228 | int r = 0; | |
231 | spin_lock(&vm->status_lock); | ||
232 | while (!list_empty(&vm->evicted)) { | ||
233 | struct amdgpu_vm_bo_base *bo_base; | ||
234 | struct amdgpu_bo *bo; | ||
235 | 229 | ||
236 | bo_base = list_first_entry(&vm->evicted, | 230 | list_for_each_entry_safe(bo_base, tmp, &vm->evicted, vm_status) { |
237 | struct amdgpu_vm_bo_base, | 231 | struct amdgpu_bo *bo = bo_base->bo; |
238 | vm_status); | ||
239 | spin_unlock(&vm->status_lock); | ||
240 | 232 | ||
241 | bo = bo_base->bo; | ||
242 | BUG_ON(!bo); | ||
243 | if (bo->parent) { | 233 | if (bo->parent) { |
244 | r = validate(param, bo); | 234 | r = validate(param, bo); |
245 | if (r) | 235 | if (r) |
246 | return r; | 236 | break; |
247 | 237 | ||
248 | spin_lock(&glob->lru_lock); | 238 | spin_lock(&glob->lru_lock); |
249 | ttm_bo_move_to_lru_tail(&bo->tbo); | 239 | ttm_bo_move_to_lru_tail(&bo->tbo); |
@@ -252,22 +242,29 @@ int amdgpu_vm_validate_pt_bos(struct amdgpu_device *adev, struct amdgpu_vm *vm, | |||
252 | spin_unlock(&glob->lru_lock); | 242 | spin_unlock(&glob->lru_lock); |
253 | } | 243 | } |
254 | 244 | ||
255 | if (bo->tbo.type == ttm_bo_type_kernel && | 245 | if (bo->tbo.type != ttm_bo_type_kernel) { |
256 | vm->use_cpu_for_update) { | 246 | spin_lock(&vm->moved_lock); |
257 | r = amdgpu_bo_kmap(bo, NULL); | ||
258 | if (r) | ||
259 | return r; | ||
260 | } | ||
261 | |||
262 | spin_lock(&vm->status_lock); | ||
263 | if (bo->tbo.type != ttm_bo_type_kernel) | ||
264 | list_move(&bo_base->vm_status, &vm->moved); | 247 | list_move(&bo_base->vm_status, &vm->moved); |
265 | else | 248 | spin_unlock(&vm->moved_lock); |
249 | } else { | ||
266 | list_move(&bo_base->vm_status, &vm->relocated); | 250 | list_move(&bo_base->vm_status, &vm->relocated); |
251 | } | ||
267 | } | 252 | } |
268 | spin_unlock(&vm->status_lock); | ||
269 | 253 | ||
270 | return 0; | 254 | spin_lock(&glob->lru_lock); |
255 | list_for_each_entry(bo_base, &vm->idle, vm_status) { | ||
256 | struct amdgpu_bo *bo = bo_base->bo; | ||
257 | |||
258 | if (!bo->parent) | ||
259 | continue; | ||
260 | |||
261 | ttm_bo_move_to_lru_tail(&bo->tbo); | ||
262 | if (bo->shadow) | ||
263 | ttm_bo_move_to_lru_tail(&bo->shadow->tbo); | ||
264 | } | ||
265 | spin_unlock(&glob->lru_lock); | ||
266 | |||
267 | return r; | ||
271 | } | 268 | } |
272 | 269 | ||
273 | /** | 270 | /** |
@@ -279,13 +276,7 @@ int amdgpu_vm_validate_pt_bos(struct amdgpu_device *adev, struct amdgpu_vm *vm, | |||
279 | */ | 276 | */ |
280 | bool amdgpu_vm_ready(struct amdgpu_vm *vm) | 277 | bool amdgpu_vm_ready(struct amdgpu_vm *vm) |
281 | { | 278 | { |
282 | bool ready; | 279 | return list_empty(&vm->evicted); |
283 | |||
284 | spin_lock(&vm->status_lock); | ||
285 | ready = list_empty(&vm->evicted); | ||
286 | spin_unlock(&vm->status_lock); | ||
287 | |||
288 | return ready; | ||
289 | } | 280 | } |
290 | 281 | ||
291 | /** | 282 | /** |
@@ -477,9 +468,7 @@ static int amdgpu_vm_alloc_levels(struct amdgpu_device *adev, | |||
477 | pt->parent = amdgpu_bo_ref(parent->base.bo); | 468 | pt->parent = amdgpu_bo_ref(parent->base.bo); |
478 | 469 | ||
479 | amdgpu_vm_bo_base_init(&entry->base, vm, pt); | 470 | amdgpu_vm_bo_base_init(&entry->base, vm, pt); |
480 | spin_lock(&vm->status_lock); | ||
481 | list_move(&entry->base.vm_status, &vm->relocated); | 471 | list_move(&entry->base.vm_status, &vm->relocated); |
482 | spin_unlock(&vm->status_lock); | ||
483 | } | 472 | } |
484 | 473 | ||
485 | if (level < AMDGPU_VM_PTB) { | 474 | if (level < AMDGPU_VM_PTB) { |
@@ -926,10 +915,8 @@ static void amdgpu_vm_invalidate_level(struct amdgpu_device *adev, | |||
926 | if (!entry->base.bo) | 915 | if (!entry->base.bo) |
927 | continue; | 916 | continue; |
928 | 917 | ||
929 | spin_lock(&vm->status_lock); | 918 | if (!entry->base.moved) |
930 | if (list_empty(&entry->base.vm_status)) | 919 | list_move(&entry->base.vm_status, &vm->relocated); |
931 | list_add(&entry->base.vm_status, &vm->relocated); | ||
932 | spin_unlock(&vm->status_lock); | ||
933 | amdgpu_vm_invalidate_level(adev, vm, entry, level + 1); | 920 | amdgpu_vm_invalidate_level(adev, vm, entry, level + 1); |
934 | } | 921 | } |
935 | } | 922 | } |
@@ -959,6 +946,14 @@ restart: | |||
959 | params.adev = adev; | 946 | params.adev = adev; |
960 | 947 | ||
961 | if (vm->use_cpu_for_update) { | 948 | if (vm->use_cpu_for_update) { |
949 | struct amdgpu_vm_bo_base *bo_base; | ||
950 | |||
951 | list_for_each_entry(bo_base, &vm->relocated, vm_status) { | ||
952 | r = amdgpu_bo_kmap(bo_base->bo, NULL); | ||
953 | if (unlikely(r)) | ||
954 | return r; | ||
955 | } | ||
956 | |||
962 | r = amdgpu_vm_wait_pd(adev, vm, AMDGPU_FENCE_OWNER_VM); | 957 | r = amdgpu_vm_wait_pd(adev, vm, AMDGPU_FENCE_OWNER_VM); |
963 | if (unlikely(r)) | 958 | if (unlikely(r)) |
964 | return r; | 959 | return r; |
@@ -974,7 +969,6 @@ restart: | |||
974 | params.func = amdgpu_vm_do_set_ptes; | 969 | params.func = amdgpu_vm_do_set_ptes; |
975 | } | 970 | } |
976 | 971 | ||
977 | spin_lock(&vm->status_lock); | ||
978 | while (!list_empty(&vm->relocated)) { | 972 | while (!list_empty(&vm->relocated)) { |
979 | struct amdgpu_vm_bo_base *bo_base, *parent; | 973 | struct amdgpu_vm_bo_base *bo_base, *parent; |
980 | struct amdgpu_vm_pt *pt, *entry; | 974 | struct amdgpu_vm_pt *pt, *entry; |
@@ -983,14 +977,12 @@ restart: | |||
983 | bo_base = list_first_entry(&vm->relocated, | 977 | bo_base = list_first_entry(&vm->relocated, |
984 | struct amdgpu_vm_bo_base, | 978 | struct amdgpu_vm_bo_base, |
985 | vm_status); | 979 | vm_status); |
986 | list_del_init(&bo_base->vm_status); | 980 | bo_base->moved = false; |
987 | spin_unlock(&vm->status_lock); | 981 | list_move(&bo_base->vm_status, &vm->idle); |
988 | 982 | ||
989 | bo = bo_base->bo->parent; | 983 | bo = bo_base->bo->parent; |
990 | if (!bo) { | 984 | if (!bo) |
991 | spin_lock(&vm->status_lock); | ||
992 | continue; | 985 | continue; |
993 | } | ||
994 | 986 | ||
995 | parent = list_first_entry(&bo->va, struct amdgpu_vm_bo_base, | 987 | parent = list_first_entry(&bo->va, struct amdgpu_vm_bo_base, |
996 | bo_list); | 988 | bo_list); |
@@ -999,12 +991,10 @@ restart: | |||
999 | 991 | ||
1000 | amdgpu_vm_update_pde(¶ms, vm, pt, entry); | 992 | amdgpu_vm_update_pde(¶ms, vm, pt, entry); |
1001 | 993 | ||
1002 | spin_lock(&vm->status_lock); | ||
1003 | if (!vm->use_cpu_for_update && | 994 | if (!vm->use_cpu_for_update && |
1004 | (ndw - params.ib->length_dw) < 32) | 995 | (ndw - params.ib->length_dw) < 32) |
1005 | break; | 996 | break; |
1006 | } | 997 | } |
1007 | spin_unlock(&vm->status_lock); | ||
1008 | 998 | ||
1009 | if (vm->use_cpu_for_update) { | 999 | if (vm->use_cpu_for_update) { |
1010 | /* Flush HDP */ | 1000 | /* Flush HDP */ |
@@ -1107,9 +1097,7 @@ static void amdgpu_vm_handle_huge_pages(struct amdgpu_pte_update_params *p, | |||
1107 | if (entry->huge) { | 1097 | if (entry->huge) { |
1108 | /* Add the entry to the relocated list to update it. */ | 1098 | /* Add the entry to the relocated list to update it. */ |
1109 | entry->huge = false; | 1099 | entry->huge = false; |
1110 | spin_lock(&p->vm->status_lock); | ||
1111 | list_move(&entry->base.vm_status, &p->vm->relocated); | 1100 | list_move(&entry->base.vm_status, &p->vm->relocated); |
1112 | spin_unlock(&p->vm->status_lock); | ||
1113 | } | 1101 | } |
1114 | return; | 1102 | return; |
1115 | } | 1103 | } |
@@ -1588,18 +1576,22 @@ int amdgpu_vm_bo_update(struct amdgpu_device *adev, | |||
1588 | amdgpu_asic_flush_hdp(adev, NULL); | 1576 | amdgpu_asic_flush_hdp(adev, NULL); |
1589 | } | 1577 | } |
1590 | 1578 | ||
1591 | spin_lock(&vm->status_lock); | 1579 | spin_lock(&vm->moved_lock); |
1592 | list_del_init(&bo_va->base.vm_status); | 1580 | list_del_init(&bo_va->base.vm_status); |
1581 | spin_unlock(&vm->moved_lock); | ||
1593 | 1582 | ||
1594 | /* If the BO is not in its preferred location add it back to | 1583 | /* If the BO is not in its preferred location add it back to |
1595 | * the evicted list so that it gets validated again on the | 1584 | * the evicted list so that it gets validated again on the |
1596 | * next command submission. | 1585 | * next command submission. |
1597 | */ | 1586 | */ |
1598 | if (bo && bo->tbo.resv == vm->root.base.bo->tbo.resv && | 1587 | if (bo && bo->tbo.resv == vm->root.base.bo->tbo.resv) { |
1599 | !(bo->preferred_domains & | 1588 | uint32_t mem_type = bo->tbo.mem.mem_type; |
1600 | amdgpu_mem_type_to_domain(bo->tbo.mem.mem_type))) | 1589 | |
1601 | list_add_tail(&bo_va->base.vm_status, &vm->evicted); | 1590 | if (!(bo->preferred_domains & amdgpu_mem_type_to_domain(mem_type))) |
1602 | spin_unlock(&vm->status_lock); | 1591 | list_add_tail(&bo_va->base.vm_status, &vm->evicted); |
1592 | else | ||
1593 | list_add(&bo_va->base.vm_status, &vm->idle); | ||
1594 | } | ||
1603 | 1595 | ||
1604 | list_splice_init(&bo_va->invalids, &bo_va->valids); | 1596 | list_splice_init(&bo_va->invalids, &bo_va->valids); |
1605 | bo_va->cleared = clear; | 1597 | bo_va->cleared = clear; |
@@ -1808,19 +1800,18 @@ int amdgpu_vm_clear_freed(struct amdgpu_device *adev, | |||
1808 | int amdgpu_vm_handle_moved(struct amdgpu_device *adev, | 1800 | int amdgpu_vm_handle_moved(struct amdgpu_device *adev, |
1809 | struct amdgpu_vm *vm) | 1801 | struct amdgpu_vm *vm) |
1810 | { | 1802 | { |
1803 | struct amdgpu_bo_va *bo_va, *tmp; | ||
1804 | struct list_head moved; | ||
1811 | bool clear; | 1805 | bool clear; |
1812 | int r = 0; | 1806 | int r; |
1813 | |||
1814 | spin_lock(&vm->status_lock); | ||
1815 | while (!list_empty(&vm->moved)) { | ||
1816 | struct amdgpu_bo_va *bo_va; | ||
1817 | struct reservation_object *resv; | ||
1818 | 1807 | ||
1819 | bo_va = list_first_entry(&vm->moved, | 1808 | INIT_LIST_HEAD(&moved); |
1820 | struct amdgpu_bo_va, base.vm_status); | 1809 | spin_lock(&vm->moved_lock); |
1821 | spin_unlock(&vm->status_lock); | 1810 | list_splice_init(&vm->moved, &moved); |
1811 | spin_unlock(&vm->moved_lock); | ||
1822 | 1812 | ||
1823 | resv = bo_va->base.bo->tbo.resv; | 1813 | list_for_each_entry_safe(bo_va, tmp, &moved, base.vm_status) { |
1814 | struct reservation_object *resv = bo_va->base.bo->tbo.resv; | ||
1824 | 1815 | ||
1825 | /* Per VM BOs never need to bo cleared in the page tables */ | 1816 | /* Per VM BOs never need to bo cleared in the page tables */ |
1826 | if (resv == vm->root.base.bo->tbo.resv) | 1817 | if (resv == vm->root.base.bo->tbo.resv) |
@@ -1833,17 +1824,19 @@ int amdgpu_vm_handle_moved(struct amdgpu_device *adev, | |||
1833 | clear = true; | 1824 | clear = true; |
1834 | 1825 | ||
1835 | r = amdgpu_vm_bo_update(adev, bo_va, clear); | 1826 | r = amdgpu_vm_bo_update(adev, bo_va, clear); |
1836 | if (r) | 1827 | if (r) { |
1828 | spin_lock(&vm->moved_lock); | ||
1829 | list_splice(&moved, &vm->moved); | ||
1830 | spin_unlock(&vm->moved_lock); | ||
1837 | return r; | 1831 | return r; |
1832 | } | ||
1838 | 1833 | ||
1839 | if (!clear && resv != vm->root.base.bo->tbo.resv) | 1834 | if (!clear && resv != vm->root.base.bo->tbo.resv) |
1840 | reservation_object_unlock(resv); | 1835 | reservation_object_unlock(resv); |
1841 | 1836 | ||
1842 | spin_lock(&vm->status_lock); | ||
1843 | } | 1837 | } |
1844 | spin_unlock(&vm->status_lock); | ||
1845 | 1838 | ||
1846 | return r; | 1839 | return 0; |
1847 | } | 1840 | } |
1848 | 1841 | ||
1849 | /** | 1842 | /** |
@@ -1902,11 +1895,11 @@ static void amdgpu_vm_bo_insert_map(struct amdgpu_device *adev, | |||
1902 | if (mapping->flags & AMDGPU_PTE_PRT) | 1895 | if (mapping->flags & AMDGPU_PTE_PRT) |
1903 | amdgpu_vm_prt_get(adev); | 1896 | amdgpu_vm_prt_get(adev); |
1904 | 1897 | ||
1905 | if (bo && bo->tbo.resv == vm->root.base.bo->tbo.resv) { | 1898 | if (bo && bo->tbo.resv == vm->root.base.bo->tbo.resv && |
1906 | spin_lock(&vm->status_lock); | 1899 | !bo_va->base.moved) { |
1907 | if (list_empty(&bo_va->base.vm_status)) | 1900 | spin_lock(&vm->moved_lock); |
1908 | list_add(&bo_va->base.vm_status, &vm->moved); | 1901 | list_move(&bo_va->base.vm_status, &vm->moved); |
1909 | spin_unlock(&vm->status_lock); | 1902 | spin_unlock(&vm->moved_lock); |
1910 | } | 1903 | } |
1911 | trace_amdgpu_vm_bo_map(bo_va, mapping); | 1904 | trace_amdgpu_vm_bo_map(bo_va, mapping); |
1912 | } | 1905 | } |
@@ -2216,9 +2209,9 @@ void amdgpu_vm_bo_rmv(struct amdgpu_device *adev, | |||
2216 | 2209 | ||
2217 | list_del(&bo_va->base.bo_list); | 2210 | list_del(&bo_va->base.bo_list); |
2218 | 2211 | ||
2219 | spin_lock(&vm->status_lock); | 2212 | spin_lock(&vm->moved_lock); |
2220 | list_del(&bo_va->base.vm_status); | 2213 | list_del(&bo_va->base.vm_status); |
2221 | spin_unlock(&vm->status_lock); | 2214 | spin_unlock(&vm->moved_lock); |
2222 | 2215 | ||
2223 | list_for_each_entry_safe(mapping, next, &bo_va->valids, list) { | 2216 | list_for_each_entry_safe(mapping, next, &bo_va->valids, list) { |
2224 | list_del(&mapping->list); | 2217 | list_del(&mapping->list); |
@@ -2258,31 +2251,28 @@ void amdgpu_vm_bo_invalidate(struct amdgpu_device *adev, | |||
2258 | 2251 | ||
2259 | list_for_each_entry(bo_base, &bo->va, bo_list) { | 2252 | list_for_each_entry(bo_base, &bo->va, bo_list) { |
2260 | struct amdgpu_vm *vm = bo_base->vm; | 2253 | struct amdgpu_vm *vm = bo_base->vm; |
2254 | bool was_moved = bo_base->moved; | ||
2261 | 2255 | ||
2262 | bo_base->moved = true; | 2256 | bo_base->moved = true; |
2263 | if (evicted && bo->tbo.resv == vm->root.base.bo->tbo.resv) { | 2257 | if (evicted && bo->tbo.resv == vm->root.base.bo->tbo.resv) { |
2264 | spin_lock(&bo_base->vm->status_lock); | ||
2265 | if (bo->tbo.type == ttm_bo_type_kernel) | 2258 | if (bo->tbo.type == ttm_bo_type_kernel) |
2266 | list_move(&bo_base->vm_status, &vm->evicted); | 2259 | list_move(&bo_base->vm_status, &vm->evicted); |
2267 | else | 2260 | else |
2268 | list_move_tail(&bo_base->vm_status, | 2261 | list_move_tail(&bo_base->vm_status, |
2269 | &vm->evicted); | 2262 | &vm->evicted); |
2270 | spin_unlock(&bo_base->vm->status_lock); | ||
2271 | continue; | 2263 | continue; |
2272 | } | 2264 | } |
2273 | 2265 | ||
2274 | if (bo->tbo.type == ttm_bo_type_kernel) { | 2266 | if (was_moved) |
2275 | spin_lock(&bo_base->vm->status_lock); | ||
2276 | if (list_empty(&bo_base->vm_status)) | ||
2277 | list_add(&bo_base->vm_status, &vm->relocated); | ||
2278 | spin_unlock(&bo_base->vm->status_lock); | ||
2279 | continue; | 2267 | continue; |
2280 | } | ||
2281 | 2268 | ||
2282 | spin_lock(&bo_base->vm->status_lock); | 2269 | if (bo->tbo.type == ttm_bo_type_kernel) { |
2283 | if (list_empty(&bo_base->vm_status)) | 2270 | list_move(&bo_base->vm_status, &vm->relocated); |
2284 | list_add(&bo_base->vm_status, &vm->moved); | 2271 | } else { |
2285 | spin_unlock(&bo_base->vm->status_lock); | 2272 | spin_lock(&bo_base->vm->moved_lock); |
2273 | list_move(&bo_base->vm_status, &vm->moved); | ||
2274 | spin_unlock(&bo_base->vm->moved_lock); | ||
2275 | } | ||
2286 | } | 2276 | } |
2287 | } | 2277 | } |
2288 | 2278 | ||
@@ -2391,10 +2381,11 @@ int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm, | |||
2391 | vm->va = RB_ROOT_CACHED; | 2381 | vm->va = RB_ROOT_CACHED; |
2392 | for (i = 0; i < AMDGPU_MAX_VMHUBS; i++) | 2382 | for (i = 0; i < AMDGPU_MAX_VMHUBS; i++) |
2393 | vm->reserved_vmid[i] = NULL; | 2383 | vm->reserved_vmid[i] = NULL; |
2394 | spin_lock_init(&vm->status_lock); | ||
2395 | INIT_LIST_HEAD(&vm->evicted); | 2384 | INIT_LIST_HEAD(&vm->evicted); |
2396 | INIT_LIST_HEAD(&vm->relocated); | 2385 | INIT_LIST_HEAD(&vm->relocated); |
2386 | spin_lock_init(&vm->moved_lock); | ||
2397 | INIT_LIST_HEAD(&vm->moved); | 2387 | INIT_LIST_HEAD(&vm->moved); |
2388 | INIT_LIST_HEAD(&vm->idle); | ||
2398 | INIT_LIST_HEAD(&vm->freed); | 2389 | INIT_LIST_HEAD(&vm->freed); |
2399 | 2390 | ||
2400 | /* create scheduler entity for page table updates */ | 2391 | /* create scheduler entity for page table updates */ |