Commit 85532bd9 authored by Ben Skeggs's avatar Ben Skeggs

drm/nouveau/fifo/gk104-: support enabling privileged ce functions

Will be used by SVM code to allow direct (without going through MMU) memcpy
using the GPU copy engines.
Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
parent 86b442d7
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
struct kepler_channel_gpfifo_a_v0 { struct kepler_channel_gpfifo_a_v0 {
__u8 version; __u8 version;
__u8 pad01[1]; __u8 priv;
__u16 chid; __u16 chid;
__u32 ilength; __u32 ilength;
__u64 ioffset; __u64 ioffset;
......
...@@ -306,7 +306,7 @@ nouveau_abi16_ioctl_channel_alloc(ABI16_IOCTL_ARGS) ...@@ -306,7 +306,7 @@ nouveau_abi16_ioctl_channel_alloc(ABI16_IOCTL_ARGS)
/* create channel object and initialise dma and fence management */ /* create channel object and initialise dma and fence management */
ret = nouveau_channel_new(drm, device, init->fb_ctxdma_handle, ret = nouveau_channel_new(drm, device, init->fb_ctxdma_handle,
init->tt_ctxdma_handle, &chan->chan); init->tt_ctxdma_handle, false, &chan->chan);
if (ret) if (ret)
goto done; goto done;
......
...@@ -217,7 +217,7 @@ nouveau_channel_prep(struct nouveau_drm *drm, struct nvif_device *device, ...@@ -217,7 +217,7 @@ nouveau_channel_prep(struct nouveau_drm *drm, struct nvif_device *device,
static int static int
nouveau_channel_ind(struct nouveau_drm *drm, struct nvif_device *device, nouveau_channel_ind(struct nouveau_drm *drm, struct nvif_device *device,
u64 runlist, struct nouveau_channel **pchan) u64 runlist, bool priv, struct nouveau_channel **pchan)
{ {
struct nouveau_cli *cli = (void *)device->object.client; struct nouveau_cli *cli = (void *)device->object.client;
static const u16 oclasses[] = { VOLTA_CHANNEL_GPFIFO_A, static const u16 oclasses[] = { VOLTA_CHANNEL_GPFIFO_A,
...@@ -253,6 +253,7 @@ nouveau_channel_ind(struct nouveau_drm *drm, struct nvif_device *device, ...@@ -253,6 +253,7 @@ nouveau_channel_ind(struct nouveau_drm *drm, struct nvif_device *device,
args.kepler.ioffset = 0x10000 + chan->push.addr; args.kepler.ioffset = 0x10000 + chan->push.addr;
args.kepler.runlist = runlist; args.kepler.runlist = runlist;
args.kepler.vmm = nvif_handle(&cli->vmm.vmm.object); args.kepler.vmm = nvif_handle(&cli->vmm.vmm.object);
args.kepler.priv = priv;
size = sizeof(args.kepler); size = sizeof(args.kepler);
} else } else
if (oclass[0] >= FERMI_CHANNEL_GPFIFO) { if (oclass[0] >= FERMI_CHANNEL_GPFIFO) {
...@@ -450,7 +451,8 @@ nouveau_channel_init(struct nouveau_channel *chan, u32 vram, u32 gart) ...@@ -450,7 +451,8 @@ nouveau_channel_init(struct nouveau_channel *chan, u32 vram, u32 gart)
int int
nouveau_channel_new(struct nouveau_drm *drm, struct nvif_device *device, nouveau_channel_new(struct nouveau_drm *drm, struct nvif_device *device,
u32 arg0, u32 arg1, struct nouveau_channel **pchan) u32 arg0, u32 arg1, bool priv,
struct nouveau_channel **pchan)
{ {
struct nouveau_cli *cli = (void *)device->object.client; struct nouveau_cli *cli = (void *)device->object.client;
bool super; bool super;
...@@ -460,7 +462,7 @@ nouveau_channel_new(struct nouveau_drm *drm, struct nvif_device *device, ...@@ -460,7 +462,7 @@ nouveau_channel_new(struct nouveau_drm *drm, struct nvif_device *device,
super = cli->base.super; super = cli->base.super;
cli->base.super = true; cli->base.super = true;
ret = nouveau_channel_ind(drm, device, arg0, pchan); ret = nouveau_channel_ind(drm, device, arg0, priv, pchan);
if (ret) { if (ret) {
NV_PRINTK(dbg, cli, "ib channel create, %d\n", ret); NV_PRINTK(dbg, cli, "ib channel create, %d\n", ret);
ret = nouveau_channel_dma(drm, device, pchan); ret = nouveau_channel_dma(drm, device, pchan);
......
...@@ -49,7 +49,8 @@ struct nouveau_channel { ...@@ -49,7 +49,8 @@ struct nouveau_channel {
int nouveau_channels_init(struct nouveau_drm *); int nouveau_channels_init(struct nouveau_drm *);
int nouveau_channel_new(struct nouveau_drm *, struct nvif_device *, int nouveau_channel_new(struct nouveau_drm *, struct nvif_device *,
u32 arg0, u32 arg1, struct nouveau_channel **); u32 arg0, u32 arg1, bool priv,
struct nouveau_channel **);
void nouveau_channel_del(struct nouveau_channel **); void nouveau_channel_del(struct nouveau_channel **);
int nouveau_channel_idle(struct nouveau_channel *); int nouveau_channel_idle(struct nouveau_channel *);
......
...@@ -370,7 +370,7 @@ nouveau_accel_init(struct nouveau_drm *drm) ...@@ -370,7 +370,7 @@ nouveau_accel_init(struct nouveau_drm *drm)
if (device->info.family >= NV_DEVICE_INFO_V0_KEPLER) { if (device->info.family >= NV_DEVICE_INFO_V0_KEPLER) {
ret = nouveau_channel_new(drm, &drm->client.device, ret = nouveau_channel_new(drm, &drm->client.device,
nvif_fifo_runlist_ce(device), 0, nvif_fifo_runlist_ce(device), 0,
&drm->cechan); true, &drm->cechan);
if (ret) if (ret)
NV_ERROR(drm, "failed to create ce channel, %d\n", ret); NV_ERROR(drm, "failed to create ce channel, %d\n", ret);
...@@ -381,7 +381,8 @@ nouveau_accel_init(struct nouveau_drm *drm) ...@@ -381,7 +381,8 @@ nouveau_accel_init(struct nouveau_drm *drm)
device->info.chipset != 0xaa && device->info.chipset != 0xaa &&
device->info.chipset != 0xac) { device->info.chipset != 0xac) {
ret = nouveau_channel_new(drm, &drm->client.device, ret = nouveau_channel_new(drm, &drm->client.device,
NvDmaFB, NvDmaTT, &drm->cechan); NvDmaFB, NvDmaTT, false,
&drm->cechan);
if (ret) if (ret)
NV_ERROR(drm, "failed to create ce channel, %d\n", ret); NV_ERROR(drm, "failed to create ce channel, %d\n", ret);
...@@ -393,7 +394,7 @@ nouveau_accel_init(struct nouveau_drm *drm) ...@@ -393,7 +394,7 @@ nouveau_accel_init(struct nouveau_drm *drm)
} }
ret = nouveau_channel_new(drm, &drm->client.device, ret = nouveau_channel_new(drm, &drm->client.device,
arg0, arg1, &drm->channel); arg0, arg1, false, &drm->channel);
if (ret) { if (ret) {
NV_ERROR(drm, "failed to create kernel channel, %d\n", ret); NV_ERROR(drm, "failed to create kernel channel, %d\n", ret);
nouveau_accel_fini(drm); nouveau_accel_fini(drm);
......
...@@ -240,7 +240,7 @@ gk104_fifo_gpfifo_func = { ...@@ -240,7 +240,7 @@ gk104_fifo_gpfifo_func = {
static int static int
gk104_fifo_gpfifo_new_(struct gk104_fifo *fifo, u64 *runlists, u16 *chid, gk104_fifo_gpfifo_new_(struct gk104_fifo *fifo, u64 *runlists, u16 *chid,
u64 vmm, u64 ioffset, u64 ilength, u64 *inst, u64 vmm, u64 ioffset, u64 ilength, u64 *inst, bool priv,
const struct nvkm_oclass *oclass, const struct nvkm_oclass *oclass,
struct nvkm_object **pobject) struct nvkm_object **pobject)
{ {
...@@ -316,6 +316,7 @@ gk104_fifo_gpfifo_new_(struct gk104_fifo *fifo, u64 *runlists, u16 *chid, ...@@ -316,6 +316,7 @@ gk104_fifo_gpfifo_new_(struct gk104_fifo *fifo, u64 *runlists, u16 *chid,
nvkm_wo32(chan->base.inst, 0x94, 0x30000001); nvkm_wo32(chan->base.inst, 0x94, 0x30000001);
nvkm_wo32(chan->base.inst, 0x9c, 0x00000100); nvkm_wo32(chan->base.inst, 0x9c, 0x00000100);
nvkm_wo32(chan->base.inst, 0xac, 0x0000001f); nvkm_wo32(chan->base.inst, 0xac, 0x0000001f);
nvkm_wo32(chan->base.inst, 0xe4, priv ? 0x00000020 : 0x00000000);
nvkm_wo32(chan->base.inst, 0xe8, chan->base.chid); nvkm_wo32(chan->base.inst, 0xe8, chan->base.chid);
nvkm_wo32(chan->base.inst, 0xb8, 0xf8000000); nvkm_wo32(chan->base.inst, 0xb8, 0xf8000000);
nvkm_wo32(chan->base.inst, 0xf8, 0x10003080); /* 0x002310 */ nvkm_wo32(chan->base.inst, 0xf8, 0x10003080); /* 0x002310 */
...@@ -338,9 +339,11 @@ gk104_fifo_gpfifo_new(struct gk104_fifo *fifo, const struct nvkm_oclass *oclass, ...@@ -338,9 +339,11 @@ gk104_fifo_gpfifo_new(struct gk104_fifo *fifo, const struct nvkm_oclass *oclass,
if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) { if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
nvif_ioctl(parent, "create channel gpfifo vers %d vmm %llx " nvif_ioctl(parent, "create channel gpfifo vers %d vmm %llx "
"ioffset %016llx ilength %08x " "ioffset %016llx ilength %08x "
"runlist %016llx\n", "runlist %016llx priv %d\n",
args->v0.version, args->v0.vmm, args->v0.ioffset, args->v0.version, args->v0.vmm, args->v0.ioffset,
args->v0.ilength, args->v0.runlist); args->v0.ilength, args->v0.runlist, args->v0.priv);
if (args->v0.priv && !oclass->client->super)
return -EINVAL;
return gk104_fifo_gpfifo_new_(fifo, return gk104_fifo_gpfifo_new_(fifo,
&args->v0.runlist, &args->v0.runlist,
&args->v0.chid, &args->v0.chid,
...@@ -348,6 +351,7 @@ gk104_fifo_gpfifo_new(struct gk104_fifo *fifo, const struct nvkm_oclass *oclass, ...@@ -348,6 +351,7 @@ gk104_fifo_gpfifo_new(struct gk104_fifo *fifo, const struct nvkm_oclass *oclass,
args->v0.ioffset, args->v0.ioffset,
args->v0.ilength, args->v0.ilength,
&args->v0.inst, &args->v0.inst,
args->v0.priv,
oclass, pobject); oclass, pobject);
} }
......
...@@ -114,7 +114,7 @@ gv100_fifo_gpfifo_func = { ...@@ -114,7 +114,7 @@ gv100_fifo_gpfifo_func = {
static int static int
gv100_fifo_gpfifo_new_(struct gk104_fifo *fifo, u64 *runlists, u16 *chid, gv100_fifo_gpfifo_new_(struct gk104_fifo *fifo, u64 *runlists, u16 *chid,
u64 vmm, u64 ioffset, u64 ilength, u64 *inst, u64 vmm, u64 ioffset, u64 ilength, u64 *inst, bool priv,
const struct nvkm_oclass *oclass, const struct nvkm_oclass *oclass,
struct nvkm_object **pobject) struct nvkm_object **pobject)
{ {
...@@ -185,9 +185,9 @@ gv100_fifo_gpfifo_new_(struct gk104_fifo *fifo, u64 *runlists, u16 *chid, ...@@ -185,9 +185,9 @@ gv100_fifo_gpfifo_new_(struct gk104_fifo *fifo, u64 *runlists, u16 *chid,
(ilength << 16)); (ilength << 16));
nvkm_wo32(chan->base.inst, 0x084, 0x20400000); nvkm_wo32(chan->base.inst, 0x084, 0x20400000);
nvkm_wo32(chan->base.inst, 0x094, 0x30000001); nvkm_wo32(chan->base.inst, 0x094, 0x30000001);
nvkm_wo32(chan->base.inst, 0x0e4, 0x00000020); nvkm_wo32(chan->base.inst, 0x0e4, priv ? 0x00000020 : 0x00000000);
nvkm_wo32(chan->base.inst, 0x0e8, chan->base.chid); nvkm_wo32(chan->base.inst, 0x0e8, chan->base.chid);
nvkm_wo32(chan->base.inst, 0x0f4, 0x00001100); nvkm_wo32(chan->base.inst, 0x0f4, 0x00001000);
nvkm_wo32(chan->base.inst, 0x0f8, 0x10003080); nvkm_wo32(chan->base.inst, 0x0f8, 0x10003080);
nvkm_mo32(chan->base.inst, 0x218, 0x00000000, 0x00000000); nvkm_mo32(chan->base.inst, 0x218, 0x00000000, 0x00000000);
nvkm_wo32(chan->base.inst, 0x220, 0x020a1000); nvkm_wo32(chan->base.inst, 0x220, 0x020a1000);
...@@ -210,9 +210,11 @@ gv100_fifo_gpfifo_new(struct gk104_fifo *fifo, const struct nvkm_oclass *oclass, ...@@ -210,9 +210,11 @@ gv100_fifo_gpfifo_new(struct gk104_fifo *fifo, const struct nvkm_oclass *oclass,
if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) { if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
nvif_ioctl(parent, "create channel gpfifo vers %d vmm %llx " nvif_ioctl(parent, "create channel gpfifo vers %d vmm %llx "
"ioffset %016llx ilength %08x " "ioffset %016llx ilength %08x "
"runlist %016llx\n", "runlist %016llx priv %d\n",
args->v0.version, args->v0.vmm, args->v0.ioffset, args->v0.version, args->v0.vmm, args->v0.ioffset,
args->v0.ilength, args->v0.runlist); args->v0.ilength, args->v0.runlist, args->v0.priv);
if (args->v0.priv && !oclass->client->super)
return -EINVAL;
return gv100_fifo_gpfifo_new_(fifo, return gv100_fifo_gpfifo_new_(fifo,
&args->v0.runlist, &args->v0.runlist,
&args->v0.chid, &args->v0.chid,
...@@ -220,6 +222,7 @@ gv100_fifo_gpfifo_new(struct gk104_fifo *fifo, const struct nvkm_oclass *oclass, ...@@ -220,6 +222,7 @@ gv100_fifo_gpfifo_new(struct gk104_fifo *fifo, const struct nvkm_oclass *oclass,
args->v0.ioffset, args->v0.ioffset,
args->v0.ilength, args->v0.ilength,
&args->v0.inst, &args->v0.inst,
args->v0.priv,
oclass, pobject); oclass, 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