drm/nv50-/disp: dump channel state when update method fails
authorBen Skeggs <bskeggs@redhat.com>
Thu, 20 Feb 2014 13:26:18 +0000 (23:26 +1000)
committerBen Skeggs <bskeggs@redhat.com>
Wed, 26 Mar 2014 04:00:39 +0000 (14:00 +1000)
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
drivers/gpu/drm/nouveau/core/engine/disp/nv50.c
drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c

index e94866e407bf76a4d5f4b53de4aa283482bf4463..9a0cab9c3adbc5b4a58b92bbb2939952d896bd49 100644 (file)
@@ -1058,6 +1058,7 @@ nv50_disp_intr_error_code[] = {
 static void
 nv50_disp_intr_error(struct nv50_disp_priv *priv, int chid)
 {
+       struct nv50_disp_impl *impl = (void *)nv_object(priv)->oclass;
        u32 data = nv_rd32(priv, 0x610084 + (chid * 0x08));
        u32 addr = nv_rd32(priv, 0x610080 + (chid * 0x08));
        u32 code = (addr & 0x00ff0000) >> 16;
@@ -1078,6 +1079,37 @@ nv50_disp_intr_error(struct nv50_disp_priv *priv, int chid)
                 et ? et->name : etunk, ec ? ec->name : ecunk,
                 chid, mthd, data);
 
+       if (chid == 0) {
+               switch (mthd) {
+               case 0x0080:
+                       nv50_disp_mthd_chan(priv, NV_DBG_ERROR, chid - 0,
+                                           impl->mthd.core);
+                       break;
+               default:
+                       break;
+               }
+       } else
+       if (chid <= 2) {
+               switch (mthd) {
+               case 0x0080:
+                       nv50_disp_mthd_chan(priv, NV_DBG_ERROR, chid - 1,
+                                           impl->mthd.base);
+                       break;
+               default:
+                       break;
+               }
+       } else
+       if (chid <= 4) {
+               switch (mthd) {
+               case 0x0080:
+                       nv50_disp_mthd_chan(priv, NV_DBG_ERROR, chid - 3,
+                                           impl->mthd.ovly);
+                       break;
+               default:
+                       break;
+               }
+       }
+
        nv_wr32(priv, 0x610020, 0x00010000 << chid);
        nv_wr32(priv, 0x610080 + (chid * 0x08), 0x90000000);
 }
index 0eac17baf8aebf067cc82e9ce5c47343effe3d89..67176f1547ecc5c34eb4e47083084e17ceb57715 100644 (file)
@@ -1222,6 +1222,53 @@ nvd0_disp_intr_supervisor(struct work_struct *work)
        nv_wr32(priv, 0x6101d0, 0x80000000);
 }
 
+static void
+nvd0_disp_intr_error(struct nv50_disp_priv *priv, int chid)
+{
+       const struct nv50_disp_impl *impl = (void *)nv_object(priv)->oclass;
+       u32 mthd = nv_rd32(priv, 0x6101f0 + (chid * 12));
+       u32 data = nv_rd32(priv, 0x6101f4 + (chid * 12));
+       u32 unkn = nv_rd32(priv, 0x6101f8 + (chid * 12));
+
+       nv_error(priv, "chid %d mthd 0x%04x data 0x%08x "
+                      "0x%08x 0x%08x\n",
+                chid, (mthd & 0x0000ffc), data, mthd, unkn);
+
+       if (chid == 0) {
+               switch (mthd) {
+               case 0x0080:
+                       nv50_disp_mthd_chan(priv, NV_DBG_ERROR, chid - 0,
+                                           impl->mthd.core);
+                       break;
+               default:
+                       break;
+               }
+       } else
+       if (chid <= 4) {
+               switch (mthd) {
+               case 0x0080:
+                       nv50_disp_mthd_chan(priv, NV_DBG_ERROR, chid - 1,
+                                           impl->mthd.base);
+                       break;
+               default:
+                       break;
+               }
+       } else
+       if (chid <= 8) {
+               switch (mthd) {
+               case 0x0080:
+                       nv50_disp_mthd_chan(priv, NV_DBG_ERROR, chid - 5,
+                                           impl->mthd.ovly);
+                       break;
+               default:
+                       break;
+               }
+       }
+
+       nv_wr32(priv, 0x61009c, (1 << chid));
+       nv_wr32(priv, 0x6101f0 + (chid * 12), 0x90000000);
+}
+
 void
 nvd0_disp_intr(struct nouveau_subdev *subdev)
 {
@@ -1238,18 +1285,8 @@ nvd0_disp_intr(struct nouveau_subdev *subdev)
        if (intr & 0x00000002) {
                u32 stat = nv_rd32(priv, 0x61009c);
                int chid = ffs(stat) - 1;
-               if (chid >= 0) {
-                       u32 mthd = nv_rd32(priv, 0x6101f0 + (chid * 12));
-                       u32 data = nv_rd32(priv, 0x6101f4 + (chid * 12));
-                       u32 unkn = nv_rd32(priv, 0x6101f8 + (chid * 12));
-
-                       nv_error(priv, "chid %d mthd 0x%04x data 0x%08x "
-                                      "0x%08x 0x%08x\n",
-                                chid, (mthd & 0x0000ffc), data, mthd, unkn);
-                       nv_wr32(priv, 0x61009c, (1 << chid));
-                       nv_wr32(priv, 0x6101f0 + (chid * 12), 0x90000000);
-               }
-
+               if (chid >= 0)
+                       nvd0_disp_intr_error(priv, chid);
                intr &= ~0x00000002;
        }