diff options
Diffstat (limited to 'drivers/gpu/drm/nouveau/nvkm/engine/fifo')
22 files changed, 1082 insertions, 359 deletions
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/Kbuild b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/Kbuild index 64e51838edf8..f00408577a6a 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/Kbuild +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/Kbuild @@ -15,6 +15,7 @@ nvkm-y += nvkm/engine/fifo/gm200.o nvkm-y += nvkm/engine/fifo/gm20b.o nvkm-y += nvkm/engine/fifo/gp100.o nvkm-y += nvkm/engine/fifo/gp10b.o +nvkm-y += nvkm/engine/fifo/gv100.o nvkm-y += nvkm/engine/fifo/chan.o nvkm-y += nvkm/engine/fifo/channv50.o @@ -31,6 +32,6 @@ nvkm-y += nvkm/engine/fifo/gpfifonv50.o nvkm-y += nvkm/engine/fifo/gpfifog84.o nvkm-y += nvkm/engine/fifo/gpfifogf100.o nvkm-y += nvkm/engine/fifo/gpfifogk104.o -nvkm-y += nvkm/engine/fifo/gpfifogk110.o -nvkm-y += nvkm/engine/fifo/gpfifogm200.o -nvkm-y += nvkm/engine/fifo/gpfifogp100.o +nvkm-y += nvkm/engine/fifo/gpfifogv100.o + +nvkm-y += nvkm/engine/fifo/usergv100.o diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c index 64f6b7654a08..c773caf21f6b 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c @@ -30,6 +30,7 @@ #include <subdev/mc.h> #include <nvif/event.h> +#include <nvif/cl0080.h> #include <nvif/unpack.h> void @@ -56,6 +57,12 @@ nvkm_fifo_start(struct nvkm_fifo *fifo, unsigned long *flags) } void +nvkm_fifo_fault(struct nvkm_fifo *fifo, struct nvkm_fault_data *info) +{ + return fifo->func->fault(fifo, info); +} + +void nvkm_fifo_chan_put(struct nvkm_fifo *fifo, unsigned long flags, struct nvkm_fifo_chan **pchan) { @@ -209,6 +216,20 @@ nvkm_fifo_uevent(struct nvkm_fifo *fifo) } static int +nvkm_fifo_class_new_(struct nvkm_device *device, + const struct nvkm_oclass *oclass, void *data, u32 size, + struct nvkm_object **pobject) +{ + struct nvkm_fifo *fifo = nvkm_fifo(oclass->engine); + return fifo->func->class_new(fifo, oclass, data, size, pobject); +} + +static const struct nvkm_device_oclass +nvkm_fifo_class_ = { + .ctor = nvkm_fifo_class_new_, +}; + +static int nvkm_fifo_class_new(struct nvkm_device *device, const struct nvkm_oclass *oclass, void *data, u32 size, struct nvkm_object **pobject) @@ -232,13 +253,9 @@ nvkm_fifo_class_get(struct nvkm_oclass *oclass, int index, int c = 0; if (fifo->func->class_get) { - int ret = fifo->func->class_get(fifo, index, &sclass); - if (ret == 0) { - oclass->base = sclass->base; - oclass->engn = sclass; - *class = &nvkm_fifo_class; - return 0; - } + int ret = fifo->func->class_get(fifo, index, oclass); + if (ret == 0) + *class = &nvkm_fifo_class_; return ret; } @@ -271,6 +288,20 @@ nvkm_fifo_fini(struct nvkm_engine *engine, bool suspend) } static int +nvkm_fifo_info(struct nvkm_engine *engine, u64 mthd, u64 *data) +{ + struct nvkm_fifo *fifo = nvkm_fifo(engine); + switch (mthd) { + case NV_DEVICE_FIFO_CHANNELS: *data = fifo->nr; return 0; + default: + if (fifo->func->info) + return fifo->func->info(fifo, mthd, data); + break; + } + return -ENOSYS; +} + +static int nvkm_fifo_oneinit(struct nvkm_engine *engine) { struct nvkm_fifo *fifo = nvkm_fifo(engine); @@ -311,6 +342,7 @@ nvkm_fifo = { .dtor = nvkm_fifo_dtor, .preinit = nvkm_fifo_preinit, .oneinit = nvkm_fifo_oneinit, + .info = nvkm_fifo_info, .init = nvkm_fifo_init, .fini = nvkm_fifo_fini, .intr = nvkm_fifo_intr, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/cgrp.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/cgrp.h new file mode 100644 index 000000000000..d0ac60b06720 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/cgrp.h @@ -0,0 +1,11 @@ +#ifndef __NVKM_FIFO_CGRP_H__ +#define __NVKM_FIFO_CGRP_H__ +#include "priv.h" + +struct nvkm_fifo_cgrp { + int id; + struct list_head head; + struct list_head chan; + int chan_nr; +}; +#endif diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/changk104.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/changk104.h index 1208e3d9dbe2..8e28ba6b2307 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/changk104.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/changk104.h @@ -10,6 +10,7 @@ struct gk104_fifo_chan { struct gk104_fifo *fifo; int runl; + struct nvkm_fifo_cgrp *cgrp; struct list_head head; bool killed; @@ -19,11 +20,20 @@ struct gk104_fifo_chan { } engn[NVKM_SUBDEV_NR]; }; -int gk104_fifo_gpfifo_new(struct nvkm_fifo *, const struct nvkm_oclass *, +extern const struct nvkm_fifo_chan_func gk104_fifo_gpfifo_func; + +int gk104_fifo_gpfifo_new(struct gk104_fifo *, const struct nvkm_oclass *, void *data, u32 size, struct nvkm_object **); +void *gk104_fifo_gpfifo_dtor(struct nvkm_fifo_chan *); +void gk104_fifo_gpfifo_init(struct nvkm_fifo_chan *); +void gk104_fifo_gpfifo_fini(struct nvkm_fifo_chan *); +int gk104_fifo_gpfifo_engine_ctor(struct nvkm_fifo_chan *, struct nvkm_engine *, + struct nvkm_object *); +void gk104_fifo_gpfifo_engine_dtor(struct nvkm_fifo_chan *, + struct nvkm_engine *); +int gk104_fifo_gpfifo_kick(struct gk104_fifo_chan *); +int gk104_fifo_gpfifo_kick_locked(struct gk104_fifo_chan *); -extern const struct nvkm_fifo_chan_oclass gk104_fifo_gpfifo_oclass; -extern const struct nvkm_fifo_chan_oclass gk110_fifo_gpfifo_oclass; -extern const struct nvkm_fifo_chan_oclass gm200_fifo_gpfifo_oclass; -extern const struct nvkm_fifo_chan_oclass gp100_fifo_gpfifo_oclass; +int gv100_fifo_gpfifo_new(struct gk104_fifo *, const struct nvkm_oclass *, + void *data, u32 size, struct nvkm_object **); #endif diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c index 84bd703dd897..a99046414a18 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c @@ -22,16 +22,19 @@ * Authors: Ben Skeggs */ #include "gk104.h" +#include "cgrp.h" #include "changk104.h" #include <core/client.h> #include <core/gpuobj.h> #include <subdev/bar.h> +#include <subdev/fault.h> #include <subdev/timer.h> #include <subdev/top.h> #include <engine/sw.h> #include <nvif/class.h> +#include <nvif/cl0080.h> struct gk104_fifo_engine_status { bool busy; @@ -93,15 +96,39 @@ gk104_fifo_engine_status(struct gk104_fifo *fifo, int engn, } static int +gk104_fifo_class_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass, + void *argv, u32 argc, struct nvkm_object **pobject) +{ + struct gk104_fifo *fifo = gk104_fifo(base); + if (oclass->engn == &fifo->func->chan) { + const struct gk104_fifo_chan_user *user = oclass->engn; + return user->ctor(fifo, oclass, argv, argc, pobject); + } else + if (oclass->engn == &fifo->func->user) { + const struct gk104_fifo_user_user *user = oclass->engn; + return user->ctor(oclass, argv, argc, pobject); + } + WARN_ON(1); + return -EINVAL; +} + +static int gk104_fifo_class_get(struct nvkm_fifo *base, int index, - const struct nvkm_fifo_chan_oclass **psclass) + struct nvkm_oclass *oclass) { struct gk104_fifo *fifo = gk104_fifo(base); int c = 0; - while ((*psclass = fifo->func->chan[c])) { - if (c++ == index) - return 0; + if (fifo->func->user.ctor && c++ == index) { + oclass->base = fifo->func->user.user; + oclass->engn = &fifo->func->user; + return 0; + } + + if (fifo->func->chan.ctor && c++ == index) { + oclass->base = fifo->func->chan.user; + oclass->engn = &fifo->func->chan; + return 0; } return c; @@ -124,10 +151,12 @@ gk104_fifo_uevent_init(struct nvkm_fifo *fifo) void gk104_fifo_runlist_commit(struct gk104_fifo *fifo, int runl) { + const struct gk104_fifo_runlist_func *func = fifo->func->runlist; struct gk104_fifo_chan *chan; struct nvkm_subdev *subdev = &fifo->base.engine.subdev; struct nvkm_device *device = subdev->device; struct nvkm_memory *mem; + struct nvkm_fifo_cgrp *cgrp; int nr = 0; int target; @@ -137,9 +166,14 @@ gk104_fifo_runlist_commit(struct gk104_fifo *fifo, int runl) nvkm_kmap(mem); list_for_each_entry(chan, &fifo->runlist[runl].chan, head) { - nvkm_wo32(mem, (nr * 8) + 0, chan->base.chid); - nvkm_wo32(mem, (nr * 8) + 4, 0x00000000); - nr++; + func->chan(chan, mem, nr++ * func->size); + } + + list_for_each_entry(cgrp, &fifo->runlist[runl].cgrp, head) { + func->cgrp(cgrp, mem, nr++ * func->size); + list_for_each_entry(chan, &cgrp->chan, head) { + func->chan(chan, mem, nr++ * func->size); + } } nvkm_done(mem); @@ -155,10 +189,10 @@ gk104_fifo_runlist_commit(struct gk104_fifo *fifo, int runl) (target << 28)); nvkm_wr32(device, 0x002274, (runl << 20) | nr); - if (wait_event_timeout(fifo->runlist[runl].wait, - !(nvkm_rd32(device, 0x002284 + (runl * 0x08)) - & 0x00100000), - msecs_to_jiffies(2000)) == 0) + if (nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, 0x002284 + (runl * 0x08)) & 0x00100000)) + break; + ) < 0) nvkm_error(subdev, "runlist %d update timeout\n", runl); unlock: mutex_unlock(&subdev->mutex); @@ -167,19 +201,45 @@ unlock: void gk104_fifo_runlist_remove(struct gk104_fifo *fifo, struct gk104_fifo_chan *chan) { + struct nvkm_fifo_cgrp *cgrp = chan->cgrp; mutex_lock(&fifo->base.engine.subdev.mutex); - list_del_init(&chan->head); + if (!list_empty(&chan->head)) { + list_del_init(&chan->head); + if (cgrp && !--cgrp->chan_nr) + list_del_init(&cgrp->head); + } mutex_unlock(&fifo->base.engine.subdev.mutex); } void gk104_fifo_runlist_insert(struct gk104_fifo *fifo, struct gk104_fifo_chan *chan) { + struct nvkm_fifo_cgrp *cgrp = chan->cgrp; mutex_lock(&fifo->base.engine.subdev.mutex); - list_add_tail(&chan->head, &fifo->runlist[chan->runl].chan); + if (cgrp) { + if (!cgrp->chan_nr++) + list_add_tail(&cgrp->head, &fifo->runlist[chan->runl].cgrp); + list_add_tail(&chan->head, &cgrp->chan); + } else { + list_add_tail(&chan->head, &fifo->runlist[chan->runl].chan); + } mutex_unlock(&fifo->base.engine.subdev.mutex); } +void +gk104_fifo_runlist_chan(struct gk104_fifo_chan *chan, + struct nvkm_memory *memory, u32 offset) +{ + nvkm_wo32(memory, offset + 0, chan->base.chid); + nvkm_wo32(memory, offset + 4, 0x00000000); +} + +const struct gk104_fifo_runlist_func +gk104_fifo_runlist = { + .size = 8, + .chan = gk104_fifo_runlist_chan, +}; + static void gk104_fifo_recover_work(struct work_struct *w) { @@ -235,6 +295,32 @@ gk104_fifo_recover_runl(struct gk104_fifo *fifo, int runl) schedule_work(&fifo->recover.work); } +static struct gk104_fifo_chan * +gk104_fifo_recover_chid(struct gk104_fifo *fifo, int runl, int chid) +{ + struct gk104_fifo_chan *chan; + struct nvkm_fifo_cgrp *cgrp; + + list_for_each_entry(chan, &fifo->runlist[runl].chan, head) { + if (chan->base.chid == chid) { + list_del_init(&chan->head); + return chan; + } + } + + list_for_each_entry(cgrp, &fifo->runlist[runl].cgrp, head) { + if (cgrp->id == chid) { + chan = list_first_entry(&cgrp->chan, typeof(*chan), head); + list_del_init(&chan->head); + if (!--cgrp->chan_nr) + list_del_init(&cgrp->head); + return chan; + } + } + + return NULL; +} + static void gk104_fifo_recover_chan(struct nvkm_fifo *base, int chid) { @@ -252,13 +338,10 @@ gk104_fifo_recover_chan(struct nvkm_fifo *base, int chid) return; /* Lookup SW state for channel, and mark it as dead. */ - list_for_each_entry(chan, &fifo->runlist[runl].chan, head) { - if (chan->base.chid == chid) { - list_del_init(&chan->head); - chan->killed = true; - nvkm_fifo_kevent(&fifo->base, chid); - break; - } + chan = gk104_fifo_recover_chid(fifo, runl, chid); + if (chan) { + chan->killed = true; + nvkm_fifo_kevent(&fifo->base, chid); } /* Disable channel. */ @@ -347,6 +430,90 @@ gk104_fifo_recover_engn(struct gk104_fifo *fifo, int engn) schedule_work(&fifo->recover.work); } +static void +gk104_fifo_fault(struct nvkm_fifo *base, struct nvkm_fault_data *info) +{ + struct gk104_fifo *fifo = gk104_fifo(base); + struct nvkm_subdev *subdev = &fifo->base.engine.subdev; + struct nvkm_device *device = subdev->device; + const struct nvkm_enum *er, *ee, *ec, *ea; + struct nvkm_engine *engine = NULL; + struct nvkm_fifo_chan *chan; + unsigned long flags; + char ct[8] = "HUB/", en[16] = ""; + int engn; + + er = nvkm_enum_find(fifo->func->fault.reason, info->reason); + ee = nvkm_enum_find(fifo->func->fault.engine, info->engine); + if (info->hub) { + ec = nvkm_enum_find(fifo->func->fault.hubclient, info->client); + } else { + ec = nvkm_enum_find(fifo->func->fault.gpcclient, info->client); + snprintf(ct, sizeof(ct), "GPC%d/", info->gpc); + } + ea = nvkm_enum_find(fifo->func->fault.access, info->access); + + if (ee && ee->data2) { + switch (ee->data2) { + case NVKM_SUBDEV_BAR: + nvkm_mask(device, 0x001704, 0x00000000, 0x00000000); + break; + case NVKM_SUBDEV_INSTMEM: + nvkm_mask(device, 0x001714, 0x00000000, 0x00000000); + break; + case NVKM_ENGINE_IFB: + nvkm_mask(device, 0x001718, 0x00000000, 0x00000000); + break; + default: + engine = nvkm_device_engine(device, ee->data2); + break; + } + } + + if (ee == NULL) { + enum nvkm_devidx engidx = nvkm_top_fault(device, info->engine); + if (engidx < NVKM_SUBDEV_NR) { + const char *src = nvkm_subdev_name[engidx]; + char *dst = en; + do { + *dst++ = toupper(*src++); + } while(*src); + engine = nvkm_device_engine(device, engidx); + } + } else { + snprintf(en, sizeof(en), "%s", ee->name); + } + + spin_lock_irqsave(&fifo->base.lock, flags); + chan = nvkm_fifo_chan_inst_locked(&fifo->base, info->inst); + + nvkm_error(subdev, + "fault %02x [%s] at %016llx engine %02x [%s] client %02x " + "[%s%s] reason %02x [%s] on channel %d [%010llx %s]\n", + info->access, ea ? ea->name : "", info->addr, + info->engine, ee ? ee->name : en, + info->client, ct, ec ? ec->name : "", + info->reason, er ? er->name : "", chan ? chan->chid : -1, + info->inst, chan ? chan->object.client->name : "unknown"); + + /* Kill the channel that caused the fault. */ + if (chan) + gk104_fifo_recover_chan(&fifo->base, chan->chid); + + /* Channel recovery will probably have already done this for the + * correct engine(s), but just in case we can't find the channel + * information... + */ + for (engn = 0; engn < fifo->engine_nr && engine; engn++) { + if (fifo->engine[engn].engine == engine) { + gk104_fifo_recover_engn(fifo, engn); + break; + } + } + + spin_unlock_irqrestore(&fifo->base.lock, flags); +} + static const struct nvkm_enum gk104_fifo_bind_reason[] = { { 0x01, "BIND_NOT_UNBOUND" }, @@ -456,88 +623,21 @@ gk104_fifo_intr_fault(struct gk104_fifo *fifo, int unit) u32 inst = nvkm_rd32(device, 0x002800 + (unit * 0x10)); u32 valo = nvkm_rd32(device, 0x002804 + (unit * 0x10)); u32 vahi = nvkm_rd32(device, 0x002808 + (unit * 0x10)); - u32 stat = nvkm_rd32(device, 0x00280c + (unit * 0x10)); - u32 gpc = (stat & 0x1f000000) >> 24; - u32 client = (stat & 0x00001f00) >> 8; - u32 write = (stat & 0x00000080); - u32 hub = (stat & 0x00000040); - u32 reason = (stat & 0x0000000f); - const struct nvkm_enum *er, *eu, *ec; - struct nvkm_engine *engine = NULL; - struct nvkm_fifo_chan *chan; - unsigned long flags; - char gpcid[8] = "", en[16] = ""; - int engn; - - er = nvkm_enum_find(fifo->func->fault.reason, reason); - eu = nvkm_enum_find(fifo->func->fault.engine, unit); - if (hub) { - ec = nvkm_enum_find(fifo->func->fault.hubclient, client); - } else { - ec = nvkm_enum_find(fifo->func->fault.gpcclient, client); - snprintf(gpcid, sizeof(gpcid), "GPC%d/", gpc); - } - - if (eu && eu->data2) { - switch (eu->data2) { - case NVKM_SUBDEV_BAR: - nvkm_mask(device, 0x001704, 0x00000000, 0x00000000); - break; - case NVKM_SUBDEV_INSTMEM: - nvkm_mask(device, 0x001714, 0x00000000, 0x00000000); - break; - case NVKM_ENGINE_IFB: - nvkm_mask(device, 0x001718, 0x00000000, 0x00000000); - break; - default: - engine = nvkm_device_engine(device, eu->data2); - break; - } - } - - if (eu == NULL) { - enum nvkm_devidx engidx = nvkm_top_fault(device, unit); - if (engidx < NVKM_SUBDEV_NR) { - const char *src = nvkm_subdev_name[engidx]; - char *dst = en; - do { - *dst++ = toupper(*src++); - } while(*src); - engine = nvkm_device_engine(device, engidx); - } - } else { - snprintf(en, sizeof(en), "%s", eu->name); - } - - spin_lock_irqsave(&fifo->base.lock, flags); - chan = nvkm_fifo_chan_inst_locked(&fifo->base, (u64)inst << 12); - - nvkm_error(subdev, - "%s fault at %010llx engine %02x [%s] client %02x [%s%s] " - "reason %02x [%s] on channel %d [%010llx %s]\n", - write ? "write" : "read", (u64)vahi << 32 | valo, - unit, en, client, gpcid, ec ? ec->name : "", - reason, er ? er->name : "", chan ? chan->chid : -1, - (u64)inst << 12, - chan ? chan->object.client->name : "unknown"); - - - /* Kill the channel that caused the fault. */ - if (chan) - gk104_fifo_recover_chan(&fifo->base, chan->chid); - - /* Channel recovery will probably have already done this for the - * correct engine(s), but just in case we can't find the channel - * information... - */ - for (engn = 0; engn < fifo->engine_nr && engine; engn++) { - if (fifo->engine[engn].engine == engine) { - gk104_fifo_recover_engn(fifo, engn); - break; - } - } - - spin_unlock_irqrestore(&fifo->base.lock, flags); + u32 type = nvkm_rd32(device, 0x00280c + (unit * 0x10)); + struct nvkm_fault_data info; + + info.inst = (u64)inst << 12; + info.addr = ((u64)vahi << 32) | valo; + info.time = 0; + info.engine = unit; + info.valid = 1; + info.gpc = (type & 0x1f000000) >> 24; + info.client = (type & 0x00001f00) >> 8; + info.access = (type & 0x00000080) >> 7; + info.hub = (type & 0x00000040) >> 6; + info.reason = (type & 0x000000ff); + + nvkm_fifo_fault(&fifo->base, &info); } static const struct nvkm_bitfield gk104_fifo_pbdma_intr_0[] = { @@ -766,6 +866,34 @@ gk104_fifo_fini(struct nvkm_fifo *base) } static int +gk104_fifo_info(struct nvkm_fifo *base, u64 mthd, u64 *data) +{ + struct gk104_fifo *fifo = gk104_fifo(base); + switch (mthd) { + case NV_DEVICE_FIFO_RUNLISTS: + *data = (1ULL << fifo->runlist_nr) - 1; + return 0; + case NV_DEVICE_FIFO_RUNLIST_ENGINES(0)... + NV_DEVICE_FIFO_RUNLIST_ENGINES(63): { + int runl = mthd - NV_DEVICE_FIFO_RUNLIST_ENGINES(0), engn; + if (runl < fifo->runlist_nr) { + unsigned long engm = fifo->runlist[runl].engm; + struct nvkm_engine *engine; + *data = 0; + for_each_set_bit(engn, &engm, fifo->engine_nr) { + if ((engine = fifo->engine[engn].engine)) + *data |= BIT_ULL(engine->subdev.index); + } + return 0; + } + } + return -EINVAL; + default: + return -EINVAL; + } +} + +static int gk104_fifo_oneinit(struct nvkm_fifo *base) { struct gk104_fifo *fifo = gk104_fifo(base); @@ -813,19 +941,18 @@ gk104_fifo_oneinit(struct nvkm_fifo *base) kfree(map); for (i = 0; i < fifo->runlist_nr; i++) { - ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, - 0x8000, 0x1000, false, - &fifo->runlist[i].mem[0]); - if (ret) - return ret; - - ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, - 0x8000, 0x1000, false, - &fifo->runlist[i].mem[1]); - if (ret) - return ret; + for (j = 0; j < ARRAY_SIZE(fifo->runlist[i].mem); j++) { + ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, + fifo->base.nr * 2/* TSG+chan */ * + fifo->func->runlist->size, + 0x1000, false, + &fifo->runlist[i].mem[j]); + if (ret) + return ret; + } init_waitqueue_head(&fifo->runlist[i].wait); + INIT_LIST_HEAD(&fifo->runlist[i].cgrp); INIT_LIST_HEAD(&fifo->runlist[i].chan); } @@ -868,6 +995,9 @@ gk104_fifo_init(struct nvkm_fifo *base) nvkm_wr32(device, 0x002254, 0x10000000 | fifo->user.bar->addr >> 12); + if (fifo->func->init_pbdma_timeout) + fifo->func->init_pbdma_timeout(fifo); + nvkm_wr32(device, 0x002100, 0xffffffff); nvkm_wr32(device, 0x002140, 0x7fffffff); } @@ -894,13 +1024,16 @@ static const struct nvkm_fifo_func gk104_fifo_ = { .dtor = gk104_fifo_dtor, .oneinit = gk104_fifo_oneinit, + .info = gk104_fifo_info, .init = gk104_fifo_init, .fini = gk104_fifo_fini, .intr = gk104_fifo_intr, + .fault = gk104_fifo_fault, .uevent_init = gk104_fifo_uevent_init, .uevent_fini = gk104_fifo_uevent_fini, .recover_chan = gk104_fifo_recover_chan, .class_get = gk104_fifo_class_get, + .class_new = gk104_fifo_class_new, }; int @@ -919,6 +1052,13 @@ gk104_fifo_new_(const struct gk104_fifo_func *func, struct nvkm_device *device, } const struct nvkm_enum +gk104_fifo_fault_access[] = { + { 0x0, "READ" }, + { 0x1, "WRITE" }, + {} +}; + +const struct nvkm_enum gk104_fifo_fault_engine[] = { { 0x00, "GR", NULL, NVKM_ENGINE_GR }, { 0x01, "DISPLAY" }, @@ -1035,14 +1175,13 @@ gk104_fifo_fault_gpcclient[] = { static const struct gk104_fifo_func gk104_fifo = { + .fault.access = gk104_fifo_fault_access, .fault.engine = gk104_fifo_fault_engine, .fault.reason = gk104_fifo_fault_reason, .fault.hubclient = gk104_fifo_fault_hubclient, .fault.gpcclient = gk104_fifo_fault_gpcclient, - .chan = { - &gk104_fifo_gpfifo_oclass, - NULL - }, + .runlist = &gk104_fifo_runlist, + .chan = {{0,0,KEPLER_CHANNEL_GPFIFO_A}, gk104_fifo_gpfifo_new }, }; int diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h index 1579785cf941..d295b81e18d6 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h @@ -3,6 +3,7 @@ #define __GK104_FIFO_H__ #define gk104_fifo(p) container_of((p), struct gk104_fifo, base) #include "priv.h" +struct nvkm_fifo_cgrp; #include <core/enum.h> #include <subdev/mmu.h> @@ -31,6 +32,7 @@ struct gk104_fifo { struct nvkm_memory *mem[2]; int next; wait_queue_head_t wait; + struct list_head cgrp; struct list_head chan; u32 engm; } runlist[16]; @@ -43,14 +45,36 @@ struct gk104_fifo { }; struct gk104_fifo_func { + void (*init_pbdma_timeout)(struct gk104_fifo *); + struct { + const struct nvkm_enum *access; const struct nvkm_enum *engine; const struct nvkm_enum *reason; const struct nvkm_enum *hubclient; const struct nvkm_enum *gpcclient; } fault; - const struct nvkm_fifo_chan_oclass *chan[]; + const struct gk104_fifo_runlist_func { + u8 size; + void (*cgrp)(struct nvkm_fifo_cgrp *, + struct nvkm_memory *, u32 offset); + void (*chan)(struct gk104_fifo_chan *, + struct nvkm_memory *, u32 offset); + } *runlist; + + struct gk104_fifo_user_user { + struct nvkm_sclass user; + int (*ctor)(const struct nvkm_oclass *, void *, u32, + struct nvkm_object **); + } user; + + struct gk104_fifo_chan_user { + struct nvkm_sclass user; + int (*ctor)(struct gk104_fifo *, const struct nvkm_oclass *, + void *, u32, struct nvkm_object **); + } chan; + bool cgrp_force; }; int gk104_fifo_new_(const struct gk104_fifo_func *, struct nvkm_device *, @@ -59,30 +83,23 @@ void gk104_fifo_runlist_insert(struct gk104_fifo *, struct gk104_fifo_chan *); void gk104_fifo_runlist_remove(struct gk104_fifo *, struct gk104_fifo_chan *); void gk104_fifo_runlist_commit(struct gk104_fifo *, int runl); -static inline u64 -gk104_fifo_engine_subdev(int engine) -{ - switch (engine) { - case 0: return (1ULL << NVKM_ENGINE_GR) | - (1ULL << NVKM_ENGINE_SW) | - (1ULL << NVKM_ENGINE_CE2); - case 1: return (1ULL << NVKM_ENGINE_MSPDEC); - case 2: return (1ULL << NVKM_ENGINE_MSPPP); - case 3: return (1ULL << NVKM_ENGINE_MSVLD); - case 4: return (1ULL << NVKM_ENGINE_CE0); - case 5: return (1ULL << NVKM_ENGINE_CE1); - case 6: return (1ULL << NVKM_ENGINE_MSENC); - default: - WARN_ON(1); - return 0; - } -} - +extern const struct nvkm_enum gk104_fifo_fault_access[]; extern const struct nvkm_enum gk104_fifo_fault_engine[]; extern const struct nvkm_enum gk104_fifo_fault_reason[]; extern const struct nvkm_enum gk104_fifo_fault_hubclient[]; extern const struct nvkm_enum gk104_fifo_fault_gpcclient[]; +extern const struct gk104_fifo_runlist_func gk104_fifo_runlist; +void gk104_fifo_runlist_chan(struct gk104_fifo_chan *, + struct nvkm_memory *, u32); + +extern const struct gk104_fifo_runlist_func gk110_fifo_runlist; +void gk110_fifo_runlist_cgrp(struct nvkm_fifo_cgrp *, + struct nvkm_memory *, u32); + +void gk208_fifo_init_pbdma_timeout(struct gk104_fifo *); extern const struct nvkm_enum gm107_fifo_fault_engine[]; +extern const struct gk104_fifo_runlist_func gm107_fifo_runlist; + extern const struct nvkm_enum gp100_fifo_fault_engine[]; #endif diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c index b2f8ab7bf847..ac7655a130fb 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c @@ -22,18 +22,38 @@ * Authors: Ben Skeggs */ #include "gk104.h" +#include "cgrp.h" #include "changk104.h" +#include <core/memory.h> + +#include <nvif/class.h> + +void +gk110_fifo_runlist_cgrp(struct nvkm_fifo_cgrp *cgrp, + struct nvkm_memory *memory, u32 offset) +{ + nvkm_wo32(memory, offset + 0, (cgrp->chan_nr << 26) | (128 << 18) | + (3 << 14) | 0x00002000 | cgrp->id); + nvkm_wo32(memory, offset + 4, 0x00000000); +} + +const struct gk104_fifo_runlist_func +gk110_fifo_runlist = { + .size = 8, + .cgrp = gk110_fifo_runlist_cgrp, + .chan = gk104_fifo_runlist_chan, +}; + static const struct gk104_fifo_func gk110_fifo = { + .fault.access = gk104_fifo_fault_access, .fault.engine = gk104_fifo_fault_engine, .fault.reason = gk104_fifo_fault_reason, .fault.hubclient = gk104_fifo_fault_hubclient, .fault.gpcclient = gk104_fifo_fault_gpcclient, - .chan = { - &gk110_fifo_gpfifo_oclass, - NULL - }, + .runlist = &gk110_fifo_runlist, + .chan = {{0,0,KEPLER_CHANNEL_GPFIFO_B}, gk104_fifo_gpfifo_new }, }; int diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk208.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk208.c index 160617d376e4..5ea7e452cc66 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk208.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk208.c @@ -24,16 +24,28 @@ #include "gk104.h" #include "changk104.h" +#include <nvif/class.h> + +void +gk208_fifo_init_pbdma_timeout(struct gk104_fifo *fifo) +{ + struct nvkm_device *device = fifo->base.engine.subdev.device; + int i; + + for (i = 0; i < fifo->pbdma_nr; i++) + nvkm_wr32(device, 0x04012c + (i * 0x2000), 0x0000ffff); +} + static const struct gk104_fifo_func gk208_fifo = { + .init_pbdma_timeout = gk208_fifo_init_pbdma_timeout, + .fault.access = gk104_fifo_fault_access, .fault.engine = gk104_fifo_fault_engine, .fault.reason = gk104_fifo_fault_reason, .fault.hubclient = gk104_fifo_fault_hubclient, .fault.gpcclient = gk104_fifo_fault_gpcclient, - .chan = { - &gk104_fifo_gpfifo_oclass, - NULL - }, + .runlist = &gk110_fifo_runlist, + .chan = {{0,0,KEPLER_CHANNEL_GPFIFO_A}, gk104_fifo_gpfifo_new }, }; int diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk20a.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk20a.c index be9f5c16ed7d..535a0eb67a5f 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk20a.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk20a.c @@ -22,16 +22,18 @@ #include "gk104.h" #include "changk104.h" +#include <nvif/class.h> + static const struct gk104_fifo_func gk20a_fifo = { + .init_pbdma_timeout = gk208_fifo_init_pbdma_timeout, + .fault.access = gk104_fifo_fault_access, .fault.engine = gk104_fifo_fault_engine, .fault.reason = gk104_fifo_fault_reason, .fault.hubclient = gk104_fifo_fault_hubclient, .fault.gpcclient = gk104_fifo_fault_gpcclient, - .chan = { - &gk104_fifo_gpfifo_oclass, - NULL - }, + .runlist = &gk110_fifo_runlist, + .chan = {{0,0,KEPLER_CHANNEL_GPFIFO_A}, gk104_fifo_gpfifo_new }, }; int diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c index 29c080683b32..79ae19b1db67 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c @@ -24,6 +24,25 @@ #include "gk104.h" #include "changk104.h" +#include <core/gpuobj.h> + +#include <nvif/class.h> + +static void +gm107_fifo_runlist_chan(struct gk104_fifo_chan *chan, + struct nvkm_memory *memory, u32 offset) +{ + nvkm_wo32(memory, offset + 0, chan->base.chid); + nvkm_wo32(memory, offset + 4, chan->base.inst->addr >> 12); +} + +const struct gk104_fifo_runlist_func +gm107_fifo_runlist = { + .size = 8, + .cgrp = gk110_fifo_runlist_cgrp, + .chan = gm107_fifo_runlist_chan, +}; + const struct nvkm_enum gm107_fifo_fault_engine[] = { { 0x01, "DISPLAY" }, @@ -49,14 +68,14 @@ gm107_fifo_fault_engine[] = { static const struct gk104_fifo_func gm107_fifo = { + .init_pbdma_timeout = gk208_fifo_init_pbdma_timeout, + .fault.access = gk104_fifo_fault_access, .fault.engine = gm107_fifo_fault_engine, .fault.reason = gk104_fifo_fault_reason, .fault.hubclient = gk104_fifo_fault_hubclient, .fault.gpcclient = gk104_fifo_fault_gpcclient, - .chan = { - &gk110_fifo_gpfifo_oclass, - NULL - }, + .runlist = &gm107_fifo_runlist, + .chan = {{0,0,KEPLER_CHANNEL_GPFIFO_B}, gk104_fifo_gpfifo_new }, }; int diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm200.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm200.c index b069f785c5d8..49565faa854d 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm200.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm200.c @@ -24,16 +24,18 @@ #include "gk104.h" #include "changk104.h" +#include <nvif/class.h> + static const struct gk104_fifo_func gm200_fifo = { + .init_pbdma_timeout = gk208_fifo_init_pbdma_timeout, + .fault.access = gk104_fifo_fault_access, .fault.engine = gm107_fifo_fault_engine, .fault.reason = gk104_fifo_fault_reason, .fault.hubclient = gk104_fifo_fault_hubclient, .fault.gpcclient = gk104_fifo_fault_gpcclient, - .chan = { - &gm200_fifo_gpfifo_oclass, - NULL - }, + .runlist = &gm107_fifo_runlist, + .chan = {{0,0,MAXWELL_CHANNEL_GPFIFO_A}, gk104_fifo_gpfifo_new }, }; int diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm20b.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm20b.c index 2ed87c2e8299..46736513bd11 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm20b.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm20b.c @@ -22,16 +22,18 @@ #include "gk104.h" #include "changk104.h" +#include <nvif/class.h> + static const struct gk104_fifo_func gm20b_fifo = { + .init_pbdma_timeout = gk208_fifo_init_pbdma_timeout, + .fault.access = gk104_fifo_fault_access, .fault.engine = gm107_fifo_fault_engine, .fault.reason = gk104_fifo_fault_reason, .fault.hubclient = gk104_fifo_fault_hubclient, .fault.gpcclient = gk104_fifo_fault_gpcclient, - .chan = { - &gm200_fifo_gpfifo_oclass, - NULL - }, + .runlist = &gm107_fifo_runlist, + .chan = {{0,0,MAXWELL_CHANNEL_GPFIFO_A}, gk104_fifo_gpfifo_new }, }; int diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c index 41f16cf5a918..e2f8f9087d7c 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c @@ -24,6 +24,8 @@ #include "gk104.h" #include "changk104.h" +#include <nvif/class.h> + const struct nvkm_enum gp100_fifo_fault_engine[] = { { 0x01, "DISPLAY" }, @@ -50,14 +52,15 @@ gp100_fifo_fault_engine[] = { static const struct gk104_fifo_func gp100_fifo = { + .init_pbdma_timeout = gk208_fifo_init_pbdma_timeout, + .fault.access = gk104_fifo_fault_access, .fault.engine = gp100_fifo_fault_engine, .fault.reason = gk104_fifo_fault_reason, .fault.hubclient = gk104_fifo_fault_hubclient, .fault.gpcclient = gk104_fifo_fault_gpcclient, - .chan = { - &gp100_fifo_gpfifo_oclass, - NULL - }, + .runlist = &gm107_fifo_runlist, + .chan = {{0,0,PASCAL_CHANNEL_GPFIFO_A}, gk104_fifo_gpfifo_new }, + .cgrp_force = true, }; int diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp10b.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp10b.c index 4af96c3e69ff..7733bf7c6545 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp10b.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp10b.c @@ -22,16 +22,19 @@ #include "gk104.h" #include "changk104.h" +#include <nvif/class.h> + static const struct gk104_fifo_func gp10b_fifo = { + .init_pbdma_timeout = gk208_fifo_init_pbdma_timeout, + .fault.access = gk104_fifo_fault_access, .fault.engine = gp100_fifo_fault_engine, .fault.reason = gk104_fifo_fault_reason, .fault.hubclient = gk104_fifo_fault_hubclient, .fault.gpcclient = gk104_fifo_fault_gpcclient, - .chan = { - &gp100_fifo_gpfifo_oclass, - NULL - }, + .runlist = &gm107_fifo_runlist, + .chan = {{0,0,PASCAL_CHANNEL_GPFIFO_A}, gk104_fifo_gpfifo_new }, + .cgrp_force = true, }; int 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, -}; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogm200.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogm200.c deleted file mode 100644 index a13315147391..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogm200.c +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright 2015 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs - */ -#include "changk104.h" - -#include <nvif/class.h> - -const struct nvkm_fifo_chan_oclass -gm200_fifo_gpfifo_oclass = { - .base.oclass = MAXWELL_CHANNEL_GPFIFO_A, - .base.minver = 0, - .base.maxver = 0, - .ctor = gk104_fifo_gpfifo_new, -}; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogp100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogp100.c deleted file mode 100644 index 1530a9217aea..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogp100.c +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright 2016 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs - */ -#include "changk104.h" - -#include <nvif/class.h> - -const struct nvkm_fifo_chan_oclass -gp100_fifo_gpfifo_oclass = { - .base.oclass = PASCAL_CHANNEL_GPFIFO_A, - .base.minver = 0, - .base.maxver = 0, - .ctor = gk104_fifo_gpfifo_new, -}; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogv100.c new file mode 100644 index 000000000000..9598853ced56 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogv100.c @@ -0,0 +1,225 @@ +/* + * Copyright 2018 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ +#include "changk104.h" +#include "cgrp.h" + +#include <core/client.h> +#include <core/gpuobj.h> + +#include <nvif/cla06f.h> +#include <nvif/unpack.h> + +static int +gv100_fifo_gpfifo_engine_valid(struct gk104_fifo_chan *chan, bool ce, bool valid) +{ + struct nvkm_subdev *subdev = &chan->base.fifo->engine.subdev; + struct nvkm_device *device = subdev->device; + const u32 mask = ce ? 0x00020000 : 0x00010000; + const u32 data = valid ? mask : 0x00000000; + int ret; + + /* Block runlist to prevent the channel from being rescheduled. */ + mutex_lock(&subdev->mutex); + nvkm_mask(device, 0x002630, BIT(chan->runl), BIT(chan->runl)); + + /* Preempt the channel. */ + ret = gk104_fifo_gpfifo_kick_locked(chan); + if (ret == 0) { + /* Update engine context validity. */ + nvkm_kmap(chan->base.inst); + nvkm_mo32(chan->base.inst, 0x0ac, mask, data); + nvkm_done(chan->base.inst); + } + + /* Resume runlist. */ + nvkm_mask(device, 0x002630, BIT(chan->runl), 0); + mutex_unlock(&subdev->mutex); + return ret; +} + +static int +gv100_fifo_gpfifo_engine_fini(struct nvkm_fifo_chan *base, + struct nvkm_engine *engine, bool suspend) +{ + struct gk104_fifo_chan *chan = gk104_fifo_chan(base); + struct nvkm_gpuobj *inst = chan->base.inst; + int ret; + + if (engine->subdev.index >= NVKM_ENGINE_CE0 && + engine->subdev.index <= NVKM_ENGINE_CE_LAST) + return gk104_fifo_gpfifo_kick(chan); + + ret = gv100_fifo_gpfifo_engine_valid(chan, false, false); + if (ret && suspend) + return ret; + + nvkm_kmap(inst); + nvkm_wo32(inst, 0x0210, 0x00000000); + nvkm_wo32(inst, 0x0214, 0x00000000); + nvkm_done(inst); + return ret; +} + +static int +gv100_fifo_gpfifo_engine_init(struct nvkm_fifo_chan *base, + struct nvkm_engine *engine) +{ + struct gk104_fifo_chan *chan = gk104_fifo_chan(base); + struct nvkm_gpuobj *inst = chan->base.inst; + u64 addr; + + if (engine->subdev.index >= NVKM_ENGINE_CE0 && + engine->subdev.index <= NVKM_ENGINE_CE_LAST) + return 0; + + addr = chan->engn[engine->subdev.index].vma->addr; + nvkm_kmap(inst); + nvkm_wo32(inst, 0x210, lower_32_bits(addr) | 0x00000004); + nvkm_wo32(inst, 0x214, upper_32_bits(addr)); + nvkm_done(inst); + + return gv100_fifo_gpfifo_engine_valid(chan, false, true); +} + +const struct nvkm_fifo_chan_func +gv100_fifo_gpfifo_func = { + .dtor = gk104_fifo_gpfifo_dtor, + .init = gk104_fifo_gpfifo_init, + .fini = gk104_fifo_gpfifo_fini, + .ntfy = gf100_fifo_chan_ntfy, + .engine_ctor = gk104_fifo_gpfifo_engine_ctor, + .engine_dtor = gk104_fifo_gpfifo_engine_dtor, + .engine_init = gv100_fifo_gpfifo_engine_init, + .engine_fini = gv100_fifo_gpfifo_engine_fini, +}; + +static int +gv100_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 = ffs(*runlists) -1, ret, i; + unsigned long engm; + u64 subdevs = 0; + u64 usermem; + + if (!vmm || runlist < 0 || runlist >= fifo->runlist_nr) + return -EINVAL; + *runlists = BIT_ULL(runlist); + + 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); + } + + /* Allocate the channel. */ + if (!(chan = kzalloc(sizeof(*chan), GFP_KERNEL))) + return -ENOMEM; + *pobject = &chan->base.object; + chan->fifo = fifo; + chan->runl = runlist; + INIT_LIST_HEAD(&chan->head); + + ret = nvkm_fifo_chan_ctor(&gv100_fifo_gpfifo_func, &fifo->base, + 0x1000, 0x1000, true, vmm, 0, subdevs, + 1, fifo->user.bar->addr, 0x200, + oclass, &chan->base); + if (ret) + return ret; + + *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); + + nvkm_kmap(fifo->user.mem); + for (i = 0; i < 0x200; i += 4) + nvkm_wo32(fifo->user.mem, usermem + i, 0x00000000); + nvkm_done(fifo->user.mem); + usermem = nvkm_memory_addr(fifo->user.mem) + usermem; + + /* RAMFC */ + nvkm_kmap(chan->base.inst); + nvkm_wo32(chan->base.inst, 0x008, lower_32_bits(usermem)); + nvkm_wo32(chan->base.inst, 0x00c, upper_32_bits(usermem)); + nvkm_wo32(chan->base.inst, 0x010, 0x0000face); + nvkm_wo32(chan->base.inst, 0x030, 0x7ffff902); + nvkm_wo32(chan->base.inst, 0x048, lower_32_bits(ioffset)); + nvkm_wo32(chan->base.inst, 0x04c, upper_32_bits(ioffset) | + (ilength << 16)); + nvkm_wo32(chan->base.inst, 0x084, 0x20400000); + nvkm_wo32(chan->base.inst, 0x094, 0x30000001); + nvkm_wo32(chan->base.inst, 0x0e4, 0x00000020); + nvkm_wo32(chan->base.inst, 0x0e8, chan->base.chid); + nvkm_wo32(chan->base.inst, 0x0f4, 0x00001100); + nvkm_wo32(chan->base.inst, 0x0f8, 0x10003080); + nvkm_mo32(chan->base.inst, 0x218, 0x00000000, 0x00000000); + nvkm_wo32(chan->base.inst, 0x220, 0x020a1000); + nvkm_wo32(chan->base.inst, 0x224, 0x00000000); + nvkm_done(chan->base.inst); + return gv100_fifo_gpfifo_engine_valid(chan, true, true); +} + +int +gv100_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; + 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 " + "runlist %016llx\n", + args->v0.version, args->v0.vmm, args->v0.ioffset, + args->v0.ilength, args->v0.runlist); + return gv100_fifo_gpfifo_new_(fifo, + &args->v0.runlist, + &args->v0.chid, + args->v0.vmm, + args->v0.ioffset, + args->v0.ilength, + oclass, pobject); + } + + return ret; +} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c new file mode 100644 index 000000000000..4e1d159c0ae7 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c @@ -0,0 +1,306 @@ +/* + * Copyright 2018 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ +#include "gk104.h" +#include "cgrp.h" +#include "changk104.h" +#include "user.h" + +#include <core/gpuobj.h> + +#include <nvif/class.h> + +static void +gv100_fifo_runlist_chan(struct gk104_fifo_chan *chan, + struct nvkm_memory *memory, u32 offset) +{ + struct nvkm_memory *usermem = chan->fifo->user.mem; + const u64 user = nvkm_memory_addr(usermem) + (chan->base.chid * 0x200); + const u64 inst = chan->base.inst->addr; + + nvkm_wo32(memory, offset + 0x0, lower_32_bits(user)); + nvkm_wo32(memory, offset + 0x4, upper_32_bits(user)); + nvkm_wo32(memory, offset + 0x8, lower_32_bits(inst) | chan->base.chid); + nvkm_wo32(memory, offset + 0xc, upper_32_bits(inst)); +} + +static void +gv100_fifo_runlist_cgrp(struct nvkm_fifo_cgrp *cgrp, + struct nvkm_memory *memory, u32 offset) +{ + nvkm_wo32(memory, offset + 0x0, (128 << 24) | (3 << 16) | 0x00000001); + nvkm_wo32(memory, offset + 0x4, cgrp->chan_nr); + nvkm_wo32(memory, offset + 0x8, cgrp->id); + nvkm_wo32(memory, offset + 0xc, 0x00000000); +} + +const struct gk104_fifo_runlist_func +gv100_fifo_runlist = { + .size = 16, + .cgrp = gv100_fifo_runlist_cgrp, + .chan = gv100_fifo_runlist_chan, +}; + +static const struct nvkm_enum +gv100_fifo_fault_gpcclient[] = { + { 0x00, "T1_0" }, + { 0x01, "T1_1" }, + { 0x02, "T1_2" }, + { 0x03, "T1_3" }, + { 0x04, "T1_4" }, + { 0x05, "T1_5" }, + { 0x06, "T1_6" }, + { 0x07, "T1_7" }, + { 0x08, "PE_0" }, + { 0x09, "PE_1" }, + { 0x0a, "PE_2" }, + { 0x0b, "PE_3" }, + { 0x0c, "PE_4" }, + { 0x0d, "PE_5" }, + { 0x0e, "PE_6" }, + { 0x0f, "PE_7" }, + { 0x10, "RAST" }, + { 0x11, "GCC" }, + { 0x12, "GPCCS" }, + { 0x13, "PROP_0" }, + { 0x14, "PROP_1" }, + { 0x15, "PROP_2" }, + { 0x16, "PROP_3" }, + { 0x17, "GPM" }, + { 0x18, "LTP_UTLB_0" }, + { 0x19, "LTP_UTLB_1" }, + { 0x1a, "LTP_UTLB_2" }, + { 0x1b, "LTP_UTLB_3" }, + { 0x1c, "LTP_UTLB_4" }, + { 0x1d, "LTP_UTLB_5" }, + { 0x1e, "LTP_UTLB_6" }, + { 0x1f, "LTP_UTLB_7" }, + { 0x20, "RGG_UTLB" }, + { 0x21, "T1_8" }, + { 0x22, "T1_9" }, + { 0x23, "T1_10" }, + { 0x24, "T1_11" }, + { 0x25, "T1_12" }, + { 0x26, "T1_13" }, + { 0x27, "T1_14" }, + { 0x28, "T1_15" }, + { 0x29, "TPCCS_0" }, + { 0x2a, "TPCCS_1" }, + { 0x2b, "TPCCS_2" }, + { 0x2c, "TPCCS_3" }, + { 0x2d, "TPCCS_4" }, + { 0x2e, "TPCCS_5" }, + { 0x2f, "TPCCS_6" }, + { 0x30, "TPCCS_7" }, + { 0x31, "PE_8" }, + { 0x32, "PE_9" }, + { 0x33, "TPCCS_8" }, + { 0x34, "TPCCS_9" }, + { 0x35, "T1_16" }, + { 0x36, "T1_17" }, + { 0x37, "T1_18" }, + { 0x38, "T1_19" }, + { 0x39, "PE_10" }, + { 0x3a, "PE_11" }, + { 0x3b, "TPCCS_10" }, + { 0x3c, "TPCCS_11" }, + { 0x3d, "T1_20" }, + { 0x3e, "T1_21" }, + { 0x3f, "T1_22" }, + { 0x40, "T1_23" }, + { 0x41, "PE_12" }, + { 0x42, "PE_13" }, + { 0x43, "TPCCS_12" }, + { 0x44, "TPCCS_13" }, + { 0x45, "T1_24" }, + { 0x46, "T1_25" }, + { 0x47, "T1_26" }, + { 0x48, "T1_27" }, + { 0x49, "PE_14" }, + { 0x4a, "PE_15" }, + { 0x4b, "TPCCS_14" }, + { 0x4c, "TPCCS_15" }, + { 0x4d, "T1_28" }, + { 0x4e, "T1_29" }, + { 0x4f, "T1_30" }, + { 0x50, "T1_31" }, + { 0x51, "PE_16" }, + { 0x52, "PE_17" }, + { 0x53, "TPCCS_16" }, + { 0x54, "TPCCS_17" }, + { 0x55, "T1_32" }, + { 0x56, "T1_33" }, + { 0x57, "T1_34" }, + { 0x58, "T1_35" }, + { 0x59, "PE_18" }, + { 0x5a, "PE_19" }, + { 0x5b, "TPCCS_18" }, + { 0x5c, "TPCCS_19" }, + { 0x5d, "T1_36" }, + { 0x5e, "T1_37" }, + { 0x5f, "T1_38" }, + { 0x60, "T1_39" }, + {} +}; + +static const struct nvkm_enum +gv100_fifo_fault_hubclient[] = { + { 0x00, "VIP" }, + { 0x01, "CE0" }, + { 0x02, "CE1" }, + { 0x03, "DNISO" }, + { 0x04, "FE" }, + { 0x05, "FECS" }, + { 0x06, "HOST" }, + { 0x07, "HOST_CPU" }, + { 0x08, "HOST_CPU_NB" }, + { 0x09, "ISO" }, + { 0x0a, "MMU" }, + { 0x0b, "NVDEC" }, + { 0x0d, "NVENC1" }, + { 0x0e, "NISO" }, + { 0x0f, "P2P" }, + { 0x10, "PD" }, + { 0x11, "PERF" }, + { 0x12, "PMU" }, + { 0x13, "RASTERTWOD" }, + { 0x14, "SCC" }, + { 0x15, "SCC_NB" }, + { 0x16, "SEC" }, + { 0x17, "SSYNC" }, + { 0x18, "CE2" }, + { 0x19, "XV" }, + { 0x1a, "MMU_NB" }, + { 0x1b, "NVENC0" }, + { 0x1c, "DFALCON" }, + { 0x1d, "SKED" }, + { 0x1e, "AFALCON" }, + { 0x1f, "DONT_CARE" }, + { 0x20, "HSCE0" }, + { 0x21, "HSCE1" }, + { 0x22, "HSCE2" }, + { 0x23, "HSCE3" }, + { 0x24, "HSCE4" }, + { 0x25, "HSCE5" }, + { 0x26, "HSCE6" }, + { 0x27, "HSCE7" }, + { 0x28, "HSCE8" }, + { 0x29, "HSCE9" }, + { 0x2a, "HSHUB" }, + { 0x2b, "PTP_X0" }, + { 0x2c, "PTP_X1" }, + { 0x2d, "PTP_X2" }, + { 0x2e, "PTP_X3" }, + { 0x2f, "PTP_X4" }, + { 0x30, "PTP_X5" }, + { 0x31, "PTP_X6" }, + { 0x32, "PTP_X7" }, + { 0x33, "NVENC2" }, + { 0x34, "VPR_SCRUBBER0" }, + { 0x35, "VPR_SCRUBBER1" }, + { 0x36, "DWBIF" }, + { 0x37, "FBFALCON" }, + { 0x38, "CE_SHIM" }, + { 0x39, "GSP" }, + {} +}; + +static const struct nvkm_enum +gv100_fifo_fault_reason[] = { + { 0x00, "PDE" }, + { 0x01, "PDE_SIZE" }, + { 0x02, "PTE" }, + { 0x03, "VA_LIMIT_VIOLATION" }, + { 0x04, "UNBOUND_INST_BLOCK" }, + { 0x05, "PRIV_VIOLATION" }, + { 0x06, "RO_VIOLATION" }, + { 0x07, "WO_VIOLATION" }, + { 0x08, "PITCH_MASK_VIOLATION" }, + { 0x09, "WORK_CREATION" }, + { 0x0a, "UNSUPPORTED_APERTURE" }, + { 0x0b, "COMPRESSION_FAILURE" }, + { 0x0c, "UNSUPPORTED_KIND" }, + { 0x0d, "REGION_VIOLATION" }, + { 0x0e, "POISONED" }, + { 0x0f, "ATOMIC_VIOLATION" }, + {} +}; + +static const struct nvkm_enum +gv100_fifo_fault_engine[] = { + { 0x01, "DISPLAY" }, + { 0x03, "PTP" }, + { 0x04, "BAR1", NULL, NVKM_SUBDEV_BAR }, + { 0x05, "BAR2", NULL, NVKM_SUBDEV_INSTMEM }, + { 0x06, "PWR_PMU" }, + { 0x08, "IFB", NULL, NVKM_ENGINE_IFB }, + { 0x09, "PERF" }, + { 0x1f, "PHYSICAL" }, + { 0x20, "HOST0" }, + { 0x21, "HOST1" }, + { 0x22, "HOST2" }, + { 0x23, "HOST3" }, + { 0x24, "HOST4" }, + { 0x25, "HOST5" }, + { 0x26, "HOST6" }, + { 0x27, "HOST7" }, + { 0x28, "HOST8" }, + { 0x29, "HOST9" }, + { 0x2a, "HOST10" }, + { 0x2b, "HOST11" }, + { 0x2c, "HOST12" }, + { 0x2d, "HOST13" }, + {} +}; + +static const struct nvkm_enum +gv100_fifo_fault_access[] = { + { 0x0, "VIRT_READ" }, + { 0x1, "VIRT_WRITE" }, + { 0x2, "VIRT_ATOMIC" }, + { 0x3, "VIRT_PREFETCH" }, + { 0x4, "VIRT_ATOMIC_WEAK" }, + { 0x8, "PHYS_READ" }, + { 0x9, "PHYS_WRITE" }, + { 0xa, "PHYS_ATOMIC" }, + { 0xb, "PHYS_PREFETCH" }, + {} +}; + +static const struct gk104_fifo_func +gv100_fifo = { + .init_pbdma_timeout = gk208_fifo_init_pbdma_timeout, + .fault.access = gv100_fifo_fault_access, + .fault.engine = gv100_fifo_fault_engine, + .fault.reason = gv100_fifo_fault_reason, + .fault.hubclient = gv100_fifo_fault_hubclient, + .fault.gpcclient = gv100_fifo_fault_gpcclient, + .runlist = &gv100_fifo_runlist, + .user = {{-1,-1,VOLTA_USERMODE_A }, gv100_fifo_user_new }, + .chan = {{ 0, 0,VOLTA_CHANNEL_GPFIFO_A}, gv100_fifo_gpfifo_new }, + .cgrp_force = true, +}; + +int +gv100_fifo_new(struct nvkm_device *device, int index, struct nvkm_fifo **pfifo) +{ + return gk104_fifo_new_(&gv100_fifo, device, index, 4096, pfifo); +} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h index ae76b1aaccd4..d5acbba293f4 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h @@ -18,16 +18,19 @@ struct nvkm_fifo_chan_oclass; struct nvkm_fifo_func { void *(*dtor)(struct nvkm_fifo *); int (*oneinit)(struct nvkm_fifo *); + int (*info)(struct nvkm_fifo *, u64 mthd, u64 *data); void (*init)(struct nvkm_fifo *); void (*fini)(struct nvkm_fifo *); void (*intr)(struct nvkm_fifo *); + void (*fault)(struct nvkm_fifo *, struct nvkm_fault_data *); void (*pause)(struct nvkm_fifo *, unsigned long *); void (*start)(struct nvkm_fifo *, unsigned long *); void (*uevent_init)(struct nvkm_fifo *); void (*uevent_fini)(struct nvkm_fifo *); void (*recover_chan)(struct nvkm_fifo *, int chid); - int (*class_get)(struct nvkm_fifo *, int index, - const struct nvkm_fifo_chan_oclass **); + int (*class_get)(struct nvkm_fifo *, int index, struct nvkm_oclass *); + int (*class_new)(struct nvkm_fifo *, const struct nvkm_oclass *, + void *, u32, struct nvkm_object **); const struct nvkm_fifo_chan_oclass *chan[]; }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/user.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/user.h new file mode 100644 index 000000000000..ed840921ebe8 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/user.h @@ -0,0 +1,6 @@ +#ifndef __NVKM_FIFO_USER_H__ +#define __NVKM_FIFO_USER_H__ +#include "priv.h" +int gv100_fifo_user_new(const struct nvkm_oclass *, void *, u32, + struct nvkm_object **); +#endif diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk110.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/usergv100.c index a9aa69c82e8e..3dc3b8b312de 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk110.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/usergv100.c @@ -1,5 +1,5 @@ /* - * Copyright 2016 Red Hat Inc. + * Copyright 2018 Red Hat Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -18,17 +18,28 @@ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs */ -#include "changk104.h" +#include "user.h" -#include <nvif/class.h> +static int +gv100_fifo_user_map(struct nvkm_object *object, void *argv, u32 argc, + enum nvkm_object_map *type, u64 *addr, u64 *size) +{ + struct nvkm_device *device = object->engine->subdev.device; + *addr = 0x810000 + device->func->resource_addr(device, 0); + *size = 0x010000; + *type = NVKM_OBJECT_MAP_IO; + return 0; +} -const struct nvkm_fifo_chan_oclass -gk110_fifo_gpfifo_oclass = { - .base.oclass = KEPLER_CHANNEL_GPFIFO_B, - .base.minver = 0, - .base.maxver = 0, - .ctor = gk104_fifo_gpfifo_new, +static const struct nvkm_object_func +gv100_fifo_user = { + .map = gv100_fifo_user_map, }; + +int +gv100_fifo_user_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, + struct nvkm_object **pobject) +{ + return nvkm_object_new_(&gv100_fifo_user, oclass, argv, argc, pobject); +} |