Replace vmwgfx's ad hoc userspace fence tracking with drm_syncobj. They are nearly identical and it is possible to maintain compatibility with the old IOCTLs.
Signed-off-by: Ian Forbes <ian.for...@broadcom.com> --- drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | 3 +- drivers/gpu/drm/vmwgfx/vmwgfx_drv.h | 2 +- drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c | 10 +- drivers/gpu/drm/vmwgfx/vmwgfx_fence.c | 230 ++++++------------------ drivers/gpu/drm/vmwgfx/vmwgfx_fence.h | 3 +- drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 2 +- 6 files changed, 67 insertions(+), 183 deletions(-) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c index bc0342c58b4b..33e5e90ce63d 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c @@ -1582,7 +1582,8 @@ static const struct file_operations vmwgfx_driver_fops = { static const struct drm_driver driver = { .driver_features = - DRIVER_MODESET | DRIVER_RENDER | DRIVER_ATOMIC | DRIVER_GEM | DRIVER_CURSOR_HOTSPOT, + DRIVER_MODESET | DRIVER_RENDER | DRIVER_ATOMIC | + DRIVER_GEM | DRIVER_CURSOR_HOTSPOT | DRIVER_SYNCOBJ, .ioctls = vmw_ioctls, .num_ioctls = ARRAY_SIZE(vmw_ioctls), .master_set = vmw_master_set, diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h index eda5b6f8f4c4..6df5f66aecf7 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h @@ -983,7 +983,7 @@ extern int vmw_execbuf_fence_commands(struct drm_file *file_priv, struct vmw_fence_obj **p_fence, uint32_t *p_handle); extern int vmw_execbuf_copy_fence_user(struct vmw_private *dev_priv, - struct vmw_fpriv *vmw_fp, + struct drm_file *, int ret, struct drm_vmw_fence_rep __user *user_fence_rep, diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c index 819704ac675d..f83c35861bf7 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c @@ -14,6 +14,7 @@ #include <drm/ttm/ttm_bo.h> #include <drm/ttm/ttm_placement.h> +#include <drm/drm_syncobj.h> #include <linux/sync_file.h> #include <linux/hashtable.h> @@ -3859,7 +3860,7 @@ int vmw_execbuf_fence_commands(struct drm_file *file_priv, */ int vmw_execbuf_copy_fence_user(struct vmw_private *dev_priv, - struct vmw_fpriv *vmw_fp, int ret, + struct drm_file *file_priv, int ret, struct drm_vmw_fence_rep __user *user_fence_rep, struct vmw_fence_obj *fence, uint32_t fence_handle, int32_t out_fence_fd) @@ -3894,7 +3895,7 @@ vmw_execbuf_copy_fence_user(struct vmw_private *dev_priv, * handle. */ if (unlikely(ret != 0) && (fence_rep.error == 0)) { - ttm_ref_object_base_unref(vmw_fp->tfile, fence_handle); + drm_syncobj_destroy(file_priv, fence_handle); VMW_DEBUG_USER("Fence copy error. Syncing.\n"); (void) vmw_fence_obj_wait(fence, false, false, VMW_FENCE_WAIT_TIMEOUT); @@ -4236,8 +4237,9 @@ int vmw_execbuf_process(struct drm_file *file_priv, } } - ret = vmw_execbuf_copy_fence_user(dev_priv, vmw_fpriv(file_priv), ret, - user_fence_rep, fence, handle, out_fence_fd); + ret = vmw_execbuf_copy_fence_user(dev_priv, file_priv, ret, + user_fence_rep, fence, handle, + out_fence_fd); if (sync_file) { if (ret) { diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c index c2294abbe753..de81d95268c3 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c @@ -7,6 +7,7 @@ **************************************************************************/ #include "vmwgfx_drv.h" +#include <drm/drm_syncobj.h> #define VMW_FENCE_WRAP (1 << 31) @@ -18,11 +19,6 @@ struct vmw_fence_manager { u64 ctx; }; -struct vmw_user_fence { - struct ttm_base_object base; - struct vmw_fence_obj fence; -}; - /** * struct vmw_event_fence_action - fence callback that delivers a DRM event. * @@ -74,7 +70,7 @@ static void vmw_fence_obj_destroy(struct dma_fence *f) vmw_seqno_waiter_remove(fman->dev_priv); spin_unlock(&fman->lock); } - fence->destroy(fence); + dma_fence_free(f); } static const char *vmw_fence_get_driver_name(struct dma_fence *f) @@ -156,14 +152,12 @@ void vmw_fence_manager_takedown(struct vmw_fence_manager *fman) } static int vmw_fence_obj_init(struct vmw_fence_manager *fman, - struct vmw_fence_obj *fence, u32 seqno, - void (*destroy) (struct vmw_fence_obj *fence)) + struct vmw_fence_obj *fence, u32 seqno) { int ret = 0; dma_fence_init(&fence->base, &vmw_fence_ops, &fman->lock, fman->ctx, seqno); - fence->destroy = destroy; spin_lock(&fman->lock); if (unlikely(fman->fifo_down)) { @@ -239,11 +233,6 @@ int vmw_fence_obj_wait(struct vmw_fence_obj *fence, bool lazy, return ret; } -static void vmw_fence_destroy(struct vmw_fence_obj *fence) -{ - dma_fence_free(&fence->base); -} - int vmw_fence_create(struct vmw_fence_manager *fman, uint32_t seqno, struct vmw_fence_obj **p_fence) @@ -255,7 +244,7 @@ int vmw_fence_create(struct vmw_fence_manager *fman, if (unlikely(!fence)) return -ENOMEM; - ret = vmw_fence_obj_init(fman, fence, seqno, vmw_fence_destroy); + ret = vmw_fence_obj_init(fman, fence, seqno); if (unlikely(ret != 0)) goto out_err_init; @@ -267,77 +256,31 @@ int vmw_fence_create(struct vmw_fence_manager *fman, return ret; } - -static void vmw_user_fence_destroy(struct vmw_fence_obj *fence) -{ - struct vmw_user_fence *ufence = - container_of(fence, struct vmw_user_fence, fence); - - ttm_base_object_kfree(ufence, base); -} - -static void vmw_user_fence_base_release(struct ttm_base_object **p_base) -{ - struct ttm_base_object *base = *p_base; - struct vmw_user_fence *ufence = - container_of(base, struct vmw_user_fence, base); - struct vmw_fence_obj *fence = &ufence->fence; - - *p_base = NULL; - vmw_fence_obj_unreference(&fence); -} - int vmw_user_fence_create(struct drm_file *file_priv, struct vmw_fence_manager *fman, uint32_t seqno, struct vmw_fence_obj **p_fence, uint32_t *p_handle) { - struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile; - struct vmw_user_fence *ufence; + struct drm_syncobj *ufence; struct vmw_fence_obj *tmp; int ret; - ufence = kzalloc(sizeof(*ufence), GFP_KERNEL); - if (unlikely(!ufence)) { - ret = -ENOMEM; - goto out_no_object; - } - - ret = vmw_fence_obj_init(fman, &ufence->fence, seqno, - vmw_user_fence_destroy); - if (unlikely(ret != 0)) { - kfree(ufence); - goto out_no_object; - } - - /* - * The base object holds a reference which is freed in - * vmw_user_fence_base_release. - */ - tmp = vmw_fence_obj_reference(&ufence->fence); - - ret = ttm_base_object_init(tfile, &ufence->base, false, - VMW_RES_FENCE, - &vmw_user_fence_base_release); - + ret = vmw_fence_create(fman, seqno, &tmp); + if (ret != 0) + return ret; - if (unlikely(ret != 0)) { - /* - * Free the base object's reference - */ + ret = drm_syncobj_create(&ufence, 0, &tmp->base); + if (ret != 0) { vmw_fence_obj_unreference(&tmp); - goto out_err; + return ret; } - *p_fence = &ufence->fence; - *p_handle = ufence->base.handle; - - return 0; -out_err: - tmp = &ufence->fence; - vmw_fence_obj_unreference(&tmp); -out_no_object: + ret = drm_syncobj_get_handle(file_priv, ufence, p_handle); + drm_syncobj_put(ufence); + if (ret != 0) + vmw_fence_obj_unreference(&tmp); + *p_fence = tmp; return ret; } @@ -385,51 +328,13 @@ void vmw_fence_fifo_up(struct vmw_fence_manager *fman) spin_unlock(&fman->lock); } - -/** - * vmw_fence_obj_lookup - Look up a user-space fence object - * - * @tfile: A struct ttm_object_file identifying the caller. - * @handle: A handle identifying the fence object. - * @return: A struct vmw_user_fence base ttm object on success or - * an error pointer on failure. - * - * The fence object is looked up and type-checked. The caller needs - * to have opened the fence object first, but since that happens on - * creation and fence objects aren't shareable, that's not an - * issue currently. - */ -static struct ttm_base_object * -vmw_fence_obj_lookup(struct ttm_object_file *tfile, u32 handle) -{ - struct ttm_base_object *base = ttm_base_object_lookup(tfile, handle); - - if (!base) { - pr_err("Invalid fence object handle 0x%08lx.\n", - (unsigned long)handle); - return ERR_PTR(-EINVAL); - } - - if (base->refcount_release != vmw_user_fence_base_release) { - pr_err("Invalid fence object handle 0x%08lx.\n", - (unsigned long)handle); - ttm_base_object_unref(&base); - return ERR_PTR(-EINVAL); - } - - return base; -} - - int vmw_fence_obj_wait_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) { struct drm_vmw_fence_wait_arg *arg = (struct drm_vmw_fence_wait_arg *)data; unsigned long timeout; - struct ttm_base_object *base; struct vmw_fence_obj *fence; - struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile; int ret; uint64_t wait_timeout = ((uint64_t)arg->timeout_us * HZ); @@ -446,11 +351,10 @@ int vmw_fence_obj_wait_ioctl(struct drm_device *dev, void *data, arg->kernel_cookie = jiffies + wait_timeout; } - base = vmw_fence_obj_lookup(tfile, arg->handle); - if (IS_ERR(base)) - return PTR_ERR(base); - - fence = &(container_of(base, struct vmw_user_fence, base)->fence); + ret = drm_syncobj_find_fence(file_priv, arg->handle, 0, 0, + (struct dma_fence **)&fence); + if (ret != 0) + return ret; timeout = jiffies; if (time_after_eq(timeout, (unsigned long)arg->kernel_cookie)) { @@ -464,14 +368,14 @@ int vmw_fence_obj_wait_ioctl(struct drm_device *dev, void *data, ret = vmw_fence_obj_wait(fence, arg->lazy, true, timeout); out: - ttm_base_object_unref(&base); + vmw_fence_obj_unreference(&fence); // from find_fence /* * Optionally unref the fence object. */ if (ret == 0 && (arg->wait_options & DRM_VMW_WAIT_OPTION_UNREF)) - return ttm_ref_object_base_unref(tfile, arg->handle); + ret = drm_syncobj_destroy(file_priv, arg->handle); return ret; } @@ -480,36 +384,33 @@ int vmw_fence_obj_signaled_ioctl(struct drm_device *dev, void *data, { struct drm_vmw_fence_signaled_arg *arg = (struct drm_vmw_fence_signaled_arg *) data; - struct ttm_base_object *base; struct vmw_fence_obj *fence; - struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile; struct vmw_private *dev_priv = vmw_priv(dev); - base = vmw_fence_obj_lookup(tfile, arg->handle); - if (IS_ERR(base)) - return PTR_ERR(base); + int ret = drm_syncobj_find_fence(file_priv, arg->handle, 0, 0, + (struct dma_fence **)&fence); + if (ret != 0) + return ret; - fence = &(container_of(base, struct vmw_user_fence, base)->fence); arg->signaled = vmw_fence_obj_signaled(fence); arg->signaled_flags = arg->flags; arg->passed_seqno = atomic_read_acquire(&dev_priv->last_read_seqno); - ttm_base_object_unref(&base); + vmw_fence_obj_unreference(&fence); // from find_fence return 0; } int vmw_fence_obj_unref_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv) + struct drm_file *file_priv) { struct drm_vmw_fence_arg *arg = (struct drm_vmw_fence_arg *) data; - return ttm_ref_object_base_unref(vmw_fpriv(file_priv)->tfile, - arg->handle); + return drm_syncobj_destroy(file_priv, arg->handle); } /** @@ -660,50 +561,34 @@ int vmw_fence_event_ioctl(struct drm_device *dev, void *data, struct vmw_private *dev_priv = vmw_priv(dev); struct drm_vmw_fence_event_arg *arg = (struct drm_vmw_fence_event_arg *) data; + struct drm_syncobj *ufence = NULL; struct vmw_fence_obj *fence = NULL; - struct vmw_fpriv *vmw_fp = vmw_fpriv(file_priv); - struct ttm_object_file *tfile = vmw_fp->tfile; struct drm_vmw_fence_rep __user *user_fence_rep = - (struct drm_vmw_fence_rep __user *)(unsigned long) - arg->fence_rep; - uint32_t handle; + (struct drm_vmw_fence_rep __user *)(unsigned long)arg->fence_rep; + u32 handle = 0; int ret; /* - * Look up an existing fence object, - * and if user-space wants a new reference, - * add one. + * Look up an existing fence object and if user-space + * wants a new reference add one. */ if (arg->handle) { - struct ttm_base_object *base = - vmw_fence_obj_lookup(tfile, arg->handle); + ufence = drm_syncobj_find(file_priv, arg->handle); + if (!ufence) + return -ENOENT; - if (IS_ERR(base)) - return PTR_ERR(base); - - fence = &(container_of(base, struct vmw_user_fence, - base)->fence); - (void) vmw_fence_obj_reference(fence); + fence = container_of(drm_syncobj_fence_get(ufence), + typeof(*fence), base); if (user_fence_rep != NULL) { - ret = ttm_ref_object_add(vmw_fp->tfile, base, - NULL, false); - if (unlikely(ret != 0)) { - DRM_ERROR("Failed to reference a fence " - "object.\n"); - goto out_no_ref_obj; + ret = drm_syncobj_get_handle(file_priv, ufence, &handle); + if (ret != 0) { + DRM_ERROR("Failed to get a fence handle.\n"); + goto out_err; } - handle = base->handle; } - ttm_base_object_unref(&base); - } - - /* - * Create a new fence object. - */ - if (!fence) { - ret = vmw_execbuf_fence_commands(file_priv, dev_priv, - &fence, + } else { + ret = vmw_execbuf_fence_commands(file_priv, dev_priv, &fence, (user_fence_rep) ? &handle : NULL); if (unlikely(ret != 0)) { @@ -714,24 +599,21 @@ int vmw_fence_event_ioctl(struct drm_device *dev, void *data, BUG_ON(fence == NULL); - ret = vmw_event_fence_action_create(file_priv, fence, - arg->flags, - arg->user_data, - true); - if (unlikely(ret != 0)) { + ret = vmw_event_fence_action_create(file_priv, fence, arg->flags, + arg->user_data, true); + if (ret != 0) { if (ret != -ERESTARTSYS) DRM_ERROR("Failed to attach event to fence.\n"); - goto out_no_create; + if (handle) + drm_syncobj_destroy(file_priv, handle); + goto out_err; } - vmw_execbuf_copy_fence_user(dev_priv, vmw_fp, 0, user_fence_rep, fence, - handle, -1); - vmw_fence_obj_unreference(&fence); - return 0; -out_no_create: - if (user_fence_rep != NULL) - ttm_ref_object_base_unref(tfile, handle); -out_no_ref_obj: + ret = vmw_execbuf_copy_fence_user(dev_priv, file_priv, 0, user_fence_rep, + fence, handle, -1); +out_err: vmw_fence_obj_unreference(&fence); + if (ufence) + drm_syncobj_put(ufence); return ret; } diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.h b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.h index e897cccae1ae..971fea9c9cad 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.h @@ -41,9 +41,8 @@ struct vmw_fence_manager; struct vmw_fence_obj { struct dma_fence base; - bool waiter_added; struct list_head head; - void (*destroy)(struct vmw_fence_obj *fence); + bool waiter_added; }; extern struct vmw_fence_manager * diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c index 05b1c54a070c..468ae4fa7103 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c @@ -1626,7 +1626,7 @@ void vmw_kms_helper_validation_finish(struct vmw_private *dev_priv, file_priv ? &handle : NULL); vmw_validation_done(ctx, fence); if (file_priv) - vmw_execbuf_copy_fence_user(dev_priv, vmw_fpriv(file_priv), + vmw_execbuf_copy_fence_user(dev_priv, file_priv, ret, user_fence_rep, fence, handle, -1); if (out_fence) -- 2.50.0