[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