aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSinclair Yeh <syeh@vmware.com>2017-07-05 04:49:32 -0400
committerSinclair Yeh <syeh@vmware.com>2017-08-28 11:51:46 -0400
commitc906965dee22d5e95d0651759ba107b420212a9f (patch)
treeb0c5a08234cebcdede8f2ddf95045331da112953
parent585851164660e8dff961178a9533857b21d63975 (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.h8
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c69
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_fence.c2
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_kms.c2
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);
830extern void __vmw_execbuf_release_pinned_bo(struct vmw_private *dev_priv, 832extern void __vmw_execbuf_release_pinned_bo(struct vmw_private *dev_priv,
831 struct vmw_fence_obj *fence); 833 struct vmw_fence_obj *fence);
832extern void vmw_execbuf_release_pinned_bo(struct vmw_private *dev_priv); 834extern 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);
845extern int vmw_validate_single_buffer(struct vmw_private *dev_priv, 849extern 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:
4263out_free_header: 4314out_free_header:
4264 if (header) 4315 if (header)
4265 vmw_cmdbuf_header_free(header); 4316 vmw_cmdbuf_header_free(header);
4317out_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;
1156out_no_create: 1156out_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