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 6a54cda9613ecc5bbbd2b0f1abac47014b73b5bc..5af610ea260e89d79e3948a1960bc71d73e8548a 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 6edb6266857e45b18cb255c5e29591f59f2a92d0..216dbd9fa616825ae55777186f726130abf6e4fb 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 af1116655910cf125161c702ce4c985d46255eee..db69d13f32a71c800a09316f46cd9443c2e3b4d6 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 14607c16a2bd6a1755c4fb27268efd8eb50c608e..64454c2ebd908ce82a1b6886ee376dd37d71d489 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 bbbf353682e1c51117ff2ba0d7f3256549d1efda..dddd42592472f53a41b28c5990c88f24f14a5fce 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 881b44b89a01831ffa45549d922a7a1e882a59eb..6e1acaec34003de38a2cbc2d4531da0f63e55664 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 503fa94dc06dbdb2b5fe5f1b098aace4f4777f1a..412d49bc6e56073fd9ebc8de2ca7fef73c03792d 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 5bd8d30d165702269de4beeccf2199a377b9cecf..b999e60580460e2fb132ebcffdc30bc91df3864f 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 fa8f2375c398e77c1164a560061101c4c7aab4dd..c41e82be48937f818d58af42f4d6198d886728f6 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 2998bde292112649cd1747110a68270d7a3a7899..4476b712dc8411d08ea8dbdb874a790cfbe445a7 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 6477b7069e144b9077628faa7f100c6a45a974f6..5d613d43b84d2055a555e3bd6c60d0da2faa9f53 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 a369d978e267f4d0b8eae2c2c5bc7f15ba40483c..a00ecc3de053532c4b2dce639fe2fcc434477143 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 5f0c0c27d5dcf86946caad343b8ab5e1af5d3019..090664899247ac3d38dbb510ffbc4f06c437f707 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 42a552d314ef3d0e9efac3065485f3fd8c569bda..600bdb8704627665ffdd48fc27662b041e4178d4 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 64f6b7654a08dc6f525c87f049ebcc7a991136ed..49b37a8a94b7da21b4fc908218bd8bff6359168a 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,