drm/nouveau/fifo/gk104-: allow fault recovery code to be called by other subdevs
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)
This will be required to support Volta.

Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
14 files changed:
drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h
drivers/gpu/drm/nouveau/include/nvkm/subdev/fault.h
drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c
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/gk110.c
drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk208.c
drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk20a.c
drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c
drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm200.c
drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm20b.c
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/priv.h

index c17b3a9bf8fbc0411c6655459e91a0078303d913..0d96edee1e6a4c177ce64ec98d5c5802316481df 100644 (file)
@@ -4,6 +4,7 @@
 #include <core/engine.h>
 #include <core/object.h>
 #include <core/event.h>
+struct nvkm_fault_data;
 
 #define NVKM_FIFO_CHID_NR 4096
 
@@ -45,6 +46,7 @@ struct nvkm_fifo {
        struct nvkm_event kevent; /* channel killed */
 };
 
+void nvkm_fifo_fault(struct nvkm_fifo *, struct nvkm_fault_data *);
 void nvkm_fifo_pause(struct nvkm_fifo *, unsigned long *);
 void nvkm_fifo_start(struct nvkm_fifo *, unsigned long *);
 
index 8ca66e57277961ebf37f35197475bc6147c465e1..8e9bc30fe65dcf1594a395861fd7b4b3a1ec64de 100644 (file)
@@ -12,5 +12,18 @@ struct nvkm_fault {
        struct nvkm_event event;
 };
 
+struct nvkm_fault_data {
+       u64  addr;
+       u64  inst;
+       u64  time;
+       u8 engine;
+       u8  valid;
+       u8    gpc;
+       u8    hub;
+       u8 access;
+       u8 client;
+       u8 reason;
+};
+
 int gp100_fault_new(struct nvkm_device *, int, struct nvkm_fault **);
 #endif
index 49b37a8a94b7da21b4fc908218bd8bff6359168a..ed56087b4abe28e366d2d778bb773649d7f44c18 100644 (file)
@@ -56,6 +56,12 @@ nvkm_fifo_start(struct nvkm_fifo *fifo, unsigned long *flags)
        return fifo->func->start(fifo, flags);
 }
 
+void
+nvkm_fifo_fault(struct nvkm_fifo *fifo, struct nvkm_fault_data *info)
+{
+       return fifo->func->fault(fifo, info);
+}
+
 void
 nvkm_fifo_chan_put(struct nvkm_fifo *fifo, unsigned long flags,
                   struct nvkm_fifo_chan **pchan)
index 84bd703dd89714cbc54343e54ae8d78b0f504185..b5706b15a64d926dc312f553537d8a72f95d0cf1 100644 (file)
@@ -27,6 +27,7 @@
 #include <core/client.h>
 #include <core/gpuobj.h>
 #include <subdev/bar.h>
+#include <subdev/fault.h>
 #include <subdev/timer.h>
 #include <subdev/top.h>
 #include <engine/sw.h>
@@ -347,6 +348,90 @@ gk104_fifo_recover_engn(struct gk104_fifo *fifo, int engn)
        schedule_work(&fifo->recover.work);
 }
 
