Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

dma-buf: add DMA_RESV_USAGE_BOOKKEEP v3

Add an usage for submissions independent of implicit sync but still
interesting for memory management.

v2: cleanup the kerneldoc a bit
v3: separate amdgpu changes from this

Signed-off-by: Christian König <christian.koenig@amd.com>
Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Link: https://patchwork.freedesktop.org/patch/msgid/20220407085946.744568-10-christian.koenig@amd.com

+35 -24
+2 -2
drivers/dma-buf/dma-resv.c
··· 520 520 521 521 list = NULL; 522 522 523 - dma_resv_iter_begin(&cursor, src, DMA_RESV_USAGE_READ); 523 + dma_resv_iter_begin(&cursor, src, DMA_RESV_USAGE_BOOKKEEP); 524 524 dma_resv_for_each_fence_unlocked(&cursor, f) { 525 525 526 526 if (dma_resv_iter_is_restarted(&cursor)) { ··· 726 726 */ 727 727 void dma_resv_describe(struct dma_resv *obj, struct seq_file *seq) 728 728 { 729 - static const char *usage[] = { "kernel", "write", "read" }; 729 + static const char *usage[] = { "kernel", "write", "read", "bookkeep" }; 730 730 struct dma_resv_iter cursor; 731 731 struct dma_fence *fence; 732 732
+1 -1
drivers/dma-buf/st-dma-resv.c
··· 296 296 int r; 297 297 298 298 spin_lock_init(&fence_lock); 299 - for (usage = DMA_RESV_USAGE_KERNEL; usage <= DMA_RESV_USAGE_READ; 299 + for (usage = DMA_RESV_USAGE_KERNEL; usage <= DMA_RESV_USAGE_BOOKKEEP; 300 300 ++usage) { 301 301 r = subtests(tests, (void *)(unsigned long)usage); 302 302 if (r)
+2 -2
drivers/gpu/drm/amd/amdgpu/amdgpu_ids.c
··· 111 111 struct dma_fence *fence; 112 112 int r; 113 113 114 - r = dma_resv_get_singleton(resv, DMA_RESV_USAGE_READ, &fence); 114 + r = dma_resv_get_singleton(resv, DMA_RESV_USAGE_BOOKKEEP, &fence); 115 115 if (r) 116 116 goto fallback; 117 117 ··· 139 139 /* Not enough memory for the delayed delete, as last resort 140 140 * block for all the fences to complete. 141 141 */ 142 - dma_resv_wait_timeout(resv, DMA_RESV_USAGE_READ, 142 + dma_resv_wait_timeout(resv, DMA_RESV_USAGE_BOOKKEEP, 143 143 false, MAX_SCHEDULE_TIMEOUT); 144 144 amdgpu_pasid_free(pasid); 145 145 }
+1 -1
drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c
··· 75 75 76 76 mmu_interval_set_seq(mni, cur_seq); 77 77 78 - r = dma_resv_wait_timeout(bo->tbo.base.resv, DMA_RESV_USAGE_READ, 78 + r = dma_resv_wait_timeout(bo->tbo.base.resv, DMA_RESV_USAGE_BOOKKEEP, 79 79 false, MAX_SCHEDULE_TIMEOUT); 80 80 mutex_unlock(&adev->notifier_lock); 81 81 if (r <= 0)
+1 -1
drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c
··· 260 260 return -EINVAL; 261 261 262 262 /* TODO: Use DMA_RESV_USAGE_READ here */ 263 - dma_resv_for_each_fence(&cursor, resv, DMA_RESV_USAGE_READ, f) { 263 + dma_resv_for_each_fence(&cursor, resv, DMA_RESV_USAGE_BOOKKEEP, f) { 264 264 dma_fence_chain_for_each(f, f) { 265 265 struct dma_fence *tmp = dma_fence_chain_contained(f); 266 266
+1 -1
drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
··· 1345 1345 * be resident to run successfully 1346 1346 */ 1347 1347 dma_resv_for_each_fence(&resv_cursor, bo->base.resv, 1348 - DMA_RESV_USAGE_READ, f) { 1348 + DMA_RESV_USAGE_BOOKKEEP, f) { 1349 1349 if (amdkfd_fence_check_mm(f, current->mm)) 1350 1350 return false; 1351 1351 }
+3 -3
drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
··· 2059 2059 struct dma_resv_iter cursor; 2060 2060 struct dma_fence *fence; 2061 2061 2062 - dma_resv_for_each_fence(&cursor, resv, DMA_RESV_USAGE_READ, fence) { 2062 + dma_resv_for_each_fence(&cursor, resv, DMA_RESV_USAGE_BOOKKEEP, fence) { 2063 2063 /* Add a callback for each fence in the reservation object */ 2064 2064 amdgpu_vm_prt_get(adev); 2065 2065 amdgpu_vm_add_prt_cb(adev, fence); ··· 2665 2665 return true; 2666 2666 2667 2667 /* Don't evict VM page tables while they are busy */ 2668 - if (!dma_resv_test_signaled(bo->tbo.base.resv, DMA_RESV_USAGE_READ)) 2668 + if (!dma_resv_test_signaled(bo->tbo.base.resv, DMA_RESV_USAGE_BOOKKEEP)) 2669 2669 return false; 2670 2670 2671 2671 /* Try to block ongoing updates */ ··· 2846 2846 long amdgpu_vm_wait_idle(struct amdgpu_vm *vm, long timeout) 2847 2847 { 2848 2848 timeout = dma_resv_wait_timeout(vm->root.bo->tbo.base.resv, 2849 - DMA_RESV_USAGE_READ, 2849 + DMA_RESV_USAGE_BOOKKEEP, 2850 2850 true, timeout); 2851 2851 if (timeout <= 0) 2852 2852 return timeout;
+1 -1
drivers/gpu/drm/i915/gem/i915_gem_lmem.c
··· 66 66 struct intel_memory_region *mr = READ_ONCE(obj->mm.region); 67 67 68 68 #ifdef CONFIG_LOCKDEP 69 - GEM_WARN_ON(dma_resv_test_signaled(obj->base.resv, DMA_RESV_USAGE_READ) && 69 + GEM_WARN_ON(dma_resv_test_signaled(obj->base.resv, DMA_RESV_USAGE_BOOKKEEP) && 70 70 i915_gem_object_evictable(obj)); 71 71 #endif 72 72 return mr && (mr->type == INTEL_MEMORY_LOCAL ||
+1 -1
drivers/gpu/drm/i915/gem/i915_gem_userptr.c
··· 86 86 return true; 87 87 88 88 /* we will unbind on next submission, still have userptr pins */ 89 - r = dma_resv_wait_timeout(obj->base.resv, DMA_RESV_USAGE_READ, false, 89 + r = dma_resv_wait_timeout(obj->base.resv, DMA_RESV_USAGE_BOOKKEEP, false, 90 90 MAX_SCHEDULE_TIMEOUT); 91 91 if (r <= 0) 92 92 drm_err(&i915->drm, "(%ld) failed to wait for idle\n", r);
+1 -1
drivers/gpu/drm/qxl/qxl_debugfs.c
··· 62 62 int rel = 0; 63 63 64 64 dma_resv_iter_begin(&cursor, bo->tbo.base.resv, 65 - DMA_RESV_USAGE_READ); 65 + DMA_RESV_USAGE_BOOKKEEP); 66 66 dma_resv_for_each_fence_unlocked(&cursor, fence) { 67 67 if (dma_resv_iter_is_restarted(&cursor)) 68 68 rel = 0;
+1 -1
drivers/gpu/drm/radeon/radeon_gem.c
··· 163 163 if (domain == RADEON_GEM_DOMAIN_CPU) { 164 164 /* Asking for cpu access wait for object idle */ 165 165 r = dma_resv_wait_timeout(robj->tbo.base.resv, 166 - DMA_RESV_USAGE_READ, 166 + DMA_RESV_USAGE_BOOKKEEP, 167 167 true, 30 * HZ); 168 168 if (!r) 169 169 r = -EBUSY;
+1 -1
drivers/gpu/drm/radeon/radeon_mn.c
··· 66 66 return true; 67 67 } 68 68 69 - r = dma_resv_wait_timeout(bo->tbo.base.resv, DMA_RESV_USAGE_READ, 69 + r = dma_resv_wait_timeout(bo->tbo.base.resv, DMA_RESV_USAGE_BOOKKEEP, 70 70 false, MAX_SCHEDULE_TIMEOUT); 71 71 if (r <= 0) 72 72 DRM_ERROR("(%ld) failed to wait for user bo\n", r);
+7 -7
drivers/gpu/drm/ttm/ttm_bo.c
··· 223 223 struct dma_resv_iter cursor; 224 224 struct dma_fence *fence; 225 225 226 - dma_resv_iter_begin(&cursor, resv, DMA_RESV_USAGE_READ); 226 + dma_resv_iter_begin(&cursor, resv, DMA_RESV_USAGE_BOOKKEEP); 227 227 dma_resv_for_each_fence_unlocked(&cursor, fence) { 228 228 if (!fence->ops->signaled) 229 229 dma_fence_enable_sw_signaling(fence); ··· 252 252 struct dma_resv *resv = &bo->base._resv; 253 253 int ret; 254 254 255 - if (dma_resv_test_signaled(resv, DMA_RESV_USAGE_READ)) 255 + if (dma_resv_test_signaled(resv, DMA_RESV_USAGE_BOOKKEEP)) 256 256 ret = 0; 257 257 else 258 258 ret = -EBUSY; ··· 264 264 dma_resv_unlock(bo->base.resv); 265 265 spin_unlock(&bo->bdev->lru_lock); 266 266 267 - lret = dma_resv_wait_timeout(resv, DMA_RESV_USAGE_READ, 267 + lret = dma_resv_wait_timeout(resv, DMA_RESV_USAGE_BOOKKEEP, 268 268 interruptible, 269 269 30 * HZ); 270 270 ··· 369 369 * fences block for the BO to become idle 370 370 */ 371 371 dma_resv_wait_timeout(bo->base.resv, 372 - DMA_RESV_USAGE_READ, false, 372 + DMA_RESV_USAGE_BOOKKEEP, false, 373 373 30 * HZ); 374 374 } 375 375 ··· 380 380 ttm_mem_io_free(bdev, bo->resource); 381 381 } 382 382 383 - if (!dma_resv_test_signaled(bo->base.resv, DMA_RESV_USAGE_READ) || 383 + if (!dma_resv_test_signaled(bo->base.resv, DMA_RESV_USAGE_BOOKKEEP) || 384 384 !dma_resv_trylock(bo->base.resv)) { 385 385 /* The BO is not idle, resurrect it for delayed destroy */ 386 386 ttm_bo_flush_all_fences(bo); ··· 1046 1046 long timeout = 15 * HZ; 1047 1047 1048 1048 if (no_wait) { 1049 - if (dma_resv_test_signaled(bo->base.resv, DMA_RESV_USAGE_READ)) 1049 + if (dma_resv_test_signaled(bo->base.resv, DMA_RESV_USAGE_BOOKKEEP)) 1050 1050 return 0; 1051 1051 else 1052 1052 return -EBUSY; 1053 1053 } 1054 1054 1055 - timeout = dma_resv_wait_timeout(bo->base.resv, DMA_RESV_USAGE_READ, 1055 + timeout = dma_resv_wait_timeout(bo->base.resv, DMA_RESV_USAGE_BOOKKEEP, 1056 1056 interruptible, timeout); 1057 1057 if (timeout < 0) 1058 1058 return timeout;
+12 -1
include/linux/dma-resv.h
··· 55 55 * This enum describes the different use cases for a dma_resv object and 56 56 * controls which fences are returned when queried. 57 57 * 58 - * An important fact is that there is the order KERNEL<WRITE<READ and 58 + * An important fact is that there is the order KERNEL<WRITE<READ<BOOKKEEP and 59 59 * when the dma_resv object is asked for fences for one use case the fences 60 60 * for the lower use case are returned as well. 61 61 * ··· 93 93 * an implicit read dependency. 94 94 */ 95 95 DMA_RESV_USAGE_READ, 96 + 97 + /** 98 + * @DMA_RESV_USAGE_BOOKKEEP: No implicit sync. 99 + * 100 + * This should be used by submissions which don't want to participate in 101 + * implicit synchronization. 102 + * 103 + * The most common case are preemption fences as well as page table 104 + * updates and their TLB flushes. 105 + */ 106 + DMA_RESV_USAGE_BOOKKEEP 96 107 }; 97 108 98 109 /**