drm/nouveau/fifo/gk104: make use of topology info during gpfifo construction
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
This commit is contained in:
Родитель
19f89279fa
Коммит
1f5ff7f52b
|
@ -3,19 +3,22 @@
|
||||||
|
|
||||||
struct kepler_channel_gpfifo_a_v0 {
|
struct kepler_channel_gpfifo_a_v0 {
|
||||||
__u8 version;
|
__u8 version;
|
||||||
#define KEPLER_CHANNEL_GPFIFO_A_V0_ENGINE_GR 0x01
|
__u8 pad01[5];
|
||||||
#define KEPLER_CHANNEL_GPFIFO_A_V0_ENGINE_MSPDEC 0x02
|
|
||||||
#define KEPLER_CHANNEL_GPFIFO_A_V0_ENGINE_MSPPP 0x04
|
|
||||||
#define KEPLER_CHANNEL_GPFIFO_A_V0_ENGINE_MSVLD 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;
|
__u16 chid;
|
||||||
|
#define NVA06F_V0_ENGINE_SW 0x00000001
|
||||||
|
#define NVA06F_V0_ENGINE_GR 0x00000002
|
||||||
|
#define NVA06F_V0_ENGINE_MSVLD 0x00000010
|
||||||
|
#define NVA06F_V0_ENGINE_MSPDEC 0x00000020
|
||||||
|
#define NVA06F_V0_ENGINE_MSPPP 0x00000040
|
||||||
|
#define NVA06F_V0_ENGINE_MSENC 0x00000080
|
||||||
|
#define NVA06F_V0_ENGINE_CE0 0x00010000
|
||||||
|
#define NVA06F_V0_ENGINE_CE1 0x00020000
|
||||||
|
#define NVA06F_V0_ENGINE_CE2 0x00040000
|
||||||
|
__u32 engines;
|
||||||
__u32 ilength;
|
__u32 ilength;
|
||||||
__u64 ioffset;
|
__u64 ioffset;
|
||||||
__u64 vm;
|
__u64 vm;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define KEPLER_CHANNEL_GPFIFO_A_V0_NTFY_UEVENT 0x00
|
#define NVA06F_V0_NTFY_UEVENT 0x00
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -263,13 +263,23 @@ 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 = KEPLER_CHANNEL_GPFIFO_A_V0_ENGINE_GR;
|
init->fb_ctxdma_handle = NVA06F_V0_ENGINE_GR;
|
||||||
else
|
else {
|
||||||
init->fb_ctxdma_handle = init->tt_ctxdma_handle;
|
init->fb_ctxdma_handle = 0;
|
||||||
|
#define _(A,B) if (init->tt_ctxdma_handle & (A)) init->fb_ctxdma_handle |= (B)
|
||||||
|
_(0x01, NVA06F_V0_ENGINE_GR);
|
||||||
|
_(0x02, NVA06F_V0_ENGINE_MSPDEC);
|
||||||
|
_(0x04, NVA06F_V0_ENGINE_MSPPP);
|
||||||
|
_(0x08, NVA06F_V0_ENGINE_MSVLD);
|
||||||
|
_(0x10, NVA06F_V0_ENGINE_CE0);
|
||||||
|
_(0x20, NVA06F_V0_ENGINE_CE1);
|
||||||
|
_(0x40, NVA06F_V0_ENGINE_MSENC);
|
||||||
|
#undef _
|
||||||
|
}
|
||||||
|
|
||||||
/* 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 == KEPLER_CHANNEL_GPFIFO_A_V0_ENGINE_GR)
|
if (init->fb_ctxdma_handle == NVA06F_V0_ENGINE_GR)
|
||||||
init->tt_ctxdma_handle = 1;
|
init->tt_ctxdma_handle = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -217,7 +217,7 @@ nouveau_channel_ind(struct nouveau_drm *drm, struct nvif_device *device,
|
||||||
do {
|
do {
|
||||||
if (oclass[0] >= KEPLER_CHANNEL_GPFIFO_A) {
|
if (oclass[0] >= KEPLER_CHANNEL_GPFIFO_A) {
|
||||||
args.kepler.version = 0;
|
args.kepler.version = 0;
|
||||||
args.kepler.engine = engine;
|
args.kepler.engines = engine;
|
||||||
args.kepler.ilength = 0x02000;
|
args.kepler.ilength = 0x02000;
|
||||||
args.kepler.ioffset = 0x10000 + chan->push.vma.offset;
|
args.kepler.ioffset = 0x10000 + chan->push.vma.offset;
|
||||||
args.kepler.vm = 0;
|
args.kepler.vm = 0;
|
||||||
|
|
|
@ -215,13 +215,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,
|
ret = nouveau_channel_new(drm, &drm->device,
|
||||||
KEPLER_CHANNEL_GPFIFO_A_V0_ENGINE_CE0|
|
NVA06F_V0_ENGINE_CE0 |
|
||||||
KEPLER_CHANNEL_GPFIFO_A_V0_ENGINE_CE1,
|
NVA06F_V0_ENGINE_CE1,
|
||||||
0, &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 = KEPLER_CHANNEL_GPFIFO_A_V0_ENGINE_GR;
|
arg0 = NVA06F_V0_ENGINE_GR;
|
||||||
arg1 = 1;
|
arg1 = 1;
|
||||||
} else
|
} else
|
||||||
if (device->info.chipset >= 0xa3 &&
|
if (device->info.chipset >= 0xa3 &&
|
||||||
|
|
|
@ -202,73 +202,79 @@ gk104_fifo_gpfifo_func = {
|
||||||
.engine_fini = gk104_fifo_gpfifo_engine_fini,
|
.engine_fini = gk104_fifo_gpfifo_engine_fini,
|
||||||
};
|
};
|
||||||
|
|
||||||
int
|
struct gk104_fifo_chan_func {
|
||||||
gk104_fifo_gpfifo_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass,
|
u32 engine;
|
||||||
void *data, u32 size, struct nvkm_object **pobject)
|
u64 subdev;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int
|
||||||
|
gk104_fifo_gpfifo_new_(const struct gk104_fifo_chan_func *func,
|
||||||
|
struct gk104_fifo *fifo, u32 *engmask, u16 *chid,
|
||||||
|
u64 vm, u64 ioffset, u64 ilength,
|
||||||
|
const struct nvkm_oclass *oclass,
|
||||||
|
struct nvkm_object **pobject)
|
||||||
{
|
{
|
||||||
union {
|
|
||||||
struct kepler_channel_gpfifo_a_v0 v0;
|
|
||||||
} *args = data;
|
|
||||||
struct gk104_fifo *fifo = gk104_fifo(base);
|
|
||||||
struct nvkm_device *device = fifo->base.engine.subdev.device;
|
struct nvkm_device *device = fifo->base.engine.subdev.device;
|
||||||
struct nvkm_object *parent = oclass->parent;
|
|
||||||
struct gk104_fifo_chan *chan;
|
struct gk104_fifo_chan *chan;
|
||||||
u64 usermem, ioffset, ilength;
|
int runlist = -1, ret = -ENOSYS, i, j;
|
||||||
u32 engines;
|
u32 engines = 0, present = 0;
|
||||||
int ret = -ENOSYS, i;
|
u64 subdevs = 0;
|
||||||
|
u64 usermem;
|
||||||
|
|
||||||
nvif_ioctl(parent, "create channel gpfifo size %d\n", size);
|
/* Determine which downstream engines are present */
|
||||||
if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
|
for (i = 0; i < fifo->engine_nr; i++) {
|
||||||
nvif_ioctl(parent, "create channel gpfifo vers %d vm %llx "
|
struct nvkm_engine *engine = fifo->engine[i].engine;
|
||||||
"ioffset %016llx ilength %08x engine %08x\n",
|
if (engine) {
|
||||||
args->v0.version, args->v0.vm, args->v0.ioffset,
|
u64 submask = BIT_ULL(engine->subdev.index);
|
||||||
args->v0.ilength, args->v0.engine);
|
for (j = 0; func[j].subdev; j++) {
|
||||||
} else
|
if (func[j].subdev & submask) {
|
||||||
return ret;
|
present |= func[j].engine;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* determine which downstream engines are present */
|
if (!func[j].subdev)
|
||||||
for (i = 0, engines = 0; i < fifo->runlist_nr; i++) {
|
continue;
|
||||||
u64 subdevs = gk104_fifo_engine_subdev(i);
|
|
||||||
if (!nvkm_device_engine(device, __ffs64(subdevs)))
|
if (runlist < 0 && (*engmask & present))
|
||||||
continue;
|
runlist = fifo->engine[i].runl;
|
||||||
engines |= (1 << i);
|
if (runlist == fifo->engine[i].runl) {
|
||||||
|
engines |= func[j].engine;
|
||||||
|
subdevs |= func[j].subdev;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* if this is an engine mask query, we're done */
|
/* Just an engine mask query? All done here! */
|
||||||
if (!args->v0.engine) {
|
if (!*engmask) {
|
||||||
args->v0.engine = engines;
|
*engmask = present;
|
||||||
return nvkm_object_new(oclass, NULL, 0, pobject);
|
return nvkm_object_new(oclass, NULL, 0, pobject);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* check that we support a requested engine - note that the user
|
/* No runlist? No supported engines. */
|
||||||
* argument is a mask in order to allow the user to request (for
|
*engmask = present;
|
||||||
* example) *any* copy engine, but doesn't matter which.
|
if (runlist < 0)
|
||||||
*/
|
|
||||||
args->v0.engine &= engines;
|
|
||||||
if (!args->v0.engine) {
|
|
||||||
nvif_ioctl(parent, "no supported engine\n");
|
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
*engmask = engines;
|
||||||
|
|
||||||
/* allocate the channel */
|
/* Allocate the channel. */
|
||||||
if (!(chan = kzalloc(sizeof(*chan), GFP_KERNEL)))
|
if (!(chan = kzalloc(sizeof(*chan), GFP_KERNEL)))
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
*pobject = &chan->base.object;
|
*pobject = &chan->base.object;
|
||||||
chan->fifo = fifo;
|
chan->fifo = fifo;
|
||||||
chan->runl = __ffs(args->v0.engine);
|
chan->runl = runlist;
|
||||||
INIT_LIST_HEAD(&chan->head);
|
INIT_LIST_HEAD(&chan->head);
|
||||||
|
|
||||||
ret = nvkm_fifo_chan_ctor(&gk104_fifo_gpfifo_func, &fifo->base,
|
ret = nvkm_fifo_chan_ctor(&gk104_fifo_gpfifo_func, &fifo->base,
|
||||||
0x1000, 0x1000, true, args->v0.vm, 0,
|
0x1000, 0x1000, true, vm, 0, subdevs,
|
||||||
gk104_fifo_engine_subdev(chan->runl),
|
|
||||||
1, fifo->user.bar.offset, 0x200,
|
1, fifo->user.bar.offset, 0x200,
|
||||||
oclass, &chan->base);
|
oclass, &chan->base);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
args->v0.chid = chan->base.chid;
|
*chid = chan->base.chid;
|
||||||
|
|
||||||
/* page directory */
|
/* Page directory. */
|
||||||
ret = nvkm_gpuobj_new(device, 0x10000, 0x1000, false, NULL, &chan->pgd);
|
ret = nvkm_gpuobj_new(device, 0x10000, 0x1000, false, NULL, &chan->pgd);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -284,10 +290,9 @@ gk104_fifo_gpfifo_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass,
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
/* clear channel control registers */
|
/* Clear channel control registers. */
|
||||||
usermem = chan->base.chid * 0x200;
|
usermem = chan->base.chid * 0x200;
|
||||||
ioffset = args->v0.ioffset;
|
ilength = order_base_2(ilength / 8);
|
||||||
ilength = order_base_2(args->v0.ilength / 8);
|
|
||||||
|
|
||||||
nvkm_kmap(fifo->user.mem);
|
nvkm_kmap(fifo->user.mem);
|
||||||
for (i = 0; i < 0x200; i += 4)
|
for (i = 0; i < 0x200; i += 4)
|
||||||
|
@ -316,6 +321,51 @@ gk104_fifo_gpfifo_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const struct gk104_fifo_chan_func
|
||||||
|
gk104_fifo_gpfifo[] = {
|
||||||
|
{ NVA06F_V0_ENGINE_SW | NVA06F_V0_ENGINE_GR,
|
||||||
|
BIT_ULL(NVKM_ENGINE_SW) | BIT_ULL(NVKM_ENGINE_GR)
|
||||||
|
},
|
||||||
|
{ NVA06F_V0_ENGINE_MSVLD , BIT_ULL(NVKM_ENGINE_MSVLD ) },
|
||||||
|
{ NVA06F_V0_ENGINE_MSPDEC, BIT_ULL(NVKM_ENGINE_MSPDEC) },
|
||||||
|
{ NVA06F_V0_ENGINE_MSPPP , BIT_ULL(NVKM_ENGINE_MSPPP ) },
|
||||||
|
{ NVA06F_V0_ENGINE_MSENC , BIT_ULL(NVKM_ENGINE_MSENC ) },
|
||||||
|
{ NVA06F_V0_ENGINE_CE0 , BIT_ULL(NVKM_ENGINE_CE0 ) },
|
||||||
|
{ NVA06F_V0_ENGINE_CE1 , BIT_ULL(NVKM_ENGINE_CE1 ) },
|
||||||
|
{ NVA06F_V0_ENGINE_CE2 , BIT_ULL(NVKM_ENGINE_CE2 ) },
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
|
int
|
||||||
|
gk104_fifo_gpfifo_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass,
|
||||||
|
void *data, u32 size, struct nvkm_object **pobject)
|
||||||
|
{
|
||||||
|
struct nvkm_object *parent = oclass->parent;
|
||||||
|
union {
|
||||||
|
struct kepler_channel_gpfifo_a_v0 v0;
|
||||||
|
} *args = data;
|
||||||
|
struct gk104_fifo *fifo = gk104_fifo(base);
|
||||||
|
int ret = -ENOSYS;
|
||||||
|
|
||||||
|
nvif_ioctl(parent, "create channel gpfifo size %d\n", size);
|
||||||
|
if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
|
||||||
|
nvif_ioctl(parent, "create channel gpfifo vers %d vm %llx "
|
||||||
|
"ioffset %016llx ilength %08x engine %08x\n",
|
||||||
|
args->v0.version, args->v0.vm, args->v0.ioffset,
|
||||||
|
args->v0.ilength, args->v0.engines);
|
||||||
|
return gk104_fifo_gpfifo_new_(gk104_fifo_gpfifo, fifo,
|
||||||
|
&args->v0.engines,
|
||||||
|
&args->v0.chid,
|
||||||
|
args->v0.vm,
|
||||||
|
args->v0.ioffset,
|
||||||
|
args->v0.ilength,
|
||||||
|
oclass, pobject);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
const struct nvkm_fifo_chan_oclass
|
const struct nvkm_fifo_chan_oclass
|
||||||
gk104_fifo_gpfifo_oclass = {
|
gk104_fifo_gpfifo_oclass = {
|
||||||
.base.oclass = KEPLER_CHANNEL_GPFIFO_A,
|
.base.oclass = KEPLER_CHANNEL_GPFIFO_A,
|
||||||
|
|
Загрузка…
Ссылка в новой задаче