aboutsummaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/nouveau/nvkm/engine
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2015-08-20 14:54:19 +1000
committerBen Skeggs <bskeggs@redhat.com>2015-08-28 12:40:40 +1000
commit8f0649b5c6e70ec18122255690e39f010c12a614 (patch)
treec6d001b9db9fdc0db86488d79dec2a25d0d2bf0f /drivers/gpu/drm/nouveau/nvkm/engine
parent9a65a38c456ebac97f0498e85fe26f6d26fe3936 (diff)
drm/nouveau/fifo: convert user classes to new-style nvkm_object
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/nouveau/nvkm/engine')
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/ce/gt215.c3
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/cipher/g84.c7
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv04.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/dma/base.c106
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c108
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c477
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.h44
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/chang84.c327
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/changf100.h25
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/changk104.h32
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv04.h24
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv50.c293
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv50.h47
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmag84.c102
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv04.c216
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv10.c61
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv17.c64
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv40.c240
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv50.c88
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/g84.c13
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c61
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.h5
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c114
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h42
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm204.c10
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifog84.c90
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c374
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c407
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogm204.c10
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifonv50.c76
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c40
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.h9
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv10.c19
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv17.c27
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv40.c27
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.c15
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.h1
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h1
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c19
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/nv20.c3
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/nv40.c3
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/nv50.c24
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv31.c4
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv44.c5
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/sec/g98.c3
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/sw/nv50.c4
46 files changed, 1967 insertions, 1705 deletions
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/ce/gt215.c b/drivers/gpu/drm/nouveau/nvkm/engine/ce/gt215.c
index a632570f20e1..1a15b8d6fece 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/ce/gt215.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/ce/gt215.c
@@ -85,7 +85,8 @@ gt215_ce_intr(struct nvkm_falcon *ce, struct nvkm_fifo_chan *chan)
nvkm_error(subdev, "DISPATCH_ERROR %04x [%s] ch %d [%010llx %s] "
"subc %d mthd %04x data %08x\n", ssta,
en ? en->name : "", chan ? chan->chid : -1,
- chan ? chan->inst : 0, nvkm_client_name(chan),
+ chan ? chan->inst->addr : 0,
+ chan ? chan->object.client->name : "unknown",
subc, mthd, data);
}
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/cipher/g84.c b/drivers/gpu/drm/nouveau/nvkm/engine/cipher/g84.c
index 62cdd1e50a95..74bea4397bf4 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/cipher/g84.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/cipher/g84.c
@@ -121,9 +121,10 @@ g84_cipher_intr(struct nvkm_subdev *subdev)
if (stat) {
nvkm_snprintbf(msg, sizeof(msg), g84_cipher_intr_mask, stat);
nvkm_error(subdev, "%08x [%s] ch %d [%010llx %s] "
- "mthd %04x data %08x\n",
- stat, msg, chan ? chan->chid : -1, (u64)inst << 12,
- nvkm_client_name(chan), mthd, data);
+ "mthd %04x data %08x\n", stat, msg,
+ chan ? chan->chid : -1, (u64)inst << 12,
+ chan ? chan->object.client->name : "unknown",
+ mthd, data);
}
nvkm_fifo_chan_put(fifo, flags, &chan);
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv04.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv04.c
index 2d9b81fb83a2..62d3fb66d0ec 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv04.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv04.c
@@ -21,7 +21,7 @@
*
* Authors: Ben Skeggs
*/
-#define nv04_disp_root(p) container_of((p), struct nv04_disp_root, object);
+#define nv04_disp_root(p) container_of((p), struct nv04_disp_root, object)
#include "priv.h"
#include <core/client.h>
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/dma/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/dma/base.c
index 57f6eca078ef..1a377201949c 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/dma/base.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/dma/base.c
@@ -24,6 +24,7 @@
#include "priv.h"
#include <core/client.h>
+#include <engine/fifo.h>
#include <nvif/class.h>
@@ -88,11 +89,19 @@ nvkm_dma_oclass_base = {
.ctor = nvkm_dma_oclass_new,
};
+static int
+nvkm_dma_oclass_fifo_new(const struct nvkm_oclass *oclass, void *data, u32 size,
+ struct nvkm_object **pobject)
+{
+ return nvkm_dma_oclass_new(oclass->engine->subdev.device,
+ oclass, data, size, pobject);
+}
+
static const struct nvkm_sclass
nvkm_dma_sclass[] = {
- { 0, 0, NV_DMA_FROM_MEMORY },
- { 0, 0, NV_DMA_TO_MEMORY },
- { 0, 0, NV_DMA_IN_MEMORY },
+ { 0, 0, NV_DMA_FROM_MEMORY, NULL, nvkm_dma_oclass_fifo_new },
+ { 0, 0, NV_DMA_TO_MEMORY, NULL, nvkm_dma_oclass_fifo_new },
+ { 0, 0, NV_DMA_IN_MEMORY, NULL, nvkm_dma_oclass_fifo_new },
};
static int
@@ -110,89 +119,21 @@ nvkm_dma_oclass_base_get(struct nvkm_oclass *sclass, int index,
return count;
}
-static const struct nvkm_engine_func
-nvkm_dma = {
- .base.sclass = nvkm_dma_oclass_base_get,
-};
-
-#include <core/gpuobj.h>
-
-static struct nvkm_oclass empty = {
- .ofuncs = &(struct nvkm_ofuncs) {
- .dtor = nvkm_object_destroy,
- .init = _nvkm_object_init,
- .fini = _nvkm_object_fini,
- },
-};
-
static int
-nvkm_dmaobj_compat_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
- struct nvkm_oclass *oclass, void *data, u32 size,
- struct nvkm_object **pobject)
-{
- struct nvkm_oclass hack = {
- .base.oclass = oclass->handle,
- .client = nvkm_client(parent),
- .parent = parent,
- .engine = nv_engine(engine),
- };
- struct nvkm_dma *dma = (void *)engine;
- struct nvkm_dma_impl *impl = (void *)dma->engine.subdev.object.oclass;
- struct nvkm_dmaobj *dmaobj = NULL;
- struct nvkm_gpuobj *gpuobj;
- int ret;
-
- ret = impl->class_new(dma, &hack, data, size, &dmaobj);
- if (dmaobj)
- *pobject = &dmaobj->object;
- if (ret)
- return ret;
-
- gpuobj = (void *)nv_pclass(parent, NV_GPUOBJ_CLASS);
-
- ret = dmaobj->func->bind(dmaobj, gpuobj, 16, &gpuobj);
- nvkm_object_ref(NULL, pobject);
- if (ret)
- return ret;
-
- ret = nvkm_object_create(parent, engine, &empty, 0, pobject);
- if (ret)
- return ret;
-
- gpuobj->object.parent = *pobject;
- gpuobj->object.engine = &dma->engine;
- gpuobj->object.oclass = oclass;
- gpuobj->object.pclass = NV_GPUOBJ_CLASS;
-#if CONFIG_NOUVEAU_DEBUG >= NV_DBG_PARANOIA
- gpuobj->object._magic = NVKM_OBJECT_MAGIC;
-#endif
- *pobject = &gpuobj->object;
- return 0;
-}
-
-static void
-nvkm_dmaobj_compat_dtor(struct nvkm_object *object)
+nvkm_dma_oclass_fifo_get(struct nvkm_oclass *oclass, int index)
{
- struct nvkm_object *parent = object->parent;
- struct nvkm_gpuobj *gpuobj = (void *)object;
- nvkm_gpuobj_del(&gpuobj);
- nvkm_object_ref(NULL, &parent);
+ const int count = ARRAY_SIZE(nvkm_dma_sclass);
+ if (index < count) {
+ oclass->base = nvkm_dma_sclass[index];
+ return index;
+ }
+ return count;
}
-static struct nvkm_ofuncs
-nvkm_dmaobj_compat_ofuncs = {
- .ctor = nvkm_dmaobj_compat_ctor,
- .dtor = nvkm_dmaobj_compat_dtor,
- .init = _nvkm_object_init,
- .fini = _nvkm_object_fini,
-};
-
-static struct nvkm_oclass
-nvkm_dma_compat_sclass[] = {
- { NV_DMA_FROM_MEMORY, &nvkm_dmaobj_compat_ofuncs },
- { NV_DMA_TO_MEMORY, &nvkm_dmaobj_compat_ofuncs },
- { NV_DMA_IN_MEMORY, &nvkm_dmaobj_compat_ofuncs },
- {}
+static const struct nvkm_engine_func
+nvkm_dma = {
+ .base.sclass = nvkm_dma_oclass_base_get,
+ .fifo.sclass = nvkm_dma_oclass_fifo_get,
};
int
@@ -209,7 +150,6 @@ _nvkm_dma_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
if (ret)
return ret;
- dmaeng->engine.sclass = nvkm_dma_compat_sclass;
dmaeng->engine.func = &nvkm_dma;
return 0;
}
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c
index 510de3c2d2e4..b693127d80e1 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c
@@ -44,12 +44,13 @@ nvkm_fifo_chan_put(struct nvkm_fifo *fifo, unsigned long flags,
struct nvkm_fifo_chan *
nvkm_fifo_chan_inst(struct nvkm_fifo *fifo, u64 inst, unsigned long *rflags)
{
+ struct nvkm_fifo_chan *chan;
unsigned long flags;
- int i;
spin_lock_irqsave(&fifo->lock, flags);
- for (i = fifo->min; i < fifo->max; i++) {
- struct nvkm_fifo_chan *chan = (void *)fifo->channel[i];
- if (chan && chan->inst == inst) {
+ list_for_each_entry(chan, &fifo->chan, head) {
+ if (chan->inst->addr == inst) {
+ list_del(&chan->head);
+ list_add(&chan->head, &fifo->chan);
*rflags = flags;
return chan;
}
@@ -61,46 +62,22 @@ nvkm_fifo_chan_inst(struct nvkm_fifo *fifo, u64 inst, unsigned long *rflags)
struct nvkm_fifo_chan *
nvkm_fifo_chan_chid(struct nvkm_fifo *fifo, int chid, unsigned long *rflags)
{
+ struct nvkm_fifo_chan *chan;
unsigned long flags;
spin_lock_irqsave(&fifo->lock, flags);
- if (fifo->channel[chid]) {
- *rflags = flags;
- return (void *)fifo->channel[chid];
+ list_for_each_entry(chan, &fifo->chan, head) {
+ if (chan->chid == chid) {
+ list_del(&chan->head);
+ list_add(&chan->head, &fifo->chan);
+ *rflags = flags;
+ return chan;
+ }
}
spin_unlock_irqrestore(&fifo->lock, flags);
return NULL;
}
static int
-nvkm_fifo_chid(struct nvkm_fifo *fifo, struct nvkm_object *object)
-{
- int engidx = nv_hclass(fifo) & 0xff;
-
- while (object && object->parent) {
- if ( nv_iclass(object->parent, NV_ENGCTX_CLASS) &&
- (nv_hclass(object->parent) & 0xff) == engidx)
- return nvkm_fifo_chan(object)->chid;
- object = object->parent;
- }
-
- return -1;
-}
-
-const char *
-nvkm_client_name_for_fifo_chid(struct nvkm_fifo *fifo, u32 chid)
-{
- struct nvkm_fifo_chan *chan = NULL;
- unsigned long flags;
-
- spin_lock_irqsave(&fifo->lock, flags);
- if (chid >= fifo->min && chid <= fifo->max)
- chan = (void *)fifo->channel[chid];
- spin_unlock_irqrestore(&fifo->lock, flags);
-
- return nvkm_client_name(chan);
-}
-
-static int
nvkm_fifo_event_ctor(struct nvkm_object *object, void *data, u32 size,
struct nvkm_notify *notify)
{
@@ -144,21 +121,62 @@ nvkm_fifo_uevent(struct nvkm_fifo *fifo)
nvkm_event_send(&fifo->uevent, 1, 0, &rep, sizeof(rep));
}
+static int
+nvkm_fifo_class_new(struct nvkm_device *device,
+ const struct nvkm_oclass *oclass, void *data, u32 size,
+ struct nvkm_object **pobject)
+{
+ const struct nvkm_fifo_chan_oclass *sclass = oclass->engn;
+ struct nvkm_fifo *fifo = nvkm_fifo(oclass->engine);
+ return sclass->ctor(fifo, oclass, data, size, pobject);
+}
+
+static const struct nvkm_device_oclass
+nvkm_fifo_class = {
+ .ctor = nvkm_fifo_class_new,
+};
+
+static int
+nvkm_fifo_class_get(struct nvkm_oclass *oclass, int index,
+ const struct nvkm_device_oclass **class)
+{
+ struct nvkm_fifo *fifo = nvkm_fifo(oclass->engine);
+ const struct nvkm_fifo_chan_oclass *sclass;
+ int c = 0;
+
+ while ((sclass = fifo->func->chan[c])) {
+ if (c++ == index) {
+ oclass->base = sclass->base;
+ oclass->engn = sclass;
+ *class = &nvkm_fifo_class;
+ return 0;
+ }
+ }
+
+ return c;
+}
+
void
nvkm_fifo_destroy(struct nvkm_fifo *fifo)
{
- kfree(fifo->channel);
nvkm_event_fini(&fifo->uevent);
nvkm_event_fini(&fifo->cevent);
nvkm_engine_destroy(&fifo->engine);
}
+static const struct nvkm_engine_func
+nvkm_fifo_func = {
+ .base.sclass = nvkm_fifo_class_get,
+};
+
int
nvkm_fifo_create_(struct nvkm_object *parent, struct nvkm_object *engine,
struct nvkm_oclass *oclass,
int min, int max, int length, void **pobject)
{
struct nvkm_fifo *fifo;
+ int nr = max + 1;
+ int cnt = nr - min;
int ret;
ret = nvkm_engine_create_(parent, engine, oclass, true, "PFIFO",
@@ -167,17 +185,21 @@ nvkm_fifo_create_(struct nvkm_object *parent, struct nvkm_object *engine,
if (ret)
return ret;
- fifo->min = min;
- fifo->max = max;
- fifo->channel = kzalloc(sizeof(*fifo->channel) * (max + 1), GFP_KERNEL);
- if (!fifo->channel)
- return -ENOMEM;
+ fifo->engine.func = &nvkm_fifo_func;
+ INIT_LIST_HEAD(&fifo->chan);
+
+ fifo->nr = nr;
+ if (WARN_ON(fifo->nr > NVKM_FIFO_CHID_NR)) {
+ fifo->nr = NVKM_FIFO_CHID_NR;
+ cnt = fifo->nr - min;
+ }
+ bitmap_fill(fifo->mask, NVKM_FIFO_CHID_NR);
+ bitmap_clear(fifo->mask, min, cnt);
ret = nvkm_event_init(&nvkm_fifo_event_func, 1, 1, &fifo->cevent);
if (ret)
return ret;
- fifo->chid = nvkm_fifo_chid;
spin_lock_init(&fifo->lock);
return 0;
}
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c
index cc401ae1d6a5..2735c2df2218 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c
@@ -24,139 +24,472 @@
#include "chan.h"
#include <core/client.h>
+#include <core/oproxy.h>
+#include <subdev/mmu.h>
#include <engine/dma.h>
-#include <nvif/class.h>
+struct nvkm_fifo_chan_object {
+ struct nvkm_oproxy oproxy;
+ struct nvkm_fifo_chan *chan;
+ int hash;
+};
-int
-_nvkm_fifo_channel_ntfy(struct nvkm_object *object, u32 type,
- struct nvkm_event **event)
+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 = &chan->engn[engine->subdev.index];
+ const char *name = nvkm_subdev_name[engine->subdev.index];
+ int ret = 0;
+
+ if (--engn->usecount)
+ return 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 = &chan->engn[engine->subdev.index];
+ const char *name = nvkm_subdev_name[engine->subdev.index];
+ int ret;
+
+ if (engn->usecount++)
+ return 0;
+
+ 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 = &chan->engn[engine->subdev.index];
+
+ 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_ref(NULL, &engn->object);
+ if (chan->vm)
+ atomic_dec(&chan->vm->engref[engine->subdev.index]);
+ }
+}
+
+static const struct nvkm_oproxy_func
+nvkm_fifo_chan_child_func = {
+ .dtor[0] = nvkm_fifo_chan_child_del,
+ .init[0] = nvkm_fifo_chan_child_init,
+ .fini[0] = nvkm_fifo_chan_child_fini,
+};
+
+static int
+nvkm_fifo_chan_child_old(const struct nvkm_oclass *oclass,
+ void *data, u32 size, struct nvkm_object **pobject)
{
- struct nvkm_fifo *fifo = (void *)object->engine;
- switch (type) {
- case G82_CHANNEL_DMA_V0_NTFY_UEVENT:
- if (nv_mclass(object) >= G82_CHANNEL_DMA) {
- *event = &fifo->uevent;
- return 0;
+ struct nvkm_fifo_chan *chan = nvkm_fifo_chan(oclass->parent);
+ struct nvkm_object *parent = &chan->object;
+ struct nvkm_engine *engine = oclass->engine;
+ struct nvkm_oclass *eclass = (void *)oclass->priv;
+ struct nvkm_object *engctx = NULL;
+ struct nvkm_fifo_chan_object *object;
+ struct nvkm_fifo_engn *engn = &chan->engn[engine->subdev.index];
+ int ret;
+
+ if (!(object = kzalloc(sizeof(*object), GFP_KERNEL)))
+ return -ENOMEM;
+ nvkm_oproxy_ctor(&nvkm_fifo_chan_child_func, oclass, &object->oproxy);
+ *pobject = &object->oproxy.base;
+ object->chan = chan;
+
+ if (!engn->refcount++) {
+ if (chan->vm)
+ atomic_inc(&chan->vm->engref[engine->subdev.index]);
+ if (engine->cclass && !engn->object) {
+ ret = nvkm_object_old(parent, &engine->subdev.object,
+ engine->cclass, NULL, 0,
+ &engn->object);
+ if (ret) {
+ nvkm_engine_unref(&engine);
+ return ret;
+ }
+ } else {
+ nvkm_object_ref(parent, &engn->object);
}
- break;
- default:
- break;
+
+ if (chan->func->engine_ctor) {
+ ret = chan->func->engine_ctor(chan, engine,
+ engn->object);
+ if (ret)
+ return ret;
+ }
+ }
+ nvkm_object_ref(engn->object, &engctx);
+
+ ret = nvkm_object_old(engctx, &engine->subdev.object, eclass,
+ data, size, &object->oproxy.object);
+ nvkm_object_ref(NULL, &engctx);
+ if (ret)
+ return ret;
+
+ object->oproxy.object->handle = oclass->handle;
+
+ if (chan->func->object_ctor) {
+ object->hash =
+ chan->func->object_ctor(chan, object->oproxy.object);
+ if (object->hash < 0)
+ return object->hash;
}
+
+ return 0;
+}
+
+static int
+nvkm_fifo_chan_child_new(const struct nvkm_oclass *oclass, void *data, u32 size,
+ struct nvkm_object **pobject)
+{
+ struct nvkm_engine *engine = oclass->engine;
+ struct nvkm_fifo_chan *chan = nvkm_fifo_chan(oclass->parent);
+ struct nvkm_fifo_engn *engn = &chan->engn[engine->subdev.index];
+ struct nvkm_fifo_chan_object *object;
+ int ret = 0;
+
+ if (!(object = kzalloc(sizeof(*object), GFP_KERNEL)))
+ return -ENOMEM;
+ nvkm_oproxy_ctor(&nvkm_fifo_chan_child_func, oclass, &object->oproxy);
+ object->chan = chan;
+ *pobject = &object->oproxy.base;
+
+ if (!engn->refcount++) {
+ struct nvkm_oclass cclass = {
+ .client = oclass->client,
+ .engine = oclass->engine,
+ };
+
+ if (chan->vm)
+ atomic_inc(&chan->vm->engref[engine->subdev.index]);
+
+ 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,
+ .engn = oclass->engn,
+ .handle = oclass->handle,
+ .object = oclass->object,
+ .client = oclass->client,
+ .parent = engn->object ?
+ engn->object :
+ oclass->parent,
+ .engine = engine,
+ }, data, size, &object->oproxy.object);
+ if (ret)
+ return ret;
+
+ if (chan->func->object_ctor) {
+ object->hash =
+ chan->func->object_ctor(chan, object->oproxy.object);
+ if (object->hash < 0)
+ return object->hash;
+ }
+
+ return 0;
+}
+
+static int
+nvkm_fifo_chan_child_get(struct nvkm_object *object, int index,
+ struct nvkm_oclass *oclass)
+{
+ struct nvkm_fifo_chan *chan = nvkm_fifo_chan(object);
+ struct nvkm_fifo *fifo = chan->fifo;
+ struct nvkm_device *device = fifo->engine.subdev.device;
+ struct nvkm_engine *engine;
+ u64 mask = chan->engines;
+ int ret, i, c;
+
+ for (; c = 0, i = __ffs64(mask), mask; mask &= ~(1ULL << i)) {
+ if ((engine = nvkm_device_engine(device, i)) &&
+ !engine->func) {
+ struct nvkm_oclass *sclass = engine->sclass;
+ int c = 0;
+ while (sclass && sclass->ofuncs) {
+ if (c++ == index) {
+ oclass->base.oclass = sclass->handle;
+ oclass->base.minver = -2;
+ oclass->base.maxver = -2;
+ oclass->ctor = nvkm_fifo_chan_child_old;
+ oclass->priv = sclass;
+ oclass->engine = engine;
+ return 0;
+ }
+ sclass++;
+ }
+ index -= c;
+ continue;
+ }
+
+ if (!(engine = nvkm_device_engine(device, i)))
+ continue;
+ oclass->engine = engine;
+ oclass->base.oclass = 0;
+
+ if (engine->func->fifo.sclass) {
+ ret = engine->func->fifo.sclass(oclass, index);
+ if (oclass->base.oclass) {
+ if (!oclass->base.ctor)
+ oclass->base.ctor = nvkm_object_new;
+ oclass->ctor = nvkm_fifo_chan_child_new;
+ return 0;
+ }
+
+ index -= ret;
+ continue;
+ }
+
+ while (engine->func->sclass[c].oclass) {
+ if (c++ == index) {
+ oclass->base = engine->func->sclass[index];
+ if (!oclass->base.ctor)
+ oclass->base.ctor = nvkm_object_new;
+ oclass->ctor = nvkm_fifo_chan_child_new;
+ return 0;
+ }
+ }
+ index -= c;
+ }
+
return -EINVAL;
}
-int
-_nvkm_fifo_channel_map(struct nvkm_object *object, u64 *addr, u32 *size)
+static int
+nvkm_fifo_chan_ntfy(struct nvkm_object *object, u32 type,
+ struct nvkm_event **pevent)
{
- struct nvkm_fifo_chan *chan = (void *)object;
+ struct nvkm_fifo_chan *chan = nvkm_fifo_chan(object);
+ if (chan->func->ntfy)
+ return chan->func->ntfy(chan, type, pevent);
+ return -ENODEV;
+}
+
+static int
+nvkm_fifo_chan_map(struct nvkm_object *object, u64 *addr, u32 *size)
+{
+ struct nvkm_fifo_chan *chan = nvkm_fifo_chan(object);
*addr = chan->addr;
*size = chan->size;
return 0;
}
-u32
-_nvkm_fifo_channel_rd32(struct nvkm_object *object, u64 addr)
+static int
+nvkm_fifo_chan_rd32(struct nvkm_object *object, u64 addr, u32 *data)
{
- struct nvkm_fifo_chan *chan = (void *)object;
+ struct nvkm_fifo_chan *chan = nvkm_fifo_chan(object);
if (unlikely(!chan->user)) {
chan->user = ioremap(chan->addr, chan->size);
- if (WARN_ON_ONCE(chan->user == NULL))
- return 0;
+ if (!chan->user)
+ return -ENOMEM;
}
- return ioread32_native(chan->user + addr);
+ if (unlikely(addr + 4 > chan->size))
+ return -EINVAL;
+ *data = ioread32_native(chan->user + addr);
+ return 0;
}
-void
-_nvkm_fifo_channel_wr32(struct nvkm_object *object, u64 addr, u32 data)
+static int
+nvkm_fifo_chan_wr32(struct nvkm_object *object, u64 addr, u32 data)
{
- struct nvkm_fifo_chan *chan = (void *)object;
+ struct nvkm_fifo_chan *chan = nvkm_fifo_chan(object);
if (unlikely(!chan->user)) {
chan->user = ioremap(chan->addr, chan->size);
- if (WARN_ON_ONCE(chan->user == NULL))
- return;
+ if (!chan->user)
+ return -ENOMEM;
}
+ if (unlikely(addr + 4 > chan->size))
+ return -EINVAL;
iowrite32_native(data, chan->user + addr);
+ return 0;
+}
+
+static int
+nvkm_fifo_chan_fini(struct nvkm_object *object, bool suspend)
+{
+ struct nvkm_fifo_chan *chan = nvkm_fifo_chan(object);
+ chan->func->fini(chan);
+ return 0;
}
-void
-nvkm_fifo_channel_destroy(struct nvkm_fifo_chan *chan)
+static int
+nvkm_fifo_chan_init(struct nvkm_object *object)
{
- struct nvkm_fifo *fifo = (void *)nv_object(chan)->engine;
+ struct nvkm_fifo_chan *chan = nvkm_fifo_chan(object);
+ chan->func->init(chan);
+ return 0;
+}
+
+static void *
+nvkm_fifo_chan_dtor(struct nvkm_object *object)
+{
+ struct nvkm_fifo_chan *chan = nvkm_fifo_chan(object);
+ struct nvkm_fifo *fifo = chan->fifo;
+ void *data = chan->func->dtor(chan);
unsigned long flags;
+ spin_lock_irqsave(&fifo->lock, flags);
+ if (!list_empty(&chan->head)) {
+ __clear_bit(chan->chid, fifo->mask);
+ list_del(&chan->head);
+ }
+ spin_unlock_irqrestore(&fifo->lock, flags);
+
if (chan->user)
iounmap(chan->user);
- spin_lock_irqsave(&fifo->lock, flags);
- fifo->channel[chan->chid] = NULL;
- spin_unlock_irqrestore(&fifo->lock, flags);
+ nvkm_vm_ref(NULL, &chan->vm, NULL);
- nvkm_gpuobj_del(&chan->pushgpu);
- nvkm_namedb_destroy(&chan->namedb);
+ nvkm_gpuobj_del(&chan->push);
+ nvkm_gpuobj_del(&chan->inst);
+ return data;
}
-void
-_nvkm_fifo_channel_dtor(struct nvkm_object *object)
-{
- struct nvkm_fifo_chan *chan = (void *)object;
- nvkm_fifo_channel_destroy(chan);
-}
+const struct nvkm_object_func
+nvkm_fifo_chan_func = {
+ .dtor = nvkm_fifo_chan_dtor,
+ .init = nvkm_fifo_chan_init,
+ .fini = nvkm_fifo_chan_fini,
+ .ntfy = nvkm_fifo_chan_ntfy,
+ .map = nvkm_fifo_chan_map,
+ .rd32 = nvkm_fifo_chan_rd32,
+ .wr32 = nvkm_fifo_chan_wr32,
+ .sclass = nvkm_fifo_chan_child_get,
+};
int
-nvkm_fifo_channel_create_(struct nvkm_object *parent,
- struct nvkm_object *engine,
- struct nvkm_oclass *oclass,
- int bar, u32 addr, u32 size, u64 pushbuf,
- u64 engmask, int len, void **ptr)
+nvkm_fifo_chan_ctor(const struct nvkm_fifo_chan_func *func,
+ struct nvkm_fifo *fifo, u32 size, u32 align, bool zero,
+ u64 vm, u64 push, u64 engines, int bar, u32 base, u32 user,
+ const struct nvkm_oclass *oclass,
+ struct nvkm_fifo_chan *chan)
{
- struct nvkm_client *client = nvkm_client(parent);
- struct nvkm_fifo *fifo = (void *)engine;
- struct nvkm_fifo_base *base = (void *)parent;
- struct nvkm_fifo_chan *chan;
- struct nvkm_subdev *subdev = &fifo->engine.subdev;
- struct nvkm_device *device = subdev->device;
+ struct nvkm_client *client = oclass->client;
+ struct nvkm_device *device = fifo->engine.subdev.device;
+ struct nvkm_mmu *mmu = device->mmu;
struct nvkm_dmaobj *dmaobj;
unsigned long flags;
int ret;
- /* create base object class */
- ret = nvkm_namedb_create_(parent, engine, oclass, 0, NULL,
- engmask, len, ptr);
- chan = *ptr;
+ nvkm_object_ctor(&nvkm_fifo_chan_func, oclass, &chan->object);
+ chan->func = func;
+ chan->fifo = fifo;
+ chan->engines = engines;
+ INIT_LIST_HEAD(&chan->head);
+
+ /* instance memory */
+ ret = nvkm_gpuobj_new(device, size, align, zero, NULL, &chan->inst);
if (ret)
return ret;
- /* validate dma object representing push buffer */
- if (pushbuf) {
- dmaobj = nvkm_dma_search(device->dma, client, pushbuf);
+ /* allocate push buffer ctxdma instance */
+ if (push) {
+ dmaobj = nvkm_dma_search(device->dma, oclass->client, push);
if (!dmaobj)
return -ENOENT;
- ret = nvkm_object_bind(&dmaobj->object, &base->gpuobj, 16,
- &chan->pushgpu);
+ ret = nvkm_object_bind(&dmaobj->object, chan->inst, -16,
+ &chan->push);
if (ret)
return ret;
}
- /* find a free fifo channel */
- spin_lock_irqsave(&fifo->lock, flags);
- for (chan->chid = fifo->min; chan->chid < fifo->max; chan->chid++) {
- if (!fifo->channel[chan->chid]) {
- fifo->channel[chan->chid] = nv_object(chan);
- break;
+ /* channel address space */
+ if (!vm && mmu) {
+ if (!client->vm || client->vm->mmu == mmu) {
+ ret = nvkm_vm_ref(client->vm, &chan->vm, NULL);
+ if (ret)
+ return ret;
+ } else {
+ return -EINVAL;
}
+ } else {
+ return -ENOENT;
}
- spin_unlock_irqrestore(&fifo->lock, flags);
- if (chan->chid == fifo->max) {
- nvkm_error(subdev, "no free channels\n");
+ /* allocate channel id */
+ spin_lock_irqsave(&fifo->lock, flags);
+ chan->chid = find_first_zero_bit(fifo->mask, NVKM_FIFO_CHID_NR);
+ if (chan->chid >= NVKM_FIFO_CHID_NR) {
+ spin_unlock_irqrestore(&fifo->lock, flags);
return -ENOSPC;
}
+ list_add(&chan->head, &fifo->chan);
+ __set_bit(chan->chid, fifo->mask);
+ spin_unlock_irqrestore(&fifo->lock, flags);
+ /* determine address of this channel's user registers */
chan->addr = nv_device_resource_start(device, bar) +
- addr + size * chan->chid;
- chan->size = size;
+ base + user * chan->chid;
+ chan->size = user;
+
nvkm_event_send(&fifo->cevent, 1, 0, NULL, 0);
return 0;
}
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.h
index 63209bc8856b..bfec12dbf492 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.h
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.h
@@ -2,27 +2,31 @@
#define __NVKM_FIFO_CHAN_H__
#include "priv.h"
-#define nvkm_fifo_channel_create(p,e,c,b,a,s,n,m,d) \
- nvkm_fifo_channel_create_((p), (e), (c), (b), (a), (s), (n), \
- (m), sizeof(**d), (void **)d)
-#define nvkm_fifo_channel_init(p) \
- nvkm_namedb_init(&(p)->namedb)
-#define nvkm_fifo_channel_fini(p,s) \
- nvkm_namedb_fini(&(p)->namedb, (s))
+struct nvkm_fifo_chan_func {
+ void *(*dtor)(struct nvkm_fifo_chan *);
+ void (*init)(struct nvkm_fifo_chan *);
+ void (*fini)(struct nvkm_fifo_chan *);
+ int (*ntfy)(struct nvkm_fifo_chan *, u32 type, struct nvkm_event **);
+ int (*engine_ctor)(struct nvkm_fifo_chan *, struct nvkm_engine *,
+ struct nvkm_object *);
+ void (*engine_dtor)(struct nvkm_fifo_chan *, struct nvkm_engine *);
+ int (*engine_init)(struct nvkm_fifo_chan *, struct nvkm_engine *);
+ int (*engine_fini)(struct nvkm_fifo_chan *, struct nvkm_engine *,
+ bool suspend);
+ int (*object_ctor)(struct nvkm_fifo_chan *, struct nvkm_object *);
+ void (*object_dtor)(struct nvkm_fifo_chan *, int);
+};
-int nvkm_fifo_channel_create_(struct nvkm_object *,
- struct nvkm_object *,
- struct nvkm_oclass *,
- int bar, u32 addr, u32 size, u64 push,
- u64 engmask, int len, void **);
-void nvkm_fifo_channel_destroy(struct nvkm_fifo_chan *);
+int nvkm_fifo_chan_ctor(const struct nvkm_fifo_chan_func *, struct nvkm_fifo *,
+ u32 size, u32 align, bool zero, u64 vm, u64 push,
+ u64 engines, int bar, u32 base, u32 user,
+ const struct nvkm_oclass *, struct nvkm_fifo_chan *);
-#define _nvkm_fifo_channel_init _nvkm_namedb_init
-#define _nvkm_fifo_channel_fini _nvkm_namedb_fini
+struct nvkm_fifo_chan_oclass {
+ int (*ctor)(struct nvkm_fifo *, const struct nvkm_oclass *,
+ void *data, u32 size, struct nvkm_object **);
+ struct nvkm_sclass base;
+};
-void _nvkm_fifo_channel_dtor(struct nvkm_object *);
-int _nvkm_fifo_channel_map(struct nvkm_object *, u64 *, u32 *);
-u32 _nvkm_fifo_channel_rd32(struct nvkm_object *, u64);
-void _nvkm_fifo_channel_wr32(struct nvkm_object *, u64, u32);
-int _nvkm_fifo_channel_ntfy(struct nvkm_object *, u32, struct nvkm_event **);
+int g84_fifo_chan_ntfy(struct nvkm_fifo_chan *, u32, struct nvkm_event **);
#endif
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chang84.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chang84.c
index f2b4a96f8794..a7e5dfae3833 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chang84.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chang84.c
@@ -25,38 +25,86 @@
#include <core/client.h>
#include <core/ramht.h>
+#include <subdev/mmu.h>
#include <subdev/timer.h>
+#include <nvif/class.h>
+
int
-g84_fifo_context_detach(struct nvkm_object *parent, bool suspend,
- struct nvkm_object *object)
+g84_fifo_chan_ntfy(struct nvkm_fifo_chan *chan, u32 type,
+ struct nvkm_event **pevent)
{
- struct nv50_fifo *fifo = (void *)parent->engine;
- struct nv50_fifo_base *base = (void *)parent->parent;
- struct nv50_fifo_chan *chan = (void *)parent;
- struct nvkm_subdev *subdev = &fifo->base.engine.subdev;
- struct nvkm_device *device = subdev->device;
- u32 addr, save, engn;
- bool done;
+ switch (type) {
+ case G82_CHANNEL_DMA_V0_NTFY_UEVENT:
+ *pevent = &chan->fifo->uevent;
+ return 0;
+ default:
+ break;
+ }
+ return -EINVAL;
+}
- switch (nv_engidx(object->engine)) {
- case NVDEV_ENGINE_SW : return 0;
- case NVDEV_ENGINE_GR : engn = 0; addr = 0x0020; break;
+static int
+g84_fifo_chan_engine(struct nvkm_engine *engine)
+{
+ switch (engine->subdev.index) {
+ case NVDEV_ENGINE_GR : return 0;
+ case NVDEV_ENGINE_MPEG :
+ case NVDEV_ENGINE_MSPPP : return 1;
+ case NVDEV_ENGINE_CE0 : return 2;
case NVDEV_ENGINE_VP :
- case NVDEV_ENGINE_MSPDEC: engn = 3; addr = 0x0040; break;
- case NVDEV_ENGINE_MSPPP :
- case NVDEV_ENGINE_MPEG : engn = 1; addr = 0x0060; break;
+ case NVDEV_ENGINE_MSPDEC: return 3;
+ case NVDEV_ENGINE_CIPHER:
+ case NVDEV_ENGINE_SEC : return 4;
case NVDEV_ENGINE_BSP :
- case NVDEV_ENGINE_MSVLD : engn = 5; addr = 0x0080; break;
+ case NVDEV_ENGINE_MSVLD : return 5;
+ default:
+ WARN_ON(1);
+ return 0;
+ }
+}
+
+static int
+g84_fifo_chan_engine_addr(struct nvkm_engine *engine)
+{
+ switch (engine->subdev.index) {
+ case NVDEV_ENGINE_DMAOBJ:
+ case NVDEV_ENGINE_SW : return -1;
+ case NVDEV_ENGINE_GR : return 0x0020;
+ case NVDEV_ENGINE_VP :
+ case NVDEV_ENGINE_MSPDEC: return 0x0040;
+ case NVDEV_ENGINE_MPEG :
+ case NVDEV_ENGINE_MSPPP : return 0x0060;
+ case NVDEV_ENGINE_BSP :
+ case NVDEV_ENGINE_MSVLD : return 0x0080;
case NVDEV_ENGINE_CIPHER:
- case NVDEV_ENGINE_SEC : engn = 4; addr = 0x00a0; break;
- case NVDEV_ENGINE_CE0 : engn = 2; addr = 0x00c0; break;
+ case NVDEV_ENGINE_SEC : return 0x00a0;
+ case NVDEV_ENGINE_CE0 : return 0x00c0;
default:
- return -EINVAL;
+ WARN_ON(1);
+ return -1;
}
+}
+static int
+g84_fifo_chan_engine_fini(struct nvkm_fifo_chan *base,
+ struct nvkm_engine *engine, bool suspend)
+{
+ struct nv50_fifo_chan *chan = nv50_fifo_chan(base);
+ struct nv50_fifo *fifo = chan->fifo;
+ struct nvkm_subdev *subdev = &fifo->base.engine.subdev;
+ struct nvkm_device *device = subdev->device;
+ u32 engn, save;
+ int offset;
+ bool done;
+
+ offset = g84_fifo_chan_engine_addr(engine);
+ if (offset < 0)
+ return 0;
+
+ engn = g84_fifo_chan_engine(engine);
save = nvkm_mask(device, 0x002520, 0x0000003f, 1 << engn);
- nvkm_wr32(device, 0x0032fc, nv_gpuobj(base)->addr >> 12);
+ nvkm_wr32(device, 0x0032fc, chan->base.inst->addr >> 12);
done = nvkm_msec(device, 2000,
if (nvkm_rd32(device, 0x0032fc) != 0xffffffff)
break;
@@ -64,168 +112,179 @@ g84_fifo_context_detach(struct nvkm_object *parent, bool suspend,
nvkm_wr32(device, 0x002520, save);
if (!done) {
nvkm_error(subdev, "channel %d [%s] unload timeout\n",
- chan->base.chid, nvkm_client_name(chan));
+ chan->base.chid, chan->base.object.client->name);
if (suspend)
return -EBUSY;
}
- nvkm_kmap(base->eng);
- nvkm_wo32(base->eng, addr + 0x00, 0x00000000);
- nvkm_wo32(base->eng, addr + 0x04, 0x00000000);
- nvkm_wo32(base->eng, addr + 0x08, 0x00000000);
- nvkm_wo32(base->eng, addr + 0x0c, 0x00000000);
- nvkm_wo32(base->eng, addr + 0x10, 0x00000000);
- nvkm_wo32(base->eng, addr + 0x14, 0x00000000);
- nvkm_done(base->eng);
+ nvkm_kmap(chan->eng);
+ nvkm_wo32(chan->eng, offset + 0x00, 0x00000000);
+ nvkm_wo32(chan->eng, offset + 0x04, 0x00000000);
+ nvkm_wo32(chan->eng, offset + 0x08, 0x00000000);
+ nvkm_wo32(chan->eng, offset + 0x0c, 0x00000000);
+ nvkm_wo32(chan->eng, offset + 0x10, 0x00000000);
+ nvkm_wo32(chan->eng, offset + 0x14, 0x00000000);
+ nvkm_done(chan->eng);
return 0;
}
int
-g84_fifo_context_attach(struct nvkm_object *parent, struct nvkm_object *object)
+g84_fifo_chan_engine_init(struct nvkm_fifo_chan *base,
+ struct nvkm_engine *engine)
{
- struct nv50_fifo_base *base = (void *)parent->parent;
- struct nvkm_gpuobj *ectx = (void *)object;
- u64 limit = ectx->addr + ectx->size - 1;
- u64 start = ectx->addr;
- u32 addr;
-
- switch (nv_engidx(object->engine)) {
- case NVDEV_ENGINE_SW : return 0;
- case NVDEV_ENGINE_GR : addr = 0x0020; break;
- case NVDEV_ENGINE_VP :
- case NVDEV_ENGINE_MSPDEC: addr = 0x0040; break;
- case NVDEV_ENGINE_MSPPP :
- case NVDEV_ENGINE_MPEG : addr = 0x0060; break;
- case NVDEV_ENGINE_BSP :
- case NVDEV_ENGINE_MSVLD : addr = 0x0080; break;
- case NVDEV_ENGINE_CIPHER:
- case NVDEV_ENGINE_SEC : addr = 0x00a0; break;
- case NVDEV_ENGINE_CE0 : addr = 0x00c0; break;
- default:
- return -EINVAL;
- }
+ struct nv50_fifo_chan *chan = nv50_fifo_chan(base);
+ struct nvkm_gpuobj *engn = chan->engn[engine->subdev.index];
+ u64 limit, start;
+ int offset;
- nv_engctx(ectx)->addr = nv_gpuobj(base)->addr >> 12;
- nvkm_kmap(base->eng);
- nvkm_wo32(base->eng, addr + 0x00, 0x00190000);
- nvkm_wo32(base->eng, addr + 0x04, lower_32_bits(limit));
- nvkm_wo32(base->eng, addr + 0x08, lower_32_bits(start));
- nvkm_wo32(base->eng, addr + 0x0c, upper_32_bits(limit) << 24 |
- upper_32_bits(start));
- nvkm_wo32(base->eng, addr + 0x10, 0x00000000);
- nvkm_wo32(base->eng, addr + 0x14, 0x00000000);
- nvkm_done(base->eng);
+ offset = g84_fifo_chan_engine_addr(engine);
+ if (offset < 0)
+ return 0;
+ limit = engn->addr + engn->size - 1;
+ start = engn->addr;
+
+ nvkm_kmap(chan->eng);
+ nvkm_wo32(chan->eng, offset + 0x00, 0x00190000);
+ nvkm_wo32(chan->eng, offset + 0x04, lower_32_bits(limit));
+ nvkm_wo32(chan->eng, offset + 0x08, lower_32_bits(start));
+ nvkm_wo32(chan->eng, offset + 0x0c, upper_32_bits(limit) << 24 |
+ upper_32_bits(start));
+ nvkm_wo32(chan->eng, offset + 0x10, 0x00000000);
+ nvkm_wo32(chan->eng, offset + 0x14, 0x00000000);
+ nvkm_done(chan->eng);
return 0;
}
+static int
+g84_fifo_chan_engine_ctor(struct nvkm_fifo_chan *base,
+ struct nvkm_engine *engine,
+ struct nvkm_object *object)
+{
+ struct nv50_fifo_chan *chan = nv50_fifo_chan(base);
+ int engn = engine->subdev.index;
+
+ if (g84_fifo_chan_engine_addr(engine) < 0)
+ return 0;
+
+ if (nv_iclass(object, NV_GPUOBJ_CLASS)) {
+ chan->engn[engn] = nv_gpuobj(object);
+ return 0;
+ }
+
+ return nvkm_object_bind(object, NULL, 0, &chan->engn[engn]);
+}
+
int
-g84_fifo_object_attach(struct nvkm_object *parent,
- struct nvkm_object *object, u32 handle)
+g84_fifo_chan_object_ctor(struct nvkm_fifo_chan *base,
+ struct nvkm_object *object)
{
- struct nv50_fifo_chan *chan = (void *)parent;
+ struct nv50_fifo_chan *chan = nv50_fifo_chan(base);
+ u32 handle = object->handle;
u32 context;
- if (nv_iclass(object, NV_GPUOBJ_CLASS))
- context = nv_gpuobj(object)->node->offset >> 4;
- else
- context = 0x00000004; /* just non-zero */
-
- if (object->engine) {
- switch (nv_engidx(object->engine)) {
- case NVDEV_ENGINE_DMAOBJ:
- case NVDEV_ENGINE_SW : context |= 0x00000000; break;
- case NVDEV_ENGINE_GR : context |= 0x00100000; break;
- case NVDEV_ENGINE_MPEG :
- case NVDEV_ENGINE_MSPPP : context |= 0x00200000; break;
- case NVDEV_ENGINE_ME :
- case NVDEV_ENGINE_CE0 : context |= 0x00300000; break;
- case NVDEV_ENGINE_VP :
- case NVDEV_ENGINE_MSPDEC: context |= 0x00400000; break;
- case NVDEV_ENGINE_CIPHER:
- case NVDEV_ENGINE_SEC :
- case NVDEV_ENGINE_VIC : context |= 0x00500000; break;
- case NVDEV_ENGINE_BSP :
- case NVDEV_ENGINE_MSVLD : context |= 0x00600000; break;
- default:
- return -EINVAL;
- }
+ switch (object->engine->subdev.index) {
+ case NVDEV_ENGINE_DMAOBJ:
+ case NVDEV_ENGINE_SW : context = 0x00000000; break;
+ case NVDEV_ENGINE_GR : context = 0x00100000; break;
+ case NVDEV_ENGINE_MPEG :
+ case NVDEV_ENGINE_MSPPP : context = 0x00200000; break;
+ case NVDEV_ENGINE_ME :
+ case NVDEV_ENGINE_CE0 : context = 0x00300000; break;
+ case NVDEV_ENGINE_VP :
+ case NVDEV_ENGINE_MSPDEC: context = 0x00400000; break;
+ case NVDEV_ENGINE_CIPHER:
+ case NVDEV_ENGINE_SEC :
+ case NVDEV_ENGINE_VIC : context = 0x00500000; break;
+ case NVDEV_ENGINE_BSP :
+ case NVDEV_ENGINE_MSVLD : context = 0x00600000; break;
+ default:
+ WARN_ON(1);
+ return -EINVAL;
}
- return nvkm_ramht_insert(chan->ramht, NULL, 0, 0, handle, context);
+ return nvkm_ramht_insert(chan->ramht, object, 0, 4, handle, context);
}
-int
-g84_fifo_chan_init(struct nvkm_object *object)
+static void
+g84_fifo_chan_init(struct nvkm_fifo_chan *base)
{
- struct nv50_fifo *fifo = (void *)object->engine;
- struct nv50_fifo_base *base = (void *)object->parent;
- struct nv50_fifo_chan *chan = (void *)object;
- struct nvkm_gpuobj *ramfc = base->ramfc;
+ struct nv50_fifo_chan *chan = nv50_fifo_chan(base);
+ struct nv50_fifo *fifo = chan->fifo;
struct nvkm_device *device = fifo->base.engine.subdev.device;
+ u64 addr = chan->ramfc->addr >> 8;
u32 chid = chan->base.chid;
- int ret;
-
- ret = nvkm_fifo_channel_init(&chan->base);
- if (ret)
- return ret;
- nvkm_wr32(device, 0x002600 + (chid * 4), 0x80000000 | ramfc->addr >> 8);
+ nvkm_wr32(device, 0x002600 + (chid * 4), 0x80000000 | addr);
nv50_fifo_runlist_update(fifo);
- return 0;
}
-static int
-g84_fifo_context_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
- struct nvkm_oclass *oclass, void *data, u32 size,
- struct nvkm_object **pobject)
+static const struct nvkm_fifo_chan_func
+g84_fifo_chan_func = {
+ .dtor = nv50_fifo_chan_dtor,
+ .init = g84_fifo_chan_init,
+ .fini = nv50_fifo_chan_fini,
+ .ntfy = g84_fifo_chan_ntfy,
+ .engine_ctor = g84_fifo_chan_engine_ctor,
+ .engine_dtor = nv50_fifo_chan_engine_dtor,
+ .engine_init = g84_fifo_chan_engine_init,
+ .engine_fini = g84_fifo_chan_engine_fini,
+ .object_ctor = g84_fifo_chan_object_ctor,
+ .object_dtor = nv50_fifo_chan_object_dtor,
+};
+
+int
+g84_fifo_chan_ctor(struct nv50_fifo *fifo, u64 vm, u64 push,
+ const struct nvkm_oclass *oclass,
+ struct nv50_fifo_chan *chan)
{
- struct nvkm_device *device = nv_engine(engine)->subdev.device;
- struct nv50_fifo_base *base;
+ struct nvkm_device *device = fifo->base.engine.subdev.device;
int ret;
- ret = nvkm_fifo_context_create(parent, engine, oclass, NULL, 0x10000,
- 0x1000, NVOBJ_FLAG_HEAP, &base);
- *pobject = nv_object(base);
+ ret = nvkm_fifo_chan_ctor(&g84_fifo_chan_func, &fifo->base,
+ 0x10000, 0x1000, false, vm, push,
+ (1ULL << NVDEV_ENGINE_BSP) |
+ (1ULL << NVDEV_ENGINE_CE0) |
+ (1ULL << NVDEV_ENGINE_CIPHER) |
+ (1ULL << NVDEV_ENGINE_DMAOBJ) |
+ (1ULL << NVDEV_ENGINE_GR) |
+ (1ULL << NVDEV_ENGINE_ME) |
+ (1ULL << NVDEV_ENGINE_MPEG) |
+ (1ULL << NVDEV_ENGINE_MSPDEC) |
+ (1ULL << NVDEV_ENGINE_MSPPP) |
+ (1ULL << NVDEV_ENGINE_MSVLD) |
+ (1ULL << NVDEV_ENGINE_SEC) |
+ (1ULL << NVDEV_ENGINE_SW) |
+ (1ULL << NVDEV_ENGINE_VIC) |
+ (1ULL << NVDEV_ENGINE_VP),
+ 0, 0xc00000, 0x2000, oclass, &chan->base);
+ chan->fifo = fifo;
if (ret)
return ret;
- ret = nvkm_gpuobj_new(device, 0x0200, 0, true, &base->base.gpuobj,
- &base->eng);
+ ret = nvkm_gpuobj_new(device, 0x0200, 0, true, chan->base.inst,
+ &chan->eng);
if (ret)
return ret;
- ret = nvkm_gpuobj_new(device, 0x4000, 0, false, &base->base.gpuobj,
- &base->pgd);
+ ret = nvkm_gpuobj_new(device, 0x4000, 0, false, chan->base.inst,
+ &chan->pgd);
if (ret)
return ret;
- ret = nvkm_vm_ref(nvkm_client(parent)->vm, &base->vm, base->pgd);
+ ret = nvkm_gpuobj_new(device, 0x1000, 0x400, true, chan->base.inst,
+ &chan->cache);
if (ret)
return ret;
- ret = nvkm_gpuobj_new(device, 0x1000, 0x400, true, &base->base.gpuobj,
- &base->cache);
+ ret = nvkm_gpuobj_new(device, 0x100, 0x100, true, chan->base.inst,
+ &chan->ramfc);
if (ret)
return ret;
- ret = nvkm_gpuobj_new(device, 0x100, 0x100, true, &base->base.gpuobj,
- &base->ramfc);
+ ret = nvkm_ramht_new(device, 0x8000, 16, chan->base.inst, &chan->ramht);
if (ret)
return ret;
- return 0;
+ return nvkm_vm_ref(chan->base.vm, &chan->vm, chan->pgd);
}
-
-struct nvkm_oclass
-g84_fifo_cclass = {
- .handle = NV_ENGCTX(FIFO, 0x84),
- .ofuncs = &(struct nvkm_ofuncs) {
- .ctor = g84_fifo_context_ctor,
- .dtor = nv50_fifo_context_dtor,
- .init = _nvkm_fifo_context_init,
- .fini = _nvkm_fifo_context_fini,
- .rd32 = _nvkm_fifo_context_rd32,
- .wr32 = _nvkm_fifo_context_wr32,
- },
-};
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/changf100.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/changf100.h
index 99324222dade..413288597e04 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/changf100.h
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/changf100.h
@@ -1,23 +1,24 @@
#ifndef __GF100_FIFO_CHAN_H__
#define __GF100_FIFO_CHAN_H__
+#define gf100_fifo_chan(p) container_of((p), struct gf100_fifo_chan, base)
#include "chan.h"
#include "gf100.h"
-struct gf100_fifo_base {
- struct nvkm_fifo_base base;
+struct gf100_fifo_chan {
+ struct nvkm_fifo_chan base;
+ struct gf100_fifo *fifo;
+
+ struct list_head head;
+ bool killed;
+
struct nvkm_gpuobj *pgd;
struct nvkm_vm *vm;
-};
-struct gf100_fifo_chan {
- struct nvkm_fifo_chan base;
- enum {
- STOPPED,
- RUNNING,
- KILLED
- } state;
+ struct {
+ struct nvkm_gpuobj *inst;
+ struct nvkm_vma vma;
+ } engn[NVDEV_SUBDEV_NR];
};
-extern struct nvkm_oclass gf100_fifo_cclass;
-extern struct nvkm_oclass gf100_fifo_sclass[];
+extern const struct nvkm_fifo_chan_oclass gf100_fifo_gpfifo_oclass;
#endif
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/changk104.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/changk104.h
index 3490cb6d8bd3..2b9d8bfc7fd7 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/changk104.h
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/changk104.h
@@ -1,27 +1,29 @@
#ifndef __GK104_FIFO_CHAN_H__
#define __GK104_FIFO_CHAN_H__
+#define gk104_fifo_chan(p) container_of((p), struct gk104_fifo_chan, base)
#include "chan.h"
#include "gk104.h"
-struct gk104_fifo_base {
- struct nvkm_fifo_base base;
+struct gk104_fifo_chan {
+ struct nvkm_fifo_chan base;
+ struct gk104_fifo *fifo;
+ int engine;
+
+ struct list_head head;
+ bool killed;
+
struct nvkm_gpuobj *pgd;
struct nvkm_vm *vm;
-};
-struct gk104_fifo_chan {
- struct nvkm_fifo_chan base;
- u32 engine;
- enum {
- STOPPED,
- RUNNING,
- KILLED
- } state;
+ struct {
+ struct nvkm_gpuobj *inst;
+ struct nvkm_vma vma;
+ } engn[NVDEV_SUBDEV_NR];
};
-extern struct nvkm_oclass gk104_fifo_cclass;
-extern struct nvkm_oclass gk104_fifo_sclass[];
-extern struct nvkm_ofuncs gk104_fifo_chan_ofuncs;
+int gk104_fifo_gpfifo_new(struct nvkm_fifo *, const struct nvkm_oclass *,
+ void *data, u32 size, struct nvkm_object **);
-extern struct nvkm_oclass gm204_fifo_sclass[];
+extern const struct nvkm_fifo_chan_oclass gk104_fifo_gpfifo_oclass;
+extern const struct nvkm_fifo_chan_oclass gm204_fifo_gpfifo_oclass;
#endif
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv04.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv04.h
index 028212df41bc..ac62a6404f87 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv04.h
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv04.h
@@ -1,24 +1,24 @@
#ifndef __NV04_FIFO_CHAN_H__
#define __NV04_FIFO_CHAN_H__
+#define nv04_fifo_chan(p) container_of((p), struct nv04_fifo_chan, base)
#include "chan.h"
#include "nv04.h"
struct nv04_fifo_chan {
struct nvkm_fifo_chan base;
- u32 subc[8];
+ struct nv04_fifo *fifo;
u32 ramfc;
+ struct nvkm_gpuobj *engn[NVDEV_SUBDEV_NR];
};
-int nv04_fifo_object_attach(struct nvkm_object *, struct nvkm_object *, u32);
-void nv04_fifo_object_detach(struct nvkm_object *, int);
+extern const struct nvkm_fifo_chan_func nv04_fifo_dma_func;
+void *nv04_fifo_dma_dtor(struct nvkm_fifo_chan *);
+void nv04_fifo_dma_init(struct nvkm_fifo_chan *);
+void nv04_fifo_dma_fini(struct nvkm_fifo_chan *);
+void nv04_fifo_dma_object_dtor(struct nvkm_fifo_chan *, int);
-void nv04_fifo_chan_dtor(struct nvkm_object *);
-int nv04_fifo_chan_init(struct nvkm_object *);
-int nv04_fifo_chan_fini(struct nvkm_object *, bool suspend);
-
-extern struct nvkm_oclass nv04_fifo_cclass;
-extern struct nvkm_oclass nv04_fifo_sclass[];
-extern struct nvkm_oclass nv10_fifo_sclass[];
-extern struct nvkm_oclass nv17_fifo_sclass[];
-extern struct nvkm_oclass nv40_fifo_sclass[];
+extern const struct nvkm_fifo_chan_oclass nv04_fifo_dma_oclass;
+extern const struct nvkm_fifo_chan_oclass nv10_fifo_dma_oclass;
+extern const struct nvkm_fifo_chan_oclass nv17_fifo_dma_oclass;
+extern const struct nvkm_fifo_chan_oclass nv40_fifo_dma_oclass;
#endif
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv50.c
index aeaba7b9bcae..2a25019ce0f4 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv50.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv50.c
@@ -25,27 +25,37 @@
#include <core/client.h>
#include <core/ramht.h>
+#include <subdev/mmu.h>
#include <subdev/timer.h>
-int
-nv50_fifo_context_detach(struct nvkm_object *parent, bool suspend,
- struct nvkm_object *object)
+static int
+nv50_fifo_chan_engine_addr(struct nvkm_engine *engine)
{
- struct nv50_fifo *fifo = (void *)parent->engine;
- struct nv50_fifo_base *base = (void *)parent->parent;
- struct nv50_fifo_chan *chan = (void *)parent;
+ switch (engine->subdev.index) {
+ case NVDEV_ENGINE_DMAOBJ:
+ case NVDEV_ENGINE_SW : return -1;
+ case NVDEV_ENGINE_GR : return 0x0000;
+ case NVDEV_ENGINE_MPEG : return 0x0060;
+ default:
+ WARN_ON(1);
+ return -1;
+ }
+}
+
+static int
+nv50_fifo_chan_engine_fini(struct nvkm_fifo_chan *base,
+ struct nvkm_engine *engine, bool suspend)
+{
+ struct nv50_fifo_chan *chan = nv50_fifo_chan(base);
+ struct nv50_fifo *fifo = chan->fifo;
struct nvkm_subdev *subdev = &fifo->base.engine.subdev;
struct nvkm_device *device = subdev->device;
- u32 addr, me;
- int ret = 0;
+ int offset, ret = 0;
+ u32 me;
- switch (nv_engidx(object->engine)) {
- case NVDEV_ENGINE_SW : return 0;
- case NVDEV_ENGINE_GR : addr = 0x0000; break;
- case NVDEV_ENGINE_MPEG : addr = 0x0060; break;
- default:
- return -EINVAL;
- }
+ offset = nv50_fifo_chan_engine_addr(engine);
+ if (offset < 0)
+ return 0;
/* HW bug workaround:
*
@@ -62,101 +72,124 @@ nv50_fifo_context_detach(struct nvkm_object *parent, bool suspend,
me = nvkm_mask(device, 0x00b860, 0x00000001, 0x00000001);
/* do the kickoff... */
- nvkm_wr32(device, 0x0032fc, nv_gpuobj(base)->addr >> 12);
+ nvkm_wr32(device, 0x0032fc, chan->base.inst->addr >> 12);
if (nvkm_msec(device, 2000,
if (nvkm_rd32(device, 0x0032fc) != 0xffffffff)
break;
) < 0) {
nvkm_error(subdev, "channel %d [%s] unload timeout\n",
- chan->base.chid, nvkm_client_name(chan));
+ chan->base.chid, chan->base.object.client->name);
if (suspend)
ret = -EBUSY;
}
nvkm_wr32(device, 0x00b860, me);
if (ret == 0) {
- nvkm_kmap(base->eng);
- nvkm_wo32(base->eng, addr + 0x00, 0x00000000);
- nvkm_wo32(base->eng, addr + 0x04, 0x00000000);
- nvkm_wo32(base->eng, addr + 0x08, 0x00000000);
- nvkm_wo32(base->eng, addr + 0x0c, 0x00000000);
- nvkm_wo32(base->eng, addr + 0x10, 0x00000000);
- nvkm_wo32(base->eng, addr + 0x14, 0x00000000);
- nvkm_done(base->eng);
+ nvkm_kmap(chan->eng);
+ nvkm_wo32(chan->eng, offset + 0x00, 0x00000000);
+ nvkm_wo32(chan->eng, offset + 0x04, 0x00000000);
+ nvkm_wo32(chan->eng, offset + 0x08, 0x00000000);
+ nvkm_wo32(chan->eng, offset + 0x0c, 0x00000000);
+ nvkm_wo32(chan->eng, offset + 0x10, 0x00000000);
+ nvkm_wo32(chan->eng, offset + 0x14, 0x00000000);
+ nvkm_done(chan->eng);
}
return ret;
}
-int
-nv50_fifo_context_attach(struct nvkm_object *parent, struct nvkm_object *object)
+static int
+nv50_fifo_chan_engine_init(struct nvkm_fifo_chan *base,
+ struct nvkm_engine *engine)
{
- struct nv50_fifo_base *base = (void *)parent->parent;
- struct nvkm_gpuobj *ectx = (void *)object;
- u64 limit = ectx->addr + ectx->size - 1;
- u64 start = ectx->addr;
- u32 addr;
-
- switch (nv_engidx(object->engine)) {
- case NVDEV_ENGINE_SW : return 0;
- case NVDEV_ENGINE_GR : addr = 0x0000; break;
- case NVDEV_ENGINE_MPEG : addr = 0x0060; break;
- default:
- return -EINVAL;
+ struct nv50_fifo_chan *chan = nv50_fifo_chan(base);
+ struct nvkm_gpuobj *engn = chan->engn[engine->subdev.index];
+ u64 limit, start;
+ int offset;
+
+ offset = nv50_fifo_chan_engine_addr(engine);
+ if (offset < 0)
+ return 0;
+ limit = engn->addr + engn->size - 1;
+ start = engn->addr;
+
+ nvkm_kmap(chan->eng);
+ nvkm_wo32(chan->eng, offset + 0x00, 0x00190000);
+ nvkm_wo32(chan->eng, offset + 0x04, lower_32_bits(limit));
+ nvkm_wo32(chan->eng, offset + 0x08, lower_32_bits(start));
+ nvkm_wo32(chan->eng, offset + 0x0c, upper_32_bits(limit) << 24 |
+ upper_32_bits(start));
+ nvkm_wo32(chan->eng, offset + 0x10, 0x00000000);
+ nvkm_wo32(chan->eng, offset + 0x14, 0x00000000);
+ nvkm_done(chan->eng);
+ return 0;
+}
+
+void
+nv50_fifo_chan_engine_dtor(struct nvkm_fifo_chan *base,
+ struct nvkm_engine *engine)
+{
+ struct nv50_fifo_chan *chan = nv50_fifo_chan(base);
+ if (!chan->engn[engine->subdev.index] ||
+ chan->engn[engine->subdev.index]->object.oclass) {
+ chan->engn[engine->subdev.index] = NULL;
+ return;
}
+ nvkm_gpuobj_del(&chan->engn[engine->subdev.index]);
+}
- nv_engctx(ectx)->addr = nv_gpuobj(base)->addr >> 12;
-
- nvkm_kmap(base->eng);
- nvkm_wo32(base->eng, addr + 0x00, 0x00190000);
- nvkm_wo32(base->eng, addr + 0x04, lower_32_bits(limit));
- nvkm_wo32(base->eng, addr + 0x08, lower_32_bits(start));
- nvkm_wo32(base->eng, addr + 0x0c, upper_32_bits(limit) << 24 |
- upper_32_bits(start));
- nvkm_wo32(base->eng, addr + 0x10, 0x00000000);
- nvkm_wo32(base->eng, addr + 0x14, 0x00000000);
- nvkm_done(base->eng);
- return 0;
+static int
+nv50_fifo_chan_engine_ctor(struct nvkm_fifo_chan *base,
+ struct nvkm_engine *engine,
+ struct nvkm_object *object)
+{
+ struct nv50_fifo_chan *chan = nv50_fifo_chan(base);
+ int engn = engine->subdev.index;
+
+ if (nv50_fifo_chan_engine_addr(engine) < 0)
+ return 0;
+
+ if (nv_iclass(object, NV_GPUOBJ_CLASS)) {
+ chan->engn[engn] = nv_gpuobj(object);
+ return 0;
+ }
+
+ return nvkm_object_bind(object, NULL, 0, &chan->engn[engn]);
}
void
-nv50_fifo_object_detach(struct nvkm_object *parent, int cookie)
+nv50_fifo_chan_object_dtor(struct nvkm_fifo_chan *base, int cookie)
{
- struct nv50_fifo_chan *chan = (void *)parent;
+ struct nv50_fifo_chan *chan = nv50_fifo_chan(base);
nvkm_ramht_remove(chan->ramht, cookie);
}
-int
-nv50_fifo_object_attach(struct nvkm_object *parent,
- struct nvkm_object *object, u32 handle)
+static int
+nv50_fifo_chan_object_ctor(struct nvkm_fifo_chan *base,
+ struct nvkm_object *object)
{
- struct nv50_fifo_chan *chan = (void *)parent;
+ struct nv50_fifo_chan *chan = nv50_fifo_chan(base);
+ u32 handle = object->handle;
u32 context;
- if (nv_iclass(object, NV_GPUOBJ_CLASS))
- context = nv_gpuobj(object)->node->offset >> 4;
- else
- context = 0x00000004; /* just non-zero */
-
- if (object->engine) {
- switch (nv_engidx(object->engine)) {
- case NVDEV_ENGINE_DMAOBJ:
- case NVDEV_ENGINE_SW : context |= 0x00000000; break;
- case NVDEV_ENGINE_GR : context |= 0x00100000; break;
- case NVDEV_ENGINE_MPEG : context |= 0x00200000; break;
- default:
- return -EINVAL;
- }
+ switch (object->engine->subdev.index) {
+ case NVDEV_ENGINE_DMAOBJ:
+ case NVDEV_ENGINE_SW : context = 0x00000000; break;
+ case NVDEV_ENGINE_GR : context = 0x00100000; break;
+ case NVDEV_ENGINE_MPEG : context = 0x00200000; break;
+ default:
+ WARN_ON(1);
+ return -EINVAL;
}
- return nvkm_ramht_insert(chan->ramht, NULL, 0, 0, handle, context);
+ return nvkm_ramht_insert(chan->ramht, object, 0, 4, handle, context);
}
-int
-nv50_fifo_chan_fini(struct nvkm_object *object, bool suspend)
+void
+nv50_fifo_chan_fini(struct nvkm_fifo_chan *base)
{
- struct nv50_fifo *fifo = (void *)object->engine;
- struct nv50_fifo_chan *chan = (void *)object;
+ struct nv50_fifo_chan *chan = nv50_fifo_chan(base);
+ struct nv50_fifo *fifo = chan->fifo;
struct nvkm_device *device = fifo->base.engine.subdev.device;
u32 chid = chan->base.chid;
@@ -164,96 +197,84 @@ nv50_fifo_chan_fini(struct nvkm_object *object, bool suspend)
nvkm_mask(device, 0x002600 + (chid * 4), 0x80000000, 0x00000000);
nv50_fifo_runlist_update(fifo);
nvkm_wr32(device, 0x002600 + (chid * 4), 0x00000000);
-
- return nvkm_fifo_channel_fini(&chan->base, suspend);
}
-int
-nv50_fifo_chan_init(struct nvkm_object *object)
+static void
+nv50_fifo_chan_init(struct nvkm_fifo_chan *base)
{
- struct nv50_fifo *fifo = (void *)object->engine;
- struct nv50_fifo_base *base = (void *)object->parent;
- struct nv50_fifo_chan *chan = (void *)object;
- struct nvkm_gpuobj *ramfc = base->ramfc;
+ struct nv50_fifo_chan *chan = nv50_fifo_chan(base);
+ struct nv50_fifo *fifo = chan->fifo;
struct nvkm_device *device = fifo->base.engine.subdev.device;
+ u64 addr = chan->ramfc->addr >> 12;
u32 chid = chan->base.chid;
- int ret;
-
- ret = nvkm_fifo_channel_init(&chan->base);
- if (ret)
- return ret;
- nvkm_wr32(device, 0x002600 + (chid * 4), 0x80000000 | ramfc->addr >> 12);
+ nvkm_wr32(device, 0x002600 + (chid * 4), 0x80000000 | addr);
nv50_fifo_runlist_update(fifo);
- return 0;
}
-void
-nv50_fifo_chan_dtor(struct nvkm_object *object)
+void *
+nv50_fifo_chan_dtor(struct nvkm_fifo_chan *base)
{
- struct nv50_fifo_chan *chan = (void *)object;
+ struct nv50_fifo_chan *chan = nv50_fifo_chan(base);
+ nvkm_vm_ref(NULL, &chan->vm, chan->pgd);
nvkm_ramht_del(&chan->ramht);
- nvkm_fifo_channel_destroy(&chan->base);
+ nvkm_gpuobj_del(&chan->pgd);
+ nvkm_gpuobj_del(&chan->eng);
+ nvkm_gpuobj_del(&chan->cache);
+ nvkm_gpuobj_del(&chan->ramfc);
+ return chan;
}
-void
-nv50_fifo_context_dtor(struct nvkm_object *object)
-{
- struct nv50_fifo_base *base = (void *)object;
- nvkm_vm_ref(NULL, &base->vm, base->pgd);
- nvkm_gpuobj_del(&base->pgd);
- nvkm_gpuobj_del(&base->eng);
- nvkm_gpuobj_del(&base->ramfc);
- nvkm_gpuobj_del(&base->cache);
- nvkm_fifo_context_destroy(&base->base);
-}
+static const struct nvkm_fifo_chan_func
+nv50_fifo_chan_func = {
+ .dtor = nv50_fifo_chan_dtor,
+ .init = nv50_fifo_chan_init,
+ .fini = nv50_fifo_chan_fini,
+ .engine_ctor = nv50_fifo_chan_engine_ctor,
+ .engine_dtor = nv50_fifo_chan_engine_dtor,
+ .engine_init = nv50_fifo_chan_engine_init,
+ .engine_fini = nv50_fifo_chan_engine_fini,
+ .object_ctor = nv50_fifo_chan_object_ctor,
+ .object_dtor = nv50_fifo_chan_object_dtor,
+};
-static int
-nv50_fifo_context_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
- struct nvkm_oclass *oclass, void *data, u32 size,
- struct nvkm_object **pobject)
+int
+nv50_fifo_chan_ctor(struct nv50_fifo *fifo, u64 vm, u64 push,
+ const struct nvkm_oclass *oclass,
+ struct nv50_fifo_chan *chan)
{
- struct nvkm_device *device = nv_engine(engine)->subdev.device;
- struct nv50_fifo_base *base;
+ struct nvkm_device *device = fifo->base.engine.subdev.device;
int ret;
- ret = nvkm_fifo_context_create(parent, engine, oclass, NULL, 0x10000,
- 0x1000, NVOBJ_FLAG_HEAP, &base);
- *pobject = nv_object(base);
+ ret = nvkm_fifo_chan_ctor(&nv50_fifo_chan_func, &fifo->base,
+ 0x10000, 0x1000, false, vm, push,
+ (1ULL << NVDEV_ENGINE_DMAOBJ) |
+ (1ULL << NVDEV_ENGINE_SW) |
+ (1ULL << NVDEV_ENGINE_GR) |
+ (1ULL << NVDEV_ENGINE_MPEG),
+ 0, 0xc00000, 0x2000, oclass, &chan->base);
+ chan->fifo = fifo;
if (ret)
return ret;
- ret = nvkm_gpuobj_new(device, 0x0200, 0x1000, true, &base->base.gpuobj,
- &base->ramfc);
+ ret = nvkm_gpuobj_new(device, 0x0200, 0x1000, true, chan->base.inst,
+ &chan->ramfc);
if (ret)
return ret;
- ret = nvkm_gpuobj_new(device, 0x1200, 0, true, &base->base.gpuobj,
- &base->eng);
+ ret = nvkm_gpuobj_new(device, 0x1200, 0, true, chan->base.inst,
+ &chan->eng);
if (ret)
return ret;
- ret = nvkm_gpuobj_new(device, 0x4000, 0, false, &base->base.gpuobj,
- &base->pgd);
+ ret = nvkm_gpuobj_new(device, 0x4000, 0, false, chan->base.inst,
+ &chan->pgd);
if (ret)
return ret;
- ret = nvkm_vm_ref(nvkm_client(parent)->vm, &base->vm, base->pgd);
+ ret = nvkm_ramht_new(device, 0x8000, 16, chan->base.inst, &chan->ramht);
if (ret)
return ret;
- return 0;
+ return nvkm_vm_ref(chan->base.vm, &chan->vm, chan->pgd);
}
-
-struct nvkm_oclass
-nv50_fifo_cclass = {
- .handle = NV_ENGCTX(FIFO, 0x50),
- .ofuncs = &(struct nvkm_ofuncs) {
- .ctor = nv50_fifo_context_ctor,
- .dtor = nv50_fifo_context_dtor,
- .init = _nvkm_fifo_context_init,
- .fini = _nvkm_fifo_context_fini,
- .rd32 = _nvkm_fifo_context_rd32,
- .wr32 = _nvkm_fifo_context_wr32,
- },
-};
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv50.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv50.h
index c4f2f1ff4c9e..7ef6bc2e27ec 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv50.h
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv50.h
@@ -1,42 +1,35 @@
#ifndef __NV50_FIFO_CHAN_H__
#define __NV50_FIFO_CHAN_H__
+#define nv50_fifo_chan(p) container_of((p), struct nv50_fifo_chan, base)
#include "chan.h"
#include "nv50.h"
-struct nv50_fifo_base {
- struct nvkm_fifo_base base;
+struct nv50_fifo_chan {
+ struct nv50_fifo *fifo;
+ struct nvkm_fifo_chan base;
+
struct nvkm_gpuobj *ramfc;
struct nvkm_gpuobj *cache;
struct nvkm_gpuobj *eng;
struct nvkm_gpuobj *pgd;
+ struct nvkm_ramht *ramht;
struct nvkm_vm *vm;
-};
-struct nv50_fifo_chan {
- struct nvkm_fifo_chan base;
- u32 subc[8];
- struct nvkm_ramht *ramht;
+ struct nvkm_gpuobj *engn[NVDEV_SUBDEV_NR];
};
-extern struct nvkm_oclass nv50_fifo_cclass;
-extern struct nvkm_oclass nv50_fifo_sclass[];
-void nv50_fifo_context_dtor(struct nvkm_object *);
-void nv50_fifo_chan_dtor(struct nvkm_object *);
-int nv50_fifo_chan_init(struct nvkm_object *);
-int nv50_fifo_chan_fini(struct nvkm_object *, bool);
-int nv50_fifo_context_attach(struct nvkm_object *, struct nvkm_object *);
-int nv50_fifo_context_detach(struct nvkm_object *, bool,
- struct nvkm_object *);
-int nv50_fifo_object_attach(struct nvkm_object *, struct nvkm_object *, u32);
-void nv50_fifo_object_detach(struct nvkm_object *, int);
-extern struct nvkm_ofuncs nv50_fifo_ofuncs_ind;
+int nv50_fifo_chan_ctor(struct nv50_fifo *, u64 vm, u64 push,
+ const struct nvkm_oclass *, struct nv50_fifo_chan *);
+void *nv50_fifo_chan_dtor(struct nvkm_fifo_chan *);
+void nv50_fifo_chan_fini(struct nvkm_fifo_chan *);
+void nv50_fifo_chan_engine_dtor(struct nvkm_fifo_chan *, struct nvkm_engine *);
+void nv50_fifo_chan_object_dtor(struct nvkm_fifo_chan *, int);
+
+int g84_fifo_chan_ctor(struct nv50_fifo *, u64 vm, u64 push,
+ const struct nvkm_oclass *, struct nv50_fifo_chan *);
-extern struct nvkm_oclass g84_fifo_cclass;
-extern struct nvkm_oclass g84_fifo_sclass[];
-int g84_fifo_chan_init(struct nvkm_object *);
-int g84_fifo_context_attach(struct nvkm_object *, struct nvkm_object *);
-int g84_fifo_context_detach(struct nvkm_object *, bool,
- struct nvkm_object *);
-int g84_fifo_object_attach(struct nvkm_object *, struct nvkm_object *, u32);
-extern struct nvkm_ofuncs g84_fifo_ofuncs_ind;
+extern const struct nvkm_fifo_chan_oclass nv50_fifo_dma_oclass;
+extern const struct nvkm_fifo_chan_oclass nv50_fifo_gpfifo_oclass;
+extern const struct nvkm_fifo_chan_oclass g84_fifo_dma_oclass;
+extern const struct nvkm_fifo_chan_oclass g84_fifo_gpfifo_oclass;
#endif
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmag84.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmag84.c
index 2016a9884b38..a5ca52c7b74f 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmag84.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmag84.c
@@ -30,15 +30,14 @@
#include <nvif/unpack.h>
static int
-g84_fifo_chan_ctor_dma(struct nvkm_object *parent, struct nvkm_object *engine,
- struct nvkm_oclass *oclass, void *data, u32 size,
- struct nvkm_object **pobject)
+g84_fifo_dma_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass,
+ void *data, u32 size, struct nvkm_object **pobject)
{
+ struct nvkm_object *parent = oclass->parent;
union {
struct nv50_channel_dma_v0 v0;
} *args = data;
- struct nvkm_device *device = parent->engine->subdev.device;
- struct nv50_fifo_base *base = (void *)parent;
+ struct nv50_fifo *fifo = nv50_fifo(base);
struct nv50_fifo_chan *chan;
int ret;
@@ -48,80 +47,47 @@ g84_fifo_chan_ctor_dma(struct nvkm_object *parent, struct nvkm_object *engine,
"pushbuf %llx offset %016llx\n",
args->v0.version, args->v0.vm, args->v0.pushbuf,
args->v0.offset);
- if (args->v0.vm)
- return -ENOENT;
+ if (!args->v0.pushbuf)
+ return -EINVAL;
} else
return ret;
- ret = nvkm_fifo_channel_create(parent, engine, oclass, 0, 0xc00000,
- 0x2000, args->v0.pushbuf,
- (1ULL << NVDEV_ENGINE_DMAOBJ) |
- (1ULL << NVDEV_ENGINE_SW) |
- (1ULL << NVDEV_ENGINE_GR) |
- (1ULL << NVDEV_ENGINE_MPEG) |
- (1ULL << NVDEV_ENGINE_ME) |
- (1ULL << NVDEV_ENGINE_VP) |
- (1ULL << NVDEV_ENGINE_CIPHER) |
- (1ULL << NVDEV_ENGINE_SEC) |
- (1ULL << NVDEV_ENGINE_BSP) |
- (1ULL << NVDEV_ENGINE_MSVLD) |
- (1ULL << NVDEV_ENGINE_MSPDEC) |
- (1ULL << NVDEV_ENGINE_MSPPP) |
- (1ULL << NVDEV_ENGINE_CE0) |
- (1ULL << NVDEV_ENGINE_VIC), &chan);
- *pobject = nv_object(chan);
- if (ret)
- return ret;
-
- chan->base.inst = base->base.gpuobj.addr;
- args->v0.chid = chan->base.chid;
+ if (!(chan = kzalloc(sizeof(*chan), GFP_KERNEL)))
+ return -ENOMEM;
+ *pobject = &chan->base.object;
- ret = nvkm_ramht_new(device, 0x8000, 16, &base->base.gpuobj,
- &chan->ramht);
+ ret = g84_fifo_chan_ctor(fifo, args->v0.vm, args->v0.pushbuf,
+ oclass, chan);
if (ret)
return ret;
- nv_parent(chan)->context_attach = g84_fifo_context_attach;
- nv_parent(chan)->context_detach = g84_fifo_context_detach;
- nv_parent(chan)->object_attach = g84_fifo_object_attach;
- nv_parent(chan)->object_detach = nv50_fifo_object_detach;
+ args->v0.chid = chan->base.chid;
- nvkm_kmap(base->ramfc);
- nvkm_wo32(base->ramfc, 0x08, lower_32_bits(args->v0.offset));
- nvkm_wo32(base->ramfc, 0x0c, upper_32_bits(args->v0.offset));
- nvkm_wo32(base->ramfc, 0x10, lower_32_bits(args->v0.offset));
- nvkm_wo32(base->ramfc, 0x14, upper_32_bits(args->v0.offset));
- nvkm_wo32(base->ramfc, 0x3c, 0x003f6078);
- nvkm_wo32(base->ramfc, 0x44, 0x01003fff);
- nvkm_wo32(base->ramfc, 0x48, chan->base.pushgpu->node->offset >> 4);
- nvkm_wo32(base->ramfc, 0x4c, 0xffffffff);
- nvkm_wo32(base->ramfc, 0x60, 0x7fffffff);
- nvkm_wo32(base->ramfc, 0x78, 0x00000000);
- nvkm_wo32(base->ramfc, 0x7c, 0x30000001);
- nvkm_wo32(base->ramfc, 0x80, ((chan->ramht->bits - 9) << 27) |
+ nvkm_kmap(chan->ramfc);
+ nvkm_wo32(chan->ramfc, 0x08, lower_32_bits(args->v0.offset));
+ nvkm_wo32(chan->ramfc, 0x0c, upper_32_bits(args->v0.offset));
+ nvkm_wo32(chan->ramfc, 0x10, lower_32_bits(args->v0.offset));
+ nvkm_wo32(chan->ramfc, 0x14, upper_32_bits(args->v0.offset));
+ nvkm_wo32(chan->ramfc, 0x3c, 0x003f6078);
+ nvkm_wo32(chan->ramfc, 0x44, 0x01003fff);
+ nvkm_wo32(chan->ramfc, 0x48, chan->base.push->node->offset >> 4);
+ nvkm_wo32(chan->ramfc, 0x4c, 0xffffffff);
+ nvkm_wo32(chan->ramfc, 0x60, 0x7fffffff);
+ nvkm_wo32(chan->ramfc, 0x78, 0x00000000);
+ nvkm_wo32(chan->ramfc, 0x7c, 0x30000001);
+ nvkm_wo32(chan->ramfc, 0x80, ((chan->ramht->bits - 9) << 27) |
(4 << 24) /* SEARCH_FULL */ |
(chan->ramht->gpuobj->node->offset >> 4));
- nvkm_wo32(base->ramfc, 0x88, base->cache->addr >> 10);
- nvkm_wo32(base->ramfc, 0x98, nv_gpuobj(base)->addr >> 12);
- nvkm_done(base->ramfc);
+ nvkm_wo32(chan->ramfc, 0x88, chan->cache->addr >> 10);
+ nvkm_wo32(chan->ramfc, 0x98, chan->base.inst->addr >> 12);
+ nvkm_done(chan->ramfc);
return 0;
}
-static struct nvkm_ofuncs
-g84_fifo_ofuncs_dma = {
- .ctor = g84_fifo_chan_ctor_dma,
- .dtor = nv50_fifo_chan_dtor,
- .init = g84_fifo_chan_init,
- .fini = nv50_fifo_chan_fini,
- .map = _nvkm_fifo_channel_map,
- .rd32 = _nvkm_fifo_channel_rd32,
- .wr32 = _nvkm_fifo_channel_wr32,
- .ntfy = _nvkm_fifo_channel_ntfy
-};
-
-struct nvkm_oclass
-g84_fifo_sclass[] = {
- { G82_CHANNEL_DMA, &g84_fifo_ofuncs_dma },
- { G82_CHANNEL_GPFIFO, &g84_fifo_ofuncs_ind },
- {}
+const struct nvkm_fifo_chan_oclass
+g84_fifo_dma_oclass = {
+ .base.oclass = G82_CHANNEL_DMA,
+ .base.minver = 0,
+ .base.maxver = 0,
+ .ctor = g84_fifo_dma_new,
};
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv04.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv04.c
index 8cc87103a369..eafa87886643 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv04.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv04.c
@@ -31,74 +31,51 @@
#include <nvif/class.h>
#include <nvif/unpack.h>
-int
-nv04_fifo_context_attach(struct nvkm_object *parent,
- struct nvkm_object *object)
-{
- nv_engctx(object)->addr = nvkm_fifo_chan(parent)->chid;
- return 0;
-}
-
void
-nv04_fifo_object_detach(struct nvkm_object *parent, int cookie)
+nv04_fifo_dma_object_dtor(struct nvkm_fifo_chan *base, int cookie)
{
- struct nv04_fifo *fifo = (void *)parent->engine;
- struct nvkm_instmem *imem = fifo->base.engine.subdev.device->imem;
- mutex_lock(&nv_subdev(fifo)->mutex);
+ struct nv04_fifo_chan *chan = nv04_fifo_chan(base);
+ struct nvkm_instmem *imem = chan->fifo->base.engine.subdev.device->imem;
nvkm_ramht_remove(imem->ramht, cookie);
- mutex_unlock(&nv_subdev(fifo)->mutex);
}
-int
-nv04_fifo_object_attach(struct nvkm_object *parent,
- struct nvkm_object *object, u32 handle)
+static int
+nv04_fifo_dma_object_ctor(struct nvkm_fifo_chan *base,
+ struct nvkm_object *object)
{
- struct nv04_fifo *fifo = (void *)parent->engine;
- struct nv04_fifo_chan *chan = (void *)parent;
- struct nvkm_instmem *imem = fifo->base.engine.subdev.device->imem;
- u32 context, chid = chan->base.chid;
- int ret;
-
- if (nv_iclass(object, NV_GPUOBJ_CLASS))
- context = nv_gpuobj(object)->addr >> 4;
- else
- context = 0x00000004; /* just non-zero */
-
- if (object->engine) {
- switch (nv_engidx(object->engine)) {
- case NVDEV_ENGINE_DMAOBJ:
- case NVDEV_ENGINE_SW:
- context |= 0x00000000;
- break;
- case NVDEV_ENGINE_GR:
- context |= 0x00010000;
- break;
- case NVDEV_ENGINE_MPEG:
- context |= 0x00020000;
- break;
- default:
- return -EINVAL;
- }
+ struct nv04_fifo_chan *chan = nv04_fifo_chan(base);
+ struct nvkm_instmem *imem = chan->fifo->base.engine.subdev.device->imem;
+ u32 context = 0x80000000 | chan->base.chid << 24;
+ u32 handle = object->handle;
+ int hash;
+
+ switch (object->engine->subdev.index) {
+ case NVDEV_ENGINE_DMAOBJ:
+ case NVDEV_ENGINE_SW : context |= 0x00000000; break;
+ case NVDEV_ENGINE_GR : context |= 0x00010000; break;
+ case NVDEV_ENGINE_MPEG : context |= 0x00020000; break;
+ default:
+ WARN_ON(1);
+ return -EINVAL;
}
- context |= 0x80000000; /* valid */
- context |= chid << 24;
-
- mutex_lock(&nv_subdev(fifo)->mutex);
- ret = nvkm_ramht_insert(imem->ramht, NULL, chid, 0, handle, context);
- mutex_unlock(&nv_subdev(fifo)->mutex);
- return ret;
+ mutex_lock(&chan->fifo->base.engine.subdev.mutex);
+ hash = nvkm_ramht_insert(imem->ramht, object, chan->base.chid, 4,
+ handle, context);
+ mutex_unlock(&chan->fifo->base.engine.subdev.mutex);
+ return hash;
}
-int
-nv04_fifo_chan_fini(struct nvkm_object *object, bool suspend)
+void
+nv04_fifo_dma_fini(struct nvkm_fifo_chan *base)
{
- struct nv04_fifo *fifo = (void *)object->engine;
- struct nv04_fifo_chan *chan = (void *)object;
+ struct nv04_fifo_chan *chan = nv04_fifo_chan(base);
+ struct nv04_fifo *fifo = chan->fifo;
struct nvkm_device *device = fifo->base.engine.subdev.device;
struct nvkm_memory *fctx = device->imem->ramfc;
struct ramfc_desc *c;
unsigned long flags;
+ u32 mask = fifo->base.nr - 1;
u32 data = chan->ramfc;
u32 chid;
@@ -107,7 +84,7 @@ nv04_fifo_chan_fini(struct nvkm_object *object, bool suspend)
nvkm_wr32(device, NV03_PFIFO_CACHES, 0);
/* if this channel is active, replace it with a null context */
- chid = nvkm_rd32(device, NV03_PFIFO_CACHE1_PUSH1) & fifo->base.max;
+ chid = nvkm_rd32(device, NV03_PFIFO_CACHE1_PUSH1) & mask;
if (chid == chan->base.chid) {
nvkm_mask(device, NV04_PFIFO_CACHE1_DMA_PUSH, 0x00000001, 0);
nvkm_wr32(device, NV03_PFIFO_CACHE1_PUSH0, 0);
@@ -129,7 +106,7 @@ nv04_fifo_chan_fini(struct nvkm_object *object, bool suspend)
nvkm_wr32(device, NV03_PFIFO_CACHE1_GET, 0);
nvkm_wr32(device, NV03_PFIFO_CACHE1_PUT, 0);
- nvkm_wr32(device, NV03_PFIFO_CACHE1_PUSH1, fifo->base.max);
+ nvkm_wr32(device, NV03_PFIFO_CACHE1_PUSH1, mask);
nvkm_wr32(device, NV03_PFIFO_CACHE1_PUSH0, 1);
nvkm_wr32(device, NV04_PFIFO_CACHE1_PULL0, 1);
}
@@ -138,35 +115,26 @@ nv04_fifo_chan_fini(struct nvkm_object *object, bool suspend)
nvkm_mask(device, NV04_PFIFO_MODE, 1 << chan->base.chid, 0);
nvkm_wr32(device, NV03_PFIFO_CACHES, 1);
spin_unlock_irqrestore(&fifo->base.lock, flags);
-
- return nvkm_fifo_channel_fini(&chan->base, suspend);
}
-int
-nv04_fifo_chan_init(struct nvkm_object *object)
+void
+nv04_fifo_dma_init(struct nvkm_fifo_chan *base)
{
- struct nv04_fifo *fifo = (void *)object->engine;
- struct nv04_fifo_chan *chan = (void *)object;
+ struct nv04_fifo_chan *chan = nv04_fifo_chan(base);
+ struct nv04_fifo *fifo = chan->fifo;
struct nvkm_device *device = fifo->base.engine.subdev.device;
u32 mask = 1 << chan->base.chid;
unsigned long flags;
- int ret;
-
- ret = nvkm_fifo_channel_init(&chan->base);
- if (ret)
- return ret;
-
spin_lock_irqsave(&fifo->base.lock, flags);
nvkm_mask(device, NV04_PFIFO_MODE, mask, mask);
spin_unlock_irqrestore(&fifo->base.lock, flags);
- return 0;
}
-void
-nv04_fifo_chan_dtor(struct nvkm_object *object)
+void *
+nv04_fifo_dma_dtor(struct nvkm_fifo_chan *base)
{
- struct nv04_fifo *fifo = (void *)object->engine;
- struct nv04_fifo_chan *chan = (void *)object;
+ struct nv04_fifo_chan *chan = nv04_fifo_chan(base);
+ struct nv04_fifo *fifo = chan->fifo;
struct nvkm_instmem *imem = fifo->base.engine.subdev.device->imem;
struct ramfc_desc *c = fifo->ramfc_desc;
@@ -175,22 +143,30 @@ nv04_fifo_chan_dtor(struct nvkm_object *object)
nvkm_wo32(imem->ramfc, chan->ramfc + c->ctxp, 0x00000000);
} while ((++c)->bits);
nvkm_done(imem->ramfc);
-
- nvkm_fifo_channel_destroy(&chan->base);
+ return chan;
}
+const struct nvkm_fifo_chan_func
+nv04_fifo_dma_func = {
+ .dtor = nv04_fifo_dma_dtor,
+ .init = nv04_fifo_dma_init,
+ .fini = nv04_fifo_dma_fini,
+ .object_ctor = nv04_fifo_dma_object_ctor,
+ .object_dtor = nv04_fifo_dma_object_dtor,
+};
+
static int
-nv04_fifo_chan_ctor(struct nvkm_object *parent,
- struct nvkm_object *engine,
- struct nvkm_oclass *oclass, void *data, u32 size,
- struct nvkm_object **pobject)
+nv04_fifo_dma_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass,
+ void *data, u32 size, struct nvkm_object **pobject)
{
+ struct nvkm_object *parent = oclass->parent;
union {
struct nv03_channel_dma_v0 v0;
} *args = data;
- struct nv04_fifo *fifo = (void *)engine;
- struct nvkm_instmem *imem = fifo->base.engine.subdev.device->imem;
- struct nv04_fifo_chan *chan;
+ struct nv04_fifo *fifo = nv04_fifo(base);
+ struct nv04_fifo_chan *chan = NULL;
+ struct nvkm_device *device = fifo->base.engine.subdev.device;
+ struct nvkm_instmem *imem = device->imem;
int ret;
nvif_ioctl(parent, "create channel dma size %d\n", size);
@@ -198,29 +174,32 @@ nv04_fifo_chan_ctor(struct nvkm_object *parent,
nvif_ioctl(parent, "create channel dma vers %d pushbuf %llx "
"offset %08x\n", args->v0.version,
args->v0.pushbuf, args->v0.offset);
+ if (!args->v0.pushbuf)
+ return -EINVAL;
} else
return ret;
- ret = nvkm_fifo_channel_create(parent, engine, oclass, 0, 0x800000,
- 0x10000, args->v0.pushbuf,
- (1ULL << NVDEV_ENGINE_DMAOBJ) |
- (1ULL << NVDEV_ENGINE_SW) |
- (1ULL << NVDEV_ENGINE_GR), &chan);
- *pobject = nv_object(chan);
+ if (!(chan = kzalloc(sizeof(*chan), GFP_KERNEL)))
+ return -ENOMEM;
+ *pobject = &chan->base.object;
+
+ ret = nvkm_fifo_chan_ctor(&nv04_fifo_dma_func, &fifo->base,
+ 0x1000, 0x1000, false, 0, args->v0.pushbuf,
+ (1ULL << NVDEV_ENGINE_DMAOBJ) |
+ (1ULL << NVDEV_ENGINE_GR) |
+ (1ULL << NVDEV_ENGINE_SW),
+ 0, 0x800000, 0x10000, oclass, &chan->base);
+ chan->fifo = fifo;
if (ret)
return ret;
args->v0.chid = chan->base.chid;
-
- nv_parent(chan)->object_attach = nv04_fifo_object_attach;
- nv_parent(chan)->object_detach = nv04_fifo_object_detach;
- nv_parent(chan)->context_attach = nv04_fifo_context_attach;
chan->ramfc = chan->base.chid * 32;
nvkm_kmap(imem->ramfc);
nvkm_wo32(imem->ramfc, chan->ramfc + 0x00, args->v0.offset);
nvkm_wo32(imem->ramfc, chan->ramfc + 0x04, args->v0.offset);
- nvkm_wo32(imem->ramfc, chan->ramfc + 0x08, chan->base.pushgpu->addr >> 4);
+ nvkm_wo32(imem->ramfc, chan->ramfc + 0x08, chan->base.push->addr >> 4);
nvkm_wo32(imem->ramfc, chan->ramfc + 0x10,
NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES |
NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES |
@@ -232,51 +211,10 @@ nv04_fifo_chan_ctor(struct nvkm_object *parent,
return 0;
}
-static struct nvkm_ofuncs
-nv04_fifo_ofuncs = {
- .ctor = nv04_fifo_chan_ctor,
- .dtor = nv04_fifo_chan_dtor,
- .init = nv04_fifo_chan_init,
- .fini = nv04_fifo_chan_fini,
- .map = _nvkm_fifo_channel_map,
- .rd32 = _nvkm_fifo_channel_rd32,
- .wr32 = _nvkm_fifo_channel_wr32,
- .ntfy = _nvkm_fifo_channel_ntfy
-};
-
-struct nvkm_oclass
-nv04_fifo_sclass[] = {
- { NV03_CHANNEL_DMA, &nv04_fifo_ofuncs },
- {}
-};
-
-int
-nv04_fifo_context_ctor(struct nvkm_object *parent,
- struct nvkm_object *engine,
- struct nvkm_oclass *oclass, void *data, u32 size,
- struct nvkm_object **pobject)
-{
- struct nv04_fifo_base *base;
- int ret;
-
- ret = nvkm_fifo_context_create(parent, engine, oclass, NULL, 0x1000,
- 0x1000, NVOBJ_FLAG_HEAP, &base);
- *pobject = nv_object(base);
- if (ret)
- return ret;
-
- return 0;
-}
-
-struct nvkm_oclass
-nv04_fifo_cclass = {
- .handle = NV_ENGCTX(FIFO, 0x04),
- .ofuncs = &(struct nvkm_ofuncs) {
- .ctor = nv04_fifo_context_ctor,
- .dtor = _nvkm_fifo_context_dtor,
- .init = _nvkm_fifo_context_init,
- .fini = _nvkm_fifo_context_fini,
- .rd32 = _nvkm_fifo_context_rd32,
- .wr32 = _nvkm_fifo_context_wr32,
- },
+const struct nvkm_fifo_chan_oclass
+nv04_fifo_dma_oclass = {
+ .base.oclass = NV03_CHANNEL_DMA,
+ .base.minver = 0,
+ .base.maxver = 0,
+ .ctor = nv04_fifo_dma_new,
};
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv10.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv10.c
index a542515e63f0..1ad16205305f 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv10.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv10.c
@@ -31,17 +31,17 @@
#include <nvif/unpack.h>
static int
-nv10_fifo_chan_ctor(struct nvkm_object *parent,
- struct nvkm_object *engine,
- struct nvkm_oclass *oclass, void *data, u32 size,
- struct nvkm_object **pobject)
+nv10_fifo_dma_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass,
+ void *data, u32 size, struct nvkm_object **pobject)
{
+ struct nvkm_object *parent = oclass->parent;
union {
struct nv03_channel_dma_v0 v0;
} *args = data;
- struct nv04_fifo *fifo = (void *)engine;
- struct nvkm_instmem *imem = fifo->base.engine.subdev.device->imem;
- struct nv04_fifo_chan *chan;
+ struct nv04_fifo *fifo = nv04_fifo(base);
+ struct nv04_fifo_chan *chan = NULL;
+ struct nvkm_device *device = fifo->base.engine.subdev.device;
+ struct nvkm_instmem *imem = device->imem;
int ret;
nvif_ioctl(parent, "create channel dma size %d\n", size);
@@ -49,29 +49,32 @@ nv10_fifo_chan_ctor(struct nvkm_object *parent,
nvif_ioctl(parent, "create channel dma vers %d pushbuf %llx "
"offset %08x\n", args->v0.version,
args->v0.pushbuf, args->v0.offset);
+ if (!args->v0.pushbuf)
+ return -EINVAL;
} else
return ret;
- ret = nvkm_fifo_channel_create(parent, engine, oclass, 0, 0x800000,
- 0x10000, args->v0.pushbuf,
- (1ULL << NVDEV_ENGINE_DMAOBJ) |
- (1ULL << NVDEV_ENGINE_SW) |
- (1ULL << NVDEV_ENGINE_GR), &chan);
- *pobject = nv_object(chan);
+ if (!(chan = kzalloc(sizeof(*chan), GFP_KERNEL)))
+ return -ENOMEM;
+ *pobject = &chan->base.object;
+
+ ret = nvkm_fifo_chan_ctor(&nv04_fifo_dma_func, &fifo->base,
+ 0x1000, 0x1000, false, 0, args->v0.pushbuf,
+ (1ULL << NVDEV_ENGINE_DMAOBJ) |
+ (1ULL << NVDEV_ENGINE_GR) |
+ (1ULL << NVDEV_ENGINE_SW),
+ 0, 0x800000, 0x10000, oclass, &chan->base);
+ chan->fifo = fifo;
if (ret)
return ret;
args->v0.chid = chan->base.chid;
-
- nv_parent(chan)->object_attach = nv04_fifo_object_attach;
- nv_parent(chan)->object_detach = nv04_fifo_object_detach;
- nv_parent(chan)->context_attach = nv04_fifo_context_attach;
chan->ramfc = chan->base.chid * 32;
nvkm_kmap(imem->ramfc);
nvkm_wo32(imem->ramfc, chan->ramfc + 0x00, args->v0.offset);
nvkm_wo32(imem->ramfc, chan->ramfc + 0x04, args->v0.offset);
- nvkm_wo32(imem->ramfc, chan->ramfc + 0x0c, chan->base.pushgpu->addr >> 4);
+ nvkm_wo32(imem->ramfc, chan->ramfc + 0x0c, chan->base.push->addr >> 4);
nvkm_wo32(imem->ramfc, chan->ramfc + 0x14,
NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES |
NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES |
@@ -83,20 +86,10 @@ nv10_fifo_chan_ctor(struct nvkm_object *parent,
return 0;
}
-static struct nvkm_ofuncs
-nv10_fifo_ofuncs = {
- .ctor = nv10_fifo_chan_ctor,
- .dtor = nv04_fifo_chan_dtor,
- .init = nv04_fifo_chan_init,
- .fini = nv04_fifo_chan_fini,
- .map = _nvkm_fifo_channel_map,
- .rd32 = _nvkm_fifo_channel_rd32,
- .wr32 = _nvkm_fifo_channel_wr32,
- .ntfy = _nvkm_fifo_channel_ntfy
-};
-
-struct nvkm_oclass
-nv10_fifo_sclass[] = {
- { NV10_CHANNEL_DMA, &nv10_fifo_ofuncs },
- {}
+const struct nvkm_fifo_chan_oclass
+nv10_fifo_dma_oclass = {
+ .base.oclass = NV10_CHANNEL_DMA,
+ .base.minver = 0,
+ .base.maxver = 0,
+ .ctor = nv10_fifo_dma_new,
};
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv17.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv17.c
index d0ece53a750b..2fbb9d4f0900 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv17.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv17.c
@@ -31,17 +31,17 @@
#include <nvif/unpack.h>
static int
-nv17_fifo_chan_ctor(struct nvkm_object *parent,
- struct nvkm_object *engine,
- struct nvkm_oclass *oclass, void *data, u32 size,
- struct nvkm_object **pobject)
+nv17_fifo_dma_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass,
+ void *data, u32 size, struct nvkm_object **pobject)
{
+ struct nvkm_object *parent = oclass->parent;
union {
struct nv03_channel_dma_v0 v0;
} *args = data;
- struct nv04_fifo *fifo = (void *)engine;
- struct nvkm_instmem *imem = fifo->base.engine.subdev.device->imem;
- struct nv04_fifo_chan *chan;
+ struct nv04_fifo *fifo = nv04_fifo(base);
+ struct nv04_fifo_chan *chan = NULL;
+ struct nvkm_device *device = fifo->base.engine.subdev.device;
+ struct nvkm_instmem *imem = device->imem;
int ret;
nvif_ioctl(parent, "create channel dma size %d\n", size);
@@ -49,31 +49,33 @@ nv17_fifo_chan_ctor(struct nvkm_object *parent,
nvif_ioctl(parent, "create channel dma vers %d pushbuf %llx "
"offset %08x\n", args->v0.version,
args->v0.pushbuf, args->v0.offset);
+ if (!args->v0.pushbuf)
+ return -EINVAL;
} else
return ret;
- ret = nvkm_fifo_channel_create(parent, engine, oclass, 0, 0x800000,
- 0x10000, args->v0.pushbuf,
- (1ULL << NVDEV_ENGINE_DMAOBJ) |
- (1ULL << NVDEV_ENGINE_SW) |
- (1ULL << NVDEV_ENGINE_GR) |
- (1ULL << NVDEV_ENGINE_MPEG), /* NV31- */
- &chan);
- *pobject = nv_object(chan);
+ if (!(chan = kzalloc(sizeof(*chan), GFP_KERNEL)))
+ return -ENOMEM;
+ *pobject = &chan->base.object;
+
+ ret = nvkm_fifo_chan_ctor(&nv04_fifo_dma_func, &fifo->base,
+ 0x1000, 0x1000, false, 0, args->v0.pushbuf,
+ (1ULL << NVDEV_ENGINE_DMAOBJ) |
+ (1ULL << NVDEV_ENGINE_GR) |
+ (1ULL << NVDEV_ENGINE_MPEG) | /* NV31- */
+ (1ULL << NVDEV_ENGINE_SW),
+ 0, 0x800000, 0x10000, oclass, &chan->base);
+ chan->fifo = fifo;
if (ret)
return ret;
args->v0.chid = chan->base.chid;
-
- nv_parent(chan)->object_attach = nv04_fifo_object_attach;
- nv_parent(chan)->object_detach = nv04_fifo_object_detach;
- nv_parent(chan)->context_attach = nv04_fifo_context_attach;
chan->ramfc = chan->base.chid * 64;
nvkm_kmap(imem->ramfc);
nvkm_wo32(imem->ramfc, chan->ramfc + 0x00, args->v0.offset);
nvkm_wo32(imem->ramfc, chan->ramfc + 0x04, args->v0.offset);
- nvkm_wo32(imem->ramfc, chan->ramfc + 0x0c, chan->base.pushgpu->addr >> 4);
+ nvkm_wo32(imem->ramfc, chan->ramfc + 0x0c, chan->base.push->addr >> 4);
nvkm_wo32(imem->ramfc, chan->ramfc + 0x14,
NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES |
NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES |
@@ -85,20 +87,10 @@ nv17_fifo_chan_ctor(struct nvkm_object *parent,
return 0;
}
-static struct nvkm_ofuncs
-nv17_fifo_ofuncs = {
- .ctor = nv17_fifo_chan_ctor,
- .dtor = nv04_fifo_chan_dtor,
- .init = nv04_fifo_chan_init,
- .fini = nv04_fifo_chan_fini,
- .map = _nvkm_fifo_channel_map,
- .rd32 = _nvkm_fifo_channel_rd32,
- .wr32 = _nvkm_fifo_channel_wr32,
- .ntfy = _nvkm_fifo_channel_ntfy
-};
-
-struct nvkm_oclass
-nv17_fifo_sclass[] = {
- { NV17_CHANNEL_DMA, &nv17_fifo_ofuncs },
- {}
+const struct nvkm_fifo_chan_oclass
+nv17_fifo_dma_oclass = {
+ .base.oclass = NV17_CHANNEL_DMA,
+ .base.minver = 0,
+ .base.maxver = 0,
+ .ctor = nv17_fifo_dma_new,
};
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv40.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv40.c
index cd3503cb6837..b46a3b3cd092 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv40.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv40.c
@@ -31,36 +31,47 @@
#include <nvif/class.h>
#include <nvif/unpack.h>
+static bool
+nv40_fifo_dma_engine(struct nvkm_engine *engine, u32 *reg, u32 *ctx)
+{
+ switch (engine->subdev.index) {
+ case NVDEV_ENGINE_DMAOBJ:
+ case NVDEV_ENGINE_SW:
+ return false;
+ case NVDEV_ENGINE_GR:
+ *reg = 0x0032e0;
+ *ctx = 0x38;
+ return true;
+ case NVDEV_ENGINE_MPEG:
+ *reg = 0x00330c;
+ *ctx = 0x54;
+ return true;
+ default:
+ WARN_ON(1);
+ return false;
+ }
+}
+
static int
-nv40_fifo_context_detach(struct nvkm_object *parent, bool suspend,
- struct nvkm_object *engctx)
+nv40_fifo_dma_engine_fini(struct nvkm_fifo_chan *base,
+ struct nvkm_engine *engine, bool suspend)
{
- struct nv04_fifo *fifo = (void *)parent->engine;
- struct nv04_fifo_chan *chan = (void *)parent;
+ struct nv04_fifo_chan *chan = nv04_fifo_chan(base);
+ struct nv04_fifo *fifo = chan->fifo;
struct nvkm_device *device = fifo->base.engine.subdev.device;
struct nvkm_instmem *imem = device->imem;
unsigned long flags;
u32 reg, ctx;
+ int chid;
- switch (nv_engidx(engctx->engine)) {
- case NVDEV_ENGINE_SW:
+ if (!nv40_fifo_dma_engine(engine, &reg, &ctx))
return 0;
- case NVDEV_ENGINE_GR:
- reg = 0x32e0;
- ctx = 0x38;
- break;
- case NVDEV_ENGINE_MPEG:
- reg = 0x330c;
- ctx = 0x54;
- break;
- default:
- return -EINVAL;
- }
spin_lock_irqsave(&fifo->base.lock, flags);
nvkm_mask(device, 0x002500, 0x00000001, 0x00000000);
- if ((nvkm_rd32(device, 0x003204) & fifo->base.max) == chan->base.chid)
+ chid = nvkm_rd32(device, 0x003204) & (fifo->base.nr - 1);
+ if (chid == chan->base.chid)
nvkm_wr32(device, reg, 0x00000000);
nvkm_kmap(imem->ramfc);
nvkm_wo32(imem->ramfc, chan->ramfc + ctx, 0x00000000);
@@ -72,38 +83,29 @@ nv40_fifo_context_detach(struct nvkm_object *parent, bool suspend,
}
static int
-nv40_fifo_context_attach(struct nvkm_object *parent, struct nvkm_object *engctx)
+nv40_fifo_dma_engine_init(struct nvkm_fifo_chan *base,
+ struct nvkm_engine *engine)
{
- struct nv04_fifo *fifo = (void *)parent->engine;
- struct nv04_fifo_chan *chan = (void *)parent;
+ struct nv04_fifo_chan *chan = nv04_fifo_chan(base);
+ struct nv04_fifo *fifo = chan->fifo;
struct nvkm_device *device = fifo->base.engine.subdev.device;
struct nvkm_instmem *imem = device->imem;
unsigned long flags;
- u32 reg, ctx;
+ u32 inst, reg, ctx;
+ int chid;
- switch (nv_engidx(engctx->engine)) {
- case NVDEV_ENGINE_SW:
+ if (!nv40_fifo_dma_engine(engine, &reg, &ctx))
return 0;
- case NVDEV_ENGINE_GR:
- reg = 0x32e0;
- ctx = 0x38;
- break;
- case NVDEV_ENGINE_MPEG:
- reg = 0x330c;
- ctx = 0x54;
- break;
- default:
- return -EINVAL;
- }
+ inst = chan->engn[engine->subdev.index]->addr >> 4;
spin_lock_irqsave(&fifo->base.lock, flags);
- nv_engctx(engctx)->addr = nv_gpuobj(engctx)->addr >> 4;
nvkm_mask(device, 0x002500, 0x00000001, 0x00000000);
- if ((nvkm_rd32(device, 0x003204) & fifo->base.max) == chan->base.chid)
- nvkm_wr32(device, reg, nv_engctx(engctx)->addr);
+ chid = nvkm_rd32(device, 0x003204) & (fifo->base.nr - 1);
+ if (chid == chan->base.chid)
+ nvkm_wr32(device, reg, inst);
nvkm_kmap(imem->ramfc);
- nvkm_wo32(imem->ramfc, chan->ramfc + ctx, nv_engctx(engctx)->addr);
+ nvkm_wo32(imem->ramfc, chan->ramfc + ctx, inst);
nvkm_done(imem->ramfc);
nvkm_mask(device, 0x002500, 0x00000001, 0x00000001);
@@ -111,57 +113,91 @@ nv40_fifo_context_attach(struct nvkm_object *parent, struct nvkm_object *engctx)
return 0;
}
+static void
+nv40_fifo_dma_engine_dtor(struct nvkm_fifo_chan *base,
+ struct nvkm_engine *engine)
+{
+ struct nv04_fifo_chan *chan = nv04_fifo_chan(base);
+ if (!chan->engn[engine->subdev.index] ||
+ chan->engn[engine->subdev.index]->object.oclass) {
+ chan->engn[engine->subdev.index] = NULL;
+ return;
+ }
+ nvkm_gpuobj_del(&chan->engn[engine->subdev.index]);
+}
+
static int
-nv40_fifo_object_attach(struct nvkm_object *parent,
- struct nvkm_object *object, u32 handle)
+nv40_fifo_dma_engine_ctor(struct nvkm_fifo_chan *base,
+ struct nvkm_engine *engine,
+ struct nvkm_object *object)
{
- struct nv04_fifo *fifo = (void *)parent->engine;
- struct nv04_fifo_chan *chan = (void *)parent;
- struct nvkm_instmem *imem = fifo->base.engine.subdev.device->imem;
- u32 context, chid = chan->base.chid;
- int ret;
+ struct nv04_fifo_chan *chan = nv04_fifo_chan(base);
+ const int engn = engine->subdev.index;
+ u32 reg, ctx;
- if (nv_iclass(object, NV_GPUOBJ_CLASS))
- context = nv_gpuobj(object)->addr >> 4;
- else
- context = 0x00000004; /* just non-zero */
-
- if (object->engine) {
- switch (nv_engidx(object->engine)) {
- case NVDEV_ENGINE_DMAOBJ:
- case NVDEV_ENGINE_SW:
- context |= 0x00000000;
- break;
- case NVDEV_ENGINE_GR:
- context |= 0x00100000;
- break;
- case NVDEV_ENGINE_MPEG:
- context |= 0x00200000;
- break;
- default:
- return -EINVAL;
- }
+ if (!nv40_fifo_dma_engine(engine, &reg, &ctx))
+ return 0;
+
+ if (nv_iclass(object, NV_GPUOBJ_CLASS)) {
+ chan->engn[engn] = nv_gpuobj(object);
+ return 0;
}
- context |= chid << 23;
+ return nvkm_object_bind(object, NULL, 0, &chan->engn[engn]);
+}
- mutex_lock(&nv_subdev(fifo)->mutex);
- ret = nvkm_ramht_insert(imem->ramht, NULL, chid, 0, handle, context);
- mutex_unlock(&nv_subdev(fifo)->mutex);
- return ret;
+static int
+nv40_fifo_dma_object_ctor(struct nvkm_fifo_chan *base,
+ struct nvkm_object *object)
+{
+ struct nv04_fifo_chan *chan = nv04_fifo_chan(base);
+ struct nvkm_instmem *imem = chan->fifo->base.engine.subdev.device->imem;
+ u32 context = chan->base.chid << 23;
+ u32 handle = object->handle;
+ int hash;
+
+ switch (object->engine->subdev.index) {
+ case NVDEV_ENGINE_DMAOBJ:
+ case NVDEV_ENGINE_SW : context |= 0x00000000; break;
+ case NVDEV_ENGINE_GR : context |= 0x00100000; break;
+ case NVDEV_ENGINE_MPEG : context |= 0x00200000; break;
+ default:
+ WARN_ON(1);
+ return -EINVAL;
+ }
+
+ mutex_lock(&chan->fifo->base.engine.subdev.mutex);
+ hash = nvkm_ramht_insert(imem->ramht, object, chan->base.chid, 4,
+ handle, context);
+ mutex_unlock(&chan->fifo->base.engine.subdev.mutex);
+ return hash;
}
+static const struct nvkm_fifo_chan_func
+nv40_fifo_dma_func = {
+ .dtor = nv04_fifo_dma_dtor,
+ .init = nv04_fifo_dma_init,
+ .fini = nv04_fifo_dma_fini,
+ .engine_ctor = nv40_fifo_dma_engine_ctor,
+ .engine_dtor = nv40_fifo_dma_engine_dtor,
+ .engine_init = nv40_fifo_dma_engine_init,
+ .engine_fini = nv40_fifo_dma_engine_fini,
+ .object_ctor = nv40_fifo_dma_object_ctor,
+ .object_dtor = nv04_fifo_dma_object_dtor,
+};
+
static int
-nv40_fifo_chan_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
- struct nvkm_oclass *oclass, void *data, u32 size,
- struct nvkm_object **pobject)
+nv40_fifo_dma_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass,
+ void *data, u32 size, struct nvkm_object **pobject)
{
+ struct nvkm_object *parent = oclass->parent;
union {
struct nv03_channel_dma_v0 v0;
} *args = data;
- struct nv04_fifo *fifo = (void *)engine;
- struct nvkm_instmem *imem = fifo->base.engine.subdev.device->imem;
- struct nv04_fifo_chan *chan;
+ struct nv04_fifo *fifo = nv04_fifo(base);
+ struct nv04_fifo_chan *chan = NULL;
+ struct nvkm_device *device = fifo->base.engine.subdev.device;
+ struct nvkm_instmem *imem = device->imem;
int ret;
nvif_ioctl(parent, "create channel dma size %d\n", size);
@@ -169,31 +205,33 @@ nv40_fifo_chan_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
nvif_ioctl(parent, "create channel dma vers %d pushbuf %llx "
"offset %08x\n", args->v0.version,
args->v0.pushbuf, args->v0.offset);
+ if (!args->v0.pushbuf)
+ return -EINVAL;
} else
return ret;
- ret = nvkm_fifo_channel_create(parent, engine, oclass, 0, 0xc00000,
- 0x1000, args->v0.pushbuf,
- (1ULL << NVDEV_ENGINE_DMAOBJ) |
- (1ULL << NVDEV_ENGINE_SW) |
- (1ULL << NVDEV_ENGINE_GR) |
- (1ULL << NVDEV_ENGINE_MPEG), &chan);
- *pobject = nv_object(chan);
+ if (!(chan = kzalloc(sizeof(*chan), GFP_KERNEL)))
+ return -ENOMEM;
+ *pobject = &chan->base.object;
+
+ ret = nvkm_fifo_chan_ctor(&nv40_fifo_dma_func, &fifo->base,
+ 0x1000, 0x1000, false, 0, args->v0.pushbuf,
+ (1ULL << NVDEV_ENGINE_DMAOBJ) |
+ (1ULL << NVDEV_ENGINE_GR) |
+ (1ULL << NVDEV_ENGINE_MPEG) |
+ (1ULL << NVDEV_ENGINE_SW),
+ 0, 0xc00000, 0x1000, oclass, &chan->base);
+ chan->fifo = fifo;
if (ret)
return ret;
args->v0.chid = chan->base.chid;
-
- nv_parent(chan)->context_attach = nv40_fifo_context_attach;
- nv_parent(chan)->context_detach = nv40_fifo_context_detach;
- nv_parent(chan)->object_attach = nv40_fifo_object_attach;
- nv_parent(chan)->object_detach = nv04_fifo_object_detach;
chan->ramfc = chan->base.chid * 128;
nvkm_kmap(imem->ramfc);
nvkm_wo32(imem->ramfc, chan->ramfc + 0x00, args->v0.offset);
nvkm_wo32(imem->ramfc, chan->ramfc + 0x04, args->v0.offset);
- nvkm_wo32(imem->ramfc, chan->ramfc + 0x0c, chan->base.pushgpu->addr >> 4);
+ nvkm_wo32(imem->ramfc, chan->ramfc + 0x0c, chan->base.push->addr >> 4);
nvkm_wo32(imem->ramfc, chan->ramfc + 0x18, 0x30000000 |
NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES |
NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES |
@@ -206,20 +244,10 @@ nv40_fifo_chan_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
return 0;
}
-static struct nvkm_ofuncs
-nv40_fifo_ofuncs = {
- .ctor = nv40_fifo_chan_ctor,
- .dtor = nv04_fifo_chan_dtor,
- .init = nv04_fifo_chan_init,
- .fini = nv04_fifo_chan_fini,
- .map = _nvkm_fifo_channel_map,
- .rd32 = _nvkm_fifo_channel_rd32,
- .wr32 = _nvkm_fifo_channel_wr32,
- .ntfy = _nvkm_fifo_channel_ntfy
-};
-
-struct nvkm_oclass
-nv40_fifo_sclass[] = {
- { NV40_CHANNEL_DMA, &nv40_fifo_ofuncs },
- {}
+const struct nvkm_fifo_chan_oclass
+nv40_fifo_dma_oclass = {
+ .base.oclass = NV40_CHANNEL_DMA,
+ .base.minver = 0,
+ .base.maxver = 0,
+ .ctor = nv40_fifo_dma_new,
};
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv50.c
index 11a283099235..6b3b15f12c39 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv50.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv50.c
@@ -30,15 +30,14 @@
#include <nvif/unpack.h>
static int
-nv50_fifo_chan_ctor_dma(struct nvkm_object *parent, struct nvkm_object *engine,
- struct nvkm_oclass *oclass, void *data, u32 size,
- struct nvkm_object **pobject)
+nv50_fifo_dma_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass,
+ void *data, u32 size, struct nvkm_object **pobject)
{
+ struct nvkm_object *parent = oclass->parent;
union {
struct nv50_channel_dma_v0 v0;
} *args = data;
- struct nvkm_device *device = parent->engine->subdev.device;
- struct nv50_fifo_base *base = (void *)parent;
+ struct nv50_fifo *fifo = nv50_fifo(base);
struct nv50_fifo_chan *chan;
int ret;
@@ -48,68 +47,45 @@ nv50_fifo_chan_ctor_dma(struct nvkm_object *parent, struct nvkm_object *engine,
"pushbuf %llx offset %016llx\n",
args->v0.version, args->v0.vm, args->v0.pushbuf,
args->v0.offset);
- if (args->v0.vm)
- return -ENOENT;
+ if (!args->v0.pushbuf)
+ return -EINVAL;
} else
return ret;
- ret = nvkm_fifo_channel_create(parent, engine, oclass, 0, 0xc00000,
- 0x2000, args->v0.pushbuf,
- (1ULL << NVDEV_ENGINE_DMAOBJ) |
- (1ULL << NVDEV_ENGINE_SW) |
- (1ULL << NVDEV_ENGINE_GR) |
- (1ULL << NVDEV_ENGINE_MPEG), &chan);
- *pobject = nv_object(chan);
+ if (!(chan = kzalloc(sizeof(*chan), GFP_KERNEL)))
+ return -ENOMEM;
+ *pobject = &chan->base.object;
+
+ ret = nv50_fifo_chan_ctor(fifo, args->v0.vm, args->v0.pushbuf,
+ oclass, chan);
if (ret)
return ret;
- chan->base.inst = base->base.gpuobj.addr;
args->v0.chid = chan->base.chid;
- nv_parent(chan)->context_attach = nv50_fifo_context_attach;
- nv_parent(chan)->context_detach = nv50_fifo_context_detach;
- nv_parent(chan)->object_attach = nv50_fifo_object_attach;
- nv_parent(chan)->object_detach = nv50_fifo_object_detach;
-
- ret = nvkm_ramht_new(device, 0x8000, 16, &base->base.gpuobj,
- &chan->ramht);
- if (ret)
- return ret;
-
- nvkm_kmap(base->ramfc);
- nvkm_wo32(base->ramfc, 0x08, lower_32_bits(args->v0.offset));
- nvkm_wo32(base->ramfc, 0x0c, upper_32_bits(args->v0.offset));
- nvkm_wo32(base->ramfc, 0x10, lower_32_bits(args->v0.offset));
- nvkm_wo32(base->ramfc, 0x14, upper_32_bits(args->v0.offset));
- nvkm_wo32(base->ramfc, 0x3c, 0x003f6078);
- nvkm_wo32(base->ramfc, 0x44, 0x01003fff);
- nvkm_wo32(base->ramfc, 0x48, chan->base.pushgpu->node->offset >> 4);
- nvkm_wo32(base->ramfc, 0x4c, 0xffffffff);
- nvkm_wo32(base->ramfc, 0x60, 0x7fffffff);
- nvkm_wo32(base->ramfc, 0x78, 0x00000000);
- nvkm_wo32(base->ramfc, 0x7c, 0x30000001);
- nvkm_wo32(base->ramfc, 0x80, ((chan->ramht->bits - 9) << 27) |
+ nvkm_kmap(chan->ramfc);
+ nvkm_wo32(chan->ramfc, 0x08, lower_32_bits(args->v0.offset));
+ nvkm_wo32(chan->ramfc, 0x0c, upper_32_bits(args->v0.offset));
+ nvkm_wo32(chan->ramfc, 0x10, lower_32_bits(args->v0.offset));
+ nvkm_wo32(chan->ramfc, 0x14, upper_32_bits(args->v0.offset));
+ nvkm_wo32(chan->ramfc, 0x3c, 0x003f6078);
+ nvkm_wo32(chan->ramfc, 0x44, 0x01003fff);
+ nvkm_wo32(chan->ramfc, 0x48, chan->base.push->node->offset >> 4);
+ nvkm_wo32(chan->ramfc, 0x4c, 0xffffffff);
+ nvkm_wo32(chan->ramfc, 0x60, 0x7fffffff);
+ nvkm_wo32(chan->ramfc, 0x78, 0x00000000);
+ nvkm_wo32(chan->ramfc, 0x7c, 0x30000001);
+ nvkm_wo32(chan->ramfc, 0x80, ((chan->ramht->bits - 9) << 27) |
(4 << 24) /* SEARCH_FULL */ |
(chan->ramht->gpuobj->node->offset >> 4));
- nvkm_done(base->ramfc);
+ nvkm_done(chan->ramfc);
return 0;
}
-static struct nvkm_ofuncs
-nv50_fifo_ofuncs_dma = {
- .ctor = nv50_fifo_chan_ctor_dma,
- .dtor = nv50_fifo_chan_dtor,
- .init = nv50_fifo_chan_init,
- .fini = nv50_fifo_chan_fini,
- .map = _nvkm_fifo_channel_map,
- .rd32 = _nvkm_fifo_channel_rd32,
- .wr32 = _nvkm_fifo_channel_wr32,
- .ntfy = _nvkm_fifo_channel_ntfy
-};
-
-struct nvkm_oclass
-nv50_fifo_sclass[] = {
- { NV50_CHANNEL_DMA, &nv50_fifo_ofuncs_dma },
- { NV50_CHANNEL_GPFIFO, &nv50_fifo_ofuncs_ind },
- {}
+const struct nvkm_fifo_chan_oclass
+nv50_fifo_dma_oclass = {
+ .base.oclass = NV50_CHANNEL_DMA,
+ .base.minver = 0,
+ .base.maxver = 0,
+ .ctor = nv50_fifo_dma_new,
};
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/g84.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/g84.c
index ab0ecc423e68..00fa9d3eff7a 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/g84.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/g84.c
@@ -47,6 +47,15 @@ g84_fifo_uevent_func = {
.fini = g84_fifo_uevent_fini,
};
+static const struct nvkm_fifo_func
+g84_fifo_func = {
+ .chan = {
+ &g84_fifo_dma_oclass,
+ &g84_fifo_gpfifo_oclass,
+ NULL
+ },
+};
+
static int
g84_fifo_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
struct nvkm_oclass *oclass, void *data, u32 size,
@@ -61,6 +70,8 @@ g84_fifo_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
if (ret)
return ret;
+ fifo->base.func = &g84_fifo_func;
+
ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, 128 * 4, 0x1000,
false, &fifo->runlist[0]);
if (ret)
@@ -77,8 +88,6 @@ g84_fifo_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
nv_subdev(fifo)->unit = 0x00000100;
nv_subdev(fifo)->intr = nv04_fifo_intr;
- nv_engine(fifo)->cclass = &g84_fifo_cclass;
- nv_engine(fifo)->sclass = g84_fifo_sclass;
fifo->base.pause = nv04_fifo_pause;
fifo->base.start = nv04_fifo_start;
return 0;
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c
index b88e7c569c0a..bdad44e84b92 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c
@@ -58,28 +58,26 @@ gf100_fifo_uevent_func = {
void
gf100_fifo_runlist_update(struct gf100_fifo *fifo)
{
+ struct gf100_fifo_chan *chan;
struct nvkm_subdev *subdev = &fifo->base.engine.subdev;
struct nvkm_device *device = subdev->device;
struct nvkm_memory *cur;
- int i, p;
+ int nr = 0;
mutex_lock(&nv_subdev(fifo)->mutex);
cur = fifo->runlist.mem[fifo->runlist.active];
fifo->runlist.active = !fifo->runlist.active;
nvkm_kmap(cur);
- for (i = 0, p = 0; i < 128; i++) {
- struct gf100_fifo_chan *chan = (void *)fifo->base.channel[i];
- if (chan && chan->state == RUNNING) {
- nvkm_wo32(cur, p + 0, i);
- nvkm_wo32(cur, p + 4, 0x00000004);
- p += 8;
- }
+ list_for_each_entry(chan, &fifo->chan, head) {
+ nvkm_wo32(cur, (nr * 8) + 0, chan->base.chid);
+ nvkm_wo32(cur, (nr * 8) + 4, 0x00000004);
+ nr++;
}
nvkm_done(cur);
nvkm_wr32(device, 0x002270, nvkm_memory_addr(cur) >> 12);
- nvkm_wr32(device, 0x002274, 0x01f00000 | (p >> 3));
+ nvkm_wr32(device, 0x002274, 0x01f00000 | nr);
if (wait_event_timeout(fifo->runlist.wait,
!(nvkm_rd32(device, 0x00227c) & 0x00100000),
@@ -166,7 +164,8 @@ gf100_fifo_recover(struct gf100_fifo *fifo, struct nvkm_engine *engine,
assert_spin_locked(&fifo->base.lock);
nvkm_mask(device, 0x003004 + (chid * 0x08), 0x00000001, 0x00000000);
- chan->state = KILLED;
+ list_del_init(&chan->head);
+ chan->killed = true;
fifo->mask |= 1ULL << nv_engidx(engine);
schedule_work(&fifo->fault);
@@ -198,11 +197,15 @@ gf100_fifo_intr_sched_ctxsw(struct gf100_fifo *fifo)
(void)save;
if (busy && unk0 && unk1) {
- if (!(chan = (void *)fifo->base.channel[chid]))
- continue;
- if (!(engine = gf100_fifo_engine(fifo, engn)))
- continue;
- gf100_fifo_recover(fifo, engine, chan);
+ list_for_each_entry(chan, &fifo->chan, head) {
+ if (chan->base.chid == chid) {
+ engine = gf100_fifo_engine(fifo, engn);
+ if (!engine)
+ break;
+ gf100_fifo_recover(fifo, engine, chan);
+ break;
+ }
+ }
}
}
spin_unlock_irqrestore(&fifo->base.lock, flags);
@@ -343,7 +346,8 @@ gf100_fifo_intr_fault(struct gf100_fifo *fifo, int unit)
write ? "write" : "read", (u64)vahi << 32 | valo,
unit, eu ? eu->name : "", client, gpcid, ec ? ec->name : "",
reason, er ? er->name : "", chan ? chan->chid : -1,
- (u64)inst << 12, nvkm_client_name(chan));
+ (u64)inst << 12,
+ chan ? chan->object.client->name : "unknown");
if (engine && chan)
gf100_fifo_recover(fifo, engine, (void *)chan);
@@ -369,6 +373,8 @@ gf100_fifo_intr_pbdma(struct gf100_fifo *fifo, int unit)
u32 chid = nvkm_rd32(device, 0x040120 + (unit * 0x2000)) & 0x7f;
u32 subc = (addr & 0x00070000) >> 16;
u32 mthd = (addr & 0x00003ffc);
+ struct nvkm_fifo_chan *chan;
+ unsigned long flags;
u32 show= stat;
char msg[128];
@@ -381,11 +387,13 @@ gf100_fifo_intr_pbdma(struct gf100_fifo *fifo, int unit)
if (show) {
nvkm_snprintbf(msg, sizeof(msg), gf100_fifo_pbdma_intr, show);
- nvkm_error(subdev, "PBDMA%d: %08x [%s] ch %d [%s] subc %d "
- "mthd %04x data %08x\n",
- unit, show, msg, chid,
- nvkm_client_name_for_fifo_chid(&fifo->base, chid),
+ chan = nvkm_fifo_chan_chid(&fifo->base, chid, &flags);
+ nvkm_error(subdev, "PBDMA%d: %08x [%s] ch %d [%010llx %s] "
+ "subc %d mthd %04x data %08x\n",
+ unit, show, msg, chid, chan ? chan->inst->addr : 0,
+ chan ? chan->object.client->name : "unknown",
subc, mthd, data);
+ nvkm_fifo_chan_put(&fifo->base, flags, &chan);
}
nvkm_wr32(device, 0x0400c0 + (unit * 0x2000), 0x80600008);
@@ -579,6 +587,14 @@ gf100_fifo_dtor(struct nvkm_object *object)
nvkm_fifo_destroy(&fifo->base);
}
+static const struct nvkm_fifo_func
+gf100_fifo_func = {
+ .chan = {
+ &gf100_fifo_gpfifo_oclass,
+ NULL
+ },
+};
+
static int
gf100_fifo_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
struct nvkm_oclass *oclass, void *data, u32 size,
@@ -594,6 +610,9 @@ gf100_fifo_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
if (ret)
return ret;
+ fifo->base.func = &gf100_fifo_func;
+
+ INIT_LIST_HEAD(&fifo->chan);
INIT_WORK(&fifo->fault, gf100_fifo_recover_work);
ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, 0x1000, 0x1000,
@@ -625,8 +644,6 @@ gf100_fifo_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
nv_subdev(fifo)->unit = 0x00000100;
nv_subdev(fifo)->intr = gf100_fifo_intr;
- nv_engine(fifo)->cclass = &gf100_fifo_cclass;
- nv_engine(fifo)->sclass = gf100_fifo_sclass;
return 0;
}
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.h
index 5190bbc6e1a1..c649ca9b53e3 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.h
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.h
@@ -1,10 +1,15 @@
#ifndef __GF100_FIFO_H__
#define __GF100_FIFO_H__
+#define gf100_fifo(p) container_of((p), struct gf100_fifo, base)
#include "priv.h"
+#include <subdev/mmu.h>
+
struct gf100_fifo {
struct nvkm_fifo base;
+ struct list_head chan;
+
struct work_struct fault;
u64 mask;
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c
index 9ab3fd40b7dd..e7f467997194 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c
@@ -32,23 +32,6 @@
#include <nvif/class.h>
-#define _(a,b) { (a), ((1ULL << (a)) | (b)) }
-static const struct {
- u64 subdev;
- u64 mask;
-} fifo_engine[] = {
- _(NVDEV_ENGINE_GR , (1ULL << NVDEV_ENGINE_SW) |
- (1ULL << NVDEV_ENGINE_CE2)),
- _(NVDEV_ENGINE_MSPDEC , 0),
- _(NVDEV_ENGINE_MSPPP , 0),
- _(NVDEV_ENGINE_MSVLD , 0),
- _(NVDEV_ENGINE_CE0 , 0),
- _(NVDEV_ENGINE_CE1 , 0),
- _(NVDEV_ENGINE_MSENC , 0),
-};
-#undef _
-#define FIFO_ENGINE_NR ARRAY_SIZE(fifo_engine)
-
static void
gk104_fifo_uevent_fini(struct nvkm_event *event, int type, int index)
{
@@ -76,28 +59,26 @@ void
gk104_fifo_runlist_update(struct gk104_fifo *fifo, u32 engine)
{
struct gk104_fifo_engn *engn = &fifo->engine[engine];
+ struct gk104_fifo_chan *chan;
struct nvkm_subdev *subdev = &fifo->base.engine.subdev;
struct nvkm_device *device = subdev->device;
struct nvkm_memory *cur;
- int i, p;
+ int nr = 0;
mutex_lock(&nv_subdev(fifo)->mutex);
cur = engn->runlist[engn->cur_runlist];
engn->cur_runlist = !engn->cur_runlist;
nvkm_kmap(cur);
- for (i = 0, p = 0; i < fifo->base.max; i++) {
- struct gk104_fifo_chan *chan = (void *)fifo->base.channel[i];
- if (chan && chan->state == RUNNING && chan->engine == engine) {
- nvkm_wo32(cur, p + 0, i);
- nvkm_wo32(cur, p + 4, 0x00000000);
- p += 8;
- }
+ list_for_each_entry(chan, &engn->chan, head) {
+ nvkm_wo32(cur, (nr * 8) + 0, chan->base.chid);
+ nvkm_wo32(cur, (nr * 8) + 4, 0x00000000);
+ nr++;
}
nvkm_done(cur);
nvkm_wr32(device, 0x002270, nvkm_memory_addr(cur) >> 12);
- nvkm_wr32(device, 0x002274, (engine << 20) | (p >> 3));
+ nvkm_wr32(device, 0x002274, (engine << 20) | nr);
if (wait_event_timeout(engn->wait, !(nvkm_rd32(device, 0x002284 +
(engine * 0x08)) & 0x00100000),
@@ -106,31 +87,13 @@ gk104_fifo_runlist_update(struct gk104_fifo *fifo, u32 engine)
mutex_unlock(&nv_subdev(fifo)->mutex);
}
-static inline int
-gk104_fifo_engidx(struct gk104_fifo *fifo, u32 engn)
-{
- switch (engn) {
- case NVDEV_ENGINE_GR :
- case NVDEV_ENGINE_CE2 : engn = 0; break;
- case NVDEV_ENGINE_MSVLD : engn = 1; break;
- case NVDEV_ENGINE_MSPPP : engn = 2; break;
- case NVDEV_ENGINE_MSPDEC: engn = 3; break;
- case NVDEV_ENGINE_CE0 : engn = 4; break;
- case NVDEV_ENGINE_CE1 : engn = 5; break;
- case NVDEV_ENGINE_MSENC : engn = 6; break;
- default:
- return -1;
- }
-
- return engn;
-}
-
static inline struct nvkm_engine *
gk104_fifo_engine(struct gk104_fifo *fifo, u32 engn)
{
- if (engn >= ARRAY_SIZE(fifo_engine))
- return NULL;
- return nvkm_engine(fifo, fifo_engine[engn].subdev);
+ u64 subdevs = gk104_fifo_engine_subdev(engn);
+ if (subdevs)
+ return nvkm_engine(fifo, __ffs(subdevs));
+ return NULL;
}
static void
@@ -149,7 +112,7 @@ gk104_fifo_recover_work(struct work_struct *work)
spin_unlock_irqrestore(&fifo->base.lock, flags);
for (todo = mask; engn = __ffs64(todo), todo; todo &= ~(1 << engn))
- engm |= 1 << gk104_fifo_engidx(fifo, engn);
+ engm |= 1 << gk104_fifo_subdev_engine(engn);
nvkm_mask(device, 0x002630, engm, engm);
for (todo = mask; engn = __ffs64(todo), todo; todo &= ~(1 << engn)) {
@@ -157,7 +120,7 @@ gk104_fifo_recover_work(struct work_struct *work)
nvkm_subdev_fini(&engine->subdev, false);
WARN_ON(nvkm_subdev_init(&engine->subdev));
}
- gk104_fifo_runlist_update(fifo, gk104_fifo_engidx(fifo, engn));
+ gk104_fifo_runlist_update(fifo, gk104_fifo_subdev_engine(engn));
}
nvkm_wr32(device, 0x00262c, engm);
@@ -177,7 +140,8 @@ gk104_fifo_recover(struct gk104_fifo *fifo, struct nvkm_engine *engine,
assert_spin_locked(&fifo->base.lock);
nvkm_mask(device, 0x800004 + (chid * 0x08), 0x00000800, 0x00000800);
- chan->state = KILLED;
+ list_del_init(&chan->head);
+ chan->killed = true;
fifo->mask |= 1ULL << nv_engidx(engine);
schedule_work(&fifo->fault);
@@ -223,7 +187,7 @@ gk104_fifo_intr_sched_ctxsw(struct gk104_fifo *fifo)
u32 engn;
spin_lock_irqsave(&fifo->base.lock, flags);
- for (engn = 0; engn < ARRAY_SIZE(fifo_engine); engn++) {
+ for (engn = 0; engn < ARRAY_SIZE(fifo->engine); engn++) {
u32 stat = nvkm_rd32(device, 0x002640 + (engn * 0x04));
u32 busy = (stat & 0x80000000);
u32 next = (stat & 0x07ff0000) >> 16;
@@ -235,11 +199,15 @@ gk104_fifo_intr_sched_ctxsw(struct gk104_fifo *fifo)
(void)save;
if (busy && chsw) {
- if (!(chan = (void *)fifo->base.channel[chid]))
- continue;
- if (!(engine = gk104_fifo_engine(fifo, engn)))
- continue;
- gk104_fifo_recover(fifo, engine, chan);
+ list_for_each_entry(chan, &fifo->engine[engn].chan, head) {
+ if (chan->base.chid == chid) {
+ engine = gk104_fifo_engine(fifo, engn);
+ if (!engine)
+ break;
+ gk104_fifo_recover(fifo, engine, chan);
+ break;
+ }
+ }
}
}
spin_unlock_irqrestore(&fifo->base.lock, flags);
@@ -444,7 +412,8 @@ gk104_fifo_intr_fault(struct gk104_fifo *fifo, int unit)
write ? "write" : "read", (u64)vahi << 32 | valo,
unit, eu ? eu->name : "", client, gpcid, ec ? ec->name : "",
reason, er ? er->name : "", chan ? chan->chid : -1,
- (u64)inst << 12, nvkm_client_name(chan));
+ (u64)inst << 12,
+ chan ? chan->object.client->name : "unknown");
if (engine && chan)
gk104_fifo_recover(fifo, engine, (void *)chan);
@@ -498,6 +467,8 @@ gk104_fifo_intr_pbdma_0(struct gk104_fifo *fifo, int unit)
u32 subc = (addr & 0x00070000) >> 16;
u32 mthd = (addr & 0x00003ffc);
u32 show = stat;
+ struct nvkm_fifo_chan *chan;
+ unsigned long flags;
char msg[128];
if (stat & 0x00800000) {
@@ -510,11 +481,13 @@ gk104_fifo_intr_pbdma_0(struct gk104_fifo *fifo, int unit)
if (show) {
nvkm_snprintbf(msg, sizeof(msg), gk104_fifo_pbdma_intr_0, show);
- nvkm_error(subdev, "PBDMA%d: %08x [%s] ch %d [%s] subc %d "
- "mthd %04x data %08x\n",
- unit, show, msg, chid,
- nvkm_client_name_for_fifo_chid(&fifo->base, chid),
+ chan = nvkm_fifo_chan_chid(&fifo->base, chid, &flags);
+ nvkm_error(subdev, "PBDMA%d: %08x [%s] ch %d [%010llx %s] "
+ "subc %d mthd %04x data %08x\n",
+ unit, show, msg, chid, chan ? chan->inst->addr : 0,
+ chan ? chan->object.client->name : "unknown",
subc, mthd, data);
+ nvkm_fifo_chan_put(&fifo->base, flags, &chan);
}
nvkm_wr32(device, 0x040108 + (unit * 0x2000), stat);
@@ -722,7 +695,7 @@ gk104_fifo_dtor(struct nvkm_object *object)
nvkm_vm_put(&fifo->user.bar);
nvkm_memory_del(&fifo->user.mem);
- for (i = 0; i < FIFO_ENGINE_NR; i++) {
+ for (i = 0; i < ARRAY_SIZE(fifo->engine); i++) {
nvkm_memory_del(&fifo->engine[i].runlist[1]);
nvkm_memory_del(&fifo->engine[i].runlist[0]);
}
@@ -730,6 +703,14 @@ gk104_fifo_dtor(struct nvkm_object *object)
nvkm_fifo_destroy(&fifo->base);
}
+static const struct nvkm_fifo_func
+gk104_fifo_func = {
+ .chan = {
+ &gk104_fifo_gpfifo_oclass,
+ NULL
+ },
+};
+
int
gk104_fifo_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
struct nvkm_oclass *oclass, void *data, u32 size,
@@ -747,9 +728,11 @@ gk104_fifo_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
if (ret)
return ret;
+ fifo->base.func = &gk104_fifo_func;
+
INIT_WORK(&fifo->fault, gk104_fifo_recover_work);
- for (i = 0; i < FIFO_ENGINE_NR; i++) {
+ for (i = 0; i < ARRAY_SIZE(fifo->engine); i++) {
ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST,
0x8000, 0x1000, false,
&fifo->engine[i].runlist[0]);
@@ -763,6 +746,7 @@ gk104_fifo_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
return ret;
init_waitqueue_head(&fifo->engine[i].wait);
+ INIT_LIST_HEAD(&fifo->engine[i].chan);
}
ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST,
@@ -783,8 +767,6 @@ gk104_fifo_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
nv_subdev(fifo)->unit = 0x00000100;
nv_subdev(fifo)->intr = gk104_fifo_intr;
- nv_engine(fifo)->cclass = &gk104_fifo_cclass;
- nv_engine(fifo)->sclass = gk104_fifo_sclass;
return 0;
}
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h
index b71abef84349..1103e6b1ee5a 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h
@@ -1,11 +1,15 @@
#ifndef __GK104_FIFO_H__
#define __GK104_FIFO_H__
+#define gk104_fifo(p) container_of((p), struct gk104_fifo, base)
#include "priv.h"
+#include <subdev/mmu.h>
+
struct gk104_fifo_engn {
struct nvkm_memory *runlist[2];
int cur_runlist;
wait_queue_head_t wait;
+ struct list_head chan;
};
struct gk104_fifo {
@@ -38,4 +42,42 @@ void gk104_fifo_runlist_update(struct gk104_fifo *, u32 engine);
int gm204_fifo_ctor(struct nvkm_object *, struct nvkm_object *,
struct nvkm_oclass *, void *, u32,
struct nvkm_object **);
+
+static inline u64
+gk104_fifo_engine_subdev(int engine)
+{
+ switch (engine) {
+ case 0: return (1ULL << NVDEV_ENGINE_GR) |
+ (1ULL << NVDEV_ENGINE_SW) |
+ (1ULL << NVDEV_ENGINE_CE2);
+ case 1: return (1ULL << NVDEV_ENGINE_MSPDEC);
+ case 2: return (1ULL << NVDEV_ENGINE_MSPPP);
+ case 3: return (1ULL << NVDEV_ENGINE_MSVLD);
+ case 4: return (1ULL << NVDEV_ENGINE_CE0);
+ case 5: return (1ULL << NVDEV_ENGINE_CE1);
+ case 6: return (1ULL << NVDEV_ENGINE_MSENC);
+ default:
+ WARN_ON(1);
+ return 0;
+ }
+}
+
+static inline int
+gk104_fifo_subdev_engine(int subdev)
+{
+ switch (subdev) {
+ case NVDEV_ENGINE_GR:
+ case NVDEV_ENGINE_SW:
+ case NVDEV_ENGINE_CE2 : return 0;
+ case NVDEV_ENGINE_MSPDEC: return 1;
+ case NVDEV_ENGINE_MSPPP : return 2;
+ case NVDEV_ENGINE_MSVLD : return 3;
+ case NVDEV_ENGINE_CE0 : return 4;
+ case NVDEV_ENGINE_CE1 : return 5;
+ case NVDEV_ENGINE_MSENC : return 6;
+ default:
+ WARN_ON(1);
+ return 0;
+ }
+}
#endif
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm204.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm204.c
index 2367b4f81a91..18c68ac741a0 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm204.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm204.c
@@ -24,6 +24,14 @@
#include "gk104.h"
#include "changk104.h"
+static const struct nvkm_fifo_func
+gm204_fifo_func = {
+ .chan = {
+ &gm204_fifo_gpfifo_oclass,
+ NULL
+ },
+};
+
int
gm204_fifo_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
struct nvkm_oclass *oclass, void *data, u32 size,
@@ -32,7 +40,7 @@ gm204_fifo_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
int ret = gk104_fifo_ctor(parent, engine, oclass, data, size, pobject);
if (ret == 0) {
struct gk104_fifo *fifo = (void *)*pobject;
- nv_engine(fifo)->sclass = gm204_fifo_sclass;
+ fifo->base.func = &gm204_fifo_func;
}
return ret;
}
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifog84.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifog84.c
index fd11e0afec25..820132363f68 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifog84.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifog84.c
@@ -30,15 +30,14 @@
#include <nvif/unpack.h>
static int
-g84_fifo_chan_ctor_ind(struct nvkm_object *parent, struct nvkm_object *engine,
- struct nvkm_oclass *oclass, void *data, u32 size,
- struct nvkm_object **pobject)
+g84_fifo_gpfifo_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass,
+ void *data, u32 size, struct nvkm_object **pobject)
{
+ struct nvkm_object *parent = oclass->parent;
union {
struct nv50_channel_gpfifo_v0 v0;
} *args = data;
- struct nvkm_device *device = parent->engine->subdev.device;
- struct nv50_fifo_base *base = (void *)parent;
+ struct nv50_fifo *fifo = nv50_fifo(base);
struct nv50_fifo_chan *chan;
u64 ioffset, ilength;
int ret;
@@ -50,73 +49,46 @@ g84_fifo_chan_ctor_ind(struct nvkm_object *parent, struct nvkm_object *engine,
"ilength %08x\n",
args->v0.version, args->v0.vm, args->v0.pushbuf,
args->v0.ioffset, args->v0.ilength);
- if (args->v0.vm)
- return -ENOENT;
+ if (!args->v0.pushbuf)
+ return -EINVAL;
} else
return ret;
- ret = nvkm_fifo_channel_create(parent, engine, oclass, 0, 0xc00000,
- 0x2000, args->v0.pushbuf,
- (1ULL << NVDEV_ENGINE_DMAOBJ) |
- (1ULL << NVDEV_ENGINE_SW) |
- (1ULL << NVDEV_ENGINE_GR) |
- (1ULL << NVDEV_ENGINE_MPEG) |
- (1ULL << NVDEV_ENGINE_ME) |
- (1ULL << NVDEV_ENGINE_VP) |
- (1ULL << NVDEV_ENGINE_CIPHER) |
- (1ULL << NVDEV_ENGINE_SEC) |
- (1ULL << NVDEV_ENGINE_BSP) |
- (1ULL << NVDEV_ENGINE_MSVLD) |
- (1ULL << NVDEV_ENGINE_MSPDEC) |
- (1ULL << NVDEV_ENGINE_MSPPP) |
- (1ULL << NVDEV_ENGINE_CE0) |
- (1ULL << NVDEV_ENGINE_VIC), &chan);
- *pobject = nv_object(chan);
- if (ret)
- return ret;
-
- chan->base.inst = base->base.gpuobj.addr;
- args->v0.chid = chan->base.chid;
+ if (!(chan = kzalloc(sizeof(*chan), GFP_KERNEL)))
+ return -ENOMEM;
+ *pobject = &chan->base.object;
- ret = nvkm_ramht_new(device, 0x8000, 16, &base->base.gpuobj,
- &chan->ramht);
+ ret = g84_fifo_chan_ctor(fifo, args->v0.vm, args->v0.pushbuf,
+ oclass, chan);
if (ret)
return ret;
- nv_parent(chan)->context_attach = g84_fifo_context_attach;
- nv_parent(chan)->context_detach = g84_fifo_context_detach;
- nv_parent(chan)->object_attach = g84_fifo_object_attach;
- nv_parent(chan)->object_detach = nv50_fifo_object_detach;
-
+ args->v0.chid = chan->base.chid;
ioffset = args->v0.ioffset;
ilength = order_base_2(args->v0.ilength / 8);
- nvkm_kmap(base->ramfc);
- nvkm_wo32(base->ramfc, 0x3c, 0x403f6078);
- nvkm_wo32(base->ramfc, 0x44, 0x01003fff);
- nvkm_wo32(base->ramfc, 0x48, chan->base.pushgpu->node->offset >> 4);
- nvkm_wo32(base->ramfc, 0x50, lower_32_bits(ioffset));
- nvkm_wo32(base->ramfc, 0x54, upper_32_bits(ioffset) | (ilength << 16));
- nvkm_wo32(base->ramfc, 0x60, 0x7fffffff);
- nvkm_wo32(base->ramfc, 0x78, 0x00000000);
- nvkm_wo32(base->ramfc, 0x7c, 0x30000001);
- nvkm_wo32(base->ramfc, 0x80, ((chan->ramht->bits - 9) << 27) |
+ nvkm_kmap(chan->ramfc);
+ nvkm_wo32(chan->ramfc, 0x3c, 0x403f6078);
+ nvkm_wo32(chan->ramfc, 0x44, 0x01003fff);
+ nvkm_wo32(chan->ramfc, 0x48, chan->base.push->node->offset >> 4);
+ nvkm_wo32(chan->ramfc, 0x50, lower_32_bits(ioffset));
+ nvkm_wo32(chan->ramfc, 0x54, upper_32_bits(ioffset) | (ilength << 16));
+ nvkm_wo32(chan->ramfc, 0x60, 0x7fffffff);
+ nvkm_wo32(chan->ramfc, 0x78, 0x00000000);
+ nvkm_wo32(chan->ramfc, 0x7c, 0x30000001);
+ nvkm_wo32(chan->ramfc, 0x80, ((chan->ramht->bits - 9) << 27) |
(4 << 24) /* SEARCH_FULL */ |
(chan->ramht->gpuobj->node->offset >> 4));
- nvkm_wo32(base->ramfc, 0x88, base->cache->addr >> 10);
- nvkm_wo32(base->ramfc, 0x98, nv_gpuobj(base)->addr >> 12);
- nvkm_done(base->ramfc);
+ nvkm_wo32(chan->ramfc, 0x88, chan->cache->addr >> 10);
+ nvkm_wo32(chan->ramfc, 0x98, chan->base.inst->addr >> 12);
+ nvkm_done(chan->ramfc);
return 0;
}
-struct nvkm_ofuncs
-g84_fifo_ofuncs_ind = {
- .ctor = g84_fifo_chan_ctor_ind,
- .dtor = nv50_fifo_chan_dtor,
- .init = g84_fifo_chan_init,
- .fini = nv50_fifo_chan_fini,
- .map = _nvkm_fifo_channel_map,
- .rd32 = _nvkm_fifo_channel_rd32,
- .wr32 = _nvkm_fifo_channel_wr32,
- .ntfy = _nvkm_fifo_channel_ntfy
+const struct nvkm_fifo_chan_oclass
+g84_fifo_gpfifo_oclass = {
+ .base.oclass = G82_CHANNEL_GPFIFO,
+ .base.minver = 0,
+ .base.maxver = 0,
+ .ctor = g84_fifo_gpfifo_new,
};
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c
index 7fd6401ca905..eb9195a6f375 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c
@@ -30,29 +30,33 @@
#include <nvif/class.h>
#include <nvif/unpack.h>
-static int
-gf100_fifo_context_detach(struct nvkm_object *parent, bool suspend,
- struct nvkm_object *object)
+static u32
+gf100_fifo_gpfifo_engine_addr(struct nvkm_engine *engine)
{
- struct gf100_fifo *fifo = (void *)parent->engine;
- struct gf100_fifo_base *base = (void *)parent->parent;
- struct gf100_fifo_chan *chan = (void *)parent;
- struct nvkm_gpuobj *engn = &base->base.gpuobj;
- struct nvkm_subdev *subdev = &fifo->base.engine.subdev;
- struct nvkm_device *device = subdev->device;
- u32 addr;
-
- switch (nv_engidx(object->engine)) {
+ switch (engine->subdev.index) {
case NVDEV_ENGINE_SW : return 0;
- case NVDEV_ENGINE_GR : addr = 0x0210; break;
- case NVDEV_ENGINE_CE0 : addr = 0x0230; break;
- case NVDEV_ENGINE_CE1 : addr = 0x0240; break;
- case NVDEV_ENGINE_MSVLD : addr = 0x0270; break;
- case NVDEV_ENGINE_MSPDEC: addr = 0x0250; break;
- case NVDEV_ENGINE_MSPPP : addr = 0x0260; break;
+ case NVDEV_ENGINE_GR : return 0x0210;
+ case NVDEV_ENGINE_CE0 : return 0x0230;
+ case NVDEV_ENGINE_CE1 : return 0x0240;
+ case NVDEV_ENGINE_MSPDEC: return 0x0250;
+ case NVDEV_ENGINE_MSPPP : return 0x0260;
+ case NVDEV_ENGINE_MSVLD : return 0x0270;
default:
- return -EINVAL;
+ WARN_ON(1);
+ return 0;
}
+}
+
+static int
+gf100_fifo_gpfifo_engine_fini(struct nvkm_fifo_chan *base,
+ struct nvkm_engine *engine, bool suspend)
+{
+ const u32 offset = gf100_fifo_gpfifo_engine_addr(engine);
+ struct gf100_fifo_chan *chan = gf100_fifo_chan(base);
+ struct nvkm_subdev *subdev = &chan->fifo->base.engine.subdev;
+ struct nvkm_device *device = subdev->device;
+ struct nvkm_gpuobj *inst = chan->base.inst;
+ int ret = 0;
nvkm_wr32(device, 0x002634, chan->base.chid);
if (nvkm_msec(device, 2000,
@@ -60,143 +64,197 @@ gf100_fifo_context_detach(struct nvkm_object *parent, bool suspend,
break;
) < 0) {
nvkm_error(subdev, "channel %d [%s] kick timeout\n",
- chan->base.chid, nvkm_client_name(chan));
+ chan->base.chid, chan->base.object.client->name);
+ ret = -EBUSY;
if (suspend)
- return -EBUSY;
+ return ret;
+ }
+
+ if (offset) {
+ nvkm_kmap(inst);
+ nvkm_wo32(inst, offset + 0x00, 0x00000000);
+ nvkm_wo32(inst, offset + 0x04, 0x00000000);
+ nvkm_done(inst);
+ }
+
+ return ret;
+}
+
+static int
+gf100_fifo_gpfifo_engine_init(struct nvkm_fifo_chan *base,
+ struct nvkm_engine *engine)
+{
+ const u32 offset = gf100_fifo_gpfifo_engine_addr(engine);
+ struct gf100_fifo_chan *chan = gf100_fifo_chan(base);
+ struct nvkm_gpuobj *inst = chan->base.inst;
+
+ if (offset) {
+ u64 addr = chan->engn[engine->subdev.index].vma.offset;
+ nvkm_kmap(inst);
+ nvkm_wo32(inst, offset + 0x00, lower_32_bits(addr) | 4);
+ nvkm_wo32(inst, offset + 0x04, upper_32_bits(addr));
+ nvkm_done(inst);
}
- nvkm_kmap(engn);
- nvkm_wo32(engn, addr + 0x00, 0x00000000);
- nvkm_wo32(engn, addr + 0x04, 0x00000000);
- nvkm_done(engn);
return 0;
}
+static void
+gf100_fifo_gpfifo_engine_dtor(struct nvkm_fifo_chan *base,
+ struct nvkm_engine *engine)
+{
+ struct gf100_fifo_chan *chan = gf100_fifo_chan(base);
+ nvkm_gpuobj_unmap(&chan->engn[engine->subdev.index].vma);
+ nvkm_gpuobj_del(&chan->engn[engine->subdev.index].inst);
+}
+
static int
-gf100_fifo_context_attach(struct nvkm_object *parent,
- struct nvkm_object *object)
+gf100_fifo_gpfifo_engine_ctor(struct nvkm_fifo_chan *base,
+ struct nvkm_engine *engine,
+ struct nvkm_object *object)
{
- struct gf100_fifo_base *base = (void *)parent->parent;
- struct nvkm_gpuobj *engn = &base->base.gpuobj;
- struct nvkm_engctx *ectx = (void *)object;
- u32 addr;
+ struct gf100_fifo_chan *chan = gf100_fifo_chan(base);
+ int engn = engine->subdev.index;
int ret;
- switch (nv_engidx(object->engine)) {
- case NVDEV_ENGINE_SW : return 0;
- case NVDEV_ENGINE_GR : addr = 0x0210; break;
- case NVDEV_ENGINE_CE0 : addr = 0x0230; break;
- case NVDEV_ENGINE_CE1 : addr = 0x0240; break;
- case NVDEV_ENGINE_MSVLD : addr = 0x0270; break;
- case NVDEV_ENGINE_MSPDEC: addr = 0x0250; break;
- case NVDEV_ENGINE_MSPPP : addr = 0x0260; break;
- default:
- return -EINVAL;
- }
-
- if (!ectx->vma.node) {
- ret = nvkm_gpuobj_map(nv_gpuobj(ectx), base->vm,
- NV_MEM_ACCESS_RW, &ectx->vma);
- if (ret)
- return ret;
+ if (!gf100_fifo_gpfifo_engine_addr(engine))
+ return 0;
- nv_engctx(ectx)->addr = nv_gpuobj(base)->addr >> 12;
+ if (object->oclass) {
+ return nvkm_gpuobj_map(nv_gpuobj(object), chan->vm,
+ NV_MEM_ACCESS_RW,
+ &chan->engn[engn].vma);
}
- nvkm_kmap(engn);
- nvkm_wo32(engn, addr + 0x00, lower_32_bits(ectx->vma.offset) | 4);
- nvkm_wo32(engn, addr + 0x04, upper_32_bits(ectx->vma.offset));
- nvkm_done(engn);
- return 0;
+ ret = nvkm_object_bind(object, NULL, 0, &chan->engn[engn].inst);
+ if (ret)
+ return ret;
+
+ return nvkm_gpuobj_map(chan->engn[engn].inst, chan->vm,
+ NV_MEM_ACCESS_RW, &chan->engn[engn].vma);
}
-static int
-gf100_fifo_chan_fini(struct nvkm_object *object, bool suspend)
+static void
+gf100_fifo_gpfifo_fini(struct nvkm_fifo_chan *base)
{
- struct gf100_fifo *fifo = (void *)object->engine;
- struct gf100_fifo_chan *chan = (void *)object;
+ struct gf100_fifo_chan *chan = gf100_fifo_chan(base);
+ struct gf100_fifo *fifo = chan->fifo;
struct nvkm_device *device = fifo->base.engine.subdev.device;
- u32 chid = chan->base.chid;
+ u32 coff = chan->base.chid * 8;
- if (chan->state == RUNNING && (chan->state = STOPPED) == STOPPED) {
- nvkm_mask(device, 0x003004 + (chid * 8), 0x00000001, 0x00000000);
+ if (!list_empty(&chan->head) && !chan->killed) {
+ list_del_init(&chan->head);
+ nvkm_mask(device, 0x003004 + coff, 0x00000001, 0x00000000);
gf100_fifo_runlist_update(fifo);
}
gf100_fifo_intr_engine(fifo);
- nvkm_wr32(device, 0x003000 + (chid * 8), 0x00000000);
- return nvkm_fifo_channel_fini(&chan->base, suspend);
+ nvkm_wr32(device, 0x003000 + coff, 0x00000000);
}
-static int
-gf100_fifo_chan_init(struct nvkm_object *object)
+static void
+gf100_fifo_gpfifo_init(struct nvkm_fifo_chan *base)
{
- struct nvkm_gpuobj *base = nv_gpuobj(object->parent);
- struct gf100_fifo *fifo = (void *)object->engine;
- struct gf100_fifo_chan *chan = (void *)object;
+ struct gf100_fifo_chan *chan = gf100_fifo_chan(base);
+ struct gf100_fifo *fifo = chan->fifo;
struct nvkm_device *device = fifo->base.engine.subdev.device;
- u32 chid = chan->base.chid;
- int ret;
-
- ret = nvkm_fifo_channel_init(&chan->base);
- if (ret)
- return ret;
+ u32 addr = chan->base.inst->addr >> 12;
+ u32 coff = chan->base.chid * 8;
- nvkm_wr32(device, 0x003000 + (chid * 8), 0xc0000000 | base->addr >> 12);
+ nvkm_wr32(device, 0x003000 + coff, 0xc0000000 | addr);
- if (chan->state == STOPPED && (chan->state = RUNNING) == RUNNING) {
- nvkm_wr32(device, 0x003004 + (chid * 8), 0x001f0001);
+ if (list_empty(&chan->head) && !chan->killed) {
+ list_add_tail(&chan->head, &fifo->chan);
+ nvkm_wr32(device, 0x003004 + coff, 0x001f0001);
gf100_fifo_runlist_update(fifo);
}
+}
- return 0;
+static void *
+gf100_fifo_gpfifo_dtor(struct nvkm_fifo_chan *base)
+{
+ struct gf100_fifo_chan *chan = gf100_fifo_chan(base);
+ nvkm_vm_ref(NULL, &chan->vm, chan->pgd);
+ nvkm_gpuobj_del(&chan->pgd);
+ return chan;
}
+static const struct nvkm_fifo_chan_func
+gf100_fifo_gpfifo_func = {
+ .dtor = gf100_fifo_gpfifo_dtor,
+ .init = gf100_fifo_gpfifo_init,
+ .fini = gf100_fifo_gpfifo_fini,
+ .ntfy = g84_fifo_chan_ntfy,
+ .engine_ctor = gf100_fifo_gpfifo_engine_ctor,
+ .engine_dtor = gf100_fifo_gpfifo_engine_dtor,
+ .engine_init = gf100_fifo_gpfifo_engine_init,
+ .engine_fini = gf100_fifo_gpfifo_engine_fini,
+};
+
static int
-gf100_fifo_chan_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
- struct nvkm_oclass *oclass, void *data, u32 size,
- struct nvkm_object **pobject)
+gf100_fifo_gpfifo_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass,
+ void *data, u32 size, struct nvkm_object **pobject)
{
union {
struct fermi_channel_gpfifo_v0 v0;
} *args = data;
- struct gf100_fifo *fifo = (void *)engine;
- struct gf100_fifo_base *base = (void *)parent;
+ struct gf100_fifo *fifo = gf100_fifo(base);
+ struct nvkm_device *device = fifo->base.engine.subdev.device;
+ struct nvkm_object *parent = oclass->parent;
struct gf100_fifo_chan *chan;
- struct nvkm_gpuobj *ramfc = &base->base.gpuobj;
u64 usermem, ioffset, ilength;
int ret, i;
nvif_ioctl(parent, "create channel gpfifo size %d\n", size);
if (nvif_unpack(args->v0, 0, 0, false)) {
- nvif_ioctl(parent, "create channel gpfifo vers %d vm %llx"
+ nvif_ioctl(parent, "create channel gpfifo vers %d vm %llx "
"ioffset %016llx ilength %08x\n",
args->v0.version, args->v0.vm, args->v0.ioffset,
args->v0.ilength);
- if (args->v0.vm)
- return -ENOENT;
} else
return ret;
- ret = nvkm_fifo_channel_create(parent, engine, oclass, 1,
- fifo->user.bar.offset, 0x1000, 0,
- (1ULL << NVDEV_ENGINE_SW) |
- (1ULL << NVDEV_ENGINE_GR) |
- (1ULL << NVDEV_ENGINE_CE0) |
- (1ULL << NVDEV_ENGINE_CE1) |
- (1ULL << NVDEV_ENGINE_MSVLD) |
- (1ULL << NVDEV_ENGINE_MSPDEC) |
- (1ULL << NVDEV_ENGINE_MSPPP), &chan);
- *pobject = nv_object(chan);
+ /* allocate channel */
+ if (!(chan = kzalloc(sizeof(*chan), GFP_KERNEL)))
+ return -ENOMEM;
+ *pobject = &chan->base.object;
+ chan->fifo = fifo;
+ INIT_LIST_HEAD(&chan->head);
+
+ ret = nvkm_fifo_chan_ctor(&gf100_fifo_gpfifo_func, &fifo->base,
+ 0x1000, 0x1000, true, args->v0.vm, 0,
+ (1ULL << NVDEV_ENGINE_CE0) |
+ (1ULL << NVDEV_ENGINE_CE1) |
+ (1ULL << NVDEV_ENGINE_GR) |
+ (1ULL << NVDEV_ENGINE_MSPDEC) |
+ (1ULL << NVDEV_ENGINE_MSPPP) |
+ (1ULL << NVDEV_ENGINE_MSVLD) |
+ (1ULL << NVDEV_ENGINE_SW),
+ 1, fifo->user.bar.offset, 0x1000,
+ oclass, &chan->base);
if (ret)
return ret;
- chan->base.inst = base->base.gpuobj.addr;
args->v0.chid = chan->base.chid;
- nv_parent(chan)->context_attach = gf100_fifo_context_attach;
- nv_parent(chan)->context_detach = gf100_fifo_context_detach;
+ /* page directory */
+ ret = nvkm_gpuobj_new(device, 0x10000, 0x1000, false, NULL, &chan->pgd);
+ if (ret)
+ return ret;
+
+ nvkm_kmap(chan->base.inst);
+ nvkm_wo32(chan->base.inst, 0x0200, lower_32_bits(chan->pgd->addr));
+ nvkm_wo32(chan->base.inst, 0x0204, upper_32_bits(chan->pgd->addr));
+ nvkm_wo32(chan->base.inst, 0x0208, 0xffffffff);
+ nvkm_wo32(chan->base.inst, 0x020c, 0x000000ff);
+ nvkm_done(chan->base.inst);
+
+ ret = nvkm_vm_ref(chan->base.vm, &chan->vm, chan->pgd);
+ if (ret)
+ return ret;
+
+ /* clear channel control registers */
usermem = chan->base.chid * 0x1000;
ioffset = args->v0.ioffset;
@@ -208,97 +266,33 @@ gf100_fifo_chan_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
nvkm_done(fifo->user.mem);
usermem = nvkm_memory_addr(fifo->user.mem) + usermem;
- nvkm_kmap(ramfc);
- nvkm_wo32(ramfc, 0x08, lower_32_bits(usermem));
- nvkm_wo32(ramfc, 0x0c, upper_32_bits(usermem));
- nvkm_wo32(ramfc, 0x10, 0x0000face);
- nvkm_wo32(ramfc, 0x30, 0xfffff902);
- nvkm_wo32(ramfc, 0x48, lower_32_bits(ioffset));
- nvkm_wo32(ramfc, 0x4c, upper_32_bits(ioffset) | (ilength << 16));
- nvkm_wo32(ramfc, 0x54, 0x00000002);
- nvkm_wo32(ramfc, 0x84, 0x20400000);
- nvkm_wo32(ramfc, 0x94, 0x30000001);
- nvkm_wo32(ramfc, 0x9c, 0x00000100);
- nvkm_wo32(ramfc, 0xa4, 0x1f1f1f1f);
- nvkm_wo32(ramfc, 0xa8, 0x1f1f1f1f);
- nvkm_wo32(ramfc, 0xac, 0x0000001f);
- nvkm_wo32(ramfc, 0xb8, 0xf8000000);
- nvkm_wo32(ramfc, 0xf8, 0x10003080); /* 0x002310 */
- nvkm_wo32(ramfc, 0xfc, 0x10000010); /* 0x002350 */
- nvkm_done(ramfc);
- return 0;
-}
-
-static struct nvkm_ofuncs
-gf100_fifo_ofuncs = {
- .ctor = gf100_fifo_chan_ctor,
- .dtor = _nvkm_fifo_channel_dtor,
- .init = gf100_fifo_chan_init,
- .fini = gf100_fifo_chan_fini,
- .map = _nvkm_fifo_channel_map,
- .rd32 = _nvkm_fifo_channel_rd32,
- .wr32 = _nvkm_fifo_channel_wr32,
- .ntfy = _nvkm_fifo_channel_ntfy
-};
-
-struct nvkm_oclass
-gf100_fifo_sclass[] = {
- { FERMI_CHANNEL_GPFIFO, &gf100_fifo_ofuncs },
- {}
-};
-
-static int
-gf100_fifo_context_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
- struct nvkm_oclass *oclass, void *data, u32 size,
- struct nvkm_object **pobject)
-{
- struct nvkm_device *device = nv_engine(engine)->subdev.device;
- struct gf100_fifo_base *base;
- int ret;
-
- ret = nvkm_fifo_context_create(parent, engine, oclass, NULL, 0x1000,
- 0x1000, NVOBJ_FLAG_ZERO_ALLOC |
- NVOBJ_FLAG_HEAP, &base);
- *pobject = nv_object(base);
- if (ret)
- return ret;
-
- ret = nvkm_gpuobj_new(device, 0x10000, 0x1000, false, NULL, &base->pgd);
- if (ret)
- return ret;
-
- nvkm_kmap(&base->base.gpuobj);
- nvkm_wo32(&base->base.gpuobj, 0x0200, lower_32_bits(base->pgd->addr));
- nvkm_wo32(&base->base.gpuobj, 0x0204, upper_32_bits(base->pgd->addr));
- nvkm_wo32(&base->base.gpuobj, 0x0208, 0xffffffff);
- nvkm_wo32(&base->base.gpuobj, 0x020c, 0x000000ff);
- nvkm_done(&base->base.gpuobj);
-
- ret = nvkm_vm_ref(nvkm_client(parent)->vm, &base->vm, base->pgd);
- if (ret)
- return ret;
-
+ /* RAMFC */
+ nvkm_kmap(chan->base.inst);
+ nvkm_wo32(chan->base.inst, 0x08, lower_32_bits(usermem));
+ nvkm_wo32(chan->base.inst, 0x0c, upper_32_bits(usermem));
+ nvkm_wo32(chan->base.inst, 0x10, 0x0000face);
+ nvkm_wo32(chan->base.inst, 0x30, 0xfffff902);
+ nvkm_wo32(chan->base.inst, 0x48, lower_32_bits(ioffset));
+ nvkm_wo32(chan->base.inst, 0x4c, upper_32_bits(ioffset) |
+ (ilength << 16));
+ nvkm_wo32(chan->base.inst, 0x54, 0x00000002);
+ nvkm_wo32(chan->base.inst, 0x84, 0x20400000);
+ nvkm_wo32(chan->base.inst, 0x94, 0x30000001);
+ nvkm_wo32(chan->base.inst, 0x9c, 0x00000100);
+ nvkm_wo32(chan->base.inst, 0xa4, 0x1f1f1f1f);
+ nvkm_wo32(chan->base.inst, 0xa8, 0x1f1f1f1f);
+ nvkm_wo32(chan->base.inst, 0xac, 0x0000001f);
+ nvkm_wo32(chan->base.inst, 0xb8, 0xf8000000);
+ nvkm_wo32(chan->base.inst, 0xf8, 0x10003080); /* 0x002310 */
+ nvkm_wo32(chan->base.inst, 0xfc, 0x10000010); /* 0x002350 */
+ nvkm_done(chan->base.inst);
return 0;
}
-static void
-gf100_fifo_context_dtor(struct nvkm_object *object)
-{
- struct gf100_fifo_base *base = (void *)object;
- nvkm_vm_ref(NULL, &base->vm, base->pgd);
- nvkm_gpuobj_del(&base->pgd);
- nvkm_fifo_context_destroy(&base->base);
-}
-
-struct nvkm_oclass
-gf100_fifo_cclass = {
- .handle = NV_ENGCTX(FIFO, 0xc0),
- .ofuncs = &(struct nvkm_ofuncs) {
- .ctor = gf100_fifo_context_ctor,
- .dtor = gf100_fifo_context_dtor,
- .init = _nvkm_fifo_context_init,
- .fini = _nvkm_fifo_context_fini,
- .rd32 = _nvkm_fifo_context_rd32,
- .wr32 = _nvkm_fifo_context_wr32,
- },
+const struct nvkm_fifo_chan_oclass
+gf100_fifo_gpfifo_oclass = {
+ .base.oclass = FERMI_CHANNEL_GPFIFO,
+ .base.minver = 0,
+ .base.maxver = 0,
+ .ctor = gf100_fifo_gpfifo_new,
};
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c
index 264c9705bccc..2595cf92ff80 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c
@@ -31,30 +31,13 @@
#include <nvif/class.h>
#include <nvif/unpack.h>
-#define _(a,b) { (a), ((1ULL << (a)) | (b)) }
-static const struct {
- u64 subdev;
- u64 mask;
-} fifo_engine[] = {
- _(NVDEV_ENGINE_GR , (1ULL << NVDEV_ENGINE_SW) |
- (1ULL << NVDEV_ENGINE_CE2)),
- _(NVDEV_ENGINE_MSPDEC , 0),
- _(NVDEV_ENGINE_MSPPP , 0),
- _(NVDEV_ENGINE_MSVLD , 0),
- _(NVDEV_ENGINE_CE0 , 0),
- _(NVDEV_ENGINE_CE1 , 0),
- _(NVDEV_ENGINE_MSENC , 0),
-};
-#undef _
-#define FIFO_ENGINE_NR ARRAY_SIZE(fifo_engine)
-
static int
-gk104_fifo_chan_kick(struct gk104_fifo_chan *chan)
+gk104_fifo_gpfifo_kick(struct gk104_fifo_chan *chan)
{
- struct nvkm_object *obj = (void *)chan;
- struct gk104_fifo *fifo = (void *)obj->engine;
+ 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;
nvkm_wr32(device, 0x002634, chan->base.chid);
if (nvkm_msec(device, 2000,
@@ -62,198 +45,249 @@ gk104_fifo_chan_kick(struct gk104_fifo_chan *chan)
break;
) < 0) {
nvkm_error(subdev, "channel %d [%s] kick timeout\n",
- chan->base.chid, nvkm_client_name(chan));
+ chan->base.chid, client->name);
return -EBUSY;
}
return 0;
}
-static int
-gk104_fifo_context_detach(struct nvkm_object *parent, bool suspend,
- struct nvkm_object *object)
+static u32
+gk104_fifo_gpfifo_engine_addr(struct nvkm_engine *engine)
{
- struct gk104_fifo_base *base = (void *)parent->parent;
- struct gk104_fifo_chan *chan = (void *)parent;
- struct nvkm_gpuobj *engn = &base->base.gpuobj;
- u32 addr;
- int ret;
-
- switch (nv_engidx(object->engine)) {
- case NVDEV_ENGINE_SW : return 0;
+ switch (engine->subdev.index) {
+ case NVDEV_ENGINE_SW :
case NVDEV_ENGINE_CE0 :
case NVDEV_ENGINE_CE1 :
- case NVDEV_ENGINE_CE2 : addr = 0x0000; break;
- case NVDEV_ENGINE_GR : addr = 0x0210; break;
- case NVDEV_ENGINE_MSVLD : addr = 0x0270; break;
- case NVDEV_ENGINE_MSPDEC: addr = 0x0250; break;
- case NVDEV_ENGINE_MSPPP : addr = 0x0260; break;
+ case NVDEV_ENGINE_CE2 : return 0x0000;
+ case NVDEV_ENGINE_GR : return 0x0210;
+ case NVDEV_ENGINE_MSPDEC: return 0x0250;
+ case NVDEV_ENGINE_MSPPP : return 0x0260;
+ case NVDEV_ENGINE_MSVLD : return 0x0270;
default:
- return -EINVAL;
+ WARN_ON(1);
+ return 0;
}
+}
- ret = gk104_fifo_chan_kick(chan);
+static int
+gk104_fifo_gpfifo_engine_fini(struct nvkm_fifo_chan *base,
+ struct nvkm_engine *engine, bool suspend)
+{
+ const u32 offset = gk104_fifo_gpfifo_engine_addr(engine);
+ struct gk104_fifo_chan *chan = gk104_fifo_chan(base);
+ struct nvkm_gpuobj *inst = chan->base.inst;
+ int ret;
+
+ ret = gk104_fifo_gpfifo_kick(chan);
if (ret && suspend)
return ret;
- if (addr) {
- nvkm_kmap(engn);
- nvkm_wo32(engn, addr + 0x00, 0x00000000);
- nvkm_wo32(engn, addr + 0x04, 0x00000000);
- nvkm_done(engn);
+ if (offset) {
+ nvkm_kmap(inst);
+ nvkm_wo32(inst, offset + 0x00, 0x00000000);
+ nvkm_wo32(inst, offset + 0x04, 0x00000000);
+ nvkm_done(inst);
+ }
+
+ return ret;
+}
+
+static int
+gk104_fifo_gpfifo_engine_init(struct nvkm_fifo_chan *base,
+ struct nvkm_engine *engine)
+{
+ const u32 offset = gk104_fifo_gpfifo_engine_addr(engine);
+ struct gk104_fifo_chan *chan = gk104_fifo_chan(base);
+ struct nvkm_gpuobj *inst = chan->base.inst;
+
+ if (offset) {
+ u64 addr = chan->engn[engine->subdev.index].vma.offset;
+ nvkm_kmap(inst);
+ nvkm_wo32(inst, offset + 0x00, lower_32_bits(addr) | 4);
+ nvkm_wo32(inst, offset + 0x04, upper_32_bits(addr));
+ nvkm_done(inst);
}
return 0;
}
+static void
+gk104_fifo_gpfifo_engine_dtor(struct nvkm_fifo_chan *base,
+ struct nvkm_engine *engine)
+{
+ struct gk104_fifo_chan *chan = gk104_fifo_chan(base);
+ nvkm_gpuobj_unmap(&chan->engn[engine->subdev.index].vma);
+ nvkm_gpuobj_del(&chan->engn[engine->subdev.index].inst);
+}
+
static int
-gk104_fifo_context_attach(struct nvkm_object *parent,
- struct nvkm_object *object)
+gk104_fifo_gpfifo_engine_ctor(struct nvkm_fifo_chan *base,
+ struct nvkm_engine *engine,
+ struct nvkm_object *object)
{
- struct gk104_fifo_base *base = (void *)parent->parent;
- struct nvkm_gpuobj *engn = &base->base.gpuobj;
- struct nvkm_engctx *ectx = (void *)object;
- u32 addr;
+ struct gk104_fifo_chan *chan = gk104_fifo_chan(base);
+ int engn = engine->subdev.index;
int ret;
- switch (nv_engidx(object->engine)) {
- case NVDEV_ENGINE_SW :
- return 0;
- case NVDEV_ENGINE_CE0:
- case NVDEV_ENGINE_CE1:
- case NVDEV_ENGINE_CE2:
- nv_engctx(ectx)->addr = nv_gpuobj(base)->addr >> 12;
+ if (!gk104_fifo_gpfifo_engine_addr(engine))
return 0;
- case NVDEV_ENGINE_GR : addr = 0x0210; break;
- case NVDEV_ENGINE_MSVLD : addr = 0x0270; break;
- case NVDEV_ENGINE_MSPDEC: addr = 0x0250; break;
- case NVDEV_ENGINE_MSPPP : addr = 0x0260; break;
- default:
- return -EINVAL;
- }
- if (!ectx->vma.node) {
- ret = nvkm_gpuobj_map(nv_gpuobj(ectx), base->vm,
- NV_MEM_ACCESS_RW, &ectx->vma);
- if (ret)
- return ret;
-
- nv_engctx(ectx)->addr = nv_gpuobj(base)->addr >> 12;
+ if (object->oclass) {
+ return nvkm_gpuobj_map(nv_gpuobj(object), chan->vm,
+ NV_MEM_ACCESS_RW,
+ &chan->engn[engn].vma);
}
- nvkm_kmap(engn);
- nvkm_wo32(engn, addr + 0x00, lower_32_bits(ectx->vma.offset) | 4);
- nvkm_wo32(engn, addr + 0x04, upper_32_bits(ectx->vma.offset));
- nvkm_done(engn);
- return 0;
+ ret = nvkm_object_bind(object, NULL, 0, &chan->engn[engn].inst);
+ if (ret)
+ return ret;
+
+ return nvkm_gpuobj_map(chan->engn[engn].inst, chan->vm,
+ NV_MEM_ACCESS_RW, &chan->engn[engn].vma);
}
-static int
-gk104_fifo_chan_fini(struct nvkm_object *object, bool suspend)
+static void
+gk104_fifo_gpfifo_fini(struct nvkm_fifo_chan *base)
{
- struct gk104_fifo *fifo = (void *)object->engine;
- struct gk104_fifo_chan *chan = (void *)object;
+ struct gk104_fifo_chan *chan = gk104_fifo_chan(base);
+ struct gk104_fifo *fifo = chan->fifo;
struct nvkm_device *device = fifo->base.engine.subdev.device;
- u32 chid = chan->base.chid;
+ u32 coff = chan->base.chid * 8;
- if (chan->state == RUNNING && (chan->state = STOPPED) == STOPPED) {
- nvkm_mask(device, 0x800004 + (chid * 8), 0x00000800, 0x00000800);
+ if (!list_empty(&chan->head)) {
+ list_del_init(&chan->head);
+ nvkm_mask(device, 0x800004 + coff, 0x00000800, 0x00000800);
gk104_fifo_runlist_update(fifo, chan->engine);
}
- nvkm_wr32(device, 0x800000 + (chid * 8), 0x00000000);
- return nvkm_fifo_channel_fini(&chan->base, suspend);
+ nvkm_wr32(device, 0x800000 + coff, 0x00000000);
}
-static int
-gk104_fifo_chan_init(struct nvkm_object *object)
+static void
+gk104_fifo_gpfifo_init(struct nvkm_fifo_chan *base)
{
- struct nvkm_gpuobj *base = nv_gpuobj(object->parent);
- struct gk104_fifo *fifo = (void *)object->engine;
- struct gk104_fifo_chan *chan = (void *)object;
+ struct gk104_fifo_chan *chan = gk104_fifo_chan(base);
+ struct gk104_fifo *fifo = chan->fifo;
struct nvkm_device *device = fifo->base.engine.subdev.device;
- u32 chid = chan->base.chid;
- int ret;
+ u32 addr = chan->base.inst->addr >> 12;
+ u32 coff = chan->base.chid * 8;
- ret = nvkm_fifo_channel_init(&chan->base);
- if (ret)
- return ret;
+ nvkm_mask(device, 0x800004 + coff, 0x000f0000, chan->engine << 16);
+ nvkm_wr32(device, 0x800000 + coff, 0x80000000 | addr);
- nvkm_mask(device, 0x800004 + (chid * 8), 0x000f0000, chan->engine << 16);
- nvkm_wr32(device, 0x800000 + (chid * 8), 0x80000000 | base->addr >> 12);
-
- if (chan->state == STOPPED && (chan->state = RUNNING) == RUNNING) {
- nvkm_mask(device, 0x800004 + (chid * 8), 0x00000400, 0x00000400);
+ if (list_empty(&chan->head) && !chan->killed) {
+ list_add_tail(&chan->head, &fifo->engine[chan->engine].chan);
+ nvkm_mask(device, 0x800004 + coff, 0x00000400, 0x00000400);
gk104_fifo_runlist_update(fifo, chan->engine);
- nvkm_mask(device, 0x800004 + (chid * 8), 0x00000400, 0x00000400);
+ nvkm_mask(device, 0x800004 + coff, 0x00000400, 0x00000400);
}
+}
- return 0;
+static void *
+gk104_fifo_gpfifo_dtor(struct nvkm_fifo_chan *base)
+{
+ struct gk104_fifo_chan *chan = gk104_fifo_chan(base);
+ nvkm_vm_ref(NULL, &chan->vm, chan->pgd);
+ nvkm_gpuobj_del(&chan->pgd);
+ return chan;
}
-static int
-gk104_fifo_chan_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
- struct nvkm_oclass *oclass, void *data, u32 size,
- struct nvkm_object **pobject)
+static const struct nvkm_fifo_chan_func
+gk104_fifo_gpfifo_func = {
+ .dtor = gk104_fifo_gpfifo_dtor,
+ .init = gk104_fifo_gpfifo_init,
+ .fini = gk104_fifo_gpfifo_fini,
+ .ntfy = g84_fifo_chan_ntfy,
+ .engine_ctor = gk104_fifo_gpfifo_engine_ctor,
+ .engine_dtor = gk104_fifo_gpfifo_engine_dtor,
+ .engine_init = gk104_fifo_gpfifo_engine_init,
+ .engine_fini = gk104_fifo_gpfifo_engine_fini,
+};
+
+int
+gk104_fifo_gpfifo_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass,
+ void *data, u32 size, struct nvkm_object **pobject)
{
union {
struct kepler_channel_gpfifo_a_v0 v0;
} *args = data;
- struct gk104_fifo *fifo = (void *)engine;
- struct gk104_fifo_base *base = (void *)parent;
+ struct gk104_fifo *fifo = gk104_fifo(base);
+ struct nvkm_device *device = fifo->base.engine.subdev.device;
+ struct nvkm_object *parent = oclass->parent;
struct gk104_fifo_chan *chan;
- struct nvkm_gpuobj *ramfc = &base->base.gpuobj;
u64 usermem, ioffset, ilength;
u32 engines;
int ret, i;
nvif_ioctl(parent, "create channel gpfifo size %d\n", size);
if (nvif_unpack(args->v0, 0, 0, false)) {
- nvif_ioctl(parent, "create channel gpfifo vers %d vm %llx"
+ nvif_ioctl(parent, "create channel gpfifo vers %d vm %llx "
"ioffset %016llx ilength %08x engine %08x\n",
args->v0.version, args->v0.vm, args->v0.ioffset,
args->v0.ilength, args->v0.engine);
- if (args->v0.vm)
- return -ENOENT;
} else
return ret;
- for (i = 0, engines = 0; i < FIFO_ENGINE_NR; i++) {
- if (!nvkm_engine(parent, fifo_engine[i].subdev))
+ /* determine which downstream engines are present */
+ for (i = 0, engines = 0; i < ARRAY_SIZE(fifo->engine); i++) {
+ u64 subdevs = gk104_fifo_engine_subdev(i);
+ if (!nvkm_device_engine(device, __ffs64(subdevs)))
continue;
engines |= (1 << i);
}
+ /* if this is an engine mask query, we're done */
if (!args->v0.engine) {
- static struct nvkm_oclass oclass = {
- .ofuncs = &nvkm_object_ofuncs,
- };
args->v0.engine = engines;
- return nvkm_object_old(parent, engine, &oclass, NULL, 0, pobject);
+ return nvkm_object_new(oclass, NULL, 0, pobject);
}
- engines &= args->v0.engine;
- if (!engines) {
- nvif_ioctl(parent, "unsupported engines %08x\n",
- args->v0.engine);
+ /* check that we support a requested engine - note that the user
+ * argument is a mask in order to allow the user to request (for
+ * example) *any* copy engine, but doesn't matter which.
+ */
+ args->v0.engine &= engines;
+ if (!args->v0.engine) {
+ nvif_ioctl(parent, "no supported engine\n");
return -ENODEV;
}
- i = __ffs(engines);
- ret = nvkm_fifo_channel_create(parent, engine, oclass, 1,
- fifo->user.bar.offset, 0x200, 0,
- fifo_engine[i].mask, &chan);
- *pobject = nv_object(chan);
+ /* allocate the channel */
+ if (!(chan = kzalloc(sizeof(*chan), GFP_KERNEL)))
+ return -ENOMEM;
+ *pobject = &chan->base.object;
+ chan->fifo = fifo;
+ chan->engine = __ffs(args->v0.engine);
+ INIT_LIST_HEAD(&chan->head);
+
+ ret = nvkm_fifo_chan_ctor(&gk104_fifo_gpfifo_func, &fifo->base,
+ 0x1000, 0x1000, true, args->v0.vm, 0,
+ gk104_fifo_engine_subdev(chan->engine),
+ 1, fifo->user.bar.offset, 0x200,
+ oclass, &chan->base);
if (ret)
return ret;
- chan->base.inst = base->base.gpuobj.addr;
args->v0.chid = chan->base.chid;
- nv_parent(chan)->context_attach = gk104_fifo_context_attach;
- nv_parent(chan)->context_detach = gk104_fifo_context_detach;
- chan->engine = i;
+ /* page directory */
+ ret = nvkm_gpuobj_new(device, 0x10000, 0x1000, false, NULL, &chan->pgd);
+ if (ret)
+ return ret;
+
+ nvkm_kmap(chan->base.inst);
+ nvkm_wo32(chan->base.inst, 0x0200, lower_32_bits(chan->pgd->addr));
+ nvkm_wo32(chan->base.inst, 0x0204, upper_32_bits(chan->pgd->addr));
+ nvkm_wo32(chan->base.inst, 0x0208, 0xffffffff);
+ nvkm_wo32(chan->base.inst, 0x020c, 0x000000ff);
+ nvkm_done(chan->base.inst);
+ ret = nvkm_vm_ref(chan->base.vm, &chan->vm, chan->pgd);
+ if (ret)
+ return ret;
+
+ /* clear channel control registers */
usermem = chan->base.chid * 0x200;
ioffset = args->v0.ioffset;
ilength = order_base_2(args->v0.ilength / 8);
@@ -264,94 +298,31 @@ gk104_fifo_chan_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
nvkm_done(fifo->user.mem);
usermem = nvkm_memory_addr(fifo->user.mem) + usermem;
- nvkm_kmap(ramfc);
- nvkm_wo32(ramfc, 0x08, lower_32_bits(usermem));
- nvkm_wo32(ramfc, 0x0c, upper_32_bits(usermem));
- nvkm_wo32(ramfc, 0x10, 0x0000face);
- nvkm_wo32(ramfc, 0x30, 0xfffff902);
- nvkm_wo32(ramfc, 0x48, lower_32_bits(ioffset));
- nvkm_wo32(ramfc, 0x4c, upper_32_bits(ioffset) | (ilength << 16));
- nvkm_wo32(ramfc, 0x84, 0x20400000);
- nvkm_wo32(ramfc, 0x94, 0x30000001);
- nvkm_wo32(ramfc, 0x9c, 0x00000100);
- nvkm_wo32(ramfc, 0xac, 0x0000001f);
- nvkm_wo32(ramfc, 0xe8, chan->base.chid);
- nvkm_wo32(ramfc, 0xb8, 0xf8000000);
- nvkm_wo32(ramfc, 0xf8, 0x10003080); /* 0x002310 */
- nvkm_wo32(ramfc, 0xfc, 0x10000010); /* 0x002350 */
- nvkm_done(ramfc);
- return 0;
-}
-
-struct nvkm_ofuncs
-gk104_fifo_chan_ofuncs = {
- .ctor = gk104_fifo_chan_ctor,
- .dtor = _nvkm_fifo_channel_dtor,
- .init = gk104_fifo_chan_init,
- .fini = gk104_fifo_chan_fini,
- .map = _nvkm_fifo_channel_map,
- .rd32 = _nvkm_fifo_channel_rd32,
- .wr32 = _nvkm_fifo_channel_wr32,
- .ntfy = _nvkm_fifo_channel_ntfy
-};
-
-struct nvkm_oclass
-gk104_fifo_sclass[] = {
- { KEPLER_CHANNEL_GPFIFO_A, &gk104_fifo_chan_ofuncs },
- {}
-};
-
-static int
-gk104_fifo_context_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
- struct nvkm_oclass *oclass, void *data, u32 size,
- struct nvkm_object **pobject)
-{
- struct nvkm_device *device = nv_engine(engine)->subdev.device;
- struct gk104_fifo_base *base;
- int ret;
-
- ret = nvkm_fifo_context_create(parent, engine, oclass, NULL, 0x1000,
- 0x1000, NVOBJ_FLAG_ZERO_ALLOC, &base);
- *pobject = nv_object(base);
- if (ret)
- return ret;
-
- ret = nvkm_gpuobj_new(device, 0x10000, 0x1000, false, NULL, &base->pgd);
- if (ret)
- return ret;
-
- nvkm_kmap(&base->base.gpuobj);
- nvkm_wo32(&base->base.gpuobj, 0x0200, lower_32_bits(base->pgd->addr));
- nvkm_wo32(&base->base.gpuobj, 0x0204, upper_32_bits(base->pgd->addr));
- nvkm_wo32(&base->base.gpuobj, 0x0208, 0xffffffff);
- nvkm_wo32(&base->base.gpuobj, 0x020c, 0x000000ff);
- nvkm_done(&base->base.gpuobj);
-
- ret = nvkm_vm_ref(nvkm_client(parent)->vm, &base->vm, base->pgd);
- if (ret)
- return ret;
-
+ /* RAMFC */
+ nvkm_kmap(chan->base.inst);
+ nvkm_wo32(chan->base.inst, 0x08, lower_32_bits(usermem));
+ nvkm_wo32(chan->base.inst, 0x0c, upper_32_bits(usermem));
+ nvkm_wo32(chan->base.inst, 0x10, 0x0000face);
+ nvkm_wo32(chan->base.inst, 0x30, 0xfffff902);
+ nvkm_wo32(chan->base.inst, 0x48, lower_32_bits(ioffset));
+ nvkm_wo32(chan->base.inst, 0x4c, upper_32_bits(ioffset) |
+ (ilength << 16));
+ nvkm_wo32(chan->base.inst, 0x84, 0x20400000);
+ nvkm_wo32(chan->base.inst, 0x94, 0x30000001);
+ nvkm_wo32(chan->base.inst, 0x9c, 0x00000100);
+ nvkm_wo32(chan->base.inst, 0xac, 0x0000001f);
+ nvkm_wo32(chan->base.inst, 0xe8, chan->base.chid);
+ nvkm_wo32(chan->base.inst, 0xb8, 0xf8000000);
+ nvkm_wo32(chan->base.inst, 0xf8, 0x10003080); /* 0x002310 */
+ nvkm_wo32(chan->base.inst, 0xfc, 0x10000010); /* 0x002350 */
+ nvkm_done(chan->base.inst);
return 0;
}
-static void
-gk104_fifo_context_dtor(struct nvkm_object *object)
-{
- struct gk104_fifo_base *base = (void *)object;
- nvkm_vm_ref(NULL, &base->vm, base->pgd);
- nvkm_gpuobj_del(&base->pgd);
- nvkm_fifo_context_destroy(&base->base);
-}
-
-struct nvkm_oclass
-gk104_fifo_cclass = {
- .handle = NV_ENGCTX(FIFO, 0xe0),
- .ofuncs = &(struct nvkm_ofuncs) {
- .ctor = gk104_fifo_context_ctor,
- .dtor = gk104_fifo_context_dtor,
- .init = _nvkm_fifo_context_init,
- .fini = _nvkm_fifo_context_fini,
- .rd32 = _nvkm_fifo_context_rd32,
- .wr32 = _nvkm_fifo_context_wr32,
- },
+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/gpfifogm204.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogm204.c
index 7beee1f8729a..6511d6e21ecc 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogm204.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogm204.c
@@ -25,8 +25,10 @@
#include <nvif/class.h>
-struct nvkm_oclass
-gm204_fifo_sclass[] = {
- { MAXWELL_CHANNEL_GPFIFO_A, &gk104_fifo_chan_ofuncs },
- {}
+const struct nvkm_fifo_chan_oclass
+gm204_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/gpfifonv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifonv50.c
index ca7de9a6d67f..a8c69f878221 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifonv50.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifonv50.c
@@ -30,15 +30,14 @@
#include <nvif/unpack.h>
static int
-nv50_fifo_chan_ctor_ind(struct nvkm_object *parent, struct nvkm_object *engine,
- struct nvkm_oclass *oclass, void *data, u32 size,
- struct nvkm_object **pobject)
+nv50_fifo_gpfifo_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass,
+ void *data, u32 size, struct nvkm_object **pobject)
{
+ struct nvkm_object *parent = oclass->parent;
union {
struct nv50_channel_gpfifo_v0 v0;
} *args = data;
- struct nvkm_device *device = parent->engine->subdev.device;
- struct nv50_fifo_base *base = (void *)parent;
+ struct nv50_fifo *fifo = nv50_fifo(base);
struct nv50_fifo_chan *chan;
u64 ioffset, ilength;
int ret;
@@ -50,61 +49,44 @@ nv50_fifo_chan_ctor_ind(struct nvkm_object *parent, struct nvkm_object *engine,
"ilength %08x\n",
args->v0.version, args->v0.vm, args->v0.pushbuf,
args->v0.ioffset, args->v0.ilength);
- if (args->v0.vm)
- return -ENOENT;
+ if (!args->v0.pushbuf)
+ return -EINVAL;
} else
return ret;
- ret = nvkm_fifo_channel_create(parent, engine, oclass, 0, 0xc00000,
- 0x2000, args->v0.pushbuf,
- (1ULL << NVDEV_ENGINE_DMAOBJ) |
- (1ULL << NVDEV_ENGINE_SW) |
- (1ULL << NVDEV_ENGINE_GR) |
- (1ULL << NVDEV_ENGINE_MPEG), &chan);
- *pobject = nv_object(chan);
- if (ret)
- return ret;
-
- chan->base.inst = base->base.gpuobj.addr;
- args->v0.chid = chan->base.chid;
-
- nv_parent(chan)->context_attach = nv50_fifo_context_attach;
- nv_parent(chan)->context_detach = nv50_fifo_context_detach;
- nv_parent(chan)->object_attach = nv50_fifo_object_attach;
- nv_parent(chan)->object_detach = nv50_fifo_object_detach;
+ if (!(chan = kzalloc(sizeof(*chan), GFP_KERNEL)))
+ return -ENOMEM;
+ *pobject = &chan->base.object;
- ret = nvkm_ramht_new(device, 0x8000, 16, &base->base.gpuobj,
- &chan->ramht);
+ ret = nv50_fifo_chan_ctor(fifo, args->v0.vm, args->v0.pushbuf,
+ oclass, chan);
if (ret)
return ret;
+ args->v0.chid = chan->base.chid;
ioffset = args->v0.ioffset;
ilength = order_base_2(args->v0.ilength / 8);
- nvkm_kmap(base->ramfc);
- nvkm_wo32(base->ramfc, 0x3c, 0x403f6078);
- nvkm_wo32(base->ramfc, 0x44, 0x01003fff);
- nvkm_wo32(base->ramfc, 0x48, chan->base.pushgpu->node->offset >> 4);
- nvkm_wo32(base->ramfc, 0x50, lower_32_bits(ioffset));
- nvkm_wo32(base->ramfc, 0x54, upper_32_bits(ioffset) | (ilength << 16));
- nvkm_wo32(base->ramfc, 0x60, 0x7fffffff);
- nvkm_wo32(base->ramfc, 0x78, 0x00000000);
- nvkm_wo32(base->ramfc, 0x7c, 0x30000001);
- nvkm_wo32(base->ramfc, 0x80, ((chan->ramht->bits - 9) << 27) |
+ nvkm_kmap(chan->ramfc);
+ nvkm_wo32(chan->ramfc, 0x3c, 0x403f6078);
+ nvkm_wo32(chan->ramfc, 0x44, 0x01003fff);
+ nvkm_wo32(chan->ramfc, 0x48, chan->base.push->node->offset >> 4);
+ nvkm_wo32(chan->ramfc, 0x50, lower_32_bits(ioffset));
+ nvkm_wo32(chan->ramfc, 0x54, upper_32_bits(ioffset) | (ilength << 16));
+ nvkm_wo32(chan->ramfc, 0x60, 0x7fffffff);
+ nvkm_wo32(chan->ramfc, 0x78, 0x00000000);
+ nvkm_wo32(chan->ramfc, 0x7c, 0x30000001);
+ nvkm_wo32(chan->ramfc, 0x80, ((chan->ramht->bits - 9) << 27) |
(4 << 24) /* SEARCH_FULL */ |
(chan->ramht->gpuobj->node->offset >> 4));
- nvkm_done(base->ramfc);
+ nvkm_done(chan->ramfc);
return 0;
}
-struct nvkm_ofuncs
-nv50_fifo_ofuncs_ind = {
- .ctor = nv50_fifo_chan_ctor_ind,
- .dtor = nv50_fifo_chan_dtor,
- .init = nv50_fifo_chan_init,
- .fini = nv50_fifo_chan_fini,
- .map = _nvkm_fifo_channel_map,
- .rd32 = _nvkm_fifo_channel_rd32,
- .wr32 = _nvkm_fifo_channel_wr32,
- .ntfy = _nvkm_fifo_channel_ntfy
+const struct nvkm_fifo_chan_oclass
+nv50_fifo_gpfifo_oclass = {
+ .base.oclass = NV50_CHANNEL_GPFIFO,
+ .base.minver = 0,
+ .base.maxver = 0,
+ .ctor = nv50_fifo_gpfifo_new,
};
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c
index d880cfa6de9e..d1ad3fa72c34 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c
@@ -25,6 +25,7 @@
#include "channv04.h"
#include "regsnv04.h"
+#include <core/client.h>
#include <core/handle.h>
#include <core/ramht.h>
#include <subdev/instmem.h>
@@ -136,6 +137,8 @@ nv04_fifo_cache_error(struct nv04_fifo *fifo, u32 chid, u32 get)
{
struct nvkm_subdev *subdev = &fifo->base.engine.subdev;
struct nvkm_device *device = subdev->device;
+ struct nvkm_fifo_chan *chan;
+ unsigned long flags;
u32 pull0 = nvkm_rd32(device, 0x003250);
u32 mthd, data;
int ptr;
@@ -157,12 +160,12 @@ nv04_fifo_cache_error(struct nv04_fifo *fifo, u32 chid, u32 get)
if (!(pull0 & 0x00000100) ||
!nv04_fifo_swmthd(device, chid, mthd, data)) {
- const char *client_name =
- nvkm_client_name_for_fifo_chid(&fifo->base, chid);
+ chan = nvkm_fifo_chan_chid(&fifo->base, chid, &flags);
nvkm_error(subdev, "CACHE_ERROR - "
"ch %d [%s] subc %d mthd %04x data %08x\n",
- chid, client_name, (mthd >> 13) & 7, mthd & 0x1ffc,
- data);
+ chid, chan ? chan->object.client->name : "unknown",
+ (mthd >> 13) & 7, mthd & 0x1ffc, data);
+ nvkm_fifo_chan_put(&fifo->base, flags, &chan);
}
nvkm_wr32(device, NV04_PFIFO_CACHE1_DMA_PUSH, 0);
@@ -189,10 +192,12 @@ nv04_fifo_dma_pusher(struct nv04_fifo *fifo, u32 chid)
u32 dma_put = nvkm_rd32(device, 0x003240);
u32 push = nvkm_rd32(device, 0x003220);
u32 state = nvkm_rd32(device, 0x003228);
- const char *client_name;
-
- client_name = nvkm_client_name_for_fifo_chid(&fifo->base, chid);
+ struct nvkm_fifo_chan *chan;
+ unsigned long flags;
+ const char *name;
+ chan = nvkm_fifo_chan_chid(&fifo->base, chid, &flags);
+ name = chan ? chan->object.client->name : "unknown";
if (device->card_type == NV_50) {
u32 ho_get = nvkm_rd32(device, 0x003328);
u32 ho_put = nvkm_rd32(device, 0x003320);
@@ -202,7 +207,7 @@ nv04_fifo_dma_pusher(struct nv04_fifo *fifo, u32 chid)
nvkm_error(subdev, "DMA_PUSHER - "
"ch %d [%s] get %02x%08x put %02x%08x ib_get %08x "
"ib_put %08x state %08x (err: %s) push %08x\n",
- chid, client_name, ho_get, dma_get, ho_put, dma_put,
+ chid, name, ho_get, dma_get, ho_put, dma_put,
ib_get, ib_put, state, nv_dma_state_err(state),
push);
@@ -217,12 +222,13 @@ nv04_fifo_dma_pusher(struct nv04_fifo *fifo, u32 chid)
} else {
nvkm_error(subdev, "DMA_PUSHER - ch %d [%s] get %08x put %08x "
"state %08x (err: %s) push %08x\n",
- chid, client_name, dma_get, dma_put, state,
+ chid, name, dma_get, dma_put, state,
nv_dma_state_err(state), push);
if (dma_get != dma_put)
nvkm_wr32(device, 0x003244, dma_put);
}
+ nvkm_fifo_chan_put(&fifo->base, flags, &chan);
nvkm_wr32(device, 0x003228, 0x00000000);
nvkm_wr32(device, 0x003220, 0x00000001);
@@ -241,7 +247,7 @@ nv04_fifo_intr(struct nvkm_subdev *subdev)
reassign = nvkm_rd32(device, NV03_PFIFO_CACHES) & 1;
nvkm_wr32(device, NV03_PFIFO_CACHES, 0);
- chid = nvkm_rd32(device, NV03_PFIFO_CACHE1_PUSH1) & fifo->base.max;
+ chid = nvkm_rd32(device, NV03_PFIFO_CACHE1_PUSH1) & (fifo->base.nr - 1);
get = nvkm_rd32(device, NV03_PFIFO_CACHE1_GET);
if (stat & NV_PFIFO_INTR_CACHE_ERROR) {
@@ -311,7 +317,7 @@ nv04_fifo_init(struct nvkm_object *object)
nvkm_wr32(device, NV03_PFIFO_RAMRO, nvkm_memory_addr(ramro) >> 8);
nvkm_wr32(device, NV03_PFIFO_RAMFC, nvkm_memory_addr(ramfc) >> 8);
- nvkm_wr32(device, NV03_PFIFO_CACHE1_PUSH1, fifo->base.max);
+ nvkm_wr32(device, NV03_PFIFO_CACHE1_PUSH1, fifo->base.nr - 1);
nvkm_wr32(device, NV03_PFIFO_INTR_0, 0xffffffff);
nvkm_wr32(device, NV03_PFIFO_INTR_EN_0, 0xffffffff);
@@ -329,6 +335,14 @@ nv04_fifo_dtor(struct nvkm_object *object)
nvkm_fifo_destroy(&fifo->base);
}
+static const struct nvkm_fifo_func
+nv04_fifo_func = {
+ .chan = {
+ &nv04_fifo_dma_oclass,
+ NULL
+ },
+};
+
static int
nv04_fifo_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
struct nvkm_oclass *oclass, void *data, u32 size,
@@ -342,10 +356,10 @@ nv04_fifo_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
if (ret)
return ret;
+ fifo->base.func = &nv04_fifo_func;
+
nv_subdev(fifo)->unit = 0x00000100;
nv_subdev(fifo)->intr = nv04_fifo_intr;
- nv_engine(fifo)->cclass = &nv04_fifo_cclass;
- nv_engine(fifo)->sclass = nv04_fifo_sclass;
fifo->base.pause = nv04_fifo_pause;
fifo->base.start = nv04_fifo_start;
fifo->ramfc_desc = nv04_ramfc;
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.h
index 5cde3310ee4d..c33dc56f8e02 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.h
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.h
@@ -1,5 +1,6 @@
#ifndef __NV04_FIFO_H__
#define __NV04_FIFO_H__
+#define nv04_fifo(p) container_of((p), struct nv04_fifo, base)
#include "priv.h"
struct ramfc_desc {
@@ -15,14 +16,6 @@ struct nv04_fifo {
struct ramfc_desc *ramfc_desc;
};
-struct nv04_fifo_base {
- struct nvkm_fifo_base base;
-};
-
-int nv04_fifo_context_ctor(struct nvkm_object *, struct nvkm_object *,
- struct nvkm_oclass *, void *, u32,
- struct nvkm_object **);
-
void nv04_fifo_dtor(struct nvkm_object *);
int nv04_fifo_init(struct nvkm_object *);
#endif
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv10.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv10.c
index ae0a1b17eb92..d7fab9598fb0 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv10.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv10.c
@@ -39,16 +39,11 @@ nv10_ramfc[] = {
{}
};
-static struct nvkm_oclass
-nv10_fifo_cclass = {
- .handle = NV_ENGCTX(FIFO, 0x10),
- .ofuncs = &(struct nvkm_ofuncs) {
- .ctor = nv04_fifo_context_ctor,
- .dtor = _nvkm_fifo_context_dtor,
- .init = _nvkm_fifo_context_init,
- .fini = _nvkm_fifo_context_fini,
- .rd32 = _nvkm_fifo_context_rd32,
- .wr32 = _nvkm_fifo_context_wr32,
+static const struct nvkm_fifo_func
+nv10_fifo_func = {
+ .chan = {
+ &nv10_fifo_dma_oclass,
+ NULL
},
};
@@ -65,10 +60,10 @@ nv10_fifo_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
if (ret)
return ret;
+ fifo->base.func = &nv10_fifo_func;
+
nv_subdev(fifo)->unit = 0x00000100;
nv_subdev(fifo)->intr = nv04_fifo_intr;
- nv_engine(fifo)->cclass = &nv10_fifo_cclass;
- nv_engine(fifo)->sclass = nv10_fifo_sclass;
fifo->base.pause = nv04_fifo_pause;
fifo->base.start = nv04_fifo_start;
fifo->ramfc_desc = nv10_ramfc;
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv17.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv17.c
index ff2b6d95d804..a8e28fc24e75 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv17.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv17.c
@@ -47,19 +47,6 @@ nv17_ramfc[] = {
{}
};
-static struct nvkm_oclass
-nv17_fifo_cclass = {
- .handle = NV_ENGCTX(FIFO, 0x17),
- .ofuncs = &(struct nvkm_ofuncs) {
- .ctor = nv04_fifo_context_ctor,
- .dtor = _nvkm_fifo_context_dtor,
- .init = _nvkm_fifo_context_init,
- .fini = _nvkm_fifo_context_fini,
- .rd32 = _nvkm_fifo_context_rd32,
- .wr32 = _nvkm_fifo_context_wr32,
- },
-};
-
static int
nv17_fifo_init(struct nvkm_object *object)
{
@@ -85,7 +72,7 @@ nv17_fifo_init(struct nvkm_object *object)
nvkm_wr32(device, NV03_PFIFO_RAMFC, nvkm_memory_addr(ramfc) >> 8 |
0x00010000);
- nvkm_wr32(device, NV03_PFIFO_CACHE1_PUSH1, fifo->base.max);
+ nvkm_wr32(device, NV03_PFIFO_CACHE1_PUSH1, fifo->base.nr - 1);
nvkm_wr32(device, NV03_PFIFO_INTR_0, 0xffffffff);
nvkm_wr32(device, NV03_PFIFO_INTR_EN_0, 0xffffffff);
@@ -96,6 +83,14 @@ nv17_fifo_init(struct nvkm_object *object)
return 0;
}
+static const struct nvkm_fifo_func
+nv17_fifo_func = {
+ .chan = {
+ &nv17_fifo_dma_oclass,
+ NULL
+ },
+};
+
static int
nv17_fifo_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
struct nvkm_oclass *oclass, void *data, u32 size,
@@ -109,10 +104,10 @@ nv17_fifo_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
if (ret)
return ret;
+ fifo->base.func = &nv17_fifo_func;
+
nv_subdev(fifo)->unit = 0x00000100;
nv_subdev(fifo)->intr = nv04_fifo_intr;
- nv_engine(fifo)->cclass = &nv17_fifo_cclass;
- nv_engine(fifo)->sclass = nv17_fifo_sclass;
fifo->base.pause = nv04_fifo_pause;
fifo->base.start = nv04_fifo_start;
fifo->ramfc_desc = nv17_ramfc;
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv40.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv40.c
index 64be69fc9572..aca146377d36 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv40.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv40.c
@@ -56,19 +56,6 @@ nv40_ramfc[] = {
{}
};
-static struct nvkm_oclass
-nv40_fifo_cclass = {
- .handle = NV_ENGCTX(FIFO, 0x40),
- .ofuncs = &(struct nvkm_ofuncs) {
- .ctor = nv04_fifo_context_ctor,
- .dtor = _nvkm_fifo_context_dtor,
- .init = _nvkm_fifo_context_init,
- .fini = _nvkm_fifo_context_fini,
- .rd32 = _nvkm_fifo_context_rd32,
- .wr32 = _nvkm_fifo_context_wr32,
- },
-};
-
static int
nv40_fifo_init(struct nvkm_object *object)
{
@@ -115,7 +102,7 @@ nv40_fifo_init(struct nvkm_object *object)
break;
}
- nvkm_wr32(device, NV03_PFIFO_CACHE1_PUSH1, fifo->base.max);
+ nvkm_wr32(device, NV03_PFIFO_CACHE1_PUSH1, fifo->base.nr - 1);
nvkm_wr32(device, NV03_PFIFO_INTR_0, 0xffffffff);
nvkm_wr32(device, NV03_PFIFO_INTR_EN_0, 0xffffffff);
@@ -126,6 +113,14 @@ nv40_fifo_init(struct nvkm_object *object)
return 0;
}
+static const struct nvkm_fifo_func
+nv40_fifo_func = {
+ .chan = {
+ &nv40_fifo_dma_oclass,
+ NULL
+ },
+};
+
static int
nv40_fifo_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
struct nvkm_oclass *oclass, void *data, u32 size,
@@ -139,10 +134,10 @@ nv40_fifo_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
if (ret)
return ret;
+ fifo->base.func = &nv40_fifo_func;
+
nv_subdev(fifo)->unit = 0x00000100;
nv_subdev(fifo)->intr = nv04_fifo_intr;
- nv_engine(fifo)->cclass = &nv40_fifo_cclass;
- nv_engine(fifo)->sclass = nv40_fifo_sclass;
fifo->base.pause = nv04_fifo_pause;
fifo->base.start = nv04_fifo_start;
fifo->ramfc_desc = nv40_ramfc;
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.c
index bf17cb0e8385..ad653e9c461a 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.c
@@ -35,7 +35,7 @@ nv50_fifo_runlist_update_locked(struct nv50_fifo *fifo)
fifo->cur_runlist = !fifo->cur_runlist;
nvkm_kmap(cur);
- for (i = fifo->base.min, p = 0; i < fifo->base.max; i++) {
+ for (i = 0, p = 0; i < fifo->base.nr; i++) {
if (nvkm_rd32(device, 0x002600 + (i * 4)) & 0x80000000)
nvkm_wo32(cur, p++ * 4, i);
}
@@ -94,6 +94,15 @@ nv50_fifo_dtor(struct nvkm_object *object)
nvkm_fifo_destroy(&fifo->base);
}
+static const struct nvkm_fifo_func
+nv50_fifo_func = {
+ .chan = {
+ &nv50_fifo_dma_oclass,
+ &nv50_fifo_gpfifo_oclass,
+ NULL
+ },
+};
+
static int
nv50_fifo_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
struct nvkm_oclass *oclass, void *data, u32 size,
@@ -108,6 +117,8 @@ nv50_fifo_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
if (ret)
return ret;
+ fifo->base.func = &nv50_fifo_func;
+
ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, 128 * 4, 0x1000,
false, &fifo->runlist[0]);
if (ret)
@@ -120,8 +131,6 @@ nv50_fifo_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
nv_subdev(fifo)->unit = 0x00000100;
nv_subdev(fifo)->intr = nv04_fifo_intr;
- nv_engine(fifo)->cclass = &nv50_fifo_cclass;
- nv_engine(fifo)->sclass = nv50_fifo_sclass;
fifo->base.pause = nv04_fifo_pause;
fifo->base.start = nv04_fifo_start;
return 0;
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.h
index 306593fc56bb..a7d5dba12fb8 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.h
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.h
@@ -1,5 +1,6 @@
#ifndef __NV50_FIFO_H__
#define __NV50_FIFO_H__
+#define nv50_fifo(p) container_of((p), struct nv50_fifo, base)
#include "priv.h"
struct nv50_fifo {
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h
index b202f7f9413d..a30d160f30db 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h
@@ -1,7 +1,6 @@
#ifndef __NVKM_FIFO_PRIV_H__
#define __NVKM_FIFO_PRIV_H__
#include <engine/fifo.h>
-#include <core/engctx.h>
void nv04_fifo_pause(struct nvkm_fifo *, unsigned long *);
void nv04_fifo_start(struct nvkm_fifo *, unsigned long *);
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c
index c6ff24b5a11d..ebc9dee03beb 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c
@@ -1168,10 +1168,14 @@ gf100_gr_intr(struct nvkm_subdev *subdev)
u32 data = nvkm_rd32(device, 0x400708);
u32 code = nvkm_rd32(device, 0x400110);
u32 class;
- int chid;
+ const char *name = "unknown";
+ int chid = -1;
chan = nvkm_fifo_chan_inst(device->fifo, (u64)inst << 12, &flags);
- chid = chan ? chan->chid : -1;
+ if (chan) {
+ name = chan->object.client->name;
+ chid = chan->chid;
+ }
if (nv_device(gr)->card_type < NV_E0 || subc < 4)
class = nvkm_rd32(device, 0x404200 + (subc * 4));
@@ -1191,8 +1195,8 @@ gf100_gr_intr(struct nvkm_subdev *subdev)
if (!gf100_gr_mthd_sw(device, class, mthd, data)) {
nvkm_error(subdev, "ILLEGAL_MTHD ch %d [%010llx %s] "
"subc %d class %04x mthd %04x data %08x\n",
- chid, inst << 12, nvkm_client_name(chan),
- subc, class, mthd, data);
+ chid, inst << 12, name, subc,
+ class, mthd, data);
}
nvkm_wr32(device, 0x400100, 0x00000010);
stat &= ~0x00000010;
@@ -1201,8 +1205,7 @@ gf100_gr_intr(struct nvkm_subdev *subdev)
if (stat & 0x00000020) {
nvkm_error(subdev, "ILLEGAL_CLASS ch %d [%010llx %s] "
"subc %d class %04x mthd %04x data %08x\n",
- chid, inst << 12, nvkm_client_name(chan), subc,
- class, mthd, data);
+ chid, inst << 12, name, subc, class, mthd, data);
nvkm_wr32(device, 0x400100, 0x00000020);
stat &= ~0x00000020;
}
@@ -1213,14 +1216,14 @@ gf100_gr_intr(struct nvkm_subdev *subdev)
nvkm_error(subdev, "DATA_ERROR %08x [%s] ch %d [%010llx %s] "
"subc %d class %04x mthd %04x data %08x\n",
code, en ? en->name : "", chid, inst << 12,
- nvkm_client_name(chan), subc, class, mthd, data);
+ name, subc, class, mthd, data);
nvkm_wr32(device, 0x400100, 0x00100000);
stat &= ~0x00100000;
}
if (stat & 0x00200000) {
nvkm_error(subdev, "TRAP ch %d [%010llx %s]\n",
- chid, inst << 12, nvkm_client_name(chan));
+ chid, inst << 12, name);
gf100_gr_trap_intr(gr);
nvkm_wr32(device, 0x400100, 0x00200000);
stat &= ~0x00200000;
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv20.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv20.c
index 262638b4e0c5..29feab391fe4 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv20.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv20.c
@@ -230,7 +230,8 @@ nv20_gr_intr(struct nvkm_subdev *subdev)
"nstatus %08x [%s] ch %d [%s] subc %d "
"class %04x mthd %04x data %08x\n",
show, msg, nsource, src, nstatus, sta, chid,
- nvkm_client_name(chan), subc, class, mthd, data);
+ chan ? chan->object.client->name : "unknown",
+ subc, class, mthd, data);
}
nvkm_fifo_chan_put(device->fifo, flags, &chan);
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv40.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv40.c
index 4db2a17f5308..e716ae12b55c 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv40.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv40.c
@@ -353,7 +353,8 @@ nv40_gr_intr(struct nvkm_subdev *subdev)
"class %04x mthd %04x data %08x\n",
show, msg, nsource, src, nstatus, sta,
chan ? chan->fifo->chid : -1, inst << 4,
- nvkm_client_name(chan), subc, class, mthd, data);
+ chan ? chan->fifo->object.client->name : "unknown",
+ subc, class, mthd, data);
}
spin_unlock_irqrestore(&gr->base.engine.lock, flags);
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv50.c
index daac54075705..5f22dd3c788c 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv50.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv50.c
@@ -608,7 +608,7 @@ nv50_gr_tp_trap(struct nv50_gr *gr, int type, u32 ustatus_old,
static int
nv50_gr_trap_handler(struct nv50_gr *gr, u32 display,
- int chid, u64 inst, struct nvkm_fifo_chan *chan)
+ int chid, u64 inst, const char *name)
{
struct nvkm_subdev *subdev = &gr->base.engine.subdev;
struct nvkm_device *device = subdev->device;
@@ -648,8 +648,7 @@ nv50_gr_trap_handler(struct nv50_gr *gr, u32 display,
"ch %d [%010llx %s] subc %d "
"class %04x mthd %04x data %08x%08x "
"400808 %08x 400848 %08x\n",
- chid, inst, nvkm_client_name(chan),
- subc, class, mthd,
+ chid, inst, name, subc, class, mthd,
datah, datal, addr, r848);
} else
if (display) {
@@ -674,9 +673,8 @@ nv50_gr_trap_handler(struct nv50_gr *gr, u32 display,
nvkm_error(subdev,
"ch %d [%010llx %s] subc %d "
"class %04x mthd %04x data %08x "
- "40084c %08x\n", chid, inst,
- nvkm_client_name(chan), subc,
- class, mthd, data, addr);
+ "40084c %08x\n", chid, inst, name,
+ subc, class, mthd, data, addr);
} else
if (display) {
nvkm_error(subdev, "no stuck command?\n");
@@ -849,11 +847,15 @@ nv50_gr_intr(struct nvkm_subdev *subdev)
u32 show = stat, show_bitfield = stat;
const struct nvkm_enum *en;
unsigned long flags;
+ const char *name = "unknown";
char msg[128];
- int chid;
+ int chid = -1;
chan = nvkm_fifo_chan_inst(device->fifo, (u64)inst << 12, &flags);
- chid = chan ? chan->chid : -1;
+ if (chan) {
+ name = chan->object.client->name;
+ chid = chan->chid;
+ }
if (show & 0x00100000) {
u32 ecode = nvkm_rd32(device, 0x400110);
@@ -864,7 +866,7 @@ nv50_gr_intr(struct nvkm_subdev *subdev)
}
if (stat & 0x00200000) {
- if (!nv50_gr_trap_handler(gr, show, chid, (u64)inst << 12, chan))
+ if (!nv50_gr_trap_handler(gr, show, chid, (u64)inst << 12, name))
show &= ~0x00200000;
show_bitfield &= ~0x00200000;
}
@@ -877,8 +879,8 @@ nv50_gr_intr(struct nvkm_subdev *subdev)
nvkm_snprintbf(msg, sizeof(msg), nv50_gr_intr_name, show);
nvkm_error(subdev, "%08x [%s] ch %d [%010llx %s] subc %d "
"class %04x mthd %04x data %08x\n",
- stat, msg, chid, (u64)inst << 12,
- nvkm_client_name(chan), subc, class, mthd, data);
+ stat, msg, chid, (u64)inst << 12, name,
+ subc, class, mthd, data);
}
if (nvkm_rd32(device, 0x400824) & (1 << 31))
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv31.c b/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv31.c
index 05597f2070ed..211b44c00c85 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv31.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv31.c
@@ -231,8 +231,8 @@ nv31_mpeg_intr(struct nvkm_subdev *subdev)
if (show) {
nvkm_error(subdev, "ch %d [%s] %08x %08x %08x %08x\n",
mpeg->chan ? mpeg->chan->fifo->chid : -1,
- nvkm_client_name(mpeg->chan),
- stat, type, mthd, data);
+ mpeg->chan ? mpeg->chan->fifo->object.client->name :
+ "unknown", stat, type, mthd, data);
}
spin_unlock_irqrestore(&mpeg->base.engine.lock, flags);
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv44.c b/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv44.c
index 1223baddfb9a..ff9ddc67a292 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv44.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv44.c
@@ -145,13 +145,11 @@ nv44_mpeg_intr(struct nvkm_subdev *subdev)
u32 mthd = nvkm_rd32(device, 0x00b234);
u32 data = nvkm_rd32(device, 0x00b238);
u32 show = stat;
- int chid = -1;
spin_lock_irqsave(&mpeg->base.engine.lock, flags);
list_for_each_entry(temp, &mpeg->chan, head) {
if (temp->inst >> 4 == inst) {
chan = temp;
- chid = chan->fifo->chid;
list_del(&chan->head);
list_add(&chan->head, &mpeg->chan);
break;
@@ -176,7 +174,8 @@ nv44_mpeg_intr(struct nvkm_subdev *subdev)
if (show) {
nvkm_error(subdev, "ch %d [%08x %s] %08x %08x %08x %08x\n",
- chid, inst << 4, nvkm_client_name(chan),
+ chan ? chan->fifo->chid : -1, inst << 4,
+ chan ? chan->fifo->object.client->name : "unknown",
stat, type, mthd, data);
}
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sec/g98.c b/drivers/gpu/drm/nouveau/nvkm/engine/sec/g98.c
index e6544097726c..c15934d7ff63 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/sec/g98.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/sec/g98.c
@@ -84,7 +84,8 @@ g98_sec_intr(struct nvkm_falcon *sec, struct nvkm_fifo_chan *chan)
nvkm_error(subdev, "DISPATCH_ERROR %04x [%s] ch %d [%010llx %s] "
"subc %d mthd %04x data %08x\n", ssta,
en ? en->name : "UNKNOWN", chan ? chan->chid : -1,
- chan ? chan->inst : 0, nvkm_client_name(chan),
+ chan ? chan->inst->addr : 0,
+ chan ? chan->object.client->name : "unknown",
subc, mthd, data);
}
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sw/nv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/sw/nv50.c
index 4e8b632ef5b1..35ec1cffb53a 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/sw/nv50.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/sw/nv50.c
@@ -24,8 +24,8 @@
#include "nv50.h"
#include <core/handle.h>
-#include <core/namedb.h>
#include <engine/disp.h>
+#include <engine/fifo/chan.h>
#include <subdev/bar.h>
#include <nvif/event.h>
@@ -136,7 +136,7 @@ nv50_sw_context_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
return ret;
}
- chan->vblank.channel = nv_gpuobj(parent->parent)->addr >> 12;
+ chan->vblank.channel = nvkm_fifo_chan(parent)->inst->addr >> 12;
return 0;
}