drm/nouveau/fifo: support channel count query
authorBen Skeggs <bskeggs@redhat.com>
Tue, 8 May 2018 10:39:46 +0000 (20:39 +1000)
committerBen Skeggs <bskeggs@redhat.com>
Fri, 18 May 2018 05:01:21 +0000 (15:01 +1000)
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
15 files changed:
drivers/gpu/drm/nouveau/include/nvif/cl0080.h
drivers/gpu/drm/nouveau/include/nvif/device.h
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/nouveau_drv.h
drivers/gpu/drm/nouveau/nouveau_fence.c
drivers/gpu/drm/nouveau/nouveau_fence.h
drivers/gpu/drm/nouveau/nv04_fence.c
drivers/gpu/drm/nouveau/nv10_fence.c
drivers/gpu/drm/nouveau/nv17_fence.c
drivers/gpu/drm/nouveau/nv50_fence.c
drivers/gpu/drm/nouveau/nv84_fence.c
drivers/gpu/drm/nouveau/nvkm/engine/device/user.c
drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c

index 6a54cda..5af610e 100644 (file)
@@ -57,6 +57,7 @@ struct nv_device_time_v0 {
 
 #define NV_DEVICE_INFO_UNIT                               (0xffffffffULL << 32)
 #define NV_DEVICE_INFO(n)                          ((n) | (0x00000000ULL << 32))
+#define NV_DEVICE_FIFO(n)                          ((n) | (0x00000001ULL << 32))
 
 /* This will be returned for unsupported queries. */
 #define NV_DEVICE_INFO_INVALID                                           ~0ULL
@@ -79,4 +80,7 @@ struct nv_device_time_v0 {
 #define NV_DEVICE_INFO_ENGINE_SEC2                   NV_DEVICE_INFO(0x0000000e)
 #define NV_DEVICE_INFO_ENGINE_NVDEC                  NV_DEVICE_INFO(0x0000000f)
 #define NV_DEVICE_INFO_ENGINE_NVENC                  NV_DEVICE_INFO(0x00000010)
+
+/* Returns the number of available channels. */
+#define NV_DEVICE_FIFO_CHANNELS                      NV_DEVICE_FIFO(0x00000000)
 #endif
index 6edb626..216dbd9 100644 (file)
@@ -67,6 +67,5 @@ u64  nvif_device_time(struct nvif_device *);
 #include <engine/fifo.h>
 #include <engine/gr.h>
 
-#define nvxx_fifo(a) nvxx_device(a)->fifo
 #define nvxx_gr(a) nvxx_device(a)->gr
 #endif
index af11166..db69d13 100644 (file)
@@ -474,3 +474,28 @@ done:
        cli->base.super = super;
        return ret;
 }
+
+int
+nouveau_channels_init(struct nouveau_drm *drm)
+{
+       struct {
+               struct nv_device_info_v1 m;
+               struct {
+                       struct nv_device_info_v1_data channels;
+               } v;
+       } args = {
+               .m.version = 1,
+               .m.count = sizeof(args.v) / sizeof(args.v.channels),
+               .v.channels.mthd = NV_DEVICE_FIFO_CHANNELS,
+       };
+       struct nvif_object *device = &drm->client.device.object;
+       int ret;
+
+       ret = nvif_object_mthd(device, NV_DEVICE_V0_INFO, &args, sizeof(args));
+       if (ret || args.v.channels.mthd == NV_DEVICE_INFO_INVALID)
+               return -ENODEV;
+
+       drm->chan.nr = args.v.channels.data;
+       drm->chan.context_base = dma_fence_context_alloc(drm->chan.nr);
+       return 0;
+}
index 14607c1..64454c2 100644 (file)
@@ -45,6 +45,7 @@ struct nouveau_channel {
        atomic_t killed;
 };
 
+int nouveau_channels_init(struct nouveau_drm *);
 
 int  nouveau_channel_new(struct nouveau_drm *, struct nvif_device *,
                         u32 arg0, u32 arg1, struct nouveau_channel **);
index bbbf353..dddd425 100644 (file)
@@ -307,6 +307,10 @@ nouveau_accel_init(struct nouveau_drm *drm)
        if (nouveau_noaccel)
                return;
 
+       ret = nouveau_channels_init(drm);
+       if (ret)
+               return;
+
        /* initialise synchronisation routines */
        /*XXX: this is crap, but the fence/channel stuff is a little
         *     backwards in some places.  this will be fixed.
index 881b44b..6e1acae 100644 (file)
@@ -170,6 +170,12 @@ struct nouveau_drm {
        /* synchronisation */
        void *fence;
 
+       /* Global channel management. */
+       struct {
+               int nr;
+               u64 context_base;
+       } chan;
+
        /* context for accelerated drm-internal operations */
        struct nouveau_channel *cechan;
        struct nouveau_channel *channel;
index 503fa94..412d49b 100644 (file)
@@ -74,15 +74,14 @@ nouveau_fence_signal(struct nouveau_fence *fence)
 }
 
 static struct nouveau_fence *
