]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
drm/nouveau/fifo/gf1xx: convert to using nvkm_fault_data
authorBen Skeggs <bskeggs@redhat.com>
Thu, 13 Jun 2019 03:58:50 +0000 (13:58 +1000)
committerBen Skeggs <bskeggs@redhat.com>
Fri, 23 Aug 2019 02:55:32 +0000 (12:55 +1000)
Would like to be able to reuse gf100_fifo_intr_fault() for (some of) the
later chipsets too, as it's identical.

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

index 10a2e7039a7522a51b1d05326e8fe93db61bb1e5..5a39e51d42d738fe5800fc2a97feb8255c901b8a 100644 (file)
@@ -28,6 +28,7 @@
 #include <core/enum.h>
 #include <core/gpuobj.h>
 #include <subdev/bar.h>
+#include <subdev/fault.h>
 #include <engine/sw.h>
 
 #include <nvif/class.h>
@@ -193,68 +194,6 @@ gf100_fifo_recover(struct gf100_fifo *fifo, struct nvkm_engine *engine,
        nvkm_fifo_kevent(&fifo->base, chid);
 }
 
-static const struct nvkm_enum
-gf100_fifo_sched_reason[] = {
-       { 0x0a, "CTXSW_TIMEOUT" },
-       {}
-};
-
-static void
-gf100_fifo_intr_sched_ctxsw(struct gf100_fifo *fifo)
-{
-       struct nvkm_device *device = fifo->base.engine.subdev.device;
-       struct nvkm_engine *engine;
-       struct gf100_fifo_chan *chan;
-       unsigned long flags;
-       u32 engn;
-
-       spin_lock_irqsave(&fifo->base.lock, flags);
-       for (engn = 0; engn < 6; engn++) {
-               u32 stat = nvkm_rd32(device, 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) {
-                       list_for_each_entry(chan, &fifo->chan, head) {
-                               if (chan->base.chid == chid) {
-                                       engine = gf100_fifo_engine(fifo, engn);
-                                       if (!engine)
-                                               break;
-                                       gf100_fifo_recover(fifo, engine, chan);
-                                       break;
-                               }
-                       }
-               }
-       }
-       spin_unlock_irqrestore(&fifo->base.lock, flags);
-}
-
-static void
-gf100_fifo_intr_sched(struct gf100_fifo *fifo)
-{
-       struct nvkm_subdev *subdev = &fifo->base.engine.subdev;
-       struct nvkm_device *device = subdev->device;
-       u32 intr = nvkm_rd32(device, 0x00254c);
-       u32 code = intr & 0x000000ff;
-       const struct nvkm_enum *en;
-
-       en = nvkm_enum_find(gf100_fifo_sched_reason, code);
-
-       nvkm_error(subdev, "SCHED_ERROR %02x [%s]\n", code, en ? en->name : "");
-
-       switch (code) {
-       case 0x0a:
-               gf100_fifo_intr_sched_ctxsw(fifo);
-               break;
-       default:
-               break;
-       }
-}
-
 static const struct nvkm_enum
 gf100_fifo_fault_engine[] = {
        { 0x00, "PGRAPH", NULL, NVKM_ENGINE_GR },
@@ -315,32 +254,24 @@ gf100_fifo_fault_gpcclient[] = {
 };
 
 static void
-gf100_fifo_intr_fault(struct gf100_fifo *fifo, int unit)
+gf100_fifo_fault(struct nvkm_fifo *base, struct nvkm_fault_data *info)
 {
+       struct gf100_fifo *fifo = gf100_fifo(base);
        struct nvkm_subdev *subdev = &fifo->base.engine.subdev;
        struct nvkm_device *device = subdev->device;
-       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] = "";
 
-       er = nvkm_enum_find(gf100_fifo_fault_reason, reason);
-       eu = nvkm_enum_find(gf100_fifo_fault_engine, unit);
-       if (hub) {
-               ec = nvkm_enum_find(gf100_fifo_fault_hubclient, client);
+       er = nvkm_enum_find(gf100_fifo_fault_reason, info->reason);
+       eu = nvkm_enum_find(gf100_fifo_fault_engine, info->engine);
+       if (info->hub) {
+               ec = nvkm_enum_find(gf100_fifo_fault_hubclient, info->client);
        } else {
-               ec = nvkm_enum_find(gf100_fifo_fault_gpcclient, client);
-               snprintf(gpcid, sizeof(gpcid), "GPC%d/", gpc);
+               ec = nvkm_enum_find(gf100_fifo_fault_gpcclient, info->client);
+               snprintf(gpcid, sizeof(gpcid), "GPC%d/", info->gpc);
        }
 
        if (eu && eu->data2) {
@@ -360,22 +291,108 @@ gf100_fifo_intr_fault(struct gf100_fifo *fifo, int unit)
                }
        }
 
-       chan = nvkm_fifo_chan_inst(&fifo->base, (u64)inst << 12, &flags);
+       chan = nvkm_fifo_chan_inst(&fifo->base, info->inst, &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 : "",
-                  reason, er ? er->name : "", chan ? chan->chid : -1,
-                  (u64)inst << 12,
-                  chan ? chan->object.client->name : "unknown");
+                  info->access ? "write" : "read", info->addr,
+                  info->engine, eu ? eu->name : "",
+                  info->client, gpcid, ec ? ec->name : "",
+                  info->reason, er ? er->name : "", chan ? chan->chid : -1,
+                  info->inst, chan ? chan->object.client->name : "unknown");
 
        if (engine && chan)
                gf100_fifo_recover(fifo, engine, (void *)chan);
        nvkm_fifo_chan_put(&fifo->base, flags, &chan);
 }
 
