diff options
Diffstat (limited to 'drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c')
-rw-r--r-- | drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c | 69 |
1 files changed, 62 insertions, 7 deletions
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; |