]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c
drm/nouveau/fifo/gk104-: implement support for PTOP fault info
[karo-tx-linux.git] / drivers / gpu / drm / nouveau / nvkm / engine / fifo / gk104.c
index 68acb36b3e6d1ea31325ad36588331c8b0bfb0f5..6e842768f5587d02b405200515cf985688be2d36 100644 (file)
 #include "changk104.h"
 
 #include <core/client.h>
-#include <core/enum.h>
 #include <core/gpuobj.h>
 #include <subdev/bar.h>
+#include <subdev/top.h>
 #include <engine/sw.h>
 
 #include <nvif/class.h>
 
-void
+static int
+gk104_fifo_class_get(struct nvkm_fifo *base, int index,
+                    const struct nvkm_fifo_chan_oclass **psclass)
+{
+       struct gk104_fifo *fifo = gk104_fifo(base);
+       int c = 0;
+
+       while ((*psclass = fifo->func->chan[c])) {
+               if (c++ == index)
+                       return 0;
+       }
+
+       return c;
+}
+
+static void
 gk104_fifo_uevent_fini(struct nvkm_fifo *fifo)
 {
        struct nvkm_device *device = fifo->engine.subdev.device;
        nvkm_mask(device, 0x002140, 0x80000000, 0x00000000);
 }
 
-void
+static void
 gk104_fifo_uevent_init(struct nvkm_fifo *fifo)
 {
        struct nvkm_device *device = fifo->engine.subdev.device;
@@ -267,111 +282,6 @@ gk104_fifo_intr_dropped_fault(struct gk104_fifo *fifo)
        nvkm_error(subdev, "DROPPED_MMU_FAULT %08x\n", stat);
 }
 
