drm/nvc0/fifo: attempt to recover from engine ctxsw timeouts
authorBen Skeggs <bskeggs@redhat.com>
Sat, 22 Feb 2014 02:44:23 +0000 (12:44 +1000)
committerBen Skeggs <bskeggs@redhat.com>
Wed, 26 Mar 2014 04:00:47 +0000 (14:00 +1000)
My test cases don't seem to trigger this on all Fermi boards, not sure
if they're broken tests or it didn't work until later versions.

GF119 definitely works.

Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c

index 358926bc73755f2025ef35c540b2152c0c87ae32..fa1e719872b769c79a959efc7b6a62321ebad552 100644 (file)
@@ -480,6 +480,32 @@ nvc0_fifo_sched_reason[] = {
        {}
 };
 
+static void
+nvc0_fifo_intr_sched_ctxsw(struct nvc0_fifo_priv *priv)
+{
+       struct nouveau_engine *engine;
+       struct nvc0_fifo_chan *chan;
+       u32 engn;
+
+       for (engn = 0; engn < 6; engn++) {
+               u32 stat = nv_rd32(priv, 0x002640 + (engn * 0x04));
+               u32 busy = (stat & 0x80000000);
+               u32 save = (stat & 0x00100000); /* maybe? */
+               u32 unk0 = (stat & 0x00040000);
+               u32 unk1 = (stat & 0x00001000);
+               u32 chid = (stat & 0x0000007f);
+               (void)save;
+
+               if (busy && unk0 && unk1) {
+                       if (!(chan = (void *)priv->base.channel[chid]))
+                               continue;
+                       if (!(engine = nvc0_fifo_engine(priv, engn)))
+                               continue;
+                       nvc0_fifo_recover(priv, engine, chan);
+               }
+       }
+}
+
 static void
 nvc0_fifo_intr_sched(struct nvc0_fifo_priv *priv)
 {
@@ -493,6 +519,14 @@ nvc0_fifo_intr_sched(struct nvc0_fifo_priv *priv)
                snprintf(enunk, sizeof(enunk), "UNK%02x", code);
 
        nv_error(priv, "SCHED_ERROR [ %s ]\n", en ? en->name : enunk);
+
+       switch (code) {
+       case 0x0a:
+               nvc0_fifo_intr_sched_ctxsw(priv);
+               break;
+       default:
+               break;
+       }
 }
 
 static const struct nouveau_enum