Commit 67059b9f authored by Ben Skeggs's avatar Ben Skeggs
Browse files

drm/nouveau/fifo: add chan start()/stop()



- nvkm_chan_error() built on top, stops channel and sends 'killed' event
- removes an odd double-bashing of channel enable regs on kepler and up
- pokes doorbell on turing and up, after enabling channel

Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
Reviewed-by: default avatarLyude Paul <lyude@redhat.com>
parent 62742b5e
Loading
Loading
Loading
Loading
+4 −3
Original line number Diff line number Diff line
@@ -20,6 +20,10 @@ struct nvkm_chan {

	union { int id; int chid; }; /*FIXME: remove later */

	spinlock_t lock;
	atomic_t blocked;
	atomic_t errored;

	struct list_head cctxs;

	struct nvkm_fifo *fifo;
@@ -62,9 +66,6 @@ struct nvkm_fifo {
	struct list_head chan;
	spinlock_t lock;
	struct mutex mutex;

#define NVKM_FIFO_EVENT_KILLED         BIT(0)
	struct nvkm_event kevent; /* channel killed */
};

void nvkm_fifo_fault(struct nvkm_fifo *, struct nvkm_fault_data *);
+1 −12
Original line number Diff line number Diff line
@@ -62,16 +62,6 @@ nvkm_fifo_fault(struct nvkm_fifo *fifo, struct nvkm_fault_data *info)
	return fifo->func->mmu_fault->recover(fifo, info);
}

void
nvkm_fifo_kevent(struct nvkm_fifo *fifo, int chid)
{
	nvkm_event_ntfy(&fifo->kevent, chid, NVKM_FIFO_EVENT_KILLED);
}

static const struct nvkm_event_func
nvkm_fifo_kevent_func = {
};

static int
nvkm_fifo_class_new(struct nvkm_device *device, const struct nvkm_oclass *oclass,
		    void *argv, u32 argc, struct nvkm_object **pobject)
@@ -293,7 +283,6 @@ nvkm_fifo_dtor(struct nvkm_engine *engine)

	if (fifo->func->dtor)
		data = fifo->func->dtor(fifo);
	nvkm_event_fini(&fifo->kevent);
	nvkm_event_fini(&fifo->nonstall.event);
	mutex_destroy(&fifo->mutex);
	return data;
@@ -343,5 +332,5 @@ nvkm_fifo_ctor(const struct nvkm_fifo_func *func, struct nvkm_device *device,
			return ret;
	}

	return nvkm_event_init(&nvkm_fifo_kevent_func, &fifo->engine.subdev, 1, nr, &fifo->kevent);
	return 0;
}
+52 −21
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@
#include "chan.h"
#include "chid.h"
#include "cgrp.h"
#include "chid.h"
#include "runl.h"
#include "priv.h"

