diff options
Diffstat (limited to 'drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c')
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c | 155 |
1 files changed, 61 insertions, 94 deletions
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c index 80c87521bebe..118b37aea318 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c @@ -22,6 +22,7 @@ * Authors: Ben Skeggs */ #include "changk104.h" +#include "cgrp.h" #include <core/client.h> #include <core/gpuobj.h> @@ -33,27 +34,40 @@ #include <nvif/cla06f.h> #include <nvif/unpack.h> -static int -gk104_fifo_gpfifo_kick(struct gk104_fifo_chan *chan) +int +gk104_fifo_gpfifo_kick_locked(struct gk104_fifo_chan *chan) { struct gk104_fifo *fifo = chan->fifo; struct nvkm_subdev *subdev = &fifo->base.engine.subdev; struct nvkm_device *device = subdev->device; struct nvkm_client *client = chan->base.object.client; + struct nvkm_fifo_cgrp *cgrp = chan->cgrp; int ret = 0; - mutex_lock(&subdev->mutex); - nvkm_wr32(device, 0x002634, chan->base.chid); + if (cgrp) + nvkm_wr32(device, 0x002634, cgrp->id | 0x01000000); + else + nvkm_wr32(device, 0x002634, chan->base.chid); if (nvkm_msec(device, 2000, if (!(nvkm_rd32(device, 0x002634) & 0x00100000)) break; ) < 0) { - nvkm_error(subdev, "channel %d [%s] kick timeout\n", - chan->base.chid, client->name); + nvkm_error(subdev, "%s %d [%s] kick timeout\n", + cgrp ? "tsg" : "channel", + cgrp ? cgrp->id : chan->base.chid, client->name); nvkm_fifo_recover_chan(&fifo->base, chan->base.chid); ret = -ETIMEDOUT; } - mutex_unlock(&subdev->mutex); + return ret; +} + +int +gk104_fifo_gpfifo_kick(struct gk104_fifo_chan *chan) +{ + int ret; + mutex_lock(&chan->base.fifo->engine.subdev.mutex); + ret = gk104_fifo_gpfifo_kick_locked(chan); + mutex_unlock(&chan->base.fifo->engine.subdev.mutex); return ret; } @@ -62,9 +76,8 @@ gk104_fifo_gpfifo_engine_addr(struct nvkm_engine *engine) { switch (engine->subdev.index) { case NVKM_ENGINE_SW : - case NVKM_ENGINE_CE0 : - case NVKM_ENGINE_CE1 : - case NVKM_ENGINE_CE2 : return 0x0000; + case NVKM_ENGINE_CE0...NVKM_ENGINE_CE_LAST: + return 0; case NVKM_ENGINE_GR : return 0x0210; case NVKM_ENGINE_SEC : return 0x0220; case NVKM_ENGINE_MSPDEC: return 0x0250; @@ -133,7 +146,7 @@ gk104_fifo_gpfifo_engine_init(struct nvkm_fifo_chan *base, return 0; } -static void +void gk104_fifo_gpfifo_engine_dtor(struct nvkm_fifo_chan *base, struct nvkm_engine *engine) { @@ -142,7 +155,7 @@ gk104_fifo_gpfifo_engine_dtor(struct nvkm_fifo_chan *base, nvkm_gpuobj_del(&chan->engn[engine->subdev.index].inst); } -static int +int gk104_fifo_gpfifo_engine_ctor(struct nvkm_fifo_chan *base, struct nvkm_engine *engine, struct nvkm_object *object) @@ -167,7 +180,7 @@ gk104_fifo_gpfifo_engine_ctor(struct nvkm_fifo_chan *base, chan->engn[engn].vma, NULL, 0); } -static void +void gk104_fifo_gpfifo_fini(struct nvkm_fifo_chan *base) { struct gk104_fifo_chan *chan = gk104_fifo_chan(base); @@ -185,7 +198,7 @@ gk104_fifo_gpfifo_fini(struct nvkm_fifo_chan *base) nvkm_wr32(device, 0x800000 + coff, 0x00000000); } -static void +void gk104_fifo_gpfifo_init(struct nvkm_fifo_chan *base) { struct gk104_fifo_chan *chan = gk104_fifo_chan(base); @@ -205,13 +218,15 @@ gk104_fifo_gpfifo_init(struct nvkm_fifo_chan *base) } } -static void * +void * gk104_fifo_gpfifo_dtor(struct nvkm_fifo_chan *base) { - return gk104_fifo_chan(base); + struct gk104_fifo_chan *chan = gk104_fifo_chan(base); + kfree(chan->cgrp); + return chan; } -static const struct nvkm_fifo_chan_func +const struct nvkm_fifo_chan_func gk104_fifo_gpfifo_func = { .dtor = gk104_fifo_gpfifo_dtor, .init = gk104_fifo_gpfifo_init, @@ -223,62 +238,30 @@ gk104_fifo_gpfifo_func = { .engine_fini = gk104_fifo_gpfifo_engine_fini, }; -struct gk104_fifo_chan_func { - u32 engine; - u64 subdev; -}; - static int -gk104_fifo_gpfifo_new_(const struct gk104_fifo_chan_func *func, - struct gk104_fifo *fifo, u32 *engmask, u16 *chid, +gk104_fifo_gpfifo_new_(struct gk104_fifo *fifo, u64 *runlists, u16 *chid, u64 vmm, u64 ioffset, u64 ilength, const struct nvkm_oclass *oclass, struct nvkm_object **pobject) { struct gk104_fifo_chan *chan; - int runlist = -1, ret = -ENOSYS, i, j; - u32 engines = 0, present = 0; + int runlist = ffs(*runlists) -1, ret, i; + unsigned long engm; u64 subdevs = 0; u64 usermem; - if (!vmm) + if (!vmm || runlist < 0 || runlist >= fifo->runlist_nr) return -EINVAL; + *runlists = BIT_ULL(runlist); - /* Determine which downstream engines are present */ - for (i = 0; i < fifo->engine_nr; i++) { - struct nvkm_engine *engine = fifo->engine[i].engine; - if (engine) { - u64 submask = BIT_ULL(engine->subdev.index); - for (j = 0; func[j].subdev; j++) { - if (func[j].subdev & submask) { - present |= func[j].engine; - break; - } - } - - if (!func[j].subdev) - continue; - - if (runlist < 0 && (*engmask & present)) - runlist = fifo->engine[i].runl; - if (runlist == fifo->engine[i].runl) { - engines |= func[j].engine; - subdevs |= func[j].subdev; - } - } - } - - /* Just an engine mask query? All done here! */ - if (!*engmask) { - *engmask = present; - return nvkm_object_new(oclass, NULL, 0, pobject); + engm = fifo->runlist[runlist].engm; + for_each_set_bit(i, &engm, fifo->engine_nr) { + if (fifo->engine[i].engine) + subdevs |= BIT_ULL(fifo->engine[i].engine->subdev.index); } - /* No runlist? No supported engines. */ - *engmask = present; - if (runlist < 0) - return -ENODEV; - *engmask = engines; + if (subdevs & BIT_ULL(NVKM_ENGINE_GR)) + subdevs |= BIT_ULL(NVKM_ENGINE_SW); /* Allocate the channel. */ if (!(chan = kzalloc(sizeof(*chan), GFP_KERNEL))) @@ -297,6 +280,18 @@ gk104_fifo_gpfifo_new_(const struct gk104_fifo_chan_func *func, *chid = chan->base.chid; + /* Hack to support GPUs where even individual channels should be + * part of a channel group. + */ + if (fifo->func->cgrp_force) { + if (!(chan->cgrp = kmalloc(sizeof(*chan->cgrp), GFP_KERNEL))) + return -ENOMEM; + chan->cgrp->id = chan->base.chid; + INIT_LIST_HEAD(&chan->cgrp->head); + INIT_LIST_HEAD(&chan->cgrp->chan); + chan->cgrp->chan_nr = 0; + } + /* Clear channel control registers. */ usermem = chan->base.chid * 0x200; ilength = order_base_2(ilength / 8); @@ -328,45 +323,25 @@ gk104_fifo_gpfifo_new_(const struct gk104_fifo_chan_func *func, return 0; } -static const struct gk104_fifo_chan_func -gk104_fifo_gpfifo[] = { - { NVA06F_V0_ENGINE_SW | NVA06F_V0_ENGINE_GR, - BIT_ULL(NVKM_ENGINE_SW) | BIT_ULL(NVKM_ENGINE_GR) - }, - { NVA06F_V0_ENGINE_SEC , BIT_ULL(NVKM_ENGINE_SEC ) }, - { NVA06F_V0_ENGINE_MSVLD , BIT_ULL(NVKM_ENGINE_MSVLD ) }, - { NVA06F_V0_ENGINE_MSPDEC, BIT_ULL(NVKM_ENGINE_MSPDEC) }, - { NVA06F_V0_ENGINE_MSPPP , BIT_ULL(NVKM_ENGINE_MSPPP ) }, - { NVA06F_V0_ENGINE_MSENC , BIT_ULL(NVKM_ENGINE_MSENC ) }, - { NVA06F_V0_ENGINE_VIC , BIT_ULL(NVKM_ENGINE_VIC ) }, - { NVA06F_V0_ENGINE_NVDEC , BIT_ULL(NVKM_ENGINE_NVDEC ) }, - { NVA06F_V0_ENGINE_NVENC0, BIT_ULL(NVKM_ENGINE_NVENC0) }, - { NVA06F_V0_ENGINE_NVENC1, BIT_ULL(NVKM_ENGINE_NVENC1) }, - { NVA06F_V0_ENGINE_CE0 , BIT_ULL(NVKM_ENGINE_CE0 ) }, - { NVA06F_V0_ENGINE_CE1 , BIT_ULL(NVKM_ENGINE_CE1 ) }, - { NVA06F_V0_ENGINE_CE2 , BIT_ULL(NVKM_ENGINE_CE2 ) }, - {} -}; - int -gk104_fifo_gpfifo_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass, +gk104_fifo_gpfifo_new(struct gk104_fifo *fifo, const struct nvkm_oclass *oclass, void *data, u32 size, struct nvkm_object **pobject) { struct nvkm_object *parent = oclass->parent; union { struct kepler_channel_gpfifo_a_v0 v0; } *args = data; - struct gk104_fifo *fifo = gk104_fifo(base); int ret = -ENOSYS; nvif_ioctl(parent, "create channel gpfifo size %d\n", size); if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) { nvif_ioctl(parent, "create channel gpfifo vers %d vmm %llx " - "ioffset %016llx ilength %08x engine %08x\n", + "ioffset %016llx ilength %08x " + "runlist %016llx\n", args->v0.version, args->v0.vmm, args->v0.ioffset, - args->v0.ilength, args->v0.engines); - return gk104_fifo_gpfifo_new_(gk104_fifo_gpfifo, fifo, - &args->v0.engines, + args->v0.ilength, args->v0.runlist); + return gk104_fifo_gpfifo_new_(fifo, + &args->v0.runlist, &args->v0.chid, args->v0.vmm, args->v0.ioffset, @@ -376,11 +351,3 @@ gk104_fifo_gpfifo_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass, return ret; } - -const struct nvkm_fifo_chan_oclass -gk104_fifo_gpfifo_oclass = { - .base.oclass = KEPLER_CHANNEL_GPFIFO_A, - .base.minver = 0, - .base.maxver = 0, - .ctor = gk104_fifo_gpfifo_new, -}; |