-nouveau_local_fence(struct dma_fence *fence, struct nouveau_drm *drm) {
-       struct nouveau_fence_priv *priv = (void*)drm->fence;
-
+nouveau_local_fence(struct dma_fence *fence, struct nouveau_drm *drm)
+{
        if (fence->ops != &nouveau_fence_ops_legacy &&
            fence->ops != &nouveau_fence_ops_uevent)
                return NULL;
 
-       if (fence->context < priv->context_base ||
-           fence->context >= priv->context_base + priv->contexts)
+       if (fence->context < drm->chan.context_base ||
+           fence->context >= drm->chan.context_base + drm->chan.nr)
                return NULL;
 
        return from_fence(fence);
@@ -176,7 +175,7 @@ nouveau_fence_context_new(struct nouveau_channel *chan, struct nouveau_fence_cha
        INIT_LIST_HEAD(&fctx->flip);
        INIT_LIST_HEAD(&fctx->pending);
        spin_lock_init(&fctx->lock);
-       fctx->context = priv->context_base + chan->chid;
+       fctx->context = chan->drm->chan.context_base + chan->chid;
 
        if (chan == chan->drm->cechan)
                strcpy(fctx->name, "copy engine channel");
index 5bd8d30..b999e60 100644 (file)
@@ -55,8 +55,6 @@ struct nouveau_fence_priv {
        int  (*context_new)(struct nouveau_channel *);
        void (*context_del)(struct nouveau_channel *);
 
-       u32 contexts;
-       u64 context_base;
        bool uevent;
 };
 
index fa8f237..c41e82b 100644 (file)
@@ -109,7 +109,5 @@ nv04_fence_create(struct nouveau_drm *drm)
        priv->base.dtor = nv04_fence_destroy;
        priv->base.context_new = nv04_fence_context_new;
        priv->base.context_del = nv04_fence_context_del;
-       priv->base.contexts = 15;
-       priv->base.context_base = dma_fence_context_alloc(priv->base.contexts);
        return 0;
 }
index 2998bde..4476b71 100644 (file)
@@ -103,8 +103,6 @@ nv10_fence_create(struct nouveau_drm *drm)
        priv->base.dtor = nv10_fence_destroy;
        priv->base.context_new = nv10_fence_context_new;
        priv->base.context_del = nv10_fence_context_del;
-       priv->base.contexts = 31;
-       priv->base.context_base = dma_fence_context_alloc(priv->base.contexts);
        spin_lock_init(&priv->lock);
        return 0;
 }
index 6477b70..5d613d4 100644 (file)
@@ -125,8 +125,6 @@ nv17_fence_create(struct nouveau_drm *drm)
        priv->base.resume = nv17_fence_resume;
        priv->base.context_new = nv17_fence_context_new;
        priv->base.context_del = nv10_fence_context_del;
-       priv->base.contexts = 31;
-       priv->base.context_base = dma_fence_context_alloc(priv->base.contexts);
        spin_lock_init(&priv->lock);
 
        ret = nouveau_bo_new(&drm->client, 4096, 0x1000, TTM_PL_FLAG_VRAM,
index a369d97..a00ecc3 100644 (file)
@@ -78,8 +78,6 @@ nv50_fence_create(struct nouveau_drm *drm)
        priv->base.resume = nv17_fence_resume;
        priv->base.context_new = nv50_fence_context_new;
        priv->base.context_del = nv10_fence_context_del;
-       priv->base.contexts = 127;
-       priv->base.context_base = dma_fence_context_alloc(priv->base.contexts);
        spin_lock_init(&priv->lock);
 
        ret = nouveau_bo_new(&drm->client, 4096, 0x1000, TTM_PL_FLAG_VRAM,
index 5f0c0c2..0906648 100644 (file)
@@ -141,9 +141,9 @@ nv84_fence_suspend(struct nouveau_drm *drm)
        struct nv84_fence_priv *priv = drm->fence;
        int i;
 
-       priv->suspend = vmalloc(priv->base.contexts * sizeof(u32));
+       priv->suspend = vmalloc(drm->chan.nr * sizeof(u32));
        if (priv->suspend) {
-               for (i = 0; i < priv->base.contexts; i++)
+               for (i = 0; i < drm->chan.nr; i++)
                        priv->suspend[i] = nouveau_bo_rd32(priv->bo, i*4);
        }
 
@@ -157,7 +157,7 @@ nv84_fence_resume(struct nouveau_drm *drm)
        int i;
 
        if (priv->suspend) {
-               for (i = 0; i < priv->base.contexts; i++)
+               for (i = 0; i < drm->chan.nr; i++)
                        nouveau_bo_wr32(priv->bo, i*4, priv->suspend[i]);
                vfree(priv->suspend);
                priv->suspend = NULL;
@@ -179,7 +179,6 @@ nv84_fence_destroy(struct nouveau_drm *drm)
 int
 nv84_fence_create(struct nouveau_drm *drm)
 {
-       struct nvkm_fifo *fifo = nvxx_fifo(&drm->client.device);
        struct nv84_fence_priv *priv;
        u32 domain;
        int ret;
@@ -194,8 +193,6 @@ nv84_fence_create(struct nouveau_drm *drm)
        priv->base.context_new = nv84_fence_context_new;
        priv->base.context_del = nv84_fence_context_del;
 
-       priv->base.contexts = fifo->nr;
-       priv->base.context_base = dma_fence_context_alloc(priv->base.contexts);
        priv->base.uevent = true;
 
        mutex_init(&priv->mutex);
@@ -207,7 +204,7 @@ nv84_fence_create(struct nouveau_drm *drm)
                          * will lose CPU/GPU coherency!
                          */
                         TTM_PL_FLAG_TT | TTM_PL_FLAG_UNCACHED;
-       ret = nouveau_bo_new(&drm->client, 16 * priv->base.contexts, 0,
+       ret = nouveau_bo_new(&drm->client, 16 * drm->chan.nr, 0,
                             domain, 0, 0, NULL, NULL, &priv->bo);
        if (ret == 0) {
                ret = nouveau_bo_pin(priv->bo, domain, false);
index 42a552d..600bdb8 100644 (file)
@@ -46,6 +46,7 @@ nvkm_udevice_info_subdev(struct nvkm_device *device, u64 mthd, u64 *data)
        enum nvkm_devidx subidx;
 
        switch (mthd & NV_DEVICE_INFO_UNIT) {
+       case NV_DEVICE_FIFO(0): subidx = NVKM_ENGINE_FIFO; break;
        default:
                return -EINVAL;
        }
index 64f6b76..49b37a8 100644 (file)
@@ -30,6 +30,7 @@
 #include <subdev/mc.h>
 
 #include <nvif/event.h>
+#include <nvif/cl0080.h>
 #include <nvif/unpack.h>
 
 void
@@ -270,6 +271,18 @@ nvkm_fifo_fini(struct nvkm_engine *engine, bool suspend)
        return 0;
 }
 
+static int
+nvkm_fifo_info(struct nvkm_engine *engine, u64 mthd, u64 *data)
+{
+       struct nvkm_fifo *fifo = nvkm_fifo(engine);
+       switch (mthd) {
+       case NV_DEVICE_FIFO_CHANNELS: *data = fifo->nr; return 0;
+       default:
+               break;
+       }
+       return -ENOSYS;
+}
+
 static int
 nvkm_fifo_oneinit(struct nvkm_engine *engine)
 {
@@ -311,6 +324,7 @@ nvkm_fifo = {
        .dtor = nvkm_fifo_dtor,
        .preinit = nvkm_fifo_preinit,
        .oneinit = nvkm_fifo_oneinit,
+       .info = nvkm_fifo_info,
        .init = nvkm_fifo_init,
        .fini = nvkm_fifo_fini,
        .intr = nvkm_fifo_intr,