Commit db6a94b2 authored by Ian Forbes's avatar Ian Forbes Committed by Zack Rusin
Browse files

drm/vmwgfx: Implement dma_fence_ops properly



vmwgfx's fencing predates dma_fence and as a result dma_fence_ops was never
properly implemented, especially with respect to enabling signaling.

Because of this dma_fence callbacks don't work properly. This change
implements enable_signaling properly so that dma_fence callbacks now
work as expected.

It also removes vmwgfx's custom implementation of fence callbacks
and removes vmwgfx's custom dma_fence_ops::wait function which is no
longer necessary now that enable_signaling works.

Signed-off-by: default avatarIan Forbes <ian.forbes@broadcom.com>
Signed-off-by: default avatarZack Rusin <zack.rusin@broadcom.com>
Link: https://lore.kernel.org/r/20250530183510.733175-2-ian.forbes@broadcom.com
parent c82f55f4
Loading
Loading
Loading
Loading
+8 −8
Original line number Diff line number Diff line
@@ -1006,13 +1006,13 @@ extern int vmw_fallback_wait(struct vmw_private *dev_priv,
			     uint32_t seqno,
			     bool interruptible,
			     unsigned long timeout);
extern void vmw_seqno_waiter_add(struct vmw_private *dev_priv);
extern void vmw_seqno_waiter_remove(struct vmw_private *dev_priv);
extern void vmw_goal_waiter_add(struct vmw_private *dev_priv);
extern void vmw_goal_waiter_remove(struct vmw_private *dev_priv);
extern void vmw_generic_waiter_add(struct vmw_private *dev_priv, u32 flag,
bool vmw_seqno_waiter_add(struct vmw_private *dev_priv);
bool vmw_seqno_waiter_remove(struct vmw_private *dev_priv);
bool vmw_goal_waiter_add(struct vmw_private *dev_priv);
bool vmw_goal_waiter_remove(struct vmw_private *dev_priv);
bool vmw_generic_waiter_add(struct vmw_private *dev_priv, u32 flag,
			    int *waiter_count);
extern void vmw_generic_waiter_remove(struct vmw_private *dev_priv,
bool vmw_generic_waiter_remove(struct vmw_private *dev_priv,
			       u32 flag, int *waiter_count);

/**
+0 −26
Original line number Diff line number Diff line
@@ -4067,23 +4067,6 @@ static int vmw_execbuf_tie_context(struct vmw_private *dev_priv,
	return 0;
}

/*
 * DMA fence callback to remove a seqno_waiter
 */
struct seqno_waiter_rm_context {
	struct dma_fence_cb base;
	struct vmw_private *dev_priv;
};

static void seqno_waiter_rm_cb(struct dma_fence *f, struct dma_fence_cb *cb)
{
	struct seqno_waiter_rm_context *ctx =
		container_of(cb, struct seqno_waiter_rm_context, base);

	vmw_seqno_waiter_remove(ctx->dev_priv);
	kfree(ctx);
}

int vmw_execbuf_process(struct drm_file *file_priv,
			struct vmw_private *dev_priv,
			void __user *user_commands, void *kernel_commands,
@@ -4264,15 +4247,6 @@ int vmw_execbuf_process(struct drm_file *file_priv,
		} else {
			/* Link the fence with the FD created earlier */
			fd_install(out_fence_fd, sync_file->file);
			struct seqno_waiter_rm_context *ctx =
				kmalloc(sizeof(*ctx), GFP_KERNEL);
			ctx->dev_priv = dev_priv;
			vmw_seqno_waiter_add(dev_priv);
			if (dma_fence_add_callback(&fence->base, &ctx->base,
						   seqno_waiter_rm_cb) < 0) {
				vmw_seqno_waiter_remove(dev_priv);
				kfree(ctx);
			}
		}
	}

+62 −430

File changed.

Preview size limit exceeded, changes collapsed.

+1 −18
Original line number Diff line number Diff line
@@ -39,27 +39,10 @@ struct drm_pending_event;
struct vmw_private;
struct vmw_fence_manager;

/**
 *
 *
 */
enum vmw_action_type {
	VMW_ACTION_EVENT = 0,
	VMW_ACTION_MAX
};

struct vmw_fence_action {
	struct list_head head;
	enum vmw_action_type type;
	void (*seq_passed) (struct vmw_fence_action *action);
	void (*cleanup) (struct vmw_fence_action *action);
};

struct vmw_fence_obj {
	struct dma_fence base;

	bool   waiter_added;
	struct list_head head;
	struct list_head seq_passed_actions;
	void (*destroy)(struct vmw_fence_obj *fence);
};

+26 −18
Original line number Diff line number Diff line
@@ -230,50 +230,58 @@ int vmw_fallback_wait(struct vmw_private *dev_priv,
	return ret;
}

void vmw_generic_waiter_add(struct vmw_private *dev_priv,
bool vmw_generic_waiter_add(struct vmw_private *dev_priv,
			    u32 flag, int *waiter_count)
{
	spin_lock_bh(&dev_priv->waiter_lock);
	bool hw_programmed = false;

	spin_lock(&dev_priv->waiter_lock);
	if ((*waiter_count)++ == 0) {
		vmw_irq_status_write(dev_priv, flag);
		dev_priv->irq_mask |= flag;
		vmw_write(dev_priv, SVGA_REG_IRQMASK, dev_priv->irq_mask);
		hw_programmed = true;
	}
	spin_unlock_bh(&dev_priv->waiter_lock);
	spin_unlock(&dev_priv->waiter_lock);
	return hw_programmed;
}

void vmw_generic_waiter_remove(struct vmw_private *dev_priv,
bool vmw_generic_waiter_remove(struct vmw_private *dev_priv,
			       u32 flag, int *waiter_count)
{
	spin_lock_bh(&dev_priv->waiter_lock);
	bool hw_programmed = false;

	spin_lock(&dev_priv->waiter_lock);
	if (--(*waiter_count) == 0) {
		dev_priv->irq_mask &= ~flag;
		vmw_write(dev_priv, SVGA_REG_IRQMASK, dev_priv->irq_mask);
		hw_programmed = true;
	}
	spin_unlock_bh(&dev_priv->waiter_lock);
	spin_unlock(&dev_priv->waiter_lock);
	return hw_programmed;
}

void vmw_seqno_waiter_add(struct vmw_private *dev_priv)
bool vmw_seqno_waiter_add(struct vmw_private *dev_priv)
{
	vmw_generic_waiter_add(dev_priv, SVGA_IRQFLAG_ANY_FENCE,
	return vmw_generic_waiter_add(dev_priv, SVGA_IRQFLAG_ANY_FENCE,
					&dev_priv->fence_queue_waiters);
}

void vmw_seqno_waiter_remove(struct vmw_private *dev_priv)
bool vmw_seqno_waiter_remove(struct vmw_private *dev_priv)
{
	vmw_generic_waiter_remove(dev_priv, SVGA_IRQFLAG_ANY_FENCE,
	return vmw_generic_waiter_remove(dev_priv, SVGA_IRQFLAG_ANY_FENCE,
					&dev_priv->fence_queue_waiters);
}

void vmw_goal_waiter_add(struct vmw_private *dev_priv)
bool vmw_goal_waiter_add(struct vmw_private *dev_priv)
{
	vmw_generic_waiter_add(dev_priv, vmw_irqflag_fence_goal(dev_priv),
	return vmw_generic_waiter_add(dev_priv, vmw_irqflag_fence_goal(dev_priv),
					&dev_priv->goal_queue_waiters);
}

void vmw_goal_waiter_remove(struct vmw_private *dev_priv)
bool vmw_goal_waiter_remove(struct vmw_private *dev_priv)
{
	vmw_generic_waiter_remove(dev_priv, vmw_irqflag_fence_goal(dev_priv),
	return vmw_generic_waiter_remove(dev_priv, vmw_irqflag_fence_goal(dev_priv),
					&dev_priv->goal_queue_waiters);
}