summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2022-06-01 20:47:38 +1000
committerBen Skeggs <bskeggs@redhat.com>2022-11-09 10:44:50 +1000
commit06db7fded6dec88772a65c5a39af12ba4dc2ad38 (patch)
treed00ff73679dd75931c7625880903e1b301184600 /drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c
parent7ac293328122075a2afc40a4089e7afc6cbc26eb (diff)
downloadlinux-06db7fded6dec88772a65c5a39af12ba4dc2ad38.tar.bz2
drm/nouveau/fifo: add new channel classes
Exposes a bunch of the new features that became possible as a result of the earlier commits. DRM will build on this in the future to add support for features such as SCG ("async compute") and multi-device rendering, as part of the work necessary to be able to write a half- decent vulkan driver - finally. For the moment, this just crudely ports DRM to the API changes. - channel class interfaces now the same for all HW classes - channel group class exposed (SCG) - channel runqueue selector exposed (SCG) - channel sub-device id control exposed (multi-device rendering) - channel names in logging will reflect creating process, not fd owner - explicit USERD allocation required by VOLTA_CHANNEL_GPFIFO_A and newer - drm is smarter about determining the appropriate channel class to use Signed-off-by: Ben Skeggs <bskeggs@redhat.com> Reviewed-by: Lyude Paul <lyude@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c')
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c97
1 files changed, 44 insertions, 53 deletions
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c
index 4f99e5bf4e7f..b7c9d6115bce 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c
@@ -28,7 +28,6 @@
#include "runl.h"
#include "priv.h"
-#include <core/oproxy.h>
#include <core/ramht.h>
#include <subdev/mmu.h>
#include <engine/dma.h>
@@ -283,16 +282,6 @@ nvkm_chan_del(struct nvkm_chan **pchan)
nvkm_cgrp_unref(&chan->cgrp);
}
- chan = nvkm_object_dtor(&chan->object);
- kfree(chan);
-}
-
-static void *
-nvkm_fifo_chan_dtor(struct nvkm_object *object)
-{
- struct nvkm_fifo_chan *chan = nvkm_fifo_chan(object);
- void *data = chan->func->dtor(chan);
-
if (chan->vmm) {
nvkm_vmm_part(chan->vmm, chan->inst->memory);
nvkm_vmm_unref(&chan->vmm);
@@ -300,8 +289,7 @@ nvkm_fifo_chan_dtor(struct nvkm_object *object)
nvkm_gpuobj_del(&chan->push);
nvkm_gpuobj_del(&chan->inst);
- kfree(chan->func);
- return data;
+ kfree(chan);
}
void
@@ -354,51 +342,42 @@ nvkm_chan_get_chid(struct nvkm_engine *engine, int id, unsigned long *pirqflags)
return NULL;
}
-static const struct nvkm_object_func
-nvkm_fifo_chan_func = {
- .dtor = nvkm_fifo_chan_dtor,
-};
-
int
-nvkm_fifo_chan_ctor(const struct nvkm_fifo_chan_func *fn,
- struct nvkm_fifo *fifo, u32 size, u32 align, bool zero,
- u64 hvmm, u64 push, u32 engm, int bar, u32 base,
- u32 user, const struct nvkm_oclass *oclass,
- struct nvkm_fifo_chan *chan)
+nvkm_chan_new_(const struct nvkm_chan_func *func, struct nvkm_runl *runl, int runq,
+ struct nvkm_cgrp *cgrp, const char *name, bool priv, u32 devm, struct nvkm_vmm *vmm,
+ struct nvkm_dmaobj *dmaobj, u64 offset, u64 length,
+ struct nvkm_memory *userd, u64 ouserd, struct nvkm_chan **pchan)
{
- struct nvkm_chan_func *func;
- struct nvkm_client *client = oclass->client;
+ struct nvkm_fifo *fifo = runl->fifo;
struct nvkm_device *device = fifo->engine.subdev.device;
- struct nvkm_dmaobj *dmaobj;
- struct nvkm_cgrp *cgrp = NULL;
- struct nvkm_runl *runl;
- struct nvkm_engn *engn = NULL;
- struct nvkm_vmm *vmm = NULL;
+ struct nvkm_chan *chan;
int ret;
- nvkm_runl_foreach(runl, fifo) {
- engn = nvkm_runl_find_engn(engn, runl, engm & BIT(engn->id));
- if (engn)
- break;
- }
-
- if (!engn)
+ /* Validate arguments against class requirements. */
+ if ((runq && runq >= runl->func->runqs) ||
+ (!func->inst->vmm != !vmm) ||
+ ((func->userd->bar < 0) == !userd) ||
+ (!func->ramfc->ctxdma != !dmaobj) ||
+ ((func->ramfc->devm < devm) && devm != BIT(0)) ||
+ (!func->ramfc->priv && priv)) {
+ RUNL_DEBUG(runl, "args runq:%d:%d vmm:%d:%p userd:%d:%p "
+ "push:%d:%p devm:%08x:%08x priv:%d:%d",
+ runl->func->runqs, runq, func->inst->vmm, vmm,
+ func->userd->bar < 0, userd, func->ramfc->ctxdma, dmaobj,
+ func->ramfc->devm, devm, func->ramfc->priv, priv);
return -EINVAL;
+ }
- /*FIXME: temp kludge to ease transition, remove later */
- if (!(func = kmalloc(sizeof(*func), GFP_KERNEL)))
+ if (!(chan = *pchan = kzalloc(sizeof(*chan), GFP_KERNEL)))
return -ENOMEM;
- *func = *fifo->func->chan.func;
- func->dtor = fn->dtor;
-
chan->func = func;
+ strscpy(chan->name, name, sizeof(chan->name));
+ chan->runq = runq;
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);
INIT_LIST_HEAD(&chan->cctxs);
INIT_LIST_HEAD(&chan->head);
@@ -437,10 +416,6 @@ nvkm_fifo_chan_ctor(const struct nvkm_fifo_chan_func *fn,
/* Initialise virtual address-space. */
if (func->inst->vmm) {
- struct nvkm_vmm *vmm = nvkm_uvmm_search(client, hvmm);
- if (IS_ERR(vmm))
- return PTR_ERR(vmm);
-
if (WARN_ON(vmm->mmu != device->mmu))
return -EINVAL;
@@ -455,10 +430,6 @@ nvkm_fifo_chan_ctor(const struct nvkm_fifo_chan_func *fn,
/* Allocate HW ctxdma for push buffer. */
if (func->ramfc->ctxdma) {
- dmaobj = nvkm_dmaobj_search(client, push);
- if (IS_ERR(dmaobj))
- return PTR_ERR(dmaobj);
-
ret = nvkm_object_bind(&dmaobj->object, chan->inst, -16, &chan->push);
if (ret) {
RUNL_DEBUG(runl, "bind %d", ret);
@@ -477,7 +448,20 @@ nvkm_fifo_chan_ctor(const struct nvkm_fifo_chan_func *fn,
cgrp->id = chan->id;
/* Initialise USERD. */
- if (1) {
+ if (func->userd->bar < 0) {
+ if (ouserd + chan->func->userd->size >= nvkm_memory_size(userd)) {
+ RUNL_DEBUG(runl, "ouserd %llx", ouserd);
+ return -EINVAL;
+ }
+
+ ret = nvkm_memory_kmap(userd, &chan->userd.mem);
+ if (ret) {
+ RUNL_DEBUG(runl, "userd %d", ret);
+ return ret;
+ }
+
+ chan->userd.base = ouserd;
+ } else {
chan->userd.mem = nvkm_memory_ref(fifo->userd.mem);
chan->userd.base = chan->id * chan->func->userd->size;
}
@@ -485,5 +469,12 @@ nvkm_fifo_chan_ctor(const struct nvkm_fifo_chan_func *fn,
if (chan->func->userd->clear)
chan->func->userd->clear(chan);
+ /* Initialise RAMFC. */
+ ret = chan->func->ramfc->write(chan, offset, length, devm, priv);
+ if (ret) {
+ RUNL_DEBUG(runl, "ramfc %d", ret);
+ return ret;
+ }
+
return 0;
}