drm/nve0/fifo: recover from mmu faults on bar1/bar3
authorBen Skeggs <bskeggs@redhat.com>
Thu, 9 Jan 2014 03:03:17 +0000 (13:03 +1000)
committerBen Skeggs <bskeggs@redhat.com>
Thu, 23 Jan 2014 03:38:45 +0000 (13:38 +1000)
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c
drivers/gpu/drm/nouveau/core/include/core/device.h

index 3bf5ba8804e9618f67b1e2af86e455e81a6bdd36..1eb06b29a9db0722f97bfc8dde40748cfa4c2d8e 100644 (file)
@@ -384,8 +384,8 @@ static const struct nouveau_enum nve0_fifo_sched_reason[] = {
 static const struct nouveau_enum nve0_fifo_fault_engine[] = {
        { 0x00, "GR", NULL, NVDEV_ENGINE_GR },
        { 0x03, "IFB" },
-       { 0x04, "BAR1" },
-       { 0x05, "BAR3" },
+       { 0x04, "BAR1", NULL, NVDEV_SUBDEV_BAR },
+       { 0x05, "BAR3", NULL, NVDEV_SUBDEV_INSTMEM },
        { 0x07, "PBDMA0", NULL, NVDEV_ENGINE_FIFO },
        { 0x08, "PBDMA1", NULL, NVDEV_ENGINE_FIFO },
        { 0x09, "PBDMA2", NULL, NVDEV_ENGINE_FIFO },
@@ -549,9 +549,10 @@ nve0_fifo_intr_fault(struct nve0_fifo_priv *priv, int unit)
        u32 vahi = nv_rd32(priv, 0x2808 + (unit * 0x10));
        u32 stat = nv_rd32(priv, 0x280c + (unit * 0x10));
        u32 client = (stat & 0x00001f00) >> 8;
-       const struct nouveau_enum *en;
-       struct nouveau_engine *engine;
+       struct nouveau_engine *engine = NULL;
        struct nouveau_object *engctx = NULL;
+       const struct nouveau_enum *en;
+       const char *name = "unknown";
 
        nv_error(priv, "PFIFO: %s fault at 0x%010llx [", (stat & 0x00000080) ?
                       "write" : "read", (u64)vahi << 32 | valo);
@@ -567,14 +568,22 @@ nve0_fifo_intr_fault(struct nve0_fifo_priv *priv, int unit)
        }
 
        if (en && en->data2) {
-               engine = nouveau_engine(priv, en->data2);
-               if (engine)
-                       engctx = nouveau_engctx_get(engine, inst);
-
+               if (en->data2 == NVDEV_SUBDEV_BAR) {
+                       nv_mask(priv, 0x001704, 0x00000000, 0x00000000);
+                       name = "BAR1";
+               } else
+               if (en->data2 == NVDEV_SUBDEV_INSTMEM) {
+                       nv_mask(priv, 0x001714, 0x00000000, 0x00000000);
+                       name = "BAR3";
+               } else {
+                       engine = nouveau_engine(priv, en->data2);
+                       if (engine) {
+                               engctx = nouveau_engctx_get(engine, inst);
+                               name   = nouveau_client_name(engctx);
+                       }
+               }
        }
-
-       pr_cont(" on channel 0x%010llx [%s]\n", (u64)inst << 12,
-                       nouveau_client_name(engctx));
+       pr_cont(" on channel 0x%010llx [%s]\n", (u64)inst << 12, name);
 
        nouveau_engctx_put(engctx);
 }
index ac2881d1776ac1a071371a84f379ea57ea8ee856..24809c10b4b3af2a9ae9f420154a733d602d336f 100644 (file)
@@ -38,7 +38,8 @@ enum nv_subdev_type {
        NVDEV_SUBDEV_THERM,
        NVDEV_SUBDEV_CLOCK,
 
-       NVDEV_ENGINE_DMAOBJ,
+       NVDEV_ENGINE_FIRST,
+       NVDEV_ENGINE_DMAOBJ = NVDEV_ENGINE_FIRST,
        NVDEV_ENGINE_FIFO,
        NVDEV_ENGINE_SW,
        NVDEV_ENGINE_GR,