+static void
+gk104_fifo_fault(struct nvkm_fifo *base, struct nvkm_fault_data *info)
+{
+       struct gk104_fifo *fifo = gk104_fifo(base);
+       struct nvkm_subdev *subdev = &fifo->base.engine.subdev;
+       struct nvkm_device *device = subdev->device;
+       const struct nvkm_enum *er, *ee, *ec, *ea;
+       struct nvkm_engine *engine = NULL;
+       struct nvkm_fifo_chan *chan;
+       unsigned long flags;
+       char ct[8] = "HUB/", en[16] = "";
+       int engn;
+
+       er = nvkm_enum_find(fifo->func->fault.reason, info->reason);
+       ee = nvkm_enum_find(fifo->func->fault.engine, info->engine);
+       if (info->hub) {
+               ec = nvkm_enum_find(fifo->func->fault.hubclient, info->client);
+       } else {
+               ec = nvkm_enum_find(fifo->func->fault.gpcclient, info->client);
+               snprintf(ct, sizeof(ct), "GPC%d/", info->gpc);
+       }
+       ea = nvkm_enum_find(fifo->func->fault.access, info->access);
+
+       if (ee && ee->data2) {
+               switch (ee->data2) {
+               case NVKM_SUBDEV_BAR:
+                       nvkm_mask(device, 0x001704, 0x00000000, 0x00000000);
+                       break;
+               case NVKM_SUBDEV_INSTMEM:
+                       nvkm_mask(device, 0x001714, 0x00000000, 0x00000000);
+                       break;
+               case NVKM_ENGINE_IFB:
+                       nvkm_mask(device, 0x001718, 0x00000000, 0x00000000);
+                       break;
+               default:
+                       engine = nvkm_device_engine(device, ee->data2);
+                       break;
+               }
+       }
+
+       if (ee == NULL) {
+               enum nvkm_devidx engidx = nvkm_top_fault(device, info->engine);
+               if (engidx < NVKM_SUBDEV_NR) {
+                       const char *src = nvkm_subdev_name[engidx];
+                       char *dst = en;
+                       do {
+                               *dst++ = toupper(*src++);
+                       } while(*src);
+                       engine = nvkm_device_engine(device, engidx);
+               }
+       } else {
+               snprintf(en, sizeof(en), "%s", ee->name);
+       }
+
+       spin_lock_irqsave(&fifo->base.lock, flags);
+       chan = nvkm_fifo_chan_inst_locked(&fifo->base, info->inst);
+
+       nvkm_error(subdev,
+                  "fault %02x [%s] at %016llx engine %02x [%s] client %02x "
+                  "[%s%s] reason %02x [%s] on channel %d [%010llx %s]\n",
+                  info->access, ea ? ea->name : "", info->addr,
+                  info->engine, ee ? ee->name : en,
+                  info->client, ct, ec ? ec->name : "",
+                  info->reason, er ? er->name : "", chan ? chan->chid : -1,
+                  info->inst, chan ? chan->object.client->name : "unknown");
+
+       /* Kill the channel that caused the fault. */
+       if (chan)
+               gk104_fifo_recover_chan(&fifo->base, chan->chid);
+
+       /* Channel recovery will probably have already done this for the
+        * correct engine(s), but just in case we can't find the channel
+        * information...
+        */
+       for (engn = 0; engn < fifo->engine_nr && engine; engn++) {
+               if (fifo->engine[engn].engine == engine) {
+                       gk104_fifo_recover_engn(fifo, engn);
+                       break;
+               }
+       }
+
+       spin_unlock_irqrestore(&fifo->base.lock, flags);
+}
+
 static const struct nvkm_enum
 gk104_fifo_bind_reason[] = {
        { 0x01, "BIND_NOT_UNBOUND" },
@@ -456,88 +541,21 @@ gk104_fifo_intr_fault(struct gk104_fifo *fifo, int unit)
        u32 inst = nvkm_rd32(device, 0x002800 + (unit * 0x10));
        u32 valo = nvkm_rd32(device, 0x002804 + (unit * 0x10));
        u32 vahi = nvkm_rd32(device, 0x002808 + (unit * 0x10));
-       u32 stat = nvkm_rd32(device, 0x00280c + (unit * 0x10));
-       u32 gpc    = (stat & 0x1f000000) >> 24;
-       u32 client = (stat & 0x00001f00) >> 8;
-       u32 write  = (stat & 0x00000080);
-       u32 hub    = (stat & 0x00000040);
-       u32 reason = (stat & 0x0000000f);
-       const struct nvkm_enum *er, *eu, *ec;
-       struct nvkm_engine *engine = NULL;
-       struct nvkm_fifo_chan *chan;
-       unsigned long flags;
-       char gpcid[8] = "", en[16] = "";
-       int engn;
-
-       er = nvkm_enum_find(fifo->func->fault.reason, reason);
-       eu = nvkm_enum_find(fifo->func->fault.engine, unit);
-       if (hub) {
-               ec = nvkm_enum_find(fifo->func->fault.hubclient, client);
-       } else {
-               ec = nvkm_enum_find(fifo->func->fault.gpcclient, client);
-               snprintf(gpcid, sizeof(gpcid), "GPC%d/", gpc);
-       }
-
-       if (eu && eu->data2) {
-               switch (eu->data2) {
-               case NVKM_SUBDEV_BAR:
-                       nvkm_mask(device, 0x001704, 0x00000000, 0x00000000);
-                       break;
-               case NVKM_SUBDEV_INSTMEM:
-                       nvkm_mask(device, 0x001714, 0x00000000, 0x00000000);
-                       break;
-               case NVKM_ENGINE_IFB:
-                       nvkm_mask(device, 0x001718, 0x00000000, 0x00000000);
-                       break;
-               default:
-                       engine = nvkm_device_engine(device, eu->data2);
-                       break;
-               }
-       }
-
-       if (eu == NULL) {
-               enum nvkm_devidx engidx = nvkm_top_fault(device, unit);
-               if (engidx < NVKM_SUBDEV_NR) {
-                       const char *src = nvkm_subdev_name[engidx];
-                       char *dst = en;
-                       do {
-                               *dst++ = toupper(*src++);
-                       } while(*src);
-                       engine = nvkm_device_engine(device, engidx);
-               }
-       } else {
-               snprintf(en, sizeof(en), "%s", eu->name);
-       }
-
-       spin_lock_irqsave(&fifo->base.lock, flags);
-       chan = nvkm_fifo_chan_inst_locked(&fifo->base, (u64)inst << 12);
-
-       nvkm_error(subdev,
-                  "%s fault at %010llx engine %02x [%s] client %02x [%s%s] "
-                  "reason %02x [%s] on channel %d [%010llx %s]\n",
-                  write ? "write" : "read", (u64)vahi << 32 | valo,
-                  unit, en, client, gpcid, ec ? ec->name : "",
-                  reason, er ? er->name : "", chan ? chan->chid : -1,
-                  (u64)inst << 12,
-                  chan ? chan->object.client->name : "unknown");
-
-
-       /* Kill the channel that caused the fault. */
-       if (chan)
-               gk104_fifo_recover_chan(&fifo->base, chan->chid);
-
-       /* Channel recovery will probably have already done this for the
-        * correct engine(s), but just in case we can't find the channel
-        * information...
-        */
-       for (engn = 0; engn < fifo->engine_nr && engine; engn++) {
-               if (fifo->engine[engn].engine == engine) {
-                       gk104_fifo_recover_engn(fifo, engn);
-                       break;
-               }
-       }
-
-       spin_unlock_irqrestore(&fifo->base.lock, flags);
+       u32 type = nvkm_rd32(device, 0x00280c + (unit * 0x10));
+       struct nvkm_fault_data info;
+
+       info.inst   =  (u64)inst << 12;
+       info.addr   = ((u64)vahi << 32) | valo;
+       info.time   = 0;
+       info.engine = unit;
+       info.valid  = 1;
+       info.gpc    = (type & 0x1f000000) >> 24;
+       info.client = (type & 0x00001f00) >> 8;
+       info.access = (type & 0x00000080) >> 7;
+       info.hub    = (type & 0x00000040) >> 6;
+       info.reason = (type & 0x000000ff);
+
+       nvkm_fifo_fault(&fifo->base, &info);
 }
 
 static const struct nvkm_bitfield gk104_fifo_pbdma_intr_0[] = {
@@ -897,6 +915,7 @@ gk104_fifo_ = {
        .init = gk104_fifo_init,
        .fini = gk104_fifo_fini,
        .intr = gk104_fifo_intr,
+       .fault = gk104_fifo_fault,
        .uevent_init = gk104_fifo_uevent_init,
        .uevent_fini = gk104_fifo_uevent_fini,
        .recover_chan = gk104_fifo_recover_chan,
@@ -918,6 +937,13 @@ gk104_fifo_new_(const struct gk104_fifo_func *func, struct nvkm_device *device,
        return nvkm_fifo_ctor(&gk104_fifo_, device, index, nr, &fifo->base);
 }
 
+const struct nvkm_enum
+gk104_fifo_fault_access[] = {
+       { 0x0, "READ" },
+       { 0x1, "WRITE" },
+       {}
+};
+
 const struct nvkm_enum
 gk104_fifo_fault_engine[] = {
        { 0x00, "GR", NULL, NVKM_ENGINE_GR },
@@ -1035,6 +1061,7 @@ gk104_fifo_fault_gpcclient[] = {
 
 static const struct gk104_fifo_func
 gk104_fifo = {
+       .fault.access = gk104_fifo_fault_access,
        .fault.engine = gk104_fifo_fault_engine,
        .fault.reason = gk104_fifo_fault_reason,
        .fault.hubclient = gk104_fifo_fault_hubclient,
index 1579785cf941ef34eb48fb2494023b606ab30766..0e8b57275e9dd3e5b2502ffa29e1fe12127e1a10 100644 (file)
@@ -44,6 +44,7 @@ struct gk104_fifo {
 
 struct gk104_fifo_func {
        struct {
+               const struct nvkm_enum *access;
                const struct nvkm_enum *engine;
                const struct nvkm_enum *reason;
                const struct nvkm_enum *hubclient;
@@ -59,25 +60,7 @@ void gk104_fifo_runlist_insert(struct gk104_fifo *, struct gk104_fifo_chan *);
 void gk104_fifo_runlist_remove(struct gk104_fifo *, struct gk104_fifo_chan *);
 void gk104_fifo_runlist_commit(struct gk104_fifo *, int runl);
 
-static inline u64
-gk104_fifo_engine_subdev(int engine)
-{
-       switch (engine) {
-       case 0: return (1ULL << NVKM_ENGINE_GR) |
-                      (1ULL << NVKM_ENGINE_SW) |
-                      (1ULL << NVKM_ENGINE_CE2);
-       case 1: return (1ULL << NVKM_ENGINE_MSPDEC);
-       case 2: return (1ULL << NVKM_ENGINE_MSPPP);
-       case 3: return (1ULL << NVKM_ENGINE_MSVLD);
-       case 4: return (1ULL << NVKM_ENGINE_CE0);
-       case 5: return (1ULL << NVKM_ENGINE_CE1);
-       case 6: return (1ULL << NVKM_ENGINE_MSENC);
-       default:
-               WARN_ON(1);
-               return 0;
-       }
-}
-
+extern const struct nvkm_enum gk104_fifo_fault_access[];
 extern const struct nvkm_enum gk104_fifo_fault_engine[];
 extern const struct nvkm_enum gk104_fifo_fault_reason[];
 extern const struct nvkm_enum gk104_fifo_fault_hubclient[];
index b2f8ab7bf84711936618a804869bf0e49eb2bfcc..ad792b6830e5768e83094252ee3b1e1e33a874bd 100644 (file)
@@ -26,6 +26,7 @@
 
 static const struct gk104_fifo_func
 gk110_fifo = {
+       .fault.access = gk104_fifo_fault_access,
        .fault.engine = gk104_fifo_fault_engine,
        .fault.reason = gk104_fifo_fault_reason,
        .fault.hubclient = gk104_fifo_fault_hubclient,
index 160617d376e4876c0f04628655118761ca8d3da2..5402d22462e86fcf6f50c77f3cc778820ad83e1c 100644 (file)
@@ -26,6 +26,7 @@
 
 static const struct gk104_fifo_func
 gk208_fifo = {
+       .fault.access = gk104_fifo_fault_access,
        .fault.engine = gk104_fifo_fault_engine,
        .fault.reason = gk104_fifo_fault_reason,
        .fault.hubclient = gk104_fifo_fault_hubclient,
index be9f5c16ed7dd1e3aa1e168ac56bc940ebfd49e0..0d7f9f59f80c88f6afdd87ce5f6e7507169eed2b 100644 (file)
@@ -24,6 +24,7 @@
 
 static const struct gk104_fifo_func
 gk20a_fifo = {
+       .fault.access = gk104_fifo_fault_access,
        .fault.engine = gk104_fifo_fault_engine,
        .fault.reason = gk104_fifo_fault_reason,
        .fault.hubclient = gk104_fifo_fault_hubclient,
index 29c080683b32c4d417aff3ed0bc03b663a937151..58a46ee5ee440c9df9d5842272401030a9b4132a 100644 (file)
@@ -49,6 +49,7 @@ gm107_fifo_fault_engine[] = {
 
 static const struct gk104_fifo_func
 gm107_fifo = {
+       .fault.access = gk104_fifo_fault_access,
        .fault.engine = gm107_fifo_fault_engine,
        .fault.reason = gk104_fifo_fault_reason,
        .fault.hubclient = gk104_fifo_fault_hubclient,
index b069f785c5d8b51e9ee7bda88a504312508afaf2..f84d5398aebebd02a74ee21336c2af863274e467 100644 (file)
@@ -26,6 +26,7 @@
 
 static const struct gk104_fifo_func
 gm200_fifo = {
+       .fault.access = gk104_fifo_fault_access,
        .fault.engine = gm107_fifo_fault_engine,
        .fault.reason = gk104_fifo_fault_reason,
        .fault.hubclient = gk104_fifo_fault_hubclient,
index 2ed87c2e829966767d83b9f4ab03c97e4a61c0c2..66399b9572a686d8b62dc623919eb10ab678616a 100644 (file)
@@ -24,6 +24,7 @@
 
 static const struct gk104_fifo_func
 gm20b_fifo = {
+       .fault.access = gk104_fifo_fault_access,
        .fault.engine = gm107_fifo_fault_engine,
        .fault.reason = gk104_fifo_fault_reason,
        .fault.hubclient = gk104_fifo_fault_hubclient,
index 41f16cf5a918c06e13338c2d38bd0120091023ce..2b8a6cff7a6863ffb1bc31759717d1d9139f070c 100644 (file)
@@ -50,6 +50,7 @@ gp100_fifo_fault_engine[] = {
 
 static const struct gk104_fifo_func
 gp100_fifo = {
+       .fault.access = gk104_fifo_fault_access,
        .fault.engine = gp100_fifo_fault_engine,
        .fault.reason = gk104_fifo_fault_reason,
        .fault.hubclient = gk104_fifo_fault_hubclient,
index 4af96c3e69fffaffbe89aeff9f9a4d8cdf7878d4..71b8d93b4368e1067205ad9cf50b724965ec0172 100644 (file)
@@ -24,6 +24,7 @@
 
 static const struct gk104_fifo_func
 gp10b_fifo = {
+       .fault.access = gk104_fifo_fault_access,
        .fault.engine = gp100_fifo_fault_engine,
        .fault.reason = gk104_fifo_fault_reason,
        .fault.hubclient = gk104_fifo_fault_hubclient,
index ae76b1aaccd461e0f761cce0a331c6285171fd92..df74b54773b912244b72c2c5466c986f60b6aa7e 100644 (file)
@@ -21,6 +21,7 @@ struct nvkm_fifo_func {
        void (*init)(struct nvkm_fifo *);
        void (*fini)(struct nvkm_fifo *);
        void (*intr)(struct nvkm_fifo *);
+       void (*fault)(struct nvkm_fifo *, struct nvkm_fault_data *);
        void (*pause)(struct nvkm_fifo *, unsigned long *);
        void (*start)(struct nvkm_fifo *, unsigned long *);
        void (*uevent_init)(struct nvkm_fifo *);