]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
drm/nouveau/fifo/gp100-: force individual channels into a channel group
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:22 +0000 (15:01 +1000)
RM does this for some reason, and is enforced in HW on Volta.

Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c
drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h
drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c
drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp10b.c
drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c

index 5c22ce91653084093dd93e40588f41504cc479fb..767e0ab44cb83c795d1319f31a7b565f73d759d1 100644 (file)
@@ -285,6 +285,32 @@ gk104_fifo_recover_runl(struct gk104_fifo *fifo, int runl)
        schedule_work(&fifo->recover.work);
 }
 
+static struct gk104_fifo_chan *
+gk104_fifo_recover_chid(struct gk104_fifo *fifo, int runl, int chid)
+{
+       struct gk104_fifo_chan *chan;
+       struct nvkm_fifo_cgrp *cgrp;
+
+       list_for_each_entry(chan, &fifo->runlist[runl].chan, head) {
+               if (chan->base.chid == chid) {
+                       list_del_init(&chan->head);
+                       return chan;
+               }
+       }
+
+       list_for_each_entry(cgrp, &fifo->runlist[runl].cgrp, head) {
+               if (cgrp->id == chid) {
+                       chan = list_first_entry(&cgrp->chan, typeof(*chan), head);
+                       list_del_init(&chan->head);
+                       if (!--cgrp->chan_nr)
+                               list_del_init(&cgrp->head);
+                       return chan;
+               }
+       }
+
+       return NULL;
+}
+
 static void
 gk104_fifo_recover_chan(struct nvkm_fifo *base, int chid)
 {
@@ -302,13 +328,10 @@ gk104_fifo_recover_chan(struct nvkm_fifo *base, int chid)
                return;
 
        /* Lookup SW state for channel, and mark it as dead. */
-       list_for_each_entry(chan, &fifo->runlist[runl].chan, head) {
-               if (chan->base.chid == chid) {
-                       list_del_init(&chan->head);
-                       chan->killed = true;
-                       nvkm_fifo_kevent(&fifo->base, chid);
-                       break;
-               }
+       chan = gk104_fifo_recover_chid(fifo, runl, chid);
+       if (chan) {
+               chan->killed = true;
+               nvkm_fifo_kevent(&fifo->base, chid);
        }
 
        /* Disable channel. */
index 1d70a5dc076220e3bcb4a8c5f6fcb82f48e0480d..1d182d8d2fcee29b7dd3e20fb2b92ee4d2c9e948 100644 (file)
@@ -68,6 +68,7 @@ struct gk104_fifo_func {
                int (*ctor)(struct gk104_fifo *, const struct nvkm_oclass *,
                            void *, u32, struct nvkm_object **);
        } chan;
+       bool cgrp_force;
 };
 
 int gk104_fifo_new_(const struct gk104_fifo_func *, struct nvkm_device *,
index f137baed7a614250790d235c10fe47d4bfe5bf84..e2f8f9087d7c8dd03501c4202b3f3a5eb674a046 100644 (file)
@@ -60,6 +60,7 @@ gp100_fifo = {
        .fault.gpcclient = gk104_fifo_fault_gpcclient,
        .runlist = &gm107_fifo_runlist,
        .chan = {{0,0,PASCAL_CHANNEL_GPFIFO_A}, gk104_fifo_gpfifo_new },
+       .cgrp_force = true,
 };
 
 int
index 787e911d95996d85c5818c66b8bfd985717f5fa7..7733bf7c6545cf03027dce6a4fd18ed9d43550d7 100644 (file)
@@ -34,6 +34,7 @@ gp10b_fifo = {
        .fault.gpcclient = gk104_fifo_fault_gpcclient,
        .runlist = &gm107_fifo_runlist,
        .chan = {{0,0,PASCAL_CHANNEL_GPFIFO_A}, gk104_fifo_gpfifo_new },
+       .cgrp_force = true,
 };
 
 int
index f7a4e0e86b23a4d54113ca8c23d039c7848cae9c..60e7d72d6e46108d26ca43676e6f78dca240d04a 100644 (file)
@@ -22,6 +22,7 @@
  * Authors: Ben Skeggs
  */
 #include "changk104.h"
+#include "cgrp.h"
 
 #include <core/client.h>
 #include <core/gpuobj.h>
@@ -40,16 +41,21 @@ gk104_fifo_gpfifo_kick(struct gk104_fifo_chan *chan)
        struct nvkm_subdev *subdev = &fifo->base.engine.subdev;
        struct nvkm_device *device = subdev->device;
        struct nvkm_client *client = chan->base.object.client;
+       struct nvkm_fifo_cgrp *cgrp = chan->cgrp;
        int ret = 0;
 
        mutex_lock(&subdev->mutex);
-       nvkm_wr32(device, 0x002634, chan->base.chid);
+       if (cgrp)
+               nvkm_wr32(device, 0x002634, cgrp->id | 0x01000000);
+       else
+               nvkm_wr32(device, 0x002634, chan->base.chid);
        if (nvkm_msec(device, 2000,
                if (!(nvkm_rd32(device, 0x002634) & 0x00100000))
                        break;
        ) < 0) {
-               nvkm_error(subdev, "channel %d [%s] kick timeout\n",
-                          chan->base.chid, client->name);
+               nvkm_error(subdev, "%s %d [%s] kick timeout\n",
+                          cgrp ? "tsg" : "channel",
+                          cgrp ? cgrp->id : chan->base.chid, client->name);
                nvkm_fifo_recover_chan(&fifo->base, chan->base.chid);
                ret = -ETIMEDOUT;
        }
@@ -207,7 +213,9 @@ gk104_fifo_gpfifo_init(struct nvkm_fifo_chan *base)
 static void *
 gk104_fifo_gpfifo_dtor(struct nvkm_fifo_chan *base)
 {
-       return gk104_fifo_chan(base);
+       struct gk104_fifo_chan *chan = gk104_fifo_chan(base);
+       kfree(chan->cgrp);
+       return chan;
 }
 
 static const struct nvkm_fifo_chan_func
@@ -264,6 +272,18 @@ gk104_fifo_gpfifo_new_(struct gk104_fifo *fifo, u64 *runlists, u16 *chid,
 
        *chid = chan->base.chid;
 
+       /* Hack to support GPUs where even individual channels should be
+        * part of a channel group.
+        */
+       if (fifo->func->cgrp_force) {
+               if (!(chan->cgrp = kmalloc(sizeof(*chan->cgrp), GFP_KERNEL)))
+                       return -ENOMEM;
+               chan->cgrp->id = chan->base.chid;
+               INIT_LIST_HEAD(&chan->cgrp->head);
+               INIT_LIST_HEAD(&chan->cgrp->chan);
+               chan->cgrp->chan_nr = 0;
+       }
+
        /* Clear channel control registers. */
        usermem = chan->base.chid * 0x200;
        ilength = order_base_2(ilength / 8);