+static const struct nvkm_enum
+gf100_fifo_sched_reason[] = {
+       { 0x0a, "CTXSW_TIMEOUT" },
+       {}
+};
+
+static void
+gf100_fifo_intr_sched_ctxsw(struct gf100_fifo *fifo)
+{
+       struct nvkm_device *device = fifo->base.engine.subdev.device;
+       struct nvkm_engine *engine;
+       struct gf100_fifo_chan *chan;
+       unsigned long flags;
+       u32 engn;
+
+       spin_lock_irqsave(&fifo->base.lock, flags);
+       for (engn = 0; engn < 6; engn++) {
+               u32 stat = nvkm_rd32(device, 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) {
+                       list_for_each_entry(chan, &fifo->chan, head) {
+                               if (chan->base.chid == chid) {
+                                       engine = gf100_fifo_engine(fifo, engn);
+                                       if (!engine)
+                                               break;
+                                       gf100_fifo_recover(fifo, engine, chan);
+                                       break;
+                               }
+                       }
+               }
+       }
+       spin_unlock_irqrestore(&fifo->base.lock, flags);
+}
+
+static void
+gf100_fifo_intr_sched(struct gf100_fifo *fifo)
+{
+       struct nvkm_subdev *subdev = &fifo->base.engine.subdev;
+       struct nvkm_device *device = subdev->device;
+       u32 intr = nvkm_rd32(device, 0x00254c);
+       u32 code = intr & 0x000000ff;
+       const struct nvkm_enum *en;
+
+       en = nvkm_enum_find(gf100_fifo_sched_reason, code);
+
+       nvkm_error(subdev, "SCHED_ERROR %02x [%s]\n", code, en ? en->name : "");
+
+       switch (code) {
+       case 0x0a:
+               gf100_fifo_intr_sched_ctxsw(fifo);
+               break;
+       default:
+               break;
+       }
+}
+
+void
+gf100_fifo_intr_fault(struct nvkm_fifo *fifo, int unit)
+{
+       struct nvkm_device *device = fifo->engine.subdev.device;
+       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 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 & 0x0000000f);
+
+       nvkm_fifo_fault(fifo, &info);
+}
+
 static const struct nvkm_bitfield
 gf100_fifo_pbdma_intr[] = {
 /*     { 0x00008000, "" }      seen with null ib push */
@@ -518,7 +535,7 @@ gf100_fifo_intr(struct nvkm_fifo *base)
                u32 mask = nvkm_rd32(device, 0x00259c);
                while (mask) {
                        u32 unit = __ffs(mask);
-                       gf100_fifo_intr_fault(fifo, unit);
+                       gf100_fifo_intr_fault(&fifo->base, unit);
                        nvkm_wr32(device, 0x00259c, (1 << unit));
                        mask &= ~(1 << unit);
                }
@@ -655,6 +672,7 @@ gf100_fifo = {
        .init = gf100_fifo_init,
        .fini = gf100_fifo_fini,
        .intr = gf100_fifo_intr,
+       .fault = gf100_fifo_fault,
        .uevent_init = gf100_fifo_uevent_init,
        .uevent_fini = gf100_fifo_uevent_fini,
        .chan = {
index 1053fe7964661ce809b4ab78e87ec04049d9180f..ac9abcc1470ae400d57868cad346b605290c1852 100644 (file)
@@ -666,7 +666,7 @@ gk104_fifo_intr_fault(struct gk104_fifo *fifo, int unit)
        info.client = (type & 0x00001f00) >> 8;
        info.access = (type & 0x00000080) >> 7;
        info.hub    = (type & 0x00000040) >> 6;
-       info.reason = (type & 0x000000ff);
+       info.reason = (type & 0x0000001f);
 
        nvkm_fifo_fault(&fifo->base, &info);
 }
index c66f5370b21f163ac68378461a02093c04520ed8..0ef8baab513e5ff4e8411da035d72b8994e53454 100644 (file)
@@ -37,4 +37,6 @@ struct nvkm_fifo_func {
 void nv04_fifo_intr(struct nvkm_fifo *);
 void nv04_fifo_pause(struct nvkm_fifo *, unsigned long *);
 void nv04_fifo_start(struct nvkm_fifo *, unsigned long *);
+
+void gf100_fifo_intr_fault(struct nvkm_fifo *, int);
 #endif