-static const struct nvkm_enum
-gk104_fifo_fault_engine[] = {
-       { 0x00, "GR", NULL, NVKM_ENGINE_GR },
-       { 0x03, "IFB", NULL, NVKM_ENGINE_IFB },
-       { 0x04, "BAR1", NULL, NVKM_SUBDEV_BAR },
-       { 0x05, "BAR3", NULL, NVKM_SUBDEV_INSTMEM },
-       { 0x07, "PBDMA0", NULL, NVKM_ENGINE_FIFO },
-       { 0x08, "PBDMA1", NULL, NVKM_ENGINE_FIFO },
-       { 0x09, "PBDMA2", NULL, NVKM_ENGINE_FIFO },
-       { 0x10, "MSVLD", NULL, NVKM_ENGINE_MSVLD },
-       { 0x11, "MSPPP", NULL, NVKM_ENGINE_MSPPP },
-       { 0x13, "PERF" },
-       { 0x14, "MSPDEC", NULL, NVKM_ENGINE_MSPDEC },
-       { 0x15, "CE0", NULL, NVKM_ENGINE_CE0 },
-       { 0x16, "CE1", NULL, NVKM_ENGINE_CE1 },
-       { 0x17, "PMU" },
-       { 0x19, "MSENC", NULL, NVKM_ENGINE_MSENC },
-       { 0x1b, "CE2", NULL, NVKM_ENGINE_CE2 },
-       {}
-};
-
-static const struct nvkm_enum
-gk104_fifo_fault_reason[] = {
-       { 0x00, "PDE" },
-       { 0x01, "PDE_SIZE" },
-       { 0x02, "PTE" },
-       { 0x03, "VA_LIMIT_VIOLATION" },
-       { 0x04, "UNBOUND_INST_BLOCK" },
-       { 0x05, "PRIV_VIOLATION" },
-       { 0x06, "RO_VIOLATION" },
-       { 0x07, "WO_VIOLATION" },
-       { 0x08, "PITCH_MASK_VIOLATION" },
-       { 0x09, "WORK_CREATION" },
-       { 0x0a, "UNSUPPORTED_APERTURE" },
-       { 0x0b, "COMPRESSION_FAILURE" },
-       { 0x0c, "UNSUPPORTED_KIND" },
-       { 0x0d, "REGION_VIOLATION" },
-       { 0x0e, "BOTH_PTES_VALID" },
-       { 0x0f, "INFO_TYPE_POISONED" },
-       {}
-};
-
-static const struct nvkm_enum
-gk104_fifo_fault_hubclient[] = {
-       { 0x00, "VIP" },
-       { 0x01, "CE0" },
-       { 0x02, "CE1" },
-       { 0x03, "DNISO" },
-       { 0x04, "FE" },
-       { 0x05, "FECS" },
-       { 0x06, "HOST" },
-       { 0x07, "HOST_CPU" },
-       { 0x08, "HOST_CPU_NB" },
-       { 0x09, "ISO" },
-       { 0x0a, "MMU" },
-       { 0x0b, "MSPDEC" },
-       { 0x0c, "MSPPP" },
-       { 0x0d, "MSVLD" },
-       { 0x0e, "NISO" },
-       { 0x0f, "P2P" },
-       { 0x10, "PD" },
-       { 0x11, "PERF" },
-       { 0x12, "PMU" },
-       { 0x13, "RASTERTWOD" },
-       { 0x14, "SCC" },
-       { 0x15, "SCC_NB" },
-       { 0x16, "SEC" },
-       { 0x17, "SSYNC" },
-       { 0x18, "GR_CE" },
-       { 0x19, "CE2" },
-       { 0x1a, "XV" },
-       { 0x1b, "MMU_NB" },
-       { 0x1c, "MSENC" },
-       { 0x1d, "DFALCON" },
-       { 0x1e, "SKED" },
-       { 0x1f, "AFALCON" },
-       {}
-};
-
-static const struct nvkm_enum
-gk104_fifo_fault_gpcclient[] = {
-       { 0x00, "L1_0" }, { 0x01, "T1_0" }, { 0x02, "PE_0" },
-       { 0x03, "L1_1" }, { 0x04, "T1_1" }, { 0x05, "PE_1" },
-       { 0x06, "L1_2" }, { 0x07, "T1_2" }, { 0x08, "PE_2" },
-       { 0x09, "L1_3" }, { 0x0a, "T1_3" }, { 0x0b, "PE_3" },
-       { 0x0c, "RAST" },
-       { 0x0d, "GCC" },
-       { 0x0e, "GPCCS" },
-       { 0x0f, "PROP_0" },
-       { 0x10, "PROP_1" },
-       { 0x11, "PROP_2" },
-       { 0x12, "PROP_3" },
-       { 0x13, "L1_4" }, { 0x14, "T1_4" }, { 0x15, "PE_4" },
-       { 0x16, "L1_5" }, { 0x17, "T1_5" }, { 0x18, "PE_5" },
-       { 0x19, "L1_6" }, { 0x1a, "T1_6" }, { 0x1b, "PE_6" },
-       { 0x1c, "L1_7" }, { 0x1d, "T1_7" }, { 0x1e, "PE_7" },
-       { 0x1f, "GPM" },
-       { 0x20, "LTP_UTLB_0" },
-       { 0x21, "LTP_UTLB_1" },
-       { 0x22, "LTP_UTLB_2" },
-       { 0x23, "LTP_UTLB_3" },
-       { 0x24, "GPC_RGG_UTLB" },
-       {}
-};
-
 static void
 gk104_fifo_intr_fault(struct gk104_fifo *fifo, int unit)
 {
@@ -390,14 +300,14 @@ gk104_fifo_intr_fault(struct gk104_fifo *fifo, int unit)
        struct nvkm_engine *engine = NULL;
        struct nvkm_fifo_chan *chan;
        unsigned long flags;
-       char gpcid[8] = "";
+       char gpcid[8] = "", en[16] = "";
 
-       er = nvkm_enum_find(gk104_fifo_fault_reason, reason);
-       eu = nvkm_enum_find(gk104_fifo_fault_engine, unit);
+       er = nvkm_enum_find(fifo->func->fault.reason, reason);
+       eu = nvkm_enum_find(fifo->func->fault.engine, unit);
        if (hub) {
-               ec = nvkm_enum_find(gk104_fifo_fault_hubclient, client);
+               ec = nvkm_enum_find(fifo->func->fault.hubclient, client);
        } else {
-               ec = nvkm_enum_find(gk104_fifo_fault_gpcclient, client);
+               ec = nvkm_enum_find(fifo->func->fault.gpcclient, client);
                snprintf(gpcid, sizeof(gpcid), "GPC%d/", gpc);
        }
 
@@ -418,13 +328,27 @@ gk104_fifo_intr_fault(struct gk104_fifo *fifo, int unit)
                }
        }
 
