This patch adds input fences to VM_IOCTL for buffer object. The kernel will map/unmap the BO only when the fence is signaled. The UAPI for the same has been approved here: https://gitlab.freedesktop.org/mesa/drm/-/merge_requests/392 V2: Bug fix (Arvind) V3: Bug fix (Arvind) V4: Rename UAPI objects as per UAPI review (Marek) V5: Addressed review comemnts from Christian - function should return error. - Add 'TODO' comment - The input fence should be independent of the operation. V6: Addressed review comemnts from Christian - Release the memory allocated by memdup_user(). V7: Addressed review comemnts from Christian - Drop the debug print and add "return r;" for the error handling. V11: Rebase v12: Fix 32-bit holes issue in sturct drm_amdgpu_gem_va. v13: Fix deadlock issue. v14: Fix merge conflict. v15: Fix review comment by renaming syncobj handles.
Unified · Split
| @@ -45,6 +45,45 @@ · 44 unmodified lines | ||
| 45 | 45 | #include "amdgpu_xgmi.h" |
| 46 | 46 | #include "amdgpu_vm.h" |
| 47 | 47 | |
| 48 | +static int | |
| 49 | +amdgpu_gem_add_input_fence(struct drm_file *filp, | |
| 50 | + uint64_t syncobj_handles_array, | |
| 51 | + uint32_t num_syncobj_handles) | |
| 52 | +{ | |
| 53 | + struct dma_fence *fence; | |
| 54 | + uint32_t *syncobj_handles; | |
| 55 | + int ret, i; | |
| 56 | + | |
| 57 | + if (!num_syncobj_handles) | |
| 58 | + return 0; | |
| 59 | + | |
| 60 | + syncobj_handles = memdup_user(u64_to_user_ptr(syncobj_handles_array), | |
| 61 | + sizeof(uint32_t) * num_syncobj_handles); | |
| 62 | + if (IS_ERR(syncobj_handles)) | |
| 63 | + return PTR_ERR(syncobj_handles); | |
| 64 | + | |
| 65 | + for (i = 0; i < num_syncobj_handles; i++) { | |
| 66 | + | |
| 67 | + if (!syncobj_handles[i]) { | |
| 68 | + ret = -EINVAL; | |
| 69 | + goto free_memdup; | |
| 70 | + } | |
| 71 | + | |
| 72 | + ret = drm_syncobj_find_fence(filp, syncobj_handles[i], 0, 0, &fence); | |
| 73 | + if (ret) | |
| 74 | + goto free_memdup; | |
| 75 | + | |
| 76 | + dma_fence_wait(fence, false); | |
| 77 | + | |
| 78 | + /* TODO: optimize async handling */ | |
| 79 | + dma_fence_put(fence); | |
| 80 | + } | |
| 81 | + | |
| 82 | +free_memdup: | |
| 83 | + kfree(syncobj_handles); | |
| 84 | + return ret; | |
| 85 | +} | |
| 86 | + | |
| 48 | 87 | static int |
| 49 | 88 | amdgpu_gem_update_timeline_node(struct drm_file *filp, |
| 50 | 89 | uint32_t syncobj_handle, |
| @@ -854,6 +893,12 @@ int amdgpu_gem_va_ioctl(struct drm_device *dev, void *data, · 803 unmodified lines | ||
| 854 | 893 | abo = NULL; |
| 855 | 894 | } |
| 856 | 895 | |
| 896 | + r = amdgpu_gem_add_input_fence(filp, | |
| 897 | + args->input_fence_syncobj_handles, | |
| 898 | + args->num_syncobj_handles); | |
| 899 | + if (r) | |
| 900 | + goto error_put_gobj; | |
| 901 | + | |
| 857 | 902 | drm_exec_init(&exec, DRM_EXEC_INTERRUPTIBLE_WAIT | |
| 858 | 903 | DRM_EXEC_IGNORE_DUPLICATES, 0); |
| 859 | 904 | drm_exec_until_all_locked(&exec) { |
| @@ -928,6 +973,7 @@ int amdgpu_gem_va_ioctl(struct drm_device *dev, void *data, · 68 unmodified lines | ||
| 928 | 973 | |
| 929 | 974 | error: |
| 930 | 975 | drm_exec_fini(&exec); |
| 976 | +error_put_gobj: | |
| 931 | 977 | drm_gem_object_put(gobj); |
| 932 | 978 | return r; |
| 933 | 979 | } |
| @@ -884,6 +884,10 @@ struct drm_amdgpu_gem_va { · 883 unmodified lines | ||
| 884 | 884 | * at vm_timeline_point. |
| 885 | 885 | */ |
| 886 | 886 | __u32 vm_timeline_syncobj_out; |
| 887 | + /** the number of syncobj handles in @input_fence_syncobj_handles */ | |
| 888 | + __u32 num_syncobj_handles; | |
| 889 | + /** Array of sync object handle to wait for given input fences */ | |
| 890 | + __u64 input_fence_syncobj_handles; | |
| 887 | 891 | }; |
| 888 | 892 | |
| 889 | 893 | #define AMDGPU_HW_IP_GFX 0 |