Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8ac3891b authored by Francisco Jerez's avatar Francisco Jerez Committed by Ben Skeggs
Browse files

drm/nouveau: Provide a means to have arbitrary work run on fence completion.

parent 2730723b
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -1243,6 +1243,9 @@ extern void nouveau_fence_update(struct nouveau_channel *);
extern int nouveau_fence_new(struct nouveau_channel *, struct nouveau_fence **,
			     bool emit);
extern int nouveau_fence_emit(struct nouveau_fence *);
extern void nouveau_fence_work(struct nouveau_fence *fence,
			       void (*work)(void *priv, bool signalled),
			       void *priv);
struct nouveau_channel *nouveau_fence_channel(struct nouveau_fence *);
extern bool nouveau_fence_signalled(void *obj, void *arg);
extern int nouveau_fence_wait(void *obj, void *arg, bool lazy, bool intr);
+30 −0
Original line number Diff line number Diff line
@@ -39,6 +39,9 @@ struct nouveau_fence {

	uint32_t sequence;
	bool signalled;

	void (*work)(void *priv, bool signalled);
	void *priv;
};

static inline struct nouveau_fence *
@@ -78,6 +81,10 @@ nouveau_fence_update(struct nouveau_channel *chan)
		sequence = fence->sequence;
		fence->signalled = true;
		list_del(&fence->entry);

		if (unlikely(fence->work))
			fence->work(fence->priv, true);

		kref_put(&fence->refcount, nouveau_fence_del);

		if (sequence == chan->fence.sequence_ack)
@@ -147,6 +154,25 @@ nouveau_fence_emit(struct nouveau_fence *fence)
	return 0;
}

void
nouveau_fence_work(struct nouveau_fence *fence,
		   void (*work)(void *priv, bool signalled),
		   void *priv)
{
	BUG_ON(fence->work);

	spin_lock(&fence->channel->fence.lock);

	if (fence->signalled) {
		work(priv, true);
	} else {
		fence->work = work;
		fence->priv = priv;
	}

	spin_unlock(&fence->channel->fence.lock);
}

void
nouveau_fence_unref(void **sync_obj)
{
@@ -268,6 +294,10 @@ nouveau_fence_channel_fini(struct nouveau_channel *chan)
	list_for_each_entry_safe(fence, tmp, &chan->fence.pending, entry) {
		fence->signalled = true;
		list_del(&fence->entry);

		if (unlikely(fence->work))
			fence->work(fence->priv, false);

		kref_put(&fence->refcount, nouveau_fence_del);
	}
}