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

Commit d375e7d5 authored by Ben Skeggs's avatar Ben Skeggs
Browse files

drm/nouveau/fence: minor api changes for an upcoming rework



Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
parent 875ac34a
Loading
Loading
Loading
Loading
+3 −2
Original line number Diff line number Diff line
@@ -35,6 +35,7 @@
#include "nouveau_dma.h"
#include "nouveau_mm.h"
#include "nouveau_vm.h"
#include "nouveau_fence.h"

#include <linux/log2.h>
#include <linux/slab.h>
@@ -478,7 +479,7 @@ nouveau_bo_move_accel_cleanup(struct nouveau_channel *chan,
	struct nouveau_fence *fence = NULL;
	int ret;

	ret = nouveau_fence_new(chan, &fence, true);
	ret = nouveau_fence_new(chan, &fence);
	if (ret)
		return ret;

@@ -1196,7 +1197,7 @@ nouveau_bo_fence_ref(void *sync_obj)
static bool
nouveau_bo_fence_signalled(void *sync_obj, void *sync_arg)
{
	return nouveau_fence_signalled(sync_obj);
	return nouveau_fence_done(sync_obj);
}

static int
+2 −1
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@
#include "nouveau_drm.h"
#include "nouveau_dma.h"
#include "nouveau_ramht.h"
#include "nouveau_fence.h"
#include "nouveau_software.h"

static int
@@ -369,7 +370,7 @@ nouveau_channel_idle(struct nouveau_channel *chan)
	nouveau_fence_update(chan);

	if (chan->fence.sequence != chan->fence.sequence_ack) {
		ret = nouveau_fence_new(chan, &fence, true);
		ret = nouveau_fence_new(chan, &fence);
		if (!ret) {
			ret = nouveau_fence_wait(fence, false, false);
			nouveau_fence_unref(&fence);
+6 −3
Original line number Diff line number Diff line
@@ -35,6 +35,7 @@
#include "nouveau_connector.h"
#include "nouveau_software.h"
#include "nouveau_gpio.h"
#include "nouveau_fence.h"
#include "nv50_display.h"

static void
@@ -465,7 +466,7 @@ nouveau_page_flip_emit(struct nouveau_channel *chan,
	}
	FIRE_RING (chan);

	ret = nouveau_fence_new(chan, pfence, true);
	ret = nouveau_fence_new(chan, pfence);
	if (ret)
		goto fail;

@@ -486,7 +487,7 @@ nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb,
	struct nouveau_bo *old_bo = nouveau_framebuffer(crtc->fb)->nvbo;
	struct nouveau_bo *new_bo = nouveau_framebuffer(fb)->nvbo;
	struct nouveau_page_flip_state *s;
	struct nouveau_channel *chan;
	struct nouveau_channel *chan = NULL;
	struct nouveau_fence *fence;
	int ret;

@@ -509,7 +510,9 @@ nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb,
		  new_bo->bo.offset };

	/* Choose the channel the flip will be handled in */
	chan = nouveau_fence_channel(new_bo->bo.sync_obj);
	fence = new_bo->bo.sync_obj;
	if (fence)
		chan = nouveau_channel_get_unlocked(fence->channel);
	if (!chan)
		chan = nouveau_channel_get_unlocked(dev_priv->channel);
	mutex_lock(&chan->mutex);
+6 −20
Original line number Diff line number Diff line
@@ -1444,26 +1444,12 @@ extern int nouveau_bo_vma_add(struct nouveau_bo *, struct nouveau_vm *,
extern void nouveau_bo_vma_del(struct nouveau_bo *, struct nouveau_vma *);

/* nouveau_fence.c */
struct nouveau_fence;
extern int nouveau_fence_init(struct drm_device *);
extern void nouveau_fence_fini(struct drm_device *);
extern int nouveau_fence_channel_init(struct nouveau_channel *);
extern void nouveau_fence_channel_fini(struct nouveau_channel *);
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(struct nouveau_fence *);
extern int nouveau_fence_wait(struct nouveau_fence *, bool lazy, bool intr);
extern void nouveau_fence_unref(struct nouveau_fence **);
extern struct nouveau_fence *nouveau_fence_ref(struct nouveau_fence *);
extern int nouveau_fence_sync(struct nouveau_fence *, struct nouveau_channel *);

int  nouveau_fence_init(struct drm_device *);
void nouveau_fence_fini(struct drm_device *);
int  nouveau_fence_channel_init(struct nouveau_channel *);
void nouveau_fence_channel_fini(struct nouveau_channel *);
void nouveau_fence_work(struct nouveau_fence *fence,
			void (*work)(void *priv, bool signalled), void *priv);
/* nouveau_gem.c */
extern int nouveau_gem_new(struct drm_device *, int size, int align,
			   uint32_t domain, uint32_t tile_mode,
+85 −130
Original line number Diff line number Diff line
@@ -32,47 +32,13 @@

#include "nouveau_drv.h"
#include "nouveau_ramht.h"
#include "nouveau_fence.h"
#include "nouveau_software.h"
#include "nouveau_dma.h"

#define USE_REFCNT(dev) (nouveau_private(dev)->chipset >= 0x10)
#define USE_SEMA(dev) (nouveau_private(dev)->chipset >= 0x17)

struct nouveau_fence {
	struct nouveau_channel *channel;
	struct kref refcount;
	struct list_head entry;

	uint32_t sequence;
	bool signalled;
	unsigned long timeout;

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

struct nouveau_semaphore {
	struct kref ref;
	struct drm_device *dev;
	struct drm_mm_node *mem;
};

static inline struct nouveau_fence *
nouveau_fence(void *sync_obj)
{
	return (struct nouveau_fence *)sync_obj;
}

static void
nouveau_fence_del(struct kref *ref)
{
	struct nouveau_fence *fence =
		container_of(ref, struct nouveau_fence, refcount);

	nouveau_channel_ref(NULL, &fence->channel);
	kfree(fence);
}

void
nouveau_fence_update(struct nouveau_channel *chan)
{
@@ -94,16 +60,16 @@ nouveau_fence_update(struct nouveau_channel *chan)
		chan->fence.sequence_ack = sequence;
	}

	list_for_each_entry_safe(fence, tmp, &chan->fence.pending, entry) {
	list_for_each_entry_safe(fence, tmp, &chan->fence.pending, head) {
		if (fence->sequence > chan->fence.sequence_ack)
			break;

		fence->signalled = true;
		list_del(&fence->entry);
		fence->channel = NULL;
		list_del(&fence->head);
		if (fence->work)
			fence->work(fence->priv, true);

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

out:
@@ -111,37 +77,8 @@ nouveau_fence_update(struct nouveau_channel *chan)
}

int
nouveau_fence_new(struct nouveau_channel *chan, struct nouveau_fence **pfence,
		  bool emit)
{
	struct nouveau_fence *fence;
	int ret = 0;

	fence = kzalloc(sizeof(*fence), GFP_KERNEL);
	if (!fence)
		return -ENOMEM;
	kref_init(&fence->refcount);
	nouveau_channel_ref(chan, &fence->channel);

	if (emit)
		ret = nouveau_fence_emit(fence);

	if (ret)
		nouveau_fence_unref(&fence);
	*pfence = fence;
	return ret;
}

struct nouveau_channel *
nouveau_fence_channel(struct nouveau_fence *fence)
{
	return fence ? nouveau_channel_get_unlocked(fence->channel) : NULL;
}

int
nouveau_fence_emit(struct nouveau_fence *fence)
nouveau_fence_emit(struct nouveau_fence *fence, struct nouveau_channel *chan)
{
	struct nouveau_channel *chan = fence->channel;
	struct drm_device *dev = chan->dev;
	struct drm_nouveau_private *dev_priv = dev->dev_private;
	int ret;
@@ -158,10 +95,11 @@ nouveau_fence_emit(struct nouveau_fence *fence)
	}

	fence->sequence = ++chan->fence.sequence;
	fence->channel = chan;

	kref_get(&fence->refcount);
	kref_get(&fence->kref);
	spin_lock(&chan->fence.lock);
	list_add_tail(&fence->entry, &chan->fence.pending);
	list_add_tail(&fence->head, &chan->fence.pending);
	spin_unlock(&chan->fence.lock);

	if (USE_REFCNT(dev)) {
@@ -179,50 +117,12 @@ 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(struct nouveau_fence **pfence)
{
	if (*pfence)
		kref_put(&(*pfence)->refcount, nouveau_fence_del);
	*pfence = NULL;
}

struct nouveau_fence *
nouveau_fence_ref(struct nouveau_fence *fence)
{
	kref_get(&fence->refcount);
	return fence;
}

bool
nouveau_fence_signalled(struct nouveau_fence *fence)
nouveau_fence_done(struct nouveau_fence *fence)
{
	struct nouveau_channel *chan = fence->channel;

	if (fence->signalled)
		return true;

	nouveau_fence_update(chan);
	return fence->signalled;
	if (fence->channel)
		nouveau_fence_update(fence->channel);
	return !fence->channel;
}

int
@@ -232,8 +132,8 @@ nouveau_fence_wait(struct nouveau_fence *fence, bool lazy, bool intr)
	ktime_t t;
	int ret = 0;

	while (!nouveau_fence_signalled(fence)) {
		if (time_after_eq(jiffies, fence->timeout)) {
	while (!nouveau_fence_done(fence)) {
		if (fence->timeout && time_after_eq(jiffies, fence->timeout)) {
			ret = -EBUSY;
			break;
		}
@@ -255,10 +155,71 @@ nouveau_fence_wait(struct nouveau_fence *fence, bool lazy, bool intr)
	}

	__set_current_state(TASK_RUNNING);
	return ret;
}

static void
nouveau_fence_del(struct kref *kref)
{
	struct nouveau_fence *fence = container_of(kref, typeof(*fence), kref);
	kfree(fence);
}

void
nouveau_fence_unref(struct nouveau_fence **pfence)
{
	if (*pfence)
		kref_put(&(*pfence)->kref, nouveau_fence_del);
	*pfence = NULL;
}

struct nouveau_fence *
nouveau_fence_ref(struct nouveau_fence *fence)
{
	kref_get(&fence->kref);
	return fence;
}

int
nouveau_fence_new(struct nouveau_channel *chan, struct nouveau_fence **pfence)
{
	struct nouveau_fence *fence;
	int ret = 0;

	fence = kzalloc(sizeof(*fence), GFP_KERNEL);
	if (!fence)
		return -ENOMEM;
	kref_init(&fence->kref);

	if (chan) {
		ret = nouveau_fence_emit(fence, chan);
		if (ret)
			nouveau_fence_unref(&fence);
	}

	*pfence = fence;
	return ret;
}

struct nouveau_semaphore {
	struct kref ref;
	struct drm_device *dev;
	struct drm_mm_node *mem;
};

void
nouveau_fence_work(struct nouveau_fence *fence,
		   void (*work)(void *priv, bool signalled),
		   void *priv)
{
	if (!fence->channel) {
		work(priv, true);
	} else {
		fence->work = work;
		fence->priv = priv;
	}
}

static struct nouveau_semaphore *
semaphore_alloc(struct drm_device *dev)
{
@@ -367,7 +328,7 @@ semaphore_acquire(struct nouveau_channel *chan, struct nouveau_semaphore *sema)
	}

	/* Delay semaphore destruction until its work is done */
	ret = nouveau_fence_new(chan, &fence, true);
	ret = nouveau_fence_new(chan, &fence);
	if (ret)
		return ret;

@@ -421,7 +382,7 @@ semaphore_release(struct nouveau_channel *chan, struct nouveau_semaphore *sema)
	}

	/* Delay semaphore destruction until its work is done */
	ret = nouveau_fence_new(chan, &fence, true);
	ret = nouveau_fence_new(chan, &fence);
	if (ret)
		return ret;

@@ -435,13 +396,13 @@ int
nouveau_fence_sync(struct nouveau_fence *fence,
		   struct nouveau_channel *wchan)
{
	struct nouveau_channel *chan = nouveau_fence_channel(fence);
	struct nouveau_channel *chan;
	struct drm_device *dev = wchan->dev;
	struct nouveau_semaphore *sema;
	int ret = 0;

	if (likely(!chan || chan == wchan ||
		   nouveau_fence_signalled(fence)))
	chan = fence ? nouveau_channel_get_unlocked(fence->channel) : NULL;
	if (likely(!chan || chan == wchan || nouveau_fence_done(fence)))
		goto out;

	sema = semaphore_alloc(dev);
@@ -479,12 +440,6 @@ nouveau_fence_sync(struct nouveau_fence *fence,
	return ret;
}

int
__nouveau_fence_flush(void *sync_obj, void *sync_arg)
{
	return 0;
}

int
nouveau_fence_channel_init(struct nouveau_channel *chan)
{
@@ -538,14 +493,14 @@ nouveau_fence_channel_fini(struct nouveau_channel *chan)
	struct nouveau_fence *tmp, *fence;

	spin_lock(&chan->fence.lock);
	list_for_each_entry_safe(fence, tmp, &chan->fence.pending, entry) {
		fence->signalled = true;
		list_del(&fence->entry);
	list_for_each_entry_safe(fence, tmp, &chan->fence.pending, head) {
		fence->channel = NULL;
		list_del(&fence->head);

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

		kref_put(&fence->refcount, nouveau_fence_del);
		kref_put(&fence->kref, nouveau_fence_del);
	}
	spin_unlock(&chan->fence.lock);

Loading