diff options
author | Sinclair Yeh <syeh@vmware.com> | 2017-07-05 04:49:32 -0400 |
---|---|---|
committer | Sinclair Yeh <syeh@vmware.com> | 2017-08-28 11:51:46 -0400 |
commit | c906965dee22d5e95d0651759ba107b420212a9f (patch) | |
tree | b0c5a08234cebcdede8f2ddf95045331da112953 | |
parent | 585851164660e8dff961178a9533857b21d63975 (diff) |
drm/vmwgfx: Add export fence to file descriptor support
Added code to link a fence to a out_fence_fd file descriptor and
thread out_fence_fd down to vmw_execbuf_copy_fence_user() so it can be
copied into the IOCTL reply and be passed back up the the user.
v2:
Make sure to sync and clean up in case of failure
Signed-off-by: Sinclair Yeh <syeh@vmware.com>
Reviewed-by: Deepak Singh Rawat <drawat@vmware.com>
Reviewed-by: Thomas Hellstrom <thellstrom@vmware.com>
-rw-r--r-- | drivers/gpu/drm/vmwgfx/vmwgfx_drv.h | 8 | ||||
-rw-r--r-- | drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c | 69 | ||||
-rw-r--r-- | drivers/gpu/drm/vmwgfx/vmwgfx_fence.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 2 |
4 files changed, 70 insertions, 11 deletions
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h index 3f802e835216..d6ab22c7d263 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h | |||
@@ -40,6 +40,7 @@ | |||
40 | #include <drm/ttm/ttm_execbuf_util.h> | 40 | #include <drm/ttm/ttm_execbuf_util.h> |
41 | #include <drm/ttm/ttm_module.h> | 41 | #include <drm/ttm/ttm_module.h> |
42 | #include "vmwgfx_fence.h" | 42 | #include "vmwgfx_fence.h" |
43 | #include <linux/sync_file.h> | ||
43 | 44 | ||
44 | #define VMWGFX_DRIVER_NAME "vmwgfx" | 45 | #define VMWGFX_DRIVER_NAME "vmwgfx" |
45 | #define VMWGFX_DRIVER_DATE "20170607" | 46 | #define VMWGFX_DRIVER_DATE "20170607" |
@@ -826,7 +827,8 @@ extern int vmw_execbuf_process(struct drm_file *file_priv, | |||
826 | uint32_t dx_context_handle, | 827 | uint32_t dx_context_handle, |
827 | struct drm_vmw_fence_rep __user | 828 | struct drm_vmw_fence_rep __user |
828 | *user_fence_rep, | 829 | *user_fence_rep, |
829 | struct vmw_fence_obj **out_fence); | 830 | struct vmw_fence_obj **out_fence, |
831 | uint32_t flags); | ||
830 | extern void __vmw_execbuf_release_pinned_bo(struct vmw_private *dev_priv, | 832 | extern void __vmw_execbuf_release_pinned_bo(struct vmw_private *dev_priv, |
831 | struct vmw_fence_obj *fence); | 833 | struct vmw_fence_obj *fence); |
832 | extern void vmw_execbuf_release_pinned_bo(struct vmw_private *dev_priv); | 834 | extern void vmw_execbuf_release_pinned_bo(struct vmw_private *dev_priv); |
@@ -841,7 +843,9 @@ extern void vmw_execbuf_copy_fence_user(struct vmw_private *dev_priv, | |||
841 | struct drm_vmw_fence_rep __user | 843 | struct drm_vmw_fence_rep __user |
842 | *user_fence_rep, | 844 | *user_fence_rep, |
843 | struct vmw_fence_obj *fence, | 845 | struct vmw_fence_obj *fence, |
844 | uint32_t fence_handle); | 846 | uint32_t fence_handle, |
847 | int32_t out_fence_fd, | ||
848 | struct sync_file *sync_file); | ||
845 | extern int vmw_validate_single_buffer(struct vmw_private *dev_priv, | 849 | extern int vmw_validate_single_buffer(struct vmw_private *dev_priv, |
846 | struct ttm_buffer_object *bo, | 850 | struct ttm_buffer_object *bo, |
847 | bool interruptible, | 851 | bool interruptible, |
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c index f94f43cca58e..21c62a34e558 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c | |||
@@ -3830,6 +3830,8 @@ int vmw_execbuf_fence_commands(struct drm_file *file_priv, | |||
3830 | * which the information should be copied. | 3830 | * which the information should be copied. |
3831 | * @fence: Pointer to the fenc object. | 3831 | * @fence: Pointer to the fenc object. |
3832 | * @fence_handle: User-space fence handle. | 3832 | * @fence_handle: User-space fence handle. |
3833 | * @out_fence_fd: exported file descriptor for the fence. -1 if not used | ||
3834 | * @sync_file: Only used to clean up in case of an error in this function. | ||
3833 | * | 3835 | * |
3834 | * This function copies fence information to user-space. If copying fails, | 3836 | * This function copies fence information to user-space. If copying fails, |
3835 | * The user-space struct drm_vmw_fence_rep::error member is hopefully | 3837 | * The user-space struct drm_vmw_fence_rep::error member is hopefully |
@@ -3845,7 +3847,9 @@ vmw_execbuf_copy_fence_user(struct vmw_private *dev_priv, | |||
3845 | int ret, | 3847 | int ret, |
3846 | struct drm_vmw_fence_rep __user *user_fence_rep, | 3848 | struct drm_vmw_fence_rep __user *user_fence_rep, |
3847 | struct vmw_fence_obj *fence, | 3849 | struct vmw_fence_obj *fence, |
3848 | uint32_t fence_handle) | 3850 | uint32_t fence_handle, |
3851 | int32_t out_fence_fd, | ||
3852 | struct sync_file *sync_file) | ||
3849 | { | 3853 | { |
3850 | struct drm_vmw_fence_rep fence_rep; | 3854 | struct drm_vmw_fence_rep fence_rep; |
3851 | 3855 | ||
@@ -3855,6 +3859,7 @@ vmw_execbuf_copy_fence_user(struct vmw_private *dev_priv, | |||
3855 | memset(&fence_rep, 0, sizeof(fence_rep)); | 3859 | memset(&fence_rep, 0, sizeof(fence_rep)); |
3856 | 3860 | ||
3857 | fence_rep.error = ret; | 3861 | fence_rep.error = ret; |
3862 | fence_rep.fd = out_fence_fd; | ||
3858 | if (ret == 0) { | 3863 | if (ret == 0) { |
3859 | BUG_ON(fence == NULL); | 3864 | BUG_ON(fence == NULL); |
3860 | 3865 | ||
@@ -3877,6 +3882,14 @@ vmw_execbuf_copy_fence_user(struct vmw_private *dev_priv, | |||
3877 | * and unreference the handle. | 3882 | * and unreference the handle. |
3878 | */ | 3883 | */ |
3879 | if (unlikely(ret != 0) && (fence_rep.error == 0)) { | 3884 | if (unlikely(ret != 0) && (fence_rep.error == 0)) { |
3885 | if (sync_file) | ||
3886 | fput(sync_file->file); | ||
3887 | |||
3888 | if (fence_rep.fd != -1) { | ||
3889 | put_unused_fd(fence_rep.fd); | ||
3890 | fence_rep.fd = -1; | ||
3891 | } | ||
3892 | |||
3880 | ttm_ref_object_base_unref(vmw_fp->tfile, | 3893 | ttm_ref_object_base_unref(vmw_fp->tfile, |
3881 | fence_handle, TTM_REF_USAGE); | 3894 | fence_handle, TTM_REF_USAGE); |
3882 | DRM_ERROR("Fence copy error. Syncing.\n"); | 3895 | DRM_ERROR("Fence copy error. Syncing.\n"); |
@@ -4052,7 +4065,8 @@ int vmw_execbuf_process(struct drm_file *file_priv, | |||
4052 | uint64_t throttle_us, | 4065 | uint64_t throttle_us, |
4053 | uint32_t dx_context_handle, | 4066 | uint32_t dx_context_handle, |
4054 | struct drm_vmw_fence_rep __user *user_fence_rep, | 4067 | struct drm_vmw_fence_rep __user *user_fence_rep, |
4055 | struct vmw_fence_obj **out_fence) | 4068 | struct vmw_fence_obj **out_fence, |
4069 | uint32_t flags) | ||
4056 | { | 4070 | { |
4057 | struct vmw_sw_context *sw_context = &dev_priv->ctx; | 4071 | struct vmw_sw_context *sw_context = &dev_priv->ctx; |
4058 | struct vmw_fence_obj *fence = NULL; | 4072 | struct vmw_fence_obj *fence = NULL; |
@@ -4062,20 +4076,33 @@ int vmw_execbuf_process(struct drm_file *file_priv, | |||
4062 | struct ww_acquire_ctx ticket; | 4076 | struct ww_acquire_ctx ticket; |
4063 | uint32_t handle; | 4077 | uint32_t handle; |
4064 | int ret; | 4078 | int ret; |
4079 | int32_t out_fence_fd = -1; | ||
4080 | struct sync_file *sync_file = NULL; | ||
4081 | |||
4082 | |||
4083 | if (flags & DRM_VMW_EXECBUF_FLAG_EXPORT_FENCE_FD) { | ||
4084 | out_fence_fd = get_unused_fd_flags(O_CLOEXEC); | ||
4085 | if (out_fence_fd < 0) { | ||
4086 | DRM_ERROR("Failed to get a fence file descriptor.\n"); | ||
4087 | return out_fence_fd; | ||
4088 | } | ||
4089 | } | ||
4065 | 4090 | ||
4066 | if (throttle_us) { | 4091 | if (throttle_us) { |
4067 | ret = vmw_wait_lag(dev_priv, &dev_priv->fifo.marker_queue, | 4092 | ret = vmw_wait_lag(dev_priv, &dev_priv->fifo.marker_queue, |
4068 | throttle_us); | 4093 | throttle_us); |
4069 | 4094 | ||
4070 | if (ret) | 4095 | if (ret) |
4071 | return ret; | 4096 | goto out_free_fence_fd; |
4072 | } | 4097 | } |
4073 | 4098 | ||
4074 | kernel_commands = vmw_execbuf_cmdbuf(dev_priv, user_commands, | 4099 | kernel_commands = vmw_execbuf_cmdbuf(dev_priv, user_commands, |
4075 | kernel_commands, command_size, | 4100 | kernel_commands, command_size, |
4076 | &header); | 4101 | &header); |
4077 | if (IS_ERR(kernel_commands)) | 4102 | if (IS_ERR(kernel_commands)) { |
4078 | return PTR_ERR(kernel_commands); | 4103 | ret = PTR_ERR(kernel_commands); |
4104 | goto out_free_fence_fd; | ||
4105 | } | ||
4079 | 4106 | ||
4080 | ret = mutex_lock_interruptible(&dev_priv->cmdbuf_mutex); | 4107 | ret = mutex_lock_interruptible(&dev_priv->cmdbuf_mutex); |
4081 | if (ret) { | 4108 | if (ret) { |
@@ -4211,8 +4238,32 @@ int vmw_execbuf_process(struct drm_file *file_priv, | |||
4211 | __vmw_execbuf_release_pinned_bo(dev_priv, fence); | 4238 | __vmw_execbuf_release_pinned_bo(dev_priv, fence); |
4212 | 4239 | ||
4213 | vmw_clear_validations(sw_context); | 4240 | vmw_clear_validations(sw_context); |
4241 | |||
4242 | /* | ||
4243 | * If anything fails here, give up trying to export the fence | ||
4244 | * and do a sync since the user mode will not be able to sync | ||
4245 | * the fence itself. This ensures we are still functionally | ||
4246 | * correct. | ||
4247 | */ | ||
4248 | if (flags & DRM_VMW_EXECBUF_FLAG_EXPORT_FENCE_FD) { | ||
4249 | |||
4250 | sync_file = sync_file_create(&fence->base); | ||
4251 | if (!sync_file) { | ||
4252 | DRM_ERROR("Unable to create sync file for fence\n"); | ||
4253 | put_unused_fd(out_fence_fd); | ||
4254 | out_fence_fd = -1; | ||
4255 | |||
4256 | (void) vmw_fence_obj_wait(fence, false, false, | ||
4257 | VMW_FENCE_WAIT_TIMEOUT); | ||
4258 | } else { | ||
4259 | /* Link the fence with the FD created earlier */ | ||
4260 | fd_install(out_fence_fd, sync_file->file); | ||
4261 | } | ||
4262 | } | ||
4263 | |||
4214 | vmw_execbuf_copy_fence_user(dev_priv, vmw_fpriv(file_priv), ret, | 4264 | vmw_execbuf_copy_fence_user(dev_priv, vmw_fpriv(file_priv), ret, |
4215 | user_fence_rep, fence, handle); | 4265 | user_fence_rep, fence, handle, |
4266 | out_fence_fd, sync_file); | ||
4216 | 4267 | ||
4217 | /* Don't unreference when handing fence out */ | 4268 | /* Don't unreference when handing fence out */ |
4218 | if (unlikely(out_fence != NULL)) { | 4269 | if (unlikely(out_fence != NULL)) { |
@@ -4263,6 +4314,9 @@ out_unlock: | |||
4263 | out_free_header: | 4314 | out_free_header: |
4264 | if (header) | 4315 | if (header) |
4265 | vmw_cmdbuf_header_free(header); | 4316 | vmw_cmdbuf_header_free(header); |
4317 | out_free_fence_fd: | ||
4318 | if (out_fence_fd >= 0) | ||
4319 | put_unused_fd(out_fence_fd); | ||
4266 | 4320 | ||
4267 | return ret; | 4321 | return ret; |
4268 | } | 4322 | } |
@@ -4479,7 +4533,8 @@ int vmw_execbuf_ioctl(struct drm_device *dev, unsigned long data, | |||
4479 | NULL, arg.command_size, arg.throttle_us, | 4533 | NULL, arg.command_size, arg.throttle_us, |
4480 | arg.context_handle, | 4534 | arg.context_handle, |
4481 | (void __user *)(unsigned long)arg.fence_rep, | 4535 | (void __user *)(unsigned long)arg.fence_rep, |
4482 | NULL); | 4536 | NULL, |
4537 | arg.flags); | ||
4483 | ttm_read_unlock(&dev_priv->reservation_sem); | 4538 | ttm_read_unlock(&dev_priv->reservation_sem); |
4484 | if (unlikely(ret != 0)) | 4539 | if (unlikely(ret != 0)) |
4485 | goto out; | 4540 | goto out; |
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c index 21563ca8ac1e..3bbad22b3748 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c | |||
@@ -1150,7 +1150,7 @@ int vmw_fence_event_ioctl(struct drm_device *dev, void *data, | |||
1150 | } | 1150 | } |
1151 | 1151 | ||
1152 | vmw_execbuf_copy_fence_user(dev_priv, vmw_fp, 0, user_fence_rep, fence, | 1152 | vmw_execbuf_copy_fence_user(dev_priv, vmw_fp, 0, user_fence_rep, fence, |
1153 | handle); | 1153 | handle, -1, NULL); |
1154 | vmw_fence_obj_unreference(&fence); | 1154 | vmw_fence_obj_unreference(&fence); |
1155 | return 0; | 1155 | return 0; |
1156 | out_no_create: | 1156 | out_no_create: |
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c index 36dd7930bf5f..5d50e45ae274 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | |||
@@ -2494,7 +2494,7 @@ void vmw_kms_helper_buffer_finish(struct vmw_private *dev_priv, | |||
2494 | if (file_priv) | 2494 | if (file_priv) |
2495 | vmw_execbuf_copy_fence_user(dev_priv, vmw_fpriv(file_priv), | 2495 | vmw_execbuf_copy_fence_user(dev_priv, vmw_fpriv(file_priv), |
2496 | ret, user_fence_rep, fence, | 2496 | ret, user_fence_rep, fence, |
2497 | handle); | 2497 | handle, -1, NULL); |
2498 | if (out_fence) | 2498 | if (out_fence) |
2499 | *out_fence = fence; | 2499 | *out_fence = fence; |
2500 | else | 2500 | else |