diff options
Diffstat (limited to 'drivers/gpu/drm/nouveau/nvkm/engine/fifo/ga100.c')
| -rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/engine/fifo/ga100.c | 128 |
1 files changed, 102 insertions, 26 deletions
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/ga100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/ga100.c index 12a5d99d5e77..6848a56f20c0 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/ga100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/ga100.c @@ -27,14 +27,12 @@ #include "runq.h" #include <core/gpuobj.h> +#include <subdev/gsp.h> #include <subdev/top.h> #include <subdev/vfn.h> #include <nvif/class.h> -/*TODO: allocate? */ -#define GA100_FIFO_NONSTALL_VECTOR 0 - static u32 ga100_chan_doorbell_handle(struct nvkm_chan *chan) { @@ -83,7 +81,7 @@ ga100_chan_ramfc_write(struct nvkm_chan *chan, u64 offset, u64 length, u32 devm, nvkm_wo32(chan->inst, 0x0e4, priv ? 0x00000020 : 0x00000000); nvkm_wo32(chan->inst, 0x0e8, chan->id); nvkm_wo32(chan->inst, 0x0f4, 0x00001000 | (priv ? 0x00000100 : 0x00000000)); - nvkm_wo32(chan->inst, 0x0f8, 0x80000000 | GA100_FIFO_NONSTALL_VECTOR); + nvkm_wo32(chan->inst, 0x0f8, 0x80000000 | chan->cgrp->runl->nonstall.vector); nvkm_mo32(chan->inst, 0x218, 0x00000000, 0x00000000); nvkm_done(chan->inst); return 0; @@ -148,8 +146,20 @@ ga100_engn_cxid(struct nvkm_engn *engn, bool *cgid) return -ENODEV; } +static int +ga100_engn_nonstall(struct nvkm_engn *engn) +{ + struct nvkm_engine *engine = engn->engine; + + if (WARN_ON(!engine->func->nonstall)) + return -EINVAL; + + return engine->func->nonstall(engine); +} + const struct nvkm_engn_func ga100_engn = { + .nonstall = ga100_engn_nonstall, .cxid = ga100_engn_cxid, .ctor = gk104_ectx_ctor, .bind = gv100_ectx_bind, @@ -157,6 +167,7 @@ ga100_engn = { const struct nvkm_engn_func ga100_engn_ce = { + .nonstall = ga100_engn_nonstall, .cxid = ga100_engn_cxid, .ctor = gv100_ectx_ce_ctor, .bind = gv100_ectx_ce_bind, @@ -429,7 +440,9 @@ static int ga100_runl_new(struct nvkm_fifo *fifo, int id, u32 addr, struct nvkm_runl **prunl) { struct nvkm_device *device = fifo->engine.subdev.device; + struct nvkm_top_device *tdev; struct nvkm_runl *runl; + struct nvkm_engn *engn; u32 chcfg = nvkm_rd32(device, addr + 0x004); u32 chnum = 1 << (chcfg & 0x0000000f); u32 chaddr = (chcfg & 0xfffffff0); @@ -437,26 +450,55 @@ ga100_runl_new(struct nvkm_fifo *fifo, int id, u32 addr, struct nvkm_runl **prun u32 vector = nvkm_rd32(device, addr + 0x160); int i, ret; - runl = *prunl = nvkm_runl_new(fifo, id, addr, chnum); + runl = nvkm_runl_new(fifo, id, addr, chnum); if (IS_ERR(runl)) return PTR_ERR(runl); + *prunl = runl; + for (i = 0; i < 2; i++) { u32 pbcfg = nvkm_rd32(device, addr + 0x010 + (i * 0x04)); if (pbcfg & 0x80000000) { runl->runq[runl->runq_nr] = nvkm_runq_new(fifo, ((pbcfg & 0x03fffc00) - 0x040000) / 0x800); - if (!runl->runq[runl->runq_nr]) + if (!runl->runq[runl->runq_nr]) { + RUNL_ERROR(runl, "runq %d", runl->runq_nr); return -ENOMEM; + } runl->runq_nr++; } } + nvkm_list_foreach(tdev, &device->top->device, head, tdev->runlist == runl->addr) { + if (tdev->engine < 0) { + RUNL_DEBUG(runl, "engn !top"); + return -EINVAL; + } + + engn = nvkm_runl_add(runl, tdev->engine, (tdev->type == NVKM_ENGINE_CE) ? + fifo->func->engn_ce : fifo->func->engn, + tdev->type, tdev->inst); + if (!engn) + return -EINVAL; + + if (!engn->engine->func->nonstall) { + RUNL_DEBUG(runl, "engn %s !nonstall", engn->engine->subdev.name); + return -EINVAL; + } + } + + if (list_empty(&runl->engns)) { + RUNL_DEBUG(runl, "!engns"); + return -EINVAL; + } + ret = nvkm_inth_add(&device->vfn->intr, vector & 0x00000fff, NVKM_INTR_PRIO_NORMAL, &fifo->engine.subdev, ga100_runl_intr, &runl->inth); - if (ret) + if (ret) { + RUNL_ERROR(runl, "inth %d", ret); return ret; + } runl->chan = chaddr; runl->doorbell = dbcfg >> 16; @@ -466,26 +508,20 @@ ga100_runl_new(struct nvkm_fifo *fifo, int id, u32 addr, struct nvkm_runl **prun static irqreturn_t ga100_fifo_nonstall_intr(struct nvkm_inth *inth) { - struct nvkm_fifo *fifo = container_of(inth, typeof(*fifo), nonstall.intr); + struct nvkm_runl *runl = container_of(inth, typeof(*runl), nonstall.inth); - nvkm_event_ntfy(&fifo->nonstall.event, 0, NVKM_FIFO_NONSTALL_EVENT); + nvkm_event_ntfy(&runl->fifo->nonstall.event, runl->id, NVKM_FIFO_NONSTALL_EVENT); return IRQ_HANDLED; } static void ga100_fifo_nonstall_block(struct nvkm_event *event, int type, int index) { - struct nvkm_fifo *fifo = container_of(event, typeof(*fifo), nonstall.event); - - nvkm_inth_block(&fifo->nonstall.intr); } static void ga100_fifo_nonstall_allow(struct nvkm_event *event, int type, int index) { - struct nvkm_fifo *fifo = container_of(event, typeof(*fifo), nonstall.event); - - nvkm_inth_allow(&fifo->nonstall.intr); } const struct nvkm_event_func @@ -497,9 +533,47 @@ ga100_fifo_nonstall = { int ga100_fifo_nonstall_ctor(struct nvkm_fifo *fifo) { - return nvkm_inth_add(&fifo->engine.subdev.device->vfn->intr, GA100_FIFO_NONSTALL_VECTOR, - NVKM_INTR_PRIO_NORMAL, &fifo->engine.subdev, ga100_fifo_nonstall_intr, - &fifo->nonstall.intr); + struct nvkm_subdev *subdev = &fifo->engine.subdev; + struct nvkm_vfn *vfn = subdev->device->vfn; + struct nvkm_runl *runl; + int ret, nr = 0; + + nvkm_runl_foreach(runl, fifo) { + struct nvkm_engn *engn = list_first_entry(&runl->engns, typeof(*engn), head); + + runl->nonstall.vector = engn->func->nonstall(engn); + + /* if no nonstall vector just keep going */ + if (runl->nonstall.vector == -1) + continue; + if (runl->nonstall.vector < 0) { + RUNL_ERROR(runl, "nonstall %d", runl->nonstall.vector); + return runl->nonstall.vector; + } + + ret = nvkm_inth_add(&vfn->intr, runl->nonstall.vector, NVKM_INTR_PRIO_NORMAL, + subdev, ga100_fifo_nonstall_intr, &runl->nonstall.inth); + if (ret) + return ret; + + nvkm_inth_allow(&runl->nonstall.inth); + + nr = max(nr, runl->id + 1); + } + + return nr; +} + +void +ga100_fifo_nonstall_dtor(struct nvkm_fifo *fifo) +{ + struct nvkm_runl *runl; + + nvkm_runl_foreach(runl, fifo) { + if (runl->nonstall.vector < 0) + continue; + nvkm_inth_block(&runl->nonstall.inth); + } } int @@ -514,15 +588,13 @@ ga100_fifo_runl_ctor(struct nvkm_fifo *fifo) runl = nvkm_runl_get(fifo, -1, tdev->runlist); if (!runl) { ret = ga100_runl_new(fifo, id++, tdev->runlist, &runl); - if (ret) - return ret; - } - - if (tdev->engine < 0) - continue; + if (ret) { + if (runl) + nvkm_runl_del(runl); - nvkm_runl_add(runl, tdev->engine, (tdev->type == NVKM_ENGINE_CE) ? - fifo->func->engn_ce : fifo->func->engn, tdev->type, tdev->inst); + continue; + } + } } return 0; @@ -533,6 +605,7 @@ ga100_fifo = { .runl_ctor = ga100_fifo_runl_ctor, .mmu_fault = &tu102_fifo_mmu_fault, .nonstall_ctor = ga100_fifo_nonstall_ctor, + .nonstall_dtor = ga100_fifo_nonstall_dtor, .nonstall = &ga100_fifo_nonstall, .runl = &ga100_runl, .runq = &ga100_runq, @@ -546,5 +619,8 @@ int ga100_fifo_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_fifo **pfifo) { + if (nvkm_gsp_rm(device->gsp)) + return r535_fifo_new(&ga100_fifo, device, type, inst, pfifo); + return nvkm_fifo_new_(&ga100_fifo, device, type, inst, pfifo); } |
