drm/nouveau/fifo/gk104-: support enabling privileged ce functions
authorBen Skeggs <bskeggs@redhat.com>
Tue, 11 Dec 2018 04:50:02 +0000 (14:50 +1000)
committerBen Skeggs <bskeggs@redhat.com>
Tue, 11 Dec 2018 05:37:47 +0000 (15:37 +1000)
Will be used by SVM code to allow direct (without going through MMU) memcpy
using the GPU copy engines.

Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
drivers/gpu/drm/nouveau/include/nvif/cla06f.h
drivers/gpu/drm/nouveau/nouveau_abi16.c
drivers/gpu/drm/nouveau/nouveau_chan.c
drivers/gpu/drm/nouveau/nouveau_chan.h
drivers/gpu/drm/nouveau/nouveau_drm.c
drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c
drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogv100.c

index e588cc720299b2d10fab779c570fe367e1853024..81401eb970ea68798356a667e7249cfea9d34fda 100644 (file)
@@ -4,7 +4,7 @@
 
 struct kepler_channel_gpfifo_a_v0 {
        __u8  version;
-       __u8  pad01[1];
+       __u8  priv;
        __u16 chid;
        __u32 ilength;
        __u64 ioffset;
index e67a471331b514b75321c4bf8a0fff1be7057113..b06cdac8f3a2bf0e0041a865cf3103379f1e11ce 100644 (file)
@@ -306,7 +306,7 @@ nouveau_abi16_ioctl_channel_alloc(ABI16_IOCTL_ARGS)
 
        /* create channel object and initialise dma and fence management */
        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)
                goto done;
 
