Commit 8ab849d6 authored by Ben Skeggs's avatar Ben Skeggs
Browse files

drm/nouveau/fifo: add new engine context handling



Builds on the context tracking that was added earlier.

- marks engine context PTEs as 'priv' where possible

Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
Reviewed-by: default avatarLyude Paul <lyude@redhat.com>
parent 3647c53b
Loading
Loading
Loading
Loading
+0 −9
Original line number Diff line number Diff line
@@ -8,11 +8,6 @@ struct nvkm_fault_data;

#define NVKM_FIFO_ENGN_NR 16

struct nvkm_fifo_engn {
	struct nvkm_object *object;
	int refcount;
};

struct nvkm_chan {
	const struct nvkm_chan_func *func;
	char name[64];
@@ -41,13 +36,10 @@ struct nvkm_chan {

	struct list_head cctxs;

	struct nvkm_fifo *fifo;
	struct nvkm_object object;

	struct list_head head;
	struct nvkm_gpuobj *push;

	struct nvkm_fifo_engn engn[NVKM_FIFO_ENGN_NR];
};

struct nvkm_chan *nvkm_chan_get_chid(struct nvkm_engine *, int id, unsigned long *irqflags);
@@ -78,7 +70,6 @@ struct nvkm_fifo {
		struct nvkm_vma *bar1;
	} userd;

	int nr;
	spinlock_t lock;
	struct mutex mutex;
};
+1 −4
Original line number Diff line number Diff line
@@ -318,7 +318,7 @@ int
nvkm_fifo_ctor(const struct nvkm_fifo_func *func, struct nvkm_device *device,
	       enum nvkm_subdev_type type, int inst, struct nvkm_fifo *fifo)
{
	int ret, nr;
	int ret;