+       if (eu == NULL) {
+               enum nvkm_devidx engidx = nvkm_top_fault(device->top, 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);
+       }
+
        chan = nvkm_fifo_chan_inst(&fifo->base, (u64)inst << 12, &flags);
 
        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, eu ? eu->name : "", client, gpcid, ec ? ec->name : "",
+                  unit, en, client, gpcid, ec ? ec->name : "",
                   reason, er ? er->name : "", chan ? chan->chid : -1,
                   (u64)inst << 12,
                   chan ? chan->object.client->name : "unknown");
@@ -557,7 +481,7 @@ gk104_fifo_intr_engine(struct gk104_fifo *fifo)
        nvkm_fifo_uevent(&fifo->base);
 }
 
-void
+static void
 gk104_fifo_intr(struct nvkm_fifo *base)
 {
        struct gk104_fifo *fifo = gk104_fifo(base);
@@ -649,7 +573,7 @@ gk104_fifo_intr(struct nvkm_fifo *base)
        }
 }
 
-void
+static void
 gk104_fifo_fini(struct nvkm_fifo *base)
 {
        struct gk104_fifo *fifo = gk104_fifo(base);
@@ -659,13 +583,15 @@ gk104_fifo_fini(struct nvkm_fifo *base)
        nvkm_mask(device, 0x002140, 0x10000000, 0x10000000);
 }
 
