Commit 37e1c45a authored by Ben Skeggs's avatar Ben Skeggs

drm/nouveau/fifo/gv100: initial support

Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
parent facaed62
......@@ -52,6 +52,8 @@
#define NV04_DISP /* cl0046.h */ 0x00000046
#define VOLTA_USERMODE_A 0x0000c361
#define NV03_CHANNEL_DMA /* cl506b.h */ 0x0000006b
#define NV10_CHANNEL_DMA /* cl506b.h */ 0x0000006e
#define NV17_CHANNEL_DMA /* cl506b.h */ 0x0000176e
......@@ -66,6 +68,7 @@
#define KEPLER_CHANNEL_GPFIFO_B /* cla06f.h */ 0x0000a16f
#define MAXWELL_CHANNEL_GPFIFO_A /* cla06f.h */ 0x0000b06f
#define PASCAL_CHANNEL_GPFIFO_A /* cla06f.h */ 0x0000c06f
#define VOLTA_CHANNEL_GPFIFO_A /* cla06f.h */ 0x0000c36f
#define NV50_DISP /* cl5070.h */ 0x00005070
#define G82_DISP /* cl5070.h */ 0x00008270
......
......@@ -4,6 +4,7 @@
#include <nvif/object.h>
#include <nvif/cl0080.h>
#include <nvif/user.h>
struct nvif_device {
struct nvif_object object;
......@@ -13,6 +14,8 @@ struct nvif_device {
u64 engines;
} *runlist;
int runlists;
struct nvif_user user;
};
int nvif_device_init(struct nvif_object *, u32 handle, s32 oclass, void *, u32,
......
#ifndef __NVIF_USER_H__
#define __NVIF_USER_H__
#include <nvif/object.h>
struct nvif_device;
struct nvif_user {
const struct nvif_user_func *func;
struct nvif_object object;
};
struct nvif_user_func {
void (*doorbell)(struct nvif_user *, u32 token);
};
int nvif_user_init(struct nvif_device *);
void nvif_user_fini(struct nvif_device *);
extern const struct nvif_user_func nvif_userc361;
#endif
......@@ -73,4 +73,5 @@ int gm200_fifo_new(struct nvkm_device *, int, struct nvkm_fifo **);
int gm20b_fifo_new(struct nvkm_device *, int, struct nvkm_fifo **);
int gp100_fifo_new(struct nvkm_device *, int, struct nvkm_fifo **);
int gp10b_fifo_new(struct nvkm_device *, int, struct nvkm_fifo **);
int gv100_fifo_new(struct nvkm_device *, int, struct nvkm_fifo **);
#endif
......@@ -220,7 +220,8 @@ nouveau_channel_ind(struct nouveau_drm *drm, struct nvif_device *device,
u64 runlist, struct nouveau_channel **pchan)
{
struct nouveau_cli *cli = (void *)device->object.client;
static const u16 oclasses[] = { PASCAL_CHANNEL_GPFIFO_A,
static const u16 oclasses[] = { VOLTA_CHANNEL_GPFIFO_A,
PASCAL_CHANNEL_GPFIFO_A,
MAXWELL_CHANNEL_GPFIFO_A,
KEPLER_CHANNEL_GPFIFO_B,
KEPLER_CHANNEL_GPFIFO_A,
......
......@@ -28,6 +28,8 @@
#include "nouveau_dma.h"
#include "nouveau_vmm.h"
#include <nvif/user.h>
void
OUT_RINGp(struct nouveau_channel *chan, const void *data, unsigned nr_dwords)
{
......@@ -82,6 +84,7 @@ READ_GET(struct nouveau_channel *chan, uint64_t *prev_get, int *timeout)
void
nv50_dma_push(struct nouveau_channel *chan, u64 offset, int length)
{
struct nvif_user *user = &chan->drm->client.device.user;
struct nouveau_bo *pb = chan->push.buffer;
int ip = (chan->dma.ib_put * 2) + chan->dma.ib_base;
......@@ -97,6 +100,8 @@ nv50_dma_push(struct nouveau_channel *chan, u64 offset, int length)
nouveau_bo_rd32(pb, 0);
nvif_wr32(&chan->user, 0x8c, chan->dma.ib_put);
if (user->func && user->func->doorbell)
user->func->doorbell(user, chan->chid);
chan->dma.ib_free--;
}
......
......@@ -39,6 +39,7 @@
#include <nvif/driver.h>
#include <nvif/fifo.h>
#include <nvif/user.h>
#include <nvif/class.h>
#include <nvif/cl0002.h>
......@@ -310,6 +311,12 @@ nouveau_accel_init(struct nouveau_drm *drm)
if (ret)
return;
if (drm->client.device.info.family >= NV_DEVICE_INFO_V0_VOLTA) {
ret = nvif_user_init(device);
if (ret)
return;
}
/* initialise synchronisation routines */
/*XXX: this is crap, but the fence/channel stuff is a little
* backwards in some places. this will be fixed.
......@@ -341,6 +348,7 @@ nouveau_accel_init(struct nouveau_drm *drm)
case KEPLER_CHANNEL_GPFIFO_B:
case MAXWELL_CHANNEL_GPFIFO_A:
case PASCAL_CHANNEL_GPFIFO_A:
case VOLTA_CHANNEL_GPFIFO_A:
ret = nvc0_fence_create(drm);
break;
default:
......
......@@ -8,3 +8,7 @@ nvif-y += nvif/mem.o
nvif-y += nvif/mmu.o
nvif-y += nvif/notify.o
nvif-y += nvif/vmm.o
# Usermode classes
nvif-y += nvif/user.o
nvif-y += nvif/userc361.o
......@@ -37,6 +37,7 @@ nvif_device_time(struct nvif_device *device)
void
nvif_device_fini(struct nvif_device *device)
{
nvif_user_fini(device);
kfree(device->runlist);
device->runlist = NULL;
nvif_object_fini(&device->object);
......@@ -49,6 +50,7 @@ nvif_device_init(struct nvif_object *parent, u32 handle, s32 oclass,
int ret = nvif_object_init(parent, handle, oclass, data, size,
&device->object);
device->runlist = NULL;
device->user.func = NULL;
if (ret == 0) {
device->info.version = 0;
ret = nvif_object_mthd(&device->object, NV_DEVICE_V0_INFO,
......
/*
* Copyright 2018 Red Hat Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#include <nvif/user.h>
#include <nvif/device.h>
#include <nvif/class.h>
void
nvif_user_fini(struct nvif_device *device)
{
if (device->user.func) {
nvif_object_fini(&device->user.object);
device->user.func = NULL;
}
}
int
nvif_user_init(struct nvif_device *device)
{
struct {
s32 oclass;
int version;
const struct nvif_user_func *func;
} users[] = {
{ VOLTA_USERMODE_A, -1, &nvif_userc361 },
{}
};
int cid, ret;
if (device->user.func)
return 0;
cid = nvif_mclass(&device->object, users);
if (cid < 0)
return cid;
ret = nvif_object_init(&device->object, 0, users[cid].oclass, NULL, 0,
&device->user.object);
if (ret)
return ret;
nvif_object_map(&device->user.object, NULL, 0);
device->user.func = users[cid].func;
return 0;
}
/*
* Copyright 2018 Red Hat Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#include <nvif/user.h>
static void
nvif_userc361_doorbell(struct nvif_user *user, u32 token)
{
nvif_wr32(&user->object, 0x90, token);
}
const struct nvif_user_func
nvif_userc361 = {
.doorbell = nvif_userc361_doorbell,
};
......@@ -2418,6 +2418,7 @@ nv140_chipset = {
.top = gk104_top_new,
.disp = gv100_disp_new,
.dma = gv100_dma_new,
.fifo = gv100_fifo_new,
};
static int
......
......@@ -15,6 +15,7 @@ nvkm-y += nvkm/engine/fifo/gm200.o
nvkm-y += nvkm/engine/fifo/gm20b.o
nvkm-y += nvkm/engine/fifo/gp100.o
nvkm-y += nvkm/engine/fifo/gp10b.o
nvkm-y += nvkm/engine/fifo/gv100.o
nvkm-y += nvkm/engine/fifo/chan.o
nvkm-y += nvkm/engine/fifo/channv50.o
......@@ -31,3 +32,6 @@ nvkm-y += nvkm/engine/fifo/gpfifonv50.o
nvkm-y += nvkm/engine/fifo/gpfifog84.o
nvkm-y += nvkm/engine/fifo/gpfifogf100.o
nvkm-y += nvkm/engine/fifo/gpfifogk104.o
nvkm-y += nvkm/engine/fifo/gpfifogv100.o
nvkm-y += nvkm/engine/fifo/usergv100.o
......@@ -20,6 +20,20 @@ struct gk104_fifo_chan {
} engn[NVKM_SUBDEV_NR];
};
extern const struct nvkm_fifo_chan_func gk104_fifo_gpfifo_func;
int gk104_fifo_gpfifo_new(struct gk104_fifo *, const struct nvkm_oclass *,
void *data, u32 size, struct nvkm_object **);
void *gk104_fifo_gpfifo_dtor(struct nvkm_fifo_chan *);
void gk104_fifo_gpfifo_init(struct nvkm_fifo_chan *);
void gk104_fifo_gpfifo_fini(struct nvkm_fifo_chan *);
int gk104_fifo_gpfifo_engine_ctor(struct nvkm_fifo_chan *, struct nvkm_engine *,
struct nvkm_object *);
void gk104_fifo_gpfifo_engine_dtor(struct nvkm_fifo_chan *,
struct nvkm_engine *);
int gk104_fifo_gpfifo_kick(struct gk104_fifo_chan *);
int gk104_fifo_gpfifo_kick_locked(struct gk104_fifo_chan *);
int gv100_fifo_gpfifo_new(struct gk104_fifo *, const struct nvkm_oclass *,
void *data, u32 size, struct nvkm_object **);
#endif
......@@ -103,6 +103,10 @@ gk104_fifo_class_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass,
if (oclass->engn == &fifo->func->chan) {
const struct gk104_fifo_chan_user *user = oclass->engn;
return user->ctor(fifo, oclass, argv, argc, pobject);
} else
if (oclass->engn == &fifo->func->user) {
const struct gk104_fifo_user_user *user = oclass->engn;
return user->ctor(oclass, argv, argc, pobject);
}
WARN_ON(1);
return -EINVAL;
......@@ -115,6 +119,12 @@ gk104_fifo_class_get(struct nvkm_fifo *base, int index,
struct gk104_fifo *fifo = gk104_fifo(base);
int c = 0;
if (fifo->func->user.ctor && c++ == index) {
oclass->base = fifo->func->user.user;
oclass->engn = &fifo->func->user;
return 0;
}
if (fifo->func->chan.ctor && c++ == index) {
oclass->base = fifo->func->chan.user;
oclass->engn = &fifo->func->chan;
......
......@@ -63,6 +63,12 @@ struct gk104_fifo_func {
struct nvkm_memory *, u32 offset);
} *runlist;
struct gk104_fifo_user_user {
struct nvkm_sclass user;
int (*ctor)(const struct nvkm_oclass *, void *, u32,
struct nvkm_object **);
} user;
struct gk104_fifo_chan_user {
struct nvkm_sclass user;
int (*ctor)(struct gk104_fifo *, const struct nvkm_oclass *,
......
......@@ -34,8 +34,8 @@
#include <nvif/cla06f.h>
#include <nvif/unpack.h>
static int
gk104_fifo_gpfifo_kick(struct gk104_fifo_chan *chan)
int
gk104_fifo_gpfifo_kick_locked(struct gk104_fifo_chan *chan)
{
struct gk104_fifo *fifo = chan->fifo;
struct nvkm_subdev *subdev = &fifo->base.engine.subdev;
......@@ -44,7 +44,6 @@ gk104_fifo_gpfifo_kick(struct gk104_fifo_chan *chan)
struct nvkm_fifo_cgrp *cgrp = chan->cgrp;
int ret = 0;
mutex_lock(&subdev->mutex);
if (cgrp)
nvkm_wr32(device, 0x002634, cgrp->id | 0x01000000);
else
......@@ -59,7 +58,16 @@ gk104_fifo_gpfifo_kick(struct gk104_fifo_chan *chan)
nvkm_fifo_recover_chan(&fifo->base, chan->base.chid);
ret = -ETIMEDOUT;
}
mutex_unlock(&subdev->mutex);
return ret;
}
int
gk104_fifo_gpfifo_kick(struct gk104_fifo_chan *chan)
{
int ret;
mutex_lock(&chan->base.fifo->engine.subdev.mutex);
ret = gk104_fifo_gpfifo_kick_locked(chan);
mutex_unlock(&chan->base.fifo->engine.subdev.mutex);
return ret;
}
......@@ -138,7 +146,7 @@ gk104_fifo_gpfifo_engine_init(struct nvkm_fifo_chan *base,
return 0;
}
static void
void
gk104_fifo_gpfifo_engine_dtor(struct nvkm_fifo_chan *base,
struct nvkm_engine *engine)
{
......@@ -147,7 +155,7 @@ gk104_fifo_gpfifo_engine_dtor(struct nvkm_fifo_chan *base,
nvkm_gpuobj_del(&chan->engn[engine->subdev.index].inst);
}
static int
int
gk104_fifo_gpfifo_engine_ctor(struct nvkm_fifo_chan *base,
struct nvkm_engine *engine,
struct nvkm_object *object)
......@@ -172,7 +180,7 @@ gk104_fifo_gpfifo_engine_ctor(struct nvkm_fifo_chan *base,
chan->engn[engn].vma, NULL, 0);
}
static void
void
gk104_fifo_gpfifo_fini(struct nvkm_fifo_chan *base)
{
struct gk104_fifo_chan *chan = gk104_fifo_chan(base);
......@@ -190,7 +198,7 @@ gk104_fifo_gpfifo_fini(struct nvkm_fifo_chan *base)
nvkm_wr32(device, 0x800000 + coff, 0x00000000);
}
static void
void
gk104_fifo_gpfifo_init(struct nvkm_fifo_chan *base)
{
struct gk104_fifo_chan *chan = gk104_fifo_chan(base);
......@@ -210,7 +218,7 @@ gk104_fifo_gpfifo_init(struct nvkm_fifo_chan *base)
}
}
static void *
void *
gk104_fifo_gpfifo_dtor(struct nvkm_fifo_chan *base)
{
struct gk104_fifo_chan *chan = gk104_fifo_chan(base);
......@@ -218,7 +226,7 @@ gk104_fifo_gpfifo_dtor(struct nvkm_fifo_chan *base)
return chan;
}
static const struct nvkm_fifo_chan_func
const struct nvkm_fifo_chan_func
gk104_fifo_gpfifo_func = {
.dtor = gk104_fifo_gpfifo_dtor,
.init = gk104_fifo_gpfifo_init,
......
/*
* Copyright 2018 Red Hat Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#include "changk104.h"
#include "cgrp.h"
#include <core/client.h>
#include <core/gpuobj.h>
#include <nvif/cla06f.h>
#include <nvif/unpack.h>
static int
gv100_fifo_gpfifo_engine_valid(struct gk104_fifo_chan *chan, bool ce, bool valid)
{
struct nvkm_subdev *subdev = &chan->base.fifo->engine.subdev;
struct nvkm_device *device = subdev->device;
const u32 mask = ce ? 0x00020000 : 0x00010000;
const u32 data = valid ? mask : 0x00000000;
int ret;
/* Block runlist to prevent the channel from being rescheduled. */
mutex_lock(&subdev->mutex);
nvkm_mask(device, 0x002630, BIT(chan->runl), BIT(chan->runl));
/* Preempt the channel. */
ret = gk104_fifo_gpfifo_kick_locked(chan);
if (ret == 0) {
/* Update engine context validity. */
nvkm_kmap(chan->base.inst);
nvkm_mo32(chan->base.inst, 0x0ac, mask, data);
nvkm_done(chan->base.inst);
}
/* Resume runlist. */
nvkm_mask(device, 0x002630, BIT(chan->runl), 0);
mutex_unlock(&subdev->mutex);
return ret;
}
static int
gv100_fifo_gpfifo_engine_fini(struct nvkm_fifo_chan *base,
struct nvkm_engine *engine, bool suspend)
{
struct gk104_fifo_chan *chan = gk104_fifo_chan(base);
struct nvkm_gpuobj *inst = chan->base.inst;
int ret;
if (engine->subdev.index >= NVKM_ENGINE_CE0 &&
engine->subdev.index <= NVKM_ENGINE_CE_LAST)
return gk104_fifo_gpfifo_kick(chan);
ret = gv100_fifo_gpfifo_engine_valid(chan, false, false);
if (ret && suspend)
return ret;
nvkm_kmap(inst);
nvkm_wo32(inst, 0x0210, 0x00000000);
nvkm_wo32(inst, 0x0214, 0x00000000);
nvkm_done(inst);
return ret;
}
static int
gv100_fifo_gpfifo_engine_init(struct nvkm_fifo_chan *base,
struct nvkm_engine *engine)
{
struct gk104_fifo_chan *chan = gk104_fifo_chan(base);
struct nvkm_gpuobj *inst = chan->base.inst;
u64 addr;
if (engine->subdev.index >= NVKM_ENGINE_CE0 &&
engine->subdev.index <= NVKM_ENGINE_CE_LAST)
return 0;
addr = chan->engn[engine->subdev.index].vma->addr;
nvkm_kmap(inst);
nvkm_wo32(inst, 0x210, lower_32_bits(addr) | 0x00000004);
nvkm_wo32(inst, 0x214, upper_32_bits(addr));
nvkm_done(inst);
return gv100_fifo_gpfifo_engine_valid(chan, false, true);
}
const struct nvkm_fifo_chan_func
gv100_fifo_gpfifo_func = {
.dtor = gk104_fifo_gpfifo_dtor,
.init = gk104_fifo_gpfifo_init,
.fini = gk104_fifo_gpfifo_fini,
.ntfy = gf100_fifo_chan_ntfy,
.engine_ctor = gk104_fifo_gpfifo_engine_ctor,
.engine_dtor = gk104_fifo_gpfifo_engine_dtor,
.engine_init = gv100_fifo_gpfifo_engine_init,
.engine_fini = gv100_fifo_gpfifo_engine_fini,
};
static int
gv100_fifo_gpfifo_new_(struct gk104_fifo *fifo, u64 *runlists, u16 *chid,
u64 vmm, u64 ioffset, u64 ilength,
const struct nvkm_oclass *oclass,
struct nvkm_object **pobject)
{
struct gk104_fifo_chan *chan;
int runlist = ffs(*runlists) -1, ret, i;
unsigned long engm;
u64 subdevs = 0;
u64 usermem;
if (!vmm || runlist < 0 || runlist >= fifo->runlist_nr)
return -EINVAL;
*runlists = BIT_ULL(runlist);
engm = fifo->runlist[runlist].engm;
for_each_set_bit(i, &engm, fifo->engine_nr) {
if (fifo->engine[i].engine)
subdevs |= BIT_ULL(fifo->engine[i].engine->subdev.index);
}
/* Allocate the channel. */
if (!(chan = kzalloc(sizeof(*chan), GFP_KERNEL)))
return -ENOMEM;
*pobject = &chan->base.object;
chan->fifo = fifo;
chan->runl = runlist;
INIT_LIST_HEAD(&chan->head);
ret = nvkm_fifo_chan_ctor(&gv100_fifo_gpfifo_func, &fifo->base,
0x1000, 0x1000, true, vmm, 0, subdevs,
1, fifo->user.bar->addr, 0x200,
oclass, &chan->base);
if (ret)
return ret;
*chid = chan->base.chid;
/* Hack to support GPUs where even individual channels should be
* part of a channel group.
*/
if (fifo->func->cgrp_force) {
if (!(chan->cgrp = kmalloc(sizeof(*chan->cgrp), GFP_KERNEL)))
return -ENOMEM;
chan->cgrp->id = chan->base.chid;
INIT_LIST_HEAD(&chan->cgrp->head);
INIT_LIST_HEAD(&chan->cgrp->chan);
chan->cgrp->chan_nr = 0;
}
/* Clear channel control registers. */
usermem = chan->base.chid * 0x200;
ilength = order_base_2(ilength / 8);
nvkm_kmap(fifo->user.mem);
for (i = 0; i < 0x200; i += 4)
nvkm_wo32(fifo->user.mem, usermem + i, 0x00000000);
nvkm_done(fifo->user.mem);
usermem = nvkm_memory_addr(fifo->user.mem) + usermem;
/* RAMFC */
nvkm_kmap(chan->base.inst);
nvkm_wo32(chan->base.inst, 0x008, lower_32_bits(usermem));
nvkm_wo32(chan->base.inst, 0x00c, upper_32_bits(usermem));
nvkm_wo32(chan->base.inst, 0x010, 0x0000face);
nvkm_wo32(chan->base.inst, 0x030, 0x7ffff902);
nvkm_wo32(chan->base.inst, 0x048, lower_32_bits(ioffset));
nvkm_wo32(chan->base.inst, 0x04c, upper_32_bits(ioffset) |
(ilength << 16));
nvkm_wo32(chan->base.inst, 0x084, 0x20400000);
nvkm_wo32(chan->base.inst, 0x094, 0x30000001);
nvkm_wo32(chan->base.inst, 0x0e4, 0x00000020);
nvkm_wo32(chan->base.inst, 0x0e8, chan->base.chid);
nvkm_wo32(chan->base.inst, 0x0f4, 0x00001100);
nvkm_wo32(chan->base.inst, 0x0f8, 0x10003080);
nvkm_mo32(chan->base.inst, 0x218, 0x00000000, 0x00000000);
nvkm_wo32(chan->base.inst, 0x220, 0x020a1000);
nvkm_wo32(chan->base.inst, 0x224, 0x00000000);
nvkm_done(chan->base.inst);
return gv100_fifo_gpfifo_engine_valid(chan, true, true);
}
int
gv100_fifo_gpfifo_new(struct gk104_fifo *fifo, const struct nvkm_oclass *oclass,
void *data, u32 size, struct nvkm_object **pobject)
{
struct nvkm_object *parent = oclass->parent;
union {
struct kepler_channel_gpfifo_a_v0 v0;
} *args = data;
int ret = -ENOSYS;
nvif_ioctl(parent, "create channel gpfifo size %d\n", size);
if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
nvif_ioctl(parent, "create channel gpfifo vers %d vmm %llx "
"ioffset %016llx ilength %08x "
"runlist %016llx\n",
args->v0.version, args->v0.vmm, args->v0.ioffset,
args->v0.ilength, args->v0.runlist);
return gv100_fifo_gpfifo_new_(fifo,
&args->v0.runlist,
&args->v0.chid,
args->v0.vmm,
args->v0.ioffset,
args->v0.ilength,
oclass, pobject);
}
return ret;
}
/*
* Copyright 2018 Red Hat Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#include "gk104.h"
#include "cgrp.h"
#include "changk104.h"
#include "user.h"
#include <core/gpuobj.h>
#include <nvif/class.h>
static void
gv100_fifo_runlist_chan(struct gk104_fifo_chan *chan,
struct nvkm_memory *memory, u32 offset)
{
struct nvkm_memory *usermem = chan->fifo->user.mem;
const u64 user = nvkm_memory_addr(usermem) + (chan->base.chid * 0x200);
const u64 inst = chan->base.inst->addr;
nvkm_wo32(memory, offset + 0x0, lower_32_bits(user));
nvkm_wo32(memory, offset + 0x4, upper_32_bits(user));
nvkm_wo32(memory, offset + 0x8, lower_32_bits(inst) | chan->base.chid);
nvkm_wo32(memory, offset + 0xc, upper_32_bits(inst));
}
static void
gv100_fifo_runlist_cgrp(struct nvkm_fifo_cgrp *cgrp,
struct nvkm_memory *memory, u32 offset)
{
nvkm_wo32(memory, offset + 0x0, (128 << 24) | (3 << 16) | 0x00000001);
nvkm_wo32(memory, offset + 0x4, cgrp->chan_nr);
nvkm_wo32(memory, offset + 0x8, cgrp->id);
nvkm_wo32(memory, offset + 0xc, 0x00000000);
}
const struct gk104_fifo_runlist_func
gv100_fifo_runlist = {
.size = 16,
.cgrp = gv100_fifo_runlist_cgrp,
.chan = gv100_fifo_runlist_chan,
};
static const struct nvkm_enum
gv100_fifo_fault_gpcclient[] = {
{ 0x00, "T1_0" },
{ 0x01, "T1_1" },
{ 0x02, "T1_2" },
{ 0x03, "T1_3" },
{ 0x04, "T1_4" },
{ 0x05, "T1_5" },
{ 0x06, "T1_6" },
{ 0x07, "T1_7" },
{ 0x08, "PE_0" },
{ 0x09, "PE_1" },
{ 0x0a, "PE_2" },
{ 0x0b, "PE_3" },
{ 0x0c, "PE_4" },
{ 0x0d, "PE_5" },
{ 0x0e, "PE_6" },
{ 0x0f, "PE_7" },
{ 0x10, "RAST" },
{ 0x11, "GCC" },
{ 0x12, "GPCCS" },
{ 0x13, "PROP_0" },
{ 0x14, "PROP_1" },
{ 0x15, "PROP_2" },
{ 0x16, "PROP_3" },
{ 0x17, "GPM" },
{ 0x18, "LTP_UTLB_0" },
{ 0x19, "LTP_UTLB_1" },
{ 0x1a, "LTP_UTLB_2" },
{ 0x1b, "LTP_UTLB_3" },
{ 0x1c, "LTP_UTLB_4" },
{ 0x1d, "LTP_UTLB_5" },
{ 0x1e, "LTP_UTLB_6" },
{ 0x1f, "LTP_UTLB_7" },
{ 0x20, "RGG_UTLB" },
{ 0x21, "T1_8" },
{ 0x22, "T1_9" },
{ 0x23, "T1_10" },
{ 0x24, "T1_11" },
{ 0x25, "T1_12" },
{ 0x26, "T1_13" },
{ 0x27, "T1_14" },
{ 0x28, "T1_15" },
{ 0x29, "TPCCS_0" },
{ 0x2a, "TPCCS_1" },
{ 0x2b, "TPCCS_2" },
{ 0x2c, "TPCCS_3" },
{ 0x2d, "TPCCS_4" },
{ 0x2e, "TPCCS_5" },
{ 0x2f, "TPCCS_6" },
{ 0x30, "TPCCS_7" },
{ 0x31, "PE_8" },
{ 0x32, "PE_9" },
{ 0x33, "TPCCS_8" },
{ 0x34, "TPCCS_9" },
{ 0x35, "T1_16" },
{ 0x36, "T1_17" },
{ 0x37, "T1_18" },
{ 0x38, "T1_19" },
{ 0x39, "PE_10" },
{ 0x3a, "PE_11" },
{ 0x3b, "TPCCS_10" },
{ 0x3c, "TPCCS_11" },
{ 0x3d, "T1_20" },
{ 0x3e, "T1_21" },
{ 0x3f, "T1_22" },
{ 0x40, "T1_23" },
{ 0x41, "PE_12" },
{ 0x42, "PE_13" },
{ 0x43, "TPCCS_12" },
{ 0x44, "TPCCS_13" },
{ 0x45, "T1_24" },
{ 0x46, "T1_25" },
{ 0x47, "T1_26" },
{ 0x48, "T1_27" },
{ 0x49, "PE_14" },
{ 0x4a, "PE_15" },
{ 0x4b, "TPCCS_14" },
{ 0x4c, "TPCCS_15" },
{ 0x4d, "T1_28" },
{ 0x4e, "T1_29" },
{ 0x4f, "T1_30" },
{ 0x50, "T1_31" },
{ 0x51, "PE_16" },
{ 0x52, "PE_17" },
{ 0x53, "TPCCS_16" },
{ 0x54, "TPCCS_17" },
{ 0x55, "T1_32" },
{ 0x56, "T1_33" },
{ 0x57, "T1_34" },
{ 0x58, "T1_35" },
{ 0x59, "PE_18" },
{ 0x5a, "PE_19" },
{ 0x5b, "TPCCS_18" },
{ 0x5c, "TPCCS_19" },
{ 0x5d, "T1_36" },
{ 0x5e, "T1_37" },
{ 0x5f, "T1_38" },
{ 0x60, "T1_39" },
{}
};
static const struct nvkm_enum
gv100_fifo_fault_hubclient[] = {
{ 0x00, "VIP" },
{ 0x01, "CE0" },
{ 0x02, "CE1" },
{ 0x03, "DNISO" },
{ 0x04, "FE" },
{ 0x05, "FECS" },
{ 0x06, "HOST" },
{ 0x07, "HOST_CPU" },
{ 0x08, "HOST_CPU_NB" },
{ 0x09, "ISO" },
{ 0x0a, "MMU" },
{ 0x0b, "NVDEC" },
{ 0x0d, "NVENC1" },
{ 0x0e, "NISO" },
{ 0x0f, "P2P" },
{ 0x10, "PD" },
{ 0x11, "PERF" },
{ 0x12, "PMU" },
{ 0x13, "RASTERTWOD" },
{ 0x14, "SCC" },
{ 0x15, "SCC_NB" },
{ 0x16, "SEC" },
{ 0x17, "SSYNC" },
{ 0x18, "CE2" },
{ 0x19, "XV" },
{ 0x1a, "MMU_NB" },
{ 0x1b, "NVENC0" },
{ 0x1c, "DFALCON" },
{ 0x1d, "SKED" },
{ 0x1e, "AFALCON" },
{ 0x1f, "DONT_CARE" },
{ 0x20, "HSCE0" },
{ 0x21, "HSCE1" },
{ 0x22, "HSCE2" },
{ 0x23, "HSCE3" },
{ 0x24, "HSCE4" },
{ 0x25, "HSCE5" },
{ 0x26, "HSCE6" },
{ 0x27, "HSCE7" },
{ 0x28, "HSCE8" },
{ 0x29, "HSCE9" },
{ 0x2a, "HSHUB" },
{ 0x2b, "PTP_X0" },
{ 0x2c, "PTP_X1" },
{ 0x2d, "PTP_X2" },
{ 0x2e, "PTP_X3" },
{ 0x2f, "PTP_X4" },
{ 0x30, "PTP_X5" },
{ 0x31, "PTP_X6" },
{ 0x32, "PTP_X7" },
{ 0x33, "NVENC2" },
{ 0x34, "VPR_SCRUBBER0" },
{ 0x35, "VPR_SCRUBBER1" },
{ 0x36, "DWBIF" },
{ 0x37, "FBFALCON" },
{ 0x38, "CE_SHIM" },
{ 0x39, "GSP" },
{}
};
static const struct nvkm_enum
gv100_fifo_fault_reason[] = {
{ 0x00, "PDE" },
{ 0x01, "PDE_SIZE" },
{ 0x02, "PTE" },
{ 0x03, "VA_LIMIT_VIOLATION" },
{ 0x04, "UNBOUND_INST_BLOCK" },
{ 0x05, "PRIV_VIOLATION" },
{ 0x06, "RO_VIOLATION" },
{ 0x07, "WO_VIOLATION" },
{ 0x08, "PITCH_MASK_VIOLATION" },
{ 0x09, "WORK_CREATION" },
{ 0x0a, "UNSUPPORTED_APERTURE" },
{ 0x0b, "COMPRESSION_FAILURE" },
{ 0x0c, "UNSUPPORTED_KIND" },
{ 0x0d, "REGION_VIOLATION" },
{ 0x0e, "POISONED" },
{ 0x0f, "ATOMIC_VIOLATION" },
{}
};
static const struct nvkm_enum
gv100_fifo_fault_engine[] = {
{ 0x01, "DISPLAY" },
{ 0x03, "PTP" },
{ 0x04, "BAR1", NULL, NVKM_SUBDEV_BAR },
{ 0x05, "BAR2", NULL, NVKM_SUBDEV_INSTMEM },
{ 0x06, "PWR_PMU" },
{ 0x08, "IFB", NULL, NVKM_ENGINE_IFB },
{ 0x09, "PERF" },
{ 0x1f, "PHYSICAL" },
{ 0x20, "HOST0" },
{ 0x21, "HOST1" },
{ 0x22, "HOST2" },
{ 0x23, "HOST3" },
{ 0x24, "HOST4" },
{ 0x25, "HOST5" },
{ 0x26, "HOST6" },
{ 0x27, "HOST7" },
{ 0x28, "HOST8" },
{ 0x29, "HOST9" },
{ 0x2a, "HOST10" },
{ 0x2b, "HOST11" },
{ 0x2c, "HOST12" },
{ 0x2d, "HOST13" },
{}
};
static const struct nvkm_enum
gv100_fifo_fault_access[] = {
{ 0x0, "VIRT_READ" },
{ 0x1, "VIRT_WRITE" },
{ 0x2, "VIRT_ATOMIC" },
{ 0x3, "VIRT_PREFETCH" },
{ 0x4, "VIRT_ATOMIC_WEAK" },
{ 0x8, "PHYS_READ" },
{ 0x9, "PHYS_WRITE" },
{ 0xa, "PHYS_ATOMIC" },
{ 0xb, "PHYS_PREFETCH" },
{}
};
static const struct gk104_fifo_func
gv100_fifo = {
.init_pbdma_timeout = gk208_fifo_init_pbdma_timeout,
.fault.access = gv100_fifo_fault_access,
.fault.engine = gv100_fifo_fault_engine,
.fault.reason = gv100_fifo_fault_reason,
.fault.hubclient = gv100_fifo_fault_hubclient,
.fault.gpcclient = gv100_fifo_fault_gpcclient,
.runlist = &gv100_fifo_runlist,
.user = {{-1,-1,VOLTA_USERMODE_A }, gv100_fifo_user_new },
.chan = {{ 0, 0,VOLTA_CHANNEL_GPFIFO_A}, gv100_fifo_gpfifo_new },
.cgrp_force = true,
};
int
gv100_fifo_new(struct nvkm_device *device, int index, struct nvkm_fifo **pfifo)
{
return gk104_fifo_new_(&gv100_fifo, device, index, 4096, pfifo);
}
#ifndef __NVKM_FIFO_USER_H__
#define __NVKM_FIFO_USER_H__
#include "priv.h"
int gv100_fifo_user_new(const struct nvkm_oclass *, void *, u32,
struct nvkm_object **);
#endif
/*
* Copyright 2018 Red Hat Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#include "user.h"
static int
gv100_fifo_user_map(struct nvkm_object *object, void *argv, u32 argc,
enum nvkm_object_map *type, u64 *addr, u64 *size)
{
struct nvkm_device *device = object->engine->subdev.device;
*addr = 0x810000 + device->func->resource_addr(device, 0);
*size = 0x010000;
*type = NVKM_OBJECT_MAP_IO;
return 0;
}
static const struct nvkm_object_func
gv100_fifo_user = {
.map = gv100_fifo_user_map,
};
int
gv100_fifo_user_new(const struct nvkm_oclass *oclass, void *argv, u32 argc,
struct nvkm_object **pobject)
{
return nvkm_object_new_(&gv100_fifo_user, oclass, argv, argc, pobject);
}
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