@@ -219,6 +220,8 @@ nvkm_chan_cctx_bind(struct nvkm_chan *chan, struct nvkm_oproxy *oproxy, struct n
	 */
	if (cgrp->hw)
		nvkm_runl_block(runl);
	else
		nvkm_chan_block(chan);

	/* Update context pointer. */
	if (cctx)
@@ -229,6 +232,8 @@ nvkm_chan_cctx_bind(struct nvkm_chan *chan, struct nvkm_oproxy *oproxy, struct n
	/* Resume normal operation. */
	if (cgrp->hw)
		nvkm_runl_allow(runl);
	else
		nvkm_chan_allow(chan);
}

void
@@ -295,23 +300,6 @@ nvkm_chan_cctx_get(struct nvkm_chan *chan, struct nvkm_engn *engn, struct nvkm_c
	return ret;
}

static int
nvkm_fifo_chan_uevent(struct nvkm_object *object, void *argv, u32 argc, struct nvkm_uevent *uevent)
{
	struct nvkm_fifo_chan *chan = nvkm_fifo_chan(object);
	union nvif_chan_event_args *args = argv;

	switch (args->v0.type) {
	case NVIF_CHAN_EVENT_V0_KILLED:
		return nvkm_uevent_add(uevent, &chan->fifo->kevent, chan->chid,
				       NVKM_FIFO_EVENT_KILLED, NULL);
	default:
		break;
	}

	return -ENOSYS;
}

static int
nvkm_fifo_chan_map(struct nvkm_object *object, void *argv, u32 argc,
		   enum nvkm_object_map *type, u64 *addr, u64 *size)
@@ -327,6 +315,7 @@ static int
nvkm_fifo_chan_fini(struct nvkm_object *object, bool suspend)
{
	struct nvkm_fifo_chan *chan = nvkm_fifo_chan(object);
	if (chan->func->fini)
		chan->func->fini(chan);
	return 0;
}
@@ -335,10 +324,51 @@ static int
nvkm_fifo_chan_init(struct nvkm_object *object)
{
	struct nvkm_fifo_chan *chan = nvkm_fifo_chan(object);
	if (chan->func->init)
		chan->func->init(chan);
	return 0;
}

static void
nvkm_chan_block_locked(struct nvkm_chan *chan)
{
	CHAN_TRACE(chan, "block %d", atomic_read(&chan->blocked));
	if (atomic_inc_return(&chan->blocked) == 1)
		chan->func->stop(chan);
}

void
nvkm_chan_error(struct nvkm_chan *chan, bool preempt)
{
	unsigned long flags;

	spin_lock_irqsave(&chan->lock, flags);
	if (atomic_inc_return(&chan->errored) == 1) {
		CHAN_ERROR(chan, "errored - disabling channel");
		nvkm_chan_block_locked(chan);
		nvkm_event_ntfy(&chan->cgrp->runl->chid->event, chan->id, NVKM_CHAN_EVENT_ERRORED);
	}
	spin_unlock_irqrestore(&chan->lock, flags);
}

void
nvkm_chan_block(struct nvkm_chan *chan)
{
	spin_lock_irq(&chan->lock);
	nvkm_chan_block_locked(chan);
	spin_unlock_irq(&chan->lock);
}

void
nvkm_chan_allow(struct nvkm_chan *chan)
{
	spin_lock_irq(&chan->lock);
	CHAN_TRACE(chan, "allow %d", atomic_read(&chan->blocked));
	if (atomic_dec_and_test(&chan->blocked))
		chan->func->start(chan);
	spin_unlock_irq(&chan->lock);
}

void
nvkm_chan_del(struct nvkm_chan **pchan)
{
@@ -437,7 +467,6 @@ nvkm_fifo_chan_func = {
	.init = nvkm_fifo_chan_init,
	.fini = nvkm_fifo_chan_fini,
	.map = nvkm_fifo_chan_map,
	.uevent = nvkm_fifo_chan_uevent,
};

int
@@ -481,10 +510,12 @@ nvkm_fifo_chan_ctor(const struct nvkm_fifo_chan_func *fn,
	func->engine_fini = fn->engine_fini;
	func->object_ctor = fn->object_ctor;
	func->object_dtor = fn->object_dtor;
	func->submit_token = fn->submit_token;

	chan->func = func;
	chan->id = -1;
	spin_lock_init(&chan->lock);
	atomic_set(&chan->blocked, 1);
	atomic_set(&chan->errored, 0);

	nvkm_object_ctor(&nvkm_fifo_chan_func, oclass, &chan->object);
	chan->fifo = fifo;
+6 −1
Original line number Diff line number Diff line
@@ -18,6 +18,9 @@ struct nvkm_cctx {
struct nvkm_chan_func {
	void (*bind)(struct nvkm_chan *);
	void (*unbind)(struct nvkm_chan *);
	void (*start)(struct nvkm_chan *);
	void (*stop)(struct nvkm_chan *);
	u32 (*doorbell_handle)(struct nvkm_chan *);

	void *(*dtor)(struct nvkm_fifo_chan *);
	void (*init)(struct nvkm_fifo_chan *);
@@ -30,7 +33,6 @@ struct nvkm_chan_func {
			    bool suspend);
	int  (*object_ctor)(struct nvkm_fifo_chan *, struct nvkm_object *);
	void (*object_dtor)(struct nvkm_fifo_chan *, int);
	u32 (*submit_token)(struct nvkm_fifo_chan *);
};

int nvkm_fifo_chan_ctor(const struct nvkm_fifo_chan_func *, struct nvkm_fifo *,
@@ -38,6 +40,9 @@ int nvkm_fifo_chan_ctor(const struct nvkm_fifo_chan_func *, struct nvkm_fifo *,
			u32 engm, int bar, u32 base, u32 user,
			const struct nvkm_oclass *, struct nvkm_fifo_chan *);
void nvkm_chan_del(struct nvkm_chan **);
void nvkm_chan_allow(struct nvkm_chan *);
void nvkm_chan_block(struct nvkm_chan *);
void nvkm_chan_error(struct nvkm_chan *, bool preempt);
int nvkm_chan_cctx_get(struct nvkm_chan *, struct nvkm_engn *, struct nvkm_cctx **,
		       struct nvkm_client * /*TODO: remove need for this */);
void nvkm_chan_cctx_put(struct nvkm_chan *, struct nvkm_cctx **);
+0 −2
Original line number Diff line number Diff line
@@ -18,8 +18,6 @@ struct nv04_fifo_chan {

extern const struct nvkm_fifo_chan_func nv04_fifo_dma_func;
void *nv04_fifo_dma_dtor(struct nvkm_fifo_chan *);
void nv04_fifo_dma_init(struct nvkm_fifo_chan *);
void nv04_fifo_dma_fini(struct nvkm_fifo_chan *);
void nv04_fifo_dma_object_dtor(struct nvkm_fifo_chan *, int);

extern const struct nvkm_fifo_chan_oclass nv04_fifo_dma_oclass;
Loading