[PATCH 2/2] drm/vmwgfx: Implement DRIVER_SYNCOBJ

Ian Forbes ian.forbes at broadcom.com
Thu Jun 26 20:11:53 UTC 2025


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.forbes at 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



More information about the dri-devel mailing list