-int
+static int
 gk104_fifo_oneinit(struct nvkm_fifo *base)
 {
        struct gk104_fifo *fifo = gk104_fifo(base);
        struct nvkm_subdev *subdev = &fifo->base.engine.subdev;
        struct nvkm_device *device = subdev->device;
-       int ret, i;
+       struct nvkm_top *top = device->top;
+       int engn, runl, pbid, ret, i, j;
+       enum nvkm_devidx engidx;
        u32 *map;
 
        /* Determine number of PBDMAs by checking valid enable bits. */
@@ -680,86 +606,26 @@ gk104_fifo_oneinit(struct nvkm_fifo *base)
        for (i = 0; i < fifo->pbdma_nr; i++)
                map[i] = nvkm_rd32(device, 0x002390 + (i * 0x04));
 
-       /* Read device topology from HW. */
-       for (i = 0; i < 64; i++) {
-               int type = -1, pbid = -1, engidx = -1;
-               int engn = -1, runl = -1, intr = -1, mcen = -1;
-               int fault = -1, j;
-               u32 data, addr = 0;
-
-               do {
-                       data = nvkm_rd32(device, 0x022700 + (i * 0x04));
-                       nvkm_trace(subdev, "%02x: %08x\n", i, data);
-                       switch (data & 0x00000003) {
-                       case 0x00000000: /* NOT_VALID */
-                               continue;
-                       case 0x00000001: /* DATA */
-                               addr  = (data & 0x00fff000);
-                               fault = (data & 0x000000f8) >> 3;
-                               break;
-                       case 0x00000002: /* ENUM */
-                               if (data & 0x00000020)
-                                       engn = (data & 0x3c000000) >> 26;
-                               if (data & 0x00000010)
-                                       runl = (data & 0x01e00000) >> 21;
-                               if (data & 0x00000008)
-                                       intr = (data & 0x000f8000) >> 15;
-                               if (data & 0x00000004)
-                                       mcen = (data & 0x00003e00) >> 9;
-                               break;
-                       case 0x00000003: /* ENGINE_TYPE */
-                               type = (data & 0x7ffffffc) >> 2;
-                               break;
-                       }
-               } while ((data & 0x80000000) && ++i < 64);
-
-               if (!data)
-                       continue;
-
+       /* Determine runlist configuration from topology device info. */
+       i = 0;
+       while ((int)(engidx = nvkm_top_engine(top, i++, &runl, &engn)) >= 0) {
                /* Determine which PBDMA handles requests for this engine. */
-               for (j = 0; runl >= 0 && j < fifo->pbdma_nr; j++) {
+               for (j = 0, pbid = -1; j < fifo->pbdma_nr; j++) {
                        if (map[j] & (1 << runl)) {
                                pbid = j;
                                break;
                        }
                }
 
-               /* Translate engine type to NVKM engine identifier. */
-               switch (type) {
-               case 0x00000000: engidx = NVKM_ENGINE_GR; break;
-               case 0x00000001: engidx = NVKM_ENGINE_CE0; break;
-               case 0x00000002: engidx = NVKM_ENGINE_CE1; break;
-               case 0x00000003: engidx = NVKM_ENGINE_CE2; break;
-               case 0x00000008: engidx = NVKM_ENGINE_MSPDEC; break;
-               case 0x00000009: engidx = NVKM_ENGINE_MSPPP; break;
-               case 0x0000000a: engidx = NVKM_ENGINE_MSVLD; break;
-               case 0x0000000b: engidx = NVKM_ENGINE_MSENC; break;
-               case 0x0000000c: engidx = NVKM_ENGINE_VIC; break;
-               case 0x0000000d: engidx = NVKM_ENGINE_SEC; break;
-               case 0x0000000e: engidx = NVKM_ENGINE_NVENC0; break;
-               case 0x0000000f: engidx = NVKM_ENGINE_NVENC1; break;
-               case 0x00000010: engidx = NVKM_ENGINE_NVDEC; break;
-                       break;
-               default:
-                       break;
-               }
+               nvkm_debug(subdev, "engine %2d: runlist %2d pbdma %2d\n",
+                          engn, runl, pbid);
 
-               nvkm_debug(subdev, "%02x (%8s): engine %2d runlist %2d "
-                                  "pbdma %2d intr %2d reset %2d "
-                                  "fault %2d addr %06x\n", type,
-                          engidx < 0 ? NULL : nvkm_subdev_name[engidx],
-                          engn, runl, pbid, intr, mcen, fault, addr);
-
-               /* Mark the engine as supported if everything checks out. */
-               if (engn >= 0 && runl >= 0) {
-                       fifo->engine[engn].engine = engidx < 0 ? NULL :
-                               nvkm_device_engine(device, engidx);
-                       fifo->engine[engn].runl = runl;
-                       fifo->engine[engn].pbid = pbid;
-                       fifo->engine_nr = max(fifo->engine_nr, engn + 1);
-                       fifo->runlist[runl].engm |= 1 << engn;
-                       fifo->runlist_nr = max(fifo->runlist_nr, runl + 1);
-               }
+               fifo->engine[engn].engine = nvkm_device_engine(device, engidx);
+               fifo->engine[engn].runl = runl;
+               fifo->engine[engn].pbid = pbid;
+               fifo->engine_nr = max(fifo->engine_nr, engn + 1);
+               fifo->runlist[runl].engm |= 1 << engn;
+               fifo->runlist_nr = max(fifo->runlist_nr, runl + 1);
        }
 
        kfree(map);
@@ -796,7 +662,7 @@ gk104_fifo_oneinit(struct nvkm_fifo *base)
        return 0;
 }
 
-void
+static void
 gk104_fifo_init(struct nvkm_fifo *base)
 {
        struct gk104_fifo *fifo = gk104_fifo(base);
@@ -825,7 +691,7 @@ gk104_fifo_init(struct nvkm_fifo *base)
        nvkm_wr32(device, 0x002140, 0x7fffffff);
 }
 
-void *
+static void *
 gk104_fifo_dtor(struct nvkm_fifo *base)
 {
        struct gk104_fifo *fifo = gk104_fifo(base);
@@ -842,29 +708,144 @@ gk104_fifo_dtor(struct nvkm_fifo *base)
        return fifo;
 }
 
+static const struct nvkm_fifo_func
+gk104_fifo_ = {
+       .dtor = gk104_fifo_dtor,
+       .oneinit = gk104_fifo_oneinit,
+       .init = gk104_fifo_init,
+       .fini = gk104_fifo_fini,
+       .intr = gk104_fifo_intr,
+       .uevent_init = gk104_fifo_uevent_init,
+       .uevent_fini = gk104_fifo_uevent_fini,
+       .class_get = gk104_fifo_class_get,
+};
+
 int
-gk104_fifo_new_(const struct nvkm_fifo_func *func, struct nvkm_device *device,
+gk104_fifo_new_(const struct gk104_fifo_func *func, struct nvkm_device *device,
                int index, int nr, struct nvkm_fifo **pfifo)
 {
        struct gk104_fifo *fifo;
 
        if (!(fifo = kzalloc(sizeof(*fifo), GFP_KERNEL)))
                return -ENOMEM;
+       fifo->func = func;
        INIT_WORK(&fifo->recover.work, gk104_fifo_recover_work);
        *pfifo = &fifo->base;
 
-       return nvkm_fifo_ctor(func, device, index, nr, &fifo->base);
+       return nvkm_fifo_ctor(&gk104_fifo_, device, index, nr, &fifo->base);
 }
 
-static const struct nvkm_fifo_func
+const struct nvkm_enum
+gk104_fifo_fault_engine[] = {
+       { 0x00, "GR", NULL, NVKM_ENGINE_GR },
+       { 0x03, "IFB", NULL, NVKM_ENGINE_IFB },
+       { 0x04, "BAR1", NULL, NVKM_SUBDEV_BAR },
+       { 0x05, "BAR3", NULL, NVKM_SUBDEV_INSTMEM },
+       { 0x07, "PBDMA0", NULL, NVKM_ENGINE_FIFO },
+       { 0x08, "PBDMA1", NULL, NVKM_ENGINE_FIFO },
+       { 0x09, "PBDMA2", NULL, NVKM_ENGINE_FIFO },
+       { 0x10, "MSVLD", NULL, NVKM_ENGINE_MSVLD },
+       { 0x11, "MSPPP", NULL, NVKM_ENGINE_MSPPP },
+       { 0x13, "PERF" },
+       { 0x14, "MSPDEC", NULL, NVKM_ENGINE_MSPDEC },
+       { 0x15, "CE0", NULL, NVKM_ENGINE_CE0 },
+       { 0x16, "CE1", NULL, NVKM_ENGINE_CE1 },
+       { 0x17, "PMU" },
+       { 0x19, "MSENC", NULL, NVKM_ENGINE_MSENC },
+       { 0x1b, "CE2", NULL, NVKM_ENGINE_CE2 },
+       {}
+};
+
+const struct nvkm_enum
+gk104_fifo_fault_reason[] = {
+       { 0x00, "PDE" },
+       { 0x01, "PDE_SIZE" },
+       { 0x02, "PTE" },
+       { 0x03, "VA_LIMIT_VIOLATION" },
+       { 0x04, "UNBOUND_INST_BLOCK" },
+       { 0x05, "PRIV_VIOLATION" },
+       { 0x06, "RO_VIOLATION" },
+       { 0x07, "WO_VIOLATION" },
+       { 0x08, "PITCH_MASK_VIOLATION" },
+       { 0x09, "WORK_CREATION" },
+       { 0x0a, "UNSUPPORTED_APERTURE" },
+       { 0x0b, "COMPRESSION_FAILURE" },
+       { 0x0c, "UNSUPPORTED_KIND" },
+       { 0x0d, "REGION_VIOLATION" },
+       { 0x0e, "BOTH_PTES_VALID" },
+       { 0x0f, "INFO_TYPE_POISONED" },
+       {}
+};
+
+const struct nvkm_enum
+gk104_fifo_fault_hubclient[] = {
+       { 0x00, "VIP" },
+       { 0x01, "CE0" },
+       { 0x02, "CE1" },
+       { 0x03, "DNISO" },
+       { 0x04, "FE" },
+       { 0x05, "FECS" },
+       { 0x06, "HOST" },
+       { 0x07, "HOST_CPU" },
+       { 0x08, "HOST_CPU_NB" },
+       { 0x09, "ISO" },
+       { 0x0a, "MMU" },
+       { 0x0b, "MSPDEC" },
+       { 0x0c, "MSPPP" },
+       { 0x0d, "MSVLD" },
+       { 0x0e, "NISO" },
+       { 0x0f, "P2P" },
+       { 0x10, "PD" },
+       { 0x11, "PERF" },
+       { 0x12, "PMU" },
+       { 0x13, "RASTERTWOD" },
+       { 0x14, "SCC" },
+       { 0x15, "SCC_NB" },
+       { 0x16, "SEC" },
+       { 0x17, "SSYNC" },
+       { 0x18, "GR_CE" },
+       { 0x19, "CE2" },
+       { 0x1a, "XV" },
+       { 0x1b, "MMU_NB" },
+       { 0x1c, "MSENC" },
+       { 0x1d, "DFALCON" },
+       { 0x1e, "SKED" },
+       { 0x1f, "AFALCON" },
+       {}
+};
+
+const struct nvkm_enum
+gk104_fifo_fault_gpcclient[] = {
+       { 0x00, "L1_0" }, { 0x01, "T1_0" }, { 0x02, "PE_0" },
+       { 0x03, "L1_1" }, { 0x04, "T1_1" }, { 0x05, "PE_1" },
+       { 0x06, "L1_2" }, { 0x07, "T1_2" }, { 0x08, "PE_2" },
+       { 0x09, "L1_3" }, { 0x0a, "T1_3" }, { 0x0b, "PE_3" },
+       { 0x0c, "RAST" },
+       { 0x0d, "GCC" },
+       { 0x0e, "GPCCS" },
+       { 0x0f, "PROP_0" },
+       { 0x10, "PROP_1" },
+       { 0x11, "PROP_2" },
+       { 0x12, "PROP_3" },
+       { 0x13, "L1_4" }, { 0x14, "T1_4" }, { 0x15, "PE_4" },
+       { 0x16, "L1_5" }, { 0x17, "T1_5" }, { 0x18, "PE_5" },
+       { 0x19, "L1_6" }, { 0x1a, "T1_6" }, { 0x1b, "PE_6" },
+       { 0x1c, "L1_7" }, { 0x1d, "T1_7" }, { 0x1e, "PE_7" },
+       { 0x1f, "GPM" },
+       { 0x20, "LTP_UTLB_0" },
+       { 0x21, "LTP_UTLB_1" },
+       { 0x22, "LTP_UTLB_2" },
+       { 0x23, "LTP_UTLB_3" },
+       { 0x24, "GPC_RGG_UTLB" },
+       {}
+};
+
+static const struct gk104_fifo_func
 gk104_fifo = {
-       .dtor = gk104_fifo_dtor,
-       .oneinit = gk104_fifo_oneinit,
-       .init = gk104_fifo_init,
-       .fini = gk104_fifo_fini,
-       .intr = gk104_fifo_intr,
-       .uevent_init = gk104_fifo_uevent_init,
-       .uevent_fini = gk104_fifo_uevent_fini,
+       .fault.engine = gk104_fifo_fault_engine,
+       .fault.reason = gk104_fifo_fault_reason,
+       .fault.hubclient = gk104_fifo_fault_hubclient,
+       .fault.gpcclient = gk104_fifo_fault_gpcclient,
        .chan = {
                &gk104_fifo_gpfifo_oclass,
                NULL