	fifo->func = func;
	INIT_LIST_HEAD(&fifo->runqs);
@@ -335,9 +335,6 @@ nvkm_fifo_ctor(const struct nvkm_fifo_func *func, struct nvkm_device *device,
	if (ret)
		return ret;

	nr = func->chid_nr(fifo);
	fifo->nr = nr;

	if (func->nonstall) {
		ret = nvkm_event_init(func->nonstall, &fifo->engine.subdev, 1, 1,
				      &fifo->nonstall.event);
+35 −0
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@
#include "runl.h"
#include "priv.h"

#include <core/gpuobj.h>
#include <subdev/mmu.h>

static void
@@ -37,6 +38,7 @@ nvkm_cgrp_ectx_put(struct nvkm_cgrp *cgrp, struct nvkm_ectx **pectx)

		if (refcount_dec_and_test(&ectx->refs)) {
			CGRP_TRACE(cgrp, "dtor ectx %d[%s]", engn->id, engn->engine->subdev.name);
			nvkm_object_del(&ectx->object);
			list_del(&ectx->head);
			kfree(ectx);
		}
@@ -49,6 +51,11 @@ static int
nvkm_cgrp_ectx_get(struct nvkm_cgrp *cgrp, struct nvkm_engn *engn, struct nvkm_ectx **pectx,
		   struct nvkm_chan *chan, struct nvkm_client *client)
{
	struct nvkm_engine *engine = engn->engine;
	struct nvkm_oclass cclass = {
		.client = client,
		.engine = engine,
	};
	struct nvkm_ectx *ectx;
	int ret = 0;

@@ -67,7 +74,18 @@ nvkm_cgrp_ectx_get(struct nvkm_cgrp *cgrp, struct nvkm_engn *engn, struct nvkm_e

	ectx->engn = engn;
	refcount_set(&ectx->refs, 1);
	refcount_set(&ectx->uses, 0);
	list_add_tail(&ectx->head, &cgrp->ectxs);

	/* Allocate the HW structures. */
	if (engine->func->fifo.cclass)
		ret = engine->func->fifo.cclass(chan, &cclass, &ectx->object);
	else if (engine->func->cclass)
		ret = nvkm_object_new_(engine->func->cclass, &cclass, NULL, 0, &ectx->object);

	if (ret)
		nvkm_cgrp_ectx_put(cgrp, pectx);

	return ret;
}

@@ -81,6 +99,8 @@ nvkm_cgrp_vctx_put(struct nvkm_cgrp *cgrp, struct nvkm_vctx **pvctx)

		if (refcount_dec_and_test(&vctx->refs)) {
			CGRP_TRACE(cgrp, "dtor vctx %d[%s]", engn->id, engn->engine->subdev.name);
			nvkm_vmm_put(vctx->vmm, &vctx->vma);
			nvkm_gpuobj_del(&vctx->inst);

			nvkm_cgrp_ectx_put(cgrp, &vctx->ectx);
			if (vctx->vmm) {
@@ -130,6 +150,21 @@ nvkm_cgrp_vctx_get(struct nvkm_cgrp *cgrp, struct nvkm_engn *engn, struct nvkm_c
	vctx->vmm = nvkm_vmm_ref(chan->vmm);
	refcount_set(&vctx->refs, 1);
	list_add_tail(&vctx->head, &cgrp->vctxs);

	/* MMU on some GPUs needs to know engine usage for TLB invalidation. */
	if (vctx->vmm)
		atomic_inc(&vctx->vmm->engref[engn->engine->subdev.type]);

	/* Allocate the HW structures. */
	if (engn->func->bind) {
		ret = nvkm_object_bind(vctx->ectx->object, NULL, 0, &vctx->inst);
		if (ret == 0 && engn->func->ctor)
			ret = engn->func->ctor(engn, vctx);
	}

	if (ret)
		nvkm_cgrp_vctx_put(cgrp, pvctx);

	return ret;
}

+6 −0
Original line number Diff line number Diff line
@@ -10,12 +10,18 @@ struct nvkm_vctx {
	struct nvkm_vmm *vmm;
	refcount_t refs;

	struct nvkm_gpuobj *inst;
	struct nvkm_vma *vma;

	struct list_head head;
};

struct nvkm_ectx {
	struct nvkm_engn *engn;
	refcount_t refs;
	refcount_t uses;

	struct nvkm_object *object;

	struct list_head head;
};
+10 −118
Original line number Diff line number Diff line
@@ -28,7 +28,6 @@
#include "runl.h"
#include "priv.h"

#include <core/client.h>
#include <core/oproxy.h>
#include <core/ramht.h>
#include <subdev/mmu.h>
@@ -46,94 +45,15 @@ struct nvkm_fifo_chan_object {
	int hash;
};

static struct nvkm_fifo_engn *
nvkm_fifo_chan_engn(struct nvkm_fifo_chan *chan, struct nvkm_engine *engine)
{
	int engi = chan->fifo->func->engine_id(chan->fifo, engine);
	if (engi >= 0)
		return &chan->engn[engi];
	return NULL;
}

static int
nvkm_fifo_chan_child_fini(struct nvkm_oproxy *base, bool suspend)
{
	struct nvkm_fifo_chan_object *object =
		container_of(base, typeof(*object), oproxy);
	struct nvkm_engine *engine  = object->oproxy.object->engine;
	struct nvkm_fifo_chan *chan = object->chan;
	struct nvkm_fifo_engn *engn = nvkm_fifo_chan_engn(chan, engine);
	const char *name = engine->subdev.name;
	int ret = 0;

	if (chan->func->engine_fini) {
		ret = chan->func->engine_fini(chan, engine, suspend);
		if (ret) {
			nvif_error(&chan->object,
				   "detach %s failed, %d\n", name, ret);
			return ret;
		}
	}

	if (engn->object) {
		ret = nvkm_object_fini(engn->object, suspend);
		if (ret && suspend)
			return ret;
	}

	nvif_trace(&chan->object, "detached %s\n", name);
	return ret;
}

static int
nvkm_fifo_chan_child_init(struct nvkm_oproxy *base)
{
	struct nvkm_fifo_chan_object *object =
		container_of(base, typeof(*object), oproxy);
	struct nvkm_engine *engine  = object->oproxy.object->engine;
	struct nvkm_fifo_chan *chan = object->chan;
	struct nvkm_fifo_engn *engn = nvkm_fifo_chan_engn(chan, engine);
	const char *name = engine->subdev.name;
	int ret;

	if (engn->object) {
		ret = nvkm_object_init(engn->object);
		if (ret)
			return ret;
	}

	if (chan->func->engine_init) {
		ret = chan->func->engine_init(chan, engine);
		if (ret) {
			nvif_error(&chan->object,
				   "attach %s failed, %d\n", name, ret);
			return ret;
		}
	}

	nvif_trace(&chan->object, "attached %s\n", name);
	return 0;
}

static void
nvkm_fifo_chan_child_del(struct nvkm_oproxy *base)
{
	struct nvkm_fifo_chan_object *object =
		container_of(base, typeof(*object), oproxy);
	struct nvkm_engine *engine  = object->oproxy.base.engine;
	struct nvkm_fifo_chan *chan = object->chan;
	struct nvkm_fifo_engn *engn = nvkm_fifo_chan_engn(chan, engine);

	if (chan->func->object_dtor)
		chan->func->object_dtor(chan, object->hash);

	if (!--engn->refcount) {
		if (chan->func->engine_dtor)
			chan->func->engine_dtor(chan, engine);
		nvkm_object_del(&engn->object);
		if (chan->vmm)
			atomic_dec(&chan->vmm->engref[engine->subdev.type]);
	}
}

static const struct nvkm_oproxy_func
@@ -147,7 +67,8 @@ nvkm_fifo_chan_child_new(const struct nvkm_oclass *oclass, void *data, u32 size,
{
	struct nvkm_engine *engine = oclass->engine;
	struct nvkm_fifo_chan *chan = nvkm_fifo_chan(oclass->parent);
	struct nvkm_fifo_engn *engn = nvkm_fifo_chan_engn(chan, engine);
	struct nvkm_ectx *engn = nvkm_list_find(engn, &chan->cgrp->ectxs, head,
						engn->engn->engine == engine);
	struct nvkm_fifo_chan_object *object;
	int ret = 0;

@@ -157,33 +78,6 @@ nvkm_fifo_chan_child_new(const struct nvkm_oclass *oclass, void *data, u32 size,
	object->chan = chan;
	*pobject = &object->oproxy.base;

	if (!engn->refcount++) {
		struct nvkm_oclass cclass = {
			.client = oclass->client,
			.engine = oclass->engine,
		};

		if (chan->vmm)
			atomic_inc(&chan->vmm->engref[engine->subdev.type]);

		if (engine->func->fifo.cclass) {
			ret = engine->func->fifo.cclass(chan, &cclass,
							&engn->object);
		} else
		if (engine->func->cclass) {
			ret = nvkm_object_new_(engine->func->cclass, &cclass,
					       NULL, 0, &engn->object);
		}
		if (ret)
			return ret;

		if (chan->func->engine_ctor) {
			ret = chan->func->engine_ctor(chan, oclass->engine,
						      engn->object);
			if (ret)
				return ret;
		}
	}

	ret = oclass->base.ctor(&(const struct nvkm_oclass) {
					.base = oclass->base,
@@ -210,10 +104,16 @@ nvkm_fifo_chan_child_new(const struct nvkm_oclass *oclass, void *data, u32 size,
}

void
nvkm_chan_cctx_bind(struct nvkm_chan *chan, struct nvkm_oproxy *oproxy, struct nvkm_cctx *cctx)
nvkm_chan_cctx_bind(struct nvkm_chan *chan, struct nvkm_engn *engn, struct nvkm_cctx *cctx)
{
	struct nvkm_cgrp *cgrp = chan->cgrp;
	struct nvkm_runl *runl = cgrp->runl;
	struct nvkm_engine *engine = engn->engine;

	if (!engn->func->bind)
		return;

	CHAN_TRACE(chan, "%sbind cctx %d[%s]", cctx ? "" : "un", engn->id, engine->subdev.name);

	/* Prevent any channel in channel group from being rescheduled, kick them
	 * off host and any engine(s) they're loaded on.
@@ -225,10 +125,7 @@ nvkm_chan_cctx_bind(struct nvkm_chan *chan, struct nvkm_oproxy *oproxy, struct n
	nvkm_chan_preempt(chan, true);

	/* Update context pointer. */
	if (cctx)
		nvkm_fifo_chan_child_init(nvkm_oproxy(oproxy->object));
	else
		nvkm_fifo_chan_child_fini(nvkm_oproxy(oproxy->object), false);
	engn->func->bind(engn, cctx, chan);

	/* Resume normal operation. */
	if (cgrp->hw)
@@ -558,10 +455,6 @@ nvkm_fifo_chan_ctor(const struct nvkm_fifo_chan_func *fn,

	*func = *fifo->func->chan.func;
	func->dtor = fn->dtor;
	func->engine_ctor = fn->engine_ctor;
	func->engine_dtor = fn->engine_dtor;
	func->engine_init = fn->engine_init;
	func->engine_fini = fn->engine_fini;
	func->object_ctor = fn->object_ctor;
	func->object_dtor = fn->object_dtor;

@@ -572,7 +465,6 @@ nvkm_fifo_chan_ctor(const struct nvkm_fifo_chan_func *fn,
	atomic_set(&chan->errored, 0);

	nvkm_object_ctor(&nvkm_fifo_chan_func, oclass, &chan->object);
	chan->fifo = fifo;
	INIT_LIST_HEAD(&chan->cctxs);
	INIT_LIST_HEAD(&chan->head);

Loading