Commit 06db7fde authored by Ben Skeggs's avatar Ben Skeggs

drm/nouveau/fifo: add new channel classes

Exposes a bunch of the new features that became possible as a result
of the earlier commits.  DRM will build on this in the future to add
support for features such as SCG ("async compute") and multi-device
rendering, as part of the work necessary to be able to write a half-
decent vulkan driver - finally.

For the moment, this just crudely ports DRM to the API changes.

- channel class interfaces now the same for all HW classes
- channel group class exposed (SCG)
- channel runqueue selector exposed (SCG)
- channel sub-device id control exposed (multi-device rendering)
- channel names in logging will reflect creating process, not fd owner
- explicit USERD allocation required by VOLTA_CHANNEL_GPFIFO_A and newer
- drm is smarter about determining the appropriate channel class to use
Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
Reviewed-by: default avatarLyude Paul <lyude@redhat.com>
parent 7ac29332
/* SPDX-License-Identifier: MIT */
#ifndef __NVIF_CL006B_H__
#define __NVIF_CL006B_H__
struct nv03_channel_dma_v0 {
__u8 version;
__u8 chid;
__u8 pad02[2];
__u32 offset;
__u64 pushbuf;
};
#endif
/* SPDX-License-Identifier: MIT */
#ifndef __NVIF_CL506E_H__
#define __NVIF_CL506E_H__
struct nv50_channel_dma_v0 {
__u8 version;
__u8 chid;
__u8 pad02[6];
__u64 vmm;
__u64 pushbuf;
__u64 offset;
};
#endif
/* SPDX-License-Identifier: MIT */
#ifndef __NVIF_CL506F_H__
#define __NVIF_CL506F_H__
struct nv50_channel_gpfifo_v0 {
__u8 version;
__u8 chid;
__u8 pad02[2];
__u32 ilength;
__u64 ioffset;
__u64 pushbuf;
__u64 vmm;
};
#endif
/* SPDX-License-Identifier: MIT */
#ifndef __NVIF_CL826E_H__
#define __NVIF_CL826E_H__
struct g82_channel_dma_v0 {
__u8 version;
__u8 chid;
__u8 pad02[6];
__u64 vmm;
__u64 pushbuf;
__u64 offset;
};
#endif
/* SPDX-License-Identifier: MIT */
#ifndef __NVIF_CL826F_H__
#define __NVIF_CL826F_H__
struct g82_channel_gpfifo_v0 {
__u8 version;
__u8 chid;
__u8 pad02[2];
__u32 ilength;
__u64 ioffset;
__u64 pushbuf;
__u64 vmm;
};
#endif
/* SPDX-License-Identifier: MIT */
#ifndef __NVIF_CL906F_H__
#define __NVIF_CL906F_H__
struct fermi_channel_gpfifo_v0 {
__u8 version;
__u8 chid;
__u8 pad02[2];
__u32 ilength;
__u64 ioffset;
__u64 vmm;
};
#endif
/* SPDX-License-Identifier: MIT */
#ifndef __NVIF_CLA06F_H__
#define __NVIF_CLA06F_H__
struct kepler_channel_gpfifo_a_v0 {
__u8 version;
__u8 priv;
__u16 chid;
__u32 ilength;
__u64 ioffset;
__u64 runlist;
__u64 vmm;
__u64 inst;
};
#endif
......@@ -70,23 +70,23 @@
#define MAXWELL_FAULT_BUFFER_A /* clb069.h */ 0x0000b069
#define VOLTA_FAULT_BUFFER_A /* clb069.h */ 0x0000c369
#define NV03_CHANNEL_DMA /* cl506b.h */ 0x0000006b
#define NV10_CHANNEL_DMA /* cl506b.h */ 0x0000006e
#define NV17_CHANNEL_DMA /* cl506b.h */ 0x0000176e
#define NV40_CHANNEL_DMA /* cl506b.h */ 0x0000406e
#define NV03_CHANNEL_DMA /* if0020.h */ 0x0000006b
#define NV10_CHANNEL_DMA /* if0020.h */ 0x0000006e
#define NV17_CHANNEL_DMA /* if0020.h */ 0x0000176e
#define NV40_CHANNEL_DMA /* if0020.h */ 0x0000406e
#define KEPLER_CHANNEL_GROUP_A /* if0021.h */ 0x0000a06c
#define NV50_CHANNEL_GPFIFO /* cl506f.h */ 0x0000506f
#define G82_CHANNEL_GPFIFO /* cl826f.h */ 0x0000826f
#define FERMI_CHANNEL_GPFIFO /* cl906f.h */ 0x0000906f
#define KEPLER_CHANNEL_GPFIFO_A /* cla06f.h */ 0x0000a06f
#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 /* clc36f.h */ 0x0000c36f
#define TURING_CHANNEL_GPFIFO_A /* clc36f.h */ 0x0000c46f
#define AMPERE_CHANNEL_GPFIFO_B /* clc36f.h */ 0x0000c76f
#define NV50_CHANNEL_GPFIFO /* if0020.h */ 0x0000506f
#define G82_CHANNEL_GPFIFO /* if0020.h */ 0x0000826f
#define FERMI_CHANNEL_GPFIFO /* if0020.h */ 0x0000906f
#define KEPLER_CHANNEL_GPFIFO_A /* if0020.h */ 0x0000a06f
#define KEPLER_CHANNEL_GPFIFO_B /* if0020.h */ 0x0000a16f
#define MAXWELL_CHANNEL_GPFIFO_A /* if0020.h */ 0x0000b06f
#define PASCAL_CHANNEL_GPFIFO_A /* if0020.h */ 0x0000c06f
#define VOLTA_CHANNEL_GPFIFO_A /* if0020.h */ 0x0000c36f
#define TURING_CHANNEL_GPFIFO_A /* if0020.h */ 0x0000c46f
#define AMPERE_CHANNEL_GPFIFO_B /* if0020.h */ 0x0000c76f
#define NV50_DISP /* if0010.h */ 0x00005070
#define G82_DISP /* if0010.h */ 0x00008270
......
/* SPDX-License-Identifier: MIT */
#ifndef __NVIF_CLC36F_H__
#define __NVIF_CLC36F_H__
struct volta_channel_gpfifo_a_v0 {
__u8 version;
__u8 priv;
__u16 chid;
__u32 ilength;
__u64 ioffset;
__u64 runlist;
__u64 vmm;
__u64 inst;
__u32 token;
};
#endif
......@@ -2,6 +2,38 @@
#ifndef __NVIF_IF0020_H__
#define __NVIF_IF0020_H__
union nvif_chan_args {
struct nvif_chan_v0 {
__u8 version;
__u8 namelen;
__u8 runlist;
__u8 runq;
__u8 priv;
__u8 pad05;
__u16 devm;
__u64 vmm;
__u64 ctxdma;
__u64 offset;
__u64 length;
__u64 huserd;
__u64 ouserd;
__u32 token;
__u16 chid;
__u8 pad3e;
#define NVIF_CHAN_V0_INST_APER_VRAM 0
#define NVIF_CHAN_V0_INST_APER_HOST 1
#define NVIF_CHAN_V0_INST_APER_NCOH 2
#define NVIF_CHAN_V0_INST_APER_INST 0xff
__u8 aper;
__u64 inst;
__u8 name[];
} v0;
};
union nvif_chan_event_args {
struct nvif_chan_event_v0 {
__u8 version;
......
/* SPDX-License-Identifier: MIT */
#ifndef __NVIF_IF0021_H__
#define __NVIF_IF0021_H__
union nvif_cgrp_args {
struct nvif_cgrp_v0 {
__u8 version;
__u8 namelen;
__u8 runlist;
__u8 pad03[3];
__u16 cgid;
__u64 vmm;
__u8 name[];
} v0;
};
#endif
......@@ -16,7 +16,8 @@ struct nvkm_chan {
struct nvkm_gpuobj *inst;
struct nvkm_vmm *vmm;
union { int id; int chid; }; /*FIXME: remove later */
struct nvkm_gpuobj *push;
int id;
struct {
struct nvkm_memory *mem;
......@@ -35,11 +36,7 @@ struct nvkm_chan {
atomic_t errored;
struct list_head cctxs;
struct nvkm_object object;
struct list_head head;
struct nvkm_gpuobj *push;
};
struct nvkm_chan *nvkm_chan_get_chid(struct nvkm_engine *, int id, unsigned long *irqflags);
......
......@@ -27,7 +27,6 @@
#include <nvif/ioctl.h>
#include <nvif/class.h>
#include <nvif/cl0002.h>
#include <nvif/cla06f.h>
#include <nvif/unpack.h>
#include "nouveau_drv.h"
......
......@@ -25,13 +25,7 @@
#include <nvif/class.h>
#include <nvif/cl0002.h>
#include <nvif/cl006b.h>
#include <nvif/cl506f.h>
#include <nvif/cl906f.h>
#include <nvif/cla06f.h>
#include <nvif/clc36f.h>
#include <nvif/if0020.h>
#include <nvif/ioctl.h>
#include "nouveau_drv.h"
#include "nouveau_dma.h"
......@@ -101,6 +95,7 @@ nouveau_channel_del(struct nouveau_channel **pchan)
nvif_object_dtor(&chan->vram);
nvif_event_dtor(&chan->kill);
nvif_object_dtor(&chan->user);
nvif_mem_dtor(&chan->mem_userd);
nvif_object_dtor(&chan->push.ctxdma);
nouveau_vma_del(&chan->push.vma);
nouveau_bo_unmap(chan->push.buffer);
......@@ -250,134 +245,112 @@ nouveau_channel_prep(struct nouveau_drm *drm, struct nvif_device *device,
}
static int
nouveau_channel_ind(struct nouveau_drm *drm, struct nvif_device *device,
u64 runlist, bool priv, struct nouveau_channel **pchan)
nouveau_channel_ctor(struct nouveau_drm *drm, struct nvif_device *device, bool priv, u64 runm,
struct nouveau_channel **pchan)
{
static const u16 oclasses[] = { AMPERE_CHANNEL_GPFIFO_B,
TURING_CHANNEL_GPFIFO_A,
VOLTA_CHANNEL_GPFIFO_A,
PASCAL_CHANNEL_GPFIFO_A,
MAXWELL_CHANNEL_GPFIFO_A,
KEPLER_CHANNEL_GPFIFO_B,
KEPLER_CHANNEL_GPFIFO_A,
FERMI_CHANNEL_GPFIFO,
G82_CHANNEL_GPFIFO,
NV50_CHANNEL_GPFIFO,
0 };
const u16 *oclass = oclasses;
union {
struct nv50_channel_gpfifo_v0 nv50;
struct fermi_channel_gpfifo_v0 fermi;
struct kepler_channel_gpfifo_a_v0 kepler;
struct volta_channel_gpfifo_a_v0 volta;
static const struct {
s32 oclass;
int version;
} hosts[] = {
{ AMPERE_CHANNEL_GPFIFO_B, 0 },
{ TURING_CHANNEL_GPFIFO_A, 0 },
{ VOLTA_CHANNEL_GPFIFO_A, 0 },
{ PASCAL_CHANNEL_GPFIFO_A, 0 },
{ MAXWELL_CHANNEL_GPFIFO_A, 0 },
{ KEPLER_CHANNEL_GPFIFO_B, 0 },
{ KEPLER_CHANNEL_GPFIFO_A, 0 },
{ FERMI_CHANNEL_GPFIFO , 0 },
{ G82_CHANNEL_GPFIFO , 0 },
{ NV50_CHANNEL_GPFIFO , 0 },
{ NV40_CHANNEL_DMA , 0 },
{ NV17_CHANNEL_DMA , 0 },
{ NV10_CHANNEL_DMA , 0 },
{ NV03_CHANNEL_DMA , 0 },
{}
};
struct {
struct nvif_chan_v0 chan;
char name[TASK_COMM_LEN+16];
} args;
struct nouveau_cli *cli = (void *)device->object.client;
struct nouveau_channel *chan;
u32 size;
int ret;
const u64 plength = 0x10000;
const u64 ioffset = plength;
const u64 ilength = 0x02000;
char name[TASK_COMM_LEN];
int cid, ret;
u64 size;
cid = nvif_mclass(&device->object, hosts);
if (cid < 0)
return cid;
if (hosts[cid].oclass < NV50_CHANNEL_GPFIFO)
size = plength;
else
size = ioffset + ilength;
/* allocate dma push buffer */
ret = nouveau_channel_prep(drm, device, 0x12000, &chan);
ret = nouveau_channel_prep(drm, device, size, &chan);
*pchan = chan;
if (ret)
return ret;
/* create channel object */
do {
if (oclass[0] >= VOLTA_CHANNEL_GPFIFO_A) {
args.volta.version = 0;
args.volta.ilength = 0x02000;
args.volta.ioffset = 0x10000 + chan->push.addr;
args.volta.runlist = runlist;
args.volta.vmm = nvif_handle(&chan->vmm->vmm.object);
args.volta.priv = priv;
size = sizeof(args.volta);
} else
if (oclass[0] >= KEPLER_CHANNEL_GPFIFO_A) {
args.kepler.version = 0;
args.kepler.ilength = 0x02000;
args.kepler.ioffset = 0x10000 + chan->push.addr;
args.kepler.runlist = runlist;
args.kepler.vmm = nvif_handle(&chan->vmm->vmm.object);
args.kepler.priv = priv;
size = sizeof(args.kepler);
} else
if (oclass[0] >= FERMI_CHANNEL_GPFIFO) {
args.fermi.version = 0;
args.fermi.ilength = 0x02000;
args.fermi.ioffset = 0x10000 + chan->push.addr;
args.fermi.vmm = nvif_handle(&chan->vmm->vmm.object);
size = sizeof(args.fermi);
} else {
args.nv50.version = 0;
args.nv50.ilength = 0x02000;
args.nv50.ioffset = 0x10000 + chan->push.addr;
args.nv50.pushbuf = nvif_handle(&chan->push.ctxdma);
args.nv50.vmm = nvif_handle(&chan->vmm->vmm.object);
size = sizeof(args.nv50);
}
ret = nvif_object_ctor(&device->object, "abi16ChanUser", 0,
*oclass++, &args, size, &chan->user);
if (ret == 0) {
if (chan->user.oclass >= VOLTA_CHANNEL_GPFIFO_A) {
chan->chid = args.volta.chid;
chan->inst = args.volta.inst;
chan->token = args.volta.token;
} else
if (chan->user.oclass >= KEPLER_CHANNEL_GPFIFO_A) {
chan->chid = args.kepler.chid;
chan->inst = args.kepler.inst;
} else
if (chan->user.oclass >= FERMI_CHANNEL_GPFIFO) {
chan->chid = args.fermi.chid;
} else {
chan->chid = args.nv50.chid;
}
args.chan.version = 0;
args.chan.namelen = sizeof(args.name);
args.chan.runlist = __ffs64(runm);
args.chan.runq = 0;
args.chan.priv = priv;
args.chan.devm = BIT(0);
if (hosts[cid].oclass < NV50_CHANNEL_GPFIFO) {
args.chan.vmm = 0;
args.chan.ctxdma = nvif_handle(&chan->push.ctxdma);
args.chan.offset = chan->push.addr;
args.chan.length = 0;
} else {
args.chan.vmm = nvif_handle(&chan->vmm->vmm.object);
if (hosts[cid].oclass < FERMI_CHANNEL_GPFIFO)
args.chan.ctxdma = nvif_handle(&chan->push.ctxdma);
else
args.chan.ctxdma = 0;
args.chan.offset = ioffset + chan->push.addr;
args.chan.length = ilength;
}
args.chan.huserd = 0;
args.chan.ouserd = 0;
/* allocate userd */
if (hosts[cid].oclass >= VOLTA_CHANNEL_GPFIFO_A) {
ret = nvif_mem_ctor(&cli->mmu, "abi16ChanUSERD", NVIF_CLASS_MEM_GF100,
NVIF_MEM_VRAM | NVIF_MEM_COHERENT | NVIF_MEM_MAPPABLE,
0, PAGE_SIZE, NULL, 0, &chan->mem_userd);
if (ret)
return ret;
}
} while (*oclass);
nouveau_channel_del(pchan);
return ret;
}
args.chan.huserd = nvif_handle(&chan->mem_userd.object);
args.chan.ouserd = 0;
static int
nouveau_channel_dma(struct nouveau_drm *drm, struct nvif_device *device,
struct nouveau_channel **pchan)
{
static const u16 oclasses[] = { NV40_CHANNEL_DMA,
NV17_CHANNEL_DMA,
NV10_CHANNEL_DMA,
NV03_CHANNEL_DMA,
0 };
const u16 *oclass = oclasses;
struct nv03_channel_dma_v0 args;
struct nouveau_channel *chan;
int ret;
chan->userd = &chan->mem_userd.object;
} else {
chan->userd = &chan->user;
}
/* allocate dma push buffer */
ret = nouveau_channel_prep(drm, device, 0x10000, &chan);
*pchan = chan;
if (ret)
return ret;
get_task_comm(name, current);
snprintf(args.name, sizeof(args.name), "%s[%d]", name, task_pid_nr(current));
/* create channel object */
args.version = 0;
args.pushbuf = nvif_handle(&chan->push.ctxdma);
args.offset = chan->push.addr;
do {
ret = nvif_object_ctor(&device->object, "abi16ChanUser", 0,
*oclass++, &args, sizeof(args),
&chan->user);
if (ret == 0) {
chan->chid = args.chid;
return ret;
}
} while (ret && *oclass);
ret = nvif_object_ctor(&device->object, "abi16ChanUser", 0, hosts[cid].oclass,
&args, sizeof(args), &chan->user);
if (ret) {
nouveau_channel_del(pchan);
return ret;
}
nouveau_channel_del(pchan);
return ret;
chan->runlist = args.chan.runlist;
chan->chid = args.chan.chid;
chan->inst = args.chan.inst;
chan->token = args.chan.token;
return 0;
}
static int
......@@ -388,7 +361,7 @@ nouveau_channel_init(struct nouveau_channel *chan, u32 vram, u32 gart)
struct nv_dma_v0 args = {};
int ret, i;
ret = nvif_object_map(&chan->user, NULL, 0);
ret = nvif_object_map(chan->userd, NULL, 0);
if (ret)
return ret;
......@@ -518,15 +491,10 @@ nouveau_channel_new(struct nouveau_drm *drm, struct nvif_device *device,
struct nouveau_cli *cli = (void *)device->object.client;
int ret;
/* hack until fencenv50 is fixed, and agp access relaxed */
ret = nouveau_channel_ind(drm, device, runm, priv, pchan);
ret = nouveau_channel_ctor(drm, device, priv, runm, pchan);
if (ret) {
NV_PRINTK(dbg, cli, "ib channel create, %d\n", ret);
ret = nouveau_channel_dma(drm, device, pchan);
if (ret) {
NV_PRINTK(dbg, cli, "dma channel create, %d\n", ret);
return ret;
}
NV_PRINTK(dbg, cli, "channel create, %d\n", ret);
return ret;
}
ret = nouveau_channel_init(*pchan, vram, gart);
......
......@@ -16,6 +16,9 @@ struct nouveau_channel {
struct nouveau_drm *drm;
struct nouveau_vmm *vmm;
struct nvif_mem mem_userd;
struct nvif_object *userd;
int runlist;
int chid;
u64 inst;
......
......@@ -42,9 +42,9 @@ READ_GET(struct nouveau_channel *chan, uint64_t *prev_get, int *timeout)
{
uint64_t val;
val = nvif_rd32(&chan->user, chan->user_get);
val = nvif_rd32(chan->userd, chan->user_get);
if (chan->user_get_hi)
val |= (uint64_t)nvif_rd32(&chan->user, chan->user_get_hi) << 32;
val |= (uint64_t)nvif_rd32(chan->userd, chan->user_get_hi) << 32;
/* reset counter as long as GET is still advancing, this is
* to avoid misdetecting a GPU lockup if the GPU happens to
......@@ -86,7 +86,7 @@ nv50_dma_push(struct nouveau_channel *chan, u64 offset, int length)
/* Flush writes. */
nouveau_bo_rd32(pb, 0);
nvif_wr32(&chan->user, 0x8c, chan->dma.ib_put);
nvif_wr32(chan->userd, 0x8c, chan->dma.ib_put);
if (user->func && user->func->doorbell)
user->func->doorbell(user, chan->token);
chan->dma.ib_free--;
......@@ -98,7 +98,7 @@ nv50_dma_push_wait(struct nouveau_channel *chan, int count)
uint32_t cnt = 0, prev_get = 0;
while (chan->dma.ib_free < count) {
uint32_t get = nvif_rd32(&chan->user, 0x88);
uint32_t get = nvif_rd32(chan->userd, 0x88);
if (get != prev_get) {
prev_get = get;
cnt = 0;
......
......@@ -50,7 +50,6 @@
#include <nvif/class.h>
#include <nvif/cl0002.h>
#include <nvif/cla06f.h>
#include "nouveau_drv.h"
#include "nouveau_dma.h"
......
......@@ -25,19 +25,5 @@ nvkm-y += nvkm/engine/fifo/gv100.o
nvkm-y += nvkm/engine/fifo/tu102.o
nvkm-y += nvkm/engine/fifo/ga102.o
nvkm-y += nvkm/engine/fifo/channv50.o
nvkm-y += nvkm/engine/fifo/chang84.o
nvkm-y += nvkm/engine/fifo/dmanv04.o
nvkm-y += nvkm/engine/fifo/dmanv10.o
nvkm-y += nvkm/engine/fifo/dmanv17.o
nvkm-y += nvkm/engine/fifo/dmanv40.o
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/gpfifotu102.o
nvkm-y += nvkm/engine/fifo/ucgrp.o
nvkm-y += nvkm/engine/fifo/uchan.o
......@@ -59,6 +59,9 @@ nvkm_fifo_class_new(struct nvkm_device *device, const struct nvkm_oclass *oclass
{
struct nvkm_fifo *fifo = nvkm_fifo(oclass->engine);
if (oclass->engn == &fifo->func->cgrp.user)
return nvkm_ucgrp_new(fifo, oclass, argv, argc, pobject);
if (oclass->engn == &fifo->func->chan.user)
return nvkm_uchan_new(fifo, NULL, oclass, argv, argc, pobject);
......@@ -75,9 +78,20 @@ 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_func_cgrp *cgrp = &fifo->func->cgrp;
const struct nvkm_fifo_func_chan *chan = &fifo->func->chan;
int c = 0;
/* *_CHANNEL_GROUP_* */
if (cgrp->user.oclass) {
if (c++ == index) {
oclass->base = cgrp->user;
oclass->engn = &fifo->func->cgrp.user;
*class = &nvkm_fifo_class;
return 0;
}
}
/* *_CHANNEL_DMA, *_CHANNEL_GPFIFO_* */
if (chan->user.oclass) {
if (c++ == index) {
......@@ -264,9 +278,6 @@ nvkm_fifo_oneinit(struct nvkm_engine *engine)
return ret;
}
if (fifo->func->oneinit)
return fifo->func->oneinit(fifo);
return 0;
}
......@@ -282,7 +293,6 @@ nvkm_fifo_dtor(struct nvkm_engine *engine)
struct nvkm_fifo *fifo = nvkm_fifo(engine);
struct nvkm_runl *runl, *runt;
struct nvkm_runq *runq, *rtmp;
void *data = fifo;
if (fifo->userd.bar1)
nvkm_vmm_put(nvkm_bar_bar1_vmm(engine->subdev.device), &fifo->userd.bar1);
......@@ -296,11 +306,9 @@ nvkm_fifo_dtor(struct nvkm_engine *engine)
nvkm_chid_unref(&fifo->cgid);
nvkm_chid_unref(&fifo->chid);
if (fifo->func->dtor)
data = fifo->func->dtor(fifo);
nvkm_event_fini(&fifo->nonstall.event);
mutex_destroy(&fifo->mutex);
return data;
return fifo;
}
static const struct nvkm_engine_func
......@@ -315,11 +323,15 @@ nvkm_fifo = {
};
int
nvkm_fifo_ctor(const struct nvkm_fifo_func *func, struct nvkm_device *device,
enum nvkm_subdev_type type, int inst, struct nvkm_fifo *fifo)
nvkm_fifo_new_(const struct nvkm_fifo_func *func, struct nvkm_device *device,
enum nvkm_subdev_type type, int inst, struct nvkm_fifo **pfifo)
{
struct nvkm_fifo *fifo;
int ret;
if (!(fifo = *pfifo = kzalloc(sizeof(*fifo), GFP_KERNEL)))
return -ENOMEM;
fifo->func = func;
INIT_LIST_HEAD(&fifo->runqs);
INIT_LIST_HEAD(&fifo->runls);
......
......@@ -28,7 +28,6 @@
#include "runl.h"
#include "priv.h"
#include <core/oproxy.h>
#include <core/ramht.h>
#include <subdev/mmu.h>
#include <engine/dma.h>
......@@ -283,16 +282,6 @@ nvkm_chan_del(struct nvkm_chan **pchan)
nvkm_cgrp_unref(&chan->cgrp);
}
chan = nvkm_object_dtor(&chan->object);
kfree(chan);
}
static void *
nvkm_fifo_chan_dtor(struct nvkm_object *object)
{
struct nvkm_fifo_chan *chan = nvkm_fifo_chan(object);
void *data = chan->func->dtor(chan);
if (chan->vmm) {
nvkm_vmm_part(chan->vmm, chan->inst->memory);
nvkm_vmm_unref(&chan->vmm);
......@@ -300,8 +289,7 @@ nvkm_fifo_chan_dtor(struct nvkm_object *object)
nvkm_gpuobj_del(&chan->push);
nvkm_gpuobj_del(&chan->inst);
kfree(chan->func);
return data;
kfree(chan);
}
void
......@@ -354,51 +342,42 @@ nvkm_chan_get_chid(struct nvkm_engine *engine, int id, unsigned long *pirqflags)
return NULL;
}
static const struct nvkm_object_func
nvkm_fifo_chan_func = {
.dtor = nvkm_fifo_chan_dtor,
};
int
nvkm_fifo_chan_ctor(const struct nvkm_fifo_chan_func *fn,
struct nvkm_fifo *fifo, u32 size, u32 align, bool zero,
u64 hvmm, u64 push, u32 engm, int bar, u32 base,
u32 user, const struct nvkm_oclass *oclass,
struct nvkm_fifo_chan *chan)
nvkm_chan_new_(const struct nvkm_chan_func *func, struct nvkm_runl *runl, int runq,
struct nvkm_cgrp *cgrp, const char *name, bool priv, u32 devm, struct nvkm_vmm *vmm,
struct nvkm_dmaobj *dmaobj, u64 offset, u64 length,
struct nvkm_memory *userd, u64 ouserd, struct nvkm_chan **pchan)
{
struct nvkm_chan_func *func;
struct nvkm_client *client = oclass->client;
struct nvkm_fifo *fifo = runl->fifo;
struct nvkm_device *device = fifo->engine.subdev.device;
struct nvkm_dmaobj *dmaobj;
struct nvkm_cgrp *cgrp = NULL;
struct nvkm_runl *runl;
struct nvkm_engn *engn = NULL;
struct nvkm_vmm *vmm = NULL;
struct nvkm_chan *chan;
int ret;
nvkm_runl_foreach(runl, fifo) {
engn = nvkm_runl_find_engn(engn, runl, engm & BIT(engn->id));
if (engn)
break;
}
if (!engn)
/* Validate arguments against class requirements. */
if ((runq && runq >= runl->func->runqs) ||
(!func->inst->vmm != !vmm) ||
((func->userd->bar < 0) == !userd) ||
(!func->ramfc->ctxdma != !dmaobj) ||
((func->ramfc->devm < devm) && devm != BIT(0)) ||
(!func->ramfc->priv && priv)) {
RUNL_DEBUG(runl, "args runq:%d:%d vmm:%d:%p userd:%d:%p "
"push:%d:%p devm:%08x:%08x priv:%d:%d",
runl->func->runqs, runq, func->inst->vmm, vmm,
func->userd->bar < 0, userd, func->ramfc->ctxdma, dmaobj,
func->ramfc->devm, devm, func->ramfc->priv, priv);
return -EINVAL;
}
/*FIXME: temp kludge to ease transition, remove later */
if (!(func = kmalloc(sizeof(*func), GFP_KERNEL)))
if (!(chan = *pchan = kzalloc(sizeof(*chan), GFP_KERNEL)))
return -ENOMEM;
*func = *fifo->func->chan.func;
func->dtor = fn->dtor;
chan->func = func;
strscpy(chan->name, name, sizeof(chan->name));
chan->runq = runq;
chan->id = -1;
spin_lock_init(&chan->lock);
atomic_set(&chan->blocked, 1);
atomic_set(&chan->errored, 0);
nvkm_object_ctor(&nvkm_fifo_chan_func, oclass, &chan->object);
INIT_LIST_HEAD(&chan->cctxs);
INIT_LIST_HEAD(&chan->head);
......@@ -437,10 +416,6 @@ nvkm_fifo_chan_ctor(const struct nvkm_fifo_chan_func *fn,
/* Initialise virtual address-space. */
if (func->inst->vmm) {
struct nvkm_vmm *vmm = nvkm_uvmm_search(client, hvmm);
if (IS_ERR(vmm))
return PTR_ERR(vmm);
if (WARN_ON(vmm->mmu != device->mmu))
return -EINVAL;
......@@ -455,10 +430,6 @@ nvkm_fifo_chan_ctor(const struct nvkm_fifo_chan_func *fn,
/* Allocate HW ctxdma for push buffer. */
if (func->ramfc->ctxdma) {
dmaobj = nvkm_dmaobj_search(client, push);
if (IS_ERR(dmaobj))
return PTR_ERR(dmaobj);
ret = nvkm_object_bind(&dmaobj->object, chan->inst, -16, &chan->push);
if (ret) {
RUNL_DEBUG(runl, "bind %d", ret);
......@@ -477,7 +448,20 @@ nvkm_fifo_chan_ctor(const struct nvkm_fifo_chan_func *fn,
cgrp->id = chan->id;
/* Initialise USERD. */
if (1) {
if (func->userd->bar < 0) {
if (ouserd + chan->func->userd->size >= nvkm_memory_size(userd)) {
RUNL_DEBUG(runl, "ouserd %llx", ouserd);
return -EINVAL;
}
ret = nvkm_memory_kmap(userd, &chan->userd.mem);
if (ret) {
RUNL_DEBUG(runl, "userd %d", ret);
return ret;
}
chan->userd.base = ouserd;
} else {
chan->userd.mem = nvkm_memory_ref(fifo->userd.mem);
chan->userd.base = chan->id * chan->func->userd->size;
}
......@@ -485,5 +469,12 @@ nvkm_fifo_chan_ctor(const struct nvkm_fifo_chan_func *fn,
if (chan->func->userd->clear)
chan->func->userd->clear(chan);
/* Initialise RAMFC. */
ret = chan->func->ramfc->write(chan, offset, length, devm, priv);
if (ret) {
RUNL_DEBUG(runl, "ramfc %d", ret);
return ret;
}
return 0;
}
/* SPDX-License-Identifier: MIT */
#ifndef __NVKM_CHAN_H__
#define __NVKM_CHAN_H__
#define nvkm_chan(p) container_of((p), struct nvkm_chan, object) /*FIXME: remove later */
#include <engine/fifo.h>
struct nvkm_dmaobj;
struct nvkm_engn;
struct nvkm_runl;
extern const struct nvkm_event_func nvkm_chan_event;
......@@ -50,14 +51,12 @@ struct nvkm_chan_func {
void (*stop)(struct nvkm_chan *);
void (*preempt)(struct nvkm_chan *);
u32 (*doorbell_handle)(struct nvkm_chan *);
void *(*dtor)(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,
u32 engm, int bar, u32 base, u32 user,
const struct nvkm_oclass *, struct nvkm_fifo_chan *);
int nvkm_chan_new_(const struct nvkm_chan_func *, struct nvkm_runl *, int runq, struct nvkm_cgrp *,
const char *name, bool priv, u32 devm, struct nvkm_vmm *, struct nvkm_dmaobj *,
u64 offset, u64 length, struct nvkm_memory *userd, u64 userd_bar1,
struct nvkm_chan **);
void nvkm_chan_del(struct nvkm_chan **);
void nvkm_chan_allow(struct nvkm_chan *);
void nvkm_chan_block(struct nvkm_chan *);
......
/*
* Copyright 2012 Red Hat Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Authors: Ben Skeggs
*/
#include "channv50.h"
#include <core/client.h>
#include <core/ramht.h>
#include <subdev/mmu.h>
#include <subdev/timer.h>
#include <nvif/cl826e.h>
static const struct nvkm_fifo_chan_func
g84_fifo_chan_func = {
.dtor = nv50_fifo_chan_dtor,
};
int
g84_fifo_chan_ctor(struct nv50_fifo *fifo, u64 vmm, u64 push,
const struct nvkm_oclass *oclass,
struct nv50_fifo_chan *chan)
{
int ret;
if (!vmm)
return -EINVAL;
ret = nvkm_fifo_chan_ctor(&g84_fifo_chan_func, &fifo->base,
0x10000, 0x1000, false, vmm, push,
BIT(G84_FIFO_ENGN_SW) |
BIT(G84_FIFO_ENGN_GR) |
BIT(G84_FIFO_ENGN_MPEG) |
BIT(G84_FIFO_ENGN_MSPPP) |
BIT(G84_FIFO_ENGN_ME) |
BIT(G84_FIFO_ENGN_CE0) |
BIT(G84_FIFO_ENGN_VP) |
BIT(G84_FIFO_ENGN_MSPDEC) |
BIT(G84_FIFO_ENGN_CIPHER) |
BIT(G84_FIFO_ENGN_SEC) |
BIT(G84_FIFO_ENGN_VIC) |
BIT(G84_FIFO_ENGN_BSP) |
BIT(G84_FIFO_ENGN_MSVLD) |
BIT(G84_FIFO_ENGN_DMA),
0, 0xc00000, 0x2000, oclass, &chan->base);
return ret;
}
/* SPDX-License-Identifier: MIT */
#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_chan {
struct nvkm_fifo_chan base;
#define GF100_FIFO_ENGN_GR 0
#define GF100_FIFO_ENGN_MSPDEC 1
#define GF100_FIFO_ENGN_MSPPP 2
#define GF100_FIFO_ENGN_MSVLD 3
#define GF100_FIFO_ENGN_CE0 4
#define GF100_FIFO_ENGN_CE1 5
#define GF100_FIFO_ENGN_SW 15
};
extern const struct nvkm_fifo_chan_oclass gf100_fifo_gpfifo_oclass;
#endif
/* SPDX-License-Identifier: MIT */
#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_chan {
struct nvkm_fifo_chan base;
int runl;
#define GK104_FIFO_ENGN_SW 15
};
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 *);
int gv100_fifo_gpfifo_new(struct gk104_fifo *, const struct nvkm_oclass *,
void *data, u32 size, struct nvkm_object **);
int gv100_fifo_gpfifo_new_(const struct nvkm_fifo_chan_func *,
struct gk104_fifo *, u64 *, u16 *, u64, u64, u64,
u64 *, bool, u32 *, const struct nvkm_oclass *,
struct nvkm_object **);
int tu102_fifo_gpfifo_new(struct gk104_fifo *, const struct nvkm_oclass *,
void *data, u32 size, struct nvkm_object **);
#endif
/* SPDX-License-Identifier: MIT */
#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;
#define NV04_FIFO_ENGN_SW 0
#define NV04_FIFO_ENGN_GR 1
#define NV04_FIFO_ENGN_MPEG 2
#define NV04_FIFO_ENGN_DMA 3
};
extern const struct nvkm_fifo_chan_func nv04_fifo_dma_func;
void *nv04_fifo_dma_dtor(struct nvkm_fifo_chan *);
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
/* SPDX-License-Identifier: MIT */
#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_chan {
struct nvkm_fifo_chan base;
#define NV50_FIFO_ENGN_SW 0
#define NV50_FIFO_ENGN_GR 1
#define NV50_FIFO_ENGN_MPEG 2
#define NV50_FIFO_ENGN_DMA 3
#define G84_FIFO_ENGN_SW 0
#define G84_FIFO_ENGN_GR 1
#define G84_FIFO_ENGN_MPEG 2
#define G84_FIFO_ENGN_MSPPP 2
#define G84_FIFO_ENGN_ME 3
#define G84_FIFO_ENGN_CE0 3
#define G84_FIFO_ENGN_VP 4
#define G84_FIFO_ENGN_MSPDEC 4
#define G84_FIFO_ENGN_CIPHER 5
#define G84_FIFO_ENGN_SEC 5
#define G84_FIFO_ENGN_VIC 5
#define G84_FIFO_ENGN_BSP 6
#define G84_FIFO_ENGN_MSVLD 6
#define G84_FIFO_ENGN_DMA 7
};
int nv50_fifo_chan_ctor(struct nv50_fifo *, u64 vmm, u64 push,
const struct nvkm_oclass *, struct nv50_fifo_chan *);
void *nv50_fifo_chan_dtor(struct nvkm_fifo_chan *);
int g84_fifo_chan_ctor(struct nv50_fifo *, u64 vmm, u64 push,
const struct nvkm_oclass *, struct nv50_fifo_chan *);
extern const struct nvkm_fifo_chan_oclass nv50_fifo_gpfifo_oclass;
extern const struct nvkm_fifo_chan_oclass g84_fifo_gpfifo_oclass;
#endif
/*
* Copyright 2012 Red Hat Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Authors: Ben Skeggs
*/
#include "channv04.h"
#include "regsnv04.h"
#include <core/client.h>
#include <core/ramht.h>
#include <subdev/instmem.h>
#include <nvif/cl006b.h>
#include <nvif/unpack.h>
void *
nv04_fifo_dma_dtor(struct nvkm_fifo_chan *base)
{
struct nv04_fifo_chan *chan = nv04_fifo_chan(base);
return chan;
}
const struct nvkm_fifo_chan_func
nv04_fifo_dma_func = {
.dtor = nv04_fifo_dma_dtor,
};
static int
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 = nv04_fifo(base);
struct nv04_fifo_chan *chan = NULL;
int ret = -ENOSYS;
nvif_ioctl(parent, "create channel dma size %d\n", size);
if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
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;
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,
BIT(NV04_FIFO_ENGN_SW) |
BIT(NV04_FIFO_ENGN_GR) |
BIT(NV04_FIFO_ENGN_DMA),
0, 0x800000, 0x10000, oclass, &chan->base);
if (ret)
return ret;
args->v0.chid = chan->base.chid;
chan->base.func->ramfc->write(&chan->base, args->v0.offset, 0, BIT(0), false);
return 0;
}
const struct nvkm_fifo_chan_oclass
nv04_fifo_dma_oclass = {
.ctor = nv04_fifo_dma_new,
};
/*
* Copyright 2012 Red Hat Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Authors: Ben Skeggs
*/
#include "channv04.h"
#include "regsnv04.h"
#include <core/client.h>
#include <core/gpuobj.h>
#include <subdev/instmem.h>
#include <nvif/cl006b.h>
#include <nvif/unpack.h>
static int
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 = nv04_fifo(base);
struct nv04_fifo_chan *chan = NULL;
int ret = -ENOSYS;
nvif_ioctl(parent, "create channel dma size %d\n", size);
if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
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;
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,
BIT(NV04_FIFO_ENGN_SW) |
BIT(NV04_FIFO_ENGN_GR) |
BIT(NV04_FIFO_ENGN_DMA),
0, 0x800000, 0x10000, oclass, &chan->base);
if (ret)
return ret;
args->v0.chid = chan->base.chid;
chan->base.func->ramfc->write(&chan->base, args->v0.offset, 0, BIT(0), false);
return 0;
}
const struct nvkm_fifo_chan_oclass
nv10_fifo_dma_oclass = {
.ctor = nv10_fifo_dma_new,
};
/*
* Copyright 2012 Red Hat Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Authors: Ben Skeggs
*/
#include "channv04.h"
#include "regsnv04.h"
#include <core/client.h>
#include <core/gpuobj.h>
#include <subdev/instmem.h>
#include <nvif/cl006b.h>
#include <nvif/unpack.h>
static int
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 = nv04_fifo(base);
struct nv04_fifo_chan *chan = NULL;
int ret = -ENOSYS;
nvif_ioctl(parent, "create channel dma size %d\n", size);
if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
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;
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,
BIT(NV04_FIFO_ENGN_SW) |
BIT(NV04_FIFO_ENGN_GR) |
BIT(NV04_FIFO_ENGN_MPEG) | /* NV31- */
BIT(NV04_FIFO_ENGN_DMA),
0, 0x800000, 0x10000, oclass, &chan->base);
if (ret)
return ret;
args->v0.chid = chan->base.chid;
chan->base.func->ramfc->write(&chan->base, args->v0.offset, 0, BIT(0), false);
return 0;
}
const struct nvkm_fifo_chan_oclass
nv17_fifo_dma_oclass = {
.ctor = nv17_fifo_dma_new,
};
/*
* Copyright 2012 Red Hat Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Authors: Ben Skeggs
*/
#include "channv04.h"
#include "regsnv04.h"
#include <core/client.h>
#include <core/ramht.h>
#include <subdev/instmem.h>
#include <nvif/cl006b.h>
#include <nvif/unpack.h>
static const struct nvkm_fifo_chan_func
nv40_fifo_dma_func = {
};
static int
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 = nv04_fifo(base);
struct nv04_fifo_chan *chan = NULL;
int ret = -ENOSYS;
nvif_ioctl(parent, "create channel dma size %d\n", size);
if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
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;
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,
BIT(NV04_FIFO_ENGN_SW) |
BIT(NV04_FIFO_ENGN_GR) |
BIT(NV04_FIFO_ENGN_MPEG) |
BIT(NV04_FIFO_ENGN_DMA),
0, 0xc00000, 0x1000, oclass, &chan->base);
if (ret)
return ret;
args->v0.chid = chan->base.chid;
chan->base.func->ramfc->write(&chan->base, args->v0.offset, 0, BIT(0), false);
return 0;
}
const struct nvkm_fifo_chan_oclass
nv40_fifo_dma_oclass = {
.ctor = nv40_fifo_dma_new,
};
......@@ -21,6 +21,7 @@
*
* Authors: Ben Skeggs
*/
#include "priv.h"
#include "cgrp.h"
#include "chan.h"
#include "runl.h"
......@@ -28,9 +29,6 @@
#include <core/ramht.h>
#include <subdev/timer.h>
#include "nv50.h"
#include "channv50.h"
#include <nvif/class.h>
static void
......@@ -210,7 +208,6 @@ g84_fifo_runl_ctor(struct nvkm_fifo *fifo)
static const struct nvkm_fifo_func
g84_fifo = {
.dtor = nv50_fifo_dtor,
.chid_nr = nv50_fifo_chid_nr,
.chid_ctor = nv50_fifo_chid_ctor,
.runl_ctor = g84_fifo_runl_ctor,
......@@ -223,12 +220,12 @@ g84_fifo = {
.engn = &g84_engn,
.engn_sw = &nv50_engn_sw,
.cgrp = {{ }, &nv04_cgrp },
.chan = {{ 0, 0, G82_CHANNEL_GPFIFO }, &g84_chan, .oclass = &g84_fifo_gpfifo_oclass },
.chan = {{ 0, 0, G82_CHANNEL_GPFIFO }, &g84_chan },
};
int
g84_fifo_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst,
struct nvkm_fifo **pfifo)
{
return nv50_fifo_new_(&g84_fifo, device, type, inst, pfifo);
return nvkm_fifo_new_(&g84_fifo, device, type, inst, pfifo);
}
......@@ -19,12 +19,10 @@
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#include "priv.h"
#include "chan.h"
#include "runl.h"
#include "nv50.h"
#include "channv50.h"
#include <nvif/class.h>
static int
......@@ -49,7 +47,6 @@ g98_fifo_runl_ctor(struct nvkm_fifo *fifo)
static const struct nvkm_fifo_func
g98_fifo = {
.dtor = nv50_fifo_dtor,
.chid_nr = nv50_fifo_chid_nr,
.chid_ctor = nv50_fifo_chid_ctor,
.runl_ctor = g98_fifo_runl_ctor,
......@@ -62,12 +59,12 @@ g98_fifo = {
.engn = &g84_engn,
.engn_sw = &nv50_engn_sw,
.cgrp = {{ }, &nv04_cgrp },
.chan = {{ 0, 0, G82_CHANNEL_GPFIFO }, &g84_chan, .oclass = &g84_fifo_gpfifo_oclass },
.chan = {{ 0, 0, G82_CHANNEL_GPFIFO }, &g84_chan },
};
int
g98_fifo_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst,
struct nvkm_fifo **pfifo)
{
return nv50_fifo_new_(&g98_fifo, device, type, inst, pfifo);
return nvkm_fifo_new_(&g98_fifo, device, type, inst, pfifo);
}
......@@ -29,7 +29,7 @@
#include <subdev/top.h>
#include <nvif/cl0080.h>
#include <nvif/clc36f.h>
#include <nvif/if0020.h>
#include <nvif/class.h>
struct ga102_fifo {
......@@ -148,9 +148,10 @@ static int
ga102_chan_new(struct nvkm_device *device,
const struct nvkm_oclass *oclass, void *argv, u32 argc, struct nvkm_object **pobject)
{
struct volta_channel_gpfifo_a_v0 *args = argv;
struct nvif_chan_v0 *args = argv;
struct nvkm_top_device *tdev;
struct nvkm_vmm *vmm;
struct nvkm_memory *userd;
struct ga102_chan *chan;
int ret;
......@@ -194,9 +195,9 @@ ga102_chan_new(struct nvkm_device *device,
nvkm_kmap(chan->inst);
nvkm_wo32(chan->inst, 0x010, 0x0000face);
nvkm_wo32(chan->inst, 0x030, 0x7ffff902);
nvkm_wo32(chan->inst, 0x048, lower_32_bits(args->ioffset));
nvkm_wo32(chan->inst, 0x04c, upper_32_bits(args->ioffset) |
(order_base_2(args->ilength / 8) << 16));
nvkm_wo32(chan->inst, 0x048, lower_32_bits(args->offset));
nvkm_wo32(chan->inst, 0x04c, upper_32_bits(args->offset) |
(order_base_2(args->length / 8) << 16));
nvkm_wo32(chan->inst, 0x084, 0x20400000);
nvkm_wo32(chan->inst, 0x094, 0x30000001);
nvkm_wo32(chan->inst, 0x0ac, 0x00020000);
......@@ -209,7 +210,12 @@ ga102_chan_new(struct nvkm_device *device,
nvkm_wo32(chan->inst, 0x224, upper_32_bits(nvkm_memory_bar2(chan->mthd)));
nvkm_done(chan->inst);
ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, 0x1000, 0x1000, true, &chan->user);
userd = nvkm_umem_search(oclass->client, args->huserd);
if (IS_ERR(userd))
return PTR_ERR(userd);
ret = nvkm_memory_kmap(userd, &chan->user);
nvkm_memory_unref(&userd);
if (ret)
return ret;
......
......@@ -21,19 +21,18 @@
*
* Authors: Ben Skeggs
*/
#include "priv.h"
#include "cgrp.h"
#include "chan.h"
#include "chid.h"
#include "runl.h"
#include "runq.h"
#include "gf100.h"
#include "changf100.h"
#include <core/gpuobj.h>
#include <subdev/bar.h>
#include <subdev/fault.h>
#include <subdev/mc.h>
#include <subdev/mmu.h>
#include <engine/sw.h>
#include <nvif/class.h>
......@@ -942,16 +941,8 @@ gf100_fifo_chid_ctor(struct nvkm_fifo *fifo, int nr)
return nvkm_chid_new(&nvkm_chan_event, &fifo->engine.subdev, nr, 0, nr, &fifo->chid);
}
static void *
gf100_fifo_dtor(struct nvkm_fifo *base)
{
struct gf100_fifo *fifo = gf100_fifo(base);
return fifo;
}
static const struct nvkm_fifo_func
gf100_fifo = {
.dtor = gf100_fifo_dtor,
.chid_nr = nv50_fifo_chid_nr,
.chid_ctor = gf100_fifo_chid_ctor,
.runq_nr = gf100_fifo_runq_nr,
......@@ -967,18 +958,12 @@ gf100_fifo = {
.runq = &gf100_runq,
.engn = &gf100_engn,
.cgrp = {{ }, &nv04_cgrp },
.chan = {{ 0, 0, FERMI_CHANNEL_GPFIFO }, &gf100_chan, .oclass = &gf100_fifo_gpfifo_oclass },
.chan = {{ 0, 0, FERMI_CHANNEL_GPFIFO }, &gf100_chan },
};
int
gf100_fifo_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst,
struct nvkm_fifo **pfifo)
{
struct gf100_fifo *fifo;
if (!(fifo = kzalloc(sizeof(*fifo), GFP_KERNEL)))
return -ENOMEM;
*pfifo = &fifo->base;
return nvkm_fifo_ctor(&gf100_fifo, device, type, inst, &fifo->base);
return nvkm_fifo_new_(&gf100_fifo, device, type, inst, pfifo);
}
/* SPDX-License-Identifier: MIT */
#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;
};
#endif
......@@ -21,17 +21,16 @@
*
* Authors: Ben Skeggs
*/
#include "priv.h"
#include "cgrp.h"
#include "chan.h"
#include "chid.h"
#include "runl.h"
#include "runq.h"
#include "gk104.h"
#include "cgrp.h"
#include "changk104.h"
#include <core/gpuobj.h>
#include <subdev/mc.h>
#include <subdev/mmu.h>
#include <subdev/top.h>
#include <nvif/class.h>
......@@ -805,56 +804,8 @@ gk104_fifo_chid_nr(struct nvkm_fifo *fifo)
return 4096;
}
int
gk104_fifo_oneinit(struct nvkm_fifo *base)
{
struct gk104_fifo *fifo = gk104_fifo(base);
struct nvkm_subdev *subdev = &fifo->base.engine.subdev;
struct nvkm_device *device = subdev->device;
struct nvkm_top_device *tdev;
/* Determine runlist configuration from topology device info. */
list_for_each_entry(tdev, &device->top->device, head) {
const int engn = tdev->engine;
if (engn < 0)
continue;
fifo->runlist[tdev->runlist].engm |= BIT(engn);
fifo->runlist[tdev->runlist].engm_sw |= BIT(engn);
if (tdev->type == NVKM_ENGINE_GR)
fifo->runlist[tdev->runlist].engm_sw |= BIT(GK104_FIFO_ENGN_SW);
fifo->runlist_nr = max(fifo->runlist_nr, tdev->runlist + 1);
}
return 0;
}
void *
gk104_fifo_dtor(struct nvkm_fifo *base)
{
struct gk104_fifo *fifo = gk104_fifo(base);
return fifo;
}
int
gk104_fifo_new_(const struct gk104_fifo_func *func, struct nvkm_device *device,
enum nvkm_subdev_type type, int inst, int nr, struct nvkm_fifo **pfifo)
{
struct gk104_fifo *fifo;
if (!(fifo = kzalloc(sizeof(*fifo), GFP_KERNEL)))
return -ENOMEM;
fifo->func = func;
*pfifo = &fifo->base;
return nvkm_fifo_ctor(func, device, type, inst, &fifo->base);
}
static const struct nvkm_fifo_func
gk104_fifo = {
.dtor = gk104_fifo_dtor,
.oneinit = gk104_fifo_oneinit,
.chid_nr = gk104_fifo_chid_nr,
.chid_ctor = gf100_fifo_chid_ctor,
.runq_nr = gf100_fifo_runq_nr,
......@@ -871,12 +822,12 @@ gk104_fifo = {
.engn = &gk104_engn,
.engn_ce = &gk104_engn_ce,
.cgrp = {{ }, &nv04_cgrp },
.chan = {{ 0, 0, KEPLER_CHANNEL_GPFIFO_A }, &gk104_chan, .ctor = &gk104_fifo_gpfifo_new },
.chan = {{ 0, 0, KEPLER_CHANNEL_GPFIFO_A }, &gk104_chan },
};
int
gk104_fifo_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst,
struct nvkm_fifo **pfifo)
{
return gk104_fifo_new_(&gk104_fifo, device, type, inst, 0, pfifo);
return nvkm_fifo_new_(&gk104_fifo, device, type, inst, pfifo);
}
/* SPDX-License-Identifier: MIT */
#ifndef __GK104_FIFO_H__
#define __GK104_FIFO_H__
#define gk104_fifo(p) container_of((p), struct gk104_fifo, base)
#include "priv.h"
struct nvkm_fifo_cgrp;
#include <subdev/mmu.h>
#define gk104_fifo_func nvkm_fifo_func
struct gk104_fifo_chan;
struct gk104_fifo {
const struct gk104_fifo_func *func;
struct nvkm_fifo base;
struct {
u32 engm;
u32 engm_sw;
} runlist[16];
int runlist_nr;
};
int gk104_fifo_new_(const struct gk104_fifo_func *, struct nvkm_device *, enum nvkm_subdev_type,
int index, int nr, struct nvkm_fifo **);
void *gk104_fifo_dtor(struct nvkm_fifo *base);
int gk104_fifo_oneinit(struct nvkm_fifo *);
#endif
......@@ -21,14 +21,12 @@
*
* Authors: Ben Skeggs
*/
#include "priv.h"
#include "cgrp.h"
#include "chan.h"
#include "chid.h"
#include "runl.h"
#include "gk104.h"
#include "changk104.h"
#include <core/memory.h>
#include <subdev/timer.h>
......@@ -107,8 +105,6 @@ gk110_fifo_chid_ctor(struct nvkm_fifo *fifo, int nr)
static const struct nvkm_fifo_func
gk110_fifo = {
.dtor = gk104_fifo_dtor,
.oneinit = gk104_fifo_oneinit,
.chid_nr = gk104_fifo_chid_nr,
.chid_ctor = gk110_fifo_chid_ctor,
.runq_nr = gf100_fifo_runq_nr,
......@@ -125,12 +121,12 @@ gk110_fifo = {
.engn = &gk104_engn,
.engn_ce = &gk104_engn_ce,
.cgrp = {{ 0, 0, KEPLER_CHANNEL_GROUP_A }, &gk110_cgrp },
.chan = {{ 0, 0, KEPLER_CHANNEL_GPFIFO_B }, &gk110_chan, .ctor = &gk104_fifo_gpfifo_new },
.chan = {{ 0, 0, KEPLER_CHANNEL_GPFIFO_B }, &gk110_chan },
};
int
gk110_fifo_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst,
struct nvkm_fifo **pfifo)
{
return gk104_fifo_new_(&gk110_fifo, device, type, inst, 0, pfifo);
return nvkm_fifo_new_(&gk110_fifo, device, type, inst, pfifo);
}
......@@ -21,9 +21,8 @@
*
* Authors: Ben Skeggs
*/
#include "priv.h"
#include "runq.h"
#include "gk104.h"
#include "changk104.h"
#include <nvif/class.h>
......@@ -51,8 +50,6 @@ gk208_fifo_chid_nr(struct nvkm_fifo *fifo)
static const struct nvkm_fifo_func
gk208_fifo = {
.dtor = gk104_fifo_dtor,
.oneinit = gk104_fifo_oneinit,
.chid_nr = gk208_fifo_chid_nr,
.chid_ctor = gk110_fifo_chid_ctor,
.runq_nr = gf100_fifo_runq_nr,
......@@ -69,12 +66,12 @@ gk208_fifo = {
.engn = &gk104_engn,
.engn_ce = &gk104_engn_ce,
.cgrp = {{ 0, 0, KEPLER_CHANNEL_GROUP_A }, &gk110_cgrp },
.chan = {{ 0, 0, KEPLER_CHANNEL_GPFIFO_A }, &gk110_chan, .ctor = &gk104_fifo_gpfifo_new },
.chan = {{ 0, 0, KEPLER_CHANNEL_GPFIFO_A }, &gk110_chan },
};
int
gk208_fifo_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst,
struct nvkm_fifo **pfifo)
{
return gk104_fifo_new_(&gk208_fifo, device, type, inst, 0, pfifo);
return nvkm_fifo_new_(&gk208_fifo, device, type, inst, pfifo);
}
......@@ -19,15 +19,12 @@
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#include "gk104.h"
#include "changk104.h"
#include "priv.h"
#include <nvif/class.h>
static const struct nvkm_fifo_func
gk20a_fifo = {
.dtor = gk104_fifo_dtor,
.oneinit = gk104_fifo_oneinit,
.chid_nr = nv50_fifo_chid_nr,
.chid_ctor = gk110_fifo_chid_ctor,
.runq_nr = gf100_fifo_runq_nr,
......@@ -44,12 +41,12 @@ gk20a_fifo = {
.engn = &gk104_engn,
.engn_ce = &gk104_engn_ce,
.cgrp = {{ }, &gk110_cgrp },
.chan = {{ 0, 0, KEPLER_CHANNEL_GPFIFO_A }, &gk110_chan, .ctor = &gk104_fifo_gpfifo_new },
.chan = {{ 0, 0, KEPLER_CHANNEL_GPFIFO_A }, &gk110_chan },
};
int
gk20a_fifo_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst,
struct nvkm_fifo **pfifo)
{
return gk104_fifo_new_(&gk20a_fifo, device, type, inst, 0, pfifo);
return nvkm_fifo_new_(&gk20a_fifo, device, type, inst, pfifo);
}
......@@ -24,8 +24,6 @@
#include "priv.h"
#include "chan.h"
#include "runl.h"
#include "gk104.h"
#include "changk104.h"
#include <core/gpuobj.h>
#include <subdev/fault.h>
......@@ -131,8 +129,6 @@ gm107_fifo_chid_nr(struct nvkm_fifo *fifo)
static const struct nvkm_fifo_func
gm107_fifo = {
.dtor = gk104_fifo_dtor,
.oneinit = gk104_fifo_oneinit,
.chid_nr = gm107_fifo_chid_nr,
.chid_ctor = gk110_fifo_chid_ctor,
.runq_nr = gf100_fifo_runq_nr,
......@@ -149,12 +145,12 @@ gm107_fifo = {
.engn = &gk104_engn,
.engn_ce = &gk104_engn_ce,
.cgrp = {{ 0, 0, KEPLER_CHANNEL_GROUP_A }, &gk110_cgrp },
.chan = {{ 0, 0, KEPLER_CHANNEL_GPFIFO_B }, &gm107_chan, .ctor = &gk104_fifo_gpfifo_new },
.chan = {{ 0, 0, KEPLER_CHANNEL_GPFIFO_B }, &gm107_chan },
};
int
gm107_fifo_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst,
struct nvkm_fifo **pfifo)
{
return gk104_fifo_new_(&gm107_fifo, device, type, inst, 0, pfifo);
return nvkm_fifo_new_(&gm107_fifo, device, type, inst, pfifo);
}
......@@ -21,8 +21,7 @@
*
* Authors: Ben Skeggs
*/
#include "gk104.h"
#include "changk104.h"
#include "priv.h"
#include <nvif/class.h>
......@@ -40,8 +39,6 @@ gm200_fifo_chid_nr(struct nvkm_fifo *fifo)
static const struct nvkm_fifo_func
gm200_fifo = {
.dtor = gk104_fifo_dtor,
.oneinit = gk104_fifo_oneinit,
.chid_nr = gm200_fifo_chid_nr,
.chid_ctor = gk110_fifo_chid_ctor,
.runq_nr = gm200_fifo_runq_nr,
......@@ -58,12 +55,12 @@ gm200_fifo = {
.engn = &gk104_engn,
.engn_ce = &gk104_engn_ce,
.cgrp = {{ 0, 0, KEPLER_CHANNEL_GROUP_A }, &gk110_cgrp },
.chan = {{ 0, 0, MAXWELL_CHANNEL_GPFIFO_A }, &gm107_chan, .ctor = &gk104_fifo_gpfifo_new },
.chan = {{ 0, 0, MAXWELL_CHANNEL_GPFIFO_A }, &gm107_chan },
};
int
gm200_fifo_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst,
struct nvkm_fifo **pfifo)
{
return gk104_fifo_new_(&gm200_fifo, device, type, inst, 0, pfifo);
return nvkm_fifo_new_(&gm200_fifo, device, type, inst, pfifo);
}
......@@ -21,9 +21,8 @@
*
* Authors: Ben Skeggs
*/
#include "priv.h"
#include "runl.h"
#include "gk104.h"
#include "changk104.h"
#include <core/gpuobj.h>
#include <subdev/fault.h>
......@@ -113,8 +112,6 @@ gp100_fifo_intr_mmu_fault_unit(struct nvkm_fifo *fifo, int unit)
static const struct nvkm_fifo_func
gp100_fifo = {
.dtor = gk104_fifo_dtor,
.oneinit = gk104_fifo_oneinit,
.chid_nr = gm200_fifo_chid_nr,
.chid_ctor = gk110_fifo_chid_ctor,
.runq_nr = gm200_fifo_runq_nr,
......@@ -131,12 +128,12 @@ gp100_fifo = {
.engn = &gk104_engn,
.engn_ce = &gk104_engn_ce,
.cgrp = {{ 0, 0, KEPLER_CHANNEL_GROUP_A }, &gk110_cgrp, .force = true },
.chan = {{ 0, 0, PASCAL_CHANNEL_GPFIFO_A }, &gm107_chan, .ctor = &gk104_fifo_gpfifo_new },
.chan = {{ 0, 0, PASCAL_CHANNEL_GPFIFO_A }, &gm107_chan },
};
int
gp100_fifo_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst,
struct nvkm_fifo **pfifo)
{
return gk104_fifo_new_(&gp100_fifo, device, type, inst, 0, pfifo);
return nvkm_fifo_new_(&gp100_fifo, device, type, inst, pfifo);
}
/*
* Copyright 2012 Red Hat Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Authors: Ben Skeggs
*/
#include "channv50.h"
#include <core/client.h>
#include <core/ramht.h>
#include <nvif/cl826f.h>
#include <nvif/unpack.h>
static int
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 g82_channel_gpfifo_v0 v0;
} *args = data;
struct nv50_fifo *fifo = nv50_fifo(base);
struct nv50_fifo_chan *chan;
u64 ioffset, ilength;
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 "
"pushbuf %llx ioffset %016llx "
"ilength %08x\n",
args->v0.version, args->v0.vmm, args->v0.pushbuf,
args->v0.ioffset, args->v0.ilength);
if (!args->v0.pushbuf)
return -EINVAL;
} else
return ret;
if (!(chan = kzalloc(sizeof(*chan), GFP_KERNEL)))
return -ENOMEM;
*pobject = &chan->base.object;
ret = g84_fifo_chan_ctor(fifo, args->v0.vmm, args->v0.pushbuf,
oclass, chan);
if (ret)
return ret;
args->v0.chid = chan->base.chid;
ioffset = args->v0.ioffset;
ilength = args->v0.ilength;
chan->base.func->ramfc->write(&chan->base, ioffset, ilength, BIT(0), false);
return 0;
}
const struct nvkm_fifo_chan_oclass
g84_fifo_gpfifo_oclass = {
.ctor = g84_fifo_gpfifo_new,
};
/*
* Copyright 2012 Red Hat Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Authors: Ben Skeggs
*/
#include "changf100.h"
#include <core/client.h>
#include <core/gpuobj.h>
#include <subdev/fb.h>
#include <subdev/timer.h>
#include <nvif/cl906f.h>
#include <nvif/unpack.h>
static void *
gf100_fifo_gpfifo_dtor(struct nvkm_fifo_chan *base)
{
return gf100_fifo_chan(base);
}
static const struct nvkm_fifo_chan_func
gf100_fifo_gpfifo_func = {
.dtor = gf100_fifo_gpfifo_dtor,
};
static int
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 = gf100_fifo(base);
struct nvkm_object *parent = oclass->parent;
struct gf100_fifo_chan *chan;
u64 usermem, ioffset, ilength;
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\n",
args->v0.version, args->v0.vmm, args->v0.ioffset,
args->v0.ilength);
if (!args->v0.vmm)
return -EINVAL;
} else
return ret;
/* allocate channel */
if (!(chan = kzalloc(sizeof(*chan), GFP_KERNEL)))
return -ENOMEM;
*pobject = &chan->base.object;
ret = nvkm_fifo_chan_ctor(&gf100_fifo_gpfifo_func, &fifo->base,
0x1000, 0x1000, true, args->v0.vmm, 0,
BIT(GF100_FIFO_ENGN_GR) |
BIT(GF100_FIFO_ENGN_MSPDEC) |
BIT(GF100_FIFO_ENGN_MSPPP) |
BIT(GF100_FIFO_ENGN_MSVLD) |
BIT(GF100_FIFO_ENGN_CE0) |
BIT(GF100_FIFO_ENGN_CE1) |
BIT(GF100_FIFO_ENGN_SW),
0, 0, 0,
oclass, &chan->base);
if (ret)
return ret;
args->v0.chid = chan->base.chid;
usermem = nvkm_memory_addr(chan->base.userd.mem) + chan->base.userd.base;
ioffset = args->v0.ioffset;
ilength = args->v0.ilength;
chan->base.func->ramfc->write(&chan->base, ioffset, ilength, BIT(0), false);
return 0;
}
const struct nvkm_fifo_chan_oclass
gf100_fifo_gpfifo_oclass = {
.ctor = gf100_fifo_gpfifo_new,
};
/*
* Copyright 2012 Red Hat Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Authors: Ben Skeggs
*/
#include "changk104.h"
#include "cgrp.h"
#include <core/client.h>
#include <core/gpuobj.h>
#include <subdev/fb.h>
#include <subdev/mmu.h>
#include <subdev/timer.h>
#include <nvif/cla06f.h>
#include <nvif/unpack.h>
void *
gk104_fifo_gpfifo_dtor(struct nvkm_fifo_chan *base)
{
struct gk104_fifo_chan *chan = gk104_fifo_chan(base);
return chan;
}
const struct nvkm_fifo_chan_func
gk104_fifo_gpfifo_func = {
.dtor = gk104_fifo_gpfifo_dtor,
};
static int
gk104_fifo_gpfifo_new_(struct gk104_fifo *fifo, u64 *runlists, u16 *chid,
u64 vmm, u64 ioffset, u64 ilength, u64 *inst, bool priv,
const struct nvkm_oclass *oclass,
struct nvkm_object **pobject)
{
struct gk104_fifo_chan *chan;
int runlist = ffs(*runlists) -1, ret;
if (!vmm || runlist < 0 || runlist >= fifo->runlist_nr)
return -EINVAL;
*runlists = BIT_ULL(runlist);
/* Allocate the channel. */
if (!(chan = kzalloc(sizeof(*chan), GFP_KERNEL)))
return -ENOMEM;
*pobject = &chan->base.object;
chan->runl = runlist;
ret = nvkm_fifo_chan_ctor(&gk104_fifo_gpfifo_func, &fifo->base,
0x1000, 0x1000, true, vmm, 0, fifo->runlist[runlist].engm_sw,
0, 0, 0,
oclass, &chan->base);
if (ret)
return ret;
*chid = chan->base.chid;
*inst = chan->base.inst->addr;
chan->base.func->ramfc->write(&chan->base, ioffset, ilength, BIT(0), priv);
return 0;
}
int
gk104_fifo_gpfifo_new(struct gk104_fifo *fifo, const struct nvkm_oclass *oclass,
void *data, u32 size, struct nvkm_object **pobject)
{
struct nvkm_object *parent = oclass->parent;
union {
struct kepler_channel_gpfifo_a_v0 v0;
} *args = data;
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 priv %d\n",
args->v0.version, args->v0.vmm, args->v0.ioffset,
args->v0.ilength, args->v0.runlist, args->v0.priv);
return gk104_fifo_gpfifo_new_(fifo,
&args->v0.runlist,
&args->v0.chid,
args->v0.vmm,
args->v0.ioffset,
args->v0.ilength,
&args->v0.inst,
args->v0.priv,
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 "changk104.h"
#include "cgrp.h"
#include <core/client.h>
#include <core/gpuobj.h>
#include <nvif/clc36f.h>
#include <nvif/unpack.h>
static const struct nvkm_fifo_chan_func
gv100_fifo_gpfifo = {
.dtor = gk104_fifo_gpfifo_dtor,
};
int
gv100_fifo_gpfifo_new_(const struct nvkm_fifo_chan_func *func,
struct gk104_fifo *fifo, u64 *runlists, u16 *chid,
u64 vmm, u64 ioffset, u64 ilength, u64 *inst, bool priv,
u32 *token, const struct nvkm_oclass *oclass,
struct nvkm_object **pobject)
{
struct gk104_fifo_chan *chan;
int runlist = ffs(*runlists) -1, ret;
if (!vmm || runlist < 0 || runlist >= fifo->runlist_nr)
return -EINVAL;
*runlists = BIT_ULL(runlist);
/* Allocate the channel. */
if (!(chan = kzalloc(sizeof(*chan), GFP_KERNEL)))
return -ENOMEM;
*pobject = &chan->base.object;
chan->runl = runlist;
ret = nvkm_fifo_chan_ctor(func, &fifo->base, 0x1000, 0x1000, true, vmm,
0, fifo->runlist[runlist].engm, 0, 0, 0,
oclass, &chan->base);
if (ret)
return ret;
*chid = chan->base.chid;
*inst = chan->base.inst->addr;
*token = chan->base.func->doorbell_handle(&chan->base);
chan->base.func->ramfc->write(&chan->base, ioffset, ilength, BIT(0), priv);
return 0;
}
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 volta_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 priv %d\n",
args->v0.version, args->v0.vmm, args->v0.ioffset,
args->v0.ilength, args->v0.runlist, args->v0.priv);
return gv100_fifo_gpfifo_new_(&gv100_fifo_gpfifo, fifo,
&args->v0.runlist,
&args->v0.chid,
args->v0.vmm,
args->v0.ioffset,
args->v0.ilength,
&args->v0.inst,
args->v0.priv,
&args->v0.token,
oclass, pobject);
}
return ret;
}
/*
* Copyright 2012 Red Hat Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Authors: Ben Skeggs
*/
#include "channv50.h"
#include <core/client.h>
#include <core/ramht.h>
#include <nvif/cl506f.h>
#include <nvif/unpack.h>
static int
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 nv50_fifo *fifo = nv50_fifo(base);
struct nv50_fifo_chan *chan;
u64 ioffset, ilength;
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 "
"pushbuf %llx ioffset %016llx "
"ilength %08x\n",
args->v0.version, args->v0.vmm, args->v0.pushbuf,
args->v0.ioffset, args->v0.ilength);
if (!args->v0.pushbuf)
return -EINVAL;
} else
return ret;
if (!(chan = kzalloc(sizeof(*chan), GFP_KERNEL)))
return -ENOMEM;
*pobject = &chan->base.object;
ret = nv50_fifo_chan_ctor(fifo, args->v0.vmm, args->v0.pushbuf,
oclass, chan);
if (ret)
return ret;
args->v0.chid = chan->base.chid;
ioffset = args->v0.ioffset;
ilength = args->v0.ilength;
chan->base.func->ramfc->write(&chan->base, ioffset, ilength, BIT(0), false);
return 0;
}
const struct nvkm_fifo_chan_oclass
nv50_fifo_gpfifo_oclass = {
.ctor = nv50_fifo_gpfifo_new,
};
/*
* 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/clc36f.h>
#include <nvif/unpack.h>
static const struct nvkm_fifo_chan_func
tu102_fifo_gpfifo = {
.dtor = gk104_fifo_gpfifo_dtor,
};
int
tu102_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 volta_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 priv %d\n",
args->v0.version, args->v0.vmm, args->v0.ioffset,
args->v0.ilength, args->v0.runlist, args->v0.priv);
return gv100_fifo_gpfifo_new_(&tu102_fifo_gpfifo, fifo,
&args->v0.runlist,
&args->v0.chid,
args->v0.vmm,
args->v0.ioffset,
args->v0.ilength,
&args->v0.inst,
args->v0.priv,
&args->v0.token,
oclass, pobject);
}
return ret;
}
......@@ -19,16 +19,15 @@
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#include "priv.h"
#include "chan.h"
#include "chid.h"
#include "cgrp.h"
#include "runl.h"
#include "runq.h"
#include "gk104.h"
#include "changk104.h"
#include <core/gpuobj.h>
#include <subdev/mmu.h>
#include <nvif/class.h>
......@@ -71,7 +70,7 @@ gv100_chan_ramfc = {
const struct nvkm_chan_func_userd
gv100_chan_userd = {
.bar = 1, /*FIXME: hw doesn't have poller, flip to user-allocated in uapi commit. */
.bar = -1,
.size = 0x200,
.clear = gf100_chan_userd_clear,
};
......@@ -467,8 +466,6 @@ gv100_fifo_intr_ctxsw_timeout(struct nvkm_fifo *fifo, u32 engm)
static const struct nvkm_fifo_func
gv100_fifo = {
.dtor = gk104_fifo_dtor,
.oneinit = gk104_fifo_oneinit,
.chid_nr = gm200_fifo_chid_nr,
.chid_ctor = gk110_fifo_chid_ctor,
.runq_nr = gm200_fifo_runq_nr,
......@@ -484,12 +481,12 @@ gv100_fifo = {
.engn = &gv100_engn,
.engn_ce = &gv100_engn_ce,
.cgrp = {{ 0, 0, KEPLER_CHANNEL_GROUP_A }, &gk110_cgrp, .force = true },
.chan = {{ 0, 0, VOLTA_CHANNEL_GPFIFO_A }, &gv100_chan, .ctor = gv100_fifo_gpfifo_new },
.chan = {{ 0, 0, VOLTA_CHANNEL_GPFIFO_A }, &gv100_chan },
};
int
gv100_fifo_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst,
struct nvkm_fifo **pfifo)
{
return gk104_fifo_new_(&gv100_fifo, device, type, inst, 0, pfifo);
return nvkm_fifo_new_(&gv100_fifo, device, type, inst, pfifo);
}
......@@ -21,13 +21,12 @@
*
* Authors: Ben Skeggs
*/
#include "priv.h"
#include "cgrp.h"
#include "chan.h"
#include "chid.h"
#include "runl.h"
#include "nv04.h"
#include "channv04.h"
#include "regsnv04.h"
#include <core/ramht.h>
......@@ -520,25 +519,6 @@ nv04_fifo_chid_nr(struct nvkm_fifo *fifo)
return 16;
}
int
nv04_fifo_new_(const struct nvkm_fifo_func *func, struct nvkm_device *device,
enum nvkm_subdev_type type, int inst, int nr, const struct nv04_fifo_ramfc *ramfc,
struct nvkm_fifo **pfifo)
{
struct nv04_fifo *fifo;
int ret;
if (!(fifo = kzalloc(sizeof(*fifo), GFP_KERNEL)))
return -ENOMEM;
*pfifo = &fifo->base;
ret = nvkm_fifo_ctor(func, device, type, inst, &fifo->base);
if (ret)
return ret;
return 0;
}
static const struct nvkm_fifo_func
nv04_fifo = {
.chid_nr = nv04_fifo_chid_nr,
......@@ -552,12 +532,12 @@ nv04_fifo = {
.engn = &nv04_engn,
.engn_sw = &nv04_engn,
.cgrp = {{ }, &nv04_cgrp },
.chan = {{ 0, 0, NV03_CHANNEL_DMA }, &nv04_chan, .oclass = &nv04_fifo_dma_oclass },
.chan = {{ 0, 0, NV03_CHANNEL_DMA }, &nv04_chan },
};
int
nv04_fifo_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst,
struct nvkm_fifo **pfifo)
{
return nv04_fifo_new_(&nv04_fifo, device, type, inst, 0, NULL, pfifo);
return nvkm_fifo_new_(&nv04_fifo, device, type, inst, pfifo);
}
/* SPDX-License-Identifier: MIT */
#ifndef __NV04_FIFO_H__
#define __NV04_FIFO_H__
#define nv04_fifo(p) container_of((p), struct nv04_fifo, base)
#include "priv.h"
#define nv04_fifo_ramfc nvkm_ramfc_layout
struct nv04_fifo {
struct nvkm_fifo base;
};
int nv04_fifo_new_(const struct nvkm_fifo_func *, struct nvkm_device *, enum nvkm_subdev_type, int,
int nr, const struct nv04_fifo_ramfc *, struct nvkm_fifo **);
#endif
......@@ -21,6 +21,7 @@
*
* Authors: Ben Skeggs
*/
#include "priv.h"
#include "cgrp.h"
#include "chan.h"
#include "runl.h"
......@@ -28,8 +29,6 @@
#include <core/gpuobj.h>
#include <subdev/instmem.h>
#include "nv04.h"
#include "channv04.h"
#include "regsnv04.h"
#include <nvif/class.h>
......@@ -103,12 +102,12 @@ nv10_fifo = {
.engn = &nv04_engn,
.engn_sw = &nv04_engn,
.cgrp = {{ }, &nv04_cgrp },
.chan = {{ 0, 0, NV10_CHANNEL_DMA }, &nv10_chan, .oclass = &nv10_fifo_dma_oclass },
.chan = {{ 0, 0, NV10_CHANNEL_DMA }, &nv10_chan },
};
int
nv10_fifo_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst,
struct nvkm_fifo **pfifo)
{
return nv04_fifo_new_(&nv10_fifo, device, type, inst, 0, NULL, pfifo);
return nvkm_fifo_new_(&nv10_fifo, device, type, inst, pfifo);
}
......@@ -21,13 +21,12 @@
*
* Authors: Ben Skeggs
*/
#include "priv.h"
#include "cgrp.h"
#include "chan.h"
#include "chid.h"
#include "runl.h"
#include "nv04.h"
#include "channv04.h"
#include "regsnv04.h"
#include <core/ramht.h>
......@@ -132,12 +131,12 @@ nv17_fifo = {
.engn = &nv04_engn,
.engn_sw = &nv04_engn,
.cgrp = {{ }, &nv04_cgrp },
.chan = {{ 0, 0, NV17_CHANNEL_DMA }, &nv17_chan, .oclass = &nv17_fifo_dma_oclass },
.chan = {{ 0, 0, NV17_CHANNEL_DMA }, &nv17_chan },
};
int
nv17_fifo_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst,
struct nvkm_fifo **pfifo)
{
return nv04_fifo_new_(&nv17_fifo, device, type, inst, 0, NULL, pfifo);
return nvkm_fifo_new_(&nv17_fifo, device, type, inst, pfifo);
}
......@@ -21,13 +21,12 @@
*
* Authors: Ben Skeggs
*/
#include "priv.h"
#include "cgrp.h"
#include "chan.h"
#include "chid.h"
#include "runl.h"
#include "nv04.h"
#include "channv04.h"
#include "regsnv04.h"
#include <core/ramht.h>
......@@ -242,12 +241,12 @@ nv40_fifo = {
.engn = &nv40_engn,
.engn_sw = &nv40_engn_sw,
.cgrp = {{ }, &nv04_cgrp },
.chan = {{ 0, 0, NV40_CHANNEL_DMA }, &nv40_chan, .oclass = &nv40_fifo_dma_oclass },
.chan = {{ 0, 0, NV40_CHANNEL_DMA }, &nv40_chan },
};
int
nv40_fifo_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst,
struct nvkm_fifo **pfifo)
{
return nv04_fifo_new_(&nv40_fifo, device, type, inst, 0, NULL, pfifo);
return nvkm_fifo_new_(&nv40_fifo, device, type, inst, pfifo);
}
......@@ -21,6 +21,7 @@
*
* Authors: Ben Skeggs
*/
#include "priv.h"
#include "cgrp.h"
#include "chan.h"
#include "chid.h"
......@@ -29,9 +30,6 @@
#include <core/ramht.h>
#include <subdev/timer.h>
#include "nv50.h"
#include "channv50.h"
#include <nvif/class.h>
void
......@@ -376,34 +374,8 @@ nv50_fifo_chid_nr(struct nvkm_fifo *fifo)
return 128;
}
void *
nv50_fifo_dtor(struct nvkm_fifo *base)
{
struct nv50_fifo *fifo = nv50_fifo(base);
return fifo;
}
int
nv50_fifo_new_(const struct nvkm_fifo_func *func, struct nvkm_device *device,
enum nvkm_subdev_type type, int inst, struct nvkm_fifo **pfifo)
{
struct nv50_fifo *fifo;
int ret;
if (!(fifo = kzalloc(sizeof(*fifo), GFP_KERNEL)))
return -ENOMEM;
*pfifo = &fifo->base;
ret = nvkm_fifo_ctor(func, device, type, inst, &fifo->base);
if (ret)
return ret;
return 0;
}
static const struct nvkm_fifo_func
nv50_fifo = {
.dtor = nv50_fifo_dtor,
.chid_nr = nv50_fifo_chid_nr,
.chid_ctor = nv50_fifo_chid_ctor,
.runl_ctor = nv04_fifo_runl_ctor,
......@@ -415,12 +387,12 @@ nv50_fifo = {
.engn = &nv50_engn,
.engn_sw = &nv50_engn_sw,
.cgrp = {{ }, &nv04_cgrp },
.chan = {{ 0, 0, NV50_CHANNEL_GPFIFO }, &nv50_chan, .oclass = &nv50_fifo_gpfifo_oclass },
.chan = {{ 0, 0, NV50_CHANNEL_GPFIFO }, &nv50_chan },
};
int
nv50_fifo_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst,
struct nvkm_fifo **pfifo)
{
return nv50_fifo_new_(&nv50_fifo, device, type, inst, pfifo);
return nvkm_fifo_new_(&nv50_fifo, device, type, inst, pfifo);
}
/* SPDX-License-Identifier: MIT */
#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 {
struct nvkm_fifo base;
};
int nv50_fifo_new_(const struct nvkm_fifo_func *, struct nvkm_device *, enum nvkm_subdev_type, int,
struct nvkm_fifo **);
void *nv50_fifo_dtor(struct nvkm_fifo *);
#endif
......@@ -11,13 +11,8 @@ struct nvkm_memory;
struct nvkm_runl;
struct nvkm_runq;
struct nvkm_vctx;
struct gk104_fifo;
struct nvkm_fifo_chan_oclass;
struct nvkm_fifo_func {
void *(*dtor)(struct nvkm_fifo *);
int (*oneinit)(struct nvkm_fifo *);
int (*chid_nr)(struct nvkm_fifo *);
int (*chid_ctor)(struct nvkm_fifo *, int nr);
int (*runq_nr)(struct nvkm_fifo *);
......@@ -59,17 +54,11 @@ struct nvkm_fifo_func {
struct nvkm_fifo_func_chan {
struct nvkm_sclass user;
const struct nvkm_chan_func *func;
const struct nvkm_fifo_chan_oclass {
int (*ctor)(struct nvkm_fifo *, const struct nvkm_oclass *,
void *data, u32 size, struct nvkm_object **);
} *oclass;
int (*ctor)(struct gk104_fifo *, const struct nvkm_oclass *, void *, u32,
struct nvkm_object **);
} chan;
};
int nvkm_fifo_ctor(const struct nvkm_fifo_func *, struct nvkm_device *, enum nvkm_subdev_type, int,
struct nvkm_fifo *);
int nvkm_fifo_new_(const struct nvkm_fifo_func *, struct nvkm_device *, enum nvkm_subdev_type, int,
struct nvkm_fifo **);
int nv04_fifo_chid_ctor(struct nvkm_fifo *, int);
int nv04_fifo_runl_ctor(struct nvkm_fifo *);
......@@ -204,4 +193,6 @@ extern const struct nvkm_fifo_func_mmu_fault tu102_fifo_mmu_fault;
int nvkm_uchan_new(struct nvkm_fifo *, struct nvkm_cgrp *, const struct nvkm_oclass *,
void *argv, u32 argc, struct nvkm_object **);
int nvkm_ucgrp_new(struct nvkm_fifo *, const struct nvkm_oclass *, void *argv, u32 argc,
struct nvkm_object **);
#endif
......@@ -19,13 +19,11 @@
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#include "priv.h"
#include "cgrp.h"
#include "chan.h"
#include "runl.h"
#include "gk104.h"
#include "cgrp.h"
#include "changk104.h"
#include <core/memory.h>
#include <subdev/mc.h>
#include <subdev/vfn.h>
......@@ -263,8 +261,6 @@ tu102_fifo_init_pbdmas(struct nvkm_fifo *fifo, u32 mask)
static const struct nvkm_fifo_func
tu102_fifo = {
.dtor = gk104_fifo_dtor,
.oneinit = gk104_fifo_oneinit,
.chid_nr = gm200_fifo_chid_nr,
.chid_ctor = gk110_fifo_chid_ctor,
.runq_nr = gm200_fifo_runq_nr,
......@@ -279,19 +275,12 @@ tu102_fifo = {
.engn = &gv100_engn,
.engn_ce = &gv100_engn_ce,
.cgrp = {{ 0, 0, KEPLER_CHANNEL_GROUP_A }, &gk110_cgrp, .force = true },
.chan = {{ 0, 0, TURING_CHANNEL_GPFIFO_A }, &tu102_chan, .ctor = tu102_fifo_gpfifo_new },
.chan = {{ 0, 0, TURING_CHANNEL_GPFIFO_A }, &tu102_chan },
};
int
tu102_fifo_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst,
struct nvkm_fifo **pfifo)
{
struct gk104_fifo *fifo;
if (!(fifo = kzalloc(sizeof(*fifo), GFP_KERNEL)))
return -ENOMEM;
fifo->func = &tu102_fifo;
*pfifo = &fifo->base;
return nvkm_fifo_ctor(&tu102_fifo, device, type, inst, &fifo->base);
return nvkm_fifo_new_(&tu102_fifo, device, type, inst, pfifo);
}
/*
* Copyright 2012 Red Hat Inc.
* Copyright 2021 Red Hat Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
......@@ -18,44 +18,108 @@
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Authors: Ben Skeggs
*/
#include "channv50.h"
#define nvkm_ucgrp(p) container_of((p), struct nvkm_ucgrp, object)
#include "priv.h"
#include "cgrp.h"
#include "runl.h"
#include <core/client.h>
#include <core/ramht.h>
#include <subdev/mmu.h>
#include <subdev/timer.h>
void *
nv50_fifo_chan_dtor(struct nvkm_fifo_chan *base)
#include <nvif/if0021.h>
struct nvkm_ucgrp {
struct nvkm_object object;
struct nvkm_cgrp *cgrp;
};
static int
nvkm_ucgrp_chan_new(const struct nvkm_oclass *oclass, void *argv, u32 argc,
struct nvkm_object **pobject)
{
struct nvkm_cgrp *cgrp = nvkm_ucgrp(oclass->parent)->cgrp;
return nvkm_uchan_new(cgrp->runl->fifo, cgrp, oclass, argv, argc, pobject);
}
static int
nvkm_ucgrp_sclass(struct nvkm_object *object, int index, struct nvkm_oclass *oclass)
{
struct nvkm_cgrp *cgrp = nvkm_ucgrp(object)->cgrp;
struct nvkm_fifo *fifo = cgrp->runl->fifo;
const struct nvkm_fifo_func_chan *chan = &fifo->func->chan;
int c = 0;
/* *_CHANNEL_GPFIFO_* */
if (chan->user.oclass) {
if (c++ == index) {
oclass->base = chan->user;
oclass->ctor = nvkm_ucgrp_chan_new;
return 0;
}
}
return -EINVAL;
}
static void *
nvkm_ucgrp_dtor(struct nvkm_object *object)
{
struct nv50_fifo_chan *chan = nv50_fifo_chan(base);
return chan;
struct nvkm_ucgrp *ucgrp = nvkm_ucgrp(object);
nvkm_cgrp_unref(&ucgrp->cgrp);
return ucgrp;
}
static const struct nvkm_fifo_chan_func
nv50_fifo_chan_func = {
.dtor = nv50_fifo_chan_dtor,
static const struct nvkm_object_func
nvkm_ucgrp = {
.dtor = nvkm_ucgrp_dtor,
.sclass = nvkm_ucgrp_sclass,
};
int
nv50_fifo_chan_ctor(struct nv50_fifo *fifo, u64 vmm, u64 push,
const struct nvkm_oclass *oclass,
struct nv50_fifo_chan *chan)
nvkm_ucgrp_new(struct nvkm_fifo *fifo, const struct nvkm_oclass *oclass, void *argv, u32 argc,
struct nvkm_object **pobject)
{
union nvif_cgrp_args *args = argv;
struct nvkm_runl *runl;
struct nvkm_vmm *vmm;
struct nvkm_ucgrp *ucgrp;
int ret;
if (!vmm)
if (argc < sizeof(args->v0) || args->v0.version != 0)
return -ENOSYS;
argc -= sizeof(args->v0);
if (args->v0.namelen != argc)
return -EINVAL;
/* Lookup objects referenced in args. */
runl = nvkm_runl_get(fifo, args->v0.runlist, 0);
if (!runl)
return -EINVAL;
ret = nvkm_fifo_chan_ctor(&nv50_fifo_chan_func, &fifo->base,
0x10000, 0x1000, false, vmm, push,
BIT(NV50_FIFO_ENGN_SW) |
BIT(NV50_FIFO_ENGN_GR) |
BIT(NV50_FIFO_ENGN_MPEG) |
BIT(NV50_FIFO_ENGN_DMA),
0, 0xc00000, 0x2000, oclass, &chan->base);
vmm = nvkm_uvmm_search(oclass->client, args->v0.vmm);
if (IS_ERR(vmm))
return PTR_ERR(vmm);
/* Allocate channel group. */
if (!(ucgrp = kzalloc(sizeof(*ucgrp), GFP_KERNEL))) {
ret = -ENOMEM;
goto done;
}
nvkm_object_ctor(&nvkm_ucgrp, oclass, &ucgrp->object);
*pobject = &ucgrp->object;
ret = nvkm_cgrp_new(runl, args->v0.name, vmm, true, &ucgrp->cgrp);
if (ret)
goto done;
/* Return channel group info to caller. */
args->v0.cgid = ucgrp->cgrp->id;
done:
nvkm_vmm_unref(&vmm);
return ret;
}
......@@ -20,6 +20,7 @@
* OTHER DEALINGS IN THE SOFTWARE.
*/
#define nvkm_uchan(p) container_of((p), struct nvkm_uchan, object)
#include "priv.h"
#include "cgrp.h"
#include "chan.h"
#include "chid.h"
......@@ -27,11 +28,11 @@
#include <core/gpuobj.h>
#include <core/oproxy.h>
#include <subdev/mmu.h>
#include <engine/dma.h>
#include <nvif/if0020.h>
#include "gk104.h"
struct nvkm_uchan {
struct nvkm_object object;
struct nvkm_chan *chan;
......@@ -204,12 +205,20 @@ nvkm_uchan_sclass(struct nvkm_object *object, int index, struct nvkm_oclass *ocl
{
struct nvkm_chan *chan = nvkm_uchan(object)->chan;
struct nvkm_engn *engn;
int ret;
int ret, runq = 0;
nvkm_runl_foreach_engn(engn, chan->cgrp->runl) {
struct nvkm_engine *engine = engn->engine;
int c = 0;
/* Each runqueue, on runlists with multiple, has its own LCE. */
if (engn->runl->func->runqs) {
if (engine->subdev.type == NVKM_ENGINE_CE) {
if (chan->runq != runq++)
continue;
}
}
oclass->engine = engine;
oclass->base.oclass = 0;
......@@ -246,8 +255,8 @@ static int
nvkm_uchan_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;
struct nvkm_chan *chan = nvkm_uchan(object)->chan;
struct nvkm_device *device = chan->cgrp->runl->fifo->engine.subdev.device;
if (chan->func->userd->bar < 0)
return -ENOSYS;
......@@ -312,23 +321,89 @@ int
nvkm_uchan_new(struct nvkm_fifo *fifo, struct nvkm_cgrp *cgrp, const struct nvkm_oclass *oclass,
void *argv, u32 argc, struct nvkm_object **pobject)
{
struct nvkm_object *object = NULL;
union nvif_chan_args *args = argv;
struct nvkm_runl *runl;
struct nvkm_vmm *vmm = NULL;
struct nvkm_dmaobj *ctxdma = NULL;
struct nvkm_memory *userd = NULL;
struct nvkm_uchan *uchan;
struct nvkm_chan *chan;
int ret;
if (!(uchan = kzalloc(sizeof(*uchan), GFP_KERNEL)))
return -ENOMEM;
if (argc < sizeof(args->v0) || args->v0.version != 0)
return -ENOSYS;
argc -= sizeof(args->v0);
if (args->v0.namelen != argc)
return -EINVAL;
/* Lookup objects referenced in args. */
runl = nvkm_runl_get(fifo, args->v0.runlist, 0);
if (!runl)
return -EINVAL;
if (args->v0.vmm) {
vmm = nvkm_uvmm_search(oclass->client, args->v0.vmm);
if (IS_ERR(vmm))
return PTR_ERR(vmm);
}
if (args->v0.ctxdma) {
ctxdma = nvkm_dmaobj_search(oclass->client, args->v0.ctxdma);
if (IS_ERR(ctxdma)) {
ret = PTR_ERR(ctxdma);
goto done;
}
}
if (args->v0.huserd) {
userd = nvkm_umem_search(oclass->client, args->v0.huserd);
if (IS_ERR(userd)) {
ret = PTR_ERR(userd);
userd = NULL;
goto done;
}
}
/* Allocate channel. */
if (!(uchan = kzalloc(sizeof(*uchan), GFP_KERNEL))) {
ret = -ENOMEM;
goto done;
}
nvkm_object_ctor(&nvkm_uchan, oclass, &uchan->object);
*pobject = &uchan->object;
if (fifo->func->chan.ctor)
ret = fifo->func->chan.ctor(gk104_fifo(fifo), oclass, argv, argc, &object);
ret = nvkm_chan_new_(fifo->func->chan.func, runl, args->v0.runq, cgrp, args->v0.name,
args->v0.priv != 0, args->v0.devm, vmm, ctxdma, args->v0.offset,
args->v0.length, userd, args->v0.ouserd, &uchan->chan);
if (ret)
goto done;
chan = uchan->chan;
/* Return channel info to caller. */
if (chan->func->doorbell_handle)
args->v0.token = chan->func->doorbell_handle(chan);
else
ret = fifo->func->chan.oclass->ctor(fifo, oclass, argv, argc, &object);
if (!object)
return ret;
args->v0.token = ~0;
args->v0.chid = chan->id;
switch (nvkm_memory_target(chan->inst->memory)) {
case NVKM_MEM_TARGET_INST: args->v0.aper = NVIF_CHAN_V0_INST_APER_INST; break;
case NVKM_MEM_TARGET_VRAM: args->v0.aper = NVIF_CHAN_V0_INST_APER_VRAM; break;
case NVKM_MEM_TARGET_HOST: args->v0.aper = NVIF_CHAN_V0_INST_APER_HOST; break;
case NVKM_MEM_TARGET_NCOH: args->v0.aper = NVIF_CHAN_V0_INST_APER_NCOH; break;
default:
WARN_ON(1);
ret = -EFAULT;
break;
}
uchan->chan = container_of(object, typeof(*uchan->chan), object);
args->v0.inst = nvkm_memory_addr(chan->inst->memory);
done:
nvkm_memory_unref(&userd);
nvkm_vmm_unref(&vmm);
return ret;
}
......@@ -39,7 +39,7 @@ nvkm_uvmm_search(struct nvkm_client *client, u64 handle)
if (IS_ERR(object))
return (void *)object;
return nvkm_uvmm(object)->vmm;
return nvkm_vmm_ref(nvkm_uvmm(object)->vmm);
}
static int
......
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