index a154978d74ef50846ee2be7c7db47a6e31a68eac..5daf9248ae63ebf494a01eb33e60f49eec19a616 100644 (file)
@@ -217,7 +217,7 @@ 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, struct nouveau_channel **pchan)
+                   u64 runlist, bool priv, struct nouveau_channel **pchan)
 {
        struct nouveau_cli *cli = (void *)device->object.client;
        static const u16 oclasses[] = { VOLTA_CHANNEL_GPFIFO_A,
@@ -253,6 +253,7 @@ nouveau_channel_ind(struct nouveau_drm *drm, struct nvif_device *device,
                        args.kepler.ioffset = 0x10000 + chan->push.addr;
                        args.kepler.runlist = runlist;
                        args.kepler.vmm = nvif_handle(&cli->vmm.vmm.object);
+                       args.kepler.priv = priv;
                        size = sizeof(args.kepler);
                } else
                if (oclass[0] >= FERMI_CHANNEL_GPFIFO) {
@@ -450,7 +451,8 @@ nouveau_channel_init(struct nouveau_channel *chan, u32 vram, u32 gart)
 
 int
 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;
        bool super;
@@ -460,7 +462,7 @@ nouveau_channel_new(struct nouveau_drm *drm, struct nvif_device *device,
        super = cli->base.super;
        cli->base.super = true;
 
-       ret = nouveau_channel_ind(drm, device, arg0, pchan);
+       ret = nouveau_channel_ind(drm, device, arg0, priv, pchan);
        if (ret) {
                NV_PRINTK(dbg, cli, "ib channel create, %d\n", ret);
                ret = nouveau_channel_dma(drm, device, pchan);
index 93d065d4a2a19ea7305a4c1fd03c89b37473d7b0..a62d233b2a97e0797a5bf4c253064271f6852b66 100644 (file)
@@ -49,7 +49,8 @@ struct nouveau_channel {
 int nouveau_channels_init(struct nouveau_drm *);
 
 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 **);
 int  nouveau_channel_idle(struct nouveau_channel *);
 
index 2b2baf6e0e0d6bbde2aadefd0a16e55aaadf3736..100cab059e4910593b1751f9dda8067b90a0d1df 100644 (file)
@@ -370,7 +370,7 @@ nouveau_accel_init(struct nouveau_drm *drm)
        if (device->info.family >= NV_DEVICE_INFO_V0_KEPLER) {
                ret = nouveau_channel_new(drm, &drm->client.device,
                                          nvif_fifo_runlist_ce(device), 0,
-                                         &drm->cechan);
+                                         true, &drm->cechan);
                if (ret)
                        NV_ERROR(drm, "failed to create ce channel, %d\n", ret);
 
@@ -381,7 +381,8 @@ nouveau_accel_init(struct nouveau_drm *drm)
            device->info.chipset != 0xaa &&
            device->info.chipset != 0xac) {
                ret = nouveau_channel_new(drm, &drm->client.device,
-                                         NvDmaFB, NvDmaTT, &drm->cechan);
+                                         NvDmaFB, NvDmaTT, false,
+                                         &drm->cechan);
                if (ret)
                        NV_ERROR(drm, "failed to create ce channel, %d\n", ret);
 
@@ -393,7 +394,7 @@ nouveau_accel_init(struct nouveau_drm *drm)
        }
 
        ret = nouveau_channel_new(drm, &drm->client.device,
-                                 arg0, arg1, &drm->channel);
+                                 arg0, arg1, false, &drm->channel);
        if (ret) {
                NV_ERROR(drm, "failed to create kernel channel, %d\n", ret);
                nouveau_accel_fini(drm);
index 523f8a09c52abb2da45b9d7186a84882bc9b1709..8e30b3d3ff1032e506b48874302b21718e1a7334 100644 (file)
@@ -240,7 +240,7 @@ gk104_fifo_gpfifo_func = {
 
 static int
 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,
                       struct nvkm_object **pobject)
 {
@@ -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, 0x9c, 0x00000100);
        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, 0xb8, 0xf8000000);
        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,
        if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
                nvif_ioctl(parent, "create channel gpfifo vers %d vmm %llx "
                                   "ioffset %016llx ilength %08x "
-                                  "runlist %016llx\n",
+                                  "runlist %016llx priv %d\n",
                           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,
                                              &args->v0.runlist,
                                              &args->v0.chid,
@@ -348,6 +351,7 @@ gk104_fifo_gpfifo_new(struct gk104_fifo *fifo, const struct nvkm_oclass *oclass,
                                               args->v0.ioffset,
                                               args->v0.ilength,
                                              &args->v0.inst,
+                                              args->v0.priv,
                                              oclass, pobject);
        }
 
index 97c3af3de9000dbd07ccd2ccfe6d548d899d9db6..65db8a1be943ac313fa17ea3c49d03f97ba0ab49 100644 (file)
@@ -114,7 +114,7 @@ gv100_fifo_gpfifo_func = {
 
 static int
 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,
                       struct nvkm_object **pobject)
 {
@@ -185,9 +185,9 @@ gv100_fifo_gpfifo_new_(struct gk104_fifo *fifo, u64 *runlists, u16 *chid,
                                          (ilength << 16));
        nvkm_wo32(chan->base.inst, 0x084, 0x20400000);
        nvkm_wo32(chan->base.inst, 0x094, 0x30000001);
-       nvkm_wo32(chan->base.inst, 0x0e4, 0x00000020);
+       nvkm_wo32(chan->base.inst, 0x0e4, priv ? 0x00000020 : 0x00000000);
        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_mo32(chan->base.inst, 0x218, 0x00000000, 0x00000000);
        nvkm_wo32(chan->base.inst, 0x220, 0x020a1000);
@@ -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))) {
                nvif_ioctl(parent, "create channel gpfifo vers %d vmm %llx "
                                   "ioffset %016llx ilength %08x "
-                                  "runlist %016llx\n",
+                                  "runlist %016llx priv %d\n",
                           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,
                                              &args->v0.runlist,
                                              &args->v0.chid,
@@ -220,6 +222,7 @@ gv100_fifo_gpfifo_new(struct gk104_fifo *fifo, const struct nvkm_oclass *oclass,
                                               args->v0.ioffset,
                                               args->v0.ilength,
                                              &args->v0.inst,
+                                              args->v0.priv,
                                              oclass, pobject);
        }