Commit bbf8906b authored by Ben Skeggs's avatar Ben Skeggs

drm/nouveau/fifo: audit and version fifo channel classes

The full object interfaces are about to be exposed to userspace, so we
need to check for any security-related issues and version the structs
to make it easier to handle any changes we may need in the future.
Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
parent a532da97
...@@ -52,10 +52,10 @@ nv04_dmaobj_bind(struct nouveau_dmaobj *dmaobj, ...@@ -52,10 +52,10 @@ nv04_dmaobj_bind(struct nouveau_dmaobj *dmaobj,
if (!nv_iclass(parent, NV_ENGCTX_CLASS)) { if (!nv_iclass(parent, NV_ENGCTX_CLASS)) {
switch (nv_mclass(parent->parent)) { switch (nv_mclass(parent->parent)) {
case NV03_CHANNEL_DMA_CLASS: case NV03_CHANNEL_DMA:
case NV10_CHANNEL_DMA_CLASS: case NV10_CHANNEL_DMA:
case NV17_CHANNEL_DMA_CLASS: case NV17_CHANNEL_DMA:
case NV40_CHANNEL_DMA_CLASS: case NV40_CHANNEL_DMA:
break; break;
default: default:
return -EINVAL; return -EINVAL;
......
...@@ -48,10 +48,9 @@ nv50_dmaobj_bind(struct nouveau_dmaobj *dmaobj, ...@@ -48,10 +48,9 @@ nv50_dmaobj_bind(struct nouveau_dmaobj *dmaobj,
if (!nv_iclass(parent, NV_ENGCTX_CLASS)) { if (!nv_iclass(parent, NV_ENGCTX_CLASS)) {
switch (nv_mclass(parent->parent)) { switch (nv_mclass(parent->parent)) {
case NV50_CHANNEL_DMA_CLASS: case NV40_CHANNEL_DMA:
case NV84_CHANNEL_DMA_CLASS: case NV50_CHANNEL_GPFIFO:
case NV50_CHANNEL_IND_CLASS: case G82_CHANNEL_GPFIFO:
case NV84_CHANNEL_IND_CLASS:
case NV50_DISP_MAST_CLASS: case NV50_DISP_MAST_CLASS:
case NV84_DISP_MAST_CLASS: case NV84_DISP_MAST_CLASS:
case NV94_DISP_MAST_CLASS: case NV94_DISP_MAST_CLASS:
......
...@@ -26,7 +26,8 @@ ...@@ -26,7 +26,8 @@
#include <core/object.h> #include <core/object.h>
#include <core/handle.h> #include <core/handle.h>
#include <core/event.h> #include <core/event.h>
#include <core/class.h> #include <nvif/unpack.h>
#include <nvif/class.h>
#include <engine/dmaobj.h> #include <engine/dmaobj.h>
#include <engine/fifo.h> #include <engine/fifo.h>
......
...@@ -22,8 +22,9 @@ ...@@ -22,8 +22,9 @@
* Authors: Ben Skeggs * Authors: Ben Skeggs
*/ */
#include <core/os.h> #include <core/client.h>
#include <core/class.h> #include <nvif/unpack.h>
#include <nvif/class.h>
#include <core/engctx.h> #include <core/engctx.h>
#include <core/namedb.h> #include <core/namedb.h>
#include <core/handle.h> #include <core/handle.h>
...@@ -117,16 +118,23 @@ nv04_fifo_chan_ctor(struct nouveau_object *parent, ...@@ -117,16 +118,23 @@ nv04_fifo_chan_ctor(struct nouveau_object *parent,
struct nouveau_oclass *oclass, void *data, u32 size, struct nouveau_oclass *oclass, void *data, u32 size,
struct nouveau_object **pobject) struct nouveau_object **pobject)
{ {
union {
struct nv03_channel_dma_v0 v0;
} *args = data;
struct nv04_fifo_priv *priv = (void *)engine; struct nv04_fifo_priv *priv = (void *)engine;
struct nv04_fifo_chan *chan; struct nv04_fifo_chan *chan;
struct nv03_channel_dma_class *args = data;
int ret; int ret;
if (size < sizeof(*args)) nv_ioctl(parent, "create channel dma size %d\n", size);
return -EINVAL; if (nvif_unpack(args->v0, 0, 0, false)) {
nv_ioctl(parent, "create channel dma vers %d pushbuf %08x "
"offset %016llx\n", args->v0.version,
args->v0.pushbuf, args->v0.offset);
} else
return ret;
ret = nouveau_fifo_channel_create(parent, engine, oclass, 0, 0x800000, ret = nouveau_fifo_channel_create(parent, engine, oclass, 0, 0x800000,
0x10000, args->pushbuf, 0x10000, args->v0.pushbuf,
(1ULL << NVDEV_ENGINE_DMAOBJ) | (1ULL << NVDEV_ENGINE_DMAOBJ) |
(1ULL << NVDEV_ENGINE_SW) | (1ULL << NVDEV_ENGINE_SW) |
(1ULL << NVDEV_ENGINE_GR), &chan); (1ULL << NVDEV_ENGINE_GR), &chan);
...@@ -134,13 +142,15 @@ nv04_fifo_chan_ctor(struct nouveau_object *parent, ...@@ -134,13 +142,15 @@ nv04_fifo_chan_ctor(struct nouveau_object *parent,
if (ret) if (ret)
return ret; return ret;
args->v0.chid = chan->base.chid;
nv_parent(chan)->object_attach = nv04_fifo_object_attach; nv_parent(chan)->object_attach = nv04_fifo_object_attach;
nv_parent(chan)->object_detach = nv04_fifo_object_detach; nv_parent(chan)->object_detach = nv04_fifo_object_detach;
nv_parent(chan)->context_attach = nv04_fifo_context_attach; nv_parent(chan)->context_attach = nv04_fifo_context_attach;
chan->ramfc = chan->base.chid * 32; chan->ramfc = chan->base.chid * 32;
nv_wo32(priv->ramfc, chan->ramfc + 0x00, args->offset); nv_wo32(priv->ramfc, chan->ramfc + 0x00, args->v0.offset);
nv_wo32(priv->ramfc, chan->ramfc + 0x04, args->offset); nv_wo32(priv->ramfc, chan->ramfc + 0x04, args->v0.offset);
nv_wo32(priv->ramfc, chan->ramfc + 0x08, chan->base.pushgpu->addr >> 4); nv_wo32(priv->ramfc, chan->ramfc + 0x08, chan->base.pushgpu->addr >> 4);
nv_wo32(priv->ramfc, chan->ramfc + 0x10, nv_wo32(priv->ramfc, chan->ramfc + 0x10,
NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES | NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES |
...@@ -248,7 +258,7 @@ nv04_fifo_ofuncs = { ...@@ -248,7 +258,7 @@ nv04_fifo_ofuncs = {
static struct nouveau_oclass static struct nouveau_oclass
nv04_fifo_sclass[] = { nv04_fifo_sclass[] = {
{ NV03_CHANNEL_DMA_CLASS, &nv04_fifo_ofuncs }, { NV03_CHANNEL_DMA, &nv04_fifo_ofuncs },
{} {}
}; };
......
...@@ -22,8 +22,9 @@ ...@@ -22,8 +22,9 @@
* Authors: Ben Skeggs * Authors: Ben Skeggs
*/ */
#include <core/os.h> #include <core/client.h>
#include <core/class.h> #include <nvif/unpack.h>
#include <nvif/class.h>
#include <core/engctx.h> #include <core/engctx.h>
#include <core/ramht.h> #include <core/ramht.h>
...@@ -59,16 +60,23 @@ nv10_fifo_chan_ctor(struct nouveau_object *parent, ...@@ -59,16 +60,23 @@ nv10_fifo_chan_ctor(struct nouveau_object *parent,
struct nouveau_oclass *oclass, void *data, u32 size, struct nouveau_oclass *oclass, void *data, u32 size,
struct nouveau_object **pobject) struct nouveau_object **pobject)
{ {
union {
struct nv03_channel_dma_v0 v0;
} *args = data;
struct nv04_fifo_priv *priv = (void *)engine; struct nv04_fifo_priv *priv = (void *)engine;
struct nv04_fifo_chan *chan; struct nv04_fifo_chan *chan;
struct nv03_channel_dma_class *args = data;
int ret; int ret;
if (size < sizeof(*args)) nv_ioctl(parent, "create channel dma size %d\n", size);
return -EINVAL; if (nvif_unpack(args->v0, 0, 0, false)) {
nv_ioctl(parent, "create channel dma vers %d pushbuf %08x "
"offset %016llx\n", args->v0.version,
args->v0.pushbuf, args->v0.offset);
} else
return ret;
ret = nouveau_fifo_channel_create(parent, engine, oclass, 0, 0x800000, ret = nouveau_fifo_channel_create(parent, engine, oclass, 0, 0x800000,
0x10000, args->pushbuf, 0x10000, args->v0.pushbuf,
(1ULL << NVDEV_ENGINE_DMAOBJ) | (1ULL << NVDEV_ENGINE_DMAOBJ) |
(1ULL << NVDEV_ENGINE_SW) | (1ULL << NVDEV_ENGINE_SW) |
(1ULL << NVDEV_ENGINE_GR), &chan); (1ULL << NVDEV_ENGINE_GR), &chan);
...@@ -76,13 +84,15 @@ nv10_fifo_chan_ctor(struct nouveau_object *parent, ...@@ -76,13 +84,15 @@ nv10_fifo_chan_ctor(struct nouveau_object *parent,
if (ret) if (ret)
return ret; return ret;
args->v0.chid = chan->base.chid;
nv_parent(chan)->object_attach = nv04_fifo_object_attach; nv_parent(chan)->object_attach = nv04_fifo_object_attach;
nv_parent(chan)->object_detach = nv04_fifo_object_detach; nv_parent(chan)->object_detach = nv04_fifo_object_detach;
nv_parent(chan)->context_attach = nv04_fifo_context_attach; nv_parent(chan)->context_attach = nv04_fifo_context_attach;
chan->ramfc = chan->base.chid * 32; chan->ramfc = chan->base.chid * 32;
nv_wo32(priv->ramfc, chan->ramfc + 0x00, args->offset); nv_wo32(priv->ramfc, chan->ramfc + 0x00, args->v0.offset);
nv_wo32(priv->ramfc, chan->ramfc + 0x04, args->offset); nv_wo32(priv->ramfc, chan->ramfc + 0x04, args->v0.offset);
nv_wo32(priv->ramfc, chan->ramfc + 0x0c, chan->base.pushgpu->addr >> 4); nv_wo32(priv->ramfc, chan->ramfc + 0x0c, chan->base.pushgpu->addr >> 4);
nv_wo32(priv->ramfc, chan->ramfc + 0x14, nv_wo32(priv->ramfc, chan->ramfc + 0x14,
NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES | NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES |
...@@ -106,7 +116,7 @@ nv10_fifo_ofuncs = { ...@@ -106,7 +116,7 @@ nv10_fifo_ofuncs = {
static struct nouveau_oclass static struct nouveau_oclass
nv10_fifo_sclass[] = { nv10_fifo_sclass[] = {
{ NV10_CHANNEL_DMA_CLASS, &nv10_fifo_ofuncs }, { NV10_CHANNEL_DMA, &nv10_fifo_ofuncs },
{} {}
}; };
......
...@@ -22,8 +22,9 @@ ...@@ -22,8 +22,9 @@
* Authors: Ben Skeggs * Authors: Ben Skeggs
*/ */
#include <core/os.h> #include <core/client.h>
#include <core/class.h> #include <nvif/unpack.h>
#include <nvif/class.h>
#include <core/engctx.h> #include <core/engctx.h>
#include <core/ramht.h> #include <core/ramht.h>
...@@ -64,16 +65,23 @@ nv17_fifo_chan_ctor(struct nouveau_object *parent, ...@@ -64,16 +65,23 @@ nv17_fifo_chan_ctor(struct nouveau_object *parent,
struct nouveau_oclass *oclass, void *data, u32 size, struct nouveau_oclass *oclass, void *data, u32 size,
struct nouveau_object **pobject) struct nouveau_object **pobject)
{ {
union {
struct nv03_channel_dma_v0 v0;
} *args = data;
struct nv04_fifo_priv *priv = (void *)engine; struct nv04_fifo_priv *priv = (void *)engine;
struct nv04_fifo_chan *chan; struct nv04_fifo_chan *chan;
struct nv03_channel_dma_class *args = data;
int ret; int ret;
if (size < sizeof(*args)) nv_ioctl(parent, "create channel dma size %d\n", size);
return -EINVAL; if (nvif_unpack(args->v0, 0, 0, false)) {
nv_ioctl(parent, "create channel dma vers %d pushbuf %08x "
"offset %016llx\n", args->v0.version,
args->v0.pushbuf, args->v0.offset);
} else
return ret;
ret = nouveau_fifo_channel_create(parent, engine, oclass, 0, 0x800000, ret = nouveau_fifo_channel_create(parent, engine, oclass, 0, 0x800000,
0x10000, args->pushbuf, 0x10000, args->v0.pushbuf,
(1ULL << NVDEV_ENGINE_DMAOBJ) | (1ULL << NVDEV_ENGINE_DMAOBJ) |
(1ULL << NVDEV_ENGINE_SW) | (1ULL << NVDEV_ENGINE_SW) |
(1ULL << NVDEV_ENGINE_GR) | (1ULL << NVDEV_ENGINE_GR) |
...@@ -83,13 +91,15 @@ nv17_fifo_chan_ctor(struct nouveau_object *parent, ...@@ -83,13 +91,15 @@ nv17_fifo_chan_ctor(struct nouveau_object *parent,
if (ret) if (ret)
return ret; return ret;
args->v0.chid = chan->base.chid;
nv_parent(chan)->object_attach = nv04_fifo_object_attach; nv_parent(chan)->object_attach = nv04_fifo_object_attach;
nv_parent(chan)->object_detach = nv04_fifo_object_detach; nv_parent(chan)->object_detach = nv04_fifo_object_detach;
nv_parent(chan)->context_attach = nv04_fifo_context_attach; nv_parent(chan)->context_attach = nv04_fifo_context_attach;
chan->ramfc = chan->base.chid * 64; chan->ramfc = chan->base.chid * 64;
nv_wo32(priv->ramfc, chan->ramfc + 0x00, args->offset); nv_wo32(priv->ramfc, chan->ramfc + 0x00, args->v0.offset);
nv_wo32(priv->ramfc, chan->ramfc + 0x04, args->offset); nv_wo32(priv->ramfc, chan->ramfc + 0x04, args->v0.offset);
nv_wo32(priv->ramfc, chan->ramfc + 0x0c, chan->base.pushgpu->addr >> 4); nv_wo32(priv->ramfc, chan->ramfc + 0x0c, chan->base.pushgpu->addr >> 4);
nv_wo32(priv->ramfc, chan->ramfc + 0x14, nv_wo32(priv->ramfc, chan->ramfc + 0x14,
NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES | NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES |
...@@ -113,7 +123,7 @@ nv17_fifo_ofuncs = { ...@@ -113,7 +123,7 @@ nv17_fifo_ofuncs = {
static struct nouveau_oclass static struct nouveau_oclass
nv17_fifo_sclass[] = { nv17_fifo_sclass[] = {
{ NV17_CHANNEL_DMA_CLASS, &nv17_fifo_ofuncs }, { NV17_CHANNEL_DMA, &nv17_fifo_ofuncs },
{} {}
}; };
......
...@@ -22,8 +22,9 @@ ...@@ -22,8 +22,9 @@
* Authors: Ben Skeggs * Authors: Ben Skeggs
*/ */
#include <core/os.h> #include <core/client.h>
#include <core/class.h> #include <nvif/unpack.h>
#include <nvif/class.h>
#include <core/engctx.h> #include <core/engctx.h>
#include <core/ramht.h> #include <core/ramht.h>
...@@ -182,16 +183,23 @@ nv40_fifo_chan_ctor(struct nouveau_object *parent, ...@@ -182,16 +183,23 @@ nv40_fifo_chan_ctor(struct nouveau_object *parent,
struct nouveau_oclass *oclass, void *data, u32 size, struct nouveau_oclass *oclass, void *data, u32 size,
struct nouveau_object **pobject) struct nouveau_object **pobject)
{ {
union {
struct nv03_channel_dma_v0 v0;
} *args = data;
struct nv04_fifo_priv *priv = (void *)engine; struct nv04_fifo_priv *priv = (void *)engine;
struct nv04_fifo_chan *chan; struct nv04_fifo_chan *chan;
struct nv03_channel_dma_class *args = data;
int ret; int ret;
if (size < sizeof(*args)) nv_ioctl(parent, "create channel dma size %d\n", size);
return -EINVAL; if (nvif_unpack(args->v0, 0, 0, false)) {
nv_ioctl(parent, "create channel dma vers %d pushbuf %08x "
"offset %016llx\n", args->v0.version,
args->v0.pushbuf, args->v0.offset);
} else
return ret;
ret = nouveau_fifo_channel_create(parent, engine, oclass, 0, 0xc00000, ret = nouveau_fifo_channel_create(parent, engine, oclass, 0, 0xc00000,
0x1000, args->pushbuf, 0x1000, args->v0.pushbuf,
(1ULL << NVDEV_ENGINE_DMAOBJ) | (1ULL << NVDEV_ENGINE_DMAOBJ) |
(1ULL << NVDEV_ENGINE_SW) | (1ULL << NVDEV_ENGINE_SW) |
(1ULL << NVDEV_ENGINE_GR) | (1ULL << NVDEV_ENGINE_GR) |
...@@ -200,14 +208,16 @@ nv40_fifo_chan_ctor(struct nouveau_object *parent, ...@@ -200,14 +208,16 @@ nv40_fifo_chan_ctor(struct nouveau_object *parent,
if (ret) if (ret)
return ret; return ret;
args->v0.chid = chan->base.chid;
nv_parent(chan)->context_attach = nv40_fifo_context_attach; nv_parent(chan)->context_attach = nv40_fifo_context_attach;
nv_parent(chan)->context_detach = nv40_fifo_context_detach; nv_parent(chan)->context_detach = nv40_fifo_context_detach;
nv_parent(chan)->object_attach = nv40_fifo_object_attach; nv_parent(chan)->object_attach = nv40_fifo_object_attach;
nv_parent(chan)->object_detach = nv04_fifo_object_detach; nv_parent(chan)->object_detach = nv04_fifo_object_detach;
chan->ramfc = chan->base.chid * 128; chan->ramfc = chan->base.chid * 128;
nv_wo32(priv->ramfc, chan->ramfc + 0x00, args->offset); nv_wo32(priv->ramfc, chan->ramfc + 0x00, args->v0.offset);
nv_wo32(priv->ramfc, chan->ramfc + 0x04, args->offset); nv_wo32(priv->ramfc, chan->ramfc + 0x04, args->v0.offset);
nv_wo32(priv->ramfc, chan->ramfc + 0x0c, chan->base.pushgpu->addr >> 4); nv_wo32(priv->ramfc, chan->ramfc + 0x0c, chan->base.pushgpu->addr >> 4);
nv_wo32(priv->ramfc, chan->ramfc + 0x18, 0x30000000 | nv_wo32(priv->ramfc, chan->ramfc + 0x18, 0x30000000 |
NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES | NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES |
...@@ -232,7 +242,7 @@ nv40_fifo_ofuncs = { ...@@ -232,7 +242,7 @@ nv40_fifo_ofuncs = {
static struct nouveau_oclass static struct nouveau_oclass
nv40_fifo_sclass[] = { nv40_fifo_sclass[] = {
{ NV40_CHANNEL_DMA_CLASS, &nv40_fifo_ofuncs }, { NV40_CHANNEL_DMA, &nv40_fifo_ofuncs },
{} {}
}; };
......
...@@ -25,7 +25,8 @@ ...@@ -25,7 +25,8 @@
#include <core/client.h> #include <core/client.h>
#include <core/engctx.h> #include <core/engctx.h>
#include <core/ramht.h> #include <core/ramht.h>
#include <core/class.h> #include <nvif/unpack.h>
#include <nvif/class.h>
#include <subdev/timer.h> #include <subdev/timer.h>
#include <subdev/bar.h> #include <subdev/bar.h>
...@@ -194,17 +195,24 @@ nv50_fifo_chan_ctor_dma(struct nouveau_object *parent, ...@@ -194,17 +195,24 @@ nv50_fifo_chan_ctor_dma(struct nouveau_object *parent,
struct nouveau_oclass *oclass, void *data, u32 size, struct nouveau_oclass *oclass, void *data, u32 size,
struct nouveau_object **pobject) struct nouveau_object **pobject)
{ {
union {
struct nv03_channel_dma_v0 v0;
} *args = data;
struct nouveau_bar *bar = nouveau_bar(parent); struct nouveau_bar *bar = nouveau_bar(parent);
struct nv50_fifo_base *base = (void *)parent; struct nv50_fifo_base *base = (void *)parent;
struct nv50_fifo_chan *chan; struct nv50_fifo_chan *chan;
struct nv03_channel_dma_class *args = data;
int ret; int ret;
if (size < sizeof(*args)) nv_ioctl(parent, "create channel dma size %d\n", size);
return -EINVAL; if (nvif_unpack(args->v0, 0, 0, false)) {
nv_ioctl(parent, "create channel dma vers %d pushbuf %08x "
"offset %016llx\n", args->v0.version,
args->v0.pushbuf, args->v0.offset);
} else
return ret;
ret = nouveau_fifo_channel_create(parent, engine, oclass, 0, 0xc00000, ret = nouveau_fifo_channel_create(parent, engine, oclass, 0, 0xc00000,
0x2000, args->pushbuf, 0x2000, args->v0.pushbuf,
(1ULL << NVDEV_ENGINE_DMAOBJ) | (1ULL << NVDEV_ENGINE_DMAOBJ) |
(1ULL << NVDEV_ENGINE_SW) | (1ULL << NVDEV_ENGINE_SW) |
(1ULL << NVDEV_ENGINE_GR) | (1ULL << NVDEV_ENGINE_GR) |
...@@ -213,6 +221,8 @@ nv50_fifo_chan_ctor_dma(struct nouveau_object *parent, ...@@ -213,6 +221,8 @@ nv50_fifo_chan_ctor_dma(struct nouveau_object *parent,
if (ret) if (ret)
return ret; return ret;
args->v0.chid = chan->base.chid;
nv_parent(chan)->context_attach = nv50_fifo_context_attach; nv_parent(chan)->context_attach = nv50_fifo_context_attach;
nv_parent(chan)->context_detach = nv50_fifo_context_detach; nv_parent(chan)->context_detach = nv50_fifo_context_detach;
nv_parent(chan)->object_attach = nv50_fifo_object_attach; nv_parent(chan)->object_attach = nv50_fifo_object_attach;
...@@ -223,10 +233,10 @@ nv50_fifo_chan_ctor_dma(struct nouveau_object *parent, ...@@ -223,10 +233,10 @@ nv50_fifo_chan_ctor_dma(struct nouveau_object *parent,
if (ret) if (ret)
return ret; return ret;
nv_wo32(base->ramfc, 0x08, lower_32_bits(args->offset)); nv_wo32(base->ramfc, 0x08, lower_32_bits(args->v0.offset));
nv_wo32(base->ramfc, 0x0c, upper_32_bits(args->offset)); nv_wo32(base->ramfc, 0x0c, upper_32_bits(args->v0.offset));
nv_wo32(base->ramfc, 0x10, lower_32_bits(args->offset)); nv_wo32(base->ramfc, 0x10, lower_32_bits(args->v0.offset));
nv_wo32(base->ramfc, 0x14, upper_32_bits(args->offset)); nv_wo32(base->ramfc, 0x14, upper_32_bits(args->v0.offset));
nv_wo32(base->ramfc, 0x3c, 0x003f6078); nv_wo32(base->ramfc, 0x3c, 0x003f6078);
nv_wo32(base->ramfc, 0x44, 0x01003fff); nv_wo32(base->ramfc, 0x44, 0x01003fff);
nv_wo32(base->ramfc, 0x48, chan->base.pushgpu->node->offset >> 4); nv_wo32(base->ramfc, 0x48, chan->base.pushgpu->node->offset >> 4);
...@@ -247,18 +257,26 @@ nv50_fifo_chan_ctor_ind(struct nouveau_object *parent, ...@@ -247,18 +257,26 @@ nv50_fifo_chan_ctor_ind(struct nouveau_object *parent,
struct nouveau_oclass *oclass, void *data, u32 size, struct nouveau_oclass *oclass, void *data, u32 size,
struct nouveau_object **pobject) struct nouveau_object **pobject)
{ {
struct nv50_channel_ind_class *args = data; union {
struct nv50_channel_gpfifo_v0 v0;
} *args = data;
struct nouveau_bar *bar = nouveau_bar(parent); struct nouveau_bar *bar = nouveau_bar(parent);
struct nv50_fifo_base *base = (void *)parent; struct nv50_fifo_base *base = (void *)parent;
struct nv50_fifo_chan *chan; struct nv50_fifo_chan *chan;
u64 ioffset, ilength; u64 ioffset, ilength;
int ret; int ret;
if (size < sizeof(*args)) nv_ioctl(parent, "create channel gpfifo size %d\n", size);
return -EINVAL; if (nvif_unpack(args->v0, 0, 0, false)) {
nv_ioctl(parent, "create channel gpfifo vers %d pushbuf %08x "
"ioffset %016llx ilength %08x\n",
args->v0.version, args->v0.pushbuf, args->v0.ioffset,
args->v0.ilength);
} else
return ret;
ret = nouveau_fifo_channel_create(parent, engine, oclass, 0, 0xc00000, ret = nouveau_fifo_channel_create(parent, engine, oclass, 0, 0xc00000,
0x2000, args->pushbuf, 0x2000, args->v0.pushbuf,
(1ULL << NVDEV_ENGINE_DMAOBJ) | (1ULL << NVDEV_ENGINE_DMAOBJ) |
(1ULL << NVDEV_ENGINE_SW) | (1ULL << NVDEV_ENGINE_SW) |
(1ULL << NVDEV_ENGINE_GR) | (1ULL << NVDEV_ENGINE_GR) |
...@@ -267,6 +285,8 @@ nv50_fifo_chan_ctor_ind(struct nouveau_object *parent, ...@@ -267,6 +285,8 @@ nv50_fifo_chan_ctor_ind(struct nouveau_object *parent,
if (ret) if (ret)
return ret; return ret;
args->v0.chid = chan->base.chid;
nv_parent(chan)->context_attach = nv50_fifo_context_attach; nv_parent(chan)->context_attach = nv50_fifo_context_attach;
nv_parent(chan)->context_detach = nv50_fifo_context_detach; nv_parent(chan)->context_detach = nv50_fifo_context_detach;
nv_parent(chan)->object_attach = nv50_fifo_object_attach; nv_parent(chan)->object_attach = nv50_fifo_object_attach;
...@@ -277,8 +297,8 @@ nv50_fifo_chan_ctor_ind(struct nouveau_object *parent, ...@@ -277,8 +297,8 @@ nv50_fifo_chan_ctor_ind(struct nouveau_object *parent,
if (ret) if (ret)
return ret; return ret;
ioffset = args->ioffset; ioffset = args->v0.ioffset;
ilength = order_base_2(args->ilength / 8); ilength = order_base_2(args->v0.ilength / 8);
nv_wo32(base->ramfc, 0x3c, 0x403f6078); nv_wo32(base->ramfc, 0x3c, 0x403f6078);
nv_wo32(base->ramfc, 0x44, 0x01003fff); nv_wo32(base->ramfc, 0x44, 0x01003fff);
...@@ -359,8 +379,8 @@ nv50_fifo_ofuncs_ind = { ...@@ -359,8 +379,8 @@ nv50_fifo_ofuncs_ind = {
static struct nouveau_oclass static struct nouveau_oclass
nv50_fifo_sclass[] = { nv50_fifo_sclass[] = {
{ NV50_CHANNEL_DMA_CLASS, &nv50_fifo_ofuncs_dma }, { NV50_CHANNEL_DMA, &nv50_fifo_ofuncs_dma },
{ NV50_CHANNEL_IND_CLASS, &nv50_fifo_ofuncs_ind }, { NV50_CHANNEL_GPFIFO, &nv50_fifo_ofuncs_ind },
{} {}
}; };
......
...@@ -27,7 +27,8 @@ ...@@ -27,7 +27,8 @@
#include <core/engctx.h> #include <core/engctx.h>
#include <core/ramht.h> #include <core/ramht.h>
#include <core/event.h> #include <core/event.h>
#include <core/class.h> #include <nvif/unpack.h>
#include <nvif/class.h>
#include <subdev/timer.h> #include <subdev/timer.h>
#include <subdev/bar.h> #include <subdev/bar.h>
...@@ -160,17 +161,24 @@ nv84_fifo_chan_ctor_dma(struct nouveau_object *parent, ...@@ -160,17 +161,24 @@ nv84_fifo_chan_ctor_dma(struct nouveau_object *parent,
struct nouveau_oclass *oclass, void *data, u32 size, struct nouveau_oclass *oclass, void *data, u32 size,
struct nouveau_object **pobject) struct nouveau_object **pobject)
{ {
union {
struct nv03_channel_dma_v0 v0;
} *args = data;
struct nouveau_bar *bar = nouveau_bar(parent); struct nouveau_bar *bar = nouveau_bar(parent);
struct nv50_fifo_base *base = (void *)parent; struct nv50_fifo_base *base = (void *)parent;
struct nv50_fifo_chan *chan; struct nv50_fifo_chan *chan;
struct nv03_channel_dma_class *args = data;
int ret; int ret;
if (size < sizeof(*args)) nv_ioctl(parent, "create channel dma size %d\n", size);
return -EINVAL; if (nvif_unpack(args->v0, 0, 0, false)) {
nv_ioctl(parent, "create channel dma vers %d pushbuf %08x "
"offset %016llx\n", args->v0.version,
args->v0.pushbuf, args->v0.offset);
} else
return ret;
ret = nouveau_fifo_channel_create(parent, engine, oclass, 0, 0xc00000, ret = nouveau_fifo_channel_create(parent, engine, oclass, 0, 0xc00000,
0x2000, args->pushbuf, 0x2000, args->v0.pushbuf,
(1ULL << NVDEV_ENGINE_DMAOBJ) | (1ULL << NVDEV_ENGINE_DMAOBJ) |
(1ULL << NVDEV_ENGINE_SW) | (1ULL << NVDEV_ENGINE_SW) |
(1ULL << NVDEV_ENGINE_GR) | (1ULL << NVDEV_ENGINE_GR) |
...@@ -186,6 +194,8 @@ nv84_fifo_chan_ctor_dma(struct nouveau_object *parent, ...@@ -186,6 +194,8 @@ nv84_fifo_chan_ctor_dma(struct nouveau_object *parent,
if (ret) if (ret)
return ret; return ret;
args->v0.chid = chan->base.chid;
ret = nouveau_ramht_new(nv_object(chan), nv_object(chan), 0x8000, 16, ret = nouveau_ramht_new(nv_object(chan), nv_object(chan), 0x8000, 16,
&chan->ramht); &chan->ramht);
if (ret) if (ret)
...@@ -196,10 +206,10 @@ nv84_fifo_chan_ctor_dma(struct nouveau_object *parent, ...@@ -196,10 +206,10 @@ nv84_fifo_chan_ctor_dma(struct nouveau_object *parent,
nv_parent(chan)->object_attach = nv84_fifo_object_attach; nv_parent(chan)->object_attach = nv84_fifo_object_attach;
nv_parent(chan)->object_detach = nv50_fifo_object_detach; nv_parent(chan)->object_detach = nv50_fifo_object_detach;
nv_wo32(base->ramfc, 0x08, lower_32_bits(args->offset)); nv_wo32(base->ramfc, 0x08, lower_32_bits(args->v0.offset));
nv_wo32(base->ramfc, 0x0c, upper_32_bits(args->offset)); nv_wo32(base->ramfc, 0x0c, upper_32_bits(args->v0.offset));
nv_wo32(base->ramfc, 0x10, lower_32_bits(args->offset)); nv_wo32(base->ramfc, 0x10, lower_32_bits(args->v0.offset));
nv_wo32(base->ramfc, 0x14, upper_32_bits(args->offset)); nv_wo32(base->ramfc, 0x14, upper_32_bits(args->v0.offset));
nv_wo32(base->ramfc, 0x3c, 0x003f6078); nv_wo32(base->ramfc, 0x3c, 0x003f6078);
nv_wo32(base->ramfc, 0x44, 0x01003fff); nv_wo32(base->ramfc, 0x44, 0x01003fff);
nv_wo32(base->ramfc, 0x48, chan->base.pushgpu->node->offset >> 4); nv_wo32(base->ramfc, 0x48, chan->base.pushgpu->node->offset >> 4);
...@@ -222,18 +232,26 @@ nv84_fifo_chan_ctor_ind(struct nouveau_object *parent, ...@@ -222,18 +232,26 @@ nv84_fifo_chan_ctor_ind(struct nouveau_object *parent,
struct nouveau_oclass *oclass, void *data, u32 size, struct nouveau_oclass *oclass, void *data, u32 size,
struct nouveau_object **pobject) struct nouveau_object **pobject)
{ {
union {
struct nv50_channel_gpfifo_v0 v0;
} *args = data;
struct nouveau_bar *bar = nouveau_bar(parent); struct nouveau_bar *bar = nouveau_bar(parent);
struct nv50_fifo_base *base = (void *)parent; struct nv50_fifo_base *base = (void *)parent;
struct nv50_fifo_chan *chan; struct nv50_fifo_chan *chan;
struct nv50_channel_ind_class *args = data;
u64 ioffset, ilength; u64 ioffset, ilength;
int ret; int ret;
if (size < sizeof(*args)) nv_ioctl(parent, "create channel gpfifo size %d\n", size);
return -EINVAL; if (nvif_unpack(args->v0, 0, 0, false)) {
nv_ioctl(parent, "create channel gpfifo vers %d pushbuf %08x "
"ioffset %016llx ilength %08x\n",
args->v0.version, args->v0.pushbuf, args->v0.ioffset,
args->v0.ilength);
} else
return ret;
ret = nouveau_fifo_channel_create(parent, engine, oclass, 0, 0xc00000, ret = nouveau_fifo_channel_create(parent, engine, oclass, 0, 0xc00000,
0x2000, args->pushbuf, 0x2000, args->v0.pushbuf,
(1ULL << NVDEV_ENGINE_DMAOBJ) | (1ULL << NVDEV_ENGINE_DMAOBJ) |
(1ULL << NVDEV_ENGINE_SW) | (1ULL << NVDEV_ENGINE_SW) |
(1ULL << NVDEV_ENGINE_GR) | (1ULL << NVDEV_ENGINE_GR) |
...@@ -249,6 +267,8 @@ nv84_fifo_chan_ctor_ind(struct nouveau_object *parent, ...@@ -249,6 +267,8 @@ nv84_fifo_chan_ctor_ind(struct nouveau_object *parent,
if (ret) if (ret)
return ret; return ret;
args->v0.chid = chan->base.chid;
ret = nouveau_ramht_new(nv_object(chan), nv_object(chan), 0x8000, 16, ret = nouveau_ramht_new(nv_object(chan), nv_object(chan), 0x8000, 16,
&chan->ramht); &chan->ramht);
if (ret) if (ret)
...@@ -259,8 +279,8 @@ nv84_fifo_chan_ctor_ind(struct nouveau_object *parent, ...@@ -259,8 +279,8 @@ nv84_fifo_chan_ctor_ind(struct nouveau_object *parent,
nv_parent(chan)->object_attach = nv84_fifo_object_attach; nv_parent(chan)->object_attach = nv84_fifo_object_attach;
nv_parent(chan)->object_detach = nv50_fifo_object_detach; nv_parent(chan)->object_detach = nv50_fifo_object_detach;
ioffset = args->ioffset; ioffset = args->v0.ioffset;
ilength = order_base_2(args->ilength / 8); ilength = order_base_2(args->v0.ilength / 8);
nv_wo32(base->ramfc, 0x3c, 0x403f6078); nv_wo32(base->ramfc, 0x3c, 0x403f6078);
nv_wo32(base->ramfc, 0x44, 0x01003fff); nv_wo32(base->ramfc, 0x44, 0x01003fff);
...@@ -320,8 +340,8 @@ nv84_fifo_ofuncs_ind = { ...@@ -320,8 +340,8 @@ nv84_fifo_ofuncs_ind = {
static struct nouveau_oclass static struct nouveau_oclass
nv84_fifo_sclass[] = { nv84_fifo_sclass[] = {
{ NV84_CHANNEL_DMA_CLASS, &nv84_fifo_ofuncs_dma }, { G82_CHANNEL_DMA, &nv84_fifo_ofuncs_dma },
{ NV84_CHANNEL_IND_CLASS, &nv84_fifo_ofuncs_ind }, { G82_CHANNEL_GPFIFO, &nv84_fifo_ofuncs_ind },
{} {}
}; };
......
...@@ -28,7 +28,8 @@ ...@@ -28,7 +28,8 @@
#include <core/gpuobj.h> #include <core/gpuobj.h>
#include <core/engctx.h> #include <core/engctx.h>
#include <core/event.h> #include <core/event.h>
#include <core/class.h> #include <nvif/unpack.h>
#include <nvif/class.h>
#include <core/enum.h> #include <core/enum.h>
#include <subdev/timer.h> #include <subdev/timer.h>
...@@ -187,20 +188,28 @@ nvc0_fifo_chan_ctor(struct nouveau_object *parent, ...@@ -187,20 +188,28 @@ nvc0_fifo_chan_ctor(struct nouveau_object *parent,
struct nouveau_oclass *oclass, void *data, u32 size, struct nouveau_oclass *oclass, void *data, u32 size,
struct nouveau_object **pobject) struct nouveau_object **pobject)
{ {
union {
struct nv50_channel_gpfifo_v0 v0;
} *args = data;
struct nouveau_bar *bar = nouveau_bar(parent); struct nouveau_bar *bar = nouveau_bar(parent);
struct nvc0_fifo_priv *priv = (void *)engine; struct nvc0_fifo_priv *priv = (void *)engine;
struct nvc0_fifo_base *base = (void *)parent; struct nvc0_fifo_base *base = (void *)parent;
struct nvc0_fifo_chan *chan; struct nvc0_fifo_chan *chan;
struct nv50_channel_ind_class *args = data;
u64 usermem, ioffset, ilength; u64 usermem, ioffset, ilength;
int ret, i; int ret, i;
if (size < sizeof(*args)) nv_ioctl(parent, "create channel gpfifo size %d\n", size);
return -EINVAL; if (nvif_unpack(args->v0, 0, 0, false)) {
nv_ioctl(parent, "create channel gpfifo vers %d pushbuf %08x "
"ioffset %016llx ilength %08x\n",
args->v0.version, args->v0.pushbuf, args->v0.ioffset,
args->v0.ilength);
} else
return ret;
ret = nouveau_fifo_channel_create(parent, engine, oclass, 1, ret = nouveau_fifo_channel_create(parent, engine, oclass, 1,
priv->user.bar.offset, 0x1000, priv->user.bar.offset, 0x1000,
args->pushbuf, args->v0.pushbuf,
(1ULL << NVDEV_ENGINE_SW) | (1ULL << NVDEV_ENGINE_SW) |
(1ULL << NVDEV_ENGINE_GR) | (1ULL << NVDEV_ENGINE_GR) |
(1ULL << NVDEV_ENGINE_COPY0) | (1ULL << NVDEV_ENGINE_COPY0) |
...@@ -212,12 +221,14 @@ nvc0_fifo_chan_ctor(struct nouveau_object *parent, ...@@ -212,12 +221,14 @@ nvc0_fifo_chan_ctor(struct nouveau_object *parent,
if (ret) if (ret)
return ret; return ret;
args->v0.chid = chan->base.chid;
nv_parent(chan)->context_attach = nvc0_fifo_context_attach; nv_parent(chan)->context_attach = nvc0_fifo_context_attach;
nv_parent(chan)->context_detach = nvc0_fifo_context_detach; nv_parent(chan)->context_detach = nvc0_fifo_context_detach;
usermem = chan->base.chid * 0x1000; usermem = chan->base.chid * 0x1000;
ioffset = args->ioffset; ioffset = args->v0.ioffset;
ilength = order_base_2(args->ilength / 8); ilength = order_base_2(args->v0.ilength / 8);
for (i = 0; i < 0x1000; i += 4) for (i = 0; i < 0x1000; i += 4)
nv_wo32(priv->user.mem, usermem + i, 0x00000000); nv_wo32(priv->user.mem, usermem + i, 0x00000000);
...@@ -297,7 +308,7 @@ nvc0_fifo_ofuncs = { ...@@ -297,7 +308,7 @@ nvc0_fifo_ofuncs = {
static struct nouveau_oclass static struct nouveau_oclass
nvc0_fifo_sclass[] = { nvc0_fifo_sclass[] = {
{ NVC0_CHANNEL_IND_CLASS, &nvc0_fifo_ofuncs }, { FERMI_CHANNEL_GPFIFO, &nvc0_fifo_ofuncs },
{} {}
}; };
...@@ -654,7 +665,7 @@ nvc0_fifo_intr_fault(struct nvc0_fifo_priv *priv, int unit) ...@@ -654,7 +665,7 @@ nvc0_fifo_intr_fault(struct nvc0_fifo_priv *priv, int unit)
object = engctx; object = engctx;
while (object) { while (object) {
switch (nv_mclass(object)) { switch (nv_mclass(object)) {
case NVC0_CHANNEL_IND_CLASS: case FERMI_CHANNEL_GPFIFO:
nvc0_fifo_recover(priv, engine, (void *)object); nvc0_fifo_recover(priv, engine, (void *)object);
break; break;
} }
......
...@@ -28,7 +28,8 @@ ...@@ -28,7 +28,8 @@
#include <core/gpuobj.h> #include <core/gpuobj.h>
#include <core/engctx.h> #include <core/engctx.h>
#include <core/event.h> #include <core/event.h>
#include <core/class.h> #include <nvif/unpack.h>
#include <nvif/class.h>
#include <core/enum.h> #include <core/enum.h>
#include <subdev/timer.h> #include <subdev/timer.h>
...@@ -216,46 +217,56 @@ nve0_fifo_chan_ctor(struct nouveau_object *parent, ...@@ -216,46 +217,56 @@ nve0_fifo_chan_ctor(struct nouveau_object *parent,
struct nouveau_oclass *oclass, void *data, u32 size, struct nouveau_oclass *oclass, void *data, u32 size,
struct nouveau_object **pobject) struct nouveau_object **pobject)
{ {
union {
struct kepler_channel_gpfifo_a_v0 v0;
} *args = data;
struct nouveau_bar *bar = nouveau_bar(parent); struct nouveau_bar *bar = nouveau_bar(parent);
struct nve0_fifo_priv *priv = (void *)engine; struct nve0_fifo_priv *priv = (void *)engine;
struct nve0_fifo_base *base = (void *)parent; struct nve0_fifo_base *base = (void *)parent;
struct nve0_fifo_chan *chan; struct nve0_fifo_chan *chan;
struct nve0_channel_ind_class *args = data;
u64 usermem, ioffset, ilength; u64 usermem, ioffset, ilength;
int ret, i; int ret, i;
if (size < sizeof(*args)) nv_ioctl(parent, "create channel gpfifo size %d\n", size);
return -EINVAL; if (nvif_unpack(args->v0, 0, 0, false)) {
nv_ioctl(parent, "create channel gpfifo vers %d pushbuf %08x "
"ioffset %016llx ilength %08x engine %08x\n",
args->v0.version, args->v0.pushbuf, args->v0.ioffset,
args->v0.ilength, args->v0.engine);
} else
return ret;
for (i = 0; i < FIFO_ENGINE_NR; i++) { for (i = 0; i < FIFO_ENGINE_NR; i++) {
if (args->engine & (1 << i)) { if (args->v0.engine & (1 << i)) {
if (nouveau_engine(parent, fifo_engine[i].subdev)) { if (nouveau_engine(parent, fifo_engine[i].subdev)) {
args->engine = (1 << i); args->v0.engine = (1 << i);
break; break;
} }
} }
} }
if (i == FIFO_ENGINE_NR) { if (i == FIFO_ENGINE_NR) {
nv_error(priv, "unsupported engines 0x%08x\n", args->engine); nv_error(priv, "unsupported engines 0x%08x\n", args->v0.engine);
return -ENODEV; return -ENODEV;
} }
ret = nouveau_fifo_channel_create(parent, engine, oclass, 1, ret = nouveau_fifo_channel_create(parent, engine, oclass, 1,
priv->user.bar.offset, 0x200, priv->user.bar.offset, 0x200,
args->pushbuf, args->v0.pushbuf,
fifo_engine[i].mask, &chan); fifo_engine[i].mask, &chan);
*pobject = nv_object(chan); *pobject = nv_object(chan);
if (ret) if (ret)
return ret; return ret;
args->v0.chid = chan->base.chid;
nv_parent(chan)->context_attach = nve0_fifo_context_attach; nv_parent(chan)->context_attach = nve0_fifo_context_attach;
nv_parent(chan)->context_detach = nve0_fifo_context_detach; nv_parent(chan)->context_detach = nve0_fifo_context_detach;
chan->engine = i; chan->engine = i;
usermem = chan->base.chid * 0x200; usermem = chan->base.chid * 0x200;
ioffset = args->ioffset; ioffset = args->v0.ioffset;
ilength = order_base_2(args->ilength / 8); ilength = order_base_2(args->v0.ilength / 8);
for (i = 0; i < 0x200; i += 4) for (i = 0; i < 0x200; i += 4)
nv_wo32(priv->user.mem, usermem + i, 0x00000000); nv_wo32(priv->user.mem, usermem + i, 0x00000000);
...@@ -331,7 +342,7 @@ nve0_fifo_ofuncs = { ...@@ -331,7 +342,7 @@ nve0_fifo_ofuncs = {
static struct nouveau_oclass static struct nouveau_oclass
nve0_fifo_sclass[] = { nve0_fifo_sclass[] = {
{ NVE0_CHANNEL_IND_CLASS, &nve0_fifo_ofuncs }, { KEPLER_CHANNEL_GPFIFO_A, &nve0_fifo_ofuncs },
{} {}
}; };
...@@ -769,7 +780,7 @@ nve0_fifo_intr_fault(struct nve0_fifo_priv *priv, int unit) ...@@ -769,7 +780,7 @@ nve0_fifo_intr_fault(struct nve0_fifo_priv *priv, int unit)
object = engctx; object = engctx;
while (object) { while (object) {
switch (nv_mclass(object)) { switch (nv_mclass(object)) {
case NVE0_CHANNEL_IND_CLASS: case KEPLER_CHANNEL_GPFIFO_A:
nve0_fifo_recover(priv, engine, (void *)object); nve0_fifo_recover(priv, engine, (void *)object);
break; break;
} }
......
...@@ -3,62 +3,6 @@ ...@@ -3,62 +3,6 @@
#include <nvif/class.h> #include <nvif/class.h>
/* DMA FIFO channel classes
*
* 006b: NV03_CHANNEL_DMA
* 006e: NV10_CHANNEL_DMA
* 176e: NV17_CHANNEL_DMA
* 406e: NV40_CHANNEL_DMA
* 506e: NV50_CHANNEL_DMA
* 826e: NV84_CHANNEL_DMA
*/
#define NV03_CHANNEL_DMA_CLASS 0x0000006b
#define NV10_CHANNEL_DMA_CLASS 0x0000006e
#define NV17_CHANNEL_DMA_CLASS 0x0000176e
#define NV40_CHANNEL_DMA_CLASS 0x0000406e
#define NV50_CHANNEL_DMA_CLASS 0x0000506e
#define NV84_CHANNEL_DMA_CLASS 0x0000826e
struct nv03_channel_dma_class {
u32 pushbuf;
u32 pad0;
u64 offset;
};
/* Indirect FIFO channel classes
*
* 506f: NV50_CHANNEL_IND
* 826f: NV84_CHANNEL_IND
* 906f: NVC0_CHANNEL_IND
* a06f: NVE0_CHANNEL_IND
*/
#define NV50_CHANNEL_IND_CLASS 0x0000506f
#define NV84_CHANNEL_IND_CLASS 0x0000826f
#define NVC0_CHANNEL_IND_CLASS 0x0000906f
#define NVE0_CHANNEL_IND_CLASS 0x0000a06f
struct nv50_channel_ind_class {
u32 pushbuf;
u32 ilength;
u64 ioffset;
};
#define NVE0_CHANNEL_IND_ENGINE_GR 0x00000001
#define NVE0_CHANNEL_IND_ENGINE_VP 0x00000002
#define NVE0_CHANNEL_IND_ENGINE_PPP 0x00000004
#define NVE0_CHANNEL_IND_ENGINE_BSP 0x00000008
#define NVE0_CHANNEL_IND_ENGINE_CE0 0x00000010
#define NVE0_CHANNEL_IND_ENGINE_CE1 0x00000020
#define NVE0_CHANNEL_IND_ENGINE_ENC 0x00000040
struct nve0_channel_ind_class {
u32 pushbuf;
u32 ilength;
u64 ioffset;
u32 engine;
};
/* 0046: NV04_DISP /* 0046: NV04_DISP
*/ */
......
...@@ -257,13 +257,13 @@ nouveau_abi16_ioctl_channel_alloc(ABI16_IOCTL_ARGS) ...@@ -257,13 +257,13 @@ nouveau_abi16_ioctl_channel_alloc(ABI16_IOCTL_ARGS)
/* hack to allow channel engine type specification on kepler */ /* hack to allow channel engine type specification on kepler */
if (device->info.family >= NV_DEVICE_INFO_V0_KEPLER) { if (device->info.family >= NV_DEVICE_INFO_V0_KEPLER) {
if (init->fb_ctxdma_handle != ~0) if (init->fb_ctxdma_handle != ~0)
init->fb_ctxdma_handle = NVE0_CHANNEL_IND_ENGINE_GR; init->fb_ctxdma_handle = KEPLER_CHANNEL_GPFIFO_A_V0_ENGINE_GR;
else else
init->fb_ctxdma_handle = init->tt_ctxdma_handle; init->fb_ctxdma_handle = init->tt_ctxdma_handle;
/* allow flips to be executed if this is a graphics channel */ /* allow flips to be executed if this is a graphics channel */
init->tt_ctxdma_handle = 0; init->tt_ctxdma_handle = 0;
if (init->fb_ctxdma_handle == NVE0_CHANNEL_IND_ENGINE_GR) if (init->fb_ctxdma_handle == KEPLER_CHANNEL_GPFIFO_A_V0_ENGINE_GR)
init->tt_ctxdma_handle = 1; init->tt_ctxdma_handle = 1;
} }
......
...@@ -187,14 +187,18 @@ static int ...@@ -187,14 +187,18 @@ static int
nouveau_channel_ind(struct nouveau_drm *drm, struct nvif_device *device, nouveau_channel_ind(struct nouveau_drm *drm, struct nvif_device *device,
u32 handle, u32 engine, struct nouveau_channel **pchan) u32 handle, u32 engine, struct nouveau_channel **pchan)
{ {
static const u16 oclasses[] = { NVE0_CHANNEL_IND_CLASS, static const u16 oclasses[] = { KEPLER_CHANNEL_GPFIFO_A,
NVC0_CHANNEL_IND_CLASS, FERMI_CHANNEL_GPFIFO,
NV84_CHANNEL_IND_CLASS, G82_CHANNEL_GPFIFO,
NV50_CHANNEL_IND_CLASS, NV50_CHANNEL_GPFIFO,
0 }; 0 };
const u16 *oclass = oclasses; const u16 *oclass = oclasses;
struct nve0_channel_ind_class args; union {
struct nv50_channel_gpfifo_v0 nv50;
struct kepler_channel_gpfifo_a_v0 kepler;
} args, *retn;
struct nouveau_channel *chan; struct nouveau_channel *chan;
u32 size;
int ret; int ret;
/* allocate dma push buffer */ /* allocate dma push buffer */
...@@ -204,16 +208,32 @@ nouveau_channel_ind(struct nouveau_drm *drm, struct nvif_device *device, ...@@ -204,16 +208,32 @@ nouveau_channel_ind(struct nouveau_drm *drm, struct nvif_device *device,
return ret; return ret;
/* create channel object */ /* create channel object */
args.pushbuf = chan->push.ctxdma.handle;
args.ioffset = 0x10000 + chan->push.vma.offset;
args.ilength = 0x02000;
args.engine = engine;
do { do {
if (oclass[0] >= KEPLER_CHANNEL_GPFIFO_A) {
args.kepler.version = 0;
args.kepler.engine = engine;
args.kepler.pushbuf = chan->push.ctxdma.handle;
args.kepler.ilength = 0x02000;
args.kepler.ioffset = 0x10000 + chan->push.vma.offset;
size = sizeof(args.kepler);
} else {
args.nv50.version = 0;
args.nv50.pushbuf = chan->push.ctxdma.handle;
args.nv50.ilength = 0x02000;
args.nv50.ioffset = 0x10000 + chan->push.vma.offset;
size = sizeof(args.nv50);
}
ret = nvif_object_new(nvif_object(device), handle, *oclass++, ret = nvif_object_new(nvif_object(device), handle, *oclass++,
&args, sizeof(args), &chan->object); &args, size, &chan->object);
if (ret == 0) if (ret == 0) {
retn = chan->object->data;
if (chan->object->oclass >= KEPLER_CHANNEL_GPFIFO_A)
chan->chid = retn->kepler.chid;
else
chan->chid = retn->nv50.chid;
return ret; return ret;
}
} while (*oclass); } while (*oclass);
nouveau_channel_del(pchan); nouveau_channel_del(pchan);
...@@ -224,13 +244,13 @@ static int ...@@ -224,13 +244,13 @@ static int
nouveau_channel_dma(struct nouveau_drm *drm, struct nvif_device *device, nouveau_channel_dma(struct nouveau_drm *drm, struct nvif_device *device,
u32 handle, struct nouveau_channel **pchan) u32 handle, struct nouveau_channel **pchan)
{ {
static const u16 oclasses[] = { NV40_CHANNEL_DMA_CLASS, static const u16 oclasses[] = { NV40_CHANNEL_DMA,
NV17_CHANNEL_DMA_CLASS, NV17_CHANNEL_DMA,
NV10_CHANNEL_DMA_CLASS, NV10_CHANNEL_DMA,
NV03_CHANNEL_DMA_CLASS, NV03_CHANNEL_DMA,
0 }; 0 };
const u16 *oclass = oclasses; const u16 *oclass = oclasses;
struct nv03_channel_dma_class args; struct nv03_channel_dma_v0 args, *retn;
struct nouveau_channel *chan; struct nouveau_channel *chan;
int ret; int ret;
...@@ -241,14 +261,18 @@ nouveau_channel_dma(struct nouveau_drm *drm, struct nvif_device *device, ...@@ -241,14 +261,18 @@ nouveau_channel_dma(struct nouveau_drm *drm, struct nvif_device *device,
return ret; return ret;
/* create channel object */ /* create channel object */
args.version = 0;
args.pushbuf = chan->push.ctxdma.handle; args.pushbuf = chan->push.ctxdma.handle;
args.offset = chan->push.vma.offset; args.offset = chan->push.vma.offset;
do { do {
ret = nvif_object_new(nvif_object(device), handle, *oclass++, ret = nvif_object_new(nvif_object(device), handle, *oclass++,
&args, sizeof(args), &chan->object); &args, sizeof(args), &chan->object);
if (ret == 0) if (ret == 0) {
retn = chan->object->data;
chan->chid = retn->chid;
return ret; return ret;
}
} while (ret && *oclass); } while (ret && *oclass);
nouveau_channel_del(pchan); nouveau_channel_del(pchan);
......
...@@ -8,6 +8,8 @@ struct nouveau_channel { ...@@ -8,6 +8,8 @@ struct nouveau_channel {
struct nvif_device *device; struct nvif_device *device;
struct nouveau_drm *drm; struct nouveau_drm *drm;
int chid;
struct nvif_object vram; struct nvif_object vram;
struct nvif_object gart; struct nvif_object gart;
struct nvif_object nvsw; struct nvif_object nvsw;
......
...@@ -156,24 +156,24 @@ nouveau_accel_init(struct nouveau_drm *drm) ...@@ -156,24 +156,24 @@ nouveau_accel_init(struct nouveau_drm *drm)
for (ret = -ENOSYS, i = 0; ret && i < ARRAY_SIZE(sclass); i++) { for (ret = -ENOSYS, i = 0; ret && i < ARRAY_SIZE(sclass); i++) {
switch (sclass[i]) { switch (sclass[i]) {
case NV03_CHANNEL_DMA_CLASS: case NV03_CHANNEL_DMA:
ret = nv04_fence_create(drm); ret = nv04_fence_create(drm);
break; break;
case NV10_CHANNEL_DMA_CLASS: case NV10_CHANNEL_DMA:
ret = nv10_fence_create(drm); ret = nv10_fence_create(drm);
break; break;
case NV17_CHANNEL_DMA_CLASS: case NV17_CHANNEL_DMA:
case NV40_CHANNEL_DMA_CLASS: case NV40_CHANNEL_DMA:
ret = nv17_fence_create(drm); ret = nv17_fence_create(drm);
break; break;
case NV50_CHANNEL_IND_CLASS: case NV50_CHANNEL_GPFIFO:
ret = nv50_fence_create(drm); ret = nv50_fence_create(drm);
break; break;
case NV84_CHANNEL_IND_CLASS: case G82_CHANNEL_GPFIFO:
ret = nv84_fence_create(drm); ret = nv84_fence_create(drm);
break; break;
case NVC0_CHANNEL_IND_CLASS: case FERMI_CHANNEL_GPFIFO:
case NVE0_CHANNEL_IND_CLASS: case KEPLER_CHANNEL_GPFIFO_A:
ret = nvc0_fence_create(drm); ret = nvc0_fence_create(drm);
break; break;
default: default:
...@@ -189,13 +189,13 @@ nouveau_accel_init(struct nouveau_drm *drm) ...@@ -189,13 +189,13 @@ nouveau_accel_init(struct nouveau_drm *drm)
if (device->info.family >= NV_DEVICE_INFO_V0_KEPLER) { if (device->info.family >= NV_DEVICE_INFO_V0_KEPLER) {
ret = nouveau_channel_new(drm, &drm->device, NVDRM_CHAN + 1, ret = nouveau_channel_new(drm, &drm->device, NVDRM_CHAN + 1,
NVE0_CHANNEL_IND_ENGINE_CE0 | KEPLER_CHANNEL_GPFIFO_A_V0_ENGINE_CE0|
NVE0_CHANNEL_IND_ENGINE_CE1, 0, KEPLER_CHANNEL_GPFIFO_A_V0_ENGINE_CE1,
&drm->cechan); 0, &drm->cechan);
if (ret) if (ret)
NV_ERROR(drm, "failed to create ce channel, %d\n", ret); NV_ERROR(drm, "failed to create ce channel, %d\n", ret);
arg0 = NVE0_CHANNEL_IND_ENGINE_GR; arg0 = KEPLER_CHANNEL_GPFIFO_A_V0_ENGINE_GR;
arg1 = 1; arg1 = 1;
} else } else
if (device->info.chipset >= 0xa3 && if (device->info.chipset >= 0xa3 &&
......
...@@ -410,7 +410,7 @@ nv50_display_flip_next(struct drm_crtc *crtc, struct drm_framebuffer *fb, ...@@ -410,7 +410,7 @@ nv50_display_flip_next(struct drm_crtc *crtc, struct drm_framebuffer *fb,
if (unlikely(push == NULL)) if (unlikely(push == NULL))
return -EBUSY; return -EBUSY;
if (chan && chan->object->oclass < NV84_CHANNEL_IND_CLASS) { if (chan && chan->object->oclass < G82_CHANNEL_GPFIFO) {
ret = RING_SPACE(chan, 8); ret = RING_SPACE(chan, 8);
if (ret) if (ret)
return ret; return ret;
...@@ -424,7 +424,7 @@ nv50_display_flip_next(struct drm_crtc *crtc, struct drm_framebuffer *fb, ...@@ -424,7 +424,7 @@ nv50_display_flip_next(struct drm_crtc *crtc, struct drm_framebuffer *fb,
OUT_RING (chan, sync->addr); OUT_RING (chan, sync->addr);
OUT_RING (chan, sync->data); OUT_RING (chan, sync->data);
} else } else
if (chan && chan->object->oclass < NVC0_CHANNEL_IND_CLASS) { if (chan && chan->object->oclass < FERMI_CHANNEL_GPFIFO) {
u64 addr = nv84_fence_crtc(chan, nv_crtc->index) + sync->addr; u64 addr = nv84_fence_crtc(chan, nv_crtc->index) + sync->addr;
ret = RING_SPACE(chan, 12); ret = RING_SPACE(chan, 12);
if (ret) if (ret)
......
...@@ -75,8 +75,7 @@ nv84_fence_emit(struct nouveau_fence *fence) ...@@ -75,8 +75,7 @@ nv84_fence_emit(struct nouveau_fence *fence)
{ {
struct nouveau_channel *chan = fence->channel; struct nouveau_channel *chan = fence->channel;
struct nv84_fence_chan *fctx = chan->fence; struct nv84_fence_chan *fctx = chan->fence;
struct nouveau_fifo_chan *fifo = nvkm_fifo_chan(chan); u64 addr = chan->chid * 16;
u64 addr = fifo->chid * 16;
if (fence->sysmem) if (fence->sysmem)
addr += fctx->vma_gart.offset; addr += fctx->vma_gart.offset;
...@@ -91,8 +90,7 @@ nv84_fence_sync(struct nouveau_fence *fence, ...@@ -91,8 +90,7 @@ nv84_fence_sync(struct nouveau_fence *fence,
struct nouveau_channel *prev, struct nouveau_channel *chan) struct nouveau_channel *prev, struct nouveau_channel *chan)
{ {
struct nv84_fence_chan *fctx = chan->fence; struct nv84_fence_chan *fctx = chan->fence;
struct nouveau_fifo_chan *fifo = nvkm_fifo_chan(prev); u64 addr = prev->chid * 16;
u64 addr = fifo->chid * 16;
if (fence->sysmem) if (fence->sysmem)
addr += fctx->vma_gart.offset; addr += fctx->vma_gart.offset;
...@@ -105,9 +103,8 @@ nv84_fence_sync(struct nouveau_fence *fence, ...@@ -105,9 +103,8 @@ nv84_fence_sync(struct nouveau_fence *fence,
static u32 static u32
nv84_fence_read(struct nouveau_channel *chan) nv84_fence_read(struct nouveau_channel *chan)
{ {
struct nouveau_fifo_chan *fifo = nvkm_fifo_chan(chan);
struct nv84_fence_priv *priv = chan->drm->fence; struct nv84_fence_priv *priv = chan->drm->fence;
return nouveau_bo_rd32(priv->bo, fifo->chid * 16/4); return nouveau_bo_rd32(priv->bo, chan->chid * 16/4);
} }
static void static void
...@@ -133,7 +130,6 @@ nv84_fence_context_del(struct nouveau_channel *chan) ...@@ -133,7 +130,6 @@ nv84_fence_context_del(struct nouveau_channel *chan)
int int
nv84_fence_context_new(struct nouveau_channel *chan) nv84_fence_context_new(struct nouveau_channel *chan)
{ {
struct nouveau_fifo_chan *fifo = nvkm_fifo_chan(chan);
struct nouveau_cli *cli = (void *)nvif_client(&chan->device->base); struct nouveau_cli *cli = (void *)nvif_client(&chan->device->base);
struct nv84_fence_priv *priv = chan->drm->fence; struct nv84_fence_priv *priv = chan->drm->fence;
struct nv84_fence_chan *fctx; struct nv84_fence_chan *fctx;
...@@ -162,7 +158,7 @@ nv84_fence_context_new(struct nouveau_channel *chan) ...@@ -162,7 +158,7 @@ nv84_fence_context_new(struct nouveau_channel *chan)
ret = nouveau_bo_vma_add(bo, cli->vm, &fctx->dispc_vma[i]); ret = nouveau_bo_vma_add(bo, cli->vm, &fctx->dispc_vma[i]);
} }
nouveau_bo_wr32(priv->bo, fifo->chid * 16/4, 0x00000000); nouveau_bo_wr32(priv->bo, chan->chid * 16/4, 0x00000000);
if (ret) if (ret)
nv84_fence_context_del(chan); nv84_fence_context_del(chan);
......
...@@ -12,6 +12,18 @@ ...@@ -12,6 +12,18 @@
#define NV_DMA_TO_MEMORY 0x00000003 #define NV_DMA_TO_MEMORY 0x00000003
#define NV_DMA_IN_MEMORY 0x0000003d #define NV_DMA_IN_MEMORY 0x0000003d
#define NV03_CHANNEL_DMA 0x0000006b
#define NV10_CHANNEL_DMA 0x0000006e
#define NV17_CHANNEL_DMA 0x0000176e
#define NV40_CHANNEL_DMA 0x0000406e
#define NV50_CHANNEL_DMA 0x0000506e
#define G82_CHANNEL_DMA 0x0000826e
#define NV50_CHANNEL_GPFIFO 0x0000506f
#define G82_CHANNEL_GPFIFO 0x0000826f
#define FERMI_CHANNEL_GPFIFO 0x0000906f
#define KEPLER_CHANNEL_GPFIFO_A 0x0000a06f
/******************************************************************************* /*******************************************************************************
* client * client
...@@ -233,4 +245,48 @@ struct nvif_control_pstate_user_v0 { ...@@ -233,4 +245,48 @@ struct nvif_control_pstate_user_v0 {
__u8 pad03[5]; __u8 pad03[5];
}; };
/*******************************************************************************
* DMA FIFO channels
******************************************************************************/
struct nv03_channel_dma_v0 {
__u8 version;
__u8 chid;
__u8 pad02[2];
__u32 pushbuf;
__u64 offset;
};
/*******************************************************************************
* GPFIFO channels
******************************************************************************/
struct nv50_channel_gpfifo_v0 {
__u8 version;
__u8 chid;
__u8 pad01[6];
__u32 pushbuf;
__u32 ilength;
__u64 ioffset;
};
struct kepler_channel_gpfifo_a_v0 {
__u8 version;
#define KEPLER_CHANNEL_GPFIFO_A_V0_ENGINE_GR 0x01
#define KEPLER_CHANNEL_GPFIFO_A_V0_ENGINE_VP 0x02
#define KEPLER_CHANNEL_GPFIFO_A_V0_ENGINE_PPP 0x04
#define KEPLER_CHANNEL_GPFIFO_A_V0_ENGINE_BSP 0x08
#define KEPLER_CHANNEL_GPFIFO_A_V0_ENGINE_CE0 0x10
#define KEPLER_CHANNEL_GPFIFO_A_V0_ENGINE_CE1 0x20
#define KEPLER_CHANNEL_GPFIFO_A_V0_ENGINE_ENC 0x40
__u8 engine;
__u16 chid;
__u8 pad04[4];
__u32 pushbuf;
__u32 ilength;
__u64 ioffset;
};
#endif #endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment